From e306e700b04607927f659948590c2c2ed234157e Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 12 Nov 2019 02:58:39 +0200 Subject: [PATCH] dos backend partial rewrite starting with DPMI --- src/dos/cdpmi.h | 53 +++++++++++--- src/dos/gfx.c | 205 --------------------------------------------------- src/dos/gfx.h | 60 --------------- src/dos/vbe.c | 212 ----------------------------------------------------- src/dos/vbe.h | 85 --------------------- src/dos/watdpmi.c | 59 --------------- src/rbtree.c | 2 +- 7 files changed, 44 insertions(+), 632 deletions(-) delete mode 100644 src/dos/gfx.c delete mode 100644 src/dos/gfx.h delete mode 100644 src/dos/vbe.c delete mode 100644 src/dos/vbe.h delete mode 100644 src/dos/watdpmi.c diff --git a/src/dos/cdpmi.h b/src/dos/cdpmi.h index 9ce64e1..cdfd2f7 100644 --- a/src/dos/cdpmi.h +++ b/src/dos/cdpmi.h @@ -7,7 +7,7 @@ #include "inttypes.h" -struct dpmi_real_regs { +struct dpmi_regs { uint32_t edi, esi, ebp; uint32_t reserved; uint32_t ebx, edx, ecx, eax; @@ -18,27 +18,60 @@ struct dpmi_real_regs { 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); +void *dpmi_mmap(uint32_t phys_addr, unsigned int size); +void dpmi_munmap(void *addr); #ifdef __WATCOMC__ #pragma aux dpmi_alloc = \ - "mov eax, 0x100" \ + "mov ax, 0x100" \ "int 0x31" \ "mov [edi], dx" \ - value[ax] parm[ebx][edi]; + value[ax] \ + parm[ebx][edi]; #pragma aux dpmi_free = \ - "mov eax, 0x101" \ + "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" \ - parm[dx]; + "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[cx di]; -void dpmi_real_int(int inum, struct dpmi_real_regs *regs); +#pragma aux dpmi_munmap = \ + "mov ax, 0x801" \ + "mov cx, bx" \ + "shr ebx, 16" \ + "int 0x31" \ + parm[ebx] \ + modify[ax]; #endif /* __WATCOMC__ */ #ifdef __DJGPP__ -#define dpmi_real_int(inum, regs) __dpmi_int((inum), (__dpmi_regs*)(regs)) +#define dpmi_int(inum, regs) __dpmi_int((inum), (__dpmi_regs*)(regs)) #endif -void *dpmi_mmap(uint32_t phys_addr, unsigned int size); -void dpmi_munmap(void *addr); - #endif /* DPMI_H_ */ diff --git a/src/dos/gfx.c b/src/dos/gfx.c deleted file mode 100644 index cbb1ed4..0000000 --- a/src/dos/gfx.c +++ /dev/null @@ -1,205 +0,0 @@ -#include -#include -#include -#include -#include "gfx.h" -#include "vbe.h" -#include "cdpmi.h" - -#ifdef __DJGPP__ -#include - -#define REALPTR(s, o) (void*)(((uint32_t)(s) << 4) - __djgpp_base_address + (uint32_t)(o)) -#else -#define REALPTR(s, o) (void*)(((uint32_t)(s) << 4) + (uint32_t)(o)) -#endif - -#define VBEPTR(x) REALPTR(((x) & 0xffff0000) >> 16, (x) & 0xffff) -#define VBEPTR_SEG(x) (((x) & 0xffff0000) >> 16) -#define VBEPTR_OFF(x) ((x) & 0xffff) - -#define SAME_BPP(a, b) \ - ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \ - ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32)) - -static unsigned int make_mask(int sz, int pos); - -static struct vbe_info *vbe_info; -static struct vbe_mode_info *mode_info; -static int pal_bits = 6; - -static void *vpgaddr[2]; - - -void *set_video_mode(int xsz, int ysz, int bpp) -{ - int i; - static uint16_t *modes; - uint16_t best = 0; - unsigned int fbsize, pgsize; - -#ifdef __DJGPP__ - __djgpp_nearptr_enable(); -#endif - - /* check for VBE2 support and output some info */ - if(!vbe_info) { - if(!(vbe_info = vbe_get_info())) { - fprintf(stderr, "VESA BIOS Extensions not available\n"); - return 0; - } - - printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff); - if(vbe_info->version < 0x200) { - fprintf(stderr, "This program requires VBE 2.0 or greater. Try running UniVBE\n"); - return 0; - } - - printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr), - (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr)); - printf("Video memory: %dkb\n", vbe_info->total_mem << 6); - - modes = VBEPTR(vbe_info->vid_mode_ptr); - } - - for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */ - if(modes[i] == 0xffff) { - break; /* reached the end */ - } - - mode_info = vbe_get_mode_info(modes[i] | VBE_MODE_LFB); - if(!mode_info || mode_info->xres != xsz || mode_info->yres != ysz) { - continue; - } - if(SAME_BPP(mode_info->bpp, bpp)) { - best = modes[i]; - } - } - - if(best) { - mode_info = vbe_get_mode_info(best); - } else { - fprintf(stderr, "Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp); - return 0; - } - - if(vbe_set_mode(best | VBE_MODE_LFB) == -1) { - fprintf(stderr, "Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp); - return 0; - } - - /* attempt to set 8 bits of color per component in palettized modes */ - /*if(bpp <= 8) { - pal_bits = vbe_set_palette_bits(8); - printf("palette bits per color primary: %d\n", pal_bits); - } - */ - - printf("avail video pages: %d\n", mode_info->num_img_pages); - printf("bytes per scanline: %d (%d pixels)\n", vbe_get_scanlen(VBE_SCANLEN_BYTES), - vbe_get_scanlen(VBE_SCANLEN_PIXELS)); - - pgsize = xsz * ysz * (bpp / CHAR_BIT); - fbsize = mode_info->num_img_pages * pgsize; - vpgaddr[0] = (void*)dpmi_mmap(mode_info->fb_addr, fbsize); - - if(mode_info->num_img_pages > 1) { - vpgaddr[1] = (char*)vpgaddr[0] + pgsize; - } else { - vpgaddr[1] = 0; - } - return vpgaddr[0]; -} - -int set_text_mode(void) -{ - vbe_set_mode(0x3); - return 0; -} - -int get_color_depth(void) -{ - if(!mode_info) { - return -1; - } - return mode_info->bpp; -} - -int get_color_bits(int *rbits, int *gbits, int *bbits) -{ - if(!mode_info) { - return -1; - } - *rbits = mode_info->rmask_size; - *gbits = mode_info->gmask_size; - *bbits = mode_info->bmask_size; - return 0; -} - -int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask) -{ - if(!mode_info) { - return -1; - } - *rmask = make_mask(mode_info->rmask_size, mode_info->rpos); - *gmask = make_mask(mode_info->gmask_size, mode_info->gpos); - *bmask = make_mask(mode_info->bmask_size, mode_info->bpos); - return 0; -} - -int get_color_shift(int *rshift, int *gshift, int *bshift) -{ - if(!mode_info) { - return -1; - } - *rshift = mode_info->rpos; - *gshift = mode_info->gpos; - *bshift = mode_info->bpos; - return 0; -} - -void set_palette(int idx, int r, int g, int b) -{ - int col[3]; - col[0] = r; - col[1] = g; - col[2] = b; - vbe_set_palette(idx, col, 1, pal_bits); -} - -void *page_flip(int vsync) -{ - static int frame; - void *nextaddr; - int y, when, bufidx; - - if(!vpgaddr[1]) { - /* page flipping not supported */ - return 0; - } - - bufidx = ++frame & 1; - - y = bufidx ? mode_info->yres : 0; - nextaddr = vpgaddr[bufidx]; - - when = vsync ? VBE_SET_DISP_START_VBLANK : VBE_SET_DISP_START_NOW; - if(vbe_set_disp_start(0, y, when) == -1) { - return 0; - } - - if(vsync == FLIP_VBLANK_WAIT) { - wait_vsync(); - } - return nextaddr; -} - -static unsigned int make_mask(int sz, int pos) -{ - unsigned int i, mask = 0; - - for(i=0; i -#include -#include -#include "vbe.h" -#include "cdpmi.h" -#include "inttypes.h" - -#ifdef __DJGPP__ -#include -#include - -#define SEG_ADDR(s) (((uint32_t)(s) << 4) - __djgpp_base_address) - -#define outp(p, v) outportb(p, v) -#else -#define SEG_ADDR(s) ((uint32_t)(s) << 4) -#endif - -/* VGA DAC registers used for palette setting in 8bpp modes */ -#define VGA_DAC_STATE 0x3c7 -#define VGA_DAC_ADDR_RD 0x3c7 -#define VGA_DAC_ADDR_WR 0x3c8 -#define VGA_DAC_DATA 0x3c9 - -#define MODE_LFB (1 << 14) - - -struct vbe_info *vbe_get_info(void) -{ - static uint16_t info_block_seg, info_block_selector; - static struct vbe_info *info; - struct dpmi_real_regs regs; - - if(!info) { - /* allocate 32 paragraphs (512 bytes) */ - info_block_seg = dpmi_alloc(32, &info_block_selector); - info = (struct vbe_info*)SEG_ADDR(info_block_seg); - } - - memcpy(info->sig, "VBE2", 4); - - memset(®s, 0, sizeof regs); - regs.es = info_block_seg; - regs.eax = 0x4f00; - - dpmi_real_int(0x10, ®s); - - return info; -} - -struct vbe_mode_info *vbe_get_mode_info(int mode) -{ - static uint16_t mode_info_seg, mode_info_selector; - static struct vbe_mode_info *mi; - struct dpmi_real_regs regs; - - if(!mi) { - /* allocate 16 paragraphs (256 bytes) */ - mode_info_seg = dpmi_alloc(16, &mode_info_selector); - mi = (struct vbe_mode_info*)SEG_ADDR(mode_info_seg); - } - - memset(®s, 0, sizeof regs); - regs.es = mode_info_seg; - regs.eax = 0x4f01; - regs.ecx = mode; - regs.es = mode_info_seg; - - dpmi_real_int(0x10, ®s); - if(regs.eax & 0xff00) { - return 0; - } - - return mi; -} - -int vbe_set_mode(int mode) -{ - struct dpmi_real_regs regs; - - memset(®s, 0, sizeof regs); - regs.eax = 0x4f02; - regs.ebx = mode; - dpmi_real_int(0x10, ®s); - - if(regs.eax == 0x100) { - return -1; - } - return 0; -} - -int vbe_set_palette_bits(int bits) -{ - struct dpmi_real_regs regs; - - memset(®s, 0, sizeof regs); - regs.eax = 0x4f08; - regs.ebx = bits << 8; /* bits in bh */ - dpmi_real_int(0x10, ®s); - - if(((regs.eax >> 8) & 0xff) == 3) { - return -1; - } - return regs.ebx >> 8 & 0xff; /* new color bits in bh */ -} - -/* TODO: implement palette setting through the VBE2 interface for - * non-VGA displays (actually don't). - */ -void vbe_set_palette(int idx, int *col, int count, int bits) -{ - int i, shift = 8 - bits; - - outp(VGA_DAC_ADDR_WR, idx); - - for(i=0; i>= shift; - g >>= shift; - b >>= shift; - } - - outp(VGA_DAC_DATA, r); - outp(VGA_DAC_DATA, g); - outp(VGA_DAC_DATA, b); - } -} - -int vbe_set_disp_start(int x, int y, int when) -{ - struct dpmi_real_regs regs; - - memset(®s, 0, sizeof regs); - regs.eax = 0x4f07; - regs.ebx = when & 0xffff; - regs.ecx = x & 0xffff; - regs.edx = y & 0xffff; - dpmi_real_int(0x10, ®s); - - if(regs.eax == 0x100) { - return -1; - } - return 0; -} - -int vbe_set_scanlen(int len, int mode) -{ - struct dpmi_real_regs regs; - - memset(®s, 0, sizeof regs); - regs.eax = 0x4f06; - regs.ebx = mode; - regs.ecx = len & 0xffff; - dpmi_real_int(0x10, ®s); - - if(regs.eax == 0x100) { - return -1; - } - return regs.ecx & 0xffff; -} - -int vbe_get_scanlen(int mode) -{ - int res; - struct dpmi_real_regs regs; - - memset(®s, 0, sizeof regs); - regs.eax = 0x4f06; - regs.ebx = 1; - dpmi_real_int(0x10, ®s); - - if(regs.eax == 0x100) { - return -1; - } - - if(mode == VBE_SCANLEN_PIXELS) { - res = regs.ecx & 0xffff; - } else { - res = regs.ebx & 0xffff; - } - return res; -} - - -static unsigned int get_mask(int sz, int pos) -{ - unsigned int i, mask = 0; - - for(i=0; ixres, mi->yres); - fprintf(fp, "color depth: %d\n", mi->bpp); - fprintf(fp, "mode attributes: %x\n", mi->mode_attr); - fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes); - fprintf(fp, "number of planes: %d\n", (int)mi->num_planes); - fprintf(fp, "number of banks: %d\n", (int)mi->num_banks); - fprintf(fp, "mem model: %d\n", (int)mi->mem_model); - fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos)); - fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos)); - fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos)); - fprintf(fp, "framebuffer address: %x\n", (unsigned int)mi->fb_addr); -} diff --git a/src/dos/vbe.h b/src/dos/vbe.h deleted file mode 100644 index 011cba3..0000000 --- a/src/dos/vbe.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef VBE_H_ -#define VBE_H_ - -#include "inttypes.h" - -#ifdef __GNUC__ -#define PACKED __attribute__((packed)) -#else -#define PACKED -#endif - -#define VBE_ATTR_LFB (1 << 7) -#define VBE_MODE_LFB (1 << 14) - -#pragma pack (push, 0) -struct vbe_info { - uint8_t sig[4]; - uint16_t version; - uint32_t oem_str_ptr; - uint8_t caps[4]; /* capabilities */ - uint32_t vid_mode_ptr; /* vbefarptr to video mode list */ - uint16_t total_mem; /* num of 64k mem blocks */ - uint16_t oem_sw_rev; /* VBE implementation software revision */ - uint32_t oem_vendor_name_ptr; - uint32_t oem_product_name_ptr; - uint32_t oem_product_rev_ptr; - uint8_t reserved[222]; - uint8_t oem_data[256]; -} PACKED; - -struct vbe_mode_info { - uint16_t mode_attr; - uint8_t wina_attr, winb_attr; - uint16_t win_gran, win_size; - uint16_t wina_seg, winb_seg; - uint32_t win_func; - uint16_t scanline_bytes; - - /* VBE 1.2 and above */ - uint16_t xres, yres; - uint8_t xcharsz, ycharsz; - uint8_t num_planes; - uint8_t bpp; - uint8_t num_banks; - uint8_t mem_model; - uint8_t bank_size; /* bank size in KB */ - uint8_t num_img_pages; - uint8_t reserved1; - - /* direct color fields */ - uint8_t rmask_size, rpos; - uint8_t gmask_size, gpos; - uint8_t bmask_size, bpos; - uint8_t xmask_size, xpos; - uint8_t cmode_info; /* direct color mode attributes */ - - /* VBE 2.0 and above */ - uint32_t fb_addr; /* physical address of the linear framebuffer */ - uint32_t reserved2; - uint16_t reserved3; - - uint8_t reserved4[206]; -} PACKED; -#pragma pack (pop) - -struct vbe_info *vbe_get_info(void); -struct vbe_mode_info *vbe_get_mode_info(int mode); - -int vbe_set_mode(int mode); - -int vbe_set_palette_bits(int bits); -void vbe_set_palette(int idx, int *col, int count, int bits); - -#define VBE_SET_DISP_START_NOW 0 -#define VBE_SET_DISP_START_VBLANK 0x80 -int vbe_set_disp_start(int x, int y, int when); - -#define VBE_SCANLEN_PIXELS 0 -#define VBE_SCANLEN_BYTES 2 -int vbe_set_scanlen(int len, int mode); -int vbe_get_scanlen(int mode); - -void print_mode_info(FILE *fp, struct vbe_mode_info *modei); - -#endif /* VBE_H_ */ 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__ */ diff --git a/src/rbtree.c b/src/rbtree.c index e595885..0a962d2 100644 --- a/src/rbtree.c +++ b/src/rbtree.c @@ -7,7 +7,7 @@ the terms of the 3-clause BSD license. See COPYING for details. */ #include #include -#include +#include #include #include "rbtree.h" -- 1.7.10.4