summaryrefslogtreecommitdiffstatshomepage
path: root/attic
diff options
context:
space:
mode:
Diffstat (limited to 'attic')
-rw-r--r--attic/fd1094dp.cpp589
-rw-r--r--attic/fddebug.cpp2439
-rw-r--r--attic/fddebug.h5
-rw-r--r--attic/jalmah.x68147
-rw-r--r--attic/jrcrypt.cpp530
-rw-r--r--attic/opwolf_cchip.txt1228
-rw-r--r--attic/unkfr.cpp752
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