From 4d5cff13938e79460a7fb2c11b50a81f022538c6 Mon Sep 17 00:00:00 2001 From: sanni Date: Mon, 18 Sep 2017 23:39:54 +0200 Subject: [PATCH] V28E: Added some untested flashrom types for GBA and N64 I don't have them myself so I can't test but maybe others can. Flashrom Programmer: Macronix MX29LV320 and MX29LV640 (connected as 16bit flashrom in 8bit mode) GBA: Intel 4400L0ZDQ0 (Only using the first 32MB) N64: Fujitsu MSP55LV100S and Macronix MX29LV640 (Fujitsu might have a different sector size) --- Cart_Reader/Cart_Reader.ino | 6 +- Cart_Reader/FLASH.ino | 120 +++++++++++++++++ Cart_Reader/GBA.ino | 213 +++++++++++++++++++++--------- Cart_Reader/N64.ino | 256 ++++++++++++++++++++---------------- 4 files changed, 419 insertions(+), 176 deletions(-) diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index dc45c18..d53c3b3 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -2,8 +2,8 @@ Cartridge Reader for Arduino Mega2560 Author: sanni - Date: 2017-09-15 - Version: V28D + Date: 2017-09-18 + Version: V28E SD lib: https://github.com/greiman/SdFat LCD lib: https://github.com/adafruit/Adafruit_SSD1306 @@ -34,7 +34,7 @@ YamaArashi - GBA flashrom bank switch command **********************************************************************************/ -char ver[5] = "V28D"; +char ver[5] = "V28E"; /****************************************** Define Output diff --git a/Cart_Reader/FLASH.ino b/Cart_Reader/FLASH.ino index 1562d9b..7e1fbde 100644 --- a/Cart_Reader/FLASH.ino +++ b/Cart_Reader/FLASH.ino @@ -97,6 +97,10 @@ void flashromMenu8() { else if (flashromType == 2) { if (strcmp(flashid, "C2F3") == 0) writeFlash29F1601(); + else if (strcmp(flashid, "C2A8") == 0) + writeFlash29LV320(); + else if (strcmp(flashid, "C2C9") == 0) + writeFlash29LV640(); else writeFlash29F1610(); } @@ -307,6 +311,16 @@ idtheflash: flashSize = 4194304; flashromType = 2; } + else if (strcmp(flashid, "C2A8") == 0) { + println_Msg(F("MX29LV320")); + flashSize = 4194304; + flashromType = 2; + } + else if (strcmp(flashid, "C2C9") == 0) { + println_Msg(F("MX29LV640")); + flashSize = 8388608; + flashromType = 2; + } else if (strcmp(flashid, "0141") == 0) { println_Msg(F("AM29F032B")); flashSize = 4194304; @@ -846,6 +860,112 @@ void busyCheck29F1610() { dataOut(); } +/****************************************** + MX29LV flashrom functions +*****************************************/ +void busyCheck29LV640(unsigned long myAddress, byte myData) { + // Set data pins to input + dataIn8(); + // Read the status register + byte statusReg = readByte_Flash(myAddress); + while ((statusReg & 0x80) != (myData & 0x80)) { + statusReg = readByte_Flash(myAddress); + } + // Set data pins to output + dataOut(); +} + +void writeFlash29LV320() { + // Create filepath + sprintf(filePath, "%s/%s", filePath, fileName); + println_Msg(F("Flashing file ")); + println_Msg(filePath); + display_Update(); + + // Open file on sd card + if (myFile.open(filePath, O_READ)) { + // Get rom size from file + fileSize = myFile.fileSize(); + if (fileSize > flashSize) + print_Error(F("File size exceeds flash size."), true); + + // Set data pins to output + dataOut(); + + for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) { + // Fill sdBuffer + myFile.read(sdBuffer, 512); + + // Blink led + if (currByte % 2048 == 0) + PORTB ^= (1 << 4); + + for (int c = 0; c < 512; c++) { + // Write command sequence + writeByte_Flash(0x555 << 1, 0xaa); + writeByte_Flash(0x2aa << 1, 0x55); + writeByte_Flash(0x555 << 1, 0xa0); + // Write current byte + writeByte_Flash(currByte + c, sdBuffer[c]); + // Check if write is complete + busyCheck29F032(sdBuffer[c]); + } + } + + // Set data pins to input again + dataIn8(); + + // Close the file: + myFile.close(); + } + else { + println_Msg(F("Can't open file on SD")); + display_Update(); + } +} +void writeFlash29LV640() { + // Create filepath + sprintf(filePath, "%s/%s", filePath, fileName); + println_Msg(F("Flashing file ")); + println_Msg(filePath); + display_Update(); + // Open file on sd card + if (myFile.open(filePath, O_READ)) { + // Get rom size from file + fileSize = myFile.fileSize(); + if (fileSize > flashSize) + print_Error(F("File size exceeds flash size."), true); + + // Set data pins to output + dataOut(); + for (unsigned long currByte = 0; currByte < fileSize; currByte += 512) { + // Fill sdBuffer + myFile.read(sdBuffer, 512); + // Blink led + if (currByte % 2048 == 0) + PORTB ^= (1 << 4); + for (int c = 0; c < 512; c++) { + // Write command sequence + writeByte_Flash(0x555 << 1, 0xaa); + writeByte_Flash(0x2aa << 1, 0x55); + writeByte_Flash(0x555 << 1, 0xa0); + // Write current byte + writeByte_Flash(currByte + c, sdBuffer[c]); + // Check if write is complete + busyCheck29LV640(currByte + c, sdBuffer[c]); + } + } + // Set data pins to input again + dataIn8(); + // Close the file: + myFile.close(); + } + else { + println_Msg(F("Can't open file on SD")); + display_Update(); + } +} + /****************************************** Common flashrom functions *****************************************/ diff --git a/Cart_Reader/GBA.ino b/Cart_Reader/GBA.ino index 5defd06..b8e38aa 100644 --- a/Cart_Reader/GBA.ino +++ b/Cart_Reader/GBA.ino @@ -2035,7 +2035,7 @@ void idFlashrom_GBA() { sprintf(flashid, "%02X%02X", ((readWord_GBA(0x2) >> 8) & 0xFF), (readWord_GBA(0x4) & 0xFF)); // Intel Strataflash - if (strcmp(flashid, "8802") == 0) { + if (strcmp(flashid, "8802") == 0 || (strcmp(flashid, "8816") == 0)) { cartSize = 0x2000000; } else { @@ -2077,7 +2077,7 @@ boolean blankcheckFlashrom_GBA() { } void eraseIntel4000_GBA() { - // If the game is smaller than 32Mbit only erase the needed blocks + // If the game is smaller than 16Mbit only erase the needed blocks unsigned long lastBlock = 0xFFFFFF; if (fileSize < 0xFFFFFF) lastBlock = fileSize; @@ -2160,6 +2160,90 @@ void eraseIntel4000_GBA() { } } +void eraseIntel4400_GBA() { + // If the game is smaller than 32Mbit only erase the needed blocks + unsigned long lastBlock = 0x1FFFFFF; + if (fileSize < 0x1FFFFFF) + lastBlock = fileSize; + + // Erase 4 blocks with 16kwords each + for (unsigned long currBlock = 0x0; currBlock < 0x1FFFF; currBlock += 0x8000) { + // Unlock Block + writeWord_GBA(currBlock, 0x60); + writeWord_GBA(currBlock, 0xD0); + + // Erase Command + writeWord_GBA(currBlock, 0x20); + writeWord_GBA(currBlock, 0xD0); + + // Read the status register + word statusReg = readWord_GBA(currBlock); + while ((statusReg | 0xFF7F) != 0xFFFF) { + statusReg = readWord_GBA(currBlock); + } + } + + // Erase 255 blocks with 64kwords each + for (unsigned long currBlock = 0x20000; currBlock < lastBlock; currBlock += 0x1FFFF) { + // Unlock Block + writeWord_GBA(currBlock, 0x60); + writeWord_GBA(currBlock, 0xD0); + + // Erase Command + writeWord_GBA(currBlock, 0x20); + writeWord_GBA(currBlock, 0xD0); + + // Read the status register + word statusReg = readWord_GBA(currBlock); + while ((statusReg | 0xFF7F) != 0xFFFF) { + statusReg = readWord_GBA(currBlock); + } + // Blink led + PORTB ^= (1 << 4); + } + + /* No need to erase the second chip as max rom size is 32MB + if (fileSize > 0x2000000) { + // 255 blocks with 64kwords each + for (unsigned long currBlock = 0x2000000; currBlock < 0x3FDFFFF; currBlock += 0x1FFFF) { + // Unlock Block + writeWord_GBA(currBlock, 0x60); + writeWord_GBA(currBlock, 0xD0); + + // Erase Command + writeWord_GBA(currBlock, 0x20); + writeWord_GBA(currBlock, 0xD0); + + // Read the status register + word statusReg = readWord_GBA(currBlock); + while ((statusReg | 0xFF7F) != 0xFFFF) { + statusReg = readWord_GBA(currBlock); + } + // Blink led + PORTB ^= (1 << 4); + } + + // 4 blocks with 16kword each + for (unsigned long currBlock = 0x3FE0000; currBlock < 0x3FFFFFF; currBlock += 0x8000) { + // Unlock Block + writeWord_GBA(currBlock, 0x60); + writeWord_GBA(currBlock, 0xD0); + + // Erase Command + writeWord_GBA(currBlock, 0x20); + writeWord_GBA(currBlock, 0xD0); + + // Read the status register + word statusReg = readWord_GBA(currBlock); + while ((statusReg | 0xFF7F) != 0xFFFF) { + statusReg = readWord_GBA(currBlock); + } + // Blink led + PORTB ^= (1 << 4); + } + }*/ +} + void sectorEraseMSP55LV128_GBA() { unsigned long lastSector = 0xFFFFFF; @@ -2382,7 +2466,7 @@ void flashRepro_GBA() { // Check flashrom ID's idFlashrom_GBA(); - if ((strcmp(flashid, "8802") == 0) || (strcmp(flashid, "227E") == 0)) { + if ((strcmp(flashid, "8802") == 0) || (strcmp(flashid, "8816") == 0) || (strcmp(flashid, "227E") == 0)) { print_Msg(F("ID: ")); print_Msg(flashid); print_Msg(F(" Size: ")); @@ -2406,15 +2490,14 @@ void flashRepro_GBA() { else if (strcmp(flashid, "8802") == 0) { println_Msg(F("Intel 4000L0YBQ0")); } + // Intel 4400L0ZDQ0 + else if (strcmp(flashid, "8816") == 0) { + println_Msg(F("Intel 4400L0ZDQ0")); + } println_Msg(""); println_Msg(F("This will erase your")); println_Msg(F("Repro Cartridge.")); - if (strcmp(flashid, "8802") == 0) { - println_Msg("Please use 3.3V!"); - } - else if (strcmp(flashid, "227E") == 0) { - println_Msg("Attention: Use 5V!"); - } + println_Msg(F("Please use 3.3V!")); println_Msg(""); println_Msg(F("Press Button")); display_Update(); @@ -2444,13 +2527,13 @@ void flashRepro_GBA() { println_Msg(F("Erasing...")); display_Update(); eraseIntel4000_GBA(); - delay(1000); - resetIntel_GBA(0x8000); - delay(1000); - resetIntel_GBA(0x100000); - delay(1000); resetIntel_GBA(0x200000); - delay(1000); + } + else if (strcmp(flashid, "8816") == 0) { + println_Msg(F("Erasing...")); + display_Update(); + eraseIntel4400_GBA(); + resetIntel_GBA(0x200000); } else if (strcmp(flashid, "227E") == 0) { //if (sectorCheckMX29GL128E_GBA()) { @@ -2467,58 +2550,66 @@ void flashRepro_GBA() { } //} } - - print_Msg(F("Blankcheck...")); - display_Update(); - if (blankcheckFlashrom_GBA()) { + /* Skip blankcheck to save time + print_Msg(F("Blankcheck...")); + display_Update(); + if (blankcheckFlashrom_GBA()) { println_Msg(F("OK")); + */ - //Write flashrom - print_Msg(F("Writing ")); - println_Msg(filePath); + //Write flashrom + print_Msg(F("Writing ")); + println_Msg(filePath); + display_Update(); + if ((strcmp(flashid, "8802") == 0) || (strcmp(flashid, "8816") == 0)) { + writeIntel4000_GBA(); + } + else if (strcmp(flashid, "227E") == 0) { + if (romType == 0xC2) { + writeMX29GL128E_GBA(); + } + else if (romType == 0x4) { + writeMSP55LV128_GBA(); + } + } + + // Close the file: + myFile.close(); + + // Verify + print_Msg(F("Verifying...")); + display_Update(); + if (strcmp(flashid, "8802") == 0) { + // Don't know the correct size so just take some guesses + resetIntel_GBA(0x8000); + delay(1000); + resetIntel_GBA(0x100000); + delay(1000); + resetIntel_GBA(0x200000); + delay(1000); + } + else if (strcmp(flashid, "8816") == 0) { + resetIntel_GBA(0x200000); + delay(1000); + } + + else if (strcmp(flashid, "227E") == 0) { + resetMX29GL128E_GBA(); + delay(1000); + } + if (verifyFlashrom_GBA() == 1) { + println_Msg(F("OK")); display_Update(); - if (strcmp(flashid, "8802") == 0) { - writeIntel4000_GBA(); - } - else if (strcmp(flashid, "227E") == 0) { - if (romType == 0xC2) { - writeMX29GL128E_GBA(); - } - else if (romType == 0x4) { - writeMSP55LV128_GBA(); - } - } - - // Close the file: - myFile.close(); - - // Verify - print_Msg(F("Verifying...")); - display_Update(); - if (strcmp(flashid, "8802") == 0) { - resetIntel_GBA(0x8000); - delay(1000); - resetIntel_GBA(0x100000); - delay(1000); - resetIntel_GBA(0x200000); - delay(1000); - } - - else if (strcmp(flashid, "227E") == 0) { - resetMX29GL128E_GBA(); - delay(1000); - } - if (verifyFlashrom_GBA() == 1) { - println_Msg(F("OK")); - display_Update(); - } - else { - print_Error(F("ERROR"), true); - } } else { - print_Error(F("failed"), true); + print_Error(F("ERROR"), true); } + /* Skipped blankcheck + } + else { + print_Error(F("failed"), true); + } + */ } else { print_Error(F("Can't open file"), true); diff --git a/Cart_Reader/N64.ino b/Cart_Reader/N64.ino index eb905a5..ded621c 100644 --- a/Cart_Reader/N64.ino +++ b/Cart_Reader/N64.ino @@ -2053,6 +2053,8 @@ calcn64crc: void flashRepro_N64() { // Check flashrom ID's idFlashrom_N64(); + + // If the ID is known continue if (cartSize != 0) { print_Msg("ID: "); print_Msg(flashid); @@ -2088,15 +2090,31 @@ void flashRepro_N64() { println_Msg(F("MB")); display_Update(); - // Erase needed sectors - if (strcmp(flashid, "227E") == 0) { - eraseSector_N64(); - } - else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) { - eraseBlock_N64(); - resetReadmode_N64(); + // Compare file size to flashrom size + if ((fileSize / 1048576) > cartSize) { + print_Error(F("File too big"), true); } + // Erase needed sectors + if (strcmp(flashid, "227E") == 0) { + // Spansion S29GL256N + eraseFlashrom_N64(0x20000); + } + else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) { + // Intel 4400L0ZDQ0 + eraseIntel4400_N64(); + resetIntel4400_N64(); + } + else if (strcmp(flashid, "127E") == 0) { + // Fujitsu MSP55LV100S + eraseFlashrom_N64(0x10000); + } + else if (strcmp(flashid, "C2C9") == 0) { + // Macronix MX29LV640 + eraseFlashrom_N64(0x8000); + } + + // Check if erase was successful if (blankcheckFlashrom_N64()) { // Write flashrom println_Msg(F("OK")); @@ -2105,11 +2123,21 @@ void flashRepro_N64() { display_Update(); if (strcmp(flashid, "227E") == 0) { - writeFlashBuffer_N64(); + // Spansion S29GL256N + write29GL256N_N64(); + } + else if (strcmp(flashid, "127E") == 0) { + // Fujitsu MSP55LV100S + writeMSP55LV100S_N64(); + } + else if (strcmp(flashid, "C2C9") == 0) { + // Macronix MX29LV640 + write29LV640_N64(); } else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) { - writeFlashBlock_N64(); - resetReadmode_N64(); + // Intel 4400L0ZDQ0 + writeIntel4400_N64(); + resetIntel4400_N64(); } // Close the file: @@ -2137,6 +2165,7 @@ void flashRepro_N64() { print_Error(F("Can't open file"), false); } } + // If the ID is unknown show error message else { print_Msg(F("Flash ID: ")); println_Msg(flashid); @@ -2151,13 +2180,14 @@ void flashRepro_N64() { } // Reset to read mode -void resetReadmode_N64() { +void resetIntel4400_N64() { for (unsigned long currPartition = 0; currPartition < (cartSize * 0x100000); currPartition += 0x20000) { setAddress_N64(romBase + currPartition); writeWord_N64(0xFF); } } +// Common reset command void resetFlashrom_N64(unsigned long flashBase) { // Send reset Command setAddress_N64(flashBase); @@ -2166,10 +2196,10 @@ void resetFlashrom_N64(unsigned long flashBase) { } void idFlashrom_N64() { - // Size of repro cartridge if no ID is found + // Set size to 0 if no ID is found cartSize = 0; - // Send ID command to first flashrom + // Send flashrom ID command setAddress_N64(romBase + (0x555 << 1)); writeWord_N64(0xAA); setAddress_N64(romBase + (0x2AA << 1)); @@ -2177,24 +2207,26 @@ void idFlashrom_N64() { setAddress_N64(romBase + (0x555 << 1)); writeWord_N64(0x90); - // Read manufacturer ID + // Read and discard manufacturer ID setAddress_N64(romBase); readWord_N64(); // Read flashrom ID sprintf(flashid, "%04X", readWord_N64()); - // Check for known ID - if ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "8816") == 0)) { - // Reset flashrom to read mode - if (strcmp(flashid, "227E") == 0) - resetFlashrom_N64(romBase); - else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) - resetReadmode_N64(); + // Spansion S29GL256N(32MB/64MB) or Macronix MX29LV640(8MB/16MB) + if ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "C2C9") == 0)) { + // Reset flashrom + resetFlashrom_N64(romBase); - // Found first flashrom chip, set to 32MB - cartSize = 32; + // Found first flashrom chip + if (strcmp(flashid, "227E") == 0) { + cartSize = 32; + } + else if (strcmp(flashid, "C2C9") == 0) { + cartSize = 8; + } - // Send ID command to possible second flashrom + // These use PCBs with either one or two flashrom chips so try to read ID of possible second chip setAddress_N64(romBase + 0x2000000 + (0x555 << 1)); writeWord_N64(0xAA); setAddress_N64(romBase + 0x2000000 + (0x2AA << 1)); @@ -2209,23 +2241,30 @@ void idFlashrom_N64() { sprintf(cartID, "%04X", readWord_N64()); // Check if second flashrom chip is present - if ((strcmp(cartID, "227E") == 0) || (strcmp(cartID, "8813") == 0)) { + if (strcmp(cartID, "227E") == 0) { cartSize = 64; - strncpy(flashid , cartID, 5); - - // Reset flashrom to read mode - if (strcmp(flashid, "227E") == 0) - resetFlashrom_N64(romBase + 0x2000000); - else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) - resetReadmode_N64(); } + else if (strcmp(cartID, "C2C9") == 0) { + cartSize = 16; + } + resetFlashrom_N64(romBase + 0x2000000); // Empty cartID string cartID[0] = '\0'; } + // Intel 4400L0ZDQ0 (64MB) + else if (strcmp(flashid, "8816") == 0) { + resetIntel4400_N64(); + cartSize = 64; + } + //Fujitsu MSP55LV100S (64MB) + else if (strcmp(flashid, "127E") == 0) { + resetFlashrom_N64(romBase); + cartSize = 64; + } } // Erase Intel flashrom -void eraseBlock_N64() { +void eraseIntel4400_N64() { unsigned long flashBase = romBase; print_Msg(F("Erasing...")); @@ -2337,23 +2376,23 @@ void eraseBlock_N64() { } } -// Erase Spansion flashrom -void eraseSector_N64() { +// Common sector erase command +void eraseFlashrom_N64(unsigned long sectorSize) { unsigned long flashBase = romBase; print_Msg(F("Erasing...")); display_Update(); - for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { + for (unsigned long currSector = 0; currSector < fileSize; currSector += sectorSize) { // Blink led PORTB ^= (1 << 4); - // Change to second rom chip - if (currSector == 0x2000000) { + // If pcb has two flashrom chips change to second + if ((currSector == 0x2000000) && ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "C2C9") == 0))) { flashBase = romBase + 0x2000000; } - // Send Erase Command to first flashrom + // Send Erase Command setAddress_N64(flashBase + (0x555 << 1)); writeWord_N64(0xAA); setAddress_N64(flashBase + (0x2AA << 1)); @@ -2377,69 +2416,7 @@ void eraseSector_N64() { } } -void eraseFlashrom_N64() { - print_Msg(F("Erasing...")); - display_Update(); - - // Send Erase Command to first flashrom - setAddress_N64(romBase + (0x555 << 1)); - writeWord_N64(0xAA); - setAddress_N64(romBase + (0x2AA << 1)); - writeWord_N64(0x55); - setAddress_N64(romBase + (0x555 << 1)); - writeWord_N64(0x80); - setAddress_N64(romBase + (0x555 << 1)); - writeWord_N64(0xAA); - setAddress_N64(romBase + (0x2AA << 1)); - writeWord_N64(0x55); - setAddress_N64(romBase + (0x555 << 1)); - writeWord_N64(0x10); - - if ((cartSize == 64) && (fileSize > 0x2000000)) { - // Send Erase Command to second flashrom - setAddress_N64(romBase + 0x2000000 + (0x555 << 1)); - writeWord_N64(0xAA); - setAddress_N64(romBase + 0x2000000 + (0x2AA << 1)); - writeWord_N64(0x55); - setAddress_N64(romBase + 0x2000000 + (0x555 << 1)); - writeWord_N64(0x80); - setAddress_N64(romBase + 0x2000000 + (0x555 << 1)); - writeWord_N64(0xAA); - setAddress_N64(romBase + 0x2000000 + (0x2AA << 1)); - writeWord_N64(0x55); - setAddress_N64(romBase + 0x2000000 + (0x555 << 1)); - writeWord_N64(0x10); - } - - delay(1000); - - // Read the status register - setAddress_N64(romBase); - word statusReg = readWord_N64(); - while ((statusReg | 0xFF7F) != 0xFFFF) { - // Blink led - PORTB ^= (1 << 4); - delay(1000); - setAddress_N64(romBase); - statusReg = readWord_N64(); - } - - if ((cartSize == 64) && (fileSize > 0x2000000)) { - // Read the status register - setAddress_N64(romBase + 0x2000000); - word statusReg = readWord_N64(); - while ((statusReg | 0xFF7F) != 0xFFFF) { - // Blink led - PORTB ^= (1 << 4); - delay(1000); - setAddress_N64(romBase + 0x2000000); - statusReg = readWord_N64(); - } - } -} - boolean blankcheckFlashrom_N64() { - display_Update(); for (unsigned long currByte = romBase; currByte < romBase + fileSize; currByte += 512) { // Blink led if (currByte % 131072 == 0) @@ -2458,7 +2435,7 @@ boolean blankcheckFlashrom_N64() { } // Write Intel flashrom -void writeFlashBlock_N64() { +void writeIntel4400_N64() { for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { // Blink led PORTB ^= (1 << 4); @@ -2510,11 +2487,11 @@ void writeFlashBlock_N64() { } } -// Write flashrom using the faster 16 word write buffer -void writeFlashBuffer_N64() { +// Write Spansion S29GL256N flashrom using the 32 byte write buffer +void write29GL256N_N64() { unsigned long flashBase = romBase; - for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { + for (unsigned long currSector = 0; currSector < fileSize; currSector += 0x20000) { // Blink led PORTB ^= (1 << 4); @@ -2524,7 +2501,7 @@ void writeFlashBuffer_N64() { } // Write to flashrom - for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) { + for (unsigned long currSdBuffer = 0; currSdBuffer < 0x20000; currSdBuffer += 512) { // Fill SD buffer myFile.read(sdBuffer, 512); @@ -2572,21 +2549,76 @@ void writeFlashBuffer_N64() { } } -// Write flashrom slowly -void writeFlashrom_N64() { +// Write Fujitsu MSP55LV100S flashrom using the 32 byte write buffer +void writeMSP55LV100S_N64() { + for (unsigned long currSector = 0; currSector < fileSize; currSector += 0x10000) { + // Blink led + PORTB ^= (1 << 4); + + // Write to flashrom + for (unsigned long currSdBuffer = 0; currSdBuffer < 0x10000; currSdBuffer += 512) { + // Fill SD buffer + myFile.read(sdBuffer, 512); + + // Write 16 words at a time + for (int currWriteBuffer = 0; currWriteBuffer < 512; currWriteBuffer += 32) { + + // 2 unlock commands + setAddress_N64(romBase + (0x555 << 1)); + writeWord_N64(0xAA); + setAddress_N64(romBase + (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 + currWord = ( ( sdBuffer[currWriteBuffer + currByte] & 0xFF ) << 8 ) | ( sdBuffer[currWriteBuffer + currByte + 1] & 0xFF ); + + // 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(); + } + } + } + } +} + +// Write MX29LV640 flashrom without write buffer +void write29LV640_N64() { unsigned long flashBase = romBase; - for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) { + for (unsigned long currSector = 0; currSector < fileSize; currSector += 0x8000) { // Blink led PORTB ^= (1 << 4); // Change to second rom - if (currSector == 0x2000000) { - flashBase = romBase + 0x2000000; + if (currSector == 0x800000) { + flashBase = romBase + 0x800000; } // Write to flashrom - for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) { + for (unsigned long currSdBuffer = 0; currSdBuffer < 0x8000; currSdBuffer += 512) { // Fill SD buffer myFile.read(sdBuffer, 512); for (int currByte = 0; currByte < 512; currByte += 2) {