mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-24 05:29:17 +01:00
V30: Add support for Fujitsu MSP55LV100S N64 repros and fix bug in Serial Monitor filebrowser
- The Fujitsu MSP55LV100S consists out of two Fujitsu MSP55LV512 which themselves are just Spansion S29GL256N flashroms. One flashrom is used for the high byte the other for the low byte. - You can now browse pages with the Serial Monitor's file browser just like you can with the OLED.
This commit is contained in:
parent
49fa28ee46
commit
27b63819e5
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 2017-10-13
|
Date: 2017-10-22
|
||||||
Version: V29D
|
Version: V30
|
||||||
|
|
||||||
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
|
||||||
@ -35,7 +35,7 @@
|
|||||||
infinest - help with GB Memory cart
|
infinest - help with GB Memory cart
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "V29D";
|
char ver[5] = "V30";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Output
|
Define Output
|
||||||
@ -354,17 +354,7 @@ static const char gbxMenuItem1[] PROGMEM = "Game Boy (Color)";
|
|||||||
static const char gbxMenuItem2[] PROGMEM = "Game Boy Advance";
|
static const char gbxMenuItem2[] PROGMEM = "Game Boy Advance";
|
||||||
static const char* const menuOptionsGBx[] PROGMEM = {gbxMenuItem1, gbxMenuItem2};
|
static const char* const menuOptionsGBx[] PROGMEM = {gbxMenuItem1, gbxMenuItem2};
|
||||||
|
|
||||||
void mainMenu() {
|
void n64Menu() {
|
||||||
// create menu with title and 6 options to choose from
|
|
||||||
unsigned char modeMenu;
|
|
||||||
// Copy menuOptions out of progmem
|
|
||||||
convertPgm(modeOptions, 7);
|
|
||||||
modeMenu = question_box("Cartridge Reader", menuOptions, 7, 0);
|
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
|
||||||
switch (modeMenu)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
// create menu with title and 3 options to choose from
|
// create menu with title and 3 options to choose from
|
||||||
unsigned char n64Dev;
|
unsigned char n64Dev;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
@ -399,16 +389,9 @@ void mainMenu() {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 1:
|
void npMenu() {
|
||||||
display_Clear();
|
|
||||||
display_Update();
|
|
||||||
setup_Snes();
|
|
||||||
mode = mode_SNES;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
// create menu with title and 2 options to choose from
|
// create menu with title and 2 options to choose from
|
||||||
unsigned char npCart;
|
unsigned char npCart;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
@ -432,9 +415,9 @@ void mainMenu() {
|
|||||||
mode = mode_GBM;
|
mode = mode_GBM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 3:
|
void gbxMenu() {
|
||||||
// create menu with title and 2 options to choose from
|
// create menu with title and 2 options to choose from
|
||||||
unsigned char gbType;
|
unsigned char gbType;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
@ -458,16 +441,9 @@ void mainMenu() {
|
|||||||
mode = mode_GBA;
|
mode = mode_GBA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 4:
|
void flashMenu() {
|
||||||
display_Clear();
|
|
||||||
display_Update();
|
|
||||||
setup_MD();
|
|
||||||
mode = mode_MD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
// create menu with title and 2 options to choose from
|
// create menu with title and 2 options to choose from
|
||||||
unsigned char flashSlot;
|
unsigned char flashSlot;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
@ -491,9 +467,9 @@ void mainMenu() {
|
|||||||
mode = mode_FLASH16;
|
mode = mode_FLASH16;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 6:
|
void aboutScreen() {
|
||||||
display_Clear();
|
display_Clear();
|
||||||
// Draw the Logo
|
// Draw the Logo
|
||||||
display.drawBitmap(0, 0, sig, 128, 64, 1);
|
display.drawBitmap(0, 0, sig, 128, 64, 1);
|
||||||
@ -541,6 +517,50 @@ void mainMenu() {
|
|||||||
rgb.setColor(random(0, 255), random(0, 255), random(0, 255));
|
rgb.setColor(random(0, 255), random(0, 255), random(0, 255));
|
||||||
delay(random(50, 100));
|
delay(random(50, 100));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainMenu() {
|
||||||
|
// create menu with title and 6 options to choose from
|
||||||
|
unsigned char modeMenu;
|
||||||
|
// Copy menuOptions out of progmem
|
||||||
|
convertPgm(modeOptions, 7);
|
||||||
|
modeMenu = question_box("Cartridge Reader", menuOptions, 7, 0);
|
||||||
|
|
||||||
|
// wait for user choice to come back from the question box menu
|
||||||
|
switch (modeMenu)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
n64Menu();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
setup_Snes();
|
||||||
|
mode = mode_SNES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
npMenu();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
gbxMenu();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
setup_MD();
|
||||||
|
mode = mode_MD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
flashMenu();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
aboutScreen();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -776,13 +796,33 @@ byte questionBox_Serial(const char* question, char answers[7][20], int num_answe
|
|||||||
}
|
}
|
||||||
// Wait for user input
|
// Wait for user input
|
||||||
Serial.println("");
|
Serial.println("");
|
||||||
Serial.print(F("Please enter a single number: _ "));
|
Serial.println(F("Please browse pages with 'u'(up) and 'd'(down)"));
|
||||||
|
Serial.print(F("and enter a selection by typing a number(0-6): _ "));
|
||||||
while (Serial.available() == 0) {
|
while (Serial.available() == 0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the incoming byte:
|
// Read the incoming byte:
|
||||||
incomingByte = Serial.read() - 48;
|
incomingByte = Serial.read() - 48;
|
||||||
|
|
||||||
|
if (incomingByte == 69) {
|
||||||
|
if (filebrowse == 1) {
|
||||||
|
if (currPage > 1) {
|
||||||
|
lastPage = currPage;
|
||||||
|
currPage--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
root = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (incomingByte == 52) {
|
||||||
|
if ((numPages > currPage) && (filebrowse == 1)) {
|
||||||
|
lastPage = currPage;
|
||||||
|
currPage++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Print the received byte for validation e.g. in case of a different keyboard mapping
|
// Print the received byte for validation e.g. in case of a different keyboard mapping
|
||||||
Serial.println(incomingByte);
|
Serial.println(incomingByte);
|
||||||
Serial.println("");
|
Serial.println("");
|
||||||
|
@ -983,7 +983,8 @@ void printCartInfo_N64() {
|
|||||||
// Set cartSize to 64MB for test dumps
|
// Set cartSize to 64MB for test dumps
|
||||||
cartSize = 64;
|
cartSize = 64;
|
||||||
strcpy(romName, "GPERROR");
|
strcpy(romName, "GPERROR");
|
||||||
print_Error(F("Cartridge unknown"), true);
|
print_Error(F("Cartridge unknown"), false);
|
||||||
|
wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2073,7 +2074,7 @@ void flashRepro_N64() {
|
|||||||
}
|
}
|
||||||
else if (strcmp(flashid, "8816") == 0)
|
else if (strcmp(flashid, "8816") == 0)
|
||||||
println_Msg(F("Intel 4400L0ZDQ0"));
|
println_Msg(F("Intel 4400L0ZDQ0"));
|
||||||
else if (strcmp(flashid, "127E") == 0)
|
else if (strcmp(flashid, "7E7E") == 0)
|
||||||
println_Msg(F("Fujitsu MSP55LV100S"));
|
println_Msg(F("Fujitsu MSP55LV100S"));
|
||||||
else if ((strcmp(flashid, "227E") == 0) && (strcmp(cartID, "2301") == 0))
|
else if ((strcmp(flashid, "227E") == 0) && (strcmp(cartID, "2301") == 0))
|
||||||
println_Msg(F("Fujitsu MSP55LV512"));
|
println_Msg(F("Fujitsu MSP55LV512"));
|
||||||
@ -2093,12 +2094,6 @@ void flashRepro_N64() {
|
|||||||
display_Update();
|
display_Update();
|
||||||
wait();
|
wait();
|
||||||
|
|
||||||
/* Check if sectors are protected
|
|
||||||
if ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "127E") == 0)) {
|
|
||||||
sectorCheck_N64();
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Launch file browser
|
// Launch file browser
|
||||||
filePath[0] = '\0';
|
filePath[0] = '\0';
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
@ -2124,10 +2119,14 @@ void flashRepro_N64() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Erase needed sectors
|
// Erase needed sectors
|
||||||
if ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "127E") == 0)) {
|
if (strcmp(flashid, "227E") == 0) {
|
||||||
// Spansion S29GL256N, Fujitsu MSP55LV512 or Fujitsu MSP55LV100S with 0x20000 sector size and 32 byte buffer
|
// Spansion S29GL256N or Fujitsu MSP55LV512 with 0x20000 sector size and 32 byte buffer
|
||||||
eraseFlashrom_N64(0x20000);
|
eraseFlashrom_N64(0x20000);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(flashid, "7E7E") == 0) {
|
||||||
|
// Fujitsu MSP55LV100S
|
||||||
|
eraseMSP55LV100_N64();
|
||||||
|
}
|
||||||
else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) {
|
else if ((strcmp(flashid, "8813") == 0) || (strcmp(flashid, "8816") == 0)) {
|
||||||
// Intel 4400L0ZDQ0
|
// Intel 4400L0ZDQ0
|
||||||
eraseIntel4400_N64();
|
eraseIntel4400_N64();
|
||||||
@ -2146,10 +2145,14 @@ void flashRepro_N64() {
|
|||||||
println_Msg(filePath);
|
println_Msg(filePath);
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
if ((strcmp(flashid, "227E") == 0) || (strcmp(flashid, "127E") == 0)) {
|
if (strcmp(flashid, "227E") == 0) {
|
||||||
// Spansion S29GL256N or Fujitsu MSP55LV512 or Fujitsu MSP55LV100S with 0x20000 sector size and 32 byte buffer
|
// Spansion S29GL256N or Fujitsu MSP55LV512 with 0x20000 sector size and 32 byte buffer
|
||||||
writeFlashBuffer_N64(0x20000, 32);
|
writeFlashBuffer_N64(0x20000, 32);
|
||||||
}
|
}
|
||||||
|
else if (strcmp(flashid, "7E7E") == 0) {
|
||||||
|
//Fujitsu MSP55LV100S
|
||||||
|
writeMSP55LV100_N64(0x20000);
|
||||||
|
}
|
||||||
else if ((strcmp(flashid, "22C9") == 0) || (strcmp(flashid, "22CB") == 0)) {
|
else if ((strcmp(flashid, "22C9") == 0) || (strcmp(flashid, "22CB") == 0)) {
|
||||||
// Macronix MX29LV640 without buffer
|
// Macronix MX29LV640 without buffer
|
||||||
writeFlashrom_N64();
|
writeFlashrom_N64();
|
||||||
@ -2178,6 +2181,8 @@ void flashRepro_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// Close the file
|
||||||
|
myFile.close();
|
||||||
print_Error(F("failed"), false);
|
print_Error(F("failed"), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2207,6 +2212,14 @@ void resetIntel4400_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset Fujitsu MSP55LV100S
|
||||||
|
void resetMSP55LV100_N64(unsigned long flashBase) {
|
||||||
|
// Send reset Command
|
||||||
|
setAddress_N64(flashBase);
|
||||||
|
writeWord_N64(0xF0F0);
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
// Common reset command
|
// Common reset command
|
||||||
void resetFlashrom_N64(unsigned long flashBase) {
|
void resetFlashrom_N64(unsigned long flashBase) {
|
||||||
// Send reset Command
|
// Send reset Command
|
||||||
@ -2320,108 +2333,32 @@ void idFlashrom_N64() {
|
|||||||
// Empty cartID string
|
// Empty cartID string
|
||||||
cartID[0] = '\0';
|
cartID[0] = '\0';
|
||||||
}
|
}
|
||||||
//Fujitsu MSP55LV100S (128MB)
|
|
||||||
else if (strcmp(flashid, "127E") == 0) {
|
|
||||||
resetFlashrom_N64(romBase);
|
|
||||||
cartSize = 64;
|
|
||||||
}
|
|
||||||
//Fujitsu MSP55LV512/Spansion S29GL512N (64MB)
|
//Fujitsu MSP55LV512/Spansion S29GL512N (64MB)
|
||||||
else if ((strcmp(cartID, "2301") == 0) && (strcmp(flashid, "227E") == 0)) {
|
else if ((strcmp(cartID, "2301") == 0) && (strcmp(flashid, "227E") == 0)) {
|
||||||
resetFlashrom_N64(romBase);
|
resetFlashrom_N64(romBase);
|
||||||
cartSize = 64;
|
cartSize = 64;
|
||||||
}
|
}
|
||||||
}
|
//Test for Fujitsu MSP55LV100S (64MB)
|
||||||
|
|
||||||
// Check for sector protection
|
|
||||||
void sectorCheck_N64() {
|
|
||||||
word numLocked = 0;
|
|
||||||
word numUnlocked = 0;
|
|
||||||
word numError = 0;
|
|
||||||
unsigned long lastSector;
|
|
||||||
|
|
||||||
// Spansion S29GL256N(32MB/64MB) with two flashrom chips
|
|
||||||
if ((cartSize == 64) && (strcmp(cartID, "2201") == 0)) {
|
|
||||||
lastSector = 0x2000000;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
lastSector = cartSize * 1024 * 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send flashrom ID command
|
// Send flashrom ID command
|
||||||
setAddress_N64(romBase + (0x555 << 1));
|
setAddress_N64(romBase + (0x555 << 1));
|
||||||
writeWord_N64(0xAA);
|
writeWord_N64(0xAAAA);
|
||||||
setAddress_N64(romBase + (0x2AA << 1));
|
setAddress_N64(romBase + (0x2AA << 1));
|
||||||
writeWord_N64(0x55);
|
writeWord_N64(0x5555);
|
||||||
setAddress_N64(romBase + (0x555 << 1));
|
setAddress_N64(romBase + (0x555 << 1));
|
||||||
writeWord_N64(0x90);
|
writeWord_N64(0x9090);
|
||||||
|
|
||||||
word tempWord;
|
setAddress_N64(romBase);
|
||||||
|
// Read 1 byte vendor ID
|
||||||
|
readWord_N64();
|
||||||
|
// Read 2 bytes flashrom ID
|
||||||
|
sprintf(cartID, "%04X", readWord_N64());
|
||||||
|
|
||||||
for (unsigned long currSector = 0x0; currSector < lastSector; currSector += 0x20000) {
|
if (strcmp(cartID, "7E7E") == 0) {
|
||||||
setAddress_N64(romBase + currSector + 0x04);
|
resetMSP55LV100_N64(romBase);
|
||||||
tempWord = readWord_N64();
|
cartSize = 64;
|
||||||
|
strncpy(flashid , cartID, 5);
|
||||||
if (tempWord == 0x1) {
|
|
||||||
numLocked++;
|
|
||||||
}
|
}
|
||||||
else if (tempWord == 0x0) {
|
|
||||||
numUnlocked++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
numError++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resetFlashrom_N64(romBase);
|
|
||||||
|
|
||||||
// Spansion S29GL256N(32MB/64MB) with two flashrom chips
|
|
||||||
if ((cartSize == 64) && (strcmp(cartID, "2201") == 0)) {
|
|
||||||
// Send flashrom ID command
|
|
||||||
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(0x90);
|
|
||||||
|
|
||||||
for (unsigned long currSector = 0x2000000; currSector < 0x4000000; currSector += 0x20000) {
|
|
||||||
setAddress_N64(romBase + currSector + 0x04);
|
|
||||||
tempWord = readWord_N64();
|
|
||||||
|
|
||||||
if (tempWord == 0x1) {
|
|
||||||
numLocked++;
|
|
||||||
}
|
|
||||||
else if (tempWord == 0x0) {
|
|
||||||
numUnlocked++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
numError++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resetFlashrom_N64(romBase + 0x2000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
display_Clear();
|
|
||||||
println_Msg(F("Sector Check"));
|
|
||||||
print_Msg(F("Unlocked: "));
|
|
||||||
println_Msg(numUnlocked);
|
|
||||||
print_Msg(F("Locked: "));
|
|
||||||
println_Msg(numLocked);
|
|
||||||
print_Msg(F("Error: "));
|
|
||||||
println_Msg(numError);
|
|
||||||
println_Msg(F(""));
|
|
||||||
|
|
||||||
if ((numLocked != 0) || (numError != 0)) {
|
|
||||||
println_Msg(F("Error:"));
|
|
||||||
println_Msg(F("Not all Sectors"));
|
|
||||||
print_Error(F("are unlocked"), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
println_Msg(F(""));
|
|
||||||
println_Msg(F("Press button"));
|
|
||||||
display_Update();
|
|
||||||
wait();
|
|
||||||
display_Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2484,7 +2421,7 @@ void eraseIntel4400_N64() {
|
|||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we should erase the seconds chip too
|
// Check if we should erase the second chip too
|
||||||
if ((cartSize = 64) && (fileSize > 0x2000000)) {
|
if ((cartSize = 64) && (fileSize > 0x2000000)) {
|
||||||
// Switch base address to second chip
|
// Switch base address to second chip
|
||||||
flashBase = romBase + 0x2000000;
|
flashBase = romBase + 0x2000000;
|
||||||
@ -2538,6 +2475,50 @@ void eraseIntel4400_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Erase Fujutsu MSP55LV100S
|
||||||
|
void eraseMSP55LV100_N64() {
|
||||||
|
unsigned long flashBase = romBase;
|
||||||
|
unsigned long sectorSize = 0x20000;
|
||||||
|
|
||||||
|
print_Msg(F("Erasing..."));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += sectorSize) {
|
||||||
|
// Blink led
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
|
// Send Erase Command to first chip
|
||||||
|
setAddress_N64(flashBase + (0x555 << 1));
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(flashBase + (0x2AA << 1));
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(flashBase + (0x555 << 1));
|
||||||
|
writeWord_N64(0x8080);
|
||||||
|
setAddress_N64(flashBase + (0x555 << 1));
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(flashBase + (0x2AA << 1));
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(romBase + currSector);
|
||||||
|
writeWord_N64(0x3030);
|
||||||
|
|
||||||
|
// Read the status register
|
||||||
|
setAddress_N64(romBase + currSector);
|
||||||
|
word statusReg = readWord_N64();
|
||||||
|
while ((statusReg | 0xFF7F) != 0xFFFF) {
|
||||||
|
setAddress_N64(romBase + currSector);
|
||||||
|
statusReg = readWord_N64();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the status register
|
||||||
|
setAddress_N64(romBase + currSector);
|
||||||
|
statusReg = readWord_N64();
|
||||||
|
while ((statusReg | 0x7FFF) != 0xFFFF) {
|
||||||
|
setAddress_N64(romBase + currSector);
|
||||||
|
statusReg = readWord_N64();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Common sector erase command
|
// Common sector erase command
|
||||||
void eraseFlashrom_N64(unsigned long sectorSize) {
|
void eraseFlashrom_N64(unsigned long sectorSize) {
|
||||||
unsigned long flashBase = romBase;
|
unsigned long flashBase = romBase;
|
||||||
@ -2653,6 +2634,62 @@ void writeIntel4400_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Write Fujitsu MSP55LV100S flashrom consisting out of two MSP55LV512 flashroms one used for the high byte the other for the low byte
|
||||||
|
void writeMSP55LV100_N64(unsigned long sectorSize) {
|
||||||
|
unsigned long flashBase = romBase;
|
||||||
|
|
||||||
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += sectorSize) {
|
||||||
|
// Blink led
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
|
// Write to flashrom
|
||||||
|
for (unsigned long currSdBuffer = 0; currSdBuffer < sectorSize; currSdBuffer += 512) {
|
||||||
|
// Fill SD buffer
|
||||||
|
myFile.read(sdBuffer, 512);
|
||||||
|
|
||||||
|
// Write 32 bytes at a time
|
||||||
|
for (int currWriteBuffer = 0; currWriteBuffer < 512; currWriteBuffer += 32) {
|
||||||
|
|
||||||
|
// 2 unlock commands
|
||||||
|
setAddress_N64(flashBase + (0x555 << 1));
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(flashBase + (0x2AA << 1));
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
|
||||||
|
// Write buffer load command at sector address
|
||||||
|
setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer);
|
||||||
|
writeWord_N64(0x2525);
|
||||||
|
// Write word count (minus 1) at sector address
|
||||||
|
setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer);
|
||||||
|
writeWord_N64(0x0F0F);
|
||||||
|
|
||||||
|
// 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(0x2929);
|
||||||
|
|
||||||
|
// Read the status register at last written address
|
||||||
|
setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer + 30);
|
||||||
|
word statusReg = readWord_N64();
|
||||||
|
while ((statusReg | 0x7F7F) != (currWord | 0x7F7F)) {
|
||||||
|
setAddress_N64(romBase + currSector + currSdBuffer + currWriteBuffer + 30);
|
||||||
|
statusReg = readWord_N64();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write Spansion S29GL256N flashrom using the 32 byte write buffer
|
// Write Spansion S29GL256N flashrom using the 32 byte write buffer
|
||||||
void writeFlashBuffer_N64(unsigned long sectorSize, byte bufferSize) {
|
void writeFlashBuffer_N64(unsigned long sectorSize, byte bufferSize) {
|
||||||
|
Loading…
Reference in New Issue
Block a user