backported fixes from rtxon
authorJohn Tsiombikas <nuclear@mutantstargoat.com>
Sat, 8 Sep 2018 03:40:38 +0000 (06:40 +0300)
committerJohn Tsiombikas <nuclear@mutantstargoat.com>
Sat, 8 Sep 2018 03:40:38 +0000 (06:40 +0300)
13 files changed:
libs/mikmod/dos/out/deleteme [new file with mode: 0644]
src/3dgfx.c
src/3dgfx.h
src/demo.c
src/demo.h
src/dos/gfx.c
src/dos/gfx.h
src/dos/main.c
src/dos/vbe.c
src/dos/vbe.h
src/music.c
src/polytmpl.h
src/sdl/main.c

diff --git a/libs/mikmod/dos/out/deleteme b/libs/mikmod/dos/out/deleteme
new file mode 100644 (file)
index 0000000..056c618
--- /dev/null
@@ -0,0 +1 @@
+this file exists only to force this directory in the repo
index 044ab66..a642c1e 100644 (file)
@@ -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; i<G3D_NUM_MATRICES; i++) {
@@ -116,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;
@@ -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<vnum; i++) {
                        if(v[i].w != 0.0f) {
index 2a82284..366912f 100644 (file)
@@ -19,16 +19,21 @@ enum {
 
 /* g3d_enable/g3d_disable bits */
 enum {
-       G3D_CULL_FACE   = 0x0001,
-       G3D_DEPTH_TEST  = 0x0002,       /* XXX not implemented */
-       G3D_LIGHTING    = 0x0004,
-       G3D_LIGHT0              = 0x0008,
-       G3D_LIGHT1              = 0x0010,
-       G3D_LIGHT2              = 0x0020,
-       G3D_LIGHT3              = 0x0040,
-       G3D_TEXTURE             = 0x0080,
-       G3D_BLEND               = 0x0100,
-       G3D_TEXTURE_GEN = 0x0200,
+       G3D_CULL_FACE   = 0x000001,
+       G3D_DEPTH_TEST  = 0x000002,     /* XXX not implemented */
+       G3D_LIGHTING    = 0x000004,
+       G3D_LIGHT0              = 0x000008,
+       G3D_LIGHT1              = 0x000010,
+       G3D_LIGHT2              = 0x000020,
+       G3D_LIGHT3              = 0x000040,
+       G3D_TEXTURE             = 0x000080,
+       G3D_BLEND               = 0x000100,
+       G3D_TEXTURE_GEN = 0x000200,
+       G3D_CLIP_FRUSTUM = 0x000800,/* when disabled, don't clip against the frustum */
+       G3D_CLIP_PLANE0 = 0x001000,     /* user-defined 3D clipping planes XXX not impl. */
+       G3D_CLIP_PLANE1 = 0x002000,
+       G3D_CLIP_PLANE2 = 0x004000,
+       G3D_CLIP_PLANE3 = 0x008000,
 
        G3D_ALL = 0x7fffffff
 };
@@ -57,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 2ff25a7..168a544 100644 (file)
 #include "tinyfps.h"
 #include "util.h"
 
-int fb_width = 320;
-int fb_height = 240;
+#define FB_WIDTH       320
+#define FB_HEIGHT      240
+
+int fb_width = FB_WIDTH;
+int fb_height = FB_HEIGHT;
 int fb_bpp = 16;
 uint16_t *fb_pixels, *vmem_back, *vmem_front;
 unsigned long time_msec;
@@ -99,9 +102,68 @@ void demo_draw(void)
        scr_update();
        scr_draw();
 
+       draw_mouse_pointer(vmem_front);
+
        ++nframes;
 }
 
+
+
+#define DEST(x, y)     dest[(y) * FB_WIDTH + (x)]
+void draw_mouse_pointer(uint16_t *fb)
+{
+       uint16_t *dest = fb + mouse_y * FB_WIDTH + mouse_x;
+       int ylines = FB_HEIGHT - mouse_y;
+
+       switch(ylines) {
+       default:
+       case 10:
+               DEST(0, 9) = 0xffff;
+       case 9:
+               DEST(0, 8) = 0xffff;
+               DEST(1, 8) = 0xffff;
+       case 8:
+               DEST(0, 7) = 0xffff;
+               DEST(2, 7) = 0xffff;
+               DEST(1, 7) = 0;
+       case 7:
+               DEST(6, 6) = 0xffff;
+               DEST(0, 6) = 0xffff;
+               DEST(3, 6) = 0xffff;
+               DEST(4, 6) = 0xffff;
+               DEST(5, 6) = 0xffff;
+               DEST(1, 6) = 0;
+               DEST(2, 6) = 0;
+       case 6:
+               DEST(5, 5) = 0xffff;
+               DEST(0, 5) = 0xffff;
+               DEST(1, 5) = 0;
+               DEST(2, 5) = 0;
+               DEST(3, 5) = 0;
+               DEST(4, 5) = 0;
+       case 5:
+               DEST(4, 4) = 0xffff;
+               DEST(0, 4) = 0xffff;
+               DEST(1, 4) = 0;
+               DEST(2, 4) = 0;
+               DEST(3, 4) = 0;
+       case 4:
+               DEST(3, 3) = 0xffff;
+               DEST(0, 3) = 0xffff;
+               DEST(1, 3) = 0;
+               DEST(2, 3) = 0;
+       case 3:
+               DEST(2, 2) = 0xffff;
+               DEST(0, 2) = 0xffff;
+               DEST(1, 2) = 0;
+       case 2:
+               DEST(1, 1) = 0xffff;
+               DEST(0, 1) = 0xffff;
+       case 1:
+               DEST(0, 0) = 0xffff;
+       }
+}
+
 static void change_screen(int idx)
 {
        printf("change screen %d\n", idx);
@@ -211,7 +273,7 @@ void mouse_orbit_update(float *theta, float *phi, float *dist)
                        int dy = mouse_y - prev_my;
 
                        if(dx || dy) {
-                               if(mouse_bmask & MOUSE_LEFT) {
+                               if(mouse_bmask & MOUSE_BN_LEFT) {
                                        float p = *phi;
                                        *theta += dx * 1.0;
                                        p += dy * 1.0;
@@ -220,7 +282,7 @@ void mouse_orbit_update(float *theta, float *phi, float *dist)
                                        if(p > 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;
index 63489c7..bf3eaa6 100644 (file)
@@ -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_ */
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 018ed51..3ac7616 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"
@@ -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();
+                       }
                }
        }
 }
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 f4327f5..11b9c44 100644 (file)
@@ -1,5 +1,7 @@
 #include <stdlib.h>
 #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
index 12df420..d61ac8e 100644 (file)
@@ -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<nverts; i++) {
+               int next = NEXTIDX(i);
+               winding += (pv[next].x - pv[i].x) * (pv[next].y + pv[i].y);
+       }
+
        /* +1 to avoid crashing due to off-by-one rounding errors in the rasterization */
        left = alloca((pfill_fb.height + 1) * sizeof *left);
        right = alloca((pfill_fb.height + 1) * sizeof *right);
@@ -133,9 +139,16 @@ void POLYFILL(struct pvertex *pv, int nverts)
                                if(idx < sltop) sltop = idx;
                        /*}*/
                } else {
-                       struct pvertex *edge = y0 > 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;
index 358d774..e7e161e 100644 (file)
@@ -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;
        }