From: John Tsiombikas Date: Tue, 4 Sep 2018 01:27:32 +0000 (+0300) Subject: added page flipping/scrolling VBE calls X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosrtxon;a=commitdiff_plain;h=d7444ccbe3cb732d7259f134ee5a21d24160cc56 added page flipping/scrolling VBE calls --- diff --git a/RUN b/RUN new file mode 100755 index 0000000..5db8178 --- /dev/null +++ b/RUN @@ -0,0 +1,3 @@ +#!/bin/sh + +dosbox -exit demo.exe $* diff --git a/src/3dgfx.c b/src/3dgfx.c index 64fd604..a642c1e 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -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; diff --git a/src/3dgfx.h b/src/3dgfx.h index 07a3aea..366912f 100644 --- a/src/3dgfx.h +++ b/src/3dgfx.h @@ -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); diff --git a/src/dos/gfx.c b/src/dos/gfx.c index c2e4f8d..cbb1ed4 100644 --- a/src/dos/gfx.c +++ b/src/dos/gfx.c @@ -1,10 +1,8 @@ -#ifndef GFX_H_ -#define GFX_H_ - #include #include #include #include +#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_ */ diff --git a/src/dos/gfx.h b/src/dos/gfx.h index 7e12554..109bbcf 100644 --- a/src/dos/gfx.h +++ b/src/dos/gfx.h @@ -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 = \ diff --git a/src/dos/main.c b/src/dos/main.c index 0b3747e..c25ea6d 100644 --- a/src/dos/main.c +++ b/src/dos/main.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #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(); + } } } } diff --git a/src/dos/vbe.c b/src/dos/vbe.c index 009d5ca..5b1afb5 100644 --- a/src/dos/vbe.c +++ b/src/dos/vbe.c @@ -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(®s, 0, sizeof regs); + regs.eax = 0x4f07; + regs.ebx = when & 0xffff; + regs.ecx = x & 0xffff; + regs.edx = y & 0xffff; + dpmi_real_int(0x10, ®s); + + if(regs.eax == 0x100) { + return -1; + } + return 0; +} + +int vbe_set_scanlen(int len, int mode) +{ + struct dpmi_real_regs regs; + + memset(®s, 0, sizeof regs); + regs.eax = 0x4f06; + regs.ebx = mode; + regs.ecx = len & 0xffff; + dpmi_real_int(0x10, ®s); + + if(regs.eax == 0x100) { + return -1; + } + return regs.ecx & 0xffff; +} + +int vbe_get_scanlen(int mode) +{ + int res; + struct dpmi_real_regs regs; + + memset(®s, 0, sizeof regs); + regs.eax = 0x4f06; + regs.ebx = 1; + dpmi_real_int(0x10, ®s); + + 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; diff --git a/src/dos/vbe.h b/src/dos/vbe.h index 5854d5e..011cba3 100644 --- a/src/dos/vbe.h +++ b/src/dos/vbe.h @@ -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_ */ diff --git a/src/parts/rtxonoff.c b/src/parts/rtxonoff.c index fc0d52b..e542427 100644 --- a/src/parts/rtxonoff.c +++ b/src/parts/rtxonoff.c @@ -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);