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 romBanks;
word lastByte = 0;
boolean audioWE = 0;
/******************************************
Menu
@ -32,14 +33,20 @@ static const char GBMenuItem3[] PROGMEM = "Write Save";
static const char* const menuOptionsGB[] PROGMEM = { GBMenuItem1, GBMenuItem2, GBMenuItem3, string_reset2 };
// GB Flash items
static const char GBFlashItem1[] PROGMEM = "29F Cart (MBC3)";
static const char GBFlashItem2[] PROGMEM = "29F Cart (MBC5)";
static const char GBFlashItem3[] PROGMEM = "29F Cart (CAM)";
static const char GBFlashItem4[] PROGMEM = "CFI Cart";
static const char GBFlashItem5[] PROGMEM = "CFI Cart and Save";
static const char GBFlashItem6[] PROGMEM = "GB Smart";
//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 };
static const char GBFlashItem1[] PROGMEM = "29F016/32/33 Cart";
static const char GBFlashItem2[] PROGMEM = "CFI Cart";
static const char GBFlashItem3[] PROGMEM = "CFI Cart and Save";
static const char GBFlashItem4[] PROGMEM = "GB Smart";
//static const char GBFlashItem5[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const menuOptionsGBFlash[] PROGMEM = { GBFlashItem1, GBFlashItem2, GBFlashItem3, GBFlashItem4, 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
static const char PelicanRead[] PROGMEM = "Read Device";
@ -78,14 +85,24 @@ void gbxMenu() {
break;
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;
// Copy menuOptions out of progmem
convertPgm(menuOptionsGBFlash, 7);
gbFlash = question_box(F("Select type"), menuOptions, 7, 0);
convertPgm(menuOptionsGBFlash, 5);
gbFlash = question_box(F("Select type"), menuOptions, 5, 0);
// wait for user choice to come back from the question box menu
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:
//Flash MBC3
display_Clear();
@ -125,6 +142,32 @@ void gbxMenu() {
break;
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
display_Clear();
display_Update();
@ -168,7 +211,13 @@ void gbxMenu() {
resetArduino();
break;
case 3:
case 4:
resetArduino();
break;
}
break;
case 1:
// Flash CFI
display_Clear();
display_Update();
@ -196,7 +245,7 @@ void gbxMenu() {
resetArduino();
break;
case 4:
case 2:
// Flash CFI and Save
display_Clear();
display_Update();
@ -271,7 +320,7 @@ void gbxMenu() {
resetArduino();
break;
case 5:
case 3:
// Flash GB Smart
display_Clear();
display_Update();
@ -279,7 +328,7 @@ void gbxMenu() {
mode = mode_GB_GBSmart;
break;
case 6:
case 4:
resetArduino();
break;
}
@ -535,6 +584,11 @@ void setup_GB() {
// Output a low signal on RST(PH0) to initialize MMC correctly
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
DDRC = 0x00;
// Enable Internal Pullups
@ -542,7 +596,7 @@ void setup_GB() {
delay(400);
// RST(PH0) to H
// RST(PH0) to HIGH
PORTH |= (1 << 0);
// Print start page
@ -757,6 +811,9 @@ void writeByte_GB(int myAddress, byte myData) {
"nop\n\t"
"nop\n\t");
if (audioWE)
// Pull Audio-In(PH4) low
PORTH &= ~(1 << 4);
// Pull WR(PH5) low
PORTH &= ~(1 << 5);
@ -766,8 +823,12 @@ void writeByte_GB(int myAddress, byte myData) {
"nop\n\t"
"nop\n\t");
if (audioWE)
// Pull Audio-In(PH4) HIGH
PORTH |= (1 << 4);
// Pull WR(PH5) HIGH
PORTH |= (1 << 5);
// Leave WR high for at least 50ns
__asm__("nop\n\t"
"nop\n\t"
@ -2055,6 +2116,9 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
}
if (MBC == 3) {
if (audioWE)
println_Msg(F("Writing flash MBC30 (Audio)"));
else
println_Msg(F("Writing flash MBC3"));
display_Update();
@ -2073,6 +2137,9 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
// Set ROM bank
writeByte_GB(0x2100, currBank);
if (romBanks > 128)
// Map SRAM Bank to prevent getting stuck at 0x2A8000
writeByte_GB(0x4000, 0x0);
if (currBank > 0) {
currAddr = 0x4000;
@ -2094,7 +2161,25 @@ void writeFlash29F_GB(byte MBC, boolean flashErase) {
PORTH &= ~(1 << 6);
// Busy check
//byte count = 0;
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