⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v3drv.c

📁 用来将电脑连接到电视荧幕, 并以15Khz输出的源码, 请只用在支援15Khz的荧幕上, 以免伤害荧幕
💻 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 + -