From 4e4ac855a9d53fd7dee3d640f3ab46740b991b5c Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 26 Jun 2023 19:56:12 +0300 Subject: [PATCH] switched to vidsys (not working yet) --- Makefile | 8 +- src/dos/cdpmi.c | 102 +++++++++++ src/dos/cdpmi.h | 86 +-------- src/dos/djdpmi.c | 35 ---- src/dos/drv.h | 25 +++ src/dos/drv_s3.c | 8 + src/dos/drv_vbe.c | 379 ++++++++++++++++++++++++++++++++++++++ src/dos/drv_vga.c | 172 ++++++++++++++++++ src/dos/gfx.c | 496 -------------------------------------------------- src/dos/gfx.h | 81 --------- src/dos/main.c | 14 +- src/dos/mtrr.c | 149 +++++++++++++++ src/dos/mtrr.h | 11 ++ src/dos/vbe.c | 525 ----------------------------------------------------- src/dos/vbe.h | 9 +- src/dos/vga.c | 71 -------- src/dos/vga.h | 132 +++++++++----- src/dos/vgaregs.h | 85 --------- src/dos/vidsys.c | 201 ++++++++++++++++++++ src/dos/vidsys.h | 77 ++++++++ src/dos/watdpmi.c | 59 ------ 21 files changed, 1237 insertions(+), 1488 deletions(-) create mode 100644 src/dos/cdpmi.c delete mode 100644 src/dos/djdpmi.c create mode 100644 src/dos/drv.h create mode 100644 src/dos/drv_s3.c create mode 100644 src/dos/drv_vbe.c create mode 100644 src/dos/drv_vga.c delete mode 100644 src/dos/gfx.c delete mode 100644 src/dos/gfx.h create mode 100644 src/dos/mtrr.c create mode 100644 src/dos/mtrr.h delete mode 100644 src/dos/vbe.c delete mode 100644 src/dos/vga.c delete mode 100644 src/dos/vgaregs.h create mode 100644 src/dos/vidsys.c create mode 100644 src/dos/vidsys.h delete mode 100644 src/dos/watdpmi.c diff --git a/Makefile b/Makefile index db0fa4d..ada31b2 100644 --- 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 index 0000000..62e877a --- /dev/null +++ b/src/dos/cdpmi.c @@ -0,0 +1,102 @@ +#include +#include +#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); +} diff --git a/src/dos/cdpmi.h b/src/dos/cdpmi.h index 96baf40..751f2d2 100644 --- a/src/dos/cdpmi.h +++ b/src/dos/cdpmi.h @@ -1,22 +1,8 @@ -#ifndef DPMI_H_ -#define DPMI_H_ - -#ifdef __DJGPP__ -#include -#include - -#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 #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 index f3a06b9..0000000 --- a/src/dos/djdpmi.c +++ /dev/null @@ -1,35 +0,0 @@ -#ifdef __DJGPP__ -#include -#include -#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 index 0000000..172f146 --- /dev/null +++ b/src/dos/drv.h @@ -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 index 0000000..02287a4 --- /dev/null +++ b/src/dos/drv_s3.c @@ -0,0 +1,8 @@ + +#include +#include +#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 index 0000000..d639417 --- /dev/null +++ b/src/dos/drv_vbe.c @@ -0,0 +1,379 @@ +#include +#include +#include +#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; ilfb) { + 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; irshift) & 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; iheight; 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 index 0000000..f6b7b01 --- /dev/null +++ b/src/dos/drv_vga.c @@ -0,0 +1,172 @@ +#include +#include +#include +#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; ir >> 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; ir = 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 -#include -#include -#include -#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= 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; ixsz != 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; imode == 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 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> 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. #include #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 index 0000000..81badd4 --- /dev/null +++ b/src/dos/mtrr.c @@ -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 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> 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 -#include -#include -#include -#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; -} diff --git a/src/dos/vbe.h b/src/dos/vbe.h index 4193d68..42417af 100644 --- a/src/dos/vbe.h +++ b/src/dos/vbe.h @@ -3,7 +3,6 @@ #include #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 index f2f8142..0000000 --- a/src/dos/vga.c +++ /dev/null @@ -1,71 +0,0 @@ -#include -#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); -} diff --git a/src/dos/vga.h b/src/dos/vga.h index 59d22ef..c15fe17 100644 --- a/src/dos/vga.h +++ b/src/dos/vga.h @@ -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 index 15c4090..0000000 --- a/src/dos/vgaregs.h +++ /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 index 0000000..427dbb5 --- /dev/null +++ b/src/dos/vidsys.c @@ -0,0 +1,201 @@ +#include +#include +#include +#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; iops->init(); + + for(j=0; jnum_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; idrv->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; iops->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; imodeno == 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; iwidth == xsz && modes[i]->height == ysz && modes[i]->bpp == bpp) { + return modes[i]->modeno; + } + } + + /* try fuzzy bpp matching */ + for(i=0; iwidth == 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; imodeno == 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 index 0000000..cd2cfec --- /dev/null +++ b/src/dos/vidsys.h @@ -0,0 +1,77 @@ +#ifndef VIDSYS_VIDEO_H_ +#define VIDSYS_VIDEO_H_ + +#include +#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 index 04d7b94..0000000 --- a/src/dos/watdpmi.c +++ /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__ */ -- 1.7.10.4