134 lines
2.6 KiB
C
134 lines
2.6 KiB
C
#include <memory.h>
|
|
#include <i86.h>
|
|
#include <dos.h>
|
|
|
|
#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;
|
|
}
|