📄 v3drv.c
字号:
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
//#include <math.h>
#include "define.h"
#include "port.h"
#include "mode15k.h"
/* find3dfx.asm */
unsigned int find3dfx(void);
/* 3dfxdrv.c */
int Detect3dfx(void);
void Set3dfxScreenSize(CRTCPARAM *cp);
void Set3dfxDacMode(int flag);
void Set3dfxExtRegister(CRTCPARAM *cp);
WORD Get3dfxBytesPerLine(void);
void Set3dfxBytesPerLine(WORD d0);
void Set3dfxInterlace(int flag);
void Set3dfxVClock(int Num, int DeN, int PS);
long Get3dfxVclkParam(long vclk, int *Num, int *DeN, int *PS);
void Set3dfxDoubleScan(int flag);
void SelectPLL(void);
int GetInterlaceStatus(void);
void SetInterlaceStatus(int d0);
static int InterlaceStatus = 0;
unsigned int _3dfxiobase = 0;
int Detect3dfx(void)
{
_3dfxiobase = find3dfx();
return (_3dfxiobase == 0) ? 0 : 1;
}
void Unlock3dfx(void)
{
DWORD d0;
d0 = _inl(_3dfxiobase + 0x28);
d0 = d0 | 0x40;
_outl(_3dfxiobase + 0x28, d0); // activate vga ext register
d0 = _inl(_3dfxiobase + 0x2C);
d0 = d0 & ~0x1FE00000;
_outl(_3dfxiobase + 0x2C, d0); // unlock vga register
}
int Set3dfx(int xres, int yres, int center_x, int center_y, int h_sync_delay, int h_disp_delay)
{
CRTCPARAM cp;
int Num;
int DeN;
int PS;
DWORD d0;
GetMode15KHz(&cp,xres, yres);
AdjustCenter(&cp, center_x, center_y);
cp.dotclockHz = Get3dfxVclkParam(cp.dotclockHz, &Num, &DeN, &PS);
cp.vert001Hz = CalcVert001Hz(cp.dotclockHz, cp.HTotal,
cp.VTotal, cp.interlace);
cp.horzHz = CalcHorizontalHz(cp.dotclockHz, cp.HTotal);
cp.HBStart = cp.HSStart;
cp.HBEnd = cp.HTotal - 8;
cp.VBStart = cp.VDisp;
cp.VBEnd = cp.VTotal - 1;
Unlock3dfx();
DisableGenerateSignal();
SetGenericVGARegister(&cp, h_sync_delay, h_disp_delay);
Set3dfxExtRegister(&cp);
Set3dfxDoubleScan(cp.doublescan);
Set3dfxInterlace(cp.interlace);
SetHVPolarity(cp.hpolarity, cp.vpolarity);
Set3dfxDacMode(0);
Set3dfxVClock(Num, DeN, PS);
Set3dfxScreenSize(&cp);
EnableGenerateSignal();
return 1;
}
void Set3dfxDacMode(int flag)
{
DWORD d0;
flag = (flag != 0) ? 1 : 0;
d0 = _inl(_3dfxiobase + 0x4C) | flag;
_outl(_3dfxiobase + 0x4C, d0);
}
void Set3dfxScreenSize(CRTCPARAM *cp)
{
int width;
int height;
DWORD d0;
int d1;
width = cp->width;
height = cp->height;
if(cp->doublescan != 0)
height *= 2;
d0 = (unsigned long)width | ((unsigned long)height << 12);
_outl(_3dfxiobase + 0x98, d0);
d0 = _inl(_3dfxiobase + 0x98);
d0 = _inl(_3dfxiobase + 0x5C);
d0 = d0 & ~0x01;
_outl(_3dfxiobase + 0x5C, d0); // off
d1 = 0;
while(d1 < 2048){
d0 = _inl(_3dfxiobase + 0x5C);
d1 += 1;
}
d0 = d0 | 1;
_outl(_3dfxiobase + 0x5C, d0); // on
}
void SelectPLL(void)
{
BYTE d0;
d0 = _inb(0x3CC);
d0 = d0 | 0x0C;
_outb(0x3C2, d0);
}
void Set3dfxExtRegister(CRTCPARAM *cp)
{
int d0;
d0 = 0;
d0 = BitMov(d0, 0, (cp->HTotal >> 3) - 5, 8);
d0 = BitMov(d0, 2, (cp->HDisp >> 3) - 1, 8);
d0 = BitMov(d0, 4, (cp->HBStart >> 3) , 8);
d0 = BitMov(d0, 5, (cp->HBEnd >> 3) , 6);
d0 = BitMov(d0, 6, (cp->HSStart >> 3) , 8);
d0 = BitMov(d0, 7, (cp->HSEnd >> 3) , 5);
SetCrtcReg(0x1A, d0); // ext horz reg
d0 = 0;
d0 = BitMov(d0, 0, cp->VTotal - 2, 10);
d0 = BitMov(d0, 2, cp->VDisp - 1, 10);
d0 = BitMov(d0, 4, cp->VBStart, 10);
d0 = BitMov(d0, 6, cp->VSStart, 10);
SetCrtcReg(0x1B, d0); // ext vert reg
}
void SetInterlaceStatus(int d0)
{
if(d0 != 0) d0 = 1;
InterlaceStatus = d0;
}
int GetInterlaceStatus(void)
{
return InterlaceStatus;
}
WORD Get3dfxBytesPerLine(void)
{
DWORD d0;
d0 = _inl(_3dfxiobase + 0xE8) & 0x7FFF;
if(GetInterlaceStatus() != 0){
d0 = d0 >> 1;
}
return (WORD)d0;
}
void Set3dfxBytesPerLine(WORD d0)
{
if(GetInterlaceStatus() != 0){
d0 = d0 << 1;
}
_outl(_3dfxiobase + 0xE8, (DWORD)d0 & 0x7fff);
}
WORD Adjust3dfxBytesPerLine(WORD bytesperline)
{
return bytesperline;
}
WORD Get3dfxMaxBytesPerLine(void)
{
return 0x7FFF;
}
DWORD Get3dfxScreenStartAddress(void)
{
DWORD d0;
d0 = _inl(_3dfxiobase + 0xE4) & 0xFFFFFF;
return d0;
}
void Set3dfxScreenStartAddress(DWORD d0)
{
_outl(_3dfxiobase + 0xE4, d0 & 0xFFFFFF);
}
static void SetDoubleScan(int flag)
{
if(flag == 0){
SetCrtcReg(0x09, BitMov(GetCrtcReg(0x09), 7, 0, 0));
}else{
SetCrtcReg(0x09, BitMov(GetCrtcReg(0x09), 7, 1, 0));
}
}
void Set3dfxDoubleScan(int flag)
{
DWORD d0;
if(flag == 0)
{
d0 = _inl(_3dfxiobase + 0x5C) & ~0x10;
_outl(_3dfxiobase + 0x5C, d0);
}
else
{
d0 = _inl(_3dfxiobase + 0x5C) | 0x10;
_outl(_3dfxiobase + 0x5C, d0);
}
}
void Set3dfxInterlace(int flag)
{
if(flag == 0){
if(GetInterlaceStatus() != 0){
Set3dfxBytesPerLine( Get3dfxBytesPerLine() / 2 );
SetInterlaceStatus(0);
}
}else{
if(GetInterlaceStatus() == 0){
Set3dfxBytesPerLine( Get3dfxBytesPerLine() * 2 );
SetInterlaceStatus(1);
}
}
}
long Get3dfxVclkParam(long vclk, int *Num, int *DeN, int *PS)
{
double desfreq;
double temp;
double tempdt;
double dt;
int d0;
int d1;
if(vclk > 135000000)
vclk = 135000000;
*PS = 1;
if(vclk >= 75000000)
*PS = 1;
else if(vclk >= 37500000)
*PS = 2;
else if(vclk >= 13500000)
*PS = 4;
else
*PS = 8;
desfreq = vclk * (*PS);
dt = 250000000.0;
*Num = 0;
*DeN = 0;
d0 = 3;
while(d0 < 258){
d1 = 3;
while(d1 < 66){
temp = 14318000 * (double)d0 / d1;
tempdt = desfreq - temp;
if(tempdt < 0) tempdt *= -1;
if(tempdt < dt){
*Num = d0;
*DeN = d1;
dt = tempdt;
}
d1 += 1;
}
d0 += 1;
}
vclk = 14318000 * ((double)(*Num)/(*DeN) / (*PS));
return vclk;
}
void Set3dfxVClock(int Num, int DeN, int PS)
{
DWORD _PS;
DWORD d0;
SelectPLL();
_PS = 0;
while(1){
PS = PS >> 1;
if(PS == 0) break;
_PS += 1;
}
d0 = _PS;
d0 |= (((unsigned long)DeN - 2) & 0x3F) << 2;
d0 |= (((unsigned long)Num - 2) & 0xFF) << 8;
_outl(_3dfxiobase + 0x40, d0);
}
// VGA modes
void Set3dfxVGA(int x, int y, int center_x, int center_y, int h_sync_delay, int h_disp_delay)
{
CRTCPARAM cp;
int Num;
int DeN;
int PS;
GetMode15KHz(&cp, x, y);
AdjustCenter(&cp, center_x, center_y);
cp.dotclockHz = Get3dfxVclkParam(cp.dotclockHz, &Num, &DeN, &PS);
DisableGenerateSignal();
Set3dfxVClock(Num, DeN, PS);
SetSeqDiv(1);
SetGenericVGARegister(&cp, h_sync_delay, h_disp_delay);
Set3dfxDoubleScan(cp.doublescan);
SetDoubleScan(cp.doublescan);
SetHVPolarity(cp.hpolarity, cp.vpolarity);
if(cp.interlace != 0)
SetVGABytesPerLine(GetVGABytesPerLine() * 2);
SetTextWidth(8);
EnableGenerateSignal();
}
void Set3dfxText40x25(int center_x, int center_y, int h_sync_delay, int h_disp_delay)
{
CRTCPARAM cp;
int Num;
int DeN;
int PS;
BYTE d0;
GetMode15KHz(&cp, 320, 200);
AdjustCenter(&cp, center_x, center_y);
cp.dotclockHz = Get3dfxVclkParam(cp.dotclockHz, &Num, &DeN, &PS);
DisableGenerateSignal();
Set3dfxVClock(Num, DeN, PS);
SetSeqDiv(1);
SetGenericVGARegister(&cp, h_sync_delay, h_disp_delay);
SetDoubleScan(cp.doublescan);
SetHVPolarity(cp.hpolarity, cp.vpolarity);
if(cp.interlace != 0)
SetVGABytesPerLine(GetVGABytesPerLine() * 2);
SetTextHeight(8);
SetTextWidth(8);
EnableGenerateSignal();
}
void Set3dfxText80x25(int center_x, int center_y, int h_sync_delay, int h_disp_delay)
{
CRTCPARAM cp;
int Num;
int DeN;
int PS;
BYTE d0;
long min14;
long max14;
GetMode15KHz(&cp, 640, 200);
AdjustCenter(&cp, center_x, center_y);
cp.dotclockHz = Get3dfxVclkParam(cp.dotclockHz, &Num, &DeN, &PS);
DisableGenerateSignal();
min14 = 14000000; /* 14.0MHz */
max14 = 14300000; /* 14.3MHz */
if(min14 <= cp.dotclockHz && cp.dotclockHz <= max14){
Set14MHz(); /* set 14.161MHz */
}else{
Set3dfxVClock(Num, DeN, PS);
SetSeqDiv(1);
}
SetGenericVGARegister(&cp, h_sync_delay, h_disp_delay);
SetDoubleScan(cp.doublescan);
SetHVPolarity(cp.hpolarity, cp.vpolarity);
if(cp.interlace != 0)
SetVGABytesPerLine(GetVGABytesPerLine() * 2);
SetTextHeight(8);
SetTextWidth(8);
EnableGenerateSignal();
}
void Set3dfxModeX(int x, int y, int center_x, int center_y, int h_sync_delay, int h_disp_delay)
{
CRTCPARAM cp;
int Num;
int DeN;
int PS;
if(GetMode15KHz(&cp, x, y) == 0)
GetMode15KHz(&cp, 640, 200);
AdjustCenter(&cp, center_x, center_y);
cp.dotclockHz = Get3dfxVclkParam(cp.dotclockHz, &Num, &DeN, &PS);
DisableGenerateSignal();
Set3dfxVClock(Num, DeN, PS);
SetSeqDiv(1);
SetGenericVGARegister(&cp, h_sync_delay, h_disp_delay);
Set3dfxDoubleScan(cp.doublescan);
SetDoubleScan(cp.doublescan);
SetHVPolarity(cp.hpolarity, cp.vpolarity);
if(cp.interlace != 0)
SetVGABytesPerLine(GetVGABytesPerLine() * 2);
SetTextWidth(8);
EnableGenerateSignal();
SetTextHeight(1);
}
/********************************************************************/
int Detect15KHz(void)
{
return Detect3dfx();
}
int SetSVGA(int xres, int yres, int center_x, int center_y, int hsyncdelay, int hdispdelay)
{
return Set3dfx(xres, yres, center_x, center_y, hsyncdelay, hdispdelay);
}
void SetVGA(int x, int y, int center_x, int center_y, int hsyncdelay, int hdispdelay)
{
Set3dfxVGA(x, y, center_x, center_y, hsyncdelay, hdispdelay);
}
void SetVGAText40x25(int center_x, int center_y, int hsyncdelay, int hdispdelay)
{
Set3dfxText40x25(center_x, center_y, hsyncdelay, hdispdelay);
}
void SetVGAText80x25(int center_x, int center_y, int hsyncdelay, int hdispdelay)
{
SetInterlaceStatus(0);
Set3dfxText80x25(center_x, center_y, hsyncdelay, hdispdelay);
}
void SetModeX(int center_x, int center_y, int hsyncdelay, int hdispdelay)
{
int x;
int y;
Copy_VGACRTC_to_VIDEOMODE(&x,&y);
Set3dfxModeX(x, y, center_x, center_y, hsyncdelay, hdispdelay);
}
WORD AdjustBytesPerLine(WORD bytesperline)
{
return Adjust3dfxBytesPerLine(bytesperline);
}
WORD GetBytesPerLine(void)
{
return Get3dfxBytesPerLine();
}
void SetBytesPerLine(WORD bytesperline)
{
Set3dfxBytesPerLine(bytesperline);
}
DWORD GetScreenStartAddress(void)
{
return Get3dfxScreenStartAddress();
}
void SetScreenStartAddress(DWORD address)
{
Set3dfxScreenStartAddress(address);
}
WORD GetMaxBytesPerLine(void)
{
return Get3dfxMaxBytesPerLine();
}
char NotFound[] = "No Voodoo3/Banshee found!\n";
char* NotFoundMessage(void)
{
return NotFound;
}
WORD GetActualVesaMode(int xres, int yres, int bpp)
{
int mode;
mode = _640x480x8;
if(xres <= 640 && yres <= 480){
if(bpp == 8){
mode = _640x480x8;
}else if(bpp == 16){
mode = _640x480x16;
}else if(bpp == 24){
mode = _640x480_TC;
}
}else if(xres <= 1024 && yres <= 768){
if(bpp == 8){
mode = _1024x768x8;
}else if(bpp == 16){
mode = _1024x768x16;
}else if(bpp == 24){
mode = _1024x768_TC;
}
}else{
if(bpp == 8){
mode = _1280x1024x8;
}else if(bpp == 16){
mode = _1280x1024x16;
}else if(bpp == 24){
mode = _1280x1024_TC;
}
}
return mode;
}
int GetAvailableBpp(int bpp)
{
int result;
result = 8;
if(bpp == 8){
result = 8;
}else if(bpp == 15){
result = 16;
}else if(bpp == 16){
result = 16;
#if 0
}else if(bpp == 24){
result = 24;
}else if(bpp == 32){
result = 24;
#endif
}
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -