backported fixes from rtxon
[dosdemo] / src / dos / gfx.c
index 558646b..cbb1ed4 100644 (file)
@@ -1,21 +1,26 @@
-#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 "dpmi.h"
-#include "logger.h"
+#include "cdpmi.h"
+
+#ifdef __DJGPP__
+#include <sys/nearptr.h>
 
+#define REALPTR(s, o)  (void*)(((uint32_t)(s) << 4) - __djgpp_base_address + (uint32_t)(o))
+#else
 #define REALPTR(s, o)  (void*)(((uint32_t)(s) << 4) + (uint32_t)(o))
+#endif
+
 #define VBEPTR(x)              REALPTR(((x) & 0xffff0000) >> 16, (x) & 0xffff)
 #define VBEPTR_SEG(x)  (((x) & 0xffff0000) >> 16)
 #define VBEPTR_OFF(x)  ((x) & 0xffff)
 
 #define SAME_BPP(a, b) \
-       ((a) == (b) || (a) == 16 && (b) == 15 || (a) == 15 && (b) == 16 || (a) == 32 && (b) == 24 || (a) == 24 && (b) == 32)
+       ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
+        ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32))
 
 static unsigned int make_mask(int sz, int pos);
 
@@ -23,11 +28,19 @@ 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;
-       uint16_t *modes, best = 0;
-       unsigned int fbsize;
+       static uint16_t *modes;
+       uint16_t best = 0;
+       unsigned int fbsize, pgsize;
+
+#ifdef __DJGPP__
+       __djgpp_nearptr_enable();
+#endif
 
        /* check for VBE2 support and output some info */
        if(!vbe_info) {
@@ -36,15 +49,15 @@ void *set_video_mode(int xsz, int ysz, int bpp)
                        return 0;
                }
 
-               printlog("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff);
+               printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff);
                if(vbe_info->version < 0x200) {
                        fprintf(stderr, "This program requires VBE 2.0 or greater. Try running UniVBE\n");
                        return 0;
                }
 
-               printlog("Graphics adapter: %s, %s (%s)\n", VBEPTR(vbe_info->oem_vendor_name_ptr),
-                               VBEPTR(vbe_info->oem_product_name_ptr), VBEPTR(vbe_info->oem_product_rev_ptr));
-               printlog("Video memory: %dkb\n", vbe_info->total_mem << 6);
+               printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr),
+                               (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr));
+               printf("Video memory: %dkb\n", vbe_info->total_mem << 6);
 
                modes = VBEPTR(vbe_info->vid_mode_ptr);
        }
@@ -78,12 +91,24 @@ void *set_video_mode(int xsz, int ysz, int bpp)
        /* attempt to set 8 bits of color per component in palettized modes */
        /*if(bpp <= 8) {
                pal_bits = vbe_set_palette_bits(8);
-               printlog("palette bits per color primary: %d\n", pal_bits);
+               printf("palette bits per color primary: %d\n", pal_bits);
        }
        */
 
-       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)
@@ -142,19 +167,31 @@ void set_palette(int idx, int r, int g, int b)
        vbe_set_palette(idx, col, 1, pal_bits);
 }
 
-void wait_vsync(void)
+void *page_flip(int vsync)
 {
-       __asm {
-               mov dx, 0x3da
-       l1:
-               in al, dx
-               and al, 0x8
-               jnz l1
-       l2:
-               in al, dx
-               and al, 0x8
-               jz l2
+       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)
@@ -166,6 +203,3 @@ static unsigned int make_mask(int sz, int pos)
        }
        return mask << pos;
 }
-
-
-#endif /* GFX_H_ */