mirror of
https://github.com/sanni/cartreader.git
synced 2024-12-28 14:01:52 +01:00
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:
parent
5f3983b36c
commit
f947fb4e3f
@ -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
|
||||||
@ -2603,7 +2688,7 @@ void readPelican_GB() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
word finalAddress = 0x3FFF;
|
word finalAddress = 0x3FFF;
|
||||||
word startAddress= 0x2000;
|
word startAddress = 0x2000;
|
||||||
word bankAddress = 0xA000;
|
word bankAddress = 0xA000;
|
||||||
|
|
||||||
//Enable bank addressing in the CPLD
|
//Enable bank addressing in the CPLD
|
||||||
@ -3036,7 +3121,7 @@ bool isToggle(byte byte1, byte byte2) {
|
|||||||
******************************************************/
|
******************************************************/
|
||||||
// Read Mega Memory Card Rom and Save Backup Data
|
// Read Mega Memory Card Rom and Save Backup Data
|
||||||
void readMegaMem_GB() {
|
void readMegaMem_GB() {
|
||||||
// Dump the Rom
|
// Dump the Rom
|
||||||
strcpy(fileName, "Rom");
|
strcpy(fileName, "Rom");
|
||||||
strcat(fileName, ".GB");
|
strcat(fileName, ".GB");
|
||||||
|
|
||||||
@ -3059,7 +3144,7 @@ void readMegaMem_GB() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
word finalAddress = 0x3FFF;
|
word finalAddress = 0x3FFF;
|
||||||
word startAddress= 0x0;
|
word startAddress = 0x0;
|
||||||
|
|
||||||
// Initialize progress bar
|
// Initialize progress bar
|
||||||
uint32_t processedProgressBar = 0;
|
uint32_t processedProgressBar = 0;
|
||||||
@ -3101,7 +3186,7 @@ void readMegaMem_GB() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
finalAddress = 0x7FFF;
|
finalAddress = 0x7FFF;
|
||||||
startAddress= 0x4000;
|
startAddress = 0x4000;
|
||||||
word bankAddress = 0x2000;
|
word bankAddress = 0x2000;
|
||||||
romBanks = 32;
|
romBanks = 32;
|
||||||
|
|
||||||
@ -3364,7 +3449,7 @@ void readGameshark_GB() {
|
|||||||
strcat(fileName, ".GB");
|
strcat(fileName, ".GB");
|
||||||
|
|
||||||
word finalAddress = 0x5FFF;
|
word finalAddress = 0x5FFF;
|
||||||
word startAddress= 0x4000;
|
word startAddress = 0x4000;
|
||||||
word bankAddress = 0x7FE1;
|
word bankAddress = 0x7FE1;
|
||||||
romBanks = 16;
|
romBanks = 16;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user