📄 g4drv.c
字号:
#include "define.h"
#include "mode15k.h"
#include "drv15k.h"
#define USE_ZOOM
#define ZOOMLIMITATION 0
static DWORD DeviceBusNumber = 0;
static int InterlaceStatus = 0;
static int G400MGAMode(void);
static void SetClockRegisterInternal(void);
static void SetG400ExtRegister(CRTCPARAM *cp);
static void SetG400Interlace(int flag, int HSyncStart, int HSyncEnd, int HTotal, int ratio);
static long get_vclk_param(unsigned long vclk, int *N, int *M, int *P, int *S);
static void SetVClock(int N, int M, int P, int S);
static void SetHZoom(int d0);
static int GetHorizontalZoomRatio(CRTCPARAM *cp);
static void AdjustCrtcParam(CRTCPARAM *cp, int hzoom);
static void AdjustSyncParam(CRTCPARAM *cp, long dotclock);
#ifdef ZOOMLIMITATION
static int CheckHorizontalTotal(int HTotal, int hzoom);
#endif
static void SetCompositeSync(int flag);
static void SetDoubleScan(int flag);
int GetInterlaceStatus(void);
void SetInterlaceStatus(int d0);
static DWORD GetG400BytesPerLine(void);
static void SetG400BytesPerLine(DWORD d0);
static DWORD AdjustG400BytesPerLine(DWORD d0);
static int GetBitsPerPixel(void);
static int GetBitsPerPixel_(void);
BYTE G400IdxReg_inb(BYTE _index);
BYTE G400CrtcExtReg_inb(BYTE _index);
void G400IdxReg_outb(BYTE _index, BYTE _data);
void G400CrtcExtReg_outb(BYTE _index, BYTE _data);
/* findg400.asm */
unsigned int findg400(void);
void G400_outb(DWORD, BYTE);
BYTE G400_inb(DWORD);
int DetectG400(void)
{
return (findg400() == 0) ? 0 : 1;
}
void resetG400_15KHz(void)
{
}
int SetG400(int xres, int yres, int center_x, int center_y, int hsyncdelay, int hdispdelay)
{
CRTCPARAM cp;
int hzoom;
int N, M, P, S;
long vclk;
GetMode15KHz(&cp, xres, yres);
hzoom = GetHorizontalZoomRatio(&cp);
AdjustCrtcParam(&cp, hzoom);
vclk = get_vclk_param(cp.dotclockHz, &N, &M, &P, &S);
AdjustSyncParam(&cp, vclk);
AdjustCenter(&cp, center_x, center_y);
DisableGenerateSignal();
SetInterlaceStatus(0);
SetGenericVGARegister(&cp, hsyncdelay, hdispdelay);
SetG400ExtRegister(&cp);
SetVClock(N, M, P, S);
SetHZoom(hzoom);
SetDoubleScan(cp.doublescan);
SetHVPolarity(cp.hpolarity, cp.vpolarity);
EnableGenerateSignal();
return 1;
}
static int GetHorizontalZoomRatio(CRTCPARAM *cp)
{
int zoom = 1;
#ifdef USE_ZOOM
if(cp->HTotal < 512){
zoom = 4;
}else if(cp->HTotal < 1024){
zoom = 2;
}else{
zoom = 1;
}
#endif
return zoom;
}
static void AdjustSyncParam(CRTCPARAM *cp, long dotclock)
{
int d0;
if(dotclock == 0){
cp->dotclockHz = CalcDotclock(cp->vert001Hz, cp->HTotal,
cp->VTotal, cp->interlace);
}else{
cp->dotclockHz = dotclock;
}
cp->horzHz = cp->dotclockHz / cp->HTotal;
d0 = cp->VTotal * 2;
if(cp->interlace != 0){
d0 += 1;
}
cp->vert001Hz = (cp->horzHz * 100 * 2) / d0;
}
static void AdjustCrtcParam(CRTCPARAM *cp, int hzoom)
{
cp->HTotal *= hzoom;
cp->HDisp *= hzoom;
cp->HBStart *= hzoom;
cp->HBEnd *= hzoom;
cp->HSStart *= hzoom;
cp->HSEnd *= hzoom;
cp->HBStart = cp->HDisp - 8;
cp->HBEnd = cp->HTotal - 8;
cp->VBStart = cp->VDisp - 1;
cp->VBEnd = cp->VTotal - 1;
if( (cp->HBEnd - cp->HBStart) > (0x7F << 3) ){
cp->HBEnd = cp->HBStart + (0x7F << 3);
}
if( (cp->HSEnd - cp->HSStart) > (0x1F << 3) ){
cp->HSEnd = cp->HSStart + (0x1F << 3);
}
if(cp->interlace != 0){
if( (cp->VTotal % 2) != 0 ){
cp->VTotal += 1;
cp->VBEnd = cp->VTotal - 1;
}
}
#ifdef ZOOMLIMITATION
if( CheckHorizontalTotal(cp->HTotal, hzoom) == 0 ){
cp->HTotal += 8;
}
#endif
AdjustSyncParam(cp, 0);
}
#ifdef ZOOMLIMITATION
static int CheckHorizontalTotal(int HTotal, int hzoom)
{
int result = 1;
int d0;
d0 = 8 * hzoom;
if( ((HTotal >> 3) % d0) == (d0 - 1) ){
result = 0;
}
return result;
}
#endif
static void SetClockRegisterInternal(void)
{
BYTE d0;
d0 = _inb(0x3CC);
d0 = d0 | 0x0C;
_outb(0x3C2, d0);
}
void SetInterlaceStatus(int d0)
{
if(d0 != 0) d0 = 1;
InterlaceStatus = d0;
}
int GetInterlaceStatus(void)
{
return InterlaceStatus;
}
static void SetG400Interlace(int flag, int HSyncStart, int HSyncEnd, int HTotal, int ratio)
{
int d1;
if(flag != 0){
SetInterlaceStatus(1);
if(G400MGAMode() != 0){
d1 = G400CrtcExtReg_inb(0x00);
if((d1 & 0x80) == 0){
d1 = (HSyncStart/8) + (HSyncEnd/8) - ((HTotal/8) - 5);
d1 = (d1 * ratio) / 100;
d1 = (d1 / 2) - 1;
if(d1 < 0) d1 = 0;
if(d1 > 0xFF) d1 = 0xFF;
G400CrtcExtReg_outb(0x05, d1 & 0xFF);
G400CrtcExtReg_outb(0x00, BitMov(G400CrtcExtReg_inb(0x00), 7, 1, 0));
SetG400BytesPerLine(GetG400BytesPerLine() * 2);
}
}else{
SetCrtcReg(0x13, GetCrtcReg(0x13) << 1);
}
}else{
SetInterlaceStatus(0);
d1 = G400CrtcExtReg_inb(0x00);
if((d1 & 0x80) != 0){
G400CrtcExtReg_outb(0x00, BitMov(G400CrtcExtReg_inb(0x00), 7, 0, 0));
G400CrtcExtReg_outb(0x05, 0);
SetG400BytesPerLine(GetG400BytesPerLine() / 2);
}
}
}
DWORD GetG400ScreenStartAddress(void)
{
DWORD d0;
d0 = (DWORD)GetCrtcReg(0x0D);
d0 |= (DWORD)GetCrtcReg(0x0C) << 8;
d0 = BitMov(d0, 16, G400CrtcExtReg_inb(0x00), 0);
d0 = BitMov(d0, 17, G400CrtcExtReg_inb(0x00), 1);
d0 = BitMov(d0, 18, G400CrtcExtReg_inb(0x00), 2);
d0 = BitMov(d0, 19, G400CrtcExtReg_inb(0x00), 3);
d0 = BitMov(d0, 20, G400CrtcExtReg_inb(0x00), 6);
switch(GetBitsPerPixel_()){
case 8:
d0 *= 8;
break;
case 16:
d0 *= 4;
break;
case 24:
d0 *= 8;
break;
case 32:
d0 *= 2;
break;
default:
d0 = 0;
}
return d0;
}
void SetG400ScreenStartAddress(DWORD d0)
{
DWORD d1;
switch(GetBitsPerPixel_()){
case 8:
d0 /= 8;
break;
case 16:
d0 /= 4;
break;
case 24:
d0 /= 8;
break;
case 32:
d0 /= 2;
break;
default:
d0 = 0;
}
SetCrtcReg(0x0D, d0);
SetCrtcReg(0x0C, d0 >> 8);
d1 = (DWORD)G400CrtcExtReg_inb(0x00);
d1 = BitMov(d1, 0, d0, 16);
d1 = BitMov(d1, 1, d0, 17);
d1 = BitMov(d1, 2, d0, 18);
d1 = BitMov(d1, 3, d0, 19);
d1 = BitMov(d1, 6, d0, 20);
G400CrtcExtReg_outb(0x00, (BYTE)d1);
}
static DWORD GetG400BytesPerLine(void)
{
DWORD d0;
d0 = GetCrtcReg(0x13);
d0 = BitMov(d0, 8, G400CrtcExtReg_inb(0x00), 4);
d0 = BitMov(d0, 9, G400CrtcExtReg_inb(0x00), 5);
d0 = d0 << (7 - 3);
if(GetInterlaceStatus() != 0){
d0 = d0 >> 1;
}
return d0;
}
static void SetG400BytesPerLine(DWORD d0)
{
d0 = AdjustG400BytesPerLine(d0);
if(GetInterlaceStatus() != 0){
d0 = d0 << 1;
}
d0 = d0 >> (7 - 3);
SetCrtcReg(0x13, d0 & 0xFF);
G400CrtcExtReg_outb(0x00, BitMov(G400CrtcExtReg_inb(0x00), 4, d0, 8));
G400CrtcExtReg_outb(0x00, BitMov(G400CrtcExtReg_inb(0x00), 5, d0, 9));
}
static WORD GetG400MaxBytesPerLine(void)
{
WORD d0;
if(GetBitsPerPixel_() == 24){
d0 = 65280;
}else{
d0 = 511 * 128;
}
return d0;
}
static int GetBitsPerPixel(void)
{
int d0;
int d1;
d0 = G400IdxReg_inb(0x19) & 0x07;
switch(d0){
case 0:
d1 = 8;
break;
case 1:
d1 = 15;
break;
case 2:
d1 = 16;
break;
case 3:
d1 = 24;
break;
case 4:
d1 = 32;
break;
case 7:
d1 = 32;
break;
default:
d1 = 0;
}
return d1;
}
static int GetBitsPerPixel_(void)
{
return (GetBitsPerPixel() + 7) & ~0x07;
}
static DWORD AdjustG400BytesPerLine(DWORD d0)
{
if(GetBitsPerPixel_() == 24){
d0 = d0 + 47;
d0 = d0 - (d0 % 48);
}else{
d0 = (d0 + 15) & ~0x0F;
}
return d0;
}
static int G400MGAMode(void)
{
return ((G400CrtcExtReg_inb(0x03) & 0x80) == 0) ? 0 : 1;
}
void SetG400ExtRegister(CRTCPARAM *cp)
{
int d0;
d0 = 0;
d0 = BitMov(d0, 0, (cp->HTotal >> 3) - 5, 8);
d0 = BitMov(d0, 1, (cp->HBStart >> 3) , 8);
d0 = BitMov(d0, 2, (cp->HSStart >> 3) , 8);
d0 = BitMov(d0, 6, (cp->HBEnd >> 3) , 6);
G400CrtcExtReg_outb(0x01, d0);
d0 = 0;
d0 = BitMov(d0, 0, cp->VTotal - 2, 10);
d0 = BitMov(d0, 1, cp->VTotal - 2, 11);
d0 = BitMov(d0, 2, cp->VDisp - 1, 10);
d0 = BitMov(d0, 3, cp->VBStart , 10);
d0 = BitMov(d0, 4, cp->VBStart , 11);
d0 = BitMov(d0, 5, cp->VSStart , 10);
d0 = BitMov(d0, 6, cp->VSStart , 11);
G400CrtcExtReg_outb(0x02, d0);
SetG400Interlace(cp->interlace, cp->HSStart, cp->HSEnd, cp->HTotal, 100);
}
#define BASE_FREQ 27000.0
static long get_vclk_param(unsigned long vclk, int *N, int *M, int *P, int *S)
{
int d0;
int d1;
double fd;
double dt;
double tempfd;
double tempdt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -