pgm2: ICRW sim improvements [MetalliC, Lord Nightmare]

This commit is contained in:
MetalliC 2017-12-11 23:43:45 +02:00
parent 3070c7e386
commit 8b23bc7b9b
3 changed files with 121 additions and 26 deletions

View File

@ -46,11 +46,7 @@
Identify which regions each game was released in and either dump alt. internal ROMs for each region, or
create them until that can be done.
properly implement RTC (integrated into the CPU)
Memory Card system (there's an MCU on the motherboard that will need simulating or dumping somehow)
Verify Sprite Zoom (check exactly which pixels are doubled / missed on hardware for flipped , non-flipped cases etc.)
Simplify IGS036 encryption based on tables in internal roms
Fix ARM? bug that means Oriental Legend 2 needs a patch (might also be that it needs the card reader, and is running a
codepath that would not exist in a real environment at the moment)
Fix Save States (is this a driver problem or an ARM core problem, they don't work unless you get through the startup tests)
Debug features (require DIP SW1:8 On and SW1:1 Off):
@ -188,47 +184,86 @@ void pgm2_state::mcu_command(address_space &space, bool is_command)
m_mcu_result1 = 0;
}
break;
// unknown / unimplemented, all C0-C9 commands is IC Card RW related
// (m_mcu_regs[0] >> 8) & 0xff - target RW unit (player)
// C0-C9 commands is IC Card RW comms
case 0xc0: // insert card or/and check card presence. result: F7 - ok, F4 - no card
if (m_memcard_device[arg1 & 3]->present() == -1)
status = 0xf4;
m_mcu_result0 = cmd;
break;
case 0xc1: // check ready/busy ?
if (m_memcard_device[arg1 & 3]->present() == -1)
status = 0xf4;
m_mcu_result0 = cmd;
break;
case 0xc2: // read data to shared ram, args - offset, len
case 0xc2: // read data to shared ram
for (int i = 0; i < arg3; i++)
{
if (m_memcard_device[arg1 & 3]->present() != -1)
m_shareram[i + (~m_share_bank & 1) * 128] = m_memcard_device[arg1 & 3]->read(space, arg2 + i);
else
status = 0xf4;
}
m_mcu_result0 = cmd;
break;
case 0xc3: // save data from shared ram, args - offset, len
case 0xc3: // save data from shared ram
for (int i = 0; i < arg3; i++)
{
if (m_memcard_device[arg1 & 3]->present() != -1)
m_memcard_device[arg1 & 3]->write(space, arg2 + i, m_shareram[i + (~m_share_bank & 1) * 128]);
else
status = 0xf4;
}
m_mcu_result0 = cmd;
break;
case 0xc7: // get card ID?, no args, result1 expected to be fixed value for new card
m_mcu_result1 = 0xf81f0000;
case 0xc4: // presumable read security mem (password only?)
if (m_memcard_device[arg1 & 3]->present() != -1)
{
m_mcu_result1 = m_memcard_device[arg1 & 3]->read_sec(space, 1) |
(m_memcard_device[arg1 & 3]->read_sec(space, 2) << 8) |
(m_memcard_device[arg1 & 3]->read_sec(space, 3) << 16);
}
else
status = 0xf4;
m_mcu_result0 = cmd;
break;
case 0xc8: // write byte, args - offset, data byte
case 0xc5: // write security mem
if (m_memcard_device[arg1 & 3]->present() != -1)
m_memcard_device[arg1 & 3]->write_sec(space, arg2 & 3, arg3);
else
status = 0xf4;
m_mcu_result0 = cmd;
break;
case 0xc6: // presumable write protection mem
if (m_memcard_device[arg1 & 3]->present() != -1)
m_memcard_device[arg1 & 3]->write_prot(space, arg2 & 3, arg3);
else
status = 0xf4;
m_mcu_result0 = cmd;
break;
case 0xc7: // read protection mem
if (m_memcard_device[arg1 & 3]->present() != -1)
{
m_mcu_result1 = m_memcard_device[arg1 & 3]->read_prot(space, 0) |
(m_memcard_device[arg1 & 3]->read_prot(space, 1) << 8) |
(m_memcard_device[arg1 & 3]->read_prot(space, 2) << 16) |
(m_memcard_device[arg1 & 3]->read_prot(space, 3) << 24);
}
else
status = 0xf4;
m_mcu_result0 = cmd;
break;
case 0xc8: // write data mem
if (m_memcard_device[arg1 & 3]->present() != -1)
m_memcard_device[arg1 & 3]->write(space, arg2, arg3);
else
status = 0xf4;
m_mcu_result0 = cmd;
break;
case 0xc4: // not used
case 0xc5: // set new password?, args - offset, data byte (offs 0 - always 7, 1-3 password)
case 0xc6: // not used
case 0xc9: // card authentication, args - 3 byte password, ('I','G','S' for new cards)
case 0xc9: // card authentication
if (m_memcard_device[arg1 & 3]->present() != -1)
m_memcard_device[arg1 & 3]->auth(arg2, arg3, m_mcu_regs[1] & 0xff);
else
status = 0xf4;
m_mcu_result0 = cmd;
break;
default:
@ -585,8 +620,8 @@ MACHINE_CONFIG_END
#define ORLEG2_INTERNAL_CHINA \
ROM_REGION( 0x04000, "maincpu", 0 ) \
ROM_LOAD( "xyj2_cn.igs036", 0x00000000, 0x0004000, CRC(bcce7641) SHA1(c3b5cf6e9f6eae09b6785314777a52b34c3c7657) ) \
ROM_REGION( 0x100, "default_card", 0 ) \
ROM_LOAD( "blank_orleg2_china_card.pg2", 0x000, 0x100, CRC(099156f0) SHA1(a621c9772a98719c657bba3a1bf235487eb78615) )
ROM_REGION( 0x108, "default_card", 0 ) \
ROM_LOAD( "blank_orleg2_china_card.pg2", 0x000, 0x108, CRC(dc29556f) SHA1(2335cc7af25d4dd9763c6944d3f0eb50276de80a) )
#define ORLEG2_INTERNAL_OVERSEAS \
ROM_REGION( 0x04000, "maincpu", 0 ) \
@ -667,8 +702,8 @@ ROM_END
#define KOV2NL_INTERNAL_CHINA \
ROM_REGION( 0x04000, "maincpu", 0 ) \
ROM_LOAD( "gsyx_igs036_china.rom", 0x00000000, 0x0004000, CRC(e09fe4ce) SHA1(c0cac64ef8727cbe79d503ec4df66ddb6f2c925e) ) \
ROM_REGION( 0x100, "default_card", 0 ) \
ROM_LOAD( "blank_kov2nl_china_card.pg2", 0x000, 0x100, CRC(91786244) SHA1(ac0ce11b46c19ffe21f6b94bc83ef061f547b591) )
ROM_REGION( 0x108, "default_card", 0 ) \
ROM_LOAD( "blank_kov2nl_china_card.pg2", 0x000, 0x108, CRC(02842ae8) SHA1(a6cda633b09a706039a79b73db2c258094826f85) )
ROM_START( kov2nl )

View File

@ -5,7 +5,7 @@
pgm2_memcard.cpp
PGM2 Memory card functions.
(based on ng_memcard.cpp)
Presumable Siemens SLE 4442 or compatible.
*********************************************************************/
@ -45,25 +45,36 @@ void pgm2_memcard_device::device_start()
image_init_result pgm2_memcard_device::call_load()
{
if(length() != 0x100)
authenticated = false;
if(length() != 0x108)
return image_init_result::FAIL;
fseek(0, SEEK_SET);
size_t ret = fread(m_memcard_data, 0x100);
if(ret != 0x100)
return image_init_result::FAIL;
ret = fread(m_protection_data, 4);
if (ret != 4)
return image_init_result::FAIL;
ret = fread(m_security_data, 4);
if (ret != 4)
return image_init_result::FAIL;
return image_init_result::PASS;
}
void pgm2_memcard_device::call_unload()
{
authenticated = false;
fseek(0, SEEK_SET);
fwrite(m_memcard_data, 0x100);
fwrite(m_protection_data, 4);
fwrite(m_security_data, 4);
}
image_init_result pgm2_memcard_device::call_create(int format_type, util::option_resolution *format_options)
{
authenticated = false;
// cards must contain valid defaults for each game / region or they don't work?
memory_region *rgn = memregion("^default_card");
@ -71,14 +82,28 @@ image_init_result pgm2_memcard_device::call_create(int format_type, util::option
return image_init_result::FAIL;
memcpy(m_memcard_data, rgn->base(), 0x100);
memcpy(m_protection_data, rgn->base() + 0x100, 4);
memcpy(m_security_data, rgn->base() + 0x104, 4);
size_t ret = fwrite(m_memcard_data, 0x100);
if(ret != 0x100)
size_t ret = fwrite(rgn->base(), 0x108);
if(ret != 0x108)
return image_init_result::FAIL;
return image_init_result::PASS;
}
void pgm2_memcard_device::auth(uint8_t p1, uint8_t p2, uint8_t p3)
{
if (m_security_data[0] & 3)
{
if (m_security_data[1] == p1 && m_security_data[2] == p2 && m_security_data[3] == p3)
authenticated = true;
else {
m_security_data[0] >>= 1; // hacky
logerror("Wrong IC Card password !!!");
}
}
}
READ8_MEMBER(pgm2_memcard_device::read)
{
@ -87,5 +112,32 @@ READ8_MEMBER(pgm2_memcard_device::read)
WRITE8_MEMBER(pgm2_memcard_device::write)
{
m_memcard_data[offset] = data;
if (authenticated && (offset >= 0x20 || (m_protection_data[offset>>3] & (1 <<(offset & 7)))))
{
m_memcard_data[offset] = data;
}
}
READ8_MEMBER(pgm2_memcard_device::read_prot)
{
return m_protection_data[offset];
}
WRITE8_MEMBER(pgm2_memcard_device::write_prot)
{
if (authenticated)
m_protection_data[offset] &= data;
}
READ8_MEMBER(pgm2_memcard_device::read_sec)
{
if (!authenticated)
return 0xff; // guess
return m_security_data[offset];
}
WRITE8_MEMBER(pgm2_memcard_device::write_sec)
{
if (authenticated)
m_security_data[offset] = data;
}

View File

@ -52,11 +52,19 @@ public:
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
DECLARE_READ8_MEMBER(read_prot);
DECLARE_WRITE8_MEMBER(write_prot);
DECLARE_READ8_MEMBER(read_sec);
DECLARE_WRITE8_MEMBER(write_sec);
void auth(uint8_t p1, uint8_t p2, uint8_t p3);
/* returns the index of the current memory card, or -1 if none */
int present() { return is_loaded() ? 0 : -1; }
private:
uint8_t m_memcard_data[0x100];
uint8_t m_protection_data[4];
uint8_t m_security_data[4];
bool authenticated;
};