39in1.cpp: decrypted 4in1a, 4in1b; started working on decryption of 19in1 and 48in1

This commit is contained in:
Ivan Vangelista 2020-08-06 13:39:59 +02:00 committed by GitHub
parent 746438653a
commit 6444fa2560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -18,7 +18,13 @@
* PCB also contains a custom ASIC, probably used for the decryption
*
* TODO:
* PXA255 peripherals
* - PXA255 peripherals
* - 4in1a and 4in1b are very similar to 39in1, currently boot but stuck at
* 'Hardware Check' with an error
* - rodent should be correctly decrypted but expects something different
from the CPLD (probably)
* - 19in1, 48in1, 48in1a, 48in1b seem to have a slightly different encryption
* - 60in1 expects something different from the CPLD (probably)
*
* 39in1 notes:
* The actual PCB just normally boots up to the game, whereas in MAME it
@ -51,8 +57,12 @@ public:
void _39in1(machine_config &config);
void driver_init() override;
void init_4in1a();
void init_4in1b();
void init_19in1();
void init_39in1();
void init_48in1();
void init_48in1a();
void init_60in1();
void init_rodent();
@ -60,6 +70,9 @@ private:
uint32_t m_seed;
uint32_t m_magic;
uint32_t m_state;
uint32_t m_mcu_ipt_pc;
void driver_init() override;
required_device<pxa255_periphs_device> m_pxa_periphs;
required_shared_ptr<uint32_t> m_ram;
@ -75,6 +88,8 @@ private:
void _39in1_map(address_map &map);
inline void ATTR_PRINTF(3,4) verboselog(int n_level, const char *s_fmt, ... );
void decrypt(uint8_t xor00, uint8_t xor08, uint8_t xor10, uint8_t xor20, uint8_t xor40, uint8_t bit7, uint8_t bit6, uint8_t bit5, uint8_t bit4, uint8_t bit3, uint8_t bit2, uint8_t bit1, uint8_t bit0);
};
@ -110,13 +125,13 @@ void _39in1_state::eeprom_w(uint32_t data, uint32_t mem_mask)
uint32_t _39in1_state::cpld_r(offs_t offset)
{
//if (m_maincpu->pc() != 0xe3af4) printf("CPLD read @ %x (PC %x state %d)\n", offset, m_maincpu->pc(), state);
// if (m_maincpu->pc() != m_mcu_ipt_pc) printf("CPLD read @ %x (PC %x state %d)\n", offset, m_maincpu->pc(), m_state);
if (m_maincpu->pc() == 0x3f04)
{
return 0xf0; // any non-zero value works here
}
else if (m_maincpu->pc() == 0xe3af4)
else if (m_maincpu->pc() == m_mcu_ipt_pc)
{
return ioport("MCUIPT")->read();
}
@ -268,28 +283,43 @@ static INPUT_PORTS_START( 39in1 )
*/
INPUT_PORTS_END
void _39in1_state::init_39in1()
void _39in1_state::decrypt(uint8_t xor00, uint8_t xor08, uint8_t xor10, uint8_t xor20, uint8_t xor40, uint8_t bit7, uint8_t bit6, uint8_t bit5, uint8_t bit4, uint8_t bit3, uint8_t bit2, uint8_t bit1, uint8_t bit0)
{
driver_init();
uint8_t *rom = memregion("maincpu")->base();
for (int i = 0; i < 0x80000; i += 2)
{
if (i & 0x08)
rom[i] ^= 0x02;
rom[i] ^= xor08;
if (i & 0x10)
rom[i] ^= 0x40;
rom[i] ^= xor10;
if (i & 0x20)
rom[i] ^= 0x04;
rom[i] ^= xor20;
if (i & 0x40)
rom[i] ^= 0x80;
rom[i] ^= xor40;
rom[i] = bitswap<8>(rom[i] ^ 0xc0, 7, 2, 5, 6, 0, 3, 1, 4);
rom[i] = bitswap<8>(rom[i] ^ xor00, bit7, bit6, bit5, bit4, bit3, bit2, bit1, bit0);
}
/*{
char filename[256];
sprintf(filename,"p_decrypted_%s", machine().system().name);
FILE *fp = fopen(filename, "w+b");
if (fp)
{
fwrite(rom, 0x80000, 1, fp);
fclose(fp);
}
}*/
}
void _39in1_state::init_60in1()
void _39in1_state::init_39in1() { driver_init(); decrypt(0xc0, 0x02, 0x40, 0x04, 0x80, 7, 2, 5, 6, 0, 3, 1, 4); m_mcu_ipt_pc = 0xe3af4; } // good
void _39in1_state::init_4in1a() { driver_init(); decrypt(0x25, 0x01, 0x80, 0x04, 0x40, 6, 0, 2, 1, 7, 5, 4, 3); m_mcu_ipt_pc = 0x45814; } // good
void _39in1_state::init_4in1b() { driver_init(); decrypt(0x43, 0x80, 0x04, 0x40, 0x08, 2, 4, 0, 6, 7, 3, 1, 5); m_mcu_ipt_pc = 0x57628; } // good
void _39in1_state::init_19in1() { driver_init(); decrypt(0x00, 0x04, 0x01, 0x80, 0x40, 2, 1, 7, 4, 5, 0, 6, 3); m_mcu_ipt_pc = 0x00000; } // TODO: seems to have different bitswaps depending on XOR address
void _39in1_state::init_48in1() { driver_init(); decrypt(0x00, 0x01, 0x40, 0x00, 0x20, 5, 3, 2, 1, 4, 6, 0, 7); m_mcu_ipt_pc = 0x00000; } // applies to both 48in1 and 48in1b, same main CPU ROM. TODO: see above
void _39in1_state::init_48in1a() { init_48in1(); m_mcu_ipt_pc = 0x00000; } // same encryption as 48in1
void _39in1_state::init_rodent() { init_4in1b(); /*m_mcu_ipt_pc = 0x?????;*/ } // same encryption as 4in1b, thus good, but doesn't boot because of different CPLD calls
void _39in1_state::init_60in1() // different encryption scheme
{
driver_init();
// TODO: Machine is marked as MNW; is this decrypt correct?
@ -301,28 +331,8 @@ void _39in1_state::init_60in1()
ROM[i] = bitswap<8>(ROM[i],5,1,4,2,0,7,6,3)^bitswap<8>(i, 6,0,4,13,0,5,3,11);
}
}
}
void _39in1_state::init_rodent()
{
driver_init();
// TODO: verify decryption. Game needs appropriate cpld_r() and cpld_w() and possibly protection_cheater_r() methods anyway
// what's below gives extremely similar code to the decrypted one for 39in1 up to 0x069C, where the code base seems to start differing
uint8_t *rom = memregion("maincpu")->base();
for (int i = 0; i < 0x80000; i += 2)
{
if (i & 0x08)
rom[i] ^= 0x80;
if (i & 0x10)
rom[i] ^= 0x04;
if (i & 0x20)
rom[i] ^= 0x40;
if (i & 0x40)
rom[i] ^= 0x08;
rom[i] = bitswap<8>(rom[i] ^ 0x43, 2, 4, 0, 6, 7, 3, 1, 5);
}
// m_mcu_ipt_pc = 0x?????;
}
void _39in1_state::_39in1(machine_config &config)
@ -466,12 +476,12 @@ ROM_START( rodent )
ROM_LOAD( "93c66.u32", 0x000, 0x200, CRC(c311c7bc) SHA1(8328002b7f6a8b7a3ffca079b7960bc990211d7b) )
ROM_END
GAME(2004, 4in1a, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "4 in 1 MAME bootleg (set 1, ver 3.00)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 4in1b, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "4 in 1 MAME bootleg (set 2)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 19in1, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "19 in 1 MAME bootleg", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 39in1, 0, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "39 in 1 MAME bootleg", MACHINE_IMPERFECT_SOUND)
GAME(2004, 48in1, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 1, ver 3.09)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 48in1b, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 2, ver 3.09, alt flash)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 48in1a, 39in1, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 3, ver 3.02)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 4in1a, 39in1, _39in1, 39in1, _39in1_state, init_4in1a, ROT270, "bootleg", "4 in 1 MAME bootleg (set 1, ver 3.00, PLZ-V014)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 4in1b, 39in1, _39in1, 39in1, _39in1_state, init_4in1b, ROT270, "bootleg", "4 in 1 MAME bootleg (set 2, PLZ-V001)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 19in1, 39in1, _39in1, 39in1, _39in1_state, init_19in1, ROT270, "bootleg", "19 in 1 MAME bootleg (SAC-V000)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 39in1, 0, _39in1, 39in1, _39in1_state, init_39in1, ROT270, "bootleg", "39 in 1 MAME bootleg (GNO-V000)", MACHINE_IMPERFECT_SOUND)
GAME(2004, 48in1, 39in1, _39in1, 39in1, _39in1_state, init_48in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 1, ver 3.09)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 48in1b, 39in1, _39in1, 39in1, _39in1_state, init_48in1, ROT270, "bootleg", "48 in 1 MAME bootleg (set 2, ver 3.09, alt flash)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 48in1a, 39in1, _39in1, 39in1, _39in1_state, init_48in1a, ROT270, "bootleg", "48 in 1 MAME bootleg (set 3, ver 3.02)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2004, 60in1, 39in1, _39in1, 39in1, _39in1_state, init_60in1, ROT270, "bootleg", "60 in 1 MAME bootleg (ver 3.00)", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)
GAME(2005, rodent, 0, _39in1, 39in1, _39in1_state, init_rodent, ROT270, "The Game Room", "Rodent Exterminator", MACHINE_NOT_WORKING|MACHINE_IMPERFECT_SOUND)