diff options
author | Lesserkuma <[email protected]> | 2022-09-25 17:06:58 +0200 |
---|---|---|
committer | Lesserkuma <[email protected]> | 2022-09-25 17:06:58 +0200 |
commit | 6098700fddd7b50cccbe0cde0ae8dd64a3587246 (patch) | |
tree | 9f0f90140807b280e445b56549ca429ab986487a /Cart_Reader | |
parent | 866f0ce2b561b893c43618249cf5e11f7cb6e8b8 (diff) | |
parent | d086b277ef694eac0a6a56077e7e19cc67983bc3 (diff) | |
download | cartreader-6098700fddd7b50cccbe0cde0ae8dd64a3587246.tar.gz cartreader-6098700fddd7b50cccbe0cde0ae8dd64a3587246.zip |
Merge branch 'master'
Diffstat (limited to 'Cart_Reader')
-rw-r--r-- | Cart_Reader/COLV.ino | 3 | ||||
-rw-r--r-- | Cart_Reader/Cart_Reader.ino | 55 | ||||
-rw-r--r-- | Cart_Reader/GB.ino | 12 | ||||
-rw-r--r-- | Cart_Reader/GBA.ino | 6 | ||||
-rw-r--r-- | Cart_Reader/GBS.ino | 3 | ||||
-rw-r--r-- | Cart_Reader/INTV.ino | 3 | ||||
-rw-r--r-- | Cart_Reader/MD.ino | 4 | ||||
-rw-r--r-- | Cart_Reader/N64.ino | 4 | ||||
-rw-r--r-- | Cart_Reader/NES.ino | 110 | ||||
-rw-r--r-- | Cart_Reader/NGP.ino | 3 | ||||
-rw-r--r-- | Cart_Reader/PCW.ino | 613 | ||||
-rw-r--r-- | Cart_Reader/SNES.ino | 6 | ||||
-rw-r--r-- | Cart_Reader/VBOY.ino | 11 | ||||
-rw-r--r-- | Cart_Reader/WS.ino | 3 | ||||
-rw-r--r-- | Cart_Reader/WSV.ino | 3 |
15 files changed, 783 insertions, 56 deletions
diff --git a/Cart_Reader/COLV.ino b/Cart_Reader/COLV.ino index 3fcb0dd..88caef3 100644 --- a/Cart_Reader/COLV.ino +++ b/Cart_Reader/COLV.ino @@ -561,3 +561,6 @@ void setCart_COL() { } } #endif +//****************************************** +// End of File +//****************************************** diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index 6e42ec0..4633d80 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -4,8 +4,8 @@ This project represents a community-driven effort to provide
an easy to build and easy to modify cartridge dumper.
- Date: 18.09.2022
- Version: 9.8
+ Date: 25.09.2022
+ Version: 9.9
SD lib: https://github.com/greiman/SdFat
OLED lib: https://github.com/adafruit/Adafruit_SSD1306
@@ -24,7 +24,7 @@ MichlK - ROM Reader for Super Nintendo
Jeff Saltzman - 4-Way Button
Wayne and Layne - Video Game Shield menu
- skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco-, Intellivision, Virtual Boy, WSV modules
+ skaman - Cart ROM READER SNES ENHANCED, Famicom Cart Dumper, Coleco-, Intellivision, Virtual Boy, WSV, PCW modules
Tamanegi_taro - PCE and Satellaview modules
splash5 - GBSmart, Wonderswan and NGP modules
hkz & themanbehindthecurtain - N64 flashram commands
@@ -59,7 +59,7 @@ **********************************************************************************/
-char ver[5] = "9.8";
+char ver[5] = "9.9";
//******************************************
// !!! CHOOSE HARDWARE VERSION !!!
@@ -97,6 +97,7 @@ char ver[5] = "9.8"; // #define enable_COLV
// #define enable_VBOY
// #define enable_WSV
+// #define enable_PCW
//******************************************
// HW CONFIGS
@@ -300,6 +301,7 @@ bool i2c_found; #define mode_COL 24
#define mode_VBOY 25
#define mode_WSV 26
+#define mode_PCW 27
// optimization-safe nop delay
#define NOP __asm__ __volatile__ ("nop\n\t")
@@ -804,9 +806,10 @@ static const char modeItem10[] PROGMEM = "Intellvision"; static const char modeItem11[] PROGMEM = "Colecovision";
static const char modeItem12[] PROGMEM = "Virtual Boy";
static const char modeItem13[] PROGMEM = "Watara Supervision";
-static const char modeItem14[] PROGMEM = "Flashrom Programmer";
-static const char modeItem15[] PROGMEM = "About";
-static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14, modeItem15};
+static const char modeItem14[] PROGMEM = "Pocket Challenge W";
+static const char modeItem15[] PROGMEM = "Flashrom Programmer";
+static const char modeItem16[] PROGMEM = "About";
+static const char* const modeOptions[] PROGMEM = {modeItem1, modeItem2, modeItem3, modeItem4, modeItem5, modeItem6, modeItem7, modeItem8, modeItem9, modeItem10, modeItem11, modeItem12, modeItem13, modeItem14, modeItem15, modeItem16};
// All included slots
void mainMenu() {
@@ -831,8 +834,8 @@ void mainMenu() { }
if (currPage == 3) {
// Copy menuOptions out of progmem
- convertPgm(modeOptions, 14, 1);
- modeMenu = question_box(F("OPEN SOURCE CART READER"), menuOptions, 1, 0);
+ convertPgm(modeOptions, 14, 2);
+ modeMenu = question_box(F("OPEN SOURCE CART READER"), menuOptions, 2, 0);
}
if (numPages == 0) {
// Execute choice
@@ -945,8 +948,15 @@ void mainMenu() { break;
#endif
-#ifdef enable_FLASH
+#ifdef enable_PCW
case 13:
+ setup_PCW();
+ pcwMenu();
+ break;
+#endif
+
+#ifdef enable_FLASH
+ case 14:
#ifdef enable_FLASH16
flashMenu();
#else
@@ -955,7 +965,7 @@ void mainMenu() { break;
#endif
- case 14:
+ case 15:
aboutScreen();
break;
@@ -1002,8 +1012,9 @@ static const char handheldsItem1[] PROGMEM = "Virtual Boy"; static const char handheldsItem2[] PROGMEM = "WonderSwan";
static const char handheldsItem3[] PROGMEM = "NeoGeo Pocket";
static const char handheldsItem4[] PROGMEM = "Watara Supervision";
-static const char handheldsItem5[] PROGMEM = "Reset";
-static const char* const handheldsOptions[] PROGMEM = {handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4, handheldsItem5};
+static const char handheldsItem5[] PROGMEM = "Pocket Challenge W";
+static const char handheldsItem6[] PROGMEM = "Reset";
+static const char* const handheldsOptions[] PROGMEM = {handheldsItem1, handheldsItem2, handheldsItem3, handheldsItem4, handheldsItem5, handheldsItem6};
// All included slots
void mainMenu() {
@@ -1160,11 +1171,11 @@ void consoleMenu() { // Everything that needs an adapter
void handheldMenu() {
- // create menu with title and 5 options to choose from
+ // create menu with title and 6 options to choose from
unsigned char handheldsMenu;
// Copy menuOptions out of progmem
- convertPgm(handheldsOptions, 5);
- handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 5, 0);
+ convertPgm(handheldsOptions, 6);
+ handheldsMenu = question_box(F("Choose Adapter"), menuOptions, 6, 0);
// wait for user choice to come back from the question box menu
switch (handheldsMenu)
@@ -1201,7 +1212,14 @@ void handheldMenu() { break;
#endif
+#ifdef enable_PCW
case 4:
+ setup_PCW();
+ pcwMenu();
+ break;
+#endif
+
+ case 5:
resetArduino();
break;
@@ -3404,6 +3422,11 @@ void loop() { wsvMenu();
}
#endif
+#ifdef enable_PCW
+ else if (mode == mode_PCW) {
+ pcwMenu();
+ }
+#endif
else {
display_Clear();
println_Msg(F("Menu Error"));
diff --git a/Cart_Reader/GB.ino b/Cart_Reader/GB.ino index 90e36ea..b2cd4dd 100644 --- a/Cart_Reader/GB.ino +++ b/Cart_Reader/GB.ino @@ -436,7 +436,7 @@ void showCartInfo_GB() { print_Msg(F("MBC1M")); else if (romType == 0x104) print_Msg(F("M161")); - + println_Msg(F("")); print_Msg(F("ROM Size: ")); switch (romSize) { @@ -835,17 +835,17 @@ void getCartInfo_GB() { if (sdBuffer[0x143] == 0x80 || sdBuffer[0x143] == 0xC0) { x++; } - for (int addr = 0x0134; addr <= 0x0143-x; addr++) { + for (int addr = 0x0134; addr <= 0x0143 - x; addr++) { myByte = sdBuffer[addr]; if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') { romName[myLength] = char(myByte); } else { - if (romName[myLength-1] == 0x5F) myLength--; + if (romName[myLength - 1] == 0x5F) myLength--; romName[myLength] = 0x5F; } myLength++; } - + // Strip trailing white space for (unsigned int i = myLength - 1; i > 0; i--) { if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break; @@ -920,13 +920,13 @@ void readROM_GB() { uint32_t processedProgressBar = 0; uint32_t totalProgressBar = (uint32_t)(romBanks) * 16384; draw_progressbar(0, totalProgressBar); - + // M161 banks are double size and start with 0 if (romType == 0x104) { startBank = 0; romBanks >>= 1; } - + for (word currBank = startBank; currBank < romBanks; currBank++) { // Second bank starts at 0x4000 if (currBank > 1) { diff --git a/Cart_Reader/GBA.ino b/Cart_Reader/GBA.ino index 02338c9..7433374 100644 --- a/Cart_Reader/GBA.ino +++ b/Cart_Reader/GBA.ino @@ -898,19 +898,19 @@ void getCartInfo_GBA() { if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') {
romName[myLength] = char(myByte);
} else {
- if (romName[myLength-1] == 0x5F) myLength--;
+ if (romName[myLength - 1] == 0x5F) myLength--;
romName[myLength] = 0x5F;
}
myLength++;
}
-
+
// Strip trailing white space
for (unsigned int i = myLength - 1; i > 0; i--) {
if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break;
romName[i] = 0x00;
myLength--;
}
-
+
// Get ROM version
romVersion = sdBuffer[0xBC];
diff --git a/Cart_Reader/GBS.ino b/Cart_Reader/GBS.ino index ee957f1..7820eee 100644 --- a/Cart_Reader/GBS.ino +++ b/Cart_Reader/GBS.ino @@ -808,3 +808,6 @@ uint8_t gbSmartGetResizeParam(uint8_t rom_size, uint8_t sram_size) } #endif +//****************************************** +// End of File +//****************************************** diff --git a/Cart_Reader/INTV.ino b/Cart_Reader/INTV.ino index c8eb31c..e4f57d5 100644 --- a/Cart_Reader/INTV.ino +++ b/Cart_Reader/INTV.ino @@ -960,3 +960,6 @@ void setCart_INTV() { } } #endif +//****************************************** +// End of File +//****************************************** diff --git a/Cart_Reader/MD.ino b/Cart_Reader/MD.ino index 1e0397b..228695a 100644 --- a/Cart_Reader/MD.ino +++ b/Cart_Reader/MD.ino @@ -2452,7 +2452,7 @@ void readRealtec_MD() { strcat(fileName, ".MD");
// create a new folder
- EEPROM_readAnything(10, foldern);
+ EEPROM_readAnything(0, foldern);
sprintf(folder, "MD/ROM/%s/%d", romName, foldern);
sd.mkdir(folder, true);
sd.chdir(folder);
@@ -2465,7 +2465,7 @@ void readRealtec_MD() { // write new folder number back to eeprom
foldern = foldern + 1;
- EEPROM_writeAnything(10, foldern);
+ EEPROM_writeAnything(0, foldern);
// Open file on sd card
if (!myFile.open(fileName, O_RDWR | O_CREAT)) {
diff --git a/Cart_Reader/N64.ino b/Cart_Reader/N64.ino index a4e6ead..a77da71 100644 --- a/Cart_Reader/N64.ino +++ b/Cart_Reader/N64.ino @@ -2719,12 +2719,12 @@ void idCart() { if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') { romName[myLength] = char(myByte); } else { - if (romName[myLength-1] == 0x5F) myLength--; + if (romName[myLength - 1] == 0x5F) myLength--; romName[myLength] = 0x5F; } myLength++; } - + // Strip trailing white space for (unsigned int i = myLength - 1; i > 0; i--) { if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break; diff --git a/Cart_Reader/NES.ino b/Cart_Reader/NES.ino index 2562334..8fb58ea 100644 --- a/Cart_Reader/NES.ino +++ b/Cart_Reader/NES.ino @@ -9,19 +9,20 @@ //Line Content //28 Supported Mappers -//103 Defines -//133 Variables -//194 Menus -//333 Setup -//362 Low Level Functions -//609 CRC Functions -//669 File Functions -//864 NES 2.0 Header Functions -//1145 Config Functions -//1946 ROM Functions -//3044 RAM Functions -//3477 Eeprom Functions -//3667 NESmaker Flash Cart Functions +//106 Defines +//136 Variables +//197 Menus +//383 Setup +//412 No-Intro SD Database Functions +//1125 Low Level Functions +//1372 CRC Functions +//1426 File Functions +//1527 NES 2.0 Header Functions +//1957 Config Functions +//2760 ROM Functions +//3951 RAM Functions +//4384 Eeprom Functions +//4574 NESmaker Flash Cart Functions /****************************************** Supported Mappers @@ -53,9 +54,10 @@ static const byte PROGMEM mapsize [] = { 33, 3, 4, 5, 6, 0, 0, // taito tc0190 34, 3, 3, 0, 0, 0, 0, // bnrom [nina-1 NOT SUPPORTED] 37, 4, 4, 6, 6, 0, 0, // (super mario bros + tetris + world cup) + 45, 3, 6, 0, 8, 0, 0, // ga23c asic multicart [UNLICENSED] 47, 4, 4, 6, 6, 0, 0, // (super spike vball + world cup) 48, 3, 4, 6, 6, 0, 0, // taito tc0690 - 64, 2, 3, 4, 5, 0, 0, // tengen rambo-1 + 64, 2, 3, 4, 5, 0, 0, // tengen rambo-1 [UNLICENSED] 65, 3, 4, 5, 6, 0, 0, // irem h-3001 66, 2, 3, 2, 3, 0, 0, // gxrom/mhrom 67, 3, 3, 5, 5, 0, 0, // sunsoft 3 @@ -90,7 +92,7 @@ static const byte PROGMEM mapsize [] = { 153, 5, 5, 0, 0, 1, 1, // (famicom jump ii) [sram r/w] 154, 3, 3, 5, 5, 0, 0, // namcot-3453 (devil man) 155, 3, 3, 3, 5, 0, 1, // mmc1 variant [sram r/w] - 158, 3, 3, 5, 5, 0, 0, // tengen rambo-1 variant (alien syndrome (u)) + 158, 3, 3, 5, 5, 0, 0, // tengen rambo-1 variant (alien syndrome (u)) [UNLICENSED] 159, 3, 4, 5, 6, 1, 1, // bandai x24c01 [eep r/w] 180, 3, 3, 0, 0, 0, 0, // unrom variant (crazy climber) 184, 1, 1, 2, 3, 0, 0, // sunsoft 1 @@ -138,13 +140,13 @@ byte mapcount = (sizeof(mapsize) / sizeof(mapsize[0])) / 7; boolean mapfound = false; byte mapselect; -int PRG[] = {16, 32, 64, 128, 256, 512}; +int PRG[] = {16, 32, 64, 128, 256, 512, 1024}; byte prglo = 0; // Lowest Entry -byte prghi = 5; // Highest Entry +byte prghi = 6; // Highest Entry -int CHR[] = {0, 8, 16, 32, 64, 128, 256, 512}; +int CHR[] = {0, 8, 16, 32, 64, 128, 256, 512, 1024}; byte chrlo = 0; // Lowest Entry -byte chrhi = 7; // Highest Entry +byte chrhi = 8; // Highest Entry byte RAM[] = {0, 8, 16, 32}; byte ramlo = 0; // Lowest Entry @@ -192,7 +194,7 @@ byte newramsize; int b = 0; /****************************************** - Menu + Menus *****************************************/ // NES start menu static const char nesMenuItem1[] PROGMEM = "Change Mapper"; @@ -2771,6 +2773,14 @@ void dumpCHR(word address) { myFile.write(sdBuffer, 512); } +void dumpCHR_M2(word address) { // MAPPER 45 - PULSE M2 LO/HI + for (int x = 0; x < 512; x++) { + PHI2_LOW; + sdBuffer[x] = read_chr_byte(address + x); + } + myFile.write(sdBuffer, 512); +} + void dumpMMC5RAM(word base, word address) { // MMC5 SRAM DUMP - PULSE M2 LO/HI for (int x = 0; x < 512; x++) { PHI2_LOW; @@ -3069,6 +3079,37 @@ void readPRG(boolean readrom) { } break; + case 45: // MMC3 Clone with Outer Registers + banks = ((int_pow(2, prgsize) * 2)) - 2; // Set Number of Banks + for (int i = 0; i < banks; i += 2) { // 128K/256K/512K/1024K + // set outer bank registers + write_prg_byte(0x6000, 0x00); // CHR-OR + write_prg_byte(0x6000, (i & 0xC0)); // PRG-OR + write_prg_byte(0x6000, ((i >> 2) & 0xC0)); // CHR-AND,CHR-OR/PRG-OR + write_prg_byte(0x6000, 0x80); // PRG-AND + // set inner bank registers + write_prg_byte(0x8000, 6); // PRG Bank 0 ($8000-$9FFF) + write_prg_byte(0x8001, i); + for (word address = 0x0; address < 0x2000; address += 512) { + dumpPRG(base, address); + } + // set outer bank registers + write_prg_byte(0x6000, 0x00); // CHR-OR + write_prg_byte(0x6000, ((i + 1) & 0xC0)); // PRG-OR + write_prg_byte(0x6000, (((i + 1) >> 2) & 0xC0)); // CHR-AND,CHR-OR/PRG-OR + write_prg_byte(0x6000, 0x80); // PRG-AND + // set inner bank registers + write_prg_byte(0x8000, 7); // PRG Bank 1 ($A000-$BFFF) + write_prg_byte(0x8001, i + 1); + for (word address = 0x2000; address < 0x4000; address += 512) { + dumpPRG(base, address); + } + } + for (word address = 0x4000; address < 0x8000; address += 512) { // Final 2 Banks ($C000-$FFFF) + dumpPRG(base, address); + } + break; + case 66: // 64K/128K banks = int_pow(2, prgsize) / 2; for (int i = 0; i < banks; i++) { // 64K/128K @@ -3608,6 +3649,35 @@ void readCHR(boolean readrom) { } break; + case 45: // 128K/256K/512K/1024K + banks = int_pow(2, chrsize) * 4; + write_prg_byte(0xA001, 0x80); // Unlock Write Protection - not used by some carts + for (int i = 0; i < banks; i++) { + // set outer bank registers + write_prg_byte(0x6000, 0x00); // CHR-OR + write_prg_byte(0x6000, 0x00); // PRG-OR + write_prg_byte(0x6000, (((i / 256) << 4) | 0x0F)); // CHR-AND,CHR-OR/PRG-OR + write_prg_byte(0x6000, 0x80); // PRG-AND + // set inner bank registers + write_prg_byte(0x8000, 0x2); // CHR Bank 2 ($1000-$13FF) + write_prg_byte(0x8001, i); + for (word address = 0x1000; address < 0x1200; address += 512) { + dumpCHR_M2(address); // Read CHR with M2 Pulse + } + // set outer bank registers + write_prg_byte(0x6000, 0x00); // CHR-OR + write_prg_byte(0x6000, 0x00); // PRG-OR + write_prg_byte(0x6000, (((i / 256) << 4) | 0x0F)); // CHR-AND,CHR-OR/PRG-OR + write_prg_byte(0x6000, 0x80); // PRG-AND + // set inner bank registers + write_prg_byte(0x8000, 0x2); // CHR Bank 2 ($1000-$13FF) + write_prg_byte(0x8001, i); + for (word address = 0x1200; address < 0x1400; address += 512) { + dumpCHR_M2(address); // Read CHR with M2 Pulse + } + } + break; + case 67: // 128K banks = int_pow(2, chrsize) * 2; for (int i = 0; i < banks; i += 4) { // 2K Banks diff --git a/Cart_Reader/NGP.ino b/Cart_Reader/NGP.ino index fe9288b..e91f337 100644 --- a/Cart_Reader/NGP.ino +++ b/Cart_Reader/NGP.ino @@ -372,3 +372,6 @@ uint8_t readByte_NGP(uint32_t addr) { } #endif +//****************************************** +// End of File +//****************************************** diff --git a/Cart_Reader/PCW.ino b/Cart_Reader/PCW.ino new file mode 100644 index 0000000..1144d87 --- /dev/null +++ b/Cart_Reader/PCW.ino @@ -0,0 +1,613 @@ +//****************************************** +// BENESSE POCKET CHALLENGE W MODULE +//****************************************** +#ifdef enable_PCW + +// Benesse Pocket Challenge W +// Cartridge Pinout +// 38P 1.27mm pitch connector +// +// CART CART +// TOP EDGE +// +---------+ +// | 1 |-- VCC +// | 2 |-- GND +// | 3 |-- AD0 (A0 IN/D0 OUT) +// | 4 |-- AD1 (A1 IN/D1 OUT) +// | 5 |-- AD2 (A2 IN/D2 OUT) +// | 6 |-- AD3 (A3 IN/D3 OUT) +// | 7 |-- AD4 (A4 IN/D4 OUT) +// | 8 |-- AD5 (A5 IN/D5 OUT) +// | 9 |-- AD6 (A6 IN/D6 OUT) +// | 10 |-- AD7 (A7 IN/D7 OUT) +// | 11 |-- A08 +// | 12 |-- A09 +// | 13 |-- A10 +// | 14 |-- A11 +// | 15 |-- A12 +// | 16 |-- A13 +// | 17 |-- A14 +// | 18 |-- A15 +// | 19 |-- A16 +// | 20 |-- A17 +// | 21 |-- A18 +// | 22 |-- A19 +// | 23 |-- A20 +// | 24 |-- A21 +// | 25 |-- NC [CPU-INT2/T15(P47)] +// | 26 |-- 1B (7W00F) -> HIGH -+ +// | 27 |-- 1A (7W00F) -> HIGH -+-> OE (ROM) = LOW +// | 28 |-- OE (LH5164A) +// | 29 |-- WE (LH5164A) +// | 30 |-- LE (HC573) [LATCH ENABLE FOR AD0-AD7] +// | 31 |-- NC [CPU-TO5(P43)] +// | 32 |-- NC [CPU-RESET] +// | 33 |-- VCC +// | 34 |-- GND +// | 35 |-- NC +// | 36 |-- NC [CPU-VCC] +// | 37 |-- NC [CONSOLE-GND] +// | 38 |-- NC +// +---------+ + +// CONTROL PINS: +// LE - (PH0) - PCW PIN 30 - SNES RST +// 1A - (PH3) - PCW PIN 27 - SNES /CS +// 1B - (PH4) - PCW PIN 26 - SNES /IRQ +// WE - (PH5) - PCW PIN 29 - SNES /WR +// OE - (PH6) - PCW PIN 28 - SNES /RD + +// NOT CONNECTED: +// CLK(PH1) - N/C + +// ADDRESS PINS: +// ADDR/DATA [AD0-AD7] - PORTC +// ADDR A8-A15 - PORTK +// ADDR A16-A21 - PORTL + +//****************************************** +// DEFINES +//****************************************** + +// CONTROL PINS - LE/1A/1B/WE/OE +#define LE_HIGH PORTH |= (1 << 0) +#define LE_LOW PORTH &= ~(1 << 0) +#define NAND_1A_HIGH PORTH |= (1 << 3) +#define NAND_1A_LOW PORTH &= ~(1 << 3) +#define NAND_1B_HIGH PORTH |= (1 << 4) +#define NAND_1B_LOW PORTH &= ~(1 << 4) // Built-in RAM + I/O +#define WE_HIGH PORTH |= (1 << 5) +#define WE_LOW PORTH &= ~(1 << 5) +#define OE_HIGH PORTH |= (1 << 6) +#define OE_LOW PORTH &= ~(1 << 6) + +#define MODE_READ DDRC = 0 // [INPUT] +#define MODE_WRITE DDRC = 0xFF //[OUTPUT] + +#define DATA_READ { DDRC = 0; PORTC = 0xFF; } // [INPUT PULLUP] +#define ADDR_WRITE DDRC = 0xFF // [OUTPUT] + +boolean multipack = 0; // Multi-Pack Cart +byte bank0; +byte bank1; + +//****************************************** +// SETUP +//****************************************** + +void setup_PCW() { + // Set Address Pins to Output + //A8-A15 + DDRK = 0xFF; + //A16-A21 + DDRL = 0xFF; + + // Set Control Pins to Output + // LE(PH0) --(PH1) 1A(PH3) 1B(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 Address/Data Pins AD0-AD7 (PC0-PC7) to Input + MODE_READ; // DDRC = 0 + + // Setting Control Pins to HIGH + // LE(PH0) ---(PH1) 1A(PH3) 1B(PH4) WE(PH5) OE(PH6) + PORTH |= (1 << 0) | (1 << 1) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6); + + // Set Unused Pins HIGH + PORTJ |= (1 << 0); // TIME(PJ0) + + // Multi-Pack Cart Check + check_multi_PCW(); + + strcpy(romName, "PCW"); + + mode = mode_PCW; +} + +//****************************************** +// MENU +//****************************************** +static const char pcwmenuItem1[] PROGMEM = "Read ROM"; +static const char pcwmenuItem2[] PROGMEM = "Read SRAM"; +static const char pcwmenuItem3[] PROGMEM = "Write SRAM"; +static const char pcwmenuItem4[] PROGMEM = "Reset"; +static const char* const menuOptionsPCW[] PROGMEM = {pcwmenuItem1, pcwmenuItem2, pcwmenuItem3, pcwmenuItem4}; + +void pcwMenu() +{ + convertPgm(menuOptionsPCW, 4); + uint8_t mainMenu = question_box(F(" POCKET CHALLENGE W"), menuOptions, 4, 0); + + switch (mainMenu) + { + case 0: + // Read ROM + sd.chdir("/"); + if (multipack) + readMultiROM_PCW(); + else + readROM_PCW(); + sd.chdir("/"); + break; + + case 1: + // Read SRAM + sd.chdir("/"); + display_Clear(); + println_Msg(F("Reading SRAM...")); + display_Update(); + readSRAM_PCW(); + sd.chdir("/"); + // Wait for user input + println_Msg(F("Press Button...")); + display_Update(); + wait(); + break; + + case 2: + // Write SRAM + sd.chdir("/"); + fileBrowser(F("Select SRM file")); + display_Clear(); + writeSRAM_PCW(); + display_Clear(); + writeErrors = verifySRAM_PCW(); + if (writeErrors == 0) { + println_Msg(F("SRAM verified OK")); + display_Update(); + } + else { + print_Msg(F("Error: ")); + print_Msg(writeErrors); + println_Msg(F(" bytes ")); + print_Error(F("did not verify."), false); + } + break; + + case 3: + // Reset + resetArduino(); + break; + } +} + +//****************************************** +// LOW LEVEL FUNCTIONS +//****************************************** + +// Max ROM Size 0x400000 (Highest Address = 0x3FFFFF) - 3F FFFF +// NAND 1A + 1B HIGH = LOW = ROM Output Enabled +void read_setup_PCW() { + NAND_1A_HIGH; + NAND_1B_HIGH; + OE_HIGH; + WE_HIGH; + LE_LOW; +} + +// READ ROM BYTE WITH ADDITIONAL DELAY +// NEEDED FOR PROBLEM CARTS TO SWITCH FROM ADDRESS TO DATA +unsigned char read_rom_byte_PCW(unsigned long address) { + PORTL = (address >> 16) & 0xFF; + PORTK = (address >> 8) & 0xFF; + // Latch Address on AD0-AD7 + ADDR_WRITE; + LE_HIGH; // Latch Enable + PORTC = address & 0xFF; // A0-A7 + LE_LOW; // Address Latched + __asm__("nop\n\t""nop\n\t"); + // Read Data on AD0-AD7 + OE_LOW; + DATA_READ; + delayMicroseconds(5); // 3+ Microseconds for Problem Carts + unsigned char data = PINC; + OE_HIGH; + + return data; +} + +// SRAM Size 0x8000 (Highest Address = 0x7FFF) +// NAND 1A LOW = SRAM Enabled [ROM DISABLED] +unsigned char read_ram_byte_1A_PCW(unsigned long address) { + NAND_1A_LOW; + PORTL = (address >> 16) & 0xFF; + PORTK = (address >> 8) & 0xFF; + // Latch Address on AD0-AD7 + ADDR_WRITE; + LE_HIGH; // Latch Enable + PORTC = address & 0xFF; // A0-A7 + LE_LOW; // Address Latched + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + // Read Data on AD0-AD7 + OE_LOW; + DATA_READ; + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + unsigned char data = PINC; + OE_HIGH; + NAND_1A_HIGH; + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + + return data; +} + +// Toshiba TMP90C845A +// 0xFEC0-0xFFBF Built-in RAM (256 bytes) +// 0xFFC0-0xFFF7 Built-in I/O (56 bytes) +// 0xFF00-0xFFBF (192 byte area available in direct addressing mode) +// 0xFF18-0xFF68 (Micro DMA parameters (if used)) + +// TEST CODE TO READ THE CPU BUILT-IN RAM + I/O +// NAND 1B LOW = Built-In RAM + I/O Enabled [ROM DISABLED] +unsigned char read_ram_byte_1B_PCW(unsigned long address) { + NAND_1B_LOW; + PORTL = (address >> 16) & 0xFF; + PORTK = (address >> 8) & 0xFF; + // Latch Address on AD0-AD7 + ADDR_WRITE; + LE_HIGH; // Latch Enable + PORTC = address & 0xFF; // A0-A7 + LE_LOW; // Address Latched + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + // Read Data on AD0-AD7 + OE_LOW; + DATA_READ; + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + unsigned char data = PINC; + OE_HIGH; + NAND_1B_HIGH; + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + + return data; +} + +// WRITE SRAM 32K +void write_ram_byte_1A_PCW(unsigned long address, unsigned char data) { + NAND_1A_LOW; + PORTL = (address >> 16) & 0xFF; + PORTK = (address >> 8) & 0xFF; + // Latch Address on AD0-AD7 + ADDR_WRITE; + LE_HIGH; // Latch Enable + PORTC = address & 0xFF; // A0-A7 + LE_LOW; // Address Latched + // Write Data on AD0-AD7 - WE LOW ~240-248ns + WE_LOW; + PORTC = data; + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WE_HIGH; + NAND_1A_HIGH; +} + +// WRITE CPU BUILT-IN RAM + I/O AREA +// MODIFIED TO MATCH WORKING BANK SWITCH ROUTINE +void write_ram_byte_1B_PCW(unsigned long address, unsigned char data) { + NAND_1A_LOW; + NAND_1A_HIGH; + NAND_1B_LOW; + PORTL = (address >> 16) & 0xFF; + PORTK = (address >> 8) & 0xFF; + // Latch Address on AD0-AD7 + ADDR_WRITE; + LE_HIGH; // Latch Enable + PORTC = address & 0xFF; // A0-A7 + LE_LOW; // Address Latched + // Write Data on AD0-AD7 - WE LOW ~740ns + WE_LOW; + PORTC = data; + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WE_HIGH; + NAND_1B_HIGH; +} + +//============================================================================== +// Overload Multi-Pack Bank Switch +// +// Known Multi-Pack Carts (Yellow Label Carts) +// 0BD400 [PS] (2MB Version) +// 0BD400 [PS] (4MB Version) +// 0BF400 [PL] +// 1BF400 [PZ] +// 8BD400 [CR] +// 8BF400 [LP] +// 9BF400 [SLP] (Undumped) + +// Per Overload, identify multi-pack cart by reading 0x3FFA-0x3FFE +// Multi-Pack carts are non-zero +// 0x3FFA - Current Cartridge Bank +// 0x3FFC - Value to Switch to Cartridge Bank 0 +// 0x3FFD - Value to Switch to Cartridge Bank 1 +// 0x3FFE - Last Value written to 0xFFFF + +// Bank Settings for 2MB +// Write 0x28 to 0xFFFF to read 1st half of ROM +// Write 0x2E to 0xFFFF to read 2nd half of ROM + +// Bank Settings for 4MB +// Write 0x20 to 0xFFFF to read 1st half of ROM +// Write 0x31 to 0xFFFF to read 2nd half of ROM + +// MULTI-PACK CART CHECK +void check_multi_PCW() { + read_setup_PCW(); + byte tempbyte = read_rom_byte_PCW(0x3FFC); // Bank 0 Switch + if (tempbyte) { + bank0 = tempbyte; // Store Bank 0 Switch + tempbyte = read_rom_byte_PCW(0x3FFD); // Bank 1 Switch + if (tempbyte) { + bank1 = tempbyte; // Store Bank 1 Switch + // Check for 00s + tempbyte = read_rom_byte_PCW(0x3FFB); // Should be 00 + if (!tempbyte) { + tempbyte = read_rom_byte_PCW(0x3FFF); // Should be 00 + if (!tempbyte) + multipack = 1; // Flag Multi-Cart + else { + bank0 = 0; + bank1 = 0; + } + } + } + } +} + +void write_bank_byte_PCW(unsigned char data) { + NAND_1A_LOW; + NAND_1A_HIGH; + NAND_1B_LOW; + // Write to Address 0xFFFF + PORTL = 0x00; + PORTK = 0xFF; // A8-A15 + // Latch Address on AD0-AD7 + ADDR_WRITE; + LE_HIGH; // Latch Enable + PORTC = 0xFF; // A0-A7 + LE_LOW; // Address Latched + // Write Data on AD0-AD7 - WE LOW ~728-736ns + WE_LOW; + PORTC = data; + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t"); + WE_HIGH; + NAND_1B_HIGH; +} + +void switchBank_PCW(int bank) { + if (bank == 1) { // Upper Half + write_bank_byte_PCW(bank1); + } + else { // Lower Half (default) + write_bank_byte_PCW(bank0); + } +} + +//****************************************** +// READ CODE +//****************************************** + +void readROM_PCW() { + strcpy(fileName, romName); + strcat(fileName, ".pcw"); + + EEPROM_readAnything(0, foldern); + sprintf(folder, "PCW/ROM/%d", foldern); + sd.mkdir(folder, true); + sd.chdir(folder); + + display_Clear(); + print_Msg(F("Saving to ")); + print_Msg(folder); + println_Msg(F("/...")); + display_Update(); + + foldern = foldern + 1; + EEPROM_writeAnything(0, foldern); + + if (!myFile.open(fileName, O_RDWR | O_CREAT)) { + print_Error(F("SD Error"), true); + } + read_setup_PCW(); + for (unsigned long address = 0; address < 0x400000; address += 512) { // 4MB + for (unsigned int x = 0; x < 512; x++) { + sdBuffer[x] = read_rom_byte_PCW(address + x); + } + myFile.write(sdBuffer, 512); + } + myFile.flush(); + myFile.close(); + + // Compare CRC32 to database and rename ROM if found + // Arguments: database name, precalculated crc string or 0 to calculate, rename rom or not, starting offset + compareCRC("pcw.txt", 0, 1, 0); + + // Wait for user input + println_Msg(F("")); + println_Msg(F("Press Button...")); + display_Update(); + wait(); +} + +void readMultiROM_PCW() { + strcpy(fileName, romName); + strcat(fileName, ".pcw"); + + EEPROM_readAnything(0, foldern); + sprintf(folder, "PCW/ROM/%d", foldern); + sd.mkdir(folder, true); + sd.chdir(folder); + + display_Clear(); + print_Msg(F("Saving to ")); + print_Msg(folder); + println_Msg(F("/...")); + display_Update(); + + foldern = foldern + 1; + EEPROM_writeAnything(0, foldern); + + if (!myFile.open(fileName, O_RDWR | O_CREAT)) { + print_Error(F("SD Error"), true); + } + display_Clear(); + println_Msg(F("READING MULTI-PACK")); + println_Msg(F("")); + display_Update(); + read_setup_PCW(); + // Lower Half + switchBank_PCW(0); + for (unsigned long address = 0; address < 0x200000; address += 512) { // 2MB + for (unsigned int x = 0; x < 512; x++) { + sdBuffer[x] = read_rom_byte_PCW(address + x); + } + myFile.write(sdBuffer, 512); + } + read_setup_PCW(); + // Upper Half + switchBank_PCW(1); + for (unsigned long address = 0x200000; address < 0x400000; address += 512) { // 2MB + for (unsigned int x = 0; x < 512; x++) { + sdBuffer[x] = read_rom_byte_PCW(address + x); + } + myFile.write(sdBuffer, 512); + } + myFile.flush(); + myFile.close(); + // Reset Bank + switchBank_PCW(0); + + // Compare CRC32 to database and rename ROM if found + // Arguments: database name, precalculated crc string or 0 to calculate, rename rom or not, starting offset + compareCRC("pcw.txt", 0, 1, 0); + + // Wait for user input + println_Msg(F("")); + println_Msg(F("Press Button...")); + display_Update(); + wait(); +} + +//****************************************** +// SRAM +//****************************************** + +void readSRAM_PCW() { // readSRAM_1A() + strcpy(fileName, romName); + strcat(fileName, ".srm"); + + EEPROM_readAnything(0, foldern); + sprintf(folder, "PCW/SAVE/%d", foldern); + sd.mkdir(folder, true); + sd.chdir(folder); + + foldern = foldern + 1; + EEPROM_writeAnything(0, foldern); + + if (!myFile.open(fileName, O_RDWR | O_CREAT)) { + print_Error(F("SD Error"), true); + } + display_Clear(); + read_setup_PCW(); + for (unsigned long address = 0x0; address < 0x8000; address += 512) { // 32K + for (unsigned int x = 0; x < 512; x++) { + sdBuffer[x] = read_ram_byte_1A_PCW(address + x); + } + myFile.write(sdBuffer, 512); + } + myFile.flush(); + myFile.close(); + print_Msg(F("Saved to ")); + print_Msg(folder); + println_Msg(F("/")); + display_Update(); + // calcCRC(fileName, 0x8000, NULL, 0); // 32K +} + +// SRAM +void writeSRAM_PCW() { + sprintf(filePath, "%s/%s", filePath, fileName); + println_Msg(F("Writing...")); + println_Msg(filePath); + display_Update(); + + if (myFile.open(filePath, O_READ)) { + sd.chdir(); + sprintf(filePath, "%s/%s", filePath, fileName); + display_Clear(); + println_Msg(F("Writing File: ")); + println_Msg(filePath); + println_Msg(fileName); + display_Update(); + //open file on sd card + if (myFile.open(filePath, O_READ)) { + read_setup_PCW(); + for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K + myFile.read(sdBuffer, 512); + for (unsigned int x = 0; x < 512; x++) { + write_ram_byte_1A_PCW(address + x, sdBuffer[x]); + } + } + myFile.close(); + println_Msg(F("Done")); + display_Update(); + } + else { + print_Error(F("SD Error"), true); + } + } + else { + print_Error(F("SD Error"), true); + } + display_Clear(); +} + +unsigned long verifySRAM_PCW() { + writeErrors = 0; + + if (myFile.open(filePath, O_READ)) { + read_setup_PCW(); + for (unsigned int address = 0x0; address < 0x8000; address += 512) { // 32K + for (unsigned int x = 0; x < 512; x++) { + byte myByte = read_ram_byte_1A_PCW(address + x); + sdBuffer[x] = myByte; + } + for (int i = 0; i < 512; i++) { + if (myFile.read() != sdBuffer[i]) { + writeErrors++; + } + } + } + myFile.close(); + } + else { + print_Error(F("SD Error"), true); + } + + return writeErrors; +} +#endif +//****************************************** +// End of File +//****************************************** diff --git a/Cart_Reader/SNES.ino b/Cart_Reader/SNES.ino index 8b1f46a..64a6c17 100644 --- a/Cart_Reader/SNES.ino +++ b/Cart_Reader/SNES.ino @@ -1016,19 +1016,19 @@ boolean checkcart_SNES() { if (isprint(myByte) && myByte != '<' && myByte != '>' && myByte != ':' && myByte != '"' && myByte != '/' && myByte != '\\' && myByte != '|' && myByte != '?' && myByte != '*') { romName[myLength] = char(myByte); } else { - if (romName[myLength-1] == 0x5F) myLength--; + if (romName[myLength - 1] == 0x5F) myLength--; romName[myLength] = 0x5F; } myLength++; } - + // Strip trailing white space for (unsigned int i = myLength - 1; i > 0; i--) { if ((romName[i] != 0x5F) && (romName[i] != 0x20)) break; romName[i] = 0x00; myLength--; } - + // If name consists out of all japanese characters use game code if (myLength == 0) { // Get rom code diff --git a/Cart_Reader/VBOY.ino b/Cart_Reader/VBOY.ino index d532ef5..ad1c193 100644 --- a/Cart_Reader/VBOY.ino +++ b/Cart_Reader/VBOY.ino @@ -384,7 +384,7 @@ void readROM_VB() { strcpy(fileName, romName); strcat(fileName, ".vb"); - EEPROM_readAnything(10, foldern); + EEPROM_readAnything(0, foldern); sprintf(folder, "VBOY/ROM/%s/%d", romName, foldern); sd.mkdir(folder, true); sd.chdir(folder); @@ -396,7 +396,7 @@ void readROM_VB() { display_Update(); foldern = foldern + 1; - EEPROM_writeAnything(10, foldern); + EEPROM_writeAnything(0, foldern); if (!myFile.open(fileName, O_RDWR | O_CREAT)) { print_Error(F("SD Error"), true); @@ -482,13 +482,13 @@ void readSRAM_VB() { strcpy(fileName, romName); strcat(fileName, ".srm"); - EEPROM_readAnything(10, foldern); + EEPROM_readAnything(0, foldern); sprintf(folder, "VBOY/SAVE/%s/%d", romName, foldern); sd.mkdir(folder, true); sd.chdir(folder); foldern = foldern + 1; - EEPROM_writeAnything(10, foldern); + EEPROM_writeAnything(0, foldern); if (!myFile.open(fileName, O_RDWR | O_CREAT)) { print_Error(F("SD Error"), true); @@ -532,3 +532,6 @@ unsigned long verifySRAM_VB() { return writeErrors; } #endif +//****************************************** +// End of File +//****************************************** diff --git a/Cart_Reader/WS.ino b/Cart_Reader/WS.ino index 99e76f5..49855f2 100644 --- a/Cart_Reader/WS.ino +++ b/Cart_Reader/WS.ino @@ -1321,3 +1321,6 @@ void dataOut_WS() } #endif +//****************************************** +// End of File +//****************************************** diff --git a/Cart_Reader/WSV.ino b/Cart_Reader/WSV.ino index e39aba3..f71a811 100644 --- a/Cart_Reader/WSV.ino +++ b/Cart_Reader/WSV.ino @@ -560,3 +560,6 @@ void setCart_WSV() { } } #endif +//****************************************** +// End of File +//****************************************** |