diff options
Diffstat (limited to 'attic')
-rw-r--r-- | attic/fd1094dp.cpp | 589 | ||||
-rw-r--r-- | attic/fddebug.cpp | 2439 | ||||
-rw-r--r-- | attic/fddebug.h | 5 | ||||
-rw-r--r-- | attic/jalmah.x68 | 147 | ||||
-rw-r--r-- | attic/jrcrypt.cpp | 530 | ||||
-rw-r--r-- | attic/opwolf_cchip.txt | 1228 | ||||
-rw-r--r-- | attic/unkfr.cpp | 752 |
7 files changed, 5690 insertions, 0 deletions
diff --git a/attic/fd1094dp.cpp b/attic/fd1094dp.cpp new file mode 100644 index 00000000000..04c499390f1 --- /dev/null +++ b/attic/fd1094dp.cpp @@ -0,0 +1,589 @@ +// license:BSD-3-Clause +// copyright-holders:Charles MacDonald, Nicola Salmoria +/***************************************************************************** + +FD1094 key dumper + +This file is not part of MAME, it is a standalone program that reads 128MB of +data extracted from the FD1094 CPU and produces a 8KB keyfile, used by +fd1094.c to decrypt the ROM data. + +*****************************************************************************/ + + +#include <cstdio> +#include <cstring> +#include <cstdlib> + + +int state2; +char srcpath[250],dstfilename[250]; + +#define BIT(x,n) (((x)>>(n))&1) + +#define bitswap<16>(val,B15,B14,B13,B12,B11,B10,B9,B8,B7,B6,B5,B4,B3,B2,B1,B0) \ + ((BIT(val,B15) << 15) | \ + (BIT(val,B14) << 14) | \ + (BIT(val,B13) << 13) | \ + (BIT(val,B12) << 12) | \ + (BIT(val,B11) << 11) | \ + (BIT(val,B10) << 10) | \ + (BIT(val, B9) << 9) | \ + (BIT(val, B8) << 8) | \ + (BIT(val, B7) << 7) | \ + (BIT(val, B6) << 6) | \ + (BIT(val, B5) << 5) | \ + (BIT(val, B4) << 4) | \ + (BIT(val, B3) << 3) | \ + (BIT(val, B2) << 2) | \ + (BIT(val, B1) << 1) | \ + (BIT(val, B0) << 0)) + +uint16_t buffer[0x2000]; +int little_endian; + +int is_little_endian(void) +{ + short magic, test; + char *ptr; + + magic = 0xABCD; + ptr = (char *)&magic; + test = (ptr[1]<<8) + (ptr[0]&0xFF); + return (magic == test); +} + + + +void load_table(int n) +{ + static int last_loaded = -1; + + if (last_loaded != n) + { + FILE *f1; + int i; + char name[250]; + + + last_loaded = n; + + sprintf(name,"%s/00%04x.tbl",srcpath,n); + + f1 = fopen(name,"rb"); + if (!f1) + { + printf("Can't open %s for reading.\n",name); + exit(1); + } + + /* read repeatedly so we support both full dumps and reduced E000-FFFF dumps */ + while (fread(buffer,1,0x4000,f1) == 0x4000) ; + + fclose(f1); + + if (little_endian) + { + for (i = 0;i < 0x2000;i++) + buffer[i] = (buffer[i] >> 8) | (buffer[i] << 8); + } + } +} + + +/* +317-0162 CPU also needs to mask: +0x107a, +0x127a, +0x147a, +0x167a, +0x187a, +0x1a7a, +0x1c7a, +0x1e7a, +this only happens with 317-0162 so far; I assume it is a fault in the CPU. +*/ +int masked_opcodes[] = +{ + 0x013a,0x033a,0x053a,0x073a,0x083a,0x093a,0x0b3a,0x0d3a,0x0f3a, + + 0x103a, 0x10ba,0x10fa, 0x113a,0x117a,0x11ba,0x11fa, + 0x123a, 0x12ba,0x12fa, 0x133a,0x137a,0x13ba,0x13fa, + 0x143a, 0x14ba,0x14fa, 0x153a,0x157a,0x15ba, + 0x163a, 0x16ba,0x16fa, 0x173a,0x177a,0x17ba, + 0x183a, 0x18ba,0x18fa, 0x193a,0x197a,0x19ba, + 0x1a3a, 0x1aba,0x1afa, 0x1b3a,0x1b7a,0x1bba, + 0x1c3a, 0x1cba,0x1cfa, 0x1d3a,0x1d7a,0x1dba, + 0x1e3a, 0x1eba,0x1efa, 0x1f3a,0x1f7a,0x1fba, + + 0x203a,0x207a,0x20ba,0x20fa, 0x213a,0x217a,0x21ba,0x21fa, + 0x223a,0x227a,0x22ba,0x22fa, 0x233a,0x237a,0x23ba,0x23fa, + 0x243a,0x247a,0x24ba,0x24fa, 0x253a,0x257a,0x25ba, + 0x263a,0x267a,0x26ba,0x26fa, 0x273a,0x277a,0x27ba, + 0x283a,0x287a,0x28ba,0x28fa, 0x293a,0x297a,0x29ba, + 0x2a3a,0x2a7a,0x2aba,0x2afa, 0x2b3a,0x2b7a,0x2bba, + 0x2c3a,0x2c7a,0x2cba,0x2cfa, 0x2d3a,0x2d7a,0x2dba, + 0x2e3a,0x2e7a,0x2eba,0x2efa, 0x2f3a,0x2f7a,0x2fba, + + 0x303a,0x307a,0x30ba,0x30fa, 0x313a,0x317a,0x31ba,0x31fa, + 0x323a,0x327a,0x32ba,0x32fa, 0x333a,0x337a,0x33ba,0x33fa, + 0x343a,0x347a,0x34ba,0x34fa, 0x353a,0x357a,0x35ba, + 0x363a,0x367a,0x36ba,0x36fa, 0x373a,0x377a,0x37ba, + 0x383a,0x387a,0x38ba,0x38fa, 0x393a,0x397a,0x39ba, + 0x3a3a,0x3a7a,0x3aba,0x3afa, 0x3b3a,0x3b7a,0x3bba, + 0x3c3a,0x3c7a,0x3cba,0x3cfa, 0x3d3a,0x3d7a,0x3dba, + 0x3e3a,0x3e7a,0x3eba,0x3efa, 0x3f3a,0x3f7a,0x3fba, + + 0x41ba,0x43ba,0x44fa,0x45ba,0x46fa,0x47ba,0x49ba,0x4bba,0x4cba,0x4cfa,0x4dba,0x4fba, + + 0x803a,0x807a,0x80ba,0x80fa, 0x81fa, + 0x823a,0x827a,0x82ba,0x82fa, 0x83fa, + 0x843a,0x847a,0x84ba,0x84fa, 0x85fa, + 0x863a,0x867a,0x86ba,0x86fa, 0x87fa, + 0x883a,0x887a,0x88ba,0x88fa, 0x89fa, + 0x8a3a,0x8a7a,0x8aba,0x8afa, 0x8bfa, + 0x8c3a,0x8c7a,0x8cba,0x8cfa, 0x8dfa, + 0x8e3a,0x8e7a,0x8eba,0x8efa, 0x8ffa, + + 0x903a,0x907a,0x90ba,0x90fa, 0x91fa, + 0x923a,0x927a,0x92ba,0x92fa, 0x93fa, + 0x943a,0x947a,0x94ba,0x94fa, 0x95fa, + 0x963a,0x967a,0x96ba,0x96fa, 0x97fa, + 0x983a,0x987a,0x98ba,0x98fa, 0x99fa, + 0x9a3a,0x9a7a,0x9aba,0x9afa, 0x9bfa, + 0x9c3a,0x9c7a,0x9cba,0x9cfa, 0x9dfa, + 0x9e3a,0x9e7a,0x9eba,0x9efa, 0x9ffa, + + 0xb03a,0xb07a,0xb0ba,0xb0fa, 0xb1fa, + 0xb23a,0xb27a,0xb2ba,0xb2fa, 0xb3fa, + 0xb43a,0xb47a,0xb4ba,0xb4fa, 0xb5fa, + 0xb63a,0xb67a,0xb6ba,0xb6fa, 0xb7fa, + 0xb83a,0xb87a,0xb8ba,0xb8fa, 0xb9fa, + 0xba3a,0xba7a,0xbaba,0xbafa, 0xbbfa, + 0xbc3a,0xbc7a,0xbcba,0xbcfa, 0xbdfa, + 0xbe3a,0xbe7a,0xbeba,0xbefa, 0xbffa, + + 0xc03a,0xc07a,0xc0ba,0xc0fa, 0xc1fa, + 0xc23a,0xc27a,0xc2ba,0xc2fa, 0xc3fa, + 0xc43a,0xc47a,0xc4ba,0xc4fa, 0xc5fa, + 0xc63a,0xc67a,0xc6ba,0xc6fa, 0xc7fa, + 0xc83a,0xc87a,0xc8ba,0xc8fa, 0xc9fa, + 0xca3a,0xca7a,0xcaba,0xcafa, 0xcbfa, + 0xcc3a,0xcc7a,0xccba,0xccfa, 0xcdfa, + 0xce3a,0xce7a,0xceba,0xcefa, 0xcffa, + + 0xd03a,0xd07a,0xd0ba,0xd0fa, 0xd1fa, + 0xd23a,0xd27a,0xd2ba,0xd2fa, 0xd3fa, + 0xd43a,0xd47a,0xd4ba,0xd4fa, 0xd5fa, + 0xd63a,0xd67a,0xd6ba,0xd6fa, 0xd7fa, + 0xd83a,0xd87a,0xd8ba,0xd8fa, 0xd9fa, + 0xda3a,0xda7a,0xdaba,0xdafa, 0xdbfa, + 0xdc3a,0xdc7a,0xdcba,0xdcfa, 0xddfa, + 0xde3a,0xde7a,0xdeba,0xdefa, 0xdffa +}; + + +int final_decrypt(int i,int moreffff) +{ + int j; + + /* final "obfuscation": invert bits 7 and 14 following a fixed pattern */ + int dec = i; + if ((i & 0xf080) == 0x8000) dec ^= 0x0080; + if ((i & 0xf080) == 0xc080) dec ^= 0x0080; + if ((i & 0xb080) == 0x8000) dec ^= 0x4000; + if ((i & 0xb100) == 0x0000) dec ^= 0x4000; + + /* mask out opcodes doing PC-relative addressing, replace them with FFFF */ + for (j = 0;j < sizeof(masked_opcodes)/sizeof(masked_opcodes[0]);j++) + { + if ((dec & 0xfffe) == masked_opcodes[j]) + { + dec = 0xffff; + break; + } + } + + /* optionally, even more values can be replaced with FFFF */ + if (moreffff) + { + if ((dec & 0xff80) == 0x4e80) + dec = 0xffff; + if ((dec & 0xf0f8) == 0x50c8) + dec = 0xffff; + if ((dec & 0xf000) == 0x6000) + dec = 0xffff; + } + + return dec; +} + + +static int parametric_decode(int val,int mainkey,int key_F,int gkey1,int gkey2,int gkey3) +{ + int key_6a,key_7a,key_6b; + int key_0a,key_0b,key_0c; + int key_1a,key_1b,key_2a,key_2b,key_3a,key_3b,key_4a,key_4b,key_5a,key_5b; + int global_xor0,global_xor1; + int global_swap0a,global_swap1,global_swap2,global_swap3,global_swap4; + int global_swap0b; + + global_xor0 = 1^BIT(gkey1,5); // could be bit 7 + global_xor1 = 1^BIT(gkey1,2); + global_swap2 = 1^BIT(gkey1,0); + + global_swap0a = 1^BIT(gkey2,5); + global_swap0b = 1^BIT(gkey2,2); + + global_swap3 = 1^BIT(gkey3,6); + global_swap1 = 1^BIT(gkey3,4); + global_swap4 = 1^BIT(gkey3,2); + + key_0a = BIT(mainkey,0) ^ BIT(gkey3,1); + key_0b = BIT(mainkey,0) ^ BIT(gkey1,7); // could be bit 5 + key_0c = BIT(mainkey,0) ^ BIT(gkey1,1); + + key_1a = BIT(mainkey,1) ^ BIT(gkey2,7); + key_1b = BIT(mainkey,1) ^ BIT(gkey1,3); + + key_2a = BIT(mainkey,2) ^ BIT(gkey3,7); // could be bit 5 + key_2b = BIT(mainkey,2) ^ BIT(gkey1,4); + + key_3a = BIT(mainkey,3) ^ BIT(gkey2,0); + key_3b = BIT(mainkey,3) ^ BIT(gkey3,3); + + key_4a = BIT(mainkey,4) ^ BIT(gkey2,3); + key_4b = BIT(mainkey,4) ^ BIT(gkey3,0); + + key_5a = BIT(mainkey,5) ^ BIT(gkey3,5); // could be bit 7 + key_5b = BIT(mainkey,5) ^ BIT(gkey1,6); + + key_6a = BIT(mainkey,6) ^ BIT(gkey2,1); + key_6b = BIT(mainkey,6) ^ BIT(gkey2,6); + + key_7a = BIT(mainkey,7) ^ BIT(gkey2,4); + + + if ((val & 0xe000) == 0x0000) + val = bitswap<16>(val, 12,15,14,13,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); + else + { + if (val & 0x8000) + { + if (!global_xor1) if (~val & 0x0008) val ^= 0x2410; // 13,10,4 + if (~val & 0x0004) val ^= 0x0022; // 5,1 + if (!key_1b) if (~val & 0x1000) val ^= 0x0848; // 11,6,3 + if (!global_swap2) if (!key_0c) val ^= 0x4101; // 14,8,0 + if (!key_2b) val = bitswap<16>(val, 15,14,13, 9,11,10,12, 8, 2, 6, 5, 4, 3, 7, 1, 0); // 12,9,7,2 + + val = 0x6561 ^ bitswap<16>(val, 15, 9,10,13, 3,12, 0,14, 6, 5, 2,11, 8, 1, 4, 7); + } + if (val & 0x4000) + { + if (!global_xor0) if (val & 0x0800) val ^= 0x9048; // 15,12,6,3 + if (!key_3a) if (val & 0x0004) val ^= 0x0202; // 9,1 + if (!key_6a) if (val & 0x0400) val ^= 0x0004; // 2 + if (!key_5b) if (!key_0b) val ^= 0x08a1; // 11,7,5,0 + if (!global_swap0b) val = bitswap<16>(val, 15,14,10,12,11,13, 9, 4, 7, 6, 5, 8, 3, 2, 1, 0); // 13,10,8,4 + + val = 0x3523 ^ bitswap<16>(val, 13,14, 7, 0, 8, 6, 4, 2, 1,15, 3,11,12,10, 5, 9); + } + if (val & 0x2000) + { + if (!key_4a) if (val & 0x0100) val ^= 0x4210; // 14,9,4 + if (!key_1a) if (val & 0x0040) val ^= 0x0080; // 7 + if (!key_7a) if (val & 0x0001) val ^= 0x110a; // 12,8,3,1 + if (!key_4b) if (!key_0a) val ^= 0x0040; // 6 + if (!global_swap0a) if (!key_6b) val ^= 0x0404; // 10,2 + if (!key_5b) val = bitswap<16>(val, 0,14,13,12,15,10, 9, 8, 7, 6,11, 4, 3, 2, 1, 5); // 15,11,5,0 + + val = 0x99a5 ^ bitswap<16>(val, 10, 2,13, 7, 8, 0, 3,14, 6,15, 1,11, 9, 4, 5,12); + } + + val = 0x87ff ^ bitswap<16>(val, 5,15,13,14, 6, 0, 9,10, 4,11, 1, 2,12, 3, 7, 8); + + if (!global_swap4) val = bitswap<16>(val, 6,14,13,12,11,10, 9, 5, 7,15, 8, 4, 3, 2, 1, 0); // 15-6, 8-5 + if (!global_swap3) val = bitswap<16>(val, 15,12,14,13,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); // 12-13-14 + if (!global_swap2) val = bitswap<16>(val, 15,14,13,12,11, 2, 9, 8,10, 6, 5, 4, 3, 0, 1, 7); // 10-2-0-7 + if (!key_3b) val = bitswap<16>(val, 15,14,13,12,11,10, 4, 8, 7, 6, 5, 9, 1, 2, 3, 0); // 9-4, 3-1 + + if (!key_2a) val = bitswap<16>(val, 15,12,13,14,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); // 14-12 + if (!global_swap1) val = bitswap<16>(val, 15,14,13,12, 9, 8,11,10, 7, 6, 5, 4, 3, 2, 1, 0); // 11...8 + if (!key_5a) val = bitswap<16>(val, 15,14,13,12,11,10, 9, 8, 4, 5, 7, 6, 3, 2, 1, 0); // 7...4 + if (!global_swap0a) val = bitswap<16>(val, 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 0, 3, 2, 1); // 3...0 + } + + return final_decrypt(val,key_F); +} + + + +int check_key(int key,int key_F,int gkey1,int gkey2,int gkey3) +{ + int i; + int err_ffff = 0; + + if (state2) + { + gkey1 ^= 0x01; + gkey2 ^= 0x10; + gkey3 ^= 0x01; + } + + for (i = 0xffff;i >= 0xe000;i--) + { + if (parametric_decode(i,key,key_F,gkey1,gkey2,gkey3) != buffer[i - 0xe000]) + { + if (buffer[i - 0xe000] == 0xffff) + { + err_ffff++; + if (err_ffff > 8) break; + } + else + break; + } + } + + if (i < 0xe000) + { + /* special handling for CPU 317-0162 */ + if (err_ffff) + { + printf("warning: %d FFFF errors: ",err_ffff); + for (i = 0xe000;i < 0x10000;i++) + { + if (parametric_decode(i,key,key_F,gkey1,gkey2,gkey3) != buffer[i - 0xe000]) + printf("%04x ",parametric_decode(i,key,key_F,gkey1,gkey2,gkey3)); + } + printf("\n"); + } + return 1; + } + else + return 0; +} + + +static void print_binary(int num) +{ + int i; + + for (i = 7;i >= 0;i--) + printf("%d",BIT(num,i)); +} + + +static int global_key1,global_key2,global_key3; + + +void find_global_key(void) +{ + int gkey1,gkey2,gkey3; + int found = 0; + + printf("Searching for global key...\n"); + + for (gkey1 = 0;gkey1 < 0x100;gkey1++) + { + fprintf(stderr,"%02x/ff\r",gkey1); + for (gkey2 = 0;gkey2 < 0x100;gkey2++) + { + for (gkey3 = 0;gkey3 < 0x100;gkey3++) + { + load_table(2); + if (check_key(gkey1,BIT(gkey1,6),gkey1,gkey2,gkey3)) + { + load_table(4); + if (check_key(gkey2,BIT(gkey2,6),gkey1,gkey2,gkey3)) + { + load_table(6); + if (check_key(gkey3,BIT(gkey3,6),gkey1,gkey2,gkey3)) + { + global_key1 = gkey1; + global_key2 = gkey2; + global_key3 = gkey3; + + printf("global key: "); + print_binary(gkey1); + printf(" "); + print_binary(gkey2); + printf(" "); + print_binary(gkey3); + printf("\n"); + + found++; + } + } + } + } + } + } + + if (found > 1) + { + printf("The tables from state %02x don't allow to uniquely determine the global key.\n",state2*2); + printf("You should dump tables from state %02x and run the program again.\n",(state2^1)*2); + exit(0); + } + + if (found == 0) + { + int key1,key2,key3; + + printf("Couldn't find the global key. This might be caused by:\n"); + printf("1) Incorrectly dumped data\n"); + printf("2) Wrong <state> parameter. 00 instead of 02, or 02 instead of 00.\n"); + printf("3) An error in the current FD1094 emulation.\n\n"); + + printf("I will now execute a broader key search, which will take a longer time.\n"); + printf("If 1) and 2) are correct, and this search succeeds, contact MAMEDEV.\n"); + + for (gkey1 = 0;gkey1 < 0x100;gkey1++) + { + fprintf(stderr,"%02x/ff\r",gkey1); + for (gkey2 = 0;gkey2 < 0x100;gkey2++) + { + for (gkey3 = 0;gkey3 < 0x100;gkey3++) + { + load_table(2); + for (key1 = gkey1 & 0x5f;key1 < 0x100;key1 += 0x20) + { + if (check_key(key1,BIT(key1,6),gkey1,gkey2,gkey3) || check_key(key1,BIT(key1,6)^1,gkey1,gkey2,gkey3)) + { + load_table(4); + key2 = gkey2; + { + if (check_key(key2,BIT(key2,6),gkey1,gkey2,gkey3) || check_key(key2,BIT(key2,6)^1,gkey1,gkey2,gkey3)) + { + load_table(6); + for (key3 = gkey3 & 0x5f;key3 < 0x100;key3 += 0x20) + { + if (check_key(key3,BIT(key3,6),gkey1,gkey2,gkey3) || check_key(key3,BIT(key3,6)^1,gkey1,gkey2,gkey3)) + { + printf("key: "); + print_binary(key1); + printf(" "); + print_binary(key2); + printf(" "); + print_binary(key3); + printf(" "); + printf("global key: "); + print_binary(gkey1); + printf(" "); + print_binary(gkey2); + printf(" "); + print_binary(gkey3); + printf("\n"); + } + } + } + } + } + } + } + } + } + + exit(0); + } +} + + +uint8_t mainkey[0x2000]; + +void find_main_key(void) +{ + int n,key,keyF,allfound = 0,found; + + printf("Searching for main key...\n"); + + for (n = 0;n < 0x2000;n++) + { + if (n % 16 == 0) fprintf(stderr,"%03x/1ff\r",n/16); + load_table(n*2); + found = 0; + for (key = 0;key < 0x100;key++) + { + if (n & 0x1000) keyF = BIT(key,7); + else keyF = BIT(key,6); + + if (check_key(key,keyF,global_key1,global_key2,global_key3)) + { + mainkey[n] = key; + found++; + } + } + + if (found == 0) + printf("00%04x.tbl: can't decrypt\n",n*2); + else if (found == 1) + allfound++; + else if (found > 1) + { + printf("00%04x.tbl: ambiguous key\n",n*2); + printf("The tables from state %02x don't allow to uniquely determine the main key.\n",state2*2); + printf("You should dump tables from state %02x and run the program again.\n",(state2^1)*2); + exit(0); + } + } + + if (allfound != 0x2000) + { + printf("The tables listed above are probably bad dumps.\n"); + printf("You should try redumping them and run the program again.\n"); + exit(0); + } + + printf("Key generation succeeded!\n"); +} + +void save_main_key() +{ + FILE *f1; + f1 = fopen(dstfilename,"wb"); + if (!f1) + { + printf("Can't open %s for writing.\n",dstfilename); + exit(1); + } + if (fwrite(mainkey,1,0x2000,f1) == 0x2000) + printf("Key saved in current directory as %s.\n",dstfilename); + else + printf("Error saving key.\n"); + + fclose(f1); +} + + +int main(int argc,char **argv) +{ + if (argc != 4 || (strcmp(argv[2],"00") && strcmp(argv[2],"02"))) + { + printf("Usage: %s <path> <state> <CPU name>\n\n",argv[0]); + printf("<path>: path to the directory holding the tables\n"); + printf(" files must be called 000000.tbl, 000002.tbl ... 003FFE.tbl\n"); + printf("<state>: must be 00 or 02 - CPU state in which the tables were extracted\n"); + printf("<CPU name>: part name of the CPU\n"); + printf("\nExample: %s c:/dumps/0053-0000 00 317-0053\n",argv[0]); + return 0; + } + + sprintf(srcpath,argv[1]); + if (strcmp(argv[2],"02") == 0) + state2 = 1; + else + state2 = 0; + sprintf(dstfilename,"%s.key",argv[3]); + + printf("reading tables from %s\n",srcpath); + printf("tables were read from the CPU in state %s\n",state2 ? "02" : "00"); + printf("output file will be %s\n\n",dstfilename); + + little_endian = is_little_endian(); + + find_global_key(); + find_main_key(); + save_main_key(); + + return 0; +} diff --git a/attic/fddebug.cpp b/attic/fddebug.cpp new file mode 100644 index 00000000000..74deb2af167 --- /dev/null +++ b/attic/fddebug.cpp @@ -0,0 +1,2439 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles + +#include <functional> + +#include "emu.h" +#include "machine/fddebug.h" + +void fd1094_init_debugging(running_machine &machine, const char *cpureg, const char *keyreg, const char *statreg, void (*changed)(running_machine &)) +{ +} + +#if 0 + +/*************************************************************************** + + fddebug.c + + FD1094 decryption helper routines. + +**************************************************************************** + + When searching for new keys, here are some common sequences in the + System 16B games that are useful. + + IRQ4 handler entry points: + + common sequence 1: + MOVE SR,(A7) 40D7 + MOVE.B #$23,(A7) 1EBC 0023 + MOVEM.L D0-D7/A0-A6,-(A7) 48E7 FFFE + + common sequence 2: + MOVEM.L D0-D7/A0-A6,-(A7) 48E7 FFFE + + common sequence 3: + BRA.W <previous sequence> 6000 xxxx + + IRQ4 handler exit points: + + common sequence (often appears twice nearby): + MOVE (A7)+,D0-D7/A0-A6 4CDF 7FFF + RTE 4E73 + + Entry points: + + common sequence 1: + LEA <stack>.L,A7 4FF9 xxxx xxxx + MOVE #$2700,SR 46FC 2700 + CMPI.L #$00xxffff,D0 0C80 00xx FFFF + MOVEQ #0,D0 + MOVE.L D0,D1 2200 + MOVE.L D0,D2 2400 + MOVE.L D0,D3 2600 + MOVE.L D0,D4 2800 + MOVE.L D0,D5 2A00 + MOVE.L D0,D6 2C00 + MOVE.L D0,D7 2E00 + + common sequence 2: + LEA <stack>.W,A7 4FF8 xxxx + MOVE #$2700,SR 46FC 2700 + CMPI.L #$00xxffff,D0 0C80 00xx FFFF + MOVEQ #0,D0 + MOVE.L D0,D1 2200 + MOVE.L D0,D2 2400 + MOVE.L D0,D3 2600 + MOVE.L D0,D4 2800 + MOVE.L D0,D5 2A00 + MOVE.L D0,D6 2C00 + MOVE.L D0,D7 2E00 + + common sequence 3: + LEA <stack>.W,A7 4FF8 xxxx + MOVE #$2700,SR 46FC 2700 + MOVEQ #0,D0 + MOVE.L D0,D1 2200 + MOVE.L D0,D2 2400 + MOVE.L D0,D3 2600 + MOVE.L D0,D4 2800 + MOVE.L D0,D5 2A00 + MOVE.L D0,D6 2C00 + MOVE.L D0,D7 2E00 + + common sequence 4: + BRA.W <previous sequence> 6000 xxxx + +**************************************************************************** + + These constraints worked for finding exctleag's seed: + + fdcset 0410,4ff9 + fdcset 0412,0000 + fdcset 0414,0000 + fdcset 0416,46fc + fdcset 0418,2700 + fdcset 041a,0c80 + fdcset 041c,0000,ff00 + fdcset 041e,ffff + + //fdcset 0f9e,40d7,ffff,irq + fdcset 0fa0,1ebc,ffff,irq + fdcset 0fa2,0023,ffff,irq + //fdcset 0fa4,48e7,ffff,irq + fdcset 0fa6,fffe,ffff,irq + fdcset 0fa8,13f8,ffff,irq + fdcset 0fac,00c4,ffff,irq + fdcset 0fae,0001,ffff,irq + + //fdcset 1060,4cdf,ffff,irq + fdcset 1062,7fff,ffff,irq + //fdcset 1064,4e73,ffff,irq + //fdcset 1070,4cdf,ffff,irq + fdcset 1072,7fff,ffff,irq + //fdcset 1074,4e73,ffff,irq + +**************************************************************************** + + Add something like this to debug_view_memory::write + + // hack for FD1094 editing + #ifdef FD1094_HACK + if (source.m_base == machine().root_device().memregion("user2")) + { + extern void fd1094_regenerate_key(running_machine &machine); + fd1094_regenerate_key(machine()); + } + #endif + +***************************************************************************/ + +#include "emu.h" +#include "machine/fd1094.h" +#include "cpu/m68000/m68000.h" + +#include "debug/debugcmd.h" +#include "debug/debugcon.h" +#include "debug/debugcpu.h" +#include "debug/debugvw.h" +#include "machine/fddebug.h" + + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define KEY_SIZE 8192 +#define MAX_CONSTRAINTS 100 +#define MAX_SEARCH_DEPTH 10000 + +/* status byte breakdown */ +#define STATE_MASK 0xff00 +#define HIBITS_MASK 0x00c0 +#define SEARCH_MASK 0x0020 +#define STATUS_MASK 0x001f + +/* possible status values */ +#define STATUS_UNVISITED 0x00 +#define STATUS_LOCKED 0x01 +#define STATUS_NOCHANGE 0x02 +#define STATUS_GUESS 0x03 + +/* sizes for the opcode table */ +#define SIZE_BYTE 1 /* single byte */ +#define SIZE_WORD 2 /* single word */ +#define SIZE_LONG 3 /* single long */ +#define SIZE_BIT 4 /* single byte, limited to bit sizes (0-7) */ +#define SIZE_MASK 7 + +/* operand sizes */ +#define OF_SIZEMASK (SIZE_MASK << 0) +#define OF_BYTE (SIZE_BYTE << 0) /* byte size operation */ +#define OF_WORD (SIZE_WORD << 0) /* word size operation */ +#define OF_LONG (SIZE_LONG << 0) /* long size operation */ + +/* immediate sizes */ +#define OF_ISIZEMASK (SIZE_MASK << 3) +#define OF_IMMB (SIZE_BYTE << 3) /* immediate byte follows */ +#define OF_IMMW (SIZE_WORD << 3) /* immediate word follows */ +#define OF_IMML (SIZE_LONG << 3) /* immediate long follows */ +#define OF_IMMBIT (SIZE_BIT << 3) /* immediate byte follows */ + +/* other opcode flags */ +#define OF_EASRC 0x00000040 /* standard EA is source */ +#define OF_EADST 0x00000080 /* standard EA is destination */ +#define OF_EADREG 0x00000100 /* EA with data register is allowed */ +#define OF_EAAREG 0x00000200 /* EA with address register is allowed */ +#define OF_EAA 0x00000400 /* EA with (An) is allowed */ +#define OF_EAPLUS 0x00000800 /* EA with (An)+ is allowed */ +#define OF_EAMINUS 0x00001000 /* EA with -(An) is allowed */ +#define OF_EADISP 0x00002000 /* EA with (D,An) displacement is allowed */ +#define OF_EAABS 0x00004000 /* EA with absolute (both word and long) is allowed */ +#define OF_EAIMM 0x00008000 /* EA with immediate is allowed */ +#define OF_EAPCR 0x00010000 /* EA with PC-relative addressing is allowed */ +#define OF_RARE 0x00080000 /* opcode is not commonly used */ +#define OF_BRANCH 0x00100000 /* opcode represents a branch */ +#define OF_JMP 0x00200000 /* opcode represents a jmp/jsr */ +#define OF_MOVE 0x00400000 /* opcode has MOVE semantics */ +#define OF_LENMASK 0xf0000000 /* opcode length mask */ +#define OF_INVALID 0xffffffff /* invalid opcode */ + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* a single possible instruction decoding */ +struct fd1094_possibility +{ + offs_t basepc; /* starting PC of the possibility */ + int length; /* number of words */ + uint8_t instrbuffer[10]; /* instruction data for disassembler */ + uint8_t keybuffer[10]; /* array of key values to produce the instruction data */ + uint8_t iffy; /* is this an iffy possibility? */ + char dasm[256]; /* disassembly */ +}; + +/* an entry in the opcode table */ +struct optable_entry +{ + uint32_t flags; /* per-opcode flags */ + const char * string; /* identifying string */ +}; + + + +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ + +/* array of PCs not to stop at */ +static uint8_t * ignorepc; +static uint8_t ignore_all; + +/* array of information about each opcode */ +static std::unique_ptr<optable_entry[]> optable; + +/* buffer for undoing operations */ +static uint8_t * undobuff; + +/* array of possible instruction decodings */ +static fd1094_possibility posslist[4*4*4*4*4]; +static int posscount; + +/* array of possible seeds */ +static uint32_t * possible_seed; + +/* array of constraints */ +static fd1094_constraint constraints[MAX_CONSTRAINTS]; +static int constcount; + +/* stack of search addresses */ +static uint32_t searchstack[MAX_SEARCH_DEPTH]; +static int searchsp; + +/* current key generation parameters */ +static uint32_t fd1094_global; +static uint32_t fd1094_seed; +static uint8_t keydirty; + +/* pointers to our data */ +static uint16_t * coderegion; +static uint32_t coderegion_words; +static uint8_t * keyregion; +static uint16_t * keystatus; +static uint32_t keystatus_words; + +/* key changed callback */ +static void (*key_changed)(running_machine &); + + + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +static void set_default_key_params(running_machine &machine); +static void load_overlay_file(running_machine &machine); +static void save_overlay_file(running_machine &machine); + +static int instruction_hook(device_t &device, offs_t curpc); + +static void execute_fdsave(running_machine &machine, int ref, int params, const char **param); +static void execute_fdoutput(running_machine &machine, int ref, int params, const char **param); +static void execute_fdseed(running_machine &machine, int ref, int params, const char **param); +static void execute_fdlockguess(running_machine &machine, int ref, int params, const char **param); +static void execute_fdeliminate(running_machine &machine, int ref, int params, const char **param); +static void execute_fdunlock(running_machine &machine, int ref, int params, const char **param); +static void execute_fdignore(running_machine &machine, int ref, int params, const char **param); +static void execute_fdundo(running_machine &machine, int ref, int params, const char **param); +static void execute_fdstatus(running_machine &machine, int ref, int params, const char **param); +static void execute_fdstate(running_machine &machine, int ref, int params, const char **param); +static void execute_fdpc(running_machine &machine, int ref, int params, const char **param); +static void execute_fdsearch(running_machine &machine, int ref, int params, const char **param); +static void execute_fddasm(running_machine &machine, int ref, int params, const char **param); +static void execute_fdcset(running_machine &machine, int ref, int params, const char **param); +static void execute_fdclist(running_machine &machine, int ref, int params, const char **param); +static void execute_fdcsearch(running_machine &machine, int ref, int params, const char **param); + +static fd1094_possibility *try_all_possibilities(address_space &space, int basepc, int offset, int length, uint8_t *instrbuffer, uint8_t *keybuffer, fd1094_possibility *possdata); +static void tag_possibility(running_machine &machine, fd1094_possibility *possdata, uint8_t status); + +static void perform_constrained_search(running_machine &machine); +static uint32_t find_global_key_matches(uint32_t startwith, uint16_t *output); +static int find_constraint_sequence(uint32_t global, int quick); +static int does_key_work_for_constraints(const uint16_t *base, uint8_t *key); +static uint32_t reconstruct_base_seed(int keybaseaddr, uint32_t startseed); + +static void build_optable(running_machine &machine); +static int validate_ea(address_space &space, uint32_t pc, uint8_t modereg, const uint8_t *parambase, uint32_t flags); +static int validate_opcode(address_space &space, uint32_t pc, const uint8_t *opdata, int maxwords); + + + + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +/*----------------------------------------------- + addr_to_keyaddr - given an address, + return the address in the key that will be + used to decrypt it +-----------------------------------------------*/ + +static inline int addr_to_keyaddr(offs_t address) +{ + /* for address xx0000-xx0006 (but only if >= 000008), use key xx2000-xx2006 */ + if ((address & 0x0ffc) == 0 && address >= 4) + return (address & 0x1fff) | 0x1000; + else + return address & 0x1fff; +} + + +/*----------------------------------------------- + mask_for_keyaddr - given a key address, + return a mask indicating which bits should + always be 1 +-----------------------------------------------*/ + +static inline uint8_t mask_for_keyaddr(offs_t address) +{ + /* the first half of the key always has bit 0x80 set; the second half 0x40 */ + /* however, the values at 0000-0003 and 1000-1003 don't follow this rule */ + if ((address & 0x0ffc) == 0) + return 0x00; + else if ((address & 0x1000) == 0) + return 0x80; + else + return 0x40; +} + + +/*----------------------------------------------- + advance_seed - advance the PRNG seed by + the specified number of steps +-----------------------------------------------*/ + +static inline uint32_t advance_seed(uint32_t seed, int count) +{ + /* iterate over the seed for 'count' reps */ + while (count--) + { + seed = seed * 0x29; + seed += seed << 16; + } + return seed; +} + + +/*----------------------------------------------- + key_value_from_seed - extract the key value + from a seed and apply the given mask +-----------------------------------------------*/ + +static inline uint8_t key_value_from_seed(uint32_t seed, uint8_t mask) +{ + /* put bits 16-21 of the seed in the low 6 bits and OR with the mask */ + return ((~seed >> 16) & 0x3f) | mask; +} + + +/*----------------------------------------------- + generate_key_bytes - generate a sequence of + consecutive key bytes, starting with the + given seed +-----------------------------------------------*/ + +static inline void generate_key_bytes(uint8_t *dest, uint32_t keyoffs, uint32_t count, uint32_t seed) +{ + int bytenum; + + /* generate 'count' bytes of a key */ + for (bytenum = 0; bytenum < count; bytenum++) + { + uint32_t keyaddr = (keyoffs + bytenum) & 0x1fff; + uint8_t mask = mask_for_keyaddr(keyaddr); + + /* advance the seed first, then store the derived value */ + seed = advance_seed(seed, 1); + dest[keyaddr] = key_value_from_seed(seed, mask); + } +} + + +/*----------------------------------------------- + get_opcode_length - return the length of + an opcode based on the opcode +-----------------------------------------------*/ + +static inline uint8_t get_opcode_length(uint16_t opcode) +{ + /* return the length from the table */ + return optable[opcode].flags >> 28; +} + + +/*----------------------------------------------- + set_constraint - set the values of a + constraint +-----------------------------------------------*/ + +static inline void set_constraint(fd1094_constraint *constraint, uint32_t pc, uint16_t state, uint16_t value, uint16_t mask) +{ + constraint->pc = pc; + constraint->state = state; + constraint->value = value & mask; + constraint->mask = mask; +} + +/*----------------------------------------------- + print_possibilities - print possibilities + for a given address +-----------------------------------------------*/ + +static inline void print_possibilities(running_machine &machine) +{ + machine.debugger().console().printf("Possibilities @ %06X:\n", posslist[0].basepc); + for (int i = 0; i < posscount; i++) + machine.debugger().console().printf(" %c%2x: %s\n", posslist[i].iffy ? ' ' : '*', i, posslist[i].dasm); +} + + +/*----------------------------------------------- + pc_is_valid - is a given PC value valid? + 0=no, 1=yes, 2=unlikely +-----------------------------------------------*/ + +static inline int pc_is_valid(address_space &space, uint32_t pc, uint32_t flags) +{ + /* if we're odd or out of range, fail */ + if ((pc & 1) == 1) + return 0; + if (pc & 0xff000000) + return 0; + if (space.direct().read_ptr(pc) == nullptr) + return 0; + return 1; +} + + +/*----------------------------------------------- + addr_is_valid - is a given address value + valid? 0=no, 1=yes, 2=unlikely +-----------------------------------------------*/ + +static inline int addr_is_valid(address_space &space, uint32_t addr, uint32_t flags) +{ + /* if this a JMP, the address is a PC */ + if (flags & OF_JMP) + return pc_is_valid(space, addr, flags); + + /* if we're odd or out of range, fail */ + if ((flags & OF_SIZEMASK) != OF_BYTE && (addr & 1) == 1) + return 0; + if ((addr & 0xff000000) != 0 && (addr & 0xff000000) != 0xff000000) + return 0; + + /* if we're invalid, fail */ + if (strcmp(const_cast<address_space &>(space)->get_handler_string(read_or_write::READ, addr), "segaic16_memory_mapper_lsb_r") == 0) + return 2; + + return 1; +} + + + +/*************************************************************************** + CORE IMPLEMENTATION +***************************************************************************/ + +/*----------------------------------------------- + fd1094_init_debugging - set up debugging +-----------------------------------------------*/ + +void fd1094_init_debugging(running_machine &machine, const char *cpureg, const char *keyreg, const char *statreg, void (*changed)(running_machine &)) +{ + /* set the key changed callback */ + key_changed = changed; + + /* set up the regions */ + coderegion = (uint16_t *)machine.root_device().memregion(cpureg)->base(); + coderegion_words = machine.root_device().memregion(cpureg)->bytes() / 2; + keyregion = (uint8_t *)machine.root_device().memregion(keyreg)->base(); + keystatus = (uint16_t *)machine.root_device().memregion(statreg)->base(); + keystatus_words = machine.root_device().memregion(statreg)->bytes() / 2; + assert(coderegion_words == keystatus_words); + + /* allocate memory for the ignore table */ + ignorepc = make_unique_clear<uint8_t>(1 << 23); + + /* allocate memory for the undo buffer */ + undobuff = std::make_unique<uint8_t[]>(keystatus_words * 2); + memcpy(undobuff, keystatus, keystatus_words * 2); + + /* allocate memory for the possible seeds array */ + possible_seed = std::make_unique<uint32_t[]>(65536); + + /* build the opcode table */ + build_optable(machine); + + /* set up default constraints */ + constcount = 0; + set_constraint(&constraints[constcount++], 0x000000, FD1094_STATE_RESET, 0x0000, 0xffff); + set_constraint(&constraints[constcount++], 0x000002, FD1094_STATE_RESET, 0x0000, 0xffff); + set_constraint(&constraints[constcount++], 0x000004, FD1094_STATE_RESET, 0x0000, 0xffff); + set_constraint(&constraints[constcount++], 0x000006, FD1094_STATE_RESET, 0x0000, 0xc001); + + /* determine the key parameters */ + set_default_key_params(machine); + + /* read the key overlay file */ + load_overlay_file(machine); + + /* add some commands */ + using namespace std::placeholder; + machine.debugger().console().register_command("fdsave", CMDFLAG_NONE, 0, 0, 0, std::bind(&execute_fdsave, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdoutput", CMDFLAG_NONE, 0, 1, 1, std::bind(&execute_fdoutput, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdseed", CMDFLAG_NONE, 0, 2, 2, std::bind(&execute_fdseed, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdguess", CMDFLAG_NONE, STATUS_GUESS, 1, 1, std::bind(&execute_fdlockguess, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdlock", CMDFLAG_NONE, STATUS_LOCKED, 1, 1, std::bind(&execute_fdlockguess, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdeliminate", CMDFLAG_NONE, 0, 1, 10, std::bind(&execute_fdeliminate, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdunlock", CMDFLAG_NONE, 0, 1, 1, std::bind(&execute_fdunlock, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdignore", CMDFLAG_NONE, 0, 0, 1, std::bind(&execute_fdignore, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdundo", CMDFLAG_NONE, 0, 0, 0, std::bind(&execute_fdundo, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdstatus", CMDFLAG_NONE, 0, 0, 0, std::bind(&execute_fdstatus, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdstate", CMDFLAG_NONE, 0, 0, 1, std::bind(&execute_fdstate, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdpc", CMDFLAG_NONE, 0, 0, 1, std::bind(&execute_fdpc, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdsearch", CMDFLAG_NONE, 0, 0, 0, std::bind(&execute_fdsearch, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fddasm", CMDFLAG_NONE, 0, 1, 1, std::bind(&execute_fddasm, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdcset", CMDFLAG_NONE, 0, 2, 4, std::bind(&execute_fdcset, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdclist", CMDFLAG_NONE, 0, 0, 0, std::bind(&execute_fdclist, std::ref(machine), _1, _2, _3)); + machine.debugger().console().register_command("fdcsearch", CMDFLAG_NONE, 0, 0, 0, std::bind(&execute_fdcsearch, std::ref(machine), _1, _2, _3)); + + /* set up the instruction hook */ + machine.device("maincpu")->debug()->set_instruction_hook(instruction_hook); + + /* regenerate the key */ + if (keydirty) + fd1094_regenerate_key(machine); +} + + +/*----------------------------------------------- + set_default_key_params - based on the game + name, set some defaults +-----------------------------------------------*/ + +static void set_default_key_params(running_machine &machine) +{ + static const struct + { + const char * gamename; + uint32_t global; + uint32_t seed; + } default_keys[] = + { + { "altbeastj1", 0xFCAFF9F9, 0x177AC6 }, + { "bullet", 0x12A8F9EC, 0x1B1FC3 }, + }; + int keynum; + + /* look for a matching game and set the key appropriately */ + for (keynum = 0; keynum < std::size(default_keys); keynum++) + if (strcmp(machine.system().name, default_keys[keynum].gamename) == 0) + { + fd1094_global = default_keys[keynum].global; + fd1094_seed = default_keys[keynum].seed; + keydirty = true; + break; + } +} + + +/*----------------------------------------------- + load_overlay_file - load the key overlay + file +-----------------------------------------------*/ + +static void load_overlay_file(running_machine &machine) +{ + int pcaddr; + + /* determine the filename and open the file */ + emu_file file(OPEN_FLAG_READ); + osd_file::error filerr = file.open(machine.system().name, ".kov"); + if (filerr == osd_file::error::NONE) + { + file.read(keystatus, keystatus_words * 2); + + /* convert from big-endian */ + for (pcaddr = 0; pcaddr < keystatus_words; pcaddr++) + keystatus[pcaddr] = big_endianize_int16(keystatus[pcaddr]) & ~SEARCH_MASK; + } + + /* mark the key dirty */ + keydirty = true; +} + + +/*----------------------------------------------- + save_overlay_file - save the key overlay + file +-----------------------------------------------*/ + +static void save_overlay_file(running_machine &machine) +{ + int pcaddr; + + /* determin the filename and open the file */ + emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + osd_file::error filerr = file.open(machine.system().name, ".kov"); + if (filerr == osd_file::error::NONE) + { + /* convert to big-endian */ + for (pcaddr = 0; pcaddr < keystatus_words; pcaddr++) + keystatus[pcaddr] = big_endianize_int16(keystatus[pcaddr]); + + /* write the data */ + file.write(keystatus, keystatus_words * 2); + + /* convert from big-endian */ + for (pcaddr = 0; pcaddr < keystatus_words; pcaddr++) + keystatus[pcaddr] = big_endianize_int16(keystatus[pcaddr]); + } +} + + +/*----------------------------------------------- + fd1094_regenerate_key - regenerate the key + based on the raw parameters and the overlay + data +-----------------------------------------------*/ + +void fd1094_regenerate_key(running_machine &machine) +{ + int reps = keystatus_words / KEY_SIZE; + int keyaddr, repnum; + + /* store the global key in the first 4 bytes */ + keyregion[0] = fd1094_global >> 24; + keyregion[1] = fd1094_global >> 16; + keyregion[2] = fd1094_global >> 8; + keyregion[3] = fd1094_global >> 0; + + /* then generate the remaining 8188 bytes */ + generate_key_bytes(keyregion, 4, 8192 - 4, fd1094_seed); + + /* apply the overlay */ + for (keyaddr = 4; keyaddr < KEY_SIZE; keyaddr++) + { + keyregion[keyaddr] |= keystatus[keyaddr] & HIBITS_MASK; + + /* if we're locked, propogate that info to all our reps */ + if ((keystatus[keyaddr] & STATUS_MASK) == STATUS_LOCKED) + for (repnum = 1; repnum < reps; repnum++) + { + keystatus[repnum * KEY_SIZE + keyaddr] = (keystatus[repnum * KEY_SIZE + keyaddr] & ~STATUS_MASK) | STATUS_LOCKED; + if ((keyaddr & 0x1ffc) == 0x1000) + keystatus[repnum * KEY_SIZE + keyaddr - 0x1000] = (keystatus[repnum * KEY_SIZE + keyaddr - 0x1000] & ~STATUS_MASK) | STATUS_LOCKED; + } + } + + /* update the key with the current fd1094 manager */ + if (key_changed != nullptr) + (*key_changed)(machine); + + /* force all memory and disassembly views to update */ + machine.debug_view().update_all(DVT_MEMORY); + machine.debug_view().update_all(DVT_DISASSEMBLY); + + /* reset keydirty */ + keydirty = false; +} + + +/*----------------------------------------------- + instruction_hook - per-instruction hook +-----------------------------------------------*/ + +static int instruction_hook(device_t &device, offs_t curpc) +{ + int curfdstate = fd1094_set_state(keyregion, -1); + uint8_t instrbuffer[10], keybuffer[5]; + int i, keystat; + + /* quick exit if we're ignoring */ + if (ignore_all || ignorepc[curpc/2]) + return 0; + + /* quick exit if we're already locked */ + keystat = keystatus[curpc/2] & STATUS_MASK; + keystatus[curpc/2] = (keystatus[curpc/2] & ~STATE_MASK) | (curfdstate << 8); + if (keystat == STATUS_LOCKED || keystat == STATUS_NOCHANGE) + { + uint16_t opcode = fd1094_decode(curpc/2, coderegion[curpc/2], keyregion, 0); + int length = get_opcode_length(opcode); + for (i = 1; i < length; i++) + { + keystat = keystatus[curpc/2 + i] & STATUS_MASK; + if (keystat != STATUS_LOCKED && keystat != STATUS_NOCHANGE) + break; + } + if (i == length) + { + for (i = 1; i < length; i++) + keystatus[curpc/2 + i] = (keystatus[curpc/2 + i] & ~STATE_MASK) | (curfdstate << 8); + return 0; + } + } + + /* try all possible decodings at the current pc */ + posscount = try_all_possibilities(device.memory().space(AS_PROGRAM), curpc, 0, 0, instrbuffer, keybuffer, posslist) - posslist; + if (keydirty) + fd1094_regenerate_key(device.machine()); + + /* if we only ended up with one possibility, mark that one as good */ + if (posscount == 1) + { + tag_possibility(device.machine(), &posslist[0], STATUS_LOCKED); + fd1094_regenerate_key(device.machine()); + return 0; + } + + /* print possibilities and break */ + print_possibilities(device.machine()); + return 1; +} + + +/*----------------------------------------------- + execute_fdsave - handle the 'fdsave' command +-----------------------------------------------*/ + +static void execute_fdsave(running_machine &machine, int ref, int params, const char **param) +{ + save_overlay_file(machine); + machine.debugger().console().printf("File saved\n"); +} + + +/*----------------------------------------------- + execute_fdoutput - output the current key + to a file +-----------------------------------------------*/ + +static void execute_fdoutput(running_machine &machine, int ref, int params, const char **param) +{ + /* make sure we're up-to-date */ + if (keydirty) + fd1094_regenerate_key(machine); + + /* determin the filename and open the file */ + emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + osd_file::error filerr = file.open(param[0]); + if (filerr == osd_file::error::NONE) + file.write(keyregion, KEY_SIZE); + + machine.debugger().console().printf("File '%s' saved\n", param[0]); +} + + +/*----------------------------------------------- + execute_fdseed - handle the 'fdseed' command +-----------------------------------------------*/ + +static void execute_fdseed(running_machine &machine, int ref, int params, const char **param) +{ + uint64_t num1, num2; + + /* extract the parameters */ + if (!machine.debugger().commands().validate_number_parameter(param[0], &num1)) + return; + if (!machine.debugger().commands().validate_number_parameter(param[1], &num2)) + return; + + /* set the global and seed, and then regenerate the key */ + fd1094_global = num1; + fd1094_seed = num2; + + /* clear out our buffer */ + memset(keystatus, 0, keystatus_words * sizeof(keystatus[0])); + + /* regenerate the key and reset the 68000 */ + fd1094_regenerate_key(machine); +} + + +/*----------------------------------------------- + execute_fdlockguess - handle the 'fdlock' + and 'fdguess' commands +-----------------------------------------------*/ + +static void execute_fdlockguess(running_machine &machine, int ref, int params, const char **param) +{ + uint64_t num1; + + /* extract the parameter */ + if (!machine.debugger().commands().validate_number_parameter(param[0], &num1)) + return; + + /* make sure it is within range of our recent possibilities */ + if (num1 >= posscount) + { + machine.debugger().console().printf("Possibility of out range (%x max)\n", posscount); + return; + } + + /* create an undo buffer */ + memcpy(undobuff, keystatus, keystatus_words * 2); + + /* tag this possibility as indicated by the ref parameter, and then regenerate the key */ + tag_possibility(machine, &posslist[num1], ref); + fd1094_regenerate_key(machine); +} + + +/*----------------------------------------------- + execute_fdeliminate - handle the + 'fdeliminate' command +-----------------------------------------------*/ + +static void execute_fdeliminate(running_machine &machine, int ref, int params, const char **param) +{ + int pnum, posssrc, possdst; + int plist[10]; + + /* extract parameters */ + for (pnum = 0; pnum < params; pnum++) + { + uint64_t num1; + + /* extract the parameters */ + if (!machine.debugger().commands().validate_number_parameter(param[pnum], &num1)) + return; + + /* make sure it is within range of our recent possibilities */ + if (num1 >= posscount) + { + machine.debugger().console().printf("Possibility %x of out range (%x max)\n", (int)num1, posscount); + return; + } + + /* set the entry */ + plist[pnum] = num1; + } + + /* loop over parameters */ + for (posssrc = possdst = 0; posssrc < posscount; posssrc++) + { + /* is the current pnum in our list to delete? */ + for (pnum = 0; pnum < params; pnum++) + if (plist[pnum] == posssrc) + break; + + /* if not, copy to the dest */ + if (pnum == params) + posslist[possdst++] = posslist[posssrc]; + } + + /* set the final count */ + posscount = possdst; + + /* reprint the possibilities */ + print_possibilities(machine); +} + + +/*----------------------------------------------- + execute_fdunlock - handle the 'fdunlock' + command +-----------------------------------------------*/ + +static void execute_fdunlock(running_machine &machine, int ref, int params, const char **param) +{ + device_t *cpu = machine.debugger().console().get_visible_cpu(); + + /* support 0 or 1 parameters */ + uint64_t offset; + if (params != 1 || !machine.debugger().commands().validate_number_parameter(param[0], &offset)) + offset = cpu->state().pc(); + int keyaddr = addr_to_keyaddr(offset / 2); + + /* toggle the ignore PC status */ + machine.debugger().console().printf("Unlocking PC %06X\n", (int)offset); + + /* iterate over all reps and unlock them */ + const int reps = keystatus_words / KEY_SIZE; + for (int repnum = 0; repnum < reps; repnum++) + { + uint16_t *dest = &keystatus[repnum * KEY_SIZE + keyaddr]; + if ((*dest & STATUS_MASK) == STATUS_LOCKED) + *dest &= ~STATUS_MASK & ~HIBITS_MASK; + + /* unlock the duplicate key bytes as well */ + if ((keyaddr & 0x1ffc) == 0x1000) + { + dest = &keystatus[repnum * KEY_SIZE + keyaddr - 0x1000]; + if ((*dest & STATUS_MASK) == STATUS_LOCKED) + *dest &= ~STATUS_MASK & ~HIBITS_MASK; + } + } +} + + +/*----------------------------------------------- + execute_fdignore - handle the 'fdignore' + command +-----------------------------------------------*/ + +static void execute_fdignore(running_machine &machine, int ref, int params, const char **param) +{ + device_t *cpu = machine.debugger().console().get_visible_cpu(); + + /* support 0 or 1 parameters */ + if (params == 1 && strcmp(param[0], "all") == 0) + { + ignore_all = true; + machine.debugger().console().printf("Ignoring all unknown opcodes\n"); + return; + } + + uint64_t offset; + if (params != 1 || !machine.debugger().commands().validate_number_parameter(param[0], &offset)) + offset = cpu->state().pc(); + offset /= 2; + + /* toggle the ignore PC status */ + ignorepc[offset] = !ignorepc[offset]; + if (ignorepc[offset]) + machine.debugger().console().printf("Ignoring address %06X\n", (int)offset * 2); + else + machine.debugger().console().printf("No longer ignoring address %06X\n", (int)offset * 2); + + /* if no parameter given, implicitly run as well */ + if (params == 0) + machine.debugger().console().get_visible_cpu()->debug()->go(); +} + + +/*----------------------------------------------- + execute_fdundo - handle the 'fdundo' + command +-----------------------------------------------*/ + +static void execute_fdundo(running_machine &machine, int ref, int params, const char **param) +{ + /* copy the undobuffer back and regenerate the key */ + memcpy(keystatus, undobuff, keystatus_words * 2); + fd1094_regenerate_key(machine); + machine.debugger().console().printf("Undid last change\n"); +} + + +/*----------------------------------------------- + execute_fdstatus - handle the 'fdstatus' + command +-----------------------------------------------*/ + +static void execute_fdstatus(running_machine &machine, int ref, int params, const char **param) +{ + int numreps = keystatus_words / KEY_SIZE; + int locked = 4, nomatter = 0, guesses = 0; + int keyaddr; + + /* count how many locked keys we have */ + for (keyaddr = 4; keyaddr < KEY_SIZE; keyaddr++) + { + int count[STATUS_MASK + 1] = { 0 }; + int repnum; + + for (repnum = 0; repnum < numreps; repnum++) + count[keystatus[repnum * KEY_SIZE + keyaddr] & STATUS_MASK]++; + if (count[STATUS_LOCKED] > 0) + locked++; + else if (count[STATUS_GUESS] > 0) + guesses++; + else + nomatter++; + } + machine.debugger().console().printf("%4d/%4d keys locked (%d%%)\n", locked, KEY_SIZE, locked * 100 / KEY_SIZE); + machine.debugger().console().printf("%4d/%4d keys guessed (%d%%)\n", guesses, KEY_SIZE, guesses * 100 / KEY_SIZE); + machine.debugger().console().printf("%4d/%4d keys don't matter (%d%%)\n", nomatter, KEY_SIZE, nomatter * 100 / KEY_SIZE); +} + + +/*----------------------------------------------- + execute_fdstate - handle the 'fdstate' + command +-----------------------------------------------*/ + +static void execute_fdstate(running_machine &machine, int ref, int params, const char **param) +{ + uint64_t newstate; + + /* set the new state if we got a parameter */ + if (params > 0) + { + if (!machine.debugger().commands().validate_number_parameter(param[0], &newstate)) + return; + fd1094_set_state(keyregion, newstate); + fd1094_regenerate_key(machine); + machine.debug_view().update_all(DVT_MEMORY); + machine.debug_view().update_all(DVT_DISASSEMBLY); + } + + /* 0 parameters displays the current state */ + machine.debugger().console().printf("FD1094 state = %X\n", fd1094_set_state(keyregion, -1)); +} + + +/*----------------------------------------------- + execute_fdpc - handle the 'fdpc' + command +-----------------------------------------------*/ + +static void execute_fdpc(running_machine &machine, int ref, int params, const char **param) +{ + device_t *cpu = machine.debugger().console().get_visible_cpu(); + + /* support 0 or 1 parameters */ + uint64_t newpc = 0; + if (!machine.debugger().commands().validate_number_parameter(param[0], &newpc)) + newpc = cpu->state().pc(); + + /* set the new PC */ + cpu->state().set_pc(newpc); + + /* recompute around that */ + instruction_hook(*cpu, newpc); +} + + +/*----------------------------------------------- + execute_fdsearch - handle the 'fdsearch' + command +-----------------------------------------------*/ + +static void execute_fdsearch(running_machine &machine, int ref, int params, const char **param) +{ + address_space &space = machine->debugger().console().get_visible_cpu()->memory().space(AS_PROGRAM); + int pc = space.device().state().pc(); + int length, first = true; + uint8_t instrdata[2]; + uint16_t decoded; + + /* if we don't match, reset the stack */ + if (searchsp == 0 || searchstack[searchsp-1] != pc) + { + int pcaddr; + machine.debugger().console().printf("Starting new search at PC=%06X\n", pc); + searchsp = 0; + for (pcaddr = 0; pcaddr < coderegion_words; pcaddr++) + keystatus[pcaddr] &= ~SEARCH_MASK; + } + else + { + machine.debugger().console().printf("Resuming search at PC=%06X\n", pc); + searchsp--; + } + + /* loop while we don't need to break */ + while (1) + { + int newpc; + + /* for each PC after the first, do some extra work */ + if (!first) + { + /* if we've hit this PC already, stop and back off */ + while ((keystatus[pc/2] & SEARCH_MASK) != 0 && searchsp > 0) + pc = searchstack[--searchsp]; + if ((keystatus[pc/2] & SEARCH_MASK) != 0) + { + machine.debugger().console().printf("Search stack exhausted\n"); + break; + } + + /* set this as our current PC and run the instruction hook */ + space.device().state().set_pc(pc); + if (instruction_hook(space.device(), pc)) + break; + } + keystatus[pc/2] |= SEARCH_MASK; + first = false; + + /* decode the first word */ + decoded = fd1094_decode(pc/2, coderegion[pc/2], keyregion, 0); + instrdata[0] = decoded >> 8; + instrdata[1] = decoded; + + /* get the opcode */ + length = validate_opcode(space, pc, instrdata, 1); + if (length < 0) + length = -length; + if (length == 0) + { + machine.debugger().console().printf("Invalid opcode; unable to advance\n"); + break; + } + + /* advance to the new PC */ + newpc = pc + length * 2; + + /* handle branches */ + if (optable[decoded].flags & OF_BRANCH) + { + int deltapc = (int8_t)decoded; + int targetpc; + + /* extract the delta PC */ + if ((optable[decoded].flags & OF_ISIZEMASK) == OF_IMMW) + deltapc = (int16_t)fd1094_decode((pc+2)/2, coderegion[(pc+2)/2], keyregion, 0); + else if ((optable[decoded].flags & OF_ISIZEMASK) == OF_IMML) + deltapc = (int32_t)(fd1094_decode((pc+2)/2, coderegion[(pc+2)/2], keyregion, 0) << 16) + fd1094_decode((pc+4)/2, coderegion[(pc+4)/2], keyregion, 0); + + /* for everything but unconditional branches, push the target on the stack; else just go there */ + targetpc = (pc + 2 + deltapc) & 0xffffff; + if ((decoded & 0xff00) != 0x6000) + searchstack[searchsp++] = targetpc; + else + newpc = targetpc; + } + + /* handle jumps */ + if (optable[decoded].flags & OF_JMP) + { + int targetpc; + + /* if we're not an absolute address, skip it */ + if ((decoded & 0x3e) != 0x38) + continue; + + /* determine the target PC */ + if ((decoded & 0x3f) == 0x38) + targetpc = (int16_t)fd1094_decode((pc+2)/2, coderegion[(pc+2)/2], keyregion, 0); + else + targetpc = (int32_t)(fd1094_decode((pc+2)/2, coderegion[(pc+2)/2], keyregion, 0) << 16) + fd1094_decode((pc+4)/2, coderegion[(pc+4)/2], keyregion, 0); + + /* for jsr's, add a stack entry to explore the destination; else just go there */ + if ((decoded & 0xffc0) == 0x4e80) + searchstack[searchsp++] = targetpc; + else + newpc = targetpc; + } + + /* if we hit RTS/RTE, stop here */ + if (decoded == 0x4e73 || decoded == 0x4e75) + continue; + + /* set the new PC */ + pc = newpc; + } + + /* push the current PC on the stack */ + searchstack[searchsp++] = pc; +} + + +/*----------------------------------------------- + execute_fddasm - handle the 'fddasm' + command +-----------------------------------------------*/ + +static void execute_fddasm(running_machine &machine, int ref, int params, const char **param) +{ + address_space &space = machine->debugger().console().get_visible_cpu()->memory().space(AS_PROGRAM); + int origstate = fd1094_set_state(keyregion, -1); + const char *filename; + int skipped = false; + uint32_t pcaddr; + + /* extract the parameters */ + filename = param[0]; + + /* open the file */ + emu_file file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE); + osd_file::error filerr = file.open(filename); + if (filerr != osd_file::error::NONE) + { + machine.debugger().console().printf("Unable to create file '%s'\n", filename); + return; + } + + /* now do the disassembly */ + for (pcaddr = 0; pcaddr < coderegion_words; ) + { + uint8_t instrbuffer[10]; + int unknowns = false; + int length, pcoffs; + char disasm[256]; + uint16_t decoded; + int pnum; + + /* if we haven't visited this word, go to the next */ + if ((keystatus[pcaddr] & STATE_MASK) == 0) + { + pcaddr++; + skipped = true; + continue; + } + + /* get the opcode */ + fd1094_set_state(keyregion, FD1094_STATE_RESET | (keystatus[pcaddr] >> 8)); + decoded = fd1094_decode(pcaddr, coderegion[pcaddr], keyregion, 0); + length = optable[decoded].flags >> 28; + if (optable[decoded].flags == OF_INVALID) + length = 1; + + /* decode the remaining words */ + instrbuffer[0] = decoded >> 8; + instrbuffer[1] = decoded; + for (pcoffs = 1; pcoffs < length; pcoffs++) + { + if ((keystatus[pcaddr + pcoffs] & STATUS_MASK) == STATUS_UNVISITED) + { + pcaddr++; + skipped = true; + continue; + } + decoded = fd1094_decode(pcaddr + pcoffs, coderegion[pcaddr + pcoffs], keyregion, 0); + instrbuffer[pcoffs*2+0] = decoded >> 8; + instrbuffer[pcoffs*2+1] = decoded; + } + + /* disassemble the instruction */ + m68k_disassemble_raw(disasm, pcaddr * 2, instrbuffer, instrbuffer, M68K_CPU_TYPE_68000); + + /* print the line */ + if (skipped) + file.printf("\n"); + skipped = false; + file.printf(" %02X %06X:", keystatus[pcaddr] >> 8, pcaddr * 2); + for (pcoffs = 0; pcoffs < 5; pcoffs++) + { + if (pcoffs < length) + { + static const char statchar[] = "? =?"; + int keystat = keystatus[pcaddr + pcoffs] & STATUS_MASK; + if (keystat != STATUS_LOCKED && keystat != STATUS_NOCHANGE) + unknowns = true; + file.printf(" %02X%02X%c", instrbuffer[pcoffs*2+0], instrbuffer[pcoffs*2+1], statchar[keystat]); + } + else + file.printf(" "); + } + file.printf("%s\n", disasm); + + /* if we have unknowns, display them as well */ + if (unknowns > 0) + { + uint8_t keybuffer[5]; + int posscount = try_all_possibilities(space, pcaddr * 2, 0, 0, instrbuffer, keybuffer, posslist) - posslist; + for (pnum = 0; pnum < posscount; pnum++) + if (strcmp(disasm, posslist[pnum].dasm) != 0) + { + file.printf(" :"); + for (pcoffs = 0; pcoffs < 5; pcoffs++) + if (pcoffs < posslist[pnum].length) + file.printf(" %02X%02X ", posslist[pnum].instrbuffer[pcoffs*2+0], posslist[pnum].instrbuffer[pcoffs*2+1]); + else + file.printf(" "); + file.printf("%s\n", posslist[pnum].dasm); + } + } + + /* advance */ + pcaddr += length; + } + + /* close the file */ + fd1094_set_state(keyregion, origstate); +} + + +/*----------------------------------------------- + execute_fdcset - handle the 'fdcset' + command +-----------------------------------------------*/ + +static void execute_fdcset(running_machine &machine, int ref, int params, const char **param) +{ + uint64_t pc, value, mask = 0xffff, state = FD1094_STATE_RESET; + int cnum; + + /* extract the parameters */ + if (!machine.debugger().commands().validate_number_parameter(param[0], &pc)) + return; + if (!machine.debugger().commands().validate_number_parameter(param[1], &value)) + return; + if (params >= 3 && !machine.debugger().commands().validate_number_parameter(param[2], &mask)) + return; + if (params >= 4) + { + if (strcmp(param[3], "irq") == 0) + state = FD1094_STATE_IRQ; + else if (!machine.debugger().commands().validate_number_parameter(param[3], &state)) + return; + } + + /* validate parameters */ + if ((pc & 1) != 0 || pc > 0xffffff) + { + machine.debugger().console().printf("Invalid PC specified (%08X)\n", (uint32_t)pc); + return; + } + + /* look for a match and remove any matching constraints */ + for (cnum = 0; cnum < constcount; cnum++) + { + /* insert ahead of later constraints */ + if (constraints[cnum].pc > pc) + { + memmove(&constraints[cnum + 1], &constraints[cnum], (constcount - cnum) * sizeof(constraints[0])); + break; + } + + /* replace matching constraints */ + else if (constraints[cnum].pc == pc) + break; + } + + /* set the new constraint and increase the count */ + if (cnum >= constcount || constraints[cnum].pc != pc) + constcount++; + set_constraint(&constraints[cnum], pc, state, value, mask); + + /* explain what we did */ + machine.debugger().console().printf("Set new constraint at PC=%06X, state=%03X: decrypted & %04X == %04X\n", + (int)pc, (int)state, (int)mask, (int)value); +} + + +/*----------------------------------------------- + execute_fdclist - handle the 'fdclist' + command +-----------------------------------------------*/ + +static void execute_fdclist(running_machine &machine, int ref, int params, const char **param) +{ + int cnum; + + /* loop over constraints and print them */ + for (cnum = 0; cnum < constcount; cnum++) + { + fd1094_constraint *constraint = &constraints[cnum]; + machine.debugger().console().printf(" PC=%06X, state=%03X: decrypted & %04X == %04X\n", + constraint->pc, constraint->state, constraint->mask, constraint->value); + } +} + + +/*----------------------------------------------- + execute_fdcsearch - handle the 'fdcsearch' + command +-----------------------------------------------*/ + +static void execute_fdcsearch(running_machine &machine, int ref, int params, const char **param) +{ +// machine.debugger().console().printf("Searching for possible global keys....\n"); + perform_constrained_search(machine); +} + + +/*----------------------------------------------- + try_all_possibilities - recursively try + all possible values of the high bits of the + key at the given address for the specified + length +-----------------------------------------------*/ + +static fd1094_possibility *try_all_possibilities(address_space &space, int basepc, int offset, int length, uint8_t *instrbuffer, uint8_t *keybuffer, fd1094_possibility *possdata) +{ + uint8_t keymask, keystat; + uint16_t possvalue[4]; + uint8_t posskey[4]; + int numposs = 0; + int decoded; + int keyaddr; + int pcaddr; + int hibit; + int i; + + /* get the key address and mask */ + pcaddr = basepc/2 + offset; + keyaddr = addr_to_keyaddr(pcaddr); + keymask = mask_for_keyaddr(keyaddr); + keystat = keystatus[pcaddr] & STATUS_MASK; + + /* if the status is 1 (locked) or 2 (doesn't matter), just take the current value */ + if (keystat == STATUS_LOCKED || keystat == STATUS_NOCHANGE) + { + posskey[numposs] = keyregion[keyaddr]; + possvalue[numposs++] = fd1094_decode(pcaddr, coderegion[pcaddr], keyregion, 0); + } + + /* otherwise, iterate over high bits */ + else + { + /* remember the original key and iterate over high bits */ + uint8_t origkey = keyregion[keyaddr]; + for (hibit = 0x00; hibit < 0x100; hibit += 0x40) + if ((hibit & keymask) == keymask) + { + /* set the key and decode this word */ + keyregion[keyaddr] = (origkey & ~HIBITS_MASK) | hibit; + decoded = fd1094_decode(pcaddr, coderegion[pcaddr], keyregion, 0); + + /* see if we already got that value */ + for (i = 0; i < numposs; i++) + if ((uint16_t)decoded == possvalue[i]) + break; + + /* if not, add it to the list */ + if (i == numposs) + { + posskey[numposs] = keyregion[keyaddr]; + possvalue[numposs++] = decoded; + } + } + + /* restore the original key */ + keyregion[keyaddr] = origkey; + + /* if there was only one possibility, then mark it as "doesn't matter" */ + if (numposs == 1) + { + keystatus[pcaddr] = (keystatus[pcaddr] & ~STATUS_MASK) | STATUS_NOCHANGE; + keydirty = true; + } + } + + /* now iterate over our possible values */ + for (i = 0; i < numposs; i++) + { + /* set the instruction buffer */ + instrbuffer[offset*2 + 0] = possvalue[i] >> 8; + instrbuffer[offset*2 + 1] = possvalue[i]; + keybuffer[offset] = posskey[i]; + + /* if our length is 0, we need to do a quick dasm to see how long our length is */ + if (offset == 0) + { + /* first make sure we are a valid instruction */ + if ((possvalue[i] & 0xf000) == 0xa000 || (possvalue[i] & 0xf000) == 0xf000) + continue; + length = validate_opcode(space, basepc, instrbuffer, 1); + if (length == 0) + continue; + if (length < 0) + length = -length; + } + + /* if we're not at our target length, recursively call ourselves */ + if (offset < length - 1) + possdata = try_all_possibilities(space, basepc, offset + 1, length, instrbuffer, keybuffer, possdata); + + /* otherwise, output what we have */ + else + { + int tlen, inoffs; + + /* do the disassembly, and make sure we don't get an invalid result */ + m68k_disassemble_raw(possdata->dasm, basepc, instrbuffer, instrbuffer, M68K_CPU_TYPE_68000); + + /* validate the opcode */ + tlen = validate_opcode(space, basepc, instrbuffer, length); + if (tlen == 0) + { + printf("Eliminated: %s [", possdata->dasm); + for (inoffs = 0; inoffs < length; inoffs++) + printf("%04X ", (instrbuffer[inoffs*2+0] << 8) | instrbuffer[inoffs*2+1]); + printf("]\n"); + continue; + } + + /* copy the rest of the data and increment the pointer */ + possdata->basepc = basepc; + possdata->length = (tlen < 0) ? -tlen : tlen; + possdata->iffy = (tlen < 0); + memcpy(possdata->instrbuffer, instrbuffer, sizeof(possdata->instrbuffer)); + memcpy(possdata->keybuffer, keybuffer, sizeof(possdata->keybuffer)); + possdata++; + } + } + + return possdata; +} + + +/*----------------------------------------------- + tag_possibility - tag a given possibility + with the specified status +-----------------------------------------------*/ + +static void tag_possibility(running_machine &machine, fd1094_possibility *possdata, uint8_t status) +{ + int curfdstate = fd1094_set_state(keyregion, -1); + int nomatter = 0, locked = 0, guessed = 0; + int reps = keystatus_words / KEY_SIZE; + uint8_t newstat[5]; + int pcoffs; + + /* determine the new status for each word */ + for (pcoffs = 0; pcoffs < possdata->length; pcoffs++) + { + int pnum; + + /* default to setting the requested status */ + newstat[pcoffs] = status; + + /* see if the current word was the same across all possibilities */ + for (pnum = 0; pnum < posscount; pnum++) + if (posslist[pnum].instrbuffer[pcoffs*2+0] != possdata->instrbuffer[pcoffs*2+0] || + posslist[pnum].instrbuffer[pcoffs*2+1] != possdata->instrbuffer[pcoffs*2+1]) + break; + + /* if so, lock, don't guess */ + if (pnum == posscount) + newstat[pcoffs] = STATUS_LOCKED; + } + + /* iterate over words in the opcode */ + for (pcoffs = 0; pcoffs < possdata->length; pcoffs++) + { + int pcaddr = possdata->basepc/2 + pcoffs; + int keyaddr = addr_to_keyaddr(pcaddr); + int keystat = keystatus[pcaddr] & STATUS_MASK; + int repnum; + + /* if the status doesn't match and isn't "no change", then set the status */ + if (keystat != STATUS_NOCHANGE) + { + keystatus[keyaddr] = (keystatus[keyaddr] & ~HIBITS_MASK) | (possdata->keybuffer[pcoffs] & HIBITS_MASK); + keystatus[pcaddr] = (keystatus[pcaddr] & ~STATE_MASK & ~STATUS_MASK) | (curfdstate << 8) | newstat[pcoffs]; + keydirty = true; + } + else + keystatus[pcaddr] = (keystatus[pcaddr] & ~STATE_MASK) | (curfdstate << 8); + + /* if we're now locked, propogate across all reps */ + keystat = keystatus[pcaddr] & STATUS_MASK; + if (keystat == STATUS_LOCKED) + for (repnum = 0; repnum < reps; repnum++) + { + keystatus[repnum * KEY_SIZE + keyaddr] = (keystatus[repnum * KEY_SIZE + keyaddr] & ~STATUS_MASK) | STATUS_LOCKED; + if ((keyaddr & 0x1ffc) == 0x1000) + keystatus[repnum * KEY_SIZE + keyaddr - 0x1000] = (keystatus[repnum * KEY_SIZE + keyaddr - 0x1000] & ~STATUS_MASK) | STATUS_LOCKED; + } + + /* update the final key status */ + if (keystat == STATUS_LOCKED) + locked++; + else if (keystat == STATUS_GUESS) + guessed++; + else if (keystat == STATUS_NOCHANGE) + nomatter++; + } + + machine.debugger().console().printf("PC=%06X: locked %d, guessed %d, nochange %d\n", possdata->basepc, locked, guessed, nomatter); +} + + +/*----------------------------------------------- + perform_constrained_search - look for + the next global key that will match the + given sequence/mask pair +-----------------------------------------------*/ + +static void perform_constrained_search(running_machine &machine) +{ + uint32_t global; + + /* ensure our first 4 constraints are what we expect */ + assert(constraints[0].pc == 0x000000); + assert(constraints[1].pc == 0x000002); + assert(constraints[2].pc == 0x000004); + assert(constraints[3].pc == 0x000006); + + /* start with a 0 global key and brute force from there */ + global = 0; + + /* loop until we run out of possibilities */ + while (1) + { + uint16_t output[4]; + int numseeds; + + /* look for the next global key match */ + global = find_global_key_matches(global + 1, output); + if (global == 0) + break; +// machine.debugger().console().printf("Checking global key %08X (PC=%06X)....\n", global, (output[2] << 16) | output[3]); + + /* use the IRQ handler to find more possibilities */ + numseeds = find_constraint_sequence(global, false); + if (numseeds > 0) + { + int i; + for (i = 0; i < numseeds; i++) + machine.debugger().console().printf(" Possible: global=%08X seed=%06X pc=%04X\n", global, possible_seed[i], output[3]); + } + } +} + + +/*----------------------------------------------- + find_global_key_matches - look for + the next global key that will match the + given sequence/mask pair +-----------------------------------------------*/ + +static uint32_t find_global_key_matches(uint32_t startwith, uint16_t *output) +{ + int key0, key1, key2, key3; + uint8_t key[4]; + + /* iterate over the first key byte, allowing all possible values */ + for (key0 = (startwith >> 24) & 0xff; key0 < 256; key0++) + { + /* set the key and reset the fd1094 */ + key[0] = key0; + startwith &= 0x00ffffff; + fd1094_set_state(key, FD1094_STATE_RESET); + + /* if we match, iterate over the second key byte */ + output[0] = fd1094_decode(0x000000, coderegion[0], key, true); + if ((output[0] & constraints[0].mask) == constraints[0].value) + + /* iterate over the second key byte, limiting the scope to known valid keys */ + for (key1 = (startwith >> 16) & 0xff; key1 < 256; key1++) + if ((key1 & 0xf8) == 0xa8 || (key1 & 0xf8) == 0xf8) + { + /* set the key and reset the fd1094 */ + key[1] = key1; + startwith &= 0x0000ffff; + fd1094_set_state(key, FD1094_STATE_RESET); + + /* if we match, iterate over the third key byte */ + output[1] = fd1094_decode(0x000001, coderegion[1], key, true); + if ((output[1] & constraints[1].mask) == constraints[1].value) + + /* iterate over the third key byte, limiting the scope to known valid keys */ + for (key2 = (startwith >> 8) & 0xff; key2 < 256; key2++) + if ((key2 & 0xc0) == 0xc0) + { + /* set the key and reset the fd1094 */ + key[2] = key2; + startwith &= 0x000000ff; + fd1094_set_state(key, FD1094_STATE_RESET); + + /* if we match, iterate over the fourth key byte */ + output[2] = fd1094_decode(0x000002, coderegion[2], key, true); + if ((output[2] & constraints[2].mask) == constraints[2].value) + + /* iterate over the fourth key byte, limiting the scope to known valid keys */ + for (key3 = (startwith >> 0) & 0xff; key3 < 256; key3++) + if ((key3 & 0xc0) == 0xc0) + { + /* set the key and reset the fd1094 */ + key[3] = key3; + startwith = 0; + fd1094_set_state(key, FD1094_STATE_RESET); + + /* if we match, return the value */ + output[3] = fd1094_decode(0x000003, coderegion[3], key, true); + if ((output[3] & constraints[3].mask) == constraints[3].value) + return (key0 << 24) | (key1 << 16) | (key2 << 8) | key3; + } + } + } + } + return 0; +} + + +/*----------------------------------------------- + find_constraint_sequence - look for a + sequence of decoded words at the given + address, and optionally verify that there + are valid PRNG keys that could generate the + results +-----------------------------------------------*/ + +static int find_constraint_sequence(uint32_t global, int quick) +{ + const fd1094_constraint *minkeyaddr = &constraints[4]; + const fd1094_constraint *maxkeyaddr = &constraints[4]; + const fd1094_constraint *curr; + int keyvalue, keyaddr, keysneeded; + int seedcount = 0; + uint16_t decrypted; + uint8_t key[8192]; + uint8_t keymask; + offs_t pcaddr; + + /* if we don't have any extra constraints, we're good */ + if (constcount <= 4) + return -1; + + /* set the global key */ + key[0] = global >> 24; + key[1] = global >> 16; + key[2] = global >> 8; + key[3] = global >> 0; + fd1094_set_state(key, -1); + + /* first see if it is even possible, regardless of PRNG */ + for (curr = &constraints[4]; curr < &constraints[constcount]; curr++) + { + /* get the key address and value for this offset */ + pcaddr = curr->pc / 2; + keyaddr = addr_to_keyaddr(pcaddr); + keymask = mask_for_keyaddr(keyaddr); + + /* track the minumum and maximum key addresses, but only for interesting combinations */ + if ((coderegion[pcaddr] & 0xe000) != 0x0000) + { + if (keyaddr < addr_to_keyaddr(minkeyaddr->pc / 2)) + minkeyaddr = curr; + if (keyaddr > addr_to_keyaddr(maxkeyaddr->pc / 2)) + maxkeyaddr = curr; + } + + /* set the state */ + fd1094_set_state(key, curr->state); + + /* brute force search this byte */ + for (keyvalue = 0; keyvalue < 256; keyvalue++) + if ((keyvalue & keymask) == keymask) + { + /* see if this works */ + key[keyaddr] = keyvalue; + decrypted = fd1094_decode(pcaddr, coderegion[pcaddr], key, false); + + /* if we got a match, stop; we're done */ + if ((decrypted & curr->mask) == curr->value) + break; + } + + /* if we failed, we're done */ + if (keyvalue == 256) + return 0; + } + + /* if we're quick, that's all the checking we do */ + if (quick) + return -1; + + /* determine how many keys we need to cover our whole range */ + keysneeded = addr_to_keyaddr(maxkeyaddr->pc / 2) + 1 - addr_to_keyaddr(minkeyaddr->pc / 2); + + /* now do the more thorough search */ + pcaddr = minkeyaddr->pc / 2; + keyaddr = addr_to_keyaddr(pcaddr); + keymask = mask_for_keyaddr(keyaddr); + + /* set the state */ + fd1094_set_state(key, minkeyaddr->state); + + /* brute force search the first byte key of the key */ + for (keyvalue = 0; keyvalue < 256; keyvalue++) + if ((keyvalue & keymask) == keymask) + { + /* see if this works */ + key[keyaddr] = keyvalue; + decrypted = fd1094_decode(pcaddr, coderegion[pcaddr], key, false); + + /* if we got a match, then iterate over all possible PRNG sequences starting with this */ + if ((decrypted & minkeyaddr->mask) == minkeyaddr->value) + { + uint32_t seedlow; + +// machine.debugger().console().printf("Global %08X ... Looking for keys that generate a keyvalue of %02X at %04X\n", +// global, keyvalue, keyaddr); + + /* iterate over seed possibilities */ + for (seedlow = 0; seedlow < (1 << 16); seedlow++) + { + /* start with the known upper bits together with the 16 guessed lower bits */ + uint32_t seedstart = (~keyvalue << 16) | seedlow; + + /* generate data starting with this seed into the key */ + generate_key_bytes(key, keyaddr + 1, keysneeded - 1, seedstart); + + /* if the whole thing matched, record the match */ + if (does_key_work_for_constraints(coderegion, key)) + { + seedstart = reconstruct_base_seed(keyaddr, seedstart); + if ((seedstart & 0x3fffff) != 0) + possible_seed[seedcount++] = seedstart; + } + } + } + } + + return seedcount; +} + + +/*----------------------------------------------- + does_key_work_for_constraints - return true + if the given key might work for a given set + of constraints +-----------------------------------------------*/ + +static int does_key_work_for_constraints(const uint16_t *base, uint8_t *key) +{ + const fd1094_constraint *curr; + uint16_t decrypted; + + /* iterate over the sequence */ + for (curr = &constraints[4]; curr < &constraints[constcount]; curr++) + { + offs_t pcaddr = curr->pc / 2; + int keyaddr = addr_to_keyaddr(pcaddr); + uint8_t keymask = mask_for_keyaddr(keyaddr); + int hibits; + + /* set the state */ + fd1094_set_state(key, curr->state); + + /* iterate over high bits (1 per byte) */ + for (hibits = 0; hibits < 0x100; hibits += 0x40) + if ((hibits & keymask) == keymask) + { + /* update the key bits */ + key[keyaddr] = (key[keyaddr] & ~0xc0) | hibits; + + /* decrypt using this key; stop if we get a match */ + decrypted = fd1094_decode(pcaddr, base[pcaddr], key, false); + if ((decrypted & curr->mask) == curr->value) + break; + } + + /* if we failed to match, we're done */ + if (hibits >= 0x100) + return false; + } + + /* got a match on all entries */ + return true; +} + + +/*----------------------------------------------- + reconstruct_base_seed - given the seed + value at a particular key address, return + the seed that would be used to generate the + first key value (at offset 4) +-----------------------------------------------*/ + +static uint32_t reconstruct_base_seed(int keybaseaddr, uint32_t startseed) +{ + uint32_t seed = startseed; + uint32_t window[8192]; + int index = 0; + + /* keep generating, starting from the start seed until we re-generate the start seed */ + /* note that some sequences are smaller than the window, so we also have to ensure */ + /* that we generate at least one full window's worth of data */ + do + { + seed = seed * 0x29; + seed += seed << 16; + window[index++ % std::size(window)] = seed; + } while (((startseed ^ seed) & 0x3fffff) != 0 || index < std::size(window)); + + /* when we break, we have overshot */ + index--; + + /* back up to where we would have been at address 3 */ + index -= keybaseaddr - 3; + if (index < 0) + index += std::size(window); + + /* return the value from the window at that location */ + return window[index % std::size(window)] & 0x3fffff; +} + + +/*----------------------------------------------- + Table of opcode parameters +-----------------------------------------------*/ + +#define ENTRY(a,b,c,d) { #a, #b, c, d }, + +static const struct +{ + const char * bitstring; + const char * eastring; + uint32_t flags; + const char * instring; +} instr_table[] = +{ + ENTRY(1100...100000..., ........., OF_BYTE | OF_RARE, "ABCD Dn,Dm") + ENTRY(1100...100001..., ........., OF_BYTE | OF_RARE, "ABCD -(An),-(Am)") + ENTRY(1101...000......, d.A+-DBIP, OF_BYTE | OF_EASRC, "ADD.B <ea>,Dn") + ENTRY(1101...001......, daA+-DBIP, OF_WORD | OF_EASRC, "ADD.W <ea>,Dn") + ENTRY(1101...010......, daA+-DBIP, OF_LONG | OF_EASRC, "ADD.L <ea>,Dn") + ENTRY(1101...011......, daA+-DBIP, OF_WORD | OF_EASRC, "ADDA.W <ea>,An") + ENTRY(1101...100......, ..A+-DB.., OF_BYTE | OF_EADST, "ADD.B Dn,<ea>") + ENTRY(1101...101......, ..A+-DB.., OF_WORD | OF_EADST, "ADD.W Dn,<ea>") + ENTRY(1101...110......, ..A+-DB.., OF_LONG | OF_EADST, "ADD.L Dn,<ea>") + ENTRY(1101...111......, daA+-DBIP, OF_LONG | OF_EASRC, "ADDA.L <ea>,An") + ENTRY(0000011000......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMB, "ADDI.B #x,<ea>") + ENTRY(0000011001......, d.A+-DB.., OF_WORD | OF_EADST | OF_IMMW, "ADDI.W #x,<ea>") + ENTRY(0000011010......, d.A+-DB.., OF_LONG | OF_EADST | OF_IMML, "ADDI.L #x,<ea>") + ENTRY(0101...000......, d.A+-DB.., OF_BYTE | OF_EADST, "ADDQ.B #x,<ea>") + ENTRY(0101...001......, daA+-DB.., OF_WORD | OF_EADST, "ADDQ.W #x,<ea>") + ENTRY(0101...010......, daA+-DB.., OF_LONG | OF_EADST, "ADDQ.L #x,<ea>") + ENTRY(1101...10000...., ........., OF_BYTE | OF_RARE, "ADDX.B") + ENTRY(1101...10100...., ........., OF_WORD | OF_RARE, "ADDX.W") + ENTRY(1101...11000...., ........., OF_LONG | OF_RARE, "ADDX.L") + ENTRY(1100...000......, d.A+-DBIP, OF_BYTE | OF_EASRC, "AND.B <ea>,Dn") + ENTRY(1100...001......, d.A+-DBIP, OF_WORD | OF_EASRC, "AND.W <ea>,Dn") + ENTRY(1100...010......, d.A+-DBIP, OF_LONG | OF_EASRC, "AND.L <ea>,Dn") + ENTRY(1100...100......, ..A+-DB.., OF_BYTE | OF_EADST, "AND.B Dn,<ea>") + ENTRY(1100...101......, ..A+-DB.., OF_WORD | OF_EADST, "AND.W Dn,<ea>") + ENTRY(1100...110......, ..A+-DB.., OF_LONG | OF_EADST, "AND.L Dn,<ea>") + ENTRY(0000001000111100, ........., OF_BYTE | OF_IMMB | OF_RARE, "ANDI #x,CCR") + ENTRY(0000001000......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMB, "ANDI.B #x,<ea>") + ENTRY(0000001001......, d.A+-DB.., OF_WORD | OF_EADST | OF_IMMW, "ANDI.W #x,<ea>") + ENTRY(0000001010......, d.A+-DB.., OF_LONG | OF_EADST | OF_IMML, "ANDI.L #x,<ea>") + ENTRY(1110....00.00..., ........., OF_BYTE, "ASL/ASR.B") + ENTRY(1110....01.00..., ........., OF_WORD, "ASL/ASR.W") + ENTRY(1110....10.00..., ........., OF_LONG, "ASL/ASR.L") + ENTRY(1110000.11......, ..A+-DB.., OF_WORD | OF_EADST, "ASL/ASR.W <ea>") + ENTRY(0110000000000000, ........., OF_WORD | OF_IMMW | OF_BRANCH, "BRA.W <dst>") + ENTRY(01100000.......0, ........., OF_BYTE | OF_BRANCH, "BRA.B <dst>") + ENTRY(0110000100000000, ........., OF_WORD | OF_IMMW | OF_BRANCH, "BSR.W <dst>") + ENTRY(01100001.......0, ........., OF_BYTE | OF_BRANCH, "BSR.B <dst>") + ENTRY(0110....00000000, ........., OF_WORD | OF_IMMW | OF_BRANCH, "Bcc.W <dst>") + ENTRY(0110...........0, ........., OF_BYTE | OF_BRANCH, "Bcc.B <dst>") + ENTRY(0000...101......, d.A+-DB.., OF_BYTE | OF_EADST, "BCHG Dn,<ea>") + ENTRY(0000100001......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMBIT, "BCHG #x,<ea>") + ENTRY(0000...110......, d.A+-DB.., OF_BYTE | OF_EADST, "BCLR Dn,<ea>") + ENTRY(0000100010......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMBIT, "BCLR #x,<ea>") + ENTRY(0000...111......, d.A+-DB.., OF_BYTE | OF_EADST, "BSET Dn,<ea>") + ENTRY(0000100011......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMBIT, "BSET #x,<ea>") + ENTRY(0000...100......, d.A+-DBIP, OF_BYTE | OF_EADST, "BTST Dn,<ea>") + ENTRY(0000100000......, d.A+-DB.P, OF_BYTE | OF_EADST | OF_IMMBIT, "BTST #x,<ea>") + ENTRY(0100...110......, d.A+-DBIP, OF_WORD | OF_EADST | OF_RARE, "CHK.W <ea>,Dn") + ENTRY(0100001000......, d.A+-DB.., OF_BYTE | OF_EADST, "CLR.B <ea>") + ENTRY(0100001001......, d.A+-DB.., OF_WORD | OF_EADST, "CLR.W <ea>") + ENTRY(0100001010......, d.A+-DB.., OF_LONG | OF_EADST, "CLR.L <ea>") + ENTRY(1011...000......, d.A+-DBIP, OF_BYTE | OF_EASRC, "CMP.B <ea>,Dn") + ENTRY(1011...001......, daA+-DBIP, OF_WORD | OF_EASRC, "CMP.W <ea>,Dn") + ENTRY(1011...010......, daA+-DBIP, OF_LONG | OF_EASRC, "CMP.L <ea>,Dn") + ENTRY(1011...011......, daA+-DBIP, OF_WORD | OF_EASRC, "CMPA.W <ea>,Dn") + ENTRY(1011...111......, daA+-DBIP, OF_LONG | OF_EASRC, "CMPA.L <ea>,Dn") + ENTRY(0000110000......, d.A+-DB.., OF_BYTE | OF_EASRC | OF_IMMB, "CMPI.B #x,<ea>") + ENTRY(0000110001......, d.A+-DB.., OF_WORD | OF_EASRC | OF_IMMW, "CMPI.W #x,<ea>") + ENTRY(0000110010......, d.A+-DB.., OF_LONG | OF_EASRC | OF_IMML, "CMPI.L #x,<ea>") + ENTRY(1011...100001..., ........., OF_BYTE | OF_RARE, "CMPM.B") + ENTRY(1011...101001..., ........., OF_WORD | OF_RARE, "CMPM.W") + ENTRY(1011...110001..., ........., OF_LONG | OF_RARE, "CMPM.L") + ENTRY(0101....11001..., ........., OF_WORD | OF_IMMW | OF_BRANCH, "DBcc.W <dst>") + ENTRY(1000...111......, d.A+-DBIP, OF_WORD | OF_EASRC, "DIVS.W <ea>,Dn") + ENTRY(1000...011......, d.A+-DBIP, OF_WORD | OF_EASRC, "DIVU.W <ea>,Dn") + ENTRY(1011...100......, d.A+-DB.., OF_BYTE | OF_EADST, "EOR.B Dn,<ea>") + ENTRY(1011...101......, d.A+-DB.., OF_WORD | OF_EADST, "EOR.W Dn,<ea>") + ENTRY(1011...110......, d.A+-DB.., OF_LONG | OF_EADST, "EOR.L Dn,<ea>") + ENTRY(0000101000111100, ........., OF_BYTE | OF_IMMB | OF_RARE, "EORI #x,CCR") + ENTRY(0000101000......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMB, "EORI.B #x,<ea>") + ENTRY(0000101001......, d.A+-DB.., OF_WORD | OF_EADST | OF_IMMW, "EORI.W #x,<ea>") + ENTRY(0000101010......, d.A+-DB.., OF_LONG | OF_EADST | OF_IMML, "EORI.L #x,<ea>") + ENTRY(1100...101000..., ........., OF_LONG, "EXG Dn,Dn") + ENTRY(1100...101001..., ........., OF_LONG, "EXG An,An") + ENTRY(1100...110001..., ........., OF_LONG, "EXG Dn,An") + ENTRY(0100100010000..., ........., OF_WORD, "EXT.W Dn") + ENTRY(0100100011000..., ........., OF_WORD, "EXT.L Dn") + ENTRY(0100111011......, ..A..DB.P, OF_WORD | OF_EASRC | OF_JMP, "JMP <ea>") + ENTRY(0100111010......, ..A..DB.P, OF_WORD | OF_EASRC | OF_JMP, "JSR <ea>") + ENTRY(0100...111......, ..A..DB.P, OF_BYTE | OF_EASRC, "LEA <ea>,An") + ENTRY(0100111001010..., ........., OF_WORD | OF_IMMW | OF_RARE, "LINK An,#x") + ENTRY(1110....00.01..., ........., OF_BYTE, "LSL/LSR.B Dn") + ENTRY(1110....01.01..., ........., OF_WORD, "LSL/LSR.W Dn") + ENTRY(1110....10.01..., ........., OF_LONG, "LSL/LSR.L Dn") + ENTRY(1110001.11......, ..A+-DB.., OF_WORD | OF_EADST, "LSL/LSR.W <ea>") + ENTRY(0001............, d.A+-DBIP, OF_BYTE | OF_EASRC | OF_MOVE, "MOVE.B <ea>,<ea>") + ENTRY(0011............, daA+-DBIP, OF_WORD | OF_EASRC | OF_MOVE, "MOVE.W <ea>,<ea>") + ENTRY(0010............, daA+-DBIP, OF_LONG | OF_EASRC | OF_MOVE, "MOVE.L <ea>,<ea>") + ENTRY(0011...001......, daA+-DBIP, OF_WORD | OF_EASRC, "MOVEA.W <ea>,An") + ENTRY(0010...001......, daA+-DBIP, OF_LONG | OF_EASRC, "MOVEA.L <ea>,An") + ENTRY(0100010011......, d.A+-DBIP, OF_WORD | OF_EASRC | OF_RARE, "MOVE <ea>,CCR") + ENTRY(0100000011......, d.A+-DB.., OF_WORD | OF_EADST | OF_RARE, "MOVE SR,<ea>") + ENTRY(0100100010......, ..A.-DB.., OF_WORD | OF_EADST | OF_IMMW, "MOVEM.W <regs>,<ea>") + ENTRY(0100100011......, ..A.-DB.., OF_LONG | OF_EADST | OF_IMMW, "MOVEM.L <regs>,<ea>") + ENTRY(0100110010......, ..A+.DB.P, OF_WORD | OF_EASRC | OF_IMMW, "MOVEM.W <ea>,<regs>") + ENTRY(0100110011......, ..A+.DB.P, OF_LONG | OF_EASRC | OF_IMMW, "MOVEM.L <ea>,<regs>") + ENTRY(0000...100001..., ........., OF_WORD | OF_IMMW | OF_RARE, "MOVEP.W (d16,Ay),Dn") + ENTRY(0000...101001..., ........., OF_LONG | OF_IMMW | OF_RARE, "MOVEP.L (d16,Ay),Dn") + ENTRY(0000...110001..., ........., OF_WORD | OF_IMMW | OF_RARE, "MOVEP.W Dn,(d16,Ay)") + ENTRY(0000...111001..., ........., OF_LONG | OF_IMMW | OF_RARE, "MOVEP.L Dn,(d16,Ay)") + ENTRY(0111...0........, ........., OF_LONG, "MOVEQ #x,Dn") + ENTRY(1100...111......, d.A+-DBIP, OF_WORD | OF_EASRC, "MULS.W <ea>,Dn") + ENTRY(1100...011......, d.A+-DBIP, OF_WORD | OF_EASRC, "MULU.W <ea>,Dn") + ENTRY(0100100000......, d.A+-DB.., OF_BYTE | OF_EADST | OF_RARE, "NBCD <ea>") + ENTRY(0100010000......, d.A+-DB.., OF_BYTE | OF_EADST, "NEG.B <ea>") + ENTRY(0100010001......, d.A+-DB.., OF_WORD | OF_EADST, "NEG.W <ea>") + ENTRY(0100010010......, d.A+-DB.., OF_LONG | OF_EADST, "NEG.L <ea>") + ENTRY(0100000000......, d.A+-DB.., OF_BYTE | OF_EADST | OF_RARE, "NEGX.B <ea>") + ENTRY(0100000001......, d.A+-DB.., OF_WORD | OF_EADST | OF_RARE, "NEGX.W <ea>") + ENTRY(0100000010......, d.A+-DB.., OF_LONG | OF_EADST | OF_RARE, "NEGX.L <ea>") + ENTRY(0100111001110001, ........., 0, "NOP") + ENTRY(0100011000......, d.A+-DB.., OF_BYTE | OF_EADST, "NOT.B <ea>") + ENTRY(0100011001......, d.A+-DB.., OF_WORD | OF_EADST, "NOT.W <ea>") + ENTRY(0100011010......, d.A+-DB.., OF_LONG | OF_EADST, "NOT.L <ea>") + ENTRY(1000...000......, d.A+-DBIP, OF_BYTE | OF_EASRC, "OR.B <ea>,Dn") + ENTRY(1000...001......, d.A+-DBIP, OF_WORD | OF_EASRC, "OR.W <ea>,Dn") + ENTRY(1000...010......, d.A+-DBIP, OF_LONG | OF_EASRC, "OR.L <ea>,Dn") + ENTRY(1000...100......, ..A+-DB.., OF_BYTE | OF_EADST, "OR.B Dn,<ea>") + ENTRY(1000...101......, ..A+-DB.., OF_WORD | OF_EADST, "OR.W Dn,<ea>") + ENTRY(1000...110......, ..A+-DB.., OF_LONG | OF_EADST, "OR.L Dn,<ea>") + ENTRY(0000000000111100, ........., OF_BYTE | OF_IMMB | OF_RARE, "ORI #x,CCR") + ENTRY(0000000000......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMB, "ORI.B #x,<ea>") + ENTRY(0000000001......, d.A+-DB.., OF_WORD | OF_EADST | OF_IMMW, "ORI.W #x,<ea>") + ENTRY(0000000010......, d.A+-DB.., OF_LONG | OF_EADST | OF_IMML, "ORI.L #x,<ea>") + ENTRY(0100100001......, ..A..DB.P, OF_BYTE | OF_EADST | OF_RARE, "PEA <ea>") + ENTRY(1110....00.11..., ........., OF_BYTE, "ROL/ROR.B Dn") + ENTRY(1110....01.11..., ........., OF_WORD, "ROL/ROR.W Dn") + ENTRY(1110....10.11..., ........., OF_LONG, "ROL/ROR.L Dn") + ENTRY(1110011.11......, ..A+-DB.., OF_WORD | OF_EADST, "ROL/ROR.W <ea>") + ENTRY(1110....00.10..., ........., OF_BYTE | OF_RARE, "ROXL/ROXR.B Dn") + ENTRY(1110....01.10..., ........., OF_WORD | OF_RARE, "ROXL/ROXR.W Dn") + ENTRY(1110....10.10..., ........., OF_LONG | OF_RARE, "ROXL/ROXR.L Dn") + ENTRY(1110010.11......, ..A+-DB.., OF_WORD | OF_EADST | OF_RARE, "ROXL/ROXR.W <ea>") + ENTRY(0100111001110111, ........., OF_RARE, "RTR") + ENTRY(0100111001110101, ........., OF_RARE, "RTS") + ENTRY(1000...100000..., ........., OF_BYTE | OF_RARE, "SBCD Dn,Dm") + ENTRY(1000...100001..., ........., OF_BYTE | OF_RARE, "SBCD -(An),-(Am)") + ENTRY(0101....11......, d.A+-DB.., OF_BYTE | OF_EADST | OF_RARE, "Scc <ea>") + ENTRY(1001...000......, d.A+-DBIP, OF_BYTE | OF_EASRC, "SUB.B <ea>,Dn") + ENTRY(1001...001......, daA+-DBIP, OF_WORD | OF_EASRC, "SUB.W <ea>,Dn") + ENTRY(1001...010......, daA+-DBIP, OF_LONG | OF_EASRC, "SUB.L <ea>,Dn") + ENTRY(1001...011......, daA+-DBIP, OF_WORD | OF_EASRC, "SUBA.W <ea>,An") + ENTRY(1001...100......, ..A+-DB.., OF_BYTE | OF_EADST, "SUB.B Dn,<ea>") + ENTRY(1001...101......, ..A+-DB.., OF_WORD | OF_EADST, "SUB.W Dn,<ea>") + ENTRY(1001...110......, ..A+-DB.., OF_LONG | OF_EADST, "SUB.L Dn,<ea>") + ENTRY(1001...111......, daA+-DBIP, OF_LONG | OF_EASRC, "SUBA.L <ea>,An") + ENTRY(0000010000......, d.A+-DB.., OF_BYTE | OF_EADST | OF_IMMB, "SUBI.B #x,<ea>") + ENTRY(0000010001......, d.A+-DB.., OF_WORD | OF_EADST | OF_IMMW, "SUBI.W #x,<ea>") + ENTRY(0000010010......, d.A+-DB.., OF_LONG | OF_EADST | OF_IMML, "SUBI.L #x,<ea>") + ENTRY(0101...100......, d.A+-DB.., OF_BYTE | OF_EADST, "SUBQ.B #x,<ea>") + ENTRY(0101...101......, daA+-DB.., OF_WORD | OF_EADST, "SUBQ.W #x,<ea>") + ENTRY(0101...110......, daA+-DB.., OF_LONG | OF_EADST, "SUBQ.L #x,<ea>") + ENTRY(1001...10000...., ........., OF_BYTE | OF_RARE, "SUBX.B") + ENTRY(1001...10100...., ........., OF_WORD | OF_RARE, "SUBX.W") + ENTRY(1001...11000...., ........., OF_LONG | OF_RARE, "SUBX.L") + ENTRY(0100100001000..., ........., OF_LONG | OF_RARE, "SWAP Dn") + ENTRY(0100101011......, d.A+-DB.., OF_BYTE | OF_EASRC | OF_RARE, "TAS <ea>") + ENTRY(010011100100...., ........., OF_RARE, "TRAP #x") + ENTRY(0100111001110110, ........., OF_RARE, "TRAPV") + ENTRY(0100101000......, d.A+-DB.., OF_BYTE | OF_EASRC, "TST.B <ea>") + ENTRY(0100101001......, d.A+-DB.., OF_WORD | OF_EASRC, "TST.W <ea>") + ENTRY(0100101010......, d.A+-DB.., OF_LONG | OF_EASRC, "TST.L <ea>") + ENTRY(0100111001011..., ........., OF_RARE, "UNLK") + ENTRY(0000001001111100, ........., OF_WORD | OF_IMMW | OF_RARE, "ANDI #x,SR") + ENTRY(0000101001111100, ........., OF_WORD | OF_IMMW | OF_RARE, "EORI #x,SR") + ENTRY(0100000011......, d.A+-DB.., OF_WORD | OF_EADST | OF_RARE, "MOVE SR,<ea>") + ENTRY(0100011011......, d.A+-DBIP, OF_WORD | OF_EASRC | OF_RARE, "MOVE <ea>,SR") + ENTRY(010011100110...., ........., OF_LONG | OF_RARE, "MOVE USP") + ENTRY(0000000001111100, ........., OF_WORD | OF_IMMW | OF_RARE, "ORI #x,SR") + ENTRY(0100111001110000, ........., OF_RARE, "RESET") + ENTRY(0100111001110011, ........., OF_RARE, "RTE") + ENTRY(0100111001110010, ........., OF_WORD | OF_IMMW | OF_RARE, "STOP #x") +}; + + +/*----------------------------------------------- + build_optable - build up the opcode table +-----------------------------------------------*/ + +static void build_optable(running_machine &machine) +{ + int opnum, inum; + + /* allocate and initialize the opcode table */ + optable = std::make_unique<optable_entry[]>(65536); + for (opnum = 0; opnum < 65536; opnum++) + { + optable[opnum].flags = OF_INVALID; + optable[opnum].string = nullptr; + } + + /* now iterate over entries in our intruction table */ + for (inum = 0; inum < std::size(instr_table); inum++) + { + const char *bitstring = instr_table[inum].bitstring; + const char *eastring = instr_table[inum].eastring; + const char *instring = instr_table[inum].instring; + uint32_t flags = instr_table[inum].flags; + uint8_t ea_allowed[64], ea2_allowed[64]; + int bitnum, step, eanum, ea2num; + uint16_t mask = 0, value = 0; + + /* build up the mask and value from the bitstring */ + for (bitnum = 0; bitnum < 16; bitnum++) + { + assert(bitstring[bitnum] == '0' || bitstring[bitnum] == '1' || bitstring[bitnum] == '.'); + mask <<= 1; + value <<= 1; + if (bitstring[bitnum] != '.') + { + mask |= 1; + value |= (bitstring[bitnum] == '1'); + } + } + + /* if we have an EA, fill in the EA bits */ + memset(ea_allowed, 0, sizeof(ea_allowed)); + if (flags & (OF_EASRC | OF_EADST)) + { + assert((mask & 0x003f) == 0); + assert(eastring[0] == 'd' || eastring[0] == '.'); + if (eastring[0] == 'd') memset(&ea_allowed[0x00], 1, 8); + assert(eastring[1] == 'a' || eastring[1] == '.'); + if (eastring[1] == 'a') memset(&ea_allowed[0x08], 1, 8); + assert(eastring[2] == 'A' || eastring[2] == '.'); + if (eastring[2] == 'A') memset(&ea_allowed[0x10], 1, 8); + assert(eastring[3] == '+' || eastring[3] == '.'); + if (eastring[3] == '+') memset(&ea_allowed[0x18], 1, 8); + assert(eastring[4] == '-' || eastring[4] == '.'); + if (eastring[4] == '-') memset(&ea_allowed[0x20], 1, 8); + assert(eastring[5] == 'D' || eastring[5] == '.'); + if (eastring[5] == 'D') memset(&ea_allowed[0x28], 1, 16); + assert(eastring[6] == 'B' || eastring[6] == '.'); + if (eastring[6] == 'B') memset(&ea_allowed[0x38], 1, 2); + assert(eastring[7] == 'I' || eastring[7] == '.'); + if (eastring[7] == 'I') ea_allowed[0x3c] = 1; + assert(eastring[8] == 'P' || eastring[8] == '.'); + if (eastring[8] == 'P') memset(&ea_allowed[0x3a], 1, 2); + step = 0x40; + } + else + { + assert(strcmp(eastring, ".........") == 0); + ea_allowed[0] = 1; + step = 1; + } + + /* if we're a move instruction, fill in the EA2 bits */ + memset(ea2_allowed, 0, sizeof(ea2_allowed)); + if (flags & OF_MOVE) + { + assert((mask & 0x0fc0) == 0); + memset(&ea2_allowed[0x00], 1, 8); + memset(&ea2_allowed[0x10], 1, 42); + step = 0x1000; + } + else + ea2_allowed[0] = 1; + + /* iterate over allowed EAs and fill in the opcode entries */ + for (ea2num = 0; ea2num < 64; ea2num++) + if (ea2_allowed[ea2num]) + for (eanum = 0; eanum < 64; eanum++) + if (ea_allowed[eanum]) + { + uint16_t eabits = ((ea2num & 0x38) << 3) | ((ea2num & 0x07) << 9) | eanum; + + /* iterate over opcode entries */ + for (opnum = 0; opnum <= mask; opnum += step) + if ((opnum & mask) == value) + { + int length = 1; + + /* skip if we've already populated */ + if (optable[opnum | eabits].flags != OF_INVALID) + continue; + + /* determine the length of the opcode */ + if (flags & OF_ISIZEMASK) + length += ((flags & OF_ISIZEMASK) == OF_IMML) ? 2 : 1; + if ((eanum >= 0x28 && eanum <= 0x38) || eanum == 0x3a || eanum == 0x3b) + length += 1; + else if (eanum == 0x39) + length += 2; + else if (eanum == 0x3c) + length += ((flags & OF_SIZEMASK) == OF_LONG) ? 2 : 1; + if ((ea2num >= 0x28 && ea2num <= 0x38) || ea2num == 0x3a || ea2num == 0x3b) + length += 1; + else if (ea2num == 0x39) + length += 2; + else if (ea2num == 0x3c) + length += ((flags & OF_SIZEMASK) == OF_LONG) ? 2 : 1; + + /* make sure we match the disassembler */ + #ifdef MAME_DEBUG + { + char dummybuffer[40]; + uint8_t instrbuffer[10]; + instrbuffer[0] = (opnum | eabits) >> 8; + instrbuffer[1] = (opnum | eabits); + dummybuffer[0] = 0; + assert(length == (m68k_disassemble_raw(dummybuffer, 0, instrbuffer, instrbuffer, M68K_CPU_TYPE_68000) & 0xff) / 2); + } + #endif + + /* set the value of the entry in the table */ + optable[opnum | eabits].flags = flags | (length << 28); + optable[opnum | eabits].string = instring; + } + } + } +} + + +/*----------------------------------------------- + validate_ea - determine whether an EA is + valid or not, and return the length +-----------------------------------------------*/ + +static int validate_ea(address_space &space, uint32_t pc, uint8_t modereg, const uint8_t *parambase, uint32_t flags) +{ + uint32_t addr; + int valid; + + /* switch off of the mode */ + switch ((modereg >> 3) & 7) + { + case 0: /* Dn -- always good */ + case 1: /* An -- always good */ + case 2: /* (An) -- always good */ + case 3: /* (An)+ -- always good */ + case 4: /* -(An) -- always good */ + return 0; + + case 5: /* (d16,An) -- always good, but odd displacements are a warning for word/long */ + if ((flags & OF_SIZEMASK) != OF_BYTE && (parambase[1] & 1) == 1) + return -1; + return 1; + + case 6: /* (d8,An,Xn) -- always good, but odd displacements are a warning for word/long */ + /* also look for invalid extension words */ + if ((parambase[0] & 7) != 0) + return 1000; + if ((flags & OF_SIZEMASK) != OF_BYTE && (parambase[1] & 1) == 1) + return -1; + return 1; + + case 7: + switch (modereg & 7) + { + case 0: /* (xxx).W -- make sure it is not odd for word/long */ + addr = (int16_t)((parambase[0] << 8) | parambase[1]); + valid = addr_is_valid(space, addr & 0xffffff, flags); + return (valid == 0) ? 1000 : (valid == 2) ? -1 : 1; + + case 1: /* (xxx).L -- make sure it is not odd for word/long, and make sure upper byte of addr is 0 */ + valid = addr_is_valid(space, (parambase[0] << 24) | (parambase[1] << 16) | (parambase[2] << 8) | parambase[3], flags); + return (valid == 0) ? 1000 : (valid == 2) ? -2 : 2; + + case 2: /* (d16,PC) -- make sure it is not odd for word/long */ + valid = addr_is_valid(space, pc + (int16_t)((parambase[0] << 8) | parambase[1]), flags); + return (valid == 0) ? 1000 : (valid == 2) ? -1 : 1; + + case 3: /* (d8,PC,Xn) -- odd displacements are a warning for word/long */ + if ((parambase[0] & 7) != 0) + return 1000; + if ((flags & OF_SIZEMASK) != OF_BYTE && (parambase[1] & 1) == 1) + return -1; + return 1; + + case 4: /* immediate -- check high byte if byte-sized */ + if ((flags & OF_SIZEMASK) == OF_BYTE && parambase[0] != 0) + return 1000; + return ((flags & OF_SIZEMASK) == SIZE_LONG) ? 2 : 1; + } + break; + } + + /* should never get here */ + assert(false); + return 0; +} + + +/*----------------------------------------------- + validate_opcode - validate an opcode up to + the length specified +-----------------------------------------------*/ + +static int validate_opcode(address_space &space, uint32_t pc, const uint8_t *opdata, int maxwords) +{ + uint32_t immvalue = 0; + int iffy = false; + int offset = 0; + uint16_t opcode; + uint32_t flags; + int oplength; + + assert(maxwords >= 1); + + /* extract the opcode and look it up in our table */ + opcode = (opdata[offset*2+0] << 8) | opdata[offset*2+1]; + flags = optable[opcode].flags; + oplength = flags >> 28; + + /* weed out invalid opcodes immediately */ + offset++; + if (flags == OF_INVALID) + return 0; + iffy = ((flags & OF_RARE) != 0); + + /* if we're done, or if we don't have enough words, stop now */ + if (offset == oplength || maxwords < oplength) + return iffy ? -oplength : oplength; + + /* if the opcode has an immediate, process that */ + if (flags & OF_ISIZEMASK) + { + int neededwords = ((flags & OF_ISIZEMASK) == OF_IMML) ? 2 : 1; + + /* extract the immediate value */ + immvalue = (opdata[offset*2+0] << 8) | opdata[offset*2+1]; + if ((flags & OF_ISIZEMASK) == OF_IMML) + immvalue = (immvalue << 16) | (opdata[offset*2+2] << 8) | opdata[offset*2+3]; + + /* if it's a byte immediate, ensure the upper bits are 0 (except for -1) */ + if ((flags & OF_ISIZEMASK) == OF_IMMB && immvalue > 0xff && immvalue != 0xffff) + return 0; + + /* if it's a bit immediate, ensure all but the lower 3 bits are 0 */ + if ((flags & OF_ISIZEMASK) == OF_IMMBIT) + { + /* registers can do up to 32 bits */ + if ((opcode & 0x3f) < 8) + { + if (immvalue > 31) + return 0; + } + + /* memory operands can do up to 8 bits */ + else + { + if (immvalue > 7) + return 0; + } + } + + /* advance past the immedate */ + offset += neededwords; + } + + /* if we're a branch, validate the immediate value */ + if (flags & OF_BRANCH) + { + int valid; + + /* first adjust the PC based on the size of the branch */ + pc += 2; + if ((flags & OF_SIZEMASK) == OF_BYTE) + pc += (int8_t)opcode; + else if ((flags & OF_SIZEMASK) == OF_WORD) + pc += (int16_t)immvalue; + else + pc += immvalue; + + /* if we're odd or out of range, fail */ + valid = pc_is_valid(space, pc, flags); + if (valid == 0) + return 0; + if (valid == 2) + iffy = true; + } + + /* process the EA, if present */ + if (flags & (OF_EASRC | OF_EADST)) + { + int modereg = opcode & 0x003f; + int ealen = validate_ea(space, pc + offset*2, modereg, &opdata[offset*2], flags); + + /* if the ea was invalid, forward that result */ + if (ealen == 1000) + return 0; + + /* if the ea was iffy, indicate that */ + if (ealen < 0) + { + ealen = -ealen; + iffy = true; + } + + /* advance past the ea */ + offset += ealen; + } + + /* process the move EA, if present */ + if (flags & OF_MOVE) + { + int modereg = ((opcode & 0x01c0) >> 3) | ((opcode & 0x0e00) >> 9); + int ealen = validate_ea(space, pc + offset*2, modereg, &opdata[offset*2], flags); + + /* if the ea was invalid, forward that result */ + if (ealen == 1000) + return 0; + + /* if the ea was iffy, indicate that */ + if (ealen < 0) + { + ealen = -ealen; + iffy = true; + } + + /* advance past the ea */ + offset += ealen; + } + + /* at this point we should be at the end */ + assert(offset == oplength); + return iffy ? -oplength : oplength; +} + +#endif diff --git a/attic/fddebug.h b/attic/fddebug.h new file mode 100644 index 00000000000..498d4e2ec68 --- /dev/null +++ b/attic/fddebug.h @@ -0,0 +1,5 @@ +// license:BSD-3-Clause +// copyright-holders:Aaron Giles + +void fd1094_regenerate_key(running_machine &machine); +void fd1094_init_debugging(running_machine &machine, const char *cpureg, const char *keyreg, const char *statreg, void (*changed)(running_machine &)); diff --git a/attic/jalmah.x68 b/attic/jalmah.x68 new file mode 100644 index 00000000000..18ee8be6488 --- /dev/null +++ b/attic/jalmah.x68 @@ -0,0 +1,147 @@ + ; license:LGPL-2.1+ + ; copyright-holders:Angelo Salese + ;***************************************************************** + ; Jaleco Mahjong code simulation snippets for 1st MCU games + ; + ; Games using this: + ; Urashima Mahjong + ; Mahjong Daireikai + ; Mahjong Channel Zoom-In + ; + ; For details @see jalmah.cpp + ; + ; +START: + ORG $0 ; palette code snippet (test mode & gameplay) + move.w #$1, $80016.l ; set priority number (for urashima) + move.w #$f, D0 ; set loop 1 +FetchNewPalette: + move.l A0, $100400.l ; save address to our local buffer (address currently points to an index of actual palette to transfer) + movea.l (A0), A0 ; read ROM location for the actual palette source + move.w #$f, D1 ; set loop 2 variable + bsr UploadPaletteChunk ; jump to uploading routine + movea.l $100400.l, A0 ; restore address index, increment by next address + adda.w #$4, A0 + dbra D0, FetchNewPalette + rts + +UploadPaletteChunk: + move.w (A0)+, (A1)+ ; copy palette source in ROM to palette RAM + dbra D1, UploadPaletteChunk + rts + + ORG $0800 ; sound code snippet + movem.l D1, -(A7) + move.w D0, D1 ; D0 is raw sound command, low byte is command number, everything else is banking and probably voice channel (unhandled) + ror.w #$8, D1 + and.w #$f, D1 ; take D1 as raw banking number + bsr CheckSoundZA + bsr CheckSoundBank + move.w #$8, $80040.l ; clear channel + bsr SoundStatus + andi.w #$3f, D0 ; take command number and write it to OKI port + ori.w #$80, D0 + move.w D0, $80040.l + bsr SoundStatus + move.w #$10, $80040.l ; play channel + movem.l (A7)+, D1 + rts +SoundStatus: + movem.l D0, -(A7) +ReadStatus: + move.w $80040.l, D0 ; check OKI voice status + andi.w #$1,D0 + bne ReadStatus + movem.l (A7)+, D0 + rts +; guess: special bits set in register D0 affect banking (oki can play up to 64 samples so bits 6 and 7 cannot be used) +; we simulate "ZA" writing but use the other bank register (jalmah can do both, cfr. ports $80018 and $8001a +CheckSoundZA: + btst #$6, D0 ; urashima BGM at start of game + beq NoZA1 + ror.w #$1, D1 ; shift one down + rts +NoZA1: + btst #$07, D0 ; mjzoomin BGM at start of game + beq NoZA2 + move.w #$8, D1 ; hardcode to bank 3 +NoZA2: + rts +CheckSoundBank: + cmpi.w #$1, D1 ; verify our raw D1 and set base bank accordingly + beq SetBank0 + cmpi.w #$2, D1 + beq SetBank1 + cmpi.w #$4, D1 + beq SetBank2 + move.w #$3, $80018.l + rts +SetBank0: + move.w #$0, $80018.l + rts +SetBank1: + move.w #$1, $80018.l + rts +SetBank2: + move.w #$2, $80018.l + rts + + ORG $1000 ; tile upload snippet +TileUploadStart: + move.w (A2)+, (A1)+ ; just take A2 source (tiles) to A1 destination VRAM + dbra D0, TileUploadStart + rts + + ORG $1800 ; (another) palette code snippet + movem.l D0-D7/A1-A6, -(A7) ; save stack (A0 intentionally updated by this snippet) + move.w #$f, D0 ; what's the difference here? Same as above but no hardcoded priority? + bsr FetchNewPalette + movem.l (A7)+, D0-D7/A1-A6 + rts + + ORG $2000 ; daireikai RNG snippet (guess) + move.w D5, $100400.l + move.w $f000c.l, D5 ; take current RNG number + add.l D6, D5 ; add D6 + andi.w #$3f, D5 + move.w D5, $f000c.l ; round it + move.w $100400.l, D5 + rts + ORG $2800 ; daireikai layer clearances + movem.l D0-D7/A0-A6, -(A7) + lea $90000.l, A6 ; layer 0 + move.w #$1fff, D1 + move.w #$00ff, D0 + bsr ClearLayer + movem.l (A7)+, D0-D7/A0-A6 + rts +ClearLayer: + move.w D0, (A6)+ + dbra D1, ClearLayer + rts + ORG $2880 + movem.l D0-D7/A0-A6, -(A7) + lea $94000.l, A6 ; layer 1 + move.w #$1fff, D1 + move.w #$00ff, D0 + bsr ClearLayer + movem.l (A7)+, D0-D7/A0-A6 + rts + ORG $2900 + movem.l D0-D7/A0-A6, -(A7) + lea $98000.l, A6 ; layer 2 + move.w #$1fff, D1 + move.w #$f0ff, D0 + bsr ClearLayer + movem.l (A7)+, D0-D7/A0-A6 + rts + + ORG $fffe ; extend binary ROM to 0x10000 in size + dc.w $ffff + END START + + +*~Font name~Courier New~ +*~Font size~10~ +*~Tab type~1~ +*~Tab size~4~ diff --git a/attic/jrcrypt.cpp b/attic/jrcrypt.cpp new file mode 100644 index 00000000000..0ca833ea0a7 --- /dev/null +++ b/attic/jrcrypt.cpp @@ -0,0 +1,530 @@ +// license:GPL-2.0+ +// copyright-holders:David Caldwell +/*************************************************************************** + + jrcrypt.cpp + + This file is not part of MAME. It is here to provide detailed + documentation of the encryption used by Jr. Pac Man ROMs. + + David Caldwell 6-1-97 + bug reports and comments to: + david@indigita.com + + This code is published under the GNU Public License. (GPL) + +***************************************************************************/ + +#include "emu.h" +#include <cctype> + +static int irq_mask; + +typedef uint16_t word; +typedef uint8_t byte; + +#define PreDecryptedRoms + +#ifndef PreDecryptedRoms +static int s0,s1,s2,s3; /* 1 bit registers inside decoder PAL */ +static uint8_t shadowROM[0xffff]; +static uint8_t used[0xFFFF]; +uint32_t numberUsed = 0; +#else +struct { + int count; + int value; +} Jr_PacManTable[] = { + { 0x00C1, 0x00 }, + { 0x0002, 0x80 }, + { 0x0004, 0x00 }, + { 0x0006, 0x80 }, + { 0x0003, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0004, 0x80 }, + { 0x9968, 0x00 }, + { 0x0001, 0x80 }, + { 0x0002, 0x00 }, + { 0x0001, 0x80 }, + { 0x0009, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0001, 0x80 }, + { 0x00AF, 0x00 }, + { 0x000E, 0x04 }, + { 0x0002, 0x00 }, + { 0x0004, 0x04 }, + { 0x001E, 0x00 }, + { 0x0001, 0x80 }, + { 0x0002, 0x00 }, + { 0x0001, 0x80 }, + { 0x0002, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0002, 0x80 }, + { 0x0083, 0x00 }, + { 0x0001, 0x04 }, + { 0x0001, 0x01 }, + { 0x0001, 0x00 }, + { 0x0002, 0x05 }, + { 0x0001, 0x00 }, + { 0x0003, 0x04 }, + { 0x0003, 0x01 }, + { 0x0002, 0x00 }, + { 0x0001, 0x04 }, + { 0x0003, 0x01 }, + { 0x0003, 0x00 }, + { 0x0003, 0x04 }, + { 0x0001, 0x01 }, + { 0x002E, 0x00 }, + { 0x0078, 0x01 }, + { 0x0001, 0x04 }, + { 0x0001, 0x05 }, + { 0x0001, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0001, 0x05 }, + { 0x0001, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0001, 0x05 }, + { 0x0001, 0x00 }, + { 0x01B0, 0x01 }, + { 0x0001, 0x00 }, + { 0x0002, 0x01 }, + { 0x00AD, 0x00 }, + { 0x0031, 0x01 }, + { 0x005C, 0x00 }, + { 0x0005, 0x01 }, + { 0x604E, 0x00 }, + { 0,0 } +}; +#endif + +MACHINE_RESET( jrpacman ) +{ +#ifndef PreDecryptedRoms + s0 = 1; + s1 = 1; + s2 = 0; + s3 = 0; + + memset(shadowROM,0,sizeof(shadowROM)); + memset(used,0,sizeof(used)); +#endif +} + + +#ifdef PreDecryptedRoms +unsigned jrpacman_decode_roms(int address) +{ + int i; + int cumulative=0; + for (i=0;Jr_PacManTable[i].count;i++) + { + cumulative += Jr_PacManTable[i].count; + if (cumulative > address) + return RAM[address] ^ Jr_PacManTable[i].value; + } + return RAM[address]; // this should never happen! +} +#else +static inline WordBit(word theWord, int theBit) +{ + return (theWord >> theBit)&1; +} +static inline ByteBit(byte theByte, int theBit) +{ + return (theByte >> theBit)&1; +} + +int jrpacman_romdecode(int offset); +int jrpacman_romdecodeA(int offset) +{ + jrpacman_romdecode(offset); +} + +int jrpacman_romdecodeB(int offset) +{ + jrpacman_romdecode(offset + 0x8000); +} + + +/**************************************************************************** + + This function would look suprisingly similiar to the source code to +the encoder pals, I imagine. I wrote is based on the jedec file that I +got from VideoDoctor. It needs to be run during the game, since the +logic is kind of weird and state based. This is slow. So you'll see +that I made it store its "decrypted" opcodes in another array. When I +ran the program and was satisfied that it had decrypted enough code, I +dumped this new array out into some ROM files. These ROM files are +effectively decrypted. But nobody else has them, so I'd have to upload +them to some ROM archive somewhere and hope for the best. Besides, If +I ever found a bug in them its not easy to upgrade every ROM archive +site out there. So I created a table that has the decrypted ROMs and +the encrypted ROMs xor-ed with each other. So if something wrong is +ever discovered , all that is needed to update is the table. Jr. Pac +only messes with 3 bits (d0, d2 and d7) so the table doesn't look too +excited. Also I run length encoded it so its not unwieldly. + + A lot of the functions that are ifdef-ed out here were debugging +functions that I used to help me during the decoding process. + + -David Caldwell + david@indigita.com + +***************************************************************************/ + +int jrpacman_romdecode(int offset) +{ + int addressBus = offset; + Z80_Regs Regs; + Z80_GetRegs(&Regs); + + { + int m1 = !Regs.M1;//active low (supposedly means opcode read) + + /* Pal 8C (16L8) */ + int pcbe = !(addressBus >= 0x0000 && addressBus <= 0x3fff || + addressBus >= 0x8000 && addressBus <= +0xdfff); + + int sop0 = !(addressBus >= 0x0000 && addressBus <= 0x001f || + addressBus >= 0x00e0 && addressBus <= +0x00ff || + addressBus >= 0x9a60 && addressBus <= +0x9a7f || + addressBus >= 0x9ac0 && addressBus <= +0x9adf || + addressBus >= 0x9b60 && addressBus <= +0x9b7f || + addressBus >= 0x9be0 && addressBus <= +0x9bff && m1); + + int sop1 = !(addressBus >= 0x9be0 && addressBus <= 0x9bff && m1 || + addressBus >= 0x9ca0 && addressBus <= +0x9cbf); + + int sop2 = !(addressBus >= 0x00c0 && addressBus <= 0x00df || + addressBus >= 0x9a40 && addressBus <= +0x9a5f); + + + /* Pal 9c (16r4) */ + int md0 = ByteBit(RAM[addressBus],0); + int md2 = ByteBit(RAM[addressBus],2); + int md7 = ByteBit(RAM[addressBus],7); + + int d0 = !( s0 && s1 && !md0 || + !s0 && s1 && md0 || + s0 && !s1 && !md0 || + !s0 && !s1 && !md2); + + int d2 = !( s0 && s1 && !md2 || + !s0 && s1 && !md2 || + s0 && !s1 && md2 || + !s0 && !s1 && !md0); + + int d7 = !( s2 && s3 || + !s2 && !md7); + + int pb1 = !( sop0 && s0 || + !sop0 && !s0); + + int ns0 = ( sop1 && s0 || + !sop1 && !s0 || + !sop0 && sop1); + + int ns1 = ( sop1 && s1 && !pb1 || + !sop1 && s1 && !pb1 || + sop1 && s1 && pb1 || + !sop1 && !s1 && pb1 || + !sop0 && sop1); + + int ns2 = ( sop0 && sop1 && s2 || + sop0 && !sop1 && s2 || + !sop0 && !sop1 && s2 || + sop0 && !sop2); + + int ns3 = ( !md7 ); + +// DebugPrint("%04x: %02x & %02x | %02x = %02x",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) | (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) | (d2<<2) | (d7<<7)); +/* printf("%04x: %02x & %02x | %02x = %02x\n",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) | (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) | (d2<<2) | (d7<<7)); + {static int i=0; + if (i++>100) + { + while (getchar()!='\n') + {} + }}*/ + { + int temp= ((int)RAM[addressBus] & 0x7A) | ((d7<<7) | (d2<<2) | (d0)); + +// if (Z80_Trace==1) + if (!used[addressBus]) + { + used[addressBus]=1; + shadowROM[addressBus] = temp; + numberUsed++; + } + else + { + if (shadowROM[addressBus] != temp) + DebugPrint("Address: %04x translates to 2 different values!!!! (%02x and %02x)",addressBus,shadowROM[addressBus],temp); + } + + + if (Z80_Trace==1) + { + static last = 0; + if (last + 30 <= TickCount()) /* print bnanner if we havent been called in half a second */ + printf("m1 sop0 sop1 sop2 pcbe md7 md2 md0 d7 d2 d0 pb1 s0 s1 s2 s3 ns0 ns1 ns2 ns3\n"); + last = TickCount(); + printf("%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d ", + m1, sop0,sop1,sop2,pcbe, md7, md2, md0, +d7, d2, d0, pb1, s0, s1, s2, s3, ns0, ns1, ns2, ns3); + printf("%04x: %02x & %02x | %02x = %02x\n",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) | (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) | (d2<<2) | (d7<<7)); + Z80_Trace = 1; /* stop it if it was running for a count */ + } + + /* latch new flip flops on rising edge of pcbe */ + if (!pcbe) + { + s0 = ns0; + s1 = ns1; + s2 = ns2; + s3 = ns3; + } + return temp; + } + } +} + +int Z80_Trace=0; + +void jr_monitor() +{ + int i; + int encrypted=0; + //int last_used=-1; + int unmapped_encrypted=0; + int unmapped=0; + printf("statistics: \n"); + printf(" Successfully mapped: %d\n",numberUsed); + for (i=0;i<0xe000;i=(i==0x4000?0x8000:i+1)) /* skip hole where +hardware and RAM is */ + { + if (used[i]) + { + if (shadowROM[i] != RAM[i]) + encrypted = 1; + else + encrypted = 0; + //last_used = i; + } + else + { + if (encrypted) + unmapped_encrypted++; + else + unmapped++; + } + } + printf(" Non mapped, Probably not encrypted: %d\n",unmapped); + printf(" Non mapped, but Probably encrypted: %d\n",unmapped_encrypted); + + while (1) + { + void write_rom_section(char *prefix,char *suffix,int +start,int end); + char c; + printf(" Enter D to Merge mapped and unmapped and dump to rom file,\n"); + printf(" Enter Q to quit.\n"); + c=tolower(getchar()); + while (getchar()!='\n') {} + if (c=='q') + return; + if (c=='d') + { + char line[100],*l; + //int i; + printf("Enter file prefix (files will be named 'prefix'.8d 'prefix'.8e, etc.\n"); + gets(line); + // kill newline: + for (l=line;*l!='\n' && *l!='\0';l++) + {} + *l = '\0'; + + write_rom_section(line,".8d",0x0000,0x2000); + write_rom_section(line,".8e",0x2000,0x4000); + write_rom_section(line,".8h",0x8000,0xa000); + write_rom_section(line,".8j",0xa000,0xc000); + write_rom_section(line,".8k",0xc000,0xe000); + } + } +} + +void write_rom_section(char *prefix,char *suffix,int start,int end) +{ + FILE *out; + char file[100]; + int i; + + strcpy(file,prefix); + strcat(file,suffix); + out = fopen(file,"wb"); + for (i=start;i<end;i++) + if (used[i]) + putc(shadowROM[i],out); + else + putc(RAM[i],out); + fclose(out); +} +#endif + +void jrpacman_interrupt_mask_w(uint8_t data) +{ + irq_mask = data; +} + + + +/*************************************************************************** + + Interrupt handler. This function is called at regular intervals + (determined by IPeriod) by the CPU emulation. + +***************************************************************************/ + +static int IntVector = 0xff; /* Here we store the interrupt vector, if +the code performs */ + /* an OUT to port $0. Not +all games do it: many use */ + /* Interrupt Mode 1, which +doesn't use an interrupt vector */ + /* (see Z80.c for details). */ + +INTERRUPT_GEN( jrpacman_interrupt ) +{ + irq0_line_hold(device); +} + + + +/*************************************************************************** + + The Pac Man machine uses OUT to port $0 to set the interrupt vector, so + we have to remember the value passed. + +***************************************************************************/ +void jrpacman_out(byte Port,byte Value) +{ + /* OUT to port $0 is used to set the interrupt vector */ + if (Port == 0) IntVector = Value; +} + +#if 0 +/**************************************************************************** +What follows is the program I used to create the JrPacMan_Table[] array at +the top of this file. It is included here for completeness. +***************************************************************************/ + + +// CreateJrDecodeTable.c +// +// Copyright David Caldwell +// This program is published under the GNU Public License. +// +// Comments, questions to: david@indigita.com + +#include <cstdio> + +typedef uint8_t byte; + +void CreateJrDecodeTable(byte *x, int length); +void Load(char *name,byte *buffer,int from, int length); + +byte encrypted[0x10000],decrypted[0x10000]; +byte xored[0x10000]; +void main() +{ + int i; + + Load("jr8d",encrypted,0x0000,0x2000); + Load("jr8e",encrypted,0x2000,0x2000); + Load("jr8h",encrypted,0x8000,0x2000); + Load("jr8j",encrypted,0xA000,0x2000); + Load("jr8k",encrypted,0xC000,0x2000); + + Load("1.8d",decrypted,0x0000,0x2000); + Load("1.8e",decrypted,0x2000,0x2000); + Load("1.8h",decrypted,0x8000,0x2000); + Load("1.8j",decrypted,0xA000,0x2000); + Load("1.8k",decrypted,0xC000,0x2000); + + for (i=0;i<0x10000;i++) + xored[i] = encrypted[i] ^ decrypted[i]; + + CreateJrDecodeTable(xored,0x10000); +} + +void Load(char *name,byte *buffer,int from, int length) +{ +/* + emu_file file(options, nullptr, OPEN_FLAG_READ); + osd_file::error filerr = file.open(name); + if (filerr != osd_file::error::NONE) + return; + while (length--) + buffer[from++]=file->getc(); +*/ +} + +void CreateJrDecodeTable(byte *x, int length) +{ + int i=0; + byte last = 0; + int count = 0; + + printf( "struct {\n" + " int count;\n" + " int value;\n" + "} Jr_PacManTable[] = {\n"); + + goto first; + + for (i=0;i<length;i++) + { + if (x[i] != last) + { + printf(" { 0x%04X, 0x%02X },\n",count,last); + count = 0; + } +first: + last = x[i]; + count++; + } + + printf(" { 0x%04X, 0x%02X },\n",count,last); + printf( " { 0,0 }\n" + "};\n"); +} +#endif diff --git a/attic/opwolf_cchip.txt b/attic/opwolf_cchip.txt new file mode 100644 index 00000000000..f56ac5242d7 --- /dev/null +++ b/attic/opwolf_cchip.txt @@ -0,0 +1,1228 @@ +Operation Wolf C-Chip Protection simulation +=========================================== + +The below simulation was replaced by emulating the actual cchip using an +extracted eprom image. The information previously contained in the MAME driver +is contained below for documentation purposes. + +Start of original notes and simulation below. + + +*************************************************************************** +File: mame/machine/opwolf.cpp +*************************************************************************** + + + Operation Wolf C-Chip Protection + ================================ + + The C-Chip (Taito TC0030CMD) is an unidentified mask programmed + microcontroller of some sort with 64 pins used for copy protection. + It probably has about 2k of ROM and 8k of RAM. The simulation in this file + is verified from the unprotected prototype game and the observed behaviour + of the real pcb running. It should give 100% accurate gameplay. The bootleg + Operation Wolf uses a Z80 and custom program to replace the c-chip. However + it's clear that bootlegger done the minimum to make the game work, with both + major and minor differences to the original game, which are outlined below. + + Operation Wolf has interesting software architecture. Unlike most games of this + era which have a simple main loop and linear code flow, Operation Wolf + implements a co-operative threading model where routines run in 68K user mode + until giving up their timeslice and a supervisor mode scheduler picks the next + thread to run. There are 32 thread slots, and each enemy in game run as its + own thread/object as well as a thread for coins, scrolling the level, level + specific gameplay and so on. The code is very robust when creating threads, + for example if there are no free slots, the creating thread just spins until + a slot frees up. The rest of the game just keeps on playing in the background. + Another interesting detail is that a thread can give up it's timeslice for more + than 1 frame - this makes it really easy to implement timed events. The 'WARNING' + text at the end of level 2 is handled by a thread that prints to screen, then just + waits a second before spawning the boss enemy thread. + + Each level in the game implements its own logic thread and often sub-threads - + this is the major difference between the protected game and the bootleg - the bootleg + mostly implements the parts that are generic between all levels rather than all of + the details. The biggest single area the bootleg did not implement revolves + around location 0x5f in the shared c-chip RAM. The original code sets up a thread + that just waits for this value to become non-zero. It then jumps to a set of + functions defined in a look-up table (that can then spawn further threads). There + are 10 non-null functions tied to this routine. + + 1: Enemy spawn for level 7 (first 'Located' cut-scene) + 2: Enemy spawn for level 8 (second 'Located' cut-scene) - zoom in helicopters + 3: Enemy spawn for level 9 (third 'Located' cut-scene) + 4: Boss & hostage sequence for level 2 + 5: Enemy spawn when less than 45 enemies in level 2 (paratrooper drop-down) + 6: Enemy spawn when less than 25 enemies in level 2 + 7: Enemy spawn when 0 men left in levels 2,4,5,6 + 8: Enemy spawn when 0 men left in level 3 + 9: Enemy spawn when 0 men left in level 1 + 10: Special explosion animation when level 4 (Powder Dump) is completed + + The bootleg also misses some other details, for example in level 5 the c-chip + sets a flag when all men are destroyed (not vehicles) and this triggers the 68K + to scroll the screen vertically to focus on the remaining helicopter enemies. + + The 'Enemy has located you' cut-scenes appear 'randomly' between levels in the + original game, but are deliberately disabled in the bootleg. The exact formula + for determining if the cut-scene appears is '(frameCount & levelNumber)==0'. + See code at 0x2D68 for this logic. + + + Interesting memory locations shared by cchip/68k: + + 0a/xx - copy of 3a0000 + 28/14 - dip switch A (written by 68k at start) + 2a/15 - dip switch B (written by 68k at start) + 2c/ ??? (mapped to $982,A5) [word] in prototype) + 2e/ (mapped to $984,A5) [word] in prototype) + 58/2c m_cchip_ram[0x2c] = 0x31; + ee/77 m_cchip_ram[0x77] = 0x05; + 4a/25 m_cchip_ram[0x25] = 0x0f; + 4c/26 m_cchip_ram[0x26] = 0x0b; + 36/1b - Current level number (1-6) + 38/1c - Number of men remaining in level + 3c/1e - Number of helicopters remaining in level + 3e/1f - Number of tanks remaining in level + 40/20 - Number of boats remaining in level + 42/21 - Hostages in plane (last level) + 44/22 - Hostages remaining (last level)/Hostages saved (2nd last level) + 4e/27 - Set to 1 when final boss is destroyed + 64/32 - Set to 1 by cchip when level complete (no more enemies remaining) + 68/34 - Game state (0=attract mode, 1=intro, 2=in-game, 3=end-screen) + 69/xx - variable mapped from ($980,A5) [byte] in prototype + 6B/xx - variable mapped from ($981,A5) [byte] in prototype + A6/xx - variable mapped from ($d6e,A5) [word] in prototype + A8/54 - ? + xx/51/52 - Used by cchip to signal change in credit level to 68k + xx/53 - Credit count + EA/75 - Set to 1 to trigger end of game boss + EC/76 - used near above + xx/7a - Used to trigger level data select command + + Notes on bootleg c-chip compared to original: + Bootleg cchip forces english language mode + Bootleg forces round 4 in attract mode + Bootleg doesn't support service switch + If you die after round 6 then the bootleg fails to reset the difficulty + for the next game. + The bootleg does not contain data for the 3 mini-levels ('Enemy has located you'), + instead it prevents them running by writing 0 to location 70 in the shared memory. + The bootleg does not play the special powder magazine (level 4) animation. + The bootleg does not vertically scroll the screen when all men killed in level 5 + The bootleg does not update the enemy spawn tables at various points. + + Notes by bmcphail@vcmame.net + + + + +/* Select how coinage data is initialised in opwolf_cchip_data_w : 0 = user-defined in function - 1 = automatic */ +#define OPWOLF_READ_COINAGE_FROM_ROM 1 + +/* List of possible regions */ +enum { + OPWOLF_REGION_BAD=0, + OPWOLF_REGION_JAPAN, + OPWOLF_REGION_US, + OPWOLF_REGION_WORLD, + OPWOLF_REGION_OTHER +}; + +static const uint16_t level_data_00[] = { + 0x0480, 0x1008, 0x0300, 0x5701, 0x0001, 0x0010, + 0x0480, 0x1008, 0x0300, 0x5701, 0x0001, 0x002b, + 0x0780, 0x0009, 0x0300, 0x4a01, 0x0004, 0x0020, + 0x0780, 0x1208, 0x0300, 0x5d01, 0x0004, 0x0030, + 0x0780, 0x0209, 0x0300, 0x4c01, 0x0004, 0x0038, + 0x0780, 0x0309, 0x0300, 0x4d01, 0x0004, 0x0048, + 0x0980, 0x1108, 0x0300, 0x5a01, 0xc005, 0x0018, + 0x0980, 0x0109, 0x0300, 0x4b01, 0xc005, 0x0028, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x8006, 0x0004, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x8006, 0x8002, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x8006, 0x0017, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x8006, 0x8015, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x0007, 0x0034, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x0007, 0x8032, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x8006, 0x803e, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x8006, 0x803d, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x0008, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x000b, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x001b, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x001e, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x8007, 0x0038, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x8007, 0x003b, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x8042, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x8045, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x800b, 0x8007, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x800b, 0x801a, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x000c, 0x8037, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x800b, 0x0042, + 0x0c80, 0xd04b, 0x0000, 0xf301, 0x8006, 0x8009, + 0x0c80, 0xd04b, 0x0000, 0xf301, 0x8006, 0x801c, + 0x0c80, 0xd04b, 0x0000, 0xf301, 0x8006, 0x0044, + 0x0c80, 0x030b, 0x0000, 0xf401, 0x0008, 0x0028, + 0x0c80, 0x030b, 0x0000, 0xf401, 0x0008, 0x804b, + 0x0c00, 0x040b, 0x0000, 0xf501, 0x0008, 0x8026, + 0xffff +}; + +static const uint16_t level_data_01[] = { + 0x0780, 0x0209, 0x0300, 0x4c01, 0x0004, 0x0010, + 0x0780, 0x0209, 0x0300, 0x4c01, 0x4004, 0x0020, + 0x0780, 0x0309, 0x0300, 0x4d01, 0xe003, 0x0030, + 0x0780, 0x0309, 0x0300, 0x4d01, 0x8003, 0x0040, + 0x0780, 0x0209, 0x0300, 0x4c01, 0x8004, 0x0018, + 0x0780, 0x0309, 0x0300, 0x4d01, 0xc003, 0x0028, + 0x0b80, 0x000b, 0x0000, 0x0b02, 0x8009, 0x0029, + 0x0b80, 0x0409, 0x0000, 0x0f02, 0x8008, 0x8028, + 0x0b80, 0x040a, 0x0000, 0x3502, 0x000a, 0x8028, + 0x0b80, 0x050a, 0x0000, 0x1002, 0x8006, 0x8028, + 0x0b80, 0x120a, 0x0000, 0x3602, 0x0008, 0x004d, + 0x0b80, 0x120a, 0x0000, 0x3602, 0x0008, 0x004f, + 0x0b80, 0x120a, 0x0000, 0x3602, 0x0008, 0x0001, + 0x0b80, 0x120a, 0x0000, 0x3602, 0x0008, 0x0003, + 0x0b80, 0x130a, 0x0000, 0x3a02, 0x0007, 0x0023, + 0x0b80, 0x130a, 0x0000, 0x3a02, 0x0007, 0x8025, + 0x0b80, 0x130a, 0x0000, 0x3a02, 0x8009, 0x0023, + 0x0b80, 0x130a, 0x0000, 0x3a02, 0x8009, 0x8025, + 0x0b80, 0x140a, 0x0000, 0x3e02, 0x0007, 0x000d, + 0x0b80, 0x140a, 0x0000, 0x3e02, 0x0007, 0x800f, + 0x0b80, 0x000b, 0x0000, 0x0102, 0x0007, 0x804e, + 0x0b80, 0xd24b, 0x0000, 0x0302, 0x0007, 0x000e, + 0x0b80, 0x000b, 0x0000, 0x0402, 0x8006, 0x0020, + 0x0b80, 0xd34b, 0x0000, 0x0502, 0x8006, 0x0024, + 0x0b80, 0x000b, 0x0000, 0x0602, 0x8009, 0x0001, + 0x0b80, 0xd44b, 0x0000, 0x0702, 0x800b, 0x800b, + 0x0b80, 0xd54b, 0x0000, 0x0802, 0x800b, 0x000e, + 0x0b80, 0x000b, 0x0000, 0x0902, 0x800b, 0x0010, + 0x0b80, 0x000b, 0x0000, 0x0a02, 0x0009, 0x0024, + 0x0b80, 0xd64b, 0x0000, 0x0c02, 0x000c, 0x8021, + 0x0b80, 0x000b, 0x0000, 0x0d02, 0x000c, 0x0025, + 0x0b80, 0x000b, 0x0000, 0x0e02, 0x8009, 0x004e, + 0x0b80, 0x000b, 0x0300, 0x4e01, 0x8006, 0x8012, + 0x0b80, 0x000b, 0x0300, 0x4e01, 0x0007, 0x8007, + 0xffff +}; + +static const uint16_t level_data_02[] = { + 0x0480, 0x000b, 0x0300, 0x4501, 0x0001, 0x0018, + 0x0480, 0x000b, 0x0300, 0x4501, 0x2001, 0x0030, + 0x0780, 0x1208, 0x0300, 0x5d01, 0x0004, 0x0010, + 0x0780, 0x1208, 0x0300, 0x5d01, 0x2004, 0x001c, + 0x0780, 0x1208, 0x0300, 0x5d01, 0xe003, 0x0026, + 0x0780, 0x1208, 0x0300, 0x5d01, 0x8003, 0x0034, + 0x0780, 0x1208, 0x0300, 0x5d01, 0x3004, 0x0040, + 0x0780, 0x010c, 0x0300, 0x4601, 0x4004, 0x0022, + 0x0780, 0x010c, 0x0300, 0x4601, 0x6004, 0x0042, + 0x0780, 0x000c, 0x0500, 0x7b01, 0x800b, 0x0008, + 0x0780, 0x010c, 0x0300, 0x4601, 0x2004, 0x0008, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0b80, 0x000b, 0x0000, 0x1902, 0x000b, 0x0004, + 0x0b80, 0x000b, 0x0000, 0x1a02, 0x0009, 0x8003, + 0x0b80, 0x000b, 0x0000, 0x1902, 0x000b, 0x000c, + 0x0b80, 0x000b, 0x0000, 0x1a02, 0x0009, 0x800b, + 0x0b80, 0x000b, 0x0000, 0x1902, 0x000b, 0x001c, + 0x0b80, 0x000b, 0x0000, 0x1a02, 0x0009, 0x801b, + 0x0b80, 0x000b, 0x0000, 0x1902, 0x000b, 0x002c, + 0x0b80, 0x000b, 0x0000, 0x1a02, 0x0009, 0x802b, + 0x0b80, 0x000b, 0x0000, 0x1902, 0x000b, 0x0044, + 0x0b80, 0x000b, 0x0000, 0x1a02, 0x0009, 0x8043, + 0x0b80, 0x000b, 0x0000, 0x1902, 0x000b, 0x004c, + 0x0b80, 0x000b, 0x0000, 0x1a02, 0x0009, 0x804b, + 0x0b80, 0x020c, 0x0300, 0x4801, 0xa009, 0x0010, + 0x0b80, 0x020c, 0x0300, 0x4801, 0xa009, 0x0028, + 0x0b80, 0x020c, 0x0300, 0x4801, 0xa009, 0x0036, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0xffff +}; + +static const uint16_t level_data_03[] = { + 0x0480, 0x000b, 0x0300, 0x4501, 0x0001, 0x0018, + 0x0480, 0x000b, 0x0300, 0x4501, 0x2001, 0x002b, + 0x0780, 0x010c, 0x0300, 0x4601, 0x0004, 0x000d, + 0x0780, 0x000c, 0x0500, 0x7b01, 0x800b, 0x0020, + 0x0780, 0x010c, 0x0300, 0x4601, 0x2004, 0x0020, + 0x0780, 0x010c, 0x0300, 0x4601, 0x8003, 0x0033, + 0x0780, 0x010c, 0x0300, 0x4601, 0x0004, 0x003c, + 0x0780, 0x010c, 0x0300, 0x4601, 0xd003, 0x0045, + 0x0780, 0x000c, 0x0500, 0x7b01, 0x900b, 0x0041, + 0x0780, 0x010c, 0x0300, 0x4601, 0x3004, 0x0041, + 0x0b80, 0x020c, 0x0300, 0x4801, 0x0007, 0x0000, + 0x0b80, 0x410a, 0x0000, 0x2b02, 0xe006, 0x4049, + 0x0b80, 0x020c, 0x0300, 0x4801, 0x8007, 0x000b, + 0x0b80, 0x000b, 0x0000, 0x2702, 0x800a, 0x8005, + 0x0b80, 0x000b, 0x0000, 0x1e02, 0x0008, 0x800e, + 0x0b80, 0x000b, 0x0000, 0x1f02, 0x8007, 0x0011, + 0x0b80, 0x000b, 0x0000, 0x2802, 0x000b, 0x0012, + 0x0b80, 0x000b, 0x0000, 0x2002, 0x0007, 0x8015, + 0x0b80, 0x000b, 0x0000, 0x2102, 0x0007, 0x801b, + 0x0b80, 0x000b, 0x0000, 0x2902, 0x800a, 0x001a, + 0x0b80, 0x000b, 0x0000, 0x2202, 0x8007, 0x001e, + 0x0b80, 0x000b, 0x0000, 0x1e02, 0x0008, 0x0025, + 0x0b80, 0x000b, 0x0000, 0x2302, 0x8007, 0x802c, + 0x0b80, 0x000b, 0x0000, 0x2802, 0x000b, 0x8028, + 0x0b80, 0x020c, 0x0300, 0x4801, 0x0007, 0x0030, + 0x0b80, 0x400a, 0x0000, 0x2e02, 0x4007, 0x002d, + 0x0b80, 0x000b, 0x0000, 0x2702, 0x800a, 0x8035, + 0x0b80, 0x020c, 0x0300, 0x4801, 0x8007, 0x0022, + 0x0b80, 0x000b, 0x0000, 0x2402, 0x8007, 0x0047, + 0x0b80, 0x000b, 0x0000, 0x2a02, 0x800a, 0x004b, + 0x0b80, 0x000b, 0x0000, 0x2502, 0x0007, 0x804b, + 0x0b80, 0x000b, 0x0000, 0x2602, 0x0007, 0x004e, + 0x0b80, 0x020c, 0x0300, 0x4801, 0x0007, 0x8043, + 0x0b80, 0x020c, 0x0300, 0x4801, 0x8007, 0x803d, + 0xffff +}; + +static const uint16_t level_data_04[] = { + 0x0780, 0x0209, 0x0300, 0x4c01, 0x0004, 0x0010, + 0x0780, 0x0209, 0x0300, 0x4c01, 0x4004, 0x0020, + 0x0780, 0x0309, 0x0300, 0x4d01, 0xe003, 0x0030, + 0x0780, 0x0309, 0x0300, 0x4d01, 0x8003, 0x0040, + 0x0780, 0x0209, 0x0300, 0x4c01, 0x8004, 0x0018, + 0x0780, 0x0309, 0x0300, 0x4d01, 0xc003, 0x0028, + 0x0780, 0x000b, 0x0300, 0x5601, 0x8004, 0x0008, + 0x0780, 0x000b, 0x0300, 0x5601, 0x8004, 0x0038, + 0x0780, 0x000b, 0x0300, 0x5501, 0x8004, 0x0048, + 0x0980, 0x0509, 0x0f00, 0x0f01, 0x4005, 0x4007, + 0x0980, 0x0509, 0x0f00, 0x0f01, 0x4005, 0x4037, + 0x0b80, 0x030a, 0x0000, 0x1302, 0x8006, 0x0040, + 0x0b80, 0x110a, 0x0000, 0x1502, 0x8008, 0x8048, + 0x0b80, 0x110a, 0x0000, 0x1502, 0x8008, 0x8049, + 0x0b80, 0x000b, 0x0000, 0xf601, 0x0007, 0x8003, + 0x0b80, 0x000b, 0x0000, 0xf701, 0x0007, 0x0005, + 0x0b80, 0x000b, 0x0000, 0xf901, 0x0007, 0x8008, + 0x0b80, 0x000b, 0x0000, 0xf901, 0x0007, 0x0010, + 0x0b80, 0x000b, 0x0000, 0xfa01, 0x0007, 0x8013, + 0x0b80, 0x000b, 0x0000, 0xf801, 0x800b, 0x800b, + 0x0b80, 0x000b, 0x0000, 0x0002, 0x800b, 0x801a, + 0x0b80, 0x000b, 0x0000, 0xf901, 0x0007, 0x8017, + 0x0b80, 0x000b, 0x0000, 0xfa01, 0x0007, 0x001b, + 0x0b80, 0x000b, 0x0000, 0xf801, 0x800b, 0x0013, + 0x0b80, 0x000b, 0x0000, 0x4202, 0x800b, 0x0016, + 0x0b80, 0x000b, 0x0000, 0xfb01, 0x8007, 0x8020, + 0x0b80, 0x000b, 0x0000, 0xf601, 0x0007, 0x8023, + 0x0b80, 0x000b, 0x0000, 0x4202, 0x800b, 0x800e, + 0x0b80, 0x000b, 0x0000, 0x4302, 0x800b, 0x801d, + 0x0b80, 0x000b, 0x0000, 0xf701, 0x0007, 0x0025, + 0x0b80, 0x000b, 0x0000, 0xfd01, 0x8006, 0x003f, + 0x0b80, 0x000b, 0x0000, 0xfe01, 0x0007, 0x0046, + 0x0b80, 0x000b, 0x0000, 0xff01, 0x8007, 0x8049, + 0x0b80, 0x000b, 0x0000, 0xfc01, 0x8009, 0x0042, + 0xffff +}; + +static const uint16_t level_data_05[] = { + 0x0480, 0x1008, 0x0300, 0x5701, 0x0001, 0x0010, + 0x0480, 0x1008, 0x0300, 0x5701, 0x0001, 0x002b, + 0x0780, 0x0009, 0x0300, 0x4a01, 0x0004, 0x0020, + 0x0780, 0x1208, 0x0300, 0x5d01, 0x0004, 0x0030, + 0x0780, 0x0209, 0x0300, 0x4c01, 0x0004, 0x0038, + 0x0780, 0x0309, 0x0300, 0x4d01, 0x0004, 0x0048, + 0x0980, 0x1108, 0x0300, 0x5a01, 0xc005, 0x0018, + 0x0980, 0x0109, 0x0300, 0x4b01, 0xc005, 0x0028, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x8006, 0x0004, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x8006, 0x8002, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x8006, 0x0017, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x8006, 0x8015, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x0007, 0x0034, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x0007, 0x8032, + 0x0b80, 0x020a, 0x0000, 0x6401, 0x8006, 0x803e, + 0x0c80, 0x010b, 0x0000, 0xf201, 0x8006, 0x803d, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x0008, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x000b, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x001b, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x001e, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x8007, 0x0038, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x8007, 0x003b, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x8042, + 0x0b80, 0x100a, 0x0000, 0x6001, 0x0007, 0x8045, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x800b, 0x8007, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x800b, 0x801a, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x000c, 0x8037, + 0x0c80, 0x000b, 0x0000, 0xf101, 0x800b, 0x0042, + 0x0c80, 0xd04b, 0x0000, 0xf301, 0x8006, 0x8009, + 0x0c80, 0xd04b, 0x0000, 0xf301, 0x8006, 0x801c, + 0x0c80, 0xd04b, 0x0000, 0xf301, 0x8006, 0x0044, + 0x0c80, 0x030b, 0x0000, 0xf401, 0x0008, 0x0028, + 0x0c80, 0x030b, 0x0000, 0xf401, 0x0008, 0x804b, + 0x0c00, 0x040b, 0x0000, 0xf501, 0x0008, 0x8026, + 0xffff +}; + +static const uint16_t level_data_06[] = { + 0x0000, 0x1008, 0x0300, 0x5701, 0x0001, 0x0010, + 0x0000, 0x1008, 0x0300, 0x5701, 0x0001, 0x002b, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0700, 0x0009, 0x0300, 0x4a01, 0x0004, 0x0020, + 0x0700, 0x1208, 0x0300, 0x5d01, 0x0004, 0x0030, + 0x0700, 0x0209, 0x0300, 0x4c01, 0x0004, 0x0038, + 0x0700, 0x0309, 0x0300, 0x4d01, 0x0004, 0x0048, + 0x0900, 0x1108, 0x0300, 0x5a01, 0xc005, 0x0018, + 0x0900, 0x0109, 0x0300, 0x4b01, 0xc005, 0x0028, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0980, 0xdb4c, 0x0000, 0x3202, 0x0006, 0x0004, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0x0000, 0x000b, 0x0000, 0x0000, 0x0018, 0x0000, + 0xffff +}; + +static const uint16_t level_data_07[] = { + 0x0480, 0x000b, 0x0300, 0x4501, 0x0001, 0x0001, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0780, 0x0109, 0x0300, 0x4a01, 0x0004, 0x0004, + 0x0780, 0x0009, 0x0300, 0x4a01, 0x0004, 0x000d, + 0x0780, 0x000c, 0x0500, 0x7b01, 0x000c, 0x0005, + 0x0780, 0x000c, 0x0540, 0x7b01, 0x000c, 0x0005, + 0x0780, 0x010c, 0x0300, 0x4601, 0x0005, 0x0005, + 0x0780, 0x000c, 0x0500, 0x7b01, 0x800b, 0xc00d, + 0x0780, 0x000c, 0x0540, 0x7b01, 0x800b, 0xc00d, + 0x0780, 0x010c, 0x0300, 0x4601, 0x8004, 0xc00d, + 0x0900, 0x0109, 0x0340, 0x4b01, 0x2006, 0x400c, + 0x0780, 0x020c, 0x0300, 0x4801, 0x8007, 0x0008, + 0x0780, 0x020c, 0x0300, 0x4801, 0x4007, 0xc00b, + 0x0980, 0x0109, 0x0300, 0x4b01, 0xc006, 0x8007, + 0x0980, 0x0109, 0x0300, 0x4b01, 0x8007, 0x8008, + 0x0980, 0x0109, 0x0300, 0x4b01, 0xc006, 0x800c, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0xffff +}; + +static const uint16_t level_data_08[] = { + 0xffff +}; + +static const uint16_t level_data_09[] = { + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0780, 0x0109, 0x0300, 0x4a01, 0x8003, 0x8003, + 0x0780, 0x0009, 0x0300, 0x4a01, 0x0004, 0x800e, + 0x0780, 0x000c, 0x0500, 0x7b01, 0x000c, 0x0005, + 0x0780, 0x000c, 0x0540, 0x7b01, 0x000c, 0x0005, + 0x0780, 0x010c, 0x0300, 0x4601, 0x0005, 0x0005, + 0x0780, 0x000c, 0x0500, 0x7b01, 0x800b, 0xc00d, + 0x0780, 0x000c, 0x0540, 0x7b01, 0x800b, 0xc00d, + 0x0780, 0x010c, 0x0300, 0x4601, 0x8004, 0xc00d, + 0x0900, 0x0109, 0x0340, 0x4b01, 0x2006, 0x400c, + 0x0780, 0x020c, 0x0300, 0x4801, 0x8007, 0x0008, + 0x0780, 0x020c, 0x0300, 0x4801, 0x4007, 0xc00b, + 0x0980, 0x0109, 0x0300, 0x4b01, 0xc006, 0x8007, + 0x0980, 0x0109, 0x0300, 0x4b01, 0x8007, 0x8008, + 0x0980, 0x0109, 0x0300, 0x4b01, 0xc006, 0x800c, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0xf001, 0x0000, 0x0000, + 0xffff +}; + +static const uint16_t *const level_data_lookup[] = +{ + level_data_00, + level_data_01, + level_data_02, + level_data_03, + level_data_04, + level_data_05, + level_data_06, + level_data_07, + level_data_08, + level_data_09 +}; + +void opwolf_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_OPWOLF: + opwolf_timer_callback(ptr, param); + break; + case TIMER_CCHIP: + cchip_timer(ptr, param); + break; + default: + throw emu_fatalerror("Unknown id in opwolf_state::device_timer"); + } +} + +TIMER_CALLBACK_MEMBER(opwolf_state::opwolf_timer_callback) +{ + // Level data command + if (m_current_cmd == 0xf5) + { + int const level = m_cchip_ram[0x1b] % 10; + uint16_t const *const level_data = level_data_lookup[level]; + + // The c-chip data is stored as a series of 3 word sets, delimited by 0xffff + memset(m_cchip_ram + 0x200, 0, 0x200); + for (unsigned i = 0; (i < 0x200) && (level_data[i] != 0xffff); i += 3) + { + m_cchip_ram[0x200 + i*2 + 0] = level_data[i]>>8; + m_cchip_ram[0x200 + i*2 + 1] = level_data[i]&0xff; + m_cchip_ram[0x200 + i*2 + 2] = level_data[i+1]>>8; + m_cchip_ram[0x200 + i*2 + 3] = level_data[i+1]&0xff; + m_cchip_ram[0x200 + i*2 + 4] = level_data[i+2]>>8; + m_cchip_ram[0x200 + i*2 + 5] = level_data[i+2]&0xff; + } + + // The bootleg cchip writes 0 to these locations - we can probably assume the real one + // does similar as this is just zeroing out work variables used in the level. + m_cchip_ram[0x0] = 0; + m_cchip_ram[0x76] = 0; + m_cchip_ram[0x75] = 0; + m_cchip_ram[0x74] = 0; + m_cchip_ram[0x72] = 0; + m_cchip_ram[0x71] = 0; + // m_cchip_ram[0x70] = 0; // The bootleg writes this to disable mini-levels. The real c-chip does not do this. + m_cchip_ram[0x66] = 0; + m_cchip_ram[0x2b] = 0; + m_cchip_ram[0x30] = 0; + m_cchip_ram[0x31] = 0; + m_cchip_ram[0x32] = 0; + m_cchip_ram[0x27] = 0; + m_c588 = 0; + m_c589 = 0; + m_c58a = 0; + m_triggeredLevel1b = 0; + m_triggeredLevel13b = 0; + m_triggeredLevel2 = 0; + m_triggeredLevel2b = 0; + m_triggeredLevel2c = 0; + m_triggeredLevel3b = 0; + m_triggeredLevel4 = 0; + m_triggeredLevel5 = 0; + m_triggeredLevel7 = 0; + m_triggeredLevel8 = 0; + m_triggeredLevel9 = 0; + + m_cchip_ram[0x1a] = 0; + m_cchip_ram[0x7a] = 1; // Signal command complete + + //logerror("Signal level command complete\n"); + } + + m_current_cmd = 0; +} + +void opwolf_state::updateDifficulty( int mode ) +{ + // The game is made up of 6 rounds, when you complete the + // sixth you return to the start but with harder difficulty. + if (mode == 0) + { + switch (m_cchip_ram[0x15]&3) // Dipswitch B + { + case 3: + m_cchip_ram[0x2c] = 0x31; + m_cchip_ram[0x77] = 0x05; + m_cchip_ram[0x25] = 0x0f; + m_cchip_ram[0x26] = 0x0b; + break; + case 0: + m_cchip_ram[0x2c] = 0x20; + m_cchip_ram[0x77] = 0x06; + m_cchip_ram[0x25] = 0x07; + m_cchip_ram[0x26] = 0x03; + break; + case 1: + m_cchip_ram[0x2c] = 0x31; + m_cchip_ram[0x77] = 0x05; + m_cchip_ram[0x25] = 0x0f; + m_cchip_ram[0x26] = 0x0b; + break; + case 2: + m_cchip_ram[0x2c] = 0x3c; + m_cchip_ram[0x77] = 0x04; + m_cchip_ram[0x25] = 0x13; + m_cchip_ram[0x26] = 0x0f; + break; + } + } + else + { + switch (m_cchip_ram[0x15]&3) // Dipswitch B + { + case 3: + m_cchip_ram[0x2c] = 0x46; + m_cchip_ram[0x77] = 0x05; + m_cchip_ram[0x25] = 0x11; + m_cchip_ram[0x26] = 0x0e; + break; + case 0: + m_cchip_ram[0x2c] = 0x30; + m_cchip_ram[0x77] = 0x06; + m_cchip_ram[0x25] = 0x0b; + m_cchip_ram[0x26] = 0x03; + break; + case 1: + m_cchip_ram[0x2c] = 0x3a; + m_cchip_ram[0x77] = 0x05; + m_cchip_ram[0x25] = 0x0f; + m_cchip_ram[0x26] = 0x09; + break; + case 2: + m_cchip_ram[0x2c] = 0x4c; + m_cchip_ram[0x77] = 0x04; + m_cchip_ram[0x25] = 0x19; + m_cchip_ram[0x26] = 0x11; + break; + }; + } +} + +/************************************* + * + * Writes to C-Chip - Important Bits + * + *************************************/ + +WRITE16_MEMBER(opwolf_state::opwolf_cchip_status_w) +{ + // This is written once after the C-Chip init is complete (and passes) + // We use it to setup some initial state (it's not clear if the real + // c-chip sets this here, or if it's as a side-effect of the other + // init sequence data). + + m_cchip_ram[0x3d] = 1; + m_cchip_ram[0x7a] = 1; + updateDifficulty(0); +} + +WRITE16_MEMBER(opwolf_state::opwolf_cchip_bank_w) +{ + m_current_bank = data & 7; +} + +WRITE16_MEMBER(opwolf_state::opwolf_cchip_data_w) +{ + //int logValue=1; + //if (offset==0x1c && offset==0x1d && offset==0x1e && offset==0x1f && offset==0x20) // Enemies, tanks, choppers, boats + // logValue=0; + //if (offset==0x50 && offset==0x51 && offset==0x52 && offset==0x53) // Coins + // logValue=0; + //if (logValue) + // logerror("%s: opwolf 68K writes c-chip %02x at %04x/%04x (bank %04x)\n", machine().describe_context(), data & 0xff, offset*2, offset, m_current_bank); + + m_cchip_ram[(m_current_bank * 0x400) + offset] = data & 0xff; + + if (m_current_bank == 0) + { + // Dip switch A is written here by the 68k - precalculate the coinage values + // Shouldn't we directly read the values from the ROM area ? + if (offset == 0x14) + { +#if OPWOLF_READ_COINAGE_FROM_ROM + uint16_t* rom = (uint16_t*)memregion("maincpu")->base(); + uint32_t coin_table[2] = {0, 0}; + uint8_t coin_offset[2]; + int slot; + + if ((m_opwolf_region == OPWOLF_REGION_JAPAN) || (m_opwolf_region == OPWOLF_REGION_US)) + { + coin_table[0] = 0x03ffce; + coin_table[1] = 0x03ffce; + } + if ((m_opwolf_region == OPWOLF_REGION_WORLD) || (m_opwolf_region == OPWOLF_REGION_OTHER)) + { + coin_table[0] = 0x03ffde; + coin_table[1] = 0x03ffee; + } + coin_offset[0] = 12 - (4 * ((data & 0x30) >> 4)); + coin_offset[1] = 12 - (4 * ((data & 0xc0) >> 6)); + + for (slot = 0; slot < 2; slot++) + { + if (coin_table[slot]) + { + m_cchip_coins_for_credit[slot] = rom[(coin_table[slot] + coin_offset[slot] + 0) / 2] & 0xff; + m_cchip_credits_for_coin[slot] = rom[(coin_table[slot] + coin_offset[slot] + 2) / 2] & 0xff; + } + } +#else + if ((m_opwolf_region == OPWOLF_REGION_JAPAN) || (m_opwolf_region == OPWOLF_REGION_US)) + { + switch (data&0x30) /* table at 0x03ffce.w - 4 * 2 words (coins for credits first) - inverted order */ + { + case 0x00: m_cchip_coins_for_credit[0] = 2; cchip_credits_for_coin[0] = 3; break; + case 0x10: m_cchip_coins_for_credit[0] = 2; cchip_credits_for_coin[0] = 1; break; + case 0x20: m_cchip_coins_for_credit[0] = 1; cchip_credits_for_coin[0] = 2; break; + case 0x30: m_cchip_coins_for_credit[0] = 1; cchip_credits_for_coin[0] = 1; break; + } + switch (data&0xc0) /* table at 0x03ffce.w - 4 * 2 words (coins for credits first) - inverted order */ + { + case 0x00: m_cchip_coins_for_credit[1] = 2; cchip_credits_for_coin[1] = 3; break; + case 0x40: m_cchip_coins_for_credit[1] = 2; cchip_credits_for_coin[1] = 1; break; + case 0x80: m_cchip_coins_for_credit[1] = 1; cchip_credits_for_coin[1] = 2; break; + case 0xc0: m_cchip_coins_for_credit[1] = 1; cchip_credits_for_coin[1] = 1; break; + } + } + + if ((opwolf_region == OPWOLF_REGION_WORLD) || (opwolf_region == OPWOLF_REGION_OTHER)) + { + switch (data&0x30) /* table at 0x03ffde.w - 4 * 2 words (coins for credits first) - inverted order */ + { + case 0x00: m_cchip_coins_for_credit[0] = 4; cchip_credits_for_coin[0] = 1; break; + case 0x10: m_cchip_coins_for_credit[0] = 3; cchip_credits_for_coin[0] = 1; break; + case 0x20: m_cchip_coins_for_credit[0] = 2; cchip_credits_for_coin[0] = 1; break; + case 0x30: m_cchip_coins_for_credit[0] = 1; cchip_credits_for_coin[0] = 1; break; + } + switch (data & 0xc0) /* table at 0x03ffee.w - 4 * 2 words (coins for credits first) - inverted order */ + { + case 0x00: m_cchip_coins_for_credit[1] = 1; cchip_credits_for_coin[1] = 6; break; + case 0x40: m_cchip_coins_for_credit[1] = 1; cchip_credits_for_coin[1] = 4; break; + case 0x80: m_cchip_coins_for_credit[1] = 1; cchip_credits_for_coin[1] = 3; break; + case 0xc0: m_cchip_coins_for_credit[1] = 1; cchip_credits_for_coin[1] = 2; break; + } + } +#endif + } + + // Dip switch B + if (offset == 0x15) + { + updateDifficulty(0); + } + } +} + +/************************************* + * + * Reads from C-Chip + * + *************************************/ + +READ16_MEMBER(opwolf_state::opwolf_cchip_status_r) +{ + /* + Bit 0x4 = Error signal + Bit 0x1 = Ready signal + */ + return 0x1; /* Return 0x5 for C-Chip error */ +} + +READ16_MEMBER(opwolf_state::opwolf_cchip_data_r) +{ +// if (offset!=0x7f && && m_maincpu->pc()!=0xc18 && m_maincpu->pc()!=0xc2e && m_maincpu->pc()!=0xc9e && offset!=0x50 && offset!=0x51 && offset!=0x52 && offset!=0x53 && offset!=0x5 && offset!=0x13 && offset!=0x79 && offset!=0x12 && offset!=0x34) +// logerror("%08x: opwolf c read %04x (bank %04x)\n", m_maincpu->pc(), offset, m_current_bank); + + //int logValue=1; + //if (offset==0x1c || offset==0x1d || offset==0x1e || offset==0x1f || offset==0x20) // Enemies, tanks, choppers, boats + // logValue=0; + //if (offset==0x50 || offset==0x51 || offset==0x52 || offset==0x53) // Coins + // logValue=0; + //if (m_maincpu->pc()==0xc18 && m_maincpu->pc()!=0xc2e && m_maincpu->pc()!=0xc9e) + // logValue=0; + //if (logValue) + // logerror("%08x: opwolf 68K reads c-chip at %04x/%04x (bank %04x)\n", m_maincpu->pc(), offset*2, offset, m_current_bank); + + return m_cchip_ram[(m_current_bank * 0x400) + offset]; +} + +/************************************* + * + * C-Chip Tick + * + *************************************/ + +TIMER_CALLBACK_MEMBER(opwolf_state::cchip_timer) +{ + // Update input ports, these are used by both the 68k directly and by the c-chip + m_cchip_ram[0x4] = ioport("IN0")->read(); + m_cchip_ram[0x5] = ioport("IN1")->read(); + + // Dev Cheat - kill all enemeies + //if ((ioport("IN1")->read()&0x10)!=0x10) + //{ + // m_cchip_ram[0x1c] = m_cchip_ram[0x1d] = m_cchip_ram[0x1e] = m_cchip_ram[0x1f] = m_cchip_ram[0x20] = 0; + //} + + // Coin slots + if (m_cchip_ram[0x4] != m_cchip_last_04) + { + int slot = -1; + + if (m_cchip_ram[0x4] & 1) slot = 0; + if (m_cchip_ram[0x4] & 2) slot = 1; + + if (slot != -1) + { + m_cchip_coins[slot]++; + if (m_cchip_coins[slot] >= m_cchip_coins_for_credit[slot]) + { + m_cchip_ram[0x53] += m_cchip_credits_for_coin[slot]; + m_cchip_ram[0x51] = 0x55; + m_cchip_ram[0x52] = 0x55; + m_cchip_coins[slot] -= m_cchip_coins_for_credit[slot]; + } + machine().bookkeeping().coin_counter_w(slot, 1); + } + + if (m_cchip_ram[0x53] > 9) + m_cchip_ram[0x53] = 9; + } + m_cchip_last_04 = m_cchip_ram[0x4]; + + // Service switch + if (m_cchip_ram[0x5] != m_cchip_last_05) + { + if ((m_cchip_ram[0x5] & 4)==0) + { + m_cchip_ram[0x53]++; + m_cchip_ram[0x51] = 0x55; + m_cchip_ram[0x52] = 0x55; + } + } + m_cchip_last_05=m_cchip_ram[0x5]; + + // Cchip handles coin lockout (68k flags error if more than 9 coins) + machine().bookkeeping().coin_lockout_w(1, m_cchip_ram[0x53] == 9); + machine().bookkeeping().coin_lockout_w(0, m_cchip_ram[0x53] == 9); + machine().bookkeeping().coin_counter_w(0, 0); + machine().bookkeeping().coin_counter_w(1, 0); + + // These variables are cleared every frame during attract mode and the intro. + if (m_cchip_ram[0x34] < 2) + { + updateDifficulty(0); + m_cchip_ram[0x76] = 0; + m_cchip_ram[0x75] = 0; + m_cchip_ram[0x74] = 0; + m_cchip_ram[0x72] = 0; + m_cchip_ram[0x71] = 0; + m_cchip_ram[0x70] = 0; + m_cchip_ram[0x66] = 0; + m_cchip_ram[0x2b] = 0; + m_cchip_ram[0x30] = 0; + m_cchip_ram[0x31] = 0; + m_cchip_ram[0x32] = 0; + m_cchip_ram[0x27] = 0; + m_c588 = 0; + m_c589 = 0; + m_c58a = 0; + } + + // The unprotected Operation Wolf (prototype) shows the game sets up a special thread function specific to each level of the game. + // This includes the end of level check as different levels have different rules. In the protected version this logic is moved + // to the c-chip, so we simulate it here. + if (m_cchip_ram[0x1c] == 0 && m_cchip_ram[0x1d] == 0 && m_cchip_ram[0x1e] == 0 && m_cchip_ram[0x1f] == 0 && m_cchip_ram[0x20] == 0) + { + // Special handling for end of level 6 + if (m_cchip_ram[0x1b] == 0x6) + { + // Don't signal end of level until final boss is destroyed + if (m_cchip_ram[0x27] == 0x1) + m_cchip_ram[0x32] = 1; + } + // Level 2 - Boss check - cross-referenced from logic at 0x91CE in OpWolfP + // When all enemies are destroyed c-chip signals function 4 in the level function table, which + // starts the 'WARNING' sequences for the boss. + else if (m_cchip_ram[0x1b] == 0x2) + { + if (m_triggeredLevel2==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f) + { + m_cchip_ram[0x5f] = 4; // 0xBE at 68K side + m_triggeredLevel2=1; + } + + // When the level 2 boss has been defeated the 68K will write 0xff to $ff0ba.l - this should signal + // the c-chip to start the end of level routine. See code at 0xC370 in OpWolf and 0x933e in OpWolfP + if (m_triggeredLevel2 && m_cchip_ram[0x5d]!=0) + { + // Signal end of level + m_cchip_ram[0x32] = 1; + m_cchip_ram[0x5d] = 0; // acknowledge 68K command + } + } + else if (m_cchip_ram[0x1b] == 0x4) + { + m_cchip_ram[0x32] = 1; + + // When level 4 (powder magazine) is complete the c-chip triggers an explosion animation. + if (m_triggeredLevel4==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_cchip_ram[0x5f]=10; + m_triggeredLevel4=1; + } + } + else + { + // Signal end of level + m_cchip_ram[0x32] = 1; + } + } + + // When all men are destroyed (not necessarily vehicles) the enemy look up table changes + // Reference functions around 0x96A4 in the unprotected prototype. + // Level 1 has a specific table. + // Level 3 has an additional flag set + if (m_cchip_ram[0x1c] == 0 && m_cchip_ram[0x1d] == 0) + { + // Compare code at 0x96DC in prototype with 0xC3A2 in protected version + if (m_cchip_ram[0x1b] == 0x1 && m_triggeredLevel1b==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_cchip_ram[0x5f]=7; + m_triggeredLevel1b=1; + } + + // Compare code at 0x96BC in prototype with 0xC3B2 in protected version + if (m_cchip_ram[0x1b] == 0x3 && m_triggeredLevel3b==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_cchip_ram[0x5f]=8; + m_triggeredLevel3b=1; + } + + // Compare code at 0x96BC in prototype with 0xC3C8 in protected version + if ((m_cchip_ram[0x1b] != 0x1 && m_cchip_ram[0x1b] != 0x3) && m_triggeredLevel13b==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_cchip_ram[0x5f]=9; + m_triggeredLevel13b=1; + } + } + + //------------------------------------------------------------------------------------------------- + // Level 2. On level 2 specifically when there are less than 45 men left the enemy lookup table is + // switched. This drops down a wave of paratroopers. When there are less than 25 men left the lookup + // table is switched again. + // See code at 0xC37A and 0xc390 in protected version against 0x9648 in prototype. + if (m_cchip_ram[0x1b] == 0x2) + { + // (Note: it's correct that 25 decimal is represented as 0x25 in hex here). + int numMen=(m_cchip_ram[0x1d]<<8) + m_cchip_ram[0x1c]; + if (numMen<0x25 && m_triggeredLevel2b==1 && m_triggeredLevel2c==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_cchip_ram[0x5f]=6; + m_triggeredLevel2c=1; + } + + // (Note: it's correct that 45 decimal is represented as 0x45 in hex here). + if (numMen<0x45 && m_triggeredLevel2b==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_cchip_ram[0x5f]=5; + m_triggeredLevel2b=1; + } + } + + //------------------------------------------------------------------------------------------------- + // Level 5 + if (m_cchip_ram[0x1b] == 0x5) + { + // When all men are destroyed (not necessarily vehicles), the c-chip writes 1 to location + // 0x2f to spawn a thread that scrolls the screen upwards to focus on the helicopter + // enemies. The 68K acknowledges this by writing 2 to 0x2f. + // See code at 0x4ED6 in prototype and 0x687e in original. + if (m_cchip_ram[0x1c] == 0 && m_cchip_ram[0x1d] == 0 && m_triggeredLevel5==0) + { + m_cchip_ram[0x2f] = 1; + m_triggeredLevel5 = 1; + } + } + + //------------------------------------------------------------------------------------------------- + // Level 6 + if (m_cchip_ram[0x1b] == 0x6) + { + // Check for triggering final helicopter (end boss) + if (m_c58a == 0) + { + if ((m_cchip_ram[0x72] & 0x7f) >= 8 && m_cchip_ram[0x74] == 0 && m_cchip_ram[0x1c] == 0 && m_cchip_ram[0x1d] == 0 && m_cchip_ram[0x1f] == 0) + { + m_cchip_ram[0x30] = 1; + m_cchip_ram[0x74] = 1; + m_c58a = 1; + } + } + + if (m_cchip_ram[0x1a] == 0x90) + m_cchip_ram[0x74] = 0; + + if (m_c58a != 0) + { + if (m_c589 == 0 && m_cchip_ram[0x27] == 0 && m_cchip_ram[0x75] == 0 && m_cchip_ram[0x1c] == 0 && m_cchip_ram[0x1d] == 0 && m_cchip_ram[0x1e] == 0 && m_cchip_ram[0x1f] == 0) + { + m_cchip_ram[0x31] = 1; + m_cchip_ram[0x75] = 1; + m_c589 = 1; + } + } + + if (m_cchip_ram[0x2b] == 0x1) + { + m_cchip_ram[0x2b] = 0; + + if (m_cchip_ram[0x30] == 0x1) + { + if (m_cchip_ram[0x1a] != 0x90) + m_cchip_ram[0x1a]--; + } + + if (m_cchip_ram[0x72] == 0x9) + { + if (m_cchip_ram[0x76] != 0x4) + { + m_cchip_ram[0x76] = 3; + } + } + else + { + // This timer is derived from the bootleg rather than the real board, I'm not 100% sure about it + m_c588 |= 0x80; + + m_cchip_ram[0x72] = m_c588; + m_c588++; + + m_cchip_ram[0x1a]--; + m_cchip_ram[0x1a]--; + m_cchip_ram[0x1a]--; + } + } + + // Update difficulty settings + if (m_cchip_ram[0x76] == 0) + { + m_cchip_ram[0x76] = 1; + updateDifficulty(1); + } + } + + //------------------------------------------------------------------------------------------------- + // Start of level 7 - should trigger '1' in level thread table (compare 0xC164 in protected to 0x9468 in unprotected) + if (m_cchip_ram[0x1b] == 0x7 && m_triggeredLevel7==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_triggeredLevel7 = 1; + m_cchip_ram[0x5f] = 1; + } + + //------------------------------------------------------------------------------------------------- + // Start of level 8 - should trigger '2' in level thread table (compare 0xC18E in protected to 0x9358 in unprotected) + // This controls the 'zoom in helicopters' enemy + if (m_cchip_ram[0x1b] == 0x8 && m_triggeredLevel8==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_triggeredLevel8 = 1; + m_cchip_ram[0x5f] = 2; + } + + //------------------------------------------------------------------------------------------------- + // Start of level 9 - should trigger '3' in level thread table (compare 0xC1B0 in protected to 0x9500 in unprotected) + // This controls the 'zoom in helicopters' enemy + if (m_cchip_ram[0x1b] == 0x9 && m_triggeredLevel9==0 && m_cchip_ram[0x5f]==0) // Don't write unless 68K is ready (0 at 0x5f)) + { + m_triggeredLevel9 = 1; + m_cchip_ram[0x5f] = 3; + } + + if (m_cchip_ram[0xe] == 1) + { + m_cchip_ram[0xe] = 0xfd; + m_cchip_ram[0x61] = 0x04; + } + + // Access level data command (address 0xf5 goes from 1 -> 0) + if (m_cchip_ram[0x7a] == 0 && m_cchip_last_7a != 0 && m_current_cmd != 0xf5) + { + // Simulate time for command to execute (exact timing unknown, this is close) + m_current_cmd = 0xf5; + m_opwolf_timer->adjust(m_maincpu->cycles_to_attotime(80000)); + } + m_cchip_last_7a = m_cchip_ram[0x7a]; + + // This seems to some kind of periodic counter - results are expected + // by the 68k when the counter reaches 0xa + if (m_cchip_ram[0x7f] == 0xa) + { + m_cchip_ram[0xfe] = 0xf7; + m_cchip_ram[0xff] = 0x6e; + } + + // These are set every frame + m_cchip_ram[0x64] = 0; + m_cchip_ram[0x66] = 0; +} + +/************************************* + * + * C-Chip State Saving + * + *************************************/ + +void opwolf_state::opwolf_cchip_init( ) +{ + m_cchip_ram.allocate(0x400 * 8); + + save_item(NAME(m_current_bank)); + save_item(NAME(m_current_cmd)); + save_item(NAME(m_cchip_last_7a)); + save_item(NAME(m_cchip_last_04)); + save_item(NAME(m_cchip_last_05)); + save_item(NAME(m_c588)); + save_item(NAME(m_c589)); + save_item(NAME(m_c58a)); + save_item(NAME(m_cchip_coins)); + save_item(NAME(m_cchip_coins_for_credit)); + save_item(NAME(m_cchip_credits_for_coin)); + save_item(NAME(m_triggeredLevel1b)); + save_item(NAME(m_triggeredLevel2)); + save_item(NAME(m_triggeredLevel2b)); + save_item(NAME(m_triggeredLevel2c)); + save_item(NAME(m_triggeredLevel3b)); + save_item(NAME(m_triggeredLevel13b)); + save_item(NAME(m_triggeredLevel4)); + save_item(NAME(m_triggeredLevel5)); + save_item(NAME(m_triggeredLevel7)); + save_item(NAME(m_triggeredLevel8)); + save_item(NAME(m_triggeredLevel9)); + + m_triggeredLevel1b = 0; + m_triggeredLevel2 = 0; + m_triggeredLevel2b = 0; + m_triggeredLevel2c = 0; + m_triggeredLevel3b = 0; + m_triggeredLevel13b = 0; + m_triggeredLevel4 = 0; + m_triggeredLevel5 = 0; + m_triggeredLevel7 = 0; + m_triggeredLevel8 = 0; + m_triggeredLevel9 = 0; + m_current_bank = 0; + m_current_cmd = 0; + m_cchip_last_7a = 0; + m_cchip_last_04 = 0xfc; + m_cchip_last_05 = 0xff; + m_c588 = 0; + m_c589 = 0; + m_c58a = 0; + m_cchip_coins[0] = 0; + m_cchip_coins[1] = 0; + m_cchip_coins_for_credit[0] = 1; + m_cchip_credits_for_coin[0] = 1; + m_cchip_coins_for_credit[1] = 1; + m_cchip_credits_for_coin[1] = 1; + + m_cchip_timer = timer_alloc(TIMER_CCHIP); + m_cchip_timer->adjust(attotime::from_hz(60), 0, attotime::from_hz(60)); +} + + +*************************************************************************** +File: mame/drivers/opwolf.cpp +*************************************************************************** + + +// map(0x0f0000, 0x0f07ff).mirror(0xf000).r(FUNC(opwolf_state::opwolf_cchip_data_r)); +// map(0x0f0802, 0x0f0803).mirror(0xf000).r(FUNC(opwolf_state::opwolf_cchip_status_r)); +// map(0x0ff000, 0x0ff7ff).w(FUNC(opwolf_state::opwolf_cchip_data_w)); +// map(0x0ff802, 0x0ff803).w(FUNC(opwolf_state::opwolf_cchip_status_w)); +// map(0x0ffc00, 0x0ffc01).w(FUNC(opwolf_state::opwolf_cchip_bank_w)); + +// m_opwolf_timer = timer_alloc(TIMER_OPWOLF); + +// opwolf_cchip_init(); // start old simulation, including periodic timer + + +*************************************************************************** +File: mame/includes/opwolf.h +*************************************************************************** + + +enum +{ + TIMER_OPWOLF, + TIMER_CCHIP +}; + +DECLARE_WRITE16_MEMBER(opwolf_cchip_status_w); +DECLARE_WRITE16_MEMBER(opwolf_cchip_bank_w); +DECLARE_WRITE16_MEMBER(opwolf_cchip_data_w); +DECLARE_READ16_MEMBER(opwolf_cchip_status_r); +DECLARE_READ16_MEMBER(opwolf_cchip_data_r); + +virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + +TIMER_CALLBACK_MEMBER(opwolf_timer_callback); +TIMER_CALLBACK_MEMBER(cchip_timer); +void updateDifficulty(int mode); +void opwolf_cchip_init(); + +emu_timer *m_opwolf_timer; + +/* c-chip */ +emu_timer *m_cchip_timer; + +int m_opwolf_region; + +uint8_t m_current_bank; +uint8_t m_current_cmd; +uint8_t m_cchip_last_7a; +uint8_t m_cchip_last_04; +uint8_t m_cchip_last_05; +uint8_t m_cchip_coins_for_credit[2]; +uint8_t m_cchip_credits_for_coin[2]; +uint8_t m_cchip_coins[2]; +uint8_t m_c588; +uint8_t m_c589; +uint8_t m_c58a; // These variables derived from the bootleg +uint8_t m_triggeredLevel1b; // These variables derived from comparison to unprotection version +uint8_t m_triggeredLevel2; +uint8_t m_triggeredLevel2b; +uint8_t m_triggeredLevel2c; +uint8_t m_triggeredLevel3b; +uint8_t m_triggeredLevel13b; +uint8_t m_triggeredLevel4; +uint8_t m_triggeredLevel5; +uint8_t m_triggeredLevel7; +uint8_t m_triggeredLevel8; +uint8_t m_triggeredLevel9; diff --git a/attic/unkfr.cpp b/attic/unkfr.cpp new file mode 100644 index 00000000000..4e7c2e7f566 --- /dev/null +++ b/attic/unkfr.cpp @@ -0,0 +1,752 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood +/* + Unknown Fruit Machine ROMs + + Fruit Machine ROMs can be difficult to identify at the best of times, and just as difficult to + place in a driver, especially if parts are missing. + + This file is just a collection of random odds and ends which I haven't been able to place yet, + some of it could well be junk. They can be deleted / placed over time. Some could be bad, + some could be missing parts, some could be unique platforms. + + Please remove any confirmed bad roms, and if hardware is positively identified, move things + to the correct drivers. + +*/ + + +#include "emu.h" + +class unkfr_state : public driver_device +{ +public: + unkfr_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu") { } + required_device<cpu_device> m_maincpu; + + void unkfr(machine_config &config); +}; + + +#if 0 + +static INPUT_PORTS_START( unkfr ) + PORT_START("IN0") + PORT_DIPNAME( 0x01, 0x01, "IN0:01" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x02, "IN0:02" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x04, "IN0:04" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x08, "IN0:08" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x10, "IN0:10" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x20, "IN0:20" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x40, "IN0:40" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + PORT_DIPNAME( 0x80, 0x80, "IN0:80" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x80, DEF_STR( On ) ) +INPUT_PORTS_END + +void unkfr_state::unkfr(machine_config &config) +{ +} + +ROM_START( unkfr ) + ROM_REGION( 0x800000, "unkroms", 0 ) +// 3 Of A Kind (Unk) + ROM_LOAD( "3ofakind.bin", 0x0000, 0x008000, CRC(46883c38) SHA1(ab1ffbc437a919e991443d1f5c1b6378b0c8fd53) ) + ROM_LOAD( "3ofakindhacked.bin", 0x0000, 0x008000, CRC(94acff35) SHA1(d0e3c7666fb655b1fc20542527e4f55bc25abe0c) ) +// Club 21 (Unk) [c] (bad - only a few bits ever used) +// ROM_LOAD( "club21_1.bin", 0x0000, 0x080000, CRC(826e047c) SHA1(1da8a86688148c184c42ce213239ea2e57cb9e29) ) +// ROM_LOAD( "club21_2.bin", 0x0000, 0x080000, CRC(75297a19) SHA1(1c7e2b3fccfc79b3fbfbc979d06aef3405fa2aad) ) +// ROM_LOAD( "club21snd-0.bin", 0x0000, 0x080000, CRC(673551c6) SHA1(d7540388ccc8df6be2ec7a3fa90765f7e6ac49f7) ) +// ROM_LOAD( "club21snd-1.bin", 0x0000, 0x080000, CRC(a9288cf4) SHA1(a30027497e965fc670ca902ca228c3e434815e34) ) +// Cops 'n' Robbers Classic (Bellfruit) - possibly a DMD ROM, given the mtx filename + ROM_LOAD( "classic-cops-and-robbers_mtx_ass.bin", 0x0000, 0x010000, CRC(3f40a2c9) SHA1(f73731171c56add1329f3a9d2f84303311d87884) ) +// Crystal Maze SWP (Barcrest) [c] (just a bad dump?) + ROM_LOAD( "cr2.p8", 0x0000, 0x080000, CRC(9196fc2f) SHA1(844581f2380045019f65b42051535972e6cf21ca) ) +// Each Way Shifter (Barcrest) + ROM_LOAD( "ews3_3.bin", 0x0000, 0x010000, CRC(fb05345f) SHA1(72183743ec8955b12724471494f19d6af778e4b1) ) // MPU? + ROM_LOAD( "ews8.a2", 0x0000, 0x000400, CRC(ee4a4809) SHA1(292a12a5ddc5a22c8568016b34dfec7959f49027) ) + //ROM_LOAD( "ews8.az", 0x0000, 0x000400, CRC(ee4a4809) SHA1(292a12a5ddc5a22c8568016b34dfec7959f49027) ) + ROM_LOAD( "ews8.b1", 0x0000, 0x000400, CRC(52e9709a) SHA1(0b437834f48ca7718e0b30303916eed00c7fb4c9) ) +// Golden Shot (Empire) + ROM_LOAD( "game_sec.mot", 0x0000, 0x161880, CRC(81ea2ee4) SHA1(8d5fe57c46054c23afdbb3c5c67fd7a7e9161646) ) +// Hells Bells Club (JPM) [c] (looks like it should be sys5 or impact, but code crashes early?) + ROM_LOAD( "hbl200p1", 0x0000, 0x010000, CRC(1f893dd8) SHA1(c2dd957f65ff6ed7f7ac027e4edb6b6a36871f88) ) + ROM_LOAD( "hbl200p2", 0x0000, 0x010000, CRC(ea470cf6) SHA1(2f64a8aac3bc01245cb4938bb01a5078c360c8d4) ) + ROM_LOAD( "hbl200p3", 0x0000, 0x010000, CRC(05c09717) SHA1(25fe309513daef262099aa1f0266f96eafb22d2c) ) + ROM_LOAD( "hbl200p4", 0x0000, 0x010000, CRC(a1d299db) SHA1(58f35ecbc524c41f4a39d3374f73f44fc54c751b) ) +// Jokers (MA Leisure) + ROM_LOAD( "jokers 1v3 (27256)", 0x0000, 0x008000, CRC(8d4222c1) SHA1(d7edc1338448436044c9fbf4448819c7ba1a9cb3) ) +// Knight Fever (Empire) (corrupt? ascii/binary mode?) + ROM_LOAD( "knight_n_vr105game.bin", 0x0000, 0x04094d, CRC(7a59e3ca) SHA1(fa44dd0fceb53dff38386f81f1e79b605adfbe6a) ) + ROM_LOAD( "knight_p_vr105game.bin", 0x0000, 0x04094d, CRC(ebbde668) SHA1(ba04b18dd398c99923dff40db753f0a43bbe0b08) ) + ROM_LOAD( "knightb3_n_vr101.bin", 0x0000, 0x042153, CRC(bb890b7d) SHA1(a30d71e96d500f4b37974c86ca9490d53c74b8e6) ) + ROM_LOAD( "knightb3_p_vr101.bin", 0x0000, 0x042153, CRC(ca2445f0) SHA1(9e622f84bc1f5349efa99cea470039c608acb7e8) ) + ROM_LOAD( "knightc_n_vr101.bin", 0x0000, 0x0412e9, CRC(66576eaf) SHA1(51d57ca904163bdbf2bf6cf5c90d8bdcee722e04) ) + ROM_LOAD( "knightc_p_vr101.bin", 0x0000, 0x0412e9, CRC(46d57021) SHA1(05a640ca5b7a10e9ae96a02b3ac1f2bc6497f052) ) +// LED (Test Rom) (test rom for what?) + ROM_LOAD( "ledtest.bin", 0x0000, 0x020000, CRC(c74a0002) SHA1(e475d5c6b3077a2b8e76322c6d0848c622fbd76c) ) +// Lucky Spin (DNCL) + ROM_LOAD( "luckyspin.bin", 0x0000, 0x002000, CRC(765bb41b) SHA1(d3f02494c35cce4dfa79dab14a1416ac7e86683c) ) +// Magic Moments (Unk) + ROM_LOAD( "magicmoments20p-6.bin", 0x0000, 0x008000, CRC(c0986a11) SHA1(0333d37d11f8b03e0507ddcefc4a67ea2cba5bd8) ) +// Millionaires Row (Bellfruit) (bad?) + ROM_LOAD( "millionaires row s16 sound (8meg)", 0x0000, 0x100000, CRC(4086df3f) SHA1(7fd358d901db48d1f8edc4b22789c73b5fb84874) ) + ROM_LOAD( "millionaires row s16 v1-0 hi (4meg)", 0x0000, 0x080000, CRC(6b879665) SHA1(79fa91721375f0f968ecbd07fe9e9695344b7cd6) ) + ROM_LOAD( "millionaires row s16 v1-0 lo (4meg)", 0x0000, 0x080000, CRC(8436aab9) SHA1(815000121e93c9a8e4f6c6d6d12a06c4484eb50c) ) +// Money Matrix (Bellfruit) + ROM_LOAD( "957179.02.bin", 0x0000, 0x008000, CRC(ee215e94) SHA1(249d16a3ed7b9b6c99b1135f350efcb2ed130865) ) +// More Money (VFS) + ROM_LOAD( "mmchancs.bin", 0x0000, 0x002000, CRC(3eaede51) SHA1(6914fcaed6e51736c6dc725ba82b691803571222) ) +// Oceans Eleven (Empire) (corrupt? ascii/binary mode?) + ROM_LOAD( "oceansb3_n_vr102.bin", 0x0000, 0x03f046, CRC(e425c04a) SHA1(9a64c6065670d4523c8f5d1094bdea0598ca2a87) ) + ROM_LOAD( "oceansb3_p_vr102.bin", 0x0000, 0x03f046, CRC(71824b03) SHA1(540c5497217de70fa4e297a9e866b3311a12d6d6) ) + ROM_LOAD( "oceansc_n_vr102.bin", 0x0000, 0x03e88a, CRC(2807cad1) SHA1(4bda5060ce60a3e7ee72f3f50cab2abc00c6ae12) ) + ROM_LOAD( "oceansc_p_vr102.bin", 0x0000, 0x03e88a, CRC(14db1bb5) SHA1(be5986aa1340fd21d22f55627e6049b0011be564) ) +// Power Game (JPM) + ROM_LOAD( "pog5.3p1", 0x0000, 0x020000, CRC(62ea507f) SHA1(ea1e2057f3b51ab3f13c7b91467ed3142c64b76a) ) // unmatched 68k rom? + ROM_LOAD( "powgam41.bin", 0x0000, 0x004000, CRC(304ccf8c) SHA1(96370bd7d6f7c7218be18e9be2fb87a58a9ac9d4) ) // looks like it should be MPS, but is bad? + ROM_LOAD( "powgam42.bin", 0x0000, 0x004000, CRC(a71cc455) SHA1(324a0ef33d0e0fc8bd8a5d1309a3b2e6f13926d6) ) + ROM_LOAD( "powgam43.bin", 0x0000, 0x004000, CRC(0661cbcc) SHA1(1d14ec7321e00e837f9cb0da6f660f1a7625b139) ) +// Rainbow Gambler (Unk) + ROM_LOAD( "rambow gambler 2p2 25-7.bin", 0x0000, 0x004000, CRC(4205d5ca) SHA1(ced743a1dee0a6dd1f5a2be8e4bddcd2ec875d23) ) + ROM_LOAD( "rambowgambler320.bin", 0x0000, 0x004000, CRC(72415a35) SHA1(822393f300d5fe3932e546dd1f7ec8feda57ebed) ) +// Scoop (Peter Simper) + ROM_LOAD( "scoopv-2.p1", 0x0000, 0x001000, CRC(e937e298) SHA1(edb4dfb5afd6c2640b6bbd83be591987225bd8fc) ) + ROM_LOAD( "scoopv-2.p2", 0x0000, 0x001000, CRC(2a97a254) SHA1(a249e013d86f7e65e43b07ff916c4d0fd5099f44) ) + ROM_LOAD( "scoopv-2.p3", 0x0000, 0x001000, CRC(34ab1805) SHA1(1e389e9b47c4b3305ec70c94f49a4e3ca0a6f439) ) +// Shogun (Bellfruit) // Scorpion encode, but missing 2nd part with vectors? + ROM_LOAD( "shogun.bin", 0x0000, 0x008000, CRC(38d25549) SHA1(50ac02b6fdaa0b4960f0de4ed28c8c4d8d23cbcf) ) +// Stars 'n' Bars (Unk) + ROM_LOAD( "snbars.bin", 0x0000, 0x008000, CRC(199cb8c9) SHA1(08c123f8eb7a239a397558945b00a61a45cb2154) ) +// Talk Of The Town (Unk) + ROM_LOAD( "ttown1.bin", 0x0000, 0x001000, CRC(996c435b) SHA1(1fcf5a637cddacd6660da752a1fe10e56a7653c7) ) + ROM_LOAD( "ttown2.bin", 0x0000, 0x001000, CRC(93bd6446) SHA1(ef271bb45d27844f0ef1437bbc7f4847f4c0c6ee) ) + ROM_LOAD( "ttown3.bin", 0x0000, 0x001000, CRC(0ca34690) SHA1(1734692d82af89272a2243e2c5f584965bfe197f) ) +// Universal Programmer (Unk) + //ROM_LOAD( "job15r", 0x0000, 0x0092ac, CRC(3c39e49f) SHA1(d45e4c490cf90b707551fd3df21f6e35d326eaf6) ) // text file +// zzz-unk ee2_519a (Unk) + ROM_LOAD( "ee2_519a", 0x0000, 0x030050, CRC(11af495c) SHA1(b035dd622ed8fa8d2e28f05a559c25049e042f67) ) +// zzz_unk 001 (Unk) + ROM_LOAD( "rom1", 0x0000, 0x000400, CRC(1a1f0d76) SHA1(a47addd727460e379f6106e059d43b3fd4e4a34e) ) + ROM_LOAD( "rom2", 0x0000, 0x000400, CRC(66ac392f) SHA1(b0e841669fe97c6edbd0b0830dd7dd84e354ef29) ) + ROM_LOAD( "rom3", 0x0000, 0x000400, CRC(d02d2983) SHA1(9e9e106083dfea44228ae56e73a3fe7184fdb473) ) + ROM_LOAD( "rom4", 0x0000, 0x000400, CRC(da6421b8) SHA1(d3099d94d722e3e12ade712842261aac8b45f9f4) ) + ROM_LOAD( "rom5", 0x0000, 0x000400, CRC(66ac392f) SHA1(b0e841669fe97c6edbd0b0830dd7dd84e354ef29) ) + ROM_LOAD( "rom6", 0x0000, 0x000400, CRC(66ac392f) SHA1(b0e841669fe97c6edbd0b0830dd7dd84e354ef29) ) + ROM_LOAD( "rom7", 0x0000, 0x000400, CRC(3700a7a3) SHA1(cf24a54e6aa3a3a86ff75f6e8bcb692d0cfd0e80) ) + //rom8 = 7.bn galaxbsf Galaxian (bootleg) + ROM_LOAD( "rom9", 0x0000, 0x000400, CRC(fdc857b4) SHA1(3b89f0cd5e8ed73c2e3cded1edc64d23d0fefa54) ) + //rom10 = 7.bn galaxbsf Galaxian (bootleg) + ROM_LOAD( "rom11", 0x0000, 0x000400, CRC(51923338) SHA1(ee29a3e187a5fce82c422c3aafbf6446d3463cc3) ) + ROM_LOAD( "rom12", 0x0000, 0x000400, CRC(656a134b) SHA1(6027480a3bf49da3fac6351f54c286c5de3752ee) ) + ROM_LOAD( "rom13", 0x0000, 0x000400, CRC(8b181929) SHA1(c7e789d1a76e8db0251ac4c75aa85f0a4259fc81) ) + ROM_LOAD( "rom14", 0x0000, 0x000400, CRC(5c65cfc6) SHA1(b04892e932c03d7c500e272eff2252b558b6f37f) ) + ROM_LOAD( "rom15", 0x0000, 0x000400, CRC(4a30ba0e) SHA1(42af9a91760cfd535d3dac2972101af1444750ca) ) + ROM_LOAD( "rom16", 0x0000, 0x000400, CRC(69243c04) SHA1(958791fbd515ab6e2b38391527b611977303ad10) ) + ROM_LOAD( "rom17", 0x0000, 0x000400, CRC(3700a7a3) SHA1(cf24a54e6aa3a3a86ff75f6e8bcb692d0cfd0e80) ) + ROM_LOAD( "rom18", 0x0000, 0x000400, CRC(3700a7a3) SHA1(cf24a54e6aa3a3a86ff75f6e8bcb692d0cfd0e80) ) + ROM_LOAD( "rom19", 0x0000, 0x000400, CRC(52e9709a) SHA1(0b437834f48ca7718e0b30303916eed00c7fb4c9) ) + // rom20 = ewn1.bin j_ewnda Each Way Nudger (Barcrest?, set 2) + ROM_LOAD( "rom21", 0x0000, 0x000400, CRC(6b93d262) SHA1(39fce614845ba1d59e27e678318b1a9331797a9b) ) + ROM_LOAD( "rom22", 0x0000, 0x000400, CRC(73342376) SHA1(8ec9b57076465a64248f1eb02ca9e7a79ea0b993) ) + ROM_LOAD( "rom23", 0x0000, 0x000400, CRC(6b93d262) SHA1(39fce614845ba1d59e27e678318b1a9331797a9b) ) + ROM_LOAD( "rom24", 0x0000, 0x000400, CRC(357d963e) SHA1(8ee43c7cbb3ea52f42e56cb6168c9aff5d279886) ) + ROM_LOAD( "rom25", 0x0000, 0x000400, CRC(8f00ce85) SHA1(9286f88f414db124a8d4b08bfddda032282752e4) ) + ROM_LOAD( "rom26", 0x0000, 0x000400, CRC(7fca2306) SHA1(1b1f1f5fc4fd1834b1c672d239a1c4375366b72a) ) + ROM_LOAD( "rom27", 0x0000, 0x000400, CRC(6669330b) SHA1(e3b83a6a24474fd9469f943a681755458752ab69) ) + ROM_LOAD( "rom28", 0x0000, 0x000400, CRC(7a5ab4b4) SHA1(6234e11c906e183cd12d42195701eb818aaf2b22) ) + ROM_LOAD( "rom29", 0x0000, 0x000400, CRC(9b9438fc) SHA1(65c6283bbfe9bed65f3aaaa051cf9ad277f758cd) ) + ROM_LOAD( "rom30", 0x0000, 0x000400, CRC(3700a7a3) SHA1(cf24a54e6aa3a3a86ff75f6e8bcb692d0cfd0e80) ) + ROM_LOAD( "rom31", 0x0000, 0x000400, CRC(9f12febb) SHA1(52f0243ab18f5fe4c2ddc43727e88cc9edf4c487) ) + ROM_LOAD( "rom32", 0x0000, 0x000400, CRC(660cb6d1) SHA1(15332d295e615298b822c31fcec7278843d8894a) ) + ROM_LOAD( "rom33", 0x0000, 0x000400, CRC(82d974b4) SHA1(2e10b40cf45c0aa7669e8bb046382982de1e77e3) ) + ROM_LOAD( "rom34", 0x0000, 0x000400, CRC(3522d990) SHA1(27544c318acfd5706b6c520b94acde3b9fe763f1) ) + ROM_LOAD( "rom35", 0x0000, 0x000400, CRC(c87e98d9) SHA1(840f0f01aacb3df1cce4d75635de476bd615680b) ) + ROM_LOAD( "rom36", 0x0000, 0x000400, CRC(82d974b4) SHA1(2e10b40cf45c0aa7669e8bb046382982de1e77e3) ) + ROM_LOAD( "rom37", 0x0000, 0x000400, CRC(cd9ac1cd) SHA1(e5983145e52843be701752c7fb52a99d799a489d) ) + ROM_LOAD( "rom38", 0x0000, 0x000400, CRC(ee4a4809) SHA1(292a12a5ddc5a22c8568016b34dfec7959f49027) ) + ROM_LOAD( "rom39", 0x0000, 0x000400, CRC(52e9709a) SHA1(0b437834f48ca7718e0b30303916eed00c7fb4c9) ) + ROM_LOAD( "rom40", 0x0000, 0x000400, CRC(3700a7a3) SHA1(cf24a54e6aa3a3a86ff75f6e8bcb692d0cfd0e80) ) + ROM_LOAD( "rom41", 0x0000, 0x000400, CRC(5eb95f74) SHA1(3bdb8e871cdc597187fb4ae1b9909209ef4ef93d) ) + ROM_LOAD( "rom42", 0x0000, 0x000400, CRC(a0059ddd) SHA1(06bc3bd5eef9fea9e038ec08e5a228ab19f31a56) ) + //rom43 = 3.bn galaxbsf Galaxian (bootleg) + //rom44 = 3.bn galaxbsf Galaxian (bootleg) + ROM_LOAD( "rom45", 0x0000, 0x000400, CRC(331762cd) SHA1(3cd9f54c18416b626fb0450fb0609ac126306ff0) ) + //rom46 = 6.bn galaxbsf Galaxian (bootleg) + //rom47 = 5.bn galaxbsf Galaxian (bootleg) +// zzz_unk 017 (Unk) + ROM_LOAD( "misc2.bin", 0x0000, 0x010000, CRC(f9b9cd85) SHA1(ca16f4c8b95d3625918756b9c26a0995f9161dab) ) +// zzz_unk 94cd910 (Unk) + ROM_LOAD( "94cd910", 0x0000, 0x004000, CRC(0340ef85) SHA1(f55dbe86a0d6b16aa62ab7ed922ff83d4fbecb04) ) +// zzz_unk aa31 (Unk) + ROM_LOAD( "aa31", 0x0000, 0x010000, CRC(2086f3a2) SHA1(13a75b5e0c1533af3e5d255182a7e6ec88d59826) ) +// zzz_unk aladdinprm (Unk) + ROM_LOAD( "aladdinprm", 0x0000, 0x010000, CRC(1a618500) SHA1(4af077bf8f6a74eae20aedf39c2df447670128f4) ) +// zzz_unk all32 (Unk) + ROM_LOAD( "all32", 0x0000, 0x020000, CRC(1d56097c) SHA1(aab18041b39c904113f5f11dc81149abec871a56) ) +// zzz_unk all41meg (Unk) + ROM_LOAD( "all41meg", 0x0000, 0x020000, CRC(317b61d2) SHA1(52fb22744efda5d236af030bb18f8248a4c19cf8) ) +// zzz_unk all4512 (Unk) + ROM_LOAD( "all4512", 0x0000, 0x010000, CRC(bf34acb0) SHA1(290307f2bed9d11adb7e91a403c973d3266e04c7) ) +// zzz_unk alladin2 (Unk) + ROM_LOAD( "alladin2", 0x0000, 0x020000, CRC(bb8b253b) SHA1(b604a3bcd9db16e84cb5c501cd625ad05a8607dd) ) +// zzz_unk astros_1 (Unk) + ROM_LOAD( "07c1t0.400", 0x0000, 0x0271d4, CRC(1c3236c7) SHA1(c6179fff16f9d8472675c307d9ab0bce5a4e17c1) ) + ROM_LOAD( "07c1t1.400", 0x0000, 0x027357, CRC(b2cac9b3) SHA1(d39266e68bdbca8ac7f19dd617d8c43670cbbe01) ) + ROM_LOAD( "g07n0227.144", 0x0000, 0x0d5676, CRC(b332820b) SHA1(871a6af360c089948082b8859bbd688812425ca6) ) + ROM_LOAD( "g07t0227.145", 0x0000, 0x0d581c, CRC(1385cb9f) SHA1(5ecc2854fb82f3a5c17eca381b6f0c02ae0a0e42) ) + ROM_LOAD( "g26n0227.242", 0x0000, 0x0d5676, CRC(82679c2f) SHA1(5f45e51b3a5f5f2eea93ace6e9c1c120c9e9c8bb) ) + ROM_LOAD( "g26t0227.243", 0x0000, 0x0d5c12, CRC(ab0760b7) SHA1(9dcad1e21d2d7d0e17baca3e20d375dfdcbbbb8a) ) +// zzz_unk bgl01 (Unk) + ROM_LOAD( "bgl01", 0x0000, 0x013ee2, CRC(dcc23e51) SHA1(5883c3d0c1cb7a8e11647218310a3f34c9c7c661) ) +// zzz_unk bre (Unk) + ROM_LOAD( "bre01", 0x0000, 0x013ee2, CRC(c1abf402) SHA1(526c30271227479877075dd259d20b3ede558d05) ) + ROM_LOAD( "bre02", 0x0000, 0x00f6e2, CRC(b7bb7d4c) SHA1(2b9860a6880259d5e96007d09289d30c543cf545) ) + ROM_LOAD( "bre03", 0x0000, 0x010ee2, CRC(2ccd60be) SHA1(056611af30fc39b437aca4e81f0d961834b4a6a3) ) + ROM_LOAD( "bre04", 0x0000, 0x00f6e2, CRC(2cf7f87c) SHA1(546ac9aae295ce389ecddb87253b6c3e9a6c81ce) ) + ROM_LOAD( "bre05", 0x0000, 0x013ee2, CRC(6747a021) SHA1(18f1e671cacdcbbe50289529f3f51446234d794b) ) +// zzz_unk ccc (Unk) + ROM_LOAD( "ccc2", 0x0000, 0x010000, CRC(2df7f687) SHA1(1ee92678944d72577e024ea948c86e89b2035722) ) + ROM_LOAD( "ccc3", 0x0000, 0x020000, CRC(7b02d860) SHA1(e3f879f031135bb6f64de3c44022982e4c321cb2) ) +// zzz_unk cdvnv (Unk) + ROM_LOAD( "cdvnv12", 0x0000, 0x004000, CRC(f49bb59c) SHA1(21184d068a38556ee06ba046ce5181b86c18234b) ) + ROM_LOAD( "cdvr92", 0x0000, 0x004000, CRC(61a8372e) SHA1(74290a034964f921a58a90b497345b4dd271a431) ) +// zzz_unk chf (Unk) + ROM_LOAD( "chf01", 0x0000, 0x013ee2, CRC(13fb2a42) SHA1(6f5434136a420d94f51c721fd03c65f268ee238b) ) + ROM_LOAD( "chf02", 0x0000, 0x00c6e2, CRC(bb9be889) SHA1(a23bfc224f1d9d5c13d3ef16419c46dde28531f2) ) + ROM_LOAD( "chf03", 0x0000, 0x00f6e2, CRC(79fa2dac) SHA1(2ec56feb8d2c38c4c0b59b4bc650daf0d5873f30) ) + ROM_LOAD( "chf04", 0x0000, 0x0036e2, CRC(ad6b71d2) SHA1(eec495b25b38e15f2a2bd35d2db8f0a6ecf98d62) ) +// zzz_unk classicsnd (Unk) + ROM_LOAD( "classicsnd0.bin", 0x0000, 0x020000, CRC(e23bd795) SHA1(8297256b0ee0c15d304c74ab2b7f8eb4891ff1fa) ) + ROM_LOAD( "classicsnd1.bin", 0x0000, 0x020000, CRC(c18ed56f) SHA1(36c2d6df2bf65c6d47500bcd0cfd0e45b5dfeaf4) ) + ROM_LOAD( "classicsnd2.bin", 0x0000, 0x020000, CRC(bee8cc32) SHA1(8d8e0087221710476ec9221ec335545739a926f3) ) +// zzz_unk classv (Unk) [Rom] SCORPION + ROM_LOAD( "classv1.2a.bin", 0x0000, 0x008000, CRC(26930c24) SHA1(2c634171d7e63839b4f8e7f9efcd2924bd38e375) ) + ROM_LOAD( "classv1.2b.bin", 0x0000, 0x008000, CRC(9d98d723) SHA1(afc1ae0bfcf6ecfc6eee2583e6fa31aca6e30550) ) +// zzz_unk cro (Unk) + ROM_LOAD( "cro01", 0x0000, 0x00f6e2, CRC(58b9481d) SHA1(9bdc54b5ef37fb818a02eb5c839667e0b883852e) ) + ROM_LOAD( "cro02", 0x0000, 0x007ee2, CRC(9a6dd9ec) SHA1(a173d65f78d133d319cbc4ac7311f3bbadef0a8d) ) +// zzz_unk csk (Unk) + ROM_LOAD( "csk01", 0x0000, 0x00aee2, CRC(8f5eb65c) SHA1(011ffaf8cb1af461688b992e6d161234cf90af78) ) + ROM_LOAD( "csk04", 0x0000, 0x007ee2, CRC(d461662c) SHA1(50713d62a67d972d6e47371afe436a4c7f7ea9d5) ) + ROM_LOAD( "csk05", 0x0000, 0x0066e2, CRC(dc73a53b) SHA1(85bb964231187fcf38fd0ad83f0cd6f024387331) ) + ROM_LOAD( "csk06", 0x0000, 0x008ae2, CRC(0e507f6b) SHA1(5c11125bb3a14df7d37a14b006283f6da851380b) ) + ROM_LOAD( "csk08", 0x0000, 0x008ae2, CRC(74c19b54) SHA1(12a2b7c29a95fca095c72deb79b88302e811afbb) ) + ROM_LOAD( "csk09", 0x0000, 0x0096e2, CRC(b63908e8) SHA1(f78b4163e8d7a2d3910a00607fb1e219650608e6) ) + ROM_LOAD( "csk10", 0x0000, 0x0072e2, CRC(043846e3) SHA1(b55964b71630f14c127412c4c74d85a5de86b287) ) + ROM_LOAD( "csk11", 0x0000, 0x008ae2, CRC(7d64ab44) SHA1(2d0e9bc59652a76af2ce75f108f78e45d337b16b) ) + ROM_LOAD( "csk12", 0x0000, 0x007ee2, CRC(f77e2605) SHA1(379fa9bdf90f348de453f94a469a505c914cfc30) ) +// zzz_unk ddav (Unk) + ROM_LOAD( "ddav12", 0x0000, 0x002000, CRC(aceba7f4) SHA1(b1e5ae8932fc8fd8ac3eb06b67911fb112fbf808) ) + ROM_LOAD( "ddav12&2", 0x0000, 0x002000, CRC(aceba7f4) SHA1(b1e5ae8932fc8fd8ac3eb06b67911fb112fbf808) ) +// zzz_unk dem (Unk) + ROM_LOAD( "dem01", 0x0000, 0x00dee2, CRC(71829408) SHA1(cba53dc8882ed0fe7ff06dcf6d8f08ef7668952a) ) + ROM_LOAD( "dem02", 0x0000, 0x0066e2, CRC(8887388b) SHA1(72eb781b2ec785db9dcb981643007586bf628c23) ) + ROM_LOAD( "dem03", 0x0000, 0x00aee2, CRC(a32ea48d) SHA1(e607e97766f76dd74476815a5248e21f11e8f92e) ) + ROM_LOAD( "dem04", 0x0000, 0x0036e2, CRC(86387b3c) SHA1(24021823b135e813a24589a1b81be3c811a3d51f) ) +// zzz_unk demats01 (Unk) + ROM_LOAD( "demats01", 0x0000, 0x00b4e2, CRC(0c65c583) SHA1(df97306745f7147016e1b85204f3c858d7dc760f) ) +// zzz_unk demgbp01 (Unk) + ROM_LOAD( "demgbp01", 0x0000, 0x00dee2, CRC(d99f7e8b) SHA1(61abbc50353acedc0e99e76d227d6c4c23af3b53) ) +// zzz_unk denlgb01 (Unk) + ROM_LOAD( "denlgb01", 0x0000, 0x016ee2, CRC(afbef1db) SHA1(3a528b80bbbfcb7894df05bc0a7b0d885660f280) ) +// zzz_unk esp (Unk) + ROM_LOAD( "esp01", 0x0000, 0x0090e2, CRC(e7ca0bca) SHA1(35591d1d04a0c5edc0a41b07b59579304af07632) ) + ROM_LOAD( "esp03", 0x0000, 0x0060e2, CRC(df1322ed) SHA1(a6be1a73dabef045cddd3eef215686d411358cc4) ) + ROM_LOAD( "esp04", 0x0000, 0x0060e2, CRC(ebcb9337) SHA1(bf58afd874e7a710ff2c36f242d24f73a8041686) ) + ROM_LOAD( "esp05", 0x0000, 0x0030e2, CRC(e4ce8ee7) SHA1(19f253fa47406a98bdf115dcf4607023d2eb0202) ) +// zzz_unk g26n0233 (Unk) + ROM_LOAD( "g26n0233.253", 0x0000, 0x0f3cf6, CRC(d3d98cd7) SHA1(2500dc34b39399cad22b2cff0dd83239b4652790) ) +// zzz_unk game1 (Unk) + ROM_LOAD( "game1", 0x0000, 0x009a0d, CRC(89f6fd63) SHA1(7e87740138a6c6e9502e654dc27ad828fe9b793a) ) +// zzz_unk game2 (Unk) + ROM_LOAD( "game2", 0x0000, 0x009a0d, CRC(bf1f1f02) SHA1(be85da267470435d23f9d61c52a4fc446b73d7e7) ) +// zzz_unk hazelgrove_superleague (Unk) + ROM_LOAD( "hazelgrove_superleague.bin", 0x0000, 0x002000, CRC(01c09d5e) SHA1(be4c00391c150ef2d7ce56c5e39836fd2d0b92ec) ) +// zzz_unk hgmwb43 (Unk) + ROM_LOAD( "hgmwb43", 0x0000, 0x008000, CRC(f929fd3a) SHA1(33cc3169eb0bd82d81086aa09679aaaa95fbc6b1) ) +// zzz_unk ld3_11i (Unk) + ROM_LOAD( "ld3_11i", 0x0000, 0x040000, CRC(b9e7e0a9) SHA1(8cfafa8ec24be030179cc1983586bb03cb4ed44e) ) +// zzz_unk link 3 (Maygay) (unknown cpu) + ROM_LOAD( "oxo_mk3-1.bin", 0x0000, 0x000400, CRC(f20a9cf4) SHA1(c97a125904e96e37e3c54a1ffd3617d7d4e0d48c) ) + ROM_LOAD( "oxo_mk3-2.bin", 0x0000, 0x000400, CRC(915c9513) SHA1(7c584fd4c0ae035446cec4515c525a0d0ddb1fd7) ) + ROM_LOAD( "oxo_mk3-3.bin", 0x0000, 0x000400, CRC(9d1479d5) SHA1(128bfc1e49a8ca65aa7bea6fc83f781140bfe18d) ) + ROM_LOAD( "oxo_mk3-4.bin", 0x0000, 0x000400, CRC(2796991f) SHA1(4bba50509719fff9184cf110cf06394eae880f59) ) +// zzz_unk mal01 (Unk) + ROM_LOAD( "mal01", 0x0000, 0x007ee2, CRC(4e984428) SHA1(149fc45c4ca183521edf9c03f3e428d92bf1da95) ) +// zzz_unk mc2 (Unk) + ROM_LOAD( "mc2", 0x0000, 0x008000, CRC(3cf1eba4) SHA1(275d7c8865f80b95f01d7c8eb143aa9f7a918077) ) +// zzz_unk mota-51 (Unk) + ROM_LOAD( "mota-51a.p1", 0x0000, 0x020000, CRC(1057ad83) SHA1(5df0bc3956c22ae14699607cebc7003152011a54) ) +// zzz_unk nbn 5p (Unk) [Rom] MPU + ROM_LOAD( "nbn 5p 1_6_95.bin", 0x0000, 0x010000, CRC(89e960be) SHA1(f97c9062d4d67c11ef4b8b6a97a8d2cc403038b0) ) + + // zzz_unk pp (Unk) [Rom] Z80? + ROM_LOAD( "pp.p1", 0x0000, 0x001000, CRC(2ab92b46) SHA1(1486751885d832ceb7e936447a9332d69011f62c) ) + ROM_LOAD( "pp.p2", 0x0000, 0x001000, CRC(babf8ffa) SHA1(bb148243eac513de83634203393c2e91c9cf98c9) ) + ROM_LOAD( "pp.p3", 0x0000, 0x001000, CRC(72cde502) SHA1(c0401810dbc04a6eff5a7795120471f3016ff3bf) ) + +// zzz_unk r92rvcd (Unk) + ROM_LOAD( "r92rvcd", 0x0000, 0x004000, CRC(b723db47) SHA1(bda42bb79b9ff15d68dc9868a40f5de2481f129e) ) +// zzz_unk sburgf2 (Unk) + ROM_LOAD( "sburgf2", 0x0000, 0x008000, CRC(c94bb9b6) SHA1(d0b1e1c6152c1be30cba5790c2e984625822504b) ) +// zzz_unk sghost (Unk) + ROM_LOAD( "sghost", 0x0000, 0x010000, CRC(7c453739) SHA1(05724cb23b711a0e4546435622eb6b6ef1ac6894) ) +// zzz_unk shuffle (Unk) + ROM_LOAD( "shuffle1.1", 0x0000, 0x000400, CRC(2eec7c4d) SHA1(a1740d27e60192659392ba7602b9b62947c4f6db) ) + ROM_LOAD( "shuffle1.3", 0x0000, 0x000400, CRC(4084c605) SHA1(b75320c042d3df79fbd8256dc82267bce09b26cc) ) +// zzz_unk sl101a (Unk) + ROM_LOAD( "sl101a.p1", 0x0000, 0x020000, CRC(7f25fa07) SHA1(9d45993f518bd3a6e54ffd358bef937773ac595e) ) +// zzz_unk slcd31 (Unk) + ROM_LOAD( "slcd31", 0x0000, 0x004000, CRC(e07d8a66) SHA1(9f7ed1566e7e4797a3c34d651c79d0fd8d0a8929) ) +// zzz_unk smn (Unk) [Rom] SCP + ROM_LOAD( "smn3v3ih", 0x0000, 0x010000, CRC(97956ceb) SHA1(c833b1efad6058bd7325a4312174bd182609617f) ) + ROM_LOAD( "smn3v3il", 0x0000, 0x010000, CRC(ddde0b8c) SHA1(093c195bde8710b064be54f7913568fcc8834f6e) ) +// zzz_unk sov (Unk) + ROM_LOAD( "sov0-03.u1", 0x0000, 0x080000, CRC(4e2e7a79) SHA1(77f32b43d2e01cb0223feccb9e29c3fde0a6e9b7) ) + ROM_LOAD( "sov0-03.u2", 0x0000, 0x080000, CRC(1ef8712a) SHA1(1a2ef378679384e720e5b20f1420454102f18258) ) + ROM_LOAD( "sov0-03d.u1", 0x0000, 0x080000, CRC(47d5e5ca) SHA1(d3624a8b8545f67d14bee90bc3967c13b8497e5b) ) +// zzz_unk srat (Unk) [Rom] SOUND + ROM_LOAD( "srat1d", 0x0000, 0x020000, CRC(46683be4) SHA1(2b4c04526f0124c239ec5653aaa49a3f11ba5000) ) + ROM_LOAD( "srat5d", 0x0000, 0x020000, CRC(d0f20a9c) SHA1(b3666e8d1063fed05a7f10c99f33a4dce26bf670) ) + ROM_LOAD( "srat6d", 0x0000, 0x020000, CRC(b023a84e) SHA1(f78a55348d0bbae59e10e47fedb30bdd27205b80) ) +// zzz_unk starltv2 (Unk) + ROM_LOAD( "starltv2", 0x0000, 0x004000, CRC(b0d418b1) SHA1(c1363578130bf9d30afb71a4c9b3e6988feb1128) ) +// zzz_unk tempson (Unk) [Rom] SOUND + ROM_LOAD( "tempson.p1", 0x0000, 0x080000, CRC(6a3beebe) SHA1(66bc8e388003c597587fc5fab7653bb2d4b1c815) ) + ROM_LOAD( "tempson.p2", 0x0000, 0x080000, CRC(3282bbfd) SHA1(2165a8a28cc6d47e99d84d660ba9ec3bb1a69aeb) ) +// zzz_unk turbowks (Unk) + ROM_LOAD( "turbowks", 0x0000, 0x000e92, CRC(0a828093) SHA1(ec755638bf25d4a38378cbbc5cf31a2c15f2cf98) ) +// zzz_unk wb (Unk) + ROM_LOAD( "wb10", 0x0000, 0x002000, CRC(4cdf2dc1) SHA1(06776428afe4f19c578f4167585d8183bfafb915) ) + ROM_LOAD( "wb10&5wz", 0x0000, 0x002000, CRC(4cdf2dc1) SHA1(06776428afe4f19c578f4167585d8183bfafb915) ) + ROM_LOAD( "wb11", 0x0000, 0x002000, CRC(4a16d4d2) SHA1(8e7fa08e769e88eaa429ae14f203f3b707897822) ) + ROM_LOAD( "wb11&4cd", 0x0000, 0x008000, CRC(f8d0d1cc) SHA1(1b392d8f1678ef420d007a64c6bdbeff2e8bd569) ) + ROM_LOAD( "wb20", 0x0000, 0x002000, CRC(af4c0793) SHA1(098cd4b3ea63e9dd4b0a0851b1ba9a2a80525630) ) + ROM_LOAD( "wb20&2da", 0x0000, 0x002000, CRC(ba1bf613) SHA1(42f0e5387a942d20c28bb70bfddaff7ef227147b) ) + ROM_LOAD( "wb21", 0x0000, 0x002000, CRC(a0db450b) SHA1(48572767c6b2ab9ffe74c41cb58e0a7634b7f0bd) ) + // wb22 = wb_v22 ep_unsrt Unknown / Unsorted 'Epoch' ROMs + ROM_LOAD( "wb23", 0x0000, 0x002000, CRC(737e4f2b) SHA1(f396a579dcd71050e19db2910a2c0967bacb4e0c) ) + ROM_LOAD( "wb4", 0x0000, 0x008000, CRC(f929fd3a) SHA1(33cc3169eb0bd82d81086aa09679aaaa95fbc6b1) ) + ROM_LOAD( "wb44", 0x0000, 0x002000, CRC(f16acc1e) SHA1(6c51d710d3c850a250bfed3af96e72b0966e782d) ) + ROM_LOAD( "wbl4", 0x0000, 0x002000, CRC(1f44b165) SHA1(097f27306355d1b61c61a6cd34a919b96bed311d) ) + ROM_LOAD( "wbstd44", 0x0000, 0x002000, CRC(f16acc1e) SHA1(6c51d710d3c850a250bfed3af96e72b0966e782d) ) + ROM_LOAD( "wbv11&3", 0x0000, 0x002000, CRC(4a16d4d2) SHA1(8e7fa08e769e88eaa429ae14f203f3b707897822) ) + // wbv22&0 = wb_v22 ep_unsrt Unknown / Unsorted 'Epoch' ROMs +// zzz_unk wishsound (Unk) [Rom] SOUND + ROM_LOAD( "wishsound1.bin", 0x0000, 0x080000, CRC(4c8fe9e5) SHA1(9046413c885454e1942c0b92b647598a660f3487) ) + ROM_LOAD( "wishsound2.bin", 0x0000, 0x080000, CRC(c5a91e30) SHA1(b7e4d78ce11bace2ae2bf30db7e5c6b4ebfe6c62) ) + ROM_LOAD( "wishsound3.bin", 0x0000, 0x080000, CRC(b9911a66) SHA1(782513afa16c0efc71cff467a1f055f1590674d5) ) +// Accepter GBA (JPM) + ROM_LOAD( "58c1.190", 0x0000, 0x0269fe, CRC(140592da) SHA1(0362d6b7d0e21a1593f3c89ce5c06072e93ec93c) ) + ROM_LOAD( "58r1.190", 0x0000, 0x0269fe, CRC(73e09e0e) SHA1(be57518033bbc1492953d8552c5a617a9977294f) ) + ROM_LOAD( "58s.190", 0x0000, 0x0269fe, CRC(e965c0a1) SHA1(dd0a377fbcb257d9a1de39ffc52a4c34fe17ba2e) ) + ROM_LOAD( "g58n0245.148", 0x0000, 0x0f8e1e, CRC(c815f689) SHA1(e57c5aa3bb6d9296320882fdc55cff7f5eb0ad99) ) +// bfmulator.zip.... + ROM_LOAD( "showtime.bin", 0x0000, 0x010000, CRC(75cb4ebf) SHA1(24e56f00502628332130b56a93847436d7125f46) ) + ROM_LOAD( "bt6-c4_0.bin", 0x0000, 0x010000, CRC(74070e83) SHA1(42ffffb62ea74eaa8d3938dee45b5beaca64a320) ) + ROM_LOAD( "club-wild-west_std_ac_var_ffp_ass1.bin", 0x0000, 0x010000, CRC(2f639748) SHA1(95ddc75bd475789ff4bb48c678f72c081cc85f92) ) +// Brain Box (Bellfruit) + ROM_LOAD( "bbb10.bin", 0x0000, 0x010000, CRC(76d061ba) SHA1(d2d5cb9c24ef04a13c649781fe7c67b13415aa4b) ) +// Brain Box 2 (Bellfruit) + ROM_LOAD( "39360122.p1", 0x0000, 0x008000, CRC(949778b3) SHA1(b40e2ca1bfe91b93165df38ddf84a1d5a6cf6ce2) ) + ROM_LOAD( "39361122.p1", 0x0000, 0x008000, CRC(597bea46) SHA1(23cb9ce90508525c84befefafc171841989f6c38) ) + ROM_LOAD( "bboxint", 0x0000, 0x008000, CRC(ecd2a1d1) SHA1(f9e77fb63f20748f644ab270b56a68e9e53b77f9) ) +// Cash Attraction (Bellfruit) + ROM_LOAD( "95727239.bin", 0x0000, 0x008000, CRC(e3f28981) SHA1(9e56a05fab5aad60d07e18ad1d2ef75cfeb41229) ) +// Flash Back (Bellfruit) (bad? both halves identical, no boot vectors) + ROM_LOAD( "958400.54 20p 6.bin", 0x0000, 0x008000, CRC(13410929) SHA1(e5414ec8fef29de8c5ae3368aa6af22c03cdc592) ) + ROM_LOAD( "958400.55 20p 6.bin", 0x0000, 0x008000, CRC(cc449195) SHA1(4b4b0263748657ca76607653e878938814569a89) ) +// Grid Runner (Global) + ROM_LOAD( "gddl2-4n.p1", 0x0000, 0x020000, CRC(95e4e432) SHA1(ca3ce326da792a19075d89c957e5661513ed0e0d) ) +// Hi Noon (JPM) + ROM_LOAD( "hino-snd.bin", 0x0000, 0x080000, CRC(cf93186d) SHA1(5d190e24d702bbb396d69497b71e9a8ac51e6c6f) ) +// James Bond - Licence To Kill (Maygay) + ROM_LOAD( "james_bond_1.1", 0x0000, 0x01681e, CRC(964d3721) SHA1(6a4e893e0dc0542a3ab81246a40392f927acaffe) ) +// Loto (Maygay) [Spain] + ROM_LOAD( "sj6-586", 0x0000, 0x020641, CRC(853c0c9c) SHA1(42465d15336fe81885f32ea8522a5331fc2d49de) ) +// Lucky Strike (Barcrest) + ROM_LOAD( "lstrikesnd-p1.bin", 0x0000, 0x020000, CRC(0c8f9dcd) SHA1(026be80620bd4afc3e45cb7a374b93fff4c13dd2) ) + ROM_LOAD( "lstrikesnd-p2.bin", 0x0000, 0x020000, CRC(2a746ba5) SHA1(7f9d727a849a7a1ecfd750f214deef150ec3d9eb) ) +// Monte Carlo (Ace) + ROM_LOAD( "monte_carlo_1.1", 0x0000, 0x168095, CRC(96f09fe9) SHA1(1fc2ad662c7e90d580cc9f9753fa6fc48f955636) ) + ROM_LOAD( "monte_carlo_1.2", 0x0000, 0x168095, CRC(ea4a8a60) SHA1(dff6f043c0ee2921367689394b73b221336cdc98) ) + ROM_LOAD( "monte_carlo_1.3", 0x0000, 0x168095, CRC(2628d037) SHA1(8754b9e40a5f815b68b4c341705e587d25db710d) ) + ROM_LOAD( "monte_carlo_1.4", 0x0000, 0x168095, CRC(f9486358) SHA1(868aef1983855e028ed3d4f4996b393774427c13) ) +// Note Acceptor Firmware (Misc) + ROM_LOAD( "ara01", 0x0000, 0x00f6e2, CRC(54ddfb81) SHA1(b1e84ff1afdce40925558d6e454bea7444e59851) ) + ROM_LOAD( "ara02", 0x0000, 0x00c6e2, CRC(043f2326) SHA1(69deef6226c9a55c7ed3a404860de38785157add) ) + ROM_LOAD( "ara05", 0x0000, 0x00c6e2, CRC(64c3051e) SHA1(0fdaa125f78476f67308ecb2ca3f89f709dc1bb7) ) + ROM_LOAD( "ats01", 0x0000, 0x00aee2, CRC(d26d3a31) SHA1(a4ede43d7424e06362933ed270a23f97fd7b07d3) ) + ROM_LOAD( "ats06", 0x0000, 0x007ee2, CRC(d59f9a0b) SHA1(264d984773eb5bc2c498e56584c3eaa51092caea) ) + ROM_LOAD( "ats07", 0x0000, 0x0096e2, CRC(fbdfd213) SHA1(8c734613b8f9af2cf41fcdd2392143593da37c7a) ) + ROM_LOAD( "ats08", 0x0000, 0x0066e2, CRC(1e526dfd) SHA1(2f9aba00695fc917d548049eae41bc341ccdb233) ) + ROM_LOAD( "ats09", 0x0000, 0x0084e2, CRC(f3a891dc) SHA1(7b7ca77bd07e23c3d9eb84e6338871e4e13b86b6) ) + ROM_LOAD( "ats10", 0x0000, 0x007ee2, CRC(18b48d22) SHA1(d433ab40c882c35bb62b489fd8aa51f739b9a93d) ) + ROM_LOAD( "ats11", 0x0000, 0x0066e2, CRC(c431f6b3) SHA1(6e7bd2c10ced131d626bfa175e9a7a67adb47253) ) + ROM_LOAD( "ats12", 0x0000, 0x0036e2, CRC(f3c2f24b) SHA1(422985f418c982e074803ebee4331f22650a61c4) ) + ROM_LOAD( "ats13", 0x0000, 0x004ee2, CRC(9ec00b5a) SHA1(2b4ed3788b0ca52f07b53e7cfc20c176b64bf237) ) + ROM_LOAD( "ats14", 0x0000, 0x0096e2, CRC(10f09ebb) SHA1(5d200be36773dec5b9fe1b784e4ada89b8002f13) ) + ROM_LOAD( "aud01", 0x0000, 0x00f6e2, CRC(e596ca9c) SHA1(e046c305161e3f463874c0eb9c0d267f5054233d) ) + ROM_LOAD( "aud02", 0x0000, 0x00dee2, CRC(fd1692aa) SHA1(7e71301a6cf8155119022de0f28c0898a2c96d5c) ) + ROM_LOAD( "aud03", 0x0000, 0x00c6e2, CRC(97c59544) SHA1(2043beba1400af7500df80bdd80d5ceb86bfcbf3) ) + ROM_LOAD( "bef01", 0x0000, 0x0138e2, CRC(d40b68eb) SHA1(d242d1ca22181a3ffab99b6f6ee697f91a1331ec) ) + ROM_LOAD( "bef02", 0x0000, 0x00eae2, CRC(d134753e) SHA1(67141048b1644baa7d587fa92556065dcb601655) ) + ROM_LOAD( "bef03", 0x0000, 0x00f0e2, CRC(6e7aeac0) SHA1(86d2c66188606345858199d8892d3b9c5bbe5cad) ) + ROM_LOAD( "bef04", 0x0000, 0x00d8e2, CRC(95ed6452) SHA1(771c27448c7210e47ab9a53f9943d216bce6dc53) ) + ROM_LOAD( "bef05", 0x0000, 0x00b4e2, CRC(3deb4219) SHA1(725aac66cc2d2a7bbb0a818034ec643cc855e50c) ) + ROM_LOAD( "bef06", 0x0000, 0x00eae2, CRC(55cc8ed4) SHA1(b96b99e390a1e8d7cfb89ec72fea7781e1eeea0c) ) + ROM_LOAD( "bef07", 0x0000, 0x0120e2, CRC(fe520418) SHA1(3f6ed4613d5f28bbb7bf4679f0a3c0842428216d) ) + ROM_LOAD( "bef08", 0x0000, 0x0102e2, CRC(a8291d68) SHA1(8c2241a24c3d8ca6dd6a4df7da91231448b7481a) ) + ROM_LOAD( "beffrf01", 0x0000, 0x00aee2, CRC(795c2339) SHA1(e51c5232dad7b1745399ca1bae4b68c7a8bb502b) ) + ROM_LOAD( "bnd01", 0x0000, 0x0066e2, CRC(f6be953f) SHA1(d225e6d72fdd025863ce1d76a6674d80ca9e36c5) ) + ROM_LOAD( "ccu0912", 0x0000, 0x010000, CRC(2ca61fdb) SHA1(54bb39f4fdf115b293e7b2f45d170fdecaf80aea) ) + ROM_LOAD( "ccu1012", 0x0000, 0x010000, CRC(860197a5) SHA1(11981df44368a8bd75ead9962972fffbf5e2147e) ) + ROM_LOAD( "cny01", 0x0000, 0x0180e2, CRC(38073629) SHA1(3a4ee9f60466dc9a84f22ff11ced372f8a477247) ) + ROM_LOAD( "cny02", 0x0000, 0x0168e2, CRC(7dd11dda) SHA1(0cb857eca1809b78d9771b5579a4b0f0fbb1021b) ) + ROM_LOAD( "cny03", 0x0000, 0x00c6e2, CRC(d103d871) SHA1(5546d5cb8e79d53ead6be609d815e522d2203699) ) + ROM_LOAD( "cny04", 0x0000, 0x017ae2, CRC(899f2c57) SHA1(7a60188dea28e78f831d708ad5c159fa45d0766a) ) + ROM_LOAD( "cop02", 0x0000, 0x0096e2, CRC(72028f78) SHA1(271342b08efec07576ab73f63c4041de0221cd49) ) + ROM_LOAD( "copo1", 0x0000, 0x0066e2, CRC(3eb6b78c) SHA1(0476c120fd38d9f7a343f323b1fec3224a74125d) ) + ROM_LOAD( "dkk01", 0x0000, 0x00f6e2, CRC(e2cc90f9) SHA1(2d2fffb9ba288590aa877eedee9ecc301627db4d) ) + ROM_LOAD( "dkk02", 0x0000, 0x00dee2, CRC(e0959343) SHA1(65fd485772e2851e8b5d204b2e4f862e4f6669ef) ) + ROM_LOAD( "dkknok02", 0x0000, 0x00dee2, CRC(1f3ac0b6) SHA1(e2098cb69f60c3b742476f49e83d25098ec22057) ) + ROM_LOAD( "dknogb01", 0x0000, 0x0108e2, CRC(fadb6284) SHA1(5b89d67b78ed9960df250facf333c7ffdbb893e0) ) + ROM_LOAD( "dpdfrf01", 0x0000, 0x007ee2, CRC(8fe65917) SHA1(c444c0475d7e1f080101ae588c2dfeb282f6a5d7) ) + ROM_LOAD( "eba-22", 0x0000, 0x040000, CRC(16974672) SHA1(c5cde3a167da1f63093d0a7a786be881c69cfaf0) ) + ROM_LOAD( "ecs01", 0x0000, 0x0066e2, CRC(8de6e3de) SHA1(68026884ce045e74cb20e907bdb11dc45d64a80c) ) + ROM_LOAD( "eek01", 0x0000, 0x0114e2, CRC(429a3ad2) SHA1(5db1f12a713216a262b5c1820cb5e19e51d18aa5) ) + ROM_LOAD( "eek02", 0x0000, 0x0090e2, CRC(9102d2c9) SHA1(e2dc3c53f405a25ca8fed063a642c69881b422ee) ) + ROM_LOAD( "eek04", 0x0000, 0x00a2e2, CRC(9bd6d717) SHA1(10850777c625a3e373b98cb5067cb7e943cb8a46) ) + ROM_LOAD( "fim01", 0x0000, 0x007ee2, CRC(4206f550) SHA1(3bdb54565d0b2cf316e205a9c5a76d25ac624a6e) ) + ROM_LOAD( "gbp01", 0x0000, 0x007ee2, CRC(64bd7bf8) SHA1(7e0c851e3c2de33580e5d0865c742780546f7e32) ) + ROM_LOAD( "gbp02", 0x0000, 0x00f6e2, CRC(67e2673f) SHA1(dc9acb3c3522d2b82f9660871b27f61e921f03a3) ) + ROM_LOAD( "gbp04", 0x0000, 0x00dee2, CRC(1e271034) SHA1(6308498ed3c6b0333f7aad0bd0345655de2a44e9) ) + ROM_LOAD( "gbp06", 0x0000, 0x0180e2, CRC(88815056) SHA1(d7c80e733e908f4c5d765816e2fe0b7718f8e390) ) + ROM_LOAD( "gbp08", 0x0000, 0x0180e2, CRC(649684a8) SHA1(bafdddddd18116cd07af6985ecdae8d614b9e9f1) ) + ROM_LOAD( "gbp09", 0x0000, 0x016ee2, CRC(d168781c) SHA1(39174cf339de3c98c8cc1a8e862f91a1dd08b127) ) + ROM_LOAD( "gbp10", 0x0000, 0x007ee2, CRC(8b430e40) SHA1(61171e1d5d115ebd84fa6422a781db6365f7ea35) ) + ROM_LOAD( "gbp11", 0x0000, 0x00dee2, CRC(2a6dfd99) SHA1(661ecfab6e534d606fbb22d0ef682d087e63d75f) ) + ROM_LOAD( "gbp12", 0x0000, 0x0096e2, CRC(1901c60b) SHA1(d1c77b56b8ef3716efcd703c12c74c82b4d407b3) ) + ROM_LOAD( "gbpnlg01", 0x0000, 0x017ae2, CRC(9bd781c3) SHA1(7499e3767966955a6d09079a22324ae1a7a9551a) ) + ROM_LOAD( "grd01", 0x0000, 0x010ee2, CRC(2ceb7d40) SHA1(6d4360aeac6d13033f93b13e4e3d1d9626795bf3) ) + ROM_LOAD( "grd02", 0x0000, 0x00c6e2, CRC(49949463) SHA1(15875951c4bb17e90accd8031534df3bf11aa613) ) + ROM_LOAD( "grd04", 0x0000, 0x00aee2, CRC(d09f40a9) SHA1(72ddb78827cd9d710fb73ab512ad3fb8baa9d144) ) + ROM_LOAD( "grd05", 0x0000, 0x00c6e2, CRC(7aecbb2d) SHA1(6e59b66528a80c929e0ee3b7573c8b6d91eec80a) ) + ROM_LOAD( "grd06", 0x0000, 0x00c6e2, CRC(e2cd2081) SHA1(8a155e78fb6a4a755b14fb2afbf45087f8777de0) ) + ROM_LOAD( "huf01", 0x0000, 0x0096e2, CRC(b1520916) SHA1(d183b67d64ff0fbe7374d8a25686cf935d1ea36b) ) + ROM_LOAD( "huf02", 0x0000, 0x0096e2, CRC(c0120fe7) SHA1(8ca5a1fc20c06414bd0f02a052aa2ec97c40b451) ) + ROM_LOAD( "huf05", 0x0000, 0x0066e2, CRC(305fcd39) SHA1(9b700c5494349d8c0237eeae27190789f8cdc017) ) + ROM_LOAD( "huf06", 0x0000, 0x0066e2, CRC(c5e2e2c4) SHA1(b4448c714ab1f713566fe438a827a232aaf7458a) ) + ROM_LOAD( "huf07", 0x0000, 0x0066e2, CRC(4d75ec3c) SHA1(1f601a6c0437a14b217f5df7fe01cc62c0b5dc27) ) + ROM_LOAD( "idr01", 0x0000, 0x0066e2, CRC(143518d1) SHA1(68c9796b793f60f19d5f3df5776006f4290387ab) ) + ROM_LOAD( "iep01", 0x0000, 0x0096e2, CRC(4d3ef434) SHA1(829c3e09f2b69caeaf37c567d30b2921ace7bfc9) ) + ROM_LOAD( "iep02", 0x0000, 0x0066e2, CRC(dc9fe966) SHA1(c6342a998297b4bda4a0a662b17449f8f740bbde) ) + ROM_LOAD( "ils01", 0x0000, 0x00aee2, CRC(48bfd441) SHA1(f842fff7c00a1ba94ada3e977203c4246e18eb89) ) + ROM_LOAD( "itl01", 0x0000, 0x00aee2, CRC(0c2a6539) SHA1(a7cabc796def4c8563bb61ad071c6a4eee615409) ) + ROM_LOAD( "itl02", 0x0000, 0x00aee2, CRC(b063efa9) SHA1(e3b733bcd813ea31543d0368dddb5ceea29bef8c) ) + ROM_LOAD( "itl03", 0x0000, 0x007ee2, CRC(fccb2121) SHA1(9e1d5a73df3911ef3fd35b3f516d798d50019949) ) + ROM_LOAD( "itl04", 0x0000, 0x00aee2, CRC(d6722143) SHA1(89ce896153583e041489c8490da2907742087850) ) + ROM_LOAD( "itl05", 0x0000, 0x00aee2, CRC(b78cb39b) SHA1(32caf62d054300f8ab4d8894ba4425527206d976) ) + ROM_LOAD( "itl06", 0x0000, 0x007ee2, CRC(84362dbe) SHA1(a95d3e2553741c8ea758176d9864ac2db8f0f030) ) + ROM_LOAD( "itl07", 0x0000, 0x007ee2, CRC(fcf95162) SHA1(92e0a91d6d4f51ed780911c19c27568c1c87c6b6) ) + ROM_LOAD( "itl08", 0x0000, 0x0066e2, CRC(6d826af2) SHA1(54eee881997f0a518ea3ad3e762ed42fd3213b74) ) + ROM_LOAD( "itl09", 0x0000, 0x008ae2, CRC(1f28d83e) SHA1(cee015901480bfaa7b5cdb3e92238fb977159705) ) + ROM_LOAD( "itl10", 0x0000, 0x007ee2, CRC(3e19cea9) SHA1(748fc499cd46cb8343a376ca60c3f30bfd9755f0) ) + ROM_LOAD( "itlsit01", 0x0000, 0x0126e2, CRC(29a51c4c) SHA1(973c72f556d4106a55e241e381237dfae6bab90f) ) + ROM_LOAD( "jmd01", 0x0000, 0x0096e2, CRC(128a1311) SHA1(8ad084e5ce9f79583199796ccf631b945ca437ba) ) + ROM_LOAD( "jpy01", 0x0000, 0x004ee2, CRC(d0943ff0) SHA1(c3fd4120c748db5c85680ab1dfa71ca8ff66a9e7) ) + ROM_LOAD( "kwd02", 0x0000, 0x0096e2, CRC(08b017a0) SHA1(dc7417f094dc72d48687847d9a54c9fe793556bc) ) + ROM_LOAD( "lbp01", 0x0000, 0x0066e2, CRC(c4eb4154) SHA1(dd542e69726f27f9cc39f0b0c5e017c461359ee3) ) + ROM_LOAD( "mkd01", 0x0000, 0x0036e2, CRC(c10cf164) SHA1(f57ebf9a160683818c775fcfe41ac3777d4b18c2) ) + ROM_LOAD( "mxp01", 0x0000, 0x00f6e2, CRC(1a82436e) SHA1(e026c1f68d0910536a9b620e4491600330f90abf) ) + ROM_LOAD( "mxp02", 0x0000, 0x00c6e2, CRC(28e1e180) SHA1(f22fac0928c7c862f0b35365fb274bc2b1e4dc1c) ) + ROM_LOAD( "myr01", 0x0000, 0x00c6e2, CRC(48de91f7) SHA1(6e103a878b3104ffe64415c98689af73e3834ed2) ) + ROM_LOAD( "nlg01", 0x0000, 0x00d2e2, CRC(ba4854d4) SHA1(f260984222a85063ab58e27694b15b7ab11489c9) ) + ROM_LOAD( "nlg02", 0x0000, 0x008ae2, CRC(6f60d306) SHA1(1d8c4e0f27c6de0b0de45fa8765c2183dd1bd979) ) + ROM_LOAD( "nlgdem01", 0x0000, 0x00cce2, CRC(d8538012) SHA1(7a9b9f78335a0cb6858a8dbd2ffc0b5d787b77f6) ) + ROM_LOAD( "nok01", 0x0000, 0x004ee2, CRC(ba94554e) SHA1(69535dbe94ae605cf2cfd607dfb0fba4e00fb1a8) ) + ROM_LOAD( "nok04", 0x0000, 0x0036e2, CRC(b3e43d84) SHA1(29d65bcd79841a2af8f675145a041733daab2a83) ) + ROM_LOAD( "nok05", 0x0000, 0x004ee2, CRC(28280de4) SHA1(72d340548ea3cad2bf1a1d226514fc4fa47a7842) ) + ROM_LOAD( "nokdem01", 0x0000, 0x010ee2, CRC(ad201aa3) SHA1(bd79fc68bb23eebcdd917dd090b1447ae8bc8ba5) ) + ROM_LOAD( "nokdkk01", 0x0000, 0x00aee2, CRC(0a2a8b65) SHA1(b0973526a6bc79e4d75bee8c56b220edff1a3584) ) + ROM_LOAD( "nv4 2.67 1.77 37", 0x0000, 0x010000, CRC(8fe50b3f) SHA1(1d0b5ce215be7e4a50d3f3b743e0a066345a58db) ) + ROM_LOAD( "nv4x 52 377", 0x0000, 0x010000, CRC(7b8c5354) SHA1(e9770dabfacc006089448808cb29139679fbaa15) ) + ROM_LOAD( "nzd01", 0x0000, 0x0102e2, CRC(508e5edf) SHA1(9c653e01612c13c8dc194b18c42c45fe319cb56e) ) + ROM_LOAD( "omr01", 0x0000, 0x0036e2, CRC(6acb862c) SHA1(beb5edced779ea2ef9f56fe0e1bb8658af295f55) ) + ROM_LOAD( "pkr02", 0x0000, 0x00aee2, CRC(8aaa977e) SHA1(91e7736ed7d8dfe2a85417cf7ac704a42cd8ebf4) ) + ROM_LOAD( "plz01", 0x0000, 0x0066e2, CRC(c3892e74) SHA1(055fb702dccb3e8a88c917ac04c535eda03b2cef) ) + ROM_LOAD( "plz02", 0x0000, 0x004ee2, CRC(64740a69) SHA1(0658ea26f83d19cbf4d94a21d67be73c45f66760) ) + ROM_LOAD( "pte01", 0x0000, 0x007ee2, CRC(f171555e) SHA1(e7f9cbbcac1130b853ceea043ce4227eff53e3f3) ) + ROM_LOAD( "qar01", 0x0000, 0x0096e2, CRC(fc26cddb) SHA1(8e6c8a56ef0e539ba05fbb0341647193423549ff) ) + ROM_LOAD( "qar02", 0x0000, 0x007ee2, CRC(7db9fd07) SHA1(ada30c5c55c3ce2f0ba978474acfb39c7c91ba6f) ) + ROM_LOAD( "qar03", 0x0000, 0x005ae2, CRC(fc84bffc) SHA1(339ded907866cda4a321663393fe9972c16d26b6) ) + ROM_LOAD( "qar04", 0x0000, 0x005ae2, CRC(e71bc66b) SHA1(3507d0b287c6fe86ce77175ea74569301b054997) ) + ROM_LOAD( "qar05", 0x0000, 0x001ee2, CRC(104993ba) SHA1(3803ee587a572c402d0bdb2f378d8aa5ccc0010d) ) + ROM_LOAD( "rol01", 0x0000, 0x00dee2, CRC(f0f17bc8) SHA1(21d2d29cec6ad6a62712e36933a8145a8c01d0fc) ) + ROM_LOAD( "rol02", 0x0000, 0x0096e2, CRC(056d9fa2) SHA1(4a221d873d4f35c1fdaa39390c94e57b4c3e3a91) ) + ROM_LOAD( "rol03", 0x0000, 0x00aee2, CRC(6dc062c5) SHA1(9849161eef3fccc8a0fbe0c817c5aea30ac0fd34) ) + ROM_LOAD( "rol04", 0x0000, 0x0096e2, CRC(f994e19e) SHA1(c8e2134b0667ae369d8e148dd47a20cdf5683e2c) ) + ROM_LOAD( "rol05", 0x0000, 0x0066e2, CRC(8685ad64) SHA1(018e2c05cbbc4c377eaad9b6fc5b57be65705095) ) + ROM_LOAD( "rur01", 0x0000, 0x00f6e2, CRC(35bc7845) SHA1(319788697449d9c9cab1ca44773cd9a66b042420) ) + ROM_LOAD( "sar01", 0x0000, 0x00dee2, CRC(dbc0380d) SHA1(a4b6518a8f606c32816557e076b36052635c1111) ) + ROM_LOAD( "sar03", 0x0000, 0x004ee2, CRC(5ff7887b) SHA1(a48279977b430b203769505a3e2e1a81bc04f5e4) ) + ROM_LOAD( "sar04", 0x0000, 0x004ee2, CRC(36f56733) SHA1(1415ad1d96db23dceeacf5a1c192cb4c2a86e527) ) + ROM_LOAD( "sar05", 0x0000, 0x00c6e2, CRC(eb1229c4) SHA1(cf197b4e2601f7fa95054628c87de54f3a049114) ) + ROM_LOAD( "saregp01", 0x0000, 0x00d8e2, CRC(d9963f25) SHA1(20a224351a23cbfd87ea6f2cad3e6f94733c795e) ) + ROM_LOAD( "sek01", 0x0000, 0x00dee2, CRC(5a255f5b) SHA1(ebd25b2463d3fd5ff97a1aac1e7f64f726e59912) ) + ROM_LOAD( "sek02", 0x0000, 0x00aee2, CRC(f9afc549) SHA1(e5d1f173d863b17609b4810ff872c925a2e5750c) ) + ROM_LOAD( "sekdem01", 0x0000, 0x00c6e2, CRC(630a4d5c) SHA1(1c2236063b4c2221148def18e8e512d4c8482c58) ) + ROM_LOAD( "sekdkk01", 0x0000, 0x00dee2, CRC(d8f39097) SHA1(337dd12a4ddfe7a0dca1bb7fc1227c203095b505) ) + ROM_LOAD( "sekgbp01", 0x0000, 0x00dee2, CRC(3a8697ac) SHA1(6610caee5d8e9b9f17b3a439ab0bbc9a4375f818) ) + ROM_LOAD( "sekplz01", 0x0000, 0x0096e2, CRC(776380fe) SHA1(b1f4dcbcb42f14ce291ff97c8d8ecd3a708748bf) ) + ROM_LOAD( "senogb01", 0x0000, 0x0156e2, CRC(dcf837f0) SHA1(c47f23886bbe11426bf136594f1f898034e89e2b) ) + ROM_LOAD( "sgd01", 0x0000, 0x010ee2, CRC(4a8316db) SHA1(b67e01d90a346f1a458947501e8b5329b2b69d6d) ) + ROM_LOAD( "sit01", 0x0000, 0x00aee2, CRC(6987dcfe) SHA1(cfd8ba5fc4b79a3870e7a953d8d17ad80505aa84) ) + ROM_LOAD( "sit02", 0x0000, 0x0066e2, CRC(ebac5fe9) SHA1(ff6c0351b07817d47b2905b56b320c85b4cfe7db) ) + ROM_LOAD( "sit03", 0x0000, 0x007ee2, CRC(ad82f79c) SHA1(fba4812364f335283d85d98e4d8f0e743a06a73e) ) + ROM_LOAD( "sit04", 0x0000, 0x004ee2, CRC(c3093338) SHA1(a5ebe26481c466d5804617af0f6336ea8a8b32f9) ) + ROM_LOAD( "sit05", 0x0000, 0x0096e2, CRC(c0e9ca0a) SHA1(d930efb7d97f30505caf8d62a6b68229f0b96afa) ) + ROM_LOAD( "sit06", 0x0000, 0x0066e2, CRC(cda230f5) SHA1(21b35f2c84bafc9e8db3db2f35d32c959e544d64) ) + ROM_LOAD( "sit07", 0x0000, 0x007ee2, CRC(151314a9) SHA1(fd38f4671127c09f0bfbc3d881bcedd8b4ce8b08) ) + ROM_LOAD( "sit08", 0x0000, 0x0066e2, CRC(73be12c7) SHA1(dd0ae3b175747101d60b7237e3661a0e974cedad) ) + ROM_LOAD( "skk02", 0x0000, 0x0066e2, CRC(786a4611) SHA1(d544bb42bcaa53aa2f806e216b1c11659eb58b41) ) + ROM_LOAD( "skko1", 0x0000, 0x007ee2, CRC(d496d44c) SHA1(6d4fabc04af356715fc8dc734416ef8a12ef5543) ) + ROM_LOAD( "tlb01", 0x0000, 0x00dee2, CRC(a3017a9c) SHA1(dd01c2c17b546985cf99a4487e1c05171607dd61) ) + ROM_LOAD( "trl01", 0x0000, 0x00dee2, CRC(e3c95c1f) SHA1(b1d4de10320b7966f598045aeb1c6c1acd304f58) ) + ROM_LOAD( "trl02", 0x0000, 0x00aee2, CRC(583f6a98) SHA1(9a257f2ec82206ed0c97b477078ca85ade661389) ) + ROM_LOAD( "trl03", 0x0000, 0x0096e2, CRC(c2875ac0) SHA1(a4f3db63beae552dd21086daa044945c4c2f5182) ) + ROM_LOAD( "trl04", 0x0000, 0x007ee2, CRC(57e953a4) SHA1(5b0b778900e2f5f46e9b883f04bedc42b3c0ab85) ) + ROM_LOAD( "trl05", 0x0000, 0x004ee2, CRC(8996ee7a) SHA1(23191ece0dcf1ca864bbf71862ed68cfbe3b84f4) ) + ROM_LOAD( "uad01", 0x0000, 0x00dee2, CRC(379d1f3c) SHA1(91b6a18e358f10dcf7702ffedcb595bcb7bcb654) ) + ROM_LOAD( "uah01", 0x0000, 0x0096e2, CRC(34b182b1) SHA1(7b2db880d7a25e06717c12db42db2f12cd474aeb) ) + ROM_LOAD( "uyp01", 0x0000, 0x00c6e2, CRC(73910f85) SHA1(8d191302d55f6f9247adf9add25b0df80798f362) ) + ROM_LOAD( "veb01", 0x0000, 0x00c6e2, CRC(c3139d53) SHA1(274f80094682a041887ee8cade48ee76d6467950) ) + ROM_LOAD( "zar03", 0x0000, 0x00f6e2, CRC(96a2a431) SHA1(7817bd3d53d62d6253068b2a14189a56d019dbc0) ) + ROM_LOAD( "zwd01", 0x0000, 0x0066e2, CRC(d1897ea7) SHA1(1824d4e765216b5a1d62bcff70574dbebaf30c1d) ) +// Quintoon (Bellfruit) + ROM_LOAD( "95750231.bin", 0x0000, 0x010000, CRC(1227367f) SHA1(b6249db6b3a814fed1cf11713b70a17be8d6e3d0) ) + ROM_LOAD( "qublcy351rp.bin", 0x0000, 0x080000, CRC(bd6b0c8b) SHA1(a79626de03e5e432f81eb93ff2dc38a7510733ba) ) +// Rhythm & Blues (JPM) + ROM_LOAD( "rhythm_&_blues1.1", 0x0000, 0x01681e, CRC(d7092860) SHA1(765621bd4c487ff20cccd70c6d2d514109cb83c4) ) + ROM_LOAD( "rhythm_&_blues1.2", 0x0000, 0x01681e, CRC(1fc40a07) SHA1(2d8f50fc1f01fcdc737c42608c98d4b6abccb3c1) ) +// Scrabble (JPM) + ROM_LOAD( "scravfp1", 0x0000, 0x080000, CRC(e1941639) SHA1(ae8e5428eb28edba5bd25f496479d8e3e9b00d86) ) //Ver F. same as we already have? +// Terrance & Phillip (Bootleg) + ROM_LOAD( "terranceandphillipsound.bin", 0x0000, 0x04fcc3, CRC(f614112e) SHA1(a628d785bb9e8e3747b1f55be3b23eca0dd058ab) ) +// Thriller (JPM) + ROM_LOAD( "thriller_2.1", 0x0000, 0x01681e, CRC(bff1defe) SHA1(83f95c7448ea2023bf640b59570b852c70c0ca08) ) +// Treble Top (Bellfruit) + ROM_LOAD( "ttpcob.pa", 0x0000, 0x010000, CRC(391181d4) SHA1(42c499ae78f38ccfec572701b3c99b7cf200ff98) ) +// zzz_unk 004 (Unk) + ROM_LOAD( "nolabel.rom", 0x0000, 0x000800, CRC(273a140c) SHA1(ea4962e1c9aa3e593b8d5b2b3eed1b791cda74a6) ) +// zzz_unk 326s (Project) + ROM_LOAD( "326-s-01.001", 0x0000, 0x080000, CRC(5a23e17e) SHA1(e664da5213ca572288193101e4a33ac8bc3d553b) ) +// zzz_unk cmz (Barcrest) + ROM_LOAD( "cmzic10", 0x0000, 0x080000, CRC(2a66564c) SHA1(52665fbc88a1e3e0fa2dfd1d846c99c1f8055bd8) ) + ROM_LOAD( "cmzic9", 0x0000, 0x080000, CRC(5db969e0) SHA1(768ba1dbf014d8efceb9c63aeb0edd107c5753de) ) +// zzz_unk fred (Barcrest) + ROM_LOAD( "fred.bin", 0x0000, 0x000c1b, CRC(cf46223b) SHA1(dcf5d0c310b8ccc2783d4d7a80ce496d7ecd0d56) ) +// zzz_unk lahroc5 (Electrocoin) - Last Action Hero (Data East Pinball) +// ROM_LOAD( "lahroc5", 0x0000, 0x010000, CRC(94102fdd) SHA1(b741fe7a646225351148f5e675bd232881730221) ) +// zzz_unk pgsnd (Maygay) + ROM_LOAD( "pgsnd", 0x0000, 0x080000, CRC(c1d5a1f1) SHA1(8b7ded8aa4a84310d08c1438d0d91a28e1d95a21) ) +// zzz_unk sil (Barcrest) + ROM_LOAD( "sil", 0x0000, 0x002000, CRC(1f8a48d2) SHA1(143c2474af9469a753bbf0e82e8e6f4f88e4d38f) ) + ROM_LOAD( "sil.p4", 0x0000, 0x002000, CRC(72f49fe9) SHA1(d6bb31d830fe125912e73cfcdc6b4e32027c45cc) ) + + ROM_REGION( 0x800000, "astra", 0 ) // these are clearly astrafr.c sets +// zzz_unk pbm (Unk) + ROM_LOAD( "pbmv0-06.u1", 0x0000, 0x080000, CRC(d0283320) SHA1(472f0e0dd45da61081ca12e466ac02dc82eb4431) ) + ROM_LOAD( "pbmv0-06.u2", 0x0000, 0x080000, CRC(38fb2ff6) SHA1(628dcdcbf4767db62b4bdee7b7feff32715e6a2d) ) +// zzz_unk pbs (Unk) + ROM_LOAD( "pbs0-06d.u1", 0x0000, 0x080000, CRC(f24e84d2) SHA1(d54e787c91c79a26383971249f935529e2a492f4) ) + ROM_LOAD( "pbs0-06g.u1", 0x0000, 0x080000, CRC(937af673) SHA1(88f33fd3921440a99b662fec7291c8b9845210a5) ) + ROM_LOAD( "pbsv0-06.u1", 0x0000, 0x080000, CRC(fbb51b61) SHA1(c1459f8f2d9f182e5be55bbcaf143315f7efc3b0) ) + ROM_LOAD( "pbsv0-06.u2", 0x0000, 0x080000, CRC(2f0934de) SHA1(915a16898087f396457d712e3847f4f7c0bd5c06) ) +// zzz_unk pgm (Unk) + ROM_LOAD( "pgm0-04.u1", 0x0000, 0x040000, CRC(2885367c) SHA1(c33cb554889b1f7390baa416a77953f45a80044f) ) + ROM_LOAD( "pgm0-04.u2", 0x0000, 0x040000, CRC(c5eed515) SHA1(9b832a6ef301a25bccf2d97cca0c9a012ca0090a) ) + ROM_LOAD( "pgm1-00.u1", 0x0000, 0x040000, CRC(1fa4e10f) SHA1(787ec967a9aba5934db79fe67efb32370d2c0258) ) + ROM_LOAD( "pgm1-00.u2", 0x0000, 0x040000, CRC(8b5a6178) SHA1(e1f9898ef37877ce50630a468b3c187a4fe253fa) ) +// zzz_unk pgs (Unk) + ROM_LOAD( "pgs0-04d.u1", 0x0000, 0x040000, CRC(1f5ede2c) SHA1(ac67536a021b531efe18027806f1f86504d72493) ) + ROM_LOAD( "pgsv0-04.u1", 0x0000, 0x040000, CRC(cb3387be) SHA1(2add224a8839e83cc04901274acc7ca4a781b7d9) ) + ROM_LOAD( "pgsv0-04.u2", 0x0000, 0x040000, CRC(63054bd6) SHA1(59cf8dd7efdaf2491a2aca8fbcda2d3b8b70fbf7) ) + ROM_LOAD( "pgsv1-00.u1", 0x0000, 0x040000, CRC(725dd2af) SHA1(f8ecd1282809c0906497c62a68429152c10e2da0) ) + ROM_LOAD( "pgsv1-00.u2", 0x0000, 0x040000, CRC(067dd0c2) SHA1(ac36aeb63b33969dc0a49150e41bfdd8624072de) ) + ROM_LOAD( "pgsv100d.u1", 0x0000, 0x040000, CRC(a6308b3d) SHA1(125ed244bcb7a515dfc9c34c12bc74f8cd50e8dd) ) +// zzz_unk ptm (Unk) + ROM_LOAD( "ptmv0-02.bin", 0x0000, 0x080000, CRC(e9dd8674) SHA1(ace543bc7fea8d09661e76c1ade4e1f27db5a116) ) + ROM_LOAD( "ptmv1-04.bin", 0x0000, 0x080000, CRC(32af5358) SHA1(bd61c396824bb2b6845126162c4ff797564ebdf2) ) + ROM_LOAD( "ptmv1-13.bin", 0x0000, 0x080000, CRC(4f321735) SHA1(3f9b0b64c42011d948291cd774a922393793a4b1) ) +// zzz_unk ptp (Unk) + ROM_LOAD( "ptp003d.u1", 0x0000, 0x100000, CRC(2b2c05b6) SHA1(541a53c84c07bd7e1f09d4d033cf652ab838b4ef) ) + ROM_LOAD( "ptp003g.u1", 0x0000, 0x100000, CRC(d9d0e151) SHA1(35fb4412602b9fd3b66e7170cc1984693b9c9ebd) ) + ROM_LOAD( "ptpv003.u1", 0x0000, 0x100000, CRC(07c189da) SHA1(c4574cdedba87058312db84c6ee7f4a7142eea65) ) + ROM_LOAD( "ptpv003.u2", 0x0000, 0x100000, CRC(e1f78cf4) SHA1(5f72b2604fd7ee300f6bd5b5a12d98c77b03b9ba) ) +// zzz_unk pts (Unk) + ROM_LOAD( "pts1-04d.bin", 0x0000, 0x080000, CRC(95564b9f) SHA1(98091d4badd346578882db75a8d72ddaa810b3f5) ) + ROM_LOAD( "pts1-13d.bin", 0x0000, 0x080000, CRC(876232cf) SHA1(5d2355f85bde636dcb6f3dbd87874294db8e1ded) ) + ROM_LOAD( "ptsv0-02.bin", 0x0000, 0x080000, CRC(3cc9c022) SHA1(1eb3c237971cf407057d077fd08e4436c765ae43) ) + ROM_LOAD( "ptsv1-04.bin", 0x0000, 0x080000, CRC(9cadd42c) SHA1(e6ead7112195a17797672112c7bbd4910ae6eb50) ) + ROM_LOAD( "ptsv1-13.bin", 0x0000, 0x080000, CRC(8e99ad7c) SHA1(d4cfce825b4a718a12d80e79ed943797c6510ad6) ) +// zzz_unk joker (Unk) + ROM_LOAD( "joker03.u1", 0x0000, 0x080000, CRC(a3dd15e8) SHA1(95d04de6c991b3c1ff43b0f477f03213e83f63f2) ) + ROM_LOAD( "joker03.u2", 0x0000, 0x080000, CRC(57b3305a) SHA1(c38bc7db6c9a3f8f5371bb4c555333404fed6a9f) ) + ROM_LOAD( "jokr03d.u1", 0x0000, 0x080000, CRC(aa268a5b) SHA1(cce89dbaaaf2d44daf127de1ad6d621c46d892fc) ) + ROM_LOAD( "jokr03g.u1", 0x0000, 0x080000, CRC(cb12f8fa) SHA1(7a9c9fe72b70fe1b4a3be2edfde9d7a54d7a8219) ) +// zzz_unk hog0-03 (Unk) + ROM_LOAD( "hog0-03.u1", 0x0000, 0x080000, CRC(eaa26ab0) SHA1(ee7d76b92c3274ba8c5ba59184bb3334fbbc64c4) ) +// zzz_unk jjrv102 (Unk) + ROM_LOAD( "jjrv1-02.u1", 0x0000, 0x080000, CRC(0f05e392) SHA1(64c885c92fb26c0ed64b8283793cdf86d2bc0e35) ) + ROM_LOAD( "jjrv1-02.u2", 0x0000, 0x080000, CRC(1d86f26c) SHA1(e7db51b217e9fb8a0440b7c7591c5ea4142540bc) ) +// zzz_unk jst (Unk) + ROM_LOAD( "jst0-05.u1", 0x0000, 0x080000, CRC(38f2d7b0) SHA1(11ccb5b5a35e43f505a7d3ebc36a0694111fed11) ) + ROM_LOAD( "jst0-05.u2", 0x0000, 0x080000, CRC(97c14933) SHA1(8515601fbacf76a78a95e4a46a47809fcec021bc) ) + ROM_LOAD( "jst0-05d.u1", 0x0000, 0x080000, CRC(31094803) SHA1(b7b5fd97681c38de5e877ca7b09909c82316d4d8) ) + ROM_LOAD( "jst0-05g.u1", 0x0000, 0x080000, CRC(503d3aa2) SHA1(818e79126ca8ae6bbd1eaac2ae13977b3402f497) ) + ROM_LOAD( "jst0-06.u1", 0x0000, 0x080000, CRC(b6106ca4) SHA1(dedeeff6e8c13da1f62e882cbeb36567a631e563) ) + ROM_LOAD( "jst0-06.u2", 0x0000, 0x080000, CRC(49a78695) SHA1(af99df8c97a8c3bcb5a81a38b985e1fc92176927) ) + ROM_LOAD( "jst0-06d.u1", 0x0000, 0x080000, CRC(bfebf317) SHA1(7f1a2a8e3f3de6a03452f535d2c314810bc652da) ) + ROM_LOAD( "jst0-06g.u1", 0x0000, 0x080000, CRC(dedf81b6) SHA1(0579501c939eacb93d1455eaf74b629c2170b05b) ) +// zzz_unk l7 (Unk) [Rom] LUCKY 7 ASTRA + ROM_LOAD( "l7v1-03.bin", 0x0000, 0x080000, CRC(878d1a3d) SHA1(fd7cb08f698bb6bbfed1c57486e53dce062d22e4) ) + ROM_LOAD( "l7v1-03d.bin", 0x0000, 0x080000, CRC(91a81e50) SHA1(6086861bd5a53fa17df8b155acd47e9aa45a032d) ) + +ROM_END + + +// despite being in an 'EPOCH' roms zip, most of this stuff clearly isn't EPOCH - sort it, place it. +ROM_START( unkfra ) + ROM_REGION( 0x200000, "maincpu", 0 ) + //ROM_LOAD( "abt1.7", 0x0000, 0x020000, CRC(2eaaec99) SHA1(d993f8bd2ba286aa64c13e1520d702955e702b95) ) bad + //ROM_LOAD( "blackjak.p1", 0x0000, 0x020000, CRC(31660bf5) SHA1(225c8ef7138b642cbf07a0cb8a575b1e768463ca) ) bad + //ROM_LOAD( "blackjak.p2", 0x0000, 0x020000, CRC(cacfcadb) SHA1(b6af22664abffe853007a6fa62631431220f46ac) ) bad + ROM_LOAD( "buble&sq.go", 0x0000, 0x080000, CRC(b05323f5) SHA1(290d7716cb61f6788d052611d662575ffdcfd55a) ) // it's not bubble & squeak? + ROM_LOAD( "cash_box.p1", 0x0000, 0x020000, CRC(2978eca5) SHA1(372e010404c4af2e905215e23ad9c8d1cf6314a3) ) + ROM_LOAD( "cstreet.swp", 0x0000, 0x080000, CRC(8e2c6d7f) SHA1(835cb7bf51260d0ba732e6b3895f77bef25a1fb4) ) + ROM_LOAD( "c.fas", 0x0000, 0x080000, CRC(e942c4bc) SHA1(9833f4b8c418d51bdab851602162811d1ebb6956) ) + ROM_LOAD( "fesnd1", 0x0000, 0x080000, CRC(d2dab810) SHA1(daa26821ad31a81e714a2ddcc0a467a60d650ed3) ) + ROM_LOAD( "fe_p_std.hi", 0x0000, 0x080000, CRC(c38a1263) SHA1(5431c9b9c000a184f4753b4aa05e037c2d3bfa46) ) + ROM_LOAD( "fruitopi.lo", 0x0000, 0x080000, CRC(da9d5edb) SHA1(249445a5193b04490641a0498f577cb2be69c0dd) ) + //ROM_LOAD( "gia_gems.p1", 0x0000, 0x080000, CRC(c841d2f7) SHA1(480397141c917bce26cfdc8ba7fa8d21ab741770) ) bad + //ROM_LOAD( "gia_gems.p2", 0x0000, 0x080000, CRC(7824adf5) SHA1(99b59d28adb80d5cf3d70691cc134eba72288f20) ) bad + ROM_LOAD( "gimme_st.p1", 0x0000, 0x080000, CRC(d5df19b3) SHA1(3efdff2894f6edcae1121a63c654b7d58bd378c0) ) + ROM_LOAD( "h hop.p1", 0x0000, 0x080000, CRC(71c3549f) SHA1(7b98acd3ce9d72dbbef573330d3206d9af60c15e) ) // bad? (looks like fixed bits in places) +// ROM_LOAD( "hbrk_hot.txt", 0x0000, 0x0000ff, CRC(c95eecc8) SHA1(fd3e5658028ab39622e761445d72ed110da3e091) ) + ROM_LOAD( "jc5p_pound5", 0x0000, 0x020000, CRC(cf1d708e) SHA1(df0188b6d66763a91ae153821f6e12b9df391146) ) // mpu4 + ROM_LOAD( "jungle.s2", 0x0000, 0x080000, CRC(df59d976) SHA1(b3a11b19228487eec36118a0ef72db15b743db80) ) + //ROM_LOAD( "jewel s", 0x0000, 0x000001, CRC(38d7a8b4) SHA1(999a0a8cad102eb519ca788d6e0cd48ee9e6ca3e) ) + ROM_LOAD( "jpoter.p1s", 0x0000, 0x080000, CRC(56aec852) SHA1(df6b35176dadc6f2b7736a2557b9af254a1e4dd2) ) // sc5 + ROM_LOAD( "jpoter.p2_", 0x0000, 0x080000, CRC(032ebbf5) SHA1(ed21f30e02826c629d0c3bfbec332aeb9a6266a9) ) // sc5 +// ROM_LOAD( "ra_cd100.3_6", 0x0000, 0x020000, CRC(4cc8cf79) SHA1(8eb51e0f6c0f66d155f9b325ee02a313f1f3a525) ) // cd100 jukebox? + ROM_LOAD( "wb_v22", 0x0000, 0x002000, CRC(bd02c9c8) SHA1(044024ce40668397e9ca2ea3ec4f68d05fd20bd0) ) + + // these look like astra/pluto + ROM_LOAD( "ldeven", 0x0000, 0x040000, CRC(179505b4) SHA1(2c80a5289f8945eba222d3daa29a1ecca26aae0c) ) + ROM_LOAD( "ldodd", 0x0000, 0x040000, CRC(9611a17f) SHA1(06199f2f8660162ce4157e07927406b4046d8457) ) + //ROM_LOAD( "sldodd", 0x0000, 0x040000, CRC(9611a17f) SHA1(06199f2f8660162ce4157e07927406b4046d8457) + ROM_LOAD( "sldeven", 0x0000, 0x040000, CRC(cbd08464) SHA1(d7b6397b597d05efcffc5ed975723f07b794a1f5) ) + + ROM_LOAD( "legion.sn1", 0x0000, 0x080000, CRC(782827cd) SHA1(0f5aeba70e639549376c5df9146fe6a9c58396d5) ) + ROM_LOAD( "mon_60.p1", 0x0000, 0x020000, CRC(ddb30a35) SHA1(c225995fe41f76d32d101cc91dcfa9c3d0e9aa02) ) + ROM_LOAD( "manic st.p2", 0x0000, 0x080000, CRC(ab8afc46) SHA1(39b75bf5e623458f256966458918a1f90b138c13) ) // manic streak features alt dump? + ROM_LOAD( "monty_p.p3", 0x0000, 0x080000, CRC(f4b034b0) SHA1(ef055a42414008f7ef2d9aad25fccd7d2c57b656) ) // monty python alt? + ROM_LOAD( "monswp1v", 0x0000, 0x080000, CRC(263f7e39) SHA1(2f554454df10b6da90cee2b1c851272d5734b644) ) + ROM_LOAD( "monswp2v", 0x0000, 0x080000, CRC(2189f360) SHA1(b28024203c4655622587c9bc7d0b49472be2c1d9) ) + ROM_LOAD( "monswp3v", 0x0000, 0x080000, CRC(3577c3b9) SHA1(3194d11dcdc39e82fa0098065e7ec3eec4f6f944) ) + ROM_LOAD( "monswp5v", 0x0000, 0x080000, CRC(1bb26415) SHA1(7f59e1aeceb9959c7ef26285648b148c2c5c3671) ) + ROM_LOAD( "monswp6v", 0x0000, 0x080000, CRC(5797e892) SHA1(261ae31cdd3b666bc759244c8d27e82dc52153c6) ) + ROM_LOAD( "monv4p1", 0x0000, 0x080000, CRC(3c689a59) SHA1(e7deb992db1d406a5626c51c270ab7285a62b535) ) + + ROM_LOAD( "note vat", 0x0000, 0x020000, CRC(b77c8f48) SHA1(5c52c156227152f6b38dea47b8a3edf241c923e0) ) // sound + ROM_LOAD( "note.vat", 0x0000, 0x020000, CRC(7885311a) SHA1(f139399f0829da389e935519148e5ba1c064e34e) ) // 68k code (jpm) (missing other rom?) + + ROM_LOAD( "noonshin.g1", 0x0000, 0x080000, CRC(b2c5f80b) SHA1(4ec7b0bd758ddad88315021ed746aec35fa688b7) ) // moonshine club? + ROM_LOAD( "phoenix.hi", 0x0000, 0x080000, CRC(f23ae723) SHA1(9a4bbe9d305f7a24ee71216270d98e5830630c63) ) + ROM_LOAD( "phoenix.lo", 0x0000, 0x080000, CRC(793350ce) SHA1(888be3c3e4711750c5102a6a4a19fd0458462444) ) +// ROM_LOAD( "pick.p2", 0x0000, 0x080000, CRC(cb170a74) SHA1(913914dcfa9c94f6e6d6d0aae6e0ba98cdcb66ce) ) bad +// ROM_LOAD( "pick_pac", 0x0000, 0x080000, CRC(c1127969) SHA1(ea72b90591df2398efbdeb55520b0fde5dd4e5a0) ) bad + ROM_LOAD( "rc_club.p1", 0x0000, 0x020000, CRC(5bf41b92) SHA1(48f85ef7352d75a7f9e9c7a9e01408b2a00b0053) ) // impact + ROM_LOAD( "rc_club.p2", 0x0000, 0x020000, CRC(e790dda8) SHA1(5564626e3235bad8048e8be00ca7a5a7798b236e) ) // impact + ROM_LOAD( "redalert.p1", 0x0000, 0x020000, CRC(ff5952b2) SHA1(c4fd40d9eae05f80497f312b85bc97c88a0c3502) ) + ROM_LOAD( "side split.lo", 0x0000, 0x080000, CRC(89e97aee) SHA1(1e0a21b9cdd049a1ed7bfd2216c9b9789ff103a2) ) + //ROM_LOAD( "side spl", 0x0000, 0x080000, CRC(89e97aee) SHA1(1e0a21b9cdd049a1ed7bfd2216c9b9789ff103a2) ) +// ROM_LOAD( "smg1", 0x0000, 0x080000, CRC(6dc368c5) SHA1(afc65e5ceefadf794b53bd073d483e4616b9cb34) ) // bad? (crystal maze rom, paired with cry.p4) + ROM_LOAD( "s_night.lo", 0x0000, 0x080000, CRC(65f8fa73) SHA1(59bc4ca637615a4e4b3ca7750a9257632ce3a31b) ) + //ROM_LOAD( "s_tonic.p4", 0x0000, 0x000001, CRC(ff000000) SHA1(85e53271e14006f0265921d02d4d736cdc580b0b) ) + + ROM_LOAD( "upov03.p2", 0x0000, 0x080000, CRC(8601a331) SHA1(b5caddd15ccd140e28eba1ae44e7d944e37ccbb3) ) // Up and Over, missing the rest of v3 + + // looks like a pluto style decode, but isn't (text is corrupt).. might just be bad + ROM_LOAD( "winamil.p1", 0x0000, 0x020000, CRC(c23539e9) SHA1(1fb5ea2a4ffe8eda890c580329471c5ec820c4ca) ) + ROM_LOAD( "winamil.p2", 0x0000, 0x020000, CRC(a2e12e68) SHA1(6abdf37a48ee8fa4728dcc6553b6e5d8f834620a) ) + + + ROM_REGION( 0x200000, "palsetc", 0 ) + ROM_LOAD( "gsg", 0x0000, 0x000b94, CRC(31a65a15) SHA1(97508a3334a72e1c44719421adecefe7845bf2fe) ) + ROM_LOAD( "_pound15gold", 0x0000, 0x000bd8, CRC(b44d0b28) SHA1(b2546d8cb1b22ba532f7de15a559e27349df2b4b) ) + ROM_LOAD( "_pound15_key", 0x0000, 0x000b99, CRC(3baa0343) SHA1(3ba6ddc35d47caa7852fb9eb72e385526d5f5cf0) ) + ROM_LOAD( "_pound15_pic", 0x0000, 0x000400, CRC(9bdab7e2) SHA1(a65915c3d7e836c6952680fa1b5276b432718c62) ) + ROM_LOAD( "cjgerm", 0x0000, 0x000ad1, CRC(9a2a4ca7) SHA1(09864d7f1fa606b18d7bfb427f936911e8f3988c) ) + ROM_LOAD( "hrpal", 0x0000, 0x000b99, CRC(386ae20f) SHA1(5768d2340357cdcacebf80911665a8c3052486bf) ) + ROM_LOAD( "hvpal", 0x0000, 0x000b99, CRC(fd99d539) SHA1(affd72faa6037dbbf6884f9490427cd1d97ff515) ) + ROM_LOAD( "pal16v8", 0x0000, 0x000b99, CRC(aabffecc) SHA1(926cc4e995715b95e0de90da2a9d98ef4da94f4a) ) + ROM_LOAD( "pinball", 0x0000, 0x000b99, CRC(e59fb17f) SHA1(0150b4f123a0ac622a99ee2e518e9fde15b96c21) ) + ROM_LOAD( "rhpal", 0x0000, 0x000b99, CRC(a6ccb2fe) SHA1(800c785c400df808bfb6bf6fd72faf2d6e7bcbaf) ) + ROM_LOAD( "sndpal", 0x0000, 0x000ad1, CRC(d8a9f9b9) SHA1(0709364647c9812cea97e95dbf82983aa73c4f22) ) + ROM_LOAD( "sound pa", 0x0000, 0x020000, CRC(896323a2) SHA1(62d458de02e0901f5d0abf5622b6f13e4de63c77) ) + ROM_LOAD( "sound.pal", 0x0000, 0x000ac2, CRC(e2946d39) SHA1(72c806213dc713bfcc2b80cc0ae5f19174149645) ) + ROM_LOAD( "vv.pal", 0x0000, 0x000b99, CRC(6bf0d1d6) SHA1(416cb32909b1b2ffdbd4b495ebceb4970680da9b) ) + ROM_LOAD( "wtapal", 0x0000, 0x000b99, CRC(1faada64) SHA1(9f04c503ea10935a888ad1cc5fa2f81ef84000a3) ) + ROM_LOAD( "age.gal", 0x0000, 0x000b99, CRC(6f1113cd) SHA1(365ffc6fe91f6f54a00ee4c764478a120f4a39a0) ) //Andy's Great Escape? + ROM_LOAD( "nwpal", 0x0000, 0x000b99, CRC(6f1113cd) SHA1(365ffc6fe91f6f54a00ee4c764478a120f4a39a0) ) + ROM_LOAD( "1-153", 0x0000, 0x000b96, CRC(95624748) SHA1(3be008f5232b6f35b6b897784d47ba060584c4ad) ) + + ROM_REGION( 0x200000, "snd", 0 ) + ROM_LOAD( "r_rich.s0", 0x0000, 0x080000, CRC(75b98d09) SHA1(f81b3b9d8aa4b9730a4ea197a30760f3f331713e) ) + ROM_LOAD( "r_rich.s1", 0x0000, 0x080000, CRC(701615a7) SHA1(b426c5bff4f172241371a9fb6be3bd021f703004) ) + ROM_LOAD( "r_roul.snd", 0x0000, 0x080000, CRC(8897f543) SHA1(8964f35e1df3ea95f74cea55536f4d0aeed16dcd) ) + ROM_LOAD( "jolly r.s0", 0x0000, 0x080000, CRC(8d30786a) SHA1(270a138895ba99a32bc165e1f1ccf2faaa84e75b) ) + ROM_LOAD( "jolly r.s1", 0x0000, 0x080000, CRC(11270f30) SHA1(6ea10d60c50359e73f543f5c6c8f86e32c1bf185) ) + //ROM_LOAD( "showspec", 0x0000, 0x080000, CRC(98a3dff2) SHA1(1f56ec3237559105131de74a71b30592c346c680) )//Almost certainly bad copy of stspec + ROM_LOAD( "skillga~.snd", 0x0000, 0x080000, CRC(a28cb082) SHA1(5b2b5dab1c11751b469ad22f8cad80d38c445cd5) ) + //ROM_LOAD( "tttsnd1", 0x0000, 0x080000, CRC(9d1a878f) SHA1(54c84790edc2b57af3d963f0b4ad99d956ec48e4) ) + ROM_LOAD( "ticttoes", 0x0000, 0x080000, CRC(9d1a878f) SHA1(54c84790edc2b57af3d963f0b4ad99d956ec48e4) ) + ROM_LOAD( "triplgol.s0", 0x0000, 0x080000, CRC(cb9da972) SHA1(8c50049aaa194fbf54dc35ba997246486f33c2fb) ) + ROM_LOAD( "triplgol.s1", 0x0000, 0x080000, CRC(5661665b) SHA1(74123be9ab5c1f19a29207e2aaf866a709037444) ) + ROM_LOAD( "superpoo.s1", 0x0000, 0x080000, CRC(10b66838) SHA1(24e202edec41f9d1c5822ebbfcbf9c17c2cd4a2c) ) + ROM_LOAD( "supetpoo.s0", 0x0000, 0x080000, CRC(fdbc8b26) SHA1(16644c83780f300133a99821526c35b86bb25aad) ) + ROM_LOAD( "mmsnd1", 0x0000, 0x080000, CRC(fc33fb69) SHA1(f2d2a4469d03f5a86f3a2a08b81b0fb0b7ce6183) ) + ROM_LOAD( "mmsnd2", 0x0000, 0x080000, CRC(8de0c411) SHA1(ee6d08be19f28ef113d89be60f3f353c857da74d) ) + ROM_LOAD( "c sound2", 0x0000, 0x080000, CRC(ad191be1) SHA1(1d0934cf0d39ad842d68eeea5c91ddd8637644e6) ) + ROM_LOAD( "carry on", 0x0000, 0x080000, CRC(4282b495) SHA1(7cdec8e8219a892c26311608ebd8953b381ecc70) ) + ROM_LOAD( "double d.s0", 0x0000, 0x080000, CRC(c57cc5c1) SHA1(03e0062048eeedf55a35f31eccd658347fc68576) ) + ROM_LOAD( "double d.s1", 0x0000, 0x080000, CRC(d74b49d2) SHA1(d6d39ad08ef1dfdd36163984ed3f9ae89cbad138) ) + ROM_LOAD( "sound2.bin", 0x0000, 0x008000, CRC(84e8cf84) SHA1(e3e05a7dd5264c26378aefa540c3fd9d7b415827) )// Seems bad + ROM_LOAD( "sound3.bin", 0x0000, 0x008000, CRC(36b25191) SHA1(8a3237fa7bc5b5e630b04f76e25d22e62a4a2375) )// Similar to Club Explosion sound roms + ROM_LOAD( "sn-33-white.bin", 0x0000, 0x010000, CRC(8d5aba16) SHA1(3b63cf53e8bc7790f63fa395711114d1b195a07c) )//just bad I think + ROM_LOAD( "taker-over-008.bin", 0x0000, 0x008000, CRC(2dad1088) SHA1(b8bdf5bf4e0ef5bee44d1f7031b08e4e6a8ae5ca) )//looks a bit ACE ish, but no strings to make sure +ROM_END + +//GAME(19??, unkfr, 0, unkfr, unkfr, driver_device, empty_init, ROT0, "<unknown>", "Unknown Fruit Machine ROMs (set 1)", MACHINE_IS_SKELETON_MECHANICAL) +//GAME(19??, unkfra, 0, unkfr, unkfr, driver_device, empty_init, ROT0, "<unknown>", "Unknown Fruit Machine ROMs (set 2)", MACHINE_IS_SKELETON_MECHANICAL) + +#endif |