nuclear@0: #include nuclear@0: #include nuclear@3: #include nuclear@0: #include "vbe.h" nuclear@0: #include "dpmi.h" nuclear@3: #include "inttypes.h" nuclear@3: nuclear@3: #ifdef __DJGPP__ nuclear@3: #include nuclear@3: #include nuclear@3: nuclear@3: #define SEG_ADDR(s) (((uint32_t)(s) << 4) - __djgpp_base_address) nuclear@3: nuclear@3: #define outp(p, v) outportb(p, v) nuclear@3: #else nuclear@3: #define SEG_ADDR(s) ((uint32_t)(s) << 4) nuclear@3: #endif nuclear@0: nuclear@0: /* VGA DAC registers used for palette setting in 8bpp modes */ nuclear@0: #define VGA_DAC_STATE 0x3c7 nuclear@0: #define VGA_DAC_ADDR_RD 0x3c7 nuclear@0: #define VGA_DAC_ADDR_WR 0x3c8 nuclear@0: #define VGA_DAC_DATA 0x3c9 nuclear@0: nuclear@0: #define MODE_LFB (1 << 14) nuclear@0: nuclear@0: nuclear@0: struct vbe_info *vbe_get_info(void) nuclear@0: { nuclear@3: static uint16_t info_block_seg, info_block_selector; nuclear@0: static struct vbe_info *info; nuclear@0: struct dpmi_real_regs regs; nuclear@0: nuclear@0: if(!info) { nuclear@0: /* allocate 32 paragraphs (512 bytes) */ nuclear@3: info_block_seg = dpmi_alloc(32, &info_block_selector); nuclear@3: info = (struct vbe_info*)SEG_ADDR(info_block_seg); nuclear@0: } nuclear@0: nuclear@0: memcpy(info->sig, "VBE2", 4); nuclear@0: nuclear@0: memset(®s, 0, sizeof regs); nuclear@0: regs.es = info_block_seg; nuclear@0: regs.eax = 0x4f00; nuclear@0: nuclear@0: dpmi_real_int(0x10, ®s); nuclear@0: nuclear@0: return info; nuclear@0: } nuclear@0: nuclear@0: struct vbe_mode_info *vbe_get_mode_info(int mode) nuclear@0: { nuclear@3: static uint16_t mode_info_seg, mode_info_selector; nuclear@0: static struct vbe_mode_info *mi; nuclear@0: struct dpmi_real_regs regs; nuclear@0: nuclear@0: if(!mi) { nuclear@0: /* allocate 16 paragraphs (256 bytes) */ nuclear@3: mode_info_seg = dpmi_alloc(16, &mode_info_selector); nuclear@3: mi = (struct vbe_mode_info*)SEG_ADDR(mode_info_seg); nuclear@0: } nuclear@0: nuclear@0: memset(®s, 0, sizeof regs); nuclear@0: regs.es = mode_info_seg; nuclear@0: regs.eax = 0x4f01; nuclear@0: regs.ecx = mode; nuclear@0: regs.es = mode_info_seg; nuclear@0: nuclear@0: dpmi_real_int(0x10, ®s); nuclear@0: if(regs.eax & 0xff00) { nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: return mi; nuclear@0: } nuclear@0: nuclear@0: int vbe_set_mode(int mode) nuclear@0: { nuclear@0: struct dpmi_real_regs regs; nuclear@0: nuclear@0: memset(®s, 0, sizeof regs); nuclear@0: regs.eax = 0x4f02; nuclear@0: regs.ebx = mode; nuclear@0: dpmi_real_int(0x10, ®s); nuclear@0: nuclear@0: if(regs.eax == 0x100) { nuclear@0: return -1; nuclear@0: } nuclear@0: return 0; nuclear@0: } nuclear@0: nuclear@0: int vbe_set_palette_bits(int bits) nuclear@0: { nuclear@0: struct dpmi_real_regs regs; nuclear@0: nuclear@0: memset(®s, 0, sizeof regs); nuclear@0: regs.eax = 0x4f08; nuclear@0: regs.ebx = bits << 8; /* bits in bh */ nuclear@0: dpmi_real_int(0x10, ®s); nuclear@0: nuclear@3: if(((regs.eax >> 8) & 0xff) == 3) { nuclear@0: return -1; nuclear@0: } nuclear@0: return regs.ebx >> 8 & 0xff; /* new color bits in bh */ nuclear@0: } nuclear@0: nuclear@0: /* TODO: implement palette setting through the VBE2 interface for nuclear@0: * non-VGA displays (actually don't). nuclear@0: */ nuclear@0: void vbe_set_palette(int idx, int *col, int count, int bits) nuclear@0: { nuclear@0: int i, shift = 8 - bits; nuclear@0: nuclear@3: outp(VGA_DAC_ADDR_WR, idx); nuclear@0: nuclear@0: for(i=0; i>= shift; nuclear@0: g >>= shift; nuclear@0: b >>= shift; nuclear@0: } nuclear@0: nuclear@3: outp(VGA_DAC_DATA, r); nuclear@3: outp(VGA_DAC_DATA, g); nuclear@3: outp(VGA_DAC_DATA, b); nuclear@0: } nuclear@0: } nuclear@0: nuclear@3: int vbe_set_disp_start(int x, int y, int when) nuclear@3: { nuclear@3: struct dpmi_real_regs regs; nuclear@3: nuclear@3: memset(®s, 0, sizeof regs); nuclear@3: regs.eax = 0x4f07; nuclear@3: regs.ebx = when & 0xffff; nuclear@3: regs.ecx = x & 0xffff; nuclear@3: regs.edx = y & 0xffff; nuclear@3: dpmi_real_int(0x10, ®s); nuclear@3: nuclear@3: if(regs.eax == 0x100) { nuclear@3: return -1; nuclear@3: } nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: int vbe_set_scanlen(int len, int mode) nuclear@3: { nuclear@3: struct dpmi_real_regs regs; nuclear@3: nuclear@3: memset(®s, 0, sizeof regs); nuclear@3: regs.eax = 0x4f06; nuclear@3: regs.ebx = mode; nuclear@3: regs.ecx = len & 0xffff; nuclear@3: dpmi_real_int(0x10, ®s); nuclear@3: nuclear@3: if(regs.eax == 0x100) { nuclear@3: return -1; nuclear@3: } nuclear@3: return regs.ecx & 0xffff; nuclear@3: } nuclear@3: nuclear@3: int vbe_get_scanlen(int mode) nuclear@3: { nuclear@3: int res; nuclear@3: struct dpmi_real_regs regs; nuclear@3: nuclear@3: memset(®s, 0, sizeof regs); nuclear@3: regs.eax = 0x4f06; nuclear@3: regs.ebx = 1; nuclear@3: dpmi_real_int(0x10, ®s); nuclear@3: nuclear@3: if(regs.eax == 0x100) { nuclear@3: return -1; nuclear@3: } nuclear@3: nuclear@3: if(mode == VBE_SCANLEN_PIXELS) { nuclear@3: res = regs.ecx & 0xffff; nuclear@3: } else { nuclear@3: res = regs.ebx & 0xffff; nuclear@3: } nuclear@3: return res; nuclear@3: } nuclear@3: nuclear@3: nuclear@0: static unsigned int get_mask(int sz, int pos) nuclear@0: { nuclear@0: unsigned int i, mask = 0; nuclear@0: nuclear@0: for(i=0; ixres, mi->yres); nuclear@0: fprintf(fp, "color depth: %d\n", mi->bpp); nuclear@0: fprintf(fp, "mode attributes: %x\n", mi->mode_attr); nuclear@0: fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes); nuclear@0: fprintf(fp, "number of planes: %d\n", (int)mi->num_planes); nuclear@0: fprintf(fp, "number of banks: %d\n", (int)mi->num_banks); nuclear@0: fprintf(fp, "mem model: %d\n", (int)mi->mem_model); nuclear@0: fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos)); nuclear@0: fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos)); nuclear@0: fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos)); nuclear@3: fprintf(fp, "framebuffer address: %x\n", (unsigned int)mi->fb_addr); nuclear@0: }