#include #include #include #include "dpmi.h" #include "vesa.h" char far *VGA = (char*)0xA0000; long windowSizeBytes, bytesPerScanLine; void *dosmem; int currentWindowPosition; #define MAX_COLORS (256) void setupVESAHandling() { dosmem = dpmiAllocateDOSMemory(1024); } void teardownVESAHandling() { dpmiDeallocateDOSMemory(); } void addDOSMemToRealModeRegs(struct dpmiRealModeRegs *rc) { rc->edi = (unsigned long)dosmem & 0xf; rc->es = (unsigned long)dosmem >> 4; } void vbeGetModeInfo( uint16_t mode, struct VbeModeInfo *modeInfo ) { struct dpmiRealModeRegs rc={0}; _fmemset(dosmem, 0, sizeof(struct VbeModeInfo)); rc.eax = 0x4f01; rc.ecx = mode; addDOSMemToRealModeRegs(&rc); dpmiInt(0x10, &rc); _fmemcpy(modeInfo, dosmem, sizeof(struct VbeModeInfo)); } int vbeGetVBEInfo( struct VbeInfo far *p ) { struct dpmiRealModeRegs rc={0}; // request VBE2 extended info _fmemset(p, 0, sizeof(struct VbeInfo)); _fmemcpy(p->VbeSignature,"VBE2",4); _fmemcpy(dosmem, p, sizeof(struct VbeInfo)); rc.eax = 0x4f00; addDOSMemToRealModeRegs(&rc); dpmiInt(0x10, &rc); _fmemcpy(p, dosmem, sizeof(struct VbeInfo)); return 0; } void startSVGAMode(int mode, struct VbeModeInfo *vbeModeInfo) { /** * Side effects: sets some internal variables for window and scanline sizes */ union REGS regs; vbeGetModeInfo(mode, vbeModeInfo); windowSizeBytes = 1024L * vbeModeInfo->WinSize; bytesPerScanLine = vbeModeInfo->BytesPerScanLine; regs.w.ax = 0x4f02; regs.w.bx = mode; int386(0x10, ®s, ®s); vbeSetWindow(0, 0); } void vbeSetWindow(int window, int position) { /** * Side effects: tracks current window position */ union REGS regs; regs.w.ax = 0x4f05; regs.h.bh = 0; regs.h.bl = window; regs.w.dx = position; int386(0x10, ®s, ®s); currentWindowPosition = position; } void maybeVbeSetWindow(int window, int position) { if (currentWindowPosition == position) return; vbeSetWindow(window, position); } void setVESAColorPalette( struct VESAColor *colors ) { struct dpmiRealModeRegs rc={0}; int i; _fmemcpy(dosmem, colors, MAX_COLORS * 4); // prep our real mode interrupt call rc.eax = 0x4f09; rc.ebx = 0; rc.ecx = MAX_COLORS; rc.edx = 0; addDOSMemToRealModeRegs(&rc); dpmiInt(0x10, &rc); } void setPixel(int x, int y, int color) { long absolutePosition = (long)y * bytesPerScanLine + x; long windowPosition = absolutePosition / windowSizeBytes; long windowOffset = absolutePosition % windowSizeBytes; /** * This will not shift window positions unless needed. */ maybeVbeSetWindow(0, windowPosition); VGA[windowOffset] = color; }