!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 &
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 &
--- /dev/null
+#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, ®s, ®s);
+ 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, ®s, ®s);
+}
+
+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, ®s, ®s, &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, ®s, ®s);
+ 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, ®s, ®s);
+}
-#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 {
uint16_t flags;
uint16_t es, ds, fs, gs;
uint16_t ip, cs, sp, ss;
-} PACKED;
+};
#pragma pack (pop)
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_ */
+++ /dev/null
-#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__ */
--- /dev/null
+#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_ */
--- /dev/null
+
+#include <conio.h>
+#include <i86.h>
+#include "drv.h"
+
+void vid_register_s3(void)
+{
+}
--- /dev/null
+#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, ®s);
+ 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, ®s);
+
+ 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, ®s);
+ 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, ®s);
+ 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 */
+}
--- /dev/null
+#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, ®s, ®s);
+ return 0;
+}
+
+static int curmode(void)
+{
+ union REGS regs = {0};
+ regs.w.ax = 0xf00;
+ int386(0x10, ®s, ®s);
+ 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;
+ }
+}
+++ /dev/null
-#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);*/
-}
+++ /dev/null
-#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_ */
#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)
{
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;
}
break_evloop:
app_shutdown();
- set_text_mode();
- cleanup_video();
+ vid_cleanup();
kb_shutdown();
return 0;
}
void app_swap_buffers(void)
{
- blit_frame(framebuf, opt.vsync);
+ vid_blitfb(framebuf, opt.vsync);
}
void app_quit(void)
--- /dev/null
+#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);*/
+}
--- /dev/null
+#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_ */
+++ /dev/null
-#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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
- 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, ®s);
- 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, ®s);
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- 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, ®s);
-
- if((regs.eax & 0xffff) != 0x4f) {
- return 0;
- }
- return regs.ecx;
-}
#include <stdio.h>
#include "sizeint.h"
-#include "util.h"
#pragma pack (push, 1)
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;
uint16_t *accel_modes;
char reserved[216];
char oem_data[256];
-} PACKED;
+};
struct vbe_mode_info {
uint16_t attr;
uint32_t max_pixel_clock;
char reserved2[190];
-} PACKED;
+};
struct vbe_crtc_info {
uint16_t htotal, hsync_start, hsync_end;
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() */
+++ /dev/null
-#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, ®s);
- 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);
-}
#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_ */
+++ /dev/null
-#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_ */
--- /dev/null
+#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);
+}
--- /dev/null
+#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_ */
+++ /dev/null
-#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__ */