From f3b2fe825242ff7c66f966da351fa050b10db517 Mon Sep 17 00:00:00 2001 From: jiyunomegami Date: Sun, 12 Jul 2020 00:14:37 +0900 Subject: [PATCH] SRAM detection fix for Psy-o-blade, segaSram16bit setting in md.txt --- Cart_Reader/Cart_Reader.ino | 5 + Cart_Reader/MD.ino | 201 +++++++++++++++++++++++++++++------- 2 files changed, 170 insertions(+), 36 deletions(-) diff --git a/Cart_Reader/Cart_Reader.ino b/Cart_Reader/Cart_Reader.ino index d05b9c9..9b9a460 100644 --- a/Cart_Reader/Cart_Reader.ino +++ b/Cart_Reader/Cart_Reader.ino @@ -825,6 +825,11 @@ void print_Msg_PaddedHexByte(byte message) { print_Msg(message, HEX); } +void print_Msg_PaddedHex16(word message) { + print_Msg_PaddedHexByte((message >> 8) & 0xFF); + print_Msg_PaddedHexByte((message >> 0) & 0xFF); +} + void print_Msg_PaddedHex32(unsigned long message) { print_Msg_PaddedHexByte((message >> 24) & 0xFF); print_Msg_PaddedHexByte((message >> 16) & 0xFF); diff --git a/Cart_Reader/MD.ino b/Cart_Reader/MD.ino index 2adbc24..0d70042 100644 --- a/Cart_Reader/MD.ino +++ b/Cart_Reader/MD.ino @@ -85,6 +85,85 @@ unsigned long bramSize = 0; // REALTEC MAPPER boolean realtec = 0; + +#define DEFAULT_VALUE_segaSram16bit 0 +int segaSram16bit = DEFAULT_VALUE_segaSram16bit; + +/****************************************** + Configuration + *****************************************/ +void mdLoadConf() { + if (myFile.open("md.txt", O_READ)) { + char line[64]; + int n; + int i; + while ((n = myFile.fgets(line, sizeof(line)-1)) > 0) { + // preprocess + for (i = 0; i < n; i++) { + if (line[i] == ';') { + // comments + line[i] = '\0'; + n = i; + break; + } else if (line[i] == '\n' || line[i] == '\r') { + // EOL + line[n] = '\0'; + n = i; + break; + } + } + //print_Msg(F("read line: ")); + //println_Msg(line); + if (line[0] == '[') { + char *name; + char *value; + i = 1; + name = line + i; + for (; i < sizeof(line); i++) { + if (line[i] == ']') { + line[i] = '\0'; + i++; + break; + } + } + if (line[i] != '\0') { + for (; i < sizeof(line); i++) { + if (line[i] != ' ') { + value = line + i; + i++; + break; + } + } + for (; i < sizeof(line) && line[i] != '\0'; i++) { + if (line[i] == ' ') { + line[i] = '\0'; + break; + } + } + } + //print_Msg(F("read name: ")); + //println_Msg(name); + //print_Msg(F("value: ")); + //println_Msg(value); + if (!strcmp("segaSram16bit", name)) { + // Retrode compatible setting + // [segaSram16bit] 1 ; 0=no, 1=yes, 2=y+large + // 0: Output each byte once. Not supported by most emulators. + // 1: Duplicate each byte. Usable by Kega Fusion. + // 2: Output everything from 0x200000 to 0x20FFFF. Like an everdrive srm file. + segaSram16bit = atoi(value); + if (segaSram16bit != 0 && segaSram16bit != 1 && segaSram16bit != 2) { + segaSram16bit = DEFAULT_VALUE_segaSram16bit; + } + print_Msg(F("segaSram16bit: ")); + println_Msg(segaSram16bit); + } + } + } + myFile.close(); + } +} + /****************************************** Menu *****************************************/ @@ -221,7 +300,7 @@ void mdCartMenu() { case 1: display_Clear(); // Does cartridge have SRAM - if ((saveType == 1) || (saveType == 2) || (saveType == 3) || (saveType == 5)) { + if ((saveType == 1) || (saveType == 2) || (saveType == 3)) { // Change working dir to root sd.chdir("/"); println_Msg(F("Reading Sram...")); @@ -238,7 +317,7 @@ void mdCartMenu() { case 2: display_Clear(); // Does cartridge have SRAM - if ((saveType == 1) || (saveType == 2) || (saveType == 3) || (saveType == 5)) { + if ((saveType == 1) || (saveType == 2) || (saveType == 3)) { // Change working dir to root sd.chdir("/"); // Launch file browser @@ -358,6 +437,8 @@ void segaCDMenu() { Setup *****************************************/ void setup_MD() { + mdLoadConf(); + // Set Address Pins to Output //A0-A7 DDRF = 0xFF; @@ -597,7 +678,10 @@ void getCartInfo_MD() { // Get sram start and end sramBase = ((long(readWord_MD(0xDA)) << 16) | readWord_MD(0xDB)); sramEnd = ((long(readWord_MD(0xDC)) << 16) | readWord_MD(0xDD)); - + if (sramBase == 0x20000020 && sramEnd == 0x00010020) { // Fix for Psy-o-blade + sramBase = 0x200001; + sramEnd = 0x203fff; + } // Check alignment of sram if ((sramBase == 0x200001) || (sramBase == 0x300001)) { // ADDED 0x300001 FOR HARDBALL '95 (U) // low byte @@ -605,10 +689,6 @@ void getCartInfo_MD() { sramSize = (sramEnd - sramBase + 2) / 2; // Right shift sram base address so [A21] is set to high 0x200000 = 0b001[0]00000000000000000000 sramBase = sramBase >> 1; - if (chksum == 0x5D33 && sramEnd == 0x203FFF) { // Dragon Slayer Eiyuu Densetsu - // the high byte read as zero - saveType = 5; // BOTH - } } else if (sramBase == 0x200000) { // high byte @@ -617,8 +697,18 @@ void getCartInfo_MD() { // Right shift sram base address so [A21] is set to high 0x200000 = 0b001[0]00000000000000000000 sramBase = sramBase / 2; } - else + else { + print_Msg(("sramType: ")); + print_Msg_PaddedHex16(sramType); + println_Msg(F("")); + print_Msg(("sramBase: ")); + print_Msg_PaddedHex32(sramBase); + println_Msg(F("")); + print_Msg(("sramEnd: ")); + print_Msg_PaddedHex32(sramEnd); + println_Msg(F("")); print_Error(F("Unknown Sram Base"), true); + } } else if (sramType == 0xE020) { // SRAM BOTH BYTES // Get sram start and end @@ -635,8 +725,18 @@ void getCartInfo_MD() { sramSize = sramEnd - sramBase + 1; sramBase = sramBase >> 1; } - else + else { + print_Msg(("sramType: ")); + print_Msg_PaddedHex16(sramType); + println_Msg(F("")); + print_Msg(("sramBase: ")); + print_Msg_PaddedHex32(sramBase); + println_Msg(F("")); + print_Msg(("sramEnd: ")); + print_Msg_PaddedHex32(sramEnd); + println_Msg(F("")); print_Error(F("Unknown Sram Base"), true); + } } } else { @@ -690,6 +790,11 @@ void getCartInfo_MD() { sramBase = sramBase >> 1; } } + if (segaSram16bit == 2) { // 64KB + sramBase = 0x200000; + sramEnd = 0x20FFFF; + sramSize = 1UL << 15; // sramSize is the number of 2 byte words + } } // Get name @@ -725,10 +830,11 @@ void getCartInfo_MD() { println_Msg(F(" ")); print_Msg(F("Name: ")); println_Msg(romName); - print_Msg(F("bramCheck: ")); - print_Msg_PaddedHexByte(bramCheck >> 8); - print_Msg_PaddedHexByte(bramCheck & 0x00ff); - println_Msg(F("")); + if (bramCheck != 0x00FF) { + print_Msg(F("bramCheck: ")); + print_Msg_PaddedHex16(bramCheck); + println_Msg(F("")); + } if (bramSize > 0) { print_Msg(F("bramSize(KB): ")); println_Msg(bramSize >> 10); @@ -966,21 +1072,23 @@ void writeSram_MD() { // Write to the lower byte if (saveType == 1) { for (unsigned long currByte = sramBase; currByte < sramBase + sramSize; currByte++) { - writeWord_MD(currByte, (myFile.read() & 0xFF)); + if (segaSram16bit > 0) { + // skip high byte + myFile.read(); + } + byte data = (myFile.read() & 0xFF); + writeWord_MD(currByte, data); } } // Write to the upper byte else if (saveType == 2) { for (unsigned long currByte = sramBase; currByte < sramBase + sramSize; currByte++) { - writeWord_MD(currByte, ((myFile.read() << 8 ) & 0xFF)); - } - } - // Write to both bytes - else if (saveType == 5) { - for (unsigned long currByte = sramBase; currByte < sramBase + sramSize; currByte++) { - word w0 = (myFile.read() & 0xFF); // skip - word w1 = (myFile.read() & 0xFF); - writeWord_MD(currByte, w1); + byte data = ((myFile.read() << 8 ) & 0xFF); + writeWord_MD(currByte, data); + if (segaSram16bit > 0) { + // skip low byte + myFile.read(); + } } } else @@ -1026,22 +1134,28 @@ void readSram_MD() { if (saveType == 2) { // Only use the upper byte - sdBuffer[currWord] = (( myWord >> 8 ) & 0xFF); + if (segaSram16bit > 0) { + sdBuffer[(currWord * 2) + 0] = (( myWord >> 8 ) & 0xFF); + sdBuffer[(currWord * 2) + 1] = (( myWord >> 8 ) & 0xFF); + } else { + sdBuffer[currWord] = (( myWord >> 8 ) & 0xFF); + } } else if (saveType == 1) { // Only use the lower byte - sdBuffer[currWord] = (myWord & 0xFF); + if (segaSram16bit > 0) { + sdBuffer[(currWord * 2) + 0] = (myWord & 0xFF); + sdBuffer[(currWord * 2) + 1] = (myWord & 0xFF); + } else { + sdBuffer[currWord] = (myWord & 0xFF); + } } else if (saveType == 3) { // BOTH sdBuffer[currWord * 2] = (( myWord >> 8 ) & 0xFF); sdBuffer[(currWord * 2) + 1] = (myWord & 0xFF); } - else if (saveType == 5) { // duplicate the lower byte - sdBuffer[(currWord * 2) + 0] = (myWord & 0xFF); - sdBuffer[(currWord * 2) + 1] = (myWord & 0xFF); - } } - if (saveType == 3 || saveType == 5) + if (saveType == 3 || segaSram16bit > 0) myFile.write(sdBuffer, 512); else myFile.write(sdBuffer, 256); @@ -1060,21 +1174,36 @@ unsigned long verifySram_MD() { // Open file on sd card if (myFile.open(filePath, O_READ)) { - for (unsigned long currBuffer = sramBase; currBuffer < sramBase + sramSize; currBuffer += 512) { - for (int currWord = 0; currWord < 512; currWord++) { + for (unsigned long currBuffer = sramBase; currBuffer < sramBase + sramSize; currBuffer += 256) { + for (int currWord = 0; currWord < 256; currWord++) { word myWord = readWord_MD(currBuffer + currWord); - + if (saveType == 2) { // Only use the upper byte - sdBuffer[currWord] = (( myWord >> 8 ) & 0xFF); + if (segaSram16bit > 0) { + sdBuffer[(currWord * 2) + 0] = (( myWord >> 8 ) & 0xFF); + sdBuffer[(currWord * 2) + 1] = (( myWord >> 8 ) & 0xFF); + } else { + sdBuffer[currWord] = (( myWord >> 8 ) & 0xFF); + } } else if (saveType == 1) { // Only use the lower byte - sdBuffer[currWord] = (myWord & 0xFF); + if (segaSram16bit > 0) { + sdBuffer[(currWord * 2) + 0] = (myWord & 0xFF); + sdBuffer[(currWord * 2) + 1] = (myWord & 0xFF); + } else { + sdBuffer[currWord] = (myWord & 0xFF); + } + } + else if (saveType == 3) { // BOTH + sdBuffer[currWord * 2] = (( myWord >> 8 ) & 0xFF); + sdBuffer[(currWord * 2) + 1] = (myWord & 0xFF); } } + int size = (saveType == 3 || segaSram16bit > 0) ? 512 : 256; // Check sdBuffer content against file on sd card - for (int i = 0; i < 512; i++) { + for (int i = 0; i < size; i++) { if (myFile.read() != sdBuffer[i]) { writeErrors++; }