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

📄 g4drv.c

📁 用来将电脑连接到电视荧幕, 并以15Khz输出的源码, 请只用在支援15Khz的荧幕上, 以免伤害荧幕
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -