V12.6 Add MSX and Pokemon Mini modules (thx to skaman)

This commit is contained in:
sanni 2023-06-25 14:09:17 +02:00
parent e86662c640
commit abe029eefc
5 changed files with 2023 additions and 24 deletions

View File

@ -4,8 +4,8 @@
This project represents a community-driven effort to provide This project represents a community-driven effort to provide
an easy to build and easy to modify cartridge dumper. an easy to build and easy to modify cartridge dumper.
Date: 2023-03-29 Date: 2023-06-25
Version: 12.5 Version: 12.6
SD lib: https://github.com/greiman/SdFat SD lib: https://github.com/greiman/SdFat
LCD lib: https://github.com/olikraus/u8g2 LCD lib: https://github.com/olikraus/u8g2
@ -15,13 +15,13 @@
RTC lib: https://github.com/adafruit/RTClib RTC lib: https://github.com/adafruit/RTClib
Frequency lib: https://github.com/PaulStoffregen/FreqCount Frequency lib: https://github.com/PaulStoffregen/FreqCount
Compiled with Arduino IDE 2.0.4 Compiled with Arduino IDE 2.1.0
Thanks to: Thanks to:
MichlK - ROM Reader for Super Nintendo MichlK - ROM Reader for Super Nintendo
Jeff Saltzman - 4-Way Button Jeff Saltzman - 4-Way Button
Wayne and Layne - Video Game Shield menu Wayne and Layne - Video Game Shield menu
skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco-, Intellivision, Virtual Boy, WSV, PCW, ARC, Atari, ODY2, Fairchild modules skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco-, Intellivision, Virtual Boy, WSV, PCW, ARC, Atari, ODY2, Fairchild, MSX2, Pokemon Mini modules
Tamanegi_taro - PCE and Satellaview modules Tamanegi_taro - PCE and Satellaview modules
splash5 - GBSmart, Wonderswan, NGP and Super A'can modules splash5 - GBSmart, Wonderswan, NGP and Super A'can modules
hkz & themanbehindthecurtain - N64 flashram commands hkz & themanbehindthecurtain - N64 flashram commands
@ -38,7 +38,7 @@
jiyunomegami, splash5, Kreeblah, ramapcsx2, PsyK0p4T, Dakkaron, majorpbx, Pickle, sdhizumi, jiyunomegami, splash5, Kreeblah, ramapcsx2, PsyK0p4T, Dakkaron, majorpbx, Pickle, sdhizumi,
Uzlopak, sakman55, Tombo89, scrap-a, borti4938, vogelfreiheit, CaitSith2, Modman, Uzlopak, sakman55, Tombo89, scrap-a, borti4938, vogelfreiheit, CaitSith2, Modman,
philenotfound, karimhadjsalem, nsx0r, ducky92, niklasweber, Lesserkuma, BacteriaMage, philenotfound, karimhadjsalem, nsx0r, ducky92, niklasweber, Lesserkuma, BacteriaMage,
vpelletier, Ancyker, mattiacci, RWeick vpelletier, Ancyker, mattiacci, RWeick, joshman196
And to nocash for figuring out the secrets of the SFC Nintendo Power cartridge. And to nocash for figuring out the secrets of the SFC Nintendo Power cartridge.
@ -248,6 +248,8 @@ void print_STR(byte string_number, boolean newline) {
#define mode_ARC 30 #define mode_ARC 30
#define mode_FAIRCHILD 31 #define mode_FAIRCHILD 31
#define mode_SUPRACAN 32 #define mode_SUPRACAN 32
#define mode_MSX 33
#define mode_POKE 34
// optimization-safe nop delay // optimization-safe nop delay
#define NOP __asm__ __volatile__("nop\n\t") #define NOP __asm__ __volatile__("nop\n\t")
@ -491,7 +493,7 @@ uint32_t calculateCRC(char* fileName, char* folder, int offset) {
/****************************************** /******************************************
CRC Functions for Atari, Fairchild, Ody2, Arc modules CRC Functions for Atari, Fairchild, Ody2, Arc modules
*****************************************/ *****************************************/
#if (defined(enable_ATARI) || defined(enable_ODY2) || defined(enable_ARC) || defined(enable_FAIRCHILD)) #if (defined(enable_ATARI) || defined(enable_ODY2) || defined(enable_ARC) || defined(enable_FAIRCHILD) || defined(enable_MSX) || defined(enable_POKE))
inline uint32_t updateCRC(uint8_t ch, uint32_t crc) { inline uint32_t updateCRC(uint8_t ch, uint32_t crc) {
uint32_t idx = ((crc) ^ (ch)) & 0xff; uint32_t idx = ((crc) ^ (ch)) & 0xff;
@ -842,11 +844,13 @@ static const char modeItem16[] PROGMEM = "Magnavox Odyssey 2";
static const char modeItem17[] PROGMEM = "Arcadia 2001"; static const char modeItem17[] PROGMEM = "Arcadia 2001";
static const char modeItem18[] PROGMEM = "Fairchild Channel F"; static const char modeItem18[] PROGMEM = "Fairchild Channel F";
static const char modeItem19[] PROGMEM = "Super A'can"; static const char modeItem19[] PROGMEM = "Super A'can";
static const char modeItem20[] PROGMEM = "Flashrom Programmer"; static const char modeItem20[] PROGMEM = "MSX";
static const char modeItem21[] PROGMEM = "Self Test"; static const char modeItem21[] PROGMEM = "Pokemon Mini (3V)";
static const char modeItem22[] PROGMEM = "About"; static const char modeItem22[] PROGMEM = "Flashrom Programmer";
//static const char modeItem22[] PROGMEM = "Reset"; (stored in common strings array) static const char modeItem23[] PROGMEM = "Self Test";
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, modeItem21, modeItem22, string_reset2 }; static const char modeItem24[] PROGMEM = "About";
//static const char modeItem25[] PROGMEM = "Reset"; (stored in common strings array)
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, modeItem21, modeItem22, modeItem23, modeItem24, string_reset2 };
// All included slots // All included slots
void mainMenu() { void mainMenu() {
@ -872,7 +876,7 @@ void mainMenu() {
num_answers = 7; num_answers = 7;
} else { // currPage == 4 } else { // currPage == 4
option_offset = 21; option_offset = 21;
num_answers = 2; num_answers = 4;
} }
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(modeOptions + option_offset, num_answers); convertPgm(modeOptions + option_offset, num_answers);
@ -1026,23 +1030,37 @@ void mainMenu() {
break; break;
#endif #endif
#ifdef enable_FLASH #ifdef enable_MSX
case 19: case 19:
setup_MSX();
msxMenu();
break;
#endif
#ifdef enable_POKE
case 20:
setup_POKE();
pokeMenu();
break;
#endif
#ifdef enable_FLASH
case 21:
flashMenu(); flashMenu();
break; break;
#endif #endif
#ifdef enable_selftest #ifdef enable_selftest
case 20: case 22:
selfTest(); selfTest();
break; break;
#endif #endif
case 21: case 23:
aboutScreen(); aboutScreen();
break; break;
case 22: case 24:
resetArduino(); resetArduino();
break; break;
@ -1093,8 +1111,9 @@ static const char* const consoles70Options[] PROGMEM = { consoles70Item1, consol
static const char consoles80Item1[] PROGMEM = "NES/Famicom"; static const char consoles80Item1[] PROGMEM = "NES/Famicom";
static const char consoles80Item2[] PROGMEM = "PC Engine/TG16"; static const char consoles80Item2[] PROGMEM = "PC Engine/TG16";
static const char consoles80Item3[] PROGMEM = "SMS/GG/MIII/SG-1000"; static const char consoles80Item3[] PROGMEM = "SMS/GG/MIII/SG-1000";
//static const char consoles80Item4[] PROGMEM = "Reset"; (stored in common strings array) static const char consoles80Item4[] PROGMEM = "MSX";
static const char* const consoles80Options[] PROGMEM = { consoles80Item1, consoles80Item2, consoles80Item3, string_reset2 }; //static const char consoles80Item5[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const consoles80Options[] PROGMEM = { consoles80Item1, consoles80Item2, consoles80Item3, consoles80Item4, string_reset2 };
// 90s Consoles submenu // 90s Consoles submenu
static const char consoles90Item1[] PROGMEM = "Super A'can"; static const char consoles90Item1[] PROGMEM = "Super A'can";
@ -1106,8 +1125,9 @@ static const char handheldsItem2[] PROGMEM = "WonderSwan (3V)";
static const char handheldsItem3[] PROGMEM = "NeoGeo Pocket (3V)"; static const char handheldsItem3[] PROGMEM = "NeoGeo Pocket (3V)";
static const char handheldsItem4[] PROGMEM = "Watara Supervision"; static const char handheldsItem4[] PROGMEM = "Watara Supervision";
static const char handheldsItem5[] PROGMEM = "Pocket Challenge W"; static const char handheldsItem5[] PROGMEM = "Pocket Challenge W";
static const char handheldsItem6[] PROGMEM = "Pokemon Mini (3V)";
//static const char handheldsItem6[] PROGMEM = "Reset"; (stored in common strings array) //static const char handheldsItem6[] PROGMEM = "Reset"; (stored in common strings array)
static const char* const handheldsOptions[] PROGMEM = { handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4, handheldsItem5, string_reset2 }; static const char* const handheldsOptions[] PROGMEM = { handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4, handheldsItem5, handheldsItem6, string_reset2 };
// All included slots // All included slots
void mainMenu() { void mainMenu() {
@ -1275,8 +1295,8 @@ void consoles80Menu() {
// create menu with title and 6 options to choose from // create menu with title and 6 options to choose from
unsigned char consoles80Menu; unsigned char consoles80Menu;
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(consoles80Options, 4); convertPgm(consoles80Options, 5);
consoles80Menu = question_box(F("Choose Adapter"), menuOptions, 4, 0); consoles80Menu = question_box(F("Choose Adapter"), 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 (consoles80Menu) { switch (consoles80Menu) {
@ -1306,7 +1326,14 @@ void consoles80Menu() {
break; break;
#endif #endif
#ifdef enable_MSX
case 3: case 3:
setup_MSX();
msxMenu();
break;
#endif
case 4:
resetArduino(); resetArduino();
break; break;
@ -1345,8 +1372,8 @@ void handheldMenu() {
// create menu with title and 6 options to choose from // create menu with title and 6 options to choose from
unsigned char handheldsMenu; unsigned char handheldsMenu;
// Copy menuOptions out of progmem // Copy menuOptions out of progmem
convertPgm(handheldsOptions, 6); convertPgm(handheldsOptions, 7);
handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 6, 0); handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 7, 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 (handheldsMenu) { switch (handheldsMenu) {
@ -1389,7 +1416,14 @@ void handheldMenu() {
break; break;
#endif #endif
#ifdef enable_POKE
case 5: case 5:
setup_POKE();
pokeMenu();
break;
#endif
case 6:
resetArduino(); resetArduino();
break; break;
@ -3548,6 +3582,16 @@ void loop() {
else if (mode == mode_SUPRACAN) { else if (mode == mode_SUPRACAN) {
suprAcanMenu(); suprAcanMenu();
} }
#endif
#ifdef enable_MSX
else if (mode == mode_MSX) {
msxMenu();
}
#endif
#ifdef enable_POKE
else if (mode == mode_POKE) {
pokeMenu();
}
#endif #endif
else { else {
display_Clear(); display_Clear();

View File

@ -151,6 +151,13 @@
/****/ /****/
/* [ MSX ------------------------------------------- ]
*/
//#define enable_MSX
/****/
/* [ PC Engine/TurboGrafx 16 -------------------------------------- ] /* [ PC Engine/TurboGrafx 16 -------------------------------------- ]
*/ */
@ -158,6 +165,13 @@
/****/ /****/
/* [ Pokemon Mini -------------------------------------- ]
*/
//#define enable_POKE
/****/
/* [ Sega Master System/Mark III/Game Gear/SG-1000 ---------------- ] /* [ Sega Master System/Mark III/Game Gear/SG-1000 ---------------- ]
*/ */

1660
Cart_Reader/MSX.ino Normal file

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@
/*==== VARIABLES ==================================================*/ /*==== VARIABLES ==================================================*/
// Firmware Version // Firmware Version
char ver[5] = "12.5"; char ver[5] = "12.6";
// Clock speed // Clock speed
unsigned long clock = CS_16MHZ; unsigned long clock = CS_16MHZ;

281
Cart_Reader/POKEMINI.ino Normal file
View File

@ -0,0 +1,281 @@
//******************************************
// POKEMON MINI MODULE
//******************************************
#ifdef enable_POKE
// Pokemon Mini
// Cartridge Pinout
// 32P 0.5mm pitch
// NOTE: Console SMD connector - 33P 1.0mm pitch
//
// TOP ROW BOTTOM ROW
// +----------+
// VCC (3.3V) -| B1 |
// | A1 |- VCC (3.3V)
// A20 -| B2 |
// | A2 |- A9/A19
// A8/A18 -| B3 |
// | A3 |- A7/A17
// A6/A16 -| B4 |
// | A4 |- A5/A15
// A4/A14 -| B5 |
// | A5 |- A3/A13
// A2/A12 -| B6 |
// | A6 |- A1/A11
// A0/A10 -| B7 |
// | A7 |- VCC (3.3V)
// HALE -| B8 |
// | -- |
// LALE -| B9 |
// | A8 |- GND
// D0 -| B10 |
// | A9 |- D1
// D2 -| B11 |
// | A10 |- D3
// D4 -| B12 |
// | A11 |- D5
// D6 -| B13 |
// | A12 |- D7
// OE -| B14 |
// | A13 |- IRQ
// WE -| B15 |
// | A14 |- CS
// CARD_N -| B16 |
// | A15 |- GND
// GND -| B17 |
// +----------+
//
// TOP
// +----------------------------------------------------------------------------+
// | B17 B16 B15 B14 B13 B12 B11 B10 B9 B8 B7 B6 B5 B4 B3 B2 B1 |
// LEFT | | RIGHT
// | A15 A14 A13 A12 A11 A10 A9 A8 --- A7 A6 A5 A4 A3 A2 A1 |
// +----------------------------------------------------------------------------+
// BOTTOM
// CONTROL PINS:
// HALE(PH0) - SNES RESET
// CS(PH3) - SNES /CS
// LALE(PH4) - SNES /IRQ
// WE(PH5) - SNES /WR
// OE(PH6) - SNES /RD
// NOTE: SET VOLTAGE TO 3.3V
//******************************************
// Defines
//******************************************
#define HALE_ENABLE PORTH |= (1 << 0) // LATCH HIGH ADDRESS
#define HALE_DISABLE PORTH &= ~(1 << 0)
#define LALE_ENABLE PORTH |= (1 << 4) // LATCH LOW ADDRESS
#define LALE_DISABLE PORTH &= ~(1 << 4)
#define CS_ENABLE PORTH |= (1 << 3) // CHIP SELECT
#define CS_DISABLE PORTH &= ~(1 << 3)
#define WE_ENABLE PORTH |= (1 << 5) // WRITE ENABLE
#define WE_DISABLE PORTH &= ~(1 << 5)
#define OE_ENABLE PORTH |= (1 << 6) // OUTPUT ENABLE
#define OE_DISABLE PORTH &= ~(1 << 6)
//******************************************
// Menu
//******************************************
// Base Menu
static const char pokeMenuItem1[] PROGMEM = "Read ROM";
static const char* const menuOptionsPOKE[] PROGMEM = { pokeMenuItem1, string_reset2 };
void pokeMenu() {
setVoltage(VOLTS_SET_3V3);
convertPgm(menuOptionsPOKE, 2);
uint8_t mainMenu = question_box(F("POKEMON MINI MENU"), menuOptions, 2, 0);
switch (mainMenu) {
case 0:
// Read ROM
sd.chdir("/");
readROM_POKE();
sd.chdir("/");
break;
case 1:
// reset
resetArduino();
break;
}
}
//******************************************
// SETUP
//******************************************
void setup_POKE() {
// Set Address Pins to Output
// Pokemon Mini uses A0-A9 (DUAL A10-A19) + A20 (CONNECT TO SNES A10) [A11-A23 UNUSED]
//A0-A7
DDRF = 0xFF;
//A8-A15
DDRK = 0xFF;
//A16-A23
DDRL = 0xFF;
// Set Control Pins to Output
// LALE(PH0) ---(PH1) CS(PH3) HALE(PH4) WE(PH5) OE(PH6)
DDRH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6);
// Set TIME(PJ0) to Output (UNUSED)
DDRJ |= (1 << 0);
// Set Pins (D0-D7) to Input
DDRC = 0x00;
// Setting Control Pins to LOW (DISABLE)
// LALE(PH0) CS(PH3) HALE(PH4) WE(PH5) OE(PH6)
PORTH &= ~(1 << 0) & ~(1 << 3) & ~(1 << 4) & ~(1 << 5) & ~(1 << 6);
// SET CS HIGH
PORTH |= (1 << 3); // CS HIGH (ENABLE)
// Set Unused Data Pins (PA0-PA7) to Output
DDRA = 0xFF;
// Set Unused Pins HIGH
PORTA = 0xFF;
PORTH |= (1 << 1); // CPUCLK(PH1)
PORTL = 0xFF; // A16-A23
PORTJ |= (1 << 0); // TIME(PJ0)
strcpy(romName, "POKEMINI");
mode = mode_POKE;
}
//******************************************
// READ DATA
//******************************************
uint8_t readData_POKE(uint32_t addr) {
// Address Lines A0-A20 = 1MB (ALL ROMS ARE 512K)
// 100000 = 1 0000 0000 0000 0000 0000 = 100 0000 0000|00 0000 0000
// High Address A10-A20
PORTF = (addr >> 10) & 0xFF; // A10-A17
PORTK = (addr >> 18) & 0x07; // A18-A20
HALE_ENABLE; // LATCH HIGH ADDRESS
NOP;
NOP;
HALE_DISABLE;
// Low Address A0-A9
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0x03; // A8-A9
LALE_ENABLE; // LATCH LOW ADDRESS
NOP;
NOP;
// Read Enable
OE_ENABLE; // OE HIGH
NOP;
NOP;
NOP;
NOP;
NOP;
// Data
uint8_t ret = PINC;
// Read Disable
OE_DISABLE; // OE LOW
NOP;
NOP;
NOP;
NOP;
LALE_DISABLE;
return ret;
}
//******************************************
// WRITE DATA
//******************************************
void writeData_POKE(uint32_t addr, uint8_t data) {
// High Address A10-A20
PORTF = (addr >> 10) & 0xFF; // A10-A17
PORTK = (addr >> 18) & 0x07; // A18-A20
HALE_ENABLE; // LATCH HIGH ADDRESS
NOP;
NOP;
HALE_DISABLE;
// Low Address A0-A9
PORTF = addr & 0xFF; // A0-A7
PORTK = (addr >> 8) & 0x03; // A8-A9
LALE_ENABLE; // LATCH LOW ADDRESS
// Set Data to Output
DDRC = 0xFF;
PORTC = data;
// Write Enable
WE_ENABLE; // WE HIGH
NOP;
NOP;
NOP;
NOP;
NOP;
// Write Disable
WE_DISABLE; // OE LOW
NOP;
NOP;
NOP;
NOP;
LALE_DISABLE;
// Reset Data to Input
DDRC = 0x00;
}
//******************************************
// READ ROM
//******************************************
void readROM_POKE() {
strcpy(fileName, romName);
strcat(fileName, ".min");
// create a new folder for storing rom file
EEPROM_readAnything(0, foldern);
sprintf(folder, "POKE/ROM/%d", foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
display_Clear();
print_STR(saving_to_STR, 0);
print_Msg(folder);
println_Msg(F("/..."));
display_Update();
// open file on sdcard
if (!myFile.open(fileName, O_RDWR | O_CREAT))
print_FatalError(sd_error_STR);
// write new folder number back to EEPROM
foldern++;
EEPROM_writeAnything(0, foldern);
for (uint32_t addr = 0; addr < 0x80000; addr += 512) { // 512K
for (int w = 0; w < 512; w++) {
uint8_t temp = readData_POKE(addr + w);
sdBuffer[w] = temp;
}
myFile.write(sdBuffer, 512);
}
myFile.close();
calcCRC(fileName, 0x80000, NULL, 0); // 512K
println_Msg(F(""));
// Prints string out of the common strings array either with or without newline
print_STR(press_button_STR, 1);
display_Update();
wait();
}
#endif