summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ivan Vangelista <mesgnet@yahoo.it>2025-09-02 19:13:42 +0200
committer Ivan Vangelista <mesgnet@yahoo.it>2025-09-02 19:13:42 +0200
commit1589b15876508b3c36b386daa4f990fb78b94db9 (patch)
tree59d7fbfe4ed9cc788694be022cedc06078a04b0a
parent4abd3acc37549c9cc5565a8138836325fdf9d209 (diff)
igs/igs036crypt:added decryption table for hlddz
-rw-r--r--src/mame/igs/igs036crypt.cpp113
-rw-r--r--src/mame/igs/igs036crypt.h20
-rw-r--r--src/mame/igs/igs_m036.cpp4
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 )