forked from Plombo/vcromclaim
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathneogeo_cmc_m1.py
164 lines (124 loc) · 7.14 KB
/
neogeo_cmc_m1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#!/usr/bin/env python3
# Python re-implementation of https://github.com/mamedev/mame/blob/master/src/devices/bus/neogeo/prot_cmc.cpp (M1 part)
# but also with encryption, so that MAME can decrypt it
# WARNING: minor adjustments to the input and output.
# this converts back and forth between the Wii ROM and an original ROM, while
# mame converts from an original ROM to the address space expected by the game code/hardware.
import arcade_utilities
#static const uint8_t m1_address_8_15_xor[256] = {
m1_address_8_15_xor = [
0x0a, 0x72, 0xb7, 0xaf, 0x67, 0xde, 0x1d, 0xb1, 0x78, 0xc4, 0x4f, 0xb5, 0x4b, 0x18, 0x76, 0xdd,
0x11, 0xe2, 0x36, 0xa1, 0x82, 0x03, 0x98, 0xa0, 0x10, 0x5f, 0x3f, 0xd6, 0x1f, 0x90, 0x6a, 0x0b,
0x70, 0xe0, 0x64, 0xcb, 0x9f, 0x38, 0x8b, 0x53, 0x04, 0xca, 0xf8, 0xd0, 0x07, 0x68, 0x56, 0x32,
0xae, 0x1c, 0x2e, 0x48, 0x63, 0x92, 0x9a, 0x9c, 0x44, 0x85, 0x41, 0x40, 0x09, 0xc0, 0xc8, 0xbf,
0xea, 0xbb, 0xf7, 0x2d, 0x99, 0x21, 0xf6, 0xba, 0x15, 0xce, 0xab, 0xb0, 0x2a, 0x60, 0xbc, 0xf1,
0xf0, 0x9e, 0xd5, 0x97, 0xd8, 0x4e, 0x14, 0x9d, 0x42, 0x4d, 0x2c, 0x5c, 0x2b, 0xa6, 0xe1, 0xa7,
0xef, 0x25, 0x33, 0x7a, 0xeb, 0xe7, 0x1b, 0x6d, 0x4c, 0x52, 0x26, 0x62, 0xb6, 0x35, 0xbe, 0x80,
0x01, 0xbd, 0xfd, 0x37, 0xf9, 0x47, 0x55, 0x71, 0xb4, 0xf2, 0xff, 0x27, 0xfa, 0x23, 0xc9, 0x83,
0x17, 0x39, 0x13, 0x0d, 0xc7, 0x86, 0x16, 0xec, 0x49, 0x6f, 0xfe, 0x34, 0x05, 0x8f, 0x00, 0xe6,
0xa4, 0xda, 0x7b, 0xc1, 0xf3, 0xf4, 0xd9, 0x75, 0x28, 0x66, 0x87, 0xa8, 0x45, 0x6c, 0x20, 0xe9,
0x77, 0x93, 0x7e, 0x3c, 0x1e, 0x74, 0xf5, 0x8c, 0x3e, 0x94, 0xd4, 0xc2, 0x5a, 0x06, 0x0e, 0xe8,
0x3d, 0xa9, 0xb2, 0xe3, 0xe4, 0x22, 0xcf, 0x24, 0x8e, 0x6b, 0x8a, 0x8d, 0x84, 0x4a, 0xd2, 0x91,
0x88, 0x79, 0x57, 0xa5, 0x0f, 0xcd, 0xb9, 0xac, 0x3b, 0xaa, 0xb3, 0xd1, 0xee, 0x31, 0x81, 0x7c,
0xd7, 0x89, 0xd3, 0x96, 0x43, 0xc5, 0xc6, 0xc3, 0x69, 0x7f, 0x46, 0xdf, 0x30, 0x5b, 0x6e, 0xe5,
0x08, 0x95, 0x9b, 0xfb, 0xb8, 0x58, 0x0c, 0x61, 0x50, 0x5d, 0x3a, 0xa2, 0x29, 0x12, 0xfc, 0x51,
0x7d, 0x1a, 0x02, 0x65, 0x54, 0x5e, 0x19, 0xcc, 0xdc, 0xdb, 0x73, 0xed, 0xad, 0x59, 0x2f, 0xa3,
]
#static const uint8_t m1_address_0_7_xor[256] = {
m1_address_0_7_xor = [
0xf4, 0xbc, 0x02, 0xf7, 0x2c, 0x3d, 0xe8, 0xd9, 0x50, 0x62, 0xec, 0xbd, 0x53, 0x73, 0x79, 0x61,
0x00, 0x34, 0xcf, 0xa2, 0x63, 0x28, 0x90, 0xaf, 0x44, 0x3b, 0xc5, 0x8d, 0x3a, 0x46, 0x07, 0x70,
0x66, 0xbe, 0xd8, 0x8b, 0xe9, 0xa0, 0x4b, 0x98, 0xdc, 0xdf, 0xe2, 0x16, 0x74, 0xf1, 0x37, 0xf5,
0xb7, 0x21, 0x81, 0x01, 0x1c, 0x1b, 0x94, 0x36, 0x09, 0xa1, 0x4a, 0x91, 0x30, 0x92, 0x9b, 0x9a,
0x29, 0xb1, 0x38, 0x4d, 0x55, 0xf2, 0x56, 0x18, 0x24, 0x47, 0x9d, 0x3f, 0x80, 0x1f, 0x22, 0xa4,
0x11, 0x54, 0x84, 0x0d, 0x25, 0x48, 0xee, 0xc6, 0x59, 0x15, 0x03, 0x7a, 0xfd, 0x6c, 0xc3, 0x33,
0x5b, 0xc4, 0x7b, 0x5a, 0x05, 0x7f, 0xa6, 0x40, 0xa9, 0x5d, 0x41, 0x8a, 0x96, 0x52, 0xd3, 0xf0,
0xab, 0x72, 0x10, 0x88, 0x6f, 0x95, 0x7c, 0xa8, 0xcd, 0x9c, 0x5f, 0x32, 0xae, 0x85, 0x39, 0xac,
0xe5, 0xd7, 0xfb, 0xd4, 0x08, 0x23, 0x19, 0x65, 0x6b, 0xa7, 0x93, 0xbb, 0x2b, 0xbf, 0xb8, 0x35,
0xd0, 0x06, 0x26, 0x68, 0x3e, 0xdd, 0xb9, 0x69, 0x2a, 0xb2, 0xde, 0x87, 0x45, 0x58, 0xff, 0x3c,
0x9e, 0x7d, 0xda, 0xed, 0x49, 0x8c, 0x14, 0x8e, 0x75, 0x2f, 0xe0, 0x6e, 0x78, 0x6d, 0x20, 0xd2,
0xfa, 0x2d, 0x51, 0xcc, 0xc7, 0xe7, 0x1d, 0x27, 0x97, 0xfc, 0x31, 0xdb, 0xf8, 0x42, 0xe3, 0x99,
0x5e, 0x83, 0x0e, 0xb4, 0x2e, 0xf6, 0xc0, 0x0c, 0x4c, 0x57, 0xb6, 0x64, 0x0a, 0x17, 0xa3, 0xc1,
0x77, 0x12, 0xfe, 0xe6, 0x8f, 0x13, 0x71, 0xe4, 0xf9, 0xad, 0x9f, 0xce, 0xd5, 0x89, 0x7e, 0x0f,
0xc2, 0x86, 0xf3, 0x67, 0xba, 0x60, 0x43, 0xc9, 0x04, 0xb3, 0xb0, 0x1e, 0xb5, 0xc8, 0xeb, 0xa5,
0x76, 0xea, 0x5c, 0x82, 0x1a, 0x4f, 0xaa, 0xca, 0xe1, 0x0b, 0x4e, 0xcb, 0x6a, 0xef, 0xd1, 0xd6,
]
# The CMC50 hardware does a checksum of the first 64kb of the M1 rom, and
# uses this checksum as the basis of the key with which to decrypt the rom */
#uint16_t cmc_prot_device::generate_cs16(uint8_t *rom, int size)
def generate_cs16(rom, size):
#uint16_t cs16 = 0x0000;
cs16 = 0x0000
#for (int i = 0; i < size; i++)
for i in range(0, size):
cs16 += rom[i]
return cs16 & 0xffff
#int cmc_prot_device::m1_address_scramble(int address, uint16_t key)
def m1_address_scramble(address, key):
#const int p1[8][16] = {
p1 = [
[15,14,10,7,1,2,3,8,0,12,11,13,6,9,5,4],
[7,1,8,11,15,9,2,3,5,13,4,14,10,0,6,12],
[8,6,14,3,10,7,15,1,4,0,2,5,13,11,12,9],
[2,8,15,9,3,4,11,7,13,6,0,10,1,12,14,5],
[1,13,6,15,14,3,8,10,9,4,7,12,5,2,0,11],
[11,15,3,4,7,0,9,2,6,14,12,1,8,5,10,13],
[10,5,13,8,6,15,1,14,11,9,3,0,12,7,4,2],
[9,3,7,0,2,12,4,11,14,10,5,8,15,13,1,6],
]
#int block = (address >> 16) & 7;
block = (address >> 16) & 7
#int aux = address & 0xffff;
aux = address & 0xffff
#aux ^= bitswap<16>(key,12,0,2,4,8,15,7,13,10,1,3,6,11,9,14,5);
aux ^= arcade_utilities.bitswap(key,[12,0,2,4,8,15,7,13,10,1,3,6,11,9,14,5])
#aux = bitswap<16>(aux,
# p1[block][15], p1[block][14], p1[block][13], p1[block][12],
# p1[block][11], p1[block][10], p1[block][9], p1[block][8],
# p1[block][7], p1[block][6], p1[block][5], p1[block][4],
# p1[block][3], p1[block][2], p1[block][1], p1[block][0]);
aux = arcade_utilities.bitswap(aux,
[p1[block][15], p1[block][14], p1[block][13], p1[block][12],
p1[block][11], p1[block][10], p1[block][9], p1[block][8],
p1[block][7], p1[block][6], p1[block][5], p1[block][4],
p1[block][3], p1[block][2], p1[block][1], p1[block][0]])
#aux ^= m1_address_0_7_xor[(aux >> 8) & 0xff];
aux ^= m1_address_0_7_xor[(aux >> 8) & 0xff]
#aux ^= m1_address_8_15_xor[aux & 0xff] << 8;
aux ^= m1_address_8_15_xor[aux & 0xff] << 8
#aux = bitswap<16>(aux, 7,15,14,6,5,13,12,4,11,3,10,2,9,1,8,0);
aux = arcade_utilities.bitswap(aux, [7,15,14,6,5,13,12,4,11,3,10,2,9,1,8,0])
return (block << 16) | aux
#void cmc_prot_device::cmc50_m1_decrypt(uint8_t* romcrypt, uint32_t romcrypt_size, uint8_t* romaudio, uint32_t romaudio_size) {
def cmc50_m1_decrypt_or_encrypt(input_rom, encrypt):
entire_m1_size = 0x20000
used_m1_size = 0x10000
empty_m1_size = 0x10000
assert len(input_rom) == entire_m1_size
for i in range(used_m1_size, entire_m1_size):
assert input_rom[i] == 0xFF
#uint8_t* rom = romcrypt;
#size_t rom_size = 0x80000;
#uint8_t* rom2 = romaudio;
#std::vector<uint8_t> buffer(rom_size);
output_data = bytearray(used_m1_size)
#uint16_t key = generate_cs16(rom, 0x10000);
key = generate_cs16(input_rom, used_m1_size)
#for (uint32_t i = 0; i < rom_size; i++)
for i in range(0, used_m1_size):
#buffer[i] = rom[m1_address_scramble(i,key)];
if encrypt:
output_data[m1_address_scramble(i, key)] = input_rom[i]
else:
output_data[i] = input_rom[m1_address_scramble(i, key)]
#memcpy(rom, &buffer[0], rom_size);
#memcpy(rom2,rom, 0x10000);
#memcpy(rom2 + 0x10000, rom, 0x80000);
#rom2[0x10000:0x90000] = rom[0:0x80000]
return output_data[0:used_m1_size] + b'\xFF' * empty_m1_size
def encrypt_cmc50_m1(unencrypted_m1rom):
print("Encrypting M1 ROM with original CMC50 encryption...")
return cmc50_m1_decrypt_or_encrypt(unencrypted_m1rom, True)
def decrypt_cmc50_m1(encrypted_m1rom):
print("Decrypting M1 ROM with CMC50 encryption...")
return cmc50_m1_decrypt_or_encrypt(encrypted_m1rom, False)