X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=dosdemo;a=blobdiff_plain;f=src%2Fdos%2Fvbe.c;h=622508401e973d78505dd87e6535b1a735ae43eb;hp=009d5cac3485d7e8bab81874b0e077ad1be50c12;hb=05672cb8988cd30a798ea3fbce124695fc76f09c;hpb=0165ec15f868a16a70b56ada2d42db0cb69ea193 diff --git a/src/dos/vbe.c b/src/dos/vbe.c index 009d5ca..6225084 100644 --- a/src/dos/vbe.c +++ b/src/dos/vbe.c @@ -1,156 +1,208 @@ #include #include -#include +#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) +#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*)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) + +int vbe_info(struct vbe_info *info) +{ + int i, num; + void *lowbuf; + uint16_t seg, sel; + uint16_t *modeptr; + struct dpmi_regs regs = {0}; + assert(sizeof *info == 512); -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); + if(!(seg = dpmi_alloc(sizeof *info / 16, &sel))) { + return -1; } + lowbuf = (void*)((uint32_t)seg << 4); - memcpy(info->sig, "VBE2", 4); + memcpy(lowbuf, "VBE2", 4); - memset(®s, 0, sizeof regs); - regs.es = info_block_seg; regs.eax = 0x4f00; + regs.es = seg; + regs.edi = 0; + dpmi_int(0x10, ®s); - 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); + if((regs.eax & 0xffff) != 0x4f) { + fprintf(stderr, "vbe_get_info (4f00) failed\n"); + dpmi_free(sel); + return -1; } - 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; + memcpy(info, lowbuf, sizeof *info); + dpmi_free(sel); + + FIXPTR(info->oem_name); + FIXPTR(info->vendor); + FIXPTR(info->product); + FIXPTR(info->revstr); + FIXPTR(info->modes); + FIXPTR(info->accel_modes); + + 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; +} - return mi; +int vbe_num_modes(struct vbe_info *info) +{ + return NMODES(info); } -int vbe_set_mode(int mode) +int vbe_mode_info(int mode, struct vbe_mode_info *minf) { - struct dpmi_real_regs regs; + int i, num; + void *lowbuf; + uint16_t seg, sel; + struct dpmi_regs regs = {0}; - memset(®s, 0, sizeof regs); - regs.eax = 0x4f02; - regs.ebx = mode; - dpmi_real_int(0x10, ®s); + assert(sizeof *minf == 256); + assert(offsetof(struct vbe_mode_info, max_pixel_clock) == 0x3e); - if(regs.eax == 0x100) { + if(!(seg = dpmi_alloc(sizeof *minf / 16, &sel))) { return -1; } - return 0; -} - -int vbe_set_palette_bits(int bits) -{ - struct dpmi_real_regs regs; + lowbuf = (void*)((uint32_t)seg << 4); - memset(®s, 0, sizeof regs); - regs.eax = 0x4f08; - regs.ebx = bits << 8; /* bits in bh */ - dpmi_real_int(0x10, ®s); + regs.eax = 0x4f01; + regs.ecx = mode; + regs.es = seg; + dpmi_int(0x10, ®s); - if(((regs.eax >> 8) & 0xff) == 3) { + if((regs.eax & 0xffff) != 0x4f) { + fprintf(stderr, "vbe_mode_info (4f01) failed\n"); + dpmi_free(sel); return -1; } - return regs.ebx >> 8 & 0xff; /* new color bits in bh */ + + memcpy(minf, lowbuf, sizeof *minf); + dpmi_free(sel); + return 0; } -/* 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) +void vbe_print_info(FILE *fp, struct vbe_info *vinf) { - int i, shift = 8 - bits; - - outp(VGA_DAC_ADDR_WR, idx); - - for(i=0; i>= shift; - g >>= shift; - b >>= shift; + fprintf(fp, "vbe version: %u.%u\n", VBE_VER_MAJOR(vinf->ver), VBE_VER_MINOR(vinf->ver)); + if(VBE_VER_MAJOR(vinf->ver) >= 2) { + fprintf(fp, "%s - %s (%s)\n", vinf->vendor, vinf->product, vinf->revstr); + if(vinf->caps & VBE_ACCEL) { + fprintf(fp, "vbe/af %d.%d\n", VBE_VER_MAJOR(vinf->accel_ver), VBE_VER_MINOR(vinf->accel_ver)); } + } else { + fprintf(fp, "oem: %s\n", vinf->oem_name); + } + fprintf(fp, "video memory: %dkb\n", vinf->vmem_blk * 64); + + if(vinf->caps) { + fprintf(fp, "caps:"); + if(vinf->caps & VBE_8BIT_DAC) fprintf(fp, " dac8"); + if(vinf->caps & VBE_NON_VGA) fprintf(fp, " non-vga"); + if(vinf->caps & VBE_DAC_BLANK) fprintf(fp, " dac-blank"); + if(vinf->caps & VBE_ACCEL) fprintf(fp, " af"); + if(vinf->caps & VBE_MUSTLOCK) fprintf(fp, " af-lock"); + if(vinf->caps & VBE_HWCURSOR) fprintf(fp, " af-curs"); + if(vinf->caps & VBE_HWCLIP) fprintf(fp, " af-clip"); + if(vinf->caps & VBE_TRANSP_BLT) fprintf(fp, " af-tblt"); + fprintf(fp, "\n"); + } - outp(VGA_DAC_DATA, r); - outp(VGA_DAC_DATA, g); - outp(VGA_DAC_DATA, b); + fprintf(fp, "%d video modes available\n", NMODES(vinf)); + if(vinf->caps & VBE_ACCEL) { + fprintf(fp, "%d accelerated (VBE/AF) modes available\n", NACCMODES(vinf)); } + fflush(fp); } -static unsigned int get_mask(int sz, int pos) +void vbe_print_mode_info(FILE *fp, struct vbe_mode_info *minf) { - unsigned int i, mask = 0; + fprintf(fp, "%dx%d %dbpp", minf->xres, minf->yres, minf->bpp); + + switch(minf->mem_model) { + case VBE_TYPE_DIRECT: + fprintf(fp, " (rgb"); + if(0) { + case VBE_TYPE_YUV: + fprintf(fp, " (yuv"); + } + fprintf(fp, " %d%d%d)", minf->rsize, minf->gsize, minf->bsize); + break; + case VBE_TYPE_PLANAR: + fprintf(fp, " (%d planes)", minf->num_planes); + break; + case VBE_TYPE_PACKED: + fprintf(fp, " (packed)"); + break; + case VBE_TYPE_TEXT: + fprintf(fp, " (%dx%d cells)", minf->xcharsz, minf->ycharsz); + break; + case VBE_TYPE_CGA: + fprintf(fp, " (CGA)"); + break; + case VBE_TYPE_UNCHAIN: + fprintf(fp, " (unchained-%d)", minf->num_planes); + break; + } + fprintf(fp, " %dpg", minf->num_img_pages); - for(i=0; iattr & VBE_ATTR_LFB) { + fprintf(fp, " lfb@%lx", (unsigned long)minf->fb_addr); } - return mask << pos; -} -void print_mode_info(FILE *fp, struct vbe_mode_info *mi) -{ - fprintf(fp, "resolution: %dx%d\n", mi->xres, 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); + fprintf(fp, " ["); + if(minf->attr & VBE_ATTR_AVAIL) fprintf(fp, " avail"); + if(minf->attr & VBE_ATTR_OPTINFO) fprintf(fp, " opt"); + if(minf->attr & VBE_ATTR_TTY) fprintf(fp, " tty"); + if(minf->attr & VBE_ATTR_COLOR) fprintf(fp, " color"); + if(minf->attr & VBE_ATTR_GFX) fprintf(fp, " gfx"); + if(minf->attr & VBE_ATTR_NOTVGA) fprintf(fp, " non-vga"); + if(minf->attr & VBE_ATTR_BANKED) fprintf(fp, " banked"); + if(minf->attr & VBE_ATTR_LFB) fprintf(fp, " lfb"); + if(minf->attr & VBE_ATTR_2XSCAN) fprintf(fp, " dblscan"); + if(minf->attr & VBE_ATTR_ILACE) fprintf(fp, " ilace"); + if(minf->attr & VBE_ATTR_TRIPLEBUF) fprintf(fp, " trplbuf"); + if(minf->attr & VBE_ATTR_STEREO) fprintf(fp, " stereo"); + if(minf->attr & VBE_ATTR_STEREO_2FB) fprintf(fp, " stdual"); + fprintf(fp, " ]\n"); + fflush(fp); }