diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 978d1d9..2f6518b 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -2,15 +2,15 @@ Cartridge Reader for Arduino Mega2560 Author: sanni - Date: 2017-03-02 - Version: V23 + Date: 2017-05-03 + Version: V23A SD lib: https://github.com/greiman/SdFat LCD lib: https://github.com/adafruit/Adafruit_SSD1306 Clockgen: https://github.com/etherkit/Si5351Arduino RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools - Compiled with Arduino 1.8.0 + Compiled with Arduino 1.8.2 Thanks to: MichlK - ROM-Reader for Super Nintendo @@ -34,12 +34,11 @@ YamaArashi - GBA flashrom bank switch command **********************************************************************************/ -char ver[5] = "V23"; +char ver[5] = "V23A"; /****************************************** Define Output ******************************************/ -// If you don't have an OLED screen change // enable_OLED to 0 and enable_Serial to 1 #define enable_OLED 1 #define enable_Serial 0 @@ -320,29 +319,29 @@ static const unsigned char PROGMEM sig [] = { *****************************************/ // All menus and menu entries are stored in progmem to save on sram // Main menu -const char modeItem1[] PROGMEM = "Nintendo 64"; -const char modeItem2[] PROGMEM = "Super Nintendo"; -const char modeItem3[] PROGMEM = "Nintendo Power"; -const char modeItem4[] PROGMEM = "Game Boy"; -const char modeItem5[] PROGMEM = "Flashrom Programmer"; -const char modeItem6[] PROGMEM = "About"; -const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6}; +static const char modeItem1[] PROGMEM = "Nintendo 64"; +static const char modeItem2[] PROGMEM = "Super Nintendo"; +static const char modeItem3[] PROGMEM = "Nintendo Power"; +static const char modeItem4[] PROGMEM = "Game Boy"; +static const char modeItem5[] PROGMEM = "Flashrom Programmer"; +static const char modeItem6[] PROGMEM = "About"; +static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6}; // N64 Submenu -const char n64MenuItem1[] PROGMEM = "Cart Slot"; -const char n64MenuItem2[] PROGMEM = "Controller"; -const char n64MenuItem3[] PROGMEM = "Flash Repro"; -const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2, n64MenuItem3}; +static const char n64MenuItem1[] PROGMEM = "Cart Slot"; +static const char n64MenuItem2[] PROGMEM = "Controller"; +static const char n64MenuItem3[] PROGMEM = "Flash Repro"; +static const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2, n64MenuItem3}; // Flash Submenu -const char flashMenuItem1[] PROGMEM = "8bit slot"; -const char flashMenuItem2[] PROGMEM = "16bit slot"; -const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2}; +static const char flashMenuItem1[] PROGMEM = "8bit slot"; +static const char flashMenuItem2[] PROGMEM = "16bit slot"; +static const char* const menuOptionsFlash[] PROGMEM = {flashMenuItem1, flashMenuItem2}; // GBx Submenu -const char gbxMenuItem1[] PROGMEM = "Game Boy (Color)"; -const char gbxMenuItem2[] PROGMEM = "Game Boy Advance"; -const char* const menuOptionsGBx[] PROGMEM = {gbxMenuItem1, gbxMenuItem2}; +static const char gbxMenuItem1[] PROGMEM = "Game Boy (Color)"; +static const char gbxMenuItem2[] PROGMEM = "Game Boy Advance"; +static const char* const menuOptionsGBx[] PROGMEM = {gbxMenuItem1, gbxMenuItem2}; void mainMenu() { // create menu with title and 6 options to choose from @@ -519,6 +518,9 @@ void setup() { //PORTD |= (1 << 7); //PORTG |= (1 << 2); + // Initialize LED + rgb.setColor(0, 0, 0); + // Read current folder number out of eeprom EEPROM_readAnything(0, foldern); @@ -919,12 +921,9 @@ int checkButton2() { // Wait for user to push button void wait_btn() { - // Change led to green if (errorLvl == 0) rgbLed(green_color); - else - errorLvl = 0; while (1) { @@ -937,12 +936,16 @@ void wait_btn() { } // if the cart readers input button is pressed shortly if (b == 1) { + errorLvl = 0; break; } // if the cart readers input button is pressed long if (b == 3) { - ignoreError = 1; + if (errorLvl) { + ignoreError = 1; + errorLvl = 0; + } break; } } diff --git a/Cart_Reader/FLASH.ino b/Cart_Reader/FLASH.ino index e732549..7d361cd 100644 --- a/Cart_Reader/FLASH.ino +++ b/Cart_Reader/FLASH.ino @@ -16,24 +16,24 @@ unsigned long blank; Menu *****************************************/ // 8bit Flash menu items -const char flash8MenuItem1[] PROGMEM = "Blankcheck"; -const char flash8MenuItem2[] PROGMEM = "Erase"; -const char flash8MenuItem3[] PROGMEM = "Read"; -const char flash8MenuItem4[] PROGMEM = "Write"; -const char flash8MenuItem5[] PROGMEM = "ID"; -const char flash8MenuItem6[] PROGMEM = "Print"; -const char flash8MenuItem7[] PROGMEM = "Reset"; -const char* const menuOptionsFLASH8[] PROGMEM = {flash8MenuItem1, flash8MenuItem2, flash8MenuItem3, flash8MenuItem4, flash8MenuItem5, flash8MenuItem6, flash8MenuItem7}; +static const char flash8MenuItem1[] PROGMEM = "Blankcheck"; +static const char flash8MenuItem2[] PROGMEM = "Erase"; +static const char flash8MenuItem3[] PROGMEM = "Read"; +static const char flash8MenuItem4[] PROGMEM = "Write"; +static const char flash8MenuItem5[] PROGMEM = "ID"; +static const char flash8MenuItem6[] PROGMEM = "Print"; +static const char flash8MenuItem7[] PROGMEM = "Reset"; +static const char* const menuOptionsFLASH8[] PROGMEM = {flash8MenuItem1, flash8MenuItem2, flash8MenuItem3, flash8MenuItem4, flash8MenuItem5, flash8MenuItem6, flash8MenuItem7}; // 16bit Flash menu items -const char flash16MenuItem1[] PROGMEM = "Blankcheck"; -const char flash16MenuItem2[] PROGMEM = "Erase"; -const char flash16MenuItem3[] PROGMEM = "Read"; -const char flash16MenuItem4[] PROGMEM = "Write"; -const char flash16MenuItem5[] PROGMEM = "ID"; -const char flash16MenuItem6[] PROGMEM = "Print"; -const char flash16MenuItem7[] PROGMEM = "Reset"; -const char* const menuOptionsFLASH16[] PROGMEM = {flash16MenuItem1, flash16MenuItem2, flash16MenuItem3, flash16MenuItem4, flash16MenuItem5, flash16MenuItem6, flash16MenuItem7}; +static const char flash16MenuItem1[] PROGMEM = "Blankcheck"; +static const char flash16MenuItem2[] PROGMEM = "Erase"; +static const char flash16MenuItem3[] PROGMEM = "Read"; +static const char flash16MenuItem4[] PROGMEM = "Write"; +static const char flash16MenuItem5[] PROGMEM = "ID"; +static const char flash16MenuItem6[] PROGMEM = "Print"; +static const char flash16MenuItem7[] PROGMEM = "Reset"; +static const char* const menuOptionsFLASH16[] PROGMEM = {flash16MenuItem1, flash16MenuItem2, flash16MenuItem3, flash16MenuItem4, flash16MenuItem5, flash16MenuItem6, flash16MenuItem7}; void flashromMenu8() { // create menu with title and 7 options to choose from diff --git a/Cart_Reader/GB.ino b/Cart_Reader/GB.ino index c306747..e129bfa 100644 --- a/Cart_Reader/GB.ino +++ b/Cart_Reader/GB.ino @@ -14,12 +14,12 @@ uint16_t sramEndAddress = 0; Menu *****************************************/ // GB menu items -const char GBMenuItem1[] PROGMEM = "Read Rom"; -const char GBMenuItem2[] PROGMEM = "Read Save"; -const char GBMenuItem3[] PROGMEM = "Write Save"; -const char GBMenuItem4[] PROGMEM = "Write Flashcart"; -const char GBMenuItem5[] PROGMEM = "Reset"; -const char* const menuOptionsGB[] PROGMEM = {GBMenuItem1, GBMenuItem2, GBMenuItem3, GBMenuItem4, GBMenuItem5}; +static const char GBMenuItem1[] PROGMEM = "Read Rom"; +static const char GBMenuItem2[] PROGMEM = "Read Save"; +static const char GBMenuItem3[] PROGMEM = "Write Save"; +static const char GBMenuItem4[] PROGMEM = "Write Flashcart"; +static const char GBMenuItem5[] PROGMEM = "Reset"; +static const char* const menuOptionsGB[] PROGMEM = {GBMenuItem1, GBMenuItem2, GBMenuItem3, GBMenuItem4, GBMenuItem5}; void gbMenu() { // create menu with title and 5 options to choose from diff --git a/Cart_Reader/GBA.ino b/Cart_Reader/GBA.ino index 2fc9787..944492a 100644 --- a/Cart_Reader/GBA.ino +++ b/Cart_Reader/GBA.ino @@ -8,7 +8,7 @@ char calcChecksumStr[5]; boolean readType; -const int nintendoLogo[] PROGMEM = { +static const int nintendoLogo[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xAE, 0x51, 0x69, 0x9A, 0xA2, 0x21, 0x3D, 0x84, 0x82, 0x0A, 0x84, 0xE4, 0x09, 0xAD, 0x11, 0x24, 0x8B, 0x98, 0xC0, 0x81, 0x7F, 0x21, 0xA3, 0x52, 0xBE, 0x19, 0x93, 0x09, 0xCE, 0x20, 0x10, 0x46, 0x4A, 0x4A, 0xF8, 0x27, 0x31, 0xEC, 0x58, 0xC7, 0xE8, 0x33, @@ -25,29 +25,29 @@ const int nintendoLogo[] PROGMEM = { Menu *****************************************/ // GBA menu items -const char GBAMenuItem1[] PROGMEM = "Read Rom"; -const char GBAMenuItem2[] PROGMEM = "Read Save"; -const char GBAMenuItem3[] PROGMEM = "Write Save"; -const char GBAMenuItem4[] PROGMEM = "Reset"; -const char* const menuOptionsGBA[] PROGMEM = {GBAMenuItem1, GBAMenuItem2, GBAMenuItem3, GBAMenuItem4}; +static const char GBAMenuItem1[] PROGMEM = "Read Rom"; +static const char GBAMenuItem2[] PROGMEM = "Read Save"; +static const char GBAMenuItem3[] PROGMEM = "Write Save"; +static const char GBAMenuItem4[] PROGMEM = "Reset"; +static const char* const menuOptionsGBA[] PROGMEM = {GBAMenuItem1, GBAMenuItem2, GBAMenuItem3, GBAMenuItem4}; // Rom menu -const char GBARomItem1[] PROGMEM = "1MB"; -const char GBARomItem2[] PROGMEM = "2MB"; -const char GBARomItem3[] PROGMEM = "4MB"; -const char GBARomItem4[] PROGMEM = "8MB"; -const char GBARomItem5[] PROGMEM = "16MB"; -const char GBARomItem6[] PROGMEM = "32MB"; -const char* const romOptionsGBA[] PROGMEM = {GBARomItem1, GBARomItem2, GBARomItem3, GBARomItem4, GBARomItem5, GBARomItem6}; +static const char GBARomItem1[] PROGMEM = "1MB"; +static const char GBARomItem2[] PROGMEM = "2MB"; +static const char GBARomItem3[] PROGMEM = "4MB"; +static const char GBARomItem4[] PROGMEM = "8MB"; +static const char GBARomItem5[] PROGMEM = "16MB"; +static const char GBARomItem6[] PROGMEM = "32MB"; +static const char* const romOptionsGBA[] PROGMEM = {GBARomItem1, GBARomItem2, GBARomItem3, GBARomItem4, GBARomItem5, GBARomItem6}; // Save menu -const char GBASaveItem1[] PROGMEM = "4K EEPROM"; -const char GBASaveItem2[] PROGMEM = "64K EEPROM"; -const char GBASaveItem3[] PROGMEM = "256K SRAM/FRAM"; -const char GBASaveItem4[] PROGMEM = "512K SRAM/FRAM"; -const char GBASaveItem5[] PROGMEM = "512K FLASHROM"; -const char GBASaveItem6[] PROGMEM = "1M FLASHROM"; -const char* const saveOptionsGBA[] PROGMEM = {GBASaveItem1, GBASaveItem2, GBASaveItem3, GBASaveItem4, GBASaveItem5, GBASaveItem6}; +static const char GBASaveItem1[] PROGMEM = "4K EEPROM"; +static const char GBASaveItem2[] PROGMEM = "64K EEPROM"; +static const char GBASaveItem3[] PROGMEM = "256K SRAM/FRAM"; +static const char GBASaveItem4[] PROGMEM = "512K SRAM/FRAM"; +static const char GBASaveItem5[] PROGMEM = "512K FLASHROM"; +static const char GBASaveItem6[] PROGMEM = "1M FLASHROM"; +static const char* const saveOptionsGBA[] PROGMEM = {GBASaveItem1, GBASaveItem2, GBASaveItem3, GBASaveItem4, GBASaveItem5, GBASaveItem6}; void gbaMenu() { // create menu with title and 4 options to choose from diff --git a/Cart_Reader/N64.ino b/Cart_Reader/N64.ino index 2dc2f63..bf6ab30 100644 --- a/Cart_Reader/N64.ino +++ b/Cart_Reader/N64.ino @@ -48,25 +48,25 @@ boolean MN63F81MPN = false; Menu *****************************************/ // N64 controller menu items -const char N64ContMenuItem1[] PROGMEM = "Test Controller"; -const char N64ContMenuItem2[] PROGMEM = "Read ControllerPak"; -const char N64ContMenuItem3[] PROGMEM = "Write ControllerPak"; -const char N64ContMenuItem4[] PROGMEM = "Reset"; -const char* const menuOptionsN64Controller[] PROGMEM = {N64ContMenuItem1, N64ContMenuItem2, N64ContMenuItem3, N64ContMenuItem4}; +static const char N64ContMenuItem1[] PROGMEM = "Test Controller"; +static const char N64ContMenuItem2[] PROGMEM = "Read ControllerPak"; +static const char N64ContMenuItem3[] PROGMEM = "Write ControllerPak"; +static const char N64ContMenuItem4[] PROGMEM = "Reset"; +static const char* const menuOptionsN64Controller[] PROGMEM = {N64ContMenuItem1, N64ContMenuItem2, N64ContMenuItem3, N64ContMenuItem4}; // N64 cart menu items -const char N64CartMenuItem1[] PROGMEM = "Read Rom"; -const char N64CartMenuItem2[] PROGMEM = "Read Save"; -const char N64CartMenuItem3[] PROGMEM = "Write Save"; -const char N64CartMenuItem4[] PROGMEM = "Reset"; -const char* const menuOptionsN64Cart[] PROGMEM = {N64CartMenuItem1, N64CartMenuItem2, N64CartMenuItem3, N64CartMenuItem4}; +static const char N64CartMenuItem1[] PROGMEM = "Read Rom"; +static const char N64CartMenuItem2[] PROGMEM = "Read Save"; +static const char N64CartMenuItem3[] PROGMEM = "Write Save"; +static const char N64CartMenuItem4[] PROGMEM = "Reset"; +static const char* const menuOptionsN64Cart[] PROGMEM = {N64CartMenuItem1, N64CartMenuItem2, N64CartMenuItem3, N64CartMenuItem4}; // N64 CRC32 error menu items -const char N64CRCMenuItem1[] PROGMEM = "Recalc CRC"; -const char N64CRCMenuItem2[] PROGMEM = "Redump"; -const char N64CRCMenuItem3[] PROGMEM = "Ignore"; -const char N64CRCMenuItem4[] PROGMEM = "Reset"; -const char* const menuOptionsN64CRC[] PROGMEM = {N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3, N64CRCMenuItem4}; +static const char N64CRCMenuItem1[] PROGMEM = "Recalc CRC"; +static const char N64CRCMenuItem2[] PROGMEM = "Redump"; +static const char N64CRCMenuItem3[] PROGMEM = "Ignore"; +static const char N64CRCMenuItem4[] PROGMEM = "Reset"; +static const char* const menuOptionsN64CRC[] PROGMEM = {N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3, N64CRCMenuItem4}; // N64 Controller Menu void n64ControllerMenu() { @@ -972,6 +972,7 @@ void printCartInfo_N64() { wait(); } else { + // Display error println_Msg(F("GAMEPAK ERROR")); println_Msg(""); print_Msg(F("Name: ")); @@ -980,6 +981,9 @@ void printCartInfo_N64() { println_Msg(cartID); println_Msg(""); display_Update(); + // Set cartSize to 1MB for test dumps + cartSize = 1; + strcpy(romName, "GPERROR"); print_Error(F("Cartridge unknown"), true); } } @@ -2078,26 +2082,47 @@ void flashRepro_N64() { display_Clear(); display_Update(); - // Erase flashrom - eraseFlashrom_N64(); - if (blankcheckFlashrom_N64()) { - writeFlashrom_N64(); + // 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(); + print_Msg(F("File size: ")); + print_Msg(fileSize / 1048576); + println_Msg(F("MB")); + display_Update(); + + // Erase needed sectors + eraseSector_N64(); + + // Write flashrom + print_Msg(F("Writing ")); + println_Msg(filePath); + display_Update(); + writeFlashBuffer_N64(); + + // Close the file: + myFile.close(); + + // Verify + print_Msg(F("Verifying...")); + display_Update(); writeErrors = verifyFlashrom_N64(); if (writeErrors == 0) { - println_Msg(F("Verified OK")); + println_Msg(F("OK")); display_Update(); } else { - print_Msg(F("Error: ")); print_Msg(writeErrors); - println_Msg(F(" bytes ")); + print_Msg(F(" bytes ")); print_Error(F("did not verify."), false); } } else { - print_Error(F("Erase failed"), false); + print_Error(F("Can't open file"), false); } - } else { print_Error(F("Unknown flashrom"), false); @@ -2160,6 +2185,45 @@ void idFlashrom_N64() { } } +void eraseSector_N64() { + unsigned long flashBase = romBase; + + println_Msg(F("Erasing Flashrom")); + display_Update(); + + for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { + // Blink led + PORTB ^= (1 << 4); + + // Change to second rom chip + if (currSector == 0x2000000) { + flashBase = romBase + 0x2000000; + } + + // Send Erase Command to first flashrom + setAddress_N64(flashBase + (0x555 << 1)); + writeWord_N64(0xAA); + setAddress_N64(flashBase + (0x2AA << 1)); + writeWord_N64(0x55); + setAddress_N64(flashBase + (0x555 << 1)); + writeWord_N64(0x80); + setAddress_N64(flashBase + (0x555 << 1)); + writeWord_N64(0xAA); + setAddress_N64(flashBase + (0x2AA << 1)); + writeWord_N64(0x55); + setAddress_N64(romBase + currSector); + writeWord_N64(0x30); + + // Read the status register + setAddress_N64(romBase + currSector); + word statusReg = readWord_N64(); + while ((statusReg | 0xFF7F) != 0xFFFF) { + setAddress_N64(romBase + currSector); + statusReg = readWord_N64(); + } + } +} + void eraseFlashrom_N64() { println_Msg(F("Erasing Flashrom")); display_Update(); @@ -2178,7 +2242,7 @@ void eraseFlashrom_N64() { setAddress_N64(romBase + (0x555 << 1)); writeWord_N64(0x10); - if (cartSize == 0x4000000) { + if ((cartSize == 0x4000000) && (fileSize > 0x2000000)) { // Send Erase Command to second flashrom setAddress_N64(romBase + 0x2000000 + (0x555 << 1)); writeWord_N64(0xAA); @@ -2207,7 +2271,7 @@ void eraseFlashrom_N64() { statusReg = readWord_N64(); } - if (cartSize == 0x4000000) { + if ((cartSize == 0x4000000) && (fileSize > 0x2000000)) { // Read the status register setAddress_N64(romBase + 0x2000000); word statusReg = readWord_N64(); @@ -2224,7 +2288,7 @@ void eraseFlashrom_N64() { boolean blankcheckFlashrom_N64() { print_Msg(F("Blankcheck...")); display_Update(); - for (unsigned long currByte = romBase; currByte < romBase + cartSize; currByte += 512) { + for (unsigned long currByte = romBase; currByte < romBase + fileSize; currByte += 512) { // Blink led if (currByte % 131072 == 0) PORTB ^= (1 << 4); @@ -2246,67 +2310,109 @@ boolean blankcheckFlashrom_N64() { return 1; } -void writeFlashrom_N64() { - // Create filepath - sprintf(filePath, "%s/%s", filePath, fileName); +// Write flashrom using the faster 16 word write buffer +void writeFlashBuffer_N64() { + unsigned long flashBase = romBase; - // Open file on sd card - if (myFile.open(filePath, O_READ)) { - // Get rom size from file - fileSize = myFile.fileSize(); - print_Msg(F("Writing ")); - println_Msg(filePath); - print_Msg(F("File size: ")); - print_Msg(fileSize / 1048576); - println_Msg(F("MB")); - display_Update(); + for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { + // Blink led + PORTB ^= (1 << 4); - unsigned long flashBase = romBase; + // Change to second rom chip + if (currSector == 0x2000000) { + flashBase = romBase + 0x2000000; + } - for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { - // Blink led - PORTB ^= (1 << 4); + // Write to flashrom + for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) { + // Fill SD buffer + myFile.read(sdBuffer, 512); - // Change to second rom - if (currSector == 0x2000000) { - flashBase = romBase + 0x2000000; - } + // Write 16 words at a time + for (int currWriteBuffer = 0; currWriteBuffer < 512; currWriteBuffer += 32) { - // Write to flashrom - for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) { - // Fill SD buffer - myFile.read(sdBuffer, 512); - for (int currByte = 0; currByte < 512; currByte += 2) { + // 2 unlock commands + setAddress_N64(flashBase + (0x555 << 1)); + writeWord_N64(0xAA); + setAddress_N64(flashBase + (0x2AA << 1)); + writeWord_N64(0x55); + + // Write buffer load command at sector address + setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer); + writeWord_N64(0x25); + // Write word count (minus 1) at sector address + setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer); + writeWord_N64(0xF); + + // Define variable before loop so we can use it later when reading the status register + word currWord; + + for (byte currByte = 0; currByte < 32; currByte += 2) { // Join two bytes into one word - word currWord = ( ( sdBuffer[currByte] & 0xFF ) << 8 ) | ( sdBuffer[currByte + 1] & 0xFF ); - // 2 unlock commands - setAddress_N64(flashBase + (0x555 << 1)); - writeWord_N64(0xAA); - setAddress_N64(flashBase + (0x2AA << 1)); - writeWord_N64(0x55); - // Program command - setAddress_N64(flashBase + (0x555 << 1)); - writeWord_N64(0xA0); - // Write word - setAddress_N64(romBase + currSector + currSdBuffer + currByte); - writeWord_N64(currWord); + currWord = ( ( sdBuffer[currWriteBuffer + currByte] & 0xFF ) << 8 ) | ( sdBuffer[currWriteBuffer + currByte + 1] & 0xFF ); - // Read the status register - setAddress_N64(romBase + currSector + currSdBuffer + currByte); - word statusReg = readWord_N64(); - while ((statusReg | 0xFF7F) != (currWord | 0xFF7F)) { - setAddress_N64(romBase + currSector + currSdBuffer + currByte); - statusReg = readWord_N64(); - } + // Load Buffer Words + setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer + currByte); + writeWord_N64(currWord); + } + + // Write Buffer to Flash + setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer + 30); + writeWord_N64(0x29); + + // Read the status register at last written address + setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer + 30); + word statusReg = readWord_N64(); + while ((statusReg | 0xFF7F) != (currWord | 0xFF7F)) { + setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer + 30); + statusReg = readWord_N64(); } } } - // Close the file: - myFile.close(); } - else { - println_Msg(F("Can't open file")); - display_Update(); +} + +// Write flashrom slowly +void writeFlashrom_N64() { + unsigned long flashBase = romBase; + + for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { + // Blink led + PORTB ^= (1 << 4); + + // Change to second rom + if (currSector == 0x2000000) { + flashBase = romBase + 0x2000000; + } + + // Write to flashrom + 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 ); + // 2 unlock commands + setAddress_N64(flashBase + (0x555 << 1)); + writeWord_N64(0xAA); + setAddress_N64(flashBase + (0x2AA << 1)); + writeWord_N64(0x55); + // Program command + setAddress_N64(flashBase + (0x555 << 1)); + writeWord_N64(0xA0); + // Write word + setAddress_N64(romBase + currSector + currSdBuffer + currByte); + writeWord_N64(currWord); + + // Read the status register + setAddress_N64(romBase + currSector + currSdBuffer + currByte); + word statusReg = readWord_N64(); + while ((statusReg | 0xFF7F) != (currWord | 0xFF7F)) { + setAddress_N64(romBase + currSector + currSdBuffer + currByte); + statusReg = readWord_N64(); + } + } + } } } diff --git a/Cart_Reader/NP.ino b/Cart_Reader/NP.ino index 410b25e..ea8c7cc 100644 --- a/Cart_Reader/NP.ino +++ b/Cart_Reader/NP.ino @@ -33,27 +33,27 @@ boolean hirom[8]; Menu *****************************************/ // NP menu items -const char NPMenuItem1[] PROGMEM = "Game Menu"; -const char NPMenuItem2[] PROGMEM = "Flash Menu"; -const char NPMenuItem3[] PROGMEM = "Reset"; -const char* const menuOptionsNP[] PROGMEM = {NPMenuItem1, NPMenuItem2, NPMenuItem3}; +static const char NPMenuItem1[] PROGMEM = "Game Menu"; +static const char NPMenuItem2[] PROGMEM = "Flash Menu"; +static const char NPMenuItem3[] PROGMEM = "Reset"; +static const char* const menuOptionsNP[] PROGMEM = {NPMenuItem1, NPMenuItem2, NPMenuItem3}; // NP flash menu items -const char NPFlashMenuItem1[] PROGMEM = "Read Flash"; -const char NPFlashMenuItem2[] PROGMEM = "Write Flash"; -const char NPFlashMenuItem3[] PROGMEM = "Print Mapping"; -const char NPFlashMenuItem4[] PROGMEM = "Read Mapping"; -const char NPFlashMenuItem5[] PROGMEM = "Write Mapping"; -const char NPFlashMenuItem6[] PROGMEM = "Back"; -const char* const menuOptionsNPFlash[] PROGMEM = {NPFlashMenuItem1, NPFlashMenuItem2, NPFlashMenuItem3, NPFlashMenuItem4, NPFlashMenuItem5, NPFlashMenuItem6}; +static const char NPFlashMenuItem1[] PROGMEM = "Read Flash"; +static const char NPFlashMenuItem2[] PROGMEM = "Write Flash"; +static const char NPFlashMenuItem3[] PROGMEM = "Print Mapping"; +static const char NPFlashMenuItem4[] PROGMEM = "Read Mapping"; +static const char NPFlashMenuItem5[] PROGMEM = "Write Mapping"; +static const char NPFlashMenuItem6[] PROGMEM = "Back"; +static const char* const menuOptionsNPFlash[] PROGMEM = {NPFlashMenuItem1, NPFlashMenuItem2, NPFlashMenuItem3, NPFlashMenuItem4, NPFlashMenuItem5, NPFlashMenuItem6}; // NP game menu items -const char NPGameMenuItem1[] PROGMEM = "Read Sram"; -const char NPGameMenuItem2[] PROGMEM = "Read Game"; -const char NPGameMenuItem3[] PROGMEM = "Write Sram"; -const char NPGameMenuItem4[] PROGMEM = "Switch Game"; -const char NPGameMenuItem5[] PROGMEM = "Reset"; -const char* const menuOptionsNPGame[] PROGMEM = {NPGameMenuItem1, NPGameMenuItem2, NPGameMenuItem3, NPGameMenuItem4, NPGameMenuItem5}; +static const char NPGameMenuItem1[] PROGMEM = "Read Sram"; +static const char NPGameMenuItem2[] PROGMEM = "Read Game"; +static const char NPGameMenuItem3[] PROGMEM = "Write Sram"; +static const char NPGameMenuItem4[] PROGMEM = "Switch Game"; +static const char NPGameMenuItem5[] PROGMEM = "Reset"; +static const char* const menuOptionsNPGame[] PROGMEM = {NPGameMenuItem1, NPGameMenuItem2, NPGameMenuItem3, NPGameMenuItem4, NPGameMenuItem5}; void npMenu() { // create menu with title and 3 options to choose from diff --git a/Cart_Reader/SNES.ino b/Cart_Reader/SNES.ino index 7ef6b75..cd18afd 100644 --- a/Cart_Reader/SNES.ino +++ b/Cart_Reader/SNES.ino @@ -26,21 +26,21 @@ boolean NP = false; Menu *****************************************/ // SNES menu items -const char SnesMenuItem1[] PROGMEM = "Read Rom"; -const char SnesMenuItem2[] PROGMEM = "Read Save"; -const char SnesMenuItem3[] PROGMEM = "Write Save"; -const char SnesMenuItem4[] PROGMEM = "Test SRAM"; -const char SnesMenuItem5[] PROGMEM = "Cycle cart"; -const char SnesMenuItem6[] PROGMEM = "Reset"; -const char* const menuOptionsSNES[] PROGMEM = {SnesMenuItem1, SnesMenuItem2, SnesMenuItem3, SnesMenuItem4, SnesMenuItem5, SnesMenuItem6}; +static const char SnesMenuItem1[] PROGMEM = "Read Rom"; +static const char SnesMenuItem2[] PROGMEM = "Read Save"; +static const char SnesMenuItem3[] PROGMEM = "Write Save"; +static const char SnesMenuItem4[] PROGMEM = "Test SRAM"; +static const char SnesMenuItem5[] PROGMEM = "Cycle cart"; +static const char SnesMenuItem6[] PROGMEM = "Reset"; +static const char* const menuOptionsSNES[] PROGMEM = {SnesMenuItem1, SnesMenuItem2, SnesMenuItem3, SnesMenuItem4, SnesMenuItem5, SnesMenuItem6}; // Manual config menu items -const char confMenuItem1[] PROGMEM = "Use header info"; -const char confMenuItem2[] PROGMEM = "4MB LoRom 256K Sram"; -const char confMenuItem3[] PROGMEM = "4MB HiRom 64K Sram"; -const char confMenuItem4[] PROGMEM = "6MB ExRom 256K Sram"; -const char confMenuItem5[] PROGMEM = "Reset"; -const char* const menuOptionsConf[] PROGMEM = {confMenuItem1, confMenuItem2, confMenuItem3, confMenuItem4, confMenuItem5}; +static const char confMenuItem1[] PROGMEM = "Use header info"; +static const char confMenuItem2[] PROGMEM = "4MB LoRom 256K Sram"; +static const char confMenuItem3[] PROGMEM = "4MB HiRom 64K Sram"; +static const char confMenuItem4[] PROGMEM = "6MB ExRom 256K Sram"; +static const char confMenuItem5[] PROGMEM = "Reset"; +static const char* const menuOptionsConf[] PROGMEM = {confMenuItem1, confMenuItem2, confMenuItem3, confMenuItem4, confMenuItem5}; // SNES Menu void snesMenu() {