mirror of
https://github.com/sanni/cartreader.git
synced 2024-11-14 17:05:08 +01:00
V25: Enabled reading of Nintendo Power GB Memory cartridges
Not super reliable right now.
This commit is contained in:
parent
fcd4400f83
commit
2b631600f9
@ -2,8 +2,8 @@
|
|||||||
Cartridge Reader for Arduino Mega2560
|
Cartridge Reader for Arduino Mega2560
|
||||||
|
|
||||||
Author: sanni
|
Author: sanni
|
||||||
Date: 2017-05-21
|
Date: 2017-05-30
|
||||||
Version: V24E
|
Version: V25
|
||||||
|
|
||||||
SD lib: https://github.com/greiman/SdFat
|
SD lib: https://github.com/greiman/SdFat
|
||||||
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
LCD lib: https://github.com/adafruit/Adafruit_SSD1306
|
||||||
@ -34,7 +34,7 @@
|
|||||||
YamaArashi - GBA flashrom bank switch command
|
YamaArashi - GBA flashrom bank switch command
|
||||||
|
|
||||||
**********************************************************************************/
|
**********************************************************************************/
|
||||||
char ver[5] = "V24E";
|
char ver[5] = "V25";
|
||||||
|
|
||||||
/******************************************
|
/******************************************
|
||||||
Define Output
|
Define Output
|
||||||
@ -170,7 +170,7 @@ boolean ignoreError;
|
|||||||
|
|
||||||
// File browser
|
// File browser
|
||||||
char fileName[26];
|
char fileName[26];
|
||||||
char filePath[36];
|
char filePath[50];
|
||||||
byte currPage;
|
byte currPage;
|
||||||
byte lastPage;
|
byte lastPage;
|
||||||
byte numPages;
|
byte numPages;
|
||||||
@ -407,8 +407,8 @@ void mainMenu() {
|
|||||||
// 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
|
||||||
convertPgm(menuOptionsNP, 1);
|
convertPgm(menuOptionsNP, 2);
|
||||||
npCart = question_box("Select NP Cart", menuOptions, 1, 0);
|
npCart = question_box("Select NP Cart", menuOptions, 2, 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 (npCart)
|
switch (npCart)
|
||||||
|
@ -271,6 +271,22 @@ void sfmFlashMenu() {
|
|||||||
|
|
||||||
// Write Flash
|
// Write Flash
|
||||||
case 1:
|
case 1:
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
|
// Print warning
|
||||||
|
println_Msg(F("Attention"));
|
||||||
|
println_Msg(F("This will erase your"));
|
||||||
|
println_Msg(F("NP Cartridge."));
|
||||||
|
println_Msg("");
|
||||||
|
println_Msg(F("Press Button"));
|
||||||
|
println_Msg(F("to continue"));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
filePath[0] = '\0';
|
filePath[0] = '\0';
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
// Launch file browser
|
// Launch file browser
|
||||||
@ -377,6 +393,19 @@ void sfmFlashMenu() {
|
|||||||
// Clear screen
|
// Clear screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
|
// Print warning
|
||||||
|
println_Msg(F("Attention"));
|
||||||
|
println_Msg(F("This will erase your"));
|
||||||
|
println_Msg(F("NP Cartridge."));
|
||||||
|
println_Msg("");
|
||||||
|
println_Msg(F("Press Button"));
|
||||||
|
println_Msg(F("to continue"));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
// Reset to root directory
|
// Reset to root directory
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
|
|
||||||
@ -1438,8 +1467,8 @@ void write_SFM(int startBank, uint32_t pos) {
|
|||||||
*****************************************/
|
*****************************************/
|
||||||
// GBM menu items
|
// GBM menu items
|
||||||
static const char gbmMenuItem1[] PROGMEM = "Read Flash";
|
static const char gbmMenuItem1[] PROGMEM = "Read Flash";
|
||||||
static const char gbmMenuItem2[] PROGMEM = "Write Flash";
|
static const char gbmMenuItem2[] PROGMEM = "Read Mapping";
|
||||||
static const char gbmMenuItem3[] PROGMEM = "Read Mapping";
|
static const char gbmMenuItem3[] PROGMEM = "Write Flash";
|
||||||
static const char gbmMenuItem4[] PROGMEM = "Write Mapping";
|
static const char gbmMenuItem4[] PROGMEM = "Write Mapping";
|
||||||
static const char* const menuOptionsGBM[] PROGMEM = {gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4};
|
static const char* const menuOptionsGBM[] PROGMEM = {gbmMenuItem1, gbmMenuItem2, gbmMenuItem3, gbmMenuItem4};
|
||||||
|
|
||||||
@ -1447,8 +1476,8 @@ void gbmMenu() {
|
|||||||
// create menu with title and 4 options to choose from
|
// create menu with title and 4 options to choose from
|
||||||
unsigned char mainMenu;
|
unsigned char mainMenu;
|
||||||
// Copy menuOptions out of progmem
|
// Copy menuOptions out of progmem
|
||||||
convertPgm(menuOptionsGBM, 4);
|
convertPgm(menuOptionsGBM, 2);
|
||||||
mainMenu = question_box("GB Memory Menu", menuOptions, 4, 0);
|
mainMenu = question_box("GB Memory Menu", menuOptions, 2, 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 (mainMenu)
|
switch (mainMenu)
|
||||||
@ -1464,23 +1493,8 @@ void gbmMenu() {
|
|||||||
readFlash_GBM();
|
readFlash_GBM();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Write Flash
|
// Read mapping
|
||||||
case 1:
|
case 1:
|
||||||
filePath[0] = '\0';
|
|
||||||
sd.chdir("/");
|
|
||||||
// Launch file browser
|
|
||||||
fileBrowser("Select 1MB file");
|
|
||||||
display_Clear();
|
|
||||||
sprintf(filePath, "%s/%s", filePath, fileName);
|
|
||||||
println_Msg(F("Writing rom"));
|
|
||||||
display_Update();
|
|
||||||
|
|
||||||
// Write flash
|
|
||||||
writeFlash_GBM();
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Print mapping
|
|
||||||
case 2:
|
|
||||||
// Clear screen
|
// Clear screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
@ -1491,11 +1505,53 @@ void gbmMenu() {
|
|||||||
readMapping_GBM();
|
readMapping_GBM();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Write Flash
|
||||||
|
case 2:
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
|
// Print warning
|
||||||
|
println_Msg(F("Attention"));
|
||||||
|
println_Msg(F("This will erase your"));
|
||||||
|
println_Msg(F("NP Cartridge."));
|
||||||
|
println_Msg("");
|
||||||
|
println_Msg(F("Press Button"));
|
||||||
|
println_Msg(F("to continue"));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
|
filePath[0] = '\0';
|
||||||
|
sd.chdir("/");
|
||||||
|
// Launch file browser
|
||||||
|
fileBrowser("Select 1MB file");
|
||||||
|
display_Clear();
|
||||||
|
sprintf(filePath, "%s/%s", filePath, fileName);
|
||||||
|
|
||||||
|
// Write rom
|
||||||
|
writeRom_GBM();
|
||||||
|
break;
|
||||||
|
|
||||||
// Write mapping
|
// Write mapping
|
||||||
case 3:
|
case 3:
|
||||||
// Clear screen
|
// Clear screen
|
||||||
display_Clear();
|
display_Clear();
|
||||||
|
|
||||||
|
// Print warning
|
||||||
|
println_Msg(F("Attention"));
|
||||||
|
println_Msg(F("This will erase your"));
|
||||||
|
println_Msg(F("NP Cartridge."));
|
||||||
|
println_Msg("");
|
||||||
|
println_Msg(F("Press Button"));
|
||||||
|
println_Msg(F("to continue"));
|
||||||
|
display_Update();
|
||||||
|
wait();
|
||||||
|
|
||||||
|
// Clear screen
|
||||||
|
display_Clear();
|
||||||
|
|
||||||
// Reset to root directory
|
// Reset to root directory
|
||||||
sd.chdir("/");
|
sd.chdir("/");
|
||||||
|
|
||||||
@ -1758,9 +1814,11 @@ boolean wakeup_GBM() {
|
|||||||
// First byte of NP register is always 0x21
|
// First byte of NP register is always 0x21
|
||||||
while (readByte_GBM(0x0120) != 0x21) {
|
while (readByte_GBM(0x0120) != 0x21) {
|
||||||
send_GBM(0x09);
|
send_GBM(0x09);
|
||||||
|
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
|
||||||
timeout++;
|
timeout++;
|
||||||
if (timeout > 4) {
|
if (timeout > 10) {
|
||||||
print_Error(F("Error: Time Out"), true);
|
println_Msg(F("Error: Time Out"));
|
||||||
|
print_Error(F("Please power cycle"), true);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1888,14 +1946,85 @@ void readFlash_GBM() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void eraseFlash_GBM() {
|
void eraseFlash_GBM() {
|
||||||
|
// Enable ports 0x0120...
|
||||||
|
wakeup_GBM();
|
||||||
|
|
||||||
|
// Set WE and WP
|
||||||
|
enableWrite_GBM();
|
||||||
|
|
||||||
|
// Unprotect sector 0
|
||||||
|
writeByte_GBM(0x2100, 0x01);
|
||||||
|
send_Flash(0x5555, 0xAA);
|
||||||
|
send_Flash(0x2AAA, 0x55);
|
||||||
|
send_Flash(0x5555, 0x60);
|
||||||
|
send_Flash(0x5555, 0xAA);
|
||||||
|
send_Flash(0x2AAA, 0x55);
|
||||||
|
writeByte_GBM(0x2100, 0x0);
|
||||||
|
send_Flash(0x0000, 0x40);
|
||||||
|
|
||||||
|
// Send erase command
|
||||||
|
writeByte_GBM(0x2100, 0x01);
|
||||||
|
send_Flash(0x5555, 0xaa);
|
||||||
|
send_Flash(0x2AAA, 0x55);
|
||||||
|
send_Flash(0x5555, 0x80);
|
||||||
|
send_Flash(0x5555, 0xaa);
|
||||||
|
send_Flash(0x2AAA, 0x55);
|
||||||
|
send_Flash(0x5555, 0x10);
|
||||||
|
|
||||||
|
// Wait for erase to complete
|
||||||
|
while ((readByte_GBM(0) & 0x80) != 0x80) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean blankcheckFlash_GBM() {
|
boolean blankcheckFlash_GBM() {
|
||||||
|
// Reset flashrom
|
||||||
|
resetFlash_GBM();
|
||||||
|
// Map entire flashrom
|
||||||
|
//send_GBM(0x04);
|
||||||
|
// Disable ports 0x0120...
|
||||||
|
send_GBM(0x08);
|
||||||
|
|
||||||
|
// Read rom
|
||||||
|
word currAddress = 0;
|
||||||
|
|
||||||
|
for (byte currBank = 1; currBank < 64; currBank++) {
|
||||||
|
// Set rom bank
|
||||||
|
writeByte_GBM(0x2100, currBank);
|
||||||
|
|
||||||
|
// Switch bank start address
|
||||||
|
if (currBank > 1) {
|
||||||
|
currAddress = 0x4000;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; currAddress < 0x7FFF; currAddress++) {
|
||||||
|
if (readByte_GBM(currAddress) != 0xFF) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeFlash_GBM() {
|
void writeFlash_GBM() {
|
||||||
|
// Open file on sd card
|
||||||
|
if (myFile.open(filePath, O_READ)) {
|
||||||
|
// Get rom size from file
|
||||||
|
fileSize = myFile.fileSize();
|
||||||
|
|
||||||
|
for (unsigned long currBuffer = 0; currBuffer < fileSize; currBuffer += 128) {
|
||||||
|
// Fill SD buffer
|
||||||
|
myFile.read(sdBuffer, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the file:
|
||||||
|
myFile.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print_Error(F("Can't open file"), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeRom_GBM() {
|
||||||
// Enable ports 0x0120...
|
// Enable ports 0x0120...
|
||||||
wakeup_GBM();
|
wakeup_GBM();
|
||||||
|
|
||||||
@ -1903,10 +2032,14 @@ void writeFlash_GBM() {
|
|||||||
if (readFlashID_GBM()) {
|
if (readFlashID_GBM()) {
|
||||||
// Reset flashrom to leave flashID area and switch to output
|
// Reset flashrom to leave flashID area and switch to output
|
||||||
resetFlash_GBM();
|
resetFlash_GBM();
|
||||||
// Earse flash
|
// Erase flash
|
||||||
|
print_Msg(F("Erasing..."));
|
||||||
|
display_Update();
|
||||||
eraseFlash_GBM();
|
eraseFlash_GBM();
|
||||||
if (blankcheckFlash_GBM()) {
|
if (blankcheckFlash_GBM()) {
|
||||||
|
println_Msg(F("Ok"));
|
||||||
|
display_Update();
|
||||||
|
writeFlash_GBM();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_Error(F("Erase failed"), true);
|
print_Error(F("Erase failed"), true);
|
||||||
|
Loading…
Reference in New Issue
Block a user