aboutsummaryrefslogtreecommitdiffhomepage
path: root/Cart_Reader
diff options
context:
space:
mode:
authorLesserkuma <[email protected]>2022-09-25 17:06:58 +0200
committerLesserkuma <[email protected]>2022-09-25 17:06:58 +0200
commit6098700fddd7b50cccbe0cde0ae8dd64a3587246 (patch)
tree9f0f90140807b280e445b56549ca429ab986487a /Cart_Reader
parent866f0ce2b561b893c43618249cf5e11f7cb6e8b8 (diff)
parentd086b277ef694eac0a6a56077e7e19cc67983bc3 (diff)
downloadcartreader-6098700fddd7b50cccbe0cde0ae8dd64a3587246.tar.gz
cartreader-6098700fddd7b50cccbe0cde0ae8dd64a3587246.zip
Merge branch 'master'
Diffstat (limited to 'Cart_Reader')
-rw-r--r--Cart_Reader/COLV.ino3
-rw-r--r--Cart_Reader/Cart_Reader.ino55
-rw-r--r--Cart_Reader/GB.ino12
-rw-r--r--Cart_Reader/GBA.ino6
-rw-r--r--Cart_Reader/GBS.ino3
-rw-r--r--Cart_Reader/INTV.ino3
-rw-r--r--Cart_Reader/MD.ino4
-rw-r--r--Cart_Reader/N64.ino4
-rw-r--r--Cart_Reader/NES.ino110
-rw-r--r--Cart_Reader/NGP.ino3
-rw-r--r--Cart_Reader/PCW.ino613
-rw-r--r--Cart_Reader/SNES.ino6
-rw-r--r--Cart_Reader/VBOY.ino11
-rw-r--r--Cart_Reader/WS.ino3
-rw-r--r--Cart_Reader/WSV.ino3
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
+//******************************************