mirror of
https://github.com/sanni/cartreader.git
synced 2025-01-27 04:05:26 +01:00
V2.5 Add Support for Gameshark N64 reflashing (beta)
Sometimes the Gameshark will lock itself up, in this case it helps if you put a 6102 game into the Gamesharks slot and then put both into the Cart Reader and just start dumping the rom as if it was a game.
This commit is contained in:
parent
8173115c93
commit
642139ca1a
@ -2,15 +2,15 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 13-01-2019
|
Date: 16-01-2018
|
||||||
Version: 2.4
|
Version: 2.5
|
||||||
|
|
||||||
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
|
||||||
Clockgen: https://github.com/etherkit/Si5351Arduino
|
Clockgen: https://github.com/etherkit/Si5351Arduino
|
||||||
RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools
|
RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools
|
||||||
|
|
||||||
Compiled with Arduino 1.8.7
|
Compiled with Arduino 1.8.8
|
||||||
|
|
||||||
Thanks to:
|
Thanks to:
|
||||||
MichlK - ROM-Reader for Super Nintendo
|
MichlK - ROM-Reader for Super Nintendo
|
||||||
@ -37,7 +37,7 @@
|
|||||||
vogelfreiheit - N64 flashram fix
|
vogelfreiheit - N64 flashram fix
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "2.4";
|
char ver[5] = "2.5";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Starting Point
|
Define Starting Point
|
||||||
|
@ -49,7 +49,8 @@ boolean MN63F81MPN = false;
|
|||||||
static const char n64MenuItem1[] PROGMEM = "Cart Slot";
|
static const char n64MenuItem1[] PROGMEM = "Cart Slot";
|
||||||
static const char n64MenuItem2[] PROGMEM = "Controller";
|
static const char n64MenuItem2[] PROGMEM = "Controller";
|
||||||
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
|
static const char n64MenuItem3[] PROGMEM = "Flash Repro";
|
||||||
static const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2, n64MenuItem3};
|
static const char n64MenuItem4[] PROGMEM = "Flash Gameshark";
|
||||||
|
static const char* const menuOptionsN64[] PROGMEM = {n64MenuItem1, n64MenuItem2, n64MenuItem3, n64MenuItem4};
|
||||||
|
|
||||||
// N64 controller menu items
|
// N64 controller menu items
|
||||||
static const char N64ContMenuItem1[] PROGMEM = "Test Controller";
|
static const char N64ContMenuItem1[] PROGMEM = "Test Controller";
|
||||||
@ -74,14 +75,13 @@ static const char N64CRCMenuItem4[] PROGMEM = "Reset";
|
|||||||
static const char* const menuOptionsN64CRC[] PROGMEM = {N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3, N64CRCMenuItem4};
|
static const char* const menuOptionsN64CRC[] PROGMEM = {N64CRCMenuItem1, N64CRCMenuItem2, N64CRCMenuItem3, N64CRCMenuItem4};
|
||||||
|
|
||||||
// Rom menu
|
// Rom menu
|
||||||
static const char N64RomItem1[] PROGMEM = "256KB";
|
static const char N64RomItem1[] PROGMEM = "4MB";
|
||||||
static const char N64RomItem2[] PROGMEM = "4MB";
|
static const char N64RomItem2[] PROGMEM = "8MB";
|
||||||
static const char N64RomItem3[] PROGMEM = "8MB";
|
static const char N64RomItem3[] PROGMEM = "12MB";
|
||||||
static const char N64RomItem4[] PROGMEM = "12MB";
|
static const char N64RomItem4[] PROGMEM = "16MB";
|
||||||
static const char N64RomItem5[] PROGMEM = "16MB";
|
static const char N64RomItem5[] PROGMEM = "32MB";
|
||||||
static const char N64RomItem6[] PROGMEM = "32MB";
|
static const char N64RomItem6[] PROGMEM = "64MB";
|
||||||
static const char N64RomItem7[] PROGMEM = "64MB";
|
static const char* const romOptionsN64[] PROGMEM = {N64RomItem1, N64RomItem2, N64RomItem3, N64RomItem4, N64RomItem5, N64RomItem6};
|
||||||
static const char* const romOptionsN64[] PROGMEM = {N64RomItem1, N64RomItem2, N64RomItem3, N64RomItem4, N64RomItem5, N64RomItem6, N64RomItem7};
|
|
||||||
|
|
||||||
// Save menu
|
// Save menu
|
||||||
static const char N64SaveItem1[] PROGMEM = "None";
|
static const char N64SaveItem1[] PROGMEM = "None";
|
||||||
@ -96,8 +96,8 @@ void n64Menu() {
|
|||||||
// 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
|
||||||
convertPgm(menuOptionsN64, 3);
|
convertPgm(menuOptionsN64, 4);
|
||||||
n64Dev = question_box("Select N64 device", menuOptions, 3, 0);
|
n64Dev = question_box("Select N64 device", menuOptions, 4, 0);
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (n64Dev)
|
switch (n64Dev)
|
||||||
@ -126,6 +126,14 @@ void n64Menu() {
|
|||||||
mode = mode_N64_Cart;
|
mode = mode_N64_Cart;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
setup_N64_Cart();
|
||||||
|
flashGameshark_N64();
|
||||||
|
printCartInfo_N64();
|
||||||
|
mode = mode_N64_Cart;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1089,43 +1097,38 @@ void printCartInfo_N64() {
|
|||||||
// Set cartsize manually
|
// Set cartsize manually
|
||||||
unsigned char N64RomMenu;
|
unsigned char N64RomMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(romOptionsN64, 7);
|
convertPgm(romOptionsN64, 6);
|
||||||
N64RomMenu = question_box("Select ROM size", menuOptions, 7, 0);
|
N64RomMenu = question_box("Select ROM size", menuOptions, 6, 0);
|
||||||
|
|
||||||
// wait for user choice to come back from the question box menu
|
// wait for user choice to come back from the question box menu
|
||||||
switch (N64RomMenu)
|
switch (N64RomMenu)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
// 1MB, will get reduced to 256KB later
|
|
||||||
cartSize = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
// 4MB
|
// 4MB
|
||||||
cartSize = 4;
|
cartSize = 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 1:
|
||||||
// 8MB
|
// 8MB
|
||||||
cartSize = 8;
|
cartSize = 8;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 2:
|
||||||
// 12MB
|
// 12MB
|
||||||
cartSize = 12;
|
cartSize = 12;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 3:
|
||||||
// 16MB
|
// 16MB
|
||||||
cartSize = 16;
|
cartSize = 16;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 4:
|
||||||
// 32MB
|
// 32MB
|
||||||
cartSize = 32;
|
cartSize = 32;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 5:
|
||||||
// 64MB
|
// 64MB
|
||||||
cartSize = 64;
|
cartSize = 64;
|
||||||
break;
|
break;
|
||||||
@ -2100,14 +2103,7 @@ readn64rom:
|
|||||||
print_Error(F("SD Error"), true);
|
print_Error(F("SD Error"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long romSize;
|
for (unsigned long currByte = romBase; currByte < (romBase + (cartSize * 1024 * 1024)); currByte += 512) {
|
||||||
// 256KB romSize
|
|
||||||
if (cartSize == 1)
|
|
||||||
romSize = cartSize * 262144;
|
|
||||||
else
|
|
||||||
romSize = cartSize * 1048576;
|
|
||||||
|
|
||||||
for (unsigned long currByte = romBase; currByte < romBase + romSize; currByte += 512) {
|
|
||||||
// Blink led
|
// Blink led
|
||||||
if (currByte % 16384 == 0)
|
if (currByte % 16384 == 0)
|
||||||
PORTB ^= (1 << 4);
|
PORTB ^= (1 << 4);
|
||||||
@ -2244,21 +2240,13 @@ void flashRepro_N64() {
|
|||||||
println_Msg(F("Fujitsu MSP55LV512"));
|
println_Msg(F("Fujitsu MSP55LV512"));
|
||||||
else if ((strcmp(flashid, "227E") == 0) && (strcmp(cartID, "3901") == 0))
|
else if ((strcmp(flashid, "227E") == 0) && (strcmp(cartID, "3901") == 0))
|
||||||
println_Msg(F("Intel 512M29EW"));
|
println_Msg(F("Intel 512M29EW"));
|
||||||
else if (strcmp(flashid, "0808") == 0)
|
|
||||||
println_Msg(F("SST 29LE010"));
|
|
||||||
|
|
||||||
// Print info
|
// Print info
|
||||||
print_Msg(F("ID: "));
|
print_Msg(F("ID: "));
|
||||||
print_Msg(flashid);
|
print_Msg(flashid);
|
||||||
print_Msg(F(" Size: "));
|
print_Msg(F(" Size: "));
|
||||||
if (strcmp(flashid, "0808") == 0) {
|
print_Msg(cartSize);
|
||||||
print_Msg(128);
|
println_Msg(F("MB"));
|
||||||
println_Msg(F("KB"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
print_Msg(cartSize);
|
|
||||||
println_Msg(F("MB"));
|
|
||||||
}
|
|
||||||
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."));
|
||||||
@ -2288,16 +2276,10 @@ void flashRepro_N64() {
|
|||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
// Compare file size to flashrom size
|
// Compare file size to flashrom size
|
||||||
if (cartSize == 1) {
|
if ((fileSize / 1048576) > cartSize) {
|
||||||
if ((fileSize / 1048576 * 4) > cartSize) {
|
print_Error(F("File too big"), true);
|
||||||
print_Error(F("File too big"), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ((fileSize / 1048576) > cartSize) {
|
|
||||||
print_Error(F("File too big"), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Erase needed sectors
|
// Erase needed sectors
|
||||||
if (strcmp(flashid, "227E") == 0) {
|
if (strcmp(flashid, "227E") == 0) {
|
||||||
// Spansion S29GL256N or Fujitsu MSP55LV512 with 0x20000 sector size and 32 byte buffer
|
// Spansion S29GL256N or Fujitsu MSP55LV512 with 0x20000 sector size and 32 byte buffer
|
||||||
@ -2316,19 +2298,16 @@ void flashRepro_N64() {
|
|||||||
// Macronix MX29LV640, C9 is top boot and CB is bottom boot block
|
// Macronix MX29LV640, C9 is top boot and CB is bottom boot block
|
||||||
eraseFlashrom_N64(0x8000);
|
eraseFlashrom_N64(0x8000);
|
||||||
}
|
}
|
||||||
else if (strcmp(flashid, "0808") == 0) {
|
|
||||||
// SST 29LE010, chip erase not needed as eeprom automaticly erases during the write cycle
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if erase was successful
|
// Check if erase was successful
|
||||||
if (blankcheckFlashrom_N64() || (strcmp(flashid, "0808") == 0)) {
|
if (blankcheckFlashrom_N64()) {
|
||||||
if ((strcmp(flashid, "0808") != 0))
|
|
||||||
println_Msg(F("OK"));
|
|
||||||
|
|
||||||
// Write flashrom
|
// Write flashrom
|
||||||
|
println_Msg(F("OK"));
|
||||||
print_Msg(F("Writing "));
|
print_Msg(F("Writing "));
|
||||||
println_Msg(filePath);
|
println_Msg(filePath);
|
||||||
display_Update();
|
display_Update();
|
||||||
|
|
||||||
|
|
||||||
if ((strcmp(cartID, "3901") == 0) && (strcmp(flashid, "227E") == 0)) {
|
if ((strcmp(cartID, "3901") == 0) && (strcmp(flashid, "227E") == 0)) {
|
||||||
// Intel 512M29EW(64MB) with 0x20000 sector size and 128 byte buffer
|
// Intel 512M29EW(64MB) with 0x20000 sector size and 128 byte buffer
|
||||||
writeFlashBuffer_N64(0x20000, 128);
|
writeFlashBuffer_N64(0x20000, 128);
|
||||||
@ -2350,9 +2329,7 @@ void flashRepro_N64() {
|
|||||||
writeIntel4400_N64();
|
writeIntel4400_N64();
|
||||||
resetIntel4400_N64();
|
resetIntel4400_N64();
|
||||||
}
|
}
|
||||||
else if (strcmp(flashid, "0808") == 0) {
|
|
||||||
writeSST29LE010_N64();
|
|
||||||
}
|
|
||||||
// Close the file:
|
// Close the file:
|
||||||
myFile.close();
|
myFile.close();
|
||||||
|
|
||||||
@ -2414,18 +2391,6 @@ void resetMSP55LV100_N64(unsigned long flashBase) {
|
|||||||
delay(100);
|
delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Reset ST29LE010
|
|
||||||
void resetST29LE010_N64(unsigned long flashBase) {
|
|
||||||
// Send reset Command
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0xAAAA);
|
|
||||||
setAddress_N64(romBase + 0x5554);
|
|
||||||
writeWord_N64(0x5555);
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
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
|
||||||
@ -2568,8 +2533,8 @@ void idFlashrom_N64() {
|
|||||||
resetFlashrom_N64(romBase);
|
resetFlashrom_N64(romBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Test for Fujitsu MSP55LV100S (64MB)
|
||||||
else {
|
else {
|
||||||
//Test for Fujitsu MSP55LV100S (64MB)
|
|
||||||
// Send flashrom ID command
|
// Send flashrom ID command
|
||||||
setAddress_N64(romBase + (0x555 << 1));
|
setAddress_N64(romBase + (0x555 << 1));
|
||||||
writeWord_N64(0xAAAA);
|
writeWord_N64(0xAAAA);
|
||||||
@ -2589,29 +2554,6 @@ void idFlashrom_N64() {
|
|||||||
cartSize = 64;
|
cartSize = 64;
|
||||||
strncpy(flashid , cartID, 5);
|
strncpy(flashid , cartID, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
|
||||||
//Test for SST 29LE010
|
|
||||||
//Send flashrom ID command
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0xAAAA);
|
|
||||||
setAddress_N64(romBase + 0x5554);
|
|
||||||
writeWord_N64(0x5555);
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0x9090);
|
|
||||||
|
|
||||||
setAddress_N64(romBase);
|
|
||||||
// Read 1 byte vendor ID
|
|
||||||
readWord_N64();
|
|
||||||
// Read 2 bytes flashrom ID
|
|
||||||
sprintf(cartID, "%04X", readWord_N64());
|
|
||||||
|
|
||||||
if (strcmp(cartID, "0808") == 0) {
|
|
||||||
resetST29LE010_N64(romBase);
|
|
||||||
cartSize = 1;
|
|
||||||
strncpy(flashid , cartID, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2817,28 +2759,6 @@ void eraseFlashrom_N64(unsigned long sectorSize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SST29LE010 erase command
|
|
||||||
void eraseSST29LE010_N64() {
|
|
||||||
print_Msg(F("Erasing..."));
|
|
||||||
display_Update();
|
|
||||||
|
|
||||||
//Sending erase command according to datasheet
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0xAAAA);
|
|
||||||
setAddress_N64(romBase + 0x5554);
|
|
||||||
writeWord_N64(0x5555);
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0x8080);
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0xAAAA);
|
|
||||||
setAddress_N64(romBase + 0x5554);
|
|
||||||
writeWord_N64(0x5555);
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0x1010);
|
|
||||||
|
|
||||||
delay(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean blankcheckFlashrom_N64() {
|
boolean blankcheckFlashrom_N64() {
|
||||||
for (unsigned long currByte = romBase; currByte < romBase + fileSize; currByte += 512) {
|
for (unsigned long currByte = romBase; currByte < romBase + fileSize; currByte += 512) {
|
||||||
// Blink led
|
// Blink led
|
||||||
@ -2850,48 +2770,13 @@ boolean blankcheckFlashrom_N64() {
|
|||||||
|
|
||||||
for (int c = 0; c < 512; c += 2) {
|
for (int c = 0; c < 512; c += 2) {
|
||||||
if (readWord_N64() != 0xFFFF) {
|
if (readWord_N64() != 0xFFFF) {
|
||||||
if ((strcmp(flashid, "0808") == 0) && (currByte > romBase + 0x3F) && (currByte < romBase + 0x1080)) {
|
return 0;
|
||||||
// Gameshark maps this area to the bootcode of the plugged in cartridge
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write SST29LE010
|
|
||||||
void writeSST29LE010_N64() {
|
|
||||||
// Each 29LE010 has 1024 pages, each 128 bytes in size
|
|
||||||
for (unsigned long currPage = 0; currPage < 1024; currPage++) {
|
|
||||||
// Fill SD buffer with twice the amount since we flash 2 chips
|
|
||||||
myFile.read(sdBuffer, 256);
|
|
||||||
// Blink led
|
|
||||||
PORTB ^= (1 << 4);
|
|
||||||
|
|
||||||
//Send page write command to both flashroms
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0xAAAA);
|
|
||||||
setAddress_N64(romBase + 0x5554);
|
|
||||||
writeWord_N64(0x5555);
|
|
||||||
setAddress_N64(romBase + 0xAAAA);
|
|
||||||
writeWord_N64(0xA0A0);
|
|
||||||
|
|
||||||
// Write 1 page each, one flashrom gets the low byte, the other the high byte.
|
|
||||||
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
|
|
||||||
// Set address
|
|
||||||
setAddress_N64(romBase + (256 * currPage) + currByte);
|
|
||||||
// Join two bytes into one word
|
|
||||||
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
|
|
||||||
// Send byte data
|
|
||||||
writeWord_N64(currWord);
|
|
||||||
}
|
|
||||||
delay(30);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write Intel flashrom
|
// Write Intel flashrom
|
||||||
void writeIntel4400_N64() {
|
void writeIntel4400_N64() {
|
||||||
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
||||||
@ -3125,12 +3010,7 @@ unsigned long verifyFlashrom_N64() {
|
|||||||
setAddress_N64(romBase + currSector + currSdBuffer + currByte);
|
setAddress_N64(romBase + currSector + currSdBuffer + currByte);
|
||||||
// Compare both
|
// Compare both
|
||||||
if (readWord_N64() != currWord) {
|
if (readWord_N64() != currWord) {
|
||||||
if ( (strcmp(flashid, "0808") == 0) && (currSector + currSdBuffer + currByte > 0x3F) && (currSector + currSdBuffer + currByte < 0x1080)) {
|
writeErrors++;
|
||||||
// Gameshark maps this area to the bootcode of the plugged in cartridge
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
writeErrors++;
|
|
||||||
}
|
|
||||||
// Abord if too many errors
|
// Abord if too many errors
|
||||||
if (writeErrors > 20) {
|
if (writeErrors > 20) {
|
||||||
print_Msg(F("More than "));
|
print_Msg(F("More than "));
|
||||||
@ -3153,6 +3033,217 @@ unsigned long verifyFlashrom_N64() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************
|
||||||
|
N64 Gameshark Flash Functions
|
||||||
|
*****************************************/
|
||||||
|
void flashGameshark_N64() {
|
||||||
|
// Check flashrom ID's
|
||||||
|
idGameshark_N64();
|
||||||
|
|
||||||
|
// Check for SST 29LE010
|
||||||
|
if (strcmp(flashid, "0808") == 0) {
|
||||||
|
|
||||||
|
println_Msg("");
|
||||||
|
println_Msg(F("This will erase your"));
|
||||||
|
println_Msg(F("Gameshark cartridge"));
|
||||||
|
println_Msg(F("Attention: Use 3.3V!"));
|
||||||
|
println_Msg("");
|
||||||
|
println_Msg(F("Press Button"));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Launch file browser
|
||||||
|
filePath[0] = '\0';
|
||||||
|
sd.chdir("/");
|
||||||
|
fileBrowser("Select z64 file");
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
// Create filepath
|
||||||
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||||
|
|
||||||
|
// Open file on sd card
|
||||||
|
if (myFile.open(filePath, O_READ)) {
|
||||||
|
// Get rom size from file
|
||||||
|
fileSize = myFile.fileSize();
|
||||||
|
print_Msg(F("File size: "));
|
||||||
|
print_Msg(fileSize / 1024);
|
||||||
|
println_Msg(F("KB"));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
// Compare file size to flashrom size
|
||||||
|
if (fileSize > 262144) {
|
||||||
|
print_Error(F("File too big"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SST 29LE010, chip erase not needed as this eeprom automaticly erases during the write cycle
|
||||||
|
eraseGameshark_N64();
|
||||||
|
|
||||||
|
// Write flashrom
|
||||||
|
print_Msg(F("Writing "));
|
||||||
|
println_Msg(filePath);
|
||||||
|
display_Update();
|
||||||
|
writeGameshark_N64();
|
||||||
|
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
|
||||||
|
// Verify
|
||||||
|
print_Msg(F("Verifying..."));
|
||||||
|
display_Update();
|
||||||
|
writeErrors = verifyGameshark_N64();
|
||||||
|
|
||||||
|
if (writeErrors == 0) {
|
||||||
|
println_Msg(F("OK"));
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Msg(writeErrors);
|
||||||
|
print_Msg(F(" bytes "));
|
||||||
|
print_Error(F("did not verify."), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Error(F("Can't open file"), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the ID is unknown show error message
|
||||||
|
else {
|
||||||
|
print_Msg(F("ID: "));
|
||||||
|
println_Msg(flashid);
|
||||||
|
print_Error(F("Unknown flashrom"), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
println_Msg(F("Press Button..."));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
display_Clear();
|
||||||
|
display_Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Test for SST 29LE010
|
||||||
|
void idGameshark_N64() {
|
||||||
|
//Send flashrom ID command
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(romBase + 0x5554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0x9090);
|
||||||
|
|
||||||
|
setAddress_N64(romBase);
|
||||||
|
// Read 1 byte vendor ID
|
||||||
|
readWord_N64();
|
||||||
|
// Read 2 bytes flashrom ID
|
||||||
|
sprintf(flashid, "%04X", readWord_N64());
|
||||||
|
// Reset flashrom
|
||||||
|
resetGameshark_N64();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reset ST29LE010
|
||||||
|
void resetGameshark_N64() {
|
||||||
|
// Send reset Command
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(romBase + 0x5554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0xF0F0);
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send chip erase to the two SST29LE010 inside the Gameshark
|
||||||
|
void eraseGameshark_N64() {
|
||||||
|
println_Msg(F("Erasing..."));
|
||||||
|
display_Update();
|
||||||
|
|
||||||
|
//Sending erase command according to datasheet
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(romBase + 0x5554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0x8080);
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(romBase + 0x5554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0x1010);
|
||||||
|
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write Gameshark with 2x SST29LE010 Eeproms
|
||||||
|
void writeGameshark_N64() {
|
||||||
|
// Each 29LE010 has 1024 pages, each 128 bytes in size
|
||||||
|
for (unsigned long currPage = 0; currPage < fileSize / 2; currPage += 128) {
|
||||||
|
// Fill SD buffer with twice the amount since we flash 2 chips
|
||||||
|
myFile.read(sdBuffer, 256);
|
||||||
|
// Blink led
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
|
||||||
|
//Send page write command to both flashroms
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0xAAAA);
|
||||||
|
setAddress_N64(romBase + 0x5554);
|
||||||
|
writeWord_N64(0x5555);
|
||||||
|
setAddress_N64(romBase + 0xAAAA);
|
||||||
|
writeWord_N64(0xA0A0);
|
||||||
|
|
||||||
|
// Write 1 page each, one flashrom gets the low byte, the other the high byte.
|
||||||
|
for (unsigned long currByte = 0; currByte < 256; currByte += 2) {
|
||||||
|
// Set address
|
||||||
|
setAddress_N64(romBase + 0xC00000 + (currPage * 2) + currByte);
|
||||||
|
// Join two bytes into one word
|
||||||
|
word currWord = ((sdBuffer[currByte] & 0xFF) << 8) | (sdBuffer[currByte + 1] & 0xFF);
|
||||||
|
// Send byte data
|
||||||
|
writeWord_N64(currWord);
|
||||||
|
}
|
||||||
|
delay(30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long verifyGameshark_N64() {
|
||||||
|
// Open file on sd card
|
||||||
|
if (myFile.open(filePath, O_READ)) {
|
||||||
|
writeErrors = 0;
|
||||||
|
|
||||||
|
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
||||||
|
// Blink led
|
||||||
|
PORTB ^= (1 << 4);
|
||||||
|
for (unsigned long currSdBuffer = 0; currSdBuffer < 131072; currSdBuffer += 512) {
|
||||||
|
// Fill SD buffer
|
||||||
|
myFile.read(sdBuffer, 512);
|
||||||
|
for (int currByte = 0; currByte < 512; currByte += 2) {
|
||||||
|
// Join two bytes into one word
|
||||||
|
word currWord = ( ( sdBuffer[currByte] & 0xFF ) << 8 ) | ( sdBuffer[currByte + 1] & 0xFF );
|
||||||
|
// Read flash
|
||||||
|
setAddress_N64(romBase + 0xC00000 + currSector + currSdBuffer + currByte);
|
||||||
|
// Compare both
|
||||||
|
if (readWord_N64() != currWord) {
|
||||||
|
if ( (strcmp(flashid, "0808") == 0) && (currSector + currSdBuffer + currByte > 0x3F) && (currSector + currSdBuffer + currByte < 0x1080)) {
|
||||||
|
// Gameshark maps this area to the bootcode of the plugged in cartridge
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
writeErrors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
return writeErrors;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println_Msg(F("Can't open file"));
|
||||||
|
display_Update();
|
||||||
|
return 9999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//******************************************
|
//******************************************
|
||||||
// End of File
|
// End of File
|
||||||
//******************************************
|
//******************************************
|
||||||
|
Loading…
x
Reference in New Issue
Block a user