#include #include #include #include #include #include #include /* Set up a 640x480x256 Super VGA screen and load a bitmap image into it. Wait 10 seconds, then exit the program. Since this is going through DOS/4GW, we need to use the DOS Protected Mode Interface (DPMI) to work with x86 Real Mode RAM so the VESA interrupt functions have a place to accept and dump data. There were a lot of scattered examples as to how to get SVGA going, but: * most were written in assembler and, while I can read assembler, I don't prefer to, especially in the early learning stages of a bunch of new concepts * very few of them covered the whole pipeline of query display, then set it up, then do something real with it So here's this one. Enjoy. John */ // built from a combination of: // // * http://www.pennelynn.com/Documents/CUJ/HTML/14.08/KREHBIEL/KREHL1.HTM // * https://forum.osdev.org/viewtopic.php?f=2&t=30186 // * https://github.com/joncampbell123/doslib/blob/master/hw/vesa/vesa.c // * https://stackoverflow.com/questions/3318410/pragma-pack-effect // * https://www.delorie.com/djgpp/doc/dpmi/ch4.4.html // * https://delorie.com/djgpp/doc/dpmi/api/310100.html // * http://www.monstersoft.com/tutorial1/VESA_intro.html // * http://www.delorie.com/djgpp/doc/ug/graphics/vesa.html.en // * https://lhlaurini.xyz/VESA_Video_Modes // * https://stackoverflow.com/questions/58328264/retrieve-list-of-vesa-video-modes-from-int-10h-ax-4f00h // * https://github.com/execomrt/vesa2/blob/main/vbelib/vbecore.c#L262 // * https://pdos.csail.mit.edu/6.828/2004/readings/hardware/vbe3.pdf #include "vesa.h" #include "bmp.h" #include "dpmi.h" /** If you want to enumerate all the possible modes to inspect, you would need something like this to turn the segment:offset data into array elements you can address in 32-bit DOS. uint16_t *modePtr; modePtr = (uint16_t*)((vbeInfo.VideoModeSegment << 4) + vbeInfo.VideoModeOffset); for (i = 0; i < 4; ++i) { printf("Available mode %d: 0x%x\n", i, modePtr[i]); } */ int main(void) { int x, y; FILE *bmp; struct BMPImage bmpImage; struct VESAColor colors[256]; struct VbeInfo vbeInfo; struct VbeModeInfo vbeModeInfo; setupVESAHandling(); vbeGetVBEInfo(&vbeInfo); printf("VBE Version: 0x%x\n", vbeInfo.VbeVersion); bmp = fopen("chkn640.bmp", "rb"); readBMPHeader(bmp, &bmpImage); bmp256ColorPaletteToVESAColorPalette(&bmpImage, colors); // we could enumerate all the modes, but in DOSBox-X's default S3 VGA card, // 0x101 is 640x480x256, and that's where I'm running this. it's more correct // to select the mode based on examining capabilities for all available // modes, but...eh. startSVGAMode(0x101, &vbeModeInfo); setVESAColorPalette(colors); for (y = 0; y < vbeModeInfo.YResolution; ++y) { for (x = 0; x < vbeModeInfo.XResolution; ++x) { setPixel(x, vbeModeInfo.YResolution - y, fgetc(bmp)); } } fclose(bmp); delay(10000); teardownVESAHandling(); return 0; }