mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-13 08:25:05 +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
|
||||
|
||||
Author: sanni
|
||||
Date: 13-01-2019
|
||||
Version: 2.4
|
||||
Date: 16-01-2018
|
||||
Version: 2.5
|
||||
|
||||
SD lib: https://github.com/greiman/SdFat
|
||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||
Clockgen: https://github.com/etherkit/Si5351Arduino
|
||||
RGB Tools lib: https://github.com/joushx/Arduino-RGB-Tools
|
||||
|
||||
Compiled with Arduino 1.8.7
|
||||
Compiled with Arduino 1.8.8
|
||||
|
||||
Thanks to:
|
||||
MichlK - ROM-Reader for Super Nintendo
|
||||
@ -37,7 +37,7 @@
|
||||
vogelfreiheit - N64 flashram fix
|
||||
|
||||
**********************************************************************************/
|
||||
char ver[5] = "2.4";
|
||||
char ver[5] = "2.5";
|
||||
|
||||
/******************************************
|
||||
Define Starting Point
|
||||
|
@ -49,7 +49,8 @@ boolean MN63F81MPN = false;
|
||||
static const char n64MenuItem1[] PROGMEM = "Cart Slot";
|
||||
static const char n64MenuItem2[] PROGMEM = "Controller";
|
||||
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
|
||||
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};
|
||||
|
||||
// Rom menu
|
||||
static const char N64RomItem1[] PROGMEM = "256KB";
|
||||
static const char N64RomItem2[] PROGMEM = "4MB";
|
||||
static const char N64RomItem3[] PROGMEM = "8MB";
|
||||
static const char N64RomItem4[] PROGMEM = "12MB";
|
||||
static const char N64RomItem5[] PROGMEM = "16MB";
|
||||
static const char N64RomItem6[] PROGMEM = "32MB";
|
||||
static const char N64RomItem7[] PROGMEM = "64MB";
|
||||
static const char* const romOptionsN64[] PROGMEM = {N64RomItem1, N64RomItem2, N64RomItem3, N64RomItem4, N64RomItem5, N64RomItem6, N64RomItem7};
|
||||
static const char N64RomItem1[] PROGMEM = "4MB";
|
||||
static const char N64RomItem2[] PROGMEM = "8MB";
|
||||
static const char N64RomItem3[] PROGMEM = "12MB";
|
||||
static const char N64RomItem4[] PROGMEM = "16MB";
|
||||
static const char N64RomItem5[] PROGMEM = "32MB";
|
||||
static const char N64RomItem6[] PROGMEM = "64MB";
|
||||
static const char* const romOptionsN64[] PROGMEM = {N64RomItem1, N64RomItem2, N64RomItem3, N64RomItem4, N64RomItem5, N64RomItem6};
|
||||
|
||||
// Save menu
|
||||
static const char N64SaveItem1[] PROGMEM = "None";
|
||||
@ -96,8 +96,8 @@ void n64Menu() {
|
||||
// create menu with title and 3 options to choose from
|
||||
unsigned char n64Dev;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(menuOptionsN64, 3);
|
||||
n64Dev = question_box("Select N64 device", menuOptions, 3, 0);
|
||||
convertPgm(menuOptionsN64, 4);
|
||||
n64Dev = question_box("Select N64 device", menuOptions, 4, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (n64Dev)
|
||||
@ -126,6 +126,14 @@ void n64Menu() {
|
||||
mode = mode_N64_Cart;
|
||||
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
|
||||
unsigned char N64RomMenu;
|
||||
// Copy menuOptions out of progmem
|
||||
convertPgm(romOptionsN64, 7);
|
||||
N64RomMenu = question_box("Select ROM size", menuOptions, 7, 0);
|
||||
convertPgm(romOptionsN64, 6);
|
||||
N64RomMenu = question_box("Select ROM size", menuOptions, 6, 0);
|
||||
|
||||
// wait for user choice to come back from the question box menu
|
||||
switch (N64RomMenu)
|
||||
{
|
||||
case 0:
|
||||
// 1MB, will get reduced to 256KB later
|
||||
cartSize = 1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// 4MB
|
||||
cartSize = 4;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 1:
|
||||
// 8MB
|
||||
cartSize = 8;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 2:
|
||||
// 12MB
|
||||
cartSize = 12;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 3:
|
||||
// 16MB
|
||||
cartSize = 16;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
case 4:
|
||||
// 32MB
|
||||
cartSize = 32;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
case 5:
|
||||
// 64MB
|
||||
cartSize = 64;
|
||||
break;
|
||||
@ -2100,14 +2103,7 @@ readn64rom:
|
||||
print_Error(F("SD Error"), true);
|
||||
}
|
||||
|
||||
unsigned long romSize;
|
||||
// 256KB romSize
|
||||
if (cartSize == 1)
|
||||
romSize = cartSize * 262144;
|
||||
else
|
||||
romSize = cartSize * 1048576;
|
||||
|
||||
for (unsigned long currByte = romBase; currByte < romBase + romSize; currByte += 512) {
|
||||
for (unsigned long currByte = romBase; currByte < (romBase + (cartSize * 1024 * 1024)); currByte += 512) {
|
||||
// Blink led
|
||||
if (currByte % 16384 == 0)
|
||||
PORTB ^= (1 << 4);
|
||||
@ -2244,21 +2240,13 @@ void flashRepro_N64() {
|
||||
println_Msg(F("Fujitsu MSP55LV512"));
|
||||
else if ((strcmp(flashid, "227E") == 0) && (strcmp(cartID, "3901") == 0))
|
||||
println_Msg(F("Intel 512M29EW"));
|
||||
else if (strcmp(flashid, "0808") == 0)
|
||||
println_Msg(F("SST 29LE010"));
|
||||
|
||||
// Print info
|
||||
print_Msg(F("ID: "));
|
||||
print_Msg(flashid);
|
||||
print_Msg(F(" Size: "));
|
||||
if (strcmp(flashid, "0808") == 0) {
|
||||
print_Msg(128);
|
||||
println_Msg(F("KB"));
|
||||
}
|
||||
else {
|
||||
print_Msg(cartSize);
|
||||
println_Msg(F("MB"));
|
||||
}
|
||||
print_Msg(cartSize);
|
||||
println_Msg(F("MB"));
|
||||
println_Msg("");
|
||||
println_Msg(F("This will erase your"));
|
||||
println_Msg(F("Repro Cartridge."));
|
||||
@ -2288,16 +2276,10 @@ void flashRepro_N64() {
|
||||
display_Update();
|
||||
|
||||
// Compare file size to flashrom size
|
||||
if (cartSize == 1) {
|
||||
if ((fileSize / 1048576 * 4) > cartSize) {
|
||||
print_Error(F("File too big"), true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((fileSize / 1048576) > cartSize) {
|
||||
print_Error(F("File too big"), true);
|
||||
}
|
||||
if ((fileSize / 1048576) > cartSize) {
|
||||
print_Error(F("File too big"), true);
|
||||
}
|
||||
|
||||
// Erase needed sectors
|
||||
if (strcmp(flashid, "227E") == 0) {
|
||||
// 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
|
||||
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
|
||||
if (blankcheckFlashrom_N64() || (strcmp(flashid, "0808") == 0)) {
|
||||
if ((strcmp(flashid, "0808") != 0))
|
||||
println_Msg(F("OK"));
|
||||
|
||||
if (blankcheckFlashrom_N64()) {
|
||||
// Write flashrom
|
||||
println_Msg(F("OK"));
|
||||
print_Msg(F("Writing "));
|
||||
println_Msg(filePath);
|
||||
display_Update();
|
||||
|
||||
|
||||
if ((strcmp(cartID, "3901") == 0) && (strcmp(flashid, "227E") == 0)) {
|
||||
// Intel 512M29EW(64MB) with 0x20000 sector size and 128 byte buffer
|
||||
writeFlashBuffer_N64(0x20000, 128);
|
||||
@ -2350,9 +2329,7 @@ void flashRepro_N64() {
|
||||
writeIntel4400_N64();
|
||||
resetIntel4400_N64();
|
||||
}
|
||||
else if (strcmp(flashid, "0808") == 0) {
|
||||
writeSST29LE010_N64();
|
||||
}
|
||||
|
||||
// Close the file:
|
||||
myFile.close();
|
||||
|
||||
@ -2414,18 +2391,6 @@ void resetMSP55LV100_N64(unsigned long flashBase) {
|
||||
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
|
||||
void resetFlashrom_N64(unsigned long flashBase) {
|
||||
// Send reset Command
|
||||
@ -2568,8 +2533,8 @@ void idFlashrom_N64() {
|
||||
resetFlashrom_N64(romBase);
|
||||
}
|
||||
|
||||
//Test for Fujitsu MSP55LV100S (64MB)
|
||||
else {
|
||||
//Test for Fujitsu MSP55LV100S (64MB)
|
||||
// Send flashrom ID command
|
||||
setAddress_N64(romBase + (0x555 << 1));
|
||||
writeWord_N64(0xAAAA);
|
||||
@ -2589,29 +2554,6 @@ void idFlashrom_N64() {
|
||||
cartSize = 64;
|
||||
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() {
|
||||
for (unsigned long currByte = romBase; currByte < romBase + fileSize; currByte += 512) {
|
||||
// Blink led
|
||||
@ -2850,48 +2770,13 @@ boolean blankcheckFlashrom_N64() {
|
||||
|
||||
for (int c = 0; c < 512; c += 2) {
|
||||
if (readWord_N64() != 0xFFFF) {
|
||||
if ((strcmp(flashid, "0808") == 0) && (currByte > romBase + 0x3F) && (currByte < romBase + 0x1080)) {
|
||||
// Gameshark maps this area to the bootcode of the plugged in cartridge
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
void writeIntel4400_N64() {
|
||||
for (unsigned long currSector = 0; currSector < fileSize; currSector += 131072) {
|
||||
@ -3125,12 +3010,7 @@ unsigned long verifyFlashrom_N64() {
|
||||
setAddress_N64(romBase + 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++;
|
||||
}
|
||||
writeErrors++;
|
||||
// Abord if too many errors
|
||||
if (writeErrors > 20) {
|
||||
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
|
||||
//******************************************
|
||||
|
Loading…
Reference in New Issue
Block a user