From 1b54a32a92a18e653ab9b2bdf27b2b42dc54ed54 Mon Sep 17 00:00:00 2001 From: 987123879113 <63495610+987123879113@users.noreply.github.com> Date: Tue, 23 May 2023 21:47:57 +0900 Subject: namco/namcos10.cpp, namco/ns10crypt.cpp: Added partial decrypter for Point Blank 3. (#11244) [Peter Wilhelmsen, Samuel Neves] sound/spu.cpp: Don't explode when the reverb parameters couldn't be found after a save state. [Windy Fairy] --- src/devices/sound/spu.cpp | 7 +++ src/devices/sound/spureverb.cpp | 2 +- src/mame/namco/namcos10.cpp | 30 +++++++-- src/mame/namco/ns10crypt.cpp | 136 +++++++++++++++++++++++++++++++++++----- src/mame/namco/ns10crypt.h | 53 +++++++++++++++- 5 files changed, 206 insertions(+), 22 deletions(-) diff --git a/src/devices/sound/spu.cpp b/src/devices/sound/spu.cpp index 120fb4a8f55..a0ec7800a9c 100644 --- a/src/devices/sound/spu.cpp +++ b/src/devices/sound/spu.cpp @@ -2536,6 +2536,13 @@ void spu_device::update_reverb() { if (dirty_flags&dirtyflag_reverb) { + // TODO: Handle cases where reverb present can't be found better + // If a save state is loaded and has reverb values that don't match a preset + // then spu_reverb_cfg is never set so the reverb settings won't be the same as + // when the save state was created. + // This only becomes an issue when loading save states from the command line + // because if you load a save state from within MAME it will hold the last used + // spu_reverb_cfg and reuse that value. cur_reverb_preset=find_reverb_preset((unsigned short *)®[0x1c0]); if (cur_reverb_preset==nullptr) diff --git a/src/devices/sound/spureverb.cpp b/src/devices/sound/spureverb.cpp index e57c33d448d..2bd3c3244bd 100644 --- a/src/devices/sound/spureverb.cpp +++ b/src/devices/sound/spureverb.cpp @@ -308,7 +308,7 @@ void spu_device::reverb::process(signed short *output, signed short *sp=(signed short *)reverb_input, *dp=(signed short *)output; - if (rp->band_gain>0.0f) + if (rp && rp->band_gain>0.0f) { // Do reverb processing diff --git a/src/mame/namco/namcos10.cpp b/src/mame/namco/namcos10.cpp index 7f966849b9c..41ed856ddc9 100644 --- a/src/mame/namco/namcos10.cpp +++ b/src/mame/namco/namcos10.cpp @@ -2289,7 +2289,24 @@ void namcos10_memn_state::ns10_ptblank3(machine_config &config) m_unscrambler = [] (uint16_t data) { return bitswap<16>(data, 0xd, 0xc, 0xf, 0xe, 0x8, 0x9, 0xb, 0xa, 0x5, 0x7, 0x4, 0x6, 0x1, 0x0, 0x2, 0x3); }; - // NS10_TYPE2_DECRYPTER(config, m_decrypter, 0, logic); + NS10_TYPE2_DECRYPTER_NONLINEAR(config, m_decrypter, 0, ns10_type2_decrypter_nonlinear_device::ns10_crypto_logic{ + { + 0x0000000057001200ULL,0x00000000000000a4ULL,0x0000000000000150ULL,0x0000000000008004ULL, + 0x0000000057002204ULL,0x0000000009001000ULL,0x0000000000102000ULL,0x0000000064004888ULL, + 0x0000000000100008ULL,0x000000a0c0980600ULL,0x000000001801c020ULL,0x00005810881a09c0ULL, + // 0x00000c10084a29dcULL if non_linear[0] is 0x44 instead of of 0x04 then we need this instead (final plaintext is the same) + 0x0000000400980600ULL,0x0000000000000300ULL,0x0000000000000080ULL,0x0000000000a00c0aULL + }, { + 0x0000000041051000ULL,0x0000000000000024ULL,0x0000000000000050ULL,0x0000000000008004ULL, + 0x0000000041052200ULL,0x0000000009401100ULL,0x0000000000122000ULL,0x0000000004100898ULL, + 0x0000000000120088ULL,0x0000000040a80400ULL,0x0000000019004000ULL,0x000001859830281dULL, + 0x0000002400880201ULL,0x0000000000000300ULL,0x00000000000000c0ULL,0x0000000000000408ULL + }, + 0xe1b8, + [] (uint16_t nonlinear_bit) -> uint16_t { + return nonlinear_bit << 11; + } + }); } void namcos10_memn_state::ns10_puzzball(machine_config &config) @@ -3460,12 +3477,12 @@ ROM_START( gunbalina ) ROM_REGION32_LE( 0x1080000, "nand0", 0 ) ROM_LOAD( "gnn1a.8e", 0x0000000, 0x1080000, CRC(981b03d4) SHA1(1c55458f1b2964afe2cf4e9d84548c0699808e9f) ) - ROM_LOAD( "ptblank3_prog.bin", 0x00029400, 0x002de3f0, CRC(1612383d) SHA1(e2f339444fe01a4f51ee784692c6d7f989080dc7) ) // Program code is unencrypted but scrambled - ROM_CONTINUE( 0x1056c00, 0x25200 ) - ROM_COPY( "nand0", 0x84000, 0x1052a00, 0x4200 ) // relocate block 0x20 ROM_REGION32_LE( 0x1080000, "nand1", 0 ) ROM_LOAD( "gnn1a.8d", 0x0000000, 0x1080000, CRC(6cd343e0) SHA1(dcec44abae1504025895f42fe574549e5010f7d5) ) + + ROM_REGION( 0x2ec00, "decrypter:nonlinear_table", 0 ) + ROM_LOAD( "ptblank3_nonlinear", 0x00000, 0x2ec00, CRC(5997d7dd) SHA1(ab3f32fd92ee20ca3c7642686d9d8039d0b6cbc5) ) ROM_END ROM_START( kd2001 ) @@ -3602,11 +3619,12 @@ ROM_START( ptblank3 ) ROM_REGION32_LE( 0x1080000, "nand0", 0 ) ROM_LOAD( "gnn2vera_0.8e", 0x0000000, 0x1080000, CRC(3777ef6b) SHA1(44dce83f75d10f843db0feef4c2a738442434246) ) - ROM_LOAD( "ptblank3_prog.bin", 0x00029400, 0x002de3f0, CRC(1612383d) SHA1(e2f339444fe01a4f51ee784692c6d7f989080dc7) ) // Program code is unencrypted but scrambled - ROM_CONTINUE(0x1056c00, 0x25200) ROM_REGION32_LE( 0x1080000, "nand1", 0 ) ROM_LOAD( "gnn2vera_1.8d", 0x0000000, 0x1080000, CRC(82d2cfb5) SHA1(4b5e713a55e74a7b32b1b9b5811892df2df86256) ) + + ROM_REGION( 0x2ec00, "decrypter:nonlinear_table", 0 ) + ROM_LOAD( "ptblank3_nonlinear", 0x00000, 0x2ec00, CRC(5997d7dd) SHA1(ab3f32fd92ee20ca3c7642686d9d8039d0b6cbc5) ) ROM_END ROM_START( puzzball ) diff --git a/src/mame/namco/ns10crypt.cpp b/src/mame/namco/ns10crypt.cpp index 4e5db02ced5..33eaa3fc22a 100644 --- a/src/mame/namco/ns10crypt.cpp +++ b/src/mame/namco/ns10crypt.cpp @@ -124,15 +124,25 @@ really exist. DEFINE_DEVICE_TYPE(MRDRILR2_DECRYPTER, mrdrilr2_decrypter_device, "mrdrilr2_decrypter", "Mr Driller 2 decrypter") DEFINE_DEVICE_TYPE(NS10_TYPE2_DECRYPTER, ns10_type2_decrypter_device, "ns10_type2_decrypter", "Namco System 10 Type 2 decrypter") +DEFINE_DEVICE_TYPE(NS10_TYPE2_DECRYPTER_NONLINEAR, ns10_type2_decrypter_nonlinear_device, "ns10_type2_decrypter_nonlinear", "Namco System 10 Type 2 decrypter (non-linear bit lookup table)") // base class ns10_decrypter_device::ns10_decrypter_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) - , m_active(false) { } +void ns10_decrypter_device::device_start() +{ + save_item(NAME(m_active)); +} + +void ns10_decrypter_device::device_reset() +{ + m_active = false; +} + void ns10_decrypter_device::activate(int iv) { init(iv); @@ -157,11 +167,25 @@ const int ns10_type1_decrypter_device::INIT_SBOX[16]{U, U, U, 0, 4, 9, U, U, U, ns10_type1_decrypter_device::ns10_type1_decrypter_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : ns10_decrypter_device(mconfig, type, tag, owner, clock) - , m_mask(0) - , m_counter(0) { } +void ns10_type1_decrypter_device::device_start() +{ + ns10_decrypter_device::device_start(); + + save_item(NAME(m_mask)); + save_item(NAME(m_counter)); +} + +void ns10_type1_decrypter_device::device_reset() +{ + ns10_decrypter_device::device_reset(); + + m_mask = 0; + m_counter = 0; +} + uint16_t ns10_type1_decrypter_device::decrypt(uint16_t cipherword) { uint16_t plainword = m_mask ^ bitswap<16>(cipherword, 9, 13, 15, 7, 14, 8, 6, 10, 11, 12, 3, 5, 0, 1, 4, 2); @@ -193,11 +217,6 @@ void ns10_type1_decrypter_device::init(int iv) m_counter = 0; } -void ns10_type1_decrypter_device::device_start() -{ - m_active = false; -} - mrdrilr2_decrypter_device::mrdrilr2_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ns10_type1_decrypter_device(mconfig, MRDRILR2_DECRYPTER, tag, owner, clock) { @@ -210,9 +229,6 @@ const int ns10_type2_decrypter_device::INIT_SBOX[16]{0, 12, 13, 6, 2, 4, 9, 8, 1 ns10_type2_decrypter_device::ns10_type2_decrypter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : ns10_decrypter_device(mconfig, NS10_TYPE2_DECRYPTER, tag, owner, clock) - , m_mask(0) - , m_previous_cipherwords(0) - , m_previous_plainwords(0) { } @@ -257,8 +273,100 @@ void ns10_type2_decrypter_device::init(int iv) void ns10_type2_decrypter_device::device_start() { - // If the logic isn't initialized then this will just fail - assert(m_logic_initialized == true); + ns10_decrypter_device::device_start(); - m_active = false; + // If the logic isn't initialized then this will just fail, this is a programmer error + if (!m_logic_initialized) + fatalerror("ns10_type2_decrypter_device: Required logic data for decrypter device not initialized"); + + save_item(NAME(m_mask)); + save_item(NAME(m_previous_cipherwords)); + save_item(NAME(m_previous_plainwords)); +} + +void ns10_type2_decrypter_device::device_reset() +{ + ns10_decrypter_device::device_reset(); + + m_mask = 0; + m_previous_cipherwords = 0; + m_previous_plainwords = 0; +} + +// type-2 decrypter with a table for the non-linear bits +const int ns10_type2_decrypter_nonlinear_device::INIT_SBOX[16]{0, 12, 13, 6, 2, 4, 9, 8, 11, 1, 7, 15, 10, 5, 14, 3}; + +ns10_type2_decrypter_nonlinear_device::ns10_type2_decrypter_nonlinear_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ns10_decrypter_device(mconfig, NS10_TYPE2_DECRYPTER_NONLINEAR, tag, owner, clock) + , m_nonlinear_region(*this, "nonlinear_table") +{ +} + +ns10_type2_decrypter_nonlinear_device::ns10_type2_decrypter_nonlinear_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, ns10_crypto_logic &&logic) + : ns10_decrypter_device(mconfig, NS10_TYPE2_DECRYPTER_NONLINEAR, tag, owner, clock) + , m_nonlinear_region(*this, "nonlinear_table") + , m_logic(std::move(logic)) +{ + m_logic_initialized = true; +} + +uint16_t ns10_type2_decrypter_nonlinear_device::decrypt(uint16_t cipherword) +{ + uint16_t const plainword = cipherword ^ m_mask; + + m_previous_cipherwords <<= 16; + m_previous_cipherwords ^= cipherword; + m_previous_plainwords <<= 16; + m_previous_plainwords ^= plainword; + + m_mask = 0; + for (int j = 15; j >= 0; --j) + { + m_mask <<= 1; + m_mask ^= gf2_reduce(m_logic.eMask[j] & m_previous_cipherwords); + m_mask ^= gf2_reduce(m_logic.dMask[j] & m_previous_plainwords); + } + m_mask ^= m_logic.xMask; + + uint8_t nonlinear_bit = BIT(m_nonlinear_region->base()[m_nonlinear_count / 8], 7 - (m_nonlinear_count % 8)); + m_nonlinear_count++; + if (m_nonlinear_count >= m_nonlinear_region->bytes() * 8) + m_nonlinear_count = 0; + m_mask ^= m_logic.nonlinear_calculation(nonlinear_bit); + + return plainword; +} + +void ns10_type2_decrypter_nonlinear_device::init(int iv) +{ + if (m_logic.iv_calculation) + m_previous_cipherwords = m_logic.iv_calculation(iv); + else + m_previous_cipherwords = bitswap(INIT_SBOX[iv], 3, 16, 16, 2, 1, 16, 16, 0, 16, 16, 16, 16, 16, 16, 16, 16); + m_previous_plainwords = 0; + m_mask = 0; +} + +void ns10_type2_decrypter_nonlinear_device::device_start() +{ + ns10_decrypter_device::device_start(); + + // If the logic isn't initialized then this will just fail, this is a programmer error + if (!m_logic_initialized) + fatalerror("ns10_type2_decrypter_nonlinear_device: Required logic data for decrypter device not initialized"); + + save_item(NAME(m_mask)); + save_item(NAME(m_previous_cipherwords)); + save_item(NAME(m_previous_plainwords)); + save_item(NAME(m_nonlinear_count)); +} + +void ns10_type2_decrypter_nonlinear_device::device_reset() +{ + ns10_decrypter_device::device_reset(); + + m_mask = 0; + m_previous_cipherwords = 0; + m_previous_plainwords = 0; + m_nonlinear_count = 0; } diff --git a/src/mame/namco/ns10crypt.h b/src/mame/namco/ns10crypt.h index 29e5c6c1051..1d48cc056c7 100644 --- a/src/mame/namco/ns10crypt.h +++ b/src/mame/namco/ns10crypt.h @@ -24,7 +24,8 @@ public: protected: ns10_decrypter_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - virtual void device_start() override = 0; + virtual void device_start() override; + virtual void device_reset() override; virtual void init(int iv) = 0; @@ -42,6 +43,7 @@ protected: ns10_type1_decrypter_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); virtual void device_start() override; + virtual void device_reset() override; private: static const int INIT_SBOX[16]; @@ -79,6 +81,7 @@ public: protected: virtual void device_start() override; + virtual void device_reset() override; private: static const int INIT_SBOX[16]; @@ -88,6 +91,53 @@ private: uint16_t m_mask; uint64_t m_previous_cipherwords; uint64_t m_previous_plainwords; + + const ns10_crypto_logic m_logic; + + bool m_logic_initialized; +}; + +class ns10_type2_decrypter_nonlinear_device : public ns10_decrypter_device +{ +public: + // this encodes the decryption logic, which varies per game and is probably hard-coded into the CPLD + struct ns10_crypto_logic + { + using nonlinear_calculation_function = uint16_t (*)(uint16_t); + using iv_calculation_function = uint64_t (*)(int); + uint64_t eMask[16]{}; + uint64_t dMask[16]{}; + uint16_t xMask = 0; + nonlinear_calculation_function nonlinear_calculation = nullptr; // preliminary encoding; need research + iv_calculation_function iv_calculation = nullptr; + }; + + ns10_type2_decrypter_nonlinear_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + ns10_type2_decrypter_nonlinear_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, ns10_crypto_logic &&logic); + + virtual uint16_t decrypt(uint16_t cipherword) override; + + static int gf2_reduce(uint64_t num) + { + return population_count_64(num) & 1; + } + +protected: + virtual void device_start() override; + virtual void device_reset() override; + +private: + static const int INIT_SBOX[16]; + + virtual void init(int iv) override; + + uint16_t m_mask; + uint64_t m_previous_cipherwords; + uint64_t m_previous_plainwords; + uint32_t m_nonlinear_count; + + required_memory_region m_nonlinear_region; + const ns10_crypto_logic m_logic; bool m_logic_initialized; @@ -101,5 +151,6 @@ public: DECLARE_DEVICE_TYPE(MRDRILR2_DECRYPTER, mrdrilr2_decrypter_device) // Type 1 DECLARE_DEVICE_TYPE(NS10_TYPE2_DECRYPTER, ns10_type2_decrypter_device) +DECLARE_DEVICE_TYPE(NS10_TYPE2_DECRYPTER_NONLINEAR, ns10_type2_decrypter_nonlinear_device) #endif // MAME_NAMCO_NS10CRYPT_H -- cgit v1.2.3