Patching header for some games

(No affect on rom file dumping)
This commit is contained in:
splash5 2019-10-13 02:02:49 +08:00
parent 92c7a41c97
commit 5e77331912

View File

@ -20,10 +20,22 @@ static const char wsMenuItem3[] PROGMEM = "Write Save";
static const char wsMenuItem4[] PROGMEM = "Reset"; static const char wsMenuItem4[] PROGMEM = "Reset";
static const char* const menuOptionsWS[] PROGMEM = {wsMenuItem1, wsMenuItem2, wsMenuItem3, wsMenuItem4}; static const char* const menuOptionsWS[] PROGMEM = {wsMenuItem1, wsMenuItem2, wsMenuItem3, wsMenuItem4};
/******************************************
* Developer Name
*****************************************/
static const char wsDevNameXX[] PROGMEM = "XXX";
static const char wsDevName01[] PROGMEM = "BAN";
static const char wsDevName12[] PROGMEM = "KNM";
static const char wsDevName18[] PROGMEM = "KGT";
static const char wsDevName1D[] PROGMEM = "BEC";
static const char wsDevName24[] PROGMEM = "0MN";
static const char wsDevName28[] PROGMEM = "SQR";
static const char wsDevName31[] PROGMEM = "VGD";
static uint8_t wsGameOrientation = 0; static uint8_t wsGameOrientation = 0;
static uint8_t wsGameHasRTC = 0; static uint8_t wsGameHasRTC = 0;
static uint16_t wsGameChecksum = 0; static uint16_t wsGameChecksum = 0;
static uint8_t wsEepromShiftReg[5]; static uint8_t wsEepromShiftReg[2];
void setup_WS() void setup_WS()
{ {
@ -140,18 +152,93 @@ uint8_t getCartInfo_WS()
for (uint32_t i = 0; i < 16; i += 2) for (uint32_t i = 0; i < 16; i += 2)
*((uint16_t*)(sdBuffer + i)) = readWord_WS(0xffff0 + i); *((uint16_t*)(sdBuffer + i)) = readWord_WS(0xffff0 + i);
// developer and cartID wsGameChecksum = *(uint16_t*)(sdBuffer + 14);
snprintf(cartID, 5, "%02X%02X", sdBuffer[6], sdBuffer[8]);
// some game has wrong info in header
// patch here
switch (wsGameChecksum)
{
// games with 256kbits SRAM installed
case 0xe600: // BAN007
case 0x8eed: // BANC16
{
sdBuffer[11] = 0x02;
break;
}
// games missing 'COLOR' flag
case 0x26db: // SQRC01
{
sdBuffer[7] = 0x01;
break;
}
case 0x7f73: // BAN030
{
// missing developerId and cartId
sdBuffer[6] = 0x01;
sdBuffer[8] = 0x30;
break;
}
case 0x0000:
{
// developerId/cartId/checksum are all filled with 0x00 in wonderwitch based games
if (readWord_WS(0xf0000) == 0x4c45 && readWord_WS(0xf0002) == 0x5349 && readWord_WS(0xf0004) == 0x0041)
{
// looking for "<Ini" string
if (readWord_WS(0xec456) == 0x493c && readWord_WS(0xec458) == 0x696e)
{
// wonderwitch SWJ-7AC003
sdBuffer[6] = 0x7a;
sdBuffer[8] = 0xc3;
// TODO check OS version and fill into version field
}
// looking for "<Ini" string
else if (readWord_WS(0x839d8) == 0x493c && readWord_WS(0x839da) == 0x696e)
{
if (readWord_WS(0x93246) == 0x4a2f && readWord_WS(0x93248) == 0x5353 && readWord_WS(0x9324a) == 0x2e32)
{
// jss2
// TODO check jss version
sdBuffer[6] = 0xff; // WWGP
sdBuffer[8] = 0x1a; // 2001A
sdBuffer[7] = 0x01; // color only
if (readWord_WS(0x93e9c) == 0x4648 && readWord_WS(0x93e9e) == 0x0050)
{
// WWGP2001A3 -> HFP Version
sdBuffer[9] = 0x03;
wsGameChecksum = 0x4870;
}
else
{
// TODO other version
}
}
else if (readWord_WS(0xe4260) == 0x6b64 && readWord_WS(0xe4262) == 0x696e)
{
// dknight
sdBuffer[6] = 0xff; // WWGP
sdBuffer[8] = 0x2b; // 2002B
sdBuffer[7] = 0x01; // color only
sdBuffer[9] = 0x00;
wsGameChecksum = 0x8b1c;
}
}
}
break;
}
}
romType = sdBuffer[7]; // wsc only = 1 romType = sdBuffer[7]; // wsc only = 1
romVersion = sdBuffer[9]; romVersion = sdBuffer[9];
romSize = sdBuffer[10]; romSize = sdBuffer[10];
sramSize = sdBuffer[11]; sramSize = sdBuffer[11];
wsGameOrientation = (sdBuffer[12] & 0x01); wsGameOrientation = (sdBuffer[12] & 0x01);
wsGameHasRTC = (sdBuffer[13] & 0x01); wsGameHasRTC = (sdBuffer[13] & 0x01);
wsGameChecksum = *(uint16_t*)(sdBuffer + 14);
snprintf(checksumStr, 5, "%04X", wsGameChecksum);
strncpy(romName, cartID, sizeof(romName) - 1); snprintf(vendorID, 4, "%02X", sdBuffer[6]);
snprintf(cartID, 4, "%c%02X", ((romType & 0x01) ? 'C' : '0'), sdBuffer[8]);
snprintf(checksumStr, 5, "%04X", wsGameChecksum);
snprintf(romName, 17, "%s%s", vendorID, cartID);
switch (romSize) switch (romSize)
{ {
@ -194,7 +281,7 @@ void showCartInfo_WS()
println_Msg(F("WonderSwan Cart Info")); println_Msg(F("WonderSwan Cart Info"));
print_Msg(F("Game: ")); print_Msg(F("Game: "));
println_Msg(cartID); println_Msg(romName);
print_Msg(F("Rom Size: ")); print_Msg(F("Rom Size: "));
if (cartSize == 0x00) if (cartSize == 0x00)
@ -307,7 +394,7 @@ void readSRAM_WS()
uint32_t bank_size = (sramSize << 7); uint32_t bank_size = (sramSize << 7);
uint16_t end_bank = (bank_size >> 16); // 64KB per bank uint16_t end_bank = (bank_size >> 16); // 64KB per bank
if (end_bank > 0) if (bank_size > 0x10000)
bank_size = 0x10000; bank_size = 0x10000;
uint16_t bank = 0; uint16_t bank = 0;
@ -349,7 +436,7 @@ void verifySRAM_WS()
uint16_t bank = 0; uint16_t bank = 0;
uint32_t write_errors = 0; uint32_t write_errors = 0;
if (end_bank > 0) if (bank_size > 0x10000)
bank_size = 0x10000; bank_size = 0x10000;
do do
@ -410,7 +497,7 @@ void writeSRAM_WS()
uint32_t bank_size = (sramSize << 7); uint32_t bank_size = (sramSize << 7);
uint16_t end_bank = (bank_size >> 16); // 64KB per bank uint16_t end_bank = (bank_size >> 16); // 64KB per bank
if (end_bank > 0) if (bank_size > 0x10000)
bank_size = 0x10000; bank_size = 0x10000;
uint16_t bank = 0; uint16_t bank = 0;
@ -478,12 +565,12 @@ void readEEPROM_WS()
if ((j & 0x1f) == 0x00) if ((j & 0x1f) == 0x00)
PORTB ^= (1 << 4); PORTB ^= (1 << 4);
generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1), 0x00, 0x00); generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1));
dataOut_WS(); dataOut_WS();
writeByte_WSPort(0xc6, wsEepromShiftReg[2]); writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
writeByte_WSPort(0xc7, wsEepromShiftReg[3]); writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
writeByte_WSPort(0xc8, wsEepromShiftReg[4]); writeByte_WSPort(0xc8, 0x10);
// MMC will shift out from port 0xc7 to 0xc6 // MMC will shift out from port 0xc7 to 0xc6
// and shift in 16bits into port 0xc5 to 0xc4 // and shift in 16bits into port 0xc5 to 0xc4
@ -522,12 +609,12 @@ void verifyEEPROM_WS()
if ((j & 0x1f) == 0x00) if ((j & 0x1f) == 0x00)
PORTB ^= (1 << 4); PORTB ^= (1 << 4);
generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1), 0x00, 0x00); generateEepromInstruction_WS(wsEepromShiftReg, 0x2, ((i + j) >> 1));
dataOut_WS(); dataOut_WS();
writeByte_WSPort(0xc6, wsEepromShiftReg[2]); writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
writeByte_WSPort(0xc7, wsEepromShiftReg[3]); writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
writeByte_WSPort(0xc8, wsEepromShiftReg[4]); writeByte_WSPort(0xc8, 0x10);
// MMC will shift out from port 0xc7 to 0xc6 // MMC will shift out from port 0xc7 to 0xc6
// and shift in 16bits into port 0xc5 to 0xc4 // and shift in 16bits into port 0xc5 to 0xc4
@ -591,14 +678,14 @@ void writeEEPROM_WS()
if ((j & 0x1f) == 0x00) if ((j & 0x1f) == 0x00)
PORTB ^= (1 << 4); PORTB ^= (1 << 4);
generateEepromInstruction_WS(wsEepromShiftReg, 0x1, ((i + j) >> 1), sdBuffer[j], sdBuffer[j + 1]); generateEepromInstruction_WS(wsEepromShiftReg, 0x1, ((i + j) >> 1));
dataOut_WS(); dataOut_WS();
writeByte_WSPort(0xc6, wsEepromShiftReg[2]); writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
writeByte_WSPort(0xc7, wsEepromShiftReg[3]); writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
writeByte_WSPort(0xc4, wsEepromShiftReg[0]); writeByte_WSPort(0xc4, sdBuffer[j]);
writeByte_WSPort(0xc5, wsEepromShiftReg[1]); writeByte_WSPort(0xc5, sdBuffer[j + 1]);
writeByte_WSPort(0xc8, wsEepromShiftReg[4]); writeByte_WSPort(0xc8, 0x20);
// MMC will shift out from port 0xc7 to 0xc4 // MMC will shift out from port 0xc7 to 0xc4
pulseCLK_WS(1 + 32 + 3); pulseCLK_WS(1 + 32 + 3);
@ -651,7 +738,7 @@ boolean compareChecksum_WS(const char *wsFilePath)
myFile.close(); myFile.close();
checksum &= 0x0000ffff; checksum &= 0x0000ffff;
calLength = *((uint16_t*)(sdBuffer + 512 - 2)); calLength = wsGameChecksum;
// don't know why formating string "%04X(%04X)" always output "xxxx(0000)" // don't know why formating string "%04X(%04X)" always output "xxxx(0000)"
// so split into two snprintf // so split into two snprintf
@ -758,68 +845,42 @@ uint16_t readWord_WS(uint32_t addr)
void unprotectEEPROM() void unprotectEEPROM()
{ {
generateEepromInstruction_WS(wsEepromShiftReg, 0x0, 0x3, 0x00, 0x00); generateEepromInstruction_WS(wsEepromShiftReg, 0x0, 0x3);
dataOut_WS(); dataOut_WS();
writeByte_WSPort(0xc6, wsEepromShiftReg[2]); writeByte_WSPort(0xc6, wsEepromShiftReg[0]);
writeByte_WSPort(0xc7, wsEepromShiftReg[3]); writeByte_WSPort(0xc7, wsEepromShiftReg[1]);
writeByte_WSPort(0xc8, wsEepromShiftReg[4]); writeByte_WSPort(0xc8, 0x40);
// MMC will shift out port 0xc7 to 0xc6 to EEPROM // MMC will shift out port 0xc7 to 0xc6 to EEPROM
pulseCLK_WS(1 + 16 + 3); pulseCLK_WS(1 + 16 + 3);
} }
// generate data for port 0xc4 to 0xc8 // generate data for port 0xc6 to 0xc7
// number of CLK pulses needed for each instruction is 1 + (16 or 32) + 3 // number of CLK pulses needed for each instruction is 1 + (16 or 32) + 3
void generateEepromInstruction_WS(uint8_t *instruction, uint8_t opcode, uint16_t addr, uint8_t l_data, uint8_t h_data) void generateEepromInstruction_WS(uint8_t *instruction, uint8_t opcode, uint16_t addr)
{ {
uint32_t *ptr = (uint32_t*)instruction;
uint8_t addr_bits = (sramSize > 1 ? 10 : 6); uint8_t addr_bits = (sramSize > 1 ? 10 : 6);
*ptr = 0x00000001; // initial with a start bit uint16_t *ptr = (uint16_t*)instruction;
*ptr = 0x0001; // initial with a start bit
switch (opcode) if (opcode == 0)
{ {
case 0x00: // 2bits opcode = 0x00
{ *ptr <<= 2;
addr &= 0x0003; // 2bits ext cmd (from addr)
*ptr <<= 2; // opcode = 0x0 *ptr <<= 2;
*ptr = ((*ptr << 2) | addr); *ptr |= (addr & 0x0003);
*ptr <<= (addr_bits - 2); *ptr <<= (addr_bits - 2);
*ptr <<= 16;
if (addr == 0x01)
{
// WRAL: fill every byte in eeprom with same data
instruction[0] = l_data;
instruction[1] = h_data;
instruction[4] = 0x20;
} }
else else
{ {
instruction[4] = 0x40; // 2bits opcode
} *ptr <<= 2;
*ptr |= (opcode & 0x03);
break; // address bits
} *ptr <<= addr_bits;
case 1: // WRITE *ptr |= (addr & ((1 << addr_bits) - 1));
{
*ptr = ((*ptr << 2) | opcode); // 2bits opcode
*ptr = ((*ptr << addr_bits) | addr); // address bits
*ptr <<= 16;
instruction[0] = l_data;
instruction[1] = h_data;
instruction[4] = 0x20;
break;
}
case 2: // READ
case 3: // ERASE
{
*ptr = ((*ptr << 2) | opcode); // 2bits opcode
*ptr = ((*ptr << addr_bits) | addr); // address bits
*ptr <<= 16;
instruction[4] = (opcode == 2 ? 0x10 : 0x20);
break;
}
} }
} }