aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorsplash5 <[email protected]>2023-01-24 16:34:54 +0800
committersplash5 <[email protected]>2023-02-23 12:19:00 +0800
commit79f2a2b16a82b602338e18a0988abd982dcbf0e2 (patch)
treedc1efb71b39841b64300c327fee4ef158adb3801
parentb57470510dc7056882165e45b2e507b82678b54e (diff)
downloadcartreader-79f2a2b16a82b602338e18a0988abd982dcbf0e2.tar.gz
cartreader-79f2a2b16a82b602338e18a0988abd982dcbf0e2.zip
Add support for Super A'can flash cart
-rw-r--r--Cart_Reader/Cart_Reader.ino60
-rw-r--r--Cart_Reader/SUPRACAN.ino142
2 files changed, 180 insertions, 22 deletions
diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino
index b57cf1a..891656e 100644
--- a/Cart_Reader/Cart_Reader.ino
+++ b/Cart_Reader/Cart_Reader.ino
@@ -147,7 +147,7 @@ char ver[5] = "12.3";
//#define enable_WS
// Super A'can
-#define enable_SUPRACAN
+// #define enable_SUPRACAN
//******************************************
// HW CONFIGS
@@ -1007,9 +1007,9 @@ static const char modeItem16[] PROGMEM = "Magnavox Odyssey 2";
static const char modeItem17[] PROGMEM = "Arcadia 2001";
static const char modeItem18[] PROGMEM = "Fairchild Channel F";
static const char modeItem19[] PROGMEM = "Flashrom Programmer";
-static const char modeItem99[] PROGMEM = "Super A'can";
static const char modeItem20[] PROGMEM = "About";
-static const char* const modeOptions[] PROGMEM = { modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14, modeItem15, modeItem16, modeItem17, modeItem18, modeItem99, modeItem19, modeItem20 };
+static const char modeItem99[] PROGMEM = "Super A'can";
+static const char* const modeOptions[] PROGMEM = { modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14, modeItem15, modeItem16, modeItem17, modeItem18, modeItem19, modeItem20, modeItem99 };
// All included slots
void mainMenu() {
@@ -1032,7 +1032,7 @@ void mainMenu() {
num_answers = 7;
} else { // currPage == 3
option_offset = 14;
- num_answers = 6;
+ num_answers = 7;
}
// Copy menuOptions out of progmem
convertPgm(modeOptions + option_offset, num_answers);
@@ -1177,11 +1177,6 @@ void mainMenu() {
case 17:
setup_FAIRCHILD();
fairchildMenu();
-
-#ifdef enable_SUPRACAN
- case 99:
- setup_SuprAcan();
- mode = mode_SUPRACAN;
break;
#endif
@@ -1199,6 +1194,12 @@ void mainMenu() {
aboutScreen();
break;
+#ifdef enable_SUPRACAN
+ case 20:
+ setup_SuprAcan();
+ break;
+#endif
+
default:
print_MissingModule(); // does not return
}
@@ -1227,8 +1228,9 @@ static const char addonsItem1[] PROGMEM = "70s Consoles";
static const char addonsItem2[] PROGMEM = "80s Consoles";
static const char addonsItem3[] PROGMEM = "Handhelds";
static const char addonsItem4[] PROGMEM = "Flashrom Programmer";
+static const char addonsItem5[] PROGMEM = "90s Consoles";
//static const char addonsItem5[] PROGMEM = "Reset"; (stored in common strings array)
-static const char* const addonsOptions[] PROGMEM = { addonsItem1, addonsItem2, addonsItem3, addonsItem4, string_reset2 };
+static const char* const addonsOptions[] PROGMEM = { addonsItem1, addonsItem2, addonsItem3, addonsItem4, string_reset2, addonsItem5 };
// 70s Consoles submenu
static const char consoles70Item1[] PROGMEM = "Atari 2600";
@@ -1316,8 +1318,8 @@ void addonMenu() {
// create menu with title and 5 options to choose from
unsigned char addonsMenu;
// Copy menuOptions out of progmem
- convertPgm(addonsOptions, 5);
- addonsMenu = question_box(F("Type"), menuOptions, 5, 0);
+ convertPgm(addonsOptions, 6);
+ addonsMenu = question_box(F("Type"), menuOptions, 6, 0);
// wait for user choice to come back from the question box menu
switch (addonsMenu) {
@@ -1350,6 +1352,10 @@ void addonMenu() {
resetArduino();
break;
+ case 5:
+ consoles90Menu();
+ break;
+
default:
print_MissingModule(); // does not return
}
@@ -1461,6 +1467,31 @@ void consoles80Menu() {
}
// Everything that needs an adapter
+void consoles90Menu() {
+ unsigned char consoles90Menu;
+ // Copy menuOptions out of progmem
+ convertPgm(consoles90Options, 2);
+ consoles90Menu = question_box(F("Choose Adapter"), menuOptions, 2, 0);
+
+ // wait for user choice to come back from the question box menu
+ switch (consoles90Menu) {
+#ifdef enable_SUPRACAN
+ case 0:
+ setup_SuprAcan();
+ break;
+#endif
+
+ case 1:
+ resetArduino();
+ break;
+
+ default:
+ print_MissingModule(); // does not return
+ break;
+ }
+}
+
+// Everything that needs an adapter
void handheldMenu() {
// create menu with title and 6 options to choose from
unsigned char handheldsMenu;
@@ -3525,6 +3556,11 @@ void loop() {
fairchildMenu();
}
#endif
+#ifdef enable_SUPRACAN
+ else if (mode == mode_SUPRACAN) {
+ suprAcanMenu();
+ }
+#endif
else {
display_Clear();
println_Msg(F("Menu Error"));
diff --git a/Cart_Reader/SUPRACAN.ino b/Cart_Reader/SUPRACAN.ino
index 4cc8a8d..9173f5a 100644
--- a/Cart_Reader/SUPRACAN.ino
+++ b/Cart_Reader/SUPRACAN.ino
@@ -11,8 +11,9 @@ static const char acanMenuItem2[] PROGMEM = "Read Save";
static const char acanMenuItem3[] PROGMEM = "Write Save";
static const char acanMenuItem4[] PROGMEM = "Read UM6650";
static const char acanMenuItem5[] PROGMEM = "Write UM6650";
+static const char acanMenuItem6[] PROGMEM = "Flash...";
-static const char* const menuOptionsAcan[] PROGMEM = {acanMenuItem1, acanMenuItem2, acanMenuItem3, acanMenuItem4, acanMenuItem5, string_reset2};
+static const char* const menuOptionsAcan[] PROGMEM = {acanMenuItem1, acanMenuItem2, acanMenuItem3, acanMenuItem4, acanMenuItem5, string_reset2, acanMenuItem6};
void setup_SuprAcan()
{
@@ -34,11 +35,33 @@ void setup_SuprAcan()
PORTH |= ((1 << 3) | (1 << 5) | (1 << 6));
PORTH &= ~((1 << 0) | (1 << 4));
- // set /CARTIN(PG5) input
- DDRG &= ~(1 << 5);
// set 6619_124(PE4) input
DDRE &= ~(1 << 4);
+ // detect if flash chip exists
+ PORTG |= (1 << 5);
+ DDRG |= (1 << 5);
+ PORTG |= (1 << 5);
+
+ dataOut_MD();
+ writeWord_Acan(0xaaaa, 0xaaaa);
+ writeWord_Acan(0x5555, 0x5555);
+ writeWord_Acan(0xaaaa, 0x9090);
+
+ dataIn_MD();
+ eepbit[0] = readWord_Acan(0x2);
+ eepbit[1] = readWord_Acan(0x0);
+
+ dataOut_MD();
+ writeWord_Acan(0x0, 0xf0f0);
+
+ dataIn_MD();
+ // set /CARTIN(PG5) input
+ PORTG &= ~(1 << 5);
+ DDRG &= ~(1 << 5);
+
+ *((uint32_t*)(eepbit + 4)) = getFlashChipSize_Acan(*((uint16_t*)eepbit));
+
display_Clear();
initializeClockOffset();
@@ -86,10 +109,13 @@ void setup_SuprAcan()
void suprAcanMenu()
{
- uint8_t mainMenu;
+ uint8_t mainMenu = 6;
+
+ if (*((uint32_t*)(eepbit + 4)) > 0)
+ mainMenu = 7;
- convertPgm(menuOptionsAcan, 6);
- mainMenu = question_box(F("Super A'can Menu"), menuOptions, 6, 0);
+ convertPgm(menuOptionsAcan, mainMenu);
+ mainMenu = question_box(F("Super A'can Menu"), menuOptions, mainMenu, 0);
switch (mainMenu)
{
@@ -120,6 +146,11 @@ void suprAcanMenu()
verifyUM6650();
break;
}
+ case 6:
+ {
+ flashCart_Acan();
+ break;
+ }
default:
{
resetCart_Acan();
@@ -139,7 +170,7 @@ static void readROM_Acan()
uint32_t crc32 = 0xffffffff;
EEPROM_readAnything(0, foldern);
- snprintf(folder, FILEPATH_LENGTH, "ACAN/ROM/%d", foldern);
+ snprintf(folder, FILEPATH_LENGTH, "/ACAN/ROM/%d", foldern);
display_Clear();
print_STR(saving_to_STR, 0);
@@ -187,7 +218,7 @@ static void readSRAM_Acan()
{
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
- snprintf(folder, FILEPATH_LENGTH, "ACAN/SAVE/%d", foldern);
+ snprintf(folder, FILEPATH_LENGTH, "/ACAN/SAVE/%d", foldern);
display_Clear();
print_STR(saving_to_STR, 0);
@@ -220,7 +251,7 @@ static void readSRAM_Acan()
static void writeSRAM_Acan()
{
filePath[0] = 0;
- sd.chdir("/");
+ sd.chdir();
fileBrowser(F("Select a file"));
snprintf(filePath, FILEPATH_LENGTH, "%s/%s", filePath, fileName);
@@ -297,7 +328,7 @@ static void readUM6650()
{
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
- snprintf(folder, sizeof(folder), "ACAN/UM6650/%d", foldern);
+ snprintf(folder, sizeof(folder), "/ACAN/UM6650/%d", foldern);
display_Clear();
print_STR(saving_to_STR, 0);
@@ -404,6 +435,84 @@ static void writeUM6650()
print_STR(done_STR, 1);
}
+static void flashCart_Acan()
+{
+ uint32_t *flash_size = (uint32_t*)(eepbit + 4);
+
+ filePath[0] = 0;
+ sd.chdir();
+ fileBrowser(F("Select a file"));
+ snprintf(filePath, FILEPATH_LENGTH, "%s/%s", filePath, fileName);
+
+ display_Clear();
+
+ if (!myFile.open(filePath, O_READ))
+ {
+ print_Error(F("File doesn't exist"));
+ return;
+ }
+
+ print_Msg(F("Writing "));
+ print_Msg(filePath + 1);
+ println_Msg(F("..."));
+ display_Update();
+
+ uint32_t i, j, k, file_length = myFile.fileSize();
+ uint16_t data;
+
+ DDRG |= (1 << 5);
+ PORTG |= (1 << 5);
+
+ draw_progressbar(0, file_length);
+
+ for (i = 0; i < file_length; i += *flash_size)
+ {
+ // erase chip
+ dataOut_MD();
+ writeWord_Acan(i + 0xaaaa, 0xaaaa);
+ writeWord_Acan(i + 0x5555, 0x5555);
+ writeWord_Acan(i + 0xaaaa, 0x8080);
+ writeWord_Acan(i + 0xaaaa, 0xaaaa);
+ writeWord_Acan(i + 0x5555, 0x5555);
+ writeWord_Acan(i + 0xaaaa, 0x1010);
+
+ dataIn_MD();
+ while (readWord_Acan(i) != 0xffff);
+
+ for (j = 0; j < *flash_size; j += 512)
+ {
+ myFile.read(sdBuffer, 512);
+
+ for (k = 0; k < 512; k += 2)
+ {
+ data = *((uint16_t*)(sdBuffer + k));
+
+ dataOut_MD();
+ writeWord_Acan(i + 0xaaaa, 0xaaaa);
+ writeWord_Acan(i + 0x5555, 0x5555);
+ writeWord_Acan(i + 0xaaaa, 0xa0a0);
+ writeWord_Acan(i + j + k, data);
+
+ dataIn_MD();
+ while (readWord_Acan(i + j + k) != data);
+ }
+
+ draw_progressbar(i + j + k, file_length);
+
+ if ((j & 0xfff) == 0)
+ blinkLED();
+ }
+ }
+
+ PORTG &= ~(1 << 5);
+ DDRG &= ~(1 << 5);
+
+ myFile.close();
+
+ print_STR(done_STR, 1);
+ display_Update();
+}
+
static uint32_t checkRomSize_Acan()
{
uint32_t addr = 0;
@@ -559,4 +668,17 @@ static uint16_t readWord_Acan(uint32_t addr)
return data;
}
+static uint32_t getFlashChipSize_Acan(uint16_t chip_id)
+{
+ // 0x0458 (8M), 0x01ab (4M), 0x01d8 (16M)
+ switch (chip_id)
+ {
+ case 0x01ab: return 524288;
+ case 0x0458: return 1048576;
+ case 0x01d8: return 2097152;
+ }
+
+ return 0;
+}
+
#endif