mirror of
https://github.com/holub/mame
synced 2025-04-16 13:34:55 +03:00
Preliminary decryption support for Namco System 10 [Andreas Naive]
This commit is contained in:
parent
820c1f8a7b
commit
e5628609f4
@ -2085,6 +2085,7 @@ files {
|
||||
MAME_DIR .. "src/mame/machine/namcos1.c",
|
||||
MAME_DIR .. "src/mame/video/namcos1.c",
|
||||
MAME_DIR .. "src/mame/drivers/namcos10.c",
|
||||
MAME_DIR .. "src/mame/machine/ns10crypt.c",
|
||||
MAME_DIR .. "src/mame/drivers/namcos11.c",
|
||||
MAME_DIR .. "src/mame/machine/ns11prot.c",
|
||||
MAME_DIR .. "src/mame/drivers/namcos12.c",
|
||||
|
@ -269,6 +269,7 @@ Kono Tako 10021 Ver.A KC034A 8E, 8D
|
||||
#include "emu.h"
|
||||
#include "cpu/psx/psx.h"
|
||||
#include "video/psx.h"
|
||||
#include "machine/ns10crypt.h"
|
||||
|
||||
class namcos10_state : public driver_device
|
||||
{
|
||||
@ -283,7 +284,8 @@ public:
|
||||
DECLARE_WRITE16_MEMBER(bank_w);
|
||||
|
||||
// memn variant interface
|
||||
DECLARE_READ16_MEMBER (nand_status_r);
|
||||
DECLARE_WRITE16_MEMBER(crypto_switch_w);
|
||||
DECLARE_READ16_MEMBER(nand_status_r);
|
||||
DECLARE_WRITE8_MEMBER(nand_address1_w);
|
||||
DECLARE_WRITE8_MEMBER(nand_address2_w);
|
||||
DECLARE_WRITE8_MEMBER(nand_address3_w);
|
||||
@ -301,6 +303,7 @@ private:
|
||||
UINT32 bank_base;
|
||||
UINT32 nand_address;
|
||||
UINT16 block[0x1ff];
|
||||
ns10_decrypter_device* decrypter;
|
||||
|
||||
UINT16 nand_read( UINT32 address );
|
||||
UINT16 nand_read2( UINT32 address );
|
||||
@ -401,6 +404,14 @@ ADDRESS_MAP_END
|
||||
// Block access to the nand. Something strange is going on with the
|
||||
// status port. Interaction with the decryption is unclear at best.
|
||||
|
||||
WRITE16_MEMBER(namcos10_state::crypto_switch_w)
|
||||
{
|
||||
if (BIT(data, 15) != 0)
|
||||
decrypter->activate();
|
||||
else
|
||||
decrypter->deactivate();
|
||||
}
|
||||
|
||||
READ16_MEMBER(namcos10_state::nand_status_r )
|
||||
{
|
||||
return 0;
|
||||
@ -451,7 +462,10 @@ READ16_MEMBER( namcos10_state::nand_data_r )
|
||||
/* printf( "data<-%08x (%08x)\n", data, nand_address ); */
|
||||
nand_address++;
|
||||
|
||||
return data;
|
||||
if (decrypter->is_active())
|
||||
return decrypter->decrypt(data);
|
||||
else
|
||||
return data;
|
||||
}
|
||||
|
||||
void namcos10_state::nand_copy( UINT32 *dst, UINT32 address, int len )
|
||||
@ -475,8 +489,7 @@ READ16_MEMBER(namcos10_state::nand_block_r)
|
||||
}
|
||||
|
||||
static ADDRESS_MAP_START( namcos10_memn_map, AS_PROGRAM, 32, namcos10_state )
|
||||
AM_RANGE(0x1f300000, 0x1f300003) AM_WRITE16(key_w, 0x0000ffff)
|
||||
|
||||
AM_RANGE(0x1f300000, 0x1f300003) AM_WRITE16(crypto_switch_w, 0x0000ffff)
|
||||
AM_RANGE(0x1f400000, 0x1f400003) AM_READ16(nand_status_r, 0x0000ffff)
|
||||
AM_RANGE(0x1f410000, 0x1f410003) AM_WRITE8(nand_address1_w, 0x000000ff)
|
||||
AM_RANGE(0x1f420000, 0x1f420003) AM_WRITE8(nand_address2_w, 0x000000ff)
|
||||
@ -492,17 +505,18 @@ void namcos10_state::memn_driver_init( )
|
||||
{
|
||||
UINT8 *BIOS = (UINT8 *)memregion( "maincpu:rom" )->base();
|
||||
nand_base = (UINT8 *)memregion( "user2" )->base();
|
||||
decrypter = static_cast<ns10_decrypter_device*>(machine().root_device().subdevice("decrypter"));
|
||||
|
||||
nand_copy( (UINT32 *)( BIOS + 0x0000000 ), 0x08000, 0x001c000 );
|
||||
nand_copy( (UINT32 *)( BIOS + 0x0020000 ), 0x24000, 0x03e0000 );
|
||||
}
|
||||
|
||||
static void decrypt_bios( running_machine &machine, const char *regionName, int start, int b15, int b14, int b13, int b12, int b11, int b10, int b9, int b8,
|
||||
static void decrypt_bios( running_machine &machine, const char *regionName, int start, int end, int b15, int b14, int b13, int b12, int b11, int b10, int b9, int b8,
|
||||
int b7, int b6, int b5, int b4, int b3, int b2, int b1, int b0 )
|
||||
{
|
||||
memory_region *region = machine.root_device().memregion( regionName );
|
||||
UINT16 *BIOS = (UINT16 *)( region->base() + start );
|
||||
int len = (region->bytes()-start)/2;
|
||||
int len = (end - start) / 2;
|
||||
|
||||
for( int i = 0; i < len; i++ )
|
||||
{
|
||||
@ -513,66 +527,77 @@ static void decrypt_bios( running_machine &machine, const char *regionName, int
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,mrdrilr2)
|
||||
{
|
||||
decrypt_bios( machine(), "maincpu:rom", 0, 0xc, 0xd, 0xf, 0xe, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x4, 0x1, 0x2, 0x5, 0x0, 0x3 );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "maincpu:rom", 0, regSize, 0xc, 0xd, 0xf, 0xe, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x4, 0x1, 0x2, 0x5, 0x0, 0x3);
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,gjspace)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x0, 0x2, 0xe, 0xd, 0xf, 0x6, 0xc, 0x7, 0x5, 0x1, 0x9, 0x8, 0xa, 0x3, 0x4, 0xb );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x0, 0x2, 0xe, 0xd, 0xf, 0x6, 0xc, 0x7, 0x5, 0x1, 0x9, 0x8, 0xa, 0x3, 0x4, 0xb);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,mrdrilrg)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x6, 0x4, 0x7, 0x5, 0x2, 0x1, 0x0, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xb, 0xa );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x6, 0x4, 0x7, 0x5, 0x2, 0x1, 0x0, 0x3, 0xc, 0xd, 0xe, 0xf, 0x8, 0x9, 0xb, 0xa);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,knpuzzle)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x6, 0x7, 0x4, 0x5, 0x2, 0x0, 0x3, 0x1, 0xc, 0xd, 0xe, 0xf, 0x9, 0xb, 0x8, 0xa );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x6, 0x7, 0x4, 0x5, 0x2, 0x0, 0x3, 0x1, 0xc, 0xd, 0xe, 0xf, 0x9, 0xb, 0x8, 0xa);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,startrgn)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9 );
|
||||
decrypt_bios(machine(), "user2", 0x008400, 0x028000, 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9);
|
||||
decrypt_bios(machine(), "user2", 0x0b4000, 0xfdc000, 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,gamshara)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x5, 0x4, 0x7, 0x6, 0x0, 0x1, 0x3, 0x2, 0xd, 0xf, 0xc, 0xe, 0x8, 0x9, 0xa, 0xb );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x5, 0x4, 0x7, 0x6, 0x0, 0x1, 0x3, 0x2, 0xd, 0xf, 0xc, 0xe, 0x8, 0x9, 0xa, 0xb);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,gunbalna)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x5, 0x4, 0x7, 0x6, 0x0, 0x1, 0x3, 0x2, 0xd, 0xf, 0xc, 0xe, 0x9, 0x8, 0xa, 0xb );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x5, 0x4, 0x7, 0x6, 0x0, 0x1, 0x3, 0x2, 0xd, 0xf, 0xc, 0xe, 0x9, 0x8, 0xa, 0xb);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,chocovdr)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x5, 0x4, 0x6, 0x7, 0x1, 0x0, 0x2, 0x3, 0xc, 0xf, 0xe, 0xd, 0x8, 0xb, 0xa, 0x9 );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x5, 0x4, 0x6, 0x7, 0x1, 0x0, 0x2, 0x3, 0xc, 0xf, 0xe, 0xd, 0x8, 0xb, 0xa, 0x9);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,panikuru)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x6, 0x4, 0x7, 0x5, 0x0, 0x1, 0x2, 0x3, 0xc, 0xf, 0xe, 0xd, 0x9, 0x8, 0xb, 0xa );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x6, 0x4, 0x7, 0x5, 0x0, 0x1, 0x2, 0x3, 0xc, 0xf, 0xe, 0xd, 0x9, 0x8, 0xb, 0xa);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,nflclsfb)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9 );
|
||||
int regSize = machine().root_device().memregion("user2")->bytes();
|
||||
decrypt_bios(machine(), "user2", 0x8400, regSize, 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
DRIVER_INIT_MEMBER(namcos10_state,konotako)
|
||||
{
|
||||
decrypt_bios( machine(), "user2", 0x8400, 0x6, 0x7, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x8, 0x9, 0xb, 0xa );
|
||||
decrypt_bios(machine(), "user2", 0x008400, 0x028000, 0x6, 0x7, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x8, 0x9, 0xb, 0xa);
|
||||
decrypt_bios(machine(), "user2", 0x0b4000, 0xfdc000, 0x6, 0x7, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0xd, 0xc, 0xf, 0xe, 0x8, 0x9, 0xb, 0xa);
|
||||
memn_driver_init();
|
||||
}
|
||||
|
||||
@ -615,6 +640,16 @@ static MACHINE_CONFIG_START( namcos10_memn, namcos10_state )
|
||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED(ns10_konotako, namcos10_memn)
|
||||
/* decrypter device (CPLD in hardware?) */
|
||||
MCFG_DEVICE_ADD("decrypter", KONOTAKO_DECRYPTER, 0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static MACHINE_CONFIG_DERIVED(ns10_startrgn, namcos10_memn)
|
||||
/* decrypter device (CPLD in hardware?) */
|
||||
MCFG_DEVICE_ADD("decrypter", STARTRGN_DECRYPTER, 0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static INPUT_PORTS_START( namcos10 )
|
||||
/* IN 0 */
|
||||
PORT_START("SYSTEM")
|
||||
@ -750,8 +785,9 @@ ROM_START( ptblank3 )
|
||||
ROM_FILL( 0x0000000, 0x400000, 0x55 )
|
||||
|
||||
ROM_REGION16_LE( 0x2100000, "user2", 0 ) /* main prg */
|
||||
ROM_LOAD( "gnn2a.8e", 0x0000000, 0x1080000, CRC(31b39221) SHA1(7fcb14aaa26c531928a6cd704e746d0e3ae3e031) )
|
||||
ROM_LOAD( "gnn2a.8d", 0x1080000, 0x1080000, CRC(82d2cfb5) SHA1(4b5e713a55e74a7b32b1b9b5811892df2df86256) )
|
||||
// protection issues preventing the last NAND block to be dumped
|
||||
ROM_LOAD("gnn2a.8e", 0x0000000, 0x1080000, BAD_DUMP CRC(31b39221) SHA1(7fcb14aaa26c531928a6cd704e746d0e3ae3e031))
|
||||
ROM_LOAD( "gnn2a.8d", 0x1080000, 0x1080000, BAD_DUMP CRC(82d2cfb5) SHA1(4b5e713a55e74a7b32b1b9b5811892df2df86256) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( gunbalina )
|
||||
@ -759,8 +795,9 @@ ROM_START( gunbalina )
|
||||
ROM_FILL( 0x0000000, 0x400000, 0x55 )
|
||||
|
||||
ROM_REGION16_LE( 0x2100000, "user2", 0 ) /* main prg */
|
||||
ROM_LOAD( "gnn1a.8e", 0x0000000, 0x1080000, CRC(981b03d4) SHA1(1c55458f1b2964afe2cf4e9d84548c0699808e9f) )
|
||||
ROM_LOAD( "gnn1a.8d", 0x1080000, 0x1080000, CRC(6cd343e0) SHA1(dcec44abae1504025895f42fe574549e5010f7d5) )
|
||||
// protection issues preventing the last NAND block to be dumped
|
||||
ROM_LOAD( "gnn1a.8e", 0x0000000, 0x1080000, BAD_DUMP CRC(981b03d4) SHA1(1c55458f1b2964afe2cf4e9d84548c0699808e9f) )
|
||||
ROM_LOAD( "gnn1a.8d", 0x1080000, 0x1080000, BAD_DUMP CRC(6cd343e0) SHA1(dcec44abae1504025895f42fe574549e5010f7d5) )
|
||||
ROM_END
|
||||
|
||||
ROM_START( chocovdr )
|
||||
@ -806,17 +843,17 @@ ROM_START( konotako )
|
||||
ROM_END
|
||||
|
||||
|
||||
GAME( 2000, mrdrilr2, 0, namcos10_memm, namcos10, namcos10_state, mrdrilr2, ROT0, "Namco", "Mr. Driller 2 (Japan, DR21 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2000, mrdrlr2a, mrdrilr2, namcos10_memm, namcos10, namcos10_state, mrdrilr2, ROT0, "Namco", "Mr. Driller 2 (Asia, DR22 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2000, ptblank3, 0, namcos10_memn, namcos10, namcos10_state, gunbalna, ROT0, "Namco", "Point Blank 3 (Asia, GNN2 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2000, gunbalina, ptblank3, namcos10_memn, namcos10, namcos10_state, gunbalna, ROT0, "Namco", "Gunbalina (Japan, GNN1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2001, gjspace, 0, namcos10_memn, namcos10, namcos10_state, gjspace, ROT0, "Namco / Metro", "Gekitoride-Jong Space (10011 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2001, mrdrilrg, 0, namcos10_memn, namcos10, namcos10_state, mrdrilrg, ROT0, "Namco", "Mr. Driller G (Japan, DRG1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2001, mrdrilrga, mrdrilrg, namcos10_memn, namcos10, namcos10_state, mrdrilrg, ROT0, "Namco", "Mr. Driller G ALT (Japan, DRG1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2001, knpuzzle, 0, namcos10_memn, namcos10, namcos10_state, knpuzzle, ROT0, "Namco", "Kotoba no Puzzle Mojipittan (Japan, KPM1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2002, chocovdr, 0, namcos10_memn, namcos10, namcos10_state, chocovdr, ROT0, "Namco", "Uchuu Daisakusen: Chocovader Contactee (Japan, CVC1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2002, startrgn, 0, namcos10_memn, namcos10, namcos10_state, startrgn, ROT0, "Namco", "Star Trigon (Japan, STT1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2002, panikuru, 0, namcos10_memn, namcos10, namcos10_state, panikuru, ROT0, "Namco", "Panicuru Panekuru (Japan, PPA1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2003, nflclsfb, 0, namcos10_memn, namcos10, namcos10_state, nflclsfb, ROT0, "Namco", "NFL Classic Football (US, NCF3 Ver.A.)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2003, gamshara, 0, namcos10_memn, namcos10, namcos10_state, gamshara, ROT0, "Mitchell", "Gamshara (10021 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2003, konotako, 0, namcos10_memn, namcos10, namcos10_state, konotako, ROT0, "Mitchell", "Kono Tako (10021 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2000, mrdrilr2, 0, namcos10_memm, namcos10, namcos10_state, mrdrilr2, ROT0, "Namco", "Mr. Driller 2 (Japan, DR21 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2000, mrdrlr2a, mrdrilr2, namcos10_memm, namcos10, namcos10_state, mrdrilr2, ROT0, "Namco", "Mr. Driller 2 (Asia, DR22 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2000, ptblank3, 0, namcos10_memn, namcos10, namcos10_state, gunbalna, ROT0, "Namco", "Point Blank 3 (Asia, GNN2 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2000, gunbalina, ptblank3, namcos10_memn, namcos10, namcos10_state, gunbalna, ROT0, "Namco", "Gunbalina (Japan, GNN1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2001, gjspace, 0, namcos10_memn, namcos10, namcos10_state, gjspace, ROT0, "Namco / Metro", "Gekitoride-Jong Space (10011 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2001, mrdrilrg, 0, namcos10_memn, namcos10, namcos10_state, mrdrilrg, ROT0, "Namco", "Mr. Driller G (Japan, DRG1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2001, mrdrilrga, mrdrilrg, namcos10_memn, namcos10, namcos10_state, mrdrilrg, ROT0, "Namco", "Mr. Driller G ALT (Japan, DRG1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // PORT_4WAY joysticks
|
||||
GAME( 2001, knpuzzle, 0, namcos10_memn, namcos10, namcos10_state, knpuzzle, ROT0, "Namco", "Kotoba no Puzzle Mojipittan (Japan, KPM1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2002, chocovdr, 0, namcos10_memn, namcos10, namcos10_state, chocovdr, ROT0, "Namco", "Uchuu Daisakusen: Chocovader Contactee (Japan, CVC1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2002, startrgn, 0, ns10_startrgn, namcos10, namcos10_state, startrgn, ROT0, "Namco", "Star Trigon (Japan, STT1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
GAME( 2002, panikuru, 0, namcos10_memn, namcos10, namcos10_state, panikuru, ROT0, "Namco", "Panicuru Panekuru (Japan, PPA1 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2003, nflclsfb, 0, namcos10_memn, namcos10, namcos10_state, nflclsfb, ROT0, "Namco", "NFL Classic Football (US, NCF3 Ver.A.)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2003, gamshara, 0, namcos10_memn, namcos10, namcos10_state, gamshara, ROT0, "Mitchell", "Gamshara (10021 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
|
||||
GAME( 2003, konotako, 0, ns10_konotako, namcos10, namcos10_state, konotako, ROT0, "Mitchell", "Kono Tako (10021 Ver.A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
|
||||
|
214
src/mame/machine/ns10crypt.c
Normal file
214
src/mame/machine/ns10crypt.c
Normal file
@ -0,0 +1,214 @@
|
||||
// license:BSD-3
|
||||
// copyright-holders:Andreas Naive
|
||||
/****************************************************************************
|
||||
Namco System 10 decryption emulation
|
||||
|
||||
(As of 2015-08, this file is still pretty much a WIP; changes are expected as
|
||||
out knowledge progress.)
|
||||
|
||||
The decryption used by type-2 System10 PCBs (MEM-N) acts on 16-bit words and is
|
||||
designed to operate in a serial way: once the decryption is triggered, every
|
||||
word is XORed with a mask calculated over data taken from the previous words
|
||||
(both encrypted and decrypted). Type-1 PCBs seem to use a similar
|
||||
scheme, probably involving the word address too and a bitswap, but his relation
|
||||
to what is described here needs further investigation.
|
||||
|
||||
In type-2 PCBs, the encrypted data is always contained in the first ROM of the
|
||||
game (8E), and it's always stored spanning an integer number of NAND blocks
|
||||
(the K9F2808U0B is organized in blocks of 16 KiB, each containing 32 pages of
|
||||
0x200 bytes). The first part of the encrypted data is stored at about the end
|
||||
of the ROM, and apparently all the blocks in that area are processed in
|
||||
reverse order (first the one nearest the end, then the second nearest, etc);
|
||||
the second part goes inmediately after it from a logic perspective, but it's
|
||||
physically located at the area starting at 0x28000 in the ROM. Games, after
|
||||
some bootup code has been executed, will copy the encrypted content from
|
||||
the ROM to RAM, moment at which the decryption is triggered.
|
||||
|
||||
Most games do a single decryption run, so the process is only initialized once;
|
||||
however, at least one game (gamshara) does write to the triggering registers
|
||||
more than once, effectively resetting the internal state of the decrypter
|
||||
several times. (gamshara do it every 5 NAND blocks).
|
||||
|
||||
The calculation of the XOR masks seem to operate this way: most bits are
|
||||
calculated by using linear equations over GF(2) taking as input data the bits from
|
||||
previously processed words; however, one nonlinear calculation is performed
|
||||
per word processed, and that calculation can affect several bits from the
|
||||
mask (but, apparently, the same nonlinear terms affect all of them),
|
||||
though in most cases only one bit is involved. Till now, most of the linear
|
||||
relations seem to depend only on the previous 3 words, but there are some
|
||||
bits from those showing nonlinear behaviour which seem to use farther words;
|
||||
this is still being investigated, and the implementation is probable to
|
||||
change to reflect new findings.
|
||||
|
||||
The bits affected by the nonlinear calculations are given below:
|
||||
chocovdr -> #10
|
||||
gamshara -> #2
|
||||
gjspace -> a subset of {#3, #4, #5, #10, #11}, maybe all of them
|
||||
gunbalina -> #11
|
||||
knpuzzle -> #1
|
||||
konotako -> #15
|
||||
mrdrilrg -> #0 & #4
|
||||
nflclsfb -> #2
|
||||
panikuru -> #2
|
||||
ptblank3 -> #11
|
||||
startrgn -> #4
|
||||
|
||||
|
||||
TO-DO:
|
||||
* Research the nonlinear calculations in most of the games.
|
||||
* Determine how many previous words the hardware is really using, and change
|
||||
the implementation accordingly.
|
||||
|
||||
Observing the linear equations, there is a keen difference between bits using
|
||||
just a bunch of previous bits, and others using much more bits from more words;
|
||||
simplyfing the latter ones could be handy, and probably closer to what the
|
||||
hardware is doing. Two possible simplyfications could be:
|
||||
A) The linear relations are creating lots of identities involving the bits
|
||||
from the sequence; they could be exploited to simplify the equations (but
|
||||
only when the implementation be stable, to avoid duplicating work).
|
||||
B) It's possible that some of those calculations are being stored and then
|
||||
used as another input bits for subsequent masks. Determining that (supposed)
|
||||
bits and factoring out them would simplify the expressions, in case they
|
||||
really exist.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "ns10crypt.h"
|
||||
|
||||
const device_type KONOTAKO_DECRYPTER = &device_creator<konotako_decrypter_device>;
|
||||
const device_type STARTRGN_DECRYPTER = &device_creator<startrgn_decrypter_device>;
|
||||
|
||||
ns10_decrypter_device::ns10_decrypter_device(device_type type, const ns10_crypto_logic &logic, const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, type, "Namco System 10 Decrypter", tag, owner, clock, "ns10_crypto", __FILE__)
|
||||
, _active(false)
|
||||
, _logic(logic)
|
||||
{
|
||||
}
|
||||
|
||||
void ns10_decrypter_device::activate()
|
||||
{
|
||||
init();
|
||||
_active = true;
|
||||
}
|
||||
|
||||
void ns10_decrypter_device::deactivate()
|
||||
{
|
||||
_active = false;
|
||||
}
|
||||
|
||||
bool ns10_decrypter_device::is_active()const
|
||||
{
|
||||
return _active;
|
||||
}
|
||||
|
||||
UINT16 ns10_decrypter_device::decrypt(UINT16 cipherword)
|
||||
{
|
||||
UINT16 plainword = cipherword ^ _mask;
|
||||
|
||||
_previous_cipherwords <<= 16;
|
||||
_previous_cipherwords ^= cipherword;
|
||||
_previous_plainwords <<= 16;
|
||||
_previous_plainwords ^= plainword;
|
||||
|
||||
_mask = 0;
|
||||
for (int j = 15; j >= 0; --j)
|
||||
{
|
||||
_mask <<= 1;
|
||||
_mask ^= gf2_reduce(_logic.eMask[j] & _previous_cipherwords);
|
||||
_mask ^= gf2_reduce(_logic.dMask[j] & _previous_plainwords);
|
||||
}
|
||||
_mask ^= _logic.xMask;
|
||||
_mask ^= _logic.nonlinear_calculation(_previous_cipherwords, _previous_plainwords);
|
||||
|
||||
return plainword;
|
||||
}
|
||||
|
||||
void ns10_decrypter_device::device_start()
|
||||
{
|
||||
int reduction;
|
||||
|
||||
// create a look-up table of GF2 reductions of 16-bits words
|
||||
for (int i = 0; i < 0x10000; ++i)
|
||||
{
|
||||
reduction = 0;
|
||||
for (int j = 0; j < 16; ++j)
|
||||
reduction ^= BIT(i, j);
|
||||
|
||||
_gf2Reduction[i] = reduction;
|
||||
}
|
||||
}
|
||||
|
||||
void ns10_decrypter_device::init()
|
||||
{
|
||||
_previous_cipherwords = 0;
|
||||
_previous_plainwords = 0;
|
||||
_mask = 0;
|
||||
}
|
||||
|
||||
int ns10_decrypter_device::gf2_reduce(UINT64 num)
|
||||
{
|
||||
return
|
||||
_gf2Reduction[num & 0xffff] ^
|
||||
_gf2Reduction[(num >> 16) & 0xffff] ^
|
||||
_gf2Reduction[(num >> 32) & 0xffff] ^
|
||||
_gf2Reduction[num >> 48];
|
||||
}
|
||||
|
||||
|
||||
// game-specific logic
|
||||
|
||||
static UINT16 konotako_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords)
|
||||
{
|
||||
UINT64 previous_masks = previous_cipherwords ^ previous_plainwords;
|
||||
return ((previous_masks >> 7) & (previous_masks >> 15) & 1) << 15;
|
||||
}
|
||||
|
||||
static const ns10_decrypter_device::ns10_crypto_logic konotako_crypto_logic = {
|
||||
{
|
||||
0x000000000000004cull, 0x00000000d39e3d3dull, 0x0000000000001110ull, 0x0000000000002200ull,
|
||||
0x000000003680c008ull, 0x0000000000000281ull, 0x0000000000005002ull, 0x00002a7371895a47ull,
|
||||
0x0000000000000003ull, 0x00002a7371897a4eull, 0x00002a73aea17a41ull, 0x00002a73fd895a4full,
|
||||
0x000000005328200aull, 0x0000000000000010ull, 0x0000000000000040ull, 0x0000000000000200ull,
|
||||
}, {
|
||||
0x000000000000008cull, 0x0000000053003d25ull, 0x0000000000001120ull, 0x0000000000002200ull,
|
||||
0x0000000037004008ull, 0x0000000000000282ull, 0x0000000000006002ull, 0x0000060035005a47ull,
|
||||
0x0000000000000003ull, 0x0000060035001a4eull, 0x0000060025007a41ull, 0x00000600b5005a2full,
|
||||
0x000000009000200bull, 0x0000000000000310ull, 0x0000000000001840ull, 0x0000000000000400ull,
|
||||
},
|
||||
0x0748,
|
||||
konotako_nonlinear_calc
|
||||
};
|
||||
|
||||
static UINT16 startrgn_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords)
|
||||
{
|
||||
UINT64 previous_masks = previous_cipherwords ^ previous_plainwords;
|
||||
return ((previous_masks >> 12) & (previous_masks >> 14) & 1) << 4;
|
||||
}
|
||||
|
||||
static const ns10_decrypter_device::ns10_crypto_logic startrgn_crypto_logic = {
|
||||
{
|
||||
0x00003e4bfe92c6a9ull, 0x000000000000010cull, 0x00003e4b7bd6c4aaull, 0x0000b1a904b8fab8ull,
|
||||
0x0000000000000080ull, 0x0000000000008c00ull, 0x0000b1a9b2f0b4cdull, 0x000000006c100828ull,
|
||||
0x000000006c100838ull, 0x0000b1a9d3913fcdull, 0x000000006161aa00ull, 0x0000000000006040ull,
|
||||
0x0000000000000420ull, 0x0000000000001801ull, 0x00003e4b7bd6deabull, 0x0000000000000105ull,
|
||||
}, {
|
||||
0x000012021f00c6a8ull, 0x0000000000000008ull, 0x000012020b1046aaull, 0x000012001502fea8ull,
|
||||
0x0000000000002000ull, 0x0000000000008800ull, 0x000012001e02b4cdull, 0x000000002c0008aaull,
|
||||
0x000000002c00083aull, 0x000012003f027ecdull, 0x0000000021008a00ull, 0x0000000000002040ull,
|
||||
0x0000000000000428ull, 0x0000000000001001ull, 0x000012020b10ceabull, 0x0000000000000144ull,
|
||||
},
|
||||
0x8c46,
|
||||
startrgn_nonlinear_calc
|
||||
};
|
||||
|
||||
// game-specific devices
|
||||
|
||||
konotako_decrypter_device::konotako_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: ns10_decrypter_device(KONOTAKO_DECRYPTER, konotako_crypto_logic, mconfig, tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
startrgn_decrypter_device::startrgn_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: ns10_decrypter_device(STARTRGN_DECRYPTER, startrgn_crypto_logic, mconfig, tag, owner, clock)
|
||||
{
|
||||
}
|
62
src/mame/machine/ns10crypt.h
Normal file
62
src/mame/machine/ns10crypt.h
Normal file
@ -0,0 +1,62 @@
|
||||
// license:BSD-3
|
||||
// copyright-holders:Andreas Naive
|
||||
|
||||
#ifndef _NS10CRYPT_H_
|
||||
#define _NS10CRYPT_H_
|
||||
|
||||
class ns10_decrypter_device : public device_t
|
||||
{
|
||||
public:
|
||||
// this encodes the decryption logic, which varies per game
|
||||
// and is probably hard-coded into the CPLD
|
||||
struct ns10_crypto_logic
|
||||
{
|
||||
UINT64 eMask[16];
|
||||
UINT64 dMask[16];
|
||||
UINT16 xMask;
|
||||
UINT16(*nonlinear_calculation)(UINT64, UINT64); // preliminary encoding; need research
|
||||
};
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
bool is_active()const;
|
||||
|
||||
UINT16 decrypt(UINT16 cipherword);
|
||||
|
||||
protected:
|
||||
ns10_decrypter_device(
|
||||
device_type type, const ns10_decrypter_device::ns10_crypto_logic &logic,
|
||||
const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
private:
|
||||
UINT16 _mask;
|
||||
UINT64 _previous_cipherwords;
|
||||
UINT64 _previous_plainwords;
|
||||
bool _active;
|
||||
const ns10_crypto_logic& _logic;
|
||||
int _gf2Reduction[0x10000];
|
||||
|
||||
void device_start();
|
||||
void init();
|
||||
int gf2_reduce(UINT64 num);
|
||||
};
|
||||
|
||||
// game-specific devices
|
||||
|
||||
class konotako_decrypter_device : public ns10_decrypter_device
|
||||
{
|
||||
public:
|
||||
konotako_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
class startrgn_decrypter_device : public ns10_decrypter_device
|
||||
{
|
||||
public:
|
||||
startrgn_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
};
|
||||
|
||||
|
||||
extern const device_type KONOTAKO_DECRYPTER;
|
||||
extern const device_type STARTRGN_DECRYPTER;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user