From 5029eb9f7a538dd58e1c66c0945784acac8cc58b Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 8 Sep 2018 06:40:38 +0300 Subject: [PATCH] backported fixes from rtxon --- libs/mikmod/dos/out/deleteme | 1 + src/3dgfx.c | 28 +++++++++++------ src/3dgfx.h | 26 ++++++++++------ src/demo.c | 71 +++++++++++++++++++++++++++++++++++++++--- src/demo.h | 8 +++-- src/dos/gfx.c | 55 ++++++++++++++++++++++++++------ src/dos/gfx.h | 8 +++++ src/dos/main.c | 31 +++++++++++++----- src/dos/vbe.c | 56 +++++++++++++++++++++++++++++++++ src/dos/vbe.h | 9 ++++++ src/music.c | 27 ++++++++++++++++ src/polytmpl.h | 19 +++++++++-- src/sdl/main.c | 7 +++-- 13 files changed, 298 insertions(+), 48 deletions(-) create mode 100644 libs/mikmod/dos/out/deleteme diff --git a/libs/mikmod/dos/out/deleteme b/libs/mikmod/dos/out/deleteme new file mode 100644 index 0000000..056c618 --- /dev/null +++ b/libs/mikmod/dos/out/deleteme @@ -0,0 +1 @@ +this file exists only to force this directory in the repo diff --git a/src/3dgfx.c b/src/3dgfx.c index 044ab66..a642c1e 100644 --- a/src/3dgfx.c +++ b/src/3dgfx.c @@ -82,6 +82,7 @@ int g3d_init(void) fprintf(stderr, "failed to allocate G3D context\n"); return -1; } + st->opt = G3D_CLIP_FRUSTUM; st->fill_mode = POLYFILL_FLAT; for(i=0; ipixels = pixels; + pfill_fb.pixels = pixels; +} + void g3d_viewport(int x, int y, int w, int h) { st->vport[0] = x; @@ -438,17 +446,19 @@ void g3d_draw_indexed(int prim, const struct g3d_vertex *varr, int varr_size, } /* clipping */ - for(i=0; i<6; i++) { - memcpy(tmpv, v, vnum * sizeof *v); - - if(clip_frustum(v, &vnum, tmpv, vnum, i) < 0) { - /* polygon completely outside of view volume. discard */ - vnum = 0; - break; + if(st->opt & G3D_CLIP_FRUSTUM) { + for(i=0; i<6; i++) { + memcpy(tmpv, v, vnum * sizeof *v); + + if(clip_frustum(v, &vnum, tmpv, vnum, i) < 0) { + /* polygon completely outside of view volume. discard */ + vnum = 0; + break; + } } - } - if(!vnum) continue; + if(!vnum) continue; + } for(i=0; i 90) p = 90; *phi = p; } - if(mouse_bmask & MOUSE_RIGHT) { + if(mouse_bmask & MOUSE_BN_RIGHT) { *dist += dy * 0.5; if(*dist < 0) *dist = 0; @@ -228,6 +290,7 @@ void mouse_orbit_update(float *theta, float *phi, float *dist) } } } + prev_mx = mouse_x; prev_my = mouse_y; prev_bmask = mouse_bmask; diff --git a/src/demo.h b/src/demo.h index 63489c7..bf3eaa6 100644 --- a/src/demo.h +++ b/src/demo.h @@ -14,9 +14,9 @@ extern int mouse_x, mouse_y; extern unsigned int mouse_bmask; enum { - MOUSE_LEFT = 1, - MOUSE_RIGHT = 2, - MOUSE_MIDDLE = 4 + MOUSE_BN_LEFT = 1, + MOUSE_BN_RIGHT = 2, + MOUSE_BN_MIDDLE = 4 }; extern float sball_matrix[16]; @@ -43,4 +43,6 @@ void swap_buffers(void *pixels); /* call each frame to get 3D viewing spherical coordinates */ void mouse_orbit_update(float *theta, float *phi, float *dist); +void draw_mouse_pointer(uint16_t *fb); + #endif /* DEMO_H_ */ 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 018ed51..3ac7616 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" @@ -50,11 +51,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))) { + fprintf(stderr, "page flipping not supported. falling back to double buffering\n"); + vmem_front = vmem_back; + } else { + assert(vmem_back != vmem_front); + } if(demo_init(argc, argv) == -1) { set_text_mode(); @@ -115,18 +120,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/music.c b/src/music.c index f4327f5..11b9c44 100644 --- a/src/music.c +++ b/src/music.c @@ -1,5 +1,7 @@ #include #include "music.h" + +#ifndef NO_MUSIC #include "mikmod.h" #ifdef __WATCOMC__ @@ -150,3 +152,28 @@ static void MikMod_RegisterAllLoaders(void) ML_RegisterLoader(&load_xm); } #endif + +#else /* NO_MUSIC */ + +int music_open(const char *fname) +{ + return 0; +} + +void music_close(void) +{ +} + +void music_play(void) +{ +} + +void music_stop(void) +{ +} + +void music_update(void) +{ +} + +#endif diff --git a/src/polytmpl.h b/src/polytmpl.h index 12df420..d61ac8e 100644 --- a/src/polytmpl.h +++ b/src/polytmpl.h @@ -93,6 +93,12 @@ void POLYFILL(struct pvertex *pv, int nverts) if(pv[i].y > pv[botidx].y) botidx = i; } + int winding = 0; + for(i=0; i y1 ? left : right; - uint32_t res = SCANEDGE(pv + i, pv + next, edge); - uint32_t tmp = (res >> 16) & 0xffff; + struct pvertex *edge; + uint32_t res, tmp; + + if(winding < 0) { + edge = y0 > y1 ? left : right; + } else { + edge = y0 > y1 ? right : left; + } + res = SCANEDGE(pv + i, pv + next, edge); + tmp = (res >> 16) & 0xffff; if(tmp > slbot) slbot = tmp; if((tmp = res & 0xffff) < sltop) { sltop = tmp; diff --git a/src/sdl/main.c b/src/sdl/main.c index 358d774..e7e161e 100644 --- a/src/sdl/main.c +++ b/src/sdl/main.c @@ -46,6 +46,7 @@ int main(int argc, char **argv) return 1; } SDL_WM_SetCaption("dosdemo/SDL", 0); + SDL_ShowCursor(0); time_msec = 0; if(demo_init(argc, argv) == -1) { @@ -123,11 +124,11 @@ static int bnmask(int sdlbn) { switch(sdlbn) { case SDL_BUTTON_LEFT: - return MOUSE_LEFT; + return MOUSE_BN_LEFT; case SDL_BUTTON_RIGHT: - return MOUSE_RIGHT; + return MOUSE_BN_RIGHT; case SDL_BUTTON_MIDDLE: - return MOUSE_MIDDLE; + return MOUSE_BN_MIDDLE; default: break; } -- 1.7.10.4