mirror of
https://github.com/sanni/cartreader.git
synced 2025-02-21 15:17:10 +01:00
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)
This commit is contained in:
parent
684cb15fc9
commit
4d5cff1393
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 2017-09-15
|
Date: 2017-09-18
|
||||||
Version: V28D
|
Version: V28E
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||||
@ -34,7 +34,7 @@
|
|||||||
YamaArashi - GBA flashrom bank switch command
|
YamaArashi - GBA flashrom bank switch command
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "V28D";
|
char ver[5] = "V28E";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Output
|
Define Output
|
||||||
|
@ -97,6 +97,10 @@ void flashromMenu8() {
|
|||||||
else if (flashromType == 2) {
|
else if (flashromType == 2) {
|
||||||
if (strcmp(flashid, "C2F3") == 0)
|
if (strcmp(flashid, "C2F3") == 0)
|
||||||
writeFlash29F1601();
|
writeFlash29F1601();
|
||||||
|
else if (strcmp(flashid, "C2A8") == 0)
|
||||||
|
writeFlash29LV320();
|
||||||
|
else if (strcmp(flashid, "C2C9") == 0)
|
||||||
|
writeFlash29LV640();
|
||||||
else
|
else
|
||||||
writeFlash29F1610();
|
writeFlash29F1610();
|
||||||
}
|
}
|
||||||
@ -307,6 +311,16 @@ idtheflash:
|
|||||||
flashSize = 4194304;
|
flashSize = 4194304;
|
||||||
flashromType = 2;
|
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) {
|
else if (strcmp(flashid, "0141") == 0) {
|
||||||
println_Msg(F("AM29F032B"));
|
println_Msg(F("AM29F032B"));
|
||||||
flashSize = 4194304;
|
flashSize = 4194304;
|
||||||
@ -846,6 +860,112 @@ void busyCheck29F1610() {
|
|||||||
dataOut();
|
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
|
Common flashrom functions
|
||||||
*****************************************/
|
*****************************************/
|
||||||
|
@ -2035,7 +2035,7 @@ void idFlashrom_GBA() {
|
|||||||
sprintf(flashid, "%02X%02X", ((readWord_GBA(0x2) >> 8) & 0xFF), (readWord_GBA(0x4) & 0xFF));
|
sprintf(flashid, "%02X%02X", ((readWord_GBA(0x2) >> 8) & 0xFF), (readWord_GBA(0x4) & 0xFF));
|
||||||
|
|
||||||
// Intel Strataflash
|
// Intel Strataflash
|
||||||
if (strcmp(flashid, "8802") == 0) {
|
if (strcmp(flashid, "8802") == 0 || (strcmp(flashid, "8816") == 0)) {
|
||||||
cartSize = 0x2000000;
|
cartSize = 0x2000000;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -2077,7 +2077,7 @@ boolean blankcheckFlashrom_GBA() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void eraseIntel4000_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;
|
unsigned long lastBlock = 0xFFFFFF;
|
||||||
if (fileSize < 0xFFFFFF)
|
if (fileSize < 0xFFFFFF)
|
||||||
lastBlock = fileSize;
|
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() {
|
void sectorEraseMSP55LV128_GBA() {
|
||||||
unsigned long lastSector = 0xFFFFFF;
|
unsigned long lastSector = 0xFFFFFF;
|
||||||
|
|
||||||
@ -2382,7 +2466,7 @@ void flashRepro_GBA() {
|
|||||||
// Check flashrom ID's
|
// Check flashrom ID's
|
||||||
idFlashrom_GBA();
|
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(F("ID: "));
|
||||||
print_Msg(flashid);
|
print_Msg(flashid);
|
||||||
print_Msg(F(" Size: "));
|
print_Msg(F(" Size: "));
|
||||||
@ -2406,15 +2490,14 @@ void flashRepro_GBA() {
|
|||||||
else if (strcmp(flashid, "8802") == 0) {
|
else if (strcmp(flashid, "8802") == 0) {
|
||||||
println_Msg(F("Intel 4000L0YBQ0"));
|
println_Msg(F("Intel 4000L0YBQ0"));
|
||||||
}
|
}
|
||||||
|
// Intel 4400L0ZDQ0
|
||||||
|
else if (strcmp(flashid, "8816") == 0) {
|
||||||
|
println_Msg(F("Intel 4400L0ZDQ0"));
|
||||||
|
}
|
||||||
println_Msg("");
|
println_Msg("");
|
||||||
println_Msg(F("This will erase your"));
|
println_Msg(F("This will erase your"));
|
||||||
println_Msg(F("Repro Cartridge."));
|
println_Msg(F("Repro Cartridge."));
|
||||||
if (strcmp(flashid, "8802") == 0) {
|
println_Msg(F("Please use 3.3V!"));
|
||||||
println_Msg("Please use 3.3V!");
|
|
||||||
}
|
|
||||||
else if (strcmp(flashid, "227E") == 0) {
|
|
||||||
println_Msg("Attention: Use 5V!");
|
|
||||||
}
|
|
||||||
println_Msg("");
|
println_Msg("");
|
||||||
println_Msg(F("Press Button"));
|
println_Msg(F("Press Button"));
|
||||||
display_Update();
|
display_Update();
|
||||||
@ -2444,13 +2527,13 @@ void flashRepro_GBA() {
|
|||||||
println_Msg(F("Erasing..."));
|
println_Msg(F("Erasing..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
eraseIntel4000_GBA();
|
eraseIntel4000_GBA();
|
||||||
delay(1000);
|
|
||||||
resetIntel_GBA(0x8000);
|
|
||||||
delay(1000);
|
|
||||||
resetIntel_GBA(0x100000);
|
|
||||||
delay(1000);
|
|
||||||
resetIntel_GBA(0x200000);
|
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) {
|
else if (strcmp(flashid, "227E") == 0) {
|
||||||
//if (sectorCheckMX29GL128E_GBA()) {
|
//if (sectorCheckMX29GL128E_GBA()) {
|
||||||
@ -2467,58 +2550,66 @@ void flashRepro_GBA() {
|
|||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
/* Skip blankcheck to save time
|
||||||
print_Msg(F("Blankcheck..."));
|
print_Msg(F("Blankcheck..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
if (blankcheckFlashrom_GBA()) {
|
if (blankcheckFlashrom_GBA()) {
|
||||||
println_Msg(F("OK"));
|
println_Msg(F("OK"));
|
||||||
|
*/
|
||||||
|
|
||||||
//Write flashrom
|
//Write flashrom
|
||||||
print_Msg(F("Writing "));
|
print_Msg(F("Writing "));
|
||||||
println_Msg(filePath);
|
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();
|
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 {
|
else {
|
||||||
print_Error(F("failed"), true);
|
print_Error(F("ERROR"), true);
|
||||||
}
|
}
|
||||||
|
/* Skipped blankcheck
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Error(F("failed"), true);
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_Error(F("Can't open file"), true);
|
print_Error(F("Can't open file"), true);
|
||||||
|
@ -2053,6 +2053,8 @@ calcn64crc:
|
|||||||
void flashRepro_N64() {
|
void flashRepro_N64() {
|
||||||
// Check flashrom ID's
|
// Check flashrom ID's
|
||||||
idFlashrom_N64();
|
idFlashrom_N64();
|
||||||
|
|
||||||
|
// If the ID is known continue
|
||||||
if (cartSize != 0) {
|
if (cartSize != 0) {
|
||||||
print_Msg("ID: ");
|
print_Msg("ID: ");
|
||||||
print_Msg(flashid);
|
print_Msg(flashid);
|
||||||
@ -2088,15 +2090,31 @@ void flashRepro_N64() {
|
|||||||
println_Msg(F("MB"));
|
println_Msg(F("MB"));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
// Erase needed sectors
|
// Compare file size to flashrom size
|
||||||
if (strcmp(flashid, "227E") == 0) {
|
if ((fileSize / 1048576) > cartSize) {
|
||||||
eraseSector_N64();
|
print_Error(F("File too big"), true);
|
||||||
}
|
|
||||||
else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) {
|
|
||||||
eraseBlock_N64();
|
|
||||||
resetReadmode_N64();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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()) {
|
if (blankcheckFlashrom_N64()) {
|
||||||
// Write flashrom
|
// Write flashrom
|
||||||
println_Msg(F("OK"));
|
println_Msg(F("OK"));
|
||||||
@ -2105,11 +2123,21 @@ void flashRepro_N64() {
|
|||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
if (strcmp(flashid, "227E") == 0) {
|
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)) {
|
else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) {
|
||||||
writeFlashBlock_N64();
|
// Intel 4400L0ZDQ0
|
||||||
resetReadmode_N64();
|
writeIntel4400_N64();
|
||||||
|
resetIntel4400_N64();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close the file:
|
// Close the file:
|
||||||
@ -2137,6 +2165,7 @@ void flashRepro_N64() {
|
|||||||
print_Error(F("Can't open file"), false);
|
print_Error(F("Can't open file"), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// If the ID is unknown show error message
|
||||||
else {
|
else {
|
||||||
print_Msg(F("Flash ID: "));
|
print_Msg(F("Flash ID: "));
|
||||||
println_Msg(flashid);
|
println_Msg(flashid);
|
||||||
@ -2151,13 +2180,14 @@ void flashRepro_N64() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset to read mode
|
// Reset to read mode
|
||||||
void resetReadmode_N64() {
|
void resetIntel4400_N64() {
|
||||||
for (unsigned long currPartition = 0; currPartition < (cartSize * 0x100000); currPartition += 0x20000) {
|
for (unsigned long currPartition = 0; currPartition < (cartSize * 0x100000); currPartition += 0x20000) {
|
||||||
setAddress_N64(romBase + currPartition);
|
setAddress_N64(romBase + currPartition);
|
||||||
writeWord_N64(0xFF);
|
writeWord_N64(0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common reset command
|
||||||
void resetFlashrom_N64(unsigned long flashBase) {
|
void resetFlashrom_N64(unsigned long flashBase) {
|
||||||
// Send reset Command
|
// Send reset Command
|
||||||
setAddress_N64(flashBase);
|
setAddress_N64(flashBase);
|
||||||
@ -2166,10 +2196,10 @@ void resetFlashrom_N64(unsigned long flashBase) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void idFlashrom_N64() {
|
void idFlashrom_N64() {
|
||||||
// Size of repro cartridge if no ID is found
|
// Set size to 0 if no ID is found
|
||||||
cartSize = 0;
|
cartSize = 0;
|
||||||
|
|
||||||
// Send ID command to first flashrom
|
// Send flashrom ID command
|
||||||
setAddress_N64(romBase + (0x555 << 1));
|
setAddress_N64(romBase + (0x555 << 1));
|
||||||
writeWord_N64(0xAA);
|
writeWord_N64(0xAA);
|
||||||
setAddress_N64(romBase + (0x2AA << 1));
|
setAddress_N64(romBase + (0x2AA << 1));
|
||||||
@ -2177,24 +2207,26 @@ void idFlashrom_N64() {
|
|||||||
setAddress_N64(romBase + (0x555 << 1));
|
setAddress_N64(romBase + (0x555 << 1));
|
||||||
writeWord_N64(0x90);
|
writeWord_N64(0x90);
|
||||||
|
|
||||||
// Read manufacturer ID
|
// Read and discard manufacturer ID
|
||||||
setAddress_N64(romBase);
|
setAddress_N64(romBase);
|
||||||
readWord_N64();
|
readWord_N64();
|
||||||
// Read flashrom ID
|
// Read flashrom ID
|
||||||
sprintf(flashid, "%04X", readWord_N64());
|
sprintf(flashid, "%04X", readWord_N64());
|
||||||
|
|
||||||
// Check for known ID
|
// Spansion S29GL256N(32MB/64MB) or Macronix MX29LV640(8MB/16MB)
|
||||||
if ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "8816") == 0)) {
|
if ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "C2C9") == 0)) {
|
||||||
// Reset flashrom to read mode
|
// Reset flashrom
|
||||||
if (strcmp(flashid, "227E") == 0)
|
resetFlashrom_N64(romBase);
|
||||||
resetFlashrom_N64(romBase);
|
|
||||||
else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0))
|
|
||||||
resetReadmode_N64();
|
|
||||||
|
|
||||||
// Found first flashrom chip, set to 32MB
|
// Found first flashrom chip
|
||||||
cartSize = 32;
|
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));
|
setAddress_N64(romBase + 0x2000000 + (0x555 << 1));
|
||||||
writeWord_N64(0xAA);
|
writeWord_N64(0xAA);
|
||||||
setAddress_N64(romBase + 0x2000000 + (0x2AA << 1));
|
setAddress_N64(romBase + 0x2000000 + (0x2AA << 1));
|
||||||
@ -2209,23 +2241,30 @@ void idFlashrom_N64() {
|
|||||||
sprintf(cartID, "%04X", readWord_N64());
|
sprintf(cartID, "%04X", readWord_N64());
|
||||||
|
|
||||||
// Check if second flashrom chip is present
|
// Check if second flashrom chip is present
|
||||||
if ((strcmp(cartID, "227E") == 0) || (strcmp(cartID, "8813") == 0)) {
|
if (strcmp(cartID, "227E") == 0) {
|
||||||
cartSize = 64;
|
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
|
// Empty cartID string
|
||||||
cartID[0] = '\0';
|
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
|
// Erase Intel flashrom
|
||||||
void eraseBlock_N64() {
|
void eraseIntel4400_N64() {
|
||||||
unsigned long flashBase = romBase;
|
unsigned long flashBase = romBase;
|
||||||
|
|
||||||
print_Msg(F("Erasing..."));
|
print_Msg(F("Erasing..."));
|
||||||
@ -2337,23 +2376,23 @@ void eraseBlock_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase Spansion flashrom
|
// Common sector erase command
|
||||||
void eraseSector_N64() {
|
void eraseFlashrom_N64(unsigned long sectorSize) {
|
||||||
unsigned long flashBase = romBase;
|
unsigned long flashBase = romBase;
|
||||||
|
|
||||||
print_Msg(F("Erasing..."));
|
print_Msg(F("Erasing..."));
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += sectorSize) {
|
||||||
// Blink led
|
// Blink led
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
// Change to second rom chip
|
// If pcb has two flashrom chips change to second
|
||||||
if (currSector == 0x2000000) {
|
if ((currSector == 0x2000000) && ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "C2C9") == 0))) {
|
||||||
flashBase = romBase + 0x2000000;
|
flashBase = romBase + 0x2000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send Erase Command to first flashrom
|
// Send Erase Command
|
||||||
setAddress_N64(flashBase + (0x555 << 1));
|
setAddress_N64(flashBase + (0x555 << 1));
|
||||||
writeWord_N64(0xAA);
|
writeWord_N64(0xAA);
|
||||||
setAddress_N64(flashBase + (0x2AA << 1));
|
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() {
|
boolean blankcheckFlashrom_N64() {
|
||||||
display_Update();
|
|
||||||
for (unsigned long currByte = romBase; currByte < romBase + fileSize; currByte += 512) {
|
for (unsigned long currByte = romBase; currByte < romBase + fileSize; currByte += 512) {
|
||||||
// Blink led
|
// Blink led
|
||||||
if (currByte % 131072 == 0)
|
if (currByte % 131072 == 0)
|
||||||
@ -2458,7 +2435,7 @@ boolean blankcheckFlashrom_N64() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write Intel flashrom
|
// Write Intel flashrom
|
||||||
void writeFlashBlock_N64() {
|
void writeIntel4400_N64() {
|
||||||
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
||||||
// Blink led
|
// Blink led
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
@ -2510,11 +2487,11 @@ void writeFlashBlock_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write flashrom using the faster 16 word write buffer
|
// Write Spansion S29GL256N flashrom using the 32 byte write buffer
|
||||||
void writeFlashBuffer_N64() {
|
void write29GL256N_N64() {
|
||||||
unsigned long flashBase = romBase;
|
unsigned long flashBase = romBase;
|
||||||
|
|
||||||
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += 0x20000) {
|
||||||
// Blink led
|
// Blink led
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
@ -2524,7 +2501,7 @@ void writeFlashBuffer_N64() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write to flashrom
|
// Write to flashrom
|
||||||
for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) {
|
for (unsigned long currSdBuffer = 0; currSdBuffer < 0x20000; currSdBuffer += 512) {
|
||||||
// Fill SD buffer
|
// Fill SD buffer
|
||||||
myFile.read(sdBuffer, 512);
|
myFile.read(sdBuffer, 512);
|
||||||
|
|
||||||
@ -2572,21 +2549,76 @@ void writeFlashBuffer_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write flashrom slowly
|
// Write Fujitsu MSP55LV100S flashrom using the 32 byte write buffer
|
||||||
void writeFlashrom_N64() {
|
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;
|
unsigned long flashBase = romBase;
|
||||||
|
|
||||||
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += 0x8000) {
|
||||||
// Blink led
|
// Blink led
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
// Change to second rom
|
// Change to second rom
|
||||||
if (currSector == 0x2000000) {
|
if (currSector == 0x800000) {
|
||||||
flashBase = romBase + 0x2000000;
|
flashBase = romBase + 0x800000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to flashrom
|
// Write to flashrom
|
||||||
for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) {
|
for (unsigned long currSdBuffer = 0; currSdBuffer < 0x8000; currSdBuffer += 512) {
|
||||||
// Fill SD buffer
|
// Fill SD buffer
|
||||||
myFile.read(sdBuffer, 512);
|
myFile.read(sdBuffer, 512);
|
||||||
for (int currByte = 0; currByte < 512; currByte += 2) {
|
for (int currByte = 0; currByte < 512; currByte += 2) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user