aboutsummaryrefslogtreecommitdiffhomepage
path: root/Cart_Reader/N64.ino
diff options
context:
space:
mode:
Diffstat (limited to 'Cart_Reader/N64.ino')
-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
//******************************************