#include<stdio.h>
#include<conio.h>

/*
Title: Vpatch
Written By: Kevin Moonlight
Date: 2020/09/25


This is a proof of concept program.  Use it absolutely at your own risk!

*/

void vlsi_set(char index, char value) {
	outportb(0xEC,index);
	delay(100);
	outportb(0xED,value);
}
char vlsi_get(char index) {
	outportb(0xEC,index);
	delay(100);
	return inportb(0xED);
}

#define XR6  0xA9C
#define XR19 0xAE6
#define XR1A 0xAE8
#define XR1B 0xAEA
#define XR50 0xAF6
#define XR51 0xAA4
#define XR52 0xA9A
#define XR53 0xA92
#define XR54 0xAA6
#define XR4F 0xAA0
#define XR64 0xAFA
#define XR65 0xAFC
#define XR66 0xAFE
#define XR67 0xB00
#define XR6F 0xAB8


void reboot(void) {
	void (far* r)(void) = (void (far*)(void))0xF000FFF0L;
	unsigned char far *rombios_data = (char far*)0x00400000L;
	rombios_data[0x72]=0x34;
	rombios_data[0x73]=0x12;
	(*r)();


}

void vabort(void) {
	printf("Unexpected or already patched video bios detected, aborting.\n");
	exit();
}

void main(void) {
	unsigned char far *videobios = (char far*)0xC0000000L;
	char revert_f;

	printf("Vpatch 0.1\n");

	if(videobios[XR6] != 0xC2) vabort();
	if(videobios[XR19] != 0x57) vabort();
	if(videobios[XR1A] != 0x19) vabort();
	if(videobios[XR1B] != 0x59) vabort();
	if(videobios[XR50] != 0x15) vabort();
	if((videobios[XR51] & 0xFB) != 0x63) vabort();
	if(videobios[XR52] != 0x44) vabort();
	if(videobios[XR53] != 0x00) vabort();
	if(videobios[XR54] != 0x3a) vabort();
	if(videobios[XR4F] != 0x04) vabort();
	if(videobios[XR64] != 0xe4) vabort();
	if(videobios[XR65] != 0x07) vabort();
	if(videobios[XR66] != 0xe0) vabort();
	if(videobios[XR67] != 0x01) vabort();
	if(videobios[XR6F] != 0x1B) vabort();

	//Change C0000 Access to Read/Write System Board
	revert_f=vlsi_get(0xF);//save to revert
	vlsi_set(0xF,revert_f | 0x3);

	videobios[XR6]=0xC0;
	videobios[XR19] = 0x56;
	videobios[XR1A] = 0x13;
	videobios[XR1B] = 0x5F;
	videobios[XR50] = 0x00;
	videobios[XR51] = (videobios[XR51] & 0x4) | 0xC0;
	videobios[XR52] = 0x42;
	videobios[XR53] = 0x1C;
	videobios[XR54] = 0xC0;
	videobios[XR4F] = 0xC5;
	videobios[XR64] = 0x01;
	videobios[XR65] = 0x26;
	videobios[XR66] = 0xDF;
	videobios[XR67] = 0x05;
	videobios[XR6F] = 0x00;
	//Restore previous C0000 Access
	vlsi_set(0xF,revert_f);
	reboot();

}

