aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRichard Weick <[email protected]>2023-09-10 22:04:31 -0500
committerGitHub <[email protected]>2023-09-10 22:04:31 -0500
commit3a30c0f5eda663dc706c1ca934b2fb477c1ced65 (patch)
tree621262d60ad7cda53627d74f850b4919cf856c09
parent996d8f77c88c65af2b9239dea17688c87f7b5360 (diff)
parentbc62414c59f927a10e7c96242ff15a19fc8a9718 (diff)
downloadcartreader-3a30c0f5eda663dc706c1ca934b2fb477c1ced65.tar.gz
cartreader-3a30c0f5eda663dc706c1ca934b2fb477c1ced65.zip
Merge pull request #847 from RWeick/master
Update N64.ino to add full dump and programming support for the Xplorer 64. Firmware must be unscrambled in order to be written to the Xplorer 64 with this function. Firmware dumped via this function are unscrambled. Firmware extracted directly from the eeproms in an eeprom programmer are scrambled and must be unscrambled before being used with this.
-rw-r--r--Cart_Reader/N64.ino301
1 files changed, 298 insertions, 3 deletions
diff --git a/Cart_Reader/N64.ino b/Cart_Reader/N64.ino
index d3e1310..8627793 100644
--- a/Cart_Reader/N64.ino
+++ b/Cart_Reader/N64.ino
@@ -55,7 +55,7 @@ static const char n64MenuItem1[] PROGMEM = "Game Cartridge";
static const char n64MenuItem2[] PROGMEM = "Controller";
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
static const char n64MenuItem4[] PROGMEM = "Flash Gameshark";
-static const char n64MenuItem5[] PROGMEM = "Backup Xplorer 64";
+static const char n64MenuItem5[] PROGMEM = "Flash Xplorer 64";
//static const char n64MenuItem6[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsN64[] PROGMEM = { n64MenuItem1, n64MenuItem2, n64MenuItem3, n64MenuItem4, n64MenuItem5, string_reset2 };
@@ -160,7 +160,7 @@ void n64Menu() {
display_Clear();
display_Update();
setup_N64_Cart();
- backupXplorer_N64();
+ flashXplorer_N64();
mode = mode_N64_Cart;
print_STR(press_button_STR, 1);
display_Update();
@@ -4476,11 +4476,139 @@ unsigned long verifyGameshark_N64() {
/******************************************
XPLORER 64 Functions
*****************************************/
+void flashXplorer_N64() {
+ // Check flashrom ID's
+ idXplorer_N64();
+
+ if (flashid == 0x0808) {
+ backupXplorer_N64();
+ println_Msg("");
+ println_Msg(F("This will erase your"));
+ println_Msg(F("Xplorer64 cartridge"));
+ println_Msg(F("Attention: Use 3.3V!"));
+ println_Msg(F("Power OFF if Unsure!"));
+ // Prints string out of the common strings array either with or without newline
+ print_STR(press_button_STR, 1);
+ display_Update();
+ wait();
+
+ // Launch file browser
+ filePath[0] = '\0';
+ sd.chdir("/");
+ fileBrowser(F("Select XP64 rom file"));
+ display_Update();
+
+ // Create filepath
+ sprintf(filePath, "%s/%s", filePath, fileName);
+
+ // Open file on sd card
+ 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"));
+ display_Update();
+
+ // Compare file size to flashrom size
+ if (fileSize > 262144) {
+ print_FatalError(file_too_big_STR);
+ }
+
+ // SST 29LE010, chip erase not needed as this eeprom automaticly erases during the write cycle
+ eraseXplorer_N64();
+ blankCheck_XP64();
+
+ // Write flashrom
+ display_Clear();
+ print_Msg(F("Writing "));
+ println_Msg(filePath);
+ display_Update();
+ writeXplorer_N64();
+
+ // Close the file:
+ myFile.close();
+
+ // Verify
+ print_STR(verifying_STR, 0);
+ display_Update();
+ writeErrors = verifyXplorer_N64();
+
+ if (writeErrors == 0) {
+ 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 {
+ display_Clear();
+ display_Update();
+ println_Msg(F("Verification Failed"));
+ println_Msg(writeErrors);
+ print_Msg(F(" bytes "));
+ print_Error(did_not_verify_STR);
+ }
+ } else {
+ print_Error(F("Can't open file"));
+ }
+ }
+
+ // Prints string out of the common strings array either with or without newline
+ print_STR(press_button_STR, 1);
+ display_Update();
+ wait();
+ display_Clear();
+ display_Update();
+}
+
+//Test for SST 29LE010
+void idXplorer_N64() {
+ flashid = 0x0;
+ //Send flashrom ID command
+ oddXPaddrWrite(0x1040AAAA, 0xAAAA);
+ evenXPaddrWrite(0x10405555, 0x5555);
+ oddXPaddrWrite(0x1040AAAA, 0x9090);
+
+ setAddress_N64(0x10760000);
+ readWord_N64();
+ setAddress_N64(0x10400D88);
+ flashid = readWord_N64();
+ setAddress_N64(0x10740000);
+ readWord_N64();
+
+ if (flashid == 0x0808) {
+ flashSize = 262144;
+ } else {
+ 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
+ resetXplorer_N64();
+}
+
+void resetXplorer_N64() {
+ // Send reset command for SST 29LE010
+ oddXPaddrWrite(0x1040AAAA, 0xAAAA);
+ evenXPaddrWrite(0x10405555, 0x5555);
+ oddXPaddrWrite(0x1040AAAA, 0xF0F0);
+ delay(100);
+}
+
// Read rom and save to the SD card
void backupXplorer_N64() {
// create a new folder
EEPROM_readAnything(0, foldern);
- sprintf(fileName, "XP64%d", foldern);
+ sprintf(fileName, "XP64-%d", foldern);
strcat(fileName, ".z64");
sd.mkdir("N64/ROM/XPLORER64", true);
sd.chdir("N64/ROM/XPLORER64");
@@ -4525,6 +4653,173 @@ void backupXplorer_N64() {
println_Msg(F("Done."));
}
+unsigned long unscramble(unsigned long addr) {
+ unsigned long result = (((addr >> 4) & 0x001) | ((addr >> 8) & 0x002) |
+ ((~addr >> 9) & 0x004) | ((addr >> 3) & 0x008) |
+ ((addr >> 6) & 0x010) | ((addr >> 2) & 0x020) |
+ ((~addr << 5) & 0x0C0) | ((~addr << 8) & 0x100) |
+ ((~addr << 6) & 0x200) | ((~addr << 2) & 0x400) |
+ ((addr << 6) & 0x800) | (addr & 0x1F000));
+
+ return result;
+}
+
+
+unsigned long scramble(unsigned long addr) {
+ unsigned long result = (((~addr >> 8) & 0x001) | ((~addr >> 5) & 0x006) |
+ ((~addr >> 6) & 0x008) | ((addr << 4) & 0x010) |
+ ((addr >> 6) & 0x020) | ((addr << 3) & 0x040) |
+ ((addr << 2) & 0x080) | ((~addr >> 2) & 0x100) |
+ ((addr << 8) & 0x200) | ((addr << 6) & 0x400) |
+ ((~addr << 9) & 0x800) | (addr & 0x1F000));
+
+ return result;
+}
+
+
+void oddXPaddrWrite(unsigned long addr, word data) {
+ unsigned long oddAddr = (0x10400000 + ((unscramble((addr & 0xFFFFF) / 2) - 1) * 2));
+ setAddress_N64(0x10770000);
+ readWord_N64();
+ readWord_N64();
+ setAddress_N64(oddAddr);
+ writeWord_N64(data);
+ writeWord_N64(data);
+ setAddress_N64(0x10740000);
+ readWord_N64();
+ readWord_N64();
+
+}
+
+void evenXPaddrWrite(unsigned long addr, word data) {
+ unsigned long evenAddr = (0x10400000 + (unscramble((addr & 0xFFFFF) / 2) * 2));
+ setAddress_N64(0x10760000);
+ readWord_N64();
+ readWord_N64();
+ setAddress_N64(evenAddr);
+ writeWord_N64(data);
+ writeWord_N64(data);
+ setAddress_N64(0x10740000);
+ readWord_N64();
+ readWord_N64();
+}
+
+void eraseXplorer_N64() {
+ println_Msg(F("Erasing..."));
+ display_Update();
+
+ // Send chip erase to SST 29LE010 / AMTEL AT29LV010A / SST 29EE010
+ oddXPaddrWrite(0x1040AAAA, 0xAAAA);
+ evenXPaddrWrite(0x10405555, 0x5555);
+ oddXPaddrWrite(0x1040AAAA, 0x8080);
+ oddXPaddrWrite(0x1040AAAA, 0xAAAA);
+ evenXPaddrWrite(0x10405555, 0x5555);
+ oddXPaddrWrite(0x1040AAAA,0x1010);
+
+ delay(20);
+}
+
+void blankCheck_XP64() {
+ // Blankcheck
+ println_Msg(F("Blankcheck..."));
+ display_Update();
+
+ for (unsigned long currSector = 0; currSector < 262144; 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(0x10400000 + currSector + currSdBuffer + currByte);
+ // Compare both
+ if (readWord_N64() != 0xFFFF) {
+ println_Msg(F("Not empty"));
+ print_FatalError(F("Erase failed"));
+ }
+ }
+ }
+ }
+}
+
+void writeXplorer_N64() {
+ // Write Xplorer64 with 2x SST 29LE010
+ // Each 29LE010 has 1024 pages, each 128 bytes in size
+ //Initialize progress bar
+ uint32_t processedProgressBar = 0;
+ uint32_t totalProgressBar = (uint32_t)(fileSize);
+ draw_progressbar(0, totalProgressBar);
+ for (unsigned long currPage = 0; currPage < fileSize / 2; currPage += 128) {
+
+ // Fill SD buffer with data in the order it will be expected by the CPLD
+ for (unsigned long i = 0; i < 256; i += 2) {
+ unsigned long unscrambled_address = (unscramble(((currPage*2) + i) / 2) * 2);
+ myFile.seek(unscrambled_address);
+ myFile.read(&sdBuffer[i], 1);
+ myFile.seek(unscrambled_address + 1);
+ myFile.read(&sdBuffer[i + 1], 1);
+ }
+
+ //Send page write command to both flashroms
+ oddXPaddrWrite(0x1040AAAA, 0xAAAA);
+ evenXPaddrWrite(0x10405555, 0x5555);
+ oddXPaddrWrite(0x1040AAAA, 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) {
+ // Join two bytes into one word
+ word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
+ // Set address
+ if ((((currByte/2) >> 4) & 0x1) == 0) {
+ evenXPaddrWrite(0x10400000 + (currPage*2) + currByte, currWord);
+ } else {
+ oddXPaddrWrite(0x10400000 + (currPage*2) + currByte, currWord);
+ }
+ }
+ processedProgressBar += 256;
+ draw_progressbar(processedProgressBar, totalProgressBar);
+ blinkLED();
+ }
+}
+
+unsigned long verifyXplorer_N64() {
+ uint32_t processedProgressBar = 0;
+ uint32_t totalProgressBar = (uint32_t)(262144);
+ println_Msg(F(""));
+ draw_progressbar(0, totalProgressBar);
+ // Open file on sd card
+ if (myFile.open(filePath, O_READ)) {
+ myFile.seek(0);
+ writeErrors = 0;
+
+ for (unsigned long currSector = 0; currSector < 262144; currSector += 131072) {
+ for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) {
+ // Fill SD buffer
+ myFile.read(sdBuffer, 512);
+ for (int currByte = 0; currByte < 512; currByte += 2) {
+ // Join two bytes into one word
+ word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
+ // Read flash
+ setAddress_N64(romBase + 0x400000 + currSector + currSdBuffer + currByte);
+ // Compare both
+ if (readWord_N64() != currWord) {
+ writeErrors++;
+ }
+ }
+ processedProgressBar += 512;
+ draw_progressbar(processedProgressBar, totalProgressBar);
+ blinkLED();
+ }
+ }
+ // Close the file:
+ myFile.close();
+ return writeErrors;
+ } else {
+ print_STR(open_file_STR, 1);
+ display_Update();
+ return 9999;
+ }
+}
+
#endif
//******************************************