aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRichard Weick <[email protected]>2023-09-07 21:50:06 -0500
committerGitHub <[email protected]>2023-09-07 21:50:06 -0500
commitb748faecde8bb1c90b545b0b29b735ac65888cf5 (patch)
tree97798b762fdc87940ab18454d346b64ce35967b0
parent7cf03d3542d7df10b69dfb0097e13ba350f839c7 (diff)
downloadcartreader-b748faecde8bb1c90b545b0b29b735ac65888cf5.tar.gz
cartreader-b748faecde8bb1c90b545b0b29b735ac65888cf5.zip
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.
-rw-r--r--Cart_Reader/N64.ino294
1 files changed, 223 insertions, 71 deletions
diff --git a/Cart_Reader/N64.ino b/Cart_Reader/N64.ino
index 9116927..ff35504 100644
--- a/Cart_Reader/N64.ino
+++ b/Cart_Reader/N64.ino
@@ -4050,7 +4050,9 @@ unsigned long verifyFlashrom_N64() {
N64 Gameshark Flash Functions
*****************************************/
void flashGameshark_N64() {
+ int flashSize = 0;
// Check flashrom ID's
+ unlockGSAddressRanges();
idGameshark_N64();
// Check for SST 29LE010 (0808)/SST 28LF040 (0404)/AMTEL AT29LV010A (3535)/SST 29EE010 (0707)
@@ -4078,7 +4080,6 @@ void flashGameshark_N64() {
filePath[0] = '\0';
sd.chdir("/");
fileBrowser(F("Select z64 file"));
- display_Clear();
display_Update();
// Create filepath
@@ -4088,18 +4089,25 @@ void flashGameshark_N64() {
if (myFile.open(filePath, O_READ)) {
// Get rom size from file
fileSize = myFile.fileSize();
+ display_Clear();
print_Msg(F("File size: "));
print_Msg(fileSize / 1024);
- println_Msg(F("KB"));
+ println_Msg(F(" KB"));
display_Update();
- // Compare file size to flashrom size
- if (fileSize > 262144) {
+ // Compare file size to flashrom size for 1 Mbit eeproms
+ 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);
}
// SST 29LE010, chip erase not needed as this eeprom automaticly erases during the write cycle
eraseGameshark_N64();
+ blankCheck_N64();
// Write flashrom
print_Msg(F("Writing "));
@@ -4116,14 +4124,19 @@ void flashGameshark_N64() {
writeErrors = verifyGameshark_N64();
if (writeErrors == 0) {
- println_Msg(F("OK"));
+ display_Clear();
+ display_Update();
+ println_Msg(F("Verfied OK"));
println_Msg(F(""));
println_Msg(F("Turn Cart Reader off now"));
display_Update();
while (1)
;
} else {
- print_Msg(writeErrors);
+ display_Clear();
+ display_Update();
+ println_Msg(F("Verification Failed"));
+ println_Msg(writeErrors);
print_Msg(F(" bytes "));
print_Error(did_not_verify_STR);
}
@@ -4131,12 +4144,6 @@ void flashGameshark_N64() {
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
print_STR(press_button_STR, 1);
@@ -4146,37 +4153,72 @@ void flashGameshark_N64() {
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)
void idGameshark_N64() {
+ flashid = 0x0;
//Send flashrom ID command
- setAddress_N64(romBase + 0xAAAA);
+ setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
- setAddress_N64(romBase + 0x5554);
+ setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
- setAddress_N64(romBase + 0xAAAA);
+ setAddress_N64(0x1EF0AAA8);
writeWord_N64(0x9090);
- setAddress_N64(romBase);
+ setAddress_N64(0x1EC00000);
// Read 1 byte vendor ID
readWord_N64();
// Read 2 bytes flashrom ID
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);
// Reset flashrom
resetGameshark_N64();
}
-//Reset ST29LE010
void resetGameshark_N64() {
- // Send reset Command
- setAddress_N64(romBase + 0xAAAA);
- writeWord_N64(0xAAAA);
- setAddress_N64(romBase + 0x5554);
- writeWord_N64(0x5555);
- setAddress_N64(romBase + 0xAAAA);
- writeWord_N64(0xF0F0);
- delay(100);
+ if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
+ // Send reset command for SST 29LE010 / AMTEL AT29LV010A / SST 29EE010
+ setAddress_N64(0x1EF0AAA8);
+ writeWord_N64(0xAAAA);
+ setAddress_N64(0x1EE05554);
+ writeWord_N64(0x5555);
+ setAddress_N64(0x1EF0AAA8);
+ 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
@@ -4203,7 +4245,7 @@ void backupGameshark_N64() {
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
if (currByte % 16384 == 0)
blinkLED();
@@ -4227,55 +4269,169 @@ void backupGameshark_N64() {
myFile.close();
}
-// Send chip erase to the two SST29LE010 inside the Gameshark
void eraseGameshark_N64() {
println_Msg(F("Erasing..."));
display_Update();
- //Sending erase command according to datasheet
- setAddress_N64(romBase + 0xAAAA);
- writeWord_N64(0xAAAA);
- setAddress_N64(romBase + 0x5554);
- writeWord_N64(0x5555);
- setAddress_N64(romBase + 0xAAAA);
- writeWord_N64(0x8080);
- setAddress_N64(romBase + 0xAAAA);
- writeWord_N64(0xAAAA);
- setAddress_N64(romBase + 0x5554);
- writeWord_N64(0x5555);
- setAddress_N64(romBase + 0xAAAA);
- writeWord_N64(0x1010);
+ // Send chip erase to SST 29LE010 / AMTEL AT29LV010A / SST 29EE010
+ if (flashid == 0x0808 || flashid == 0x3535 || flashid == 0x0707) {
+ setAddress_N64(0x1EF0AAA8);
+ writeWord_N64(0xAAAA);
+ setAddress_N64(0x1EE05554);
+ writeWord_N64(0x5555);
+ setAddress_N64(0x1EF0AAA8);
+ writeWord_N64(0x8080);
+ setAddress_N64(0x1EF0AAA8);
+ writeWord_N64(0xAAAA);
+ setAddress_N64(0x1EE05554);
+ writeWord_N64(0x5555);
+ setAddress_N64(0x1EF0AAA8);
+ writeWord_N64(0x1010);
- delay(20);
-}
+ delay(20);
+ }
-// Write Gameshark with 2x SST29LE010 Eeproms
-void writeGameshark_N64() {
- // Each 29LE010 has 1024 pages, each 128 bytes in size
- 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();
+ 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);
- //Send page write command to both flashroms
- setAddress_N64(romBase + 0xAAAA);
+ //Erase flash
+ setAddress_N64(0x1EF0AAA8);
writeWord_N64(0xAAAA);
- setAddress_N64(romBase + 0x5554);
+ setAddress_N64(0x1EE05554);
writeWord_N64(0x5555);
- setAddress_N64(romBase + 0xAAAA);
- 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 + 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);
+ setAddress_N64(0x1EF0AAA8);
+ writeWord_N64(0x3030);
+ setAddress_N64(0x1EF0AAA8);
+ writeWord_N64(0x3030);
+ delay(1000);
+ }
+}
+
+void blankCheck_N64() {
+ // Blankcheck
+ println_Msg(F("Blankcheck..."));
+ display_Update();
+
+ for (unsigned long currSector = 0; currSector < flashSize; currSector += 131072) {
+ // Blink led
+ blinkLED();
+ for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) {
+ for (int currByte = 0; currByte < 512; currByte += 2) {
+ // Read flash
+ setAddress_N64(romBase + 0xEC00000 + currSector + currSdBuffer + currByte);
+ // Compare both
+ if (readWord_N64() != 0xFFFF) {
+ println_Msg(F("Not empty"));
+ print_FatalError(F("Erase failed"));
+ }
+ }
+ }
+ }
+}
+
+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();
+ }
}
- delay(30);
+
+ //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
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
// Read flash
- setAddress_N64(romBase + 0xC00000 + currSector + currSdBuffer + currByte);
+ setAddress_N64(romBase + 0xEC00000 + currSector + currSdBuffer + currByte);
// Compare both
if (readWord_N64() != currWord) {
- if ((flashid == 0x0808) && (currSector + currSdBuffer + currByte > 0x3F) && (currSector + currSdBuffer + currByte < 0x1080)) {
- // Gameshark maps this area to the bootcode of the plugged in cartridge
- } else {
- writeErrors++;
- }
+ writeErrors++;
}
}
}