Add support for MBC30 flash cart by HDR (thx to ManCloud)

Two issues were resolved:
- this flashcart uses the Audio-In pin instead of the WR pin
- Writing 4MB gets stuck after bank 170 and needed the SRAM to be mapped (same as MBC5)
This commit is contained in:
sanni 2024-02-29 09:36:23 +01:00
parent 5f3983b36c
commit f947fb4e3f

View File

@ -10,6 +10,7 @@
word sramBanks; word sramBanks;
word romBanks; word romBanks;
word lastByte = 0; word lastByte = 0;
boolean audioWE = 0;
/****************************************** /******************************************
Menu Menu
@ -32,14 +33,20 @@ static const char GBMenuItem3[] PROGMEM = "Write Save";
static const char* const menuOptionsGB[] PROGMEM = { GBMenuItem1, GBMenuItem2, GBMenuItem3, string_reset2 }; static const char* const menuOptionsGB[] PROGMEM = { GBMenuItem1, GBMenuItem2, GBMenuItem3, string_reset2 };
// GB Flash items // GB Flash items
static const char GBFlashItem1[] PROGMEM = "29F Cart (MBC3)"; static const char GBFlashItem1[] PROGMEM = "29F016/32/33 Cart";
static const char GBFlashItem2[] PROGMEM = "29F Cart (MBC5)"; static const char GBFlashItem2[] PROGMEM = "CFI Cart";
static const char GBFlashItem3[] PROGMEM = "29F Cart (CAM)"; static const char GBFlashItem3[] PROGMEM = "CFI Cart and Save";
static const char GBFlashItem4[] PROGMEM = "CFI Cart"; static const char GBFlashItem4[] PROGMEM = "GB Smart";
static const char GBFlashItem5[] PROGMEM = "CFI Cart and Save"; //static const char GBFlashItem5[] PROGMEM = "Reset"; (stored in common strings array)
static const char GBFlashItem6[] PROGMEM = "GB Smart"; static const char* const menuOptionsGBFlash[] PROGMEM = { GBFlashItem1, GBFlashItem2, GBFlashItem3, GBFlashItem4, string_reset2 };
//static const char GBFlashItem7[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsGBFlash[] PROGMEM = { GBFlashItem1, GBFlashItem2, GBFlashItem3, GBFlashItem4, GBFlashItem5, GBFlashItem6, string_reset2 }; // 29F Flash items
static const char GBFlash29Item1[] PROGMEM = "DIY MBC3 (WR)";
static const char GBFlash29Item2[] PROGMEM = "DIY MBC5 (WR)";
static const char GBFlash29Item3[] PROGMEM = "HDR MBC30 (Audio)";
static const char GBFlash29Item4[] PROGMEM = "HDR GameBoy Cam";
//static const char GBFlashItem5[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsGBFlash29[] PROGMEM = { GBFlash29Item1, GBFlash29Item2, GBFlash29Item3, GBFlash29Item4, string_reset2 };
// Pelican Codebreaker, Brainboy, and Monster Brain Operation Menu // Pelican Codebreaker, Brainboy, and Monster Brain Operation Menu
static const char PelicanRead[] PROGMEM = "Read Device"; static const char PelicanRead[] PROGMEM = "Read Device";
@ -78,14 +85,24 @@ void gbxMenu() {
break; break;
case 2: case 2:
// create submenu with title and 7 options to choose from // create submenu with title and 5 options to choose from
unsigned char gbFlash; unsigned char gbFlash;
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(menuOptionsGBFlash, 7); convertPgm(menuOptionsGBFlash, 5);
gbFlash = question_box(F("Select type"), menuOptions, 7, 0); gbFlash = question_box(F("Select type"), menuOptions, 5, 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 (gbFlash) { switch (gbFlash) {
case 0:
//29F Menu
// create submenu with title and 5 options to choose from
unsigned char gbFlash29;
// Copy menuOptions out of progmem
convertPgm(menuOptionsGBFlash29, 5);
gbFlash29 = question_box(F("Select MBC"), menuOptions, 5, 0);
// wait for user choice to come back from the question box menu
switch (gbFlash29) {
case 0: case 0:
//Flash MBC3 //Flash MBC3
display_Clear(); display_Clear();
@ -125,6 +142,32 @@ void gbxMenu() {
break; break;
case 2: case 2:
//Also pulse Audio-In during writes
display_Clear();
display_Update();
setup_GB();
mode = mode_GB;
//Setup Audio-In(PH4) as Output
DDRH |= (1 << 4);
// Output a high signal on Audio-In(PH4)
PORTH |= (1 << 4);
//Tell writeByte_GB function to pulse Audio-In too
audioWE = 1;
// Change working dir to root
sd.chdir("/");
//MBC5
writeFlash29F_GB(3, 1);
// Reset
// Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1);
display_Update();
wait();
resetArduino();
break;
case 3:
//Flash GB Camera //Flash GB Camera
display_Clear(); display_Clear();
display_Update(); display_Update();
@ -168,7 +211,13 @@ void gbxMenu() {
resetArduino(); resetArduino();
break; break;
case 3: case 4:
resetArduino();
break;
}
break;
case 1:
// Flash CFI // Flash CFI
display_Clear(); display_Clear();
display_Update(); display_Update();
@ -196,7 +245,7 @@ void gbxMenu() {
resetArduino(); resetArduino();
break; break;
case 4: case 2:
// Flash CFI and Save // Flash CFI and Save
display_Clear(); display_Clear();
display_Update(); display_Update();
@ -271,7 +320,7 @@ void gbxMenu() {
resetArduino(); resetArduino();
break; break;
case 5: case 3:
// Flash GB Smart // Flash GB Smart
display_Clear(); display_Clear();
display_Update(); display_Update();
@ -279,7 +328,7 @@ void gbxMenu() {
mode = mode_GB_GBSmart; mode = mode_GB_GBSmart;
break; break;
case 6: case 4:
resetArduino(); resetArduino();
break; break;
} }
@ -535,6 +584,11 @@ void setup_GB() {
// Output a low signal on RST(PH0) to initialize MMC correctly // Output a low signal on RST(PH0) to initialize MMC correctly
PORTH &= ~((1 << 0) | (1 << 1)); PORTH &= ~((1 << 0) | (1 << 1));
// Set Audio-In(PH4) to Input
DDRH &= ~(1 << 4);
// Enable Internal Pullup
PORTH |= (1 << 4);
// Set Data Pins (D0-D7) to Input // Set Data Pins (D0-D7) to Input
DDRC = 0x00; DDRC = 0x00;
// Enable Internal Pullups // Enable Internal Pullups
@ -542,7 +596,7 @@ void setup_GB() {
delay(400); delay(400);
// RST(PH0) to H // RST(PH0) to HIGH
PORTH |= (1 << 0); PORTH |= (1 << 0);
// Print start page // Print start page
@ -757,6 +811,9 @@ void writeByte_GB(int myAddress, byte myData) {
"nop\n\t" "nop\n\t"
"nop\n\t"); "nop\n\t");
if (audioWE)
// Pull Audio-In(PH4) low
PORTH &= ~(1 << 4);
// Pull WR(PH5) low // Pull WR(PH5) low
PORTH &= ~(1 << 5); PORTH &= ~(1 << 5);
@ -766,8 +823,12 @@ void writeByte_GB(int myAddress, byte myData) {
"nop\n\t" "nop\n\t"
"nop\n\t"); "nop\n\t");
if (audioWE)
// Pull Audio-In(PH4) HIGH
PORTH |= (1 << 4);
// Pull WR(PH5) HIGH // Pull WR(PH5) HIGH
PORTH |= (1 << 5); PORTH |= (1 << 5);
// Leave WR high for at least 50ns // Leave WR high for at least 50ns
__asm__("nop\n\t" __asm__("nop\n\t"
"nop\n\t" "nop\n\t"
@ -2055,6 +2116,9 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
} }
if (MBC == 3) { if (MBC == 3) {
if (audioWE)
println_Msg(F("Writing flash MBC30 (Audio)"));
else
println_Msg(F("Writing flash MBC3")); println_Msg(F("Writing flash MBC3"));
display_Update(); display_Update();
@ -2073,6 +2137,9 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
// Set ROM bank // Set ROM bank
writeByte_GB(0x2100, currBank); writeByte_GB(0x2100, currBank);
if (romBanks > 128)
// Map SRAM Bank to prevent getting stuck at 0x2A8000
writeByte_GB(0x4000, 0x0);
if (currBank > 0) { if (currBank > 0) {
currAddr = 0x4000; currAddr = 0x4000;
@ -2094,7 +2161,25 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
PORTH &= ~(1 << 6); PORTH &= ~(1 << 6);
// Busy check // Busy check
//byte count = 0;
while ((PINC & 0x80) != (sdBuffer[currByte] & 0x80)) { while ((PINC & 0x80) != (sdBuffer[currByte] & 0x80)) {
/*
// Debug
count++;
__asm__("nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t");
if (count > 250) {
println_Msg("");
print_Msg(F("Bank: "));
print_Msg(currBank);
print_Msg(F(" Addr: "));
println_Msg(currAddr + currByte);
display_Update();
wait();
}
*/
} }
// Switch OE/RD(PH6) to HIGH // Switch OE/RD(PH6) to HIGH