From 977221d7a5cf90fc7d04eea181350915b53a209b Mon Sep 17 00:00:00 2001 From: andreasnaive Date: Wed, 5 Aug 2015 18:47:40 +0200 Subject: [PATCH] on-the-fly decryption support for chocovdr & nflclsfb (nw) --- src/mame/drivers/namcos10.c | 44 ++++++++++++----- src/mame/machine/ns10crypt.c | 93 +++++++++++++++++++++++++++++------- src/mame/machine/ns10crypt.h | 30 ++++++++++-- 3 files changed, 137 insertions(+), 30 deletions(-) diff --git a/src/mame/drivers/namcos10.c b/src/mame/drivers/namcos10.c index 1d31a740d2d..e20ca8f7219 100644 --- a/src/mame/drivers/namcos10.c +++ b/src/mame/drivers/namcos10.c @@ -406,6 +406,10 @@ ADDRESS_MAP_END WRITE16_MEMBER(namcos10_state::crypto_switch_w) { + printf("crypto_switch_w: %04x\n", data); + if (decrypter == 0) + return; + if (BIT(data, 15) != 0) decrypter->activate(data & 0xf); else @@ -462,6 +466,9 @@ READ16_MEMBER( namcos10_state::nand_data_r ) /* printf( "data<-%08x (%08x)\n", data, nand_address ); */ nand_address++; + if (decrypter == 0) + return data; + if (decrypter->is_active()) return decrypter->decrypt(data); else @@ -490,6 +497,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(crypto_switch_w, 0x0000ffff) + AM_RANGE(0x1f380000, 0x1f380003) 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) @@ -580,7 +588,9 @@ DRIVER_INIT_MEMBER(namcos10_state,gunbalna) DRIVER_INIT_MEMBER(namcos10_state,chocovdr) { 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); + decrypt_bios(machine(), "user2", 0x0008400, 0x0029400, 0x5, 0x4, 0x6, 0x7, 0x1, 0x0, 0x2, 0x3, 0xc, 0xf, 0xe, 0xd, 0x8, 0xb, 0xa, 0x9); + decrypt_bios(machine(), "user2", 0x01eae00, 0x105ae00, 0x5, 0x4, 0x6, 0x7, 0x1, 0x0, 0x2, 0x3, 0xc, 0xf, 0xe, 0xd, 0x8, 0xb, 0xa, 0x9); + decrypt_bios(machine(), "user2", 0x1080000, regSize , 0x5, 0x4, 0x6, 0x7, 0x1, 0x0, 0x2, 0x3, 0xc, 0xf, 0xe, 0xd, 0x8, 0xb, 0xa, 0x9); memn_driver_init(); } @@ -594,7 +604,9 @@ DRIVER_INIT_MEMBER(namcos10_state,panikuru) DRIVER_INIT_MEMBER(namcos10_state,nflclsfb) { 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); + decrypt_bios(machine(), "user2", 0x0008400, 0x0029400, 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9); + decrypt_bios(machine(), "user2", 0x0214200, 0x105ae00, 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9); + decrypt_bios(machine(), "user2", 0x1080000, regSize , 0x6, 0x5, 0x4, 0x7, 0x1, 0x3, 0x0, 0x2, 0xc, 0xd, 0xe, 0xf, 0x8, 0xb, 0xa, 0x9); memn_driver_init(); } @@ -646,14 +658,9 @@ 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) +static MACHINE_CONFIG_DERIVED(ns10_chocovdr, 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) +MCFG_DEVICE_ADD("decrypter", CHOCOVDR_DECRYPTER, 0) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED(ns10_gamshara, namcos10_memn) @@ -661,6 +668,21 @@ static MACHINE_CONFIG_DERIVED(ns10_gamshara, namcos10_memn) MCFG_DEVICE_ADD("decrypter", GAMSHARA_DECRYPTER, 0) 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_nflclsfb, namcos10_memn) +/* decrypter device (CPLD in hardware?) */ +MCFG_DEVICE_ADD("decrypter", NFLCLSFB_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") @@ -862,9 +884,9 @@ GAME( 2001, gjspace, 0, namcos10_memn, namcos10, namcos10_state, gjspac 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, chocovdr, 0, ns10_chocovdr, 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, nflclsfb, 0, ns10_nflclsfb, namcos10, namcos10_state, nflclsfb, ROT0, "Namco", "NFL Classic Football (US, NCF3 Ver.A.)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) GAME( 2003, gamshara, 0, ns10_gamshara, 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) diff --git a/src/mame/machine/ns10crypt.c b/src/mame/machine/ns10crypt.c index 14e09dc8878..3d81f09f830 100644 --- a/src/mame/machine/ns10crypt.c +++ b/src/mame/machine/ns10crypt.c @@ -84,8 +84,10 @@ really exist. #include "emu.h" #include "ns10crypt.h" +const device_type CHOCOVDR_DECRYPTER = &device_creator; const device_type GAMSHARA_DECRYPTER = &device_creator; const device_type KONOTAKO_DECRYPTER = &device_creator; +const device_type NFLCLSFB_DECRYPTER = &device_creator; const device_type STARTRGN_DECRYPTER = &device_creator; // this could perfectly be part of the per-game logic; by now, only gamshara seems to use it, so we keep it global @@ -127,16 +129,30 @@ UINT16 ns10_decrypter_device::decrypt(UINT16 cipherword) 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 ^= _reducer.gf2_reduce(_logic.eMask[j] & _previous_cipherwords); + _mask ^= _reducer.gf2_reduce(_logic.dMask[j] & _previous_plainwords); } _mask ^= _logic.xMask; - _mask ^= _logic.nonlinear_calculation(_previous_cipherwords, _previous_plainwords); + _mask ^= _logic.nonlinear_calculation(_previous_cipherwords, _previous_plainwords, _reducer); return plainword; } void ns10_decrypter_device::device_start() +{ + _active = false; +} + +void ns10_decrypter_device::init(int iv) +{ + // by now, only gamshara requires non-trivial initialization code; data + // should be moved to the per-game logic in case any other game do it differently + _previous_cipherwords = BITSWAP16(initSbox[iv],3,16,16,2,1,16,16,0,16,16,16,16,16,16,16,16); + _previous_plainwords = 0; + _mask = 0; +} + +gf2_reducer::gf2_reducer() { int reduction; @@ -151,16 +167,7 @@ void ns10_decrypter_device::device_start() } } -void ns10_decrypter_device::init(int iv) -{ - // by now, only gamshara requires non-trivial initialization code; data - // should be moved to the per-game logic in case any other game do it differently - _previous_cipherwords = BITSWAP16(initSbox[iv],3,16,16,2,1,16,16,0,16,16,16,16,16,16,16,16); - _previous_plainwords = 0; - _mask = 0; -} - -int ns10_decrypter_device::gf2_reduce(UINT64 num) +int gf2_reducer::gf2_reduce(UINT64 num)const { return _gf2Reduction[num & 0xffff] ^ @@ -172,7 +179,29 @@ int ns10_decrypter_device::gf2_reduce(UINT64 num) // game-specific logic -static UINT16 gamshara_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords) +static UINT16 chocovdr_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords, const gf2_reducer& reducer) +{ + UINT64 previous_masks = previous_cipherwords ^ previous_plainwords; + return ((previous_masks >> 9) & (reducer.gf2_reduce(0x0000000010065810ull & previous_cipherwords) ^ reducer.gf2_reduce(0x0000000021005810ull & previous_plainwords)) & 1) << 10; +} + +static const ns10_decrypter_device::ns10_crypto_logic chocovdr_crypto_logic = { + { + 0x00005239351ec1daull, 0x0000000000008090ull, 0x0000000048264808ull, 0x0000000000004820ull, + 0x0000000000000500ull, 0x0000000058ff5a54ull, 0x00000000d8220208ull, 0x00005239351e91d3ull, + 0x000000009a1dfaffull, 0x0000000090040001ull, 0x0000000000000100ull, 0x0000000000001408ull, + 0x0000000032efd3f1ull, 0x00000000000000d0ull, 0x0000000032efd2d7ull, 0x0000000000000840ull, + }, { + 0x00002000410485daull, 0x0000000000008081ull, 0x0000000008044088ull, 0x0000000000004802ull, + 0x0000000000000500ull, 0x00000000430cda54ull, 0x0000000010000028ull, 0x00002000410491dbull, + 0x000000001100fafeull, 0x0000000018040001ull, 0x0000000000000010ull, 0x0000000000000508ull, + 0x000000006800d3f5ull, 0x0000000000000058ull, 0x000000006800d2d5ull, 0x0000000000001840ull, + }, + 0x5b22, + chocovdr_nonlinear_calc +}; + +static UINT16 gamshara_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords, const gf2_reducer&) { UINT64 previous_masks = previous_cipherwords ^ previous_plainwords; return ((previous_masks >> 7) & (previous_masks >> 13) & 1) << 2; @@ -194,7 +223,7 @@ static const ns10_decrypter_device::ns10_crypto_logic gamshara_crypto_logic = { gamshara_nonlinear_calc }; -static UINT16 konotako_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords) +static UINT16 konotako_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords, const gf2_reducer&) { UINT64 previous_masks = previous_cipherwords ^ previous_plainwords; return ((previous_masks >> 7) & (previous_masks >> 15) & 1) << 15; @@ -216,7 +245,29 @@ static const ns10_decrypter_device::ns10_crypto_logic konotako_crypto_logic = { konotako_nonlinear_calc }; -static UINT16 startrgn_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords) +static UINT16 nflclsfb_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords, const gf2_reducer& reducer) +{ + UINT64 previous_masks = previous_cipherwords ^ previous_plainwords; + return ((previous_masks >> 1) & (reducer.gf2_reduce(0x0000000040de8fb3ull & previous_cipherwords) ^ reducer.gf2_reduce(0x0000000088008fb3ull & previous_plainwords)) & 1) << 2; +} + +static const ns10_decrypter_device::ns10_crypto_logic nflclsfb_crypto_logic = { + { + 0x000034886e281880ull, 0x0000000012c5e7baull, 0x0000000000000200ull, 0x000000002900002aull, + 0x00000000000004c0ull, 0x0000000012c5e6baull, 0x00000000e0df8bbbull, 0x000000002011532aull, + 0x0000000000009040ull, 0x0000000000006004ull, 0x000000000000a001ull, 0x000034886e2818e1ull, + 0x0000000000004404ull, 0x0000000000004200ull, 0x0000000000009100ull, 0x0000000020115712ull, + }, { + 0x00000e00060819c0ull, 0x000000000e08e7baull, 0x0000000000000800ull, 0x000000000100002aull, + 0x00000000000010c0ull, 0x000000000e08cebaull, 0x0000000088018bbbull, 0x000000008c005302ull, + 0x000000000000c040ull, 0x0000000000006010ull, 0x0000000000000001ull, 0x00000e00060818e3ull, + 0x0000000000000404ull, 0x0000000000004201ull, 0x0000000000001100ull, 0x000000008c0057b2ull, + }, + 0xbe32, + nflclsfb_nonlinear_calc +}; + +static UINT16 startrgn_nonlinear_calc(UINT64 previous_cipherwords, UINT64 previous_plainwords, const gf2_reducer&) { UINT64 previous_masks = previous_cipherwords ^ previous_plainwords; return ((previous_masks >> 12) & (previous_masks >> 14) & 1) << 4; @@ -241,6 +292,11 @@ static const ns10_decrypter_device::ns10_crypto_logic startrgn_crypto_logic = { // game-specific devices +chocovdr_decrypter_device::chocovdr_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : ns10_decrypter_device(CHOCOVDR_DECRYPTER, chocovdr_crypto_logic, mconfig, tag, owner, clock) +{ +} + gamshara_decrypter_device::gamshara_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : ns10_decrypter_device(GAMSHARA_DECRYPTER, gamshara_crypto_logic, mconfig, tag, owner, clock) { @@ -251,6 +307,11 @@ konotako_decrypter_device::konotako_decrypter_device(const machine_config &mconf { } +nflclsfb_decrypter_device::nflclsfb_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : ns10_decrypter_device(NFLCLSFB_DECRYPTER, nflclsfb_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) { diff --git a/src/mame/machine/ns10crypt.h b/src/mame/machine/ns10crypt.h index a70aee65d8e..5952e23f1b1 100644 --- a/src/mame/machine/ns10crypt.h +++ b/src/mame/machine/ns10crypt.h @@ -4,6 +4,15 @@ #ifndef _NS10CRYPT_H_ #define _NS10CRYPT_H_ +class gf2_reducer // helper class +{ +public: + gf2_reducer(); + int gf2_reduce(UINT64 num)const; +private: + int _gf2Reduction[0x10000]; +}; + class ns10_decrypter_device : public device_t { public: @@ -14,7 +23,7 @@ public: UINT64 eMask[16]; UINT64 dMask[16]; UINT16 xMask; - UINT16(*nonlinear_calculation)(UINT64, UINT64); // preliminary encoding; need research + UINT16(*nonlinear_calculation)(UINT64, UINT64, const gf2_reducer&); // preliminary encoding; need research }; void activate(int iv); @@ -34,16 +43,23 @@ private: UINT64 _previous_plainwords; bool _active; const ns10_crypto_logic& _logic; - int _gf2Reduction[0x10000]; static const int initSbox[16]; + const gf2_reducer _reducer; void device_start(); void init(int iv); - int gf2_reduce(UINT64 num); }; + + // game-specific devices +class chocovdr_decrypter_device : public ns10_decrypter_device +{ +public: + chocovdr_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; + class gamshara_decrypter_device : public ns10_decrypter_device { public: @@ -56,6 +72,12 @@ public: konotako_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); }; +class nflclsfb_decrypter_device : public ns10_decrypter_device +{ +public: + nflclsfb_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); +}; + class startrgn_decrypter_device : public ns10_decrypter_device { public: @@ -63,8 +85,10 @@ public: }; +extern const device_type CHOCOVDR_DECRYPTER; extern const device_type GAMSHARA_DECRYPTER; extern const device_type KONOTAKO_DECRYPTER; +extern const device_type NFLCLSFB_DECRYPTER; extern const device_type STARTRGN_DECRYPTER; #endif