vga-logic-processor-examples/svga.c

103 lines
3.0 KiB
C

#include <stddef.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <i86.h>
#include <memory.h>
#include <sys/types.h>
/*
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;
}