added page flipping/scrolling VBE calls master
authorJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 4 Sep 2018 01:27:32 +0000 (04:27 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Tue, 4 Sep 2018 01:27:32 +0000 (04:27 +0300)
RUN [new file with mode: 0755]
src/3dgfx.c
src/3dgfx.h
src/dos/gfx.c
src/dos/gfx.h
src/dos/main.c
src/dos/vbe.c
src/dos/vbe.h
src/parts/rtxonoff.c

diff --git a/RUN b/RUN
new file mode 100755 (executable)
index 0000000..5db8178
--- /dev/null
+++ b/RUN
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+dosbox -exit demo.exe $*
index 64fd604..a642c1e 100644 (file)
@@ -117,6 +117,13 @@ void g3d_framebuffer(int width, int height, void *pixels)
        g3d_viewport(0, 0, width, height);
 }
 
+/* set the framebuffer pointer, without resetting the size */
+void g3d_framebuffer_addr(void *pixels)
+{
+       st->pixels = pixels;
+       pfill_fb.pixels = pixels;
+}
+
 void g3d_viewport(int x, int y, int w, int h)
 {
        st->vport[0] = x;
index 07a3aea..366912f 100644 (file)
@@ -62,6 +62,7 @@ int g3d_init(void);
 void g3d_destroy(void);
 
 void g3d_framebuffer(int width, int height, void *pixels);
+void g3d_framebuffer_addr(void *pixels);
 void g3d_viewport(int x, int y, int w, int h);
 
 void g3d_enable(unsigned int opt);
index c2e4f8d..cbb1ed4 100644 (file)
@@ -1,10 +1,8 @@
-#ifndef GFX_H_
-#define GFX_H_
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
+#include "gfx.h"
 #include "vbe.h"
 #include "cdpmi.h"
 
@@ -30,12 +28,15 @@ static struct vbe_info *vbe_info;
 static struct vbe_mode_info *mode_info;
 static int pal_bits = 6;
 
+static void *vpgaddr[2];
+
+
 void *set_video_mode(int xsz, int ysz, int bpp)
 {
        int i;
        static uint16_t *modes;
        uint16_t best = 0;
-       unsigned int fbsize;
+       unsigned int fbsize, pgsize;
 
 #ifdef __DJGPP__
        __djgpp_nearptr_enable();
@@ -94,8 +95,20 @@ void *set_video_mode(int xsz, int ysz, int bpp)
        }
        */
 
-       fbsize = xsz * ysz * mode_info->num_img_pages * (bpp / CHAR_BIT);
-       return (void*)dpmi_mmap(mode_info->fb_addr, fbsize);
+       printf("avail video pages: %d\n", mode_info->num_img_pages);
+       printf("bytes per scanline: %d (%d pixels)\n", vbe_get_scanlen(VBE_SCANLEN_BYTES),
+                       vbe_get_scanlen(VBE_SCANLEN_PIXELS));
+
+       pgsize = xsz * ysz * (bpp / CHAR_BIT);
+       fbsize = mode_info->num_img_pages * pgsize;
+       vpgaddr[0] = (void*)dpmi_mmap(mode_info->fb_addr, fbsize);
+
+       if(mode_info->num_img_pages > 1) {
+               vpgaddr[1] = (char*)vpgaddr[0] + pgsize;
+       } else {
+               vpgaddr[1] = 0;
+       }
+       return vpgaddr[0];
 }
 
 int set_text_mode(void)
@@ -154,6 +167,33 @@ void set_palette(int idx, int r, int g, int b)
        vbe_set_palette(idx, col, 1, pal_bits);
 }
 
+void *page_flip(int vsync)
+{
+       static int frame;
+       void *nextaddr;
+       int y, when, bufidx;
+
+       if(!vpgaddr[1]) {
+               /* page flipping not supported */
+               return 0;
+       }
+
+       bufidx = ++frame & 1;
+
+       y = bufidx ? mode_info->yres : 0;
+       nextaddr = vpgaddr[bufidx];
+
+       when = vsync ? VBE_SET_DISP_START_VBLANK : VBE_SET_DISP_START_NOW;
+       if(vbe_set_disp_start(0, y, when) == -1) {
+               return 0;
+       }
+
+       if(vsync == FLIP_VBLANK_WAIT) {
+               wait_vsync();
+       }
+       return nextaddr;
+}
+
 static unsigned int make_mask(int sz, int pos)
 {
        unsigned int i, mask = 0;
@@ -163,6 +203,3 @@ static unsigned int make_mask(int sz, int pos)
        }
        return mask << pos;
 }
-
-
-#endif /* GFX_H_ */
index 7e12554..109bbcf 100644 (file)
@@ -15,6 +15,14 @@ int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask
 
 void set_palette(int idx, int r, int g, int b);
 
+enum {
+       FLIP_NOW,
+       FLIP_VBLANK,
+       FLIP_VBLANK_WAIT
+};
+/* page flip and return pointer to the start of the display area (front buffer) */
+void *page_flip(int vsync);
+
 #ifdef __WATCOMC__
 void wait_vsync(void);
 #pragma aux wait_vsync = \
index 0b3747e..c25ea6d 100644 (file)
@@ -3,6 +3,7 @@
 #include <math.h>
 #include <string.h>
 #include <limits.h>
+#include <assert.h>
 #include <conio.h>
 #include "demo.h"
 #include "keyb.h"
@@ -45,11 +46,15 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       if(!(vmem_front = set_video_mode(fb_width, fb_height, fb_bpp))) {
+       if(!(vmem_back = set_video_mode(fb_width, fb_height, fb_bpp))) {
                return 1;
        }
-       /* TODO implement multiple video memory pages for flipping */
-       vmem_back = vmem_front;
+       if(!(vmem_front = page_flip(FLIP_NOW))) {
+               /* page flipping not supported */
+               vmem_front = vmem_back;
+       } else {
+               assert(vmem_back != vmem_front);
+       }
 
        if(demo_init(argc, argv) == -1) {
                set_text_mode();
@@ -95,18 +100,30 @@ void demo_quit(void)
 
 void swap_buffers(void *pixels)
 {
-       /* TODO implement page flipping */
        if(pixels) {
+               /* just memcpy to the front buffer */
                if(opt.vsync) {
                        wait_vsync();
                }
                drawFps(pixels);
                memcpy(vmem_front, pixels, fbsize);
+
        } else {
-               drawFps(vmem_back);
+               /* attempt page flipping */
+               void *next;
 
-               if(opt.vsync) {
-                       wait_vsync();
+               drawFps(vmem_back);
+               if((next = page_flip(opt.vsync ? FLIP_VBLANK_WAIT : FLIP_NOW))) {
+                       assert(next == vmem_back);
+                       vmem_back = vmem_front;
+                       vmem_front = next;
+               } else {
+                       /* failed to page flip, assume we drew in the front buffer then
+                        * and just wait for vsync if necessary
+                        */
+                       if(opt.vsync) {
+                               wait_vsync();
+                       }
                }
        }
 }
index 009d5ca..5b1afb5 100644 (file)
@@ -130,6 +130,62 @@ void vbe_set_palette(int idx, int *col, int count, int bits)
        }
 }
 
+int vbe_set_disp_start(int x, int y, int when)
+{
+       struct dpmi_real_regs regs;
+
+       memset(&regs, 0, sizeof regs);
+       regs.eax = 0x4f07;
+       regs.ebx = when & 0xffff;
+       regs.ecx = x & 0xffff;
+       regs.edx = y & 0xffff;
+       dpmi_real_int(0x10, &regs);
+
+       if(regs.eax == 0x100) {
+               return -1;
+       }
+       return 0;
+}
+
+int vbe_set_scanlen(int len, int mode)
+{
+       struct dpmi_real_regs regs;
+
+       memset(&regs, 0, sizeof regs);
+       regs.eax = 0x4f06;
+       regs.ebx = mode;
+       regs.ecx = len & 0xffff;
+       dpmi_real_int(0x10, &regs);
+
+       if(regs.eax == 0x100) {
+               return -1;
+       }
+       return regs.ecx & 0xffff;
+}
+
+int vbe_get_scanlen(int mode)
+{
+       int res;
+       struct dpmi_real_regs regs;
+
+       memset(&regs, 0, sizeof regs);
+       regs.eax = 0x4f06;
+       regs.ebx = 1;
+       dpmi_real_int(0x10, &regs);
+
+       if(regs.eax == 0x100) {
+               return -1;
+       }
+
+       if(mode == VBE_SCANLEN_PIXELS) {
+               res = regs.ecx & 0xffff;
+       } else {
+               res = regs.ebx & 0xffff;
+       }
+       return res;
+}
+
+
 static unsigned int get_mask(int sz, int pos)
 {
        unsigned int i, mask = 0;
index 5854d5e..011cba3 100644 (file)
@@ -71,6 +71,15 @@ int vbe_set_mode(int mode);
 int vbe_set_palette_bits(int bits);
 void vbe_set_palette(int idx, int *col, int count, int bits);
 
+#define VBE_SET_DISP_START_NOW         0
+#define VBE_SET_DISP_START_VBLANK      0x80
+int vbe_set_disp_start(int x, int y, int when);
+
+#define VBE_SCANLEN_PIXELS     0
+#define VBE_SCANLEN_BYTES      2
+int vbe_set_scanlen(int len, int mode);
+int vbe_get_scanlen(int mode);
+
 void print_mode_info(FILE *fp, struct vbe_mode_info *modei);
 
 #endif /* VBE_H_ */
index fc0d52b..e542427 100644 (file)
@@ -182,13 +182,10 @@ static void backdrop(void)
 
 static void draw(void)
 {
-       int i, j;
-       uint16_t *fbptr = fb_pixels;
-       static float vdir[3];
-       float t = (float)time_msec / 16.0f;
-
        update();
 
+       g3d_framebuffer_addr(fb_pixels);
+
        backdrop();
 
        g3d_matrix_mode(G3D_MODELVIEW);