103 lines
3.0 KiB
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;
|
|
}
|