mirror of
https://github.com/sanni/cartreader.git
synced 2025-02-17 13:36:19 +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
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
*****************************************/
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user