X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fdos%2Fvbe.c;fp=src%2Fdos%2Fvbe.c;h=0000000000000000000000000000000000000000;hb=4e4ac855a9d53fd7dee3d640f3ab46740b991b5c;hp=021a40f6d17affd2145c01247789fd01b710afe8;hpb=f87f51babcc2d9c15e1ecaca19c26acf58292bf7;p=retroray diff --git a/src/dos/vbe.c b/src/dos/vbe.c deleted file mode 100644 index 021a40f..0000000 --- a/src/dos/vbe.c +++ /dev/null @@ -1,525 +0,0 @@ -#include -#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; -}