switched to vidsys (not working yet)
authorJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 26 Jun 2023 16:56:12 +0000 (19:56 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Mon, 26 Jun 2023 16:56:12 +0000 (19:56 +0300)
21 files changed:
Makefile
src/dos/cdpmi.c [new file with mode: 0644]
src/dos/cdpmi.h
src/dos/djdpmi.c [deleted file]
src/dos/drv.h [new file with mode: 0644]
src/dos/drv_s3.c [new file with mode: 0644]
src/dos/drv_vbe.c [new file with mode: 0644]
src/dos/drv_vga.c [new file with mode: 0644]
src/dos/gfx.c [deleted file]
src/dos/gfx.h [deleted file]
src/dos/main.c
src/dos/mtrr.c [new file with mode: 0644]
src/dos/mtrr.h [new file with mode: 0644]
src/dos/vbe.c [deleted file]
src/dos/vbe.h
src/dos/vga.c [deleted file]
src/dos/vga.h
src/dos/vgaregs.h [deleted file]
src/dos/vidsys.c [new file with mode: 0644]
src/dos/vidsys.h [new file with mode: 0644]
src/dos/watdpmi.c [deleted file]

index db0fa4d..ada31b2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 !ifdef __UNIX__
-dosobj = src/dos/djdpmi.obj src/dos/gfx.obj src/dos/keyb.obj src/dos/main.obj &
-       src/dos/mouse.obj src/dos/vbe.obj src/dos/vga.obj src/dos/watdpmi.obj
+dosobj = src/dos/main.obj src/dos/keyb.obj src/dos/mouse.obj src/dos/cdpmi.obj &
+       src/dos/vidsys.obj src/dos/drv_vga.obj src/dos/drv_vbe.obj src/dos/drv_s3.obj
 appobj = src/app.obj src/cmesh.obj src/darray.obj src/font.obj src/logger.obj &
        src/meshgen.obj src/meshload.obj src/options.obj src/rbtree.obj src/geom.obj &
        src/rend.obj src/rtk.obj src/scene.obj src/scr_mod.obj src/scr_rend.obj &
@@ -11,8 +11,8 @@ gawobj = src/gaw/gaw_sw.obj src/gaw/gawswtnl.obj src/gaw/polyclip.obj src/gaw/po
 incpath = -Isrc -Isrc/dos -Ilibs -Ilibs/imago/src -Ilibs/treestor/include -Ilibs/drawtext
 libpath = libpath libs/dos
 !else
-dosobj = src\dos\djdpmi.obj src\dos\gfx.obj src\dos\keyb.obj src\dos\main.obj &
-       src\dos\mouse.obj src\dos\vbe.obj src\dos\vga.obj src\dos\watdpmi.obj
+dosobj = src\dos\main.obj src\dos\keyb.obj src\dos\mouse.obj src\dos\cdpmi.obj &
+       src\dos\vidsys.obj src\dos\drv_vga.obj src\dos\drv_vbe.obj src\dos\drv_s3.obj
 appobj = src\app.obj src\cmesh.obj src\darray.obj src\font.obj src\logger.obj &
        src\meshgen.obj src\meshload.obj src\options.obj src\rbtree.obj src\geom.obj &
        src\rend.obj src\rtk.obj src\scene.obj src\scr_mod.obj src\scr_rend.obj &
diff --git a/src/dos/cdpmi.c b/src/dos/cdpmi.c
new file mode 100644 (file)
index 0000000..62e877a
--- /dev/null
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <i86.h>
+#include "cdpmi.h"
+
+#define LOWBUF_SIZE            8192
+#define RMSTACK_SIZE   4096
+
+static char *lowbuf, *lowfree;
+static uint16_t lowbuf_sel, lowbuf_seg;
+
+int dpmi_init(void)
+{
+       if(!(lowbuf_seg = dpmi_alloc(LOWBUF_SIZE >> 4, &lowbuf_sel))) {
+               fprintf(stderr, "DPMI init failed to allocate low memory buffer\n");
+               return -1;
+       }
+       lowbuf = (char*)((intptr_t)lowbuf_seg << 4);
+       lowfree = lowbuf + RMSTACK_SIZE;
+       return 0;
+}
+
+void dpmi_cleanup(void)
+{
+       if(!lowbuf_sel) return;
+       dpmi_free(lowbuf_sel);
+       lowbuf = 0;
+       lowbuf_sel = 0;
+       lowbuf_seg = 0;
+}
+
+void *dpmi_lowbuf(void)
+{
+       return lowfree;
+}
+
+uint16_t dpmi_alloc(unsigned int par, uint16_t *sel)
+{
+       union REGS regs = {0};
+
+       regs.w.ax = 0x100;
+       regs.w.bx = par;
+       int386(0x31, &regs, &regs);
+       if(regs.w.cflag != 0) {
+               return 0;
+       }
+       *sel = regs.w.dx;
+       return regs.w.ax;
+}
+
+void dpmi_free(uint16_t sel)
+{
+       union REGS regs = {0};
+
+       regs.w.ax = 0x101;
+       regs.w.dx = sel;
+       int386(0x31, &regs, &regs);
+}
+
+int dpmi_rmint(int inum, struct dpmi_regs *dregs)
+{
+       union REGS regs = {0};
+       struct SREGS sregs = {0};
+
+       regs.x.eax = 0x300;
+       regs.x.ebx = inum;
+       sregs.es = FP_SEG(dregs);
+       regs.x.edi = FP_OFF(dregs);
+       sregs.ss = lowbuf_seg;  /* 4k real mode stack */
+       int386x(0x31, &regs, &regs, &sregs);
+       if(regs.x.cflag != 0) {
+               return -1;
+       }
+       return 0;
+}
+
+void *dpmi_mmap(uint32_t phys_addr, unsigned int size)
+{
+       union REGS regs = {0};
+
+       regs.w.ax = 0x800;
+       regs.w.bx = phys_addr >> 16;
+       regs.w.cx = phys_addr & 0xffff;
+       regs.w.si = size >> 16;
+       regs.w.di = size & 0xffff;
+       int386(0x31, &regs, &regs);
+       if(regs.w.cflag != 0) {
+               return 0;
+       }
+
+       return (void*)(((intptr_t)regs.w.bx << 16) | (intptr_t)regs.w.cx);
+}
+
+void dpmi_munmap(void *ptr)
+{
+       union REGS regs = {0};
+       intptr_t addr = (intptr_t)ptr;
+
+       regs.w.ax = 0x801;
+       regs.w.bx = addr >> 16;
+       regs.w.cx = addr & 0xffff;
+       int386(0x31, &regs, &regs);
+}
index 96baf40..751f2d2 100644 (file)
@@ -1,22 +1,8 @@
-#ifndef DPMI_H_
-#define DPMI_H_
-
-#ifdef __DJGPP__
-#include <dpmi.h>
-#include <sys/nearptr.h>
-
-#define virt_to_phys(v)        ((v) + __djgpp_base_address)
-#define phys_to_virt(p)        ((p) - __djgpp_base_address)
-
-#else  /* not djgpp (basically watcom) */
-
-#define virt_to_phys(v)        (v)
-#define phys_to_virt(p)        (p)
-
-#endif /* __DJGPP__ */
+#ifndef CDPMI_H_
+#define CDPMI_H_
 
+#include <stdlib.h>
 #include "sizeint.h"
-#include "util.h"
 
 #pragma pack (push, 1)
 struct dpmi_regs {
@@ -26,7 +12,7 @@ struct dpmi_regs {
        uint16_t flags;
        uint16_t es, ds, fs, gs;
        uint16_t ip, cs, sp, ss;
-} PACKED;
+};
 #pragma pack (pop)
 
 enum {
@@ -40,66 +26,14 @@ enum {
        FLAGS_ID        = 0x200000,
 };
 
+int dpmi_init(void);
+void dpmi_cleanup(void);
+void *dpmi_lowbuf(void);
+
 uint16_t dpmi_alloc(unsigned int par, uint16_t *sel);
 void dpmi_free(uint16_t sel);
-void dpmi_int(int inum, struct dpmi_regs *regs);
+int dpmi_rmint(int inum, struct dpmi_regs *regs);
 void *dpmi_mmap(uint32_t phys_addr, unsigned int size);
 void dpmi_munmap(void *addr);
 
-#ifdef __WATCOMC__
-#pragma aux dpmi_alloc = \
-               "mov ax, 0x100" \
-               "int 0x31" \
-               "mov [edi], dx" \
-               "jnc alloc_skip_err" \
-               "xor ax, ax" \
-               "alloc_skip_err:" \
-               value[ax] \
-               parm[ebx][edi] \
-               modify[dx];
-
-#pragma aux dpmi_free = \
-               "mov ax, 0x101" \
-               "int 0x31" \
-               parm[dx] \
-               modify[ax];
-
-#pragma aux dpmi_int = \
-               "mov ax, 0x300" \
-               "xor ecx, ecx" \
-               "int 0x31" \
-               parm[ebx][edi] \
-               modify[ax ecx];
-
-#pragma aux dpmi_mmap = \
-               "mov ax, 0x800" \
-               "mov cx, bx" \
-               "shr ebx, 16" \
-               "mov di, si" \
-               "shr esi, 16" \
-               "int 0x31" \
-               "jnc mmap_skip_err" \
-               "xor bx, bx" \
-               "xor cx, cx" \
-       "mmap_skip_err:" \
-               "mov ax, bx" \
-               "shl eax, 16" \
-               "mov ax, cx" \
-               value[eax] \
-               parm[ebx][esi] \
-               modify[bx cx di esi];
-
-#pragma aux dpmi_munmap = \
-               "mov ax, 0x801" \
-               "mov cx, bx" \
-               "shr ebx, 16" \
-               "int 0x31" \
-               parm[ebx] \
-               modify[ax cx ebx];
-#endif /* __WATCOMC__ */
-
-#ifdef __DJGPP__
-#define dpmi_int(inum, regs) __dpmi_int((inum), (__dpmi_regs*)(regs))
-#endif
-
-#endif /* DPMI_H_ */
+#endif /* CDPMI_H_ */
diff --git a/src/dos/djdpmi.c b/src/dos/djdpmi.c
deleted file mode 100644 (file)
index f3a06b9..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifdef __DJGPP__
-#include <dpmi.h>
-#include <sys/nearptr.h>
-#include "cdpmi.h"
-#include "inttypes.h"
-
-uint16_t dpmi_alloc(unsigned int par, uint16_t *sel)
-{
-       int tmp;
-       uint16_t seg = __dpmi_allocate_dos_memory(par, &tmp);
-       *sel = tmp;
-       return seg;
-}
-
-void dpmi_free(uint16_t sel)
-{
-       __dpmi_free_dos_memory(sel);
-}
-
-void *dpmi_mmap(uint32_t phys_addr, unsigned int size)
-{
-       __dpmi_meminfo mem;
-       mem.address = phys_addr;
-       mem.size = size;
-       __dpmi_physical_address_mapping(&mem);
-       return (void*)(mem.address - __djgpp_base_address);
-}
-
-void dpmi_munmap(void *addr)
-{
-       __dpmi_meminfo mem;
-       mem.address = (uint32_t)addr + __djgpp_base_address;
-       __dpmi_free_physical_address_mapping(&mem);
-}
-#endif /* __DJGPP__ */
diff --git a/src/dos/drv.h b/src/dos/drv.h
new file mode 100644 (file)
index 0000000..172f146
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef DRV_H_
+#define DRV_H_
+
+#include "sizeint.h"
+
+struct vid_drvops {
+       int (*init)(void);
+       void (*cleanup)(void);
+
+       int (*setmode)(int mode);
+       int (*curmode)(void);
+};
+
+#define MAX_DRV        16
+extern struct vid_driver *vid_drvlist[MAX_DRV];
+extern int vid_numdrv;
+
+extern void *vid_vmem;
+extern int vid_vmem_size;
+
+void vid_register_vga(void);           /* drv_vga.c */
+void vid_register_vbe(void);           /* drv_vbe.c */
+void vid_register_s3(void);            /* drv_s3.c */
+
+#endif /* DRV_H_ */
diff --git a/src/dos/drv_s3.c b/src/dos/drv_s3.c
new file mode 100644 (file)
index 0000000..02287a4
--- /dev/null
@@ -0,0 +1,8 @@
+
+#include <conio.h>
+#include <i86.h>
+#include "drv.h"
+
+void vid_register_s3(void)
+{
+}
diff --git a/src/dos/drv_vbe.c b/src/dos/drv_vbe.c
new file mode 100644 (file)
index 0000000..d639417
--- /dev/null
@@ -0,0 +1,379 @@
+#include <string.h>
+#include <conio.h>
+#include <i86.h>
+#include "vidsys.h"
+#include "drv.h"
+#include "vbe.h"
+#include "vga.h"
+#include "cdpmi.h"
+
+#define farptr_to_linear(rmaddr) \
+       ((((intptr_t)(rmaddr) >> 12) & 0xffff0) + ((intptr_t)(rmaddr) & 0xffff))
+
+static int init(void);
+static void cleanup(void);
+static struct vid_modeinfo *find_mode(int mode);
+static int setmode(int mode);
+static int getmode(void);
+static const char *memsize_str(long sz);
+static int get_mode_info(int mode, struct vbe_mode_info *mi);
+static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi);
+static unsigned int calc_mask(int nbits, int pos);
+
+static void pack(uint32_t *pix, int r, int g, int b);
+static void unpack(uint32_t pix, int *r, int *g, int *b);
+static void clear(uint32_t color);
+static void blitfb_lfb(void *fb, int pitch);
+static void blitfb_banked(void *fb, int pitch);
+static void flip(int vsync);
+
+static struct vid_driver drv;
+static struct vid_drvops drvops = {init, cleanup, setmode, getmode};
+static unsigned int vbe_ver;
+
+static int cur_mode;
+static struct vid_modeinfo *cur_mi;
+static int cur_pgsize;
+
+
+void vid_register_vbe(void)
+{
+       drv.name = "vbe";
+       drv.prio = 2;
+       drv.ops = &drvops;
+
+       vid_drvlist[vid_numdrv++] = &drv;
+}
+
+
+static int init(void)
+{
+       struct dpmi_regs regs = {0};
+       struct vbe_info *vbe;
+       struct vbe_mode_info vbemi;
+       unsigned short bufseg;
+       uint16_t *vbe_modelist, *modelist;
+       int i, count;
+       struct vid_modeinfo modeinf;
+
+       cur_mode = -1;
+       cur_mi = 0;
+
+       vbe = dpmi_lowbuf();
+       bufseg = (intptr_t)vbe >> 4;
+
+       /* call VBE function 00 (get controller information) */
+       memcpy(vbe->sig, "VBE2", 4);    /* denote we want VBE 2.0 info */
+       regs.eax = 0x4f00;
+       regs.es = bufseg;
+       dpmi_rmint(0x10, &regs);
+       if((regs.eax & 0xffff) != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) {
+               fprintf(stderr, "failed to get VBE controller information\n");
+               return -1;
+       }
+
+       vbe_ver = vbe->ver;
+
+       printf("Found VBE %d.%d\n", VBE_VER_MAJOR(vbe_ver), VBE_VER_MINOR(vbe_ver));
+       printf("OEM: %s\n", (char*)farptr_to_linear(vbe->oem_name));
+       if(vbe_ver >= 0x0200) {
+               printf("%s - %s (%s)\n", (char*)farptr_to_linear(vbe->vendor),
+                               (char*)farptr_to_linear(vbe->product),
+                               (char*)farptr_to_linear(vbe->revstr));
+       }
+       printf("Video RAM: %s\n", memsize_str((long)vbe->vmem_blk * 65536));
+
+       vbe_modelist = (uint16_t*)farptr_to_linear(vbe->modelist_addr);
+       count = 0;
+       for(i=0; i<1024; i++) {
+               if(vbe_modelist[i] == 0xffff) break;
+               count++;
+       }
+
+       if(!(modelist = malloc(count * sizeof *modelist))) {
+               fprintf(stderr, "failed to allocate mode list\n");
+               return -1;
+       }
+       for(i=0; i<count; i++) {
+               modelist[i] = vbe_modelist[i];
+       }
+
+       if(!(drv.modes = malloc(count * sizeof *drv.modes))) {
+               fprintf(stderr, "failed to allocate mode list\n");
+               free(modelist);
+               return -1;
+       }
+
+       drv.num_modes = 0;
+       for(i=0; i<count; i++) {
+               if(get_mode_info(modelist[i], &vbemi) == -1) {
+                       continue;
+               }
+               if(conv_vbeinfo(modelist[i], drv.modes + drv.num_modes, &vbemi) == -1) {
+                       continue;
+               }
+               drv.num_modes++;
+       }
+
+       free(modelist);
+       return 0;
+}
+
+static void cleanup(void)
+{
+       free(drv.modes);
+       drv.modes = 0;
+       drv.num_modes = 0;
+}
+
+static struct vid_modeinfo *find_mode(int mode)
+{
+       int i;
+       for(i=0; i<drv.num_modes; i++) {
+               if(drv.modes[i].modeno == mode) {
+                       return drv.modes + i;
+               }
+       }
+       return 0;
+}
+
+static int setmode(int mode)
+{
+       struct vid_modeinfo *minf;
+       struct dpmi_regs regs = {0};
+
+       if((minf = find_mode(mode)) && minf->lfb) {
+               mode |= VBE_MODE_LFB;
+       }
+
+retry:
+       regs.eax = 0x4f02;
+       regs.ebx = mode;
+       dpmi_rmint(0x10, &regs);
+
+       if((regs.eax & 0xffff) != 0x4f) {
+               if(mode & VBE_MODE_LFB) {
+                       mode &= ~VBE_MODE_LFB;
+                       goto retry;
+               }
+               return -1;
+       }
+       cur_mode = mode;
+
+       if(!(cur_mi = minf)) return 0;
+
+       cur_pgsize = minf->height * minf->pitch;
+
+       if(mode & VBE_MODE_LFB) {
+               minf->ops.blitfb = blitfb_lfb;
+       } else {
+               minf->ops.blitfb = blitfb_banked;
+       }
+       return 0;
+}
+
+static int getmode(void)
+{
+       return cur_mode;
+}
+
+static const char *memsize_str(long sz)
+{
+       static const char *suffix[] = {"bytes", "kb", "mb", "gb", 0};
+       static int cnt = 0;
+       static char buf[64];
+
+       while(sz > 1024 && suffix[cnt + 1]) {
+               sz >>= 10;
+               cnt++;
+       }
+
+       sprintf(buf, "%ld %s", sz, suffix[cnt]);
+       return buf;
+}
+
+static int get_mode_info(int mode, struct vbe_mode_info *mi)
+{
+       struct dpmi_regs regs = {0};
+       struct vbe_mode_info *miptr;
+       uint16_t bufseg;
+
+       miptr = dpmi_lowbuf();
+       bufseg = (intptr_t)miptr >> 4;
+
+       regs.eax = 0x4f01;
+       regs.ecx = mode;
+       regs.es = bufseg;
+       dpmi_rmint(0x10, &regs);
+       if((regs.eax & 0xffff) != 0x4f) {
+               return -1;
+       }
+
+       *mi = *miptr;
+       return 0;
+}
+
+int vid_setwin(int wid, int pos)
+{
+       struct dpmi_regs regs = {0};
+
+       regs.eax = 0x4f05;
+       regs.ebx = wid;
+       regs.edx = pos;
+       dpmi_rmint(0x10, &regs);
+       if((regs.eax & 0xffff) != 0x4f) {
+               return -1;
+       }
+       return 0;
+}
+
+static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi)
+{
+       static int gran_shift;
+       static const struct { int width, height, bpp; } stdmode[] = {
+               {640, 400, 8},          /* 100h */
+               {640, 480, 8},          /* 101h */
+               {800, 600, 4}, {800, 600, 8},           /* 102h - 103h */
+               {1024, 768, 4}, {1024, 768, 8},         /* 104h - 105h */
+               {1280, 1024, 4}, {1280, 1024, 8},       /* 106h - 107h */
+               {80, 60, 4}, {132, 25, 4}, {132, 43, 4}, {132, 50, 4}, {132, 60, 4},
+               {320, 200, 15}, {320, 200, 16}, {320, 200, 24}, /* 10dh - 10fh */
+               {640, 480, 15}, {640, 480, 16}, {640, 480, 24}, /* 110h - 112h */
+               {800, 600, 15}, {800, 600, 16}, {800, 600, 24}, /* 113h - 115h */
+               {1024, 768, 15}, {1024, 768, 16}, {1024, 768, 24}, /* 116h - 118h */
+               {1280, 1024, 15}, {1280, 1024, 16}, {1280, 1024, 24} /* 119h - 11bh */
+       };
+
+       if(!(vbemi->attr & VBE_ATTR_AVAIL)) {
+               return -1;      /* ignore unsupported modes */
+       }
+       if(!(vbemi->attr & VBE_ATTR_GFX)) {
+               return -1;      /* ignore text modes */
+       }
+       if(vbemi->attr & VBE_ATTR_LFB) {
+               mi->lfb = 1;
+       }
+
+       mi->drv = &drv;
+       mi->modeno = mode;
+       mi->vmem_addr = 0xa0000;
+
+       if(vbe_ver >= 0x0102) {
+               mi->width = vbemi->xres;
+               mi->height = vbemi->yres;
+               mi->bpp = vbemi->bpp;
+               mi->rshift = vbemi->rpos;
+               mi->gshift = vbemi->gpos;
+               mi->bshift = vbemi->bpos;
+               mi->rmask = calc_mask(vbemi->rsize, vbemi->rpos);
+               mi->gmask = calc_mask(vbemi->gsize, vbemi->gpos);
+               mi->bmask = calc_mask(vbemi->bsize, vbemi->bpos);
+               mi->pages = vbemi->num_img_pages + 1;
+
+               if(vbe_ver >= 0x0200) {
+                       mi->vmem_addr = vbemi->fb_addr;
+                       mi->vmem_size = vbemi->scanline_bytes * mi->height * mi->pages;
+               }
+       } else {
+               if((mode & 0xff) > 7) {
+                       return -1;
+               }
+               mi->width = stdmode[mode & 0xff].width;
+               mi->height = stdmode[mode & 0xff].height;
+               mi->bpp = stdmode[mode & 0xff].bpp;
+       }
+       mi->ncolors = 1 << mi->bpp;
+       mi->pitch = vbemi->scanline_bytes;
+       mi->win_size = vbemi->win_size;
+       mi->win_gran = vbemi->win_gran;
+
+       gran_shift = 0;
+       mi->win_step = 1;
+       if(mi->win_gran > 0 && mi->win_gran < 64) {
+               int gran = mi->win_gran;
+               while(gran < 64) {
+                       gran_shift++;
+                       gran <<= 1;
+               }
+               mi->win_step = 1 << gran_shift;
+       }
+
+       mi->ops.pack = pack;
+       mi->ops.unpack = unpack;
+       mi->ops.setpal = vga_setpal;
+       mi->ops.getpal = vga_getpal;
+       mi->ops.vsync = vid_vsync;
+       mi->ops.clear = clear;
+       mi->ops.blitfb = 0;
+       mi->ops.flip = flip;
+       return 0;
+}
+
+static unsigned int calc_mask(int nbits, int pos)
+{
+       int i;
+       unsigned int mask = 0;
+
+       for(i=0; i<nbits; i++) {
+               mask = (mask << 1) | 1;
+       }
+       return mask << pos;
+}
+
+
+static void pack(uint32_t *pix, int r, int g, int b)
+{
+       *pix = (((uint32_t)r << cur_mi->rshift) & cur_mi->rmask) |
+               (((uint32_t)g << cur_mi->gshift) & cur_mi->gmask) |
+               (((uint32_t)b << cur_mi->bshift) & cur_mi->bmask);
+}
+
+static void unpack(uint32_t pix, int *r, int *g, int *b)
+{
+       *r = (pix & cur_mi->rmask) >> cur_mi->rshift;
+       *g = (pix & cur_mi->gmask) >> cur_mi->gshift;
+       *b = (pix & cur_mi->bmask) >> cur_mi->bshift;
+}
+
+static void clear(uint32_t color)
+{
+}
+
+static void blitfb_lfb(void *fb, int pitch)
+{
+       int i;
+       unsigned char *dest, *src;
+
+       dest = vid_vmem;
+       src = fb;
+
+       for(i=0; i<cur_mi->height; i++) {
+               memcpy(dest, src, cur_mi->pitch);
+               dest += cur_mi->pitch;
+               src += pitch;
+       }
+}
+
+static void blitfb_banked(void *fb, int pitch)
+{
+       int sz, offs, pending;
+       unsigned char *pptr = fb;
+
+       /* assume initial window offset at 0 */
+       offs = 0;
+       pending = cur_pgsize;
+       while(pending > 0) {
+               sz = pending > 65536 ? 65536 : pending;
+               memcpy((void*)0xa0000, pptr, sz);
+               pptr += sz;
+               pending -= sz;
+               offs += cur_mi->win_step;
+               vid_setwin(0, offs);
+       }
+       vid_setwin(0, 0);
+}
+
+static void flip(int vsync)
+{
+       /* TODO */
+}
diff --git a/src/dos/drv_vga.c b/src/dos/drv_vga.c
new file mode 100644 (file)
index 0000000..f6b7b01
--- /dev/null
@@ -0,0 +1,172 @@
+#include <string.h>
+#include <conio.h>
+#include <i86.h>
+#include "vidsys.h"
+#include "drv.h"
+#include "vga.h"
+
+static int init(void);
+static void cleanup(void);
+static int setmode(int mode);
+static int curmode(void);
+
+static void setpal4(int idx, int count, const struct vid_color *col);
+static void getpal4(int idx, int count, struct vid_color *col);
+static void clear4(uint32_t color);
+static void blitfb4(void *fb, int pitch);
+static void fill4(int x, int y, int w, int h, uint32_t color);
+
+static void clear8(uint32_t color);
+static void blitfb8(void *fb, int pitch);
+static void fill8(int x, int y, int w, int h, uint32_t color);
+
+
+static struct vid_driver drv;
+static struct vid_drvops drvops = {init, cleanup, setmode, curmode};
+static struct vid_modeinfo modes[] = {
+       {3, 80, 25, 4},
+       {0x12, 640, 480, 4},
+       {0x13, 320, 200, 8}
+};
+
+static struct vid_gfxops gfxops_mode12h = {
+       0, 0, setpal4, getpal4, vid_vsync, clear4, blitfb4, 0, fill4 };
+static struct vid_gfxops gfxops_mode13h = {
+       0, 0, vga_setpal, vga_getpal, vid_vsync, clear8, blitfb8, 0, fill8 };
+
+void vid_register_vga(void)
+{
+       int i;
+
+       drv.name = "vga";
+       drv.prio = 1;
+       drv.ops = &drvops;
+       drv.modes = modes;
+       drv.num_modes = sizeof modes / sizeof *modes;
+
+       for(i=0; i<drv.num_modes; i++) {
+               modes[i].drv = &drv;
+               modes[i].vmem_addr = 0xa0000;
+
+               switch(modes[i].modeno) {
+               case 0x3:
+                       modes[i].vmem_addr = 0xb8000;
+                       break;
+                               
+               case 0x13:
+                       modes[i].ops = gfxops_mode13h;
+                       break;
+
+               case 0x12:
+                       modes[i].ops = gfxops_mode12h;
+                       break;
+               }
+       }
+
+       vid_drvlist[vid_numdrv++] = &drv;
+}
+
+void vid_vsync(void)
+{
+       while(inp(VGA_STAT1_PORT) & 8);
+       while((inp(VGA_STAT1_PORT) & 8) == 0);
+}
+
+void vga_setpal(int idx, int count, const struct vid_color *col)
+{
+       int i;
+       outp(VGA_DAC_WADDR_PORT, idx);
+       for(i=0; i<count; i++) {
+               outp(VGA_DAC_DATA_PORT, col->r >> 2);
+               outp(VGA_DAC_DATA_PORT, col->g >> 2);
+               outp(VGA_DAC_DATA_PORT, col->b >> 2);
+               col++;
+       }
+}
+
+void vga_getpal(int idx, int count, struct vid_color *col)
+{
+       int i;
+       outp(VGA_DAC_RADDR_PORT, idx);
+       for(i=0; i<count; i++) {
+               col->r = inp(VGA_DAC_DATA_PORT) << 2;
+               col->g = inp(VGA_DAC_DATA_PORT) << 2;
+               col->b = inp(VGA_DAC_DATA_PORT) << 2;
+               col++;
+       }
+}
+
+
+static int init(void)
+{
+       return 0;
+}
+
+static void cleanup(void)
+{
+}
+
+static int setmode(int mode)
+{
+       union REGS regs = {0};
+       regs.w.ax = mode;
+       int386(0x10, &regs, &regs);
+       return 0;
+}
+
+static int curmode(void)
+{
+       union REGS regs = {0};
+       regs.w.ax = 0xf00;
+       int386(0x10, &regs, &regs);
+       return regs.x.eax & 0xff;
+}
+
+static void setpal4(int idx, int count, const struct vid_color *col)
+{
+}
+
+static void getpal4(int idx, int count, struct vid_color *col)
+{
+}
+
+static void clear4(uint32_t color)
+{
+}
+
+static void blitfb4(void *fb, int pitch)
+{
+}
+
+static void fill4(int x, int y, int w, int h, uint32_t color)
+{
+}
+
+static void clear8(uint32_t color)
+{
+       memset((void*)0xa0000, color, 64000);
+}
+
+static void blitfb8(void *fb, int pitch)
+{
+       int i;
+       unsigned char *src = fb;
+       unsigned char *dest = (unsigned char*)0xa0000;
+       for(i=0; i<200; i++) {
+               memcpy(dest, src, 320);
+               dest += 320;
+               src += pitch;
+       }
+}
+
+static void fill8(int x, int y, int w, int h, uint32_t color)
+{
+       int i;
+       unsigned char *fbptr = (unsigned char*)0xa0000;
+
+       fbptr += y * 320 + x;
+       for(i=0; i<h; i++) {
+               memset(fbptr, color, w);
+               fbptr += 320;
+       }
+}
diff --git a/src/dos/gfx.c b/src/dos/gfx.c
deleted file mode 100644 (file)
index ed171e8..0000000
+++ /dev/null
@@ -1,496 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dos.h>
-#include "app.h"
-#include "cdpmi.h"
-#include "gfx.h"
-#include "vbe.h"
-#include "vga.h"
-#include "util.h"
-#include "cpuid.h"
-#include "logger.h"
-
-#ifdef __DJGPP__
-#define VMEM_PTR       ((void*)(0xa0000 + __djgpp_conventional_base))
-#else
-#define VMEM_PTR       ((void*)0xa0000)
-#endif
-
-#define SAME_BPP(a, b) \
-       ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
-        ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32))
-
-void (*blit_frame)(void*, int);
-
-static void blit_frame_lfb(void *pixels, int vsync);
-static void blit_frame_banked(void *pixels, int vsync);
-static uint32_t calc_mask(int sz, int pos);
-
-static void enable_wrcomb(uint32_t addr, int len);
-static const char *mtrr_type_name(int type);
-static void print_mtrr(void);
-
-static struct video_mode *vmodes;
-static int num_vmodes;
-
-static int vbe_init_ver;
-static struct vbe_info vbe;
-
-/* current mode */
-static struct video_mode *curmode;
-static void *vpgaddr[2];
-static int frontidx, backidx;
-static int pgcount, pgsize, fbsize;
-
-
-int init_video(void)
-{
-       int i, num, max_modes;
-       struct video_mode *vmptr;
-
-       if(vbe_info(&vbe) == -1) {
-               errormsg("failed to retrieve VBE information\n");
-               return -1;
-       }
-       vbe_print_info(stdout, &vbe);
-
-       num_vmodes = 0;
-       max_modes = 64;
-       if(!(vmodes = malloc(max_modes * sizeof *vmodes))) {
-               errormsg("failed to allocate video modes list\n");
-               return -1;
-       }
-
-       num = vbe_num_modes(&vbe);
-       for(i=0; i<num; i++) {
-               struct vbe_mode_info minf;
-
-               if(vbe_mode_info(vbe.modes[i], &minf) == -1) {
-                       continue;
-               }
-
-               if(num_vmodes >= max_modes) {
-                       int newmax = max_modes ? (max_modes << 1) : 16;
-                       if(!(vmptr = realloc(vmodes, newmax * sizeof *vmodes))) {
-                               errormsg("failed to grow video mode list (%d)\n", newmax);
-                               free(vmodes);
-                               return -1;
-                       }
-                       vmodes = vmptr;
-                       max_modes = newmax;
-               }
-
-               vmptr = vmodes + num_vmodes++;
-               memset(vmptr, 0, sizeof *vmptr);
-               vmptr->mode = vbe.modes[i];
-               vmptr->xsz = minf.xres;
-               vmptr->ysz = minf.yres;
-               vmptr->bpp = minf.bpp;
-               vmptr->pitch = minf.scanline_bytes;
-               if(minf.mem_model == VBE_TYPE_DIRECT) {
-                       vmptr->rbits = minf.rsize;
-                       vmptr->gbits = minf.gsize;
-                       vmptr->bbits = minf.bsize;
-                       vmptr->rshift = minf.rpos;
-                       vmptr->gshift = minf.gpos;
-                       vmptr->bshift = minf.bpos;
-                       vmptr->rmask = calc_mask(minf.rsize, minf.rpos);
-                       vmptr->gmask = calc_mask(minf.gsize, minf.gpos);
-                       vmptr->bmask = calc_mask(minf.bsize, minf.bpos);
-                       /*vmptr->bpp = vmptr->rbits + vmptr->gbits + vmptr->bbits;*/
-               }
-               if(minf.attr & VBE_ATTR_LFB) {
-                       vmptr->fb_addr = minf.fb_addr;
-               }
-               vmptr->max_pages = minf.num_img_pages;
-               vmptr->win_gran = minf.win_gran;
-
-               infomsg("%04x: ", vbe.modes[i]);
-               vbe_print_mode_info(stdout, &minf);
-       }
-       /*fflush(stdout);*/
-
-       vbe_init_ver = VBE_VER_MAJOR(vbe.ver);
-       return 0;
-}
-
-void cleanup_video(void)
-{
-       free(vmodes);
-}
-
-struct video_mode *video_modes(void)
-{
-       return vmodes;
-}
-
-int num_video_modes(void)
-{
-       return num_vmodes;
-}
-
-struct video_mode *get_video_mode(int idx)
-{
-       if(idx == VMODE_CURRENT) {
-               return curmode;
-       }
-       return vmodes + idx;
-}
-
-int match_video_mode(int xsz, int ysz, int bpp)
-{
-       int i, best = -1;
-       struct video_mode *vm;
-
-       for(i=0; i<num_vmodes; i++) {
-               vm = vmodes + i;
-               if(vm->xsz != xsz || vm->ysz != ysz) continue;
-               if(SAME_BPP(vm->bpp, bpp)) {
-                       best = i;
-               }
-               if(vm->bpp == bpp) break;
-       }
-
-       if(best == -1) {
-               errormsg("failed to find video mode %dx%d %d bpp)\n", xsz, ysz, bpp);
-               return -1;
-       }
-       return best;
-}
-
-int find_video_mode(int mode)
-{
-       int i;
-       struct video_mode *vm;
-
-       vm = vmodes;
-       for(i=0; i<num_vmodes; i++) {
-               if(vm->mode == mode) return i;
-       }
-       return -1;
-}
-
-void *set_video_mode(int idx, int nbuf)
-{
-       unsigned int mode;
-       struct video_mode *vm = vmodes + idx;
-
-       if(curmode == vm) return vpgaddr[0];
-
-       infomsg("setting video mode %x (%dx%d %d bpp)\n", (unsigned int)vm->mode,
-                       vm->xsz, vm->ysz, vm->bpp);
-       /*fflush(stdout);*/
-
-       mode = vm->mode | VBE_MODE_LFB;
-       if(vbe_setmode(mode) == -1) {
-               infomsg("Warning: failed to get a linear framebuffer. falling back to banked mode\n");
-               mode = vm->mode;
-               if(vbe_setmode(mode) == -1) {
-                       errormsg("failed to set video mode %x\n", (unsigned int)vm->mode);
-                       return 0;
-               }
-       }
-
-       /* unmap previous video memory mapping, if there was one (switching modes) */
-       if(vpgaddr[0] && vpgaddr[0] != VMEM_PTR) {
-               dpmi_munmap(vpgaddr[0]);
-               vpgaddr[0] = vpgaddr[1] = 0;
-       }
-
-       curmode = vm;
-       if(nbuf < 1) nbuf = 1;
-       if(nbuf > 2) nbuf = 2;
-       pgcount = nbuf > vm->max_pages + 1 ? vm->max_pages + 1 : nbuf;
-       pgsize = vm->ysz * vm->pitch;
-       fbsize = pgcount * pgsize;
-
-       if(vm->bpp > 8) {
-               infomsg("rgb mask: %x %x %x\n", (unsigned int)vm->rmask,
-                               (unsigned int)vm->gmask, (unsigned int)vm->bmask);
-               infomsg("rgb shift: %d %d %d\n", vm->rshift, vm->gshift, vm->bshift);
-       }
-       infomsg("pgcount: %d, pgsize: %d, fbsize: %d\n", pgcount, pgsize, fbsize);
-       if(vm->fb_addr) {
-               infomsg("phys addr: %p\n", (void*)vm->fb_addr);
-       }
-       /*fflush(stdout);*/
-
-       if(vm->fb_addr) {
-               vpgaddr[0] = (void*)dpmi_mmap(vm->fb_addr, fbsize);
-               if(!vpgaddr[0]) {
-                       errormsg("failed to map framebuffer (phys: %lx, size: %d)\n",
-                                       (unsigned long)vm->fb_addr, fbsize);
-                       set_text_mode();
-                       return 0;
-               }
-               memset(vpgaddr[0], 0xaa, pgsize);
-
-               if(pgcount > 1) {
-                       vpgaddr[1] = (char*)vpgaddr[0] + pgsize;
-                       backidx = 1;
-                       page_flip(FLIP_NOW);    /* start with the second page visible */
-               } else {
-                       frontidx = backidx = 0;
-                       vpgaddr[1] = 0;
-               }
-
-               blit_frame = blit_frame_lfb;
-
-               /* only attempt to set up write combining if the CPU we're running on
-                * supports memory type range registers, and we're running on ring 0
-                */
-               if(CPU_HAVE_MTRR) {
-                       int cpl = get_cpl();
-                       if(cpl > 0) {
-                               errormsg("Can't set framebuffer range to write-combining, running in ring %d\n", cpl);
-                       } else {
-                               uint32_t len = (uint32_t)vbe.vmem_blk << 16;
-
-                               /* if vmem_blk is 0 or if the reported size is absurd (more than
-                                * 256mb), just use the framebuffer size for this mode to setup the
-                                * mtrr
-                                */
-                               if(!len || len > 0x10000000) {
-                                       infomsg("reported vmem too large or overflowed, using fbsize for wrcomb setup\n");
-                                       len = fbsize;
-                               }
-                               print_mtrr();
-                               enable_wrcomb(vm->fb_addr, len);
-                       }
-               }
-
-       } else {
-               vpgaddr[0] = VMEM_PTR;
-               vpgaddr[1] = 0;
-
-               blit_frame = blit_frame_banked;
-
-               /* calculate window granularity shift */
-               vm->win_gran_shift = 0;
-               vm->win_64k_step = 1;
-               if(vm->win_gran > 0 && vm->win_gran < 64) {
-                       int gran = vm->win_gran;
-                       while(gran < 64) {
-                               vm->win_gran_shift++;
-                               gran <<= 1;
-                       }
-                       vm->win_64k_step = 1 << vm->win_gran_shift;
-               }
-
-               infomsg("granularity: %dk (step: %d)\n", vm->win_gran, vm->win_64k_step);
-       }
-
-       /*fflush(stdout);*/
-       return vpgaddr[0];
-}
-
-int set_text_mode(void)
-{
-       /* unmap previous video memory mapping, if there was one (switching modes) */
-       if(vpgaddr[0] && vpgaddr[0] != VMEM_PTR) {
-               dpmi_munmap(vpgaddr[0]);
-               vpgaddr[0] = vpgaddr[1] = 0;
-       }
-
-       vga_setmode(3);
-       curmode = 0;
-       return 0;
-}
-
-void *page_flip(int vsync)
-{
-       if(!vpgaddr[1]) {
-               /* page flipping not supported */
-               return vpgaddr[0];
-       }
-
-       vbe_swap(backidx ? pgsize : 0, vsync ? VBE_SWAP_VBLANK : VBE_SWAP_NOW);
-       frontidx = backidx;
-       backidx = (backidx + 1) & 1;
-
-       return vpgaddr[backidx];
-}
-
-
-static void blit_frame_lfb(void *pixels, int vsync)
-{
-       if(vsync) wait_vsync();
-       memcpy(vpgaddr[frontidx], pixels, pgsize);
-}
-
-static void blit_frame_banked(void *pixels, int vsync)
-{
-       int sz, offs, pending;
-       unsigned char *pptr = pixels;
-
-       if(vsync) wait_vsync();
-
-       /* assume initial window offset at 0 */
-       offs = 0;
-       pending = pgsize;
-       while(pending > 0) {
-               sz = pending > 65536 ? 65536 : pending;
-               memcpy(VMEM_PTR, pptr, sz);
-               pptr += sz;
-               pending -= sz;
-               offs += curmode->win_64k_step;
-               vbe_setwin(0, offs);
-       }
-       vbe_setwin(0, 0);
-}
-
-static uint32_t calc_mask(int sz, int pos)
-{
-       uint32_t mask = 0;
-       while(sz-- > 0) {
-               mask = (mask << 1) | 1;
-       }
-       return mask << pos;
-}
-
-#define MSR_MTRRCAP                    0xfe
-#define MSR_MTRRDEFTYPE                0x2ff
-#define MSR_MTRRBASE(x)                (0x200 | ((x) << 1))
-#define MSR_MTRRMASK(x)                (0x201 | ((x) << 1))
-#define MTRRDEF_EN                     0x800
-#define MTRRCAP_HAVE_WC                0x400
-#define MTRRMASK_VALID         0x800
-
-#define MTRR_WC                                1
-
-static int get_page_memtype(uint32_t addr, int num_ranges)
-{
-       int i;
-       uint32_t rlow, rhigh;
-       uint32_t base, mask;
-
-       for(i=0; i<num_ranges; i++) {
-               get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
-               if(!(rlow & MTRRMASK_VALID)) {
-                       continue;
-               }
-               mask = rlow & 0xfffff000;
-
-               get_msr(MSR_MTRRBASE(i), &rlow, &rhigh);
-               base = rlow & 0xfffff000;
-
-               if((addr & mask) == (base & mask)) {
-                       return rlow & 0xff;
-               }
-       }
-
-       get_msr(MSR_MTRRDEFTYPE, &rlow, &rhigh);
-       return rlow & 0xff;
-}
-
-static int check_wrcomb_enabled(uint32_t addr, int len, int num_ranges)
-{
-       while(len > 0) {
-               if(get_page_memtype(addr, num_ranges) != MTRR_WC) {
-                       return 0;
-               }
-               addr += 4096;
-               len -= 4096;
-       }
-       return 1;
-}
-
-static int alloc_mtrr(int num_ranges)
-{
-       int i;
-       uint32_t rlow, rhigh;
-
-       for(i=0; i<num_ranges; i++) {
-               get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
-               if(!(rlow & MTRRMASK_VALID)) {
-                       return i;
-               }
-       }
-       return -1;
-}
-
-static void enable_wrcomb(uint32_t addr, int len)
-{
-       int num_ranges, mtrr;
-       uint32_t rlow, rhigh;
-       uint32_t def, mask;
-
-       if(len <= 0 || (addr | (uint32_t)len) & 0xfff) {
-               errormsg("failed to enable write combining, unaligned range: %p/%x\n",
-                               (void*)addr, (unsigned int)len);
-               return;
-       }
-
-       get_msr(MSR_MTRRCAP, &rlow, &rhigh);
-       num_ranges = rlow & 0xff;
-
-       infomsg("enable_wrcomb: addr=%p len=%x\n", (void*)addr, (unsigned int)len);
-
-       if(!(rlow & MTRRCAP_HAVE_WC)) {
-               errormsg("failed to enable write combining, processor doesn't support it\n");
-               return;
-       }
-
-       if(check_wrcomb_enabled(addr, len, num_ranges)) {
-               return;
-       }
-
-       if((mtrr = alloc_mtrr(num_ranges)) == -1) {
-               errormsg("failed to enable write combining, no free MTRRs\n");
-               return;
-       }
-
-       mask = len - 1;
-       mask |= mask >> 1;
-       mask |= mask >> 2;
-       mask |= mask >> 4;
-       mask |= mask >> 8;
-       mask |= mask >> 16;
-       mask = ~mask & 0xfffff000;
-
-       infomsg("  ... mask: %08x\n", (unsigned int)mask);
-
-       _disable();
-       get_msr(MSR_MTRRDEFTYPE, &def, &rhigh);
-       set_msr(MSR_MTRRDEFTYPE, def & ~MTRRDEF_EN, rhigh);
-
-       set_msr(MSR_MTRRBASE(mtrr), addr | MTRR_WC, 0);
-       set_msr(MSR_MTRRMASK(mtrr), mask | MTRRMASK_VALID, 0);
-
-       set_msr(MSR_MTRRDEFTYPE, def | MTRRDEF_EN, 0);
-       _enable();
-}
-
-static const char *mtrr_names[] = { "N/A", "W C", "N/A", "N/A", "W T", "W P", "W B" };
-
-static const char *mtrr_type_name(int type)
-{
-       if(type < 0 || type >= sizeof mtrr_names / sizeof *mtrr_names) {
-               return mtrr_names[0];
-       }
-       return mtrr_names[type];
-}
-
-static void print_mtrr(void)
-{
-       int i, num_ranges;
-       uint32_t rlow, rhigh, base, mask;
-
-       get_msr(MSR_MTRRCAP, &rlow, &rhigh);
-       num_ranges = rlow & 0xff;
-
-       for(i=0; i<num_ranges; i++) {
-               get_msr(MSR_MTRRBASE(i), &base, &rhigh);
-               get_msr(MSR_MTRRMASK(i), &mask, &rhigh);
-
-               if(mask & MTRRMASK_VALID) {
-                       infomsg("mtrr%d: base %p, mask %08x type %s\n", i, (void*)(base & 0xfffff000),
-                                       (unsigned int)(mask & 0xfffff000), mtrr_type_name(base & 0xff));
-               } else {
-                       infomsg("mtrr%d unused (%08x/%08x)\n", i, (unsigned int)base,
-                                       (unsigned int)mask);
-               }
-       }
-       /*fflush(stdout);*/
-}
diff --git a/src/dos/gfx.h b/src/dos/gfx.h
deleted file mode 100644 (file)
index 0c1fe86..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef GFX_H_
-#define GFX_H_
-
-#include "sizeint.h"
-
-struct video_mode {
-       uint16_t mode;
-       short xsz, ysz, bpp, pitch;
-       short rbits, gbits, bbits;
-       short rshift, gshift, bshift;
-       uint32_t rmask, gmask, bmask;
-       uint32_t fb_addr;
-       short max_pages;
-       short win_gran, win_gran_shift, win_64k_step;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int init_video(void);
-void cleanup_video(void);
-
-struct video_mode *video_modes(void);
-int num_video_modes(void);
-
-#define VMODE_CURRENT  (-1)
-struct video_mode *get_video_mode(int idx);
-
-int match_video_mode(int xsz, int ysz, int bpp);
-int find_video_mode(int mode);
-
-/* argument is the mode list index [0, nmodes-1] */
-void *set_video_mode(int idx, int nbuf);
-int set_text_mode(void);
-
-void set_palette(int idx, int r, int g, int b);
-
-enum {
-       FLIP_NOW,
-       FLIP_VBLANK
-};
-/* page flip and return pointer to the start of the display area (front buffer) */
-void *page_flip(int vsync);
-extern void (*blit_frame)(void *pixels, int vsync);
-
-#ifdef __WATCOMC__
-void wait_vsync(void);
-#pragma aux wait_vsync = \
-       "mov dx, 0x3da" \
-       "l1:" \
-       "in al, dx" \
-       "and al, 0x8" \
-       "jnz l1" \
-       "l2:" \
-       "in al, dx" \
-       "and al, 0x8" \
-       "jz l2" \
-       modify[al dx];
-#endif
-
-#ifdef __DJGPP__
-#define wait_vsync()  asm volatile ( \
-       "mov $0x3da, %%dx\n\t" \
-       "0:\n\t" \
-       "in %%dx, %%al\n\t" \
-       "and $8, %%al\n\t" \
-       "jnz 0b\n\t" \
-       "0:\n\t" \
-       "in %%dx, %%al\n\t" \
-       "and $8, %%al\n\t" \
-       "jz 0b\n\t" \
-       :::"%eax","%edx")
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* GFX_H_ */
index 77752fb..ba70c54 100644 (file)
@@ -21,12 +21,13 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #include <time.h>
 #include "app.h"
 #include "keyb.h"
-#include "gfx.h"
+#include "vidsys.h"
 #include "cdpmi.h"
 #include "mouse.h"
 #include "logger.h"
 #include "options.h"
 #include "cpuid.h"
+#include "util.h"
 
 static INLINE int clamp(int x, int a, int b)
 {
@@ -66,14 +67,14 @@ int main(int argc, char **argv)
 
        add_log_file("retroray.log");
 
-       if(init_video() == -1) {
+       if(vid_init() == -1) {
                return 1;
        }
 
-       if((vmidx = match_video_mode(640, 480, 32)) == -1) {
+       if((vmidx = vid_findmode(640, 480, 32)) == -1) {
                return 1;
        }
-       if(!(vmem = set_video_mode(vmidx, 1))) {
+       if(!(vmem = vid_setmode(vmidx))) {
                return 1;
        }
 
@@ -142,8 +143,7 @@ int main(int argc, char **argv)
 
 break_evloop:
        app_shutdown();
-       set_text_mode();
-       cleanup_video();
+       vid_cleanup();
        kb_shutdown();
        return 0;
 }
@@ -160,7 +160,7 @@ void app_redisplay(void)
 
 void app_swap_buffers(void)
 {
-       blit_frame(framebuf, opt.vsync);
+       vid_blitfb(framebuf, opt.vsync);
 }
 
 void app_quit(void)
diff --git a/src/dos/mtrr.c b/src/dos/mtrr.c
new file mode 100644 (file)
index 0000000..81badd4
--- /dev/null
@@ -0,0 +1,149 @@
+#include "mtrr.h"
+
+#define MSR_MTRRCAP                    0xfe
+#define MSR_MTRRDEFTYPE                0x2ff
+#define MSR_MTRRBASE(x)                (0x200 | ((x) << 1))
+#define MSR_MTRRMASK(x)                (0x201 | ((x) << 1))
+#define MTRRDEF_EN                     0x800
+#define MTRRCAP_HAVE_WC                0x400
+#define MTRRMASK_VALID         0x800
+
+static const char *mtrr_type_name(int type);
+static void print_mtrr(void);
+
+
+int get_page_memtype(uint32_t addr, int num_ranges)
+{
+       int i;
+       uint32_t rlow, rhigh;
+       uint32_t base, mask;
+
+       for(i=0; i<num_ranges; i++) {
+               get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
+               if(!(rlow & MTRRMASK_VALID)) {
+                       continue;
+               }
+               mask = rlow & 0xfffff000;
+
+               get_msr(MSR_MTRRBASE(i), &rlow, &rhigh);
+               base = rlow & 0xfffff000;
+
+               if((addr & mask) == (base & mask)) {
+                       return rlow & 0xff;
+               }
+       }
+
+       get_msr(MSR_MTRRDEFTYPE, &rlow, &rhigh);
+       return rlow & 0xff;
+}
+
+int check_wrcomb_enabled(uint32_t addr, int len, int num_ranges)
+{
+       while(len > 0) {
+               if(get_page_memtype(addr, num_ranges) != MTRR_WC) {
+                       return 0;
+               }
+               addr += 4096;
+               len -= 4096;
+       }
+       return 1;
+}
+
+int alloc_mtrr(int num_ranges)
+{
+       int i;
+       uint32_t rlow, rhigh;
+
+       for(i=0; i<num_ranges; i++) {
+               get_msr(MSR_MTRRMASK(i), &rlow, &rhigh);
+               if(!(rlow & MTRRMASK_VALID)) {
+                       return i;
+               }
+       }
+       return -1;
+}
+
+void enable_wrcomb(uint32_t addr, int len)
+{
+       int num_ranges, mtrr;
+       uint32_t rlow, rhigh;
+       uint32_t def, mask;
+
+       if(len <= 0 || (addr | (uint32_t)len) & 0xfff) {
+               errormsg("failed to enable write combining, unaligned range: %p/%x\n",
+                               (void*)addr, (unsigned int)len);
+               return;
+       }
+
+       get_msr(MSR_MTRRCAP, &rlow, &rhigh);
+       num_ranges = rlow & 0xff;
+
+       infomsg("enable_wrcomb: addr=%p len=%x\n", (void*)addr, (unsigned int)len);
+
+       if(!(rlow & MTRRCAP_HAVE_WC)) {
+               errormsg("failed to enable write combining, processor doesn't support it\n");
+               return;
+       }
+
+       if(check_wrcomb_enabled(addr, len, num_ranges)) {
+               return;
+       }
+
+       if((mtrr = alloc_mtrr(num_ranges)) == -1) {
+               errormsg("failed to enable write combining, no free MTRRs\n");
+               return;
+       }
+
+       mask = len - 1;
+       mask |= mask >> 1;
+       mask |= mask >> 2;
+       mask |= mask >> 4;
+       mask |= mask >> 8;
+       mask |= mask >> 16;
+       mask = ~mask & 0xfffff000;
+
+       infomsg("  ... mask: %08x\n", (unsigned int)mask);
+
+       _disable();
+       get_msr(MSR_MTRRDEFTYPE, &def, &rhigh);
+       set_msr(MSR_MTRRDEFTYPE, def & ~MTRRDEF_EN, rhigh);
+
+       set_msr(MSR_MTRRBASE(mtrr), addr | MTRR_WC, 0);
+       set_msr(MSR_MTRRMASK(mtrr), mask | MTRRMASK_VALID, 0);
+
+       set_msr(MSR_MTRRDEFTYPE, def | MTRRDEF_EN, 0);
+       _enable();
+}
+
+static const char *mtrr_names[] = { "N/A", "W C", "N/A", "N/A", "W T", "W P", "W B" };
+
+static const char *mtrr_type_name(int type)
+{
+       if(type < 0 || type >= sizeof mtrr_names / sizeof *mtrr_names) {
+               return mtrr_names[0];
+       }
+       return mtrr_names[type];
+}
+
+static void print_mtrr(void)
+{
+       int i, num_ranges;
+       uint32_t rlow, rhigh, base, mask;
+
+       get_msr(MSR_MTRRCAP, &rlow, &rhigh);
+       num_ranges = rlow & 0xff;
+
+       for(i=0; i<num_ranges; i++) {
+               get_msr(MSR_MTRRBASE(i), &base, &rhigh);
+               get_msr(MSR_MTRRMASK(i), &mask, &rhigh);
+
+               if(mask & MTRRMASK_VALID) {
+                       infomsg("mtrr%d: base %p, mask %08x type %s\n", i, (void*)(base & 0xfffff000),
+                                       (unsigned int)(mask & 0xfffff000), mtrr_type_name(base & 0xff));
+               } else {
+                       infomsg("mtrr%d unused (%08x/%08x)\n", i, (unsigned int)base,
+                                       (unsigned int)mask);
+               }
+       }
+       /*fflush(stdout);*/
+}
diff --git a/src/dos/mtrr.h b/src/dos/mtrr.h
new file mode 100644 (file)
index 0000000..b77eb58
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef MTRR_H_
+#define MTRR_H_
+
+#define MTRR_WC                1
+
+int get_page_memtype(uint32_t addr, int num_ranges);
+int check_wrcomb_enabled(uint32_t addr, int len, int num_ranges);
+int alloc_mtrr(int num_ranges);
+void enable_wrcomb(uint32_t addr, int len);
+
+#endif /* MTRR_H_ */
diff --git a/src/dos/vbe.c b/src/dos/vbe.c
deleted file mode 100644 (file)
index 021a40f..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stddef.h>
-#include <assert.h>
-#include "vbe.h"
-#include "cdpmi.h"
-#include "logger.h"
-
-
-#define FIXPTR(ptr) \
-       do { \
-               uint32_t paddr = (uint32_t)(ptr); \
-               uint16_t pseg = paddr >> 16; \
-               uint16_t poffs = paddr & 0xffff; \
-               if(pseg == seg && poffs < 512) { \
-                       paddr = ((uint32_t)seg << 4) + poffs; \
-               } else { \
-                       paddr = ((uint32_t)pseg << 4) + poffs; \
-               } \
-               (ptr) = (void*)phys_to_virt(paddr); \
-       } while(0)
-
-/* hijack the "VESA" sig field, to pre-cache number of modes */
-#define NMODES(inf) *(uint16_t*)((inf)->sig)
-#define NACCMODES(inf) *(uint16_t*)((inf)->sig + 2)
-
-static int cur_pitch;
-/* TODO update cur_pitch on mode-change and on setscanlen */
-
-int vbe_info(struct vbe_info *info)
-{
-       void *lowbuf;
-       uint16_t seg, sel;
-       uint16_t *modeptr;
-       uint32_t offs;
-       struct dpmi_regs regs = {0};
-
-       assert(sizeof *info == 512);
-
-       if(!(seg = dpmi_alloc(sizeof *info / 16, &sel))) {
-               return -1;
-       }
-       lowbuf = (void*)phys_to_virt((uint32_t)seg << 4);
-
-       memcpy(lowbuf, "VBE2", 4);
-
-       regs.eax = 0x4f00;
-       regs.es = seg;
-       regs.edi = 0;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               errormsg("vbe_get_info (4f00) failed\n");
-               dpmi_free(sel);
-               return -1;
-       }
-
-       memcpy(info, lowbuf, sizeof *info);
-       dpmi_free(sel);
-
-       FIXPTR(info->oem_name);
-       FIXPTR(info->vendor);
-       FIXPTR(info->product);
-       FIXPTR(info->revstr);
-       FIXPTR(info->modes);
-       /* implementations without the accel capability, will use the space taken
-        * by the accel_modes pointer for other data (probably video modes). We
-        * need to check for the capability before "fixing" this pointer, otherwise
-        * we'll shuffle random data.
-        */
-       if(info->caps & VBE_ACCEL) {
-               FIXPTR(info->accel_modes);
-       }
-
-       /* info->modes should be pointing somewhere at the end of the original
-        * low memory buffer. make it point at the same offset in the info
-        * buffer where we copied everything instead.
-        */
-       offs = (char*)info->modes - (char*)lowbuf;
-       if(offs < sizeof *info) {       /* this should always be true */
-               info->modes = (uint16_t*)((char*)info + offs);
-       }
-
-       modeptr = info->modes;
-       while(*modeptr != 0xffff) {
-               if(modeptr - info->modes >= 256) {
-                       modeptr = info->modes;
-                       break;
-               }
-               modeptr++;
-       }
-       NMODES(info) = modeptr - info->modes;
-
-       if(info->caps & VBE_ACCEL) {
-               modeptr = info->accel_modes;
-               while(*modeptr != 0xffff) {
-                       if(modeptr - info->accel_modes >= 256) {
-                               modeptr = info->accel_modes;
-                               break;
-                       }
-                       modeptr++;
-               }
-               NACCMODES(info) = modeptr - info->accel_modes;
-       }
-       return 0;
-}
-
-int vbe_num_modes(struct vbe_info *info)
-{
-       return NMODES(info);
-}
-
-int vbe_mode_info(int mode, struct vbe_mode_info *minf)
-{
-       void *lowbuf;
-       uint16_t seg, sel;
-       struct dpmi_regs regs = {0};
-
-       assert(sizeof *minf == 256);
-       assert(offsetof(struct vbe_mode_info, max_pixel_clock) == 0x3e);
-
-       if(!(seg = dpmi_alloc(sizeof *minf / 16, &sel))) {
-               return -1;
-       }
-       lowbuf = (void*)phys_to_virt((uint32_t)seg << 4);
-
-       regs.eax = 0x4f01;
-       regs.ecx = mode;
-       regs.es = seg;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               errormsg("vbe_mode_info (4f01) failed\n");
-               dpmi_free(sel);
-               return -1;
-       }
-
-       memcpy(minf, lowbuf, sizeof *minf);
-       dpmi_free(sel);
-       return 0;
-}
-
-void vbe_print_info(FILE *fp, struct vbe_info *vinf)
-{
-       infomsg("vbe version: %u.%u\n", VBE_VER_MAJOR(vinf->ver), VBE_VER_MINOR(vinf->ver));
-       if(VBE_VER_MAJOR(vinf->ver) >= 2) {
-               infomsg("%s - %s (%s)\n", vinf->vendor, vinf->product, vinf->revstr);
-               if(vinf->caps & VBE_ACCEL) {
-                       infomsg("vbe/af %d.%d\n", VBE_VER_MAJOR(vinf->accel_ver), VBE_VER_MINOR(vinf->accel_ver));
-               }
-       } else {
-               infomsg("oem: %s\n", vinf->oem_name);
-       }
-       infomsg("video memory: %dkb\n", vinf->vmem_blk * 64);
-
-       if(vinf->caps) {
-               infomsg("caps:");
-               if(vinf->caps & VBE_8BIT_DAC) infomsg(" dac8");
-               if(vinf->caps & VBE_NON_VGA) infomsg(" non-vga");
-               if(vinf->caps & VBE_DAC_BLANK) infomsg(" dac-blank");
-               if(vinf->caps & VBE_ACCEL) infomsg(" af");
-               if(vinf->caps & VBE_MUSTLOCK) infomsg(" af-lock");
-               if(vinf->caps & VBE_HWCURSOR) infomsg(" af-curs");
-               if(vinf->caps & VBE_HWCLIP) infomsg(" af-clip");
-               if(vinf->caps & VBE_TRANSP_BLT) infomsg(" af-tblt");
-               infomsg("\n");
-       }
-
-       infomsg("%d video modes available\n", NMODES(vinf));
-       if(vinf->caps & VBE_ACCEL) {
-               infomsg("%d accelerated (VBE/AF) modes available\n", NACCMODES(vinf));
-       }
-       /*fflush(fp);*/
-}
-
-void vbe_print_mode_info(FILE *fp, struct vbe_mode_info *minf)
-{
-       infomsg("%dx%d %dbpp", minf->xres, minf->yres, minf->bpp);
-
-       switch(minf->mem_model) {
-       case VBE_TYPE_DIRECT:
-               infomsg(" (rgb");
-               if(0) {
-       case VBE_TYPE_YUV:
-                       infomsg(" (yuv");
-               }
-               infomsg(" %d%d%d)", minf->rsize, minf->gsize, minf->bsize);
-               break;
-       case VBE_TYPE_PLANAR:
-               infomsg(" (%d planes)", minf->num_planes);
-               break;
-       case VBE_TYPE_PACKED:
-               infomsg(" (packed)");
-               break;
-       case VBE_TYPE_TEXT:
-               infomsg(" (%dx%d cells)", minf->xcharsz, minf->ycharsz);
-               break;
-       case VBE_TYPE_CGA:
-               infomsg(" (CGA)");
-               break;
-       case VBE_TYPE_UNCHAIN:
-               infomsg(" (unchained-%d)", minf->num_planes);
-               break;
-       }
-       infomsg(" %dpg", minf->num_img_pages);
-
-       if(minf->attr & VBE_ATTR_LFB) {
-               infomsg(" lfb@%lx", (unsigned long)minf->fb_addr);
-       } else {
-               infomsg(" (%dk gran)", (int)minf->win_gran);
-       }
-
-       infomsg(" [");
-       if(minf->attr & VBE_ATTR_AVAIL) infomsg(" avail");
-       if(minf->attr & VBE_ATTR_OPTINFO) infomsg(" opt");
-       if(minf->attr & VBE_ATTR_TTY) infomsg(" tty");
-       if(minf->attr & VBE_ATTR_COLOR) infomsg(" color");
-       if(minf->attr & VBE_ATTR_GFX) infomsg(" gfx");
-       if(minf->attr & VBE_ATTR_NOTVGA) infomsg(" non-vga");
-       if(minf->attr & VBE_ATTR_BANKED) infomsg(" banked");
-       if(minf->attr & VBE_ATTR_LFB) infomsg(" lfb");
-       if(minf->attr & VBE_ATTR_DBLSCAN) infomsg(" dblscan");
-       if(minf->attr & VBE_ATTR_ILACE) infomsg(" ilace");
-       if(minf->attr & VBE_ATTR_TRIPLEBUF) infomsg(" trplbuf");
-       if(minf->attr & VBE_ATTR_STEREO) infomsg(" stereo");
-       if(minf->attr & VBE_ATTR_STEREO_2FB) infomsg(" stdual");
-       infomsg(" ]\n");
-       /*fflush(fp);*/
-}
-
-int vbe_setmode(uint16_t mode)
-{
-       struct dpmi_regs regs = {0};
-
-       regs.eax = 0x4f02;
-       regs.ebx = mode;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-
-       cur_pitch = vbe_getpitch();
-       return 0;
-}
-
-int vbe_setmode_crtc(uint16_t mode, struct vbe_crtc_info *crtc)
-{
-       void *lowbuf;
-       uint16_t seg, sel;
-       struct dpmi_regs regs = {0};
-
-       assert(sizeof *crtc == 59);
-
-       if(!(seg = dpmi_alloc((sizeof *crtc + 15) / 16, &sel))) {
-               return -1;
-       }
-       lowbuf = (void*)phys_to_virt((uint32_t)seg << 4);
-
-       memcpy(lowbuf, crtc, sizeof *crtc);
-
-       regs.eax = 0x4f02;
-       regs.ebx = mode;
-       regs.es = seg;
-       dpmi_int(0x10, &regs);
-
-       dpmi_free(sel);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-
-       cur_pitch = vbe_getpitch();
-       return 0;
-}
-
-int vbe_getmode(void)
-{
-       struct dpmi_regs regs = {0};
-
-       regs.eax = 0x4f03;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return regs.ebx & 0xffff;
-}
-
-int vbe_state_size(unsigned int flags)
-{
-       struct dpmi_regs regs = {0};
-
-       regs.eax = 0x4f04;
-       regs.edx = 0;
-       regs.ecx = flags;
-       dpmi_int(0x10, &regs);
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return (regs.ebx & 0xffff) * 64;
-}
-
-int vbe_save(void *stbuf, int sz, unsigned int flags)
-{
-       void *lowbuf;
-       uint16_t seg, sel;
-       struct dpmi_regs regs = {0};
-
-       if(!(seg = dpmi_alloc((sz + 15) / 16, &sel))) {
-               return -1;
-       }
-       lowbuf = (void*)phys_to_virt((uint32_t)seg << 4);
-
-       regs.eax = 0x4f04;
-       regs.edx = 1;   /* save */
-       regs.ecx = flags;
-       regs.es = seg;
-       dpmi_int(0x10, &regs);
-       if((regs.eax & 0xffff) != 0x4f) {
-               dpmi_free(sel);
-               return -1;
-       }
-
-       memcpy(stbuf, lowbuf, sz);
-       dpmi_free(sel);
-       return 0;
-}
-
-int vbe_restore(void *stbuf, int sz, unsigned int flags)
-{
-       void *lowbuf;
-       uint16_t seg, sel;
-       struct dpmi_regs regs = {0};
-
-       if(!(seg = dpmi_alloc((sz + 15) / 16, &sel))) {
-               return -1;
-       }
-       lowbuf = (void*)phys_to_virt((uint32_t)seg << 4);
-
-       memcpy(lowbuf, stbuf, sz);
-
-       regs.eax = 0x4f04;
-       regs.edx = 2;   /* restore */
-       regs.ecx = flags;
-       regs.es = seg;
-       dpmi_int(0x10, &regs);
-       dpmi_free(sel);
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return 0;
-}
-
-int vbe_setwin(int wid, int pos)
-{
-       struct dpmi_regs regs;
-
-       if(wid & ~1) return -1;
-
-       regs.eax = 0x4f05;
-       regs.ebx = wid;
-       regs.edx = pos;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return 0;
-}
-
-int vbe_getwin(int wid)
-{
-       struct dpmi_regs regs;
-
-       if(wid & ~1) return -1;
-
-       regs.eax = 0x4f05;
-       regs.ebx = wid;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-
-       return regs.edx & 0xffff;
-}
-
-int vbe_setscanlen(int len_pix)
-{
-       struct dpmi_regs regs;
-
-       regs.eax = 0x4f06;
-       regs.ebx = 0;   /* set scanline length in pixels */
-       regs.ecx = len_pix;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-
-       cur_pitch = vbe_getpitch();
-       return regs.ecx;
-}
-
-int vbe_getscanlen(void)
-{
-       struct dpmi_regs regs;
-
-       regs.eax = 0x4f06;
-       regs.ebx = 1;   /* get scanline length */
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return regs.ecx;
-}
-
-int vbe_getpitch(void)
-{
-       struct dpmi_regs regs;
-
-       regs.eax = 0x4f06;
-       regs.ebx = 1;   /* get scanline length */
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return regs.ebx;
-}
-
-int vbe_scanline_info(struct vbe_scanline_info *sinf)
-{
-       struct dpmi_regs regs;
-
-       regs.eax = 0x4f06;
-       regs.ebx = 1;   /* get scanline length */
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-
-       sinf->size = regs.ebx & 0xffff;
-       sinf->num_pixels = regs.ecx & 0xffff;
-       sinf->max_scanlines = regs.edx & 0xffff;
-       return 0;
-}
-
-enum {
-       SDISP_SET                       = 0x00,
-       SDISP_GET                       = 0x01,
-       SDISP_ALTSET            = 0x02,
-       SDISP_SET_STEREO        = 0x03,
-       SDISP_GETSCHED          = 0x04,
-       SDISP_STEREO_ON         = 0x05,
-       SDISP_STEREO_OFF        = 0x06,
-       SDISP_SET_VBLANK        = 0x80,
-       SDISP_ALTSET_VBLANK     = 0x82,
-       SDISP_SET_STEREO_VBLANK = 0x83
-};
-
-int vbe_setdisp(int x, int y, int when)
-{
-       struct dpmi_regs regs;
-
-       regs.eax = 0x4f07;
-       regs.ebx = (when == VBE_SWAP_VBLANK) ? SDISP_SET_VBLANK : SDISP_SET;
-       regs.ecx = x;
-       regs.edx = y;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return 0;
-}
-
-int vbe_swap(uint32_t voffs, int when)
-{
-       struct dpmi_regs regs;
-       int op;
-
-       switch(when) {
-       case VBE_SWAP_ASYNC:
-               op = SDISP_ALTSET;
-               break;
-
-       case VBE_SWAP_NOW:
-               /* XXX is this the only way? */
-               return vbe_setdisp(voffs % cur_pitch, voffs / cur_pitch, when);
-
-       case VBE_SWAP_VBLANK:
-       default:
-               op = SDISP_ALTSET_VBLANK;
-               break;
-       }
-
-
-       regs.eax = 0x4f07;
-       regs.ebx = op;
-       regs.ecx = voffs;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return -1;
-       }
-       return 0;
-}
-
-int vbe_swap_pending(void)
-{
-       struct dpmi_regs regs;
-
-       regs.eax = 0x4f07;
-       regs.ebx = SDISP_GETSCHED;
-       dpmi_int(0x10, &regs);
-
-       if((regs.eax & 0xffff) != 0x4f) {
-               return 0;
-       }
-       return regs.ecx;
-}
index 4193d68..42417af 100644 (file)
@@ -3,7 +3,6 @@
 
 #include <stdio.h>
 #include "sizeint.h"
-#include "util.h"
 
 #pragma pack (push, 1)
 struct vbe_info {
@@ -11,7 +10,7 @@ struct vbe_info {
        uint16_t ver;
        char *oem_name;
        uint32_t caps;
-       uint16_t *modes;
+       uint32_t modelist_addr;
        uint16_t vmem_blk;      /* video memory size in 64k blocks */
        uint16_t oem_ver;
        char *vendor;
@@ -21,7 +20,7 @@ struct vbe_info {
        uint16_t *accel_modes;
        char reserved[216];
        char oem_data[256];
-} PACKED;
+};
 
 struct vbe_mode_info {
        uint16_t attr;
@@ -65,7 +64,7 @@ struct vbe_mode_info {
        uint32_t max_pixel_clock;
 
        char reserved2[190];
-} PACKED;
+};
 
 struct vbe_crtc_info {
        uint16_t htotal, hsync_start, hsync_end;
@@ -74,7 +73,7 @@ struct vbe_crtc_info {
        uint32_t pixel_clock;
        uint16_t rate_centihz;  /* refresh rate in 1/100 hz (pck / (htotal * vtotal)) */
        char reserved[40];
-} PACKED;
+};
 #pragma pack (pop)
 
 /* returned by vbe_scanline_info() */
diff --git a/src/dos/vga.c b/src/dos/vga.c
deleted file mode 100644 (file)
index f2f8142..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <string.h>
-#include "vga.h"
-#include "vgaregs.h"
-#include "cdpmi.h"
-#include "dosutil.h"
-
-static void crtc_write(int reg, unsigned char val);
-static unsigned char crtc_read(int reg);
-
-int vga_setmode(int mode)
-{
-       struct dpmi_regs regs = {0};
-
-       regs.eax = mode;        /* func 00 | mode */
-       dpmi_int(0x10, &regs);
-       return 0;
-}
-
-static unsigned short crtc_modex_regs[] = {
-       0x0d06, /* vertical total */
-       0x3e07, /* vcount overflow bit */
-       0x4109, /* double-scan */
-       0xea10, /* vsync start */
-       0xac11, /* vsync end & protect */
-       0xdf12, /* vertical visible */
-       0x0014, /* no dword mode */
-       0xe715, /* vblank start */
-       0x0616, /* vblank end */
-       0xe317, /* byte mode */
-       0
-};
-
-int vga_setmodex(void)
-{
-       int i;
-       unsigned char val;
-
-       vga_setmode(0x13);
-
-       /* disable chain-4 (C4=0, O/E=1 (sequential), EM=1 (extmem), A/G=0 (gfx) */
-       outpw(VGA_SC_ADDR_PORT, VGA_SC_MEMMODE_REG | 0x0600);
-       /* pull reset low */
-       outpw(VGA_SC_ADDR_PORT, VGA_SC_RESET_REG | 0x0100);
-       /* 25mhz dot clock, 60hz scan */
-       outp(VGA_MISC_PORT, VGA_MISC_480 | VGA_MISC_PG1 | VGA_MISC_CLK25 |
-                       VGA_MISC_CPUEN | VGA_MISC_COLOR);
-       /* return reset high */
-       outpw(VGA_SC_ADDR_PORT, VGA_SC_RESET_REG | 0x0300);
-
-       /* disable CRTC write-protect */
-       crtc_write(CRTC_VRETEND_REG, crtc_read(CRTC_VRETEND_REG) & ~CRTC_VRETEND_PR);
-       /* change CRTC registers */
-       for(i=0; crtc_modex_regs[i]; i++) {
-               outpw(VGA_CRTC_PORT, crtc_modex_regs[i]);
-       }
-
-       vga_planemask(0xf);
-       memset(VGA_FBADDR, 3, 320 * 240 / 4);
-       return 0;
-}
-
-static void crtc_write(int reg, unsigned char val)
-{
-       outpw(VGA_CRTC_ADDR_PORT, reg | ((unsigned int)val << 8));
-}
-
-static unsigned char crtc_read(int reg)
-{
-       outp(VGA_CRTC_ADDR_PORT, reg);
-       return inp(VGA_CRTC_DATA_PORT);
-}
index 59d22ef..c15fe17 100644 (file)
@@ -1,49 +1,93 @@
 #ifndef VGA_H_
 #define VGA_H_
 
-#include "sizeint.h"
-#include "dosutil.h"
-#include "cdpmi.h"
-#include "vgaregs.h"
-
-#define VGA_FBADDR     ((void*)phys_to_virt(0xa0000))
-
-int vga_setmode(int mode);
-int vga_setmodex(void);
-
-#define vga_planemask(mask)            vga_sc_write(VGA_SC_MAPMASK_REG, mask)
-
-#ifdef __WATCOMC__
-void vga_setpal(int16_t idx, uint8_t r, uint8_t g, uint8_t b);
-#pragma aux vga_setpal = \
-       "test ax, 0x8000" \
-       "jnz skip_dacaddr" \
-       "mov dx, 0x3c8" \
-       "out dx, al" \
-       "skip_dacaddr:" \
-       "mov dx, 0x3c9" \
-       "mov al, bl" \
-       "shr al, 2" \
-       "out dx, al" \
-       "mov al, bh" \
-       "shr al, 2" \
-       "out dx, al" \
-       "mov al, cl" \
-       "shr al, 2" \
-       "out dx, al" \
-       parm[ax][bl][bh][cl] \
-       modify[dx];
-#endif /* __WATCOMC__ */
-
-#define vga_sc_write(reg, data) \
-       outpw(VGA_SC_ADDR_PORT, (uint16_t)(reg) | ((uint16_t)(data) << 8))
-#define vga_sc_read(reg) \
-       (outp(VGA_SC_ADDR_PORT, reg), inp(VGA_SC_DATA_PORT))
-#define vga_crtc_write(reg, data) \
-       outpw(VGA_CRTC_PORT, (uint16_t)(reg) | ((uint16_t)(data) << 8))
-#define vga_crtc_read(reg) \
-       (outp(VGA_CRTC_ADDR_PORT, reg), inp(VGA_CRTC_DATA_PORT))
-#define vga_crtc_wrmask(reg, data, mask) \
-       outp(VGA_CRTC_DATA_PORT, (crtc_read(reg) & ~(mask)) | (data))
+/* ---- VGA registers ---- */
+#define VGA_AC_PORT            0x3c0
+#define VGA_AC_RD_PORT         0x3c1
+#define VGA_SC_ADDR_PORT       0x3c4
+#define VGA_SC_DATA_PORT       0x3c5
+#define VGA_DAC_STATUS_PORT    0x3c7
+#define VGA_DAC_RADDR_PORT     0x3c7
+#define VGA_DAC_WADDR_PORT     0x3c8
+#define VGA_DAC_DATA_PORT      0x3c9
+#define VGA_GC_ADDR_PORT       0x3ce
+#define VGA_GC_DATA_PORT       0x3cf
+#define VGA_CRTC_PORT          0x3d4
+#define VGA_CRTC_ADDR_PORT     0x3d4
+#define VGA_CRTC_DATA_PORT     0x3d5
+#define VGA_STAT0_PORT         0x3c2
+#define VGA_STAT1_PORT         0x3da
+#define VGA_MISC_PORT          0x3c2
+#define VGA_MISC_RD_PORT       0x3cc
+
+/* attribute controller registers */
+#define VGA_AC_EN              0x20
+#define VGA_AC_MODE_REG                0x10
+
+/* sequence controller registers */
+#define VGA_SC_RESET_REG       0x00
+#define VGA_SC_CLOCK_REG       0x01
+#define VGA_SC_MAPMASK_REG     0x02
+#define VGA_SC_MEMMODE_REG     0x04
+
+/* graphics controller registers */
+#define VGA_GC_SR_REG          0x00
+#define VGA_GC_SREN_REG                0x01
+#define VGA_GC_ROT_REG         0x03
+#define VGA_GC_MODE_REG                0x05
+#define VGA_GC_MASK_REG                0x08
+
+/* attribute controller mode register (10h) bits */
+#define VGA_AC_MODE_GFX                0x01
+#define VGA_AC_MODE_MONO       0x02
+#define VGA_AC_MODE_LGE                0x04
+#define VGA_AC_MODE_BLINK      0x08
+#define VGA_AC_MODE_PIXPAN     0x20
+#define VGA_AC_MODE_8BIT       0x40
+
+/* misc register bits */
+#define VGA_MISC_COLOR         0x01
+#define VGA_MISC_CPUEN         0x02
+#define VGA_MISC_CLK25         0
+#define VGA_MISC_CLK28         0x04
+#define VGA_MISC_PG1           0x20
+#define VGA_MISC_400           0
+#define VGA_MISC_350           0x40
+#define VGA_MISC_480           0xc0
+
+
+/* CRTC registers */
+#define CRTC_HTOTAL_REG                0x00
+#define CRTC_HEND_REG          0x01
+#define CRTC_HBLSTART_REG      0x02
+#define CRTC_HBLEND_REG                0x03
+#define CRTC_HRETSTART_REG     0x04
+#define CRTC_HRETEND_REG       0x05
+#define CRTC_VTOTAL_REG                0x06
+#define CRTC_OVF_REG           0x07
+#define CRTC_PRESET_REG                0x08
+#define CRTC_MAXSCAN_REG       0x09
+#define CRTC_CURSTART_REG      0x0a
+#define CRTC_CUREND_REG                0x0b
+#define CRTC_STARTH_REG                0x0c
+#define CRTC_STARTL_REG                0x0d
+#define CRTC_CURH_REG          0x0e
+#define CRTC_CURL_REG          0x0f
+#define CRTC_VRETSTART_REG     0x10
+#define CRTC_VRETEND_REG       0x11
+#define CRTC_VEND_REG          0x12
+#define CRTC_OFFSET_REG                0x13
+#define CRTC_UL_REG            0x14
+#define CRTC_VBLSTART_REG      0x15
+#define CRTC_VBLEND_REG                0x16
+#define CRTC_MODE_REG          0x17
+#define CRTC_LCMP_REG          0x18
+
+/* CRTC register bits */
+#define CRTC_VRETEND_PR                0x80
+
+void vga_vsync(void);
+void vga_setpal(int idx, int count, const struct vid_color *col);
+void vga_getpal(int idx, int count, struct vid_color *col);
 
 #endif /* VGA_H_ */
diff --git a/src/dos/vgaregs.h b/src/dos/vgaregs.h
deleted file mode 100644 (file)
index 15c4090..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef VGAREGS_H_
-#define VGAREGS_H_
-
-/* ---- VGA registers ---- */
-#define VGA_AC_PORT            0x3c0
-#define VGA_AC_RD_PORT         0x3c1
-#define VGA_SC_ADDR_PORT       0x3c4
-#define VGA_SC_DATA_PORT       0x3c5
-#define VGA_GC_ADDR_PORT       0x3ce
-#define VGA_GC_DATA_PORT       0x3cf
-#define VGA_CRTC_PORT          0x3d4
-#define VGA_CRTC_ADDR_PORT     0x3d4
-#define VGA_CRTC_DATA_PORT     0x3d5
-#define VGA_STAT0_PORT         0x3c2
-#define VGA_STAT1_PORT         0x3da
-#define VGA_MISC_PORT          0x3c2
-#define VGA_MISC_RD_PORT       0x3cc
-
-/* attribute controller registers */
-#define VGA_AC_EN              0x20
-#define VGA_AC_MODE_REG                0x10
-
-/* sequence controller registers */
-#define VGA_SC_RESET_REG       0x00
-#define VGA_SC_CLOCK_REG       0x01
-#define VGA_SC_MAPMASK_REG     0x02
-#define VGA_SC_MEMMODE_REG     0x04
-
-/* graphics controller registers */
-#define VGA_GC_SR_REG          0x00
-#define VGA_GC_SREN_REG                0x01
-#define VGA_GC_ROT_REG         0x03
-#define VGA_GC_MODE_REG                0x05
-#define VGA_GC_MASK_REG                0x08
-
-/* attribute controller mode register (10h) bits */
-#define VGA_AC_MODE_GFX                0x01
-#define VGA_AC_MODE_MONO       0x02
-#define VGA_AC_MODE_LGE                0x04
-#define VGA_AC_MODE_BLINK      0x08
-#define VGA_AC_MODE_PIXPAN     0x20
-#define VGA_AC_MODE_8BIT       0x40
-
-/* misc register bits */
-#define VGA_MISC_COLOR         0x01
-#define VGA_MISC_CPUEN         0x02
-#define VGA_MISC_CLK25         0
-#define VGA_MISC_CLK28         0x04
-#define VGA_MISC_PG1           0x20
-#define VGA_MISC_400           0
-#define VGA_MISC_350           0x40
-#define VGA_MISC_480           0xc0
-
-
-/* CRTC registers */
-#define CRTC_HTOTAL_REG                0x00
-#define CRTC_HEND_REG          0x01
-#define CRTC_HBLSTART_REG      0x02
-#define CRTC_HBLEND_REG                0x03
-#define CRTC_HRETSTART_REG     0x04
-#define CRTC_HRETEND_REG       0x05
-#define CRTC_VTOTAL_REG                0x06
-#define CRTC_OVF_REG           0x07
-#define CRTC_PRESET_REG                0x08
-#define CRTC_MAXSCAN_REG       0x09
-#define CRTC_CURSTART_REG      0x0a
-#define CRTC_CUREND_REG                0x0b
-#define CRTC_STARTH_REG                0x0c
-#define CRTC_STARTL_REG                0x0d
-#define CRTC_CURH_REG          0x0e
-#define CRTC_CURL_REG          0x0f
-#define CRTC_VRETSTART_REG     0x10
-#define CRTC_VRETEND_REG       0x11
-#define CRTC_VEND_REG          0x12
-#define CRTC_OFFSET_REG                0x13
-#define CRTC_UL_REG            0x14
-#define CRTC_VBLSTART_REG      0x15
-#define CRTC_VBLEND_REG                0x16
-#define CRTC_MODE_REG          0x17
-#define CRTC_LCMP_REG          0x18
-
-/* CRTC register bits */
-#define CRTC_VRETEND_PR                0x80
-
-#endif /* VGAREGS_H_ */
diff --git a/src/dos/vidsys.c b/src/dos/vidsys.c
new file mode 100644 (file)
index 0000000..427dbb5
--- /dev/null
@@ -0,0 +1,201 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include "vidsys.h"
+#include "vga.h"
+#include "drv.h"
+#include "cdpmi.h"
+
+struct vid_driver *vid_drvlist[MAX_DRV];
+int vid_numdrv;
+
+void *vid_vmem;
+int vid_vmem_size;
+
+static struct vid_modeinfo **modes, *cur_mode;
+static int num_modes, max_modes;
+
+
+int vid_init(void)
+{
+       int i, j, len;
+       struct vid_modeinfo *vm;
+
+       vid_numdrv = 0;
+       free(modes);
+       modes = 0;
+       cur_mode = 0;
+       num_modes = max_modes = 0;
+
+       vid_vmem = 0;
+       vid_vmem_size = 0;
+
+       if(dpmi_init() == -1) {
+               return -1;
+       }
+
+       vid_register_vga();
+       vid_register_vbe();
+       vid_register_s3();
+
+       for(i=0; i<vid_numdrv; i++) {
+               struct vid_driver *drv = vid_drvlist[i];
+
+               drv->ops->init();
+
+               for(j=0; j<drv->num_modes; j++) {
+                       if(num_modes >= max_modes) {
+                               int newsz = max_modes ? max_modes * 2 : 128;
+                               void *tmp = realloc(modes, newsz * sizeof *modes);
+                               if(!tmp) {
+                                       fprintf(stderr, "failed to allocate modes list\n");
+                                       return -1;
+                               }
+                               modes = tmp;
+                               max_modes = newsz;
+                       }
+
+                       modes[num_modes++] = drv->modes + j;
+               }
+       }
+
+       printf("found %d modes:\n", num_modes);
+       for(i=0; i<num_modes; i+=2) {
+               vm = modes[i];
+               len = printf("[%4s] %04x: %dx%d %dbpp", vm->drv->name, vm->modeno,
+                               vm->width, vm->height, vm->bpp);
+               if(i + 1 >= num_modes) {
+                       putchar('\n');
+                       break;
+               }
+               for(j=len; j<40; j++) putchar(' ');
+               vm = modes[i + 1];
+               printf("[%4s] %04x: %dx%d %dbpp\n", vm->drv->name, vm->modeno,
+                               vm->width, vm->height, vm->bpp);
+       }
+
+       return 0;
+}
+
+void vid_cleanup(void)
+{
+       int i;
+
+       if(cur_mode && cur_mode->modeno != 3) {
+               vid_setmode(3);
+       }
+
+       if(vid_vmem >= (void*)0x100000) {
+               dpmi_munmap(vid_vmem);
+       }
+
+       for(i=0; i<vid_numdrv; i++) {
+               struct vid_driver *drv = vid_drvlist[i];
+               drv->ops->cleanup();
+       }
+
+       free(modes);
+       dpmi_cleanup();
+}
+
+
+int vid_curmode(void)
+{
+       if(cur_mode) {
+               return cur_mode->modeno;
+       }
+       return -1;
+}
+
+void *vid_setmode(int mode)
+{
+       int i;
+       struct vid_driver *drv;
+
+       for(i=0; i<num_modes; i++) {
+               if(modes[i]->modeno == mode) {
+                       drv = modes[i]->drv;
+                       if(drv->ops->setmode(mode) == 0) {
+                               cur_mode = modes[i];
+
+                               if(vid_vmem >= (void*)0x100000) {
+                                       assert(vid_vmem_size);
+                                       dpmi_munmap(vid_vmem);
+                               }
+
+                               if(modes[i]->vmem_addr < 0x100000) {
+                                       vid_vmem = (void*)modes[i]->vmem_addr;
+                                       vid_vmem_size = 0;
+                               } else {
+                                       vid_vmem = dpmi_mmap(modes[i]->vmem_addr, modes[i]->vmem_size);
+                                       vid_vmem_size = modes[i]->vmem_size;
+                               }
+                               return vid_vmem;
+                       }
+               }
+       }
+       return 0;
+}
+
+#define EQUIV_BPP(a, b)        \
+       ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
+        ((a) == 24 && (b) == 32) || ((a) == 32 && (b) == 24))
+
+int vid_findmode(int xsz, int ysz, int bpp)
+{
+       int i;
+
+       for(i=0; i<num_modes; i++) {
+               if(modes[i]->width == xsz && modes[i]->height == ysz && modes[i]->bpp == bpp) {
+                       return modes[i]->modeno;
+               }
+       }
+
+       /* try fuzzy bpp matching */
+       for(i=0; i<num_modes; i++) {
+               if(modes[i]->width == xsz && modes[i]->height == ysz &&
+                               EQUIV_BPP(modes[i]->bpp, bpp)) {
+                       return modes[i]->modeno;
+               }
+       }
+
+       return -1;
+}
+
+
+struct vid_modeinfo *vid_modeinfo(int mode)
+{
+       int i;
+
+       for(i=0; i<num_modes; i++) {
+               if(modes[i]->modeno == mode) {
+                       return modes[i];
+               }
+       }
+       return 0;
+}
+
+int vid_islinear(void)
+{
+       return !vid_isbanked();
+}
+
+int vid_isbanked(void)
+{
+       return cur_mode->win_size && vid_vmem < (void*)0x100000;
+}
+
+void vid_setpal(int idx, int count, const struct vid_color *col)
+{
+       cur_mode->ops.setpal(idx, count, col);
+}
+
+void vid_getpal(int idx, int count, struct vid_color *col)
+{
+       cur_mode->ops.getpal(idx, count, col);
+}
+
+void vid_blitfb(void *fb, int vsync)
+{
+       cur_mode->ops.blitfb(fb, vsync);
+}
diff --git a/src/dos/vidsys.h b/src/dos/vidsys.h
new file mode 100644 (file)
index 0000000..cd2cfec
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef VIDSYS_VIDEO_H_
+#define VIDSYS_VIDEO_H_
+
+#include <stdlib.h>
+#include "sizeint.h"
+
+struct vid_drvops;
+
+struct vid_color {
+       int r, g, b;
+};
+
+struct vid_gfxops {
+       void (*pack)(uint32_t *pix, int r, int g, int b);
+       void (*unpack)(uint32_t pix, int *r, int *g, int *b);
+       void (*setpal)(int idx, int count, const struct vid_color *col);
+       void (*getpal)(int idx, int count, struct vid_color *col);
+       void (*vsync)(void);
+
+       void (*clear)(uint32_t color);
+       void (*blitfb)(void *fb, int pitch);
+       void (*flip)(int vsync);
+
+       void (*fill)(int x, int y, int w, int h, uint32_t color);
+       void (*blit)(int x, int y, int w, int h, void *img, int pitch);
+       void (*line)(int x0, int y0, int x1, int y1, uint32_t color);
+       void (*hline)(int x, int y, int len, uint32_t color);
+       void (*vline)(int x, int y, int len, uint32_t color);
+};
+
+struct vid_driver {
+       const char *name;
+       int prio;
+
+       struct vid_modeinfo *modes;
+       int num_modes;
+
+       struct vid_drvops *ops;
+};
+
+struct vid_modeinfo {
+       int modeno;
+       int width, height, bpp, pitch;
+       int ncolors;
+       uint32_t rmask, gmask, bmask;
+       int rshift, gshift, bshift;
+       int pages;
+       int win_size, win_gran, win_step;
+       uint32_t vmem_addr;
+       size_t vmem_size;
+       int lfb;
+
+       struct vid_driver *drv;
+       struct vid_gfxops ops;
+};
+
+int vid_init(void);
+void vid_cleanup(void);
+
+int vid_curmode(void);
+void *vid_setmode(int mode);
+int vid_findmode(int xsz, int ysz, int bpp);
+struct vid_modeinfo *vid_modeinfo(int mode);
+
+void vid_vsync(void);                          /* defined in drv_vga.c */
+int vid_setwin(int win, int pos);      /* defined in drv_vbe.c */
+
+/* current mode functions */
+int vid_islinear(void);
+int vid_isbanked(void);
+
+void vid_setpal(int idx, int count, const struct vid_color *col);
+void vid_getpal(int idx, int count, struct vid_color *col);
+
+void vid_blitfb(void *fb, int vsync);
+
+#endif /* VIDSYS_VIDEO_H_ */
diff --git a/src/dos/watdpmi.c b/src/dos/watdpmi.c
deleted file mode 100644 (file)
index 04d7b94..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifdef __WATCOMC__
-#include "cdpmi.h"
-
-void dpmi_real_int(int inum, struct dpmi_real_regs *regs)
-{
-       unsigned char int_num = (unsigned char)inum;
-       __asm {
-               mov eax, 0x300
-               mov edi, regs
-               mov bl, int_num
-               mov bh, 0
-               xor ecx, ecx
-               int 0x31
-       }
-}
-
-void *dpmi_mmap(uint32_t phys_addr, unsigned int size)
-{
-       uint16_t mem_high, mem_low;
-       uint16_t phys_high = phys_addr >> 16;
-       uint16_t phys_low = phys_addr & 0xffff;
-       uint16_t size_high = size >> 16;
-       uint16_t size_low = size & 0xffff;
-       unsigned int err, res = 0;
-
-       __asm {
-               mov eax, 0x800
-               mov bx, phys_high
-               mov cx, phys_low
-               mov si, size_high
-               mov di, size_low
-               int 0x31
-               add res, 1
-               mov err, eax
-               mov mem_high, bx
-               mov mem_low, cx
-       }
-
-       if(res == 2) {
-               return 0;
-       }
-       return (void*)(((uint32_t)mem_high << 16) | ((uint32_t)mem_low));
-}
-
-void dpmi_munmap(void *addr)
-{
-       uint16_t mem_high = (uint32_t)addr >> 16;
-       uint16_t mem_low = (uint16_t)addr;
-
-       __asm {
-               mov eax, 0x801
-               mov bx, mem_high
-               mov cx, mem_low
-               int 0x31
-       }
-}
-#else
-int stop_gcc_crying_about_empty_translation_units = 0;
-#endif /* __WATCOM__ */