📄 grengine.cpp
字号:
{ 360, 0x6B, 0x59, 0x5A, 0x8E, 0x5E, 0x8A, 1, 1 },
{ 376, 0x6E, 0x5D, 0x5E, 0x91, 0x62, 0x8F, 1, 1 },
{ 400, 0x70, 0x63, 0x64, 0x92, 0x69, 0x85, 1, 0 }
};
static struct {
int res;
int overflow, v_total;
int v_retracestart, v_retraceend;
int v_enableend, v_blankstart, v_blankend;
int v_polarity, v_maxscan;
} y [9] = {
{ 400, 0x1F, 0xBF, 0x9C, 0x8E, 0x8F, 0x96, 0xB9, 0, 0x40 },
{ 480, 0x3E, 0x0D, 0xEA, 0xAC, 0xDF, 0xE7, 0x06, 1, 0x40 },
{ 360, 0x1F, 0xBF, 0x88, 0x85, 0x67, 0x6D, 0xBA, 0, 0x40 },
{ 512, 0xB2, 0x30, 0x0A, 0xAC, 0xFF, 0x07, 0x1A, 1, 0x60 },
{ 600, 0xF0, 0x70, 0x5B, 0x8C, 0x57, 0x58, 0x70, 1, 0x60 },
{ 564, 0xF0, 0x62, 0x37, 0x89, 0x33, 0x3C, 0x5C, 1, 0x60 },
{ 540, 0xF0, 0x30, 0x20, 0xA9, 0x1B, 0x1F, 0x2F, 1, 0x60 },
{ 448, 0x3E, 0x0B, 0xDA, 0x9C, 0xBF, 0xC7, 0x04, 1, 0x40 },
{ 300, 0x1F, 0x46, 0x31, 0x80, 0x2B, 0x2F, 0x44, 1, 0x40 },
};
switch (mode) {
case 0:
xres = 160; yres = 25;
break;
case 1:
xres = 256; yres = 256;
xregset = 1; yregset = 3;
break;
case 2:
xres = 320; yres = 200;
break;
case 3:
xres = 320; yres = 240;
xregset = 0; yregset = 1; chained = false;
break;
case 4:
xres = 360; yres = 240;
xregset = 2; yregset = 1; chained = false;
break;
case 5:
xres = 360; yres = 360;
xregset = 2; yregset = 2; chained = false;
doublescan = false;
break;
}
if (qsize) {
xres = 256;
yres = 256;
}
if (mode == vidmode) {
if (qsize && !chained) // Select all planes for changing at once: set all bits of register 2
outpw (_SEQU, 0x0F02);
memset (_VGA_PTR, 0, 0xFFFF);
return;
}
if (mode != 0) {
regs.w.ax = 0x0013;
int386 (0x10, ®s, ®s); // Set regular mode 13h
} else {
regs.w.ax = 0x0003;
int386 (0x10, ®s, ®s); // Set text mode
}
if (mode != 0 && mode != 2) {
outp (_CRTC, 0x11);
v = inp (_CRTC+1) & 0x7F;
outp (_CRTC, 0x11);
outp (_CRTC+1, v);
// Write protect off
outp(0x3C2, 0x23 | (x [xregset].clockselect << 2) |
(x [xregset].h_polarity << 6) | (y [yregset].v_polarity << 7));
// Write misc.output
outp(_CRTC, 0x00); outp(_CRTC+1, x [xregset].h_total);
// Write horizontal total
outp(_CRTC, 0x01); outp(_CRTC+1, x [xregset].h_enableend);
// Write horizontal display enable end
outp(_CRTC, 0x02); outp(_CRTC+1, x [xregset].h_blankstart);
// Write horizontal blank start
outp(_CRTC, 0x03); outp(_CRTC+1, x [xregset].h_blankend);
// Write horizontal blank end
outp(_CRTC, 0x04); outp(_CRTC+1, x [xregset].h_retracestart);
// Write horizontal retrace start
outp(_CRTC, 0x05); outp(_CRTC+1, x [xregset].h_retraceend);
// Write horizontal retrace end
outp(_CRTC, 0x06); outp(_CRTC+1, y [yregset].v_total);
// Write vertical total
outp(_CRTC, 0x07); outp(_CRTC+1, y [yregset].overflow);
// Write overflow register
outp(_CRTC, 0x08); outp(_CRTC+1, 0x08);
// Write preset row scan
outp(_CRTC, 0x09); outp(_CRTC+1, 0x40 | ((y [yregset].res & 512) >> 4) | doublescan);
// Write number of duplicate scans and split screen scanline bit 9 (to help disable it)
outp(_CRTC, 0x10); outp(_CRTC+1, y [yregset].v_retracestart);
// Write vertical retrace start
outp(_CRTC, 0x11); outp(_CRTC+1, y [yregset].v_retraceend);
// Write vertical retrace end
outp(_CRTC, 0x12); outp(_CRTC+1, y [yregset].v_enableend);
// Write vertical display enable end
outp(_CRTC, 0x13); outp(_CRTC+1, x [xregset].res / 8);
// Write virtual width
outp(_CRTC, 0x14); outp(_CRTC+1, chained << 6);
// Write Underline location OR DWord mode off OR Byte mode on
// (Well, which one is it? I dunno)
outp(_CRTC, 0x15); outp(_CRTC+1, y [yregset].v_blankstart);
// Write vertical blank start
outp(_CRTC, 0x16); outp(_CRTC+1, y [yregset].v_blankend);
// Write vertical blank end
outp(_CRTC, 0x17); outp(_CRTC+1, 0xE3 - (chained << 6));
// Mode Control: same in all versions of Mode X
outp(_CRTC, 0x18); outp(_CRTC+1, y [yregset].res & 255);
// Send split screen scanline bits 0 to 7 (to disable split screen)
// _SEQU = 0x3C4
outpw (_SEQU, 0x0100);
outpw (_SEQU, 0x0101);
outpw (_SEQU, 0x0300);
// Set clock mode register
if (!chained) // Turn off chain-4: bit 2(??) of register ("index") 4.
outpw (_SEQU, 0x0604);
// _GRAC = 0x3CE
outpw (_GRAC, 0x4005);
outpw (_GRAC, 0x0506);
// Set mode and misc. regs
inp (0x3DA); outp (0x3C0, 0x10); outp (0x3C0, 0x41);
// Reset flop-flop, write index, write value
// ...of mode control.
inp (0x3DA); outp (0x3C0, 0x13); outp (0x3C0, 0x00);
// Reset flop-flop, write index, write value
// ...of horizontal panning.
outp (0x3C0, 0x20);
// Re-enable display
if (!chained) // Select all planes for changing at once: set all bits of register 2
outpw (_SEQU, 0x0F02);
memset (_VGA_PTR, 0, 0xFFFF);
// Clear video memory.
outp (0,0);
}
vidmode = mode;
debug0("video mode Set!");
}
//----------------------------------------------------------------------------
void testpattern ()
{
int x, y;
int starttime;
setvideomode (vidmode, true);
for (y = 0; y < 256; y++) {
for (x = 0; x < 256; x++) {
vs [(y << 8) + x] = (((x*x + y*y) & 255) >> 4) + 16;
}
}
copyscreen ();
tdelay (500);
clearscreen ();
setvideomode (vidmode, false);
starttime = tmsec;
for (y = 0; y < 256; y++) {
memset (&vs [y * xres], y, xres);
copyscreen ();
clearscreen();
}
debug0 ("Video mode %d: 256 pageflips in %d milliseconds. %d fps.", vidmode, tmsec-starttime, 256000/(tmsec-starttime));
}
//----------------------------------------------------------------------------
void waitforretrace ()
{
if (leadingedge) {
while (inp (0x3DA) & 8)
;
}
while (!(inp (0x3DA) & 8))
;
}
int modexflip = true;
extern void move64k (void *src, void *dest);
extern void move64k_fpu (void *src, void *dest);
#pragma aux move64k = \
"cld" \
"mov ecx, 0x4000" \
"rep movsd" \
parm [esi] [edi] \
modify [esi edi ecx];
// "mov ax, ds" \
"mov es, ax" \
"pusha"\
"pushf"\
"mov ax, seg vs"\
"mov ds, ax"\
"popf"\
"popa"\
"mov debugesi, eax"\
"mov debugedi, ecx"\
"mov edi, 0xA0000" \
"mov esi, offset vs" \
#pragma aux move64k_fpu =\
" mov ecx, 0x1000"\
"TOP: FILD QWORD PTR [ESI]"\
" FILD QWORD PTR [ESI+8]"\
" FXCH"\
" FISTP QWORD PTR [EDI]"\
" FISTP QWORD PTR [EDI+8]"\
" ADD ESI, 16"\
" ADD EDI, 16"\
" DEC ECX"\
" JNZ TOP"\
parm [esi] [edi] \
modify [esi edi ecx];
extern void clear64k (void *dest, dword fill);
#pragma aux clear64k = \
"cld" \
"mov ecx, 0x4000" \
"rep stosd" \
parm [edi] [eax] \
modify [edi ecx];
// "mov byte ptr debugesi, al"\
"mov debugedi, edi"\
extern void modexcopy (void *src, void *dest, int amount);
// src is always vs
int amnt;
byte iter;
int strt;
void *vgadest;
//#pragma aux modexcopy = \
"pusha"\
"cld" \
"again: mov dh, byte ptr iter" /*4 iterations starting with plane 3*/\
"shr dh, 1"\
"mov dl, 2"\
"mov ax, 0x3C4"\
"out dx, ax"\
"mov esi, offset vs"\
"add esi, strt"\
"mov edi, vgadest"\
"mov ecx, amnt"\
"inner: movsb"\
"add edi, 3"\
"loop inner"\
"mov ecx, strt"\
"dec ecx"\
"jnz again"\
"popa"\
parm [edi] [ecx]\
modify [ax];
// ecx=amount
// esi=vs[strt]
// edi=
#pragma aux modexcopy = \
"inner: mov al,ds:[esi]"\
"mov es:[edi],al"\
"add esi, 4"\
"inc edi"\
"dec cx"\
"jnz inner"\
parm [esi] [edi] [ecx]\
modify [edi esi ecx al];
// "cld"\
"inner: movsb"\
"add esi, 3"\
"dec cx"\
"jnz inner"\
parm [esi] [edi] [ecx]\
modify [edi esi ecx al];
/*
last = ((xres * yres) >> 2) + drawstart;
for (p = 0; p < 4; p++) {
qpos = p;
outp (_SEQU, 0x02); outp (_SEQU+1, 1 << p);
for (x = drawstart; x < last; x++) {
_VGA_PTR [x] = vs [qpos];
qpos += 4;
}
}
*/
//----------------------------------------------------------------------------
void copyscreen ()
{
int x, y, p, qpos, start, linesize, last;
static visiblestart = 0;
static drawstart = modexflip ? 0x8000 : 0;
//double *ptr, *ptr2;
if (waitretrace)
waitforretrace ();
if (vidmode == 2 && xres == 256) { // Mode Q screen must be squished to 200 lines
for (x = 0, y = 0; y < 256; y++) {
if (y & 7) {
memcpy (_VGA_PTR + x * 320 + 32, vs + y * 256, 256);
x++;
}
}
} else if (vidmode < 3) { // Linear mode
//memcpy (_VGA_PTR, vs, 65536);
if (fpucopy) {
move64k_fpu (vs, _VGA_PTR);
//for (ptr = (double*)_VGA_PTR, ptr2 = (double*)vs; ptr < (double*)(_VGA_PTR+0x10000); ptr++, ptr2++) {
// *ptr = *ptr2;
//}
} else {
move64k (vs, _VGA_PTR);
}
} else if (xres == 256 && yres == 256) { // Mode X copy of 256x256 buffer.
switch (vidmode) {
case 3: linesize = 80; last = 240; break;
case 4: linesize = 90; last = 240; break;
case 5: linesize = 90; last = 256; break;
}
for (p = 0; p < 4; p++) {
switch (vidmode) {
case 3: start = 8; break;
case 4: start = 13; break;
case 5: start = 6493; break;
}
start += drawstart;
qpos = p;
outp (_SEQU, 0x02); outp (_SEQU+1, 1 << p);
for (y = 0; y < last; y++) {
for (x = 0; x < 64; x++) {
_VGA_PTR [start + x] = vs [qpos];
qpos += 4;
}
start += linesize;
}
}
} else { // Mode X copy
last = ((xres * yres) >> 2);
for (p = 0; p < 4; p++) {
outp (_SEQU, 0x02); outp (_SEQU+1, 1 << p);
modexcopy (vs+p, _VGA_PTR+drawstart, last);
}/**/
/*last = ((xres * yres) >> 2) + drawstart;
for (p = 0; p < 4; p++) {
qpos = p;
outp (_SEQU, 0x02); outp (_SEQU+1, 1 << p);
for (x = drawstart; x < last; x++) {
_VGA_PTR [x] = vs [qpos];
qpos += 4;
}
}*/
}
if (modexflip && vidmode > 2) {
drawstart ^= 0x8000;
visiblestart ^= 0x8000;
outp (_CRTC, 0x0C);
outp (_CRTC + 1, visiblestart >> 8);
outp (_CRTC, 0x0D);
outp (_CRTC + 1, visiblestart & 255);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -