What's new

Key cps2 20 bytes X key master mame

WRF77

Beginner
Joined
Jul 31, 2023
Messages
12
Reaction score
2
Location
Brasil
Hi, I would like to ask you a question about the relationship between the 20-byte decryption key used in real cps2 and the decryption key used in mame, which uses two 32-bit pairs. Is it possible to generate the key that mame uses using the 20-byte key or vice versa, and how is this done?
for example:
MAME key master
{ "sfzjr2", { 0xfc74bc,0x150796,0x1bb62b,0x99b3b4, 0x6d804f,0x0fedcf,0x8e9fb8,0xdc1171 } }, // 0C80 0564 2194 cmpi.l #$05642194,D0

cps2 real key
index watchdog key#2 key#1
{ 0x06{ 0x84, 0xc2, 0xeb, 0x7a, 0x3c, 0xa5 }, { 0xf4, 0x38, 0xeb, 0x65 }, { 0x79, 0x9c, 0xbf, 0x70 } 1944.key
 
Mame are not using hardcoded master keys anymore. From Mame 0.178 (Released 2016) did they start to use a 20 bytes ".key" file instead that can be programmed onto a CPS2 motherboard. It's possible to extract the 64 bit master key and the watchdog instruction from the file but not really needed since this is done internally in the CPS2 driver in Mame...
 
cps2 real key
index watchdog key#2 key#1
{ 0x06{ 0x84, 0xc2, 0xeb, 0x7a, 0x3c, 0xa5 }, { 0xf4, 0x38, 0xeb, 0x65 }, { 0x79, 0x9c, 0xbf, 0x70 } 1944.key
That line is from openkey-cps2 firmware. Please be mindful of the complete context of the code.

Code:
// There are only 10 unique combinations of the first 6 bytes
// of all key data.  In order to save about 800 bytes of flash
// we are using the below lookup table for these 6 bytes.
// Without the lookup table the code compiles very near to 4k,
// which would put it at risk of not being viable on attiny4x4s
uint8_t config_table[][CONFIG_SIZE] = {
 { 0x01, 0x00, 0x02, 0x40, 0x00, 0x08 },  // 0x00
 { 0x01, 0x00, 0x02, 0x40, 0x00, 0x09 },  // 0x01
 { 0x01, 0x00, 0x02, 0x40, 0x00, 0x0a },  // 0x02
 { 0x07, 0x00, 0x02, 0x40, 0x00, 0x08 },  // 0x03
 { 0x07, 0x00, 0x02, 0x40, 0x00, 0x0a },  // 0x04
 { 0x0f, 0x00, 0x02, 0x40, 0x00, 0x08 },  // 0x05
 { 0x0f, 0x00, 0x02, 0x40, 0x00, 0x09 },  // 0x06
 { 0x0f, 0x00, 0x02, 0x40, 0x00, 0x0a },  // 0x07
 { 0x3f, 0x00, 0x02, 0x40, 0x00, 0x08 },  // 0x08
 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },  // 0x09
};

struct game_data_t {
  uint8_t config_table_index;
  uint8_t watchdog[WATCHDOG_SIZE];
  uint8_t key2[KEY_SIZE];
  uint8_t key1[KEY_SIZE];
};

#define MAX_GAME_NUM 174
struct game_data_t game_data[MAX_GAME_NUM + 1] = {
  // config table                                                                                                          jumpers
  //    index                  watchdog config                         key#2                        key#1                  12345678 raw key filename
  {     0x06,       { 0x84, 0xc2, 0xeb, 0x7a, 0x3c, 0xa5 },  { 0xf4, 0x38, 0xeb, 0x65 },  { 0x79, 0x9c, 0xbf, 0x70 } }, // 00000000 1944.key

That 0x06 index byte gets replaced with
Code:
{ 0x0f, 0x00, 0x02, 0x40, 0x00, 0x09 }
to build the full key before writing. The resulting 20 bytes should match the contents of mame's .key file for the game/romset.
 
Thanks for answering friend, yes I know that the code I passed is from the infinity key, I just passed it as an example I know how it works. The doubt I have is regarding the decryption of mame that even using a 20 byte key to decrypt, in the logic of the cps2decrypt.ccp file it uses 64 bits that were supposed to be the last 8 bytes of the 20 byte key, but analyzing the script it does not use that value directly, it seems that a modification is made. So the doubt is whether in the mame decryption file it directly uses the last 8 bytes of the key or it takes these last 8 bytes, makes a modification and then uses them. And if it makes this modification, where does it do it.
 
The .keyfile does include more than the master key. Mame decodes the data before it's used for decryption.
If you want to see how the data looks decoded you can do the following from a command promt:

mame -cc (create mame.ini)
Open mame.ini with a text editor and change "log 0" to "log 1". ("CORE DEBUGGING OPTIONS")
run mame. (example: "mame 1944")
close mame after the game is started.

Look in your mame folder for a file called "error.log".
In error.log you will find the following from my example.

"[:] cps2 decrypt 0x3bf4e67a,0x9b5c70be,0x00000000,0x00100000"
This is the encryption keys and the memory range for the decryption.
And that's all that mame uses from the .key file.
 
Hello, I understand how mame uses the key file, it takes the 20 bytes of the key and converts it into the master key used in the decryption script. I still don't understand how it gets the data from the ROM, I adapted an external script to mame, I added logs, the logs are the same as mame, but the decrypted ROM is different from mame.
 
Not sure what your end goal is but the entire rom is not encrypted. sp+entry point and opcodes are encrypted while vectors and data are not. Plus the key defines an address range for what part of the rom can contain encrypted data. The hard part is that opcodes and data are intermixed within the rom so you have to know which is which to determine if it should be decrypted or not.

MAME decrypts the entire range specified by the key, including the data parts which aren't encrypted (which become garbled). This decrypted rom is fed into MAME's 68K CPU along with the original rom. MAME's 68k CPU has logic in it so when it needs to load an opcode it reads from the decrypted rom while data reads happen from the original rom.
 
Yes, if I dump in mame, for example, from the range of rom03, 0x0000 to 0x07FFF, everything is decrypted opcodes and data. This would not be the problem for me but rather trying to understand how mame applies the decryption script. In my script I adapted the entire decryption part of mame, including logs to compare the values with mame and they are the same, but the decrypted data is different from mame. for example, decrypting the data from address 0x0000 to 0x00C2 the data is different from mame with my script, even though the master key, FN1, FN2, expand key1, expand 1st key, expand 2nd key and subkey are the same as mame.
 
Is it possible its just wrong because its byte swapped? If you are decrypting the rom file, then writing out the decrypted rom, it will be byte swapped compared to what you see in mame's debugger.
 
Yes, mame reads in big endian and converts to little endian when saving the decrypted rom. But that's not the problem. The decrypted values are different. I believe my script is missing something that is not in cps2crypt.cpp.
 
You can see how your script compares to this.

https://www.mvs-scans.com/misc/cps2-crypt.cpp

Its code I wrote a while ago when I was looking into encrypting roms for a project I'm working on, but it also supports the full decryption like MAME does.

Code:
$ g++ cps2-crypt.cpp -o cps2-crypt
$ ./cps2-crypt -d -i mvca.03a -k mvsca.key -o decrypt.bin
Input ROM: mvca.03a
Key File: mvsca.key
Output ROM: decrypt.bin
f248aec6 7905cd17 0 100000
 
Last edited:
  • Like
Reactions: nem
Back
Top