mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-14 17:05:08 +01:00
Update N64.ino
This completes the N64 Gameshark functions. It adds the command to enable CPLD address ranges of 0x1EEx_xxxx, 0x1EFx_xxxx, and 0x1ECx_xxxx which are necessary to program the SST 28LF040 eeprom. This also adds full support for the SST 28LF040 eeproms.
This commit is contained in:
parent
7cf03d3542
commit
b748faecde
@ -4050,7 +4050,9 @@ unsigned long verifyFlashrom_N64() {
|
|||||||
N64 Gameshark Flash Functions
|
N64 Gameshark Flash Functions
|
||||||
*****************************************/
|
*****************************************/
|
||||||
void flashGameshark_N64() {
|
void flashGameshark_N64() {
|
||||||
|
int flashSize = 0;
|
||||||
// Check flashrom ID's
|
// Check flashrom ID's
|
||||||
|
unlockGSAddressRanges();
|
||||||
idGameshark_N64();
|
idGameshark_N64();
|
||||||
|
|
||||||
// Check for SST 29LE010 (0808)/SST 28LF040 (0404)/AMTEL AT29LV010A (3535)/SST 29EE010 (0707)
|
// Check for SST 29LE010 (0808)/SST 28LF040 (0404)/AMTEL AT29LV010A (3535)/SST 29EE010 (0707)
|
||||||
@ -4078,7 +4080,6 @@ void flashGameshark_N64() {
|
|||||||
filePath[0] = '\0';
|
filePath[0] = '\0';
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
fileBrowser(F("Select z64 file"));
|
fileBrowser(F("Select z64 file"));
|
||||||
display_Clear();
|
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
// Create filepath
|
// Create filepath
|
||||||
@ -4088,18 +4089,25 @@ void flashGameshark_N64() {
|
|||||||
if (myFile.open(filePath, O_READ)) {
|
if (myFile.open(filePath, O_READ)) {
|
||||||
// Get rom size from file
|
// Get rom size from file
|
||||||
fileSize = myFile.fileSize();
|
fileSize = myFile.fileSize();
|
||||||
|
display_Clear();
|
||||||
print_Msg(F("File size: "));
|
print_Msg(F("File size: "));
|
||||||
print_Msg(fileSize / 1024);
|
print_Msg(fileSize / 1024);
|
||||||
println_Msg(F("KB"));
|
println_Msg(F(" KB"));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
// Compare file size to flashrom size
|
// Compare file size to flashrom size for 1 Mbit eeproms
|
||||||
if (fileSize > 262144) {
|
if (fileSize > 262144 && (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707)) {
|
||||||
|
print_FatalError(file_too_big_STR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare file size to flashrom size for 1 Mbit eeproms
|
||||||
|
if (fileSize > 1048576 && flashid == 0x0404) {
|
||||||
print_FatalError(file_too_big_STR);
|
print_FatalError(file_too_big_STR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SST 29LE010, chip erase not needed as this eeprom automaticly erases during the write cycle
|
// SST 29LE010, chip erase not needed as this eeprom automaticly erases during the write cycle
|
||||||
eraseGameshark_N64();
|
eraseGameshark_N64();
|
||||||
|
blankCheck_N64();
|
||||||
|
|
||||||
// Write flashrom
|
// Write flashrom
|
||||||
print_Msg(F("Writing "));
|
print_Msg(F("Writing "));
|
||||||
@ -4116,14 +4124,19 @@ void flashGameshark_N64() {
|
|||||||
writeErrors = verifyGameshark_N64();
|
writeErrors = verifyGameshark_N64();
|
||||||
|
|
||||||
if (writeErrors == 0) {
|
if (writeErrors == 0) {
|
||||||
println_Msg(F("OK"));
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
println_Msg(F("Verfied OK"));
|
||||||
println_Msg(F(""));
|
println_Msg(F(""));
|
||||||
println_Msg(F("Turn Cart Reader off now"));
|
println_Msg(F("Turn Cart Reader off now"));
|
||||||
display_Update();
|
display_Update();
|
||||||
while (1)
|
while (1)
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
print_Msg(writeErrors);
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
println_Msg(F("Verification Failed"));
|
||||||
|
println_Msg(writeErrors);
|
||||||
print_Msg(F(" bytes "));
|
print_Msg(F(" bytes "));
|
||||||
print_Error(did_not_verify_STR);
|
print_Error(did_not_verify_STR);
|
||||||
}
|
}
|
||||||
@ -4131,12 +4144,6 @@ void flashGameshark_N64() {
|
|||||||
print_Error(F("Can't open file"));
|
print_Error(F("Can't open file"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the ID is unknown show error message
|
|
||||||
else {
|
|
||||||
print_Msg(F("ID: "));
|
|
||||||
println_Msg(flashid_str);
|
|
||||||
print_Error(F("Unknown flashrom"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints string out of the common strings array either with or without newline
|
// Prints string out of the common strings array either with or without newline
|
||||||
print_STR(press_button_STR, 1);
|
print_STR(press_button_STR, 1);
|
||||||
@ -4146,37 +4153,72 @@ void flashGameshark_N64() {
|
|||||||
display_Update();
|
display_Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unlockGSAddressRanges() {
|
||||||
|
// This enables using the 0x1EEx_xxxx, 0x1EFx_xxxx, and 0x1ECx_xxxx address ranges, necessary for writing to all supported chips
|
||||||
|
setAddress_N64(0x10400400);
|
||||||
|
writeWord_N64(0x1E);
|
||||||
|
writeWord_N64(0x1E);
|
||||||
|
}
|
||||||
|
|
||||||
//Test for SST 29LE010 or SST 28LF040 (0404) or AMTEL AT29LV010A (3535) or SST 29EE010 (0707)
|
//Test for SST 29LE010 or SST 28LF040 (0404) or AMTEL AT29LV010A (3535) or SST 29EE010 (0707)
|
||||||
void idGameshark_N64() {
|
void idGameshark_N64() {
|
||||||
|
flashid = 0x0;
|
||||||
//Send flashrom ID command
|
//Send flashrom ID command
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
writeWord_N64(0xAAAA);
|
writeWord_N64(0xAAAA);
|
||||||
setAddress_N64(romBase + 0x5554);
|
setAddress_N64(0x1EE05554);
|
||||||
writeWord_N64(0x5555);
|
writeWord_N64(0x5555);
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
writeWord_N64(0x9090);
|
writeWord_N64(0x9090);
|
||||||
|
|
||||||
setAddress_N64(romBase);
|
setAddress_N64(0x1EC00000);
|
||||||
// Read 1 byte vendor ID
|
// Read 1 byte vendor ID
|
||||||
readWord_N64();
|
readWord_N64();
|
||||||
// Read 2 bytes flashrom ID
|
// Read 2 bytes flashrom ID
|
||||||
flashid = readWord_N64();
|
flashid = readWord_N64();
|
||||||
|
|
||||||
|
if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
|
||||||
|
flashSize = 262144;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flashid == 0x0404) {
|
||||||
|
//Set SST 28LF040 flashrom size
|
||||||
|
flashSize = 1048574;
|
||||||
|
if (flashid != 0x0404) {
|
||||||
|
println_Msg(F("Check cart connection"));
|
||||||
|
println_Msg(F("Unknown Flash ID"));
|
||||||
|
sprintf(flashid_str, "%04X", flashid);
|
||||||
|
print_STR(press_button_STR, 1);
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
mainMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
sprintf(flashid_str, "%04X", flashid);
|
sprintf(flashid_str, "%04X", flashid);
|
||||||
// Reset flashrom
|
// Reset flashrom
|
||||||
resetGameshark_N64();
|
resetGameshark_N64();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Reset ST29LE010
|
|
||||||
void resetGameshark_N64() {
|
void resetGameshark_N64() {
|
||||||
// Send reset Command
|
if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
// Send reset command for SST 29LE010 / AMTEL AT29LV010A / SST 29EE010
|
||||||
writeWord_N64(0xAAAA);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
setAddress_N64(romBase + 0x5554);
|
writeWord_N64(0xAAAA);
|
||||||
writeWord_N64(0x5555);
|
setAddress_N64(0x1EE05554);
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
writeWord_N64(0x5555);
|
||||||
writeWord_N64(0xF0F0);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
delay(100);
|
writeWord_N64(0xF0F0);
|
||||||
|
delay(100);
|
||||||
|
} else if (flashid == 0x0404) {
|
||||||
|
// Send reset command for SST 28LF040
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(0x1EE05554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0xFFFF);
|
||||||
|
delay(300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read rom and save to the SD card
|
// Read rom and save to the SD card
|
||||||
@ -4203,7 +4245,7 @@ void backupGameshark_N64() {
|
|||||||
print_FatalError(sd_error_STR);
|
print_FatalError(sd_error_STR);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned long currByte = romBase + 0xC00000; currByte < (romBase + 0xC00000 + 262144); currByte += 512) {
|
for (unsigned long currByte = romBase + 0xEC00000; currByte < (romBase + 0xEC00000 + flashSize); currByte += 512) {
|
||||||
// Blink led
|
// Blink led
|
||||||
if (currByte % 16384 == 0)
|
if (currByte % 16384 == 0)
|
||||||
blinkLED();
|
blinkLED();
|
||||||
@ -4227,55 +4269,169 @@ void backupGameshark_N64() {
|
|||||||
myFile.close();
|
myFile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send chip erase to the two SST29LE010 inside the Gameshark
|
|
||||||
void eraseGameshark_N64() {
|
void eraseGameshark_N64() {
|
||||||
println_Msg(F("Erasing..."));
|
println_Msg(F("Erasing..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
//Sending erase command according to datasheet
|
// Send chip erase to SST 29LE010 / AMTEL AT29LV010A / SST 29EE010
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
|
||||||
writeWord_N64(0xAAAA);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
setAddress_N64(romBase + 0x5554);
|
writeWord_N64(0xAAAA);
|
||||||
writeWord_N64(0x5555);
|
setAddress_N64(0x1EE05554);
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
writeWord_N64(0x5555);
|
||||||
writeWord_N64(0x8080);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
writeWord_N64(0x8080);
|
||||||
writeWord_N64(0xAAAA);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
setAddress_N64(romBase + 0x5554);
|
writeWord_N64(0xAAAA);
|
||||||
writeWord_N64(0x5555);
|
setAddress_N64(0x1EE05554);
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
writeWord_N64(0x5555);
|
||||||
writeWord_N64(0x1010);
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0x1010);
|
||||||
|
|
||||||
delay(20);
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flashid == 0x0404) {
|
||||||
|
//Unprotect flash
|
||||||
|
setAddress_N64(0x1EF03044);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE03040);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE03044);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE00830);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EF00834);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EF00830);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE00834);
|
||||||
|
readWord_N64();
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
//Erase flash
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(0x1EE05554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0x3030);
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0x3030);
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write Gameshark with 2x SST29LE010 Eeproms
|
void blankCheck_N64() {
|
||||||
void writeGameshark_N64() {
|
// Blankcheck
|
||||||
// Each 29LE010 has 1024 pages, each 128 bytes in size
|
println_Msg(F("Blankcheck..."));
|
||||||
for (unsigned long currPage = 0; currPage < fileSize / 2; currPage += 128) {
|
display_Update();
|
||||||
// Fill SD buffer with twice the amount since we flash 2 chips
|
|
||||||
myFile.read(sdBuffer, 256);
|
|
||||||
// Blink led
|
|
||||||
blinkLED();
|
|
||||||
|
|
||||||
//Send page write command to both flashroms
|
for (unsigned long currSector = 0; currSector < flashSize; currSector += 131072) {
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
// Blink led
|
||||||
writeWord_N64(0xAAAA);
|
blinkLED();
|
||||||
setAddress_N64(romBase + 0x5554);
|
for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) {
|
||||||
writeWord_N64(0x5555);
|
for (int currByte = 0; currByte < 512; currByte += 2) {
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
// Read flash
|
||||||
writeWord_N64(0xA0A0);
|
setAddress_N64(romBase + 0xEC00000 + currSector + currSdBuffer + currByte);
|
||||||
|
// Compare both
|
||||||
// Write 1 page each, one flashrom gets the low byte, the other the high byte.
|
if (readWord_N64() != 0xFFFF) {
|
||||||
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
|
println_Msg(F("Not empty"));
|
||||||
// Set address
|
print_FatalError(F("Erase failed"));
|
||||||
setAddress_N64(romBase + 0xC00000 + (currPage * 2) + currByte);
|
}
|
||||||
// Join two bytes into one word
|
}
|
||||||
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
|
}
|
||||||
// Send byte data
|
|
||||||
writeWord_N64(currWord);
|
|
||||||
}
|
}
|
||||||
delay(30);
|
}
|
||||||
|
|
||||||
|
void writeGameshark_N64() {
|
||||||
|
// Write Gameshark with 2x SST 29LE010 / AMTEL AT29LV010A / SST 29EE010 Eeproms
|
||||||
|
if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
|
||||||
|
// Each 29LE010 has 1024 pages, each 128 bytes in size
|
||||||
|
myFile.seek(0);
|
||||||
|
for (unsigned long currPage = 0; currPage < fileSize / 2; currPage += 128) {
|
||||||
|
// Fill SD buffer with twice the amount since we flash 2 chips
|
||||||
|
myFile.read(sdBuffer, 256);
|
||||||
|
// Blink led
|
||||||
|
blinkLED();
|
||||||
|
|
||||||
|
//Send page write command to both flashroms
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(0x1EE05554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0xA0A0);
|
||||||
|
|
||||||
|
// Write 1 page each, one flashrom gets the low byte, the other the high byte.
|
||||||
|
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
|
||||||
|
// Set address
|
||||||
|
setAddress_N64(romBase + 0xEC00000 + (currPage * 2) + currByte);
|
||||||
|
// Join two bytes into one word
|
||||||
|
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
|
||||||
|
// Send byte data
|
||||||
|
writeWord_N64(currWord);
|
||||||
|
}
|
||||||
|
delay(30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flashid == 0x0404) {
|
||||||
|
// Write Gameshark with 2x SST 28LF040
|
||||||
|
//Initialize progress bar
|
||||||
|
uint32_t processedProgressBar = 0;
|
||||||
|
uint32_t totalProgressBar = (uint32_t)(fileSize);
|
||||||
|
draw_progressbar(0, totalProgressBar);
|
||||||
|
bool toggle = true;
|
||||||
|
myFile.seek(0);
|
||||||
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += 16384) {
|
||||||
|
// Blink led
|
||||||
|
blinkLED();
|
||||||
|
for (unsigned long currSdBuffer = 0; currSdBuffer < 16384; currSdBuffer += 256) {
|
||||||
|
// Fill SD buffer
|
||||||
|
myFile.read(sdBuffer, 256);
|
||||||
|
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
|
||||||
|
|
||||||
|
// Send byte program command
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(0x1EE05554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(0x1EF0AAA8);
|
||||||
|
writeWord_N64(0x1010);
|
||||||
|
|
||||||
|
// Set address
|
||||||
|
setAddress_N64(romBase + 0xEC00000 + currSector + currSdBuffer + currByte);
|
||||||
|
|
||||||
|
// Join two bytes into one word
|
||||||
|
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
|
||||||
|
|
||||||
|
// Send byte data
|
||||||
|
writeWord_N64(currWord);
|
||||||
|
delayMicroseconds(60);
|
||||||
|
}
|
||||||
|
processedProgressBar += 256;
|
||||||
|
draw_progressbar(processedProgressBar, totalProgressBar);
|
||||||
|
blinkLED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Protect flash
|
||||||
|
setAddress_N64(0x1EF03044);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE03040);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE03044);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE00830);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EF00834);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EF00830);
|
||||||
|
readWord_N64();
|
||||||
|
setAddress_N64(0x1EE00814);
|
||||||
|
readWord_N64();
|
||||||
|
delay(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4294,14 +4450,10 @@ unsigned long verifyGameshark_N64() {
|
|||||||
// Join two bytes into one word
|
// Join two bytes into one word
|
||||||
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
|
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
|
||||||
// Read flash
|
// Read flash
|
||||||
setAddress_N64(romBase + 0xC00000 + currSector + currSdBuffer + currByte);
|
setAddress_N64(romBase + 0xEC00000 + currSector + currSdBuffer + currByte);
|
||||||
// Compare both
|
// Compare both
|
||||||
if (readWord_N64() != currWord) {
|
if (readWord_N64() != currWord) {
|
||||||
if ((flashid == 0x0808) && (currSector + currSdBuffer + currByte > 0x3F) && (currSector + currSdBuffer + currByte < 0x1080)) {
|
writeErrors++;
|
||||||
// Gameshark maps this area to the bootcode of the plugged in cartridge
|
|
||||||
} else {
|
|
||||||
writeErrors++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user