diff options
| author | 2025-09-02 19:13:42 +0200 | |
|---|---|---|
| committer | 2025-09-02 19:13:42 +0200 | |
| commit | 1589b15876508b3c36b386daa4f990fb78b94db9 (patch) | |
| tree | 59d7fbfe4ed9cc788694be022cedc06078a04b0a | |
| parent | 4abd3acc37549c9cc5565a8138836325fdf9d209 (diff) | |
igs/igs036crypt:added decryption table for hlddz
| -rw-r--r-- | src/mame/igs/igs036crypt.cpp | 113 | ||||
| -rw-r--r-- | src/mame/igs/igs036crypt.h | 20 | ||||
| -rw-r--r-- | src/mame/igs/igs_m036.cpp | 4 |
3 files changed, 79 insertions, 58 deletions
diff --git a/src/mame/igs/igs036crypt.cpp b/src/mame/igs/igs036crypt.cpp index fdfa172a63a..44138aa52ef 100644 --- a/src/mame/igs/igs036crypt.cpp +++ b/src/mame/igs/igs036crypt.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Andreas Naive,David Haywood +// copyright-holders: Andreas Naive, David Haywood + #include "emu.h" #include "igs036crypt.h" @@ -60,33 +61,32 @@ kof98umh $E50E60-$E50E73 TO-DO: - complete the table with the 20-bytes values - decryption tables for the programs using less than 0x80000 of code (huoqilin, jhzb) -- decryption table for hlddz *****************************************************************************/ -igs036_decryptor::igs036_decryptor(const uint8_t* game_key) +igs036_decryptor::igs036_decryptor(const uint8_t *game_key) : key(game_key) { } -void igs036_decryptor::decrypter_rom(uint16_t* rom, int size, int offset) +void igs036_decryptor::decrypter_rom(uint16_t *rom, int size, int offset) { for (int i = 0; i < size / 2; i++) { - rom[i] = decrypt(rom[i], i+offset); + rom[i] = decrypt(rom[i], i + offset); } } -uint16_t igs036_decryptor::decrypt(uint16_t cipherword, int word_address)const +uint16_t igs036_decryptor::decrypt(uint16_t cipherword, int word_address) const { // key-independent manipulation int aux = deobfuscate(cipherword, word_address); // key-dependent manipulation - for (int i=0; i<16; ++i) + for (int i = 0; i < 16; ++i) { - if ((word_address&triggers[i][0]) == triggers[i][1]) - aux ^= BIT(key[word_address&0xff],i&7) << i; + if ((word_address & triggers[i][0]) == triggers[i][1]) + aux ^= BIT(key[word_address&0xff], i & 7) << i; else aux ^= BIT(0x1a3a, i) << i; } @@ -94,17 +94,17 @@ uint16_t igs036_decryptor::decrypt(uint16_t cipherword, int word_address)const return aux; } -uint16_t igs036_decryptor::deobfuscate(uint16_t cipherword, int word_address)const +uint16_t igs036_decryptor::deobfuscate(uint16_t cipherword, int word_address) const { // key-independent manipulation - int shift = rotation(word_address); + const int shift = rotation(word_address); int aux = rol(cipherword, shift); aux = bitswap<16>(aux, 10,9,8,7,0,15,6,5, 14,13,4,3,12,11,2,1); return aux; } -int igs036_decryptor::rotation(int address)const +int igs036_decryptor::rotation(int address) const { const int group15[] = {15,11, 7, 5}; // 15 is a guess const int group14[] = {14, 9, 3, 2}; @@ -112,37 +112,37 @@ int igs036_decryptor::rotation(int address)const const int group12[] = {12, 8, 4, 0}; // rotation depending on all the address bits - int enabled0 = rot_enabled(address, group15); + const int enabled0 = rot_enabled(address, group15); int rot = enabled0 * rot_group(address, group15) * 9; - int enabled1 = enabled0 ^ rot_enabled(address, group14); + const int enabled1 = enabled0 ^ rot_enabled(address, group14); rot += enabled1 * rot_group(address, group14) * 1; - int enabled2 = enabled0 ^ rot_enabled(address, group13); + const int enabled2 = enabled0 ^ rot_enabled(address, group13); rot += enabled2 * rot_group(address, group13) * 2; - int enabled3 = enabled0 ^ rot_enabled(address, group12); + const int enabled3 = enabled0 ^ rot_enabled(address, group12); rot += enabled3 * rot_group(address, group12) * 4; // block-independent rotation (just depending on the lowest 8 bits) - int rot2 = 4*BIT(address,0); - rot2 += 1*BIT(address,4)*(BIT(address,0)*2-1); - rot2 += 4*BIT(address,3)*(BIT(address,0)*2-1); - rot2 *= (BIT(address,7)|(BIT(address,0)^BIT(address,1)^1))*2-1; - rot2 += 2*((BIT(address,0)^BIT(address,1))&(BIT(address,7)^1)); + int rot2 = 4 * BIT(address, 0); + rot2 += 1 * BIT(address, 4) * (BIT(address, 0) * 2 - 1); + rot2 += 4 * BIT(address, 3) * (BIT(address, 0) * 2 - 1); + rot2 *= (BIT(address, 7) | (BIT(address, 0) ^ BIT(address, 1) ^ 1)) * 2 - 1; + rot2 += 2 * ((BIT(address, 0) ^ BIT(address, 1)) & (BIT(address, 7) ^ 1)); - return (rot+rot2)&0xf; + return (rot + rot2) & 0xf; } -int igs036_decryptor::rot_enabled(int address, const int* group)const +int igs036_decryptor::rot_enabled(int address, const int *group) const { int enabled = 0; - for (int j=0; j<4; ++j) + for (int j = 0; j <4 ; ++j) { - if (BIT(address,8+group[j])) + if (BIT(address, 8 + group[j])) { - int aux = address ^ (0x1b*BIT(address,2)); - enabled = rot_enabling[group[j]][aux&3](aux); + const int aux = address ^ (0x1b * BIT(address, 2)); + enabled = rot_enabling[group[j]][aux & 3](aux); break; } } @@ -150,18 +150,18 @@ int igs036_decryptor::rot_enabled(int address, const int* group)const return enabled; } -int igs036_decryptor::rot_group(int address, const int* group)const +int igs036_decryptor::rot_group(int address, const int *group) const { - int aux = rot_direction[group[0]&3][address&7](address); - return (aux*2)-1; + const int aux = rot_direction[group[0] & 3][address & 7](address); + return (aux * 2) - 1; } -uint16_t igs036_decryptor::rol(uint16_t num, int shift)const +uint16_t igs036_decryptor::rol(uint16_t num, int shift) const { - uint16_t r = num<<shift; - uint16_t l = num>>(16-shift); + const uint16_t r = num << shift; + const uint16_t l = num >> (16 - shift); - return r|l; + return r | l; } // the triggers describe under what conditions are every one of the 16 XORs activated @@ -188,18 +188,18 @@ const uint32_t igs036_decryptor::triggers[16][2] = { static int unknown(int address) { return 0; } static int cZero (int address) { return 0; } static int cOne (int address) { return 1; } -static int bit_3 (int address) { return BIT(address,3); } -static int bit_4 (int address) { return BIT(address,4); } -static int bit_7 (int address) { return BIT(address,7); } -static int not_3 (int address) { return BIT(address,3)^1; } -static int not_4 (int address) { return BIT(address,4)^1; } -static int not_7 (int address) { return BIT(address,7)^1; } -static int xor_37 (int address) { return BIT(address,3)^BIT(address,7); } -static int xnor_37(int address) { return BIT(address,3)^BIT(address,7)^1; } -static int xor_47 (int address) { return BIT(address,4)^BIT(address,7); } -static int xnor_47(int address) { return BIT(address,4)^BIT(address,7)^1; } -static int nor_34 (int address) { return (BIT(address,3)|BIT(address,4))^1; } -static int impl_43(int address) { return BIT(address,3)||(BIT(address,4)^1); } +static int bit_3 (int address) { return BIT(address, 3); } +static int bit_4 (int address) { return BIT(address, 4); } +static int bit_7 (int address) { return BIT(address, 7); } +static int not_3 (int address) { return BIT(address, 3) ^ 1; } +static int not_4 (int address) { return BIT(address, 4) ^ 1; } +static int not_7 (int address) { return BIT(address, 7) ^ 1; } +static int xor_37 (int address) { return BIT(address, 3) ^ BIT(address, 7); } +static int xnor_37(int address) { return BIT(address, 3) ^ BIT(address, 7) ^ 1; } +static int xor_47 (int address) { return BIT(address, 4) ^ BIT(address, 7); } +static int xnor_47(int address) { return BIT(address, 4) ^ BIT(address, 7) ^ 1; } +static int nor_34 (int address) { return (BIT(address, 3) | BIT(address, 4)) ^ 1; } +static int impl_43(int address) { return BIT(address, 3) || (BIT(address, 4) ^ 1); } int (*igs036_decryptor::rot_enabling[16][4])(int) = { @@ -233,7 +233,7 @@ int (*igs036_decryptor::rot_direction[4][8])(int) = { // The keys below have been obtained by an automatic process // exploiting the simple XOR scheme used by the system. Overall, the process, // while simple, seems to be pretty robust, so few errors should be expected, -// if any. The exceptions are DDPDOJ & KOF98UMH (see below). +// if any. const uint8_t m312cn_key[0x100] = { 0x01, 0x09, 0x02, 0xab, 0x23, 0x20, 0xa2, 0x03, 0x10, 0x9b, 0xba, 0x33, 0x04, 0x2e, 0x27, 0x23, @@ -652,3 +652,22 @@ const uint8_t hyleyuan_key[0x100] = { 0x30, 0x51, 0xb0, 0xd1, 0x24, 0xa1, 0x20, 0x40, 0x32, 0xb9, 0xf8, 0x68, 0xa3, 0xc8, 0x88, 0x05, 0x80, 0xe1, 0x11, 0xe1, 0x40, 0x63, 0x84, 0x90, 0x11, 0x49, 0xd1, 0x29, 0x45, 0x01, 0x35, 0x08, }; + +const uint8_t hlddz_key[0x100] = { + 0xb1, 0x02, 0x20, 0x29, 0x05, 0xa7, 0xa5, 0x2c, 0xbb, 0x9a, 0x09, 0x20, 0x09, 0x87, 0x85, 0x28, + 0x13, 0x80, 0x11, 0x10, 0x03, 0x1a, 0x04, 0x81, 0x0b, 0x0a, 0x10, 0x08, 0x14, 0x01, 0x91, 0x04, + 0x80, 0x18, 0x31, 0x38, 0x20, 0x05, 0xa5, 0xac, 0x82, 0xb1, 0x21, 0x91, 0x2a, 0x2a, 0x01, 0x0d, + 0xa1, 0xb2, 0x10, 0x31, 0x21, 0x33, 0x20, 0x28, 0x12, 0xba, 0x38, 0xb1, 0x81, 0x8d, 0x01, 0x94, + 0xe1, 0x48, 0x10, 0xd8, 0x81, 0x83, 0x44, 0x6c, 0xba, 0x02, 0x80, 0x29, 0x68, 0x23, 0xa1, 0x41, + 0x43, 0xcb, 0x50, 0xd0, 0xc3, 0x06, 0x85, 0xd1, 0x91, 0x8a, 0xd9, 0x10, 0x08, 0xce, 0xd4, 0x58, + 0xb0, 0x21, 0x91, 0xd1, 0x22, 0x89, 0x81, 0x68, 0x3a, 0x31, 0x89, 0xf9, 0x66, 0x25, 0x21, 0x28, + 0x42, 0x00, 0xf1, 0x71, 0x32, 0xcb, 0x25, 0xcc, 0x90, 0xb1, 0xa9, 0x28, 0xf9, 0xf3, 0xb8, 0x79, + 0x12, 0x98, 0x81, 0x18, 0xa4, 0x2d, 0x84, 0x08, 0xa1, 0x99, 0x10, 0x09, 0x21, 0x2b, 0xad, 0xa0, + 0x11, 0x00, 0x80, 0x98, 0x15, 0x9c, 0x01, 0x1d, 0x19, 0x11, 0x08, 0x19, 0x15, 0x9d, 0x94, 0x18, + 0xa3, 0x08, 0x91, 0x30, 0x86, 0x28, 0x01, 0xa4, 0x08, 0x28, 0xb1, 0x19, 0x0b, 0x8b, 0x8d, 0x8c, + 0x82, 0x39, 0xb1, 0x31, 0x34, 0x3f, 0x11, 0x35, 0x8b, 0x33, 0x08, 0x18, 0x87, 0x37, 0x9c, 0x20, + 0xe2, 0xab, 0x41, 0x91, 0xc1, 0xe1, 0x60, 0xe5, 0xf9, 0xa3, 0xf9, 0x98, 0x2c, 0x0e, 0x05, 0x05, + 0x11, 0x51, 0xd1, 0xc9, 0x40, 0x4d, 0xd5, 0x8c, 0xdb, 0x1b, 0x48, 0x89, 0x84, 0xc7, 0x58, 0x9c, + 0x00, 0x52, 0x30, 0x71, 0x04, 0x21, 0x05, 0x00, 0x9b, 0x79, 0x88, 0xf0, 0xe3, 0x2f, 0xcc, 0x05, + 0xf3, 0xe8, 0x41, 0x79, 0x90, 0x7d, 0xd5, 0x1c, 0x83, 0x20, 0xd8, 0x38, 0xeb, 0x97, 0x65, 0x11, +}; diff --git a/src/mame/igs/igs036crypt.h b/src/mame/igs/igs036crypt.h index 734a4cf3cff..af2a6d1d375 100644 --- a/src/mame/igs/igs036crypt.h +++ b/src/mame/igs/igs036crypt.h @@ -1,5 +1,6 @@ // license:BSD-3-Clause -// copyright-holders:Andreas Naive, David Haywood +// copyright-holders: Andreas Naive, David Haywood + #ifndef MAME_IGS_IGS036CRYPT_H #define MAME_IGS_IGS036CRYPT_H @@ -9,10 +10,10 @@ class igs036_decryptor { public: - igs036_decryptor(const uint8_t* game_key); - void decrypter_rom(uint16_t* rom, int size, int offset); - uint16_t decrypt(uint16_t cipherword, int word_address)const; - uint16_t deobfuscate(uint16_t cipherword, int word_address)const; + igs036_decryptor(const uint8_t *game_key); + void decrypter_rom(uint16_t *rom, int size, int offset); + uint16_t decrypt(uint16_t cipherword, int word_address) const; + uint16_t deobfuscate(uint16_t cipherword, int word_address) const; private: const uint8_t* key; @@ -21,10 +22,10 @@ private: static int (*rot_direction[4][8])(int); static const uint32_t triggers[16][2]; - int rotation(int address)const; - uint16_t rol(uint16_t num, int shift)const; - int rot_enabled(int address, const int* group)const ; - int rot_group(int address, const int* group)const; + int rotation(int address) const; + uint16_t rol(uint16_t num, int shift) const; + int rot_enabled(int address, const int *group) const; + int rot_group(int address, const int *group) const; }; extern const uint8_t m312cn_key[0x100]; @@ -49,5 +50,6 @@ extern const uint8_t mghammer_key[0x100]; extern const uint8_t mghammer_io_key[0x100]; extern const uint8_t zjddz_key[0x100]; extern const uint8_t hyleyuan_key[0x100]; +extern const uint8_t hlddz_key[0x100]; #endif // MAME_IGS_IGS036CRYPT_H diff --git a/src/mame/igs/igs_m036.cpp b/src/mame/igs/igs_m036.cpp index a66ba73ea59..2e8bf1e4bd8 100644 --- a/src/mame/igs/igs_m036.cpp +++ b/src/mame/igs/igs_m036.cpp @@ -755,7 +755,7 @@ ROM_START( huoqilin ) ROM_LOAD( "v103cn.u30", 0x1200000, 0x0200000, CRC(1eb6463e) SHA1(2979d7ef627ffbddd1c5236d4dcc1b622a2a9a38) ) ROM_END -// 猴椰乐园 (Hóu Yē Lèyuán) +// 猴椰乐园 (Hóu Yē Lèyuán) - PCB-0733-04-JC ROM_START( hyleyuan ) ROM_REGION( 0x4000, "maincpu", 0 ) // Internal ROM of IGS036 ARM based MCU @@ -884,7 +884,7 @@ GAME( 2010, mjzhizun, 0, igs_m036_tt, igs_m036, igs_m036_state, init_key<mjz GAME( 2010, lhfy, 0, igs_m036_tt, igs_m036, igs_m036_state, init_key<lhfy_key>, ROT0, "IGS", "Long Hu Feng Yun Gao Qing Ban (V206CN)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) -GAME( 20??, hlddz, 0, igs_m036_tt, igs_m036, igs_m036_state, init_igs_m036, ROT0, "IGS", "Huanle Dou Dizhu (V104CN)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) +GAME( 2010, hlddz, 0, igs_m036_tt, igs_m036, igs_m036_state, init_key<hlddz_key>, ROT0, "IGS", "Huanle Dou Dizhu (V104CN)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) GAME( 2010, zjddz, 0, igs_m036_tt, igs_m036, igs_m036_state, init_key<zjddz_key>, ROT0, "IGS", "Zhongji Dou Dizhu (V204CN)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) |
