summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine')
-rw-r--r--src/mame/machine/acitya.c205
-rw-r--r--src/mame/machine/ajax.c222
-rw-r--r--src/mame/machine/amiga.c1761
-rw-r--r--src/mame/machine/arkanoid.c597
-rw-r--r--src/mame/machine/asic65.c750
-rw-r--r--src/mame/machine/asic65.h18
-rw-r--r--src/mame/machine/asteroid.c193
-rw-r--r--src/mame/machine/atari.c982
-rw-r--r--src/mame/machine/atari_vg.c68
-rw-r--r--src/mame/machine/atari_vg.h13
-rw-r--r--src/mame/machine/atarifb.c304
-rw-r--r--src/mame/machine/atarigen.c1500
-rw-r--r--src/mame/machine/atarigen.h289
-rw-r--r--src/mame/machine/bagman.c242
-rw-r--r--src/mame/machine/balsente.c1251
-rw-r--r--src/mame/machine/beezer.c143
-rw-r--r--src/mame/machine/bfm_bd1.c567
-rw-r--r--src/mame/machine/bfm_bd1.h22
-rw-r--r--src/mame/machine/bigevglf.c107
-rw-r--r--src/mame/machine/bonzeadv.c467
-rw-r--r--src/mame/machine/bsktball.c169
-rw-r--r--src/mame/machine/btime.c93
-rw-r--r--src/mame/machine/bublbobl.c498
-rw-r--r--src/mame/machine/buggychl.c148
-rw-r--r--src/mame/machine/carpolo.c585
-rw-r--r--src/mame/machine/cchasm.c15
-rw-r--r--src/mame/machine/cchip.c184
-rw-r--r--src/mame/machine/cclimber.c142
-rw-r--r--src/mame/machine/chaknpop.c166
-rw-r--r--src/mame/machine/copsnrob.c59
-rw-r--r--src/mame/machine/cps2crpt.c978
-rw-r--r--src/mame/machine/cubocd32.c892
-rw-r--r--src/mame/machine/daikaiju.c351
-rw-r--r--src/mame/machine/dc.c95
-rw-r--r--src/mame/machine/dec0.c623
-rw-r--r--src/mame/machine/deco102.c93
-rw-r--r--src/mame/machine/deco156.c133
-rw-r--r--src/mame/machine/decocass.c2159
-rw-r--r--src/mame/machine/decocass.h113
-rw-r--r--src/mame/machine/decocrpt.c670
-rw-r--r--src/mame/machine/decoprot.c1772
-rw-r--r--src/mame/machine/docastle.c82
-rw-r--r--src/mame/machine/drakton.c113
-rw-r--r--src/mame/machine/equites.c444
-rw-r--r--src/mame/machine/exctsccr.c340
-rw-r--r--src/mame/machine/fd1089.c6611
-rw-r--r--src/mame/machine/fd1094.c843
-rw-r--r--src/mame/machine/fd1094.h19
-rw-r--r--src/mame/machine/fddebug.c2427
-rw-r--r--src/mame/machine/flstory.c271
-rw-r--r--src/mame/machine/gaelco2.c245
-rw-r--r--src/mame/machine/galaxian.c563
-rw-r--r--src/mame/machine/gaplus.c69
-rw-r--r--src/mame/machine/harddriv.c1941
-rw-r--r--src/mame/machine/irem_cpu.c807
-rw-r--r--src/mame/machine/irem_cpu.h19
-rw-r--r--src/mame/machine/irobot.c1023
-rw-r--r--src/mame/machine/jackal.c79
-rw-r--r--src/mame/machine/jumpshot.c56
-rw-r--r--src/mame/machine/kabuki.c214
-rw-r--r--src/mame/machine/kaneko16.c893
-rw-r--r--src/mame/machine/kanekotb.h3673
-rw-r--r--src/mame/machine/konami.c67
-rw-r--r--src/mame/machine/konamigx.c2247
-rw-r--r--src/mame/machine/konamigx.h103
-rw-r--r--src/mame/machine/konamiic.c122
-rw-r--r--src/mame/machine/konamiic.h10
-rw-r--r--src/mame/machine/konppc.c697
-rw-r--r--src/mame/machine/konppc.h44
-rw-r--r--src/mame/machine/leland.c1494
-rw-r--r--src/mame/machine/lkage.c139
-rw-r--r--src/mame/machine/lsasquad.c192
-rw-r--r--src/mame/machine/m68kfmly.c236
-rw-r--r--src/mame/machine/m68kfmly.h18
-rw-r--r--src/mame/machine/maniach.c136
-rw-r--r--src/mame/machine/mathbox.c285
-rw-r--r--src/mame/machine/mathbox.h12
-rw-r--r--src/mame/machine/mb14241.c50
-rw-r--r--src/mame/machine/mb14241.h16
-rw-r--r--src/mame/machine/mc8123.c498
-rw-r--r--src/mame/machine/mc8123.h5
-rw-r--r--src/mame/machine/mcr.c1026
-rw-r--r--src/mame/machine/meters.c113
-rw-r--r--src/mame/machine/meters.h33
-rw-r--r--src/mame/machine/mexico86.c334
-rw-r--r--src/mame/machine/mhavoc.c362
-rw-r--r--src/mame/machine/midtunit.c629
-rw-r--r--src/mame/machine/midwayic.c1098
-rw-r--r--src/mame/machine/midwayic.h55
-rw-r--r--src/mame/machine/midwunit.c668
-rw-r--r--src/mame/machine/midyunit.c578
-rw-r--r--src/mame/machine/model1.c2171
-rw-r--r--src/mame/machine/model3.c363
-rw-r--r--src/mame/machine/mspacman.c195
-rw-r--r--src/mame/machine/mw8080bw.c125
-rw-r--r--src/mame/machine/n64.c1752
-rw-r--r--src/mame/machine/namco50.c338
-rw-r--r--src/mame/machine/namco50.h23
-rw-r--r--src/mame/machine/namcoio.c1081
-rw-r--r--src/mame/machine/namcoio.h53
-rw-r--r--src/mame/machine/namcond1.c113
-rw-r--r--src/mame/machine/namcos1.c1430
-rw-r--r--src/mame/machine/namcos2.c849
-rw-r--r--src/mame/machine/nb1413m3.c708
-rw-r--r--src/mame/machine/neoboot.c1001
-rw-r--r--src/mame/machine/neocrypt.c1365
-rw-r--r--src/mame/machine/neoprot.c525
-rw-r--r--src/mame/machine/nitedrvr.c283
-rw-r--r--src/mame/machine/nmk004.c1076
-rw-r--r--src/mame/machine/nmk004.h4
-rw-r--r--src/mame/machine/nmk112.c59
-rw-r--r--src/mame/machine/nmk112.h9
-rw-r--r--src/mame/machine/nycaptor.c127
-rw-r--r--src/mame/machine/opwolf.c751
-rw-r--r--src/mame/machine/pacplus.c56
-rw-r--r--src/mame/machine/pckeybrd.c1264
-rw-r--r--src/mame/machine/pckeybrd.h35
-rw-r--r--src/mame/machine/pcshare.c572
-rw-r--r--src/mame/machine/pcshare.h29
-rw-r--r--src/mame/machine/pgmcrypt.c611
-rw-r--r--src/mame/machine/pgmprot.c891
-rw-r--r--src/mame/machine/pgmy2ks.c2122
-rw-r--r--src/mame/machine/pitnrun.c158
-rw-r--r--src/mame/machine/playch10.c905
-rw-r--r--src/mame/machine/psx.c1650
-rw-r--r--src/mame/machine/qix.c605
-rw-r--r--src/mame/machine/rainbow.c831
-rw-r--r--src/mame/machine/retofinv.c137
-rw-r--r--src/mame/machine/s16fd.c198
-rw-r--r--src/mame/machine/s24fd.c149
-rw-r--r--src/mame/machine/sbrkout.c110
-rw-r--r--src/mame/machine/scramble.c946
-rw-r--r--src/mame/machine/scudsp.c1278
-rw-r--r--src/mame/machine/scudsp.h9
-rw-r--r--src/mame/machine/segacrpt.c1422
-rw-r--r--src/mame/machine/segacrpt.h35
-rw-r--r--src/mame/machine/segag80.c347
-rw-r--r--src/mame/machine/segaic16.c702
-rw-r--r--src/mame/machine/segaic16.h56
-rw-r--r--src/mame/machine/segas32.c400
-rw-r--r--src/mame/machine/seibuspi.c388
-rw-r--r--src/mame/machine/simpsons.c146
-rw-r--r--src/mame/machine/slapfght.c251
-rw-r--r--src/mame/machine/slapstic.c1174
-rw-r--r--src/mame/machine/slikshot.c697
-rw-r--r--src/mame/machine/snes.c1911
-rw-r--r--src/mame/machine/snesdsp1.c1268
-rw-r--r--src/mame/machine/spisprit.c281
-rw-r--r--src/mame/machine/stactics.c94
-rw-r--r--src/mame/machine/starwars.c480
-rw-r--r--src/mame/machine/steppers.c746
-rw-r--r--src/mame/machine/steppers.h40
-rw-r--r--src/mame/machine/stfight.c244
-rw-r--r--src/mame/machine/strtheat.c194
-rw-r--r--src/mame/machine/stvcd.c1856
-rw-r--r--src/mame/machine/stvcd.h17
-rw-r--r--src/mame/machine/stvprot.c480
-rw-r--r--src/mame/machine/stvprot.h8
-rw-r--r--src/mame/machine/subs.c186
-rw-r--r--src/mame/machine/system16.c69
-rw-r--r--src/mame/machine/system24.c109
-rw-r--r--src/mame/machine/tait8741.c553
-rw-r--r--src/mame/machine/tait8741.h50
-rw-r--r--src/mame/machine/taitosj.c349
-rw-r--r--src/mame/machine/tatsumi.c373
-rw-r--r--src/mame/machine/theglobp.c259
-rw-r--r--src/mame/machine/ticket.c190
-rw-r--r--src/mame/machine/ticket.h38
-rw-r--r--src/mame/machine/tnzs.c782
-rw-r--r--src/mame/machine/toaplan1.c341
-rw-r--r--src/mame/machine/twincobr.c394
-rw-r--r--src/mame/machine/tx1.c679
-rw-r--r--src/mame/machine/vertigo.c228
-rw-r--r--src/mame/machine/volfied.c495
-rw-r--r--src/mame/machine/vsnes.c1361
-rw-r--r--src/mame/machine/williams.c919
-rw-r--r--src/mame/machine/wrally.c154
-rw-r--r--src/mame/machine/xevious.c185
-rw-r--r--src/mame/machine/znsec.c181
-rw-r--r--src/mame/machine/znsec.h5
-rw-r--r--src/mame/machine/zs01.c697
-rw-r--r--src/mame/machine/zs01.h25
182 files changed, 100454 insertions, 0 deletions
diff --git a/src/mame/machine/acitya.c b/src/mame/machine/acitya.c
new file mode 100644
index 00000000000..ea71c9e265c
--- /dev/null
+++ b/src/mame/machine/acitya.c
@@ -0,0 +1,205 @@
+/***************************************************************************
+
+ machine.c
+
+Same Epos board as usual(theglobp,beastf,street heat), see theglobp.c for hardware documentation. This is fairly easy to decrypt since it has consecutive bytes with the same algorithym. There are 4 different algorithyms. One consists almost entirely of text, one contains the majority of code and the remaining 2 are not used much and are therefore the most difficult. It is however difficult to decrypt to rom. The data for the coin sound is actually program code in a different phase. You need to move the sound tables and add a rom to get it to run without the daughterboard.
+
+acitya contains a bug with the insurance in blackjack. It's impossible to collect, so it's likely that acitya is earlier than bwcasino.
+
+I don't think this game is a gambling game. For one thing there's no real output hardware on a pacman board and the epos daughterboard doesn't contain any either.
+
+David Widel d_widel@hotmail.com
+
+***************************************************************************/
+
+#include "driver.h"
+#include "includes/pacman.h"
+
+static INT8 counter=0;
+
+
+static void acitya_decrypt_rom_8(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* Direct inversion */
+ newbyte = (inverted_oldbyte & 0x80) >> 2;
+ newbyte |= (oldbyte & 0x40) >> 0;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (inverted_oldbyte & 0x10) >> 1;
+ newbyte |= (oldbyte & 0x08) << 1;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (oldbyte & 0x02) << 6;
+ newbyte |= (inverted_oldbyte & 0x01) << 2;
+
+ RAM[mem + 0x10000] = newbyte;
+ }
+
+ return;
+}
+
+
+static void acitya_decrypt_rom_9(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* Direct inversion */
+ newbyte = (inverted_oldbyte & 0x80) >> 0;
+ newbyte |= (oldbyte & 0x40) >> 0;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (oldbyte & 0x10) >> 1;
+ newbyte |= (oldbyte & 0x08) << 1;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x02) << 4;
+ newbyte |= (inverted_oldbyte & 0x01) << 2;
+ RAM[mem + 0x14000] = newbyte;
+ }
+
+ return;
+}
+
+static void acitya_decrypt_rom_A(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ newbyte = (inverted_oldbyte & 0x80) >> 2;
+ newbyte |= (inverted_oldbyte & 0x40) >> 2;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (inverted_oldbyte & 0x10) >> 1;
+
+ newbyte |= (inverted_oldbyte & 0x08) >> 1;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (oldbyte & 0x02) << 6;
+ newbyte |= (oldbyte & 0x01) << 6;
+ RAM[mem + 0x18000] = newbyte;
+ }
+
+ return;
+}
+
+static void acitya_decrypt_rom_B(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* Direct inversion */
+ newbyte = (inverted_oldbyte & 0x80) >> 0;
+ newbyte |= (inverted_oldbyte & 0x40) >> 2;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (oldbyte & 0x10) >> 1;
+ newbyte |= (inverted_oldbyte & 0x08) >> 1;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x02) << 4;
+ newbyte |= (oldbyte & 0x01) << 6;
+
+
+ RAM[mem + 0x1C000] = newbyte;
+ }
+
+ return;
+}
+
+
+READ8_HANDLER( acitya_decrypt_rom )
+{
+ if (offset & 0x01)
+ {
+ counter = counter - 1;
+ if (counter < 0)
+ counter = 0x0F;
+ }
+ else
+ {
+ counter = (counter + 1) & 0x0F;
+ }
+
+ switch(counter)
+ {
+ case 0x08: memory_set_bank (1, 0); break;
+ case 0x09: memory_set_bank (1, 1); break;
+ case 0x0A: memory_set_bank (1, 2); break;
+ case 0x0B: memory_set_bank (1, 3); break;
+ default:
+ logerror("Invalid counter = %02X\n",counter);
+ break;
+ }
+
+ return 0;
+}
+
+
+MACHINE_RESET( acitya )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ /* While the PAL supports up to 16 decryption methods, only four
+ are actually used in the PAL. Therefore, we'll take a little
+ memory overhead and decrypt the ROMs using each method in advance. */
+ acitya_decrypt_rom_8();
+ acitya_decrypt_rom_9();
+ acitya_decrypt_rom_A();
+ acitya_decrypt_rom_B();
+
+ /* The initial state of the counter is 0x0B */
+ counter = 0x0B;
+ memory_configure_bank(1, 0, 4, &RAM[0x10000], 0x4000);
+ memory_set_bank(1, 3);
+
+ state_save_register_global(counter);
+}
diff --git a/src/mame/machine/ajax.c b/src/mame/machine/ajax.c
new file mode 100644
index 00000000000..f84afa67260
--- /dev/null
+++ b/src/mame/machine/ajax.c
@@ -0,0 +1,222 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6809/m6809.h"
+#include "cpu/z80/z80.h"
+#include "cpu/konami/konami.h"
+#include "video/konamiic.h"
+
+UINT8 *ajax_sharedram;
+extern UINT8 ajax_priority;
+static int firq_enable;
+
+/* ajax_bankswitch_w:
+ Handled by the LS273 Octal +ve edge trigger D-type Flip-flop with Reset at H11:
+
+ Bit Description
+ --- -----------
+ 7 MRB3 Selects ROM N11/N12
+ 6 CCOUNT2 Coin Counter 2 (*)
+ 5 CCOUNT1 Coin Counter 1 (*)
+ 4 SRESET Slave CPU Reset?
+ 3 PRI0 Layer Priority Selector
+ 2 MRB2 \
+ 1 MRB1 | ROM Bank Select
+ 0 MRB0 /
+
+ (*) The Coin Counters are handled by the Konami Custom 051550
+*/
+
+static WRITE8_HANDLER( ajax_bankswitch_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+ int bankaddress = 0;
+
+ /* rom select */
+ if (!(data & 0x80)) bankaddress += 0x8000;
+
+ /* coin counters */
+ coin_counter_w(0,data & 0x20);
+ coin_counter_w(1,data & 0x40);
+
+ /* priority */
+ ajax_priority = data & 0x08;
+
+ /* bank # (ROMS N11 and N12) */
+ bankaddress += 0x10000 + (data & 0x07)*0x2000;
+ memory_set_bankptr(2,&RAM[bankaddress]);
+}
+
+/* ajax_lamps_w:
+ Handled by the LS273 Octal +ve edge trigger D-type Flip-flop with Reset at B9:
+
+ Bit Description
+ --- -----------
+ 7 LAMP7 & LAMP8 - Game over lamps (*)
+ 6 LAMP3 & LAMP4 - Game over lamps (*)
+ 5 LAMP1 - Start lamp (*)
+ 4 Control panel quaking (**)
+ 3 Joystick vibration (**)
+ 2 LAMP5 & LAMP6 - Power up lamps (*)
+ 1 LAMP2 - Super weapon lamp (*)
+ 0 unused
+
+ (*) The Lamps are handled by the M54585P
+ (**)Vibration/Quaking handled by these chips:
+ Chip Location Description
+ ---- -------- -----------
+ PS2401-4 B21 ???
+ UPA1452H B22 ???
+ LS74 H2 Dual +ve edge trigger D-type Flip-flop with SET and RESET
+ LS393 C20 Dual -ve edge trigger 4-bit Binary Ripple Counter with Resets
+*/
+
+static WRITE8_HANDLER( ajax_lamps_w )
+{
+ set_led_status(1,data & 0x02); /* super weapon lamp */
+ set_led_status(2,data & 0x04); /* power up lamps */
+ set_led_status(5,data & 0x04); /* power up lamps */
+ set_led_status(0,data & 0x20); /* start lamp */
+ set_led_status(3,data & 0x40); /* game over lamps */
+ set_led_status(6,data & 0x40); /* game over lamps */
+ set_led_status(4,data & 0x80); /* game over lamps */
+ set_led_status(7,data & 0x80); /* game over lamps */
+}
+
+/* ajax_ls138_f10:
+ The LS138 1-of-8 Decoder/Demultiplexer at F10 selects what to do:
+
+ Address R/W Description
+ ------- --- -----------
+ 0x0000 (r) ??? I think this read is because a CPU core bug
+ (w) 0x0000 NSFIRQ Trigger FIRQ on the M6809
+ 0x0020 AFR Watchdog reset (handled by the 051550)
+ 0x0040 (w) SOUND Cause interrupt on the Z80
+ 0x0080 (w) SOUNDDATA Sound code number
+ 0x00c0 (w) MBL1 Enables the LS273 at H11 (Banking + Coin counters)
+ 0x0100 (r) MBL2 Enables 2P Inputs reading
+ 0x0140 (w) MBL3 Enables the LS273 at B9 (Lamps + Vibration)
+ 0x0180 (r) MIO1 Enables 1P Inputs + DIPSW #1 & #2 reading
+ 0x01c0 (r) MIO2 Enables DIPSW #3 reading
+*/
+
+READ8_HANDLER( ajax_ls138_f10_r )
+{
+ int data = 0;
+
+ switch ((offset & 0x01c0) >> 6){
+ case 0x00: /* ??? */
+ data = mame_rand(Machine);
+ break;
+ case 0x04: /* 2P inputs */
+ data = readinputport(5);
+ break;
+ case 0x06: /* 1P inputs + DIPSW #1 & #2 */
+ if (offset & 0x02)
+ data = readinputport(offset & 0x01);
+ else
+ data = readinputport(3 + (offset & 0x01));
+ break;
+ case 0x07: /* DIPSW #3 */
+ data = readinputport(2);
+ break;
+
+ default:
+ logerror("%04x: (ls138_f10) read from an unknown address %02x\n",activecpu_get_pc(), offset);
+ }
+
+ return data;
+}
+
+WRITE8_HANDLER( ajax_ls138_f10_w )
+{
+ switch ((offset & 0x01c0) >> 6){
+ case 0x00: /* NSFIRQ + AFR */
+ if (offset)
+ watchdog_reset_w(0, data);
+ else{
+ if (firq_enable) /* Cause interrupt on slave CPU */
+ cpunum_set_input_line(1, M6809_FIRQ_LINE, HOLD_LINE);
+ }
+ break;
+ case 0x01: /* Cause interrupt on audio CPU */
+ cpunum_set_input_line(2, 0, HOLD_LINE);
+ break;
+ case 0x02: /* Sound command number */
+ soundlatch_w(offset,data);
+ break;
+ case 0x03: /* Bankswitch + coin counters + priority*/
+ ajax_bankswitch_w(0, data);
+ break;
+ case 0x05: /* Lamps + Joystick vibration + Control panel quaking */
+ ajax_lamps_w(0, data);
+ break;
+
+ default:
+ logerror("%04x: (ls138_f10) write %02x to an unknown address %02x\n",activecpu_get_pc(), data, offset);
+ }
+}
+
+/* Shared RAM between the 052001 and the 6809 (6264SL at I8) */
+READ8_HANDLER( ajax_sharedram_r )
+{
+ return ajax_sharedram[offset];
+}
+
+WRITE8_HANDLER( ajax_sharedram_w )
+{
+ ajax_sharedram[offset] = data;
+}
+
+/* ajax_bankswitch_w_2:
+ Handled by the LS273 Octal +ve edge trigger D-type Flip-flop with Reset at K14:
+
+ Bit Description
+ --- -----------
+ 7 unused
+ 6 RMRD Enable char ROM reading through the video RAM
+ 5 RVO enables 051316 wraparound
+ 4 FIRQST FIRQ control
+ 3 SRB3 \
+ 2 SRB2 |
+ 1 SRB1 | ROM Bank Select
+ 0 SRB0 /
+*/
+
+WRITE8_HANDLER( ajax_bankswitch_2_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU2);
+ int bankaddress;
+
+ /* enable char ROM reading through the video RAM */
+ K052109_set_RMRD_line((data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
+
+ /* bit 5 enables 051316 wraparound */
+ K051316_wraparound_enable(0, data & 0x20);
+
+ /* FIRQ control */
+ firq_enable = data & 0x10;
+
+ /* bank # (ROMS G16 and I16) */
+ bankaddress = 0x10000 + (data & 0x0f)*0x2000;
+ memory_set_bankptr(1,&RAM[bankaddress]);
+}
+
+
+MACHINE_RESET( ajax )
+{
+ firq_enable = 1;
+}
+
+INTERRUPT_GEN( ajax_interrupt )
+{
+ if (K051960_is_IRQ_enabled())
+ cpunum_set_input_line(0, KONAMI_IRQ_LINE, HOLD_LINE);
+}
diff --git a/src/mame/machine/amiga.c b/src/mame/machine/amiga.c
new file mode 100644
index 00000000000..27fdd27cb0a
--- /dev/null
+++ b/src/mame/machine/amiga.c
@@ -0,0 +1,1761 @@
+/***************************************************************************
+
+ Amiga Computer / Arcadia Game System
+
+ Driver by:
+
+ Aaron Giles, Ernesto Corvi & Mariusz Wojcieszek
+
+***************************************************************************/
+
+#include "driver.h"
+#include "includes/amiga.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/6526cia.h"
+
+
+/*************************************
+ *
+ * Debugging
+ *
+ *************************************/
+
+#define LOG_CUSTOM 0
+#define LOG_CIA 0
+#define LOG_BLITS 0
+
+
+
+/*************************************
+ *
+ * Constants
+ *
+ *************************************/
+
+/* 715909 Hz for NTSC, 709379 for PAL */
+#define O2_CLOCK (Machine->drv->cpu[0].clock / 10)
+
+/* How many CPU cycles we delay until we fire a pending interrupt */
+#define AMIGA_IRQ_DELAY_CYCLES 24
+
+/* How many CPU cycles we wait until we process a blit when the blitter-nasty bit is set */
+#define BLITTER_NASTY_DELAY 16
+
+
+/*************************************
+ *
+ * Type definitions
+ *
+ *************************************/
+
+typedef struct _autoconfig_device autoconfig_device;
+struct _autoconfig_device
+{
+ autoconfig_device * next;
+ amiga_autoconfig_device device;
+ offs_t base;
+};
+
+
+
+/*************************************
+ *
+ * Globals
+ *
+ *************************************/
+
+UINT16 *amiga_chip_ram;
+UINT32 *amiga_chip_ram32;
+size_t amiga_chip_ram_size;
+
+UINT16 *amiga_custom_regs;
+UINT16 *amiga_expansion_ram;
+UINT16 *amiga_autoconfig_mem;
+
+static const amiga_machine_interface *amiga_intf;
+
+static autoconfig_device *autoconfig_list;
+static autoconfig_device *cur_autoconfig;
+static emu_timer * amiga_irq_timer;
+static emu_timer * amiga_blitter_timer;
+
+const char *amiga_custom_names[0x100] =
+{
+ /* 0x000 */
+ "BLTDDAT", "DMACONR", "VPOSR", "VHPOSR",
+ "DSKDATR", "JOY0DAT", "JOY1DAT", "CLXDAT",
+ "ADKCONR", "POT0DAT", "POT1DAT", "POTGOR",
+ "SERDATR", "DSKBYTR", "INTENAR", "INTREQR",
+ /* 0x020 */
+ "DSKPTH", "DSKPTL", "DSKLEN", "DSKDAT",
+ "REFPTR", "VPOSW", "VHPOSW", "COPCON",
+ "SERDAT", "SERPER", "POTGO", "JOYTEST",
+ "STREQU", "STRVBL", "STRHOR", "STRLONG",
+ /* 0x040 */
+ "BLTCON0", "BLTCON1", "BLTAFWM", "BLTALWM",
+ "BLTCPTH", "BLTCPTL", "BLTBPTH", "BLTBPTL",
+ "BLTAPTH", "BLTAPTL", "BLTDPTH", "BLTDPTL",
+ "BLTSIZE", "BLTCON0L", "BLTSIZV", "BLTSIZH",
+ /* 0x060 */
+ "BLTCMOD", "BLTBMOD", "BLTAMOD", "BLTDMOD",
+ "UNK068", "UNK06A", "UNK06C", "UNK06E",
+ "BLTCDAT", "BLTBDAT", "BLTADAT", "UNK076",
+ "UNK078", "UNK07A", "UNK07C", "DSRSYNC",
+ /* 0x080 */
+ "COP1LCH", "COP1LCL", "COP2LCH", "COP2LCL",
+ "COPJMP1", "COPJMP2", "COPINS", "DIWSTRT",
+ "DIWSTOP", "DDFSTRT", "DDFSTOP", "DMACON",
+ "CLXCON", "INTENA", "INTREQ", "ADKCON",
+ /* 0x0A0 */
+ "AUD0LCH", "AUD0LCL", "AUD0LEN", "AUD0PER",
+ "AUD0VOL", "AUD0DAT", "UNK0AC", "UNK0AE",
+ "AUD1LCH", "AUD1LCL", "AUD1LEN", "AUD1PER",
+ "AUD1VOL", "AUD1DAT", "UNK0BC", "UNK0BE",
+ /* 0x0C0 */
+ "AUD2LCH", "AUD2LCL", "AUD2LEN", "AUD2PER",
+ "AUD2VOL", "AUD2DAT", "UNK0CC", "UNK0CE",
+ "AUD3LCH", "AUD3LCL", "AUD3LEN", "AUD3PER",
+ "AUD3VOL", "AUD3DAT", "UNK0DC", "UNK0DE",
+ /* 0x0E0 */
+ "BPL1PTH", "BPL1PTL", "BPL2PTH", "BPL2PTL",
+ "BPL3PTH", "BPL3PTL", "BPL4PTH", "BPL4PTL",
+ "BPL5PTH", "BPL5PTL", "BPL6PTH", "BPL6PTL",
+ "UNK0F8", "UNK0FA", "UNK0FC", "UNK0FE",
+ /* 0x100 */
+ "BPLCON0", "BPLCON1", "BPLCON2", "UNK106",
+ "BPL1MOD", "BPL2MOD", "UNK10C", "UNK10E",
+ "BPL1DAT", "BPL2DAT", "BPL3DAT", "BPL4DAT",
+ "BPL5DAT", "BPL6DAT", "UNK11C", "UNK11E",
+ /* 0x120 */
+ "SPR0PTH", "SPR0PTL", "SPR1PTH", "SPR1PTL",
+ "SPR2PTH", "SPR2PTL", "SPR3PTH", "SPR3PTL",
+ "SPR4PTH", "SPR4PTL", "SPR5PTH", "SPR5PTL",
+ "SPR6PTH", "SPR6PTL", "SPR7PTH", "SPR7PTL",
+ /* 0x140 */
+ "SPR0POS", "SPR0CTL", "SPR0DATA", "SPR0DATB",
+ "SPR1POS", "SPR1CTL", "SPR1DATA", "SPR1DATB",
+ "SPR2POS", "SPR2CTL", "SPR2DATA", "SPR2DATB",
+ "SPR3POS", "SPR3CTL", "SPR3DATA", "SPR3DATB",
+ /* 0x160 */
+ "SPR4POS", "SPR4CTL", "SPR4DATA", "SPR4DATB",
+ "SPR5POS", "SPR5CTL", "SPR5DATA", "SPR5DATB",
+ "SPR6POS", "SPR6CTL", "SPR6DATA", "SPR6DATB",
+ "SPR7POS", "SPR7CTL", "SPR7DATA", "SPR7DATB",
+ /* 0x180 */
+ "COLOR00", "COLOR01", "COLOR02", "COLOR03",
+ "COLOR04", "COLOR05", "COLOR06", "COLOR07",
+ "COLOR08", "COLOR09", "COLOR10", "COLOR11",
+ "COLOR12", "COLOR13", "COLOR14", "COLOR15",
+ /* 0x1A0 */
+ "COLOR16", "COLOR17", "COLOR18", "COLOR19",
+ "COLOR20", "COLOR21", "COLOR22", "COLOR23",
+ "COLOR24", "COLOR25", "COLOR26", "COLOR27",
+ "COLOR28", "COLOR29", "COLOR30", "COLOR31",
+ /* 0x1C0 */
+ "UNK1C0", "UNK1C2", "UNK1C4", "UNK1C6",
+ "UNK1C8", "UNK1CA", "UNK1CC", "UNK1CE",
+ "UNK1D0", "UNK1D2", "UNK1D4", "UNK1D6",
+ "UNK1D8", "UNK1DA", "UNK1DC", "UNK1DE",
+ /* 0x1E0 */
+ "UNK1E0", "UNK1E2", "UNK1E4", "UNK1E6",
+ "UNK1E8", "UNK1EA", "UNK1EC", "UNK1EE",
+ "UNK1F0", "UNK1F2", "UNK1F4", "UNK1F6",
+ "UNK1F8", "UNK1FA", "UNK1FC", "UNK1FE"
+};
+
+
+
+/*************************************
+ *
+ * Prototypes
+ *
+ *************************************/
+
+static void custom_reset(void);
+static void autoconfig_reset(void);
+static void amiga_cia_0_irq(int state);
+static void amiga_cia_1_irq(int state);
+static TIMER_CALLBACK( amiga_irq_proc );
+static TIMER_CALLBACK( amiga_blitter_proc );
+
+/*************************************
+ *
+ * Chipmem 16/32 bit access
+ *
+ *************************************/
+
+UINT16 (*amiga_chip_ram_r)(offs_t offset);
+void (*amiga_chip_ram_w)(offs_t offset, UINT16 data);
+
+static UINT16 amiga_chip_ram16_r(offs_t offset)
+{
+ extern const amiga_machine_interface *amiga_intf;
+ offset &= amiga_intf->chip_ram_mask;
+ return (offset < amiga_chip_ram_size) ? amiga_chip_ram[offset/2] : 0xffff;
+}
+
+static UINT16 amiga_chip_ram32_r(offs_t offset)
+{
+ extern const amiga_machine_interface *amiga_intf;
+ offset &= amiga_intf->chip_ram_mask;
+
+ if ( offset < amiga_chip_ram_size )
+ {
+ UINT32 dat = amiga_chip_ram32[offset / 4];
+
+ if ( offset & 2 )
+ return (dat & 0xffff);
+
+ return (dat >> 16);
+ }
+
+ return 0xffff;
+}
+
+static void amiga_chip_ram16_w(offs_t offset, UINT16 data)
+{
+ extern const amiga_machine_interface *amiga_intf;
+ offset &= amiga_intf->chip_ram_mask;
+
+ if (offset < amiga_chip_ram_size)
+ amiga_chip_ram[offset/2] = data;
+}
+
+static void amiga_chip_ram32_w(offs_t offset, UINT16 data)
+{
+ extern const amiga_machine_interface *amiga_intf;
+ offset &= amiga_intf->chip_ram_mask;
+
+ if ( offset < amiga_chip_ram_size )
+ {
+ UINT32 dat = amiga_chip_ram32[offset / 4];
+
+ if ( offset & 2 )
+ {
+ dat &= 0xffff0000;
+ dat |= data;
+ }
+ else
+ {
+ dat &= 0x0000ffff;
+ dat |= ((UINT32)data) << 16;
+ }
+
+ amiga_chip_ram32[offset / 4] = dat;
+ }
+}
+
+
+/*************************************
+ *
+ * Machine config/reset
+ *
+ *************************************/
+
+void amiga_machine_config(const amiga_machine_interface *intf)
+{
+ cia6526_interface cia_intf[2];
+
+ amiga_intf = intf;
+
+ /* setup chipmem handlers */
+ if ( IS_AGA(intf) )
+ {
+ amiga_chip_ram_r = amiga_chip_ram32_r;
+ amiga_chip_ram_w = amiga_chip_ram32_w;
+ }
+ else
+ {
+ amiga_chip_ram_r = amiga_chip_ram16_r;
+ amiga_chip_ram_w = amiga_chip_ram16_w;
+ }
+
+ /* set up CIA interfaces */
+ memset(&cia_intf, 0, sizeof(cia_intf));
+ cia_intf[0].type = CIA8520;
+ cia_intf[0].clock = O2_CLOCK;
+ cia_intf[0].tod_clock = 0;
+ cia_intf[0].irq_func = amiga_cia_0_irq;
+ cia_intf[0].port[0].read = intf->cia_0_portA_r;
+ cia_intf[0].port[0].write = intf->cia_0_portA_w;
+ cia_intf[0].port[1].read = intf->cia_0_portB_r;
+ cia_intf[0].port[1].write = intf->cia_0_portB_w;
+ cia_config(0, &cia_intf[0]);
+
+ cia_intf[1].type = CIA8520;
+ cia_intf[1].clock = O2_CLOCK;
+ cia_intf[1].tod_clock = 0;
+ cia_intf[1].irq_func = amiga_cia_1_irq;
+ cia_intf[1].port[0].read = intf->cia_1_portA_r;
+ cia_intf[1].port[0].write = intf->cia_1_portA_w;
+ cia_intf[1].port[1].read = intf->cia_1_portB_r;
+ cia_intf[1].port[1].write = intf->cia_1_portB_w;
+ cia_config(1, &cia_intf[1]);
+
+ /* setup the timers */
+ amiga_irq_timer = timer_alloc(amiga_irq_proc);
+ amiga_blitter_timer = timer_alloc(amiga_blitter_proc);
+}
+
+
+static void amiga_m68k_reset(void)
+{
+ logerror("Executed RESET at PC=%06x\n", activecpu_get_pc());
+
+ /* Initialize the various chips */
+ cia_reset();
+ custom_reset();
+ autoconfig_reset();
+
+ /* set the overlay bit */
+ if ( IS_AGA(amiga_intf) )
+ {
+ program_write_byte( 0xbfa001, 1 );
+ }
+ else
+ {
+ amiga_cia_w(0x1001/2, 1, 0);
+ }
+
+ if (activecpu_get_pc() < 0x80000)
+ memory_set_opbase(0);
+}
+
+
+MACHINE_RESET( amiga )
+{
+ /* set m68k reset function */
+ cpunum_set_info_fct(0, CPUINFO_PTR_M68K_RESET_CALLBACK, (genf *)amiga_m68k_reset);
+
+ /* Initialize the various chips */
+ cia_reset();
+ custom_reset();
+ autoconfig_reset();
+
+ /* set the overlay bit */
+ if ( IS_AGA(amiga_intf) )
+ {
+ program_write_byte( 0xbfa001, 1 );
+ }
+ else
+ {
+ amiga_cia_w(0x1001/2, 1, 0);
+ }
+
+ /* call the system-specific callback */
+ if (amiga_intf->reset_callback)
+ (*amiga_intf->reset_callback)();
+}
+
+
+
+/*************************************
+ *
+ * Per scanline callback
+ *
+ *************************************/
+
+INTERRUPT_GEN( amiga_scanline_callback )
+{
+ int scanline = Machine->screen[0].height - 1 - cpu_getiloops();
+
+ /* on the first scanline, we do some extra bookkeeping */
+ if (scanline == 0)
+ {
+ /* signal VBLANK IRQ */
+ amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_VERTB, 0);
+
+ /* clock the first CIA TOD */
+ cia_clock_tod(0);
+
+ /* call the system-specific callback */
+ if (amiga_intf->scanline0_callback != NULL)
+ (*amiga_intf->scanline0_callback)();
+ }
+
+ /* on every scanline, clock the second CIA TOD */
+ cia_clock_tod(1);
+
+ /* render this scanline */
+ amiga_render_scanline(scanline);
+
+ /* force a sound update */
+ amiga_audio_update();
+}
+
+
+
+/*************************************
+ *
+ * Interrupt management
+ *
+ *************************************/
+
+static void update_irqs(void)
+{
+ int ints = CUSTOM_REG(REG_INTENA) & CUSTOM_REG(REG_INTREQ);
+ int irq = -1;
+
+ /* Master interrupt switch */
+ if (CUSTOM_REG(REG_INTENA) & 0x4000)
+ {
+ /* Serial transmit buffer empty, disk block finished, software interrupts */
+ if (ints & 0x0007)
+ irq = 1;
+
+ /* I/O ports and timer interrupts */
+ if (ints & 0x0008)
+ irq = 2;
+
+ /* Copper, VBLANK, blitter interrupts */
+ if (ints & 0x0070)
+ irq = 3;
+
+ /* Audio interrupts */
+ if (ints & 0x0780)
+ irq = 4;
+
+ /* Serial receive buffer full, disk sync match */
+ if (ints & 0x1800)
+ irq = 5;
+
+ /* External interrupts */
+ if (ints & 0x2000)
+ irq = 6;
+ }
+
+ /* set the highest IRQ line */
+ if (irq >= 0)
+ cpunum_set_input_line(0, irq, ASSERT_LINE);
+ else
+ cpunum_set_input_line(0, 7, CLEAR_LINE);
+}
+
+static TIMER_CALLBACK( amiga_irq_proc )
+{
+ update_irqs();
+ timer_reset( amiga_irq_timer, attotime_never);
+}
+
+/*************************************
+ *
+ * Standard joystick conversion
+ *
+ *************************************/
+
+UINT32 amiga_joystick_convert(void *param)
+{
+ UINT8 bits = readinputportbytag(param);
+ int up = (bits >> 0) & 1;
+ int down = (bits >> 1) & 1;
+ int left = (bits >> 2) & 1;
+ int right = (bits >> 3) & 1;
+
+ if (left) up ^= 1;
+ if (right) down ^= 1;
+
+ return down | (right << 1) | (up << 8) | (left << 9);
+}
+
+
+
+/*************************************
+ *
+ * Ascending blitter variant
+ *
+ *************************************/
+
+static UINT32 blit_ascending(void)
+{
+ UINT32 shifta = (CUSTOM_REG(REG_BLTCON0) >> 12) & 0xf;
+ UINT32 shiftb = (CUSTOM_REG(REG_BLTCON1) >> 12) & 0xf;
+ UINT32 height = CUSTOM_REG(REG_BLTSIZV);
+ UINT32 width = CUSTOM_REG(REG_BLTSIZH);
+ UINT32 acca = 0, accb = 0;
+ UINT32 blitsum = 0;
+ UINT32 x, y;
+
+ /* iterate over the height */
+ for (y = 0; y < height; y++)
+ {
+ /* iterate over the width */
+ for (x = 0; x < width; x++)
+ {
+ UINT16 abc0, abc1, abc2, abc3;
+ UINT32 tempa, tempd = 0;
+ UINT32 b;
+
+ /* fetch data for A */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
+ {
+ CUSTOM_REG(REG_BLTADAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTAPTH));
+ CUSTOM_REG_LONG(REG_BLTAPTH) += 2;
+ }
+
+ /* fetch data for B */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
+ {
+ CUSTOM_REG(REG_BLTBDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTBPTH));
+ CUSTOM_REG_LONG(REG_BLTBPTH) += 2;
+ }
+
+ /* fetch data for C */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
+ {
+ CUSTOM_REG(REG_BLTCDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTCPTH));
+ CUSTOM_REG_LONG(REG_BLTCPTH) += 2;
+ }
+
+ /* apply start/end masks to the A data */
+ tempa = CUSTOM_REG(REG_BLTADAT);
+ if (x == 0)
+ tempa &= CUSTOM_REG(REG_BLTAFWM);
+ if (x == width - 1)
+ tempa &= CUSTOM_REG(REG_BLTALWM);
+
+ /* update the B accumulator applying shifts */
+ acca = (acca << 16) | (tempa << (16 - shifta));
+ accb = (accb << 16) | (CUSTOM_REG(REG_BLTBDAT) << (16 - shiftb));
+
+ /* build up 4 16-bit words containing 4 pixels each in 0ABC bit order */
+ abc0 = ((acca >> 17) & 0x4444) | ((accb >> 18) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 3) & 0x1111);
+ abc1 = ((acca >> 16) & 0x4444) | ((accb >> 17) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 2) & 0x1111);
+ abc2 = ((acca >> 15) & 0x4444) | ((accb >> 16) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 1) & 0x1111);
+ abc3 = ((acca >> 14) & 0x4444) | ((accb >> 15) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 0) & 0x1111);
+
+ /* now loop over bits and compute the destination value */
+ for (b = 0; b < 4; b++)
+ {
+ UINT32 bit;
+
+ /* shift previous data up 4 bits */
+ tempd <<= 4;
+
+ /* lookup first bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc0 >> 12)) & 1;
+ abc0 <<= 4;
+ tempd |= bit << 3;
+
+ /* lookup second bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc1 >> 12)) & 1;
+ abc1 <<= 4;
+ tempd |= bit << 2;
+
+ /* lookup third bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc2 >> 12)) & 1;
+ abc2 <<= 4;
+ tempd |= bit << 1;
+
+ /* lookup fourth bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc3 >> 12)) & 1;
+ abc3 <<= 4;
+ tempd |= bit << 0;
+ }
+
+ /* accumulate the sum */
+ blitsum |= tempd;
+
+ /* write to the destination */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
+ {
+ amiga_chip_ram_w(CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
+ CUSTOM_REG_LONG(REG_BLTDPTH) += 2;
+ }
+ }
+
+ /* apply end of line modulos */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
+ CUSTOM_REG_LONG(REG_BLTAPTH) += CUSTOM_REG_SIGNED(REG_BLTAMOD) & ~1;
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
+ CUSTOM_REG_LONG(REG_BLTBPTH) += CUSTOM_REG_SIGNED(REG_BLTBMOD) & ~1;
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
+ CUSTOM_REG_LONG(REG_BLTCPTH) += CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1;
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
+ CUSTOM_REG_LONG(REG_BLTDPTH) += CUSTOM_REG_SIGNED(REG_BLTDMOD) & ~1;
+ }
+
+ /* return the blit sum */
+ return blitsum;
+}
+
+
+
+/*************************************
+ *
+ * Descending blitter variant
+ *
+ *************************************/
+
+static UINT32 blit_descending(void)
+{
+ UINT32 fill_exclusive = (CUSTOM_REG(REG_BLTCON1) >> 4);
+ UINT32 fill_inclusive = (CUSTOM_REG(REG_BLTCON1) >> 3);
+ UINT32 shifta = (CUSTOM_REG(REG_BLTCON0) >> 12) & 0xf;
+ UINT32 shiftb = (CUSTOM_REG(REG_BLTCON1) >> 12) & 0xf;
+ UINT32 height = CUSTOM_REG(REG_BLTSIZV);
+ UINT32 width = CUSTOM_REG(REG_BLTSIZH);
+ UINT32 acca = 0, accb = 0;
+ UINT32 blitsum = 0;
+ UINT32 x, y;
+
+ /* iterate over the height */
+ for (y = 0; y < height; y++)
+ {
+ UINT32 fill_state = (CUSTOM_REG(REG_BLTCON1) >> 2) & 1;
+
+ /* iterate over the width */
+ for (x = 0; x < width; x++)
+ {
+ UINT16 abc0, abc1, abc2, abc3;
+ UINT32 tempa, tempd = 0;
+ UINT32 b;
+
+ /* fetch data for A */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
+ {
+ CUSTOM_REG(REG_BLTADAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTAPTH));
+ CUSTOM_REG_LONG(REG_BLTAPTH) -= 2;
+ }
+
+ /* fetch data for B */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
+ {
+ CUSTOM_REG(REG_BLTBDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTBPTH));
+ CUSTOM_REG_LONG(REG_BLTBPTH) -= 2;
+ }
+
+ /* fetch data for C */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
+ {
+ CUSTOM_REG(REG_BLTCDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTCPTH));
+ CUSTOM_REG_LONG(REG_BLTCPTH) -= 2;
+ }
+
+ /* apply start/end masks to the A data */
+ tempa = CUSTOM_REG(REG_BLTADAT);
+ if (x == 0)
+ tempa &= CUSTOM_REG(REG_BLTAFWM);
+ if (x == width - 1)
+ tempa &= CUSTOM_REG(REG_BLTALWM);
+
+ /* update the B accumulator applying shifts */
+ acca = (acca >> 16) | (tempa << shifta);
+ accb = (accb >> 16) | (CUSTOM_REG(REG_BLTBDAT) << shiftb);
+
+ /* build up 4 16-bit words containing 4 pixels each in 0ABC bit order */
+ abc0 = ((acca >> 1) & 0x4444) | ((accb >> 2) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 3) & 0x1111);
+ abc1 = ((acca >> 0) & 0x4444) | ((accb >> 1) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 2) & 0x1111);
+ abc2 = ((acca << 1) & 0x4444) | ((accb >> 0) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 1) & 0x1111);
+ abc3 = ((acca << 2) & 0x4444) | ((accb << 1) & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 0) & 0x1111);
+
+ /* now loop over bits and compute the destination value */
+ for (b = 0; b < 4; b++)
+ {
+ UINT32 prev_fill_state;
+ UINT32 bit;
+
+ /* shift previous data up 4 bits */
+ tempd >>= 4;
+
+ /* lookup fourth bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc3 & 0xf)) & 1;
+ abc3 >>= 4;
+ prev_fill_state = fill_state;
+ fill_state ^= bit;
+ bit ^= prev_fill_state & fill_exclusive;
+ bit |= prev_fill_state & fill_inclusive;
+ tempd |= bit << 12;
+
+ /* lookup third bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc2 & 0xf)) & 1;
+ abc2 >>= 4;
+ prev_fill_state = fill_state;
+ fill_state ^= bit;
+ bit ^= prev_fill_state & fill_exclusive;
+ bit |= prev_fill_state & fill_inclusive;
+ tempd |= bit << 13;
+
+ /* lookup second bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc1 & 0xf)) & 1;
+ abc1 >>= 4;
+ prev_fill_state = fill_state;
+ fill_state ^= bit;
+ bit ^= prev_fill_state & fill_exclusive;
+ bit |= prev_fill_state & fill_inclusive;
+ tempd |= bit << 14;
+
+ /* lookup first bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc0 & 0xf)) & 1;
+ abc0 >>= 4;
+ prev_fill_state = fill_state;
+ fill_state ^= bit;
+ bit ^= prev_fill_state & fill_exclusive;
+ bit |= prev_fill_state & fill_inclusive;
+ tempd |= bit << 15;
+ }
+
+ /* accumulate the sum */
+ blitsum |= tempd;
+
+ /* write to the destination */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
+ {
+ amiga_chip_ram_w(CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
+ CUSTOM_REG_LONG(REG_BLTDPTH) -= 2;
+ }
+ }
+
+ /* apply end of line modulos */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
+ CUSTOM_REG_LONG(REG_BLTAPTH) -= CUSTOM_REG_SIGNED(REG_BLTAMOD) & ~1;
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
+ CUSTOM_REG_LONG(REG_BLTBPTH) -= CUSTOM_REG_SIGNED(REG_BLTBMOD) & ~1;
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
+ CUSTOM_REG_LONG(REG_BLTCPTH) -= CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1;
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
+ CUSTOM_REG_LONG(REG_BLTDPTH) -= CUSTOM_REG_SIGNED(REG_BLTDMOD) & ~1;
+ }
+
+ /* return the blit sum */
+ return blitsum;
+}
+
+
+
+/*************************************
+ *
+ * Line drawing blitter variant
+ *
+ *************************************/
+
+/*
+ The exact line drawing algorithm is not known, but based on the cryptic
+ setup instructions, it is clear that it is a basic Bresenham line
+ algorithm. A standard Bresenham algorithm looks like this:
+
+ epsilon = 0;
+ while (length--)
+ {
+ plot(x, y);
+ x++;
+ epsilon += dy;
+ if ((2 * epsilon) >= dx)
+ {
+ y++;
+ epsilon -= dx;
+ }
+ }
+
+ If you multiply the epsilon term by 4 and shuffle the logic a bit, the
+ equivalent logic is:
+
+ epsilon = 4 * dy - 2 * dx;
+ while (length--)
+ {
+ plot(x, y);
+ x++;
+ if (epsilon >= 0)
+ {
+ y++;
+ epsilon += 4 * (dy - dx);
+ }
+ else
+ epsilon += 4 * dy;
+ }
+
+ With this refactoring, you can see that BLTAPT = epsilon,
+ BLTAMOD = 4 * (dy - dx) and BLTBMOD = 4 * dy.
+*/
+
+static UINT32 blit_line(void)
+{
+ UINT32 singlemode = (CUSTOM_REG(REG_BLTCON1) & 0x0002) ? 0x0000 : 0xffff;
+ UINT32 singlemask = 0xffff;
+ UINT32 blitsum = 0;
+ UINT32 height;
+
+ /* see if folks are breaking the rules */
+ if (CUSTOM_REG(REG_BLTSIZH) != 0x0002)
+ logerror("Blitter: Blit width != 2 in line mode!\n");
+ if ((CUSTOM_REG(REG_BLTCON0) & 0x0a00) != 0x0a00)
+ logerror("Blitter: Channel selection incorrect in line mode!\n" );
+
+ /* extract the length of the line */
+ height = CUSTOM_REG(REG_BLTSIZV);
+
+ /* iterate over the line height */
+ while (height--)
+ {
+ UINT16 abc0, abc1, abc2, abc3;
+ UINT32 tempa, tempb, tempd = 0;
+ int b, dx, dy;
+
+ /* fetch data for C */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
+ CUSTOM_REG(REG_BLTCDAT) = amiga_chip_ram_r(CUSTOM_REG_LONG(REG_BLTCPTH));
+
+ /* rotate the A data according to the shift */
+ tempa = CUSTOM_REG(REG_BLTADAT) >> (CUSTOM_REG(REG_BLTCON0) >> 12);
+
+ /* apply single bit mask */
+ tempa &= singlemask;
+ singlemask &= singlemode;
+
+ /* rotate the B data according to the shift and expand to 16 bits */
+ tempb = -((CUSTOM_REG(REG_BLTBDAT) >> (CUSTOM_REG(REG_BLTCON1) >> 12)) & 1);
+
+ /* build up 4 16-bit words containing 4 pixels each in 0ABC bit order */
+ abc0 = ((tempa >> 1) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 3) & 0x1111);
+ abc1 = ((tempa >> 0) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 2) & 0x1111);
+ abc2 = ((tempa << 1) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 1) & 0x1111);
+ abc3 = ((tempa << 2) & 0x4444) | (tempb & 0x2222) | ((CUSTOM_REG(REG_BLTCDAT) >> 0) & 0x1111);
+
+ /* now loop over bits and compute the destination value */
+ for (b = 0; b < 4; b++)
+ {
+ UINT32 bit;
+
+ /* shift previous data up 4 bits */
+ tempd <<= 4;
+
+ /* lookup first bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc0 >> 12)) & 1;
+ abc0 <<= 4;
+ tempd |= bit << 3;
+
+ /* lookup second bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc1 >> 12)) & 1;
+ abc1 <<= 4;
+ tempd |= bit << 2;
+
+ /* lookup third bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc2 >> 12)) & 1;
+ abc2 <<= 4;
+ tempd |= bit << 1;
+
+ /* lookup fourth bit in series */
+ bit = (CUSTOM_REG(REG_BLTCON0) >> (abc3 >> 12)) & 1;
+ abc3 <<= 4;
+ tempd |= bit << 0;
+ }
+
+ /* accumulate the sum */
+ blitsum |= tempd;
+
+ /* write to the destination */
+ amiga_chip_ram_w(CUSTOM_REG_LONG(REG_BLTDPTH), tempd);
+
+ /* always increment along the major axis */
+ if (CUSTOM_REG(REG_BLTCON1) & 0x0010)
+ {
+ dx = (CUSTOM_REG(REG_BLTCON1) & 0x0004) ? -1 : 1;
+ dy = 0;
+ }
+ else
+ {
+ dx = 0;
+ dy = (CUSTOM_REG(REG_BLTCON1) & 0x0004) ? -1 : 1;
+ }
+
+ /* is the sign bit clear? */
+ if (!(CUSTOM_REG(REG_BLTCON1) & 0x0040))
+ {
+ /* add 4 * (dy-dx) */
+ CUSTOM_REG_LONG(REG_BLTAPTH) += CUSTOM_REG_SIGNED(REG_BLTAMOD) & ~1;
+
+ /* increment along the minor axis */
+ if (CUSTOM_REG(REG_BLTCON1) & 0x0010)
+ dy = (CUSTOM_REG(REG_BLTCON1) & 0x0008) ? -1 : 1;
+ else
+ dx = (CUSTOM_REG(REG_BLTCON1) & 0x0008) ? -1 : 1;
+ }
+
+ /* else add 4 * dy and don't increment along the minor axis */
+ else
+ CUSTOM_REG_LONG(REG_BLTAPTH) += CUSTOM_REG_SIGNED(REG_BLTBMOD) & ~1;
+
+ /* adjust X if necessary */
+ if (dx)
+ {
+ /* adjust the A shift value */
+ UINT32 temp = CUSTOM_REG(REG_BLTCON0) + (INT32)(dx << 12);
+ CUSTOM_REG(REG_BLTCON0) = temp;
+
+ /* if we went from 0xf to 0x0 or vice-versa, adjust the actual pointers */
+ if (temp & 0x10000)
+ {
+ CUSTOM_REG_LONG(REG_BLTCPTH) += 2 * dx;
+ CUSTOM_REG_LONG(REG_BLTDPTH) += 2 * dx;
+ }
+ }
+
+ /* adjust Y if necessary */
+ if (dy)
+ {
+ /* BLTCMOD seems to be used for both C and D pointers */
+ CUSTOM_REG_LONG(REG_BLTCPTH) += dy * (INT16)(CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1);
+ CUSTOM_REG_LONG(REG_BLTDPTH) += dy * (INT16)(CUSTOM_REG_SIGNED(REG_BLTCMOD) & ~1);
+
+ /* reset the single mask since we're on a new line */
+ singlemask = 0xffff;
+ }
+
+ /* set the new sign bit value */
+ CUSTOM_REG(REG_BLTCON1) = (CUSTOM_REG(REG_BLTCON1) & ~0x0040) | ((CUSTOM_REG(REG_BLTAPTL) >> 9) & 0x0040);
+
+ /* increment texture shift on every pixel */
+ CUSTOM_REG(REG_BLTCON1) += 0x1000;
+ }
+
+ return blitsum;
+}
+
+
+
+/*************************************
+ *
+ * Blitter deferred callback
+ *
+ *************************************/
+
+static TIMER_CALLBACK( amiga_blitter_proc )
+{
+ UINT32 blitsum = 0;
+
+ /* logging */
+ if (LOG_BLITS)
+ {
+ static const char *type[] = { "ASCENDING", "LINE", "DESCENDING", "LINE" };
+ logerror("BLIT %s: %dx%d %04x %04x\n", type[CUSTOM_REG(REG_BLTCON1) & 0x0003], CUSTOM_REG(REG_BLTSIZH), CUSTOM_REG(REG_BLTSIZV), CUSTOM_REG(REG_BLTCON0), CUSTOM_REG(REG_BLTCON1));
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
+ logerror(" A: addr=%06X mod=%3d shift=%2d maskl=%04x maskr=%04x\n", CUSTOM_REG_LONG(REG_BLTAPTH), CUSTOM_REG_SIGNED(REG_BLTAMOD), CUSTOM_REG(REG_BLTCON0) >> 12, CUSTOM_REG(REG_BLTAFWM), CUSTOM_REG(REG_BLTALWM));
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
+ logerror(" B: addr=%06X mod=%3d shift=%2d\n", CUSTOM_REG_LONG(REG_BLTBPTH), CUSTOM_REG_SIGNED(REG_BLTBMOD), CUSTOM_REG(REG_BLTCON1) >> 12);
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0200)
+ logerror(" C: addr=%06X mod=%3d\n", CUSTOM_REG_LONG(REG_BLTCPTH), CUSTOM_REG_SIGNED(REG_BLTCMOD));
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0100)
+ logerror(" D: addr=%06X mod=%3d\n", CUSTOM_REG_LONG(REG_BLTDPTH), CUSTOM_REG_SIGNED(REG_BLTDMOD));
+ }
+
+ /* set the zero flag */
+ CUSTOM_REG(REG_DMACON) |= 0x2000;
+
+ /* switch off the type of blit */
+ switch (CUSTOM_REG(REG_BLTCON1) & 0x0003)
+ {
+ case 0: /* ascending */
+ blitsum = blit_ascending();
+ break;
+
+ case 2: /* descending */
+ blitsum = blit_descending();
+ break;
+
+ case 1: /* line */
+ case 3:
+ blitsum = blit_line();
+ break;
+ }
+
+ /* clear the zero flag if we actually wrote data */
+ if (blitsum)
+ CUSTOM_REG(REG_DMACON) &= ~0x2000;
+
+ /* no longer busy */
+ CUSTOM_REG(REG_DMACON) &= ~0x4000;
+
+ /* signal an interrupt */
+ amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_BLIT, 0);
+
+ /* reset the blitter timer */
+ timer_reset( amiga_blitter_timer, attotime_never);
+}
+
+
+
+/*************************************
+ *
+ * Blitter setup
+ *
+ *************************************/
+
+static void blitter_setup(void)
+{
+ int ticks, width, height, blittime;
+
+ /* is there another blitting in progress? */
+ if (CUSTOM_REG(REG_DMACON) & 0x4000)
+ {
+ logerror("PC: %08x - This program is playing tricks with the blitter\n", safe_activecpu_get_pc() );
+ return;
+ }
+
+ /* line mode is 8 ticks/pixel */
+ if (CUSTOM_REG(REG_BLTCON1) & 1)
+ ticks = 8;
+
+ /* standard mode is 4 ticks base */
+ else
+ {
+ ticks = 4;
+
+ /* plus 2 ticks if channel B is involved */
+ if (CUSTOM_REG(REG_BLTCON0) & 0x0400)
+ ticks += 2;
+
+ /* plus 2 ticks if both channel C and D are involved */
+ if ((CUSTOM_REG(REG_BLTCON0) & 0x0300) == 0x0300)
+ ticks += 2;
+ }
+
+ /* extract height/width */
+ width = CUSTOM_REG(REG_BLTSIZH);
+ height = CUSTOM_REG(REG_BLTSIZV);
+
+ /* compute the blit time */
+ blittime = ticks * height * width;
+
+ /* if 'blitter-nasty' is set, then the blitter takes over the bus. Make the blit semi-immediate */
+ if ( CUSTOM_REG(REG_DMACON) & 0x0400 )
+ {
+ /* simulate the 68k not running while the blit is going */
+ activecpu_adjust_icount( -(blittime/2) );
+
+ blittime = BLITTER_NASTY_DELAY;
+ }
+
+ /* AGA has twice the bus bandwidth, so blits take half the time */
+ if ( IS_AGA(amiga_intf) )
+ blittime /= 2;
+
+ /* signal blitter busy */
+ CUSTOM_REG(REG_DMACON) |= 0x4000;
+
+ /* set a timer */
+ timer_adjust( amiga_blitter_timer, ATTOTIME_IN_CYCLES( blittime, 0 ), 0, attotime_zero);
+}
+
+
+
+/*************************************
+ *
+ * 8520 CIA read handler
+ *
+ *************************************/
+
+READ16_HANDLER( amiga_cia_r )
+{
+ UINT8 data;
+ int shift, which;
+
+ /* offsets 0000-07ff reference CIA B, and are accessed via the MSB */
+ if ((offset & 0x0800) == 0)
+ {
+ which = 1;
+ shift = 8;
+ }
+
+ /* offsets 0800-0fff reference CIA A, and are accessed via the LSB */
+ else
+ {
+ which = 0;
+ shift = 0;
+ }
+
+ /* handle the reads */
+ data = cia_read(which, offset >> 7);
+
+#if LOG_CIA
+ logerror("%06x:cia_%c_read(%03x) = %04x & %04x\n", safe_activecpu_get_pc(), 'A' + ((~offset & 0x0800) >> 11), offset * 2, data << shift, mem_mask ^ 0xffff);
+#endif
+
+ return data << shift;
+}
+
+
+
+/*************************************
+ *
+ * 8520 CIA write handler
+ *
+ *************************************/
+
+WRITE16_HANDLER( amiga_cia_w )
+{
+ int which;
+
+#if LOG_CIA
+ logerror("%06x:cia_%c_write(%03x) = %04x & %04x\n", safe_activecpu_get_pc(), 'A' + ((~offset & 0x0800) >> 11), offset * 2, data, mem_mask ^ 0xffff);
+#endif
+
+ /* offsets 0000-07ff reference CIA B, and are accessed via the MSB */
+ if ((offset & 0x0800) == 0)
+ {
+ if (!ACCESSING_MSB)
+ return;
+ which = 1;
+ data >>= 8;
+ }
+
+ /* offsets 0800-0fff reference CIA A, and are accessed via the LSB */
+ else
+ {
+ if (!ACCESSING_LSB)
+ return;
+ which = 0;
+ data &= 0xff;
+ }
+
+ /* handle the writes */
+ cia_write(which, offset >> 7, (UINT8) data);
+}
+
+
+
+/*************************************
+ *
+ * CIA interrupt callbacks
+ *
+ *************************************/
+
+static void amiga_cia_0_irq(int state)
+{
+ amiga_custom_w(REG_INTREQ, (state ? 0x8000 : 0x0000) | INTENA_PORTS, 0);
+}
+
+
+static void amiga_cia_1_irq(int state)
+{
+ amiga_custom_w(REG_INTREQ, (state ? 0x8000 : 0x0000) | INTENA_EXTER, 0);
+}
+
+
+
+/*************************************
+ *
+ * Custom chip reset
+ *
+ *************************************/
+
+static void custom_reset(void)
+{
+ int clock = Machine->drv->cpu[0].clock;
+ UINT16 vidmode = (clock == AMIGA_68000_NTSC_CLOCK || clock == AMIGA_68EC020_NTSC_CLOCK ) ? 0x1000 : 0x0000; /* NTSC or PAL? */
+
+ CUSTOM_REG(REG_DDFSTRT) = 0x18;
+ CUSTOM_REG(REG_DDFSTOP) = 0xd8;
+ CUSTOM_REG(REG_INTENA) = 0x0000;
+ CUSTOM_REG(REG_VPOSR) = vidmode;
+ CUSTOM_REG(REG_SERDATR) = 0x3000;
+
+ switch (amiga_intf->chip_ram_mask)
+ {
+ case ANGUS_CHIP_RAM_MASK:
+ case FAT_ANGUS_CHIP_RAM_MASK:
+ CUSTOM_REG(REG_DENISEID) = 0x00FF;
+ break;
+
+ case ECS_CHIP_RAM_MASK:
+ CUSTOM_REG(REG_VPOSR) |= 0x2000;
+ CUSTOM_REG(REG_DENISEID) = 0x00FC;
+ if (IS_AGA(amiga_intf))
+ {
+ CUSTOM_REG(REG_VPOSR) |= 0x0300;
+ CUSTOM_REG(REG_DENISEID) = 0x00F8;
+ }
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Custom chip register read
+ *
+ *************************************/
+
+READ16_HANDLER( amiga_custom_r )
+{
+ UINT16 temp;
+
+ switch (offset & 0xff)
+ {
+ case REG_BLTDDAT:
+ return CUSTOM_REG(REG_BLTDDAT);
+
+ case REG_DMACONR:
+ return CUSTOM_REG(REG_DMACON);
+
+ case REG_VPOSR:
+ CUSTOM_REG(REG_VPOSR) &= 0xff00;
+ CUSTOM_REG(REG_VPOSR) |= amiga_gethvpos() >> 16;
+ return CUSTOM_REG(REG_VPOSR);
+
+ case REG_VHPOSR:
+ return amiga_gethvpos() & 0xffff;
+
+ case REG_SERDATR:
+ CUSTOM_REG(REG_SERDATR) &= ~0x4000;
+ CUSTOM_REG(REG_SERDATR) |= (CUSTOM_REG(REG_INTREQ) & INTENA_RBF) ? 0x4000 : 0x0000;
+ return CUSTOM_REG(REG_SERDATR);
+
+ case REG_JOY0DAT:
+ if (amiga_intf->joy0dat_r != NULL)
+ return (*amiga_intf->joy0dat_r)();
+ return readinputportbytag_safe("JOY0DAT", 0xffff);
+
+ case REG_JOY1DAT:
+ if (amiga_intf->joy1dat_r != NULL)
+ return (*amiga_intf->joy1dat_r)();
+ return readinputportbytag_safe("JOY1DAT", 0xffff);
+
+ case REG_ADKCONR:
+ return CUSTOM_REG(REG_ADKCON);
+
+ case REG_POTGOR:
+ return readinputportbytag_safe("POTGO", 0x5500);
+
+ case REG_POT0DAT:
+ return readinputportbytag_safe("POT0DAT", 0x0000);
+
+ case REG_POT1DAT:
+ return readinputportbytag_safe("POT1DAT", 0x0000);
+
+ case REG_DSKBYTR:
+ if (amiga_intf->dskbytr_r != NULL)
+ return (*amiga_intf->dskbytr_r)();
+ return 0x0000;
+
+ case REG_INTENAR:
+ return CUSTOM_REG(REG_INTENA);
+
+ case REG_INTREQR:
+ return CUSTOM_REG(REG_INTREQ);
+
+ case REG_COPJMP1:
+ copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
+ break;
+
+ case REG_COPJMP2:
+ copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
+ break;
+
+ case REG_CLXDAT:
+ temp = CUSTOM_REG(REG_CLXDAT);
+ CUSTOM_REG(REG_CLXDAT) = 0;
+ return temp;
+
+ case REG_DENISEID:
+ return CUSTOM_REG(REG_DENISEID);
+ break;
+ }
+
+#if LOG_CUSTOM
+ logerror("%06X:read from custom %s\n", safe_activecpu_get_pc(), amiga_custom_names[offset & 0xff]);
+#endif
+
+ return 0xffff;
+}
+
+
+
+/*************************************
+ *
+ * Custom chip register write
+ *
+ *************************************/
+
+static TIMER_CALLBACK( finish_serial_write )
+{
+ /* mark the transfer buffer empty */
+ CUSTOM_REG(REG_SERDATR) |= 0x3000;
+
+ /* signal an interrupt */
+ amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_TBE, 0);
+}
+
+
+WRITE16_HANDLER( amiga_custom_w )
+{
+ UINT16 temp;
+ offset &= 0xff;
+
+#if LOG_CUSTOM
+ logerror("%06X:write to custom %s = %04X\n", safe_activecpu_get_pc(), amiga_custom_names[offset & 0xff], data);
+#endif
+
+ switch (offset)
+ {
+ case REG_BLTDDAT: case REG_DMACONR: case REG_VPOSR: case REG_VHPOSR:
+ case REG_DSKDATR: case REG_JOY0DAT: case REG_JOY1DAT: case REG_CLXDAT:
+ case REG_ADKCONR: case REG_POT0DAT: case REG_POT1DAT: case REG_POTGOR:
+ case REG_SERDATR: case REG_DSKBYTR: case REG_INTENAR: case REG_INTREQR:
+ /* read-only registers */
+ break;
+
+ case REG_DSKLEN:
+ if (amiga_intf->dsklen_w != NULL)
+ (*amiga_intf->dsklen_w)(data);
+ break;
+
+ case REG_POTGO:
+ if (amiga_intf->potgo_w != NULL)
+ (*amiga_intf->potgo_w)(data);
+ break;
+
+ case REG_SERDAT:
+ if (amiga_intf->serdat_w != NULL)
+ (*amiga_intf->serdat_w)(data);
+ CUSTOM_REG(REG_SERDATR) &= ~0x3000;
+ timer_set(amiga_get_serial_char_period(), 0, finish_serial_write);
+ break;
+
+ case REG_BLTSIZE:
+ CUSTOM_REG(REG_BLTSIZE) = data;
+ CUSTOM_REG(REG_BLTSIZV) = (data >> 6) & 0x3ff;
+ CUSTOM_REG(REG_BLTSIZH) = data & 0x3f;
+ if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x400;
+ if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x40;
+ blitter_setup();
+ break;
+
+ case REG_BLTSIZV: /* ECS-AGA only */
+ if ( IS_ECS_OR_AGA(amiga_intf) )
+ {
+ CUSTOM_REG(REG_BLTSIZV) = data & 0x7fff;
+ if ( CUSTOM_REG(REG_BLTSIZV) == 0 ) CUSTOM_REG(REG_BLTSIZV) = 0x8000;
+ }
+ break;
+
+ case REG_BLTSIZH: /* ECS-AGA only */
+ if ( IS_ECS_OR_AGA(amiga_intf) )
+ {
+ CUSTOM_REG(REG_BLTSIZH) = data & 0x7ff;
+ if ( CUSTOM_REG(REG_BLTSIZH) == 0 ) CUSTOM_REG(REG_BLTSIZH) = 0x800;
+ blitter_setup();
+ }
+ break;
+
+ case REG_BLTCON0L: /* ECS-AGA only */
+ if ( IS_ECS_OR_AGA(amiga_intf) )
+ {
+ CUSTOM_REG(REG_BLTCON0) &= 0xff00;
+ CUSTOM_REG(REG_BLTCON0) |= data & 0xff;
+ }
+ break;
+
+ case REG_SPR0PTH: case REG_SPR1PTH: case REG_SPR2PTH: case REG_SPR3PTH:
+ case REG_SPR4PTH: case REG_SPR5PTH: case REG_SPR6PTH: case REG_SPR7PTH:
+ data &= ( amiga_intf->chip_ram_mask >> 16 );
+ break;
+
+ case REG_SPR0PTL: case REG_SPR1PTL: case REG_SPR2PTL: case REG_SPR3PTL:
+ case REG_SPR4PTL: case REG_SPR5PTL: case REG_SPR6PTL: case REG_SPR7PTL:
+ amiga_sprite_dma_reset((offset - REG_SPR0PTL) / 2);
+ break;
+
+ case REG_SPR0CTL: case REG_SPR1CTL: case REG_SPR2CTL: case REG_SPR3CTL:
+ case REG_SPR4CTL: case REG_SPR5CTL: case REG_SPR6CTL: case REG_SPR7CTL:
+ /* disable comparitor on writes here */
+ amiga_sprite_enable_comparitor((offset - REG_SPR0CTL) / 4, FALSE);
+ break;
+
+ case REG_SPR0DATA: case REG_SPR1DATA: case REG_SPR2DATA: case REG_SPR3DATA:
+ case REG_SPR4DATA: case REG_SPR5DATA: case REG_SPR6DATA: case REG_SPR7DATA:
+ /* enable comparitor on writes here */
+ amiga_sprite_enable_comparitor((offset - REG_SPR0DATA) / 4, TRUE);
+ break;
+
+ case REG_COP1LCH: case REG_COP2LCH:
+ data &= ( amiga_intf->chip_ram_mask >> 16 );
+ break;
+
+ case REG_COPJMP1:
+ copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
+ break;
+
+ case REG_COPJMP2:
+ copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
+ break;
+
+ case REG_DDFSTRT:
+ /* impose hardware limits ( HRM, page 75 ) */
+ data &= 0xfe;
+ if (data < 0x18)
+ data = 0x18;
+ break;
+
+ case REG_DDFSTOP:
+ /* impose hardware limits ( HRM, page 75 ) */
+ data &= 0xfe;
+ if (data > 0xd8)
+ data = 0xd8;
+ break;
+
+ case REG_DMACON:
+ amiga_audio_update();
+
+ /* bits BBUSY (14) and BZERO (13) are read-only */
+ data &= 0x9fff;
+ data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
+
+ /* if 'blitter-nasty' has been turned on and we have a blit pending, reschedule it */
+ if ( ( data & 0x400 ) && ( CUSTOM_REG(REG_DMACON) & 0x4000 ) )
+ timer_adjust( amiga_blitter_timer, ATTOTIME_IN_CYCLES( BLITTER_NASTY_DELAY, 0 ), 0, attotime_zero);
+
+ break;
+
+ case REG_INTENA:
+ temp = data;
+
+ data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
+ CUSTOM_REG(offset) = data;
+
+ if ( temp & 0x8000 ) /* if we're enabling irq's, delay a bit */
+ timer_adjust( amiga_irq_timer, ATTOTIME_IN_CYCLES( AMIGA_IRQ_DELAY_CYCLES, 0 ), 0, attotime_zero);
+ else /* if we're disabling irq's, process right away */
+ update_irqs();
+ break;
+
+ case REG_INTREQ:
+ temp = data;
+ /* Update serial data line status if appropiate */
+ if (!(data & 0x8000) && (data & INTENA_RBF))
+ CUSTOM_REG(REG_SERDATR) &= ~0x8000;
+
+ data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
+ if ( cia_get_irq( 0 ) ) data |= INTENA_PORTS;
+ if ( cia_get_irq( 1 ) ) data |= INTENA_EXTER;
+ CUSTOM_REG(offset) = data;
+
+ if ( temp & 0x8000 ) /* if we're generating irq's, delay a bit */
+ timer_adjust( amiga_irq_timer, ATTOTIME_IN_CYCLES( AMIGA_IRQ_DELAY_CYCLES, 0 ), 0, attotime_zero);
+ else /* if we're clearing irq's, process right away */
+ update_irqs();
+ break;
+
+ case REG_ADKCON:
+ amiga_audio_update();
+ data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
+ break;
+
+ case REG_AUD0LCL: case REG_AUD0LCH: case REG_AUD0LEN: case REG_AUD0PER: case REG_AUD0VOL:
+ case REG_AUD1LCL: case REG_AUD1LCH: case REG_AUD1LEN: case REG_AUD1PER: case REG_AUD1VOL:
+ case REG_AUD2LCL: case REG_AUD2LCH: case REG_AUD2LEN: case REG_AUD2PER: case REG_AUD2VOL:
+ case REG_AUD3LCL: case REG_AUD3LCH: case REG_AUD3LEN: case REG_AUD3PER: case REG_AUD3VOL:
+ amiga_audio_update();
+ break;
+
+ case REG_AUD0DAT: case REG_AUD1DAT: case REG_AUD2DAT: case REG_AUD3DAT:
+ amiga_audio_data_w((offset - REG_AUD0DAT) / 8, data);
+ break;
+
+ case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH:
+ case REG_BPL5PTH: case REG_BPL6PTH:
+ data &= ( amiga_intf->chip_ram_mask >> 16 );
+ break;
+
+ case REG_BPLCON0:
+ if ((data & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) == (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2))
+ {
+ /* planes go from 0 to 6, inclusive */
+ logerror( "This game is doing funky planes stuff. (planes > 6)\n" );
+ data &= ~BPLCON0_BPU0;
+ }
+ break;
+
+ case REG_COLOR00: case REG_COLOR01: case REG_COLOR02: case REG_COLOR03:
+ case REG_COLOR04: case REG_COLOR05: case REG_COLOR06: case REG_COLOR07:
+ case REG_COLOR08: case REG_COLOR09: case REG_COLOR10: case REG_COLOR11:
+ case REG_COLOR12: case REG_COLOR13: case REG_COLOR14: case REG_COLOR15:
+ case REG_COLOR16: case REG_COLOR17: case REG_COLOR18: case REG_COLOR19:
+ case REG_COLOR20: case REG_COLOR21: case REG_COLOR22: case REG_COLOR23:
+ case REG_COLOR24: case REG_COLOR25: case REG_COLOR26: case REG_COLOR27:
+ case REG_COLOR28: case REG_COLOR29: case REG_COLOR30: case REG_COLOR31:
+ data &= 0xfff;
+ CUSTOM_REG(offset + 32) = (data >> 1) & 0x777;
+ break;
+
+ default:
+ break;
+ }
+
+ if (offset <= REG_COLOR31)
+ CUSTOM_REG(offset) = data;
+}
+
+
+
+/*************************************
+ *
+ * Serial writes
+ *
+ *************************************/
+
+void amiga_serial_in_w(UINT16 data)
+{
+ int mask = (CUSTOM_REG(REG_SERPER) & 0x8000) ? 0x1ff : 0xff;
+
+ /* copy the data to the low 8 bits of SERDATR and set RBF */
+ CUSTOM_REG(REG_SERDATR) &= ~0x3ff;
+ CUSTOM_REG(REG_SERDATR) |= (data & mask) | (mask + 1) | 0x4000;
+
+ /* set overrun if we weren't cleared */
+ if (CUSTOM_REG(REG_INTREQ) & INTENA_RBF)
+ {
+ mame_printf_debug("Serial data overflow\n");
+ CUSTOM_REG(REG_SERDATR) |= 0x8000;
+ }
+
+ /* signal an interrupt */
+ amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_RBF, 0);
+}
+
+
+attotime amiga_get_serial_char_period(void)
+{
+ UINT32 divisor = (CUSTOM_REG(REG_SERPER) & 0x7fff) + 1;
+ UINT32 baud = Machine->drv->cpu[0].clock / 2 / divisor;
+ UINT32 numbits = 2 + ((CUSTOM_REG(REG_SERPER) & 0x8000) ? 9 : 8);
+ return attotime_mul(ATTOTIME_IN_HZ(baud), numbits);
+}
+
+
+
+/*************************************
+ *
+ * Autoconfig registration
+ *
+ *************************************/
+
+void amiga_add_autoconfig(amiga_autoconfig_device *device)
+{
+ autoconfig_device *dev, **d;
+
+ /* validate the data */
+ assert_always(mame_get_phase(Machine) == MAME_PHASE_INIT, "Can only call amiga_add_autoconfig at init time!");
+ assert_always((device->size & (device->size - 1)) == 0, "device->size must be power of 2!");
+
+ /* allocate memory and link it in at the end of the list */
+ dev = auto_malloc(sizeof(*dev));
+ dev->next = NULL;
+ for (d = &autoconfig_list; *d; d = &(*d)->next) ;
+ *d = dev;
+
+ /* fill in the data */
+ dev->device = *device;
+ dev->base = 0;
+}
+
+
+
+/*************************************
+ *
+ * Autoconfig reset
+ *
+ *************************************/
+
+static void autoconfig_reset(void)
+{
+ autoconfig_device *dev;
+
+ /* uninstall any installed devices */
+ for (dev = autoconfig_list; dev; dev = dev->next)
+ if (dev->base && dev->device.uninstall)
+ {
+ (*dev->device.uninstall)(dev->base);
+ dev->base = 0;
+ }
+
+ /* reset the current autoconfig */
+ cur_autoconfig = autoconfig_list;
+}
+
+
+
+/*************************************
+ *
+ * Autoconfig space read
+ *
+ *************************************/
+
+READ16_HANDLER( amiga_autoconfig_r )
+{
+ UINT8 byte;
+ int i;
+
+ /* if nothing present, just return */
+ if (!cur_autoconfig)
+ {
+ logerror("autoconfig_r(%02X) but no device selected\n", offset);
+ return 0;
+ }
+
+ /* switch off of the base offset */
+ switch (offset/2)
+ {
+ /*
+ 00/02 1 1 x x x 0 0 0 = 8 Megabytes
+ ^ ^ ^ 0 0 1 = 64 Kbytes
+ | | | 0 1 0 = 128 Kbytes
+ | | | 0 1 1 = 256 Kbytes
+ | | | 1 0 0 = 1 Megabyte
+ | | | 1 1 0 = 2 Megabytes
+ | | | 1 1 1 = 4 Megabytes
+ | | |
+ | | `-- 1 = multiple devices on this card
+ | `-------- 1 = ROM vector offset is valid
+ `----------- 1 = link into free memory list
+ */
+ case 0x00/4:
+ byte = 0xc0;
+ if (cur_autoconfig->device.link_memory)
+ byte |= 0x20;
+ if (cur_autoconfig->device.rom_vector_valid)
+ byte |= 0x10;
+ if (cur_autoconfig->device.multi_device)
+ byte |= 0x08;
+ for (i = 0; i < 8; i++)
+ if (cur_autoconfig->device.size & (1 << i))
+ break;
+ byte |= (i + 1) & 7;
+ break;
+
+ /*
+ 04/06 product number (all bits inverted)
+ */
+ case 0x04/4:
+ byte = ~cur_autoconfig->device.product_number;
+ break;
+
+ /*
+ 08/0a x x 1 1 1 1 1 1
+ ^ ^
+ | |
+ | `-- 1 = this board can be shut up
+ `----- 0 = prefer 8 Meg address space
+ */
+ case 0x08/4:
+ byte = 0x3f;
+ if (!cur_autoconfig->device.prefer_8meg)
+ byte |= 0x80;
+ if (cur_autoconfig->device.can_shutup)
+ byte |= 0x40;
+ break;
+
+ /*
+ 10/12 manufacturers number (high byte, all inverted)
+ 14/16 '' (low byte, all inverted)
+ */
+ case 0x10/4:
+ byte = ~cur_autoconfig->device.mfr_number >> 8;
+ break;
+
+ case 0x14/4:
+ byte = ~cur_autoconfig->device.mfr_number >> 0;
+ break;
+
+ /*
+ 18/1a optional serial number (all bits inverted) byte0
+ 1c/1e '' byte1
+ 20/22 '' byte2
+ 24/26 '' byte3
+ */
+ case 0x18/4:
+ byte = ~cur_autoconfig->device.serial_number >> 24;
+ break;
+
+ case 0x1c/4:
+ byte = ~cur_autoconfig->device.serial_number >> 16;
+ break;
+
+ case 0x20/4:
+ byte = ~cur_autoconfig->device.serial_number >> 8;
+ break;
+
+ case 0x24/4:
+ byte = ~cur_autoconfig->device.serial_number >> 0;
+ break;
+
+ /*
+ 28/2a optional ROM vector offset (all bits inverted) high byte
+ 2c/2e '' low byte
+ */
+ case 0x28/4:
+ byte = ~cur_autoconfig->device.rom_vector >> 8;
+ break;
+
+ case 0x2c/4:
+ byte = ~cur_autoconfig->device.rom_vector >> 0;
+ break;
+
+ /*
+ 40/42 optional interrupt control and status register
+ */
+ case 0x40/4:
+ byte = 0x00;
+ if (cur_autoconfig->device.int_control_r)
+ byte = (*cur_autoconfig->device.int_control_r)();
+ break;
+
+ default:
+ byte = 0xff;
+ break;
+ }
+
+ /* return the appropriate nibble */
+ logerror("autoconfig_r(%02X) = %04X\n", offset, (offset & 1) ? ((byte << 12) | 0xfff) : ((byte << 8) | 0xfff));
+ return (offset & 1) ? ((byte << 12) | 0xfff) : ((byte << 8) | 0xfff);
+}
+
+
+
+/*************************************
+ *
+ * Autoconfig space write
+ *
+ *************************************/
+
+WRITE16_HANDLER( amiga_autoconfig_w )
+{
+ int move_to_next = FALSE;
+
+ logerror("autoconfig_w(%02X) = %04X & %04X\n", offset, data, mem_mask ^ 0xffff);
+
+ /* if no current device, bail */
+ if (!cur_autoconfig || !ACCESSING_MSB)
+ return;
+
+ /* switch off of the base offset */
+ switch (offset/2)
+ {
+ /*
+ 48/4a write-only register for base address (A23-A16)
+ */
+ case 0x48/4:
+ if ((offset & 1) == 0)
+ cur_autoconfig->base = (cur_autoconfig->base & ~0xf00000) | ((data & 0xf000) << 8);
+ else
+ cur_autoconfig->base = (cur_autoconfig->base & ~0x0f0000) | ((data & 0xf000) << 4);
+ move_to_next = TRUE;
+ break;
+
+ /*
+ 4c/4e optional write-only 'shutup' trigger
+ */
+ case 0x4c/4:
+ cur_autoconfig->base = 0;
+ move_to_next = TRUE;
+ break;
+ }
+
+ /* install and move to the next device if requested */
+ if (move_to_next && (offset & 1) == 0)
+ {
+ logerror("Install to %06X\n", cur_autoconfig->base);
+ if (cur_autoconfig->base && cur_autoconfig->device.install)
+ (*cur_autoconfig->device.install)(cur_autoconfig->base);
+ cur_autoconfig = cur_autoconfig->next;
+ }
+}
diff --git a/src/mame/machine/arkanoid.c b/src/mame/machine/arkanoid.c
new file mode 100644
index 00000000000..1112886118c
--- /dev/null
+++ b/src/mame/machine/arkanoid.c
@@ -0,0 +1,597 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "arkanoid.h"
+
+
+/* To log specific reads and writes of the bootlegs */
+#define ARKANOID_BOOTLEG_VERBOSE 1
+
+
+UINT8 arkanoid_paddle_select;
+static UINT8 arkanoid_paddle_value;
+
+static UINT8 z80write,fromz80,m68705write,toz80;
+
+static UINT8 portA_in,portA_out,ddrA;
+static UINT8 portC_out,ddrC;
+
+
+MACHINE_START( arkanoid )
+{
+ state_save_register_global(arkanoid_paddle_select);
+ state_save_register_global(z80write);
+ state_save_register_global(fromz80);
+ state_save_register_global(m68705write);
+ state_save_register_global(toz80);
+
+ state_save_register_global(portA_in);
+ state_save_register_global(portA_out);
+ state_save_register_global(ddrA);
+
+ state_save_register_global(portC_out);
+ state_save_register_global(ddrC);
+}
+
+MACHINE_RESET( arkanoid )
+{
+ portA_in = portA_out = z80write = m68705write = 0;
+}
+
+READ8_HANDLER( arkanoid_Z80_mcu_r )
+{
+ /* return the last value the 68705 wrote, and mark that we've read it */
+ m68705write = 0;
+ return toz80;
+}
+
+static TIMER_CALLBACK( test )
+{
+ z80write = 1;
+ fromz80 = param;
+}
+
+WRITE8_HANDLER( arkanoid_Z80_mcu_w )
+{
+ timer_call_after_resynch(data, test);
+ /* boost the interleave for a few usecs to make sure it is read successfully */
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(10));
+}
+
+READ8_HANDLER( arkanoid_68705_portA_r )
+{
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( arkanoid_68705_portA_w )
+{
+ portA_out = data;
+}
+
+WRITE8_HANDLER( arkanoid_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+READ8_HANDLER( arkanoid_68705_portC_r )
+{
+ int res=0;
+
+ /* bit 0 is high on a write strobe; clear it once we've detected it */
+ if (z80write) res |= 0x01;
+
+ /* bit 1 is high if the previous write has been read */
+ if (!m68705write) res |= 0x02;
+
+ return (portC_out & ddrC) | (res & ~ddrC);
+}
+
+WRITE8_HANDLER( arkanoid_68705_portC_w )
+{
+ if ((ddrC & 0x04) && (~data & 0x04) && (portC_out & 0x04))
+ {
+ /* return the last value the Z80 wrote */
+ z80write = 0;
+ portA_in = fromz80;
+ }
+ if ((ddrC & 0x08) && (~data & 0x08) && (portC_out & 0x08))
+ {
+ /* a write from the 68705 to the Z80; remember its value */
+ m68705write = 1;
+ toz80 = portA_out;
+ }
+
+ portC_out = data;
+}
+
+WRITE8_HANDLER( arkanoid_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+
+
+READ8_HANDLER( arkanoid_68705_input_0_r )
+{
+ int res = input_port_0_r(offset) & 0x3f;
+
+ /* bit 0x40 comes from the sticky bit */
+ if (!z80write) res |= 0x40;
+
+ /* bit 0x80 comes from a write latch */
+ if (!m68705write) res |= 0x80;
+
+ return res;
+}
+
+READ8_HANDLER( arkanoid_input_2_r )
+{
+ if (arkanoid_paddle_select)
+ {
+ arkanoid_paddle_value = input_port_3_r(offset);
+ }
+ else
+ {
+ arkanoid_paddle_value = input_port_2_r(offset);
+ }
+
+ return arkanoid_paddle_value;
+}
+
+
+/*
+
+Bootlegs stuff
+
+The bootlegs simulate the missing MCU behaviour with writes to 0xd018 and reads value back from 0xf002.
+Fortunately, 'arkangc', 'arkbloc2' and 'arkblock' has patched code not to bother with that.
+So I've fixed 'arkbl3' and 'paddle2' to return the expected values (code is strongly similar).
+
+Some bootlegs also test some bits from 0xd008 after reading the paddle value at 0xd018.
+Their effect is completely unknown but I need to set some bits to 1 so the games are playable :
+
+ - 'arkangc' : NO read from 0xd008 !
+ - 'arkangc2' :
+ * bit 1 must be set to 1 or you enter sort of endless "demo mode" when you start :
+ . you can't select your starting level (it always starts at level 1)
+ . you can't control the paddle (it automoves by following the ball)
+ . you can use the "fire" button (the game never shoots)
+ . you are awarded points as in a normal game
+ . sounds are played
+ - 'arkblock' : NO read from 0xd008 !
+ - 'arkbloc2' :
+ * bit 5 must sometimes be set to 1 or you can't reach right side of the screen
+ nor select all levels at the begining of the game
+ - 'arkgcbl' :
+ * bit 1 must be set to 1 or you enter sort of endless "demo mode" when you start :
+ . you can't select your starting level (it always starts at level 1)
+ . you can't control the paddle (it automoves by following the ball)
+ . you can use the "fire" button (the game never shoots)
+ . you are awarded points as in a normal game
+ . sounds are played
+ * bit 5 must sometimes be set to 1 or you can't reach right side of the screen
+ nor select all levels at the begining of the game
+ - 'paddle2' :
+ * bits 0 and 1 must be set to 1 or the paddle goes up (joystick issue ?)
+ * bits 2 and 3 must be set to 1 or the paddle goes down (joystick issue ?)
+ * bit 5 must sometimes be set to 1 or you can't reach right side of the screen
+ nor select all levels at the begining of the game
+
+
+TO DO (2006.09.12) :
+
+ - understand reads from 0xd008 (even if the games are playable)
+ - try to document writes to 0xd018 with unknown effect
+
+*/
+
+
+#if ARKANOID_BOOTLEG_VERBOSE
+#define LOG_F002_R logerror("%04x: arkanoid_bootleg_f002_r - cmd = %02x - val = %02x\n",activecpu_get_pc(),arkanoid_bootleg_cmd,arkanoid_bootleg_val);
+#define LOG_D018_W logerror("%04x: arkanoid_bootleg_d018_w - data = %02x - cmd = %02x\n",activecpu_get_pc(),data,arkanoid_bootleg_cmd);
+#define LOG_D008_R logerror("%04x: arkanoid_bootleg_d008_r - val = %02x\n",activecpu_get_pc(),arkanoid_bootleg_d008_val);
+#else
+#define LOG_F002_R
+#define LOG_D018_W
+#define LOG_D008_R
+#endif
+
+
+static UINT8 arkanoid_bootleg_cmd;
+
+/* Kludge for some bootlegs that read this address */
+READ8_HANDLER( arkanoid_bootleg_f002_r )
+{
+ UINT8 arkanoid_bootleg_val = 0x00;
+
+ switch (arkanoid_bootleg_id)
+ {
+ case ARKANGC:
+ case ARKBLOCK:
+ switch (arkanoid_bootleg_cmd)
+ {
+ default:
+ break;
+ }
+ LOG_F002_R
+ break;
+ case ARKANGC2: /* There are no reads from 0xf002 in this bootleg */
+ switch (arkanoid_bootleg_cmd)
+ {
+ default:
+ break;
+ }
+ LOG_F002_R
+ break;
+ case ARKBLOC2:
+ switch (arkanoid_bootleg_cmd)
+ {
+ default:
+ break;
+ }
+ LOG_F002_R
+ break;
+ case ARKGCBL:
+ switch (arkanoid_bootleg_cmd)
+ {
+ case 0x8a: /* Current level (fixed routine) */
+ arkanoid_bootleg_val = 0xa5;
+ break;
+ case 0xff: /* Avoid "BAD HARDWARE " message (fixed routine) */
+ arkanoid_bootleg_val = 0xe2;
+ break;
+ default:
+ break;
+ }
+ LOG_F002_R
+ break;
+ case PADDLE2:
+ switch (arkanoid_bootleg_cmd)
+ {
+ case 0x24: /* Avoid bad jump to 0x0066 */
+ arkanoid_bootleg_val = 0x9b;
+ break;
+ case 0x36: /* Avoid "BAD HARDWARE " message */
+ arkanoid_bootleg_val = 0x2d;
+ break;
+ case 0x38: /* Start of levels table (fixed offset) */
+ arkanoid_bootleg_val = 0xf3;
+ break;
+ case 0x8a: /* Current level (fixed routine) */
+ arkanoid_bootleg_val = 0xa5;
+ break;
+ case 0xc3: /* Avoid bad jump to 0xf000 */
+ arkanoid_bootleg_val = 0x1d;
+ break;
+ case 0xe3: /* Number of bricks left (fixed offset) */
+ arkanoid_bootleg_val = 0x61;
+ break;
+ case 0xf7: /* Avoid "U69" message */
+ arkanoid_bootleg_val = 0x00;
+ break;
+ case 0xff: /* Avoid "BAD HARDWARE " message (fixed routine) */
+ arkanoid_bootleg_val = 0xe2;
+ break;
+ default:
+ break;
+ }
+ LOG_F002_R
+ break;
+ default:
+ logerror("%04x: arkanoid_bootleg_f002_r - cmd = %02x - unknown bootleg !\n",activecpu_get_pc(),arkanoid_bootleg_cmd);
+ break;
+ }
+
+ return arkanoid_bootleg_val;
+}
+
+/* Kludge for some bootlegs that write this address */
+WRITE8_HANDLER( arkanoid_bootleg_d018_w )
+{
+ arkanoid_bootleg_cmd = 0x00;
+
+ switch (arkanoid_bootleg_id)
+ {
+ case ARKANGC:
+ case ARKBLOCK:
+ switch (data)
+ {
+ case 0x36: /* unneeded value : no call 0x2050, unused A and overwritten HL (0x0313 -> 0x0340) */
+ if (activecpu_get_pc() == 0x7c47)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x38: /* unneeded value : no call 0x2050, unused A and fixed HL (0x7bd5) */
+ if (activecpu_get_pc() == 0x7b87)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x8a: /* unneeded value : no call 0x2050, unused A and overwritten HL (0x7b77 -> 0x7c1c) */
+ if (activecpu_get_pc() == 0x9661)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xe3: /* unneeded value : call 0x2050 but fixed A (0x00) and fixed HL (0xed83) */
+ if (activecpu_get_pc() == 0x67e3)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xf7: /* unneeded value : 3 * 'NOP' at 0x034f + 2 * 'NOP' at 0x35b */
+ if (activecpu_get_pc() == 0x0349)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xff: /* unneeded value : no call 0x2050, unused A and overwritten HL (0x7c4f -> 0x7d31) */
+ if (activecpu_get_pc() == 0x9670)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ default:
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ }
+ LOG_D018_W
+ break;
+ case ARKANGC2:
+ switch (data)
+ {
+ case 0x36: /* unneeded value : call 0x2050 but fixed A (0x2d) */
+ if (activecpu_get_pc() == 0x7c4c)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x38: /* unneeded value : call 0x2050 but fixed A (0xf3) */
+ if (activecpu_get_pc() == 0x7b87)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x88: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e3)
+ arkanoid_bootleg_cmd = 0x00;
+ if (activecpu_get_pc() == 0x7c47)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x89: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e5)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x8a: /* unneeded value : call 0x2050 but fixed A (0xa5) */
+ if (activecpu_get_pc() == 0x9661)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xc0: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e7)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xe3: /* unneeded value : call 0x2050 but fixed A (0x61) */
+ if (activecpu_get_pc() == 0x67e9)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xff: /* unneeded value : call 0x2050 but fixed A (0xe2) */
+ if (activecpu_get_pc() == 0x9670)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ default:
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ }
+ LOG_D018_W
+ break;
+ case ARKBLOC2:
+ switch (data)
+ {
+ case 0x36: /* unneeded value : call 0x2050 but fixed A (0x2d) */
+ if (activecpu_get_pc() == 0x7c4c)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x38: /* unneeded value : call 0x2050 but fixed A (0xf3) */
+ if (activecpu_get_pc() == 0x7b87)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x88: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e3)
+ arkanoid_bootleg_cmd = 0x00;
+ if (activecpu_get_pc() == 0x7c47)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x89: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e5)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x8a: /* unneeded value : call 0x2050 but unused HL and fixed DE (0x7c1c) */
+ if (activecpu_get_pc() == 0x9661)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xc0: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e7)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xe3: /* unneeded value : call 0x2050 but fixed A (0x61) */
+ if (activecpu_get_pc() == 0x67e9)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xf7: /* unneeded value : call 0x2050 but never called (check code at 0x0340) */
+ if (activecpu_get_pc() == 0x0349)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xff: /* unneeded value : no call 0x2050, unused A and fixed HL (0x7d31) */
+ if (activecpu_get_pc() == 0x9670)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ default:
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ }
+ LOG_D018_W
+ break;
+ case ARKGCBL:
+ switch (data)
+ {
+ case 0x36: /* unneeded value : call 0x2050 but fixed A (0x2d) */
+ if (activecpu_get_pc() == 0x7c4c)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x38: /* unneeded value : call 0x2050 but fixed A (0xf3) */
+ if (activecpu_get_pc() == 0x7b87)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x88: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e3)
+ arkanoid_bootleg_cmd = 0x00;
+ if (activecpu_get_pc() == 0x7c47)
+ arkanoid_bootleg_cmd = 0x00;
+ case 0x89: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e5)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x8a: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x9661)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0xc0: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e7)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xe3: /* unneeded value : call 0x2050 but fixed A (0x61) */
+ if (activecpu_get_pc() == 0x67e9)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xf7: /* unneeded value : 3 * 'NOP' at 0x034f + 'JR NZ,$035D' at 0x35b */
+ if (activecpu_get_pc() == 0x0349)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xff: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x9670)
+ arkanoid_bootleg_cmd = data;
+ break;
+ default:
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ }
+ LOG_D018_W
+ break;
+ case PADDLE2:
+ switch (data)
+ {
+ case 0x24: /* A read from 0xf002 (expected to be 0x9b) */
+ if (activecpu_get_pc() == 0xbd7a)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0x36: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x7c4c)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0x38: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x7b87)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0x88: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e3)
+ arkanoid_bootleg_cmd = 0x00;
+ if (activecpu_get_pc() == 0x7c47)
+ arkanoid_bootleg_cmd = 0x00;
+ case 0x89: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e5)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0x8a: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x9661)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0xc0: /* unneeded value : no read back */
+ if (activecpu_get_pc() == 0x67e7)
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ case 0xc3: /* A read from 0xf002 (expected to be 0x1d) */
+ if (activecpu_get_pc() == 0xbd8a)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0xe3: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x67e9)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0xf7: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x0349)
+ arkanoid_bootleg_cmd = data;
+ break;
+ case 0xff: /* call 0x2050 with A read from 0xf002 and wrong HL */
+ if (activecpu_get_pc() == 0x9670)
+ arkanoid_bootleg_cmd = data;
+ break;
+ default:
+ arkanoid_bootleg_cmd = 0x00;
+ break;
+ }
+ LOG_D018_W
+ break;
+ default:
+ logerror("%04x: arkanoid_bootleg_d018_w - data = %02x - unknown bootleg !\n",activecpu_get_pc(),data);
+ break;
+ }
+}
+
+/* Kludge for some bootlegs that read this address */
+READ8_HANDLER( arkanoid_bootleg_d008_r )
+{
+ UINT8 arkanoid_bootleg_d008_bit[8];
+ UINT8 arkanoid_bootleg_d008_val;
+ int b;
+
+ arkanoid_bootleg_d008_bit[4] = arkanoid_bootleg_d008_bit[6] = arkanoid_bootleg_d008_bit[7] = 0; /* untested bits */
+
+ switch (arkanoid_bootleg_id)
+ {
+ case ARKANGC:
+ case ARKBLOCK:
+ arkanoid_bootleg_d008_bit[0] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[1] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[2] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[3] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[5] = 0; /* untested bit */
+ break;
+ case ARKANGC2:
+ arkanoid_bootleg_d008_bit[0] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[1] = 1; /* check code at 0x0cad */
+ arkanoid_bootleg_d008_bit[2] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[3] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[5] = 0; /* untested bit */
+ break;
+ case ARKBLOC2:
+ arkanoid_bootleg_d008_bit[0] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[1] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[2] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[3] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[5] = (arkanoid_paddle_value < 0x40); /* check code at 0x96b0 */
+ break;
+ case ARKGCBL:
+ arkanoid_bootleg_d008_bit[0] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[1] = 1; /* check code at 0x0cad */
+ arkanoid_bootleg_d008_bit[2] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[3] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[5] = (arkanoid_paddle_value < 0x40); /* check code at 0x96b0 */
+ break;
+ case PADDLE2:
+ arkanoid_bootleg_d008_bit[0] = 1; /* check code at 0x7d65 */
+ arkanoid_bootleg_d008_bit[1] = 1; /* check code at 0x7d65 */
+ arkanoid_bootleg_d008_bit[2] = 1; /* check code at 0x7d65 */
+ arkanoid_bootleg_d008_bit[3] = 1; /* check code at 0x7d65 */
+ arkanoid_bootleg_d008_bit[5] = (arkanoid_paddle_value < 0x40); /* check code at 0x96b0 */
+ break;
+ default:
+ arkanoid_bootleg_d008_bit[0] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[1] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[2] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[3] = 0; /* untested bit */
+ arkanoid_bootleg_d008_bit[5] = 0; /* untested bit */
+ logerror("%04x: arkanoid_bootleg_d008_r - unknown bootleg !\n",activecpu_get_pc());
+ break;
+ }
+
+ arkanoid_bootleg_d008_val = 0;
+ for (b=0; b<8; b++)
+ arkanoid_bootleg_d008_val |= (arkanoid_bootleg_d008_bit[b] << b);
+ LOG_D008_R
+
+ return arkanoid_bootleg_d008_val;
+}
+
diff --git a/src/mame/machine/asic65.c b/src/mame/machine/asic65.c
new file mode 100644
index 00000000000..a6f464ef29a
--- /dev/null
+++ b/src/mame/machine/asic65.c
@@ -0,0 +1,750 @@
+/*************************************
+ *
+ * Implementation of ASIC65
+ *
+ *************************************/
+
+#include "driver.h"
+#include "includes/atarig42.h"
+#include "cpu/tms32010/tms32010.h"
+#include "asic65.h"
+#include <math.h>
+
+
+#define LOG_ASIC 0
+
+
+/*************************************
+ *
+ * !$#@$ asic
+ *
+ *************************************/
+
+static UINT8 asic65_type;
+static int asic65_command;
+static UINT16 asic65_param[32];
+static UINT16 asic65_yorigin = 0x1800;
+static UINT8 asic65_param_index;
+static UINT8 asic65_result_index;
+static UINT8 asic65_reset_state;
+static UINT8 asic65_last_bank;
+
+/* ROM-based interface states */
+static UINT8 asic65_cpunum;
+static UINT8 asic65_tfull;
+static UINT8 asic65_68full;
+static UINT8 asic65_cmd;
+static UINT8 asic65_xflg;
+static UINT16 asic65_68data;
+static UINT16 asic65_tdata;
+
+static FILE * asic65_log;
+
+WRITE16_HANDLER( asic65_w );
+WRITE16_HANDLER( asic65_data_w );
+
+READ16_HANDLER( asic65_r );
+READ16_HANDLER( asic65_io_r );
+
+
+#define PARAM_WRITE 0
+#define COMMAND_WRITE 1
+#define DATA_READ 2
+
+#define OP_UNKNOWN 0
+#define OP_REFLECT 1
+#define OP_CHECKSUM 2
+#define OP_VERSION 3
+#define OP_RAMTEST 4
+#define OP_RESET 5
+#define OP_SIN 6
+#define OP_COS 7
+#define OP_ATAN 8
+#define OP_TMATRIXMULT 9
+#define OP_MATRIXMULT 10
+#define OP_TRANSFORM 11
+#define OP_YORIGIN 12
+#define OP_INITBANKS 13
+#define OP_SETBANK 14
+#define OP_VERIFYBANK 15
+
+#define MAX_COMMANDS 0x2b
+
+static const UINT8 command_map[3][MAX_COMMANDS] =
+{
+ {
+ /* standard version */
+ OP_UNKNOWN, OP_REFLECT, OP_CHECKSUM, OP_VERSION, /* 00-03 */
+ OP_RAMTEST, OP_UNKNOWN, OP_UNKNOWN, OP_RESET, /* 04-07 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 08-0b */
+ OP_UNKNOWN, OP_UNKNOWN, OP_TMATRIXMULT, OP_UNKNOWN, /* 0c-0f */
+ OP_MATRIXMULT, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 10-13 */
+ OP_SIN, OP_COS, OP_YORIGIN, OP_TRANSFORM, /* 14-17 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 18-1b */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 1c-1f */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 20-23 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 24-27 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN /* 28-2a */
+ },
+ {
+ /* Steel Talons version */
+ OP_UNKNOWN, OP_REFLECT, OP_CHECKSUM, OP_VERSION, /* 00-03 */
+ OP_RAMTEST, OP_UNKNOWN, OP_UNKNOWN, OP_RESET, /* 04-07 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 08-0b */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 0c-0f */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 10-13 */
+ OP_TMATRIXMULT, OP_UNKNOWN, OP_MATRIXMULT, OP_UNKNOWN, /* 14-17 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 18-1b */
+ OP_UNKNOWN, OP_UNKNOWN, OP_SIN, OP_COS, /* 1c-1f */
+ OP_ATAN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 20-23 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 24-27 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN /* 28-2a */
+ },
+ {
+ /* Guardians version */
+ OP_UNKNOWN, OP_REFLECT, OP_CHECKSUM, OP_VERSION, /* 00-03 */
+ OP_RAMTEST, OP_UNKNOWN, OP_UNKNOWN, OP_RESET, /* 04-07 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 08-0b */
+ OP_UNKNOWN, OP_UNKNOWN, OP_INITBANKS, OP_SETBANK, /* 0c-0f */
+ OP_VERIFYBANK, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 10-13 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 14-17 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 18-1b */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 1c-1f */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 20-23 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN, /* 24-27 */
+ OP_UNKNOWN, OP_UNKNOWN, OP_UNKNOWN /* 28-2a */
+ }
+};
+
+
+
+/*************************************
+ *
+ * Configure the chip
+ *
+ *************************************/
+
+void asic65_config(int asictype)
+{
+ asic65_type = asictype;
+ if (asic65_type == ASIC65_ROMBASED)
+ asic65_cpunum = mame_find_cpu_index(Machine, "asic65");
+}
+
+
+
+/*************************************
+ *
+ * Reset the chip
+ *
+ *************************************/
+
+void asic65_reset(int state)
+{
+ /* rom-based means reset and clear states */
+ if (asic65_type == ASIC65_ROMBASED)
+ cpunum_set_input_line(asic65_cpunum, INPUT_LINE_RESET, state ? ASSERT_LINE : CLEAR_LINE);
+
+ /* otherwise, do it manually */
+ else
+ {
+ cpunum_suspend(mame_find_cpu_index(Machine, "asic65"), SUSPEND_REASON_DISABLE, 1);
+
+ /* if reset is being signalled, clear everything */
+ if (state && !asic65_reset_state)
+ asic65_command = -1;
+
+ /* if reset is going high, latch the command */
+ else if (!state && asic65_reset_state)
+ {
+ if (asic65_command != -1)
+ asic65_data_w(1, asic65_command, 0);
+ }
+
+ /* update the state */
+ asic65_reset_state = state;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Handle writes to the chip
+ *
+ *************************************/
+
+static TIMER_CALLBACK( m68k_asic65_deferred_w )
+{
+ asic65_tfull = 1;
+ asic65_cmd = param >> 16;
+ asic65_tdata = param;
+ cpunum_set_input_line(asic65_cpunum, 0, ASSERT_LINE);
+}
+
+
+WRITE16_HANDLER( asic65_data_w )
+{
+ /* logging */
+#if LOG_ASIC
+ if (!asic65_log) asic65_log = fopen("asic65.log", "w");
+#endif
+
+ /* rom-based use a deferred write mechanism */
+ if (asic65_type == ASIC65_ROMBASED)
+ {
+ timer_call_after_resynch(data | (offset << 16), m68k_asic65_deferred_w);
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(20));
+ return;
+ }
+
+ /* parameters go to offset 0 */
+ if (!(offset & 1))
+ {
+ if (asic65_log) fprintf(asic65_log, " W=%04X", data);
+
+ /* add to the parameter list, but don't overflow */
+ asic65_param[asic65_param_index++] = data;
+ if (asic65_param_index >= 32)
+ asic65_param_index = 32;
+ }
+
+ /* commands go to offset 2 */
+ else
+ {
+ int command = (data < MAX_COMMANDS) ? command_map[asic65_type][data] : OP_UNKNOWN;
+ if (asic65_log) fprintf(asic65_log, "\n(%06X)%c%04X:", activecpu_get_previouspc(), (command == OP_UNKNOWN) ? '*' : ' ', data);
+
+ /* set the command number and reset the parameter/result indices */
+ asic65_command = data;
+ asic65_result_index = asic65_param_index = 0;
+ }
+}
+
+
+READ16_HANDLER( asic65_r )
+{
+ int command = (asic65_command < MAX_COMMANDS) ? command_map[asic65_type][asic65_command] : OP_UNKNOWN;
+ INT64 element, result64 = 0;
+ UINT16 result = 0;
+
+ /* rom-based just returns latched data */
+ if (asic65_type == ASIC65_ROMBASED)
+ {
+ asic65_68full = 0;
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(5));
+ return asic65_68data;
+ }
+
+ /* update results */
+ switch (command)
+ {
+ case OP_UNKNOWN: /* return bogus data */
+ popmessage("ASIC65: Unknown cmd %02X", asic65_command);
+ break;
+
+ case OP_REFLECT: /* reflect data */
+ if (asic65_param_index >= 1)
+ result = asic65_param[--asic65_param_index];
+ break;
+
+ case OP_CHECKSUM: /* compute checksum (should be XX27) */
+ result = 0x0027;
+ break;
+
+ case OP_VERSION: /* get version (returns 1.3) */
+ result = 0x0013;
+ break;
+
+ case OP_RAMTEST: /* internal RAM test (result should be 0) */
+ result = 0;
+ break;
+
+ case OP_RESET: /* reset */
+ asic65_result_index = asic65_param_index = 0;
+ break;
+
+ case OP_SIN: /* sin */
+ if (asic65_param_index >= 1)
+ result = (int)(16384. * sin(M_PI * (double)(INT16)asic65_param[0] / 32768.));
+ break;
+
+ case OP_COS: /* cos */
+ if (asic65_param_index >= 1)
+ result = (int)(16384. * cos(M_PI * (double)(INT16)asic65_param[0] / 32768.));
+ break;
+
+ case OP_ATAN: /* vector angle */
+ if (asic65_param_index >= 4)
+ {
+ INT32 xint = (INT32)((asic65_param[0] << 16) | asic65_param[1]);
+ INT32 yint = (INT32)((asic65_param[2] << 16) | asic65_param[3]);
+ double a = atan2((double)yint, (double)xint);
+ result = (INT16)(a * 32768. / M_PI);
+ }
+ break;
+
+ case OP_TMATRIXMULT: /* matrix multiply by transpose */
+ /* if this is wrong, the labels on the car selection screen */
+ /* in Race Drivin' will be off */
+ if (asic65_param_index >= 9+6)
+ {
+ INT32 v0 = (INT32)((asic65_param[9] << 16) | asic65_param[10]);
+ INT32 v1 = (INT32)((asic65_param[11] << 16) | asic65_param[12]);
+ INT32 v2 = (INT32)((asic65_param[13] << 16) | asic65_param[14]);
+
+ /* 2 results per element */
+ switch (asic65_result_index / 2)
+ {
+ case 0:
+ result64 = (INT64)v0 * (INT16)asic65_param[0] +
+ (INT64)v1 * (INT16)asic65_param[3] +
+ (INT64)v2 * (INT16)asic65_param[6];
+ break;
+
+ case 1:
+ result64 = (INT64)v0 * (INT16)asic65_param[1] +
+ (INT64)v1 * (INT16)asic65_param[4] +
+ (INT64)v2 * (INT16)asic65_param[7];
+ break;
+
+ case 2:
+ result64 = (INT64)v0 * (INT16)asic65_param[2] +
+ (INT64)v1 * (INT16)asic65_param[5] +
+ (INT64)v2 * (INT16)asic65_param[8];
+ break;
+ }
+
+ /* remove lower 14 bits and pass back either upper or lower words */
+ result64 >>= 14;
+ result = (asic65_result_index & 1) ? (result64 & 0xffff) : ((result64 >> 16) & 0xffff);
+ asic65_result_index++;
+ }
+ break;
+
+ case OP_MATRIXMULT: /* matrix multiply???? */
+ if (asic65_param_index >= 9+6)
+ {
+ INT32 v0 = (INT32)((asic65_param[9] << 16) | asic65_param[10]);
+ INT32 v1 = (INT32)((asic65_param[11] << 16) | asic65_param[12]);
+ INT32 v2 = (INT32)((asic65_param[13] << 16) | asic65_param[14]);
+
+ /* 2 results per element */
+ switch (asic65_result_index / 2)
+ {
+ case 0:
+ result64 = (INT64)v0 * (INT16)asic65_param[0] +
+ (INT64)v1 * (INT16)asic65_param[1] +
+ (INT64)v2 * (INT16)asic65_param[2];
+ break;
+
+ case 1:
+ result64 = (INT64)v0 * (INT16)asic65_param[3] +
+ (INT64)v1 * (INT16)asic65_param[4] +
+ (INT64)v2 * (INT16)asic65_param[5];
+ break;
+
+ case 2:
+ result64 = (INT64)v0 * (INT16)asic65_param[6] +
+ (INT64)v1 * (INT16)asic65_param[7] +
+ (INT64)v2 * (INT16)asic65_param[8];
+ break;
+ }
+
+ /* remove lower 14 bits and pass back either upper or lower words */
+ result64 >>= 14;
+ result = (asic65_result_index & 1) ? (result64 & 0xffff) : ((result64 >> 16) & 0xffff);
+ asic65_result_index++;
+ }
+ break;
+
+ case OP_YORIGIN:
+ if (asic65_param_index >= 1)
+ asic65_yorigin = asic65_param[asic65_param_index - 1];
+ break;
+
+ case OP_TRANSFORM: /* 3d transform */
+ if (asic65_param_index >= 2)
+ {
+ /* param 0 == 1/z */
+ /* param 1 == height */
+ /* param 2 == X */
+ /* param 3 == Y */
+ /* return 0 == scale factor for 1/z */
+ /* return 1 == transformed X */
+ /* return 2 == transformed Y, taking height into account */
+ element = (INT16)asic65_param[0];
+ if (asic65_param_index == 2)
+ {
+ result64 = (element * (INT16)asic65_param[1]) >> 8;
+ result64 -= 1;
+ if (result64 > 0x3fff) result64 = 0;
+ }
+ else if (asic65_param_index == 3)
+ {
+ result64 = (element * (INT16)asic65_param[2]) >> 15;
+ result64 += 0xa8;
+ }
+ else if (asic65_param_index == 4)
+ {
+ result64 = (INT16)((element * (INT16)asic65_param[3]) >> 10);
+ result64 = (INT16)asic65_yorigin - result64 - (result64 << 1);
+ }
+ result = result64 & 0xffff;
+ }
+ break;
+
+ case OP_INITBANKS: /* initialize banking */
+ asic65_last_bank = 0;
+ break;
+
+ case OP_SETBANK: /* set a bank */
+ {
+ static const UINT8 banklist[] =
+ {
+ 1,4,0,4,4,3,4,2, 4,4,4,4,4,4,4,4,
+ 3,3,4,4,1,1,0,0, 4,4,4,4,2,2,4,4,
+ 4,4
+ };
+ static const UINT16 bankaddr[][8] =
+ {
+ { 0x77c0,0x77ce,0x77c2,0x77cc,0x77c4,0x77ca,0x77c6,0x77c8 },
+ { 0x77d0,0x77de,0x77d2,0x77dc,0x77d4,0x77da,0x77d6,0x77d8 },
+ { 0x77e0,0x77ee,0x77e2,0x77ec,0x77e4,0x77ea,0x77e6,0x77e8 },
+ { 0x77f0,0x77fe,0x77f2,0x77fc,0x77f4,0x77fa,0x77f6,0x77f8 },
+ { 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 },
+ };
+ if (asic65_param_index >= 1)
+ {
+ if (asic65_param_index < sizeof(banklist) && banklist[asic65_param[0]] < 4)
+ asic65_last_bank = banklist[asic65_param[0]];
+ result = bankaddr[asic65_last_bank][(asic65_result_index < 8) ? asic65_result_index : 7];
+ asic65_result_index++;
+ }
+ break;
+ }
+
+ case OP_VERIFYBANK: /* verify a bank */
+ {
+ static const UINT16 bankverify[] =
+ {
+ 0x0eb2,0x1000,0x171b,0x3d28
+ };
+ result = bankverify[asic65_last_bank];
+ break;
+ }
+ }
+
+#if LOG_ASIC
+ if (!asic65_log) asic65_log = fopen("asic65.log", "w");
+#endif
+ if (asic65_log) fprintf(asic65_log, " (R=%04X)", result);
+
+ return result;
+}
+
+
+READ16_HANDLER( asic65_io_r )
+{
+ if (asic65_type == ASIC65_ROMBASED)
+ {
+ /* bit 15 = TFULL */
+ /* bit 14 = 68FULL */
+ /* bit 13 = XFLG */
+ /* bit 12 = controlled by jumper */
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(5));
+ return (asic65_tfull << 15) | (asic65_68full << 14) | (asic65_xflg << 13) | 0x0000;
+ }
+ else
+ {
+ /* indicate that we always are ready to accept data and always ready to send */
+ return 0x4000;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Read/write handlers for TMS32015
+ *
+ *************************************/
+
+static WRITE16_HANDLER( asic65_68k_w )
+{
+ asic65_68full = 1;
+ asic65_68data = data;
+}
+
+
+static READ16_HANDLER( asic65_68k_r )
+{
+ asic65_tfull = 0;
+ cpunum_set_input_line(asic65_cpunum, 0, CLEAR_LINE);
+ return asic65_tdata;
+}
+
+
+static WRITE16_HANDLER( asic65_stat_w )
+{
+ asic65_xflg = data & 1;
+}
+
+
+static READ16_HANDLER( asic65_stat_r )
+{
+ /* bit 15 = 68FULL */
+ /* bit 14 = TFULL */
+ /* bit 13 = CMD */
+ /* bit 12 = controlled by jumper (0 = test?) */
+ return (asic65_68full << 15) | (asic65_tfull << 14) | (asic65_cmd << 13) | 0x1000;
+}
+
+
+static READ16_HANDLER( asci65_get_bio )
+{
+ if (!asic65_tfull)
+ cpu_spinuntil_int();
+ return asic65_tfull ? CLEAR_LINE : ASSERT_LINE;
+}
+
+
+
+/*************************************
+ *
+ * Address maps for TMS32015
+ *
+ *************************************/
+
+static ADDRESS_MAP_START( asic65_program_map, ADDRESS_SPACE_PROGRAM, 16 )
+ ADDRESS_MAP_FLAGS( AMEF_UNMAP(1) )
+ AM_RANGE(0x000, 0xfff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( asic65_io_map, ADDRESS_SPACE_IO, 16 )
+ AM_RANGE(0, 0) AM_MIRROR(6) AM_READWRITE(asic65_68k_r, asic65_68k_w)
+ AM_RANGE(1, 1) AM_MIRROR(6) AM_READWRITE(asic65_stat_r, asic65_stat_w)
+ AM_RANGE(TMS32010_BIO, TMS32010_BIO) AM_READ(asci65_get_bio)
+ADDRESS_MAP_END
+
+
+
+/*************************************
+ *
+ * Machine driver for ROM-based
+ *
+ *************************************/
+
+MACHINE_DRIVER_START( asic65 )
+
+ /* ASIC65 */
+ MDRV_CPU_ADD_TAG("asic65", TMS32010, 20000000/TMS32010_CLOCK_DIVIDER)
+ MDRV_CPU_PROGRAM_MAP(asic65_program_map,0)
+ MDRV_CPU_IO_MAP(asic65_io_map,0)
+MACHINE_DRIVER_END
+
+
+
+/***********************************************************************
+
+ Information about various versions:
+
+ Notation:
+ C = command write
+ W = write
+ R = read
+ 7 = wait for bit 7
+ 6 = wait for bit 6
+
+ Guardians of the Hood:
+ Version = 0040
+ Checksum = ????
+
+ Command $08: C7
+ Command $09: C7W6R
+ Command $0a: C7
+ Command $0b: C7W7W7W7W7WW7W7W7W
+ Command $0c: C7W7W7W7W7W7W
+ Command $0d: C7W7W
+ Command $0e: C7W7W7W7W7WW7W7W7WWWWWWW6R6R6R6R6R6R
+ Command $0f: C7W7W7W7W7W7W6R6R6R6R6R6R
+ Command $10: C7W7W7W7W7WW7W7W7WWWWWWW6R6R6R6R6R6R
+ Command $11: C7W7W7W7W7W7W6R6R6R6R6R6R
+ Command $12: C7W7W7W7W7WW7W7W7W6R6R6R6R6R6R6R6R6R
+ Command $13: C7W7W7W7W7WW7W7W7W
+ Command $14: C7W6R
+ Command $15: C7W6R
+ Command $16: C7W6R6R
+ Command $17: C7W
+ Command $18: C76R6R6R6R6R6R6R6R6R
+ Command $19: C7
+ Command $1a: C76R6R6R6R6R6R6R6R6R
+ Command $1b: C7
+ Command $1c: C76R6R6R6R6R6R6R6R6R
+ Command $1d: C7
+ Command $1e: C76R6R6R6R6R6R6R6R6R
+ Command $1f: C7
+ Command $20: C76R6R6R6R6R6R6R6R6R
+ Command $21: C7
+ Command $22: C76R6R6R6R6R6R6R6R6R
+ Command $23: C7
+ Command $24: C7
+
+ Command $0e: C76RRRRRRRRR
+ Command $0f: C7W6RRRRRRRR
+ Command $16: C7W
+ Command $17: C7W7W7W7W6R6R6R
+
+ Road Riot 4WD:
+ Version = ????
+ Checksum = ????
+
+ Command $08: C7
+ Command $09: C7W6R
+ Command $0a: C7
+ Command $0b: C7W7WWWWWWWW
+ Command $0c: C7W7WWWWW
+ Command $0d: C7W7W
+ Command $0e: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $0f: C7W7WWWWW6RRRRRR
+ Command $10: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $11: C7W7WWWWW6RRRRRR
+ Command $12: C7W7WWWWWWWW6RRRRRRRRR
+ Command $13: C7W7WWWWWWWW
+ Command $14: C7W6R
+ Command $15: C7W6R
+ Command $16: C7W6RR
+ Command $17: C7W
+ Command $18: C76RRRRRRRRR
+ Command $19: C7
+ Command $1a: C76RRRRRRRRR
+ Command $1b: C7
+ Command $1c: C76RRRRRRRRR
+ Command $1d: C7
+ Command $1e: C76RRRRRRRRR
+ Command $1f: C7
+ Command $20: C76RRRRRRRRR
+ Command $21: C7
+ Command $22: C76RRRRRRRRR
+ Command $23: C7
+ Command $24: C7
+
+ Command $16: C7W
+ Command $17: C7W7WWW6RRR
+ Command $17: C7WRWRWR
+
+ Race Drivin':
+ Version = ????
+ Checksum = ????
+
+ Command $08: C7
+ Command $09: C7W6R
+ Command $0a: C7
+ Command $0b: C7W7WWWWWWWW
+ Command $0c: C7W7WWWWW
+ Command $0d: C7W7W
+ Command $0e: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $0f: C7W7WWWWW6RRRRRR
+ Command $10: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $11: C7W7WWWWW6RRRRRR
+ Command $12: C7W7WWWWWWWW6RRRRRRRRR
+ Command $13: C7W7WWWWWWWW
+ Command $14: C7W6R
+ Command $15: C7W6R
+ Command $16: C7W6RR
+ Command $17: C7W
+ Command $18: C76RRRRRRRRR
+ Command $19: C7
+ Command $1a: C76RRRRRRRRR
+ Command $1b: C7
+ Command $1c: C76RRRRRRRRR
+ Command $1d: C7
+ Command $1e: C76RRRRRRRRR
+ Command $1f: C7
+ Command $20: C76RRRRRRRRR
+ Command $21: C7
+ Command $22: C76RRRRRRRRR
+ Command $23: C7
+ Command $24: C7
+
+ Command $0e: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $14: C7W6R
+ Command $15: C7W6R
+
+ Steel Talons:
+ Version = ????
+ Checksum = ????
+
+ Command $08: C7
+ Command $09: C7W6R
+ Command $0a: C7
+ Command $0b: C7W7WWWWWWWW
+ Command $0c: C7W7WWWWW
+ Command $0d: C7W7W
+ Command $14: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $15: C7W7WWWWW6RRRRRR
+ Command $16: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $17: C7W7WWWWW6RRRRRR
+ Command $12: C7W7WWWWWWWW6RRRRRRRRR
+ Command $13: C7W7WWWWWWWW
+ Command $1e: C7W6R
+ Command $1f: C7W6R
+ Command $16: C7W6RR
+ Command $17: C7W
+ Command $20: C7W7WWW6R
+ Command $18: C76RRRRRRRRR
+ Command $19: C7
+ Command $1a: C76RRRRRRRRR
+ Command $1b: C7
+ Command $1c: C76RRRRRRRRR
+ Command $1d: C7
+ Command $1e: C76RRRRRRRRR
+ Command $1f: C7
+ Command $20: C76RRRRRRRRR
+ Command $21: C7
+ Command $22: C76RRRRRRRRR
+ Command $23: C7
+ Command $24: C7
+
+ Hard Drivin's Airborne:
+ Version = ????
+ Checksum = ????
+
+ Command $0e: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $14: C7W6R
+
+ Command $08: C7
+ Command $09: C7W6R
+ Command $0a: C7
+ Command $0b: C7W7WWWWWWWW
+ Command $0c: C7W7WWWWW
+ Command $0d: C7W7W
+ Command $0e: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $0f: C7W7WWWWW6RRRRRR
+ Command $10: C7W7WWWWWWWWWWWWWW6RRRRRR
+ Command $11: C7W7WWWWW6RRRRRR
+ Command $12: C7W7WWWWWWWW6RRRRRRRRR
+ Command $13: C7W7WWWWWWWW
+ Command $14: C7W6R
+ Command $15: C7W6R
+ Command $16: C7W6RR
+ Command $17: C7W
+ Command $18: C76RRRRRRRRR
+ Command $19: C7
+ Command $1a: C76RRRRRRRRR
+ Command $1b: C7
+ Command $1c: C76RRRRRRRRR
+ Command $1d: C7
+ Command $1e: C76RRRRRRRRR
+ Command $1f: C7
+ Command $20: C76RRRRRRRRR
+ Command $21: C7
+ Command $22: C76RRRRRRRRR
+ Command $23: C7
+ Command $24: C7
+ Command $26: C7W
+ Command $27: C7W7WWWWW
+ Command $28: C7
+ Command $2a: C76RRRRRRRRR
+
+***********************************************************************/
diff --git a/src/mame/machine/asic65.h b/src/mame/machine/asic65.h
new file mode 100644
index 00000000000..b1b2436743b
--- /dev/null
+++ b/src/mame/machine/asic65.h
@@ -0,0 +1,18 @@
+/*************************************
+ *
+ * Implementation of ASIC65
+ *
+ *************************************/
+
+#define ASIC65_STANDARD 0
+#define ASIC65_STEELTAL 1
+#define ASIC65_GUARDIANS 2
+#define ASIC65_ROMBASED 3
+
+void asic65_config(int asictype);
+void asic65_reset(int state);
+WRITE16_HANDLER( asic65_data_w );
+READ16_HANDLER( asic65_r );
+READ16_HANDLER( asic65_io_r );
+
+MACHINE_DRIVER_EXTERN( asic65 );
diff --git a/src/mame/machine/asteroid.c b/src/mame/machine/asteroid.c
new file mode 100644
index 00000000000..72912641965
--- /dev/null
+++ b/src/mame/machine/asteroid.c
@@ -0,0 +1,193 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/atari_vg.h"
+#include "video/avgdvg.h"
+#include "asteroid.h"
+
+UINT8 *asteroid_ram1, *asteroid_ram2;
+
+INTERRUPT_GEN( asteroid_interrupt )
+{
+ /* Turn off interrupts if self-test is enabled */
+ if (!(readinputport(0) & 0x80))
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+INTERRUPT_GEN( asterock_interrupt )
+{
+ /* Turn off interrupts if self-test is enabled */
+ if ((readinputport(0) & 0x80))
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+INTERRUPT_GEN( llander_interrupt )
+{
+ /* Turn off interrupts if self-test is enabled */
+ if (readinputport(0) & 0x02)
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+
+READ8_HANDLER( asteroid_IN0_r )
+{
+
+ int res;
+ int bitmask;
+
+ res=readinputport(0);
+
+ bitmask = (1 << offset);
+
+ if (activecpu_gettotalcycles() & 0x100)
+ res |= 0x02;
+ if (!avgdvg_done())
+ res |= 0x04;
+
+ if (res & bitmask)
+ res = 0x80;
+ else
+ res = ~0x80;
+
+ return res;
+}
+
+
+READ8_HANDLER( asteroib_IN0_r )
+{
+ int res;
+
+ res=readinputport(0);
+
+// if (activecpu_gettotalcycles() & 0x100)
+// res |= 0x02;
+ if (!avgdvg_done())
+ res |= 0x80;
+
+ return res;
+}
+
+READ8_HANDLER( asterock_IN0_r )
+{
+ int res;
+ int bitmask;
+
+ res=readinputport(0);
+
+ bitmask = (1 << offset);
+
+ if (activecpu_gettotalcycles() & 0x100)
+ res |= 0x04;
+ if (!avgdvg_done())
+ res |= 0x01;
+
+ if (res & bitmask)
+ res = ~0x80;
+ else
+ res = 0x80;
+
+ return res;
+}
+
+/*
+ * These 7 memory locations are used to read the player's controls.
+ * Typically, only the high bit is used. This is handled by one input port.
+ */
+
+READ8_HANDLER( asteroid_IN1_r )
+{
+ int res;
+ int bitmask;
+
+ res=readinputport(1);
+ bitmask = (1 << offset);
+
+ if (res & bitmask)
+ res = 0x80;
+ else
+ res = ~0x80;
+ return (res);
+}
+
+
+READ8_HANDLER( asteroid_DSW1_r )
+{
+ int res;
+ int res1;
+
+ res1 = readinputport(2);
+
+ res = 0xfc | ((res1 >> (2 * (3 - (offset & 0x3)))) & 0x3);
+ return res;
+}
+
+
+WRITE8_HANDLER( asteroid_bank_switch_w )
+{
+ if (data & 4)
+ {
+ memory_set_bankptr(1, asteroid_ram2);
+ memory_set_bankptr(2, asteroid_ram1);
+ }
+ else
+ {
+ memory_set_bankptr(1, asteroid_ram1);
+ memory_set_bankptr(2, asteroid_ram2);
+ }
+
+ set_led_status (0, ~data & 0x02);
+ set_led_status (1, ~data & 0x01);
+}
+
+
+WRITE8_HANDLER( astdelux_bank_switch_w )
+{
+ if (data & 0x80)
+ {
+ memory_set_bankptr(1, asteroid_ram2);
+ memory_set_bankptr(2, asteroid_ram1);
+ }
+ else
+ {
+ memory_set_bankptr(1, asteroid_ram1);
+ memory_set_bankptr(2, asteroid_ram2);
+ }
+}
+
+
+WRITE8_HANDLER( astdelux_led_w )
+{
+ set_led_status(offset,(data&0x80)?0:1);
+}
+
+
+MACHINE_RESET( asteroid )
+{
+ asteroid_bank_switch_w (0,0);
+ avgdvg_reset_w (0,0);
+}
+
+
+/*
+ * This is Lunar Lander's Inputport 0.
+ */
+READ8_HANDLER( llander_IN0_r )
+{
+ int res;
+
+ res = readinputport(0);
+
+ if (avgdvg_done())
+ res |= 0x01;
+ if (activecpu_gettotalcycles() & 0x100)
+ res |= 0x40;
+
+ return res;
+}
diff --git a/src/mame/machine/atari.c b/src/mame/machine/atari.c
new file mode 100644
index 00000000000..47c92e0415f
--- /dev/null
+++ b/src/mame/machine/atari.c
@@ -0,0 +1,982 @@
+/***************************************************************************
+
+ Atari 400/800
+
+ Machine driver
+
+ Juergen Buchmueller, June 1998
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6502/m6502.h"
+#include "includes/atari.h"
+#include "sound/pokey.h"
+#include "machine/6821pia.h"
+#include "sound/dac.h"
+#include "video/gtia.h"
+
+#define VERBOSE_POKEY 0
+#define VERBOSE_SERIAL 0
+#define VERBOSE_TIMERS 0
+
+//#define LOG(x) if (errorlog) fprintf x
+
+static int atari = 0;
+#define ATARI_5200 0
+#define ATARI_400 1
+#define ATARI_800 2
+#define ATARI_600XL 3
+#define ATARI_800XL 4
+
+#ifdef MESS
+static int a800_cart_loaded = 0;
+static int a800_cart_is_16k = 0;
+#endif
+
+static void a800xl_mmu(UINT8 new_mmu);
+static void a600xl_mmu(UINT8 new_mmu);
+
+static void pokey_reset(running_machine *machine);
+
+void atari_interrupt_cb(int mask)
+{
+
+#if VERBOSE_POKEY
+ if (mask & 0x80)
+ logerror("atari interrupt_cb BREAK\n");
+ if (mask & 0x40)
+ logerror("atari interrupt_cb KBCOD\n");
+#endif
+#if VERBOSE_SERIAL
+ if (mask & 0x20)
+ logerror("atari interrupt_cb SERIN\n");
+ if (mask & 0x10)
+ logerror("atari interrupt_cb SEROR\n");
+ if (mask & 0x08)
+ logerror("atari interrupt_cb SEROC\n");
+#endif
+#if VERBOSE_TIMERS
+ if (mask & 0x04)
+ logerror("atari interrupt_cb TIMR4\n");
+ if (mask & 0x02)
+ logerror("atari interrupt_cb TIMR2\n");
+ if (mask & 0x01)
+ logerror("atari interrupt_cb TIMR1\n");
+#endif
+
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+}
+
+/**************************************************************
+ *
+ * PIA interface
+ *
+ **************************************************************/
+
+static READ8_HANDLER(atari_pia_pa_r)
+{
+ return atari_input_disabled() ? 0xFF : readinputportbytag_safe("djoy_0_1", 0);
+}
+
+static READ8_HANDLER(atari_pia_pb_r)
+{
+ return atari_input_disabled() ? 0xFF : readinputportbytag_safe("djoy_2_3", 0);
+}
+
+static WRITE8_HANDLER(a600xl_pia_pb_w) { a600xl_mmu(data); }
+static WRITE8_HANDLER(a800xl_pia_pb_w) { a800xl_mmu(data); }
+
+#ifdef MESS
+extern WRITE8_HANDLER(atari_pia_cb2_w);
+#else
+#define atari_pia_cb2_w (0)
+#endif
+
+static const pia6821_interface atari_pia_interface =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ atari_pia_pa_r, atari_pia_pb_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, atari_pia_cb2_w,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface a600xl_pia_interface =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ atari_pia_pa_r, atari_pia_pb_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, a600xl_pia_pb_w, 0, atari_pia_cb2_w,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface a800xl_pia_interface =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ atari_pia_pa_r, atari_pia_pb_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, a800xl_pia_pb_w, 0, atari_pia_cb2_w,
+ /*irqs : A/B */ 0, 0
+};
+
+
+
+
+/**************************************************************
+ *
+ * Reset hardware
+ *
+ **************************************************************/
+
+void a600xl_mmu(UINT8 new_mmu)
+{
+ read8_handler rbank2;
+ write8_handler wbank2;
+
+ /* check if self-test ROM changed */
+ if ( new_mmu & 0x80 )
+ {
+ logerror("%s MMU SELFTEST RAM\n", Machine->gamedrv->name);
+ rbank2 = MRA8_NOP;
+ wbank2 = MWA8_NOP;
+ }
+ else
+ {
+ logerror("%s MMU SELFTEST ROM\n", Machine->gamedrv->name);
+ rbank2 = MRA8_BANK2;
+ wbank2 = MWA8_ROM;
+ }
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, rbank2);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, wbank2);
+ if (rbank2 == MRA8_BANK2)
+ memory_set_bankptr(2, memory_region(REGION_CPU1)+0x5000);
+}
+
+void a800xl_mmu(UINT8 new_mmu)
+{
+ read8_handler rbank1, rbank2, rbank3, rbank4;
+ write8_handler wbank1, wbank2, wbank3, wbank4;
+ UINT8 *base1, *base2, *base3, *base4;
+
+ /* check if memory C000-FFFF changed */
+ if( new_mmu & 0x01 )
+ {
+ logerror("%s MMU BIOS ROM\n", Machine->gamedrv->name);
+ rbank3 = MRA8_BANK3;
+ wbank3 = MWA8_ROM;
+ base3 = memory_region(REGION_CPU1)+0x14000; /* 8K lo BIOS */
+ rbank4 = MRA8_BANK4;
+ wbank4 = MWA8_ROM;
+ base4 = memory_region(REGION_CPU1)+0x15800; /* 4K FP ROM + 8K hi BIOS */
+ }
+ else
+ {
+ logerror("%s MMU BIOS RAM\n", Machine->gamedrv->name);
+ rbank3 = MRA8_BANK3;
+ wbank3 = MWA8_BANK3;
+ base3 = memory_region(REGION_CPU1)+0x0c000; /* 8K RAM */
+ rbank4 = MRA8_BANK4;
+ wbank4 = MWA8_BANK4;
+ base4 = memory_region(REGION_CPU1)+0x0d800; /* 4K RAM + 8K RAM */
+ }
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, rbank3);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, wbank3);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xd800, 0xffff, 0, 0, rbank4);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xd800, 0xffff, 0, 0, wbank4);
+ memory_set_bankptr(3, base3);
+ memory_set_bankptr(4, base4);
+
+ /* check if BASIC changed */
+ if( new_mmu & 0x02 )
+ {
+ logerror("%s MMU BASIC RAM\n", Machine->gamedrv->name);
+ rbank1 = MRA8_BANK1;
+ wbank1 = MWA8_BANK1;
+ base1 = memory_region(REGION_CPU1)+0x0a000; /* 8K RAM */
+ }
+ else
+ {
+ logerror("%s MMU BASIC ROM\n", Machine->gamedrv->name);
+ rbank1 = MRA8_BANK1;
+ wbank1 = MWA8_ROM;
+ base1 = memory_region(REGION_CPU1)+0x10000; /* 8K BASIC */
+ }
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa000, 0xbfff, 0, 0, rbank1);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa000, 0xbfff, 0, 0, wbank1);
+ memory_set_bankptr(1, base1);
+
+ /* check if self-test ROM changed */
+ if( new_mmu & 0x80 )
+ {
+ logerror("%s MMU SELFTEST RAM\n", Machine->gamedrv->name);
+ rbank2 = MRA8_BANK2;
+ wbank2 = MWA8_BANK2;
+ base2 = memory_region(REGION_CPU1)+0x05000; /* 0x0800 bytes */
+ }
+ else
+ {
+ logerror("%s MMU SELFTEST ROM\n", Machine->gamedrv->name);
+ rbank2 = MRA8_BANK2;
+ wbank2 = MWA8_ROM;
+ base2 = memory_region(REGION_CPU1)+0x15000; /* 0x0800 bytes */
+ }
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, rbank2);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5000, 0x57ff, 0, 0, wbank2);
+ memory_set_bankptr(2, base2);
+}
+
+
+
+/**************************************************************
+ *
+ * Keyboard
+ *
+ **************************************************************/
+
+#define AKEY_L 0x00
+#define AKEY_J 0x01
+#define AKEY_SEMICOLON 0x02
+#define AKEY_BREAK 0x03 /* this not really a scancode */
+#define AKEY_K 0x05
+#define AKEY_PLUS 0x06
+#define AKEY_ASTERISK 0x07
+#define AKEY_O 0x08
+#define AKEY_NONE 0x09
+#define AKEY_P 0x0a
+#define AKEY_U 0x0b
+#define AKEY_ENTER 0x0c
+#define AKEY_I 0x0d
+#define AKEY_MINUS 0x0e
+#define AKEY_EQUALS 0x0f
+#define AKEY_V 0x10
+#define AKEY_C 0x12
+#define AKEY_B 0x15
+#define AKEY_X 0x16
+#define AKEY_Z 0x17
+#define AKEY_4 0x18
+#define AKEY_3 0x1a
+#define AKEY_6 0x1b
+#define AKEY_ESC 0x1c
+#define AKEY_5 0x1d
+#define AKEY_2 0x1e
+#define AKEY_1 0x1f
+#define AKEY_COMMA 0x20
+#define AKEY_SPACE 0x21
+#define AKEY_STOP 0x22
+#define AKEY_N 0x23
+#define AKEY_M 0x25
+#define AKEY_SLASH 0x26
+#define AKEY_ATARI 0x27
+#define AKEY_R 0x28
+#define AKEY_E 0x2a
+#define AKEY_Y 0x2b
+#define AKEY_TAB 0x2c
+#define AKEY_T 0x2d
+#define AKEY_W 0x2e
+#define AKEY_Q 0x2f
+#define AKEY_9 0x30
+#define AKEY_0 0x32
+#define AKEY_7 0x33
+#define AKEY_BSP 0x34
+#define AKEY_8 0x35
+#define AKEY_LESSER 0x36
+#define AKEY_GREATER 0x37
+#define AKEY_F 0x38
+#define AKEY_H 0x39
+#define AKEY_D 0x3a
+#define AKEY_CAPS 0x3c
+#define AKEY_G 0x3d
+#define AKEY_S 0x3e
+#define AKEY_A 0x3f
+#define ASHF_L 0x40
+#define ASHF_J 0x41
+#define ASHF_COLON 0x42
+#define ASHF_BREAK 0x43 /* this not really a scancode */
+#define ASHF_K 0x45
+#define ASHF_BACKSLASH 0x46
+#define ASHF_TILDE 0x47
+#define ASHF_O 0x48
+#define ASHF_SHIFT 0x49
+#define ASHF_P 0x4a
+#define ASHF_U 0x4b
+#define ASHF_ENTER 0x4c
+#define ASHF_I 0x4d
+#define ASHF_UNDERSCORE 0x4e
+#define ASHF_BAR 0x4f
+#define ASHF_V 0x50
+#define ASHF_C 0x52
+#define ASHF_B 0x55
+#define ASHF_X 0x56
+#define ASHF_Z 0x57
+#define ASHF_DOLLAR 0x58
+#define ASHF_HASH 0x5a
+#define ASHF_AMPERSAND 0x5b
+#define ASHF_ESC 0x5c
+#define ASHF_PERCENT 0x5d
+#define ASHF_DQUOTE 0x5e
+#define ASHF_EXCLAM 0x5f
+#define ASHF_LBRACE 0x60
+#define ASHF_SPACE 0x61
+#define ASHF_RBRACE 0x62
+#define ASHF_N 0x63
+#define ASHF_M 0x65
+#define ASHF_QUESTION 0x66
+#define ASHF_ATARI 0x67
+#define ASHF_R 0x68
+#define ASHF_E 0x6a
+#define ASHF_Y 0x6b
+#define ASHF_TAB 0x6c
+#define ASHF_T 0x6d
+#define ASHF_W 0x6e
+#define ASHF_Q 0x6f
+#define ASHF_LPAREN 0x70
+#define ASHF_RPAREN 0x72
+#define ASHF_QUOTE 0x73
+#define ASHF_BSP 0x74
+#define ASHF_AT 0x75
+#define ASHF_CLEAR 0x76
+#define ASHF_INSERT 0x77
+#define ASHF_F 0x78
+#define ASHF_H 0x79
+#define ASHF_D 0x7a
+#define ASHF_CAPS 0x7c
+#define ASHF_G 0x7d
+#define ASHF_S 0x7e
+#define ASHF_A 0x7f
+#define ACTL_L 0x80
+#define ACTL_J 0x81
+#define ACTL_SEMICOLON 0x82
+#define ACTL_BREAK 0x83 /* this not really a scancode */
+#define ACTL_K 0x85
+#define ACTL_PLUS 0x86
+#define ACTL_ASTERISK 0x87
+#define ACTL_O 0x88
+#define ACTL_CONTROL 0x89
+#define ACTL_P 0x8a
+#define ACTL_U 0x8b
+#define ACTL_ENTER 0x8c
+#define ACTL_I 0x8d
+#define ACTL_MINUS 0x8e
+#define ACTL_EQUALS 0x8f
+#define ACTL_V 0x90
+#define ACTL_C 0x92
+#define ACTL_B 0x95
+#define ACTL_X 0x96
+#define ACTL_Z 0x97
+#define ACTL_4 0x98
+#define ACTL_3 0x9a
+#define ACTL_6 0x9b
+#define ACTL_ESC 0x9c
+#define ACTL_5 0x9d
+#define ACTL_2 0x9e
+#define ACTL_1 0x9f
+#define ACTL_COMMA 0xa0
+#define ACTL_SPACE 0xa1
+#define ACTL_STOP 0xa2
+#define ACTL_N 0xa3
+#define ACTL_M 0xa5
+#define ACTL_SLASH 0xa6
+#define ACTL_ATARI 0xa7
+#define ACTL_R 0xa8
+#define ACTL_E 0xaa
+#define ACTL_Y 0xab
+#define ACTL_TAB 0xac
+#define ACTL_T 0xad
+#define ACTL_W 0xae
+#define ACTL_Q 0xaf
+#define ACTL_9 0xb0
+#define ACTL_0 0xb2
+#define ACTL_7 0xb3
+#define ACTL_BSP 0xb4
+#define ACTL_8 0xb5
+#define ACTL_LESSER 0xb6
+#define ACTL_GREATER 0xb7
+#define ACTL_F 0xb8
+#define ACTL_H 0xb9
+#define ACTL_D 0xba
+#define ACTL_CAPS 0xbc
+#define ACTL_G 0xbd
+#define ACTL_S 0xbe
+#define ACTL_A 0xbf
+#define ACSH_L 0xc0
+#define ACSH_J 0xc1
+#define ACSH_COLON 0xc2
+#define ACSH_BREAK 0xc3 /* this not really a scancode */
+#define ACSH_K 0xc5
+#define ACSH_BACKSLASH 0xc6
+#define ACSH_TILDE 0xc7
+#define ACSH_O 0xc8
+#define ACSH_CTRLSHIFT 0xc9
+#define ACSH_P 0xca
+#define ACSH_U 0xcb
+#define ACSH_ENTER 0xcc
+#define ACSH_I 0xcd
+#define ACSH_UNDERSCORE 0xce
+#define ACSH_BAR 0xcf
+#define ACSH_V 0xd0
+#define ACSH_C 0xd2
+#define ACSH_B 0xd5
+#define ACSH_X 0xd6
+#define ACSH_Z 0xd7
+#define ACSH_DOLLAR 0xd8
+#define ACSH_HASH 0xda
+#define ACSH_AMPERSAND 0xdb
+#define ACSH_ESC 0xdc
+#define ACSH_PERCENT 0xdd
+#define ACSH_DQUOTE 0xde
+#define ACSH_EXCLAM 0xdf
+#define ACSH_LBRACE 0xe0
+#define ACSH_SPACE 0xe1
+#define ACSH_RBRACE 0xe2
+#define ACSH_N 0xe3
+#define ACSH_M 0xe5
+#define ACSH_QUESTION 0xe6
+#define ACSH_ATARI 0xe7
+#define ACSH_R 0xe8
+#define ACSH_E 0xea
+#define ACSH_Y 0xeb
+#define ACSH_TAB 0xec
+#define ACSH_T 0xed
+#define ACSH_W 0xee
+#define ACSH_Q 0xef
+#define ACSH_LPAREN 0xf0
+#define ACSH_RPAREN 0xf2
+#define ACSH_QUOTE 0xf3
+#define ACSH_BSP 0xf4
+#define ACSH_AT 0xf5
+#define ACSH_CLEAR 0xf6
+#define ACSH_INSERT 0xf7
+#define ACSH_F 0xf8
+#define ACSH_H 0xf9
+#define ACSH_D 0xfa
+#define ACSH_CAPS 0xfc
+#define ACSH_G 0xfd
+#define ACSH_S 0xfe
+#define ACSH_A 0xff
+
+static const UINT8 keys[64][4] = {
+{AKEY_NONE ,AKEY_NONE ,AKEY_NONE ,AKEY_NONE }, /* "" CODE_NONE */
+{AKEY_ESC ,ASHF_ESC ,ACTL_ESC ,ACSH_ESC }, /*"Escape" KEYCODE_ESC */
+{AKEY_1 ,ASHF_EXCLAM ,ACTL_1 ,ACSH_EXCLAM }, /* "1 !" KEYCODE_1 */
+{AKEY_2 ,ASHF_DQUOTE ,ACTL_2 ,ACSH_DQUOTE }, /* "2 \"" KEYCODE_2 */
+{AKEY_3 ,ASHF_HASH ,ACTL_3 ,ACSH_HASH }, /* "3 #" KEYCODE_3 */
+{AKEY_4 ,ASHF_DOLLAR ,ACTL_4 ,ACSH_DOLLAR }, /* "4 $" KEYCODE_4 */
+{AKEY_5 ,ASHF_PERCENT ,ACTL_5 ,ACSH_PERCENT }, /* "5 %" KEYCODE_5 */
+{AKEY_6 ,ASHF_TILDE ,ACTL_6 ,ACSH_AMPERSAND }, /* "6 ^" KEYCODE_6 */
+{AKEY_7 ,ASHF_AMPERSAND ,ACTL_7 ,ACSH_N }, /* "7 &" KEYCODE_7 */
+{AKEY_8 ,AKEY_ASTERISK ,ACTL_8 ,ACSH_M }, /* "8 *" KEYCODE_8 */
+{AKEY_9 ,ASHF_LPAREN ,ACTL_9 ,ACSH_LBRACE }, /* "9 (" KEYCODE_9 */
+{AKEY_0 ,ASHF_RPAREN ,ACTL_0 ,ACSH_RBRACE }, /* "0 )" KEYCODE_0 */
+{AKEY_MINUS ,ASHF_UNDERSCORE ,ACTL_MINUS ,ACSH_UNDERSCORE }, /* "- _" KEYCODE_MINUS */
+{AKEY_EQUALS ,AKEY_PLUS ,ACTL_EQUALS ,ACTL_PLUS }, /* "= +" KEYCODE_EQUALS */
+{AKEY_BSP ,ASHF_BSP ,ACTL_BSP ,ACSH_BSP }, /* "Backsp" KEYCODE_BACKSPACE */
+{AKEY_TAB ,ASHF_TAB ,ACTL_TAB ,ACSH_TAB }, /* "Tab" KEYCODE_TAB */
+{AKEY_Q ,ASHF_Q ,ACTL_Q ,ACSH_Q }, /* "q Q" KEYCODE_Q */
+{AKEY_W ,ASHF_W ,ACTL_W ,ACSH_W }, /* "w W" KEYCODE_W */
+{AKEY_E ,ASHF_E ,ACTL_E ,ACSH_E }, /* "e E" KEYCODE_E */
+{AKEY_R ,ASHF_R ,ACTL_R ,ACSH_R }, /* "r R" KEYCODE_R */
+{AKEY_T ,ASHF_T ,ACTL_T ,ACSH_T }, /* "t T" KEYCODE_T */
+{AKEY_Y ,ASHF_Y ,ACTL_Y ,ACSH_Y }, /* "y Y" KEYCODE_Y */
+{AKEY_U ,ASHF_U ,ACTL_U ,ACTL_U }, /* "u U" KEYCODE_U */
+{AKEY_I ,ASHF_I ,ACTL_I ,ACTL_I }, /* "i I" KEYCODE_I */
+{AKEY_O ,ASHF_O ,ACTL_O ,ACTL_O }, /* "o O" KEYCODE_O */
+{AKEY_P ,ASHF_P ,ACTL_P ,ACTL_P }, /* "p P" KEYCODE_P */
+{ASHF_LBRACE ,ACTL_COMMA ,ACTL_COMMA ,ACSH_LBRACE }, /* "[ {" KEYCODE_LBRACE */
+{ASHF_RBRACE ,ACTL_STOP ,ACTL_STOP ,ACSH_RBRACE }, /* "] }" KEYCODE_RBRACE */
+{AKEY_ENTER ,ASHF_ENTER ,ACTL_ENTER ,ACSH_ENTER }, /* "Enter" KEYCODE_ENTER */
+{AKEY_A ,ASHF_A ,ACTL_A ,ACSH_A }, /* "a A" KEYCODE_A */
+{AKEY_S ,ASHF_S ,ACTL_S ,ACSH_S }, /* "s S" KEYCODE_S */
+{AKEY_D ,ASHF_D ,ACTL_D ,ACSH_D }, /* "d D" KEYCODE_D */
+{AKEY_F ,ASHF_F ,ACTL_F ,ACSH_F }, /* "f F" KEYCODE_F */
+{AKEY_G ,ASHF_G ,ACTL_G ,ACSH_G }, /* "g G" KEYCODE_G */
+{AKEY_H ,ASHF_H ,ACTL_H ,ACSH_H }, /* "h H" KEYCODE_H */
+{AKEY_J ,ASHF_J ,ACTL_J ,ACSH_J }, /* "j J" KEYCODE_J */
+{AKEY_K ,ASHF_K ,ACTL_K ,ACSH_K }, /* "k K" KEYCODE_K */
+{AKEY_L ,ASHF_L ,ACTL_L ,ACSH_L }, /* "l L" KEYCODE_L */
+{AKEY_SEMICOLON ,ASHF_COLON ,ACTL_SEMICOLON ,ACSH_COLON }, /* "; :" KEYCODE_COLON */
+{ASHF_QUOTE ,ACSH_QUOTE ,ASHF_DQUOTE ,ACSH_DQUOTE }, /* "+ \\" KEYCODE_QUOTE */
+{ASHF_QUOTE ,ACSH_QUOTE ,ACTL_ASTERISK ,ACSH_TILDE }, /* "* ^" KEYCODE_TILDE */
+{ASHF_BACKSLASH ,ASHF_BAR ,ACSH_BACKSLASH ,ACSH_BAR }, /* "\ |" KEYCODE_BACKSLASH */
+{AKEY_Z ,ASHF_Z ,ACTL_Z ,ACSH_Z }, /* "z Z" KEYCODE_Z */
+{AKEY_X ,ASHF_X ,ACTL_X ,ACTL_X }, /* "x X" KEYCODE_X */
+{AKEY_C ,ASHF_C ,ACTL_C ,ACTL_C }, /* "c C" KEYCODE_C */
+{AKEY_V ,ASHF_V ,ACTL_V ,ACTL_V }, /* "v V" KEYCODE_V */
+{AKEY_B ,ASHF_B ,ACTL_B ,ACTL_B }, /* "b B" KEYCODE_B */
+{AKEY_N ,ASHF_N ,ACTL_N ,ACTL_N }, /* "n N" KEYCODE_N */
+{AKEY_M ,ASHF_M ,ACTL_M ,ACTL_M }, /* "m M" KEYCODE_M */
+{AKEY_COMMA ,AKEY_LESSER ,ACTL_COMMA ,ACTL_LESSER }, /* ", [" KEYCODE_COMMA */
+{AKEY_STOP ,AKEY_GREATER ,ACTL_STOP ,ACTL_GREATER }, /* ". ]" KEYCODE_STOP */
+{AKEY_SLASH ,ASHF_QUESTION ,ACTL_SLASH ,ACSH_QUESTION }, /* "/ ?" KEYCODE_SLASH */
+{ASHF_BACKSLASH ,ASHF_BAR ,ACSH_BACKSLASH ,ACSH_BAR }, /* "\ |" KEYCODE_BACKSLASH2 */
+{AKEY_ATARI ,ASHF_ATARI ,ACTL_ATARI ,ACSH_ATARI }, /* "Atari" KEYCODE_LALT */
+{AKEY_SPACE ,ASHF_SPACE ,ACTL_SPACE ,ACSH_SPACE }, /* "Space" KEYCODE_SPACE */
+{AKEY_CAPS ,ASHF_CAPS ,ACTL_CAPS ,ACSH_CAPS }, /* "Caps" KEYCODE_CAPSLOCK */
+{ASHF_CLEAR ,ASHF_CLEAR ,ACSH_CLEAR ,ACSH_CLEAR }, /* "Clear" KEYCODE_HOME */
+{ASHF_INSERT ,ASHF_INSERT ,ASHF_INSERT ,ASHF_INSERT }, /* "Insert" KEYCODE_INSERT */
+{AKEY_BSP ,AKEY_BSP ,AKEY_BSP ,AKEY_BSP }, /* "Delete" KEYCODE_DEL */
+{AKEY_BREAK ,ASHF_BREAK ,ACTL_BREAK ,ACSH_BREAK }, /* "Break" KEYCODE_PGUP */
+{ACTL_PLUS ,ACTL_PLUS ,ACTL_PLUS ,ACTL_PLUS }, /* "(Left)" KEYCODE_LEFT */
+{ACTL_ASTERISK ,ACTL_ASTERISK ,ACTL_ASTERISK ,ACTL_ASTERISK }, /* "(Right)"KEYCODE_RIGHT */
+{ACTL_MINUS ,ACTL_MINUS ,ACTL_MINUS ,ACTL_MINUS }, /* "(Up)" KEYCODE_UP */
+{ACTL_EQUALS ,ACTL_EQUALS ,ACTL_EQUALS ,ACTL_EQUALS } /* "(Down)" KEYCODE_DOWN */
+};
+
+
+void a800_handle_keyboard(void)
+{
+ static int atari_last = 0xff;
+ int i, modifiers, atari_code;
+ char tag[64];
+
+ modifiers = 0;
+
+ /* with shift ? */
+ if( input_code_pressed(KEYCODE_LSHIFT) || input_code_pressed(KEYCODE_RSHIFT) )
+ modifiers |= 1;
+
+ /* with control ? */
+ if( input_code_pressed(KEYCODE_LCONTROL) || input_code_pressed(KEYCODE_RCONTROL) )
+ modifiers |= 2;
+
+ for( i = 0; i < 64; i++ )
+ {
+ sprintf(tag, "keyboard_%d", i / 16);
+ if( readinputportbytag_safe(tag, 0) & (1 << (i&15)) )
+ {
+ atari_code = keys[i][modifiers];
+ if( atari_code != AKEY_NONE )
+ {
+ if( atari_code == atari_last )
+ return;
+ atari_last = atari_code;
+ if( (atari_code & 0x3f) == AKEY_BREAK )
+ {
+ pokey1_break_w(atari_code & 0x40);
+ return;
+ }
+ pokey1_kbcode_w(atari_code, 1);
+ return;
+ }
+ }
+ }
+ /* remove key pressed status bit from skstat */
+ pokey1_kbcode_w(AKEY_NONE, 0);
+ atari_last = AKEY_NONE;
+}
+
+#define VKEY_BREAK 0x10
+
+/* absolutely no clue what to do here :((( */
+void a5200_handle_keypads(void)
+{
+ int i, modifiers;
+ static int atari_last = 0xff;
+
+ modifiers = 0;
+
+ /* with shift ? */
+ if (input_code_pressed(KEYCODE_LSHIFT) || input_code_pressed(KEYCODE_RSHIFT))
+ modifiers |= 1;
+
+ /* with control ? */
+ if (input_code_pressed(KEYCODE_LCONTROL) || input_code_pressed(KEYCODE_RCONTROL))
+ modifiers |= 2;
+
+ /* check keypad */
+ for (i = 0; i < 16; i++)
+ {
+ if( readinputportbytag("keypad") & (1 << i) )
+ {
+ if( i == atari_last )
+ return;
+ atari_last = i;
+ if( i == 0 )
+ {
+ pokey1_break_w(i & 0x40);
+ return;
+ }
+ pokey1_kbcode_w((i << 1) | 0x21, 1);
+ return;
+ }
+ }
+
+ /* check top button */
+ if ((readinputportbytag("djoy_b") & 0x10) == 0)
+ {
+ if (atari_last == 0xFE)
+ return;
+ pokey1_kbcode_w(0x61, 1);
+ //pokey1_break_w(0x40);
+ atari_last = 0xFE;
+ return;
+ }
+ else if (atari_last == 0xFE)
+ pokey1_kbcode_w(0x21, 1);
+
+ /* remove key pressed status bit from skstat */
+ pokey1_kbcode_w(0xFF, 0);
+ atari_last = 0xff;
+}
+
+#ifdef MESS
+DRIVER_INIT( atari )
+{
+ offs_t ram_top;
+ offs_t ram_size;
+
+ if (!strcmp(machine->gamedrv->name, "a400")
+ || !strcmp(machine->gamedrv->name, "a400pal")
+ || !strcmp(machine->gamedrv->name, "a800")
+ || !strcmp(machine->gamedrv->name, "a800pal")
+ || !strcmp(machine->gamedrv->name, "a800xl"))
+ {
+ ram_size = 0xA000;
+ }
+ else
+ {
+ ram_size = 0x8000;
+ }
+
+ /* install RAM */
+ ram_top = MIN(mess_ram_size, ram_size) - 1;
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM,
+ 0x0000, ram_top, 0, 0, MRA8_BANK2);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM,
+ 0x0000, ram_top, 0, 0, MWA8_BANK2);
+ memory_set_bankptr(2, mess_ram);
+}
+#endif
+
+
+
+/*************************************
+ *
+ * Generic Atari Code
+ *
+ *************************************/
+
+#ifdef MESS
+static void a800_setbank(int n)
+{
+ void *read_addr;
+ void *write_addr;
+ UINT8 *mem = memory_region(REGION_CPU1);
+
+ switch (n)
+ {
+ case 1:
+ read_addr = &mem[0x10000];
+ write_addr = NULL;
+ break;
+ default:
+ if( atari <= ATARI_400 )
+ {
+ /* Atari 400 has no RAM here, so install the NOP handler */
+ read_addr = NULL;
+ write_addr = NULL;
+ }
+ else
+ {
+ read_addr = &mess_ram[0x08000];
+ write_addr = &mess_ram[0x08000];
+ }
+ break;
+ }
+
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xbfff, 0, 0,
+ read_addr ? MRA8_BANK1 : MRA8_NOP);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xbfff, 0, 0,
+ write_addr ? MWA8_BANK1 : MWA8_NOP);
+ if (read_addr)
+ memory_set_bankptr(1, read_addr);
+ if (write_addr)
+ memory_set_bankptr(1, write_addr);
+}
+#endif
+
+
+
+static void pokey_reset(running_machine *machine)
+{
+ pokey1_w(15,0);
+}
+
+
+
+static void cart_reset(running_machine *machine)
+{
+#ifdef MESS
+ if (a800_cart_loaded)
+ a800_setbank(1);
+#endif /* MESS */
+}
+
+
+
+static UINT8 console_read(void)
+{
+ return readinputportbytag("console");
+}
+
+
+
+static void console_write(UINT8 data)
+{
+ if (data & 0x08)
+ DAC_data_w(0, -120);
+ else
+ DAC_data_w(0, +120);
+}
+
+
+static void _pia_reset(running_machine *machine)
+{
+ pia_reset();
+}
+
+static void _antic_reset(running_machine *machine)
+{
+ antic_reset();
+}
+
+
+static void atari_machine_start(int type, const pia6821_interface *pia_intf, int has_cart)
+{
+ gtia_interface gtia_intf;
+
+ atari = type;
+
+ /* GTIA */
+ memset(&gtia_intf, 0, sizeof(gtia_intf));
+ if (port_tag_to_index("console") >= 0)
+ gtia_intf.console_read = console_read;
+ if (sndti_exists(SOUND_DAC, 0))
+ gtia_intf.console_write = console_write;
+ gtia_init(&gtia_intf);
+
+ /* pokey */
+ add_reset_callback(Machine, pokey_reset);
+
+ /* PIA */
+ if (pia_intf)
+ {
+ pia_config(0, pia_intf);
+ add_reset_callback(Machine, _pia_reset);
+ }
+
+ /* ANTIC */
+ add_reset_callback(Machine, _antic_reset);
+
+ /* cartridge */
+ if (has_cart)
+ add_reset_callback(Machine, cart_reset);
+
+#ifdef MESS
+ {
+ offs_t ram_top;
+ offs_t ram_size;
+
+ if (!strcmp(Machine->gamedrv->name, "a400")
+ || !strcmp(Machine->gamedrv->name, "a400pal")
+ || !strcmp(Machine->gamedrv->name, "a800")
+ || !strcmp(Machine->gamedrv->name, "a800pal")
+ || !strcmp(Machine->gamedrv->name, "a800xl"))
+ {
+ ram_size = 0xA000;
+ }
+ else
+ {
+ ram_size = 0x8000;
+ }
+
+ /* install RAM */
+ ram_top = MIN(mess_ram_size, ram_size) - 1;
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM,
+ 0x0000, ram_top, 0, 0, MRA8_BANK2);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM,
+ 0x0000, ram_top, 0, 0, MWA8_BANK2);
+ memory_set_bankptr(2, mess_ram);
+ }
+#endif /* MESS */
+
+ /* save states */
+ state_save_register_global_pointer(((UINT8 *) &antic.r), sizeof(antic.r));
+ state_save_register_global_pointer(((UINT8 *) &antic.w), sizeof(antic.w));
+}
+
+
+
+/*************************************
+ *
+ * Atari 400
+ * Atari 600XL
+ *
+ *************************************/
+
+MACHINE_START( a400 )
+{
+ atari_machine_start(ATARI_400, &atari_pia_interface, TRUE);
+}
+
+MACHINE_START( a600xl )
+{
+ atari_machine_start(ATARI_600XL, &a600xl_pia_interface, TRUE);
+}
+
+
+
+/*************************************
+ *
+ * Atari 800
+ *
+ *************************************/
+
+MACHINE_START( a800 )
+{
+ atari_machine_start(ATARI_800, &atari_pia_interface, TRUE);
+}
+
+
+
+#ifdef MESS
+DEVICE_LOAD( a800_cart )
+{
+ UINT8 *mem = memory_region(REGION_CPU1);
+ int size;
+
+ /* load an optional (dual) cartridge (e.g. basic.rom) */
+ if( image_index_in_device(image) > 0 )
+ {
+ size = image_fread(image, &mem[0x12000], 0x2000);
+ a800_cart_is_16k = (size == 0x2000);
+ logerror("%s loaded right cartridge '%s' size 16K\n", Machine->gamedrv->name, image_filename(image) );
+ }
+ else
+ {
+ size = image_fread(image, &mem[0x10000], 0x2000);
+ a800_cart_loaded = size > 0x0000;
+ size = image_fread(image, &mem[0x12000], 0x2000);
+ a800_cart_is_16k = size > 0x2000;
+ logerror("%s loaded left cartridge '%s' size %s\n", Machine->gamedrv->name, image_filename(image) , (a800_cart_is_16k) ? "16K":"8K");
+ }
+ return INIT_PASS;
+}
+
+DEVICE_UNLOAD( a800_cart )
+{
+ if( image_index_in_device(image) > 0 )
+ {
+ a800_cart_is_16k = 0;
+ a800_setbank(1);
+ }
+ else
+ {
+ a800_cart_loaded = 0;
+ a800_setbank(0);
+ }
+}
+#endif
+
+
+
+/*************************************
+ *
+ * Atari 800XL
+ *
+ *************************************/
+
+MACHINE_START( a800xl )
+{
+ atari_machine_start(ATARI_800XL, &a800xl_pia_interface, TRUE);
+}
+
+
+
+#ifdef MESS
+DEVICE_LOAD( a800xl_cart )
+{
+ UINT8 *mem = memory_region(REGION_CPU1);
+ astring *fname;
+ mame_file *basic_fp;
+ file_error filerr;
+ unsigned size;
+
+ fname = astring_assemble_3(astring_alloc(), Machine->gamedrv->name, PATH_SEPARATOR, "basic.rom");
+ filerr = mame_fopen(SEARCHPATH_ROM, astring_c(fname), OPEN_FLAG_READ, &basic_fp);
+ astring_free(fname);
+
+ if (filerr != FILERR_NONE)
+ {
+ size = mame_fread(basic_fp, &mem[0x14000], 0x2000);
+ if( size < 0x2000 )
+ {
+ logerror("%s image '%s' load failed (less than 8K)\n", Machine->gamedrv->name, astring_c(fname));
+ mame_fclose(basic_fp);
+ return 2;
+ }
+ }
+
+ /* load an optional (dual) cartidge (e.g. basic.rom) */
+ if (filerr != FILERR_NONE)
+ {
+ {
+ size = image_fread(image, &mem[0x14000], 0x2000);
+ a800_cart_loaded = size / 0x2000;
+ size = image_fread(image, &mem[0x16000], 0x2000);
+ a800_cart_is_16k = size / 0x2000;
+ logerror("%s loaded cartridge '%s' size %s\n",
+ Machine->gamedrv->name, image_filename(image), (a800_cart_is_16k) ? "16K":"8K");
+ }
+ mame_fclose(basic_fp);
+ }
+
+ return INIT_PASS;
+}
+#endif
+
+
+
+/*************************************
+ *
+ * Atari 5200 console
+ *
+ *************************************/
+
+MACHINE_START( a5200 )
+{
+ atari_machine_start(ATARI_800XL, NULL, FALSE);
+}
+
+
+
+#ifdef MESS
+DEVICE_LOAD( a5200_cart )
+{
+ UINT8 *mem = memory_region(REGION_CPU1);
+ int size;
+
+ /* load an optional (dual) cartidge */
+ size = image_fread(image, &mem[0x4000], 0x8000);
+ if (size<0x8000) memmove(mem+0x4000+0x8000-size, mem+0x4000, size);
+ // mirroring of smaller cartridges
+ if (size <= 0x1000) memcpy(mem+0xa000, mem+0xb000, 0x1000);
+ if (size <= 0x2000) memcpy(mem+0x8000, mem+0xa000, 0x2000);
+ if (size <= 0x4000)
+ {
+ const char *info;
+ memcpy(&mem[0x4000], &mem[0x8000], 0x4000);
+ info = image_extrainfo(image);
+ if (info!=NULL && strcmp(info, "A13MIRRORING")==0)
+ {
+ memcpy(&mem[0x8000], &mem[0xa000], 0x2000);
+ memcpy(&mem[0x6000], &mem[0x4000], 0x2000);
+ }
+ }
+ logerror("%s loaded cartridge '%s' size %dK\n",
+ Machine->gamedrv->name, image_filename(image) , size/1024);
+ return INIT_PASS;
+}
+
+DEVICE_UNLOAD( a5200_cart )
+{
+ UINT8 *mem = memory_region(REGION_CPU1);
+ /* zap the cartridge memory (again) */
+ memset(&mem[0x4000], 0x00, 0x8000);
+}
+#endif
+
diff --git a/src/mame/machine/atari_vg.c b/src/mame/machine/atari_vg.c
new file mode 100644
index 00000000000..382db18c0b2
--- /dev/null
+++ b/src/mame/machine/atari_vg.c
@@ -0,0 +1,68 @@
+/***************************************************************************
+
+ Atari vector hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "atari_vg.h"
+
+#define EAROM_SIZE 0x40
+
+static int earom_offset;
+static int earom_data;
+static char earom[EAROM_SIZE];
+
+
+READ8_HANDLER( atari_vg_earom_r )
+{
+ logerror("read earom: %02x(%02x):%02x\n", earom_offset, offset, earom_data);
+ return (earom_data);
+}
+
+
+WRITE8_HANDLER( atari_vg_earom_w )
+{
+ logerror("write earom: %02x:%02x\n", offset, data);
+ earom_offset = offset;
+ earom_data = data;
+}
+
+
+/* 0,8 and 14 get written to this location, too.
+ * Don't know what they do exactly
+ */
+WRITE8_HANDLER( atari_vg_earom_ctrl_w )
+{
+ logerror("earom ctrl: %02x:%02x\n",offset, data);
+ /*
+ 0x01 = clock
+ 0x02 = set data latch? - writes only (not always)
+ 0x04 = write mode? - writes only
+ 0x08 = set addr latch?
+ */
+ if (data & 0x01)
+ earom_data = earom[earom_offset];
+ if ((data & 0x0c) == 0x0c)
+ {
+ earom[earom_offset]=earom_data;
+ logerror(" written %02x:%02x\n", earom_offset, earom_data);
+ }
+}
+
+
+NVRAM_HANDLER( atari_vg )
+{
+ if (read_or_write)
+ mame_fwrite(file,earom,EAROM_SIZE);
+ else if (file)
+ mame_fread(file,earom,EAROM_SIZE);
+ else
+ memset(earom,0,EAROM_SIZE);
+}
+
+void atari_vg_register_states(void)
+{
+ state_save_register_global(earom_offset);
+ state_save_register_global(earom_data);
+}
diff --git a/src/mame/machine/atari_vg.h b/src/mame/machine/atari_vg.h
new file mode 100644
index 00000000000..3f2a127c363
--- /dev/null
+++ b/src/mame/machine/atari_vg.h
@@ -0,0 +1,13 @@
+/***************************************************************************
+
+ Atari vector hardware
+
+***************************************************************************/
+
+READ8_HANDLER( atari_vg_earom_r );
+WRITE8_HANDLER( atari_vg_earom_w );
+WRITE8_HANDLER( atari_vg_earom_ctrl_w );
+
+NVRAM_HANDLER( atari_vg );
+
+void atari_vg_register_states(void);
diff --git a/src/mame/machine/atarifb.c b/src/mame/machine/atarifb.c
new file mode 100644
index 00000000000..a52deecb513
--- /dev/null
+++ b/src/mame/machine/atarifb.c
@@ -0,0 +1,304 @@
+/*************************************************************************
+
+ Atari Football hardware
+
+*************************************************************************/
+
+#include "driver.h"
+#include "atarifb.h"
+#include "sound/discrete.h"
+
+static int CTRLD;
+static int sign_x_1, sign_y_1;
+static int sign_x_2, sign_y_2;
+static int sign_x_3, sign_y_3;
+static int sign_x_4, sign_y_4;
+
+
+WRITE8_HANDLER( atarifb_out1_w )
+{
+ CTRLD = data;
+
+ discrete_sound_w(ATARIFB_WHISTLE_EN, data & 0x01); // Whistle
+ discrete_sound_w(ATARIFB_HIT_EN, data & 0x02); // Hit
+ discrete_sound_w(ATARIFB_ATTRACT_EN, data & 0x10); // Attract
+ discrete_sound_w(ATARIFB_NOISE_EN, data & 0x04); // Noise Enable / Kicker
+
+ if (GAME_IS_SOCCER)
+ {
+ /* bit 0 = whistle */
+ /* bit 1 = hit */
+ /* bit 2 = kicker */
+ /* bit 3 = unused */
+ /* bit 4 = 2/4 Player LED */ // Say what?
+ /* bit 5-6 = trackball CTRL bits */
+ /* bit 7 = Rule LED */
+// set_led_status(0,data & 0x10); // !!!!!!!!!! Is this correct????
+ set_led_status(1,data & 0x80);
+ }
+
+ if (GAME_IS_FOOTBALL4)
+ coin_counter_w (1, data & 0x80);
+
+ if (GAME_IS_BASEBALL)
+ {
+ if (data & 0x80)
+ {
+ /* Invert video */
+ palette_set_color(Machine,2,MAKE_RGB(0x00,0x00,0x00)); /* black */
+ palette_set_color(Machine,0,MAKE_RGB(0xff,0xff,0xff)); /* white */
+ }
+ else
+ {
+ /* Regular video */
+ palette_set_color(Machine,0,MAKE_RGB(0x00,0x00,0x00)); /* black */
+ palette_set_color(Machine,2,MAKE_RGB(0xff,0xff,0xff)); /* white */
+ }
+ }
+}
+
+
+WRITE8_HANDLER( atarifb_out2_w )
+{
+ discrete_sound_w(ATARIFB_CROWD_DATA, data & 0x0f); // Crowd
+
+ coin_counter_w (0, data & 0x10);
+
+ if (GAME_IS_SOCCER)
+ {
+ coin_counter_w (1, data & 0x20);
+ coin_counter_w (2, data & 0x40);
+ }
+}
+
+
+/*************************************
+ *
+ * LED control
+ *
+ *************************************/
+
+WRITE8_HANDLER( atarifb_out3_w )
+{
+ int loop = cpu_getiloops();
+
+ switch (loop)
+ {
+ case 0x00:
+ /* Player 1 play select lamp */
+ output_set_value("ledleft0", (data >> 0) & 1);
+ output_set_value("ledleft1", (data >> 1) & 1);
+ output_set_value("ledleft2", (data >> 2) & 1);
+ output_set_value("ledleft3", (data >> 3) & 1);
+ output_set_value("ledleft4", (data >> 4) & 1);
+ break;
+ case 0x01:
+ break;
+ case 0x02:
+ /* Player 2 play select lamp */
+ output_set_value("ledright0", (data >> 0) & 1);
+ output_set_value("ledright1", (data >> 1) & 1);
+ output_set_value("ledright2", (data >> 2) & 1);
+ output_set_value("ledright3", (data >> 3) & 1);
+ output_set_value("ledright4", (data >> 4) & 1);
+ break;
+ case 0x03:
+ break;
+ }
+// logerror("out3_w, %02x:%02x\n", loop, data);
+}
+
+
+READ8_HANDLER( atarifb_in0_r )
+{
+ if ((CTRLD & 0x20)==0x00)
+ {
+ int val;
+
+ val = (sign_y_2 >> 7) |
+ (sign_x_2 >> 6) |
+ (sign_y_1 >> 5) |
+ (sign_x_1 >> 4) |
+ input_port_0_r(offset);
+ return val;
+ }
+ else
+ {
+ static int counter_x,counter_y;
+ int new_x,new_y;
+
+ /* Read player 1 trackball */
+ new_x = readinputport(3);
+ if (new_x != counter_x)
+ {
+ sign_x_1 = (new_x - counter_x) & 0x80;
+ counter_x = new_x;
+ }
+
+ new_y = readinputport(2);
+ if (new_y != counter_y)
+ {
+ sign_y_1 = (new_y - counter_y) & 0x80;
+ counter_y = new_y;
+ }
+
+ return (((counter_y & 0x0f) << 4) | (counter_x & 0x0f));
+ }
+}
+
+
+READ8_HANDLER( atarifb_in2_r )
+{
+ if ((CTRLD & 0x20)==0x00)
+ {
+ return input_port_1_r(offset);
+ }
+ else
+ {
+ static int counter_x,counter_y;
+ int new_x,new_y;
+
+ /* Read player 2 trackball */
+ new_x = readinputport(5);
+ if (new_x != counter_x)
+ {
+ sign_x_2 = (new_x - counter_x) & 0x80;
+ counter_x = new_x;
+ }
+
+ new_y = readinputport(4);
+ if (new_y != counter_y)
+ {
+ sign_y_2 = (new_y - counter_y) & 0x80;
+ counter_y = new_y;
+ }
+
+ return (((counter_y & 0x0f) << 4) | (counter_x & 0x0f));
+ }
+}
+
+READ8_HANDLER( atarifb4_in0_r )
+{
+ /* LD1 and LD2 low, return sign bits */
+ if ((CTRLD & 0x60)==0x00)
+ {
+ int val;
+
+ val = (sign_x_4 >> 7) |
+ (sign_y_4 >> 6) |
+ (sign_x_2 >> 5) |
+ (sign_y_2 >> 4) |
+ (sign_x_3 >> 3) |
+ (sign_y_3 >> 2) |
+ (sign_x_1 >> 1) |
+ (sign_y_1 >> 0);
+ return val;
+ }
+ else if ((CTRLD & 0x60) == 0x60)
+ /* LD1 and LD2 both high, return Team 1 right player (player 1) */
+ {
+ static int counter_x,counter_y;
+ int new_x,new_y;
+
+ /* Read player 1 trackball */
+ new_x = readinputport(4);
+ if (new_x != counter_x)
+ {
+ sign_x_1 = (new_x - counter_x) & 0x80;
+ counter_x = new_x;
+ }
+
+ new_y = readinputport(3);
+ if (new_y != counter_y)
+ {
+ sign_y_1 = (new_y - counter_y) & 0x80;
+ counter_y = new_y;
+ }
+
+ return (((counter_y & 0x0f) << 4) | (counter_x & 0x0f));
+ }
+ else if ((CTRLD & 0x60) == 0x40)
+ /* LD1 high, LD2 low, return Team 1 left player (player 2) */
+ {
+ static int counter_x,counter_y;
+ int new_x,new_y;
+
+ /* Read player 2 trackball */
+ new_x = readinputport(6);
+ if (new_x != counter_x)
+ {
+ sign_x_2 = (new_x - counter_x) & 0x80;
+ counter_x = new_x;
+ }
+
+ new_y = readinputport(5);
+ if (new_y != counter_y)
+ {
+ sign_y_2 = (new_y - counter_y) & 0x80;
+ counter_y = new_y;
+ }
+
+ return (((counter_y & 0x0f) << 4) | (counter_x & 0x0f));
+ }
+
+ else return 0;
+}
+
+
+READ8_HANDLER( atarifb4_in2_r )
+{
+ if ((CTRLD & 0x40)==0x00)
+ {
+ return input_port_2_r(offset);
+ }
+ else if ((CTRLD & 0x60) == 0x60)
+ /* LD1 and LD2 both high, return Team 2 right player (player 3) */
+ {
+ static int counter_x,counter_y;
+ int new_x,new_y;
+
+ /* Read player 3 trackball */
+ new_x = readinputport(8);
+ if (new_x != counter_x)
+ {
+ sign_x_3 = (new_x - counter_x) & 0x80;
+ counter_x = new_x;
+ }
+
+ new_y = readinputport(7);
+ if (new_y != counter_y)
+ {
+ sign_y_3 = (new_y - counter_y) & 0x80;
+ counter_y = new_y;
+ }
+
+ return (((counter_y & 0x0f) << 4) | (counter_x & 0x0f));
+ }
+ else if ((CTRLD & 0x60) == 0x40)
+ /* LD1 high, LD2 low, return Team 2 left player (player 4) */
+ {
+ static int counter_x,counter_y;
+ int new_x,new_y;
+
+ /* Read player 4 trackball */
+ new_x = readinputport(10);
+ if (new_x != counter_x)
+ {
+ sign_x_4 = (new_x - counter_x) & 0x80;
+ counter_x = new_x;
+ }
+
+ new_y = readinputport(9);
+ if (new_y != counter_y)
+ {
+ sign_y_4 = (new_y - counter_y) & 0x80;
+ counter_y = new_y;
+ }
+
+ return (((counter_y & 0x0f) << 4) | (counter_x & 0x0f));
+ }
+
+ else return 0;
+}
+
+
diff --git a/src/mame/machine/atarigen.c b/src/mame/machine/atarigen.c
new file mode 100644
index 00000000000..ddff7ce6da5
--- /dev/null
+++ b/src/mame/machine/atarigen.c
@@ -0,0 +1,1500 @@
+/*##########################################################################
+
+ atarigen.c
+
+ General functions for Atari raster games.
+
+##########################################################################*/
+
+
+#include "driver.h"
+#include "atarigen.h"
+#include "slapstic.h"
+#include "cpu/m6502/m6502.h"
+
+
+
+/*##########################################################################
+ CONSTANTS
+##########################################################################*/
+
+#define SOUND_TIMER_RATE ATTOTIME_IN_USEC(5)
+#define SOUND_TIMER_BOOST ATTOTIME_IN_USEC(100)
+
+
+
+/*##########################################################################
+ GLOBAL VARIABLES
+##########################################################################*/
+
+UINT8 atarigen_scanline_int_state;
+UINT8 atarigen_sound_int_state;
+UINT8 atarigen_video_int_state;
+
+const UINT16 * atarigen_eeprom_default;
+UINT16 * atarigen_eeprom;
+size_t atarigen_eeprom_size;
+
+UINT8 atarigen_cpu_to_sound_ready;
+UINT8 atarigen_sound_to_cpu_ready;
+
+UINT16 * atarigen_playfield;
+UINT16 * atarigen_playfield2;
+UINT16 * atarigen_playfield_upper;
+UINT16 * atarigen_alpha;
+UINT16 * atarigen_alpha2;
+UINT16 * atarigen_xscroll;
+UINT16 * atarigen_yscroll;
+
+UINT32 * atarigen_playfield32;
+UINT32 * atarigen_alpha32;
+
+tilemap * atarigen_playfield_tilemap;
+tilemap * atarigen_playfield2_tilemap;
+tilemap * atarigen_alpha_tilemap;
+tilemap * atarigen_alpha2_tilemap;
+
+UINT16 * atarivc_data;
+UINT16 * atarivc_eof_data;
+struct atarivc_state_desc atarivc_state;
+
+
+
+/*##########################################################################
+ STATIC VARIABLES
+##########################################################################*/
+
+static atarigen_int_callback update_int_callback;
+static emu_timer * scanline_interrupt_timer;
+
+static UINT8 eeprom_unlocked;
+
+static UINT8 atarigen_slapstic_num;
+static UINT16 * atarigen_slapstic;
+static UINT32 atarigen_slapstic_bank;
+static void * atarigen_slapstic_bank0;
+
+static UINT8 sound_cpu_num;
+static UINT8 atarigen_cpu_to_sound;
+static UINT8 atarigen_sound_to_cpu;
+static UINT8 timed_int;
+static UINT8 ym2151_int;
+
+static atarigen_scanline_callback scanline_callback;
+static UINT32 scanlines_per_callback;
+
+static UINT32 actual_vc_latch0;
+static UINT32 actual_vc_latch1;
+static UINT8 atarivc_playfields;
+
+static UINT32 playfield_latch;
+static UINT32 playfield2_latch;
+
+static emu_timer * scanline_timer[ATARIMO_MAX];
+static emu_timer * atarivc_eof_update_timer[ATARIMO_MAX];
+
+
+
+/*##########################################################################
+ STATIC FUNCTION DECLARATIONS
+##########################################################################*/
+
+static TIMER_CALLBACK( scanline_interrupt_callback );
+
+static void decompress_eeprom_word(const UINT16 *data);
+static void decompress_eeprom_byte(const UINT16 *data);
+
+static void update_6502_irq(void);
+static TIMER_CALLBACK( delayed_sound_reset );
+static TIMER_CALLBACK( delayed_sound_w );
+static TIMER_CALLBACK( delayed_6502_sound_w );
+
+static void atarigen_set_vol(running_machine *machine, int volume, sound_type type);
+
+static TIMER_CALLBACK( scanline_timer_callback );
+
+static void atarivc_common_w(int scrnum, offs_t offset, UINT16 newword);
+
+static TIMER_CALLBACK( unhalt_cpu );
+
+static TIMER_CALLBACK( atarivc_eof_update );
+
+
+
+/*##########################################################################
+ INTERRUPT HANDLING
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_interrupt_reset: Initializes the state of all
+ the interrupt sources.
+---------------------------------------------------------------*/
+
+void atarigen_interrupt_reset(atarigen_int_callback update_int)
+{
+ int i;
+
+ /* set the callback */
+ update_int_callback = update_int;
+
+ /* reset the interrupt states */
+ atarigen_video_int_state = atarigen_sound_int_state = atarigen_scanline_int_state = 0;
+ scanline_interrupt_timer = NULL;
+
+ /* create timers */
+ for (i = 0; i < ATARIMO_MAX; i++)
+ scanline_timer[i] = timer_alloc(scanline_timer_callback);
+
+ /* create a timer for scanlines */
+ scanline_interrupt_timer = timer_alloc(scanline_interrupt_callback);
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_update_interrupts: Forces the interrupt callback
+ to be called with the current VBLANK and sound interrupt
+ states.
+---------------------------------------------------------------*/
+
+void atarigen_update_interrupts(void)
+{
+ (*update_int_callback)();
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_scanline_int_set: Sets the scanline when the next
+ scanline interrupt should be generated.
+---------------------------------------------------------------*/
+
+void atarigen_scanline_int_set(int scrnum, int scanline)
+{
+ timer_adjust(scanline_interrupt_timer, video_screen_get_time_until_pos(scrnum, scanline, 0), scrnum, attotime_zero);
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_scanline_int_gen: Standard interrupt routine
+ which sets the scanline interrupt state.
+---------------------------------------------------------------*/
+
+INTERRUPT_GEN( atarigen_scanline_int_gen )
+{
+ atarigen_scanline_int_state = 1;
+ (*update_int_callback)();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_scanline_int_ack_w: Resets the state of the
+ scanline interrupt.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_scanline_int_ack_w )
+{
+ atarigen_scanline_int_state = 0;
+ (*update_int_callback)();
+}
+
+WRITE32_HANDLER( atarigen_scanline_int_ack32_w )
+{
+ atarigen_scanline_int_state = 0;
+ (*update_int_callback)();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_sound_int_gen: Standard interrupt routine which
+ sets the sound interrupt state.
+---------------------------------------------------------------*/
+
+INTERRUPT_GEN( atarigen_sound_int_gen )
+{
+ atarigen_sound_int_state = 1;
+ (*update_int_callback)();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_sound_int_ack_w: Resets the state of the sound
+ interrupt.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_sound_int_ack_w )
+{
+ atarigen_sound_int_state = 0;
+ (*update_int_callback)();
+}
+
+WRITE32_HANDLER( atarigen_sound_int_ack32_w )
+{
+ atarigen_sound_int_state = 0;
+ (*update_int_callback)();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_video_int_gen: Standard interrupt routine which
+ sets the video interrupt state.
+---------------------------------------------------------------*/
+
+INTERRUPT_GEN( atarigen_video_int_gen )
+{
+ atarigen_video_int_state = 1;
+ (*update_int_callback)();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_video_int_ack_w: Resets the state of the video
+ interrupt.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_video_int_ack_w )
+{
+ atarigen_video_int_state = 0;
+ (*update_int_callback)();
+}
+
+WRITE32_HANDLER( atarigen_video_int_ack32_w )
+{
+ atarigen_video_int_state = 0;
+ (*update_int_callback)();
+}
+
+
+/*---------------------------------------------------------------
+ scanline_interrupt_callback: Signals an interrupt.
+---------------------------------------------------------------*/
+
+static TIMER_CALLBACK( scanline_interrupt_callback )
+{
+ /* generate the interrupt */
+ atarigen_scanline_int_gen();
+
+ /* set a new timer to go off at the same scan line next frame */
+ timer_adjust(scanline_interrupt_timer, video_screen_get_frame_period(param), param, attotime_zero);
+}
+
+
+
+/*##########################################################################
+ EEPROM HANDLING
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_eeprom_reset: Makes sure that the unlocked state
+ is cleared when we reset.
+---------------------------------------------------------------*/
+
+void atarigen_eeprom_reset(void)
+{
+ eeprom_unlocked = 0;
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_eeprom_enable_w: Any write to this handler will
+ allow one byte to be written to the EEPROM data area the
+ next time.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_eeprom_enable_w )
+{
+ eeprom_unlocked = 1;
+}
+
+WRITE32_HANDLER( atarigen_eeprom_enable32_w )
+{
+ eeprom_unlocked = 1;
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_eeprom_w: Writes a "word" to the EEPROM, which is
+ almost always accessed via the low byte of the word only.
+ If the EEPROM hasn't been unlocked, the write attempt is
+ ignored.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_eeprom_w )
+{
+ if (!eeprom_unlocked)
+ return;
+
+ COMBINE_DATA(&atarigen_eeprom[offset]);
+ eeprom_unlocked = 0;
+}
+
+WRITE32_HANDLER( atarigen_eeprom32_w )
+{
+ if (!eeprom_unlocked)
+ return;
+
+ COMBINE_DATA(&atarigen_eeprom[offset * 2 + 1]);
+ data >>= 16;
+ mem_mask >>= 16;
+ COMBINE_DATA(&atarigen_eeprom[offset * 2]);
+ eeprom_unlocked = 0;
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_eeprom_r: Reads a "word" from the EEPROM, which is
+ almost always accessed via the low byte of the word only.
+---------------------------------------------------------------*/
+
+READ16_HANDLER( atarigen_eeprom_r )
+{
+ return atarigen_eeprom[offset] | 0xff00;
+}
+
+READ16_HANDLER( atarigen_eeprom_upper_r )
+{
+ return atarigen_eeprom[offset] | 0x00ff;
+}
+
+READ32_HANDLER( atarigen_eeprom_upper32_r )
+{
+ return (atarigen_eeprom[offset * 2] << 16) | atarigen_eeprom[offset * 2 + 1] | 0x00ff00ff;
+}
+
+
+/*---------------------------------------------------------------
+ nvram_handler_atarigen: Loads the EEPROM data.
+---------------------------------------------------------------*/
+
+NVRAM_HANDLER( atarigen )
+{
+ if (read_or_write)
+ mame_fwrite(file, atarigen_eeprom, atarigen_eeprom_size);
+ else if (file)
+ mame_fread(file, atarigen_eeprom, atarigen_eeprom_size);
+ else
+ {
+ /* all 0xff's work for most games */
+ memset(atarigen_eeprom, 0xff, atarigen_eeprom_size);
+
+ /* anything else must be decompressed */
+ if (atarigen_eeprom_default)
+ {
+ if (atarigen_eeprom_default[0] == 0)
+ decompress_eeprom_byte(atarigen_eeprom_default + 1);
+ else
+ decompress_eeprom_word(atarigen_eeprom_default + 1);
+ }
+ }
+}
+
+
+/*---------------------------------------------------------------
+ decompress_eeprom_word: Used for decompressing EEPROM data
+ that has every other byte invalid.
+---------------------------------------------------------------*/
+
+void decompress_eeprom_word(const UINT16 *data)
+{
+ UINT16 *dest = (UINT16 *)atarigen_eeprom;
+ UINT16 value;
+
+ while ((value = *data++) != 0)
+ {
+ int count = (value >> 8);
+ value = (value << 8) | (value & 0xff);
+
+ while (count--)
+ *dest++ = value;
+ }
+}
+
+
+/*---------------------------------------------------------------
+ decompress_eeprom_byte: Used for decompressing EEPROM data
+ that is byte-packed.
+---------------------------------------------------------------*/
+
+void decompress_eeprom_byte(const UINT16 *data)
+{
+ UINT8 *dest = (UINT8 *)atarigen_eeprom;
+ UINT16 value;
+
+ while ((value = *data++) != 0)
+ {
+ int count = (value >> 8);
+ value = (value << 8) | (value & 0xff);
+
+ while (count--)
+ *dest++ = value;
+ }
+}
+
+
+
+/*##########################################################################
+ SLAPSTIC HANDLING
+##########################################################################*/
+
+INLINE void update_bank(int bank)
+{
+ /* if the bank has changed, copy the memory; Pit Fighter needs this */
+ if (bank != atarigen_slapstic_bank)
+ {
+ /* bank 0 comes from the copy we made earlier */
+ if (bank == 0)
+ memcpy(atarigen_slapstic, atarigen_slapstic_bank0, 0x2000);
+ else
+ memcpy(atarigen_slapstic, &atarigen_slapstic[bank * 0x1000], 0x2000);
+
+ /* remember the current bank */
+ atarigen_slapstic_bank = bank;
+ }
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_slapstic_init: Installs memory handlers for the
+ slapstic and sets the chip number.
+---------------------------------------------------------------*/
+
+void atarigen_slapstic_init(int cpunum, int base, int chipnum)
+{
+ atarigen_slapstic_num = chipnum;
+ atarigen_slapstic = NULL;
+
+ /* if we have a chip, install it */
+ if (chipnum)
+ {
+ /* initialize the slapstic */
+ slapstic_init(chipnum);
+
+ /* install the memory handlers */
+ atarigen_slapstic = memory_install_read16_handler(cpunum, ADDRESS_SPACE_PROGRAM, base, base + 0x7fff, 0, 0, atarigen_slapstic_r);
+ atarigen_slapstic = memory_install_write16_handler(cpunum, ADDRESS_SPACE_PROGRAM, base, base + 0x7fff, 0, 0, atarigen_slapstic_w);
+
+ /* allocate memory for a copy of bank 0 */
+ atarigen_slapstic_bank0 = auto_malloc(0x2000);
+ memcpy(atarigen_slapstic_bank0, atarigen_slapstic, 0x2000);
+ }
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_slapstic_reset: Makes the selected slapstic number
+ active and resets its state.
+---------------------------------------------------------------*/
+
+void atarigen_slapstic_reset(void)
+{
+ if (atarigen_slapstic_num)
+ {
+ slapstic_reset();
+ update_bank(slapstic_bank());
+ }
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_slapstic_w: Assuming that the slapstic sits in
+ ROM memory space, we just simply tweak the slapstic at this
+ address and do nothing more.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_slapstic_w )
+{
+ update_bank(slapstic_tweak(offset));
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_slapstic_r: Tweaks the slapstic at the appropriate
+ address and then reads a word from the underlying memory.
+---------------------------------------------------------------*/
+
+READ16_HANDLER( atarigen_slapstic_r )
+{
+ /* fetch the result from the current bank first */
+ int result = atarigen_slapstic[offset & 0xfff];
+
+ /* then determine the new one */
+ update_bank(slapstic_tweak(offset));
+ return result;
+}
+
+
+
+/*##########################################################################
+ SOUND I/O
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_sound_io_reset: Resets the state of the sound I/O.
+---------------------------------------------------------------*/
+
+void atarigen_sound_io_reset(int cpu_num)
+{
+ /* remember which CPU is the sound CPU */
+ sound_cpu_num = cpu_num;
+
+ /* reset the internal interrupts states */
+ timed_int = ym2151_int = 0;
+
+ /* reset the sound I/O states */
+ atarigen_cpu_to_sound = atarigen_sound_to_cpu = 0;
+ atarigen_cpu_to_sound_ready = atarigen_sound_to_cpu_ready = 0;
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_6502_irq_gen: Generates an IRQ signal to the 6502
+ sound processor.
+---------------------------------------------------------------*/
+
+INTERRUPT_GEN( atarigen_6502_irq_gen )
+{
+ timed_int = 1;
+ update_6502_irq();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_6502_irq_ack_r: Resets the IRQ signal to the 6502
+ sound processor. Both reads and writes can be used.
+---------------------------------------------------------------*/
+
+READ8_HANDLER( atarigen_6502_irq_ack_r )
+{
+ timed_int = 0;
+ update_6502_irq();
+ return 0;
+}
+
+WRITE8_HANDLER( atarigen_6502_irq_ack_w )
+{
+ timed_int = 0;
+ update_6502_irq();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_ym2151_irq_gen: Sets the state of the YM2151's
+ IRQ line.
+---------------------------------------------------------------*/
+
+void atarigen_ym2151_irq_gen(int irq)
+{
+ ym2151_int = irq;
+ update_6502_irq();
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_sound_reset_w: Write handler which resets the
+ sound CPU in response.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_sound_reset_w )
+{
+ timer_call_after_resynch(0, delayed_sound_reset);
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_sound_reset: Resets the state of the sound CPU
+ manually.
+---------------------------------------------------------------*/
+
+void atarigen_sound_reset(void)
+{
+ timer_call_after_resynch(1, delayed_sound_reset);
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_sound_w: Handles communication from the main CPU
+ to the sound CPU. Two versions are provided, one with the
+ data byte in the low 8 bits, and one with the data byte in
+ the upper 8 bits.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_sound_w )
+{
+ if (ACCESSING_LSB)
+ timer_call_after_resynch(data & 0xff, delayed_sound_w);
+}
+
+WRITE16_HANDLER( atarigen_sound_upper_w )
+{
+ if (ACCESSING_MSB)
+ timer_call_after_resynch((data >> 8) & 0xff, delayed_sound_w);
+}
+
+WRITE32_HANDLER( atarigen_sound_upper32_w )
+{
+ if (ACCESSING_MSB32)
+ timer_call_after_resynch((data >> 24) & 0xff, delayed_sound_w);
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_sound_r: Handles reading data communicated from the
+ sound CPU to the main CPU. Two versions are provided, one
+ with the data byte in the low 8 bits, and one with the data
+ byte in the upper 8 bits.
+---------------------------------------------------------------*/
+
+READ16_HANDLER( atarigen_sound_r )
+{
+ atarigen_sound_to_cpu_ready = 0;
+ atarigen_sound_int_ack_w(0, 0, 0);
+ return atarigen_sound_to_cpu | 0xff00;
+}
+
+READ16_HANDLER( atarigen_sound_upper_r )
+{
+ atarigen_sound_to_cpu_ready = 0;
+ atarigen_sound_int_ack_w(0, 0, 0);
+ return (atarigen_sound_to_cpu << 8) | 0x00ff;
+}
+
+READ32_HANDLER( atarigen_sound_upper32_r )
+{
+ atarigen_sound_to_cpu_ready = 0;
+ atarigen_sound_int_ack32_w(0, 0, 0);
+ return (atarigen_sound_to_cpu << 24) | 0x00ffffff;
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_6502_sound_w: Handles communication from the sound
+ CPU to the main CPU.
+---------------------------------------------------------------*/
+
+WRITE8_HANDLER( atarigen_6502_sound_w )
+{
+ timer_call_after_resynch(data, delayed_6502_sound_w);
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_6502_sound_r: Handles reading data communicated
+ from the main CPU to the sound CPU.
+---------------------------------------------------------------*/
+
+READ8_HANDLER( atarigen_6502_sound_r )
+{
+ atarigen_cpu_to_sound_ready = 0;
+ cpunum_set_input_line(sound_cpu_num, INPUT_LINE_NMI, CLEAR_LINE);
+ return atarigen_cpu_to_sound;
+}
+
+
+/*---------------------------------------------------------------
+ update_6502_irq: Called whenever the IRQ state changes. An
+ interrupt is generated if either atarigen_6502_irq_gen()
+ was called, or if the YM2151 generated an interrupt via
+ the atarigen_ym2151_irq_gen() callback.
+---------------------------------------------------------------*/
+
+void update_6502_irq(void)
+{
+ if (timed_int || ym2151_int)
+ cpunum_set_input_line(sound_cpu_num, M6502_IRQ_LINE, ASSERT_LINE);
+ else
+ cpunum_set_input_line(sound_cpu_num, M6502_IRQ_LINE, CLEAR_LINE);
+}
+
+
+/*---------------------------------------------------------------
+ delayed_sound_reset: Synchronizes the sound reset command
+ between the two CPUs.
+---------------------------------------------------------------*/
+
+static TIMER_CALLBACK( delayed_sound_reset )
+{
+ /* unhalt and reset the sound CPU */
+ if (param == 0)
+ {
+ cpunum_set_input_line(sound_cpu_num, INPUT_LINE_HALT, CLEAR_LINE);
+ cpunum_set_input_line(sound_cpu_num, INPUT_LINE_RESET, PULSE_LINE);
+ }
+
+ /* reset the sound write state */
+ atarigen_sound_to_cpu_ready = 0;
+ atarigen_sound_int_ack_w(0, 0, 0);
+}
+
+
+/*---------------------------------------------------------------
+ delayed_sound_w: Synchronizes a data write from the main
+ CPU to the sound CPU.
+---------------------------------------------------------------*/
+
+static TIMER_CALLBACK( delayed_sound_w )
+{
+ /* warn if we missed something */
+ if (atarigen_cpu_to_sound_ready)
+ logerror("Missed command from 68010\n");
+
+ /* set up the states and signal an NMI to the sound CPU */
+ atarigen_cpu_to_sound = param;
+ atarigen_cpu_to_sound_ready = 1;
+ cpunum_set_input_line(sound_cpu_num, INPUT_LINE_NMI, ASSERT_LINE);
+
+ /* allocate a high frequency timer until a response is generated */
+ /* the main CPU is *very* sensistive to the timing of the response */
+ cpu_boost_interleave(SOUND_TIMER_RATE, SOUND_TIMER_BOOST);
+}
+
+
+/*---------------------------------------------------------------
+ delayed_6502_sound_w: Synchronizes a data write from the
+ sound CPU to the main CPU.
+---------------------------------------------------------------*/
+
+static TIMER_CALLBACK( delayed_6502_sound_w )
+{
+ /* warn if we missed something */
+ if (atarigen_sound_to_cpu_ready)
+ logerror("Missed result from 6502\n");
+
+ /* set up the states and signal the sound interrupt to the main CPU */
+ atarigen_sound_to_cpu = param;
+ atarigen_sound_to_cpu_ready = 1;
+ atarigen_sound_int_gen();
+}
+
+
+
+/*##########################################################################
+ SOUND HELPERS
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_set_vol: Scans for a particular sound chip and
+ changes the volume on all channels associated with it.
+---------------------------------------------------------------*/
+
+void atarigen_set_vol(running_machine *machine, int volume, sound_type type)
+{
+ int sndindex = 0;
+ int ch;
+
+ for (ch = 0; ch < MAX_SOUND; ch++)
+ if (machine->drv->sound[ch].type == type)
+ {
+ int output;
+ for (output = 0; output < 2; output++)
+ sndti_set_output_gain(type, sndindex, output, volume / 100.0);
+ sndindex++;
+ }
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_set_XXXXX_vol: Sets the volume for a given type
+ of chip.
+---------------------------------------------------------------*/
+
+void atarigen_set_ym2151_vol(running_machine *machine, int volume)
+{
+ atarigen_set_vol(machine, volume, SOUND_YM2151);
+}
+
+void atarigen_set_ym2413_vol(running_machine *machine, int volume)
+{
+ atarigen_set_vol(machine, volume, SOUND_YM2413);
+}
+
+void atarigen_set_pokey_vol(running_machine *machine, int volume)
+{
+ atarigen_set_vol(machine, volume, SOUND_POKEY);
+}
+
+void atarigen_set_tms5220_vol(running_machine *machine, int volume)
+{
+ atarigen_set_vol(machine, volume, SOUND_TMS5220);
+}
+
+void atarigen_set_oki6295_vol(running_machine *machine, int volume)
+{
+ atarigen_set_vol(machine, volume, SOUND_OKIM6295);
+}
+
+
+
+/*##########################################################################
+ SCANLINE TIMING
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_scanline_timer_reset: Sets up the scanline timer.
+---------------------------------------------------------------*/
+
+void atarigen_scanline_timer_reset(int scrnum, atarigen_scanline_callback update_graphics, int frequency)
+{
+ /* set the scanline callback */
+ scanline_callback = update_graphics;
+ scanlines_per_callback = frequency;
+
+ /* set a timer to go off at scanline 0 */
+ if (scanline_callback != NULL)
+ timer_adjust(scanline_timer[scrnum], video_screen_get_time_until_pos(scrnum, 0, 0), (scrnum << 16) | 0, attotime_zero);
+}
+
+
+/*---------------------------------------------------------------
+ scanline_timer: Called once every n scanlines to generate
+ the periodic callback to the main system.
+---------------------------------------------------------------*/
+
+static TIMER_CALLBACK( scanline_timer_callback )
+{
+ int scanline = param & 0x0fff;
+ int scrnum = param >> 16;
+
+ /* callback */
+ if (scanline_callback != NULL)
+ {
+ (*scanline_callback)(machine, scrnum, scanline);
+
+ /* generate another */
+ scanline += scanlines_per_callback;
+ if (scanline >= machine->screen[scrnum].height)
+ scanline = 0;
+ timer_adjust(scanline_timer[scrnum], video_screen_get_time_until_pos(scrnum, scanline, 0), (scrnum << 16) | scanline, attotime_zero);
+ }
+}
+
+
+
+/*##########################################################################
+ VIDEO CONTROLLER
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarivc_eof_update: Callback that slurps up data and feeds
+ it into the video controller registers every refresh.
+---------------------------------------------------------------*/
+
+static TIMER_CALLBACK( atarivc_eof_update )
+{
+ int scrnum = param;
+ int i;
+
+ /* echo all the commands to the video controller */
+ for (i = 0; i < 0x1c; i++)
+ if (atarivc_eof_data[i])
+ atarivc_common_w(scrnum, i, atarivc_eof_data[i]);
+
+ /* update the scroll positions */
+ atarimo_set_xscroll(0, atarivc_state.mo_xscroll);
+ atarimo_set_yscroll(0, atarivc_state.mo_yscroll);
+
+ tilemap_set_scrollx(atarigen_playfield_tilemap, 0, atarivc_state.pf0_xscroll);
+ tilemap_set_scrolly(atarigen_playfield_tilemap, 0, atarivc_state.pf0_yscroll);
+
+ if (atarivc_playfields > 1)
+ {
+ tilemap_set_scrollx(atarigen_playfield2_tilemap, 0, atarivc_state.pf1_xscroll);
+ tilemap_set_scrolly(atarigen_playfield2_tilemap, 0, atarivc_state.pf1_yscroll);
+ }
+ timer_adjust(atarivc_eof_update_timer[scrnum], video_screen_get_time_until_pos(scrnum, 0, 0), scrnum, attotime_zero);
+
+ /* use this for debugging the video controller values */
+#if 0
+ if (input_code_pressed(KEYCODE_8))
+ {
+ static FILE *out;
+ if (!out) out = fopen("scroll.log", "w");
+ if (out)
+ {
+ for (i = 0; i < 64; i++)
+ fprintf(out, "%04X ", data[i]);
+ fprintf(out, "\n");
+ }
+ }
+#endif
+}
+
+
+/*---------------------------------------------------------------
+ atarivc_reset: Initializes the video controller.
+---------------------------------------------------------------*/
+
+void atarivc_reset(int scrnum, UINT16 *eof_data, int playfields)
+{
+ /* this allows us to manually reset eof_data to NULL if it's not used */
+ atarivc_eof_data = eof_data;
+ atarivc_playfields = playfields;
+
+ /* clear the RAM we use */
+ memset(atarivc_data, 0, 0x40);
+ memset(&atarivc_state, 0, sizeof(atarivc_state));
+
+ /* reset the latches */
+ atarivc_state.latch1 = atarivc_state.latch2 = -1;
+ actual_vc_latch0 = actual_vc_latch1 = -1;
+
+ atarivc_eof_update_timer[scrnum] = timer_alloc(atarivc_eof_update);
+
+ /* start a timer to go off a little before scanline 0 */
+ if (atarivc_eof_data)
+ timer_adjust(atarivc_eof_update_timer[scrnum], video_screen_get_time_until_pos(scrnum, 0, 0), scrnum, attotime_zero);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarivc_w: Handles an I/O write to the video controller.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarivc_w )
+{
+ int oldword = atarivc_data[offset];
+ int newword = oldword;
+
+ COMBINE_DATA(&newword);
+ atarivc_common_w(0, offset, newword); /* need to support scrnum */
+}
+
+
+
+/*---------------------------------------------------------------
+ atarivc_common_w: Does the bulk of the word for an I/O
+ write.
+---------------------------------------------------------------*/
+
+static void atarivc_common_w(int scrnum, offs_t offset, UINT16 newword)
+{
+ int oldword = atarivc_data[offset];
+ atarivc_data[offset] = newword;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ /*
+ additional registers:
+
+ 01 = vertical start (for centering)
+ 04 = horizontal start (for centering)
+ */
+
+ /* set the scanline interrupt here */
+ case 0x03:
+ if (oldword != newword)
+ atarigen_scanline_int_set(scrnum, newword & 0x1ff);
+ break;
+
+ /* latch enable */
+ case 0x0a:
+
+ /* reset the latches when disabled */
+ atarigen_set_playfield_latch((newword & 0x0080) ? actual_vc_latch0 : -1);
+ atarigen_set_playfield2_latch((newword & 0x0080) ? actual_vc_latch1 : -1);
+
+ /* check for rowscroll enable */
+ atarivc_state.rowscroll_enable = (newword & 0x2000) >> 13;
+
+ /* check for palette banking */
+ if (atarivc_state.palette_bank != (((newword & 0x0400) >> 10) ^ 1))
+ {
+ video_screen_update_partial(scrnum, video_screen_get_vpos(scrnum));
+ atarivc_state.palette_bank = ((newword & 0x0400) >> 10) ^ 1;
+ }
+ break;
+
+ /* indexed parameters */
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ switch (newword & 15)
+ {
+ case 9:
+ atarivc_state.mo_xscroll = (newword >> 7) & 0x1ff;
+ break;
+
+ case 10:
+ atarivc_state.pf1_xscroll_raw = (newword >> 7) & 0x1ff;
+ atarivc_update_pf_xscrolls();
+ break;
+
+ case 11:
+ atarivc_state.pf0_xscroll_raw = (newword >> 7) & 0x1ff;
+ atarivc_update_pf_xscrolls();
+ break;
+
+ case 13:
+ atarivc_state.mo_yscroll = (newword >> 7) & 0x1ff;
+ break;
+
+ case 14:
+ atarivc_state.pf1_yscroll = (newword >> 7) & 0x1ff;
+ break;
+
+ case 15:
+ atarivc_state.pf0_yscroll = (newword >> 7) & 0x1ff;
+ break;
+ }
+ break;
+
+ /* latch 1 value */
+ case 0x1c:
+ actual_vc_latch0 = -1;
+ actual_vc_latch1 = newword;
+ atarigen_set_playfield_latch((atarivc_data[0x0a] & 0x80) ? actual_vc_latch0 : -1);
+ atarigen_set_playfield2_latch((atarivc_data[0x0a] & 0x80) ? actual_vc_latch1 : -1);
+ break;
+
+ /* latch 2 value */
+ case 0x1d:
+ actual_vc_latch0 = newword;
+ actual_vc_latch1 = -1;
+ atarigen_set_playfield_latch((atarivc_data[0x0a] & 0x80) ? actual_vc_latch0 : -1);
+ atarigen_set_playfield2_latch((atarivc_data[0x0a] & 0x80) ? actual_vc_latch1 : -1);
+ break;
+
+ /* scanline IRQ ack here */
+ case 0x1e:
+ atarigen_scanline_int_ack_w(0, 0, 0);
+ break;
+
+ /* log anything else */
+ case 0x00:
+ default:
+ if (oldword != newword)
+ logerror("vc_w(%02X, %04X) ** [prev=%04X]\n", offset, newword, oldword);
+ break;
+ }
+}
+
+
+/*---------------------------------------------------------------
+ atarivc_r: Handles an I/O read from the video controller.
+---------------------------------------------------------------*/
+
+READ16_HANDLER( atarivc_r )
+{
+ logerror("vc_r(%02X)\n", offset);
+
+ /* a read from offset 0 returns the current scanline */
+ /* also sets bit 0x4000 if we're in VBLANK */
+ if (offset == 0)
+ {
+ int result = video_screen_get_vpos(0); /* need to support scrum */
+
+ if (result > 255)
+ result = 255;
+ if (result > Machine->screen[0].visarea.max_y) /* need to support scrum */
+ result |= 0x4000;
+
+ return result;
+ }
+ else
+ return atarivc_data[offset];
+}
+
+
+
+/*##########################################################################
+ PLAYFIELD/ALPHA MAP HELPERS
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_alpha_w: Generic write handler for alpha RAM.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_alpha_w )
+{
+ COMBINE_DATA(&atarigen_alpha[offset]);
+ tilemap_mark_tile_dirty(atarigen_alpha_tilemap, offset);
+}
+
+WRITE32_HANDLER( atarigen_alpha32_w )
+{
+ COMBINE_DATA(&atarigen_alpha32[offset]);
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ tilemap_mark_tile_dirty(atarigen_alpha_tilemap, offset * 2);
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ tilemap_mark_tile_dirty(atarigen_alpha_tilemap, offset * 2 + 1);
+}
+
+WRITE16_HANDLER( atarigen_alpha2_w )
+{
+ COMBINE_DATA(&atarigen_alpha2[offset]);
+ tilemap_mark_tile_dirty(atarigen_alpha2_tilemap, offset);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_set_playfield_latch: Sets the latch for the latched
+ playfield handlers below.
+---------------------------------------------------------------*/
+
+void atarigen_set_playfield_latch(int data)
+{
+ playfield_latch = data;
+}
+
+void atarigen_set_playfield2_latch(int data)
+{
+ playfield2_latch = data;
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_playfield_w: Generic write handler for PF RAM.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_playfield_w )
+{
+ COMBINE_DATA(&atarigen_playfield[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset);
+}
+
+WRITE32_HANDLER( atarigen_playfield32_w )
+{
+ COMBINE_DATA(&atarigen_playfield32[offset]);
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset * 2);
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset * 2 + 1);
+}
+
+WRITE16_HANDLER( atarigen_playfield2_w )
+{
+ COMBINE_DATA(&atarigen_playfield2[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield2_tilemap, offset);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_playfield_large_w: Generic write handler for
+ large (2-word) playfield RAM.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_playfield_large_w )
+{
+ COMBINE_DATA(&atarigen_playfield[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset / 2);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_playfield_upper_w: Generic write handler for
+ upper word of split playfield RAM.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_playfield_upper_w )
+{
+ COMBINE_DATA(&atarigen_playfield_upper[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_playfield_dual_upper_w: Generic write handler for
+ upper word of split dual playfield RAM.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_playfield_dual_upper_w )
+{
+ COMBINE_DATA(&atarigen_playfield_upper[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset);
+ tilemap_mark_tile_dirty(atarigen_playfield2_tilemap, offset);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_playfield_latched_lsb_w: Generic write handler for
+ lower word of playfield RAM with a latch in the LSB of the
+ upper word.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_playfield_latched_lsb_w )
+{
+ COMBINE_DATA(&atarigen_playfield[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset);
+
+ if (playfield_latch != -1)
+ atarigen_playfield_upper[offset] = (atarigen_playfield_upper[offset] & ~0x00ff) | (playfield_latch & 0x00ff);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_playfield_latched_lsb_w: Generic write handler for
+ lower word of playfield RAM with a latch in the MSB of the
+ upper word.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_playfield_latched_msb_w )
+{
+ COMBINE_DATA(&atarigen_playfield[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield_tilemap, offset);
+
+ if (playfield_latch != -1)
+ atarigen_playfield_upper[offset] = (atarigen_playfield_upper[offset] & ~0xff00) | (playfield_latch & 0xff00);
+}
+
+
+
+/*---------------------------------------------------------------
+ atarigen_playfield_latched_lsb_w: Generic write handler for
+ lower word of second playfield RAM with a latch in the MSB
+ of the upper word.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_playfield2_latched_msb_w )
+{
+ COMBINE_DATA(&atarigen_playfield2[offset]);
+ tilemap_mark_tile_dirty(atarigen_playfield2_tilemap, offset);
+
+ if (playfield2_latch != -1)
+ atarigen_playfield_upper[offset] = (atarigen_playfield_upper[offset] & ~0xff00) | (playfield2_latch & 0xff00);
+}
+
+
+
+
+/*##########################################################################
+ VIDEO HELPERS
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_get_hblank: Returns a guesstimate about the current
+ HBLANK state, based on the assumption that HBLANK represents
+ 10% of the scanline period.
+---------------------------------------------------------------*/
+
+int atarigen_get_hblank(running_machine *machine, int scrnum)
+{
+ return (video_screen_get_hpos(scrnum) > (machine->screen[scrnum].width * 9 / 10));
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_halt_until_hblank_0_w: Halts CPU 0 until the
+ next HBLANK.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_halt_until_hblank_0_w )
+{
+ /* halt the CPU until the next HBLANK */
+ int hpos = video_screen_get_hpos(0); /* need to support scrnum */
+ int hblank = Machine->screen[0].width * 9 / 10;
+ double fraction;
+
+ /* if we're in hblank, set up for the next one */
+ if (hpos >= hblank)
+ hblank += Machine->screen[0].width;
+
+ /* halt and set a timer to wake up */
+ fraction = (double)(hblank - hpos) / (double)Machine->screen[0].width;
+ timer_set(double_to_attotime(attotime_to_double(video_screen_get_scan_period(0)) * fraction), 0, unhalt_cpu);
+ cpunum_set_input_line(0, INPUT_LINE_HALT, ASSERT_LINE);
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_666_paletteram_w: 6-6-6 RGB palette RAM handler.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_666_paletteram_w )
+{
+ int newword, r, g, b;
+
+ COMBINE_DATA(&paletteram16[offset]);
+ newword = paletteram16[offset];
+
+ r = ((newword >> 9) & 0x3e) | ((newword >> 15) & 1);
+ g = ((newword >> 4) & 0x3e) | ((newword >> 15) & 1);
+ b = ((newword << 1) & 0x3e) | ((newword >> 15) & 1);
+
+ palette_set_color_rgb(Machine, offset, pal6bit(r), pal6bit(g), pal6bit(b));
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_expanded_666_paletteram_w: 6-6-6 RGB expanded
+ palette RAM handler.
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_expanded_666_paletteram_w )
+{
+ COMBINE_DATA(&paletteram16[offset]);
+
+ if (ACCESSING_MSB)
+ {
+ int palentry = offset / 2;
+ int newword = (paletteram16[palentry * 2] & 0xff00) | (paletteram16[palentry * 2 + 1] >> 8);
+
+ int r, g, b;
+
+ r = ((newword >> 9) & 0x3e) | ((newword >> 15) & 1);
+ g = ((newword >> 4) & 0x3e) | ((newword >> 15) & 1);
+ b = ((newword << 1) & 0x3e) | ((newword >> 15) & 1);
+
+ palette_set_color_rgb(Machine, palentry & 0x1ff, pal6bit(r), pal6bit(g), pal6bit(b));
+ }
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_666_paletteram32_w: 6-6-6 RGB palette RAM handler.
+---------------------------------------------------------------*/
+
+WRITE32_HANDLER( atarigen_666_paletteram32_w )
+{
+ int newword, r, g, b;
+
+ COMBINE_DATA(&paletteram32[offset]);
+
+ if (ACCESSING_MSW32)
+ {
+ newword = paletteram32[offset] >> 16;
+
+ r = ((newword >> 9) & 0x3e) | ((newword >> 15) & 1);
+ g = ((newword >> 4) & 0x3e) | ((newword >> 15) & 1);
+ b = ((newword << 1) & 0x3e) | ((newword >> 15) & 1);
+
+ palette_set_color_rgb(Machine, offset * 2, pal6bit(r), pal6bit(g), pal6bit(b));
+ }
+
+ if (ACCESSING_LSW32)
+ {
+ newword = paletteram32[offset] & 0xffff;
+
+ r = ((newword >> 9) & 0x3e) | ((newword >> 15) & 1);
+ g = ((newword >> 4) & 0x3e) | ((newword >> 15) & 1);
+ b = ((newword << 1) & 0x3e) | ((newword >> 15) & 1);
+
+ palette_set_color_rgb(Machine, offset * 2 + 1, pal6bit(r), pal6bit(g), pal6bit(b));
+ }
+}
+
+
+/*---------------------------------------------------------------
+ unhalt_cpu: Timer callback to release the CPU from a halted state.
+---------------------------------------------------------------*/
+
+static TIMER_CALLBACK( unhalt_cpu )
+{
+ cpunum_set_input_line(param, INPUT_LINE_HALT, CLEAR_LINE);
+}
+
+
+
+/*##########################################################################
+ MISC HELPERS
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ atarigen_swap_mem: Inverts the bits in a region.
+---------------------------------------------------------------*/
+
+void atarigen_swap_mem(void *ptr1, void *ptr2, int bytes)
+{
+ UINT8 *p1 = ptr1;
+ UINT8 *p2 = ptr2;
+ while (bytes--)
+ {
+ int temp = *p1;
+ *p1++ = *p2;
+ *p2++ = temp;
+ }
+}
+
+
+/*---------------------------------------------------------------
+ atarigen_blend_gfx: Takes two GFXElements and blends their
+ data together to form one. Then frees the second.
+---------------------------------------------------------------*/
+
+void atarigen_blend_gfx(running_machine *machine, int gfx0, int gfx1, int mask0, int mask1)
+{
+ gfx_element *gx0 = machine->gfx[gfx0];
+ gfx_element *gx1 = machine->gfx[gfx1];
+ int c, x, y;
+
+ /* loop over elements */
+ for (c = 0; c < gx0->total_elements; c++)
+ {
+ UINT8 *c0base = gx0->gfxdata + gx0->char_modulo * c;
+ UINT8 *c1base = gx1->gfxdata + gx1->char_modulo * c;
+ UINT32 usage = 0;
+
+ /* loop over height */
+ for (y = 0; y < gx0->height; y++)
+ {
+ UINT8 *c0 = c0base, *c1 = c1base;
+
+ for (x = 0; x < gx0->width; x++, c0++, c1++)
+ {
+ *c0 = (*c0 & mask0) | (*c1 & mask1);
+ usage |= 1 << *c0;
+ }
+ c0base += gx0->line_modulo;
+ c1base += gx1->line_modulo;
+ if (gx0->pen_usage)
+ gx0->pen_usage[c] = usage;
+ }
+ }
+
+ /* free the second graphics element */
+ freegfx(gx1);
+ machine->gfx[gfx1] = NULL;
+}
+
+
+/*##########################################################################
+ SAVE STATE
+##########################################################################*/
+
+void atarigen_init_save_state(void)
+{
+ state_save_register_global(atarigen_scanline_int_state);
+ state_save_register_global(atarigen_sound_int_state);
+ state_save_register_global(atarigen_video_int_state);
+
+ state_save_register_global(atarigen_cpu_to_sound_ready);
+ state_save_register_global(atarigen_sound_to_cpu_ready);
+
+ state_save_register_global(atarivc_state.latch1); /* latch #1 value (-1 means disabled) */
+ state_save_register_global(atarivc_state.latch2); /* latch #2 value (-1 means disabled) */
+ state_save_register_global(atarivc_state.rowscroll_enable); /* true if row-scrolling is enabled */
+ state_save_register_global(atarivc_state.palette_bank); /* which palette bank is enabled */
+ state_save_register_global(atarivc_state.pf0_xscroll); /* playfield 1 xscroll */
+ state_save_register_global(atarivc_state.pf0_xscroll_raw); /* playfield 1 xscroll raw value */
+ state_save_register_global(atarivc_state.pf0_yscroll); /* playfield 1 yscroll */
+ state_save_register_global(atarivc_state.pf1_xscroll); /* playfield 2 xscroll */
+ state_save_register_global(atarivc_state.pf1_xscroll_raw); /* playfield 2 xscroll raw value */
+ state_save_register_global(atarivc_state.pf1_yscroll); /* playfield 2 yscroll */
+ state_save_register_global(atarivc_state.mo_xscroll); /* sprite xscroll */
+ state_save_register_global(atarivc_state.mo_yscroll); /* sprite xscroll */
+
+ state_save_register_global(eeprom_unlocked);
+
+ state_save_register_global(atarigen_slapstic_num);
+ state_save_register_global(atarigen_slapstic_bank);
+
+ state_save_register_global(sound_cpu_num);
+ state_save_register_global(atarigen_cpu_to_sound);
+ state_save_register_global(atarigen_sound_to_cpu);
+ state_save_register_global(timed_int);
+ state_save_register_global(ym2151_int);
+
+ state_save_register_global(scanlines_per_callback);
+
+ state_save_register_global(actual_vc_latch0);
+ state_save_register_global(actual_vc_latch1);
+
+ state_save_register_global(playfield_latch);
+ state_save_register_global(playfield2_latch);
+}
diff --git a/src/mame/machine/atarigen.h b/src/mame/machine/atarigen.h
new file mode 100644
index 00000000000..67d22ab430f
--- /dev/null
+++ b/src/mame/machine/atarigen.h
@@ -0,0 +1,289 @@
+/*##########################################################################
+
+ atarigen.h
+
+ General functions for Atari raster games.
+
+##########################################################################*/
+
+#include "video/atarimo.h"
+#include "video/atarirle.h"
+
+#ifndef __MACHINE_ATARIGEN__
+#define __MACHINE_ATARIGEN__
+
+
+/*##########################################################################
+ CONSTANTS
+##########################################################################*/
+
+#define ATARI_CLOCK_14MHz 14318180
+#define ATARI_CLOCK_20MHz 20000000
+#define ATARI_CLOCK_32MHz 32000000
+#define ATARI_CLOCK_50MHz 50000000
+
+
+
+/*##########################################################################
+ TYPES & STRUCTURES
+##########################################################################*/
+
+typedef void (*atarigen_int_callback)(void);
+
+typedef void (*atarigen_scanline_callback)(running_machine *machine, int scrnum, int scanline);
+
+struct atarivc_state_desc
+{
+ UINT32 latch1; /* latch #1 value (-1 means disabled) */
+ UINT32 latch2; /* latch #2 value (-1 means disabled) */
+ UINT32 rowscroll_enable; /* true if row-scrolling is enabled */
+ UINT32 palette_bank; /* which palette bank is enabled */
+ UINT32 pf0_xscroll; /* playfield 1 xscroll */
+ UINT32 pf0_xscroll_raw; /* playfield 1 xscroll raw value */
+ UINT32 pf0_yscroll; /* playfield 1 yscroll */
+ UINT32 pf1_xscroll; /* playfield 2 xscroll */
+ UINT32 pf1_xscroll_raw; /* playfield 2 xscroll raw value */
+ UINT32 pf1_yscroll; /* playfield 2 yscroll */
+ UINT32 mo_xscroll; /* sprite xscroll */
+ UINT32 mo_yscroll; /* sprite xscroll */
+};
+
+
+
+/*##########################################################################
+ GLOBAL VARIABLES
+##########################################################################*/
+
+extern UINT8 atarigen_scanline_int_state;
+extern UINT8 atarigen_sound_int_state;
+extern UINT8 atarigen_video_int_state;
+
+extern const UINT16 * atarigen_eeprom_default;
+extern UINT16 * atarigen_eeprom;
+extern size_t atarigen_eeprom_size;
+
+extern UINT8 atarigen_cpu_to_sound_ready;
+extern UINT8 atarigen_sound_to_cpu_ready;
+
+extern UINT16 * atarigen_playfield;
+extern UINT16 * atarigen_playfield2;
+extern UINT16 * atarigen_playfield_upper;
+extern UINT16 * atarigen_alpha;
+extern UINT16 * atarigen_alpha2;
+extern UINT16 * atarigen_xscroll;
+extern UINT16 * atarigen_yscroll;
+
+extern UINT32 * atarigen_playfield32;
+extern UINT32 * atarigen_alpha32;
+
+extern tilemap * atarigen_playfield_tilemap;
+extern tilemap * atarigen_playfield2_tilemap;
+extern tilemap * atarigen_alpha_tilemap;
+extern tilemap * atarigen_alpha2_tilemap;
+
+extern UINT16 * atarivc_data;
+extern UINT16 * atarivc_eof_data;
+extern struct atarivc_state_desc atarivc_state;
+
+
+
+/*##########################################################################
+ FUNCTION PROTOTYPES
+##########################################################################*/
+
+/*---------------------------------------------------------------
+ INTERRUPT HANDLING
+---------------------------------------------------------------*/
+
+void atarigen_interrupt_reset(atarigen_int_callback update_int);
+void atarigen_update_interrupts(void);
+
+void atarigen_scanline_int_set(int scrnum, int scanline);
+INTERRUPT_GEN( atarigen_scanline_int_gen );
+WRITE16_HANDLER( atarigen_scanline_int_ack_w );
+WRITE32_HANDLER( atarigen_scanline_int_ack32_w );
+
+INTERRUPT_GEN( atarigen_sound_int_gen );
+WRITE16_HANDLER( atarigen_sound_int_ack_w );
+WRITE32_HANDLER( atarigen_sound_int_ack32_w );
+
+INTERRUPT_GEN( atarigen_video_int_gen );
+WRITE16_HANDLER( atarigen_video_int_ack_w );
+WRITE32_HANDLER( atarigen_video_int_ack32_w );
+
+
+/*---------------------------------------------------------------
+ EEPROM HANDLING
+---------------------------------------------------------------*/
+
+void atarigen_eeprom_reset(void);
+
+WRITE16_HANDLER( atarigen_eeprom_enable_w );
+WRITE16_HANDLER( atarigen_eeprom_w );
+READ16_HANDLER( atarigen_eeprom_r );
+READ16_HANDLER( atarigen_eeprom_upper_r );
+
+WRITE32_HANDLER( atarigen_eeprom_enable32_w );
+WRITE32_HANDLER( atarigen_eeprom32_w );
+READ32_HANDLER( atarigen_eeprom_upper32_r );
+
+NVRAM_HANDLER( atarigen );
+
+
+/*---------------------------------------------------------------
+ SLAPSTIC HANDLING
+---------------------------------------------------------------*/
+
+void atarigen_slapstic_init(int cpunum, int base, int chipnum);
+void atarigen_slapstic_reset(void);
+
+WRITE16_HANDLER( atarigen_slapstic_w );
+READ16_HANDLER( atarigen_slapstic_r );
+
+
+/*---------------------------------------------------------------
+ SOUND I/O
+---------------------------------------------------------------*/
+
+void atarigen_sound_io_reset(int cpu_num);
+
+INTERRUPT_GEN( atarigen_6502_irq_gen );
+READ8_HANDLER( atarigen_6502_irq_ack_r );
+WRITE8_HANDLER( atarigen_6502_irq_ack_w );
+
+void atarigen_ym2151_irq_gen(int irq);
+
+WRITE16_HANDLER( atarigen_sound_w );
+READ16_HANDLER( atarigen_sound_r );
+WRITE16_HANDLER( atarigen_sound_upper_w );
+READ16_HANDLER( atarigen_sound_upper_r );
+
+WRITE32_HANDLER( atarigen_sound_upper32_w );
+READ32_HANDLER( atarigen_sound_upper32_r );
+
+void atarigen_sound_reset(void);
+WRITE16_HANDLER( atarigen_sound_reset_w );
+WRITE8_HANDLER( atarigen_6502_sound_w );
+READ8_HANDLER( atarigen_6502_sound_r );
+
+
+/*---------------------------------------------------------------
+ SOUND HELPERS
+---------------------------------------------------------------*/
+
+void atarigen_set_ym2151_vol(running_machine *machine, int volume);
+void atarigen_set_ym2413_vol(running_machine *machine, int volume);
+void atarigen_set_pokey_vol(running_machine *machine, int volume);
+void atarigen_set_tms5220_vol(running_machine *machine, int volume);
+void atarigen_set_oki6295_vol(running_machine *machine, int volume);
+
+
+/*---------------------------------------------------------------
+ VIDEO CONTROLLER
+---------------------------------------------------------------*/
+
+void atarivc_reset(int scrnum, UINT16 *eof_data, int playfields);
+
+WRITE16_HANDLER( atarivc_w );
+READ16_HANDLER( atarivc_r );
+
+INLINE void atarivc_update_pf_xscrolls(void)
+{
+ atarivc_state.pf0_xscroll = atarivc_state.pf0_xscroll_raw + ((atarivc_state.pf1_xscroll_raw) & 7);
+ atarivc_state.pf1_xscroll = atarivc_state.pf1_xscroll_raw + 4;
+}
+
+
+/*---------------------------------------------------------------
+ PLAYFIELD/ALPHA MAP HELPERS
+---------------------------------------------------------------*/
+
+WRITE16_HANDLER( atarigen_alpha_w );
+WRITE32_HANDLER( atarigen_alpha32_w );
+WRITE16_HANDLER( atarigen_alpha2_w );
+void atarigen_set_playfield_latch(int data);
+void atarigen_set_playfield2_latch(int data);
+WRITE16_HANDLER( atarigen_playfield_w );
+WRITE32_HANDLER( atarigen_playfield32_w );
+WRITE16_HANDLER( atarigen_playfield_large_w );
+WRITE16_HANDLER( atarigen_playfield_upper_w );
+WRITE16_HANDLER( atarigen_playfield_dual_upper_w );
+WRITE16_HANDLER( atarigen_playfield_latched_lsb_w );
+WRITE16_HANDLER( atarigen_playfield_latched_msb_w );
+WRITE16_HANDLER( atarigen_playfield2_w );
+WRITE16_HANDLER( atarigen_playfield2_latched_msb_w );
+
+
+/*---------------------------------------------------------------
+ VIDEO HELPERS
+---------------------------------------------------------------*/
+
+void atarigen_scanline_timer_reset(int scrnum, atarigen_scanline_callback update_graphics, int frequency);
+int atarigen_get_hblank(running_machine *machine, int scrnum);
+WRITE16_HANDLER( atarigen_halt_until_hblank_0_w );
+WRITE16_HANDLER( atarigen_666_paletteram_w );
+WRITE16_HANDLER( atarigen_expanded_666_paletteram_w );
+WRITE32_HANDLER( atarigen_666_paletteram32_w );
+
+
+/*---------------------------------------------------------------
+ MISC HELPERS
+---------------------------------------------------------------*/
+
+void atarigen_swap_mem(void *ptr1, void *ptr2, int bytes);
+void atarigen_blend_gfx(running_machine *machine, int gfx0, int gfx1, int mask0, int mask1);
+
+
+/*---------------------------------------------------------------
+ STATE SAVE
+---------------------------------------------------------------*/
+
+void atarigen_init_save_state(void);
+
+/*##########################################################################
+ GENERAL ATARI NOTES
+############################################################################
+
+ Atari 68000 list:
+
+ Driver Pr? Up? VC? PF? P2? MO? AL? BM? PH?
+ ---------- --- --- --- --- --- --- --- --- ---
+ arcadecl.c * * *
+ atarig1.c * * rle *
+ atarig42.c * * rle *
+ atarigt.c * rle *
+ atarigx2.c * rle *
+ atarisy1.c * * * * * 270->260
+ atarisy2.c * * * * * 150->120
+ badlands.c * * * 250->260
+ batman.c * * * * * * * * 200->160 ?
+ blstroid.c * * * 240->230
+ cyberbal.c * * * * 125->105 ?
+ eprom.c * * * * 170->170
+ gauntlet.c * * * * * * 220->250
+ klax.c * * * * 480->440 ?
+ offtwall.c * * * * 260->260
+ rampart.c * * * 280->280
+ relief.c * * * * * * 240->240
+ shuuz.c * * * * 410->290 fix!
+ skullxbo.c * * * * 150->145
+ thunderj.c * * * * * * * 180->180
+ toobin.c * * * * 140->115 fix!
+ vindictr.c * * * * * * 200->210
+ xybots.c * * * * * 235->238
+ ---------- --- --- --- --- --- --- --- --- ---
+
+ Pr? - do we have verifiable proof on priorities?
+ Up? - have we updated to use new MO's & tilemaps?
+ VC? - does it use the video controller?
+ PF? - does it have a playfield?
+ P2? - does it have a dual playfield?
+ MO? - does it have MO's?
+ AL? - does it have an alpha layer?
+ BM? - does it have a bitmap layer?
+ PH? - does it use the palette hack?
+
+##########################################################################*/
+
+
+#endif
diff --git a/src/mame/machine/bagman.c b/src/mame/machine/bagman.c
new file mode 100644
index 00000000000..6c9bedf4b0b
--- /dev/null
+++ b/src/mame/machine/bagman.c
@@ -0,0 +1,242 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+/*Creation date: 98-02-18 */
+/* A few words of comment:
+**
+** What's inside of this file is a PAL16R6 emulator. Maybe someday we will
+**need to use it for some other game too. We will need to make it more exact
+**then (some of the functionality of this chip IS NOT implemented). However I
+**have bought a book about PALs and I'm able to improve it. Just LMK.
+** Jarek Burczynski
+** bujar at mame dot net
+*/
+
+
+/*table holds outputs of all ANDs (after AND map)*/
+static UINT8 andmap[64];
+
+/*table holds inputs (ie. not x, x, not q, q) to the AND map*/
+static UINT8 columnvalue[32];
+
+/*8 output pins (actually 6 output and 2 input/output)*/
+static UINT8 outvalue[8];
+
+/* 64 rows x 32 columns
+** 1 - fuse blown: disconnected from input (equal to 1)
+** 0 - fuse not blown: connected to input (ie. x, not x, q, not q accordingly)
+*/
+static UINT8 fusemap[64*32]=
+{
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,0,1,1,1,1,0,1,1,0,1,1,1,1,0,1,1,0,1,1,1,0,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,
+1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
+1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+
+
+static void update_pal(void)
+{
+UINT16 rowoffs;
+UINT8 row, column, val;
+
+/*calculate all rows ANDs*/
+ for (row = 0; row < 64; row++)
+ {
+ rowoffs = row*32;
+ val = 1; /*prepare for AND */
+ for (column = 0; column < 32; column++)
+ {
+ if ( fusemap[ rowoffs + column ] == 0 )
+ val &= columnvalue[column];
+ }
+ andmap[row] = val;
+ }
+
+/* I/O pin #19 */
+ val = 0; /*prepare for OR*/
+ for (row = 1; row < 8; row++)
+ val |= andmap[row];
+ if (andmap[0] == 1)
+ {
+ columnvalue[2] = 1-val;
+ columnvalue[3] = val;
+ outvalue[0] = 1-val;
+ }
+ else
+ {
+ /*pin is in INPUT configuration so it doesn't create output...*/
+ columnvalue[2] = 0;
+ columnvalue[3] = 1;
+ }
+
+/* O pin #18 (D1) */
+ val = 0; /*prepare for OR*/
+ for (row = 8; row < 16; row++)
+ val |= andmap[row];
+ columnvalue[6] = 1-val;
+ columnvalue[7] = val;
+ outvalue[1] = 1-val;
+
+/* O pin #17 (D2) */
+ val = 0; /*prepare for OR*/
+ for (row = 16; row < 24; row++)
+ val |= andmap[row];
+ columnvalue[10] = 1-val;
+ columnvalue[11] = val;
+ outvalue[2] = 1-val;
+
+/* O pin #16 (D3) */
+ val = 0; /*prepare for OR*/
+ for (row = 24; row < 32; row++)
+ val |= andmap[row];
+ columnvalue[14] = 1-val;
+ columnvalue[15] = val;
+ outvalue[3] = 1-val;
+
+/* O pin #15 (D4) */
+ val = 0; /*prepare for OR*/
+ for (row = 32; row < 40; row++)
+ val |= andmap[row];
+ columnvalue[18] = 1-val;
+ columnvalue[19] = val;
+ outvalue[4] = 1-val;
+
+/* O pin #14 (D5) */
+ val = 0; /*prepare for OR*/
+ for (row = 40; row < 48; row++)
+ val |= andmap[row];
+ columnvalue[22] = 1-val;
+ columnvalue[23] = val;
+ outvalue[5] = 1-val;
+
+/* O pin #13 (D6) */
+ val = 0; /*prepare for OR*/
+ for (row = 48; row < 56; row++)
+ val |= andmap[row];
+ columnvalue[26] = 1-val;
+ columnvalue[27] = val;
+ outvalue[6] = 1-val;
+
+/* I/O pin #12 */
+ val = 0; /*prepare for OR*/
+ for (row = 57; row < 64; row++)
+ val |= andmap[row];
+ if (andmap[56] == 1)
+ {
+ columnvalue[30] = 1-val;
+ columnvalue[31] = val;
+ outvalue[7] = 1-val;
+ }
+ else
+ {
+ /*pin is in INPUT configuration so it doesn't create output...*/
+ columnvalue[30] = 0;
+ columnvalue[31] = 1;
+ }
+
+}
+
+
+WRITE8_HANDLER( bagman_pal16r6_w )
+{
+UINT8 line;
+
+ line = offset*4;
+ columnvalue[line ] = data&1;
+ columnvalue[line+1] = 1-(data&1);
+}
+
+MACHINE_RESET( bagman )
+{
+ bagman_pal16r6_w(0,1); /*pin 2*/
+ bagman_pal16r6_w(1,1); /*pin 3*/
+ bagman_pal16r6_w(2,1); /*pin 4*/
+ bagman_pal16r6_w(3,1); /*pin 5*/
+ bagman_pal16r6_w(4,1); /*pin 6*/
+ bagman_pal16r6_w(5,1); /*pin 7*/
+ bagman_pal16r6_w(6,1); /*pin 8*/
+ bagman_pal16r6_w(7,1); /*pin 9*/
+ update_pal();
+}
+
+READ8_HANDLER( bagman_pal16r6_r )
+{
+ update_pal();
+ return (outvalue[6]) + (outvalue[5]<<1) + (outvalue[4]<<2) +
+ (outvalue[3]<<3) + (outvalue[2]<<4) + (outvalue[1]<<5);
+
+/* Bagman schematics show that this is right mapping order of PAL outputs to bits.
+** This is the PAL 16R6 shown almost in the middle of the schematics.
+** The /RD4 line goes low (active) whenever CPU reads from memory address a000.
+*/
+}
diff --git a/src/mame/machine/balsente.c b/src/mame/machine/balsente.c
new file mode 100644
index 00000000000..cfe4ec0332d
--- /dev/null
+++ b/src/mame/machine/balsente.c
@@ -0,0 +1,1251 @@
+/***************************************************************************
+
+ Bally/Sente SAC-1 system
+
+ driver by Aaron Giles
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6809/m6809.h"
+#include "balsente.h"
+#include "sound/cem3394.h"
+#include <math.h>
+
+
+#define LOG_CEM_WRITES 0
+
+
+/* local prototypes */
+static void poly17_init(void);
+static void counter_set_out(int which, int gate);
+static TIMER_CALLBACK( counter_callback );
+static TIMER_CALLBACK( clock_counter_0_ff );
+static void update_grudge_steering(void);
+
+/* global data */
+UINT8 balsente_shooter;
+UINT8 balsente_shooter_x;
+UINT8 balsente_shooter_y;
+UINT8 balsente_adc_shift;
+UINT16 *shrike_shared;
+UINT16 *shrike_io;
+
+
+/* 8253 counter state */
+struct counter_state
+{
+ emu_timer *timer;
+ UINT8 timer_active;
+ INT32 initial;
+ INT32 count;
+ UINT8 gate;
+ UINT8 out;
+ UINT8 mode;
+ UINT8 readbyte;
+ UINT8 writebyte;
+};
+
+static struct counter_state counter[3];
+
+static emu_timer *scanline_timer;
+
+/* manually clocked counter 0 states */
+static UINT8 counter_control;
+static UINT8 counter_0_ff;
+static emu_timer *counter_0_timer;
+static UINT8 counter_0_timer_active;
+
+/* random number generator states */
+static UINT8 *poly17 = NULL;
+static UINT8 *rand17 = NULL;
+
+/* ADC I/O states */
+static INT8 analog_input_data[4];
+static UINT8 adc_value;
+
+/* CEM3394 DAC control states */
+static UINT16 dac_value;
+static UINT8 dac_register;
+static UINT8 chip_select;
+
+/* main CPU 6850 states */
+static UINT8 m6850_status;
+static UINT8 m6850_control;
+static UINT8 m6850_input;
+static UINT8 m6850_output;
+static UINT8 m6850_data_ready;
+
+/* sound CPU 6850 states */
+static UINT8 m6850_sound_status;
+static UINT8 m6850_sound_control;
+static UINT8 m6850_sound_input;
+static UINT8 m6850_sound_output;
+
+/* noise generator states */
+static UINT32 noise_position[6];
+
+/* game-specific states */
+static UINT8 nstocker_bits;
+static UINT8 spiker_expand_color;
+static UINT8 spiker_expand_bgcolor;
+static UINT8 spiker_expand_bits;
+static UINT8 grudge_steering_result;
+static UINT8 grudge_last_steering[3];
+
+
+
+/*************************************
+ *
+ * Interrupt handling
+ *
+ *************************************/
+
+static TIMER_CALLBACK( irq_off )
+{
+ cpunum_set_input_line(0, M6809_IRQ_LINE, CLEAR_LINE);
+}
+
+
+static TIMER_CALLBACK( interrupt_timer )
+{
+ /* next interrupt after scanline 256 is scanline 64 */
+ if (param == 256)
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, 64, 0), 64, attotime_zero);
+ else
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, param + 64, 0), param + 64, attotime_zero);
+
+ /* IRQ starts on scanline 0, 64, 128, etc. */
+ cpunum_set_input_line(0, M6809_IRQ_LINE, ASSERT_LINE);
+
+ /* it will turn off on the next HBLANK */
+ timer_set(video_screen_get_time_until_pos(0, param, BALSENTE_HBSTART), 0, irq_off);
+
+ /* if this is Grudge Match, update the steering */
+ if (grudge_steering_result & 0x80)
+ update_grudge_steering();
+
+ /* if we're a shooter, we do a little more work */
+ if (balsente_shooter)
+ {
+ UINT8 tempx, tempy;
+
+ /* we latch the beam values on the first interrupt after VBLANK */
+ if (param == 64 && balsente_shooter)
+ {
+ balsente_shooter_x = readinputport(8);
+ balsente_shooter_y = readinputport(9);
+ }
+
+ /* which bits get returned depends on which scanline we're at */
+ tempx = balsente_shooter_x << ((param - 64) / 64);
+ tempy = balsente_shooter_y << ((param - 64) / 64);
+ nstocker_bits = ((tempx >> 4) & 0x08) | ((tempx >> 1) & 0x04) |
+ ((tempy >> 6) & 0x02) | ((tempy >> 3) & 0x01);
+ }
+}
+
+
+MACHINE_RESET( balsente )
+{
+ int numbanks, i;
+
+ /* create the polynomial tables */
+ poly17_init();
+
+ /* reset counters; counter 2's gate is tied high */
+ memset(counter, 0, sizeof(counter));
+ counter[1].timer = timer_alloc(counter_callback);
+ counter[2].timer = timer_alloc(counter_callback);
+ counter[2].gate = 1;
+
+ /* reset the manual counter 0 clock */
+ counter_control = 0x00;
+ counter_0_ff = 0;
+ counter_0_timer = timer_alloc(clock_counter_0_ff);
+ counter_0_timer_active = 0;
+
+ /* reset the ADC states */
+ adc_value = 0;
+
+ /* reset the CEM3394 I/O states */
+ dac_value = 0;
+ dac_register = 0;
+ chip_select = 0x3f;
+
+ /* reset game-specific states */
+ grudge_steering_result = 0;
+
+ /* reset the 6850 chips */
+ balsente_m6850_w(0, 3);
+ balsente_m6850_sound_w(0, 3);
+
+ /* reset the noise generator */
+ memset(noise_position, 0, sizeof(noise_position));
+
+ /* point the banks to bank 0 */
+ numbanks = (memory_region_length(REGION_CPU1) > 0x40000) ? 16 : 8;
+ memory_configure_bank(1, 0, numbanks, &memory_region(REGION_CPU1)[0x10000], 0x6000);
+ memory_configure_bank(2, 0, numbanks, &memory_region(REGION_CPU1)[0x12000], 0x6000);
+ memory_set_bank(1, 0);
+ memory_set_bank(2, 0);
+
+ /* start a timer to generate interrupts */
+ scanline_timer = timer_alloc(interrupt_timer);
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, 0, 0), 0, attotime_zero);
+
+ /* register for saving */
+ for (i = 0; i < 3; i++)
+ {
+ state_save_register_item("8253counter", i, counter[i].timer_active);
+ state_save_register_item("8253counter", i, counter[i].initial);
+ state_save_register_item("8253counter", i, counter[i].count);
+ state_save_register_item("8253counter", i, counter[i].gate);
+ state_save_register_item("8253counter", i, counter[i].out);
+ state_save_register_item("8253counter", i, counter[i].mode);
+ state_save_register_item("8253counter", i, counter[i].readbyte);
+ state_save_register_item("8253counter", i, counter[i].writebyte);
+ }
+
+ state_save_register_global(counter_control);
+ state_save_register_global(counter_0_ff);
+ state_save_register_global(counter_0_timer_active);
+
+ state_save_register_global_array(analog_input_data);
+ state_save_register_global(adc_value);
+
+ state_save_register_global(dac_value);
+ state_save_register_global(dac_register);
+ state_save_register_global(chip_select);
+
+ state_save_register_global(m6850_status);
+ state_save_register_global(m6850_control);
+ state_save_register_global(m6850_input);
+ state_save_register_global(m6850_output);
+ state_save_register_global(m6850_data_ready);
+
+ state_save_register_global(m6850_sound_status);
+ state_save_register_global(m6850_sound_control);
+ state_save_register_global(m6850_sound_input);
+ state_save_register_global(m6850_sound_output);
+
+ state_save_register_global_array(noise_position);
+
+ state_save_register_global(nstocker_bits);
+ state_save_register_global(spiker_expand_color);
+ state_save_register_global(spiker_expand_bgcolor);
+ state_save_register_global(spiker_expand_bits);
+ state_save_register_global(grudge_steering_result);
+ state_save_register_global_array(grudge_last_steering);
+}
+
+
+
+/*************************************
+ *
+ * MM5837 noise generator
+ *
+ * NOTE: this is stolen straight from
+ * POKEY.c
+ *
+ *************************************/
+
+#define POLY17_BITS 17
+#define POLY17_SIZE ((1 << POLY17_BITS) - 1)
+#define POLY17_SHL 7
+#define POLY17_SHR 10
+#define POLY17_ADD 0x18000
+
+static void poly17_init(void)
+{
+ UINT32 i, x = 0;
+ UINT8 *p, *r;
+
+ /* allocate memory */
+ p = poly17 = auto_malloc(POLY17_SIZE + 1);
+ r = rand17 = auto_malloc(POLY17_SIZE + 1);
+
+ /* generate the polynomial */
+ for (i = 0; i < POLY17_SIZE; i++)
+ {
+ /* store new values */
+ *p++ = x & 1;
+ *r++ = x >> 3;
+
+ /* calculate next bit */
+ x = ((x << POLY17_SHL) + (x >> POLY17_SHR) + POLY17_ADD) & POLY17_SIZE;
+ }
+}
+
+
+void balsente_noise_gen(int chip, int count, short *buffer)
+{
+ /* noise generator runs at 100kHz */
+ UINT32 step = (100000 << 14) / CEM3394_SAMPLE_RATE;
+ UINT32 noise_counter = noise_position[chip];
+
+ while (count--)
+ {
+ *buffer++ = poly17[(noise_counter >> 14) & POLY17_SIZE] << 12;
+ noise_counter += step;
+ }
+
+ /* remember the noise position */
+ noise_position[chip] = noise_counter;
+}
+
+
+
+/*************************************
+ *
+ * Hardware random numbers
+ *
+ *************************************/
+
+WRITE8_HANDLER( balsente_random_reset_w )
+{
+ /* reset random number generator */
+}
+
+
+READ8_HANDLER( balsente_random_num_r )
+{
+ UINT32 cc;
+
+ /* CPU runs at 1.25MHz, noise source at 100kHz --> multiply by 12.5 */
+ cc = activecpu_gettotalcycles();
+
+ /* 12.5 = 8 + 4 + 0.5 */
+ cc = (cc << 3) + (cc << 2) + (cc >> 1);
+ return rand17[cc & POLY17_SIZE];
+}
+
+
+
+/*************************************
+ *
+ * ROM banking
+ *
+ *************************************/
+
+WRITE8_HANDLER( balsente_rombank_select_w )
+{
+ /* the bank number comes from bits 4-6 */
+ memory_set_bank(1, (data >> 4) & 7);
+ memory_set_bank(2, (data >> 4) & 7);
+}
+
+
+WRITE8_HANDLER( balsente_rombank2_select_w )
+{
+ /* Night Stocker and Name that Tune only so far.... */
+ int bank = data & 7;
+
+ /* top bit controls which half of the ROMs to use (Name that Tune only) */
+ if (memory_region_length(REGION_CPU1) > 0x40000) bank |= (data >> 4) & 8;
+
+ /* when they set the AB bank, it appears as though the CD bank is reset */
+ if (data & 0x20)
+ {
+ memory_set_bank(1, bank);
+ memory_set_bank(2, 6);
+ }
+
+ /* set both banks */
+ else
+ {
+ memory_set_bank(1, bank);
+ memory_set_bank(2, bank);
+ }
+}
+
+
+
+/*************************************
+ *
+ * Special outputs
+ *
+ *************************************/
+
+WRITE8_HANDLER( balsente_misc_output_w )
+{
+ offset = (offset / 4) % 8;
+ data >>= 7;
+
+ /* these are generally used to control the various lamps */
+ /* special case is offset 7, which recalls the NVRAM data */
+ if (offset == 7)
+ {
+ logerror("nvrecall_w=%d\n", data);
+ }
+ else
+ {
+// set_led_status(offset, data);
+ }
+}
+
+
+
+/*************************************
+ *
+ * 6850 UART communications
+ *
+ *************************************/
+
+static void m6850_update_io(void)
+{
+ UINT8 new_state;
+
+ /* sound -> main CPU communications */
+ if (!(m6850_sound_status & 0x02))
+ {
+ /* set the overrun bit if the data in the destination hasn't been read yet */
+ if (m6850_status & 0x01)
+ m6850_status |= 0x20;
+
+ /* copy the sound's output to our input */
+ m6850_input = m6850_sound_output;
+
+ /* set the receive register full bit */
+ m6850_status |= 0x01;
+
+ /* set the sound's trasmitter register empty bit */
+ m6850_sound_status |= 0x02;
+ }
+
+ /* main -> sound CPU communications */
+ if (m6850_data_ready)
+ {
+ /* set the overrun bit if the data in the destination hasn't been read yet */
+ if (m6850_sound_status & 0x01)
+ m6850_sound_status |= 0x20;
+
+ /* copy the main CPU's output to our input */
+ m6850_sound_input = m6850_output;
+
+ /* set the receive register full bit */
+ m6850_sound_status |= 0x01;
+
+ /* set the main CPU's trasmitter register empty bit */
+ m6850_status |= 0x02;
+ m6850_data_ready = 0;
+ }
+
+ /* check for reset states */
+ if ((m6850_control & 3) == 3)
+ {
+ m6850_status = 0x02;
+ m6850_data_ready = 0;
+ }
+ if ((m6850_sound_control & 3) == 3)
+ m6850_sound_status = 0x02;
+
+ /* check for transmit/receive IRQs on the main CPU */
+ new_state = 0;
+ if ((m6850_control & 0x80) && (m6850_status & 0x21)) new_state = 1;
+ if ((m6850_control & 0x60) == 0x20 && (m6850_status & 0x02)) new_state = 1;
+
+ /* apply the change */
+ if (new_state && !(m6850_status & 0x80))
+ {
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
+ m6850_status |= 0x80;
+ }
+ else if (!new_state && (m6850_status & 0x80))
+ {
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, CLEAR_LINE);
+ m6850_status &= ~0x80;
+ }
+
+ /* check for transmit/receive IRQs on the sound CPU */
+ new_state = 0;
+ if ((m6850_sound_control & 0x80) && (m6850_sound_status & 0x21)) new_state = 1;
+ if ((m6850_sound_control & 0x60) == 0x20 && (m6850_sound_status & 0x02)) new_state = 1;
+ if (!(counter_control & 0x20)) new_state = 0;
+
+ /* apply the change */
+ if (new_state && !(m6850_sound_status & 0x80))
+ {
+ cpunum_set_input_line(1, INPUT_LINE_NMI, ASSERT_LINE);
+ m6850_sound_status |= 0x80;
+ }
+ else if (!new_state && (m6850_sound_status & 0x80))
+ {
+ cpunum_set_input_line(1, INPUT_LINE_NMI, CLEAR_LINE);
+ m6850_sound_status &= ~0x80;
+ }
+}
+
+
+
+/*************************************
+ *
+ * 6850 UART (main CPU)
+ *
+ *************************************/
+
+READ8_HANDLER( balsente_m6850_r )
+{
+ int result;
+
+ /* status register is at offset 0 */
+ if (offset == 0)
+ {
+ result = m6850_status;
+ }
+
+ /* input register is at offset 1 */
+ else
+ {
+ result = m6850_input;
+
+ /* clear the overrun and receive buffer full bits */
+ m6850_status &= ~0x21;
+ m6850_update_io();
+ }
+
+ return result;
+}
+
+
+static TIMER_CALLBACK( m6850_data_ready_callback )
+{
+ /* set the output data byte and indicate that we're ready to go */
+ m6850_output = param;
+ m6850_data_ready = 1;
+ m6850_update_io();
+}
+
+
+static TIMER_CALLBACK( m6850_w_callback )
+{
+ /* indicate that the transmit buffer is no longer empty and update the I/O state */
+ m6850_status &= ~0x02;
+ m6850_update_io();
+
+ /* set a timer for 500usec later to actually transmit the data */
+ /* (this is very important for several games, esp Snacks'n Jaxson) */
+ timer_set(ATTOTIME_IN_USEC(500), param, m6850_data_ready_callback);
+}
+
+
+WRITE8_HANDLER( balsente_m6850_w )
+{
+ /* control register is at offset 0 */
+ if (offset == 0)
+ {
+ m6850_control = data;
+
+ /* re-update since interrupt enables could have been modified */
+ m6850_update_io();
+ }
+
+ /* output register is at offset 1; set a timer to synchronize the CPUs */
+ else
+ timer_call_after_resynch(data, m6850_w_callback);
+}
+
+
+
+/*************************************
+ *
+ * 6850 UART (sound CPU)
+ *
+ *************************************/
+
+READ8_HANDLER( balsente_m6850_sound_r )
+{
+ int result;
+
+ /* status register is at offset 0 */
+ if (offset == 0)
+ {
+ result = m6850_sound_status;
+ }
+
+ /* input register is at offset 1 */
+ else
+ {
+ result = m6850_sound_input;
+
+ /* clear the overrun and receive buffer full bits */
+ m6850_sound_status &= ~0x21;
+ m6850_update_io();
+ }
+
+ return result;
+}
+
+
+WRITE8_HANDLER( balsente_m6850_sound_w )
+{
+ /* control register is at offset 0 */
+ if (offset == 0)
+ m6850_sound_control = data;
+
+ /* output register is at offset 1 */
+ else
+ {
+ m6850_sound_output = data;
+ m6850_sound_status &= ~0x02;
+ }
+
+ /* re-update since interrupt enables could have been modified */
+ m6850_update_io();
+}
+
+
+
+/*************************************
+ *
+ * ADC handlers
+ *
+ *************************************/
+
+INTERRUPT_GEN( balsente_update_analog_inputs )
+{
+ int i;
+
+ /* the analog input system helpfully scales the value read by the percentage of time */
+ /* into the current frame we are; unfortunately, this is bad for us, since the analog */
+ /* ports are read once a frame, just at varying intervals. To get around this, we */
+ /* read all the analog inputs at VBLANK time and just return the cached values. */
+ for (i = 0; i < 4; i++)
+ analog_input_data[i] = readinputport(4 + i);
+}
+
+
+static TIMER_CALLBACK( adc_finished )
+{
+ int which = param;
+
+ /* analog controls are read in two pieces; the lower port returns the sign */
+ /* and the upper port returns the absolute value of the magnitude */
+ int val = analog_input_data[which / 2] << balsente_adc_shift;
+
+ /* special case for Stompin'/Shrike Avenger */
+ if (balsente_adc_shift == 32)
+ {
+ adc_value = analog_input_data[which];
+ return;
+ }
+
+ /* push everything out a little bit extra; most games seem to have a dead */
+ /* zone in the middle that feels unnatural with the mouse */
+ if (val < 0) val -= 8;
+ else if (val > 0) val += 8;
+
+ /* clip to 0xff maximum magnitude */
+ if (val < -0xff) val = -0xff;
+ else if (val > 0xff) val = 0xff;
+
+ /* return the sign */
+ if (!(which & 1))
+ adc_value = (val < 0) ? 0xff : 0x00;
+
+ /* return the magnitude */
+ else
+ adc_value = (val < 0) ? -val : val;
+}
+
+
+READ8_HANDLER( balsente_adc_data_r )
+{
+ /* just return the last value read */
+ return adc_value;
+}
+
+
+WRITE8_HANDLER( balsente_adc_select_w )
+{
+ /* set a timer to go off and read the value after 50us */
+ /* it's important that we do this for Mini Golf */
+logerror("adc_select %d\n", offset & 7);
+ timer_set(ATTOTIME_IN_USEC(50), offset & 7, adc_finished);
+}
+
+
+
+/*************************************
+ *
+ * 8253-5 timer utilities
+ *
+ * NOTE: this is far from complete!
+ *
+ *************************************/
+
+INLINE void counter_start(int which)
+{
+ /* don't start a timer for channel 0; it is clocked manually */
+ if (which != 0)
+ {
+ /* only start a timer if we're gated and there is none already */
+ if (counter[which].gate && !counter[which].timer_active)
+ {
+ counter[which].timer_active = 1;
+ timer_adjust(counter[which].timer, attotime_mul(ATTOTIME_IN_HZ(2000000), counter[which].count), which, attotime_zero);
+ }
+ }
+}
+
+
+INLINE void counter_stop(int which)
+{
+ /* only stop the timer if it exists */
+ if (counter[which].timer_active)
+ timer_adjust(counter[which].timer, attotime_never, 0, attotime_zero);
+ counter[which].timer_active = 0;
+}
+
+
+INLINE void counter_update_count(int which)
+{
+ /* only update if the timer is running */
+ if (counter[which].timer_active)
+ {
+ /* determine how many 2MHz cycles are remaining */
+ int count = attotime_to_double(attotime_mul(timer_timeleft(counter[which].timer), 2000000));
+ counter[which].count = (count < 0) ? 0 : count;
+ }
+}
+
+
+
+/*************************************
+ *
+ * 8253-5 timer internals
+ *
+ * NOTE: this is far from complete!
+ *
+ *************************************/
+
+static void counter_set_gate(int which, int gate)
+{
+ int oldgate = counter[which].gate;
+
+ /* remember the gate state */
+ counter[which].gate = gate;
+
+ /* if the counter is being halted, update the count and remove the system timer */
+ if (!gate && oldgate)
+ {
+ counter_update_count(which);
+ counter_stop(which);
+ }
+
+ /* if the counter is being started, create the timer */
+ else if (gate && !oldgate)
+ {
+ /* mode 1 waits for the gate to trigger the counter */
+ if (counter[which].mode == 1)
+ {
+ counter_set_out(which, 0);
+
+ /* add one to the count; technically, OUT goes low on the next clock pulse */
+ /* and then starts counting down; it's important that we don't count the first one */
+ counter[which].count = counter[which].initial + 1;
+ }
+
+ /* start the counter */
+ counter_start(which);
+ }
+}
+
+
+static void counter_set_out(int which, int out)
+{
+ /* OUT on counter 2 is hooked to the /INT line on the Z80 */
+ if (which == 2)
+ cpunum_set_input_line(1, 0, out ? ASSERT_LINE : CLEAR_LINE);
+
+ /* OUT on counter 0 is hooked to the GATE line on counter 1 */
+ else if (which == 0)
+ counter_set_gate(1, !out);
+
+ /* remember the out state */
+ counter[which].out = out;
+}
+
+
+static TIMER_CALLBACK( counter_callback )
+{
+ /* reset the counter and the count */
+ counter[param].timer_active = 0;
+ counter[param].count = 0;
+
+ /* set the state of the OUT line */
+ /* mode 0 and 1: when firing, transition OUT to high */
+ if (counter[param].mode == 0 || counter[param].mode == 1)
+ counter_set_out(param, 1);
+
+ /* no other modes handled currently */
+}
+
+
+
+/*************************************
+ *
+ * 8253-5 timer handlers
+ *
+ * NOTE: this is far from complete!
+ *
+ *************************************/
+
+READ8_HANDLER( balsente_counter_8253_r )
+{
+ int which;
+
+ switch (offset & 3)
+ {
+ case 0:
+ case 1:
+ case 2:
+ /* warning: assumes LSB/MSB addressing and no latching! */
+ which = offset & 3;
+
+ /* update the count */
+ counter_update_count(which);
+
+ /* return the LSB */
+ if (counter[which].readbyte == 0)
+ {
+ counter[which].readbyte = 1;
+ return counter[which].count & 0xff;
+ }
+
+ /* write the MSB and reset the counter */
+ else
+ {
+ counter[which].readbyte = 0;
+ return (counter[which].count >> 8) & 0xff;
+ }
+ break;
+ }
+ return 0;
+}
+
+
+WRITE8_HANDLER( balsente_counter_8253_w )
+{
+ int which;
+
+ switch (offset & 3)
+ {
+ case 0:
+ case 1:
+ case 2:
+ /* warning: assumes LSB/MSB addressing and no latching! */
+ which = offset & 3;
+
+ /* if the counter is in mode 0, a write here will reset the OUT state */
+ if (counter[which].mode == 0)
+ counter_set_out(which, 0);
+
+ /* write the LSB */
+ if (counter[which].writebyte == 0)
+ {
+ counter[which].count = (counter[which].count & 0xff00) | (data & 0x00ff);
+ counter[which].initial = (counter[which].initial & 0xff00) | (data & 0x00ff);
+ counter[which].writebyte = 1;
+ }
+
+ /* write the MSB and reset the counter */
+ else
+ {
+ counter[which].count = (counter[which].count & 0x00ff) | ((data << 8) & 0xff00);
+ counter[which].initial = (counter[which].initial & 0x00ff) | ((data << 8) & 0xff00);
+ counter[which].writebyte = 0;
+
+ /* treat 0 as $10000 */
+ if (counter[which].count == 0) counter[which].count = counter[which].initial = 0x10000;
+
+ /* remove any old timer and set a new one */
+ counter_stop(which);
+
+ /* note that in mode 1, we have to wait for a rising edge of a gate */
+ if (counter[which].mode == 0)
+ counter_start(which);
+
+ /* if the counter is in mode 1, a write here will set the OUT state */
+ if (counter[which].mode == 1)
+ counter_set_out(which, 1);
+ }
+ break;
+
+ case 3:
+ /* determine which counter */
+ which = data >> 6;
+ if (which == 3) break;
+
+ /* if the counter was in mode 0, a write here will reset the OUT state */
+ if (((counter[which].mode >> 1) & 7) == 0)
+ counter_set_out(which, 0);
+
+ /* set the mode */
+ counter[which].mode = (data >> 1) & 7;
+
+ /* if the counter is in mode 0, a write here will reset the OUT state */
+ if (counter[which].mode == 0)
+ counter_set_out(which, 0);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Sound CPU counter 0 emulation
+ *
+ *************************************/
+
+static void set_counter_0_ff(running_machine *machine, int newstate)
+{
+ /* the flip/flop output is inverted, so if we went high to low, that's a clock */
+ if (counter_0_ff && !newstate)
+ {
+ /* only count if gated and non-zero */
+ if (counter[0].count > 0 && counter[0].gate)
+ {
+ counter[0].count--;
+ if (counter[0].count == 0)
+ counter_callback(machine, 0);
+ }
+ }
+
+ /* remember the new state */
+ counter_0_ff = newstate;
+}
+
+
+static TIMER_CALLBACK( clock_counter_0_ff )
+{
+ /* clock the D value through the flip-flop */
+ set_counter_0_ff(machine, (counter_control >> 3) & 1);
+}
+
+
+static void update_counter_0_timer(void)
+{
+ double maxfreq = 0.0;
+ int i;
+
+ /* if there's already a timer, remove it */
+ if (counter_0_timer_active)
+ timer_adjust(counter_0_timer, attotime_never, 0, attotime_zero);
+ counter_0_timer_active = 0;
+
+ /* find the counter with the maximum frequency */
+ /* this is used to calibrate the timers at startup */
+ for (i = 0; i < 6; i++)
+ if (cem3394_get_parameter(i, CEM3394_FINAL_GAIN) < 10.0)
+ {
+ double tempfreq;
+
+ /* if the filter resonance is high, then they're calibrating the filter frequency */
+ if (cem3394_get_parameter(i, CEM3394_FILTER_RESONANCE) > 0.9)
+ tempfreq = cem3394_get_parameter(i, CEM3394_FILTER_FREQENCY);
+
+ /* otherwise, they're calibrating the VCO frequency */
+ else
+ tempfreq = cem3394_get_parameter(i, CEM3394_VCO_FREQUENCY);
+
+ if (tempfreq > maxfreq) maxfreq = tempfreq;
+ }
+
+ /* reprime the timer */
+ if (maxfreq > 0.0)
+ {
+ counter_0_timer_active = 1;
+ timer_adjust(counter_0_timer, ATTOTIME_IN_HZ(maxfreq), 0, ATTOTIME_IN_HZ(maxfreq));
+ }
+}
+
+
+
+/*************************************
+ *
+ * Sound CPU counter handlers
+ *
+ *************************************/
+
+READ8_HANDLER( balsente_counter_state_r )
+{
+ /* bit D0 is the inverse of the flip-flop state */
+ int result = !counter_0_ff;
+
+ /* bit D1 is the OUT value from counter 0 */
+ if (counter[0].out) result |= 0x02;
+
+ return result;
+}
+
+
+WRITE8_HANDLER( balsente_counter_control_w )
+{
+ UINT8 diff_counter_control = counter_control ^ data;
+
+ /* set the new global value */
+ counter_control = data;
+
+ /* bit D0 enables/disables audio */
+ if (diff_counter_control & 0x01)
+ {
+ int ch;
+ for (ch = 0; ch < 6; ch++)
+ sndti_set_output_gain(SOUND_CEM3394, ch, 0, (data & 0x01) ? 1.0 : 0);
+ }
+
+ /* bit D1 is hooked to counter 0's gate */
+ /* if we gate on, start a pulsing timer to clock it */
+ if (!counter[0].gate && (data & 0x02) && !counter_0_timer_active)
+ {
+ update_counter_0_timer();
+ }
+
+ /* if we gate off, remove the timer */
+ else if (counter[0].gate && !(data & 0x02) && counter_0_timer_active)
+ {
+ timer_adjust(counter_0_timer, attotime_never, 0, attotime_zero);
+ counter_0_timer_active = 0;
+ }
+
+ /* set the actual gate afterwards, since we need to know the old value above */
+ counter_set_gate(0, (data >> 1) & 1);
+
+ /* bits D2 and D4 control the clear/reset flags on the flip-flop that feeds counter 0 */
+ if (!(data & 0x04)) set_counter_0_ff(Machine, 1);
+ if (!(data & 0x10)) set_counter_0_ff(Machine, 0);
+
+ /* bit 5 clears the NMI interrupt; recompute the I/O state now */
+ m6850_update_io();
+}
+
+
+
+/*************************************
+ *
+ * CEM3394 Interfaces
+ *
+ *************************************/
+
+WRITE8_HANDLER( balsente_chip_select_w )
+{
+ static const UINT8 register_map[8] =
+ {
+ CEM3394_VCO_FREQUENCY,
+ CEM3394_FINAL_GAIN,
+ CEM3394_FILTER_RESONANCE,
+ CEM3394_FILTER_FREQENCY,
+ CEM3394_MIXER_BALANCE,
+ CEM3394_MODULATION_AMOUNT,
+ CEM3394_PULSE_WIDTH,
+ CEM3394_WAVE_SELECT
+ };
+
+ double voltage = (double)dac_value * (8.0 / 4096.0) - 4.0;
+ int diffchip = data ^ chip_select, i;
+ int reg = register_map[dac_register];
+
+ /* remember the new select value */
+ chip_select = data;
+
+ /* check all six chip enables */
+ for (i = 0; i < 6; i++)
+ if ((diffchip & (1 << i)) && (data & (1 << i)))
+ {
+ double temp = 0;
+
+ /* remember the previous value */
+ temp = cem3394_get_parameter(i, reg);
+
+ /* set the voltage */
+ cem3394_set_voltage(i, reg, voltage);
+
+ /* only log changes */
+#if LOG_CEM_WRITES
+ if (temp != cem3394_get_parameter(i, reg))
+ {
+ static const char *names[] =
+ {
+ "VCO_FREQUENCY",
+ "FINAL_GAIN",
+ "FILTER_RESONANCE",
+ "FILTER_FREQENCY",
+ "MIXER_BALANCE",
+ "MODULATION_AMOUNT",
+ "PULSE_WIDTH",
+ "WAVE_SELECT"
+ };
+ logerror("s%04X: CEM#%d:%s=%f\n", activecpu_get_previouspc(), i, names[dac_register], voltage);
+ }
+#endif
+ }
+
+ /* if a timer for counter 0 is running, recompute */
+ if (counter_0_timer_active)
+ update_counter_0_timer();
+}
+
+
+
+WRITE8_HANDLER( balsente_dac_data_w )
+{
+ /* LSB or MSB? */
+ if (offset & 1)
+ dac_value = (dac_value & 0xfc0) | ((data >> 2) & 0x03f);
+ else
+ dac_value = (dac_value & 0x03f) | ((data << 6) & 0xfc0);
+
+ /* if there are open channels, force the values in */
+ if ((chip_select & 0x3f) != 0x3f)
+ {
+ UINT8 temp = chip_select;
+ balsente_chip_select_w(0, 0x3f);
+ balsente_chip_select_w(0, temp);
+ }
+}
+
+
+WRITE8_HANDLER( balsente_register_addr_w )
+{
+ dac_register = data & 7;
+}
+
+
+
+/*************************************
+ *
+ * Game-specific handlers
+ *
+ *************************************/
+
+READ8_HANDLER( nstocker_port2_r )
+{
+ return (readinputport(2) & 0xf0) | nstocker_bits;
+}
+
+
+WRITE8_HANDLER( spiker_expand_w )
+{
+ /* offset 0 is the bit pattern */
+ if (offset == 0)
+ spiker_expand_bits = data;
+
+ /* offset 1 is the background color (cleared on each read) */
+ else if (offset == 1)
+ spiker_expand_bgcolor = data;
+
+ /* offset 2 is the color */
+ else if (offset == 2)
+ spiker_expand_color = data;
+}
+
+
+READ8_HANDLER( spiker_expand_r )
+{
+ UINT8 left, right;
+
+ /* first rotate each nibble */
+ spiker_expand_bits = ((spiker_expand_bits << 1) & 0xee) | ((spiker_expand_bits >> 3) & 0x11);
+
+ /* compute left and right pixels */
+ left = (spiker_expand_bits & 0x10) ? spiker_expand_color : spiker_expand_bgcolor;
+ right = (spiker_expand_bits & 0x01) ? spiker_expand_color : spiker_expand_bgcolor;
+
+ /* reset the background color */
+ spiker_expand_bgcolor = 0;
+
+ /* return the combined result */
+ return (left & 0xf0) | (right & 0x0f);
+}
+
+
+static void update_grudge_steering(void)
+{
+ UINT8 wheel[3];
+ INT8 diff[3];
+
+ /* read the current steering values */
+ wheel[0] = readinputport(4);
+ wheel[1] = readinputport(5);
+ wheel[2] = readinputport(6);
+
+ /* diff the values */
+ diff[0] = wheel[0] - grudge_last_steering[0];
+ diff[1] = wheel[1] - grudge_last_steering[1];
+ diff[2] = wheel[2] - grudge_last_steering[2];
+
+ /* update the last values */
+ grudge_last_steering[0] += diff[0];
+ grudge_last_steering[1] += diff[1];
+ grudge_last_steering[2] += diff[2];
+
+ /* compute the result */
+ grudge_steering_result = 0xff;
+ if (diff[0])
+ {
+ grudge_steering_result ^= 0x01;
+ if (diff[0] > 0) grudge_steering_result ^= 0x02;
+ }
+ if (diff[1])
+ {
+ grudge_steering_result ^= 0x04;
+ if (diff[1] > 0) grudge_steering_result ^= 0x08;
+ }
+ if (diff[2])
+ {
+ grudge_steering_result ^= 0x10;
+ if (diff[2] > 0) grudge_steering_result ^= 0x20;
+ }
+ logerror("Recomputed steering\n");
+}
+
+
+READ8_HANDLER( grudge_steering_r )
+{
+ logerror("%04X:grudge_steering_r(@%d)\n", activecpu_get_pc(), video_screen_get_vpos(0));
+ grudge_steering_result |= 0x80;
+ return grudge_steering_result;
+}
+
+
+
+/*************************************
+ *
+ * Shrike Avenger CPU memory handlers
+ *
+ *************************************/
+
+READ8_HANDLER( shrike_shared_6809_r )
+{
+ UINT16 mem_mask = offset & 1 ? 0xff : 0xff00;
+
+ switch( offset )
+ {
+ case 6: // return OK for 68k status register until motors hooked up
+ return 0;
+ default:
+ return ( shrike_shared[offset >> 1] & mem_mask ) >> ( ~mem_mask & 8 );
+ }
+}
+
+
+WRITE8_HANDLER( shrike_shared_6809_w )
+{
+ UINT16 mem_mask = offset & 1 ? 0xff : 0xff00;
+ shrike_shared[offset >> 1] = ( shrike_shared[offset >> 1] & ~mem_mask ) | ( data << ( ~mem_mask & 0x8 ) );
+}
+
+// uses movep, so writes even 8 bit addresses to odd 16 bit addresses, reads as 16 bit from odd addresses
+// i.e. write 0xdeadbeef to 10000, read 0xde from 10001, 0xad from 10003, 0xbe from 10005...
+WRITE16_HANDLER( shrike_io_68k_w )
+{
+ COMBINE_DATA( &shrike_io[offset] );
+}
+
+READ16_HANDLER( shrike_io_68k_r )
+{
+ return ( shrike_io[offset] & ~mem_mask ) >> ( 8 & mem_mask );
+}
+
diff --git a/src/mame/machine/beezer.c b/src/mame/machine/beezer.c
new file mode 100644
index 00000000000..66a6e3036a5
--- /dev/null
+++ b/src/mame/machine/beezer.c
@@ -0,0 +1,143 @@
+#include "driver.h"
+#include "cpu/m6809/m6809.h"
+#include "machine/6522via.h"
+
+WRITE8_HANDLER( beezer_map_w );
+READ8_HANDLER( beezer_line_r );
+
+static int pbus;
+
+static READ8_HANDLER( b_via_0_pb_r );
+static WRITE8_HANDLER( b_via_0_pa_w );
+static WRITE8_HANDLER( b_via_0_pb_w );
+static READ8_HANDLER( b_via_0_ca2_r );
+static WRITE8_HANDLER( b_via_0_ca2_w );
+static void b_via_0_irq (int level);
+
+static READ8_HANDLER( b_via_1_pa_r );
+static READ8_HANDLER( b_via_1_pb_r );
+static WRITE8_HANDLER( b_via_1_pa_w );
+static WRITE8_HANDLER( b_via_1_pb_w );
+static void b_via_1_irq (int level);
+
+static struct via6522_interface b_via_0_interface =
+{
+ /*inputs : A/B */ 0, b_via_0_pb_r,
+ /*inputs : CA/B1,CA/B2 */ 0, via_1_ca2_r, b_via_0_ca2_r, via_1_ca1_r,
+ /*outputs: A/B */ b_via_0_pa_w, b_via_0_pb_w,
+ /*outputs: CA/B1,CA/B2 */ 0, 0, b_via_0_ca2_w, via_1_ca1_w,
+ /*irq */ b_via_0_irq
+};
+
+static struct via6522_interface b_via_1_interface =
+{
+ /*inputs : A/B */ b_via_1_pa_r, b_via_1_pb_r,
+ /*inputs : CA/B1,CA/B2 */ via_0_cb2_r, 0, via_0_cb1_r, 0,
+ /*outputs: A/B */ b_via_1_pa_w, b_via_1_pb_w,
+ /*outputs: CA/B1,CA/B2 */ 0, 0, via_0_cb1_w, 0,
+ /*irq */ b_via_1_irq
+};
+
+static READ8_HANDLER( b_via_0_ca2_r )
+{
+ return 0;
+}
+
+static WRITE8_HANDLER( b_via_0_ca2_w )
+{
+}
+
+static void b_via_0_irq (int level)
+{
+ cpunum_set_input_line(0, M6809_IRQ_LINE, level);
+}
+
+static READ8_HANDLER( b_via_0_pb_r )
+{
+ return pbus;
+}
+
+static WRITE8_HANDLER( b_via_0_pa_w )
+{
+ if ((data & 0x08) == 0)
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ASSERT_LINE);
+ else
+ cpunum_set_input_line(1, INPUT_LINE_RESET, CLEAR_LINE);
+
+ if ((data & 0x04) == 0)
+ {
+ switch (data & 0x03)
+ {
+ case 0:
+ pbus = input_port_0_r(0);
+ break;
+ case 1:
+ pbus = input_port_1_r(0) | (input_port_2_r(0) << 4);
+ break;
+ case 2:
+ pbus = input_port_3_r(0);
+ break;
+ case 3:
+ pbus = 0xff;
+ break;
+ }
+ }
+}
+
+static WRITE8_HANDLER( b_via_0_pb_w )
+{
+ pbus = data;
+}
+
+static void b_via_1_irq (int level)
+{
+ cpunum_set_input_line(1, M6809_IRQ_LINE, level);
+}
+
+static READ8_HANDLER( b_via_1_pa_r )
+{
+ return pbus;
+}
+
+static READ8_HANDLER( b_via_1_pb_r )
+{
+ return 0xff;
+}
+
+static WRITE8_HANDLER( b_via_1_pa_w )
+{
+ pbus = data;
+}
+
+static WRITE8_HANDLER( b_via_1_pb_w )
+{
+}
+
+DRIVER_INIT( beezer )
+{
+ via_config(0, &b_via_0_interface);
+ via_config(1, &b_via_1_interface);
+ via_reset();
+ pbus = 0;
+}
+
+WRITE8_HANDLER( beezer_bankswitch_w )
+{
+ if ((data & 0x07) == 0)
+ {
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc600, 0xc7ff, 0, 0, watchdog_reset_w);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc800, 0xc9ff, 0, 0, beezer_map_w);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xca00, 0xcbff, 0, 0, beezer_line_r);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xce00, 0xcfff, 0, 0, via_0_r);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xce00, 0xcfff, 0, 0, via_0_w);
+ }
+ else
+ {
+ UINT8 *rom = memory_region(REGION_CPU1) + 0x10000;
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MRA8_BANK1);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MWA8_BANK1);
+ memory_set_bankptr(1, rom + (data & 0x07) * 0x2000 + ((data & 0x08) ? 0x1000: 0));
+ }
+}
+
+
diff --git a/src/mame/machine/bfm_bd1.c b/src/mame/machine/bfm_bd1.c
new file mode 100644
index 00000000000..a3bac92df10
--- /dev/null
+++ b/src/mame/machine/bfm_bd1.c
@@ -0,0 +1,567 @@
+/**********************************************************************
+
+ Bellfruit BD1 VFD module interface and emulation by J.Wallace
+
+**********************************************************************/
+
+#include "driver.h"
+#include "bfm_bd1.h"
+
+static struct
+{
+ UINT8 type, // type of alpha display
+
+ changed, // flag <>0, if contents are changed
+ window_start, // display window start pos 0-15
+ window_end, // display window end pos 0-15
+ window_size, // window size
+ pad; // unused align byte
+
+ INT8 pcursor_pos, // previous cursor pos
+ cursor_pos; // current cursor pos
+
+ UINT16 user_def, // user defined character state
+ user_data; // user defined character data (16 bit)
+
+ UINT8 scroll_active, // flag <>0, scrolling active
+ display_mode, // display scroll mode, 0/1/2/3
+ display_blanking, // display blanking mode, 0/1/2/3
+ flash_rate, // flash rate 0-F
+ flash_control; // flash control 0/1/2/3
+
+ UINT8 string[18]; // text buffer
+ UINT32 segments[16], // segments
+ outputs[16]; // standardised outputs
+
+ UINT8 count, // bit counter
+ data; // receive register
+
+} bd1[MAX_BD1];
+
+
+// local prototypes ///////////////////////////////////////////////////////
+
+static void ScrollLeft( int id);
+static int BD1_setdata(int id, int segdata, int data);
+
+// local vars /////////////////////////////////////////////////////////////
+
+//
+// Bellfruit BD1 charset to ASCII conversion table
+//
+static const char BD1ASCII[] =
+//0123456789ABCDEF0123456789ABC DEF01 23456789ABCDEF0123456789ABCDEF
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+.-./0123456789&%<=>?"\
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+.-./0123456789&%<=>?"\
+ "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_ ?\"#$%%'()*+.-./0123456789&%<=>?";
+
+/*
+ BD1 14 segment charset lookup table
+ 2
+ ---------
+ |\ |3 /|
+ 0 | \6 | /7| 1
+ | \ | / |
+ -F-- --E-
+ | / | \ |
+ D | /4 |A \B| 5
+ |/ | \|
+ --------- C
+ 9
+
+ */
+
+static UINT16 BD1charset[]=
+{ // FEDC BA98 7654 3210
+ 0xA626, // 1010 0110 0010 0110 @.
+ 0xE027, // 1110 0000 0010 0111 A.
+ 0x462E, // 0100 0110 0010 1110 B.
+ 0x2205, // 0010 0010 0000 0101 C.
+ 0x062E, // 0000 0110 0010 1110 D.
+ 0xA205, // 1010 0010 0000 0101 E.
+ 0xA005, // 1010 0000 0000 0101 F.
+ 0x6225, // 0110 0010 0010 0101 G.
+ 0xE023, // 1110 0000 0010 0011 H.
+ 0x060C, // 0000 0110 0000 1100 I.
+ 0x2222, // 0010 0010 0010 0010 J.
+ 0xA881, // 1010 1000 1000 0001 K.
+ 0x2201, // 0010 0010 0000 0001 L.
+ 0x20E3, // 0010 0000 1110 0011 M.
+ 0x2863, // 0010 1000 0110 0011 N.
+ 0x2227, // 0010 0010 0010 0111 O.
+ 0xE007, // 1110 0000 0000 0111 P.
+ 0x2A27, // 0010 1010 0010 0111 Q.
+ 0xE807, // 1110 1000 0000 0111 R.
+ 0xC225, // 1100 0010 0010 0101 S.
+ 0x040C, // 0000 0100 0000 1100 T.
+ 0x2223, // 0010 0010 0010 0011 U.
+ 0x2091, // 0010 0000 1001 0001 V.
+ 0x2833, // 0010 1000 0011 0011 W.
+ 0x08D0, // 0000 1000 1101 0000 X.
+ 0x04C0, // 0000 0100 1100 0000 Y.
+ 0x0294, // 0000 0010 1001 0100 Z.
+ 0x2205, // 0010 0010 0000 0101 [.
+ 0x0840, // 0000 1000 0100 0000 \.
+ 0x0226, // 0000 0010 0010 0110 ].
+ 0x0810, // 0000 1000 0001 0000 ^.
+ 0x0200, // 0000 0010 0000 0000 _
+ 0x0000, // 0000 0000 0000 0000
+ 0xC290, // 1100 0010 1001 0000 POUND.
+ 0x0009, // 0000 0000 0000 1001 ".
+ 0xC62A, // 1100 0110 0010 1010 #.
+ 0xC62D, // 1100 0110 0010 1101 $.
+ 0x0100, // 0000 0000 0000 0000 flash ?
+ 0x0000, // 0000 0000 0000 0000 not defined
+ 0x0040, // 0000 0000 1000 0000 '.
+ 0x0880, // 0000 1000 1000 0000 (.
+ 0x0050, // 0000 0000 0101 0000 ).
+ 0xCCD8, // 1100 1100 1101 1000 *.
+ 0xC408, // 1100 0100 0000 1000 +.
+ 0x1000, // 0001 0000 0000 0000 .
+ 0xC000, // 1100 0000 0000 0000 -.
+ 0x1000, // 0001 0000 0000 0000 ..
+ 0x0090, // 0000 0000 1001 0000 /.
+ 0x22B7, // 0010 0010 1011 0111 0.
+ 0x0408, // 0000 0100 0000 1000 1.
+ 0xE206, // 1110 0010 0000 0110 2.
+ 0x4226, // 0100 0010 0010 0110 3.
+ 0xC023, // 1100 0000 0010 0011 4.
+ 0xC225, // 1100 0010 0010 0101 5.
+ 0xE225, // 1110 0010 0010 0101 6.
+ 0x0026, // 0000 0000 0010 0110 7.
+ 0xE227, // 1110 0010 0010 0111 8.
+ 0xC227, // 1100 0010 0010 0111 9.
+ 0xFFFF, // 0000 0000 0000 0000 user defined, can be replaced by main program
+ 0x0000, // 0000 0000 0000 0000 dummy
+ 0x0290, // 0000 0010 1001 0000 <.
+ 0xC200, // 1100 0010 0000 0000 =.
+ 0x0A40, // 0000 1010 0100 0000 >.
+ 0x4406, // 0100 0100 0000 0110 ?
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+void BFM_BD1_init(int id)
+{
+ assert_always((id >= 0) && (id < MAX_BD1), "BFM_BD1_init called on an invalid display ID!");
+
+ memset( &bd1[id], 0, sizeof(bd1[0]));
+
+ BFM_BD1_reset(id);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void BFM_BD1_reset(int id)
+{
+ bd1[id].window_end = 15;
+ bd1[id].window_size = (bd1[id].window_end - bd1[id].window_start)+1;
+ memset(bd1[id].string, ' ', 16);
+
+ bd1[id].count = 0;
+
+ bd1[id].changed |= 1;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+UINT32 *BFM_BD1_get_segments(int id)
+{
+ return bd1[id].segments;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+UINT32 *BFM_BD1_get_outputs(int id)
+{
+ return bd1[id].outputs;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+UINT32 *BFM_BD1_set_outputs(int id)
+{
+ int cursor;
+ for (cursor = 0; cursor < 16; cursor++)
+ {
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0004 ) bd1[id].outputs[cursor] |= 0x0001;
+ else bd1[id].outputs[cursor] &= ~0x0001;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0002 ) bd1[id].outputs[cursor] |= 0x0002;
+ else bd1[id].outputs[cursor] &= ~0x0002;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0020 ) bd1[id].outputs[cursor] |= 0x0004;
+ else bd1[id].outputs[cursor] &= ~0x0004;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0200 ) bd1[id].outputs[cursor] |= 0x0008;
+ else bd1[id].outputs[cursor] &= ~0x0008;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x2000 ) bd1[id].outputs[cursor] |= 0x0010;
+ else bd1[id].outputs[cursor] &= ~0x0010;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0001 ) bd1[id].outputs[cursor] |= 0x0020;
+ else bd1[id].outputs[cursor] &= ~0x0020;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x8000 ) bd1[id].outputs[cursor] |= 0x0040;
+ else bd1[id].outputs[cursor] &= ~0x0040;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x4000 ) bd1[id].outputs[cursor] |= 0x0080;
+ else bd1[id].outputs[cursor] &= ~0x0080;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0008 ) bd1[id].outputs[cursor] |= 0x0100;
+ else bd1[id].outputs[cursor] &= ~0x0100;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0400 ) bd1[id].outputs[cursor] |= 0x0200;
+ else bd1[id].outputs[cursor] &= ~0x0200;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0010 ) bd1[id].outputs[cursor] |= 0x0400;
+ else bd1[id].outputs[cursor] &= ~0x0400;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0040 ) bd1[id].outputs[cursor] |= 0x0800;
+ else bd1[id].outputs[cursor] &= ~0x0800;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0080 ) bd1[id].outputs[cursor] |= 0x1000;
+ else bd1[id].outputs[cursor] &= ~0x1000;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x0800 ) bd1[id].outputs[cursor] |= 0x2000;
+ else bd1[id].outputs[cursor] &= ~0x2000;
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x1000 ) bd1[id].outputs[cursor] |= 0x4000;
+ else bd1[id].outputs[cursor] &= ~0x4000;
+ //Flashing ? Set an unused pin as a control
+ if ( BFM_BD1_get_segments(id)[cursor] & 0x100 ) bd1[id].outputs[cursor] |= 0x40000;
+ else bd1[id].outputs[cursor] &= ~0x40000;
+ }
+ return 0;
+}
+///////////////////////////////////////////////////////////////////////////
+
+char *BFM_BD1_get_string( int id)
+{
+ return (char *)bd1[id].string;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void BFM_BD1_shift_data(int id, int data)
+{
+ bd1[id].data <<= 1;
+
+ if ( !data ) bd1[id].data |= 1;
+
+ if ( ++bd1[id].count >= 8 )
+ {
+ if ( BFM_BD1_newdata(id, bd1[id].data) )
+ {
+ bd1[id].changed |= 1;
+ }
+ //logerror("vfd %3d -> %02X \"%s\"\n", id, bd1[id].data, bd1[id].string);
+
+ bd1[id].count = 0;
+ bd1[id].data = 0;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+int BFM_BD1_newdata(int id, int data)
+{
+ int change = 0;
+ int cursor;
+
+ if ( bd1[id].user_def )
+ {
+ bd1[id].user_def--;
+
+ bd1[id].user_data <<= 8;
+ bd1[id].user_data |= data;
+
+ if ( bd1[id].user_def )
+ {
+ return 0;
+ }
+
+ data = '@';
+ change = BD1_setdata(id, bd1[id].user_def, data);
+ }
+ else
+ {
+ }
+
+ switch ( data & 0xF0 )
+ {
+ case 0x80: // 0x80 - 0x8F Set display blanking
+
+ bd1[id].display_blanking = data & 0x0F;
+ change = 1;
+ break;
+
+ case 0x90: // 0x90 - 0x9F Set cursor pos
+
+ bd1[id].cursor_pos = data & 0x0F;
+
+ bd1[id].scroll_active = 0;
+ if ( bd1[id].display_mode == 2 )
+ {
+ if ( bd1[id].cursor_pos >= bd1[id].window_end) bd1[id].scroll_active = 1;
+ }
+ break;
+
+ case 0xA0: // 0xA0 - 0xAF Set display mode
+
+ bd1[id].display_mode = data &0x03;
+ break;
+
+ case 0xB0: // 0xB0 - 0xBF Clear display area
+
+ switch ( data & 0x03 )
+ {
+ case 0x00: // clr nothing
+ break;
+
+ case 0x01: // clr inside window
+
+ if ( bd1[id].window_size > 0 )
+ {
+ memset( bd1[id].string+bd1[id].window_start, ' ',bd1[id].window_size );
+ }
+ break;
+
+ case 0x02: // clr outside window
+
+ if ( bd1[id].window_size > 0 )
+ {
+ if ( bd1[id].window_start > 0 )
+ {
+ memset( bd1[id].string, ' ', bd1[id].window_start);
+ for (cursor = 0; cursor < bd1[id].window_start; cursor++)
+ {
+ bd1[id].segments[cursor] = 0x0000;
+ }
+ }
+
+ if (bd1[id].window_end < 15 )
+ {
+ memset( bd1[id].string+bd1[id].window_end, ' ', 15-bd1[id].window_end);
+ for (cursor = bd1[id].window_end; cursor < 15-bd1[id].window_end; cursor++)
+ {
+ bd1[id].segments[cursor] = 0x0000;
+ }
+
+ }
+ }
+ case 0x03: // clr entire display
+
+ memset(bd1[id].string, ' ' , 16);
+ for (cursor = 0; cursor < 16; cursor++)
+ {
+ bd1[id].segments[cursor] = 0x0000;
+ }
+ break;
+ }
+ change = 1;
+ break;
+
+ case 0xC0: // 0xC0 - 0xCF Set flash rate
+
+ bd1[id].flash_rate = data & 0x0F;
+ break;
+
+ case 0xD0: // 0xD0 - 0xDF Set Flash control
+
+ bd1[id].flash_control = data & 0x03;
+ break;
+
+ case 0xE0: // 0xE0 - 0xEF Set window start pos
+
+ bd1[id].window_start = data &0x0F;
+ bd1[id].window_size = (bd1[id].window_end - bd1[id].window_start)+1;
+ break;
+
+ case 0xF0: // 0xF0 - 0xFF Set window end pos
+
+ bd1[id].window_end = data &0x0F;
+ bd1[id].window_size = (bd1[id].window_end - bd1[id].window_start)+1;
+
+ bd1[id].scroll_active = 0;
+ if ( bd1[id].display_mode == 2 )
+ {
+ if ( bd1[id].cursor_pos >= bd1[id].window_end)
+ {
+ bd1[id].scroll_active = 1;
+ bd1[id].cursor_pos = bd1[id].window_end;
+ }
+ }
+ break;
+
+ default: // normal character
+
+ change = BD1_setdata(id, BD1charset[data & 0x3F], data);
+ break;
+ }
+ return change;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static void ScrollLeft(int id)
+{
+ int i = bd1[id].window_start;
+
+ while ( i < bd1[id].window_end )
+ {
+ bd1[id].string[ i ] = bd1[id].string[ i+1 ];
+ bd1[id].segments[i] = bd1[id].segments[i+1];
+ i++;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static int BD1_setdata(int id, int segdata, int data)
+{
+ int change = 0, move = 0;
+
+ switch ( data )
+ {
+ case 0x25: // flash
+ move++;
+ break;
+
+ case 0x26: // undefined
+ break;
+
+ case 0x2C: // semicolon
+ case 0x2E: // decimal point
+
+ bd1[id].segments[bd1[id].pcursor_pos] |= (1<<12);
+ change++;
+ break;
+
+ case 0x3B: // dummy char
+ move++;
+ break;
+
+ case 0x3A:
+ bd1[id].user_def = 2;
+ break;
+
+ default:
+ move = 1;
+ change = 1;
+ }
+
+ if ( move )
+ {
+ int mode = bd1[id].display_mode;
+
+ bd1[id].pcursor_pos = bd1[id].cursor_pos;
+
+ if ( bd1[id].window_size <= 0 || (bd1[id].window_size > 16))
+ { // no window selected default to rotate mode
+ if ( mode == 2 ) mode = 0;
+ else if ( mode == 3 ) mode = 1;
+ //mode &= -2;
+ }
+
+ switch ( mode )
+ {
+ case 0: // rotate left
+
+ bd1[id].cursor_pos &= 0x0F;
+
+ if ( change )
+ {
+ bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
+ bd1[id].segments[bd1[id].cursor_pos] = segdata;
+ }
+ bd1[id].cursor_pos++;
+ if ( bd1[id].cursor_pos >= 16 ) bd1[id].cursor_pos = 0;
+ break;
+
+
+ case 1: // Rotate right
+
+ bd1[id].cursor_pos &= 0x0F;
+
+ if ( change )
+ {
+ bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
+ bd1[id].segments[bd1[id].cursor_pos] = segdata;
+ }
+ bd1[id].cursor_pos--;
+ if ( bd1[id].cursor_pos < 0 ) bd1[id].cursor_pos = 15;
+ break;
+
+ case 2: // Scroll left
+
+ if ( bd1[id].cursor_pos < bd1[id].window_end )
+ {
+ bd1[id].scroll_active = 0;
+ if ( change )
+ {
+ bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
+ bd1[id].segments[bd1[id].cursor_pos] = segdata;
+ }
+ if ( move ) bd1[id].cursor_pos++;
+ }
+ else
+ {
+ if ( move )
+ {
+ if ( bd1[id].scroll_active ) ScrollLeft(id);
+ else bd1[id].scroll_active = 1;
+ }
+
+ if ( change )
+ {
+ bd1[id].string[bd1[id].window_end] = BD1ASCII[data];
+ bd1[id].segments[bd1[id].cursor_pos] = segdata;
+ }
+ else
+ {
+ bd1[id].string[bd1[id].window_end] = ' ';
+ bd1[id].segments[bd1[id].cursor_pos] = 0;
+ }
+ }
+ break;
+
+ case 3: // Scroll right
+
+ if ( bd1[id].cursor_pos > bd1[id].window_start )
+ {
+ if ( change )
+ {
+ bd1[id].string[bd1[id].cursor_pos] = BD1ASCII[data];
+ bd1[id].segments[bd1[id].cursor_pos] = segdata;
+ }
+ bd1[id].cursor_pos--;
+ }
+ else
+ {
+ int i = bd1[id].window_end;
+
+ while ( i > bd1[id].window_start )
+ {
+ bd1[id].string[ i ] = bd1[id].string[ i-1 ];
+ bd1[id].segments[i] = bd1[id].segments[i-1];
+ i--;
+ }
+
+ if ( change )
+ {
+ bd1[id].string[bd1[id].window_start] = BD1ASCII[data];
+ bd1[id].segments[bd1[id].window_start] = segdata;
+ }
+ }
+ break;
+ }
+ }
+ return change;
+}
+
+void BFM_BD1_draw(int id)
+{
+ int cursor;
+ BFM_BD1_set_outputs(id);
+
+ for (cursor = 0; cursor < 16; cursor++)
+ {
+ output_set_indexed_value("vfd", (id*16)+cursor, BFM_BD1_get_outputs(id)[cursor]);
+
+ if (BFM_BD1_get_outputs(id)[cursor] & 0x40000)
+ {
+ //activate flashing (unimplemented, just toggle on and off)
+ }
+ else
+ {
+ //deactivate flashing (unimplemented)
+ }
+ }
+}
diff --git a/src/mame/machine/bfm_bd1.h b/src/mame/machine/bfm_bd1.h
new file mode 100644
index 00000000000..a6edb0372e2
--- /dev/null
+++ b/src/mame/machine/bfm_bd1.h
@@ -0,0 +1,22 @@
+#ifndef BFM_BD1
+#define BFM_BD1
+
+#define MAX_BD1 3 // max number of displays emulated
+
+void BFM_BD1_init( int id ); // setup a display
+
+void BFM_BD1_reset( int id); // reset the alpha
+
+void BFM_BD1_shift_data(int id, int data); // clock in a bit of data
+
+int BFM_BD1_newdata( int id, int data); // clock in 8 bits of data
+
+UINT32 *BFM_BD1_get_segments(int id); // get current segments displayed
+UINT32 *BFM_BD1_set_outputs(int id); // convert segments to standard for display
+UINT32 *BFM_BD1_get_outputs(int id); // get converted segments
+
+char *BFM_BD1_get_string( int id); // get current string displayed (not as accurate)
+
+void BFM_BD1_draw(int id);
+#endif
+
diff --git a/src/mame/machine/bigevglf.c b/src/mame/machine/bigevglf.c
new file mode 100644
index 00000000000..92307ed20e7
--- /dev/null
+++ b/src/mame/machine/bigevglf.c
@@ -0,0 +1,107 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+static UINT8 from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+
+static UINT8 portA_in,portA_out,ddrA;
+static UINT8 portB_in,portB_out,ddrB;
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( bigevglf_68705_portA_r )
+{
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( bigevglf_68705_portA_w )
+{
+ portA_out = data;
+}
+
+WRITE8_HANDLER( bigevglf_68705_ddrA_w )
+{
+ ddrA = data;
+
+}
+
+READ8_HANDLER( bigevglf_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( bigevglf_68705_portB_w )
+{
+
+ if ((ddrB & 0x02) && (~portB_out & 0x02) && (data & 0x02)) /* positive going transition of the clock */
+ {
+ cpunum_set_input_line(3,0,CLEAR_LINE);
+ main_sent = 0;
+
+ }
+ if ((ddrB & 0x04) && (~portB_out & 0x04) && (data & 0x04) ) /* positive going transition of the clock */
+ {
+ from_mcu = portA_out;
+ mcu_sent = 0;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( bigevglf_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+READ8_HANDLER( bigevglf_68705_portC_r )
+{
+ portC_in = 0;
+ if (main_sent) portC_in |= 0x01;
+ if (mcu_sent) portC_in |= 0x02;
+
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( bigevglf_68705_portC_w )
+{
+ portC_out = data;
+}
+
+WRITE8_HANDLER( bigevglf_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+WRITE8_HANDLER( bigevglf_mcu_w )
+{
+ portA_in = data;
+ main_sent = 1;
+ cpunum_set_input_line(3,0,ASSERT_LINE);
+}
+
+
+READ8_HANDLER( bigevglf_mcu_r )
+{
+ mcu_sent = 1;
+ return from_mcu;
+}
+
+READ8_HANDLER( bigevglf_mcu_status_r )
+{
+ int res = 0;
+
+ if (!main_sent) res |= 0x08;
+ if (!mcu_sent) res |= 0x10;
+
+ return res;
+}
+
diff --git a/src/mame/machine/bonzeadv.c b/src/mame/machine/bonzeadv.c
new file mode 100644
index 00000000000..ded86335c52
--- /dev/null
+++ b/src/mame/machine/bonzeadv.c
@@ -0,0 +1,467 @@
+/*************************************************************************
+
+ Bonze Adventure C-Chip
+ ======================
+
+ Based on RAINE. Improvements with a lot of help from Ruben Panossian.
+ Additional thanks to Robert Gallagher and Stephane Humbert.
+
+ Verification on real hardware by Bryan McPhail, Feb 2006:
+ The restart positions on real hardware are affected by the level
+ variable, as well as scroll & player position. The old implementation
+ did not account for this and so overlapping map positions between
+ levels reported the wrong data.
+
+ Restart data is confirmed correct & complete. Previously many
+ restart points were missed.
+
+ Mapping of restart positions now accurate to the real hardware -
+ previously these values were approximated by hand (and many
+ missing).
+
+*************************************************************************/
+
+#include "driver.h"
+
+static int current_round = 0;
+static int current_bank = 0;
+
+static UINT8 cval[26];
+static UINT8 cc_port;
+static UINT8 restart_status;
+
+struct cchip_mapping
+{
+ UINT16 xmin;
+ UINT16 xmax;
+ UINT16 ymin;
+ UINT16 ymax;
+ UINT16 sx;
+ UINT16 sy;
+ UINT16 px;
+ UINT16 py;
+};
+
+static const UINT16 CLEV[][13] =
+{
+/* map start player start player y-range player x-range map y-range map x-range time */
+ { 0x0000, 0x0018, 0x0020, 0x0030, 0x0028, 0x00D0, 0x0050, 0x0090, 0x0000, 0x0118, 0x0000, 0x0C90, 0x3800 },
+ { 0x0000, 0x0100, 0x0048, 0x0028, 0x0028, 0x0090, 0x0070, 0x00B0, 0x0000, 0x02C0, 0x0000, 0x0CA0, 0x3000 },
+ { 0x0000, 0x0518, 0x0068, 0x00B8, 0x0028, 0x00D0, 0x0068, 0x00B0, 0x02F8, 0x0518, 0x0000, 0x0EF8, 0x3000 },
+ { 0x0978, 0x0608, 0x00C8, 0x00B0, 0x0028, 0x00D0, 0x0098, 0x00C8, 0x0608, 0x06E8, 0x0000, 0x0A48, 0x2000 },
+ { 0x0410, 0x0708, 0x0070, 0x0030, 0x0028, 0x00D0, 0x0060, 0x0090, 0x0708, 0x0708, 0x0410, 0x1070, 0x3800 },
+ { 0x1288, 0x0808, 0x0099, 0x00CE, 0x0028, 0x00D0, 0x0060, 0x00C0, 0x0000, 0x0808, 0x1288, 0x1770, 0x3000 },
+ { 0x11B0, 0x0908, 0x0118, 0x0040, 0x0028, 0x00D0, 0x00B0, 0x00C0, 0x0900, 0x0910, 0x0050, 0x11B0, 0x3800 },
+ { 0x0000, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x0000, 0x0398, 0x1000 },
+ { 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0x8800 },
+ { 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0xffff },
+ { 0x06F8, 0x0808, 0x0028, 0x00B8, 0x0028, 0x00D0, 0x0070, 0x00B0, 0x0808, 0x0808, 0x06F8, 0x06F8, 0xffff },
+};
+
+static const struct cchip_mapping level00[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0000, 0x0200, 0x0000, 0x0100, 0x0000, 0x0018, 0x0020, 0x00a8 },
+ { 0x0200, 0x0380, 0x0000, 0x0100, 0x01e0, 0x0018, 0x0070, 0x0098 },
+ { 0x0380, 0x0620, 0x0000, 0x0100, 0x04a0, 0x0018, 0x0070, 0x0090 },
+ { 0x0620, 0x08f0, 0x0000, 0x0100, 0x06b8, 0x0018, 0x0078, 0x0078 },
+ { 0x08f0, 0x0a20, 0x0000, 0x0100, 0x08c8, 0x0018, 0x0070, 0x0028 },
+ { 0x0a20, 0x0c80, 0x0000, 0x0100, 0x0a68, 0x0018, 0x0070, 0x0058 },
+ { 0x0c80, 0x0e00, 0x0000, 0x0100, 0x0c40, 0x0018, 0x0070, 0x0040 },
+
+ { 0x0380, 0x07c0, 0x0100, 0x0200, 0x0038, 0x0418, 0x0070, 0x00a8 },
+ { 0xff }
+};
+
+static const struct cchip_mapping level01[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0000, 0x0120, 0x0100, 0x0200, 0x0000, 0x0208, 0x0040, 0x0070 },
+
+ { 0x0000, 0x0120, 0x0200, 0x0300, 0x0000, 0x0208, 0x0040, 0x0070 },
+ { 0x0120, 0x0460, 0x0200, 0x0300, 0x0080, 0x0218, 0x00b0, 0x0080 },
+ { 0x0460, 0x0690, 0x0200, 0x0278, 0x0450, 0x01f8, 0x0090, 0x0030 },
+ { 0x0460, 0x0690, 0x0278, 0x0300, 0x0450, 0x0218, 0x00a0, 0x00a0 },
+ { 0x0690, 0x07d0, 0x0200, 0x0278, 0x0618, 0x01f8, 0x00a0, 0x0040 },
+ { 0x0690, 0x07d0, 0x0278, 0x0300, 0x0628, 0x0218, 0x00a8, 0x00b0 },
+ { 0x07d0, 0x08b0, 0x0200, 0x0300, 0x07a8, 0x0218, 0x0090, 0x0060 },
+ { 0x08b0, 0x09d0, 0x0200, 0x0300, 0x0840, 0x0218, 0x0088, 0x0060 },
+ { 0x09d0, 0x0b00, 0x0200, 0x0300, 0x0958, 0x0218, 0x00a0, 0x0070 },
+ { 0x0b00, 0x0c90, 0x0200, 0x0300, 0x0a98, 0x0218, 0x0088, 0x0050 },
+ { 0x0c90, 0x0e00, 0x0200, 0x0300, 0x0c20, 0x0200, 0x00a0, 0x0028 },
+ { 0xff }
+};
+
+static const struct cchip_mapping level02[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0000, 0x01c0, 0x04f4, 0x05f8, 0x0000, 0x0518, 0x0068, 0x00b0 },
+ { 0x01c0, 0x03c0, 0x04f4, 0x05f8, 0x00d0, 0x0518, 0x0078, 0x0060 },
+ { 0x03c0, 0x06e0, 0x04f4, 0x05f8, 0x02f0, 0x0518, 0x0078, 0x0048 },
+ { 0x06e0, 0x0840, 0x04f4, 0x05f8, 0x0670, 0x0518, 0x0078, 0x0048 },
+ { 0x0840, 0x0a10, 0x04f4, 0x05f8, 0x07d8, 0x0518, 0x0070, 0x0060 },
+ { 0x0a10, 0x0b80, 0x04f4, 0x05f8, 0x09e8, 0x0500, 0x0080, 0x0080 },
+ { 0x0b80, 0x1090, 0x04f4, 0x05f8, 0x0b20, 0x0418, 0x0070, 0x0080 },
+
+ { 0x0230, 0x03a0, 0x040c, 0x04f4, 0x02e8, 0x04b0, 0x0080, 0x0090 },
+ { 0x03a0, 0x03b0, 0x040c, 0x04f4, 0x0278, 0x0318, 0x0078, 0x00a8 },
+ { 0x0520, 0x08e0, 0x040c, 0x04f4, 0x0608, 0x0318, 0x0080, 0x0058 },
+ { 0x08e0, 0x0a00, 0x040c, 0x04f4, 0x0878, 0x0318, 0x0078, 0x0098 },
+
+ { 0x0230, 0x03b0, 0x02f8, 0x040c, 0x0278, 0x0318, 0x0078, 0x00a8 },
+ { 0x03b0, 0x0520, 0x02f8, 0x040c, 0x0390, 0x0318, 0x0070, 0x00b8 },
+ { 0x0520, 0x08e0, 0x02f8, 0x040c, 0x0608, 0x0318, 0x0080, 0x0058 },
+ { 0x08e0, 0x0a00, 0x02f8, 0x040c, 0x0878, 0x0318, 0x0078, 0x0098 }
+};
+
+static const struct cchip_mapping level03[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0000, 0x0280, 0x0618, 0x06f8, 0x00d8, 0x0608, 0x00b8, 0x00a0 },
+ { 0x0280, 0x0380, 0x0618, 0x06f8, 0x02b0, 0x0608, 0x00b8, 0x0090 },
+ { 0x0380, 0x0620, 0x0618, 0x06f8, 0x02c8, 0x0608, 0x00c0, 0x0090 },
+ { 0x0620, 0x0760, 0x0618, 0x06f8, 0x0630, 0x0608, 0x00c0, 0x0028 },
+ { 0x0760, 0x0910, 0x0618, 0x06f8, 0x07e8, 0x0608, 0x00b8, 0x0078 },
+ { 0x0910, 0x0a30, 0x0618, 0x06f8, 0x0930, 0x0608, 0x00b8, 0x0080 },
+ { 0x0a30, 0x0b60, 0x0618, 0x06f8, 0x0a48, 0x0608, 0x00c0, 0x0068 },
+
+ { 0x0090, 0x01d0, 0x06f8, 0x07f8, 0x0020, 0x0610, 0x00b8, 0x00a8 },
+ { 0xff }
+};
+
+static const struct cchip_mapping level04[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0390, 0x06a0, 0x0704, 0x0804, 0x0560, 0x0708, 0x0068, 0x0090 },
+ { 0x06a0, 0x0850, 0x0704, 0x0804, 0x0600, 0x0708, 0x0080, 0x0070 },
+ { 0x0850, 0x09e0, 0x0704, 0x0804, 0x0860, 0x0708, 0x0060, 0x0090 },
+ { 0x09e0, 0x0c00, 0x0704, 0x0804, 0x09c0, 0x0708, 0x0068, 0x0080 },
+ { 0x0c00, 0x0da0, 0x0704, 0x0804, 0x0c58, 0x0708, 0x0068, 0x0070 },
+ { 0x0da0, 0x0f80, 0x0704, 0x0804, 0x0d80, 0x0708, 0x0070, 0x00b0 },
+ { 0x0f80, 0x1080, 0x0704, 0x0804, 0x0ea8, 0x0708, 0x0070, 0x00b0 },
+ { 0x1080, 0x1230, 0x0704, 0x0804, 0x0fc0, 0x0708, 0x0080, 0x0030 },
+ { 0xff }
+};
+
+static const struct cchip_mapping level05[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x1280, 0x1370, 0x800, 0x900, 0x1288, 0x0808, 0x0099, 0x00ce },
+ { 0x1370, 0x14e0, 0x800, 0x900, 0x12f0, 0x0808, 0x0078, 0x0028 },
+ { 0x14e0, 0x1660, 0x800, 0x900, 0x1488, 0x0808, 0x0080, 0x0070 },
+ { 0x1660, 0x18f0, 0x800, 0x900, 0x1600, 0x0808, 0x0080, 0x0090 },
+
+ { 0x1480, 0x1640, 0x6f8, 0x800, 0x1508, 0x0708, 0x0080, 0x0090 },
+ { 0x1640, 0x1760, 0x6f8, 0x800, 0x16e8, 0x06f0, 0x0080, 0x0058 },
+ { 0x1760, 0x1900, 0x6f8, 0x800, 0x1770, 0x0728, 0x0080, 0x0080 },
+
+ { 0x14e0, 0x1570, 0x6a0, 0x6f8, 0x1508, 0x05e8, 0x0040, 0x0088 },
+ { 0x1570, 0x1680, 0x6a0, 0x6f8, 0x1568, 0x0608, 0x0080, 0x0090 },
+ { 0x1680, 0x1770, 0x6a0, 0x6f8, 0x1640, 0x05e8, 0x0088, 0x0088 },
+ { 0x1770, 0x18d0, 0x6a0, 0x6f8, 0x1770, 0x0650, 0x00d8, 0x0070 },
+
+ { 0x14e0, 0x1570, 0x664, 0x6a0, 0x1508, 0x05e8, 0x0040, 0x0088 },
+ { 0x1570, 0x1680, 0x664, 0x6a0, 0x1578, 0x05d0, 0x0098, 0x0060 },
+ { 0x1680, 0x1770, 0x664, 0x6a0, 0x1640, 0x05e8, 0x0088, 0x0088 },
+ { 0x1770, 0x18d0, 0x664, 0x6a0, 0x1770, 0x0650, 0x00d8, 0x0070 },
+
+ { 0x14e0, 0x1570, 0x624, 0x664, 0x1508, 0x05e8, 0x0040, 0x0088 },
+ { 0x1570, 0x1680, 0x624, 0x664, 0x1578, 0x05d0, 0x0098, 0x0060 },
+ { 0x1680, 0x1770, 0x624, 0x664, 0x1640, 0x05e8, 0x0088, 0x0088 },
+ { 0x1770, 0x18d0, 0x624, 0x664, 0x1770, 0x0588, 0x0090, 0x0088 },
+
+ { 0x14e0, 0x1570, 0x5d4, 0x624, 0x1508, 0x05e8, 0x0040, 0x0088 },
+ { 0x1570, 0x1680, 0x5d4, 0x624, 0x1578, 0x05d0, 0x0098, 0x0060 },
+ { 0x1680, 0x16a0, 0x5d4, 0x624, 0x1630, 0x0528, 0x0088, 0x0088 },
+ { 0x16a0, 0x1770, 0x5d4, 0x624, 0x1658, 0x0528, 0x0088, 0x0088 },
+ { 0x1770, 0x18d0, 0x5d4, 0x624, 0x1770, 0x0588, 0x0090, 0x0088 },
+
+ { 0x14e0, 0x15d0, 0x5a4, 0x5d4, 0x1508, 0x0580, 0x0040, 0x0080 },
+ { 0x15d0, 0x15f0, 0x5a4, 0x5d4, 0x1508, 0x04f8, 0x0080, 0x0060 },
+ { 0x15f0, 0x1630, 0x5a4, 0x5d4, 0x1580, 0x04f8, 0x0068, 0x0080 },
+ { 0x1630, 0x16a0, 0x5a4, 0x5d4, 0x1630, 0x0530, 0x0088, 0x0080 },
+ { 0x16a0, 0x17b0, 0x5a4, 0x5d4, 0x1658, 0x0528, 0x0088, 0x0088 },
+ { 0x17b0, 0x18c0, 0x5a4, 0x5d4, 0x1770, 0x0508, 0x0098, 0x0088 },
+
+ { 0x14e0, 0x15f0, 0x4f8, 0x5a4, 0x1508, 0x04f8, 0x0080, 0x0060 },
+ { 0x15f0, 0x1670, 0x4f8, 0x5a4, 0x15c8, 0x0548, 0x00a8, 0x0070 },
+ { 0x1670, 0x1750, 0x4f8, 0x5a4, 0x1680, 0x0528, 0x00a8, 0x0070 },
+ { 0x1750, 0x18d0, 0x4f8, 0x5a4, 0x1770, 0x04a0, 0x00a8, 0x0078 },
+
+ { 0x14e0, 0x1630, 0x478, 0x4f8, 0x1508, 0x04f8, 0x0080, 0x0060 },
+ { 0x1630, 0x16b0, 0x478, 0x4f8, 0x15d0, 0x0440, 0x00b8, 0x0078 },
+ { 0x16b0, 0x1760, 0x478, 0x4f8, 0x1660, 0x0460, 0x0080, 0x0060 },
+ { 0x1760, 0x17f0, 0x478, 0x4f8, 0x1738, 0x0420, 0x0090, 0x0070 },
+ { 0x17f0, 0x18d0, 0x478, 0x4f8, 0x1770, 0x0450, 0x00d8, 0x0060 },
+
+ { 0x14e0, 0x16d0, 0x3f8, 0x478, 0x1500, 0x03e8, 0x0090, 0x0058 },
+ { 0x16d0, 0x17f0, 0x3f8, 0x478, 0x16e0, 0x0398, 0x0068, 0x0068 },
+ { 0x17f0, 0x18d0, 0x3f8, 0x478, 0x1770, 0x0450, 0x00d8, 0x0060 },
+
+ { 0x14e0, 0x1610, 0x35c, 0x3f8, 0x1518, 0x0368, 0x0090, 0x0058 },
+ { 0x1610, 0x16b0, 0x35c, 0x3f8, 0x15b0, 0x0340, 0x0098, 0x0058 },
+ { 0x16b0, 0x17e0, 0x35c, 0x3f8, 0x1728, 0x0320, 0x0068, 0x0068 },
+ { 0x17e0, 0x18d0, 0x35c, 0x3f8, 0x1770, 0x0330, 0x00c0, 0x0080 },
+
+ { 0x14e0, 0x1650, 0x2f8, 0x35c, 0x1518, 0x0368, 0x0090, 0x0058 },
+ { 0x1650, 0x17d0, 0x2f8, 0x35c, 0x1630, 0x02b0, 0x0088, 0x0060 },
+ { 0x17d0, 0x18d0, 0x2f8, 0x35c, 0x1740, 0x02a8, 0x0090, 0x0058 },
+
+ { 0x14e0, 0x1650, 0x268, 0x2f8, 0x15a8, 0x0268, 0x0080, 0x0058 },
+ { 0x1650, 0x17b0, 0x268, 0x2f8, 0x1650, 0x0250, 0x0080, 0x0058 },
+ { 0x17b0, 0x18d0, 0x268, 0x2f8, 0x1740, 0x02a8, 0x0090, 0x0058 },
+
+ { 0x14e0, 0x15f0, 0x1d8, 0x268, 0x1508, 0x0208, 0x0078, 0x0060 },
+ { 0x15f0, 0x17b0, 0x1d8, 0x268, 0x16c8, 0x0178, 0x0080, 0x0060 },
+ { 0x17b0, 0x18d0, 0x1d8, 0x268, 0x1740, 0x02a8, 0x0090, 0x0058 },
+
+ { 0x14e0, 0x18d0, 0x158, 0x1d8, 0x1610, 0x0110, 0x0078, 0x0068 },
+ { 0x14e0, 0x18d0, 0x158, 0x1d8, 0x1610, 0x0110, 0x0078, 0x0068 },
+
+ { 0x14d0, 0x18d0, 0x15c, 0x19c, 0x1618, 0x0110, 0x0078, 0x0068 },
+ { 0x14d0, 0x15b0, 0x19c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 },
+ { 0x15b0, 0x1670, 0x19c, 0x1bc, 0x1580, 0x0128, 0x0070, 0x0080 },
+ { 0x1670, 0x18d0, 0x19c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 },
+ { 0x14d0, 0x14f0, 0x1bc, 0x1dc, 0x1618, 0x0110, 0x0078, 0x0068 },
+ { 0x14f0, 0x15f0, 0x1bc, 0x1dc, 0x1508, 0x0208, 0x0078, 0x0060 },
+ { 0x15f0, 0x1670, 0x1bc, 0x1dc, 0x1580, 0x0128, 0x0070, 0x0080 },
+ { 0x1670, 0x18d0, 0x1bc, 0x1dc, 0x1618, 0x0110, 0x0078, 0x0068 },
+
+ { 0x14d0, 0x14f0, 0x1bc, 0x1dc, 0x1618, 0x0110, 0x0078, 0x0068 },
+ { 0x14f0, 0x1670, 0x18c, 0x1bc, 0x1508, 0x0208, 0x0078, 0x0060 },
+
+ { 0x14d0, 0x15b0, 0x18c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 },
+ { 0x15b0, 0x1670, 0x18c, 0x1bc, 0x1580, 0x0128, 0x0070, 0x0080 },
+ { 0x1670, 0x18d0, 0x18c, 0x1bc, 0x1618, 0x0110, 0x0078, 0x0068 },
+
+ { 0x14d0, 0x18d0, 0x15c, 0x18c, 0x1618, 0x0110, 0x0078, 0x0068 },
+
+ { 0x14e0, 0x1840, 0x098, 0x15c, 0x16b0, 0x00b0, 0x0088, 0x0060 },
+ { 0x1840, 0x18d0, 0x088, 0x15c, 0x1770, 0x0118, 0x00c0, 0x0060 },
+
+ { 0x1250, 0x15a0, 0x000, 0x108, 0x1500, 0x0000, 0x0080, 0x0048 },
+ { 0x15a0, 0x16f0, 0x000, 0x098, 0x1698, 0x0000, 0x0080, 0x0050 },
+ { 0x16f0, 0x18d0, 0x000, 0x088, 0x1770, 0x0000, 0x00b8, 0x0060 },
+
+ { 0x1250, 0x14e0, 0x000, 0x10c, 0x1500, 0x0000, 0x0080, 0x0048 },
+ { 0x14e0, 0x15a0, 0x000, 0x09c, 0x1500, 0x0000, 0x0080, 0x0048 },
+ { 0x15a0, 0x16f0, 0x000, 0x09c, 0x1698, 0x0000, 0x0080, 0x0050 },
+ { 0x16f0, 0x1830, 0x000, 0x09c, 0x1770, 0x0000, 0x00b8, 0x0060 },
+ { 0x1830, 0x18d0, 0x000, 0x09c, 0x1770, 0x0118, 0x00c0, 0x0060 },
+
+ { 0x14e0, 0x1830, 0x09c, 0x158, 0x16b0, 0x00b0, 0x0088, 0x0060 },
+ { 0x1830, 0x18d0, 0x09c, 0x158, 0x1770, 0x0118, 0x00c0, 0x0060 },
+
+ //--------------------------
+ { 0x14e0, 0x1650, 0x29c, 0x2f0, 0x15a8, 0x0268, 0x0080, 0x0058 },
+ { 0x14e0, 0x1610, 0x2f0, 0x3fc, 0x1518, 0x0368, 0x0090, 0x0058 },
+ { 0x14e0, 0x1630, 0x3fc, 0x46c, 0x1500, 0x03e8, 0x0090, 0x0058 },
+ { 0x14e0, 0x1630, 0x46c, 0x51c, 0x1508, 0x04f8, 0x0080, 0x0060 },
+ { 0x14e0, 0x15f0, 0x51c, 0x59c, 0x1508, 0x04f8, 0x0080, 0x0060 },
+ { 0x14e0, 0x15f0, 0x59c, 0x5d8, 0x1508, 0x0580, 0x0040, 0x0080 },
+ { 0x14e0, 0x1570, 0x5d8, 0x700, 0x1508, 0x05e8, 0x0040, 0x0088 },
+ { 0x1480, 0x1640, 0x700, 0x808, 0x1508, 0x0708, 0x0080, 0x0090 },
+
+ { 0x0000, 0x18d0, 0x000, 0x900, 0x1288, 0x0808, 0x0099, 0x00ce },
+ { 0xff }
+};
+
+static const struct cchip_mapping level06[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0000, 0x01a0, 0x0904, 0x0a04, 0x00d0, 0x0908, 0x00b0, 0x0090 },
+ { 0x01a0, 0x04e0, 0x0904, 0x0a04, 0x03d0, 0x0908, 0x00b0, 0x0038 },
+ { 0x04e0, 0x0740, 0x0904, 0x0a04, 0x0660, 0x0908, 0x00b0, 0x0098 },
+ { 0x0740, 0x0950, 0x0904, 0x0a04, 0x07e8, 0x0908, 0x00b8, 0x00b8 },
+ { 0x0950, 0x0a80, 0x0904, 0x0a04, 0x08f8, 0x0908, 0x00b0, 0x0080 },
+ { 0x0a80, 0x0da0, 0x0904, 0x0a04, 0x0cd0, 0x0908, 0x00b8, 0x00b0 },
+ { 0x0da0, 0x0f40, 0x0904, 0x0a04, 0x0e08, 0x0908, 0x00b8, 0x0070 },
+ { 0x0f40, 0x10c0, 0x0904, 0x0a04, 0x0fe8, 0x0908, 0x00b8, 0x0098 },
+ { 0x10c0, 0x1370, 0x0904, 0x0a04, 0x1140, 0x0908, 0x00b8, 0x0068 },
+ { 0xff }
+};
+
+static const struct cchip_mapping level07[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0000, 0x0570, 0x0804, 0x0904, 0x0000, 0x0808, 0x0028, 0x00b8 },
+ { 0xff }
+};
+
+static const struct cchip_mapping level08[] =
+{
+ /* X1 X2 Y1 Y2 => SX SY PX PY */
+ { 0x0000, 0xf000, 0x0000, 0xf000, 0x06f8, 0x0808, 0x0028, 0x00b8 },
+ { 0xff }
+};
+
+static const struct cchip_mapping* levelData[]=
+{
+ level00,
+ level01,
+ level02,
+ level03,
+ level04,
+ level05,
+ level06,
+ level07,
+ level08
+};
+
+static void WriteLevelData(void)
+{
+ int i;
+
+ for (i = 0; i < 13; i++)
+ {
+ UINT16 v = CLEV[current_round][i];
+
+ cval[2 * i + 0] = v & 0xff;
+ cval[2 * i + 1] = v >> 8;
+ }
+}
+
+static void WriteRestartPos(int level)
+{
+ /*
+ Cval0/1 = scroll x position
+ Cval4/5 = player x screen position
+ Cval2/3 = scroll y position
+ Cval6/7 = player y screen position
+
+ These are combined to find the absolute player position
+ on the map, which is then given to the C-Chip in order
+ for the restart position to be returned.
+ */
+
+ int x = cval[0] + 256 * cval[1] + cval[4] + 256 * cval[5];
+ int y = cval[2] + 256 * cval[3] + cval[6] + 256 * cval[7];
+
+ const struct cchip_mapping* thisLevel=levelData[level];
+
+ while (thisLevel->xmin!=0xff)
+ {
+ if (x >= thisLevel->xmin && x < thisLevel->xmax &&
+ y >= thisLevel->ymin && y < thisLevel->ymax)
+ {
+ cval[0] = thisLevel->sx & 0xff;
+ cval[1] = thisLevel->sx >> 8;
+ cval[2] = thisLevel->sy & 0xff;
+ cval[3] = thisLevel->sy >> 8;
+ cval[4] = thisLevel->px & 0xff;
+ cval[5] = thisLevel->px >> 8;
+ cval[6] = thisLevel->py & 0xff;
+ cval[7] = thisLevel->py >> 8;
+
+ // Restart position found ok
+ restart_status=0;
+
+ return;
+ }
+
+ thisLevel++;
+ }
+
+ // No restart position found for this position (cval0-7 confirmed unchanged in this case)
+ restart_status=0xff;
+}
+
+
+/*************************************
+ *
+ * Writes to C-Chip - Important Bits
+ *
+ *************************************/
+
+WRITE16_HANDLER( bonzeadv_cchip_ctrl_w )
+{
+ /* value 2 is written here */
+}
+
+WRITE16_HANDLER( bonzeadv_cchip_bank_w )
+{
+ current_bank = data & 7;
+}
+
+WRITE16_HANDLER( bonzeadv_cchip_ram_w )
+{
+// if (activecpu_get_pc()!=0xa028)
+// logerror("%08x: write %04x %04x cchip\n", activecpu_get_pc(), offset, data);
+
+ if (current_bank == 0)
+ {
+ if (offset == 0x08)
+ {
+ cc_port = data;
+
+ coin_lockout_w(1, data & 0x80);
+ coin_lockout_w(0, data & 0x40);
+ coin_counter_w(1, data & 0x20);
+ coin_counter_w(0, data & 0x10);
+ }
+
+ if (offset == 0x0e && data != 0x00)
+ {
+ WriteRestartPos(current_round);
+ }
+
+ if (offset == 0x0f && data != 0x00)
+ {
+ WriteLevelData();
+ }
+
+ if (offset == 0x10)
+ {
+ current_round = data;
+ }
+
+ if (offset >= 0x11 && offset <= 0x2a)
+ {
+ cval[offset - 0x11] = data;
+ }
+ }
+}
+
+/*************************************
+ *
+ * Reads from C-Chip
+ *
+ *************************************/
+
+READ16_HANDLER( bonzeadv_cchip_ctrl_r )
+{
+ /*
+ Bit 2 = Error signal
+ Bit 0 = Ready signal
+ */
+ return 0x01; /* Return 0x05 for C-Chip error */
+}
+
+READ16_HANDLER( bonzeadv_cchip_ram_r )
+{
+// logerror("%08x: read %04x cchip\n", activecpu_get_pc(), offset);
+
+ if (current_bank == 0)
+ {
+ switch (offset)
+ {
+ case 0x03: return readinputportbytag("800007"); /* STARTn + SERVICE1 */
+ case 0x04: return readinputportbytag("800009"); /* COINn */
+ case 0x05: return readinputportbytag("80000B"); /* Player controls + TILT */
+ case 0x06: return readinputportbytag("80000D"); /* Player controls (cocktail) */
+ case 0x08: return cc_port;
+ }
+
+ if (offset == 0x0e)
+ {
+ return restart_status; /* 0xff signals error, 0 signals ok */
+ }
+
+ if (offset >= 0x11 && offset <= 0x2a)
+ {
+ return cval[offset - 0x11];
+ }
+ }
+
+ return 0;
+}
diff --git a/src/mame/machine/bsktball.c b/src/mame/machine/bsktball.c
new file mode 100644
index 00000000000..e84855d550d
--- /dev/null
+++ b/src/mame/machine/bsktball.c
@@ -0,0 +1,169 @@
+/***************************************************************************
+
+ Atari Basketball hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "bsktball.h"
+
+static int LD1=0;
+static int LD2=0;
+static UINT32 NMION = 0;
+
+/***************************************************************************
+bsktball_nmion_w
+***************************************************************************/
+WRITE8_HANDLER( bsktball_nmion_w )
+{
+ NMION = offset & 0x01;
+}
+
+/***************************************************************************
+bsktball_interrupt
+***************************************************************************/
+/* NMI every 32V, IRQ every VBLANK */
+INTERRUPT_GEN( bsktball_interrupt )
+{
+ static int i256V=0;
+
+ /* We mod by 8 because we're interrupting 8x per frame, 1 per 32V */
+ i256V=(i256V+1) % 8;
+
+ if (i256V==0)
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+ else if (NMION)
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+/***************************************************************************
+bsktball_ld_w
+***************************************************************************/
+
+WRITE8_HANDLER( bsktball_ld1_w )
+{
+ LD1 = (offset & 0x01);
+}
+
+WRITE8_HANDLER( bsktball_ld2_w )
+{
+ LD2 = (offset & 0x01);
+}
+
+
+/***************************************************************************
+bsktball_in0_r
+***************************************************************************/
+
+READ8_HANDLER( bsktball_in0_r )
+{
+ static int DR0=0; /* PL2 H DIR */
+ static int DR1=0; /* PL2 V DIR */
+ static int DR2=0; /* PL1 H DIR */
+ static int DR3=0; /* PL1 V DIR */
+
+ static int last_p1_horiz=0;
+ static int last_p1_vert=0;
+ static int last_p2_horiz=0;
+ static int last_p2_vert=0;
+
+ int p1_horiz;
+ int p1_vert;
+ int p2_horiz;
+ int p2_vert;
+ int temp;
+
+ p1_horiz = input_port_0_r(offset);
+ p1_vert = input_port_1_r(offset);
+ p2_horiz = input_port_2_r(offset);
+ p2_vert = input_port_3_r(offset);
+
+ /* Set direction bits */
+
+ /* P1 H DIR */
+ if (p1_horiz > last_p1_horiz)
+ {
+ if ((p1_horiz-last_p1_horiz) > 128) DR2=0x40;
+ else DR2=0;
+ }
+ else if (p1_horiz < last_p1_horiz)
+ {
+ if ((last_p1_horiz-p1_horiz) > 128) DR2=0;
+ else DR2=0x40;
+ }
+
+ /* P1 V DIR */
+ if (p1_vert > last_p1_vert)
+ {
+ if ((p1_vert-last_p1_vert) > 128) DR3=0;
+ else DR3=0x80;
+ }
+ else if (p1_vert < last_p1_vert)
+ {
+ if ((last_p1_vert-p1_vert) > 128) DR3=0x80;
+ else DR3=0;
+ }
+
+ /* P2 H DIR */
+ if (p2_horiz > last_p2_horiz)
+ {
+ if ((p2_horiz-last_p2_horiz) > 128) DR0=0x10;
+ else DR0=0;
+ }
+ else if (p2_horiz < last_p2_horiz)
+ {
+ if ((last_p2_horiz-p2_horiz) > 128) DR0=0;
+ else DR0=0x10;
+ }
+
+ /* P2 V DIR */
+ if (p2_vert > last_p2_vert)
+ {
+ if ((p2_vert-last_p2_vert) > 128) DR1=0;
+ else DR1=0x20;
+ }
+ else if (p2_vert < last_p2_vert)
+ {
+ if ((last_p2_vert-p2_vert) > 128) DR1=0x20;
+ else DR1=0;
+ }
+
+
+ last_p1_horiz = p1_horiz;
+ last_p1_vert = p1_vert;
+ last_p2_horiz = p2_horiz;
+ last_p2_vert = p2_vert;
+
+ /* D0-D3 = Plyr 1 Horiz, D4-D7 = Plyr 1 Vert */
+ if ((LD1) & (LD2))
+ {
+ return ((p1_horiz & 0x0F) | ((p1_vert << 4) & 0xF0));
+ }
+ /* D0-D3 = Plyr 2 Horiz, D4-D7 = Plyr 2 Vert */
+ else if (LD2)
+ {
+ return ((p2_horiz & 0x0F) | ((p2_vert << 4) & 0xF0));
+ }
+ else
+ {
+ temp = input_port_4_r(offset) & 0x0F;
+ /* Remap button 1 back to the Start button */
+ /* NOTE: This is an ADDED feature, not a part of the original hardware! */
+ temp = (temp) & (temp>>2);
+
+ return (temp | DR0 | DR1 | DR2 | DR3);
+ }
+}
+
+/***************************************************************************
+bsktball_led_w
+***************************************************************************/
+WRITE8_HANDLER( bsktball_led1_w )
+{
+ set_led_status(0,offset & 0x01);
+}
+
+WRITE8_HANDLER( bsktball_led2_w )
+{
+ set_led_status(1,offset & 0x01);
+}
diff --git a/src/mame/machine/btime.c b/src/mame/machine/btime.c
new file mode 100644
index 00000000000..2d2c815ec5e
--- /dev/null
+++ b/src/mame/machine/btime.c
@@ -0,0 +1,93 @@
+
+#include "driver.h"
+
+
+#define BASE 0xb000
+
+
+static int protection_command;
+static int protection_status = 0;
+static int protection_value;
+static int protection_ret = 0;
+
+
+READ8_HANDLER( mmonkey_protection_r )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ int ret = 0;
+
+ if (offset == 0x0000) ret = protection_status;
+ else if (offset == 0x0e00) ret = protection_ret;
+ else if (offset >= 0x0d00 && offset <= 0x0d02) ret = RAM[BASE+offset]; /* addition result */
+ else logerror("Unknown protection read. PC=%04X Offset=%04X\n", activecpu_get_pc(), offset);
+
+ return ret;
+}
+
+
+
+WRITE8_HANDLER( mmonkey_protection_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+
+ if (offset == 0)
+ {
+ /* protection trigger */
+ if (data == 0)
+ {
+ int i,s1,s2,r;
+
+ switch (protection_command)
+ {
+ case 0: /* score addition */
+
+ s1 = ( 1 * (RAM[BASE+0x0d00] & 0x0f)) + ( 10 * (RAM[BASE+0x0d00] >> 4)) +
+ ( 100 * (RAM[BASE+0x0d01] & 0x0f)) + ( 1000 * (RAM[BASE+0x0d01] >> 4)) +
+ (10000 * (RAM[BASE+0x0d02] & 0x0f)) + (100000 * (RAM[BASE+0x0d02] >> 4));
+
+ s2 = ( 1 * (RAM[BASE+0x0d03] & 0x0f)) + ( 10 * (RAM[BASE+0x0d03] >> 4)) +
+ ( 100 * (RAM[BASE+0x0d04] & 0x0f)) + ( 1000 * (RAM[BASE+0x0d04] >> 4)) +
+ (10000 * (RAM[BASE+0x0d05] & 0x0f)) + (100000 * (RAM[BASE+0x0d05] >> 4));
+
+ r = s1 + s2;
+
+ RAM[BASE+0x0d00] = (r % 10); r /= 10;
+ RAM[BASE+0x0d00] |= ((r % 10) << 4); r /= 10;
+ RAM[BASE+0x0d01] = (r % 10); r /= 10;
+ RAM[BASE+0x0d01] |= ((r % 10) << 4); r /= 10;
+ RAM[BASE+0x0d02] = (r % 10); r /= 10;
+ RAM[BASE+0x0d02] |= ((r % 10) << 4);
+
+ break;
+
+ case 1: /* decryption */
+
+ /* Compute return value by searching the decryption table. */
+ /* During the search the status should be 2, but we're done */
+ /* instanteniously in emulation time */
+ for (i = 0; i < 0x100; i++)
+ {
+ if (RAM[BASE+0x0f00+i] == protection_value)
+ {
+ protection_ret = i;
+ break;
+ }
+ }
+ break;
+
+ default:
+ logerror("Unemulated protection command=%02X. PC=%04X\n", protection_command, activecpu_get_pc());
+ break;
+ }
+
+ protection_status = 0;
+ }
+ }
+ else if (offset == 0x0c00) protection_command = data;
+ else if (offset == 0x0e00) protection_value = data;
+ else if (offset >= 0x0f00) RAM[BASE+offset] = data; /* decrypt table */
+ else if (offset >= 0x0d00 && offset <= 0x0d05) RAM[BASE+offset] = data; /* source table */
+ else logerror("Unknown protection write=%02X. PC=%04X Offset=%04X\n", data, activecpu_get_pc(), offset);
+}
diff --git a/src/mame/machine/bublbobl.c b/src/mame/machine/bublbobl.c
new file mode 100644
index 00000000000..9f2812b5ac4
--- /dev/null
+++ b/src/mame/machine/bublbobl.c
@@ -0,0 +1,498 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/z80/z80.h"
+
+
+
+UINT8 *bublbobl_mcu_sharedram;
+extern int bublbobl_video_enable;
+
+
+WRITE8_HANDLER( bublbobl_bankswitch_w )
+{
+ UINT8 *ROM = memory_region(REGION_CPU1);
+
+ /* bits 0-2 select ROM bank */
+ memory_set_bankptr(1,&ROM[0x10000 + 0x4000 * ((data ^ 4) & 7)]);
+
+ /* bit 3 n.c. */
+
+ /* bit 4 resets second Z80 */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
+
+ /* bit 5 resets mcu */
+ if (Machine->drv->cpu[3].type != CPU_DUMMY) // only if we have a MCU
+ cpunum_set_input_line(3, INPUT_LINE_RESET, (data & 0x20) ? CLEAR_LINE : ASSERT_LINE);
+
+ /* bit 6 enables display */
+ bublbobl_video_enable = data & 0x40;
+
+ /* bit 7 flips screen */
+ flip_screen_set(data & 0x80);
+}
+
+WRITE8_HANDLER( tokio_bankswitch_w )
+{
+ UINT8 *ROM = memory_region(REGION_CPU1);
+
+ /* bits 0-2 select ROM bank */
+ memory_set_bankptr(1,&ROM[0x10000 + 0x4000 * (data & 7)]);
+
+ /* bits 3-7 unknown */
+}
+
+WRITE8_HANDLER( tokio_videoctrl_w )
+{
+ /* bit 7 flips screen */
+ flip_screen_set(data & 0x80);
+
+ /* other bits unknown */
+}
+
+WRITE8_HANDLER( bublbobl_nmitrigger_w )
+{
+ cpunum_set_input_line(1,INPUT_LINE_NMI,PULSE_LINE);
+}
+
+
+static UINT8 tokio_prot_data[] =
+{
+ 0x6c,
+ 0x7f,0x5f,0x7f,0x6f,0x5f,0x77,0x5f,0x7f,0x5f,0x7f,0x5f,0x7f,0x5b,0x7f,0x5f,0x7f,
+ 0x5f,0x77,0x59,0x7f,0x5e,0x7e,0x5f,0x6d,0x57,0x7f,0x5d,0x7d,0x5f,0x7e,0x5f,0x7f,
+ 0x5d,0x7d,0x5f,0x7e,0x5e,0x79,0x5f,0x7f,0x5f,0x7f,0x5d,0x7f,0x5f,0x7b,0x5d,0x7e,
+ 0x5f,0x7f,0x5d,0x7d,0x5f,0x7e,0x5e,0x7e,0x5f,0x7d,0x5f,0x7f,0x5f,0x7e,0x7f,0x5f,
+ 0x01,0x00,0x02,0x01,0x01,0x01,0x03,0x00,0x05,0x02,0x04,0x01,0x03,0x00,0x05,0x01,
+ 0x02,0x03,0x00,0x04,0x04,0x01,0x02,0x00,0x05,0x03,0x02,0x01,0x04,0x05,0x00,0x03,
+ 0x00,0x05,0x02,0x01,0x03,0x04,0x05,0x00,0x01,0x04,0x04,0x02,0x01,0x04,0x01,0x00,
+ 0x03,0x01,0x02,0x05,0x00,0x03,0x00,0x01,0x02,0x00,0x03,0x04,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x00,
+ 0x01,0x02,0x01,0x00,0x00,0x00,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x01,0x02,0x00,0x01,0x01,0x00,0x00,0x02,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01
+};
+static int tokio_prot_count;
+
+READ8_HANDLER( tokio_mcu_r )
+{
+ tokio_prot_count %= sizeof(tokio_prot_data);
+ return tokio_prot_data[tokio_prot_count++];
+}
+
+READ8_HANDLER( tokiob_mcu_r )
+{
+ return 0xbf; /* ad-hoc value set to pass initial testing */
+}
+
+
+
+static int sound_nmi_enable,pending_nmi;
+
+static TIMER_CALLBACK( nmi_callback )
+{
+ if (sound_nmi_enable) cpunum_set_input_line(2,INPUT_LINE_NMI,PULSE_LINE);
+ else pending_nmi = 1;
+}
+
+WRITE8_HANDLER( bublbobl_sound_command_w )
+{
+ soundlatch_w(offset,data);
+ timer_call_after_resynch(data,nmi_callback);
+}
+
+WRITE8_HANDLER( bublbobl_sh_nmi_disable_w )
+{
+ sound_nmi_enable = 0;
+}
+
+WRITE8_HANDLER( bublbobl_sh_nmi_enable_w )
+{
+ sound_nmi_enable = 1;
+ if (pending_nmi)
+ {
+ cpunum_set_input_line(2,INPUT_LINE_NMI,PULSE_LINE);
+ pending_nmi = 0;
+ }
+}
+
+
+
+
+
+/***************************************************************************
+
+Bubble Bobble MCU
+
+***************************************************************************/
+
+static UINT8 ddr1, ddr2, ddr3, ddr4;
+static UINT8 port1_in, port2_in, port3_in, port4_in;
+static UINT8 port1_out, port2_out, port3_out, port4_out;
+
+READ8_HANDLER( bublbobl_mcu_ddr1_r )
+{
+ return ddr1;
+}
+
+WRITE8_HANDLER( bublbobl_mcu_ddr1_w )
+{
+ ddr1 = data;
+}
+
+READ8_HANDLER( bublbobl_mcu_ddr2_r )
+{
+ return ddr2;
+}
+
+WRITE8_HANDLER( bublbobl_mcu_ddr2_w )
+{
+ ddr2 = data;
+}
+
+READ8_HANDLER( bublbobl_mcu_ddr3_r )
+{
+ return ddr3;
+}
+
+WRITE8_HANDLER( bublbobl_mcu_ddr3_w )
+{
+ ddr3 = data;
+}
+
+READ8_HANDLER( bublbobl_mcu_ddr4_r )
+{
+ return ddr4;
+}
+
+WRITE8_HANDLER( bublbobl_mcu_ddr4_w )
+{
+ ddr4 = data;
+}
+
+READ8_HANDLER( bublbobl_mcu_port1_r )
+{
+//logerror("%04x: 6801U4 port 1 read\n",activecpu_get_pc());
+ port1_in = readinputport(0);
+ return (port1_out & ddr1) | (port1_in & ~ddr1);
+}
+
+WRITE8_HANDLER( bublbobl_mcu_port1_w )
+{
+//logerror("%04x: 6801U4 port 1 write %02x\n",activecpu_get_pc(),data);
+
+ // bit 4: coin lockout
+ coin_lockout_global_w(~data & 0x10);
+
+ // bit 5: select 1-way or 2-way coin counter
+
+ // bit 6: trigger IRQ on main CPU (jumper switchable to vblank)
+ // trigger on high->low transition
+ if ((port1_out & 0x40) && (~data & 0x40))
+ {
+// logerror("triggering IRQ on main CPU\n");
+ cpunum_set_input_line_vector(0,0,bublbobl_mcu_sharedram[0]);
+ cpunum_set_input_line(0,0,HOLD_LINE);
+ }
+
+ // bit 7: select read or write shared RAM
+
+ port1_out = data;
+}
+
+READ8_HANDLER( bublbobl_mcu_port2_r )
+{
+//logerror("%04x: 6801U4 port 2 read\n",activecpu_get_pc());
+ return (port2_out & ddr2) | (port2_in & ~ddr2);
+}
+
+WRITE8_HANDLER( bublbobl_mcu_port2_w )
+{
+//logerror("%04x: 6801U4 port 2 write %02x\n",activecpu_get_pc(),data);
+
+ // bits 0-3: bits 8-11 of shared RAM address
+
+ // bit 4: clock (goes to PAL A78-04.12)
+ // latch on low->high transition
+ if ((~port2_out & 0x10) && (data & 0x10))
+ {
+ int address = port4_out | ((data & 0x0f) << 8);
+
+ if (port1_out & 0x80)
+ {
+ // read
+ if ((address & 0x0800) == 0x0000)
+ port3_in = readinputport((address & 3) + 1);
+ else if ((address & 0x0c00) == 0x0c00)
+ port3_in = bublbobl_mcu_sharedram[address & 0x03ff];
+// logerror("reading %02x from shared RAM %04x\n",port3_in,address);
+ }
+ else
+ {
+ // write
+// logerror("writing %02x to shared RAM %04x\n",port3_out,address);
+ if ((address & 0x0c00) == 0x0c00)
+ bublbobl_mcu_sharedram[address & 0x03ff] = port3_out;
+ }
+ }
+
+ port2_out = data;
+}
+
+READ8_HANDLER( bublbobl_mcu_port3_r )
+{
+//logerror("%04x: 6801U4 port 3 read\n",activecpu_get_pc());
+ return (port3_out & ddr3) | (port3_in & ~ddr3);
+}
+
+WRITE8_HANDLER( bublbobl_mcu_port3_w )
+{
+//logerror("%04x: 6801U4 port 3 write %02x\n",activecpu_get_pc(),data);
+
+ port3_out = data;
+}
+
+READ8_HANDLER( bublbobl_mcu_port4_r )
+{
+//logerror("%04x: 6801U4 port 4 read\n",activecpu_get_pc());
+ return (port4_out & ddr4) | (port4_in & ~ddr4);
+}
+
+WRITE8_HANDLER( bublbobl_mcu_port4_w )
+{
+//logerror("%04x: 6801U4 port 4 write %02x\n",activecpu_get_pc(),data);
+
+ // bits 0-7 of shared RAM address
+
+ port4_out = data;
+}
+
+/***************************************************************************
+
+Bobble Bobble protection (IC43). This appears to be a PAL.
+
+Note: the checks on the values returned by ic43_b_r are actually patched out
+in boblbobl, so they don't matter. All checks are patched out in sboblbob.
+
+***************************************************************************/
+
+static int ic43_a,ic43_b;
+
+
+READ8_HANDLER( boblbobl_ic43_a_r )
+{
+// if (offset >= 2)
+// logerror("%04x: ic43_a_r (offs %d) res = %02x\n",activecpu_get_pc(),offset,res);
+
+ if (offset == 0)
+ return ic43_a << 4;
+ else
+ return mame_rand(Machine) & 0xff;
+}
+
+WRITE8_HANDLER( boblbobl_ic43_a_w )
+{
+ int res = 0;
+
+ switch (offset)
+ {
+ case 0:
+ if (~ic43_a & 8) res ^= 1;
+ if (~ic43_a & 1) res ^= 2;
+ if (~ic43_a & 1) res ^= 4;
+ if (~ic43_a & 2) res ^= 4;
+ if (~ic43_a & 4) res ^= 8;
+ break;
+ case 1:
+ if (~ic43_a & 8) res ^= 1;
+ if (~ic43_a & 2) res ^= 1;
+ if (~ic43_a & 8) res ^= 2;
+ if (~ic43_a & 1) res ^= 4;
+ if (~ic43_a & 4) res ^= 8;
+ break;
+ case 2:
+ if (~ic43_a & 4) res ^= 1;
+ if (~ic43_a & 8) res ^= 2;
+ if (~ic43_a & 2) res ^= 4;
+ if (~ic43_a & 1) res ^= 8;
+ if (~ic43_a & 4) res ^= 8;
+ break;
+ case 3:
+ if (~ic43_a & 2) res ^= 1;
+ if (~ic43_a & 4) res ^= 2;
+ if (~ic43_a & 8) res ^= 2;
+ if (~ic43_a & 8) res ^= 4;
+ if (~ic43_a & 1) res ^= 8;
+ break;
+ }
+ ic43_a = res;
+}
+
+WRITE8_HANDLER( boblbobl_ic43_b_w )
+{
+ static int xor[4] = { 4, 1, 8, 2 };
+
+// logerror("%04x: ic43_b_w (offs %d) %02x\n",activecpu_get_pc(),offset,data);
+ ic43_b = (data >> 4) ^ xor[offset];
+}
+
+READ8_HANDLER( boblbobl_ic43_b_r )
+{
+// logerror("%04x: ic43_b_r (offs %d)\n",activecpu_get_pc(),offset);
+ if (offset == 0)
+ return ic43_b << 4;
+ else
+ return 0xff; // not used?
+}
+
+
+
+/***************************************************************************
+
+ Bootleg Bubble Bobble 68705 protection interface
+
+ This is used by the 68705 bootleg version. Note that this actually
+ wasn't working 100%, for some unknown reason the enemy movement wasn't right.
+
+ The following is ENTIRELY GUESSWORK!!!
+
+***************************************************************************/
+
+
+INTERRUPT_GEN( bublbobl_m68705_interrupt )
+{
+ /* I don't know how to handle the interrupt line so I just toggle it every time. */
+ if (cpu_getiloops() & 1)
+ cpunum_set_input_line(3,0,CLEAR_LINE);
+ else
+ cpunum_set_input_line(3,0,ASSERT_LINE);
+}
+
+
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( bublbobl_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( bublbobl_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( bublbobl_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 W enables latch which holds data from main Z80 memory
+ * 1 W loads the latch which holds the low 8 bits of the address of
+ * the main Z80 memory location to access
+ * 2 W loads the latch which holds the high 4 bits of the address of
+ * the main Z80 memory location to access
+ * 00-07 = read input ports
+ * 0c-0f = access z80 memory at 0xfc00
+ * 3 W selects Z80 memory access direction (0 = write 1 = read)
+ * 4 W clocks main Z80 memory access (goes to a PAL)
+ * 5 W clocks a flip-flop which causes IRQ on the main Z80
+ * 6 W not used?
+ * 7 W not used?
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( bublbobl_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+static int address,latch;
+
+WRITE8_HANDLER( bublbobl_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x01) && (~data & 0x01) && (portB_out & 0x01))
+ {
+ portA_in = latch;
+ }
+ if ((ddrB & 0x02) && (data & 0x02) && (~portB_out & 0x02)) /* positive edge trigger */
+ {
+ address = (address & 0xff00) | portA_out;
+//logerror("%04x: 68705 address %02x\n",activecpu_get_pc(),portA_out);
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04)) /* positive edge trigger */
+ {
+ address = (address & 0x00ff) | ((portA_out & 0x0f) << 8);
+ }
+ if ((ddrB & 0x10) && (~data & 0x10) && (portB_out & 0x10))
+ {
+ if (data & 0x08) /* read */
+ {
+ if ((address & 0x0800) == 0x0000)
+ {
+//logerror("%04x: 68705 read input port %02x\n",activecpu_get_pc(),address);
+ latch = readinputport((address & 3) + 1);
+ }
+ else if ((address & 0x0c00) == 0x0c00)
+ {
+//logerror("%04x: 68705 read %02x from address %04x\n",activecpu_get_pc(),bublbobl_mcu_sharedram[address],address);
+ latch = bublbobl_mcu_sharedram[address & 0x03ff];
+ }
+ else
+logerror("%04x: 68705 unknown read address %04x\n",activecpu_get_pc(),address);
+ }
+ else /* write */
+ {
+ if ((address & 0x0c00) == 0x0c00)
+ {
+//logerror("%04x: 68705 write %02x to address %04x\n",activecpu_get_pc(),portA_out,address);
+ bublbobl_mcu_sharedram[address & 0x03ff] = portA_out;
+ }
+ else
+logerror("%04x: 68705 unknown write to address %04x\n",activecpu_get_pc(),address);
+ }
+ }
+ if ((ddrB & 0x20) && (~data & 0x20) && (portB_out & 0x20))
+ {
+ /* hack to get random EXTEND letters (who is supposed to do this? 68705? PAL?) */
+ bublbobl_mcu_sharedram[0x7c] = mame_rand(Machine)%6;
+
+ cpunum_set_input_line_vector(0,0,bublbobl_mcu_sharedram[0]);
+ cpunum_set_input_line(0,0,HOLD_LINE);
+ }
+ if ((ddrB & 0x40) && (~data & 0x40) && (portB_out & 0x40))
+ {
+logerror("%04x: 68705 unknown port B bit %02x\n",activecpu_get_pc(),data);
+ }
+ if ((ddrB & 0x80) && (~data & 0x80) && (portB_out & 0x80))
+ {
+logerror("%04x: 68705 unknown port B bit %02x\n",activecpu_get_pc(),data);
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( bublbobl_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
diff --git a/src/mame/machine/buggychl.c b/src/mame/machine/buggychl.c
new file mode 100644
index 00000000000..1229dd5d469
--- /dev/null
+++ b/src/mame/machine/buggychl.c
@@ -0,0 +1,148 @@
+#include "driver.h"
+#include "cpu/z80/z80.h"
+
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+
+/***************************************************************************
+
+ Buggy CHallenge 68705 protection interface
+
+ This is accurate. FairyLand Story seems to be identical.
+
+***************************************************************************/
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( buggychl_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( buggychl_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( buggychl_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ * parts in [ ] are optional (not used by buggychl)
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 n.c.
+ * 1 W IRQ ack and enable latch which holds data from main Z80 memory
+ * 2 W loads latch to Z80
+ * 3 W to Z80 BUSRQ (put it on hold?)
+ * 4 W n.c.
+ * 5 W [selects Z80 memory access direction (0 = write 1 = read)]
+ * 6 W [loads the latch which holds the low 8 bits of the address of
+ * the main Z80 memory location to access]
+ * 7 W [loads the latch which holds the high 8 bits of the address of
+ * the main Z80 memory location to access]
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( buggychl_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( buggychl_68705_portB_w )
+{
+logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ if (main_sent) cpunum_set_input_line(2,0,CLEAR_LINE);
+ main_sent = 0;
+logerror("read command %02x from main cpu\n",portA_in);
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+logerror("send command %02x to main cpu\n",portA_out);
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( buggychl_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+
+/*
+ * Port C connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 R 1 when pending command Z80->68705
+ * 1 R 0 when pending command 68705->Z80
+ */
+
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( buggychl_68705_portC_r )
+{
+ portC_in = 0;
+ if (main_sent) portC_in |= 0x01;
+ if (!mcu_sent) portC_in |= 0x02;
+logerror("%04x: 68705 port C read %02x\n",activecpu_get_pc(),portC_in);
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( buggychl_68705_portC_w )
+{
+logerror("%04x: 68705 port C write %02x\n",activecpu_get_pc(),data);
+ portC_out = data;
+}
+
+WRITE8_HANDLER( buggychl_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+
+WRITE8_HANDLER( buggychl_mcu_w )
+{
+logerror("%04x: mcu_w %02x\n",activecpu_get_pc(),data);
+ from_main = data;
+ main_sent = 1;
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+}
+
+READ8_HANDLER( buggychl_mcu_r )
+{
+logerror("%04x: mcu_r %02x\n",activecpu_get_pc(),from_mcu);
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( buggychl_mcu_status_r )
+{
+ int res = 0;
+
+ /* bit 0 = when 1, mcu is ready to receive data from main cpu */
+ /* bit 1 = when 1, mcu has sent data to the main cpu */
+//logerror("%04x: mcu_status_r\n",activecpu_get_pc());
+ if (!main_sent) res |= 0x01;
+ if (mcu_sent) res |= 0x02;
+
+ return res;
+}
diff --git a/src/mame/machine/carpolo.c b/src/mame/machine/carpolo.c
new file mode 100644
index 00000000000..6ebadeacd3e
--- /dev/null
+++ b/src/mame/machine/carpolo.c
@@ -0,0 +1,585 @@
+/***************************************************************************
+
+ Exidy Car Polo hardware
+
+ driver by Zsolt Vasvari
+
+****************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6502/m6502.h"
+#include "machine/6821pia.h"
+#include "machine/7474.h"
+#include "machine/74148.h"
+#include "machine/74153.h"
+#include "includes/carpolo.h"
+
+
+/*************************************
+ *
+ * Interrupt system
+ *
+ *************************************/
+
+/* the interrupt system consists of a 74148 priority encoder
+ with the following interrupt priorites. A lower number
+ indicates a lower priority (coins handled first):
+
+ 7 - player 1 coin
+ 6 - player 2 coin
+ 5 - player 3 coin
+ 4 - player 4 coin
+ 3 - ball/screen object collision
+ 2 - car/car collision
+ 1 - car/goal collision
+ 0 - timer (bit 4=0, bit 6=0)
+ 0 - car/ball collision (bit 4=0, bit 6=1)
+ 0 - car/border (bit 4=1, bit 6=1)
+
+ After the interrupt is serviced, the code clears the
+ priority encoder's appropriate line by pulling it HI. This
+ can trigger another interrupt immediately if there were
+ lower priority lines LO.
+
+ The four coin inputs are latched via 7474 flip-flop's. */
+
+#define COIN1_PRIORITY_LINE 7
+#define COIN2_PRIORITY_LINE 6
+#define COIN3_PRIORITY_LINE 5
+#define COIN4_PRIORITY_LINE 4
+#define BALL_SCREEN_PRIORITY_LINE 3
+#define CAR_CAR_PRIORITY_LINE 2
+#define CAR_GOAL_PRIORITY_LINE 1
+#define PRI0_PRIORTITY_LINE 0
+
+/* priority 0 controls three different things */
+#define TIMER_EXTRA_BITS 0x00
+#define CAR_BALL_EXTRA_BITS 0x40
+#define CAR_BORDER_EXTRA_BITS 0x50
+
+
+#define TTL74148_3S 0
+
+#define TTL74153_1K 0
+
+#define TTL7474_2S_1 0
+#define TTL7474_2S_2 1
+#define TTL7474_2U_1 2
+#define TTL7474_2U_2 3
+#define TTL7474_1F_1 4
+#define TTL7474_1F_2 5
+#define TTL7474_1D_1 6
+#define TTL7474_1D_2 7
+#define TTL7474_1C_1 8
+#define TTL7474_1C_2 9
+#define TTL7474_1A_1 10
+#define TTL7474_1A_2 11
+
+
+static UINT8 ball_screen_collision_cause;
+static UINT8 car_ball_collision_x;
+static UINT8 car_ball_collision_y;
+static UINT8 car_car_collision_cause;
+static UINT8 car_goal_collision_cause;
+static UINT8 car_ball_collision_cause;
+static UINT8 car_border_collision_cause;
+static UINT8 priority_0_extension;
+static UINT8 last_wheel_value[4];
+
+
+static void TTL74148_3S_cb(void)
+{
+ cpunum_set_input_line(0, M6502_IRQ_LINE, TTL74148_output_valid_r(TTL74148_3S) ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+/* the outputs of the flip-flops are connected to the priority encoder */
+static void TTL7474_2S_1_cb(void)
+{
+ TTL74148_input_line_w(TTL74148_3S, COIN1_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2S_1));
+ TTL74148_update(TTL74148_3S);
+}
+
+static void TTL7474_2S_2_cb(void)
+{
+ TTL74148_input_line_w(TTL74148_3S, COIN2_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2S_2));
+ TTL74148_update(TTL74148_3S);
+}
+
+static void TTL7474_2U_1_cb(void)
+{
+ TTL74148_input_line_w(TTL74148_3S, COIN3_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2U_1));
+ TTL74148_update(TTL74148_3S);
+}
+
+static void TTL7474_2U_2_cb(void)
+{
+ TTL74148_input_line_w(TTL74148_3S, COIN4_PRIORITY_LINE, TTL7474_output_comp_r(TTL7474_2U_2));
+ TTL74148_update(TTL74148_3S);
+}
+
+
+void carpolo_generate_ball_screen_interrupt(UINT8 cause)
+{
+ ball_screen_collision_cause = cause;
+
+ TTL74148_input_line_w(TTL74148_3S, BALL_SCREEN_PRIORITY_LINE, 0);
+ TTL74148_update(TTL74148_3S);
+}
+
+void carpolo_generate_car_car_interrupt(int car1, int car2)
+{
+ car_car_collision_cause = ~((1 << (3 - car1)) | (1 << (3 - car2)));
+
+ TTL74148_input_line_w(TTL74148_3S, CAR_CAR_PRIORITY_LINE, 0);
+ TTL74148_update(TTL74148_3S);
+}
+
+void carpolo_generate_car_goal_interrupt(int car, int right_goal)
+{
+ car_goal_collision_cause = car | (right_goal ? 0x08 : 0x00);
+
+ TTL74148_input_line_w(TTL74148_3S, CAR_GOAL_PRIORITY_LINE, 0);
+ TTL74148_update(TTL74148_3S);
+}
+
+void carpolo_generate_car_ball_interrupt(int car, int car_x, int car_y)
+{
+ car_ball_collision_cause = car;
+ car_ball_collision_x = car_x;
+ car_ball_collision_y = car_y;
+
+ priority_0_extension = CAR_BALL_EXTRA_BITS;
+
+ TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0);
+ TTL74148_update(TTL74148_3S);
+}
+
+void carpolo_generate_car_border_interrupt(int car, int horizontal_border)
+{
+ car_border_collision_cause = car | (horizontal_border ? 0x04 : 0x00);
+
+ priority_0_extension = CAR_BORDER_EXTRA_BITS;
+
+ TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0);
+ TTL74148_update(TTL74148_3S);
+}
+
+
+READ8_HANDLER( carpolo_ball_screen_collision_cause_r )
+{
+ /* bit 0 - 0=ball collided with border
+ bit 1 - 0=ball collided with goal
+ bit 2 - 0=ball collided with score area
+ bit 3 - which goal/score collided (0=left, 1=right) */
+ return ball_screen_collision_cause;
+}
+
+READ8_HANDLER( carpolo_car_ball_collision_x_r )
+{
+ /* the x coordinate of the colliding pixel */
+ return car_ball_collision_x;
+}
+
+READ8_HANDLER( carpolo_car_ball_collision_y_r )
+{
+ /* the y coordinate of the colliding pixel */
+ return car_ball_collision_y;
+}
+
+READ8_HANDLER( carpolo_car_car_collision_cause_r )
+{
+ /* bit 0 - car 4 collided
+ bit 1 - car 3 collided
+ bit 2 - car 2 collided
+ bit 3 - car 1 collided */
+ return car_car_collision_cause;
+}
+
+READ8_HANDLER( carpolo_car_goal_collision_cause_r )
+{
+ /* bit 0-1 - which car collided
+ bit 2 - horizontal timing bit 1TEC4 (not accessed)
+ bit 3 - which goal collided (0=left, 1=right) */
+ return car_goal_collision_cause;
+}
+
+READ8_HANDLER( carpolo_car_ball_collision_cause_r )
+{
+ /* bit 0-1 - which car collided
+ bit 2-3 - unconnected */
+ return car_ball_collision_cause;
+}
+
+READ8_HANDLER( carpolo_car_border_collision_cause_r )
+{
+ /* bit 0-1 - which car collided
+ bit 2 - 0=vertical border, 1=horizontal border */
+ return car_border_collision_cause;
+}
+
+
+READ8_HANDLER( carpolo_interrupt_cause_r )
+{
+ /* the output of the 148 goes to bits 1-3 (which is priority ^ 7) */
+ return (TTL74148_output_r(TTL74148_3S) << 1) | priority_0_extension;
+}
+
+
+INTERRUPT_GEN( carpolo_timer_interrupt )
+{
+ UINT8 port_value;
+ int player;
+
+
+ /* cause the timer interrupt */
+ TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 0);
+ priority_0_extension = TIMER_EXTRA_BITS;
+
+ TTL74148_update(TTL74148_3S);
+
+
+ /* check the coins here as well - they drive the clock of the flip-flops */
+ port_value = readinputport(0);
+
+ TTL7474_clock_w(TTL7474_2S_1, port_value & 0x01);
+ TTL7474_clock_w(TTL7474_2S_2, port_value & 0x02);
+ TTL7474_clock_w(TTL7474_2U_1, port_value & 0x04);
+ TTL7474_clock_w(TTL7474_2U_2, port_value & 0x08);
+
+ TTL7474_update(TTL7474_2S_1);
+ TTL7474_update(TTL7474_2S_2);
+ TTL7474_update(TTL7474_2U_1);
+ TTL7474_update(TTL7474_2U_2);
+
+
+ /* read the steering controls */
+ for (player = 0; player < 4; player++)
+ {
+ int movement_flip_flop = TTL7474_1F_1 + (2 * player);
+ int dir_flip_flop = movement_flip_flop + 1;
+
+
+ port_value = readinputport(2 + player);
+
+ if (port_value != last_wheel_value[player])
+ {
+ /* set the movement direction */
+ TTL7474_d_w(dir_flip_flop, ((port_value - last_wheel_value[player]) & 0x80) ? 1 : 0);
+
+ last_wheel_value[player] = port_value;
+ }
+
+ /* as the wheel moves, both flip-flops are clocked */
+ TTL7474_clock_w(movement_flip_flop, port_value & 0x01);
+ TTL7474_clock_w(dir_flip_flop, port_value & 0x01);
+
+ TTL7474_update(movement_flip_flop);
+ TTL7474_update(dir_flip_flop);
+ }
+
+
+
+ /* finally read the accelerator pedals */
+ port_value = readinputport(6);
+
+ for (player = 0; player < 4; player++)
+ {
+ /* one line indicates if the pedal is pressed and the other
+ how much, resulting in only two different possible levels */
+ if (port_value & 0x01)
+ {
+ TTL74153_input_line_w(TTL74153_1K, 0, player, 1);
+ TTL74153_input_line_w(TTL74153_1K, 1, player, 0);
+ }
+ else if (port_value & 0x02)
+ {
+ TTL74153_input_line_w(TTL74153_1K, 0, player, 1);
+ TTL74153_input_line_w(TTL74153_1K, 1, player, 1);
+ }
+ else
+ {
+ TTL74153_input_line_w(TTL74153_1K, 0, player, 0);
+ /* the other line is irrelevant */
+ }
+
+ port_value >>= 2;
+ }
+
+ TTL74153_update(TTL74153_1K);
+}
+
+
+static WRITE8_HANDLER( coin1_interrupt_clear_w )
+{
+ TTL7474_clear_w(TTL7474_2S_1, data);
+ TTL7474_update(TTL7474_2S_1);
+}
+
+static WRITE8_HANDLER( coin2_interrupt_clear_w )
+{
+ TTL7474_clear_w(TTL7474_2S_2, data);
+ TTL7474_update(TTL7474_2S_2);
+}
+
+static WRITE8_HANDLER( coin3_interrupt_clear_w )
+{
+ TTL7474_clear_w(TTL7474_2U_1, data);
+ TTL7474_update(TTL7474_2U_1);
+}
+
+static WRITE8_HANDLER( coin4_interrupt_clear_w )
+{
+ TTL7474_clear_w(TTL7474_2U_2, data);
+ TTL7474_update(TTL7474_2U_2);
+}
+
+WRITE8_HANDLER( carpolo_ball_screen_interrupt_clear_w )
+{
+ TTL74148_input_line_w(TTL74148_3S, BALL_SCREEN_PRIORITY_LINE, 1);
+ TTL74148_update(TTL74148_3S);
+}
+
+WRITE8_HANDLER( carpolo_car_car_interrupt_clear_w )
+{
+ TTL74148_input_line_w(TTL74148_3S, CAR_CAR_PRIORITY_LINE, 1);
+ TTL74148_update(TTL74148_3S);
+}
+
+WRITE8_HANDLER( carpolo_car_goal_interrupt_clear_w )
+{
+ TTL74148_input_line_w(TTL74148_3S, CAR_GOAL_PRIORITY_LINE, 1);
+ TTL74148_update(TTL74148_3S);
+}
+
+WRITE8_HANDLER( carpolo_car_ball_interrupt_clear_w )
+{
+ TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1);
+ TTL74148_update(TTL74148_3S);
+}
+
+WRITE8_HANDLER( carpolo_car_border_interrupt_clear_w )
+{
+ TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1);
+ TTL74148_update(TTL74148_3S);
+}
+
+WRITE8_HANDLER( carpolo_timer_interrupt_clear_w )
+{
+ TTL74148_input_line_w(TTL74148_3S, PRI0_PRIORTITY_LINE, 1);
+ TTL74148_update(TTL74148_3S);
+}
+
+
+/*************************************
+ *
+ * Input port handling
+ *
+ *************************************/
+
+static WRITE8_HANDLER( pia_0_port_a_w )
+{
+ /* bit 0 - Coin counter
+ bit 1 - Player 4 crash sound
+ bit 2 - Player 3 crash sound
+ bit 3 - Clear steering wheel logic
+ bit 4 - Player 2 crash sound
+ bit 5 - Score pulse sound
+ bit 6 - Player 1 crash sound
+ bit 7 - Ball hit pulse sound */
+
+ coin_counter_w(0, data & 0x01);
+
+
+ TTL7474_clear_w(TTL7474_1F_1, data & 0x08);
+ TTL7474_clear_w(TTL7474_1D_1, data & 0x08);
+ TTL7474_clear_w(TTL7474_1C_1, data & 0x08);
+ TTL7474_clear_w(TTL7474_1A_1, data & 0x08);
+
+ TTL7474_update(TTL7474_1F_1);
+ TTL7474_update(TTL7474_1D_1);
+ TTL7474_update(TTL7474_1C_1);
+ TTL7474_update(TTL7474_1A_1);
+}
+
+
+static WRITE8_HANDLER( pia_0_port_b_w )
+{
+ /* bit 0 - Strobe speed bits sound
+ bit 1 - Speed bit 0 sound
+ bit 2 - Speed bit 1 sound
+ bit 3 - Speed bit 2 sound
+ bit 6 - Select pedal 0
+ bit 7 - Select pdeal 1 */
+
+ TTL74153_a_w(TTL74153_1K, data & 0x40);
+ TTL74153_b_w(TTL74153_1K, data & 0x80);
+
+ TTL74153_update(TTL74153_1K);
+}
+
+static READ8_HANDLER( pia_0_port_b_r )
+{
+ /* bit 4 - Pedal bit 0
+ bit 5 - Pedal bit 1 */
+
+ return (TTL74153_output_r(TTL74153_1K, 0) << 5) |
+ (TTL74153_output_r(TTL74153_1K, 1) << 4);
+}
+
+
+static READ8_HANDLER( pia_1_port_a_r )
+{
+ UINT8 ret;
+
+ /* bit 0 - Player 4 steering input (left or right)
+ bit 1 - Player 3 steering input (left or right)
+ bit 2 - Player 2 steering input (left or right)
+ bit 3 - Player 1 steering input (left or right)
+ bit 4 - Player 4 forward/reverse input
+ bit 5 - Player 3 forward/reverse input
+ bit 6 - Player 2 forward/reverse input
+ bit 7 - Player 1 forward/reverse input */
+
+ ret = (TTL7474_output_r(TTL7474_1A_2) ? 0x01 : 0x00) |
+ (TTL7474_output_r(TTL7474_1C_2) ? 0x02 : 0x00) |
+ (TTL7474_output_r(TTL7474_1D_2) ? 0x04 : 0x00) |
+ (TTL7474_output_r(TTL7474_1F_2) ? 0x08 : 0x00) |
+ (readinputport(7) & 0xf0);
+
+ return ret;
+}
+
+
+static READ8_HANDLER( pia_1_port_b_r )
+{
+ UINT8 ret;
+
+ /* bit 4 - Player 4 steering input (wheel moving or stopped)
+ bit 5 - Player 3 steering input (wheel moving or stopped)
+ bit 6 - Player 2 steering input (wheel moving or stopped)
+ bit 7 - Player 1 steering input (wheel moving or stopped) */
+
+ ret = (TTL7474_output_r(TTL7474_1A_1) ? 0x10 : 0x00) |
+ (TTL7474_output_r(TTL7474_1C_1) ? 0x20 : 0x00) |
+ (TTL7474_output_r(TTL7474_1D_1) ? 0x40 : 0x00) |
+ (TTL7474_output_r(TTL7474_1F_1) ? 0x80 : 0x00);
+
+ return ret;
+}
+
+
+static const pia6821_interface pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, pia_0_port_b_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ pia_0_port_a_w, pia_0_port_b_w, coin1_interrupt_clear_w, coin2_interrupt_clear_w,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface pia_1_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ pia_1_port_a_r, pia_1_port_b_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, coin3_interrupt_clear_w, coin4_interrupt_clear_w,
+ /*irqs : A/B */ 0, 0
+};
+
+static struct TTL74148_interface TTL74148_3S_intf =
+{
+ TTL74148_3S_cb
+};
+
+static struct TTL7474_interface TTL7474_2S_1_intf =
+{
+ TTL7474_2S_1_cb
+};
+
+static struct TTL7474_interface TTL7474_2S_2_intf =
+{
+ TTL7474_2S_2_cb
+};
+
+static struct TTL7474_interface TTL7474_2U_1_intf =
+{
+ TTL7474_2U_1_cb
+};
+
+static struct TTL7474_interface TTL7474_2U_2_intf =
+{
+ TTL7474_2U_2_cb
+};
+
+
+MACHINE_START( carpolo )
+{
+ /* set up the PIA's */
+ pia_config(0, &pia_0_intf);
+ pia_config(1, &pia_1_intf);
+}
+
+MACHINE_RESET( carpolo )
+{
+ /* set up the priority encoder */
+ TTL74148_config(TTL74148_3S, &TTL74148_3S_intf);
+ TTL74148_enable_input_w(TTL74148_3S, 0); /* always enabled */
+
+
+ /* set up the coin handling flip-flops */
+ TTL7474_config(TTL7474_2S_1, &TTL7474_2S_1_intf);
+ TTL7474_config(TTL7474_2S_2, &TTL7474_2S_2_intf);
+ TTL7474_config(TTL7474_2U_1, &TTL7474_2U_1_intf);
+ TTL7474_config(TTL7474_2U_2, &TTL7474_2U_2_intf);
+
+ TTL7474_d_w (TTL7474_2S_1, 1);
+ TTL7474_preset_w(TTL7474_2S_1, 1);
+
+ TTL7474_d_w (TTL7474_2S_2, 1);
+ TTL7474_preset_w(TTL7474_2S_2, 1);
+
+ TTL7474_d_w (TTL7474_2U_1, 1);
+ TTL7474_preset_w(TTL7474_2U_1, 1);
+
+ TTL7474_d_w (TTL7474_2U_2, 1);
+ TTL7474_preset_w(TTL7474_2U_2, 1);
+
+
+ /* set up the steering handling flip-flops */
+ TTL7474_config(TTL7474_1F_1, 0);
+ TTL7474_config(TTL7474_1F_2, 0);
+ TTL7474_config(TTL7474_1D_1, 0);
+ TTL7474_config(TTL7474_1D_2, 0);
+ TTL7474_config(TTL7474_1C_1, 0);
+ TTL7474_config(TTL7474_1C_2, 0);
+ TTL7474_config(TTL7474_1A_1, 0);
+ TTL7474_config(TTL7474_1A_2, 0);
+
+ TTL7474_d_w (TTL7474_1F_1, 1);
+ TTL7474_preset_w(TTL7474_1F_1, 1);
+
+ TTL7474_clear_w (TTL7474_1F_2, 1);
+ TTL7474_preset_w(TTL7474_1F_2, 1);
+
+ TTL7474_d_w (TTL7474_1D_1, 1);
+ TTL7474_preset_w(TTL7474_1D_1, 1);
+
+ TTL7474_clear_w (TTL7474_1D_2, 1);
+ TTL7474_preset_w(TTL7474_1D_2, 1);
+
+ TTL7474_d_w (TTL7474_1C_1, 1);
+ TTL7474_preset_w(TTL7474_1C_1, 1);
+
+ TTL7474_clear_w (TTL7474_1C_2, 1);
+ TTL7474_preset_w(TTL7474_1C_2, 1);
+
+ TTL7474_d_w (TTL7474_1A_1, 1);
+ TTL7474_preset_w(TTL7474_1A_1, 1);
+
+ TTL7474_clear_w (TTL7474_1A_2, 1);
+ TTL7474_preset_w(TTL7474_1A_2, 1);
+
+
+ /* set up the pedal handling chips */
+ TTL74153_config(TTL74153_1K, 0);
+
+ TTL74153_enable_w(TTL74153_1K, 0, 0);
+ TTL74153_enable_w(TTL74153_1K, 1, 0);
+}
diff --git a/src/mame/machine/cchasm.c b/src/mame/machine/cchasm.c
new file mode 100644
index 00000000000..53cf5bd048d
--- /dev/null
+++ b/src/mame/machine/cchasm.c
@@ -0,0 +1,15 @@
+/***************************************************************************
+
+ Cinematronics Cosmic Chasm hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "video/vector.h"
+#include "cchasm.h"
+
+WRITE16_HANDLER( cchasm_led_w )
+{
+ /*logerror("LED write %x to %x\n", data, offset);*/
+}
+
diff --git a/src/mame/machine/cchip.c b/src/mame/machine/cchip.c
new file mode 100644
index 00000000000..8424f33b711
--- /dev/null
+++ b/src/mame/machine/cchip.c
@@ -0,0 +1,184 @@
+/***************************************************************************
+
+ cchip.c
+
+This file contains routines to interface with the Taito Controller Chip
+(or "Command Chip") version 1. It's currently used by Superman and Mega
+Blast. [Further cchip emulation is in machine/rainbow.c, machine/volfied.c,
+drivers/opwolf.c]
+
+According to Richard Bush, the C-Chip is an encrypted Z80 which communicates
+with the main board as a protection feature.
+
+
+Superman (revised SJ 060601)
+--------
+
+In Superman, the C-chip's main purpose is to handle player inputs and
+coins and pass commands along to the sound chip.
+
+The 68k queries the c-chip, which passes back $100 bytes of 68k code which
+are then executed in RAM. To get around this, we hack in our own code to
+communicate with the sound board, since we are familiar with the interface
+as it's used in Rastan and Super Space Invaders '91.
+
+It is believed that the NOPs in the 68k code are there to supply the
+necessary cycles to the cchip to switch banks.
+
+This code requires that the player & coin inputs be in input ports 2-4.
+
+
+Mega Blast
+----------
+
+C-Chip simply used as RAM, the game doesn't even bother to change banks.
+It does read the chip id though. The dump is confirmed to be from an
+original board.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "includes/taito_f2.h"
+
+static UINT16 current_bank = 0;
+
+static UINT8 cc_port = 0;
+
+/* This code for sound communication is a hack, it will not be
+ identical to the code derived from the real c-chip */
+
+static UINT8 superman_code[40] =
+{
+ 0x48, 0xe7, 0x80, 0x80, /* MOVEM.L D0/A0,-(A7) ( Preserve Regs ) */
+ 0x20, 0x6d, 0x1c, 0x40, /* MOVEA.L ($1C40,A5),A0 ( Load sound pointer in A0 ) */
+ 0x30, 0x2f, 0x00, 0x0c, /* MOVE.W ($0C,A7),D0 ( Fetch sound number ) */
+ 0x10, 0x80, /* MOVE.B D0,(A0) ( Store it on sound pointer ) */
+ 0x52, 0x88, /* ADDQ.W #1,A0 ( Increment sound pointer ) */
+ 0x20, 0x3c, 0x00, 0xf0, 0x1c, 0x40, /* MOVE.L #$F01C40,D0 ( Load top of buffer in D0 ) */
+ 0xb1, 0xc0, /* CMPA.L D0,A0 ( Are we there yet? ) */
+ 0x66, 0x04, /* BNE.S *+$6 ( No, we arent, skip next line ) */
+ 0x41, 0xed, 0x1c, 0x20, /* LEA ($1C20,A5),A0 ( Point to the start of the buffer ) */
+ 0x2b, 0x48, 0x1c, 0x40, /* MOVE.L A0,($1C40,A5) ( Store new sound pointer ) */
+ 0x4c, 0xdf, 0x01, 0x01, /* MOVEM.L (A7)+, D0/A0 ( Restore Regs ) */
+ 0x4e, 0x75 /* RTS ( Return ) */
+};
+
+MACHINE_RESET( cchip1 )
+{
+ state_save_register_global(current_bank);
+ state_save_register_global(cc_port);
+}
+
+/*************************************
+ *
+ * Writes to C-Chip - Important Bits
+ *
+ *************************************/
+
+WRITE16_HANDLER( cchip1_ctrl_w )
+{
+ /* value 2 is written here */
+}
+
+WRITE16_HANDLER( cchip1_bank_w )
+{
+ current_bank = data & 7;
+}
+
+WRITE16_HANDLER( cchip1_ram_w )
+{
+ if (current_bank == 0 && offset == 0x03)
+ {
+ cc_port = data;
+
+ coin_lockout_w(1, data & 0x08);
+ coin_lockout_w(0, data & 0x04);
+ coin_counter_w(1, data & 0x02);
+ coin_counter_w(0, data & 0x01);
+ }
+ else
+ {
+logerror("cchip1_w pc: %06x bank %02x offset %04x: %02x\n",activecpu_get_pc(),current_bank,offset,data);
+ }
+}
+
+
+/*************************************
+ *
+ * Reads from C-Chip
+ *
+ *************************************/
+
+READ16_HANDLER( cchip1_ctrl_r )
+{
+ /*
+ Bit 2 = Error signal
+ Bit 0 = Ready signal
+ */
+ return 0x01; /* Return 0x05 for C-Chip error */
+}
+
+READ16_HANDLER( cchip1_ram_r )
+{
+ /* Check for input ports */
+ if (current_bank == 0)
+ {
+ switch (offset)
+ {
+ case 0x00: return readinputportbytag("IN0"); /* Player 1 controls + START1 */
+ case 0x01: return readinputportbytag("IN1"); /* Player 2 controls + START2 */
+ case 0x02: return readinputportbytag("IN2"); /* COINn + SERVICE1 + TILT */
+ case 0x03: return cc_port;
+ }
+ }
+
+ /* Other non-standard offsets */
+
+ if (current_bank == 1 && offset <= 0xff)
+ {
+ if (offset < 40) /* our hack code is only 40 bytes long */
+ return superman_code[offset];
+ else /* so pad with zeros */
+ return 0;
+ }
+
+ if (current_bank == 2)
+ {
+ switch (offset)
+ {
+ case 0x000: return 0x47;
+ case 0x001: return 0x57;
+ case 0x002: return 0x4b;
+ }
+ }
+
+logerror("cchip1_r bank: %02x offset: %04x\n",current_bank,offset);
+ return 0;
+}
+
+
+/* Mega Blast */
+
+UINT16 *cchip2_ram;
+
+WRITE16_HANDLER( cchip2_word_w )
+{
+ logerror("cchip2_w pc: %06x offset %04x: %02x\n", activecpu_get_pc(), offset, data);
+
+ COMBINE_DATA(&cchip2_ram[offset]);
+}
+
+READ16_HANDLER( cchip2_word_r )
+{
+ /* C-Chip ID */
+
+ if (offset == 0x401)
+ {
+ return 0x01;
+ }
+
+ logerror("cchip2_r offset: %04x\n", offset);
+
+ return cchip2_ram[offset];
+}
+
diff --git a/src/mame/machine/cclimber.c b/src/mame/machine/cclimber.c
new file mode 100644
index 00000000000..24fce0fb794
--- /dev/null
+++ b/src/mame/machine/cclimber.c
@@ -0,0 +1,142 @@
+#include "driver.h"
+#include "includes/cclimber.h"
+
+/* set to 1 to fix protection check after bonus round (see notes in pacman.c driver) */
+#define CANNONB_HACK 0
+
+static void cclimber_decode(const UINT8 convtable[8][16])
+{
+ UINT8 *rom = memory_region(REGION_CPU1);
+ UINT8 *decrypt = auto_malloc(0x10000);
+ int A;
+
+ memory_set_decrypted_region(0, 0x0000, 0xffff, decrypt);
+
+ for (A = 0x0000;A < 0x10000;A++)
+ {
+ int i,j;
+ UINT8 src;
+
+
+ src = rom[A];
+
+ /* pick the translation table from bit 0 of the address */
+ /* and from bits 1 7 of the source data */
+ i = (A & 1) | (src & 0x02) | ((src & 0x80) >> 5);
+
+ /* pick the offset in the table from bits 0 2 4 6 of the source data */
+ j = (src & 0x01) | ((src & 0x04) >> 1) | ((src & 0x10) >> 2) | ((src & 0x40) >> 3);
+
+ /* decode the opcodes */
+ decrypt[A] = (src & 0xaa) | convtable[i][j];
+ }
+}
+
+DRIVER_INIT( cclimber )
+{
+ static const UINT8 convtable[8][16] =
+ {
+ /* -1 marks spots which are unused and therefore unknown */
+ { 0x44,0x14,0x54,0x10,0x11,0x41,0x05,0x50,0x51,0x00,0x40,0x55,0x45,0x04,0x01,0x15 },
+ { 0x44,0x10,0x15,0x55,0x00,0x41,0x40,0x51,0x14,0x45,0x11,0x50,0x01,0x54,0x04,0x05 },
+ { 0x45,0x10,0x11,0x44,0x05,0x50,0x51,0x04,0x41,0x14,0x15,0x40,0x01,0x54,0x55,0x00 },
+ { 0x04,0x51,0x45,0x00,0x44,0x10, -1,0x55,0x11,0x54,0x50,0x40,0x05, -1,0x14,0x01 },
+ { 0x54,0x51,0x15,0x45,0x44,0x01,0x11,0x41,0x04,0x55,0x50, -1,0x00,0x10,0x40, -1 },
+ { -1,0x54,0x14,0x50,0x51,0x01, -1,0x40,0x41,0x10,0x00,0x55,0x05,0x44,0x11,0x45 },
+ { 0x51,0x04,0x10, -1,0x50,0x40,0x00, -1,0x41,0x01,0x05,0x15,0x11,0x14,0x44,0x54 },
+ { -1, -1,0x54,0x01,0x15,0x40,0x45,0x41,0x51,0x04,0x50,0x05,0x11,0x44,0x10,0x14 }
+ };
+
+ cclimber_decode(convtable);
+}
+
+DRIVER_INIT( cclimbrj )
+{
+ static const UINT8 convtable[8][16] =
+ {
+ { 0x41,0x54,0x51,0x14,0x05,0x10,0x01,0x55,0x44,0x11,0x00,0x50,0x15,0x40,0x04,0x45 },
+ { 0x50,0x11,0x40,0x55,0x51,0x14,0x45,0x04,0x54,0x15,0x10,0x05,0x44,0x01,0x00,0x41 },
+ { 0x44,0x11,0x00,0x50,0x41,0x54,0x04,0x14,0x15,0x40,0x51,0x55,0x05,0x10,0x01,0x45 },
+ { 0x10,0x50,0x54,0x55,0x01,0x44,0x40,0x04,0x14,0x11,0x00,0x41,0x45,0x15,0x51,0x05 },
+ { 0x14,0x41,0x01,0x44,0x04,0x50,0x51,0x45,0x11,0x40,0x54,0x15,0x10,0x00,0x55,0x05 },
+ { 0x01,0x05,0x41,0x45,0x54,0x50,0x55,0x10,0x11,0x15,0x51,0x14,0x44,0x40,0x04,0x00 },
+ { 0x05,0x55,0x00,0x50,0x11,0x40,0x54,0x14,0x45,0x51,0x10,0x04,0x44,0x01,0x41,0x15 },
+ { 0x55,0x50,0x15,0x10,0x01,0x04,0x41,0x44,0x45,0x40,0x05,0x00,0x11,0x14,0x51,0x54 },
+ };
+
+ cclimber_decode(convtable);
+}
+
+DRIVER_INIT( mshuttle )
+{
+ static const UINT8 convtable[8][16] =
+ {
+ /* -1 marks spots which are unused and therefore unknown */
+ { 0x40,0x41,0x44,0x15,0x05,0x51,0x54,0x55,0x50,0x00,0x01,0x04, -1,0x10,0x11,0x14 },
+ { 0x45,0x51,0x55,0x44,0x40,0x11,0x05,0x41,0x10,0x14,0x54,0x50,0x15,0x04,0x00,0x01 },
+ { 0x11,0x14,0x10,0x00,0x44,0x05, -1,0x04,0x45,0x15,0x55,0x50, -1,0x01,0x54,0x51 },
+ { 0x14,0x01,0x11,0x10,0x50,0x15,0x00,0x40,0x04,0x51,0x45,0x05,0x55,0x54, -1,0x44 },
+ { 0x04,0x10, -1,0x40,0x15,0x41,0x50,0x50,0x11, -1,0x14,0x00,0x51,0x45,0x55,0x01 },
+ { 0x44,0x45,0x00,0x51, -1, -1,0x15,0x11,0x01,0x10,0x04,0x55,0x05,0x40,0x50,0x41 },
+ { 0x51,0x00,0x01,0x05,0x04,0x55,0x54,0x50,0x41, -1,0x11,0x15,0x14,0x10,0x44,0x40 },
+ { 0x05,0x04,0x51,0x01, -1, -1,0x55, -1,0x00,0x50,0x15,0x14,0x44,0x41,0x40,0x54 },
+ };
+
+ cclimber_decode(convtable);
+}
+
+DRIVER_INIT( ckongb )
+{
+ int A;
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+ for (A = 0x0000;A < 0x6000;A++) /* all the program ROMs are encrypted */
+ {
+ rom[A] = rom[A] ^ 0xf0;
+ }
+}
+
+#if CANNONB_HACK
+static void cannonb_patch(void)
+{
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+ rom[0x2ba0] = 0x21;
+ rom[0x2ba1] = 0xfb;
+ rom[0x2ba2] = 0x0e;
+ rom[0x2ba3] = 0x00;
+}
+#endif
+
+DRIVER_INIT( cannonb )
+{
+ int A;
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+ for (A = 0x0000;A < 0x1000;A++) /* only first ROM is encrypted */
+ {
+ UINT8 src;
+ int i;
+ static const UINT8 xor_tab[4] ={0x92, 0x82, 0x12, 0x10};
+
+ src = rom[A+0x10000];
+
+ i = ((A&0x200)>>8) | ((A&0x80)>>7);
+
+ src ^= xor_tab[i];
+
+ rom[A] = src;
+ }
+
+#if CANNONB_HACK
+ cannonb_patch();
+#endif
+}
+
+DRIVER_INIT( cannonb2 )
+{
+#if CANNONB_HACK
+ cannonb_patch();
+#endif
+}
+
diff --git a/src/mame/machine/chaknpop.c b/src/mame/machine/chaknpop.c
new file mode 100644
index 00000000000..21eb9edefde
--- /dev/null
+++ b/src/mame/machine/chaknpop.c
@@ -0,0 +1,166 @@
+/*
+ * Chack'n Pop (C) 1983 TAITO Corp.
+ * simulate 68705 MCU
+ */
+
+#include "driver.h"
+#include "cpu/z80/z80.h"
+
+#define MCU_INITIAL_SEED 0x81
+
+UINT8 *chaknpop_ram;
+
+
+static UINT8 mcu_seed;
+static UINT8 mcu_select;
+static UINT8 mcu_result;
+
+/* mcu data that is extracted from the real board! */
+/* updated on 2st Jun 2003 */
+static UINT8 mcu_data[256] = {
+ 0x3a, 0xe6, 0x80, 0xc6, 0x0e, 0xdd, 0x77, 0xfd,
+ 0x7e, 0xfe, 0x10, 0x38, 0x10, 0xdd, 0x7e, 0x03,
+ 0xc6, 0x08, 0xdd, 0x77, 0x03, 0xdd, 0x7e, 0xff,
+ 0xc6, 0x08, 0xdd, 0x77, 0xff, 0x34, 0x23, 0xc9,
+ 0x06, 0x10, 0xdd, 0xe5, 0xe1, 0x23, 0x23, 0x23,
+ 0x4e, 0x23, 0x5e, 0x23, 0x56, 0x23, 0x23, 0x7b,
+ 0xb2, 0x28, 0x02, 0x79, 0x12, 0x10, 0xf1, 0xc9,
+ 0xe6, 0x03, 0x87, 0x87, 0x6f, 0x26, 0x00, 0x29,
+ 0x29, 0x29, 0xe5, 0x29, 0x29, 0x29, 0xc1, 0x09,
+ 0x01, 0xc3, 0x81, 0x09, 0xe5, 0xdd, 0xe1, 0xc9,
+ 0x10, 0x00, 0x08, 0x10, 0x20, 0x64, 0x50, 0x00,
+ 0x08, 0x50, 0xb0, 0x01, 0x34, 0xa0, 0x13, 0x34,
+ 0xb0, 0x05, 0x34, 0xc0, 0x04, 0x34, 0xd0, 0x02,
+ 0x34, 0xf0, 0x02, 0x34, 0x00, 0x60, 0x00, 0x00,
+ 0x3f, 0x00, 0x0c, 0x1f, 0xa0, 0x3f, 0x1e, 0xa2,
+ 0x01, 0x1e, 0xa1, 0x0a, 0x1e, 0xa2, 0x07, 0x1e,
+ 0x92, 0x05, 0x1e, 0x02, 0x04, 0x1e, 0x12, 0x09,
+ 0x3f, 0x22, 0x06, 0x3f, 0x21, 0x03, 0x3f, 0x20,
+ 0x02, 0x00, 0x00, 0x3f, 0x00, 0x04, 0x02, 0xa0,
+ 0x40, 0x12, 0xa1, 0x06, 0x12, 0xa2, 0x02, 0x12,
+ 0xa1, 0x0a, 0x12, 0xa2, 0x07, 0x10, 0x92, 0x05,
+ 0x10, 0x02, 0x04, 0x12, 0x12, 0x09, 0x12, 0x22,
+ 0x06, 0x12, 0x21, 0x03, 0x12, 0x20, 0x02, 0x26,
+ 0x00, 0x14, 0x12, 0x00, 0x00, 0x00, 0x3f, 0x00,
+ 0x04, 0x1a, 0xa0, 0x40, 0x3f, 0x00, 0x00, 0x00,
+ 0x3e, 0x3a, 0x87, 0x83, 0x3c, 0x32, 0x87, 0x83,
+ 0x0f, 0x0f, 0xe6, 0x07, 0xfe, 0x02, 0x20, 0x01,
+ 0xaf, 0x11, 0x40, 0x98, 0x1d, 0x12, 0x1d, 0x20,
+ 0xfb, 0x2a, 0x89, 0x83, 0x2b, 0x22, 0x89, 0x83,
+ 0xc9, 0x3a, 0x5b, 0x81, 0xa7, 0xc0, 0x21, 0x80,
+ 0x81, 0x11, 0x04, 0x00, 0x06, 0x09, 0x34, 0x19,
+ 0x10, 0xfc, 0x3e, 0x01, 0x32, 0x5b, 0x81, 0xc9
+};
+
+static void mcu_update_seed(UINT8 data)
+{
+ if (!(data & 0x80))
+ {
+ mcu_seed += 0x83;
+ mcu_seed = (mcu_seed & 0x80) | (mcu_seed >> 1);
+ }
+
+ mcu_seed += 0x19;
+
+ //logerror("New seed: 0x%02x\n", mcu_seed);
+}
+
+
+/***************************************************************************
+ Memory handlers
+***************************************************************************/
+
+READ8_HANDLER( chaknpop_mcu_portA_r )
+{
+ //logerror("%04x: MCU portA read\n", activecpu_get_pc());
+ return mcu_result;
+}
+
+
+READ8_HANDLER( chaknpop_mcu_portB_r )
+{
+ //logerror("%04x: MCU portB read\n", activecpu_get_pc());
+
+ return 0xff;
+}
+
+READ8_HANDLER( chaknpop_mcu_portC_r )
+{
+ //logerror("%04x: MCU portC read\n", activecpu_get_pc());
+ return 0x00;
+}
+
+WRITE8_HANDLER( chaknpop_mcu_portA_w )
+{
+ UINT8 mcu_command;
+
+ mcu_command = data + mcu_seed;
+ mcu_result = 0;
+
+ if (mcu_command < 0x08)
+ {
+ mcu_update_seed(data);
+
+ mcu_result = mcu_data[mcu_select * 8 + mcu_command];
+ mcu_result -= mcu_seed;
+
+ mcu_update_seed(mcu_result);
+
+ logerror("%04x: MCU command 0x%02x, result 0x%02x\n", activecpu_get_pc(), mcu_command, mcu_result);
+ }
+ else if (mcu_command >= 0x28 && mcu_command <= 0x2a)
+ {
+ mcu_update_seed(data);
+
+ mcu_result = chaknpop_ram[0x380 + mcu_command];
+ mcu_result -= mcu_seed;
+
+ mcu_update_seed(mcu_result);
+
+ logerror("%04x: MCU command 0x%02x, result 0x%02x\n", activecpu_get_pc(), mcu_command, mcu_result);
+ }
+ else if (mcu_command < 0x80)
+ {
+ mcu_update_seed(data);
+
+ if (mcu_command >= 0x40 && mcu_command < 0x60)
+ {
+ mcu_select = mcu_command - 0x40;
+
+ logerror("%04x: MCU select 0x%02x\n", activecpu_get_pc(), mcu_select);
+ }
+ }
+ else if (mcu_command == 0x9c|| mcu_command == 0xde)
+ {
+ mcu_update_seed(data);
+
+ logerror("%04x: MCU command 0x%02x\n", activecpu_get_pc(), mcu_command);
+ }
+}
+
+WRITE8_HANDLER( chaknpop_mcu_portB_w )
+{
+ //logerror("%04x: MCU portB write 0x%02x\n", activecpu_get_pc(), data);
+}
+
+WRITE8_HANDLER( chaknpop_mcu_portC_w )
+{
+ //logerror("%04x: MCU portC write 0x%02x\n", activecpu_get_pc(), data);
+}
+
+
+/***************************************************************************
+ Initialize mcu emulation
+***************************************************************************/
+
+DRIVER_INIT( chaknpop )
+{
+ state_save_register_global(mcu_seed);
+ state_save_register_global(mcu_result);
+ state_save_register_global(mcu_select);
+}
+
+MACHINE_RESET( chaknpop )
+{
+ mcu_seed = MCU_INITIAL_SEED;
+}
diff --git a/src/mame/machine/copsnrob.c b/src/mame/machine/copsnrob.c
new file mode 100644
index 00000000000..53186c867a6
--- /dev/null
+++ b/src/mame/machine/copsnrob.c
@@ -0,0 +1,59 @@
+/***************************************************************************
+
+ Atari Cops'n Robbers hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "copsnrob.h"
+
+static int gun_mask[] = {0x7e, 0x7d, 0x7b, 0x77, 0x6f, 0x5f, 0x3f};
+
+// The gun control is a 7 position switch. I'm doing the following to
+// emulate it:
+//
+// I read out the current gun position via the sprite image locations,
+// and then decrement/increment it if the up/down keys are pressed.
+
+READ8_HANDLER( copsnrob_gun_position_r )
+{
+ int keys, current_car_image, current_gun_pos = 0;
+
+ // Determine which player we need
+ switch (offset)
+ {
+ default:
+ case 0x00:
+ current_car_image = copsnrob_carimage[0];
+ keys = input_port_4_r(0);
+ break;
+ case 0x04:
+ current_car_image = copsnrob_carimage[1];
+ keys = input_port_5_r(0);
+ break;
+ case 0x08:
+ current_car_image = copsnrob_carimage[2];
+ keys = input_port_6_r(0);
+ break;
+ case 0x0c:
+ current_car_image = copsnrob_carimage[3];
+ keys = input_port_7_r(0);
+ }
+
+ if (current_car_image < 7)
+ {
+ current_gun_pos = 6 - current_car_image;
+ }
+ else if (current_car_image < 14)
+ {
+ current_gun_pos = 13 - current_car_image;
+ }
+
+ // Gun up
+ if ((keys & 0x01) && (current_gun_pos != 6)) current_gun_pos++;
+
+ // Gun down
+ if ((keys & 0x02) && (current_gun_pos != 0)) current_gun_pos--;
+
+ return (keys & 0x80) | gun_mask[current_gun_pos];
+}
diff --git a/src/mame/machine/cps2crpt.c b/src/mame/machine/cps2crpt.c
new file mode 100644
index 00000000000..0b4e803b62d
--- /dev/null
+++ b/src/mame/machine/cps2crpt.c
@@ -0,0 +1,978 @@
+/******************************************************************************
+
+CPS-2 Encryption
+
+All credit goes to Andreas Naive for breaking the encryption algorithm.
+Code by Nicola Salmoria.
+Thanks to Charles MacDonald and Razoola for extracting the data from the hardware.
+
+
+The encryption only affects opcodes, not data.
+
+It consists of two 4-round Feistel networks (FN) and involves both
+the 16-bit opcode and the low 16 bits of the address.
+
+Let be:
+
+E = 16-bit ciphertext
+A = 16-bit address
+K = 64-bit key
+D = 16-bit plaintext
+y = FN1(x,k) = function describing the first Feistel network (x,y = 16 bit, k = 64 bit)
+y = FN2(x,k) = function describing the second Feistel network (x,y = 16 bit, k = 64 bit)
+y = EX(x) = fixed function that expands the 16-bit x to the 64-bit y
+
+Then the cipher can be described as:
+
+D = FN2( E, K XOR EX( FN1(A, K ) ) )
+
+
+Each round of the Feistel networks consists of four substitution boxes. The boxes
+have 6 inputs and 2 outputs. Usually the input is the XOR of a data bit and a key
+bit, however in some cases only the key is used.
+
+(TODO-notes about accuracy of s-boxes)
+
+The s-boxes were chosen in order to use an empty key (all FF) for the dead board.
+
+
+Also, the hardware has different watchdog opcodes and address range (see below)
+which are stored in the battery backed RAM. There doesn't appear to be any relation
+between those and the 64-bit encryption key, so they probably use an additional
+64 bits of battery-backed RAM.
+
+
+
+First FN:
+
+ B(0 1 3 5 8 9 11 12) A(10 4 6 7 2 13 15 14)
+ L0 R0
+ | |
+ XOR<-----------[F1]<------------|
+ | |
+ R1 L1
+ | |
+ |------------>[F2]----------->XOR
+ | |
+ L2 R2
+ | |
+ XOR<-----------[F3]<------------|
+ | |
+ R3 L3
+ | |
+ |------------>[F4]----------->XOR
+ | |
+ L4 R4
+ (10 4 6 7 2 13 15 14) (0 1 3 5 8 9 11 12)
+
+
+Second FN:
+
+ B(3 5 9 10 8 15 12 11) A(6 0 2 13 1 4 14 7)
+ L0 R0
+ | |
+ XOR<-----------[F1]<------------|
+ | |
+ R1 L1
+ | |
+ |------------>[F2]----------->XOR
+ | |
+ L2 R2
+ | |
+ XOR<-----------[F3]<------------|
+ | |
+ R3 L3
+ | |
+ |------------>[F4]----------->XOR
+ | |
+ L4 R4
+ (6 0 2 13 1 4 14 7) (3 5 9 10 8 15 12 11)
+
+******************************************************************************
+
+Some Encryption notes.
+----------------------
+
+Address range.
+
+The encryption does _not_ cover the entire address space. The range covered
+differs per game.
+
+
+Encryption Watchdog.
+
+The CPS2 system has a watchdog system that will disable the decryption
+of data if the watchdog isn't triggered at least once every few seconds.
+The trigger varies from game to game (some games do use the same) and is
+basically a 68000 opcode/s instruction. The instruction is the same for
+all regions of the game. The watchdog instructions are listed alongside
+the decryption keys.
+
+*******************************************************************************/
+
+#include "driver.h"
+#include "cpu/m68000/m68kmame.h"
+#include "ui.h"
+#include "includes/cps1.h"
+
+
+/******************************************************************************/
+
+static const int fn1_groupA[8] = { 10, 4, 6, 7, 2, 13, 15, 14 };
+static const int fn1_groupB[8] = { 0, 1, 3, 5, 8, 9, 11, 12 };
+
+static const int fn2_groupA[8] = { 6, 0, 2, 13, 1, 4, 14, 7 };
+static const int fn2_groupB[8] = { 3, 5, 9, 10, 8, 15, 12, 11 };
+
+/******************************************************************************/
+
+// The order of the input and output bits in the s-boxes is arbitrary.
+// Each s-box can be XORed with an arbitrary vale in range 0-3 (but the same value
+// must be used for the corresponding output bits in f1 and f3 or in f2 and f4)
+
+struct sbox
+{
+ const UINT8 table[64];
+ const int inputs[6]; // positions of the inputs bits, -1 means no input except from key
+ const int outputs[2]; // positions of the output bits
+};
+
+// the above struct better defines how the hardware works, however
+// to speed up the decryption at run time we convert it to the
+// following one
+struct optimised_sbox
+{
+ UINT8 input_lookup[256];
+ UINT8 output[64];
+};
+
+
+static const struct sbox fn1_r1_boxes[4] =
+{
+ { // subkey bits 0- 5
+ {
+ 0,2,2,0,1,0,1,1,3,2,0,3,0,3,1,2,1,1,1,2,1,3,2,2,2,3,3,2,1,1,1,2,
+ 2,2,0,0,3,1,3,1,1,1,3,0,0,1,0,0,1,2,2,1,2,3,2,2,2,3,1,3,2,0,1,3,
+ },
+ { 3, 4, 5, 6, -1, -1 },
+ { 3, 6 }
+ },
+ { // subkey bits 6-11
+ {
+ 3,0,2,2,2,1,1,1,1,2,1,0,0,0,2,3,2,3,1,3,0,0,0,2,1,2,2,3,0,3,3,3,
+ 0,1,3,2,3,3,3,1,1,1,1,2,0,1,2,1,3,2,3,1,1,3,2,2,2,3,1,3,2,3,0,0,
+ },
+ { 0, 1, 2, 4, 7, -1 },
+ { 2, 7 }
+ },
+ { // subkey bits 12-17
+ {
+ 3,0,3,1,1,0,2,2,3,1,2,0,3,3,2,3,0,1,0,1,2,3,0,2,0,2,0,1,0,0,1,0,
+ 2,3,1,2,1,0,2,0,2,1,0,1,0,2,1,0,3,1,2,3,1,3,1,1,1,2,0,2,2,0,0,0,
+ },
+ { 0, 1, 2, 3, 6, 7 },
+ { 0, 1 }
+ },
+ { // subkey bits 18-23
+ {
+ 3,2,0,3,0,2,2,1,1,2,3,2,1,3,2,1,2,2,1,3,3,2,1,0,1,0,1,3,0,0,0,2,
+ 2,1,0,1,0,1,0,1,3,1,1,2,2,3,2,0,3,3,2,0,2,1,3,3,0,0,3,0,1,1,3,3,
+ },
+ { 0, 1, 3, 5, 6, 7 },
+ { 4, 5 }
+ },
+};
+
+static const struct sbox fn1_r2_boxes[4] =
+{
+ { // subkey bits 24-29
+ {
+ 3,3,2,0,3,0,3,1,0,3,0,1,0,2,1,3,1,3,0,3,3,1,3,3,3,2,3,2,2,3,1,2,
+ 0,2,2,1,0,1,2,0,3,3,0,1,3,2,1,2,3,0,1,3,0,1,2,2,1,2,1,2,0,1,3,0,
+ },
+ { 0, 1, 2, 3, 6, -1 },
+ { 1, 6 }
+ },
+ { // subkey bits 30-35
+ {
+ 1,2,3,2,1,3,0,1,1,0,2,0,0,2,3,2,3,3,0,1,2,2,1,0,1,0,1,2,3,2,1,3,
+ 2,2,2,0,1,0,2,3,2,1,2,1,2,1,0,3,0,1,2,3,1,2,1,3,2,0,3,2,3,0,2,0,
+ },
+ { 2, 4, 5, 6, 7, -1 },
+ { 5, 7 }
+ },
+ { // subkey bits 36-41
+ {
+ 0,1,0,2,1,1,0,1,0,2,2,2,1,3,0,0,1,1,3,1,2,2,2,3,1,0,3,3,3,2,2,2,
+ 1,1,3,0,3,1,3,0,1,3,3,2,1,1,0,0,1,2,2,2,1,1,1,2,2,0,0,3,2,3,1,3,
+ },
+ { 1, 2, 3, 4, 5, 7 },
+ { 0, 3 }
+ },
+ { // subkey bits 42-47
+ {
+ 2,1,0,3,3,3,2,0,1,2,1,1,1,0,3,1,1,3,3,0,1,2,1,0,0,0,3,0,3,0,3,0,
+ 1,3,3,3,0,3,2,0,2,1,2,2,2,1,1,3,0,1,0,1,0,1,1,1,1,3,1,0,1,2,3,3,
+ },
+ { 0, 1, 3, 4, 6, 7 },
+ { 2, 4 }
+ },
+};
+
+static const struct sbox fn1_r3_boxes[4] =
+{
+ { // subkey bits 48-53
+ {
+ 0,0,0,3,3,1,1,0,2,0,2,0,0,0,3,2,0,1,2,3,2,2,1,0,3,0,0,0,0,0,2,3,
+ 3,0,0,1,1,2,3,3,0,1,3,2,0,1,3,3,2,0,0,1,0,2,0,0,0,3,1,3,3,3,3,3,
+ },
+ { 0, 1, 5, 6, 7, -1 },
+ { 0, 5 }
+ },
+ { // subkey bits 54-59
+ {
+ 2,3,2,3,0,2,3,0,2,2,3,0,3,2,0,2,1,0,2,3,1,1,1,0,0,1,0,2,1,2,2,1,
+ 3,0,2,1,2,3,3,0,3,2,3,1,0,2,1,0,1,2,2,3,0,2,1,3,1,3,0,2,1,1,1,3,
+ },
+ { 2, 3, 4, 6, 7, -1 },
+ { 6, 7 }
+ },
+ { // subkey bits 60-65
+ {
+ 3,0,2,1,1,3,1,2,2,1,2,2,2,0,0,1,2,3,1,0,2,0,0,2,3,1,2,0,0,0,3,0,
+ 2,1,1,2,0,0,1,2,3,1,1,2,0,1,3,0,3,1,1,0,0,2,3,0,0,0,0,3,2,0,0,0,
+ },
+ { 0, 2, 3, 4, 5, 6 },
+ { 1, 4 }
+ },
+ { // subkey bits 66-71
+ {
+ 0,1,0,0,2,1,3,2,3,3,2,1,0,1,1,1,1,1,0,3,3,1,1,0,0,2,2,1,0,3,3,2,
+ 1,3,3,0,3,0,2,1,1,2,3,2,2,2,1,0,0,3,3,3,2,2,3,1,0,2,3,0,3,1,1,0,
+ },
+ { 0, 1, 2, 3, 5, 7 },
+ { 2, 3 }
+ },
+};
+
+static const struct sbox fn1_r4_boxes[4] =
+{
+ { // subkey bits 72-77
+ {
+ 1,1,1,1,1,0,1,3,3,2,3,0,1,2,0,2,3,3,0,1,2,1,2,3,0,3,2,3,2,0,1,2,
+ 0,1,0,3,2,1,3,2,3,1,2,3,2,0,1,2,2,0,0,0,2,1,3,0,3,1,3,0,1,3,3,0,
+ },
+ { 1, 2, 3, 4, 5, 7 },
+ { 0, 4 }
+ },
+ { // subkey bits 78-83
+ {
+ 3,0,0,0,0,1,0,2,3,3,1,3,0,3,1,2,2,2,3,1,0,0,2,0,1,0,2,2,3,3,0,0,
+ 1,1,3,0,2,3,0,3,0,3,0,2,0,2,0,1,0,3,0,1,3,1,1,0,0,1,3,3,2,2,1,0,
+ },
+ { 0, 1, 2, 3, 5, 6 },
+ { 1, 3 }
+ },
+ { // subkey bits 84-89
+ {
+ 0,1,1,2,0,1,3,1,2,0,3,2,0,0,3,0,3,0,1,2,2,3,3,2,3,2,0,1,0,0,1,0,
+ 3,0,2,3,0,2,2,2,1,1,0,2,2,0,0,1,2,1,1,1,2,3,0,3,1,2,3,3,1,1,3,0,
+ },
+ { 0, 2, 4, 5, 6, 7 },
+ { 2, 6 }
+ },
+ { // subkey bits 90-95
+ {
+ 0,1,2,2,0,1,0,3,2,2,1,1,3,2,0,2,0,1,3,3,0,2,2,3,3,2,0,0,2,1,3,3,
+ 1,1,1,3,1,2,1,1,0,3,3,2,3,2,3,0,3,1,0,0,3,0,0,0,2,2,2,1,2,3,0,0,
+ },
+ { 0, 1, 3, 4, 6, 7 },
+ { 5, 7 }
+ },
+};
+
+/******************************************************************************/
+
+static const struct sbox fn2_r1_boxes[4] =
+{
+ { // subkey bits 0- 5
+ {
+ 2,0,2,0,3,0,0,3,1,1,0,1,3,2,0,1,2,0,1,2,0,2,0,2,2,2,3,0,2,1,3,0,
+ 0,1,0,1,2,2,3,3,0,3,0,2,3,0,1,2,1,1,0,2,0,3,1,1,2,2,1,3,1,1,3,1,
+ },
+ { 0, 3, 4, 5, 7, -1 },
+ { 6, 7 }
+ },
+ { // subkey bits 6-11
+ {
+ 1,1,0,3,0,2,0,1,3,0,2,0,1,1,0,0,1,3,2,2,0,2,2,2,2,0,1,3,3,3,1,1,
+ 1,3,1,3,2,2,2,2,2,2,0,1,0,1,1,2,3,1,1,2,0,3,3,3,2,2,3,1,1,1,3,0,
+ },
+ { 1, 2, 3, 4, 6, -1 },
+ { 3, 5 }
+ },
+ { // subkey bits 12-17
+ {
+ 1,0,2,2,3,3,3,3,1,2,2,1,0,1,2,1,1,2,3,1,2,0,0,1,2,3,1,2,0,0,0,2,
+ 2,0,1,1,0,0,2,0,0,0,2,3,2,3,0,1,3,0,0,0,2,3,2,0,1,3,2,1,3,1,1,3,
+ },
+ { 1, 2, 4, 5, 6, 7 },
+ { 1, 4 }
+ },
+ { // subkey bits 18-23
+ {
+ 1,3,3,0,3,2,3,1,3,2,1,1,3,3,2,1,2,3,0,3,1,0,0,2,3,0,0,0,3,3,0,1,
+ 2,3,0,0,0,1,2,1,3,0,0,1,0,2,2,2,3,3,1,2,1,3,0,0,0,3,0,1,3,2,2,0,
+ },
+ { 0, 2, 3, 5, 6, 7 },
+ { 0, 2 }
+ },
+};
+
+static const struct sbox fn2_r2_boxes[4] =
+{
+ { // subkey bits 24-29
+ {
+ 3,1,3,0,3,0,3,1,3,0,0,1,1,3,0,3,1,1,0,1,2,3,2,3,3,1,2,2,2,0,2,3,
+ 2,2,2,1,1,3,3,0,3,1,2,1,1,1,0,2,0,3,3,0,0,2,0,0,1,1,2,1,2,1,1,0,
+ },
+ { 0, 2, 4, 6, -1, -1 },
+ { 4, 6 }
+ },
+ { // subkey bits 30-35
+ {
+ 0,3,0,3,3,2,1,2,3,1,1,1,2,0,2,3,0,3,1,2,2,1,3,3,3,2,1,2,2,0,1,0,
+ 2,3,0,1,2,0,1,1,2,0,2,1,2,0,2,3,3,1,0,2,3,3,0,3,1,1,3,0,0,1,2,0,
+ },
+ { 1, 3, 4, 5, 6, 7 },
+ { 0, 3 }
+ },
+ { // subkey bits 36-41
+ {
+ 0,0,2,1,3,2,1,0,1,2,2,2,1,1,0,3,1,2,2,3,2,1,1,0,3,0,0,1,1,2,3,1,
+ 3,3,2,2,1,0,1,1,1,2,0,1,2,3,0,3,3,0,3,2,2,0,2,2,1,2,3,2,1,0,2,1,
+ },
+ { 0, 1, 3, 4, 5, 7 },
+ { 1, 7 }
+ },
+ { // subkey bits 42-47
+ {
+ 0,2,1,2,0,2,2,0,1,3,2,0,3,2,3,0,3,3,2,3,1,2,3,1,2,2,0,0,2,2,1,2,
+ 2,3,3,3,1,1,0,0,0,3,2,0,3,2,3,1,1,1,1,0,1,0,1,3,0,0,1,2,2,3,2,0,
+ },
+ { 1, 2, 3, 5, 6, 7 },
+ { 2, 5 }
+ },
+};
+
+static const struct sbox fn2_r3_boxes[4] =
+{
+ { // subkey bits 48-53
+ {
+ 2,1,2,1,2,3,1,3,2,2,1,3,3,0,0,1,0,2,0,3,3,1,0,0,1,1,0,2,3,2,1,2,
+ 1,1,2,1,1,3,2,2,0,2,2,3,3,3,2,0,0,0,0,0,3,3,3,0,1,2,1,0,2,3,3,1,
+ },
+ { 2, 3, 4, 6, -1, -1 },
+ { 3, 5 }
+ },
+ { // subkey bits 54-59
+ {
+ 3,2,3,3,1,0,3,0,2,0,1,1,1,0,3,0,3,1,3,1,0,1,2,3,2,2,3,2,0,1,1,2,
+ 3,0,0,2,1,0,0,2,2,0,1,0,0,2,0,0,1,3,1,3,2,0,3,3,1,0,2,2,2,3,0,0,
+ },
+ { 0, 1, 3, 5, 7, -1 },
+ { 0, 2 }
+ },
+ { // subkey bits 60-65
+ {
+ 2,2,1,0,2,3,3,0,0,0,1,3,1,2,3,2,2,3,1,3,0,3,0,3,3,2,2,1,0,0,0,2,
+ 1,2,2,2,0,0,1,2,0,1,3,0,2,3,2,1,3,2,2,2,3,1,3,0,2,0,2,1,0,3,3,1,
+ },
+ { 0, 1, 2, 3, 5, 7 },
+ { 1, 6 }
+ },
+ { // subkey bits 66-71
+ {
+ 1,2,3,2,0,2,1,3,3,1,0,1,1,2,2,0,0,1,1,1,2,1,1,2,0,1,3,3,1,1,1,2,
+ 3,3,1,0,2,1,1,1,2,1,0,0,2,2,3,2,3,2,2,0,2,2,3,3,0,2,3,0,2,2,1,1,
+ },
+ { 0, 2, 4, 5, 6, 7 },
+ { 4, 7 }
+ },
+};
+
+static const struct sbox fn2_r4_boxes[4] =
+{
+ { // subkey bits 72-77
+ {
+ 2,0,1,1,2,1,3,3,1,1,1,2,0,1,0,2,0,1,2,0,2,3,0,2,3,3,2,2,3,2,0,1,
+ 3,0,2,0,2,3,1,3,2,0,0,1,1,2,3,1,1,1,0,1,2,0,3,3,1,1,1,3,3,1,1,0,
+ },
+ { 0, 1, 3, 6, 7, -1 },
+ { 0, 3 }
+ },
+ { // subkey bits 78-83
+ {
+ 1,2,2,1,0,3,3,1,0,2,2,2,1,0,1,0,1,1,0,1,0,2,1,0,2,1,0,2,3,2,3,3,
+ 2,2,1,2,2,3,1,3,3,3,0,1,0,1,3,0,0,0,1,2,0,3,3,2,3,2,1,3,2,1,0,2,
+ },
+ { 0, 1, 2, 4, 5, 6 },
+ { 4, 7 }
+ },
+ { // subkey bits 84-89
+ {
+ 2,3,2,1,3,2,3,0,0,2,1,1,0,0,3,2,3,1,0,1,2,2,2,1,3,2,2,1,0,2,1,2,
+ 0,3,1,0,0,3,1,1,3,3,2,0,1,0,1,3,0,0,1,2,1,2,3,2,1,0,0,3,2,1,1,3,
+ },
+ { 0, 2, 3, 4, 5, 7 },
+ { 1, 2 }
+ },
+ { // subkey bits 90-95
+ {
+ 2,0,0,3,2,2,2,1,3,3,1,1,2,0,0,3,1,0,3,2,1,0,2,0,3,2,2,3,2,0,3,0,
+ 1,3,0,2,2,1,3,3,0,1,0,3,1,1,3,2,0,3,0,2,3,2,1,3,2,3,0,0,1,3,2,1,
+ },
+ { 2, 3, 4, 5, 6, 7 },
+ { 5, 6 }
+ },
+};
+
+/******************************************************************************/
+
+
+static UINT8 fn(UINT8 in, const struct optimised_sbox *sboxes, UINT32 key)
+{
+ const struct optimised_sbox *sbox1 = &sboxes[0];
+ const struct optimised_sbox *sbox2 = &sboxes[1];
+ const struct optimised_sbox *sbox3 = &sboxes[2];
+ const struct optimised_sbox *sbox4 = &sboxes[3];
+
+ return
+ sbox1->output[sbox1->input_lookup[in] ^ ((key >> 0) & 0x3f)] |
+ sbox2->output[sbox2->input_lookup[in] ^ ((key >> 6) & 0x3f)] |
+ sbox3->output[sbox3->input_lookup[in] ^ ((key >> 12) & 0x3f)] |
+ sbox4->output[sbox4->input_lookup[in] ^ ((key >> 18) & 0x3f)];
+}
+
+
+
+// srckey is the 64-bit master key (2x32 bits)
+// dstkey will contain the 96-bit key for the 1st FN (4x24 bits)
+static void expand_1st_key(UINT32 *dstkey, const UINT32 *srckey)
+{
+ static const int bits[96] =
+ {
+ 33, 58, 49, 36, 0, 31,
+ 22, 30, 3, 16, 5, 53,
+ 10, 41, 23, 19, 27, 39,
+ 43, 6, 34, 12, 61, 21,
+ 48, 13, 32, 35, 6, 42,
+ 43, 14, 21, 41, 52, 25,
+ 18, 47, 46, 37, 57, 53,
+ 20, 8, 55, 54, 59, 60,
+ 27, 33, 35, 18, 8, 15,
+ 63, 1, 50, 44, 16, 46,
+ 5, 4, 45, 51, 38, 25,
+ 13, 11, 62, 29, 48, 2,
+ 59, 61, 62, 56, 51, 57,
+ 54, 9, 24, 63, 22, 7,
+ 26, 42, 45, 40, 23, 14,
+ 2, 31, 52, 28, 44, 17,
+ };
+ int i;
+
+ dstkey[0] = 0;
+ dstkey[1] = 0;
+ dstkey[2] = 0;
+ dstkey[3] = 0;
+
+ for (i = 0; i < 96; ++i)
+ dstkey[i / 24] |= BIT(srckey[bits[i] / 32], bits[i] % 32) << (i % 24);
+}
+
+
+// srckey is the 64-bit master key (2x32 bits) XORed with the subkey
+// dstkey will contain the 96-bit key for the 2nd FN (4x24 bits)
+static void expand_2nd_key(UINT32 *dstkey, const UINT32 *srckey)
+{
+ static const int bits[96] =
+ {
+ 34, 9, 32, 24, 44, 54,
+ 38, 61, 47, 13, 28, 7,
+ 29, 58, 18, 1, 20, 60,
+ 15, 6, 11, 43, 39, 19,
+ 63, 23, 16, 62, 54, 40,
+ 31, 3, 56, 61, 17, 25,
+ 47, 38, 55, 57, 5, 4,
+ 15, 42, 22, 7, 2, 19,
+ 46, 37, 29, 39, 12, 30,
+ 49, 57, 31, 41, 26, 27,
+ 24, 36, 11, 63, 33, 16,
+ 56, 62, 48, 60, 59, 32,
+ 12, 30, 53, 48, 10, 0,
+ 50, 35, 3, 59, 14, 49,
+ 51, 45, 44, 2, 21, 33,
+ 55, 52, 23, 28, 8, 26,
+ };
+ int i;
+
+ dstkey[0] = 0;
+ dstkey[1] = 0;
+ dstkey[2] = 0;
+ dstkey[3] = 0;
+
+ for (i = 0; i < 96; ++i)
+ dstkey[i / 24] |= BIT(srckey[bits[i] / 32], bits[i] % 32) << (i % 24);
+}
+
+
+
+// seed is the 16-bit seed generated by the first FN
+// subkey will contain the 64-bit key to be XORed with the master key
+// for the 2nd FN (2x32 bits)
+static void expand_subkey(UINT32* subkey, UINT16 seed)
+{
+ // Note that each row of the table is a permutation of the seed bits.
+ static const int bits[64] =
+ {
+ 5, 10, 14, 9, 4, 0, 15, 6, 1, 8, 3, 2, 12, 7, 13, 11,
+ 5, 12, 7, 2, 13, 11, 9, 14, 4, 1, 6, 10, 8, 0, 15, 3,
+ 4, 10, 2, 0, 6, 9, 12, 1, 11, 7, 15, 8, 13, 5, 14, 3,
+ 14, 11, 12, 7, 4, 5, 2, 10, 1, 15, 0, 9, 8, 6, 13, 3,
+ };
+ int i;
+
+ subkey[0] = 0;
+ subkey[1] = 0;
+
+ for (i = 0; i < 64; ++i)
+ subkey[i / 32] |= BIT(seed, bits[i]) << (i % 32);
+}
+
+
+
+static UINT16 feistel(UINT16 val, const int *bitsA, const int *bitsB,
+ const struct optimised_sbox* boxes1, const struct optimised_sbox* boxes2, const struct optimised_sbox* boxes3, const struct optimised_sbox* boxes4,
+ UINT32 key1, UINT32 key2, UINT32 key3, UINT32 key4)
+{
+ UINT8 l = BITSWAP8(val, bitsB[7],bitsB[6],bitsB[5],bitsB[4],bitsB[3],bitsB[2],bitsB[1],bitsB[0]);
+ UINT8 r = BITSWAP8(val, bitsA[7],bitsA[6],bitsA[5],bitsA[4],bitsA[3],bitsA[2],bitsA[1],bitsA[0]);
+
+ l ^= fn(r, boxes1, key1);
+ r ^= fn(l, boxes2, key2);
+ l ^= fn(r, boxes3, key3);
+ r ^= fn(l, boxes4, key4);
+
+ return
+ (BIT(l, 0) << bitsA[0]) |
+ (BIT(l, 1) << bitsA[1]) |
+ (BIT(l, 2) << bitsA[2]) |
+ (BIT(l, 3) << bitsA[3]) |
+ (BIT(l, 4) << bitsA[4]) |
+ (BIT(l, 5) << bitsA[5]) |
+ (BIT(l, 6) << bitsA[6]) |
+ (BIT(l, 7) << bitsA[7]) |
+ (BIT(r, 0) << bitsB[0]) |
+ (BIT(r, 1) << bitsB[1]) |
+ (BIT(r, 2) << bitsB[2]) |
+ (BIT(r, 3) << bitsB[3]) |
+ (BIT(r, 4) << bitsB[4]) |
+ (BIT(r, 5) << bitsB[5]) |
+ (BIT(r, 6) << bitsB[6]) |
+ (BIT(r, 7) << bitsB[7]);
+}
+
+
+
+static int extract_inputs(UINT32 val, const int *inputs)
+{
+ int i;
+ int res = 0;
+
+ for (i = 0; i < 6; ++i)
+ {
+ if (inputs[i] != -1)
+ res |= BIT(val, inputs[i]) << i;
+ }
+
+ return res;
+}
+
+
+
+static void optimise_sboxes(struct optimised_sbox* out, const struct sbox* in)
+{
+ int box;
+
+ for (box = 0; box < 4; ++box)
+ {
+ int i;
+
+ // precalculate the input lookup
+ for (i = 0; i < 256; ++i)
+ {
+ out[box].input_lookup[i] = extract_inputs(i, in[box].inputs);
+ }
+
+ // precalculate the output masks
+ for (i = 0; i < 64; ++i)
+ {
+ int o = in[box].table[i];
+
+ out[box].output[i] = 0;
+ if (o & 1)
+ out[box].output[i] |= 1 << in[box].outputs[0];
+ if (o & 2)
+ out[box].output[i] |= 1 << in[box].outputs[1];
+ }
+ }
+}
+
+
+
+static void cps2_decrypt(const UINT32 *master_key, UINT32 upper_limit)
+{
+ UINT16 *rom = (UINT16 *)memory_region(REGION_CPU1);
+ int length = memory_region_length(REGION_CPU1);
+ UINT16 *dec = auto_malloc(length);
+ int i;
+ UINT32 key1[4];
+ struct optimised_sbox sboxes1[4*4];
+ struct optimised_sbox sboxes2[4*4];
+
+ optimise_sboxes(&sboxes1[0*4], fn1_r1_boxes);
+ optimise_sboxes(&sboxes1[1*4], fn1_r2_boxes);
+ optimise_sboxes(&sboxes1[2*4], fn1_r3_boxes);
+ optimise_sboxes(&sboxes1[3*4], fn1_r4_boxes);
+ optimise_sboxes(&sboxes2[0*4], fn2_r1_boxes);
+ optimise_sboxes(&sboxes2[1*4], fn2_r2_boxes);
+ optimise_sboxes(&sboxes2[2*4], fn2_r3_boxes);
+ optimise_sboxes(&sboxes2[3*4], fn2_r4_boxes);
+
+
+ // expand master key to 1st FN 96-bit key
+ expand_1st_key(key1, master_key);
+
+ // add extra bits for s-boxes with less than 6 inputs
+ key1[0] ^= BIT(key1[0], 1) << 4;
+ key1[0] ^= BIT(key1[0], 2) << 5;
+ key1[0] ^= BIT(key1[0], 8) << 11;
+ key1[1] ^= BIT(key1[1], 0) << 5;
+ key1[1] ^= BIT(key1[1], 8) << 11;
+ key1[2] ^= BIT(key1[2], 1) << 5;
+ key1[2] ^= BIT(key1[2], 8) << 11;
+
+ for (i = 0; i < 0x10000; ++i)
+ {
+ int a;
+ UINT16 seed;
+ UINT32 subkey[2];
+ UINT32 key2[4];
+
+ if ((i & 0xff) == 0)
+ {
+ char loadingMessage[256]; // for displaying with UI
+ sprintf(loadingMessage, "Decrypting %d%%", i*100/0x10000);
+ ui_set_startup_text(loadingMessage,FALSE);
+ }
+
+
+ // pass the address through FN1
+ seed = feistel(i, fn1_groupA, fn1_groupB,
+ &sboxes1[0*4], &sboxes1[1*4], &sboxes1[2*4], &sboxes1[3*4],
+ key1[0], key1[1], key1[2], key1[3]);
+
+
+ // expand the result to 64-bit
+ expand_subkey(subkey, seed);
+
+ // XOR with the master key
+ subkey[0] ^= master_key[0];
+ subkey[1] ^= master_key[1];
+
+ // expand key to 2nd FN 96-bit key
+ expand_2nd_key(key2, subkey);
+
+ // add extra bits for s-boxes with less than 6 inputs
+ key2[0] ^= BIT(key2[0], 0) << 5;
+ key2[0] ^= BIT(key2[0], 6) << 11;
+ key2[1] ^= BIT(key2[1], 0) << 5;
+ key2[1] ^= BIT(key2[1], 1) << 4;
+ key2[2] ^= BIT(key2[2], 2) << 5;
+ key2[2] ^= BIT(key2[2], 3) << 4;
+ key2[2] ^= BIT(key2[2], 7) << 11;
+ key2[3] ^= BIT(key2[3], 1) << 5;
+
+
+ // decrypt the opcodes
+ for (a = i; a < length/2 && a < upper_limit/2; a += 0x10000)
+ {
+ dec[a] = feistel(rom[a], fn2_groupA, fn2_groupB,
+ &sboxes2[0*4], &sboxes2[1*4], &sboxes2[2*4], &sboxes2[3*4],
+ key2[0], key2[1], key2[2], key2[3]);
+ }
+ // copy the unencrypted part (not really needed)
+ while (a < length/2)
+ {
+ dec[a] = rom[a];
+ a += 0x10000;
+ }
+ }
+
+ memory_set_decrypted_region(0, 0x000000, length - 1, dec);
+ m68k_set_encrypted_opcode_range(0,0,length);
+}
+
+
+
+
+
+
+
+
+
+
+struct game_keys
+{
+ const char *name; /* game driver name */
+ const UINT32 keys[2];
+ UINT32 upper_limit;
+};
+
+
+/*
+(1) On a dead board, the only encrypted range is actually FF0000-FFFFFF.
+It doesn't start from 0, and it's the upper half of a 128kB bank.
+*/
+
+static const struct game_keys keys_table[] =
+{
+ // name key upper watchdog
+ { "dead", { 0xffffffff,0xffffffff }, /*(1)*/ }, // ffff ffff ffff
+ { "ssf2", { 0x23456789,0xabcdef01 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2u", { 0x12345678,0x9abcdef0 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2a", { 0x3456789a,0xbcdef012 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2ar1", { 0x3456789a,0xbcdef012 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2j", { 0x01234567,0x89abcdef }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2jr1", { 0x01234567,0x89abcdef }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2jr2", { 0x01234567,0x89abcdef }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2tb", { 0x89abcdef,0x01234567 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2tbr1", { 0x89abcdef,0x01234567 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2tbj", { 0x6789abcd,0xef012345 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ddtod", { 0x4767fe08,0x14ca35d9 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ddtodr1", { 0x4767fe08,0x14ca35d9 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ddtodu", { 0xeca19c3d,0x24736bf0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ddtodur1", { 0xeca19c3d,0x24736bf0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ddtodj", { 0x4510e79c,0xf36b8a2d }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ddtodjr1", { 0x4510e79c,0xf36b8a2d }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ddtoda", { 0xdecac105,0x19710411 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ddtodh", { 0x19691019,0xe825dde0 }, 0x180000 }, // 0C78 1019 4000 cmpi.w #$1019,$4000
+ { "ecofghtr", { 0x931031dc,0xba987654 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345
+ { "ecofghtu", { 0x931031ed,0xcba98765 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345
+ { "ecofgtu1", { 0x931031ed,0xcba98765 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345
+ { "uecology", { 0x931031fe,0xdcba9876 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345
+ { "ecofghta", { 0x931031ba,0x98765432 }, 0x200000 }, // 0838 0003 7345 btst #3,$7345
+ { "ssf2t", { 0x944e8302,0x56d3143c }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2ta", { 0x94c4d002,0x664a1471 }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2tu", { 0x94fa8902,0x4c77143f }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2tur1", { 0x94fa8902,0x4c77143f }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "ssf2xj", { 0x942a5702,0x05ac140e }, 0x400000 }, // 0838 0007 2000 btst #7,$2000
+ { "xmcota", { 0x3bc6eda4,0x97f80251 }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "xmcotau", { 0x32a57ecd,0x98016f4b }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "xmcotah", { 0xf5e8dc34,0xa096b217 }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "xmcotaj", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "xmcotaj1", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "xmcotaj2", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "xmcotajr", { 0x46027315,0xaf8bcd9e }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "xmcotaa", { 0x0795a4e2,0xdb3f861c }, 0x100000 }, // 0C80 1972 0301 cmpi.l #$19720301,D0
+ { "armwar", { 0x9e9d4c0b,0x8a39081f }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "armwarr1", { 0x9e9d4c0b,0x8a39081f }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "armwaru", { 0xd4c0b8a3,0x9081f9e9 }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "pgear", { 0x9d4c0b8a,0x39081f9e }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "pgearr1", { 0x9d4c0b8a,0x39081f9e }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "armwara", { 0x1f9e9d4c,0x0b8a3908 }, 0x100000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "avsp", { 0x15208f79,0x4ade6cb3 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0
+ { "avspu", { 0xb4f61089,0xccf75a23 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0
+ { "avspj", { 0xe9dcb8fa,0x51372064 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0
+ { "avspa", { 0xc168f3bd,0x2e4a5970 }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0
+ { "avsph", { 0x712b690a,0x43cd8e5f }, 0x100000 }, // 0C80 1234 5678 cmpi.l #$12345678,D0
+ { "dstlk", { 0x13d8a7a8,0x0008b090 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160
+ { "dstlku", { 0x1e80ebf0,0x10227119 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160
+ { "dstlkur1", { 0x1e80ebf0,0x10227119 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160
+ { "dstlka", { 0x205d8398,0x06221971 }, 0x100000 }, // 0838 0000 6160 btst #0,$6160
+ { "vampj", { 0xefcb0804,0x026819ae }, 0x100000 }, // 0838 0000 6160 btst #0,$6160
+ { "vampja", { 0xefcb0804,0x026819ae }, 0x100000 }, // 0838 0000 6160 btst #0,$6160
+ { "vampjr1", { 0xefcb0804,0x026819ae }, 0x100000 }, // 0838 0000 6160 btst #0,$6160
+ { "ringdest", { 0x19940727,0x17444903 }, 0x180000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "smbomb", { 0x19940209,0x17031403 }, 0x180000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "smbombr1", { 0x19940209,0x17031403 }, 0x180000 }, // 3039 0080 4020 move.w $00804020,D0
+ { "cybots", { 0x45425943,0x05090901 }, 0x100000 }, // 0C38 00FF 0C38 cmpi.b #$FF,$0C38
+ { "cybotsu", { 0x43050909,0x01554259 }, 0x100000 }, // 0C38 00FF 0C38 cmpi.b #$FF,$0C38
+ { "cybotsj", { 0x05090901,0x4a425943 }, 0x100000 }, // 0C38 00FF 0C38 cmpi.b #$FF,$0C38
+ { "msh", { 0x1a11ee26,0xe7955d17 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "mshu", { 0x8705a24e,0x4a17319b }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "mshj", { 0x05e88219,0x31ad2142 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "mshjr1", { 0x05e88219,0x31ad2142 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "msha", { 0x457aeb01,0x3897c53d }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "mshh", { 0xfc4c5a50,0xb59cc190 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "mshb", { 0x7a152416,0xad27f8e6 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "nwarr", { 0x1019d145,0x03f05a05 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160
+ { "nwarru", { 0x104a7d0c,0x3f1b7a1e }, 0x180000 }, // 0838 0000 6160 btst #0,$6160
+ { "nwarrh", { 0xc4961b01,0x2a946020 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160
+ { "nwarrb", { 0x17c67109,0xb7362a20 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160
+ { "vhuntj", { 0x1135b2c3,0xa4e9d7f2 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160
+ { "vhuntjr1", { 0x1135b2c3,0xa4e9d7f2 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160
+ { "vhuntjr2", { 0x1135b2c3,0xa4e9d7f2 }, 0x180000 }, // 0838 0000 6160 btst #0,$6160
+ { "sfa", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfar1", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfar2", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfar3", { 0x0f895d6e,0xc4273a1b }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfau", { 0x25bead36,0x97cf4018 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfza", { 0xe43dc508,0x621b9a7f }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfzj", { 0x8db3167a,0xc29e0f45 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfzjr1", { 0x8db3167a,0xc29e0f45 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfzjr2", { 0x8db3167a,0xc29e0f45 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfzh", { 0x876b0e39,0x5ca24fd1 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfzb", { 0xef415bd3,0x7a92c680 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "sfzbr1", { 0xef415bd3,0x7a92c680 }, 0x080000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "mmancp2u", { 0x054893fa,0x94642525 }, 0x100000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "rmancp2j", { 0x07215501,0x37fa32d0 }, 0x100000 }, // 0C80 0564 2194 cmpi.l #$05642194,D0
+ { "19xx", { 0x0e07181f,0x5fd0f080 }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1
+ { "19xxa", { 0xcce74cf5,0xb7da3711 }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1
+ { "19xxj", { 0x00115df8,0x000ff87e }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1
+ { "19xxjr1", { 0x00115df8,0x000ff87e }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1
+ { "19xxh", { 0x5d49bafa,0xf7216c9f }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1
+ { "19xxb", { 0xe5f9476a,0x2dfb623f }, 0x200000 }, // 0C81 0095 1101 cmpi.l #$00951101,D1
+ { "ddsom", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomr1", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomr2", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomr3", { 0x87889abc,0xd81f5f63 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomu", { 0x489f0526,0x1bcd3e7a }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomur1", { 0x489f0526,0x1bcd3e7a }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomj", { 0xae92fa94,0x315a9045 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomjr1", { 0xae92fa94,0x315a9045 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsoma", { 0x8719abcd,0xef028345 }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "ddsomb", { 0x7149a782,0xf3a5bfce }, 0x100000 }, // 0C81 1966 0419 cmpi.l #$19660419,D1
+ { "megaman2", { 0x50501cac,0xed346550 }, 0x100000 }, // 0C80 0164 7101 cmpi.l #$01647101,D0
+ { "megamn2a", { 0x3f148a2b,0xd6790a15 }, 0x100000 }, // 0C80 0164 7101 cmpi.l #$01647101,D0
+ { "rckman2j", { 0x319eca73,0x10551270 }, 0x100000 }, // 0C80 0164 7101 cmpi.l #$01647101,D0
+ { "qndream", { 0x5804ea73,0xf66b0798 }, 0x080000 }, // 0C81 1973 0827 cmpi.l #$19730827,D1
+ { "sfa2", { 0x1bbf3d96,0x8af4614a }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0
+ { "sfz2j", { 0x83f47e99,0xda772111 }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0
+ { "sfz2a", { 0xafc2e8f4,0x43789487 }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0
+ { "sfz2b", { 0xac134599,0x61f8bb2e }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0
+ { "sfz2br1", { 0xac134599,0x61f8bb2e }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0
+ { "sfz2h", { 0xf98a2d42,0x597b089f }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0
+ { "sfz2n", { 0xe32bf89c,0xa57b46dc }, 0x100000 }, // 0C80 3039 9783 cmpi.l #$30399783,D0
+ { "sfz2aj", { 0x99450c88,0xa00a2c4d }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0
+ { "sfz2ah", { 0x95f15b7c,0x200c08c6 }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0
+ { "sfz2ab", { 0x73cd4a28,0xff83af1c }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0
+ { "sfz2aa", { 0xf172c0d0,0x040621a6 }, 0x100000 }, // 0C80 8E73 9110 cmpi.l #$8E739110,D0
+ { "spf2t", { 0x706a8750,0x7d0fc185 }, 0x040000 }, // 0C80 3039 9819 cmpi.l #$30399819,D0
+ { "spf2xj", { 0xb12c835a,0xe90976ff }, 0x040000 }, // 0C80 3039 9819 cmpi.l #$30399819,D0
+ { "spf2ta", { 0x9c48e1ab,0xd60f34fb }, 0x040000 }, // 0C80 3039 9819 cmpi.l #$30399819,D0
+ { "xmvsf", { 0xbdcf8519,0x3fb2acea }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfr1", { 0xbdcf8519,0x3fb2acea }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfu", { 0x4fcb03d2,0xf8653bc1 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfur1", { 0x4fcb03d2,0xf8653bc1 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfj", { 0x38df93bc,0x210373ac }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfjr1", { 0x38df93bc,0x210373ac }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfjr2", { 0x38df93bc,0x210373ac }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfa", { 0x7438fc3e,0x19abed90 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfar1", { 0x7438fc3e,0x19abed90 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfh", { 0x835fb2d0,0x42fa9137 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "xmvsfb", { 0x8ead9e4a,0xb02184f0 }, 0x100000 }, // 0C81 1972 0327 cmpi.l #$19720327,D1
+ { "batcir", { 0xd195e597,0x3cbce2b5 }, 0x200000 }, // 0C81 0097 0131 cmpi.l #$00970131,D1
+ { "batcira", { 0x1e5d80cb,0x98882ec7 }, 0x200000 }, // 0C81 0097 0131 cmpi.l #$00970131,D1
+ { "batcirj", { 0x00ff4dd8,0x000008e8 }, 0x200000 }, // 0C81 0097 0131 cmpi.l #$00970131,D1
+ { "csclub", { 0x662e9fa0,0x4210e7c1 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1
+ { "cscluba", { 0x1366de2a,0x9ab42937 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1
+ { "csclubj", { 0x4a2d0be5,0x56c013c0 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1
+ { "csclubh", { 0xf014a8a7,0x2e7794d0 }, 0x200000 }, // 0C81 0097 0310 cmpi.l #$00970310,D1
+ { "mshvsf", { 0x1384ae60,0x9cd725bf }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfu", { 0xa36d4971,0xcef51b28 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfu1", { 0xa36d4971,0xcef51b28 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfj", { 0x5dc391f8,0xa627e0b4 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfj1", { 0x5dc391f8,0xa627e0b4 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfj2", { 0x5dc391f8,0xa627e0b4 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfh", { 0x7e916fc4,0x03ab852d }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfa", { 0x52e3fa61,0x0c497bd8 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfa1", { 0x52e3fa61,0x0c497bd8 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfb", { 0xda68c749,0x5bf3e201 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mshvsfb1", { 0xda68c749,0x5bf3e201 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "sgemf", { 0x84234976,0x5e0fbb7e }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0
+ { "pfghtj", { 0x97d2ebc0,0x308f94d7 }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0
+ { "sgemfa", { 0x090b412a,0xc47ee993 }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0
+ { "sgemfh", { 0x8163a71b,0x7c8fd224 }, 0x080000 }, // 0C80 1F74 0D12 cmpi.l #$1F740D12,D0
+ { "vhunt2", { 0x36c1eba3,0x26b10f18 }, 0x100000 }, // 0C80 0692 0760 cmpi.l #$06920760,D0
+ { "vhunt2r1", { 0x36c1eba3,0x26b10f18 }, 0x100000 }, // 0C80 0692 0760 cmpi.l #$06920760,D0
+ { "vsav", { 0xe0cd5881,0x71babb70 }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0
+ { "vsavu", { 0xa62ea0ee,0x573e03e6 }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0
+ { "vsavj", { 0xfa8f4e33,0xa4b881b9 }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0
+ { "vsava", { 0x47ee9930,0x90b412ac }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0
+ { "vsavh", { 0xb2d37c8d,0xd3b7aadd }, 0x100000 }, // 0C80 726A 4BAF cmpi.l #$726A4BAF,D0
+ { "vsav2", { 0xd681e4f4,0x60371edf }, 0x100000 }, // 0C80 0692 0760 cmpi.l #$06920760,D0
+ { "mvsc", { 0x48025ade,0x1c697b27 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "mvscu", { 0x692dc41b,0x7ef1c805 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "mvscj", { 0xafc16138,0x97123eb0 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "mvscjr1", { 0xafc16138,0x97123eb0 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "mvsca", { 0xf248aec6,0x7905cd17 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "mvscar1", { 0xf248aec6,0x7905cd17 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "mvsch", { 0x9d5c7a23,0xe56b18ef }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "mvscb", { 0x0874d6eb,0x51c2b798 }, 0x100000 }, // 0C81 1972 0121 cmpi.l #$19720121,D1
+ { "sfa3", { 0x6abfc8e0,0x2780ddc1 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfa3u", { 0xe7bbf0e5,0x67943248 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfa3ur1", { 0xe7bbf0e5,0x67943248 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfa3b", { 0xd421c0b2,0x8116d296 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfz3j", { 0x7d49f803,0x0cbe2d79 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfz3jr1", { 0x7d49f803,0x0cbe2d79 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfz3jr2", { 0x7d49f803,0x0cbe2d79 }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfz3a", { 0x990b9301,0xa4e42c7e }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "sfz3ar1", { 0x990b9301,0xa4e42c7e }, 0x100000 }, // 0C80 1C62 F5A8 cmpi.l #$1C62F5A8,D0
+ { "jyangoku", { 0x6ca42ae6,0x92f63f59 }, /*?*/ }, // 0C80 3652 1573 cmpi.l #$36521573,D0
+ { "hsf2", { 0xb8ed3630,0xaae30a3d }, 0x100000 }, // 0838 0007 2000 btst #7,$2000
+ { "hsf2j", { 0x65d82fe0,0xdbb83e47 }, 0x100000 }, // 0838 0007 2000 btst #7,$2000
+ { "gigawing", { 0xe52de290,0x1b60d780 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "gwingj", { 0x1126196a,0xbef50895 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "gwinga", { 0x3506a85a,0x66b1b768 }, 0x100000 }, // 0C81 1972 1027 cmpi.l #$19721027,D1
+ { "mmatrix", { 0xac9ebd79,0x410467df }, 0x180000 }, // B6C0 B447 BACF cmpa.w D0,A3 cmp.w D7,D2 cmpa.w A7,A5
+ { "mmatrixj", { 0x4df81e95,0x72ed9823 }, 0x180000 }, // B6C0 B447 BACF cmpa.w D0,A3 cmp.w D7,D2 cmpa.w A7,A5
+ { "mpang", { 0x95f741c6,0xe547a21b }, 0x100000 }, // 0C84 347D 89A3 cmpi.l #$347D89A3,D4
+ { "mpangj", { 0x95f741c6,0xe547a21b }, 0x100000 }, // 0C84 347D 89A3 cmpi.l #$347D89A3,D4
+ { "pzloop2", { 0xa054f812,0xc40d36b4 }, 0x400000 }, // 0C82 9A73 15F1 cmpi.l #$9A7315F1,D2
+ { "pzloop2j", { 0xa054f812,0xc40d36b4 }, 0x400000 }, // 0C82 9A73 15F1 cmpi.l #$9A7315F1,D2
+ { "choko", { 0xd3fb12c6,0x7f8e17b5 }, 0x400000 }, // 0C86 4D17 5B3C cmpi.l #$4D175B3C,D6
+ { "dimahoo", { 0x0ddb8e40,0x2817fd2b }, 0x080000 }, // BE4C B244 B6C5 cmp.w A4,D7 cmp.w D4,D1 cmpa.w D5,A3
+ { "dimahoou", { 0x6575af59,0xb0fea691 }, 0x080000 }, // BE4C B244 B6C5 cmp.w A4,D7 cmp.w D4,D1 cmpa.w D5,A3
+ { "gmahou", { 0x97f7be58,0x6121eb62 }, 0x080000 }, // BE4C B244 B6C5 cmp.w A4,D7 cmp.w D4,D1 cmpa.w D5,A3
+ { "1944", { 0x1d3e724c,0x8b59fc7a }, 0x080000 }, // 0C86 7B5D 94F1 cmpi.l #$7B5D94F1,D6
+ { "1944j", { 0x23d79c3a,0xe18b2746 }, 0x080000 }, // 0C86 7B5D 94F1 cmpi.l #$7B5D94F1,D6
+ { "progear", { 0x639ad8c6,0xef130df3 }, 0x400000 }, // 0C81 63A1 B8D3 cmpi.l #$63A1B8D3,D1
+ { "progearj", { 0x9f7edc56,0x39fb47be }, 0x400000 }, // 0C81 63A1 B8D3 cmpi.l #$63A1B8D3,D1
+ { "progeara", { 0x658ab128,0xfddc9b5e }, 0x400000 }, // 0C81 63A1 B8D3 cmpi.l #$63A1B8D3,D1
+
+ { 0 } // end of table
+};
+
+
+
+
+DRIVER_INIT( cps2crpt )
+{
+ const char *gamename = machine->gamedrv->name;
+ const struct game_keys *k = &keys_table[0];
+
+ while (k->name)
+ {
+ if (strcmp(k->name, gamename) == 0)
+ {
+ // we have a proper key so use it to decrypt
+ cps2_decrypt(k->keys, k->upper_limit ? k->upper_limit : 0x400000);
+
+ break;
+ }
+ ++k;
+ }
+
+ driver_init_cps2_video(machine);
+}
diff --git a/src/mame/machine/cubocd32.c b/src/mame/machine/cubocd32.c
new file mode 100644
index 00000000000..93c1898dfbc
--- /dev/null
+++ b/src/mame/machine/cubocd32.c
@@ -0,0 +1,892 @@
+#include "driver.h"
+#include "includes/amiga.h"
+#include "cdrom.h"
+#include "coreutil.h"
+#include "sound/cdda.h"
+#include "machine/i2cmem.h"
+
+
+/*********************************************************************************
+
+ Akiko custom chip emulation
+
+The Akiko chip has:
+- built in 1KB NVRAM
+- chunky to planar converter
+- custom CDROM controller
+
+TODO: Add CDDA support
+
+*********************************************************************************/
+
+#define LOG_AKIKO 0
+#define LOG_AKIKO_CD 0
+
+#define CD_SECTOR_TIME (1000/((150*1024)/2048)) /* 1X CDROM sector time in msec (300KBps) */
+
+
+#define NVRAM_SIZE 1024
+#define NVRAM_PAGE_SIZE 16 /* max size of one write request */
+
+static struct akiko_def
+{
+ /* chunky to planar converter */
+ UINT32 c2p_input_buffer[8];
+ UINT32 c2p_output_buffer[8];
+ UINT32 c2p_input_index;
+ UINT32 c2p_output_index;
+
+ /* i2c bus */
+ int i2c_scl_out;
+ int i2c_scl_dir;
+ int i2c_sda_out;
+ int i2c_sda_dir;
+
+ /* cdrom */
+ UINT32 cdrom_status[2];
+ UINT32 cdrom_address[2];
+ UINT32 cdrom_track_index;
+ UINT32 cdrom_lba_start;
+ UINT32 cdrom_lba_end;
+ UINT32 cdrom_lba_cur;
+ UINT16 cdrom_readmask;
+ UINT16 cdrom_readreqmask;
+ UINT32 cdrom_dmacontrol;
+ UINT32 cdrom_numtracks;
+ UINT8 cdrom_speed;
+ UINT8 cdrom_cmd_start;
+ UINT8 cdrom_cmd_end;
+ UINT8 cdrom_cmd_resp;
+ cdrom_file *cdrom;
+ UINT8 * cdrom_toc;
+ emu_timer *dma_timer;
+ emu_timer *frame_timer;
+} akiko;
+
+static TIMER_CALLBACK(akiko_dma_proc);
+static TIMER_CALLBACK(akiko_frame_proc);
+
+void amiga_akiko_init(void)
+{
+ i2cmem_init( 0, I2CMEM_SLAVE_ADDRESS, NVRAM_PAGE_SIZE, NVRAM_SIZE, NULL );
+
+ akiko.c2p_input_index = 0;
+ akiko.c2p_output_index = 0;
+
+ akiko.i2c_scl_out = 0;
+ akiko.i2c_scl_dir = 0;
+ akiko.i2c_sda_out = 0;
+ akiko.i2c_sda_dir = 0;
+
+ akiko.cdrom_status[0] = akiko.cdrom_status[1] = 0;
+ akiko.cdrom_address[0] = akiko.cdrom_address[1] = 0;
+ akiko.cdrom_track_index = 0;
+ akiko.cdrom_lba_start = 0;
+ akiko.cdrom_lba_end = 0;
+ akiko.cdrom_lba_cur = 0;
+ akiko.cdrom_readmask = 0;
+ akiko.cdrom_readreqmask = 0;
+ akiko.cdrom_dmacontrol = 0;
+ akiko.cdrom_numtracks = 0;
+ akiko.cdrom_speed = 0;
+ akiko.cdrom_cmd_start = 0;
+ akiko.cdrom_cmd_end = 0;
+ akiko.cdrom_cmd_resp = 0;
+ akiko.cdrom = cdrom_open(get_disk_handle(0));
+ akiko.cdrom_toc = NULL;
+ akiko.dma_timer = timer_alloc(akiko_dma_proc);
+ akiko.frame_timer = timer_alloc(akiko_frame_proc);
+
+ /* create the TOC table */
+ if ( akiko.cdrom != NULL && cdrom_get_last_track(akiko.cdrom) )
+ {
+ UINT8 *p;
+ int i, addrctrl = cdrom_get_adr_control( akiko.cdrom, 0 );
+ UINT32 discend;
+
+ discend = cdrom_get_track_start(akiko.cdrom,cdrom_get_last_track(akiko.cdrom)-1);
+ discend += cdrom_get_toc(akiko.cdrom)->tracks[cdrom_get_last_track(akiko.cdrom)-1].frames;
+ discend = lba_to_msf(discend);
+
+ akiko.cdrom_numtracks = cdrom_get_last_track(akiko.cdrom)+3;
+
+ akiko.cdrom_toc = (UINT8*)auto_malloc(13*akiko.cdrom_numtracks);
+ memset( akiko.cdrom_toc, 0, 13*akiko.cdrom_numtracks);
+
+ p = akiko.cdrom_toc;
+ p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
+ p[3] = 0xa0; /* first track */
+ p[8] = 1;
+ p += 13;
+ p[1] = 0x01;
+ p[3] = 0xa1; /* last track */
+ p[8] = cdrom_get_last_track(akiko.cdrom);
+ p += 13;
+ p[1] = 0x01;
+ p[3] = 0xa2; /* disc end */
+ p[8] = (discend >> 16 ) & 0xff;
+ p[9] = (discend >> 8 ) & 0xff;
+ p[10] = discend & 0xff;
+ p += 13;
+
+ for( i = 0; i < cdrom_get_last_track(akiko.cdrom); i++ )
+ {
+ UINT32 trackpos = cdrom_get_track_start(akiko.cdrom,i);
+
+ trackpos = lba_to_msf(trackpos);
+ addrctrl = cdrom_get_adr_control( akiko.cdrom, i );
+
+ p[1] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
+ p[3] = dec_2_bcd( i+1 );
+ p[8] = (trackpos >> 16 ) & 0xff;
+ p[9] = (trackpos >> 8 ) & 0xff;
+ p[10] = trackpos & 0xff;
+
+ p += 13;
+ }
+ }
+}
+
+static void akiko_nvram_write(UINT32 data)
+{
+ akiko.i2c_scl_out = BIT(data,31);
+ akiko.i2c_sda_out = BIT(data,30);
+ akiko.i2c_scl_dir = BIT(data,15);
+ akiko.i2c_sda_dir = BIT(data,14);
+
+ i2cmem_write( 0, I2CMEM_SCL, akiko.i2c_scl_out );
+ i2cmem_write( 0, I2CMEM_SDA, akiko.i2c_sda_out );
+}
+
+static UINT32 akiko_nvram_read(void)
+{
+ UINT32 v = 0;
+
+ if ( akiko.i2c_scl_dir )
+ {
+ v |= akiko.i2c_scl_out << 31;
+ }
+ else
+ {
+ v |= 0 << 31;
+ }
+
+ if ( akiko.i2c_sda_dir )
+ {
+ v |= akiko.i2c_sda_out << 30;
+ }
+ else
+ {
+ v |= i2cmem_read( 0, I2CMEM_SDA ) << 30;
+ }
+
+ v |= akiko.i2c_scl_dir << 15;
+ v |= akiko.i2c_sda_dir << 14;
+
+ return v;
+}
+
+NVRAM_HANDLER( cd32 )
+{
+ nvram_handler_i2cmem_0( machine, file, read_or_write );
+}
+
+/*************************************
+ *
+ * Akiko Chunky to Planar converter
+ *
+ ************************************/
+
+static void akiko_c2p_write(UINT32 data)
+{
+ akiko.c2p_input_buffer[akiko.c2p_input_index] = data;
+ akiko.c2p_input_index++;
+ akiko.c2p_input_index &= 7;
+ akiko.c2p_output_index = 0;
+}
+
+static UINT32 akiko_c2p_read(void)
+{
+ UINT32 val;
+
+ if ( akiko.c2p_output_index == 0 )
+ {
+ int i;
+
+ for ( i = 0; i < 8; i++ )
+ akiko.c2p_output_buffer[i] = 0;
+
+ for (i = 0; i < 8 * 32; i++) {
+ if (akiko.c2p_input_buffer[7 - (i >> 5)] & (1 << (i & 31)))
+ akiko.c2p_output_buffer[i & 7] |= 1 << (i >> 3);
+ }
+ }
+ akiko.c2p_input_index = 0;
+ val = akiko.c2p_output_buffer[akiko.c2p_output_index];
+ akiko.c2p_output_index++;
+ akiko.c2p_output_index &= 7;
+ return val;
+}
+
+#if LOG_AKIKO
+static const char* akiko_reg_names[] =
+{
+ /*0*/ "ID",
+ /*1*/ "CDROM STATUS 1",
+ /*2*/ "CDROM_STATUS 2",
+ /*3*/ "???",
+ /*4*/ "CDROM ADDRESS 1",
+ /*5*/ "CDROM ADDRESS 2",
+ /*6*/ "CDROM COMMAND 1",
+ /*7*/ "CDROM COMMAND 2",
+ /*8*/ "CDROM READMASK",
+ /*9*/ "CDROM DMACONTROL",
+ /*A*/ "???",
+ /*B*/ "???",
+ /*C*/ "NVRAM",
+ /*D*/ "???",
+ /*E*/ "C2P"
+};
+
+const char* get_akiko_reg_name(int reg)
+{
+ if (reg < 0xf )
+ {
+ return akiko_reg_names[reg];
+ }
+ else
+ {
+ return "???";
+ }
+}
+#endif
+
+/*************************************
+ *
+ * Akiko CDROM Controller
+ *
+ ************************************/
+
+static void akiko_cdda_stop( void )
+{
+ int cddanum = cdda_num_from_cdrom(akiko.cdrom);
+
+ if (cddanum != -1)
+ {
+ cdda_stop_audio(cddanum);
+ timer_reset( akiko.frame_timer, attotime_never );
+ }
+}
+
+static void akiko_cdda_play( UINT32 lba, UINT32 num_blocks )
+{
+ int cddanum = cdda_num_from_cdrom(akiko.cdrom);
+ if (cddanum != -1)
+ {
+ cdda_start_audio(cddanum, lba, num_blocks);
+ timer_adjust( akiko.frame_timer, ATTOTIME_IN_HZ( 75 ), 0, attotime_zero );
+ }
+}
+
+static void akiko_cdda_pause( int pause )
+{
+ int cddanum = cdda_num_from_cdrom(akiko.cdrom);
+ if (cddanum != -1)
+ {
+ if (cdda_audio_active(cddanum) && cdda_audio_paused(cddanum) != pause )
+ {
+ cdda_pause_audio(cddanum, pause);
+
+ if ( pause )
+ {
+ timer_reset( akiko.frame_timer, attotime_never );
+ }
+ else
+ {
+ timer_adjust( akiko.frame_timer, ATTOTIME_IN_HZ( 75 ), 0, attotime_zero );
+ }
+ }
+ }
+}
+
+static UINT8 akiko_cdda_getstatus( UINT32 *lba )
+{
+ int cddanum = cdda_num_from_cdrom(akiko.cdrom);
+
+ if ( lba ) *lba = 0;
+
+ if (cddanum != -1)
+ {
+ if (cdda_audio_active(cddanum))
+ {
+ if ( lba ) *lba = cdda_get_audio_lba(cddanum);
+
+ if (cdda_audio_paused(cddanum))
+ {
+ return 0x12; /* audio paused */
+ }
+ else
+ {
+ return 0x11; /* audio in progress */
+ }
+ }
+ else if (cdda_audio_ended(cddanum))
+ {
+ return 0x13; /* audio ended */
+ }
+ }
+
+ return 0x15; /* no audio status */
+}
+
+static void akiko_set_cd_status( UINT32 status )
+{
+ akiko.cdrom_status[0] |= status;
+
+ if ( akiko.cdrom_status[0] & akiko.cdrom_status[1] )
+ {
+#if LOG_AKIKO_CD
+ logerror( "Akiko CD IRQ\n" );
+#endif
+ amiga_custom_w(REG_INTREQ, 0x8000 | INTENA_PORTS, 0);
+ }
+}
+
+static TIMER_CALLBACK(akiko_frame_proc)
+{
+ int cddanum = cdda_num_from_cdrom(akiko.cdrom);
+
+ (void)param;
+
+ if (cddanum != -1)
+ {
+ UINT8 s = akiko_cdda_getstatus(NULL);
+
+ if ( s == 0x11 )
+ {
+ akiko_set_cd_status( 0x80000000 ); /* subcode ready */
+ }
+
+ timer_adjust( akiko.frame_timer, ATTOTIME_IN_HZ( 75 ), 0, attotime_zero );
+ }
+}
+
+static UINT32 lba_from_triplet( UINT8 *triplet )
+{
+ UINT32 r;
+
+ r = bcd_2_dec(triplet[0]) * (60*75);
+ r += bcd_2_dec(triplet[1]) * 75;
+ r += bcd_2_dec(triplet[2]);
+
+ return r;
+}
+
+static TIMER_CALLBACK(akiko_dma_proc)
+{
+ UINT8 buf[2352];
+ int index;
+
+ if ( (akiko.cdrom_dmacontrol & 0x04000000) == 0 )
+ return;
+
+ if ( akiko.cdrom_readreqmask == 0 )
+ return;
+
+ index = (akiko.cdrom_lba_cur - akiko.cdrom_lba_start) & 0x0f;
+
+ if ( akiko.cdrom_readreqmask & ( 1 << index ) )
+ {
+ UINT32 track = cdrom_get_track( akiko.cdrom, akiko.cdrom_lba_cur );
+ UINT32 datasize = cdrom_get_toc( akiko.cdrom )->tracks[track].datasize;
+ UINT32 subsize = cdrom_get_toc( akiko.cdrom )->tracks[track].subsize;
+ UINT32 secsize = datasize + subsize;
+ int i;
+
+ if ( secsize <= (2352-16) )
+ {
+ UINT32 curmsf = lba_to_msf( akiko.cdrom_lba_cur );
+ memset( buf, 0, 16 );
+
+ buf[3] = akiko.cdrom_lba_cur - akiko.cdrom_lba_start;
+ memset( &buf[4], 0xff, 8 );
+
+ buf[12] = (curmsf >> 16) & 0xff;
+ buf[13] = (curmsf >> 8) & 0xff;
+ buf[14] = curmsf & 0xff;
+ buf[15] = 0x01; /* mode1 */
+
+ if ( !cdrom_read_data( akiko.cdrom, akiko.cdrom_lba_cur, &buf[16], CD_TRACK_RAW_DONTCARE ) )
+ {
+ logerror( "AKIKO: Read error trying to read sector %08x!\n", akiko.cdrom_lba_cur );
+ return;
+ }
+
+ if ( subsize )
+ {
+ if ( !cdrom_read_subcode( akiko.cdrom, akiko.cdrom_lba_cur, &buf[16+datasize] ) )
+ {
+ logerror( "AKIKO: Read error trying to read subcode for sector %08x!\n", akiko.cdrom_lba_cur );
+ return;
+ }
+ }
+ }
+ else
+ {
+ if ( !cdrom_read_data( akiko.cdrom, akiko.cdrom_lba_cur, buf, CD_TRACK_RAW_DONTCARE) )
+ {
+ logerror( "AKIKO: Read error trying to read sector %08x!\n", akiko.cdrom_lba_cur );
+ return;
+ }
+
+ if ( subsize )
+ {
+ if ( !cdrom_read_subcode( akiko.cdrom, akiko.cdrom_lba_cur, &buf[datasize] ) )
+ {
+ logerror( "AKIKO: Read error trying to read subcode for sector %08x!\n", akiko.cdrom_lba_cur );
+ return;
+ }
+ }
+ }
+
+#if LOG_AKIKO_CD
+ logerror( "DMA: sector %d - address %08x\n", akiko.cdrom_lba_cur, akiko.cdrom_address[0] + (index*4096) );
+#endif
+
+ for( i = 0; i < 2352; i += 2 )
+ {
+ UINT16 data;
+
+ data = buf[i];
+ data <<= 8;
+ data |= buf[i+1];
+
+ amiga_chip_ram_w( akiko.cdrom_address[0] + (index*4096) + i, data );
+ }
+
+ akiko.cdrom_readmask |= ( 1 << index );
+ akiko.cdrom_readreqmask &= ~( 1 << index );
+ akiko.cdrom_lba_cur++;
+ }
+
+ if ( akiko.cdrom_readreqmask == 0 )
+ akiko_set_cd_status(0x04000000);
+ else
+ timer_adjust( akiko.dma_timer, ATTOTIME_IN_USEC( CD_SECTOR_TIME / akiko.cdrom_speed ), 0, attotime_zero );
+}
+
+static void akiko_start_dma( void )
+{
+ if ( akiko.cdrom_readreqmask == 0 )
+ return;
+
+ if ( akiko.cdrom_lba_start > akiko.cdrom_lba_end )
+ return;
+
+ if ( akiko.cdrom_speed == 0 )
+ return;
+
+ akiko.cdrom_lba_cur = akiko.cdrom_lba_start;
+
+ timer_adjust( akiko.dma_timer, ATTOTIME_IN_USEC( CD_SECTOR_TIME / akiko.cdrom_speed ), 0, attotime_zero );
+}
+
+static void akiko_setup_response( int len, UINT8 *r1 )
+{
+ int resp_addr = akiko.cdrom_address[1];
+ UINT8 resp_csum = 0xff;
+ UINT8 resp_buffer[32];
+ int i;
+
+ memset( resp_buffer, 0, sizeof( resp_buffer ) );
+
+ for( i = 0; i < len; i++ )
+ {
+ resp_buffer[i] = r1[i];
+ resp_csum -= resp_buffer[i];
+ }
+
+ resp_buffer[len++] = resp_csum;
+
+ for( i = 0; i < len; i++ )
+ {
+ program_write_byte( resp_addr + ((akiko.cdrom_cmd_resp + i) & 0xff), resp_buffer[i] );
+ }
+
+ akiko.cdrom_cmd_resp = (akiko.cdrom_cmd_resp+len) & 0xff;
+
+ akiko_set_cd_status( 0x10000000 ); /* new data available */
+}
+
+static TIMER_CALLBACK( akiko_cd_delayed_cmd )
+{
+ UINT8 resp[32];
+ UINT8 cddastatus;
+
+ if ( akiko.cdrom_status[0] & 0x10000000 )
+ return;
+
+ cddastatus = akiko_cdda_getstatus(NULL);
+
+ if ( cddastatus == 0x11 || cddastatus == 0x12 )
+ return;
+
+ memset( resp, 0, sizeof( resp ) );
+ resp[0] = param;
+
+ param &= 0x0f;
+
+ if ( param == 0x05 )
+ {
+#if LOG_AKIKO_CD
+ logerror( "AKIKO: Completing Command %d\n", param );
+#endif
+
+ resp[0] = 0x06;
+
+ if ( akiko.cdrom == NULL || akiko.cdrom_numtracks == 0 )
+ {
+ resp[1] = 0x80;
+ akiko_setup_response( 15, resp );
+ }
+ else
+ {
+ resp[1] = 0x00;
+ memcpy( &resp[2], &akiko.cdrom_toc[13*akiko.cdrom_track_index], 13 );
+
+ akiko.cdrom_track_index = ( akiko.cdrom_track_index + 1 ) % akiko.cdrom_numtracks;
+
+ akiko_setup_response( 15, resp );
+ }
+ }
+}
+
+static void akiko_update_cdrom( void )
+{
+ UINT8 resp[32], cmdbuf[32];
+
+ if ( akiko.cdrom_status[0] & 0x10000000 )
+ return;
+
+ while ( akiko.cdrom_cmd_start != akiko.cdrom_cmd_end )
+ {
+ UINT32 cmd_addr = akiko.cdrom_address[1] + 0x200 + akiko.cdrom_cmd_start;
+ int cmd = program_read_byte( cmd_addr );
+
+ memset( resp, 0, sizeof( resp ) );
+ resp[0] = cmd;
+
+ cmd &= 0x0f;
+
+#if LOG_AKIKO_CD
+ logerror( "CDROM command: %02X\n", cmd );
+#endif
+
+ if ( cmd == 0x02 ) /* pause audio */
+ {
+ resp[1] = 0x00;
+
+ if ( akiko_cdda_getstatus(NULL) == 0x11 )
+ resp[1] = 0x08;
+
+ akiko_cdda_pause( 1 );
+
+ akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+2) & 0xff;
+
+ akiko_setup_response( 2, resp );
+ }
+ else if ( cmd == 0x03 ) /* unpause audio (and check audiocd playing status) */
+ {
+ resp[1] = 0x00;
+
+ if ( akiko_cdda_getstatus(NULL) == 0x11 )
+ resp[1] = 0x08;
+
+ akiko_cdda_pause( 0 );
+
+ akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+2) & 0xff;
+
+ akiko_setup_response( 2, resp );
+ }
+ else if ( cmd == 0x04 ) /* seek/read/play cd multi command */
+ {
+ int i;
+ UINT32 startpos, endpos;
+
+ for( i = 0; i < 13; i++ )
+ {
+ cmdbuf[i] = program_read_byte( cmd_addr );
+ cmd_addr &= 0xffffff00;
+ cmd_addr += ( akiko.cdrom_cmd_start + i + 1 ) & 0xff;
+ }
+
+ akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+13) & 0xff;
+
+ if ( akiko.cdrom == NULL || akiko.cdrom_numtracks == 0 )
+ {
+ resp[1] = 0x80;
+ akiko_setup_response( 2, resp );
+ }
+ else
+ {
+ startpos = lba_from_triplet( &cmdbuf[1] );
+ endpos = lba_from_triplet( &cmdbuf[4] );
+
+ akiko_cdda_stop();
+
+ resp[1] = 0x00;
+
+ if ( cmdbuf[7] == 0x80 )
+ {
+#if LOG_AKIKO_CD
+ logerror( "AKIKO CD: PC:%06x Data read - start lba: %08x - end lba: %08x\n", safe_activecpu_get_pc(), startpos, endpos );
+#endif
+ akiko.cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1;
+ akiko.cdrom_lba_start = startpos;
+ akiko.cdrom_lba_end = endpos;
+
+ resp[1] = 0x02;
+ }
+ else if ( cmdbuf[10] & 0x04 )
+ {
+ logerror( "AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos );
+ akiko_cdda_play( startpos, endpos - startpos );
+ resp[1] = 0x08;
+ }
+ else
+ {
+#if LOG_AKIKO_CD
+ logerror( "AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos );
+#endif
+ akiko.cdrom_track_index = 0;
+
+ for( i = 0; i < cdrom_get_last_track(akiko.cdrom); i++ )
+ {
+ if ( startpos <= cdrom_get_track_start( akiko.cdrom, i ) )
+ {
+ /* reset to 0 */
+ akiko.cdrom_track_index = i + 2;
+ akiko.cdrom_track_index %= akiko.cdrom_numtracks;
+ break;
+ }
+ }
+ }
+
+ akiko_setup_response( 2, resp );
+ }
+ }
+ else if ( cmd == 0x05 ) /* read toc */
+ {
+ akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+3) & 0xff;
+
+ timer_set( ATTOTIME_IN_MSEC(1), resp[0], akiko_cd_delayed_cmd );
+
+ break;
+ }
+ else if ( cmd == 0x06 ) /* read subq */
+ {
+ UINT32 lba;
+
+ resp[1] = 0x00;
+
+ (void)akiko_cdda_getstatus( &lba );
+
+ if ( lba > 0 )
+ {
+ UINT32 disk_pos;
+ UINT32 track_pos;
+ UINT32 track;
+ int addrctrl;
+
+ track = cdrom_get_track(akiko.cdrom, lba);
+ addrctrl = cdrom_get_adr_control(akiko.cdrom, track);
+
+ resp[2] = 0x00;
+ resp[3] = ((addrctrl & 0x0f) << 4) | ((addrctrl & 0xf0) >> 4);
+ resp[4] = dec_2_bcd(track+1);
+ resp[5] = 0; /* index */
+
+ disk_pos = lba_to_msf(lba);
+ track_pos = lba_to_msf(lba - cdrom_get_track_start(akiko.cdrom, track));
+
+ /* track position */
+ resp[6] = (track_pos >> 16) & 0xff;
+ resp[7] = (track_pos >> 8) & 0xff;
+ resp[8] = track_pos & 0xff;
+
+ /* disk position */
+ resp[9] = (disk_pos >> 24) & 0xff;
+ resp[10] = (disk_pos >> 16) & 0xff;
+ resp[11] = (disk_pos >> 8) & 0xff;
+ resp[12] = disk_pos & 0xff;
+ }
+ else
+ {
+ resp[1] = 0x80;
+ }
+
+ akiko_setup_response( 15, resp );
+ }
+ else if ( cmd == 0x07 ) /* check door status */
+ {
+ resp[1] = 0x01;
+
+ akiko.cdrom_cmd_start = (akiko.cdrom_cmd_start+2) & 0xff;
+
+ if ( akiko.cdrom == NULL || akiko.cdrom_numtracks == 0 )
+ resp[1] = 0x80;
+
+ akiko_setup_response( 20, resp );
+ break;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+READ32_HANDLER(amiga_akiko32_r)
+{
+ UINT32 retval;
+
+#if LOG_AKIKO
+ if ( offset < (0x30/4) )
+ {
+ logerror( "Reading AKIKO reg %0x [%s] at PC=%06x\n", offset, get_akiko_reg_name(offset), activecpu_get_pc() );
+ }
+#endif
+
+ switch( offset )
+ {
+ case 0x00/4: /* ID */
+ if ( akiko.cdrom != NULL ) cdda_set_cdrom(0, akiko.cdrom);
+ return 0x0000cafe;
+
+ case 0x04/4: /* CDROM STATUS 1 */
+ return akiko.cdrom_status[0];
+
+ case 0x08/4: /* CDROM STATUS 2 */
+ return akiko.cdrom_status[1];
+
+ case 0x10/4: /* CDROM ADDRESS 1 */
+ return akiko.cdrom_address[0];
+
+ case 0x14/4: /* CDROM ADDRESS 2 */
+ return akiko.cdrom_address[1];
+
+ case 0x18/4: /* CDROM COMMAND 1 */
+ akiko_update_cdrom();
+ retval = akiko.cdrom_cmd_start;
+ retval <<= 8;
+ retval |= akiko.cdrom_cmd_resp;
+ retval <<= 8;
+ return retval;
+
+ case 0x1C/4: /* CDROM COMMAND 2 */
+ akiko_update_cdrom();
+ retval = akiko.cdrom_cmd_end;
+ retval <<= 16;
+ return retval;
+
+ case 0x20/4: /* CDROM DMA SECTOR READ MASK */
+ retval = akiko.cdrom_readmask << 16;
+ return retval;
+
+ case 0x24/4: /* CDROM DMA ENABLE? */
+ retval = akiko.cdrom_dmacontrol;
+ return retval;
+
+ case 0x30/4: /* NVRAM */
+ return akiko_nvram_read();
+
+ case 0x38/4: /* C2P */
+ return akiko_c2p_read();
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+WRITE32_HANDLER(amiga_akiko32_w)
+{
+#if LOG_AKIKO
+ if ( offset < (0x30/4) )
+ {
+ logerror( "Writing AKIKO reg %0x [%s] with %08x at PC=%06x\n", offset, get_akiko_reg_name(offset), data, activecpu_get_pc() );
+ }
+#endif
+
+ switch( offset )
+ {
+ case 0x04/4: /* CDROM STATUS 1 */
+ akiko.cdrom_status[0] = data;
+ break;
+
+ case 0x08/4: /* CDROM STATUS 2 */
+ akiko.cdrom_status[1] = data;
+ akiko.cdrom_status[0] &= data;
+ break;
+
+ case 0x10/4: /* CDROM ADDRESS 1 */
+ akiko.cdrom_address[0] = data;
+ break;
+
+ case 0x14/4: /* CDROM ADDRESS 2 */
+ akiko.cdrom_address[1] = data;
+ break;
+
+ case 0x18/4: /* CDROM COMMAND 1 */
+ if ( ( mem_mask & 0x00ff0000 ) == 0 )
+ akiko.cdrom_cmd_start = ( data >> 16 ) & 0xff;
+
+ if ( ( mem_mask & 0x0000ff00 ) == 0 )
+ akiko.cdrom_cmd_resp = ( data >> 8 ) & 0xff;
+
+ akiko_update_cdrom();
+ break;
+
+ case 0x1C/4: /* CDROM COMMAND 2 */
+ if ( ( mem_mask & 0x00ff0000 ) == 0 )
+ akiko.cdrom_cmd_end = ( data >> 16 ) & 0xff;
+
+ akiko_update_cdrom();
+ break;
+
+ case 0x20/4: /* CDROM DMA SECTOR READ REQUEST WRITE */
+#if LOG_AKIKO_CD
+ logerror( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask );
+#endif
+ if ( ( mem_mask & 0xffff0000 ) == 0 )
+ {
+ akiko.cdrom_readreqmask = (data >> 16);
+ akiko.cdrom_readmask = 0;
+ }
+ break;
+
+ case 0x24/4: /* CDROM DMA ENABLE? */
+#if LOG_AKIKO_CD
+ logerror( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask );
+#endif
+ if ( ( akiko.cdrom_dmacontrol ^ data ) & 0x04000000 )
+ {
+ if ( data & 0x04000000 )
+ akiko_start_dma();
+ }
+ akiko.cdrom_dmacontrol = data;
+ break;
+
+ case 0x30/4:
+ akiko_nvram_write(data);
+ break;
+
+ case 0x38/4:
+ akiko_c2p_write(data);
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/src/mame/machine/daikaiju.c b/src/mame/machine/daikaiju.c
new file mode 100644
index 00000000000..a4f6423a2c1
--- /dev/null
+++ b/src/mame/machine/daikaiju.c
@@ -0,0 +1,351 @@
+/***************************************************************************
+
+Daikaijuu no Gyakushuu protection sim
+
+Tomasz Slanina 20060529
+
+
+Communciation from CPU to MCU is encrypted - every byte
+is xored with data taken from cyclic , 22 bytes long buffer.
+
+MCU commands:
+=============
+
+ 0x19 - unknown
+----------------
+ - no args
+ - no results
+Few writes at the end of level (level summary screen).
+
+
+ 0x1d - watchdog?
+------------------
+ - no args
+ - no results
+
+
+ 0x31 - VRAM address 1
+-----------------------
+ - args = row
+ column
+ - result = 0xd000 + column*2 + row*64
+ Address in text layer.
+
+
+ 0x32 - VRAM address 2
+-----------------------
+ - args = row
+ column
+ - result = 0xc000 + column*2 + row*64
+ Address in BG layer.
+
+
+ 0x36 - Controls 1
+------------------
+ - args = data from input port
+ previous result
+ - result - bits 0-2 = direction ,
+ encoded as:
+ 0
+ 7 1
+ 6 2
+ 5 3
+ 4
+ - result - bit 3 = 0 -> no movement (bits 0-2 = bits 0-2 of previous result
+ 1 -> movement
+ - result - bit 4 = 0/1 -> button A pressed/released
+ - result - bit 5 = previous status of button A
+ - result - bit 6 = 0/1 -> button B pressed/released
+ - result - bit 7 = previous status of button B
+
+ 0x40 - Player message(s) status (not working ?)
+-------------------------------------------------
+ - args = unk (0/9/d/f (stored at $a020))
+ unk (0/1/2 (stored at $a023))
+ unk (0/1/2 (stored at $a024)) (2nd and 3rd args are ident.)
+ - result = 0/1/2/ (same as 2nd/3rd arg)
+Result is discarded due to bug (or patch?) in the code - missing "cp 0"/"or a"/"and a"/etc instruction
+to set CPU flags before conditional jump at addr. 0x256 (previous flags are tested, Z is _always_ set
+(it's result of testing MCU "data ready to send" flag).
+Thic mcu command is used to determine if player message(READY/PLAYER1/PLAYER2) should be
+displayed (game) or not (attract mode). Due to above bug message is always displayed
+(confirmed on real hw).
+
+ 0x44 - Controls 2
+--------------------
+- args = result of command 0x36
+ previous result of command 44
+ step (1 or 2)
+- result - bits 0-3 = direction encoded like in result of command 0x36, but
+ 16 steps instead 8. This command calculates all steps between
+ new direction (1st arg) and old one with given step.
+ Example:
+ w (2,0,1) r (1)
+ w (2,1,1) r (2)
+ w (2,2,1) r (3)
+ w (2,3,1) r (4)
+ w (2,4,1) r (4)
+ ...
+ w (2,4,1) r (4)
+ - bit 4 = 1 -> result bits 0-3 == prev result bits 0-3, otherwise 0
+ - bits 5-7 = unknown , always 0 ?
+
+ 0x60 - MCU ID
+---------------
+ - no args
+ - result = 0x5a
+
+
+***************************************************************************/
+#include "driver.h"
+#include "cpu/z80/z80.h"
+
+#define ID_DAIKAIJU 0x5a
+
+#define MCU_UNKNOWN 0x19
+#define MCU_WATCHDOG 0x1d
+#define MCU_ADDRESS1 0x31
+#define MCU_ADDRESS2 0x32
+#define MCU_CONTROLS1 0x36
+#define MCU_MESSAGE 0x40
+#define MCU_CONTROLS2 0x44
+#define MCU_ID 0x60
+
+#define MCU_ADDRESS1_LENGTH 2
+#define MCU_ADDRESS2_LENGTH 2
+#define MCU_CONTROLS1_LENGTH 2
+#define MCU_MESSAGE_LENGTH 3
+#define MCU_CONTROLS2_LENGTH 3
+#define MCU_ID_LENGTH 0
+
+#define SET_COMMAND(n) daikaiju_command=data; \
+ daikaiju_length=n;\
+ daikaiju_cnt=0;\
+ daikaiju_cntr=0;
+
+
+extern int lsasquad_sound_pending;
+static int daikaiju_xor, daikaiju_command, daikaiju_length, daikaiju_prev, daikaiju_cnt, daikaiju_cntr;
+
+static int daikaiju_buffer[256];
+
+static int xortable[]=
+{
+ 0xF5, 0xD5, 0x6A, 0x26, 0x00, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x16, 0x00, 0xCB, 0x23, 0x19,
+ 0x11, 0x00, 0xC0, 0x19, 0xD1, 0xF1, 0xC9, -1
+};
+
+MACHINE_RESET(daikaiju)
+{
+ daikaiju_xor=-1;
+ daikaiju_command=0;
+ daikaiju_length=0;
+}
+
+WRITE8_HANDLER( daikaiju_mcu_w )
+{
+ if(daikaiju_xor <0)
+ {
+ //reset
+ daikaiju_xor=0;
+ data^=0xc3;
+ }
+ else
+ {
+ data^=xortable[daikaiju_xor];
+ //check for end of table
+ if(xortable[++daikaiju_xor]<0)
+ {
+ daikaiju_xor=0;
+ }
+ }
+ daikaiju_prev=data;
+
+ if(daikaiju_length == 0) //new command
+ {
+ switch(data)
+ {
+ case MCU_UNKNOWN:
+ case MCU_WATCHDOG: break;
+ case MCU_ADDRESS1: SET_COMMAND(MCU_ADDRESS1_LENGTH); break;
+ case MCU_ADDRESS2: SET_COMMAND(MCU_ADDRESS2_LENGTH); break;
+ case MCU_CONTROLS1: SET_COMMAND(MCU_CONTROLS1_LENGTH); break;
+ case MCU_MESSAGE: SET_COMMAND(MCU_MESSAGE_LENGTH); break;
+ case MCU_CONTROLS2: SET_COMMAND(MCU_CONTROLS2_LENGTH); break;
+ case MCU_ID: SET_COMMAND(MCU_ID_LENGTH); break;
+ default:
+ daikaiju_command=data;
+ logerror("Unknown MCU command W %x %x \n",data,activecpu_get_pc());
+ }
+ }
+ else
+ {
+ --daikaiju_length;
+ daikaiju_buffer[daikaiju_cnt++]=data;
+ }
+}
+
+READ8_HANDLER( daikaiju_mcu_r )
+{
+ switch(daikaiju_command)
+ {
+ case MCU_ID:
+ return ID_DAIKAIJU;
+
+ case MCU_CONTROLS1:
+ {
+ int n;
+ switch( (daikaiju_buffer[0]&0xf)^0xf)
+ {
+ case 0x00: n = (daikaiju_buffer[1]&(~8))&0xf; break;
+ case 0x08: n = 0 | 8; break;
+ case 0x0a: n = 1 | 8; break;
+ case 0x02: n = 2 | 8; break;
+ case 0x06: n = 3 | 8; break;
+ case 0x04: n = 4 | 8; break;
+ case 0x05: n = 5 | 8; break;
+ case 0x01: n = 6 | 8; break;
+ case 0x09: n = 7 | 8; break;
+
+ default: n = 0; break;
+ }
+
+ if( !(daikaiju_buffer[0]&0x10) ) //button 1 pressed
+ {
+ if(daikaiju_buffer[1]&0x10) //previous status
+ {
+ n|=0x40; // button 0->1
+ }
+ else
+ {
+ n|=0; //button 1->1
+ }
+ }
+ else
+ {
+ if(daikaiju_buffer[1]&0x10) //previous status
+ {
+ n|=0x40+0x10; // button 0->0
+ }
+ else
+ {
+ n|=0x10; //button 1->0
+ }
+ }
+
+ if( !(daikaiju_buffer[0]&0x20) ) //button 2 pressed
+ {
+ if(daikaiju_buffer[1]&0x20) //previous status
+ {
+ n|=0x80; // button 0->1
+ }
+ else
+ {
+ n|=0; //button 1->1
+ }
+ }
+ else
+ {
+ if(daikaiju_buffer[1]&0x20) //previous status
+ {
+ n|=0x80+0x20; // button 0->0
+ }
+ else
+ {
+ n|=0x20; //button 1->0
+ }
+ }
+ return n;
+ }
+ return 0;
+
+ case MCU_ADDRESS1:
+ {
+ int address=daikaiju_buffer[1]*2+64*daikaiju_buffer[0];
+
+ address&=0x0fff; // ?
+ address+=0xd000;
+
+ if(daikaiju_cntr==0)
+ {
+ daikaiju_cntr++;
+ return address&0xff;
+ }
+ else
+ {
+ return address>>8;
+ }
+ }
+ return 0;
+
+ case MCU_ADDRESS2:
+ {
+ int address=daikaiju_buffer[1]*2+64*daikaiju_buffer[0];
+
+ address&=0x1fff; // ?
+ address+=0xc000;
+
+ if(daikaiju_cntr==0)
+ {
+ daikaiju_cntr++;
+ return address&0xff;
+ }
+ else
+ {
+ return address>>8;
+ }
+ }
+ return 0;
+
+ case MCU_MESSAGE:
+ return daikaiju_buffer[1];
+
+ case MCU_CONTROLS2:
+ {
+ int n;
+ int dest=(daikaiju_buffer[0]&0x7)<<1;
+ int prev=(daikaiju_buffer[1]&0xf);
+
+ if(daikaiju_buffer[2]==2)
+ {
+ prev&=0xfe;
+ }
+ if(prev!=dest)
+ {
+ int diff=(dest-prev);
+
+ if((diff>8 )|| (diff<0 && diff >-8))
+ {
+ n=(prev-daikaiju_buffer[2])&0xf;
+ }
+ else
+ {
+ n=(prev+daikaiju_buffer[2])&0xf;
+ }
+ }
+ else
+ {
+ n=prev;
+ }
+ prev&=0xf;
+ if(prev!=n)
+ {
+ n|=0x10;
+ }
+ return n;
+ }
+ }
+ logerror("Unknown MCU R %x %x %x %x\n",activecpu_get_pc(), daikaiju_command, daikaiju_length, daikaiju_prev);
+ return 0xff;
+}
+
+READ8_HANDLER( daikaiju_mcu_status_r )
+{
+ int res = input_port_3_r(0);
+
+ res^=mame_rand(Machine)&3;
+ res |=((lsasquad_sound_pending & 0x02)^2)<<3; //inverted flag
+ lsasquad_sound_pending &= ~0x02;
+ return res;
+}
+
diff --git a/src/mame/machine/dc.c b/src/mame/machine/dc.c
new file mode 100644
index 00000000000..f71f67c1e6e
--- /dev/null
+++ b/src/mame/machine/dc.c
@@ -0,0 +1,95 @@
+/*
+
+ dc.c - Sega Dreamcast hardware
+
+*/
+
+#include "driver.h"
+#include "dc.h"
+
+READ64_HANDLER( dc_sysctrl_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_sysctrl_w )
+{
+ mame_printf_verbose("SYSCTRL: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
+READ64_HANDLER( dc_maple_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_maple_w )
+{
+ mame_printf_verbose("MAPLE: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
+READ64_HANDLER( dc_gdrom_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_gdrom_w )
+{
+ mame_printf_verbose("GDROM: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
+READ64_HANDLER( dc_g1_ctrl_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_g1_ctrl_w )
+{
+ mame_printf_verbose("G1CTRL: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
+READ64_HANDLER( dc_g2_ctrl_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_g2_ctrl_w )
+{
+ mame_printf_verbose("G2CTRL: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
+READ64_HANDLER( dc_modem_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_modem_w )
+{
+ mame_printf_verbose("MODEM: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
+READ64_HANDLER( dc_rtc_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_rtc_w )
+{
+ mame_printf_verbose("RTC: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
+MACHINE_RESET( dc )
+{
+ /* halt the ARM7 */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ASSERT_LINE);
+}
+
+READ64_HANDLER( dc_aica_reg_r )
+{
+ return 0;
+}
+
+WRITE64_HANDLER( dc_aica_reg_w )
+{
+ mame_printf_verbose("AICA REG: write %llx to %x, mask %llx\n", data, offset, mem_mask);
+}
+
diff --git a/src/mame/machine/dec0.c b/src/mame/machine/dec0.c
new file mode 100644
index 00000000000..41821b576b0
--- /dev/null
+++ b/src/mame/machine/dec0.c
@@ -0,0 +1,623 @@
+/*******************************************************************************
+
+Data East machine functions - Bryan McPhail, mish@tendril.co.uk
+
+* Control reads, protection chip emulations & cycle skipping patches
+
+*******************************************************************************/
+
+#include "driver.h"
+#include "dec0.h"
+#include "cpu/h6280/h6280.h"
+
+static int GAME,i8751_return,slyspy_state;
+
+/******************************************************************************/
+
+READ16_HANDLER( dec0_controls_r )
+{
+ switch (offset<<1)
+ {
+ case 0: /* Player 1 & 2 joystick & buttons */
+ return (readinputport(0) + (readinputport(1) << 8));
+
+ case 2: /* Credits, start buttons */
+ return readinputport(2);
+
+ case 4: /* Byte 4: Dipswitch bank 2, Byte 5: Dipswitch Bank 1 */
+ return (readinputport(3) + (readinputport(4) << 8));
+
+ case 8: /* Intel 8751 mc, Bad Dudes & Heavy Barrel only */
+ //logerror("CPU #0 PC %06x: warning - read unmapped memory address %06x\n",activecpu_get_pc(),0x30c000+offset);
+ return i8751_return;
+ }
+
+ logerror("CPU #0 PC %06x: warning - read unmapped memory address %06x\n",activecpu_get_pc(),0x30c000+offset);
+ return ~0;
+}
+
+/******************************************************************************/
+
+READ16_HANDLER( dec0_rotary_r )
+{
+ switch (offset<<1)
+ {
+ case 0: /* Player 1 rotary */
+ return ~(1 << (readinputport(5) * 12 / 256));
+
+ case 8: /* Player 2 rotary */
+ return ~(1 << (readinputport(6) * 12 / 256));
+
+ default:
+ logerror("Unknown rotary read at 300000 %02x\n",offset);
+ }
+
+ return 0;
+}
+
+/******************************************************************************/
+
+READ16_HANDLER( midres_controls_r )
+{
+ switch (offset<<1)
+ {
+ case 0: /* Player 1 Joystick + start, Player 2 Joystick + start */
+ return (readinputport(0) + (readinputport(1) << 8));
+
+ case 2: /* Dipswitches */
+ return (readinputport(3) + (readinputport(4) << 8));
+
+ case 4: /* Player 1 rotary */
+ return ~(1 << (readinputport(5) * 12 / 256));
+
+ case 6: /* Player 2 rotary */
+ return ~(1 << (readinputport(6) * 12 / 256));
+
+ case 8: /* Credits, start buttons */
+ return readinputport(2);
+
+ case 12:
+ return 0; /* ?? watchdog ?? */
+ }
+
+ logerror("PC %06x unknown control read at %02x\n",activecpu_get_pc(),0x180000+offset);
+ return ~0;
+}
+
+/******************************************************************************/
+
+READ16_HANDLER( slyspy_controls_r )
+{
+ switch (offset<<1)
+ {
+ case 0: /* Dip Switches */
+ return (readinputport(3) + (readinputport(4) << 8));
+
+ case 2: /* Player 1 & Player 2 joysticks & fire buttons */
+ return (readinputport(0) + (readinputport(1) << 8));
+
+ case 4: /* Credits */
+ return readinputport(2);
+ }
+
+ logerror("Unknown control read at 30c000 %d\n",offset);
+ return ~0;
+}
+
+READ16_HANDLER( slyspy_protection_r )
+{
+ /* These values are for Boulderdash, I have no idea what they do in Slyspy */
+ switch (offset<<1) {
+ case 0: return 0;
+ case 2: return 0x13;
+ case 4: return 0;
+ case 6: return 0x2;
+ }
+
+ logerror("%04x, Unknown protection read at 30c000 %d\n",activecpu_get_pc(),offset);
+ return 0;
+}
+
+/*
+ The memory map in Sly Spy can change between 4 states according to the protection!
+
+ Default state (called by Traps 1, 3, 4, 7, C)
+
+ 240000 - 24001f = control (Playfield 2 area)
+ 242000 - 24207f = colscroll
+ 242400 - 2425ff = rowscroll
+ 246000 - 2467ff = data
+
+ 248000 - 24801f = control (Playfield 1 area)
+ 24c000 - 24c07f = colscroll
+ 24c400 - 24c4ff = rowscroll
+ 24e000 - 24e7ff = data
+
+ State 1 (Called by Trap 9) uses this memory map:
+
+ 248000 = pf1 data
+ 24c000 = pf2 data
+
+ State 2 (Called by Trap A) uses this memory map:
+
+ 240000 = pf2 data
+ 242000 = pf1 data
+ 24e000 = pf1 data
+
+ State 3 (Called by Trap B) uses this memory map:
+
+ 240000 = pf1 data
+ 248000 = pf2 data
+
+*/
+
+WRITE16_HANDLER( slyspy_state_w )
+{
+ slyspy_state=0;
+}
+
+READ16_HANDLER( slyspy_state_r )
+{
+ slyspy_state++;
+ slyspy_state=slyspy_state%4;
+ return 0; /* Value doesn't mater */
+}
+
+WRITE16_HANDLER( slyspy_240000_w )
+{
+ switch (slyspy_state) {
+ case 0x3:
+ dec0_pf1_data_w(offset,data,mem_mask);
+ return;
+ case 0x2:
+ dec0_pf2_data_w(offset,data,mem_mask);
+ return;
+ case 0x0:
+ if (offset<0x8) dec0_pf2_control_0_w(offset,data,mem_mask);
+ else if (offset<0x10) dec0_pf2_control_1_w(offset-0x8,data,mem_mask);
+ return;
+ }
+ logerror("Wrote to 240000 %02x at %04x %04x (Trap %02x)\n",offset,activecpu_get_pc(),data,slyspy_state);
+}
+
+WRITE16_HANDLER( slyspy_242000_w )
+{
+ switch (slyspy_state) {
+ case 0x2: /* Trap A */
+ dec0_pf1_data_w(offset,data,mem_mask);
+ return;
+ case 0x0: /* Trap C */
+ if (offset<0x40) COMBINE_DATA(&dec0_pf2_colscroll[offset]);
+ else if (offset<0x300) COMBINE_DATA(&dec0_pf2_rowscroll[offset-0x200]);
+ return;
+ }
+ logerror("Wrote to 242000 %02x at %04x %04x (Trap %02x)\n",offset,activecpu_get_pc(),data,slyspy_state);
+}
+
+WRITE16_HANDLER( slyspy_246000_w )
+{
+ switch (slyspy_state) {
+ case 0x0:
+ dec0_pf2_data_w(offset,data,mem_mask);
+ return;
+ }
+ logerror("Wrote to 246000 %02x at %04x %04x (Trap %02x)\n",offset,activecpu_get_pc(),data,slyspy_state);
+}
+
+WRITE16_HANDLER( slyspy_248000_w )
+{
+ switch (slyspy_state) {
+ case 0x1:
+ dec0_pf1_data_w(offset,data,mem_mask);
+ return;
+ case 0x3:
+ dec0_pf2_data_w(offset,data,mem_mask);
+ return;
+ case 0x0:
+ if (offset<0x8) dec0_pf1_control_0_w(offset,data,mem_mask);
+ else if (offset<0x10) dec0_pf1_control_1_w(offset-0x8,data,mem_mask);
+ return;
+ }
+ logerror("Wrote to 248000 %02x at %04x %04x (Trap %02x)\n",offset,activecpu_get_pc(),data,slyspy_state);
+}
+
+WRITE16_HANDLER( slyspy_24c000_w )
+{
+ switch (slyspy_state) {
+ case 0x1: /* Trap 9 */
+ dec0_pf2_data_w(offset,data,mem_mask);
+ return;
+ case 0x0: /* Trap C */
+ if (offset<0x40) COMBINE_DATA(&dec0_pf1_colscroll[offset]);
+ else if (offset<0x300) COMBINE_DATA(&dec0_pf1_rowscroll[offset-0x200]);
+ return;
+ }
+ logerror("Wrote to 24c000 %02x at %04x %04x (Trap %02x)\n",offset,activecpu_get_pc(),data,slyspy_state);
+}
+
+WRITE16_HANDLER( slyspy_24e000_w )
+{
+ switch (slyspy_state) {
+ case 0x2:
+ case 0x0:
+ dec0_pf1_data_w(offset,data,mem_mask);
+ return;
+ }
+ logerror("Wrote to 24e000 %02x at %04x %04x (Trap %02x)\n",offset,activecpu_get_pc(),data,slyspy_state);
+}
+
+/******************************************************************************/
+
+static int share[0xff];
+static int hippodrm_msb,hippodrm_lsb;
+
+READ8_HANDLER( hippodrm_prot_r )
+{
+//logerror("6280 PC %06x - Read %06x\n",cpu_getpc(),offset+0x1d0000);
+ if (hippodrm_lsb==0x45) return 0x4e;
+ if (hippodrm_lsb==0x92) return 0x15;
+ return 0;
+}
+
+WRITE8_HANDLER( hippodrm_prot_w )
+{
+ switch (offset) {
+ case 4: hippodrm_msb=data; break;
+ case 5: hippodrm_lsb=data; break;
+ }
+//logerror("6280 PC %06x - Wrote %06x to %04x\n",cpu_getpc(),data,offset+0x1d0000);
+}
+
+READ8_HANDLER( hippodrm_shared_r )
+{
+ return share[offset];
+}
+
+WRITE8_HANDLER( hippodrm_shared_w )
+{
+ share[offset]=data;
+}
+
+static READ16_HANDLER( hippodrm_68000_share_r )
+{
+ if (offset==0) cpu_yield(); /* A wee helper */
+ return share[offset]&0xff;
+}
+
+static WRITE16_HANDLER( hippodrm_68000_share_w )
+{
+ share[offset]=data&0xff;
+}
+
+/******************************************************************************/
+
+static void hbarrel_i8751_write(int data)
+{
+ static int level,state;
+
+ static const int title[]={ 1, 2, 5, 6, 9,10,13,14,17,18,21,22,25,26,29,30,33,34,37,38,41,42,0,
+ 3, 4, 7, 8,11,12,15,16,19,20,23,24,27,28,31,32,35,36,39,40,43,44,0,
+ 45,46,49,50,53,54,57,58,61,62,65,66,69,70,73,74,77,78,81,82,0,
+ 47,48,51,52,55,56,59,60,63,64,67,68,71,72,75,76,79,80,83,84,0,
+ 85,86,89,90,93,94,97,98,101,102,105,106,109,110,113,114,117,118,121,122,125,126,0,
+ 87,88,91,92,95,96,99,100,103,104,107,108,111,112,115,116,119,120,123,124,127,128,0,
+ 129,130,133,134,137,138,141,142,145,146,149,150,153,154,157,158,161,162,165,166,169,170,173,174,0,
+ 131,132,135,136,139,140,143,144,147,148,151,152,155,156,159,160,163,164,167,168,171,172,175,176,0,
+ 0x10b1,0x10b2,0,0x10b3,0x10b4,-1
+ };
+
+ /* This table is from the USA version - others could be different.. */
+ static const int weapons_table[][0x20]={
+ { 0x558,0x520,0x5c0,0x600,0x520,0x540,0x560,0x5c0,0x688,0x688,0x7a8,0x850,0x880,0x880,0x990,0x9b0,0x9b0,0x9e0,0xffff }, /* Level 1 */
+ { 0x330,0x370,0x3d8,0x580,0x5b0,0x640,0x6a0,0x8e0,0x8e0,0x940,0x9f0,0xa20,0xa50,0xa80,0xffff }, /* Level 2 */
+ { 0xb20,0xbd0,0xb20,0xb20,0xbd8,0xb50,0xbd8,0xb20,0xbe0,0xb40,0xb80,0xa18,0xa08,0xa08,0x980,0x8e0,0x780,0x790,0x650,0x600,0x5d0,0x5a0,0x570,0x590,0x5e0,0xffff }, /* Level 3 */
+ { 0x530,0x5d0,0x5e0,0x5c8,0x528,0x520,0x5d8,0x5e0,0x5d8,0x540,0x570,0x5a0,0x658,0x698,0x710,0x7b8,0x8e0,0x8e0,0x8d8,0x818,0x8e8,0x820,0x8e0,0x848,0x848,0xffff }, /* Level 4 */
+ { 0x230,0x280,0x700,0x790,0x790,0x7e8,0x7e8,0x8d0,0x920,0x950,0xad0,0xb90,0xb50,0xb10,0xbe0,0xbe0,0xffff }, /* Level 5 */
+ { 0xd20,0xde0,0xd20,0xde0,0xd80,0xd80,0xd90,0xdd0,0xdb0,0xb20,0xa40,0x9e0,0x960,0x8a0,0x870,0x840,0x7e0,0x7b0,0x780,0xffff }, /* Level 6 */
+ { 0x730,0x7e0,0x720,0x7e0,0x740,0x7c0,0x730,0x7d0,0x740,0x7c0,0x730,0x7d0,0x720,0x7e0,0x720,0x7e0,0x720,0x7e0,0x720,0x7e0,0x730,0x7d0,0xffff } /* Level 7 */
+ };
+
+ switch (data>>8) {
+ case 0x2: /* Selects level */
+ i8751_return=level;
+ break;
+ case 0x3: /* Increment level counter */
+ level++;
+ i8751_return=0x301;
+ break;
+ case 0x5: /* Set level 0 */
+ i8751_return=0xb3b;
+ level=0;
+ break;
+ case 0x06: /* Controls appearance & placement of special weapons */
+ i8751_return=weapons_table[level][data&0x1f];
+ //logerror("CPU #0 PC %06x: warning - write %02x to i8751, returning %04x\n",activecpu_get_pc(),data,i8751_return);
+ break;
+ case 0xb: /* Initialise the variables? */
+ i8751_return=0;
+ break;
+ default:
+ i8751_return=0;
+ }
+
+ /* Protection */
+ if (data==7) i8751_return=0xc000; /* Stack pointer */
+ if (data==0x175) i8751_return=0x68b; /* ID check - USA version */
+ if (data==0x174) i8751_return=0x68c; /* ID check - World version */
+
+ /* All commands in range 4xx are related to title screen.. */
+ if (data==0x4ff) state=0;
+ if (data>0x3ff && data<0x4ff) {
+ state++;
+
+ if (title[state-1]==0) i8751_return=0xfffe;
+ else if (title[state-1]==-1) i8751_return=0xffff;
+ else if (title[state-1]>0x1000) i8751_return=(title[state-1]&0xfff)+128+15;
+ else i8751_return=title[state-1]+128+15+0x2000;
+
+ /* We have to use a state as the microcontroller remembers previous commands */
+ }
+
+//logerror("CPU #0 PC %06x: warning - write %02x to i8751\n",activecpu_get_pc(),data);
+}
+
+static void baddudes_i8751_write(int data)
+{
+ i8751_return=0;
+
+ switch (data&0xffff) {
+ case 0x714: i8751_return=0x700; break;
+ case 0x73b: i8751_return=0x701; break;
+ case 0x72c: i8751_return=0x702; break;
+ case 0x73f: i8751_return=0x703; break;
+ case 0x755: i8751_return=0x704; break;
+ case 0x722: i8751_return=0x705; break;
+ case 0x72b: i8751_return=0x706; break;
+ case 0x724: i8751_return=0x707; break;
+ case 0x728: i8751_return=0x708; break;
+ case 0x735: i8751_return=0x709; break;
+ case 0x71d: i8751_return=0x70a; break;
+ case 0x721: i8751_return=0x70b; break;
+ case 0x73e: i8751_return=0x70c; break;
+ case 0x761: i8751_return=0x70d; break;
+ case 0x753: i8751_return=0x70e; break;
+ case 0x75b: i8751_return=0x70f; break;
+ }
+
+ if (!i8751_return) logerror("%04x: warning - write unknown command %02x to 8571\n",activecpu_get_pc(),data);
+}
+
+static void birdtry_i8751_write(int data)
+{
+ static int pwr,
+ hgt;
+
+ i8751_return=0;
+
+ switch(data&0xffff) {
+ /*"Sprite control"*/
+ case 0x22a: i8751_return = 0x200; break;
+
+ /* Gives an O.B. otherwise (it must be > 0xb0 )*/
+ case 0x3c7: i8751_return = 0x7ff; break;
+
+ /*Enables shot checks*/
+ case 0x33c: i8751_return = 0x200; break;
+
+ /*Used on the title screen only(???)*/
+ case 0x31e: i8751_return = 0x200; break;
+
+/* 0x100-0x10d values are for club power meters(1W=0x100<<-->>PT=0x10d). *
+ * Returned value to i8751 doesn't matter,but send the result to 0x481. *
+ * Lower the value,stronger is the power. */
+ case 0x100: pwr = 0x30; break; /*1W*/
+ case 0x101: pwr = 0x34; break; /*3W*/
+ case 0x102: pwr = 0x38; break; /*4W*/
+ case 0x103: pwr = 0x3c; break; /*1I*/
+ case 0x104: pwr = 0x40; break; /*3I*/
+ case 0x105: pwr = 0x44; break; /*4I*/
+ case 0x106: pwr = 0x48; break; /*5I*/
+ case 0x107: pwr = 0x4c; break; /*6I*/
+ case 0x108: pwr = 0x50; break; /*7I*/
+ case 0x109: pwr = 0x54; break; /*8I*/
+ case 0x10a: pwr = 0x58; break; /*9I*/
+ case 0x10b: pwr = 0x5c; break; /*PW*/
+ case 0x10c: pwr = 0x60; break; /*SW*/
+ case 0x10d: pwr = 0x80; break; /*PT*/
+ case 0x481: i8751_return = pwr; break; /*Power meter*/
+
+/* 0x200-0x20f values are for shot height(STRONG=0x200<<-->>WEAK=0x20f). *
+ * Returned value to i8751 doesn't matter,but send the result to 0x534. *
+ * Higher the value,stronger is the height. */
+ case 0x200: hgt = 0x5c0; break; /*H*/
+ case 0x201: hgt = 0x580; break; /*|*/
+ case 0x202: hgt = 0x540; break; /*|*/
+ case 0x203: hgt = 0x500; break; /*|*/
+ case 0x204: hgt = 0x4c0; break; /*|*/
+ case 0x205: hgt = 0x480; break; /*|*/
+ case 0x206: hgt = 0x440; break; /*|*/
+ case 0x207: hgt = 0x400; break; /*M*/
+ case 0x208: hgt = 0x3c0; break; /*|*/
+ case 0x209: hgt = 0x380; break; /*|*/
+ case 0x20a: hgt = 0x340; break; /*|*/
+ case 0x20b: hgt = 0x300; break; /*|*/
+ case 0x20c: hgt = 0x2c0; break; /*|*/
+ case 0x20d: hgt = 0x280; break; /*|*/
+ case 0x20e: hgt = 0x240; break; /*|*/
+ case 0x20f: hgt = 0x200; break; /*L*/
+ case 0x534: i8751_return = hgt; break; /*Shot height*/
+
+ /*At the ending screen(???)*/
+ //case 0x3b4: i8751_return = 0; break;
+
+ /*These are activated after a shot (???)*/
+ case 0x6ca: i8751_return = 0xff; break;
+ case 0x7ff: i8751_return = 0x200; break;
+ default: logerror("%04x: warning - write unknown command %02x to 8571\n",activecpu_get_pc(),data);
+ }
+}
+
+#if 0
+static emu_timer *i8751_timer;
+
+static TIMER_CALLBACK( i8751_callback )
+{
+ /* Signal main cpu microcontroller task is complete */
+ cpunum_set_input_line(0,5,HOLD_LINE);
+ i8751_timer=NULL;
+
+ logerror("i8751: Timer called!!!\n");
+}
+#endif
+
+void dec0_i8751_write(int data)
+{
+ /* Writes to this address cause an IRQ to the i8751 microcontroller */
+ if (GAME==1) hbarrel_i8751_write(data);
+ if (GAME==2) baddudes_i8751_write(data);
+ if (GAME==3) birdtry_i8751_write(data);
+
+ cpunum_set_input_line(0,5,HOLD_LINE);
+
+ /* Simulate the processing time of the i8751, time value is guessed
+ if (i8751_timer)
+ logerror("i8751: Missed a timer!!!\n");
+ else
+ i8751_timer = timer_call_after_resynch(0, i8751_callback);*/
+
+/* There is a timing problem in Heavy Barrel if the processing time is not
+simulated - if the interrupt is triggered straight away then HB will reset
+at the end of level one, the processing time needs to be at least the cycles
+of a TST.W + BMI.S (ie, not very much at all).
+
+See the code about 0xb60 (USA version)
+
+*/
+
+logerror("CPU #0 PC %06x: warning - write %02x to i8751\n",activecpu_get_pc(),data);
+
+}
+
+void dec0_i8751_reset(void)
+{
+ i8751_return=0;
+}
+
+/******************************************************************************/
+
+static WRITE16_HANDLER( sprite_mirror_w )
+{
+ COMBINE_DATA(&spriteram16[offset]);
+}
+
+/******************************************************************************/
+
+static READ16_HANDLER( robocop_68000_share_r )
+{
+//logerror("%08x: Share read %04x\n",activecpu_get_pc(),offset);
+
+ return robocop_shared_ram[offset];
+}
+
+static WRITE16_HANDLER( robocop_68000_share_w )
+{
+// logerror("%08x: Share write %04x %04x\n",activecpu_get_pc(),offset,data);
+
+ robocop_shared_ram[offset]=data&0xff;
+
+ if (offset==0x7ff) /* A control address - not standard ram */
+ cpunum_set_input_line(2,0,HOLD_LINE);
+}
+
+/******************************************************************************/
+
+static void h6280_decrypt(int memory_area)
+{
+ int i;
+ UINT8 *RAM = memory_region(memory_area);
+
+ /* Read each byte, decrypt it */
+ for (i=0x00000; i<0x10000; i++)
+ RAM[i]=(RAM[i] & 0x7e) | ((RAM[i] & 0x1) << 7) | ((RAM[i] & 0x80) >> 7);
+}
+
+DRIVER_INIT( hippodrm )
+{
+ UINT8 *RAM = memory_region(REGION_CPU3);
+
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x180000, 0x180fff, 0, 0, hippodrm_68000_share_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x180000, 0x180fff, 0, 0, hippodrm_68000_share_w);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0xffc800, 0xffcfff, 0, 0, sprite_mirror_w);
+
+ h6280_decrypt(REGION_CPU3);
+
+ /* The protection cpu has additional memory mapped protection! */
+ RAM[0x189]=0x60; /* RTS prot area */
+ RAM[0x1af]=0x60; /* RTS prot area */
+ RAM[0x1db]=0x60; /* RTS prot area */
+ RAM[0x21a]=0x60; /* RTS prot area */
+}
+
+DRIVER_INIT( slyspy )
+{
+ UINT8 *RAM = memory_region(REGION_CPU2);
+
+ h6280_decrypt(REGION_CPU2);
+
+ /* Slyspy sound cpu has some protection */
+ RAM[0xf2d]=0xea;
+ RAM[0xf2e]=0xea;
+}
+
+DRIVER_INIT( robocop )
+{
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x180000, 0x180fff, 0, 0, robocop_68000_share_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x180000, 0x180fff, 0, 0, robocop_68000_share_w);
+}
+
+DRIVER_INIT( baddudes )
+{
+ GAME=2;
+}
+
+DRIVER_INIT( hbarrel )
+{
+ GAME=1;
+{ /* Remove this patch once processing time of i8751 is simulated */
+UINT16 *rom = (UINT16 *)memory_region(REGION_CPU1);
+rom[0xb68/2] = 0x8008;
+}
+}
+
+DRIVER_INIT( hbarrelw )
+{
+ GAME=1;
+{ /* Remove this patch once processing time of i8751 is simulated */
+UINT16 *rom = (UINT16 *)memory_region(REGION_CPU1);
+rom[0xb3e/2] = 0x8008;
+}
+}
+
+DRIVER_INIT( birdtry )
+{
+ UINT8 *src, tmp;
+ int i, j, k;
+
+ GAME=3;
+
+ src = memory_region(REGION_GFX4);
+
+ /* some parts of the graphic have bytes swapped */
+ for (k = 0;k < 0x70000;k += 0x20000)
+ {
+ for (i = 0x2000;i < 0x10000;i += 32)
+ {
+ for (j = 0;j < 16;j++)
+ {
+ tmp = src[k+i+j+16];
+ src[k+i+j+16] = src[k+i+j];
+ src[k+i+j] = tmp;
+ }
+ }
+ }
+}
diff --git a/src/mame/machine/deco102.c b/src/mame/machine/deco102.c
new file mode 100644
index 00000000000..ede2d8dd861
--- /dev/null
+++ b/src/mame/machine/deco102.c
@@ -0,0 +1,93 @@
+/*
+
+ Data East Custom Chip 102 decryption
+ (encrypted 68000)
+
+ by Nicola Salmoria
+
+*/
+
+#include "driver.h"
+#include "cpu/m68000/m68000.h"
+
+extern void deco102_decrypt(int region, int address_xor, int data_select_xor, int opcode_select_xor);
+
+static UINT16 decrypt(UINT16 data, int address, int select_xor)
+{
+ static UINT16 xors[16] =
+ {
+ 0xb52c,0x2458,0x139a,0xc998,0xce8e,0x5144,0x0429,0xaad4,0xa331,0x3645,0x69a3,0xac64,0x1a53,0x5083,0x4dea,0xd237
+ };
+ static UINT8 bitswaps[16][16] =
+ {
+ { 12,8,13,11,14,10,15,9, 3,2,1,0,4,5,6,7 }, { 10,11,14,12,15,13,8,9, 6,7,5,3,0,4,2,1 },
+ { 14,13,15,9,8,12,11,10, 7,4,1,5,6,0,3,2 }, { 15,14,8,9,10,11,13,12, 1,2,7,3,4,6,0,5 },
+ { 10,9,13,14,15,8,12,11, 5,2,1,0,3,4,7,6 }, { 8,9,15,14,10,11,13,12, 0,6,5,4,1,2,3,7 },
+ { 14,8,15,9,10,11,13,12, 4,5,3,0,2,7,6,1 }, { 13,11,12,10,15,9,14,8, 6,0,7,5,1,4,3,2 },
+ { 12,11,13,10,9,8,14,15, 0,2,4,6,7,5,3,1 }, { 15,13,9,8,10,11,12,14, 2,1,0,7,6,5,4,3 },
+ { 13,8,9,10,11,12,15,14, 6,0,1,2,3,7,4,5 }, { 12,11,10,8,9,13,14,15, 6,5,4,0,7,1,2,3 },
+ { 12,15,8,13,9,11,14,10, 6,5,4,3,2,1,0,7 }, { 11,12,13,14,15,8,9,10, 4,5,7,1,6,3,2,0 },
+ { 13,8,12,14,11,15,10,9, 7,6,5,4,3,2,1,0 }, { 15,14,13,12,11,10,9,8, 0,6,7,4,3,2,1,5 }
+ };
+ int j, xor;
+ UINT8 *bs;
+
+ // calculate bitswap to use
+ j = ((address ^ select_xor) & 0xf0) >> 4;
+ if (address & 0x20000) j ^= 4;
+ bs = bitswaps[j];
+
+ // calculate xor to use
+ j = (address ^ select_xor) & 0x0f;
+ if (address & 0x40000) j ^= 2; // boogwing
+ xor = xors[j];
+
+ // decrypt
+ return xor ^ BITSWAP16(data,
+ bs[0],bs[1],bs[2],bs[3],bs[4],bs[5],bs[6],bs[7],
+ bs[8],bs[9],bs[10],bs[11],bs[12],bs[13],bs[14],bs[15]);
+}
+
+void deco102_decrypt(int region, int address_xor, int data_select_xor, int opcode_select_xor)
+{
+ int i;
+ UINT16 *rom = (UINT16 *)memory_region(region);
+ int size = memory_region_length(region);
+ UINT16 *opcodes = auto_malloc(size);
+ UINT16 *buf = malloc_or_die(size);
+
+ memcpy(buf,rom,size);
+
+ memory_set_decrypted_region(0, 0, size - 1, opcodes);
+ m68k_set_encrypted_opcode_range(0,0,size);
+
+ for (i = 0;i < size/2;i++)
+ {
+ int src;
+
+ // calculate address of encrypted word in ROM
+ src = i & 0xf0000;
+ if (i & 0x0001) src ^= 0xbe0b;
+ if (i & 0x0002) src ^= 0x5699;
+ if (i & 0x0004) src ^= 0x1322;
+ if (i & 0x0008) src ^= 0x0004;
+ if (i & 0x0010) src ^= 0x08a0;
+ if (i & 0x0020) src ^= 0x0089;
+ if (i & 0x0040) src ^= 0x0408;
+ if (i & 0x0080) src ^= 0x1212;
+ if (i & 0x0100) src ^= 0x08e0;
+ if (i & 0x0200) src ^= 0x5499;
+ if (i & 0x0400) src ^= 0x9a8b;
+ if (i & 0x0800) src ^= 0x1222;
+ if (i & 0x1000) src ^= 0x1200;
+ if (i & 0x2000) src ^= 0x0008;
+ if (i & 0x4000) src ^= 0x1210;
+ if (i & 0x8000) src ^= 0x00e0;
+ src ^= address_xor;
+
+ rom[i] = decrypt(buf[src], i, data_select_xor);
+ opcodes[i] = decrypt(buf[src], i, opcode_select_xor);
+ }
+
+ free(buf);
+}
diff --git a/src/mame/machine/deco156.c b/src/mame/machine/deco156.c
new file mode 100644
index 00000000000..5aedf0e002e
--- /dev/null
+++ b/src/mame/machine/deco156.c
@@ -0,0 +1,133 @@
+/* Deco 156 analysis
+
+ Data East chip 156 is an encrypted ARM processor.
+
+ The 156 Chip is used on the following games:
+
+ deco_mlc.c
+
+ Stadium Hero 96 (stadhr96, stadh96a)
+ Skull Fang (skullfng)
+ Dunk Dream '95 / Hoops '96 (ddream95, hoops96)
+
+ deco32.c
+
+ Night Slashers (nslasher, nslashej)
+
+ simpl156
+
+ Charlie Ninja (charlien)
+ Magical Drop / Magical Drop Plus / Chain Reaction (magdrop, magdropp, chainrec)
+ Joe & Mac Returns (joemacr, joemacra)
+ Party Time / Ganbare! Gonta!! 2 (prtytime, gangonta)
+
+ deco156.c
+
+ Osman (osman)
+ Heavy Smash (hvysmsh)
+ World Cup Volly '95 (wcvol95)
+ Backfire!! (backfire, backfira)
+
+*/
+
+#include "driver.h"
+
+
+static void decrypt(UINT32 *src, UINT32 *dst, int length)
+{
+ int a;
+
+ for (a = 0; a < length/4; a++)
+ {
+ int addr, dword;
+
+ addr = (a & 0xff0000) | 0x92c6;
+
+ if (a & 0x0001) addr ^= 0xce4a;
+ if (a & 0x0002) addr ^= 0x4db2;
+ if (a & 0x0004) addr ^= 0xef60;
+ if (a & 0x0008) addr ^= 0x5737;
+ if (a & 0x0010) addr ^= 0x13dc;
+ if (a & 0x0020) addr ^= 0x4bd9;
+ if (a & 0x0040) addr ^= 0xa209;
+ if (a & 0x0080) addr ^= 0xd996;
+ if (a & 0x0100) addr ^= 0xa700;
+ if (a & 0x0200) addr ^= 0xeca0;
+ if (a & 0x0400) addr ^= 0x7529;
+ if (a & 0x0800) addr ^= 0x3100;
+ if (a & 0x1000) addr ^= 0x33b4;
+ if (a & 0x2000) addr ^= 0x6161;
+ if (a & 0x4000) addr ^= 0x1eef;
+ if (a & 0x8000) addr ^= 0xf5a5;
+
+ dword = src[addr];
+
+ // note that each of the following lines affects exactly two bits
+
+ if (a & 0x00004) dword ^= 0x04400000;
+ if (a & 0x00008) dword ^= 0x40000004;
+ if (a & 0x00010) dword ^= 0x00048000;
+ if (a & 0x00020) dword ^= 0x00000280;
+ if (a & 0x00040) dword ^= 0x00200040;
+ if (a & 0x00080) dword ^= 0x09000000;
+ if (a & 0x00100) dword ^= 0x00001100;
+ if (a & 0x00200) dword ^= 0x20002000;
+ if (a & 0x00400) dword ^= 0x00000022;
+ if (a & 0x00800) dword ^= 0x000a0000;
+ if (a & 0x01000) dword ^= 0x10004000;
+ if (a & 0x02000) dword ^= 0x00010400;
+ if (a & 0x04000) dword ^= 0x80000010;
+ if (a & 0x08000) dword ^= 0x00000009;
+ if (a & 0x10000) dword ^= 0x02100000;
+ if (a & 0x20000) dword ^= 0x00800800;
+
+ switch (a & 3)
+ {
+ case 0:
+ dword = BITSWAP32( dword ^ 0xec63197a,
+ 1, 4, 7, 28, 22, 18, 20, 9,
+ 16, 10, 30, 2, 31, 24, 19, 29,
+ 6, 21, 23, 11, 12, 13, 5, 0,
+ 8, 26, 27, 15, 14, 17, 25, 3 );
+ break;
+
+ case 1:
+ dword = BITSWAP32( dword ^ 0x58a5a55f,
+ 14, 23, 28, 29, 6, 24, 10, 1,
+ 5, 16, 7, 2, 30, 8, 18, 3,
+ 31, 22, 25, 20, 17, 0, 19, 27,
+ 9, 12, 21, 15, 26, 13, 4, 11 );
+ break;
+
+ case 2:
+ dword = BITSWAP32( dword ^ 0xe3a65f16,
+ 19, 30, 21, 4, 2, 18, 15, 1,
+ 12, 25, 8, 0, 24, 20, 17, 23,
+ 22, 26, 28, 16, 9, 27, 6, 11,
+ 31, 10, 3, 13, 14, 7, 29, 5 );
+ break;
+
+ case 3:
+ dword = BITSWAP32( dword ^ 0x28d93783,
+ 30, 6, 15, 0, 31, 18, 26, 22,
+ 14, 23, 19, 17, 10, 8, 11, 20,
+ 1, 28, 2, 4, 9, 24, 25, 27,
+ 7, 21, 13, 29, 5, 3, 16, 12 );
+ break;
+ }
+
+ dst[a] = dword;
+ }
+}
+
+
+void decrypt156(void)
+{
+ UINT32 *rom = (UINT32 *)memory_region(REGION_CPU1);
+ int length = memory_region_length(REGION_CPU1);
+ UINT32 *buf = malloc_or_die(length);
+
+ memcpy(buf, rom, length);
+ decrypt(buf, rom, length);
+ free(buf);
+}
diff --git a/src/mame/machine/decocass.c b/src/mame/machine/decocass.c
new file mode 100644
index 00000000000..4af788d0b08
--- /dev/null
+++ b/src/mame/machine/decocass.c
@@ -0,0 +1,2159 @@
+/***********************************************************************
+
+ DECO Cassette System machine
+
+ ***********************************************************************/
+
+#include "driver.h"
+#include "cpu/m6502/m6502.h"
+#include "cpu/i8x41/i8x41.h"
+#include "machine/decocass.h"
+
+/* tape direction, speed and timing (used also in video/decocass.c) */
+INT32 tape_dir;
+INT32 tape_speed;
+attotime tape_time0;
+emu_timer *tape_timer;
+
+static INT32 firsttime = 1;
+static INT32 tape_present;
+static INT32 tape_blocks;
+static INT32 tape_length;
+static INT32 tape_bot_eot;
+static UINT8 crc16_lsb;
+static UINT8 crc16_msb;
+
+/* pre-calculated crc16 of the tape blocks */
+static UINT8 tape_crc16_lsb[256];
+static UINT8 tape_crc16_msb[256];
+
+static read8_handler decocass_dongle_r;
+static write8_handler decocass_dongle_w;
+
+static UINT8 decocass_reset;
+static UINT8 i8041_p1;
+static UINT8 i8041_p2;
+
+/* dongle type #1: jumpers C and D assignments */
+#define MAKE_MAP(m0,m1,m2,m3,m4,m5,m6,m7) \
+ ((UINT32)(m0)) | \
+ ((UINT32)(m1) << 3) | \
+ ((UINT32)(m2) << 6) | \
+ ((UINT32)(m3) << 9) | \
+ ((UINT32)(m4) << 12) | \
+ ((UINT32)(m5) << 15) | \
+ ((UINT32)(m6) << 18) | \
+ ((UINT32)(m7) << 21)
+
+#define MAP0(m) ((m)&7)
+#define MAP1(m) (((m)>>3)&7)
+#define MAP2(m) (((m)>>6)&7)
+#define MAP3(m) (((m)>>9)&7)
+#define MAP4(m) (((m)>>12)&7)
+#define MAP5(m) (((m)>>15)&7)
+#define MAP6(m) (((m)>>18)&7)
+#define MAP7(m) (((m)>>21)&7)
+
+static UINT32 type1_inmap;
+static UINT32 type1_outmap;
+
+static INT32 de0091_enable; /* DE-0091xx daughter board enable */
+
+/* dongle type #2: status of the latches */
+static INT32 type2_d2_latch; /* latched 8041-STATUS D2 value */
+static INT32 type2_xx_latch; /* latched value (D7-4 == 0xc0) ? 1 : 0 */
+static INT32 type2_promaddr; /* latched PROM address A0-A7 */
+
+/* dongle type #3: status and patches */
+static INT32 type3_ctrs; /* 12 bit counter stage */
+static INT32 type3_d0_latch; /* latched 8041-D0 value */
+static INT32 type3_pal_19; /* latched 1 for PAL input pin-19 */
+static INT32 type3_swap;
+enum {
+ TYPE3_SWAP_01,
+ TYPE3_SWAP_12,
+ TYPE3_SWAP_13,
+ TYPE3_SWAP_24,
+ TYPE3_SWAP_25,
+ TYPE3_SWAP_34_0,
+ TYPE3_SWAP_34_7,
+ TYPE3_SWAP_23_56,
+ TYPE3_SWAP_56,
+ TYPE3_SWAP_67
+};
+
+/* dongle type #4: status */
+static INT32 type4_ctrs; /* latched PROM address (E5x0 LSB, E5x1 MSB) */
+static INT32 type4_latch; /* latched enable PROM (1100xxxx written to E5x1) */
+
+/* dongle type #5: status */
+static INT32 type5_latch; /* latched enable PROM (1100xxxx written to E5x1) */
+
+/* four inputs from the quadrature decoder (H1, V1, H2, V2) */
+static UINT8 decocass_quadrature_decoder[4];
+
+/* sound latches, ACK status bits and NMI timer */
+static UINT8 decocass_sound_ack;
+static emu_timer *decocass_sound_timer;
+
+WRITE8_HANDLER( decocass_coin_counter_w )
+{
+}
+
+WRITE8_HANDLER( decocass_sound_command_w )
+{
+ LOG(2,("CPU #%d sound command -> $%02x\n", cpu_getactivecpu(), data));
+ soundlatch_w(0,data);
+ decocass_sound_ack |= 0x80;
+ /* remove snd cpu data ack bit. i don't see it in the schems, but... */
+ decocass_sound_ack &= ~0x40;
+ cpunum_set_input_line(1, M6502_IRQ_LINE, ASSERT_LINE);
+}
+
+READ8_HANDLER( decocass_sound_data_r )
+{
+ UINT8 data = soundlatch2_r(0);
+ LOG(2,("CPU #%d sound data <- $%02x\n", cpu_getactivecpu(), data));
+ return data;
+}
+
+READ8_HANDLER( decocass_sound_ack_r )
+{
+ UINT8 data = decocass_sound_ack; /* D6+D7 */
+ LOG(4,("CPU #%d sound ack <- $%02x\n", cpu_getactivecpu(), data));
+ return data;
+}
+
+WRITE8_HANDLER( decocass_sound_data_w )
+{
+ LOG(2,("CPU #%d sound data -> $%02x\n", cpu_getactivecpu(), data));
+ soundlatch2_w(0, data);
+ decocass_sound_ack |= 0x40;
+}
+
+READ8_HANDLER( decocass_sound_command_r )
+{
+ UINT8 data = soundlatch_r(0);
+ LOG(4,("CPU #%d sound command <- $%02x\n", cpu_getactivecpu(), data));
+ cpunum_set_input_line(1, M6502_IRQ_LINE, CLEAR_LINE);
+ decocass_sound_ack &= ~0x80;
+ return data;
+}
+
+static TIMER_CALLBACK( decocass_sound_nmi_pulse )
+{
+ cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+WRITE8_HANDLER( decocass_sound_nmi_enable_w )
+{
+ LOG(2,("CPU #%d sound NMI enb -> $%02x\n", cpu_getactivecpu(), data));
+ timer_adjust(decocass_sound_timer, ATTOTIME_IN_HZ(256 * 57 / 8 / 2), 0, ATTOTIME_IN_HZ(256 * 57 / 8 / 2));
+}
+
+READ8_HANDLER( decocass_sound_nmi_enable_r )
+{
+ UINT8 data = 0xff;
+ LOG(2,("CPU #%d sound NMI enb <- $%02x\n", cpu_getactivecpu(), data));
+ timer_adjust(decocass_sound_timer, ATTOTIME_IN_HZ(256 * 57 / 8 / 2), 0, ATTOTIME_IN_HZ(256 * 57 / 8 / 2));
+ return data;
+}
+
+READ8_HANDLER( decocass_sound_data_ack_reset_r )
+{
+ UINT8 data = 0xff;
+ LOG(2,("CPU #%d sound ack rst <- $%02x\n", cpu_getactivecpu(), data));
+ decocass_sound_ack &= ~0x40;
+ return data;
+}
+
+WRITE8_HANDLER( decocass_sound_data_ack_reset_w )
+{
+ LOG(2,("CPU #%d sound ack rst -> $%02x\n", cpu_getactivecpu(), data));
+ decocass_sound_ack &= ~0x40;
+}
+
+WRITE8_HANDLER( decocass_nmi_reset_w )
+{
+ cpunum_set_input_line(0, INPUT_LINE_NMI, CLEAR_LINE );
+}
+
+WRITE8_HANDLER( decocass_quadrature_decoder_reset_w )
+{
+ /* just latch the analog controls here */
+ decocass_quadrature_decoder[0] = input_port_3_r(0);
+ decocass_quadrature_decoder[1] = input_port_4_r(0);
+ decocass_quadrature_decoder[2] = input_port_5_r(0);
+ decocass_quadrature_decoder[3] = input_port_6_r(0);
+}
+
+WRITE8_HANDLER( decocass_adc_w )
+{
+}
+
+/*
+ * E6x0 inputs
+ * E6x1 inputs
+ * E6x2 coin inp
+ * E6x3 quadrature decoder read
+ * E6x4 ""
+ * E6x5 ""
+ * E6x6 ""
+ * E6x7 a/d converter read
+ */
+READ8_HANDLER( decocass_input_r )
+{
+ UINT8 data = 0xff;
+ switch (offset & 7)
+ {
+ case 0: case 1: case 2:
+ data = readinputport(offset & 7);
+ break;
+ case 3: case 4: case 5: case 6:
+ data = decocass_quadrature_decoder[(offset & 7) - 3];
+ break;
+ default:
+ break;
+ }
+
+ return data;
+}
+
+/*
+ * D0 - REQ/ data request (8041 pin 34 port 1.7)
+ * D1 - FNO/ function number (8041 pin 21 port 2.0)
+ * D2 - EOT/ end-of-tape (8041 pin 22 port 2.1)
+ * D3 - ERR/ error condition (8041 pin 23 port 2.2)
+ * D4 - BOT-EOT from tape
+ * D5 -
+ * D6 -
+ * D7 - cassette present
+ */
+/* Note on a tapes leader-BOT-data-EOT-trailer format:
+ * A cassette has a transparent piece of tape on both ends,
+ * leader and trailer. And data tapes also have BOT and EOT
+ * holes, shortly before the the leader and trailer.
+ * The holes and clear tape are detected using a photo-resitor.
+ * When rewinding, the BOT/EOT signal will show a short
+ * pulse and if rewind continues a constant high signal later.
+ * The specs say the holes are "> 2ms" in length.
+ */
+
+#define TAPE_CLOCKRATE 4800 /* clock pulses per second */
+
+/* duration of the clear LEADER (and trailer) of the tape */
+#define TAPE_LEADER TAPE_CLOCKRATE /* 1s */
+/* duration of the GAP between leader and BOT/EOT */
+#define TAPE_GAP TAPE_CLOCKRATE*3/2 /* 1.5s */
+/* duration of BOT/EOT holes */
+#define TAPE_HOLE TAPE_CLOCKRATE/400 /* 0.0025s */
+
+/* byte offset of the tape chunks (8 clocks per byte = 16 samples) */
+/* 300 ms GAP between BOT and first data block (doesn't work.. thus /2) */
+#define TAPE_PRE_GAP 34
+#define TAPE_LEADIN (TAPE_PRE_GAP + 1)
+#define TAPE_HEADER (TAPE_LEADIN + 1)
+#define TAPE_BLOCK (TAPE_HEADER + 256)
+#define TAPE_CRC16_MSB (TAPE_BLOCK + 1)
+#define TAPE_CRC16_LSB (TAPE_CRC16_MSB + 1)
+#define TAPE_TRAILER (TAPE_CRC16_LSB + 1)
+#define TAPE_LEADOUT (TAPE_TRAILER + 1)
+#define TAPE_LONGCLOCK (TAPE_LEADOUT + 1)
+#define TAPE_POST_GAP (TAPE_LONGCLOCK + 34)
+
+/* size of a tape chunk (block) including gaps */
+#define TAPE_CHUNK TAPE_POST_GAP
+
+#define E5XX_MASK 0x02 /* use 0x0e for old style board */
+
+#define BIT0(x) ((x)&1)
+#define BIT1(x) (((x)>>1)&1)
+#define BIT2(x) (((x)>>2)&1)
+#define BIT3(x) (((x)>>3)&1)
+#define BIT4(x) (((x)>>4)&1)
+#define BIT5(x) (((x)>>5)&1)
+#define BIT6(x) (((x)>>6)&1)
+#define BIT7(x) (((x)>>7)&1)
+
+WRITE8_HANDLER( decocass_reset_w )
+{
+ LOG(1,("%9.7f 6502-PC: %04x decocass_reset_w(%02x): $%02x\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ decocass_reset = data;
+
+ /* CPU #1 active hight reset */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, data & 0x01 );
+
+ /* on reset also remove the sound timer */
+ if (data & 1)
+ timer_adjust(decocass_sound_timer, attotime_never, 0, attotime_never);
+
+ /* 8041 active low reset */
+ cpunum_set_input_line(2, INPUT_LINE_RESET, (data & 0x08) ^ 0x08 );
+}
+
+#ifdef MAME_DEBUG
+static const char *dirnm(int speed)
+{
+ if (speed < -1) return "fast rewind";
+ if (speed == -1) return "rewind";
+ if (speed == 0) return "stop";
+ if (speed == 1) return "forward";
+ return "fast forward";
+}
+#endif
+
+static void tape_crc16(UINT8 data)
+{
+ UINT8 c0, c1;
+ UINT8 old_lsb = crc16_lsb;
+ UINT8 old_msb = crc16_msb;
+ UINT8 feedback;
+
+ feedback = ((data >> 7) ^ crc16_msb) & 1;
+
+ /* rotate 16 bits */
+ c0 = crc16_lsb & 1;
+ c1 = crc16_msb & 1;
+ crc16_msb = (crc16_msb >> 1) | (c0 << 7);
+ crc16_lsb = (crc16_lsb >> 1) | (c1 << 7);
+
+ /* feedback into bit 7 */
+ if (feedback)
+ crc16_lsb |= 0x80;
+ else
+ crc16_lsb &= ~0x80;
+
+ /* feedback to bit 6 into bit 5 */
+ if (((old_lsb >> 6) ^ feedback) & 1)
+ crc16_lsb |= 0x20;
+ else
+ crc16_lsb &= ~0x20;
+
+ /* feedback to bit 1 into bit 0 */
+ if (((old_msb >> 1) ^ feedback) & 1)
+ crc16_msb |= 0x01;
+ else
+ crc16_msb &= ~0x01;
+}
+
+
+attotime decocass_adjust_tape_time(attotime tape_time)
+{
+ attotime ret = tape_time;
+
+ if (tape_timer)
+ {
+ attotime elapsed = timer_timeelapsed(tape_timer);
+
+ if (tape_dir > 0)
+ {
+ ret = attotime_add(tape_time, elapsed);
+
+ if (attotime_compare(ret, ATTOTIME_IN_MSEC(999900)) > 0)
+ ret = ATTOTIME_IN_MSEC(999900);
+ }
+
+ if (tape_dir < 0)
+ {
+ if (attotime_compare(tape_time, elapsed) > 0)
+ ret = attotime_sub(tape_time, elapsed);
+ else
+ ret = attotime_zero;
+ }
+ }
+
+ return ret;
+}
+
+
+static void tape_update(void)
+{
+ static int last_byte;
+ int offset, rclk, rdata, tape_bit, tape_byte, tape_block;
+
+ attotime tape_time = decocass_adjust_tape_time(tape_time0);
+
+ offset = (int)(attotime_to_double(attotime_mul(tape_time, TAPE_CLOCKRATE)) + 0.499995);
+
+ /* reset RCLK and RDATA inputs */
+ rclk = 0;
+ rdata = 0;
+
+ if (offset < TAPE_LEADER)
+ {
+ if (offset < 0)
+ offset = 0;
+ /* LEADER area */
+ if (0 == tape_bot_eot)
+ {
+ tape_bot_eot = 1;
+ set_led_status(1, 1);
+ LOG(5,("tape %5.4fs: %s found LEADER\n", attotime_to_double(tape_time), dirnm(tape_dir)));
+ }
+ }
+ else
+ if (offset < TAPE_LEADER + TAPE_GAP)
+ {
+ /* GAP between LEADER and BOT hole */
+ if (1 == tape_bot_eot)
+ {
+ tape_bot_eot = 0;
+ set_led_status(1, 0);
+ LOG(5,("tape %5.4fs: %s between BOT + LEADER\n", attotime_to_double(tape_time), dirnm(tape_dir)));
+ }
+ }
+ else
+ if (offset < TAPE_LEADER + TAPE_GAP + TAPE_HOLE)
+ {
+ /* during BOT hole */
+ if (0 == tape_bot_eot)
+ {
+ tape_bot_eot = 1;
+ set_led_status(1, 1);
+ LOG(5,("tape %5.4fs: %s found BOT\n", attotime_to_double(tape_time), dirnm(tape_dir)));
+ }
+ }
+ else
+ if (offset < tape_length - TAPE_LEADER - TAPE_GAP - TAPE_HOLE)
+ {
+ offset -= TAPE_LEADER + TAPE_GAP + TAPE_HOLE;
+
+ /* data area */
+ if (1 == tape_bot_eot)
+ {
+ tape_bot_eot = 0;
+ set_led_status(1, 0);
+ LOG(5,("tape %5.4fs: %s data area\n", attotime_to_double(tape_time), dirnm(tape_dir)));
+ }
+ rclk = (offset ^ 1) & 1;
+ tape_bit = (offset / 2) % 8;
+ tape_byte = (offset / 16) % TAPE_CHUNK;
+ tape_block = offset / 16 / TAPE_CHUNK;
+
+ if (tape_byte < TAPE_PRE_GAP)
+ {
+ rclk = 0;
+ rdata = 0;
+ }
+ else
+ if (tape_byte < TAPE_LEADIN)
+ {
+ rdata = (0x00 >> tape_bit) & 1;
+ if (tape_byte != last_byte)
+ {
+ LOG(5,("tape %5.4fs: LEADIN $00\n", attotime_to_double(tape_time)));
+ set_led_status(2, 1);
+ }
+ }
+ else
+ if (tape_byte < TAPE_HEADER)
+ {
+ rdata = (0xaa >> tape_bit) & 1;
+ if (tape_byte != last_byte)
+ LOG(5,("tape %5.4fs: HEADER $aa\n", attotime_to_double(tape_time)));
+ }
+ else
+ if (tape_byte < TAPE_BLOCK)
+ {
+ UINT8 *ptr = memory_region(REGION_USER2) + tape_block * 256 + tape_byte - TAPE_HEADER;
+ rdata = (*ptr >> tape_bit) & 1;
+ if (tape_byte != last_byte)
+ LOG(4,("tape %5.4fs: DATA(%02x) $%02x\n", attotime_to_double(tape_time), tape_byte - TAPE_HEADER, *ptr));
+ }
+ else
+ if (tape_byte < TAPE_CRC16_MSB)
+ {
+ rdata = (tape_crc16_msb[tape_block] >> tape_bit) & 1;
+ if (tape_byte != last_byte)
+ LOG(4,("tape %5.4fs: CRC16 MSB $%02x\n", attotime_to_double(tape_time), tape_crc16_msb[tape_block]));
+ }
+ else
+ if (tape_byte < TAPE_CRC16_LSB)
+ {
+ rdata = (tape_crc16_lsb[tape_block] >> tape_bit) & 1;
+ if (tape_byte != last_byte)
+ LOG(4,("tape %5.4fs: CRC16 LSB $%02x\n", attotime_to_double(tape_time), tape_crc16_lsb[tape_block]));
+ }
+ else
+ if (tape_byte < TAPE_TRAILER)
+ {
+ rdata = (0xaa >> tape_bit) & 1;
+ if (tape_byte != last_byte)
+ LOG(4,("tape %5.4fs: TRAILER $aa\n", attotime_to_double(tape_time)));
+ }
+ else
+ if (tape_byte < TAPE_LEADOUT)
+ {
+ rdata = (0x00 >> tape_bit) & 1;
+ if (tape_byte != last_byte)
+ LOG(4,("tape %5.4fs: LEADOUT $00\n", attotime_to_double(tape_time)));
+ }
+ else
+ if (tape_byte < TAPE_LONGCLOCK)
+ {
+ if (tape_byte != last_byte)
+ {
+ LOG(4,("tape %5.4fs: LONG CLOCK\n", attotime_to_double(tape_time)));
+ set_led_status(2, 0);
+ }
+ rclk = 1;
+ rdata = 0;
+ }
+ last_byte = tape_byte;
+ }
+ else
+ if (offset < tape_length - TAPE_LEADER - TAPE_GAP)
+ {
+ /* during EOT hole */
+ if (0 == tape_bot_eot)
+ {
+ tape_bot_eot = 1;
+ set_led_status(1, 1);
+ LOG(5,("tape %5.4fs: %s found EOT\n", attotime_to_double(tape_time), dirnm(tape_dir)));
+ }
+ }
+ else
+ if (offset < tape_length - TAPE_LEADER)
+ {
+ /* GAP between EOT and trailer */
+ if (1 == tape_bot_eot)
+ {
+ tape_bot_eot = 0;
+ set_led_status(1, 0);
+ LOG(5,("tape %5.4fs: %s EOT and TRAILER\n", attotime_to_double(tape_time), dirnm(tape_dir)));
+ }
+ }
+ else
+ {
+ /* TRAILER area */
+ if (0 == tape_bot_eot)
+ {
+ tape_bot_eot = 1;
+ set_led_status(1, 1);
+ LOG(5,("tape %5.4fs: %s found TRAILER\n", attotime_to_double(tape_time), dirnm(tape_dir)));
+ }
+ offset = tape_length - 1;
+ }
+
+ i8041_p2 = (i8041_p2 & ~0xe0) | (tape_bot_eot << 5) | (rclk << 6) | (rdata << 7);
+}
+
+#ifdef MAME_DEBUG
+static void decocass_fno(offs_t offset, UINT8 data)
+{
+ /* 8041ENA/ and is this a FNO write (function number)? */
+ if (0 == (i8041_p2 & 0x01))
+ {
+ switch (data)
+ {
+ case 0x25: logerror("8041 FNO 25: write_block\n"); break;
+ case 0x26: logerror("8041 FNO 26: rewind_block\n"); break;
+ case 0x27: logerror("8041 FNO 27: read_block_a\n"); break;
+ case 0x28: logerror("8041 FNO 28: read_block_b\n"); break;
+ case 0x29: logerror("8041 FNO 29: tape_rewind_fast\n"); break;
+ case 0x2a: logerror("8041 FNO 2a: tape_forward\n"); break;
+ case 0x2b: logerror("8041 FNO 2b: tape_rewind\n"); break;
+ case 0x2c: logerror("8041 FNO 2c: force_abort\n"); break;
+ case 0x2d: logerror("8041 FNO 2d: tape_erase\n"); break;
+ case 0x2e: logerror("8041 FNO 2e: search_tape_mark\n"); break;
+ case 0x2f: logerror("8041 FNO 2f: search_eot\n"); break;
+ case 0x30: logerror("8041 FNO 30: advance_block\n"); break;
+ case 0x31: logerror("8041 FNO 31: write_tape_mark\n"); break;
+ case 0x32: logerror("8041 FNO 32: reset_error\n"); break;
+ case 0x33: logerror("8041 FNO 33: flag_status_report\n"); break;
+ case 0x34: logerror("8041 FNO 34: report_status_to_main\n"); break;
+ default: logerror("8041 FNO %02x: invalid\n", data);
+ }
+ }
+}
+#endif
+
+/***************************************************************************
+ *
+ * TYPE1 DONGLE (DE-0061)
+ * - Lock 'n Chase
+ * - Treasure Island
+ * - Super Astro Fighter
+ * - Lucky Poker
+ * - Terranian
+ * - Explorer
+ * - Pro Golf
+ *
+ * Latch bits 2 and 6, pass bit 3, invert bit 2.
+ * Lookup PROM DE-0061 using bits 0, 1, 4, 5, and 7 as the
+ * address bits; take PROM data 0-4 as data bits 0, 1, 4, 5, and 7.
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_type1_latch_26_pass_3_inv_2_r )
+{
+ static UINT8 latch1;
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_STAT);
+ else
+ data = 0xff;
+
+ data = (BIT0(data) << 0) | (BIT1(data) << 1) | 0x7c;
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type1_latch_26_pass_3_inv_2_r(%02x): $%02x <- (%s %s)\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data,
+ (data & 1) ? "OBF" : "-",
+ (data & 2) ? "IBF" : "-"));
+ }
+ else
+ {
+ offs_t promaddr;
+ UINT8 save;
+ UINT8 *prom = memory_region(REGION_USER1);
+
+ if (firsttime)
+ {
+ LOG(3,("prom data:\n"));
+ for (promaddr = 0; promaddr < 32; promaddr++)
+ {
+ if (promaddr % 8 == 0)
+ LOG(3,(" %02x:", promaddr));
+ LOG(3,(" %02x%s", prom[promaddr], (promaddr % 8) == 7 ? "\n" : ""));
+ }
+ firsttime = 0;
+ latch1 = 0; /* reset latch (??) */
+ }
+
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_DATA);
+ else
+ data = 0xff;
+
+ save = data; /* save the unmodifed data for the latch */
+
+ promaddr =
+ (((data >> MAP0(type1_inmap)) & 1) << 0) |
+ (((data >> MAP1(type1_inmap)) & 1) << 1) |
+ (((data >> MAP4(type1_inmap)) & 1) << 2) |
+ (((data >> MAP5(type1_inmap)) & 1) << 3) |
+ (((data >> MAP7(type1_inmap)) & 1) << 4);
+ /* latch bits 2 and 6, pass bit 3, invert bit 2 */
+ data =
+ (((prom[promaddr] >> 0) & 1) << MAP0(type1_outmap)) |
+ (((prom[promaddr] >> 1) & 1) << MAP1(type1_outmap)) |
+ ((1 - ((latch1 >> MAP2(type1_inmap)) & 1)) << MAP2(type1_outmap)) |
+ (((data >> MAP3(type1_inmap)) & 1) << MAP3(type1_outmap)) |
+ (((prom[promaddr] >> 2) & 1) << MAP4(type1_outmap)) |
+ (((prom[promaddr] >> 3) & 1) << MAP5(type1_outmap)) |
+ (((latch1 >> MAP6(type1_inmap)) & 1) << MAP6(type1_outmap)) |
+ (((prom[promaddr] >> 4) & 1) << MAP7(type1_outmap));
+
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type1_latch_26_pass_3_inv_2_r(%02x): $%02x\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+
+ latch1 = save; /* latch the data for the next A0 == 0 read */
+ }
+ return data;
+}
+
+
+/***************************************************************************
+ *
+ * TYPE1 DONGLE (DE-0061)
+ * - Test Tape
+ *
+ * Pass bits 1, 3, and 6. Lookup PROM DE-0061 using bits 0, 2, 4, 5, and 7
+ * as the address bits; take PROM data 0-4 as data bits 0, 2, 4, 5, and 7.
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_type1_pass_136_r )
+{
+ static UINT8 latch1;
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_STAT);
+ else
+ data = 0xff;
+
+ data = (BIT0(data) << 0) | (BIT1(data) << 1) | 0x7c;
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type1_pass_136_r(%02x): $%02x <- (%s %s)\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data,
+ (data & 1) ? "OBF" : "-",
+ (data & 2) ? "IBF" : "-"));
+ }
+ else
+ {
+ offs_t promaddr;
+ UINT8 save;
+ UINT8 *prom = memory_region(REGION_USER1);
+
+ if (firsttime)
+ {
+ LOG(3,("prom data:\n"));
+ for (promaddr = 0; promaddr < 32; promaddr++)
+ {
+ if (promaddr % 8 == 0)
+ LOG(3,(" %02x:", promaddr));
+ LOG(3,(" %02x%s", prom[promaddr], (promaddr % 8) == 7 ? "\n" : ""));
+ }
+ firsttime = 0;
+ latch1 = 0; /* reset latch (??) */
+ }
+
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_DATA);
+ else
+ data = 0xff;
+
+ save = data; /* save the unmodifed data for the latch */
+
+ promaddr =
+ (((data >> MAP0(type1_inmap)) & 1) << 0) |
+ (((data >> MAP2(type1_inmap)) & 1) << 1) |
+ (((data >> MAP4(type1_inmap)) & 1) << 2) |
+ (((data >> MAP5(type1_inmap)) & 1) << 3) |
+ (((data >> MAP7(type1_inmap)) & 1) << 4);
+ /* latch bits 1 and 6, pass bit 3, invert bit 1 */
+ data =
+ (((prom[promaddr] >> 0) & 1) << MAP0(type1_outmap)) |
+ (((data >> MAP1(type1_inmap)) & 1) << MAP1(type1_outmap)) |
+ (((prom[promaddr] >> 1) & 1) << MAP2(type1_outmap)) |
+ (((data >> MAP3(type1_inmap)) & 1) << MAP3(type1_outmap)) |
+ (((prom[promaddr] >> 2) & 1) << MAP4(type1_outmap)) |
+ (((prom[promaddr] >> 3) & 1) << MAP5(type1_outmap)) |
+ (((data >> MAP6(type1_inmap)) & 1) << MAP6(type1_outmap)) |
+ (((prom[promaddr] >> 4) & 1) << MAP7(type1_outmap));
+
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type1_pass_136_r(%02x): $%02x\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+
+ latch1 = save; /* latch the data for the next A0 == 0 read */
+ }
+ return data;
+}
+
+/***************************************************************************
+ *
+ * TYPE1 DONGLE (DE-0061)
+ * - Highway Chase
+ *
+ * Latch bits 2 and 7, pass bit 3, invert bit 2 to the output.
+ * Lookup PROM (Highway Chase) using data bits 0, 1, 4, 5, and 6 as the
+ * address bits. Take PROM data 0-4 as data bits 0, 1, 4, 5, and 6.
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_type1_latch_27_pass_3_inv_2_r )
+{
+ static UINT8 latch1;
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_STAT);
+ else
+ data = 0xff;
+
+ data = (BIT0(data) << 0) | (BIT1(data) << 1) | 0x7c;
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type1_latch_27_pass_3_inv_2_r(%02x): $%02x <- (%s %s)\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data,
+ (data & 1) ? "OBF" : "-",
+ (data & 2) ? "IBF" : "-"));
+ }
+ else
+ {
+ offs_t promaddr;
+ UINT8 save;
+ UINT8 *prom = memory_region(REGION_USER1);
+
+ if (firsttime)
+ {
+ LOG(3,("prom data:\n"));
+ for (promaddr = 0; promaddr < 32; promaddr++)
+ {
+ if (promaddr % 8 == 0)
+ LOG(3,(" %02x:", promaddr));
+ LOG(3,(" %02x%s", prom[promaddr], (promaddr % 8) == 7 ? "\n" : ""));
+ }
+ firsttime = 0;
+ latch1 = 0; /* reset latch (??) */
+ }
+
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_DATA);
+ else
+ data = 0xff;
+
+ save = data; /* save the unmodifed data for the latch */
+
+ promaddr =
+ (((data >> MAP0(type1_inmap)) & 1) << 0) |
+ (((data >> MAP1(type1_inmap)) & 1) << 1) |
+ (((data >> MAP4(type1_inmap)) & 1) << 2) |
+ (((data >> MAP5(type1_inmap)) & 1) << 3) |
+ (((data >> MAP6(type1_inmap)) & 1) << 4);
+ /* latch bits 2 and 7, pass bit 3, invert bit 2 */
+ data =
+ (((prom[promaddr] >> 0) & 1) << MAP0(type1_outmap)) |
+ (((prom[promaddr] >> 1) & 1) << MAP1(type1_outmap)) |
+ ((1 - ((latch1 >> MAP2(type1_inmap)) & 1)) << MAP2(type1_outmap)) |
+ (((data >> MAP3(type1_inmap)) & 1) << MAP3(type1_outmap)) |
+ (((prom[promaddr] >> 2) & 1) << MAP4(type1_outmap)) |
+ (((prom[promaddr] >> 3) & 1) << MAP5(type1_outmap)) |
+ (((prom[promaddr] >> 4) & 1) << MAP6(type1_outmap)) |
+ (((latch1 >> MAP7(type1_inmap)) & 1) << MAP7(type1_outmap));
+
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type1_latch_27_pass_3_inv_2_r(%02x): $%02x\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+
+ latch1 = save; /* latch the data for the next A0 == 0 read */
+ }
+ return data;
+}
+
+/***************************************************************************
+ *
+ * TYPE1 DONGLE (DE-0061)
+ * - Explorer
+ *
+ * Latch bits 2 and 6, pass bit 5, invert bit 2 to the output.
+ * Lookup PROM (Explorer) using bits 0, 1, 3, 4, and 7 as the
+ * address bits. Take PROM data 0-4 as data bits 0, 1, 3, 4, and 7.
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_type1_latch_26_pass_5_inv_2_r )
+{
+ static UINT8 latch1;
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_STAT);
+ else
+ data = 0xff;
+
+ data = (BIT0(data) << 0) | (BIT1(data) << 1) | 0x7c;
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type1_latch_26_pass_5_inv_2_r(%02x): $%02x <- (%s %s)\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data,
+ (data & 1) ? "OBF" : "-",
+ (data & 2) ? "IBF" : "-"));
+ }
+ else
+ {
+ offs_t promaddr;
+ UINT8 save;
+ UINT8 *prom = memory_region(REGION_USER1);
+
+ if (firsttime)
+ {
+ LOG(3,("prom data:\n"));
+ for (promaddr = 0; promaddr < 32; promaddr++)
+ {
+ if (promaddr % 8 == 0)
+ LOG(3,(" %02x:", promaddr));
+ LOG(3,(" %02x%s", prom[promaddr], (promaddr % 8) == 7 ? "\n" : ""));
+ }
+ firsttime = 0;
+ latch1 = 0; /* reset latch (??) */
+ }
+
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_DATA);
+ else
+ data = 0xff;
+
+ save = data; /* save the unmodifed data for the latch */
+
+ promaddr =
+ (((data >> MAP0(type1_inmap)) & 1) << 0) |
+ (((data >> MAP1(type1_inmap)) & 1) << 1) |
+ (((data >> MAP3(type1_inmap)) & 1) << 2) |
+ (((data >> MAP4(type1_inmap)) & 1) << 3) |
+ (((data >> MAP7(type1_inmap)) & 1) << 4);
+ /* latch bits 2 and 6, pass bit 5, invert bit 2 */
+ data =
+ (((prom[promaddr] >> 0) & 1) << MAP0(type1_outmap)) |
+ (((prom[promaddr] >> 1) & 1) << MAP1(type1_outmap)) |
+ ((1 - ((latch1 >> MAP2(type1_inmap)) & 1)) << MAP2(type1_outmap)) |
+ (((prom[promaddr] >> 2) & 1) << MAP3(type1_outmap)) |
+ (((prom[promaddr] >> 3) & 1) << MAP4(type1_outmap)) |
+ (((data >> MAP5(type1_inmap)) & 1) << MAP5(type1_outmap)) |
+ (((latch1 >> MAP6(type1_inmap)) & 1) << MAP6(type1_outmap)) |
+ (((prom[promaddr] >> 4) & 1) << MAP7(type1_outmap));
+
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type1_latch_26_pass_5_inv_2_r(%02x): $%02x\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+
+ latch1 = save; /* latch the data for the next A0 == 0 read */
+ }
+ return data;
+}
+
+
+
+/***************************************************************************
+ *
+ * TYPE1 DONGLE (DE-0061)
+ * - Astro Fantazia
+ *
+ * Latch bits 1 and 6, pass bit 3, invert bit 1.
+ * Lookup PROM DE-0061 using bits 0, 2, 4, 5, and 7 as the
+ * address bits; take PROM data 0-4 as data bits 0, 2, 4, 5, and 7.
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_type1_latch_16_pass_3_inv_1_r )
+{
+ static UINT8 latch1;
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_STAT);
+ else
+ data = 0xff;
+
+ data = (BIT0(data) << 0) | (BIT1(data) << 1) | 0x7c;
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type1_latch_16_pass_3_inv_1_r(%02x): $%02x <- (%s %s)\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data,
+ (data & 1) ? "OBF" : "-",
+ (data & 2) ? "IBF" : "-"));
+ }
+ else
+ {
+ offs_t promaddr;
+ UINT8 save;
+ UINT8 *prom = memory_region(REGION_USER1);
+
+ if (firsttime)
+ {
+ LOG(3,("prom data:\n"));
+ for (promaddr = 0; promaddr < 32; promaddr++)
+ {
+ if (promaddr % 8 == 0)
+ LOG(3,(" %02x:", promaddr));
+ LOG(3,(" %02x%s", prom[promaddr], (promaddr % 8) == 7 ? "\n" : ""));
+ }
+ firsttime = 0;
+ latch1 = 0; /* reset latch (??) */
+ }
+
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, I8X41_DATA);
+ else
+ data = 0xff;
+
+ save = data; /* save the unmodifed data for the latch */
+
+ promaddr =
+ (((data >> MAP0(type1_inmap)) & 1) << 0) |
+ (((data >> MAP2(type1_inmap)) & 1) << 1) |
+ (((data >> MAP4(type1_inmap)) & 1) << 2) |
+ (((data >> MAP5(type1_inmap)) & 1) << 3) |
+ (((data >> MAP7(type1_inmap)) & 1) << 4);
+ /* latch bits 1 and 6, pass bit 3, invert bit 1 */
+ data =
+ (((prom[promaddr] >> 0) & 1) << MAP0(type1_outmap)) |
+ ((1 - ((latch1 >> MAP1(type1_inmap)) & 1)) << MAP1(type1_outmap)) |
+ (((prom[promaddr] >> 1) & 1) << MAP2(type1_outmap)) |
+ (((data >> MAP3(type1_inmap)) & 1) << MAP3(type1_outmap)) |
+ (((prom[promaddr] >> 2) & 1) << MAP4(type1_outmap)) |
+ (((prom[promaddr] >> 3) & 1) << MAP5(type1_outmap)) |
+ (((latch1 >> MAP6(type1_inmap)) & 1) << MAP6(type1_outmap)) |
+ (((prom[promaddr] >> 4) & 1) << MAP7(type1_outmap));
+
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type1_latch_16_pass_3_inv_1_r(%02x): $%02x\n",
+ attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+
+ latch1 = save; /* latch the data for the next A0 == 0 read */
+ }
+ return data;
+}
+
+
+
+
+/***************************************************************************
+ *
+ * TYPE2 DONGLE (CS82-007)
+ * - Mission X
+ * - Disco No 1
+ * - Pro Tennis
+ * - Tornado
+ *
+ ***************************************************************************/
+static READ8_HANDLER( decocass_type2_r )
+{
+ UINT8 data;
+
+ if (1 == type2_xx_latch)
+ {
+ if (1 == (offset & 1))
+ {
+ UINT8 *prom = memory_region(REGION_USER1);
+ data = prom[256 * type2_d2_latch + type2_promaddr];
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type2_r(%02x): $%02x <- prom[%03x]\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, 256 * type2_d2_latch + type2_promaddr));
+ }
+ else
+ {
+ data = 0xff; /* floating input? */
+ }
+ }
+ else
+ {
+ if (0 == (offset & E5XX_MASK))
+ data = cpunum_get_reg(2, offset & 1 ? I8X41_STAT : I8X41_DATA);
+ else
+ data = offset & 0xff;
+
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type2_r(%02x): $%02x <- 8041-%s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, offset & 1 ? "STATUS" : "DATA"));
+ }
+ return data;
+}
+
+static WRITE8_HANDLER( decocass_type2_w )
+{
+ if (1 == type2_xx_latch)
+ {
+ if (1 == (offset & 1))
+ {
+ LOG(4,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> set PROM+D2 latch", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ else
+ {
+ type2_promaddr = data;
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> set PROM addr $%02x\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, type2_promaddr));
+ return;
+ }
+ }
+ else
+ {
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s ", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041 DATA"));
+ }
+ if (1 == (offset & 1))
+ {
+ if (0xc0 == (data & 0xf0))
+ {
+ type2_xx_latch = 1;
+ type2_d2_latch = (data & 0x04) ? 1 : 0;
+ LOG(3,("PROM:%s D2:%d", type2_xx_latch ? "on" : "off", type2_d2_latch));
+ }
+ }
+ cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
+
+#ifdef MAME_DEBUG
+ decocass_fno(offset, data);
+#endif
+}
+
+/***************************************************************************
+ *
+ * TYPE3 DONGLE
+ * - Bump 'n Jump
+ * - Burnin' Rubber
+ * - Burger Time
+ * - Graplop
+ * - Cluster Buster
+ * - LaPaPa
+ * - Fighting Ice Hockey
+ * - Pro Bowling
+ * - Night Star
+ * - Pro Soccer
+ * - Peter Pepper's Ice Cream Factory
+ *
+ ***************************************************************************/
+static READ8_HANDLER( decocass_type3_r )
+{
+ UINT8 data, save;
+
+ if (1 == (offset & 1))
+ {
+ if (1 == type3_pal_19)
+ {
+ UINT8 *prom = memory_region(REGION_USER1);
+ data = prom[type3_ctrs];
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- prom[$%03x]\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, type3_ctrs));
+ if (++type3_ctrs == 4096)
+ type3_ctrs = 0;
+ }
+ else
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ data = cpunum_get_reg(2, I8X41_STAT);
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- 8041 STATUS\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ else
+ {
+ data = 0xff; /* open data bus? */
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- open bus\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ }
+ }
+ else
+ {
+ if (1 == type3_pal_19)
+ {
+ save = data = 0xff; /* open data bus? */
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x <- open bus", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ else
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ save = cpunum_get_reg(2, I8X41_DATA);
+ switch (type3_swap)
+ {
+ case TYPE3_SWAP_01:
+ data =
+ (BIT1(save) << 0) |
+ (type3_d0_latch << 1) |
+ (BIT2(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_12:
+ data =
+ (type3_d0_latch << 0) |
+ (BIT2(save) << 1) |
+ (BIT1(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_13:
+ data =
+ (type3_d0_latch << 0) |
+ (BIT3(save) << 1) |
+ (BIT2(save) << 2) |
+ (BIT1(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_24:
+ data =
+ (type3_d0_latch << 0) |
+ (BIT1(save) << 1) |
+ (BIT4(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT2(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_25:
+ data =
+ (type3_d0_latch << 0) |
+ (BIT1(save) << 1) |
+ (BIT5(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT2(save) << 5) |
+ (BIT6(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_34_0:
+ data =
+ (type3_d0_latch << 0) |
+ (BIT1(save) << 1) |
+ (BIT2(save) << 2) |
+ (BIT3(save) << 4) |
+ (BIT4(save) << 3) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_34_7:
+ data =
+ (BIT7(save) << 0) |
+ (BIT1(save) << 1) |
+ (BIT2(save) << 2) |
+ (BIT4(save) << 3) |
+ (BIT3(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 6) |
+ (type3_d0_latch << 7);
+ break;
+ case TYPE3_SWAP_23_56:
+ data =
+ (type3_d0_latch << 0) |
+ (BIT1(save) << 1) |
+ (BIT3(save) << 2) |
+ (BIT2(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT6(save) << 5) |
+ (BIT5(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_56:
+ data =
+ type3_d0_latch |
+ (BIT1(save) << 1) |
+ (BIT2(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT6(save) << 5) |
+ (BIT5(save) << 6) |
+ (BIT7(save) << 7);
+ break;
+ case TYPE3_SWAP_67:
+ data =
+ type3_d0_latch |
+ (BIT1(save) << 1) |
+ (BIT2(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT7(save) << 6) |
+ (BIT6(save) << 7);
+ break;
+ default:
+ data =
+ type3_d0_latch |
+ (BIT1(save) << 1) |
+ (BIT2(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 6) |
+ (BIT7(save) << 7);
+ }
+ type3_d0_latch = save & 1;
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x '%c' <- 8041-DATA\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
+ }
+ else
+ {
+ save = 0xff; /* open data bus? */
+ data =
+ type3_d0_latch |
+ (BIT1(save) << 1) |
+ (BIT2(save) << 2) |
+ (BIT3(save) << 3) |
+ (BIT4(save) << 4) |
+ (BIT5(save) << 5) |
+ (BIT6(save) << 7) |
+ (BIT7(save) << 6);
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type3_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
+ type3_d0_latch = save & 1;
+ }
+ }
+ }
+
+ return data;
+}
+
+static WRITE8_HANDLER( decocass_type3_w )
+{
+ if (1 == (offset & 1))
+ {
+ if (1 == type3_pal_19)
+ {
+ type3_ctrs = data << 4;
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, "LDCTRS"));
+ return;
+ }
+ else
+ if (0xc0 == (data & 0xf0))
+ type3_pal_19 = 1;
+ }
+ else
+ {
+ if (1 == type3_pal_19)
+ {
+ /* write nowhere?? */
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, "nowhere?"));
+ return;
+ }
+ }
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
+ cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
+}
+
+/***************************************************************************
+ *
+ * TYPE4 DONGLE
+ * - Scrum Try
+ * Contains a 32K (EP)ROM that can be read from any byte
+ * boundary sequentially. The EPROM is enable after writing
+ * 1100xxxx to E5x1 once. Then an address is written LSB
+ * to E5x0 MSB to E5x1 and every read from E5x1 returns the
+ * next byte of the contents.
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_type4_r )
+{
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ data = cpunum_get_reg(2, I8X41_STAT);
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x <- 8041 STATUS\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ else
+ {
+ data = 0xff; /* open data bus? */
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x <- open bus\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ }
+ else
+ {
+ if (type4_latch)
+ {
+ UINT8 *prom = memory_region(REGION_USER1);
+
+ data = prom[type4_ctrs];
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x '%c' <- PROM[%04x]\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.', type4_ctrs));
+ type4_ctrs = (type4_ctrs+1) & 0x7fff;
+ }
+ else
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ data = cpunum_get_reg(2, I8X41_DATA);
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
+ }
+ else
+ {
+ data = 0xff; /* open data bus? */
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type4_r(%02x): $%02x <- open bus\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ }
+ }
+
+ return data;
+}
+
+static WRITE8_HANDLER( decocass_type4_w )
+{
+ if (1 == (offset & 1))
+ {
+ if (1 == type4_latch)
+ {
+ type4_ctrs = (type4_ctrs & 0x00ff) | ((data & 0x7f) << 8);
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS MSB (%04x)\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, type4_ctrs));
+ return;
+ }
+ else
+ if (0xc0 == (data & 0xf0))
+ {
+ type4_latch = 1;
+ }
+ }
+ else
+ {
+ if (type4_latch)
+ {
+ type4_ctrs = (type4_ctrs & 0xff00) | data;
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> CTRS LSB (%04x)\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, type4_ctrs));
+ return;
+ }
+ }
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
+ cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
+}
+
+/***************************************************************************
+ *
+ * TYPE5 DONGLE
+ * - Boulder Dash
+ * Actually a NOP dongle returning 0x55 after triggering a latch
+ * by writing 1100xxxx to E5x1
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_type5_r )
+{
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ data = cpunum_get_reg(2, I8X41_STAT);
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x <- 8041 STATUS\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ else
+ {
+ data = 0xff; /* open data bus? */
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x <- open bus\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ }
+ else
+ {
+ if (type5_latch)
+ {
+ data = 0x55; /* Only a fixed value? It looks like this is all we need to do */
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x '%c' <- fixed value???\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
+ }
+ else
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ data = cpunum_get_reg(2, I8X41_DATA);
+ LOG(3,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
+ }
+ else
+ {
+ data = 0xff; /* open data bus? */
+ LOG(4,("%9.7f 6502-PC: %04x decocass_type5_r(%02x): $%02x <- open bus\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ }
+ }
+
+ return data;
+}
+
+static WRITE8_HANDLER( decocass_type5_w )
+{
+ if (1 == (offset & 1))
+ {
+ if (1 == type5_latch)
+ {
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, "latch #2??"));
+ return;
+ }
+ else
+ if (0xc0 == (data & 0xf0))
+ type5_latch = 1;
+ }
+ else
+ {
+ if (type5_latch)
+ {
+ /* write nowhere?? */
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, "nowhere?"));
+ return;
+ }
+ }
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
+ cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
+}
+
+/***************************************************************************
+ *
+ * NO DONGLE
+ * - Flying Ball
+ * A NOP dongle returning the data read from cassette as is.
+ *
+ ***************************************************************************/
+
+static READ8_HANDLER( decocass_nodong_r )
+{
+ UINT8 data;
+
+ if (1 == (offset & 1))
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ data = cpunum_get_reg(2, I8X41_STAT);
+ LOG(4,("%9.7f 6502-PC: %04x decocass_nodong_r(%02x): $%02x <- 8041 STATUS\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ else
+ {
+ data = 0xff; /* open data bus? */
+ LOG(4,("%9.7f 6502-PC: %04x decocass_nodong_r(%02x): $%02x <- open bus\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ }
+ else
+ {
+ if (0 == (offset & E5XX_MASK))
+ {
+ data = cpunum_get_reg(2, I8X41_DATA);
+ LOG(3,("%9.7f 6502-PC: %04x decocass_nodong_r(%02x): $%02x '%c' <- open bus (D0 replaced with latch)\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, (data >= 32) ? data : '.'));
+ }
+ else
+ {
+ data = 0xff; /* open data bus? */
+ LOG(4,("%9.7f 6502-PC: %04x decocass_nodong_r(%02x): $%02x <- open bus\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+ }
+
+ return data;
+}
+
+/***************************************************************************
+ *
+ * Main dongle and 8041 interface
+ *
+ ***************************************************************************/
+
+READ8_HANDLER( decocass_e5xx_r )
+{
+ UINT8 data;
+
+ /* E5x2-E5x3 and mirrors */
+ if (2 == (offset & E5XX_MASK))
+ {
+ data =
+ (BIT7(i8041_p1) << 0) | /* D0 = P17 - REQ/ */
+ (BIT0(i8041_p2) << 1) | /* D1 = P20 - FNO/ */
+ (BIT1(i8041_p2) << 2) | /* D2 = P21 - EOT/ */
+ (BIT2(i8041_p2) << 3) | /* D3 = P22 - ERR/ */
+ ((tape_bot_eot) << 4) | /* D4 = BOT/EOT (direct from drive) */
+ (1 << 5) | /* D5 floating input */
+ (1 << 6) | /* D6 floating input */
+ ((1 - tape_present) << 7); /* D7 = cassette present */
+
+ LOG(4,("%9.7f 6502-PC: %04x decocass_e5xx_r(%02x): $%02x <- STATUS (%s%s%s%s%s%s%s%s)\n",
+ attotime_to_double(timer_get_time()),
+ activecpu_get_previouspc(),
+ offset, data,
+ data & 0x01 ? "" : "REQ/",
+ data & 0x02 ? "" : " FNO/",
+ data & 0x04 ? "" : " EOT/",
+ data & 0x08 ? "" : " ERR/",
+ data & 0x10 ? " [BOT-EOT]" : "",
+ data & 0x20 ? " [BIT5?]" : "",
+ data & 0x40 ? " [BIT6?]" : "",
+ data & 0x80 ? "" : " [CASS-PRESENT/]"));
+ }
+ else
+ {
+ if (decocass_dongle_r)
+ data = (*decocass_dongle_r)(offset);
+ else
+ data = 0xff;
+ }
+ return data;
+}
+
+WRITE8_HANDLER( decocass_e5xx_w )
+{
+ if (decocass_dongle_w)
+ {
+ (*decocass_dongle_w)(offset, data);
+ return;
+ }
+
+ if (0 == (offset & E5XX_MASK))
+ {
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> %s\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data, offset & 1 ? "8041-CMND" : "8041-DATA"));
+ cpunum_set_reg(2, offset & 1 ? I8X41_CMND : I8X41_DATA, data);
+#ifdef MAME_DEBUG
+ decocass_fno(offset, data);
+#endif
+ }
+ else
+ {
+ LOG(3,("%9.7f 6502-PC: %04x decocass_e5xx_w(%02x): $%02x -> dongle\n", attotime_to_double(timer_get_time()), activecpu_get_previouspc(), offset, data));
+ }
+}
+
+/***************************************************************************
+ *
+ * DE-0091xx daughter board handler
+ *
+ * The DE-0091xx daughter board seems to be a read-only ROM board with
+ * two times five 4K ROMs. The only game using it (so far) is
+ * Treasure Island, which has 4 ROMs.
+ * The board's ROMs are mapped into view for reads between addresses
+ * 0x6000 and 0xafff by setting bit0 of address 0xe900.
+ *
+ ***************************************************************************/
+
+WRITE8_HANDLER( decocass_e900_w )
+{
+ de0091_enable = data & 1;
+ memory_set_bank(1, data & 1);
+ /* Perhaps the second row of ROMs is enabled by another bit.
+ * There is no way to verify this yet, so for now just look
+ * at bit 0 to enable the daughter board at reads between
+ * 0x6000 and 0xafff.
+ */
+}
+
+WRITE8_HANDLER( decocass_de0091_w )
+{
+ /* don't allow writes to the ROMs */
+ if (!de0091_enable)
+ decocass_charram_w(offset, data);
+}
+
+/***************************************************************************
+ *
+ * state save setup
+ *
+ ***************************************************************************/
+static void decocass_state_save_postload(void)
+{
+#if 0
+ /* fix me - this won't work anymore */
+ int A;
+ UINT8 *mem = memory_region(REGION_CPU1);
+ int diff = memory_region_length(REGION_CPU1) / 2;
+
+ memory_set_opcode_base(0, mem + diff);
+
+ for (A = 0;A < 0x10000; A++)
+ decocass_w(A, mem[A]);
+ /* restart the timer if the tape was playing */
+ if (0 != tape_dir)
+ timer_adjust(tape_timer, attotime_never, 0, attotime_never);
+#endif
+}
+
+/* To be called once from driver_init, i.e. decocass_init */
+void decocass_machine_state_save_init(void)
+{
+ state_save_register_func_postload(decocass_state_save_postload);
+ state_save_register_global(tape_dir);
+ state_save_register_global(tape_speed);
+ state_save_register_global(tape_time0.seconds);
+ state_save_register_global(tape_time0.attoseconds);
+ state_save_register_global(firsttime);
+ state_save_register_global(tape_present);
+ state_save_register_global(tape_blocks);
+ state_save_register_global(tape_length);
+ state_save_register_global(tape_bot_eot);
+ state_save_register_global(crc16_lsb);
+ state_save_register_global(crc16_msb);
+ state_save_register_global_array(tape_crc16_lsb);
+ state_save_register_global_array(tape_crc16_msb);
+ state_save_register_global(decocass_reset);
+ state_save_register_global(i8041_p1);
+ state_save_register_global(i8041_p2);
+ state_save_register_global(de0091_enable);
+ state_save_register_global(type1_inmap);
+ state_save_register_global(type1_outmap);
+ state_save_register_global(type2_d2_latch);
+ state_save_register_global(type2_xx_latch);
+ state_save_register_global(type2_promaddr);
+ state_save_register_global(type3_ctrs);
+ state_save_register_global(type3_d0_latch);
+ state_save_register_global(type3_pal_19);
+ state_save_register_global(type3_swap);
+ state_save_register_global(type4_ctrs);
+ state_save_register_global(type4_latch);
+ state_save_register_global(type5_latch);
+ state_save_register_global(decocass_sound_ack);
+}
+
+/***************************************************************************
+ *
+ * init machine functions (select dongle and determine tape image size)
+ *
+ ***************************************************************************/
+
+static void decocass_init_common(void)
+{
+ UINT8 *image = memory_region(REGION_USER2);
+ int i, offs;
+
+ tape_dir = 0;
+ tape_speed = 0;
+ tape_timer = timer_alloc(NULL);
+
+ firsttime = 1;
+ tape_present = 1;
+ tape_blocks = 0;
+ for (i = memory_region_length(REGION_USER2) / 256 - 1; !tape_blocks && i > 0; i--)
+ for (offs = 256 * i; !tape_blocks && offs < 256 * i + 256; offs++)
+ if (image[offs])
+ tape_blocks = i+1;
+ for (i = 0; i < tape_blocks; i++)
+ {
+ crc16_lsb = 0;
+ crc16_msb = 0;
+ for (offs = 256 * i; offs < 256 * i + 256; offs++)
+ {
+ tape_crc16(image[offs] << 7);
+ tape_crc16(image[offs] << 6);
+ tape_crc16(image[offs] << 5);
+ tape_crc16(image[offs] << 4);
+ tape_crc16(image[offs] << 3);
+ tape_crc16(image[offs] << 2);
+ tape_crc16(image[offs] << 1);
+ tape_crc16(image[offs] << 0);
+ }
+ tape_crc16_lsb[i] = crc16_lsb;
+ tape_crc16_msb[i] = crc16_msb;
+ }
+
+ tape_length = tape_blocks * TAPE_CHUNK * 8 * 2 + 2 * (TAPE_LEADER + TAPE_GAP + TAPE_HOLE);
+ tape_time0 = attotime_mul(ATTOTIME_IN_HZ(TAPE_CLOCKRATE), TAPE_LEADER + TAPE_GAP - TAPE_HOLE);
+ LOG(0,("tape: %d blocks\n", tape_blocks));
+ tape_bot_eot = 0;
+
+ decocass_dongle_r = NULL;
+ decocass_dongle_w = NULL;
+
+ decocass_reset = 0;
+ i8041_p1 = 0xff;
+ i8041_p2 = 0xff;
+
+ type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
+ type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
+
+ type2_d2_latch = 0;
+ type2_xx_latch = 0;
+ type2_promaddr = 0;
+
+ type3_ctrs = 0;
+ type3_d0_latch = 0;
+ type3_pal_19 = 0;
+ type3_swap = 0;
+
+ memset(decocass_quadrature_decoder, 0, sizeof(decocass_quadrature_decoder));
+ decocass_sound_ack = 0;
+ decocass_sound_timer = timer_alloc(decocass_sound_nmi_pulse);
+}
+
+MACHINE_RESET( decocass )
+{
+ decocass_init_common();
+}
+
+MACHINE_RESET( ctsttape )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061)\n"));
+ decocass_dongle_r = decocass_type1_pass_136_r;
+}
+
+MACHINE_RESET( chwy )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 own PROM)\n"));
+ decocass_dongle_r = decocass_type1_latch_27_pass_3_inv_2_r;
+}
+
+MACHINE_RESET( clocknch )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 flip 2-3)\n"));
+ decocass_dongle_r = decocass_type1_latch_26_pass_3_inv_2_r;
+ type1_inmap = MAKE_MAP(0,1,3,2,4,5,6,7);
+ type1_outmap = MAKE_MAP(0,1,3,2,4,5,6,7);
+}
+
+MACHINE_RESET( ctisland )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 flip 0-2)\n"));
+ decocass_dongle_r = decocass_type1_latch_26_pass_3_inv_2_r;
+ type1_inmap = MAKE_MAP(2,1,0,3,4,5,6,7);
+ type1_outmap = MAKE_MAP(2,1,0,3,4,5,6,7);
+}
+
+MACHINE_RESET( csuperas )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 flip 4-5)\n"));
+ decocass_dongle_r = decocass_type1_latch_26_pass_3_inv_2_r;
+ type1_inmap = MAKE_MAP(0,1,2,3,5,4,6,7);
+ type1_outmap = MAKE_MAP(0,1,2,3,5,4,6,7);
+}
+
+MACHINE_RESET( castfant )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061)\n"));
+ decocass_dongle_r = decocass_type1_latch_16_pass_3_inv_1_r;
+}
+
+MACHINE_RESET( cluckypo )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 flip 1-3)\n"));
+ decocass_dongle_r = decocass_type1_latch_26_pass_3_inv_2_r;
+ type1_inmap = MAKE_MAP(0,3,2,1,4,5,6,7);
+ type1_outmap = MAKE_MAP(0,3,2,1,4,5,6,7);
+}
+
+MACHINE_RESET( cterrani )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 straight)\n"));
+ decocass_dongle_r = decocass_type1_latch_26_pass_3_inv_2_r;
+ type1_inmap = MAKE_MAP(0,1,2,3,4,5,6,7);
+ type1_outmap = MAKE_MAP(0,1,2,3,4,5,6,7);
+}
+
+MACHINE_RESET( cexplore )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 own PROM)\n"));
+ decocass_dongle_r = decocass_type1_latch_26_pass_5_inv_2_r;
+}
+
+MACHINE_RESET( cprogolf )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #1 (DE-0061 flip 0-1)\n"));
+ decocass_dongle_r = decocass_type1_latch_26_pass_3_inv_2_r;
+ type1_inmap = MAKE_MAP(1,0,2,3,4,5,6,7);
+ type1_outmap = MAKE_MAP(1,0,2,3,4,5,6,7);
+}
+
+MACHINE_RESET( cmissnx )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #2 (CS82-007)\n"));
+ decocass_dongle_r = decocass_type2_r;
+ decocass_dongle_w = decocass_type2_w;
+}
+
+MACHINE_RESET( cdiscon1 )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #2 (CS82-007)\n"));
+ decocass_dongle_r = decocass_type2_r;
+ decocass_dongle_w = decocass_type2_w;
+}
+
+MACHINE_RESET( cptennis )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #2 (CS82-007)\n"));
+ decocass_dongle_r = decocass_type2_r;
+ decocass_dongle_w = decocass_type2_w;
+}
+
+MACHINE_RESET( ctornado )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #2 (CS82-007)\n"));
+ decocass_dongle_r = decocass_type2_r;
+ decocass_dongle_w = decocass_type2_w;
+}
+
+MACHINE_RESET( cbnj )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_67;
+}
+
+MACHINE_RESET( cburnrub )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_67;
+}
+
+MACHINE_RESET( cbtime )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_12;
+}
+
+MACHINE_RESET( cgraplop )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_56;
+}
+
+MACHINE_RESET( cgraplp2 )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_67;
+}
+
+MACHINE_RESET( clapapa )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_34_7;
+}
+
+MACHINE_RESET( cfghtice )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_25;
+}
+
+MACHINE_RESET( cprobowl )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_34_0;
+}
+
+MACHINE_RESET( cnightst )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_13;
+}
+
+MACHINE_RESET( cprosocc )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_24;
+}
+
+MACHINE_RESET( cppicf )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_01;
+}
+
+MACHINE_RESET( cscrtry )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #4 (32K ROM)\n"));
+ decocass_dongle_r = decocass_type4_r;
+ decocass_dongle_w = decocass_type4_w;
+}
+
+MACHINE_RESET( cbdash )
+{
+ decocass_init_common();
+ LOG(0,("dongle type #5 (NOP)\n"));
+ decocass_dongle_r = decocass_type5_r;
+ decocass_dongle_w = decocass_type5_w;
+}
+
+MACHINE_RESET( cflyball )
+{
+ decocass_init_common();
+ LOG(0,("no dongle\n"));
+ decocass_dongle_r = decocass_nodong_r;
+}
+
+MACHINE_RESET( czeroize )
+{
+ UINT8 *mem = memory_region(REGION_USER1);
+ decocass_init_common();
+ LOG(0,("dongle type #3 (PAL)\n"));
+ decocass_dongle_r = decocass_type3_r;
+ decocass_dongle_w = decocass_type3_w;
+ type3_swap = TYPE3_SWAP_23_56;
+
+ /*
+ * FIXME: remove if the original ROM is available.
+ * The Zeroize 6502 code at 0x3707 issues LODCTRS with 0x8a,
+ * and expects to read 0x18 from 0x08a0 ff. within 7 bytes.
+ * This hack seems to be sufficient to get around
+ * the missing dongle ROM contents and play the game.
+ */
+ memset(mem,0x00,0x1000);
+ mem[0x08a0] = 0x18;
+}
+
+/***************************************************************************
+ *
+ * 8041 port handlers
+ *
+ ***************************************************************************/
+
+static void tape_stop(void)
+{
+ /* remember time */
+ tape_time0 = decocass_adjust_tape_time(tape_time0);
+
+ timer_adjust(tape_timer, attotime_never, 0, attotime_never);
+}
+
+
+WRITE8_HANDLER( i8041_p1_w )
+{
+ static int i8041_p1_old;
+
+ if (data != i8041_p1_old)
+ {
+ LOG(4,("%9.7f 8041-PC: %03x i8041_p1_w: $%02x (%s%s%s%s%s%s%s%s)\n",
+ attotime_to_double(timer_get_time()),
+ activecpu_get_previouspc(),
+ data,
+ data & 0x01 ? "" : "DATA-WRT",
+ data & 0x02 ? "" : " DATA-CLK",
+ data & 0x04 ? "" : " FAST",
+ data & 0x08 ? "" : " BIT3",
+ data & 0x10 ? "" : " REW",
+ data & 0x20 ? "" : " FWD",
+ data & 0x40 ? "" : " WREN",
+ data & 0x80 ? "" : " REQ"));
+ i8041_p1_old = data;
+ }
+
+ /* change in REW signal ? */
+ if ((data ^ i8041_p1) & 0x10)
+ {
+ tape_stop();
+ if (0 == (data & 0x10))
+ {
+ LOG(2,("tape %5.4fs: rewind\n", attotime_to_double(tape_time0)));
+ tape_dir = -1;
+ timer_adjust(tape_timer, attotime_never, 0, attotime_never);
+ set_led_status(0, 1);
+ }
+ else
+ {
+ tape_dir = 0;
+ tape_speed = 0;
+ LOG(2,("tape %5.4fs: stopped\n", attotime_to_double(tape_time0)));
+#if TAPE_UI_DISPLAY
+ popmessage(" [%05.1fs] ", attotime_to_double(tape_time0));
+#endif
+ set_led_status(0, 0);
+ }
+ }
+
+ /* change in FWD signal ? */
+ if ((data ^ i8041_p1) & 0x20)
+ {
+ tape_stop();
+ if (0 == (data & 0x20))
+ {
+ LOG(2,("tape %5.4fs: forward\n", attotime_to_double(tape_time0)));
+ tape_dir = +1;
+ timer_adjust(tape_timer, attotime_never, 0, attotime_never);
+ set_led_status(0, 1);
+ }
+ else
+ {
+ tape_dir = 0;
+ tape_speed = 0;
+ LOG(2,("tape %5.4fs: stopped\n", attotime_to_double(tape_time0)));
+#if TAPE_UI_DISPLAY
+ popmessage(" [%05.1fs] ", attotime_to_double(tape_time0));
+#endif
+ set_led_status(0, 0);
+ }
+ }
+
+ /* change in FAST signal ? */
+ if (tape_timer && (data ^ i8041_p1) & 0x04)
+ {
+ tape_stop();
+ tape_speed = (0 == (data & 0x04)) ? 1 : 0;
+
+ if (tape_dir < 0)
+ {
+ LOG(2,("tape: fast rewind %s\n", (0 == (data & 0x04)) ? "on" : "off"));
+ tape_dir = (tape_speed) ? -7 : -1;
+ timer_adjust(tape_timer, attotime_never, 0, attotime_never);
+ }
+ else
+ if (tape_dir > 0)
+ {
+ LOG(2,("tape: fast forward %s\n", (0 == (data & 0x04)) ? "on" : "off"));
+ tape_dir = (tape_speed) ? +7 : +1;
+ timer_adjust(tape_timer, attotime_never, 0, attotime_never);
+ }
+ }
+
+ i8041_p1 = data;
+}
+
+READ8_HANDLER( i8041_p1_r )
+{
+ UINT8 data = i8041_p1;
+ static int i8041_p1_old;
+
+ if (data != i8041_p1_old)
+ {
+ LOG(4,("%9.7f 8041-PC: %03x i8041_p1_r: $%02x (%s%s%s%s%s%s%s%s)\n",
+ attotime_to_double(timer_get_time()),
+ activecpu_get_previouspc(),
+ data,
+ data & 0x01 ? "" : "DATA-WRT",
+ data & 0x02 ? "" : " DATA-CLK",
+ data & 0x04 ? "" : " FAST",
+ data & 0x08 ? "" : " BIT3",
+ data & 0x10 ? "" : " REW",
+ data & 0x20 ? "" : " FWD",
+ data & 0x40 ? "" : " WREN",
+ data & 0x80 ? "" : " REQ"));
+ i8041_p1_old = data;
+ }
+ return data;
+}
+
+WRITE8_HANDLER( i8041_p2_w )
+{
+ static int i8041_p2_old;
+
+ if (data != i8041_p2_old)
+ {
+ LOG(4,("%9.7f 8041-PC: %03x i8041_p2_w: $%02x (%s%s%s%s%s%s%s%s)\n",
+ attotime_to_double(timer_get_time()),
+ activecpu_get_previouspc(),
+ data,
+ data & 0x01 ? "" : "FNO/",
+ data & 0x02 ? "" : " EOT/",
+ data & 0x04 ? "" : " ERR/",
+ data & 0x08 ? "" : " OUT3?/",
+ data & 0x10 ? " [IN4]" : "",
+ data & 0x20 ? " [BOT-EOT]" : "",
+ data & 0x40 ? " [RCLK]" : "",
+ data & 0x80 ? " [RDATA]" : ""));
+ i8041_p2_old = data;
+ }
+ i8041_p2 = data;
+}
+
+READ8_HANDLER( i8041_p2_r )
+{
+ UINT8 data;
+ static int i8041_p2_old;
+
+ tape_update();
+
+ data = i8041_p2;
+
+ if (data != i8041_p2_old)
+ {
+ LOG(4,("%9.7f 8041-PC: %03x i8041_p2_r: $%02x (%s%s%s%s%s%s%s%s)\n",
+ attotime_to_double(timer_get_time()),
+ activecpu_get_previouspc(),
+ data,
+ data & 0x01 ? "" : "FNO/",
+ data & 0x02 ? "" : " EOT/",
+ data & 0x04 ? "" : " ERR/",
+ data & 0x08 ? "" : " OUT3?/",
+ data & 0x10 ? " [IN4]" : "",
+ data & 0x20 ? " [BOT-EOT]" : "",
+ data & 0x40 ? " [RCLK]" : "",
+ data & 0x80 ? " [RDATA]" : ""));
+ i8041_p2_old = data;
+ }
+ return data;
+}
+
+
diff --git a/src/mame/machine/decocass.h b/src/mame/machine/decocass.h
new file mode 100644
index 00000000000..d6429e8a22e
--- /dev/null
+++ b/src/mame/machine/decocass.h
@@ -0,0 +1,113 @@
+/* Set this to 1 to display current tape position */
+#define TAPE_UI_DISPLAY 0
+
+#ifdef MAME_DEBUG
+#define LOGLEVEL 3
+#define LOG(n,x) if (LOGLEVEL >= n) logerror x
+#else
+#define LOG(n,x)
+#endif
+
+extern WRITE8_HANDLER( decocass_coin_counter_w );
+extern WRITE8_HANDLER( decocass_sound_command_w );
+extern READ8_HANDLER( decocass_sound_data_r );
+extern READ8_HANDLER( decocass_sound_ack_r );
+extern WRITE8_HANDLER( decocass_sound_data_w );
+extern READ8_HANDLER( decocass_sound_command_r );
+extern WRITE8_HANDLER( decocass_sound_nmi_enable_w );
+extern READ8_HANDLER( decocass_sound_nmi_enable_r );
+extern READ8_HANDLER( decocass_sound_data_ack_reset_r );
+extern WRITE8_HANDLER( decocass_sound_data_ack_reset_w );
+extern WRITE8_HANDLER( decocass_nmi_reset_w );
+extern WRITE8_HANDLER( decocass_quadrature_decoder_reset_w );
+extern WRITE8_HANDLER( decocass_adc_w );
+extern READ8_HANDLER( decocass_input_r );
+extern int tape_dir;
+extern int tape_speed;
+extern attotime tape_time0;
+extern emu_timer *tape_timer;
+attotime decocass_adjust_tape_time(attotime tape_time);
+
+extern WRITE8_HANDLER( decocass_reset_w );
+
+extern READ8_HANDLER( decocass_e5xx_r );
+extern WRITE8_HANDLER( decocass_e5xx_w );
+extern WRITE8_HANDLER( decocass_de0091_w );
+extern WRITE8_HANDLER( decocass_e900_w );
+
+extern MACHINE_RESET( decocass );
+extern MACHINE_RESET( ctsttape );
+extern MACHINE_RESET( chwy );
+extern MACHINE_RESET( clocknch );
+extern MACHINE_RESET( ctisland );
+extern MACHINE_RESET( csuperas );
+extern MACHINE_RESET( castfant );
+extern MACHINE_RESET( cluckypo );
+extern MACHINE_RESET( cterrani );
+extern MACHINE_RESET( cexplore );
+extern MACHINE_RESET( cprogolf );
+extern MACHINE_RESET( cmissnx );
+extern MACHINE_RESET( cdiscon1 );
+extern MACHINE_RESET( cptennis );
+extern MACHINE_RESET( ctornado );
+extern MACHINE_RESET( cbnj );
+extern MACHINE_RESET( cburnrub );
+extern MACHINE_RESET( cbtime );
+extern MACHINE_RESET( cgraplop );
+extern MACHINE_RESET( cgraplp2 );
+extern MACHINE_RESET( clapapa );
+extern MACHINE_RESET( cfghtice );
+extern MACHINE_RESET( cprobowl );
+extern MACHINE_RESET( cnightst );
+extern MACHINE_RESET( cprosocc );
+extern MACHINE_RESET( cppicf );
+extern MACHINE_RESET( cscrtry );
+extern MACHINE_RESET( cflyball );
+extern MACHINE_RESET( cbdash );
+extern MACHINE_RESET( czeroize );
+
+extern WRITE8_HANDLER( i8041_p1_w );
+extern READ8_HANDLER( i8041_p1_r );
+extern WRITE8_HANDLER( i8041_p2_w );
+extern READ8_HANDLER( i8041_p2_r );
+
+void decocass_machine_state_save_init(void);
+
+/*----------- defined in video/decocass.c -----------*/
+extern WRITE8_HANDLER( decocass_paletteram_w );
+extern WRITE8_HANDLER( decocass_charram_w );
+extern WRITE8_HANDLER( decocass_fgvideoram_w );
+extern WRITE8_HANDLER( decocass_colorram_w );
+extern WRITE8_HANDLER( decocass_bgvideoram_w );
+extern WRITE8_HANDLER( decocass_tileram_w );
+extern WRITE8_HANDLER( decocass_objectram_w );
+
+extern WRITE8_HANDLER( decocass_watchdog_count_w );
+extern WRITE8_HANDLER( decocass_watchdog_flip_w );
+extern WRITE8_HANDLER( decocass_color_missiles_w );
+extern WRITE8_HANDLER( decocass_mode_set_w );
+extern WRITE8_HANDLER( decocass_color_center_bot_w );
+extern WRITE8_HANDLER( decocass_back_h_shift_w );
+extern WRITE8_HANDLER( decocass_back_vl_shift_w );
+extern WRITE8_HANDLER( decocass_back_vr_shift_w );
+extern WRITE8_HANDLER( decocass_part_h_shift_w );
+extern WRITE8_HANDLER( decocass_part_v_shift_w );
+extern WRITE8_HANDLER( decocass_center_h_shift_space_w );
+extern WRITE8_HANDLER( decocass_center_v_shift_w );
+
+extern VIDEO_START( decocass );
+extern VIDEO_UPDATE( decocass );
+
+extern UINT8 *decocass_charram;
+extern UINT8 *decocass_fgvideoram;
+extern UINT8 *decocass_colorram;
+extern UINT8 *decocass_bgvideoram;
+extern UINT8 *decocass_tileram;
+extern UINT8 *decocass_objectram;
+extern size_t decocass_fgvideoram_size;
+extern size_t decocass_colorram_size;
+extern size_t decocass_bgvideoram_size;
+extern size_t decocass_tileram_size;
+extern size_t decocass_objectram_size;
+
+void decocass_video_state_save_init(void);
diff --git a/src/mame/machine/decocrpt.c b/src/mame/machine/decocrpt.c
new file mode 100644
index 00000000000..c482017d344
--- /dev/null
+++ b/src/mame/machine/decocrpt.c
@@ -0,0 +1,670 @@
+/*******************************************************************************
+
+Data East gfx encryption emulation by Nicola Salmoria
+
+Most Data East games from 1991 onwards use this encryption scheme for graphics.
+
+It works on blocks of 0x800 16-bit words (256 8x8 tiles, or 64 16x16 tiles), and
+consists of three steps:
+
+1) scramble the offset within the block. Every word can go everywhere, there doesn't
+ seem to be any regularity.
+2) XOR with one of 16 masks. The mask to use depends on the offset within the block,
+ there doesn't seem to be any regularity.
+ The masks are hardcoded (don't change from game to game).
+3) scramble the bits inside the word, using one of 8 patterns. The pattern to use
+ depends on the offset within the block, there doesn't seem to be any regularity.
+ The patterns are hardcoded (don't change from game to game).
+ Note that bits 0-7 and 8-15 are not mixed by the scrambling, suggesting that the
+ chip might actually work on one byte at a time.
+
+Luckily, only two different encryption tables have been found so far.
+
+Table 1 (custom chip 56/141)
+------------------------
+Mutant Fighter 1991
+Rohga Armour Attack 1991
+Captain America 1991
+Tumble Pop 1991
+Diet GoGo 1993
+Double Wing 1993
+Night Slashers 1993
+Joe & Mac Return 1994
+Ganbare! Gonta!! 2 1995
+Chain Reaction 1994
+
+Table 2 (custom chip 74)
+------------------------
+Wizard's Fire 1992
+Funky Jet 1992
+Sotsugyo Shousho 1995
+
+*******************************************************************************/
+
+#include "driver.h"
+#include "decocrpt.h"
+
+static const UINT16 xor_masks[16] =
+{
+ 0xd556,0x73cb,0x2963,0x4b9a,0xb3bc,0xbc73,0xcbc9,0xaeb5,
+ 0x1e6d,0xd5b5,0xe676,0x5cc5,0x395a,0xdaae,0x2629,0xe59e,
+};
+
+static const UINT8 swap_patterns[8][16] =
+{
+ { 0xf,0x8,0x9,0xc,0xa,0xd,0xb,0xe, 0x2,0x7,0x4,0x3,0x1,0x5,0x6,0x0 },
+ { 0xc,0xa,0xb,0x9,0x8,0xf,0xe,0xd, 0x6,0x0,0x3,0x5,0x7,0x4,0x2,0x1 },
+ { 0x8,0xc,0xb,0x9,0xd,0xe,0xf,0xa, 0x4,0x6,0x5,0x0,0x3,0x1,0x7,0x2 },
+ { 0x8,0x9,0xa,0xd,0xb,0xf,0xe,0xc, 0x5,0x4,0x0,0x7,0x2,0x6,0x1,0x3 },
+ { 0xc,0xd,0xe,0xf,0x8,0x9,0xa,0xb, 0x1,0x5,0x0,0x3,0x2,0x7,0x6,0x4 },
+ { 0xe,0xf,0xd,0x8,0xc,0xa,0xb,0x9, 0x1,0x2,0x7,0x6,0x4,0x3,0x0,0x5 },
+ { 0xd,0xe,0xa,0xb,0x9,0x8,0xc,0xf, 0x3,0x1,0x7,0x4,0x5,0x0,0x2,0x6 },
+ { 0x9,0x8,0xe,0xa,0xf,0xb,0xd,0xc, 0x6,0x0,0x5,0x2,0x4,0x1,0x3,0x7 },
+};
+
+static const UINT8 deco56_xor_table[0x800] =
+{
+ 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9,10, 7,11,11, 9,11, 3, 7,10,12,13, 3,14, 0, 0, 9, 0,15, 3, 4,14,
+ 6, 3,14,14, 3,12, 3,13, 9, 5,13, 3, 8, 2, 7,14, 2, 5, 1, 2, 3, 4,14,11, 8, 0, 6, 7,10, 3, 4, 7,
+ 15, 1, 2, 7, 7,14,15, 0, 7, 9,15, 3,14,10, 9,12,11,12, 2, 8, 1,10, 9,14, 5, 6,15,10, 4,15, 5, 2,
+ 3, 2, 4,15, 7, 7,10,13, 1,13, 6, 6, 7, 5,10, 9, 5,15,14, 2, 7,12, 7, 4, 2,15,12,10,11,15, 4, 6,
+ 9, 3,11,13, 0, 3, 6, 4,15, 8, 3, 8, 0, 3,13, 8, 6, 0,11, 4, 9, 7,11, 1, 8, 1,10, 9, 2, 8,11,15,
+ 2, 8,10, 5, 3, 8, 0,10, 0,15, 3, 1,15, 3, 8, 6,13,11,10, 4,15, 4, 4, 3, 7, 7,15, 3,11,15,15, 2,
+ 3, 7,13, 4,10,12, 9, 8,11, 2, 5, 8, 7, 4,14, 0,12, 1,15,10, 3,10, 5,13, 1, 4, 0, 7, 7, 2, 8,15,
+ 12, 1, 9,14,12, 9,11, 5,13, 1,12,12,14, 8, 8,13, 4,13, 1,12,10, 1,10,15, 7, 5, 1,13,10,10,15, 1,
+ 3,14,13, 0, 0, 1, 3, 9, 5, 0, 4,13, 6,14, 2, 8, 3, 3, 5, 8, 1,10, 7, 5,13, 4, 2,12, 5, 1, 0, 4,
+ 4, 6,14,10, 6, 3,11,10, 0,10, 2, 3,11,11,15,13, 3,10, 3, 8, 3, 4, 7, 1, 5, 3, 9, 8,14,13,13, 4,
+ 1, 0, 1,12,12,12,11,11, 3, 7, 4,10,10, 3,10, 3, 1, 7, 4, 6, 2,12, 3, 3, 0, 0,10, 0, 6, 8, 0, 7,
+ 2,15,10,14, 1,14, 4,12, 4, 2, 3, 4, 8, 0,10,10,15, 1, 8, 4,11, 2,12, 6,12,12,12, 2, 4, 6, 3,12,
+ 4, 7,14,11,10, 6,13, 3, 4,14, 7, 5, 7, 5,10, 8, 5, 0, 7,12, 3, 7,14, 3, 3, 8, 0, 7, 6, 9,11,15,
+ 10,15, 9, 7, 0,13, 7, 3, 7, 4,10, 1, 7, 4, 3,15, 2, 6, 1,14,12,12,10,10, 1,11,15, 0,10, 7,12,15,
+ 8,10, 2,14,11, 0,10,12,13,15,12,15, 8,11, 5, 3, 0, 7,10, 6, 1, 9,11, 8, 4, 2, 4,12, 6, 3,15, 3,
+ 2, 1,10, 2, 2, 7,10, 6,11,12, 6, 2,11, 7,15, 1,13, 9,12, 3, 9,12, 2,12, 6, 5,11, 8, 0, 7,14,10,
+ 7, 8, 6, 5,12, 4, 1,12,12,13, 8, 4, 8,12, 8, 2, 1,15,13,14, 8, 6,11, 2,13, 5, 6,10, 9, 5, 7,11,
+ 5,11,13, 2, 0, 8, 2,10, 2, 1, 6, 4, 8,14, 0, 4, 8,11, 8,15,12, 0,15, 6, 1,13,15,10, 3,13,14,13,
+ 4, 5,12, 4, 3, 8, 9,15,13,11, 4, 8,10, 7,12, 7, 7, 9, 7,11,13, 0,15, 5,11, 5, 6, 2, 5, 1, 9, 2,
+ 9,15, 9, 8,14, 6,11, 7,10, 4,14,12, 3,12, 3, 0, 4, 8,11, 9, 5, 7,14, 1,10, 3, 2,12,12,10,12, 8,
+ 4, 5,10,13,11, 6,14, 4,13,14, 8, 3,10, 5, 6, 4, 4,10, 6, 5,12,11,10, 5, 9, 6, 7, 6, 4, 6, 3,15,
+ 5,14,14,13, 7, 6,12,13,15, 5,15,10, 2, 1,15, 3,10,15, 7, 4, 5, 2,10,15,14,15, 1,13,12, 9, 8,14,
+ 15, 3, 4, 1, 9,13,13, 3,12,15, 8,15, 7, 1,10,12,10, 9,12,10,14, 6, 5, 5, 4, 0,12,14,15, 6, 5, 5,
+ 2,14, 2, 6,14, 2,12, 7, 5, 1, 2, 3, 2,12,15, 4,10, 5,10,13, 0, 2, 2, 1, 5, 7, 5, 2, 0,13, 0, 4,
+ 13,13, 9,12, 5, 5,10,15, 6,11, 5, 2,11, 8, 0, 6, 9,13, 2, 6, 1,11, 5, 1,12, 8, 4, 7, 9,13, 4, 4,
+ 15, 3, 4, 5, 5, 0, 9, 4,10, 8, 1, 0,13, 8, 6,12,15,15,10, 7,10, 2, 6, 1, 4, 0, 2, 8, 3,10, 2,12,
+ 4, 1,12,15, 0, 1,10, 0,10,11, 6, 1, 0, 3, 2, 3, 4, 4, 9,14, 7, 3,13, 7,13, 9,14,12,10, 5, 4,14,
+ 0, 5,15, 8,12,12, 0, 5,11,15, 8, 7,15, 5,12, 5, 5, 3, 6,13,15,15, 7, 0, 3, 9, 1, 5, 7, 7,12, 5,
+ 3,12,10,11, 2,11, 5,10, 1, 3, 6, 2, 7, 1, 3, 0, 6, 8,12,15,14, 6,10,13, 9, 1,15, 4, 6,13,14, 7,
+ 2,13,12, 9, 4, 7, 9, 9, 6,10, 6,15,15, 2, 0, 4,12,12,10, 2, 7, 4,14,10, 2, 6, 5,12, 0,14, 1,15,
+ 13, 1, 4,13, 3,13, 6,15,11,15, 0,13,12, 5, 4,11,14,15, 6,13, 6, 7, 2, 2, 7,11, 6, 7,15, 0,13,10,
+ 6,14, 9,13,12,14, 4, 8, 5,13, 3,14, 6, 6,13, 8, 7, 7, 5, 8,12, 2, 6, 0, 6, 8, 2,13, 9,14, 3,15,
+ 1, 4,13, 3, 6, 8,15, 4, 8, 7, 4,10, 0, 9, 2,15, 2, 1, 3, 3, 1, 4, 0, 3, 1, 8, 5, 0,10, 0, 1, 6,
+ 11, 3,12, 0,14,11, 0, 5,15, 9, 1, 7,15,12,12,10, 2, 2, 3,15,13,13, 2,13,14,13,13, 8,11,10, 9, 9,
+ 9, 7, 7, 4, 9, 1, 9,10, 9, 9, 9,15,13,14,12,13, 6,11, 4, 6, 9,14, 6, 6, 7, 0, 8, 6,10, 7, 9,13,
+ 4, 8, 1, 8, 9, 9, 3,14,10,14,11, 7,15, 8,13,11, 9, 0, 5, 4, 4, 7, 6, 0,13, 9,13, 7, 9, 3, 2, 0,
+ 7,11, 5, 8, 8, 0,10, 3, 1, 4, 2,15,12, 5, 2, 6,15, 5,13, 6,12, 8,10, 9,12, 9, 1, 2,15,14, 5,11,
+ 13, 3, 6, 8,15, 5, 8, 2,10, 2, 8,14,15, 5, 4, 0,10, 2,14,14, 8, 8, 9, 9,11,11,12,11, 5, 4, 2,12,
+ 15,12, 1,11, 5,13, 0,12, 2, 4, 0, 0,12,12, 4,15, 7, 1, 2,13,10,10, 6, 4, 8, 6, 0,14,13, 1, 8, 3,
+ 10, 9,11,12, 6, 0,11,14, 1,13, 7, 4,11, 3,10, 0, 2,10,14,13, 7, 8,10, 7, 7,12,10,11, 3, 9,13, 8,
+ 0,10,10,13, 7,12, 8, 8, 5,15,10,15, 7, 1, 8, 2,12, 1,14,10,10, 4, 5, 7,11, 3, 7, 7, 1,12,12,12,
+ 1,14, 4, 0,11,15, 8,10, 1,14, 2,11, 5, 5,10,12, 2, 2, 1, 0,10, 0, 6, 2,10,13, 1,11,14, 0,12,11,
+ 8, 8,12, 4, 5, 5,14,14, 9, 8, 0,10, 1, 9,15,10,13, 5, 2, 7, 1, 2, 6, 5, 5,11, 0,13, 8, 0, 7, 2,
+ 15,11,15, 0, 5,15, 5, 6, 0, 2, 5, 3, 0,14,14, 4,11, 7, 7, 4,10,11, 1, 8,13, 9, 4,13, 3, 6, 1,10,
+ 1, 0,15,15,12,10, 6,11, 3, 4, 7, 8, 7,14, 8, 7,12,15, 9, 8, 7,14,14, 9,15, 8, 9, 4,12, 3,12,12,
+ 7, 8,11, 2, 4, 8, 4, 9, 4,11,15, 2,13, 6, 3,13, 1,13, 5, 0, 2,10, 5, 8, 1,13,14, 0,11,15, 8,12,
+ 10, 4, 5,10, 4,11,11, 2, 2,13, 2, 6, 0, 7, 4,11, 1,12, 6,13,14, 5, 9, 0, 5,13,14, 6,13, 3,13, 9,
+ 14,14, 0, 9,12,14, 9,10, 1, 2,12, 3, 3,15, 8, 4, 3, 1,13,13,13,13, 4, 3, 5,15, 8, 2,15,13,11, 7,
+ 4, 0,15,14, 1,13, 6, 8, 2, 8, 7,14,11, 7, 4, 1, 8,12,13,11, 0, 9, 0, 3,12,11, 2, 3, 9, 1, 3,13,
+ 4, 5,15,10, 5, 9, 0, 3, 9, 6,13, 7,15,13,11,13,12, 6,14,15, 3, 6,10, 3,11,10, 1, 4,13, 0,15,15,
+ 11, 0, 7,14, 9,15, 1,14, 2,13, 7,12,11, 7, 9, 6,11, 5,12, 4, 3, 6, 8, 3, 9, 0,15, 7, 1,11, 7,12,
+ 2,13,13, 3, 0,11, 1,11, 6, 1, 5, 5, 4, 5,12, 3, 3,15, 3,10, 7,12,15, 0,13,10, 0, 2, 6,12, 9, 5,
+ 3, 0, 0, 6, 3,13, 7,14,11,15, 7, 2, 2,11, 6,11, 9, 3,10,11, 1, 8, 1,13, 0,11, 2,10, 3,12, 4,11,
+ 0, 0,10,10, 2, 3,15, 0, 0, 9,14, 5,14,10,14, 0,13, 1, 1,12, 3, 3, 1,15, 8, 8,11,13, 8, 4, 8, 5,
+ 8, 7,13, 2, 1, 1,14,15, 1, 7, 7, 1,14, 1, 4,14, 0, 0, 7, 6, 5,11, 5, 8, 7, 1, 4, 3, 8,14, 5,11,
+ 13, 8, 1, 9, 6,12, 9, 6, 3, 3,11,12, 5,11, 4, 4, 3,11, 0, 0,10,10, 7,15,15,11, 1,11,13,11, 6, 8,
+ 2,15,10, 7, 0, 6, 3, 5, 2,14,12, 8,12,10,15, 8, 4,11, 8,13,11, 2, 5,13,10, 5, 9,10,15, 6, 3,12,
+ 3, 0,11,15, 5,13,12,13,12, 0, 8,12,10, 0, 5, 5, 3, 2,10, 5, 3,10, 7, 2,13,12,15,13, 1,10, 4,10,
+ 12,14,12, 1, 6,13, 6, 6, 0,13,11, 4, 5, 7, 1, 7, 7, 0, 4,13,13,12,14, 6, 1, 3,13,11, 1, 4, 9, 9,
+ 2,12, 8, 5,10,15, 2, 0,14, 9, 5, 8,11, 5, 3, 4, 7, 1, 2,13, 3, 8, 1, 3,11,12,11, 5, 1, 5,10,12,
+ 10, 2,10,13,12, 3, 9, 2,12,14,13, 8, 2, 1, 5, 3,15, 2, 8, 2, 1,15,10, 6,10, 3, 8, 9, 6, 9, 2,10,
+ 4,12,10,15,14,15, 1,15, 0,13, 6, 0, 5, 6,13,12, 2,14, 0,10, 6,15, 8, 8, 6, 8, 2,12,11, 3, 9, 5,
+ 9,15,11, 3,11,14,15, 6,14, 6, 7,12, 7,10, 6,14, 6, 6, 3, 5, 9,14, 7, 5, 8, 6, 2,12,15, 1, 2, 4,
+ 11, 6, 3, 0, 5,11,14,14,14, 4,13, 6,11, 6, 4,12,15, 2, 4, 1, 1, 5, 1,15, 7, 0, 5, 0, 0, 0,12, 1,
+};
+
+static const UINT16 deco56_address_table[0x800] =
+{
+ 0x527,0x1a1,0x2f6,0x523,0x297,0x005,0x141,0x3b4,0x539,0x794,0x6dd,0x498,0x59b,0x119,0x5db,0x631,
+ 0x2f1,0x565,0x409,0x158,0x2d6,0x16e,0x571,0x0b9,0x543,0x52b,0x668,0x0c0,0x5fd,0x216,0x5ea,0x24e,
+ 0x14b,0x09b,0x6d1,0x2f5,0x591,0x0b4,0x0a8,0x64a,0x39b,0x0d9,0x336,0x2a1,0x460,0x068,0x7b4,0x187,
+ 0x59a,0x2f0,0x5cd,0x181,0x7f7,0x733,0x223,0x581,0x4c5,0x1d4,0x11b,0x22a,0x688,0x738,0x130,0x202,
+ 0x12e,0x203,0x33e,0x4d0,0x2bd,0x0c4,0x042,0x614,0x6c2,0x385,0x3ed,0x7e2,0x2bb,0x2ef,0x3e1,0x654,
+ 0x73f,0x447,0x15f,0x41d,0x320,0x05a,0x2f4,0x116,0x1d6,0x0c2,0x4c1,0x0f3,0x694,0x28f,0x15c,0x125,
+ 0x343,0x291,0x33b,0x21e,0x031,0x4fa,0x76b,0x133,0x503,0x4e8,0x19c,0x3c6,0x24a,0x0b5,0x1df,0x71e,
+ 0x5ed,0x564,0x648,0x5d7,0x5c2,0x4a4,0x30e,0x750,0x474,0x11f,0x4a2,0x3bb,0x64c,0x258,0x4c7,0x586,
+ 0x071,0x362,0x593,0x252,0x2b0,0x5aa,0x053,0x047,0x6ef,0x669,0x6e8,0x011,0x093,0x443,0x33c,0x060,
+ 0x211,0x7d3,0x4c8,0x426,0x1c1,0x2e8,0x1fb,0x51a,0x402,0x49f,0x519,0x1c7,0x096,0x4e6,0x279,0x455,
+ 0x7ac,0x3a6,0x4af,0x736,0x1cb,0x45c,0x275,0x18c,0x776,0x6e0,0x5d4,0x59c,0x210,0x358,0x64f,0x2cf,
+ 0x0f4,0x307,0x577,0x7ba,0x296,0x0f6,0x1a3,0x09d,0x2c5,0x532,0x7bd,0x26c,0x171,0x727,0x5ba,0x2da,
+ 0x37b,0x707,0x366,0x10e,0x346,0x107,0x20a,0x4b1,0x12d,0x10b,0x603,0x788,0x2f7,0x6da,0x28b,0x08d,
+ 0x3ff,0x1e6,0x2a4,0x39f,0x454,0x112,0x2ec,0x441,0x0fa,0x054,0x3e5,0x3a2,0x1ec,0x322,0x53e,0x413,
+ 0x5b5,0x058,0x751,0x27a,0x3a7,0x2d1,0x16d,0x3f3,0x5f5,0x13e,0x122,0x1fe,0x069,0x7dd,0x213,0x424,
+ 0x36f,0x6f5,0x20e,0x431,0x5b2,0x25e,0x601,0x169,0x1a9,0x1cd,0x2e3,0x39e,0x338,0x7e5,0x5e5,0x7b1,
+ 0x3dc,0x464,0x065,0x255,0x246,0x71c,0x55c,0x3f7,0x5f6,0x0c8,0x1b4,0x148,0x284,0x69f,0x17f,0x4cd,
+ 0x6d4,0x63f,0x7ca,0x28a,0x75f,0x2df,0x708,0x442,0x00e,0x140,0x457,0x14f,0x63a,0x420,0x23e,0x672,
+ 0x440,0x716,0x3ca,0x1bb,0x622,0x367,0x018,0x109,0x3c1,0x206,0x7cb,0x42e,0x44c,0x613,0x61e,0x67c,
+ 0x396,0x06d,0x01b,0x0c9,0x40f,0x4b6,0x6b8,0x485,0x758,0x4d3,0x61b,0x34d,0x4fe,0x7a6,0x025,0x3eb,
+ 0x73a,0x79b,0x3db,0x312,0x190,0x35d,0x7b2,0x78b,0x248,0x010,0x075,0x12b,0x345,0x753,0x64b,0x163,
+ 0x374,0x557,0x4d8,0x25b,0x780,0x479,0x012,0x360,0x51c,0x3a1,0x0d0,0x020,0x137,0x5cf,0x7c5,0x189,
+ 0x679,0x352,0x7da,0x48a,0x18b,0x5fc,0x1fd,0x344,0x4dd,0x69e,0x761,0x542,0x65d,0x55b,0x755,0x4f9,
+ 0x427,0x501,0x329,0x6f2,0x2b4,0x1b6,0x319,0x459,0x3fb,0x6df,0x4ab,0x176,0x2fd,0x62f,0x1ca,0x1b3,
+ 0x1b7,0x2dc,0x674,0x56c,0x3ab,0x428,0x6c0,0x541,0x23d,0x283,0x6aa,0x5cb,0x231,0x713,0x014,0x79c,
+ 0x1af,0x3f2,0x32b,0x19b,0x0d2,0x25c,0x5be,0x1c5,0x383,0x50d,0x3e4,0x657,0x4bb,0x0e8,0x403,0x26b,
+ 0x14e,0x3b7,0x08f,0x31b,0x43f,0x375,0x2ca,0x6bc,0x678,0x13d,0x0e3,0x395,0x2ff,0x120,0x7eb,0x630,
+ 0x52d,0x369,0x36a,0x58c,0x538,0x04a,0x461,0x24f,0x717,0x73c,0x784,0x59f,0x0c3,0x340,0x476,0x207,
+ 0x6b7,0x31c,0x0da,0x729,0x2c0,0x7f0,0x3d5,0x67a,0x092,0x314,0x34f,0x2bc,0x6ee,0x32a,0x1a7,0x06b,
+ 0x40b,0x029,0x7fc,0x608,0x316,0x15a,0x113,0x3b8,0x22b,0x445,0x389,0x7a1,0x174,0x218,0x10d,0x29b,
+ 0x4a5,0x0e5,0x25f,0x250,0x75e,0x4c4,0x721,0x230,0x0d8,0x3c2,0x680,0x65f,0x25d,0x222,0x44d,0x57d,
+ 0x056,0x37f,0x4a9,0x30d,0x6de,0x7f5,0x423,0x2f9,0x3be,0x097,0x380,0x27c,0x5f1,0x2ba,0x1ea,0x2a5,
+ 0x162,0x0bd,0x4ff,0x5fa,0x3bf,0x01c,0x3ae,0x682,0x550,0x46a,0x13c,0x193,0x3cb,0x01e,0x6e9,0x03a,
+ 0x6d6,0x323,0x55a,0x74f,0x508,0x4f1,0x616,0x609,0x2b3,0x32c,0x0b7,0x584,0x77c,0x4c2,0x412,0x20d,
+ 0x21c,0x5f8,0x26f,0x69a,0x40d,0x50b,0x552,0x000,0x4e9,0x6e2,0x022,0x5d1,0x2f3,0x243,0x22d,0x706,
+ 0x304,0x76d,0x201,0x1e0,0x7be,0x3a9,0x074,0x1ac,0x57a,0x754,0x244,0x08a,0x425,0x561,0x6d3,0x48f,
+ 0x298,0x636,0x760,0x507,0x282,0x013,0x091,0x232,0x067,0x1ef,0x691,0x7e8,0x489,0x62e,0x289,0x487,
+ 0x3df,0x562,0x3e7,0x104,0x040,0x117,0x3d8,0x3f1,0x135,0x1b2,0x3cc,0x0e4,0x5e8,0x75c,0x595,0x2af,
+ 0x72f,0x361,0x0cf,0x5ca,0x3d1,0x049,0x002,0x347,0x287,0x337,0x799,0x404,0x7bc,0x0f1,0x101,0x467,
+ 0x1e2,0x544,0x095,0x37c,0x2fa,0x763,0x38f,0x376,0x722,0x035,0x2e1,0x28e,0x09e,0x4fb,0x26d,0x611,
+ 0x46c,0x5e7,0x563,0x6d2,0x724,0x2a0,0x475,0x24d,0x240,0x437,0x7c8,0x1dc,0x47a,0x356,0x72b,0x06a,
+ 0x765,0x499,0x1a8,0x7b0,0x73d,0x592,0x149,0x4cb,0x5a9,0x1e1,0x4ba,0x774,0x0b6,0x570,0x469,0x294,
+ 0x2d0,0x5df,0x5a3,0x16c,0x273,0x2b9,0x6c3,0x68a,0x5c6,0x041,0x768,0x4e3,0x0bc,0x077,0x21a,0x2db,
+ 0x0be,0x006,0x79a,0x17b,0x6ec,0x689,0x4b5,0x471,0x0f5,0x515,0x683,0x47d,0x576,0x5de,0x3b0,0x705,
+ 0x676,0x7d4,0x659,0x02c,0x49e,0x05e,0x02d,0x68c,0x3c8,0x4b9,0x5dd,0x390,0x0f0,0x42a,0x663,0x381,
+ 0x48b,0x06e,0x2be,0x0c7,0x42f,0x62c,0x568,0x5ee,0x212,0x559,0x3ec,0x3b9,0x180,0x4e2,0x1e9,0x303,
+ 0x446,0x387,0x6c9,0x52a,0x33d,0x7e4,0x325,0x5ff,0x554,0x290,0x675,0x7db,0x22f,0x578,0x5bf,0x3b6,
+ 0x4b7,0x7dc,0x5e2,0x18f,0x1ba,0x56a,0x78c,0x6af,0x5a2,0x749,0x4d6,0x208,0x400,0x43a,0x35f,0x286,
+ 0x251,0x332,0x030,0x6f6,0x0d3,0x786,0x3a5,0x214,0x087,0x667,0x378,0x29e,0x015,0x166,0x7ce,0x1f7,
+ 0x3e8,0x49c,0x787,0x6be,0x16f,0x0ba,0x7d6,0x458,0x488,0x783,0x7cf,0x588,0x5dc,0x6c4,0x70a,0x100,
+ 0x4fd,0x13a,0x078,0x715,0x1d2,0x633,0x32d,0x72a,0x6d5,0x6fd,0x78f,0x3d2,0x2c3,0x03e,0x17e,0x505,
+ 0x583,0x326,0x2ea,0x51b,0x44a,0x04d,0x3d7,0x1e4,0x0ab,0x3e6,0x124,0x3b1,0x368,0x2c2,0x6c6,0x68e,
+ 0x4ee,0x1d5,0x00c,0x430,0x71a,0x651,0x22e,0x20f,0x4ec,0x08e,0x292,0x086,0x589,0x435,0x6db,0x567,
+ 0x769,0x4f6,0x599,0x038,0x36d,0x448,0x4f7,0x3fa,0x082,0x3c0,0x021,0x4bf,0x5b9,0x277,0x023,0x422,
+ 0x0c6,0x6ab,0x4e5,0x044,0x00f,0x23a,0x664,0x36b,0x6fb,0x462,0x3d4,0x5ec,0x439,0x604,0x04c,0x546,
+ 0x0a2,0x14c,0x436,0x128,0x063,0x735,0x7cc,0x410,0x105,0x4d1,0x655,0x1b5,0x3a4,0x6ba,0x04b,0x634,
+ 0x7c6,0x1ce,0x3ef,0x11a,0x066,0x433,0x767,0x526,0x524,0x37a,0x5ad,0x0ec,0x4dc,0x38d,0x35b,0x4b2,
+ 0x54d,0x19d,0x172,0x495,0x692,0x545,0x6a8,0x5a0,0x164,0x407,0x742,0x145,0x1ab,0x7c4,0x285,0x299,
+ 0x1aa,0x66b,0x55d,0x594,0x69b,0x138,0x660,0x463,0x5b8,0x027,0x29d,0x57c,0x77a,0x481,0x797,0x7d9,
+ 0x732,0x7c1,0x6c1,0x416,0x701,0x78e,0x695,0x4a6,0x7ea,0x44f,0x7e6,0x106,0x5d9,0x57e,0x4f2,0x779,
+ 0x79f,0x509,0x2b5,0x22c,0x502,0x108,0x0b8,0x228,0x062,0x147,0x4fc,0x417,0x205,0x619,0x60b,0x308,
+ 0x7d7,0x1ee,0x555,0x0bf,0x398,0x04e,0x02e,0x061,0x4f3,0x699,0x182,0x48c,0x0e9,0x4b8,0x196,0x27e,
+ 0x1de,0x2b6,0x3d6,0x677,0x0d6,0x579,0x700,0x19a,0x3af,0x68d,0x51d,0x5d2,0x31e,0x4ae,0x617,0x1f8,
+ 0x47c,0x7b3,0x7e3,0x50f,0x470,0x3a3,0x6dc,0x0c1,0x46e,0x6b2,0x5ae,0x5e1,0x492,0x6b6,0x14d,0x178,
+ 0x1c9,0x798,0x781,0x0a5,0x23b,0x702,0x540,0x245,0x3d9,0x3b5,0x3ea,0x6ae,0x605,0x3de,0x0aa,0x179,
+ 0x2c9,0x2ae,0x0ee,0x6a0,0x262,0x4ac,0x0cc,0x60a,0x5b1,0x0cd,0x194,0x0ad,0x76c,0x73e,0x71d,0x5eb,
+ 0x7c0,0x486,0x0cb,0x200,0x551,0x1c6,0x3bc,0x686,0x696,0x12c,0x242,0x321,0x373,0x60f,0x635,0x56d,
+ 0x115,0x5e6,0x4da,0x704,0x48d,0x261,0x4f8,0x217,0x49a,0x6fa,0x085,0x56b,0x2ad,0x75a,0x5da,0x720,
+ 0x790,0x1f9,0x10f,0x55e,0x05d,0x21d,0x748,0x263,0x4d7,0x771,0x3bd,0x26e,0x07e,0x415,0x432,0x6eb,
+ 0x525,0x2ee,0x703,0x08b,0x274,0x310,0x533,0x1b0,0x21f,0x5f3,0x1b1,0x090,0x5a6,0x35e,0x7ad,0x6e5,
+ 0x330,0x4b0,0x175,0x4c6,0x70d,0x2d3,0x2b2,0x68b,0x5ef,0x650,0x003,0x081,0x1b9,0x46f,0x01f,0x026,
+ 0x7cd,0x2cb,0x642,0x0a6,0x764,0x7a3,0x58e,0x45a,0x63b,0x6ed,0x1db,0x5e4,0x78d,0x661,0x2e4,0x051,
+ 0x719,0x558,0x7fd,0x4d2,0x348,0x220,0x5e9,0x377,0x434,0x5d3,0x4a1,0x07a,0x301,0x7a9,0x33f,0x372,
+ 0x52e,0x582,0x70f,0x1d9,0x690,0x6f4,0x391,0x084,0x4a0,0x399,0x7af,0x6f0,0x5ac,0x7f6,0x1ae,0x392,
+ 0x77b,0x52c,0x7f9,0x2e7,0x0a9,0x5a7,0x3a0,0x6a1,0x5bc,0x6fc,0x32f,0x746,0x6bd,0x16b,0x42d,0x036,
+ 0x233,0x0f7,0x224,0x480,0x055,0x465,0x4aa,0x159,0x5fe,0x478,0x1c3,0x536,0x518,0x7c2,0x143,0x7e1,
+ 0x331,0x597,0x199,0x5ab,0x4d5,0x2de,0x0ed,0x0dc,0x317,0x229,0x4db,0x76e,0x351,0x5c1,0x618,0x684,
+ 0x54b,0x1f4,0x103,0x553,0x64e,0x2b1,0x271,0x775,0x1a5,0x239,0x521,0x51f,0x12f,0x418,0x466,0x134,
+ 0x468,0x0f9,0x15b,0x192,0x548,0x1bc,0x6b9,0x6e1,0x411,0x653,0x2c1,0x5f0,0x6cd,0x511,0x0af,0x7d1,
+ 0x5d6,0x5bd,0x3ad,0x34e,0x41a,0x0fd,0x4f4,0x33a,0x666,0x146,0x1dd,0x30f,0x5a8,0x254,0x69d,0x44e,
+ 0x42c,0x1f1,0x5fb,0x37d,0x3b2,0x080,0x7d8,0x2ac,0x221,0x1ad,0x66f,0x0eb,0x0e6,0x649,0x7fe,0x2a2,
+ 0x673,0x18e,0x535,0x5cc,0x644,0x293,0x65e,0x1f6,0x573,0x150,0x3da,0x237,0x238,0x3c3,0x45b,0x1f2,
+ 0x4d4,0x43d,0x1d0,0x63d,0x429,0x386,0x64d,0x46d,0x620,0x7ae,0x453,0x2c7,0x57b,0x697,0x6e7,0x2dd,
+ 0x5e3,0x09f,0x019,0x41b,0x6e3,0x43e,0x363,0x0db,0x62d,0x341,0x215,0x37e,0x3e9,0x1da,0x32e,0x647,
+ 0x21b,0x406,0x793,0x58f,0x560,0x0b2,0x569,0x607,0x2cd,0x640,0x38e,0x38a,0x388,0x4c9,0x652,0x185,
+ 0x219,0x7bf,0x7ab,0x1eb,0x472,0x4ad,0x226,0x2fe,0x53f,0x270,0x739,0x313,0x032,0x7f3,0x70c,0x3e0,
+ 0x2a9,0x259,0x5b7,0x08c,0x3c7,0x6ad,0x15d,0x2fb,0x10a,0x75d,0x66e,0x4e4,0x1fa,0x68f,0x643,0x2b8,
+ 0x6bf,0x497,0x6ff,0x405,0x490,0x170,0x50e,0x073,0x693,0x1d8,0x59d,0x53c,0x1e8,0x711,0x740,0x637,
+ 0x624,0x45e,0x483,0x6f3,0x09a,0x513,0x5bb,0x34c,0x414,0x54c,0x007,0x757,0x74a,0x2a3,0x355,0x017,
+ 0x72e,0x379,0x5a1,0x4a3,0x2c4,0x671,0x731,0x572,0x65c,0x5d0,0x034,0x1be,0x31f,0x300,0x7b8,0x2d2,
+ 0x0fe,0x57f,0x7fb,0x6a4,0x227,0x260,0x1c2,0x052,0x0ef,0x5ce,0x547,0x510,0x0f2,0x6ce,0x6ac,0x04f,
+ 0x2d7,0x0d5,0x5a5,0x29a,0x256,0x3ac,0x195,0x048,0x752,0x6d9,0x606,0x2e6,0x7ff,0x05c,0x3f6,0x0d4,
+ 0x623,0x602,0x5b3,0x58a,0x77e,0x6f8,0x3f5,0x698,0x587,0x78a,0x450,0x7c7,0x2e9,0x66c,0x49d,0x01d,
+ 0x2ce,0x046,0x1d1,0x357,0x628,0x718,0x0dd,0x13b,0x685,0x600,0x741,0x072,0x4eb,0x646,0x71f,0x165,
+ 0x05b,0x63e,0x043,0x136,0x66d,0x0fc,0x500,0x0f8,0x23f,0x31a,0x35a,0x7bb,0x45f,0x710,0x264,0x58d,
+ 0x2f2,0x079,0x656,0x154,0x444,0x03c,0x12a,0x7b9,0x60e,0x315,0x364,0x3f8,0x725,0x575,0x365,0x7aa,
+ 0x6e6,0x796,0x009,0x008,0x6a3,0x2ab,0x549,0x47b,0x2a7,0x778,0x730,0x627,0x7f2,0x743,0x3a8,0x39c,
+ 0x598,0x67f,0x1bd,0x65b,0x71b,0x615,0x6d8,0x27f,0x714,0x13f,0x7d0,0x0e0,0x126,0x118,0x2a6,0x7d2,
+ 0x4cf,0x2aa,0x60d,0x3dd,0x19f,0x24c,0x225,0x6a7,0x60c,0x7ee,0x6e4,0x41f,0x6ea,0x001,0x687,0x6cc,
+ 0x6f7,0x514,0x40c,0x4de,0x11c,0x39a,0x1e3,0x53d,0x327,0x050,0x276,0x632,0x11d,0x183,0x0c5,0x3fe,
+ 0x2a8,0x00b,0x30b,0x4f0,0x79d,0x257,0x3f0,0x15e,0x43c,0x6f1,0x110,0x596,0x2c6,0x5c5,0x0bb,0x318,
+ 0x77d,0x306,0x1cc,0x267,0x5b6,0x161,0x151,0x160,0x638,0x7f4,0x1d3,0x1e7,0x452,0x6b1,0x057,0x197,
+ 0x324,0x482,0x333,0x712,0x3ba,0x1a2,0x3f9,0x6ca,0x099,0x266,0x25a,0x17a,0x61d,0x1b8,0x556,0x4b3,
+ 0x6a6,0x0ac,0x67b,0x792,0x66a,0x0ca,0x098,0x74d,0x75b,0x522,0x629,0x512,0x53a,0x73b,0x529,0x156,
+ 0x65a,0x094,0x48e,0x737,0x123,0x129,0x1c0,0x18a,0x662,0x7ec,0x6cf,0x438,0x6cb,0x14a,0x4d9,0x728,
+ 0x534,0x658,0x06c,0x70b,0x184,0x3fc,0x46b,0x791,0x665,0x7df,0x744,0x3fd,0x3ee,0x0e1,0x394,0x56e,
+ 0x496,0x30a,0x7f1,0x55f,0x6a9,0x28d,0x770,0x2fc,0x41e,0x0ff,0x204,0x494,0x186,0x1c8,0x155,0x2eb,
+ 0x328,0x5d5,0x49b,0x50c,0x0e7,0x76a,0x235,0x47e,0x62a,0x0fb,0x3f4,0x7c9,0x280,0x4c3,0x7a4,0x756,
+ 0x0e2,0x5c3,0x24b,0x064,0x305,0x3e2,0x38b,0x7a8,0x31d,0x3d3,0x132,0x2ed,0x0b1,0x61f,0x02b,0x342,
+ 0x18d,0x00a,0x62b,0x4be,0x72c,0x1ff,0x5c7,0x7de,0x295,0x0b3,0x059,0x7d5,0x253,0x20b,0x1f5,0x5f7,
+ 0x27d,0x0a3,0x45d,0x7f8,0x1a0,0x088,0x43b,0x1ed,0x037,0x6f9,0x153,0x747,0x269,0x612,0x16a,0x265,
+ 0x370,0x574,0x504,0x354,0x7a7,0x2b7,0x2d9,0x54a,0x7a0,0x745,0x421,0x734,0x528,0x0d1,0x371,0x4cc,
+ 0x585,0x07b,0x477,0x58b,0x3cd,0x278,0x38c,0x03b,0x349,0x40a,0x7e7,0x6b4,0x6c5,0x19e,0x493,0x4e7,
+ 0x4a8,0x382,0x610,0x72d,0x566,0x36c,0x5c8,0x766,0x083,0x34b,0x789,0x7ed,0x0b0,0x173,0x139,0x144,
+ 0x28c,0x4e1,0x20c,0x3b3,0x41c,0x1bf,0x2e0,0x1a4,0x1f0,0x004,0x77f,0x7ef,0x114,0x63c,0x34a,0x27b,
+ 0x070,0x4e0,0x537,0x4b4,0x127,0x302,0x033,0x47f,0x5f4,0x3cf,0x3c4,0x07f,0x272,0x102,0x6b5,0x121,
+ 0x516,0x5f9,0x7b6,0x076,0x334,0x5c0,0x2e2,0x339,0x3e3,0x6b0,0x69c,0x0ea,0x56f,0x168,0x5e0,0x167,
+ 0x3c9,0x639,0x191,0x762,0x7b5,0x795,0x384,0x772,0x3ce,0x76f,0x02f,0x23c,0x773,0x249,0x2c8,0x03d,
+ 0x74c,0x06f,0x09c,0x0ae,0x6a2,0x131,0x4ea,0x1fc,0x309,0x2d8,0x3d0,0x51e,0x7e0,0x209,0x111,0x234,
+ 0x01a,0x782,0x2e5,0x506,0x35c,0x7a5,0x2cc,0x517,0x30c,0x0d7,0x759,0x26a,0x4ce,0x401,0x1f3,0x10c,
+ 0x449,0x29f,0x5b4,0x79e,0x6c7,0x028,0x530,0x681,0x397,0x00d,0x670,0x2d5,0x5af,0x520,0x0a4,0x6a5,
+ 0x0df,0x723,0x039,0x4a7,0x281,0x70e,0x1e5,0x0de,0x02a,0x5c4,0x777,0x456,0x142,0x451,0x785,0x17d,
+ 0x393,0x491,0x419,0x6d0,0x645,0x247,0x11e,0x0a1,0x580,0x473,0x3aa,0x709,0x17c,0x6bb,0x177,0x52f,
+ 0x268,0x0a7,0x4ca,0x626,0x7a2,0x54e,0x484,0x4f5,0x4bd,0x5f2,0x198,0x4df,0x1c4,0x5a4,0x2d4,0x157,
+ 0x4c0,0x241,0x531,0x40e,0x44b,0x2f8,0x0a0,0x1d7,0x350,0x152,0x67d,0x6b3,0x6c8,0x288,0x36e,0x7c3,
+ 0x621,0x67e,0x4ef,0x7b7,0x7fa,0x359,0x408,0x6d7,0x29c,0x5c9,0x590,0x045,0x3c5,0x5b0,0x59e,0x0ce,
+ 0x50a,0x236,0x1a6,0x641,0x54f,0x61c,0x05f,0x61a,0x74e,0x74b,0x016,0x6fe,0x311,0x39d,0x4ed,0x353,
+ 0x625,0x4bc,0x335,0x42b,0x5d8,0x07d,0x03f,0x089,0x7e9,0x07c,0x1cf,0x024,0x188,0x53b,0x2bf,0x726,
+};
+
+static const UINT8 deco56_swap_table[0x800] =
+{
+ 4,0,7,2,0,0,7,2,0,1,6,3,2,2,2,2,0,5,6,3,7,0,0,5,1,1,1,7,1,0,0,0,
+ 2,5,6,6,2,0,4,1,5,0,1,7,4,7,0,4,6,2,1,5,3,1,2,4,6,4,2,0,4,3,3,7,
+ 2,7,0,6,0,5,0,2,2,6,4,0,3,5,5,7,0,4,7,5,4,5,6,3,5,5,3,6,2,0,0,4,
+ 2,3,7,5,6,4,7,4,3,2,0,0,0,1,5,4,0,3,7,3,1,6,4,1,2,6,7,4,1,3,0,7,
+ 1,7,2,6,5,6,5,1,6,7,0,3,4,6,5,0,6,2,2,6,4,6,7,3,2,3,2,4,0,0,4,5,
+ 6,5,0,3,0,6,0,6,0,6,7,1,3,5,0,4,5,3,7,4,3,3,5,1,2,1,6,7,1,6,7,6,
+ 0,5,2,4,5,1,0,6,3,3,4,1,0,1,1,6,3,4,7,0,4,1,6,5,5,2,2,3,5,3,0,6,
+ 6,7,4,4,7,3,3,2,0,6,3,0,4,7,7,6,1,1,1,7,1,5,3,7,6,4,6,2,2,4,1,5,
+ 4,6,5,3,5,5,4,2,7,4,7,4,3,3,5,7,4,0,3,0,4,3,2,2,2,5,0,3,5,7,0,7,
+ 2,7,7,7,2,3,3,6,4,0,3,7,2,5,1,2,1,0,5,4,3,5,5,3,6,3,4,6,2,2,1,4,
+ 2,5,4,3,0,4,0,3,6,4,7,1,7,2,3,7,6,2,3,3,4,1,5,7,0,0,6,7,5,2,2,7,
+ 1,5,7,4,6,3,0,4,4,3,6,6,5,1,1,6,6,1,1,5,1,5,1,4,1,6,5,6,2,6,6,0,
+ 7,7,3,4,0,3,5,7,4,5,1,6,1,7,5,6,4,6,7,0,7,6,5,2,4,6,2,5,5,3,6,6,
+ 5,6,2,5,1,7,6,1,3,5,1,4,6,6,6,4,6,0,4,2,5,6,5,0,4,5,1,1,2,2,1,3,
+ 4,7,3,3,2,0,2,7,6,3,3,3,2,6,4,5,6,4,0,0,6,5,2,5,1,6,1,5,0,2,4,0,
+ 0,5,6,0,5,1,7,1,5,7,6,5,7,3,2,1,2,0,4,5,7,4,3,5,0,6,1,6,1,6,2,6,
+ 3,5,6,3,1,1,6,6,4,0,0,7,5,3,2,4,4,3,4,3,3,2,3,3,6,0,1,6,0,7,7,7,
+ 6,7,5,5,7,0,6,7,4,7,3,5,4,5,0,1,1,7,0,4,1,0,0,3,2,6,2,6,4,5,4,6,
+ 3,3,4,4,7,4,4,5,3,3,0,0,3,5,2,5,3,4,4,0,5,2,6,5,6,3,0,5,2,3,3,2,
+ 5,7,0,4,1,7,0,5,7,5,3,6,1,5,2,4,3,4,7,7,5,7,7,5,5,2,5,4,7,2,5,5,
+ 2,0,3,3,6,4,7,1,7,5,5,0,6,3,4,3,7,7,1,0,2,2,3,0,2,0,6,5,4,0,4,5,
+ 6,0,3,7,5,0,3,4,0,6,7,0,2,3,6,3,5,6,3,4,6,0,1,1,2,2,1,6,6,1,6,1,
+ 2,6,0,6,5,4,5,5,5,4,7,3,6,6,5,6,5,5,0,6,4,2,2,4,2,7,5,7,7,0,1,5,
+ 5,3,4,1,6,4,3,0,1,5,0,2,0,7,4,1,6,4,5,3,4,4,4,6,5,4,7,6,5,1,6,3,
+ 6,6,0,1,2,2,7,6,5,1,0,2,7,4,3,6,5,5,4,5,6,5,5,0,6,7,0,5,3,0,7,0,
+ 6,0,3,3,4,6,0,3,5,7,4,5,0,1,1,5,3,4,3,5,2,6,6,1,1,2,7,1,2,1,5,7,
+ 3,2,3,6,7,5,4,7,1,7,2,1,7,0,5,5,1,2,6,5,0,6,5,6,3,0,5,3,0,5,5,1,
+ 0,3,0,5,1,5,6,3,2,7,4,1,0,5,6,3,7,5,1,3,0,3,1,0,0,1,1,7,4,0,7,4,
+ 4,5,4,7,3,7,6,6,1,1,2,5,7,6,4,1,1,5,6,7,1,1,2,7,1,3,6,4,1,3,6,3,
+ 5,3,5,6,2,0,4,5,3,5,1,1,0,4,2,6,6,5,3,2,5,5,1,0,4,3,5,7,6,3,4,4,
+ 7,1,6,2,2,2,0,3,3,4,5,1,6,2,0,5,3,0,7,3,6,3,6,7,4,0,0,3,7,4,6,1,
+ 1,1,6,0,0,0,7,1,2,3,5,5,2,3,0,3,7,2,5,1,3,5,4,0,4,6,2,2,0,7,7,7,
+ 2,5,3,4,7,7,3,2,3,5,4,1,6,7,0,7,3,7,0,6,0,2,7,6,2,6,1,6,5,0,0,0,
+ 2,2,2,2,5,5,5,6,5,0,4,1,1,2,2,0,3,5,5,5,6,3,5,1,3,0,1,4,1,0,0,3,
+ 1,5,3,1,0,5,5,6,4,5,3,0,3,3,1,4,4,4,4,2,7,7,7,0,1,6,1,1,1,7,7,5,
+ 6,4,7,5,3,6,6,1,1,6,7,1,4,4,7,7,6,0,6,4,6,7,6,6,3,3,1,1,3,7,3,1,
+ 0,4,4,3,4,2,2,4,7,1,5,1,5,0,3,4,7,3,7,4,5,3,5,4,0,2,0,7,6,0,4,0,
+ 6,0,7,1,3,4,7,0,0,6,7,5,7,7,2,2,0,7,2,4,7,1,6,1,1,5,5,5,2,5,3,5,
+ 1,1,5,0,5,4,3,2,2,0,3,1,2,2,6,7,2,7,4,1,4,5,6,0,1,0,6,4,2,1,7,2,
+ 2,2,4,1,3,0,3,5,7,2,1,1,3,6,2,5,5,7,4,2,7,5,5,5,1,4,4,0,7,2,0,6,
+ 0,6,2,5,4,7,6,2,1,2,4,5,1,2,3,5,1,6,2,3,0,0,7,5,0,1,0,5,7,7,0,7,
+ 2,6,0,0,3,6,1,0,4,0,5,1,5,7,4,3,1,5,7,7,6,4,7,3,3,4,6,5,0,4,7,6,
+ 4,1,2,4,0,4,3,1,5,6,3,1,7,0,2,4,0,2,6,0,7,0,3,3,4,5,2,2,0,6,6,0,
+ 3,7,7,1,5,0,2,1,5,1,1,5,2,4,5,3,1,6,4,7,6,3,4,3,5,3,6,7,7,4,4,3,
+ 2,4,0,6,7,4,1,6,2,6,0,2,3,5,3,0,2,2,5,5,2,3,1,5,1,0,0,0,6,3,6,3,
+ 3,5,6,4,0,4,2,6,3,5,1,2,7,1,3,0,3,3,0,2,3,2,7,0,7,7,4,6,2,4,7,0,
+ 7,5,6,7,2,2,0,2,5,0,0,3,2,7,3,3,5,7,5,4,3,6,2,2,6,4,3,7,2,6,5,7,
+ 7,7,6,0,2,6,7,2,4,0,1,0,3,5,3,4,3,1,7,7,5,4,0,1,6,3,0,7,6,4,5,4,
+ 7,3,0,5,3,5,0,6,2,3,5,0,4,2,5,3,1,1,3,7,4,1,2,7,7,4,1,6,3,7,7,7,
+ 6,6,4,1,1,3,1,3,4,7,5,6,2,7,2,5,1,1,6,7,0,7,6,3,4,1,4,0,1,2,6,0,
+ 5,2,2,2,7,7,1,7,0,0,4,5,3,3,7,5,0,4,4,4,0,5,7,0,0,6,7,7,4,1,1,6,
+ 1,1,0,1,4,5,2,6,0,4,4,5,7,0,3,7,4,6,6,2,1,7,6,4,7,1,7,2,5,5,6,6,
+ 5,5,0,5,2,0,3,4,4,7,3,7,1,2,1,2,4,0,3,3,3,4,2,3,0,1,7,0,0,0,4,0,
+ 7,2,1,5,6,3,4,6,2,6,6,3,5,4,3,4,0,4,7,4,7,7,0,2,1,6,7,0,6,7,5,7,
+ 4,0,3,4,5,4,6,7,1,7,5,3,6,7,1,7,1,0,5,5,7,3,2,6,7,4,4,2,6,7,3,4,
+ 1,7,4,1,5,3,3,5,3,4,6,4,4,6,0,4,2,6,0,4,3,1,7,2,7,7,1,7,1,0,4,6,
+ 4,7,1,7,6,3,3,3,6,0,3,6,2,3,6,2,6,4,5,3,1,2,1,6,7,5,0,0,4,0,7,0,
+ 6,1,1,2,2,7,6,2,5,4,4,6,3,5,4,7,3,1,4,0,0,2,4,1,4,6,3,6,0,7,2,3,
+ 0,7,7,1,7,0,1,2,7,3,7,2,7,5,1,3,6,2,7,2,0,1,3,5,2,3,4,4,2,4,4,3,
+ 4,4,0,3,7,2,6,6,6,0,0,7,1,0,1,5,0,1,7,1,4,3,7,7,6,1,0,4,3,3,1,2,
+ 0,5,6,3,1,2,5,6,0,0,0,4,2,0,1,6,2,4,0,1,5,4,7,1,2,2,7,7,5,3,6,3,
+ 3,5,4,0,5,3,0,1,5,5,4,0,5,0,1,1,3,6,4,2,3,1,5,5,7,4,0,5,7,0,6,6,
+ 6,6,7,3,2,2,5,4,0,6,1,1,6,0,4,3,2,0,4,0,3,4,7,3,3,5,7,1,3,5,2,3,
+ 6,5,6,0,1,1,6,0,6,1,7,2,4,5,6,5,0,4,0,3,2,3,7,7,0,3,5,0,4,1,1,1,
+};
+
+static const UINT8 deco74_xor_table[0x800] =
+{
+ 13,13, 0,10, 8,15,12, 0,10, 8,13,15,12, 3,15, 2,11, 1, 8,10,13, 4,10,12,11, 2, 0, 3, 0,11, 8,11,
+ 5,14,11, 2, 5, 3, 8,11, 8,13,14, 4, 3,13,11,10,14, 6, 9,11,11, 8, 0,15, 2, 4, 5, 7,15, 8,13,11,
+ 7, 0,12, 3,13, 3, 1, 2, 6,14,10, 3,15,11,15, 7,13,14, 4, 6, 1,10,14, 8, 4,15, 2, 8,15, 9, 3,11,
+ 15,11, 1,14,11, 5, 6,14, 3, 9,12,14,15,12, 6,15,12,13, 3,15, 4, 0, 8, 0, 6, 8, 0, 1, 6,10,14, 9,
+ 12,15, 3, 5,11, 4, 9, 6, 9,13,12, 0,12,14, 9, 9,13,10,15, 8,15, 4, 9, 3,15,15,14, 8, 9, 0,10,11,
+ 15,15, 1,15,10, 6,11,15, 7,11, 8,15, 2,12,15,15, 1,14,10,13, 0,14, 4, 3,12,13, 3, 5, 7, 0, 4, 1,
+ 3, 5,13, 2, 0, 7, 2,13, 3, 7, 9, 2,15, 0, 2, 2, 2, 8, 6, 6,14, 2,15,11, 8, 0, 1,15, 5, 4, 2,15,
+ 13, 1, 1,13, 4,10,15, 3,14, 2,12, 8, 9, 8,13, 2, 0,14, 2, 9, 0, 2,12, 3, 4,15,13, 8, 4,12, 3,11,
+ 13,15, 5, 8, 7, 7, 7,15, 5,11,10, 4, 2, 1, 4,11,11,11, 8,10, 1,13, 5, 3, 1, 5, 8,15,10, 3,10, 9,
+ 4,14, 2, 8, 6,14,14, 9, 7, 2,15, 0,15, 5,10, 3, 5,12,10, 0, 7, 2, 1,11, 4,13,10,14, 3, 1, 1, 1,
+ 9,10,11, 0,14, 0, 1,11, 1, 2, 4,14, 9, 1,12,15, 0,10,11, 6,10, 4, 9, 1, 1, 5, 4, 3,15, 9,11, 0,
+ 7,12,10, 9, 3,14, 4,11,11, 3, 2,10, 1,12, 4, 3,11, 1, 9, 1,15, 9, 3,11,12, 7,11, 6,15, 8, 1, 3,
+ 10,12,10, 4, 2,13,13,11, 3,13, 1, 2, 7,13, 6, 6, 7,14,12,15, 9, 7,15, 7,15, 6, 5,11, 5, 1,15,11,
+ 11, 7,14,12,12, 4,11, 3, 8, 9, 8,15,12, 8,10, 6, 0,12, 5, 9, 6, 7,10, 6, 1, 6,13, 1, 3,10, 8, 2,
+ 1,13, 9, 4, 6,11, 2, 6, 2,15, 4,13, 3, 0, 7, 0, 9, 0, 6,14, 2,12,11, 0, 5,12, 7, 2, 6, 0, 2,10,
+ 10, 5, 1,12, 5,14,12, 1,13, 2, 6,11, 7,10, 0, 0, 7, 1, 8,10, 2, 3, 6, 4,11,10,10,13,15, 0,14,10,
+ 3, 8,14,10, 0, 7, 2, 4, 4, 4, 0, 9,15, 9,14, 3, 4, 3, 5, 4, 7,15, 6,13, 7,12, 1,12,10, 1, 8,15,
+ 5,15,12,13,14,14, 0, 4, 0, 0, 5, 0, 6,14, 8,14,14, 1,11, 5, 5,11, 3, 0, 2,15,11, 2, 7, 1,14,10,
+ 14, 3, 1, 5, 5,10, 1,10,13,13, 9, 9, 2, 1, 6, 7, 6, 7,11,15, 6, 6, 4,12, 8, 4, 3, 0, 0,15, 8, 2,
+ 2,14, 1, 8,11, 7,11,10, 3,10, 6,10,14,10,14, 6, 1, 3, 5, 2, 2, 5, 5, 5, 8, 3,12,15, 6, 9,12,10,
+ 4, 8,11, 6, 1, 8, 9,15,15,10, 0, 6,11, 8, 2, 9,15, 2, 2,10, 0, 5, 6, 5,11, 0, 0, 6, 0, 1,13, 6,
+ 4, 4, 4, 1, 4, 0, 9,12, 2,10,13, 5,10,12,15,10,12, 3, 4, 7,10,13, 3,15,12,11, 6, 8,13, 2, 8,10,
+ 3,12,13, 9,10, 4, 2,11, 1, 4, 9, 1,11, 2,14, 5, 2, 0,10,12, 0, 6, 7, 0, 2,10,15, 9, 0, 0, 8, 1,
+ 0, 9, 1,14, 0,13,12,13, 9, 6,10,12,10, 0,13, 3, 7, 4,12, 0,11, 0, 0,11, 5, 0,14,15,11, 8, 2, 5,
+ 4, 6, 5, 9,13, 5, 4, 4,13, 4, 0,12,10, 3, 2, 2, 0,13,11,12, 4,12, 9, 7,13,14,14, 8, 5, 0,13, 0,
+ 1, 4,15,15, 9, 8, 5,12,13, 8,12, 8, 8,10, 0,15, 8,11, 5, 6, 9, 8,10,12, 9,12, 5,14, 6, 9, 7,15,
+ 1, 9,15, 0, 1, 9, 1, 2, 8, 1, 4,12, 1, 4, 9, 7, 2,10, 8, 1,13, 6, 0,12, 0, 6,12,13, 5, 9, 4,12,
+ 7,14,10, 4, 6, 8,12, 4, 9, 1, 2, 2, 3,13,10, 2,15, 7, 1, 6, 0,12, 5,10, 9, 1, 0,14,15, 3, 7, 6,
+ 9,12,13, 7, 0,13, 2, 5, 7,13, 1, 3, 8,15, 9,10, 3, 0,15, 2,11, 5, 7, 3,10, 7, 4, 0, 7, 2,10, 2,
+ 0, 3, 6, 6,13, 0, 5, 9,13, 8,11, 9, 0, 4, 1,11,15, 5,15, 3, 1,15, 1,15,12, 8, 9, 4, 1, 5, 8,11,
+ 5, 7, 6,11, 5, 7,15,15, 9, 4, 7,12,14,11, 8, 6, 7, 7,12, 3, 9,12, 6, 9, 5, 8,13,14, 6,14, 4, 7,
+ 12,12, 2,14,10, 2, 1,10, 3, 8,12,11,12, 7,12,15, 7,13, 9,15, 6, 3, 1,14,13,14, 8,11,14, 4, 9, 2,
+ 13,13, 0, 2, 9,11, 3, 2, 4,11, 6, 8, 2,14, 7,15, 8, 8, 9, 5, 4,15,11, 7,13, 7, 4,15,15, 4, 2, 1,
+ 6, 4, 3,15, 0,11,14,15, 6,15,11,14,10, 4, 4, 0, 5, 4, 6,15, 8,10,15, 1, 3, 8,13, 3, 3, 0, 7, 7,
+ 2, 3, 2,11,14, 1,12,13,10, 2, 4,13, 4,13, 9, 3, 2, 1,14, 9, 8,11,15, 4, 8, 9,13, 2,10,14, 2, 4,
+ 8,13,13,14,12, 1, 5,15,13, 3,12, 8,11,12,12, 1, 0,15, 9, 2, 6, 9, 3,12, 5, 0,10, 8, 5, 6,11,14,
+ 7, 7, 0,10, 0,14,10, 8, 4,12, 5, 3,11,10, 5,13,15, 9,14,12,12, 0,14, 3, 2,12, 9,14,11,11, 9, 2,
+ 8, 9,13, 0,10, 3,14,14,13, 6, 4,14, 2,10,10, 9,10, 4, 5, 4, 5, 3, 4, 6,15, 5,14, 2, 6,10, 4, 8,
+ 6, 9, 9, 7, 3, 3, 9, 5, 9, 8,10, 5, 0,13, 7, 8, 4, 1, 3,13, 4, 1, 8,10, 3,11,13, 3,12, 0, 2, 0,
+ 3, 1, 3, 3, 1, 6,13, 2, 3,13,11, 5, 9, 0, 4,12, 6,11, 4, 4, 3, 3,12, 7,13, 2,15,12, 1,11,15, 7,
+ 10, 0, 9, 3, 3,13,12,12, 9,14, 2, 2, 0, 3,12, 2, 0,15, 0,10, 1, 9, 8, 3, 2, 3, 9, 1, 4, 5,12, 9,
+ 10,11, 0, 2, 2,11, 5,13, 8, 1, 7, 8, 4,12,11, 1, 2,11, 7, 7, 8, 6, 5, 8, 8,14, 2, 6,10, 6, 1, 9,
+ 3, 4, 2, 9,11, 1, 4, 9, 8,13, 5, 0,15,13, 0, 9, 9,11, 5,11, 6, 4, 6, 9, 5, 1,13, 8, 8, 2,14,14,
+ 2, 3,14,12, 4, 6,15, 4,11,14, 7, 2, 3,14, 4,15, 4, 1, 8,13, 5, 5, 7, 0, 6,14, 0, 1, 1,13, 5,10,
+ 10,14,14,10, 2, 9, 1,11, 5, 6, 8,12, 4, 2, 7, 7,11, 6,13,15, 1, 3, 9, 0,14,12, 9, 2, 3, 2, 1, 9,
+ 12, 7, 4,12,14, 3, 3, 2, 3,14,10, 5, 8, 4, 9, 9,11,14,13,15,14, 7, 3,13, 0, 9, 4, 9,12,12, 1, 2,
+ 10,11, 7,11, 1, 9, 2, 8, 1, 4, 5,14, 8,15, 9, 3, 8, 9, 6, 3, 7, 3, 1,10, 7, 5,13,14, 8, 7, 4,10,
+ 14, 4, 6, 9, 6, 2, 5, 3, 8, 0, 9, 7, 2, 7,12, 8,12, 2,15, 4, 5, 0,11, 8,11, 2,14, 8,15, 0, 8, 9,
+ 14, 5, 4,13,12,11, 2, 6,11, 9, 9, 7,14, 6, 6, 7, 4, 6, 3, 5,12, 5,11, 1,12,14, 0,13,15,13, 2, 2,
+ 1, 8, 3,11, 3, 1, 6, 9,12,12, 5,10, 7,13,15, 4,12,10, 9,11,12,14,12,11,15, 2, 3, 2, 7, 8,15, 2,
+ 2, 0,12,12, 9,11,13,14,13, 7, 3,11,11,14,12, 3, 2, 7, 4, 8, 9,11, 8,11, 5,10, 3, 7,15,11,12,15,
+ 10, 8, 5,13, 8, 3, 9, 8, 5, 7, 1,15,15, 0,13, 7, 8, 6, 8,10, 8, 6, 6, 3, 4,10,13, 1, 6, 6,10, 1,
+ 2,11, 4,15,15, 3, 1, 1,14,12, 1,15, 1, 6, 8,10,14,14, 9, 4, 7, 8, 6, 5, 3, 1, 0, 5, 3, 8, 6, 1,
+ 4, 2,13,15,14, 5,13,11,10,13,11,11, 6,10, 7, 2, 1,15, 2,10, 5, 0,11, 5,15, 8, 0,14, 3,12,11, 7,
+ 10, 1, 4, 0, 3,15, 7,15,12, 8, 9, 0, 1,15,13, 2, 3, 2,15,15,14,14, 7, 8,12,11,15,15,14, 2, 8, 8,
+ 2, 0,15, 4, 2, 5,14,10, 4,12, 2, 1, 0,13, 7, 5, 4, 3,11, 6, 0, 2, 6,14, 9,14,10,13, 6,10, 5, 8,
+ 15, 2, 4, 7, 1, 8, 5, 3,11, 5,12, 1, 3, 1,14, 4, 8,12, 6,10,14, 7,14, 7,15,14, 5,10, 6, 9, 3, 6,
+ 12,15, 1,12, 0, 6, 1, 4,13,13, 7, 1, 7, 1, 9, 1, 8, 6, 9, 9, 8,12, 5, 2, 8,11, 9, 1, 3, 9, 0,11,
+ 14, 8, 5, 9, 7, 7,14, 4, 6, 1, 6,11, 4, 0,15, 5, 9, 8, 5,13, 2, 6,13,10,12, 3, 4, 3,15, 5, 6,14,
+ 2,10,14, 1, 5, 9, 6, 1, 9, 2, 7,11,14, 7,14, 5, 8, 9,14,13,14, 8, 3, 8, 4,10, 3,14, 0,13,12,15,
+ 9, 9, 0, 4, 6, 7,12,13,12, 1,15, 2,13,13, 8,10,13, 5,12, 5, 4, 0, 2, 1,13,12, 2,14, 9,15,13, 9,
+ 7,13, 7, 0,14, 7,12,15, 3,11, 0, 5, 8, 1, 0,12, 9, 0,11,13, 6, 3, 3, 7, 2, 2, 3, 5,14,14, 0, 9,
+ 2, 6, 4,12, 2, 6, 3,12, 3,13, 3,14, 7, 1, 8,15,14, 3, 0,10, 2,15,15, 9,14,11,10,12,13,13,13, 9,
+ 7, 7,12, 5, 3,14, 1, 5, 1,10, 6, 7, 9, 8,15, 7,13,11, 4, 5, 4,10,14,14,12, 1,13,14,15,14,15,10,
+};
+
+static const UINT16 deco74_address_table[0x800] =
+{
+ 0x526,0x684,0x15f,0x1ad,0x736,0x341,0x4c3,0x23c,0x3eb,0x01f,0x18e,0x375,0x029,0x227,0x707,0x506,
+ 0x5ce,0x0dc,0x5dc,0x5fd,0x15c,0x013,0x7b9,0x3c1,0x77d,0x1eb,0x53d,0x4a9,0x66e,0x0a9,0x4e2,0x361,
+ 0x32d,0x151,0x16a,0x5ed,0x4b0,0x78a,0x0d1,0x01e,0x4be,0x7dd,0x22d,0x125,0x401,0x118,0x051,0x784,
+ 0x48a,0x083,0x42f,0x56b,0x448,0x679,0x019,0x076,0x44c,0x663,0x3a1,0x740,0x095,0x242,0x4c5,0x13b,
+ 0x3c4,0x130,0x122,0x047,0x16b,0x162,0x0d9,0x1f4,0x0be,0x018,0x56c,0x494,0x0b0,0x185,0x3b3,0x257,
+ 0x764,0x05d,0x7d4,0x2bd,0x159,0x2fb,0x07a,0x365,0x4fd,0x451,0x452,0x52d,0x753,0x5c8,0x1a4,0x50e,
+ 0x5ff,0x536,0x45b,0x281,0x4b8,0x1ff,0x228,0x5f9,0x1ca,0x587,0x0fd,0x02a,0x0da,0x03f,0x6a4,0x671,
+ 0x2d9,0x377,0x39c,0x534,0x6c5,0x1b2,0x1db,0x263,0x5c3,0x0c7,0x474,0x4db,0x152,0x3de,0x47d,0x64a,
+ 0x41c,0x66c,0x3d9,0x769,0x0c1,0x4ec,0x46b,0x274,0x6aa,0x623,0x31a,0x2ef,0x270,0x1e7,0x4e5,0x2e3,
+ 0x1f9,0x203,0x150,0x4a3,0x7d3,0x0af,0x1c8,0x310,0x4cd,0x1a6,0x14e,0x636,0x3f8,0x04d,0x337,0x441,
+ 0x3c0,0x1d8,0x482,0x399,0x3ef,0x520,0x260,0x352,0x4f8,0x521,0x271,0x6e6,0x5da,0x763,0x595,0x4e0,
+ 0x2db,0x3c6,0x012,0x09b,0x14f,0x26b,0x512,0x0cb,0x616,0x605,0x63a,0x5e2,0x139,0x7cd,0x7d0,0x00c,
+ 0x198,0x234,0x4f7,0x37e,0x0a1,0x4bd,0x1a1,0x2f0,0x3b4,0x0a6,0x1c7,0x51e,0x166,0x567,0x719,0x5cb,
+ 0x3b5,0x31c,0x751,0x6a1,0x065,0x4fa,0x6e1,0x106,0x1a5,0x331,0x3a2,0x16d,0x756,0x090,0x554,0x241,
+ 0x19a,0x35c,0x0e9,0x388,0x1c9,0x11b,0x5c7,0x56a,0x168,0x5b2,0x47f,0x5a9,0x551,0x3bb,0x3d3,0x428,
+ 0x132,0x4d7,0x1d1,0x538,0x5d7,0x297,0x6df,0x0ce,0x728,0x2c5,0x6f6,0x60d,0x2a0,0x45f,0x46d,0x4f0,
+ 0x5ea,0x1e0,0x4d6,0x442,0x32f,0x243,0x30f,0x0c9,0x344,0x42d,0x22f,0x327,0x2b2,0x158,0x7af,0x3d2,
+ 0x127,0x6d3,0x411,0x7eb,0x632,0x277,0x60b,0x356,0x307,0x1c3,0x0f1,0x762,0x207,0x13e,0x25a,0x6d0,
+ 0x38e,0x0a7,0x79a,0x2a5,0x771,0x39e,0x325,0x160,0x014,0x115,0x698,0x712,0x2c8,0x3c3,0x1bc,0x696,
+ 0x0d6,0x692,0x49f,0x4de,0x5b3,0x0cc,0x2f3,0x667,0x318,0x52c,0x3e0,0x181,0x462,0x1f7,0x366,0x4f4,
+ 0x547,0x44e,0x1be,0x3ed,0x04e,0x490,0x661,0x703,0x320,0x42e,0x406,0x161,0x259,0x702,0x58b,0x619,
+ 0x51f,0x502,0x391,0x4ce,0x779,0x0f9,0x05b,0x45e,0x14a,0x66a,0x42b,0x35a,0x363,0x1b8,0x373,0x117,
+ 0x78f,0x34e,0x2e0,0x2d7,0x7ee,0x27b,0x2c6,0x103,0x7dc,0x23d,0x2ad,0x049,0x68a,0x41f,0x582,0x3d5,
+ 0x631,0x107,0x2be,0x28e,0x5af,0x119,0x694,0x744,0x546,0x19b,0x766,0x5cf,0x2ee,0x0e0,0x4a5,0x313,
+ 0x6a3,0x3b1,0x28a,0x104,0x415,0x19e,0x01c,0x009,0x167,0x266,0x397,0x056,0x525,0x416,0x64f,0x689,
+ 0x706,0x413,0x004,0x6c9,0x244,0x2f8,0x78b,0x510,0x02e,0x505,0x5a6,0x612,0x114,0x4d9,0x1cc,0x20f,
+ 0x7e9,0x13a,0x584,0x495,0x6d2,0x5f4,0x093,0x43f,0x0e3,0x382,0x746,0x71e,0x794,0x72d,0x3ec,0x7c1,
+ 0x03a,0x33d,0x1ec,0x128,0x27f,0x700,0x149,0x10c,0x553,0x2bc,0x492,0x080,0x5b0,0x015,0x1c4,0x691,
+ 0x037,0x59f,0x542,0x4cf,0x253,0x5ae,0x74d,0x407,0x6e8,0x354,0x7b4,0x49b,0x300,0x6f2,0x26e,0x3f4,
+ 0x086,0x37c,0x1ee,0x347,0x6b1,0x26d,0x105,0x55d,0x1ba,0x70b,0x236,0x3e3,0x0b6,0x2c2,0x33b,0x254,
+ 0x140,0x2e8,0x5c2,0x03b,0x04c,0x5aa,0x480,0x560,0x6ed,0x633,0x7a6,0x29f,0x789,0x0e4,0x08a,0x15b,
+ 0x57e,0x4fe,0x532,0x25c,0x215,0x709,0x5f7,0x197,0x586,0x2f1,0x5e0,0x477,0x61b,0x608,0x063,0x01b,
+ 0x212,0x016,0x795,0x205,0x1fa,0x742,0x777,0x40b,0x146,0x73b,0x503,0x792,0x10e,0x545,0x7f6,0x3f7,
+ 0x4ad,0x38d,0x3b9,0x516,0x2ac,0x3bd,0x31b,0x214,0x170,0x5d6,0x21b,0x1b1,0x3cd,0x213,0x565,0x40a,
+ 0x113,0x515,0x724,0x03d,0x5c0,0x334,0x3e9,0x2a8,0x1c5,0x089,0x24e,0x7cb,0x4d5,0x280,0x36c,0x2b0,
+ 0x430,0x0e6,0x0d5,0x3c5,0x662,0x275,0x60f,0x0de,0x248,0x07b,0x22c,0x7b5,0x340,0x739,0x2b8,0x65a,
+ 0x508,0x116,0x079,0x7a0,0x4c2,0x099,0x4bb,0x52a,0x4d1,0x389,0x3a3,0x1e6,0x2a4,0x10d,0x4ba,0x581,
+ 0x0b2,0x302,0x0f4,0x760,0x25d,0x4c6,0x39b,0x12b,0x046,0x637,0x38b,0x0f6,0x109,0x51c,0x40d,0x6e9,
+ 0x6e2,0x7da,0x4a0,0x487,0x67e,0x65f,0x265,0x439,0x189,0x208,0x4b5,0x250,0x4f1,0x16e,0x496,0x3fc,
+ 0x272,0x20c,0x7ae,0x292,0x5e3,0x472,0x458,0x66d,0x657,0x722,0x438,0x3b8,0x4e4,0x39a,0x598,0x539,
+ 0x4b4,0x290,0x18b,0x1de,0x65c,0x2ea,0x6ff,0x20a,0x232,0x058,0x2d3,0x0d3,0x1f1,0x61d,0x0d2,0x1d2,
+ 0x295,0x466,0x038,0x0ac,0x4c7,0x6c7,0x672,0x040,0x6a0,0x699,0x624,0x71f,0x120,0x10b,0x072,0x192,
+ 0x3ba,0x638,0x58d,0x530,0x00e,0x761,0x6dd,0x1cd,0x18d,0x142,0x2eb,0x55e,0x7b2,0x367,0x5d3,0x71c,
+ 0x2d2,0x0a0,0x6b2,0x134,0x286,0x12e,0x0cf,0x5dd,0x2e7,0x74b,0x261,0x082,0x726,0x14d,0x1e3,0x4b7,
+ 0x7e7,0x435,0x294,0x31f,0x154,0x2cf,0x5f5,0x330,0x400,0x13d,0x629,0x7d1,0x4a2,0x3e6,0x3e8,0x1f5,
+ 0x3f3,0x368,0x410,0x3ca,0x221,0x71b,0x669,0x195,0x7f2,0x70f,0x006,0x504,0x062,0x461,0x053,0x6f7,
+ 0x0a3,0x6fa,0x1f2,0x745,0x7df,0x12a,0x05a,0x23b,0x4da,0x568,0x665,0x30d,0x5f6,0x328,0x283,0x169,
+ 0x17c,0x601,0x201,0x6c3,0x6c0,0x491,0x63f,0x6f5,0x2b5,0x2c7,0x628,0x3f9,0x02b,0x38a,0x2e9,0x60c,
+ 0x2a9,0x102,0x39f,0x0c3,0x42c,0x7cf,0x3df,0x4f9,0x235,0x3a8,0x7e4,0x485,0x21d,0x349,0x0e8,0x0b8,
+ 0x345,0x683,0x18c,0x317,0x6ca,0x323,0x17d,0x36a,0x7c9,0x1a0,0x3e1,0x6f9,0x0a2,0x353,0x7b6,0x759,
+ 0x287,0x7d7,0x25e,0x523,0x092,0x427,0x5a7,0x396,0x136,0x75a,0x3d6,0x507,0x385,0x5de,0x55f,0x0ad,
+ 0x096,0x239,0x5b8,0x6cb,0x574,0x511,0x41e,0x537,0x074,0x148,0x7a4,0x70e,0x2cb,0x284,0x191,0x06e,
+ 0x2da,0x51a,0x374,0x6ba,0x41b,0x552,0x460,0x371,0x183,0x0b3,0x444,0x748,0x7f4,0x59e,0x5bd,0x381,
+ 0x0ab,0x6fd,0x4cc,0x3e5,0x5c5,0x09c,0x717,0x22e,0x708,0x1bb,0x70c,0x4a6,0x778,0x034,0x1d5,0x30b,
+ 0x7f5,0x743,0x6ae,0x2de,0x2a6,0x613,0x5d0,0x40c,0x0bf,0x209,0x1b7,0x4f5,0x72b,0x620,0x647,0x643,
+ 0x024,0x2ca,0x0bd,0x501,0x0a4,0x453,0x3ff,0x6b5,0x625,0x2f7,0x556,0x469,0x409,0x747,0x031,0x1f6,
+ 0x47c,0x2ab,0x1fd,0x533,0x74f,0x395,0x754,0x0d0,0x6b0,0x42a,0x635,0x1af,0x6a9,0x49c,0x77b,0x611,
+ 0x2ae,0x2b4,0x3a5,0x1b5,0x3fe,0x3ab,0x479,0x498,0x3aa,0x5c1,0x27e,0x26a,0x590,0x29d,0x02c,0x121,
+ 0x404,0x61c,0x650,0x518,0x33a,0x768,0x0f2,0x0b4,0x686,0x67b,0x301,0x04b,0x1c1,0x7d9,0x772,0x0c8,
+ 0x49a,0x68f,0x59b,0x419,0x73a,0x750,0x360,0x58e,0x264,0x52e,0x00d,0x46e,0x085,0x46f,0x788,0x164,
+ 0x3d8,0x6db,0x52b,0x473,0x332,0x073,0x440,0x028,0x35b,0x3f1,0x14b,0x7fb,0x03e,0x28c,0x1ea,0x3f5,
+ 0x6a8,0x53c,0x5b5,0x0fb,0x585,0x478,0x179,0x4ac,0x137,0x173,0x1e5,0x7c6,0x262,0x027,0x6d8,0x144,
+ 0x3e4,0x673,0x7b7,0x145,0x6b7,0x596,0x1c6,0x54b,0x110,0x155,0x64e,0x4f6,0x44b,0x7fa,0x422,0x5a4,
+ 0x06c,0x51d,0x023,0x0aa,0x459,0x5fc,0x11a,0x2dd,0x4e1,0x603,0x224,0x497,0x308,0x5c9,0x3dd,0x4e8,
+ 0x48d,0x4cb,0x548,0x36f,0x094,0x36e,0x58a,0x299,0x797,0x57d,0x7c8,0x75f,0x321,0x431,0x045,0x131,
+ 0x543,0x486,0x1ce,0x47b,0x57f,0x38f,0x775,0x1dd,0x34a,0x177,0x4d8,0x634,0x48c,0x2e5,0x5ee,0x255,
+ 0x644,0x456,0x653,0x1e9,0x0ca,0x72e,0x576,0x710,0x6ab,0x4aa,0x4fb,0x569,0x541,0x309,0x1d9,0x714,
+ 0x35d,0x757,0x278,0x7ef,0x2ec,0x668,0x6d7,0x335,0x62d,0x3b6,0x5b4,0x676,0x46c,0x0e2,0x5bc,0x7bd,
+ 0x07f,0x267,0x68e,0x649,0x721,0x53f,0x226,0x0cd,0x6c2,0x312,0x1b9,0x11d,0x53e,0x602,0x6bd,0x561,
+ 0x19c,0x62a,0x135,0x651,0x09e,0x3c8,0x237,0x204,0x610,0x798,0x690,0x5a5,0x5f3,0x0f8,0x540,0x614,
+ 0x14c,0x5d1,0x00f,0x402,0x4b9,0x583,0x5c6,0x21e,0x457,0x3f6,0x07e,0x216,0x4b1,0x369,0x06b,0x37f,
+ 0x091,0x580,0x61a,0x1cf,0x4b2,0x2c4,0x1bf,0x38c,0x0ff,0x314,0x7d8,0x26f,0x7a9,0x31e,0x2f2,0x7ca,
+ 0x12d,0x101,0x54e,0x32e,0x791,0x4a1,0x76d,0x6b9,0x34d,0x061,0x69c,0x6bb,0x41d,0x571,0x711,0x339,
+ 0x5bb,0x1e1,0x680,0x026,0x032,0x23f,0x524,0x329,0x488,0x2c9,0x7f8,0x043,0x0dd,0x5c4,0x589,0x6f1,
+ 0x4c8,0x00b,0x782,0x670,0x6b8,0x196,0x1d4,0x43d,0x10f,0x56e,0x030,0x165,0x559,0x6b6,0x4ef,0x67d,
+ 0x15d,0x56f,0x2ed,0x7a2,0x04a,0x4c1,0x7a3,0x2e4,0x111,0x5f8,0x725,0x685,0x3bc,0x1fb,0x5a3,0x178,
+ 0x293,0x3a6,0x3a9,0x036,0x7ab,0x07d,0x4c9,0x5a1,0x5b7,0x19d,0x13c,0x519,0x0ee,0x157,0x5a8,0x23e,
+ 0x2af,0x62e,0x25b,0x785,0x73d,0x172,0x3be,0x7ed,0x4e6,0x15e,0x5e7,0x211,0x44d,0x682,0x7db,0x5b6,
+ 0x40f,0x020,0x0f5,0x7c0,0x609,0x5f2,0x6cf,0x08b,0x256,0x514,0x799,0x5d2,0x1e2,0x727,0x7e5,0x279,
+ 0x30c,0x11c,0x30a,0x58f,0x0df,0x03c,0x577,0x5ef,0x7c2,0x55a,0x5b1,0x776,0x65d,0x2aa,0x225,0x3db,
+ 0x276,0x6a5,0x5ec,0x229,0x5ca,0x513,0x1a8,0x30e,0x783,0x3fd,0x124,0x535,0x13f,0x64c,0x1a3,0x607,
+ 0x02f,0x0e5,0x701,0x24c,0x45c,0x566,0x6d1,0x035,0x044,0x455,0x042,0x20e,0x7e8,0x767,0x2fa,0x476,
+ 0x003,0x2bf,0x37a,0x5d4,0x247,0x660,0x1f0,0x2d6,0x36d,0x564,0x3c2,0x37b,0x2f4,0x17a,0x4a7,0x176,
+ 0x3d4,0x59a,0x383,0x258,0x08e,0x098,0x528,0x62c,0x72f,0x35e,0x0b5,0x56d,0x6f0,0x44a,0x723,0x45d,
+ 0x4eb,0x055,0x285,0x0ed,0x182,0x429,0x393,0x470,0x555,0x3a4,0x078,0x1a2,0x43a,0x16c,0x65e,0x087,
+ 0x7f3,0x74e,0x273,0x386,0x6da,0x550,0x25f,0x206,0x039,0x2a3,0x2e6,0x199,0x1cb,0x445,0x4c0,0x06a,
+ 0x54c,0x316,0x0d8,0x741,0x194,0x05c,0x606,0x43e,0x100,0x21a,0x43c,0x4c4,0x693,0x5e1,0x1d3,0x240,
+ 0x20d,0x433,0x796,0x238,0x765,0x4af,0x0eb,0x7e1,0x050,0x4ee,0x2d5,0x75e,0x5a2,0x5be,0x70a,0x3cf,
+ 0x376,0x005,0x61e,0x002,0x5cd,0x069,0x0c6,0x041,0x084,0x64b,0x60e,0x268,0x51b,0x000,0x464,0x34b,
+ 0x615,0x3d7,0x5cc,0x1b0,0x233,0x7fe,0x641,0x53a,0x24d,0x00a,0x32a,0x18f,0x282,0x749,0x3dc,0x0b7,
+ 0x5b9,0x336,0x0c4,0x5eb,0x398,0x475,0x2d8,0x5bf,0x646,0x418,0x5a0,0x3cc,0x531,0x187,0x3ea,0x6bc,
+ 0x1ab,0x1e4,0x69d,0x63c,0x6f8,0x0f3,0x251,0x2dc,0x648,0x6a7,0x219,0x731,0x573,0x7f1,0x070,0x188,
+ 0x7d5,0x436,0x730,0x6de,0x27d,0x163,0x129,0x403,0x298,0x2b9,0x06d,0x357,0x249,0x4b3,0x296,0x2b6,
+ 0x6b4,0x697,0x770,0x484,0x303,0x7fc,0x1da,0x2d1,0x7f0,0x379,0x16f,0x222,0x48f,0x394,0x64d,0x68d,
+ 0x3b2,0x5ab,0x3e2,0x5f1,0x7ff,0x69b,0x50c,0x384,0x655,0x346,0x446,0x7ea,0x4f3,0x2fc,0x2b1,0x562,
+ 0x387,0x2ff,0x4ed,0x5e5,0x5d9,0x6fe,0x1ef,0x656,0x47e,0x171,0x067,0x600,0x6eb,0x246,0x4d2,0x73c,
+ 0x305,0x1d0,0x434,0x5d8,0x6e7,0x781,0x32c,0x2bb,0x4d4,0x4b6,0x493,0x0c0,0x3bf,0x4f2,0x7ba,0x774,
+ 0x6ad,0x378,0x7c4,0x63b,0x733,0x752,0x454,0x184,0x74c,0x3c9,0x618,0x688,0x054,0x414,0x6c4,0x07c,
+ 0x2b7,0x3c7,0x2fe,0x73e,0x351,0x4a4,0x3fa,0x6e4,0x6d9,0x4a8,0x1fe,0x517,0x010,0x4d3,0x6c8,0x153,
+ 0x180,0x593,0x7b1,0x7a5,0x24b,0x141,0x424,0x7e0,0x186,0x405,0x2ce,0x604,0x425,0x447,0x677,0x79b,
+ 0x76f,0x0ec,0x2cd,0x358,0x1fc,0x3b7,0x0f0,0x32b,0x2cc,0x138,0x735,0x09a,0x549,0x704,0x720,0x786,
+ 0x3f2,0x088,0x639,0x133,0x7b0,0x4ae,0x2f9,0x007,0x54d,0x68c,0x509,0x08d,0x67a,0x443,0x0ba,0x499,
+ 0x06f,0x71d,0x0bc,0x695,0x3b0,0x63e,0x734,0x057,0x033,0x7a1,0x068,0x355,0x49d,0x5ba,0x76c,0x675,
+ 0x54a,0x10a,0x417,0x3a0,0x658,0x1df,0x7aa,0x112,0x6c1,0x372,0x420,0x048,0x011,0x2df,0x202,0x622,
+ 0x483,0x5e6,0x28d,0x0a8,0x324,0x380,0x6ea,0x449,0x23a,0x6a2,0x066,0x021,0x6fb,0x1e8,0x48b,0x0d4,
+ 0x666,0x33f,0x077,0x50f,0x370,0x338,0x76a,0x2fd,0x1d6,0x2a2,0x77e,0x489,0x3ad,0x73f,0x7c5,0x17b,
+ 0x471,0x5df,0x1aa,0x2f5,0x0db,0x7d6,0x6e0,0x7cc,0x645,0x729,0x08c,0x097,0x790,0x41a,0x4dc,0x7a8,
+ 0x1bd,0x21f,0x01a,0x3ac,0x713,0x193,0x55b,0x59d,0x1c0,0x6ce,0x364,0x33c,0x4e9,0x57b,0x426,0x1a7,
+ 0x21c,0x1ed,0x343,0x69a,0x732,0x6ef,0x55c,0x72a,0x18a,0x7f9,0x432,0x29b,0x7b3,0x468,0x319,0x0fe,
+ 0x245,0x7ec,0x7be,0x24f,0x008,0x500,0x31d,0x33e,0x217,0x6be,0x50d,0x230,0x02d,0x15a,0x46a,0x1ac,
+ 0x220,0x0ae,0x1d7,0x50a,0x558,0x718,0x40e,0x621,0x594,0x52f,0x27a,0x758,0x29e,0x4d0,0x642,0x75b,
+ 0x156,0x20b,0x350,0x39d,0x0bb,0x08f,0x218,0x075,0x652,0x57c,0x6d5,0x0ea,0x678,0x052,0x5db,0x1b4,
+ 0x423,0x3a7,0x4df,0x50b,0x77f,0x49e,0x0c5,0x5ac,0x79e,0x3fb,0x591,0x5fa,0x0c2,0x0e1,0x755,0x67c,
+ 0x66b,0x60a,0x66f,0x481,0x467,0x7a7,0x61f,0x57a,0x17e,0x05f,0x5f0,0x7f7,0x0d7,0x773,0x05e,0x7e2,
+ 0x6e5,0x659,0x4e7,0x738,0x24a,0x12c,0x77c,0x4bf,0x45a,0x69f,0x7fd,0x69e,0x529,0x19f,0x2ba,0x0b1,
+ 0x627,0x412,0x65b,0x2f6,0x269,0x342,0x2b3,0x291,0x0fc,0x3da,0x12f,0x4e3,0x592,0x0fa,0x463,0x7bc,
+ 0x780,0x11f,0x4ff,0x7ac,0x28f,0x175,0x0ef,0x6d6,0x4ea,0x527,0x3ee,0x0f7,0x0b9,0x311,0x27c,0x025,
+ 0x2c3,0x71a,0x6af,0x190,0x11e,0x588,0x78e,0x6c6,0x147,0x3ae,0x578,0x6ac,0x4fc,0x252,0x7c7,0x43b,
+ 0x557,0x7e3,0x2d0,0x63d,0x79c,0x62b,0x640,0x123,0x6e3,0x306,0x77a,0x4ab,0x787,0x421,0x1dc,0x390,
+ 0x1ae,0x1f3,0x705,0x7d2,0x081,0x2e1,0x5e9,0x5fe,0x687,0x2a1,0x59c,0x0a5,0x223,0x78d,0x35f,0x7c3,
+ 0x326,0x575,0x348,0x715,0x6b3,0x793,0x6f4,0x7b8,0x064,0x210,0x2c0,0x579,0x022,0x3af,0x74a,0x200,
+ 0x1a9,0x75d,0x7ce,0x72c,0x79f,0x75c,0x09d,0x4dd,0x2e2,0x7e6,0x17f,0x716,0x570,0x7de,0x017,0x76e,
+ 0x54f,0x362,0x29a,0x522,0x1b3,0x22a,0x572,0x3d1,0x408,0x437,0x3cb,0x6dc,0x58c,0x6a6,0x37d,0x53b,
+ 0x1b6,0x7bf,0x5e8,0x143,0x289,0x392,0x22b,0x5fb,0x5ad,0x01d,0x2c1,0x26c,0x76b,0x70d,0x44f,0x6fc,
+ 0x79d,0x4ca,0x450,0x34f,0x3e7,0x1c2,0x664,0x3d0,0x001,0x7ad,0x6f3,0x359,0x544,0x67f,0x563,0x6d4,
+ 0x108,0x48e,0x3f0,0x04f,0x322,0x6cd,0x2d4,0x597,0x09f,0x62f,0x5e4,0x28b,0x681,0x231,0x630,0x315,
+ 0x68b,0x059,0x3ce,0x36b,0x654,0x47a,0x29c,0x6bf,0x071,0x6cc,0x2a7,0x333,0x304,0x1f8,0x0e7,0x599,
+ 0x174,0x060,0x674,0x6ec,0x7bb,0x288,0x6ee,0x737,0x34c,0x617,0x4bc,0x5d5,0x78c,0x465,0x126,0x626,
+};
+
+static const UINT8 deco74_swap_table[0x800] =
+{
+ 2,7,5,7,1,1,4,4,7,5,6,7,7,3,4,3,0,2,1,3,0,4,7,7,2,5,3,1,4,4,6,7,
+ 6,7,4,5,1,3,0,3,7,2,5,0,1,5,2,1,4,0,6,1,1,2,4,2,1,0,6,5,2,6,4,6,
+ 4,4,2,2,0,6,0,4,6,0,1,7,0,6,1,2,5,0,1,5,0,2,6,2,2,7,0,7,2,4,6,3,
+ 3,5,1,1,2,3,4,1,4,6,1,4,0,6,6,3,5,4,1,1,3,0,5,7,5,4,5,4,3,6,2,0,
+ 4,5,7,3,1,3,4,7,7,4,2,7,1,6,4,1,1,4,0,4,2,0,4,0,1,5,6,4,7,7,3,7,
+ 7,0,1,2,6,7,7,0,5,1,2,4,2,0,4,4,7,4,0,3,7,1,7,4,2,5,7,4,3,7,3,6,
+ 7,3,0,5,1,7,5,3,0,1,6,1,7,4,7,6,5,1,2,7,3,3,1,4,6,2,3,7,0,4,5,6,
+ 3,2,3,1,7,6,0,1,5,7,4,0,5,1,4,1,2,0,6,4,3,5,7,4,3,0,0,6,5,1,7,6,
+ 0,2,4,0,0,5,4,7,4,3,3,0,2,3,5,7,0,3,2,3,7,2,0,0,7,6,3,5,0,1,3,2,
+ 4,7,2,3,4,7,1,5,6,7,3,6,4,1,7,7,4,4,3,4,0,7,5,3,2,5,7,7,0,4,0,7,
+ 7,2,5,1,2,4,7,6,0,6,7,0,5,0,1,6,5,0,2,4,5,1,6,7,6,0,7,0,6,0,1,4,
+ 3,2,0,2,4,6,3,2,3,3,0,5,7,2,3,7,1,2,6,3,7,2,0,5,7,1,2,6,4,3,4,6,
+ 4,0,1,4,2,3,3,2,3,7,0,7,4,3,2,1,0,3,5,2,5,3,0,0,0,4,6,4,4,6,1,0,
+ 3,1,1,5,7,1,5,2,0,1,5,7,2,4,5,4,2,6,3,1,4,0,3,0,1,7,3,5,1,1,1,2,
+ 2,3,4,1,2,0,0,7,1,6,1,5,2,2,2,1,6,6,0,5,5,4,2,3,7,4,6,6,6,3,1,3,
+ 3,0,1,7,4,6,3,7,0,1,4,2,3,3,1,7,6,0,6,4,1,3,6,1,6,2,3,1,6,5,3,4,
+ 2,1,3,3,1,6,6,3,6,6,5,0,1,7,1,0,4,6,0,6,0,0,3,6,5,6,4,0,4,2,6,5,
+ 0,4,2,7,6,2,4,6,6,4,6,6,0,5,6,6,5,2,3,0,4,4,6,4,1,6,6,0,7,0,1,6,
+ 1,2,2,4,6,4,2,5,4,2,2,5,4,1,3,3,4,5,3,4,5,6,3,5,2,3,7,6,1,0,4,4,
+ 7,6,0,5,2,6,2,2,3,7,1,5,4,2,6,7,0,5,5,2,5,7,5,6,2,3,0,5,4,5,2,1,
+ 0,5,3,6,7,2,3,4,0,3,5,7,6,6,5,6,7,2,2,2,3,5,0,2,0,1,2,2,4,6,7,2,
+ 5,4,4,3,5,7,3,4,5,3,4,7,1,2,3,5,3,3,6,0,4,4,2,5,4,1,7,2,7,7,4,5,
+ 2,1,0,3,4,1,3,6,2,4,3,3,3,0,0,1,2,0,3,3,6,5,6,7,5,2,0,4,2,0,1,6,
+ 7,1,0,4,1,7,5,2,3,0,2,7,2,2,4,6,7,5,7,5,0,6,5,3,2,7,2,3,3,6,0,4,
+ 1,5,2,2,5,6,4,1,3,6,2,7,4,3,4,1,6,0,5,6,0,0,3,1,1,2,4,3,4,1,4,2,
+ 0,3,0,7,6,3,2,0,2,3,6,5,3,3,6,6,2,4,5,4,1,5,1,6,0,7,5,5,4,7,3,7,
+ 4,3,5,0,7,4,4,3,5,5,7,7,2,4,6,6,7,0,7,6,1,0,2,4,0,2,3,5,4,6,3,5,
+ 2,4,2,4,2,4,5,2,6,5,2,4,6,2,2,2,4,4,2,1,4,0,1,1,1,4,7,0,3,1,7,5,
+ 7,5,5,4,1,0,2,3,5,3,3,7,2,6,1,2,7,4,1,5,2,4,2,5,4,0,5,0,5,4,1,3,
+ 5,1,7,4,2,2,1,3,3,7,6,3,2,1,7,5,3,2,4,6,6,5,6,2,0,2,5,3,4,2,3,4,
+ 0,2,6,3,4,6,6,7,3,0,3,0,1,0,2,7,4,6,0,3,5,2,5,5,5,3,6,4,7,3,5,3,
+ 7,1,1,3,1,5,7,3,0,4,6,5,3,3,2,3,0,7,0,5,1,1,7,2,2,0,0,6,7,6,7,6,
+ 3,4,7,3,7,6,6,0,7,6,3,0,0,6,2,7,1,0,2,7,6,2,2,2,7,1,3,2,3,4,1,3,
+ 1,7,5,2,0,7,7,0,6,1,6,0,2,2,6,7,0,6,7,0,6,4,0,1,6,6,6,0,1,3,4,4,
+ 4,1,2,2,7,3,7,2,4,4,3,4,0,3,1,0,0,7,3,3,6,5,0,4,3,5,5,0,1,7,2,3,
+ 3,0,6,6,5,6,4,0,6,0,1,7,5,4,2,6,3,7,4,4,5,6,7,6,1,7,2,5,5,5,1,4,
+ 3,0,6,3,2,3,0,2,0,0,0,1,0,6,3,7,7,4,3,2,3,4,6,4,2,0,5,3,3,6,4,3,
+ 5,1,4,0,0,1,0,5,2,1,6,3,3,1,1,6,2,0,3,0,7,0,2,0,5,3,6,6,0,6,2,4,
+ 0,3,0,1,2,1,6,4,5,2,3,4,1,2,0,6,7,0,5,5,0,0,3,7,1,4,1,2,7,3,4,7,
+ 4,4,5,5,7,0,4,2,0,7,4,4,7,2,7,2,1,7,4,5,5,7,7,4,0,5,2,2,7,0,5,3,
+ 3,2,0,5,2,1,1,7,0,5,4,3,1,3,2,5,3,4,5,3,4,6,2,2,2,5,4,2,1,3,1,4,
+ 7,5,5,7,3,2,0,4,6,0,4,1,6,5,6,1,3,0,1,1,0,4,5,1,5,0,2,3,7,2,5,6,
+ 0,6,4,2,6,1,5,6,3,3,5,0,3,2,0,0,1,2,1,0,2,7,5,1,6,4,1,7,6,5,3,2,
+ 3,4,3,2,7,1,6,2,3,2,4,3,4,7,0,5,2,0,6,7,2,0,3,7,6,7,4,0,4,3,7,7,
+ 5,2,6,6,7,6,3,6,6,1,6,2,3,1,5,1,0,5,1,0,3,7,4,5,0,3,2,1,3,5,3,1,
+ 1,7,4,2,1,2,3,0,4,7,1,1,6,3,6,4,0,2,7,1,0,5,4,6,1,2,7,1,3,6,5,2,
+ 3,0,5,7,3,5,5,2,2,6,1,6,0,4,5,7,3,4,0,7,0,5,4,3,6,5,7,0,1,0,0,7,
+ 3,3,4,4,1,4,7,1,2,0,0,7,0,5,3,4,6,3,4,6,4,2,5,0,7,5,5,6,6,7,6,7,
+ 3,4,5,0,5,5,7,5,4,4,1,4,3,1,4,3,3,2,5,7,6,3,0,4,1,2,5,4,4,3,0,2,
+ 7,5,5,7,3,7,3,3,7,0,0,5,3,1,4,4,6,0,1,3,1,4,7,2,1,1,4,1,0,7,4,5,
+ 2,7,2,4,5,7,3,3,7,6,4,4,5,3,2,4,0,3,5,5,5,4,3,6,7,7,5,1,3,0,2,6,
+ 3,2,0,4,6,7,4,6,7,2,0,6,7,2,5,0,1,3,0,2,4,7,5,1,4,7,7,4,2,3,6,4,
+ 3,2,0,4,0,6,0,0,5,7,0,4,0,4,6,3,6,0,0,3,1,0,1,2,6,2,1,0,5,7,6,4,
+ 5,4,1,2,3,6,6,1,3,1,1,2,4,3,1,4,1,0,4,2,0,3,2,1,1,1,1,6,2,1,3,0,
+ 6,6,2,5,5,5,2,6,7,6,1,1,3,1,1,6,0,2,6,0,3,6,0,6,3,4,3,3,0,2,0,1,
+ 5,6,5,0,5,3,4,2,7,5,6,4,4,1,1,4,7,7,1,2,3,6,1,6,4,5,3,6,5,1,7,1,
+ 0,6,6,2,6,2,6,0,2,2,6,1,0,2,5,6,6,7,4,4,7,6,1,0,1,4,3,1,2,1,4,1,
+ 4,6,2,5,1,2,0,2,3,4,3,0,3,7,7,6,5,1,7,3,1,0,6,1,1,3,0,7,4,3,1,3,
+ 7,6,1,5,4,3,5,4,7,0,2,5,4,5,1,6,3,7,4,5,6,7,3,6,1,2,3,3,6,6,1,5,
+ 2,0,7,2,5,4,1,7,6,6,0,1,7,5,2,4,1,2,0,2,2,2,7,4,3,0,6,0,7,2,1,7,
+ 5,1,7,1,2,2,4,3,1,3,6,5,5,0,2,6,2,6,0,1,4,1,1,4,3,2,6,0,6,3,7,5,
+ 6,0,7,7,7,2,0,4,2,5,6,3,4,3,2,0,3,1,6,2,3,3,6,7,1,5,6,6,4,0,6,1,
+ 1,6,2,0,7,6,3,2,5,6,0,4,2,4,4,2,5,7,5,4,4,1,6,3,4,6,5,5,6,0,0,4,
+ 4,7,2,2,1,3,4,4,1,7,0,2,5,4,7,3,7,6,1,5,6,0,7,4,1,1,5,2,2,6,7,2,
+};
+
+static void deco_decrypt(int mem_region,const UINT8 *xor_table,const UINT16 *address_table,const UINT8 *swap_table,int remap_only)
+{
+ UINT16 *rom = (UINT16 *)memory_region(mem_region);
+ int len = memory_region_length(mem_region)/2;
+ UINT16 *buffer = malloc_or_die(len*2);
+ int i;
+
+#ifdef LSB_FIRST
+ /* we work on 16-bit words but data is loaded as 8-bit, so swap bytes on LSB machines */
+ for (i = 0;i < len;i++)
+ {
+ rom[i] = (rom[i] >> 8) | (rom[i] << 8);
+ }
+#endif
+
+ memcpy(buffer,rom,len*2);
+
+ for (i = 0;i < len;i++)
+ {
+ int addr = (i & ~0x7ff) | address_table[i & 0x7ff];
+ int pat = swap_table[i & 0x7ff];
+
+ if (remap_only)
+ rom[i] = buffer[addr];
+ else
+ rom[i] = BITSWAP16(buffer[addr] ^ xor_masks[xor_table[addr & 0x7ff]],
+ swap_patterns[pat][0],
+ swap_patterns[pat][1],
+ swap_patterns[pat][2],
+ swap_patterns[pat][3],
+ swap_patterns[pat][4],
+ swap_patterns[pat][5],
+ swap_patterns[pat][6],
+ swap_patterns[pat][7],
+ swap_patterns[pat][8],
+ swap_patterns[pat][9],
+ swap_patterns[pat][10],
+ swap_patterns[pat][11],
+ swap_patterns[pat][12],
+ swap_patterns[pat][13],
+ swap_patterns[pat][14],
+ swap_patterns[pat][15]);
+ }
+
+ free(buffer);
+
+#ifdef LSB_FIRST
+ /* we work on 16-bit words but data is loaded as 8-bit, so swap bytes on LSB machines */
+ for (i = 0;i < len;i++)
+ {
+ rom[i] = (rom[i] >> 8) | (rom[i] << 8);
+ }
+#endif
+}
+
+void deco56_decrypt(int region)
+{
+ deco_decrypt(region,deco56_xor_table,deco56_address_table,deco56_swap_table, 0);
+}
+
+void deco74_decrypt(int region)
+{
+ deco_decrypt(region,deco74_xor_table,deco74_address_table,deco74_swap_table, 0);
+}
+
+void deco56_remap(int region)
+{
+ // Apply address remap, but not XOR/shift
+ deco_decrypt(region,deco56_xor_table,deco56_address_table,deco56_swap_table, 1);
+}
diff --git a/src/mame/machine/decoprot.c b/src/mame/machine/decoprot.c
new file mode 100644
index 00000000000..4acf0a102c6
--- /dev/null
+++ b/src/mame/machine/decoprot.c
@@ -0,0 +1,1772 @@
+/****************************************************************************
+
+ Data East protection/IO chips
+
+
+ Game Custom chip number
+ ------------------------------------------------
+ Edward Randy 60
+ Mutant Fighter 66
+ Captain America 75
+ Robocop 2 75
+ Lemmings 75
+ Caveman Ninja 104
+ Wizard Fire 104
+ Pocket Gal DX 104
+ Boogie Wings 104
+ Rohga 104
+ Diet GoGo 104
+ Funky Jet 146
+ Nitro Ball 146
+ Super Shanghai Dragon's Eye 146
+ Dragon Gun 146
+ Fighter's History 146 (ID scratched off)
+ Stadium Hero 96 146
+ Tattoo Assassins ?
+
+ This series of chips is used for I/O and copy protection. They are all
+ 16 bit word based chips, with 0x400 write addresses, and 0x400 read
+ addresses. The basic idea of the protection is that read & write
+ addresses don't match. So if you write to write address 0, you might
+ read that data back at read address 10, and something else will be at 0.
+ In addition, the data read back may be bit shifted in various ways.
+ Games can be very well protected by writing variables to the chip, and
+ expecting certain values back from certain read addresses. With care,
+ it can be impossible to tell from the game code what values go where,
+ and what shifting goes on. Eg, writing 10 values to the chip, of which
+ 7 are dummy values, then reading back 3 particular values, and using them
+ in a multiplication and add calculation to get a jump address for the
+ program. Even if you can guess one of many possible legal jump addresses
+ it's hard to tell what values should be bit shifted in what way.
+
+ It's also been found some chips contain a hardwired XOR port and hardwired
+ NAND port which affects only certain read values.
+
+ The chips also handle the interface to the sound cpu via a write address,
+ and game inputs via several read addresses. The I/O input data is also
+ mirrored to several locations, some with bit shifting.
+
+ Although several games use chip 104, each seems to be different, the
+ address lines leading to the chip on each game are probably arranged
+ differently, to further scramble reads/writes. From hardware tests
+ chips 60 && 66 appear to be identical.
+
+ Update January - April 2006:
+ Further work on examining the 146 chip has revealed that if you
+ read an address immediately after writing it, you always get
+ the written value returned. This behaviour is confirmed
+ to only exist for one read/write 'tick' - any other read will
+ return that location to its usual state - ie, bit shifter
+ or input port. This has been emulated for the 146 chip in
+ Nitroball and Fighters History but the behaviour probably
+ also exists in earlier chips as it explains the 'one-shot'
+ ports in Mutant Fighter.
+
+ The 'double buffer' feature seen in the 104 chip is also
+ confirmed to exist in the 146 chip. Again, this may well
+ be present in the earlier chip too.
+
+ Emulation by Bryan McPhail, mish@tendril.co.uk
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/eeprom.h"
+#include "decoprot.h"
+
+#define DECO_PORT(p) (prot_ram[p/2])
+
+static UINT8 decoprot_buffer_ram_selected=0;
+static UINT16 deco16_xor=0;
+static UINT16 deco16_mask=0xffff;
+static int decoprot_last_write=0, decoprot_last_write_val=0;
+static UINT16 decoprot_buffer_ram[0x800];
+static UINT16 decoprot_buffer_ram2[0x800];
+
+UINT16 *deco16_prot_ram;
+UINT32 *deco32_prot_ram;
+
+/***************************************************************************/
+
+void decoprot_reset(void)
+{
+ deco16_xor=0;
+ deco16_mask=0xffff;
+ decoprot_last_write=decoprot_last_write_val=0;
+ decoprot_buffer_ram_selected=0;
+
+ state_save_register_global(deco16_xor);
+ state_save_register_global(deco16_mask);
+ state_save_register_global(decoprot_last_write);
+ state_save_register_global(decoprot_last_write_val);
+ state_save_register_global(decoprot_buffer_ram_selected);
+ state_save_register_global_array(decoprot_buffer_ram);
+ state_save_register_global_array(decoprot_buffer_ram2);
+}
+
+/***************************************************************************/
+
+WRITE16_HANDLER( deco16_104_prot_w ) /* Wizard Fire */
+{
+ if (offset==(0x150/2)) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ return;
+ }
+
+ if (offset!=(0x150>>1) && offset!=(0x0>>1) && offset!=(0x110>>1) && offset!=(0x280>>1)
+ && offset!=(0x290>>1) && offset!=(0x2b0>>1) && offset!=(0x370>>1) && offset!=(0x3c0>>1)
+ && offset!=(0x370>>1) && offset!=(0x3c0>>1) && offset!=(0x430>>1) && offset!=(0x460>>1)
+ && offset!=(0x5a0>>1) && offset!=(0x5b0>>1) && offset!=(0x6e0>>1) && offset!=(0x7d0>>1)
+ )
+ logerror("CONTROL PC %06x: warning - write protection memory address %04x %04x\n",activecpu_get_pc(),offset<<1,data);
+
+ COMBINE_DATA(&deco16_prot_ram[offset]);
+}
+
+READ16_HANDLER( deco16_104_prot_r ) /* Wizard Fire */
+{
+ switch (offset<<1) {
+ case 0x110: /* Player input */
+ return readinputport(0);
+
+ case 0x36c: /* Coins */
+ case 0x334: /* Probably also, c6, 2c0, 2e0, 4b2, 46a, 4da, rohga is 44c */
+ return readinputport(1);
+ case 0x0dc:
+ return readinputport(1)<<4;
+
+ case 0x494: /* Dips */
+ return readinputport(2);
+
+ case 0x244:
+ return deco16_prot_ram[0];
+ case 0x7cc:
+ return ((deco16_prot_ram[0]&0x000f)<<12) | ((deco16_prot_ram[0]&0x00f0)<<4) | ((deco16_prot_ram[0]&0x0f00)>>4) | ((deco16_prot_ram[0]&0xf000)>>12);
+ case 0x0c0:
+ return (((deco16_prot_ram[0]&0x000e)>>1) | ((deco16_prot_ram[0]&0x0001)<<3))<<12;
+ case 0x188:
+ return (((deco16_prot_ram[0]&0x000e)>>1) | ((deco16_prot_ram[0]&0x0001)<<3))<<12;
+ case 0x65e:
+ return (((deco16_prot_ram[0]&0x000c)>>2) | ((deco16_prot_ram[0]&0x0003)<<2))<<12;
+ case 0x5ce:
+ return ((deco16_prot_ram[0]<<8)&0xf000) | ((deco16_prot_ram[0]&0xe)<<7) | ((deco16_prot_ram[0]&0x1)<<11);
+ case 0x61a:
+ return (deco16_prot_ram[0]<<8)&0xff00;
+
+ case 0x496:
+ return deco16_prot_ram[0x110/2];
+ case 0x40a:
+ return ((deco16_prot_ram[0x110/2]&0x000f)<<12) | ((deco16_prot_ram[0x110/2]&0x00f0)>>4) | ((deco16_prot_ram[0x110/2]&0x0f00)<<0) | ((deco16_prot_ram[0x110/2]&0xf000)>>8);
+ case 0x1e8:
+ return ((deco16_prot_ram[0x110/2]&0x00ff)<<8) | ((deco16_prot_ram[0x110/2]&0xff00)>>8);
+ case 0x4bc:
+ return ((deco16_prot_ram[0x110/2]&0x0ff0)<<4) | ((deco16_prot_ram[0x110/2]&0x0003)<<6) | ((deco16_prot_ram[0x110/2]&0x000c)<<2);
+ case 0x46e:
+ return ((deco16_prot_ram[0x110/2]&0xfff0)<<0) | ((deco16_prot_ram[0x110/2]&0x0007)<<1) | ((deco16_prot_ram[0x110/2]&0x0008)>>3);
+ case 0x264:
+ return ((deco16_prot_ram[0x110/2]&0x000f)<<8) | ((deco16_prot_ram[0x110/2]&0x00f0)>>0) | ((deco16_prot_ram[0x110/2]&0x0f00)<<4);
+ case 0x172:
+ return ((deco16_prot_ram[0x110/2]&0x000f)<<4) | ((deco16_prot_ram[0x110/2]&0x00f0)<<4) | ((deco16_prot_ram[0x110/2]&0xf000)<<0);
+
+ case 0x214:
+ return deco16_prot_ram[0x280/2];
+ case 0x52e:
+ return ((deco16_prot_ram[0x280/2]&0x000f)<<8) | ((deco16_prot_ram[0x280/2]&0x00f0)>>0) | ((deco16_prot_ram[0x280/2]&0x0f00)>>8) | ((deco16_prot_ram[0x280/2]&0xf000)>>0);
+ case 0x07a:
+ return ((deco16_prot_ram[0x280/2]&0x000f)<<8) | ((deco16_prot_ram[0x280/2]&0x00f0)>>0) | ((deco16_prot_ram[0x280/2]&0x0f00)>>8) | ((deco16_prot_ram[0x280/2]&0xf000)>>0);
+ case 0x360:
+ return ((deco16_prot_ram[0x280/2]&0x000f)<<8) | ((deco16_prot_ram[0x280/2]&0x00f0)>>0) | ((deco16_prot_ram[0x280/2]&0x0f00)>>8) | ((deco16_prot_ram[0x280/2]&0xf000)>>0);
+ case 0x4dc:
+ return ((deco16_prot_ram[0x280/2]&0x0ff0)<<4) | ((deco16_prot_ram[0x280/2]&0x0007)<<5) | ((deco16_prot_ram[0x280/2]&0x0008)<<1);
+ case 0x3a8:
+ return ((deco16_prot_ram[0x280/2]&0x000e)<<3) | ((deco16_prot_ram[0x280/2]&0x0001)<<7) | ((deco16_prot_ram[0x280/2]&0x0ff0)<<4) | ((deco16_prot_ram[0x280/2]&0xf000)>>12);
+ case 0x2f6:
+ return ((deco16_prot_ram[0x280/2]&0xff00)>>8) | ((deco16_prot_ram[0x280/2]&0x00f0)<<8) | ((deco16_prot_ram[0x280/2]&0x000c)<<6) | ((deco16_prot_ram[0x280/2]&0x0003)<<10);
+
+ case 0x7e4:
+ return (deco16_prot_ram[0x290/2]&0x00f0)<<8;
+
+ case 0x536:
+ return ((deco16_prot_ram[0x2b0/2]&0x000f)<<8) | ((deco16_prot_ram[0x2b0/2]&0x00f0)<<0) | ((deco16_prot_ram[0x2b0/2]&0x0f00)<<4) | ((deco16_prot_ram[0x2b0/2]&0xf000)>>12);
+
+ case 0x0be:
+ return ((deco16_prot_ram[0x370/2]&0x000f)<<4) | ((deco16_prot_ram[0x370/2]&0x00f0)<<4) | ((deco16_prot_ram[0x370/2]&0x0f00)>>8) | ((deco16_prot_ram[0x370/2]&0xf000)>>0);
+
+ case 0x490:
+ return (deco16_prot_ram[0x3c0/2]&0xfff0) | ((deco16_prot_ram[0x3c0/2]&0x0007)<<1) | ((deco16_prot_ram[0x3c0/2]&0x0008)>>3);
+
+ case 0x710:
+ return (deco16_prot_ram[0x430/2]&0xfff0) | ((deco16_prot_ram[0x430/2]&0x0007)<<1) | ((deco16_prot_ram[0x430/2]&0x0008)>>3);
+
+ case 0x22a:
+ return ((deco16_prot_ram[0x5a0/2]&0xff00)>>8) | ((deco16_prot_ram[0x5a0/2]&0x00f0)<<8) | ((deco16_prot_ram[0x5a0/2]&0x0001)<<11) | ((deco16_prot_ram[0x5a0/2]&0x000e)<<7);
+
+ case 0x626:
+ return ((deco16_prot_ram[0x5b0/2]&0x000f)<<8) | ((deco16_prot_ram[0x5b0/2]&0x00f0)<<8) | ((deco16_prot_ram[0x5b0/2]&0x0f00)>>4) | ((deco16_prot_ram[0x5b0/2]&0xf000)>>12);
+
+ case 0x444:
+ return deco16_prot_ram[0x604/2]; //rohga
+
+ case 0x5ac:
+ return ((deco16_prot_ram[0x6e0/2]&0xfff0)>>4) | ((deco16_prot_ram[0x6e0/2]&0x0007)<<13) | ((deco16_prot_ram[0x6e0/2]&0x0008)<<9);
+
+ case 0x650:
+ return ((deco16_prot_ram[0x7d0/2]&0xfff0)>>4) | ((deco16_prot_ram[0x7d0/2]&0x000f)<<12);
+
+ case 0x4ac:
+ return ((deco16_prot_ram[0x460/2]&0x0007)<<13) | ((deco16_prot_ram[0x460/2]&0x0008)<<9);
+ }
+
+ logerror("Deco Protection PC %06x: warning - read unmapped memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return 0;
+}
+
+/***************************************************************************/
+
+WRITE16_HANDLER( deco16_60_prot_w ) /* Edward Randy */
+{
+ if (offset==(0x64/2)) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ }
+
+ COMBINE_DATA(&deco16_prot_ram[offset]);
+
+// 0 4 2c 32 34 36 3c 3e 40 54 56 58 6a 76 80 84 88 8a 8c 8e 90 92 94 96 9e a0 a2 a4 a6 a8 aa ac ae b0
+
+if (offset!=0x32 && offset!=0x36/2 && offset!=0x9e/2 && offset!=0x76/2
+ && offset!=4/2 && offset!=0x2c/2 && offset!=0x3c/2 && offset!=0x3e/2
+ && offset!=0x80/2 && offset!=0x84/2 &&offset!=0x88/2 && offset!=0x8c/2 && offset!=0x90/2 && offset!=0x94/2
+ && offset!=0xa0/2 &&offset!=0xa2/2 && offset!=0xa4/2 && offset!=0xa6/2 && offset!=0xa8/2
+ && offset!=0xaa/2 && offset!=0xac/2 && offset!=0xae/2 && offset!=0xb0/2
+ && (offset<0xd0/2 || offset>0xe0/2)
+ && (offset<4 || offset>17)
+ && offset!=0x40/2 && offset!=0x54/2 && offset!=0x56/2 && offset!=0x58/2 && offset!=0x6a/2 && offset!=0x2c/2
+ && offset!=0 && offset!=0x34 && offset!=0x8a && offset!=0x8e && offset!=0x92 && offset!=0x96
+ )
+logerror("Protection PC %06x: warning - write %04x to %04x\n",activecpu_get_pc(),data,offset<<1);
+
+}
+
+READ16_HANDLER( deco16_60_prot_r ) /* Edward Randy */
+{
+ switch (offset<<1) {
+ /* Video registers */
+ case 0x32a: /* Moved to 0x140006 on int */
+ return deco16_prot_ram[0x80/2];
+ case 0x380: /* Moved to 0x140008 on int */
+ return deco16_prot_ram[0x84/2];
+ case 0x63a: /* Moved to 0x150002 on int */
+ return deco16_prot_ram[0x88/2];
+ case 0x42a: /* Moved to 0x150004 on int */
+ return deco16_prot_ram[0x8c/2];
+ case 0x030: /* Moved to 0x150006 on int */
+ return deco16_prot_ram[0x90/2];
+ case 0x6b2: /* Moved to 0x150008 on int */
+ return deco16_prot_ram[0x94/2];
+
+ case 0x6fa:
+ return deco16_prot_ram[0x4/2];
+ case 0xe4:
+ return (deco16_prot_ram[0x4/2]&0xf000)|((deco16_prot_ram[0x4/2]&0x00ff)<<4)|((deco16_prot_ram[0x4/2]&0x0f00)>>8);
+
+ case 0x390:
+ return deco16_prot_ram[0x2c/2];
+ case 0x3b2:
+ return deco16_prot_ram[0x3c/2];
+ case 0x440:
+ return deco16_prot_ram[0x3e/2];
+
+ case 0x6fc:
+ return deco16_prot_ram[0x66/2];
+
+ case 0x15a:
+ return deco16_prot_ram[0xa0/2];
+ case 0x102:
+ return deco16_prot_ram[0xa2/2];
+ case 0x566:
+ return deco16_prot_ram[0xa4/2];
+ case 0xd2:
+ return deco16_prot_ram[0xa6/2];
+ case 0x4a6:
+ return deco16_prot_ram[0xa8/2];
+ case 0x3dc:
+ return deco16_prot_ram[0xaa/2];
+ case 0x2a0:
+ return deco16_prot_ram[0xac/2];
+ case 0x392:
+ return deco16_prot_ram[0xae/2];
+ case 0x444:
+ return deco16_prot_ram[0xb0/2];
+
+ case 0x5ea:
+ return deco16_prot_ram[0xb8/2];
+ case 0x358:
+ return deco16_prot_ram[0xba/2];
+ case 0x342:
+ return deco16_prot_ram[0xbc/2];
+ case 0x3c:
+ return deco16_prot_ram[0xbe/2];
+ case 0x656:
+ return deco16_prot_ram[0xc0/2];
+ case 0x18c:
+ return deco16_prot_ram[0xc2/2];
+ case 0x370:
+ return deco16_prot_ram[0xc4/2];
+ case 0x5c6:
+ return deco16_prot_ram[0xc6/2];
+
+ /* C8 written but not read */
+
+ case 0x248:
+ return deco16_prot_ram[0xd0/2];
+ case 0x1ea:
+ return deco16_prot_ram[0xd2/2];
+ case 0x4cc:
+ return deco16_prot_ram[0xd4/2];
+ case 0x724:
+ return deco16_prot_ram[0xd6/2];
+ case 0x578:
+ return deco16_prot_ram[0xd8/2];
+ case 0x63e:
+ return deco16_prot_ram[0xda/2];
+ case 0x4ba:
+ return deco16_prot_ram[0xdc/2];
+ case 0x1a:
+ return deco16_prot_ram[0xde/2];
+ case 0x120:
+ return deco16_prot_ram[0xe0/2];
+ case 0x7c2: /* (Not checked for mask/xor but seems standard) */
+ return deco16_prot_ram[0x50/2];
+
+ /* memcpy selectors, transfer occurs in interrupt */
+ case 0x32e: return deco16_prot_ram[4]; /* src msb */
+ case 0x6d8: return deco16_prot_ram[5]; /* src lsb */
+ case 0x010: return deco16_prot_ram[6]; /* dst msb */
+ case 0x07a: return deco16_prot_ram[7]; /* src lsb */
+
+ case 0x37c: return deco16_prot_ram[8]; /* src msb */
+ case 0x250: return deco16_prot_ram[9];
+ case 0x04e: return deco16_prot_ram[10];
+ case 0x5ba: return deco16_prot_ram[11];
+ case 0x5f4: return deco16_prot_ram[12]; /* length */
+
+ case 0x38c: return deco16_prot_ram[13]; /* src msb */
+ case 0x02c: return deco16_prot_ram[14];
+ case 0x1e6: return deco16_prot_ram[15];
+ case 0x3e4: return deco16_prot_ram[16];
+ case 0x174: return deco16_prot_ram[17]; /* length */
+
+ /* Player 1 & 2 controls, read in IRQ then written *back* to protection device */
+ case 0x50: /* written to 9e byte */
+ return readinputport(0);
+ case 0x6f8: /* written to 76 byte */
+ return (readinputport(0)>>8)|(readinputport(0)<<8); /* byte swap IN0 */
+
+ case 0x5c: /* After coin insert, high 0x8000 bit set starts game */
+ return deco16_prot_ram[0x3b];
+ case 0x3a6: /* Top byte OR'd with above, masked to 7 */
+ return deco16_prot_ram[0x9e/2];
+ case 0xc6:
+ return ((deco16_prot_ram[0x9e/2]&0xff00)>>8) | ((deco16_prot_ram[0x9e/2]&0x00ff)<<8);
+
+ case 0xac: /* Dip switches */
+ return readinputport(2);
+ case 0xc2:
+ return readinputport(2) ^ deco16_prot_ram[0x2c/2];
+
+ case 0x5d4: /* The state of the dips last frame */
+ return deco16_prot_ram[0x34/2];
+
+ case 0x7bc:
+ return ((deco16_prot_ram[0x76/2]&0xff00)>>8) | ((deco16_prot_ram[0x76/2]&0x00ff)<<8);
+
+ case 0x2f6: /* Stage clear flag */
+ return (((deco16_prot_ram[0]&0xfff0)>>0) | ((deco16_prot_ram[0]&0x000c)>>2) | ((deco16_prot_ram[0]&0x0003)<<2)) & (~deco16_prot_ram[0x36/2]);
+
+ case 0x76a: /* Coins */
+ return readinputport(1);
+
+ case 0x284: /* Bit shifting with inverted mask register */
+ return (((deco16_prot_ram[0x40/2]&0xfff0)>>0) | ((deco16_prot_ram[0x40/2]&0x0007)<<1) | ((deco16_prot_ram[0x40/2]&0x0008)>>3)) & (~deco16_prot_ram[0x36/2]);
+ case 0x6c4: /* Bit shifting with inverted mask register */
+ return (((deco16_prot_ram[0x54/2]&0xf000)>>4) | ((deco16_prot_ram[0x54/2]&0x0f00)>>4) | ((deco16_prot_ram[0x54/2]&0x00f0)>>4) | ((deco16_prot_ram[0x54/2]&0x0003)<<14) | ((deco16_prot_ram[0x54/2]&0x000c)<<10)) & (~deco16_prot_ram[0x36/2]);
+ case 0x33e: /* Bit shifting with inverted mask register */
+ return (((deco16_prot_ram[0x56/2]&0xff00)>>0) | ((deco16_prot_ram[0x56/2]&0x00f0)>>4) | ((deco16_prot_ram[0x56/2]&0x000f)<<4)) & (~deco16_prot_ram[0x36/2]);
+ case 0x156: /* Bit shifting with inverted mask register */
+ return (((deco16_prot_ram[0x58/2]&0xfff0)>>4) | ((deco16_prot_ram[0x58/2]&0x000e)<<11) | ((deco16_prot_ram[0x58/2]&0x0001)<<15)) & (~deco16_prot_ram[0x36/2]);
+ case 0x286: /* Bit shifting with inverted mask register */
+ return (((deco16_prot_ram[0x6a/2]&0x00f0)<<4) | ((deco16_prot_ram[0x6a/2]&0x0f00)<<4) | ((deco16_prot_ram[0x6a/2]&0x0007)<<5) | ((deco16_prot_ram[0x6a/2]&0x0008)<<1)) & (~deco16_prot_ram[0x36/2]);
+
+ case 0x7d6: /* XOR IN0 */
+ return readinputport(0) ^ deco16_prot_ram[0x2c/2];
+ case 0x4b4:
+ return ((deco16_prot_ram[0x32/2]&0x00f0)<<8) | ((deco16_prot_ram[0x32/2]&0x000e)<<7) | ((deco16_prot_ram[0x32/2]&0x0001)<<11);
+ }
+
+ logerror("Protection PC %06x: warning - read unmapped memory address %04x\n",activecpu_get_pc(),offset*2);
+ return 0;
+}
+
+/***************************************************************************/
+
+static int mutantf_port_0e_hack=0, mutantf_port_6a_hack=0,mutantf_port_e8_hack=0;
+
+WRITE16_HANDLER( deco16_66_prot_w ) /* Mutant Fighter */
+{
+ if (offset==(0x64/2)) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ return;
+ }
+
+ COMBINE_DATA(&deco16_prot_ram[offset]);
+
+ /* See below */
+ if (offset==(0xe/2))
+ mutantf_port_0e_hack=data;
+ else
+ mutantf_port_0e_hack=0x800;
+
+ if (offset==(0x6a/2))
+ mutantf_port_6a_hack=data;
+ else
+ mutantf_port_6a_hack=0x2866;
+
+ if (offset==(0xe8/2))
+ mutantf_port_e8_hack=data;
+ else
+ mutantf_port_e8_hack=0x2401;
+
+// 2 4 c e 18 1e 22 2c 2e 34 36 38 3a 42 48 58 6a 72 7a 82 88 92 a2 a4 aa b0 b6 b8 dc e4 e8 f4 fa 1c8 308 7e8 40e
+ offset=offset<<1;
+ if (offset!=0x02 && offset!=0xc && offset!=0xe && offset!=0x18 && offset!=0x2c && offset!=0x2e && offset!=0x34
+ && offset!=0x42 && offset!=0x58 && offset!=0x6a && offset!=0x72 && offset!=0x7a && offset!=0xb8
+ && offset!=0xdc && offset!=0xe8 && offset!=0xf4 && offset!=0x1c8 && offset!=0x7e8
+ && offset!=0xe && offset!=0x48 && offset!=0xaa && offset!=0xb0 && offset!=0x36
+ && offset!=0xa4 && offset!=0x4 && offset!=0x82 && offset!=0x88 && offset!=0x22
+ && offset!=0xb6 && offset!=0xfa && offset!=0xe4 && offset!=0x3a && offset!=0x1e
+ && offset!=0x38 && offset!=0x92 && offset!=0xa2 && offset!=0x308 && offset!=0x40e
+ )
+ logerror("Protection PC %06x: warning - write %04x to %04x\n",activecpu_get_pc(),data,offset);
+}
+
+READ16_HANDLER( deco16_66_prot_r ) /* Mutant Fighter */
+{
+ if (offset!=0xe/2)
+ mutantf_port_0e_hack=0x0800;
+ if (offset!=0x6a/2)
+ mutantf_port_6a_hack=0x2866;
+
+ switch (offset*2) {
+ case 0xac: /* Dip switches */
+ return readinputport(2);
+ case 0xc2: /* Dip switches */
+ return readinputport(2) ^ deco16_prot_ram[0x2c/2];
+ case 0x46: /* Coins */
+ return readinputport(1) ^ deco16_prot_ram[0x2c/2];
+ case 0x50: /* Player 1 & 2 input ports */
+ return readinputport(0);
+ case 0x63c: /* Player 1 & 2 input ports */
+ return readinputport(0) ^ deco16_prot_ram[0x2c/2];
+
+ case 0x5f4:
+ return deco16_prot_ram[0x18/2];
+ case 0x7e8:
+ return deco16_prot_ram[0x58/2];
+ case 0x1c8:
+ return deco16_prot_ram[0x6a/2];
+ case 0x10:
+ return deco16_prot_ram[0xc/2];
+ case 0x672:
+ return deco16_prot_ram[0x72/2];
+ case 0x5ea:
+ return deco16_prot_ram[0xb8/2];
+ case 0x1e8:
+ return deco16_prot_ram[0x2/2];
+ case 0xf6:
+ return deco16_prot_ram[0x42/2];
+ case 0x692:
+ return deco16_prot_ram[0x2e/2];
+ case 0x63a:
+ return deco16_prot_ram[0x88/2];
+ case 0x7a:
+ return deco16_prot_ram[0xe/2];
+ case 0x40e:
+ return deco16_prot_ram[0x7a/2];
+ case 0x602:
+ return deco16_prot_ram[0x92/2];
+ case 0x5d4:
+ return deco16_prot_ram[0x34/2];
+ case 0x6fa:
+ return deco16_prot_ram[0x4/2];
+ case 0x3dc:
+ return deco16_prot_ram[0xaa/2];
+ case 0x444:
+ return deco16_prot_ram[0xb0/2];
+ case 0x102:
+ return deco16_prot_ram[0xa2/2];
+ case 0x458:
+ return deco16_prot_ram[0xb6/2];
+ case 0x2a6:
+ return deco16_prot_ram[0xe8/2];
+ case 0x626:
+ return deco16_prot_ram[0xf4/2];
+ case 0x762:
+ return deco16_prot_ram[0x82/2];
+ case 0x308:
+ return deco16_prot_ram[0x38/2];
+ case 0x1e6:
+ return deco16_prot_ram[0x1e/2];
+ case 0x566:
+ return deco16_prot_ram[0xa4/2];
+ case 0x5b6:
+ return deco16_prot_ram[0xe4/2];
+ case 0x77c:
+ return deco16_prot_ram[0xfa/2];
+ case 0x4ba:
+ return deco16_prot_ram[0xdc/2];
+
+ case 0x1e:
+ return deco16_prot_ram[0xf4/2] ^ deco16_prot_ram[0x2c/2];
+ case 0x18e:
+ return ((deco16_prot_ram[0x1e/2]&0x000f)<<12) | ((deco16_prot_ram[0x1e/2]&0x0ff0)>>0) | ((deco16_prot_ram[0x1e/2]&0xf000)>>12);
+ case 0x636:
+ return ((deco16_prot_ram[0x18/2]&0x00ff)<<8) | ((deco16_prot_ram[0x18/2]&0x0f00)>>4) | ((deco16_prot_ram[0x18/2]&0xf000)>>12);
+ case 0x7d4:
+ return ((deco16_prot_ram[0xc/2]&0x0ff0)<<4) | ((deco16_prot_ram[0xc/2]&0x000c)<<2) | ((deco16_prot_ram[0xc/2]&0x0003)<<6);
+ case 0x542:
+ return ((deco16_prot_ram[0x92/2]&0x00ff)<<8) ^ deco16_prot_ram[0x2c/2];
+ case 0xb0:
+ return (((deco16_prot_ram[0xc/2]&0x000f)<<12) | ((deco16_prot_ram[0xc/2]&0x00f0)<<4) | ((deco16_prot_ram[0xc/2]&0xff00)>>8)) ^ deco16_prot_ram[0x2c/2];
+ case 0x4:
+ return (((deco16_prot_ram[0x18/2]&0x00f0)<<8) | ((deco16_prot_ram[0x18/2]&0x0003)<<10) | ((deco16_prot_ram[0x18/2]&0x000c)<<6)) & (~deco16_prot_ram[0x36/2]);
+
+ case 0xe: /* On real hardware this value only seems to persist for 1 read or write, then reverts to 0800. Hmm */
+ {
+ int ret=mutantf_port_0e_hack;
+ mutantf_port_0e_hack=0x800;
+ //logerror("Protection PC %06x: warning - read unknown memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return ret;
+ }
+
+ case 0x6a: /* On real hardware this value only seems to persist for 1 read or write, then reverts to 0x2866. Hmm */
+ {
+ int ret=mutantf_port_6a_hack;
+ mutantf_port_6a_hack=0x2866;
+ //logerror("Protection PC %06x: warning - read unknown memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return ret;
+ }
+
+ case 0xe8: /* On real hardware this value only seems to persist for 1 read or write, then reverts to 0x2401. Hmm */
+ {
+ int ret=mutantf_port_e8_hack;
+ mutantf_port_e8_hack=0x2401;
+ //logerror("Protection PC %06x: warning - read unknown memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return ret;
+ }
+
+ case 0xaa: /* ??? */
+ //logerror("Protection PC %06x: warning - read unknown memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return 0xc080;
+
+ case 0x42: /* Strange, but consistent */
+ //logerror("Protection PC %06x: warning - read unknown memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return deco16_prot_ram[0x2c/2]^0x5302;
+
+ case 0x48: /* Correct for test data, but I wonder if the 0x1800 is from an address, not a constant */
+ //logerror("Protection PC %06x: warning - read unmapped memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return (0x1800) & (~deco16_prot_ram[0x36/2]);
+
+ case 0x52:
+ return (0x2188) & (~deco16_prot_ram[0x36/2]);
+
+ case 0x82:
+ return ((0x0022 ^ deco16_prot_ram[0x2c/2])) & (~deco16_prot_ram[0x36/2]);
+
+ case 0xc:
+ return 0x2000;
+ }
+
+#ifdef MAME_DEBUG
+ popmessage("Deco66: Read unmapped port %04x\n",offset*2);
+#endif
+
+ logerror("Protection PC %06x: warning - read unmapped memory address %04x\n",activecpu_get_pc(),offset<<1);
+ return 0;
+}
+
+/***************************************************************************/
+
+WRITE16_HANDLER( deco16_104_cninja_prot_w )
+{
+ if (offset==(0xa8/2)) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ return;
+ }
+
+ COMBINE_DATA(&deco16_prot_ram[offset]);
+}
+
+READ16_HANDLER( deco16_104_cninja_prot_r )
+{
+ switch (offset<<1) {
+ case 0x80: /* Master level control */
+ return deco16_prot_ram[0];
+
+ case 0xde: /* Restart position control */
+ return deco16_prot_ram[1];
+
+ case 0xe6: /* The number of credits in the system. */
+ return deco16_prot_ram[2];
+
+ case 0x86: /* End of game check. See 0x1814 */
+ return deco16_prot_ram[3];
+
+ /* Video registers */
+ case 0x5a: /* Moved to 0x140000 on int */
+ return deco16_prot_ram[8];
+ case 0x84: /* Moved to 0x14000a on int */
+ return deco16_prot_ram[9];
+ case 0x20: /* Moved to 0x14000c on int */
+ return deco16_prot_ram[10];
+ case 0x72: /* Moved to 0x14000e on int */
+ return deco16_prot_ram[11];
+ case 0xdc: /* Moved to 0x150000 on int */
+ return deco16_prot_ram[12];
+ case 0x6e: /* Moved to 0x15000a on int */
+ return deco16_prot_ram[13]; /* Not used on bootleg */
+ case 0x6c: /* Moved to 0x15000c on int */
+ return deco16_prot_ram[14];
+ case 0x08: /* Moved to 0x15000e on int */
+ return deco16_prot_ram[15];
+
+ case 0x36: /* Dip switches */
+ return readinputport(2);
+
+ case 0x1c8: /* Coins */
+ return readinputport(1);
+
+ case 0x22c: /* Player 1 & 2 input ports */
+ return readinputport(0);
+ }
+
+ logerror("Protection PC %06x: warning - read unmapped memory address %04x\n",activecpu_get_pc(),offset);
+ return 0;
+}
+
+/***************************************************************************/
+
+WRITE16_HANDLER( deco16_146_funkyjet_prot_w )
+{
+ COMBINE_DATA(&deco16_prot_ram[offset]);
+
+ if (offset == (0x10a >> 1)) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ return;
+ }
+}
+
+READ16_HANDLER( deco16_146_funkyjet_prot_r )
+{
+ switch (offset)
+ {
+ case 0x0be >> 1:
+ return deco16_prot_ram[0x106>>1];
+ case 0x11e >> 1:
+ return deco16_prot_ram[0x500>>1];
+
+ case 0x148 >> 1: /* EOR mask for joysticks */
+ return deco16_prot_ram[0x70e>>1];
+
+ case 0x1da >> 1:
+ return deco16_prot_ram[0x100>>1];
+ case 0x21c >> 1:
+ return deco16_prot_ram[0x504>>1];
+ case 0x226 >> 1:
+ return deco16_prot_ram[0x58c>>1];
+ case 0x24c >> 1:
+ return deco16_prot_ram[0x78e>>1];
+ case 0x250 >> 1:
+ return deco16_prot_ram[0x304>>1];
+ case 0x2d4 >> 1:
+ return deco16_prot_ram[0x102>>1];
+ case 0x2d8 >> 1: /* EOR mask for credits */
+ return deco16_prot_ram[0x502>>1];
+
+ case 0x3a6 >> 1:
+ return deco16_prot_ram[0x104>>1];
+ case 0x3a8 >> 1: /* See 93e4/9376 */
+ return deco16_prot_ram[0x500>>1];
+ case 0x3e8 >> 1:
+ return deco16_prot_ram[0x50c>>1];
+
+ case 0x4e4 >> 1:
+ return deco16_prot_ram[0x702>>1];
+ case 0x562 >> 1:
+ return deco16_prot_ram[0x18e>>1];
+ case 0x56c >> 1:
+ return deco16_prot_ram[0x50c>>1];
+
+ case 0x688 >> 1:
+ return deco16_prot_ram[0x300>>1];
+ case 0x788 >> 1:
+ return deco16_prot_ram[0x700>>1];
+
+ case 0x7d4 >> 1: /* !? On the bootleg these address checks are NOP'd, so a BEQ is never taken */
+ return 0x10; //deco16_prot_ram[0x7da>>1];
+
+ case 0x27c >>1: /* From bootleg code at 0x400 */
+ return ((deco16_prot_ram[0x70e>>1]>>4)&0x0fff) | ((deco16_prot_ram[0x70e>>1]&0x0001)<<15) | ((deco16_prot_ram[0x70e>>1]&0x000e)<<11);
+ case 0x192 >>1: /* From bootleg code at 0x400 */
+ return ((deco16_prot_ram[0x78e>>1]<<0)&0xf000);
+
+ case 0x5be >> 1: /* Confirmed from bootleg code at 0xc07c */
+ return ((deco16_prot_ram[0x70e>>1]<<4)&0xff00) | (deco16_prot_ram[0x70e>>1]&0x000f);
+ case 0x5ca >> 1: /* Confirmed from bootleg code at 0xc05e */
+ return ((deco16_prot_ram[0x78e>>1]>>4)&0xff00) | (deco16_prot_ram[0x78e>>1]&0x000f) | ((deco16_prot_ram[0x78e>>1]<<8)&0xf000);
+
+ case 0x00c >> 1: /* Player 1 & Player 2 joysticks & fire buttons */
+ return (readinputport(0) + (readinputport(1) << 8));
+ case 0x778 >> 1: /* Credits */
+ return readinputport(2);
+ case 0x382 >> 1: /* DIPS */
+ return (readinputport(3) + (readinputport(4) << 8));
+ }
+
+ if (activecpu_get_pc()!=0xc0ea) logerror("CPU #0 PC %06x: warning - read unmapped control address %06x\n",activecpu_get_pc(),offset<<1);
+
+ return 0;
+}
+
+/***************************************************************************/
+
+WRITE16_HANDLER( deco16_104_rohga_prot_w )
+{
+ /*
+ Schmeizr uses a feature of this chip that other games don't seem to exploit. There
+ appear to be two banks of data ports (referred to here as front and back buffers).
+ These banks are switched when certain addresses are read - also very good protection
+ against trojans as it is non-obvious when data ports are switched.
+
+ It appears to work as follows.. When the front buffer is active (the state upon
+ reset) any writes to data ports push the existing front buffer word into the back
+ buffer (ie, a FIFO latch type of system). When the back buffer is active, any writes
+ to data ports affect the back buffer only - the front buffer data is not affected, and
+ there is no FIFO action.
+
+ By default the read ports return a scrambled address and scrambled data from a
+ front buffer port. When the back buffer is active most read ports return scrambled
+ data from the back buffer, however some ports work exclusively on front buffer data
+ even if the back buffer is selected.
+
+ There doesn't appear to be any way to detect what bank is currently selected - it
+ seems game code must maintain this state (if it matters).
+ */
+
+ if (decoprot_buffer_ram_selected)
+ COMBINE_DATA(&decoprot_buffer_ram[offset]);
+ else
+ COMBINE_DATA(&deco16_prot_ram[offset]);
+
+ if (offset==(0xa8/2)) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ return;
+ }
+
+ // These are set regardless of bank
+ if (offset==0x42/2)
+ COMBINE_DATA(&deco16_xor);
+ if (offset==0xee/2)
+ COMBINE_DATA(&deco16_mask);
+
+ offset=offset*2;
+
+ //logerror("CONTROL PC %06x: warning - write protection memory address %04x %04x\n",activecpu_get_pc(),offset,data);
+ if (offset==0xee || offset==0x42 || offset==0xa8)
+ return;
+
+// logerror("CONTROL PC %06x: warning - write protection memory address %04x %04x\n",activecpu_get_pc(),offset,data);
+
+#if 1
+// 66 7c 7e 28 58 4a 9e
+ if (offset==0x66 || offset==0x7c || offset==0x7e || offset==0x28 || offset==0x58 || offset==0x4a)
+ return;
+ if (offset==0x9e || offset==0x7c || offset==0x7e || offset==0x28 || offset==0x58 || offset==0x4a)
+ return;
+#endif
+
+#if 1
+ if (offset>=0x80 && offset<0xa0)
+ return;
+ if (offset>=0xc0 && offset<0xd0)
+ return;
+
+// if (offset==0x3c)
+// logerror("CONTROL PC %06x: warning - write protection memory address %04x %04x\n",activecpu_get_pc(),offset,data);
+// Actually read:
+// 22 24 26 2c 2e 30 32 3c 40 44 46 48 60 62 66 6a 6e 76 7e 80 82 84 86 88 8a 8c 90 94 96 98 9a 9c a0 c0 c4 c6 c8 cc ce d6 dc de
+
+// check 74 b0 b4 d4
+
+// 24 2a 2c 2e 30 3c 44 48 66 6a 74 a0 b0 b4 d4 d6
+// 32 60 7e
+// 22 26 a4 a6
+// 62 6e d0 dc de d2 d8 da 46
+ if (offset==0x24 || offset==0x2a || offset==0x2c || offset==0x2e || offset==0x30 || offset==0x3c)
+ return;
+ if (offset==0x44 || offset==0x48 || offset==0x66 || offset==0x6a || offset==0x74 || offset==0xa0)
+ return;
+ if (offset==0xb0 || offset==0xb4 || offset==0xd4 || offset==0xd6)
+ return;
+ if (offset==0x32 || offset==0x60 || offset==0x7e || offset==0xa4 || offset==0xa6)
+ return;
+ if (offset==0x22 || offset==0x26 || offset==0x62 || offset==0xd0 || offset==0xdc)
+ return;
+ if (offset==0xde || offset==0xd2 || offset==0xd8 || offset==0xda || offset==0x46)
+ return;
+ if (offset==0x20 || offset==0x40)
+ return;
+ if (offset==0x6e || offset==0xaa || offset==0xac || offset==0xa2)
+ return;
+#endif
+
+ logerror("CONTROL PC %06x: warning - write unmapped protection memory address %04x %04x\n",activecpu_get_pc(),offset,data);
+}
+
+READ16_HANDLER( deco16_104_rohga_prot_r )
+{
+ const UINT16* prot_ram=decoprot_buffer_ram_selected ? decoprot_buffer_ram : deco16_prot_ram;
+
+// if (offset!=0x88/2 && offset!=0x44c/2 && offset!=0x36c/2 && offset!=0x292/2)
+// logerror("Protection PC %06x: warning - read prot address %04x\n",activecpu_get_pc(),offset<<1);
+
+ switch (offset) {
+ case 0x88/2: /* Player 1 & 2 input ports */
+ return readinputport(0);
+ case 0x36c/2:
+ return readinputport(1);
+ case 0x44c/2:
+
+ return ((readinputport(1)&0x7)<<13)|((readinputport(1)&0x8)<<9);
+ case 0x292/2: /* Dips */
+ return readinputport(2);
+
+ case 0x44/2:
+ return ((((DECO_PORT(0x2c)&0x000f)<<12)) ^ deco16_xor) & (~deco16_mask);
+ case 0x282/2:
+ return ((DECO_PORT(0x26)&0x000f)<<12) & (~deco16_mask);
+ case 0xd4/2:
+ return ((DECO_PORT(0x6e)&0x0ff0)<<4) | ((DECO_PORT(0x6e)&0x000e)<<3) | ((DECO_PORT(0x6e)&0x0001)<<7);
+ case 0x5a2/2:
+ return (((DECO_PORT(0x24)&0xff00)>>4) | ((DECO_PORT(0x24)&0x000f)<<0) | ((DECO_PORT(0x24)&0x00f0)<<8)) & (~deco16_mask);
+ case 0x570/2:
+ return (((DECO_PORT(0x24)&0xf0f0)>>0) | ((DECO_PORT(0x24)&0x000f)<<8)) ^ deco16_xor;
+ case 0x32e/2:
+ return (((DECO_PORT(0x46)&0xf000)>>0) | ((DECO_PORT(0x46)&0x00ff)<<4)) & (~deco16_mask);
+ case 0x4dc/2:
+ return ((DECO_PORT(0x62)&0x00ff)<<8);
+ case 0x1be/2:
+ return ((((DECO_PORT(0xc2)&0x0ff0)<<4) | ((DECO_PORT(0xc2)&0x0003)<<6) | ((DECO_PORT(0xc2)&0x000c)<<2)) ^ deco16_xor) & (~deco16_mask);
+
+ case 0x420/2:
+ return ((DECO_PORT(0x2e)&0xf000)>>4) | ((DECO_PORT(0x2e)&0x0f00)<<4) | ((DECO_PORT(0x2e)&0x00f0)>>4) | ((DECO_PORT(0x2e)&0x000f)<<4);
+
+ case 0x390/2:
+ return DECO_PORT(0x2c);
+
+ case 0x756/2:
+ return ((DECO_PORT(0x60)&0xfff0)>>4) | ((DECO_PORT(0x60)&0x0007)<<13) | ((DECO_PORT(0x60)&0x0008)<<9);
+ case 0x424/2:
+ return ((DECO_PORT(0x60)&0xf000)>>4) | ((DECO_PORT(0x60)&0x0f00)<<4) | ((DECO_PORT(0x60)&0x00f0)>>0) | ((DECO_PORT(0x60)&0x000f)<<0);
+
+ case 0x156/2:
+ return (((DECO_PORT(0xde)&0xff00)<<0) | ((DECO_PORT(0xde)&0x000f)<<4) | ((DECO_PORT(0xde)&0x00f0)>>4)) & (~deco16_mask);
+ case 0xa8/2:
+ return (((DECO_PORT(0xde)&0xff00)>>4) | ((DECO_PORT(0xde)&0x000f)<<0) | ((DECO_PORT(0xde)&0x00f0)<<8)) & (~deco16_mask);
+ case 0x64a/2:
+ return (((DECO_PORT(0xde)&0xfff0)>>4) | ((DECO_PORT(0xde)&0x000c)<<10) | ((DECO_PORT(0xde)&0x0003)<<14)) & (~deco16_mask);
+
+ case 0x16e/2:
+ return DECO_PORT(0x6a);
+
+ case 0x39c/2:
+ return (DECO_PORT(0x6a)&0x00ff) | ((DECO_PORT(0x6a)&0xf000)>>4) | ((DECO_PORT(0x6a)&0x0f00)<<4);
+ case 0x212/2:
+ return (((DECO_PORT(0x6e)&0xff00)>>4) | ((DECO_PORT(0x6e)&0x00f0)<<8) | ((DECO_PORT(0x6e)&0x000f)<<0)) ^ deco16_xor;
+
+ case 0x70a/2:
+ return (((DECO_PORT(0xde)&0x00f0)<<8) | ((DECO_PORT(0xde)&0x0007)<<9) | ((DECO_PORT(0xde)&0x0008)<<5)) ^ deco16_xor;
+
+ case 0x7a0/2:
+ return (DECO_PORT(0x6e)&0x00ff) | ((DECO_PORT(0x6e)&0xf000)>>4) | ((DECO_PORT(0x6e)&0x0f00)<<4);
+ case 0x162/2:
+ return DECO_PORT(0x6e);
+
+ case 0x384/2:
+ return ((DECO_PORT(0xdc)&0xf000)>>12) | ((DECO_PORT(0xdc)&0x0ff0)<<4) | ((DECO_PORT(0xdc)&0x000c)<<2) | ((DECO_PORT(0xdc)&0x0003)<<6);
+
+ case 0x302/2:
+ return DECO_PORT(0x24);
+ case 0x334/2:
+ return DECO_PORT(0x30);
+ case 0x34c/2:
+ return DECO_PORT(0x3c);
+
+ case 0x514/2:
+ return (((DECO_PORT(0x32)&0x0ff0)<<4) | ((DECO_PORT(0x32)&0x000c)<<2) | ((DECO_PORT(0x32)&0x0003)<<6)) & (~deco16_mask);
+
+ case 0x34e/2:
+ return ((DECO_PORT(0xde)&0x0ff0)<<4) | ((DECO_PORT(0xde)&0xf000)>>8) | ((DECO_PORT(0xde)&0x000f)<<0);
+ case 0x722/2:
+ return (((DECO_PORT(0xdc)&0x0fff)<<4) ^ deco16_xor) & (~deco16_mask);
+ case 0x574/2:
+ return ((((DECO_PORT(0xdc)&0xfff0)>>0) | ((DECO_PORT(0xdc)&0x0003)<<2) | ((DECO_PORT(0xdc)&0x000c)>>2)) ^ deco16_xor) & (~deco16_mask);
+
+ case 0x5ae/2:
+ return DECO_PORT(0xdc);
+ case 0x410/2:
+ return DECO_PORT(0xde);
+ case 0x340/2:
+ return ((DECO_PORT(0x90)&0xfff0) | ((DECO_PORT(0x90)&0x7)<<1) | ((DECO_PORT(0x90)&0x8)>>3)) ^ deco16_xor;
+ case 0x4a4/2:
+ return (((DECO_PORT(0xce)&0x0ff0) | ((DECO_PORT(0xce)&0xf000)>>12) | ((DECO_PORT(0xce)&0x000f)<<12)) ^ deco16_xor) & (~deco16_mask);
+ case 0x256/2:
+ return ((((DECO_PORT(0xce)&0xf000)>>12) | ((DECO_PORT(0xce)&0x0fff)<<4))) & (~deco16_mask);
+ case 0x79a/2:
+ return (((DECO_PORT(0xc8)&0xfff0)>>4) | ((DECO_PORT(0xc8)&0x0008)<<9) | ((DECO_PORT(0xc8)&0x0007)<<13)) ^ deco16_xor;
+
+ case 0x65e/2:
+ return DECO_PORT(0x9c);
+ case 0x79c/2:
+ return ((DECO_PORT(0xc6)&0xf000) | ((DECO_PORT(0xc6)&0x00ff)<<4) | ((DECO_PORT(0xc6)&0x0f00)>>8)) & (~deco16_mask);
+ case 0x15e/2:
+ return (((DECO_PORT(0x98)&0x0ff0)<<4) | ((DECO_PORT(0x98)&0xf000)>>12) | ((DECO_PORT(0x98)&0x0003)<<6) | ((DECO_PORT(0x98)&0x000c)<<2)) ^ deco16_xor;
+ case 0x6e4/2:
+ return DECO_PORT(0x98);
+ case 0x1e/2:
+ return ((((DECO_PORT(0xc4)&0xf000)>>4) | ((DECO_PORT(0xc4)&0x0f00)<<4) | ((DECO_PORT(0xc4)&0x00ff)<<0)) ^ deco16_xor) & (~deco16_mask);
+ case 0x23a/2:
+ return ((((DECO_PORT(0x86)&0xfff0)>>0) | ((DECO_PORT(0x86)&0x0003)<<2) | ((DECO_PORT(0x86)&0x000c)>>2)) ^ deco16_xor);
+ case 0x6e/2:
+ return ((((DECO_PORT(0x96)&0xf000)>>8) | ((DECO_PORT(0x96)&0x0f0f)<<0) | ((DECO_PORT(0x96)&0x00f0)<<8)) ^ deco16_xor);
+ case 0x3a2/2:
+ return ((((DECO_PORT(0x94)&0xf000)>>8) | ((DECO_PORT(0x94)&0x0f00)>>8) | ((DECO_PORT(0x94)&0x00f0)<<8) | ((DECO_PORT(0x94)&0x000e)<<7) | ((DECO_PORT(0x94)&0x0001)<<11)) ^ deco16_xor);// & (~deco16_mask);
+ case 0x4a6/2:
+ return ((DECO_PORT(0x8c)&0xff00)>>0) | ((DECO_PORT(0x8c)&0x00f0)>>4) | ((DECO_PORT(0x8c)&0x000f)<<4);
+ case 0x7b0/2:
+ return DECO_PORT(0x80);
+ case 0x5aa/2:
+ return ((((DECO_PORT(0x98)&0x0f00)>>8) | ((DECO_PORT(0x98)&0xf000)>>8) | ((DECO_PORT(0x98)&0x00f0)<<8) | ((DECO_PORT(0x98)&0x000e)<<7) | ((DECO_PORT(0x98)&0x0001)<<11)) ^ deco16_xor) & (~deco16_mask);
+ case 0x662/2:
+ return DECO_PORT(0x8c);
+ case 0x624/2:
+ return DECO_PORT(0x9a);
+ case 0x2c/2:
+ return (((DECO_PORT(0x82)&0x0f0f)>>0) | ((DECO_PORT(0x82)&0xf000)>>8) | ((DECO_PORT(0x82)&0x00f0)<<8)) & (~deco16_mask);
+
+ case 0x1b4/2:
+ return ((DECO_PORT(0xcc)&0x00f0)<<4) | ((DECO_PORT(0xcc)&0x000f)<<12);
+
+ case 0x7ce/2:
+ return ((DECO_PORT(0x80)&0x000e)<<11) | ((DECO_PORT(0x80)&0x0001)<<15);
+ case 0x41a/2:
+ return ((((DECO_PORT(0x84)&0x00f0)<<8) | ((DECO_PORT(0x84)&0xf000)>>8) | ((DECO_PORT(0x84)&0x0f00)>>8) | ((DECO_PORT(0x84)&0x0003)<<10) | ((DECO_PORT(0x84)&0x000c)<<6)) ^ deco16_xor);
+ case 0x168/2:
+ return ((((DECO_PORT(0x84)&0x0ff0)<<4) | ((DECO_PORT(0x84)&0x000e)<<3) | ((DECO_PORT(0x84)&0x0001)<<5))) & (~deco16_mask);
+ case 0x314/2:
+ return ((((DECO_PORT(0x84)&0x0ff0)<<4) | ((DECO_PORT(0x84)&0x000e)<<3) | ((DECO_PORT(0x84)&0x0001)<<5)));
+ case 0x5e2/2:
+ return ((((DECO_PORT(0x84)&0x00f0)<<8) | ((DECO_PORT(0x84)&0x000e)<<7) | ((DECO_PORT(0x84)&0x0001)<<9)));
+ case 0x72a/2:
+ return ((((DECO_PORT(0x86)&0xfff0)>>4) | ((DECO_PORT(0x86)&0x0003)<<14) | ((DECO_PORT(0x86)&0x000c)<<10)) ^ deco16_xor) & (~deco16_mask);
+ case 0x178/2:
+ return (((DECO_PORT(0x88)&0x00ff)<<8) | ((DECO_PORT(0x88)&0xff00)>>8)) & (~deco16_mask);
+ case 0x40e/2:
+ return ((((DECO_PORT(0x8a)&0xf000)>>0) | ((DECO_PORT(0x8a)&0x00ff)<<4)) ^ deco16_xor) & (~deco16_mask);
+ case 0x248/2:
+ return ((((DECO_PORT(0x8c)&0xff00)>>8) | ((DECO_PORT(0x8c)&0x00f0)<<4) | ((DECO_PORT(0x8c)&0x000f)<<12)) ^ deco16_xor) & (~deco16_mask);
+
+ case 0x27e/2:
+ return ((((DECO_PORT(0x94)&0x00f0)<<8)) ^ deco16_xor) & (~deco16_mask);
+
+ case 0x22c/2:
+ return ((DECO_PORT(0xc4)&0x00f0)<<8);
+ case 0x77e/2:
+ return ((DECO_PORT(0x62)&0xf000)>>12) | ((DECO_PORT(0x62)&0x0ff0)<<0) | ((DECO_PORT(0x62)&0x000f)<<12);
+ case 0xc/2:
+ return ((DECO_PORT(0xd6)&0xf000)>>12) | ((DECO_PORT(0xd6)&0x0fff)<<4);
+
+ case 0x90/2:
+ return DECO_PORT(0x44);
+ case 0x246/2:
+ return ((((DECO_PORT(0x48)&0xff00)>>8) | ((DECO_PORT(0x48)&0x00f0)<<8) | ((DECO_PORT(0x48)&0x0f00)>>8) | ((DECO_PORT(0x48)&0x0003)<<10) | ((DECO_PORT(0x48)&0x000c)<<6)) ^ deco16_xor);
+ case 0x546/2:
+ return (((DECO_PORT(0x62)&0xf0f0)>>0) | ((DECO_PORT(0x62)&0x000f)<<8)) & (~deco16_mask);
+ case 0x2e2/2:
+ return ((DECO_PORT(0xc6)&0x000e)<<11) | ((DECO_PORT(0xc6)&0x0001)<<15);
+ case 0x3c0/2:
+ return DECO_PORT(0x22);
+ case 0x4b8/2:
+ return (((DECO_PORT(0x46)&0xf000)>>12) | ((DECO_PORT(0x46)&0x0f00)>>4) | ((DECO_PORT(0x46)&0x00ff)<<8)) ^ deco16_xor;
+ case 0x65c/2:
+ return ((((DECO_PORT(0x44)&0xf000)>>12) | ((DECO_PORT(0x44)&0x0fff)<<4)) ^ deco16_xor) & (~deco16_mask);
+
+ case 0x32a/2:
+ return ((((DECO_PORT(0xc0)&0x0ff0)<<4) | ((DECO_PORT(0xc0)&0x000e)<<3) | ((DECO_PORT(0xc0)&0x0001)<<7))) & (~deco16_mask);// ^ deco16_xor;
+ case 0x8/2:
+ return ((((DECO_PORT(0x94)&0xfff0)<<0) | ((DECO_PORT(0x94)&0x000e)>>1) | ((DECO_PORT(0x94)&0x0001)<<3))) & (~deco16_mask);// ^ deco16_xor;
+ case 0x456/2:
+ return (((DECO_PORT(0x26)&0xfff0)<<0) | ((DECO_PORT(0x26)&0x0007)<<1) | ((DECO_PORT(0x26)&0x0008)>>3));// ^ deco16_xor;
+ case 0x190/2:
+ return ((((DECO_PORT(0x44)&0xf000)<<0) | ((DECO_PORT(0x44)&0x00ff)<<4))) & (~deco16_mask);// ^ deco16_xor;
+ case 0x3f2/2:
+ return ((((DECO_PORT(0x48)&0x000f)<<12) | ((DECO_PORT(0x48)&0x00f0)<<4))) & (~deco16_mask);// ^ deco16_xor;
+ case 0x2be/2:
+ return ((DECO_PORT(0x40)&0x00ff)<<8);
+
+ case 0x19e/2:
+ return ((((DECO_PORT(0x3c)&0xf000)>>12) | ((DECO_PORT(0x3c)&0x0f00)<<4) | ((DECO_PORT(0x3c)&0x00f0)>>0) | ((DECO_PORT(0x3c)&0x000f)<<8)) ^ deco16_xor) & (~deco16_mask);
+ case 0x2a2/2:
+ return ((((DECO_PORT(0x44)&0xff00)>>8) | ((DECO_PORT(0x44)&0x00f0)<<8) | ((DECO_PORT(0x44)&0x000e)<<7) | ((DECO_PORT(0x44)&0x0001)<<11)) ^ deco16_xor) & (~deco16_mask);
+ case 0x748/2:
+ return (((DECO_PORT(0x44)&0xfff0)<<0) | ((DECO_PORT(0x44)&0x000e)>>1) | ((DECO_PORT(0x44)&0x0001)<<3));// & (~deco16_mask);
+ case 0x686/2:
+ return (((DECO_PORT(0x46)&0xf000)>>4) | ((DECO_PORT(0x46)&0x0f00)>>8) | ((DECO_PORT(0x46)&0x00f0)<<8) | ((DECO_PORT(0x46)&0x000f)<<4));// & (~deco16_mask);
+ case 0x4c4/2:
+ return ((DECO_PORT(0x3c)&0x000f)<<12) & (~deco16_mask);
+ case 0x538/2:
+ return ((DECO_PORT(0x3c)&0x000f)<<12);
+ case 0x63a/2:
+ return ((DECO_PORT(0x3c)&0x000f)<<12);
+ case 0x348/2:
+ return ((((DECO_PORT(0x44)&0xf000)>>12) | ((DECO_PORT(0x44)&0x0ff0)<<4) | ((DECO_PORT(0x44)&0x000e)<<3) | ((DECO_PORT(0x44)&0x0001)<<7))) ^ deco16_xor;// & (~deco16_mask);
+ case 0x200/2:
+ return (((DECO_PORT(0xa0)&0xfff0)>>4) | ((DECO_PORT(0xa0)&0x0007)<<13) | ((DECO_PORT(0xa0)&0x0008)<<9));// & (~deco16_mask);
+ case 0x254/2:
+ return ((((DECO_PORT(0x7e)&0x0ff0)<<4) | ((DECO_PORT(0x7e)&0x000c)<<2) | ((DECO_PORT(0x7e)&0x0003)<<6))) ^ deco16_xor;// & (~deco16_mask);
+ case 0x182/2:
+ return ((DECO_PORT(0x46)&0xf000)<<0) | ((DECO_PORT(0x46)&0x0f00)>>8) | ((DECO_PORT(0x46)&0x00f0)>>0) | ((DECO_PORT(0x46)&0x000f)<<8);
+ case 0x58/2:
+ return DECO_PORT(0x46);
+ case 0x48e/2:
+ return ((((DECO_PORT(0x46)&0xf000)>>12) | ((DECO_PORT(0x46)&0x0f00)>>4) | ((DECO_PORT(0x46)&0x00f0)<<4) | ((DECO_PORT(0x46)&0x000f)<<12)));// /*^ deco16_xor*/) & (~deco16_mask);
+
+ case 0x4ba/2:
+ return (((DECO_PORT(0x24)&0xf000)>>12) | ((DECO_PORT(0x24)&0x0ff0)<<4) | ((DECO_PORT(0x24)&0x000c)<<2) | ((DECO_PORT(0x24)&0x0003)<<6)) & (~deco16_mask);
+ case 0x92/2:
+ return (((DECO_PORT(0x3c)&0xfff0)>>0) | ((DECO_PORT(0x3c)&0x0007)<<1) | ((DECO_PORT(0x3c)&0x0008)>>3));
+ case 0x1f0/2:
+ return ((((DECO_PORT(0xa2)&0xf000)>>12) | ((DECO_PORT(0xa2)&0x0f00)>>4) | ((DECO_PORT(0xa2)&0x00ff)<<8)) ^ deco16_xor) & (~deco16_mask);
+ case 0x24e/2:
+ return ((((DECO_PORT(0x46)&0xf000)>>8) | ((DECO_PORT(0x46)&0x0f00)>>0) | ((DECO_PORT(0x46)&0x00f0)>>4) | ((DECO_PORT(0x46)&0x000f)<<12)) ^ deco16_xor);// & (~deco16_mask);
+ case 0x594/2:
+ return ((((DECO_PORT(0x40)&0x00f0)<<8) | ((DECO_PORT(0x40)&0x000c)<<6) | ((DECO_PORT(0x40)&0x0003)<<10)) ^ deco16_xor);// & (~deco16_mask);
+
+ case 0x7e2/2:
+ return ((((DECO_PORT(0x96)&0xf000)<<0) | ((DECO_PORT(0x96)&0x00f0)<<4) | ((DECO_PORT(0x96)&0x000f)<<4))) ^ deco16_xor;// | ((DECO_PORT(0x96)&0x0001)<<7));// ^ deco16_xor);// & (~deco16_mask);
+ case 0x18c/2:
+ return (((DECO_PORT(0x22)&0xfff0)>>4) | ((DECO_PORT(0x22)&0x000e)<<11) | ((DECO_PORT(0x22)&0x0001)<<15));// ^ deco16_xor);// & (~deco16_mask);
+ case 0x1fa/2:
+ return ((((DECO_PORT(0x26)&0xf000)>>8) | ((DECO_PORT(0x26)&0x0f00)<<0) | ((DECO_PORT(0x26)&0x00f0)>>4) | ((DECO_PORT(0x26)&0x000f)<<12))) ^ deco16_xor;// & (~deco16_mask);
+ case 0x70e/2:
+ return ((((DECO_PORT(0x26)&0x0ff0)<<4) | ((DECO_PORT(0x26)&0x000c)<<2) | ((DECO_PORT(0x26)&0x0003)<<6))) ^ deco16_xor;// & (~deco16_mask);
+ case 0x33a/2:
+ return DECO_PORT(0x60) & (~deco16_mask);
+ case 0x1e2/2:
+ return ((DECO_PORT(0xd0)&0xf000)>>12) | ((DECO_PORT(0xd0)&0x0f00)>>4) | ((DECO_PORT(0xd0)&0x00ff)<<8);
+ case 0x3f4/2:
+ return DECO_PORT(0x6e)<<4;
+
+ case 0x2ae/2:
+ return ((DECO_PORT(0x9c)&0xf000)<<0) | ((DECO_PORT(0x9c)&0x0ff0)>>4) | ((DECO_PORT(0x9c)&0x000f)<<8);// & (~deco16_mask);
+ case 0x96/2:
+ return ((((DECO_PORT(0x22)&0xff00)>>8) | ((DECO_PORT(0x22)&0x00f0)<<8) | ((DECO_PORT(0x22)&0x000e)<<7) | ((DECO_PORT(0x22)&0x0001)<<11)) ^ deco16_xor) & (~deco16_mask);
+
+ case 0x33e/2:
+ return (((DECO_PORT(0x0)&0xf000)>>12) | ((DECO_PORT(0x0)&0x0f00)>>4) | ((DECO_PORT(0x0)&0x00f0)<<4) | ((DECO_PORT(0x0)&0x000f)<<12)) & (~deco16_mask);
+
+ case 0x6c4/2: /* Reads from here flip buffers */
+ decoprot_buffer_ram_selected^=1;
+ // Flip occurs AFTER this data has been calculated
+ return ((DECO_PORT(0x66)&0xf0f0) | ((DECO_PORT(0x66)&0x000f)<<8)) & (~deco16_mask);
+ case 0x700/2: /* Reads from here flip buffers */
+ decoprot_buffer_ram_selected^=1;
+ return (((DECO_PORT(0x66)&0xf000)>>4) | ((DECO_PORT(0x66)&0x00f0)<<8)) ^ deco16_xor;
+ case 0x444/2:
+ decoprot_buffer_ram_selected^=1;
+ return ((DECO_PORT(0x66)&0x00f0)<<8) | ((DECO_PORT(0x66)&0x0007)<<9) | ((DECO_PORT(0x66)&0x0008)<<5);
+ case 0x2d0/2:
+ decoprot_buffer_ram_selected^=1;
+ return (((DECO_PORT(0x66)&0xf000)>>4) | ((DECO_PORT(0x66)&0x00f0)<<8)) ^ deco16_xor;
+ case 0x2b8/2:
+ decoprot_buffer_ram_selected^=1;
+ return ((DECO_PORT(0x66)&0x00f0)<<8) ^ deco16_xor;
+ case 0x294/2:
+ decoprot_buffer_ram_selected^=1;
+ return ((DECO_PORT(0x66)&0x000f)<<12);
+ case 0x1e8/2:
+ decoprot_buffer_ram_selected^=1;
+ return 0; // todo
+
+ case 0x49c/2:
+ return (((DECO_PORT(0x6c)&0x00f0)<<8) ^ deco16_xor) & (~deco16_mask);
+
+ case 0x44e/2:
+ return (((DECO_PORT(0x44)&0x00f0)<<4) | ((DECO_PORT(0x44)&0x000f)<<12)) ^ deco16_xor;
+ case 0x3ca/2:
+ return (((DECO_PORT(0x1e)&0xfff0)>>4) | ((DECO_PORT(0x1e)&0x0003)<<14) | ((DECO_PORT(0x1e)&0x000c)<<10)) ^ deco16_xor;
+ case 0x2ac/2:
+ return DECO_PORT(0x1e);
+ case 0x3c/2:
+ return (((DECO_PORT(0x1e)&0x0003)<<14) | ((DECO_PORT(0x1e)&0x000c)<<10)) & (~deco16_mask);
+ case 0x174/2:
+ return (((DECO_PORT(0x1e)&0xff00)>>8) | ((DECO_PORT(0x1e)&0x00f0)<<8) | ((DECO_PORT(0x1e)&0x0007)<<9) | ((DECO_PORT(0x1e)&0x0008)<<5)) & (~deco16_mask);
+ case 0x34a/2:
+ return (((DECO_PORT(0x4)&0xff00)>>0) | ((DECO_PORT(0x4)&0x00f0)>>4) | ((DECO_PORT(0x4)&0x000f)<<4)) & (~deco16_mask);
+ case 0x324/2:
+ return (((DECO_PORT(0x6)&0xf000)>>12) | ((DECO_PORT(0x6)&0x0ff0)<<4) | ((DECO_PORT(0x6)&0x0007)<<5) | ((DECO_PORT(0x6)&0x0008)<<1));
+ case 0x344/2:
+ return (((DECO_PORT(0x8)&0xf000)>>8) | ((DECO_PORT(0x8)&0x0f00)>>8) | ((DECO_PORT(0x8)&0x00f0)<<4) | ((DECO_PORT(0x8)&0x000f)<<12));
+ case 0x72/2:
+ return ((((DECO_PORT(0xa)&0xf000)>>8) | ((DECO_PORT(0xa)&0x0ff0)<<4) | ((DECO_PORT(0xa)&0x000f)>>0))) & (~deco16_mask);
+ case 0x36e/2:
+ return ((((DECO_PORT(0xc)&0xf000)>>0) | ((DECO_PORT(0xc)&0x0ff0)>>4) | ((DECO_PORT(0xc)&0x000f)<<8))) & (~deco16_mask);
+
+ case 0x590/2:
+ return ((((DECO_PORT(0xe)&0xfff0)>>4) | ((DECO_PORT(0xe)&0x000e)<<11) | ((DECO_PORT(0xe)&0x0001)<<15))) ^ deco16_xor;
+ case 0x7b6/2:
+ return ((((DECO_PORT(0x2)&0xf000)>>8) | ((DECO_PORT(0x2)&0x0ff0)<<4) | ((DECO_PORT(0x2)&0x000f)<<0)) ^ deco16_xor) & (~deco16_mask);
+ case 0x588/2:
+ return ((((DECO_PORT(0x4)&0xff00)>>4) | ((DECO_PORT(0x4)&0x00f0)<<8) | ((DECO_PORT(0x4)&0x000f)<<0)) ^ deco16_xor) & (~deco16_mask);
+ case 0x1f6/2:
+ return (((DECO_PORT(0x6)&0xf000)>>12) | ((DECO_PORT(0x6)&0x0ff0)<<4) | ((DECO_PORT(0x6)&0x0007)<<5) | ((DECO_PORT(0x6)&0x0008)<<1)) ^ deco16_xor;
+ case 0x4c0/2:
+ return (((DECO_PORT(0x8)&0xf000)>>4) | ((DECO_PORT(0x8)&0x0f00)<<4) | ((DECO_PORT(0x8)&0x00f0)>>4) | ((DECO_PORT(0x8)&0x000f)<<4)) & (~deco16_mask);
+ case 0x63e/2:
+ return ((((DECO_PORT(0xa)&0x0ff0)<<4) | ((DECO_PORT(0xa)&0xf000)>>12) | ((DECO_PORT(0xa)&0x0003)<<6) | ((DECO_PORT(0xa)&0x000c)<<2)));
+ case 0x7cc/2:
+ return ((((DECO_PORT(0xc)&0xfff0)>>4) | ((DECO_PORT(0xc)&0x000e)<<11) | ((DECO_PORT(0xc)&0x0001)<<15)) ^ deco16_xor) & (~deco16_mask);
+ case 0x1bc/2:
+ return (((DECO_PORT(0xe)&0xf000)>>12) | ((DECO_PORT(0xe)&0x0f00)>>4) | ((DECO_PORT(0xe)&0x00ff)<<8)) & (~deco16_mask);
+
+ case 0x780/2:
+ return DECO_PORT(0xb8);
+
+ case 0x454/2:
+ return (((DECO_PORT(0x82)&0xf000)>>8) | ((DECO_PORT(0x82)&0x0f00)>>0) | ((DECO_PORT(0x82)&0x00f0)>>4) | ((DECO_PORT(0x82)&0x000f)<<12)) ^ deco16_xor;
+ case 0x53e/2:
+ return ((DECO_PORT(0x9e)&0x0003)<<14) | ((DECO_PORT(0x9e)&0x000c)<<10);
+ case 0x250/2:
+ return (((DECO_PORT(0x62)&0xf0f0)<<0) | ((DECO_PORT(0x62)&0x0f00)>>8) | ((DECO_PORT(0x62)&0x000f)<<8)) & (~deco16_mask);
+
+
+ case 0x150/2: /* Shared */
+ return DECO_PORT(0x7e);
+ case 0x10e/2: /* Schmeizr Robo only */
+ return DECO_PORT(0x7c);
+ case 0x56a/2: /* Schmeizr Robo only */
+ return (((DECO_PORT(0x7c)&0xfff0)>>4) | ((DECO_PORT(0x7c)&0x000e)<<11) | ((DECO_PORT(0x7c)&0x0001)<<15)) & (~deco16_mask);
+ case 0x39a/2: /* Schmeizr Robo only */
+ return ((((DECO_PORT(0x7e)&0xfff0)>>4) | ((DECO_PORT(0x7e)&0x000e)<<11) | ((DECO_PORT(0x7e)&0x0001)<<15)) ^ deco16_xor) & (~deco16_mask);
+ case 0x188/2: /* Schmeizr Robo only */
+ return (((deco16_mask&0x0003)<<6) | ((deco16_mask&0x000c)<<2) | ((deco16_mask&0x00f0)<<4) | ((deco16_mask&0x0f00)<<4)) & (~deco16_mask);
+ case 0x3cc/2: /* Schmeizr Robo only */
+ return deco16_mask;
+ case 0x4a/2: /* Schmeizr Robo only */
+ return DECO_PORT(0x9e) & (~deco16_mask);
+ case 0x7e8/2: /* Schmeizr Robo only */
+ return DECO_PORT(0x4a) ^ deco16_xor;
+ case 0xfc/2: /* Schmeizr Robo only */
+ return DECO_PORT(0x4a);
+ case 0x38c/2: /* Schmeizr Robo only */
+ return DECO_PORT(0x28);
+ case 0x28/2: /* Schmeizr Robo only */
+ return DECO_PORT(0x58);
+ }
+
+ logerror("Protection PC %06x: warning - read unmapped protection address %04x\n",activecpu_get_pc(),offset<<1);
+
+ return 0;
+}
+
+/**********************************************************************************/
+
+static WRITE16_HANDLER( deco16_146_core_prot_w )
+{
+ const int writeport=offset;
+ const int sndport=0x260;
+ const int xorport=0x340;
+ const int maskport=0x6c0;
+
+ if (writeport==sndport) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ return;
+ }
+
+ if (writeport==xorport)
+ COMBINE_DATA(&deco16_xor);
+ if (writeport==maskport)
+ COMBINE_DATA(&deco16_mask);
+
+ if (decoprot_buffer_ram_selected)
+ COMBINE_DATA(&decoprot_buffer_ram2[offset>>1]);
+ else
+ COMBINE_DATA(&decoprot_buffer_ram[offset>>1]);
+
+// if (offset!=0x5e0 && offset!=0x340 && offset!=0 && offset!=0x3d0 && offset!=0x280)
+// logerror("%08x: Write protection port %04x, data %04x (%08x)\n", activecpu_get_pc(), offset, data, mem_mask);
+}
+
+static READ16_HANDLER( deco16_146_core_prot_r )
+{
+// const UINT16* prot_ram=decoprot_buffer_ram;
+ UINT16 val;
+ const UINT16* prot_ram=decoprot_buffer_ram_selected ? decoprot_buffer_ram2 : decoprot_buffer_ram;
+
+ switch (offset)
+ {
+ case 0x582: /* Player 1 & Player 2 */
+ return readinputport(0);
+ case 0x04c: /* Coins/VBL */
+ return readinputport(1);
+ case 0x672: /* Dip switches */
+ return readinputport(2);
+
+ case 0x13a:
+ return ((DECO_PORT(0x190)&0x00f0)<<8) | ((DECO_PORT(0x190)&0x0003)<<10) | ((DECO_PORT(0x190)&0x000c)<<6);
+
+ case 0x53c:
+ return ((DECO_PORT(0x30)&0x0ff0)<<4) | ((DECO_PORT(0x30)&0xf000)>>8);
+
+ case 0x6c:
+ return ((DECO_PORT(0x370)&0x00ff)<<8);
+
+ case 0xa:
+ return ((DECO_PORT(0x310)&0x0fff)<<4);
+
+ case 0x4f6:
+ return ((DECO_PORT(0x20)&0x00f0)<<8) | ((DECO_PORT(0x20)&0x0007)<<9) | ((DECO_PORT(0x20)&0x0008)<<5);
+
+ case 0xea:
+ return ((DECO_PORT(0x1c0)&0xf000)<<0) | ((DECO_PORT(0x1c0)&0x00ff)<<4);
+
+ case 0x12e:
+ return ((DECO_PORT(0x1f0)&0xf000)>>4) | ((DECO_PORT(0x1f0)&0x0f00)<<4) | ((DECO_PORT(0x1f0)&0x00f0)>>4) | ((DECO_PORT(0x1f0)&0x000f)<<4);
+
+ case 0x316:
+ return ((DECO_PORT(0x290)&0xf000)>>4) | ((DECO_PORT(0x290)&0x0f00)<<4) | ((DECO_PORT(0x290)&0x00ff)<<0);
+
+ case 0x3c6:
+ return ((DECO_PORT(0x170)&0xfff0)<<0) | ((DECO_PORT(0x170)&0x000e)>>1) | ((DECO_PORT(0x170)&0x0001)<<3);
+
+ case 0x4d0:
+ return ((DECO_PORT(0x20)&0x00f0)<<8) | ((DECO_PORT(0x20)&0x0007)<<9) | ((DECO_PORT(0x20)&0x0008)<<5);
+
+ case 0x53a:
+ return ((DECO_PORT(0x370)&0xffff)<<0);
+
+ case 0x552:
+ return ((DECO_PORT(0x240)&0xfff0)<<0) | ((DECO_PORT(0x240)&0x0007)<<1) | ((DECO_PORT(0x240)&0x0008)>>3);
+
+ case 0x54c:
+ return ((DECO_PORT(0x2f0)&0x00ff)<<8);
+
+ case 0x5da:
+ return ((DECO_PORT(0x130)&0x00f0)<<8) | ((DECO_PORT(0x130)&0x000e)<<7) | ((DECO_PORT(0x130)&0x0001)<<11);
+
+ case 0x6be:
+ return ((DECO_PORT(0x150)&0xf000)>>12) | ((DECO_PORT(0x150)&0x0ff0)<<0) | ((DECO_PORT(0x150)&0x000f)<<12);
+
+ case 0x70a:
+ return ((DECO_PORT(0x1d0)&0x0ff0)<<4) | ((DECO_PORT(0x1d0)&0x0003)<<6) | ((DECO_PORT(0x1d0)&0x000c)<<2);
+
+ case 0x7e0:
+ return ((DECO_PORT(0x2b0)&0xfff0)<<0) | ((DECO_PORT(0x2b0)&0x0003)<<2) | ((DECO_PORT(0x2b0)&0x000c)>>2);
+
+ case 0x1de:
+ return ((DECO_PORT(0x1b0)&0x0ff0)<<4) | ((DECO_PORT(0x1b0)&0x000e)<<3) | ((DECO_PORT(0x1b0)&0x0001)<<7);
+
+ /*********************************************************************************/
+
+// case 0x582: return readinputport(0); /* IN0 */
+// case 0x672: return readinputport(1); /* IN1 */
+// case 0x04c: return EEPROM_read_bit();
+
+ case 0x468:
+ val=DECO_PORT(0x570);
+ val=((val&0x0003)<<6) | ((val&0x000c)<<2) | ((val&0x00f0)<<4) | ((val&0x0f00)<<4) | ((val&0xf000)>>12);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x1ea:
+ val=DECO_PORT(0x570);
+ val=((val&0x0003)<<10) | ((val&0x000c)<<6) | ((val&0x00f0)<<8) | ((val&0x0f00)>>8) | ((val&0xf000)>>8);
+ return val ^ deco16_xor;
+
+ case 0x7b6:
+ val=((DECO_PORT(0))&0xffff);
+ val=((val&0x000c)>>2) | ((val&0x0003)<<2) | ((val&0xfff0)<<0);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x01c:
+ val=((DECO_PORT(0))&0xffff);
+ val=((val&0x000f)<<12) | ((val&0x00f0)<<4) | ((val&0x0f00)>>8) | ((val&0xf000)>>8);
+ return val ^ deco16_xor;
+
+ case 0x1e0:
+ val=((DECO_PORT(0))&0xffff);
+ val=((val&0x000e)<<3) | ((val&0x0001)<<7) | ((val&0x00f0)<<4) | ((val&0x0f00)<<4) | ((val&0xf000)>>12);
+ return val ^ deco16_xor;
+
+ case 0x1d4:
+ val=((DECO_PORT(0))&0xffff);
+ val=((val&0x000f)<<0) | ((val&0x00f0)<<4) | ((val&0x0f00)<<4) | ((val&0xf000)>>8);
+ return val;
+
+ case 0x0c0:
+ val=((DECO_PORT(0x280))&0xffff);
+ val=((val&0x000f)<<4) | ((val&0x00f0)>>4) | ((val&0x0f00)<<4) | ((val&0xf000)>>4);
+ return val ^ deco16_xor;
+
+ case 0x794:
+ val=((DECO_PORT(0x280))&0xffff);
+ val=((val&0x0007)<<1) | ((val&0xfff0)>>0) | ((val&0x0008)>>3);
+ return val ^ deco16_xor;
+
+ case 0x30:
+ val=DECO_PORT(0x5e0);
+ val=((val&0x0007)<<13) | ((val&0x0008)<<9); /* Bottom bits are masked out before XOR */
+ return val ^ deco16_xor;
+
+ case 0x422:
+ val=((DECO_PORT(0x3d0))&0xffff);
+ val=((val&0x0007)<<1) | ((val&0xfff0)>>0) | ((val&0x0008)>>3);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x558:
+ val=((DECO_PORT(0x210))&0xffff);
+ val=((val&0x000f)<<0) | ((val&0x00f0)<<8) | ((val&0x0f00)>>0) | ((val&0xf000)>>8);
+ return val;
+
+ case 0x3e:
+ val=((DECO_PORT(0x210))&0xffff);
+ val=((val&0x000f)<<4) | ((val&0x00f0)>>4) | ((val&0x0f00)<<4) | ((val&0xf000)>>4);
+ return val & (~deco16_mask);
+
+ case 0x328:
+ val=((DECO_PORT(0x210))&0xffff);
+ val=((val&0x000e)<<3) | ((val&0x0001)<<7) | ((val&0x00f0)<<4) | ((val&0xf000)>>12) | ((val&0x0f00)<<4);
+ return val ^ deco16_xor;
+
+ case 0x476:
+ val=((DECO_PORT(0x210))&0xffff);
+ val=((val&0x000f)<<0) | ((val&0x00f0)<<8) | ((val&0xff00)>>4);
+ return val;
+
+ case 0x50a:
+ val=((DECO_PORT(0x210))&0xffff);
+ val=((val&0x000f)<<12) | ((val&0x00f0)>>4) | ((val&0x0f00)<<0) | ((val&0xf000)>>8);
+ return val;
+
+ case 0x5ae:
+ val=((DECO_PORT(0x210))&0xffff);
+ val=((val&0x000f)<<12) | ((val&0x00f0)>>4) | ((val&0x0f00)>>0) | ((val&0xf000)>>8);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x1ae:
+ val=((DECO_PORT(0x3d0))&0xffff);
+ val=((val&0x000f)<<12) | ((val&0x00f0)<<4);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x7a4:
+ val=((DECO_PORT(0x620))&0xffff);
+ val=((val&0x000f)<<4) | ((val&0x00f0)<<4) | ((val&0x0f00)>>8) | ((val&0xf000)>>0);
+ return val;
+
+ case 0x2c4:
+ val=((DECO_PORT(0x410))&0xffff);
+ val=((val&0x00ff)<<8) | ((val&0xff00)>>8);
+ return val ^ deco16_xor;
+
+ case 0x76: /* Bitshifted XOR, with additional inverse mask on final output */
+ val=((DECO_PORT(0x2a0))&0xffff);
+ val=((val&0x000f)<<12) | ((val&0x00f0)<<4) | ((val&0x0f00)>>8) | ((val&0xf000)>>8);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x714: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0x2a0))&0xffff);
+ val=((val&0x0003)<<14) | ((val&0x000c)<<10) | ((val&0xfff0)>>4);
+ return val & (~deco16_mask);
+
+ case 0x642:
+ val=((DECO_PORT(0x2a0))&0xffff);
+ val=((val&0xf000)>>4) | ((val&0x0f00)>>8)| ((val&0x00f0)<<8) | ((val&0x000f)<<4);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x49a: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0x580))&0xffff);
+ val=((val&0x000f)<<4) | ((val&0x00f0)>>4) | ((val&0xff00)>>0);
+ return val & (~deco16_mask);
+
+ case 0x49c: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0x580))&0xffff);
+ val=((val&0x000e)<<7) | ((val&0x00f0)<<8) | ((val&0x0001)<<11);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x584: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0x580))&0xffff);
+ val=((val&0xff00)>>8) | ((val&0x00f0)<<8) | ((val&0x0008)<<5) | ((val&0x0007)<<9);
+ return val & (~deco16_mask);
+
+ case 0x614: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0x580))&0xffff);
+ val=((val&0x000f)<<12) | ((val&0x00f0)<<4) | ((val&0x0f00)>>4) | ((val&0xf000)>>12);
+ return val & (~deco16_mask);
+
+ case 0x162: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0xe0))&0xffff);
+ val=((val&0x0fff)<<4);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x18:
+ val=((DECO_PORT(0x230))&0xffff);
+ val=((val&0xfff0)>>4) | ((val&0x0007)<<13) | ((val&0x0008)<<9);
+ return val ^ deco16_xor;
+
+ case 0x7f6: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0x230))&0xffff);
+ val=((val&0x000f)<<12) | ((val&0x00f0)<<4);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x1a0: /* Bitshifting with inverse mask on final output */
+ val=((DECO_PORT(0x230))&0xffff);
+ val=((val&0xff00)>>8) | ((val&0x00f0)<<8) | ((val&0x0003)<<10) | ((val&0x000c)<<6);
+ return val & (~deco16_mask);
+
+ case 0x4f8:
+ val=((DECO_PORT(0x2d0))&0xffff);
+ val=((val&0x0fff)<<4);
+ return val;
+
+ case 0x1d6:
+ val=((DECO_PORT(0xa0))&0xffff);
+ val=((val&0x0fff)<<4);
+ return val ^ deco16_xor;
+
+ case 0x254:
+ val=((DECO_PORT(0x320))&0xffff);
+ val=((val&0x0f00)<<4) | ((val&0x00f0)<<0) | ((val&0x000f)<<8);
+ return val & (~deco16_mask);
+
+ case 0x2ea:
+ val=((DECO_PORT(0x320))&0xffff);
+ val=((val&0x00ff)<<8);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x21e:
+ val=((DECO_PORT(0x2f0))&0xffff);
+ val=((val&0xfff0)<<0) | ((val&0x0007)<<1) | ((val&0x0008)>>3);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x7b0:
+ val=((DECO_PORT(0x2f0))&0xffff);
+ val=((val&0xfff0)>>4) | ((val&0x0007)<<13) | ((val&0x0008)<<9);
+ return val ^ deco16_xor;
+
+ case 0x7da:
+ val=((DECO_PORT(0x2f0))&0xffff);
+ val=((val&0xff00)>>8) | ((val&0x000f)<<12) | ((val&0x00f0)<<4);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x280:
+ val=((DECO_PORT(0x2d0))&0xffff);
+ val=((val&0x000f)<<8) | ((val&0x00f0)<<8) | ((val&0xf000)>>12) | ((val&0x0f00)>>4);
+ return val ^ deco16_xor;
+
+ case 0x416:
+ val=((DECO_PORT(0x2e0))&0xffff);
+ val=((val&0x000f)<<8) | ((val&0x00f0)>>4) | ((val&0xf000)>>0) | ((val&0x0f00)>>4);
+ return val;
+
+
+ case 0xac:
+ val=((DECO_PORT(0x350))&0xffff);
+ val=((val&0x000f)<<4) | ((val&0x00f0)<<4) | ((val&0xf000)>>0) | ((val&0x0f00)>>8);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x2c2:
+ val=((DECO_PORT(0x2e0))&0xffff);
+ val=((val&0xf000)<<0) | ((val&0x0ff0)>>4) | ((val&0x000f)<<8);
+ return val;
+
+ case 0x450:
+ val=((DECO_PORT(0x440))&0xffff);
+ val=((val&0xff00)>>8) | ((val&0x00f0)<<4) | ((val&0x000f)<<12);
+ return val;
+
+ case 0x504:
+ val=((DECO_PORT(0x440))&0xffff);
+ val=((val&0x000c)<<2) | ((val&0x0003)<<6)| ((val&0x0ff0)<<4);
+ return val ^ deco16_xor;
+
+ case 0xfe:
+ val=((DECO_PORT(0x440))&0xffff);
+ val=((val&0x0fff)<<4);
+ return val;
+
+ // 1c0 swap address
+ case 0x1c0:
+ decoprot_buffer_ram_selected^=1;
+ return 0;
+
+ case 0x0e2:
+ decoprot_buffer_ram_selected^=1;
+ val=((DECO_PORT(0x6c0))&0xffff);
+ return val ^ deco16_xor;
+
+ case 0x444:
+ val=((DECO_PORT(0xa0))&0xffff);
+ val=((val&0xfff0)>>4) | ((val&0x0007)<<13) | ((val&0x0008)<<9);
+ return val & (~deco16_mask);
+
+ case 0x46a:
+ val=((DECO_PORT(0x10))&0xffff);
+ val=((val&0xff00)>>8) | ((val&0x00f0)<<8)| ((val&0x0007)<<9) | ((val&0x0008)<<5);
+ return val;
+
+ case 0x80:
+ return DECO_PORT(0xe0);
+
+ case 0xb2:
+ val=((DECO_PORT(0x280))&0xffff);
+ val=((val&0x00f0)<<8);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x250:
+ val=((DECO_PORT(0x160))&0xffff);
+ val=((val&0xf000)>>12) | ((val&0x0f00)<<4)| ((val&0x00f0)<<4) | ((val&0x000e)<<3) | ((val&0x0001)<<7);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x306:
+ val=((DECO_PORT(0x160))&0xffff);
+ val=((val&0x00f0)<<8) | ((val&0xf000)>>4);
+ return (val ^ deco16_xor);
+
+ case 0x608:
+ val=((DECO_PORT(0x160))&0xffff);
+ val=((val&0xf000)>>4) | ((val&0x0f00)>>4)| ((val&0x00f0)<<8) | ((val&0x000f)<<0);
+ return val & (~deco16_mask);
+
+ case 0x52e:
+ val=((DECO_PORT(0x160))&0xffff);
+ val=((val&0xf000)>>4) | ((val&0x0f00)<<4)| ((val&0x00f0)<<0) | ((val&0x000f)<<0);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x67a:
+ val=((DECO_PORT(0x390))&0xffff);
+ val=((val&0xf000)>>8) | ((val&0x0ff0)<<4)| ((val&0x000f)<<0);
+ return val;
+
+ case 0x6c2:
+ val=((DECO_PORT(0x390))&0xffff);
+ val=((val&0x00f0)<<8) | ((val&0x000c)<<6)| ((val&0x0003)<<10);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x3d8:
+ val=((DECO_PORT(0x7e0))&0xffff);
+ val=((val&0xf000)>>8) | ((val&0x0ff0)<<4)| ((val&0x000f)<<0);
+ return val & (~deco16_mask);
+
+ case 0x244:
+ val=((DECO_PORT(0x760))&0xffff);
+ val=((val&0x0f00)<<4) | ((val&0x00f0)>>0)| ((val&0x000f)<<8);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x7e8:
+ val=((DECO_PORT(0x390))&0xffff);
+ val=((val&0x0f00)<<4) | ((val&0xf000)>>4)| ((val&0x00ff)>>0);
+ return (val ^ deco16_xor);
+
+ case 0x276:
+ val=((DECO_PORT(0x7e0))&0xffff);
+ val=((val&0x00ff)<<8);
+ return (val ^ deco16_xor) & (~deco16_mask);
+
+ case 0x540:
+ val=((DECO_PORT(0x530))&0xffff);
+ val=((val&0x00f0)<<8) | ((val&0x0007)<<9) | ((val&0x0008)<<5);
+ return val & (~deco16_mask);
+
+ case 0x5c2:
+ val=((DECO_PORT(0x7e0))&0xffff);
+ val=((val&0xf000)>>12) | ((val&0x0ff0)<<4)| ((val&0x000c)<<2)| ((val&0x0003)<<6);
+ return val;
+
+ case 0x15c:
+ val=((DECO_PORT(0x230))&0xffff);
+ val=((val&0xff00)<<0) | ((val&0x000f)<<4) | ((val&0x00f0)>>4);
+ return (val ^ deco16_xor);
+
+ case 0x2c:
+ val=((DECO_PORT(0x390))&0xffff);
+ val=((val&0x00ff)<<8);
+ return val & (~deco16_mask);
+ }
+
+ //logerror("Protection PC %06x: warning - read fully unmapped protection address %04x\n", activecpu_get_pc(), offset);
+
+ return 0;
+}
+
+/**********************************************************************************/
+
+WRITE32_HANDLER( deco16_146_fghthist_prot_w )
+{
+ UINT16 addr=BITSWAP16(offset<<1, 0, 0, 0, 0, 0, 10, 1, 9, 2, 8, 3, 7, 4, 6, 5, 0);
+
+ decoprot_last_write=addr;
+ decoprot_last_write_val=data>>16;
+
+ deco16_146_core_prot_w(addr, data>>16, mem_mask>>16);
+}
+
+READ32_HANDLER( deco16_146_fghthist_prot_r )
+{
+ UINT16 addr=BITSWAP16(offset<<1, 0, 0, 0, 0, 0, 10, 1, 9, 2, 8, 3, 7, 4, 6, 5, 0);
+ UINT16 val;
+
+ /* Special case inputs, because this is the only game with an eprom */
+ switch (addr)
+ {
+ case 0x582: return (readinputport(0)<<16) | 0xffff; /* IN0 */
+ case 0x672: return (readinputport(1)<<16) | 0xffff; /* IN1 */
+ case 0x04c: return (EEPROM_read_bit()<<16) | 0xffff;
+ }
+
+ /* Handle 'one shots' - writing data to an address, then immediately reading it back */
+ if (decoprot_last_write==addr)
+ {
+ //logerror("Hit one shot for %04x (return %04x)\n", addr, decoprot_last_write_val);
+ decoprot_last_write=-1;
+ return (decoprot_last_write_val<<16)|0xffff;
+ }
+ decoprot_last_write=-1;
+
+ val=deco16_146_core_prot_r(addr, mem_mask>>16);
+
+ if (addr!=0x7b6 && addr!=0x1c && addr!=0x1e0 && addr!=0x1d4
+ && addr!=0x2c4 && addr!=0x7a4 && addr!=0x30 // confirmed
+ && addr!=0x49a && addr!=0x49c && addr!=0x584 // confirmed
+ && addr!=0x162 // confirmed
+ && addr!=0x1a0 && addr!=0x7f6 && addr!=0x18 // confirmed
+ && addr!=0x422 && addr!=0x794 // confirmed
+ && addr!=0xc0 && addr!=0x280 && addr!=0x1c0 && addr!=0xe2 // confirmed
+ && addr!=0x6c0 // not confirmed butnot read
+ && addr!=0x1ae && addr!=0x1d6 && addr!=0x4f8 && addr!=0x614 // cnofirmed
+ && addr!=0x5ae && addr!=0x50a && addr!=0x476 && addr!=0x328 && addr!=0x3e && addr!=0x558 // dbl check these later
+ && addr!=0x444 && addr!=0x46a // confirmed
+ && activecpu_get_pc()!=0x16448 // hmm
+ && addr!=0x67a
+ && addr!=0x6c2 && addr!=0xac && addr!=0x416 && addr!=0x2c2 // confirmed
+ && addr!=0x3d8
+ && addr!=0x250 && addr!=0x306 && addr!=0x608 && addr!=0x52e // confirmed
+ && addr!=0x21e && addr!=0x7b0 && addr!=0x7da
+ && addr!=0xfe && addr!=0x504 && addr!=0x450 && addr!=0x276 // confirmed
+ && addr!=0x76 && addr!=0x714 && addr!=0x642 && addr!=0x7e8 && addr!=0x244 // confirmed
+ && addr!=0x2ea && addr!=0x254
+ && addr!=0x540 && addr!=0x5c2 // confirmed
+ && addr!=0x15c // confirmed
+ && addr!=0x80 && addr!=0xb2
+ && addr!=0x2c
+
+ && addr!=0x2e0 && addr!=0x350 && addr!=0x244 && addr!=0x2c4 && addr!=0xac && addr!=0x416 // not handled at all
+
+ // These addresses are read but the value is never used, and there are no side effects from reading
+ // these addresses - seems to purely be some code obfustication
+ && addr!=0x400 && addr!=0x640 && addr!= 0x4c0 && addr!= 0x660 && addr!=0x4e0 && addr!=0x6e0 && addr!=0x448 && addr!=0x648 && addr!=0x4c8 && addr!=0x6c8 && addr!=0x468 && addr!=0x668 && addr!=0x4e8 && addr!=0x6e8 && addr!=0x442 && addr!=0x4c2 && addr!=0x462 && addr!=0x662
+ && addr!=0x4e2 && addr!=0x6e2 && addr!=0x44a && addr!=0x64a && addr!=0x4ca && addr!=0x6ca && addr!=0x66a && addr!=0x4ea && addr!=0x6ea
+ && addr!=0x440 && addr!=0x460
+ )
+ {
+ logerror("Protection PC %06x: warning - read unmapped protection address %04x (ret %04x)\n", activecpu_get_pc(), addr, val);
+ popmessage("Read protection port %04x", addr);
+ }
+ // logerror("Protection PC %06x: warning - read unmapped protection address %04x (ret %04x)\n", activecpu_get_pc(), addr, val);
+
+ return (val<<16)|0xffff;
+}
+
+WRITE16_HANDLER( deco16_146_nitroball_prot_w )
+{
+ UINT16 addr=BITSWAP16(offset<<1, 0, 0, 0, 0, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
+
+ deco16_146_core_prot_w(addr, data, mem_mask);
+}
+
+READ16_HANDLER( deco16_146_nitroball_prot_r )
+{
+ UINT16 addr=BITSWAP16(offset<<1, 0, 0, 0, 0, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
+
+ return deco16_146_core_prot_r(addr, mem_mask);
+}
+
+/**********************************************************************************/
+
+READ16_HANDLER( dietgo_104_prot_r )
+{
+ switch (offset * 2)
+ {
+ case 0x298: return input_port_0_word_r(0, 0);
+ case 0x342: return input_port_1_word_r(0, 0);
+ case 0x506: return input_port_2_word_r(0, 0);
+ }
+
+ logerror("Protection PC %06x: warning - read unmapped memory address %04x\n",activecpu_get_pc(),offset<<1);
+
+ return 0;
+}
+
+WRITE16_HANDLER( dietgo_104_prot_w )
+{
+ if (offset==(0x380/2)) {
+ soundlatch_w(0,data&0xff);
+ cpunum_set_input_line(1,0,HOLD_LINE);
+ return;
+ }
+ logerror("Protection PC %06x: warning - write unmapped memory address %04x %04x\n",activecpu_get_pc(),offset<<1,data);
+}
+
+/**********************************************************************************/
+
+READ16_HANDLER( deco16_104_pktgaldx_prot_r )
+{
+ const UINT16* prot_ram=deco16_prot_ram;
+
+ switch (offset * 2)
+ {
+ case 0x5b2: return input_port_0_word_r(0, 0);
+ case 0x44c: return input_port_1_word_r(0, 0);
+ case 0x042: return input_port_2_word_r(0, 0);
+
+ case 0x510: return DECO_PORT(0);
+ case 0x51a: return DECO_PORT(2);
+ }
+
+ logerror("Protection PC %06x: warning - read unmapped memory address %04x\n",activecpu_get_pc(),offset<<1);
+
+ return 0;
+}
+
+WRITE16_HANDLER( deco16_104_pktgaldx_prot_w )
+{
+ COMBINE_DATA(&deco16_prot_ram[offset]);
+// logerror("Protection PC %06x: warning - write unmapped memory address %04x %04x\n",activecpu_get_pc(),offset<<1,data);
+}
+
+/**********************************************************************************/
+
diff --git a/src/mame/machine/docastle.c b/src/mame/machine/docastle.c
new file mode 100644
index 00000000000..8f0196c12c8
--- /dev/null
+++ b/src/mame/machine/docastle.c
@@ -0,0 +1,82 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/z80/z80.h"
+#include "includes/docastle.h"
+
+
+
+static UINT8 buffer0[9],buffer1[9];
+
+
+
+/*
+Communication between the two CPUs happens through a single bidirectional latch.
+Whenever CPU 0 reads or writes it, its WAIT input is asserted. It is implicitly
+cleared by CPU 1, when it accesses the latch. This enforces synchronization
+between the two CPUs.
+This is currently impossible to reproduce accurately in MAME, because it would
+require putting on hold CPU 0 while it is reading the latch, and resume its
+execution only when CPU 1 has written it.
+Instead, we take advantage of how the two CPUs access the latch, and treat it as
+if it was a small shared buffer. The order of operations is:
+1) CPU 0 triggers NMI on CPU 1
+2) CPU 0 writes 9 bytes to the buffer
+3) at this point we suspend execution of CPU 0, to give CPU 1 time to read the 9
+ bytes and write its own 9 bytes
+4) resume execution of CPU 0.
+*/
+READ8_HANDLER( docastle_shared0_r )
+{
+ if (offset == 8) logerror("CPU #0 shared0r clock = %d\n",activecpu_gettotalcycles());
+ return buffer0[offset];
+}
+
+
+READ8_HANDLER( docastle_shared1_r )
+{
+ if (offset == 8) logerror("CPU #1 shared1r clock = %d\n",activecpu_gettotalcycles());
+ return buffer1[offset];
+}
+
+
+WRITE8_HANDLER( docastle_shared0_w )
+{
+ if (offset == 8) logerror("CPU #1 shared0w %02x %02x %02x %02x %02x %02x %02x %02x %02x clock = %d\n",
+ buffer0[0],buffer0[1],buffer0[2],buffer0[3],buffer0[4],buffer0[5],buffer0[6],buffer0[7],data,activecpu_gettotalcycles());
+
+ buffer0[offset] = data;
+
+ if (offset == 8)
+ /* awake the master CPU */
+ cpu_trigger(500);
+}
+
+
+WRITE8_HANDLER( docastle_shared1_w )
+{
+ buffer1[offset] = data;
+
+ if (offset == 8)
+ {
+ logerror("CPU #0 shared1w %02x %02x %02x %02x %02x %02x %02x %02x %02x clock = %d\n",
+ buffer1[0],buffer1[1],buffer1[2],buffer1[3],buffer1[4],buffer1[5],buffer1[6],buffer1[7],data,activecpu_gettotalcycles());
+
+ /* freeze execution of the master CPU until the slave has used the shared memory */
+ cpu_spinuntil_trigger(500);
+ }
+}
+
+
+
+WRITE8_HANDLER( docastle_nmitrigger_w )
+{
+ cpunum_set_input_line(1,INPUT_LINE_NMI,PULSE_LINE);
+}
diff --git a/src/mame/machine/drakton.c b/src/mame/machine/drakton.c
new file mode 100644
index 00000000000..70a6556ac46
--- /dev/null
+++ b/src/mame/machine/drakton.c
@@ -0,0 +1,113 @@
+/***************************************************************************************
+ Drakton (c) 1984 Epos
+ decryption by Pierpaolo Prazzoli
+ based on decryptions of the other Epos games
+
+ For general documentation on how the encryption works, see machine/theglobp.c
+****************************************************************************************/
+
+#include "driver.h"
+#include "includes/dkong.h"
+
+static void drakton_decrypt_rom_8(void)
+{
+ UINT8 oldbyte,newbyte;
+ UINT8 *ROM;
+ int mem;
+
+ ROM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = ROM[mem];
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+
+ newbyte = (oldbyte & 0x02) | (~oldbyte & ~0x02);
+ newbyte = BITSWAP8(newbyte,7,6,1,3,0,4,2,5);
+
+ ROM[mem + 0x10000] = newbyte;
+ }
+}
+
+static void drakton_decrypt_rom_9(void)
+{
+ UINT8 oldbyte,newbyte;
+ UINT8 *ROM;
+ int mem;
+
+ ROM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = ROM[mem];
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+
+ newbyte = (oldbyte & 0x40) | (~oldbyte & ~0x40);
+ newbyte = BITSWAP8(newbyte,7,1,4,3,0,6,2,5);
+
+ ROM[mem + 0x14000] = newbyte;
+ }
+}
+
+static void drakton_decrypt_rom_A(void)
+{
+ UINT8 oldbyte,newbyte;
+ UINT8 *ROM;
+ int mem;
+
+ ROM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = ROM[mem];
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+
+ newbyte = (oldbyte & 0x8a) | (~oldbyte & ~0x8a);
+ newbyte = BITSWAP8(newbyte,7,6,1,0,3,4,2,5);
+
+ ROM[mem + 0x18000] = newbyte;
+ }
+}
+
+static void drakton_decrypt_rom_B(void)
+{
+ UINT8 oldbyte,newbyte;
+ UINT8 *ROM;
+ int mem;
+
+ ROM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = ROM[mem];
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+
+ newbyte = (oldbyte & 0xc8) | (~oldbyte & ~0xc8);
+ newbyte = BITSWAP8(newbyte,7,1,4,0,3,6,2,5);
+
+ ROM[mem + 0x1C000] = newbyte;
+ }
+}
+
+DRIVER_INIT( drakton )
+{
+ /* While the PAL supports up to 16 decryption methods, only four
+ are actually used in the PAL. Therefore, we'll take a little
+ memory overhead and decrypt the ROMs using each method in advance. */
+ drakton_decrypt_rom_8();
+ drakton_decrypt_rom_9();
+ drakton_decrypt_rom_A();
+ drakton_decrypt_rom_B();
+}
diff --git a/src/mame/machine/equites.c b/src/mame/machine/equites.c
new file mode 100644
index 00000000000..47b89a85301
--- /dev/null
+++ b/src/mame/machine/equites.c
@@ -0,0 +1,444 @@
+/*******************************************************************************
+
+Equites (c) 1984 Alpha Denshi Co./Sega
+Bull Fighter (c) 1984 Alpha Denshi Co./Sega
+The Koukouyakyuh (c) 1985 Alpha Denshi Co.
+Splendor Blast (c) 1985 Alpha Denshi Co.
+High Voltage (c) 1985 Alpha Denshi Co.
+
+drivers by Acho A. Tang
+
+*******************************************************************************/
+// Directives
+
+#include "driver.h"
+#include "cpu/i8085/i8085.h"
+#include "sound/ay8910.h"
+#include "sound/msm5232.h"
+#include "sound/dac.h"
+
+#define MCU_RTNMSB 0x80
+
+#if 0 // ** cut-and-pasted to driver module **
+
+// Common Hardware Start
+#define EQUITES_ADD_SOUNDBOARD7 \
+ MDRV_CPU_ADD(8085A, 5000000) \
+ /* audio CPU */ \
+ MDRV_CPU_PROGRAM_MAP(equites_s_readmem, equites_s_writemem) \
+ MDRV_CPU_IO_MAP(0, equites_s_writeport) \
+ MDRV_CPU_PERIODIC_INT(nmi_line_pulse, 4000) \
+ \
+ MDRV_SOUND_ADD(MSM5232, 2500000) \
+ MDRV_SOUND_CONFIG(equites_5232intf) \
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75) \
+ \
+ MDRV_SOUND_ADD(AY8910, 6144444/4) \
+ MDRV_SOUND_CONFIG(equites_8910intf) \
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) \
+ \
+ MDRV_SOUND_ADD(DAC, 0) \
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75) \
+ \
+ MDRV_SOUND_ADD(DAC, 0) \
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.75) \
+
+extern void equites_8404init(void);
+extern void equites_8404rule(unsigned pc, int offset, int data);
+
+extern READ16_HANDLER(equites_8404_r);
+extern WRITE8_HANDLER(equites_5232_w);
+extern WRITE8_HANDLER(equites_8910control_w);
+extern WRITE8_HANDLER(equites_8910data_w);
+extern WRITE8_HANDLER(equites_dac0_w);
+extern WRITE8_HANDLER(equites_dac1_w);
+
+extern UINT16 *equites_8404ram;
+extern struct MSM5232interface equites_5232intf;
+extern struct AY8910interface equites_8910intf;
+
+static ADDRESS_MAP_START( equites_s_readmem, ADDRESS_SPACE_PROGRAM, 8 )
+ { 0x0000, 0xbfff, MRA8_ROM }, // sound program
+ { 0xc000, 0xc000, soundlatch_r },
+ { 0xe000, 0xe0ff, MRA8_RAM }, // stack and variables
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( equites_s_writemem, ADDRESS_SPACE_PROGRAM, 8 )
+ { 0x0000, 0xbfff, MWA8_ROM }, // sound program
+ { 0xc080, 0xc08d, equites_5232_w },
+ { 0xc0a0, 0xc0a0, equites_8910data_w },
+ { 0xc0a1, 0xc0a1, equites_8910control_w },
+ { 0xc0b0, 0xc0b0, MWA8_NOP }, // INTR: sync with main melody
+ { 0xc0c0, 0xc0c0, MWA8_NOP }, // INTR: sync with specific beats
+ { 0xc0d0, 0xc0d0, equites_dac0_w },
+ { 0xc0e0, 0xc0e0, equites_dac1_w },
+ { 0xc0f8, 0xc0fe, MWA8_NOP }, // soundboard I/O, ignored
+ { 0xc0ff, 0xc0ff, soundlatch_clear_w },
+ { 0xe000, 0xe0ff, MWA8_RAM }, // stack and variables
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( equites_s_writeport, ADDRESS_SPACE_IO, 8 )
+ { 0x00e0, 0x00e5, MWA8_NOP }, // soundboard I/O, ignored
+ADDRESS_MAP_END
+// Common Hardware End
+
+#endif
+
+/******************************************************************************/
+// Imports
+
+extern UINT16 *equites_workram;
+
+/******************************************************************************/
+// Locals
+
+static UINT16 e_ent_addr[8][4] =
+{
+ {0xce25, 0xcd3c, 0xcd89, 0xcdd5},
+ { 0, 0xce6e, 0xcebe, 0xcff2},
+ { 0, 0xcf07, 0xcf55, 0xcfa2},
+ { 0, 0xcff2, 0xd03a, 0},
+ { 0, 0xd08e, 0xd0e1, 0xd132},
+ { 0, 0xd17a, 0, 0},
+ { 0, 0xd1c0, 0xcff2, 0},
+ { 0, 0, 0, 0},
+};
+
+static UINT16 e_exit_pos[8][4] =
+{
+ {0x1878, 0x4878, 0x7878, 0x3878},
+ { 0, 0x3878, 0x4878, 0x4878},
+ { 0, 0x3878, 0x0060, 0x4878},
+ { 0, 0x0060, 0x4878, 0},
+ { 0, 0x7878, 0x4878, 0x4878},
+ { 0, 0x4878, 0, 0},
+ { 0, 0x3878, 0x4878, 0},
+ { 0, 0, 0, 0},
+};
+
+static UINT16 e_swap_addr[4][4] =
+{
+ { 0, 0x92ec, 0, 0x92ec},
+ { 0, 0x92ec, 0, 0x92ec},
+ { 0, 0, 0, 0x92ec},
+ { 0, 0x92d2, 0, 0x92d2},
+};
+
+static UINT16 e_respawn_addr[4][4] =
+{
+ { 0, 0x9382, 0, 0x9382},
+ { 0, 0x9382, 0, 0x9382},
+ { 0, 0, 0, 0x9382},
+ { 0, 0x0cc8, 0, 0x9382},
+};
+
+static UINT16 h_respawn_addr[2][4] =
+{
+ {0x1026, 0x0fb6, 0x0fb6, 0x0fb6},
+ {0x11ac, 0x20b0, 0x1c44, 0x1996},
+};
+
+static UINT16 s_respawn_addr[3][6] =
+{
+ {0x0b6a, 0x0b52, 0x29da, 0x0846, 0x1610, 0x0c84}, // game over seq
+ {0x347e, 0x0e10, 0x0c2c, 0x0c2c, 0x0c2c, 0x0c2c}, // depth seq
+ {0x0c2e, 0x1fbe, 0x166a, 0x0c84, 0x0c2c, 0x0c2c}, // level change seq
+};
+
+static UINT16 s_lvdata_addr[6] = {0xccc2, 0xd04a, 0xd408, 0xd796, 0xdaa8, 0xdbd6};
+
+static UINT16 s_objdata_addr[6] = {0xb7ce, 0xba64, 0xbdbc, 0xc0f2, 0xc446, 0xc810};
+
+static UINT8 s_spawn_list[8] = {0x07, 0x08, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26};
+
+static UINT8 s_pow_list[8] = {0, 0, 2, 2, 2, 2, 2, 1};
+
+static struct MRULE
+{
+ struct MRULE *next;
+ UINT16 pc;
+ UINT8 data;
+ UINT8 mode;
+} *mrulepool;
+
+static struct MRULELIST
+{
+ struct MRULE *head;
+ struct MRULE *tail;
+} *mrulemap;
+
+/******************************************************************************/
+// Exports
+
+UINT16 *equites_8404ram;
+
+/******************************************************************************/
+// Local Functions
+
+static TIMER_CALLBACK( equites_synth_callback )
+{
+ static int parity = 0;
+
+ if (parity^=1) cpunum_set_input_line(1, I8085_INTR_LINE, HOLD_LINE);
+ cpunum_set_input_line(1, I8085_RST75_LINE, HOLD_LINE);
+}
+
+// Optimized Mersenne Twister - courtesy of Shawn J. Cokus, University of Washington
+
+typedef UINT32 uint32;
+
+#define N (624) // length of state vector
+#define M (397) // a period parameter
+#define K (0x9908B0DFU) // a magic constant
+#define hiBit(u) ((u) & 0x80000000U) // mask all but highest bit of u
+#define loBit(u) ((u) & 0x00000001U) // mask all but lowest bit of u
+#define loBits(u) ((u) & 0x7FFFFFFFU) // mask the highest bit of u
+#define mixBits(u, v) (hiBit(u)|loBits(v)) // move hi bit of u to hi bit of v
+
+static uint32 state[N+1]; // state vector + 1 extra to not violate ANSI C
+static uint32 *next; // next random value is computed from here
+static int left = -1; // can *next++ this many times before reloading
+
+static void seedMT(uint32 seed)
+{
+ register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = state;
+ register int j;
+
+ for(left=0, *s++=x, j=N; --j;
+ *s++ = (x*=69069U) & 0xFFFFFFFFU);
+}
+
+static uint32 reloadMT(void)
+{
+ register uint32 *p0=state, *p2=state+2, *pM=state+M, s0, s1;
+ register int j;
+
+ if(left < -1)
+ seedMT(4357U);
+
+ left=N-1, next=state+1;
+
+ for(s0=state[0], s1=state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
+ *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+
+ for(pM=state, j=M; --j; s0=s1, s1=*p2++)
+ *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+
+ s1=state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+ s1 ^= (s1 >> 11);
+ s1 ^= (s1 << 7) & 0x9D2C5680U;
+ s1 ^= (s1 << 15) & 0xEFC60000U;
+ return(s1 ^ (s1 >> 18));
+}
+
+INLINE uint32 randomMT(void)
+{
+ uint32 y;
+
+ if(--left < 0)
+ return(reloadMT());
+
+ y = *next++;
+ y ^= (y >> 11);
+ y ^= (y << 7) & 0x9D2C5680U;
+ y ^= (y << 15) & 0xEFC60000U;
+ return(y ^ (y >> 18));
+}
+
+/******************************************************************************/
+// Export Functions
+
+void equites_8404init(void)
+{
+ UINT8 *byte_ptr;
+
+ byte_ptr = auto_malloc(0x8000);
+ memset(byte_ptr, 0, 0x8000);
+
+ mrulemap = (struct MRULELIST *)byte_ptr; // pointer table to rule lists
+ mrulepool = (struct MRULE *)(byte_ptr + 0x4000); // rules pool
+
+ timer_pulse(ATTOTIME_IN_HZ(106), 0, equites_synth_callback); // hand tuned
+
+ seedMT(mame_rand(Machine));
+}
+
+void equites_8404rule(unsigned pc, int offset, int data)
+{
+ struct MRULELIST *listptr;
+
+ mrulepool->pc = pc;
+
+ if (data >= 0)
+ mrulepool->data = data & 0xff;
+ else
+ {
+ data = -data;
+ if (data > 0x0f) data = (data>>4 & 0x0f) | MCU_RTNMSB;
+ mrulepool->mode = data;
+ }
+
+ listptr = mrulemap + (offset>>1);
+
+ if (!listptr->head)
+ listptr->head = mrulepool;
+ else
+ listptr->tail->next = mrulepool;
+
+ listptr->tail = mrulepool++;
+}
+
+/******************************************************************************/
+// Export Handlers
+
+READ16_HANDLER(equites_8404_r)
+{
+ int pc, data, mode, col, row;
+ struct MRULE *ruleptr;
+
+ if (ACCESSING_LSB)
+ {
+ pc = activecpu_get_pc();
+
+ //logerror("%04x: 8404 reads offset %04x\n", pc, offset<<1);
+
+ ruleptr = mrulemap[offset].head;
+ while (ruleptr)
+ {
+ if (pc == ruleptr->pc)
+ {
+ mode = ruleptr->mode;
+ if (!mode) return (ruleptr->data);
+ switch (mode & 0xf)
+ {
+ case 1:
+ col = equites_8404ram[0x47d>>1] & 3;
+ row = equites_8404ram[0x47f>>1] & 7;
+ data = e_ent_addr[row][col];
+ break;
+
+ case 2:
+ col = equites_8404ram[0x47d>>1] & 3;
+ row = equites_8404ram[0x47f>>1] & 7;
+ data = e_exit_pos[row][col];
+ break;
+
+ case 3:
+ data = equites_workram[0x130>>1];
+ break;
+
+ case 4:
+ col = equites_8404ram[0x27b>>1] & 3;
+ row = equites_8404ram[0x279>>1] & 3;
+ data = e_respawn_addr[row][col];
+ break;
+
+ case 5:
+ col = equites_8404ram[0x27b>>1] & 3;
+ row = equites_8404ram[0x279>>1] & 3;
+ data = e_swap_addr[row][col];
+ break;
+
+ case 6:
+ col = offset - (0x493>>1);
+ row = (equites_8404ram[0x495>>1] & 0xff) ? 1 : 0;
+ data = h_respawn_addr[row][col>>1];
+ break;
+
+ case 7:
+ col = offset - (0x5e3>>1);
+ if ((equites_8404ram[0xf>>1] & 0xf) == 2)
+ {
+ if (col >= 0xb) equites_8404ram[0xf>>1] = 0;
+ row = 2;
+ }
+ else
+ row = (equites_8404ram[0x4f9>>1] & 0xff) ? 1 : 0;
+ data = s_respawn_addr[row][col>>1];
+ break;
+
+ case 8:
+ data = s_pow_list[randomMT()&7];
+ break;
+
+ case 9:
+ data = s_spawn_list[randomMT()&7];
+ break;
+
+ case 0xa:
+ data = s_objdata_addr[equites_workram[0x90>>1]%6];
+ break;
+
+ case 0xb:
+ data = s_lvdata_addr[equites_workram[0x90>>1]%6];
+ break;
+
+ case 0xc:
+ data = equites_workram[0x90>>1]%6;
+ break;
+
+ default:
+ return (equites_8404ram[offset]);
+ }
+ if (mode & MCU_RTNMSB) data >>= 8;
+ return (data & 0xff);
+ }
+ ruleptr = ruleptr->next;
+ }
+ }
+ return (equites_8404ram[offset]);
+}
+
+WRITE8_HANDLER(equites_5232_w)
+{
+ if (offset < 0x08 && data) data |= 0x80; // gets around a current 5232 emulation restriction
+ MSM5232_0_w(offset, data);
+}
+
+WRITE8_HANDLER(equites_8910control_w)
+{
+ AY8910_control_port_0_w(0, data);
+}
+
+WRITE8_HANDLER(equites_8910data_w)
+{
+ AY8910_write_port_0_w(0, data);
+}
+
+static WRITE8_HANDLER(equites_8910porta_w)
+{
+ // sync with one or more MSM5232 channels. MIDI out?
+}
+
+static WRITE8_HANDLER(equites_8910portb_w)
+{
+ // sync with one or more MSM5232 channels. MIDI out?
+}
+
+WRITE8_HANDLER(equites_dac0_w)
+{
+ DAC_signed_data_w(0, data<<2);
+}
+
+WRITE8_HANDLER(equites_dac1_w)
+{
+ DAC_signed_data_w(1, data<<2);
+}
+
+/******************************************************************************/
+// Alpha "Soundboard 7" Chip Definitions
+
+struct MSM5232interface equites_5232intf =
+{
+ { 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6, 0.39e-6 } // needs verification
+};
+
+struct AY8910interface equites_8910intf =
+{
+ 0,
+ 0,
+ equites_8910porta_w,
+ equites_8910portb_w
+};
+
+/******************************************************************************/
diff --git a/src/mame/machine/exctsccr.c b/src/mame/machine/exctsccr.c
new file mode 100644
index 00000000000..46223367232
--- /dev/null
+++ b/src/mame/machine/exctsccr.c
@@ -0,0 +1,340 @@
+/*************************************************************************************
+
+Emulation of the Alpha 8302 microcontroller.
+
+All tables built manually from the analisis of the bootleg set.
+
+The main purpose of the MCU is to control the program flow.
+This tables are actually subroutine addresses, wich get pushed
+onto the stack one after the other. Basically then the program
+runs and when it returns on one of these subroutines, it expects
+to land on the proper 'next' subroutine.
+
+Ernesto Corvi - 10/30/98
+
+- 09/12/2004 Pierpaolo Prazzoli
+ added Exciting Soccer II protection
+ (still at least one issue because you can't control the player)
+
+*************************************************************************************/
+
+#include "driver.h"
+
+#define MCU_HACK 0
+#if MCU_HACK
+
+#define MCU_KEY_TABLE_SIZE 16
+
+/* These are global */
+UINT8 *exctsccr_mcu_ram;
+
+WRITE8_HANDLER( exctsccr_mcu_w );
+WRITE8_HANDLER( exctsccr_mcu_control_w );
+
+/* Local stuff */
+static int mcu_code_latch;
+
+/* Exciting Soccer */
+
+/* input = 0x6009 - data = 0x6170 */
+static UINT8 mcu_table1[MCU_KEY_TABLE_SIZE] = {
+ 0x23, 0x05, 0xfb, 0x07, 0x4d, 0x3b, 0x7d, 0x03,
+ 0x9a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x600d - data = 0x61f0 */
+static UINT8 mcu_table2[MCU_KEY_TABLE_SIZE] = {
+ 0x75, 0x25, 0x4b, 0x10, 0xa6, 0x06, 0x9a, 0x02,
+ 0x04, 0x11, 0x09, 0x09, 0x2a, 0x10, 0x3a, 0x10
+};
+
+/* input = ?????? - data = 0x6300 */
+static UINT8 mcu_table3[MCU_KEY_TABLE_SIZE*4] = {
+ 0xba, 0x26, 0x53, 0x0d, 0x01, 0x24, 0x1d, 0x15,
+ 0xd0, 0x1d, 0x35, 0x1f, 0x32, 0x22, 0xa0, 0x2c,
+
+ 0x5e, 0x2e, 0x92, 0x2e, 0xf9, 0x2e, 0x43, 0x2f,
+ 0x59, 0x2f, 0x6f, 0x2f, 0xd1, 0x38, 0xd8, 0x3e,
+
+ 0x9e, 0x0d, 0x4c, 0x47, 0x1f, 0x1f, 0x5a, 0x1f,
+ 0xbe, 0x22, 0xa2, 0x23, 0x33, 0x35, 0x69, 0x34,
+
+ 0x7c, 0x3a, 0x00, 0x00, 0xdc, 0x44, 0x78, 0x0b,
+ 0x65, 0x0d, 0xc4, 0xb2, 0xc4, 0xb2, 0xc4, 0xb2
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 mcu_table4[MCU_KEY_TABLE_SIZE] = {
+ 0xc5, 0x24, 0xc5, 0x24, 0x27, 0x3f, 0xd0, 0x07,
+ 0x07, 0x0b, 0xd8, 0x02, 0x9a, 0x08, 0x00, 0x00
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 mcu_table5[MCU_KEY_TABLE_SIZE] = {
+ 0x54, 0x43, 0xd0, 0x07, 0xd8, 0x02, 0x9a, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 mcu_table6[MCU_KEY_TABLE_SIZE] = {
+ 0x2b, 0x03, 0xd0, 0x07, 0xd8, 0x02, 0x9a, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 mcu_table7[MCU_KEY_TABLE_SIZE] = {
+ 0xfa, 0x0e, 0x9a, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x6011 - data = 0x607f */
+static UINT8 mcu_table8[MCU_KEY_TABLE_SIZE*2] = {
+ 0x0b, 0x78, 0x47, 0x04, 0x36, 0x18, 0x23, 0xf1,
+ 0x10, 0xee, 0x16, 0x04, 0x11, 0x94, 0x16, 0xdd,
+
+ 0x13, 0x4e, 0x06, 0xa6, 0x13, 0x12, 0x08, 0x9a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static void mcu_sort_list( UINT8 *src, UINT8 *dst, UINT8 *table ) {
+ int i;
+
+ for ( i = 0; i < 0x20; i++ ) {
+ int where = src[i];
+
+ if ( where < 0x20 ) {
+ int offs = ( i << 1 );
+
+ where <<= 1;
+ dst[where] = table[offs];
+ dst[where+1] = table[offs+1];
+ }
+ }
+}
+
+WRITE8_HANDLER( exctsccr_mcu_control_w ) {
+
+ if ( data == 0xff ) { /* goes around the mcu checks */
+ exctsccr_mcu_ram[0x0003] = 0x01; /* mcu state = running */
+
+ exctsccr_mcu_ram[0x0005] = 0x08;
+ exctsccr_mcu_ram[0x0380] = 0xf1;
+ exctsccr_mcu_ram[0x0381] = 0x01;
+ exctsccr_mcu_ram[0x02f8] = 0x1f; /* Selects song to play during gameplay */
+
+ exctsccr_mcu_ram[0x0009] = 0x08;
+ memcpy( &exctsccr_mcu_ram[0x0170], mcu_table1, MCU_KEY_TABLE_SIZE );
+
+ if ( exctsccr_mcu_ram[0x000d] == 0x01 ) {
+ exctsccr_mcu_ram[0x000d] = 0x08;
+
+ memcpy( &exctsccr_mcu_ram[0x01f0], mcu_table2, MCU_KEY_TABLE_SIZE );
+ }
+
+ mcu_sort_list( &exctsccr_mcu_ram[0x03e0], &exctsccr_mcu_ram[0x0300], mcu_table3 );
+
+ exctsccr_mcu_ram[0x02fb] = 0x7e;
+ exctsccr_mcu_ram[0x02fd] = 0x7e;
+
+ if ( mcu_code_latch ) {
+ exctsccr_mcu_ram[0x02f9] = 0x7f;
+ exctsccr_mcu_ram[0x02fa] = 0x0d;
+ exctsccr_mcu_ram[0x02fc] = 0x05;
+ exctsccr_mcu_ram[0x02fe] = 0x01;
+ } else {
+ exctsccr_mcu_ram[0x02f9] = 0x81;
+ exctsccr_mcu_ram[0x02fa] = 0x2d;
+ exctsccr_mcu_ram[0x02fc] = 0x25;
+ exctsccr_mcu_ram[0x02fe] = 0x09;
+ }
+
+ if ( exctsccr_mcu_ram[0x000f] == 0x02 ) {
+ exctsccr_mcu_ram[0x000f] = 0x08;
+ exctsccr_mcu_ram[0x02f6] = 0xd6;
+ exctsccr_mcu_ram[0x02f7] = 0x39;
+ }
+
+ if ( exctsccr_mcu_ram[0x0007] == 0x02 ) {
+ exctsccr_mcu_ram[0x0007] = 0x08;
+
+ if ( exctsccr_mcu_ram[0x0204] > 3 )
+ exctsccr_mcu_ram[0x0204] = 0;
+
+ switch( exctsccr_mcu_ram[0x0204] ) {
+ case 0x00:
+ memcpy( &exctsccr_mcu_ram[0x029b], mcu_table4, MCU_KEY_TABLE_SIZE );
+ break;
+
+ case 0x01:
+ memcpy( &exctsccr_mcu_ram[0x029b], mcu_table5, MCU_KEY_TABLE_SIZE );
+ break;
+
+ case 0x02:
+ memcpy( &exctsccr_mcu_ram[0x029b], mcu_table6, MCU_KEY_TABLE_SIZE );
+ break;
+
+ case 0x03:
+ memcpy( &exctsccr_mcu_ram[0x029b], mcu_table7, MCU_KEY_TABLE_SIZE );
+ break;
+ }
+
+ if ( exctsccr_mcu_ram[0x0204] != 3 )
+ exctsccr_mcu_ram[0x0204]++;
+ }
+
+ exctsccr_mcu_ram[0x0011] = 0x08;
+ memcpy( &exctsccr_mcu_ram[0x007f], mcu_table8, MCU_KEY_TABLE_SIZE*2 );
+ }
+}
+
+WRITE8_HANDLER( exctsccr_mcu_w ) {
+
+ if ( offset == 0x02f9 )
+ mcu_code_latch = data;
+
+ exctsccr_mcu_ram[offset] = data;
+}
+
+
+/* Exciting Soccer II */
+
+/* input = 0x6009 - data = 0x6170 */
+static UINT8 exctscc2_mcu_table1[MCU_KEY_TABLE_SIZE] = {
+ 0x56, 0x05, 0x90, 0x08, 0x19, 0x3e, 0xa8, 0x03,
+ 0x2f, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x600d - data = 0x61f0 */
+static UINT8 exctscc2_mcu_table2[MCU_KEY_TABLE_SIZE] = {
+ 0xff, 0x27, 0x35, 0x10, 0xd9, 0x06, 0xc3, 0x02,
+ 0x4d, 0x12, 0x9e, 0x09, 0x14, 0x10, 0x24, 0x10
+};
+
+/* input = ?????? - data = 0x6300 */
+static UINT8 exctscc2_mcu_table3[MCU_KEY_TABLE_SIZE*4] = {
+ 0x41, 0x29, 0xb2, 0x12, 0x91, 0x26, 0xa6, 0x16, //0x12b2?
+ 0x5f, 0x20, 0xc4, 0x21, 0xc1, 0x24, 0x3e, 0x2f,
+
+ 0x03, 0x31, 0x37, 0x31, 0x9e, 0x31, 0xe8, 0x31,
+ 0xfe, 0x31, 0x14, 0x32, 0x93, 0x3b, 0xa4, 0x41,
+
+ 0x88, 0x0d, 0x55, 0x4b, 0xae, 0x21, 0xe9, 0x21,
+ 0x4d, 0x25, 0x32, 0x26, 0xd8, 0x37, 0x0e, 0x37,
+
+ 0x48, 0x3d, 0x00, 0x00, 0xd5, 0x48, 0x54, 0x0c,
+ 0xa0, 0x0c, 0xc4, 0xb2, 0xc4, 0xb2, 0xc4, 0xb2 //0x0ca0? //last 3 couples?
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 exctscc2_mcu_table4[MCU_KEY_TABLE_SIZE] = {
+ 0x55, 0x27, 0x55, 0x27, 0xf3, 0x41, 0x65, 0x08,
+ 0xe3, 0x0b, 0x01, 0x03, 0x2f, 0x09, 0x00, 0x00
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 exctscc2_mcu_table5[MCU_KEY_TABLE_SIZE] = {
+ 0xdd, 0x45, 0x65, 0x08, 0x01, 0x03, 0x2f, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 exctscc2_mcu_table6[MCU_KEY_TABLE_SIZE] = {
+ 0x54, 0x03, 0x65, 0x08, 0x01, 0x03, 0x2f, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x6007 - data = 0x629b */
+static UINT8 exctscc2_mcu_table7[MCU_KEY_TABLE_SIZE] = {
+ 0xe4, 0x0e, 0x2f, 0x09, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+/* input = 0x6011 - data = 0x607f */
+static UINT8 exctscc2_mcu_table8[MCU_KEY_TABLE_SIZE*2] = {
+ 0x0c, 0x54, 0x4b, 0x0d, 0x38, 0xbd, 0x26, 0x81,
+ 0x12, 0x37, 0x18, 0x4a, 0x13, 0x0f, 0x19, 0x23,
+
+ 0x14, 0xd6, 0x06, 0xd9, 0x14, 0x9a, 0x09, 0x2f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+WRITE8_HANDLER( exctscc2_mcu_control_w )
+{
+ if ( data == 0xff ) /* goes around the mcu checks */
+ {
+ exctsccr_mcu_ram[0x0003] = 0x01; /* mcu state = running */
+
+ exctsccr_mcu_ram[0x0005] = 0x08;
+ exctsccr_mcu_ram[0x0380] = 0x1a;
+ exctsccr_mcu_ram[0x0381] = 0x02;
+ exctsccr_mcu_ram[0x02f8] = 0x1f; /* Selects song to play during gameplay */
+
+ exctsccr_mcu_ram[0x0009] = 0x08;
+ memcpy( &exctsccr_mcu_ram[0x0170], exctscc2_mcu_table1, MCU_KEY_TABLE_SIZE );
+
+ if ( exctsccr_mcu_ram[0x000d] == 0x01 ) {
+ exctsccr_mcu_ram[0x000d] = 0x08;
+
+ memcpy( &exctsccr_mcu_ram[0x01f0], exctscc2_mcu_table2, MCU_KEY_TABLE_SIZE );
+ }
+
+ mcu_sort_list( &exctsccr_mcu_ram[0x03e0], &exctsccr_mcu_ram[0x0300], exctscc2_mcu_table3 );
+
+/* are these right ? */
+ exctsccr_mcu_ram[0x02fb] = 0x7e;
+ exctsccr_mcu_ram[0x02fd] = 0x7e;
+
+ if ( mcu_code_latch ) {
+ exctsccr_mcu_ram[0x02f9] = 0x7f;
+ exctsccr_mcu_ram[0x02fa] = 0x0d;
+ exctsccr_mcu_ram[0x02fc] = 0x05;
+ exctsccr_mcu_ram[0x02fe] = 0x01;
+ } else {
+ exctsccr_mcu_ram[0x02f9] = 0x81;
+ exctsccr_mcu_ram[0x02fa] = 0x2d;
+ exctsccr_mcu_ram[0x02fc] = 0x25;
+ exctsccr_mcu_ram[0x02fe] = 0x09;
+ }
+/*******/
+
+ if ( exctsccr_mcu_ram[0x000f] == 0x02 ) {
+ exctsccr_mcu_ram[0x000f] = 0x08;
+ exctsccr_mcu_ram[0x02f6] = 0x98;
+ exctsccr_mcu_ram[0x02f7] = 0x3c;
+ }
+
+ if ( exctsccr_mcu_ram[0x0007] == 0x02 ) {
+ exctsccr_mcu_ram[0x0007] = 0x08;
+
+ if ( exctsccr_mcu_ram[0x0204] > 3 )
+ exctsccr_mcu_ram[0x0204] = 0;
+
+ switch( exctsccr_mcu_ram[0x0204] ) {
+ case 0x00:
+ memcpy( &exctsccr_mcu_ram[0x029b], exctscc2_mcu_table4, MCU_KEY_TABLE_SIZE );
+ break;
+
+ case 0x01:
+ memcpy( &exctsccr_mcu_ram[0x029b], exctscc2_mcu_table5, MCU_KEY_TABLE_SIZE );
+ break;
+
+ case 0x02:
+ memcpy( &exctsccr_mcu_ram[0x029b], exctscc2_mcu_table6, MCU_KEY_TABLE_SIZE );
+ break;
+
+ case 0x03:
+ memcpy( &exctsccr_mcu_ram[0x029b], exctscc2_mcu_table7, MCU_KEY_TABLE_SIZE );
+ break;
+ }
+
+ if ( exctsccr_mcu_ram[0x0204] != 3 )
+ exctsccr_mcu_ram[0x0204]++;
+
+ }
+
+ exctsccr_mcu_ram[0x0011] = 0x08;
+ memcpy( &exctsccr_mcu_ram[0x007f], exctscc2_mcu_table8, MCU_KEY_TABLE_SIZE*2 );
+ }
+}
+
+#endif
diff --git a/src/mame/machine/fd1089.c b/src/mame/machine/fd1089.c
new file mode 100644
index 00000000000..05971a0e879
--- /dev/null
+++ b/src/mame/machine/fd1089.c
@@ -0,0 +1,6611 @@
+/***************************************************************************
+
+Hitachi FD1089A/FD1089B encryption emulation
+
+Decryption tables provided by Charles MacDonald
+Decryption algorithm by Nicola Salmoria
+
+The FD1089 is a 680000 with built-in encryption.
+It contains some battery-backed RAM, when the battery dies the CPU stops
+working.
+
+Both opcodes and data are encrypted, using different (but related) tables.
+Decryption works on 16-bit words, but only 8 bits are affected, the other 8 are
+left untouched. Opcodes are always encrypted; data can be not encrypted, this
+is necessary otherwise RAM would not work as expected (writing data and reading
+it back would return a different number).
+
+The FD1089A and FD1089B work in the same way, but the decryption tables are
+different. The internal RAM only contains the code of the table to use at every
+address (only 12 bits of the address are used, so the encryption repeats).
+
+The FD1089 design is clearly derived from the MC8123. The MC8123 is a Z80 so it
+made sense to encrypt all 8 data bits and use 12 of the 16 address bits. It makes
+a lot less sense to encrypt only half of the 16 data bits; using 12 of the 24
+address bits might be ok, but not in the way they did it. The choice of address
+bits to use was probably dictated by the need to not encrypt data in certain areas
+of the address space, so they had to include the top 8 bits of the address.
+However this means that if you pick e.g. area 000000-00FFFF, where most of the
+program code resides, just 4 address bits affect the encryption, making it very
+weak when compared to the MC8123. Out of the 16KB of internal RAM, you need less
+than 128 bytes to decrypt a whole game - the rest is not used. A waste of space
+and security. Also, since only 8 of the 16 bits are encrypted, it is very easy
+to use the unencrypted ones to search for known sequences of code or data.
+
+
+Known games that use this CPU are:
+
+CPU # Status Game Notes
+--------- --- ------------------------ ------------------
+FD1089A
+317-0018 [1] Action Fighter
+317-0021? [2] Alex Kidd
+317-0022 [1] Dunk Shot
+317-0028 [2] Defense
+317-0033 [1] Alien Syndrome
+317-0167 [2] Aurail
+
+FD1089B
+317-0013A [1] Enduro Racer
+317-0024 [2] Time Scanner FD1089B 6J2 317-0024
+317-0027 [2] SDI
+317-0034 [1] Super Hang-On
+317-0168 [1] Aurail
+317-5021 [3] Sukeban Jansi Ryuko
+
+[1] Complete
+[2] Partial tables derived by comparison with unencrypted version
+[3] Partial tables derived staring at the ROMs intensely
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+/* 317-0013A FD1089B */
+static const UINT8 key_0013A[0x2000] =
+{
+ /* data */
+ 0xe8,0x96,0xcc,0x84,0x7f,0x25,0x35,0x48,0x45,0x72,0x12,0x92,0x41,0x51,0xe1,0x40,
+ 0x61,0x32,0xca,0x4e,0x8e,0x09,0x00,0x9e,0xe1,0xbb,0x58,0xb3,0xf4,0x70,0x79,0x96,
+ 0x09,0xa9,0x40,0xd4,0x0f,0x10,0xa8,0xd1,0x88,0xcf,0x0f,0xee,0xae,0x09,0x0e,0x8f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xde,0x1c,0x33,0xbf,0x2c,0xd8,0x04,0x06,0x22,0x16,0x50,0x30,0xdc,0xdd,0x6c,0x88,
+ 0xa0,0x55,0x8c,0xd0,0x08,0x9b,0xb3,0xa4,0xb9,0xb9,0x69,0x8a,0xde,0xfd,0x5d,0x3c,
+ 0x5d,0xd5,0xb9,0x63,0x07,0x6e,0x4e,0x36,0xe5,0x8a,0x47,0x2c,0xcd,0x3e,0xf2,0xbe,
+ 0x19,0x8a,0xe1,0x1c,0x75,0xb8,0xa2,0xb9,0x73,0x37,0x9f,0xb2,0xd9,0xb9,0x18,0x14,
+ 0xe5,0xd0,0xcb,0xe0,0x6c,0x4e,0xa6,0x6c,0xbb,0x11,0x75,0x70,0xa4,0x85,0x51,0xa1,
+ 0xad,0xaa,0x82,0xce,0xea,0xe5,0x2e,0xfc,0x44,0x97,0xa5,0x0b,0x25,0x89,0xc2,0x26,
+ 0x7e,0xf2,0x6f,0x35,0x66,0xc0,0x60,0xdd,0x8c,0x75,0xaf,0x1a,0x8f,0x46,0x7c,0x17,
+ 0xcc,0x64,0xda,0x49,0xef,0x2b,0xc3,0x66,0x43,0xf6,0x6f,0x96,0x65,0x28,0x88,0x1f,
+ 0x36,0x26,0xd0,0xed,0x24,0xe8,0x03,0xb3,0x74,0xd3,0x8c,0x84,0x46,0x07,0xd2,0x3e,
+ 0x43,0x72,0x85,0x80,0x8d,0x97,0x08,0x07,0x52,0xa6,0x63,0xfb,0x63,0x2f,0xe3,0xac,
+ 0x83,0x05,0xbb,0xce,0xaf,0xa7,0xd8,0xa1,0x8e,0x54,0xe7,0x99,0x1c,0x03,0xf5,0xe8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xda,0x5d,0x18,0xb6,0xa0,0x95,0x69,0x2c,0x42,0x09,0x5e,0x06,0x10,0x96,0xf0,0x80,
+ 0x1a,0xd6,0xf4,0x4d,0x90,0xbe,0x36,0xe8,0x7d,0x0f,0xc8,0x16,0x29,0x6d,0x97,0xd0,
+ 0xae,0x5d,0x5d,0xbe,0xdc,0xcb,0xab,0x8f,0x28,0xbf,0x4e,0xbe,0x09,0xb3,0x9e,0x51,
+ 0x76,0x05,0x9c,0x54,0x3b,0x37,0x6e,0x58,0x5a,0x46,0xee,0xbe,0xa9,0x49,0x1f,0x47,
+ 0xb3,0x72,0xb8,0x2c,0x5b,0x39,0x03,0x33,0xce,0xd2,0x22,0xfd,0x4b,0xe6,0x3a,0x05,
+ 0xad,0x94,0x23,0xfe,0x79,0xd9,0x72,0xab,0xc6,0xd0,0x79,0xbf,0xa6,0xbf,0x37,0x4f,
+ 0x04,0x36,0x51,0x1c,0xe1,0x4d,0x97,0xb0,0x90,0x5e,0xfa,0xbf,0x2a,0x22,0x1c,0xcd,
+ 0x6c,0x6a,0xed,0x6f,0x69,0xa5,0x3b,0x21,0x40,0xb3,0x52,0x6a,0xba,0x2f,0xe9,0x7a,
+ 0x3a,0xde,0x1b,0x84,0x1c,0x3a,0x2f,0xe6,0xc5,0x59,0x76,0xaa,0xca,0x2a,0x1e,0xe0,
+ 0x91,0xf6,0x61,0x9d,0xfb,0xcb,0x75,0x61,0xec,0xae,0xe5,0x2f,0x39,0xdb,0xb0,0x4e,
+ 0xcc,0x34,0xc1,0xb6,0x9e,0x82,0xaf,0x81,0xd7,0xfe,0x34,0x20,0x0a,0xf8,0x29,0x03,
+ 0xb7,0xea,0x98,0x12,0x95,0x89,0xee,0x43,0x33,0xdc,0x12,0xdc,0x03,0xf1,0x81,0x6c,
+ 0x22,0xf6,0x51,0x02,0xf0,0xc0,0xdc,0x81,0x84,0x7a,0x19,0x09,0x91,0x55,0x1a,0x2e,
+ 0x0b,0xc0,0x92,0xd1,0xb1,0x46,0x37,0xf6,0xb2,0xa8,0xb9,0xa5,0x36,0x1e,0xac,0x75,
+ 0xe5,0xac,0x8a,0x19,0xd5,0x2e,0x24,0xf5,0x29,0x8f,0x78,0xe8,0x5e,0x53,0x3c,0xf0,
+ 0xd5,0x26,0xcc,0x50,0xfb,0x21,0xbc,0x44,0xe6,0x71,0x6d,0xa9,0xb4,0x04,0x4a,0xe2,
+ 0x20,0xae,0x0b,0xbf,0x62,0x85,0x60,0xb2,0xbc,0xdb,0x48,0x86,0x51,0x6e,0xd2,0x07,
+ 0xea,0x91,0xdd,0xf8,0xa0,0xbc,0xd7,0x1e,0x9f,0x37,0x03,0x32,0x70,0x6b,0x5a,0xd9,
+ 0x6d,0x4f,0x28,0x99,0xe1,0x3d,0xbc,0x4a,0x42,0x02,0xb1,0x47,0x8d,0x08,0x42,0x0c,
+ 0x08,0x4f,0x4c,0x5c,0xe5,0x2e,0x4b,0xdc,0x90,0xa2,0x90,0xe1,0xbc,0x87,0x64,0x85,
+ 0x49,0xf8,0xd0,0x3f,0x9b,0xfc,0x0e,0x99,0x12,0xac,0x1a,0xb7,0x13,0xb4,0x9a,0xfc,
+ 0x17,0xcd,0xb7,0x43,0xc2,0x3b,0xd2,0x34,0xeb,0xab,0xcf,0xf3,0x81,0x44,0x56,0x61,
+ 0xb5,0xb6,0x2f,0xe1,0x76,0x65,0x6a,0x6d,0x68,0x72,0x27,0xc7,0x10,0x7f,0xb4,0x7d,
+ 0xf4,0x83,0xec,0xf8,0xa3,0xa8,0x98,0xf2,0x4a,0xbd,0x32,0x22,0x18,0xd4,0x41,0xca,
+ 0x7b,0x2e,0x02,0x5d,0x33,0x76,0x46,0x62,0xd6,0x87,0x61,0x08,0x7f,0x2a,0x3d,0x34,
+ 0xd0,0x0b,0x39,0x91,0x69,0x40,0xb4,0x01,0xc7,0x9e,0xb5,0x5c,0xee,0xbd,0x43,0x65,
+ 0x4b,0xb1,0xea,0xad,0xf3,0x24,0x33,0x4b,0xbc,0xb4,0x18,0xb6,0xbf,0x29,0x24,0xa0,
+ 0xd3,0xac,0x37,0x91,0x0a,0xbd,0x3e,0x6e,0xa5,0x5f,0xdf,0x6d,0xbb,0x41,0x13,0x30,
+ 0x9f,0x17,0xa0,0x0b,0xb6,0x16,0x55,0x58,0x30,0x77,0x83,0xb2,0x32,0x8d,0x3d,0xe3,
+ 0x2d,0xde,0x3f,0xe9,0xf3,0xf5,0xa7,0x80,0x39,0x34,0x46,0xda,0x8d,0x36,0x11,0x92,
+ 0x88,0xbf,0x6e,0x82,0xa0,0xf8,0x13,0xc6,0x79,0x9c,0xdb,0x4e,0x03,0x86,0xba,0x93,
+ 0x4e,0x4f,0xdf,0xf3,0x78,0x4a,0x52,0x2b,0x59,0xdf,0x97,0x8f,0xc2,0xab,0xe2,0xe2,
+ 0xcd,0x68,0x5c,0xa1,0xf4,0x8c,0xaf,0xa4,0xe2,0x00,0x0f,0x24,0xd2,0xae,0x9b,0xc9,
+ 0x8a,0xe3,0x37,0x1b,0xcc,0x21,0xd2,0x5b,0x84,0xc6,0x87,0x5b,0x01,0x5a,0xf5,0xf9,
+ 0xe6,0x2c,0xca,0xb4,0xbb,0xd1,0xfb,0xdf,0x18,0x29,0x8e,0x3f,0x7b,0x8e,0xa5,0x24,
+ 0x02,0xfa,0xab,0x43,0xe0,0x9b,0x70,0x25,0xdc,0x52,0x67,0xfb,0xf0,0x4a,0x0e,0x2a,
+ 0x32,0x0f,0x53,0xd7,0x7d,0x56,0xa3,0x39,0x31,0x34,0xce,0xdb,0xd5,0x73,0x2b,0x2d,
+ 0x5a,0x69,0x37,0xe0,0x93,0x0e,0x56,0x30,0xc4,0x42,0xac,0x43,0xd0,0x87,0x21,0x9e,
+ 0x1f,0xfd,0x93,0x92,0xef,0x5f,0xdd,0xa5,0xf6,0x17,0x75,0x14,0xdd,0xaf,0x36,0xd8,
+ 0xeb,0xc4,0x5a,0x41,0x93,0x80,0x96,0xbc,0x08,0x02,0xc7,0x0d,0xb6,0x6a,0x46,0x4a,
+ 0x52,0xe6,0x04,0xd0,0xd9,0x3d,0xd3,0xc7,0xd6,0xbd,0xa9,0x6b,0x92,0x13,0x4b,0xd0,
+ 0x80,0x2f,0x3f,0x6b,0xf0,0x69,0x83,0xd6,0x2c,0x61,0x29,0xfc,0x07,0x99,0xce,0x71,
+ 0xfc,0x1f,0x14,0x00,0x67,0x39,0x11,0x4a,0x27,0xeb,0xc3,0x4b,0x12,0x3f,0x3c,0x9e,
+ 0xcf,0x98,0x2b,0x03,0x52,0xf0,0x7d,0xaf,0x9d,0x4d,0x64,0x64,0x8b,0xb3,0xb0,0xd2,
+ 0x21,0x73,0x6d,0xa4,0xa9,0x23,0x1d,0x21,0x66,0xa2,0x99,0x4e,0xb1,0x44,0x69,0x58,
+ 0x74,0xd6,0x98,0x64,0xd6,0x50,0xda,0xc9,0xef,0x2f,0x9d,0x9c,0x27,0x6f,0x90,0xee,
+ 0xf1,0x69,0x94,0xcc,0xc3,0xb4,0x9b,0x3c,0x35,0x54,0x20,0xdb,0x46,0x61,0x78,0x16,
+ 0x86,0x37,0x9d,0x7e,0x6d,0xd9,0xbd,0x27,0xcc,0xc6,0x4b,0x4a,0x20,0x84,0x3e,0x0b,
+ 0x60,0xf0,0xc0,0x1c,0xba,0xc8,0x1e,0x83,0xdf,0xe7,0x03,0xc4,0x74,0x50,0x84,0xd2,
+ 0x51,0xa2,0xc3,0xcb,0x48,0x72,0x0b,0x49,0x81,0xd2,0xe3,0x89,0x3b,0x94,0x22,0xb7,
+ 0x5d,0x94,0xb8,0x6e,0x94,0x77,0x83,0xe6,0xad,0x20,0xdd,0xcc,0x44,0x75,0x48,0x2c,
+ 0xe3,0x95,0x4f,0x42,0x2a,0xd5,0xee,0xfa,0x87,0x94,0x13,0x18,0x2d,0xb9,0xdb,0x89,
+ 0x0d,0xbb,0x0f,0xfb,0xe1,0x2c,0xa4,0x3e,0xbb,0x7e,0x66,0xc2,0x77,0x68,0xe3,0x42,
+ 0x13,0xc2,0x42,0x06,0x8f,0x98,0x84,0xfc,0x2d,0xb8,0xe1,0xca,0x16,0xb5,0xd6,0x64,
+ 0xd8,0xf0,0xec,0x98,0x6a,0x66,0x18,0x6f,0x32,0x62,0x5b,0xf1,0x61,0xad,0x30,0x86,
+ 0x8b,0xe4,0x2f,0x8c,0x09,0xe1,0x0a,0xb8,0x89,0x0f,0x4d,0x00,0xcc,0x75,0x1e,0x14,
+ 0xec,0x17,0xa1,0xc5,0xc4,0xc1,0x96,0xd8,0x32,0xad,0x5c,0xa0,0x93,0xa7,0xf8,0x65,
+ 0x57,0x76,0xb1,0xd8,0x96,0x67,0x82,0x19,0xbb,0xc4,0x4e,0x09,0x3d,0xbe,0x5f,0xe4,
+ 0xb8,0x8d,0xe6,0xcc,0x97,0x92,0x0e,0x04,0xa8,0x1d,0xe0,0x90,0x92,0xce,0xdc,0xf7,
+ 0x1b,0x11,0x54,0x2b,0xe4,0x1d,0x20,0xf6,0xd2,0xaf,0xa5,0x35,0xc7,0xb9,0x7b,0x16,
+ 0x5c,0x8a,0xfb,0x97,0x38,0x9d,0x9a,0x66,0xab,0xab,0xc9,0x40,0x05,0x39,0x26,0x15,
+ 0x07,0x3a,0x18,0xda,0x8f,0x61,0x68,0x18,0x2f,0xd4,0x60,0x00,0x1e,0x67,0x78,0x76,
+ 0x9c,0xaf,0x5d,0xfb,0xcb,0x86,0x31,0x61,0x7c,0x77,0xc5,0x11,0x2d,0x57,0x0e,0x4f,
+ 0x6f,0xcc,0x8c,0x07,0x32,0x90,0x2c,0xd4,0x7f,0xc8,0xd8,0xb6,0x3e,0xd5,0x57,0xa0,
+ 0x8b,0x78,0x10,0x50,0x50,0x9c,0xbe,0x57,0xec,0xcf,0xb7,0x19,0xbc,0x24,0xd6,0x9b,
+ 0x6a,0xb9,0x9f,0xe4,0x02,0x7e,0x5f,0xea,0xdc,0x5d,0xf4,0x72,0xe1,0x5b,0x5c,0xfb,
+ 0xd1,0x08,0x10,0x6e,0x68,0x5a,0x10,0x0b,0x78,0xcc,0x68,0x5c,0x87,0x85,0x0e,0x07,
+ 0x72,0xf2,0xdb,0x5d,0x75,0x52,0x06,0xcc,0x79,0xbd,0x89,0xcb,0x20,0xd0,0x73,0x5a,
+ 0xf0,0xe3,0x69,0x9b,0x2f,0x56,0x93,0xde,0x6a,0x75,0xc1,0xf5,0x56,0xdc,0x26,0x70,
+ 0x61,0x0a,0x0a,0x54,0x2c,0xa6,0x61,0xf8,0x7b,0x72,0x6f,0xa5,0x7f,0x95,0x6e,0xf5,
+ 0xc9,0xaa,0x7f,0xee,0x80,0xcd,0xf5,0xec,0xfe,0x6c,0x3f,0x2e,0xb1,0x83,0xf9,0x00,
+ 0xcd,0x6e,0x5c,0x55,0x48,0x76,0x32,0x24,0xdd,0xcb,0x20,0x7e,0x92,0x9f,0xab,0x88,
+ 0x08,0x3f,0x26,0xf0,0x96,0x84,0xbe,0x55,0x7e,0x27,0x20,0x34,0xd0,0xc0,0xf7,0xa3,
+ 0xee,0x02,0xec,0x8a,0xc2,0x8d,0x73,0x32,0xdc,0x8b,0xe9,0x36,0x10,0xe6,0x0f,0x46,
+ 0xf7,0xc1,0xfe,0x2c,0x0a,0xc9,0x37,0xf9,0xc2,0x96,0xce,0xcd,0xc0,0xde,0x23,0xd1,
+ 0xe7,0xf2,0xc7,0xc0,0x44,0x2f,0x9c,0xc9,0xe4,0xa5,0x11,0xac,0x4f,0x54,0x98,0x76,
+ 0x6c,0x5e,0x48,0x47,0xf7,0xa6,0x32,0x18,0x09,0x90,0x2c,0xfa,0xaa,0x1c,0x5f,0x11,
+ 0x8f,0x4b,0x2f,0x66,0x51,0x7f,0x88,0x2a,0x46,0xb8,0x48,0xd5,0xe7,0xa8,0xe7,0x92,
+ 0xb0,0xa2,0x99,0xe8,0xeb,0x2d,0xc7,0x7b,0x34,0x0d,0x5f,0x0c,0xec,0x39,0x79,0x77,
+ 0xb8,0xb2,0x92,0x11,0x0a,0xd7,0xbe,0xa2,0x50,0xc6,0x3b,0xe9,0xa1,0x9c,0x39,0x4f,
+ 0x37,0x08,0xa3,0x65,0xfc,0xa2,0xd8,0xd8,0x94,0x1d,0x37,0x46,0x44,0xdd,0xfc,0x8a,
+ 0x1b,0x03,0x50,0x92,0x12,0x72,0xa0,0xf1,0x13,0xed,0x49,0xc0,0xb1,0xd7,0xec,0x0a,
+ 0x2a,0x28,0x5f,0x3c,0xab,0x69,0x3b,0x6c,0x7f,0x79,0x1f,0xd2,0x40,0x92,0x75,0x07,
+ 0xfd,0xf4,0xeb,0x52,0xbb,0xfd,0xda,0xd1,0x76,0x3f,0xb1,0x24,0xb9,0xe4,0x9b,0x0d,
+ 0x60,0xb2,0x2b,0x8c,0xed,0x6d,0xc0,0x88,0xfe,0x9b,0xc0,0xe3,0x90,0x28,0xa5,0xb2,
+ 0x56,0x9e,0xaf,0x15,0x1b,0x89,0x7c,0xf5,0x68,0x72,0xbe,0x2c,0x53,0x39,0x80,0x86,
+ 0x53,0xdd,0x0c,0xf9,0x91,0xf4,0x70,0x3e,0x03,0x9f,0xfb,0x57,0x4a,0x29,0xf7,0x13,
+ 0xac,0x38,0x8e,0xab,0x7a,0xca,0xbe,0xa3,0xaf,0xbf,0x6a,0xf5,0x2b,0x4d,0xf7,0xb6,
+ 0xee,0x97,0xab,0x4b,0xe3,0xb0,0x7a,0x20,0x09,0xbb,0xd5,0x57,0x86,0x05,0xe1,0x1a,
+ 0xd3,0x86,0x0d,0xde,0x11,0xd6,0xe6,0x62,0x0c,0xab,0xa8,0x2c,0x37,0x86,0x25,0x11,
+ 0x40,0x01,0x3a,0x29,0x79,0x6d,0xf3,0x5b,0xe2,0xe3,0xd5,0x82,0x7a,0xa3,0x89,0xbd,
+ 0x7b,0x78,0x4a,0x7c,0x7f,0xae,0x98,0x2f,0x30,0x40,0x6a,0x24,0xf8,0x68,0xe7,0x59,
+ 0x66,0x16,0x7f,0xb8,0x74,0xc0,0x13,0xaf,0x44,0x0c,0xfb,0x95,0xcc,0x4e,0x78,0x9f,
+ 0xb3,0x3a,0x01,0x3a,0x62,0xef,0xb5,0xe4,0x12,0x55,0xbe,0xc0,0x3e,0x38,0xa4,0x6d,
+ 0xe6,0x84,0x28,0x3d,0x18,0x86,0xad,0xf2,0x9d,0xf3,0xc0,0xa1,0xc9,0x72,0xcf,0x16,
+ 0xd5,0xad,0xb1,0xa2,0x1d,0xb4,0x19,0xc8,0xbd,0xe8,0xb1,0xf3,0xdb,0x1c,0x6c,0x1e,
+ 0x8d,0x35,0x6e,0x1b,0x5c,0xa2,0x87,0xc6,0x7f,0xda,0x1f,0x8a,0xdb,0x29,0x32,0x03,
+ 0xa3,0xd3,0x35,0x7d,0xbf,0xa3,0x09,0xb6,0x95,0xdb,0x49,0xed,0xca,0x26,0xd2,0x28,
+ 0x13,0x9d,0xee,0x70,0x03,0x16,0xf9,0xb5,0xcc,0xce,0xe2,0xb5,0x2e,0xdc,0x46,0x8e,
+ 0x74,0x70,0x73,0xf3,0x3a,0xd0,0xb7,0x68,0xbf,0x37,0x50,0xa9,0x79,0x54,0xe9,0x73,
+ 0x0f,0xe2,0xac,0x20,0x60,0x74,0x12,0x6c,0xe9,0x79,0xb5,0x49,0xea,0x09,0x8c,0xc7,
+ 0xf0,0x24,0x05,0x94,0x61,0x8d,0x8e,0xc7,0xf1,0x29,0xbf,0x47,0x78,0x72,0x64,0x59,
+ 0x8a,0xdc,0x1d,0x74,0x56,0xbe,0x43,0x8b,0xd0,0x8e,0x42,0x97,0x25,0xbb,0x69,0xc7,
+ 0x88,0xba,0x56,0x95,0xd5,0x5a,0xc3,0x1e,0xd6,0x48,0x4c,0x3e,0x40,0xba,0x36,0x7a,
+ 0x00,0x37,0xe0,0x2c,0x80,0x2f,0x70,0xb7,0x1a,0x5b,0x9f,0x0c,0x97,0x6f,0x35,0x46,
+ 0x2d,0x2e,0x35,0xb7,0x97,0x99,0x8d,0x0b,0x0b,0xc9,0xa5,0x0d,0x70,0x22,0x93,0xf6,
+ 0xfc,0xf6,0x7f,0x13,0x14,0xd3,0x0c,0xd0,0x81,0xc6,0xcf,0x38,0x63,0xfe,0xc2,0x16,
+ 0xc2,0xd8,0x23,0xa0,0xe3,0xb3,0x4d,0x96,0x59,0x98,0x4f,0x8b,0xbe,0xa2,0x53,0x6b,
+ 0x83,0x87,0x85,0xcd,0x7c,0x18,0xca,0xf4,0xad,0xea,0xd9,0x9b,0xa0,0xf7,0x55,0x5c,
+ 0x57,0xeb,0xbe,0xa3,0xa5,0x60,0x34,0x88,0x84,0xad,0x1d,0x3b,0x42,0x44,0x6a,0x6f,
+ 0x5f,0xbe,0x4d,0x65,0xc4,0x75,0x87,0x87,0x8e,0x5f,0x7b,0x75,0xea,0x5e,0x08,0xcc,
+ 0xfb,0x86,0xcd,0x6a,0xe7,0x0a,0x0b,0x86,0x58,0x5a,0x94,0xf9,0x7e,0xa3,0x1a,0xce,
+ 0x58,0x43,0xf6,0x44,0x76,0x28,0x19,0xea,0xce,0x71,0x40,0x96,0x30,0xdc,0x9a,0x28,
+ 0xec,0x1e,0x9b,0x9a,0xa6,0xbb,0x27,0xae,0xa7,0x49,0x8d,0x19,0x85,0x76,0x47,0x81,
+ 0x91,0xd4,0x9d,0xdf,0x40,0xc6,0xe9,0xdc,0xde,0x4a,0xcd,0x02,0xc1,0x39,0x0b,0x67,
+ 0x7c,0xb4,0xe3,0xe2,0xa5,0xb4,0xad,0xc2,0x8c,0xb0,0xa8,0x0a,0x87,0xeb,0x81,0x39,
+ 0x3a,0x6b,0x3a,0x5c,0xdc,0x73,0x10,0xcc,0xc8,0x6f,0xdc,0xe2,0x46,0x68,0x02,0xf5,
+ 0x19,0xef,0x72,0x66,0x19,0xd7,0x78,0x2c,0xf9,0xb5,0xad,0x0c,0xba,0xd0,0x11,0x27,
+ 0x5f,0xfb,0x58,0x14,0x50,0xb7,0x42,0x9f,0xe2,0x72,0xd3,0x38,0x4a,0x51,0xb4,0xc9,
+ 0x71,0xa4,0xe4,0x35,0x54,0x1e,0xe6,0x01,0x23,0xd7,0x65,0xa5,0xc8,0xba,0x8f,0x8d,
+ 0x1d,0x8a,0xef,0xb1,0xdf,0x0d,0x66,0x51,0x1e,0xb7,0xf9,0x08,0xb1,0x7d,0xb7,0x9f,
+ 0x33,0xf7,0x53,0x74,0x88,0x72,0x02,0x97,0x30,0x2f,0xa6,0x63,0x24,0xb7,0x5d,0xc8,
+ 0x99,0xfc,0x79,0x4b,0xfd,0x68,0xdd,0x82,0xf2,0xb6,0xfd,0xd4,0x1f,0xfe,0xef,0x24,
+ 0xb3,0xc1,0x31,0xa6,0xfa,0xa5,0xe6,0x6c,0x0c,0xdc,0xa8,0x7c,0xca,0xf7,0x33,0x5e,
+ 0x7f,0x1f,0xe8,0x1b,0x93,0x7f,0x29,0x0a,0xb9,0x73,0xe6,0x7f,0x00,0xf8,0x0c,0x2c,
+ 0x6f,0x82,0x03,0x3d,0xad,0x2f,0x68,0xa9,0x2e,0x04,0x86,0x4d,0xbc,0xd3,0x2e,0x4b,
+ 0x17,0x71,0xe1,0x91,0xc3,0x30,0x4e,0xf3,0x8b,0x65,0x12,0x94,0xe4,0x96,0x60,0x64,
+ 0xf8,0xd7,0x6a,0x97,0x59,0x08,0xbe,0x33,0xd5,0x3d,0x94,0xb2,0x55,0xa0,0xbf,0x2e,
+ 0x7a,0x3e,0x76,0x29,0xef,0xfd,0x90,0xfd,0x99,0x40,0xe4,0x53,0x4b,0xa0,0x0f,0x0d,
+ 0x8d,0x7f,0x31,0xdb,0xc9,0x58,0x25,0xc7,0x6f,0x29,0xdd,0xfe,0x55,0x52,0x68,0xad,
+ 0x16,0xb3,0x14,0x83,0xb9,0x4b,0x50,0x69,0x5d,0x70,0x21,0xbe,0x75,0xd1,0x1e,0xbb,
+ 0x3d,0x18,0xb5,0xb2,0x72,0x1c,0x09,0x2b,0x55,0x30,0x07,0xea,0xf9,0x9d,0xcd,0x60,
+ 0xbb,0xeb,0x7a,0x19,0x00,0x6d,0xc9,0x88,0x63,0x55,0x0c,0x8f,0x56,0x07,0x96,0x9c,
+ 0xb7,0x5c,0x27,0xaf,0x79,0xf9,0x5d,0xfe,0x66,0x35,0x3a,0xea,0xc9,0x1e,0x09,0x2f,
+ 0x18,0x9f,0x0f,0x29,0x3f,0xf5,0xd5,0x8e,0xc1,0xa2,0x34,0x1d,0x0f,0x84,0x97,0xdb,
+ 0xfc,0x08,0x62,0xdc,0xc1,0x77,0x85,0x63,0x70,0xfb,0xed,0xfe,0x36,0x2e,0x76,0x72,
+ 0x18,0xf7,0xb2,0x67,0x6a,0xf8,0x54,0xa8,0x39,0xf7,0x08,0x22,0x14,0x99,0x36,0xb9,
+ 0xf2,0x6b,0xdf,0xa8,0x86,0xbd,0x4a,0xa7,0x83,0x24,0x0b,0x24,0x9a,0x78,0xfd,0xab,
+ 0xaa,0xbb,0xeb,0x05,0x37,0x8d,0xbf,0xf9,0x0d,0xd0,0x0a,0xe0,0x09,0x46,0x2c,0xab,
+ 0xaa,0x00,0x4b,0xcc,0xa4,0x07,0xe9,0xad,0xe8,0xd1,0x0c,0x5c,0xaf,0xb8,0x37,0x3f,
+ 0xf2,0xf4,0x9f,0x5a,0x27,0x07,0x06,0x24,0x32,0x13,0x27,0xdf,0x68,0x0b,0x75,0xc5,
+ 0x18,0xb5,0xcf,0xad,0xe2,0xfa,0x00,0xde,0xe7,0x3e,0xf7,0x6c,0x53,0xf6,0xac,0x8c,
+ 0x7c,0x6c,0xd6,0x0b,0x46,0xd8,0xe7,0xc9,0xc1,0x35,0x8f,0xc6,0x95,0xc3,0x3e,0xb9,
+ 0x59,0x27,0x47,0xa5,0xb4,0x9f,0x40,0xcf,0xfc,0x0a,0xe0,0x73,0xd0,0x3e,0x5c,0xdb,
+ 0x7b,0x83,0xf5,0x49,0x91,0xc4,0x4a,0xed,0xca,0xaf,0x48,0x44,0x95,0xd6,0x72,0x3d,
+ 0x63,0x26,0x28,0x18,0x77,0xb0,0x0a,0x02,0x29,0xdb,0xb4,0xfc,0xb1,0xcc,0x2f,0xa8,
+ 0xae,0x08,0x01,0x72,0xca,0x26,0x7c,0x2e,0xd1,0xcd,0x59,0x62,0xdd,0x25,0xe3,0x62,
+ 0xe2,0x10,0xc1,0xbe,0x20,0x0b,0xf4,0xb1,0x1b,0x92,0x42,0x22,0x3a,0x8f,0x60,0x20,
+ 0xd5,0x0f,0x4f,0x9a,0x7a,0x12,0xa2,0x78,0xbb,0x7b,0xa0,0x07,0x03,0x6e,0x7e,0x27,
+ 0x0f,0xcf,0x8c,0xf2,0xa4,0x79,0x7b,0xe3,0x08,0x0b,0xbe,0x80,0xc3,0x3a,0xdb,0x3b,
+ 0x50,0xcf,0xc5,0x64,0xe0,0x37,0x16,0x29,0x64,0xe7,0x63,0x9f,0x1c,0xe5,0x42,0x10,
+ 0xb3,0x1f,0x28,0xc2,0xde,0x65,0xa2,0x49,0x8b,0xbc,0x70,0xf9,0x6f,0x1f,0x04,0x50,
+ 0xf1,0x02,0x67,0x51,0xbb,0x7f,0xf8,0xf0,0x6b,0x7e,0x97,0xe7,0xf4,0x0b,0xc8,0xd8,
+ 0xed,0xeb,0x7a,0x30,0x95,0xab,0xc8,0x7a,0x89,0xdc,0x40,0xac,0x41,0x51,0x6f,0x54,
+ 0x94,0x39,0xd3,0x83,0x78,0x40,0x5f,0xb5,0x72,0x34,0x93,0xe1,0x97,0x4c,0x3d,0x70,
+ 0x65,0xf6,0x0f,0xd7,0xb5,0xc2,0x11,0xd8,0x89,0x86,0x94,0xbd,0x8b,0x1c,0x5c,0x61,
+ 0x94,0x8e,0x50,0x17,0x01,0x85,0xb2,0x2d,0xdc,0xb4,0xaa,0x75,0x98,0x63,0x64,0x42,
+ 0x7c,0xf9,0x52,0x2e,0xdd,0x21,0x77,0x2a,0x8b,0xae,0x83,0xfb,0xb5,0x2a,0x19,0x1e,
+ 0x03,0x80,0xfc,0xed,0x8e,0xf9,0xd2,0x36,0xd4,0x8f,0xb9,0x08,0xa1,0xef,0x60,0xc3,
+ 0x07,0xc5,0xe7,0x8b,0x36,0x17,0xac,0xa9,0x86,0x5b,0xd3,0x0d,0xf0,0x73,0x0a,0x84,
+ 0x3c,0x9a,0x4d,0xbe,0x3a,0x56,0x37,0x26,0x84,0x3b,0x2a,0x0b,0x73,0x8e,0x38,0x12,
+ 0x96,0x63,0x46,0xe2,0xb2,0x92,0x8f,0x58,0x67,0x86,0x99,0x28,0xf5,0xe4,0x7e,0xf9,
+ 0x8e,0x1c,0xec,0xd6,0xd6,0x4c,0x1b,0xc1,0xac,0x37,0xd6,0x64,0x54,0xd3,0x93,0x93,
+ 0xe6,0x9b,0x14,0xf7,0x49,0xb3,0x1f,0x48,0xba,0x7e,0x61,0x4a,0xba,0x39,0xee,0x55,
+ 0x1f,0xe0,0x01,0xc1,0x62,0x06,0x00,0x3e,0x50,0x8d,0xdc,0x54,0x14,0x09,0xcb,0xdb,
+ 0x7c,0xe0,0x2e,0xa1,0x45,0x9a,0xeb,0xae,0x5d,0x7f,0x7c,0xae,0xdc,0x4c,0xbc,0x09,
+ 0x9e,0x9b,0x61,0x98,0xae,0xd1,0xda,0x18,0x52,0xbd,0xb6,0x0e,0x1f,0x4f,0xbe,0xbd,
+ 0x18,0xab,0x5f,0xf6,0xe3,0x1d,0xda,0x83,0x7c,0x8c,0x45,0xb6,0x1c,0xd0,0xd8,0xa7,
+ 0xc8,0xe5,0x38,0x69,0x07,0xfc,0x8d,0xdb,0xb9,0x5a,0xa6,0xc4,0x4c,0x16,0x87,0x01,
+ 0x55,0xca,0xce,0x17,0x08,0x12,0xd5,0xb2,0x5c,0x2b,0xf5,0xd4,0x77,0x73,0xd7,0xd1,
+ 0x46,0x72,0xa2,0xf6,0x3b,0xbe,0xbe,0xfc,0x17,0x9c,0x5c,0x91,0xec,0xe3,0xd1,0x8c,
+ 0xc9,0xa4,0xdb,0x6e,0x98,0x19,0xde,0x89,0xb1,0xc8,0x3a,0x1f,0x80,0x55,0x7d,0x6d,
+ 0x1b,0xc2,0xb2,0xeb,0x23,0x7c,0x8d,0xb8,0x3a,0x7d,0xe7,0x9a,0x29,0x77,0x57,0xf5,
+ 0x4f,0x03,0x47,0x91,0x4a,0xb5,0x83,0xa5,0x6d,0x18,0x17,0x64,0xca,0x2e,0x33,0x0d,
+ 0xbc,0x22,0x18,0x4a,0xbc,0x83,0x88,0x4f,0xfe,0x0e,0x03,0x7f,0x73,0x2c,0x0b,0x6e,
+ 0xfa,0xe0,0x08,0xe8,0x03,0x83,0x94,0x42,0x86,0xc1,0xa3,0x93,0xc4,0xc2,0x63,0x67,
+ 0xc4,0x88,0x80,0x2a,0x46,0xfd,0x10,0x18,0x83,0x6d,0xf6,0x43,0x00,0xc4,0x72,0x6a,
+ 0xa3,0x42,0x4c,0x9f,0xda,0x3d,0x41,0xe9,0x11,0x9c,0x42,0xee,0xfc,0x74,0x41,0x10,
+ 0xf1,0xd1,0x60,0x3e,0x27,0x6b,0x83,0xd3,0x35,0x58,0xa3,0x2f,0xd0,0xd2,0xbf,0x01,
+ 0xbf,0x1a,0x0b,0xfe,0xda,0x25,0x5d,0x2e,0x6d,0xa8,0xfb,0xe3,0xbd,0x8d,0x03,0x87,
+ 0x25,0x85,0x80,0x5f,0x31,0x6e,0x76,0xb3,0xba,0xab,0xc1,0x30,0x98,0xb3,0x11,0xca,
+ 0xea,0x46,0xee,0x87,0x84,0xb6,0xe6,0xe6,0xeb,0x54,0xaf,0x7b,0x30,0x1c,0xdb,0x99,
+ 0xcc,0x29,0x7d,0xf9,0xda,0x3d,0x2a,0x7b,0x07,0x62,0x72,0x8d,0x5c,0x92,0x40,0x9e,
+ 0xf4,0xca,0x36,0x59,0x9e,0xa6,0xd7,0x7d,0x80,0x24,0x97,0xd6,0xe5,0x97,0x3e,0x23,
+ 0x5c,0x41,0x7e,0x6c,0xe8,0xd0,0x68,0xaa,0x97,0xae,0xdc,0x0c,0xd9,0x02,0x25,0xf5,
+ 0xab,0x26,0xd5,0x46,0x38,0x58,0x57,0x13,0xab,0x3f,0xb5,0x95,0x49,0x5b,0xa0,0xd0,
+ 0x0e,0xc1,0x40,0x46,0x49,0x9b,0x56,0x3c,0x99,0x12,0x42,0xa8,0x16,0x98,0xa0,0xe8,
+ 0xd9,0xc1,0x96,0xfc,0xfc,0xfe,0x5d,0xbf,0x6e,0xb3,0x6f,0x7d,0x81,0x5d,0x25,0xe9,
+ 0x9b,0x25,0xc2,0x08,0x7f,0xf9,0xf4,0x84,0xa1,0xb4,0x90,0xa1,0xa8,0x76,0xae,0x31,
+ 0x69,0x02,0xe3,0xc8,0x9b,0x8a,0x73,0xcf,0x73,0x17,0xd9,0xdd,0x58,0xe1,0xcf,0x6f,
+ 0x7d,0x82,0xcb,0xf2,0x99,0x74,0x38,0x59,0xa9,0x4d,0xab,0x93,0xdc,0x89,0x81,0xb1,
+ 0xb4,0x0d,0x77,0x59,0x33,0x24,0xf1,0x14,0x60,0x90,0x87,0xf1,0x98,0x44,0x97,0x2e,
+ 0x22,0x18,0xaa,0x38,0xb5,0x50,0xd4,0x40,0x63,0x91,0xc0,0x01,0x70,0xe9,0xd8,0x07,
+ 0x15,0xb6,0x64,0x2a,0xec,0x39,0x34,0x3f,0xcc,0x5d,0x0c,0x42,0x2b,0x03,0x09,0xdf,
+ 0x54,0x9b,0x81,0x19,0x4e,0x6a,0x00,0x92,0xa9,0x13,0xda,0x9e,0xdb,0xb3,0x4d,0x28,
+ 0xdb,0x6a,0xe0,0xe0,0x5b,0x29,0x17,0xc0,0xd2,0x0b,0x37,0x1d,0x96,0xd4,0x8f,0xbc,
+ 0x84,0x4d,0x0f,0xa5,0x55,0x45,0x2d,0x08,0xd4,0xc3,0x63,0x6a,0x4e,0xac,0x0b,0x5d,
+ 0x8c,0xf7,0x18,0xd5,0x75,0x25,0x82,0x65,0x2f,0x44,0x9d,0xd2,0x95,0xaa,0x6b,0xdf,
+ 0xfc,0x35,0x8b,0x08,0x63,0x61,0xbe,0x99,0xec,0x2c,0xda,0xb7,0x88,0x88,0x6b,0x08,
+ 0xbf,0x06,0xfd,0xaa,0x13,0x1e,0xd1,0xa0,0xeb,0x62,0x8f,0x2b,0xe6,0x03,0xab,0x4b,
+ 0x14,0xd1,0x22,0x0d,0x0c,0xbd,0x31,0x97,0xc5,0xea,0x5c,0xdb,0x8a,0x0b,0x45,0xbc,
+ 0x70,0xf3,0x53,0xe7,0xe1,0x8c,0x8e,0x8b,0x74,0x77,0xca,0x71,0x22,0x7c,0x8d,0xe9,
+ 0x81,0x53,0x1c,0x1f,0x8d,0x40,0x18,0x60,0xc6,0x96,0xfa,0x58,0x1d,0xae,0xc0,0x79,
+ 0xe5,0x04,0xa8,0xac,0xc8,0x1c,0x6b,0x83,0xbc,0x39,0xe1,0x33,0x0d,0x7d,0x2c,0xc7,
+ 0x72,0xb9,0xcf,0xd9,0x58,0xbc,0x3f,0x6e,0xe6,0xbf,0x2e,0xc6,0x4f,0x8c,0x75,0x95,
+ 0xc6,0xb1,0x58,0x27,0x59,0x5d,0xa3,0x6d,0x18,0x86,0x0a,0x7e,0x24,0xfb,0x1c,0x66,
+ 0xab,0x85,0x57,0x88,0xfd,0x5d,0x58,0x65,0xa6,0x8e,0x22,0xfe,0xc1,0x86,0xfd,0x82,
+ 0x83,0xdd,0x8d,0x1d,0xa4,0x05,0x97,0x19,0xfe,0x11,0x34,0x54,0x5f,0xec,0xa8,0x8e,
+ 0x59,0x72,0x21,0xec,0xd0,0x59,0x6d,0x2d,0x4b,0xb1,0x34,0xad,0xb2,0x59,0x78,0xf9,
+ 0x57,0xdf,0xcb,0x99,0xfd,0xfb,0x67,0x91,0xc1,0xfd,0x53,0x59,0xe2,0xeb,0x0c,0x70,
+ 0xdd,0xc3,0x3a,0x8c,0x27,0xc9,0x52,0x91,0x2d,0xfd,0x48,0x51,0xd5,0x44,0xe7,0xd8,
+ 0x0d,0xf5,0x08,0x85,0x3b,0x46,0x01,0x2d,0xc7,0xb1,0xb1,0xd9,0xaf,0x17,0xae,0x85,
+ 0x9c,0xdc,0x73,0xa0,0xd6,0x83,0xa0,0x19,0x19,0x41,0xaf,0xb3,0x43,0x6a,0x77,0xda,
+ 0x69,0x6c,0x4b,0x2b,0xc2,0x0f,0x2c,0x65,0x94,0x9e,0x00,0xc9,0x77,0xdc,0xe8,0x66,
+ 0x07,0x95,0x7c,0xe7,0x72,0xe3,0x68,0x3f,0x0d,0x96,0xf6,0x32,0x84,0x3d,0x1f,0xeb,
+ 0xc9,0xa1,0x79,0x70,0xd8,0x5e,0xe4,0x61,0xa2,0xf6,0xd9,0xf8,0xec,0x1a,0x9c,0x38,
+ 0x00,0xb0,0x0f,0x4e,0x47,0x90,0x97,0x9f,0x7e,0xd2,0x29,0x0c,0xf0,0xc2,0x8b,0x12,
+ 0x07,0xd1,0x15,0xb4,0xb4,0xf9,0x19,0xce,0x5c,0x93,0xb5,0x96,0x73,0xcb,0xde,0xc2,
+ 0x95,0x78,0xe0,0x96,0x54,0xc0,0x98,0xd4,0x40,0xd9,0x91,0x55,0x82,0xd5,0x02,0xef,
+ 0x72,0x0a,0xca,0x01,0xbf,0x7e,0xcb,0x72,0x9c,0x73,0x6d,0x44,0xfd,0xc1,0xb1,0x0f,
+ 0x1d,0x2b,0x62,0xd2,0x47,0x4b,0xaa,0x8d,0x85,0x8d,0xb4,0x80,0xe1,0x27,0xb2,0x1d,
+ 0x20,0xc4,0x47,0xb9,0xb6,0x1a,0xfb,0xef,0xda,0xc9,0xe4,0xec,0xe4,0xf0,0xdb,0x0e,
+ 0xb9,0xeb,0xbf,0xc2,0xc5,0xcc,0xb2,0x3d,0xb6,0x0a,0x2d,0xab,0xe0,0x1b,0xcb,0x30,
+ 0x8d,0x92,0xa4,0x52,0x8a,0x80,0xd8,0xb8,0x2c,0xb3,0xdc,0x25,0xb8,0x90,0x64,0xd4,
+
+ /* opcodes */
+ 0xe2,0xae,0x2f,0x63,0x69,0x10,0x04,0xb4,0x87,0x22,0xfc,0xc1,0x4e,0x26,0xd8,0x70,
+ 0x47,0xa5,0x8b,0x48,0x62,0xdd,0x93,0x0a,0x5a,0x31,0xaf,0x4b,0x12,0x29,0x88,0x98,
+ 0xd1,0x7f,0x33,0xf0,0x86,0x86,0x9c,0xf8,0x1b,0x6a,0xc1,0xf6,0x26,0x33,0xca,0x57,
+ 0xd2,0x66,0x0f,0xfd,0x05,0x28,0x38,0x76,0xa9,0x5e,0x87,0x33,0x2a,0x57,0xad,0x11,
+ 0xb4,0x9a,0x24,0x7e,0x40,0x2f,0x1e,0xdb,0xa0,0xb1,0x14,0x9f,0x7f,0x66,0xf6,0x73,
+ 0xa1,0x60,0x8e,0xde,0x1c,0x32,0xee,0xd0,0x40,0x77,0x5f,0x8e,0x0a,0x46,0xae,0xbb,
+ 0x02,0x6f,0x75,0x8b,0x73,0x0f,0xa6,0x56,0xe3,0x5e,0x94,0xcd,0xb6,0x11,0x61,0xcc,
+ 0x31,0xca,0xf7,0x38,0x0c,0x18,0x2c,0x58,0x4e,0xbd,0xd7,0x05,0x7f,0xc7,0xaf,0x9e,
+ 0xa6,0xd8,0x55,0x88,0xee,0x75,0xd7,0xeb,0x4e,0x95,0x3d,0x84,0xcb,0xf8,0x03,0xfc,
+ 0x60,0xff,0x75,0x63,0x81,0x40,0x45,0x82,0xe3,0x22,0xfb,0x56,0x4a,0x77,0x7e,0x2d,
+ 0x62,0x59,0x1a,0x77,0x00,0xb3,0xc8,0x82,0x40,0x7d,0xe1,0xb5,0x8c,0xba,0x76,0xdd,
+ 0x20,0xaa,0xe6,0xc3,0xd6,0xb5,0x39,0xeb,0x1b,0x2e,0x93,0x49,0xb7,0x67,0xb0,0xd9,
+ 0xd1,0x75,0x8b,0x35,0x43,0x5c,0xa2,0x58,0x5a,0xc1,0xf2,0x4f,0xf2,0xd9,0x32,0xec,
+ 0xe7,0x18,0x7d,0xbd,0x3e,0x0f,0x17,0x56,0x87,0xe7,0x95,0x3d,0x03,0xbc,0x96,0xbb,
+ 0x74,0x92,0x6d,0x4e,0x0e,0x97,0x9d,0xd0,0xd4,0x09,0xfb,0x69,0x43,0xaa,0x06,0xfb,
+ 0x06,0xbb,0x3f,0x1d,0xfe,0xb0,0x5b,0xf8,0xcf,0x6c,0x58,0x27,0x0c,0xbd,0xd0,0x38,
+ 0x1c,0xc2,0x4e,0xa3,0x26,0x88,0x96,0x4a,0x3e,0x9b,0x14,0x31,0x90,0xfe,0xc0,0x5a,
+ 0xec,0x38,0xb2,0x40,0x3b,0xa4,0x96,0xca,0x11,0xbb,0xf1,0x87,0x22,0xae,0x3e,0xd9,
+ 0x22,0x9e,0xd5,0x06,0x0b,0x0c,0x0d,0xff,0x9a,0x01,0xa7,0xd5,0x25,0x38,0x4d,0x62,
+ 0x98,0xfb,0xf0,0x5b,0x41,0x81,0xcd,0xcf,0x4c,0xca,0x9e,0x97,0xea,0xc6,0x92,0x29,
+ 0x7f,0x54,0x0a,0x47,0x58,0x27,0xa1,0x63,0x7c,0x17,0x2f,0x57,0xde,0xd1,0xc1,0xc5,
+ 0x38,0xb7,0x68,0x47,0xd2,0x39,0x47,0x6b,0xe1,0x1b,0x34,0x7a,0x14,0xbb,0x6d,0x1e,
+ 0xf3,0x3f,0x56,0x15,0x11,0x19,0x29,0x09,0x4f,0x88,0xdb,0x06,0x26,0xd1,0xd4,0xf3,
+ 0x9a,0xcb,0x9d,0x82,0x53,0xec,0x4b,0xd3,0x93,0xc1,0x59,0x8b,0x24,0x7c,0x15,0xc5,
+ 0x87,0x76,0x8d,0x00,0xc6,0x5d,0xc0,0x26,0x1c,0x84,0x73,0xb6,0xe8,0x26,0x45,0x56,
+ 0x32,0x2d,0xbc,0x16,0x7a,0x83,0x54,0x33,0x4e,0xf2,0xc6,0x66,0x8a,0x46,0x78,0xf0,
+ 0xda,0x66,0xac,0x9a,0x85,0x3b,0x66,0x3e,0xe4,0x3f,0xe2,0x54,0x94,0xc2,0x62,0x5a,
+ 0x9f,0xc0,0x8a,0xb6,0xc9,0x05,0x22,0xaa,0x46,0x1e,0xde,0xa3,0x54,0x42,0x37,0x06,
+ 0x1e,0x7d,0x27,0xe1,0xbb,0x58,0xd4,0xac,0xf0,0x1d,0x0e,0x28,0xaf,0x5a,0x4d,0xd5,
+ 0x7f,0x51,0xce,0x3b,0x7b,0x47,0x21,0x39,0xaf,0x24,0xc9,0xd7,0xde,0x31,0xc1,0x69,
+ 0xc7,0x79,0xaf,0x1c,0x7f,0x3b,0xe8,0x00,0xa9,0xd8,0x21,0x46,0xb7,0xa9,0x1c,0x87,
+ 0xf0,0x24,0x0d,0x3d,0x6f,0x84,0x7a,0xfa,0x32,0x17,0xbf,0xe1,0xc3,0x74,0xee,0x2b,
+ 0xb7,0xc5,0xd7,0x2a,0x0c,0x76,0x27,0x0a,0x6f,0xbc,0x06,0xb7,0xc4,0x17,0xe8,0x2a,
+ 0xee,0x54,0xdd,0x81,0x34,0x92,0x83,0xb4,0x12,0xfc,0x16,0xa9,0x59,0x3a,0x41,0x3d,
+ 0xd2,0x22,0xd7,0xa9,0x53,0x3e,0x56,0x24,0x27,0x17,0x22,0x00,0x2e,0x24,0xdb,0xdb,
+ 0x28,0xf0,0x34,0xc7,0xca,0xe9,0x01,0x3d,0x4a,0xa4,0xc1,0x1b,0x24,0xf3,0xa6,0x88,
+ 0xb6,0x62,0x66,0x16,0xf6,0x02,0x6e,0x99,0x8d,0xc8,0x70,0xb9,0x49,0x5b,0x52,0xc7,
+ 0xb7,0x4a,0xf7,0x42,0x6f,0xff,0xe7,0x4e,0x94,0xde,0xdc,0xbb,0x50,0x0b,0xee,0x73,
+ 0xfb,0x97,0xbc,0x6e,0xc0,0x83,0xfb,0x57,0x2e,0xe2,0xed,0xfc,0xe6,0x9f,0xce,0xb9,
+ 0x4c,0x6e,0x6b,0xc6,0x51,0x46,0x4c,0x00,0x73,0xd1,0xbd,0xfd,0x01,0xcc,0xb3,0xc2,
+ 0x57,0x26,0x40,0x8e,0x5f,0xe5,0x0f,0xb7,0x6c,0x4a,0xf9,0x76,0xd3,0xd3,0x26,0x5b,
+ 0xe2,0x4d,0x43,0xbd,0x2a,0x13,0xdb,0x34,0xa4,0xaa,0x2a,0x63,0xbf,0x52,0xeb,0xc5,
+ 0x48,0xd7,0x08,0x0e,0x6c,0xab,0x15,0xaf,0x19,0xe7,0x9a,0x19,0x91,0x11,0xe3,0x2f,
+ 0x89,0x8f,0x48,0x58,0x3a,0x1f,0x7a,0x48,0xa8,0x63,0xeb,0xcf,0x18,0xe2,0xdd,0xff,
+ 0x03,0x81,0x42,0xa4,0x67,0x76,0xa1,0xd5,0x1d,0xa8,0xc8,0x95,0xac,0xb8,0x9e,0xba,
+ 0x70,0x1c,0xa0,0xea,0x22,0xdc,0xb2,0x07,0x19,0xe9,0xb0,0x80,0x04,0x94,0x30,0xf8,
+ 0x7d,0x16,0x6c,0x93,0x8e,0xc6,0xe3,0xdb,0x0f,0x52,0x8d,0x30,0x4e,0xac,0xf6,0x00,
+ 0x8c,0x99,0x0a,0xaf,0x5f,0xc4,0xc3,0xbb,0x88,0xf7,0x41,0xc0,0xc2,0x08,0x01,0x99,
+ 0x21,0xa7,0xf1,0x04,0x3c,0xdf,0x3b,0x0d,0x7a,0x6a,0x58,0x88,0x01,0xe0,0xd2,0xa4,
+ 0x32,0xda,0xc2,0x51,0x78,0xb0,0xe4,0xf8,0x49,0x6c,0x80,0xec,0x54,0x58,0xbe,0x58,
+ 0x78,0x57,0x19,0xb4,0x11,0xbb,0x08,0xa8,0x68,0x41,0x4c,0x53,0x27,0xd2,0x9a,0xe9,
+ 0x3e,0x17,0x70,0xcd,0x4d,0xdc,0x55,0x57,0xac,0x33,0x34,0x3c,0xa0,0x15,0x17,0x89,
+ 0x66,0xaa,0x1c,0xbf,0xca,0x36,0x41,0xd0,0xfd,0xde,0xaa,0x68,0xa9,0x76,0xea,0xdf,
+ 0xbb,0xc3,0x66,0x40,0xe9,0x82,0x1b,0x0f,0x1c,0x83,0xb0,0x69,0xd0,0xf3,0x03,0x9a,
+ 0x76,0xfd,0x02,0x60,0x00,0x3f,0x5b,0x2b,0x20,0x1c,0x02,0xe9,0x7b,0x0f,0x5d,0x18,
+ 0x63,0x8e,0x8f,0x30,0xc7,0xdf,0xf1,0x05,0xd4,0xa8,0xe8,0xd4,0x9d,0xf5,0xa6,0x6f,
+ 0xa7,0x6a,0x20,0xd3,0xae,0xa9,0x23,0x24,0xa8,0x87,0x93,0xc6,0x4e,0x9a,0xed,0xa8,
+ 0xb7,0xad,0x38,0xde,0xdb,0x1d,0xcf,0x5a,0x78,0x67,0x0a,0x57,0x3b,0x32,0x24,0x9a,
+ 0xa0,0xd6,0xdb,0xbe,0xf5,0x93,0xdf,0x89,0x53,0x5f,0x49,0xe6,0x63,0x7f,0x75,0x9f,
+ 0x75,0xd9,0x24,0xf9,0x0f,0x85,0x93,0xe0,0x67,0xa7,0x37,0x9f,0xaa,0xa3,0xa6,0x89,
+ 0xde,0x07,0x28,0xbb,0x23,0xcd,0x76,0x46,0x9d,0xed,0x77,0xd7,0x77,0x6b,0xd5,0x74,
+ 0x11,0xe1,0xb3,0x33,0x81,0x5f,0x4a,0x08,0x6b,0x5a,0xe3,0xab,0xe4,0xcf,0x03,0xcb,
+ 0x1e,0xe1,0xf1,0x13,0xba,0x57,0x3a,0xa7,0xd3,0xe6,0x62,0xe7,0xfa,0xae,0x9a,0x92,
+ 0x2e,0x56,0x47,0x68,0xb5,0x2a,0xde,0xa6,0x66,0xe9,0xb3,0xa8,0x6f,0xb3,0xaa,0x7a,
+ 0x01,0x5f,0x77,0xd3,0x48,0x21,0xf8,0x04,0xeb,0x13,0x2c,0x7c,0xb7,0x4d,0xd6,0xaf,
+ 0x5c,0x2c,0xc4,0x21,0xf7,0xea,0x4d,0x76,0xeb,0xce,0x3e,0x38,0xc9,0x33,0x9c,0x47,
+ 0x30,0x0d,0x40,0x1b,0xa9,0x73,0x15,0x50,0x66,0x10,0xf0,0xcf,0x95,0x52,0x92,0x31,
+ 0x89,0x7c,0xa1,0x6d,0xfd,0xb5,0x22,0x16,0xd3,0xff,0xe1,0x12,0x97,0x8d,0x93,0xcf,
+ 0xf7,0xc6,0x7e,0xc0,0x93,0xc0,0xfd,0x51,0x51,0x64,0x32,0x6a,0x95,0x53,0x04,0xfe,
+ 0x0f,0x01,0x90,0xfb,0x07,0x6a,0xd9,0x30,0xe6,0x8a,0x48,0x88,0x79,0x32,0x1b,0xa3,
+ 0x23,0x18,0x01,0x73,0xcb,0x4b,0xfd,0x38,0x68,0xe5,0x59,0x50,0xc1,0xb3,0xe3,0x2c,
+ 0x9c,0x37,0x3f,0xd3,0x5d,0x67,0xca,0x9c,0x56,0x7f,0xaa,0x68,0x46,0x56,0xf8,0x94,
+ 0xf4,0x86,0x9b,0xc4,0x76,0x65,0x0a,0xb3,0xbc,0x5f,0x0f,0xf5,0x12,0x92,0x55,0xc9,
+ 0x64,0xe8,0x69,0xc1,0x72,0x88,0x07,0x0b,0x4d,0x72,0xd0,0xd8,0xd0,0x43,0x2a,0x85,
+ 0x52,0xa5,0xc9,0x4a,0x1f,0x7f,0x72,0x50,0xa1,0xe9,0x1f,0xe1,0xf6,0x73,0x14,0xd6,
+ 0x5d,0x9f,0x3e,0x38,0xe8,0x9f,0x31,0xe4,0xd3,0x2f,0xdd,0x75,0xf9,0xcf,0x97,0x31,
+ 0xe1,0x74,0x93,0x16,0x23,0x73,0x89,0xe8,0xac,0x42,0x59,0xe8,0x7a,0x9b,0x64,0xab,
+ 0x85,0x3c,0x80,0x4d,0x36,0x77,0x1c,0x79,0xe4,0xe9,0xa0,0x23,0xd2,0xde,0x69,0x61,
+ 0x1e,0x13,0x3b,0x87,0xf6,0xba,0xea,0xb5,0xce,0x80,0xdb,0xdc,0x04,0x69,0x88,0x68,
+ 0x68,0xf3,0x21,0xf3,0xa6,0xeb,0x1c,0x90,0x23,0x40,0xf0,0x59,0xdb,0xbf,0x74,0xb6,
+ 0xa3,0x43,0xe9,0xd9,0x69,0x51,0x89,0x6c,0xbb,0xae,0x54,0xf7,0x71,0xc4,0x76,0xda,
+ 0x18,0x67,0xdc,0xb7,0x31,0x48,0x3a,0x6a,0xb3,0x9a,0x97,0x59,0xfb,0x79,0x4b,0x46,
+ 0xe0,0x3c,0x05,0xe9,0x5c,0xf1,0xba,0xf7,0xa8,0x64,0x86,0xd5,0x7b,0x46,0x6c,0x3e,
+ 0x66,0xc4,0xa2,0x9c,0x9b,0x77,0x9d,0x52,0xb3,0x72,0x5e,0x36,0xa0,0x8e,0xa0,0x80,
+ 0x39,0x1d,0xa6,0xb4,0x9e,0x18,0x9f,0xe2,0xb0,0xcb,0x5d,0xeb,0xb5,0x65,0x53,0x1c,
+ 0xbb,0x96,0xf3,0x3e,0xda,0x0c,0xac,0xa3,0x23,0xb2,0x1f,0x20,0x96,0x00,0x3f,0x10,
+ 0x25,0xba,0x08,0x34,0xa4,0x35,0xd3,0x6a,0xc5,0x2e,0xd8,0x3f,0x27,0x26,0x31,0xcf,
+ 0x34,0x6d,0x8f,0x60,0xca,0x44,0xaa,0xf8,0xe4,0xaf,0x62,0xfa,0x59,0x27,0xa9,0xf6,
+ 0xfa,0x3b,0x52,0x9d,0xe7,0x7d,0x40,0xa1,0xa7,0x12,0x5b,0xc4,0x4c,0x1f,0x0a,0x4d,
+ 0x1f,0x0e,0xa8,0xd2,0x25,0xb7,0x1d,0x41,0xd3,0xc1,0xd5,0x0b,0x95,0xb6,0x83,0xa0,
+ 0xa6,0xf1,0x16,0x8b,0xd3,0x5d,0x52,0x2e,0x53,0xfd,0x54,0x71,0x42,0x5c,0xf4,0xfe,
+ 0xc1,0x9d,0x81,0x29,0x83,0xdc,0x7d,0xeb,0x3b,0x3b,0x34,0xa5,0xd4,0x57,0x6c,0x66,
+ 0x9e,0x70,0x3f,0xc7,0x2d,0xf6,0x24,0x50,0x00,0x8f,0xaa,0x41,0x45,0xdb,0xcd,0xb8,
+ 0x58,0xcd,0x4c,0x63,0x45,0xd3,0xea,0x90,0x5f,0xf0,0x39,0xb2,0xb9,0xe0,0x07,0x48,
+ 0x2c,0xcc,0x65,0xa8,0xc2,0xe6,0x20,0x28,0xcc,0xe7,0xb8,0xe3,0xd3,0x5b,0xf4,0x4b,
+ 0x94,0x37,0xb3,0x1f,0xdc,0xfc,0xd2,0xad,0xc4,0x74,0x4e,0xa4,0x4a,0x74,0xf1,0x04,
+ 0x6f,0x95,0xed,0xa5,0xa8,0x7d,0xbf,0x0a,0x43,0x90,0xbd,0xb7,0x19,0xcc,0x87,0xc8,
+ 0xd2,0xc7,0x6f,0x71,0xc0,0x60,0xd9,0x1a,0xe6,0x5d,0x1f,0x73,0x3f,0x97,0x86,0x63,
+ 0xf7,0x46,0xcc,0x8d,0x37,0x52,0x22,0x56,0x95,0x7c,0xd0,0xc5,0x6f,0x1b,0xa2,0x40,
+ 0x15,0x8f,0x1a,0x1b,0x48,0x79,0xe0,0x02,0xe9,0x9e,0xcf,0x84,0x3d,0x73,0xdf,0x24,
+ 0xf5,0x7b,0xc1,0x81,0xbd,0x54,0x2c,0x48,0xfe,0xba,0x44,0xec,0x18,0x8b,0xf7,0xb3,
+ 0xcc,0x58,0x93,0xee,0x65,0x2a,0x9b,0x09,0x6a,0xd3,0x27,0x15,0x58,0x81,0x9f,0x0a,
+ 0xaf,0xe9,0x29,0x26,0xf2,0x28,0xf1,0x54,0x58,0xbd,0x37,0x4f,0x2f,0xfb,0xa2,0xb6,
+ 0x9a,0xb2,0x38,0x90,0x8b,0x51,0xbb,0x18,0xb0,0x36,0xd0,0xb4,0xbc,0xfa,0xce,0xfa,
+ 0xdb,0x10,0xc3,0x98,0x99,0x0a,0xb1,0x78,0x16,0x93,0x13,0x87,0xca,0x45,0x4d,0x23,
+ 0x1c,0xf6,0xd3,0x4b,0xfb,0xc4,0x51,0x11,0x33,0x38,0xfd,0x4b,0x42,0x68,0xb7,0x3f,
+ 0x92,0xc4,0x22,0x07,0x6d,0xeb,0x3f,0x20,0xe2,0xeb,0xff,0x68,0x3c,0xfd,0x68,0xe1,
+ 0xfa,0xe4,0x13,0xdf,0xa2,0x6e,0x4d,0xbc,0xba,0x5d,0x8e,0xdc,0x1d,0x79,0xd1,0xe6,
+ 0xd8,0x8a,0xcc,0x9d,0xf3,0xb6,0x92,0xdc,0x4f,0x39,0x3d,0x59,0x6b,0xce,0x5b,0x99,
+ 0xb1,0xe8,0x69,0xa3,0x5d,0x50,0x2b,0xa1,0x5e,0x6d,0x5e,0x39,0xf9,0x95,0xb7,0x52,
+ 0xd0,0xa0,0x06,0x92,0xe8,0x98,0x71,0x6a,0x2f,0x35,0x87,0xb9,0xdc,0xcc,0xd4,0x1e,
+ 0xe7,0x1b,0x17,0x2b,0x91,0x0d,0x04,0x13,0xa4,0x1d,0x48,0xba,0x7d,0xa3,0xf7,0xd8,
+ 0x44,0x17,0xc6,0xde,0x90,0xe5,0x38,0xd4,0x30,0xc0,0xa4,0x7f,0x4a,0xe8,0x46,0xb2,
+ 0x49,0xe3,0x72,0x67,0x3f,0x2c,0xf8,0x0a,0x96,0x22,0x28,0xa9,0xc8,0xf0,0x03,0x2d,
+ 0xe0,0x2e,0xd9,0x50,0x0e,0x2f,0xa1,0x22,0x95,0xb2,0xce,0x87,0x0f,0x68,0xb2,0xc5,
+ 0x76,0x1d,0xbf,0xb6,0x7e,0xcc,0x41,0x55,0x9b,0x57,0xc4,0xee,0xc5,0x06,0xbd,0x0c,
+ 0xa3,0x52,0x7c,0xc9,0xbb,0x62,0x94,0xb0,0xe8,0x67,0xc1,0x53,0x76,0xa0,0x99,0xe9,
+ 0x30,0x83,0xe9,0x7c,0xbf,0xd3,0x91,0x92,0x3d,0x17,0x5c,0x36,0xdd,0x91,0x86,0x0b,
+ 0x7a,0x03,0x20,0x53,0xd8,0xdd,0x47,0x4e,0x8b,0xe8,0x32,0x80,0xcb,0xe4,0xe7,0xfb,
+ 0x2d,0xd6,0x6f,0x23,0x58,0x98,0x67,0x09,0x11,0x9d,0x0a,0x46,0x86,0xe7,0xa8,0xed,
+ 0x76,0x9c,0xc4,0x2d,0x13,0xa7,0x35,0x44,0xa8,0x1b,0x1f,0x55,0xc8,0x46,0x9d,0x88,
+ 0x7a,0x2c,0x76,0x3f,0x3e,0x56,0x0f,0xc6,0xd0,0x0d,0x06,0xc0,0xd7,0xb1,0x23,0x46,
+ 0xf3,0x8a,0x47,0x8b,0x37,0x7e,0x51,0x0b,0x87,0x97,0xa6,0x9c,0x61,0xd4,0x75,0x5d,
+ 0x14,0x4e,0x71,0x3c,0xd9,0x2a,0x7e,0x3c,0x60,0xe5,0xf9,0x87,0x2e,0x87,0x8a,0x51,
+ 0x7d,0xa7,0x1f,0x27,0x44,0x43,0x14,0xd8,0x32,0x94,0x84,0x5e,0x1a,0x26,0x5f,0x93,
+ 0x48,0x70,0x11,0x34,0xde,0x73,0xa9,0xbc,0x0f,0x32,0x7f,0xca,0x22,0x67,0xcf,0x80,
+ 0x78,0x56,0x0a,0x98,0x76,0xac,0xe7,0x75,0x1e,0x2a,0x8f,0x8b,0xf2,0x82,0xf9,0x57,
+ 0x58,0x05,0xac,0x29,0x86,0xe8,0xc8,0x53,0xf8,0x19,0xf3,0x5b,0x4d,0x51,0xd2,0x97,
+ 0x72,0xbe,0x99,0xd4,0xa5,0xf1,0x8d,0x7b,0xfb,0x69,0x77,0x58,0xfe,0x57,0x50,0x95,
+ 0xf6,0x0e,0x9d,0xa6,0xd7,0xd0,0xf8,0x09,0xf4,0x69,0xe3,0x7c,0x67,0xb0,0x1c,0x9e,
+ 0xfd,0x5f,0xa4,0x4d,0x90,0x4f,0xcf,0x50,0xd8,0x12,0xf3,0x85,0x36,0x25,0xbc,0x47,
+ 0xb1,0xba,0x9a,0xa2,0xd1,0x4d,0xc9,0x38,0xa4,0x21,0x1c,0x1d,0xb9,0x96,0xb7,0x9e,
+ 0x98,0x74,0x51,0x2b,0x22,0x25,0x7c,0x12,0x57,0x30,0x2f,0x81,0x1d,0x26,0x02,0x9c,
+ 0x6d,0xa3,0xa2,0x7f,0x21,0x15,0xbf,0x60,0xe2,0x96,0x86,0xb5,0x93,0x76,0x49,0x5e,
+ 0x55,0x92,0x49,0x16,0xd0,0x1b,0x6f,0x2b,0xa2,0xf8,0xdd,0x14,0x92,0x94,0x2e,0x89,
+ 0x65,0xc7,0xe4,0x2e,0x35,0x73,0xab,0x0f,0x5d,0xeb,0xd5,0xf1,0xb7,0x46,0x82,0xaf,
+ 0x69,0xe5,0x11,0xcf,0xb9,0x78,0x1d,0x9d,0xa0,0x61,0xa7,0xf0,0xc1,0x71,0x2a,0xc0,
+ 0xe5,0x27,0x4a,0x62,0xcf,0x09,0xe9,0x13,0xed,0xec,0x80,0x42,0xe1,0xcf,0x18,0x21,
+ 0xae,0x8c,0x4c,0x31,0x32,0xe2,0x4a,0xcd,0xf4,0xf5,0x57,0x80,0x85,0x52,0x1c,0x61,
+ 0xbf,0x9c,0xf0,0xad,0x90,0x86,0x03,0x46,0xe4,0xe5,0xb5,0x71,0x60,0xb8,0xfa,0x15,
+ 0xb5,0x90,0x63,0x0b,0xed,0x56,0x42,0xc5,0xa0,0x61,0x27,0x10,0xc7,0x29,0x17,0x6e,
+ 0x50,0xd5,0xae,0x17,0x6d,0x71,0x36,0xc5,0x54,0xe2,0x91,0x55,0x4f,0xd8,0x18,0x2f,
+ 0x7c,0xfe,0xbd,0xeb,0xec,0xd9,0x70,0x26,0x4a,0xc5,0x78,0x1e,0x04,0x43,0x14,0xb7,
+ 0x62,0x70,0xcd,0x27,0xa9,0xa3,0xf6,0x31,0xbe,0xbb,0x4e,0xe5,0xd1,0xfc,0x03,0xa9,
+ 0x09,0xf2,0x07,0xd8,0x77,0xf7,0x1e,0x35,0x1e,0xe9,0x7b,0xc7,0xd1,0x9f,0xe0,0x1d,
+ 0x79,0xf0,0xc3,0x1c,0x80,0x23,0x7c,0x69,0xff,0x9d,0x3e,0x9a,0xe1,0xf0,0x1b,0xf5,
+ 0x28,0x8d,0x5f,0x6a,0xaf,0x84,0x35,0x57,0x43,0x5c,0x56,0xaa,0x92,0xa7,0xd2,0x8d,
+ 0x3a,0xf6,0x60,0x0a,0xab,0x83,0x9d,0x09,0xf6,0x87,0xfe,0x90,0x71,0x8f,0x3a,0x90,
+ 0x32,0x18,0xa9,0x39,0xf3,0xf7,0x80,0x3c,0x00,0x12,0x02,0x23,0x17,0xcd,0xc8,0xb3,
+ 0x75,0xed,0x5c,0xcb,0x53,0x13,0xc5,0x58,0xa7,0x79,0x48,0x2e,0x21,0x05,0x2b,0xf8,
+ 0x45,0x2a,0xd2,0xdb,0x1d,0xd2,0x19,0x38,0x5f,0xc9,0xd1,0x28,0x84,0x62,0x7a,0x4f,
+ 0xe0,0x6c,0xe5,0x8a,0x7f,0xcc,0xae,0x54,0x7b,0xd9,0x66,0x92,0x56,0xca,0xb7,0xdd,
+ 0x6a,0x21,0xed,0x29,0xb0,0x06,0x65,0x77,0x0d,0x3a,0x64,0x70,0x46,0xb8,0xa8,0xc9,
+ 0x3a,0xe5,0xcf,0x5c,0x50,0x1d,0x17,0x04,0xdb,0xb2,0xc7,0x4a,0x41,0xc0,0x80,0x40,
+ 0xfc,0xc4,0xa1,0x92,0x68,0x94,0xfb,0x92,0xe6,0x14,0x4c,0xc4,0x65,0x71,0x8c,0xf6,
+ 0xf9,0xe3,0x2b,0x5d,0x9c,0x6c,0xa6,0x8d,0x32,0xba,0xe7,0x4b,0xd0,0xe3,0xe6,0x9f,
+ 0x17,0x9c,0x20,0x76,0xc5,0x27,0x7e,0x67,0x33,0x66,0xf8,0xf9,0x41,0x07,0x03,0xe0,
+ 0xc6,0x02,0x84,0xcd,0xf5,0x5b,0x8a,0xab,0x52,0x7a,0x97,0xc0,0xc6,0x6a,0x07,0xec,
+ 0xb6,0x09,0xce,0x74,0x3b,0x6d,0x52,0x6b,0x0d,0x9c,0xda,0x00,0x73,0xbb,0x27,0x3c,
+ 0x42,0x9e,0xf8,0x9d,0x49,0xfb,0x35,0xac,0x1f,0x06,0x7a,0x08,0xa1,0x81,0x3e,0xc1,
+ 0xbf,0xeb,0xf2,0x87,0x81,0xaf,0xca,0x48,0x78,0x55,0x69,0xca,0x57,0x95,0xb4,0x42,
+ 0x18,0x18,0x27,0x45,0x31,0x8c,0x4f,0xf1,0x68,0x69,0x3b,0x14,0xa1,0xf8,0xae,0x08,
+ 0xf9,0x40,0x9a,0x35,0x08,0xcd,0x4f,0x2c,0x35,0x71,0x54,0xe5,0x73,0x79,0x97,0x55,
+ 0x4b,0x3f,0x6c,0x44,0x1a,0x6d,0xc8,0x76,0x80,0x8f,0xea,0xdb,0xc6,0x93,0x4f,0xfb,
+ 0x14,0x62,0x7d,0x10,0x84,0x4e,0xc3,0x15,0x41,0x0a,0x07,0x9f,0x41,0xc0,0xfb,0x9f,
+ 0xc5,0xc1,0x59,0x33,0xb5,0x46,0x46,0x78,0x21,0xa5,0xed,0x47,0xd0,0xca,0x0f,0xc6,
+ 0x62,0x50,0x20,0xd2,0x8c,0xfa,0x9b,0x00,0x8f,0xc3,0xb4,0x40,0x65,0x9d,0x2f,0x07,
+ 0xf0,0xe1,0xd0,0xf3,0x78,0x17,0x3d,0x79,0xbc,0x32,0x93,0x6f,0x41,0x47,0x23,0xa3,
+ 0xbc,0x09,0x38,0x60,0xa0,0x1e,0x21,0xdc,0xea,0x20,0x56,0xdd,0x46,0x03,0xbb,0x80,
+ 0x3b,0x61,0xbc,0x42,0x40,0xe6,0xe4,0xff,0x2d,0x8b,0xb3,0xb4,0x56,0x5f,0x45,0x2a,
+ 0x0c,0x4b,0x05,0x0f,0x9e,0x9d,0xf3,0x59,0x01,0x2d,0xce,0xf3,0x84,0x08,0x4f,0x6a,
+ 0x0f,0x8a,0xe5,0x05,0x9b,0x61,0x73,0x43,0x64,0xf1,0xa2,0x4a,0x21,0x4c,0x15,0x21,
+ 0xd0,0xb7,0x15,0xfa,0x22,0x3f,0x6b,0x4c,0xa2,0x92,0xbc,0x90,0x17,0x9f,0x11,0x4a,
+ 0xa6,0xec,0xd7,0x63,0xc2,0xf6,0xff,0x95,0xc4,0xe7,0x23,0xdd,0x71,0xc0,0xc2,0x84,
+ 0x5f,0x15,0x8a,0xe9,0xba,0x97,0xe1,0x53,0xbd,0xd1,0xf9,0xfc,0x92,0xd7,0xa2,0x13,
+ 0xd4,0x43,0x5c,0x35,0xde,0x30,0x70,0xe4,0x22,0x9e,0xdf,0x06,0xe1,0x48,0x8d,0xdb,
+ 0xbb,0xed,0x15,0x4f,0xcd,0xb6,0x1d,0x94,0x3c,0x3d,0xa2,0xd1,0x6a,0x46,0x8e,0x8f,
+ 0xc2,0x12,0x34,0x96,0x31,0x2d,0x2b,0x18,0xd3,0xd8,0xd9,0xd1,0xe4,0x0a,0x09,0x65,
+ 0x18,0x89,0x22,0xae,0xf7,0xc4,0x11,0x13,0x2d,0xa5,0x22,0xe8,0x26,0x56,0x0b,0x6b,
+ 0x6d,0x71,0x81,0xac,0x2c,0x2d,0xe6,0x6d,0x1e,0x48,0x17,0x2c,0x06,0x68,0x00,0xe0,
+ 0x1e,0xb6,0x9b,0x12,0x0b,0x15,0x75,0xb0,0x7d,0x54,0x76,0x7c,0xe9,0x67,0x24,0xe5,
+ 0x50,0x59,0xdd,0xd3,0x21,0x29,0xb1,0x2b,0x0b,0x5a,0x19,0x70,0x05,0xa1,0x9e,0xe9,
+ 0x06,0x8d,0xd0,0x8c,0x3d,0xbf,0xbc,0xf4,0xdd,0x84,0xa3,0x49,0x39,0xee,0x37,0xa9,
+ 0x9e,0x83,0xa5,0x1f,0xf3,0xcc,0xd1,0xa2,0xaf,0xbf,0x18,0xc7,0xb9,0x3c,0x38,0xd2,
+ 0xba,0x62,0x6f,0x8f,0x05,0x7f,0x68,0x57,0x2b,0xc4,0x61,0x60,0x52,0xf8,0x3d,0xc7,
+ 0x42,0x67,0x53,0x88,0x8a,0x61,0x9c,0x82,0x2c,0x5a,0xff,0x50,0xdc,0x9e,0x55,0xbd,
+ 0xb2,0x15,0x7d,0x72,0x33,0xd7,0xbb,0xb2,0x4b,0xd5,0xbd,0x32,0x92,0x63,0x32,0x0a,
+ 0xab,0x99,0x99,0xe6,0x2e,0x45,0xeb,0x04,0x77,0x48,0x99,0x5e,0xa2,0x86,0xfd,0x50,
+ 0x8e,0x0e,0xa7,0x4a,0x9f,0x97,0x3e,0xbd,0x9d,0xe3,0xd8,0xc6,0x25,0x4b,0xe9,0x02,
+ 0x71,0x94,0x56,0x0d,0xf3,0x2a,0xca,0xb3,0x02,0xc1,0x6e,0x4e,0xf6,0xd4,0xdd,0x77,
+ 0xa0,0x50,0x69,0x09,0x97,0x80,0xf4,0xbe,0xeb,0x62,0x4d,0xda,0x1c,0x4d,0x4a,0x07,
+ 0x90,0x3d,0x5e,0x68,0xe5,0x24,0x85,0x32,0xea,0xdb,0xb0,0xa5,0x1e,0xf4,0x3f,0xde,
+ 0x72,0xe2,0x87,0xcc,0xfc,0x6b,0x6f,0x17,0x2f,0xa8,0x57,0x60,0x25,0x80,0xce,0xab,
+ 0x01,0xff,0xc0,0x5e,0x8f,0x92,0x9e,0xed,0x1b,0x20,0x51,0x8a,0x78,0x16,0x05,0x23,
+ 0x4c,0x46,0xd8,0xce,0x9f,0x33,0x74,0x03,0x9d,0x71,0x82,0x9c,0x89,0x96,0xcc,0xfb,
+ 0xac,0xbf,0xbd,0xa5,0x7e,0x82,0xe8,0xcb,0xdb,0x88,0x67,0xf1,0x1f,0xce,0x23,0x27,
+ 0x41,0x83,0x04,0xec,0x65,0x31,0xd1,0x8e,0x37,0xac,0x26,0xa3,0x2c,0x0c,0x55,0xd2,
+ 0xcf,0x07,0x05,0x25,0xc6,0x5b,0x16,0xa0,0x3b,0xb3,0x87,0x9f,0xa9,0x72,0xcd,0x92,
+ 0x87,0xc7,0x6b,0xbf,0xdc,0x65,0x28,0x36,0xf3,0xf2,0xd4,0x3f,0x98,0x5c,0x41,0xd2,
+ 0x41,0xf6,0xdf,0x72,0xfa,0x3b,0x20,0x6f,0x34,0xba,0xb1,0x23,0x03,0x37,0xbd,0x2c,
+ 0xee,0x93,0xa6,0x4a,0xe1,0xe8,0xfd,0x95,0x67,0x68,0x46,0x46,0xdd,0x74,0xdc,0xf2,
+ 0x3c,0x31,0xf0,0x54,0x4a,0xfa,0xca,0x18,0x73,0x81,0xe7,0x41,0x74,0x3e,0x30,0x28,
+ 0xf5,0xa7,0x88,0x5f,0x42,0x8a,0x26,0x9f,0xc4,0xa0,0xe4,0xe1,0x92,0x9e,0x28,0xa9,
+ 0x14,0x80,0xcd,0x43,0xb5,0x81,0x9d,0xb3,0x63,0xaf,0x91,0x88,0x12,0x6a,0x61,0xdd,
+ 0xcd,0x9e,0x44,0xb1,0x5c,0xf9,0xf2,0x70,0x9d,0x8d,0xa0,0x0d,0x77,0xe8,0xf0,0x9f,
+ 0x61,0xb6,0x83,0x64,0x28,0xe1,0x93,0x92,0x43,0x25,0x06,0x53,0x55,0x07,0xbf,0xf0,
+ 0xdc,0xfd,0xdc,0xd3,0x67,0xd6,0xcc,0x33,0x6f,0x0f,0x63,0x83,0x02,0x80,0xe2,0x99,
+ 0x3a,0xb6,0x0e,0xe4,0xd1,0x7f,0x24,0x9b,0x49,0xd4,0xf0,0xad,0xdc,0x62,0x97,0x25,
+ 0xbc,0x51,0xb1,0xbc,0x87,0xb9,0xa3,0xc5,0x1b,0xba,0x4b,0x7a,0x07,0xf0,0x65,0x99,
+ 0xa6,0x66,0x9e,0x4e,0x5c,0xf0,0xa0,0x35,0xa7,0x2b,0x06,0x39,0x57,0xa3,0x8f,0x8e,
+ 0x82,0x68,0xd4,0x2a,0x3a,0x1b,0x1b,0x34,0xfb,0xcf,0x35,0x1a,0x78,0xb5,0xe9,0x12,
+ 0xaf,0xda,0x77,0x95,0x78,0x01,0xb7,0x27,0x24,0x8a,0xb1,0x1b,0x2a,0x4c,0x98,0x96,
+ 0x6e,0xd5,0xea,0x63,0xca,0xa8,0x58,0xf3,0xad,0xac,0xe7,0xd1,0xbf,0xfe,0x8b,0x5d,
+ 0xf4,0x52,0xdd,0x06,0x52,0x1d,0x91,0x62,0xb0,0x31,0xdf,0x22,0x9e,0x61,0x15,0xcd,
+ 0x1e,0x4b,0x01,0xd3,0xf4,0xfc,0x6c,0xe4,0x6c,0xc4,0xa3,0x6b,0x02,0x70,0x4a,0x03,
+ 0x0c,0xd9,0x6d,0x40,0x8c,0x06,0xc6,0xb4,0xb0,0xe8,0xf7,0x70,0x77,0x3d,0xe5,0xe0,
+ 0x29,0x05,0xd8,0x75,0xc0,0xbf,0x32,0xdd,0x0c,0x6e,0xb9,0x3c,0x84,0xa9,0xc8,0x2f,
+ 0x99,0xb4,0x04,0xae,0xbc,0xac,0x25,0xfe,0x47,0x08,0xe3,0x25,0x19,0x81,0xe8,0x5d,
+ 0x53,0xca,0x68,0x75,0x62,0x6b,0x03,0x4c,0x25,0x6c,0x98,0x3a,0x8e,0x76,0xc5,0x94,
+ 0xc6,0x98,0x47,0x4b,0xc5,0xda,0x86,0x2d,0x80,0x04,0xb9,0xbf,0x82,0xbe,0xb1,0xc5,
+ 0xfc,0x97,0x36,0xff,0x76,0x5e,0xc4,0x5c,0xd1,0x9e,0x23,0x56,0x90,0x5d,0x7c,0x1d,
+ 0x2a,0xd9,0x8f,0x90,0x95,0x1d,0x62,0x0f,0x86,0xc2,0xca,0x9b,0x9f,0xf9,0x08,0xb5,
+ 0xaa,0xbd,0x53,0xbc,0x6c,0x5a,0xcc,0x19,0x14,0x8d,0x31,0xbb,0xb4,0x42,0xfe,0x0a,
+ 0xb9,0x2c,0x62,0x81,0x84,0xa6,0x97,0x28,0x20,0x30,0x79,0x91,0x39,0xbb,0xd5,0xd7,
+ 0x91,0xf8,0x4a,0xdf,0x7e,0xd4,0x1f,0xfa,0x57,0xc3,0x15,0x7d,0xd8,0x99,0x87,0x7c,
+ 0x21,0xac,0xa2,0x41,0x9f,0xc8,0x1c,0x44,0x40,0x4f,0x3f,0xf3,0x32,0x59,0x6a,0xc3,
+ 0x29,0xcc,0x48,0x30,0x94,0x7f,0x5a,0xf5,0x14,0x58,0x48,0x83,0xbd,0x7f,0x7b,0xeb,
+ 0x5a,0x57,0xa9,0x50,0xaf,0x1e,0xdc,0xbc,0xe6,0x13,0x0e,0x2a,0x94,0xf2,0xe6,0xb1,
+ 0x65,0xd9,0x43,0x65,0x47,0x6a,0xa7,0x29,0x41,0xf0,0xab,0xbf,0x24,0xff,0xb4,0x1c,
+ 0x45,0x61,0xa0,0x39,0x76,0x75,0x7b,0xc8,0x6a,0x6e,0xd3,0xe9,0xf9,0xd2,0xa8,0x98,
+ 0x7b,0x19,0x9b,0x30,0x94,0x82,0x7a,0x6c,0xbe,0x36,0xcd,0xaf,0xe9,0xbd,0x67,0x8c,
+ 0x78,0x29,0x31,0xb1,0xe4,0x6c,0xfb,0x89,0xb0,0xd7,0x30,0x02,0xb4,0xe8,0x90,0x34,
+ 0x46,0x38,0xca,0x95,0x87,0xd3,0x37,0x88,0x6c,0xc1,0xbc,0x56,0x10,0xf7,0xae,0x23,
+ 0x41,0x55,0xe2,0x71,0xb2,0x89,0x8f,0x02,0xa7,0x73,0x1c,0x4d,0x04,0x37,0x5c,0x5b,
+ 0xd2,0x91,0xb4,0xb6,0xcb,0x13,0xf4,0xc4,0xc4,0x52,0x5a,0x8f,0xea,0x03,0x35,0x7a,
+ 0x50,0x72,0xf5,0x1b,0x30,0x55,0x0d,0x10,0xeb,0x32,0x8e,0x00,0x08,0xca,0xa6,0x32,
+ 0x83,0xed,0x27,0xa4,0xa4,0x0a,0x78,0x17,0xaf,0x47,0x7c,0xa0,0x7b,0x7d,0xce,0x8b,
+ 0xb9,0x68,0x50,0xc4,0x38,0x1f,0x24,0x18,0x1d,0xc1,0xc6,0x56,0xe3,0x3e,0xb5,0xd7,
+ 0xfb,0x79,0x3b,0x9f,0x02,0x87,0x27,0x34,0x63,0xae,0xd7,0xd0,0x1b,0xb0,0x20,0xa4,
+ 0x02,0xcb,0x2b,0xd9,0x6a,0xac,0xd2,0x79,0xc9,0x1d,0x4e,0x88,0x6e,0x07,0x8b,0xe3,
+ 0xaa,0x4e,0x38,0x2a,0xf4,0x31,0x12,0xee,0x12,0x6e,0x3a,0x4d,0x30,0x19,0xbb,0x32,
+ 0x81,0x47,0x8c,0x3f,0x3e,0x99,0xf5,0x38,0xf7,0x38,0xe9,0xe3,0x36,0x67,0x96,0x1c,
+ 0x82,0x37,0x05,0x19,0xa9,0xc1,0xe6,0xba,0xf4,0x12,0x0f,0xb3,0x8e,0x3d,0x65,0x38,
+ 0xcf,0x95,0x1b,0x4e,0x7a,0x4a,0x5a,0x03,0xc4,0xc6,0x35,0xad,0x6a,0x6a,0x98,0xf7,
+ 0xd9,0x47,0x50,0x02,0xc9,0xf6,0x63,0xbf,0x3d,0x3d,0x87,0x6e,0x43,0x26,0x6f,0x36,
+ 0x8c,0xca,0xc3,0x19,0x09,0xd4,0x2b,0xe5,0x4e,0x82,0xbb,0xed,0x25,0xd5,0x63,0x24,
+ 0xff,0xa1,0xb2,0x01,0x6e,0x77,0xc6,0xa6,0xeb,0x2d,0x6d,0xac,0xfd,0x58,0x2f,0x70,
+ 0x50,0x79,0xa4,0x89,0xed,0xb6,0xed,0x14,0x7d,0xee,0xa7,0x67,0x2f,0xa8,0xc1,0x7d,
+ 0xd6,0x3a,0xfd,0xd2,0x18,0x77,0x7b,0xb5,0xc6,0x91,0xf9,0x94,0x91,0xe5,0xe6,0xfc,
+ 0xc2,0xb5,0x75,0x66,0x2e,0xd4,0xcb,0xc4,0x52,0x9a,0x67,0xc9,0x70,0xb1,0x1f,0xf7,
+ 0xe7,0x6b,0xa9,0xa0,0x18,0xf6,0x1e,0x56,0xa1,0xe6,0x37,0x19,0x59,0x8b,0xab,0xa5,
+ 0x1a,0x07,0xdf,0xc0,0xed,0x41,0xba,0xab,0x67,0x24,0x29,0x25,0xad,0x2d,0xa2,0x84,
+ 0xfb,0x22,0x5d,0xf3,0x6e,0xc1,0x2c,0xd3,0x6e,0x89,0xaa,0x61,0x35,0xc6,0xf2,0x32,
+ 0x36,0xc3,0xff,0xc1,0x09,0x92,0x56,0xfb,0xb3,0x3f,0x12,0x3b,0xb3,0x62,0x4b,0x7c,
+ 0x2a,0xe5,0x00,0xb0,0xc9,0x31,0x3f,0x98,0x5f,0xcf,0x44,0x2c,0x2c,0x38,0xc9,0x0f,
+ 0x15,0xcc,0x5e,0xa0,0x7a,0xa7,0x81,0x7d,0xe8,0x0c,0x93,0xb6,0xd9,0x7e,0xd0,0xd7,
+};
+
+
+/* 317-0018 FD1089A */
+static const UINT8 key_0018[0x2000] =
+{
+ /* data */
+ 0xca,0x7c,0x36,0x46,0x27,0x75,0xf7,0x04,0x8d,0x6f,0xf8,0xd1,0xea,0xb6,0x20,0xc1,
+ 0xb3,0xb2,0x0a,0xe0,0x1b,0xf1,0x5f,0xce,0x20,0x68,0xa8,0x03,0xf4,0x2d,0x74,0x6c,
+ 0x01,0x4e,0x81,0x3c,0x3f,0x1a,0x55,0xe0,0x9f,0x35,0x3f,0xef,0x7c,0x96,0x18,0x5e,
+ 0xc5,0x79,0xd0,0x1e,0x1c,0x99,0xd6,0x35,0x26,0x26,0xf9,0x37,0x76,0xc0,0x9d,0xf8,
+ 0x72,0x51,0x7b,0xd4,0x05,0x39,0x03,0x64,0x32,0x53,0x70,0x4a,0xd5,0xed,0x02,0x1d,
+ 0x56,0x69,0x40,0x63,0x47,0x99,0x86,0x3a,0xe7,0x4a,0x19,0x0c,0xc1,0x6c,0x93,0xb9,
+ 0xf3,0x5b,0x20,0x79,0x16,0x5b,0x45,0x53,0xf5,0x16,0x61,0x49,0x5d,0x53,0x17,0x74,
+ 0x73,0x64,0xdc,0xfd,0x9d,0x86,0x25,0x9d,0x68,0xfb,0xa6,0x2d,0x64,0x47,0xb6,0x63,
+ 0x2e,0x6a,0xd2,0xc4,0x3b,0x73,0xfe,0x9f,0xc0,0x66,0x65,0x54,0xf5,0x8e,0x00,0x71,
+ 0x1d,0x93,0xc3,0x67,0x8c,0xd7,0x6d,0x95,0x7f,0xa6,0x7d,0x82,0x2a,0x21,0xe9,0xd7,
+ 0xa3,0x98,0x8d,0xae,0x1f,0xda,0x80,0xdb,0xaf,0xf7,0xc3,0x6c,0x92,0xd9,0xf8,0xcf,
+ 0x4d,0x71,0x64,0xea,0x4b,0xc9,0x1e,0x41,0xac,0xe3,0x7f,0x46,0x44,0x02,0x02,0x6c,
+ 0xaf,0x7f,0x12,0x53,0x75,0xd6,0x05,0x12,0xa9,0xa5,0xf6,0xdb,0x63,0x22,0xc1,0xaf,
+ 0x84,0x11,0x68,0xc4,0x7d,0xa0,0x99,0x73,0x1b,0x48,0x15,0x88,0x79,0xb8,0xf2,0xca,
+ 0xeb,0x47,0x14,0x06,0x62,0x70,0x62,0x1c,0xa5,0x01,0x49,0x35,0x0a,0x6c,0xd0,0x42,
+ 0xe3,0xcb,0xe5,0x4b,0x97,0xa8,0x2a,0xc9,0xc2,0x3f,0xea,0xb0,0x2e,0x97,0xd6,0xd4,
+ 0x6e,0x47,0x56,0xa8,0x76,0x6b,0x6b,0x2a,0xd9,0xa9,0x86,0x2f,0x96,0xd3,0xb6,0xc9,
+ 0x8d,0xbd,0xa1,0xdf,0x4f,0xbd,0xc8,0xf6,0x05,0x7d,0x96,0x68,0xad,0xb1,0xc2,0xf1,
+ 0x76,0x82,0x09,0x4b,0xcd,0xc3,0x34,0xcf,0x6b,0x56,0xa1,0xed,0x9a,0x90,0x5e,0x01,
+ 0x2e,0xee,0xc2,0xf9,0x74,0xde,0x7f,0x7b,0x9a,0x64,0x64,0x1e,0x25,0xb8,0x04,0x8c,
+ 0xd6,0x2a,0x93,0x79,0x20,0x28,0x76,0x61,0x51,0x49,0xf5,0xa9,0x2b,0xa1,0x79,0xd1,
+ 0xfa,0xb8,0x9b,0x93,0x62,0xe6,0x2c,0x22,0x81,0x52,0xa9,0x6c,0x5d,0x21,0x28,0xab,
+ 0x38,0x60,0x03,0x55,0xdc,0x5e,0x22,0xe1,0xcf,0xa2,0xc9,0x6a,0x48,0x3b,0x4a,0xfd,
+ 0x50,0xe6,0x67,0x67,0x8c,0xdc,0xb5,0xb3,0x0c,0x6e,0xe4,0x42,0x2f,0x6f,0x61,0x86,
+ 0xa3,0x29,0x03,0x06,0xce,0x85,0x6f,0x43,0xcd,0xbc,0x29,0xd1,0x16,0x3a,0xaa,0xb8,
+ 0xb6,0x29,0xfb,0x8f,0x60,0x8e,0xec,0xaf,0xd0,0x76,0xe9,0xc6,0xb8,0x6e,0x43,0x9d,
+ 0xa1,0xf7,0xb6,0xfa,0xc0,0xd7,0xc6,0x52,0x55,0xab,0x84,0x96,0x50,0x40,0x82,0x7e,
+ 0x00,0x62,0x91,0xf1,0x60,0x44,0x16,0xe6,0x3b,0x55,0x32,0x77,0x2a,0x1a,0xaf,0xa6,
+ 0xe4,0xab,0x1a,0xf3,0xce,0xfe,0x28,0x06,0xaa,0x5e,0x6e,0xca,0x29,0xb0,0x0f,0x87,
+ 0x69,0xf6,0xa3,0xf9,0xdb,0x22,0xbd,0x95,0x90,0xb1,0x87,0x4e,0xa2,0xd6,0x80,0x21,
+ 0xd1,0xed,0x00,0x1e,0xdc,0x47,0xb9,0x49,0x3c,0x6f,0xa4,0xef,0xd3,0xe8,0x02,0x47,
+ 0x49,0x96,0xc0,0x3a,0xc7,0x3c,0xdd,0x1a,0x71,0xb5,0xb8,0x24,0xaa,0xb2,0x98,0x0b,
+ 0x87,0x8c,0x8e,0x9a,0x20,0xb4,0x2d,0x0a,0x1e,0xe7,0x3d,0xa0,0x44,0x27,0xf7,0x4f,
+ 0x2f,0xcc,0x59,0xc4,0xd4,0x48,0x8e,0x8c,0xed,0x7c,0x98,0xaa,0xc7,0x69,0x7b,0x39,
+ 0xe3,0x09,0xdc,0x90,0xcd,0xca,0x73,0xc3,0x29,0xfa,0x09,0x1e,0x02,0x68,0xf5,0xe8,
+ 0x27,0x7f,0x82,0x46,0x38,0x49,0x01,0xb3,0xce,0x95,0x37,0xc4,0x93,0x1d,0x2e,0xf7,
+ 0xee,0x49,0xcd,0xb2,0x2f,0x2c,0xd1,0x5e,0x4d,0xce,0xcd,0x28,0x9d,0x15,0x11,0x13,
+ 0xa9,0x10,0xde,0xbc,0x26,0xf9,0x89,0xf2,0xfb,0x5b,0xe7,0xfb,0xe2,0xda,0x17,0xa4,
+ 0x6c,0x1f,0x5c,0xc2,0xfd,0x02,0x8c,0xdc,0xcb,0x72,0x05,0xb3,0xa7,0x3b,0x33,0x29,
+ 0xc6,0x54,0x3f,0x50,0x62,0xc1,0xa2,0x1d,0x3d,0x79,0x24,0x3a,0xec,0xad,0x67,0x72,
+ 0x8f,0x37,0xc0,0x88,0x77,0x99,0x58,0x14,0xf1,0x53,0xfe,0xba,0x44,0x63,0xe3,0xf6,
+ 0x35,0x57,0xea,0x15,0x47,0xe6,0xe5,0x95,0x7c,0xbf,0xe3,0x09,0x8b,0x1f,0xa7,0x61,
+ 0x70,0x62,0x54,0xa6,0xb0,0x20,0x3d,0x37,0xe2,0x94,0x3b,0x24,0xe4,0x23,0x81,0xfd,
+ 0xc5,0x20,0x4f,0x86,0x71,0xbb,0x34,0xb5,0x73,0xc5,0x6a,0xc5,0x2e,0x5d,0x4c,0x67,
+ 0x99,0x10,0x89,0xdb,0x6c,0x7c,0x85,0x6e,0x64,0xab,0x0d,0xfd,0xf7,0x36,0x20,0x43,
+ 0xbb,0x0e,0x97,0x9c,0xeb,0xa0,0x82,0x28,0xbc,0x5b,0xa4,0xbc,0x5f,0x13,0xac,0xf1,
+ 0x65,0x81,0x2a,0x49,0x0f,0xa2,0xf4,0x45,0x42,0xe7,0x42,0xc6,0x9f,0xe6,0xcb,0x21,
+ 0x70,0x29,0x9e,0xf5,0xc6,0xee,0xf4,0x76,0xb9,0xfe,0x19,0xed,0x3c,0xbb,0xad,0x17,
+ 0x57,0x96,0x47,0x03,0x69,0x91,0x82,0x41,0xfa,0x60,0x2c,0xd3,0x36,0xb8,0x29,0xe7,
+ 0x0b,0xf2,0x49,0x51,0x28,0x09,0x85,0x8c,0x67,0x94,0xc8,0xcc,0x77,0xd5,0x8e,0x74,
+ 0xf4,0x79,0x65,0x69,0x49,0xee,0x2f,0x31,0x29,0xc4,0xcd,0xde,0x75,0xc8,0xfd,0xbd,
+ 0x62,0x04,0xec,0xf0,0x59,0x0b,0x37,0xae,0xa5,0x1f,0xaf,0xc6,0x74,0x22,0x69,0xcf,
+ 0x7c,0xf0,0xd1,0x0f,0x50,0xc0,0x77,0xe6,0xc5,0x16,0x74,0xc0,0x6f,0x3a,0xe8,0x63,
+ 0x2e,0xd8,0xea,0x82,0x53,0x7c,0xbd,0x15,0xfa,0x2f,0xbf,0x06,0x0e,0x44,0x90,0x0c,
+ 0xe1,0x34,0xd4,0x5d,0x23,0xe3,0x3d,0xd9,0x0d,0x5f,0xb2,0xd1,0x1f,0x8a,0xc6,0x22,
+ 0x42,0x20,0xb2,0x87,0x62,0x84,0xcb,0x1c,0x05,0xaa,0xf8,0x12,0x88,0xc4,0x17,0x9f,
+ 0xdf,0xc4,0x5f,0x96,0x2f,0x89,0x80,0xb1,0x63,0xe1,0xca,0xe9,0x51,0x1d,0xee,0x41,
+ 0x92,0x3f,0x7e,0xf6,0x92,0xb8,0x6a,0x81,0x33,0xe9,0xf6,0xea,0xc5,0xc8,0x1e,0x67,
+ 0x55,0xe6,0x4e,0xcb,0x03,0x58,0xe7,0x6e,0x44,0xa7,0xe7,0x43,0xa1,0x16,0xd7,0x47,
+ 0x2e,0x5e,0xc6,0x8a,0xf5,0xdc,0xf8,0x78,0x28,0x62,0x9e,0x27,0xfa,0x74,0x0f,0x0b,
+ 0x10,0x1d,0xc5,0x5a,0xe8,0x65,0x51,0xd6,0x4f,0xd3,0x48,0xa2,0xc4,0x85,0x1e,0x1e,
+ 0xbe,0x58,0x1d,0x17,0x3a,0xdc,0xb4,0x9e,0x46,0xfa,0xa7,0x37,0x90,0x23,0xf1,0x4e,
+ 0x61,0x28,0x25,0xd4,0xa6,0x39,0xc2,0x27,0x6a,0x96,0x9e,0x54,0x62,0xee,0xc0,0x03,
+ 0xd2,0x48,0x42,0xb8,0x3a,0x0e,0x1f,0xf9,0x67,0x88,0x27,0xeb,0xe9,0x31,0xd6,0x61,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x2d,0x92,0x4f,0x9e,0x89,0xe8,0x9e,0x1a,0xa6,0xdf,0x08,0x9d,0xd6,0xc1,0x2f,0x92,
+ 0xd7,0x60,0xbd,0x25,0x65,0x80,0x93,0xf9,0x8d,0xda,0xca,0xc7,0x10,0x62,0x38,0x0c,
+ 0x1a,0xdd,0x8c,0x32,0xba,0x64,0xfc,0x57,0xad,0x9c,0x10,0x80,0x6a,0xc1,0xa5,0x1f,
+ 0x45,0xb4,0xb4,0x4d,0xfb,0x55,0xf8,0x78,0x48,0x20,0x0a,0x26,0x24,0xcb,0x88,0x99,
+ 0xc0,0x0c,0x89,0xb8,0xdb,0xa0,0xc3,0x24,0xdc,0xf2,0xfe,0x67,0xae,0x27,0xef,0x5a,
+ 0x04,0x42,0x7b,0x01,0x40,0xa6,0x0a,0x9e,0x3f,0x4f,0x5f,0x36,0x16,0x19,0xc4,0x0c,
+ 0xd7,0xe7,0xcc,0x3e,0x41,0xfc,0xe8,0x34,0xaa,0x4d,0x72,0x82,0xa4,0x5c,0x82,0x57,
+ 0xc9,0x56,0xf9,0x6c,0xf1,0xd2,0xf3,0xdd,0x08,0xdd,0xbf,0x86,0x87,0xc7,0x17,0x99,
+ 0x4e,0x28,0x81,0x03,0xd3,0x30,0x14,0x3b,0x96,0x00,0x42,0x9e,0x58,0xc8,0x6d,0x80,
+ 0x20,0x5a,0xc0,0x0a,0x33,0x3a,0x0f,0x1d,0x98,0x7e,0x9b,0x8c,0xc2,0xe3,0x3e,0x59,
+ 0xac,0xb0,0xfd,0x2b,0xf7,0x9d,0xdb,0x7b,0xcc,0x09,0x81,0x50,0xb9,0xf6,0x10,0x02,
+ 0x2a,0x14,0xfa,0x2a,0xb3,0x78,0x17,0x22,0x3c,0x6d,0x5f,0x19,0xf1,0xfe,0x8e,0xdd,
+ 0x7d,0x56,0xcb,0x6b,0xef,0x31,0xb3,0x8b,0x84,0x7b,0x89,0xee,0x33,0x18,0x8c,0x93,
+ 0x24,0xcf,0x47,0x34,0x51,0x0c,0xbd,0x27,0x8b,0xe8,0xa6,0x6c,0x69,0x33,0x62,0x4b,
+ 0xfe,0x0a,0x99,0xbc,0x90,0x3e,0x61,0xa5,0xf3,0x53,0xf3,0x24,0x60,0xcc,0x27,0xa1,
+ 0x14,0x45,0xce,0xa3,0xa5,0x00,0x7e,0x41,0x59,0x03,0xac,0x88,0x6f,0x0c,0x8e,0xd6,
+ 0x36,0xcc,0x3e,0x93,0x28,0x13,0x2c,0xe4,0x83,0x66,0x04,0x96,0xd5,0x46,0x69,0x69,
+ 0x12,0xf1,0x4d,0xf8,0xe5,0xcd,0x4f,0x2e,0xd5,0xdc,0x88,0x52,0xf9,0x68,0xda,0xfa,
+ 0xdd,0x51,0x94,0x96,0x21,0x4d,0xc8,0x89,0xc4,0x0c,0x13,0x4b,0xd9,0xf9,0xa3,0x17,
+ 0xe6,0xfc,0xd1,0xdb,0x25,0xdf,0x1c,0x85,0x55,0x5d,0x07,0x40,0xf2,0x3e,0xe6,0x38,
+ 0x3b,0x7a,0xe9,0xc9,0x89,0x50,0x07,0xf3,0xae,0xc7,0x33,0x9f,0x60,0x96,0x05,0x25,
+ 0xef,0xb4,0x4b,0xa6,0x35,0x03,0x37,0x9a,0xc3,0x80,0x20,0x0d,0x76,0xbc,0xb6,0x50,
+ 0x7b,0xf5,0xb2,0x2c,0x9b,0x50,0x09,0x77,0x45,0xc5,0xcd,0xb9,0xc6,0xcb,0x79,0x5a,
+ 0x85,0x23,0xf8,0x70,0xa6,0x47,0xed,0x7e,0x29,0x31,0x21,0x1e,0x22,0xee,0x42,0xf3,
+ 0x03,0x0d,0x1c,0x06,0x19,0xb5,0xc8,0x10,0xfc,0xc7,0xc1,0xc7,0xc5,0xd2,0xf1,0xa2,
+ 0x93,0xa8,0xc7,0x95,0x22,0x7d,0x09,0x04,0x77,0xfb,0xab,0x8c,0x18,0x9b,0xc9,0xfa,
+ 0x58,0xb5,0x19,0x94,0xa1,0x24,0x17,0x96,0x97,0x1c,0x65,0x7a,0xdc,0x41,0xfb,0x4d,
+ 0x9a,0x22,0xdb,0xb6,0xb4,0x8f,0x3b,0x42,0x48,0x04,0xce,0xa2,0x31,0x07,0xd1,0x5c,
+ 0x54,0xda,0x8a,0x63,0xee,0x3d,0xb0,0x29,0xbf,0x11,0x1b,0xa9,0x2f,0x74,0x80,0x48,
+ 0x3b,0x91,0xe8,0x06,0xcd,0x2f,0x00,0x99,0xca,0x2c,0x4f,0xe7,0xdd,0x3f,0x8c,0xb5,
+ 0x05,0x4f,0x92,0x9f,0x45,0xe8,0x99,0xee,0x3d,0x04,0x44,0xc0,0xc0,0xf8,0x1a,0x52,
+ 0x0e,0xbc,0x83,0xf8,0x7f,0xc7,0xed,0x1c,0xfb,0xbf,0x62,0xd5,0xcd,0x0c,0x16,0x5a,
+ 0xd9,0x50,0xbe,0x6b,0x62,0x3c,0xfa,0xb4,0xd4,0x7f,0xd5,0x91,0x91,0x16,0x02,0xed,
+ 0xe5,0xf6,0x0c,0x57,0xed,0xeb,0xf1,0xc9,0x30,0x60,0x4b,0x32,0xa4,0x9c,0x2c,0x6d,
+ 0x3b,0xc8,0xcf,0xfb,0x87,0x62,0x8f,0xf9,0x39,0x62,0xc2,0x97,0xc9,0x77,0x3b,0x4c,
+ 0xce,0x6f,0x43,0x52,0xd9,0xe9,0x06,0x78,0x6f,0xa8,0xba,0xb0,0x2f,0x22,0x7a,0xb0,
+ 0x95,0x0b,0x98,0x01,0x61,0xaa,0x6c,0x1e,0x61,0x8c,0x46,0xe1,0xaa,0x94,0x1c,0xaf,
+ 0xdb,0x4c,0x7b,0x1c,0x0a,0xb9,0x5e,0x6f,0x1e,0xb8,0xb7,0xc8,0x4b,0xf3,0xb7,0x7a,
+ 0x76,0x7b,0x8a,0xc2,0x61,0xba,0xc3,0x96,0x57,0xde,0x46,0xef,0x11,0x32,0x82,0x92,
+ 0x7a,0x2c,0xc5,0xfb,0xd9,0x90,0xdc,0x0b,0xcc,0x55,0xba,0x04,0xef,0x75,0x89,0x91,
+ 0x1d,0x2a,0x2e,0x64,0x87,0x3f,0x60,0xc8,0xb1,0xd8,0xbe,0x89,0x63,0x03,0x0a,0x7d,
+ 0x00,0x2e,0x25,0xdb,0xf4,0x2e,0xa3,0xb8,0xfb,0x60,0x20,0xc5,0x30,0x06,0x9c,0x26,
+ 0xa7,0x5b,0xbf,0x62,0x1c,0x6f,0x87,0x0b,0xcb,0x60,0x24,0xe0,0x6e,0x71,0x52,0x2a,
+ 0x0d,0x2a,0x79,0x0f,0x24,0xa4,0xe9,0x51,0x2f,0xc7,0x6c,0xdb,0xc6,0xd0,0x90,0x46,
+ 0xd9,0x33,0x17,0x7e,0xae,0xc3,0xf7,0x57,0xd7,0x63,0x19,0x6f,0x25,0xb0,0x69,0x2e,
+ 0x60,0x54,0xbb,0xa2,0xf3,0xea,0xbc,0xc9,0xd5,0x64,0x06,0xb4,0x88,0xeb,0xc0,0x34,
+ 0x89,0xef,0x99,0xcc,0x9d,0x9f,0xc4,0x75,0x07,0x98,0x8c,0x91,0x2c,0x2b,0x16,0x80,
+ 0xb1,0x4a,0x93,0xaf,0xdf,0x9c,0x74,0x75,0x73,0xd2,0x37,0xce,0x2e,0x3b,0xf1,0xb3,
+ 0xd4,0xa5,0xd7,0xd5,0x81,0xc1,0xe0,0xad,0x47,0xca,0x40,0x40,0xaa,0x9b,0x89,0xf7,
+ 0x60,0x97,0xd4,0x09,0xef,0x05,0x49,0x79,0x1a,0xb0,0xf3,0x22,0xae,0xe4,0x23,0xa6,
+ 0x2a,0x4b,0x40,0xe7,0x94,0x8c,0xad,0x46,0x20,0x1a,0x6a,0xcd,0x3c,0xb7,0x4a,0xd5,
+ 0x44,0x29,0x5d,0xe1,0xb2,0x4d,0xf3,0x7f,0x51,0x65,0xee,0x53,0xca,0xc9,0xb0,0x22,
+ 0x09,0x93,0xf1,0xa4,0x5e,0xd5,0xaf,0xe9,0x48,0xa3,0x82,0x51,0x39,0x91,0x26,0x5d,
+ 0x0b,0xc5,0xde,0xbd,0x80,0x1a,0xcb,0xb5,0x45,0xfc,0xc1,0x69,0x3a,0xba,0x5f,0xb5,
+ 0xfd,0x1c,0x53,0x42,0x2d,0xb6,0xe3,0xf2,0x61,0x1b,0x76,0x83,0x67,0x42,0xee,0xfe,
+ 0xf7,0x37,0x76,0x88,0x75,0x54,0x54,0x4e,0xe6,0x2c,0x2d,0x25,0x82,0x77,0xeb,0xe6,
+ 0xb4,0x1f,0xc4,0xe3,0x0b,0x64,0x13,0xda,0x35,0x39,0x71,0xf9,0x00,0xb0,0x45,0x99,
+ 0xd2,0x62,0xc1,0x41,0x4b,0x7c,0xb1,0x89,0x9e,0x4b,0x2f,0x54,0x36,0xb2,0xf3,0x74,
+ 0x47,0xc1,0x8b,0x14,0x18,0xe5,0xaa,0x3b,0x5d,0x58,0x62,0xf3,0x51,0x5c,0x46,0xf6,
+ 0xa8,0x4f,0x65,0x3f,0x39,0xf8,0x23,0xae,0x2d,0x3c,0x35,0x95,0xb8,0x93,0x41,0x2f,
+ 0x28,0x82,0xae,0xb5,0xc4,0x72,0x5f,0x41,0xa1,0xa6,0x49,0x49,0x15,0x24,0xcb,0x7a,
+ 0x91,0xb8,0xa2,0xa6,0x12,0xef,0x3d,0xbd,0xee,0x98,0xbe,0x38,0xf0,0xc4,0xa8,0xaf,
+ 0x77,0x95,0x8e,0xd9,0xf3,0x3b,0xc4,0x17,0x81,0x6c,0xa7,0xc6,0x08,0xd9,0x0c,0x1a,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x39,0x9d,0xa5,0x68,0x07,0x6e,0xa0,0xae,0xe4,0x84,0x54,0x8e,0x4a,0x13,0x50,0x3c,
+ 0xf7,0x37,0x91,0xda,0x4f,0x76,0xc5,0xe1,0xd1,0xfa,0x03,0xb9,0x00,0xf1,0x8f,0xb3,
+ 0xc2,0x21,0x65,0x15,0xae,0x00,0x7b,0x5c,0x31,0x06,0xc4,0xf6,0x43,0x3f,0x2a,0x66,
+ 0x2a,0x3a,0x76,0xf5,0x0a,0x24,0x8b,0xc3,0xc6,0x44,0x42,0x78,0x9d,0x06,0x84,0x1f,
+ 0x6f,0xdb,0x84,0xdd,0xfe,0xba,0xc8,0xb2,0x2e,0x0b,0x69,0xc6,0x89,0x17,0x11,0xcb,
+ 0xbb,0x74,0x99,0xa7,0xb4,0x71,0x44,0xdf,0xf2,0x9c,0xe1,0xd3,0xb3,0x09,0x17,0x64,
+ 0x04,0x05,0x48,0x1a,0xe1,0x1d,0xd2,0xdd,0x82,0x65,0xea,0x5d,0x5e,0x75,0xbb,0x5b,
+ 0x0f,0x60,0xd3,0xbf,0x8c,0xd3,0x1a,0x37,0xd8,0x15,0x60,0x85,0xb6,0xe5,0xd0,0xf3,
+ 0xb0,0xac,0x8f,0x6f,0x9d,0x66,0xa7,0x21,0xa5,0x71,0x4b,0x37,0x02,0x8b,0x88,0xf8,
+ 0x64,0x9a,0xed,0x6a,0xc0,0x85,0xd3,0x06,0xed,0xd8,0xcf,0xbc,0xaf,0x2b,0x41,0x03,
+ 0x23,0xa1,0x65,0x65,0xf0,0xfa,0x4c,0xd6,0x55,0xe9,0x0a,0xf3,0xd0,0x58,0xa7,0xdf,
+ 0xc9,0x03,0xf0,0x27,0xaa,0x06,0x53,0x75,0x90,0xb4,0x5f,0xf4,0x0b,0x1c,0x83,0x95,
+ 0x0e,0x23,0xae,0x42,0x6a,0x4e,0xef,0x34,0x7e,0x4f,0xac,0x92,0xfe,0x8a,0xd7,0xa0,
+ 0x20,0x01,0xe2,0x37,0x86,0x57,0x2b,0x92,0x8f,0x68,0x04,0x7c,0x3f,0xc8,0xf4,0xdd,
+ 0x6c,0xd6,0xa2,0x05,0xb9,0x30,0xde,0x33,0x78,0x5a,0x20,0x62,0xb8,0x7e,0x1c,0x0e,
+ 0x8a,0xaa,0x1f,0xed,0x30,0xed,0xda,0x91,0xa4,0x36,0x9a,0x72,0xdd,0x3e,0xe4,0xa7,
+ 0x31,0xcd,0x4e,0x3d,0xf5,0xa8,0x83,0x2e,0xd2,0x0d,0x40,0x0c,0x6a,0xaa,0xb0,0x52,
+ 0xc4,0x94,0x32,0x8a,0xbc,0x62,0x47,0xbb,0x53,0xa8,0x16,0xe0,0x4a,0x57,0x46,0x14,
+ 0xb2,0x5a,0x6f,0xdc,0x96,0xc8,0x40,0xa7,0x12,0x29,0xd8,0x67,0x91,0xb9,0x57,0xe7,
+ 0x50,0x79,0x7d,0x7b,0x5d,0x63,0xbf,0x80,0x92,0x63,0xce,0xf8,0x92,0x66,0x6d,0x37,
+ 0x7c,0x97,0x76,0xd6,0x01,0x29,0x7a,0xec,0x2d,0x83,0xcd,0x15,0x64,0x76,0x91,0x3a,
+ 0xb4,0x02,0xbc,0xa1,0xa8,0xce,0x7b,0xe2,0x46,0x83,0xe2,0x46,0x80,0x9d,0xf7,0xc3,
+ 0x1d,0x01,0x6b,0x88,0x8f,0x32,0xaf,0x77,0x14,0x73,0xaa,0x9e,0x4a,0x40,0xdf,0x7e,
+ 0xb2,0x62,0x0b,0x49,0x18,0xf5,0x5c,0x52,0xea,0x76,0xae,0x27,0x4f,0x0f,0xaf,0x20,
+ 0x21,0x33,0x7e,0x6a,0xdb,0x78,0x4b,0xf9,0x80,0x43,0xf1,0x3f,0x9c,0xf0,0x55,0x63,
+ 0x50,0x16,0xe4,0x1e,0xc8,0xbf,0xc6,0x06,0x6a,0x01,0x44,0x1c,0x7b,0xec,0x5f,0xca,
+ 0x36,0x64,0x02,0x38,0xaa,0xc9,0x86,0x4c,0x4d,0xcd,0x5b,0x16,0x51,0x93,0x61,0xe5,
+ 0x98,0x07,0x02,0x27,0x4b,0xb2,0x1f,0x17,0xd3,0x78,0x54,0x16,0x7b,0xa0,0x24,0xa5,
+ 0xae,0x44,0xf5,0x09,0xc5,0x07,0x6c,0x94,0x8d,0xb0,0xe6,0xab,0xcf,0xe9,0xfa,0x9e,
+ 0x12,0x21,0x99,0xa2,0x19,0x11,0x05,0x5e,0xca,0xc5,0xe2,0xfc,0x40,0xa2,0xb1,0x19,
+ 0x65,0xa2,0xe5,0x81,0xa5,0x9f,0x16,0x6a,0xf5,0xd4,0x6c,0x5c,0xdf,0x35,0x7a,0x69,
+ 0xd7,0xc4,0x96,0x1a,0x90,0x2d,0xc8,0x60,0x87,0xab,0x66,0x00,0xde,0x1b,0x94,0xbd,
+ 0xf3,0xa9,0xfd,0x38,0x52,0x81,0x91,0xa5,0x97,0xfd,0xbf,0xcf,0x83,0x13,0x39,0xb3,
+ 0xad,0xdf,0x18,0xe5,0x8f,0xfe,0xe0,0x91,0xa2,0xdc,0xd2,0xe4,0xc2,0x79,0x21,0x1a,
+ 0x41,0xa8,0xc3,0x12,0xf4,0x60,0x52,0xd1,0xb4,0xa1,0x5e,0x2a,0x3f,0x83,0xce,0x6d,
+ 0xcb,0x08,0xba,0x8f,0x45,0xfe,0x68,0x26,0x62,0x47,0x0e,0xe8,0xbe,0x17,0x3f,0x35,
+ 0xcf,0xd3,0xc6,0x74,0x26,0x81,0x05,0x54,0xa8,0x42,0xe2,0x2a,0xdf,0x2c,0x99,0x25,
+ 0x7b,0xc8,0x6a,0x16,0x26,0x2d,0xc8,0xa2,0x71,0x71,0x79,0xe4,0xb4,0x5b,0x03,0xdf,
+ 0x8e,0x10,0xc5,0xe3,0x45,0xae,0x4b,0xac,0xaa,0xc8,0x93,0xcf,0x66,0x99,0x6e,0xfa,
+ 0xf1,0x93,0x68,0xb4,0x3a,0xd0,0x66,0xbe,0x76,0x07,0xe5,0x54,0xea,0xf9,0x9b,0x63,
+ 0x1c,0xa7,0x70,0x7b,0x8b,0x1c,0xd9,0xc6,0x81,0xaf,0xea,0xd3,0x93,0x18,0x68,0x3f,
+ 0x92,0x94,0x7e,0xc1,0x41,0x24,0x7f,0x39,0x82,0x20,0x76,0x45,0x33,0xaa,0x92,0x77,
+ 0x6d,0x7d,0xb2,0x10,0xe8,0xf9,0xd9,0x7a,0x78,0xad,0x2b,0xdc,0x3a,0x67,0x78,0x4c,
+ 0xf9,0xc5,0xad,0x47,0x49,0xee,0xd6,0xb3,0x6a,0xb5,0x89,0x71,0x98,0x35,0x8f,0x98,
+ 0x0c,0x7e,0x95,0x53,0xe2,0x2b,0x5a,0x7c,0x94,0xcb,0xa3,0x5a,0xe2,0x19,0x1e,0x42,
+ 0x9f,0xfb,0x1b,0xd8,0xd5,0x3a,0xbd,0x4d,0x40,0x05,0xe7,0xaf,0xb9,0xe2,0x47,0x7b,
+ 0x15,0x5a,0x4d,0xc5,0xab,0x5f,0x7a,0xb7,0xe3,0x3e,0x87,0xf5,0x06,0x46,0x0f,0x59,
+ 0x28,0x2f,0x2a,0x0b,0xb5,0xe5,0x23,0xac,0x5a,0x12,0x75,0x1b,0x39,0xf8,0x7c,0x63,
+ 0x21,0x44,0x5a,0x91,0x5e,0xbb,0x86,0x7a,0x88,0x8e,0xf2,0x14,0x1d,0xc8,0x5f,0xdc,
+ 0x0c,0xcb,0xd9,0x43,0x52,0x11,0xaf,0x16,0xcb,0x98,0x48,0xf2,0xf0,0x90,0x90,0x9c,
+ 0xd4,0xf3,0x3e,0x03,0xdf,0xb5,0x5d,0x1d,0x67,0x90,0xde,0x2f,0x7a,0x40,0x7f,0xfd,
+ 0x1d,0x11,0x6b,0x27,0x09,0xfc,0x99,0x73,0xd6,0x48,0x74,0x01,0xdc,0xcd,0xe9,0xfd,
+ 0xef,0xe7,0x9f,0x9d,0x63,0x7c,0x47,0x27,0xe9,0xed,0xc6,0x45,0xac,0x01,0xce,0x9c,
+ 0x05,0x9b,0xed,0x86,0xeb,0x17,0xba,0xad,0xa6,0x08,0xdf,0xcb,0xb9,0xbc,0xa0,0xcc,
+ 0x11,0xf7,0xc2,0x2d,0x8d,0xf3,0xe9,0x7f,0x8d,0xb7,0xdc,0x64,0xf9,0xa4,0x8b,0x73,
+ 0x39,0x70,0x02,0xf8,0x75,0xdf,0x53,0xd8,0x25,0xae,0x10,0x36,0x74,0x0d,0x20,0x48,
+ 0xc4,0x70,0x05,0x8f,0xde,0x3b,0x3a,0xc8,0x06,0xbd,0x80,0x75,0xdd,0xf1,0x21,0x6f,
+ 0x54,0x77,0xac,0xa8,0xa8,0xf8,0xc5,0xdd,0x5c,0x96,0x1e,0xc2,0xf1,0xcf,0x4e,0x76,
+ 0xdf,0x89,0x9b,0xe2,0xd5,0xd9,0xd5,0xea,0x5e,0xdf,0x42,0x40,0x85,0xd0,0x13,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x49,0xf6,0xc2,0xe9,0xe4,0x5b,0x38,0x85,0x15,0x08,0xaa,0xe2,0x33,0xb7,0x8c,0x1e,
+ 0x19,0x96,0xe1,0xa3,0x94,0xe6,0xd0,0xa0,0xd7,0x98,0x48,0x7e,0x97,0xbf,0xbd,0x26,
+ 0xa0,0xe1,0xbd,0x84,0xf8,0x8c,0x0d,0x08,0xb8,0xa7,0x75,0x0c,0x54,0xe8,0xe6,0xfd,
+ 0x15,0xc9,0x1e,0xf3,0x78,0x35,0x7e,0x41,0x4f,0x90,0x3e,0x64,0x98,0x32,0x32,0xa6,
+ 0x8b,0x32,0x60,0x26,0x4a,0xb2,0xf1,0xe8,0x23,0x43,0x80,0x8d,0x83,0xb2,0xa0,0xe3,
+ 0x2e,0xcd,0x9e,0x8d,0xc7,0x3d,0x6c,0x2a,0x04,0x0c,0xdb,0x4e,0xde,0x45,0x5a,0xb8,
+ 0x89,0x9c,0x0e,0x96,0x01,0x98,0xf8,0x60,0xa8,0x12,0x01,0x51,0x28,0xe0,0xf7,0x95,
+ 0xf5,0x2c,0x01,0xac,0x22,0x44,0x68,0x30,0x8b,0x96,0xdb,0xa8,0xf5,0xf3,0xc3,0x59,
+ 0x65,0xba,0x6f,0x5b,0x17,0xad,0xa2,0x6e,0x1c,0x87,0xe1,0x98,0x28,0x41,0x58,0x93,
+ 0xe9,0xa4,0xd3,0x19,0xb3,0x64,0xb6,0xb8,0xf9,0x4b,0x3e,0xaf,0x69,0x72,0x1b,0x23,
+ 0xbd,0x81,0x58,0xca,0x81,0x6a,0x81,0xee,0x6b,0x6f,0xe4,0x4d,0x91,0xc1,0x69,0xe5,
+ 0x18,0x68,0x46,0x56,0xa4,0x74,0x84,0x37,0x63,0xd9,0x59,0x65,0x88,0x6c,0x61,0x3b,
+ 0xb7,0xc1,0xf6,0x79,0x90,0xaf,0x8b,0xf0,0xd3,0x36,0x2d,0x6b,0x47,0xdc,0x23,0x34,
+ 0xe2,0xb1,0xec,0x20,0xed,0x40,0xd8,0x2d,0x2d,0x75,0x53,0x84,0x20,0xf6,0x11,0xa0,
+ 0x6f,0x0e,0x71,0xc6,0xd6,0x2e,0xa8,0x40,0x81,0x75,0x6c,0x45,0xee,0x66,0x82,0xd4,
+ 0xf5,0x2d,0x55,0xb2,0xc0,0x7f,0xee,0x5e,0xa2,0xb0,0x90,0x3b,0xc0,0x9b,0x66,0x8a,
+ 0x88,0xca,0x8c,0x68,0xda,0xd7,0x9e,0xd0,0x3e,0x9e,0x52,0xa5,0x11,0xe7,0x1a,0x9c,
+ 0x25,0xce,0xb4,0x2c,0x4a,0x64,0x05,0x6f,0x1b,0xcd,0xa1,0xf2,0xea,0x2d,0x51,0x5f,
+ 0xf3,0xa4,0x40,0xc2,0x16,0x36,0xe2,0x0a,0x7b,0xa9,0xb4,0x84,0x42,0xc8,0xbf,0xb0,
+ 0x21,0x76,0x51,0x79,0x17,0x98,0xd9,0x5c,0x0d,0xe9,0xa2,0x1c,0xb4,0x08,0x4a,0x15,
+ 0xaf,0xf6,0xe8,0x61,0xfb,0x59,0xf9,0xdb,0xcf,0x69,0x33,0x91,0x24,0xc5,0xe7,0x29,
+ 0xed,0x56,0xe7,0xe3,0xdc,0xdc,0x74,0x57,0x62,0xac,0xbe,0xab,0x27,0xab,0x7f,0x5a,
+ 0xa3,0x2a,0xad,0x90,0x21,0x04,0x9a,0x0a,0x17,0x2a,0xc0,0xe0,0x44,0xfa,0x3a,0xb5,
+ 0x8c,0x47,0x81,0xe6,0x0b,0x48,0x32,0x6e,0x45,0x06,0x9c,0x90,0x8f,0x7e,0xea,0xd1,
+ 0x35,0xf4,0xd1,0x2d,0x1f,0x6c,0x5a,0xe7,0x9d,0x70,0xe1,0xe0,0xaf,0x54,0x47,0x7b,
+ 0x94,0x17,0xde,0xa6,0xf5,0x68,0xcc,0x1f,0x93,0x81,0x38,0x9b,0xa7,0x5b,0x75,0x9d,
+ 0xf3,0xa1,0x0d,0x82,0x49,0x10,0x81,0x87,0x9a,0xc7,0x77,0x28,0xe0,0xd2,0x56,0x50,
+ 0x3b,0xa9,0x8b,0xfd,0xc2,0x9f,0x29,0xa7,0x5b,0xbc,0xcd,0x80,0xe7,0x35,0xd8,0x66,
+ 0xef,0xdf,0xbf,0x60,0x81,0xae,0x85,0xc2,0x6d,0x40,0x13,0x50,0x9e,0xec,0x8c,0x73,
+ 0xc9,0x2a,0x00,0x25,0x29,0x69,0x6f,0xfc,0x03,0x79,0xd4,0xb1,0xbf,0xcb,0xd1,0xb4,
+ 0xa2,0xe2,0xdc,0xdf,0x73,0x91,0x14,0x6d,0xda,0x7c,0xf5,0xbb,0x2d,0x7c,0xc7,0x74,
+ 0xe4,0x34,0x31,0xab,0x8b,0x79,0x34,0x94,0xbd,0x2f,0x32,0x30,0x2c,0x85,0x0c,0xa8,
+ 0x7f,0x40,0x35,0x5d,0xa8,0xac,0x20,0xe8,0x90,0xa9,0xfe,0xca,0x8c,0xc6,0x4b,0xb0,
+ 0xb8,0x91,0x70,0x7e,0x18,0x5e,0xd0,0x17,0xef,0x16,0xad,0x28,0xdb,0x79,0xdb,0x7b,
+ 0x12,0x46,0x9f,0xfc,0x47,0x3d,0xe3,0xa5,0x4c,0x26,0x0d,0x03,0xef,0x7c,0x95,0x94,
+ 0xd2,0x73,0x2d,0x64,0x01,0x66,0x84,0xbc,0xfb,0x29,0x18,0x41,0x0c,0x31,0x1b,0xa2,
+ 0x6f,0x53,0xa9,0x64,0xb1,0xd0,0x78,0x8a,0x56,0x58,0xae,0x3b,0xa2,0xfe,0xd8,0x46,
+ 0xb6,0xcc,0xda,0xfc,0xdb,0x96,0x50,0x41,0xed,0xa3,0xa2,0x44,0xe7,0x4c,0x2d,0xd2,
+ 0xe1,0x38,0x7b,0x07,0x09,0x0c,0x50,0xee,0x7c,0xa4,0xd3,0xde,0x95,0xa2,0xf9,0xbf,
+ 0xf2,0x05,0x47,0xac,0x44,0x1d,0xfd,0x3d,0x60,0x60,0xde,0x6f,0x70,0xed,0x47,0xdd,
+ 0x76,0xf5,0x72,0xd9,0x94,0xc7,0xf3,0x84,0x8b,0xcd,0x41,0xaf,0x6c,0xe2,0xeb,0x62,
+ 0xfa,0x8a,0x88,0x45,0x6d,0x0c,0x82,0x68,0x69,0x09,0x4e,0x84,0x76,0x8a,0x9c,0x02,
+ 0x60,0x8b,0xa2,0x6f,0x81,0xfd,0x30,0x2c,0x7c,0xe6,0x24,0x46,0x33,0x7f,0x63,0x09,
+ 0x73,0x74,0xbb,0xf9,0x29,0x14,0x67,0x00,0x77,0xde,0x3a,0x0c,0x82,0xdd,0xdb,0x09,
+ 0xf4,0x6d,0x94,0x19,0x30,0xd6,0x61,0xbe,0x56,0xaa,0x4c,0x87,0x00,0x2b,0x8f,0x12,
+ 0xe0,0x10,0xa2,0xa2,0x98,0xe2,0xc7,0x3a,0x90,0xb2,0x6c,0xf5,0xdc,0x60,0x10,0xc5,
+ 0x6e,0xfd,0x6c,0x59,0x62,0xfb,0x3c,0x91,0x0b,0x96,0x40,0xd2,0xce,0x9d,0x0f,0xdf,
+ 0xa6,0x18,0xad,0x1e,0xbe,0xdc,0xdf,0x6d,0x5a,0x32,0x15,0x78,0xd5,0x79,0xeb,0x4f,
+ 0x11,0xbe,0xc3,0x6d,0x42,0x85,0xd3,0x39,0x09,0xaf,0xa8,0xd4,0x8f,0xab,0x8a,0x7b,
+ 0x8c,0xdd,0xcf,0xa3,0x52,0x9f,0x99,0x2c,0x94,0x0f,0xbc,0xc6,0x23,0xe7,0xdb,0x0e,
+ 0xa8,0xa7,0x4e,0xa9,0x3c,0xe4,0x86,0xc5,0x72,0x22,0x22,0x7e,0x09,0xb3,0xde,0xa3,
+ 0xda,0xc7,0x13,0xfc,0x51,0x0a,0xba,0x52,0xd6,0x75,0x5b,0x51,0x88,0xbd,0x92,0x3b,
+ 0x8e,0xee,0x9a,0x6e,0xdb,0x56,0xf7,0x57,0x0b,0x62,0x0a,0x21,0x4b,0xdc,0xcd,0x7a,
+ 0x84,0x3f,0x0a,0x35,0x69,0x0c,0xa1,0xbe,0x94,0x47,0xe8,0x4b,0x2f,0x4b,0x68,0x04,
+ 0x82,0x8c,0xbd,0x9d,0xfe,0xc6,0xf8,0x83,0x40,0xd5,0x6f,0x98,0x74,0x3b,0x50,0xaa,
+ 0x44,0xba,0xcc,0x9c,0xd0,0x66,0x42,0xbb,0xba,0xd6,0x96,0x43,0x35,0x4c,0x2c,0x5d,
+ 0x84,0x7f,0xc2,0xa4,0x87,0xad,0x5d,0x49,0xa9,0x81,0x6d,0x4b,0x73,0xb2,0xee,0x2f,
+ 0x03,0x7a,0xdc,0x96,0x7a,0x43,0x78,0x5f,0xc0,0x6e,0x8f,0xe3,0xd6,0x9d,0xe3,0x05,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+ /* opcodes */
+ 0x23,0xee,0x4b,0x1e,0x9c,0x63,0xa9,0x74,0x84,0x21,0xd7,0xda,0xd8,0xe7,0x5f,0x04,
+ 0x2d,0xf8,0x36,0x29,0x5e,0xe9,0x66,0x39,0x6b,0x16,0xbd,0x49,0xae,0x3f,0x85,0x64,
+ 0x44,0x88,0xf3,0xe3,0xdb,0xd0,0x3b,0x02,0xac,0x09,0xd1,0x34,0xec,0xf9,0xdb,0xc3,
+ 0x1a,0x82,0x7b,0xe1,0xcd,0x09,0xf9,0x9d,0x40,0x64,0xae,0x79,0x39,0x57,0xe5,0x93,
+ 0xd0,0x62,0xaf,0x3d,0xb3,0x73,0xa2,0xba,0xa6,0xde,0x67,0x47,0xa5,0xa3,0x00,0x48,
+ 0x16,0xdb,0xc2,0xfa,0xbe,0xb3,0x88,0xa2,0xd8,0x7d,0x05,0x65,0x81,0x4a,0xbf,0x31,
+ 0xa2,0x54,0xc2,0x8c,0xf0,0x77,0x07,0x22,0xd3,0x33,0xd6,0xc5,0xcf,0x0b,0x31,0xc9,
+ 0x82,0xc8,0xaf,0x1e,0x90,0x40,0x25,0x3f,0x6f,0x28,0xe2,0xb3,0x7c,0x6d,0x7e,0xe6,
+ 0x97,0x5a,0x7b,0x64,0x25,0xf5,0xcc,0x3f,0x4b,0x42,0xb6,0x99,0xa1,0xff,0xed,0xe9,
+ 0x22,0x10,0xf3,0xd2,0xe2,0x90,0x15,0x22,0xa7,0x90,0xb4,0x50,0x5b,0x85,0x53,0x91,
+ 0x4d,0x77,0x36,0x2f,0x7e,0xc0,0x8f,0xa2,0x60,0xd1,0xf6,0x4c,0xe0,0x91,0x17,0x1e,
+ 0x17,0xb3,0x4b,0x76,0x25,0x73,0xcc,0xba,0x8d,0x17,0x33,0xdd,0x26,0x59,0x76,0x9a,
+ 0x49,0x82,0x6e,0xd8,0xb9,0xd4,0xbc,0x9d,0xff,0xdb,0xe2,0x9e,0x7e,0x1b,0x62,0xe8,
+ 0x60,0x58,0x30,0x19,0xdd,0x51,0x9d,0x02,0x84,0x8e,0xa2,0x8a,0xbe,0x76,0x9d,0xf8,
+ 0x5b,0x89,0x05,0xc1,0xbe,0xe6,0x81,0x33,0x62,0x9b,0x60,0x52,0x86,0xc7,0xad,0x3e,
+ 0xf9,0xa7,0xe9,0x90,0xdf,0x41,0x87,0xb7,0xa5,0xdc,0x10,0xaa,0x51,0xfb,0xad,0xdd,
+ 0x58,0x28,0x0c,0xaa,0x69,0x2c,0xb1,0x42,0x83,0xc5,0x36,0x25,0x90,0x61,0xcd,0x9f,
+ 0xd7,0x6a,0xd1,0x0d,0x3b,0x6b,0xfc,0x2f,0xdf,0x81,0xe7,0x2c,0x12,0x3a,0xd9,0x12,
+ 0xb3,0xd2,0x06,0x1e,0x65,0x2c,0x1d,0x46,0x9e,0xed,0x06,0x4a,0x5b,0x5f,0x94,0x41,
+ 0x52,0xaf,0xc2,0x81,0x69,0xca,0x15,0xd8,0x67,0xea,0x06,0x58,0x5d,0x2e,0xfb,0xb8,
+ 0xe8,0xd4,0x9b,0x9f,0xc4,0x4f,0xe2,0xc3,0x9b,0x20,0xec,0xdc,0xf1,0x6e,0x55,0x4a,
+ 0x2f,0x9d,0x5c,0x97,0xbb,0x55,0x2f,0x25,0x61,0x46,0x76,0x3c,0x32,0x82,0xfe,0x18,
+ 0xc1,0xe5,0x40,0x72,0xa5,0x14,0x78,0x52,0x56,0xaf,0xff,0xe4,0x8e,0x85,0xe5,0x5f,
+ 0x20,0x5e,0x7e,0x7d,0x3e,0x72,0x53,0xd4,0xb6,0x18,0x3e,0x1e,0xbe,0x94,0x2b,0x57,
+ 0x20,0x05,0x24,0xbb,0x5d,0x86,0xc4,0xb4,0x74,0x17,0xb6,0x74,0x71,0xa3,0x64,0x40,
+ 0x35,0xcd,0x20,0xa2,0xfb,0x0f,0xba,0x20,0x0c,0x15,0x7e,0x84,0xba,0x29,0xe9,0xca,
+ 0x38,0x90,0x88,0xb6,0x8c,0xe4,0x1a,0x0f,0x07,0x0c,0xc5,0x30,0xf3,0x0a,0x31,0xfc,
+ 0x0d,0xce,0x4c,0xbf,0x28,0x0e,0x91,0xb5,0x7d,0x2a,0x51,0x23,0x71,0x67,0x0a,0x02,
+ 0x42,0x12,0x8e,0xbf,0x7b,0x9c,0xa6,0x5a,0x78,0x94,0xc7,0x03,0xda,0xfa,0x34,0x27,
+ 0xaa,0x8b,0x39,0xbd,0xac,0x86,0xd9,0x9a,0x8c,0xc0,0xa4,0xc4,0x18,0x24,0x32,0x80,
+ 0x35,0xf0,0xf7,0xa9,0x2d,0xfe,0x08,0x69,0xba,0x09,0xab,0x8e,0x30,0x77,0x51,0x73,
+ 0x17,0x4f,0x13,0xb2,0x63,0x53,0xe6,0x0b,0x50,0x8e,0x21,0x16,0x63,0xa9,0x44,0xa9,
+ 0x68,0xc3,0x7d,0x74,0xaa,0xe4,0x40,0x32,0xb7,0x93,0x0f,0x8f,0x19,0xa6,0x73,0x9a,
+ 0x18,0x7a,0xc0,0x79,0x22,0xad,0xfa,0xdc,0x55,0x90,0x7b,0x90,0x9b,0x3b,0x47,0xd6,
+ 0x70,0x31,0x2b,0x9c,0x9b,0xc1,0xeb,0x04,0xd5,0xeb,0x17,0xbe,0x53,0x09,0x73,0xe3,
+ 0xe8,0x4e,0x5f,0x53,0x02,0x7b,0x30,0xaa,0x3e,0xad,0xcc,0x9a,0x42,0xb3,0x44,0x1a,
+ 0x73,0x80,0xb2,0x52,0x9b,0xc9,0x6c,0xf2,0x46,0xe5,0xd2,0xa9,0x2c,0x0e,0x51,0x73,
+ 0x85,0x7c,0x74,0x1d,0x22,0x21,0x83,0xf7,0x9f,0xb7,0x01,0x89,0x98,0xa0,0x32,0xfd,
+ 0x0e,0x41,0xf1,0xe3,0xa1,0x4d,0xd7,0x81,0x05,0x8d,0x66,0x97,0xd8,0x78,0xec,0x0c,
+ 0x5b,0x71,0xf1,0xe1,0x5a,0x19,0x84,0x60,0x63,0x87,0x3a,0xc3,0x00,0x17,0x02,0x67,
+ 0xd5,0x8f,0x3f,0x26,0x42,0x28,0x99,0xdc,0x32,0x7a,0xa0,0xb2,0x14,0x38,0x36,0x4c,
+ 0x6c,0x09,0x60,0xa7,0xb9,0x03,0xf2,0xf7,0xb4,0x61,0x9f,0x46,0x07,0xab,0x35,0xe8,
+ 0xbc,0xcb,0x58,0xc3,0x47,0xed,0x5c,0x7f,0xec,0x66,0x05,0x6d,0x57,0x04,0x83,0xa1,
+ 0xb4,0xfe,0xf9,0x9b,0x6e,0x69,0x52,0x2c,0x3e,0x81,0xe8,0xa6,0x20,0xff,0x5f,0xe0,
+ 0x16,0xfc,0x87,0x4c,0x2b,0x09,0xde,0x9c,0xda,0xd0,0x76,0x1f,0xf1,0x11,0xb5,0xae,
+ 0xc3,0x5a,0x4b,0xfa,0xbc,0x15,0xdd,0xa2,0x53,0x57,0x29,0x7b,0xcc,0x81,0x81,0x5f,
+ 0xee,0x22,0xa4,0x7e,0xd9,0xd3,0x97,0x8a,0x18,0xda,0x28,0xaa,0xf0,0xc1,0x19,0x07,
+ 0x56,0xb9,0xba,0x8b,0x50,0x8f,0xb0,0x83,0xde,0x9e,0xb0,0x03,0x32,0x6e,0xdd,0xb5,
+ 0x1e,0x06,0x71,0x42,0xa5,0xca,0x53,0xab,0x2d,0x13,0x90,0x43,0x13,0x66,0x36,0xea,
+ 0xbf,0xc5,0x0b,0xec,0x3e,0x26,0x64,0x55,0x1e,0xa5,0xca,0x4f,0xb5,0x0d,0x3d,0x8b,
+ 0xd1,0x82,0xd3,0x85,0x1a,0x23,0xbb,0xbb,0xb2,0x17,0x1c,0x30,0x62,0x71,0xd4,0x73,
+ 0x30,0x93,0xe2,0xb7,0x1c,0x9a,0x01,0xf3,0x99,0x20,0x85,0xe9,0x17,0x68,0x07,0xc0,
+ 0xba,0x3b,0x61,0xcf,0x8a,0x3f,0xfa,0x1d,0xf2,0x5a,0x56,0xda,0xfe,0x6f,0x88,0xdf,
+ 0x33,0x30,0x56,0x61,0x85,0xdb,0xdf,0xb3,0x81,0x1b,0x1f,0x57,0xb3,0x0b,0x67,0x3e,
+ 0xdb,0x4a,0x45,0xed,0x96,0x3a,0xf5,0x9b,0xa5,0x73,0xd5,0xae,0x48,0xc9,0x1b,0x60,
+ 0xaf,0x9c,0xd1,0xe8,0x8e,0xb5,0xda,0x97,0xe1,0x96,0x5f,0x96,0x22,0x3e,0xa8,0x94,
+ 0xf1,0x1b,0x77,0x04,0x88,0xe2,0x54,0x1a,0x28,0x0f,0xbd,0x34,0xb8,0x0e,0xe0,0xcd,
+ 0x91,0xff,0xd6,0x1f,0x16,0x4f,0x56,0xd8,0xb4,0x36,0xd6,0xdd,0x34,0x61,0x75,0xaa,
+ 0x59,0x64,0x44,0x97,0x12,0x8e,0x24,0x5b,0xca,0x7b,0xd6,0x76,0x8f,0x4f,0x86,0x24,
+ 0x33,0xcb,0xf7,0xd4,0xcb,0x01,0xe1,0x1b,0x0b,0x88,0xbd,0xda,0xab,0x94,0x90,0xe7,
+ 0xf9,0x45,0xe6,0x8b,0xbc,0x73,0x3e,0x0b,0x78,0x04,0x5f,0xd8,0x88,0x78,0xfa,0x48,
+ 0xf8,0xb9,0xb6,0x03,0x44,0x1a,0x01,0xa9,0x8b,0xd5,0xd5,0xb5,0x5f,0x83,0xfb,0xa8,
+ 0xd1,0x44,0x45,0xce,0x11,0xfd,0x19,0x7d,0x53,0xa9,0x14,0x31,0x39,0xf5,0x40,0xa1,
+ 0x94,0x72,0xb7,0xcc,0x60,0xdb,0xa8,0x3a,0xba,0xaa,0x8e,0xc2,0x3b,0xe4,0x4a,0x51,
+ 0x70,0x0b,0x6c,0x25,0xe5,0x39,0x20,0x68,0xbe,0x18,0x97,0x60,0x6c,0xc4,0x4d,0xa7,
+ 0x19,0x6e,0x21,0x1b,0x57,0x1a,0xe8,0x19,0xed,0x63,0x88,0x31,0x62,0x1a,0x81,0xbd,
+ 0x58,0xa9,0xf4,0xfa,0xea,0x07,0xb9,0xc9,0xbf,0x6b,0x9c,0x0f,0x8a,0xbb,0x55,0x08,
+ 0xea,0x24,0x37,0x1c,0xbd,0x1b,0x07,0xea,0x14,0xda,0x9e,0x41,0xe0,0xb4,0xc6,0x88,
+ 0x0b,0xa4,0x2c,0xa8,0x54,0x37,0x5c,0x52,0xa8,0xce,0x84,0xe3,0xe4,0xa0,0xd6,0x69,
+ 0xaa,0xe4,0x0e,0xfc,0xe6,0x7f,0x76,0xbc,0x31,0x9d,0x8c,0x82,0x87,0xb2,0x60,0x1c,
+ 0x56,0x86,0xc0,0x9a,0x3d,0xc4,0xec,0xbf,0x47,0xed,0x17,0x69,0xee,0x92,0xd0,0xcb,
+ 0x3a,0xa2,0xb7,0x38,0xb3,0x6e,0x23,0x51,0xcf,0x6a,0x7e,0x46,0x5f,0xa0,0xce,0x9a,
+ 0x76,0x00,0x2c,0x87,0x67,0xf3,0x07,0xc3,0x43,0x0d,0x20,0x76,0x27,0x39,0x6a,0x59,
+ 0xf7,0x24,0xdf,0x73,0x27,0x85,0x1c,0x57,0x99,0x54,0x30,0x83,0xe5,0x16,0x8d,0xdf,
+ 0xbb,0xc4,0x8b,0xdb,0x47,0x1b,0x09,0xe5,0xb4,0x97,0xfe,0x51,0x8a,0xaa,0x3d,0x01,
+ 0x08,0x94,0xbc,0x1c,0x4b,0x42,0x13,0xfb,0xae,0x5f,0x45,0x27,0x0d,0x39,0x5e,0x04,
+ 0xb2,0x0e,0x51,0x50,0x52,0x0c,0xa4,0x85,0x38,0xae,0xa7,0x40,0x2c,0x63,0x62,0x0e,
+ 0xa6,0xbe,0x48,0x57,0x54,0x0d,0x5c,0x8a,0x24,0xec,0x90,0x96,0x4c,0x5c,0x7d,0xb8,
+ 0xfc,0x06,0xde,0x6b,0x2d,0x5f,0xbf,0x8f,0xd3,0x66,0xbd,0x27,0x59,0x41,0x4a,0x22,
+ 0x07,0xca,0x57,0x3e,0xed,0xe4,0x5d,0x25,0xcf,0x10,0xad,0xd1,0x5a,0x9e,0x03,0xa2,
+ 0x9e,0x2f,0x1e,0x25,0x85,0x6d,0x9a,0xae,0xea,0x1c,0x91,0x41,0x77,0xbc,0x2b,0x5b,
+ 0x82,0x5f,0x05,0x18,0xf3,0x20,0xcb,0x82,0x17,0x08,0x6f,0x56,0x9d,0xc1,0x83,0x67,
+ 0x31,0xfe,0x04,0x06,0xc9,0x93,0xa9,0x45,0x83,0xda,0x73,0x77,0x40,0xf7,0x71,0x6b,
+ 0x33,0xec,0xf8,0x05,0xd3,0x25,0x42,0x16,0x98,0x53,0x7d,0x32,0x36,0xc8,0xc1,0x1f,
+ 0x59,0x77,0x69,0x0f,0x03,0x63,0x37,0x55,0xa3,0x7e,0xd0,0x9b,0x6e,0x2b,0xc8,0xae,
+ 0x7a,0x0c,0xfc,0xe5,0x32,0x0e,0x7b,0xf3,0x48,0xee,0x2b,0x95,0x70,0x0d,0xa8,0xd0,
+ 0x9d,0xd0,0xa1,0xb2,0x1e,0x9a,0x82,0x97,0x0a,0xc0,0xc5,0x9d,0x9c,0x6d,0x32,0x4f,
+ 0x5d,0x86,0xc1,0x52,0x13,0x67,0x8f,0xf2,0x60,0xb8,0xbb,0x1a,0x5e,0xaf,0x2d,0x73,
+ 0xb9,0xbb,0x0d,0x15,0x98,0xb6,0x7e,0x41,0xd0,0x94,0x66,0x51,0x84,0xfc,0xb0,0x12,
+ 0xec,0x51,0xf8,0x5b,0x5d,0xbb,0x1d,0x0a,0xea,0x90,0xfa,0xa1,0x74,0xdd,0x10,0x5f,
+ 0xf7,0x2b,0x90,0x62,0xc9,0x89,0x28,0x87,0xce,0x5f,0x03,0x5f,0x77,0xcc,0xeb,0x7a,
+ 0x9b,0x7c,0x44,0xf0,0x83,0x25,0x92,0x08,0xab,0x96,0x3c,0x97,0x4e,0x7d,0x21,0xec,
+ 0x0f,0x16,0x0c,0x79,0xa6,0x6d,0x8b,0x5c,0x34,0x2a,0x29,0x0e,0xb5,0x2e,0x3b,0x41,
+ 0x45,0x28,0xb5,0xbb,0x2b,0x30,0x20,0x23,0x22,0xc8,0x1d,0x26,0x3c,0x14,0xb6,0xfe,
+ 0xee,0x79,0xfe,0xa1,0x94,0x5e,0x92,0xf7,0xb8,0x7b,0x0d,0x0c,0xeb,0x44,0xfa,0x54,
+ 0x46,0x8b,0xbc,0x00,0xac,0x41,0x06,0x4c,0x1e,0xdd,0x51,0x89,0x55,0x5f,0x89,0xf4,
+ 0xaf,0x9e,0x07,0x61,0x5d,0x2a,0x11,0xde,0xb0,0xd5,0x1e,0xff,0x33,0x5b,0x94,0x94,
+ 0x45,0x62,0x82,0xa4,0x6d,0x72,0x1c,0x49,0x24,0x86,0x41,0x0e,0x82,0xf7,0x13,0x17,
+ 0x68,0xc5,0x2a,0x7a,0x69,0xa9,0xb1,0x78,0x0c,0x20,0xfc,0x4b,0x07,0xc0,0x5f,0x9e,
+ 0xc7,0x97,0xe8,0x9a,0x14,0xf1,0xff,0x01,0xcd,0x73,0x81,0xaf,0xad,0x5c,0x43,0x50,
+ 0x6f,0xe1,0x85,0x30,0x5b,0x0b,0x39,0x74,0x21,0xcb,0xa3,0xc5,0xea,0x26,0xed,0x77,
+ 0x9b,0x91,0x56,0xb9,0x49,0x13,0x21,0x30,0x98,0x5c,0x86,0x73,0x1d,0x43,0x80,0xe6,
+ 0x07,0xbc,0xa7,0x7c,0x8b,0xa6,0xc2,0x43,0xc1,0x4e,0xf9,0x57,0x6b,0x76,0x67,0x07,
+ 0x53,0xad,0x1b,0x9a,0x97,0x67,0x51,0xaf,0x85,0xd3,0x69,0xe4,0x45,0x80,0x28,0x0a,
+ 0x87,0x21,0xa6,0xb5,0x56,0x71,0x82,0xde,0xc5,0xcb,0xd7,0xfd,0x7a,0xdb,0xd1,0xb1,
+ 0x31,0x22,0x69,0x5f,0xfd,0x2d,0xd8,0x36,0xa4,0x02,0x21,0x1a,0xe6,0x1c,0xeb,0xee,
+ 0xeb,0x69,0xc8,0xa2,0x6f,0x87,0xd2,0xa3,0x7f,0x39,0x5c,0xd2,0x1c,0x05,0xf8,0xe6,
+ 0x3b,0x4e,0xed,0x72,0xf0,0x2f,0x9e,0x0c,0xac,0x04,0xd7,0xcc,0x55,0x7f,0x85,0xba,
+ 0x5b,0xe6,0x39,0x25,0xb3,0x78,0x97,0x9d,0xab,0x6b,0xcd,0x07,0xfd,0xc3,0x55,0x00,
+ 0x99,0x24,0x28,0x33,0x7e,0xbb,0x65,0x88,0x8e,0xcf,0x85,0x17,0x21,0xc2,0x03,0x41,
+ 0xf3,0xb7,0xe0,0x51,0xf9,0xf4,0x88,0x51,0x54,0x14,0x28,0x22,0xe5,0xa9,0x71,0xf0,
+ 0x0d,0x83,0x9e,0x22,0x05,0x5f,0x02,0x67,0xc5,0xd5,0xa8,0xe5,0xac,0x66,0x2b,0x04,
+ 0xa3,0xdf,0xe8,0x61,0xa3,0x9b,0x73,0x17,0x81,0xd8,0x21,0x8c,0x8f,0x23,0x68,0xb1,
+ 0x33,0x64,0xed,0xfa,0x17,0xaf,0x18,0xc1,0xc4,0x3d,0xe9,0x37,0xff,0xc3,0xa9,0x6e,
+ 0xf9,0x34,0xd0,0xaf,0xc5,0x69,0x0b,0x7d,0x00,0x5f,0xd8,0xc6,0xe3,0x0c,0x6f,0xb6,
+ 0xf7,0xb8,0x2b,0x72,0x47,0xd5,0x93,0xe1,0xd9,0x0c,0xd0,0x2d,0x80,0x1d,0x21,0x65,
+ 0x78,0x56,0x1d,0x21,0xa7,0xb0,0x8d,0xd8,0x3a,0xfd,0x0e,0xaf,0xaa,0xcb,0x1c,0xbd,
+ 0xe7,0x24,0x14,0x41,0xd4,0x82,0x48,0x4c,0x88,0x8b,0xf1,0x55,0x52,0x18,0x30,0x24,
+ 0x6d,0x4b,0x29,0x97,0x53,0xe6,0x14,0x60,0xfe,0x12,0x95,0x04,0x2a,0x64,0x2e,0x88,
+ 0x09,0x9d,0x25,0x30,0xe9,0xea,0x21,0x97,0x82,0x3a,0x3f,0x68,0xd9,0x2c,0x44,0x3d,
+ 0x63,0xe4,0x73,0x64,0x10,0x2f,0xf9,0x26,0x1d,0x07,0xfa,0xdb,0xd4,0xa2,0x0c,0x5c,
+ 0x24,0x33,0x13,0x25,0x0b,0x34,0x9c,0x13,0x93,0x5c,0x6d,0x42,0x45,0x27,0xe0,0xed,
+ 0xee,0x99,0x27,0x61,0x4e,0x73,0x61,0x2b,0x0f,0xf5,0x5b,0x57,0x3f,0xb4,0x9e,0x14,
+ 0xaa,0x8f,0x48,0x63,0x19,0x7f,0x47,0x0b,0xf2,0xe3,0xd3,0x7b,0xc1,0xc4,0x14,0x83,
+ 0x77,0x97,0x84,0xd2,0x28,0x72,0xec,0x1d,0x21,0x52,0xb6,0x8f,0xb8,0x35,0xec,0xa1,
+ 0x27,0x1d,0x09,0x20,0x77,0x4c,0x3e,0xde,0xc1,0x23,0xa8,0x94,0xce,0x00,0xbc,0x32,
+ 0xea,0x71,0x9a,0xd0,0x38,0x5c,0xe5,0x14,0x46,0x72,0x82,0x03,0x01,0xcf,0x99,0x9a,
+ 0x1e,0xd1,0xe7,0xb3,0x81,0x80,0x45,0x02,0x83,0x61,0x4a,0x3f,0xc5,0x94,0x5d,0x0f,
+ 0xe5,0xcc,0x6e,0x72,0xd5,0x57,0x63,0x20,0x73,0xc9,0x4e,0x5d,0xba,0x49,0xad,0xdf,
+ 0x76,0x22,0x1d,0x9a,0x0d,0xe5,0x77,0x89,0x63,0x1a,0x71,0x22,0x0e,0x5b,0x5e,0x06,
+ 0x47,0x81,0xa8,0x19,0x3d,0x16,0x4d,0x93,0xda,0x1f,0x4d,0xdc,0x31,0xa3,0xd2,0xf6,
+ 0xb5,0x54,0x64,0xc2,0x1a,0x2f,0x18,0x28,0xea,0x4a,0x44,0x6e,0x7c,0x19,0xe9,0xea,
+ 0xce,0x79,0x01,0x02,0xc7,0xbc,0xb6,0xc7,0x49,0xf0,0x2a,0xd7,0xa4,0xd8,0x58,0xc1,
+ 0xc7,0xce,0x21,0xc3,0x6f,0x9e,0xc3,0x7f,0x25,0xb6,0xbd,0xea,0xac,0xd5,0xcb,0xd9,
+ 0xae,0x17,0xbf,0xc6,0x24,0xc1,0x7e,0xc8,0xb1,0x10,0x82,0xfb,0x51,0xcc,0xf2,0x34,
+ 0x82,0x39,0x8d,0x44,0xbc,0xd2,0x36,0x8d,0xdf,0x9a,0x7b,0xc4,0xf2,0x91,0x09,0xb3,
+ 0xaa,0x1e,0x00,0xcb,0x21,0x2d,0x25,0xae,0xd8,0xc8,0xc5,0x47,0xce,0xfe,0x77,0xf8,
+ 0xc8,0xcf,0xa0,0x72,0x57,0xab,0xfb,0xe9,0x29,0x99,0x3c,0x6e,0x29,0x0b,0x25,0xca,
+ 0x58,0x5a,0x0c,0x58,0x74,0xf1,0xac,0x19,0x4d,0xc9,0xc6,0x55,0xb1,0x4c,0x77,0x56,
+ 0x1f,0x46,0x88,0x8b,0xe5,0x68,0x0f,0x9a,0x67,0x82,0xba,0xd8,0x50,0xfd,0x17,0x3c,
+ 0xe7,0x3f,0x51,0x6b,0x54,0x64,0xab,0x1f,0x60,0x04,0x55,0x0a,0x05,0x19,0xfb,0x14,
+ 0x8f,0xc0,0x54,0x0c,0xc7,0xa2,0x53,0x98,0x4a,0x7c,0xad,0xc6,0x21,0x4b,0xc9,0x86,
+ 0x13,0x41,0x1f,0xb5,0xe8,0x48,0xf3,0x06,0x2f,0x45,0x96,0x70,0x8f,0x3d,0xfd,0x6f,
+ 0x29,0x61,0x3b,0x56,0xa2,0xcc,0x02,0xfc,0x15,0x49,0x9d,0xa6,0xfa,0x6c,0xcc,0xdf,
+ 0x22,0xe6,0x57,0x83,0x7e,0x87,0xf3,0x67,0x0b,0xfd,0xa4,0xb5,0x26,0x75,0x95,0xd0,
+ 0xc5,0x4c,0xd6,0x96,0x46,0x86,0x9f,0x79,0xd4,0xc6,0x9c,0x1c,0xb7,0x1d,0xa7,0xd2,
+ 0x55,0x40,0x0b,0xbb,0x9f,0x5c,0x69,0x32,0x87,0x27,0x61,0x9a,0x8a,0x26,0x81,0x3a,
+ 0x02,0xbc,0x59,0xe2,0x2f,0xf9,0x0d,0x6b,0x79,0x2d,0x11,0x90,0x2e,0xda,0xb5,0x2b,
+ 0xe9,0x8d,0x90,0xbf,0xd8,0x20,0x68,0xd7,0x9e,0xd0,0xc3,0x39,0x74,0x81,0xb8,0xb3,
+ 0x81,0x25,0x14,0x8f,0x4c,0xf5,0x14,0x9e,0x00,0x0e,0x11,0x02,0xee,0x2d,0xfd,0x42,
+ 0xbd,0x2f,0x2f,0x4c,0x4e,0x88,0x24,0x70,0x63,0x1f,0x61,0xe0,0xd6,0xd7,0x49,0x39,
+ 0x5d,0x95,0x7b,0x6e,0xce,0xed,0x23,0xcd,0x6d,0x53,0x97,0xbf,0x45,0xe2,0x0e,0x5e,
+ 0x15,0x7d,0x18,0x44,0x1b,0xeb,0x77,0x90,0x1a,0x20,0x11,0xa3,0xf0,0xd1,0x51,0x22,
+ 0xa9,0xd0,0x95,0xd4,0xa1,0x0a,0xca,0xb6,0x2a,0x37,0x12,0x07,0x68,0x52,0xab,0x77,
+ 0xd1,0x2d,0x99,0xb0,0xcf,0x18,0xb8,0x72,0x3c,0x2f,0xda,0x83,0x57,0xd0,0xeb,0x73,
+ 0xce,0x5e,0x61,0x74,0xa8,0xa4,0x2d,0xc3,0xff,0xfe,0x2b,0xfa,0xc9,0xd2,0x69,0x76,
+ 0x3f,0xac,0x1f,0x2b,0x06,0x81,0x2c,0xae,0x7a,0x4a,0x95,0xde,0x20,0x92,0x9d,0x89,
+ 0x53,0x8a,0xf1,0x03,0xb5,0x69,0x74,0x36,0x70,0x28,0xe3,0xf1,0xf9,0xc7,0xe7,0xb0,
+ 0x7a,0x31,0x7f,0x00,0x51,0x32,0xe6,0x5c,0x00,0xc6,0x2d,0x4c,0x09,0x7a,0x99,0xf2,
+ 0x6e,0x43,0x0b,0x61,0x22,0xb2,0xf5,0x8f,0x7c,0x37,0x2c,0xcf,0x37,0x9d,0x52,0xc4,
+ 0xfe,0x28,0x3b,0x5c,0x2f,0xa1,0x82,0x59,0x93,0xc5,0x6e,0xa3,0x7c,0xa2,0x1d,0x07,
+ 0x16,0x18,0x3d,0xc3,0x39,0x4e,0x17,0xc0,0xe9,0x70,0xc4,0x13,0xc6,0xae,0xcf,0x99,
+ 0x2a,0xf7,0xd4,0xbd,0xa0,0xae,0x4d,0xf4,0xc9,0x82,0x05,0x8f,0x79,0xf4,0x75,0xc0,
+ 0x27,0xe1,0x01,0x06,0xe5,0x36,0x31,0xfc,0x60,0xb6,0x29,0xcc,0x53,0xe4,0x41,0x7d,
+ 0xb0,0x3a,0xa7,0x3a,0xbc,0xff,0x0e,0xd0,0x62,0x44,0x84,0xc0,0xd0,0x49,0xaf,0xaf,
+ 0xc9,0x69,0xb7,0x7e,0xb9,0xe3,0x2d,0xd0,0x71,0xe2,0xa1,0x82,0x88,0x81,0xf9,0xed,
+ 0x28,0xee,0xc2,0x45,0xaa,0x72,0xee,0xe7,0x36,0xaf,0xe7,0xb3,0xd1,0x89,0xbb,0x70,
+ 0x9b,0xfa,0x52,0xee,0xf3,0xbb,0x18,0x2b,0xc7,0x88,0x6b,0x1d,0x2c,0x77,0x18,0xa7,
+ 0x43,0xae,0x2e,0x11,0x77,0x53,0x42,0xa7,0xed,0xa6,0x28,0x87,0x42,0x14,0x54,0x5a,
+ 0xf6,0x8e,0x37,0x34,0xfd,0x2a,0xda,0xb9,0x7f,0x04,0x65,0x1a,0x38,0x21,0x62,0xd9,
+ 0x96,0x8f,0xdd,0xbc,0x59,0x3e,0xf6,0xc6,0x19,0x5b,0x15,0xf0,0x33,0xa3,0x38,0x44,
+ 0xf1,0x0d,0x08,0x8b,0x44,0x84,0xbf,0xbc,0xb8,0x4a,0x41,0x2d,0xfa,0x58,0xfc,0x55,
+ 0x6b,0xcf,0x6e,0x81,0x14,0xc3,0x23,0x4e,0x00,0x80,0x53,0x0b,0xd6,0x4a,0x52,0x85,
+ 0xa0,0x8e,0x99,0x00,0xdf,0x34,0x5b,0xb9,0xc3,0x56,0x0e,0x3a,0xc9,0x7d,0x43,0x11,
+ 0x4b,0xe8,0xf3,0x07,0x9a,0x43,0x83,0x0f,0x7d,0x09,0x48,0x1e,0x09,0x3a,0x8d,0x89,
+ 0x89,0xfa,0x99,0xd1,0x22,0xa9,0x66,0x2b,0x80,0xde,0xa1,0xd2,0x3c,0x54,0x79,0xb9,
+ 0xf0,0xaf,0x65,0xdd,0x2e,0xae,0xb7,0x6f,0x5f,0x97,0x50,0x8a,0x28,0xd0,0x72,0x67,
+ 0xba,0x69,0x03,0x3e,0xd0,0xfe,0xd3,0xd3,0x9d,0xd3,0x36,0xf4,0xe9,0x66,0x45,0x54,
+ 0x95,0xd9,0xd6,0x21,0x35,0x4d,0x22,0x5e,0x97,0x8c,0xc6,0x97,0xaf,0xb7,0x93,0xdd,
+ 0xd5,0x1d,0x14,0x42,0x70,0x09,0xbf,0x9f,0x53,0xf8,0x18,0x35,0x30,0xe8,0xe8,0x20,
+ 0x8d,0x8b,0xc9,0x89,0x69,0xcc,0x49,0x0c,0xc3,0x8b,0x50,0x23,0x55,0x86,0x3b,0xc8,
+ 0xcd,0xdc,0xcd,0x48,0x31,0xec,0x68,0x22,0xb0,0x46,0x63,0x12,0xb0,0xc3,0x2c,0x5c,
+ 0x54,0x55,0x6e,0xf3,0x40,0x31,0xbc,0x7b,0x37,0x32,0x3e,0x74,0x48,0xeb,0xfa,0xbe,
+ 0x76,0xe7,0x7e,0x34,0xaf,0xcf,0x53,0x85,0x87,0xfc,0x0d,0x55,0xc8,0x8a,0xa4,0x4f,
+ 0xa9,0x16,0x5f,0x1d,0x4d,0x72,0x33,0xf3,0xe5,0x12,0x5b,0xbe,0xc9,0x51,0x8d,0xb7,
+ 0x6e,0x92,0x9c,0x9d,0x1b,0x4c,0x0b,0xfe,0x86,0x6c,0xaa,0xe1,0x4c,0x82,0x86,0x41,
+ 0x57,0xbc,0x06,0x54,0xcb,0xd5,0x08,0xe9,0xf7,0x3b,0x64,0xcb,0xa6,0x58,0xad,0x36,
+ 0xf5,0xe2,0xfe,0x00,0x20,0x69,0xd4,0xf7,0xf6,0xc3,0x26,0x31,0x76,0x88,0xf0,0x66,
+ 0xab,0xaf,0xb6,0xaf,0x37,0x30,0x8c,0x1f,0x55,0x57,0xe9,0x49,0x06,0xf6,0x26,0x1d,
+ 0xea,0x68,0x7c,0xfe,0xd0,0xba,0xb3,0x90,0x17,0xa4,0x49,0x25,0x03,0xc2,0xd6,0xf0,
+ 0x85,0xac,0x52,0x46,0xe7,0x65,0x86,0x45,0xee,0xb4,0x82,0x3a,0xcb,0xaa,0x06,0x2a,
+ 0x47,0x7e,0x46,0x90,0xbc,0x01,0x1e,0xbf,0x71,0x8e,0xa5,0x1c,0x0b,0xfd,0x4c,0x3a,
+ 0x0d,0xc1,0x51,0xe5,0xad,0x0e,0x98,0x20,0x04,0xf1,0x24,0x5a,0x1c,0xf3,0xfb,0x51,
+ 0xcc,0xf8,0x4f,0x53,0xed,0x20,0xfa,0x8a,0x70,0x69,0x68,0x59,0x1e,0x0c,0x38,0xc4,
+ 0x5a,0x5f,0xae,0xf8,0x0b,0x94,0xaf,0x0a,0x8a,0x02,0x4f,0xf8,0x53,0xe2,0x00,0x40,
+ 0x33,0xd6,0x29,0x9f,0xe3,0x8f,0x7f,0xd2,0xd3,0x4d,0xc9,0x29,0x4a,0xd0,0xb1,0xc1,
+ 0x08,0x54,0xa3,0x47,0x65,0x21,0x48,0x9a,0x15,0x34,0xa4,0xac,0x3a,0x5b,0x66,0x52,
+ 0x9e,0xf4,0xc0,0xfd,0xe9,0x04,0x7f,0xcc,0x4c,0xab,0x6d,0xaf,0xea,0x65,0x00,0xac,
+ 0x4f,0xb9,0xc2,0xb6,0xbf,0x41,0x22,0x92,0x60,0xa0,0xc2,0xbc,0xbe,0xe3,0x0e,0x3f,
+ 0x06,0x56,0x87,0xeb,0x48,0xf0,0x62,0x7a,0x1e,0x4f,0xd8,0x2a,0x20,0x89,0x1f,0xa5,
+ 0xb2,0xe5,0x46,0x88,0x42,0x43,0x5b,0xf4,0xe3,0x71,0x0d,0xed,0x72,0xaf,0xac,0x3a,
+ 0xeb,0x5b,0x3d,0x81,0xf0,0x05,0xa0,0x76,0x4d,0xb4,0x00,0x18,0x31,0xd0,0x1f,0x21,
+ 0x9a,0x72,0x75,0xe1,0x40,0xf4,0x2a,0xff,0xd1,0x9a,0xe7,0xeb,0x33,0xf4,0x0e,0xf3,
+ 0xa5,0x2e,0xfb,0xa9,0x80,0x74,0x6e,0x78,0x2f,0x2a,0x5b,0x97,0x8f,0x14,0x08,0x14,
+ 0x67,0x7b,0x0a,0xea,0x6f,0xa1,0xf1,0x4d,0x83,0xca,0x8e,0x0a,0x6f,0x14,0x47,0x64,
+ 0xa8,0x5b,0x6a,0x83,0xfc,0xc2,0xb3,0xcf,0xcc,0xb8,0x51,0xf4,0xb8,0xff,0x0e,0x3f,
+ 0x88,0xec,0x9e,0x83,0xbb,0xb5,0xbe,0xa4,0x06,0xd3,0x41,0x5a,0xcd,0xdb,0xd5,0x82,
+ 0x26,0x85,0xdd,0xea,0x4b,0x3f,0x4a,0xa3,0x4e,0x12,0x57,0xd0,0x06,0x77,0x31,0xbe,
+ 0x91,0xbb,0x2b,0xa9,0xc4,0x43,0xd8,0x8e,0x52,0x28,0x55,0xcb,0x6f,0x57,0xf2,0x8e,
+ 0x2b,0xf6,0x03,0xe1,0xd7,0x5e,0xee,0xec,0x5c,0xf3,0x5c,0x13,0x11,0xea,0x64,0x6e,
+ 0xcc,0x77,0xcf,0x81,0x3e,0x24,0x42,0x1c,0xc7,0x99,0x8b,0x86,0x31,0x6e,0x4c,0x9c,
+ 0x04,0x6a,0x54,0x81,0x33,0x3e,0x13,0x0b,0xde,0xe9,0x91,0x83,0x4a,0xf4,0x45,0xd7,
+ 0x11,0x61,0xfb,0xe2,0xeb,0x01,0xaa,0x14,0xf7,0x61,0x96,0x56,0xb1,0xa3,0x6f,0x28,
+ 0x3e,0x6f,0x72,0x78,0x58,0xdf,0x7c,0x83,0xad,0x73,0x99,0xa4,0x8a,0xc9,0xf0,0x83,
+ 0x4e,0x0f,0x56,0xe9,0x35,0x05,0x64,0x98,0x66,0x86,0xcf,0x8c,0x27,0x9b,0x98,0x9d,
+ 0x56,0x85,0xce,0x9d,0xd5,0x39,0x3e,0xa9,0x12,0x28,0xc7,0xb5,0x5c,0xc2,0xba,0x84,
+ 0x7a,0x3a,0x7f,0x71,0x4d,0x28,0xfa,0x9e,0x25,0x46,0x9e,0xf9,0xf4,0x87,0x5c,0xfa,
+ 0x43,0xa0,0xe7,0xc1,0x82,0xfe,0xdf,0x56,0xaf,0x63,0x4e,0x03,0x26,0x28,0xf5,0xaa,
+ 0x79,0xb0,0xd4,0x3d,0x1d,0x2c,0x3e,0x90,0x8b,0xa1,0x18,0x9a,0xde,0x1f,0xa7,0x5a,
+ 0x06,0x35,0xba,0x7f,0xae,0x1f,0x18,0x54,0x10,0x17,0xea,0xc4,0xd0,0x61,0x28,0xc9,
+ 0xdb,0xf2,0xe5,0xe5,0x65,0x38,0x86,0x45,0xa1,0x7b,0xb9,0x2f,0xfb,0xdf,0x29,0x30,
+ 0x83,0x28,0x2e,0xb4,0x9b,0xe8,0xee,0x78,0x3b,0x7f,0xaf,0x14,0xc8,0xb7,0xcd,0x2e,
+ 0x02,0x4c,0x1e,0xe6,0xaf,0xea,0x8c,0x67,0x88,0x87,0xb6,0xaa,0x8d,0xe7,0x89,0x53,
+ 0xe8,0x78,0x36,0x7a,0xaf,0x73,0x2c,0xde,0x1e,0x1c,0xe8,0x53,0xeb,0xe2,0x80,0x73,
+ 0x1d,0x58,0xf0,0xe5,0x1c,0x0c,0xa5,0x47,0xaf,0xce,0x29,0xde,0xbc,0x14,0xc5,0xdc,
+ 0x9c,0xae,0x43,0x33,0x18,0x0a,0x83,0x5c,0xcc,0x3f,0x2b,0xd0,0x05,0x70,0xe1,0x3b,
+ 0x2d,0x4b,0x82,0xa9,0x59,0xd2,0x18,0x36,0x33,0x7f,0x0e,0xa2,0x43,0xe9,0xa6,0x21,
+ 0xb3,0x82,0xed,0xa7,0x11,0xb1,0xc1,0x4e,0x86,0x53,0xb9,0xcd,0xbf,0x26,0x2f,0xb1,
+ 0x5d,0xe8,0xde,0xac,0x0a,0xc9,0xab,0x61,0x2b,0x02,0x79,0x27,0x2f,0xdb,0xa2,0x09,
+ 0x87,0xe7,0x81,0x78,0xb6,0x39,0x68,0xcc,0xb4,0x2d,0xa6,0x4c,0xe3,0xd9,0xb9,0x86,
+ 0xdc,0x84,0x24,0xa9,0xa9,0xa3,0xb8,0x07,0xda,0x9c,0xba,0x64,0x2c,0x46,0x07,0xe2,
+ 0xeb,0x00,0x65,0xd0,0x84,0x81,0xd4,0x16,0xee,0x0c,0x9d,0x68,0x53,0x20,0x73,0xd3,
+ 0x1a,0x29,0x9a,0x17,0xf9,0x51,0xe0,0x1b,0x0c,0xd8,0x85,0x94,0xb7,0x36,0xa6,0x1b,
+ 0xd3,0xf8,0xca,0xc1,0x1d,0x76,0xf9,0xae,0x9d,0xfb,0x97,0x0a,0x7d,0x93,0x17,0x90,
+ 0x2d,0xa1,0x3b,0x25,0x8b,0xd5,0xfa,0xc2,0xf1,0x2a,0xa6,0xdc,0x85,0x7d,0xc6,0x3f,
+ 0x33,0x65,0x7f,0xaa,0xda,0xfa,0xf7,0x35,0xae,0x7a,0x01,0x72,0xdd,0x54,0xf1,0x8d,
+ 0x33,0xac,0xd3,0xb1,0xaf,0x6b,0x26,0x45,0x95,0x24,0x7a,0x17,0x1c,0x6d,0xc0,0x9a,
+ 0x2d,0x5d,0xd3,0x1b,0x3d,0x15,0xbc,0xd6,0xdd,0x8d,0x9f,0x7e,0xe5,0x6b,0xd7,0xaa,
+ 0xd8,0xd2,0x7f,0xd2,0xf7,0x2a,0x1f,0xd8,0x34,0x93,0xf8,0x59,0xe3,0x15,0x42,0xc3,
+ 0x13,0x43,0x32,0x9d,0x6d,0x97,0xa2,0x7e,0xe6,0xbb,0xf9,0x37,0xa9,0x49,0x04,0x5d,
+ 0xe0,0x78,0x3e,0xec,0xa5,0xe7,0x0e,0x42,0xf0,0xf0,0x87,0x40,0x0e,0xd3,0x42,0xe2,
+ 0xf2,0x3f,0x58,0xba,0x6d,0xea,0x46,0x95,0x73,0xfd,0xbe,0x7a,0xf2,0xf1,0xd7,0x10,
+ 0x90,0x77,0x67,0x99,0xf7,0xcf,0x45,0x53,0x78,0x87,0x12,0x0d,0xf4,0x04,0xc0,0x15,
+ 0x5c,0xa3,0x4c,0xba,0x36,0x18,0xba,0x11,0xf3,0x3a,0x74,0x51,0x36,0x86,0xf1,0x70,
+ 0xbc,0xfc,0xc6,0xec,0xa4,0xff,0x8d,0x8c,0x64,0x46,0x87,0xf9,0x6a,0x8f,0xda,0x24,
+ 0xdd,0xce,0xa1,0x07,0xd5,0xec,0x6f,0xa8,0x6f,0x7a,0x5b,0x9b,0xa2,0x3f,0x2d,0x5f,
+ 0x3a,0x12,0x92,0xbb,0x6c,0xc8,0x02,0xe8,0x12,0x69,0x1e,0x6b,0x4f,0xd0,0x04,0x50,
+ 0xa4,0x14,0x7b,0xd9,0x8b,0x3f,0x40,0xb0,0xbb,0xed,0xc5,0xec,0xb3,0xcc,0x5a,0x64,
+ 0x96,0x97,0x15,0x05,0x50,0xfe,0xa4,0x67,0xb4,0xa5,0x98,0x75,0x96,0x0c,0x58,0x7a,
+ 0x6e,0xfa,0xa3,0x86,0x3e,0x71,0xb7,0x7e,0x40,0x9f,0xfd,0x65,0x67,0x61,0x10,0x19,
+ 0x8c,0x77,0x98,0x16,0xdf,0xb9,0xfa,0x4b,0x78,0xdb,0x93,0x86,0xec,0x9a,0x31,0xe3,
+ 0xda,0xab,0xbd,0xf2,0x59,0x5e,0x6f,0xea,0xa4,0x47,0x27,0x38,0xbf,0x82,0x81,0x3a,
+ 0xa2,0x13,0x6f,0x4b,0xe8,0xd1,0xfa,0x1d,0x51,0x26,0xb4,0xd4,0x05,0x6e,0x08,0xb1,
+ 0xaa,0x3d,0x4e,0x9f,0xec,0xf4,0xb6,0x7f,0x69,0x8a,0x66,0x58,0xe4,0xcf,0x86,0xc7,
+ 0x97,0xc6,0xc6,0xb3,0xaf,0xd1,0x17,0x9b,0xb1,0x68,0xd8,0x9c,0x99,0x6a,0x4f,0xfa,
+ 0x77,0x95,0x5c,0x08,0x57,0xc3,0xc2,0x0d,0x6a,0xfb,0xbe,0x42,0x97,0x66,0x88,0x52,
+};
+
+
+/* 317-???? FD1089A */
+static const UINT8 key_alexkidd[0x2000] =
+{
+ /* data */
+ 0x2b,0xe7,0x6e,0x6f,0x8b,0xcd,0xd8,0x4a,0x23,0x8e,0x30,0x97,0x93,0xe4,0x9b,0x92,
+ 0x60,0x2d,0x9e,0x4b,0x75,0x5c,0x08,0xa6,0x9b,0x96,0x37,0x69,0xf4,0xb3,0xc3,0x77,
+ 0x73,0x24,0x80,0xf1,0xea,0xad,0x04,0x66,0x7f,0xf9,0x8b,0xad,0xb4,0x63,0x00,0xd7,
+ 0x74,0x21,0x2f,0x40,0xec,0x8d,0xde,0x42,0x92,0xc6,0x55,0x3d,0x6d,0x8e,0x66,0x0c,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ /* opcodes */
+ 0x86,0xde,0xb5,0xb0,0x78,0x6d,0x01,0x1c,0x0b,0xdc,0x23,0x97,0xc8,0x4c,0xcc,0xf1,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+};
+
+
+/* 317-0022 FD1089A */
+static const UINT8 key_0022[0x2000] =
+{
+ /* data */
+ 0x00,0xd1,0x14,0x06,0x00,0xe5,0x18,0x30,0xc8,0xd5,0x94,0x32,0x2b,0x37,0xf4,0x99,
+ 0xb2,0x01,0x62,0xc6,0xec,0xef,0x67,0xcf,0x84,0x12,0x30,0x85,0x6d,0xf2,0x57,0x78,
+ 0x65,0xe7,0x76,0x95,0x51,0xdc,0x39,0x32,0xba,0xf1,0x55,0x49,0xe6,0x17,0x71,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+ /* opcodes */
+ 0x15,0xa8,0xda,0xe4,0x8d,0x40,0x15,0xbb,0x3e,0x99,0xd4,0x0d,0x2e,0x3c,0x35,0xb6,
+ 0x55,0x19,0x12,0x85,0x39,0x92,0xa5,0x3f,0x3c,0x3a,0x84,0xde,0x75,0xfe,0xc9,0x4f,
+ 0x40,0x88,0xa0,0xcd,0x39,0xa0,0xcd,0x69,0x1f,0x63,0x30,0xf7,0xb6,0x8a,0x58,0x1c,
+ 0xd0,0x85,0xfd,0x8b,0x6a,0x00,0xb7,0x01,0x79,0x84,0x8e,0x05,0x48,0x43,0xf8,0x5b,
+ 0xd8,0xb7,0x50,0xa9,0x0c,0x97,0xca,0x73,0x2a,0xe3,0xe4,0x84,0x5e,0xf9,0xf0,0xcc,
+ 0xb3,0x44,0x8f,0x71,0x6d,0xa5,0x02,0xc2,0x3c,0x3d,0x5d,0x93,0xd6,0x8d,0x4c,0xd8,
+ 0xf4,0x30,0xfd,0xc1,0xd3,0xdf,0xc7,0xc5,0xc4,0x0c,0x0c,0xfc,0x1b,0x6b,0x80,0xb7,
+ 0x18,0xab,0x9e,0x9e,0x01,0xaf,0x69,0x47,0x6f,0x1f,0x73,0x0c,0x46,0x06,0x89,0x88,
+ 0x60,0x19,0xce,0x11,0x6e,0x7b,0xa5,0xbd,0x5d,0x67,0xa0,0xb1,0xff,0xe1,0xdd,0x51,
+ 0x9f,0x5f,0x18,0x37,0x35,0x65,0xff,0x1b,0x49,0xb6,0x85,0xcc,0x21,0xe0,0xf6,0x88,
+ 0xa5,0x12,0xd1,0xee,0x0f,0x91,0xb0,0xc0,0xc9,0x3f,0xf4,0x75,0xbf,0x45,0x8f,0x8e,
+ 0x6c,0x43,0x0a,0x7a,0x22,0xed,0xa3,0x8d,0x5e,0x92,0x44,0xfa,0x42,0x67,0x5e,0xda,
+ 0x30,0x3b,0xd9,0xaa,0x4b,0xa3,0x01,0x5a,0x47,0x76,0x94,0x75,0x35,0xd6,0x87,0x9e,
+ 0x7e,0xca,0xc8,0xf6,0xd0,0x74,0xde,0x32,0x8a,0x18,0xb0,0xaf,0x7c,0x67,0xa3,0x88,
+ 0x7d,0x7f,0xe1,0xc3,0xf8,0xdc,0xe8,0x5d,0xe6,0xcc,0x95,0xb3,0x8b,0xe5,0x96,0x20,
+ 0x23,0x76,0xe9,0x0f,0x48,0xa9,0x17,0x1d,0xaf,0xcb,0x4b,0x61,0xed,0xe9,0x49,0x52,
+ 0x71,0x17,0x42,0x14,0xd1,0x48,0x45,0x77,0x08,0xc7,0x5a,0x0a,0x63,0xae,0x7f,0xe7,
+ 0x71,0xb4,0x25,0xa7,0x0b,0x4e,0x43,0x91,0xc8,0x20,0xfa,0xa0,0x22,0x04,0xa6,0xd8,
+ 0x0b,0xae,0xaa,0x7d,0x48,0xe7,0x4f,0xb8,0x1d,0xae,0xfe,0xa3,0xf9,0x38,0x1b,0xdc,
+ 0x9e,0x1e,0x5d,0x67,0x03,0x1b,0xbe,0xb3,0x68,0x34,0x86,0x0f,0x81,0x8f,0xdf,0x50,
+ 0x1a,0xd5,0xcb,0x19,0xa2,0x4b,0x6e,0x23,0x54,0x36,0x78,0x78,0x54,0xf1,0x62,0x6b,
+ 0x00,0x11,0x85,0xf3,0x51,0x59,0x2b,0xbc,0x2c,0x2c,0xe9,0x2b,0x3e,0x48,0xa4,0x59,
+ 0x42,0xc6,0xe6,0x70,0xa9,0x70,0x9f,0x43,0xa2,0xb7,0xe8,0x69,0x10,0xa1,0x45,0x67,
+ 0x6d,0x1f,0x38,0x85,0x3a,0x59,0xdc,0xae,0x2e,0x1e,0x10,0x7e,0x5f,0xc8,0x52,0xc7,
+ 0x39,0xcc,0x64,0x06,0x57,0x13,0xac,0x47,0xfc,0x10,0x50,0x4a,0xf0,0x2a,0xa3,0x75,
+ 0x1c,0xad,0x05,0x10,0x71,0x19,0x3a,0x9e,0xae,0x70,0x83,0x19,0x24,0x6d,0xb1,0x99,
+ 0x26,0xc1,0x49,0x65,0xc7,0xaf,0xf1,0xd3,0xbf,0x05,0x4f,0xd9,0x30,0x10,0x77,0x0e,
+ 0xa1,0x65,0x2b,0xe6,0x6d,0x84,0x33,0x88,0xde,0xc7,0xc9,0xb5,0x4e,0xe1,0x86,0x44,
+ 0x46,0xa8,0x39,0xe6,0x40,0x78,0x99,0xc9,0x82,0x71,0xf2,0x46,0xeb,0x1c,0xa8,0xad,
+ 0xdf,0x05,0xcf,0x1a,0x78,0xc2,0x13,0x2a,0x79,0x7c,0x47,0xe3,0x2f,0x03,0xcf,0xff,
+ 0xea,0x74,0x3a,0x46,0xd4,0xd5,0x09,0x52,0x26,0x32,0x5e,0x37,0x9c,0x3d,0x02,0xc2,
+ 0x45,0x38,0x90,0xa7,0x67,0xaf,0xa0,0x4f,0xfb,0xd9,0xbb,0xa0,0xe4,0x86,0x56,0x50,
+ 0x4c,0x96,0xbc,0x0a,0x52,0xd7,0x39,0x88,0x22,0x51,0x51,0x1b,0x62,0x67,0xd0,0xc2,
+ 0x57,0x85,0x09,0x51,0x49,0xae,0xe7,0xa8,0xd2,0xa8,0xeb,0x49,0x0d,0xb1,0x5f,0xde,
+ 0x7c,0xfa,0x56,0x66,0x2c,0x50,0x0c,0x4a,0xf0,0xa6,0xf7,0x20,0xc3,0xb2,0x2c,0xad,
+ 0x2b,0x5d,0x61,0x9e,0x62,0x9d,0x66,0x8e,0xc2,0x51,0xcb,0x3b,0x85,0x52,0x05,0x3e,
+ 0xd6,0x0a,0x03,0x0e,0x3c,0x14,0xb5,0x73,0x42,0x3b,0xb0,0x1a,0xcc,0xde,0xea,0x84,
+ 0x8b,0x25,0x4e,0x3e,0x23,0xff,0xff,0x3c,0xca,0x76,0xdf,0xa3,0xf4,0xaf,0x58,0x02,
+ 0xc2,0x01,0xd9,0x0b,0x2d,0x7b,0x7f,0xe0,0x26,0xdd,0xd1,0x29,0xff,0x88,0x53,0x09,
+ 0x9c,0xe0,0xd2,0x41,0x67,0x37,0x8b,0x38,0x38,0xfd,0xf3,0x02,0x54,0x32,0x43,0x3b,
+ 0xa2,0xf0,0xc9,0x1a,0x46,0xc4,0xbb,0x16,0xa9,0x0e,0x0c,0xf8,0x31,0xd5,0xbf,0xc9,
+ 0xc3,0xce,0x5b,0xf2,0x57,0xa2,0xb9,0xf6,0xd3,0xc0,0x3c,0xe2,0xad,0xf6,0xc4,0x54,
+ 0x8e,0x20,0xbb,0xc1,0x6a,0xc1,0x99,0x05,0x9b,0xd1,0xca,0x99,0xa6,0x8f,0x03,0x76,
+ 0x01,0xb8,0x41,0x84,0x19,0xca,0x18,0x93,0xfc,0x7e,0x95,0x5b,0x83,0x55,0x84,0x3a,
+ 0x68,0xa6,0x18,0x67,0xed,0x0d,0x01,0x70,0x20,0xbb,0xfc,0x51,0x7c,0x46,0x5e,0x71,
+ 0x13,0x69,0x35,0xb1,0xac,0x33,0x1b,0x3f,0xbe,0xdb,0x08,0xc5,0xa8,0x47,0x5a,0x59,
+ 0xd5,0xad,0x1c,0xb9,0x5a,0x64,0xe2,0xb7,0x0c,0xfc,0x2f,0x57,0xdb,0x59,0xa0,0x01,
+ 0x95,0x9b,0x9c,0x9b,0x0d,0x30,0xa9,0x9b,0x82,0x9e,0xc8,0x0b,0x9c,0x17,0xa0,0xb8,
+ 0xe7,0x2a,0xe1,0x3a,0xd9,0x3d,0x1e,0x52,0x00,0x58,0xe6,0x4c,0x53,0x5c,0x22,0x25,
+ 0x84,0x8f,0x9f,0x37,0x8d,0x3f,0xd8,0x24,0xa7,0x49,0x72,0x3f,0xfd,0x70,0x4d,0x69,
+ 0xa0,0xde,0x7c,0x51,0x11,0x88,0x9a,0xa5,0xe1,0x9c,0xea,0x8d,0xcf,0x20,0xaf,0xe9,
+ 0xf6,0xee,0x61,0x19,0x32,0x6e,0xdf,0xb2,0x07,0x54,0xe6,0x2c,0x5c,0xb3,0x9d,0x65,
+ 0x16,0xcd,0x16,0xf4,0x8d,0xfb,0x20,0x47,0xc3,0x44,0x43,0x86,0xc1,0xe4,0xb7,0xbe,
+ 0x81,0xa3,0xc6,0xc6,0xf1,0x9d,0x8b,0x9c,0xc3,0x77,0xdb,0xba,0x4e,0xe6,0x3c,0x57,
+ 0x29,0x15,0x94,0x0d,0x82,0x7b,0x40,0xc7,0x91,0xcc,0x40,0x9c,0xc0,0x3a,0x5d,0x4e,
+ 0x12,0x8c,0xb6,0x7a,0x8f,0x19,0x6e,0x58,0x2e,0x4a,0xbd,0xb0,0xec,0xb7,0x6e,0xf7,
+ 0x8b,0x51,0x44,0xee,0x35,0x83,0x3a,0xe2,0x3c,0x82,0xb0,0x41,0x0e,0x6f,0xcd,0x6d,
+ 0x5d,0xb4,0x62,0xfd,0xa4,0x67,0x5e,0x82,0x9f,0x5a,0x57,0xf9,0xab,0xb0,0xc0,0x60,
+ 0x15,0x6b,0x05,0x6b,0x60,0x89,0xa9,0x34,0x19,0xa2,0xa1,0x54,0x9c,0x66,0x70,0x50,
+ 0x42,0xbe,0xdf,0x2d,0xf7,0x2f,0x68,0x03,0x6b,0xf0,0x42,0x3c,0x44,0x82,0x19,0xc5,
+ 0xd8,0x7b,0x5b,0x27,0x10,0x76,0xf7,0xe8,0xb4,0x33,0x8a,0xe1,0xd6,0x25,0xe5,0xad,
+ 0x04,0x5f,0x0a,0x0e,0x79,0x1b,0x35,0xec,0xf9,0xd2,0x3d,0x60,0xb6,0x43,0x83,0xdd,
+ 0x92,0x20,0x17,0x69,0x10,0xb0,0x07,0xd8,0x72,0x34,0x1e,0x30,0x1f,0xe5,0x7b,0x21,
+ 0x0d,0xf4,0x7c,0x01,0xd6,0x29,0x17,0xb2,0x06,0x75,0x37,0x1d,0xad,0x21,0x9d,0xc8,
+ 0xb6,0x29,0x40,0xcb,0x89,0x3e,0xa7,0x62,0x0b,0xf9,0x06,0x3a,0x7a,0x41,0x16,0x9a,
+ 0x74,0xf7,0xeb,0x17,0xfc,0x08,0x6c,0x94,0xf2,0xba,0x50,0x41,0x82,0x79,0x4d,0xd6,
+ 0xfe,0x72,0x7f,0x9e,0x81,0x0a,0xb4,0x1e,0x63,0x01,0x26,0xff,0x85,0x8d,0x1d,0xb7,
+ 0xa2,0x5a,0x17,0x08,0x5b,0x09,0x1d,0x8b,0x6e,0x8e,0x83,0x5d,0x3f,0xa9,0x01,0xc7,
+ 0xbc,0x0d,0x09,0xb8,0x79,0x74,0x57,0x70,0x29,0x68,0x75,0x70,0x15,0x5e,0xba,0x9d,
+ 0x50,0x24,0xdb,0xe3,0x53,0x3c,0xd7,0x3e,0x5d,0x17,0xa6,0xc6,0xc0,0xf9,0x3d,0x09,
+ 0xf5,0x8e,0xd3,0xe1,0xf9,0x14,0x36,0xb6,0x29,0xa3,0xa7,0x01,0x1c,0x59,0x42,0x64,
+ 0x97,0x6d,0x84,0xda,0x51,0xe9,0x65,0x7b,0x9f,0xc6,0x69,0x4d,0xba,0xfc,0x90,0x4a,
+ 0x73,0x58,0xc7,0x0d,0x59,0x2d,0xaf,0x73,0x6a,0xd9,0x9d,0x2e,0x4f,0x19,0x4f,0xbb,
+ 0x15,0x29,0x20,0x2a,0x90,0x10,0x8f,0x6a,0x78,0xc8,0xe1,0x54,0x26,0x41,0x73,0x75,
+ 0x52,0xf9,0xec,0x45,0x3c,0x28,0x50,0xa1,0x08,0x2e,0x0b,0xda,0xa0,0x62,0x22,0xfe,
+ 0x41,0xe2,0x22,0x61,0x02,0xae,0x4e,0x26,0x50,0x7a,0xd9,0xe0,0xd8,0xf4,0x2d,0x02,
+ 0x25,0x21,0x64,0x54,0xa4,0x36,0x5e,0x0b,0x70,0x48,0x26,0x02,0x17,0x17,0xb1,0xfb,
+ 0xfa,0xa0,0x45,0x81,0x2d,0x21,0xa5,0x74,0xf2,0xb3,0x8e,0x70,0xa0,0x14,0xc4,0xbb,
+ 0x6e,0xff,0x8b,0x73,0xe1,0x27,0xe7,0x67,0x78,0x4a,0x62,0x68,0xc8,0x61,0xa9,0xcb,
+ 0x61,0x8f,0x25,0xd8,0x7f,0xbe,0x23,0x7f,0x5a,0x4a,0xf9,0x62,0x0c,0x60,0x2e,0x1f,
+ 0x5f,0xf3,0x9f,0x97,0xc2,0xf9,0x7f,0x38,0x62,0x2f,0x9f,0x15,0xab,0xc0,0x15,0x0d,
+ 0x8b,0xbc,0xf5,0xa5,0xf2,0xe2,0xea,0x27,0xdd,0x92,0xba,0x45,0xe2,0x8d,0xaf,0xc1,
+ 0x03,0xe3,0x61,0x7a,0x10,0x6c,0xa5,0x1b,0x43,0x2e,0xe1,0xc7,0xa2,0xcf,0x18,0xc9,
+ 0xd5,0xd2,0x0c,0x0b,0xbf,0x1f,0x4c,0xae,0x6b,0xf0,0x54,0x13,0x3f,0xad,0x5a,0x70,
+ 0xd0,0x73,0xd0,0x54,0x6c,0x15,0x09,0xd2,0xd0,0x95,0x2b,0xcc,0xc2,0x0d,0xf8,0xfa,
+ 0xca,0x7f,0x73,0xa9,0x03,0x25,0xc6,0x6a,0x6f,0xff,0x69,0xe6,0x1d,0x5d,0x39,0x59,
+ 0xca,0xe3,0x7f,0x4c,0xb2,0xd5,0x56,0xad,0x92,0xaa,0x48,0x1d,0x1d,0xcd,0x21,0x0b,
+ 0x87,0x45,0x0f,0x00,0x86,0x99,0xb5,0xd5,0xe2,0x19,0x80,0x15,0xec,0x5f,0x42,0x0b,
+ 0xad,0xf3,0x9c,0x0e,0xea,0x7a,0x08,0x46,0x89,0x04,0xe3,0x76,0x78,0xca,0xb6,0xab,
+ 0x5a,0xb0,0x15,0xa7,0x2b,0x87,0x4f,0x45,0x77,0xd2,0xb6,0x3f,0xda,0x22,0x47,0xea,
+ 0x71,0xf7,0x63,0xea,0x2f,0xb9,0xb3,0xa4,0x96,0xf5,0xb6,0x14,0x9d,0xb1,0xd2,0x7e,
+ 0xcc,0x0c,0x1a,0x25,0xd1,0xce,0x09,0x80,0x78,0x26,0x80,0xf5,0x4f,0xb1,0xb3,0xea,
+ 0xa2,0x28,0x30,0xba,0xfb,0x77,0xb8,0xd2,0xeb,0xb4,0x59,0xce,0xfa,0x03,0x74,0x4a,
+ 0xfc,0x6d,0xae,0x42,0x0e,0x81,0xe0,0x66,0x2c,0xdd,0x62,0x0b,0x5a,0x66,0x47,0x00,
+ 0xbf,0xf3,0x5c,0x97,0x3b,0xc7,0x17,0x12,0xbc,0x36,0x32,0xce,0xe7,0x65,0xac,0x6b,
+ 0x3f,0x60,0xdf,0x7b,0xea,0xf9,0x01,0x9b,0x9e,0xcb,0x54,0xd4,0xfd,0x40,0x4b,0x50,
+ 0x28,0x9a,0xe6,0xc8,0xc6,0x8e,0x9f,0x2d,0x38,0x51,0x5c,0x14,0x91,0xc4,0x38,0x97,
+ 0x1b,0xc2,0x38,0x7c,0x13,0x23,0x8a,0xec,0x59,0x3e,0xb1,0x59,0x8d,0xf9,0x3a,0xa8,
+ 0x31,0x5d,0x4b,0x60,0xa3,0xdc,0xf0,0x65,0x1a,0x84,0xcd,0x76,0x7e,0x4b,0xbc,0xc9,
+ 0x3d,0x92,0xab,0x26,0xd4,0xd9,0x7b,0x47,0x41,0x3c,0xfb,0x41,0xb8,0xb1,0x58,0x3e,
+ 0x0f,0x0f,0xaa,0x26,0x97,0x84,0x6e,0x09,0x31,0xfc,0x70,0x1d,0x49,0x98,0x6b,0x37,
+ 0xfd,0x10,0x09,0x12,0x60,0x35,0x32,0x0e,0xc0,0x35,0x85,0xed,0x8a,0x7c,0x14,0x83,
+ 0xba,0xc6,0xb0,0xc1,0x81,0xa0,0xa8,0x7d,0x42,0x12,0xcc,0xd3,0x57,0x06,0x8c,0xd8,
+ 0xcf,0x53,0xe0,0x85,0x88,0x85,0xd1,0xba,0xc3,0xdb,0x29,0xab,0x5d,0xd3,0xb0,0x70,
+ 0x21,0xb4,0x34,0x7f,0xfb,0x59,0xb4,0xe3,0x3a,0xa8,0xcc,0x37,0x5f,0x35,0x57,0x56,
+ 0xed,0x4f,0xf4,0xd8,0x93,0x38,0x17,0xba,0xdc,0x0f,0xce,0xad,0xc2,0x13,0x0b,0x3e,
+ 0x2a,0xb9,0x98,0x34,0xb3,0xbf,0x85,0x04,0xce,0x1e,0xca,0x15,0x27,0xfe,0x5b,0x75,
+ 0x13,0xea,0x4e,0x08,0xae,0xbf,0xcb,0x39,0x6b,0x38,0x97,0x6f,0x27,0x7c,0x0b,0xb1,
+ 0x3e,0x47,0x98,0x57,0x58,0xb1,0x91,0xad,0x8b,0xa7,0x1a,0xd6,0x93,0x53,0x23,0xa3,
+ 0x48,0xce,0x25,0x72,0x54,0xac,0x48,0xd1,0x6d,0x7b,0xdc,0xc5,0xb4,0x43,0x72,0x0d,
+ 0xf1,0xce,0x89,0x23,0xd7,0xf2,0x40,0x38,0xde,0x17,0x96,0x5c,0xf8,0xfa,0x3f,0xba,
+ 0xa7,0xd7,0x59,0xb8,0xe6,0x29,0x92,0x11,0x42,0xc9,0x24,0xb0,0x4f,0x02,0xd3,0x85,
+ 0xd7,0xda,0x30,0xee,0x38,0xa2,0x2d,0xbc,0x83,0xd8,0x30,0x26,0x9a,0x67,0x96,0xc0,
+ 0x57,0xa0,0x76,0xf3,0xec,0x88,0x47,0xe8,0x88,0xde,0x6b,0xab,0x35,0xd9,0x4a,0x51,
+ 0x64,0x5f,0x2b,0xcb,0xa5,0xc7,0x54,0x3c,0xa0,0xda,0xae,0x49,0x25,0x74,0x47,0x5a,
+ 0x05,0x41,0x36,0x8f,0x4d,0xf5,0x2e,0x17,0x36,0xae,0x06,0xe0,0x0b,0xde,0x2f,0xf2,
+ 0x35,0xf8,0x05,0xa5,0xc9,0xfd,0x7f,0x70,0x19,0x03,0x89,0xaa,0xc8,0x00,0x01,0xfb,
+ 0x53,0x01,0x38,0x80,0x70,0x52,0xbd,0x4b,0x23,0xc4,0xfc,0x3a,0x8e,0xc3,0x47,0x20,
+ 0x0a,0x72,0x75,0x55,0xa6,0x06,0x6e,0x7e,0x5a,0x72,0x95,0xb2,0xe1,0x83,0x44,0x83,
+ 0x57,0x3d,0xda,0xcf,0xc3,0x2a,0x7e,0x9d,0xe6,0xff,0xd5,0xe9,0x93,0xd6,0xe3,0xe9,
+ 0x78,0x5b,0xd4,0x9c,0xf9,0xc8,0x5c,0x86,0x64,0xfc,0xa0,0x6b,0x71,0xc7,0xe3,0xb5,
+ 0xe6,0x9a,0x3a,0xf3,0xee,0x74,0xe9,0x86,0x14,0x27,0x4b,0x71,0x59,0xcc,0xbf,0x14,
+ 0x47,0x84,0x43,0xbe,0x50,0x8b,0x0f,0x7c,0x1b,0x38,0x1b,0x61,0xbb,0xe4,0x56,0xf9,
+ 0x29,0xd0,0x2a,0x0e,0x7e,0xad,0xa4,0x65,0x67,0x89,0x87,0x6b,0x04,0x1c,0x53,0x0c,
+ 0x86,0x02,0x9d,0x33,0xce,0xd5,0x47,0xa1,0x46,0x33,0x6a,0x85,0xd3,0xf6,0x16,0x0f,
+ 0x10,0x9c,0xa7,0x72,0x94,0x1f,0xa0,0x29,0x70,0x62,0xea,0x11,0x71,0x82,0xfd,0x69,
+ 0xaf,0x40,0x7c,0x46,0x88,0xfd,0xa9,0x21,0x74,0xe2,0x42,0x18,0x6c,0x70,0xb3,0x14,
+ 0x1a,0x24,0x81,0xb9,0xf6,0xc7,0x3b,0x2f,0x38,0x68,0x45,0x75,0x0b,0x20,0xdd,0x19,
+ 0xfa,0xc1,0xba,0xdf,0x1f,0x16,0xa2,0xa7,0xc9,0x9e,0xf5,0xa5,0xb9,0x70,0x5e,0xac,
+ 0xa6,0x44,0x38,0x93,0x2c,0xe2,0x9a,0xe0,0x21,0x16,0x6a,0xdf,0x47,0x15,0x71,0x1e,
+ 0x24,0xca,0x7e,0xac,0xbd,0xe1,0x97,0xd6,0xe8,0x0d,0x09,0x1b,0x10,0xe0,0x26,0xf1,
+ 0x1e,0x7a,0x55,0x28,0xdd,0x70,0xfa,0x83,0xfe,0x86,0x92,0x93,0x69,0x62,0x72,0xea,
+ 0xd5,0x8a,0x53,0x91,0x3e,0x34,0x07,0x71,0x50,0xc9,0x5f,0x5f,0x2b,0xe6,0x38,0xf5,
+ 0x5d,0xce,0x2d,0x35,0x26,0x81,0x99,0x97,0xd8,0x84,0x64,0x59,0xbd,0xfa,0x48,0xaf,
+ 0x12,0x1d,0x8b,0x94,0x79,0x85,0x43,0xc4,0x86,0xc8,0xa4,0x76,0xd7,0xd0,0x55,0x5b,
+ 0x4b,0xe6,0x59,0x9e,0x04,0x5f,0x66,0xa0,0x49,0xf3,0x34,0x7d,0x7d,0xc9,0x5f,0x17,
+ 0x82,0x79,0x33,0x4c,0xde,0x6d,0xae,0xc8,0xa0,0x13,0x83,0x78,0x50,0x79,0x6f,0x3a,
+ 0x89,0xb7,0x23,0x99,0x29,0x93,0xdf,0x0d,0x67,0xb3,0x40,0x8c,0x61,0x85,0x8e,0x0d,
+ 0x87,0x21,0x6f,0x3d,0x31,0xb1,0x16,0xc1,0x93,0xc5,0x73,0xe9,0xf5,0x09,0x43,0x49,
+ 0x74,0xc1,0xbf,0xa9,0x84,0x9f,0xfd,0x44,0xa6,0xd0,0x4f,0xd1,0x87,0x96,0x50,0x2d,
+ 0x7d,0xe2,0xf6,0x4f,0x2f,0x5b,0x19,0xd8,0xcc,0xd5,0xa7,0x68,0x4f,0x96,0x9d,0xb6,
+ 0xd3,0x81,0x03,0x6a,0x6b,0x85,0xe8,0x79,0x05,0x21,0x91,0x1f,0x8b,0x11,0x11,0x52,
+ 0x37,0x67,0x9e,0x29,0xcb,0x91,0xea,0x2b,0x3a,0x8c,0x29,0x76,0x0c,0x76,0xf0,0x7c,
+ 0x11,0x4e,0x66,0x25,0xf8,0x74,0x90,0x07,0x34,0x67,0x64,0xfc,0xba,0x47,0x44,0x80,
+ 0x2e,0x49,0xf8,0x80,0x1e,0x88,0x15,0x77,0xff,0xcd,0xbb,0x1e,0x59,0x04,0x2b,0x7c,
+ 0xcc,0x87,0x5a,0xb2,0xe8,0xdc,0x10,0xed,0xf1,0xc2,0x30,0xf5,0xb6,0x66,0xdf,0x07,
+ 0x8d,0x0d,0xac,0x2f,0x9b,0xa9,0xe4,0x24,0x86,0x79,0xd5,0x85,0xe9,0x3f,0x06,0xb6,
+ 0xdd,0x3e,0x1c,0xab,0xe5,0xfe,0xf1,0x00,0x92,0x55,0x2d,0xf0,0x3b,0xbf,0x69,0xe2,
+ 0x9e,0xc5,0x79,0xe6,0xe5,0xae,0x9b,0x59,0x07,0xdb,0x80,0xe8,0x89,0x3f,0xe1,0x7d,
+ 0xa9,0x25,0x06,0x18,0x71,0x98,0x30,0x7e,0x04,0x5c,0x3f,0x5d,0xf5,0x97,0xa2,0xae,
+ 0xde,0x05,0xe9,0x53,0xda,0xcd,0x85,0xdf,0x7e,0x81,0x94,0x93,0x4d,0x04,0xc3,0x80,
+ 0x9a,0x78,0x05,0xbd,0x4a,0xbf,0x0c,0x06,0x45,0xc8,0x79,0xae,0x91,0xcc,0x2d,0x72,
+ 0xa2,0xed,0x49,0x85,0x97,0x24,0x5f,0x62,0xbb,0x45,0xa0,0x88,0x75,0x76,0x90,0xe5,
+ 0x05,0xe2,0x08,0xbd,0x5c,0x13,0x71,0x0d,0xa5,0xbc,0xfe,0x32,0xad,0x42,0x51,0x2f,
+ 0x3a,0xae,0x0c,0x01,0x20,0x5f,0x5f,0xb0,0x73,0xa7,0x9b,0x7c,0x6f,0x9d,0x70,0xcc,
+ 0xb5,0xf7,0x8e,0x10,0x2a,0x87,0x3d,0x2b,0x8c,0x2b,0xa5,0x42,0xe9,0x59,0xe0,0x29,
+ 0xb3,0x06,0x48,0x7c,0xd5,0x90,0x85,0x3c,0x31,0xb3,0x9b,0x28,0xe5,0x41,0x95,0xa9,
+ 0xeb,0x21,0x62,0xa2,0x58,0xab,0x51,0x09,0x20,0x92,0x32,0xbf,0xa1,0xfd,0x1b,0x0f,
+ 0xb5,0xa0,0x98,0x16,0x75,0x2a,0x92,0x14,0x5b,0x98,0xa0,0x58,0x5b,0xad,0x08,0x99,
+ 0x45,0xe2,0xe3,0xb9,0x92,0x1a,0x9c,0x4b,0xde,0xe5,0x07,0xec,0xd0,0xab,0x1f,0x3c,
+ 0xeb,0x98,0xcf,0x89,0x8b,0x75,0xed,0x2b,0xc9,0x09,0x9f,0xae,0x30,0x59,0xb3,0x38,
+ 0x3f,0x10,0x7d,0xd1,0xa1,0x96,0x18,0x0d,0x65,0x61,0x06,0xc3,0x5e,0xcd,0x76,0xc4,
+ 0xc6,0x5b,0xfb,0x7b,0x31,0xe5,0x1c,0x79,0xa7,0x3d,0x57,0x8c,0x12,0x01,0x7a,0x55,
+ 0x19,0xb7,0xf3,0x68,0xcf,0xa4,0x0d,0x6a,0x0d,0x42,0x2f,0x84,0xcd,0xe2,0xf3,0xb9,
+ 0x9b,0x90,0xcf,0x80,0x1e,0xe5,0x0f,0xa1,0x97,0x99,0xd6,0xa9,0x64,0xe7,0xb3,0xd1,
+ 0x14,0x35,0x2e,0xaa,0x3d,0xff,0xac,0x7e,0x02,0x8e,0x60,0xed,0xa5,0x2c,0x0f,0xa4,
+ 0x0c,0x95,0x98,0x1c,0xee,0x77,0xda,0x71,0xa8,0xa6,0xb9,0xae,0xd1,0xae,0x08,0x5a,
+ 0x42,0xa0,0x2a,0x21,0xdf,0x84,0xa7,0x6b,0x2f,0xca,0xec,0x0f,0xf0,0xb3,0x0b,0x83,
+ 0xfb,0x2b,0x48,0xa6,0xeb,0x20,0x35,0x0e,0x7c,0x10,0x21,0x0f,0x64,0xfb,0x9e,0x2a,
+ 0xe6,0x00,0x64,0x94,0x3a,0x0e,0xe4,0x54,0x78,0xab,0xd8,0xdd,0x24,0x9e,0x40,0x29,
+ 0x1f,0x0c,0xf4,0xaf,0x50,0x62,0x6c,0x03,0xf0,0x49,0xfc,0x12,0xe1,0x7b,0xff,0x00,
+ 0x83,0x20,0x50,0x24,0x99,0x11,0xba,0x9c,0x2e,0xd0,0x2f,0xa5,0x06,0x18,0xb4,0x22,
+ 0x22,0x49,0x90,0x16,0x8c,0x4c,0x51,0xb4,0x83,0xff,0x7e,0x30,0xf8,0x99,0x9a,0xd9,
+ 0x12,0x2d,0xb1,0x32,0x77,0x57,0xb1,0xe5,0xa5,0xfd,0xd2,0x4f,0xd3,0x34,0x7d,0x1c,
+ 0x97,0xe9,0x85,0x98,0x33,0x88,0x54,0x8b,0xec,0x90,0xd8,0x52,0x65,0xc8,0xb2,0x6d,
+ 0x82,0x1e,0xfd,0x0a,0x16,0x96,0xec,0xa9,0xb7,0xf4,0xe2,0xfe,0xb5,0x37,0x27,0xc6,
+ 0x59,0x72,0xfb,0x80,0xdb,0xe3,0x7b,0x4f,0xea,0xdd,0xa4,0xec,0x52,0xe8,0xc3,0x94,
+ 0x97,0xb1,0xcd,0x7a,0x6e,0x20,0x65,0x28,0x13,0xd2,0x8a,0xd2,0x12,0x0c,0x6d,0xe5,
+ 0x81,0xac,0xd4,0x42,0xba,0xc8,0x39,0x93,0x3f,0x21,0xeb,0x64,0xfa,0x04,0xdb,0xda,
+ 0x01,0x11,0xf3,0x7b,0xeb,0xb9,0x6d,0x6a,0x35,0x7a,0xba,0xd7,0xfa,0xaa,0xda,0x39,
+ 0x58,0xf1,0x9f,0xd6,0xbb,0xa5,0x97,0xb0,0x4a,0x05,0x13,0x7c,0x9a,0x29,0x0e,0x57,
+ 0x80,0xae,0x7e,0x69,0x63,0x11,0xa1,0xcf,0xcd,0xe4,0x32,0x2a,0x02,0xf3,0xbb,0xc7,
+ 0xb9,0x9e,0xbf,0x83,0xee,0x92,0xe7,0x19,0x24,0xab,0xa8,0x46,0xd7,0xf3,0xe8,0xd5,
+ 0x53,0x4b,0x67,0xe2,0x05,0xc9,0xc4,0xff,0xa7,0xa9,0x50,0x7c,0xde,0x03,0x29,0x9e,
+ 0x12,0x44,0xd5,0x9e,0x5d,0x1a,0x1f,0xb5,0x90,0xb9,0x74,0x8b,0x63,0x9f,0x0f,0x1f,
+ 0xd0,0x05,0x37,0x37,0xb1,0x15,0x14,0x39,0x7b,0xd8,0x28,0x22,0x4f,0x59,0x56,0x5a,
+ 0x61,0x3d,0xc8,0x97,0xcc,0xbd,0x54,0x8e,0x7d,0xcc,0xed,0xeb,0xb1,0x81,0xc4,0x89,
+ 0x16,0x25,0x99,0x3e,0x05,0xd9,0xe1,0x8c,0xdd,0xeb,0x8e,0x35,0x6a,0x78,0x5a,0x6f,
+ 0xfa,0xd5,0xb0,0xed,0xf7,0x96,0x6f,0x75,0xab,0x95,0x5b,0x23,0x26,0x32,0xbc,0x12,
+ 0x2c,0x0b,0xfc,0x68,0xa0,0x5e,0xb7,0xe8,0xc5,0x38,0xb8,0x99,0xd6,0x9e,0x1a,0x79,
+ 0x42,0xca,0x29,0x13,0x88,0x44,0x3f,0x66,0x49,0x19,0x49,0x83,0x6d,0x78,0x70,0x19,
+ 0x99,0x6f,0xe9,0x18,0xd3,0xee,0x6f,0x27,0xb6,0x0e,0x92,0x1c,0x34,0xb2,0xd1,0x35,
+ 0xb4,0x1f,0x27,0xb2,0x05,0xa7,0xaf,0xf4,0xb2,0x4d,0x1b,0x96,0x8d,0xb6,0x60,0xe6,
+ 0x3f,0xbe,0xb2,0x4b,0x25,0x78,0xe7,0xb0,0x4c,0xe5,0x3e,0xe4,0x16,0xe7,0x13,0xbd,
+ 0xc7,0x5d,0xbc,0xe4,0x11,0xcc,0x63,0xd6,0x76,0x0b,0x05,0x14,0xf8,0x67,0x43,0x61,
+ 0xb5,0x34,0xf2,0xc5,0x65,0x3c,0xf7,0x14,0x8c,0x5e,0xe0,0x63,0x11,0xe5,0xf8,0x14,
+ 0xea,0x90,0x36,0xcb,0x1c,0x6a,0x49,0xc7,0xf4,0x7b,0x44,0x77,0x3a,0x5e,0x35,0xd9,
+ 0x77,0x83,0x2b,0x1f,0x1a,0x7f,0x58,0xb7,0x83,0xa6,0xfe,0xfd,0x88,0x62,0x68,0x88,
+ 0xc6,0x0d,0x45,0x98,0x7b,0x92,0xd6,0x89,0xf0,0x89,0xdd,0x1b,0x72,0xf3,0xd7,0x8d,
+ 0xfb,0x0c,0x8c,0xd4,0xe0,0x0e,0x04,0xdd,0x81,0x07,0x27,0xdf,0x13,0x8d,0x05,0xc5,
+ 0xaf,0xb7,0xb6,0xd0,0xe2,0xf1,0x56,0x4b,0xd4,0x33,0x71,0x07,0xf4,0x3b,0x70,0xf5,
+ 0xc5,0xfd,0x27,0x07,0xdf,0x1e,0xff,0xcd,0x5f,0x58,0x86,0x32,0x1f,0x22,0xa0,0x5b,
+ 0x9b,0x25,0x43,0x86,0xc2,0x59,0x6f,0x89,0xf7,0x3a,0x7c,0x28,0xbb,0x4c,0xc0,0xd5,
+ 0xeb,0x9c,0x7b,0x73,0x54,0xd2,0xb8,0xd9,0xa8,0x3d,0x35,0xf7,0x3e,0x8b,0x4a,0xf0,
+ 0xb4,0x04,0x60,0xcf,0x3f,0xb8,0xc7,0xd9,0x25,0x57,0xea,0x42,0xf4,0xc6,0x21,0xbd,
+ 0xa8,0xff,0x03,0x35,0xba,0x48,0x94,0x3c,0x75,0xe5,0x33,0xae,0x30,0x7b,0x9b,0x6f,
+ 0x2d,0xc5,0x51,0x86,0xd8,0xd2,0xfc,0xd5,0x44,0x79,0xa0,0x9c,0x79,0x4a,0x96,0xb9,
+ 0x83,0x06,0x20,0x4a,0x41,0x61,0x7d,0x84,0x0e,0x64,0x7c,0x81,0x4a,0x0c,0x87,0xc2,
+ 0xd0,0xbd,0xb9,0xdb,0x90,0x61,0x0b,0xf6,0x50,0x17,0xa3,0x9a,0x38,0x20,0x76,0xb6,
+ 0x56,0x52,0x9a,0xa1,0xcf,0x8e,0x14,0x0c,0x82,0xed,0x56,0xf9,0x51,0xd9,0x84,0xac,
+ 0xc3,0xf0,0x43,0x4a,0xd6,0x9b,0xe3,0xbd,0xc0,0x87,0x6e,0x0f,0xe5,0x12,0x57,0xd7,
+ 0x22,0x3e,0x0e,0xea,0x88,0x35,0x15,0x57,0x32,0x3e,0x6f,0x5f,0x35,0x46,0x3f,0x31,
+ 0xa3,0x8f,0x78,0xd7,0x65,0xec,0xdd,0x62,0xda,0x06,0xcf,0x9c,0xa1,0xfa,0x25,0xff,
+ 0x45,0xbb,0x66,0xf5,0x4b,0x2e,0xba,0xb4,0x98,0x82,0xdc,0x75,0x73,0xe2,0xee,0xc9,
+ 0x12,0x7f,0x4c,0x40,0xa5,0x46,0x63,0xdb,0xb2,0x90,0xb9,0x74,0xad,0x99,0xe3,0x4c,
+ 0x79,0x7e,0x53,0x6b,0x2e,0x77,0x92,0x3e,0x1a,0xe2,0x7c,0x96,0x11,0x83,0x35,0x51,
+ 0x9d,0x4c,0x28,0x69,0xad,0xa5,0x03,0x6e,0x3a,0xf7,0xba,0x5c,0x33,0x4f,0xc0,0xd3,
+ 0x38,0x09,0x0f,0x69,0x99,0xf9,0x5c,0x21,0x73,0x28,0x9a,0xfa,0x2a,0xd4,0x70,0xba,
+ 0x72,0x09,0x7f,0x19,0xe8,0xcf,0xbc,0x60,0x77,0x97,0xb4,0x07,0x18,0x49,0xe6,0x72,
+ 0xb5,0xd5,0x2b,0x0b,0x58,0x85,0xcc,0xbc,0x80,0x70,0x3e,0x5b,0xc4,0x39,0x9d,0x50,
+ 0xa8,0xb0,0x2f,0x5a,0xb0,0x7f,0xd3,0x1b,0x0b,0x56,0xf5,0x5d,0xeb,0xf5,0x81,0xfa,
+ 0xbb,0xd7,0x9c,0xfc,0x1c,0x08,0x33,0x88,0x4b,0x9b,0xcd,0xb7,0xab,0x87,0x5d,0x69,
+ 0x4f,0x39,0x2b,0x6f,0x53,0x54,0x1f,0x22,0x03,0x21,0x3c,0x91,0xf4,0x33,0xd0,0xcf,
+ 0xc5,0x0a,0x1d,0xa7,0xb9,0x67,0xf9,0xc1,0x09,0x0a,0x25,0x03,0x28,0x1f,0x47,0x65,
+ 0xd2,0xd3,0xf4,0x07,0x4f,0x52,0x99,0xc2,0xbd,0x7e,0x7e,0x14,0xe1,0x7d,0x83,0x33,
+ 0x62,0x6d,0x26,0x8f,0xc1,0x22,0x33,0xf9,0x01,0x11,0xbb,0x38,0x5d,0x9c,0xa4,0xf2,
+ 0x48,0x37,0xd9,0x87,0x4c,0x5a,0x44,0x88,0xc0,0x83,0xd0,0xb6,0xcd,0xf2,0xe7,0x33,
+ 0x6b,0x7d,0x62,0x26,0x78,0x63,0xc7,0x55,0x16,0x24,0xf6,0x26,0x9d,0x02,0xfe,0x94,
+ 0x66,0x57,0x85,0xbe,0xc3,0x6b,0xe7,0xe2,0xba,0x4f,0x82,0x25,0xd5,0x6f,0x35,0xcf,
+ 0xd9,0x7e,0x98,0x37,0x40,0x07,0x57,0x61,0x59,0xdf,0x44,0x08,0xc0,0x49,0x69,0x02,
+ 0xc1,0x32,0xec,0xdd,0x94,0xeb,0x11,0xee,0xc3,0x25,0x17,0x31,0xa9,0x1c,0x07,0xfa,
+ 0x6c,0xf3,0x1e,0x16,0x79,0x16,0x50,0xaa,0x8d,0xdf,0x90,0xbc,0x7e,0x34,0x44,0xb3,
+ 0x75,0xff,0x65,0xf4,0xfc,0x78,0x71,0x7c,0x7a,0xe8,0x02,0xb5,0x89,0x72,0x33,0x72,
+ 0x7d,0xd0,0xd3,0x12,0xa1,0xc6,0x79,0x46,0x20,0x24,0x04,0x50,0xf7,0x77,0x01,0xb1,
+ 0xa1,0x01,0x72,0x4d,0x0f,0x97,0xee,0xb5,0xff,0x23,0x98,0x0c,0x02,0x35,0x93,0xd3,
+ 0x32,0xcf,0x77,0x5f,0x1e,0x95,0x09,0xce,0xf4,0x11,0xac,0xf1,0x27,0xf4,0xea,0x03,
+ 0xeb,0xda,0xd3,0x70,0xf3,0x93,0x7a,0xc3,0xfc,0xcf,0x2f,0xf0,0xc1,0x11,0x72,0x4c,
+ 0x84,0x85,0xba,0x16,0xb3,0x67,0x1e,0xaa,0x7b,0x0a,0xc2,0x9d,0xf2,0x30,0x0b,0x85,
+ 0x86,0x6a,0x32,0xb4,0x61,0x8f,0x1a,0x91,0xbd,0x2a,0xb4,0xe9,0x82,0xf5,0x92,0xff,
+ 0x89,0xd9,0x56,0x9e,0x67,0x82,0xac,0x3b,0x18,0x9b,0xdf,0x7e,0x31,0xeb,0x96,0x02,
+ 0x6f,0xd8,0x4d,0xde,0xf6,0x2a,0xec,0x87,0xdc,0xe9,0x77,0x64,0xc6,0x09,0x6d,0xd7,
+ 0x66,0x39,0x1e,0xed,0x53,0x26,0x54,0xfc,0x76,0x70,0xa2,0x96,0x0f,0xbf,0x64,0xa7,
+ 0x2a,0x0b,0x81,0xcf,0xc2,0xf1,0x87,0x6c,0xae,0xd8,0x0c,0xea,0x8f,0xff,0x22,0xb6,
+ 0x59,0xf4,0x1a,0x8f,0xd7,0x04,0x72,0xf3,0xe7,0x21,0xec,0xf3,0x71,0x7c,0xf9,0x74,
+ 0x62,0x03,0x7c,0xf5,0x28,0xc3,0x44,0x4b,0x3b,0x5f,0xb5,0x09,0xdb,0xc5,0x89,0xb9,
+ 0xfa,0x67,0xd5,0xee,0x13,0x32,0xe0,0x02,0x2e,0xe1,0xb8,0x52,0xaf,0xfb,0xc8,0xf1,
+ 0x5d,0x2d,0xa6,0xe7,0x2f,0xbc,0xf0,0x4b,0x2b,0x9b,0x8b,0xd9,0x94,0x29,0x22,0xbd,
+ 0x55,0x4a,0x64,0x5e,0x32,0x9d,0x07,0xd3,0xa6,0x41,0x6e,0x74,0xed,0xe3,0x74,0x55,
+ 0x32,0x86,0xfa,0x92,0x40,0xb8,0xd2,0xbe,0xfa,0x34,0xa8,0xa8,0xa4,0x47,0x6d,0xd5,
+ 0x13,0xa3,0x7d,0x0b,0x5c,0x70,0x9d,0xb5,0x7d,0x3c,0x9e,0xfe,0xf9,0x5f,0x86,0x52,
+ 0xe5,0xd5,0xfa,0x96,0x37,0xa0,0x6c,0x46,0xee,0xc8,0xd6,0x3d,0x07,0xf6,0x92,0xf5,
+ 0x31,0x3a,0x9e,0x44,0x66,0x8e,0xeb,0xfc,0x7b,0xee,0xe1,0x39,0xbe,0xe3,0x7b,0xa4,
+ 0x91,0x13,0xad,0x98,0xba,0xd1,0x09,0x53,0xc0,0x91,0x47,0x3f,0x50,0xb9,0x79,0x8d,
+ 0xf7,0xae,0x96,0xce,0xa9,0xc0,0xfb,0x4e,0xb1,0x66,0x89,0x30,0x95,0xf2,0xbd,0x21,
+ 0x91,0xd2,0x7e,0x8b,0x4c,0x58,0xae,0x37,0x1a,0x7b,0x8e,0xb1,0x8f,0xfd,0x93,0xd9,
+ 0x6b,0x61,0x49,0xf5,0x87,0xcd,0x78,0xbf,0x65,0xe7,0xa7,0xf7,0x2a,0x77,0x11,0x80,
+};
+
+
+/* 317-0024 FD1089B */
+static const UINT8 key_0024[0x2000] =
+{
+ /* data */
+ 0x31,0xce,0xea,0x22,0x7d,0x86,0x74,0x6a,0xd1,0x28,0xa3,0x5a,0x00,0xac,0x00,0x3a,
+ 0xa5,0xaf,0x7a,0x2c,0x08,0xc9,0xf8,0x6f,0x00,0xec,0x82,0x71,0x63,0x96,0xd0,0xcd,
+ 0x49,0x0d,0x71,0x26,0x15,0xb8,0xd2,0xd8,0x25,0x79,0xa2,0xe9,0xce,0x9c,0x46,0x8e,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ /* opcodes */
+ 0xd7,0x1e,0x88,0xde,0x90,0x3d,0x5f,0xd3,0x47,0x32,0xe5,0x6d,0x29,0xfd,0x36,0x5b,
+ 0x63,0xe8,0x24,0xc3,0x40,0x5e,0x70,0x5e,0xee,0xd4,0x4c,0x4d,0x39,0xc7,0x73,0x68,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+};
+
+
+/* 317-0027 FD1089B */
+static const UINT8 key_0027[0x2000] =
+{
+ /* data */
+ 0xce,0x92,0x01,0x6b,0xd3,0x3c,0x3a,0xcb,0xaa,0x57,0xdc,0x12,0x8d,0x7b,0x6e,0x8c,
+ 0x91,0x33,0xb0,0x66,0x78,0x27,0x80,0xe8,0x6e,0x52,0xe7,0xf3,0x63,0x4c,0x3b,0x94,
+ 0x85,0x6b,0x4b,0xd9,0x70,0x8c,0xa2,0xa7,0x93,0x8c,0x14,0xb2,0x42,0xdd,0x56,0x45,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ /* opcodes */
+ 0x72,0xc8,0x6c,0x47,0xf4,0x4f,0xc7,0xc2,0xb2,0x33,0xd0,0xc2,0xee,0x4a,0xf0,0xc8,
+ 0xcf,0x6f,0x8a,0x15,0x0d,0x7a,0xca,0xf3,0x84,0x09,0x57,0x4f,0x5c,0xcf,0x7c,0xd4,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+};
+
+
+/* 317-0028 FD1089A */
+static const UINT8 key_0028[0x2000] =
+{
+ /* data */
+ 0xce,0x92,0x03,0x6b,0xd3,0x3c,0x3a,0xcb,0xaa,0x57,0xdc,0x10,0x8d,0x7b,0x6e,0x8c,
+ 0x91,0x31,0xb0,0x66,0x78,0x27,0x80,0xe8,0x6e,0x50,0xe7,0xf3,0x61,0x4c,0x3b,0x94,
+ 0x85,0x6b,0x4b,0xd9,0x72,0x8c,0xa2,0xa7,0x93,0x8c,0x14,0xb2,0x40,0xdd,0x56,0x45,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ /* opcodes */
+ 0x72,0xc8,0x6c,0x47,0xf4,0x4f,0xc7,0xc2,0xb2,0x31,0xd0,0xc2,0xee,0x4a,0xf2,0xc8,
+ 0xcf,0x6f,0x8a,0x15,0x0d,0x7a,0xca,0xf1,0x84,0x09,0x57,0x4f,0x5c,0xcf,0x7c,0xd4,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+};
+
+
+/* 317-0033 FD1089A */
+static const UINT8 key_0033[0x2000] =
+{
+ /* data */
+ 0xe7,0x57,0x69,0xa4,0x29,0x6c,0x18,0xa3,0x64,0x73,0x13,0x55,0x16,0x59,0xaa,0x2c,
+ 0x51,0xb4,0x82,0xce,0x26,0x3f,0xfb,0x44,0xaa,0xac,0xc9,0x76,0x61,0xc6,0x55,0x6e,
+ 0xbd,0x9e,0x8a,0x33,0x46,0x6a,0x4e,0x20,0x8a,0xca,0x33,0x48,0x84,0x3e,0x69,0x7c,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+ /* opcodes */
+ 0xf3,0x4e,0xd0,0xeb,0x26,0xd6,0x7d,0xaf,0x37,0x2f,0x78,0xd9,0xb4,0xad,0x7f,0x9d,
+ 0x57,0x96,0xb0,0xaa,0xd5,0x38,0xfe,0xc7,0x20,0x89,0x91,0x8c,0xc4,0x19,0x3f,0x1d,
+ 0x5a,0x29,0xb2,0xe8,0x22,0x6f,0xed,0xbe,0x2c,0xc7,0xd3,0x5d,0x7e,0xbc,0xeb,0x30,
+ 0x19,0x89,0x73,0xa5,0xc7,0xbd,0x3d,0x55,0xbe,0x5d,0x92,0xe8,0xda,0x3c,0xb2,0xa3,
+ 0x90,0x81,0x72,0x6c,0x4f,0x36,0x13,0xe2,0xd0,0x1e,0x57,0x93,0x5e,0xe2,0x86,0xdd,
+ 0x51,0xce,0xfe,0x67,0x60,0x09,0x60,0xa7,0x48,0x71,0x62,0x4c,0xe5,0x55,0x0f,0x39,
+ 0x39,0xf2,0xfd,0x14,0xba,0x82,0x46,0xb1,0x6e,0x8d,0x6a,0xd1,0x31,0xb1,0xce,0xfa,
+ 0x55,0x7b,0xeb,0xd8,0x60,0xec,0x6b,0xbe,0xf2,0xe6,0x2a,0x48,0xe9,0xd0,0x32,0x5c,
+ 0x7a,0xb7,0xbd,0x61,0x76,0x14,0x49,0x41,0x75,0xb8,0x25,0xba,0x80,0x56,0x9f,0xec,
+ 0xf1,0x0e,0x68,0xb7,0xc5,0x2d,0x34,0x76,0x24,0x05,0xab,0x2f,0xb3,0x4f,0xe9,0x1d,
+ 0x7a,0x8d,0x99,0x6f,0x97,0x06,0xd5,0xa6,0x4f,0x8e,0x7d,0xf2,0x0e,0x72,0xa0,0x2f,
+ 0xb6,0x63,0x68,0xba,0x60,0xf1,0xe2,0x4c,0xbc,0xe2,0x44,0xc7,0xa5,0x68,0xb4,0xeb,
+ 0x3b,0xd4,0xda,0x78,0x1c,0x19,0xe9,0x97,0x96,0x32,0xa1,0x39,0x75,0xe3,0xc2,0x50,
+ 0xdf,0x04,0xe2,0x36,0xb9,0xfe,0xa8,0x59,0xed,0x5f,0x22,0xac,0x1f,0xa0,0xbf,0x15,
+ 0x50,0x7c,0xb7,0x97,0xbf,0xfe,0xcc,0x6c,0xde,0x02,0xb6,0xb9,0x7b,0xc7,0x2d,0x85,
+ 0x29,0xb8,0xfc,0x4f,0xc7,0x62,0xf6,0x05,0xc2,0x32,0xd8,0xa6,0x53,0x65,0xf6,0x82,
+ 0x2d,0xf6,0x83,0x12,0xe1,0x87,0xa1,0xf0,0x3e,0x1c,0x02,0x57,0x5a,0xe6,0x3b,0x0f,
+ 0x96,0x1b,0x71,0x16,0xbb,0x34,0xca,0x64,0x93,0xbb,0x24,0x82,0x09,0x5c,0x39,0xd6,
+ 0x77,0xda,0xdb,0x9a,0x81,0x69,0xa9,0xfa,0xf8,0x2d,0x32,0x50,0x44,0xd4,0x75,0x97,
+ 0xa2,0x86,0x22,0x4d,0xb0,0xb8,0x78,0x99,0x38,0xb0,0x69,0x71,0xa8,0x0a,0xe8,0x47,
+ 0x23,0x88,0xa9,0xac,0x99,0xe0,0x86,0x60,0xeb,0x91,0x32,0xf0,0x56,0xd6,0xa1,0x79,
+ 0x71,0xd1,0x56,0x29,0xd8,0x26,0xb4,0xcb,0x9f,0xde,0x1c,0x45,0x5e,0x73,0x69,0x4b,
+ 0x13,0xfd,0x91,0xba,0x1d,0xb2,0xd3,0xaa,0x98,0x6e,0x00,0x02,0x97,0xe7,0x09,0x88,
+ 0x93,0x5a,0x95,0xa8,0x67,0x39,0xde,0x52,0x3c,0x4f,0x57,0xcb,0xcc,0xf6,0xbb,0xe7,
+ 0x97,0x4a,0x09,0x99,0x32,0x59,0x0d,0x34,0x1f,0x74,0x7a,0x09,0x60,0xd1,0xbf,0x66,
+ 0xca,0xc1,0xfd,0x68,0xbc,0x4e,0x17,0xa0,0x1f,0x0c,0x86,0x77,0xe2,0x9f,0xcf,0x5f,
+ 0xff,0xf1,0x27,0x30,0x43,0xe1,0x37,0xaa,0x82,0x50,0x86,0xfa,0x2d,0x12,0x00,0x35,
+ 0xd8,0xee,0x42,0x2d,0x27,0xb6,0xb5,0xdb,0x72,0xce,0x9b,0xfb,0x23,0xa8,0x29,0xa9,
+ 0xc7,0x8f,0x64,0x40,0x2a,0xdb,0xfb,0x60,0xfc,0xaf,0x68,0x46,0x49,0x47,0x45,0x76,
+ 0x34,0xb9,0x2c,0x68,0xae,0xaa,0xf0,0x1f,0xc3,0x15,0x39,0xf9,0x07,0x70,0x2f,0x1c,
+ 0x0c,0x81,0x7b,0x89,0xd9,0xdb,0xee,0xfa,0x83,0x2d,0x26,0x47,0xbf,0x52,0x6d,0x07,
+ 0x85,0x07,0xf5,0xa8,0xa7,0xd1,0x25,0x85,0xe8,0x7f,0xe4,0x2b,0x30,0x51,0x4c,0xc8,
+ 0x99,0xba,0x5d,0x4a,0xc4,0xe1,0x24,0xf0,0xdf,0xc0,0x7b,0x73,0xf8,0x97,0xcb,0x1c,
+ 0x74,0x41,0xcb,0x29,0x3b,0xc6,0x3e,0x41,0x5b,0x42,0x94,0xdd,0x4d,0xfc,0x48,0xa2,
+ 0x3f,0x50,0xf0,0xf2,0xd5,0x9b,0xe4,0x6c,0xd1,0x86,0x98,0xd1,0xc1,0xc4,0xd5,0xd9,
+ 0x61,0x3d,0xea,0x46,0xb1,0x6b,0xcb,0x48,0x97,0x02,0x40,0x72,0x87,0x6d,0x29,0x73,
+ 0x4e,0xb1,0xe3,0x23,0xb8,0x60,0xf1,0x9c,0x9c,0x3b,0x68,0x84,0x33,0x23,0x55,0xf8,
+ 0x0b,0xca,0x1e,0xa8,0x24,0x1a,0x5d,0x76,0x50,0x27,0xaf,0x2c,0x15,0x8f,0x32,0x53,
+ 0x40,0xd0,0x0b,0xea,0xf6,0xc0,0xad,0x57,0x13,0xce,0xbe,0x4b,0x17,0xae,0xbc,0x7f,
+ 0x84,0xe9,0x44,0xc8,0x3c,0x4d,0xf3,0xab,0xa2,0x5f,0x84,0xff,0x86,0xbb,0xe4,0x4e,
+ 0x45,0xd6,0x4f,0x82,0xab,0xe9,0x48,0x32,0x3b,0x7a,0x10,0xf4,0x36,0x88,0x80,0x71,
+ 0xcb,0x30,0x28,0x4c,0x9b,0x21,0xc6,0xbf,0x52,0x68,0x35,0xd4,0xa9,0x09,0x3d,0x34,
+ 0x14,0x3d,0x90,0xbe,0x56,0xcf,0xba,0x23,0x8d,0xb9,0x45,0x19,0x21,0x32,0xd1,0x95,
+ 0x17,0xfb,0xb1,0x5e,0x41,0x53,0xbd,0xb4,0x03,0xb1,0xa2,0xfa,0x6f,0xe8,0xa3,0x90,
+ 0x53,0xaf,0xe0,0xb0,0x08,0xb8,0xeb,0xf5,0xc2,0xd4,0xc4,0x0c,0x01,0x94,0xfe,0xd0,
+ 0x47,0x12,0x74,0x29,0x08,0x01,0x4f,0x62,0xec,0x81,0xe2,0x03,0xb0,0x58,0x98,0x07,
+ 0x0f,0xb4,0xa9,0x45,0x0e,0x7c,0x0d,0x27,0x27,0x9f,0x63,0x01,0xd7,0x2b,0xce,0x17,
+ 0x2a,0x53,0xd3,0x98,0x45,0x10,0x39,0xa7,0x63,0x3d,0x0e,0x60,0x91,0xfd,0x4c,0xd2,
+ 0xe5,0x73,0x06,0x1c,0xe3,0x76,0x5e,0xf2,0x7e,0x00,0x1e,0x92,0x27,0x0c,0xa8,0xea,
+ 0x0f,0xe4,0xb5,0x5a,0x80,0x0d,0x9f,0x80,0xfe,0xea,0x63,0xa4,0x0c,0xf9,0xad,0xfd,
+ 0x39,0x78,0xee,0x7a,0xf9,0xe3,0x8a,0x2d,0x99,0x1f,0xcb,0x63,0x94,0xf1,0xad,0x78,
+ 0x85,0xb2,0xa7,0x78,0xc4,0xee,0x36,0x4b,0x2c,0xf5,0x6e,0x91,0xba,0xbf,0x0b,0x55,
+ 0x0c,0x64,0xf8,0x12,0x55,0xf2,0x7b,0xe0,0xbe,0x84,0x61,0x33,0x16,0x52,0x67,0x13,
+ 0xb5,0xb8,0xc3,0x4f,0x16,0x68,0xf5,0x0c,0xcc,0xd1,0xed,0x69,0x31,0x7f,0x75,0xcf,
+ 0xa9,0x2b,0x11,0xf3,0x35,0xd2,0xf0,0xad,0x6b,0xe1,0x4d,0x99,0x56,0x16,0x05,0xde,
+ 0xc7,0x51,0x59,0xd9,0x19,0x5a,0x21,0x4b,0x72,0x98,0x86,0x01,0x3b,0x70,0x2b,0x3f,
+ 0xca,0x74,0xf8,0x88,0x5a,0x59,0xc1,0x82,0x27,0x03,0x3e,0x32,0xf7,0x4a,0x21,0xfd,
+ 0x2f,0xe4,0xbc,0x9f,0x60,0xac,0x47,0x21,0x30,0xfe,0x38,0xf8,0x68,0x47,0xad,0x98,
+ 0x31,0xcc,0x0f,0xdd,0x5c,0xc3,0x9d,0xd1,0x05,0x11,0x93,0x21,0xdd,0x44,0xe7,0x8c,
+ 0x51,0x98,0xee,0x58,0x98,0x73,0xfe,0xba,0x18,0x93,0x38,0x1e,0xb9,0xb7,0x3a,0xaa,
+ 0x11,0x1c,0x77,0xac,0x02,0x2a,0x94,0xfb,0x80,0x2f,0x0f,0x07,0xa8,0x2d,0x9f,0x6a,
+ 0x9f,0xd4,0xf0,0x1b,0x90,0xa6,0xaf,0xb1,0x2d,0xf1,0x86,0xc6,0xff,0x3a,0x81,0xf6,
+ 0xfe,0x02,0xe4,0x5a,0x8f,0x02,0xcb,0x1f,0xe0,0x39,0x35,0xa0,0x04,0x1d,0xee,0x20,
+ 0x3b,0xbb,0x8f,0x83,0x54,0x78,0x92,0x2a,0x76,0x76,0x6b,0xa2,0xcc,0x53,0xdd,0x1e,
+ 0x49,0xd1,0x7d,0x90,0x84,0xd8,0x2b,0x24,0x18,0x26,0xb2,0x60,0x84,0xf5,0x37,0xd0,
+ 0x38,0xb4,0x01,0x01,0xb8,0xae,0xc3,0xe4,0x10,0xa1,0x93,0xfa,0xee,0x19,0xa0,0x77,
+ 0x8b,0x79,0x2b,0x56,0x03,0x14,0x0a,0x5a,0xf1,0xce,0xb8,0xc4,0xc8,0x77,0xe1,0x08,
+ 0x5e,0x0f,0xe9,0xb7,0x30,0x93,0x9b,0xd0,0xec,0xcc,0xa6,0x6c,0x39,0xde,0xa0,0x3d,
+ 0xbe,0x2f,0x20,0xa1,0x48,0xcb,0xd9,0x74,0x7a,0xf4,0xba,0x66,0x0d,0x12,0x06,0x99,
+ 0x70,0xa4,0x51,0x73,0x9d,0x03,0x7c,0x26,0xf9,0xc4,0xb0,0x30,0xd1,0xdd,0xd4,0x87,
+ 0x35,0xf7,0xb7,0x23,0x56,0x24,0x4b,0xb1,0x4a,0x81,0x6c,0x28,0x16,0xc4,0x77,0x47,
+ 0xfd,0xbd,0x18,0x5a,0xcd,0x3c,0x08,0xf6,0xd3,0xac,0xf5,0x10,0x5a,0x0e,0x52,0x96,
+ 0x12,0xf4,0x49,0x0b,0x2f,0x82,0x1a,0xf8,0x48,0x8f,0x2a,0xe7,0xf2,0xb9,0x0a,0x65,
+ 0xf3,0xdb,0xc7,0xbd,0x20,0x9a,0x8d,0x7b,0x9c,0xbd,0xfb,0x18,0xe7,0x91,0x38,0x32,
+ 0x49,0x3a,0x29,0xb9,0x08,0x54,0xf1,0xb9,0xbd,0x2a,0x13,0x1b,0xfd,0xdb,0xee,0x2b,
+ 0xc0,0x79,0x49,0x6c,0x7a,0x24,0x37,0xf2,0x75,0x9d,0xdc,0xdf,0x5e,0x2e,0x77,0x30,
+ 0x7b,0x86,0xf6,0x11,0x64,0xdf,0x37,0xed,0xf6,0x87,0xf2,0x38,0xd0,0x05,0x30,0xc7,
+ 0x9a,0x30,0x09,0x77,0x96,0xe3,0xe9,0x37,0x7f,0xeb,0xb7,0xe2,0x60,0x2a,0x53,0x37,
+ 0x3b,0x40,0xd9,0xaa,0x84,0xc4,0xb4,0x0d,0x4c,0xaf,0x6f,0xb5,0x6e,0x63,0xcf,0xb2,
+ 0xac,0xc9,0x90,0xd1,0xaf,0x5b,0xee,0x6e,0x94,0x38,0x14,0xfd,0x72,0x18,0x96,0xfd,
+ 0xe8,0x4b,0x37,0xa0,0x66,0xac,0x8c,0x03,0x31,0xe7,0x67,0xf0,0xc7,0x21,0xfd,0xca,
+ 0x0c,0x01,0xe1,0x50,0x19,0x9e,0x6c,0xf8,0xbd,0x90,0xbb,0x70,0x7d,0x9e,0xcb,0x41,
+ 0xe1,0xeb,0x75,0x97,0x85,0xb5,0x66,0x8d,0x53,0x3d,0xdd,0x78,0xc4,0x66,0xf2,0x70,
+ 0x3e,0x75,0x55,0x36,0x42,0xb5,0xee,0x76,0xa5,0x5b,0xda,0x4f,0xc3,0xfe,0x34,0x22,
+ 0xd4,0x75,0x35,0x3a,0x91,0xe9,0xca,0xf7,0x38,0x89,0x86,0xea,0xbd,0x8e,0x83,0x7c,
+ 0x3b,0xb4,0x57,0x48,0x91,0xb4,0xe9,0x64,0x11,0xd5,0xf5,0xb1,0xee,0xc6,0xed,0xff,
+ 0x9e,0xe6,0xc5,0xce,0x30,0x05,0xa9,0x1a,0x4e,0x15,0x9e,0x56,0xea,0x78,0x8c,0x4e,
+ 0x42,0xc5,0x0e,0xf9,0x45,0x7e,0x1f,0x6c,0xc5,0x11,0x17,0x0a,0xca,0x0f,0x1d,0x4e,
+ 0xdd,0x63,0x49,0x6d,0x37,0x55,0x40,0x15,0xfc,0xce,0xc1,0x70,0xfc,0x77,0x58,0x7c,
+ 0x2c,0xb7,0x49,0x0a,0x45,0x2b,0x70,0x5b,0xa3,0xa4,0x0f,0x01,0x7d,0x85,0xbc,0x32,
+ 0xe3,0x64,0xab,0xeb,0x03,0x90,0x74,0xb7,0x3f,0x32,0x7b,0x7d,0xc9,0x84,0x80,0x7b,
+ 0x31,0xb3,0xe9,0xf9,0x98,0xa6,0xe9,0xa4,0x7f,0x05,0xc8,0xa8,0x7b,0xc3,0xa8,0x59,
+ 0xe3,0xbf,0x1d,0xf4,0x31,0xb0,0x69,0x92,0x72,0xd5,0xb7,0xb8,0xe4,0xd0,0x95,0xca,
+ 0x1d,0xc3,0xba,0x41,0x4b,0x60,0x31,0x2e,0xe7,0x2e,0x97,0x92,0xb2,0x70,0x2d,0xa4,
+ 0xdd,0x7b,0x3c,0x23,0xe9,0x91,0x9c,0x83,0x90,0x2d,0x19,0x91,0x44,0x01,0x86,0xb9,
+ 0x22,0x80,0xb7,0x21,0x07,0x7b,0xd3,0x24,0x98,0x4a,0xd3,0x4c,0x2c,0x41,0x3c,0x14,
+ 0x9e,0x16,0xb3,0xe1,0x66,0xb2,0xcf,0xa3,0x08,0x0d,0xc0,0x02,0xe8,0x1a,0x84,0xc5,
+ 0xbb,0x53,0x49,0x52,0x77,0x96,0xe6,0xa2,0x08,0x9e,0x9b,0x06,0x93,0x7b,0x14,0x69,
+ 0xd4,0xa0,0x93,0x12,0x7e,0x44,0x88,0x10,0x1b,0x88,0xcd,0x3f,0xa1,0x7f,0x8d,0xcb,
+ 0x35,0x62,0x61,0x25,0x9d,0x09,0x20,0x1f,0x48,0xff,0x7b,0x18,0x07,0xc2,0x0e,0x0b,
+ 0xe1,0xcc,0x5f,0x6e,0xf1,0x47,0x92,0x3f,0xdb,0x7d,0x70,0x8c,0xbe,0x30,0x4c,0xf1,
+ 0x52,0x40,0x55,0xad,0x2f,0x38,0x7b,0x4c,0x4b,0x87,0xb5,0x53,0xdc,0x5f,0x91,0xa0,
+ 0xe1,0xfe,0x57,0xdd,0xff,0xe8,0x04,0xd7,0xda,0xc7,0x98,0x23,0x58,0x30,0x55,0xf7,
+ 0xe3,0xf0,0xdb,0xab,0x91,0x67,0x72,0xb1,0x60,0x0a,0x61,0x0a,0xd7,0xeb,0xed,0xf2,
+ 0x32,0xf4,0xbb,0x7e,0x82,0x03,0x6a,0x1c,0xc5,0x57,0xa0,0xf6,0xd7,0x74,0x43,0x72,
+ 0x00,0x9e,0xe2,0x7e,0x35,0x81,0x29,0x96,0xae,0x70,0x5f,0x52,0x18,0x1b,0xa5,0x75,
+ 0x4e,0x24,0x2e,0x88,0x1e,0x69,0x3d,0x22,0xe3,0xcd,0x8a,0x4d,0xc5,0x11,0x5f,0x95,
+ 0x72,0xe1,0xca,0xcc,0x08,0x3a,0xe4,0xdb,0xe3,0x86,0x19,0xc8,0x5f,0x1c,0x93,0x46,
+ 0x39,0x68,0x54,0x97,0x85,0xb0,0x20,0xbe,0xf9,0xb0,0x42,0x89,0x36,0xfe,0x59,0x2f,
+ 0xf3,0x1a,0x1e,0x56,0x9a,0x4c,0xdb,0x4f,0xf4,0x0c,0xa7,0x23,0x3b,0xa3,0xb4,0x38,
+ 0xf6,0x0c,0x39,0x81,0x2e,0x0f,0x9e,0xaf,0x58,0x8e,0x7f,0x55,0x83,0xd8,0xe7,0x33,
+ 0xf2,0x81,0x03,0xdd,0x76,0x13,0x2d,0x9c,0xb6,0x15,0xd2,0xfd,0xae,0xea,0x84,0xa8,
+ 0xf4,0x56,0xb1,0x7c,0xdb,0xd8,0x24,0x0a,0xbb,0x08,0x92,0x54,0x8b,0x86,0x08,0x58,
+ 0x47,0xdf,0x6d,0x72,0xb6,0xa1,0xff,0x9d,0xc0,0x3b,0xec,0xc0,0x55,0xc0,0x28,0x00,
+ 0x2d,0x86,0x50,0xd7,0x98,0x59,0xf4,0x3f,0x2f,0x10,0x9d,0x09,0x49,0xa4,0x05,0x98,
+ 0x0d,0x35,0x31,0x87,0xad,0xd8,0xba,0x05,0x7b,0x1d,0x5d,0xd8,0x8f,0x37,0x61,0x34,
+ 0x7b,0x9c,0x1c,0xbc,0x88,0xfd,0x19,0xaf,0x40,0xc5,0x37,0xdc,0x21,0x71,0x25,0x2e,
+ 0xd1,0xea,0x66,0x88,0x78,0x5f,0xf3,0x86,0x20,0x0d,0x85,0x47,0xa6,0xc5,0x3e,0x9c,
+ 0x25,0x49,0x02,0xcf,0xae,0x5f,0xbd,0x2e,0x62,0x12,0x7f,0x57,0xdb,0x87,0x3e,0xcd,
+ 0xfe,0xa2,0xfe,0x53,0xa5,0xa6,0xfc,0xbf,0x6a,0xa8,0xf2,0x5a,0xf5,0x96,0x63,0x02,
+ 0x00,0x31,0x05,0x9b,0xe8,0xf6,0x43,0xe9,0x02,0x22,0x27,0xc3,0xbd,0x7a,0x68,0x67,
+ 0x7f,0x02,0x6c,0x51,0x0e,0x40,0x78,0x3a,0x63,0x38,0xb6,0xbd,0xd8,0x3f,0xde,0x09,
+ 0x94,0x9c,0xad,0x5e,0xe6,0x09,0x74,0x5f,0x8a,0x9b,0x96,0x29,0xb1,0x69,0x9a,0xd5,
+ 0x3f,0xcf,0xfe,0x44,0x60,0x57,0x3d,0x14,0x4e,0x93,0x55,0x22,0x7b,0x7d,0xd9,0xa9,
+ 0x36,0x04,0x19,0x3b,0xfc,0x15,0x0a,0x6b,0x17,0xae,0xae,0xb3,0x53,0x83,0x86,0x5c,
+ 0x0d,0x72,0x3d,0x63,0x83,0xd2,0xee,0x51,0x27,0x86,0x9f,0x2b,0xaf,0x87,0x76,0x3c,
+ 0xec,0x07,0x19,0xc7,0xa4,0x5e,0xad,0x10,0x98,0x75,0x9e,0x12,0xfa,0x9a,0xdf,0x94,
+ 0x27,0xf9,0x5a,0x7e,0x01,0x4b,0xe5,0x16,0xe5,0xc5,0x4c,0xd9,0x89,0xf6,0xc4,0x23,
+ 0x21,0x69,0x9c,0xa8,0xeb,0x11,0x94,0x4c,0x10,0x35,0x19,0xf1,0x19,0x06,0x68,0x6e,
+ 0x98,0x10,0x3a,0x3a,0xe5,0x4d,0x21,0xb8,0x9a,0xd6,0x2b,0x58,0x6e,0x3b,0xf3,0xa7,
+ 0x57,0x24,0x99,0x70,0x1d,0xc3,0xe3,0x13,0xcd,0x29,0x8a,0xf7,0xc9,0xe7,0x6a,0xfa,
+ 0xa1,0xc5,0x85,0x11,0xa7,0x0b,0xd4,0x84,0x8b,0x00,0xfa,0x18,0x9b,0x78,0xe7,0xfb,
+ 0xf8,0xc8,0x7f,0xcc,0x13,0x24,0x3e,0xb0,0x87,0x6c,0xf2,0x6f,0xb9,0x26,0xc9,0x0a,
+ 0xf1,0xe0,0x66,0xe3,0x08,0x7e,0x70,0x19,0x44,0xc1,0xc2,0xd7,0x47,0xa8,0x0c,0x69,
+ 0xf7,0x5a,0x92,0x33,0x76,0x81,0x67,0x4f,0x19,0x96,0x36,0x19,0x82,0xf5,0x89,0x5a,
+ 0xba,0x85,0xcf,0xeb,0xd0,0xf5,0x6f,0x0b,0xe2,0x30,0x6b,0x39,0xfe,0x5f,0x69,0xda,
+ 0xfc,0x76,0x8b,0x83,0x39,0x26,0x9c,0xff,0xf6,0x11,0x0d,0x06,0xf0,0xdc,0x4f,0xd9,
+ 0x47,0xaf,0xf8,0x0f,0x1a,0x40,0x95,0xc9,0xbf,0x56,0xb0,0x03,0x83,0xe7,0xe1,0xea,
+ 0xee,0x82,0xc6,0xf6,0x2e,0x35,0x5f,0xcc,0x7b,0xba,0xc4,0x21,0xdb,0xf6,0x70,0x3b,
+ 0x1b,0x8a,0x96,0xc4,0x59,0x1e,0x29,0xfe,0x1f,0xf3,0x36,0x74,0x3a,0xf4,0x50,0x12,
+ 0x95,0x26,0xd9,0x51,0x6f,0xcc,0x90,0x2f,0x46,0xd9,0x6c,0xf3,0x6d,0xdd,0x18,0x0a,
+ 0x1f,0xdb,0x80,0x30,0xc8,0xdc,0x6c,0xc6,0xb1,0x97,0xfc,0x42,0x10,0x1a,0x99,0xc1,
+ 0x35,0x05,0x53,0x01,0xed,0x41,0x90,0xd3,0x9e,0x50,0x2d,0x56,0x55,0x09,0x35,0x6d,
+ 0xdb,0x3d,0x8b,0xaf,0x7f,0x92,0x18,0x80,0x75,0xf4,0xb0,0xf5,0xb0,0x2c,0x0a,0x89,
+ 0x83,0xca,0xfa,0x87,0xa1,0xfe,0x5f,0x04,0xc6,0xa3,0x30,0xfb,0x16,0xdb,0x38,0x6e,
+ 0x5d,0x20,0x5d,0xb3,0xb7,0x70,0xd9,0x97,0xca,0x00,0x99,0xfb,0xa6,0xd4,0x22,0x39,
+ 0xc2,0xed,0x47,0xc6,0xa1,0xfd,0x95,0x42,0xdd,0x6e,0xb1,0x7e,0x33,0x5b,0x92,0xdd,
+ 0x54,0x32,0xf0,0x9b,0xc9,0xaa,0x47,0xe3,0x2b,0x76,0x1e,0x45,0x90,0xcb,0x16,0x16,
+ 0x7b,0x9b,0x09,0xf4,0xed,0x5d,0x6c,0x72,0xf7,0xbb,0xd5,0x13,0xb7,0x03,0xcf,0x5c,
+ 0xc7,0x00,0xc7,0x1b,0x44,0x40,0x7b,0x4b,0x63,0x43,0xfa,0xd9,0x5a,0xc1,0x9a,0x50,
+ 0x4d,0x18,0x83,0x7a,0x6f,0xdd,0xca,0x3b,0x6f,0xb1,0xd5,0xc5,0x5b,0x8f,0xc4,0x5d,
+ 0xf0,0x61,0xa9,0xb4,0x0e,0x3d,0x01,0x12,0xe7,0xb2,0x48,0xab,0xd1,0xc1,0x48,0xed,
+ 0xee,0x94,0x35,0x66,0x25,0x69,0xe1,0x4d,0x78,0x87,0x79,0x62,0xd9,0x51,0x50,0x74,
+ 0x05,0xfd,0x59,0x87,0x11,0xeb,0x52,0x5a,0x7e,0x42,0x35,0xac,0xcd,0xcb,0xe4,0x1b,
+ 0x4b,0x94,0x23,0xfb,0x3b,0x6d,0x53,0xc2,0x1b,0x1b,0x3b,0x07,0xb2,0x3d,0x33,0x1c,
+ 0x8f,0x3f,0xd7,0x2f,0xf0,0x02,0xc6,0x4d,0x08,0x83,0x9f,0x7a,0x72,0xdf,0xdd,0xb2,
+ 0x93,0x18,0x17,0x03,0xa5,0x07,0x77,0x5c,0x6f,0xbe,0x26,0xfe,0x50,0x64,0x34,0xe3,
+ 0xac,0xb9,0x44,0x9e,0xb2,0xc6,0xe4,0xc2,0x93,0x71,0xf7,0xc4,0x6a,0x25,0x50,0xe2,
+ 0x60,0x92,0xc7,0xba,0x11,0xbb,0x00,0x01,0x28,0xe0,0xbe,0x2f,0x2e,0x17,0xc4,0x9b,
+ 0x6e,0xad,0xc7,0x90,0x7f,0x0d,0x2e,0xa3,0x45,0x12,0x7b,0xea,0x13,0x70,0x5f,0x13,
+ 0xee,0xf1,0x9a,0x1e,0x84,0xbc,0x33,0xf9,0x9e,0xc6,0x82,0xac,0xf5,0x84,0xd4,0xb8,
+ 0x22,0x0d,0x80,0xf8,0xd9,0x43,0x65,0x8d,0x71,0xfc,0x42,0xea,0xf7,0xb8,0x9e,0x86,
+ 0x3e,0x32,0x6d,0xe8,0xbb,0xff,0x7c,0xcd,0x77,0x05,0xb2,0xf2,0xb5,0x92,0x2a,0x97,
+ 0x19,0x90,0xdc,0x94,0xf7,0x4d,0x30,0x8c,0x83,0x51,0xf2,0x68,0xe5,0x9f,0x43,0xe8,
+ 0x07,0xc7,0x4e,0xa6,0x07,0xa2,0xa9,0x08,0x31,0x2a,0x61,0x3c,0xbe,0x91,0x11,0xc5,
+ 0x55,0x86,0xec,0x2b,0x12,0x28,0xa4,0x05,0x42,0xc8,0x85,0xba,0x9d,0x11,0x14,0x28,
+ 0x3a,0x86,0x6d,0xf4,0x66,0x81,0x78,0x69,0xdb,0x1d,0x16,0x91,0x01,0x3c,0xac,0xf7,
+ 0x13,0xb7,0x63,0x5a,0x66,0x3d,0x17,0x67,0xb2,0x5c,0xb6,0x1a,0x7b,0x80,0x3d,0xbc,
+ 0x43,0x80,0x9a,0xec,0x62,0xd1,0x28,0x79,0x2d,0x4b,0xaa,0xc6,0x1e,0xa3,0x95,0xd6,
+ 0x6f,0xb0,0xdc,0x17,0x5d,0x1e,0x0e,0x43,0xed,0xd2,0xb4,0xab,0xec,0x79,0xa7,0x37,
+ 0xba,0xe2,0xd6,0x62,0xd0,0x2a,0x20,0x18,0xb8,0x68,0xaf,0xa8,0xbd,0xec,0xa5,0x7d,
+ 0xf6,0x5d,0x5a,0x95,0x20,0x8e,0x76,0xfa,0x10,0x98,0x33,0xbd,0x84,0xa5,0x9d,0xb7,
+ 0x08,0x7a,0x56,0x4a,0xf1,0x9f,0xa1,0x55,0x50,0xfe,0x3e,0xc3,0x42,0xf9,0xac,0x9e,
+ 0x92,0xbd,0x9f,0xfe,0x2e,0xa1,0x0b,0x54,0xcd,0x85,0xff,0x72,0xb7,0xa4,0x35,0xca,
+ 0xf0,0x18,0xf6,0xec,0x6a,0x8e,0x08,0x63,0x75,0x71,0x4a,0x8b,0x00,0x3d,0x6d,0x81,
+ 0x9c,0x8a,0x03,0x85,0xbd,0x7b,0xf4,0x7a,0x1e,0x20,0x56,0x17,0x79,0x11,0x3a,0x95,
+ 0x6d,0xe0,0xfc,0xe0,0xc5,0xa9,0xa9,0x8e,0x31,0xf1,0xb1,0x85,0x94,0xcd,0xc4,0x13,
+ 0xae,0xe0,0xa2,0xf4,0x07,0x43,0x9c,0x16,0x68,0xa2,0xbc,0x7f,0x59,0x51,0xbb,0xba,
+ 0x73,0x31,0x43,0x11,0x4e,0x9d,0xf6,0x37,0x23,0x7c,0x1e,0xb8,0x27,0x35,0x8b,0xa9,
+ 0x62,0x0b,0xd9,0x41,0xd8,0x17,0xf3,0xd7,0x09,0xe3,0xdf,0xc8,0x33,0x3b,0x13,0x07,
+ 0xff,0x5e,0xd9,0xc7,0xea,0x48,0x41,0x2e,0x8e,0x4b,0x87,0x0d,0xc1,0xee,0x11,0x4b,
+ 0x73,0x57,0x0c,0x52,0x97,0x2a,0x5d,0xbd,0xd0,0xd3,0x15,0xd6,0x4d,0x8d,0x07,0xdb,
+ 0xc4,0x7c,0x37,0xc6,0x77,0xc9,0xbb,0x7e,0x6e,0x29,0x1a,0xdd,0x07,0x81,0xa6,0x23,
+ 0xa9,0xc7,0x32,0xbf,0xb3,0x30,0xa6,0xd9,0x44,0x45,0xbd,0x76,0xf1,0xb4,0x90,0x85,
+ 0x29,0x3a,0x0d,0x86,0x6e,0x7c,0xe6,0x67,0x4b,0xf3,0xcc,0x74,0x25,0x74,0xf3,0x6c,
+ 0x75,0x86,0xa2,0xf3,0x74,0xca,0x2f,0x14,0x1f,0x3e,0x87,0x71,0x0d,0x13,0xeb,0x03,
+ 0x79,0x49,0x1e,0x44,0x2a,0x75,0x91,0x90,0x77,0x27,0x58,0x47,0xf9,0xb7,0xac,0x70,
+ 0x22,0xd6,0x1f,0x97,0x34,0x00,0x59,0xb5,0xb1,0x1c,0x23,0xbc,0x11,0xd9,0x52,0x93,
+ 0x07,0x38,0x85,0xe6,0x88,0x60,0xe6,0x66,0xf3,0x17,0xfd,0xb6,0xe2,0x7e,0xde,0x53,
+ 0xcf,0x13,0x4b,0x5b,0xde,0xdd,0xdc,0xe6,0x9f,0xba,0x1a,0x5f,0xe3,0xac,0x2d,0xf4,
+ 0x81,0x3e,0x63,0xee,0x09,0x89,0x22,0xc1,0xab,0x24,0xfc,0xe6,0xae,0x0e,0xe1,0xfb,
+ 0x86,0x2c,0xdf,0xbf,0x3d,0xc5,0xae,0xe1,0xb4,0x2c,0x0e,0xd3,0xed,0x3e,0xd9,0x81,
+ 0x4b,0xcd,0xc0,0x99,0x58,0xfe,0xda,0xbb,0xff,0xfb,0x8b,0xf5,0x78,0x8d,0xf1,0xc7,
+ 0xfa,0x6c,0x0e,0xbd,0x76,0x8d,0x45,0xfc,0xa8,0x85,0x30,0x94,0xb1,0xbf,0x5c,0x31,
+ 0xcc,0x89,0x02,0x47,0xcd,0x66,0x3e,0x09,0xb3,0xc6,0x05,0x87,0x43,0xe8,0x88,0xbf,
+ 0x16,0xe1,0x23,0x8a,0xe6,0x93,0x68,0x94,0xca,0x23,0x72,0x6e,0x2e,0xe6,0x5d,0xc6,
+ 0x80,0x02,0x7b,0x6f,0xd8,0x14,0x54,0x51,0xd2,0x9b,0xdb,0x32,0x7c,0x35,0x8a,0x58,
+ 0x9f,0x92,0x0c,0x80,0x2b,0xbd,0xc1,0xc8,0xbe,0xf8,0xd9,0x6d,0x5e,0x41,0x7a,0x79,
+ 0x6e,0x08,0xda,0x05,0x88,0x6a,0xac,0x44,0x9f,0x08,0x16,0x22,0xb6,0x73,0xf2,0x07,
+ 0x3e,0x59,0xd6,0x1e,0x08,0x51,0xe4,0x8d,0x39,0x78,0xfa,0xb0,0xe2,0xe6,0x89,0x72,
+ 0x63,0x93,0x41,0x55,0xd9,0xca,0x95,0xd2,0x21,0x8d,0xbd,0xdb,0x42,0x66,0x07,0xb2,
+ 0x8d,0x0f,0xe6,0x84,0x51,0x4c,0xdc,0x9d,0x69,0x16,0x42,0x53,0xc8,0x66,0x6c,0xce,
+ 0xe5,0x2f,0xda,0x2e,0x1b,0xc5,0x07,0x46,0x1c,0x9d,0xa3,0xa1,0x8b,0xd4,0x3c,0xfb,
+ 0x98,0xb7,0x1c,0x91,0x84,0xd0,0xb2,0x5c,0x2d,0x78,0xf6,0xdb,0x73,0xca,0xec,0x33,
+ 0xb9,0x64,0x70,0xa3,0x89,0x07,0x88,0x9f,0xba,0x20,0xbb,0x9f,0xf1,0x1d,0xa1,0x6d,
+ 0x63,0x3a,0xb2,0x30,0x9e,0xcb,0x7f,0xa4,0xa0,0xf1,0x7c,0x9f,0x62,0xae,0x4b,0x49,
+ 0x3d,0x21,0x00,0x1c,0xf8,0xce,0xf9,0x08,0x31,0xa9,0x06,0x76,0x6c,0xb2,0xfe,0x14,
+ 0xd8,0xc7,0xab,0xd0,0x9b,0xf4,0xad,0xec,0x39,0x20,0x1f,0x65,0xaf,0xc5,0x6f,0xe9,
+ 0x71,0xf7,0xca,0x3a,0x5f,0xc8,0x3f,0x67,0x42,0xf4,0x23,0xfc,0xbb,0xee,0xa9,0x67,
+ 0x76,0xc1,0xed,0xbe,0x11,0x2a,0x0c,0x27,0x67,0x4f,0x8b,0xb4,0x25,0x1b,0xb5,0x9f,
+ 0x92,0x64,0xb8,0x64,0xdd,0xa7,0xea,0x34,0x7f,0x0d,0x34,0xc6,0x40,0xcc,0x00,0xcf,
+ 0x55,0x8b,0x9d,0xc9,0xa7,0xc0,0x7b,0xc0,0xc3,0x2d,0x4c,0xbe,0xed,0x64,0x2d,0xfc,
+ 0xa0,0x7d,0x44,0x67,0xaf,0xf0,0x10,0x71,0x2f,0x72,0xf7,0x1f,0x8f,0xd6,0xb3,0x8e,
+ 0x63,0x3e,0x0e,0x69,0xcd,0x5b,0x14,0xd3,0x70,0x70,0x44,0x5d,0xab,0x06,0x62,0x99,
+ 0x20,0xa4,0x09,0xb7,0xd9,0xad,0x60,0x83,0xe6,0x70,0x77,0xa6,0x54,0x3a,0xdd,0x60,
+ 0x31,0xd2,0x81,0x0d,0x88,0x03,0x1b,0x83,0x66,0x00,0xc7,0x27,0xf0,0x19,0x3e,0xd9,
+ 0xbc,0x08,0x07,0xa0,0x68,0x0b,0xda,0xac,0xb3,0x12,0xa0,0x7d,0xc3,0xe1,0xfc,0x38,
+ 0x86,0x30,0x0d,0x07,0x80,0x5a,0x07,0x3f,0x53,0x34,0x48,0x87,0xdc,0x62,0x91,0xe8,
+ 0x1d,0xc3,0xd2,0x3c,0x7b,0x95,0x24,0xae,0xc2,0x04,0x30,0x36,0x38,0x93,0x50,0xf5,
+ 0x90,0xae,0x51,0x7f,0x55,0x10,0xe7,0xb1,0xb3,0x97,0xa9,0xac,0x67,0x2f,0x4a,0x6b,
+ 0x84,0x2a,0xda,0x19,0xc9,0x71,0xac,0x50,0xf5,0xbe,0x43,0x99,0xb7,0xde,0x93,0x50,
+ 0x9d,0x0c,0x83,0x77,0x4f,0x0d,0x7d,0x4c,0xfb,0x08,0xa6,0xb9,0x86,0xcb,0xd5,0x71,
+ 0x61,0xcd,0xcc,0x85,0x79,0x28,0x3a,0x64,0x58,0x71,0xee,0x1e,0x38,0x47,0x48,0x48,
+ 0xa2,0x83,0xb4,0x95,0xea,0x4e,0x01,0x6e,0x87,0xc9,0xa5,0xb3,0x4c,0x93,0x6f,0x09,
+ 0x8e,0x4e,0x04,0xaf,0xae,0x28,0x31,0xc2,0x6b,0x49,0x96,0x9d,0xc8,0xec,0x9f,0xaa,
+ 0xf9,0x49,0x73,0x2a,0x71,0x9b,0xc9,0xce,0xdb,0xa7,0xec,0x81,0xae,0x7f,0x13,0xf6,
+ 0xdf,0xed,0xfb,0xf3,0xcd,0x71,0x76,0x71,0x33,0x9f,0x3d,0x39,0x5f,0xfe,0x42,0x61,
+ 0xcc,0x07,0xf8,0xa0,0x00,0x7b,0xaf,0xb8,0xe1,0x90,0x7a,0xc2,0x3f,0x57,0xad,0x8d,
+ 0x08,0x8a,0x53,0x20,0x29,0x95,0x25,0xf8,0x01,0xcf,0x70,0x7e,0xaa,0x15,0x04,0x61,
+ 0xcd,0xa5,0x92,0x0a,0x4c,0x0a,0x3c,0x46,0x7a,0xea,0x25,0xe6,0xfe,0x25,0xd4,0x56,
+ 0x0b,0xac,0x67,0x9a,0x38,0x0b,0xd2,0x9e,0x5d,0x0b,0xb8,0x2e,0x83,0x5f,0x3d,0xaa,
+ 0xed,0x3b,0x2e,0x1f,0xa9,0x08,0x0e,0x59,0x2a,0xd5,0xc6,0x9e,0xa7,0xea,0x57,0x69,
+ 0x33,0x03,0x3a,0xfc,0x98,0xad,0xa9,0x82,0x68,0xc1,0x32,0x9c,0x60,0xb6,0x5c,0x48,
+ 0xa4,0xdb,0xfe,0xca,0xa4,0xba,0x95,0x45,0x5d,0x69,0xc9,0x79,0xf5,0xdc,0x80,0x82,
+ 0x53,0xcc,0xee,0x2f,0x8a,0xf0,0x0d,0xeb,0x20,0xcf,0xaa,0x99,0xb0,0x15,0x12,0x50,
+ 0x9c,0x35,0xde,0x0c,0x62,0x8c,0x0f,0xd4,0x48,0x4c,0x8f,0x82,0x34,0x8a,0xd5,0x62,
+ 0xbc,0xe2,0x6e,0x3c,0x8f,0xa7,0xf7,0x97,0xd8,0x66,0x89,0x8f,0xe5,0x34,0xb1,0xf5,
+ 0x82,0x82,0x0b,0xc2,0x89,0x7b,0xc0,0x47,0xc5,0x46,0xd8,0x02,0xa5,0x8e,0xb4,0x87,
+ 0x68,0x9c,0x0f,0x23,0xe0,0xc8,0xc9,0xb1,0x01,0x25,0xa9,0x18,0x5c,0x63,0xd9,0x38,
+ 0xbb,0x3e,0xc6,0xe7,0xeb,0xff,0x21,0x81,0x1b,0x16,0xfa,0x6d,0x9e,0x04,0xc7,0x47,
+ 0x40,0xf4,0x61,0xc1,0x0e,0xce,0x42,0x4d,0x50,0x71,0xf9,0xdd,0x8a,0x9e,0x4f,0x6b,
+ 0xe1,0xd9,0x9f,0x14,0xb7,0xeb,0x3a,0x5b,0x63,0x0d,0x83,0xfd,0x4c,0x41,0xa2,0xe3,
+ 0xbd,0x10,0xe0,0xda,0x96,0x07,0x85,0x3e,0x5c,0xd1,0x0c,0x0e,0x6d,0x7b,0x67,0x5d,
+ 0x22,0x39,0x46,0xa4,0xc7,0x9c,0xf0,0xa3,0xae,0xd8,0x01,0x44,0xbc,0x41,0x34,0xf5,
+ 0xd4,0xf3,0x7a,0x17,0x0e,0xc5,0xfd,0x13,0x7d,0xa6,0x1e,0x63,0x29,0xad,0xc8,0x1a,
+ 0x71,0x7d,0x35,0xde,0xfa,0xec,0xa9,0x2e,0xe0,0xdf,0x3d,0x53,0xcb,0xe3,0x85,0xbb,
+ 0x36,0xa0,0x4d,0x5e,0xe0,0xca,0xba,0x2d,0x64,0x12,0xb5,0x98,0x80,0xea,0xd2,0x65,
+ 0xc0,0x06,0xd7,0xa7,0x99,0x58,0x4d,0xac,0xe0,0x3e,0x49,0x14,0x5f,0x46,0xb7,0x89,
+ 0x51,0x18,0xc8,0x8f,0x6a,0x6b,0x72,0xc0,0xdc,0x8e,0x76,0x64,0x63,0x12,0xf2,0xec,
+ 0x52,0x57,0xde,0x81,0xda,0x0b,0x4a,0xa5,0x23,0xa3,0xce,0x60,0x59,0x6f,0x1b,0xc8,
+ 0x53,0x2b,0x52,0x83,0x14,0x89,0xd7,0x2e,0xf2,0x53,0xe9,0xb5,0xf2,0x18,0x6f,0xd6,
+ 0x5b,0x7d,0xaf,0xf4,0x3a,0x0b,0x9c,0x61,0x75,0xa5,0xb1,0xe7,0xdf,0xb3,0x31,0xd0,
+ 0xb9,0x61,0xc3,0x98,0x66,0x31,0xdf,0x07,0x0d,0x6f,0x25,0xf7,0xc7,0x2c,0xf9,0xaf,
+ 0x0f,0x81,0x1f,0x3f,0xed,0x44,0x64,0x13,0x7c,0x89,0x24,0x26,0xfd,0x3f,0xed,0xc3,
+ 0x16,0x93,0x55,0x31,0xfe,0x05,0xbe,0xfc,0x89,0x54,0xff,0xee,0x33,0x23,0x60,0xc9,
+ 0xb5,0x7b,0xec,0x5d,0xce,0x7a,0x1d,0xd2,0x2b,0xfd,0x0a,0x6d,0xc7,0x47,0x07,0x82,
+};
+
+
+/* 317-0034 FD1089B */
+static const UINT8 key_0034[0x2000] =
+{
+ /* data */
+ 0xd4,0xac,0x66,0xc0,0x6a,0xd5,0x81,0x09,0x5d,0xfc,0x8b,0x0b,0x6e,0x1d,0xf0,0xdf,
+ 0x46,0x47,0x58,0x01,0x84,0x60,0xe3,0x34,0xf0,0xef,0x6f,0x32,0x63,0xbf,0x63,0xd9,
+ 0xb0,0xb3,0xaa,0x15,0x18,0x5c,0x93,0x02,0xfa,0x40,0x0a,0x19,0xac,0x66,0x88,0xbd,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xb9,0xb4,0xe5,0xf6,0xf2,0x87,0xe1,0x33,0x37,0xb4,0xc3,0xba,0xa6,0x4f,0xdf,0x6c,
+ 0x59,0x06,0x5d,0x23,0x33,0xa9,0x57,0x11,0x00,0x28,0x3b,0x56,0x59,0x62,0x24,0x61,
+ 0xec,0x93,0xcd,0x4d,0x42,0x76,0x1f,0x0f,0xf3,0x4f,0xc9,0x24,0xd3,0xa5,0x58,0xab,
+ 0x7f,0x93,0x8a,0x3c,0xa4,0x61,0x4d,0xbe,0x73,0x12,0x85,0xc5,0x10,0x9c,0xa7,0xc7,
+ 0x23,0x06,0xf7,0xa6,0x95,0x4e,0x08,0x45,0x7f,0x48,0x20,0x67,0xc7,0xe5,0x1c,0x15,
+ 0xba,0x1f,0xc5,0x19,0x95,0xd2,0x9d,0x42,0x21,0xc0,0xb3,0x4e,0x21,0xb8,0x1d,0x2a,
+ 0xb7,0x6d,0x78,0x08,0x14,0x14,0x5e,0x64,0x16,0x93,0x45,0xd5,0xbd,0x0d,0x97,0xe5,
+ 0xb1,0xce,0xb9,0xe7,0x22,0x79,0xba,0xde,0x8f,0xa9,0x8c,0xfb,0x32,0x80,0xf7,0x90,
+ 0x44,0x42,0x86,0x19,0x44,0x95,0x55,0x2f,0x82,0x73,0x96,0x9a,0x86,0xf1,0x55,0x91,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x74,0x98,0xba,0xcf,0xe0,0x05,0x9d,0xe4,0x53,0xf2,0xef,0x82,0x00,0x6f,0x01,0xf0,
+ 0x37,0x7a,0x4d,0xf9,0x9b,0x81,0x41,0x84,0x8a,0xa5,0x3a,0xf1,0x18,0x1b,0x47,0x52,
+ 0x3b,0xed,0x3a,0xbe,0xb2,0x4d,0x5b,0xb7,0x5d,0xc5,0x2d,0x42,0x03,0x0e,0x3d,0x74,
+ 0xaf,0xb5,0xf0,0x26,0xdb,0xa0,0x54,0x76,0xe3,0x19,0x6e,0xda,0xf3,0x52,0xef,0x7d,
+ 0x5e,0x4a,0xe9,0x0b,0x7a,0x31,0xa7,0x85,0xce,0x09,0xa6,0xee,0xe8,0xbc,0x35,0x5d,
+ 0x04,0x93,0xef,0x2f,0xa6,0x43,0xa6,0x53,0xf9,0xd4,0xed,0xd6,0xab,0x3e,0xc4,0xa6,
+ 0x5a,0xa0,0xcc,0x0c,0x08,0x01,0x33,0xc1,0x09,0x81,0x2e,0xc7,0xe4,0xc8,0xa3,0x8e,
+ 0xfc,0x3e,0xd3,0x73,0xd5,0x78,0x30,0xc4,0x15,0x05,0x63,0x95,0x4b,0x4a,0x55,0xe3,
+ 0xda,0xf8,0x25,0xb7,0x7d,0x06,0xf5,0xa0,0xea,0x70,0xe7,0x0b,0x83,0xa5,0x69,0x7b,
+ 0x4b,0x7a,0xeb,0xc9,0xa1,0x71,0x00,0xa8,0x40,0x65,0x8e,0x47,0x64,0xcf,0x82,0x3e,
+ 0x7b,0x53,0x37,0xa7,0x3c,0x10,0x67,0x21,0xec,0xed,0xac,0xd8,0xe9,0x4c,0x9e,0x07,
+ 0xf4,0xf3,0xa9,0xc3,0x0b,0x21,0x15,0xb9,0x45,0xc7,0xce,0xa9,0x77,0x00,0xc7,0x0d,
+ 0x87,0x2e,0x34,0xda,0xfc,0x7a,0xba,0xa5,0xfb,0xde,0x7f,0x49,0xc8,0x4b,0xbc,0xfb,
+ 0x31,0xf9,0x7d,0xc3,0xf8,0x96,0x61,0xb7,0xbe,0xa0,0x2a,0x3f,0x6a,0xdd,0xc1,0xc2,
+ 0x1d,0xcc,0x4b,0xac,0x07,0x30,0xc3,0x92,0xf2,0x64,0x27,0x84,0x5a,0x69,0xaf,0x8e,
+ 0x7b,0xc4,0x7d,0xb0,0xdf,0xb0,0xeb,0xd3,0x13,0x27,0xd9,0xf4,0x13,0xb9,0x02,0x80,
+ 0x5c,0xe2,0xb2,0xdf,0xdd,0x3d,0x88,0xac,0x3f,0xd4,0xfb,0xa3,0x10,0x3a,0xc4,0xe3,
+ 0x60,0xd1,0xee,0x10,0x06,0x39,0x71,0x1c,0x2a,0xb1,0x6e,0xf0,0xa2,0x74,0xce,0x3e,
+ 0xab,0x3a,0xd3,0x9f,0x5f,0x8f,0x14,0x7c,0x5b,0x4c,0xf9,0x22,0x4a,0x08,0xf8,0x66,
+ 0x2b,0x3b,0x9e,0xa0,0xea,0x3a,0x17,0xde,0x38,0xc5,0x98,0x10,0xe2,0x01,0x3a,0xc3,
+ 0xc4,0xe3,0xc0,0xa4,0xa0,0x68,0x3d,0xdc,0x65,0x11,0x23,0x44,0x90,0x57,0x87,0x6e,
+ 0x38,0x96,0xcc,0xd6,0xa6,0xb5,0x1f,0xa0,0xe3,0x17,0x5a,0x45,0xad,0x3b,0x3b,0xe4,
+ 0x82,0x7e,0xea,0xae,0x70,0xf8,0x92,0x5c,0xad,0xf3,0x23,0xdd,0x09,0xac,0x5d,0xbe,
+ 0x52,0x1f,0x65,0x19,0x1c,0xf1,0xd0,0x55,0x31,0x42,0x5c,0x12,0x21,0x10,0x6d,0xc5,
+ 0xf0,0x27,0x3b,0x8c,0x65,0x8b,0x68,0x7c,0x79,0x29,0x6e,0x40,0x88,0x05,0x90,0x3a,
+ 0x2a,0xbb,0x83,0x20,0xfb,0xb1,0xa5,0x01,0xd0,0x9b,0x16,0x6e,0xdb,0x25,0x5d,0x6d,
+ 0x4e,0x73,0x26,0xb0,0xc3,0x23,0x2b,0x32,0x46,0x7c,0x18,0x30,0xbc,0x17,0x0d,0x5b,
+ 0xb4,0x9a,0x6d,0xef,0x60,0x3f,0x25,0xd5,0x29,0x9f,0x76,0x13,0x5a,0xc4,0x79,0x59,
+ 0xc8,0x46,0x7d,0xb3,0xd6,0xa6,0x57,0xea,0x6f,0x4d,0x8c,0x6b,0x39,0x39,0xe0,0x69,
+ 0xd6,0xdf,0x66,0xdb,0x55,0xd3,0x95,0x99,0xf5,0xfd,0xa9,0x86,0x6c,0xe6,0xbf,0xca,
+ 0xbc,0xcd,0xa1,0x92,0x7d,0xab,0x16,0x03,0x8d,0x62,0x47,0xd2,0x3d,0x0d,0xdd,0xf2,
+ 0xbb,0x78,0xda,0xe9,0xd7,0x79,0x1e,0xb0,0x1a,0x13,0xcb,0x21,0x0b,0x9b,0xe7,0x97,
+ 0x39,0x9c,0x5a,0xfd,0x98,0xda,0x7d,0x67,0xf0,0x25,0xf9,0x83,0x76,0xf2,0xfd,0x3d,
+ 0x39,0x67,0xed,0x1a,0xe8,0x38,0xcd,0x37,0x2b,0x0a,0xa5,0xb7,0xa3,0xde,0xe8,0x3a,
+ 0x90,0x61,0x33,0x1d,0xb3,0x35,0xe2,0x9b,0xcd,0x48,0x3c,0xed,0xf5,0xf6,0xb9,0xdc,
+ 0x57,0x62,0x50,0xce,0xbd,0x37,0x47,0x38,0x3c,0xd6,0xb7,0xd8,0x96,0xe7,0x77,0xc9,
+ 0x7a,0x33,0x10,0x6a,0x0f,0x0d,0xd8,0xe0,0x16,0xc1,0x86,0xb2,0x69,0x6b,0x26,0xc2,
+ 0x10,0x08,0xb8,0x9a,0xc5,0xb5,0x05,0x54,0x7a,0x38,0xe4,0xbd,0x5d,0x62,0xeb,0xc7,
+ 0x0d,0x88,0x13,0x98,0xaa,0x2d,0xcd,0x80,0xf2,0xe6,0x08,0x6e,0x94,0x33,0x05,0x4e,
+ 0x8d,0x4d,0x2e,0x43,0xab,0x5a,0x97,0xf1,0x52,0xa4,0x5c,0xd5,0x76,0x31,0xa0,0xc2,
+ 0x62,0x27,0x18,0xcf,0xe5,0x8c,0x1c,0xaa,0xea,0xc1,0x12,0x74,0x82,0x4d,0xe6,0xb9,
+ 0x95,0xda,0xec,0xf0,0x42,0x7b,0x0b,0xe5,0x2d,0x29,0xa3,0x75,0x77,0xf5,0x52,0xe4,
+ 0x45,0xd1,0xdb,0x2f,0xc0,0xa3,0x06,0x54,0x1b,0x94,0xa3,0xa0,0x47,0x62,0x82,0x54,
+ 0x63,0x8a,0xe3,0x33,0x06,0x30,0xc8,0xe9,0xe9,0x45,0x4f,0x0f,0x59,0xed,0x38,0xe3,
+ 0x66,0xde,0x33,0xa0,0xba,0x84,0xe6,0xd4,0x1f,0x16,0xd7,0xb8,0x95,0xcb,0x11,0x5a,
+ 0xe4,0x4b,0xaa,0x0f,0x93,0x7b,0x11,0x43,0x48,0x91,0xe4,0x0a,0x13,0x60,0xf4,0x05,
+ 0xb3,0xbf,0x3d,0x47,0xec,0xbe,0x11,0x86,0x79,0x4f,0xbf,0xbb,0x4d,0xc2,0x40,0x84,
+ 0xc2,0xa7,0x0b,0x16,0x41,0xc6,0x83,0x89,0xf9,0x8f,0x16,0x48,0xbb,0x8a,0xbe,0x00,
+ 0x65,0x21,0xba,0x12,0x20,0x3e,0x0b,0xab,0xd4,0x20,0x7f,0x76,0x09,0xdc,0xc0,0x34,
+ 0x2a,0x12,0xa5,0x1e,0xc5,0x60,0x60,0xe4,0x69,0xd3,0xda,0x9b,0xeb,0x4d,0x8e,0xb6,
+ 0x45,0x0e,0xf5,0xe2,0x0f,0x7c,0x4f,0x5a,0x61,0xc2,0x95,0x09,0xeb,0x0c,0x07,0x95,
+ 0x79,0xec,0xe9,0x2a,0x87,0x02,0x7a,0x5b,0xad,0xb4,0xe3,0xe4,0x3e,0x8a,0xbb,0x32,
+ 0x23,0x32,0x42,0xf4,0x6f,0xed,0xb9,0x7d,0xe2,0xdd,0xce,0xd9,0xc8,0x6f,0x04,0x95,
+ 0x76,0xb1,0x8d,0xd1,0x0b,0xc5,0x34,0xd9,0xef,0xca,0x2d,0x05,0x5c,0x0c,0x07,0x9e,
+ 0x23,0xd8,0xac,0x7c,0x60,0x37,0x61,0xe6,0x4c,0x89,0xd3,0x21,0x52,0xc5,0x79,0x9c,
+ 0x4b,0x6d,0x63,0x55,0xc3,0x3c,0xdb,0x43,0x7b,0xf6,0xb6,0xe0,0x23,0xbb,0xe1,0x44,
+ 0x6f,0x88,0x04,0xf1,0x07,0xdc,0xe6,0xd3,0xea,0x65,0x2f,0x92,0xbb,0x76,0x56,0x7a,
+ 0x5a,0x16,0xe2,0xea,0xb4,0xf7,0xd3,0xb8,0xa5,0x4a,0x5f,0x27,0xc7,0xf8,0x77,0xb5,
+ 0x42,0x55,0x94,0x88,0x11,0x0b,0xc9,0x7b,0xc8,0xe4,0x14,0xbf,0xcd,0xcb,0x0e,0x01,
+ 0x70,0x3a,0x82,0x9a,0x8b,0xa8,0x9b,0xe5,0xd5,0x4d,0x9e,0xf9,0x81,0xa2,0xcf,0xb9,
+ 0x97,0xea,0x05,0xeb,0x8d,0xc6,0x1f,0xc5,0x42,0x1f,0x13,0x8f,0xa0,0xb7,0x5b,0x3b,
+ 0x8c,0x42,0x29,0x41,0x70,0x94,0x5d,0x7a,0x55,0x2e,0x9c,0x4b,0xac,0x05,0x26,0x1d,
+ 0x5d,0xc1,0x7f,0xef,0x40,0xd0,0xb5,0xb9,0x25,0x4c,0x92,0x6e,0x4a,0xca,0x8d,0xcf,
+ 0x8a,0x46,0xba,0x0d,0x10,0xa0,0x8d,0x92,0xf5,0x70,0x7b,0x83,0xea,0x99,0x4e,0x33,
+ 0x83,0x4e,0x26,0x44,0xba,0xf0,0x42,0x51,0xb8,0x51,0x88,0x5a,0x3b,0xd3,0x3e,0xd9,
+ 0xb4,0xee,0x0e,0x9a,0xa7,0xe8,0x44,0x14,0xc0,0x51,0x6e,0x4a,0x4d,0xfa,0x4e,0x28,
+ 0xfd,0x73,0x2b,0x77,0x51,0xe1,0x41,0x94,0x72,0xcd,0x32,0xec,0xd1,0x8f,0xba,0x24,
+ 0xd4,0x53,0xaf,0x79,0xd2,0xaa,0x22,0xe6,0x12,0xb8,0x15,0x83,0x80,0xb2,0xd0,0x38,
+ 0x8d,0xcd,0x33,0xe7,0x10,0x1a,0x84,0x09,0x74,0xce,0x53,0xc6,0xc4,0xea,0xd7,0xdb,
+ 0xeb,0x07,0xab,0xbb,0x9e,0x69,0x37,0x50,0x40,0x93,0x7c,0xc5,0x6b,0x8b,0xa0,0x03,
+ 0x74,0x74,0x58,0x13,0x40,0x4f,0x05,0x46,0xce,0xc0,0x91,0x60,0xf9,0x26,0x8a,0x0b,
+ 0x78,0x95,0x7e,0x16,0xd8,0x37,0x00,0x1e,0x94,0x9a,0x5e,0xb0,0xaa,0x18,0x0a,0xaf,
+ 0x35,0x33,0xa7,0x1e,0xe1,0x58,0xd9,0x30,0x08,0xdf,0xd6,0x42,0xc0,0x5f,0x31,0xce,
+ 0x7d,0x20,0x97,0x1c,0x74,0x08,0x15,0x82,0x24,0xa6,0x37,0xad,0xa7,0x53,0xc7,0x41,
+ 0x3c,0xb6,0x4c,0x80,0x74,0x1d,0x19,0xbc,0xb3,0xac,0x94,0x3d,0xeb,0xa8,0xf5,0x38,
+ 0xed,0x50,0xc4,0xd7,0xe1,0x1a,0xbf,0xc9,0x8c,0x75,0x5b,0x14,0xa1,0x88,0x6f,0x75,
+ 0x2d,0x28,0xb3,0x9c,0xd8,0x2a,0x33,0x3a,0x8a,0x89,0x2a,0x85,0xd3,0xf9,0x7e,0xc1,
+ 0x0b,0xe9,0x17,0x80,0x40,0x97,0xab,0x98,0x4d,0x8f,0xf4,0x7b,0x6b,0xf5,0xd7,0x67,
+ 0x72,0x60,0x25,0x9e,0x9e,0x05,0x03,0xb8,0x03,0xa6,0xde,0x43,0xef,0x92,0x2a,0x61,
+ 0x91,0x6d,0x2e,0x47,0x10,0xac,0x70,0x77,0x6e,0xa5,0xb8,0x69,0x4f,0x0d,0x10,0x24,
+ 0xe1,0x0e,0x6d,0xa5,0xfb,0xf4,0xb6,0x84,0xf5,0xdc,0x5c,0x17,0x8e,0x9d,0x79,0x30,
+ 0xaa,0x1c,0x5d,0x1f,0x81,0xc6,0xe4,0x3d,0x86,0x9b,0x59,0x57,0x0b,0x51,0x6d,0xd9,
+ 0x8d,0xb8,0x30,0xa7,0xa3,0x44,0x24,0xb7,0x86,0xe1,0x93,0x43,0x00,0x5d,0x98,0xf7,
+ 0x02,0x41,0xe7,0xe3,0x3d,0xfd,0x73,0x88,0x69,0x1f,0x77,0x7b,0x1a,0xc2,0xa5,0xd5,
+ 0x91,0xc9,0x14,0xdc,0xee,0x65,0x68,0x6b,0x79,0x7b,0x7b,0x4a,0x3e,0xf7,0xa6,0x05,
+ 0x46,0xbb,0x19,0x72,0x37,0x05,0xcd,0x79,0x13,0x18,0x7c,0x61,0xeb,0x59,0xf1,0x46,
+ 0xee,0x5c,0x9a,0xbc,0xc1,0xb8,0xda,0x3c,0x77,0xb4,0xd3,0x9d,0x94,0xb2,0x7c,0x7a,
+ 0x30,0x81,0x0d,0x2e,0xbe,0x0e,0x7f,0x17,0x26,0x69,0xd5,0x4a,0xa1,0xdb,0x12,0x86,
+ 0xa3,0x65,0x9a,0xdb,0x3a,0xe6,0x55,0xc0,0x65,0xda,0x86,0xb5,0x03,0xef,0x52,0x53,
+ 0xb7,0xcb,0x4e,0x98,0x7c,0xf6,0x38,0x3c,0xa6,0x28,0x1b,0x0f,0x14,0xd8,0x1e,0xa9,
+ 0x3c,0x6d,0x4d,0x5c,0x72,0xbf,0xb2,0x32,0xb5,0x14,0x88,0x21,0x54,0x1f,0x61,0x4a,
+ 0x20,0x53,0xf7,0x48,0xf9,0x4a,0x66,0xe7,0xfc,0x21,0x06,0x72,0x15,0x2d,0xdd,0x5c,
+ 0x73,0x2e,0x48,0x7d,0x13,0xab,0xe3,0x62,0x51,0xe1,0xd0,0x9c,0xbc,0xaf,0x9e,0xc0,
+ 0x6a,0xf6,0xdb,0x64,0x38,0x21,0xdf,0x92,0x2f,0x07,0xa8,0x6c,0x37,0xfc,0x4b,0x3a,
+ 0xca,0x06,0x1e,0x2a,0x13,0x40,0xcd,0x00,0x11,0x7d,0xa0,0x51,0xca,0x36,0x8e,0x25,
+ 0x11,0xd5,0x48,0x0f,0xa4,0xdc,0xcb,0xdb,0xfd,0x17,0x71,0x75,0x95,0xc2,0x40,0xbc,
+ 0xce,0x9c,0x59,0xd1,0x21,0x3c,0x84,0xe6,0x6c,0x95,0xa3,0xd4,0x8c,0xcf,0x89,0xa8,
+ 0x6e,0xf3,0xed,0xb4,0xa7,0x6b,0xfd,0x1c,0xa1,0x02,0x1a,0x38,0x52,0x33,0x4e,0xd2,
+ 0x95,0x6d,0x9d,0x5f,0x44,0x5e,0xfc,0x2c,0x10,0x73,0xa8,0xc9,0x32,0xb9,0xe5,0xbb,
+ 0x74,0xae,0xb9,0xba,0x38,0x6c,0x29,0x06,0x19,0x81,0x04,0xc3,0x4a,0x3d,0x4d,0xb0,
+ 0x94,0x64,0x66,0x8c,0xc4,0xd5,0xdc,0x16,0x62,0x80,0x67,0x2e,0xc6,0x30,0x9a,0xa2,
+ 0xbe,0x0f,0x5e,0xce,0x83,0x67,0xe5,0x2e,0x2e,0x60,0x59,0x64,0x86,0x59,0x5f,0x77,
+ 0x1f,0xcc,0xa8,0xa2,0x64,0x38,0xfa,0xb2,0x55,0x5d,0xf4,0x5f,0x27,0xfe,0x46,0xd7,
+ 0x92,0x6d,0x2e,0xc8,0xf4,0xe5,0xcc,0x7a,0x94,0xab,0x2a,0xe2,0xaa,0x63,0xe0,0x4e,
+ 0x12,0x5b,0xf5,0x86,0xee,0x80,0xc6,0x33,0xc9,0x6f,0xfb,0x1e,0xbc,0xb1,0xcf,0xd2,
+ 0x2c,0x23,0xd2,0x2b,0xb9,0xd2,0x56,0xf3,0x18,0xa7,0x38,0x4f,0x5b,0xcc,0xb2,0xa5,
+ 0xe6,0x14,0x2b,0x10,0xcb,0x7f,0x0d,0xab,0x7e,0x64,0x4d,0xa7,0xa0,0xa2,0x7b,0xfd,
+ 0xdf,0xba,0x9d,0x3a,0xbb,0x60,0x95,0xde,0xd0,0xab,0x8d,0x0b,0x7b,0x3a,0xf3,0xcb,
+ 0xb1,0x9c,0x1c,0x62,0x44,0xba,0x17,0xd1,0xaf,0x25,0xba,0x95,0x9e,0xc9,0xdd,0xd2,
+ 0x69,0x2c,0xab,0x20,0x53,0x6b,0x79,0xe8,0x66,0x45,0xe1,0x73,0x8d,0x6f,0xba,0x9f,
+ 0x98,0x67,0x88,0x08,0x00,0x0f,0x9a,0xe1,0xa4,0x5c,0x87,0xb7,0x6b,0x2f,0xb2,0x59,
+ 0x1c,0xe9,0x91,0x9c,0xd8,0xa2,0x55,0xdb,0x81,0xf1,0x90,0xec,0x6f,0x28,0x39,0x69,
+ 0x4f,0x58,0x06,0x91,0x91,0xcd,0x9b,0xea,0x78,0x56,0x40,0x4a,0x7b,0x2a,0x7e,0x7d,
+ 0xfb,0x19,0x6d,0x16,0x0e,0x80,0x47,0x2e,0x4d,0x4d,0xa9,0x75,0xcc,0x72,0x93,0x13,
+ 0x6d,0x80,0x6f,0xdc,0xb6,0x4d,0x9a,0x07,0x75,0xbe,0xdc,0x30,0x93,0x3d,0x55,0x54,
+ 0x2a,0x21,0x06,0x09,0x87,0x81,0xce,0x70,0xc4,0xd2,0x44,0x50,0x92,0xa5,0x35,0x2e,
+ 0x7c,0xe7,0x20,0x6a,0xb7,0x70,0x88,0x6c,0xc0,0x9c,0x0a,0xd4,0x71,0xa8,0x3a,0x65,
+ 0xfd,0xcc,0xa8,0x90,0x40,0x1d,0x74,0xcb,0x51,0x84,0x30,0x5b,0xb3,0xc5,0xc1,0xa8,
+ 0xbd,0x09,0x50,0x0f,0x30,0x91,0x5a,0x37,0x83,0x14,0x19,0x30,0xd5,0xea,0x0c,0x96,
+ 0xf9,0x88,0xad,0xda,0x17,0xfb,0x9a,0xca,0x11,0x1b,0xee,0x7e,0x0c,0x5c,0x7a,0x92,
+ 0x6b,0xc5,0x75,0x73,0x27,0xa1,0xb5,0xee,0xdb,0xb1,0xb9,0x29,0xf7,0x76,0x56,0xe9,
+ 0x34,0xbb,0x33,0x4b,0xc4,0x0e,0x47,0xac,0x56,0xa8,0x3b,0x45,0xdf,0xea,0x5c,0x56,
+ 0xad,0x39,0xde,0xae,0x06,0x36,0x4f,0x77,0x9a,0x4d,0xdc,0x97,0xcf,0x3a,0x30,0x0c,
+ 0xbe,0x95,0x37,0x67,0x03,0xa5,0x3d,0x30,0xa7,0xbf,0x86,0xa1,0x5a,0x61,0x09,0x76,
+ 0x7d,0x9e,0xb9,0x8e,0x19,0xe8,0x6b,0xde,0xfe,0x47,0xd9,0x91,0xa0,0xb9,0xba,0xc0,
+ 0x01,0x32,0xa4,0x85,0x0a,0x52,0xdf,0x58,0xc0,0x90,0x2a,0xab,0xf1,0xc3,0xf6,0x9c,
+ 0xb9,0x5e,0x11,0xfc,0xe1,0xf6,0xda,0x71,0x73,0x1e,0xd1,0xdb,0x54,0x19,0x75,0x2e,
+ 0xe8,0xfe,0x80,0x25,0xe6,0x16,0xa2,0xe5,0xd6,0x78,0xf2,0x95,0x10,0x2f,0x89,0x90,
+ 0xe9,0x06,0xdb,0x7b,0xc2,0x33,0xa1,0xc8,0x66,0x38,0x13,0xe6,0x13,0x18,0xb9,0x2e,
+ 0xda,0x4a,0xfe,0x3e,0x45,0x16,0x59,0x8b,0x61,0x2b,0x1f,0x2f,0xa6,0xa1,0xba,0x9c,
+ 0x36,0xb0,0x5e,0xa9,0x31,0xf6,0xb7,0xb2,0x32,0x20,0x36,0x4c,0x4d,0x69,0xdb,0xc0,
+ 0x4f,0x28,0x62,0x58,0x45,0x03,0xe8,0xd8,0x0e,0x21,0xd1,0xdd,0x2f,0x39,0x2c,0x76,
+ 0x3d,0x99,0x27,0x3b,0xc2,0x99,0x02,0x36,0x91,0xe7,0xdf,0x73,0x1d,0xda,0x37,0x0c,
+ 0x88,0xd6,0xc6,0xbe,0x77,0x25,0x8a,0x8d,0xdb,0x17,0xfd,0xa7,0xb4,0xad,0x20,0x56,
+ 0x80,0xf4,0xb3,0xc9,0x80,0xa3,0xf8,0x9e,0x86,0x9f,0x0c,0x2c,0x67,0xb5,0x82,0x34,
+ 0xf9,0x4a,0x9f,0x3e,0x5b,0x0c,0x68,0xf7,0x92,0xdc,0x28,0x68,0x19,0x37,0xd1,0xcc,
+ 0x66,0x42,0x04,0x53,0x4e,0xa4,0x87,0x17,0xdf,0x83,0x59,0xd4,0x26,0x91,0x54,0xf9,
+ 0x13,0x01,0x37,0xeb,0x52,0x88,0xd0,0x73,0xe2,0x7a,0xde,0x12,0x8e,0x13,0x8b,0xd8,
+ 0xd4,0x38,0x40,0xd3,0xe5,0x56,0x9e,0x80,0x59,0x50,0xbe,0x25,0x5d,0x34,0x61,0x8f,
+ 0xe3,0x79,0xad,0xcd,0xcd,0x79,0x2d,0x20,0x18,0xfd,0xe1,0xb4,0xcf,0x02,0x5c,0x96,
+ 0x63,0xa4,0x2d,0xea,0xa3,0x36,0xb7,0x42,0x08,0x92,0x76,0xc6,0x77,0x18,0x2d,0x88,
+ 0x37,0x10,0xe0,0xcb,0xab,0x49,0xdc,0xa6,0x9f,0xf5,0x15,0x84,0x0e,0x4a,0xfe,0x79,
+ 0x12,0xe0,0xbc,0xf9,0x1f,0x0d,0x7b,0x30,0x89,0x62,0x30,0x49,0x66,0xc4,0xb5,0x3f,
+ 0xfc,0x8e,0x03,0x69,0x26,0x26,0xe1,0x23,0xaf,0xdc,0x42,0xf8,0x64,0x81,0x7e,0xf5,
+ 0xc3,0x42,0xac,0xd6,0x3f,0xb5,0x88,0xe2,0x6e,0x0c,0xf7,0xd6,0x6a,0xa2,0x3d,0x22,
+ 0x48,0xdf,0x8b,0x74,0xe4,0x8c,0x2a,0xec,0x33,0x18,0x70,0xbd,0x5e,0x64,0x2a,0xe7,
+ 0xd8,0x43,0x7b,0xf4,0xe3,0xf3,0xaf,0x60,0xe2,0x43,0x04,0xe1,0x71,0x99,0x2c,0x20,
+ 0xa8,0x7f,0x51,0xf5,0x0d,0x4d,0x23,0x5b,0x31,0xa9,0x33,0x64,0xec,0xbd,0xf7,0x99,
+ 0x6f,0x01,0xcf,0xfe,0xd3,0xca,0x10,0x3e,0xa5,0x74,0x5c,0x91,0xdf,0x18,0xfb,0xf4,
+ 0xcf,0x30,0xde,0x31,0xc1,0x88,0x9a,0x0a,0x19,0xa3,0x8f,0x30,0xa8,0xa4,0xf9,0x0c,
+ 0xdf,0xef,0x27,0xc9,0x59,0x5a,0x42,0x72,0xad,0x48,0x44,0x44,0x99,0x17,0xf4,0x37,
+ 0xb9,0x22,0x0d,0xcc,0xc5,0x16,0xca,0xec,0x71,0x81,0x87,0x22,0x01,0xe9,0xcc,0x27,
+ 0xac,0x52,0x6a,0x04,0xa0,0x25,0x00,0x57,0x5a,0x53,0xec,0xd3,0xed,0xdd,0x39,0x6c,
+ 0x9c,0x6b,0xb3,0x88,0x13,0xf8,0x21,0x86,0x85,0x6d,0x6b,0x72,0x8f,0xfe,0x2a,0x68,
+ 0x98,0x2c,0x62,0x12,0x0f,0x54,0x54,0xb4,0xd7,0xbd,0x99,0xac,0x15,0x47,0xe1,0x0a,
+ 0x02,0x7f,0x46,0x2f,0xdb,0x2b,0xb4,0xe0,0x83,0x02,0x30,0x1a,0x7d,0x71,0x21,0x83,
+ 0xd3,0x2f,0x80,0x84,0x66,0x67,0xe2,0x38,0x3f,0x52,0x01,0x6f,0xb1,0xfa,0x5c,0x0e,
+ 0xa3,0x28,0x47,0x47,0x4c,0xfd,0xe8,0x6b,0x7e,0xcc,0x98,0xa6,0x8e,0x13,0x08,0x02,
+ 0xa2,0x54,0x69,0x77,0x45,0xa1,0x7f,0x7c,0x6c,0x28,0x55,0x8d,0x64,0xa9,0x7c,0xd3,
+ 0xf9,0xbe,0x59,0xbe,0x69,0xec,0x1d,0x24,0x88,0xcc,0xe5,0x44,0x02,0xb9,0xab,0xf6,
+ 0x4f,0xa4,0x67,0xca,0x26,0xa2,0xa6,0x07,0x78,0x13,0x40,0xee,0x5b,0xcb,0x6d,0xf0,
+ 0xf2,0x48,0xae,0xdb,0x28,0x2a,0x64,0x3d,0x53,0x54,0x2e,0x7f,0x0b,0xda,0x43,0xce,
+ 0x07,0xd2,0xb3,0x48,0x8b,0x72,0xe1,0x0e,0x9f,0x98,0xe1,0xc6,0x36,0x4e,0xdc,0xac,
+ 0xbb,0x00,0x1a,0x50,0xd1,0xca,0xfa,0x74,0x79,0xe1,0x6b,0xa6,0xc8,0xdd,0xd0,0x5a,
+ 0x65,0x1d,0x9f,0x06,0xb8,0x90,0x66,0x9f,0xcf,0x2a,0x96,0x59,0x61,0x5b,0xa6,0xc5,
+ 0xbe,0xda,0x39,0x30,0x3c,0x06,0x44,0xb4,0x82,0x0d,0xd7,0x83,0xc1,0xec,0x04,0xca,
+ 0x85,0x52,0xe2,0xca,0x5c,0xa3,0xc3,0xab,0x0f,0xf9,0x1b,0xe0,0x9d,0x6f,0x84,0xbf,
+ 0x59,0xfe,0x0d,0x2d,0x17,0x6c,0x67,0x24,0x34,0x6c,0x32,0x78,0xbb,0x00,0x5b,0xad,
+ 0xa0,0x66,0xb9,0xa8,0xfe,0x23,0x4e,0xb4,0xfb,0x95,0x93,0x81,0x2e,0xac,0x4c,0xe0,
+ 0xaf,0xee,0x69,0x9a,0x3b,0x13,0x64,0xbd,0xb2,0x1d,0xb7,0x87,0xf2,0x9b,0x67,0xca,
+ 0x2b,0x92,0x96,0xbe,0xc1,0x9a,0x0c,0xc8,0xf6,0xdc,0xb2,0xf7,0x91,0x1e,0x33,0x30,
+ 0x16,0xf0,0xf0,0xc1,0x4c,0x76,0xc3,0x02,0x2c,0x98,0xc4,0xd7,0xf7,0x5b,0xd9,0xaa,
+ 0xca,0x1d,0xa7,0x70,0x4f,0xd2,0x0a,0xc9,0x3e,0x49,0xf6,0x67,0xa6,0xe6,0xb6,0x67,
+ 0x26,0xef,0xbf,0x10,0x04,0x10,0xed,0xd9,0x2a,0x38,0x6a,0xd0,0x0e,0x1f,0x3e,0xb5,
+ 0x95,0xd9,0xbc,0xc7,0xf2,0xce,0x8e,0xc5,0x72,0x2b,0xdf,0x83,0x85,0x35,0xa5,0x4d,
+ 0x90,0xde,0x8b,0x91,0x65,0x3a,0xdf,0xdb,0x9d,0xc9,0xbb,0x8c,0xea,0x34,0xac,0xb0,
+ 0x3f,0x2a,0xb8,0xc5,0x15,0x0d,0x22,0x26,0xbc,0x9b,0x65,0x74,0x55,0xc1,0xd5,0x7a,
+ 0x7d,0x7a,0x88,0x0e,0xba,0x16,0xc7,0x4b,0x8f,0x02,0x5d,0x34,0x2c,0x3b,0x99,0x03,
+ 0xe5,0x37,0x62,0xf3,0x39,0x7c,0x29,0x2f,0x44,0x0c,0xe4,0x4c,0x53,0x7a,0xaa,0x31,
+ 0x8d,0x55,0x0a,0x8f,0xf4,0x78,0x29,0xa8,0x00,0x48,0x9a,0xfc,0x54,0xb7,0xc8,0x53,
+ 0xcd,0x2c,0x10,0x77,0xdc,0x4d,0xc4,0x28,0x28,0xab,0x25,0x6b,0x54,0x4c,0xce,0xe4,
+ 0x93,0x78,0xae,0x26,0x00,0x4d,0x29,0xc5,0x8b,0xd5,0xd3,0xd3,0x97,0xb6,0x40,0x60,
+ 0xd2,0xd0,0xed,0xfd,0x87,0xee,0x58,0x59,0x64,0xfa,0x4d,0x93,0x2e,0xe7,0x63,0x80,
+ 0x8e,0x0d,0xa3,0xab,0xb2,0x6e,0xc7,0xc7,0xda,0x98,0xf1,0xcc,0x40,0x18,0xd3,0xfa,
+ 0xac,0x07,0x96,0x6c,0xd9,0x04,0x9c,0x5c,0x22,0x2e,0x5a,0xb8,0xd4,0x83,0x0c,0xae,
+ 0x60,0xdd,0xf2,0xc0,0x12,0xf1,0xdb,0xac,0x5a,0xba,0xb2,0x69,0x24,0xa4,0xad,0xf8,
+ 0x82,0xdd,0xe1,0xf1,0x02,0xcc,0x62,0xd8,0x87,0xa0,0x62,0xb0,0x0e,0x3d,0x55,0xf2,
+ 0x51,0x15,0xc5,0xbb,0x29,0xda,0xd9,0x75,0xbf,0x37,0x7b,0x66,0xe5,0xba,0xf1,0x54,
+ 0x47,0xbe,0x22,0x93,0xb6,0x7a,0x8a,0x26,0x47,0xd2,0xc8,0x8d,0x8f,0x35,0x0e,0xbd,
+ 0xef,0xa3,0xf6,0xeb,0x4f,0x7a,0xf1,0xa3,0x45,0x66,0x68,0x7e,0x47,0xd8,0x42,0xe5,
+ 0x4f,0xd0,0x20,0x22,0x93,0x86,0x5c,0x7c,0xc2,0xb2,0xee,0x71,0xf6,0x77,0x42,0xa9,
+ 0x80,0x1c,0xc7,0xca,0xcc,0x92,0xd0,0x0a,0xbb,0xbd,0xd3,0x59,0x70,0x71,0x0e,0x0e,
+ 0x15,0xcd,0x22,0x71,0xe2,0x93,0x33,0xcf,0x31,0x5e,0xb5,0xef,0xe4,0xdd,0x6f,0x5e,
+ 0x09,0xf7,0x2a,0xbb,0x7a,0xdb,0x82,0x7f,0xd1,0xfb,0x48,0xed,0xc7,0xc3,0xe3,0xa8,
+ 0xb7,0xa7,0xc8,0x34,0x88,0x7f,0xc2,0x4a,0xef,0xae,0xe2,0x0b,0xf4,0x79,0x1c,0xa0,
+ 0xd5,0x4e,0xe1,0x40,0x10,0x39,0x64,0x1e,0xc9,0x1d,0x33,0x16,0x12,0x58,0x80,0x7f,
+ 0xb7,0xe3,0xcc,0xc6,0xa9,0x91,0x6f,0x35,0xec,0xcb,0x8f,0x8b,0xcb,0xcb,0x2d,0x8a,
+ 0x5f,0x1f,0xdc,0xdd,0xca,0xe1,0xc9,0x67,0xd3,0xcf,0x5b,0xd3,0x06,0x0a,0x99,0x42,
+ 0x07,0x16,0x06,0x4d,0x11,0x01,0x99,0x59,0x40,0x13,0x0d,0x60,0x7d,0x74,0x7e,0x95,
+ 0xf3,0xeb,0x2d,0xae,0x78,0x0e,0x28,0x62,0xcd,0x84,0xd1,0xa1,0x28,0xf8,0xfc,0xb9,
+ 0x4d,0x74,0xd9,0x93,0x7d,0x12,0xcb,0x4c,0xa7,0xeb,0x71,0xab,0x99,0xae,0x59,0x89,
+ 0x7c,0x49,0x27,0xab,0x07,0xf1,0x21,0xe1,0x94,0x4c,0x7a,0x73,0x7b,0xbb,0x39,0x88,
+ 0xae,0xf8,0xf3,0x33,0x25,0x32,0xf8,0x21,0x41,0xb4,0xda,0x1d,0x85,0x0d,0xc6,0x0e,
+ 0x88,0x97,0x26,0xf5,0xaf,0xf4,0x51,0x5d,0x57,0x6a,0x06,0xc3,0x7e,0x01,0x6b,0x8f,
+ 0xf8,0xd5,0x3c,0x70,0xaa,0x2c,0xac,0x9c,0xf6,0x47,0x50,0x26,0x90,0xab,0xb4,0x03,
+ 0xf1,0x06,0xdc,0x03,0xa2,0x61,0x98,0xe6,0x7b,0xee,0x84,0x20,0x56,0x7b,0x67,0x82,
+ 0x97,0x75,0xe7,0x7b,0x64,0x21,0x21,0x7f,0xaa,0xd4,0x7f,0x3d,0x7c,0xed,0x8d,0x88,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+ /* opcodes */
+ 0x32,0x03,0x52,0xb4,0x6f,0x93,0xf2,0x6e,0xdb,0x2e,0x43,0xe9,0x15,0x0c,0xcf,0x38,
+ 0x3b,0x1a,0xce,0xdc,0x62,0x0a,0x80,0xaf,0x12,0x6f,0x9d,0x56,0xb8,0x04,0xd5,0x86,
+ 0x29,0x55,0x2e,0xd8,0xec,0xf0,0xab,0xb3,0x4c,0xa5,0xe8,0x0e,0x0f,0x33,0xec,0x81,
+ 0x44,0xaf,0x75,0x08,0xfd,0x18,0x66,0xd2,0x57,0xa1,0xd3,0xcd,0xf8,0xb4,0x9a,0x77,
+ 0xed,0x0d,0x90,0xe9,0xf6,0xaa,0x87,0xc2,0x04,0xfb,0xd6,0xd8,0xe8,0x82,0xd1,0x7f,
+ 0x35,0xad,0x99,0xfc,0xae,0x29,0x9a,0x0d,0x43,0x89,0x4d,0x0a,0x12,0x35,0xdf,0x49,
+ 0x3c,0x0a,0x6a,0x61,0xc2,0xd5,0xba,0x8a,0x31,0xb5,0xb6,0x2d,0x89,0xf9,0xa7,0x01,
+ 0xb1,0x9e,0x09,0x11,0x82,0xac,0x2d,0x0e,0x99,0xa1,0xb8,0xfb,0x64,0xac,0xf4,0xe2,
+ 0x37,0x62,0x90,0x66,0x90,0x14,0x99,0xbd,0x6a,0xb8,0x24,0xa6,0xc6,0x26,0x0c,0x9e,
+ 0x1b,0x55,0x7f,0xb7,0xe0,0x8c,0xaa,0x28,0x76,0x77,0xb4,0xb4,0xd3,0xcb,0xf6,0x18,
+ 0xbc,0x34,0x6c,0x93,0xd9,0x28,0x1d,0xba,0x95,0xcc,0x6d,0xe2,0xa3,0x61,0x0a,0xa4,
+ 0xba,0x71,0x9d,0x01,0xdb,0x70,0x87,0xdb,0xf2,0x4b,0xd0,0x3a,0x73,0x0f,0x02,0x67,
+ 0xc8,0xfd,0xdc,0x2a,0x04,0x61,0xd9,0x0d,0x34,0x76,0x8b,0x01,0x97,0x9d,0x02,0xab,
+ 0x47,0xe3,0x0f,0x8c,0x42,0x30,0xe0,0xc1,0xed,0xd3,0x0a,0x2a,0xc2,0x9c,0x0a,0x3b,
+ 0x47,0x7d,0x1a,0xc1,0xac,0x84,0x7a,0xed,0xb8,0x5f,0xe1,0xcb,0xc3,0x5d,0xe9,0x81,
+ 0xc8,0x60,0x73,0xfa,0xce,0x98,0x20,0x85,0xbf,0x3e,0xe5,0x46,0x43,0x07,0x07,0xc3,
+ 0xbe,0x62,0x93,0x29,0xe4,0x0b,0xfe,0xd4,0xd4,0xe3,0x54,0xab,0x78,0xcd,0x91,0x6a,
+ 0xb7,0xa0,0xec,0x00,0x14,0x12,0xba,0xe7,0x64,0xf3,0x78,0x2b,0x02,0x61,0xa4,0x2f,
+ 0x00,0x79,0x41,0x0d,0x10,0xde,0x0b,0xb4,0x3c,0x98,0x0f,0xae,0xf1,0xd0,0xbc,0x65,
+ 0xb9,0x4d,0xdf,0x0a,0x10,0x4f,0x7a,0xa8,0x1b,0xdc,0x8d,0xec,0x9e,0x57,0xcc,0x41,
+ 0x5f,0x87,0xc5,0x3a,0x39,0x9c,0xba,0xe7,0x57,0x82,0x30,0x76,0x76,0x63,0x4a,0xdf,
+ 0xe1,0xc8,0x7c,0xb6,0xc2,0x2d,0x6b,0x59,0x19,0x14,0xf7,0x62,0xdb,0xb6,0x52,0x93,
+ 0x03,0x16,0xba,0x3b,0xe4,0xe1,0x58,0xfc,0x16,0x4c,0xa7,0x3e,0xc6,0xf1,0xc6,0x96,
+ 0xd1,0x20,0x75,0xdc,0x4e,0x52,0x0a,0x04,0xe6,0x73,0x65,0x82,0x19,0x4e,0xd4,0x01,
+ 0xd6,0x2e,0x77,0xc7,0x27,0xd2,0x40,0x8d,0xb5,0x14,0x60,0x31,0x9e,0x3a,0x4d,0xe8,
+ 0x81,0xf6,0x32,0x65,0xd3,0x9c,0xfe,0x37,0x6b,0x5d,0x13,0xac,0xa9,0xc3,0x6d,0x76,
+ 0xba,0x6c,0xac,0x15,0x2c,0x09,0xfe,0x5d,0x77,0x68,0xf4,0xcb,0x1b,0xbb,0x43,0x1b,
+ 0x05,0xd6,0x1c,0xcd,0xed,0x80,0xbb,0x7b,0x40,0x1f,0x52,0xe1,0x39,0xbf,0x3e,0x21,
+ 0x17,0xf3,0x05,0x9e,0x42,0xb9,0x13,0x78,0xa7,0xb5,0xd8,0xbb,0x62,0x41,0x83,0xf2,
+ 0x49,0x05,0xae,0xc7,0x5f,0x14,0x6b,0xe7,0x04,0xf0,0x9c,0x2d,0x7a,0x01,0x16,0x78,
+ 0xaf,0xad,0x0b,0xdf,0x2d,0x48,0x26,0xa1,0xf6,0x4d,0x1f,0x88,0x54,0xe5,0x31,0xb5,
+ 0xd1,0xb9,0x01,0x6a,0x90,0xa4,0x16,0x38,0x0f,0x96,0xa8,0xfc,0x0e,0xe9,0x3c,0x87,
+ 0x4b,0x17,0x31,0x53,0x39,0x8d,0xca,0x3c,0x44,0xbf,0x3e,0x3d,0x0a,0xe9,0x83,0xed,
+ 0x0f,0xa0,0xc1,0x75,0x0f,0xe3,0xf8,0xac,0x49,0xbf,0x5e,0x71,0xce,0xb5,0xb6,0x6d,
+ 0xa4,0xa3,0x8a,0x11,0xf0,0xd5,0x7c,0x76,0x40,0x7e,0xca,0x02,0xce,0xcf,0x43,0xff,
+ 0xbb,0xe9,0xb9,0xba,0x62,0xfa,0x21,0xf3,0xa2,0xfa,0x88,0x74,0x8f,0x69,0xc2,0xc1,
+ 0x02,0x28,0x52,0xad,0xc1,0xa3,0x71,0xc2,0x3b,0x9e,0xf3,0x94,0x38,0xd3,0x44,0xf1,
+ 0x69,0xda,0xbc,0xd1,0xe1,0x03,0xc0,0xc2,0x81,0x39,0xc4,0xd6,0x7d,0x69,0x70,0xd2,
+ 0xda,0x6a,0x21,0x9c,0x65,0x76,0xf1,0xdc,0xc4,0x57,0x38,0xd1,0xcd,0xb1,0xfe,0xf8,
+ 0xb4,0xda,0x90,0xde,0x41,0x5c,0xea,0xaf,0xb7,0x86,0x58,0x2f,0xec,0xc2,0xea,0xe6,
+ 0x86,0x05,0xbf,0xae,0x37,0xee,0x38,0x15,0x94,0xc5,0xcc,0x43,0xe9,0x05,0x38,0x25,
+ 0x63,0x96,0x9f,0x84,0x12,0xea,0x75,0xe0,0x9e,0x4e,0xea,0xd5,0x7b,0xff,0xe9,0x1c,
+ 0x72,0xb9,0xed,0xb8,0xa1,0xd0,0x6e,0xa6,0x09,0x01,0x0d,0xbe,0x32,0x4a,0x13,0x9b,
+ 0x2a,0x7a,0xf6,0x7f,0x81,0x27,0x97,0x3c,0x52,0x59,0x06,0x6a,0x4f,0x07,0xa4,0xa9,
+ 0x68,0xea,0x7b,0x73,0x5a,0x18,0xab,0x3f,0x5d,0x16,0x68,0x38,0xe5,0xb1,0x3e,0xb7,
+ 0xd0,0x28,0xf1,0x08,0xa2,0x8a,0x6f,0x8f,0x7a,0x0f,0xa3,0x99,0x84,0x31,0x2c,0x2f,
+ 0x35,0xf0,0xa8,0x8e,0xa1,0xea,0xc4,0x5b,0x6b,0x8c,0x8a,0x09,0x84,0x45,0x97,0x1b,
+ 0x8d,0x71,0xc8,0xa2,0x49,0x3d,0xdd,0xb8,0xb2,0x9f,0xe5,0x3c,0x67,0xa2,0x21,0x83,
+ 0xb3,0xed,0xeb,0x72,0xa1,0xbe,0x92,0xfd,0xfa,0xe1,0x2b,0x77,0xa0,0x0d,0x05,0xc6,
+ 0xe7,0xbf,0x6d,0xb8,0xf2,0x0d,0xa7,0xd8,0x3b,0x09,0xb1,0x43,0x23,0xd5,0x89,0x19,
+ 0xea,0xeb,0x2d,0xd5,0x31,0xd6,0xbb,0x99,0x8b,0xf4,0x81,0xc3,0xc2,0x77,0x84,0x35,
+ 0x59,0x73,0xce,0xb6,0xc5,0xde,0x93,0x31,0x0d,0xf0,0x80,0xc2,0xb6,0xbc,0xa6,0xda,
+ 0xea,0x13,0xd9,0xbb,0x54,0x85,0xcb,0x87,0xa6,0xa3,0xc4,0x97,0x85,0x5c,0xfc,0x82,
+ 0x5a,0xe1,0xdf,0x7a,0x1b,0x59,0xd1,0x6e,0x8b,0x04,0xce,0x73,0x28,0x81,0x7a,0x83,
+ 0xed,0xd5,0xb4,0xc0,0xce,0xaf,0x6d,0x21,0x14,0xcb,0x91,0xa3,0x13,0xe3,0x41,0x4c,
+ 0xb9,0x94,0x57,0xe2,0xe6,0x69,0x02,0x2a,0xc5,0xc9,0xf8,0xda,0x0c,0xde,0x92,0x07,
+ 0x76,0x65,0xfd,0x5e,0x36,0x0d,0x42,0xbb,0xca,0xe0,0x9c,0xc6,0xde,0x65,0x9f,0xda,
+ 0xea,0xbc,0x71,0x2f,0xb0,0x25,0x07,0x56,0xbf,0x61,0xf5,0xbb,0x9e,0x9d,0xbe,0xfa,
+ 0xf6,0x92,0x1e,0x84,0x22,0x59,0x45,0x2d,0xb0,0x91,0xe2,0xc2,0x04,0xaf,0xfc,0x93,
+ 0x48,0x85,0x4f,0x1f,0x03,0x74,0x85,0xb7,0x1d,0xb4,0x7c,0xe3,0x37,0x7d,0x35,0x36,
+ 0x24,0x24,0xdb,0x38,0x9c,0x94,0x65,0xbe,0x85,0x67,0xf1,0x0f,0x86,0x44,0x00,0x57,
+ 0xca,0x15,0xdc,0x24,0x42,0xc1,0x20,0xab,0xa4,0xd3,0x8a,0xd7,0x09,0xe5,0xc0,0x60,
+ 0x5e,0x87,0xd7,0xe7,0xb3,0x25,0x75,0x22,0x54,0xb4,0xd3,0x80,0x3c,0x9b,0xdf,0x53,
+ 0x3e,0x43,0xd3,0xc3,0x92,0x64,0x7f,0x33,0xf1,0xdd,0xec,0x34,0x8b,0xb8,0x8a,0x71,
+ 0x38,0x48,0x09,0x64,0x61,0x15,0x59,0xeb,0x5b,0x5e,0xf7,0xd0,0x0c,0xd0,0x19,0xa1,
+ 0xad,0x8e,0x9e,0x3a,0x8a,0x50,0xdc,0x92,0xbc,0x9c,0xbc,0x2d,0xb0,0xb1,0x08,0x30,
+ 0x88,0x14,0x32,0x9f,0x45,0xe3,0x49,0xae,0x00,0x3b,0xb4,0xa0,0xf2,0x88,0xb5,0x34,
+ 0xa7,0x2e,0x41,0x00,0x1c,0x72,0xb1,0x39,0x24,0xa6,0x9a,0xf9,0x7e,0xfb,0x80,0xae,
+ 0x67,0x0c,0xf1,0x32,0x35,0x75,0x68,0xd3,0xff,0x57,0xee,0x5d,0x24,0xcf,0x46,0x31,
+ 0x28,0xa6,0xd7,0x9d,0xe4,0x33,0x3b,0xa5,0xd6,0xcb,0x9e,0x92,0x1e,0xca,0x60,0x9d,
+ 0xad,0x02,0x9c,0x61,0xea,0x0a,0xd9,0x6b,0x20,0x06,0xfa,0x95,0x46,0xfa,0xee,0x34,
+ 0x99,0x38,0xeb,0x8b,0x50,0x82,0xc1,0x16,0x28,0xe9,0x95,0xca,0x56,0x1d,0xeb,0x15,
+ 0x79,0xce,0xa6,0x13,0x3b,0x3e,0x48,0x0b,0xda,0xdb,0xee,0x9f,0x49,0x6f,0xf2,0x8d,
+ 0x58,0x58,0x94,0x52,0xdd,0x49,0x34,0xac,0xe4,0x6b,0xa3,0x0a,0xe1,0xc0,0xa5,0x29,
+ 0x3b,0xfc,0x19,0x81,0xe6,0x34,0x27,0x5c,0x73,0x1c,0x90,0xeb,0x2b,0x7b,0xf3,0xc6,
+ 0x18,0x15,0xbf,0xd3,0xcf,0x91,0xc1,0x29,0x4b,0xa1,0xb5,0xe6,0x8c,0x36,0xf7,0x09,
+ 0x28,0xb3,0x53,0x44,0x00,0xea,0x47,0xb1,0xd9,0xab,0x43,0x74,0x37,0x6e,0x8a,0x83,
+ 0x1f,0xed,0xe0,0x93,0x71,0xca,0x32,0x2b,0xc1,0x62,0x75,0x08,0x0b,0x07,0xbd,0x56,
+ 0xec,0x81,0x36,0x16,0x7f,0x60,0xe1,0x80,0x37,0x95,0x76,0x39,0x53,0x1b,0x51,0x9d,
+ 0x38,0x6c,0xa1,0x62,0x33,0xb3,0x1a,0xb3,0x2f,0xfd,0x2c,0xc2,0xa3,0x76,0x44,0x8c,
+ 0xf8,0x5b,0xee,0xc8,0x7f,0xa8,0x66,0xf7,0x1d,0x63,0x34,0xc6,0x7b,0x6f,0x79,0x40,
+ 0x1e,0x50,0xcc,0xb4,0xa9,0x68,0x1e,0x01,0xa5,0xc9,0x1c,0x8c,0x48,0x73,0x4c,0x55,
+ 0x24,0xd5,0xe9,0xa8,0xf8,0xa4,0x14,0x84,0xac,0x4e,0xa0,0xe1,0x93,0x5b,0x5c,0x31,
+ 0x01,0x99,0x9e,0x69,0x16,0xa4,0x60,0x1b,0xdb,0x64,0x3a,0xa2,0x26,0x82,0x0b,0x4b,
+ 0x5c,0x0f,0x4d,0x9e,0xce,0x2a,0x8c,0xd9,0xd8,0xaf,0xf7,0x89,0x2a,0xfe,0x76,0xba,
+ 0xdd,0xf4,0x62,0xda,0x62,0xde,0x4b,0x8c,0x6a,0x61,0x99,0x9f,0xcd,0x54,0x7c,0xaf,
+ 0x91,0x5c,0x9e,0xe9,0x16,0xc6,0x41,0xfc,0x2b,0x17,0x8d,0x45,0xac,0x01,0xb2,0xdc,
+ 0xe3,0xa9,0x6e,0x81,0x93,0xd3,0xab,0x3e,0xd5,0x00,0xbe,0x80,0x77,0x99,0x32,0x29,
+ 0xc4,0xb1,0x58,0x36,0x9f,0x98,0x25,0xce,0x20,0x34,0xfb,0x36,0x92,0x67,0xc2,0xbe,
+ 0xfa,0x34,0xba,0xdf,0xbb,0x89,0x62,0x3d,0xa7,0x52,0x7b,0x21,0x1d,0xe7,0x53,0xd7,
+ 0x1d,0x1b,0x3d,0x44,0x65,0x84,0x83,0x86,0xb8,0x82,0x9a,0x60,0x11,0xbb,0xbf,0xeb,
+ 0x0c,0x39,0xaf,0xff,0xb4,0x11,0x0c,0x18,0x07,0x2a,0x1c,0xf6,0xe2,0xcd,0xa0,0x6b,
+ 0x26,0x97,0xe1,0xc7,0xb3,0xd2,0x2e,0x9d,0x07,0x99,0xc1,0xf5,0x89,0x59,0x0c,0x11,
+ 0x6c,0xc3,0x36,0xe2,0x25,0x59,0x0b,0x6c,0xf2,0x2f,0xb8,0x2b,0x85,0x94,0x41,0x73,
+ 0x83,0x99,0x02,0x68,0x2c,0x48,0xfb,0xac,0xe7,0x94,0xd9,0x30,0xe8,0xc0,0x32,0x69,
+ 0x4a,0x47,0x94,0xe8,0x09,0xd9,0xdc,0x46,0xec,0xc6,0x7c,0xba,0xb3,0xf1,0x9e,0x2f,
+ 0x19,0x59,0x55,0xb2,0x67,0x2c,0xff,0xdc,0xfa,0x2a,0xd4,0x75,0x7c,0xa1,0x09,0x45,
+ 0x0a,0x34,0x5a,0xe6,0x90,0x92,0xcc,0x14,0x1e,0xad,0x54,0x8d,0xa2,0x6f,0xd3,0x8c,
+ 0x6d,0xd8,0x15,0x3b,0xf8,0xf4,0x5c,0x92,0xfc,0xd7,0xfb,0x28,0x4f,0xdc,0xd7,0x45,
+ 0x21,0x36,0x3e,0xac,0x9d,0x0d,0x3a,0x9f,0xab,0xf9,0x9f,0xf9,0x19,0xe7,0xc8,0x59,
+ 0x00,0x62,0x61,0xbf,0x37,0x0e,0xc2,0x9e,0x37,0xd3,0xc4,0x60,0x25,0x38,0x92,0x8a,
+ 0x11,0x9e,0xe0,0x93,0x3c,0x16,0xbe,0xe8,0x0a,0x76,0x1f,0x56,0x36,0xe5,0xf7,0x42,
+ 0x63,0xa2,0x78,0xde,0x40,0x57,0xf9,0xfb,0xab,0xfd,0xd0,0x99,0x7d,0x1f,0xe4,0x42,
+ 0xc1,0x40,0x9d,0xe0,0x02,0xc9,0x6c,0xc8,0x91,0xa1,0x59,0xba,0x87,0x36,0xb4,0x81,
+ 0x21,0xec,0xf5,0xe1,0xa1,0x5a,0xde,0xd9,0x44,0x3f,0xfa,0x19,0x19,0x18,0x4c,0x52,
+ 0x80,0x74,0xd3,0x35,0x90,0x04,0x27,0x65,0x5e,0xcc,0xbf,0x28,0x7a,0x32,0xae,0x4f,
+ 0x28,0x8c,0xdc,0x46,0xb8,0xd4,0x3e,0x3d,0x28,0x05,0x29,0x34,0x83,0x58,0x11,0x9f,
+ 0xc0,0x9e,0xc8,0x7d,0xed,0xca,0x72,0x95,0x92,0xcd,0x98,0xe1,0xc3,0xb1,0x2b,0x82,
+ 0x7d,0xc6,0x30,0x67,0x58,0x38,0xe1,0x69,0x07,0xc0,0x6c,0xbc,0x4d,0x99,0xc0,0xa1,
+ 0x07,0x3a,0x11,0x98,0xce,0x01,0x8b,0x54,0xdb,0x63,0x98,0x9a,0x22,0xa4,0xe5,0x7d,
+ 0x1f,0xf0,0xf9,0xd0,0x12,0x86,0x67,0xa7,0xeb,0x1e,0x29,0x97,0x09,0x28,0xd8,0x7a,
+ 0x07,0xd4,0x47,0x8a,0x7b,0xce,0x6e,0x52,0x41,0xa2,0xbf,0x28,0x8f,0x47,0xcf,0x36,
+ 0x7d,0x2e,0xca,0x5d,0x95,0x6c,0x9c,0x72,0x25,0x0d,0xfa,0x96,0xeb,0x84,0x8a,0x04,
+ 0xb3,0x60,0xbf,0x62,0xee,0x17,0x4d,0xda,0xc3,0x95,0x90,0xd6,0xc6,0xcc,0x3e,0x4f,
+ 0x91,0xf5,0x19,0x4b,0x6f,0x4d,0x01,0xae,0xbb,0xcd,0x83,0xfa,0x3c,0x68,0x60,0xe3,
+ 0x2d,0x5e,0x98,0xe9,0x65,0xe0,0xaf,0xf0,0xbe,0xdf,0x3f,0x50,0xb3,0x40,0x2a,0x90,
+ 0xf6,0xb9,0xc3,0x17,0xda,0x5e,0x0a,0x36,0x20,0xfc,0xd6,0xe9,0xf2,0x06,0xf0,0x13,
+ 0xd8,0x7a,0x50,0x97,0x73,0x80,0x4d,0x5f,0xe1,0x6d,0x9e,0xbb,0x2a,0xd8,0x33,0xf2,
+ 0x47,0xae,0x3d,0xce,0xc2,0x1a,0x9b,0x26,0xb8,0xa0,0x65,0x3a,0x49,0xdb,0x38,0xd4,
+ 0xab,0x87,0x8c,0x75,0x43,0xf0,0xe0,0x5c,0xfb,0xd2,0x99,0x3a,0xa9,0xe3,0xf9,0x10,
+ 0x70,0xd1,0x27,0xaf,0x41,0xce,0x6b,0xdb,0x13,0xb0,0x61,0x6e,0xcf,0x52,0x34,0x6b,
+ 0x0e,0x93,0x63,0xd8,0xca,0x51,0x13,0x97,0xc4,0x60,0x4f,0xeb,0xe4,0x6c,0x7a,0x22,
+ 0xe6,0xa6,0xee,0x93,0x6b,0x5a,0x15,0x25,0x0b,0x18,0x6b,0x83,0x41,0x0e,0xd5,0x5d,
+ 0xfd,0x3a,0xd8,0xe0,0x3a,0xc6,0xf7,0x58,0x9e,0x7c,0xa8,0xfb,0x8d,0x76,0x44,0x48,
+ 0xb0,0x27,0x64,0xcd,0x68,0xf9,0xd5,0xc8,0xd0,0xc3,0x2f,0xd7,0x86,0xe7,0xeb,0xcc,
+ 0xc8,0x3e,0x70,0x0a,0x60,0x10,0x58,0xed,0x67,0x49,0xdf,0xec,0x98,0xd9,0x08,0x1a,
+ 0xbd,0x6a,0x96,0xa1,0x0b,0x5c,0x64,0xb9,0x89,0x04,0x9d,0x85,0xed,0xca,0x86,0x70,
+ 0xec,0x02,0x40,0xf4,0xe1,0x47,0xcb,0x10,0x8b,0x22,0xaa,0xe0,0xf6,0xde,0x04,0x95,
+ 0x67,0x4c,0x1e,0xb9,0x8c,0x26,0x31,0x41,0xca,0x97,0x83,0x68,0xbe,0x43,0x96,0x33,
+ 0x40,0xeb,0xf2,0xe7,0x52,0x20,0xc0,0x4d,0x88,0xa4,0x92,0xcd,0x22,0x90,0x7a,0x07,
+ 0x88,0x29,0xce,0x87,0xfb,0xd8,0x0c,0x43,0x3d,0x2a,0xe2,0x22,0x88,0x3e,0x51,0x0c,
+ 0xe9,0xe4,0xca,0x2f,0x60,0xe4,0x85,0xe0,0x5f,0xc5,0xd5,0x1f,0xa0,0x6e,0x52,0x2d,
+ 0xd2,0x5d,0xa5,0x2c,0xb4,0x4f,0x6c,0x2d,0x50,0xaf,0x5d,0x79,0x00,0xa4,0x78,0x5e,
+ 0xbd,0x8f,0x63,0x5f,0x96,0xf1,0x30,0x2d,0xac,0x12,0xa5,0x3d,0xaf,0x0a,0xa7,0xab,
+ 0x88,0xb6,0x2a,0xf9,0xb0,0x30,0xf5,0xe0,0xf1,0xd6,0x79,0xd9,0x8b,0xc3,0x2f,0xba,
+ 0xa6,0x27,0xf8,0x95,0xa1,0x85,0x8e,0x43,0xf2,0xe4,0xf3,0xe1,0xe5,0x35,0x22,0xeb,
+ 0x18,0xf9,0x31,0x0b,0xc5,0xb7,0xb8,0x2f,0xb8,0x15,0xbb,0xe0,0x03,0xeb,0xe8,0x59,
+ 0x15,0x7b,0x37,0xe4,0xe1,0x6b,0xa4,0x7f,0xac,0xce,0xb7,0x32,0x05,0xb0,0x5b,0x8b,
+ 0x38,0x66,0x62,0x04,0x95,0x8a,0x4c,0x44,0x13,0x94,0xa7,0x21,0xc9,0x06,0x6f,0x2e,
+ 0x4b,0x5d,0xa6,0x5a,0x61,0x4f,0x51,0x62,0x1b,0x10,0x86,0x50,0xd9,0x45,0xc9,0xcb,
+ 0x73,0x2b,0xed,0xc9,0x95,0x39,0x45,0xd6,0x67,0x25,0x5f,0x57,0x43,0x27,0xa9,0xfc,
+ 0x14,0x2f,0xf3,0x5c,0xf9,0xd2,0x36,0xd2,0x2a,0xf4,0x1d,0xe5,0xd4,0xdf,0x5a,0x2b,
+ 0x29,0x34,0x1a,0xa7,0x3d,0x5d,0x47,0xf4,0xf7,0x47,0x55,0x3d,0x38,0xe3,0xb5,0x0c,
+ 0x8e,0xe0,0x6c,0x50,0xb7,0x43,0x02,0xd1,0xcb,0xcf,0x32,0x82,0xee,0x20,0x8d,0x1d,
+ 0xd2,0xbc,0xb9,0xb5,0xfb,0x95,0xcf,0x0a,0xf4,0x42,0xe4,0x14,0xd5,0x24,0x06,0x16,
+ 0xb0,0x5d,0xe0,0xb1,0x74,0x8d,0x18,0x7a,0x2d,0xd3,0x22,0x79,0x4f,0x52,0x4f,0x3f,
+ 0x1d,0x37,0x4e,0x23,0x84,0xf2,0x7d,0x49,0xc7,0x6f,0xcf,0xc5,0x7a,0x15,0xa4,0xeb,
+ 0xb8,0xe7,0xf1,0x20,0x4e,0x61,0xc9,0x1c,0x80,0xc0,0xe1,0x45,0x50,0xad,0x52,0x30,
+ 0xc6,0x24,0xd3,0x72,0x5e,0xea,0x97,0xbc,0xb5,0xde,0xe6,0x8a,0x9d,0xd0,0x6d,0x64,
+ 0xa0,0x19,0x90,0xe9,0x93,0x2b,0x80,0x7d,0x70,0x35,0xa8,0x5f,0x25,0xd5,0xc5,0x7f,
+ 0x68,0xa7,0x40,0x55,0x87,0x67,0x7e,0xff,0x1c,0x71,0x31,0x77,0xcc,0x43,0xff,0xa3,
+ 0xbd,0xa8,0xc1,0xbc,0xed,0xb2,0x82,0x1d,0xb1,0x9c,0x5a,0x4a,0x8f,0x62,0xe9,0x4c,
+ 0x04,0x3b,0xc5,0xb8,0x0a,0xc0,0x9e,0x3d,0xb9,0x1c,0xcc,0x51,0xaa,0x61,0x25,0x4e,
+ 0x62,0xa9,0x20,0x88,0xcf,0xf0,0xde,0xd1,0x47,0x28,0x71,0xb2,0xcd,0xf5,0x6e,0xb1,
+ 0x4c,0xdf,0x01,0x3e,0xdc,0x6f,0xb5,0xb9,0x0c,0x4d,0x45,0x1f,0xd0,0x54,0x16,0xb0,
+ 0x79,0x84,0xf7,0x03,0x73,0x4a,0x6d,0x30,0x8c,0x23,0x58,0x19,0x98,0x42,0x76,0x29,
+ 0xc1,0xb1,0xb4,0xaa,0xf1,0x3b,0xff,0xf6,0x51,0xa1,0x6d,0xb2,0xc6,0xec,0x8a,0x1d,
+ 0xc8,0xbc,0xe2,0x2a,0xbd,0x15,0x97,0x97,0x53,0x45,0x71,0x88,0xb4,0xe0,0x07,0x59,
+ 0x82,0x7b,0xc2,0xb8,0x5a,0x8e,0x5a,0xe8,0x8e,0xf6,0xdb,0x2e,0xf7,0x4f,0xd4,0x16,
+ 0x86,0x76,0x41,0xc0,0x81,0x98,0x30,0xdb,0x28,0xeb,0x85,0xc4,0x63,0x2b,0x7c,0x49,
+ 0x30,0xf4,0x60,0xb8,0x41,0x6a,0xe7,0x21,0xc8,0x7b,0x6b,0xc9,0x3c,0x57,0xe9,0xbf,
+ 0x1a,0x6f,0xad,0x42,0xf7,0x3d,0xa6,0x5c,0x34,0xe1,0xcc,0xb8,0x9f,0xc3,0x51,0x5d,
+ 0xae,0xe8,0x22,0xfe,0x26,0xc1,0x14,0xa0,0x27,0x56,0x7a,0x20,0x15,0xd0,0x90,0xf1,
+ 0x14,0xda,0xf6,0x35,0x70,0x67,0xf7,0x96,0xa6,0x40,0x91,0xab,0x8e,0x1c,0xc6,0xaa,
+ 0x27,0xb9,0xd1,0xb6,0x18,0xc5,0x9b,0x18,0x17,0x4e,0xf5,0x81,0x38,0x5c,0x82,0x4b,
+ 0x3c,0x17,0x90,0x2a,0x9a,0x27,0x2b,0x6c,0xe5,0x0c,0xd5,0xae,0xde,0x37,0x60,0x9c,
+ 0xca,0x8f,0x15,0x0d,0xab,0x57,0x47,0x1c,0xd1,0x24,0xb5,0x7d,0xfb,0xe5,0x6c,0xff,
+ 0xc7,0xa2,0xb8,0xb1,0xca,0xb1,0x55,0xab,0x50,0xfe,0x9d,0x5b,0x24,0xaf,0x56,0xf1,
+ 0x42,0xa0,0x57,0xf8,0xd6,0xf2,0x78,0xf7,0x81,0x62,0x08,0xbd,0x12,0x99,0xc9,0x2b,
+ 0x78,0x47,0xc9,0xf6,0x34,0x57,0x15,0x61,0xf1,0x6c,0xff,0x04,0xe8,0x1f,0x18,0xc6,
+ 0xf7,0x22,0x16,0xb5,0x40,0xd8,0xde,0x00,0x7a,0xa6,0xbc,0x41,0x78,0xfc,0xf2,0xd3,
+ 0xae,0x1f,0x5e,0x92,0x60,0xcc,0x09,0x07,0x1d,0x79,0xfd,0x7a,0x86,0x3a,0xf6,0x36,
+ 0xdd,0xfe,0x2c,0x3a,0xb5,0x42,0x9a,0xa7,0x1a,0x5d,0x9b,0x8c,0x96,0x57,0x57,0x2b,
+ 0xcc,0xae,0xb5,0x9f,0x08,0x35,0x7f,0xaf,0x09,0x14,0xf1,0x5a,0x99,0x7c,0xee,0xdd,
+ 0x2d,0xba,0x45,0xaf,0x40,0x6c,0x77,0xb1,0xb0,0x1b,0x3c,0x3e,0x8c,0x35,0x45,0xf7,
+ 0x71,0x13,0x6a,0xce,0x2e,0x78,0xc0,0xcc,0x80,0x30,0xf4,0xb0,0x82,0xb2,0x1e,0x84,
+ 0x4b,0xcf,0xc8,0xf5,0xf2,0x10,0xdf,0x06,0xb8,0x75,0xfd,0xc0,0xb5,0xe7,0x99,0x18,
+ 0xa2,0x84,0x90,0x00,0x19,0x6c,0xd6,0x29,0xc4,0x6e,0x37,0x80,0xdc,0xa5,0x38,0xa9,
+ 0x33,0xaa,0xc7,0x06,0x57,0x47,0x3c,0xf7,0x29,0xa8,0xfb,0x93,0x1e,0x73,0xda,0x95,
+ 0xd0,0x12,0xc9,0xd7,0x48,0x74,0xbd,0xfd,0xde,0x43,0x52,0x29,0xa7,0x63,0x82,0x91,
+ 0xc2,0x04,0x2d,0x79,0xc5,0xd9,0xb1,0xa6,0x83,0x87,0xe2,0xa8,0x07,0xfb,0x94,0x9c,
+ 0xb8,0xb5,0x1f,0xfd,0xff,0xbe,0x44,0xce,0x10,0x4b,0x76,0x69,0xae,0x74,0x22,0xab,
+ 0xe8,0xa0,0x69,0x6a,0x3e,0xa3,0x0f,0x30,0xe2,0xfb,0x23,0x1d,0xfb,0x7e,0xb7,0x11,
+ 0x8b,0xe5,0x44,0x3a,0xe9,0x71,0x75,0x4a,0x45,0x08,0xa2,0xe2,0x32,0xa9,0x3b,0x45,
+ 0xbe,0x92,0xf0,0x01,0xda,0xf4,0x5a,0x76,0xfb,0xfd,0x42,0x53,0x62,0x5d,0x65,0xe9,
+ 0x67,0x3a,0x4b,0xe4,0x9f,0x34,0xd9,0x58,0xee,0xe3,0x61,0xe3,0x8d,0x3f,0x3c,0xc9,
+ 0x89,0x11,0x7b,0xf2,0xb0,0x37,0xe5,0x24,0x70,0xa7,0x67,0x97,0x9b,0xce,0xe9,0xee,
+ 0x09,0xcc,0x54,0x71,0xe4,0x47,0x0f,0xf9,0x7c,0x53,0x39,0xee,0xc1,0x60,0xa3,0xfb,
+ 0x6b,0x1c,0x7f,0xaa,0x93,0xdf,0x3e,0x7f,0x40,0x78,0xc2,0xd4,0x94,0xb1,0x8e,0x29,
+ 0x25,0x87,0xcf,0xbd,0xfd,0x11,0x45,0xe2,0x04,0x47,0x5e,0x96,0xd9,0x69,0x7f,0x2e,
+ 0x1a,0x45,0xa5,0xed,0x56,0xdd,0xe1,0xb6,0x09,0xaf,0x77,0x66,0xbe,0x1a,0x49,0x6f,
+ 0x30,0xbe,0x46,0x08,0x0a,0x97,0xa7,0x9a,0xb8,0x4c,0x78,0x26,0x52,0x74,0x5d,0xfd,
+ 0xb3,0x6f,0xec,0x91,0x95,0x28,0xc6,0xfa,0xe5,0xbf,0x92,0xd9,0x10,0x93,0xd5,0xe9,
+ 0xc4,0x35,0x9b,0x11,0x8c,0xcb,0x4f,0x01,0xfa,0x98,0x7f,0x3b,0x3d,0x5c,0x28,0x78,
+ 0xe4,0xca,0xfb,0x0f,0x22,0xd3,0x90,0x14,0x5d,0xb9,0xb2,0x53,0xea,0x73,0x75,0xc7,
+ 0xd0,0x3b,0x16,0xe5,0xe1,0x12,0x4c,0x95,0x57,0x2f,0x1f,0xd9,0x01,0x5f,0xd6,0x0c,
+ 0x1d,0x08,0x0e,0xcc,0xbb,0x0d,0x50,0xea,0xb3,0x38,0x01,0x6e,0xd8,0x86,0xfc,0x25,
+ 0x26,0xb7,0x3c,0x52,0x9c,0x19,0xaf,0x11,0x69,0x7d,0x5e,0x54,0xba,0x0f,0xaa,0x62,
+ 0x02,0x40,0x55,0x1f,0x61,0xd0,0xc1,0x4b,0x28,0xd9,0x1c,0x17,0x3b,0xeb,0x07,0xf0,
+ 0x26,0xff,0xcc,0x62,0x38,0xc0,0xba,0xcb,0x24,0x06,0x42,0x0c,0xcd,0x68,0xb4,0x63,
+ 0x16,0x1c,0x91,0xbd,0x70,0x62,0x31,0x77,0x0f,0xc8,0x7e,0xcd,0xde,0x4e,0x8f,0x7e,
+ 0xd0,0x43,0xb4,0x92,0x91,0x80,0x39,0xd2,0xe7,0x92,0x65,0x10,0x8d,0xd5,0x89,0x28,
+ 0xa4,0xac,0x8d,0x6e,0x14,0x78,0x0a,0x1f,0x9d,0xe6,0x7f,0x60,0xf1,0x31,0x59,0x15,
+ 0x6e,0x4f,0xa0,0x27,0xb3,0xf1,0xf4,0xe9,0x30,0xf1,0x0f,0xc9,0x63,0xc4,0xda,0x56,
+ 0x8f,0x40,0x1d,0x2a,0xb0,0x60,0x14,0x52,0xdd,0xc2,0x53,0xeb,0x03,0x70,0xf9,0x46,
+ 0x54,0x56,0x0d,0x17,0x55,0xcf,0x9d,0x3d,0x8c,0x00,0x68,0x94,0xda,0x97,0x0f,0xe0,
+ 0xf0,0xbe,0x50,0xe9,0xc4,0x81,0x69,0xa5,0x5b,0xf7,0xb7,0xb4,0xce,0x3e,0x79,0xb9,
+ 0x1a,0x0c,0xdf,0xa7,0x83,0x9c,0x06,0x62,0x6f,0x20,0x86,0xea,0x40,0x74,0xbc,0xc6,
+ 0x37,0xb2,0xc1,0x76,0x5b,0xac,0x61,0x1b,0xbb,0x0f,0xee,0x4e,0x20,0x28,0x83,0x0a,
+ 0xae,0x93,0xf7,0x00,0x12,0xb7,0x09,0x78,0x1b,0x07,0xc0,0xd1,0x4e,0x58,0x68,0xea,
+ 0x8c,0x8c,0x29,0xe4,0x8f,0xba,0xdd,0x60,0x31,0x7a,0x5b,0x57,0x5c,0x48,0x55,0x3f,
+ 0xe3,0x89,0x23,0x31,0xb4,0x93,0x73,0x3a,0x61,0x67,0x94,0xb4,0x5b,0x87,0xed,0x59,
+ 0x96,0x68,0xc7,0x59,0xa5,0xd7,0xdd,0x20,0xa6,0x77,0xf3,0x6d,0xbc,0x2a,0x4d,0xf3,
+ 0x1a,0xaa,0x4c,0x46,0x77,0x4e,0xce,0x0d,0x7f,0x3d,0xfb,0x64,0x13,0x7e,0x7c,0x1e,
+ 0x7e,0x25,0xe2,0x78,0x8f,0x29,0x98,0xf0,0x2c,0xa2,0xdd,0xb7,0x64,0x04,0x60,0xc8,
+ 0x7b,0x96,0x38,0x3e,0x19,0x11,0xc8,0x95,0x26,0x93,0x76,0x6d,0xc0,0xcc,0x85,0x9e,
+ 0x95,0x02,0x81,0xab,0x4e,0x56,0xb8,0xf8,0x68,0xc6,0x85,0x0d,0x9d,0x84,0xc3,0xe2,
+ 0xa5,0x52,0x1e,0x3b,0x58,0xb4,0x9f,0x0f,0x15,0xb8,0x1f,0x38,0x19,0xe2,0x86,0xf8,
+ 0x79,0x65,0x4d,0x34,0xfa,0x89,0xa4,0x80,0x67,0xcb,0x21,0x24,0x52,0xf7,0x45,0x04,
+ 0x3f,0xac,0x38,0x62,0xab,0x8f,0xfd,0x8d,0x55,0xf2,0xf7,0x9f,0xb6,0xd2,0xc5,0xf6,
+ 0xda,0xf6,0x20,0x9c,0x2b,0x32,0x4e,0x4b,0xa2,0xb2,0xf3,0x88,0xec,0xb9,0xcd,0x8c,
+ 0xce,0xfb,0xdd,0xf8,0x4e,0xb7,0x30,0x6f,0x8a,0x0b,0xe0,0xb9,0x3a,0x08,0x70,0x23,
+ 0x26,0xdd,0xe6,0x27,0xdc,0xb2,0x50,0x3b,0x49,0xaf,0x66,0x5c,0x66,0x9c,0x6a,0x4a,
+ 0xa6,0xfc,0xd4,0xae,0xdc,0xc4,0xbf,0x7c,0x6b,0x91,0xf6,0xb4,0x62,0xbe,0xfd,0x0e,
+ 0xe6,0xbf,0x34,0x02,0x31,0xc1,0x63,0x3e,0x84,0xda,0x98,0xaf,0x76,0x1c,0x50,0x11,
+ 0x8c,0x2f,0x77,0x29,0x78,0xa5,0x68,0xa7,0x2e,0x17,0x63,0xd0,0x9f,0xaf,0x70,0x4c,
+ 0x9b,0x85,0xed,0x7a,0x10,0x12,0x7b,0xf4,0xca,0xcb,0x17,0x99,0xc4,0xca,0xd8,0xcb,
+ 0xdc,0x10,0xbd,0xec,0x71,0x86,0x14,0x07,0x23,0x8a,0xf3,0x3c,0x57,0x4a,0x7d,0xe8,
+ 0xd9,0xd2,0xf6,0x4a,0xa0,0xd2,0xba,0x56,0x3c,0x9e,0x64,0x82,0x66,0x70,0x43,0xfa,
+ 0xab,0x15,0x5c,0xee,0xd2,0x5e,0xb7,0x0e,0x26,0x8b,0xab,0xf2,0x37,0x08,0x55,0xe5,
+ 0x2c,0xbb,0x75,0xbd,0x7f,0xd8,0x5d,0x03,0xe2,0x02,0xe1,0xfd,0x6f,0x81,0x7a,0x03,
+ 0x21,0x5f,0xc4,0x3d,0xb8,0x95,0x35,0xbe,0x8e,0xbb,0x2d,0x08,0x9c,0x2d,0xff,0x2c,
+ 0x1f,0x56,0xfb,0x7b,0xc3,0xc6,0xdb,0x9e,0xa9,0x30,0xfa,0x46,0x1b,0xe1,0x77,0xb5,
+ 0x16,0xb7,0x8e,0x39,0x8b,0x7b,0xc1,0x64,0xe3,0x3b,0xdb,0xb0,0x4a,0xa4,0xa7,0x1e,
+ 0x7c,0xff,0x89,0x3a,0x54,0xea,0x94,0x5d,0x61,0x62,0x09,0xe8,0xb0,0x26,0xb7,0x6e,
+ 0x30,0x32,0x4e,0xba,0xb5,0xb0,0x65,0x94,0xfd,0x14,0x37,0xab,0xab,0xb7,0xc3,0xd2,
+ 0x7f,0x2f,0x45,0xca,0x1d,0xfb,0xa5,0x23,0xad,0x47,0x3a,0x53,0x72,0x3f,0x0c,0x2a,
+ 0x8a,0x8c,0x07,0x2c,0xe4,0xea,0x7b,0xd9,0x1e,0x70,0x1d,0x92,0xec,0xbe,0x71,0x51,
+ 0x76,0x42,0x73,0x7f,0x98,0x91,0xd4,0x9f,0xdf,0x25,0x2d,0x02,0x17,0x37,0x45,0x85,
+ 0x8b,0x2d,0xe4,0x96,0xde,0xf9,0x3b,0xb9,0x65,0xae,0x0f,0xb7,0x32,0xc7,0x5e,0x69,
+ 0xc3,0x90,0xa4,0xe6,0xbe,0x86,0xa7,0x22,0x41,0x5e,0xb0,0x62,0x93,0xfe,0x7f,0x4f,
+ 0x2b,0x43,0x0a,0xf8,0x6b,0x40,0x2d,0x77,0xed,0x68,0x6c,0x92,0x64,0x4b,0x33,0x5f,
+ 0xe6,0x42,0x5e,0x9b,0xc5,0xa1,0x25,0xa7,0xfc,0x3a,0x10,0xa5,0xca,0x9d,0x51,0x7c,
+ 0x4b,0xc2,0xb6,0x84,0xb5,0xe5,0x65,0x40,0x07,0x95,0xc2,0x57,0x64,0x9c,0x1b,0x45,
+ 0xca,0x00,0xc9,0x34,0x7b,0x89,0xc7,0x3f,0xc4,0x42,0xe8,0x24,0x98,0xb1,0xc2,0xa5,
+ 0x2c,0x14,0x24,0xfb,0xaf,0x01,0xc4,0xfb,0xcf,0x5b,0x77,0xc4,0x39,0x74,0xca,0x12,
+ 0xae,0xd8,0x26,0xbf,0xed,0x59,0x73,0x5c,0x0e,0xb8,0x3e,0x73,0x1c,0x6e,0xd9,0xc0,
+ 0x2a,0x55,0xca,0x46,0x0c,0xda,0x05,0x6a,0x0a,0x07,0x9b,0xc7,0xee,0xb9,0x50,0xcd,
+ 0xaa,0x7a,0x6b,0x07,0x01,0xe8,0xe1,0x70,0x49,0x20,0xf8,0xd4,0xf6,0xb2,0x21,0xaa,
+ 0x36,0xb2,0x58,0xde,0xa3,0x78,0x22,0x85,0x57,0xbf,0xb8,0x94,0x7e,0xbe,0x48,0x5a,
+ 0xbe,0x4f,0x0d,0x3d,0x1f,0x23,0xf5,0x13,0xa0,0x3b,0x52,0x45,0xf2,0xa7,0xed,0xbe,
+ 0xc7,0x7e,0xb2,0xc3,0x09,0x5d,0x02,0xb3,0x2f,0x59,0x9c,0xf0,0x57,0xa1,0xe5,0xf0,
+ 0x3b,0x3a,0x03,0xdb,0x48,0x93,0xd7,0x2c,0xec,0x2e,0x05,0xa3,0x47,0x48,0x53,0x01,
+ 0x87,0x28,0x6a,0xf1,0xcc,0x2e,0xf3,0x15,0xa5,0x35,0x05,0x82,0x90,0x4d,0x6d,0x48,
+ 0x4f,0x58,0x32,0x63,0xc3,0xd3,0xe6,0xab,0xcc,0x48,0x2a,0xc6,0x2d,0xce,0x30,0xee,
+ 0x5a,0xb5,0x70,0x86,0x4f,0x3f,0x6d,0xb9,0x10,0xb3,0x7e,0xb2,0xf3,0xc2,0xe6,0x04,
+};
+
+
+/* 317-0167 FD1089A */
+static const UINT8 key_0167[0x2000] =
+{
+ /* data */
+ 0x98,0xb0,0xcf,0x36,0xd7,0xa2,0xc0,0x94,0xa5,0x41,0x82,0x6b,0xc8,0x42,0xfa,0xc8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+ /* opcodes */
+ 0x68,0xcd,0x56,0xcd,0xb5,0x15,0xc6,0x7a,0x1c,0x7a,0x21,0x44,0x8d,0x23,0xdb,0x16,
+ 0xc2,0x0a,0xb6,0x03,0x36,0xd0,0x45,0x8d,0x97,0x55,0xb4,0x56,0xaa,0x70,0x84,0xf4,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+};
+
+
+/* 317-0168 FD1089B */
+static const UINT8 key_0168[0x2000] =
+{
+ /* data */
+ 0x98,0xb0,0xcf,0x36,0xd7,0xa2,0xc0,0x94,0xa5,0x43,0x82,0x6b,0xc8,0x40,0xfa,0xc8,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+
+ /* opcodes */
+ 0x68,0xcd,0x56,0xcd,0xb5,0x15,0xc6,0x7a,0x1c,0x7a,0x23,0x44,0x8d,0x21,0xdb,0x16,
+ 0xc2,0x0a,0xb6,0x03,0x36,0xd0,0x45,0x8d,0x97,0x55,0xb4,0x56,0xaa,0x70,0x84,0xf4,
+ 0x7f,0xe1,0x07,0x16,0x94,0x11,0x9e,0xd0,0x8f,0xe6,0xd8,0xd6,0xbb,0xa2,0x6b,0x59,
+ 0x80,0xf1,0x66,0xab,0xba,0x2b,0x50,0x9f,0x65,0xec,0xba,0xc0,0x8c,0x7b,0xb0,0x57,
+ 0x8c,0xb8,0xbf,0xbe,0x88,0xfa,0x27,0x75,0xca,0x48,0x5e,0x40,0x6c,0xe8,0x82,0xba,
+ 0x44,0xe9,0x19,0x1a,0xbc,0x94,0x9a,0xea,0xf6,0xc1,0xb6,0x01,0x4c,0x8c,0xea,0x74,
+ 0x91,0xc2,0x78,0xde,0x8f,0xe5,0xb4,0x56,0x97,0x4a,0x42,0x97,0x24,0x90,0x79,0x7f,
+ 0xba,0x34,0xa2,0x1c,0xcc,0x34,0xc3,0xae,0x39,0xf8,0x17,0xe6,0x25,0xd2,0xc3,0x61,
+ 0x22,0xda,0xc5,0x2f,0x19,0x0f,0x28,0x22,0x93,0xe7,0x5a,0x9e,0x72,0x8c,0xda,0x9c,
+ 0x0f,0x90,0x65,0x0a,0xab,0x19,0xa7,0x3a,0xcd,0x82,0x2e,0x09,0xb4,0x98,0x39,0x4d,
+ 0x57,0xd6,0x7d,0x3f,0x30,0x66,0x16,0xce,0xa0,0xc9,0xca,0x59,0x55,0x1d,0xa2,0x03,
+ 0x3a,0x6e,0x3b,0x2d,0xa2,0xe0,0x6c,0x12,0x98,0x97,0x12,0x39,0x23,0xa0,0x8a,0x38,
+ 0x89,0x7f,0xaa,0x4e,0x07,0x1c,0x32,0x1b,0xee,0x83,0xa7,0x2e,0x73,0xc2,0xbf,0xb0,
+ 0x06,0x22,0x97,0xaa,0xc5,0xda,0xc5,0xc7,0x03,0x59,0x82,0x89,0x1e,0xad,0xd2,0x9b,
+ 0x7c,0x0a,0x77,0xc5,0xa1,0x8b,0x38,0xdf,0xfc,0x7b,0x6e,0x58,0xee,0x99,0x0d,0x25,
+ 0xa3,0x6d,0x56,0x26,0xb5,0x65,0xa0,0xa4,0x16,0xd3,0x0b,0x3f,0xdf,0xbc,0xd9,0xa8,
+ 0x5f,0x86,0x88,0x52,0x5b,0xa3,0xe6,0xba,0x99,0xae,0xcf,0x69,0xe9,0xb7,0x64,0x06,
+ 0x50,0x47,0xb8,0x01,0xb8,0xff,0x6b,0x90,0x72,0x4a,0x16,0xd9,0x39,0x52,0x5b,0xba,
+ 0x5b,0x69,0x03,0x43,0x5a,0x98,0x32,0x18,0xc3,0x55,0x73,0xaf,0x49,0xbd,0x78,0xc5,
+ 0x9f,0x05,0x04,0x17,0x3f,0x98,0xd3,0x73,0xfb,0xb6,0xa8,0xd3,0xe7,0x3f,0x24,0x9f,
+ 0xb1,0xb2,0x92,0x54,0x3d,0xf7,0xc9,0x90,0x60,0x0a,0x7a,0x65,0x20,0xbc,0xcc,0x6f,
+ 0x2a,0x8b,0x3b,0x11,0x5f,0x70,0x68,0xdf,0x1e,0x23,0x1e,0x75,0xd6,0xf7,0xde,0x10,
+ 0xe2,0x8b,0x3d,0xf4,0xaa,0xbb,0xf7,0x93,0x23,0xb0,0xc6,0x44,0x61,0x44,0xa5,0x8a,
+ 0x4e,0xb0,0x1b,0xa0,0xe6,0x5c,0x8d,0x3b,0x9c,0x7a,0x03,0x54,0xc1,0xed,0xfc,0x45,
+ 0xd0,0x19,0x76,0xa2,0xb3,0xdb,0xbd,0x46,0xe7,0x2e,0x67,0xc2,0xa0,0xde,0x4e,0xb9,
+ 0xa3,0xb9,0x47,0xfe,0x80,0x14,0xa4,0xbf,0xe1,0x91,0x4a,0x23,0xeb,0x14,0x73,0x20,
+ 0x08,0x55,0xb6,0x0c,0x32,0xf4,0x7f,0x05,0xce,0x0d,0xb8,0x15,0xeb,0xf1,0x6d,0xca,
+ 0xd7,0x95,0xee,0x98,0x27,0xaf,0x88,0x8c,0xc5,0x2f,0x1a,0x13,0xab,0x25,0x68,0xc2,
+ 0xbb,0x7a,0xff,0xec,0xb3,0x0f,0x37,0x76,0x0d,0xc6,0x34,0x92,0xca,0x9d,0xe4,0x3e,
+ 0x84,0xf6,0x99,0x8f,0x7c,0xe9,0x0b,0x28,0xf1,0x42,0x26,0x0d,0x6a,0x8f,0x2b,0x77,
+ 0x89,0xa6,0xc2,0xec,0xa8,0xc0,0x4d,0x25,0x89,0xaf,0x54,0x4b,0xdd,0x85,0xe9,0x67,
+ 0x97,0xb8,0xb4,0x98,0xdd,0x81,0x44,0x07,0x7e,0x41,0xfe,0x2d,0x2b,0x30,0x42,0x5c,
+ 0x63,0xae,0x32,0x0c,0x3f,0x4a,0x09,0xe9,0x03,0x52,0xec,0x1b,0xe5,0xf5,0x4b,0xe5,
+ 0xaf,0x35,0x9a,0xfe,0x9b,0x4b,0x3e,0xf4,0xbc,0x9f,0x69,0x7d,0x83,0xea,0xe8,0xd9,
+ 0xc6,0xed,0xed,0xab,0x58,0x3c,0x90,0xea,0x00,0xab,0x41,0xbc,0x33,0x6f,0xa4,0xa0,
+ 0x4d,0x3b,0x4a,0x62,0x04,0x04,0x6c,0xc6,0x29,0x02,0x84,0xea,0xf4,0xe3,0xfa,0x9b,
+ 0xa4,0xa6,0x26,0xf6,0x90,0x13,0x2b,0xde,0x95,0xd7,0x26,0xcd,0x32,0x01,0xa8,0x33,
+ 0xf8,0x21,0x77,0xc4,0xf5,0xa9,0xa4,0x73,0xed,0x7c,0x6b,0x9d,0xe4,0x32,0x62,0x5e,
+ 0x3d,0x18,0x31,0x56,0x70,0x19,0x79,0x9c,0xfd,0xc2,0x6f,0xfb,0x1f,0x5d,0x67,0xd0,
+ 0x82,0x9e,0x9f,0x02,0x84,0xe9,0x09,0xf0,0x07,0x00,0xfc,0x4c,0xbf,0xa8,0x98,0x4a,
+ 0x09,0xf5,0x1f,0x41,0x06,0xd6,0x67,0xdf,0x0e,0x6b,0xc2,0xf1,0x3f,0x53,0x12,0xc3,
+ 0xd0,0xcc,0x4f,0xf5,0x14,0x87,0x3a,0xa3,0x03,0x5f,0x31,0x91,0x9e,0xd0,0x47,0x14,
+ 0xcb,0x0c,0x34,0x50,0x3a,0xaa,0x1a,0xf6,0x9b,0x81,0x83,0x07,0x6f,0xe5,0x7e,0x8f,
+ 0x34,0x90,0x74,0x33,0x1f,0x5a,0xd3,0xb9,0x61,0x5a,0xce,0x01,0xb8,0xfa,0xd5,0x21,
+ 0xc0,0x21,0x64,0xc7,0x0d,0xd2,0x6f,0x03,0x30,0xbf,0x1b,0x71,0xd8,0x39,0x36,0xcd,
+ 0xda,0x89,0x1c,0x84,0x8f,0xe4,0x99,0x7d,0x88,0xe7,0x58,0x71,0xd1,0x83,0xb8,0x15,
+ 0x03,0x92,0xda,0x9e,0x7b,0xe5,0x77,0xc6,0x22,0xd3,0xe0,0x01,0xa1,0x96,0x03,0x59,
+ 0x98,0x53,0x0d,0x3a,0xfe,0x2f,0xcd,0x8e,0x4d,0xdf,0xf4,0x07,0x60,0x02,0x61,0x51,
+ 0x20,0xab,0x86,0x28,0x92,0x99,0xea,0x62,0xd0,0x11,0x97,0x91,0x96,0x6b,0x3f,0x4a,
+ 0x1d,0x0b,0x40,0xfc,0xe1,0x41,0xc5,0x2d,0xa9,0x85,0x0a,0xf1,0xa0,0xc9,0xd4,0x93,
+ 0x73,0xc0,0x8e,0x38,0x93,0xf1,0x6f,0x01,0x9e,0xdf,0x08,0x47,0xb1,0x75,0x21,0x8e,
+ 0x81,0x6f,0x29,0x0b,0x46,0x66,0x88,0x59,0x85,0x6c,0x47,0x1f,0xcd,0x56,0x8f,0xe6,
+ 0x2c,0x3e,0xa8,0xc9,0x35,0x2d,0x71,0x4a,0x5b,0x63,0x03,0x5f,0x1b,0x62,0x04,0xe0,
+ 0xa2,0xf4,0x74,0xcd,0x30,0xca,0x31,0x86,0x46,0xbf,0x01,0xce,0xbb,0xab,0x57,0x3b,
+ 0x4e,0xb5,0xc4,0x7f,0x72,0x82,0xda,0xa8,0x48,0x0d,0x5c,0x0f,0xca,0x9f,0x69,0xb2,
+ 0x51,0x9b,0xa4,0x6b,0x2b,0x75,0xc3,0x84,0xb5,0xb5,0xe9,0x7f,0x7d,0x34,0xb4,0x8e,
+ 0x5d,0xf1,0x3d,0x09,0x68,0x22,0x72,0x8b,0xdd,0x96,0xea,0xae,0x2c,0x26,0xa7,0x11,
+ 0x98,0x46,0x1d,0xf7,0xda,0x4e,0x0f,0x46,0xfa,0x4d,0x94,0x18,0xd5,0xaf,0x49,0x6c,
+ 0xb1,0x6e,0x3a,0x72,0x38,0x38,0x80,0x09,0xb0,0x45,0x11,0x38,0x54,0x4b,0x34,0x14,
+ 0x7c,0x08,0xd1,0x91,0x5c,0x07,0x67,0xd3,0xfe,0xd7,0xd2,0x82,0x4e,0x00,0xbf,0x12,
+ 0xd5,0x46,0x64,0x68,0xd6,0xbb,0xbd,0xb4,0x4a,0x0e,0xe2,0x43,0x4f,0x16,0x58,0x2a,
+ 0x10,0x86,0x42,0x91,0x45,0x91,0x5d,0x1f,0xdd,0x52,0x44,0x06,0x85,0xbc,0xc0,0x3a,
+ 0x0e,0x64,0xb1,0xbb,0x02,0x0e,0xe0,0x17,0x3e,0xc4,0x03,0x58,0x16,0xcc,0x5d,0xe7,
+ 0x98,0x91,0x53,0xac,0x69,0x6b,0x31,0x8c,0xe0,0x02,0x72,0x8b,0xc9,0x92,0xd8,0x20,
+ 0xe9,0x72,0xc1,0xf3,0xc6,0xf1,0x28,0x6f,0x73,0x22,0x8f,0x1e,0x85,0x7f,0xb0,0x4e,
+ 0xf4,0xf7,0xc3,0x63,0x00,0x6f,0x75,0x90,0x67,0xc3,0x0e,0x65,0xa0,0xc0,0x5a,0x43,
+ 0x55,0x02,0x41,0xb5,0x0a,0x14,0x3d,0xe2,0xdd,0x85,0x1e,0x21,0x3e,0x1b,0xf3,0x63,
+ 0xf5,0xb9,0xae,0x5f,0xd3,0xbc,0x26,0xe8,0x5e,0x92,0xdf,0x6e,0x34,0x15,0xfe,0x3a,
+ 0xfc,0x7d,0x4d,0x3e,0x74,0xc7,0xff,0x8a,0x9d,0xa4,0x09,0x1d,0xb7,0x49,0xf7,0x5c,
+ 0x5c,0xce,0xb9,0xc7,0x0f,0x59,0x53,0xa2,0xb5,0xb5,0x18,0x89,0xee,0x46,0x14,0xf0,
+ 0xfd,0xcb,0xba,0xc0,0x96,0xa5,0x75,0x49,0x16,0x25,0x97,0x93,0xbd,0x4d,0x4f,0x00,
+ 0xe0,0x08,0x18,0x91,0x86,0x3c,0x1d,0xea,0xe3,0x64,0x47,0xe1,0xc6,0x83,0x61,0x59,
+ 0x91,0x3a,0xea,0xab,0x5c,0xc6,0xb6,0xe3,0x59,0xda,0xe1,0x89,0xff,0x1f,0xdc,0x62,
+ 0x07,0xff,0xbf,0xbb,0xe5,0xfe,0x88,0x50,0xdc,0xbb,0xe6,0xaa,0x0d,0x0e,0xe5,0xf3,
+ 0xcf,0x2a,0x24,0x92,0xc2,0xfa,0xd3,0xbd,0xaf,0x2a,0xc6,0x88,0xc0,0xd6,0x78,0xcc,
+ 0x59,0x39,0x66,0x73,0x88,0x40,0xbd,0x92,0xd1,0x9d,0x46,0x22,0x89,0xbb,0xec,0xda,
+ 0x2f,0x9c,0xe3,0x29,0x61,0x7b,0x01,0x45,0x4a,0xe7,0xd1,0xdd,0x54,0xc2,0xf7,0xd4,
+ 0x4e,0x10,0xb8,0x60,0xf2,0x80,0x0b,0x56,0x2d,0x6d,0xc8,0x01,0x19,0x79,0x4e,0x02,
+ 0xd0,0xb3,0x19,0xac,0xfd,0x98,0x9f,0xba,0xdd,0x2a,0x4a,0xf8,0xa0,0x90,0x0f,0x22,
+ 0x32,0x60,0xe7,0x44,0xd0,0x95,0x37,0x0f,0x8a,0x4a,0xbf,0x0a,0xed,0x0b,0xc2,0xbd,
+ 0x81,0x4f,0xf7,0x33,0x29,0xbc,0x8b,0x2d,0x0a,0xbb,0xb4,0x30,0x23,0xe3,0xc3,0xdb,
+ 0xf4,0x7d,0x6d,0x99,0x72,0xc1,0x49,0xe2,0x5c,0x8b,0x91,0x5e,0x49,0xe8,0x1a,0x61,
+ 0x91,0x48,0x1a,0x61,0xed,0xf7,0x90,0xb7,0xfa,0x3c,0x3f,0xdc,0x66,0x1c,0x91,0x47,
+ 0x03,0xcb,0x1a,0x67,0x26,0x4e,0xb3,0x8b,0x80,0x22,0x3a,0xe0,0xfd,0x44,0xc6,0xa6,
+ 0x87,0xc8,0x64,0xaa,0x72,0x25,0xce,0x7f,0xf6,0x52,0xbf,0x08,0x5c,0x68,0x28,0x59,
+ 0xc5,0x9a,0xf5,0xec,0xfd,0x9c,0xb0,0xeb,0xe7,0x93,0xf3,0x1b,0x75,0x30,0x28,0xf9,
+ 0xe0,0xb8,0xee,0x23,0xb0,0xe1,0x45,0x33,0x37,0xe2,0x80,0x77,0xcf,0x8a,0xc5,0x89,
+ 0xb2,0x83,0x0e,0x09,0xff,0x7e,0x79,0x06,0xc0,0x54,0x8e,0x88,0xf1,0x75,0x5a,0xc4,
+ 0x60,0x76,0x68,0x5f,0xb3,0xa3,0x3d,0x72,0x46,0xf2,0xdb,0x6b,0x9d,0x90,0xcd,0x32,
+ 0xfd,0x95,0x36,0x91,0x2c,0x54,0xe4,0x4f,0x40,0x6e,0x50,0xd7,0x45,0x2c,0x37,0xf4,
+ 0x18,0x27,0x66,0x4b,0x81,0x8a,0x38,0x9c,0x60,0x6e,0x92,0xdf,0xb8,0xb2,0xc1,0x6b,
+ 0x5a,0xd2,0x8c,0xda,0x68,0x81,0x2a,0x2f,0x86,0xf9,0x07,0xad,0xa7,0x48,0x19,0x7b,
+ 0xf9,0x76,0xab,0x95,0x35,0x8e,0xc2,0x66,0x36,0x5f,0x9e,0x41,0xba,0x50,0x55,0xad,
+ 0x4c,0x28,0xbd,0x3e,0x1a,0x84,0xf7,0xc3,0x79,0xe9,0xbc,0x2f,0x95,0xec,0xe3,0x40,
+ 0xf9,0x6a,0x82,0xce,0x17,0xad,0x7d,0x81,0xaf,0x98,0x57,0x4b,0x85,0xe4,0x3a,0xf7,
+ 0x5a,0x38,0xd4,0xc6,0x42,0x0c,0x42,0x0c,0x58,0x59,0xc5,0x80,0x1e,0x56,0x2c,0x90,
+ 0x18,0xcb,0x18,0xca,0x4d,0x80,0x00,0x08,0x8f,0x21,0xe7,0x48,0xd0,0x7b,0x17,0x3e,
+ 0xfd,0x8e,0xde,0x4c,0x87,0x39,0xec,0xac,0x0f,0xc1,0x1e,0xed,0xbd,0x23,0x7f,0x69,
+ 0xb9,0x8b,0x98,0xd2,0x59,0x82,0xa8,0x44,0xe8,0x57,0xca,0x31,0x53,0xff,0xee,0xc8,
+ 0xb0,0xf6,0xa0,0x88,0xf3,0x0d,0x11,0x41,0xb8,0x60,0x16,0x9f,0x19,0x70,0xe3,0x44,
+ 0xe3,0x85,0x67,0x48,0xeb,0x20,0xb4,0xc3,0x9e,0x80,0xe5,0x7a,0xb0,0x1a,0xf5,0x02,
+ 0xc7,0x17,0x8a,0x91,0x26,0x79,0x7f,0x68,0xc9,0x36,0xc6,0xc1,0x1d,0xae,0x9d,0x92,
+ 0x44,0x63,0xbb,0xfb,0x78,0x58,0xb6,0xbb,0xa9,0xad,0x5e,0x23,0x73,0xe7,0xca,0x3d,
+ 0x01,0xb1,0xbd,0xca,0x43,0x44,0xc4,0x19,0xd8,0xed,0x6c,0xac,0x08,0xda,0x47,0xbc,
+ 0x53,0xe2,0x95,0x83,0xfd,0x8c,0x8f,0x20,0x73,0x8c,0x86,0xf0,0x61,0x75,0x4f,0x7c,
+ 0xf6,0xe7,0x25,0x68,0x77,0x80,0xfa,0x35,0xd4,0x1a,0x04,0xb2,0x26,0x6e,0x58,0xf1,
+ 0x42,0x2e,0xff,0xa9,0x44,0x7f,0xf5,0xf0,0xa3,0x4b,0x87,0x2d,0xec,0x76,0x62,0x11,
+ 0x30,0xec,0xce,0x67,0xdd,0xc2,0xee,0x3a,0xb5,0xeb,0x99,0x10,0x84,0x65,0xf5,0x01,
+ 0xd3,0xe9,0xa7,0x5a,0x96,0x15,0x6a,0x2e,0x02,0x8d,0xcd,0xd3,0x6f,0xaf,0x3d,0xae,
+ 0x47,0xba,0xd7,0xcc,0x3e,0xac,0xe3,0x9b,0x02,0x45,0x51,0x6d,0x31,0x27,0xa0,0x5f,
+ 0x5c,0x68,0xc0,0x93,0xf3,0x06,0x37,0xc4,0xb5,0x05,0x95,0x90,0x1b,0xfb,0x77,0x9e,
+ 0xdf,0x1c,0x7b,0x69,0xac,0xbe,0xad,0x10,0xa3,0x14,0x40,0x64,0xf4,0xb3,0x18,0x33,
+ 0x2b,0x56,0x2d,0xaf,0x30,0xe4,0xd5,0x94,0xd4,0x33,0x7e,0xdb,0x08,0xd9,0x8f,0xa2,
+ 0xe9,0xf4,0x13,0x60,0x08,0xdb,0xf0,0x0e,0x73,0xf2,0xda,0x07,0x01,0x47,0x14,0x2b,
+ 0x3b,0x57,0x35,0x5a,0x54,0x2b,0xad,0x0d,0xd3,0xe3,0xd7,0x25,0xea,0x04,0xea,0x1d,
+ 0xfe,0x54,0x92,0xda,0x7b,0xb0,0x9e,0x53,0xab,0x79,0x55,0xab,0xd2,0x6f,0x1c,0x2c,
+ 0xca,0xd7,0xa8,0x85,0xb9,0xae,0x41,0x06,0xcb,0x68,0x20,0xe7,0x35,0x97,0x97,0x11,
+ 0xd9,0x24,0x48,0x63,0x64,0xb5,0x6a,0x05,0x9c,0x1e,0x29,0xb5,0xbe,0x8a,0xd0,0x41,
+ 0xac,0xa7,0x07,0xbe,0x7c,0x6d,0x38,0x5f,0xba,0x5f,0x4c,0xca,0x96,0x15,0x69,0x00,
+ 0x6e,0x3f,0x56,0x86,0xa6,0x31,0x97,0x1a,0xea,0xfe,0x31,0xd6,0xea,0x08,0x63,0xf9,
+ 0x0a,0xbc,0x96,0xf0,0x69,0x09,0xf3,0xce,0x0d,0x9e,0x13,0xa4,0xa4,0xfb,0xa2,0x7f,
+ 0xe2,0xce,0xeb,0xad,0xb3,0x8f,0x1e,0x50,0x8d,0x91,0xcb,0x8b,0x8e,0x44,0xcc,0x99,
+ 0xa1,0xda,0xaa,0xe2,0x5a,0x24,0x87,0x24,0x5a,0x31,0x5f,0xd0,0x26,0x79,0x8d,0x54,
+ 0x94,0x4e,0xb2,0x83,0x16,0x4a,0xb4,0x30,0xad,0xc7,0x7d,0x92,0x8b,0xc1,0xf1,0xa4,
+ 0xb6,0xbc,0x95,0x59,0x2f,0xc6,0x49,0x1c,0x7b,0xb0,0x70,0x8d,0x33,0x1d,0xfe,0x82,
+ 0x95,0x90,0xc4,0x00,0x65,0xb9,0x0c,0x28,0x21,0xd6,0x02,0xa1,0x4f,0x65,0x9c,0xb6,
+ 0xa5,0xee,0xc1,0x8a,0x94,0x13,0xad,0x47,0x71,0x8d,0x85,0xbf,0x08,0xa5,0xca,0x94,
+ 0x80,0x1e,0x4d,0xdf,0x14,0x1f,0xc4,0xb0,0xe1,0x79,0x1a,0x07,0x7c,0xf4,0xaa,0xa1,
+ 0xd5,0xc1,0x62,0x82,0xea,0xac,0xb7,0xe6,0x0c,0x8a,0xa1,0x4d,0x43,0xcb,0x70,0xe2,
+ 0xd6,0x17,0x35,0xda,0x07,0x02,0x72,0x90,0x7d,0xa6,0xc3,0x63,0x1e,0x21,0xd6,0x01,
+ 0x55,0xf1,0x3f,0x41,0xe8,0xd1,0x28,0xc1,0x6d,0xd4,0xcc,0x7e,0x11,0x26,0xb1,0x6c,
+ 0x6c,0xdb,0x67,0xc8,0xf2,0x2c,0x9d,0x36,0x4a,0xad,0xd0,0x31,0x2d,0x79,0x68,0x5f,
+ 0x4a,0x40,0xf2,0x9a,0xfe,0x88,0xf1,0xbd,0x88,0x22,0xcd,0x33,0x3f,0xde,0xdb,0x7a,
+ 0xa5,0xad,0x7b,0x71,0x70,0x70,0xe0,0x6a,0xba,0x9a,0x05,0xc7,0xb3,0xa8,0x3e,0xae,
+ 0x82,0x12,0x37,0x07,0xfc,0xe2,0x41,0xc4,0xa1,0xde,0x0e,0xfc,0x84,0x84,0xfc,0x0d,
+ 0xc4,0x02,0x19,0x9e,0x2f,0xc6,0xf0,0x13,0x15,0x02,0x11,0x85,0x6b,0x35,0xdf,0xff,
+ 0x49,0xff,0xf3,0xc5,0x27,0xfa,0x48,0xb5,0xba,0x8a,0x2d,0xb9,0x11,0x55,0xeb,0x7c,
+ 0xee,0x31,0x5d,0xac,0x03,0x29,0xff,0x23,0xbe,0xf8,0x2a,0x10,0xa7,0x4a,0x7e,0xd0,
+ 0x26,0xa1,0x89,0xe6,0xb8,0x6b,0x72,0x5a,0xc4,0x74,0x4c,0x4f,0x6d,0xdd,0x75,0x50,
+ 0xda,0x45,0xce,0x17,0xd5,0xc9,0xd5,0xd6,0xbc,0x5f,0x18,0x59,0x8c,0x89,0xf7,0x9d,
+ 0xf3,0x4c,0x3e,0xc5,0x91,0x39,0x22,0x05,0x19,0xe0,0xb0,0x95,0x50,0x9c,0x04,0x0b,
+ 0x92,0x80,0x64,0xcf,0x42,0x58,0x2c,0x52,0x2b,0x4d,0xcb,0xa7,0x25,0x76,0xbb,0xee,
+ 0x4f,0xbd,0xec,0x5e,0x8e,0x99,0xa8,0x5a,0x53,0xe2,0x4a,0x16,0xd6,0x73,0xc3,0xc6,
+ 0x14,0x20,0x62,0xcc,0x7e,0xd8,0x3c,0x59,0xd9,0x2e,0xf0,0xff,0xe4,0x9d,0x64,0xa7,
+ 0xcd,0x39,0x88,0xc8,0xbe,0x1e,0x37,0x05,0xa1,0xd6,0x16,0x9f,0xe0,0x6e,0x99,0xcc,
+ 0x20,0xf4,0xfc,0x11,0x2f,0xd9,0x84,0x6c,0xcd,0xdd,0x5f,0xd2,0x94,0x9c,0xbe,0xf3,
+ 0x9e,0x93,0x02,0xa3,0x78,0x8e,0x3a,0x18,0x82,0xd8,0x75,0x32,0xf7,0xdf,0xbe,0x83,
+ 0x03,0x2a,0x91,0x8e,0x33,0x90,0xcf,0xe4,0xc8,0xf7,0x85,0x03,0x92,0xdd,0x46,0x1e,
+ 0x20,0xe7,0xcb,0xaa,0xa5,0xc0,0x3c,0x9b,0x1e,0x5d,0x0a,0x6d,0xd0,0x89,0xa6,0x39,
+ 0x4f,0x7e,0x45,0xcf,0xb4,0xd1,0x46,0x1f,0x47,0xa2,0x0a,0x6c,0x04,0x7d,0xcb,0x57,
+ 0xd5,0x54,0x87,0xc1,0x83,0xb0,0x72,0x33,0xad,0x0f,0x87,0xdc,0x67,0x46,0x6b,0xca,
+ 0x8c,0x0c,0x5a,0xd2,0x92,0x31,0x5c,0x5c,0x25,0xb1,0xaf,0x41,0x65,0x65,0x1c,0x1b,
+ 0x21,0x37,0xb9,0x57,0x34,0x77,0x0f,0x3e,0xe9,0xe2,0x8e,0x90,0xe8,0xa1,0x53,0x04,
+ 0x09,0x60,0xf6,0xed,0xa4,0x1c,0x53,0x13,0xf1,0x6f,0x02,0x70,0xcd,0xd2,0x92,0x2f,
+ 0x84,0x68,0x2b,0x9f,0xf5,0x1c,0x41,0x0c,0x8a,0x80,0x15,0x0f,0x5f,0x11,0x2e,0xbe,
+ 0x3d,0x63,0x6e,0xcb,0xd2,0x7c,0x03,0x39,0x52,0xfa,0x5a,0x2e,0x1d,0x65,0x49,0x01,
+ 0x07,0xbb,0xb6,0x65,0x42,0x3a,0xac,0xa5,0x49,0xe3,0x37,0x08,0x5e,0xca,0x59,0x4c,
+ 0xee,0x36,0xd2,0x77,0x1a,0xbb,0xbf,0xeb,0xf0,0x18,0x80,0xa2,0x1d,0x7f,0x07,0x6b,
+ 0x53,0x18,0x89,0x14,0xfa,0xda,0xb3,0x48,0xe1,0x07,0x72,0x5f,0xda,0x47,0x62,0x86,
+ 0x4f,0xf7,0xd8,0xdd,0xcb,0xe0,0x74,0x3a,0x03,0x88,0x64,0xcd,0xdf,0x6c,0x4e,0xb8,
+ 0x64,0xc4,0x0d,0xcc,0x92,0x44,0x7d,0x73,0x99,0xa3,0xec,0xe8,0x5a,0x9c,0x08,0x63,
+ 0x1d,0xe8,0x4e,0xba,0x54,0x8a,0x98,0x48,0xa7,0xda,0xea,0x6c,0x9e,0x1a,0xb0,0x7b,
+ 0xa6,0x9d,0xe6,0x6a,0xc5,0x2f,0x04,0xf7,0x3a,0x7d,0xed,0xb5,0x03,0x42,0xda,0x57,
+ 0x8e,0xd5,0x44,0x1b,0x14,0x83,0xba,0x2b,0x92,0x80,0x77,0x06,0x51,0xf3,0xeb,0x99,
+ 0x05,0x61,0x77,0xda,0xd2,0x87,0xc9,0x54,0x3f,0x47,0xa7,0xd3,0xf2,0xdf,0x04,0x03,
+ 0xca,0x5c,0x4c,0x4d,0x44,0xe2,0xc5,0x38,0x9d,0x6f,0xa6,0x90,0xb7,0xee,0xde,0x2d,
+ 0x7a,0xb3,0xb8,0x0b,0x49,0x6a,0xd1,0x41,0x13,0x1e,0xf9,0xf4,0xa5,0x59,0x4e,0x60,
+ 0x67,0xd7,0xda,0x8b,0x28,0x6f,0xaf,0xdd,0xaf,0xc3,0x18,0x96,0x01,0xe1,0xd1,0x4f,
+ 0x6e,0x5d,0xa2,0x17,0xdf,0x74,0x54,0x83,0xb1,0x7a,0x09,0xe3,0x42,0xb1,0xec,0xd2,
+ 0x64,0x0f,0xa6,0x56,0xb8,0x17,0x37,0xb2,0x4a,0x7c,0x65,0xe6,0xcc,0x6d,0x8c,0x61,
+ 0x3b,0xc7,0xf4,0xc6,0x3f,0x82,0xe8,0xd8,0x94,0x11,0x43,0xd5,0x49,0x7d,0x83,0xe9,
+ 0x01,0xeb,0x3e,0xe0,0x6e,0x4a,0x14,0xe7,0x41,0x47,0xb3,0x27,0x0a,0x15,0x0e,0x74,
+ 0x97,0x98,0xdc,0xb0,0x19,0xe9,0xf7,0x5c,0x7b,0x08,0xcd,0x55,0xae,0x55,0xb9,0x0c,
+ 0xde,0x27,0xf8,0xb0,0x10,0x45,0xdf,0x65,0x64,0x13,0x2a,0x48,0xbc,0x82,0xe1,0x57,
+ 0x85,0x62,0x26,0xe0,0x76,0xa7,0x95,0x7e,0xce,0xe2,0x3b,0xdc,0xf9,0xfe,0x4d,0x3f,
+ 0x3a,0xae,0x25,0xc6,0xa6,0x54,0x30,0xc0,0x87,0x9d,0x46,0xaf,0x53,0xa8,0x9a,0xf4,
+ 0xb1,0x66,0x50,0x56,0x57,0xdc,0xfe,0xdd,0x2b,0xdc,0xe0,0xea,0x00,0x67,0x92,0x9d,
+ 0x05,0xdb,0x17,0x77,0x0e,0xf2,0xd5,0x42,0xb1,0x1e,0xde,0x45,0x41,0x0e,0x76,0x0e,
+ 0xae,0xd9,0x80,0x67,0xd3,0xf6,0x3f,0xd7,0x48,0x7f,0xfd,0x91,0x26,0xbe,0x7e,0x24,
+ 0x4d,0x90,0x08,0xea,0x61,0xc8,0xb6,0xaa,0xa8,0x8e,0x3f,0x32,0xfc,0x11,0xdd,0xdd,
+ 0x42,0xd2,0x99,0xfd,0xd5,0x53,0xb1,0xe4,0x35,0x43,0xda,0xd0,0x1b,0xe7,0xd1,0x31,
+ 0x98,0xd0,0x2e,0x6d,0xdd,0x21,0x8c,0x0f,0x92,0xc3,0xb8,0xb5,0xb2,0x8a,0xd9,0xcf,
+ 0x2b,0x8a,0x18,0x3a,0xae,0xce,0xe2,0xd0,0x1a,0x63,0xbc,0xcb,0xd3,0x02,0xd3,0x14,
+ 0x92,0x2f,0xb8,0xab,0xc4,0x12,0x3f,0x2c,0x26,0x6c,0xff,0xb9,0xd2,0xd5,0x3b,0x5c,
+ 0xe1,0x3a,0x79,0x1a,0xf7,0x31,0x97,0xce,0x10,0x1a,0xe1,0x1b,0x78,0x58,0x21,0x3d,
+ 0x1b,0xf2,0xd9,0x25,0x2e,0x7f,0xea,0xf7,0x4f,0xad,0x45,0xce,0xff,0x20,0xbe,0xf1,
+ 0x14,0xc0,0xde,0x82,0x9c,0xf5,0xb2,0x4d,0xc9,0x21,0x56,0x7b,0xe6,0xd1,0x93,0xbf,
+ 0x61,0x34,0xf9,0xa3,0x78,0x47,0x09,0xb5,0x63,0x00,0xa2,0xb9,0xe1,0xdb,0x0b,0x83,
+ 0xfc,0xe8,0xcf,0x15,0x65,0x69,0xb0,0xd9,0x4c,0xd7,0x57,0x85,0xb7,0x35,0xd7,0x2c,
+ 0x39,0xbd,0xe4,0x93,0x40,0xa2,0x0d,0x41,0xbc,0xdf,0xa2,0x67,0xcb,0x45,0x8f,0xa0,
+ 0xd6,0xb9,0xd3,0xf3,0x7f,0xa1,0x8b,0x2c,0x27,0xee,0x56,0x95,0x2a,0xce,0xfd,0x47,
+ 0x0c,0x26,0xf4,0xb5,0xbb,0x1e,0x22,0x79,0x97,0x2f,0x45,0x31,0x43,0x46,0xa0,0x5f,
+ 0x48,0xa3,0x64,0xae,0x9f,0xa2,0x0e,0xf1,0x1f,0x25,0xe1,0x33,0x22,0x47,0x1e,0x44,
+ 0x11,0x57,0x23,0xfe,0xc3,0xc6,0x50,0xdb,0xf5,0x83,0xf4,0x86,0x35,0x9c,0xb2,0x9d,
+ 0x34,0xbd,0x52,0xc7,0x08,0x4c,0x34,0x42,0xd3,0x7f,0x69,0x68,0x83,0x0d,0x86,0x28,
+ 0x88,0x42,0xd8,0xc8,0xf5,0x65,0xbf,0xbc,0xda,0xba,0x9a,0x18,0x24,0x80,0x78,0xcc,
+ 0xfb,0x73,0xee,0x5a,0x27,0x6f,0xb6,0x0b,0x8a,0x2e,0x6f,0x16,0x58,0x7e,0xd2,0x94,
+ 0x82,0x63,0xe9,0xb9,0x68,0x21,0x22,0x31,0x2c,0x3d,0x6c,0x07,0xb6,0x12,0x44,0xd9,
+ 0x11,0x32,0xb1,0xb5,0x1b,0x2a,0x38,0xd7,0x26,0xe9,0xe9,0xb7,0xc1,0x4b,0x2b,0x2a,
+ 0x33,0xa2,0x61,0x81,0x46,0xa4,0x01,0xcf,0xe7,0xdc,0x0b,0xdd,0x2a,0x57,0x81,0x23,
+ 0xfe,0x3a,0x00,0xb9,0x89,0xb9,0x8b,0x54,0xd6,0x0f,0x28,0xcb,0x63,0xae,0xde,0xc6,
+ 0x7a,0x7d,0x46,0x6d,0x5a,0x8f,0x35,0x24,0xc8,0xad,0xc4,0xa3,0x15,0xab,0x72,0x9a,
+ 0x68,0xad,0xe1,0x4e,0x17,0x46,0x49,0x7a,0xfe,0xc9,0x36,0x32,0xbe,0x66,0x8a,0x13,
+ 0x21,0x4d,0x91,0xd2,0x29,0xeb,0x3c,0x6b,0x7e,0x4a,0x02,0xd9,0x30,0xbf,0xfd,0xc0,
+ 0x92,0x9d,0x90,0x00,0xfb,0x35,0x43,0xc1,0xb4,0x89,0xf6,0x7e,0xc7,0x62,0x11,0xdc,
+ 0x16,0xdd,0x3d,0x19,0x97,0x4e,0xff,0x1f,0xc5,0x26,0x65,0xee,0x3a,0x6a,0xce,0xe8,
+ 0x9d,0xca,0xdc,0x6c,0xb8,0xf7,0x30,0x29,0x74,0xc2,0xa6,0x80,0x62,0x41,0x05,0xa1,
+ 0x39,0xec,0x8d,0x38,0x9c,0xbd,0xad,0xb3,0x7b,0xe7,0x98,0x46,0xe5,0xf8,0x1d,0x0a,
+ 0x7c,0xeb,0x6d,0x33,0xf1,0xe5,0x62,0x72,0x3d,0x04,0xab,0x2d,0xb9,0xc5,0x91,0xd9,
+ 0x24,0x9a,0xaa,0xb7,0x28,0x6f,0x69,0x6d,0x51,0x56,0x8f,0xfa,0x30,0xbd,0xb6,0x11,
+ 0x80,0x1c,0x3b,0xcf,0x1d,0x17,0x7c,0xf6,0x90,0xe2,0x2d,0xfa,0xd1,0x96,0x0f,0xe4,
+ 0x4b,0x51,0xc2,0xfd,0x41,0x6a,0x33,0xb6,0x61,0x50,0x38,0x24,0xcb,0xc5,0xa3,0x78,
+ 0x48,0x06,0x94,0x38,0x9e,0x3a,0x08,0x4e,0xfe,0x25,0x4c,0x44,0x6a,0x6a,0x0c,0x87,
+ 0x2d,0x16,0x45,0x43,0x5d,0xf2,0x97,0x4e,0x19,0x07,0x6e,0x89,0xf4,0xe0,0x60,0x14,
+ 0xa4,0x20,0x15,0xb0,0xe1,0x5e,0xdc,0x73,0x49,0x74,0x54,0x4e,0x68,0x4f,0xee,0x30,
+ 0x36,0x82,0xb8,0xbe,0xa0,0x44,0xeb,0xc3,0xb7,0xa0,0x29,0x78,0xc4,0xe2,0x8d,0x54,
+ 0x81,0x83,0x1c,0xcc,0xca,0x30,0xbd,0x64,0x0d,0xb3,0xc6,0xa6,0x5a,0x25,0xd3,0x09,
+ 0xf1,0xbf,0x86,0x16,0x25,0xaa,0xa1,0x25,0xd9,0x11,0x26,0x7d,0xa6,0xdc,0xbe,0x5b,
+ 0xb7,0xbf,0xa3,0xf9,0xcf,0xf3,0x70,0x4c,0x8c,0x05,0xba,0x8a,0x18,0xd7,0x4c,0x7e,
+ 0x57,0x88,0xe6,0x0d,0x10,0xcf,0xaf,0x5d,0x09,0xa0,0xdd,0x34,0x42,0x2f,0xb3,0xb1,
+ 0x77,0x89,0xa9,0x77,0xcd,0xd6,0x02,0x6a,0x8b,0xde,0x3a,0x08,0x9c,0xe3,0xc1,0x62,
+ 0x4e,0x1e,0x3c,0x24,0x3c,0x23,0xe0,0x09,0xbb,0xb2,0x99,0x67,0x9b,0x5b,0xf6,0x78,
+ 0x4e,0x60,0x7d,0x34,0xc3,0xbc,0xd1,0x8c,0xce,0xe3,0x46,0x64,0x6c,0xd2,0xdd,0x8e,
+ 0x9f,0x14,0x20,0x6e,0x27,0xbb,0x01,0xd9,0x2d,0xf8,0x0b,0x2a,0x11,0xd7,0xd9,0x5e,
+ 0xd7,0x80,0x7e,0x41,0xfd,0xd6,0xb9,0x0d,0x48,0x0f,0x3c,0x36,0x9e,0x2c,0x9a,0x18,
+ 0x31,0x9f,0xac,0x0b,0x54,0x59,0x4e,0x7f,0xaa,0xbe,0x52,0x7e,0x13,0xf8,0x02,0x19,
+ 0x70,0x1b,0xe7,0xc2,0x78,0x2e,0x69,0x76,0x16,0xd6,0xbe,0xa2,0xbb,0x66,0xe6,0x8f,
+ 0xa6,0x51,0xbf,0x4e,0xf6,0x23,0x02,0x12,0x43,0xc1,0x7e,0xba,0x87,0x93,0x62,0x48,
+ 0xa1,0x82,0x1a,0xe0,0x7d,0xc3,0xc5,0x27,0xe6,0x4c,0xa6,0x96,0xff,0x59,0x58,0x3f,
+ 0xd6,0xf0,0x00,0xbb,0x09,0xea,0x03,0x83,0xb2,0xcb,0x7b,0x08,0xd9,0x91,0x9c,0x6e,
+ 0x3c,0x69,0xf4,0x03,0x37,0x7b,0x6c,0xe0,0x67,0x3a,0x0b,0xd4,0x33,0xb4,0xde,0x38,
+ 0x4d,0xca,0x3a,0x7f,0x7b,0x16,0x8b,0x85,0x15,0xa2,0xb5,0x6a,0x2d,0xf9,0x76,0xb2,
+ 0x4a,0xb6,0x70,0x11,0x44,0x19,0xac,0x06,0x90,0x03,0x39,0xf0,0x11,0x2d,0xb2,0xc3,
+ 0xeb,0x42,0xd2,0x96,0xf9,0xe9,0x07,0xf3,0x18,0x99,0xcf,0x23,0x1e,0xc3,0x10,0x95,
+ 0x8c,0xb1,0xed,0x7a,0x17,0x54,0xc0,0xc0,0x9b,0x1f,0xd1,0x4d,0x43,0x2e,0xad,0x63,
+ 0x1c,0xa8,0x56,0xd3,0xf2,0xc3,0xd0,0x33,0x1e,0x21,0x6d,0xc1,0x75,0x4b,0x29,0xf4,
+ 0xac,0xfb,0x83,0x1e,0x99,0x8d,0x98,0x80,0x6c,0x06,0x9b,0x49,0x0b,0x23,0x0a,0xf4,
+ 0x63,0x76,0x0c,0x56,0xa1,0x96,0x1f,0x9a,0xb9,0x07,0xa4,0xa2,0xb0,0xa1,0xc3,0x63,
+ 0xf5,0xa2,0xb0,0x4c,0x2a,0x57,0x59,0xc8,0xed,0xad,0xce,0x1b,0x1f,0x8b,0xd7,0x95,
+ 0x42,0x97,0x05,0x63,0xf5,0x6f,0xa4,0x6d,0x80,0xfc,0x0f,0x87,0xc3,0x63,0xf2,0xc3,
+ 0xc5,0xd8,0x5b,0x7f,0xb8,0xf9,0x84,0x0e,0x14,0xf3,0xc7,0x7f,0xba,0x31,0xdf,0xb2,
+ 0x83,0x0b,0x96,0x76,0x06,0x32,0x7d,0xcb,0x70,0x13,0x6d,0x35,0x8c,0x8b,0x3b,0x33,
+ 0x02,0x06,0x42,0x7b,0xb2,0x2a,0x1a,0xe8,0x82,0xa3,0x8a,0xcc,0xf1,0x1e,0xf3,0x6c,
+ 0xbe,0x62,0xcd,0x43,0x59,0xdd,0x2b,0x2a,0x27,0x6f,0xa2,0xe9,0x09,0xf7,0x30,0x3d,
+ 0xb9,0xd0,0x61,0x42,0x07,0x17,0xc0,0x2f,0xc4,0x6e,0x32,0x15,0x14,0x4b,0xd4,0x4a,
+ 0xd9,0x25,0x0f,0xdc,0xa0,0xe6,0x7b,0x60,0xe6,0x2e,0xfb,0x5b,0xbe,0x1f,0x8d,0x89,
+ 0x7a,0x0b,0xc1,0x75,0x5f,0xc7,0xae,0xdf,0x61,0xc1,0x16,0x47,0x17,0xcb,0x1b,0xf9,
+ 0xf6,0xf0,0x7b,0x6f,0x42,0x19,0xeb,0x7a,0xa7,0x70,0xff,0xaf,0x24,0x3e,0x1a,0xb8,
+ 0xf3,0x04,0x14,0x2a,0x94,0x48,0x05,0x0f,0x5b,0x0d,0xc4,0xe8,0xdf,0xf7,0x5c,0x47,
+ 0x0c,0x2b,0x3f,0x33,0x7a,0x08,0x97,0x1b,0x6d,0x43,0xcb,0x84,0x07,0x75,0x8c,0xc7,
+ 0x68,0x50,0x96,0xff,0xfb,0x14,0x44,0x68,0xc2,0xb5,0xb0,0xcd,0x93,0x66,0x7a,0x06,
+ 0x3d,0xb2,0x3b,0x91,0x26,0x63,0x60,0x7a,0xa2,0x6e,0x9f,0xa7,0xd9,0xcd,0x4c,0x66,
+ 0xa6,0xca,0x54,0x2b,0xc8,0x42,0x43,0x51,0xf2,0x47,0xe3,0xf8,0x7c,0xbe,0xa6,0xd1,
+ 0x54,0xc0,0x28,0xf2,0xd8,0x5b,0x60,0x62,0x89,0x00,0xad,0xd3,0x64,0x6a,0x80,0x20,
+ 0xbd,0xa2,0x09,0x6f,0x83,0x6b,0x44,0xa1,0x9f,0x6b,0x4f,0x22,0x39,0xc3,0x76,0x00,
+ 0xaf,0x8c,0x86,0x4d,0x35,0x8c,0x97,0x25,0x10,0xc5,0x32,0x6b,0x8a,0x80,0xf0,0xfc,
+};
+
+
+/* 317-5021 FD1089B */
+static const UINT8 key_5021[0x2000] =
+{
+ /* data */
+ 0x40,0x7d,0xd5,0x54,0xe5,0x9a,0x53,0xbe,0x3b,0x2e,0xf9,0xcd,0x02,0x24,0x12,0x4f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ /* opcodes */
+ 0xe6,0xd7,0x93,0x50,0x86,0x25,0x28,0xa4,0x96,0x43,0x03,0x61,0x3e,0x8f,0x24,0x57,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+};
+
+
+
+
+
+struct parameters
+{
+ int xor;
+ int s7,s6,s5,s4,s3,s2,s1,s0;
+};
+
+static UINT8 basetable_fd1089[0x100] =
+{
+ 0x00,0x1c,0x75,0x69,0x5d,0x41,0x24,0x38,0x4b,0x67,0xae,0x82,0xea,0xc6,0x03,0x2f,
+ 0x46,0x6a,0xaf,0x83,0xe7,0xcb,0x02,0x2e,0x01,0x1d,0x78,0x64,0x5c,0x40,0x29,0x35,
+ 0x31,0x2d,0x44,0x58,0xe4,0xf8,0x9d,0x81,0x2a,0x06,0xcf,0xe3,0x93,0xbf,0x7a,0x56,
+ 0x3f,0x13,0xd6,0xfa,0x86,0xaa,0x63,0x4f,0xb8,0xa4,0xc1,0xdd,0x6d,0x71,0x18,0x04,
+ 0x0c,0x10,0x79,0x65,0xfc,0xe0,0x85,0x99,0x47,0x6b,0xa2,0x8e,0xbb,0x97,0x52,0x7e,
+ 0x17,0x3b,0xfe,0xd2,0xeb,0xc7,0x0e,0x22,0xa0,0xbc,0xd9,0xc5,0x50,0x4c,0x25,0x39,
+ 0x3d,0x21,0x48,0x54,0x45,0x59,0x3c,0x20,0x26,0x0a,0xc3,0xef,0xc2,0xee,0x2b,0x07,
+ 0x6e,0x42,0x87,0xab,0x8a,0xa6,0x6f,0x43,0x19,0x05,0x60,0x7c,0x61,0x7d,0x14,0x08,
+ 0x09,0x15,0x70,0x6c,0xdc,0xc0,0xa9,0xb5,0x4e,0x62,0xa7,0x8b,0xf7,0xdb,0x12,0x3e,
+ 0x5b,0x77,0xbe,0x92,0xe2,0xce,0x0b,0x27,0x80,0x9c,0xf5,0xe9,0x55,0x49,0x2c,0x30,
+ 0xb0,0xac,0xc9,0xd5,0xed,0xf1,0x98,0x84,0x37,0x1b,0xde,0xf2,0x96,0xba,0x73,0x5f,
+ 0x3a,0x16,0xdf,0xf3,0x9b,0xb7,0x72,0x5e,0xb1,0xad,0xc4,0xd8,0xec,0xf0,0x95,0x89,
+ 0xa8,0xb4,0xd1,0xcd,0xd0,0xcc,0xa5,0xb9,0x1f,0x33,0xf6,0xda,0xfb,0xd7,0x1e,0x32,
+ 0x57,0x7b,0xb2,0x9e,0xb3,0x9f,0x5a,0x76,0x8c,0x90,0xf9,0xe5,0xf4,0xe8,0x8d,0x91,
+ 0x11,0x0d,0x68,0x74,0xe1,0xfd,0x94,0x88,0x66,0x4a,0x8f,0xa3,0x9a,0xb6,0x7f,0x53,
+ 0x36,0x1a,0xd3,0xff,0xca,0xe6,0x23,0x0f,0xbd,0xa1,0xc8,0xd4,0x4d,0x51,0x34,0x28,
+};
+
+
+/* common to FD1089A and FD1089B */
+static struct parameters addr_params[16] =
+{
+ { 0x26, 3,1,7,5,2,4,6,0 },
+ { 0x08, 6,7,4,2,0,5,1,3 },
+ { 0x92, 6,4,5,7,3,0,1,2 },
+ { 0xce, 3,5,6,0,2,1,7,4 },
+ { 0x7e, 7,4,1,0,6,2,3,5 },
+ { 0x52, 1,0,3,7,4,5,2,6 },
+ { 0x44, 0,4,1,2,6,5,7,3 },
+ { 0xe0, 5,7,2,4,3,1,6,0 },
+ { 0x74, 3,1,6,4,5,0,2,7 },
+ { 0xc2, 1,6,0,5,7,2,4,3 },
+ { 0xa4, 7,2,0,6,1,3,4,5 },
+ { 0xea, 0,7,5,3,1,4,2,6 },
+ { 0xc4, 5,3,7,1,4,6,0,2 },
+ { 0x80, 7,6,2,3,0,4,5,1 },
+ { 0x22, 2,5,3,6,7,1,0,4 },
+ { 0xb2, 2,3,4,0,6,7,5,1 },
+};
+
+
+static int decode_fd1089a(int val,int table,int opcode)
+{
+ static struct parameters data_params[16] =
+ {
+ { 0x94, 7,6,4,2,1,5,0,3 },
+ { 0x3f, 7,3,1,2,4,6,0,5 },
+ { 0x99, 4,3,5,6,1,2,0,7 },
+ { 0x8a, 3,5,1,6,0,2,7,4 },
+ { 0xff, 0,7,2,3,6,4,5,1 },
+ { 0xf7, 6,3,7,1,5,4,2,0 },
+ { 0xc6, 3,5,0,4,2,7,1,6 },
+ { 0xac, 0,6,3,5,1,7,4,2 },
+ { 0x56, 6,5,0,1,7,4,2,3 },
+ { 0xec, 4,7,5,0,6,1,2,3 },
+ { 0x8e, 0,4,2,3,1,6,7,5 },
+ { 0x5c, 0,3,1,7,5,2,4,6 },
+ { 0x05, 6,5,3,2,4,0,1,7 },
+ { 0x39, 6,0,3,2,7,4,5,1 },
+ { 0x71, 4,3,7,1,5,6,0,2 },
+ { 0x57, 6,4,7,2,0,5,3,1 },
+ };
+ struct parameters *p = &addr_params[table >> 4];
+ struct parameters *q;
+ int family = table & 0x0e;
+
+
+ /* special case - don't decrypt */
+ if (opcode == 0 && table == 0xff)
+ return val;
+
+ val = BITSWAP8(val, p->s7,p->s6,p->s5,p->s4,p->s3,p->s2,p->s1,p->s0) ^ p->xor;
+
+ if (table & 0x01) val ^= 0x01;
+ if (table & 0x08) val ^= 0xb0;
+ if (opcode) val ^= 0x34;
+
+ val = basetable_fd1089[val];
+
+ if (table & 0x04)
+ {
+ family ^= 1;
+ if (table & 0x40) family ^= 1;
+ }
+ else
+ {
+ if (table & 0x80) family ^= 1;
+ if (opcode) family ^= 1;
+ }
+
+ if (opcode)
+ {
+ if (table & 0x20) family ^= 1;
+ if (table & 0x40) family ^= 1;
+ }
+
+ if (~table & 0x08)
+ {
+ if (val & 0x02) val ^= 0xc0;
+ if ((BIT(val,6) ^ BIT(val,4)) == 0)
+ val = BITSWAP8(val, 7,6,5,4,0,1,3,2);
+ }
+ else
+ {
+ if ((BIT(val,6) ^ BIT(val,4)) == 0)
+ val = BITSWAP8(val, 7,6,5,4,1,0,2,3);
+ }
+ if (!BIT(val,6))
+ val = BITSWAP8(val, 7,6,5,4,2,3,0,1);
+
+ q = &data_params[family];
+
+ val ^= q->xor;
+ val = BITSWAP8(val, q->s7,q->s6,q->s5,q->s4,q->s3,q->s2,q->s1,q->s0);
+
+ return val;
+}
+
+static int decode_fd1089b(int val,int table,int opcode)
+{
+ struct parameters *p = &addr_params[table >> 4];
+
+
+ /* special case - don't decrypt */
+ if (opcode == 0 && table == 0xff)
+ return val;
+
+ val = BITSWAP8(val, p->s7,p->s6,p->s5,p->s4,p->s3,p->s2,p->s1,p->s0) ^ p->xor;
+
+ if (table & 0x01) val ^= 0x01;
+ if (table & 0x08) val ^= 0xb0;
+ if (opcode) val ^= 0x34;
+
+ val = basetable_fd1089[val];
+
+ if (table & 0x04)
+ {
+ val ^= 0x02;
+ if (table & 0x40) val ^= 0x02;
+ }
+ else
+ {
+ if (table & 0x80) val ^= 0x02;
+ if (opcode) val ^= 0x02;
+ }
+
+ if (opcode)
+ {
+ if (table & 0x20) val ^= 0x02;
+ if (table & 0x40) val ^= 0x02;
+ }
+
+ if (table & 0x02)
+ val = BITSWAP8(val, 7,6,5,4,1,0,2,3);
+ if (table & 0x04)
+ val = BITSWAP8(val, 7,6,5,4,2,3,0,1);
+
+ return val;
+}
+
+
+enum
+{
+ FD1089A,
+ FD1089B
+};
+
+static UINT16 fd1089_decrypt(offs_t addr,UINT16 val,const UINT8 *key,int opcode,int cputype)
+{
+ int tbl_num,src;
+
+ /* pick the translation table from bits ff022a of the address */
+ tbl_num = ((addr & 0x000002) >> 1) |
+ ((addr & 0x000008) >> 2) |
+ ((addr & 0x000020) >> 3) |
+ ((addr & 0x000200) >> 6) |
+ ((addr & 0xff0000) >> 12);
+
+ src = ((val & 0x0008) >> 3) |
+ ((val & 0x0040) >> 5) |
+ ((val & 0xfc00) >> 8);
+
+ switch (cputype)
+ {
+ case FD1089A: src = decode_fd1089a(src,key[tbl_num + opcode * 0x1000],opcode); break;
+ case FD1089B: src = decode_fd1089b(src,key[tbl_num + opcode * 0x1000],opcode); break;
+ }
+
+ src = ((src & 0x01) << 3) |
+ ((src & 0x02) << 5) |
+ ((src & 0xfc) << 8);
+
+ return (val & ~0xfc48) | src;
+}
+
+static UINT16 *decrypted;
+
+static void sys16_decrypt(const UINT8 *key,int cputype)
+{
+ UINT16 *rom = (UINT16 *)memory_region(REGION_CPU1);
+ int size = memory_region_length(REGION_CPU1);
+ int A;
+ decrypted = (UINT16 *)auto_malloc(size);
+
+ memory_set_decrypted_region(0, 0x000000, size - 1, decrypted);
+
+ for (A = 0;A < size;A+=2)
+ {
+ UINT16 src = rom[A/2];
+
+ /* decode the opcodes */
+ decrypted[A/2] = fd1089_decrypt(A,src,key,1,cputype);
+
+ /* decode the data */
+ rom[A/2] = fd1089_decrypt(A,src,key,0,cputype);
+ }
+}
+
+void *fd1089_get_decrypted_base(void)
+{
+ return decrypted;
+}
+
+
+
+void fd1089_decrypt_0013A(void)
+{
+ sys16_decrypt(key_0013A,FD1089B);
+}
+
+void fd1089_decrypt_0018(void)
+{
+ sys16_decrypt(key_0018,FD1089A);
+}
+
+void fd1089_decrypt_alexkidd(void)
+{
+ sys16_decrypt(key_alexkidd,FD1089A);
+}
+
+void fd1089_decrypt_0022(void)
+{
+ sys16_decrypt(key_0022,FD1089A);
+}
+
+void fd1089_decrypt_0024(void)
+{
+ sys16_decrypt(key_0024,FD1089B);
+}
+
+void fd1089_decrypt_0027(void)
+{
+ sys16_decrypt(key_0027,FD1089B);
+}
+
+void fd1089_decrypt_0028(void)
+{
+ sys16_decrypt(key_0028,FD1089A);
+}
+
+void fd1089_decrypt_0033(void)
+{
+ sys16_decrypt(key_0033,FD1089A);
+}
+
+void fd1089_decrypt_0034(void)
+{
+ sys16_decrypt(key_0034,FD1089B);
+}
+
+void fd1089_decrypt_0167(void)
+{
+ sys16_decrypt(key_0167,FD1089A);
+}
+
+void fd1089_decrypt_0168(void)
+{
+ sys16_decrypt(key_0168,FD1089B);
+}
+
+void fd1089_decrypt_5021(void)
+{
+ sys16_decrypt(key_5021,FD1089B);
+}
diff --git a/src/mame/machine/fd1094.c b/src/mame/machine/fd1094.c
new file mode 100644
index 00000000000..58bb7c07c6f
--- /dev/null
+++ b/src/mame/machine/fd1094.c
@@ -0,0 +1,843 @@
+/*****************************************************************************
+
+FD1094 encryption
+
+
+The FD1094 is a custom CPU based on the 68000, which runs encrypted code.
+The decryption key is stored in 8KB of battery-backed RAM; when the battery
+dies, the CPU can no longer decrypt the program code and the game stops
+working (though the CPU itself still works - it just uses a wrong decryption
+key).
+
+Being a 68000, the encryption works on 16-bit words. Only words fetched from
+program space are decrypted; words fetched from data space are not affected.
+
+The decryption can logically be split in two parts. The first part consists
+of a series of conditional XORs and bitswaps, controlled by the decryption
+key, which will be described in the next paragraph. The second part does a
+couple more XORs which don't depend on the key, followed by the replacement
+of several values with FFFF. This last step is done to prevent usage of any
+PC-relative opcode, which would easily allow an intruder to dump decrypted
+values from program space. The FFFF replacement may affect either ~300 values
+or ~5000, depending on the decryption key.
+
+The main part of the decryption can itself be subdivided in four consecutive
+steps. The first one is executed only if bit 15 of the encrypted value is 1;
+the second one only if bit 14 of the _current_ value is 1; the third one only
+if bit 13 of the current value is 1; the fourth one is always executed. The
+first three steps consist of a few conditional XORs and a final conditional
+bitswap; the fourth one consists of a fixed XOR and a few conditional
+bitswaps. There is, however, a special case: if bits 15, 14 and 13 of the
+encrypted value are all 0, none of the above steps are executed, replaced by
+a single fixed bitswap.
+
+In the end, the decryption of a value at a given address is controlled by 32
+boolean variables; 8 of them change at every address (repeating after 0x2000
+words), and constitute the main key which is stored in the battery-backed
+RAM; the other 24 don't change with the address, and depend solely on bytes
+1, 2, and 3 of the battery-backed RAM, modified by the "state" which the CPU
+is in.
+
+The CPU can be in one of 256 possible states. The 8 bits of the state modify
+the 24 bits of the global key in a fixed way, which isn't affected by the
+battery-backed RAM.
+On reset, the CPU goes in state 0x00. The state can then be modified by the
+program, executing the instruction
+CMPI.L #$00xxFFFF, D0
+where xx is the state.
+When an interrupt happens, the CPU enters "irq mode", forcing a specific
+state, which is stored in byte 0 of the battery-backed RAM. Irq mode can also
+be selected by the program with the instruction
+CMPI.L #$0200FFFF, D0
+When RTE is executed, the CPU leaves irq mode, restoring the previous state.
+This can also be done by the program with the instruction
+CMPI.L #$0300FFFF, D0
+
+Since bytes 0-3 of the battery-backed RAM are used to store the irq state and
+the global key, they have a double use: this one, and the normal 8-bit key
+that changes at every address. To prevent that double use, the CPU fetches
+the 8-bit key from a different place when decrypting words 0-3, but this only
+happens after wrapping around at least once; when decrypting the first four
+words of memory, which correspond the the initial SP and initial PC vectors,
+the 8-bit key is taken from bytes 0-3 of RAM. Instead, when fetching the
+vectors, the global key is handled differently, to prevent double use of
+those bytes. But this special handling of the global key doesn't apply to
+normal operations: reading words 1-3 from program space results in bytes 1-3
+of RAM being used both for the 8-bit key and for the 24-bit global key.
+
+
+
+There is still uncertainty about the assignment of two global key bits.
+
+key[1]
+------
+key_0b invert; \ bits 7,5 always 1 for now (but 0 in a bad CPU)
+global_xor0; /
+key_5b invert; bit 6
+key_2b invert; bit 4
+key_1b invert; bit 3 always 1 for now (but 0 in a bad CPU)
+global_xor1; bit 2
+key_0c invert; bit 1
+global_swap2; bit 0
+
+key[2]
+------
+key_1a invert; bit 7 always 1 for now (but 0 in a bad CPU)
+key_6b invert; bit 6 always 1 for now (but 0 in a bad CPU)
+global_swap0a; bit 5
+key_7a invert; bit 4
+key_4a invert; bit 3
+global_swap0b; bit 2
+key_6a invert; bit 1
+key_3a invert; bit 0
+
+key[3]
+------
+key_2a invert; bit 7 always 1 for now (but 0 in a bad CPU)
+global_swap3; bit 6 always 1 for now (but 0 in a bad CPU)
+key_5a_invert; bit 5
+global_swap1; bit 4
+key_3b invert; bit 3
+global_swap4; bit 2
+key_0a invert; bit 1
+key_4b invert; bit 0
+
+
+Analysis of the data contained in the 8k key data indicates some regularities.
+To begin with, in all the keys seen so far, bit 7 ($80) in key values at
+addresses $0004-$0FFF is always set to 1. Similarly, bit 6 ($40) in key values
+at addresses $1000-$1FFF is always set to 1.
+
+Even more interesting, however, is that analyzing the low 6 bits of the key
+data reveals that a simple linear congruential generator has been used
+consistently to generate the key bits. The LCG is of the form:
+
+ temp = A * val;
+ val' = temp + (temp << 16);
+
+and it appears to be calculated to at least 22 bits. In all cases seen so far,
+the value of 'A' is fixed at $29. To generate the low 6 bits of the key, the
+result of the LCG is shifted right 16 bits and inverted.
+
+The following pseudo-code will generate 7 of the 8 bits of the key data
+successfully for all known keys, given the values of the 'shift' and 'B'
+parameters, as well as an initial 'seed' for the generator:
+
+void genkey(UINT32 seed, UINT8 *output)
+{
+ int bytenum;
+
+ for (bytenum = 4; bytenum < 8192; bytenum++)
+ {
+ UINT8 byteval;
+
+ seed = seed * 0x29;
+ seed += seed << 16;
+
+ byteval = (~seed >> 16) & 0x3f;
+ byteval |= (bytenum < 0x1000) ? 0x80 : 0x40;
+
+ output[bytenum] = byteval;
+ }
+}
+
+This only leaves one bit per key value (and the global key) left to determine.
+It is worth pointing out that this remaining bit is the same bit that controls
+how many opcodes to blank to $FFFF: 0 means a smaller subset (~300), while 1
+indicates a much larger subset (~5000). Looking at the correlations between
+where the key has this bit set to 0, and the presence of opcodes that would
+be blanked as a result, seems to imply that the key is generated based on the
+plaintext. That is, this final bit is set to 1 by default (hence blanking
+more aggressively), and cleared to 0 if any plaintext words affected by the
+byte in question would be incorrectly blanked.
+
+
+When the keys were generated, the LCG seed wasn't input directly. Instead,
+another value was entered, which in most cases was derived from the current
+date/time. The LCG seed is obtained from that value via a multiplication.
+The current date/time was also used in most cases to select the three bytes of
+the global key. Interestingly, the global key must be inverted and read in
+decimal representation to see this, while the seed must be read in hexadecimal
+representation.
+
+For some reason, bit 3 of the first byte of the global key was always set to 1
+regardless of the value input into the key generator program, so e.g. the
+input "88 01 23" would become "80 01 23".
+
+The very first byte of internal RAM, which indicates the IRQ state, doesn't
+seem to follow the same procedure. The IRQ state was probably decided at an
+earlier time, not during the final key generation.
+
+
+summary:
+--------
+
+ +------------------------------------------------- 317- part #
+ | +----------------------------------------- IRQ state (hex)
+ | | +----------------------------------- global key (inverted, dec)
+ | | | +-------------------------- main key seed (hex) (LCG seed = seed * 0x2F1E21)
+ | | | | +----------------- game
+ | | | | | +---------- year
+ | | | | | | +- inferred key generation date
+ | | | | | | |
+-------- -- -------- ------ -------- ---- --------------------------
+0041 12 87 06 19 895963 bullet 1987 87/06/19 (atypical)
+0045 34 97 02 39 384694 suprleag 1987 (atypical)
+0049 F1 87 10 28 8932F7 shinobi2 1987 87/10/28 (atypical)
+0050 F1 87 10 28 8932F7 shinobi1 1987 87/10/28 (atypical)
+0053 00 00 00 00 020000 sonicbom 1987 atypical
+0056 CD 80 01 23 032ABC thndrbld 1987 88/01/23 (atypical)
+0059 aceattac 1988
+0060 45 80 03 30 343210 aceattaa 1988 88/03/30 (atypical)
+0065 altbeaj1 1988
+0068 20 80 06 10 880610 altbeaj3 1988 88/06/10
+0070 59 80 08 06 880806 passshtj 1988 88/08/06
+0074 47 80 08 06 880806 passshta 1988 88/08/06
+0071 20 80 08 09 880809 passsht 1988 88/08/09
+0079 98 80 09 05 880906 exctleag 1988 88/09/05-88/09/06 (atypical)
+0080 96 80 08 26 880826 passsht 1988 88/08/26
+0058-02C FF 80 10 07 881007 sspirtfc 1988 88/10/07
+0084 0E 80 10 31 881031 wb31 1988 88/10/31
+0085 26 80 11 08 881108 wb32 1988 88/11/08
+0087 69 80 11 08 881108 wb34 1988 88/11/08
+0089 52 80 11 29 881129 wb33 1988 88/11/29
+0058-03B 71 80 11 25 881125 ggroundj 1988 88/11/25
+0058-03C 04 80 11 27 881127 gground 1988 88/11/27
+0090 AB 80 01 27 247333 wrestwa1 1989 atypical
+0091 68 80 11 27 881127 tetris1 1988 88/11/27
+0092 10 80 11 28 881128 tetris2 1988 88/11/28
+0093 25 80 11 29 881129 tetris 1988 88/11/29
+0093A 35 02 09 17 900209 tetris3 1988 90/02/09
+0096 21 80 11 21 881121 ddux 1988 88/11/21
+0102 AB 80 02 03 04588A wrestwa2 1989 atypical
+0058-04B 27 03 27 14 032714 crkdownj 1989 89/03/27 14:xx
+0058-04C 19 03 27 05 032705 crkdown 1989 89/03/27 05:xx
+0058-04D DC 03 27 06 032706 crkdownu 1989 89/03/27 06:xx
+0110 19 81 03 29 032916 goldnax1 1989 89/03/29 16:xx
+0115 12 04 05 11 040511 bayroutj 1989 89/04/05 11:xx
+0116 11 03 30 09 033009 bayroute 1989 89/03/30 09:xx
+0118 22 81 03 07 030719 toutrun 1989 89/03/07 19:xx
+toutrun2 22 81 03 07 031113 toutrun2 1989 89/03/11 13:xx (atypical)
+0120 0D 81 03 29 032916 goldnax3 1989 89/03/29 16:xx
+0121 35 81 03 29 032916 goldnaxj 1989 89/03/29 16:xx
+0122 03 81 04 04 890404 goldnaxu 1989 89/04/04
+0058-05B 92 81 06 09 890609 sgmastj 1989 89/06/09
+0058-05C 30 81 06 13 890613 sgmastc 1989 89/06/13
+0058-05D sgmast 1989
+0124A 80 06 21 11 890621 smgpj 1989 89/06/21 11:xx
+0125A DE 06 15 16 890615 smgpu 1989 89/06/15 16:xx
+0126 54 05 28 01 890528 smgp5 1989 89/05/28 01:xx
+0126A 74 06 16 15 890616 smgp 1989 89/06/16 15:xx
+0127A 5F 81 07 06 890706 fpoint 1989 89/07/06
+0128 55 00 28 20 890828 eswatj 1989 89/08/28 20:xx
+0129 0A 00 28 20 890828 eswatu 1989 89/08/28 20:xx
+0130 EC 00 28 19 890828 eswat 1989 89/08/28 19:xx
+0134 DE 81 11 30 891130 loffirej 1989 89/11/30
+0135 98 81 11 31 891131 loffireu 1989 89/11/31
+0136 12 81 11 29 891129 loffire 1989 89/11/29
+0139 49 03 25 15 891125 bloxeed 1990 89/11/25 15:xx
+0142 91 01 24 17 900124 mvpj 1989 90/01/24 17:xx
+0143 20 02 02 18 900202 mvp 1989 90/02/02 18:xx
+0144 2E 02 23 18 022318 rachero 1989 90/02/23 18:xx
+0058-06B 88 03 15 09 900315 roughrac 1990 90/03/15 09:xx
+0146 10 04 26 17 900426 astormj 1990 90/04/26 17:xx
+0147 2D 04 14 14 900414 astormu 1990 90/04/14 14:xx
+0148 50 04 26 15 900426 astorm3 1990 90/04/26 15:xx
+0153 FC 04 10 14 900410 pontoon 1990 90/04/10 14:xx
+0157 20 07 20 10 900720 mwalkj 1990 90/07/20 10:xx
+0158 DE 07 15 15 900715 mwalku 1990 90/07/15 15:xx
+0159 39 07 20 10 900720 mwalk 1990 90/07/20 10:xx
+0162 8F 01 14 15 900914 gprider1 1990 90/09/14 15:xx
+0163 99 01 13 15 900913 gprider 1990 90/09/13 15:xx
+5023 EF 04 18 05 900917 ryukyu 1990 90/09/17 12:18? (atypical)
+0165 56 82 11 25 901125 lghostu 1990 90/11/25
+0166 A2 82 11 24 901124 lghost 1990 90/11/24
+0169B 48 06 35 32 901205 abcop 1990 90/12/05 14:35? (atypical)
+0058-08B 4E 04 17 15 910206 qsww 1991 91/02/06 12:17? (atypical)
+0175 91 83 03 22 910322 cltchtrj 1991 91/03/22
+0176 FC 83 03 14 910314 cltchitr 1991 91/03/14
+0179A 73 06 55 17 910318 cottonj 1991 91/03/18 14:55? (atypical)
+0180 73 03 53 00 910403 cottonu 1991 91/04/03 11:53? (atypical)
+0181A 73 06 55 17 910318 cotton 1991 91/03/18 14:55? (atypical)
+0058-09D 91 83 06 26 910618 dcclubfd 1991 91/06/18-91/06/26 (atypical)
+0182 07 07 12 14 921401 ddcrewj 1991 92/07/12 14:01? (atypical)
+0184 07 07 12 16 921622 ddcrew2 1991 92/07/12 16:22? (atypical)
+0186 5F 83 07 01 912030 ddcrewu 1991 92/07/01 20:30? (atypical)
+0190 07 07 17 16 921716 ddcrew 1991 92/07/17 17:16? (atypical)
+ddcrew1 91 84 07 42 910744 ddcrew1 1991 92/07/xx 07:44? (atypical)
+0196 4A 20 12 22 920623 desertbr 1992 92/06/23 20:12? (atypical)
+0197A 3F 84 06 19 920612 wwallyja 1992 92/06/12-92/06/19 (atypical)
+0197B 3F 84 06 19 920612 wwallyj 1992 92/06/12-92/06/19 (atypical)
+
+----
+
+Bad CPUs that gave some more information about the global key:
+
+ global01 global02 global03
+ -------- -------- --------
+ ..... .. ..
+unknown 11111111 11110110 10111110 (Shinobi 16A, part no. unreadable, could be dead)
+unknown 10101011 11111000 11010101 (unknown ddcrewa key)
+dead 00001111 00001111 00001111 (Alien Storm CPU with no battery)
+bad 11100000 10101011 10111001 (flaky 317-0049)
+
+----
+
+Notes:
+
+We start in state 0.
+Vectors are fetched:
+ SP.HI @ $000000 -> mainkey = key[0], globalkey = { $00, $00, $00 }, less aggressive blanking
+ SP.LO @ $000002 -> mainkey = key[1], globalkey = { $00, $00, $00 }, less aggressive blanking
+ PC.HI @ $000004 -> mainkey = key[2], globalkey = { key[1], $00, $00 }
+ PC.LO @ $000006 -> mainkey = key[3], globalkey = { key[1], key[2], $00 }
+
+driver FD1094 SP plain SP enc PC plain PC enc States Used
+-------- -------- -------- -------- -------- -------- -----------
+aceattaa 317-0060 00000000 A711AF59 00000400 AF59EADD 00 17 31 45 90 FC
+altbeaj3 317-0068 FFFFFF00 B2F7F299 00000400 CCDDEF58 00 0F 18 20 93 A7 D8
+altbeaj1 317-0065 C9C5F299 CCDDECDD
+bayroute 317-0116 00504000 5EB40000 00001000 5533A184 00 04 11 18
+bayroutj 317-0115 00504000 56150000 00001000 85948DCF 00 05 12 16
+bullet 317-0041 00000000 57355D96 00001882 8DDC8CF4 (deduced, not 100% sure)
+cotton 317-0181a 00204000 5DB20000 00000716 CCDD0716 00 0E 73
+cottonu 317-0180 00204000 5DB20000 00000716 A1840716 00 0E 73
+cottonj 317-0179a 00204000 5DB20000 00000716 CCDD0716 00 0E 73
+ddux 317-0096 00000000 5F94AF59 00000406 AF5987A0 00 21 28 70 D9
+eswat 317-0130 00000000 A711AF59 00000400 5533BC59 00 05 0C EC FA
+eswatu 317-0129 00000000 5537AF59 00000400 55334735 00 0A 12 C3 CC
+eswatj 317-0128 00000000 A711AF59 00000400 55334735 00 63 CB D5
+exctleag 317-0079? 00000000 5537AF59 00000410 83018384 (deduced, not 100% sure)
+fpoint 317-0127A 00000000 AF59AF59 00001A40 8DDC9960 00 15 35 5F 82 DB
+fpoint1 317-0127A 00000000 AF59AF59 00001A40 8DDC9960 00 15 35 5F 82 DB
+goldnaxu 317-0122 FFFFFF00 E53AF2B9 00000400 A184A196 00 03 51 72 99 F6
+goldnaxj 317-0121 FFFFFF00 C9D6F2B9 00000400 AF59A785 00 12 35 58 7A 9E
+goldnax3 317-0120 FFFFFF00 ED62F2B9 00000400 AF59A785 00 0A 0D 44 C7 EF
+goldnax1 317-0110 FFFFFF00 ED62F2B9 00000400 AF59A785 00 19 2E 31 48 5D
+mvp 317-0143 00000000 5F94A711 00000416 BD59DC5B 00 19 20 88 98
+mvpj 317-0142 00000000 5F94AF59 00000416 BD599C7D 00 19 35 91 DA
+passsht 317-0080 00000000 AF59AF59 00003202 C2003923 00 11 52 96 EE
+passshta 317-0074 00000000 AF59AF59 000031E4 C2003F8C 00 12 47 83 A7
+passshtj 317-0070 00000000 5D92AF59 000031E4 C2003F8C 00 12 59 83 FE
+ryukyu 317-5023 00203800 AF49D30B 0000042E FC5863B5 00 DC EF
+shinobi2 317-0049 FFFFFF00 C9C5F25F 00000400 AF598395 00 53 88 9B 9C F1
+sonicbom 317-0053 00000000 5735AF59 00001000 FC587133 00
+suprleag 317-0045? 00000000 A711AF59 BD59CE5B
+tetris2 317-0092 00000000 5735AF59 00000410 AF598685 00 10 52 74 97 FC
+tetris1 317-0091 00000000 5D92AF59 00000410 AF59AE58 99 25 42 5B 68 FC
+wb34 317-0087 FFFFFF7E B2978997 00000500 AF590500 00 11 64 69 82
+wb33 317-0089 FFFFFF7E E5C78997 00000500 AF590500 00 23 40 52 71
+wb32 317-0085 FFFFFF7E B2F78997 00000500 AF590500 00 10 13 26 77
+wrestwa2 317-0102 00000000 5D96AF59 00000414 EE588E5B 00 12 A7 AB CC F9 FC
+wrestwa1 317-0090 00000000 5D96AF59 00000414 8301AE18 00 12 A7 AB CC F9 FC
+
+suprleag pc possibilities:
+ 101E -> follows an RTS
+ 108E -> follows 3 NOPs
+ 11C4
+ 11C8
+ 1212
+ 1214
+ 1218
+ 1282
+ 1284
+ 1288
+ 1342
+ 1416
+ 141C
+ 1486
+ 148C
+ 1606
+ 1E52
+ 1E54
+
+bullet pc possibilities:
+ 0822
+ 0824
+ 0882
+ 0884
+ 0C08
+ 137C
+ 1822
+ 1824
+ 1882
+ 1884
+ 1C08
+
+tetris1:
+ 410: 4ff9 0000 0000 lea $0.l, a7
+ 416: 46fc 2700 move #$2700, sr
+ 41a: 0c80 005b ffff cmpi.l #$5bffff, d0
+
+ 400: 4e71 nop
+ 402: 4e73 rte
+
+tetris2:
+ 410: 4ff9 0000 0000 lea $0.l, a7
+ 416: 46fc 2700 move #$2700, sr
+ 41a: 0c80 0052 ffff cmpi.l #$52ffff, d0
+
+ 400: 4e71 nop
+ 402: 4e73 rte
+
+wrestwa1:
+ 414: 4ff8 0000 lea $0.w, a7
+ 418: 46fc 2700 move #$2700, sr
+ 41c: 0c80 00fc ffff cmpi.l #$fcffff, d0
+
+mvp:
+ 416: 4ff8 0000 lea $0.w, a7
+ 41a: 46fc 2700 move #$2700, sr
+ 41e: 7000 moveq #0, d0
+ 420: 2200 move.l d0, d1
+ ...
+ 42c: 2e00 move.l d0, d7
+ 42e: 2040 movea.l d0, a0
+ ...
+ 43a: 2c40 movea.l d0, a6
+ 43c: 0c80 0098 ffff cmpi.l #$98ffff, d0
+
+wb34:
+ 500: 46fc 2700 move #$2700, sr
+ 504: 0c80 0064 ffff cmpi.l #$64ffff, d0
+
+goldnaxu:
+ 400: 6000 000c bra $40e
+ 40e: 4ff8 ff00 lea $ff00.w, a7
+ 412: 46fc 2700 move #$2700, sr
+ 416: 0c80 0072 ffff cmpi.l #$72ffff, d0
+
+ryukyu:
+ 42e: 4e71 nop
+ ...
+ 440: 0c80 00dc ffff cmpi.l #$dcffff, d0
+
+eswat:
+ 400: 4ff8 0000 lea $0.w, a7
+ 404: 46fc 2700 move #$2700, sr
+ 408: 0c80 000c ffff cmpi.l #$cffff, d0
+
+*****************************************************************************/
+
+#include "driver.h"
+#include "fd1094.h"
+
+
+/*
+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.
+*/
+static const UINT16 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
+};
+
+static UINT8 masked_opcodes_lookup[2][65536/8/2];
+static UINT8 masked_opcodes_created = FALSE;
+
+static 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 */
+ if (!masked_opcodes_created)
+ {
+ masked_opcodes_created = TRUE;
+ for (j = 0; j < ARRAY_LENGTH(masked_opcodes); j++)
+ {
+ UINT16 opcode = masked_opcodes[j];
+ masked_opcodes_lookup[0][opcode >> 4] |= 1 << ((opcode >> 1) & 7);
+ masked_opcodes_lookup[1][opcode >> 4] |= 1 << ((opcode >> 1) & 7);
+ }
+ for (j = 0; j < 65536; j += 2)
+ {
+ if ((j & 0xff80) == 0x4e80 || (j & 0xf0f8) == 0x50c8 || (j & 0xf000) == 0x6000)
+ masked_opcodes_lookup[1][j >> 4] |= 1 << ((j >> 1) & 7);
+ }
+ }
+
+ if ((masked_opcodes_lookup[moreffff][dec >> 4] >> ((dec >> 1) & 7)) & 1)
+ dec = -1;
+
+ return dec;
+}
+
+
+/* note: address is the word offset (physical address / 2) */
+static int decode(int address,int val,UINT8 *main_key,int gkey1,int gkey2,int gkey3,int vector_fetch)
+{
+ int mainkey,key_F,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;
+
+
+ /* for address xx0000-xx0006 (but only if >= 000008), use key xx2000-xx2006 */
+ if ((address & 0x0ffc) == 0 && address >= 4)
+ mainkey = main_key[(address & 0x1fff) | 0x1000];
+ else
+ mainkey = main_key[address & 0x1fff];
+
+ if (address & 0x1000) key_F = BIT(mainkey,7);
+ else key_F = BIT(mainkey,6);
+
+ /* the CPU has been verified to produce different results when fetching opcodes
+ from 0000-0006 than when fetching the inital SP and PC on reset. */
+ if (vector_fetch)
+ {
+ if (address <= 3) gkey3 = 0x00; // supposed to always be the case
+ if (address <= 2) gkey2 = 0x00;
+ if (address <= 1) gkey1 = 0x00;
+ if (address <= 1) key_F = 0;
+ }
+
+ global_xor0 = 1^BIT(gkey1,5);
+ 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);
+ 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);
+ 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);
+ 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 = BITSWAP16(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 = BITSWAP16(val, 15,14,13, 9,11,10,12, 8, 2, 6, 5, 4, 3, 7, 1, 0); // 12,9,7,2
+
+ val = 0x6561 ^ BITSWAP16(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 = BITSWAP16(val, 15,14,10,12,11,13, 9, 4, 7, 6, 5, 8, 3, 2, 1, 0); // 13,10,8,4
+
+ val = 0x3523 ^ BITSWAP16(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 = BITSWAP16(val, 0,14,13,12,15,10, 9, 8, 7, 6,11, 4, 3, 2, 1, 5); // 15,11,5,0
+
+ val = 0x99a5 ^ BITSWAP16(val, 10, 2,13, 7, 8, 0, 3,14, 6,15, 1,11, 9, 4, 5,12);
+ }
+
+ val = 0x87ff ^ BITSWAP16(val, 5,15,13,14, 6, 0, 9,10, 4,11, 1, 2,12, 3, 7, 8);
+
+ if (!global_swap4) val = BITSWAP16(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 = BITSWAP16(val, 15,12,14,13,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); // 12-13-14
+ if (!global_swap2) val = BITSWAP16(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 = BITSWAP16(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 = BITSWAP16(val, 15,12,13,14,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); // 14-12
+ if (!global_swap1) val = BITSWAP16(val, 15,14,13,12, 9, 8,11,10, 7, 6, 5, 4, 3, 2, 1, 0); // 11...8
+ if (!key_5a) val = BITSWAP16(val, 15,14,13,12,11,10, 9, 8, 4, 5, 7, 6, 3, 2, 1, 0); // 7...4
+ if (!global_swap0a) val = BITSWAP16(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);
+}
+
+
+static int global_key1,global_key2,global_key3;
+
+int fd1094_decode(int address,int val,UINT8 *key,int vector_fetch)
+{
+ if (!key) return 0;
+
+ return decode(address,val,key,global_key1,global_key2,global_key3,vector_fetch);
+}
+
+int fd1094_set_state(UINT8 *key,int state)
+{
+ static int selected_state,irq_mode;
+
+ if (!key) return 0;
+
+ if (state == -1)
+ state = selected_state;
+
+ switch (state & 0x300)
+ {
+ case 0x0000: // 0x00xx: select state xx
+ selected_state = state & 0xff;
+ break;
+
+ case FD1094_STATE_RESET: // 0x01xx: select state xx and exit irq mode
+ selected_state = state & 0xff;
+ irq_mode = 0;
+ break;
+
+ case FD1094_STATE_IRQ: // 0x02xx: enter irq mode
+ irq_mode = 1;
+ break;
+
+ case FD1094_STATE_RTE: // 0x03xx: exit irq mode
+ irq_mode = 0;
+ break;
+ }
+
+ if (irq_mode)
+ state = key[0];
+ else
+ state = selected_state;
+
+ global_key1 = key[1];
+ global_key2 = key[2];
+ global_key3 = key[3];
+
+ if (state & 0x0001)
+ {
+ global_key1 ^= 0x04; // global_xor1
+ global_key2 ^= 0x80; // key_1a invert
+ global_key3 ^= 0x80; // key_2a invert
+ }
+ if (state & 0x0002)
+ {
+ global_key1 ^= 0x01; // global_swap2
+ global_key2 ^= 0x10; // key_7a invert
+ global_key3 ^= 0x01; // key_4b invert
+ }
+ if (state & 0x0004)
+ {
+ global_key1 ^= 0x80; // key_0b invert
+ global_key2 ^= 0x40; // key_6b invert
+ global_key3 ^= 0x04; // global_swap4
+ }
+ if (state & 0x0008)
+ {
+ global_key1 ^= 0x20; // global_xor0
+ global_key2 ^= 0x02; // key_6a invert
+ global_key3 ^= 0x20; // key_5a invert
+ }
+ if (state & 0x0010)
+ {
+ global_key1 ^= 0x02; // key_0c invert
+ global_key1 ^= 0x40; // key_5b invert
+ global_key2 ^= 0x08; // key_4a invert
+ }
+ if (state & 0x0020)
+ {
+ global_key1 ^= 0x08; // key_1b invert
+ global_key3 ^= 0x08; // key_3b invert
+ global_key3 ^= 0x10; // global_swap1
+ }
+ if (state & 0x0040)
+ {
+ global_key1 ^= 0x10; // key_2b invert
+ global_key2 ^= 0x20; // global_swap0a
+ global_key2 ^= 0x04; // global_swap0b
+ }
+ if (state & 0x0080)
+ {
+ global_key2 ^= 0x01; // key_3a invert
+ global_key3 ^= 0x02; // key_0a invert
+ global_key3 ^= 0x40; // global_swap3
+ }
+ return (state & 0xff) | (irq_mode ? FD1094_STATE_IRQ : FD1094_STATE_RESET);
+}
+
+
+#ifdef MAME_DEBUG
+
+/*
+
+// Possible: global=12A8F8E5 seed=0AD691 pc=1882
+// Possible: global=12AAF8E5 seed=0AD691 pc=1882
+// Possible: global=82A8F8EC seed=24921C pc=1882
+// Possible: global=82AAF8EC seed=24921C pc=1882
+// Possible: global=92A8F8EC seed=3D5C17 pc=1882
+// Possible: global=92AAF8EC seed=3D5C17 pc=1882
+static const fd1094_constraint bullet_constraints[] =
+{
+ // main entry point
+ { 0x001882, FD1094_STATE_RESET | 0x00, 0x4ff8, 0xffff }, // lea $0.w,a7
+ { 0x001884, FD1094_STATE_RESET | 0x00, 0x0000, 0xffff },
+ { 0x001886, FD1094_STATE_RESET | 0x00, 0x46fc, 0xffff }, // move #$2700,sr
+ { 0x001888, FD1094_STATE_RESET | 0x00, 0x2700, 0xffff },
+ { 0x00188a, FD1094_STATE_RESET | 0x00, 0x0c80, 0xffff }, // cmpi.l #$00xxffff,d0
+ { 0x00188c, FD1094_STATE_RESET | 0x00, 0x0000, 0xff00 },
+ { 0x00188e, FD1094_STATE_RESET | 0x00, 0xffff, 0xffff },
+
+ // IRQ4 entry point
+ { 0x000418, FD1094_STATE_IRQ | 0x00, 0x48e7, 0xffff }, // movem.l d0-d7/a0-a6,-(a7)
+ { 0x00041a, FD1094_STATE_IRQ | 0x00, 0xfffe, 0xffff },
+
+ // IRQ4 exit points
+ { 0x000612, FD1094_STATE_IRQ | 0x00, 0x4cdf, 0xffff }, // movem.l (a7)+,d0-d7/a0-a6
+ { 0x000614, FD1094_STATE_IRQ | 0x00, 0x7fff, 0xffff },
+ { 0x000616, FD1094_STATE_IRQ | 0x00, 0x4e73, 0xffff }, // rte
+ { 0 }
+};
+
+// Possible: global=FCAFF9F9 seed=177AC6 pc=0400
+static const fd1094_constraint altbeaj1_constraints[] =
+{
+ // main entry point
+ { 0x000400, FD1094_STATE_RESET | 0x00, 0x6000, 0xffff }, // bra $40e
+ { 0x000402, FD1094_STATE_RESET | 0x00, 0x000c, 0xffff },
+ { 0x00040e, FD1094_STATE_RESET | 0x00, 0x4ff8, 0xffff }, // lea $ff00.w,a7
+ { 0x000410, FD1094_STATE_RESET | 0x00, 0xff00, 0xffff },
+ { 0x000412, FD1094_STATE_RESET | 0x00, 0x46fc, 0xffff }, // move #$2700,sr
+ { 0x000414, FD1094_STATE_RESET | 0x00, 0x2700, 0xffff },
+ { 0x000416, FD1094_STATE_RESET | 0x00, 0x0c80, 0xffff }, // cmpi.l #$00xxffff,d0
+ { 0x000418, FD1094_STATE_RESET | 0x00, 0x0000, 0xff00 },
+ { 0x00041a, FD1094_STATE_RESET | 0x00, 0xffff, 0xffff },
+
+ // IRQ4 entry point
+ { 0x000404, FD1094_STATE_IRQ | 0x00, 0x6000, 0xffff }, // bra $2ac4
+ { 0x000406, FD1094_STATE_IRQ | 0x00, 0x26be, 0xffff },
+ { 0x002ac4, FD1094_STATE_IRQ | 0x00, 0x48e7, 0xffff }, // movem.l d0-d7/a0-a6,-(a7)
+ { 0x002ac6, FD1094_STATE_IRQ | 0x00, 0xfffe, 0xffff },
+
+ // IRQ4 exit points
+ { 0x002ca4, FD1094_STATE_IRQ | 0x00, 0x4cdf, 0xffff }, // movem.l (a7)+,d0-d7/a0-a6
+ { 0x002ca6, FD1094_STATE_IRQ | 0x00, 0x7fff, 0xffff },
+ { 0x002ca8, FD1094_STATE_IRQ | 0x00, 0x4e73, 0xffff }, // rte
+ { 0x002cc4, FD1094_STATE_IRQ | 0x00, 0x3f3c, 0xffff }, // move #$2300,-(a7)
+ { 0x002cc6, FD1094_STATE_IRQ | 0x00, 0x2300, 0xffff },
+ { 0x002cc8, FD1094_STATE_IRQ | 0x00, 0x4e73, 0xffff }, // rte
+
+ // other IRQ entry points
+ { 0x000408, FD1094_STATE_IRQ | 0x00, 0x6000, 0xffff }, // bra $40c
+ { 0x00040a, FD1094_STATE_IRQ | 0x00, 0x0002, 0xffff },
+ { 0x00040c, FD1094_STATE_IRQ | 0x00, 0x4e73, 0xffff }, // rte
+
+ { 0 }
+};
+
+*/
+
+#endif
diff --git a/src/mame/machine/fd1094.h b/src/mame/machine/fd1094.h
new file mode 100644
index 00000000000..5e4483131ad
--- /dev/null
+++ b/src/mame/machine/fd1094.h
@@ -0,0 +1,19 @@
+#define FD1094_STATE_RESET 0x0100
+#define FD1094_STATE_IRQ 0x0200
+#define FD1094_STATE_RTE 0x0300
+
+int fd1094_set_state(UINT8 *key,int state);
+int fd1094_decode(int address,int val,UINT8 *key,int vector_fetch);
+
+#ifdef MAME_DEBUG
+
+typedef struct _fd1094_constraint fd1094_constraint;
+struct _fd1094_constraint
+{
+ offs_t pc;
+ UINT16 state;
+ UINT16 value;
+ UINT16 mask;
+};
+
+#endif
diff --git a/src/mame/machine/fddebug.c b/src/mame/machine/fddebug.c
new file mode 100644
index 00000000000..d05c9f6e722
--- /dev/null
+++ b/src/mame/machine/fddebug.c
@@ -0,0 +1,2427 @@
+/***************************************************************************
+
+ fddebug.c
+
+ FD1094 decryption helper routines.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ 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
+
+***************************************************************************/
+
+#ifdef MAME_DEBUG
+
+#include "driver.h"
+#include "machine/fd1094.h"
+#include "cpu/m68000/m68k.h"
+
+#include "debug/debugcmd.h"
+#include "debug/debugcon.h"
+#include "debug/debugcpu.h"
+#include "debug/debugvw.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 */
+typedef struct _fd1094_possibility fd1094_possibility;
+struct _fd1094_possibility
+{
+ offs_t basepc; /* starting PC of the possibility */
+ int length; /* number of words */
+ UINT8 instrbuffer[10]; /* instruction data for disassembler */
+ UINT8 keybuffer[10]; /* array of key values to produce the instruction data */
+ UINT8 iffy; /* is this an iffy possibility? */
+ char dasm[256]; /* disassembly */
+};
+
+/* an entry in the opcode table */
+typedef struct _optable_entry optable_entry;
+struct _optable_entry
+{
+ UINT32 flags; /* per-opcode flags */
+ const char * string; /* identifying string */
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+/* array of PCs not to stop at */
+static UINT8 * ignorepc;
+static UINT8 ignore_all;
+
+/* array of information about each opcode */
+static optable_entry * optable;
+
+/* buffer for undoing operations */
+static UINT8 * undobuff;
+
+/* array of possible instruction decodings */
+static fd1094_possibility posslist[4*4*4*4*4];
+static int posscount;
+
+/* array of possible seeds */
+static UINT32 * possible_seed;
+
+/* array of constraints */
+static fd1094_constraint constraints[MAX_CONSTRAINTS];
+static int constcount;
+
+/* stack of search addresses */
+static UINT32 searchstack[MAX_SEARCH_DEPTH];
+static int searchsp;
+
+/* current key generation parameters */
+static UINT32 fd1094_global;
+static UINT32 fd1094_seed;
+static UINT8 keydirty;
+
+/* pointers to our data */
+static UINT16 * coderegion;
+static UINT32 coderegion_words;
+static UINT8 * keyregion;
+static UINT16 * keystatus;
+static UINT32 keystatus_words;
+
+/* key changed callback */
+static void (*key_changed)(void);
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void set_default_key_params(void);
+static void load_overlay_file(void);
+static void save_overlay_file(void);
+void fd1094_regenerate_key(void);
+
+static int instruction_hook(offs_t curpc);
+
+static void execute_fdsave(int ref, int params, const char **param);
+static void execute_fdoutput(int ref, int params, const char **param);
+static void execute_fdseed(int ref, int params, const char **param);
+static void execute_fdlockguess(int ref, int params, const char **param);
+static void execute_fdeliminate(int ref, int params, const char **param);
+static void execute_fdunlock(int ref, int params, const char **param);
+static void execute_fdignore(int ref, int params, const char **param);
+static void execute_fdundo(int ref, int params, const char **param);
+static void execute_fdstatus(int ref, int params, const char **param);
+static void execute_fdstate(int ref, int params, const char **param);
+static void execute_fdpc(int ref, int params, const char **param);
+static void execute_fdsearch(int ref, int params, const char **param);
+static void execute_fddasm(int ref, int params, const char **param);
+static void execute_fdcset(int ref, int params, const char **param);
+static void execute_fdclist(int ref, int params, const char **param);
+static void execute_fdcsearch(int ref, int params, const char **param);
+
+static fd1094_possibility *try_all_possibilities(int basepc, int offset, int length, UINT8 *instrbuffer, UINT8 *keybuffer, fd1094_possibility *possdata);
+static void tag_possibility(fd1094_possibility *possdata, UINT8 status);
+
+static void perform_constrained_search(void);
+static UINT32 find_global_key_matches(UINT32 startwith, UINT16 *output);
+static int find_constraint_sequence(UINT32 global, int quick);
+static int does_key_work_for_constraints(const UINT16 *base, UINT8 *key);
+static UINT32 reconstruct_base_seed(int keybaseaddr, UINT32 startseed);
+
+static void build_optable(void);
+static int validate_ea(UINT32 pc, UINT8 modereg, const UINT8 *parambase, UINT32 flags);
+static int validate_opcode(UINT32 pc, const UINT8 *opdata, int maxwords);
+
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-----------------------------------------------
+ addr_to_keyaddr - given an address,
+ return the address in the key that will be
+ used to decrypt it
+-----------------------------------------------*/
+
+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
+-----------------------------------------------*/
+
+INLINE UINT8 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
+-----------------------------------------------*/
+
+INLINE UINT32 advance_seed(UINT32 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
+-----------------------------------------------*/
+
+INLINE UINT8 key_value_from_seed(UINT32 seed, UINT8 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
+-----------------------------------------------*/
+
+INLINE void generate_key_bytes(UINT8 *dest, UINT32 keyoffs, UINT32 count, UINT32 seed)
+{
+ int bytenum;
+
+ /* generate 'count' bytes of a key */
+ for (bytenum = 0; bytenum < count; bytenum++)
+ {
+ UINT32 keyaddr = (keyoffs + bytenum) & 0x1fff;
+ UINT8 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
+-----------------------------------------------*/
+
+INLINE UINT8 get_opcode_length(UINT16 opcode)
+{
+ /* return the length from the table */
+ return optable[opcode].flags >> 28;
+}
+
+
+/*-----------------------------------------------
+ set_constraint - set the values of a
+ constraint
+-----------------------------------------------*/
+
+INLINE void set_constraint(fd1094_constraint *constraint, UINT32 pc, UINT16 state, UINT16 value, UINT16 mask)
+{
+ constraint->pc = pc;
+ constraint->state = state;
+ constraint->value = value & mask;
+ constraint->mask = mask;
+}
+
+/*-----------------------------------------------
+ print_possibilities - print possibilities
+ for a given address
+-----------------------------------------------*/
+
+INLINE void print_possibilities(void)
+{
+ int i;
+
+ debug_console_printf("Possibilities @ %06X:\n", posslist[0].basepc);
+ for (i = 0; i < posscount; i++)
+ debug_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
+-----------------------------------------------*/
+
+INLINE int pc_is_valid(UINT32 pc, UINT32 flags)
+{
+ /* if we're odd or out of range, fail */
+ if ((pc & 1) == 1)
+ return 0;
+ if (pc & 0xff000000)
+ return 0;
+ if (memory_get_op_ptr(cpu_getactivecpu(), pc, 0) == NULL)
+ return 0;
+ return 1;
+}
+
+
+/*-----------------------------------------------
+ addr_is_valid - is a given address value
+ valid? 0=no, 1=yes, 2=unlikely
+-----------------------------------------------*/
+
+INLINE int addr_is_valid(UINT32 addr, UINT32 flags)
+{
+ /* if this a JMP, the address is a PC */
+ if (flags & OF_JMP)
+ return pc_is_valid(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(memory_get_handler_string(0, cpu_getactivecpu(), ADDRESS_SPACE_PROGRAM, addr), "segaic16_memory_mapper_lsb_r") == 0)
+ return 2;
+
+ return 1;
+}
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*-----------------------------------------------
+ fd1094_init_debugging - set up debugging
+-----------------------------------------------*/
+
+void fd1094_init_debugging(int cpureg, int keyreg, int statreg, void (*changed)(void))
+{
+ /* set the key changed callback */
+ key_changed = changed;
+
+ /* set up the regions */
+ coderegion = (UINT16 *)memory_region(cpureg);
+ coderegion_words = memory_region_length(cpureg) / 2;
+ keyregion = (UINT8 *)memory_region(keyreg);
+ keystatus = (UINT16 *)memory_region(statreg);
+ keystatus_words = memory_region_length(statreg) / 2;
+ assert(coderegion_words == keystatus_words);
+
+ /* allocate memory for the ignore table */
+ ignorepc = auto_malloc(1 << 23);
+ memset(ignorepc, 0, 1 << 23);
+
+ /* allocate memory for the undo buffer */
+ undobuff = auto_malloc(keystatus_words * 2);
+ memcpy(undobuff, keystatus, keystatus_words * 2);
+
+ /* allocate memory for the possible seeds array */
+ possible_seed = auto_malloc(65536 * sizeof(possible_seed[0]));
+
+ /* build the opcode table */
+ build_optable();
+
+ /* 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();
+
+ /* read the key overlay file */
+ load_overlay_file();
+
+ /* add some commands */
+ debug_console_register_command("fdsave", CMDFLAG_NONE, 0, 0, 0, execute_fdsave);
+ debug_console_register_command("fdoutput", CMDFLAG_NONE, 0, 1, 1, execute_fdoutput);
+ debug_console_register_command("fdseed", CMDFLAG_NONE, 0, 2, 2, execute_fdseed);
+ debug_console_register_command("fdguess", CMDFLAG_NONE, STATUS_GUESS, 1, 1, execute_fdlockguess);
+ debug_console_register_command("fdlock", CMDFLAG_NONE, STATUS_LOCKED, 1, 1, execute_fdlockguess);
+ debug_console_register_command("fdeliminate", CMDFLAG_NONE, 0, 1, 10, execute_fdeliminate);
+ debug_console_register_command("fdunlock", CMDFLAG_NONE, 0, 1, 1, execute_fdunlock);
+ debug_console_register_command("fdignore", CMDFLAG_NONE, 0, 0, 1, execute_fdignore);
+ debug_console_register_command("fdundo", CMDFLAG_NONE, 0, 0, 0, execute_fdundo);
+ debug_console_register_command("fdstatus", CMDFLAG_NONE, 0, 0, 0, execute_fdstatus);
+ debug_console_register_command("fdstate", CMDFLAG_NONE, 0, 0, 1, execute_fdstate);
+ debug_console_register_command("fdpc", CMDFLAG_NONE, 0, 0, 1, execute_fdpc);
+ debug_console_register_command("fdsearch", CMDFLAG_NONE, 0, 0, 0, execute_fdsearch);
+ debug_console_register_command("fddasm", CMDFLAG_NONE, 0, 1, 1, execute_fddasm);
+ debug_console_register_command("fdcset", CMDFLAG_NONE, 0, 2, 4, execute_fdcset);
+ debug_console_register_command("fdclist", CMDFLAG_NONE, 0, 0, 0, execute_fdclist);
+ debug_console_register_command("fdcsearch", CMDFLAG_NONE, 0, 0, 0, execute_fdcsearch);
+
+ /* set up the instruction hook */
+ debug_set_instruction_hook(0, instruction_hook);
+
+ /* regenerate the key */
+ if (keydirty)
+ fd1094_regenerate_key();
+}
+
+
+/*-----------------------------------------------
+ set_default_key_params - based on the game
+ name, set some defaults
+-----------------------------------------------*/
+
+static void set_default_key_params(void)
+{
+ static const struct
+ {
+ const char * gamename;
+ UINT32 global;
+ UINT32 seed;
+ } default_keys[] =
+ {
+ { "altbeaj1", 0xFCAFF9F9, 0x177AC6 },
+ { "bullet", 0x12A8F9EC, 0x1B1FC3 },
+ };
+ int keynum;
+
+ /* look for a matching game and set the key appropriately */
+ for (keynum = 0; keynum < ARRAY_LENGTH(default_keys); keynum++)
+ if (strcmp(Machine->gamedrv->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(void)
+{
+ char filename[20];
+ file_error filerr;
+ mame_file *file;
+ int pcaddr;
+
+ /* determine the filename and open the file */
+ sprintf(filename, "%s.kov", Machine->gamedrv->name);
+ filerr = mame_fopen(SEARCHPATH_RAW, filename, OPEN_FLAG_READ, &file);
+ if (filerr == FILERR_NONE)
+ {
+ mame_fread(file, keystatus, keystatus_words * 2);
+ mame_fclose(file);
+
+ /* 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(void)
+{
+ char filename[20];
+ file_error filerr;
+ mame_file *file;
+ int pcaddr;
+
+ /* determin the filename and open the file */
+ sprintf(filename, "%s.kov", Machine->gamedrv->name);
+ filerr = mame_fopen(SEARCHPATH_RAW, filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file);
+ if (filerr == FILERR_NONE)
+ {
+ /* convert to big-endian */
+ for (pcaddr = 0; pcaddr < keystatus_words; pcaddr++)
+ keystatus[pcaddr] = BIG_ENDIANIZE_INT16(keystatus[pcaddr]);
+
+ /* write the data */
+ mame_fwrite(file, keystatus, keystatus_words * 2);
+ mame_fclose(file);
+
+ /* 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(void)
+{
+ 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 != NULL)
+ (*key_changed)();
+
+ /* force all memory and disassembly views to update */
+ debug_view_update_type(DVT_MEMORY);
+ debug_disasm_update_all();
+
+ /* reset keydirty */
+ keydirty = FALSE;
+}
+
+
+/*-----------------------------------------------
+ instruction_hook - per-instruction hook
+-----------------------------------------------*/
+
+static int instruction_hook(offs_t curpc)
+{
+ int curfdstate = fd1094_set_state(keyregion, -1);
+ UINT8 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 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(curpc, 0, 0, instrbuffer, keybuffer, posslist) - posslist;
+ if (keydirty)
+ fd1094_regenerate_key();
+
+ /* if we only ended up with one possibility, mark that one as good */
+ if (posscount == 1)
+ {
+ tag_possibility(&posslist[0], STATUS_LOCKED);
+ fd1094_regenerate_key();
+ return 0;
+ }
+
+ /* print possibilities and break */
+ print_possibilities();
+ return 1;
+}
+
+
+/*-----------------------------------------------
+ execute_fdsave - handle the 'fdsave' command
+-----------------------------------------------*/
+
+static void execute_fdsave(int ref, int params, const char **param)
+{
+ save_overlay_file();
+ debug_console_printf("File saved\n");
+}
+
+
+/*-----------------------------------------------
+ execute_fdoutput - output the current key
+ to a file
+-----------------------------------------------*/
+
+static void execute_fdoutput(int ref, int params, const char **param)
+{
+ file_error filerr;
+ mame_file *file;
+
+ /* make sure we're up-to-date */
+ if (keydirty)
+ fd1094_regenerate_key();
+
+ /* determin the filename and open the file */
+ filerr = mame_fopen(SEARCHPATH_RAW, param[0], OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file);
+ if (filerr == FILERR_NONE)
+ {
+ mame_fwrite(file, keyregion, KEY_SIZE);
+ mame_fclose(file);
+ }
+ debug_console_printf("File '%s' saved\n", param[0]);
+}
+
+
+/*-----------------------------------------------
+ execute_fdseed - handle the 'fdseed' command
+-----------------------------------------------*/
+
+static void execute_fdseed(int ref, int params, const char **param)
+{
+ UINT64 num1, num2;
+
+ /* extract the parameters */
+ if (!debug_command_parameter_number(param[0], &num1))
+ return;
+ if (!debug_command_parameter_number(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();
+}
+
+
+/*-----------------------------------------------
+ execute_fdlockguess - handle the 'fdlock'
+ and 'fdguess' commands
+-----------------------------------------------*/
+
+static void execute_fdlockguess(int ref, int params, const char **param)
+{
+ UINT64 num1;
+
+ /* extract the parameter */
+ if (!debug_command_parameter_number(param[0], &num1))
+ return;
+
+ /* make sure it is within range of our recent possibilities */
+ if (num1 >= posscount)
+ {
+ debug_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(&posslist[num1], ref);
+ fd1094_regenerate_key();
+}
+
+
+/*-----------------------------------------------
+ execute_fdeliminate - handle the
+ 'fdeliminate' command
+-----------------------------------------------*/
+
+static void execute_fdeliminate(int ref, int params, const char **param)
+{
+ int pnum, posssrc, possdst;
+ int plist[10];
+
+ /* extract parameters */
+ for (pnum = 0; pnum < params; pnum++)
+ {
+ UINT64 num1;
+
+ /* extract the parameters */
+ if (!debug_command_parameter_number(param[pnum], &num1))
+ return;
+
+ /* make sure it is within range of our recent possibilities */
+ if (num1 >= posscount)
+ {
+ debug_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();
+}
+
+
+/*-----------------------------------------------
+ execute_fdunlock - handle the 'fdunlock'
+ command
+-----------------------------------------------*/
+
+static void execute_fdunlock(int ref, int params, const char **param)
+{
+ int reps = keystatus_words / KEY_SIZE;
+ int keyaddr, repnum;
+ UINT64 offset;
+
+ /* support 0 or 1 parameters */
+ if (params != 1 || !debug_command_parameter_number(param[0], &offset))
+ offset = activecpu_get_pc();
+ keyaddr = addr_to_keyaddr(offset / 2);
+
+ /* toggle the ignore PC status */
+ debug_console_printf("Unlocking PC %06X\n", (int)offset);
+
+ /* iterate over all reps and unlock them */
+ for (repnum = 0; repnum < reps; repnum++)
+ {
+ UINT16 *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(int ref, int params, const char **param)
+{
+ UINT64 offset;
+
+ /* support 0 or 1 parameters */
+ if (params == 1 && strcmp(param[0], "all") == 0)
+ {
+ ignore_all = TRUE;
+ debug_console_printf("Ignoring all unknown opcodes\n");
+ return;
+ }
+ if (params != 1 || !debug_command_parameter_number(param[0], &offset))
+ offset = activecpu_get_pc();
+ offset /= 2;
+
+ /* toggle the ignore PC status */
+ ignorepc[offset] = !ignorepc[offset];
+ if (ignorepc[offset])
+ debug_console_printf("Ignoring address %06X\n", (int)offset * 2);
+ else
+ debug_console_printf("No longer ignoring address %06X\n", (int)offset * 2);
+
+ /* if no parameter given, implicitly run as well */
+ if (params == 0)
+ debug_cpu_go(~0);
+}
+
+
+/*-----------------------------------------------
+ execute_fdundo - handle the 'fdundo'
+ command
+-----------------------------------------------*/
+
+static void execute_fdundo(int ref, int params, const char **param)
+{
+ /* copy the undobuffer back and regenerate the key */
+ memcpy(keystatus, undobuff, keystatus_words * 2);
+ fd1094_regenerate_key();
+ debug_console_printf("Undid last change\n");
+}
+
+
+/*-----------------------------------------------
+ execute_fdstatus - handle the 'fdstatus'
+ command
+-----------------------------------------------*/
+
+static void execute_fdstatus(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++;
+ }
+ debug_console_printf("%4d/%4d keys locked (%d%%)\n", locked, KEY_SIZE, locked * 100 / KEY_SIZE);
+ debug_console_printf("%4d/%4d keys guessed (%d%%)\n", guesses, KEY_SIZE, guesses * 100 / KEY_SIZE);
+ debug_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(int ref, int params, const char **param)
+{
+ UINT64 newstate;
+
+ /* set the new state if we got a parameter */
+ if (params > 0)
+ {
+ if (!debug_command_parameter_number(param[0], &newstate))
+ return;
+ fd1094_set_state(keyregion, newstate);
+ fd1094_regenerate_key();
+ debug_view_update_type(DVT_MEMORY);
+ debug_disasm_update_all();
+ }
+
+ /* 0 parameters displays the current state */
+ debug_console_printf("FD1094 state = %X\n", fd1094_set_state(keyregion, -1));
+}
+
+
+/*-----------------------------------------------
+ execute_fdpc - handle the 'fdpc'
+ command
+-----------------------------------------------*/
+
+static void execute_fdpc(int ref, int params, const char **param)
+{
+ UINT64 newpc;
+
+ /* support 0 or 1 parameters */
+ if (!debug_command_parameter_number(param[0], &newpc))
+ newpc = activecpu_get_pc();
+
+ /* set the new PC */
+ activecpu_set_reg(REG_PC, newpc);
+
+ /* recompute around that */
+ instruction_hook(newpc);
+}
+
+
+/*-----------------------------------------------
+ execute_fdsearch - handle the 'fdsearch'
+ command
+-----------------------------------------------*/
+
+static void execute_fdsearch(int ref, int params, const char **param)
+{
+ int pc = activecpu_get_pc();
+ int length, first = TRUE;
+ UINT8 instrdata[2];
+ UINT16 decoded;
+
+ /* if we don't match, reset the stack */
+ if (searchsp == 0 || searchstack[searchsp-1] != pc)
+ {
+ int pcaddr;
+ debug_console_printf("Starting new search at PC=%06X\n", pc);
+ searchsp = 0;
+ for (pcaddr = 0; pcaddr < coderegion_words; pcaddr++)
+ keystatus[pcaddr] &= ~SEARCH_MASK;
+ }
+ else
+ {
+ debug_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)
+ {
+ debug_console_printf("Search stack exhausted\n");
+ break;
+ }
+
+ /* set this as our current PC and run the instruction hook */
+ activecpu_set_reg(REG_PC, pc);
+ if (instruction_hook(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(pc, instrdata, 1);
+ if (length < 0)
+ length = -length;
+ if (length == 0)
+ {
+ debug_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)decoded;
+ int targetpc;
+
+ /* extract the delta PC */
+ if ((optable[decoded].flags & OF_ISIZEMASK) == OF_IMMW)
+ deltapc = (INT16)fd1094_decode((pc+2)/2, coderegion[(pc+2)/2], keyregion, 0);
+ else if ((optable[decoded].flags & OF_ISIZEMASK) == OF_IMML)
+ deltapc = (INT32)(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)fd1094_decode((pc+2)/2, coderegion[(pc+2)/2], keyregion, 0);
+ else
+ targetpc = (INT32)(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(int ref, int params, const char **param)
+{
+ int origstate = fd1094_set_state(keyregion, -1);
+ const char *filename;
+ int skipped = FALSE;
+ file_error filerr;
+ mame_file *file;
+ UINT32 pcaddr;
+
+ /* extract the parameters */
+ filename = param[0];
+
+ /* open the file */
+ filerr = mame_fopen(SEARCHPATH_RAW, filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, &file);
+ if (filerr != FILERR_NONE)
+ {
+ debug_console_printf("Unable to create file '%s'\n", filename);
+ return;
+ }
+
+ /* now do the disassembly */
+ for (pcaddr = 0; pcaddr < coderegion_words; )
+ {
+ UINT8 instrbuffer[10];
+ int unknowns = FALSE;
+ int length, pcoffs;
+ char disasm[256];
+ UINT16 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)
+ mame_fprintf(file, "\n");
+ skipped = FALSE;
+ mame_fprintf(file, " %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;
+ mame_fprintf(file, " %02X%02X%c", instrbuffer[pcoffs*2+0], instrbuffer[pcoffs*2+1], statchar[keystat]);
+ }
+ else
+ mame_fprintf(file, " ");
+ }
+ mame_fprintf(file, "%s\n", disasm);
+
+ /* if we have unknowns, display them as well */
+ if (unknowns > 0)
+ {
+ UINT8 keybuffer[5];
+ int posscount = try_all_possibilities(pcaddr * 2, 0, 0, instrbuffer, keybuffer, posslist) - posslist;
+ for (pnum = 0; pnum < posscount; pnum++)
+ if (strcmp(disasm, posslist[pnum].dasm) != 0)
+ {
+ mame_fprintf(file, " :");
+ for (pcoffs = 0; pcoffs < 5; pcoffs++)
+ if (pcoffs < posslist[pnum].length)
+ mame_fprintf(file, " %02X%02X ", posslist[pnum].instrbuffer[pcoffs*2+0], posslist[pnum].instrbuffer[pcoffs*2+1]);
+ else
+ mame_fprintf(file, " ");
+ mame_fprintf(file, "%s\n", posslist[pnum].dasm);
+ }
+ }
+
+ /* advance */
+ pcaddr += length;
+ }
+
+ /* close the file */
+ mame_fclose(file);
+ fd1094_set_state(keyregion, origstate);
+}
+
+
+/*-----------------------------------------------
+ execute_fdcset - handle the 'fdcset'
+ command
+-----------------------------------------------*/
+
+static void execute_fdcset(int ref, int params, const char **param)
+{
+ UINT64 pc, value, mask = 0xffff, state = FD1094_STATE_RESET;
+ int cnum;
+
+ /* extract the parameters */
+ if (!debug_command_parameter_number(param[0], &pc))
+ return;
+ if (!debug_command_parameter_number(param[1], &value))
+ return;
+ if (params >= 3 && !debug_command_parameter_number(param[2], &mask))
+ return;
+ if (params >= 4)
+ {
+ if (strcmp(param[3], "irq") == 0)
+ state = FD1094_STATE_IRQ;
+ else if (!debug_command_parameter_number(param[3], &state))
+ return;
+ }
+
+ /* validate parameters */
+ if ((pc & 1) != 0 || pc > 0xffffff)
+ {
+ debug_console_printf("Invalid PC specified (%08X)\n", (UINT32)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 */
+ debug_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(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];
+ debug_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(int ref, int params, const char **param)
+{
+// debug_console_printf("Searching for possible global keys....\n");
+ perform_constrained_search();
+}
+
+
+/*-----------------------------------------------
+ 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(int basepc, int offset, int length, UINT8 *instrbuffer, UINT8 *keybuffer, fd1094_possibility *possdata)
+{
+ UINT8 keymask, keystat;
+ UINT16 possvalue[4];
+ UINT8 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 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)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(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(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(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(fd1094_possibility *possdata, UINT8 status)
+{
+ int curfdstate = fd1094_set_state(keyregion, -1);
+ int nomatter = 0, locked = 0, guessed = 0;
+ int reps = keystatus_words / KEY_SIZE;
+ UINT8 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++;
+ }
+
+ debug_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(void)
+{
+ UINT32 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 output[4];
+ int numseeds;
+
+ /* look for the next global key match */
+ global = find_global_key_matches(global + 1, output);
+ if (global == 0)
+ break;
+// debug_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++)
+ debug_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 find_global_key_matches(UINT32 startwith, UINT16 *output)
+{
+ int key0, key1, key2, key3;
+ UINT8 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 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 decrypted;
+ UINT8 key[8192];
+ UINT8 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 seedlow;
+
+// debug_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 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 *base, UINT8 *key)
+{
+ const fd1094_constraint *curr;
+ UINT16 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 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 reconstruct_base_seed(int keybaseaddr, UINT32 startseed)
+{
+ UINT32 seed = startseed;
+ UINT32 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++ % ARRAY_LENGTH(window)] = seed;
+ } while (((startseed ^ seed) & 0x3fffff) != 0 || index < ARRAY_LENGTH(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 += ARRAY_LENGTH(window);
+
+ /* return the value from the window at that location */
+ return window[index % ARRAY_LENGTH(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 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(void)
+{
+ int opnum, inum;
+
+ /* allocate and initialize the opcode table */
+ optable = auto_malloc(65536 * sizeof(optable[0]));
+ for (opnum = 0; opnum < 65536; opnum++)
+ {
+ optable[opnum].flags = OF_INVALID;
+ optable[opnum].string = NULL;
+ }
+
+ /* now iterate over entries in our intruction table */
+ for (inum = 0; inum < ARRAY_LENGTH(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 flags = instr_table[inum].flags;
+ UINT8 ea_allowed[64], ea2_allowed[64];
+ int bitnum, step, eanum, ea2num;
+ UINT16 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 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 */
+ {
+ char dummybuffer[256];
+ UINT8 instrbuffer[10];
+ instrbuffer[0] = (opnum | eabits) >> 8;
+ instrbuffer[1] = (opnum | eabits);
+ assert(length == (m68k_disassemble_raw(dummybuffer, 0, instrbuffer, instrbuffer, M68K_CPU_TYPE_68000) & 0xff) / 2);
+ }
+
+ /* 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(UINT32 pc, UINT8 modereg, const UINT8 *parambase, UINT32 flags)
+{
+ UINT32 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)((parambase[0] << 8) | parambase[1]);
+ valid = addr_is_valid(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((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(pc + (INT16)((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(UINT32 pc, const UINT8 *opdata, int maxwords)
+{
+ UINT32 immvalue = 0;
+ int iffy = FALSE;
+ int offset = 0;
+ UINT16 opcode;
+ UINT32 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)opcode;
+ else if ((flags & OF_SIZEMASK) == OF_WORD)
+ pc += (INT16)immvalue;
+ else
+ pc += immvalue;
+
+ /* if we're odd or out of range, fail */
+ valid = pc_is_valid(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(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(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/src/mame/machine/flstory.c b/src/mame/machine/flstory.c
new file mode 100644
index 00000000000..174317be19a
--- /dev/null
+++ b/src/mame/machine/flstory.c
@@ -0,0 +1,271 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+
+/***************************************************************************
+
+ Fairy Land Story 68705 protection interface
+
+ The following is ENTIRELY GUESSWORK!!!
+
+ It seems, however, to be identical to Buggy Challenge.
+
+***************************************************************************/
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( flstory_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( flstory_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( flstory_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 1 W when 1->0, enables latch which brings the command from main CPU (read from port A)
+ * 2 W when 0->1, copies port A to the latch for the main CPU
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( flstory_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( flstory_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ if (main_sent) cpunum_set_input_line(2,0,CLEAR_LINE);
+ main_sent = 0;
+logerror("read command %02x from main cpu\n",portA_in);
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+logerror("send command %02x to main cpu\n",portA_out);
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( flstory_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( flstory_68705_portC_r )
+{
+ portC_in = 0;
+ if (main_sent) portC_in |= 0x01;
+ if (!mcu_sent) portC_in |= 0x02;
+//logerror("%04x: 68705 port C read %02x\n",activecpu_get_pc(),portC_in);
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( flstory_68705_portC_w )
+{
+logerror("%04x: 68705 port C write %02x\n",activecpu_get_pc(),data);
+ portC_out = data;
+}
+
+WRITE8_HANDLER( flstory_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+WRITE8_HANDLER( flstory_mcu_w )
+{
+logerror("%04x: mcu_w %02x\n",activecpu_get_pc(),data);
+ from_main = data;
+ main_sent = 1;
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+}
+
+READ8_HANDLER( flstory_mcu_r )
+{
+logerror("%04x: mcu_r %02x\n",activecpu_get_pc(),from_mcu);
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( flstory_mcu_status_r )
+{
+ int res = 0;
+
+ /* bit 0 = when 1, mcu is ready to receive data from main cpu */
+ /* bit 1 = when 1, mcu has sent data to the main cpu */
+//logerror("%04x: mcu_status_r\n",activecpu_get_pc());
+ if (!main_sent) res |= 0x01;
+ if (mcu_sent) res |= 0x02;
+
+ return res;
+}
+
+WRITE8_HANDLER( onna34ro_mcu_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+ UINT16 score_adr = RAM[0xe29e]*0x100 + RAM[0xe29d];
+
+ switch (data)
+ {
+ case 0x0e:
+ from_mcu = 0xff;
+ break;
+ case 0x01:
+ from_mcu = 0x6a;
+ break;
+ case 0x40:
+ from_mcu = RAM[score_adr]; /* score l*/
+ break;
+ case 0x41:
+ from_mcu = RAM[score_adr+1]; /* score m*/
+ break;
+ case 0x42:
+ from_mcu = RAM[score_adr+2] & 0x0f; /* score h*/
+ break;
+ default:
+ from_mcu = 0x80;
+ }
+}
+
+READ8_HANDLER( onna34ro_mcu_r )
+{
+ return from_mcu;
+}
+
+READ8_HANDLER( onna34ro_mcu_status_r )
+{
+ int res = 3;
+
+ return res;
+}
+
+
+#define VICTNINE_MCU_SEED (memory_region(REGION_CPU1)[0xE685])
+
+static UINT8 victnine_mcu_data[0x100] =
+{
+ 0x3e, 0x08, 0xdd, 0x29, 0xcb, 0x14, 0xfd, 0x29,
+ 0xcb, 0x15, 0xd9, 0x29, 0xd9, 0x30, 0x0d, 0xd9,
+ 0x19, 0xd9, 0xdd, 0x09, 0x30, 0x01, 0x24, 0xfd,
+ 0x19, 0x30, 0x01, 0x2c, 0x3d, 0x20, 0xe3, 0xc9,
+ 0x11, 0x14, 0x00, 0x19, 0x7e, 0x32, 0xed, 0xe4,
+ 0x2a, 0x52, 0xe5, 0x22, 0xe9, 0xe4, 0x2a, 0x54,
+ 0xe5, 0x22, 0xeb, 0xe4, 0x21, 0x2a, 0xe6, 0xfe,
+ 0x06, 0x38, 0x02, 0xcb, 0xc6, 0xcb, 0xce, 0xc9,
+ 0x06, 0x00, 0x3a, 0xaa, 0xe4, 0x07, 0x07, 0x07,
+ 0xb0, 0x47, 0x3a, 0xab, 0xe4, 0x07, 0x07, 0xb0,
+ 0x47, 0x3a, 0xac, 0xe4, 0xe6, 0x03, 0xb0, 0x21,
+ 0xe3, 0xe6, 0xc9, 0x38, 0xe1, 0x29, 0x07, 0xc9,
+ 0x23, 0x7e, 0x47, 0xe6, 0x1f, 0x32, 0x0c, 0xe6,
+ 0x78, 0xe6, 0xe0, 0x07, 0x07, 0x47, 0xe6, 0x03,
+ 0x28, 0x06, 0xcb, 0x7a, 0x28, 0x02, 0xc6, 0x02,
+ 0x32, 0x0a, 0xe6, 0x78, 0xe6, 0x80, 0xc9, 0x3a,
+ 0x21, 0x29, 0xe5, 0x7e, 0xe6, 0xf8, 0xf6, 0x01,
+ 0x77, 0x23, 0x3a, 0x0a, 0xe6, 0x77, 0x21, 0x08,
+ 0xe6, 0xcb, 0xc6, 0xcb, 0x8e, 0x3a, 0x2b, 0xe5,
+ 0x21, 0xff, 0xe5, 0xfe, 0x02, 0xc9, 0x1f, 0xc6,
+ 0x47, 0x3a, 0xaa, 0xe4, 0xa7, 0x21, 0x00, 0xe5,
+ 0x28, 0x03, 0x21, 0x1b, 0xe5, 0x70, 0x3a, 0xaa,
+ 0xe4, 0xee, 0x01, 0x32, 0xaa, 0xe4, 0x21, 0xb0,
+ 0xe4, 0x34, 0x23, 0x36, 0x00, 0xc9, 0x2b, 0xb2,
+ 0xaf, 0x77, 0x12, 0x23, 0x13, 0x3c, 0xfe, 0x09,
+ 0x20, 0xf7, 0x3e, 0x01, 0x32, 0xad, 0xe4, 0x21,
+ 0x48, 0xe5, 0xcb, 0xfe, 0xc9, 0x32, 0xe5, 0xaa,
+ 0x21, 0x00, 0x13, 0xe4, 0x47, 0x1b, 0xa1, 0xc9,
+ 0x00, 0x08, 0x04, 0x0c, 0x05, 0x0d, 0x06, 0x0e,
+ 0x22, 0x66, 0xaa, 0x22, 0x33, 0x01, 0x11, 0x88,
+ 0x06, 0x05, 0x03, 0x04, 0x08, 0x01, 0x03, 0x02,
+ 0x06, 0x07, 0x02, 0x03, 0x15, 0x17, 0x11, 0x13
+};
+
+static int mcu_select = 0;
+
+WRITE8_HANDLER( victnine_mcu_w )
+{
+ UINT8 seed = VICTNINE_MCU_SEED;
+
+ if (!seed && (data & 0x37) == 0x37)
+ {
+ from_mcu = 0xa6;
+ logerror("mcu initialize (%02x)\n", data);
+ }
+ else
+ {
+ data += seed;
+
+ if ((data & ~0x1f) == 0xa0)
+ {
+ mcu_select = data & 0x1f;
+ //logerror("mcu select: 0x%02x\n", mcu_select);
+ }
+ else if (data < 0x20)
+ {
+ int offset = mcu_select * 8 + data;
+
+ //logerror("mcu fetch: 0x%02x\n", offset);
+ from_mcu = victnine_mcu_data[offset];
+ }
+ else if (data >= 0x38 && data <= 0x3a)
+ {
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ from_mcu = RAM[0xe691 - 0x38 + data];
+ }
+ else
+ {
+ //logerror("mcu: 0x%02x: unknown command\n", data);
+ }
+ }
+}
+
+READ8_HANDLER( victnine_mcu_r )
+{
+ //logerror("%04x: mcu read (0x%02x)\n", activecpu_get_previouspc(), from_mcu);
+
+ return from_mcu - VICTNINE_MCU_SEED;
+}
+
+READ8_HANDLER( victnine_mcu_status_r )
+{
+ int res = 3;
+
+ return res;
+}
diff --git a/src/mame/machine/gaelco2.c b/src/mame/machine/gaelco2.c
new file mode 100644
index 00000000000..c634ec61004
--- /dev/null
+++ b/src/mame/machine/gaelco2.c
@@ -0,0 +1,245 @@
+/***************************************************************************
+
+ Gaelco CG-1V/GAE1 based games
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/eeprom.h"
+
+/***************************************************************************
+
+ Split even/odd bytes from ROMs in 16 bit mode to different memory areas
+
+***************************************************************************/
+
+static void gaelco2_ROM16_split(int src_reg, int dst_reg, int start, int length, int dest1, int dest2)
+{
+ int i;
+
+ /* get a pointer to the source data */
+ UINT8 *src = (UINT8 *)memory_region(src_reg);
+
+ /* get a pointer to the destination data */
+ UINT8 *dst = (UINT8 *)memory_region(dst_reg);
+
+ /* fill destination areas with the proper data */
+ for (i = 0; i < length/2; i++){
+ dst[dest1 + i] = src[start + i*2 + 0];
+ dst[dest2 + i] = src[start + i*2 + 1];
+ }
+}
+
+
+/***************************************************************************
+
+ Driver init routines
+
+***************************************************************************/
+
+DRIVER_INIT( alighunt )
+{
+ /*
+ For REGION_GFX2 we have this memory map:
+ 0x0000000-0x03fffff ROM u48
+ 0x0400000-0x07fffff ROM u47
+ 0x0800000-0x0bfffff ROM u50
+ 0x0c00000-0x0ffffff ROM u49
+
+ and we are going to construct this one for REGION_GFX1:
+ 0x0000000-0x01fffff ROM u48 even bytes
+ 0x0200000-0x03fffff ROM u47 even bytes
+ 0x0400000-0x05fffff ROM u48 odd bytes
+ 0x0600000-0x07fffff ROM u47 odd bytes
+ 0x0800000-0x09fffff ROM u50 even bytes
+ 0x0a00000-0x0bfffff ROM u49 even bytes
+ 0x0c00000-0x0dfffff ROM u50 odd bytes
+ 0x0e00000-0x0ffffff ROM u49 odd bytes
+ */
+
+ /* split ROM u48 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0000000, 0x0400000, 0x0000000, 0x0400000);
+
+ /* split ROM u47 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0400000, 0x0400000, 0x0200000, 0x0600000);
+
+ /* split ROM u50 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0800000, 0x0400000, 0x0800000, 0x0c00000);
+
+ /* split ROM u49 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0c00000, 0x0400000, 0x0a00000, 0x0e00000);
+}
+
+
+DRIVER_INIT( touchgo )
+{
+ /*
+ For REGION_GFX2 we have this memory map:
+ 0x0000000-0x03fffff ROM ic65
+ 0x0400000-0x05fffff ROM ic66
+ 0x0800000-0x0bfffff ROM ic67
+
+ and we are going to construct this one for REGION_GFX1:
+ 0x0000000-0x01fffff ROM ic65 even bytes
+ 0x0200000-0x02fffff ROM ic66 even bytes
+ 0x0400000-0x05fffff ROM ic65 odd bytes
+ 0x0600000-0x06fffff ROM ic66 odd bytes
+ 0x0800000-0x09fffff ROM ic67 even bytes
+ 0x0c00000-0x0dfffff ROM ic67 odd bytes
+ */
+
+ /* split ROM ic65 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0000000, 0x0400000, 0x0000000, 0x0400000);
+
+ /* split ROM ic66 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0400000, 0x0200000, 0x0200000, 0x0600000);
+
+ /* split ROM ic67 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0800000, 0x0400000, 0x0800000, 0x0c00000);
+}
+
+
+DRIVER_INIT( snowboar )
+{
+ /*
+ For REGION_GFX2 we have this memory map:
+ 0x0000000-0x03fffff ROM sb44
+ 0x0400000-0x07fffff ROM sb45
+ 0x0800000-0x0bfffff ROM sb46
+
+ and we are going to construct this one for REGION_GFX1:
+ 0x0000000-0x01fffff ROM sb44 even bytes
+ 0x0200000-0x03fffff ROM sb45 even bytes
+ 0x0400000-0x05fffff ROM sb44 odd bytes
+ 0x0600000-0x07fffff ROM sb45 odd bytes
+ 0x0800000-0x09fffff ROM sb46 even bytes
+ 0x0c00000-0x0dfffff ROM sb46 odd bytes
+ */
+
+ /* split ROM sb44 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0000000, 0x0400000, 0x0000000, 0x0400000);
+
+ /* split ROM sb45 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0400000, 0x0400000, 0x0200000, 0x0600000);
+
+ /* split ROM sb46 */
+ gaelco2_ROM16_split(REGION_GFX2, REGION_GFX1, 0x0800000, 0x0400000, 0x0800000, 0x0c00000);
+}
+
+/***************************************************************************
+
+ Coin counters/lockouts
+
+***************************************************************************/
+
+WRITE16_HANDLER( gaelco2_coin_w )
+{
+ /* Coin Lockouts */
+ coin_lockout_w(0, ~data & 0x01);
+ coin_lockout_w(1, ~data & 0x02);
+
+ /* Coin Counters */
+ coin_counter_w(0, data & 0x04);
+ coin_counter_w(1, data & 0x08);
+}
+
+WRITE16_HANDLER( gaelco2_coin2_w )
+{
+ /* coin counters */
+ coin_counter_w(offset & 0x01, data & 0x01);
+}
+
+WRITE16_HANDLER( wrally2_coin_w )
+{
+ /* coin counters */
+ coin_counter_w((offset >> 3) & 0x01, data & 0x01);
+}
+
+/***************************************************************************
+
+ EEPROM (93C66)
+
+***************************************************************************/
+
+static struct EEPROM_interface gaelco2_eeprom_interface =
+{
+ 8, /* address bits */
+ 16, /* data bits */
+ "*110", /* read command */
+ "*101", /* write command */
+ "*111", /* erase command */
+ "*10000xxxxxx", /* lock command */
+ "*10011xxxxxx", /* unlock command */
+// "*10001xxxxxx", /* write all */
+// "*10010xxxxxx", /* erase all */
+};
+
+NVRAM_HANDLER( gaelco2 )
+{
+ if (read_or_write){
+ EEPROM_save(file);
+ } else {
+ EEPROM_init(&gaelco2_eeprom_interface);
+
+ if (file) EEPROM_load(file);
+ }
+}
+
+READ16_HANDLER( gaelco2_eeprom_r )
+{
+ /* bit 6 is EEPROM data (DOUT) */
+ /* bit 7 is EEPROM ready */
+ /* bits 0-5, COINSW, STARTSW & Service */
+ return (1 << 7) | (EEPROM_read_bit() << 6) | (readinputport(2) & 0x3f);
+}
+
+WRITE16_HANDLER( gaelco2_eeprom_cs_w )
+{
+ /* bit 0 is CS (active low) */
+ EEPROM_set_cs_line((data & 0x01) ? CLEAR_LINE : ASSERT_LINE);
+}
+
+WRITE16_HANDLER( gaelco2_eeprom_sk_w )
+{
+ /* bit 0 is SK (active high) */
+ EEPROM_set_clock_line((data & 0x01) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+WRITE16_HANDLER( gaelco2_eeprom_data_w )
+{
+ /* bit 0 is EEPROM data (DIN) */
+ EEPROM_write_bit(data & 0x01);
+}
+
+/***************************************************************************
+
+ Protection
+
+***************************************************************************/
+
+UINT16 *snowboar_protection;
+
+/*
+ The game writes 2 values and then reads from a memory address.
+ If the read value is wrong, the game can crash in some places.
+ If we always return 0, the game doesn't crash but you can't see
+ the full intro (because it expects 0xffff somewhere).
+
+ The protection handles sound, controls, gameplay and some sprites
+*/
+
+READ16_HANDLER( snowboar_protection_r )
+{
+ logerror("%06x: protection read from %04x\n", activecpu_get_pc(), offset*2);
+ return 0x0000;
+}
+
+WRITE16_HANDLER( snowboar_protection_w )
+{
+ COMBINE_DATA(&snowboar_protection[offset]);
+ logerror("%06x: protection write %04x to %04x\n", activecpu_get_pc(), data, offset*2);
+
+}
diff --git a/src/mame/machine/galaxian.c b/src/mame/machine/galaxian.c
new file mode 100644
index 00000000000..6616a14f733
--- /dev/null
+++ b/src/mame/machine/galaxian.c
@@ -0,0 +1,563 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/7474.h"
+#include "includes/galaxian.h"
+
+static int irq_line;
+static emu_timer *int_timer;
+
+static UINT8 kingball_speech_dip;
+static UINT8 kingball_sound;
+
+static UINT8 _4in1_bank;
+static UINT8 gmgalax_selected_game;
+
+
+static void galaxian_7474_9M_2_callback(void)
+{
+ /* Q bar clocks the other flip-flop,
+ Q is VBLANK (not visible to the CPU) */
+ TTL7474_clock_w(1, TTL7474_output_comp_r(0));
+ TTL7474_update(1);
+}
+
+static void galaxian_7474_9M_1_callback(void)
+{
+ /* Q goes to the NMI line */
+ cpunum_set_input_line(0, irq_line, TTL7474_output_r(1) ? CLEAR_LINE : ASSERT_LINE);
+}
+
+static const struct TTL7474_interface galaxian_7474_9M_2_intf =
+{
+ galaxian_7474_9M_2_callback
+};
+
+static const struct TTL7474_interface galaxian_7474_9M_1_intf =
+{
+ galaxian_7474_9M_1_callback
+};
+
+
+WRITE8_HANDLER( galaxian_nmi_enable_w )
+{
+ TTL7474_preset_w(1, data);
+ TTL7474_update(1);
+}
+
+
+static TIMER_CALLBACK( interrupt_timer )
+{
+ /* 128V, 64V and 32V go to D */
+ TTL7474_d_w(0, (param & 0xe0) != 0xe0);
+
+ /* 16V clocks the flip-flop */
+ TTL7474_clock_w(0, param & 0x10);
+
+ param = (param + 0x10) & 0xff;
+
+ timer_adjust(int_timer, video_screen_get_time_until_pos(0, param, 0), param, attotime_zero);
+
+ TTL7474_update(0);
+}
+
+
+static void machine_reset_common( int line )
+{
+ irq_line = line;
+
+ /* initalize main CPU interrupt generator flip-flops */
+ TTL7474_config(0, &galaxian_7474_9M_2_intf);
+ TTL7474_preset_w(0, 1);
+ TTL7474_clear_w (0, 1);
+
+ TTL7474_config(1, &galaxian_7474_9M_1_intf);
+ TTL7474_clear_w (1, 1);
+ TTL7474_d_w (1, 0);
+ TTL7474_preset_w(1, 0);
+
+ /* start a timer to generate interrupts */
+ int_timer = timer_alloc(interrupt_timer);
+ timer_adjust(int_timer, video_screen_get_time_until_pos(0, 0, 0), 0, attotime_zero);
+}
+
+MACHINE_RESET( galaxian )
+{
+ machine_reset_common(INPUT_LINE_NMI);
+}
+
+MACHINE_RESET( devilfsg )
+{
+ machine_reset_common(0);
+}
+
+
+
+WRITE8_HANDLER( galaxian_coin_lockout_w )
+{
+ coin_lockout_global_w(~data & 1);
+}
+
+
+WRITE8_HANDLER( galaxian_coin_counter_w )
+{
+ coin_counter_w(offset, data & 0x01);
+}
+
+WRITE8_HANDLER( galaxian_coin_counter_1_w )
+{
+ coin_counter_w(1, data & 0x01);
+}
+
+WRITE8_HANDLER( galaxian_coin_counter_2_w )
+{
+ coin_counter_w(2, data & 0x01);
+}
+
+
+WRITE8_HANDLER( galaxian_leds_w )
+{
+ set_led_status(offset,data & 1);
+}
+
+
+READ8_HANDLER( jumpbug_protection_r )
+{
+ switch (offset)
+ {
+ case 0x0114: return 0x4f;
+ case 0x0118: return 0xd3;
+ case 0x0214: return 0xcf;
+ case 0x0235: return 0x02;
+ case 0x0311: return 0x00; /* not checked */
+ default:
+ logerror("Unknown protection read. Offset: %04X PC=%04X\n",0xb000+offset,activecpu_get_pc());
+ }
+
+ return 0;
+}
+
+
+
+static READ8_HANDLER( checkmaj_protection_r )
+{
+ switch (activecpu_get_pc())
+ {
+ case 0x0f15: return 0xf5;
+ case 0x0f8f: return 0x7c;
+ case 0x10b3: return 0x7c;
+ case 0x10e0: return 0x00;
+ case 0x10f1: return 0xaa;
+ case 0x1402: return 0xaa;
+ default:
+ logerror("Unknown protection read. PC=%04X\n",activecpu_get_pc());
+ }
+
+ return 0;
+}
+
+
+/* Zig Zag can swap ROMs 2 and 3 as a form of copy protection */
+WRITE8_HANDLER( zigzag_sillyprotection_w )
+{
+ if (data)
+ {
+ /* swap ROM 2 and 3! */
+ memory_set_bank(1, 1);
+ memory_set_bank(2, 0);
+ }
+ else
+ {
+ memory_set_bank(1, 0);
+ memory_set_bank(2, 1);
+ }
+}
+
+DRIVER_INIT( zigzag )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+ memory_configure_bank(1, 0, 2, &RAM[0x2000], 0x1000);
+ memory_configure_bank(2, 0, 2, &RAM[0x2000], 0x1000);
+ memory_set_bank(1, 0);
+ memory_set_bank(2, 1);
+}
+
+
+
+static READ8_HANDLER( dingo_3000_r )
+{
+ return 0xaa;
+}
+
+static READ8_HANDLER( dingo_3035_r )
+{
+ return 0x8c;
+}
+
+static READ8_HANDLER( dingoe_3001_r )
+{
+ return 0xaa;
+}
+
+
+DRIVER_INIT( dingoe )
+{
+ offs_t i;
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+ for (i = 0; i < 0x3000; i++)
+ {
+ UINT8 data_xor;
+
+ /* XOR bit 2 with 4 and 5 with 0 */
+ data_xor = BIT(rom[i], 2) << 4 | BIT(rom[i], 5) << 0;
+ rom[i] ^= data_xor;
+
+
+ /* Invert bit 1 */
+ if (~rom[i] & 0x02)
+ rom[i] = rom[i] | 0x02;
+ else
+ rom[i] = rom[i] & 0xfd;
+
+
+ /* Swap bit0 with bit4 */
+ if ((i & 0x0f) == 0x02 || (i & 0x0f) == 0x0a || (i & 0x0f) == 0x03 || (i & 0x0f) == 0x0b || (i & 0x0f) == 0x06 || (i & 0x0f) == 0x0e || (i & 0x0f) == 0x07 || (i & 0x0f) == 0x0f) /* Swap Bit 0 and 4 */
+ rom[i] = BITSWAP8(rom[i],7,6,5,0,3,2,1,4);
+ }
+
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x3001, 0x3001, 0, 0, dingoe_3001_r); /* Protection check */
+
+}
+
+
+
+/* Hack? If $b003 is high, we'll check our "fake" speech dipswitch (marked as SLAM) */
+static READ8_HANDLER( kingball_IN0_r )
+{
+ if (kingball_speech_dip)
+ return (readinputport(0) & ~0x40) | ((readinputport(3) & 0x01) << 6);
+ else
+ return readinputport(0);
+}
+
+static READ8_HANDLER( kingball_IN1_r )
+{
+ /* bit 5 is the NOISE line from the sound circuit. The code just verifies
+ that it's working, doesn't actually use return value, so we can just use
+ rand() */
+
+ return (readinputport(1) & ~0x20) | (mame_rand(Machine) & 0x20);
+}
+
+WRITE8_HANDLER( kingball_speech_dip_w )
+{
+ kingball_speech_dip = data;
+}
+
+WRITE8_HANDLER( kingball_sound1_w )
+{
+ kingball_sound = (kingball_sound & ~0x01) | data;
+}
+
+WRITE8_HANDLER( kingball_sound2_w )
+{
+ kingball_sound = (kingball_sound & ~0x02) | (data << 1);
+ soundlatch_w (0, kingball_sound | 0xf0);
+}
+
+
+READ8_HANDLER( scramblb_protection_1_r )
+{
+ switch (activecpu_get_pc())
+ {
+ case 0x01da: return 0x80;
+ case 0x01e4: return 0x00;
+ default:
+ logerror("%04x: read protection 1\n",activecpu_get_pc());
+ return 0;
+ }
+}
+
+READ8_HANDLER( scramblb_protection_2_r )
+{
+ switch (activecpu_get_pc())
+ {
+ case 0x01ca: return 0x90;
+ default:
+ logerror("%04x: read protection 2\n",activecpu_get_pc());
+ return 0;
+ }
+}
+
+
+static READ8_HANDLER( azurian_IN1_r )
+{
+ return (readinputport(1) & ~0x40) | ((readinputport(3) & 0x01) << 6);
+}
+
+static READ8_HANDLER( azurian_IN2_r )
+{
+ return (readinputport(2) & ~0x04) | ((readinputport(3) & 0x02) << 1);
+}
+
+
+WRITE8_HANDLER( _4in1_bank_w )
+{
+ _4in1_bank = data & 0x03;
+ galaxian_gfxbank_w(0, _4in1_bank);
+ memory_set_bank(1, _4in1_bank);
+}
+
+READ8_HANDLER( _4in1_input_port_1_r )
+{
+ return (readinputport(1) & ~0xc0) | (readinputport(3+_4in1_bank) & 0xc0);
+}
+
+READ8_HANDLER( _4in1_input_port_2_r )
+{
+ return (readinputport(2) & 0x04) | (readinputport(3+_4in1_bank) & ~0xc4);
+}
+
+
+static void gmgalax_select_game(int game)
+{
+ gmgalax_selected_game = game;
+
+ memory_set_bank(1, game);
+
+ galaxian_gfxbank_w(0, gmgalax_selected_game);
+}
+
+READ8_HANDLER( gmgalax_input_port_0_r )
+{
+ return readinputport(gmgalax_selected_game ? 3 : 0);
+}
+
+READ8_HANDLER( gmgalax_input_port_1_r )
+{
+ return readinputport(gmgalax_selected_game ? 4 : 1);
+}
+
+READ8_HANDLER( gmgalax_input_port_2_r )
+{
+ return readinputport(gmgalax_selected_game ? 5 : 2);
+}
+
+
+DRIVER_INIT( pisces )
+{
+ /* the coin lockout was replaced */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6002, 0x6002, 0, 0, galaxian_gfxbank_w);
+}
+
+DRIVER_INIT( checkmaj )
+{
+ /* for the title screen */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x3800, 0x3800, 0, 0, checkmaj_protection_r);
+}
+
+DRIVER_INIT( dingo )
+{
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x3000, 0x3000, 0, 0, dingo_3000_r);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x3035, 0x3035, 0, 0, dingo_3035_r);
+}
+
+DRIVER_INIT( kingball )
+{
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa000, 0xa000, 0, 0, kingball_IN0_r);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa800, 0xa800, 0, 0, kingball_IN1_r);
+
+ state_save_register_global(kingball_speech_dip);
+ state_save_register_global(kingball_sound);
+}
+
+
+static UINT8 decode_mooncrst(UINT8 data,offs_t addr)
+{
+ UINT8 res;
+
+ res = data;
+ if (BIT(data,1)) res ^= 0x40;
+ if (BIT(data,5)) res ^= 0x04;
+ if ((addr & 1) == 0)
+ res = (res & 0xbb) | (BIT(res,6) << 2) | (BIT(res,2) << 6);
+ return res;
+}
+
+DRIVER_INIT( mooncrsu )
+{
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa000, 0xa002, 0, 0, galaxian_gfxbank_w);
+}
+
+DRIVER_INIT( mooncrst )
+{
+ offs_t i;
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+
+ for (i = 0;i < memory_region_length(REGION_CPU1);i++)
+ rom[i] = decode_mooncrst(rom[i],i);
+
+ driver_init_mooncrsu(machine);
+}
+
+DRIVER_INIT( mooncrgx )
+{
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x6002, 0, 0, galaxian_gfxbank_w);
+}
+
+DRIVER_INIT( moonqsr )
+{
+ offs_t i;
+ UINT8 *rom = memory_region(REGION_CPU1);
+ UINT8 *decrypt = auto_malloc(0x8000);
+
+ memory_set_decrypted_region(0, 0x0000, 0x7fff, decrypt);
+
+ for (i = 0;i < 0x8000;i++)
+ decrypt[i] = decode_mooncrst(rom[i],i);
+}
+
+DRIVER_INIT( checkman )
+{
+/*
+ Encryption Table
+ ----------------
++---+---+---+------+------+------+------+------+------+------+------+
+|A2 |A1 |A0 |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 |
++---+---+---+------+------+------+------+------+------+------+------+
+| 0 | 0 | 0 |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0^^D6|
+| 0 | 0 | 1 |D7 |D6 |D5 |D4 |D3 |D2 |D1^^D5|D0 |
+| 0 | 1 | 0 |D7 |D6 |D5 |D4 |D3 |D2^^D4|D1^^D6|D0 |
+| 0 | 1 | 1 |D7 |D6 |D5 |D4^^D2|D3 |D2 |D1 |D0^^D5|
+| 1 | 0 | 0 |D7 |D6^^D4|D5^^D1|D4 |D3 |D2 |D1 |D0 |
+| 1 | 0 | 1 |D7 |D6^^D0|D5^^D2|D4 |D3 |D2 |D1 |D0 |
+| 1 | 1 | 0 |D7 |D6 |D5 |D4 |D3 |D2^^D0|D1 |D0 |
+| 1 | 1 | 1 |D7 |D6 |D5 |D4^^D1|D3 |D2 |D1 |D0 |
++---+---+---+------+------+------+------+------+------+------+------+
+
+For example if A2=1, A1=1 and A0=0 then D2 to the CPU would be an XOR of
+D2 and D0 from the ROM's. Note that D7 and D3 are not encrypted.
+
+Encryption PAL 16L8 on cardridge
+ +--- ---+
+ OE --| U |-- VCC
+ ROMD0 --| |-- D0
+ ROMD1 --| |-- D1
+ ROMD2 --|VER 5.2|-- D2
+ A0 --| |-- NOT USED
+ A1 --| |-- A2
+ ROMD4 --| |-- D4
+ ROMD5 --| |-- D5
+ ROMD6 --| |-- D6
+ GND --| |-- M1 (NOT USED)
+ +-------+
+Pin layout is such that links can replace the PAL if encryption is not used.
+
+*/
+ static const UINT8 xortable[8][4] =
+ {
+ { 6,0,6,0 },
+ { 5,1,5,1 },
+ { 4,2,6,1 },
+ { 2,4,5,0 },
+ { 4,6,1,5 },
+ { 0,6,2,5 },
+ { 0,2,0,2 },
+ { 1,4,1,4 }
+ };
+
+ offs_t i;
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+
+ for (i = 0; i < memory_region_length(REGION_CPU1); i++)
+ {
+ UINT8 data_xor;
+ int line = i & 0x07;
+
+ data_xor = (BIT(rom[i],xortable[line][0]) << xortable[line][1]) |
+ (BIT(rom[i],xortable[line][2]) << xortable[line][3]);
+
+ rom[i] ^= data_xor;
+ }
+}
+
+DRIVER_INIT( gteikob2 )
+{
+ driver_init_pisces(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x7006, 0x7006, 0, 0, gteikob2_flip_screen_x_w);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x7007, 0x7007, 0, 0, gteikob2_flip_screen_y_w);
+}
+
+DRIVER_INIT( azurian )
+{
+ driver_init_pisces(machine);
+
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6800, 0x6800, 0, 0, azurian_IN1_r);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x7000, 0x7000, 0, 0, azurian_IN2_r);
+}
+
+DRIVER_INIT( 4in1 )
+{
+ offs_t i;
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ /* Decrypt Program Roms */
+ for (i = 0; i < memory_region_length(REGION_CPU1); i++)
+ RAM[i] = RAM[i] ^ (i & 0xff);
+
+ /* games are banked at 0x0000 - 0x3fff */
+ memory_configure_bank(1, 0, 4, &RAM[0x10000], 0x4000);
+
+ _4in1_bank_w(0, 0); /* set the initial CPU bank */
+
+ state_save_register_global(_4in1_bank);
+}
+
+INTERRUPT_GEN( hunchbks_vh_interrupt )
+{
+ cpunum_set_input_line_and_vector(0,0,PULSE_LINE,0x03);
+}
+
+DRIVER_INIT( ladybugg )
+{
+/* Doesn't actually use the bank, but it mustn't have a coin lock! */
+memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6002, 0x6002, 0, 0, galaxian_gfxbank_w);
+}
+
+DRIVER_INIT( gmgalax )
+{
+ /* games are banked at 0x0000 - 0x3fff */
+ UINT8 *RAM=memory_region(REGION_CPU1);
+ memory_configure_bank(1, 0, 2, &RAM[0x10000], 0x4000);
+
+ state_save_register_global(gmgalax_selected_game);
+
+ gmgalax_select_game(input_port_6_r(0) & 0x01);
+}
+
+INTERRUPT_GEN( gmgalax_vh_interrupt )
+{
+ // reset the cpu if the selected game changed
+ int new_game = input_port_6_r(0) & 0x01;
+
+ if (gmgalax_selected_game != new_game)
+ {
+ gmgalax_select_game(new_game);
+
+ /* Ghost Muncher never clears this */
+ galaxian_stars_enable_w(0, 0);
+
+ cpunum_set_input_line(0, INPUT_LINE_RESET, ASSERT_LINE);
+ }
+}
diff --git a/src/mame/machine/gaplus.c b/src/mame/machine/gaplus.c
new file mode 100644
index 00000000000..d726303860e
--- /dev/null
+++ b/src/mame/machine/gaplus.c
@@ -0,0 +1,69 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/namcoio.h"
+#include "sound/samples.h"
+
+UINT8 *gaplus_customio_3;
+
+/************************************************************************************
+* *
+* Gaplus custom I/O chips (preliminary) *
+* *
+************************************************************************************/
+
+WRITE8_HANDLER( gaplus_customio_3_w )
+{
+ if ((offset == 0x09) && (data >= 0x0f))
+ sample_start(0,0,0);
+ gaplus_customio_3[offset] = data;
+}
+
+
+READ8_HANDLER( gaplus_customio_3_r )
+{
+ int mode;
+
+ mode = gaplus_customio_3[8];
+ if (mode == 2)
+ {
+ switch (offset)
+ {
+ case 0:
+ return readinputport( 4 ); /* cabinet & test mode */
+ break;
+ case 2:
+ return 0x0f;
+ break;
+ default:
+ return gaplus_customio_3[offset];
+ }
+ }
+ else
+ {
+ switch (offset)
+ {
+ case 0:
+ return readinputport( 4 ); /* cabinet & test mode */
+ break;
+ case 1:
+ return 0x0f;
+ break;
+ case 2:
+ return 0x0e;
+ break;
+ case 3:
+ return 0x01;
+ break;
+ default:
+ return gaplus_customio_3[offset];
+ }
+ }
+}
diff --git a/src/mame/machine/harddriv.c b/src/mame/machine/harddriv.c
new file mode 100644
index 00000000000..76d4b3b8dbc
--- /dev/null
+++ b/src/mame/machine/harddriv.c
@@ -0,0 +1,1941 @@
+/***************************************************************************
+
+ Hard Drivin' machine hardware
+
+****************************************************************************/
+
+#include "driver.h"
+#include "cpu/tms34010/tms34010.h"
+#include "cpu/tms34010/34010ops.h"
+#include "cpu/adsp2100/adsp2100.h"
+#include "cpu/m68000/m68000.h"
+#include "cpu/dsp32/dsp32.h"
+#include "machine/atarigen.h"
+#include "machine/asic65.h"
+#include "audio/atarijsa.h"
+#include "harddriv.h"
+
+
+/*************************************
+ *
+ * Constants and macros
+ *
+ *************************************/
+
+#define DUART_CLOCK (36864000)
+#define DS3_TRIGGER 7777
+
+/* debugging tools */
+#define LOG_COMMANDS 0
+
+
+
+/*************************************
+ *
+ * External definitions
+ *
+ *************************************/
+
+/* externally accessible */
+INT8 hdcpu_main;
+INT8 hdcpu_gsp;
+INT8 hdcpu_msp;
+INT8 hdcpu_adsp;
+INT8 hdcpu_sound;
+INT8 hdcpu_sounddsp;
+INT8 hdcpu_jsa;
+INT8 hdcpu_dsp32;
+
+UINT8 hd34010_host_access;
+UINT8 hddsk_pio_access;
+
+UINT16 *hdmsp_ram;
+UINT16 *hddsk_ram;
+UINT16 *hddsk_rom;
+UINT16 *hddsk_zram;
+UINT16 *hd68k_slapstic_base;
+UINT16 *st68k_sloop_alt_base;
+
+UINT16 *hdadsp_data_memory;
+UINT32 *hdadsp_pgm_memory;
+
+UINT16 *hdgsp_protection;
+UINT16 *stmsp_sync[3];
+
+UINT16 *hdgsp_speedup_addr[2];
+offs_t hdgsp_speedup_pc;
+
+UINT16 *hdmsp_speedup_addr;
+offs_t hdmsp_speedup_pc;
+
+UINT16 *hdds3_speedup_addr;
+offs_t hdds3_speedup_pc;
+offs_t hdds3_transfer_pc;
+
+UINT32 *rddsp32_sync[2];
+
+UINT32 gsp_speedup_count[4];
+UINT32 msp_speedup_count[4];
+UINT32 adsp_speedup_count[4];
+
+
+/* from slapstic.c */
+int slapstic_tweak(offs_t offset);
+void slapstic_reset(void);
+
+
+/* from video */
+extern UINT8 *hdgsp_vram;
+
+
+
+/*************************************
+ *
+ * Static globals
+ *
+ *************************************/
+
+static UINT8 irq_state;
+static UINT8 gsp_irq_state;
+static UINT8 msp_irq_state;
+static UINT8 adsp_irq_state;
+static UINT8 duart_irq_state;
+
+static UINT8 duart_read_data[16];
+static UINT8 duart_write_data[16];
+static UINT8 duart_output_port;
+static emu_timer *duart_timer;
+
+static UINT8 last_gsp_shiftreg;
+
+static UINT8 m68k_zp1, m68k_zp2;
+static UINT8 m68k_adsp_buffer_bank;
+
+static UINT8 adsp_halt, adsp_br;
+static UINT8 adsp_xflag;
+
+static UINT16 adsp_sim_address;
+static UINT16 adsp_som_address;
+static UINT32 adsp_eprom_base;
+
+static UINT16 *sim_memory;
+static UINT16 *som_memory;
+static UINT32 sim_memory_size;
+static UINT16 *adsp_pgm_memory_word;
+
+static UINT8 ds3_gcmd, ds3_gflag, ds3_g68irqs, ds3_gfirqs, ds3_g68flag, ds3_send, ds3_reset;
+static UINT16 ds3_gdata, ds3_g68data;
+static UINT32 ds3_sim_address;
+
+static UINT16 adc_control;
+static UINT8 adc8_select;
+static UINT8 adc8_data;
+static UINT8 adc12_select;
+static UINT8 adc12_byte;
+static UINT16 adc12_data;
+
+static UINT16 hdc68k_last_wheel;
+static UINT16 hdc68k_last_port1;
+static UINT8 hdc68k_wheel_edge;
+static UINT8 hdc68k_shifter_state;
+
+static UINT8 st68k_sloop_bank = 0;
+static offs_t st68k_last_alt_sloop_offset;
+
+#define MAX_MSP_SYNC 16
+static UINT32 *dataptr[MAX_MSP_SYNC];
+static UINT32 dataval[MAX_MSP_SYNC];
+static int next_msp_sync;
+
+static void hd68k_update_interrupts(void);
+static TIMER_CALLBACK( duart_callback );
+
+
+
+#if 0
+#pragma mark * DRIVER/MULTISYNC BOARD
+#endif
+
+
+/*************************************
+ *
+ * Initialization
+ *
+ *************************************/
+
+MACHINE_START( harddriv )
+{
+ /* predetermine memory regions */
+ sim_memory = (UINT16 *)memory_region(REGION_USER1);
+ som_memory = (UINT16 *)auto_malloc(0x8000);
+ sim_memory_size = memory_region_length(REGION_USER1) / 2;
+ adsp_pgm_memory_word = (UINT16 *)((UINT8 *)hdadsp_pgm_memory + 1);
+}
+
+
+MACHINE_RESET( harddriv )
+{
+ /* generic reset */
+ atarigen_eeprom_reset();
+ slapstic_reset();
+ atarigen_interrupt_reset(hd68k_update_interrupts);
+
+ /* halt several of the DSPs to start */
+ if (hdcpu_adsp != -1) cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_HALT, ASSERT_LINE);
+ if (hdcpu_dsp32 != -1) cpunum_set_input_line(hdcpu_dsp32, INPUT_LINE_HALT, ASSERT_LINE);
+ if (hdcpu_sounddsp != -1) cpunum_set_input_line(hdcpu_sounddsp, INPUT_LINE_HALT, ASSERT_LINE);
+
+ /* if we found a 6502, reset the JSA board */
+ if (hdcpu_jsa != -1)
+ atarijsa_reset();
+
+ last_gsp_shiftreg = 0;
+
+ m68k_adsp_buffer_bank = 0;
+
+ /* reset IRQ states */
+ irq_state = gsp_irq_state = msp_irq_state = adsp_irq_state = duart_irq_state = 0;
+
+ /* reset the DUART */
+ memset(duart_read_data, 0, sizeof(duart_read_data));
+ memset(duart_write_data, 0, sizeof(duart_write_data));
+ duart_output_port = 0;
+ duart_timer = timer_alloc(duart_callback);
+
+ /* reset the ADSP/DSIII/DSIV boards */
+ adsp_halt = 1;
+ adsp_br = 0;
+ adsp_xflag = 0;
+}
+
+
+
+/*************************************
+ *
+ * 68000 interrupt handling
+ *
+ *************************************/
+
+static void hd68k_update_interrupts(void)
+{
+ int newstate = 0;
+
+ if (msp_irq_state)
+ newstate = 1;
+ if (adsp_irq_state)
+ newstate = 2;
+ if (gsp_irq_state)
+ newstate = 3;
+ if (atarigen_sound_int_state) /* /LINKIRQ on STUN Runner */
+ newstate = 4;
+ if (irq_state)
+ newstate = 5;
+ if (duart_irq_state)
+ newstate = 6;
+
+ if (newstate)
+ cpunum_set_input_line(hdcpu_main, newstate, ASSERT_LINE);
+ else
+ cpunum_set_input_line(hdcpu_main, 7, CLEAR_LINE);
+}
+
+
+INTERRUPT_GEN( hd68k_irq_gen )
+{
+ irq_state = 1;
+ atarigen_update_interrupts();
+}
+
+
+WRITE16_HANDLER( hd68k_irq_ack_w )
+{
+ irq_state = 0;
+ atarigen_update_interrupts();
+}
+
+
+void hdgsp_irq_gen(int state)
+{
+ gsp_irq_state = state;
+ atarigen_update_interrupts();
+}
+
+
+void hdmsp_irq_gen(int state)
+{
+ msp_irq_state = state;
+ atarigen_update_interrupts();
+}
+
+
+
+/*************************************
+ *
+ * 68000 access to GSP
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_gsp_io_r )
+{
+ UINT16 result;
+ offset = (offset / 2) ^ 1;
+ hd34010_host_access = 1;
+ result = tms34010_host_r(hdcpu_gsp, offset);
+ hd34010_host_access = 0;
+ return result;
+}
+
+
+WRITE16_HANDLER( hd68k_gsp_io_w )
+{
+ offset = (offset / 2) ^ 1;
+ hd34010_host_access = 1;
+ tms34010_host_w(hdcpu_gsp, offset, data);
+ hd34010_host_access = 0;
+}
+
+
+
+/*************************************
+ *
+ * 68000 access to MSP
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_msp_io_r )
+{
+ UINT16 result;
+ offset = (offset / 2) ^ 1;
+ hd34010_host_access = 1;
+ result = (hdcpu_msp != -1) ? tms34010_host_r(hdcpu_msp, offset) : 0xffff;
+ hd34010_host_access = 0;
+ return result;
+}
+
+
+WRITE16_HANDLER( hd68k_msp_io_w )
+{
+ offset = (offset / 2) ^ 1;
+ if (hdcpu_msp != -1)
+ {
+ hd34010_host_access = 1;
+ tms34010_host_w(hdcpu_msp, offset, data);
+ hd34010_host_access = 0;
+ }
+}
+
+
+
+/*************************************
+ *
+ * 68000 input handlers
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_port0_r )
+{
+ /* port is as follows:
+
+ 0x0001 = DIAGN
+ 0x0002 = /HSYNCB
+ 0x0004 = /VSYNCB
+ 0x0008 = EOC12
+ 0x0010 = EOC8
+ 0x0020 = SELF-TEST
+ 0x0040 = COIN2
+ 0x0080 = COIN1
+ 0x0100 = SW1 #8
+ 0x0200 = SW1 #7
+ .....
+ 0x8000 = SW1 #1
+ */
+ int temp = readinputport(0);
+ if (atarigen_get_hblank(Machine, 0)) temp ^= 0x0002;
+ temp ^= 0x0018; /* both EOCs always high for now */
+ return temp;
+}
+
+
+READ16_HANDLER( hdc68k_port1_r )
+{
+ UINT16 result = readinputport(1);
+ UINT16 diff = result ^ hdc68k_last_port1;
+
+ /* if a new shifter position is selected, use it */
+ /* if it's the same shifter position as last time, go back to neutral */
+ if ((diff & 0x0100) && !(result & 0x0100))
+ hdc68k_shifter_state = (hdc68k_shifter_state == 1) ? 0 : 1;
+ if ((diff & 0x0200) && !(result & 0x0200))
+ hdc68k_shifter_state = (hdc68k_shifter_state == 2) ? 0 : 2;
+ if ((diff & 0x0400) && !(result & 0x0400))
+ hdc68k_shifter_state = (hdc68k_shifter_state == 4) ? 0 : 4;
+ if ((diff & 0x0800) && !(result & 0x0800))
+ hdc68k_shifter_state = (hdc68k_shifter_state == 8) ? 0 : 8;
+
+ /* merge in the new shifter value */
+ result = (result | 0x0f00) ^ (hdc68k_shifter_state << 8);
+
+ /* merge in the wheel edge latch bit */
+ if (hdc68k_wheel_edge)
+ result ^= 0x4000;
+
+ hdc68k_last_port1 = result;
+ return result;
+}
+
+
+READ16_HANDLER( hda68k_port1_r )
+{
+ UINT16 result = readinputport(1);
+
+ /* merge in the wheel edge latch bit */
+ if (hdc68k_wheel_edge)
+ result ^= 0x4000;
+
+ return result;
+}
+
+
+READ16_HANDLER( hdc68k_wheel_r )
+{
+ /* grab the new wheel value and upconvert to 12 bits */
+ UINT16 new_wheel = readinputport(10) << 4;
+
+ /* hack to display the wheel position */
+ if (input_code_pressed(KEYCODE_LSHIFT))
+ popmessage("%04X", new_wheel);
+
+ /* if we crossed the center line, latch the edge bit */
+ if ((hdc68k_last_wheel / 0xf0) != (new_wheel / 0xf0))
+ hdc68k_wheel_edge = 1;
+
+ /* remember the last value and return the low 8 bits */
+ hdc68k_last_wheel = new_wheel;
+ return (new_wheel << 8) | 0xff;
+}
+
+
+READ16_HANDLER( hd68k_adc8_r )
+{
+ return adc8_data;
+}
+
+
+READ16_HANDLER( hd68k_adc12_r )
+{
+ return adc12_byte ? ((adc12_data >> 8) & 0x0f) : (adc12_data & 0xff);
+}
+
+
+READ16_HANDLER( hd68k_sound_reset_r )
+{
+ if (hdcpu_jsa != -1)
+ atarijsa_reset();
+ return ~0;
+}
+
+
+
+/*************************************
+ *
+ * 68000 output handlers
+ *
+ *************************************/
+
+WRITE16_HANDLER( hd68k_adc_control_w )
+{
+ COMBINE_DATA(&adc_control);
+
+ /* handle a write to the 8-bit ADC address select */
+ if (adc_control & 0x08)
+ {
+ adc8_select = adc_control & 0x07;
+ adc8_data = readinputport(2 + adc8_select);
+ }
+
+ /* handle a write to the 12-bit ADC address select */
+ if (adc_control & 0x40)
+ {
+ adc12_select = (adc_control >> 4) & 0x03;
+ adc12_data = readinputport(10 + adc12_select) << 4;
+ }
+
+ /* bit 7 selects which byte of the 12 bit data to read */
+ adc12_byte = (adc_control >> 7) & 1;
+}
+
+
+WRITE16_HANDLER( hd68k_wr0_write )
+{
+ /* bit 3 selects the value; data is ignored */
+ data = (offset >> 3) & 1;
+
+ /* low 3 bits select the function */
+ offset &= 7;
+ switch (offset)
+ {
+ case 1: /* SEL1 */
+ case 2: /* SEL2 */
+ case 3: /* SEL3 */
+ case 4: /* SEL4 */
+ default:
+ /* just ignore */
+ break;
+
+ case 6: /* CC1 */
+ case 7: /* CC2 */
+ coin_counter_w(offset - 6, data);
+ break;
+ }
+}
+
+
+WRITE16_HANDLER( hd68k_wr1_write )
+{
+ if (offset == 0) { // logerror("Shifter Interface Latch = %02X\n", data);
+ } else { logerror("/WR1(%04X)=%02X\n", offset, data);
+ }
+}
+
+
+WRITE16_HANDLER( hd68k_wr2_write )
+{
+ if (offset == 0) { // logerror("Steering Wheel Latch = %02X\n", data);
+ } else { logerror("/WR2(%04X)=%02X\n", offset, data);
+ }
+}
+
+
+WRITE16_HANDLER( hd68k_nwr_w )
+{
+ /* bit 3 selects the value; data is ignored */
+ data = (offset >> 3) & 1;
+
+ /* low 3 bits select the function */
+ offset &= 7;
+ switch (offset)
+ {
+ case 0: /* CR2 */
+ case 1: /* CR1 */
+ set_led_status(offset, data);
+ break;
+ case 2: /* LC1 */
+ break;
+ case 3: /* LC2 */
+ break;
+ case 4: /* ZP1 */
+ m68k_zp1 = data;
+ break;
+ case 5: /* ZP2 */
+ m68k_zp2 = data;
+ break;
+ case 6: /* /GSPRES */
+ logerror("Write to /GSPRES(%d)\n", data);
+ if (hdcpu_gsp != -1)
+ cpunum_set_input_line(hdcpu_gsp, INPUT_LINE_RESET, data ? CLEAR_LINE : ASSERT_LINE);
+ break;
+ case 7: /* /MSPRES */
+ logerror("Write to /MSPRES(%d)\n", data);
+ if (hdcpu_msp != -1)
+ cpunum_set_input_line(hdcpu_msp, INPUT_LINE_RESET, data ? CLEAR_LINE : ASSERT_LINE);
+ break;
+ }
+}
+
+
+WRITE16_HANDLER( hdc68k_wheel_edge_reset_w )
+{
+ /* reset the edge latch */
+ hdc68k_wheel_edge = 0;
+}
+
+
+
+/*************************************
+ *
+ * 68000 ZRAM access
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_zram_r )
+{
+ return atarigen_eeprom[offset];
+}
+
+
+WRITE16_HANDLER( hd68k_zram_w )
+{
+ if (m68k_zp1 == 0 && m68k_zp2 == 1)
+ COMBINE_DATA(&atarigen_eeprom[offset]);
+}
+
+
+
+/*************************************
+ *
+ * 68000 DUART interface
+ *
+ *************************************/
+
+/*
+ DUART registers
+
+ Read Write
+ ---------------------------------- -------------------------------------------
+ 0x00 = Mode Register A (MR1A, MR2A) Mode Register A (MR1A, MR2A)
+ 0x02 = Status Register A (SRA) Clock-Select Register A (CSRA)
+ 0x04 = Clock-Select Register A 1 (CSRA) Command Register A (CRA)
+ 0x06 = Receiver Buffer A (RBA) Transmitter Buffer A (TBA)
+ 0x08 = Input Port Change Register (IPCR) Auxiliary Control Register (ACR)
+ 0x0a = Interrupt Status Register (ISR) Interrupt Mask Register (IMR)
+ 0x0c = Counter Mode: Current MSB of Counter/Timer Upper Register (CTUR)
+ Counter (CUR)
+ 0x0e = Counter Mode: Current LSB of Counter/Timer Lower Register (CTLR)
+ Counter (CLR)
+ 0x10 = Mode Register B (MR1B, MR2B) Mode Register B (MR1B, MR2B)
+ 0x12 = Status Register B (SRB) Clock-Select Register B (CSRB)
+ 0x14 = Clock-Select Register B 2 (CSRB) Command Register B (CRB)
+ 0x16 = Receiver Buffer B (RBB) Transmitter Buffer B (TBB)
+ 0x18 = Interrupt-Vector Register (IVR) Interrupt-Vector Register (IVR)
+ 0x1a = Input Port (IP) Output Port Configuration Register (OPCR)
+ 0x1c = Start-Counter Command 3 Output Port Register (OPR): Bit Set Command 3
+ 0x1e = Stop-Counter Command 3 Output Port Register (OPR): Bit Reset Command 3
+*/
+
+
+INLINE int duart_clock(void)
+{
+ int mode = (duart_write_data[0x04] >> 4) & 7;
+ if (mode != 3)
+ logerror("DUART: unsupported clock mode %d\n", mode);
+ return DUART_CLOCK / 16;
+}
+
+
+INLINE attotime duart_clock_period(void)
+{
+ return ATTOTIME_IN_HZ(duart_clock());
+}
+
+
+static TIMER_CALLBACK( duart_callback )
+{
+ logerror("DUART timer fired\n");
+ if (duart_write_data[0x05] & 0x08)
+ {
+ logerror("DUART interrupt generated\n");
+ duart_read_data[0x05] |= 0x08;
+ duart_irq_state = (duart_read_data[0x05] & duart_write_data[0x05]) != 0;
+ atarigen_update_interrupts();
+ }
+ timer_adjust(duart_timer, attotime_mul(duart_clock_period(), 65536), 0, attotime_zero);
+}
+
+
+READ16_HANDLER( hd68k_duart_r )
+{
+ switch (offset)
+ {
+ case 0x00: /* Mode Register A (MR1A, MR2A) */
+ case 0x08: /* Mode Register B (MR1B, MR2B) */
+ return (duart_write_data[0x00] << 8) | 0x00ff;
+ case 0x01: /* Status Register A (SRA) */
+ case 0x02: /* Clock-Select Register A 1 (CSRA) */
+ case 0x03: /* Receiver Buffer A (RBA) */
+ case 0x04: /* Input Port Change Register (IPCR) */
+ case 0x05: /* Interrupt Status Register (ISR) */
+ case 0x06: /* Counter Mode: Current MSB of Counter (CUR) */
+ case 0x07: /* Counter Mode: Current LSB of Counter (CLR) */
+ case 0x09: /* Status Register B (SRB) */
+ case 0x0a: /* Clock-Select Register B 2 (CSRB) */
+ case 0x0b: /* Receiver Buffer B (RBB) */
+ case 0x0c: /* Interrupt-Vector Register (IVR) */
+ case 0x0d: /* Input Port (IP) */
+ return (duart_read_data[offset] << 8) | 0x00ff;
+ case 0x0e: /* Start-Counter Command 3 */
+ {
+ int reps = (duart_write_data[0x06] << 8) | duart_write_data[0x07];
+ timer_adjust(duart_timer, attotime_mul(duart_clock_period(), reps), 0, attotime_zero);
+ logerror("DUART timer started (period=%f)\n", attotime_to_double(attotime_mul(duart_clock_period(), reps)));
+ return 0x00ff;
+ }
+ case 0x0f: /* Stop-Counter Command 3 */
+ {
+ int reps = attotime_to_double(attotime_mul(timer_timeleft(duart_timer), duart_clock()));
+ timer_adjust(duart_timer, attotime_never, 0, attotime_zero);
+ duart_read_data[0x06] = reps >> 8;
+ duart_read_data[0x07] = reps & 0xff;
+ logerror("DUART timer stopped (final count=%04X)\n", reps);
+ }
+ duart_read_data[0x05] &= ~0x08;
+ duart_irq_state = (duart_read_data[0x05] & duart_write_data[0x05]) != 0;
+ atarigen_update_interrupts();
+ return 0x00ff;
+ }
+ return 0x00ff;
+}
+
+
+WRITE16_HANDLER( hd68k_duart_w )
+{
+ if (ACCESSING_MSB)
+ {
+ int newdata = (data >> 8) & 0xff;
+ duart_write_data[offset] = newdata;
+
+ switch (offset)
+ {
+ case 0x00: /* Mode Register A (MR1A, MR2A) */
+ case 0x01: /* Clock-Select Register A (CSRA) */
+ case 0x02: /* Command Register A (CRA) */
+ case 0x03: /* Transmitter Buffer A (TBA) */
+ case 0x04: /* Auxiliary Control Register (ACR) */
+ case 0x05: /* Interrupt Mask Register (IMR) */
+ case 0x06: /* Counter/Timer Upper Register (CTUR) */
+ case 0x07: /* Counter/Timer Lower Register (CTLR) */
+ case 0x08: /* Mode Register B (MR1B, MR2B) */
+ case 0x09: /* Clock-Select Register B (CSRB) */
+ case 0x0a: /* Command Register B (CRB) */
+ case 0x0b: /* Transmitter Buffer B (TBB) */
+ case 0x0c: /* Interrupt-Vector Register (IVR) */
+ case 0x0d: /* Output Port Configuration Register (OPCR) */
+ break;
+ case 0x0e: /* Output Port Register (OPR): Bit Set Command 3 */
+ duart_output_port |= newdata;
+ break;
+ case 0x0f: /* Output Port Register (OPR): Bit Reset Command 3 */
+ duart_output_port &= ~newdata;
+ break;
+ }
+ logerror("DUART write %02X @ %02X\n", (data >> 8) & 0xff, offset);
+ }
+ else
+ logerror("Unexpected DUART write %02X @ %02X\n", data, offset);
+}
+
+
+
+/*************************************
+ *
+ * GSP I/O register writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( hdgsp_io_w )
+{
+ /* detect an enabling of the shift register and force yielding */
+ if (offset == REG_DPYCTL)
+ {
+ UINT8 new_shiftreg = (data >> 11) & 1;
+ if (new_shiftreg != last_gsp_shiftreg)
+ {
+ last_gsp_shiftreg = new_shiftreg;
+ if (new_shiftreg)
+ cpu_yield();
+ }
+ }
+
+ /* detect changes to HEBLNK and HSBLNK and force an update before they change */
+ if ((offset == REG_HEBLNK || offset == REG_HSBLNK) && data != tms34010_io_register_r(offset, 0))
+ video_screen_update_partial(0, video_screen_get_vpos(0) - 1);
+
+ tms34010_io_register_w(offset, data, mem_mask);
+}
+
+
+
+/*************************************
+ *
+ * GSP protection workarounds
+ *
+ *************************************/
+
+WRITE16_HANDLER( hdgsp_protection_w )
+{
+ /* this memory address is incremented whenever a protection check fails */
+ /* after it reaches a certain value, the GSP will randomly trash a */
+ /* register; we just prevent it from ever going above 0 */
+ *hdgsp_protection = 0;
+}
+
+
+
+/*************************************
+ *
+ * MSP synchronization helpers
+ *
+ *************************************/
+
+static TIMER_CALLBACK( stmsp_sync_update )
+{
+ int which = param >> 28;
+ offs_t offset = (param >> 16) & 0xfff;
+ UINT16 data = param;
+ stmsp_sync[which][offset] = data;
+ cpu_triggerint(hdcpu_msp);
+}
+
+
+INLINE void stmsp_sync_w(int which, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ UINT16 newdata = stmsp_sync[which][offset];
+ COMBINE_DATA(&newdata);
+
+ /* if being written from the 68000, synchronize on it */
+ if (hd34010_host_access)
+ timer_call_after_resynch(newdata | (offset << 16) | (which << 28), stmsp_sync_update);
+
+ /* otherwise, just update */
+ else
+ stmsp_sync[which][offset] = newdata;
+}
+
+
+WRITE16_HANDLER( stmsp_sync0_w )
+{
+ stmsp_sync_w(0, offset, data, mem_mask);
+}
+
+
+WRITE16_HANDLER( stmsp_sync1_w )
+{
+ stmsp_sync_w(1, offset, data, mem_mask);
+}
+
+
+WRITE16_HANDLER( stmsp_sync2_w )
+{
+ stmsp_sync_w(2, offset, data, mem_mask);
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * ADSP BOARD
+#endif
+
+/*************************************
+ *
+ * 68000 access to ADSP program memory
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_adsp_program_r )
+{
+ UINT32 word = hdadsp_pgm_memory[offset/2];
+ return (!(offset & 1)) ? (word >> 16) : (word & 0xffff);
+}
+
+
+WRITE16_HANDLER( hd68k_adsp_program_w )
+{
+ UINT32 *base = &hdadsp_pgm_memory[offset/2];
+ UINT32 oldword = *base;
+ UINT16 temp;
+
+ if (!(offset & 1))
+ {
+ temp = oldword >> 16;
+ COMBINE_DATA(&temp);
+ oldword = (oldword & 0x0000ffff) | (temp << 16);
+ }
+ else
+ {
+ temp = oldword & 0xffff;
+ COMBINE_DATA(&temp);
+ oldword = (oldword & 0xffff0000) | temp;
+ }
+ *base = oldword;
+}
+
+
+
+/*************************************
+ *
+ * 68000 access to ADSP data memory
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_adsp_data_r )
+{
+ return hdadsp_data_memory[offset];
+}
+
+
+WRITE16_HANDLER( hd68k_adsp_data_w )
+{
+ COMBINE_DATA(&hdadsp_data_memory[offset]);
+
+ /* any write to $1FFF is taken to be a trigger; synchronize the CPUs */
+ if (offset == 0x1fff)
+ {
+ logerror("%06X:ADSP sync address written (%04X)\n", activecpu_get_previouspc(), data);
+ timer_call_after_resynch(0, 0);
+ cpu_triggerint(hdcpu_adsp);
+ }
+ else
+ logerror("%06X:ADSP W@%04X (%04X)\n", activecpu_get_previouspc(), offset, data);
+}
+
+
+
+/*************************************
+ *
+ * 68000 access to ADSP output memory
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_adsp_buffer_r )
+{
+/* logerror("hd68k_adsp_buffer_r(%04X)\n", offset);*/
+ return som_memory[m68k_adsp_buffer_bank * 0x2000 + offset];
+}
+
+
+WRITE16_HANDLER( hd68k_adsp_buffer_w )
+{
+ COMBINE_DATA(&som_memory[m68k_adsp_buffer_bank * 0x2000 + offset]);
+}
+
+
+
+/*************************************
+ *
+ * 68000 access to ADSP control regs
+ *
+ *************************************/
+
+static TIMER_CALLBACK( deferred_adsp_bank_switch )
+{
+#if LOG_COMMANDS
+ if (m68k_adsp_buffer_bank != param && input_code_pressed(KEYCODE_L))
+ {
+ static FILE *commands;
+ if (!commands) commands = fopen("commands.log", "w");
+ if (commands)
+ {
+ INT16 *base = (INT16 *)&som_memory[param * 0x2000];
+ INT16 *end = base + (UINT16)*base++;
+ INT16 *current = base;
+ INT16 *table = base + (UINT16)*current++;
+
+ fprintf(commands, "\n---------------\n");
+
+ while ((current + 5) < table)
+ {
+ int offset = (int)(current - base);
+ int c1 = *current++;
+ int c2 = *current++;
+ int c3 = *current++;
+ int c4 = *current++;
+ fprintf(commands, "Cmd @ %04X = %04X %d-%d @ %d\n", offset, c1, c2, c3, c4);
+ while (current < table)
+ {
+ UINT32 rslope, lslope;
+ rslope = (UINT16)*current++,
+ rslope |= *current++ << 16;
+ if (rslope == 0xffffffff)
+ {
+ fprintf(commands, " (end)\n");
+ break;
+ }
+ lslope = (UINT16)*current++,
+ lslope |= *current++ << 16;
+ fprintf(commands, " L=%08X R=%08X count=%d\n",
+ (int)lslope, (int)rslope, (int)*current++);
+ }
+ }
+ fprintf(commands, "\nTable:\n");
+ current = table;
+ while (current < end)
+ fprintf(commands, " %04X\n", *current++);
+ }
+ }
+#endif
+ m68k_adsp_buffer_bank = param;
+ logerror("ADSP bank = %d\n", param);
+}
+
+
+WRITE16_HANDLER( hd68k_adsp_control_w )
+{
+ /* bit 3 selects the value; data is ignored */
+ int val = (offset >> 3) & 1;
+
+ /* low 3 bits select the function */
+ offset &= 7;
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ /* LEDs */
+ break;
+
+ case 3:
+ logerror("ADSP bank = %d (deferred)\n", val);
+ timer_call_after_resynch(val, deferred_adsp_bank_switch);
+ break;
+
+ case 5:
+ /* connected to the /BR (bus request) line; this effectively halts */
+ /* the ADSP at the next instruction boundary */
+ adsp_br = !val;
+ logerror("ADSP /BR = %d\n", !adsp_br);
+ if (adsp_br || adsp_halt)
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_HALT, ASSERT_LINE);
+ else
+ {
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_HALT, CLEAR_LINE);
+ /* a yield in this case is not enough */
+ /* we would need to increase the interleaving otherwise */
+ /* note that this only affects the test mode */
+ cpu_spin();
+ }
+ break;
+
+ case 6:
+ /* connected to the /HALT line; this effectively halts */
+ /* the ADSP at the next instruction boundary */
+ adsp_halt = !val;
+ logerror("ADSP /HALT = %d\n", !adsp_halt);
+ if (adsp_br || adsp_halt)
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_HALT, ASSERT_LINE);
+ else
+ {
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_HALT, CLEAR_LINE);
+ /* a yield in this case is not enough */
+ /* we would need to increase the interleaving otherwise */
+ /* note that this only affects the test mode */
+ cpu_spin();
+ }
+ break;
+
+ case 7:
+ logerror("ADSP reset = %d\n", val);
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_RESET, val ? CLEAR_LINE : ASSERT_LINE);
+ cpu_yield();
+ break;
+
+ default:
+ logerror("ADSP control %02X = %04X\n", offset, data);
+ break;
+ }
+}
+
+
+WRITE16_HANDLER( hd68k_adsp_irq_clear_w )
+{
+ logerror("%06X:68k clears ADSP interrupt\n", activecpu_get_previouspc());
+ adsp_irq_state = 0;
+ atarigen_update_interrupts();
+}
+
+
+READ16_HANDLER( hd68k_adsp_irq_state_r )
+{
+ int result = 0xfffd;
+ if (adsp_xflag) result ^= 2;
+ if (adsp_irq_state) result ^= 1;
+ logerror("%06X:68k reads ADSP interrupt state = %04x\n", activecpu_get_previouspc(), result);
+ return result;
+}
+
+
+
+/*************************************
+ *
+ * ADSP memory-mapped I/O
+ *
+ *************************************/
+
+READ16_HANDLER( hdadsp_special_r )
+{
+ switch (offset & 7)
+ {
+ case 0: /* /SIMBUF */
+ if (adsp_eprom_base + adsp_sim_address < sim_memory_size)
+ return sim_memory[adsp_eprom_base + adsp_sim_address++];
+ else
+ return 0xff;
+
+ case 1: /* /SIMLD */
+ break;
+
+ case 2: /* /SOMO */
+ break;
+
+ case 3: /* /SOMLD */
+ break;
+
+ default:
+ logerror("%04X:hdadsp_special_r(%04X)\n", activecpu_get_previouspc(), offset);
+ break;
+ }
+ return 0;
+}
+
+
+WRITE16_HANDLER( hdadsp_special_w )
+{
+ switch (offset & 7)
+ {
+ case 1: /* /SIMCLK */
+ adsp_sim_address = data;
+ break;
+
+ case 2: /* SOMLATCH */
+ som_memory[(m68k_adsp_buffer_bank ^ 1) * 0x2000 + (adsp_som_address++ & 0x1fff)] = data;
+ break;
+
+ case 3: /* /SOMCLK */
+ adsp_som_address = data;
+ break;
+
+ case 5: /* /XOUT */
+ adsp_xflag = data & 1;
+ break;
+
+ case 6: /* /GINT */
+ logerror("%04X:ADSP signals interrupt\n", activecpu_get_previouspc());
+ adsp_irq_state = 1;
+ atarigen_update_interrupts();
+ break;
+
+ case 7: /* /MP */
+ adsp_eprom_base = 0x10000 * data;
+ break;
+
+ default:
+ logerror("%04X:hdadsp_special_w(%04X)=%04X\n", activecpu_get_previouspc(), offset, data);
+ break;
+ }
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * DS III BOARD
+#endif
+
+/*************************************
+ *
+ * General DS III I/O
+ *
+ *************************************/
+
+static void update_ds3_irq(void)
+{
+ /* update the IRQ2 signal to the ADSP2101 */
+ if (!(!ds3_g68flag && ds3_g68irqs) && !(ds3_gflag && ds3_gfirqs))
+ cpunum_set_input_line(hdcpu_adsp, ADSP2100_IRQ2, ASSERT_LINE);
+ else
+ cpunum_set_input_line(hdcpu_adsp, ADSP2100_IRQ2, CLEAR_LINE);
+}
+
+
+WRITE16_HANDLER( hd68k_ds3_control_w )
+{
+ int val = (offset >> 3) & 1;
+
+ switch (offset & 7)
+ {
+ case 0:
+ /* SRES - reset sound CPU */
+ break;
+
+ case 1:
+ /* XRES - reset sound helper CPU */
+ break;
+
+ case 2:
+ /* connected to the /BR (bus request) line; this effectively halts */
+ /* the ADSP at the next instruction boundary */
+ adsp_br = !val;
+ if (adsp_br)
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_HALT, ASSERT_LINE);
+ else
+ {
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_HALT, CLEAR_LINE);
+ /* a yield in this case is not enough */
+ /* we would need to increase the interleaving otherwise */
+ /* note that this only affects the test mode */
+ cpu_spin();
+ }
+ break;
+
+ case 3:
+ cpunum_set_input_line(hdcpu_adsp, INPUT_LINE_RESET, val ? CLEAR_LINE : ASSERT_LINE);
+ if (val && !ds3_reset)
+ {
+ ds3_gflag = 0;
+ ds3_gcmd = 0;
+ ds3_gfirqs = 0;
+ ds3_g68irqs = !ds3_gfirqs;
+ ds3_send = 0;
+ update_ds3_irq();
+ }
+ ds3_reset = val;
+ cpu_yield();
+ logerror("DS III reset = %d\n", val);
+ break;
+
+ case 7:
+ /* LED */
+ break;
+
+ default:
+ logerror("DS III control %02X = %04X\n", offset, data);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * DS III graphics I/O
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_ds3_girq_state_r )
+{
+ int result = 0x0fff;
+ if (ds3_g68flag) result ^= 0x8000;
+ if (ds3_gflag) result ^= 0x4000;
+ if (ds3_g68irqs) result ^= 0x2000;
+ if (!adsp_irq_state) result ^= 0x1000;
+ return result;
+}
+
+
+READ16_HANDLER( hd68k_ds3_gdata_r )
+{
+ offs_t pc = activecpu_get_pc();
+
+ ds3_gflag = 0;
+ update_ds3_irq();
+
+ logerror("%06X:hd68k_ds3_gdata_r(%04X)\n", activecpu_get_previouspc(), ds3_gdata);
+
+ /* attempt to optimize the transfer if conditions are right */
+ if (cpu_getactivecpu() == 0 && pc == hdds3_transfer_pc &&
+ !(!ds3_g68flag && ds3_g68irqs) && !(ds3_gflag && ds3_gfirqs))
+ {
+ UINT32 destaddr = activecpu_get_reg(M68K_A1);
+ UINT16 count68k = activecpu_get_reg(M68K_D1);
+ UINT16 mstat = cpunum_get_reg(hdcpu_adsp, ADSP2100_MSTAT);
+ UINT16 i6 = cpunum_get_reg(hdcpu_adsp, (mstat & 1) ? ADSP2100_MR0 : ADSP2100_MR0_SEC);
+ UINT16 l6 = cpunum_get_reg(hdcpu_adsp, ADSP2100_L6) - 1;
+ UINT16 m7 = cpunum_get_reg(hdcpu_adsp, ADSP2100_M7);
+
+ logerror("%06X:optimizing 68k transfer, %d words\n", activecpu_get_previouspc(), count68k);
+
+ while (count68k > 0 && hdadsp_data_memory[0x16e6] > 0)
+ {
+ program_write_word(destaddr, ds3_gdata);
+ {
+ hdadsp_data_memory[0x16e6]--;
+ ds3_gdata = hdadsp_pgm_memory[i6] >> 8;
+ i6 = (i6 & ~l6) | ((i6 + m7) & l6);
+ }
+ count68k--;
+ }
+ activecpu_set_reg(M68K_D1, count68k);
+ cpunum_set_reg(hdcpu_adsp, (mstat & 1) ? ADSP2100_MR0 : ADSP2100_MR0_SEC, i6);
+ adsp_speedup_count[1]++;
+ }
+
+ /* if we just cleared the IRQ, we are going to do some VERY timing critical reads */
+ /* it is important that all the CPUs be in sync before we continue, so spin a little */
+ /* while to let everyone else catch up */
+ cpu_spinuntil_trigger(DS3_TRIGGER);
+ cpu_triggertime(ATTOTIME_IN_USEC(5), DS3_TRIGGER);
+
+ return ds3_gdata;
+}
+
+
+WRITE16_HANDLER( hd68k_ds3_gdata_w )
+{
+ logerror("%06X:hd68k_ds3_gdata_w(%04X)\n", activecpu_get_previouspc(), ds3_gdata);
+
+ COMBINE_DATA(&ds3_g68data);
+ ds3_g68flag = 1;
+ ds3_gcmd = offset & 1;
+ cpu_triggerint(hdcpu_adsp);
+ update_ds3_irq();
+}
+
+
+
+/*************************************
+ *
+ * DS III sound I/O
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_ds3_sirq_state_r )
+{
+ return 0x4000;
+}
+
+
+READ16_HANDLER( hd68k_ds3_sdata_r )
+{
+ return 0;
+}
+
+
+WRITE16_HANDLER( hd68k_ds3_sdata_w )
+{
+}
+
+
+/*************************************
+ *
+ * DS III internal I/O
+ *
+ *************************************/
+
+READ16_HANDLER( hdds3_special_r )
+{
+ int result;
+
+ switch (offset & 7)
+ {
+ case 0:
+ ds3_g68flag = 0;
+ update_ds3_irq();
+ return ds3_g68data;
+
+ case 1:
+ result = 0x0fff;
+ if (ds3_gcmd) result ^= 0x8000;
+ if (ds3_g68flag) result ^= 0x4000;
+ if (ds3_gflag) result ^= 0x2000;
+ return result;
+
+ case 6:
+ logerror("ADSP r @ %04x\n", ds3_sim_address);
+ if (ds3_sim_address < sim_memory_size)
+ return sim_memory[ds3_sim_address];
+ else
+ return 0xff;
+ }
+ return 0;
+}
+
+
+WRITE16_HANDLER( hdds3_special_w )
+{
+ /* IMPORTANT! these data values also write through to the underlying RAM */
+ hdadsp_data_memory[offset] = data;
+
+ switch (offset & 7)
+ {
+ case 0:
+ logerror("%04X:ADSP sets gdata to %04X\n", activecpu_get_previouspc(), data);
+ ds3_gdata = data;
+ ds3_gflag = 1;
+ update_ds3_irq();
+
+ /* once we've written data, trigger the main CPU to wake up again */
+ cpu_trigger(DS3_TRIGGER);
+ break;
+
+ case 1:
+ logerror("%04X:ADSP sets interrupt = %d\n", activecpu_get_previouspc(), (data >> 1) & 1);
+ adsp_irq_state = (data >> 1) & 1;
+ hd68k_update_interrupts();
+ break;
+
+ case 2:
+ ds3_send = (data >> 0) & 1;
+ break;
+
+ case 3:
+ ds3_gfirqs = (data >> 1) & 1;
+ ds3_g68irqs = !ds3_gfirqs;
+ update_ds3_irq();
+ break;
+
+ case 4:
+ ds3_sim_address = (ds3_sim_address & 0xffff0000) | (data & 0xffff);
+ break;
+
+ case 5:
+ ds3_sim_address = (ds3_sim_address & 0xffff) | ((data << 16) & 0x00070000);
+ break;
+ }
+}
+
+
+READ16_HANDLER( hdds3_control_r )
+{
+ logerror("adsp2101 control r @ %04X\n", 0x3fe0 + offset);
+ return 0;
+}
+
+
+WRITE16_HANDLER( hdds3_control_w )
+{
+ if (offset != 0x1e && offset != 0x1f)
+ logerror("adsp2101 control w @ %04X = %04X\n", 0x3fe0 + offset, data);
+}
+
+
+
+/*************************************
+ *
+ * DS III program memory handlers
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_ds3_program_r )
+{
+ UINT32 *base = &hdadsp_pgm_memory[offset & 0x1fff];
+ UINT32 word = *base;
+ return (!(offset & 0x2000)) ? (word >> 8) : (word & 0xff);
+}
+
+
+WRITE16_HANDLER( hd68k_ds3_program_w )
+{
+ UINT32 *base = &hdadsp_pgm_memory[offset & 0x1fff];
+ UINT32 oldword = *base;
+ UINT16 temp;
+
+ if (!(offset & 0x2000))
+ {
+ temp = oldword >> 8;
+ COMBINE_DATA(&temp);
+ oldword = (oldword & 0x000000ff) | (temp << 8);
+ }
+ else
+ {
+ temp = oldword & 0xff;
+ COMBINE_DATA(&temp);
+ oldword = (oldword & 0xffffff00) | (temp & 0xff);
+ }
+ *base = oldword;
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * DSK BOARD
+#endif
+
+/*************************************
+ *
+ * DSK board IRQ generation
+ *
+ *************************************/
+
+void hddsk_update_pif(UINT32 pins)
+{
+ atarigen_sound_int_state = ((pins & DSP32_OUTPUT_PIF) != 0);
+ hd68k_update_interrupts();
+}
+
+
+
+/*************************************
+ *
+ * DSK board control handlers
+ *
+ *************************************/
+
+WRITE16_HANDLER( hd68k_dsk_control_w )
+{
+ int val = (offset >> 3) & 1;
+ switch (offset & 7)
+ {
+ case 0: /* DSPRESTN */
+ cpunum_set_input_line(hdcpu_dsp32, INPUT_LINE_RESET, val ? CLEAR_LINE : ASSERT_LINE);
+ break;
+
+ case 1: /* DSPZN */
+ cpunum_set_input_line(hdcpu_dsp32, INPUT_LINE_HALT, val ? CLEAR_LINE : ASSERT_LINE);
+ break;
+
+ case 2: /* ZW1 */
+ break;
+
+ case 3: /* ZW2 */
+ break;
+
+ case 4: /* ASIC65 reset */
+ asic65_reset(!val);
+ break;
+
+ case 7: /* LED */
+ break;
+
+ default:
+ logerror("hd68k_dsk_control_w(%d) = %d\n", offset & 7, val);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * DSK board RAM/ZRAM/ROM handlers
+ *
+ *************************************/
+
+READ16_HANDLER( hd68k_dsk_ram_r )
+{
+ return hddsk_ram[offset];
+}
+
+
+WRITE16_HANDLER( hd68k_dsk_ram_w )
+{
+ COMBINE_DATA(&hddsk_ram[offset]);
+}
+
+
+READ16_HANDLER( hd68k_dsk_zram_r )
+{
+ return hddsk_zram[offset];
+}
+
+
+WRITE16_HANDLER( hd68k_dsk_zram_w )
+{
+ COMBINE_DATA(&hddsk_zram[offset]);
+}
+
+
+READ16_HANDLER( hd68k_dsk_small_rom_r )
+{
+ return hddsk_rom[offset & 0x1ffff];
+}
+
+
+READ16_HANDLER( hd68k_dsk_rom_r )
+{
+ return hddsk_rom[offset];
+}
+
+
+
+/*************************************
+ *
+ * DSK board DSP32C I/O handlers
+ *
+ *************************************/
+
+WRITE16_HANDLER( hd68k_dsk_dsp32_w )
+{
+ hddsk_pio_access = 1;
+ dsp32c_pio_w(hdcpu_dsp32, offset, data);
+ hddsk_pio_access = 0;
+}
+
+
+READ16_HANDLER( hd68k_dsk_dsp32_r )
+{
+ UINT16 result;
+ hddsk_pio_access = 1;
+ result = dsp32c_pio_r(hdcpu_dsp32, offset);
+ hddsk_pio_access = 0;
+ return result;
+}
+
+
+/*************************************
+ *
+ * DSP32C synchronization
+ *
+ *************************************/
+
+static TIMER_CALLBACK( rddsp32_sync_cb )
+{
+ *dataptr[param] = dataval[param];
+}
+
+
+WRITE32_HANDLER( rddsp32_sync0_w )
+{
+ if (hddsk_pio_access)
+ {
+ UINT32 *dptr = &rddsp32_sync[0][offset];
+ UINT32 newdata = *dptr;
+ COMBINE_DATA(&newdata);
+ dataptr[next_msp_sync % MAX_MSP_SYNC] = dptr;
+ dataval[next_msp_sync % MAX_MSP_SYNC] = newdata;
+ timer_call_after_resynch(next_msp_sync++ % MAX_MSP_SYNC, rddsp32_sync_cb);
+ }
+ else
+ COMBINE_DATA(&rddsp32_sync[0][offset]);
+}
+
+
+WRITE32_HANDLER( rddsp32_sync1_w )
+{
+ if (hddsk_pio_access)
+ {
+ UINT32 *dptr = &rddsp32_sync[1][offset];
+ UINT32 newdata = *dptr;
+ COMBINE_DATA(&newdata);
+ dataptr[next_msp_sync % MAX_MSP_SYNC] = dptr;
+ dataval[next_msp_sync % MAX_MSP_SYNC] = newdata;
+ timer_call_after_resynch(next_msp_sync++ % MAX_MSP_SYNC, rddsp32_sync_cb);
+ }
+ else
+ COMBINE_DATA(&rddsp32_sync[1][offset]);
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * DSPCOM BOARD
+#endif
+
+/*************************************
+ *
+ * DSPCOM control handlers
+ *
+ *************************************/
+
+WRITE16_HANDLER( hddspcom_control_w )
+{
+ int val = (offset >> 3) & 1;
+ switch (offset & 7)
+ {
+ case 2: /* ASIC65 reset */
+ asic65_reset(!val);
+ break;
+
+ default:
+ logerror("hddspcom_control_w(%d) = %d\n", offset & 7, val);
+ break;
+ }
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * GAME-SPECIFIC PROTECTION
+#endif
+
+/*************************************
+ *
+ * Race Drivin' slapstic handling
+ *
+ *************************************/
+
+WRITE16_HANDLER( rd68k_slapstic_w )
+{
+ slapstic_tweak(offset & 0x3fff);
+}
+
+
+READ16_HANDLER( rd68k_slapstic_r )
+{
+ int bank = slapstic_tweak(offset & 0x3fff) * 0x4000;
+ return hd68k_slapstic_base[bank + (offset & 0x3fff)];
+}
+
+
+
+/*************************************
+ *
+ * Steel Talons SLOOP handling
+ *
+ *************************************/
+
+static int st68k_sloop_tweak(offs_t offset)
+{
+ static int last_offset;
+
+ if (last_offset == 0)
+ {
+ switch (offset)
+ {
+ case 0x78e8:
+ st68k_sloop_bank = 0;
+ break;
+ case 0x6ca4:
+ st68k_sloop_bank = 1;
+ break;
+ case 0x15ea:
+ st68k_sloop_bank = 2;
+ break;
+ case 0x6b28:
+ st68k_sloop_bank = 3;
+ break;
+ }
+ }
+ last_offset = offset;
+ return st68k_sloop_bank;
+}
+
+
+WRITE16_HANDLER( st68k_sloop_w )
+{
+ st68k_sloop_tweak(offset & 0x3fff);
+}
+
+
+READ16_HANDLER( st68k_sloop_r )
+{
+ int bank = st68k_sloop_tweak(offset) * 0x4000;
+ return hd68k_slapstic_base[bank + (offset & 0x3fff)];
+}
+
+
+READ16_HANDLER( st68k_sloop_alt_r )
+{
+ if (st68k_last_alt_sloop_offset == 0x00fe)
+ {
+ switch (offset*2)
+ {
+ case 0x22c:
+ st68k_sloop_bank = 0;
+ break;
+ case 0x1e2:
+ st68k_sloop_bank = 1;
+ break;
+ case 0x1fa:
+ st68k_sloop_bank = 2;
+ break;
+ case 0x206:
+ st68k_sloop_bank = 3;
+ break;
+ }
+ }
+ st68k_last_alt_sloop_offset = offset*2;
+ return st68k_sloop_alt_base[offset];
+}
+
+
+static int st68k_protosloop_tweak(offs_t offset)
+{
+ static int last_offset;
+
+ if (last_offset == 0)
+ {
+ switch (offset)
+ {
+ case 0x0001:
+ st68k_sloop_bank = 0;
+ break;
+ case 0x0002:
+ st68k_sloop_bank = 1;
+ break;
+ case 0x0003:
+ st68k_sloop_bank = 2;
+ break;
+ case 0x0004:
+ st68k_sloop_bank = 3;
+ break;
+ }
+ }
+ last_offset = offset;
+ return st68k_sloop_bank;
+}
+
+
+WRITE16_HANDLER( st68k_protosloop_w )
+{
+ st68k_protosloop_tweak(offset & 0x3fff);
+}
+
+
+READ16_HANDLER( st68k_protosloop_r )
+{
+ int bank = st68k_protosloop_tweak(offset) * 0x4000;
+ return hd68k_slapstic_base[bank + (offset & 0x3fff)];
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * GSP OPTIMIZATIONS
+#endif
+
+/*************************************
+ *
+ * GSP Optimizations - case 1
+ * Works for:
+ * Hard Drivin'
+ * STUN Runner
+ *
+ *************************************/
+
+READ16_HANDLER( hdgsp_speedup_r )
+{
+ int result = hdgsp_speedup_addr[0][offset];
+
+ /* if both this address and the other important address are not $ffff */
+ /* then we can spin until something gets written */
+ if (result != 0xffff && hdgsp_speedup_addr[1][0] != 0xffff &&
+ cpu_getactivecpu() == hdcpu_gsp && activecpu_get_pc() == hdgsp_speedup_pc)
+ {
+ gsp_speedup_count[0]++;
+ cpu_spinuntil_int();
+ }
+
+ return result;
+}
+
+
+WRITE16_HANDLER( hdgsp_speedup1_w )
+{
+ COMBINE_DATA(&hdgsp_speedup_addr[0][offset]);
+
+ /* if $ffff is written, send an "interrupt" trigger to break us out of the spin loop */
+ if (hdgsp_speedup_addr[0][offset] == 0xffff)
+ cpu_triggerint(hdcpu_gsp);
+}
+
+
+WRITE16_HANDLER( hdgsp_speedup2_w )
+{
+ COMBINE_DATA(&hdgsp_speedup_addr[1][offset]);
+
+ /* if $ffff is written, send an "interrupt" trigger to break us out of the spin loop */
+ if (hdgsp_speedup_addr[1][offset] == 0xffff)
+ cpu_triggerint(hdcpu_gsp);
+}
+
+
+
+/*************************************
+ *
+ * GSP Optimizations - case 2
+ * Works for:
+ * Race Drivin'
+ *
+ *************************************/
+
+READ16_HANDLER( rdgsp_speedup1_r )
+{
+ int result = hdgsp_speedup_addr[0][offset];
+
+ /* if this address is equal to $f000, spin until something gets written */
+ if (cpu_getactivecpu() == hdcpu_gsp && activecpu_get_pc() == hdgsp_speedup_pc &&
+ (result & 0xff) < activecpu_get_reg(TMS34010_A1))
+ {
+ gsp_speedup_count[0]++;
+ cpu_spinuntil_int();
+ }
+
+ return result;
+}
+
+
+WRITE16_HANDLER( rdgsp_speedup1_w )
+{
+ COMBINE_DATA(&hdgsp_speedup_addr[0][offset]);
+ if (cpu_getactivecpu() != hdcpu_gsp)
+ cpu_triggerint(hdcpu_gsp);
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * MSP OPTIMIZATIONS
+#endif
+
+/*************************************
+ *
+ * MSP Optimizations
+ *
+ *************************************/
+
+READ16_HANDLER( hdmsp_speedup_r )
+{
+ int data = hdmsp_speedup_addr[offset];
+
+ if (data == 0 && activecpu_get_pc() == hdmsp_speedup_pc && cpu_getactivecpu() == hdcpu_msp)
+ {
+ msp_speedup_count[0]++;
+ cpu_spinuntil_int();
+ }
+
+ return data;
+}
+
+
+WRITE16_HANDLER( hdmsp_speedup_w )
+{
+ COMBINE_DATA(&hdmsp_speedup_addr[offset]);
+ if (offset == 0 && hdmsp_speedup_addr[offset] != 0)
+ cpu_triggerint(hdcpu_msp);
+}
+
+
+READ16_HANDLER( stmsp_speedup_r )
+{
+ /* assumes: stmsp_sync[0] -> $80010, stmsp_sync[1] -> $99680, stmsp_sync[2] -> $99d30 */
+ if (stmsp_sync[0][0] == 0 && /* 80010 */
+ stmsp_sync[0][1] == 0 && /* 80020 */
+ stmsp_sync[0][2] == 0 && /* 80030 */
+ stmsp_sync[0][3] == 0 && /* 80040 */
+ stmsp_sync[0][4] == 0 && /* 80050 */
+ stmsp_sync[0][5] == 0 && /* 80060 */
+ stmsp_sync[0][6] == 0 && /* 80070 */
+ stmsp_sync[1][0] == 0 && /* 99680 */
+ stmsp_sync[2][0] == 0xffff && /* 99d30 */
+ stmsp_sync[2][1] == 0xffff && /* 99d40 */
+ stmsp_sync[2][2] == 0 && /* 99d50 */
+ activecpu_get_pc() == 0x3c0)
+ {
+ msp_speedup_count[0]++;
+ cpu_spinuntil_int();
+ }
+ return stmsp_sync[0][1];
+}
+
+
+
+#if 0
+#pragma mark -
+#pragma mark * ADSP OPTIMIZATIONS
+#endif
+
+/*************************************
+ *
+ * ADSP Optimizations
+ *
+ *************************************/
+
+READ16_HANDLER( hdadsp_speedup_r )
+{
+ int data = hdadsp_data_memory[0x1fff];
+
+ if (data == 0xffff && activecpu_get_pc() <= 0x3b && cpu_getactivecpu() == hdcpu_adsp)
+ {
+ adsp_speedup_count[0]++;
+ cpu_spinuntil_int();
+ }
+
+ return data;
+}
+
+
+READ16_HANDLER( hdds3_speedup_r )
+{
+ int data = *hdds3_speedup_addr;
+
+ if (data != 0 && activecpu_get_pc() == hdds3_speedup_pc && cpu_getactivecpu() == hdcpu_adsp)
+ {
+ adsp_speedup_count[2]++;
+ cpu_spinuntil_int();
+ }
+
+ return data;
+}
diff --git a/src/mame/machine/irem_cpu.c b/src/mame/machine/irem_cpu.c
new file mode 100644
index 00000000000..af2414d1469
--- /dev/null
+++ b/src/mame/machine/irem_cpu.c
@@ -0,0 +1,807 @@
+/*****************************************************************************
+
+ Irem Custom V30 CPU:
+
+ It uses a simple opcode lookup encryption, the painful part is that it's
+ preprogrammed into the cpu and isn't a algorithmic based one.
+
+ Hasamu Nanao 08J27261A1 011 9102KK700
+ Gunforce Nanao 08J27261A1 011 9106KK701
+ Ken-Go Nanao 08J27261A1 011 9102KK701
+ Bomberman Nanao 08J27261A1 012 9123KK200
+ Atomic Punk Nanao 08J27291A1 012 9128KK440
+ Blade Master / Cross Blades! Nanao 08J27291A1 012 9123KK740
+ Quiz F-1 1,2 Finish Nanao 08J27291A4 014 9147KK700
+ Gunforce 2 Nanao 08J27291A4 014 9247KK700
+ Lethal Thunder Nanao 08J27291A4 014 9147KK700
+ Bomberman World / New Atomic Punk Nanao 08J27291A5 015 9219KK700
+ Undercover Cops Nanao 08J27291A5 015 9219KK700
+ Gun Hohki Nanao 08J27291A6 016 9217NK700
+ Skins Game Nanao 08J27291A7 017
+ Hook Nanao 08J27291A8 018 9237NK700
+
+ R-Type Leo Irem D8000021A1 019 9242NK700
+ Fire Barrel Irem D8000010A1 019 9243NK700
+ In The Hunt Irem D8000011A1 020
+ Risky Challenge/Gussun Oyoyo Irem D8000019A1 022 9331NK700
+ Match It II/Shisensho II Irem D8000020A1 023 9320NK700
+ World PK Soccer Irem D8000021A1
+ Ninja Baseball Batman Irem D8000021A1 024 9335NK700
+ Perfect Soldiers Irem D8000022A1
+ Dream Soccer '94 Irem D8000023A1 026
+
+ Please let me know if you can fill in any of the blanks.
+
+ Emulation by Bryan McPhail, mish@tendril.co.uk, thanks to Chris Hardy too!
+
+*****************************************************************************/
+
+#include "driver.h"
+#include "irem_cpu.h"
+
+int m90_game_kludge;
+
+// CAVEATS:
+// 0x80 and 0x82 pre- opcodes can easily be confused. They perform exactly the same
+// function when operating on memory, but when working with registers one affects
+// byte registers and the other word registers. Gunforce, Blade Master and
+// Lethal Thunder had this error.
+
+//double check 0x00 0x22 0x28 0x4a 0x34 in these tables
+
+#define xxxx 0x90/* Unknown */
+
+const UINT8 gunforce_decryption_table[256] = {
+ 0xff,xxxx,xxxx,0x2c,xxxx,xxxx,0x43,0x88, xxxx,0x13,0x0a,0xbd,0xba,0x60,0xea,xxxx, /* 00 */
+ xxxx,xxxx,0xf2,0x29,0xb3,0x22,xxxx,0x0c, 0xa9,0x5f,0x9d,0x07,xxxx,xxxx,0x0b,0xbb, /* 10 */
+ 0x8a,xxxx,xxxx,xxxx,0x3a,0x3c,0x5a,0x38, 0x99,xxxx,0xf8,0x89,xxxx,0x91,xxxx,0x55, /* 20 */
+ 0xac,0x40,0x73,xxxx,0x59,xxxx,0xfc,xxxx, 0x50,0xfa,xxxx,0x25,xxxx,0x34,0x47,0xb7, /* 30 */
+ xxxx,xxxx,xxxx,0x49,xxxx,0x0f,0x8b,0x05, 0xc3,0xa5,0xbf,0x83,0x86,0xc5,xxxx,xxxx, /* 40 */
+ 0x28,0x77,0x24,0xb4,xxxx,0x92,xxxx,0x3b, 0x5e,0xb6,0x80,0x0d,0x2e,0xab,0xe7,xxxx, /* 50 */
+ 0x48,xxxx,0xad,0xc0,xxxx,0x1b,0xc6,0xa3, 0x04,xxxx,xxxx,xxxx,0x16,0xb0,0x7d,0x98, /* 60 */
+ 0x87,0x46,0x8c,xxxx,xxxx,0xfe,xxxx,0xcf, xxxx,0x68,0x84,xxxx,0xd2,xxxx,0x18,0x51, /* 70 */
+ 0x76,0xa4,0x36,0x52,0xfb,xxxx,0xb9,xxxx, xxxx,0xb1,0x1c,0x21,0xe6,0xb5,0x17,0x27, /* 80 */
+ 0x3d,0x45,0xbe,0xae,xxxx,0x4a,0x0e,0xe5, xxxx,0x58,0x1f,0x61,0xf3,0x02,xxxx,0xe8, /* 90 */
+ xxxx,xxxx,xxxx,0xf7,0x56,0x96,xxxx,0xbc, 0x4f,xxxx,xxxx,0x79,0xd0,xxxx,0x2a,0x12, /* A0 */
+ 0x4e,0xb8,xxxx,0x41,xxxx,0x90,0xd3,xxxx, 0x2d,0x33,0xf6,xxxx,xxxx,0x14,xxxx,0x32, /* B0 */
+ 0x5d,0xa8,0x53,0x26,0x2b,0x20,0x81,0x75, 0x7f,0x3e,xxxx,xxxx,0x00,0x93,xxxx,0xb2, /* C0 */
+ 0x57,xxxx,0xa0,xxxx,0x39,xxxx,xxxx,0x72, xxxx,0x01,0x42,0x74,0x9c,0x1e,xxxx,0x5b, /* D0 */
+ xxxx,0xf9,xxxx,0x2f,0x85,xxxx,0xeb,0xa2, xxxx,0xe2,0x11,xxxx,0x4b,0x7e,xxxx,0x78, /* E0 */
+ xxxx,xxxx,0x09,0xa1,0x03,xxxx,0x23,0xc1, 0x8e,0xe9,0xd1,0x7c,xxxx,xxxx,0xc7,0x06, /* F0 */
+};
+// 0x13 (0x29) guess
+// 0x18 (0xa9) guess
+// 0x50 (0x28) guess
+// 0x63 (0xc0) guess
+// 0x7e (0x18) opcode is right but arguments could be swapped
+// 0xcc (0x00) guess
+// 0xea (0x11) guess
+// 0x51 (0x77) guess (kengo)
+// 0x96 (0x0e) complete guess (kengo), maybe wrong but I don't see what it could be
+
+
+//double check 22 (boot bomb at 2a000)
+//47a7 (46e0 in boot) - hmm
+
+// 0x00 is NOT 0x20 (no context in bomberman)
+
+const UINT8 bomberman_decryption_table[256] = {
+ xxxx,xxxx,0x79,xxxx,0x9d,0x48,xxxx,xxxx, xxxx,xxxx,0x2e,xxxx,xxxx,0xa5,0x72,xxxx, /* 00 */
+ 0x46,0x5b,0xb1,0x3a,0xc3,xxxx,0x35,xxxx, xxxx,0x23,xxxx,0x99,xxxx,0x05,xxxx,0x3c, /* 10 */
+ 0x3b,0x76,0x11,xxxx,xxxx,0x4b,xxxx,0x92, xxxx,0x32,0x5d,xxxx,0xf7,0x5a,0x9c,xxxx, /* 20 */
+ 0x26,0x40,0x89,xxxx,xxxx,xxxx,xxxx,0x57, xxxx,xxxx,xxxx,xxxx,xxxx,0xba,0x53,0xbb, /* 30 */
+ 0x42,0x59,0x2f,xxxx,0x77,xxxx,xxxx,0x4f, 0xbf, 0x4a/*0x41*/, 0xcb,0x86,0x62,0x7d,xxxx,0xb8, /* 40 */
+ xxxx,0x34,xxxx,0x5f,xxxx,0x7f,0xf8,0x80, 0xa0,0x84,0x12,0x52,xxxx,xxxx,xxxx,0x47, /* 50 */
+ xxxx,0x2b,0x88,0xf9,xxxx,0xa3,0x83,xxxx, 0x75,0x87,xxxx,0xab,0xeb,xxxx,0xfe,xxxx, /* 60 */
+ xxxx,0xaf,0xd0,0x2c,0xd1,0xe6,0x90,0x43, 0xa2,0xe7,0x85,0xe2,0x49,0x22,0x29,xxxx, /* 70 */
+ 0x7c,xxxx,xxxx,0x9a,xxxx,xxxx,0xb9,xxxx, 0x14,0xcf,0x33,0x02,xxxx,xxxx,xxxx,0x73, /* 80 */
+ xxxx,0xc5,xxxx,xxxx,xxxx,0xf3,0xf6,0x24, xxxx,0x56,0xd3,xxxx,0x09,0x01,xxxx,xxxx, /* 90 */
+ 0x03,0x2d,0x1b,xxxx,0xf5,0xbe,xxxx,xxxx, 0xfb,0x8e,0x21,0x8d,0x0b,xxxx,xxxx,0xb2, /* A0 */
+ 0xfc,0xfa,0xc6,xxxx,0xe8,0xd2,xxxx,0x08, 0x0a,0xa8,0x78,0xff,xxxx,0xb5,xxxx,xxxx, /* B0 */
+ 0xc7,0x06,0x18,xxxx,xxxx,0x1e,0x7e,0xb0, 0x0e,0x0f,xxxx,xxxx,0x0c,0xaa,0x55,xxxx, /* C0 */
+ xxxx,0x74,0x3d,xxxx,xxxx,0x38,0x27,0x50, xxxx,0xb6,0x5e,0x8b,0x07,0xe5,0x39,0xea, /* D0 */
+ 0xbd,xxxx,0x81,0xb7,xxxx,0x8a,0x0d,xxxx, 0x58,0xa1,0xa9,0x36,xxxx,0xc4,xxxx,0x8f, /* E0 */
+ 0x8c,0x1f,0x51,0x04,0xf2,xxxx,0xb3,0xb4, 0xe9,0x2a,xxxx,xxxx,xxxx,0x25,xxxx,0xbc, /* F0 */
+};
+
+
+const UINT8 lethalth_decryption_table[256] = {
+ 0x7f,0x26,0x5d,xxxx,0xba,xxxx,0x1e,0x5e, 0xb8,xxxx,0xbc,0xe8,0x01,xxxx,0x4a,0x25, /* 00 */
+ xxxx,0xbd,xxxx,0x22,0x10,xxxx,0x02,0x57, 0x70,xxxx,0x7c,xxxx,0xe7,0x52,xxxx,0xa9, /* 10 */
+// ^^^^ ^^^^
+ xxxx,xxxx,0xc6,0x06,0xa0,0xfe,0xcf,0x8e, 0x43,0x8f,0x2d,xxxx,0xd4,0x85,0x75,0xa2, /* 20 */
+// ^^^^
+ 0x3d,xxxx,xxxx,0x38,0x7c,0x89,0xd1,0x80, 0x3b,0x72,0x07,xxxx,0x42,0x37,0x0a,0x18, /* 30 */
+// ^^^^
+ 0x88,0xb4,0x98,0x8b,0xb9,0x9c,0xad,0x0e, 0x2b,xxxx,0xbf,xxxx,0x55,xxxx,0x56,0xb0, /* 40 */
+// ^^^^
+ 0x93,0x91,xxxx,0xeb,xxxx,0x50,0x41,0x29, 0x47,xxxx,xxxx,0x60,xxxx,0xab,xxxx,xxxx, /* 50 */
+ 0xc3,0xe2,0xd0,0xb2,0x11,0x79,xxxx,0x08, xxxx,0xfb,xxxx,0x2c,0x23,xxxx,0x28,0x0d, /* 60 */
+ xxxx,xxxx,xxxx,0x83,0x3c,xxxx,0x1b,0x34, 0x5b,xxxx,0x40,xxxx,xxxx,0x04,0xfc,0x09, /* 70 */
+// ^^^^
+ 0xb1,0xf3,0x8a,xxxx,xxxx,0x87,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0xbe,0x84,0x1f,0xe6, /* 80 */
+ 0xff,xxxx,0x12,xxxx,0xb5,0x36,xxxx,0xb3, xxxx,xxxx,xxxx,0xd2,0x4e,xxxx,xxxx,xxxx, /* 90 */
+ 0xa5,xxxx,xxxx,0xc7,xxxx,0x27,0x0b,xxxx, 0x20,xxxx,xxxx,xxxx,xxxx,xxxx,0x61,0x7f, /* A0 */
+ xxxx,xxxx,0x86,0x0f,xxxx,0xb7,xxxx,0x4f, xxxx,xxxx,0xc0,0xfd,xxxx,0x39,xxxx,0x7d, /* B0 */
+ 0x05,0x3a,xxxx,0x48,0x92,0x7a,0x3e,0x03, xxxx,0xf8,xxxx,0x59,0xa8,0x5f,0xf9,0xbb, /* C0 */
+ 0x81,0xfa,0x9d,0xe9,0x2e,0xa1,0xc1,0x33, xxxx,0x78,xxxx,0x0c,xxxx,0x24,0xaa,0xac, /* D0 */
+ xxxx,0xb6,xxxx,0xea,xxxx,0x73,0xe5,0x58, 0x00,0xf7,xxxx,0x74,xxxx,0x7e,xxxx,0xa3, /* E0 */
+ xxxx,0x5a,0xf6,0x32,0x46,0x2a,xxxx,xxxx, 0x53,0x4b,0x90,xxxx,0x51,0x68,0x99,0x13, /* F0 */
+// ^^^^
+};
+// 0x2c (0xd4) complete guess
+// 0x2d (0x85) complete guess
+// 0xc4 (0x92) guess
+// 0xbb (0xfd) guess
+// 0x46 (0xad) guess
+// 0x6e (0x28) guess
+// 0x76 (0x1b) guess
+// 0x8d (0x84) guess
+// 0xa6 (0x0b) guess
+// 0xa8 (0x20) guess
+// 0xbd (0x39) guess
+// 0xc3 (0x48) guess
+// and our collection of conditional branches:
+// 0xbf (0x7d) >= (monitor test)
+// 0x34 (0x7c) < or <= (seems more like <) | these two are used toghether
+// 0xaf (0x7f) > or >= (seems more like >) |
+// 0xed (0x7e) <= or < (seems more like <=)
+// 0x00 (0x7f) > ? | these two are used toghether
+// 0x1a (0x7c) < ? | (rowscroll on pink screen on startup)
+// 0xc5 (0x7a) completely in the dark (game start after car seelction)
+
+
+const UINT8 dynablaster_decryption_table[256] = {
+ 0x1f,0x51,0x84,xxxx,0x3d,0x09,0x0d,xxxx, xxxx,0x57,xxxx,xxxx,xxxx,0x32,0x11,xxxx, /* 00 */
+ xxxx,0x9c,xxxx,xxxx,0x4b,xxxx,xxxx,0x03, xxxx,xxxx,xxxx,0x89,0xb0,xxxx,xxxx,xxxx, /* 10 */
+ xxxx,0xbb,0x18,0xbe,0x53,0x21,0x55,0x7c, xxxx,xxxx,0x47,0x58,0xf6,xxxx,xxxx,0xb2, /* 20 */
+ 0x06,xxxx,0x2b,xxxx,0x2f,0x0b,0xfc, 0x91 , xxxx,xxxx,0xfa,0x81,0x83,0x40,0x38,xxxx, /* 30 */
+ xxxx,xxxx,0x49,0x85,0xd1,0xf5,0x07,0xe2, 0x5e,0x1e,xxxx,0x04,xxxx,xxxx,xxxx,0xb1, /* 40 */
+ 0xc7,xxxx,0x96, 0xf2 /*0xaf*/, 0xb6,0xd2,0xc3,xxxx, 0x87,0xba,0xcb,0x88,xxxx,0xb9,0xd0,0xb5, /* 50 */
+ 0x9a,0x80,0xa2,0x72,xxxx,0xb4,xxxx,0xaa, 0x26,0x7d,0x52,0x33,0x2e,0xbc,0x08,0x79, /* 60 */
+ 0x48,xxxx,0x76,0x36,0x02,xxxx,0x5b,0x12, 0x8b,0xe7,xxxx,xxxx,xxxx,0xab,xxxx,0x4f, /* 70 */
+ xxxx,xxxx,0xa8,0xe5,0x39,0x0e,0xa9,xxxx, xxxx,0x14,xxxx,0xff, 0x7f/*0x75*/ ,xxxx,xxxx,0x27, /* 80 */
+ xxxx,0x01,xxxx,xxxx,0xe6,0x8a,0xd3,xxxx, xxxx,0x8e,0x56,0xa5,0x92,xxxx,xxxx,0xf9, /* 90 */
+ 0x22,xxxx,0x5f,xxxx,xxxx,0xa1,xxxx,0x74, 0xb8,xxxx,0x46,0x05,0xeb,0xcf,0xbf,0x5d, /* a0 */
+ 0x24,xxxx,0x9d,xxxx,xxxx,xxxx,xxxx,xxxx, 0x59,0x8d,0x3c,0xf8,0xc5,xxxx,0xf3,0x4e, /* b0 */
+ xxxx,xxxx,0x50,0xc6,0xe9,0xfe,0x0a,xxxx, 0x99,0x86,xxxx,xxxx,0xaf ,0x8c/*0x8e*/,0x42,0xf7, /* c0 */
+ xxxx,0x41,xxxx,0xa3,xxxx,0x3a,0x2a,0x43, xxxx,0xb3,0xe8,xxxx,0xc4,0x35,0x78,0x25, /* d0 */
+ 0x75,xxxx,0xb7,xxxx,0x23,xxxx, xxxx/*0xe2*/,0x8f, xxxx,xxxx,0x2c,xxxx,0x77,0x7e,xxxx,0x0f, /* e0 */
+ 0x0c,0xa0,0xbd,xxxx,xxxx,0x2d,0x29,0xea, xxxx,0x3b,0x73,xxxx,0xfb,0x20,xxxx,0x5a /* f0 */
+};
+//double check 0x00/0xa0 AND.
+//double check 0x8c (0x7d jg)
+//double check 0xfd (0x20 AND) - 9d2 in code
+//double check 0xd1 (0x41 INC cw) used in uccops and dynablaster (LOOKS GOOD)
+
+//AND fd (0x20)
+//0x37 (91) guess from dynablaster title screen
+
+// BM - 0x61 NOT 82, but instead 0x80 verified in both Atomic Punk and UCCops
+// 0x22 is 0x18 (SBB) verified from Gunforce
+// 0x5b seems confirmed (previous commented out as 0x36)
+// NS I expected 0x32 to be 0x1b (SBB) like in gunforce, but startup tests fail in bbmanw.
+// therefore it seems to be 0x2b (SUB)
+// NS010718 0xa0 was 0x00 (ADDB), verified to be 0x22 (ANDB)
+
+
+const UINT8 mysticri_decryption_table[256] = {
+ xxxx,0x57,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0xbf,0x43,xxxx,xxxx,xxxx,xxxx,0xfc,xxxx, /* 00 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,0x52,0xa3,0x26, xxxx,0xc7,xxxx,0x0f,xxxx,0x0c,xxxx,xxxx, /* 10 */
+ xxxx,xxxx,0xff,xxxx,xxxx,0x02,xxxx,xxxx, 0x2e,xxxx,0x5f,xxxx,xxxx,xxxx,0x73,0x50, /* 20 */
+ 0xb2,0x3a,xxxx,xxxx,0xbb,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
+ xxxx,xxxx,0x8e,0x3c,0x42,xxxx,xxxx,0xb9, xxxx,xxxx,0x2a,xxxx,0x47,0xa0,0x2b,0x03, /* 40 */
+ 0xb5,0x1f,xxxx,0xaa,xxxx,0xfb,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0x38,xxxx,xxxx,xxxx, /* 50 */
+ 0x2c,xxxx,xxxx,0xc6,xxxx,xxxx,0xb1,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xa2,xxxx, /* 60 */
+ 0xe9,0xe8,xxxx,xxxx,0x86,xxxx,0x8b,xxxx, xxxx,xxxx,xxxx,xxxx,0x5b,0x72,xxxx,xxxx, /* 70 */
+ xxxx,xxxx,0x5d,0x0a,xxxx,xxxx,0x89,xxxx, 0xb0,0x88,xxxx,xxxx,xxxx,0x87,0x75,0xbd, /* 80 */
+ xxxx,0x51,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,0x5a,0x58,xxxx,xxxx,0x56, /* 90 */
+ xxxx,0x8a,xxxx,0x55,xxxx,xxxx,xxxx,0xb4, 0x08,xxxx,0xf6,xxxx,xxxx,0x9d,xxxx,0xbc, /* A0 */
+ 0x0b,xxxx,xxxx,0x5e,xxxx,xxxx,xxxx,0x22, 0x36,xxxx,0x1e,xxxx,0xb6,0xba,0x23,xxxx, /* B0 */
+ 0x20,xxxx,xxxx,xxxx,0x59,0x53,xxxx,0x04, 0x81,xxxx,xxxx,0xf3,xxxx,xxxx,0x3b,0x06, /* C0 */
+ xxxx,0x79,0x83,0x9c,xxxx,0x18,0x80,xxxx, 0xc3,xxxx,xxxx,xxxx,0x32,xxxx,0xcf,xxxx, /* D0 */
+ 0xeb,xxxx,xxxx,0x33,xxxx,0xfa,xxxx,xxxx, 0xd2,xxxx,0x24,xxxx,0x74,0x41,0xb8,xxxx, /* E0 */
+ xxxx,xxxx,0xd0,0x07,xxxx,xxxx,xxxx,xxxx, xxxx,0x46,xxxx,0xea,0xfe,0x78,xxxx,xxxx, /* F0 */
+};
+// 0xd5 (0x18) opcode is right but arguments could be swapped
+// 0x4e (0x2b) not sure, could be 0x1b
+
+
+const UINT8 majtitl2_decryption_table[256] = {
+ 0x87,xxxx,0x78,0xaa,xxxx,xxxx,xxxx,0x2c, 0x32,0x0a,0x0f,xxxx,0x5e,xxxx,0xc6,0x8a, /* 00 */
+ 0x33,xxxx,xxxx,xxxx,xxxx,0xea,xxxx,0x72, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x24,0x55, /* 10 */
+ xxxx,xxxx,xxxx,0x89,0xfb,xxxx,0x59,0x02, xxxx,xxxx,0x5d,xxxx,xxxx,xxxx,0x36,xxxx, /* 20 */
+ xxxx,0x06,0x79,xxxx,xxxx,0x1e,0x07,xxxx, xxxx,xxxx,0x83,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
+ 0x9d,xxxx,xxxx,0x74,xxxx,xxxx,xxxx,0x0c, 0x58,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 40 */
+ 0x3c,xxxx,0x03,xxxx,xxxx,0xfa,0x43,xxxx, 0xbf,xxxx,xxxx,0x75,xxxx,0x88,xxxx,0x80, /* 50 */
+ xxxx,0xa3,xxxx,0xfe,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0x3a,xxxx,xxxx,xxxx, /* 60 */
+ 0x2b,xxxx,xxxx,xxxx,xxxx,0xe9,0x5f,xxxx, 0x46,xxxx,0x41,xxxx,0x18,0xb8,xxxx,xxxx, /* 70 */
+ 0xb4,0x5a,0xb1,xxxx,xxxx,0x50,0xe8,0x20, xxxx,0xb2,xxxx,xxxx,xxxx,xxxx,xxxx,0x51, /* 80 */
+ xxxx,xxxx,xxxx,0x56,xxxx,xxxx,xxxx,xxxx, xxxx,0xcf,xxxx,xxxx,xxxx,0xc3,xxxx,xxxx, /* 90 */
+ xxxx,xxxx,xxxx,xxxx,0x0b,xxxx,xxxx,0xb5, 0x57,xxxx,xxxx,0xc7,0x3b,xxxx,xxxx,xxxx, /* A0 */
+ xxxx,xxxx,xxxx,xxxx,0xb6,xxxx,0xeb,xxxx, 0x38,xxxx,0xa0,0x08,xxxx,0x86,0xb0,xxxx, /* B0 */
+ 0x42,0x1f,0x73,xxxx,0xf6,xxxx,xxxx,xxxx, 0x53,xxxx,0x52,xxxx,0x04,0xbd,xxxx,xxxx, /* C0 */
+ 0x26,0xff,0x2e,xxxx,0x81,xxxx,0x47,xxxx, xxxx,xxxx,xxxx,0xd0,0x22,xxxx,xxxx,0xb9, /* D0 */
+ 0x23,xxxx,0xf3,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0xd2,0x8b,0xba,xxxx,xxxx,xxxx,0x5b, /* E0 */
+ xxxx,xxxx,0x9c,xxxx,xxxx,xxxx,xxxx,0xfc, 0xbc,0xa2,0x2a,xxxx,xxxx,0x8e,0xbb,xxxx, /* F0 */
+};
+// 0x7c (0x18) opcode is right but arguments could be swapped
+// 0x70 (0x2b) not sure, could be 0x1b
+
+
+const UINT8 hook_decryption_table[256] = {
+ 0xb6,0x20,0x22,xxxx,0x0f,0x57,0x59,0xc6, 0xeb,xxxx,0xb0,0xbb,0x3b,xxxx,xxxx,xxxx, /* 00 */
+ 0x36,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0xfe,xxxx,xxxx,xxxx,xxxx,xxxx,0xa0, /* 10 */
+ 0x2e,xxxx,0x0b,xxxx,xxxx,0x58,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,0x80,xxxx,xxxx, /* 20 */
+ 0x33,xxxx,xxxx,0xbf,0x55,xxxx,xxxx,xxxx, 0x53,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
+ 0x47,0x74,xxxx,0xb1,0xb4,xxxx,xxxx,0x88, xxxx,xxxx,0x38,0xcf,xxxx,0x8e,xxxx,xxxx, /* 40 */
+ xxxx,0xc7,xxxx,0x32,xxxx,0x52,0x3c,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,0x72, /* 50 */
+ xxxx,0x73,xxxx,0x5a,xxxx,0x43,xxxx,xxxx, xxxx,xxxx,0x41,0xe9,0xbd,xxxx,0xb2,0xd2, /* 60 */
+ xxxx,0xaa,0xa2,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,0x26,xxxx,xxxx,0x8a,xxxx, /* 70 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x18, xxxx,0x9d,xxxx,xxxx,xxxx,0x5d,xxxx,0x46, /* 80 */
+ xxxx,xxxx,xxxx,0xf6,0xc3,0xa3,0x1e,0x07, 0x5f,0x81,xxxx,0x0c,xxxx,0xb8,xxxx,0x75, /* 90 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x79, /* A0 */
+ xxxx,0x5e,xxxx,xxxx,0x06,xxxx,0xff,xxxx, 0x5b,0x24,xxxx,0x2b,xxxx,xxxx,xxxx,0x02, /* B0 */
+ 0x86,xxxx,xxxx,0xfb,xxxx,xxxx,0x50,0xfc, 0x08,xxxx,xxxx,xxxx,0x03,xxxx,0xb9,xxxx, /* C0 */
+ xxxx,0xbc,0xe8,0x1f,0xfa,0x42,xxxx,xxxx, 0x89,xxxx,0x23,0x87,xxxx,0x2a,xxxx,xxxx, /* D0 */
+ 0x8b,xxxx,0xf3,0xea,0x04,0x2c,0xb5,xxxx, 0x0a,xxxx,0x51,xxxx,xxxx,0x3a,xxxx,0x9c, /* E0 */
+ xxxx,xxxx,0x78,xxxx,0xba,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,0xd0,0x56,xxxx,xxxx, /* F0 */
+};
+// 0x87 (0x18) opcode is right but arguments could be swapped
+// 0xbb (0x2b) not sure, could be 0x1b
+
+
+const UINT8 rtypeleo_decryption_table[256] = {
+ 0x5d,xxxx,0xc6,xxxx,xxxx,xxxx,0x2a,0x3a, xxxx,xxxx,xxxx,0x86,xxxx,0x22,xxxx,0xf3, /* 00 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,0x38,0x01,0x42, 0x04,xxxx,xxxx,0x1f,xxxx,xxxx,xxxx,0x58, /* 10 */
+// ^^^^
+ 0x57,0x2e,xxxx,xxxx,0x53,xxxx,0xb9,xxxx, xxxx,xxxx,xxxx,xxxx,0x20,0x55,xxxx,0x3d, /* 20 */
+// ^^^^
+ 0xa0,xxxx,xxxx,0x0c,0x03,xxxx,0x83,xxxx, xxxx,xxxx,0x8a,xxxx,xxxx,0xaa,xxxx,xxxx, /* 30 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0x41,0x0a,0x26,0x8b,0x56,0x5e,xxxx, /* 40 */
+ xxxx,0x74,xxxx,xxxx,xxxx,xxxx,0x06,xxxx, xxxx,0x89,0x5b,0xc7,0x43,xxxx,xxxx,xxxx, /* 50 */
+ xxxx,0xb6,xxxx,0x3b,xxxx,xxxx,xxxx,xxxx, xxxx,0x36,0xea,0x80,xxxx,xxxx,xxxx,0x5f, /* 60 */
+ xxxx,0x0f,xxxx,xxxx,xxxx,0x46,xxxx,xxxx, 0x3c,0x8e,xxxx,0xa3,0x87,xxxx,xxxx,xxxx, /* 70 */
+ 0x2b,0xfb,0x47,0x0b,xxxx,0xfc,0x02,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x72,0x2c, /* 80 */
+ 0x33,xxxx,xxxx,xxxx,xxxx,xxxx,0x9d,0xbd, xxxx,0xb2,xxxx,0x78,0x75,0xb8,xxxx,xxxx, /* 90 */
+ xxxx,xxxx,xxxx,xxxx,0xcf,0x5a,0x88,xxxx, xxxx,xxxx,0xc3,xxxx,0xeb,0xfa,xxxx,0x32, /* A0 */
+ xxxx,xxxx,xxxx,0x52,0xb4,xxxx,xxxx,xxxx, xxxx,0xbc,xxxx,xxxx,xxxx,0xb1,0x59,0x50, /* B0 */
+ xxxx,xxxx,0xb5,xxxx,0x08,0xa2,0xbf,0xbb, 0x1e,0x9c,xxxx,0x73,xxxx,0xd0,xxxx,xxxx, /* C0 */
+ xxxx,xxxx,xxxx,xxxx,0x81,xxxx,0x79,xxxx, xxxx,0x24,0x23,xxxx,xxxx,0xb0,0x07,0xff, /* D0 */
+ xxxx,0xba,0xf6,0x51,xxxx,xxxx,xxxx,0xfe, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xe9,xxxx, /* E0 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xe8,0xd2, xxxx,0x18,xxxx,xxxx,xxxx,0xd1,xxxx,xxxx, /* F0 */
+// ^^^^
+};
+// 0xf9 (0x18) opcode is right but arguments could be swapped
+// 0x80 (0x2b) not sure, could be 0x1b
+// 0x16 (0x01) guess (wrong?)
+
+
+const UINT8 inthunt_decryption_table[256] = {
+ 0x1f,xxxx,0xbb,0x50,xxxx,0x58,0x42,0x57, xxxx,xxxx,0xe9,xxxx,xxxx,xxxx,xxxx,0x0b, /* 00 */
+ xxxx,xxxx,0x9d,0x9c,xxxx,xxxx,0x1e,xxxx, xxxx,0xb4,0x5b,xxxx,xxxx,xxxx,xxxx,xxxx, /* 10 */
+ xxxx,xxxx,0x78,0xc7,xxxx,xxxx,0x83,xxxx, xxxx,0x0c,0xb0,0x04,xxxx,xxxx,xxxx,xxxx, /* 20 */
+ xxxx,xxxx,xxxx,xxxx,0x3b,0xc3,0xb5,0x47, xxxx,xxxx,xxxx,xxxx,0x59,xxxx,xxxx,xxxx, /* 30 */
+ xxxx,xxxx,xxxx,0x38,xxxx,xxxx,xxxx,xxxx, 0x5f,0xa3,0xfa,xxxx,0xe8,0x36,0x75,xxxx, /* 40 */
+ 0x88,0x33,xxxx,xxxx,xxxx,xxxx,0x43,xxxx, xxxx,0x87,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */
+ xxxx,xxxx,xxxx,xxxx,0x8e,0xf3,0x56,xxxx, xxxx,xxxx,xxxx,0x26,0xff,xxxx,xxxx,xxxx, /* 60 */
+ xxxx,xxxx,xxxx,0x2a,xxxx,0x8a,xxxx,0x18, xxxx,xxxx,0x03,0x89,0x24,xxxx,xxxx,xxxx, /* 70 */
+ 0x0a,xxxx,0xeb,xxxx,0x86,xxxx,xxxx,xxxx, 0x79,0x3a,xxxx,xxxx,xxxx,xxxx,0xa0,xxxx, /* 80 */
+ 0xea,xxxx,xxxx,xxxx,xxxx,xxxx,0x2c,xxxx, 0xc6,xxxx,xxxx,0x46,xxxx,0xaa,0xb6,0x5e, /* 90 */
+ xxxx,xxxx,xxxx,xxxx,0x8b,xxxx,xxxx,xxxx, xxxx,xxxx,0xba,xxxx,0xb9,0x53,0xa2,xxxx, /* A0 */
+ xxxx,0x07,xxxx,xxxx,xxxx,0x3c,0x32,xxxx, 0x2b,xxxx,0xb8,xxxx,xxxx,xxxx,xxxx,xxxx, /* B0 */
+ 0xbd,xxxx,xxxx,xxxx,xxxx,0x81,xxxx,0xd0, 0x08,xxxx,0x55,0x06,0xcf,xxxx,xxxx,0xfc, /* C0 */
+ xxxx,xxxx,xxxx,0xb1,0xbf,xxxx,xxxx,0x51, 0x52,xxxx,0x5d,xxxx,0x5a,xxxx,0xb2,xxxx, /* D0 */
+ 0xfe,xxxx,xxxx,0x22,0x20,0x72,0xf6,0x80, 0x02,0x2e,xxxx,0x74,0x0f,xxxx,xxxx,xxxx, /* E0 */
+ xxxx,xxxx,xxxx,xxxx,0xbc,0x41,xxxx,0xfb, 0x73,xxxx,xxxx,xxxx,0x23,0xd2,xxxx,xxxx, /* F0 */
+};
+// 0x77 (0x18) opcode is right but arguments could be swapped
+// 0xb8 (0x2b) not sure, could be 0x1b
+
+
+const UINT8 gussun_decryption_table[256] = {
+ 0xcd,xxxx,xxxx,0x36,xxxx,0x52,0xb1,0x5b, 0x68,0xcd,xxxx,xxxx,xxxx,0xa8,xxxx,xxxx, /* 00 */
+// !!!! ^^^^ !!!! !!!!
+ xxxx,xxxx,0x75,0x24,0x01,0x83,0x32,0xe9, xxxx,0x78,xxxx,0x19,0x22,xxxx,0xac,xxxx, /* 10 */
+// !!!! ???? ^^^^ ???? ???? !!!! ^^^^
+ 0x5d,0xa5,0x10,0x51,0x0a,xxxx,0x19,xxxx ,0xf8,0x90,0x91,0x40,0x28,0x22,0x03,0x5f, /* 20 */
+// ???? !!!! ???? ^^^^ ???? ^^^^ gggg gggg ????
+ 0x26,xxxx,xxxx,0x8b,xxxx,0x02,xxxx,xxxx, 0x8e,0xab,xxxx,xxxx,0xbc,0xf1,0xb3,xxxx, /* 30 */
+//
+ xxxx,0x19,0xc6,xxxx,xxxx,0x3a,0x10,xxxx, xxxx,0x74,0x61,xxxx,0x33,xxxx,0x19,xxxx, /* 40 */
+// ???? ???? !!!! ????
+ xxxx,0x53,0xa0,0xc0,0xc3,0x41,0xfc,0xe7, xxxx,0x2c,0x7f,0x2b,xxxx,xxxx,0xba,0x2a, /* 50 */
+// !!!! ^^^^ ^^^^ gggg ???? !!!! !!!!
+ 0xb0,xxxx,0x28,0x7e,xxxx,xxxx,0xb5,0x07, 0xb9,xxxx,0x27,0x46,0xf9,xxxx,xxxx,xxxx, /* 60 */
+// ???? gggg !!!! ^^^^
+ xxxx,0xea,0x72,0x73,0xad,0xd1,0x3b,0x5e, 0xe5,0x57,xxxx,0x0d,xxxx,xxxx,xxxx,0x3c, /* 70 */
+// ^^^^
+ xxxx,0x86,xxxx,0xb7,0x30,0x25,0x2d,xxxx, 0x9a,0xeb,0x04,0x0b,0xa2,0xb8,0xf6,xxxx, /* 80 */
+// ???? ???? ^^^^ !!!! !!!!
+ xxxx,xxxx,0x9d,xxxx,0xbb,xxxx,xxxx,0xcb, 0xa9,0xcf,xxxx,0x60,0x43,0x56,xxxx,0x19, /* 90 */
+// ^^^^ ^^^^ !!!! ^^^^ !!!! ????
+ xxxx,0xa3,xxxx,xxxx,xxxx,xxxx,0xfa,0xb4, xxxx,0x81,0xe6,0x42,0x80,0x8c,0xd4,xxxx, /* a0 */
+// gggg ???? gggg !!!!
+ xxxx,0x11,0x11,0x11,0x77,0x3d,0x3e,xxxx, xxxx,xxxx,0x4b,xxxx,xxxx,xxxx,xxxx,xxxx, /* b0 */
+// ???? ???? ???? gggg ????
+ xxxx,0xff,0x47,xxxx,0x55,0x1e,xxxx,0x59, 0x93,xxxx,xxxx,xxxx,0x88,0xc1,0x11,0xb2, /* c0 */
+// ^^^^ ^^^^ ^^^^ ????
+ xxxx,0x2e,0x06,0xc7,0x05,xxxx,0x8a,0x5a, 0x58,0xbe,xxxx,xxxx,xxxx,0x1f,0x23,xxxx, /* d0 */
+// ^^^^ ????
+ 0xe8,xxxx,0x89,0xa1,0xd0,xxxx,0x19,0xe2, 0x38,0xfe,0x50,0x9c,xxxx,xxxx,xxxx,0x49, /* e0 */
+// ???? ^^^^ !!!!
+ 0xfb,xxxx,0xf3,xxxx,xxxx,0x0f,xxxx,xxxx, xxxx,0x70,0xf7,0xbd,0x39,0x7f,0xbf,xxxx, /* f0 */
+// !!!! ???? !!!! gggg
+};
+
+
+/*
+missing opcode:
+
+1**14 -> 09? (2097b - 20980 (01 09 11 31
++++19 -> 79? (2282f - routine from 2281f to 22871) (78, 79, 7a, 7b)
+0++1b -> 19? (1d8f9 - routine from 1d8c7 to 1d8fc) - three bytes (09,11,21,29,31 - 01,19)
+01+22 -> 00? (1deff - routine from 1dee8 to 1df26) no 08,18,20,30 - ok 00,10
+0++26 -> 29? (14ed_ , 198e_
+01*29 -> 48? (1df22 - routine from 1df1d to
+01+2d -> 1a? (1df1d - routine from 1dee8 to 1df26) (00,01,10,11,12,13,20,21,28,29,30,31 - 08,09,18,19
+---41 -> 19?
+///46 -> 10? (1461b
+---4e -> 19? (208ac -
+1//5a -> 76? (222fc - routine from 222ed to ) (7x j...) 70 76 78 7a 7c
+1//62 -> 28? (1cf86 1cfa3 - routine from 1cf61 to 1cff4) (water in level 1)
+1--83 -> b7? (194cd - routine from
+0**84 -> 18? (1d8f1 - routine from 1d8c7 to 1d8fc) - three bytes (00,08,10,18,20,28,30)
+---9f -> 19? (
+///ab -> 42?
+---b1 -> 19?
+---b2 -> 19? (20a8c - 20acd
+///b3 -> 19? (216b6 - 216cf
+///ba -> 4b? (1094d, 10b28 - routine from 10948 to 10b73) one byte (4b
+01+ce -> 11? (10236 - routine from 1017e to 10254) (01, 09, 11, 19, 21, 29, 31)
+///db -> (16992
+///f9 -> 71? (16598 - 165a1 - 18de7 - routine from 18dc4 to ) 70,71
+
+
+rz guess:
+2b -> 40 (1d4d2 1db81 1dba9 - routine from 1d4b2 to 1d4de) (ok 40,48,96) -> 40
+ (no 0e,16,17,27,2f,37,3f,41,42,44,45,4a,4b,4c,4d,4e,4f,54,5c,6c,6d,92,94,95,97)
+2c -> 28 (20333 - routine from 2032a to 20366)
+59 -> 2c (220cf - 2037f - routine from 2202f to ) 2bytes (2c,
+63 -> 7d (1df7f, 1df8c, 1df95,21f08 - routine from 1df1d to ) - two bytes j..
+a7 -> b4 (2029a - routine from 20290 to
+ad -> 8c (1d559, 1d8d4 - routine from 1d547 - ; routine from 1d8b8 to 1d8fc)
+b4 -> 77 (1d03a, 1d57a - routine from 1d4df ) 7f,7d,7b - 79 - "77"
+fd -> 7f (1d659 - routine from 1d63c to 1d65e) 77,7f
+
+missing V35+ core:
+00 -> 63 not supported (229e2 - routine from 229da to 229ec) (for now we use cd instruction + hack)
+0f 92 -> of 92 not supported (1011d before of STI instruction) (for now no effects)
+
+above - c8 (inc aw) guess from stos code
+0xc5 -> 1e (push ds) guess (pop ds soon after) right?
+0xa9 -> 81 (not 0x82 PRE) guess from 237df
+0xcd -> c1 total guess (wrong but 3 bytes)
+
+AS notes:
+0x1e is lodsb not lds,noted from 2344f
+0x16 is xor r8,r8 not xor r16,r16
+0xc8 not inc aw but xch bw,aw
+0xcd is 0xc1 not 0xbd(palette at startup)
+0x97 guess,but seems right(228c1),known to *not* be ret %Iw.
+0x00 wrong(for sure it needs a one byte operand due to push es called at one point...)
+0x19 guess (0x82 PRE)
+0xc2 guess,it could be dec iy...
+
+RZ notes
+0xef -> 49 (dec CW) (used in "Service Mode" / "CHARACTER menu")
+0x24 -> (0a, 12) probably 0a (OR) (used in "Service Mode" / "CHARACTER menu")
+0x5b -> 2b (used in "Service Mode" / "CHARACTER menu")
+0x21 -> a5 (used in "Service Mode" / "CHARACTER menu")
+
+checked against "hasamu" code: hasamu and gussun share code (i.e. you can compare gussun from 2002a and hasamu from 54a0)
+0x09 -> cd (22a17 - routine from 229ed to 22a1a) - two bytes
+0x13 -> 24 (interrupt routine)
+0x1c -> 22 (interrupt routine)
+0x34 -> 2f (20381 - routine from 2037b to 20391) - used to handle number of lives and game over
+0x4a -> 61 (interrupt routine)
+0x66 -> b5 (1daaf - routine from 1da61 to 1daca) - two bytes (colors effect)
+0x6a -> 27 (20368 - routine from 20368 to 2037a) - used to limit the max lives number
+0x73 -> 73 (1d4f7 - routine from 1d4df to 1d539) -> (no 70,71,72,74,75,76,77,78,79,7a,7b,7c,7d,7e,7f) - ok 73
+0x8c -> a2 (interrupt routine)
+0x8e -> f6 (interrupt routine)
+0x9b -> 60 (interrupt routine)
+0xf0 -> fb guess (interrupt)
+0xae -> d4 (20215 - ) used when you insert a coin to handle the "coin number" in decimal
+*/
+
+/*
+e0100 palette sub-routine:
+12485: 23 push es
+12486: 27 C2 mov es,dw
+12488: D7 C0 xor aw,aw
+1248A: D7 FF xor iy,iy
+1248C: 44 00 01 mov cw,$0100
+1248F: 81 5D repe stosw
+12491: 95 22 06 97 39 mov byte ss:[$3997],$FF
+12497: 3A pop es
+12498: 60 ret
+
+d1a86
+
+unk
+add bw,bw [d8]
+add ix,sp [e6]
+add iy,sp [e7]
+clc
+ret
+
+Unused: [2] 00 add %Eb,%Gb
+Unused: [2] 01 add %Ev,%Gv
+Unused: [2] 08 or %Eb,%Gb
+Unused: [2] 09 or %Ev,%Gv
+Unused: [2] 0a or %Gb,%Eb
+Unused: [2] 0c or al,%Ib
+Unused: [1] 0e push cs
+Unused: [2] 10 adc %Eb,%Gb
+Unused: [2] 11 adc %Ev,%Gv
+Unused: [2] 12 adc %Gb,%Eb
+Unused: [2] 13 adc %Gv,%Ev
+Unused: [2] 14 adc al,%Ib
+Unused: [3] 15 adc aw,%Iv
+Unused: [1] 16 push ss
+Unused: [1] 17 pop ss
+Unused: [2] 18 sbb %Eb,%Gb
+Unused: [2] 19 sbb %Ev,%Gv
+Unused: [2] 1a sbb %Gb,%Eb
+Unused: [2] 1b sbb %Gv,%Ev
+Unused: [2] 1c sbb al,%Ib
+Unused: [3] 1d sbb aw,%Iv
+Unused: [2] 20 and %Eb,%Gb
+Unused: [2] 22 and %Gb,%Eb
+Unused: [2] 24 and al,%Ib
+Unused: [1] 27 adj4a
+Unused: [2] 28 sub %Eb,%Gb
+Unused: [2] 29 sub %Ev,%Gv
+Unused: [2] 2a sub %Gb,%Eb
+Unused: [2] 2b sub %Gv,%Ev
+Unused: [2] 2c sub al,%Ib
+Unused: [1] 2f adj4s
+Unused: [2] 30 xor %Eb,%Gb
+Unused: [2] 31 xor %Ev,%Gv
+Unused: [2] 34 xor al,%Ib
+Unused: [3] 35 xor aw,%Iv
+Unused: [1] 37 adjba
+Unused: [1] 3f adjbs
+Unused: [1] 40 inc aw
+Unused: [1] 42 inc dw
+Unused: [1] 44 inc sp
+Unused: [1] 45 inc bp
+Unused: [1] 47 inc iy
+Unused: [1] 48 dec aw
+Unused: [1] 49 dec cw
+Unused: [1] 4a dec dw
+Unused: [1] 4b dec bw
+Unused: [1] 4c dec sp
+Unused: [1] 4d dec bp
+Unused: [1] 4e dec ix
+Unused: [1] 54 push sp
+Unused: [1] 5c pop sp
+Unused: [1] 60 pusha
+Unused: [1] 61 popa
+Unused: [0] 62 chkind %Gv,%Ma
+Unused: [0] 63 (null)
+Unused: [0] 64 repnc %p
+Unused: [0] 65 repc %p
+Unused: [0] 66 (null)
+Unused: [0] 67 (null)
+Unused: [0] 69 imul %Gw,%Ew,%Iw
+Unused: [0] 6a push %Ix
+Unused: [0] 6b imul %Gw,%Ew,%Ib
+Unused: [0] 6c insb
+Unused: [0] 6d insw
+Unused: [0] 6e outsb
+Unused: [0] 6f outsw
+Unused: [1] 71 jno %Jb
+Unused: [1] 76 jbe %Jb
+Unused: [1] 77 ja %Jb
+Unused: [1] 78 js %Jb
+Unused: [1] 79 jns %Jb
+Unused: [1] 7a jpe %Jb
+Unused: [1] 7b jpo %Jb
+Unused: [1] 7c jl %Jb
+Unused: [1] 7e jle %Jb
+Unused: [1] 7f jg %Jb
+DUPLICATE: 81 %g0 %Ew,%Iw
+Unused: [2] 84 test %Eb,%Gb
+Unused: [2] 85 test %Ew,%Gw
+Unused: [2] 87 xch %Ew,%Gw
+Unused: [0] 8c mov %Ew,%Sw
+Unused: [0] 8d ldea %Gw,%M
+Unused: [0] 8f pop %Ev
+Unused: [1] 92 xch dw,aw
+Unused: [1] 94 xch sp,aw
+Unused: [1] 95 xch bp,aw
+Unused: [1] 96 xch ix,aw
+Unused: [1] 97 xch iy,aw
+Unused: [0] 98 cvtbw
+Unused: [0] 99 cvtwl
+Unused: [0] 9b fwait
+Unused: [0] 9e sahf
+Unused: [0] 9f lahf
+Unused: [0] a0 mov al,%Oc
+Unused: [0] a2 mov %Oc,al
+Unused: [0] a5 %P movsw
+Unused: [0] a6 %P cmpsb
+Unused: [0] a7 %P cmpsw
+Unused: [0] a9 test aw,%Iv
+Unused: [0] aa %P stosb
+Unused: [0] ae %P scasb
+Unused: [0] af %P scasw
+Unused: [2] b4 mov ah,%Ib
+Unused: [2] b5 mov ch,%Ib
+Unused: [2] b6 mov dh,%Ib
+Unused: [2] b7 mov bh,%Ib
+Unused: [3] bd mov bp,%Iv
+Unused: [0] c2 ret %Iw
+Unused: [0] c4 les %Gv,%Mp
+Unused: [0] c5 lds %Gv,%Mp
+Unused: [0] c8 enter %Iw,%Ib
+Unused: [0] c9 leave
+Unused: [0] ca retf %Iw
+Unused: [0] cc int 03
+Unused: [0] cd int %Ib
+Unused: [0] ce into
+Unused: [0] d2 %g1 %Eb,cl
+Unused: [0] d3 %g1 %Ev,cl
+Unused: [0] d4 aam ; %Ib
+Unused: [0] d5 aad ; %Ib
+Unused: [0] d6 (null)
+Unused: [0] d7 trans
+Unused: [0] d8 %f0
+Unused: [0] d9 %f1
+Unused: [0] da %f2
+Unused: [0] db %f3
+Unused: [0] dc %f4
+Unused: [0] dd %f5
+Unused: [0] de %f6
+Unused: [0] df %f7
+Unused: [0] e0 loopne %Jb
+Unused: [0] e1 loope %Jb
+Unused: [0] e3 j%j cxz %Jb
+Unused: [0] e4 in al,%Ib
+Unused: [0] ec in al,dw
+Unused: [0] ed in aw,dw
+Unused: [0] ee out dw,al
+Unused: [0] ef out dx,aw
+Unused: [0] f0 lock %p
+DUPLICATE: f1 (null)
+Unused: [0] f2 repne %p
+Unused: [0] f4 hlt
+Unused: [0] f5 not1 CY(cmc)
+Unused: [0] f6 %g2
+Unused: [1] fb ei
+Unused: [1] fd std
+*/
+
+const UINT8 leagueman_decryption_table[256] = {
+ xxxx,xxxx,xxxx,0x55,0xbb,xxxx,0x23,0x79, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x38,xxxx, /* 00 */
+ 0x01,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0x3d,xxxx,xxxx,xxxx,0xba,xxxx,0x1e,xxxx, /* 10 */
+ 0x2c,0x46,xxxx,0xb5,xxxx,0x4b,xxxx,0xfe, xxxx,xxxx,0xfb,0x2e,xxxx,xxxx,0x36,0x04, /* 20 */
+ 0xcf,xxxx,0xf3,0x5a,0x8a,0x0c,0x9c,xxxx, xxxx,xxxx,0xb2,0x50,xxxx,xxxx,xxxx,0x5f, /* 30 */
+ xxxx,xxxx,0x24,xxxx,xxxx,0x41,0x2b,xxxx, 0xe9,xxxx,0x08,0x3b,xxxx,xxxx,xxxx,xxxx, /* 40 */
+ xxxx,0xd2,0x51,xxxx,xxxx,xxxx,0x22,xxxx, 0xeb,0x3a,0x5b,0xa2,0xb1,0x80,xxxx,xxxx, /* 50 */
+ xxxx,xxxx,xxxx,xxxx,0x59,0xb4,0x88,xxxx, xxxx,0xbf,0xd1,xxxx,0xb9,0x57,xxxx,xxxx, /* 60 */
+ 0x72,xxxx,0x73,xxxx,xxxx,xxxx,xxxx,0x0f, xxxx,xxxx,xxxx,xxxx,0x56,xxxx,xxxx,0xc6, /* 70 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,0x2a,0x8e,xxxx, 0x81,0xa3,0x58,xxxx,0xaa,0x78,0x89,xxxx, /* 80 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xbd,xxxx, xxxx,xxxx,0xff,xxxx,xxxx,xxxx,0x07,0x53, /* 90 */
+ 0xa0,xxxx,xxxx,0x5e,0xb0,xxxx,0x83,0xf6, xxxx,0x26,0x32,xxxx,xxxx,xxxx,0x74,0x0a, /* A0 */
+ 0x18,xxxx,xxxx,xxxx,0x75,0x03,xxxx,xxxx, 0xb6,0x02,xxxx,xxxx,0x43,xxxx,0xb8,xxxx, /* B0 */
+ 0xe8,xxxx,0xfc,xxxx,0x20,0xc3,xxxx,0x06, xxxx,0x1f,0x86,0x00,xxxx,xxxx,xxxx,0xd0, /* C0 */
+ 0x47,xxxx,0x87,xxxx,xxxx,0x9d,0x3c,0xc7, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* D0 */
+ xxxx,xxxx,xxxx,0x8b,xxxx,xxxx,0x33,xxxx, xxxx,xxxx,xxxx,xxxx,0xfa,0x42,xxxx,xxxx, /* E0 */
+ xxxx,xxxx,xxxx,0xea,xxxx,0x52,xxxx,0x5d, xxxx,xxxx,xxxx,xxxx,0xbc,xxxx,xxxx,xxxx, /* F0 */
+};
+// 0x25 (0x4b) guess
+// 0x10 (0x01) guess (wrong?)
+
+
+const UINT8 psoldier_decryption_table[256] = {
+ xxxx,xxxx,xxxx,0x8a,xxxx,0xaa,xxxx,xxxx, xxxx,0x20,0x23,0x55,xxxx,0xb5,0x0a,xxxx, /* 00 */
+ xxxx,0x46,xxxx,0xb6,xxxx,0x74,0x8b,xxxx, xxxx,0xba,0x01,xxxx,xxxx,0x5a,0x86,0xfb, /* 10 */
+ 0xb2,xxxx,0xb0,xxxx,0x42,0x06,0x1e,0x08, 0x22,0x9d,xxxx,xxxx,xxxx,xxxx,xxxx,0x73, /* 20 */
+ xxxx,xxxx,0x5f,xxxx,xxxx,0xd0,xxxx,0xff, xxxx,xxxx,0xbd,xxxx,0x03,xxxx,0xb9,xxxx, /* 30 */
+ xxxx,xxxx,xxxx,0x51,0x5e,0x24,xxxx,xxxx, xxxx,xxxx,xxxx,0x58,0x59,xxxx,xxxx,xxxx, /* 40 */
+ 0x52,xxxx,xxxx,xxxx,0xa0,xxxx,xxxx,0x02, 0xd2,xxxx,0x79,0x26,0x3a,0x0f,0xcf,0xb4, /* 50 */
+ 0xf3,xxxx,xxxx,0x50,xxxx,0x75,0xb1,xxxx, 0xd1,0x47,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 60 */
+ 0xc6,xxxx,xxxx,xxxx,xxxx,xxxx,0xbc,xxxx, xxxx,xxxx,xxxx,xxxx,0x53,0x41,xxxx,xxxx, /* 70 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x04,xxxx, xxxx,xxxx,xxxx,0x2c,xxxx,0xbf,xxxx,xxxx, /* 80 */
+ xxxx,xxxx,0xe8,xxxx,xxxx,0x78,xxxx,0xbb, xxxx,xxxx,0x1f,0x2b,0x87,xxxx,0x4b,0x56, /* 90 */
+ 0x36,0x33,xxxx,xxxx,xxxx,0x9c,0xc3,xxxx, xxxx,0x81,xxxx,0xe9,xxxx,0xfa,xxxx,xxxx, /* A0 */
+ xxxx,0x72,xxxx,0xa2,xxxx,xxxx,0xc7,xxxx, xxxx,0x92,xxxx,xxxx,0x88,xxxx,xxxx,xxxx, /* B0 */
+ 0x3b,xxxx,0x0c,xxxx,0x80,xxxx,xxxx,xxxx, xxxx,0x2e,xxxx,xxxx,xxxx,0x57,xxxx,0x8e, /* C0 */
+ 0x07,xxxx,0xa3,xxxx,xxxx,xxxx,0x3d,xxxx, 0xfe,xxxx,xxxx,0xfc,0xea,xxxx,0x38,xxxx, /* D0 */
+ 0x3c,0xf6,xxxx,xxxx,xxxx,0x18,xxxx,xxxx, 0xb8,xxxx,xxxx,xxxx,0x2a,0x5d,0x5b,xxxx, /* E0 */
+ xxxx,0x43,0x32,xxxx,xxxx,xxxx,0xeb,xxxx, xxxx,xxxx,xxxx,xxxx,0x83,0x89,xxxx,xxxx, /* F0 */
+};
+// 0x9e (0x4b) guess
+// 0x1a (0x01) guess (wrong?)
+
+
+const UINT8 dsoccr94_decryption_table[256] = {
+ xxxx,0xd1,xxxx,xxxx,xxxx,0x79,0x2e,xxxx, xxxx,xxxx,0x5a,0x0f,xxxx,xxxx,0x43,xxxx, /* 00 */
+ xxxx,xxxx,0xe8,0x50,xxxx,xxxx,xxxx,0xa0, 0x5d,0x22,xxxx,xxxx,0xb2,0x3a,xxxx,xxxx, /* 10 */
+ 0xf6,0x8a,0x41,xxxx,xxxx,0x81,xxxx,xxxx, xxxx,xxxx,0x2b,0x58,xxxx,xxxx,xxxx,0xc6, /* 20 */
+ xxxx,xxxx,0xb9,xxxx,xxxx,0x2a,xxxx,0x3c, xxxx,0x80,0x26,xxxx,0xb0,xxxx,0x47,xxxx, /* 30 */
+ xxxx,xxxx,0x0a,0x55,xxxx,xxxx,xxxx,0x88, xxxx,xxxx,0x87,xxxx,xxxx,0xb4,0x0c,xxxx, /* 40 */
+ 0x73,0x53,xxxx,xxxx,0x3b,0x1f,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */
+ 0x01,xxxx,xxxx,xxxx,xxxx,0x1e,xxxx,xxxx, 0xc3,xxxx,0xa3,0x74,xxxx,0x32,0x42,0x75, /* 60 */
+ 0xfc,xxxx,0xb8,xxxx,0x33,xxxx,0x5e,xxxx, xxxx,0xaa,xxxx,xxxx,0x04,xxxx,0x9c,0xba, /* 70 */
+ xxxx,xxxx,0x24,0x89,xxxx,xxxx,0xea,xxxx, 0x23,xxxx,xxxx,xxxx,0xbb,xxxx,xxxx,0xc7, /* 80 */
+ xxxx,0x8e,xxxx,0x52,xxxx,0x18,xxxx,0x72, xxxx,xxxx,xxxx,xxxx,0xb6,xxxx,xxxx,xxxx, /* 90 */
+ 0xfa,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, 0xb1,xxxx,xxxx,xxxx,xxxx,0x57,0x78,0xa2, /* A0 */
+ xxxx,0x3d,0x51,xxxx,xxxx,0xbf,0x46,0x2c, xxxx,xxxx,0xfb,xxxx,xxxx,xxxx,xxxx,0x38, /* B0 */
+ 0x56,xxxx,0xcf,xxxx,0x08,xxxx,xxxx,xxxx, 0x5b,0x07,xxxx,xxxx,xxxx,0x20,0x9d,xxxx, /* C0 */
+ 0x03,xxxx,xxxx,xxxx,xxxx,xxxx,0xbc,0x86, 0x59,xxxx,0x02,xxxx,0xff,0xd2,0x8b,xxxx, /* D0 */
+ xxxx,0xd0,xxxx,xxxx,xxxx,xxxx,xxxx,0xe9, 0x06,xxxx,0x5f,0xf3,xxxx,0xb5,xxxx,xxxx, /* E0 */
+ 0xeb,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,xxxx, 0x36,xxxx,xxxx,xxxx,xxxx,0xbd,0xfe,xxxx, /* F0 */
+};
+
+// 0x95 (0x18) opcode is right but arguments could be swapped
+// 0x2a (0x2b) not sure, could be 0x1b
+// 0x60 (0x01) guess (wrong?)
+
+
+/* preliminary table by Pierpaolo Prazzoli */
+const UINT8 matchit2_decryption_table[256] = {
+ xxxx,0x86,0x0a,xxxx,0x32,0x01,0x81,0xbe, 0xea,xxxx,0xbb,xxxx,xxxx,xxxx,0xa5,0xf6, /* 00 */
+// new new new new new new new new new
+ 0x5d,0x8c,0xf3,0xc4,0x42,0x5a,0x22,0x26, xxxx,0x58,xxxx,0xfd,0x59,0x53,0x80,0x09, /* 10 */
+// new new new new !!!! new !!!! new !!!! new new new !!!!
+ xxxx,0x1e,0x48,0xe2,0x50,xxxx,0xc3,0x23, xxxx,xxxx,0xe9,xxxx,0x40,0x83,0xa3,0x46, /* 20 */
+// new new new new new new new new new new
+ 0x49,0xb4,0xa9,xxxx,0xd3,0x8b,0xe8,0xb8, 0xa0,xxxx,xxxx,xxxx,0x84,xxxx,xxxx,xxxx, /* 30 */
+// !!!! ???? new !!!! new new new new
+ xxxx,xxxx,xxxx,xxxx,0x14,xxxx,0x25,xxxx, xxxx,0x5e,xxxx,0x87,0x56,0xb9,xxxx,0x39, /* 40 */
+// new new new new new new ???? new
+ 0x89,xxxx,xxxx,xxxx,xxxx,0x1f,0xa4,xxxx, 0xf8,0x5f,0x21,0xb3,0x5b,xxxx,0x8d,xxxx, /* 50 */
+// new new !!!! new new !!!! new new
+ xxxx,0xc5,0x7c,0x07,xxxx,0x88,0xba,0x47, 0x35,0xfb,xxxx,0x7f,xxxx,xxxx,0xc6,0xeb, /* 60 */
+// new !!!! new new new new new new !!!! new
+ xxxx,0xc7,xxxx,xxxx,0xd2,0xa1,0x72,0x79, 0xfe,0x24,0xab,0x2a,0xbc,0x0d,0x8f,0x7e, /* 70 */
+// !!!! new new new new new new new new new !!!!
+ xxxx,0x7d,xxxx,0xe7,0x2d,xxxx,xxxx,0x57, 0x0b,0xa2,xxxx,0x9d,xxxx,xxxx,0x74,0x85, /* 80 */
+// !!!! new new new new new new new new
+ 0xaf,0x2f,0x8a,0xe6,0x08,xxxx,0xff,xxxx, xxxx,0x1c,xxxx,xxxx,0x02,xxxx,xxxx,xxxx, /* 90 */
+// new !!!! new new new new !!!! new
+ 0x43,0x04,xxxx,xxxx,0xbf,0x3b,0x93,0x38, xxxx,xxxx,xxxx,0x77,xxxx,0xb0,xxxx,0x3a, /* A0 */
+// new new new new new new new new new
+ 0xfc,xxxx,0xb5,xxxx,xxxx,xxxx,xxxx,0x05, 0x52,0x76,0x2b,0xe5,0xbd,xxxx,0x0e,0xb1, /* B0 */
+// new new new new new new new new new !!!!
+ 0x73,xxxx,xxxx,0x45,0x92,0x99,xxxx,0xf7, 0x3d,0xd0,0xb6,0x36,0xf9,0xfa,0x0f,xxxx, /* C0 */
+// new new new new new new new !!!! new new
+ 0x75,xxxx,0xaa,0x9c,xxxx,0x11,xxxx,xxxx, 0x27,0x4b,xxxx,0x2c,0x51,0x2e,0x4d,xxxx, /* D0 */
+// new !!!! new new new new new new new !!!!
+ 0x55,0x3c,xxxx,0xb7,xxxx,0xd1,0x8e,xxxx, 0xb2,xxxx,0x78,xxxx,0x12,xxxx,0x29,0x0c, /* E0 */
+// new new new ???? new new new new new new new
+ 0x33,xxxx,0xf2,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,0x03,0x06,0xa8,xxxx,xxxx,0xcf,xxxx, /* F0 */
+// new new new new new new
+};
+/*
+Unknown (marked "????")
+
+from shisen 2:
+E4 -> pc: b08; f458, 1920 (99% 1 byte at boot and sometimes when a piece is selected)
+ b65c (after one match is finished with the girl on the background or when you finish some levels in the other modes)
+ (16 37 3e 3f 41 4a 4d 4e 4f 90 91 95 96)
+4E -> pc: 7ac3, 7ae8 (after a 2 players match and in a 2 players match in "stalemate")
+
+Found (marked "!!!!")
+14 -> pc: 8b2a -> 42
+16 -> pc: 1714, 1804, 1a70, 1cc3 (00 10 13 1C 20 21 22 34 D4 D5 after a match) -> 22
+1B -> pc: 630e (it's used to update the high score) -> FD
+1F -> pc: f30, f35, af74, 153a, 6dd8, 674f -> 09
+30 -> pc: 19af, 1986 -> 49
+31 -> pc: c804, c813, c822, 1358, c303, c312, c321, 1315, 1338 (2 bytes opcode) -> B4
+34 -> pc: 42cd -> D3
+56 -> pc: 6587 (can be 6C, 6D, 6E, 6F, A4, A6, A7, AA, AC, AD, AE at boot) -> A4
+5A -> pc: ae83 (after an item is selected) (00 10 13 15 1B -1C already used- 1D 21 28) -> 21 (it's used to evidence tiles similar to the one selected)
+62 -> pc: 5b3f (jump 71, 7C) -> 7C
+6B -> pc: 1810, 1936 (jump) -> 7F
+74 -> pc: ca75 -> D2
+7F -> pc: 6b7e, 51d7, 5a8c, 5a9a, 5996 (jump: 7C, 7E) -> 7E
+81 -> pc: 599d (jump: 7D, 7F) -> 7D
+91 -> pc: 6e0c, 96ef, 96d0 (1 byte opcode) -> 2F
+99 -> pc: 96f7, 9702 (after undo button is pressed) -> 1C (it's used to update the score when the you undo the moves)
+BF -> pc: 6af3, 6b01, ca73, ab39 (2 bytes opcode) -> B1
+C4 -> pc: deb4 -> 92 from bbmanw
+EC -> pc: 966e, 9679 -> 12 from bbmanw
+D2 -> pc: 631c (it's used to update the high score) (6C, 6E, A6, AA, AE) -> AA
+
+the ones marked with "new" are checked against dynablst and bomberman tables
+*/
+
+
+const UINT8 test_decryption_table[256] = {
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 00 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 10 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 20 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 30 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 40 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 50 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 60 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 70 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 80 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* 90 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* A0 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* B0 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* C0 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* D0 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* E0 */
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, /* F0 */
+};
+
+static const UINT8 byte_count_table[256] = {
+ 2,2,2,2,2,3,1,1, 2,2,2,2,2,3,1,0, /* 00 */
+ 2,2,2,2,2,3,1,1, 2,2,2,2,2,3,1,1, /* 10 */
+ 2,2,2,2,2,3,1,1, 2,2,2,2,2,3,1,1, /* 20 */
+ 2,2,2,2,2,3,1,1, 2,2,2,2,2,3,1,1, /* 30 */
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, /* 40 */
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, /* 50 */
+ 1,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* 60 */
+ 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, /* 70 */
+ 3,3,3,3,2,2,2,2, 2,2,2,2,0,0,0,0, /* 80 */
+ 1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0, /* 90 */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* A0 */
+ 2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3, /* B0 */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* C0 */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* D0 */
+ 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, /* E0 */
+ 0,0,0,0,0,0,0,0, 1,1,1,1,1,1,0,0, /* F0 */
+};
+
+UINT8 *irem_cpu_decrypted;
+
+void irem_cpu_decrypt(int cpu,const UINT8 *decryption_table)
+{
+ int A,size;
+ UINT8 *rom;
+// int t[256];
+#ifdef MAME_DEBUG
+// extern char *opmap1[];
+#endif
+
+ rom = memory_region(cpu+REGION_CPU1);
+ size = memory_region_length(cpu+REGION_CPU1);
+ irem_cpu_decrypted = auto_malloc(size);
+
+ memory_set_decrypted_region(cpu,0,size-1,irem_cpu_decrypted);
+ for (A = 0;A < size; A++)
+ irem_cpu_decrypted[A] = decryption_table[rom[A]];
+
+ // RZ note:
+ // for "gussun" and "riskchal" an hack to not decrypt a not encrypted routine
+ // we need a real nec v25+/35+ core to support 0x63 (brkn for "break native") instruction
+ // for now we use "cd" (int) instruction + hack (to force to not decrypt the code from 0xa8fd to 0xa90b)
+
+ if (m90_game_kludge==1) // for gussun and riskchal
+ for (A = 0xa8fd;A < 0xa90c; A++)
+ irem_cpu_decrypted[A] = rom[A];
+
+/*
+ for (A=0; A<256; A++) {
+ t[A]=0;
+ for (diff=0; diff<256; diff++)
+ if (decryption_table[diff]==A) {
+ t[A]++;
+ }
+#ifdef MAME_DEBUG
+// if (t[A]==0) logerror("Unused: [%d] %02x\t%s\n",byte_count_table[A],A,opmap1[A]);
+// if (t[A]>1) logerror("DUPLICATE: %02x\t%s\n",A,opmap1[A]);
+#else
+ if (t[A]==0) logerror("Unused: [%d] %02x\n",byte_count_table[A],A);
+ if (t[A]>1) logerror("DUPLICATE: %02x\n",A);
+#endif
+ }
+*/
+}
diff --git a/src/mame/machine/irem_cpu.h b/src/mame/machine/irem_cpu.h
new file mode 100644
index 00000000000..40630503585
--- /dev/null
+++ b/src/mame/machine/irem_cpu.h
@@ -0,0 +1,19 @@
+
+extern const UINT8 gunforce_decryption_table[];
+extern const UINT8 bomberman_decryption_table[];
+extern const UINT8 lethalth_decryption_table[];
+extern const UINT8 dynablaster_decryption_table[];
+extern const UINT8 mysticri_decryption_table[];
+extern const UINT8 majtitl2_decryption_table[];
+extern const UINT8 hook_decryption_table[];
+extern const UINT8 rtypeleo_decryption_table[];
+extern const UINT8 inthunt_decryption_table[];
+extern const UINT8 gussun_decryption_table[];
+extern const UINT8 leagueman_decryption_table[];
+extern const UINT8 psoldier_decryption_table[];
+extern const UINT8 dsoccr94_decryption_table[];
+extern const UINT8 matchit2_decryption_table[];
+
+extern const UINT8 test_decryption_table[];
+
+extern void irem_cpu_decrypt(int cpu,const UINT8 *decryption_table);
diff --git a/src/mame/machine/irobot.c b/src/mame/machine/irobot.c
new file mode 100644
index 00000000000..2fd1243e252
--- /dev/null
+++ b/src/mame/machine/irobot.c
@@ -0,0 +1,1023 @@
+/***************************************************************************
+
+ Atari I, Robot hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "profiler.h"
+#include "cpu/m6809/m6809.h"
+#include "irobot.h"
+
+/* Note:
+ * There's probably something wrong with the way the Mathbox gets started.
+ * Try compiling with IR_TIMING=1, run with logging on and take a look at
+ * the resulting logilfe.
+ * The mathbox is started in short intervals (<10 scanlines) without (!)
+ * checking its idle status.
+ * It also seems that the mathbox in this emulation would have to cope with
+ * approx. 5000 instructions per scanline [look at the number of instructions
+ * and the number of scanlines to the next mathbox start]. This seems a bit
+ * too high.
+ */
+
+#define IR_TIMING 1 /* try to emulate MB and VG running time */
+#define DISASSEMBLE_MB_ROM 0 /* generate a disassembly of the mathbox ROMs */
+
+#define IR_CPU_STATE \
+ logerror(\
+ "pc: %4x, scanline: %d\n", activecpu_get_previouspc(), video_screen_get_vpos(0))
+
+
+UINT8 irobot_vg_clear;
+static UINT8 irvg_vblank;
+static UINT8 irvg_running;
+static UINT8 irmb_running;
+
+#if IR_TIMING
+static emu_timer *irvg_timer;
+static emu_timer *irmb_timer;
+#endif
+
+static UINT8 *comRAM[2], *mbRAM, *mbROM;
+static UINT8 irobot_control_num = 0;
+static UINT8 irobot_statwr;
+static UINT8 irobot_out0;
+static UINT8 irobot_outx,irobot_mpage;
+
+static UINT8 *irobot_combase_mb;
+UINT8 *irobot_combase;
+UINT8 irobot_bufsel;
+UINT8 irobot_alphamap;
+
+static void irmb_run(void);
+
+
+/***********************************************************************/
+
+
+
+READ8_HANDLER( irobot_sharedmem_r )
+{
+ if (irobot_outx == 3)
+ return mbRAM[BYTE_XOR_BE(offset)];
+
+ if (irobot_outx == 2)
+ return irobot_combase[BYTE_XOR_BE(offset & 0xFFF)];
+
+ if (irobot_outx == 0)
+ return mbROM[((irobot_mpage & 1) << 13) + BYTE_XOR_BE(offset)];
+
+ if (irobot_outx == 1)
+ return mbROM[0x4000 + ((irobot_mpage & 3) << 13) + BYTE_XOR_BE(offset)];
+
+ return 0xFF;
+}
+
+/* Comment out the mbRAM =, comRAM2 = or comRAM1 = and it will start working */
+WRITE8_HANDLER( irobot_sharedmem_w )
+{
+ if (irobot_outx == 3)
+ mbRAM[BYTE_XOR_BE(offset)] = data;
+
+ if (irobot_outx == 2)
+ irobot_combase[BYTE_XOR_BE(offset & 0xFFF)] = data;
+}
+
+static TIMER_CALLBACK( irvg_done_callback )
+{
+ logerror("vg done. ");
+ irvg_running = 0;
+}
+
+WRITE8_HANDLER( irobot_statwr_w )
+{
+ logerror("write %2x ", data);
+ IR_CPU_STATE;
+
+ irobot_combase = comRAM[data >> 7];
+ irobot_combase_mb = comRAM[(data >> 7) ^ 1];
+ irobot_bufsel = data & 0x02;
+ if (((data & 0x01) == 0x01) && (irobot_vg_clear == 0))
+ irobot_poly_clear();
+
+ irobot_vg_clear = data & 0x01;
+
+ if ((data & 0x04) && !(irobot_statwr & 0x04))
+ {
+ irobot_run_video();
+#if IR_TIMING
+ if (irvg_running == 0)
+ logerror("vg start ");
+ else
+ logerror("vg start [busy!] ");
+ IR_CPU_STATE;
+ timer_adjust(irvg_timer, ATTOTIME_IN_MSEC(10), 0, attotime_zero);
+#endif
+ irvg_running=1;
+ }
+ if ((data & 0x10) && !(irobot_statwr & 0x10))
+ irmb_run();
+ irobot_statwr = data;
+}
+
+WRITE8_HANDLER( irobot_out0_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ irobot_out0 = data;
+ switch (data & 0x60)
+ {
+ case 0:
+ memory_set_bankptr(2, &RAM[0x1C000]);
+ break;
+ case 0x20:
+ memory_set_bankptr(2, &RAM[0x1C800]);
+ break;
+ case 0x40:
+ memory_set_bankptr(2, &RAM[0x1D000]);
+ break;
+ }
+ irobot_outx = (data & 0x18) >> 3;
+ irobot_mpage = (data & 0x06) >> 1;
+ irobot_alphamap = (data & 0x80);
+}
+
+WRITE8_HANDLER( irobot_rom_banksel_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ switch ((data & 0x0E) >> 1)
+ {
+ case 0:
+ memory_set_bankptr(1, &RAM[0x10000]);
+ break;
+ case 1:
+ memory_set_bankptr(1, &RAM[0x12000]);
+ break;
+ case 2:
+ memory_set_bankptr(1, &RAM[0x14000]);
+ break;
+ case 3:
+ memory_set_bankptr(1, &RAM[0x16000]);
+ break;
+ case 4:
+ memory_set_bankptr(1, &RAM[0x18000]);
+ break;
+ case 5:
+ memory_set_bankptr(1, &RAM[0x1A000]);
+ break;
+ }
+ set_led_status(0,data & 0x10);
+ set_led_status(1,data & 0x20);
+}
+
+static TIMER_CALLBACK( scanline_callback )
+{
+ int scanline = param;
+
+ if (scanline == 0) irvg_vblank=0;
+ if (scanline == 224) irvg_vblank=1;
+ logerror("SCANLINE CALLBACK %d\n",scanline);
+ /* set the IRQ line state based on the 32V line state */
+ cpunum_set_input_line(0, M6809_IRQ_LINE, (scanline & 32) ? ASSERT_LINE : CLEAR_LINE);
+
+ /* set a callback for the next 32-scanline increment */
+ scanline += 32;
+ if (scanline >= 256) scanline = 0;
+ timer_set(video_screen_get_time_until_pos(0, scanline, 0), scanline, scanline_callback);
+}
+
+static TIMER_CALLBACK( irmb_done_callback );
+MACHINE_RESET( irobot )
+{
+ UINT8 *MB = memory_region(REGION_CPU2);
+
+ /* initialize the memory regions */
+ mbROM = MB + 0x00000;
+ mbRAM = MB + 0x0c000;
+ comRAM[0] = MB + 0x0e000;
+ comRAM[1] = MB + 0x0f000;
+
+ irvg_vblank=0;
+ irvg_running = 0;
+ irvg_timer = timer_alloc(irvg_done_callback);
+ irmb_running = 0;
+ irmb_timer = timer_alloc(irmb_done_callback);
+
+ /* set an initial timer to go off on scanline 0 */
+ timer_set(video_screen_get_time_until_pos(0, 0, 0), 0, scanline_callback);
+
+ irobot_rom_banksel_w(0,0);
+ irobot_out0_w(0,0);
+ irobot_combase = comRAM[0];
+ irobot_combase_mb = comRAM[1];
+ irobot_outx = 0;
+}
+
+WRITE8_HANDLER( irobot_control_w )
+{
+
+ irobot_control_num = offset & 0x03;
+}
+
+READ8_HANDLER( irobot_control_r )
+{
+
+ if (irobot_control_num == 0)
+ return readinputport (5);
+ else if (irobot_control_num == 1)
+ return readinputport (6);
+ return 0;
+
+}
+
+/* we allow irmb_running and irvg_running to appear running before clearing
+ them to simulate the mathbox and vector generator running in real time */
+READ8_HANDLER( irobot_status_r )
+{
+ int d=0;
+
+ logerror("status read. ");
+ IR_CPU_STATE;
+
+ if (!irmb_running) d |= 0x20;
+ if (irvg_running) d |= 0x40;
+
+ // d = (irmb_running * 0x20) | (irvg_running * 0x40);
+ if (irvg_vblank) d = d | 0x80;
+#if IR_TIMING
+ /* flags are cleared by callbacks */
+#else
+ irmb_running=0;
+ irvg_running=0;
+#endif
+ return d;
+}
+
+
+/***********************************************************************
+
+ I-Robot Mathbox
+
+ Based on 4 2901 chips slice processors connected to form a 16-bit ALU
+
+ Microcode roms:
+ 6N: bits 0..3: Address of ALU A register
+ 5P: bits 0..3: Address of ALU B register
+ 6M: bits 0..3: ALU Function bits 5..8
+ 7N: bits 0..3: ALU Function bits 1..4
+ 8N: bits 0,1: Memory write timing
+ bit 2: Hardware multiply mode
+ bit 3: ALU Function bit 0
+ 6P: bits 0,1: Direct addressing bits 0,1
+ bits 2,3: Jump address bits 0,1
+ 8M: bits 0..3: Jump address bits 6..9
+ 9N: bits 0..3: Jump address bits 2..5
+ 8P: bits 0..3: Memory address bits 2..5
+ 9M: bit 0: Shift control
+ bits 1..3: Jump type
+ 0 = No Jump
+ 1 = On carry
+ 2 = On zero
+ 3 = On positive
+ 4 = On negative
+ 5 = Unconditional
+ 6 = Jump to Subroutine
+ 7 = Return from Subroutine
+ 7M: Bit 0: Mathbox memory enable
+ Bit 1: Latch data to address bus
+ Bit 2: Carry in select
+ Bit 3: Carry in value
+ (if 2,3 = 11 then mathbox is done)
+ 9P: Bit 0: Hardware divide enable
+ Bits 1,2: Memory select
+ Bit 3: Memory R/W
+ 7P: Bits 0,1: Direct addressing bits 6,7
+ Bits 2,3: Unused
+
+***********************************************************************/
+
+#define FL_MULT 0x01
+#define FL_shift 0x02
+#define FL_MBMEMDEC 0x04
+#define FL_ADDEN 0x08
+#define FL_DPSEL 0x10
+#define FL_carry 0x20
+#define FL_DIV 0x40
+#define FL_MBRW 0x80
+
+typedef struct irmb_ops
+{
+ const struct irmb_ops *nxtop;
+ UINT32 func;
+ UINT32 diradd;
+ UINT32 latchmask;
+ UINT32 *areg;
+ UINT32 *breg;
+ UINT8 cycles;
+ UINT8 diren;
+ UINT8 flags;
+ UINT8 ramsel;
+} irmb_ops;
+
+static irmb_ops *mbops;
+
+static const irmb_ops *irmb_stack[16];
+static UINT32 irmb_regs[16];
+static UINT32 irmb_latch;
+
+#if DISASSEMBLE_MB_ROM
+static void disassemble_instruction(irmb_ops *op);
+#endif
+
+
+static UINT32 irmb_din(const irmb_ops *curop)
+{
+ UINT32 d = 0;
+
+ if (!(curop->flags & FL_MBMEMDEC) && (curop->flags & FL_MBRW))
+ {
+ UINT32 ad = curop->diradd | (irmb_latch & curop->latchmask);
+
+ if (curop->diren || (irmb_latch & 0x6000) == 0)
+ d = ((UINT16 *)mbRAM)[ad & 0xfff]; /* MB RAM read */
+ else if (irmb_latch & 0x4000)
+ d = ((UINT16 *)mbROM)[ad + 0x2000]; /* MB ROM read, CEMATH = 1 */
+ else
+ d = ((UINT16 *)mbROM)[ad & 0x1fff]; /* MB ROM read, CEMATH = 0 */
+ }
+ return d;
+}
+
+
+static void irmb_dout(const irmb_ops *curop, UINT32 d)
+{
+ /* Write to video com ram */
+ if (curop->ramsel == 3)
+ ((UINT16 *)irobot_combase_mb)[irmb_latch & 0x7ff] = d;
+
+ /* Write to mathox ram */
+ if (!(curop->flags & FL_MBMEMDEC))
+ {
+ UINT32 ad = curop->diradd | (irmb_latch & curop->latchmask);
+
+ if (curop->diren || (irmb_latch & 0x6000) == 0)
+ ((UINT16 *)mbRAM)[ad & 0xfff] = d; /* MB RAM write */
+ }
+}
+
+
+/* Convert microcode roms to a more usable form */
+static void load_oproms(void)
+{
+ UINT8 *MB = memory_region(REGION_PROMS) + 0x20;
+ int i;
+
+ /* allocate RAM */
+ mbops = auto_malloc(sizeof(irmb_ops) * 1024);
+
+ for (i = 0; i < 1024; i++)
+ {
+ int nxtadd, func, ramsel, diradd, latchmask, dirmask, time;
+
+ mbops[i].areg = &irmb_regs[MB[0x0000 + i] & 0x0F];
+ mbops[i].breg = &irmb_regs[MB[0x0400 + i] & 0x0F];
+ func = (MB[0x0800 + i] & 0x0F) << 5;
+ func |= ((MB[0x0C00 +i] & 0x0F) << 1);
+ func |= (MB[0x1000 + i] & 0x08) >> 3;
+ time = MB[0x1000 + i] & 0x03;
+ mbops[i].flags = (MB[0x1000 + i] & 0x04) >> 2;
+ nxtadd = (MB[0x1400 + i] & 0x0C) >> 2;
+ diradd = MB[0x1400 + i] & 0x03;
+ nxtadd |= ((MB[0x1800 + i] & 0x0F) << 6);
+ nxtadd |= ((MB[0x1C00 + i] & 0x0F) << 2);
+ diradd |= (MB[0x2000 + i] & 0x0F) << 2;
+ func |= (MB[0x2400 + i] & 0x0E) << 9;
+ mbops[i].flags |= (MB[0x2400 + i] & 0x01) << 1;
+ mbops[i].flags |= (MB[0x2800 + i] & 0x0F) << 2;
+ mbops[i].flags |= ((MB[0x2C00 + i] & 0x01) << 6);
+ mbops[i].flags |= (MB[0x2C00 + i] & 0x08) << 4;
+ ramsel = (MB[0x2C00 + i] & 0x06) >> 1;
+ diradd |= (MB[0x3000 + i] & 0x03) << 6;
+
+ if (mbops[i].flags & FL_shift) func |= 0x200;
+
+ mbops[i].func = func;
+ mbops[i].nxtop = &mbops[nxtadd];
+
+ /* determine the number of 12MHz cycles for this operation */
+ if (time == 3)
+ mbops[i].cycles = 2;
+ else
+ mbops[i].cycles = 3 + time;
+
+ /* precompute the hardcoded address bits and the mask to be used on the latch value */
+ if (ramsel == 0)
+ {
+ dirmask = 0x00FC;
+ latchmask = 0x3000;
+ }
+ else
+ {
+ dirmask = 0x0000;
+ latchmask = 0x3FFC;
+ }
+ if (ramsel & 2)
+ latchmask |= 0x0003;
+ else
+ dirmask |= 0x0003;
+
+ mbops[i].ramsel = ramsel;
+ mbops[i].diradd = diradd & dirmask;
+ mbops[i].latchmask = latchmask;
+ mbops[i].diren = (ramsel == 0);
+
+#if DISASSEMBLE_MB_ROM
+ disassemble_instruction(&mbops[i]);
+#endif
+ }
+}
+
+
+/* Init mathbox (only called once) */
+DRIVER_INIT( irobot )
+{
+ int i;
+ for (i = 0; i < 16; i++)
+ {
+ irmb_stack[i] = &mbops[0];
+ irmb_regs[i] = 0;
+ }
+ irmb_latch=0;
+ load_oproms();
+}
+
+static TIMER_CALLBACK( irmb_done_callback )
+{
+ logerror("mb done. ");
+ irmb_running = 0;
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
+}
+
+
+#define COMPUTE_CI \
+ CI = 0;\
+ if (curop->flags & FL_DPSEL)\
+ CI = cflag;\
+ else\
+ {\
+ if (curop->flags & FL_carry)\
+ CI = 1;\
+ if (!(prevop->flags & FL_DIV) && !nflag)\
+ CI = 1;\
+ }
+
+#define ADD(r,s) \
+ COMPUTE_CI;\
+ result = r + s + CI;\
+ cflag = (result >> 16) & 1;\
+ vflag = (((r & 0x7fff) + (s & 0x7fff) + CI) >> 15) ^ cflag
+
+#define SUBR(r,s) \
+ COMPUTE_CI;\
+ result = (r ^ 0xFFFF) + s + CI; /*S - R + CI - 1*/ \
+ cflag = (result >> 16) & 1;\
+ vflag = (((s & 0x7fff) + ((r ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag
+
+#define SUB(r,s) \
+ COMPUTE_CI;\
+ result = r + (s ^ 0xFFFF) + CI; /*R - S + CI - 1*/ \
+ cflag = (result >> 16) & 1;\
+ vflag = (((r & 0x7fff) + ((s ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag
+
+#define OR(r,s) \
+ result = r | s;\
+ vflag = cflag = 0
+
+#define AND(r,s) \
+ result = r & s;\
+ vflag = cflag = 0
+
+#define IAND(r,s) \
+ result = (r ^ 0xFFFF) & s;\
+ vflag = cflag = 0
+
+#define XOR(r,s) \
+ result = r ^ s;\
+ vflag = cflag = 0
+
+#define IXOR(r,s) \
+ result = (r ^ s) ^ 0xFFFF;\
+ vflag = cflag = 0
+
+
+#define DEST0 \
+ Q = Y = zresult
+
+#define DEST1 \
+ Y = zresult
+
+#define DEST2 \
+ Y = *curop->areg;\
+ *curop->breg = zresult
+
+#define DEST3 \
+ *curop->breg = zresult;\
+ Y = zresult
+
+#define DEST4_NOSHIFT \
+ *curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\
+ Q = (Q >> 1) | ((curop->flags & 0x20) << 10);\
+ Y = zresult
+
+#define DEST4_SHIFT \
+ *curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\
+ Q = (Q >> 1) | ((zresult & 0x01) << 15);\
+ Y = zresult
+
+#define DEST5_NOSHIFT \
+ *curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\
+ Y = zresult
+
+#define DEST5_SHIFT \
+ *curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\
+ Y = zresult
+
+#define DEST6_NOSHIFT \
+ *curop->breg = zresult << 1;\
+ Q = ((Q << 1) & 0xffff) | (nflag ^ 1);\
+ Y = zresult
+
+#define DEST6_SHIFT \
+ *curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\
+ Q = (Q << 1) & 0xffff;\
+ Y = zresult
+
+#define DEST7_NOSHIFT \
+ *curop->breg = zresult << 1;\
+ Y = zresult
+
+#define DEST7_SHIFT \
+ *curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\
+ Y = zresult
+
+
+#define JUMP0 curop++;
+#define JUMP1 if (cflag) curop = curop->nxtop; else curop++;
+#define JUMP2 if (!zresult) curop = curop->nxtop; else curop++;
+#define JUMP3 if (!nflag) curop = curop->nxtop; else curop++;
+#define JUMP4 if (nflag) curop = curop->nxtop; else curop++;
+#define JUMP5 curop = curop->nxtop;
+#define JUMP6 irmb_stack[SP] = curop + 1; SP = (SP + 1) & 15; curop = curop->nxtop;
+#define JUMP7 SP = (SP - 1) & 15; curop = irmb_stack[SP];
+
+
+/* Run mathbox */
+static void irmb_run(void)
+{
+ const irmb_ops *prevop = &mbops[0];
+ const irmb_ops *curop = &mbops[0];
+
+ UINT32 Q = 0;
+ UINT32 Y = 0;
+ UINT32 nflag = 0;
+ UINT32 vflag = 0;
+ UINT32 cflag = 0;
+ UINT32 zresult = 1;
+ UINT32 CI = 0;
+ UINT32 SP = 0;
+ UINT32 icount = 0;
+
+ profiler_mark(PROFILER_USER1);
+
+ while ((prevop->flags & (FL_DPSEL | FL_carry)) != (FL_DPSEL | FL_carry))
+ {
+ UINT32 result;
+ UINT32 fu;
+ UINT32 tmp;
+
+ icount += curop->cycles;
+
+ /* Get function code */
+ fu = curop->func;
+
+ /* Modify function for MULT */
+ if (!(prevop->flags & FL_MULT) || (Q & 1))
+ fu = fu ^ 0x02;
+ else
+ fu = fu | 0x02;
+
+ /* Modify function for DIV */
+ if ((prevop->flags & FL_DIV) || nflag)
+ fu = fu ^ 0x08;
+ else
+ fu = fu | 0x08;
+
+ /* Do source and operation */
+ switch (fu & 0x03f)
+ {
+ case 0x00: ADD(*curop->areg, Q); break;
+ case 0x01: ADD(*curop->areg, *curop->breg); break;
+ case 0x02: ADD(0, Q); break;
+ case 0x03: ADD(0, *curop->breg); break;
+ case 0x04: ADD(0, *curop->areg); break;
+ case 0x05: tmp = irmb_din(curop); ADD(tmp, *curop->areg); break;
+ case 0x06: tmp = irmb_din(curop); ADD(tmp, Q); break;
+ case 0x07: tmp = irmb_din(curop); ADD(tmp, 0); break;
+ case 0x08: SUBR(*curop->areg, Q); break;
+ case 0x09: SUBR(*curop->areg, *curop->breg); break;
+ case 0x0a: SUBR(0, Q); break;
+ case 0x0b: SUBR(0, *curop->breg); break;
+ case 0x0c: SUBR(0, *curop->areg); break;
+ case 0x0d: tmp = irmb_din(curop); SUBR(tmp, *curop->areg); break;
+ case 0x0e: tmp = irmb_din(curop); SUBR(tmp, Q); break;
+ case 0x0f: tmp = irmb_din(curop); SUBR(tmp, 0); break;
+ case 0x10: SUB(*curop->areg, Q); break;
+ case 0x11: SUB(*curop->areg, *curop->breg); break;
+ case 0x12: SUB(0, Q); break;
+ case 0x13: SUB(0, *curop->breg); break;
+ case 0x14: SUB(0, *curop->areg); break;
+ case 0x15: tmp = irmb_din(curop); SUB(tmp, *curop->areg); break;
+ case 0x16: tmp = irmb_din(curop); SUB(tmp, Q); break;
+ case 0x17: tmp = irmb_din(curop); SUB(tmp, 0); break;
+ case 0x18: OR(*curop->areg, Q); break;
+ case 0x19: OR(*curop->areg, *curop->breg); break;
+ case 0x1a: OR(0, Q); break;
+ case 0x1b: OR(0, *curop->breg); break;
+ case 0x1c: OR(0, *curop->areg); break;
+ case 0x1d: OR(irmb_din(curop), *curop->areg); break;
+ case 0x1e: OR(irmb_din(curop), Q); break;
+ case 0x1f: OR(irmb_din(curop), 0); break;
+ case 0x20: AND(*curop->areg, Q); break;
+ case 0x21: AND(*curop->areg, *curop->breg); break;
+ case 0x22: AND(0, Q); break;
+ case 0x23: AND(0, *curop->breg); break;
+ case 0x24: AND(0, *curop->areg); break;
+ case 0x25: AND(irmb_din(curop), *curop->areg); break;
+ case 0x26: AND(irmb_din(curop), Q); break;
+ case 0x27: AND(irmb_din(curop), 0); break;
+ case 0x28: IAND(*curop->areg, Q); break;
+ case 0x29: IAND(*curop->areg, *curop->breg); break;
+ case 0x2a: IAND(0, Q); break;
+ case 0x2b: IAND(0, *curop->breg); break;
+ case 0x2c: IAND(0, *curop->areg); break;
+ case 0x2d: IAND(irmb_din(curop), *curop->areg); break;
+ case 0x2e: IAND(irmb_din(curop), Q); break;
+ case 0x2f: IAND(irmb_din(curop), 0); break;
+ case 0x30: XOR(*curop->areg, Q); break;
+ case 0x31: XOR(*curop->areg, *curop->breg); break;
+ case 0x32: XOR(0, Q); break;
+ case 0x33: XOR(0, *curop->breg); break;
+ case 0x34: XOR(0, *curop->areg); break;
+ case 0x35: XOR(irmb_din(curop), *curop->areg); break;
+ case 0x36: XOR(irmb_din(curop), Q); break;
+ case 0x37: XOR(irmb_din(curop), 0); break;
+ case 0x38: IXOR(*curop->areg, Q); break;
+ case 0x39: IXOR(*curop->areg, *curop->breg); break;
+ case 0x3a: IXOR(0, Q); break;
+ case 0x3b: IXOR(0, *curop->breg); break;
+ case 0x3c: IXOR(0, *curop->areg); break;
+ case 0x3d: IXOR(irmb_din(curop), *curop->areg); break;
+ case 0x3e: IXOR(irmb_din(curop), Q); break;
+default: case 0x3f: IXOR(irmb_din(curop), 0); break;
+ }
+
+ /* Evaluate flags */
+ zresult = result & 0xFFFF;
+ nflag = zresult >> 15;
+
+ prevop = curop;
+
+ /* Do destination and jump */
+ switch (fu >> 6)
+ {
+ case 0x00:
+ case 0x08: DEST0; JUMP0; break;
+ case 0x01:
+ case 0x09: DEST1; JUMP0; break;
+ case 0x02:
+ case 0x0a: DEST2; JUMP0; break;
+ case 0x03:
+ case 0x0b: DEST3; JUMP0; break;
+ case 0x04: DEST4_NOSHIFT; JUMP0; break;
+ case 0x05: DEST5_NOSHIFT; JUMP0; break;
+ case 0x06: DEST6_NOSHIFT; JUMP0; break;
+ case 0x07: DEST7_NOSHIFT; JUMP0; break;
+ case 0x0c: DEST4_SHIFT; JUMP0; break;
+ case 0x0d: DEST5_SHIFT; JUMP0; break;
+ case 0x0e: DEST6_SHIFT; JUMP0; break;
+ case 0x0f: DEST7_SHIFT; JUMP0; break;
+
+ case 0x10:
+ case 0x18: DEST0; JUMP1; break;
+ case 0x11:
+ case 0x19: DEST1; JUMP1; break;
+ case 0x12:
+ case 0x1a: DEST2; JUMP1; break;
+ case 0x13:
+ case 0x1b: DEST3; JUMP1; break;
+ case 0x14: DEST4_NOSHIFT; JUMP1; break;
+ case 0x15: DEST5_NOSHIFT; JUMP1; break;
+ case 0x16: DEST6_NOSHIFT; JUMP1; break;
+ case 0x17: DEST7_NOSHIFT; JUMP1; break;
+ case 0x1c: DEST4_SHIFT; JUMP1; break;
+ case 0x1d: DEST5_SHIFT; JUMP1; break;
+ case 0x1e: DEST6_SHIFT; JUMP1; break;
+ case 0x1f: DEST7_SHIFT; JUMP1; break;
+
+ case 0x20:
+ case 0x28: DEST0; JUMP2; break;
+ case 0x21:
+ case 0x29: DEST1; JUMP2; break;
+ case 0x22:
+ case 0x2a: DEST2; JUMP2; break;
+ case 0x23:
+ case 0x2b: DEST3; JUMP2; break;
+ case 0x24: DEST4_NOSHIFT; JUMP2; break;
+ case 0x25: DEST5_NOSHIFT; JUMP2; break;
+ case 0x26: DEST6_NOSHIFT; JUMP2; break;
+ case 0x27: DEST7_NOSHIFT; JUMP2; break;
+ case 0x2c: DEST4_SHIFT; JUMP2; break;
+ case 0x2d: DEST5_SHIFT; JUMP2; break;
+ case 0x2e: DEST6_SHIFT; JUMP2; break;
+ case 0x2f: DEST7_SHIFT; JUMP2; break;
+
+ case 0x30:
+ case 0x38: DEST0; JUMP3; break;
+ case 0x31:
+ case 0x39: DEST1; JUMP3; break;
+ case 0x32:
+ case 0x3a: DEST2; JUMP3; break;
+ case 0x33:
+ case 0x3b: DEST3; JUMP3; break;
+ case 0x34: DEST4_NOSHIFT; JUMP3; break;
+ case 0x35: DEST5_NOSHIFT; JUMP3; break;
+ case 0x36: DEST6_NOSHIFT; JUMP3; break;
+ case 0x37: DEST7_NOSHIFT; JUMP3; break;
+ case 0x3c: DEST4_SHIFT; JUMP3; break;
+ case 0x3d: DEST5_SHIFT; JUMP3; break;
+ case 0x3e: DEST6_SHIFT; JUMP3; break;
+ case 0x3f: DEST7_SHIFT; JUMP3; break;
+
+ case 0x40:
+ case 0x48: DEST0; JUMP4; break;
+ case 0x41:
+ case 0x49: DEST1; JUMP4; break;
+ case 0x42:
+ case 0x4a: DEST2; JUMP4; break;
+ case 0x43:
+ case 0x4b: DEST3; JUMP4; break;
+ case 0x44: DEST4_NOSHIFT; JUMP4; break;
+ case 0x45: DEST5_NOSHIFT; JUMP4; break;
+ case 0x46: DEST6_NOSHIFT; JUMP4; break;
+ case 0x47: DEST7_NOSHIFT; JUMP4; break;
+ case 0x4c: DEST4_SHIFT; JUMP4; break;
+ case 0x4d: DEST5_SHIFT; JUMP4; break;
+ case 0x4e: DEST6_SHIFT; JUMP4; break;
+ case 0x4f: DEST7_SHIFT; JUMP4; break;
+
+ case 0x50:
+ case 0x58: DEST0; JUMP5; break;
+ case 0x51:
+ case 0x59: DEST1; JUMP5; break;
+ case 0x52:
+ case 0x5a: DEST2; JUMP5; break;
+ case 0x53:
+ case 0x5b: DEST3; JUMP5; break;
+ case 0x54: DEST4_NOSHIFT; JUMP5; break;
+ case 0x55: DEST5_NOSHIFT; JUMP5; break;
+ case 0x56: DEST6_NOSHIFT; JUMP5; break;
+ case 0x57: DEST7_NOSHIFT; JUMP5; break;
+ case 0x5c: DEST4_SHIFT; JUMP5; break;
+ case 0x5d: DEST5_SHIFT; JUMP5; break;
+ case 0x5e: DEST6_SHIFT; JUMP5; break;
+ case 0x5f: DEST7_SHIFT; JUMP5; break;
+
+ case 0x60:
+ case 0x68: DEST0; JUMP6; break;
+ case 0x61:
+ case 0x69: DEST1; JUMP6; break;
+ case 0x62:
+ case 0x6a: DEST2; JUMP6; break;
+ case 0x63:
+ case 0x6b: DEST3; JUMP6; break;
+ case 0x64: DEST4_NOSHIFT; JUMP6; break;
+ case 0x65: DEST5_NOSHIFT; JUMP6; break;
+ case 0x66: DEST6_NOSHIFT; JUMP6; break;
+ case 0x67: DEST7_NOSHIFT; JUMP6; break;
+ case 0x6c: DEST4_SHIFT; JUMP6; break;
+ case 0x6d: DEST5_SHIFT; JUMP6; break;
+ case 0x6e: DEST6_SHIFT; JUMP6; break;
+ case 0x6f: DEST7_SHIFT; JUMP6; break;
+
+ case 0x70:
+ case 0x78: DEST0; JUMP7; break;
+ case 0x71:
+ case 0x79: DEST1; JUMP7; break;
+ case 0x72:
+ case 0x7a: DEST2; JUMP7; break;
+ case 0x73:
+ case 0x7b: DEST3; JUMP7; break;
+ case 0x74: DEST4_NOSHIFT; JUMP7; break;
+ case 0x75: DEST5_NOSHIFT; JUMP7; break;
+ case 0x76: DEST6_NOSHIFT; JUMP7; break;
+ case 0x77: DEST7_NOSHIFT; JUMP7; break;
+ case 0x7c: DEST4_SHIFT; JUMP7; break;
+ case 0x7d: DEST5_SHIFT; JUMP7; break;
+ case 0x7e: DEST6_SHIFT; JUMP7; break;
+ case 0x7f: DEST7_SHIFT; JUMP7; break;
+ }
+
+ /* Do write */
+ if (!(prevop->flags & FL_MBRW))
+ irmb_dout(prevop, Y);
+
+ /* ADDEN */
+ if (!(prevop->flags & FL_ADDEN))
+ {
+ if (prevop->flags & FL_MBRW)
+ irmb_latch = irmb_din(prevop);
+ else
+ irmb_latch = Y;
+ }
+ }
+ profiler_mark(PROFILER_END);
+
+ logerror("%d instructions for Mathbox \n", icount);
+
+
+#if IR_TIMING
+ if (irmb_running == 0)
+ {
+ timer_adjust(irmb_timer, attotime_mul(ATTOTIME_IN_HZ(12000000), icount), 0, attotime_zero);
+ logerror("mb start ");
+ IR_CPU_STATE;
+ }
+ else
+ {
+ logerror("mb start [busy!] ");
+ IR_CPU_STATE;
+ timer_adjust(irmb_timer, attotime_mul(ATTOTIME_IN_NSEC(200), icount), 0, attotime_zero);
+ }
+#else
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
+#endif
+ irmb_running=1;
+}
+
+
+
+
+#if DISASSEMBLE_MB_ROM
+static void disassemble_instruction(irmb_ops *op)
+{
+ int lp;
+
+ if (i==0)
+ logerror(" Address a b func stor: Q :Y, R, S RDCSAESM da m rs\n");
+ logerror("%04X : ",i);
+ logerror("%X ",op->areg);
+ logerror("%X ",op->breg);
+
+ lp=(op->func & 0x38)>>3;
+ if ((lp&1)==0)
+ lp|=1;
+ else if((op->flags & FL_DIV) != 0)
+ lp&=6;
+ else
+ logerror("*");
+
+ switch (lp)
+ {
+ case 0:
+ logerror("ADD ");
+ break;
+ case 1:
+ logerror("SUBR ");
+ break;
+ case 2:
+ logerror("SUB ");
+ break;
+ case 3:
+ logerror("OR ");
+ break;
+ case 4:
+ logerror("AND ");
+ break;
+ case 5:
+ logerror("AND ");
+ break;
+ case 6:
+ logerror("XOR ");
+ break;
+ case 7:
+ logerror("XNOR ");
+ break;
+ }
+
+ switch ((op->func & 0x1c0)>>6)
+ {
+ case 0:
+ logerror(" - : Q :F,");
+ break;
+ case 1:
+ logerror(" - : - :F,");
+ break;
+ case 2:
+ logerror(" R%x: - :A,",op->breg);
+ break;
+ case 3:
+ logerror(" R%x: - :F,",op->breg);
+ break;
+ case 4:
+ logerror(">>R%x:>>Q:F,",op->breg);
+ break;
+ case 5:
+ logerror(">>R%x: - :F,",op->breg);
+ break;
+ case 6:
+ logerror("<<R%x:<<Q:F,",op->breg);
+ break;
+ case 7:
+ logerror("<<R%x: - :F,",op->breg);
+ break;
+ }
+
+ lp=(op->func & 0x7);
+ if ((lp&2)==0)
+ lp|=2;
+ else if((op->flags & FL_MULT) == 0)
+ lp&=5;
+ else
+ logerror("*");
+
+ switch (lp)
+ {
+ case 0:
+ logerror("R%x, Q ",op->areg);
+ break;
+ case 1:
+ logerror("R%x,R%x ",op->areg,op->breg);
+ break;
+ case 2:
+ logerror("00, Q ");
+ break;
+ case 3:
+ logerror("00,R%x ",op->breg);
+ break;
+ case 4:
+ logerror("00,R%x ",op->areg);
+ break;
+ case 5:
+ logerror(" D,R%x ",op->areg);
+ break;
+ case 6:
+ logerror(" D, Q ");
+ break;
+ case 7:
+ logerror(" D,00 ");
+ break;
+ }
+
+ for (lp=0;lp<8;lp++)
+ if (op->flags & (0x80>>lp))
+ logerror("1");
+ else
+ logerror("0");
+
+ logerror(" %02X ",op->diradd);
+ logerror("%X\n",op->ramsel);
+ if (op->jtype)
+ {
+ logerror(" ");
+ switch (op->jtype)
+ {
+ case 1:
+ logerror("BO ");
+ break;
+ case 2:
+ logerror("BZ ");
+ break;
+ case 3:
+ logerror("BH ");
+ break;
+ case 4:
+ logerror("BL ");
+ break;
+ case 5:
+ logerror("B ");
+ break;
+ case 6:
+ logerror("Cl ");
+ break;
+ case 7:
+ logerror("Return\n\n");
+ break;
+ }
+ if (op->jtype != 7) logerror(" %04X \n",op->nxtadd);
+ if (op->jtype == 5) logerror("\n");
+ }
+ }
+}
+#endif
diff --git a/src/mame/machine/jackal.c b/src/mame/machine/jackal.c
new file mode 100644
index 00000000000..cc5539dcd9c
--- /dev/null
+++ b/src/mame/machine/jackal.c
@@ -0,0 +1,79 @@
+/***************************************************************************
+
+ machine.c
+
+ Written by Kenneth Lin (kenneth_lin@ai.vancouver.bc.ca)
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6809/m6809.h"
+
+extern UINT8 jackal_interrupt_enable;
+extern void jackal_mark_tile_dirty(int offset);
+
+UINT8 *jackal_rambank = 0;
+UINT8 *jackal_spritebank = 0;
+
+
+MACHINE_RESET( jackal )
+{
+ memory_set_bankptr(1,&((memory_region(REGION_CPU1))[0x4000]));
+ jackal_rambank = &((memory_region(REGION_CPU1))[0]);
+ jackal_spritebank = &((memory_region(REGION_CPU1))[0]);
+}
+
+
+
+READ8_HANDLER( jackal_zram_r )
+{
+ return jackal_rambank[0x0020+offset];
+}
+
+
+READ8_HANDLER( jackal_voram_r )
+{
+ return jackal_rambank[0x2000+offset];
+}
+
+
+READ8_HANDLER( jackal_spriteram_r )
+{
+ return jackal_spritebank[0x3000+offset];
+}
+
+
+WRITE8_HANDLER( jackal_rambank_w )
+{
+if (data & 0xc4) popmessage("jackal_rambank_w %02x",data);
+ coin_counter_w(0,data & 0x01);
+ coin_counter_w(1,data & 0x02);
+ jackal_rambank = &((memory_region(REGION_CPU1))[((data & 0x10) << 12)]);
+ jackal_spritebank = &((memory_region(REGION_CPU1))[((data & 0x08) << 13)]);
+ memory_set_bankptr(1,&((memory_region(REGION_CPU1))[((data & 0x20) << 11) + 0x4000]));
+}
+
+
+WRITE8_HANDLER( jackal_zram_w )
+{
+ jackal_rambank[0x0020+offset] = data;
+}
+
+
+WRITE8_HANDLER( jackal_voram_w )
+{
+ if ((offset & 0xF800) == 0)
+ {
+ jackal_mark_tile_dirty(offset & 0x3ff);
+ }
+ jackal_rambank[0x2000+offset] = data;
+}
+
+
+WRITE8_HANDLER( jackal_spriteram_w )
+{
+ jackal_spritebank[0x3000+offset] = data;
+}
diff --git a/src/mame/machine/jumpshot.c b/src/mame/machine/jumpshot.c
new file mode 100644
index 00000000000..587fee3b99b
--- /dev/null
+++ b/src/mame/machine/jumpshot.c
@@ -0,0 +1,56 @@
+#include "driver.h"
+#include "includes/pacman.h"
+
+
+static UINT8 decrypt(int addr, UINT8 e)
+{
+ static const UINT8 swap_xor_table[6][9] =
+ {
+ { 7,6,5,4,3,2,1,0, 0x00 },
+ { 7,6,3,4,5,2,1,0, 0x20 },
+ { 5,0,4,3,7,1,2,6, 0xa4 },
+ { 5,0,4,3,7,1,2,6, 0x8c },
+ { 2,3,1,7,4,6,0,5, 0x6e },
+ { 2,3,4,7,1,6,0,5, 0x4e }
+ };
+ static const int picktable[32] =
+ {
+ 0,2,4,4,4,2,0,2,2,0,2,4,4,2,0,2,
+ 5,3,5,1,5,3,5,3,1,5,1,5,5,3,5,3
+ };
+ UINT32 method = 0;
+ const UINT8 *tbl;
+
+
+ /* pick method from bits 0 2 5 7 9 of the address */
+ method = picktable[
+ (addr & 0x001) |
+ ((addr & 0x004) >> 1) |
+ ((addr & 0x020) >> 3) |
+ ((addr & 0x080) >> 4) |
+ ((addr & 0x200) >> 5)];
+
+ /* switch method if bit 11 of the address is set */
+ if ((addr & 0x800) == 0x800)
+ method ^= 1;
+
+ tbl = swap_xor_table[method];
+ return BITSWAP8(e,tbl[0],tbl[1],tbl[2],tbl[3],tbl[4],tbl[5],tbl[6],tbl[7]) ^ tbl[8];
+}
+
+
+void jumpshot_decode(void)
+{
+ int i;
+ UINT8 *RAM;
+
+ /* CPU ROMs */
+
+ RAM = memory_region(REGION_CPU1);
+ for (i = 0; i < 0x4000; i++)
+ {
+ RAM[i] = decrypt(i,RAM[i]);
+ }
+}
+
+
diff --git a/src/mame/machine/kabuki.c b/src/mame/machine/kabuki.c
new file mode 100644
index 00000000000..13dd5c2f1b8
--- /dev/null
+++ b/src/mame/machine/kabuki.c
@@ -0,0 +1,214 @@
+/***************************************************************************
+
+"Kabuki" Z80 encryption
+
+
+The "Kabuki" is a custom Z80 module which runs encrypted code. The encryption
+key is stored in some battery-backed RAM, therefore the chip has the annoying
+habit of stopping working every few years, when the battery dies.
+
+The suicide battery supplies power to pin 28. When you remove the battery, if
+you pull pin 28 low, the Kabuki will behave like a normal Z80.
+
+
+Check at the bottom of this text to see a list of all the known games which
+use this chip.
+
+
+How it works:
+The base operation is a bit swap which affects couples of adjacent bits.
+Each of the 4 couples may or may not be swapped, depending on the address of
+the byte and on whether it is an opcode or data.
+The decryption consists of these steps:
+- bitswap
+- ROL
+- bitswap
+- XOR with a key
+- ROL
+- bitswap
+- ROL
+- bitswap
+
+To know how to apply the bit swap, take the address of the byte to decode and:
+- if the byte is an opcode, add addr_key to the address
+- if the byte is data, XOR the address with 1FC0, add 1, and then add addr_key
+You'll get a 16-bit word. The first two bitswaps depend on bits 0-7 of that
+word, while the second two on bits 8-15. When a bit in the word is 1, swap the
+two bits, otherwise don't. The exact couple of bits affected depends on the
+game and is identified in this file with two keys: swap_key1 and swap_key2
+(which are just permutations of the numbers 0-7, not full 32-bit integers).
+
+
+Key space size:
+- swap_key1 8! = 40320
+- swap_key2 8! = 40320
+- addr_key 2^16 = 65536
+- xor_key 2^8 = 256
+- total 2.7274 * 10^16
+
+
+Weaknesses:
+- 0x00 and 0xff, having all the bits set to the same value, are not affected
+ by bit permutations after the XOR. Therefore, their encryption is the same
+ regardless of the high 8 bits of the address, and of the value of
+ swap_key2. If there is a long stream of 0x00 or 0xff in the original data,
+ this can be used to find by brute force all the candidates for swap_key1,
+ xor_key, and for the low 8 bits of addr_key. This is a serious weakness
+ which dramatically reduces the security of the encryption.
+- A 0x00 is always encrypted as a byte with as many 1s as xor_key; a 0xff is
+ always encrypted as a byte with as many 0s as xor_key has 1s. So you just
+ need to know one 0x00 or 0xff in the unencrypted data to know how many 1s
+ there are in xor_key.
+- Once you have restricted the range for swap_key1 and you know the number of
+ 1s in the xor_key, you can easily use known plaintext attacks and brute
+ force to find the remaining keys. Long strings like THIS GAME IS FOR USE IN
+ and ABCDEFGHIJKLMNOPQRSTUVWXYZ can be found by comparing the number of 1s
+ in the clear and encrypted data, taking xor_key into account. When you have
+ found where the string is, use brute force to reduce the key space.
+
+
+Known games:
+ swap_key1 swap_key2 addr_key xor_key
+Mahjong Gakuen 2 Gakuen-chou no Fukushuu 76543210 01234567 aa55 a5
+Poker Ladies " " " " "" ""
+Dokaben " " " " "" ""
+Dokaben 2 unknown
+Pang / Buster Bros / Pomping World 01234567 76543210 6548 24
+Capcom Baseball " " " " "" ""
+Capcom World 04152637 40516273 5751 43
+Adventure Quiz 2 Hatena ? no Dai-Bouken 45670123 45670123 5751 43
+Super Pang (World) 45670123 45670123 5852 43
+Super Pang (Japan) 45123670 67012345 55aa 5a
+Super Buster Bros 45670123 45670123 2130 12
+Super Marukin-Ban 54321076 54321076 4854 4f
+Quiz Tonosama no Yabou 12345670 12345670 1111 11
+Ashita Tenki ni Naare unknown
+Quiz Sangokushi 23456701 23456701 1828 18
+Block Block 02461357 64207531 0002 01
+
+Warriors of Fate 01234567 54163072 5151 51
+Cadillacs and Dinosaurs 76543210 24601357 4343 43
+Punisher 67452103 75316024 2222 22
+Slam Masters 54321076 65432107 3131 19
+
+***************************************************************************/
+
+#include "driver.h"
+#include "includes/cps1.h"
+
+
+
+static int bitswap1(int src,int key,int select)
+{
+ if (select & (1 << ((key >> 0) & 7)))
+ src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
+ if (select & (1 << ((key >> 4) & 7)))
+ src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
+ if (select & (1 << ((key >> 8) & 7)))
+ src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
+ if (select & (1 << ((key >>12) & 7)))
+ src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
+
+ return src;
+}
+
+static int bitswap2(int src,int key,int select)
+{
+ if (select & (1 << ((key >>12) & 7)))
+ src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
+ if (select & (1 << ((key >> 8) & 7)))
+ src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
+ if (select & (1 << ((key >> 4) & 7)))
+ src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
+ if (select & (1 << ((key >> 0) & 7)))
+ src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
+
+ return src;
+}
+
+static int bytedecode(int src,int swap_key1,int swap_key2,int xor_key,int select)
+{
+ src = bitswap1(src,swap_key1 & 0xffff,select & 0xff);
+ src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
+ src = bitswap2(src,swap_key1 >> 16,select & 0xff);
+ src ^= xor_key;
+ src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
+ src = bitswap2(src,swap_key2 & 0xffff,select >> 8);
+ src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
+ src = bitswap1(src,swap_key2 >> 16,select >> 8);
+ return src;
+}
+
+static void kabuki_decode(UINT8 *src,UINT8 *dest_op,UINT8 *dest_data,
+ int base_addr,int length,int swap_key1,int swap_key2,int addr_key,int xor_key)
+{
+ int A;
+ int select;
+
+ for (A = 0;A < length;A++)
+ {
+ /* decode opcodes */
+ select = (A + base_addr) + addr_key;
+ dest_op[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,select);
+
+ /* decode data */
+ select = ((A + base_addr) ^ 0x1fc0) + addr_key + 1;
+ dest_data[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,select);
+ }
+}
+
+
+
+static void mitchell_decode(int swap_key1,int swap_key2,int addr_key,int xor_key)
+{
+ UINT8 *rom = memory_region(REGION_CPU1);
+ UINT8 *decrypt = auto_malloc(memory_region_length(REGION_CPU1));
+ int numbanks = (memory_region_length(REGION_CPU1) - 0x10000) / 0x4000;
+ int i;
+
+ memory_set_decrypted_region(0, 0x0000, 0x7fff, decrypt);
+ kabuki_decode(rom,decrypt,rom,0x0000,0x8000, swap_key1,swap_key2,addr_key,xor_key);
+
+ rom += 0x10000;
+ decrypt += 0x10000;
+ for (i = 0; i < numbanks; i++)
+ kabuki_decode(rom+i*0x4000,decrypt+i*0x4000,rom+i*0x4000,0x8000,0x4000, swap_key1,swap_key2,addr_key,xor_key);
+
+ memory_configure_bank_decrypted(1, 0, numbanks, decrypt, 0x4000);
+/*
+ {
+ FILE *f;
+ f = fopen("a","wb");
+ fwrite(rom,1,0x8000,f);
+ fwrite(rom+0x10000,1,0x40000,f);
+ fclose(f);
+ }
+*/
+}
+
+void mgakuen2_decode(void) { mitchell_decode(0x76543210,0x01234567,0xaa55,0xa5); }
+void pang_decode(void) { mitchell_decode(0x01234567,0x76543210,0x6548,0x24); }
+void cworld_decode(void) { mitchell_decode(0x04152637,0x40516273,0x5751,0x43); }
+void hatena_decode(void) { mitchell_decode(0x45670123,0x45670123,0x5751,0x43); }
+void spang_decode(void) { mitchell_decode(0x45670123,0x45670123,0x5852,0x43); }
+void spangj_decode(void) { mitchell_decode(0x45123670,0x67012345,0x55aa,0x5a); }
+void sbbros_decode(void) { mitchell_decode(0x45670123,0x45670123,0x2130,0x12); }
+void marukin_decode(void) { mitchell_decode(0x54321076,0x54321076,0x4854,0x4f); }
+void qtono1_decode(void) { mitchell_decode(0x12345670,0x12345670,0x1111,0x11); }
+void qsangoku_decode(void) { mitchell_decode(0x23456701,0x23456701,0x1828,0x18); }
+void block_decode(void) { mitchell_decode(0x02461357,0x64207531,0x0002,0x01); }
+
+
+static void cps1_decode(int swap_key1,int swap_key2,int addr_key,int xor_key)
+{
+ UINT8 *decrypt = auto_malloc(0x8000);
+ UINT8 *rom = memory_region(REGION_CPU2);
+
+ memory_set_decrypted_region(1, 0x0000, 0x7fff, decrypt);
+ kabuki_decode(rom,decrypt,rom,0x0000,0x8000, swap_key1,swap_key2,addr_key,xor_key);
+}
+
+void wof_decode(void) { cps1_decode(0x01234567,0x54163072,0x5151,0x51); }
+void dino_decode(void) { cps1_decode(0x76543210,0x24601357,0x4343,0x43); }
+void punisher_decode(void) { cps1_decode(0x67452103,0x75316024,0x2222,0x22); }
+void slammast_decode(void) { cps1_decode(0x54321076,0x65432107,0x3131,0x19); }
diff --git a/src/mame/machine/kaneko16.c b/src/mame/machine/kaneko16.c
new file mode 100644
index 00000000000..bf3b6657df2
--- /dev/null
+++ b/src/mame/machine/kaneko16.c
@@ -0,0 +1,893 @@
+/***************************************************************************
+
+
+ MCU Code Simulation
+
+ CALC1 is a 40 pin DIP MCU of unknown type with unknown internal rom
+ CALC3 is a NEC uPD78322 series MCU with 16K internal rom & 640 bytes of ram
+TBSOP01 is a NEC uPD78324 series MCU with 32K internal rom & 1024 bytes of ram
+TBSOP02 is likely the same NEC uPD78324 series MCU as the TBS0P01
+
+Currently none of the MCUs' internal roms are dumped so simulation is used
+
+***************************************************************************/
+
+#include "driver.h"
+#include "includes/kaneko16.h"
+
+#include "kanekotb.h" // TOYBOX MCU trojaning results
+
+#define MCU_RESPONSE(d) memcpy(&kaneko16_mcu_ram[mcu_offset], d, sizeof(d))
+
+UINT16 *kaneko16_mcu_ram;
+
+/***************************************************************************
+ Gals Panic (set 2)
+ Gals Panic (set 3)
+ Sand Scorpion
+ Bonk's Adventure
+ Blood Warrior
+***************************************************************************/
+
+/*
+ - see notes about this "calculator" implementation in drivers\galpanic.c
+ - bonkadv only uses Random Number, XY Overlap Collision bit and register '0x02'
+*/
+
+static struct {
+ UINT16 x1p, y1p, x1s, y1s;
+ UINT16 x2p, y2p, x2s, y2s;
+
+ INT16 x12, y12, x21, y21;
+
+ UINT16 mult_a, mult_b;
+} hit;
+
+READ16_HANDLER(galpanib_calc_r) /* Simulation of the CALC1 MCU */
+{
+ UINT16 data = 0;
+
+ switch (offset)
+ {
+ case 0x00/2: // watchdog
+ return watchdog_reset_r(0);
+
+ case 0x02/2: // unknown (yet!), used by *MANY* games !!!
+ //popmessage("unknown collision reg");
+ break;
+
+ case 0x04/2: // similar to the hit detection from SuperNova, but much simpler
+
+ // X Absolute Collision
+ if (hit.x1p > hit.x2p) data |= 0x0200;
+ else if (hit.x1p == hit.x2p) data |= 0x0400;
+ else if (hit.x1p < hit.x2p) data |= 0x0800;
+
+ // Y Absolute Collision
+ if (hit.y1p > hit.y2p) data |= 0x2000;
+ else if (hit.y1p == hit.y2p) data |= 0x4000;
+ else if (hit.y1p < hit.y2p) data |= 0x8000;
+
+ // XY Overlap Collision
+ hit.x12 = (hit.x1p) - (hit.x2p + hit.x2s);
+ hit.y12 = (hit.y1p) - (hit.y2p + hit.y2s);
+ hit.x21 = (hit.x1p + hit.x1s) - (hit.x2p);
+ hit.y21 = (hit.y1p + hit.y1s) - (hit.y2p);
+
+ if ((hit.x12 < 0) && (hit.y12 < 0) &&
+ (hit.x21 >= 0) && (hit.y21 >= 0))
+ data |= 0x0001;
+
+ return data;
+
+ case 0x10/2:
+ return (((UINT32)hit.mult_a * (UINT32)hit.mult_b) >> 16);
+ case 0x12/2:
+ return (((UINT32)hit.mult_a * (UINT32)hit.mult_b) & 0xffff);
+
+ case 0x14/2:
+ return (mame_rand(Machine) & 0xffff);
+
+ default:
+ logerror("CPU #0 PC %06x: warning - read unmapped calc address %06x\n",activecpu_get_pc(),offset<<1);
+ }
+
+ return 0;
+}
+
+WRITE16_HANDLER(galpanib_calc_w)
+{
+ switch (offset)
+ {
+ // p is position, s is size
+ case 0x00/2: hit.x1p = data; break;
+ case 0x02/2: hit.x1s = data; break;
+ case 0x04/2: hit.y1p = data; break;
+ case 0x06/2: hit.y1s = data; break;
+ case 0x08/2: hit.x2p = data; break;
+ case 0x0a/2: hit.x2s = data; break;
+ case 0x0c/2: hit.y2p = data; break;
+ case 0x0e/2: hit.y2s = data; break;
+ case 0x10/2: hit.mult_a = data; break;
+ case 0x12/2: hit.mult_b = data; break;
+
+ default:
+ logerror("CPU #0 PC %06x: warning - write unmapped hit address %06x\n",activecpu_get_pc(),offset<<1);
+ }
+}
+
+WRITE16_HANDLER(bloodwar_calc_w)
+{
+ switch (offset)
+ {
+ // p is position, s is size
+ case 0x20/2: hit.x1p = data; break;
+ case 0x22/2: hit.x1s = data; break;
+ case 0x24/2: hit.y1p = data; break;
+ case 0x26/2: hit.y1s = data; break;
+
+ case 0x2c/2: hit.x2p = data; break;
+ case 0x2e/2: hit.x2s = data; break;
+ case 0x30/2: hit.y2p = data; break;
+ case 0x32/2: hit.y2s = data; break;
+
+ // this register is set to zero before any computation,
+ // but it has no effect on inputs or result registers
+ case 0x38/2: break;
+
+ default:
+ logerror("CPU #0 PC %06x: warning - write unmapped hit address %06x\n",activecpu_get_pc(),offset<<1);
+ }
+}
+
+/*
+ collision detection: absolute "distance", negative if no overlap
+ [one inside other] | [ normal overlap ] | [ no overlap ]
+ rect1 <--------------> | <-----------> | <--->
+ rect2 <-----> | <-----------> | <--->
+ result <----------> | <--------> | <---->
+*/
+static INT16 calc_compute_x(void)
+{
+ INT16 x_coll;
+
+ // X distance
+ if ((hit.x2p >= hit.x1p) && (hit.x2p < (hit.x1p + hit.x1s))) // x2p inside x1
+ x_coll = (hit.x1s - (hit.x2p - hit.x1p));
+ else if ((hit.x1p >= hit.x2p) && (hit.x1p < (hit.x2p + hit.x2s))) // x1p inside x2
+ x_coll = (hit.x2s - (hit.x1p - hit.x2p));
+ else // normal/no overlap
+ x_coll = ((hit.x1s + hit.x2s)/2) - abs((hit.x1p + hit.x1s/2) - (hit.x2p + hit.x2s/2));
+
+ return x_coll;
+}
+static INT16 calc_compute_y(void)
+{
+ INT16 y_coll;
+
+ // Y distance
+ if ((hit.y2p >= hit.y1p) && (hit.y2p < (hit.y1p + hit.y1s))) // y2p inside y1
+ y_coll = (hit.y1s - (hit.y2p - hit.y1p));
+ else if ((hit.y1p >= hit.y2p) && (hit.y1p < (hit.y2p + hit.y2s))) // y1p inside y2
+ y_coll = (hit.y2s - (hit.y1p - hit.y2p));
+ else // normal/no overlap
+ y_coll = ((hit.y1s + hit.y2s)/2) - abs((hit.y1p + hit.y1s/2) - (hit.y2p + hit.y2s/2));
+
+ return y_coll;
+}
+
+READ16_HANDLER(bloodwar_calc_r)
+{
+ UINT16 data = 0;
+ INT16 x_coll, y_coll;
+
+ x_coll = calc_compute_x();
+ y_coll = calc_compute_y();
+
+ switch (offset)
+ {
+ case 0x00/2: // X distance
+ return x_coll;
+
+ case 0x02/2: // Y distance
+ return y_coll;
+
+ case 0x04/2: // similar to the hit detection from SuperNova, but much simpler
+
+ // 4th nibble: Y Absolute Collision -> possible values = 9,8,4,3,2
+ if (hit.y1p > hit.y2p) data |= 0x2000;
+ else if (hit.y1p == hit.y2p) data |= 0x4000;
+ else if (hit.y1p < hit.y2p) data |= 0x8000;
+ if (y_coll<0) data |= 0x1000;
+
+ // 3rd nibble: X Absolute Collision -> possible values = 9,8,4,3,2
+ if (hit.x1p > hit.x2p) data |= 0x0200;
+ else if (hit.x1p == hit.x2p) data |= 0x0400;
+ else if (hit.x1p < hit.x2p) data |= 0x0800;
+ if (x_coll<0) data |= 0x0100;
+
+ // 2nd nibble: always set to 4
+ data |= 0x0040;
+
+ // 1st nibble: XY Overlap Collision -> possible values = 0,2,4,f
+ if (x_coll>=0) data |= 0x0004;
+ if (y_coll>=0) data |= 0x0002;
+ if ((x_coll>=0)&&(y_coll>=0)) data |= 0x000F;
+
+ return data;
+
+ case 0x14/2:
+ return (mame_rand(Machine) & 0xffff);
+
+ case 0x20/2: return hit.x1p;
+ case 0x22/2: return hit.x1s;
+ case 0x24/2: return hit.y1p;
+ case 0x26/2: return hit.y1s;
+
+ case 0x2c/2: return hit.x2p;
+ case 0x2e/2: return hit.x2s;
+ case 0x30/2: return hit.y2p;
+ case 0x32/2: return hit.y2s;
+
+ default:
+ logerror("CPU #0 PC %06x: warning - read unmapped calc address %06x\n",activecpu_get_pc(),offset<<1);
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+ CALC3 MCU:
+
+ Shogun Warriors
+ Fujiyama Buster
+ B.Rap Boys
+***************************************************************************/
+/*
+---------------------------------------------------------------------------
+ CALC 3
+
+92 B.Rap Boys KANEKO CALC3 508 (74 PIN PQFP)
+92 Shogun Warriors
+ Fujiyama Buster KANEKO CALC3 508 (74 Pin PQFP)
+---------------------------------------------------------------------------
+
+MCU Initialization command:
+
+shogwarr: CPU #0 PC 00037A : MCU executed command: 00FF 0059 019E 030A FFFE 0042 0020 7FE0
+fjbuster: CPU #0 PC 00037A : MCU executed command: 00FF 0059 019E 030A FFFE 0042 0020 7FE0
+brapboys: CPU #0 PC 000BAE : MCU executed command: 00FF 00C2 0042 0830 082E 00C8 0020 0872
+
+shogwarr/fjbuster:
+
+00FF : busy flag, MCU clears it when cmd finished (main program loops until it's cleared)
+0059 : MCU writes DSW -> $102e15
+019E : ??? -> $102e14, compared with -1 once, very interesting, see $1063e6 - IT2
+030A : location where MCU will get its parameters from now on
+FFFE : probably polled by MCU, needs to be kept alive (cleared by main cpu - IT2)
+0042 : MCU writes its checksum
+00207FE0 : may serves for relocating code (written as .l)
+*/
+
+static void calc3_mcu_run(void);
+
+static int calc3_mcu_status, calc3_mcu_command_offset;
+
+
+void calc3_mcu_init(void)
+{
+ calc3_mcu_status = 0;
+ calc3_mcu_command_offset = 0;
+}
+
+WRITE16_HANDLER( calc3_mcu_ram_w )
+{
+ COMBINE_DATA(&kaneko16_mcu_ram[offset]);
+ calc3_mcu_run();
+}
+
+#define CALC3_MCU_COM_W(_n_) \
+WRITE16_HANDLER( calc3_mcu_com##_n_##_w ) \
+{ \
+ calc3_mcu_status |= (1 << _n_); \
+ calc3_mcu_run(); \
+}
+
+CALC3_MCU_COM_W(0)
+CALC3_MCU_COM_W(1)
+CALC3_MCU_COM_W(2)
+CALC3_MCU_COM_W(3)
+
+/***************************************************************************
+ Shogun Warriors
+***************************************************************************/
+
+/* Preliminary simulation: the game doesn't work */
+
+/*
+ MCU Tasks:
+
+ - Read the DSWs
+ - Supply code snippets to the 68000
+*/
+
+void calc3_mcu_run(void)
+{
+ UINT16 mcu_command;
+
+ if ( calc3_mcu_status != (1|2|4|8) ) return;
+
+ mcu_command = kaneko16_mcu_ram[calc3_mcu_command_offset + 0];
+
+ if (mcu_command == 0) return;
+
+ logerror("CPU #0 PC %06X : MCU executed command at %04X: %04X\n",
+ activecpu_get_pc(),calc3_mcu_command_offset*2,mcu_command);
+
+ switch (mcu_command)
+ {
+
+ case 0x00ff:
+ {
+ int param1 = kaneko16_mcu_ram[calc3_mcu_command_offset + 1];
+ int param2 = kaneko16_mcu_ram[calc3_mcu_command_offset + 2];
+ int param3 = kaneko16_mcu_ram[calc3_mcu_command_offset + 3];
+ //int param4 = kaneko16_mcu_ram[calc3_mcu_command_offset + 4];
+ int param5 = kaneko16_mcu_ram[calc3_mcu_command_offset + 5];
+ //int param6 = kaneko16_mcu_ram[calc3_mcu_command_offset + 6];
+ //int param7 = kaneko16_mcu_ram[calc3_mcu_command_offset + 7];
+
+ // clear old command (handshake to main cpu)
+ kaneko16_mcu_ram[calc3_mcu_command_offset] = 0x0000;
+
+ // execute the command:
+
+ kaneko16_mcu_ram[param1 / 2] = ~readinputport(4); // DSW
+ kaneko16_mcu_ram[param2 / 2] = 0xffff; // ? -1 / anything else
+
+ calc3_mcu_command_offset = param3 / 2; // where next command will be written?
+ // param 4?
+ kaneko16_mcu_ram[param5 / 2] = 0x8ee4; // MCU Rom Checksum!
+ // param 6&7 = address.l
+
+/*
+
+First code snippet provided by the MCU:
+
+207FE0: 48E7 FFFE movem.l D0-D7/A0-A6, -(A7)
+
+207FE4: 3039 00A8 0000 move.w $a80000.l, D0
+207FEA: 4279 0020 FFFE clr.w $20fffe.l
+
+207FF0: 41F9 0020 0000 lea $200000.l, A0
+207FF6: 7000 moveq #$0, D0
+
+207FF8: 43E8 01C6 lea ($1c6,A0), A1
+207FFC: 7E02 moveq #$2, D7
+207FFE: D059 add.w (A1)+, D0
+208000: 51CF FFFC dbra D7, 207ffe
+
+208004: 43E9 0002 lea ($2,A1), A1
+208008: 7E04 moveq #$4, D7
+20800A: D059 add.w (A1)+, D0
+20800C: 51CF FFFC dbra D7, 20800a
+
+208010: 4640 not.w D0
+208012: 5340 subq.w #1, D0
+208014: 0068 0030 0216 ori.w #$30, ($216,A0)
+
+20801A: B07A 009A cmp.w ($9a,PC), D0; ($2080b6)
+20801E: 670A beq 20802a
+
+208020: 0268 000F 0216 andi.w #$f, ($216,A0)
+208026: 4268 0218 clr.w ($218,A0)
+
+20802A: 5468 0216 addq.w #2, ($216,A0)
+20802E: 42A8 030C clr.l ($30c,A0)
+208032: 117C 0020 030C move.b #$20, ($30c,A0)
+
+208038: 3E3C 0001 move.w #$1, D7
+
+20803C: 0C68 0008 0218 cmpi.w #$8, ($218,A0)
+208042: 6C00 0068 bge 2080ac
+
+208046: 117C 0080 0310 move.b #$80, ($310,A0)
+20804C: 117C 0008 0311 move.b #$8, ($311,A0)
+208052: 317C 7800 0312 move.w #$7800, ($312,A0)
+208058: 5247 addq.w #1, D7
+20805A: 0C68 0040 0216 cmpi.w #$40, ($216,A0)
+208060: 6D08 blt 20806a
+
+208062: 5468 0218 addq.w #2, ($218,A0)
+208066: 6000 0044 bra 2080ac
+
+20806A: 117C 0041 0314 move.b #$41, ($314,A0)
+
+208070: 0C39 0001 0010 2E12 cmpi.b #$1, $102e12.l
+208078: 6606 bne 208080
+
+20807A: 117C 0040 0314 move.b #$40, ($314,A0)
+
+208080: 117C 000C 0315 move.b #$c, ($315,A0)
+208086: 317C 7000 0316 move.w #$7000, ($316,A0)
+20808C: 5247 addq.w #1, D7
+
+20808E: 0839 0001 0010 2E15 btst #$1, $102e15.l ; service mode
+208096: 6714 beq 2080ac
+
+208098: 117C 0058 0318 move.b #$58, ($318,A0)
+20809E: 117C 0006 0319 move.b #$6, ($319,A0)
+2080A4: 317C 6800 031A move.w #$6800, ($31a,A0)
+2080AA: 5247 addq.w #1, D7
+
+2080AC: 3147 030A move.w D7, ($30a,A0)
+2080B0: 4CDF 7FFF movem.l (A7)+, D0-D7/A0-A6
+2080B4: 4E73 rte
+
+2080B6: C747
+*/
+ }
+ break;
+
+
+ case 0x0001:
+ {
+ //int param1 = kaneko16_mcu_ram[calc3_mcu_command_offset + 1];
+ int param2 = kaneko16_mcu_ram[calc3_mcu_command_offset + 2];
+
+ // clear old command (handshake to main cpu)
+ kaneko16_mcu_ram[calc3_mcu_command_offset] = 0x0000;
+
+ // execute the command:
+
+ // param1 ?
+ kaneko16_mcu_ram[param2/2 + 0] = 0x0000; // ?
+ kaneko16_mcu_ram[param2/2 + 1] = 0x0000; // ?
+ kaneko16_mcu_ram[param2/2 + 2] = 0x0000; // ?
+ kaneko16_mcu_ram[param2/2 + 3] = 0x0000; // ? addr.l
+ kaneko16_mcu_ram[param2/2 + 4] = 0x00e0; // 0000e0: 4e73 rte
+
+ }
+ break;
+
+
+ case 0x0002:
+ {
+ //int param1 = kaneko16_mcu_ram[calc3_mcu_command_offset + 1];
+ //int param2 = kaneko16_mcu_ram[calc3_mcu_command_offset + 2];
+ //int param3 = kaneko16_mcu_ram[calc3_mcu_command_offset + 3];
+ //int param4 = kaneko16_mcu_ram[calc3_mcu_command_offset + 4];
+ //int param5 = kaneko16_mcu_ram[calc3_mcu_command_offset + 5];
+ //int param6 = kaneko16_mcu_ram[calc3_mcu_command_offset + 6];
+ //int param7 = kaneko16_mcu_ram[calc3_mcu_command_offset + 7];
+
+ // clear old command (handshake to main cpu)
+ kaneko16_mcu_ram[calc3_mcu_command_offset] = 0x0000;
+
+ // execute the command:
+
+ }
+ break;
+
+ }
+
+}
+
+
+/***************************************************************************
+ TOYBOX MCU:
+
+ Bonk's Adventure
+ Blood Warrior
+ Great 1000 Miles Rally
+ ...
+***************************************************************************/
+/*
+---------------------------------------------------------------------------
+ TOYBOX
+
+94 Bonk's Adventure TOYBOX? TBSOP01
+94 Blood Warrior TOYBOX? TBS0P01 452 9339PK001
+94 Great 1000 Miles Rally TOYBOX "MM0525-TOYBOX199","USMM0713-TB1994 "
+95 Great 1000 Miles Rally 2 TOYBOX KANEKO TBSOP02 454 9451MK002 (74 pin PQFP) "USMM0713-TB1994 "
+95 Jackie Chan TOYBOX "USMM0713-TB1994 "
+95 Gals Panic 3 TOYBOX? TBSOP01
+---------------------------------------------------------------------------
+
+All the considerations are based on the analysis of jchan, and to a fewer extent galpani3, and make references to the current driver sources:
+
+MCU triggering:
+---------------
+
+the 4 JCHAN_MCU_COM_W(...) are in fact 2 groups:
+
+AM_RANGE(0x330000, 0x330001) AM_WRITE(jchan_mcu_com0_w) // _[ these 2 are set to 0xFFFF
+AM_RANGE(0x340000, 0x340001) AM_WRITE(jchan_mcu_com1_w) // [ for MCU to execute cmd
+
+AM_RANGE(0x350000, 0x350001) AM_WRITE(jchan_mcu_com2_w) // _[ these 2 are set to 0xFFFF
+AM_RANGE(0x360000, 0x360001) AM_WRITE(jchan_mcu_com3_w) // [ for MCU to return its status
+
+
+MCU parameters:
+---------------
+
+mcu_command = kaneko16_mcu_ram[0x0010/2]; // command nb
+mcu_offset = kaneko16_mcu_ram[0x0012/2]/2; // offset in shared RAM where MCU will write
+mcu_subcmd = kaneko16_mcu_ram[0x0014/2]; // sub-command parameter, happens only for command #4
+
+
+ the only MCU commands found in program code are:
+ - 0x04: protection: provide data (see below) and code <<<---!!!
+ - 0x03: read DSW
+ - 0x02: load game settings \ stored in ATMEL AT93C46 chip,
+ - 0x42: save game settings / 128 bytes serial EEPROM
+
+
+Current feeling of devs is that this EEPROM might also play a role in the protection scheme,
+but I (SV) feel that it is very unlikely because of the following, which has been verified:
+if the checksum test fails at most 3 times, then the initial settings, stored in main68k ROM,
+are loaded in RAM then saved with cmd 0x42 (see code @ $5196 & $50d4)
+Note that this is valid for jchan only, other games haven't been looked at.
+
+Others:
+-------
+
+There is one interesting MCU cmd $4 in jchan:
+-> sub-cmd $3d, MCU writes the string "USMM0713-TB1994 "
+
+The very same string is written by gtmr games (gtmre/gtmrusa/gtmr2) but apparently with no sub-cmd: this string is
+probably the MCU model string, so this one should be in internal MCU ROM (another one for gtmr is "MM0525-TOYBOX199")
+
+TODO: look at this one since this remark is only driver-based.
+*/
+
+void (*toybox_mcu_run)(void); /* One of the following */
+void bloodwar_mcu_run(void);
+void bonkadv_mcu_run(void);
+void gtmr_mcu_run(void);
+
+static UINT16 toybox_mcu_com[4];
+
+void toybox_mcu_init(void)
+{
+ memset(toybox_mcu_com, 0, 4 * sizeof( UINT16) );
+}
+
+#define TOYBOX_MCU_COM_W(_n_) \
+WRITE16_HANDLER( toybox_mcu_com##_n_##_w ) \
+{ \
+ COMBINE_DATA(&toybox_mcu_com[_n_]); \
+ if (toybox_mcu_com[0] != 0xFFFF) return; \
+ if (toybox_mcu_com[1] != 0xFFFF) return; \
+ if (toybox_mcu_com[2] != 0xFFFF) return; \
+ if (toybox_mcu_com[3] != 0xFFFF) return; \
+ \
+ memset(toybox_mcu_com, 0, 4 * sizeof( UINT16 ) ); \
+ toybox_mcu_run(); \
+}
+
+TOYBOX_MCU_COM_W(0)
+TOYBOX_MCU_COM_W(1)
+TOYBOX_MCU_COM_W(2)
+TOYBOX_MCU_COM_W(3)
+
+/*
+ bonkadv and bloodwar test bit 0
+*/
+READ16_HANDLER( toybox_mcu_status_r )
+{
+ logerror("CPU #%d (PC=%06X) : read MCU status\n", cpu_getactivecpu(), activecpu_get_previouspc());
+ return 0; // most games test bit 0 for failure
+}
+
+
+/***************************************************************************
+ Blood Warrior
+***************************************************************************/
+
+void bloodwar_mcu_run(void)
+{
+ UINT16 mcu_command = kaneko16_mcu_ram[0x0010/2];
+ UINT16 mcu_offset = kaneko16_mcu_ram[0x0012/2] / 2;
+ UINT16 mcu_data = kaneko16_mcu_ram[0x0014/2];
+
+ switch (mcu_command >> 8)
+ {
+ case 0x02: // Read from NVRAM
+ {
+ mame_file *f;
+ if ((f = nvram_fopen(Machine, OPEN_FLAG_READ)) != 0)
+ {
+ mame_fread(f,&kaneko16_mcu_ram[mcu_offset], 128);
+ mame_fclose(f);
+ }
+ logerror("PC=%06X : MCU executed command: %04X %04X (load NVRAM settings)\n", activecpu_get_pc(), mcu_command, mcu_offset*2);
+ }
+ break;
+
+ case 0x42: // Write to NVRAM
+ {
+ mame_file *f;
+ if ((f = nvram_fopen(Machine, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS)) != 0)
+ {
+ mame_fwrite(f,&kaneko16_mcu_ram[mcu_offset], 128);
+ mame_fclose(f);
+ }
+ logerror("PC=%06X : MCU executed command: %04X %04X (save NVRAM settings)\n", activecpu_get_pc(), mcu_command, mcu_offset*2);
+ }
+ break;
+
+ case 0x03: // DSW
+ {
+ kaneko16_mcu_ram[mcu_offset] = readinputport(4);
+ logerror("PC=%06X : MCU executed command: %04X %04X (read DSW)\n", activecpu_get_pc(), mcu_command, mcu_offset*2);
+ }
+ break;
+
+ case 0x04: // Protection
+ {
+ logerror("PC=%06X : MCU executed command: %04X %04X %04X\n", activecpu_get_pc(), mcu_command, mcu_offset*2, mcu_data);
+
+ switch(mcu_data)
+ {
+ // unknown purpose data
+ case 0x01: MCU_RESPONSE(bloodwar_mcu_4_01); break; // Warrior 1
+ case 0x02: MCU_RESPONSE(bloodwar_mcu_4_02); break; // Warrior 2
+ case 0x03: MCU_RESPONSE(bloodwar_mcu_4_03); break; // Warrior 3
+ case 0x04: MCU_RESPONSE(bloodwar_mcu_4_04); break; // Warrior 4
+ case 0x05: MCU_RESPONSE(bloodwar_mcu_4_05); break; // Warrior 5
+ case 0x06: MCU_RESPONSE(bloodwar_mcu_4_06); break; // Warrior 6
+ case 0x07: MCU_RESPONSE(bloodwar_mcu_4_07); break; // Warrior 7
+ case 0x08: MCU_RESPONSE(bloodwar_mcu_4_08); break; // Warrior 8
+ case 0x09: MCU_RESPONSE(bloodwar_mcu_4_09); break; // Warrior 9
+
+ // palette data
+ case 0x0a: MCU_RESPONSE(bloodwar_mcu_4_0a); break; // Warrior 1 Player 1
+ case 0x0b: MCU_RESPONSE(bloodwar_mcu_4_0b); break; // Warrior 1 Player 2
+ case 0x0c: MCU_RESPONSE(bloodwar_mcu_4_0c); break; // Warrior 5 Player 1
+ case 0x0d: MCU_RESPONSE(bloodwar_mcu_4_0d); break; // Warrior 5 Player 2
+ case 0x0e: MCU_RESPONSE(bloodwar_mcu_4_0e); break; // Warrior 4 Player 2
+ case 0x0f: MCU_RESPONSE(bloodwar_mcu_4_0f); break; // Warrior 4 Player 1
+ case 0x10: MCU_RESPONSE(bloodwar_mcu_4_10); break; // Warrior 6 Player 1
+ case 0x11: MCU_RESPONSE(bloodwar_mcu_4_11); break; // Warrior 6 Player 2
+ case 0x12: MCU_RESPONSE(bloodwar_mcu_4_12); break; // Warrior 9 Player 1
+ case 0x13: MCU_RESPONSE(bloodwar_mcu_4_13); break; // Warrior 9 Player 2
+ case 0x14: MCU_RESPONSE(bloodwar_mcu_4_14); break; // Warrior 7 Player 1
+ case 0x15: MCU_RESPONSE(bloodwar_mcu_4_15); break; // Warrior 7 Player 2
+ case 0x16: MCU_RESPONSE(bloodwar_mcu_4_16); break; // Warrior 8 Player 1
+ case 0x17: MCU_RESPONSE(bloodwar_mcu_4_17); break; // Warrior 8 Player 2
+ case 0x18: MCU_RESPONSE(bloodwar_mcu_4_18); break; // Warrior 2 Player 2
+ case 0x19: MCU_RESPONSE(bloodwar_mcu_4_19); break; // Warrior 2 Player 1
+ case 0x1a: MCU_RESPONSE(bloodwar_mcu_4_1a); break; // Warrior 3 Player 1
+ case 0x1b: MCU_RESPONSE(bloodwar_mcu_4_1b); break; // Warrior 3 Player 2
+
+ // tilemap data
+ case 0x1c: MCU_RESPONSE(bloodwar_mcu_4_1c); break; // Warrior 8
+ case 0x1d: MCU_RESPONSE(bloodwar_mcu_4_1d); break; // Warrior 2
+ case 0x1e: MCU_RESPONSE(bloodwar_mcu_4_1e); break; // Warrior 3
+ case 0x1f: MCU_RESPONSE(bloodwar_mcu_4_1f); break; // Warrior 5
+ case 0x20: MCU_RESPONSE(bloodwar_mcu_4_20); break; // Warrior 4
+ case 0x21: MCU_RESPONSE(bloodwar_mcu_4_21); break; // Warrior 6
+ case 0x22: MCU_RESPONSE(bloodwar_mcu_4_22); break; // Warrior 1
+ case 0x23: MCU_RESPONSE(bloodwar_mcu_4_23); break; // Warrior 9
+ case 0x24: MCU_RESPONSE(bloodwar_mcu_4_24); break; // Warrior 7
+
+ // fighter data: pointers to ROM data
+ case 0x25: MCU_RESPONSE(bloodwar_mcu_4_25); break; // Warrior 1
+ case 0x26: MCU_RESPONSE(bloodwar_mcu_4_26); break; // Warrior 2
+ case 0x27: MCU_RESPONSE(bloodwar_mcu_4_27); break; // Warrior 3
+ case 0x28: MCU_RESPONSE(bloodwar_mcu_4_28); break; // Warrior 4
+ case 0x29: MCU_RESPONSE(bloodwar_mcu_4_29); break; // Warrior 5
+ case 0x2a: MCU_RESPONSE(bloodwar_mcu_4_2a); break; // Warrior 6
+ case 0x2b: MCU_RESPONSE(bloodwar_mcu_4_2b); break; // Warrior 7
+ case 0x2c: MCU_RESPONSE(bloodwar_mcu_4_2c); break; // Warrior 8
+ case 0x2d: MCU_RESPONSE(bloodwar_mcu_4_2d); break; // Warrior 9
+
+ default:
+ logerror(" (UNKNOWN PARAMETER %02X)\n", mcu_data);
+ }
+ }
+ break;
+
+ default:
+ logerror("PC=%06X : MCU executed command: %04X %04X %04X (UNKNOWN COMMAND)\n", activecpu_get_pc(), mcu_command, mcu_offset*2, mcu_data);
+ break;
+ }
+}
+
+/***************************************************************************
+ Bonk's Adventure
+***************************************************************************/
+
+void bonkadv_mcu_run(void)
+{
+ UINT16 mcu_command = kaneko16_mcu_ram[0x0010/2];
+ UINT16 mcu_offset = kaneko16_mcu_ram[0x0012/2] / 2;
+ UINT16 mcu_data = kaneko16_mcu_ram[0x0014/2];
+
+ switch (mcu_command >> 8)
+ {
+
+ case 0x02: // Read from NVRAM
+ {
+ mame_file *f;
+ if ((f = nvram_fopen(Machine, OPEN_FLAG_READ)) != 0)
+ {
+ mame_fread(f,&kaneko16_mcu_ram[mcu_offset], 128);
+ mame_fclose(f);
+ }
+ logerror("PC=%06X : MCU executed command: %04X %04X (load NVRAM settings)\n", activecpu_get_pc(), mcu_command, mcu_offset*2);
+ }
+ break;
+
+ case 0x42: // Write to NVRAM
+ {
+ mame_file *f;
+ if ((f = nvram_fopen(Machine, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS)) != 0)
+ {
+ mame_fwrite(f,&kaneko16_mcu_ram[mcu_offset], 128);
+ mame_fclose(f);
+ }
+ logerror("PC=%06X : MCU executed command: %04X %04X (save NVRAM settings)\n", activecpu_get_pc(), mcu_command, mcu_offset*2);
+ }
+ break;
+
+ case 0x43: // Initialize NVRAM - MCU writes Default Data Set directly to NVRAM
+ {
+ mame_file *f;
+ if ((f = nvram_fopen(Machine, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS)) != 0)
+ {
+ mame_fwrite(f, bonkadv_mcu_43, sizeof(bonkadv_mcu_43));
+ mame_fclose(f);
+ }
+ logerror("PC=%06X : MCU executed command: %04X %04X (restore default NVRAM settings)\n", activecpu_get_pc(), mcu_command, mcu_offset*2);
+ }
+ break;
+
+ case 0x03: // DSW
+ {
+ kaneko16_mcu_ram[mcu_offset] = readinputport(4);
+ logerror("PC=%06X : MCU executed command: %04X %04X (read DSW)\n", activecpu_get_pc(), mcu_command, mcu_offset*2);
+ }
+ break;
+
+ case 0x04: // Protection
+ {
+ logerror("PC=%06X : MCU executed command: %04X %04X %04X\n", activecpu_get_pc(), mcu_command, mcu_offset*2, mcu_data);
+
+ switch(mcu_data)
+ {
+ // static, in this order, at boot/reset
+ case 0x34: MCU_RESPONSE(bonkadv_mcu_4_34); break;
+ case 0x30: MCU_RESPONSE(bonkadv_mcu_4_30); break;
+ case 0x31: MCU_RESPONSE(bonkadv_mcu_4_31); break;
+ case 0x32: MCU_RESPONSE(bonkadv_mcu_4_32); break;
+ case 0x33: MCU_RESPONSE(bonkadv_mcu_4_33); break;
+
+ // dynamic, per-level (29), in level order
+ case 0x00: MCU_RESPONSE(bonkadv_mcu_4_00); break;
+ case 0x02: MCU_RESPONSE(bonkadv_mcu_4_02); break;
+ case 0x01: MCU_RESPONSE(bonkadv_mcu_4_01); break;
+ case 0x05: MCU_RESPONSE(bonkadv_mcu_4_05); break;
+ case 0x07: MCU_RESPONSE(bonkadv_mcu_4_07); break;
+ case 0x06: MCU_RESPONSE(bonkadv_mcu_4_06); break;
+ case 0x09: MCU_RESPONSE(bonkadv_mcu_4_09); break;
+ case 0x0D: MCU_RESPONSE(bonkadv_mcu_4_0D); break;
+ case 0x03: MCU_RESPONSE(bonkadv_mcu_4_03); break;
+ case 0x08: MCU_RESPONSE(bonkadv_mcu_4_08); break;
+ case 0x04: MCU_RESPONSE(bonkadv_mcu_4_04); break;
+ case 0x0C: MCU_RESPONSE(bonkadv_mcu_4_0C); break;
+ case 0x0A: MCU_RESPONSE(bonkadv_mcu_4_0A); break;
+ case 0x0B: MCU_RESPONSE(bonkadv_mcu_4_0B); break;
+ case 0x10: MCU_RESPONSE(bonkadv_mcu_4_10); break;
+ case 0x0E: MCU_RESPONSE(bonkadv_mcu_4_0E); break;
+ case 0x13: MCU_RESPONSE(bonkadv_mcu_4_13); break;
+ case 0x0F: MCU_RESPONSE(bonkadv_mcu_4_0F); break;
+ case 0x11: MCU_RESPONSE(bonkadv_mcu_4_11); break;
+ case 0x14: MCU_RESPONSE(bonkadv_mcu_4_14); break;
+ case 0x12: MCU_RESPONSE(bonkadv_mcu_4_12); break;
+ case 0x17: MCU_RESPONSE(bonkadv_mcu_4_17); break;
+ case 0x1A: MCU_RESPONSE(bonkadv_mcu_4_1A); break;
+ case 0x15: MCU_RESPONSE(bonkadv_mcu_4_15); break;
+ case 0x18: MCU_RESPONSE(bonkadv_mcu_4_18); break;
+ case 0x16: MCU_RESPONSE(bonkadv_mcu_4_16); break;
+ case 0x19: MCU_RESPONSE(bonkadv_mcu_4_19); break;
+ case 0x1B: MCU_RESPONSE(bonkadv_mcu_4_1B); break;
+ case 0x1C: MCU_RESPONSE(bonkadv_mcu_4_1C); break;
+
+ default:
+ logerror(" (UNKNOWN PARAMETER %02X)\n", mcu_data);
+ }
+ }
+ break;
+
+ default:
+ logerror("PC=%06X : MCU executed command: %04X %04X %04X (UNKNOWN COMMAND)\n", activecpu_get_pc(), mcu_command, mcu_offset*2, mcu_data);
+ break;
+ }
+}
+
+/***************************************************************************
+ Great 1000 Miles Rally
+***************************************************************************/
+
+/*
+ MCU Tasks:
+
+ - Write and ID string to shared RAM.
+ - Access the EEPROM
+ - Read the DSWs
+*/
+
+void gtmr_mcu_run(void)
+{
+ UINT16 mcu_command = kaneko16_mcu_ram[0x0010/2];
+ UINT16 mcu_offset = kaneko16_mcu_ram[0x0012/2] / 2;
+ UINT16 mcu_data = kaneko16_mcu_ram[0x0014/2];
+
+ logerror("CPU #0 PC %06X : MCU executed command: %04X %04X %04X\n", activecpu_get_pc(), mcu_command, mcu_offset*2, mcu_data);
+
+ switch (mcu_command >> 8)
+ {
+
+ case 0x02: // Read from NVRAM
+ {
+ mame_file *f;
+ if ((f = nvram_fopen(Machine, OPEN_FLAG_READ)) != 0)
+ {
+ mame_fread(f,&kaneko16_mcu_ram[mcu_offset], 128);
+ mame_fclose(f);
+ }
+ }
+ break;
+
+ case 0x42: // Write to NVRAM
+ {
+ mame_file *f;
+ if ((f = nvram_fopen(Machine, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS)) != 0)
+ {
+ mame_fwrite(f,&kaneko16_mcu_ram[mcu_offset], 128);
+ mame_fclose(f);
+ }
+ }
+ break;
+
+ case 0x03: // DSW
+ {
+ kaneko16_mcu_ram[mcu_offset] = readinputport(4);
+ }
+ break;
+
+ case 0x04: // TEST (2 versions)
+ {
+ if (strcmp(Machine->gamedrv->name, "gtmr") == 0 ||
+ strcmp(Machine->gamedrv->name, "gtmra") == 0)
+ {
+ /* MCU writes the string "MM0525-TOYBOX199" to shared ram */
+ kaneko16_mcu_ram[mcu_offset+0] = 0x4d4d;
+ kaneko16_mcu_ram[mcu_offset+1] = 0x3035;
+ kaneko16_mcu_ram[mcu_offset+2] = 0x3235;
+ kaneko16_mcu_ram[mcu_offset+3] = 0x2d54;
+ kaneko16_mcu_ram[mcu_offset+4] = 0x4f59;
+ kaneko16_mcu_ram[mcu_offset+5] = 0x424f;
+ kaneko16_mcu_ram[mcu_offset+6] = 0x5831;
+ kaneko16_mcu_ram[mcu_offset+7] = 0x3939;
+ }
+ else
+ {
+ /* MCU writes the string "USMM0713-TB1994 " to shared ram */
+ kaneko16_mcu_ram[mcu_offset+0] = 0x5553;
+ kaneko16_mcu_ram[mcu_offset+1] = 0x4d4d;
+ kaneko16_mcu_ram[mcu_offset+2] = 0x3037;
+ kaneko16_mcu_ram[mcu_offset+3] = 0x3133;
+ kaneko16_mcu_ram[mcu_offset+4] = 0x2d54;
+ kaneko16_mcu_ram[mcu_offset+5] = 0x4231;
+ kaneko16_mcu_ram[mcu_offset+6] = 0x3939;
+ kaneko16_mcu_ram[mcu_offset+7] = 0x3420;
+ }
+ }
+ break;
+ }
+
+}
+
diff --git a/src/mame/machine/kanekotb.h b/src/mame/machine/kanekotb.h
new file mode 100644
index 00000000000..ca11a31c511
--- /dev/null
+++ b/src/mame/machine/kanekotb.h
@@ -0,0 +1,3673 @@
+/*
+ TODO:
+ - bonkadv_mcu_43: extract data from MCU (dumped eeprom data for now)
+ - bloodwar: verify all extracted data against real board (WIP)
+*/
+
+/***************************************************************************
+
+ TOYBOX MCU data for Bonk's Adventure
+
+***************************************************************************/
+
+// notes based on test programs results, verified on PCB:
+// - bonkadv_mcu_4_30 is the only cmd that ouputs an odd (655) number of bytes
+// - bonkadv_mcu_4_33: the 32 'zeroed' bytes every 64 bytes are effectively written by the MCU
+
+// MCU executed command: 4300 0100 - factory settings
+// this command is issued whenever the nvram settings are corrupted
+// the MCU writes directly to NVRAM
+static UINT16 bonkadv_mcu_43[] = {
+ 0x8BE0,0x8E71,0x0102,0x0102,0x0300,0x010C,0x0202,0x0202,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0030,0x0020,0x4F6B,0x0305,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0082,0x6F82,0x628C,0xB490,0x6CAB
+};
+
+// MCU executed command: 0400 0E00 0034 - code
+/*
+200E00: 7071 moveq #$71, D0
+200E02: 7273 moveq #$73, D1
+200E04: 7475 moveq #$75, D2
+200E06: 7677 moveq #$77, D3
+200E08: 7879 moveq #$79, D4
+200E0A: 7A7B moveq #$7b, D5
+200E0C: 7C7D moveq #$7d, D6
+200E0E: 7E7F moveq #$7f, D7
+200E10: 4E75 rts
+*/
+static UINT16 bonkadv_mcu_4_34[] = {
+ 0x7071,0x7273,0x7475,0x7677,0x7879,0x7a7b,0x7c7d,0x7e7f,
+ 0x4e75
+};
+// MCU executed command: 0400 0180 0032 - 128 bytes at $200180
+static UINT16 bonkadv_mcu_4_32[] = {
+ 0x00cc,0xcc0c,0xc0c0,0xc080,0x0484,0xb6a6,0x0404,0x80c0,
+ 0x80b1,0xb1a1,0xa1b2,0xa2b3,0xb3a3,0xa3b1,0xb1b1,0xb1c0,
+ 0xc0a1,0xa1a1,0xa1b2,0xb2a2,0xa290,0x9090,0xb9b9,0xa9a9,
+ 0xbaaa,0xbbbb,0xabab,0xb9b9,0xb9b9,0xc8c8,0xa9a9,0xa9a9,
+ 0xbaba,0xaaaa,0x9898,0x98b9,0xb9a9,0xa9ba,0xaabb,0xbbab,
+ 0xabb9,0xb9b9,0xb9c8,0xc8a9,0xa9a9,0xa9ba,0xbaaa,0xaa98,
+ 0x9898,0xb1b1,0xa1a1,0xb2a2,0xb3b3,0xa3a3,0xb1b1,0xb1b1,
+ 0xc0c0,0xa1a1,0xa1a1,0xb2b2,0xa2a2,0x9090,0x9000,0x0000
+};
+// MCU executed command: 0400 0280 0031 - 112 bytes at $200280
+static UINT16 bonkadv_mcu_4_31[] = {
+ 0x1013,0x1411,0x1216,0x1519,0x1a17,0x1824,0x2322,0x211f,
+ 0x201e,0x1d1c,0x1b27,0x2825,0x2629,0x2a2b,0x2e2f,0x2c2d,
+ 0x3130,0x3435,0x3233,0x3f3e,0x3d3c,0x3a3b,0x3938,0x3736,
+ 0x4243,0x4041,0x4445,0x4649,0x4a47,0x484c,0x4b4f,0x504d,
+ 0x4e5a,0x5958,0x5755,0x5654,0x5352,0x515d,0x5e5b,0x5c5f,
+ 0x6061,0x6465,0x6263,0x6766,0x6a6b,0x6869,0x7574,0x7372,
+ 0x7071,0x6f6e,0x6d6c,0x7879,0x7677,0x7a7b,0x7c7d,0x7e7f
+};
+// MCU executed command: 0400 0E50 0030 - 655 bytes at $200E50 (656 here)
+static UINT16 bonkadv_mcu_4_30[] = {
+ 0x8c00,0x9700,0xa000,0xa700,0xb200,0xb700,0xc000,0xcc00,
+ 0xd600,0xdf00,0xef00,0xf500,0xfd00,0x0501,0x0b01,0x1801,
+ 0x1e01,0x2901,0x3101,0x3701,0x4101,0x4901,0x0b01,0x5d01,
+ 0xa700,0xb200,0x6c01,0x8101,0xb200,0x8101,0x8101,0x8101,
+ 0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,
+ 0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,
+ 0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x8101,0x2e02,
+ 0x3602,0x3d02,0x4102,0x4f02,0x5502,0x5502,0x5f02,0x6402,
+ 0x6d02,0x7302,0x7802,0x7d02,0x8302,0x8a02,0x0165,0x712b,
+ 0x57fe,0x57a2,0xff00,0x0003,0x7c3a,0x436c,0x66ff,0x0000,
+ 0x026c,0x6d43,0xff00,0x0000,0x74a5,0x8373,0x3599,0x9fff,
+
+ 0x0000,0x074a,0xff00,0x0002,0x8788,0x3331,0x32ff,0x0000,
+ 0x0276,0x8c71,0x2d8c,0xfe12,0x8cff,0x0000,0x0171,0x0d29,
+ 0xfe0d,0x29ff,0x0000,0x0559,0x5a5b,0x8a8b,0xff00,0x0003,
+ 0x0d0e,0x576a,0x641e,0xfe0d,0x0efe,0x64a3,0xff00,0x0006,
+ 0x0262,0xff00,0x0007,0x3e3f,0x7a7b,0xff00,0x0007,0x7584,
+ 0x4c53,0xff00,0x0001,0x6645,0xff00,0x0007,0x0d18,0x2984,
+ 0x5384,0xfe0d,0x29ff,0x0000,0x0457,0x5cff,0x0000,0x0751,
+ 0x5202,0x45fe,0x4575,0xff00,0x0000,0x191a,0x1b6e,0xff00,
+ 0x0006,0x3472,0xff00,0x0000,0x6569,0x090f,0x8b23,0xff00,
+ 0x0004,0x3b3c,0x3d79,0xff00,0x0080,0x770a,0x8176,0x2a65,
+ 0x64fe,0x7776,0xfe2a,0x76fe,0x650a,0xff00,0x0000,0x1011,
+ 0x1226,0x2728,0xa655,0x940f,0x68ff,0x0000,0x8045,0x6477,
+ 0x0a81,0x762a,0x65fe,0x7776,0xfe2a,0x76fe,0x650a,0xff00,
+ 0x0000,0x166b,0xff00,0x0007,0x1e30,0x39ff,0x0000,0x0345,
+ 0x3a77,0x7843,0x4647,0xff00,0x0000,0x7335,0x8399,0x9fff,
+ 0x0000,0x0237,0x38ff,0x0000,0x0044,0x303b,0xff00,0x0000,
+
+ 0x7d7e,0x7fa1,0x0aff,0x0000,0x0070,0xff00,0x0000,0x3e3f,
+ 0x7a7b,0x6180,0x89a4,0xff00,0x0006,0x86a5,0x4f42,0xff00,
+ 0x0000,0x1011,0x1255,0x0f68,0xff00,0x0002,0x8788,0x4033,
+ 0xff00,0x0005,0x650f,0xff00,0x0008,0x9596,0x9ba7,0xff00,
+ 0x0000,0x4849,0x82ff,0x0000,0x022e,0x2f30,0xff00,0x0001,
+ 0x7778,0x5826,0x2728,0xa6ff,0x0000,0x0813,0x1402,0x51ff,
+ 0x0000,0x072e,0x5c5d,0xff00,0x0006,0x57ff,0x0000,0x0230,
+ 0x391e,0x65fe,0x6530,0xff00,0x0000,0x4bff,0x0000,0x008e,
+ 0x8f90,0x91ff,0x0000,0x0092,0x9d17,0xff00,0x0000,0xff00,
+ 0x0000,0x8d9b,0xa77d,0x7e7f,0xa10a,0x9596,0xff00,0x0001,
+ 0x1993,0xff00,0x0000,0x67ff,0x0000,0x0067,0xff00,0x0000,
+ 0x27ff,0x0000,0x0390,0x8e23,0x978b,0xff00,0x0000,0x1d9e,
+ 0xff00,0x0007,0x3bff,0x0000,0x001d,0xff00,0x0000,0x8e90,
+ 0xff00,0x0005,0x2495,0x96ff,0x0000,0x009a,0xff00,0x0000
+};
+// MCU executed command: 0400 0400 0033 - 2560 bytes at $200400
+static UINT16 bonkadv_mcu_4_33[] = {
+ 0x00a4,0x0001,0x00a5,0x005a,0x00a6,0x0074,0x00a7,0x009b,
+ 0x00a8,0x00d0,0x00a9,0x00fe,0x00aa,0x015d,0x00ab,0x01b0,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0001,0x0002,0x0019,0x005b,0x0022,0x0075,0x002d,0x009c,
+ 0x0041,0x00d1,0x004e,0x00ff,0x0060,0x015f,0x0072,0x01b1,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0002,0x0008,0x001a,0x0061,0x0023,0x007b,0x002e,0x00a2,
+ 0x0042,0x00d7,0x004f,0x0107,0x0061,0x0165,0x0073,0x01b7,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x000a,0x0000,0x0063,0x0000,0x007d,0x0000,0x00a4,
+ 0x0000,0x00d9,0x0000,0x0109,0x0000,0x0167,0x0000,0x01b9,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x0003,0x000b,0x001b,0x0064,0x0024,0x007e,0x002f,0x00a5,
+ 0x0043,0x00da,0x0050,0x010a,0x0062,0x0168,0x0074,0x01ba,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x000c,0x0000,0x0065,0x0000,0x007f,0x0000,0x00a6,
+ 0x0000,0x00db,0x0000,0x010b,0x0000,0x0169,0x0000,0x01bb,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0004,0x0008,0x001c,0x0061,0x0025,0x007b,0x0030,0x00a2,
+ 0x0044,0x00d7,0x0051,0x0107,0x0063,0x0165,0x0075,0x01b7,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0005,0x000d,0x001d,0x0066,0x0025,0x007b,0x0031,0x00a7,
+ 0x0045,0x00dc,0x0051,0x0107,0x0063,0x0165,0x0075,0x01b7,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x0000,0x0017,0x0000,0x0069,0x0000,0x0089,0x0000,0x00af,
+ 0x0000,0x00df,0x0000,0x0115,0x0000,0x0173,0x0000,0x01c5,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0009,0x0015,0x001e,0x0067,0x0029,0x0087,0x0034,0x00ad,
+ 0x0046,0x00dd,0x0055,0x0113,0x0067,0x0171,0x0079,0x01c3,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0006,0x000e,0x0006,0x000e,0x0026,0x0080,0x0006,0x000e,
+ 0x0000,0x0000,0x0052,0x010c,0x0064,0x016a,0x0076,0x01bc,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0007,0x0010,0x0007,0x0010,0x0027,0x0082,0x0032,0x00a8,
+ 0x0000,0x0000,0x0053,0x010e,0x0065,0x016c,0x0077,0x01be,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x0000,0x0013,0x0000,0x0013,0x0000,0x0085,0x0000,0x00ab,
+ 0x0000,0x0000,0x0000,0x0111,0x0000,0x016f,0x0000,0x01c1,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0008,0x0014,0x0008,0x0014,0x0028,0x0086,0x0033,0x00ac,
+ 0x0000,0x0000,0x0054,0x0112,0x0066,0x0170,0x0078,0x01c2,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0018,0x0000,0x006a,0x0000,0x008a,0x0000,0x00b0,
+ 0x0000,0x00e0,0x0000,0x0116,0x0000,0x0174,0x0000,0x01c6,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x000c,0x0000,0x0065,0x0000,0x007f,0x0000,0x00a6,
+ 0x0000,0x00db,0x0000,0x010b,0x0000,0x0169,0x0000,0x01bb,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x000a,0x0019,0x001f,0x006b,0x002a,0x008b,0x0035,0x00b1,
+ 0x0047,0x00e1,0x0056,0x0117,0x0068,0x0175,0x007a,0x01c7,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x000b,0x0019,0x0020,0x006b,0x002b,0x008b,0x0036,0x00b1,
+ 0x0048,0x00e1,0x0057,0x0117,0x0069,0x0175,0x007a,0x01c7,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0015,0x003e,0x0015,0x003e,0x0099,0x0095,0x0015,0x003e,
+ 0x0000,0x0000,0x009e,0x013a,0x006d,0x018f,0x007e,0x01dc,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x000c,0x001d,0x000c,0x001d,0x000c,0x001d,0x000c,0x001d,
+ 0x0049,0x00e5,0x0058,0x011b,0x006a,0x0179,0x007b,0x01c9,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x0000,0x001f,0x0000,0x001f,0x0000,0x001f,0x0000,0x001f,
+ 0x0000,0x00e7,0x0000,0x011d,0x0000,0x017b,0x0000,0x01cb,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x000d,0x0020,0x0021,0x006f,0x002c,0x008f,0x0037,0x00b5,
+ 0x004a,0x00e8,0x0059,0x011e,0x006b,0x017c,0x007c,0x01cc,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0022,0x0000,0x0071,0x0000,0x0091,0x0000,0x00b7,
+ 0x0000,0x00ea,0x0000,0x0120,0x0000,0x017e,0x0000,0x01ce,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0014,0x003b,0x0014,0x003b,0x005d,0x0092,0x0014,0x003b,
+ 0x0014,0x003b,0x009d,0x0137,0x00a0,0x018c,0x00a1,0x01d9,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x0012,0x0036,0x0012,0x0036,0x0012,0x0036,0x0012,0x0036,
+ 0x008a,0x00e5,0x00be,0x013c,0x006c,0x0184,0x007d,0x01d1,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0013,0x0038,0x0013,0x0038,0x0013,0x0038,0x0013,0x0038,
+ 0x008a,0x00e5,0x00bf,0x013d,0x006c,0x0184,0x007d,0x01d1,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0038,0x00ba,0x0038,0x00ba,0x0038,0x00ba,0x0038,0x00ba,
+ 0x0038,0x00ba,0x00a2,0x0128,0x006e,0x019c,0x007f,0x01e7,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x005c,0x014d,0x005c,0x014d,0x005c,0x014d,0x005c,0x014d,
+ 0x0000,0x0000,0x009c,0x0124,0x0071,0x01a5,0x0082,0x01f0,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x005b,0x014d,0x005b,0x014d,0x005b,0x014d,0x005b,0x014d,
+ 0x0000,0x0000,0x009b,0x0124,0x0070,0x01a1,0x0081,0x01ec,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0044,0x0000,0x0044,0x0000,0x0044,0x0000,0x0044,
+ 0x0000,0x00db,0x0000,0x010b,0x0000,0x0169,0x0000,0x01bb,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0018,0x0045,0x0018,0x0045,0x0018,0x0045,0x0018,0x0045,
+ 0x0044,0x00d7,0x0051,0x0107,0x0063,0x0165,0x0075,0x01b7,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x008b,0x000e,0x008b,0x000e,0x008c,0x0080,0x008b,0x000e,
+ 0x0000,0x0000,0x008d,0x010c,0x008e,0x016a,0x008f,0x01bc,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x0090,0x0010,0x0090,0x0010,0x0091,0x0082,0x0092,0x00a8,
+ 0x0000,0x0000,0x0093,0x010e,0x0094,0x016c,0x0095,0x01be,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0096,0x003e,0x0096,0x003e,0x009a,0x0095,0x0096,0x003e,
+ 0x0000,0x0000,0x009f,0x013a,0x0097,0x018f,0x0098,0x01dc,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0049,0x0000,0x0069,0x0000,0x0098,0x0000,0x00af,
+ 0x0000,0x00df,0x0000,0x0145,0x0000,0x0173,0x0000,0x01c5,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x005e,0x0048,0x005f,0x0068,0x006f,0x0097,0x0080,0x00ae,
+ 0x00ac,0x00de,0x00ad,0x0144,0x00ae,0x0172,0x00af,0x01c4,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+
+ 0x004b,0x00ed,0x004b,0x00ed,0x004b,0x00ed,0x004b,0x00ed,
+ 0x004b,0x00ed,0x00b0,0x012b,0x00b6,0x0186,0x00ba,0x01d3,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0087,0x00f2,0x0087,0x00f2,0x0087,0x00f2,0x0087,0x00f2,
+ 0x0087,0x00f2,0x00b3,0x0130,0x00b8,0x018b,0x00bc,0x01d8,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x00c1,0x0050,0x00c1,0x0050,0x00c1,0x0050,0x00c1,0x0050,
+ 0x00c1,0x0050,0x00c3,0x0148,0x00c5,0x019a,0x00c7,0x01e5,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x00c2,0x0050,0x00c2,0x0050,0x00c2,0x0050,0x00c2,0x0050,
+ 0x00c2,0x0050,0x00c4,0x0148,0x00c6,0x019a,0x00c8,0x01e5,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
+ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
+};
+// dynamic, per-level (29), in level order
+// PC=078896 : MCU executed command: 0400 0300 00xx - xx = subcmd
+static UINT16 bonkadv_mcu_4_00[] = { 0x0000,0x04C0,0x0000,0x0100,0x0600,0x0100 };
+static UINT16 bonkadv_mcu_4_02[] = { 0x0000,0x0760,0x0000,0x0100,0x0270,0x0100,0x0320,0x01B0,
+ 0x0460,0x01B0,0x0510,0x0100,0x05E0,0x0100,0x0620,0x0120,
+ 0x08A0,0x0120 };
+static UINT16 bonkadv_mcu_4_01[] = { 0x0000,0x0670,0x0000,0x0100,0x0200,0x0100,0x02E0,0x0090,
+ 0x0400,0x0090,0x04E0,0x0100,0x07B0,0x0100 };
+static UINT16 bonkadv_mcu_4_05[] = { 0x0000,0x0610,0x0000,0x0100,0x0750,0x0100 };
+static UINT16 bonkadv_mcu_4_07[] = { 0x0000,0x03C0,0x0000,0x0100,0x0500,0x0100 };
+static UINT16 bonkadv_mcu_4_06[] = { 0x0000,0x05F0,0x0000,0x0100,0x0730,0x0100 };
+static UINT16 bonkadv_mcu_4_09[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 };
+static UINT16 bonkadv_mcu_4_0D[] = { 0x0000,0x07A0,0x0000,0x0100,0x08E0,0x0100 };
+static UINT16 bonkadv_mcu_4_03[] = { 0x0000,0x0920,0x0000,0x0100,0x0A60,0x0100 };
+static UINT16 bonkadv_mcu_4_08[] = { 0x0000,0x0730,0x0000,0x0100,0x0870,0x0100 };
+static UINT16 bonkadv_mcu_4_04[] = { 0x0000,0x05C0,0x0000,0x0100,0x0200,0x0100,0x0280,0x00C0,
+ 0x02E0,0x0060,0x03A0,0x0000,0x0700,0x0000 };
+static UINT16 bonkadv_mcu_4_0C[] = { 0x0000,0x06E0,0x0000,0x0100,0x0820,0x0100 };
+static UINT16 bonkadv_mcu_4_0A[] = { 0x0000,0x05A0,0x0000,0x0100,0x06E0,0x0100 };
+static UINT16 bonkadv_mcu_4_0B[] = { 0x0000,0x0470,0x0000,0x0100,0x05B0,0x0100 };
+static UINT16 bonkadv_mcu_4_10[] = { 0x0000,0x06C0,0x0000,0x0100,0x03B0,0x0100,0x0460,0x0050,
+ 0x05E0,0x0050,0x0650,0xFFE0,0x0800,0xFFE0 };
+static UINT16 bonkadv_mcu_4_0E[] = { 0x0000,0x0630,0x0000,0x0100,0x0770,0x0100 };
+static UINT16 bonkadv_mcu_4_13[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 };
+static UINT16 bonkadv_mcu_4_0F[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 };
+static UINT16 bonkadv_mcu_4_11[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 };
+static UINT16 bonkadv_mcu_4_14[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 };
+static UINT16 bonkadv_mcu_4_12[] = { 0x0000,0x05C0,0x0000,0x0100,0x0700,0x0100 };
+static UINT16 bonkadv_mcu_4_17[] = { 0x0000,0x0520,0x0000,0x0100,0x0660,0x0100 };
+static UINT16 bonkadv_mcu_4_1A[] = { 0x0000,0x03C0,0x0000,0x0100,0x0500,0x0100 };
+static UINT16 bonkadv_mcu_4_15[] = { 0x0000,0x02C0,0x0000,0x0100,0x0400,0x0100 };
+static UINT16 bonkadv_mcu_4_18[] = { 0x0000,0x03C0,0x0000,0x0100,0x0500,0x0100 };
+static UINT16 bonkadv_mcu_4_16[] = { 0x0000,0x02F0,0x0000,0x0100,0x0430,0x0100 };
+static UINT16 bonkadv_mcu_4_19[] = { 0x0000,0x03A0,0x0000,0x0100,0x04E0,0x0100 };
+static UINT16 bonkadv_mcu_4_1B[] = { 0x0000,0x0460,0x0000,0x0100,0x05A0,0x0100 };
+static UINT16 bonkadv_mcu_4_1C[] = { 0x0000,0x02C0,0x0000,0x0100,0x0400,0x0100 };
+
+
+/***************************************************************************
+
+ TOYBOX MCU data for Blood Warrior
+
+***************************************************************************/
+
+// bloodwar MCU writes by 16-bytes block, and data seems to be contiguous?
+// unknown data: the last 4 words of a cmd are the 4 firsts of the next one
+// palette data: when the negative word is not on a 16-bytes boundary,
+// it is followed by the first bytes of the next palette
+// unknown data are followed by tilemap (last tilemap ends with 0xff)
+// palette (last ends with: 0x0004,0xce4a,0x0004 ???)
+// fighter: order is unclear - cmd 26 is probably the last (ends with 0xff)
+
+// --- unknown data ---
+static UINT16 bloodwar_mcu_4_01[] = { 0x00E6,0x00C6,0x00E8,0x00D0,0xFC9A,0x05C0,0x0F00,0x08C0, // Warrior 1
+ 0x0001,0x0120,0x0090,0x021B,0x00B4,0x0094,0x00AC,0x0094 };
+static UINT16 bloodwar_mcu_4_02[] = { 0x00B4,0x0094,0x00AC,0x0094,0xFCD2,0x03C0,0x1000,0x0900, // Warrior 2
+ 0x0001,0x0100,0x0080,0x0118,0x00F0,0x00D0,0x00F4,0x00DC };
+static UINT16 bloodwar_mcu_4_03[] = { 0x00F0,0x00D0,0x00F4,0x00DC,0xFC90,0x03C0,0x0C00,0x0CC0, // Warrior 3
+ 0x0001,0x0200,0x0100,0x0930,0x00D2,0x00B2,0x00CA,0x00B0 };
+static UINT16 bloodwar_mcu_4_04[] = { 0x00D2,0x00B2,0x00CA,0x00B0,0xFCB5,0x05C0,0x1000,0x0C00, // Warrior 4
+ 0x0001,0x0140,0x00A0,0x031E,0x00A0,0x0080,0x00DC,0x00C4 };
+static UINT16 bloodwar_mcu_4_05[] = { 0x00A0,0x0080,0x00DC,0x00C4,0xFCA2,0x05C0,0x0AC0,0x0880, // Warrior 5
+ 0x0001,0x01A0,0x00D0,0x0627,0x00BE,0x009E,0x00C2,0x00A8 };
+static UINT16 bloodwar_mcu_4_06[] = { 0x00BE,0x009E,0x00C2,0x00A8,0xFCBF,0x04C0,0x1100,0x0C00, // Warrior 6
+ 0x0001,0x0180,0x00C0,0x0524,0x00C8,0x00A8,0x00D6,0x009C };
+static UINT16 bloodwar_mcu_4_07[] = { 0x00C8,0x00A8,0x00D6,0x009C,0xFCC8,0x05C0,0x0F40,0x0CC0, // Warrior 7
+ 0x0001,0x0160,0x00B0,0x0421,0x00AA,0x008A,0x00A0,0x0086 };
+static UINT16 bloodwar_mcu_4_08[] = { 0x00AA,0x008A,0x00A0,0x0086,0xFCDB,0x05C0,0x1380,0x0F80, // Warrior 8
+ 0x0000,0x01E0,0x00F0,0x082D,0x00DC,0x00BC,0x00D6,0x00BC };
+static UINT16 bloodwar_mcu_4_09[] = { 0x00DC,0x00BC,0x00D6,0x00BC,0xFCAC,0x04C0,0x10C0,0x1000, // Warrior 9
+ 0x0001,0x01C0,0x00E0,0x072A,0xFF08,0xFF02,0x0000,0xFF03 };
+
+// --- palette data ---
+// number of palettes (>=1)
+// palette data follows (each palette is 0x200 bytes long)
+// a negative word will end the palette
+static UINT16 bloodwar_mcu_4_0a[] = { // Warrior 1 Player 1
+ 0x000B,0x0000,0x4232,0x56F8,0x2D8D,0x27FF,0x3BFF,0x53FF,
+ 0x63FF,0x381F,0x4C1F,0x581F,0x6C1F,0x7C1F,0x7E1F,0x7EBF,
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x294A,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x381F,0x4C1F,0x581F,0x6C1E,0x781E,0x7E1F,0x7EBF,
+
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x0360,0x13E0,0x2BE0,0x3BE9,0x4FEE,0x5FF3,0x6FF8,
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x4191,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x2AC0,0x3700,0x47A0,0x5BC0,0x6FE4,0x7BEF,0x7FFB,
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x021C,0x0ABE,0x171E,0x275F,0x379F,0x4FBF,0x67BF,
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F,
+ 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F,
+ 0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0,0x4FC0,0x57C0,
+ 0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3,0x7FFA,0x7FFC,
+ 0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320,0x0340,
+ 0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0,0x1DA3,
+ 0x2243,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407,
+ 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D,
+ 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,
+ 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,
+
+ 0x7E9F,0x7BDE,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4,
+ 0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7,0x7FFA,
+ 0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320,
+ 0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0,
+ 0x1DA3,0x2243,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77,0x12B9,
+ 0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F,0x639F,
+ 0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x0011,0x0016,0x001A,
+ 0x1C1D,0x281E,0x341D,0x401E,0x501E,0x581E,0x641E,0x6C1F,
+ 0x785F,0x7E5F,0x7F3F,0x7BDE,0xFFFF,0x4191,0x2000,0x2800,
+ 0x3000,0x3400,0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821,
+ 0x7084,0x7D29,0x7E52,0x7F39,0x7BDE,0xFFFF,0x4191,0x1320,
+ 0x2340,0x2B60,0x3380,0x3FA0,0x47A0,0x4FC1,0x5BC0,0x67E2,
+ 0x6FE4,0x77E6,0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x000B
+};
+static UINT16 bloodwar_mcu_4_0b[] = { // Warrior 1 Player 2
+ 0x000B,0x292A,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x2E2A,0x29E9,0x2609,0x29E9,0x2629,0x2A4A,0x2A4B,
+ 0x260A,0x25E8,0x25C8,0x1965,0x21A8,0x21A7,0x25E8,0x1DA7,
+ 0x21A8,0x21A8,0x2186,0x1D86,0x1524,0x2187,0x2146,0x1925,
+ 0x1504,0x1924,0x18E5,0x0CE2,0x10E2,0x1926,0x10C3,0x14E3,
+ 0x1082,0x10A0,0x0C40,0x0C60,0x1080,0x14A1,0x18C2,0x1925,
+ 0x1924,0x0CC3,0x2146,0x0CA2,0x1D25,0x10C0,0x1104,0x1905,
+ 0x18C4,0x1523,0x1D45,0x1101,0x1D62,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x25A9,0x1906,0x1D67,0x1125,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29C9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x7F88,0x7F88,0x7EA9,0x7B73,0x7E68,0x72CB,0x66CB,
+ 0x772A,0x6348,0x52A8,0x6F4E,0x66EC,0x5669,0x6B2A,0x5288,
+ 0x4585,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x62C7,0x62E7,0x4ACC,0x532D,
+ 0x4B0D,0x294A,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x381F,0x4C1F,0x581F,0x6C1E,0x781E,0x7E1F,0x7EBF,
+
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x0360,0x13E0,0x2BE0,0x3BE9,0x4FEE,0x5FF3,0x6FF8,
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x4191,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x2AC0,0x3700,0x47A0,0x5BC0,0x6FE4,0x7BEF,0x7FFB,
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x2D0C,0x0002,0x0002,0x0002,0x0002,0x0002,0x0002,
+ 0x0002,0x021C,0x0ABE,0x171E,0x275F,0x379F,0x4FBF,0x67BF,
+ 0x7BDE,0x2DAF,0x296E,0x298E,0x29AE,0x2DAE,0x31CF,0x31D0,
+ 0x2DCF,0x258D,0x256D,0x190A,0x214D,0x214C,0x256E,0x1D4C,
+ 0x216C,0x216D,0x1D2B,0x192B,0x10E9,0x1D4B,0x1D2C,0x1509,
+ 0x10E8,0x14E9,0x1508,0x08A6,0x0CA6,0x1529,0x0CC7,0x10C8,
+ 0x0CA5,0x0CC3,0x0862,0x0882,0x0CA2,0x10C4,0x14E5,0x1927,
+ 0x1926,0x0CC5,0x2148,0x0CA4,0x1948,0x0CE3,0x0CE9,0x1509,
+
+ 0x14E7,0x1525,0x1D47,0x1103,0x1D64,0x1D66,0x1D65,0x1945,
+ 0x1104,0x0CC2,0x0CE2,0x0D03,0x2569,0x1906,0x1D67,0x10E7,
+ 0x422F,0x6F79,0x6F59,0x6B57,0x6737,0x6B37,0x6F7A,0x737A,
+ 0x6B78,0x6B58,0x6F99,0x6F78,0x4EB0,0x4A90,0x3E4E,0x4A8F,
+ 0x2DC9,0x466E,0x4A8F,0x6736,0x6756,0x5733,0x4AAF,0x468E,
+ 0x424D,0x31EA,0x2DE9,0x29C9,0x2DCA,0x29A9,0x320A,0x362B,
+ 0x2DCB,0x360C,0x360D,0x320B,0x1D45,0x1D46,0x10E3,0x0CC3,
+ 0x35EA,0x35EB,0x2186,0x2587,0x29A8,0x1945,0x1D65,0x1D66,
+ 0x2166,0x0CC2,0x0CE3,0x1524,0x1103,0x1503,0x0D02,0x1123,
+ 0x1543,0x08A2,0x08C2,0x0D42,0x0862,0x1924,0x0CE2,0x1523,
+ 0x2168,0x19A5,0x3A8C,0x21E6,0x2A28,0x36AA,0x2646,0x2EA9,
+ 0x36EB,0x2AA7,0x2286,0x22A6,0x1EE6,0x1F06,0x42CE,0x5753,
+ 0x1A05,0x0E02,0x1A44,0x32C9,0x3AEC,0x2EA9,0x470F,0x2226,
+ 0x1183,0x2E8A,0x36CB,0x2246,0x0D42,0x1A05,0x2687,0x2AE9,
+ 0x2227,0x472D,0x430D,0x42EC,0x3288,0x4F4F,0x46CD,0x36AA,
+ 0x2E87,0x2A07,0x3249,0x3689,0x1142,0x25C7,0x1DA4,0x42CC,
+
+ 0x366A,0x21A5,0x1984,0x470B,0x3EEA,0x430A,0x21C4,0x42CD,
+ 0x2E08,0x536E,0x2647,0x4F2F,0x5B72,0x3A8B,0x324A,0x21E5,
+ 0x2E29,0x67C8,0x67E8,0x67E9,0x6B8F,0x638A,0x5FCB,0x5B6B,
+ 0x6FCA,0x5BE8,0x4B48,0x67EE,0x5F8C,0x42A9,0x63CA,0x42C8,
+ 0x3666,0x2E05,0x2E06,0x1D63,0x4F4C,0x46B0,0x46CE,0x46EB,
+ 0x534D,0x29C4,0x25C3,0x3A88,0x5B67,0x5B87,0x4ACC,0x532D,
+ 0x4B0D,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F,
+ 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F,
+ 0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0,0x4FC0,0x57C0,
+ 0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3,0x7FFA,0x7FFC,
+ 0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320,0x0340,
+ 0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0,0x1DA3,
+ 0x2243,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407,
+ 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D,
+ 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,
+ 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,
+
+ 0x7E9F,0x7BDE,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4,
+ 0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7,0x7FFA,
+ 0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,0x0320,
+ 0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,0x13E0,
+ 0x1DA3,0x2243,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77,0x12B9,
+ 0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F,0x639F,
+ 0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x0011,0x0016,0x001A,
+ 0x1C1D,0x281E,0x341D,0x401E,0x501E,0x581E,0x641E,0x6C1F,
+ 0x785F,0x7E5F,0x7F3F,0x7BDE,0xFFFF,0x4191,0x2000,0x2800,
+ 0x3000,0x3400,0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821,
+ 0x7084,0x7D29,0x7E52,0x7F39,0x7BDE,0xFFFF,0x4191,0x1320,
+ 0x2340,0x2B60,0x3380,0x3FA0,0x47A0,0x4FC1,0x5BC0,0x67E2,
+ 0x6FE4,0x77E6,0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x0004
+};
+static UINT16 bloodwar_mcu_4_0c[] = { // Warrior 5 Player 1
+ 0x0004,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x1422,0x1423,0x2044,0x1803,0x1C23,0x2CA6,0x2445,
+ 0x2446,0x38CA,0x2C87,0x38EA,0x30A8,0x34A9,0x2C88,0x2887,
+ 0x2866,0x1824,0x3089,0x28A7,0x2466,0x2867,0x30C9,0x34E9,
+ 0x59F0,0x59D0,0x6212,0x6654,0x6211,0x5DF0,0x59CE,0x558D,
+ 0x518F,0x4D2F,0x492E,0x34AB,0x4D4E,0x55B1,0x40EB,0x5591,
+ 0x40CB,0x59B1,0x5590,0x450D,0x2865,0x5170,0x3D0D,0x2045,
+ 0x2046,0x51D0,0x4D8D,0x2885,0x30C8,0x3CEA,0x3CEB,0x38C9,
+ 0x3087,0x3088,0x2465,0x2064,0x1C43,0x1822,0x494E,0x412C,
+ 0x452D,0x51AC,0x5E0F,0x6653,0x6A53,0x496B,0x55CF,0x34AA,
+ 0x38A9,0x3CEB,0x3489,0x2006,0x1C05,0x308A,0x450F,0x40EE,
+ 0x40CD,0x38AC,0x2C48,0x2C89,0x496E,0x55D0,0x59B2,0x55D2,
+ 0x492E,0x5970,0x5991,0x61D3,0x5DB2,0x44EB,0x55B0,0x494B,
+ 0x5171,0x5570,0x5571,0x5191,0x38EB,0x34AA,0x2846,0x4D8E,
+ 0x2CA7,0x2464,0x410C,0x3CCB,0x38CC,0x410B,0x3CEC,0x30CA,
+
+ 0x408B,0x20A7,0x452C,0x51AF,0x454C,0x24A3,0x494C,0x518E,
+ 0x61F1,0x55AE,0x5DF2,0x5A0E,0x55ED,0x6271,0x38AA,0x30A6,
+ 0x2887,0x2A40,0x53A0,0x63E1,0x6FE5,0x6FE5,0x5BC2,0x5FC4,
+ 0x5FC3,0x67C4,0x6FC8,0x73C6,0x6BE6,0x29E0,0x2E00,0x2E00,
+ 0x3E82,0x5B47,0x1DA0,0x3EC0,0x3681,0x3680,0x4B03,0x5364,
+ 0x2A00,0x5384,0x5787,0x5B26,0x5FC4,0x5FE2,0x5BE2,0x3F00,
+ 0x4320,0x3AC0,0x2E40,0x2A20,0x4760,0x4300,0x4B41,0x3240,
+ 0x3220,0x3A61,0x3260,0x3280,0x2A60,0x32A0,0x2E00,0x3AA0,
+ 0x4722,0x3AA0,0x31C0,0x3200,0x3220,0x3620,0x3200,0x5385,
+ 0x67E7,0x5784,0x6388,0x6368,0x73AA,0x73CB,0x3A82,0x73C5,
+ 0x6BE7,0x1943,0x1542,0x08A1,0x0CE3,0x0CE1,0x1962,0x2164,
+ 0x29E5,0x25A3,0x25C4,0x2E25,0x3226,0x3227,0x1963,0x21A4,
+ 0x2DE8,0x1D84,0x25A5,0x1122,0x0460,0x0CE2,0x1543,0x1DA3,
+ 0x1DA4,0x25E5,0x25C5,0x2DE7,0x29C6,0x2E07,0x3A49,0x42CB,
+ 0x4F0C,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F,
+ 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F,
+
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x001F,0x0FE0,0x1BE0,
+ 0x27E0,0x37E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x7FF5,
+ 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,
+ 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,
+ 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F,
+ 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92,
+ 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4,
+ 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6,
+ 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB,
+ 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539,
+ 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F,
+ 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F,
+ 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF,
+ 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF,
+ 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F,
+ 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x79BF,
+
+ 0x79FF,0x7A1F,0x7A5F,0x7A7F,0x7ABF,0x7B5F,0x7B7F,0x7DDF,
+ 0x7E1F,0x7E5F,0x7F1F,0x7F7F,0x7D7F,0x7E1F,0x7E5F,0x7EBF,
+ 0x7EFF,0x7F5F,0x7FBF,0x7FDF,0x7E3F,0x7E5F,0x7E7F,0x7E9F,
+ 0x7EBF,0x7EDF,0x7EFF,0x7F1F,0x7F3F,0x7F5F,0x7F7F,0x7FBF,
+ 0x7FFF,0x0000,0xFFFF,0x3C48,0x7FE0,0x7C1F,0x7C00,0x001F,
+ 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7DFF,0x7E9F,0x7BDE,0x7FE0,0x0445,0x08C5,0x04E5,0x0505,
+ 0x0525,0x0545,0x0565,0x0945,0x0965,0x0966,0x0986,0x09A6,
+ 0x198C,0x19AA,0x1D66,0x7FE0,0x1D82,0x1DA2,0x1DC2,0x218C,
+ 0x21AC,0x21C2,0x258D,0x25AC,0x29AD,0x29AE,0x29AF,0x29CF,
+ 0x29E2,0x2D91,0x2DB0,0x7FE0,0x2DF0,0x31D0,0x31D1,0x31D2,
+ 0x31F1,0x31F2,0x3592,0x35D1,0x35D2,0x35F2,0x35F3,0x3A33,
+ 0x3DF3,0x3DF4,0x3DF5,0x7FE0,0x3E14,0x3E15,0x3E33,0x3E34,
+ 0x3F62,0x41D3,0x41F5,0x4215,0x4216,0x4234,0x4235,0x4236,
+ 0x4382,0x4616,0x4617,0x7FE0,0x4636,0x4637,0x4639,0x4656,
+ 0x4657,0x4676,0x4A17,0x4A19,0x4A37,0x4A39,0x4E77,0x4E78,
+
+ 0x4FAD,0x5259,0x525A,0x7FE0,0x5279,0x527A,0x5299,0x5299,
+ 0x529A,0x53EC,0x53EE,0x5699,0x569A,0x56B9,0x56BA,0x56BC,
+ 0x5A9C,0x5ABA,0x5ABC,0x7FE0,0x5BF1,0x5EFB,0x5EFC,0x62BD,
+ 0x62FD,0x62FE,0x631D,0x66FD,0x671D,0x671E,0x673D,0x67B2,
+ 0x67D4,0x6B3E,0x6B3F,0x7FE0,0x6F7F,0x737F,0x739E,0x739F,
+ 0x73FD,0x77BF,0x77F9,0x7BBE,0x7BDD,0x7BFC,0x7FFA,0x7FFB,
+ 0x7FFC,0x7FFD,0x7FFF,0x7FE0,0x1D6C,0x2DD0,0x3E13,0x4635,
+ 0x5278,0x5ABD,0x6F7F,0x3C48,0x3C48,0x3C48,0x3C48,0x3C48,
+ 0x3C48,0x3C48,0x3C48,0x3971,0x0842,0x15C6,0x2666,0x1E8C,
+ 0x270A,0x32F1,0x2EAB,0x3BCF,0x3BD2,0x4BEE,0x53F6,0x5B94,
+ 0x6BB5,0x6FFB,0x7BDE,0xFFFF,0x0004,0x0000,0x4232,0x56F8
+};
+static UINT16 bloodwar_mcu_4_0d[] = { // Warrior 5 Player 2
+ 0x0004,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x0C29,0x0C2A,0x184B,0x100A,0x142A,0x24AD,0x1C4C,
+ 0x1C4D,0x30D1,0x248E,0x30F1,0x28AF,0x2CB0,0x248F,0x208E,
+ 0x206D,0x102B,0x2890,0x20AE,0x1C6D,0x206E,0x28D0,0x2CF0,
+ 0x51F7,0x51D7,0x5A19,0x5E5B,0x5A18,0x55F7,0x51D5,0x4D94,
+ 0x4996,0x4536,0x4135,0x2CB2,0x4555,0x4DB8,0x38F2,0x4D98,
+ 0x38D2,0x51B8,0x4D97,0x3D14,0x206C,0x4977,0x3514,0x184C,
+ 0x184D,0x49D7,0x4594,0x208C,0x28CF,0x34F1,0x34F2,0x30D0,
+ 0x288E,0x288F,0x1C6C,0x186B,0x144A,0x1029,0x4155,0x3933,
+ 0x3D34,0x49B3,0x5616,0x5E5A,0x625A,0x4172,0x4DD6,0x2CB1,
+ 0x30B0,0x34F2,0x2C90,0x180D,0x140C,0x2891,0x3D16,0x38F5,
+ 0x38D4,0x30B3,0x244F,0x2490,0x4174,0x4DD7,0x51B9,0x4DD9,
+ 0x4135,0x5177,0x5198,0x59DA,0x55B9,0x3CF2,0x4DB7,0x4152,
+ 0x4978,0x4D77,0x4D78,0x4998,0x30F2,0x2CB1,0x204D,0x4595,
+ 0x24AE,0x1C6B,0x3913,0x34D2,0x30D3,0x3912,0x34F3,0x28D1,
+
+ 0x3892,0x18AE,0x3D33,0x49B6,0x3D53,0x1CAA,0x4153,0x4995,
+ 0x59F8,0x4DB5,0x55F9,0x5215,0x4DF4,0x5A78,0x30B1,0x28AD,
+ 0x208E,0x2A40,0x53A0,0x63E1,0x6FE5,0x6FE5,0x5BC2,0x5FC4,
+ 0x5FC3,0x67C4,0x6FC8,0x73C6,0x6BE6,0x29E0,0x2E00,0x2E00,
+ 0x3E82,0x5B47,0x1DA0,0x3EC0,0x3681,0x3680,0x4B03,0x5364,
+ 0x2A00,0x5384,0x5787,0x5B26,0x5FC4,0x5FE2,0x5BE2,0x3F00,
+ 0x4320,0x3AC0,0x2E40,0x2A20,0x4760,0x4300,0x4B41,0x3240,
+ 0x3220,0x3A61,0x3260,0x3280,0x2A60,0x32A0,0x2E00,0x3AA0,
+ 0x4722,0x3AA0,0x31C0,0x3200,0x3220,0x3620,0x3200,0x5385,
+ 0x67E7,0x5784,0x6388,0x6368,0x73AA,0x73CB,0x3A82,0x73C5,
+ 0x6BE7,0x1943,0x1542,0x08A1,0x0CE3,0x0CE1,0x1962,0x2164,
+ 0x29E5,0x25A3,0x25C4,0x2E25,0x3226,0x3227,0x1963,0x21A4,
+ 0x2DE8,0x1D84,0x25A5,0x1122,0x0460,0x0CE2,0x1543,0x1DA3,
+ 0x1DA4,0x25E5,0x25C5,0x2DE7,0x29C6,0x2E07,0x3A49,0x42CB,
+ 0x4F0C,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,0x301F,
+ 0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,0x7E9F,
+
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x001F,0x0FE0,0x1BE0,
+ 0x27E0,0x37E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x7FF5,
+ 0x7BDE,0xFFFF,0x35B3,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,
+ 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,
+ 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F,
+ 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92,
+ 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4,
+ 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6,
+ 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB,
+ 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539,
+ 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F,
+ 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F,
+ 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF,
+ 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF,
+ 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F,
+ 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x79BF,
+
+ 0x79FF,0x7A1F,0x7A5F,0x7A7F,0x7ABF,0x7B5F,0x7B7F,0x7DDF,
+ 0x7E1F,0x7E5F,0x7F1F,0x7F7F,0x7D7F,0x7E1F,0x7E5F,0x7EBF,
+ 0x7EFF,0x7F5F,0x7FBF,0x7FDF,0x7E3F,0x7E5F,0x7E7F,0x7E9F,
+ 0x7EBF,0x7EDF,0x7EFF,0x7F1F,0x7F3F,0x7F5F,0x7F7F,0x7FBF,
+ 0x7FFF,0x0000,0xFFFF,0x3C48,0x7FE0,0x7C1F,0x7C00,0x001F,
+ 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7DFF,0x7E9F,0x7BDE,0x7FE0,0x0445,0x08C5,0x04E5,0x0505,
+ 0x0525,0x0545,0x0565,0x0945,0x0965,0x0966,0x0986,0x09A6,
+ 0x198C,0x19AA,0x1D66,0x7FE0,0x1D82,0x1DA2,0x1DC2,0x218C,
+ 0x21AC,0x21C2,0x258D,0x25AC,0x29AD,0x29AE,0x29AF,0x29CF,
+ 0x29E2,0x2D91,0x2DB0,0x7FE0,0x2DF0,0x31D0,0x31D1,0x31D2,
+ 0x31F1,0x31F2,0x3592,0x35D1,0x35D2,0x35F2,0x35F3,0x3A33,
+ 0x3DF3,0x3DF4,0x3DF5,0x7FE0,0x3E14,0x3E15,0x3E33,0x3E34,
+ 0x3F62,0x41D3,0x41F5,0x4215,0x4216,0x4234,0x4235,0x4236,
+ 0x4382,0x4616,0x4617,0x7FE0,0x4636,0x4637,0x4639,0x4656,
+ 0x4657,0x4676,0x4A17,0x4A19,0x4A37,0x4A39,0x4E77,0x4E78,
+
+ 0x4FAD,0x5259,0x525A,0x7FE0,0x5279,0x527A,0x5299,0x5299,
+ 0x529A,0x53EC,0x53EE,0x5699,0x569A,0x56B9,0x56BA,0x56BC,
+ 0x5A9C,0x5ABA,0x5ABC,0x7FE0,0x5BF1,0x5EFB,0x5EFC,0x62BD,
+ 0x62FD,0x62FE,0x631D,0x66FD,0x671D,0x671E,0x673D,0x67B2,
+ 0x67D4,0x6B3E,0x6B3F,0x7FE0,0x6F7F,0x737F,0x739E,0x739F,
+ 0x73FD,0x77BF,0x77F9,0x7BBE,0x7BDD,0x7BFC,0x7FFA,0x7FFB,
+ 0x7FFC,0x7FFD,0x7FFF,0x7FE0,0x1D6C,0x2DD0,0x3E13,0x4635,
+ 0x5278,0x5ABD,0x6F7F,0x3C48,0x3C48,0x3C48,0x3C48,0x3C48,
+ 0x3C48,0x3C48,0x3C48,0x3971,0x0842,0x15C6,0x2666,0x1E8C,
+ 0x270A,0x32F1,0x2EAB,0x3BCF,0x3BD2,0x4BEE,0x53F6,0x5B94,
+ 0x6BB5,0x6FFB,0x7BDE,0xFFFF,0x0005,0x40CE,0x4232,0x56F8
+};
+static UINT16 bloodwar_mcu_4_0e[] = { // Warrior 4 Player 2
+ 0x0005,0x40CE,0x4232,0x56F8,0x2D8D,0x1D08,0x254A,0x2D8C,
+ 0x35CE,0x3E10,0x4652,0x4E94,0x56D6,0x5F18,0x675A,0x6F9C,
+ 0x7BDE,0x7BF9,0x6FF5,0x6BD4,0x63F1,0x538D,0x63F2,0x57EE,
+ 0x57EF,0x53EE,0x57CE,0x36E7,0x4FCD,0x4FEC,0x4FCA,0x2F06,
+ 0x1A63,0x3B29,0x1201,0x1622,0x0DC1,0x3F4A,0x3707,0x1A42,
+ 0x1221,0x3307,0x2EC6,0x0DE1,0x1E63,0x434B,0x53AC,0x67F0,
+ 0x1E24,0x3EE9,0x472B,0x4B4C,0x6BF3,0x6FF5,0x73F6,0x73F6,
+ 0x73F6,0x73F5,0x6FF5,0x5FF0,0x5FF1,0x476A,0x19A1,0x1161,
+ 0x19E1,0x2AC5,0x32C7,0x32E6,0x3F6A,0x3B28,0x2665,0x0941,
+ 0x3289,0x47CB,0x4BEB,0x4389,0x1A44,0x2285,0x2AA6,0x2284,
+ 0x1A23,0x7FFF,0x7FFE,0x7FFD,0x7FFD,0x77F9,0x5370,0x5392,
+ 0x4B2F,0x5792,0x5BB3,0x4F31,0x7FFD,0x7FFC,0x73D8,0x4F11,
+ 0x46F0,0x3E8E,0x322B,0x4EF1,0x4ED3,0x5332,0x5773,0x46AF,
+ 0x428F,0x266F,0x3AB0,0x364C,0x29E9,0x2A6D,0x2DEA,0x29C9,
+ 0x25C9,0x25C8,0x2E4B,0x1144,0x0D64,0x21A7,0x3B0B,0x2207,
+ 0x478E,0x4FB0,0x4B8F,0x53D2,0x6FF6,0x7FFA,0x6FF8,0x5FF4,
+
+ 0x36CC,0x536F,0x474D,0x3AEC,0x2A49,0x1DE5,0x2627,0x2E88,
+ 0x2E89,0x1E05,0x1184,0x0D24,0x15A6,0x1104,0x0D23,0x08E2,
+ 0x08E1,0x6BFF,0x577D,0x42D8,0x3697,0x3677,0x3256,0x3A98,
+ 0x3EBA,0x3EB9,0x3AB8,0x3654,0x2E55,0x2A13,0x3274,0x2610,
+ 0x21F1,0x2A91,0x0545,0x0946,0x2631,0x2A4F,0x2231,0x21AE,
+ 0x0566,0x15C8,0x29ED,0x25EC,0x222A,0x2EB0,0x36B4,0x3A94,
+ 0x1E11,0x7FFF,0x77F9,0x3ACA,0x3288,0x2A66,0x4B4E,0x3EEB,
+ 0x0900,0x2606,0x1563,0x0940,0x1142,0x1E43,0x430C,0x430B,
+ 0x3F0A,0x5FF3,0x53B0,0x3689,0x1DE3,0x2E67,0x15A2,0x5791,
+ 0x15A2,0x2E68,0x15A2,0x4F6E,0x2A47,0x4B2E,0x2607,0x2E47,
+ 0x3A8A,0x5390,0x3688,0x7BF8,0x77FB,0x5FD5,0x5BD4,0x73F7,
+ 0x77F9,0x3F0A,0x4F4F,0x2608,0x6FF7,0x5FF4,0x5FF1,0x5BB1,
+ 0x3EEA,0x4F6E,0x3EEC,0x1583,0x4B2D,0x57B1,0x2605,0x25C5,
+ 0x536F,0x73FA,0x6FF9,0x328A,0x3ECD,0x470D,0x5792,0x474E,
+ 0x5371,0x4191,0x3C00,0x4000,0x4400,0x4800,0x4C21,0x5063,
+ 0x5484,0x5CA5,0x64C6,0x7063,0x78A5,0x7DCE,0x7E94,0x7F39,
+
+ 0x7BDE,0xFFFF,0x41D3,0x0300,0x0340,0x0362,0x03A2,0x03C9,
+ 0x1FCC,0x27EE,0x37F0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF,
+ 0x6FFF,0x7FFF,0xFFFF,0x4191,0x0019,0x001B,0x001C,0x18DD,
+ 0x295D,0x319F,0x39DF,0x421F,0x4A5F,0x529F,0x5ADF,0x631F,
+ 0x6B5F,0x739F,0x7BDE,0xFFFF,0x4191,0x2EE0,0x3300,0x3B20,
+ 0x4340,0x4760,0x4F80,0x57A1,0x5BC0,0x67E2,0x6FE4,0x77E6,
+ 0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x0005,0x40CE,0x4232
+};
+static UINT16 bloodwar_mcu_4_0f[] = { // Warrior 4 Player 1
+ 0x0005,0x40CE,0x4232,0x56F8,0x2D8D,0x20E9,0x292B,0x316D,
+ 0x39AF,0x41F1,0x4A33,0x5275,0x5AB7,0x62F9,0x6B3B,0x737D,
+ 0x7BDF,0x7FFA,0x73F6,0x6FF5,0x67F2,0x57CE,0x67F3,0x5BEF,
+ 0x5BF0,0x57EF,0x5BEF,0x3B08,0x53EE,0x53ED,0x53EB,0x3327,
+ 0x1E84,0x3B29,0x1201,0x1622,0x0DC1,0x3F4A,0x3707,0x1A42,
+ 0x1221,0x3307,0x2EC6,0x0DE1,0x1E63,0x434B,0x53AC,0x67F0,
+ 0x1E24,0x3EE9,0x472B,0x4B4C,0x6BF3,0x6FF5,0x6FF6,0x73F7,
+ 0x73F6,0x73F7,0x6FF5,0x5FF0,0x5FF1,0x476A,0x19A1,0x1161,
+ 0x19E1,0x2AC5,0x32C7,0x32E6,0x3F6A,0x3B28,0x2665,0x0941,
+ 0x3289,0x47CB,0x4BEB,0x4389,0x1A44,0x2285,0x2AA6,0x2284,
+ 0x1A23,0x7FFF,0x7FFE,0x7FFD,0x7FFC,0x77F9,0x5370,0x5392,
+ 0x4B2F,0x5792,0x5BB3,0x4F31,0x7FFC,0x7FFB,0x73F8,0x4F11,
+ 0x46F0,0x3ECE,0x3289,0x4EF1,0x4F32,0x5332,0x5773,0x46AF,
+ 0x428F,0x1EC8,0x3309,0x368A,0x2A27,0x22C8,0x2E28,0x2A07,
+ 0x2607,0x25E6,0x2E69,0x1162,0x0D82,0x21C5,0x3B0B,0x2225,
+ 0x478E,0x4FB0,0x4B8F,0x53D2,0x6FF6,0x7FFA,0x6FF8,0x5FF4,
+
+ 0x36CC,0x538F,0x476D,0x3B0C,0x2A69,0x1E05,0x2647,0x2EA8,
+ 0x2EA9,0x1E25,0x11C3,0x0D63,0x15E5,0x1143,0x0D62,0x0921,
+ 0x0920,0x63F8,0x4FF2,0x3B8D,0x2F4C,0x2F2C,0x2B0B,0x334D,
+ 0x376F,0x376E,0x336D,0x2F09,0x270A,0x22C8,0x2B28,0x1EC5,
+ 0x1AA6,0x2327,0x05E1,0x05E1,0x1EC5,0x22E5,0x1AC5,0x1A44,
+ 0x0601,0x0E61,0x2283,0x1E82,0x1A81,0x2B46,0x2F49,0x332A,
+ 0x16A6,0x7FFF,0x77F9,0x3ACA,0x3288,0x2A66,0x4B4E,0x3EEB,
+ 0x0900,0x2606,0x1563,0x0940,0x1142,0x1E43,0x430C,0x430B,
+ 0x3F0A,0x5FF3,0x53B0,0x3689,0x1DE3,0x2E67,0x15A2,0x5791,
+ 0x15A2,0x2E68,0x15A2,0x4F6E,0x2A47,0x4B2E,0x2607,0x2E47,
+ 0x3A8A,0x5390,0x3688,0x7BF8,0x77FB,0x5FD5,0x5BD4,0x73F7,
+ 0x77F9,0x3F0A,0x4F4F,0x2608,0x6FF7,0x5FF4,0x5FF1,0x5BB1,
+ 0x3EEA,0x4B4D,0x3ACB,0x1162,0x470C,0x5390,0x21E4,0x21A4,
+ 0x4F4E,0x6FF9,0x6BF8,0x2E69,0x3AAC,0x42EC,0x5371,0x432D,
+ 0x4F50,0x4191,0x3C00,0x4000,0x4400,0x4800,0x4C21,0x5063,
+ 0x5484,0x5CA5,0x64C6,0x7063,0x78A5,0x7DCE,0x7E94,0x7F39,
+
+ 0x7BDE,0xFFFF,0x41D3,0x0300,0x0340,0x0362,0x03A2,0x03C9,
+ 0x1FCC,0x27EE,0x37F0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF,
+ 0x6FFF,0x7FFF,0xFFFF,0x4191,0x0019,0x001B,0x001C,0x18DD,
+ 0x295D,0x319F,0x39DF,0x421F,0x4A5F,0x529F,0x5ADF,0x631F,
+ 0x6B5F,0x739F,0x7BDE,0xFFFF,0x4191,0x2EE0,0x3300,0x3B20,
+ 0x4340,0x4760,0x4F80,0x57A1,0x5BC0,0x67E2,0x6FE4,0x77E6,
+ 0x7BEF,0x7FF4,0x7FFB,0x7BDE,0xFFFF,0x0009,0x0000,0x4232
+};
+static UINT16 bloodwar_mcu_4_10[] = { // Warrior 6 Player 1
+ 0x0009,0x0000,0x4232,0x56F8,0x2D8D,0x27FF,0x3BFF,0x53FF,
+ 0x63FF,0x401E,0x4C1F,0x581F,0x6C1F,0x7C1F,0x7E1F,0x7EBF,
+ 0x7BDE,0x4BCD,0x47EC,0x43CA,0x3BC8,0x2F45,0x2703,0x22E2,
+ 0x1EC1,0x1EE1,0x1AE1,0x16C0,0x12C0,0x0E80,0x0E40,0x1221,
+ 0x0580,0x2765,0x2324,0x1F03,0x1F23,0x1B22,0x12E0,0x12C1,
+ 0x1281,0x1241,0x0A00,0x05C0,0x0180,0x0140,0x0540,0x0520,
+ 0x0100,0x1A42,0x1622,0x1201,0x0E01,0x0580,0x0100,0x1A62,
+ 0x1E83,0x1641,0x0DE0,0x05A0,0x0560,0x53AF,0x3F4A,0x3308,
+ 0x2A86,0x3B29,0x2E87,0x1E43,0x26A5,0x1A22,0x1201,0x0DA1,
+ 0x1602,0x00C0,0x0540,0x0521,0x1663,0x1643,0x0DE1,0x1642,
+ 0x05C0,0x4EEF,0x5312,0x4AD0,0x3E4B,0x3A4B,0x31E9,0x3A2A,
+ 0x2DC8,0x2DA8,0x2987,0x2566,0x1D25,0x1504,0x25A7,0x2DC7,
+ 0x3608,0x2986,0x2DE7,0x3A2A,0x3207,0x25A5,0x21A4,0x29C5,
+ 0x3A4B,0x466A,0x3A08,0x3A28,0x3A08,0x2564,0x31A5,0x29A6,
+ 0x3184,0x2965,0x1903,0x2143,0x2163,0x2963,0x2164,0x2DA4,
+ 0x2583,0x31C5,0x1D63,0x2164,0x31A6,0x35E6,0x31C6,0x3E8A,
+
+ 0x3A69,0x2DE7,0x46CD,0x532F,0x3E8B,0x2DE6,0x10E2,0x1502,
+ 0x4ACD,0x530F,0x2E07,0x08C1,0x25A6,0x10E2,0x1522,0x1523,
+ 0x25A5,0x4ED1,0x3A2D,0x3A0C,0x31CA,0x360C,0x31EA,0x2DCA,
+ 0x360B,0x2568,0x2DA9,0x426E,0x468F,0x29A9,0x29A8,0x2588,
+ 0x1504,0x2988,0x2167,0x360A,0x426D,0x35EC,0x3E2D,0x52D1,
+ 0x4A90,0x3A2C,0x424E,0x3E4D,0x5310,0x5732,0x426C,0x6795,
+ 0x5B51,0x5B51,0x6FD5,0x6373,0x52EF,0x1D27,0x2549,0x10C4,
+ 0x08C2,0x18E6,0x35AE,0x31AC,0x2D8C,0x2DAD,0x31AD,0x256A,
+ 0x1D28,0x1506,0x0CC4,0x6FF8,0x63B3,0x4AED,0x3E8A,0x4F0F,
+ 0x42CC,0x6796,0x4A8F,0x3249,0x4AEE,0x5FB2,0x46ED,0x3A6A,
+ 0x322A,0x7BEE,0x63EA,0x57E9,0x4FA8,0x3B44,0x3AC4,0x2622,
+ 0x1141,0x4F0B,0x7BF9,0x67F2,0x5FB0,0x25E3,0x4F2D,0x5B70,
+ 0x4ACD,0x576E,0x574E,0x572F,0x1263,0x0E83,0x0EA3,0x1725,
+ 0x23C8,0x1304,0x17C4,0x22E6,0x1323,0x0A62,0x0621,0x01C1,
+ 0x05A1,0x41D3,0x0241,0x02A0,0x02E4,0x0322,0x0369,0x1F8C,
+ 0x27CE,0x37D0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF,0x6FFF,
+
+ 0x7FFF,0xFFFF,0x4191,0x11E0,0x1A20,0x2680,0x32C0,0x3B00,
+ 0x4740,0x4F61,0x57A0,0x63E2,0x6FE4,0x77E6,0x7BEF,0x7FF4,
+ 0x7FFB,0x7BDE,0xFFFF,0x4191,0x2000,0x2800,0x3000,0x3400,
+ 0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821,0x7084,0x7D29,
+ 0x7E52,0x7F39,0x7BDE,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77,
+ 0x12B9,0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F,
+ 0x639F,0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x7F40,0x7B60,
+ 0x7780,0x73A0,0x6FC0,0x6BE0,0x6BE0,0x6FE3,0x73E6,0x77E9,
+ 0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x4191,0x6000,0x6400,
+ 0x6800,0x6C00,0x7021,0x7484,0x78C6,0x7D29,0x7D68,0x7DA6,
+ 0x7DE4,0x7E23,0x7E82,0x7EE1,0x7BDE,0x21A6,0x2000,0x2400,
+ 0x2C00,0x3400,0x3800,0x3C00,0x4000,0x4400,0x4800,0x4C00,
+ 0x5000,0x5400,0x5800,0x5C00,0x31EA,0xFFFF,0x4191,0x47FF,
+ 0x4BFF,0x4FFF,0x53FF,0x57FF,0x5BFF,0x5FFF,0x63FF,0x67FF,
+ 0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF,0x7BDE,0x0421,0x179F,
+ 0x1BBF,0x1FDF,0x23FF,0x27FF,0x2BFF,0x2FFF,0x33FF,0x37FF,
+
+ 0x3BFF,0x3FFF,0x43FF,0x47FF,0x4BFF,0x7BDE,0x21A6,0x143F,
+ 0x10BF,0x0D1F,0x099F,0x05FF,0x063F,0x0A7F,0x0ABF,0x0EDF,
+ 0x0EFF,0x131F,0x133F,0x175F,0x177F,0x31EA,0xFFFF,0x4191,
+ 0x53E0,0x57E0,0x5BE0,0x5FE0,0x63E0,0x67E0,0x6BE0,0x6FE3,
+ 0x73E6,0x77E9,0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x0421,
+ 0x1BE0,0x1FE0,0x23E0,0x27E0,0x2BE0,0x2FE0,0x33E0,0x37E0,
+ 0x3BE0,0x3FE0,0x43E0,0x47E0,0x4BE0,0x4FE0,0x7BDE,0x21A6,
+ 0x1600,0x1620,0x1640,0x1660,0x1680,0x16A0,0x16C0,0x16E0,
+ 0x1700,0x1720,0x1740,0x1760,0x1780,0x1BA0,0x31EA,0xFFFF,
+ 0x4191,0x03EF,0x03EA,0x03E5,0x03E0,0x03E0,0x17E0,0x2BE0,
+ 0x3FE0,0x53E0,0x67E0,0x7FE0,0x7FEF,0x7FF4,0x7FF9,0x7BDE,
+ 0x0000,0x641F,0x501F,0x3C1F,0x281F,0x141F,0x001F,0x00BF,
+ 0x015F,0x01FF,0x029F,0x033F,0x03FF,0x03F9,0x03F4,0x7BDE,
+ 0x0000,0x7FEA,0x7FE0,0x7F20,0x7E80,0x7DE0,0x7D40,0x7CA0,
+ 0x7C00,0x7C05,0x780A,0x7C0F,0x7C14,0x7C19,0x7C1F,0x7BDE,
+ 0xFFFF,0x0009,0x0000,0x4232,0x56F8,0x2D8D,0x6C1F,0x7C1F
+};
+static UINT16 bloodwar_mcu_4_11[] = { // Warrior 6 Player 2
+ 0x0009,0x0000,0x4232,0x56F8,0x2D8D,0x6C1F,0x7C1F,0x7E1F,
+ 0x7EBF,0x5C13,0x5C52,0x6432,0x7075,0x7992,0x7DF6,0x7EF9,
+ 0x7BDE,0x52F2,0x4F11,0x4AEF,0x42CD,0x368A,0x2E48,0x2A27,
+ 0x2606,0x2626,0x2226,0x1E05,0x1A05,0x15C4,0x1584,0x1966,
+ 0x0CC4,0x2E69,0x2A48,0x2627,0x2647,0x2246,0x1A04,0x19E5,
+ 0x19C5,0x1985,0x1144,0x0D04,0x08C4,0x08A4,0x0CA4,0x0C84,
+ 0x0864,0x21A6,0x1D86,0x1965,0x1565,0x1104,0x10A4,0x21C6,
+ 0x25E7,0x1DA5,0x1544,0x1124,0x10E4,0x5B13,0x46AE,0x3A6C,
+ 0x31EA,0x428D,0x35EB,0x2587,0x2DE9,0x2166,0x1945,0x1505,
+ 0x1D66,0x0C64,0x10C4,0x10A5,0x1DC7,0x1DA7,0x1545,0x1DA6,
+ 0x0D24,0x4EEF,0x5312,0x4AD0,0x3E4B,0x3A4B,0x31E9,0x3A2A,
+ 0x2DC8,0x2DA8,0x2987,0x2566,0x1D25,0x1504,0x25A7,0x2DC7,
+ 0x3608,0x2986,0x2DE7,0x3A2A,0x3207,0x25A5,0x21A4,0x29C5,
+ 0x3A4B,0x466A,0x3A08,0x3A28,0x3A08,0x2564,0x31A5,0x29A6,
+ 0x3184,0x2965,0x1903,0x2143,0x2163,0x2963,0x2164,0x2DA4,
+ 0x2583,0x31C5,0x1D63,0x2164,0x31A6,0x35E6,0x31C6,0x3E8A,
+
+ 0x3A69,0x2DE7,0x46CD,0x532F,0x3E8B,0x2DE6,0x10E2,0x1502,
+ 0x4ACD,0x530F,0x2E07,0x08C1,0x25A6,0x10E2,0x1522,0x1523,
+ 0x25A5,0x4ED1,0x3A2D,0x3A0C,0x31CA,0x360C,0x31EA,0x2DCA,
+ 0x360B,0x2568,0x2DA9,0x426E,0x468F,0x29A9,0x29A8,0x2588,
+ 0x1504,0x2988,0x2167,0x360A,0x426D,0x35EC,0x3E2D,0x52D1,
+ 0x4A90,0x3A2C,0x424E,0x3E4D,0x5310,0x5732,0x426C,0x6795,
+ 0x5B51,0x5B51,0x6FD5,0x6373,0x52EF,0x1D27,0x2549,0x10C4,
+ 0x08C2,0x18E6,0x35AE,0x31AC,0x2D8C,0x2DAD,0x31AD,0x256A,
+ 0x1D28,0x1506,0x0CC4,0x6FF8,0x63B3,0x4AED,0x3E8A,0x4F0F,
+ 0x42CC,0x6796,0x4A8F,0x3249,0x4AEE,0x5FB2,0x46ED,0x3A6A,
+ 0x322A,0x7BEE,0x63EA,0x57E9,0x4FA8,0x3B44,0x3AC4,0x2622,
+ 0x1141,0x4F0B,0x7BF9,0x67F2,0x5FB0,0x25E3,0x4F2D,0x5B70,
+ 0x4ACD,0x576E,0x574E,0x572F,0x1263,0x0E83,0x0EA3,0x1725,
+ 0x23C8,0x1304,0x17C4,0x22E6,0x1323,0x0A62,0x0621,0x01C1,
+ 0x05A1,0x41D3,0x0241,0x02A0,0x02E4,0x0322,0x0369,0x1F8C,
+ 0x27CE,0x37D0,0x3FF3,0x47F6,0x53FB,0x5FFF,0x6BFF,0x6FFF,
+
+ 0x7FFF,0xFFFF,0x4191,0x11E0,0x1A20,0x2680,0x32C0,0x3B00,
+ 0x4740,0x4F61,0x57A0,0x63E2,0x6FE4,0x77E6,0x7BEF,0x7FF4,
+ 0x7FFB,0x7BDE,0xFFFF,0x4191,0x2000,0x2800,0x3000,0x3400,
+ 0x3800,0x4000,0x4800,0x5400,0x5C00,0x6821,0x7084,0x7D29,
+ 0x7E52,0x7F39,0x7BDE,0xFFFF,0x41D3,0x01D1,0x0215,0x0A77,
+ 0x12B9,0x16FB,0x273C,0x375D,0x435E,0x4B7F,0x537F,0x5B9F,
+ 0x639F,0x6FBF,0x77DF,0x7FFF,0xFFFF,0x4191,0x7F40,0x7B60,
+ 0x7780,0x73A0,0x6FC0,0x6BE0,0x6BE0,0x6FE3,0x73E6,0x77E9,
+ 0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x4191,0x6000,0x6400,
+ 0x6800,0x6C00,0x7021,0x7484,0x78C6,0x7D29,0x7D68,0x7DA6,
+ 0x7DE4,0x7E23,0x7E82,0x7EE1,0x7BDE,0x21A6,0x2000,0x2400,
+ 0x2C00,0x3400,0x3800,0x3C00,0x4000,0x4400,0x4800,0x4C00,
+ 0x5000,0x5400,0x5800,0x5C00,0x31EA,0xFFFF,0x4191,0x47FF,
+ 0x4BFF,0x4FFF,0x53FF,0x57FF,0x5BFF,0x5FFF,0x63FF,0x67FF,
+ 0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF,0x7BDE,0x0421,0x179F,
+ 0x1BBF,0x1FDF,0x23FF,0x27FF,0x2BFF,0x2FFF,0x33FF,0x37FF,
+
+ 0x3BFF,0x3FFF,0x43FF,0x47FF,0x4BFF,0x7BDE,0x21A6,0x143F,
+ 0x10BF,0x0D1F,0x099F,0x05FF,0x063F,0x0A7F,0x0ABF,0x0EDF,
+ 0x0EFF,0x131F,0x133F,0x175F,0x177F,0x31EA,0xFFFF,0x4191,
+ 0x53E0,0x57E0,0x5BE0,0x5FE0,0x63E0,0x67E0,0x6BE0,0x6FE3,
+ 0x73E6,0x77E9,0x7BEC,0x7FEF,0x7FF4,0x7FF9,0x7BDE,0x0421,
+ 0x1BE0,0x1FE0,0x23E0,0x27E0,0x2BE0,0x2FE0,0x33E0,0x37E0,
+ 0x3BE0,0x3FE0,0x43E0,0x47E0,0x4BE0,0x4FE0,0x7BDE,0x21A6,
+ 0x1600,0x1620,0x1640,0x1660,0x1680,0x16A0,0x16C0,0x16E0,
+ 0x1700,0x1720,0x1740,0x1760,0x1780,0x1BA0,0x31EA,0xFFFF,
+ 0x4191,0x03EF,0x03EA,0x03E5,0x03E0,0x03E0,0x17E0,0x2BE0,
+ 0x3FE0,0x53E0,0x67E0,0x7FE0,0x7FEF,0x7FF4,0x7FF9,0x7BDE,
+ 0x0000,0x641F,0x501F,0x3C1F,0x281F,0x141F,0x001F,0x00BF,
+ 0x015F,0x01FF,0x029F,0x033F,0x03FF,0x03F9,0x03F4,0x7BDE,
+ 0x0000,0x7FEA,0x7FE0,0x7F20,0x7E80,0x7DE0,0x7D40,0x7CA0,
+ 0x7C00,0x7C05,0x780A,0x7C0F,0x7C14,0x7C19,0x7C1F,0x7BDE,
+ 0xFFFF,0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A
+};
+static UINT16 bloodwar_mcu_4_12[] = { // Warrior 9 Player 1
+ 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x1AC2,0x1AE2,0x1B02,0x1703,0x1723,0x1743,0x1763,
+ 0x1784,0x1BA3,0x17A3,0x1BC4,0x1BC6,0x1FE5,0x12C2,0x1BE5,
+ 0x1FC5,0x1FA5,0x1B65,0x1F64,0x2386,0x2786,0x1B83,0x1BA4,
+ 0x23A6,0x23E7,0x1FC5,0x23E7,0x1FE6,0x1FE8,0x1FC8,0x1AA4,
+ 0x1A84,0x1703,0x1704,0x1B04,0x1F84,0x1723,0x1F46,0x23A7,
+ 0x1B05,0x1BC4,0x13A3,0x16C3,0x1AE4,0x2FE8,0x43EB,0x37EB,
+ 0x2FEA,0x37EC,0x3BED,0x3FEE,0x3FED,0x43EE,0x43EE,0x43EE,
+ 0x33EB,0x37EB,0x37EB,0x33EA,0x3BEC,0x3BEC,0x37EB,0x3FEC,
+ 0x3FED,0x25C7,0x2E08,0x428E,0x5751,0x5F93,0x5B71,0x67F3,
+ 0x67B5,0x6FD8,0x6793,0x6FF7,0x73F8,0x6BB6,0x73D8,0x77F9,
+ 0x77FA,0x428F,0x46CD,0x4B0F,0x46D0,0x5732,0x67D5,0x63B5,
+ 0x63B5,0x6BB6,0x6BD6,0x6FD7,0x67B7,0x73F9,0x6376,0x6776,
+ 0x5F54,0x1104,0x10E4,0x10E4,0x1524,0x1525,0x1164,0x15A4,
+ 0x1965,0x1103,0x1544,0x1103,0x1564,0x1584,0x1604,0x1986,
+
+ 0x0CA3,0x1525,0x10E4,0x1925,0x10C4,0x14E5,0x10A4,0x2167,
+ 0x29A8,0x2587,0x29C9,0x29C8,0x320A,0x320B,0x25A8,0x1DA6,
+ 0x1D47,0x1128,0x1528,0x1223,0x1664,0x158A,0x19AB,0x1DAC,
+ 0x21EE,0x21ED,0x220D,0x220C,0x222D,0x194A,0x21CD,0x21AD,
+ 0x260E,0x220E,0x25EF,0x29E9,0x2DEA,0x3A0C,0x3E2D,0x2A0F,
+ 0x29EE,0x46D2,0x428F,0x4AD1,0x46B1,0x4690,0x428D,0x2608,
+ 0x4250,0x2903,0x2D44,0x3565,0x41C8,0x3DA7,0x3986,0x41E8,
+ 0x4A08,0x41E7,0x45E8,0x524B,0x3526,0x564E,0x49ED,0x3DA8,
+ 0x416B,0x2E84,0x4746,0x5787,0x4F46,0x57A8,0x4B45,0x5FE9,
+ 0x5BAB,0x578A,0x57AA,0x5369,0x5FE8,0x53A8,0x4FA7,0x4344,
+ 0x4345,0x0D63,0x1162,0x1983,0x19A4,0x15A4,0x19C4,0x19E4,
+ 0x1DE4,0x1A04,0x1E05,0x2246,0x2647,0x2A26,0x2A46,0x2646,
+ 0x2625,0x2E88,0x3669,0x36AA,0x2626,0x2646,0x2226,0x36EA,
+ 0x36EB,0x3AEB,0x36CB,0x36CA,0x3ACC,0x3A8B,0x536F,0x63B3,
+ 0x4B0F,0x290D,0x6004,0x7FFF,0x6409,0x681F,0x281F,0x401F,
+ 0x2BFF,0x4FFF,0x77FF,0x7C5F,0x681F,0x541F,0x7E15,0x7FE0,
+
+ 0x03E0,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0,
+ 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC,
+ 0x7FFF,0x2E88,0x3669,0x1E04,0x0DE2,0x2646,0x2226,0x36EA,
+ 0x2E6A,0x3AEB,0x36CB,0x32A9,0x430C,0x3A8B,0x536F,0x63B3,
+ 0x4B0F,0x0000,0x201B,0x241D,0x2C1F,0x341F,0x3C1E,0x401F,
+ 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B1F,
+ 0x7BDE,0x7FFA,0x1CC2,0x2065,0x2083,0x24C4,0x24E2,0x2502,
+ 0x2503,0x28A5,0x2D43,0x2D45,0x2D63,0x2D64,0x3144,0x3145,
+ 0x3583,0x3584,0x3586,0x3587,0x35C3,0x3986,0x3987,0x39C3,
+ 0x39E5,0x39E7,0x39E8,0x39E3,0x3A05,0x3A23,0x41C6,0x41E5,
+ 0x4205,0x420A,0x4226,0x4229,0x4263,0x4265,0x4266,0x4267,
+ 0x4287,0x46E3,0x4A07,0x4A0B,0x4A26,0x4A27,0x4A29,0x4A65,
+ 0x4A66,0x4A8A,0x4AA5,0x4AA6,0x4AA8,0x4AC5,0x4AE3,0x524C,
+ 0x5286,0x5289,0x52A6,0x52C9,0x52E5,0x52E6,0x52E8,0x52E9,
+ 0x5AC6,0x5AC9,0x5AE6,0x5AE8,0x5AE9,0x5AEB,0x62E6,0x62E8,
+ 0x62E9,0x62EA,0x62EB,0x62EC,0x6AE8,0x6AEA,0x6AED,0x6AEE,
+
+ 0x6AF0,0x6EE8,0x6EEA,0x6EED,0x6EEE,0x6EF0,0x76EA,0x76EB,
+ 0x76ED,0x770E,0x7710,0x7711,0x7712,0x7713,0x7F0D,0x7F0F,
+ 0x7F10,0x7F12,0x7F13,0x7F35,0x7F1A,0x7F1B,0x7F0E,0x7F30,
+ 0x7F32,0x7F38,0x7F5B,0x7F6B,0x7F70,0x7F92,0x7F95,0x7F97,
+ 0x7F9A,0x7FBE,0x7FDF,0x7F91,0x7FB2,0x7FB3,0x7FB4,0x7FB5,
+ 0x7FB6,0x7FB7,0x7FB8,0x7FB9,0x7FBF,0x7FBB,0x7FFF,0x7FFF,
+ 0x0000,0xFFFF,0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108
+};
+static UINT16 bloodwar_mcu_4_13[] = { // Warrior 9 Player 2
+ 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x146D,0x1CAF,0x24EF,0x24EF,0x2910,0x3553,0x3DB7,
+ 0x45B8,0x3993,0x2610,0x4196,0x2632,0x2A52,0x1D2F,0x2652,
+ 0x569A,0x2A15,0x4A19,0x41D6,0x41F8,0x39D6,0x25F2,0x2613,
+ 0x2E15,0x2E56,0x2A34,0x2E56,0x2A55,0x2A56,0x2A36,0x1C6D,
+ 0x2931,0x20B0,0x2D33,0x3133,0x4196,0x3596,0x3575,0x39D6,
+ 0x3134,0x31D5,0x2994,0x2CF2,0x3113,0x3D98,0x41D8,0x3E3A,
+ 0x4E1B,0x4DF9,0x521A,0x563B,0x561A,0x5A3C,0x629F,0x5A3C,
+ 0x49B8,0x5618,0x4DD8,0x4997,0x49F9,0x51F9,0x4DF8,0x561A,
+ 0x561B,0x25E6,0x2E27,0x42CD,0x5F92,0x5FD2,0x5BB0,0x67F4,
+ 0x6FF7,0x6FF7,0x67D2,0x6FF6,0x73F7,0x6BF5,0x73F7,0x77F8,
+ 0x77F9,0x42EC,0x3EE9,0x4B4E,0x470F,0x5771,0x6FF7,0x67F3,
+ 0x63F3,0x67F4,0x73F7,0x5FB5,0x67F6,0x73F8,0x63B5,0x5FB5,
+ 0x5F93,0x1063,0x1484,0x18A5,0x0C42,0x1CC6,0x0C42,0x1063,
+ 0x0C42,0x0C42,0x1484,0x1484,0x1063,0x10C9,0x1449,0x1986,
+
+ 0x0C42,0x1484,0x1063,0x1063,0x1484,0x18A5,0x10A4,0x18A5,
+ 0x29A8,0x18A5,0x29C9,0x29C8,0x320A,0x320B,0x18A5,0x1484,
+ 0x1D47,0x1128,0x1528,0x1068,0x146B,0x158A,0x19AB,0x1DAC,
+ 0x21EE,0x21ED,0x220D,0x220C,0x222D,0x194A,0x21CD,0x21AD,
+ 0x260E,0x220E,0x25EF,0x29E9,0x2DEA,0x3A0C,0x3E2D,0x2A0F,
+ 0x29EE,0x46D2,0x428F,0x4AD1,0x46B1,0x4690,0x428D,0x2608,
+ 0x4250,0x11C2,0x1683,0x2302,0x2305,0x1B22,0x1EC3,0x2385,
+ 0x3FE6,0x3344,0x2FC4,0x4FE7,0x2AE3,0x376B,0x2B0A,0x22C5,
+ 0x2688,0x2E84,0x4746,0x5787,0x4F46,0x57A8,0x4B45,0x5FE9,
+ 0x5BAB,0x578A,0x57AA,0x5369,0x5FE8,0x53A8,0x4FA7,0x4344,
+ 0x4345,0x0D63,0x1162,0x1983,0x19A4,0x15A4,0x19C4,0x19E4,
+ 0x1DE4,0x1A04,0x1E05,0x2246,0x2647,0x2A26,0x2A46,0x2646,
+ 0x2625,0x2E88,0x3669,0x36AA,0x2626,0x2646,0x2226,0x36EA,
+ 0x36EB,0x3AEB,0x36CB,0x36CA,0x4B0D,0x3A8B,0x4F8E,0x63B3,
+ 0x4B0F,0x290D,0x6004,0x7FFF,0x6409,0x681F,0x281F,0x401F,
+ 0x2BFF,0x4FFF,0x77FF,0x7C5F,0x681F,0x541F,0x7E15,0x7FE0,
+
+ 0x03E0,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0,
+ 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC,
+ 0x7FFF,0x2E88,0x3669,0x1E04,0x0DE2,0x2646,0x2226,0x36EA,
+ 0x2E6A,0x3AEB,0x36CB,0x32A9,0x430C,0x3A8B,0x536F,0x63B3,
+ 0x4B0F,0x0000,0x201B,0x241D,0x2C1F,0x341F,0x3C1E,0x401F,
+ 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B1F,
+ 0x7BDE,0x7FFA,0x1CC2,0x2065,0x2083,0x24C4,0x24E2,0x2502,
+ 0x2503,0x28A5,0x2D43,0x2D45,0x2D63,0x2D64,0x3144,0x3145,
+ 0x3583,0x3584,0x3586,0x3587,0x35C3,0x3986,0x3987,0x39C3,
+ 0x39E5,0x39E7,0x39E8,0x39E3,0x3A05,0x3A23,0x41C6,0x41E5,
+ 0x4205,0x420A,0x4226,0x4229,0x4263,0x4265,0x4266,0x4267,
+ 0x4287,0x46E3,0x4A07,0x4A0B,0x4A26,0x4A27,0x4A29,0x4A65,
+ 0x4A66,0x4A8A,0x4AA5,0x4AA6,0x4AA8,0x4AC5,0x4AE3,0x524C,
+ 0x5286,0x5289,0x52A6,0x52C9,0x52E5,0x52E6,0x52E8,0x52E9,
+ 0x5AC6,0x5AC9,0x5AE6,0x5AE8,0x5AE9,0x5AEB,0x62E6,0x62E8,
+ 0x62E9,0x62EA,0x62EB,0x62EC,0x6AE8,0x6AEA,0x6AED,0x6AEE,
+
+ 0x6AF0,0x6EE8,0x6EEA,0x6EED,0x6EEE,0x6EF0,0x76EA,0x76EB,
+ 0x76ED,0x770E,0x7710,0x7711,0x7712,0x7713,0x7F0D,0x7F0F,
+ 0x7F10,0x7F12,0x7F13,0x7F35,0x7F1A,0x7F1B,0x7F0E,0x7F30,
+ 0x7F32,0x7F38,0x7F5B,0x7F6B,0x7F70,0x7F92,0x7F95,0x7F97,
+ 0x7F9A,0x7FBE,0x7FDF,0x7F91,0x7FB2,0x7FB3,0x7FB4,0x7FB5,
+ 0x7FB6,0x7FB7,0x7FB8,0x7FB9,0x7FBF,0x7FBB,0x7FFF,0x7FFF,
+ 0x0000,0xFFFF,0x0006,0x0000,0x4232,0x56F8,0x2D8D,0x2108
+};
+static UINT16 bloodwar_mcu_4_14[] = { // Warrior 7 Player 1
+ 0x0006,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x0D00,0x0D00,0x0D40,0x0D40,0x0D60,0x0D80,0x1140,
+ 0x1561,0x1581,0x15A1,0x15E1,0x1601,0x19A1,0x19C1,0x19C2,
+ 0x19E1,0x1E23,0x1E42,0x1E43,0x1E82,0x2204,0x2223,0x2242,
+ 0x2243,0x2244,0x2262,0x2263,0x22A2,0x22A3,0x2664,0x2683,
+ 0x2684,0x2AA3,0x2AA4,0x2EC3,0x2EC4,0x32A4,0x32C3,0x32C4,
+ 0x3304,0x3305,0x3325,0x3344,0x36C5,0x3704,0x3705,0x3706,
+ 0x3707,0x3B45,0x3B46,0x3B65,0x3B84,0x3B85,0x3F05,0x3F27,
+ 0x3F28,0x3F44,0x3F46,0x3F47,0x3F65,0x3F66,0x3F67,0x3F85,
+ 0x3FA5,0x4328,0x4347,0x43A6,0x47A7,0x47A8,0x47C6,0x47C7,
+ 0x47E5,0x47E6,0x4B69,0x4BA7,0x4BA8,0x4BC6,0x4BC7,0x4BC8,
+ 0x4BE7,0x57E9,0x57E8,0x57E7,0x5BCA,0x5BE9,0x5BEA,0x5BEC,
+ 0x5BE8,0x5BE9,0x5BE8,0x5BEB,0x5F6E,0x5FCD,0x5FEB,0x5FE9,
+ 0x5BEC,0x67E9,0x67EA,0x67EC,0x67ED,0x6FED,0x6FED,0x6FEE,
+ 0x6FEF,0x6FEC,0x6FEC,0x6FED,0x6FEB,0x6FED,0x6FEC,0x73EE,
+
+ 0x73EC,0x77F1,0x77F0,0x77F1,0x7BF1,0x7BF2,0x7BF3,0x7BF1,
+ 0x7BF2,0x7FF2,0x7FF4,0x7FF2,0x7FF4,0x7FF2,0x7FF4,0x7FF4,
+ 0x7FF5,0x33E9,0x0D82,0x0DC1,0x0DC2,0x0DE1,0x0DE2,0x0E02,
+ 0x1223,0x1243,0x1263,0x12A3,0x12C3,0x12E3,0x1303,0x1323,
+ 0x1343,0x16E3,0x1703,0x1723,0x1743,0x1783,0x1784,0x17A3,
+ 0x17A4,0x17C4,0x17E4,0x1AC3,0x1AE3,0x1AE4,0x1B03,0x1B04,
+ 0x1B43,0x1F45,0x1F65,0x1F85,0x1FA4,0x1FA5,0x1FA6,0x1FC5,
+ 0x1FE5,0x1FE6,0x1FE8,0x23E6,0x23E7,0x23E8,0x23E8,0x27E7,
+ 0x27E7,0x2BE8,0x2BE9,0x2BEA,0x2BE8,0x2FE9,0x2FEA,0x2FE9,
+ 0x2FEA,0x2FE9,0x2FE9,0x2FEB,0x33EB,0x3BEB,0x3FEE,0x3FEE,
+ 0x47F0,0x7FF8,0x25E6,0x29A6,0x29A7,0x2DE7,0x3A0A,0x46AC,
+ 0x4ACC,0x4EEF,0x4F2F,0x532F,0x574E,0x67F1,0x63D2,0x63EF,
+ 0x63F1,0x6BF5,0x6BF6,0x6FB7,0x6FF5,0x6FF6,0x6FF7,0x6FF6,
+ 0x77F6,0x77F7,0x77F8,0x77F9,0x7BF8,0x7FFA,0x7FFB,0x7BDC,
+ 0x7FFA,0x41D3,0x0000,0x0000,0x131A,0x2BBF,0x4FBF,0x23E0,
+ 0x43E0,0x67ED,0x4C07,0x6409,0x7CCF,0x3C1F,0x541F,0x6C1F,
+
+ 0x7FFF,0x7C00,0x3786,0x37A6,0x3B86,0x3BC6,0x3F47,0x3F86,
+ 0x3FC6,0x3FE6,0x3FE7,0x47A7,0x47C6,0x47C7,0x47E6,0x47E7,
+ 0x4BA7,0x4BA8,0x4BC7,0x4BC8,0x4BE7,0x4BE8,0x4FA8,0x4FC8,
+ 0x4FE8,0x53C8,0x53CA,0x53CB,0x53EA,0x53EB,0x53EC,0x5BCC,
+ 0x5BCD,0x5BD0,0x5BEB,0x5BEC,0x5BED,0x5BEE,0x5FD0,0x5FED,
+ 0x5FEF,0x5FF0,0x5FF2,0x63EF,0x63F1,0x63F2,0x63F3,0x63F5,
+ 0x63F6,0x6BF3,0x6BF5,0x6BF6,0x6BF7,0x6BF8,0x6FF6,0x6FF7,
+ 0x6FF8,0x6FFA,0x6FFB,0x6FFC,0x73FB,0x73FC,0x73FD,0x73FF,
+ 0x7FFF,0x53E7,0x5FE8,0x4FE7,0x4BE7,0x3FE6,0x37C6,0x33A6,
+ 0x2BA6,0x2366,0x2325,0x2346,0x2304,0x2786,0x2306,0x2746,
+ 0x1F24,0x1F04,0x2345,0x1F06,0x33C6,0x33E6,0x27A6,0x2785,
+ 0x2B86,0x1EC4,0x37E6,0x37A6,0x3BE6,0x2745,0x47E6,0x4BE6,
+ 0x4FE6,0x47E7,0x5BE8,0x5BEA,0x3B86,0x3766,0x4BE8,0x53E8,
+ 0x5FEA,0x63EB,0x6FEF,0x73F0,0x73F1,0x6FF0,0x6FED,0x6BEC,
+ 0x63EA,0x5FE9,0x63E9,0x1AE4,0x2365,0x2BA5,0x27A5,0x1AA4,
+ 0x22C6,0x2B85,0x1A24,0x3386,0x3FC6,0x3FE7,0x2726,0x2B46,
+
+ 0x3366,0x15C4,0x15E5,0x1644,0x1605,0x1604,0x1E84,0x1EC6,
+ 0x2306,0x15E4,0x1625,0x22C6,0x1664,0x1624,0x1EA6,0x1E86,
+ 0x1645,0x6ABB,0x6A9B,0x6A5B,0x663A,0x661A,0x5DD9,0x5D99,
+ 0x5519,0x48B7,0x4896,0x140C,0x140D,0x140B,0x100B,0x100A,
+ 0x1009,0x0C08,0x0C09,0x200F,0x200D,0x1C0D,0x1C0A,0x200C,
+ 0x200A,0x2009,0x202A,0x204A,0x208B,0x24C9,0x24C7,0x356D,
+ 0x1C0C,0x1410,0x1412,0x1C13,0x2015,0x2417,0x2C17,0x3419,
+ 0x3819,0x4419,0x4877,0x4C39,0x4C59,0x4C79,0x543A,0x5479,
+ 0x55D6,0x5859,0x5879,0x5CB9,0x5CBA,0x5CDA,0x5D39,0x5D59,
+ 0x5D9B,0x60F9,0x651B,0x655B,0x6A1B,0x6A3B,0x6ABB,0x6ADB,
+ 0x6F1B,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,
+ 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,
+ 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F,
+ 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92,
+ 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4,
+ 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6,
+
+ 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB,
+ 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539,
+ 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F,
+ 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F,
+ 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF,
+ 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF,
+ 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F,
+ 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x75BF,
+ 0x75FF,0x761F,0x723F,0x725F,0x769F,0x773F,0x7B7F,0x75BF,
+ 0x75FF,0x7A3F,0x7AFF,0x7F7F,0x755F,0x75FF,0x763F,0x7A9F,
+ 0x7ADF,0x7F5F,0x7FBF,0x7FDF,0x75FF,0x761F,0x763F,0x765F,
+ 0x7A7F,0x7A9F,0x7ABF,0x7EDF,0x7EFF,0x7F3F,0x7F7F,0x7FBF,
+ 0x7FFF,0x0000,0xFFFF,0x31EC,0x7FE0,0x7C1F,0x7C00,0x001F,
+ 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7DFF,0x7E9F,0x7BDE,0x7FFC,0x1C40,0x1C81,0x2060,0x2880,
+ 0x2C80,0x38C1,0x38C1,0x38C1,0x38C1,0x38C1,0x3CC0,0x3CC0,
+
+ 0x38E0,0x38E1,0x4100,0x4500,0x4503,0x4503,0x4D00,0x4522,
+ 0x4522,0x4D20,0x5121,0x5123,0x5124,0x5520,0x5521,0x5920,
+ 0x4D62,0x5161,0x5561,0x5565,0x5961,0x5964,0x6160,0x6160,
+ 0x6161,0x6162,0x6562,0x6982,0x55A2,0x59A6,0x59A1,0x59A2,
+ 0x59A4,0x61A0,0x61A1,0x65A4,0x69A0,0x69A0,0x69A2,0x6DA0,
+ 0x71A0,0x5DE6,0x5DE0,0x65E3,0x69E0,0x6DE3,0x71E0,0x71E1,
+ 0x71E3,0x71C3,0x6E20,0x6E24,0x7221,0x7223,0x7224,0x7226,
+ 0x7261,0x7263,0x7264,0x7265,0x7266,0x7267,0x72A3,0x72A5,
+ 0x72A8,0x72A9,0x72AB,0x72C3,0x72C5,0x72C7,0x72C9,0x72C1,
+ 0x7306,0x7306,0x7308,0x7309,0x730B,0x730C,0x730D,0x730E,
+ 0x7328,0x732A,0x732B,0x7308,0x774C,0x7B90,0x7BB4,0x7FD9,
+ 0x7728,0x774B,0x7B8C,0x7FB5,0x7FD9,0x7725,0x772A,0x7B4D,
+ 0x7B70,0x7FB4,0x7FF9,0x7FFC,0x7FFD,0x7B4A,0x7B4B,0x7B4C,
+ 0x7B2D,0x7B6E,0x7B6F,0x7B90,0x7BB2,0x7BB3,0x7FD6,0x7FD8,
+ 0x7BDA,0x7FFE,0x0000,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00,
+ 0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,
+
+ 0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7F9F,0x1DD0,0x25F0,0x1DF1,
+ 0x2213,0x1A14,0x1E17,0x2237,0x2637,0x2657,0x2657,0x1E58,
+ 0x2278,0x2278,0x2678,0x1E99,0x22B9,0x2AB9,0x2EB9,0x1EBB,
+ 0x2AD9,0x2ED9,0x1EDB,0x2EDC,0x36DC,0x32DC,0x1EDD,0x26DE,
+ 0x1EDE,0x2B1B,0x271C,0x271D,0x3B3C,0x2B3D,0x331C,0x1B1E,
+ 0x26FE,0x2B1E,0x2F1F,0x2F1F,0x1F3F,0x335B,0x373B,0x2F3C,
+ 0x333C,0x333C,0x2B3E,0x2F3E,0x375E,0x235F,0x2F1F,0x2F5F,
+ 0x235F,0x1B5F,0x2B7A,0x2F9A,0x339C,0x2B9D,0x339E,0x379F,
+ 0x379F,0x3F9F,0x3F9F,0x3BDE,0x3B9E,0x2F9F,0x379F,0x3B9F,
+ 0x439F,0x2B9F,0x379F,0x3B9F,0x3F9F,0x439F,0x479F,0x37BF,
+ 0x3FDF,0x4BDF,0x4FDF,0x57DF,0x37BF,0x3FDF,0x479E,0x4B9F,
+ 0x539F,0x47DF,0x4BDF,0x4FDF,0x53DF,0x57DF,0x5BDF,0x5FDF,
+ 0x63FF,0x57FF,0x5BFF,0x5FFF,0x5BDF,0x63DF,0x6BFF,0x73FF,
+ 0x7BFF,0x5FFF,0x63FF,0x67FF,0x73FF,0x7BFF,0x5FFF,0x63FF,
+ 0x67FF,0x6FFF,0x73FF,0x77FF,0x7FBF,0x7FDF,0x57FF,0x5BFF,
+ 0x5FFF,0x63FF,0x67FF,0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF,
+
+ 0x7BFF,0x7FFF,0x7FFF,0x0000,0xFFFF,0x28ED,0x7FE0,0x7C1F,
+ 0x7C00,0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,
+ 0x701F,0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7FFA,0x1180,0x1580,
+ 0x15C0,0x19C0,0x1600,0x1A00,0x1A40,0x1E40,0x1E80,0x2280,
+ 0x1EA0,0x22A0,0x1EC0,0x22C0,0x26C0,0x2300,0x2302,0x2303,
+ 0x2300,0x2702,0x2B03,0x2720,0x2723,0x2743,0x2744,0x2760,
+ 0x2761,0x2762,0x2B60,0x2B62,0x2F61,0x3366,0x3380,0x3383,
+ 0x33A6,0x33A1,0x33A2,0x33C3,0x37C3,0x37C0,0x3762,0x3766,
+ 0x3781,0x3782,0x3784,0x37A0,0x37A1,0x3BA6,0x3BC1,0x3BC2,
+ 0x3BC4,0x3BE0,0x3BE3,0x3F87,0x3FA1,0x3FA4,0x3FC1,0x3FE4,
+ 0x3FE0,0x3FE1,0x3FE3,0x3FE4,0x43E0,0x4BE2,0x4BE4,0x4BE6,
+ 0x4BE8,0x4BEA,0x53E2,0x53E4,0x53E6,0x53E8,0x53EA,0x53EC,
+ 0x5BE4,0x5BE6,0x5BE8,0x5BEA,0x5BEC,0x5FE4,0x5FE6,0x5FE8,
+ 0x5FEA,0x5FEC,0x67E2,0x67E4,0x67E6,0x67E8,0x67EA,0x67EC,
+ 0x6FE8,0x6FEA,0x6FEC,0x6FEE,0x6FF0,0x73E0,0x73E8,0x73F0,
+ 0x73F4,0x73F9,0x77E0,0x77E8,0x77F0,0x77F4,0x77F9,0x7BE2,
+
+ 0x7BE6,0x7BEC,0x7BF2,0x7BF5,0x7BF9,0x7FFB,0x7BFC,0x77E0,
+ 0x77E2,0x77E4,0x77E6,0x77E8,0x7BEA,0x7BED,0x7BF0,0x7BF3,
+ 0x7BF6,0x7BF9,0x7BFB,0x7FFF,0x0000,0xFFFF,0x0006,0x3CB1
+};
+static UINT16 bloodwar_mcu_4_15[] = { // Warrior 7 Player 2
+ 0x0006,0x3CB1,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x1CCB,0x1049,0x184A,0x18E9,0x1CAA,0x1C4C,0x20AE,
+ 0x210D,0x214C,0x20EB,0x210D,0x20CB,0x292D,0x252D,0x292E,
+ 0x252D,0x254C,0x292E,0x254C,0x252C,0x294D,0x290C,0x2D2D,
+ 0x294C,0x2D4D,0x314F,0x296F,0x318E,0x3570,0x3571,0x3551,
+ 0x3531,0x35D0,0x39F1,0x3190,0x3DD1,0x41D1,0x3E12,0x41D3,
+ 0x3DB3,0x39B2,0x3DF2,0x4253,0x45F3,0x49F2,0x3DD2,0x3E32,
+ 0x41B3,0x4A55,0x4654,0x41F3,0x4613,0x45D3,0x4A56,0x4A75,
+ 0x45D4,0x45F4,0x4E35,0x45F2,0x4612,0x4674,0x45F4,0x4A35,
+ 0x4A35,0x4E35,0x4A55,0x4633,0x4A14,0x4E76,0x5696,0x4E75,
+ 0x5257,0x5A78,0x5296,0x4E76,0x4A35,0x5278,0x56D7,0x5B19,
+ 0x4E97,0x673C,0x631B,0x5ADA,0x6B1C,0x673C,0x66FE,0x66FB,
+ 0x5EFA,0x5ADA,0x5ED9,0x62FC,0x671A,0x6B1B,0x673C,0x677D,
+ 0x66FA,0x777F,0x777F,0x735F,0x6B7E,0x777F,0x7B9F,0x6F5F,
+ 0x6B9E,0x733D,0x6B1E,0x737F,0x6F5E,0x6F5E,0x6B3D,0x737F,
+
+ 0x6F3E,0x7FFF,0x7FFF,0x7FDF,0x7BBF,0x7FDF,0x7B9F,0x777F,
+ 0x7B9F,0x779F,0x7BBF,0x7FFF,0x7FFF,0x7BBF,0x7FDF,0x779F,
+ 0x7FDF,0x3FE7,0x0940,0x0960,0x0960,0x0980,0x09A0,0x09C0,
+ 0x1200,0x1220,0x1240,0x16A0,0x1AC0,0x1AE0,0x2760,0x1F40,
+ 0x1F60,0x26E0,0x2700,0x2720,0x2740,0x2780,0x2781,0x27A0,
+ 0x27A1,0x27C1,0x27E1,0x22C0,0x22E0,0x22E1,0x2300,0x2300,
+ 0x2340,0x3762,0x3782,0x37A2,0x37C1,0x37C2,0x37C3,0x37E2,
+ 0x37E2,0x37E3,0x37E5,0x3BE3,0x3BE4,0x3BE5,0x3BE5,0x3FE4,
+ 0x3FE4,0x4BE5,0x4BE6,0x4BE7,0x4BE5,0x4FE6,0x4FE7,0x4FE6,
+ 0x4FE7,0x4FE6,0x4FE6,0x4FE8,0x53E8,0x5BE8,0x5FEB,0x5FEB,
+ 0x67ED,0x6FF5,0x2245,0x1E03,0x21E5,0x2A46,0x3688,0x3F08,
+ 0x3707,0x3F48,0x47AB,0x4FAB,0x53AD,0x5FEF,0x57ED,0x57EC,
+ 0x57EE,0x4FCD,0x57F0,0x5BD1,0x5BEF,0x5FF0,0x5FF1,0x5FF2,
+ 0x63F0,0x63F1,0x63F2,0x63F3,0x6FF4,0x6BF4,0x6BF5,0x73F6,
+ 0x77F6,0x41D3,0x0000,0x0000,0x131A,0x2BBF,0x4FBF,0x23E0,
+ 0x43E0,0x67ED,0x4C07,0x6409,0x7CCF,0x3C1F,0x541F,0x6C1F,
+
+ 0x7FFF,0x7C00,0x3786,0x37A6,0x3B86,0x3BC6,0x3F47,0x3F86,
+ 0x3FC6,0x3FE6,0x3FE7,0x47A7,0x47C6,0x47C7,0x47E6,0x47E7,
+ 0x4BA7,0x4BA8,0x4BC7,0x4BC8,0x4BE7,0x4BE8,0x4FA8,0x4FC8,
+ 0x4FE8,0x53C8,0x53CA,0x53CB,0x53EA,0x53EB,0x53EC,0x5BCC,
+ 0x5BCD,0x5BD0,0x5BEB,0x5BEC,0x5BED,0x5BEE,0x5FD0,0x5FED,
+ 0x5FEF,0x5FF0,0x5FF2,0x63EF,0x63F1,0x63F2,0x63F3,0x63F5,
+ 0x63F6,0x6BF3,0x6BF5,0x6BF6,0x6BF7,0x6BF8,0x6FF6,0x6FF7,
+ 0x6FF8,0x6FFA,0x6FFB,0x6FFC,0x73FB,0x73FC,0x73FD,0x73FF,
+ 0x7FFF,0x53E7,0x5FE8,0x4FE7,0x4BE7,0x3FE6,0x37C6,0x33A6,
+ 0x2BA6,0x2366,0x2325,0x2346,0x2304,0x2786,0x2306,0x2746,
+ 0x1F24,0x1F04,0x2345,0x1F06,0x33C6,0x33E6,0x27A6,0x2785,
+ 0x2B86,0x1EC4,0x37E6,0x37A6,0x3BE6,0x2745,0x47E6,0x4BE6,
+ 0x4FE6,0x47E7,0x5BE8,0x5BEA,0x3B86,0x3766,0x4BE8,0x53E8,
+ 0x5FEA,0x63EB,0x6FEF,0x73F0,0x73F1,0x6FF0,0x6FED,0x6BEC,
+ 0x63EA,0x5FE9,0x63E9,0x1AE4,0x2365,0x2BA5,0x27A5,0x1AA4,
+ 0x22C6,0x2B85,0x1A24,0x3386,0x3FC6,0x3FE7,0x2726,0x2B46,
+
+ 0x3366,0x15C4,0x15E5,0x1644,0x1605,0x1604,0x1E84,0x1EC6,
+ 0x2306,0x15E4,0x1625,0x22C6,0x1664,0x1624,0x1EA6,0x1E86,
+ 0x1645,0x6ABB,0x6A9B,0x6A5B,0x663A,0x661A,0x5DD9,0x5D99,
+ 0x5519,0x48B7,0x4896,0x140C,0x140D,0x140B,0x100B,0x100A,
+ 0x1009,0x0C08,0x0C09,0x200F,0x200D,0x1C0D,0x1C0A,0x200C,
+ 0x200A,0x2009,0x202A,0x204A,0x208B,0x24C9,0x24C7,0x356D,
+ 0x1C0C,0x1410,0x1412,0x1C13,0x2015,0x2417,0x2C17,0x3419,
+ 0x3819,0x4419,0x4877,0x4C39,0x4C59,0x4C79,0x543A,0x5479,
+ 0x55D6,0x5859,0x5879,0x5CB9,0x5CBA,0x5CDA,0x5D39,0x5D59,
+ 0x5D9B,0x60F9,0x651B,0x655B,0x6A1B,0x6A3B,0x6ABB,0x6ADB,
+ 0x6F1B,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00,0x001F,0x03FF,
+ 0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,0x7DFF,
+ 0x7E9F,0x7BDE,0x7F9F,0x186B,0x1CAB,0x1C6C,0x208E,0x204F,
+ 0x28B2,0x28B2,0x28B2,0x28B2,0x28B2,0x2873,0x2893,0x2C92,
+ 0x2CB2,0x3074,0x3094,0x30D4,0x30F4,0x3076,0x34D4,0x34F4,
+ 0x3476,0x34B7,0x34F7,0x3517,0x3478,0x34B8,0x3479,0x3CD6,
+
+ 0x3CB7,0x3CB8,0x3D58,0x3CD9,0x3D39,0x3C7B,0x3CBB,0x3CDB,
+ 0x3CFB,0x3CFC,0x407F,0x44F8,0x4578,0x44D9,0x44F9,0x4539,
+ 0x44BB,0x44DB,0x455C,0x44BD,0x44DD,0x451D,0x44BE,0x447F,
+ 0x4D9A,0x4CDA,0x4D3C,0x4CDD,0x4D3E,0x4CBF,0x4CDF,0x4D1F,
+ 0x4D3F,0x54DE,0x553E,0x54DF,0x551F,0x553F,0x557F,0x5CDF,
+ 0x5D1F,0x5D3F,0x5D5F,0x5D7F,0x5D9F,0x651F,0x655F,0x65BF,
+ 0x65DF,0x661F,0x691F,0x695F,0x69BE,0x69DF,0x6A1F,0x715F,
+ 0x717F,0x71BF,0x71DF,0x721F,0x723F,0x725F,0x727F,0x75BF,
+ 0x75FF,0x761F,0x723F,0x725F,0x769F,0x773F,0x7B7F,0x75BF,
+ 0x75FF,0x7A3F,0x7AFF,0x7F7F,0x755F,0x75FF,0x763F,0x7A9F,
+ 0x7ADF,0x7F5F,0x7FBF,0x7FDF,0x75FF,0x761F,0x763F,0x765F,
+ 0x7A7F,0x7A9F,0x7ABF,0x7EDF,0x7EFF,0x7F3F,0x7F7F,0x7FBF,
+ 0x7FFF,0x0000,0xFFFF,0x31EC,0x7FE0,0x7C1F,0x7C00,0x001F,
+ 0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7DFF,0x7E9F,0x7BDE,0x7FFC,0x1C40,0x1C81,0x2060,0x2880,
+ 0x2C80,0x38C1,0x38C1,0x38C1,0x38C1,0x38C1,0x3CC0,0x3CC0,
+
+ 0x38E0,0x38E1,0x4100,0x4500,0x4503,0x4503,0x4D00,0x4522,
+ 0x4522,0x4D20,0x5121,0x5123,0x5124,0x5520,0x5521,0x5920,
+ 0x4D62,0x5161,0x5561,0x5565,0x5961,0x5964,0x6160,0x6160,
+ 0x6161,0x6162,0x6562,0x6982,0x55A2,0x59A6,0x59A1,0x59A2,
+ 0x59A4,0x61A0,0x61A1,0x65A4,0x69A0,0x69A0,0x69A2,0x6DA0,
+ 0x71A0,0x5DE6,0x5DE0,0x65E3,0x69E0,0x6DE3,0x71E0,0x71E1,
+ 0x71E3,0x71C3,0x6E20,0x6E24,0x7221,0x7223,0x7224,0x7226,
+ 0x7261,0x7263,0x7264,0x7265,0x7266,0x7267,0x72A3,0x72A5,
+ 0x72A8,0x72A9,0x72AB,0x72C3,0x72C5,0x72C7,0x72C9,0x72C1,
+ 0x7306,0x7306,0x7308,0x7309,0x730B,0x730C,0x730D,0x730E,
+ 0x7328,0x732A,0x732B,0x7308,0x774C,0x7B90,0x7BB4,0x7FD9,
+ 0x7728,0x774B,0x7B8C,0x7FB5,0x7FD9,0x7725,0x772A,0x7B4D,
+ 0x7B70,0x7FB4,0x7FF9,0x7FFC,0x7FFD,0x7B4A,0x7B4B,0x7B4C,
+ 0x7B2D,0x7B6E,0x7B6F,0x7B90,0x7BB2,0x7BB3,0x7FD6,0x7FD8,
+ 0x7BDA,0x7FFE,0x0000,0xFFFF,0x396C,0x7FE0,0x7C1F,0x7C00,
+ 0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,0x701F,
+
+ 0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7F9F,0x1DD0,0x25F0,0x1DF1,
+ 0x2213,0x1A14,0x1E17,0x2237,0x2637,0x2657,0x2657,0x1E58,
+ 0x2278,0x2278,0x2678,0x1E99,0x22B9,0x2AB9,0x2EB9,0x1EBB,
+ 0x2AD9,0x2ED9,0x1EDB,0x2EDC,0x36DC,0x32DC,0x1EDD,0x26DE,
+ 0x1EDE,0x2B1B,0x271C,0x271D,0x3B3C,0x2B3D,0x331C,0x1B1E,
+ 0x26FE,0x2B1E,0x2F1F,0x2F1F,0x1F3F,0x335B,0x373B,0x2F3C,
+ 0x333C,0x333C,0x2B3E,0x2F3E,0x375E,0x235F,0x2F1F,0x2F5F,
+ 0x235F,0x1B5F,0x2B7A,0x2F9A,0x339C,0x2B9D,0x339E,0x379F,
+ 0x379F,0x3F9F,0x3F9F,0x3BDE,0x3B9E,0x2F9F,0x379F,0x3B9F,
+ 0x439F,0x2B9F,0x379F,0x3B9F,0x3F9F,0x439F,0x479F,0x37BF,
+ 0x3FDF,0x4BDF,0x4FDF,0x57DF,0x37BF,0x3FDF,0x479E,0x4B9F,
+ 0x539F,0x47DF,0x4BDF,0x4FDF,0x53DF,0x57DF,0x5BDF,0x5FDF,
+ 0x63FF,0x57FF,0x5BFF,0x5FFF,0x5BDF,0x63DF,0x6BFF,0x73FF,
+ 0x7BFF,0x5FFF,0x63FF,0x67FF,0x73FF,0x7BFF,0x5FFF,0x63FF,
+ 0x67FF,0x6FFF,0x73FF,0x77FF,0x7FBF,0x7FDF,0x57FF,0x5BFF,
+ 0x5FFF,0x63FF,0x67FF,0x6BFF,0x6FFF,0x73FF,0x77FF,0x7BFF,
+
+ 0x7BFF,0x7FFF,0x7FFF,0x0000,0xFFFF,0x28ED,0x7FE0,0x7C1F,
+ 0x7C00,0x001F,0x03FF,0x301F,0x401F,0x501F,0x5C1F,0x681F,
+ 0x701F,0x7C5F,0x7DFF,0x7E9F,0x7BDE,0x7FFA,0x1180,0x1580,
+ 0x15C0,0x19C0,0x1600,0x1A00,0x1A40,0x1E40,0x1E80,0x2280,
+ 0x1EA0,0x22A0,0x1EC0,0x22C0,0x26C0,0x2300,0x2302,0x2303,
+ 0x2300,0x2702,0x2B03,0x2720,0x2723,0x2743,0x2744,0x2760,
+ 0x2761,0x2762,0x2B60,0x2B62,0x2F61,0x3366,0x3380,0x3383,
+ 0x33A6,0x33A1,0x33A2,0x33C3,0x37C3,0x37C0,0x3762,0x3766,
+ 0x3781,0x3782,0x3784,0x37A0,0x37A1,0x3BA6,0x3BC1,0x3BC2,
+ 0x3BC4,0x3BE0,0x3BE3,0x3F87,0x3FA1,0x3FA4,0x3FC1,0x3FE4,
+ 0x3FE0,0x3FE1,0x3FE3,0x3FE4,0x43E0,0x4BE2,0x4BE4,0x4BE6,
+ 0x4BE8,0x4BEA,0x53E2,0x53E4,0x53E6,0x53E8,0x53EA,0x53EC,
+ 0x5BE4,0x5BE6,0x5BE8,0x5BEA,0x5BEC,0x5FE4,0x5FE6,0x5FE8,
+ 0x5FEA,0x5FEC,0x67E2,0x67E4,0x67E6,0x67E8,0x67EA,0x67EC,
+ 0x6FE8,0x6FEA,0x6FEC,0x6FEE,0x6FF0,0x73E0,0x73E8,0x73F0,
+ 0x73F4,0x73F9,0x77E0,0x77E8,0x77F0,0x77F4,0x77F9,0x7BE2,
+
+ 0x7BE6,0x7BEC,0x7BF2,0x7BF5,0x7BF9,0x7FFB,0x7BFC,0x77E0,
+ 0x77E2,0x77E4,0x77E6,0x77E8,0x7BEA,0x7BED,0x7BF0,0x7BF3,
+ 0x7BF6,0x7BF9,0x7BFB,0x7FFF,0x0000,0xFFFF,0x0002,0x0000
+};
+static UINT16 bloodwar_mcu_4_16[] = { // Warrior 8 Player 1
+ 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x29A9,0x2DCA,0x31EB,0x360C,0x3A0D,0x3A2D,0x3A4D,
+ 0x3E4E,0x3E6E,0x3E6F,0x426E,0x428E,0x468E,0x468F,0x4AAF,
+ 0x4AB0,0x46D0,0x4AD0,0x4AF0,0x4AF1,0x4EF1,0x4F11,0x4F12,
+ 0x5311,0x5312,0x5330,0x5751,0x5752,0x5B73,0x5B74,0x5B93,
+ 0x5B94,0x6396,0x67D5,0x67D6,0x67D7,0x67D5,0x67D6,0x6BD6,
+ 0x6BD7,0x6BD9,0x6BD5,0x6BD6,0x6BD7,0x6BD6,0x6FD6,0x6FD7,
+ 0x6FD9,0x73D7,0x73D8,0x73DA,0x7BD8,0x7BF9,0x7BFA,0x7BFB,
+ 0x7BFC,0x7FFB,0x7FFB,0x7FFC,0x7FFD,0x7FFB,0x7FFD,0x7FFD,
+ 0x7FFE,0x1946,0x1965,0x2187,0x21A5,0x25A7,0x29C7,0x29E8,
+ 0x360A,0x362B,0x3A8C,0x426D,0x428C,0x46EF,0x4ACF,0x5350,
+ 0x5352,0x5752,0x5753,0x5791,0x5B53,0x5B73,0x5FB3,0x6374,
+ 0x63B3,0x63B4,0x63D4,0x67B4,0x67D4,0x67D6,0x6FF6,0x6FF7,
+ 0x73F7,0x0882,0x0CA3,0x10E3,0x10E4,0x1103,0x1104,0x1524,
+ 0x1945,0x1965,0x1D65,0x1985,0x1986,0x21A6,0x21A7,0x21C6,
+
+ 0x25A6,0x29E9,0x2E09,0x2E28,0x2E29,0x364B,0x3A4D,0x3E8C,
+ 0x42CC,0x4B0F,0x4EF2,0x5BD3,0x67F7,0x6BF5,0x73F8,0x77FB,
+ 0x7FFC,0x1982,0x1DA4,0x21C5,0x25E6,0x2A07,0x2E27,0x2E47,
+ 0x3267,0x36A8,0x3AC9,0x3EEA,0x3F0A,0x3F2B,0x434C,0x476C,
+ 0x478C,0x4F8E,0x4FAD,0x4FCE,0x53EF,0x53F0,0x57F0,0x5BF0,
+ 0x5BF1,0x5FF3,0x5FF4,0x5FF2,0x63F2,0x63F4,0x67F5,0x6BF6,
+ 0x73F8,0x1E24,0x1E44,0x2265,0x2287,0x22A7,0x26C8,0x26E8,
+ 0x2B09,0x2F2A,0x3349,0x3F6C,0x438D,0x47AE,0x53D2,0x57F2,
+ 0x5FF3,0x0C09,0x100A,0x180C,0x1C0D,0x200E,0x240F,0x2810,
+ 0x3052,0x3473,0x3CB5,0x44F7,0x4D39,0x557B,0x5DBD,0x65FE,
+ 0x7BBE,0x10C3,0x1905,0x2146,0x2546,0x2988,0x31C8,0x35C9,
+ 0x39EB,0x3E0C,0x422C,0x464E,0x56F2,0x5733,0x5753,0x5B33,
+ 0x5B52,0x10E3,0x0CA3,0x10E4,0x1103,0x1104,0x1524,0x1946,
+ 0x21A5,0x2A08,0x322A,0x366A,0x42EE,0x4F0F,0x5FB2,0x5FB3,
+ 0x63D3,0x3D71,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300,
+ 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5,
+
+ 0x7BDE,0xFFFF,0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108
+};
+static UINT16 bloodwar_mcu_4_17[] = { // Warrior 8 Player 2
+ 0x0002,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x296A,0x2D8B,0x31AC,0x35CD,0x35EF,0x39F0,0x3A10,
+ 0x3DD1,0x3E11,0x3E12,0x4230,0x4231,0x4630,0x4631,0x4671,
+ 0x4673,0x4674,0x4A73,0x4A93,0x4AB3,0x4AB4,0x4E74,0x4E75,
+ 0x52B3,0x52B4,0x52D3,0x56F4,0x56F5,0x5B16,0x5B17,0x5B36,
+ 0x5B37,0x6339,0x6778,0x6779,0x677A,0x6778,0x6779,0x6B79,
+ 0x6B7A,0x6B7C,0x6B78,0x6B79,0x6B7A,0x6B79,0x6F79,0x6F7A,
+ 0x6F7C,0x737A,0x737B,0x737D,0x7B7B,0x7B9C,0x7B9D,0x7B9E,
+ 0x7B9F,0x7F9E,0x7F9E,0x7F9F,0x7FBF,0x7F9E,0x7FBF,0x7FBF,
+ 0x7FBF,0x18E9,0x1908,0x212A,0x2148,0x254A,0x296A,0x298B,
+ 0x35AD,0x35CE,0x3A2F,0x4210,0x422F,0x4692,0x4A72,0x52D3,
+ 0x52F5,0x56F5,0x56F6,0x5715,0x5AF6,0x5B16,0x5F36,0x6317,
+ 0x6356,0x6357,0x6377,0x6757,0x6777,0x6779,0x6F99,0x6F9A,
+ 0x739A,0x0825,0x0C46,0x1086,0x1087,0x10A6,0x10A7,0x14C7,
+ 0x18E8,0x1908,0x1D08,0x1928,0x1929,0x2149,0x214A,0x2169,
+
+ 0x2549,0x298C,0x2DAC,0x2DCB,0x2DCC,0x35EE,0x39F0,0x3E2F,
+ 0x426F,0x4AB2,0x4E95,0x5B76,0x679A,0x6B98,0x739B,0x779E,
+ 0x7F9F,0x1982,0x1DA4,0x21C5,0x25E6,0x2A07,0x2E27,0x2E47,
+ 0x3267,0x36A8,0x3AC9,0x3EEA,0x3F0A,0x3F2B,0x434C,0x476C,
+ 0x478C,0x4F8E,0x4FAD,0x4FCE,0x53EF,0x53F0,0x57F0,0x5BF0,
+ 0x5BF1,0x5FF3,0x5FF4,0x5FF2,0x63F2,0x63F4,0x67F5,0x6BF6,
+ 0x739B,0x2810,0x2C31,0x3473,0x3894,0x3CB5,0x40D6,0x44F7,
+ 0x4918,0x4D39,0x515A,0x557B,0x599C,0x5DBD,0x65FE,0x6A1F,
+ 0x767F,0x0C09,0x100A,0x180C,0x1C0D,0x200E,0x240F,0x2810,
+ 0x3052,0x3473,0x3CB5,0x44F7,0x4D39,0x557B,0x5DBD,0x65FE,
+ 0x7BBE,0x10C3,0x1905,0x2146,0x2546,0x2988,0x31C8,0x35C9,
+ 0x39EB,0x3E0C,0x422C,0x464E,0x56F2,0x5733,0x5753,0x5B33,
+ 0x5B52,0x10E3,0x0CA3,0x10E4,0x1103,0x1104,0x1524,0x1946,
+ 0x21A5,0x2A08,0x322A,0x366A,0x42EE,0x4F0F,0x5FB2,0x5FB3,
+ 0x63D3,0x3D71,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300,
+ 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5,
+
+ 0x7BDE,0xFFFF,0x0003,0x0000,0x4232,0x56F8,0x2D8D,0x2108
+};
+static UINT16 bloodwar_mcu_4_18[] = { // Warrior 2 Player 2
+ 0x0003,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x1524,0x0CC2,0x0CE2,0x0CE3,0x10E3,0x1103,0x14E3,
+ 0x1544,0x1946,0x1966,0x2166,0x2167,0x2187,0x2567,0x25A7,
+ 0x29E8,0x31EA,0x320A,0x3A4B,0x3A4D,0x3A6B,0x3E4D,0x3E6B,
+ 0x3E6D,0x3E6E,0x3E8D,0x426E,0x428E,0x468F,0x46AE,0x46CF,
+ 0x46EE,0x46EF,0x4710,0x4AEF,0x4EF0,0x4F10,0x4F11,0x52F1,
+ 0x5310,0x5312,0x5313,0x5332,0x5732,0x5753,0x5B33,0x5B34,
+ 0x5B53,0x5F95,0x5FB5,0x5FD4,0x63B4,0x63B5,0x63B6,0x63D5,
+ 0x67F7,0x6FD7,0x6FF7,0x6FF8,0x6FF7,0x6FF8,0x73FA,0x7BFC,
+ 0x7FFC,0x0440,0x0080,0x0940,0x0D80,0x11C0,0x1200,0x1240,
+ 0x1280,0x12E0,0x1300,0x1301,0x1761,0x1B81,0x1BC2,0x1BE1,
+ 0x1E01,0x1E80,0x1EA0,0x22C0,0x22E1,0x2361,0x2381,0x2382,
+ 0x2782,0x27C2,0x27E4,0x2BC3,0x2FC4,0x2FE5,0x33E5,0x33E6,
+ 0x37E8,0x1520,0x1500,0x1940,0x1960,0x1D80,0x25E1,0x2DE3,
+ 0x3242,0x3262,0x3683,0x3EC3,0x3EC4,0x3F23,0x42A5,0x42C7,
+
+ 0x4765,0x4B08,0x4B46,0x4B66,0x53C7,0x5769,0x57C7,0x5BC8,
+ 0x5BCA,0x5FC9,0x5FE8,0x5FE9,0x6FEB,0x73ED,0x77EF,0x7FF4,
+ 0x7FF8,0x2E0A,0x320A,0x3A4E,0x3A6D,0x3E4D,0x3E6D,0x3E6E,
+ 0x426E,0x46CF,0x5310,0x5312,0x5332,0x5B94,0x5FB6,0x6797,
+ 0x67D6,0x6BD8,0x6BDA,0x6BF9,0x6BFA,0x6FDC,0x6FFA,0x6FFB,
+ 0x73FB,0x73FC,0x7BFB,0x7BFC,0x7BFD,0x7BFE,0x7FFD,0x7FFE,
+ 0x7FFF,0x1504,0x10E4,0x1524,0x1945,0x1965,0x1D67,0x1D87,
+ 0x2587,0x25A8,0x29E8,0x2A07,0x2E08,0x324A,0x3268,0x3269,
+ 0x3A68,0x3A8B,0x3EAB,0x42CB,0x4F2E,0x5330,0x534F,0x5352,
+ 0x57B1,0x5FB3,0x5FB4,0x67F3,0x6BF4,0x6BF5,0x6BF8,0x6FF7,
+ 0x73F9,0x0461,0x0441,0x0862,0x0882,0x0CC2,0x0CC3,0x0CE2,
+ 0x0CE3,0x10C3,0x10E3,0x10E4,0x1103,0x1104,0x1123,0x14E4,
+ 0x1524,0xFFFF,0x390F,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,
+ 0x181C,0x1C1F,0x241F,0x0BE0,0x3BE0,0x53E0,0x381F,0x4C1F,
+ 0x65FF,0x7BDE,0xFFFF,0x41D3,0x0013,0x281F,0x581F,0x6DFF,
+ 0x2243,0x0000,0x0340,0x4210,0x4A52,0x5294,0x5AD6,0x6318,
+
+ 0x4409,0x7BC0,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,
+ 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,
+ 0x7FF6,0x7FFC,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,
+ 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,
+ 0x7DBD,0x7EBD,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,
+ 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,
+ 0x681F,0x6DFF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,
+ 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7E5F,0x7B5F,0x7FFF,0x0000,0x7FE0,0x7C1F,0x0B58,0x13BB,
+ 0x1FFF,0x33FF,0x43FF,0x47FF,0x4FFF,0x57FF,0x5FFF,0x67FF,
+ 0x6FFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,
+ 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,
+ 0x5FF3,0x6FF8,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,
+ 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,
+ 0x77EE,0x77F5,0x7FFF,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,
+ 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,
+
+ 0x7EBA,0x7F5D,0x7FFF,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8,
+ 0x5BC4,0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7,
+ 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,
+ 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,
+ 0x13E0,0x1DA3,0x2243,0x41D3,0x0842,0x1084,0x18C6,0x2108,
+ 0x294A,0x318C,0x39CE,0x03A0,0x23E0,0x37E0,0x3FE0,0x4FE0,
+ 0x67ED,0x77EE,0x7FFF,0xFFFF,0x0003,0x0000,0x4232,0x56F8
+};
+static UINT16 bloodwar_mcu_4_19[] = { // Warrior 2 Player 1
+ 0x0003,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x1524,0x0CC2,0x0CE2,0x0CE3,0x10E3,0x1103,0x14E3,
+ 0x1544,0x1946,0x1966,0x2166,0x2167,0x2187,0x2567,0x25A7,
+ 0x29E8,0x2A05,0x2E05,0x2E45,0x3266,0x3285,0x3285,0x3284,
+ 0x32A5,0x36C5,0x3AE1,0x3EC1,0x3EE2,0x4704,0x4724,0x4745,
+ 0x4764,0x4765,0x4786,0x4B65,0x4F66,0x4F86,0x4F87,0x5367,
+ 0x5386,0x57A8,0x57A9,0x57C8,0x5BC8,0x5BE9,0x5FC9,0x5FCA,
+ 0x5FE9,0x63EC,0x63EC,0x63EB,0x67EB,0x6BEB,0x6BEE,0x6BED,
+ 0x6FEF,0x73EE,0x73EE,0x73EF,0x73EE,0x77EF,0x7BF3,0x7FF5,
+ 0x7FF6,0x0440,0x0080,0x0940,0x0D80,0x11C0,0x1200,0x1240,
+ 0x1280,0x12E0,0x1300,0x1301,0x1761,0x1B81,0x1BC2,0x1BE1,
+ 0x1E01,0x1E80,0x1EA0,0x22C0,0x22E1,0x2361,0x2381,0x2382,
+ 0x2782,0x27C2,0x27E4,0x2BC3,0x2FC4,0x2FE5,0x33E5,0x33E6,
+ 0x37E8,0x1520,0x1500,0x1940,0x1960,0x1D80,0x25E1,0x2DE3,
+ 0x3242,0x3262,0x3683,0x3EC3,0x3EC4,0x3F23,0x42A5,0x42C7,
+
+ 0x4765,0x4B08,0x4B46,0x4B66,0x53C7,0x5769,0x57C7,0x5BC8,
+ 0x5BCA,0x5FC9,0x5FE8,0x5FE9,0x6FEB,0x73ED,0x77EF,0x7FF4,
+ 0x7FF8,0x2A61,0x2E81,0x32A3,0x36C2,0x3AC2,0x3EE3,0x42E3,
+ 0x4303,0x4324,0x4B45,0x4F67,0x4F88,0x57A9,0x5BCD,0x63ED,
+ 0x63EE,0x6BEE,0x6BF0,0x6BEF,0x6BF0,0x6FF2,0x6FF0,0x6FF1,
+ 0x73F1,0x73F2,0x7BF2,0x7BF3,0x7BF4,0x7BF7,0x7FFC,0x7FFC,
+ 0x7FFC,0x1504,0x10E4,0x1524,0x1945,0x1965,0x1D67,0x1D87,
+ 0x2587,0x25A8,0x29E8,0x2A07,0x2E08,0x324A,0x3268,0x3269,
+ 0x3A68,0x32C0,0x36E0,0x3B00,0x3F20,0x4343,0x4B63,0x4F87,
+ 0x53A6,0x57C7,0x5BE9,0x5FE7,0x63E8,0x63E9,0x63EC,0x67EC,
+ 0x6BED,0x0461,0x0441,0x0862,0x0882,0x0CC2,0x0CC3,0x0CE2,
+ 0x0CE3,0x10C3,0x10E3,0x10E4,0x1103,0x1104,0x1123,0x14E4,
+ 0x1524,0xFFFF,0x390F,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,
+ 0x181C,0x1C1F,0x241F,0x0BE0,0x3BE0,0x53E0,0x381F,0x4C1F,
+ 0x65FF,0x7BDE,0xFFFF,0x41D3,0x0013,0x281F,0x581F,0x6DFF,
+ 0x2243,0x0000,0x0340,0x4210,0x4A52,0x5294,0x5AD6,0x6318,
+
+ 0x4409,0x7BC0,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,
+ 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,
+ 0x7FF6,0x7FFC,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,
+ 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,
+ 0x7DBD,0x7EBD,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,
+ 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,
+ 0x681F,0x6DFF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,
+ 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7E5F,0x7B5F,0x7FFF,0x0000,0x7FE0,0x7C1F,0x0B58,0x13BB,
+ 0x1FFF,0x33FF,0x43FF,0x47FF,0x4FFF,0x57FF,0x5FFF,0x67FF,
+ 0x6FFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,
+ 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,
+ 0x5FF3,0x6FF8,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,
+ 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,
+ 0x77EE,0x77F5,0x7FFF,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,
+ 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,
+
+ 0x7EBA,0x7F5D,0x7FFF,0x2AA1,0x3724,0x3FA6,0x43E0,0x4FE8,
+ 0x5BC4,0x63C5,0x67EB,0x67EB,0x67ED,0x6FF0,0x77F3,0x7FF7,
+ 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,
+ 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,
+ 0x13E0,0x1DA3,0x2243,0x41D3,0x0842,0x1084,0x18C6,0x2108,
+ 0x294A,0x318C,0x39CE,0x03A0,0x23E0,0x37E0,0x3FE0,0x4FE0,
+ 0x67ED,0x77EE,0x7FFF,0xFFFF,0x0005,0x0000,0x4232,0x56F8
+};
+static UINT16 bloodwar_mcu_4_1a[] = { // Warrior 3 Player 1
+ 0x0005,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x08A0,0x0D02,0x1142,0x19C2,0x3EEB,0x430D,0x4B6C,
+ 0x4F4F,0x4F50,0x432A,0x368A,0x328A,0x3AE9,0x3689,0x3268,
+ 0x2A26,0x2A27,0x3AE9,0x4B4E,0x3269,0x3EEB,0x3AA8,0x19A3,
+ 0x08E2,0x21E5,0x2E47,0x3F2A,0x4B4F,0x3F0B,0x3AEB,0x36A8,
+ 0x25E3,0x1DC6,0x2606,0x2E46,0x36AA,0x2E66,0x36A8,0x36CA,
+ 0x32A9,0x2604,0x15C2,0x1182,0x0D42,0x1583,0x1162,0x0D22,
+ 0x15A2,0x19E3,0x11C2,0x1E45,0x1A04,0x2204,0x2E68,0x25E4,
+ 0x1DA4,0x3268,0x3AC9,0x4B2D,0x36A9,0x430C,0x2A46,0x534F,
+ 0x532F,0x42EA,0x2A26,0x1964,0x4F8E,0x4F8D,0x4B6C,0x474D,
+ 0x434A,0x3F29,0x3AE8,0x3B08,0x474B,0x3F09,0x4349,0x4B6B,
+ 0x1944,0x1D44,0x25C7,0x2E08,0x3AEA,0x3688,0x3247,0x3A2A,
+ 0x3AC8,0x3689,0x3EAA,0x426E,0x10C3,0x2603,0x1503,0x1925,
+ 0x42CA,0x42EB,0x3F2A,0x25E3,0x42A8,0x534E,0x1924,0x46CC,
+ 0x4B0D,0x2EA4,0x1DE4,0x2605,0x2E67,0x3ACA,0x3AAA,0x2A45,
+
+ 0x1185,0x2E46,0x1122,0x0862,0x08C2,0x1562,0x2A25,0x2A26,
+ 0x2624,0x472E,0x3688,0x4B4D,0x15A3,0x21E4,0x4F4E,0x4F6E,
+ 0x4F6D,0x5F34,0x5F36,0x5F36,0x5F56,0x4ED1,0x46AF,0x426E,
+ 0x2E26,0x21C6,0x324A,0x5B14,0x6777,0x6356,0x5F15,0x1380,
+ 0x1380,0x0F60,0x0F80,0x0F80,0x0F20,0x1300,0x0EE0,0x0F00,
+ 0x1320,0x0E82,0x1300,0x0A02,0x0DE2,0x0E02,0x09A2,0x0DC2,
+ 0x0D82,0x0D85,0x0E22,0x0E42,0x1262,0x1720,0x0EE0,0x0F00,
+ 0x1320,0x0F20,0x0F60,0x1623,0x1AA4,0x1683,0x1283,0x12A3,
+ 0x0E62,0x15E3,0x13A0,0x0B60,0x1282,0x12A2,0x16E0,0x1760,
+ 0x1760,0x1B80,0x1780,0x1F80,0x1B80,0x1B60,0x1AE0,0x1B60,
+ 0x1720,0x5FE5,0x5BE5,0x5BE5,0x5BE4,0x57E4,0x5BE4,0x4FA4,
+ 0x4B84,0x4B84,0x4F85,0x53A4,0x4B85,0x53A6,0x57C5,0x4366,
+ 0x4B87,0x4BA7,0x4766,0x2EC4,0x2EA6,0x2643,0x3B07,0x32A3,
+ 0x36C3,0x57E8,0x57CA,0x4FC4,0x32E3,0x32E4,0x32C3,0x2263,
+ 0x2AA3,0x2E91,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0,
+ 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC,
+
+ 0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0,0x46E0,
+ 0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6,0x7FFC,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09,0x4009,
+ 0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD,0x7EBD,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,0x181C,
+ 0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F,0x6DFF,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F,0x401F,
+ 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B5F,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5,0x1358,
+ 0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF,0x77FF,
+ 0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200,0x0260,
+ 0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3,0x6FF8,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300,
+ 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5,
+ 0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407,
+ 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D,
+
+ 0x7BDE,0x3408,0x3C0F,0x4813,0x4C12,0x5413,0x5C0F,0x680D,
+ 0x700A,0x7484,0x7900,0x7DA0,0x7ECD,0x7F6D,0x7FF5,0x7F7E,
+ 0x7BDE,0x240C,0x280C,0x2C0C,0x340C,0x380C,0x3C0C,0x400C,
+ 0x440E,0x4810,0x5012,0x5413,0x400E,0x440E,0x4C0E,0x284F,
+ 0x2C4E,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,
+ 0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,
+ 0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0,
+ 0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6,
+ 0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09,
+ 0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD,
+ 0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,
+ 0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F,
+ 0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F,
+ 0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,
+ 0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5,
+ 0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF,
+
+ 0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200,
+ 0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3,
+ 0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,
+ 0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,
+ 0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,
+ 0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,
+ 0x7F5D,0x7BDE,0x0216,0x0257,0x12D8,0x2718,0x2FB8,0x3FB9,
+ 0x47FA,0x4FFC,0x53FF,0x5BFF,0x5BFF,0x67FE,0x6FFF,0x73DF,
+ 0x7BDF,0x7FFF,0x01B2,0x01F4,0x0215,0x0237,0x0258,0x027A,
+ 0x029B,0x02DB,0x02FA,0x033A,0x035B,0x029B,0x02DD,0x031F,
+ 0x0210,0x0215,0xFFFF,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724,
+ 0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,
+ 0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,
+ 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,
+ 0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,
+ 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,
+
+ 0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,
+ 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,
+ 0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,
+ 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,
+ 0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,
+ 0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,
+ 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,
+ 0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,
+ 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,
+ 0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,
+ 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,
+ 0x7EBA,0x7F5D,0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0,
+ 0x4FC0,0x57C0,0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3,
+ 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,
+ 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,
+
+ 0x13E0,0x1DA3,0x2243,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1,
+ 0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,
+ 0x77F3,0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,
+ 0x36A0,0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,
+ 0x7FF0,0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x3809,0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,
+ 0x70FB,0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x0013,0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,
+ 0x581F,0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x301F,0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,
+ 0x7C5F,0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,
+ 0x02B3,0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,
+ 0x5FFF,0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x0200,0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,
+ 0x47EC,0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x0E60,0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,
+
+ 0x67ED,0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,
+ 0x4409,0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,
+ 0x7E15,0x7EBA,0x7F5D,0x7BDE,0x19B7,0x21DA,0x31BC,0x3D9E,
+ 0x499E,0x511D,0x5CFE,0x60DF,0x68BF,0x707F,0x741F,0x7C1F,
+ 0x7E7F,0x7F5F,0x7F9F,0x7FFF,0x018C,0x018E,0x018F,0x0191,
+ 0x0192,0x0194,0x0195,0x2597,0x2998,0x3599,0x3D99,0x0195,
+ 0x0999,0x1199,0x21CF,0x25D4,0xFFFF,0x0005,0x0000,0x4232
+};
+static UINT16 bloodwar_mcu_4_1b[] = { // Warrior 3 Player 2
+ 0x0005,0x0000,0x4232,0x56F8,0x2D8D,0x2108,0x294A,0x318C,
+ 0x39CE,0x4210,0x4A52,0x5294,0x5AD6,0x6318,0x6B5A,0x739C,
+ 0x7BDE,0x08A0,0x0D02,0x1142,0x19C2,0x3EEB,0x430D,0x4B6C,
+ 0x4F4F,0x4F50,0x432A,0x368A,0x328A,0x3AE9,0x3689,0x3268,
+ 0x2A26,0x2A27,0x3AE9,0x4B4E,0x3269,0x3EEB,0x3AA8,0x19A3,
+ 0x08E2,0x21E5,0x2E47,0x3F2A,0x4B4F,0x3F0B,0x3AEB,0x36A8,
+ 0x25E3,0x1DC6,0x2606,0x2E46,0x36AA,0x2E66,0x36A8,0x36CA,
+ 0x32A9,0x2604,0x15C2,0x1182,0x0D42,0x1583,0x1162,0x0D22,
+ 0x15A2,0x19E3,0x11C2,0x1E45,0x1A04,0x2204,0x2E68,0x25E4,
+ 0x1DA4,0x3268,0x3AC9,0x4B2D,0x36A9,0x430C,0x2A46,0x534F,
+ 0x532F,0x42EA,0x2A26,0x1964,0x4F8E,0x4F8D,0x4B6C,0x474D,
+ 0x434A,0x3F29,0x3AE8,0x3B08,0x474B,0x3F09,0x4349,0x4B6B,
+ 0x1944,0x1D44,0x25C7,0x2E08,0x3AEA,0x3688,0x3247,0x3A2A,
+ 0x3AC8,0x3689,0x3EAA,0x426E,0x10C3,0x2603,0x1503,0x1925,
+ 0x42CA,0x42EB,0x3F2A,0x25E3,0x42A8,0x534E,0x1924,0x46CC,
+ 0x4B0D,0x2EA4,0x1DE4,0x2605,0x2E67,0x3ACA,0x3AAA,0x2A45,
+
+ 0x1185,0x2E46,0x1122,0x0862,0x08C2,0x1562,0x2A25,0x2A26,
+ 0x2624,0x472E,0x3688,0x4B4D,0x15A3,0x21E4,0x4F4E,0x4F6E,
+ 0x4F6D,0x5F34,0x5F36,0x5F36,0x5F56,0x4ED1,0x46AF,0x426E,
+ 0x2E26,0x21C6,0x324A,0x5B14,0x6777,0x6356,0x5F15,0x036E,
+ 0x036F,0x032D,0x034D,0x034E,0x030C,0x02ED,0x02CC,0x02EC,
+ 0x030D,0x0289,0x02EE,0x0207,0x01E7,0x0207,0x09A2,0x0DC2,
+ 0x0D82,0x0D85,0x0227,0x0249,0x0269,0x030F,0x02CD,0x02ED,
+ 0x030E,0x030D,0x032E,0x0228,0x02AB,0x028A,0x028A,0x02AA,
+ 0x0269,0x01E8,0x036E,0x032D,0x0289,0x02A9,0x02CE,0x0332,
+ 0x0331,0x0351,0x0351,0x0350,0x0350,0x0330,0x02D1,0x0332,
+ 0x0310,0x5FE5,0x5BE5,0x5BE5,0x5BE4,0x57E4,0x5BE4,0x4FA4,
+ 0x4B84,0x4B84,0x4F85,0x53A4,0x4B85,0x53A6,0x57C5,0x4366,
+ 0x4B87,0x4BA7,0x4766,0x2EC4,0x2EA6,0x2643,0x3B07,0x32A3,
+ 0x36C3,0x57E8,0x57CA,0x4FC4,0x32E3,0x32E4,0x32C3,0x2263,
+ 0x2AA3,0x2E91,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,0x43E0,
+ 0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,0x7FFC,
+
+ 0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0,0x46E0,
+ 0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6,0x7FFC,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09,0x4009,
+ 0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD,0x7EBD,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,0x181C,
+ 0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F,0x6DFF,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F,0x401F,
+ 0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,0x7B5F,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5,0x1358,
+ 0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF,0x77FF,
+ 0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200,0x0260,
+ 0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3,0x6FF8,
+ 0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,0x2300,
+ 0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,0x77F5,
+ 0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,0x5407,
+ 0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,0x7F5D,
+
+ 0x7BDE,0x3408,0x3C0F,0x4813,0x4C12,0x5413,0x5C0F,0x680D,
+ 0x700A,0x7484,0x7900,0x7DA0,0x7ECD,0x7F6D,0x7FF5,0x7F7E,
+ 0x7BDE,0x240C,0x280C,0x2C0C,0x340C,0x380C,0x3C0C,0x400C,
+ 0x440E,0x4810,0x5012,0x5413,0x400E,0x440E,0x4C0E,0x284F,
+ 0x2C4E,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1,0x3724,0x3FA6,
+ 0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,0x7FFA,
+ 0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,0x3EA0,
+ 0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,0x7FF6,
+ 0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,0x3C09,
+ 0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,0x7DBD,
+ 0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,0x101A,
+ 0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,0x681F,
+ 0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,0x381F,
+ 0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,0x7E5F,
+ 0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,0x0AF5,
+ 0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,0x6BFF,
+
+ 0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,0x0200,
+ 0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,0x5FF3,
+ 0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,0x1EC0,
+ 0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,0x77EE,
+ 0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,0x4C07,
+ 0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,0x7EBA,
+ 0x7F5D,0x7BDE,0x0216,0x0257,0x12D8,0x2718,0x2FB8,0x3FB9,
+ 0x47FA,0x4FFC,0x53FF,0x5BFF,0x5BFF,0x67FE,0x6FFF,0x73DF,
+ 0x7BDF,0x7FFF,0x01B2,0x01F4,0x0215,0x0237,0x0258,0x027A,
+ 0x029B,0x02DB,0x02FA,0x033A,0x035B,0x029B,0x02DD,0x031F,
+ 0x0210,0x0215,0xFFFF,0x41D3,0x6004,0x3FA6,0x2AA1,0x3724,
+ 0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,0x77F3,
+ 0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,0x36A0,
+ 0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,0x7FF0,
+ 0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x3809,
+ 0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,0x70FB,
+
+ 0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0013,
+ 0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,0x581F,
+ 0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x301F,
+ 0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,0x7C5F,
+ 0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,0x02B3,
+ 0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,0x5FFF,
+ 0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,0x0200,
+ 0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,0x47EC,
+ 0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,0x0E60,
+ 0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,0x67ED,
+ 0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,0x4409,
+ 0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,0x7E15,
+ 0x7EBA,0x7F5D,0x7BDE,0x1B01,0x23A0,0x2FC0,0x3BE0,0x43E0,
+ 0x4FC0,0x57C0,0x5FE0,0x63E0,0x67E0,0x6FE0,0x77EE,0x7FF3,
+ 0x7FFA,0x7FFC,0x7FFF,0x0220,0x0260,0x0280,0x02C0,0x02E0,
+ 0x0320,0x0340,0x2780,0x2BA0,0x37E0,0x3FE0,0x0340,0x0BE0,
+
+ 0x13E0,0x1DA3,0x2243,0xFFFF,0x410E,0x6004,0x3FA6,0x2AA1,
+ 0x3724,0x3FA6,0x43E0,0x4FE8,0x5BC4,0x63C5,0x67ED,0x6FF0,
+ 0x77F3,0x7FFA,0x7FFC,0x7FFF,0x352E,0x7FE0,0x7C1F,0x7C00,
+ 0x36A0,0x3EA0,0x46E0,0x5320,0x5F80,0x6BE0,0x73E0,0x7FE2,
+ 0x7FF0,0x7FF6,0x7FFC,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x3809,0x3C09,0x4009,0x4406,0x480E,0x500F,0x5812,0x6016,
+ 0x70FB,0x7DBD,0x7EBD,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x0013,0x101A,0x181C,0x201F,0x281F,0x341F,0x401F,0x481F,
+ 0x581F,0x681F,0x6DFF,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x301F,0x381F,0x401F,0x481F,0x541F,0x5C1F,0x681F,0x701F,
+ 0x7C5F,0x7E5F,0x7B5F,0x7BDE,0x0000,0x7FE0,0x7C1F,0x024F,
+ 0x02B3,0x0AF5,0x1358,0x1B9C,0x23FD,0x2BFF,0x3FFF,0x4FFF,
+ 0x5FFF,0x6BFF,0x77FF,0x7FFF,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x0200,0x0200,0x0260,0x02C0,0x0320,0x03E0,0x23E0,0x33E7,
+ 0x47EC,0x5FF3,0x6FF8,0x7BDE,0x0000,0x7FE0,0x7C1F,0x7C00,
+ 0x0E60,0x1EC0,0x2300,0x2F60,0x33E0,0x43E0,0x4FE0,0x63E0,
+
+ 0x67ED,0x77EE,0x77F5,0x7BDE,0x2D2F,0x7FE0,0x3405,0x3C05,
+ 0x4409,0x4C07,0x5407,0x5C0A,0x6409,0x6C09,0x7409,0x7CCF,
+ 0x7E15,0x7EBA,0x7F5D,0x7BDE,0x19B7,0x21DA,0x31BC,0x3D9E,
+ 0x499E,0x511D,0x5CFE,0x60DF,0x68BF,0x707F,0x741F,0x7C1F,
+ 0x7E7F,0x7F5F,0x7F9F,0x7FFF,0x018C,0x018E,0x018F,0x0191,
+ 0x0192,0x0194,0x0195,0x2597,0x2998,0x3599,0x3D99,0x0195,
+ 0x0999,0x1199,0x21CF,0x25D4,0xFFFF,0x0004,0xCE4A,0x0004
+};
+
+// --- tilemap data ---
+// tile data (ff means no tiles) followed by routine index (end marker: 0xff00)
+static UINT16 bloodwar_mcu_4_1c[] = { // Warrior 8
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0D00,0xFF06,
+ 0x01BF,0xFF06,0x00FF,0xFF06,0x0008,0x2C01,0xFF06,0x0001,
+ 0xFF05,0x0002,0x2C02,0xFF06,0x0001,0xFF05,0x0002,0x2C55,
+ 0xFF06,0x0001,0x2C58,0xFF06,0x0008,0xFF06,0x0007,0xFF05,
+ 0x0007,0x2C05,0xFF05,0x0007,0x2C59,0xFF06,0x0007,0xFF06,
+ 0x0007,0xFF05,0x0007,0x2C0D,0xFF05,0x0007,0x2C61,0xFF06,
+ 0x0007,0xFF05,0x000F,0x2C15,0xFF05,0x000F,0x2C69,0xFF05,
+ 0x000F,0x2C25,0xFF05,0x000F,0x2C79,0xFF05,0x000F,0x2C35,
+ 0xFF05,0x000F,0x2C89,0xFF05,0x000F,0x2C45,0xFF05,0x000F,
+ 0x2C99,0xFF04,0x0002,0xFF09,0x0007,0x28D0,0xFF04,0x0000,
+ 0xFF05,0x0007,0x28A9,0xFF05,0x000F,0x28C1,0xFF04,0x0002,
+ 0xFF09,0x0007,0x28E0,0xFF04,0x0000,0xFF05,0x0007,0x28B1,
+ 0xFF05,0x000F,0x28D1,0xFF04,0x0002,0xFF09,0x0007,0x28F0,
+ 0xFF04,0x0000,0xFF05,0x0007,0x28B9,0xFF05,0x000F,0x28E1,
+ 0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x0E00,0xFF06,
+ 0x01BF,0xFF06,0x001F,0xFF06,0x0001,0xFF05,0x0002,0x2401,
+
+ 0xFF06,0x001A,0xFF06,0x0001,0xFF05,0x0003,0x2404,0xFF06,
+ 0x0019,0xFF06,0x0001,0xFF05,0x0004,0x2409,0xFF06,0x0018,
+ 0xFF06,0x0001,0xFF05,0x0005,0x240E,0xFF06,0x0011,0xFF05,
+ 0x0003,0x2474,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0008,
+ 0x2414,0xFF06,0x000A,0xFF05,0x0007,0x2478,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x0008,0x241D,0xFF06,0x000A,0xFF05,
+ 0x0007,0x2480,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0009,
+ 0x2426,0xFF06,0x0009,0xFF05,0x0007,0x2488,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x0009,0x2430,0xFF06,0x0008,0xFF05,
+ 0x0008,0x2490,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x000A,
+ 0x243A,0xFF06,0x0007,0xFF05,0x0008,0x2499,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x000A,0x2445,0xFF06,0x0007,0xFF05,
+ 0x0008,0x24A2,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0008,
+ 0x2450,0xFF06,0x0009,0xFF05,0x0008,0x24AB,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x0008,0x2459,0xFF06,0x0009,0xFF05,
+ 0x0008,0x24B4,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0008,
+
+ 0x2462,0xFF06,0x0009,0xFF05,0x0008,0x24BD,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x0008,0x246B,0xFF06,0x0008,0xFF05,
+ 0x0009,0x48C6,0xFF06,0x0001,0xFF05,0x001F,0x48C6,0xFF06,
+ 0x003F,0xFF08,0xFF02,0x0002,0xFF03,0x0400,0xFF01,0x0B00,
+ 0xFF06,0x01BF,0xFF06,0x005F,0xFF06,0x000A,0xFF05,0x0001,
+ 0x3001,0xFF06,0x0012,0xFF06,0x0008,0xFF05,0x0004,0x3003,
+ 0xFF06,0x0011,0xFF06,0x0006,0xFF05,0x0008,0x3008,0xFF06,
+ 0x000F,0xFF06,0x0004,0xFF05,0x000A,0x3011,0xFF06,0x000F,
+ 0xFF06,0x0004,0xFF05,0x000B,0x301C,0xFF05,0x0009,0x3461,
+ 0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x000B,0x3028,0xFF05,
+ 0x0009,0x346B,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0015,
+ 0x3034,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0015,0x304A,
+ 0xFF06,0x0004,0xFF06,0x0004,0xFF0A,0x0015,0x3060,0xFF06,
+ 0x0004,0xFF06,0x00BF,0xFF08,0xFF02,0x0003,0xFF03,0x0400,
+ 0xFF01,0x0B00,0xFF06,0x01BF,0xFF06,0x003F,0xFF06,0x000E,
+ 0xFF05,0x0002,0x34D5,0xFF06,0x0001,0xFF05,0x0002,0x3880,
+
+ 0xFF06,0x0008,0xFF06,0x000E,0xFF05,0x0002,0x34D8,0xFF06,
+ 0x0000,0xFF05,0x0004,0x3883,0xFF06,0x0007,0xFF06,0x000E,
+ 0xFF05,0x0002,0x34DB,0xFF06,0x0000,0xFF05,0x0004,0x3888,
+ 0xFF06,0x0007,0xFF06,0x0011,0xFF05,0x0006,0x388D,0xFF06,
+ 0x0006,0xFF06,0x0010,0xFF05,0x0007,0x3894,0xFF06,0x0006,
+ 0xFF06,0x000E,0xFF05,0x000A,0x389C,0xFF06,0x0005,0xFF06,
+ 0x000F,0xFF05,0x0009,0x38A7,0xFF06,0x0005,0xFF06,0x000E,
+ 0xFF05,0x000A,0x38B1,0xFF06,0x0004,0xFF06,0x000E,0xFF05,
+ 0x000A,0x38BD,0xFF06,0x0004,0xFF06,0x000E,0xFF05,0x000A,
+ 0x38C9,0xFF06,0x0004,0xFF06,0x00BF,0xFF00,0xFF08,0xFF02
+};
+static UINT16 bloodwar_mcu_4_1d[] = { // Warrior 2
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0000,0xFF06,
+ 0x01BF,0xFF06,0x0003,0x4401,0xFF06,0x0002,0x4401,0xFF05,
+ 0x0001,0x340B,0xFF06,0x0000,0x4401,0xFF06,0x0005,0xFF04,
+ 0x0002,0x4401,0xFF06,0x0000,0xFF04,0x0000,0xFF05,0x0002,
+ 0x341F,0xFF04,0x0002,0x4401,0xFF06,0x0002,0x4401,0xFF04,
+ 0x0000,0xFF06,0x0002,0xFF06,0x0003,0x4402,0xFF06,0x0002,
+ 0x4402,0xFF05,0x0001,0x340B,0xFF06,0x0000,0x4402,0xFF06,
+ 0x0005,0xFF04,0x0002,0x4402,0xFF06,0x0000,0xFF04,0x0000,
+ 0xFF05,0x0002,0x341F,0xFF04,0x0002,0x4402,0xFF06,0x0002,
+ 0x4402,0xFF04,0x0000,0xFF06,0x0002,0xFF06,0x0002,0xFF05,
+ 0x0001,0x4403,0xFF06,0x0001,0xFF05,0x0001,0x4403,0xFF05,
+ 0x0001,0x340B,0xFF05,0x0001,0x4403,0xFF06,0x0005,0xFF04,
+ 0x0002,0xFF09,0x0001,0x4404,0xFF04,0x0000,0xFF05,0x0002,
+ 0x341F,0xFF04,0x0002,0xFF09,0x0001,0x4404,0xFF06,0x0001,
+ 0xFF09,0x0001,0x4404,0xFF04,0x0000,0xFF06,0x0001,0xFF06,
+ 0x0002,0xFF05,0x0001,0x4005,0xFF06,0x0001,0xFF05,0x0001,
+
+ 0x4005,0xFF05,0x0001,0x340B,0xFF05,0x0001,0x4005,0xFF06,
+ 0x0005,0xFF04,0x0002,0xFF09,0x0001,0x4006,0xFF04,0x0000,
+ 0xFF05,0x0002,0x341F,0xFF04,0x0002,0xFF09,0x0001,0x4006,
+ 0xFF06,0x0001,0xFF09,0x0001,0x4006,0xFF04,0x0000,0xFF06,
+ 0x0001,0xFF06,0x0002,0xFF05,0x0001,0x4007,0xFF06,0x0001,
+ 0xFF05,0x0001,0x4007,0xFF05,0x0001,0x340D,0xFF05,0x0001,
+ 0x4007,0xFF06,0x0005,0xFF04,0x0002,0xFF09,0x0001,0x4008,
+ 0xFF04,0x0000,0xFF05,0x0002,0x3422,0xFF04,0x0002,0xFF09,
+ 0x0001,0x4008,0xFF06,0x0001,0xFF09,0x0001,0x4008,0xFF04,
+ 0x0000,0xFF06,0x0001,0xFF06,0x0002,0xFF05,0x0001,0x4409,
+ 0xFF06,0x0001,0xFF05,0x0001,0x4409,0xFF05,0x0001,0x340F,
+ 0xFF05,0x0001,0x4409,0xFF06,0x0005,0xFF04,0x0002,0xFF09,
+ 0x0001,0x440A,0xFF04,0x0000,0xFF05,0x0002,0x3425,0xFF04,
+ 0x0002,0xFF09,0x0001,0x440A,0xFF06,0x0001,0xFF09,0x0001,
+ 0x440A,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0008,0xFF05,
+ 0x0001,0x3411,0xFF06,0x0009,0xFF05,0x0002,0x3428,0xFF06,
+
+ 0x0007,0xFF06,0x0008,0xFF05,0x0001,0x3413,0xFF06,0x0009,
+ 0xFF05,0x0002,0x342B,0xFF06,0x0007,0xFF06,0x0008,0xFF05,
+ 0x0001,0x3415,0xFF06,0x0009,0xFF05,0x0002,0x342E,0xFF06,
+ 0x0007,0xFF06,0x0006,0x383E,0xFF06,0x0000,0xFF05,0x0001,
+ 0x3417,0x383D,0xFF06,0x0007,0x383E,0xFF05,0x0002,0x3431,
+ 0x383D,0xFF06,0x0006,0xFF05,0x0007,0x3841,0xFF06,0x0000,
+ 0xFF05,0x0001,0x3419,0xFF05,0x0009,0x383F,0xFF05,0x0002,
+ 0x3434,0xFF05,0x0007,0x383F,0xFF05,0x0007,0x384B,0xFF06,
+ 0x0000,0xFF05,0x0001,0x341B,0xFF05,0x0009,0x3849,0xFF05,
+ 0x0002,0x3437,0xFF05,0x0007,0x3849,0xFF05,0x0007,0x3855,
+ 0xFF06,0x0000,0xFF05,0x0001,0x341D,0xFF05,0x0009,0x3853,
+ 0xFF05,0x0002,0x343A,0xFF05,0x0007,0x3853,0xFF06,0x0006,
+ 0xFF05,0x0001,0x385E,0xFF06,0x0001,0x385D,0xFF06,0x0007,
+ 0xFF05,0x0001,0x385E,0xFF06,0x0001,0x385D,0xFF06,0x0006,
+ 0xFF04,0x0002,0xFF09,0x000D,0x3C71,0xFF04,0x0000,0xFF05,
+ 0x0011,0x3C60,0xFF04,0x0002,0xFF09,0x000D,0x3C83,0xFF04,
+
+ 0x0000,0xFF05,0x0011,0x3C72,0xFF04,0x0002,0xFF09,0x000D,
+ 0x3C95,0xFF04,0x0000,0xFF05,0x0011,0x3C84,0xFF04,0x0002,
+ 0xFF09,0x000D,0x3CA7,0xFF04,0x0000,0xFF05,0x0011,0x3C96,
+ 0xFF08,0xFF02,0x0001,0xFF03,0x0300,0xFF01,0x0000,0xFF06,
+ 0x01BF,0xFF06,0x0003,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,
+ 0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,
+ 0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,
+ 0xFF05,0x0002,0x2CB0,0xFF06,0x0003,0xFF06,0x0003,0xFF05,
+ 0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,
+ 0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,
+ 0x2CB0,0xFF05,0x0002,0x2CB0,0xFF05,0x0002,0x2CB0,0xFF06,
+ 0x0003,0xFF06,0x0003,0xFF05,0x0003,0x2CB3,0xFF05,0x0003,
+ 0x2CB3,0xFF05,0x0003,0x2CB3,0xFF05,0x0003,0x2CB3,0xFF05,
+ 0x0003,0x2CB3,0xFF05,0x0003,0x2CB3,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x2CB7,0xFF06,0x0004,0xFF05,0x0002,
+ 0x2CB9,0xFF06,0x0004,0xFF05,0x0002,0x2D13,0xFF06,0x0004,
+
+ 0x2D16,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CBC,
+ 0xFF06,0x0004,0xFF05,0x0002,0x2CBE,0xFF06,0x0004,0xFF05,
+ 0x0002,0x2D17,0xFF06,0x0004,0x2D1A,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x2CC1,0xFF06,0x0004,0xFF05,0x0002,
+ 0x2CC3,0xFF06,0x0004,0xFF05,0x0002,0x2D1B,0xFF06,0x0004,
+ 0x2D1E,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CC6,
+ 0xFF06,0x0004,0xFF05,0x0002,0x2CC8,0xFF06,0x0004,0xFF05,
+ 0x0002,0x2D1F,0xFF06,0x0004,0x2D22,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x2CCB,0xFF06,0x0004,0xFF05,0x0002,
+ 0x2CCD,0xFF06,0x0004,0xFF05,0x0002,0x2D23,0xFF06,0x0004,
+ 0x2D26,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CD0,
+ 0xFF06,0x0004,0xFF05,0x0002,0x2CD2,0xFF06,0x0004,0xFF05,
+ 0x0002,0x2D27,0xFF06,0x0004,0x2D2A,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x2CD5,0xFF06,0x0004,0xFF05,0x0002,
+ 0x2CD7,0xFF06,0x0004,0xFF05,0x0002,0x2D2B,0xFF06,0x0004,
+ 0x2D2E,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2CDA,
+
+ 0xFF06,0x0004,0xFF05,0x0002,0x2CDC,0xFF06,0x0004,0xFF05,
+ 0x0002,0x2D2F,0xFF06,0x0004,0x2D32,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x000B,0x2CDF,0xFF05,0x000B,0x2D33,0xFF06,
+ 0x0003,0xFF06,0x0003,0xFF05,0x000B,0x2CEB,0xFF05,0x000B,
+ 0x2D3F,0xFF06,0x0003,0xFF06,0x0001,0x2CF7,0xFF05,0x0008,
+ 0x2CF7,0xFF05,0x0003,0x2D01,0xFF05,0x000C,0x2D4B,0x2CF7,
+ 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x000D,0x2D05,0xFF05,
+ 0x000D,0x2D58,0xFF06,0x0001,0xFF06,0x005F,0xFF08,0xFF02,
+ 0x0002,0xFF03,0x0400,0xFF01,0x0000,0xFF06,0x01BF,0xFF06,
+ 0x003F,0xFF05,0x0007,0x3001,0xFF05,0x0007,0x3001,0xFF05,
+ 0x0007,0x3001,0xFF05,0x0007,0x3001,0xFF05,0x0007,0x3009,
+ 0xFF05,0x0007,0x3009,0xFF05,0x0007,0x3009,0xFF05,0x0007,
+ 0x3009,0xFF06,0x001F,0xFF03,0x0300,0xFF06,0x0003,0xFF05,
+ 0x0001,0x2811,0xFF06,0x0003,0xFF05,0x0001,0x2811,0xFF06,
+ 0x0007,0xFF05,0x0001,0x2811,0xFF06,0x0003,0xFF05,0x0001,
+ 0x2811,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x2813,
+
+ 0xFF06,0x0003,0xFF05,0x0001,0x2813,0xFF06,0x0007,0xFF05,
+ 0x0001,0x2813,0xFF06,0x0003,0xFF05,0x0001,0x2813,0xFF06,
+ 0x0003,0xFF06,0x0002,0xFF05,0x0003,0x2815,0xFF06,0x0001,
+ 0xFF05,0x0003,0x2815,0xFF06,0x0005,0xFF05,0x0003,0x2815,
+ 0xFF06,0x0001,0xFF05,0x0003,0x2815,0xFF06,0x0002,0xFF06,
+ 0x0002,0xFF05,0x0003,0x2819,0xFF06,0x0001,0xFF05,0x0003,
+ 0x2819,0xFF06,0x0005,0xFF05,0x0003,0x2819,0xFF06,0x0001,
+ 0xFF05,0x0003,0x2819,0xFF06,0x0002,0xFF06,0x0001,0xFF05,
+ 0x0004,0x281D,0xFF06,0x0000,0xFF05,0x0004,0x281D,0xFF06,
+ 0x0004,0xFF05,0x0004,0x281D,0xFF06,0x0000,0xFF05,0x0004,
+ 0x281D,0xFF06,0x0002,0xFF06,0x0001,0xFF05,0x0005,0x2822,
+ 0xFF05,0x0005,0x2822,0xFF06,0x0003,0xFF05,0x0005,0x2822,
+ 0xFF05,0x0005,0x2822,0xFF06,0x0001,0xFF06,0x0001,0xFF05,
+ 0x0005,0x2828,0xFF05,0x0005,0x2828,0xFF06,0x0003,0xFF05,
+ 0x0005,0x2828,0xFF05,0x0005,0x2828,0xFF06,0x0001,0xFF06,
+ 0x00BF,0xFF08,0xFF02,0x0003,0xFF03,0x0300,0xFF01,0x0000,
+
+ 0xFF06,0x01BF,0xFF06,0x007F,0xFF06,0x0003,0xFF05,0x0002,
+ 0x2432,0xFF05,0x0002,0x2046,0xFF05,0x0004,0x2430,0xFF05,
+ 0x0002,0x2046,0xFF05,0x0004,0x2430,0xFF05,0x0002,0x2046,
+ 0xFF05,0x0001,0x2430,0xFF06,0x0003,0xFF06,0x0003,0xFF05,
+ 0x0002,0x2437,0xFF05,0x0002,0x2049,0xFF05,0x0004,0x2435,
+ 0xFF05,0x0002,0x2049,0xFF05,0x0004,0x2435,0xFF05,0x0002,
+ 0x2049,0xFF05,0x0001,0x2435,0xFF06,0x0003,0xFF06,0x0003,
+ 0xFF05,0x0001,0x243C,0xFF05,0x0003,0x204C,0xFF05,0x0003,
+ 0x243A,0xFF05,0x0003,0x204C,0xFF05,0x0003,0x243A,0xFF05,
+ 0x0003,0x204C,0xFF05,0x0001,0x243A,0xFF06,0x0003,0xFF06,
+ 0x0003,0x243F,0xFF05,0x0005,0x2050,0xFF05,0x0001,0x243E,
+ 0xFF05,0x0005,0x2050,0xFF05,0x0001,0x243E,0xFF05,0x0005,
+ 0x2050,0x283E,0xFF06,0x0003,0xFF06,0x0003,0x2441,0xFF05,
+ 0x0005,0x2056,0xFF05,0x0001,0x2440,0xFF05,0x0005,0x2056,
+ 0xFF05,0x0001,0x2440,0xFF05,0x0005,0x2056,0x2840,0xFF06,
+ 0x0003,0xFF06,0x0003,0x2443,0xFF05,0x0005,0x205C,0xFF05,
+
+ 0x0001,0x2442,0xFF05,0x0005,0x205C,0xFF05,0x0001,0x2442,
+ 0xFF05,0x0005,0x205C,0x2842,0xFF06,0x0003,0xFF06,0x0003,
+ 0x2445,0xFF05,0x0005,0x2062,0xFF05,0x0001,0x2444,0xFF05,
+ 0x0005,0x2062,0xFF05,0x0001,0x2444,0xFF05,0x0005,0x2062,
+ 0x2844,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0007,0x2068,
+ 0xFF05,0x0007,0x2068,0xFF05,0x0007,0x2068,0xFF06,0x0003,
+ 0xFF06,0x0003,0xFF05,0x0007,0x2070,0xFF05,0x0007,0x2070,
+ 0xFF05,0x0007,0x2070,0xFF06,0x0003,0xFF06,0x009F,0xFF00,
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0200,0xFF06
+};
+static UINT16 bloodwar_mcu_4_1e[] = { // Warrior 3
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0200,0xFF06,
+ 0x01BF,0xFF05,0x000F,0x2C01,0xFF05,0x000F,0x2C01,0xFF05,
+ 0x000F,0x2C11,0xFF05,0x000F,0x2C11,0xFF05,0x0001,0x3C27,
+ 0xFF06,0x0003,0xFF05,0x0003,0x3C25,0xFF06,0x0003,0xFF05,
+ 0x0003,0x3C25,0xFF06,0x0003,0xFF05,0x0003,0x3C25,0xFF06,
+ 0x0003,0xFF05,0x0001,0x3C25,0xFF05,0x0001,0x3C2B,0xFF06,
+ 0x0003,0xFF05,0x0003,0x3C29,0xFF06,0x0003,0xFF05,0x0003,
+ 0x3C29,0xFF06,0x0003,0xFF05,0x0003,0x3C29,0xFF06,0x0003,
+ 0xFF05,0x0001,0x3C29,0xFF05,0x0001,0x3C2F,0xFF06,0x0003,
+ 0xFF05,0x0003,0x3C2D,0xFF06,0x0003,0xFF05,0x0003,0x3C2D,
+ 0xFF06,0x0003,0xFF05,0x0003,0x3C2D,0xFF06,0x0003,0xFF05,
+ 0x0001,0x3C2D,0xFF05,0x0001,0x3C33,0xFF06,0x0003,0xFF05,
+ 0x0003,0x3C31,0xFF06,0x0003,0xFF05,0x0003,0x3C31,0xFF06,
+ 0x0003,0xFF05,0x0003,0x3C31,0xFF06,0x0003,0xFF05,0x0001,
+ 0x3C31,0x3C36,0xFF06,0x0005,0xFF05,0x0001,0x3C35,0xFF06,
+ 0x0005,0xFF05,0x0001,0x3C35,0xFF06,0x0005,0xFF05,0x0001,
+
+ 0x3C35,0xFF06,0x0005,0x3C35,0xFF06,0x00DF,0xFF03,0x0300,
+ 0xFF06,0x0001,0xFF05,0x0001,0x2439,0xFF05,0x0001,0x203B,
+ 0xFF05,0x0002,0x243D,0xFF05,0x000C,0x2040,0xFF04,0x0002,
+ 0x2040,0xFF09,0x0002,0x243F,0xFF09,0x0001,0x203C,0xFF09,
+ 0x0001,0x243A,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0000,
+ 0xFF05,0x0002,0x244E,0xFF05,0x0001,0x2051,0xFF05,0x0002,
+ 0x2453,0xFF05,0x000C,0x2056,0xFF04,0x0002,0x2056,0xFF09,
+ 0x0002,0x2455,0xFF09,0x0001,0x2052,0xFF09,0x0002,0x2450,
+ 0xFF04,0x0000,0xFF06,0x0000,0xFF05,0x0003,0x2463,0xFF05,
+ 0x0001,0x2067,0xFF05,0x0002,0x2469,0xFF05,0x000C,0x206C,
+ 0xFF04,0x0002,0x206C,0xFF09,0x0002,0x246B,0xFF09,0x0001,
+ 0x2068,0xFF09,0x0003,0x2466,0xFF04,0x0000,0xFF05,0x0003,
+ 0x2479,0xFF05,0x0001,0x207D,0xFF05,0x0002,0x247F,0xFF05,
+ 0x000C,0x2082,0xFF04,0x0002,0x2082,0xFF09,0x0002,0x2481,
+ 0xFF09,0x0001,0x207E,0xFF09,0x0003,0x247C,0xFF04,0x0000,
+ 0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x0200,0xFF06,
+
+ 0x01BF,0xFF06,0x003F,0xFF06,0x0003,0xFF05,0x0001,0x38AB,
+ 0xFF06,0x0002,0xFF05,0x0001,0x38AB,0xFF06,0x0009,0xFF04,
+ 0x0002,0xFF09,0x0001,0x38AC,0xFF06,0x0002,0xFF09,0x0001,
+ 0x38AC,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,
+ 0x0001,0x38AD,0xFF06,0x0002,0xFF05,0x0001,0x38AD,0xFF06,
+ 0x0009,0xFF04,0x0002,0xFF09,0x0001,0x38AE,0xFF06,0x0002,
+ 0xFF09,0x0001,0x38AE,0xFF04,0x0000,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x38AF,0xFF06,0x0002,0xFF05,0x0001,
+ 0x38AF,0xFF06,0x0009,0xFF04,0x0002,0xFF09,0x0001,0x38B0,
+ 0xFF06,0x0002,0xFF09,0x0001,0x38B0,0xFF04,0x0000,0xFF06,
+ 0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38B1,0xFF06,0x0002,
+ 0xFF05,0x0001,0x38B1,0xFF06,0x0009,0xFF04,0x0002,0xFF09,
+ 0x0001,0x38B2,0xFF06,0x0002,0xFF09,0x0001,0x38B2,0xFF04,
+ 0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38B3,
+ 0xFF06,0x0002,0xFF05,0x0001,0x38B3,0xFF06,0x0000,0xFF05,
+ 0x0001,0x3490,0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0001,
+
+ 0x3091,0xFF06,0x0000,0xFF09,0x0001,0x38B4,0xFF06,0x0002,
+ 0xFF09,0x0001,0x38B4,0xFF04,0x0000,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x38B5,0xFF06,0x0002,0xFF05,0x0001,
+ 0x38B5,0xFF06,0x0000,0xFF05,0x0002,0x3492,0xFF06,0x0001,
+ 0xFF04,0x0002,0xFF09,0x0002,0x3094,0xFF06,0x0000,0xFF09,
+ 0x0001,0x38B6,0xFF06,0x0002,0xFF09,0x0001,0x38B6,0xFF04,
+ 0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38B7,
+ 0xFF06,0x0002,0xFF05,0x0001,0x38B7,0xFF06,0x0000,0xFF05,
+ 0x0002,0x3495,0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x0002,
+ 0x3097,0xFF06,0x0000,0xFF09,0x0001,0x38B8,0xFF06,0x0002,
+ 0xFF09,0x0001,0x38B8,0xFF04,0x0000,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x38B9,0xFF06,0x0002,0xFF05,0x0001,
+ 0x38B9,0xFF05,0x0003,0x3498,0xFF06,0x0001,0xFF04,0x0002,
+ 0xFF09,0x0003,0x309B,0xFF09,0x0001,0x38BA,0xFF06,0x0002,
+ 0xFF09,0x0001,0x38BA,0xFF04,0x0000,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0001,0x38BB,0xFF06,0x0002,0xFF05,0x0001,
+
+ 0x38BB,0xFF05,0x0004,0x349C,0xFF04,0x0002,0xFF09,0x0004,
+ 0x30A0,0xFF09,0x0001,0x38BC,0xFF06,0x0002,0xFF09,0x0001,
+ 0x38BC,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,
+ 0x0001,0x38BD,0xFF06,0x0002,0xFF05,0x0001,0x38BD,0xFF05,
+ 0x0004,0x34A1,0xFF04,0x0002,0xFF09,0x0004,0x30A5,0xFF09,
+ 0x0001,0x38BE,0xFF06,0x0002,0xFF09,0x0001,0x38BE,0xFF04,
+ 0x0000,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38BF,
+ 0xFF06,0x0002,0xFF05,0x0001,0x38BF,0xFF05,0x0004,0x34A6,
+ 0xFF04,0x0002,0xFF09,0x0004,0x30AA,0xFF09,0x0001,0x38C0,
+ 0xFF06,0x0002,0xFF09,0x0001,0x38C0,0xFF04,0x0000,0xFF06,
+ 0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38C1,0xFF06,0x0002,
+ 0xFF05,0x0007,0x38C1,0xFF04,0x0002,0xFF09,0x0005,0x38C6,
+ 0xFF06,0x0002,0xFF09,0x0001,0x38C2,0xFF04,0x0000,0xFF06,
+ 0x0003,0xFF06,0x0003,0xFF05,0x0001,0x38C9,0xFF06,0x0002,
+ 0xFF05,0x0007,0x38C9,0xFF04,0x0002,0xFF09,0x0005,0x38CE,
+ 0xFF06,0x0002,0xFF09,0x0001,0x38CA,0xFF04,0x0000,0xFF06,
+
+ 0x0003,0xFF06,0x005F,0xFF08,0xFF02,0x0002,0xFF03,0x0400,
+ 0xFF01,0x0100,0xFF06,0x01BF,0xFF06,0x003F,0xFF05,0x0002,
+ 0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0002,0x2C01,0xFF05,
+ 0x0002,0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0002,0x2C01,
+ 0xFF05,0x0002,0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0002,
+ 0x2C01,0xFF05,0x0002,0x2C01,0xFF05,0x0001,0x2C01,0xFF05,
+ 0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0002,0x2C04,
+ 0xFF05,0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0002,
+ 0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05,
+ 0x0002,0x2C04,0xFF05,0x0002,0x2C04,0xFF05,0x0001,0x2C04,
+ 0xFF05,0x0007,0x2C07,0xFF05,0x0007,0x2C07,0xFF05,0x0007,
+ 0x2C07,0xFF05,0x0007,0x2C07,0xFF05,0x0007,0x2C0F,0xFF05,
+ 0x0007,0x2C0F,0xFF05,0x0007,0x2C0F,0xFF05,0x0007,0x2C0F,
+ 0xFF06,0x0002,0x3819,0xFF06,0x0003,0x3819,0xFF06,0x0003,
+ 0x3819,0xFF06,0x0003,0x3819,0xFF06,0x0003,0x3819,0xFF06,
+ 0x0003,0x3819,0xFF06,0x0002,0xFF06,0x0002,0x381A,0xFF06,
+
+ 0x0003,0x381A,0xFF06,0x0003,0x381A,0xFF06,0x0003,0x381A,
+ 0xFF06,0x0003,0x381A,0xFF06,0x0003,0x381A,0xFF06,0x0002,
+ 0xFF06,0x0002,0x381B,0xFF06,0x0003,0x381B,0xFF06,0x0003,
+ 0x381B,0xFF06,0x0003,0x381B,0xFF06,0x0003,0x381B,0xFF06,
+ 0x0003,0x381B,0xFF06,0x0002,0xFF06,0x0002,0x381C,0xFF06,
+ 0x0003,0x381C,0xFF06,0x0003,0x381C,0xFF06,0x0003,0x381C,
+ 0xFF06,0x0003,0x381C,0xFF06,0x0003,0x381C,0xFF06,0x0002,
+ 0xFF06,0x0002,0x381D,0xFF06,0x0003,0x381D,0xFF06,0x0003,
+ 0x381D,0xFF06,0x0003,0x381D,0xFF06,0x0003,0x381D,0xFF06,
+ 0x0003,0x381D,0xFF06,0x0002,0xFF06,0x0002,0x381E,0xFF06,
+ 0x0003,0x381E,0xFF06,0x0003,0x381E,0xFF06,0x0003,0x381E,
+ 0xFF06,0x0003,0x381E,0xFF06,0x0003,0x381E,0xFF06,0x0002,
+ 0xFF06,0x0002,0x381F,0xFF06,0x0003,0x381F,0xFF06,0x0003,
+ 0x381F,0xFF06,0x0003,0x381F,0xFF06,0x0003,0x381F,0xFF06,
+ 0x0003,0x381F,0xFF06,0x0002,0xFF06,0x0002,0x3820,0xFF06,
+ 0x0003,0x3820,0xFF06,0x0003,0x3820,0xFF06,0x0003,0x3820,
+
+ 0xFF06,0x0003,0x3820,0xFF06,0x0003,0x3820,0xFF06,0x0002,
+ 0xFF06,0x0002,0x3821,0xFF06,0x0003,0x3821,0xFF06,0x0003,
+ 0x3821,0xFF06,0x0003,0x3821,0xFF06,0x0003,0x3821,0xFF06,
+ 0x0003,0x3821,0xFF06,0x0002,0xFF06,0x005F,0xFF08,0xFF02,
+ 0x0003,0xFF03,0x0400,0xFF01,0x0100,0xFF06,0x01BF,0xFF06,
+ 0x00BF,0xFF05,0x0007,0x2C30,0xFF05,0x0007,0x2C30,0xFF05,
+ 0x0007,0x2C30,0xFF05,0x0007,0x2C30,0xFF05,0x000F,0x2C38,
+ 0xFF05,0x000F,0x2CA0,0xFF05,0x000F,0x2C48,0xFF05,0x000F,
+ 0x2CB0,0xFF05,0x000F,0x2C58,0xFF05,0x000F,0x2CC0,0xFF06,
+ 0x0002,0xFF04,0x0002,0xFF09,0x000B,0x2875,0xFF04,0x0000,
+ 0xFF05,0x000D,0x2868,0xFF06,0x0002,0xFF06,0x0002,0xFF04,
+ 0x0002,0xFF09,0x000B,0x2883,0xFF04,0x0000,0xFF05,0x000D,
+ 0x2876,0xFF06,0x0002,0xFF06,0x0002,0xFF04,0x0002,0xFF09,
+ 0x000B,0x2891,0xFF04,0x0000,0xFF05,0x000D,0x2884,0xFF06,
+ 0x0002,0xFF06,0x0002,0xFF04,0x0002,0xFF09,0x000B,0x289F,
+ 0xFF04,0x0000,0xFF05,0x000D,0x2892,0xFF06,0x0002,0xFF06,
+
+ 0x007F,0xFF00,0xFF08,0xFF02,0x0000,0xFF03,0x0200,0xFF01
+};
+static UINT16 bloodwar_mcu_4_1f[] = { // Warrior 5
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0200,0xFF01,0x0800,0xFF06,
+ 0x01BF,0xFF06,0x007F,0xFF06,0x0009,0xFF05,0x0002,0x2801,
+ 0xFF05,0x0004,0x3429,0xFF06,0x0000,0xFF05,0x0002,0x342E,
+ 0xFF05,0x0002,0x2815,0xFF06,0x0006,0xFF06,0x0009,0xFF05,
+ 0x0002,0x2804,0xFF05,0x0008,0x3431,0xFF05,0x0002,0x2818,
+ 0xFF06,0x0006,0xFF06,0x0009,0xFF05,0x0001,0x2807,0xFF06,
+ 0x0000,0xFF05,0x0008,0x343A,0xFF06,0x0000,0xFF05,0x0001,
+ 0x281B,0xFF06,0x0006,0xFF06,0x0009,0xFF05,0x0001,0x2809,
+ 0xFF06,0x0000,0xFF05,0x0004,0x3443,0xFF06,0x0000,0xFF05,
+ 0x0002,0x3448,0xFF06,0x0000,0xFF05,0x0001,0x281D,0xFF06,
+ 0x0006,0xFF06,0x0009,0xFF05,0x0001,0x280B,0xFF06,0x000A,
+ 0xFF05,0x0001,0x281F,0xFF06,0x0006,0xFF06,0x0009,0xFF05,
+ 0x0001,0x280D,0xFF06,0x000A,0xFF05,0x0001,0x2821,0xFF06,
+ 0x0006,0xFF06,0x0009,0xFF05,0x0001,0x280F,0xFF06,0x000A,
+ 0xFF05,0x0001,0x2823,0xFF06,0x0006,0xFF06,0x0009,0xFF05,
+ 0x0001,0x2811,0xFF06,0x000A,0xFF05,0x0001,0x2825,0xFF06,
+
+ 0x0006,0xFF06,0x0009,0xFF05,0x0001,0x2813,0xFF06,0x000A,
+ 0xFF05,0x0001,0x2827,0xFF06,0x0006,0xFF05,0x0007,0x2053,
+ 0xFF05,0x000F,0x204B,0xFF05,0x0007,0x204B,0xFF05,0x0007,
+ 0x2063,0xFF05,0x000F,0x205B,0xFF05,0x0007,0x205B,0xFF05,
+ 0x0007,0x2073,0xFF05,0x000F,0x206B,0xFF05,0x0007,0x206B,
+ 0xFF06,0x003F,0xFF08,0xFF02,0x0001,0xFF03,0x0200,0xFF01,
+ 0x0900,0xFF06,0x01BF,0xFF06,0x0001,0xFF05,0x000D,0x2801,
+ 0xFF05,0x000F,0x284A,0xFF06,0x0003,0xFF05,0x000B,0x280F,
+ 0xFF05,0x000D,0x285A,0xFF06,0x0001,0xFF06,0x0005,0xFF05,
+ 0x0009,0x281B,0xFF05,0x000C,0x2868,0xFF06,0x0002,0xFF06,
+ 0x0006,0xFF05,0x0008,0x2825,0xFF05,0x000A,0x2875,0xFF06,
+ 0x0004,0xFF06,0x0008,0xFF05,0x0006,0x282E,0xFF05,0x0009,
+ 0x2880,0xFF06,0x0005,0xFF06,0x0009,0xFF05,0x0005,0x2835,
+ 0xFF05,0x0006,0x288A,0xFF06,0x0008,0xFF06,0x000A,0xFF05,
+ 0x0004,0x283B,0xFF05,0x0005,0x2891,0xFF06,0x0009,0xFF06,
+ 0x000B,0xFF05,0x0003,0x2840,0xFF05,0x0005,0x2897,0xFF06,
+
+ 0x0009,0xFF06,0x000C,0xFF05,0x0002,0x2844,0xFF05,0x0004,
+ 0x289D,0xFF06,0x000A,0xFF06,0x000C,0x2847,0xFF06,0x0005,
+ 0x28A2,0xFF06,0x000A,0xFF06,0x000C,0x2848,0xFF06,0x0005,
+ 0x28A3,0xFF06,0x000A,0xFF06,0x000C,0x2849,0xFF06,0x0005,
+ 0x28A4,0xFF06,0x000A,0xFF06,0x005F,0xFF03,0x0300,0xFF06,
+ 0x0000,0xFF04,0x0002,0xFF09,0x000E,0x30B3,0xFF04,0x0000,
+ 0xFF05,0x000E,0x30A5,0xFF06,0x0000,0xFF04,0x0002,0xFF09,
+ 0x000F,0x30C3,0xFF04,0x0000,0xFF05,0x000F,0x30B4,0xFF04,
+ 0x0002,0xFF09,0x000F,0x30D3,0xFF04,0x0000,0xFF05,0x000F,
+ 0x30C4,0xFF08,0xFF02,0x0002,0xFF03,0x0200,0xFF01,0x0400,
+ 0xFF06,0x01BF,0xFF06,0x005F,0xFF06,0x0005,0xFF05,0x0001,
+ 0x25C6,0xFF06,0x0005,0xFF05,0x0003,0x2401,0xFF06,0x000D,
+ 0xFF06,0x0003,0xFF05,0x0003,0x25C8,0xFF05,0x000C,0x2405,
+ 0xFF06,0x0003,0xFF05,0x0002,0x25E4,0xFF06,0x0003,0xFF06,
+ 0x0003,0xFF05,0x0003,0x25CC,0xFF05,0x000F,0x2412,0xFF05,
+ 0x0003,0x25E7,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0003,
+
+ 0x25D0,0xFF05,0x000F,0x2422,0xFF05,0x0003,0x25EB,0xFF06,
+ 0x0003,0xFF06,0x0003,0xFF05,0x0003,0x25D4,0xFF05,0x000F,
+ 0x2432,0xFF05,0x0003,0x25EF,0xFF06,0x0003,0xFF06,0x0003,
+ 0xFF05,0x0003,0x25D8,0xFF05,0x000F,0x2442,0xFF05,0x0003,
+ 0x25F3,0xFF06,0x0003,0xFF06,0x0003,0xFF05,0x0003,0x25DC,
+ 0xFF05,0x000F,0x2452,0xFF05,0x0003,0x25F7,0xFF06,0x0003,
+ 0xFF06,0x0003,0xFF05,0x0003,0x25E0,0xFF05,0x000F,0x2462,
+ 0xFF05,0x0003,0x25FB,0xFF06,0x0003,0xFF06,0x005F,0xFF03,
+ 0x0400,0xFF06,0x0004,0xFF05,0x0002,0x3A01,0xFF06,0x0000,
+ 0xFF05,0x0001,0x3A07,0xFF06,0x0009,0xFF05,0x0001,0x3A0B,
+ 0xFF06,0x0000,0xFF05,0x0002,0x3A0F,0xFF06,0x0004,0xFF06,
+ 0x0004,0xFF05,0x0002,0x3A04,0xFF06,0x0000,0xFF05,0x0001,
+ 0x3A09,0xFF06,0x0009,0xFF05,0x0001,0x3A0D,0xFF06,0x0000,
+ 0xFF05,0x0002,0x3A12,0xFF06,0x0004,0xFF06,0x003F,0xFF08,
+ 0xFF02,0x0003,0xFF03,0x0200,0xFF01,0x0600,0xFF06,0x01BF,
+ 0xFF05,0x000F,0x3C6D,0xFF05,0x000F,0x3C6D,0xFF05,0x000F,
+
+ 0x3C7D,0xFF05,0x000F,0x3C7D,0xFF05,0x000F,0x3C8D,0xFF05,
+ 0x000F,0x3C8D,0xFF05,0x000F,0x3C6D,0xFF05,0x000F,0x3C6D,
+ 0xFF05,0x000F,0x3C7D,0xFF05,0x000F,0x3C7D,0xFF05,0x000F,
+ 0x3C8D,0xFF05,0x000F,0x3C8D,0xFF06,0x007F,0xFF03,0x0300,
+ 0xFF05,0x0007,0x2C28,0xFF05,0x000F,0x2C20,0xFF05,0x0007,
+ 0x2C20,0xFF05,0x0007,0x2C38,0xFF05,0x000F,0x2C30,0xFF05,
+ 0x0007,0x2C30,0xFF05,0x0007,0x2C48,0xFF05,0x000F,0x2C40,
+ 0xFF05,0x0007,0x2C40,0xFF05,0x0007,0x2C58,0xFF05,0x000F,
+ 0x2C50,0xFF05,0x0007,0x2C50,0xFF06,0x0003,0xFF05,0x0003,
+ 0x2C66,0xFF05,0x0004,0x2C60,0xFF06,0x0006,0xFF05,0x0003,
+ 0x2C66,0xFF05,0x0004,0x2C60,0xFF06,0x0002,0xFF06,0x0005,
+ 0xFF05,0x0001,0x2C6B,0x2C6A,0xFF06,0x000C,0xFF05,0x0001,
+ 0x2C6B,0x2C6A,0xFF06,0x0006,0xFF06,0x003F,0xFF00,0xFF08
+};
+static UINT16 bloodwar_mcu_4_20[] = { // Warrior 4
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x1100,0xFF06,
+ 0x01BF,0xFF06,0x00DF,0xFF06,0x0001,0xFF04,0x0002,0xFF09,
+ 0x0001,0x2402,0xFF04,0x0000,0xFF06,0x0017,0xFF05,0x0001,
+ 0x2401,0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x0004,0x2407,
+ 0xFF04,0x0000,0xFF06,0x0003,0xFF05,0x0001,0x3837,0xFF06,
+ 0x0009,0xFF04,0x0002,0xFF09,0x0001,0x3838,0xFF04,0x0000,
+ 0xFF06,0x0003,0xFF05,0x0004,0x2403,0xFF04,0x0002,0xFF09,
+ 0x0005,0x240D,0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0002,
+ 0x3839,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0002,0x383B,
+ 0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0005,0x2408,0xFF04,
+ 0x0002,0xFF09,0x0005,0x2415,0xFF04,0x0000,0xFF06,0x0002,
+ 0xFF05,0x0001,0x383C,0xFF06,0x0009,0xFF04,0x0002,0xFF09,
+ 0x0001,0x383D,0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0005,
+ 0x2410,0xFF04,0x0002,0xFF09,0x0006,0x241E,0xFF04,0x0000,
+ 0xFF06,0x0001,0xFF05,0x0001,0x383E,0xFF06,0x0009,0xFF04,
+ 0x0002,0xFF09,0x0001,0x383F,0xFF04,0x0000,0xFF06,0x0001,
+
+ 0xFF05,0x0006,0x2418,0xFF04,0x0002,0xFF09,0x0006,0x2427,
+ 0xFF04,0x0000,0xFF06,0x0002,0x3840,0xFF06,0x0009,0xFF04,
+ 0x0002,0x3840,0xFF04,0x0000,0xFF06,0x0002,0xFF05,0x0006,
+ 0x2421,0xFF04,0x0002,0xFF09,0x0006,0x2430,0xFF04,0x0000,
+ 0xFF06,0x0001,0xFF05,0x0002,0x3841,0xFF06,0x0007,0xFF04,
+ 0x0002,0xFF09,0x0002,0x3843,0xFF04,0x0000,0xFF06,0x0001,
+ 0xFF05,0x0006,0x242A,0xFF06,0x0000,0xFF04,0x0002,0xFF09,
+ 0x0001,0x2434,0xFF04,0x0000,0xFF06,0x0005,0xFF05,0x0002,
+ 0x3844,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0002,0x3846,
+ 0xFF04,0x0000,0xFF06,0x0005,0xFF05,0x0001,0x2433,0xFF06,
+ 0x0000,0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x1100,
+ 0xFF06,0x01BF,0xFF06,0x003F,0xFF06,0x0001,0xFF04,0x0002,
+ 0xFF09,0x000D,0x347C,0xFF04,0x0000,0xFF05,0x000D,0x346F,
+ 0xFF06,0x0001,0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x000D,
+ 0x348A,0xFF04,0x0000,0xFF05,0x000D,0x347D,0xFF06,0x0001,
+ 0xFF06,0x0000,0xFF04,0x0002,0xFF09,0x000E,0x3499,0xFF04,
+
+ 0x0000,0xFF05,0x000E,0x348B,0xFF06,0x0000,0xFF04,0x0002,
+ 0xFF09,0x000F,0x34A9,0xFF04,0x0000,0xFF05,0x000F,0x349A,
+ 0xFF04,0x0002,0xFF09,0x000F,0x34B9,0xFF04,0x0000,0xFF05,
+ 0x000F,0x34AA,0xFF06,0x0000,0xFF04,0x0002,0xFF09,0x000E,
+ 0x30C8,0xFF04,0x0000,0xFF05,0x000E,0x30BA,0xFF06,0x0000,
+ 0xFF04,0x0002,0xFF09,0x000F,0x30D8,0xFF04,0x0000,0xFF05,
+ 0x000F,0x30C9,0xFF04,0x0002,0xFF09,0x000C,0x30E5,0xFF04,
+ 0x0000,0xFF06,0x0005,0xFF05,0x000C,0x30D9,0xFF04,0x0002,
+ 0xFF09,0x000C,0x30F2,0xFF04,0x0000,0xFF06,0x0005,0xFF05,
+ 0x000C,0x30E6,0xFF04,0x0002,0xFF09,0x000C,0x30FF,0xFF04,
+ 0x0000,0xFF06,0x0005,0xFF05,0x000C,0x30F3,0xFF04,0x0002,
+ 0xFF09,0x000C,0x310D,0xFF04,0x0000,0xFF06,0x0005,0xFF05,
+ 0x000C,0x3101,0xFF04,0x0002,0xFF09,0x000C,0x311A,0xFF04,
+ 0x0000,0xFF06,0x0005,0xFF05,0x000C,0x310E,0xFF06,0x007F,
+ 0xFF08,0xFF02,0x0002,0xFF03,0x0400,0xFF01,0x0E00,0xFF06,
+ 0x01BF,0xFF06,0x00BF,0xFF06,0x000A,0xFF05,0x000B,0x2C01,
+
+ 0xFF06,0x0008,0xFF06,0x000A,0xFF05,0x000B,0x2C0D,0xFF06,
+ 0x0008,0xFF06,0x000A,0xFF05,0x000B,0x2C19,0xFF06,0x0008,
+ 0xFF06,0x000A,0xFF05,0x000B,0x2C25,0xFF06,0x0008,0xFF06,
+ 0x000A,0xFF05,0x000B,0x2C31,0xFF06,0x0008,0xFF06,0x000A,
+ 0xFF05,0x000B,0x2C3D,0xFF06,0x0008,0xFF06,0x000A,0xFF05,
+ 0x000B,0x2C49,0xFF06,0x0008,0xFF0A,0x000B,0x3C61,0xFF05,
+ 0x000B,0x2C55,0xFF0A,0x0007,0x3C61,0xFF04,0x0002,0xFF09,
+ 0x000D,0x3C79,0xFF04,0x0000,0xFF05,0x0001,0x3C62,0xFF05,
+ 0x000F,0x3C6A,0xFF04,0x0002,0xFF09,0x000D,0x3C89,0xFF04,
+ 0x0000,0xFF05,0x0001,0x3C64,0xFF05,0x000F,0x3C7A,0xFF04,
+ 0x0002,0xFF09,0x000D,0x3C99,0xFF04,0x0000,0xFF05,0x0001,
+ 0x3C66,0xFF05,0x000F,0x3C8A,0xFF04,0x0002,0xFF09,0x000D,
+ 0x3CA9,0xFF04,0x0000,0xFF05,0x0001,0x3C68,0xFF05,0x000F,
+ 0x3C9A,0xFF08,0xFF02,0x0003,0xFF03,0x0200,0xFF01,0x0E00,
+ 0xFF06,0x01BF,0xFF05,0x000F,0x20B0,0xFF05,0x000F,0x20B0,
+ 0xFF05,0x000F,0x20C0,0xFF05,0x000F,0x20C0,0xFF05,0x000F,
+
+ 0x20D0,0xFF05,0x000F,0x20D0,0xFF05,0x000F,0x20E0,0xFF05,
+ 0x000F,0x20E0,0xFF05,0x000F,0x20F0,0xFF05,0x000F,0x20F0,
+ 0xFF05,0x000F,0x2101,0xFF05,0x000F,0x2101,0xFF05,0x000F,
+ 0x2111,0xFF05,0x000F,0x2111,0xFF05,0x000F,0x2121,0xFF05,
+ 0x000F,0x2121,0xFF06,0x013F,0xFF00,0xFF08,0xFF02,0x0000
+};
+static UINT16 bloodwar_mcu_4_21[] = { // Warrior 6
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0F00,0xFF06,
+ 0x01BF,0xFF06,0x005F,0xFF06,0x000F,0x4401,0xFF06,0x000E,
+ 0xFF06,0x000C,0xFF05,0x0005,0x4402,0xFF06,0x000C,0xFF06,
+ 0x000C,0xFF05,0x0005,0x4408,0xFF06,0x000C,0xFF06,0x000C,
+ 0xFF05,0x0005,0x440E,0xFF06,0x000C,0xFF06,0x000C,0xFF05,
+ 0x0005,0x4414,0xFF06,0x000C,0xFF06,0x000C,0xFF05,0x0005,
+ 0x401A,0xFF06,0x000C,0xFF06,0x0008,0xFF05,0x0001,0x4901,
+ 0xFF06,0x0000,0xFF05,0x0007,0x4020,0xFF06,0x0000,0xFF04,
+ 0x0002,0xFF09,0x0001,0x4902,0xFF04,0x0000,0xFF06,0x0008,
+ 0xFF06,0x0007,0xFF05,0x0002,0x4903,0xFF06,0x0000,0xFF05,
+ 0x0007,0x4028,0xFF06,0x0000,0xFF04,0x0002,0xFF09,0x0002,
+ 0x4905,0xFF04,0x0000,0xFF06,0x0007,0xFF06,0x0007,0xFF05,
+ 0x0002,0x4906,0xFF06,0x0000,0xFF05,0x0007,0x3C30,0xFF06,
+ 0x0000,0xFF04,0x0002,0xFF09,0x0002,0x4908,0xFF04,0x0000,
+ 0xFF06,0x0007,0xFF06,0x0007,0xFF05,0x0002,0x4909,0xFF06,
+ 0x0000,0xFF05,0x0007,0x3C38,0xFF06,0x0000,0xFF04,0x0002,
+
+ 0xFF09,0x0002,0x490B,0xFF04,0x0000,0xFF06,0x0007,0xFF06,
+ 0x0007,0x490C,0xFF06,0x0000,0x490D,0xFF05,0x0009,0x3C40,
+ 0xFF04,0x0002,0x490D,0xFF06,0x0000,0x490C,0xFF04,0x0000,
+ 0xFF06,0x0007,0xFF06,0x0007,0x490E,0xFF06,0x0001,0xFF05,
+ 0x0009,0x3C4A,0xFF06,0x0001,0xFF04,0x0002,0x490E,0xFF04,
+ 0x0000,0xFF06,0x0007,0xFF06,0x0007,0x490F,0xFF06,0x0003,
+ 0xFF05,0x0005,0x3C54,0xFF06,0x0003,0xFF04,0x0002,0x490F,
+ 0xFF04,0x0000,0xFF06,0x0007,0xFF06,0x003F,0xFF08,0xFF02,
+ 0x0001,0xFF03,0x0300,0xFF01,0x0F00,0xFF06,0x01BF,0xFF06,
+ 0x007F,0xFF06,0x0001,0xFF05,0x0001,0x3870,0xFF06,0x0005,
+ 0xFF05,0x0001,0x3872,0xFF06,0x0007,0xFF05,0x0001,0x38CA,
+ 0xFF06,0x0005,0xFF04,0x0002,0xFF09,0x0001,0x3871,0xFF04,
+ 0x0000,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0002,0x3874,
+ 0xFF06,0x0000,0x3877,0xFF06,0x0001,0xFF05,0x0002,0x3878,
+ 0xFF06,0x0007,0xFF05,0x0002,0x38CC,0xFF06,0x0003,0xFF04,
+ 0x0002,0xFF09,0x0002,0x3876,0xFF04,0x0000,0xFF06,0x0001,
+
+ 0xFF06,0x0001,0xFF05,0x0005,0x387B,0xFF06,0x0000,0xFF05,
+ 0x0003,0x3881,0xFF06,0x0005,0xFF05,0x0003,0x38CF,0xFF06,
+ 0x0003,0xFF04,0x0002,0xFF09,0x0002,0x387D,0xFF04,0x0000,
+ 0xFF06,0x0001,0xFF06,0x0000,0xFF05,0x0006,0x3885,0xFF06,
+ 0x0000,0xFF05,0x0003,0x388C,0xFF06,0x0005,0xFF05,0x0007,
+ 0x38D3,0xFF04,0x0002,0xFF09,0x0003,0x3888,0xFF04,0x0000,
+ 0xFF06,0x0000,0xFF06,0x0000,0xFF05,0x0007,0x3890,0xFF06,
+ 0x0000,0xFF05,0x0002,0x3898,0xFF06,0x0005,0xFF05,0x0007,
+ 0x38DB,0xFF04,0x0002,0xFF09,0x0003,0x3893,0xFF04,0x0000,
+ 0xFF06,0x0000,0xFF06,0x0000,0xFF05,0x000B,0x389B,0xFF06,
+ 0x0005,0xFF05,0x0007,0x38E3,0xFF04,0x0002,0xFF09,0x0003,
+ 0x389E,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0xFF05,
+ 0x000B,0x38A7,0xFF06,0x0005,0xFF05,0x0007,0x38EB,0xFF04,
+ 0x0002,0xFF09,0x0003,0x38AA,0xFF04,0x0000,0xFF06,0x0000,
+ 0xFF06,0x0000,0xFF05,0x000B,0x38B3,0xFF06,0x0005,0xFF05,
+ 0x0007,0x38F3,0xFF04,0x0002,0xFF09,0x0003,0x38B6,0xFF04,
+
+ 0x0000,0xFF06,0x0000,0xFF06,0x0001,0xFF05,0x000A,0x38BF,
+ 0xFF06,0x0005,0xFF05,0x0004,0x38FB,0xFF05,0x0002,0x386D,
+ 0xFF04,0x0002,0xFF09,0x0002,0x38C1,0xFF04,0x0000,0xFF06,
+ 0x0001,0xFF06,0x009F,0xFF08,0xFF02,0x0002,0xFF03,0x0200,
+ 0xFF01,0x0C00,0xFF06,0x01BF,0xFF06,0x0001,0x2000,0xFF05,
+ 0x0001,0x2001,0x2400,0xFF05,0x0001,0x2590,0x2800,0xFF05,
+ 0x0001,0x29AC,0x2C00,0xFF05,0x0001,0x2DCB,0xFF06,0x0003,
+ 0xFF04,0x0002,0xFF09,0x0001,0x2002,0x2000,0xFF09,0x0001,
+ 0x2591,0x2400,0xFF09,0x0001,0x29AD,0x2800,0xFF09,0x0001,
+ 0x2DCC,0x2C00,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,
+ 0x2000,0xFF05,0x0001,0x2003,0xFF05,0x0002,0x2592,0xFF05,
+ 0x0002,0x29AE,0xFF05,0x0002,0x2DCD,0xFF06,0x0003,0xFF04,
+ 0x0002,0xFF09,0x0001,0x2004,0x2000,0xFF09,0x0002,0x2594,
+ 0xFF09,0x0002,0x29B0,0xFF09,0x0002,0x2DCF,0xFF04,0x0000,
+ 0xFF06,0x0001,0xFF06,0x0001,0x2000,0xFF05,0x0001,0x2005,
+ 0xFF05,0x0002,0x2595,0xFF05,0x0002,0x29B1,0xFF05,0x0002,
+
+ 0x2DD0,0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0001,0x2006,
+ 0x2000,0xFF09,0x0002,0x2597,0xFF09,0x0002,0x29B3,0xFF09,
+ 0x0002,0x2DD2,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,
+ 0x2000,0xFF05,0x0001,0x2007,0x2400,0xFF05,0x0001,0x2598,
+ 0xFF05,0x0002,0x29B4,0x2C00,0xFF05,0x0001,0x2DD3,0xFF06,
+ 0x0003,0xFF04,0x0002,0xFF09,0x0001,0x2008,0x2000,0xFF09,
+ 0x0001,0x2599,0x2400,0xFF09,0x0002,0x29B6,0xFF09,0x0001,
+ 0x2DD4,0x2C00,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,
+ 0x2000,0xFF05,0x0001,0x2009,0xFF05,0x0002,0x259A,0xFF05,
+ 0x0002,0x29B7,0x2C00,0xFF05,0x0001,0x2DD5,0xFF06,0x0003,
+ 0xFF04,0x0002,0xFF09,0x0001,0x200A,0x2000,0xFF09,0x0002,
+ 0x259C,0xFF09,0x0002,0x29B9,0xFF09,0x0001,0x2DD6,0x2C00,
+ 0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,0x2000,0xFF05,
+ 0x0001,0x200B,0xFF05,0x0002,0x259D,0xFF05,0x0002,0x29BA,
+ 0x2C00,0xFF05,0x0001,0x2DD7,0xFF06,0x0003,0xFF04,0x0002,
+ 0xFF09,0x0001,0x200C,0x2000,0xFF09,0x0002,0x259F,0xFF09,
+
+ 0x0002,0x29BC,0xFF09,0x0001,0x2DD8,0x2C00,0xFF04,0x0000,
+ 0xFF06,0x0001,0xFF06,0x0001,0x2000,0xFF05,0x0001,0x200D,
+ 0xFF05,0x0002,0x25A0,0xFF05,0x0002,0x29BD,0x2C00,0xFF05,
+ 0x0001,0x2DD9,0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0001,
+ 0x200E,0x2000,0xFF09,0x0002,0x25A2,0xFF09,0x0002,0x29BF,
+ 0xFF09,0x0001,0x2DDA,0x2C00,0xFF04,0x0000,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x0002,0x200F,0xFF05,0x0002,0x25A3,
+ 0xFF05,0x0002,0x29C0,0xFF05,0x0002,0x2DDB,0xFF06,0x0003,
+ 0xFF04,0x0002,0xFF09,0x0002,0x2011,0xFF09,0x0002,0x25A5,
+ 0xFF09,0x0002,0x29C2,0xFF09,0x0002,0x2DDD,0xFF04,0x0000,
+ 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0002,0x2012,0xFF05,
+ 0x0002,0x25A6,0xFF05,0x0002,0x29C3,0xFF05,0x0002,0x2DDE,
+ 0xFF06,0x0003,0xFF04,0x0002,0xFF09,0x0002,0x2014,0xFF09,
+ 0x0002,0x25A8,0xFF09,0x0002,0x29C5,0xFF09,0x0002,0x2DE0,
+ 0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0002,
+ 0x2015,0x25A9,0xFF0A,0x0001,0x2400,0xFF05,0x0002,0x29C6,
+
+ 0x2DE1,0xFF0A,0x0001,0x2C00,0xFF06,0x0003,0xFF04,0x0002,
+ 0xFF09,0x0002,0x2017,0xFF0A,0x0001,0x2400,0x25A9,0xFF09,
+ 0x0002,0x29C8,0xFF0A,0x0001,0x2C00,0x2DE1,0xFF04,0x0000,
+ 0xFF06,0x0001,0xFF06,0x0001,0x2018,0xFF0A,0x0001,0x2000,
+ 0x25AA,0xFF0A,0x0001,0x2400,0x29C9,0xFF0A,0x0001,0x2800,
+ 0x2DE2,0xFF0A,0x0001,0x2C00,0xFF06,0x0003,0xFF04,0x0002,
+ 0xFF0A,0x0001,0x2000,0x2018,0xFF0A,0x0001,0x2400,0x25AA,
+ 0xFF0A,0x0001,0x2800,0x29C9,0xFF0A,0x0001,0x2C00,0x2DE2,
+ 0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,0x2019,0xFF0A,
+ 0x0001,0x2000,0x25AB,0xFF0A,0x0001,0x2400,0x29CA,0xFF0A,
+ 0x0001,0x2800,0x2DE3,0xFF0A,0x0001,0x2C00,0xFF06,0x0003,
+ 0xFF04,0x0002,0xFF0A,0x0001,0x2000,0x2019,0xFF0A,0x0001,
+ 0x2400,0x25AB,0xFF0A,0x0001,0x2800,0x29CA,0xFF0A,0x0001,
+ 0x2C00,0x2DE3,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x001F,
+ 0xFF03,0x0400,0xFF06,0x000B,0xFF05,0x0001,0x3170,0xFF0A,
+ 0x0004,0x3172,0x3173,0xFF06,0x000B,0xFF06,0x000A,0xFF05,
+
+ 0x0009,0x3174,0xFF06,0x000A,0xFF06,0x000A,0xFF05,0x0009,
+ 0x317E,0xFF06,0x000A,0xFF06,0x003F,0xFF08,0xFF02,0x0003,
+ 0xFF03,0x0200,0xFF01,0x0C00,0xFF06,0x01BF,0xFF04,0x0002,
+ 0xFF09,0x000F,0x343F,0xFF04,0x0000,0xFF05,0x000F,0x3430,
+ 0xFF04,0x0002,0xFF09,0x000F,0x344F,0xFF04,0x0000,0xFF05,
+ 0x000F,0x3440,0xFF04,0x0002,0xFF09,0x000F,0x345F,0xFF04,
+ 0x0000,0xFF05,0x000F,0x3450,0xFF04,0x0002,0xFF0A,0x0001,
+ 0x3463,0x3471,0x3463,0xFF09,0x0002,0x346E,0xFF0A,0x0001,
+ 0x3463,0xFF09,0x0001,0x3469,0xFF0A,0x0001,0x3463,0xFF09,
+ 0x0002,0x3462,0xFF04,0x0000,0xFF05,0x0002,0x3460,0xFF0A,
+ 0x0001,0x3463,0xFF05,0x0001,0x3468,0xFF0A,0x0001,0x3463,
+ 0xFF05,0x0002,0x346C,0x3463,0x3471,0xFF0A,0x0001,0x3463,
+ 0xFF04,0x0002,0xFF0A,0x0001,0x3463,0x3472,0xFF0A,0x0002,
+ 0x3463,0x346F,0xFF0A,0x0002,0x3463,0x346A,0xFF0A,0x0001,
+ 0x3463,0xFF09,0x0001,0x3465,0xFF0A,0x0001,0x3463,0xFF04,
+ 0x0000,0xFF05,0x0001,0x3464,0xFF0A,0x0001,0x3463,0x346A,
+
+ 0xFF0A,0x0002,0x3463,0x346F,0xFF0A,0x0002,0x3463,0x3472,
+ 0xFF0A,0x0001,0x3463,0xFF04,0x0002,0xFF0A,0x0001,0x341D,
+ 0x3473,0xFF0A,0x0002,0x341D,0x3470,0xFF0A,0x0002,0x341D,
+ 0x346B,0xFF0A,0x0001,0x341D,0xFF09,0x0001,0x3467,0xFF0A,
+ 0x0001,0x341D,0xFF04,0x0000,0xFF05,0x0001,0x3466,0xFF0A,
+ 0x0001,0x341D,0x346B,0xFF0A,0x0002,0x341D,0x3470,0xFF0A,
+ 0x0002,0x341D,0x3473,0xFF0A,0x0001,0x341D,0xFF03,0x0300,
+ 0xFF05,0x000A,0x3474,0xFF06,0x0008,0xFF05,0x0004,0x34BB,
+ 0xFF04,0x0002,0xFF09,0x0006,0x347A,0xFF04,0x0000,0xFF05,
+ 0x000B,0x347F,0xFF06,0x0007,0xFF05,0x0004,0x34C0,0xFF04,
+ 0x0002,0xFF09,0x0006,0x3485,0xFF04,0x0000,0xFF05,0x000B,
+ 0x348B,0xFF06,0x0007,0xFF05,0x0004,0x34C5,0xFF04,0x0002,
+ 0xFF09,0x0006,0x3491,0xFF04,0x0000,0xFF05,0x000B,0x3497,
+ 0xFF06,0x0007,0xFF05,0x0004,0x34CA,0xFF04,0x0002,0xFF09,
+ 0x0006,0x349D,0xFF04,0x0000,0xFF05,0x000B,0x34A3,0xFF06,
+ 0x0006,0xFF05,0x0005,0x34CF,0xFF04,0x0002,0xFF09,0x0006,
+
+ 0x34A9,0xFF04,0x0000,0xFF05,0x000B,0x34AF,0xFF06,0x0006,
+ 0xFF05,0x0005,0x34D5,0xFF04,0x0002,0xFF09,0x0006,0x34B5,
+ 0xFF04,0x0000,0xFF0A,0x001F,0x301D,0xFF05,0x0003,0x30DB,
+ 0xFF05,0x0003,0x30DB,0xFF05,0x0003,0x30DB,0xFF05,0x0003,
+ 0x30DB,0xFF05,0x0003,0x30DB,0xFF05,0x0003,0x30DB,0xFF05,
+ 0x0003,0x30DB,0xFF05,0x0003,0x30DB,0xFF05,0x000F,0x3121,
+ 0xFF05,0x000F,0x30DF,0xFF05,0x000F,0x3131,0xFF05,0x000F,
+ 0x30EF,0xFF05,0x000F,0x3141,0xFF05,0x000F,0x3101,0xFF05,
+ 0x000F,0x3151,0xFF05,0x000F,0x3111,0xFF00,0xFF08,0xFF02
+};
+static UINT16 bloodwar_mcu_4_22[] = { // Warrior 1
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0300,0xFF01,0x0B00,0xFF06,
+ 0x01BF,0xFF06,0x0001,0x3401,0xFF06,0x0000,0xFF05,0x0002,
+ 0x3402,0xFF06,0x0010,0xFF05,0x0001,0x3440,0xFF06,0x0001,
+ 0xFF05,0x0001,0x345C,0xFF06,0x0001,0xFF06,0x0001,0x3405,
+ 0xFF06,0x0000,0xFF05,0x0002,0x3406,0xFF06,0x0000,0xFF05,
+ 0x0001,0x4880,0xFF06,0x000C,0x4882,0xFF05,0x0001,0x3442,
+ 0xFF06,0x0001,0xFF05,0x0001,0x345E,0xFF06,0x0001,0xFF06,
+ 0x0001,0x3409,0xFF06,0x0000,0xFF05,0x0002,0x340A,0xFF06,
+ 0x0000,0xFF05,0x000F,0x4883,0xFF05,0x0001,0x3444,0xFF06,
+ 0x0001,0xFF05,0x0001,0x3460,0xFF06,0x0001,0xFF06,0x0001,
+ 0x340D,0xFF06,0x0000,0xFF05,0x0002,0x340E,0xFF06,0x0000,
+ 0xFF05,0x000F,0x4893,0xFF05,0x0001,0x3446,0xFF06,0x0001,
+ 0xFF05,0x0001,0x3462,0xFF06,0x0001,0xFF06,0x0001,0x3411,
+ 0xFF06,0x0000,0xFF05,0x0002,0x3412,0xFF06,0x0002,0xFF05,
+ 0x0001,0x40A3,0x44A5,0xFF06,0x0001,0xFF05,0x0001,0x44A6,
+ 0xFF06,0x0001,0xFF05,0x0002,0x44A8,0xFF06,0x0001,0xFF05,
+
+ 0x0001,0x3448,0xFF06,0x0001,0xFF05,0x0001,0x3464,0xFF06,
+ 0x0001,0xFF06,0x0001,0x3415,0xFF06,0x0000,0xFF05,0x0002,
+ 0x3416,0xFF06,0x0000,0xFF05,0x0003,0x40AB,0xFF05,0x0009,
+ 0x44AF,0xFF05,0x0001,0x40B9,0xFF05,0x0001,0x344A,0xFF06,
+ 0x0001,0xFF05,0x0001,0x3466,0xFF06,0x0001,0xFF06,0x0001,
+ 0x3419,0xFF06,0x0000,0xFF05,0x0002,0x341A,0xFF06,0x0003,
+ 0xFF05,0x0001,0x44BB,0xFF06,0x0005,0xFF05,0x0001,0x44D0,
+ 0xFF06,0x0002,0xFF05,0x0001,0x344C,0xFF06,0x0001,0xFF05,
+ 0x0001,0x3468,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004,
+ 0x341D,0xFF06,0x0003,0xFF05,0x0001,0x44BD,0xFF06,0x0005,
+ 0xFF05,0x0001,0x44D2,0xFF06,0x0002,0xFF05,0x0001,0x344E,
+ 0xFF06,0x0001,0xFF05,0x0001,0x346A,0xFF06,0x0001,0xFF06,
+ 0x0001,0xFF05,0x0004,0x3422,0xFF06,0x0003,0xFF05,0x0001,
+ 0x44BF,0xFF06,0x0005,0xFF05,0x0001,0x44D4,0xFF06,0x0002,
+ 0xFF05,0x0001,0x3450,0xFF06,0x0001,0xFF05,0x0001,0x346C,
+ 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004,0x3427,0xFF06,
+
+ 0x0002,0xFF05,0x0002,0x44C1,0xFF06,0x0005,0xFF05,0x0002,
+ 0x44D6,0xFF06,0x0001,0xFF05,0x0001,0x3452,0xFF05,0x0001,
+ 0x3875,0xFF05,0x0001,0x346E,0xFF06,0x0001,0xFF06,0x0001,
+ 0xFF05,0x0004,0x342C,0xFF06,0x0002,0xFF05,0x0002,0x44C4,
+ 0xFF06,0x0005,0xFF05,0x0002,0x44D9,0xFF06,0x0001,0xFF05,
+ 0x0001,0x3454,0xFF05,0x0001,0x3877,0xFF05,0x0001,0x3470,
+ 0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004,0x3431,0xFF06,
+ 0x0002,0xFF05,0x0002,0x44C7,0xFF06,0x0005,0xFF05,0x0002,
+ 0x44DC,0xFF06,0x0001,0xFF05,0x0001,0x3456,0xFF05,0x0002,
+ 0x3879,0x3472,0xFF06,0x0001,0xFF06,0x0001,0xFF05,0x0004,
+ 0x3436,0xFF06,0x0002,0xFF05,0x0002,0x44CA,0xFF06,0x0005,
+ 0xFF05,0x0002,0x44DF,0xFF06,0x0001,0xFF05,0x0001,0x3458,
+ 0xFF05,0x0001,0x387C,0xFF06,0x0000,0x3473,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x0004,0x343B,0xFF06,0x0002,0xFF05,
+ 0x0002,0x44CD,0xFF06,0x0005,0xFF05,0x0002,0x44E2,0xFF06,
+ 0x0001,0xFF05,0x0001,0x345A,0xFF05,0x0001,0x387E,0xFF06,
+
+ 0x0000,0x3474,0xFF06,0x0001,0xFF05,0x0007,0x3CE5,0xFF04,
+ 0x0002,0xFF09,0x0007,0x3D08,0xFF04,0x0000,0xFF05,0x000F,
+ 0x3D01,0xFF05,0x0006,0x3CED,0xFF04,0x0002,0xFF09,0x0008,
+ 0x3D19,0xFF04,0x0000,0xFF05,0x000F,0x3D11,0xFF05,0x0005,
+ 0x3CF4,0xFF04,0x0002,0xFF09,0x0009,0x3D2A,0xFF04,0x0000,
+ 0xFF05,0x000F,0x3D21,0xFF05,0x0004,0x3CFA,0xFF04,0x0002,
+ 0xFF09,0x000A,0x3D3B,0xFF04,0x0000,0xFF05,0x000F,0x3D31,
+ 0xFF08,0xFF02,0x0001,0xFF03,0x0400,0xFF01,0x0C00,0xFF06,
+ 0x01BF,0xFF06,0x003F,0xFF06,0x000D,0xFF05,0x0003,0x2850,
+ 0xFF06,0x000D,0xFF06,0x000D,0xFF05,0x0003,0x2854,0xFF06,
+ 0x000D,0xFF06,0x000D,0xFF05,0x0002,0x2858,0xFF06,0x000E,
+ 0xFF06,0x000D,0xFF05,0x0002,0x285B,0xFF06,0x000E,0xFF03,
+ 0x0300,0xFF06,0x0011,0xFF05,0x0003,0x307A,0xFF06,0x0009,
+ 0xFF06,0x000D,0xFF05,0x0007,0x307E,0xFF06,0x0009,0xFF06,
+ 0x0004,0xFF05,0x0001,0x305E,0xFF06,0x0006,0xFF05,0x000B,
+ 0x3086,0xFF06,0x0005,0xFF06,0x0004,0xFF05,0x0002,0x3060,
+
+ 0xFF06,0x0005,0xFF05,0x000B,0x3092,0xFF06,0x0005,0xFF06,
+ 0x0004,0xFF05,0x0004,0x3063,0xFF06,0x0002,0xFF05,0x000D,
+ 0x309E,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0003,0x3068,
+ 0xFF06,0x0003,0xFF05,0x000C,0x30AB,0xFF06,0x0005,0xFF06,
+ 0x0004,0xFF05,0x0006,0x306C,0xFF05,0x000E,0x30B8,0xFF06,
+ 0x0004,0xFF06,0x0004,0xFF05,0x0006,0x3073,0xFF05,0x000E,
+ 0x30C7,0xFF06,0x0004,0xFF06,0x007F,0xFF08,0xFF02,0x0002,
+ 0xFF03,0x0200,0xFF01,0x0900,0xFF06,0x01BF,0xFF05,0x0006,
+ 0x2001,0xFF06,0x0000,0xFF05,0x0007,0x2008,0xFF05,0x0006,
+ 0x2001,0xFF06,0x0000,0xFF05,0x0007,0x2008,0xFF05,0x000F,
+ 0x2010,0xFF05,0x000F,0x2010,0xFF05,0x000F,0x2020,0xFF05,
+ 0x000F,0x2020,0xFF05,0x000F,0x2030,0xFF05,0x000F,0x2030,
+ 0xFF05,0x000F,0x2040,0xFF05,0x000F,0x2040,0xFF05,0x000F,
+ 0x2050,0xFF05,0x000F,0x2050,0xFF05,0x000F,0x2060,0xFF05,
+ 0x000F,0x2060,0xFF05,0x000F,0x2070,0xFF05,0x000F,0x2070,
+ 0xFF05,0x000F,0x2080,0xFF05,0x000F,0x2080,0xFF05,0x000D,
+
+ 0x2090,0xFF06,0x0000,0x209E,0xFF05,0x000D,0x2090,0xFF06,
+ 0x0000,0x209E,0x209F,0xFF06,0x0001,0xFF05,0x000A,0x20A0,
+ 0xFF06,0x0000,0x20AB,0x209F,0xFF06,0x0001,0xFF05,0x000A,
+ 0x20A0,0xFF06,0x0000,0x20AB,0x20AC,0xFF06,0x0001,0xFF05,
+ 0x000A,0x20AD,0xFF06,0x0000,0x20B8,0x20AC,0xFF06,0x0001,
+ 0xFF05,0x000A,0x20AD,0xFF06,0x0000,0x20B8,0x20B9,0xFF06,
+ 0x0001,0xFF05,0x000C,0x20BA,0x20B9,0xFF06,0x0001,0xFF05,
+ 0x000C,0x20BA,0xFF05,0x000F,0x20C7,0xFF05,0x000F,0x20C7,
+ 0xFF06,0x007F,0xFF08,0xFF02,0x0003,0xFF03,0x0200,0xFF01,
+ 0x0900,0xFF06,0x01BF,0xFF0A,0x0005,0x2501,0xFF05,0x0009,
+ 0x2501,0xFF05,0x0004,0x255B,0xFF0A,0x0004,0x2501,0xFF0A,
+ 0x0005,0x2501,0xFF05,0x0005,0x25A6,0xFF05,0x0009,0x250B,
+ 0xFF05,0x0005,0x2560,0xFF0A,0x0003,0x2501,0xFF05,0x0005,
+ 0x25A0,0xFF05,0x0005,0x25B2,0xFF05,0x0009,0x2515,0xFF05,
+ 0x0006,0x2566,0x2501,0xFF05,0x0001,0x256D,0xFF05,0x0005,
+ 0x25AC,0xFF05,0x0005,0x25BE,0xFF05,0x0009,0x251F,0xFF05,
+
+ 0x0009,0x256F,0xFF05,0x0005,0x25B8,0xFF05,0x0005,0x25CA,
+ 0xFF05,0x0009,0x2529,0xFF05,0x0009,0x2579,0xFF05,0x0005,
+ 0x25C4,0xFF05,0x0005,0x25D6,0xFF05,0x0009,0x2533,0xFF05,
+ 0x0009,0x2583,0xFF05,0x0005,0x25D0,0xFF05,0x0005,0x25E2,
+ 0xFF05,0x0009,0x253D,0xFF05,0x0009,0x258D,0xFF05,0x0005,
+ 0x25DC,0xFF05,0x0005,0x25EE,0xFF05,0x0009,0x2547,0xFF05,
+ 0x0002,0x2597,0xFF0A,0x0001,0x2501,0x259A,0xFF0A,0x0001,
+ 0x2501,0xFF05,0x0001,0x259B,0xFF05,0x0005,0x25E8,0xFF05,
+ 0x0005,0x25FA,0xFF05,0x0009,0x2551,0xFF0A,0x0009,0x2501,
+ 0xFF05,0x0005,0x25F4,0xFF03,0x0300,0xFF06,0x0006,0x2CE0,
+ 0xFF06,0x0002,0x2CE1,0xFF06,0x000A,0x2CE0,0xFF06,0x0002,
+ 0x2CE1,0xFF06,0x0003,0xFF06,0x0005,0xFF05,0x0006,0x2CE2,
+ 0xFF06,0x0008,0xFF05,0x0006,0x2CE2,0xFF06,0x0002,0xFF06,
+ 0x0005,0xFF05,0x0006,0x2CE9,0xFF06,0x0008,0xFF05,0x0006,
+ 0x2CE9,0xFF06,0x0002,0xFF06,0x0005,0xFF05,0x0006,0x2CF0,
+ 0xFF06,0x0008,0xFF05,0x0006,0x2CF0,0xFF06,0x0002,0xFF06,
+
+ 0x0005,0xFF05,0x0006,0x2CF7,0xFF06,0x0008,0xFF05,0x0006,
+ 0x2CF7,0xFF06,0x0002,0xFF06,0x007F,0xFF00,0xFF08,0xFF02
+};
+static UINT16 bloodwar_mcu_4_23[] = { // Warrior 9
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0A00,0xFF06,
+ 0x01BF,0xFF06,0x0006,0xFF05,0x0001,0x3C88,0xFF06,0x0005,
+ 0xFF05,0x0001,0x4001,0xFF06,0x0005,0xFF04,0x0002,0xFF09,
+ 0x0001,0x3C89,0xFF04,0x0000,0xFF06,0x0006,0xFF06,0x0006,
+ 0xFF05,0x0001,0x3C8A,0xFF06,0x0004,0xFF05,0x0002,0x4003,
+ 0xFF06,0x0005,0xFF04,0x0002,0xFF09,0x0001,0x3C8B,0xFF04,
+ 0x0000,0xFF06,0x0006,0xFF06,0x0001,0xFF05,0x0004,0x3032,
+ 0xFF05,0x0001,0x3C16,0xFF06,0x0004,0xFF05,0x0003,0x4006,
+ 0xFF06,0x0004,0xFF04,0x0002,0xFF09,0x0001,0x3C17,0xFF09,
+ 0x0004,0x3036,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0000,
+ 0xFF05,0x0005,0x3037,0xFF05,0x0001,0x3C18,0xFF06,0x0004,
+ 0xFF05,0x0003,0x400A,0xFF06,0x0004,0xFF04,0x0002,0xFF09,
+ 0x0001,0x3C19,0xFF09,0x0005,0x303C,0xFF04,0x0000,0xFF06,
+ 0x0000,0xFF06,0x0000,0xFF05,0x0005,0x303D,0xFF05,0x0001,
+ 0x3C1A,0xFF06,0x0004,0xFF05,0x0003,0x400E,0xFF06,0x0004,
+ 0xFF04,0x0002,0xFF09,0x0001,0x3C1B,0xFF09,0x0005,0x3042,
+
+ 0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0xFF05,0x0005,
+ 0x3043,0xFF05,0x0001,0x3C1C,0xFF06,0x0004,0xFF05,0x0003,
+ 0x4012,0xFF06,0x0004,0xFF04,0x0002,0xFF09,0x0001,0x3C1D,
+ 0xFF09,0x0005,0x3048,0xFF06,0x0000,0xFF04,0x0000,0xFF05,
+ 0x0006,0x3049,0xFF05,0x0001,0x3C1E,0xFF06,0x000D,0xFF04,
+ 0x0002,0xFF09,0x0001,0x3C1F,0xFF09,0x0006,0x304F,0xFF04,
+ 0x0000,0xFF05,0x0006,0x3050,0xFF05,0x0001,0x3C20,0xFF06,
+ 0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C21,0xFF09,0x0006,
+ 0x3056,0xFF04,0x0000,0xFF05,0x0006,0x3057,0xFF05,0x0001,
+ 0x3C22,0xFF06,0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C23,
+ 0xFF09,0x0006,0x305D,0xFF04,0x0000,0xFF05,0x0005,0x305E,
+ 0xFF06,0x0000,0xFF05,0x0001,0x3C24,0xFF06,0x000D,0xFF04,
+ 0x0002,0xFF09,0x0001,0x3C25,0xFF06,0x0000,0xFF09,0x0005,
+ 0x3063,0xFF04,0x0000,0xFF06,0x0000,0xFF05,0x0004,0x3064,
+ 0xFF06,0x0000,0xFF05,0x0001,0x3C26,0xFF06,0x000D,0xFF04,
+ 0x0002,0xFF09,0x0001,0x3C27,0xFF06,0x0000,0xFF09,0x0004,
+
+ 0x3068,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0xFF05,
+ 0x0004,0x3069,0xFF06,0x0000,0xFF05,0x0001,0x3C28,0xFF06,
+ 0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C29,0xFF06,0x0000,
+ 0xFF09,0x0004,0x306D,0xFF04,0x0000,0xFF06,0x0000,0xFF06,
+ 0x0000,0xFF05,0x0004,0x306E,0xFF06,0x0000,0xFF05,0x0001,
+ 0x3C2A,0xFF06,0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C2B,
+ 0xFF06,0x0000,0xFF09,0x0004,0x3072,0xFF04,0x0000,0xFF06,
+ 0x0000,0xFF06,0x0000,0xFF05,0x0004,0x3073,0xFF06,0x0000,
+ 0xFF05,0x0001,0x3C2C,0xFF06,0x000D,0xFF04,0x0002,0xFF09,
+ 0x0001,0x3C2D,0xFF06,0x0000,0xFF09,0x0004,0x3077,0xFF04,
+ 0x0000,0xFF06,0x0000,0xFF05,0x0005,0x3078,0xFF06,0x0000,
+ 0xFF05,0x0001,0x3C2E,0xFF06,0x000D,0xFF04,0x0002,0xFF09,
+ 0x0001,0x3C2F,0xFF06,0x0000,0xFF09,0x0005,0x307D,0xFF04,
+ 0x0000,0xFF05,0x0005,0x307E,0xFF06,0x0000,0xFF05,0x0001,
+ 0x3C30,0xFF06,0x000D,0xFF04,0x0002,0xFF09,0x0001,0x3C31,
+ 0xFF06,0x0000,0xFF09,0x0005,0x3083,0xFF04,0x0000,0xFF06,
+
+ 0x003F,0xFF08,0xFF02,0x0001,0xFF03,0x0200,0xFF01,0x0A00,
+ 0xFF06,0x01BF,0xFF06,0x0009,0xFF05,0x0001,0x3C8C,0xFF06,
+ 0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3C8D,0xFF04,0x0000,
+ 0xFF06,0x0009,0xFF06,0x0001,0xFF05,0x0002,0x40A0,0xFF06,
+ 0x0004,0xFF05,0x0001,0x3C8E,0xFF06,0x0002,0xFF05,0x0001,
+ 0x4090,0xFF06,0x0002,0xFF04,0x0002,0xFF09,0x0001,0x3C8F,
+ 0xFF06,0x0004,0xFF09,0x0002,0x40A2,0xFF04,0x0000,0xFF06,
+ 0x0001,0xFF06,0x0001,0xFF05,0x0002,0x40A3,0xFF06,0x0000,
+ 0xFF05,0x0003,0x34C7,0xFF05,0x0001,0x3CAF,0xFF06,0x0001,
+ 0xFF05,0x0003,0x4092,0xFF06,0x0001,0xFF04,0x0002,0xFF09,
+ 0x0001,0x3CB0,0xFF09,0x0003,0x34CA,0xFF06,0x0000,0xFF09,
+ 0x0002,0x40A5,0xFF04,0x0000,0xFF06,0x0001,0xFF06,0x0001,
+ 0xFF05,0x0002,0x40A6,0xFF05,0x0004,0x34CB,0xFF05,0x0001,
+ 0x3CB1,0xFF06,0x0002,0xFF05,0x0001,0x4096,0xFF06,0x0002,
+ 0xFF04,0x0002,0xFF09,0x0001,0x3CB2,0xFF09,0x0004,0x34CF,
+ 0xFF09,0x0002,0x40A8,0xFF04,0x0000,0xFF06,0x0001,0xFF06,
+
+ 0x0001,0xFF05,0x0002,0x40A9,0xFF05,0x0004,0x34D0,0xFF05,
+ 0x0001,0x3CB3,0xFF06,0x0001,0xFF05,0x0003,0x4098,0xFF06,
+ 0x0001,0xFF04,0x0002,0xFF09,0x0001,0x3CB4,0xFF09,0x0004,
+ 0x34D4,0xFF09,0x0002,0x40AB,0xFF04,0x0000,0xFF06,0x0001,
+ 0xFF06,0x0001,0xFF05,0x0002,0x40AC,0xFF05,0x0004,0x34D5,
+ 0xFF05,0x0001,0x3CB5,0xFF06,0x0001,0xFF05,0x0003,0x409C,
+ 0xFF06,0x0001,0xFF04,0x0002,0xFF09,0x0001,0x3CB6,0xFF09,
+ 0x0004,0x34D9,0xFF09,0x0002,0x40AE,0xFF04,0x0000,0xFF06,
+ 0x0001,0xFF06,0x0004,0xFF05,0x0004,0x34DA,0xFF05,0x0001,
+ 0x3CB7,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CB8,
+ 0xFF09,0x0004,0x34DE,0xFF04,0x0000,0xFF06,0x0004,0xFF06,
+ 0x0004,0xFF05,0x0004,0x34DF,0xFF05,0x0001,0x3CB9,0xFF06,
+ 0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CBA,0xFF09,0x0004,
+ 0x34E3,0xFF04,0x0000,0xFF06,0x0004,0xFF06,0x0004,0xFF05,
+ 0x0004,0x34E4,0xFF05,0x0001,0x3CBB,0xFF06,0x0007,0xFF04,
+ 0x0002,0xFF09,0x0001,0x3CBC,0xFF09,0x0004,0x34E8,0xFF04,
+
+ 0x0000,0xFF06,0x0004,0xFF06,0x0004,0xFF05,0x0004,0x34E9,
+ 0xFF05,0x0001,0x3CBD,0xFF06,0x0007,0xFF04,0x0002,0xFF09,
+ 0x0001,0x3CBE,0xFF09,0x0004,0x34ED,0xFF04,0x0000,0xFF06,
+ 0x0004,0xFF06,0x0004,0xFF05,0x0004,0x34EE,0xFF05,0x0001,
+ 0x3CBF,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC0,
+ 0xFF09,0x0004,0x34F2,0xFF04,0x0000,0xFF06,0x0004,0xFF06,
+ 0x0005,0xFF05,0x0002,0x34F3,0xFF06,0x0000,0xFF05,0x0001,
+ 0x3CC1,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC2,
+ 0xFF06,0x0000,0xFF09,0x0002,0x34F5,0xFF04,0x0000,0xFF06,
+ 0x0005,0xFF06,0x0004,0xFF05,0x0004,0x34F6,0xFF05,0x0001,
+ 0x3CC3,0xFF06,0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC4,
+ 0xFF09,0x0004,0x34FA,0xFF04,0x0000,0xFF06,0x0004,0xFF06,
+ 0x0004,0xFF05,0x0004,0x34FB,0xFF05,0x0001,0x3CC5,0xFF06,
+ 0x0007,0xFF04,0x0002,0xFF09,0x0001,0x3CC6,0xFF09,0x0004,
+ 0x34FF,0xFF04,0x0000,0xFF06,0x0004,0xFF06,0x007F,0xFF08,
+ 0xFF02,0x0002,0xFF03,0x0200,0xFF01,0x0700,0xFF06,0x01BF,
+
+ 0xFF05,0x000F,0x3C01,0xFF04,0x0002,0xFF09,0x000F,0x3C10,
+ 0xFF04,0x0000,0xFF06,0x0003,0xFF05,0x000B,0x3C11,0xFF04,
+ 0x0002,0xFF09,0x000B,0x3C1C,0xFF04,0x0000,0xFF06,0x0003,
+ 0xFF06,0x0006,0xFF05,0x0001,0x401D,0xFF06,0x0000,0xFF05,
+ 0x0002,0x3835,0x3C23,0xFF06,0x0000,0xFF05,0x0001,0x401D,
+ 0xFF06,0x0000,0xFF04,0x0002,0x3C23,0xFF09,0x0002,0x3837,
+ 0xFF06,0x0000,0xFF09,0x0001,0x401E,0xFF04,0x0000,0xFF06,
+ 0x0006,0xFF06,0x0006,0xFF05,0x0001,0x401F,0xFF05,0x0003,
+ 0x3838,0x3C24,0xFF06,0x0000,0xFF05,0x0001,0x401F,0xFF06,
+ 0x0000,0xFF04,0x0002,0x3C24,0xFF09,0x0003,0x383B,0xFF09,
+ 0x0001,0x4020,0xFF04,0x0000,0xFF06,0x0006,0xFF06,0x0006,
+ 0xFF05,0x0001,0x4021,0xFF05,0x0003,0x383C,0x3C25,0xFF06,
+ 0x0000,0xFF05,0x0001,0x4021,0xFF06,0x0000,0xFF04,0x0002,
+ 0x3C25,0xFF09,0x0003,0x383F,0xFF09,0x0001,0x4022,0xFF04,
+ 0x0000,0xFF06,0x0006,0xFF06,0x0008,0xFF05,0x0003,0x3840,
+ 0x3C26,0xFF06,0x0003,0xFF04,0x0002,0x3C26,0xFF09,0x0003,
+
+ 0x3843,0xFF04,0x0000,0xFF06,0x0008,0xFF06,0x0008,0xFF05,
+ 0x0003,0x3844,0x3C27,0xFF06,0x0003,0xFF04,0x0002,0x3C27,
+ 0xFF09,0x0003,0x3847,0xFF04,0x0000,0xFF06,0x0008,0xFF06,
+ 0x0008,0xFF05,0x0003,0x3848,0x3C28,0xFF06,0x0003,0xFF04,
+ 0x0002,0x3C28,0xFF09,0x0003,0x384B,0xFF04,0x0000,0xFF06,
+ 0x0008,0xFF06,0x0008,0xFF05,0x0003,0x384C,0x3C29,0xFF06,
+ 0x0003,0xFF04,0x0002,0x3C29,0xFF09,0x0003,0x384F,0xFF04,
+ 0x0000,0xFF06,0x0008,0xFF06,0x0008,0xFF05,0x0003,0x3850,
+ 0x3C2A,0xFF06,0x0003,0xFF04,0x0002,0x3C2A,0xFF09,0x0003,
+ 0x3853,0xFF04,0x0000,0xFF06,0x0008,0xFF06,0x0008,0xFF05,
+ 0x0003,0x3854,0x3C2B,0xFF05,0x0003,0x442D,0xFF04,0x0002,
+ 0x3C2B,0xFF09,0x0003,0x3857,0xFF04,0x0000,0xFF06,0x0008,
+ 0xFF06,0x0008,0xFF05,0x0003,0x3858,0x3C2C,0xFF05,0x0003,
+ 0x4431,0xFF04,0x0002,0x3C2C,0xFF09,0x0003,0x385B,0xFF04,
+ 0x0000,0xFF06,0x0008,0xFF06,0x0003,0xFF05,0x0017,0x485C,
+ 0xFF06,0x0003,0xFF05,0x001F,0x4874,0xFF05,0x001F,0x4894,
+
+ 0xFF05,0x001F,0x48B4,0xFF05,0x001F,0x48D4,0xFF05,0x000B,
+ 0x48F4,0xFF05,0x0013,0x4901,0xFF08,0xFF02,0x0003,0xFF03,
+ 0x0200,0xFF01,0x0800,0xFF06,0x01BF,0xFF05,0x0007,0x2820,
+ 0xFF05,0x0007,0x2820,0xFF05,0x0007,0x2820,0xFF05,0x0007,
+ 0x2820,0xFF05,0x0007,0x2828,0xFF05,0x0007,0x2828,0xFF05,
+ 0x0007,0x2828,0xFF05,0x0007,0x2828,0xFF05,0x0007,0x2830,
+ 0xFF05,0x0007,0x2830,0xFF05,0x0007,0x2830,0xFF05,0x0007,
+ 0x2830,0xFF05,0x0007,0x2438,0xFF05,0x0007,0x2438,0xFF05,
+ 0x0007,0x2438,0xFF05,0x0007,0x2438,0xFF05,0x0007,0x2040,
+ 0xFF05,0x0007,0x2040,0xFF05,0x0007,0x2040,0xFF05,0x0007,
+ 0x2040,0xFF05,0x0007,0x2048,0xFF05,0x0007,0x2048,0xFF05,
+ 0x0007,0x2048,0xFF05,0x0007,0x2048,0xFF0A,0x001F,0x2C50,
+ 0xFF05,0x0007,0x2051,0xFF05,0x0007,0x2051,0xFF05,0x0007,
+ 0x2051,0xFF05,0x0007,0x2051,0xFF05,0x0007,0x2059,0xFF05,
+ 0x0007,0x2059,0xFF05,0x0007,0x2059,0xFF05,0x0007,0x2059,
+ 0xFF05,0x0007,0x2461,0xFF05,0x0007,0x2461,0xFF05,0x0007,
+
+ 0x2461,0xFF05,0x0007,0x2461,0xFF05,0x0007,0x2869,0xFF05,
+ 0x0007,0x2869,0xFF05,0x0007,0x2869,0xFF05,0x0007,0x2869,
+ 0xFF05,0x0007,0x2871,0xFF05,0x0007,0x2871,0xFF05,0x0007,
+ 0x2871,0xFF05,0x0007,0x2871,0xFF05,0x0007,0x2879,0xFF05,
+ 0x0007,0x2879,0xFF05,0x0007,0x2879,0xFF05,0x0007,0x2879,
+ 0xFF05,0x0007,0x2881,0xFF05,0x0007,0x2881,0xFF05,0x0007,
+ 0x2881,0xFF05,0x0007,0x2881,0xFF06,0x007F,0xFF00,0xFF08
+};
+static UINT16 bloodwar_mcu_4_24[] = { // Warrior 7
+ 0xFF08,0xFF02,0x0000,0xFF03,0x0400,0xFF01,0x0300,0xFF06,
+ 0x01BF,0xFF06,0x0000,0x3402,0xFF05,0x0005,0x4C14,0x3402,
+ 0xFF05,0x0006,0x4C14,0xFF05,0x0006,0x4C14,0xFF04,0x0002,
+ 0x3402,0xFF04,0x0000,0xFF05,0x0005,0x4C14,0xFF04,0x0002,
+ 0x3402,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3403,
+ 0xFF05,0x0005,0x4C1B,0x3403,0xFF05,0x0002,0x4C1B,0xFF05,
+ 0x0007,0x4B32,0xFF05,0x0002,0x4C1F,0xFF04,0x0002,0x3403,
+ 0xFF04,0x0000,0xFF05,0x0005,0x4C1B,0xFF04,0x0002,0x3403,
+ 0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3404,0xFF05,
+ 0x0005,0x4C22,0x3404,0xFF05,0x0002,0x4C22,0xFF05,0x0007,
+ 0x4B3A,0xFF05,0x0002,0x4C26,0xFF04,0x0002,0x3404,0xFF04,
+ 0x0000,0xFF05,0x0005,0x4C22,0xFF04,0x0002,0x3404,0xFF04,
+ 0x0000,0xFF06,0x0000,0xFF05,0x0007,0x340C,0xFF05,0x0007,
+ 0x340C,0xFF05,0x0007,0x340C,0xFF05,0x0007,0x340C,0xFF06,
+ 0x0000,0x3401,0xFF05,0x0006,0x2029,0xFF05,0x000D,0x207E,
+ 0xFF05,0x0006,0x2029,0xFF04,0x0002,0x3401,0xFF04,0x0000,
+
+ 0xFF06,0x0000,0xFF06,0x0000,0x3402,0xFF05,0x0006,0x2030,
+ 0xFF05,0x000D,0x208C,0xFF05,0x0006,0x2030,0xFF04,0x0002,
+ 0x3402,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3403,
+ 0xFF05,0x0006,0x2037,0xFF05,0x000D,0x209A,0xFF05,0x0006,
+ 0x2037,0xFF04,0x0002,0x3403,0xFF04,0x0000,0xFF06,0x0000,
+ 0xFF06,0x0000,0x3404,0xFF05,0x0006,0x203E,0xFF05,0x000D,
+ 0x20A8,0xFF05,0x0006,0x203E,0xFF04,0x0002,0x3404,0xFF04,
+ 0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3405,0xFF05,0x0006,
+ 0x2045,0xFF05,0x000D,0x20B6,0xFF05,0x0006,0x2045,0xFF04,
+ 0x0002,0x3405,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,
+ 0x3406,0xFF05,0x0001,0x2076,0xFF05,0x0004,0x204E,0xFF05,
+ 0x000D,0x20C4,0xFF05,0x0004,0x204C,0xFF05,0x0001,0x207A,
+ 0xFF04,0x0002,0x3406,0xFF04,0x0000,0xFF06,0x0000,0xFF06,
+ 0x0000,0x3407,0xFF05,0x0001,0x2078,0xFF05,0x0004,0x2055,
+ 0xFF05,0x000D,0x20D2,0xFF05,0x0004,0x2053,0xFF05,0x0001,
+ 0x207C,0xFF04,0x0002,0x3407,0xFF04,0x0000,0xFF06,0x0000,
+
+ 0xFF06,0x0000,0x3408,0xFF05,0x0006,0x205A,0xFF05,0x000D,
+ 0x20E0,0xFF05,0x0006,0x205A,0xFF04,0x0002,0x3408,0xFF04,
+ 0x0000,0xFF06,0x0000,0xFF06,0x0000,0x3409,0xFF05,0x0006,
+ 0x2061,0xFF05,0x000D,0x20EE,0xFF05,0x0006,0x2061,0xFF04,
+ 0x0002,0x3409,0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x0000,
+ 0x340A,0xFF05,0x0006,0x2068,0xFF05,0x000D,0x2101,0xFF05,
+ 0x0006,0x2068,0xFF04,0x0002,0x340A,0xFF04,0x0000,0xFF06,
+ 0x0000,0xFF06,0x0000,0x340B,0xFF05,0x0006,0x206F,0xFF05,
+ 0x000D,0x210F,0xFF05,0x0006,0x206F,0xFF04,0x0002,0x340B,
+ 0xFF04,0x0000,0xFF06,0x0000,0xFF06,0x005F,0xFF08,0xFF02,
+ 0x0001,0xFF03,0x0200,0xFF01,0x0600,0xFF06,0x01BF,0xFF06,
+ 0x007F,0xFF05,0x001F,0x34D0,0xFF06,0x0003,0x34F0,0xFF05,
+ 0x0004,0x2507,0xFF05,0x000B,0x2501,0xFF05,0x0004,0x2502,
+ 0xFF04,0x0002,0x34F0,0xFF04,0x0000,0xFF06,0x0003,0xFF06,
+ 0x0003,0x34F1,0xFF05,0x0004,0x2513,0xFF05,0x000B,0x250D,
+ 0xFF05,0x0004,0x250E,0xFF04,0x0002,0x34F1,0xFF04,0x0000,
+
+ 0xFF06,0x0003,0xFF06,0x0003,0x34F2,0xFF05,0x0004,0x251F,
+ 0xFF05,0x000B,0x2519,0xFF05,0x0004,0x251A,0xFF04,0x0002,
+ 0x34F2,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0x34F3,
+ 0xFF05,0x0004,0x252B,0xFF05,0x000B,0x2525,0xFF05,0x0004,
+ 0x2526,0xFF04,0x0002,0x34F3,0xFF04,0x0000,0xFF06,0x0003,
+ 0xFF06,0x0003,0x34F4,0xFF05,0x0004,0x2537,0xFF05,0x000B,
+ 0x2531,0xFF05,0x0004,0x2532,0xFF04,0x0002,0x34F4,0xFF04,
+ 0x0000,0xFF06,0x0003,0xFF06,0x0003,0x34F5,0xFF05,0x0004,
+ 0x2543,0xFF05,0x000B,0x253D,0xFF05,0x0004,0x253E,0xFF04,
+ 0x0002,0x34F5,0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,
+ 0x34F6,0xFF05,0x0004,0x254F,0xFF05,0x000B,0x2549,0xFF05,
+ 0x0004,0x254A,0xFF04,0x0002,0x34F6,0xFF04,0x0000,0xFF06,
+ 0x0003,0xFF06,0x0003,0x34F7,0xFF05,0x0004,0x255B,0xFF05,
+ 0x000B,0x2555,0xFF05,0x0004,0x2556,0xFF04,0x0002,0x34F7,
+ 0xFF04,0x0000,0xFF06,0x0003,0xFF06,0x0003,0x34F8,0xFF05,
+ 0x0004,0x2567,0xFF05,0x000B,0x2561,0xFF05,0x0004,0x2562,
+
+ 0xFF04,0x0002,0x34F8,0xFF04,0x0000,0xFF06,0x0003,0xFF06,
+ 0x007F,0xFF08,0xFF02,0x0002,0xFF03,0x0200,0xFF01,0x0200,
+ 0xFF06,0x01BF,0xFF06,0x009F,0xFF05,0x001F,0x3408,0xFF06,
+ 0x0002,0xFF05,0x0003,0x2830,0x3401,0xFF05,0x0003,0x2830,
+ 0xFF05,0x0007,0x2C28,0xFF05,0x0003,0x2830,0xFF04,0x0002,
+ 0x3401,0xFF04,0x0000,0xFF05,0x0003,0x2830,0xFF06,0x0002,
+ 0xFF06,0x0002,0xFF05,0x0003,0x283C,0x3402,0xFF05,0x0003,
+ 0x283C,0xFF05,0x0007,0x2C34,0xFF05,0x0003,0x283C,0xFF04,
+ 0x0002,0x3402,0xFF04,0x0000,0xFF05,0x0003,0x283C,0xFF06,
+ 0x0002,0xFF06,0x0002,0xFF05,0x0003,0x2848,0x3403,0xFF05,
+ 0x0003,0x2848,0xFF05,0x0007,0x2C40,0xFF05,0x0003,0x2848,
+ 0xFF04,0x0002,0x3403,0xFF04,0x0000,0xFF05,0x0003,0x2848,
+ 0xFF06,0x0002,0xFF06,0x0002,0xFF05,0x0003,0x2854,0x3404,
+ 0xFF05,0x0003,0x2854,0xFF05,0x0007,0x2C4C,0xFF05,0x0003,
+ 0x2854,0xFF04,0x0002,0x3404,0xFF04,0x0000,0xFF05,0x0003,
+ 0x2854,0xFF06,0x0002,0xFF06,0x0002,0xFF05,0x0003,0x2860,
+
+ 0x3405,0xFF05,0x0003,0x2860,0xFF05,0x0007,0x2C58,0xFF05,
+ 0x0003,0x2860,0xFF04,0x0002,0x3405,0xFF04,0x0000,0xFF05,
+ 0x0003,0x2860,0xFF06,0x0002,0xFF06,0x0002,0xFF05,0x0003,
+ 0x286C,0x3406,0xFF05,0x0003,0x286C,0xFF05,0x0007,0x2C64,
+ 0xFF05,0x0003,0x286C,0xFF04,0x0002,0x3406,0xFF04,0x0000,
+ 0xFF05,0x0003,0x286C,0xFF06,0x0002,0xFF06,0x0002,0xFF05,
+ 0x0003,0x2878,0x3407,0xFF05,0x0003,0x2878,0xFF05,0x0007,
+ 0x2C70,0xFF05,0x0003,0x2878,0xFF04,0x0002,0x3407,0xFF04,
+ 0x0000,0xFF05,0x0003,0x2878,0xFF06,0x0002,0xFF06,0x009F,
+ 0xFF08,0xFF02,0x0003,0xFF03,0x0200,0xFF01,0x0200,0xFF06,
+ 0x01BF,0xFF06,0x00BF,0xFF06,0x0005,0xFF05,0x0004,0x3480,
+ 0xFF05,0x0004,0x3480,0xFF05,0x0004,0x3480,0xFF05,0x0004,
+ 0x3480,0xFF06,0x0005,0xFF06,0x0005,0xFF05,0x0013,0x3085,
+ 0xFF06,0x0005,0xFF06,0x0005,0xFF05,0x0013,0x3099,0xFF06,
+ 0x0005,0xFF06,0x0005,0xFF05,0x0013,0x30AD,0xFF06,0x0005,
+ 0xFF06,0x0005,0xFF05,0x0013,0x30C1,0xFF06,0x0005,0xFF06,
+
+ 0x0005,0xFF05,0x0013,0x30D5,0xFF06,0x0005,0xFF05,0x000F,
+ 0x44E9,0xFF04,0x0002,0xFF09,0x000F,0x44F8,0xFF04,0x0000,
+ 0xFF05,0x000F,0x4101,0xFF04,0x0002,0xFF09,0x000F,0x4110,
+ 0xFF04,0x0000,0xFF05,0x000F,0x3D11,0xFF04,0x0002,0xFF09,
+ 0x000F,0x3D20,0xFF04,0x0000,0xFF05,0x000F,0x3921,0xFF04,
+ 0x0002,0xFF09,0x000F,0x3930,0xFF04,0x0000,0xFF05,0x000F,
+ 0x3931,0xFF04,0x0002,0xFF09,0x000F,0x3940,0xFF04,0x0000,
+ 0xFF05,0x000F,0x3941,0xFF04,0x0002,0xFF09,0x000F,0x3950,
+ 0xFF04,0x0000,0xFF00,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
+};
+
+// --- fighter data: pointers to ROM ---
+static UINT16 bloodwar_mcu_4_25[] = { // Warrior 1
+ 0x0007,0x2B72,0x0007,0x2B9E,0x0007,0x2C52,0x0007,0x2D36,
+ 0x0007,0x3584,0x0007,0x2E3A,0x0007,0x2E54,0x0007,0x2E74,
+ 0x0007,0x2F28,0x0007,0x3022,0x0007,0x35A0,0x0007,0x377C,
+ 0x0007,0x378E,0x0007,0x37C0,0x0007,0x37F2,0x0007,0x385C,
+ 0x0007,0x386E,0x0007,0x38A0,0x0007,0x38D2,0x0007,0x3824,
+ 0x0007,0x3832,0x0007,0x3840,0x0007,0x384E,0x0007,0x3904,
+ 0x0007,0x3912,0x0007,0x3920,0x0007,0x392E,0x0007,0x30F6,
+ 0x0007,0x3110,0x0007,0x3142,0x0007,0x31BA,0x0007,0x3232,
+ 0x0007,0x32AC,0x0007,0x32DE,0x0007,0x3356,0x0007,0x33CE,
+ 0x0007,0x35BC,0x0007,0x35CE,0x0007,0x3600,0x0007,0x3632,
+ 0x0007,0x369C,0x0007,0x36AE,0x0007,0x36E0,0x0007,0x3712,
+ 0x0007,0x3664,0x0007,0x3672,0x0007,0x3680,0x0007,0x368E,
+ 0x0007,0x3744,0x0007,0x3752,0x0007,0x3760,0x0007,0x376E,
+ 0x0007,0x3446,0x0007,0x34A4,0x0007,0x3514,0x0007,0x345A,
+ 0x0007,0x34B8,0x0007,0x3528,0x0007,0x3490,0x0007,0x3500,
+ 0x0007,0x3570,0x0007,0x3A18,0x0007,0x3A48,0x0007,0x3A9C,
+
+ 0x0007,0x3AF0,0x0007,0x3B44,0x0007,0x3BB0,0x0007,0x3C64,
+ 0x0007,0x3D18,0x0007,0x3DCC,0x0007,0x3E20,0x0007,0x3E98,
+ 0x0007,0x3F10,0x0007,0x3F88,0x0007,0x3FD6,0x0007,0x4072,
+ 0x0007,0x410E,0x0007,0x5180,0x0007,0x51BC,0x0007,0x521C,
+ 0x0007,0x527C,0x0007,0x52DC,0x0007,0x5330,0x0007,0x53D2,
+ 0x0007,0x5474,0x0007,0x5516,0x0007,0x5570,0x0007,0x55EE,
+ 0x0007,0x566C,0x0007,0x56EA,0x0007,0x5768,0x0007,0x580A,
+ 0x0007,0x58AC,0x0007,0x41AA,0x0007,0x41DA,0x0007,0x422E,
+ 0x0007,0x4282,0x0007,0x42D6,0x0007,0x4336,0x0007,0x43EE,
+ 0x0007,0x44A6,0x0007,0x455E,0x0007,0x45BE,0x0007,0x4642,
+ 0x0007,0x46C6,0x0007,0x474A,0x0007,0x47A4,0x0007,0x4866,
+ 0x0007,0x4928,0x0007,0x594E,0x0007,0x597E,0x0007,0x59D2,
+ 0x0007,0x5A26,0x0007,0x5A7A,0x0007,0x5ADA,0x0007,0x5B6E,
+ 0x0007,0x5C02,0x0007,0x5C96,0x0007,0x5CF0,0x0007,0x5D78,
+ 0x0007,0x5E00,0x0007,0x5E88,0x0007,0x5EE0,0x0007,0x5F50,
+ 0x0007,0x5FC0,0x0007,0x49EA,0x0007,0x4A1E,0x0007,0x4AB6,
+
+ 0x0007,0x4B4E,0x0007,0x4BE6,0x0007,0x4C32,0x0007,0x4CA2,
+ 0x0007,0x4D12,0x0007,0x6030,0x0007,0x6070,0x0007,0x611E,
+ 0x0007,0x61CC,0x0007,0x627A,0x0007,0x62BA,0x0007,0x631E,
+ 0x0007,0x6382,0x0007,0x4D82,0x0007,0x4DDA,0x0007,0x4E96,
+ 0x0007,0x4F52,0x0007,0x500E,0x0007,0x5048,0x0007,0x50B0,
+ 0x0007,0x5118,0x0007,0x63E6,0x0007,0x6426,0x0007,0x64CA,
+ 0x0007,0x656E,0x0007,0x6612,0x0007,0x6652,0x0007,0x66B6,
+ 0x0007,0x671A,0x0007,0x393C,0x0007,0x3992,0x0007,0x39EE,
+ 0x0007,0x6FA2,0x0007,0x6FAE,0x0007,0x6FCC,0x0007,0x6FF6,
+ 0x0007,0x7002,0x0007,0x7020,0x0007,0x704A,0x0007,0x7056,
+ 0x0007,0x7074,0x0007,0x7118,0x0007,0x712E,0x0007,0x709E,
+ 0x0007,0x70A6,0x0007,0x713A,0x0007,0x73C6,0x0007,0x7262,
+ 0x0007,0x72D6,0x0007,0x733C,0x0007,0x7384,0x0007,0x7476,
+ 0x0007,0x7548,0x0007,0x7906,0x0007,0x7712,0x0007,0x7AD0,
+ 0x0007,0x7852,0x0007,0x7C32,0x0007,0x7D0A,0x0007,0x7DFC,
+ 0x0007,0x7EEE,0x0007,0x7FE0,0x0007,0x8158,0x0007,0x824A,
+
+ 0x0007,0x833C,0x0007,0x842E,0x0007,0x8F92,0x0007,0x8FB2,
+ 0x0007,0x8FEE,0x0007,0x902A,0x0007,0x9038,0x0007,0x9066,
+ 0x0007,0x90C6,0x0007,0x9102,0x0007,0x9108,0x0007,0x9136,
+ 0x0007,0x9172,0x0007,0x9180,0x0007,0x919E,0x0007,0x91AC,
+ 0x0007,0x91CA,0x0007,0x9206,0x0007,0x9262,0x0007,0x929C,
+ 0x0007,0x92AA,0x0007,0x92D0,0x0007,0x930C,0x0007,0x9322,
+ 0x0007,0x9340,0x0007,0x937C,0x0007,0x93CE,0x0007,0x93E4,
+ 0x0007,0x9402,0x0007,0x945C,0x0007,0x9462,0x0007,0x9480,
+ 0x0007,0x94CC,0x0007,0x94EA,0x0007,0x9510,0x0007,0x954C,
+ 0x0007,0x9552,0x0007,0x677E,0x0007,0x677E,0x0007,0x677E,
+ 0x0007,0x677E,0x0007,0x67CC,0x0007,0x67CC,0x0007,0x67CC,
+ 0x0007,0x67CC,0x0007,0x6820,0x0007,0x68A6,0x0007,0x697E,
+ 0x0007,0x6AA6,0x0007,0x6C1E,0x0007,0x6CBE,0x0007,0x6DAE,
+ 0x0007,0x6E9E,0x0007,0x6C66,0x0007,0x6D24,0x0007,0x6E14,
+ 0x0007,0x6F04,0x0007,0x6F8E,0x0007,0x85A6,0x0007,0x85BA,
+ 0x0007,0x85CE,0x0007,0x862A,0x0007,0x8644,0x0007,0x8658,
+
+ 0x0007,0x862A,0x0007,0x8644,0x0007,0x869C,0x0007,0x86A6,
+ 0x0007,0xCC3C,0x0007,0xCC68,0x0007,0xCD1C,0x0007,0xCD9A
+};
+static UINT16 bloodwar_mcu_4_26[] = { // Warrior 2
+ 0x000B,0xB188,0x000B,0xB1C0,0x000B,0xB308,0x000B,0xB590,
+ 0x000B,0xCF38,0x000B,0xBA00,0x000B,0xBA1A,0x000B,0xBA3A,
+ 0x000B,0xBE62,0x000B,0xC4AA,0x000B,0xCF54,0x000B,0xD130,
+ 0x000B,0xD142,0x000B,0xD174,0x000B,0xD1A6,0x000B,0xD210,
+ 0x000B,0xD222,0x000B,0xD254,0x000B,0xD286,0x000B,0xD1D8,
+ 0x000B,0xD1E6,0x000B,0xD1F4,0x000B,0xD202,0x000B,0xD2B8,
+ 0x000B,0xD2C6,0x000B,0xD2D4,0x000B,0xD2E2,0x000B,0xC662,
+ 0x000B,0xC67C,0x000B,0xC6B4,0x000B,0xC7BC,0x000B,0xC8C4,
+ 0x000B,0xC9B8,0x000B,0xC9E4,0x000B,0xCB58,0x000B,0xCCCC,
+ 0x000B,0xCF70,0x000B,0xCF82,0x000B,0xCFB4,0x000B,0xCFE6,
+ 0x000B,0xD050,0x000B,0xD062,0x000B,0xD094,0x000B,0xD0C6,
+ 0x000B,0xD018,0x000B,0xD026,0x000B,0xD034,0x000B,0xD042,
+ 0x000B,0xD0F8,0x000B,0xD106,0x000B,0xD114,0x000B,0xD122,
+ 0x000B,0xCE18,0x000B,0xCE58,0x000B,0xCECE,0x000B,0xCE2C,
+ 0x000B,0xCE6C,0x000B,0xCEE2,0x000B,0xCE44,0x000B,0xCEC0,
+ 0x000B,0xCF2A,0x000B,0xD52A,0x000B,0xD566,0x000B,0xD5C6,
+
+ 0x000B,0xD626,0x000B,0xD686,0x000B,0xD6D4,0x000B,0xD780,
+ 0x000B,0xD82C,0x000B,0xD8D8,0x000B,0xD920,0x000B,0xD99C,
+ 0x000B,0xDA18,0x000B,0xDA94,0x000B,0xDAEE,0x000B,0xDB86,
+ 0x000B,0xDC1E,0x000B,0xED72,0x000B,0xED9C,0x000B,0xEDFA,
+ 0x000B,0xEE58,0x000B,0xEEB6,0x000B,0xEEF8,0x000B,0xEFB8,
+ 0x000B,0xF078,0x000B,0xF138,0x000B,0xF186,0x000B,0xF208,
+ 0x000B,0xF28A,0x000B,0xF30C,0x000B,0xF366,0x000B,0xF3FE,
+ 0x000B,0xF496,0x000B,0xDCB6,0x000B,0xDCEC,0x000B,0xDD56,
+ 0x000B,0xDDC0,0x000B,0xDE2A,0x000B,0xDE6C,0x000B,0xDF2C,
+ 0x000B,0xDFEC,0x000B,0xE0AC,0x000B,0xE10C,0x000B,0xE1A0,
+ 0x000B,0xE234,0x000B,0xE2C8,0x000B,0xE332,0x000B,0xE3B4,
+ 0x000B,0xE436,0x000B,0xF52E,0x000B,0xF55E,0x000B,0xF5C2,
+ 0x000B,0xF626,0x000B,0xF68A,0x000B,0xF6CC,0x000B,0xF77C,
+ 0x000B,0xF82C,0x000B,0xF8DC,0x000B,0xF93A,0x000B,0xF9B0,
+ 0x000B,0xFA26,0x000B,0xFA9C,0x000B,0xFAF6,0x000B,0xFB8E,
+ 0x000B,0xFC26,0x000B,0xE4B8,0x000B,0xE4F8,0x000B,0xE59C,
+
+ 0x000B,0xE640,0x000B,0xE6E4,0x000B,0xE72A,0x000B,0xE794,
+ 0x000B,0xE7FE,0x000B,0xFCBE,0x000B,0xFCF2,0x000B,0xFD8A,
+ 0x000B,0xFE22,0x000B,0xFEBA,0x000B,0xFEEE,0x000B,0xFF46,
+ 0x000B,0xFF9E,0x000B,0xE868,0x000B,0xE8EE,0x000B,0xE9CE,
+ 0x000B,0xEAAE,0x000B,0xEB8E,0x000B,0xEBEC,0x000B,0xEC6E,
+ 0x000B,0xECF0,0x000B,0xFFF6,0x000C,0x008E,0x000C,0x0178,
+ 0x000C,0x0262,0x000C,0x034C,0x000C,0x038C,0x000C,0x03F0,
+ 0x000C,0x0454,0x000B,0xD2F0,0x000B,0xD450,0x000B,0xD4E2,
+ 0x000C,0x0946,0x000C,0x0952,0x000C,0x0970,0x000C,0x099A,
+ 0x000C,0x09A6,0x000C,0x09C4,0x000C,0x09EE,0x000C,0x09FA,
+ 0x000C,0x0A18,0x000C,0x0ABC,0x000C,0x0AD2,0x000C,0x0A42,
+ 0x000C,0x0A4A,0x000C,0x0ADE,0x000C,0x0D6A,0x000C,0x0C06,
+ 0x000C,0x0C7A,0x000C,0x0CE0,0x000C,0x0D28,0x000C,0x0E1A,
+ 0x000C,0x0EEC,0x000C,0x12AA,0x000C,0x10B6,0x000C,0x1474,
+ 0x000C,0x11F6,0x000C,0x15D6,0x000C,0x16AE,0x000C,0x17A0,
+ 0x000C,0x1892,0x000C,0x1984,0x000C,0x1AFC,0x000C,0x1BEE,
+
+ 0x000C,0x1CE0,0x000C,0x1DD2,0x000C,0x246A,0x000C,0x248A,
+ 0x000C,0x24C6,0x000C,0x2502,0x000C,0x2510,0x000C,0x253E,
+ 0x000C,0x259E,0x000C,0x25DA,0x000C,0x25E0,0x000C,0x260E,
+ 0x000C,0x264A,0x000C,0x2658,0x000C,0x2676,0x000C,0x2684,
+ 0x000C,0x26A2,0x000C,0x26DE,0x000C,0x273A,0x000C,0x2774,
+ 0x000C,0x2782,0x000C,0x27A8,0x000C,0x27E4,0x000C,0x27FA,
+ 0x000C,0x2818,0x000C,0x2854,0x000C,0x28A6,0x000C,0x28BC,
+ 0x000C,0x28DA,0x000C,0x2934,0x000C,0x293A,0x000C,0x2958,
+ 0x000C,0x29A4,0x000C,0x29C2,0x000C,0x29E8,0x000C,0x2A24,
+ 0x000C,0x2A2A,0x000C,0x04B8,0x000C,0x0506,0x000C,0x050E,
+ 0x000C,0x0516,0x000C,0x051E,0x000C,0x0620,0x000C,0x0634,
+ 0x000C,0x0736,0x000C,0x074A,0x000C,0x0834,0x000C,0x0848,
+ 0x000C,0x0932,0x000C,0x1F4A,0x000C,0x1F5E,0x000C,0x1F78,
+ 0x000C,0x1F4A,0x000C,0x1F5E,0x000C,0x1FC2,0x000C,0x1FCC,
+ 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF
+};
+static UINT16 bloodwar_mcu_4_27[] = { // Warrior 3
+ 0x0008,0x631C,0x0008,0x6348,0x0008,0x63EC,0x0008,0x6494,
+ 0x0008,0x6C5C,0x0008,0x6598,0x0008,0x65B2,0x0008,0x65D2,
+ 0x0008,0x6676,0x0008,0x674A,0x0008,0x6C78,0x0008,0x6E54,
+ 0x0008,0x6E66,0x0008,0x6E98,0x0008,0x6ECA,0x0008,0x6F34,
+ 0x0008,0x6F46,0x0008,0x6F78,0x0008,0x6FAA,0x0008,0x6EFC,
+ 0x0008,0x6F0A,0x0008,0x6F18,0x0008,0x6F26,0x0008,0x6FDC,
+ 0x0008,0x6FEA,0x0008,0x6FF8,0x0008,0x7006,0x0008,0x681E,
+ 0x0008,0x6838,0x0008,0x6864,0x0008,0x68CC,0x0008,0x6934,
+ 0x0008,0x699C,0x0008,0x69C8,0x0008,0x6A30,0x0008,0x6A98,
+ 0x0008,0x6C94,0x0008,0x6CA6,0x0008,0x6CD8,0x0008,0x6D0A,
+ 0x0008,0x6D74,0x0008,0x6D86,0x0008,0x6DB8,0x0008,0x6DEA,
+ 0x0008,0x6D3C,0x0008,0x6D4A,0x0008,0x6D58,0x0008,0x6D66,
+ 0x0008,0x6E1C,0x0008,0x6E2A,0x0008,0x6E38,0x0008,0x6E46,
+ 0x0008,0x6B00,0x0008,0x6B64,0x0008,0x6BE0,0x0008,0x6B1A,
+ 0x0008,0x6B7E,0x0008,0x6C00,0x0008,0x6B4A,0x0008,0x6BC0,
+ 0x0008,0x6C42,0x0008,0x7100,0x0008,0x7130,0x0008,0x7184,
+
+ 0x0008,0x71D8,0x0008,0x722C,0x0008,0x7280,0x0008,0x7322,
+ 0x0008,0x73C4,0x0008,0x7466,0x0008,0x74AE,0x0008,0x751A,
+ 0x0008,0x7586,0x0008,0x75F2,0x0008,0x7658,0x0008,0x76E2,
+ 0x0008,0x776C,0x0008,0x857A,0x0008,0x85AA,0x0008,0x85FE,
+ 0x0008,0x8652,0x0008,0x86A6,0x0008,0x870C,0x0008,0x8790,
+ 0x0008,0x8814,0x0008,0x8898,0x0008,0x88EC,0x0008,0x8964,
+ 0x0008,0x89DC,0x0008,0x8A54,0x0008,0x8ABA,0x0008,0x8B68,
+ 0x0008,0x8C16,0x0008,0x77F6,0x0008,0x782C,0x0008,0x7886,
+ 0x0008,0x78E0,0x0008,0x793A,0x0008,0x7982,0x0008,0x7A28,
+ 0x0008,0x7ACE,0x0008,0x7B74,0x0008,0x7BA4,0x0008,0x7BF8,
+ 0x0008,0x7C4C,0x0008,0x7CA0,0x0008,0x7CFA,0x0008,0x7D92,
+ 0x0008,0x7E2A,0x0008,0x8CC4,0x0008,0x8CF4,0x0008,0x8D48,
+ 0x0008,0x8D9C,0x0008,0x8DF0,0x0008,0x8E3E,0x0008,0x8EEA,
+ 0x0008,0x8F96,0x0008,0x9042,0x0008,0x907E,0x0008,0x90DE,
+ 0x0008,0x913E,0x0008,0x919E,0x0008,0x91FE,0x0008,0x929C,
+ 0x0008,0x933A,0x0008,0x7EC2,0x0008,0x7EF6,0x0008,0x7F8E,
+
+ 0x0008,0x8026,0x0008,0x80BE,0x0008,0x80FE,0x0008,0x8152,
+ 0x0008,0x81A6,0x0008,0x93D8,0x0008,0x9412,0x0008,0x94B0,
+ 0x0008,0x954E,0x0008,0x95EC,0x0008,0x9644,0x0008,0x96C0,
+ 0x0008,0x973C,0x0008,0x81FA,0x0008,0x823A,0x0008,0x82DE,
+ 0x0008,0x8382,0x0008,0x8426,0x0008,0x8460,0x0008,0x84BE,
+ 0x0008,0x851C,0x0008,0x97B8,0x0008,0x97F2,0x0008,0x9890,
+ 0x0008,0x992E,0x0008,0x99CC,0x0008,0x9A12,0x0008,0x9A7C,
+ 0x0008,0x9AE6,0x0008,0x7014,0x0008,0x706A,0x0008,0x70C4,
+ 0x0008,0xA16E,0x0008,0xA17A,0x0008,0xA198,0x0008,0xA1C2,
+ 0x0008,0xA1CE,0x0008,0xA1EC,0x0008,0xA216,0x0008,0xA222,
+ 0x0008,0xA240,0x0008,0xA2E4,0x0008,0xA2FA,0x0008,0xA26A,
+ 0x0008,0xA272,0x0008,0xA306,0x0008,0xA592,0x0008,0xA42E,
+ 0x0008,0xA4A2,0x0008,0xA508,0x0008,0xA550,0x0008,0xA642,
+ 0x0008,0xA714,0x0008,0xAAD2,0x0008,0xA8DE,0x0008,0xAC9C,
+ 0x0008,0xAA1E,0x0008,0xADFE,0x0008,0xAED6,0x0008,0xAFC8,
+ 0x0008,0xB0BA,0x0008,0xB1AC,0x0008,0xB324,0x0008,0xB416,
+
+ 0x0008,0xB508,0x0008,0xB5FA,0x0008,0xBC1C,0x0008,0xBC3C,
+ 0x0008,0xBC78,0x0008,0xBCB4,0x0008,0xBCC2,0x0008,0xBCF0,
+ 0x0008,0xBD50,0x0008,0xBD8C,0x0008,0xBD92,0x0008,0xBDC0,
+ 0x0008,0xBDFC,0x0008,0xBE0A,0x0008,0xBE28,0x0008,0xBE36,
+ 0x0008,0xBE54,0x0008,0xBE90,0x0008,0xBEEC,0x0008,0xBF26,
+ 0x0008,0xBF34,0x0008,0xBF5A,0x0008,0xBF96,0x0008,0xBFAC,
+ 0x0008,0xBFCA,0x0008,0xC006,0x0008,0xC058,0x0008,0xC06E,
+ 0x0008,0xC08C,0x0008,0xC0E6,0x0008,0xC0EC,0x0008,0xC10A,
+ 0x0008,0xC156,0x0008,0xC174,0x0008,0xC19A,0x0008,0xC1D6,
+ 0x0008,0xC1DC,0x0008,0x9B50,0x0008,0x9BF8,0x0008,0x9CDC,
+ 0x0008,0x9DC0,0x0008,0x9B52,0x0008,0x9BFA,0x0008,0x9CDE,
+ 0x0008,0x9DC2,0x0008,0x9EA4,0x0008,0x9EB2,0x0008,0x9F38,
+ 0x0008,0x9F4C,0x0008,0x9FD2,0x0008,0x9FE6,0x0008,0xA06C,
+ 0x0008,0xA080,0x0008,0xA106,0x0008,0xA11A,0x0008,0xA11A,
+ 0x0008,0xA11A,0x0008,0xA11A,0x0008,0xB772,0x0008,0xB786,
+ 0x0008,0xB7AC,0x0008,0xB7EA,0x0008,0xB7FE,0x0008,0xB818,
+
+ 0x0008,0xB772,0x0008,0xB786,0x0008,0xB87E,0x0008,0xB772,
+ 0x0008,0xB786,0x0008,0xB8F0,0x0008,0xB912,0x0008,0xB93A,
+ 0x0008,0xF128,0x0008,0xF148,0x0008,0xF1EC,0x0008,0xF2AA
+};
+static UINT16 bloodwar_mcu_4_28[] = { // Warrior 4
+ 0x0008,0xF128,0x0008,0xF148,0x0008,0xF1EC,0x0008,0xF2AA,
+ 0x0008,0xFA80,0x0008,0xF3AA,0x0008,0xF3C4,0x0008,0xF3E4,
+ 0x0008,0xF4A8,0x0008,0xF56C,0x0008,0xFA9C,0x0008,0xFC78,
+ 0x0008,0xFC8A,0x0008,0xFCBC,0x0008,0xFCEE,0x0008,0xFD58,
+ 0x0008,0xFD6A,0x0008,0xFD9C,0x0008,0xFDCE,0x0008,0xFD20,
+ 0x0008,0xFD2E,0x0008,0xFD3C,0x0008,0xFD4A,0x0008,0xFE00,
+ 0x0008,0xFE0E,0x0008,0xFE1C,0x0008,0xFE2A,0x0008,0xF630,
+ 0x0008,0xF64A,0x0008,0xF67C,0x0008,0xF6F4,0x0008,0xF76C,
+ 0x0008,0xF7E4,0x0008,0xF816,0x0008,0xF88E,0x0008,0xF906,
+ 0x0008,0xFAB8,0x0008,0xFACA,0x0008,0xFAFC,0x0008,0xFB2E,
+ 0x0008,0xFB98,0x0008,0xFBAA,0x0008,0xFBDC,0x0008,0xFC0E,
+ 0x0008,0xFB60,0x0008,0xFB6E,0x0008,0xFB7C,0x0008,0xFB8A,
+ 0x0008,0xFC40,0x0008,0xFC4E,0x0008,0xFC5C,0x0008,0xFC6A,
+ 0x0008,0xF97E,0x0008,0xF9D0,0x0008,0xFA28,0x0008,0xF992,
+ 0x0008,0xF9E4,0x0008,0xFA3C,0x0008,0xF9BC,0x0008,0xFA14,
+ 0x0008,0xFA6C,0x0008,0xFF1A,0x0008,0xFF4A,0x0008,0xFF9E,
+
+ 0x0008,0xFFF2,0x0009,0x0046,0x0009,0x00A0,0x0009,0x012E,
+ 0x0009,0x01BC,0x0009,0x024A,0x0009,0x02A4,0x0009,0x0322,
+ 0x0009,0x03A0,0x0009,0x041E,0x0009,0x046C,0x0009,0x04F8,
+ 0x0009,0x0584,0x0009,0x16C4,0x0009,0x1700,0x0009,0x1760,
+ 0x0009,0x17C0,0x0009,0x1820,0x0009,0x1868,0x0009,0x190E,
+ 0x0009,0x19B4,0x0009,0x1A5A,0x0009,0x1AAE,0x0009,0x1B36,
+ 0x0009,0x1BBE,0x0009,0x1C46,0x0009,0x1C9A,0x0009,0x1D46,
+ 0x0009,0x1DF2,0x0009,0x0610,0x0009,0x064C,0x0009,0x06BC,
+ 0x0009,0x072C,0x0009,0x079C,0x0009,0x07F0,0x0009,0x08BC,
+ 0x0009,0x0988,0x0009,0x0A54,0x0009,0x0A9C,0x0009,0x0B18,
+ 0x0009,0x0B94,0x0009,0x0C10,0x0009,0x0C76,0x0009,0x0D10,
+ 0x0009,0x0DAA,0x0009,0x1E9E,0x0009,0x1ECE,0x0009,0x1F22,
+ 0x0009,0x1F76,0x0009,0x1FCA,0x0009,0x2024,0x0009,0x20BC,
+ 0x0009,0x2154,0x0009,0x21EC,0x0009,0x2240,0x0009,0x22C8,
+ 0x0009,0x2350,0x0009,0x23D8,0x0009,0x243E,0x0009,0x24D8,
+ 0x0009,0x2572,0x0009,0x0E44,0x0009,0x0E90,0x0009,0x0F40,
+
+ 0x0009,0x0FF0,0x0009,0x10A0,0x0009,0x1104,0x0009,0x117C,
+ 0x0009,0x11F4,0x0009,0x260C,0x0009,0x2664,0x0009,0x2700,
+ 0x0009,0x279C,0x0009,0x2838,0x0009,0x2878,0x0009,0x28DC,
+ 0x0009,0x2940,0x0009,0x126C,0x0009,0x12D0,0x0009,0x1398,
+ 0x0009,0x1460,0x0009,0x1528,0x0009,0x1574,0x0009,0x15E4,
+ 0x0009,0x1654,0x0009,0x29A4,0x0009,0x29EA,0x0009,0x2A84,
+ 0x0009,0x2B1E,0x0009,0x2BB8,0x0009,0x2BFE,0x0009,0x2C58,
+ 0x0009,0x2CB2,0x0008,0xFE38,0x0008,0xFEA6,0x0008,0xFEF6,
+ 0x0009,0x3406,0x0009,0x3412,0x0009,0x3430,0x0009,0x345A,
+ 0x0009,0x3466,0x0009,0x3484,0x0009,0x34AE,0x0009,0x34BA,
+ 0x0009,0x34D8,0x0009,0x357C,0x0009,0x3592,0x0009,0x3502,
+ 0x0009,0x350A,0x0009,0x359E,0x0009,0x379A,0x0009,0x3636,
+ 0x0009,0x36AA,0x0009,0x3710,0x0009,0x3758,0x0009,0x384A,
+ 0x0009,0x391C,0x0009,0x3CDA,0x0009,0x3AE6,0x0009,0x3EA4,
+ 0x0009,0x3C26,0x0009,0x4006,0x0009,0x40DE,0x0009,0x41D0,
+ 0x0009,0x42C2,0x0009,0x43B4,0x0009,0x452C,0x0009,0x461E,
+
+ 0x0009,0x4710,0x0009,0x4802,0x0009,0x4ED8,0x0009,0x4EF8,
+ 0x0009,0x4F34,0x0009,0x4F70,0x0009,0x4F7E,0x0009,0x4FAC,
+ 0x0009,0x500C,0x0009,0x5048,0x0009,0x504E,0x0009,0x507C,
+ 0x0009,0x50B8,0x0009,0x50C6,0x0009,0x50E4,0x0009,0x50F2,
+ 0x0009,0x5110,0x0009,0x514C,0x0009,0x51A8,0x0009,0x51E2,
+ 0x0009,0x51F0,0x0009,0x5216,0x0009,0x5252,0x0009,0x5268,
+ 0x0009,0x5286,0x0009,0x52C2,0x0009,0x5314,0x0009,0x532A,
+ 0x0009,0x5348,0x0009,0x53A2,0x0009,0x53A8,0x0009,0x53C6,
+ 0x0009,0x5412,0x0009,0x5430,0x0009,0x5456,0x0009,0x5492,
+ 0x0009,0x5498,0x0009,0x2D0C,0x0009,0x2DC8,0x0009,0x2E84,
+ 0x0009,0x2F40,0x0009,0x2D0E,0x0009,0x2DCA,0x0009,0x2E86,
+ 0x0009,0x2F42,0x0009,0x2FFC,0x0009,0x300A,0x0009,0x300A,
+ 0x0009,0x300A,0x0009,0x300A,0x0009,0x305E,0x0009,0x3148,
+ 0x0009,0x3232,0x0009,0x331C,0x0009,0x497A,0x0009,0x498E,
+ 0x0009,0x49A2,0x0009,0x497A,0x0009,0x498E,0x0009,0x49E6,
+ 0x0009,0x49F6,0x0009,0x497A,0x0009,0x498E,0x0009,0x4A18,
+
+ 0x0009,0x4A2A,0x0009,0x81A8,0x0009,0x81C8,0x0009,0x8270
+};
+static UINT16 bloodwar_mcu_4_29[] = { // Warrior 5
+ 0x0007,0xCC3C,0x0007,0xCC68,0x0007,0xCD1C,0x0007,0xCD9A,
+ 0x0007,0xD616,0x0007,0xCE38,0x0007,0xCE52,0x0007,0xCE72,
+ 0x0007,0xCF16,0x0007,0xCFAA,0x0007,0xD632,0x0007,0xD80E,
+ 0x0007,0xD820,0x0007,0xD852,0x0007,0xD884,0x0007,0xD8EE,
+ 0x0007,0xD900,0x0007,0xD932,0x0007,0xD964,0x0007,0xD8B6,
+ 0x0007,0xD8C4,0x0007,0xD8D2,0x0007,0xD8E0,0x0007,0xD996,
+ 0x0007,0xD9A4,0x0007,0xD9B2,0x0007,0xD9C0,0x0007,0xD064,
+ 0x0007,0xD07E,0x0007,0xD0C2,0x0007,0xD16A,0x0007,0xD212,
+ 0x0007,0xD2BA,0x0007,0xD2FE,0x0007,0xD3A6,0x0007,0xD44E,
+ 0x0007,0xD64E,0x0007,0xD660,0x0007,0xD692,0x0007,0xD6C4,
+ 0x0007,0xD72E,0x0007,0xD740,0x0007,0xD772,0x0007,0xD7A4,
+ 0x0007,0xD6F6,0x0007,0xD704,0x0007,0xD712,0x0007,0xD720,
+ 0x0007,0xD7D6,0x0007,0xD7E4,0x0007,0xD7F2,0x0007,0xD800,
+ 0x0007,0xD4F6,0x0007,0xD54E,0x0007,0xD5BE,0x0007,0xD50A,
+ 0x0007,0xD562,0x0007,0xD5D2,0x0007,0xD53A,0x0007,0xD5B0,
+ 0x0007,0xD602,0x0007,0xDA8C,0x0007,0xDAC8,0x0007,0xDB2C,
+
+ 0x0007,0xDB90,0x0007,0xDBF4,0x0007,0xDC36,0x0007,0xDCE0,
+ 0x0007,0xDD8A,0x0007,0xDE34,0x0007,0xDE94,0x0007,0xDF3C,
+ 0x0007,0xDFE4,0x0007,0xE08C,0x0007,0xE0F2,0x0007,0xE1B4,
+ 0x0007,0xE276,0x0007,0xF2D6,0x0007,0xF30C,0x0007,0xF366,
+ 0x0007,0xF3C0,0x0007,0xF41A,0x0007,0xF462,0x0007,0xF538,
+ 0x0007,0xF60E,0x0007,0xF6E4,0x0007,0xF77A,0x0007,0xF862,
+ 0x0007,0xF94A,0x0007,0xFA32,0x0007,0xFACE,0x0007,0xFBC6,
+ 0x0007,0xFCBE,0x0007,0xE338,0x0007,0xE36E,0x0007,0xE3C8,
+ 0x0007,0xE422,0x0007,0xE47C,0x0007,0xE4B8,0x0007,0xE552,
+ 0x0007,0xE5EC,0x0007,0xE686,0x0007,0xE6E0,0x0007,0xE772,
+ 0x0007,0xE804,0x0007,0xE896,0x0007,0xE8E2,0x0007,0xE946,
+ 0x0007,0xE9AA,0x0007,0xFDB6,0x0007,0xFDE6,0x0007,0xFE3A,
+ 0x0007,0xFE8E,0x0007,0xFEE2,0x0007,0xFF3C,0x0007,0xFFE4,
+ 0x0008,0x008C,0x0008,0x0134,0x0008,0x01B2,0x0008,0x0282,
+ 0x0008,0x0352,0x0008,0x0422,0x0008,0x04A6,0x0008,0x0586,
+ 0x0008,0x0666,0x0007,0xEA0E,0x0007,0xEA6C,0x0007,0xEB22,
+
+ 0x0007,0xEBD8,0x0007,0xEC8E,0x0007,0xECEC,0x0007,0xED72,
+ 0x0007,0xEDF8,0x0008,0x0746,0x0008,0x079E,0x0008,0x083E,
+ 0x0008,0x08DE,0x0008,0x097E,0x0008,0x09D6,0x0008,0x0A56,
+ 0x0008,0x0AD6,0x0007,0xEE7E,0x0007,0xEED0,0x0007,0xEF7A,
+ 0x0007,0xF024,0x0007,0xF0CE,0x0007,0xF132,0x0007,0xF1BE,
+ 0x0007,0xF24A,0x0008,0x0B56,0x0008,0x0BB4,0x0008,0x0C5A,
+ 0x0008,0x0D00,0x0008,0x0DA6,0x0008,0x0E04,0x0008,0x0E8A,
+ 0x0008,0x0F10,0x0007,0xD9CE,0x0007,0xDA1C,0x0007,0xDA58,
+ 0x0008,0x1EDC,0x0008,0x1EE8,0x0008,0x1F06,0x0008,0x1F30,
+ 0x0008,0x1F3C,0x0008,0x1F5A,0x0008,0x1F84,0x0008,0x1F90,
+ 0x0008,0x1FAE,0x0008,0x204C,0x0008,0x2062,0x0008,0x1FD8,
+ 0x0008,0x1FE0,0x0008,0x206E,0x0008,0x226A,0x0008,0x2106,
+ 0x0008,0x217A,0x0008,0x21E0,0x0008,0x2228,0x0008,0x231A,
+ 0x0008,0x23E6,0x0008,0x27A4,0x0008,0x25B0,0x0008,0x296E,
+ 0x0008,0x26F0,0x0008,0x2AD0,0x0008,0x2BA8,0x0008,0x2C94,
+ 0x0008,0x2D80,0x0008,0x2E6C,0x0008,0x2FDE,0x0008,0x30CA,
+
+ 0x0008,0x31B6,0x0008,0x32A2,0x0008,0x3414,0x0008,0x3434,
+ 0x0008,0x3470,0x0008,0x34AC,0x0008,0x34BA,0x0008,0x34E8,
+ 0x0008,0x3548,0x0008,0x3584,0x0008,0x358A,0x0008,0x35B8,
+ 0x0008,0x35F4,0x0008,0x3602,0x0008,0x3620,0x0008,0x362E,
+ 0x0008,0x364C,0x0008,0x3688,0x0008,0x36E4,0x0008,0x371E,
+ 0x0008,0x372C,0x0008,0x3752,0x0008,0x378E,0x0008,0x37A4,
+ 0x0008,0x37C2,0x0008,0x37FE,0x0008,0x3850,0x0008,0x3866,
+ 0x0008,0x3884,0x0008,0x38DE,0x0008,0x38E4,0x0008,0x3902,
+ 0x0008,0x394E,0x0008,0x396C,0x0008,0x3992,0x0008,0x39CE,
+ 0x0008,0x39D4,0x0008,0x0F96,0x0008,0x10A2,0x0008,0x10B6,
+ 0x0008,0x11C2,0x0008,0x11D6,0x0008,0x12E2,0x0008,0x12F6,
+ 0x0008,0x1402,0x0008,0x1416,0x0008,0x14E8,0x0008,0x15DE,
+ 0x0008,0x16DE,0x0008,0x17DE,0x0008,0x1934,0x0008,0x1A8A,
+ 0x0008,0x1BE0,0x0008,0x1D36,0x0008,0x1D50,0x0008,0x1D70,
+ 0x0008,0x1DAE,0x0008,0x1DC8,0x0008,0x1DE8,0x0008,0x1E2C,
+ 0x0008,0x1E46,0x0008,0x1E5A,0x0008,0x1DAE,0x0008,0x1DC8,
+
+ 0x0008,0x1E9A,0x0008,0x1EAC,0x0008,0x631C,0x0008,0x6348
+};
+static UINT16 bloodwar_mcu_4_2a[] = { // Warrior 6
+ 0x000A,0x0E3C,0x000A,0x0E5C,0x000A,0x0F00,0x000A,0x0FA8,
+ 0x000A,0x16E2,0x000A,0x105C,0x000A,0x1076,0x000A,0x1096,
+ 0x000A,0x113A,0x000A,0x11DE,0x000A,0x16FE,0x000A,0x18DA,
+ 0x000A,0x18EC,0x000A,0x191E,0x000A,0x1950,0x000A,0x19BA,
+ 0x000A,0x19CC,0x000A,0x19FE,0x000A,0x1A30,0x000A,0x1982,
+ 0x000A,0x1990,0x000A,0x199E,0x000A,0x19AC,0x000A,0x1A62,
+ 0x000A,0x1A70,0x000A,0x1A7E,0x000A,0x1A8C,0x000A,0x1286,
+ 0x000A,0x12A0,0x000A,0x12D2,0x000A,0x134A,0x000A,0x13C2,
+ 0x000A,0x143A,0x000A,0x146C,0x000A,0x14E4,0x000A,0x155C,
+ 0x000A,0x171A,0x000A,0x172C,0x000A,0x175E,0x000A,0x1790,
+ 0x000A,0x17FA,0x000A,0x180C,0x000A,0x183E,0x000A,0x1870,
+ 0x000A,0x17C2,0x000A,0x17D0,0x000A,0x17DE,0x000A,0x17EC,
+ 0x000A,0x18A2,0x000A,0x18B0,0x000A,0x18BE,0x000A,0x18CC,
+ 0x000A,0x15D4,0x000A,0x1632,0x000A,0x168A,0x000A,0x15E8,
+ 0x000A,0x1646,0x000A,0x169E,0x000A,0x161E,0x000A,0x1676,
+ 0x000A,0x16CE,0x000A,0x1B52,0x000A,0x1B82,0x000A,0x1BD6,
+
+ 0x000A,0x1C2A,0x000A,0x1C7E,0x000A,0x1CCC,0x000A,0x1D68,
+ 0x000A,0x1E04,0x000A,0x1EA0,0x000A,0x1EE8,0x000A,0x1F54,
+ 0x000A,0x1FC0,0x000A,0x202C,0x000A,0x207A,0x000A,0x2106,
+ 0x000A,0x2192,0x000A,0x3092,0x000A,0x30C2,0x000A,0x3116,
+ 0x000A,0x316A,0x000A,0x31BE,0x000A,0x320C,0x000A,0x32B8,
+ 0x000A,0x3364,0x000A,0x3410,0x000A,0x345E,0x000A,0x34D0,
+ 0x000A,0x3542,0x000A,0x35B4,0x000A,0x3602,0x000A,0x36AE,
+ 0x000A,0x375A,0x000A,0x221E,0x000A,0x224E,0x000A,0x22A2,
+ 0x000A,0x22F6,0x000A,0x234A,0x000A,0x2392,0x000A,0x2438,
+ 0x000A,0x24DE,0x000A,0x2584,0x000A,0x25C6,0x000A,0x262C,
+ 0x000A,0x2692,0x000A,0x26F8,0x000A,0x273A,0x000A,0x27DA,
+ 0x000A,0x287A,0x000A,0x3806,0x000A,0x3836,0x000A,0x388A,
+ 0x000A,0x38DE,0x000A,0x3932,0x000A,0x3980,0x000A,0x3A2C,
+ 0x000A,0x3AD8,0x000A,0x3B84,0x000A,0x3BCC,0x000A,0x3C48,
+ 0x000A,0x3CC4,0x000A,0x3D40,0x000A,0x3D8E,0x000A,0x3E3A,
+ 0x000A,0x3EE6,0x000A,0x291A,0x000A,0x294E,0x000A,0x29E6,
+
+ 0x000A,0x2A7E,0x000A,0x2B16,0x000A,0x2B56,0x000A,0x2BBA,
+ 0x000A,0x2C1E,0x000A,0x3F92,0x000A,0x3FC6,0x000A,0x405E,
+ 0x000A,0x40F6,0x000A,0x418E,0x000A,0x41C2,0x000A,0x421A,
+ 0x000A,0x4272,0x000A,0x2C82,0x000A,0x2CCE,0x000A,0x2D86,
+ 0x000A,0x2E3E,0x000A,0x2EF6,0x000A,0x2F42,0x000A,0x2FB2,
+ 0x000A,0x3022,0x000A,0x42CA,0x000A,0x42FE,0x000A,0x4396,
+ 0x000A,0x442E,0x000A,0x44C6,0x000A,0x44FA,0x000A,0x4552,
+ 0x000A,0x45AA,0x000A,0x1A9A,0x000A,0x1AF0,0x000A,0x1B2E,
+ 0x000A,0x4D2C,0x000A,0x4D38,0x000A,0x4D56,0x000A,0x4D80,
+ 0x000A,0x4D8C,0x000A,0x4DAA,0x000A,0x4DD4,0x000A,0x4DE0,
+ 0x000A,0x4DFE,0x000A,0x4EA2,0x000A,0x4EB8,0x000A,0x4E28,
+ 0x000A,0x4E30,0x000A,0x4EC4,0x000A,0x50C0,0x000A,0x4F5C,
+ 0x000A,0x4FD0,0x000A,0x5036,0x000A,0x507E,0x000A,0x5170,
+ 0x000A,0x5242,0x000A,0x5600,0x000A,0x540C,0x000A,0x57CA,
+ 0x000A,0x554C,0x000A,0x592C,0x000A,0x5A04,0x000A,0x5AF6,
+ 0x000A,0x5BE8,0x000A,0x5CDA,0x000A,0x5E52,0x000A,0x5F44,
+
+ 0x000A,0x6036,0x000A,0x6128,0x000A,0x6738,0x000A,0x6758,
+ 0x000A,0x6794,0x000A,0x67D0,0x000A,0x67DE,0x000A,0x680C,
+ 0x000A,0x686C,0x000A,0x68A8,0x000A,0x68AE,0x000A,0x68DC,
+ 0x000A,0x6918,0x000A,0x6926,0x000A,0x6944,0x000A,0x6952,
+ 0x000A,0x6970,0x000A,0x69AC,0x000A,0x6A08,0x000A,0x6A42,
+ 0x000A,0x6A50,0x000A,0x6A76,0x000A,0x6AB2,0x000A,0x6AC8,
+ 0x000A,0x6AE6,0x000A,0x6B22,0x000A,0x6B74,0x000A,0x6B8A,
+ 0x000A,0x6BA8,0x000A,0x6C02,0x000A,0x6C08,0x000A,0x6C26,
+ 0x000A,0x6C72,0x000A,0x6C90,0x000A,0x6CB6,0x000A,0x6CF2,
+ 0x000A,0x6CF8,0x000A,0x4602,0x000A,0x4602,0x000A,0x4602,
+ 0x000A,0x4602,0x000A,0x4644,0x000A,0x46F8,0x000A,0x47AC,
+ 0x000A,0x4860,0x000A,0x4646,0x000A,0x46FA,0x000A,0x47AE,
+ 0x000A,0x4862,0x000A,0x4916,0x000A,0x4924,0x000A,0x4A26,
+ 0x000A,0x4B28,0x000A,0x4C2A,0x000A,0x62A0,0x000A,0x62B4,
+ 0x000A,0x62DA,0x000A,0x62A0,0x000A,0x62B4,0x000A,0x631E,
+ 0x000A,0x6338,0x000A,0x94A4,0x000A,0x94C4,0x000A,0x9568
+};
+static UINT16 bloodwar_mcu_4_2b[] = { // Warrior 7
+ 0x000A,0x94A4,0x000A,0x94C4,0x000A,0x9568,0x000A,0x9646,
+ 0x000A,0x9DFC,0x000A,0x9746,0x000A,0x9760,0x000A,0x9780,
+ 0x000A,0x9824,0x000A,0x98C8,0x000A,0x9E18,0x000A,0x9FF4,
+ 0x000A,0xA006,0x000A,0xA038,0x000A,0xA06A,0x000A,0xA0D4,
+ 0x000A,0xA0E6,0x000A,0xA118,0x000A,0xA14A,0x000A,0xA09C,
+ 0x000A,0xA0AA,0x000A,0xA0B8,0x000A,0xA0C6,0x000A,0xA17C,
+ 0x000A,0xA18A,0x000A,0xA198,0x000A,0xA1A6,0x000A,0x9970,
+ 0x000A,0x998A,0x000A,0x99B0,0x000A,0x9A44,0x000A,0x9AD8,
+ 0x000A,0x9B6C,0x000A,0x9B8C,0x000A,0x9BEA,0x000A,0x9C48,
+ 0x000A,0x9E34,0x000A,0x9E46,0x000A,0x9E78,0x000A,0x9EAA,
+ 0x000A,0x9F14,0x000A,0x9F26,0x000A,0x9F58,0x000A,0x9F8A,
+ 0x000A,0x9EDC,0x000A,0x9EEA,0x000A,0x9EF8,0x000A,0x9F06,
+ 0x000A,0x9FBC,0x000A,0x9FCA,0x000A,0x9FD8,0x000A,0x9FE6,
+ 0x000A,0x9CA6,0x000A,0x9D04,0x000A,0x9D86,0x000A,0x9CBA,
+ 0x000A,0x9D18,0x000A,0x9D9A,0x000A,0x9CF0,0x000A,0x9D72,
+ 0x000A,0x9DE8,0x000A,0xA260,0x000A,0xA296,0x000A,0xA2F0,
+
+ 0x000A,0xA34A,0x000A,0xA3A4,0x000A,0xA3FE,0x000A,0xA4B0,
+ 0x000A,0xA562,0x000A,0xA614,0x000A,0xA67A,0x000A,0xA6F8,
+ 0x000A,0xA776,0x000A,0xA7F4,0x000A,0xA860,0x000A,0xA900,
+ 0x000A,0xA9A0,0x000A,0xB9F2,0x000A,0xBA22,0x000A,0xBA76,
+ 0x000A,0xBACA,0x000A,0xBB1E,0x000A,0xBB60,0x000A,0xBC00,
+ 0x000A,0xBCA0,0x000A,0xBD40,0x000A,0xBD88,0x000A,0xBDF4,
+ 0x000A,0xBE60,0x000A,0xBECC,0x000A,0xBF20,0x000A,0xBFA8,
+ 0x000A,0xC030,0x000A,0xAA40,0x000A,0xAA76,0x000A,0xAAD0,
+ 0x000A,0xAB2A,0x000A,0xAB84,0x000A,0xABEA,0x000A,0xAC88,
+ 0x000A,0xAD26,0x000A,0xADC4,0x000A,0xAE24,0x000A,0xAEB8,
+ 0x000A,0xAF4C,0x000A,0xAFE0,0x000A,0xB03A,0x000A,0xB0E2,
+ 0x000A,0xB18A,0x000A,0xC0B8,0x000A,0xC0E8,0x000A,0xC13C,
+ 0x000A,0xC190,0x000A,0xC1E4,0x000A,0xC226,0x000A,0xC2C6,
+ 0x000A,0xC366,0x000A,0xC406,0x000A,0xC44E,0x000A,0xC4BA,
+ 0x000A,0xC526,0x000A,0xC592,0x000A,0xC5D4,0x000A,0xC694,
+ 0x000A,0xC754,0x000A,0xB232,0x000A,0xB272,0x000A,0xB316,
+
+ 0x000A,0xB3BA,0x000A,0xB45E,0x000A,0xB49E,0x000A,0xB502,
+ 0x000A,0xB566,0x000A,0xC814,0x000A,0xC848,0x000A,0xC8E0,
+ 0x000A,0xC978,0x000A,0xCA10,0x000A,0xCA44,0x000A,0xCA9C,
+ 0x000A,0xCAF4,0x000A,0xB5CA,0x000A,0xB622,0x000A,0xB6DE,
+ 0x000A,0xB79A,0x000A,0xB856,0x000A,0xB8A2,0x000A,0xB912,
+ 0x000A,0xB982,0x000A,0xCB4C,0x000A,0xCB80,0x000A,0xCC0E,
+ 0x000A,0xCC9C,0x000A,0xCD2A,0x000A,0xCD6A,0x000A,0xCDCE,
+ 0x000A,0xCE32,0x000A,0xA1B4,0x000A,0xA1F2,0x000A,0xA236,
+ 0x000A,0xDD1A,0x000A,0xDD26,0x000A,0xDD44,0x000A,0xDD6E,
+ 0x000A,0xDD7A,0x000A,0xDD98,0x000A,0xDDC2,0x000A,0xDDCE,
+ 0x000A,0xDDEC,0x000A,0xDE90,0x000A,0xDEA6,0x000A,0xDE16,
+ 0x000A,0xDE1E,0x000A,0xDEB2,0x000A,0xE13E,0x000A,0xDFDA,
+ 0x000A,0xE04E,0x000A,0xE0B4,0x000A,0xE0FC,0x000A,0xE1EE,
+ 0x000A,0xE2C0,0x000A,0xE67E,0x000A,0xE48A,0x000A,0xE848,
+ 0x000A,0xE5CA,0x000A,0xE9AA,0x000A,0xEA82,0x000A,0xEB74,
+ 0x000A,0xEC66,0x000A,0xED58,0x000A,0xEED0,0x000A,0xEFC2,
+
+ 0x000A,0xF0B4,0x000A,0xF1A6,0x000A,0xF752,0x000A,0xF772,
+ 0x000A,0xF7AE,0x000A,0xF7EA,0x000A,0xF7F8,0x000A,0xF826,
+ 0x000A,0xF886,0x000A,0xF8C2,0x000A,0xF8C8,0x000A,0xF8F6,
+ 0x000A,0xF932,0x000A,0xF940,0x000A,0xF95E,0x000A,0xF96C,
+ 0x000A,0xF98A,0x000A,0xF9C6,0x000A,0xFA22,0x000A,0xFA5C,
+ 0x000A,0xFA6A,0x000A,0xFA90,0x000A,0xFACC,0x000A,0xFAE2,
+ 0x000A,0xFB00,0x000A,0xFB3C,0x000A,0xFB8E,0x000A,0xFBA4,
+ 0x000A,0xFBC2,0x000A,0xFC1C,0x000A,0xFC22,0x000A,0xFC40,
+ 0x000A,0xFC8C,0x000A,0xFCAA,0x000A,0xFCD0,0x000A,0xFD0C,
+ 0x000A,0xFD12,0x000A,0xCE96,0x000A,0xCFA0,0x000A,0xD0AA,
+ 0x000A,0xD1B4,0x000A,0xD2BE,0x000A,0xD4FA,0x000A,0xD75A,
+ 0x000A,0xD9DA,0x000A,0xDC7A,0x000A,0xDC7A,0x000A,0xDC7A,
+ 0x000A,0xDC7A,0x000A,0xF31E,0x000A,0xF344,0x000A,0xF364,
+ 0x000A,0xF31E,0x000A,0xF344,0x000A,0xF39C,0x000A,0xF3A6,
+ 0x000B,0x272C,0x000B,0x274C,0x000B,0x284C,0x000B,0x2924
+};
+static UINT16 bloodwar_mcu_4_2c[] = { // Warrior 8
+ 0x000B,0x272C,0x000B,0x274C,0x000B,0x284C,0x000B,0x2924,
+ 0x000B,0x3242,0x000B,0x2A0E,0x000B,0x2A28,0x000B,0x2A48,
+ 0x000B,0x2B4C,0x000B,0x2C1A,0x000B,0x325E,0x000B,0x343A,
+ 0x000B,0x344C,0x000B,0x347E,0x000B,0x34B0,0x000B,0x351A,
+ 0x000B,0x352C,0x000B,0x355E,0x000B,0x3590,0x000B,0x34E2,
+ 0x000B,0x34F0,0x000B,0x34FE,0x000B,0x350C,0x000B,0x35C2,
+ 0x000B,0x35D0,0x000B,0x35DE,0x000B,0x35EC,0x000B,0x2D1A,
+ 0x000B,0x2D34,0x000B,0x2D66,0x000B,0x2DFE,0x000B,0x2E96,
+ 0x000B,0x2F2E,0x000B,0x2F66,0x000B,0x2FFE,0x000B,0x3096,
+ 0x000B,0x327A,0x000B,0x328C,0x000B,0x32BE,0x000B,0x32F0,
+ 0x000B,0x335A,0x000B,0x336C,0x000B,0x339E,0x000B,0x33D0,
+ 0x000B,0x3322,0x000B,0x3330,0x000B,0x333E,0x000B,0x334C,
+ 0x000B,0x3402,0x000B,0x3410,0x000B,0x341E,0x000B,0x342C,
+ 0x000B,0x312E,0x000B,0x3186,0x000B,0x31E4,0x000B,0x3142,
+ 0x000B,0x31A0,0x000B,0x31FE,0x000B,0x3172,0x000B,0x31D0,
+ 0x000B,0x322E,0x000B,0x3702,0x000B,0x373E,0x000B,0x37AE,
+
+ 0x000B,0x381E,0x000B,0x388E,0x000B,0x38D6,0x000B,0x397C,
+ 0x000B,0x3A22,0x000B,0x3AC8,0x000B,0x3B10,0x000B,0x3B86,
+ 0x000B,0x3BFC,0x000B,0x3C72,0x000B,0x3CC0,0x000B,0x3D6C,
+ 0x000B,0x3E18,0x000B,0x4D98,0x000B,0x4DD4,0x000B,0x4E44,
+ 0x000B,0x4EB4,0x000B,0x4F24,0x000B,0x4F78,0x000B,0x501A,
+ 0x000B,0x50BC,0x000B,0x515E,0x000B,0x51AC,0x000B,0x5212,
+ 0x000B,0x5278,0x000B,0x52DE,0x000B,0x5320,0x000B,0x53D0,
+ 0x000B,0x5480,0x000B,0x3EC4,0x000B,0x3EF4,0x000B,0x3F58,
+ 0x000B,0x3FBC,0x000B,0x4020,0x000B,0x405C,0x000B,0x4120,
+ 0x000B,0x41E4,0x000B,0x42A8,0x000B,0x42DE,0x000B,0x4348,
+ 0x000B,0x43B2,0x000B,0x441C,0x000B,0x4458,0x000B,0x44D8,
+ 0x000B,0x4558,0x000B,0x5530,0x000B,0x5560,0x000B,0x55C4,
+ 0x000B,0x5628,0x000B,0x568C,0x000B,0x56C8,0x000B,0x5782,
+ 0x000B,0x583C,0x000B,0x58F6,0x000B,0x594A,0x000B,0x59BC,
+ 0x000B,0x5A2E,0x000B,0x5AA0,0x000B,0x5AE8,0x000B,0x5B8E,
+ 0x000B,0x5C34,0x000B,0x45D8,0x000B,0x4624,0x000B,0x46D4,
+
+ 0x000B,0x4784,0x000B,0x4834,0x000B,0x4880,0x000B,0x48F0,
+ 0x000B,0x4960,0x000B,0x5CDA,0x000B,0x5D26,0x000B,0x5DD6,
+ 0x000B,0x5E86,0x000B,0x5F36,0x000B,0x5F82,0x000B,0x5FF2,
+ 0x000B,0x6062,0x000B,0x49D0,0x000B,0x4A10,0x000B,0x4AB4,
+ 0x000B,0x4B58,0x000B,0x4BFC,0x000B,0x4C48,0x000B,0x4CB8,
+ 0x000B,0x4D28,0x000B,0x60D2,0x000B,0x6112,0x000B,0x61B6,
+ 0x000B,0x625A,0x000B,0x62FE,0x000B,0x634A,0x000B,0x63BA,
+ 0x000B,0x642A,0x000B,0x35FA,0x000B,0x3666,0x000B,0x36D8,
+ 0x000B,0x6B1A,0x000B,0x6B26,0x000B,0x6B44,0x000B,0x6B6E,
+ 0x000B,0x6B7A,0x000B,0x6B98,0x000B,0x6BC2,0x000B,0x6BCE,
+ 0x000B,0x6BEC,0x000B,0x6C90,0x000B,0x6CA6,0x000B,0x6C16,
+ 0x000B,0x6C1E,0x000B,0x6CB2,0x000B,0x6EAE,0x000B,0x6D4A,
+ 0x000B,0x6DBE,0x000B,0x6E24,0x000B,0x6E6C,0x000B,0x6F5E,
+ 0x000B,0x7030,0x000B,0x73EE,0x000B,0x71FA,0x000B,0x75B8,
+ 0x000B,0x733A,0x000B,0x771A,0x000B,0x77F2,0x000B,0x78E4,
+ 0x000B,0x79D6,0x000B,0x7AC8,0x000B,0x7C40,0x000B,0x7D32,
+
+ 0x000B,0x7E24,0x000B,0x7F16,0x000B,0x84AE,0x000B,0x84CE,
+ 0x000B,0x850A,0x000B,0x8546,0x000B,0x8554,0x000B,0x8582,
+ 0x000B,0x85E2,0x000B,0x861E,0x000B,0x8624,0x000B,0x8652,
+ 0x000B,0x868E,0x000B,0x869C,0x000B,0x86BA,0x000B,0x86C8,
+ 0x000B,0x86E6,0x000B,0x8722,0x000B,0x877E,0x000B,0x87B8,
+ 0x000B,0x87C6,0x000B,0x87EC,0x000B,0x8828,0x000B,0x883E,
+ 0x000B,0x885C,0x000B,0x8898,0x000B,0x88EA,0x000B,0x8900,
+ 0x000B,0x891E,0x000B,0x8978,0x000B,0x897E,0x000B,0x899C,
+ 0x000B,0x89E8,0x000B,0x8A06,0x000B,0x8A2C,0x000B,0x8A68,
+ 0x000B,0x8A6E,0x000B,0x649A,0x000B,0x649A,0x000B,0x649A,
+ 0x000B,0x649A,0x000B,0x64D0,0x000B,0x65B6,0x000B,0x66DC,
+ 0x000B,0x6802,0x000B,0x6928,0x000B,0x698C,0x000B,0x6A08,
+ 0x000B,0x6A84,0x000B,0x693C,0x000B,0x69A0,0x000B,0x6A1C,
+ 0x000B,0x6A98,0x000B,0x6B00,0x000B,0x808E,0x000B,0x80A2,
+ 0x000B,0x80C8,0x000B,0x808E,0x000B,0x80A2,0x000B,0x811C,
+ 0x000B,0x813E,0x000B,0xB188,0x000B,0xB1C0,0x000B,0xB308
+};
+static UINT16 bloodwar_mcu_4_2d[] = { // Warrior 9
+ 0x0009,0x81A8,0x0009,0x81C8,0x0009,0x8270,0x0009,0x8328,
+ 0x0009,0x8A98,0x0009,0x8416,0x0009,0x8430,0x0009,0x8450,
+ 0x0009,0x84E8,0x0009,0x8580,0x0009,0x8AB4,0x0009,0x8C90,
+ 0x0009,0x8CA2,0x0009,0x8CD4,0x0009,0x8D06,0x0009,0x8D70,
+ 0x0009,0x8D82,0x0009,0x8DB4,0x0009,0x8DE6,0x0009,0x8D38,
+ 0x0009,0x8D46,0x0009,0x8D54,0x0009,0x8D62,0x0009,0x8E18,
+ 0x0009,0x8E26,0x0009,0x8E34,0x0009,0x8E42,0x0009,0x864E,
+ 0x0009,0x8668,0x0009,0x8694,0x0009,0x870C,0x0009,0x8784,
+ 0x0009,0x87FC,0x0009,0x8828,0x0009,0x88A0,0x0009,0x8918,
+ 0x0009,0x8AD0,0x0009,0x8AE2,0x0009,0x8B14,0x0009,0x8B46,
+ 0x0009,0x8BB0,0x0009,0x8BC2,0x0009,0x8BF4,0x0009,0x8C26,
+ 0x0009,0x8B78,0x0009,0x8B86,0x0009,0x8B94,0x0009,0x8BA2,
+ 0x0009,0x8C58,0x0009,0x8C66,0x0009,0x8C74,0x0009,0x8C82,
+ 0x0009,0x8990,0x0009,0x89EE,0x0009,0x8A46,0x0009,0x89A4,
+ 0x0009,0x8A02,0x0009,0x8A5A,0x0009,0x89DA,0x0009,0x8A32,
+ 0x0009,0x8A8A,0x0009,0x8F0E,0x0009,0x8F50,0x0009,0x8FB6,
+
+ 0x0009,0x901C,0x0009,0x9082,0x0009,0x90DC,0x0009,0x9184,
+ 0x0009,0x922C,0x0009,0x92D4,0x0009,0x9310,0x0009,0x9370,
+ 0x0009,0x93D0,0x0009,0x9430,0x0009,0x94A2,0x0009,0x9548,
+ 0x0009,0x95EE,0x0009,0xA4F0,0x0009,0xA520,0x0009,0xA574,
+ 0x0009,0xA5C8,0x0009,0xA61C,0x0009,0xA66A,0x0009,0xA716,
+ 0x0009,0xA7C2,0x0009,0xA86E,0x0009,0xA8B0,0x0009,0xA926,
+ 0x0009,0xA99C,0x0009,0xAA12,0x0009,0xAA78,0x0009,0xAB12,
+ 0x0009,0xABAC,0x0009,0x9694,0x0009,0x96D0,0x0009,0x9730,
+ 0x0009,0x9790,0x0009,0x97F0,0x0009,0x9838,0x0009,0x98DE,
+ 0x0009,0x9984,0x0009,0x9A2A,0x0009,0x9A66,0x0009,0x9AD6,
+ 0x0009,0x9B46,0x0009,0x9BB6,0x0009,0x9C16,0x0009,0x9CC4,
+ 0x0009,0x9D72,0x0009,0xAC46,0x0009,0xAC6A,0x0009,0xACB2,
+ 0x0009,0xACFA,0x0009,0xAD42,0x0009,0xAD84,0x0009,0xAE34,
+ 0x0009,0xAEE4,0x0009,0xAF94,0x0009,0xAFEC,0x0009,0xB05C,
+ 0x0009,0xB0CC,0x0009,0xB13C,0x0009,0xB196,0x0009,0xB248,
+ 0x0009,0xB2FA,0x0009,0x9E20,0x0009,0x9E54,0x0009,0x9EEC,
+
+ 0x0009,0x9F84,0x0009,0xA01C,0x0009,0xA050,0x0009,0xA0A8,
+ 0x0009,0xA100,0x0009,0xB3AC,0x0009,0xB3E0,0x0009,0xB478,
+ 0x0009,0xB510,0x0009,0xB5A8,0x0009,0xB5E8,0x0009,0xB64C,
+ 0x0009,0xB6B0,0x0009,0xA158,0x0009,0xA198,0x0009,0xA23C,
+ 0x0009,0xA2E0,0x0009,0xA384,0x0009,0xA3C4,0x0009,0xA428,
+ 0x0009,0xA48C,0x0009,0xB714,0x0009,0xB748,0x0009,0xB7E0,
+ 0x0009,0xB878,0x0009,0xB910,0x0009,0xB95C,0x0009,0xB9CC,
+ 0x0009,0xBA3C,0x0009,0x8E50,0x0009,0x8E82,0x0009,0x8ED2,
+ 0x0009,0xC388,0x0009,0xC394,0x0009,0xC3B2,0x0009,0xC3DC,
+ 0x0009,0xC3E8,0x0009,0xC406,0x0009,0xC430,0x0009,0xC43C,
+ 0x0009,0xC45A,0x0009,0xC4FE,0x0009,0xC514,0x0009,0xC484,
+ 0x0009,0xC48C,0x0009,0xC520,0x0009,0xC71C,0x0009,0xC5B8,
+ 0x0009,0xC62C,0x0009,0xC692,0x0009,0xC6DA,0x0009,0xC7CC,
+ 0x0009,0xC89E,0x0009,0xCC5C,0x0009,0xCA68,0x0009,0xCE26,
+ 0x0009,0xCBA8,0x0009,0xCF88,0x0009,0xD060,0x0009,0xD152,
+ 0x0009,0xD244,0x0009,0xD336,0x0009,0xD4AE,0x0009,0xD5A0,
+
+ 0x0009,0xD692,0x0009,0xD784,0x0009,0xDDC4,0x0009,0xDDE4,
+ 0x0009,0xDE20,0x0009,0xDE5C,0x0009,0xDE6A,0x0009,0xDE98,
+ 0x0009,0xDEF8,0x0009,0xDF34,0x0009,0xDF3A,0x0009,0xDF68,
+ 0x0009,0xDFA4,0x0009,0xDFB2,0x0009,0xDFD0,0x0009,0xDFDE,
+ 0x0009,0xDFFC,0x0009,0xE038,0x0009,0xE094,0x0009,0xE0CE,
+ 0x0009,0xE0DC,0x0009,0xE102,0x0009,0xE13E,0x0009,0xE154,
+ 0x0009,0xE172,0x0009,0xE1AE,0x0009,0xE200,0x0009,0xE216,
+ 0x0009,0xE234,0x0009,0xE28E,0x0009,0xE294,0x0009,0xE2B2,
+ 0x0009,0xE2FE,0x0009,0xE31C,0x0009,0xE342,0x0009,0xE37E,
+ 0x0009,0xE384,0x0009,0xBAAC,0x0009,0xBAAC,0x0009,0xBAAC,
+ 0x0009,0xBAAC,0x0009,0xBB44,0x0009,0xBC0C,0x0009,0xBCF4,
+ 0x0009,0xBDFC,0x0009,0xBF24,0x0009,0xC00E,0x0009,0xC040,
+ 0x0009,0xC124,0x0009,0xC156,0x0009,0xC240,0x0009,0xC272,
+ 0x0009,0xC356,0x0009,0xD8FC,0x0009,0xD910,0x0009,0xD936,
+ 0x0009,0xD8FC,0x0009,0xD910,0x0009,0xD96E,0x0009,0xD8FC,
+ 0x0009,0xD910,0x0009,0xD9B8,0x0009,0xD9D2,0x000A,0x0E3C
+};
diff --git a/src/mame/machine/konami.c b/src/mame/machine/konami.c
new file mode 100644
index 00000000000..6e2143187be
--- /dev/null
+++ b/src/mame/machine/konami.c
@@ -0,0 +1,67 @@
+/***************************************************************************
+
+ The Konami_1 CPU is a 6809 with opcodes scrambled. Here is how to
+ descramble them.
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+UINT8 *konami1_decrypted;
+
+UINT8 konami1_decodebyte( UINT8 opcode, UINT16 address )
+{
+/*
+>
+> CPU_D7 = (EPROM_D7 & ~ADDRESS_1) | (~EPROM_D7 & ADDRESS_1) >
+> CPU_D6 = EPROM_D6
+>
+> CPU_D5 = (EPROM_D5 & ADDRESS_1) | (~EPROM_D5 & ~ADDRESS_1) >
+> CPU_D4 = EPROM_D4
+>
+> CPU_D3 = (EPROM_D3 & ~ADDRESS_3) | (~EPROM_D3 & ADDRESS_3) >
+> CPU_D2 = EPROM_D2
+>
+> CPU_D1 = (EPROM_D1 & ADDRESS_3) | (~EPROM_D1 & ~ADDRESS_3) >
+> CPU_D0 = EPROM_D0
+>
+*/
+ UINT8 xormask;
+
+
+ xormask = 0;
+ if (address & 0x02) xormask |= 0x80;
+ else xormask |= 0x20;
+ if (address & 0x08) xormask |= 0x08;
+ else xormask |= 0x02;
+
+ return opcode ^ xormask;
+}
+
+
+
+static void decode(int cpu)
+{
+ UINT8 *rom = memory_region(REGION_CPU1+cpu);
+ int size = memory_region_length(REGION_CPU1+cpu);
+ int A;
+
+ konami1_decrypted = auto_malloc(size);
+ memory_set_decrypted_region(cpu, 0x0000, 0xffff, konami1_decrypted);
+
+ for (A = 0;A < size;A++)
+ {
+ konami1_decrypted[A] = konami1_decodebyte(rom[A],A);
+ }
+}
+
+void konami1_decode(void)
+{
+ decode(0);
+}
+
+void konami1_decode_cpu2(void)
+{
+ decode(1);
+}
diff --git a/src/mame/machine/konamigx.c b/src/mame/machine/konamigx.c
new file mode 100644
index 00000000000..ba336815a5b
--- /dev/null
+++ b/src/mame/machine/konamigx.c
@@ -0,0 +1,2247 @@
+#define VERBOSE 0
+#define GX_DEBUG 0
+
+/**************************************************************************
+ *
+ * machine/konamigx.c - contains various System GX hardware abstractions
+ *
+ * Currently includes: TMS57002 skipper/simulator to make the sound 68k happy.
+ *
+ */
+
+#include "driver.h"
+#include "video/konamiic.h"
+#include "machine/konamigx.h"
+#include <math.h>
+
+
+static struct
+{
+ UINT8 control;
+ UINT8 program[1024];
+ UINT32 tables[256];
+ int curpos;
+ int bytepos;
+ UINT32 tmp;
+} tms57002;
+
+static int ldw = 0;
+
+
+void tms57002_init(void)
+{
+ tms57002.control = 0;
+}
+
+static void chk_ldw(void)
+{
+ ldw = 0;
+}
+
+WRITE8_HANDLER( tms57002_control_w )
+{
+ chk_ldw();
+
+ switch(tms57002.control)
+ {
+ case 0xf8:
+ break;
+ case 0xf0:
+ break;
+ }
+
+ tms57002.control = data;
+
+ switch(data)
+ {
+ case 0xf8: // Program write
+ case 0xf0: // Table write
+ tms57002.curpos = 0;
+ tms57002.bytepos = 3;
+ tms57002.tmp = 0;
+ break;
+ case 0xf4: // Entry write
+ tms57002.curpos = -1;
+ tms57002.bytepos = 3;
+ tms57002.tmp = 0;
+ break;
+ case 0xfc: // Checksum (?) Status (?)
+ tms57002.bytepos = 3;
+ tms57002.tmp = 0;
+ break;
+ case 0xff: // Standby
+ break;
+ case 0xfe: // Irq
+ /* (place ack of timer IRQ here) */
+ break;
+ default:
+ break;
+ }
+}
+
+READ8_HANDLER( tms57002_status_r )
+{
+ chk_ldw();
+ return 1;
+}
+
+WRITE8_HANDLER( tms57002_data_w )
+{
+ switch(tms57002.control)
+ {
+ case 0xf8:
+ tms57002.program[tms57002.curpos++] = data;
+ break;
+ case 0xf0:
+ tms57002.tmp |= data << (8*tms57002.bytepos);
+ tms57002.bytepos--;
+ if (tms57002.bytepos < 0)
+ {
+ tms57002.bytepos = 3;
+ tms57002.tables[tms57002.curpos++] = tms57002.tmp;
+ tms57002.tmp = 0;
+ }
+ break;
+ case 0xf4:
+ if (tms57002.curpos == -1)
+ tms57002.curpos = data;
+ else
+ {
+ tms57002.tmp |= data << (8*tms57002.bytepos);
+ tms57002.bytepos--;
+
+ if (tms57002.bytepos < 0)
+ {
+ tms57002.bytepos = 3;
+ tms57002.tables[tms57002.curpos] = tms57002.tmp;
+ tms57002.tmp = 0;
+ tms57002.curpos = -1;
+ }
+ }
+ break;
+ default:
+ ldw++;
+ break;
+ }
+}
+
+READ8_HANDLER( tms57002_data_r )
+{
+ UINT8 res;
+
+ chk_ldw();
+
+ switch(tms57002.control)
+ {
+ case 0xfc:
+ res = tms57002.tmp >> (8*tms57002.bytepos);
+ tms57002.bytepos--;
+
+ if(tms57002.bytepos < 0) tms57002.bytepos = 3;
+ return res;
+ }
+
+ return 0;
+}
+
+
+READ16_HANDLER( tms57002_data_word_r )
+{
+ return(tms57002_data_r(0));
+}
+
+READ16_HANDLER( tms57002_status_word_r )
+{
+ return(tms57002_status_r(0));
+}
+
+WRITE16_HANDLER( tms57002_control_word_w )
+{
+ tms57002_control_w(0, data);
+}
+
+WRITE16_HANDLER( tms57002_data_word_w )
+{
+ tms57002_data_w(0, data);
+}
+
+
+
+/***************************************************************************/
+/* */
+/* 2nd-Tier GX/MW Graphics Functions */
+/* */
+/***************************************************************************/
+
+#if GX_DEBUG
+ #define GX_ZBUFW 512
+ #define GX_ZBUFH 384
+ #define GX_ZPAGESIZE 0x300000
+ #define GX_ZBUFSIZE 0x600000
+#else
+ #define GX_ZBUFW 384
+ #define GX_ZBUFH 224
+ #define GX_ZPAGESIZE 0x150000
+ #define GX_ZBUFSIZE 0x2a0000
+#endif
+
+static UINT8 *gx_objzbuf, *gx_shdzbuf;
+
+
+// Localized K053936/ROZ+
+#define K053936_MAX_CHIPS 2
+
+static rectangle K053936_cliprect[K053936_MAX_CHIPS] = {{0,0,0,0},{0,0,0,0}};
+static int K053936_offset[K053936_MAX_CHIPS][2] = {{0,0},{0,0}};
+static int K053936_clip_enabled[K053936_MAX_CHIPS] = {0,0};
+
+
+void K053936GP_set_offset(int chip, int xoffs, int yoffs) { K053936_offset[chip][0] = xoffs; K053936_offset[chip][1] = yoffs; }
+
+void K053936GP_clip_enable(int chip, int status) { K053936_clip_enabled[chip] = status; }
+
+void K053936GP_set_cliprect(int chip, int minx, int maxx, int miny, int maxy)
+{
+ rectangle *cliprect = &K053936_cliprect[chip];
+ cliprect->min_x = minx;
+ cliprect->max_x = maxx;
+ cliprect->min_y = miny;
+ cliprect->max_y = maxy;
+}
+
+INLINE void K053936GP_copyroz32clip( mame_bitmap *dst_bitmap, mame_bitmap *src_bitmap,
+ const rectangle *dst_cliprect, const rectangle *src_cliprect,
+ UINT32 _startx,UINT32 _starty,int _incxx,int _incxy,int _incyx,int _incyy,
+ int tilebpp, int blend, int clip )
+{
+ static const int colormask[8]={1,3,7,0xf,0x1f,0x3f,0x7f,0xff};
+
+ int cy, cx;
+ int ecx;
+ int src_pitch, incxy, incxx;
+ int src_minx, src_maxx, src_miny, src_maxy, cmask;
+ UINT16 *src_base;
+ const pen_t *pal_base;
+ UINT32 *dst_ptr;
+
+ int tx, dst_pitch;
+ UINT32 *dst_base;
+ int starty, incyy, startx, incyx, ty, sx, sy;
+
+ incxy = _incxy; incxx = _incxx; incyy = _incyy; incyx = _incyx;
+ starty = _starty; startx = _startx;
+
+ if (src_cliprect && clip) // set source clip range to some extreme values when disabled
+ {
+ src_minx = src_cliprect->min_x;
+ src_maxx = src_cliprect->max_x;
+ src_miny = src_cliprect->min_y;
+ src_maxy = src_cliprect->max_y;
+ }
+ else { src_minx = src_miny = -0x10000; src_maxx = src_maxy = 0x10000; }
+
+ if (dst_cliprect) // set target clip range
+ {
+ sx = dst_cliprect->min_x;
+ tx = dst_cliprect->max_x - sx + 1;
+ sy = dst_cliprect->min_y;
+ ty = dst_cliprect->max_y - sy + 1;
+
+ startx += sx * incxx + sy * incyx;
+ starty += sx * incxy + sy * incyy;
+ }
+ else { sx = sy = 0; tx = dst_bitmap->width; ty = dst_bitmap->height; }
+
+ // adjust entry points and other loop constants
+ dst_pitch = dst_bitmap->rowpixels;
+ dst_base = (UINT32*)dst_bitmap->base + sy * dst_pitch + sx + tx;
+ ecx = tx = -tx;
+
+ tilebpp = (tilebpp-1) & 7;
+ pal_base = Machine->remapped_colortable;
+ cmask = colormask[tilebpp];
+
+ src_pitch = src_bitmap->rowpixels;
+ src_base = src_bitmap->base;
+
+ dst_ptr = dst_base;
+ cy = starty;
+ cx = startx;
+
+ if (blend > 0)
+ {
+ dst_base += dst_pitch; // draw blended
+ starty += incyy;
+ startx += incyx;
+
+ do {
+ do {
+ int srcx = (cx >> 16) & 0x1fff;
+ int srcy = (cy >> 16) & 0x1fff;
+ int pixel;
+
+ cx += incxx;
+ cy += incxy;
+ if (srcx < src_minx || srcx > src_maxx || srcy < src_miny || srcy > src_maxy)
+ continue;
+
+ pixel = src_base[srcy * src_pitch + srcx];
+ if (!(pixel & cmask))
+ continue;
+
+ dst_ptr[ecx] = alpha_blend32(pal_base[pixel], dst_ptr[ecx]);
+ }
+ while (++ecx);
+
+ ecx = tx;
+ dst_ptr = dst_base; dst_base += dst_pitch;
+ cy = starty; starty += incyy;
+ cx = startx; startx += incyx;
+ } while (--ty);
+ }
+ else // draw solid
+ {
+ if (blend == 0)
+ {
+ dst_base += dst_pitch;
+ starty += incyy;
+ startx += incyx;
+ }
+ else
+ {
+ if ((sy & 1) ^ (blend & 1))
+ {
+ if (ty <= 1) return;
+
+ dst_ptr += dst_pitch;
+ cy += incyy;
+ cx += incyx;
+ }
+
+ if (ty > 1)
+ {
+ ty >>= 1;
+ dst_pitch <<= 1;
+ incyy <<= 1;
+ incyx <<= 1;
+
+ dst_base = dst_ptr + dst_pitch;
+ starty = cy + incyy;
+ startx = cx + incyx;
+ }
+ }
+
+ do {
+ do {
+ int srcx = (cx >> 16) & 0x1fff;
+ int srcy = (cy >> 16) & 0x1fff;
+ int pixel;
+
+ cx += incxx;
+ cy += incxy;
+ if (srcx < src_minx || srcx > src_maxx || srcy < src_miny || srcy > src_maxy)
+ continue;
+
+ pixel = src_base[srcy * src_pitch + srcx];
+ if (!(pixel & cmask))
+ continue;
+
+ dst_ptr[ecx] = pal_base[pixel];
+ }
+ while (++ecx);
+
+ ecx = tx;
+ dst_ptr = dst_base; dst_base += dst_pitch;
+ cy = starty; starty += incyy;
+ cx = startx; startx += incyx;
+ } while (--ty);
+ }
+}
+
+// adpoted from generic K053936_zoom_draw()
+static void K053936GP_zoom_draw(int chip, UINT16 *ctrl, UINT16 *linectrl,
+ mame_bitmap *bitmap, const rectangle *cliprect, tilemap *tmap,
+ int tilebpp, int blend)
+{
+ mame_bitmap *src_bitmap;
+ rectangle *src_cliprect;
+ UINT16 *lineaddr;
+
+ rectangle my_clip;
+ UINT32 startx, starty;
+ int incxx, incxy, incyx, incyy, y, maxy, clip;
+
+ src_bitmap = tilemap_get_pixmap(tmap);
+ src_cliprect = &K053936_cliprect[chip];
+ clip = K053936_clip_enabled[chip];
+
+ if (ctrl[0x07] & 0x0040) /* "super" mode */
+ {
+ my_clip.min_x = cliprect->min_x;
+ my_clip.max_x = cliprect->max_x;
+ y = cliprect->min_y;
+ maxy = cliprect->max_y;
+
+ while (y <= maxy)
+ {
+ lineaddr = linectrl + ( ((y - K053936_offset[chip][1]) & 0x1ff) << 2);
+ my_clip.min_y = my_clip.max_y = y;
+
+ startx = (INT16)(lineaddr[0] + ctrl[0x00]) << 8;
+ starty = (INT16)(lineaddr[1] + ctrl[0x01]) << 8;
+ incxx = (INT16)(lineaddr[2]);
+ incxy = (INT16)(lineaddr[3]);
+
+ if (ctrl[0x06] & 0x8000) incxx <<= 8;
+ if (ctrl[0x06] & 0x0080) incxy <<= 8;
+
+ startx -= K053936_offset[chip][0] * incxx;
+ starty -= K053936_offset[chip][0] * incxy;
+
+ K053936GP_copyroz32clip(bitmap, src_bitmap, &my_clip, src_cliprect,
+ startx<<5, starty<<5, incxx<<5, incxy<<5, 0, 0,
+ tilebpp, blend, clip);
+ y++;
+ }
+ }
+ else /* "simple" mode */
+ {
+ startx = (INT16)(ctrl[0x00]) << 8;
+ starty = (INT16)(ctrl[0x01]) << 8;
+ incyx = (INT16)(ctrl[0x02]);
+ incyy = (INT16)(ctrl[0x03]);
+ incxx = (INT16)(ctrl[0x04]);
+ incxy = (INT16)(ctrl[0x05]);
+
+ if (ctrl[0x06] & 0x4000) { incyx <<= 8; incyy <<= 8; }
+ if (ctrl[0x06] & 0x0040) { incxx <<= 8; incxy <<= 8; }
+
+ startx -= K053936_offset[chip][1] * incyx;
+ starty -= K053936_offset[chip][1] * incyy;
+
+ startx -= K053936_offset[chip][0] * incxx;
+ starty -= K053936_offset[chip][0] * incxy;
+
+ K053936GP_copyroz32clip(bitmap, src_bitmap, cliprect, src_cliprect,
+ startx<<5, starty<<5, incxx<<5, incxy<<5, incyx<<5, incyy<<5,
+ tilebpp, blend, clip);
+ }
+}
+
+void K053936GP_0_zoom_draw(mame_bitmap *bitmap, const rectangle *cliprect,
+ tilemap *tmap, int tilebpp, int blend)
+{
+ K053936GP_zoom_draw(0,K053936_0_ctrl,K053936_0_linectrl,bitmap,cliprect,tmap,tilebpp,blend);
+}
+
+void K053936GP_1_zoom_draw(mame_bitmap *bitmap, const rectangle *cliprect,
+ tilemap *tmap, int tilebpp, int blend)
+{
+ K053936GP_zoom_draw(1,K053936_1_ctrl,K053936_1_linectrl,bitmap,cliprect,tmap,tilebpp,blend);
+}
+
+
+
+/*
+ Parameter Notes
+ ---------------
+ clip : *caller must supply a pointer to target clip rectangle
+ alpha : 0 = invisible, 255 = solid
+ drawmode:
+ 0 = all pens solid
+ 1 = solid pens only
+ 2 = all pens solid with alpha blending
+ 3 = solid pens only with alpha blending
+ 4 = shadow pens only
+ 5 = all pens shadow
+ zcode : 0 = closest, 255 = furthest (pixel z-depth), -1 = disable depth buffers and shadows
+ pri : 0 = topmost, 255 = backmost (pixel priority)
+*/
+
+INLINE void zdrawgfxzoom32GP( mame_bitmap *bitmap, const gfx_element *gfx, const rectangle *cliprect,
+ UINT32 code, UINT32 color, int flipx, int flipy, int sx, int sy,
+ int scalex, int scaley, int alpha, int drawmode, int zcode, int pri)
+{
+#define FP 19
+#define FPONE (1<<FP)
+#define FPHALF (1<<(FP-1))
+#define FPENT 0
+
+ // inner loop
+ UINT8 *src_ptr;
+ int src_x;
+ int eax, ecx;
+ int src_fx, src_fdx;
+ int shdpen;
+ UINT8 z8, db0, p8, db1;
+ UINT8 *ozbuf_ptr;
+ UINT8 *szbuf_ptr;
+ const pen_t *pal_base;
+ const pen_t *shd_base;
+ UINT32 *dst_ptr;
+
+ // outter loop
+ int src_fby, src_fdy, src_fbx;
+ UINT8 *src_base;
+ int dst_w, dst_h;
+
+ // one-time
+ int nozoom, granularity;
+ int src_fw, src_fh;
+ int dst_minx, dst_maxx, dst_miny, dst_maxy;
+ int dst_skipx, dst_skipy, dst_x, dst_y, dst_lastx, dst_lasty;
+ int src_pitch, dst_pitch;
+
+
+ // cull illegal and transparent objects
+ if (!scalex || !scaley) return;
+
+ // find shadow pens and cull invisible shadows
+ granularity = shdpen = gfx->color_granularity;
+ shdpen--;
+
+ if (zcode >= 0)
+ {
+ if (drawmode == 5) { drawmode = 4; shdpen = 1; }
+ }
+ else
+ if (drawmode >= 4) return;
+
+ // alpha blend necessary?
+ if (drawmode & 2)
+ {
+ if (alpha <= 0) return;
+ if (alpha >= 255) drawmode &= ~2;
+ }
+
+ // fill internal data structure with default values
+ ozbuf_ptr = gx_objzbuf;
+ szbuf_ptr = gx_shdzbuf;
+
+ src_pitch = 16;
+ src_fw = 16;
+ src_fh = 16;
+ src_base = gfx->gfxdata + (code % gfx->total_elements) * gfx->char_modulo;
+
+ pal_base = Machine->remapped_colortable + gfx->color_base + (color % gfx->total_colors) * granularity;
+ shd_base = Machine->shadow_table;
+
+ dst_ptr = bitmap->base;
+ dst_pitch = bitmap->rowpixels;
+ dst_minx = cliprect->min_x;
+ dst_maxx = cliprect->max_x;
+ dst_miny = cliprect->min_y;
+ dst_maxy = cliprect->max_y;
+ dst_x = sx;
+ dst_y = sy;
+
+ // cull off-screen objects
+ if (dst_x > dst_maxx || dst_y > dst_maxy) return;
+ if ((nozoom = (scalex == 0x10000 && scaley == 0x10000)))
+ {
+ dst_h = dst_w = 16;
+ src_fdy = src_fdx = 1;
+ }
+ else
+ {
+ dst_w = ((scalex<<4)+0x8000)>>16;
+ dst_h = ((scaley<<4)+0x8000)>>16;
+ if (!dst_w || !dst_h) return;
+
+ src_fw <<= FP;
+ src_fh <<= FP;
+ src_fdx = src_fw / dst_w;
+ src_fdy = src_fh / dst_h;
+ }
+ dst_lastx = dst_x + dst_w - 1;
+ if (dst_lastx < dst_minx) return;
+ dst_lasty = dst_y + dst_h - 1;
+ if (dst_lasty < dst_miny) return;
+
+ // clip destination
+ dst_skipx = 0;
+ eax = dst_minx; if ((eax -= dst_x) > 0) { dst_skipx = eax; dst_w -= eax; dst_x = dst_minx; }
+ eax = dst_lastx; if ((eax -= dst_maxx) > 0) dst_w -= eax;
+ dst_skipy = 0;
+ eax = dst_miny; if ((eax -= dst_y) > 0) { dst_skipy = eax; dst_h -= eax; dst_y = dst_miny; }
+ eax = dst_lasty; if ((eax -= dst_maxy) > 0) dst_h -= eax;
+
+ // calculate zoom factors and clip source
+ if (nozoom)
+ {
+ if (!flipx) src_fbx = 0; else { src_fbx = src_fw - 1; src_fdx = -src_fdx; }
+ if (!flipy) src_fby = 0; else { src_fby = src_fh - 1; src_fdy = -src_fdy; src_pitch = -src_pitch; }
+ }
+ else
+ {
+ if (!flipx) src_fbx = FPENT; else { src_fbx = src_fw - FPENT - 1; src_fdx = -src_fdx; }
+ if (!flipy) src_fby = FPENT; else { src_fby = src_fh - FPENT - 1; src_fdy = -src_fdy; }
+ }
+ src_fbx += dst_skipx * src_fdx;
+ src_fby += dst_skipy * src_fdy;
+
+ // adjust insertion points and pre-entry constants
+ eax = (dst_y - dst_miny) * GX_ZBUFW + (dst_x - dst_minx) + dst_w;
+ db0 = z8 = (UINT8)zcode;
+ db1 = p8 = (UINT8)pri;
+ ozbuf_ptr += eax;
+ szbuf_ptr += eax << 1;
+ dst_ptr += dst_y * dst_pitch + dst_x + dst_w;
+ dst_w = -dst_w;
+
+ if (!nozoom)
+ {
+ ecx = src_fby; src_fby += src_fdy;
+ ecx >>= FP; src_fx = src_fbx;
+ src_x = src_fbx; src_fx += src_fdx;
+ ecx <<= 4; src_ptr = src_base;
+ src_x >>= FP; src_ptr += ecx;
+ ecx = dst_w;
+
+ if (zcode < 0) // no shadow and z-buffering
+ {
+ do {
+ do {
+ eax = src_ptr[src_x];
+ src_x = src_fx;
+ src_fx += src_fdx;
+ src_x >>= FP;
+ if (!eax || eax >= shdpen) continue;
+ dst_ptr [ecx] = pal_base[eax];
+ }
+ while (++ecx);
+
+ ecx = src_fby; src_fby += src_fdy;
+ dst_ptr += dst_pitch;
+ ecx >>= FP; src_fx = src_fbx;
+ src_x = src_fbx; src_fx += src_fdx;
+ ecx <<= 4; src_ptr = src_base;
+ src_x >>= FP; src_ptr += ecx;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ }
+ else
+ {
+ switch (drawmode)
+ {
+ case 0: // all pens solid
+ do {
+ do {
+ eax = src_ptr[src_x];
+ src_x = src_fx;
+ src_fx += src_fdx;
+ src_x >>= FP;
+ if (!eax || ozbuf_ptr[ecx] < z8) continue;
+ eax = pal_base[eax];
+ ozbuf_ptr[ecx] = z8;
+ dst_ptr [ecx] = eax;
+ }
+ while (++ecx);
+
+ ecx = src_fby; src_fby += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx >>= FP; src_fx = src_fbx;
+ src_x = src_fbx; src_fx += src_fdx;
+ ecx <<= 4; src_ptr = src_base;
+ src_x >>= FP; src_ptr += ecx;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 1: // solid pens only
+ do {
+ do {
+ eax = src_ptr[src_x];
+ src_x = src_fx;
+ src_fx += src_fdx;
+ src_x >>= FP;
+ if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
+ eax = pal_base[eax];
+ ozbuf_ptr[ecx] = z8;
+ dst_ptr [ecx] = eax;
+ }
+ while (++ecx);
+
+ ecx = src_fby; src_fby += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx >>= FP; src_fx = src_fbx;
+ src_x = src_fbx; src_fx += src_fdx;
+ ecx <<= 4; src_ptr = src_base;
+ src_x >>= FP; src_ptr += ecx;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 2: // all pens solid with alpha blending
+ do {
+ do {
+ eax = src_ptr[src_x];
+ src_x = src_fx;
+ src_fx += src_fdx;
+ src_x >>= FP;
+ if (!eax || ozbuf_ptr[ecx] < z8) continue;
+ ozbuf_ptr[ecx] = z8;
+
+ dst_ptr[ecx] = alpha_blend32(pal_base[eax], dst_ptr[ecx]);
+ }
+ while (++ecx);
+
+ ecx = src_fby; src_fby += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx >>= FP; src_fx = src_fbx;
+ src_x = src_fbx; src_fx += src_fdx;
+ ecx <<= 4; src_ptr = src_base;
+ src_x >>= FP; src_ptr += ecx;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 3: // solid pens only with alpha blending
+ do {
+ do {
+ eax = src_ptr[src_x];
+ src_x = src_fx;
+ src_fx += src_fdx;
+ src_x >>= FP;
+ if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
+ ozbuf_ptr[ecx] = z8;
+
+ dst_ptr[ecx] = alpha_blend32(pal_base[eax], dst_ptr[ecx]);
+ }
+ while (++ecx);
+
+ ecx = src_fby; src_fby += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx >>= FP; src_fx = src_fbx;
+ src_x = src_fbx; src_fx += src_fdx;
+ ecx <<= 4; src_ptr = src_base;
+ src_x >>= FP; src_ptr += ecx;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 4: // shadow pens only
+ do {
+ do {
+ eax = src_ptr[src_x];
+ src_x = src_fx;
+ src_fx += src_fdx;
+ src_x >>= FP;
+ if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
+ eax = dst_ptr[ecx];
+ szbuf_ptr[ecx*2] = z8;
+ szbuf_ptr[ecx*2+1] = p8;
+ eax = (eax>>9&0x7c00) | (eax>>6&0x03e0) | (eax>>3&0x001f);
+ dst_ptr[ecx] = shd_base[eax];
+ }
+ while (++ecx);
+
+ ecx = src_fby; src_fby += src_fdy;
+ szbuf_ptr += (GX_ZBUFW<<1);
+ dst_ptr += dst_pitch;
+ ecx >>= FP; src_fx = src_fbx;
+ src_x = src_fbx; src_fx += src_fdx;
+ ecx <<= 4; src_ptr = src_base;
+ src_x >>= FP; src_ptr += ecx;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+ } // switch (drawmode)
+ } // if (zcode < 0)
+ } // if (!nozoom)
+ else
+ {
+ src_ptr = src_base + (src_fby<<4) + src_fbx;
+ src_fdy = src_fdx * dst_w + src_pitch;
+ ecx = dst_w;
+
+ if (zcode < 0) // no shadow and z-buffering
+ {
+ do {
+ do {
+ eax = *src_ptr;
+ src_ptr += src_fdx;
+ if (!eax || eax >= shdpen) continue;
+ dst_ptr[ecx] = pal_base[eax];
+ }
+ while (++ecx);
+
+ src_ptr += src_fdy;
+ dst_ptr += dst_pitch;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ }
+ else
+ {
+ switch (drawmode)
+ {
+ case 0: // all pens solid
+ do {
+ do {
+ eax = *src_ptr;
+ src_ptr += src_fdx;
+ if (!eax || ozbuf_ptr[ecx] < z8) continue;
+ eax = pal_base[eax];
+ ozbuf_ptr[ecx] = z8;
+ dst_ptr[ecx] = eax;
+ }
+ while (++ecx);
+
+ src_ptr += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 1: // solid pens only
+ do {
+ do {
+ eax = *src_ptr;
+ src_ptr += src_fdx;
+ if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
+ eax = pal_base[eax];
+ ozbuf_ptr[ecx] = z8;
+ dst_ptr[ecx] = eax;
+ }
+ while (++ecx);
+
+ src_ptr += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 2: // all pens solid with alpha blending
+ do {
+ do {
+ eax = *src_ptr;
+ src_ptr += src_fdx;
+ if (!eax || ozbuf_ptr[ecx] < z8) continue;
+ ozbuf_ptr[ecx] = z8;
+
+ dst_ptr[ecx] = alpha_blend32(pal_base[eax], dst_ptr[ecx]);
+ }
+ while (++ecx);
+
+ src_ptr += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 3: // solid pens only with alpha blending
+ do {
+ do {
+ eax = *src_ptr;
+ src_ptr += src_fdx;
+ if (!eax || eax >= shdpen || ozbuf_ptr[ecx] < z8) continue;
+ ozbuf_ptr[ecx] = z8;
+
+ dst_ptr[ecx] = alpha_blend32(pal_base[eax], dst_ptr[ecx]);
+ }
+ while (++ecx);
+
+ src_ptr += src_fdy;
+ ozbuf_ptr += GX_ZBUFW;
+ dst_ptr += dst_pitch;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+
+ case 4: // shadow pens only
+ do {
+ do {
+ eax = *src_ptr;
+ src_ptr += src_fdx;
+ if (eax < shdpen || szbuf_ptr[ecx*2] < z8 || szbuf_ptr[ecx*2+1] <= p8) continue;
+ eax = dst_ptr[ecx];
+ szbuf_ptr[ecx*2] = z8;
+ szbuf_ptr[ecx*2+1] = p8;
+ eax = (eax>>9&0x7c00) | (eax>>6&0x03e0) | (eax>>3&0x001f);
+ dst_ptr[ecx] = shd_base[eax];
+ }
+ while (++ecx);
+
+ src_ptr += src_fdy;
+ szbuf_ptr += (GX_ZBUFW<<1);
+ dst_ptr += dst_pitch;
+ ecx = dst_w;
+ }
+ while (--dst_h);
+ break;
+ }
+ }
+ }
+#undef FP
+#undef FPONE
+#undef FPHALF
+#undef FPENT
+}
+
+
+
+/***************************************************************************/
+/* */
+/* 1st-Tier GX/MW Variables and Functions */
+/* */
+/***************************************************************************/
+
+// global system ports access
+UINT8 konamigx_wrport1_0, konamigx_wrport1_1;
+UINT16 konamigx_wrport2;
+
+// frequently used registers
+static int K053246_objset1;
+static int K053247_vrcbk[4];
+static int K053247_coreg, K053247_coregshift, K053247_opset;
+static int opri, oinprion;
+static int vcblk[6], ocblk;
+static int vinmix, vmixon, osinmix, osmixon;
+
+
+static void konamigx_precache_registers(void)
+{
+ // (see sprite color coding scheme on p.46 & 47)
+ static int coregmasks[5] = {0xf,0xe,0xc,0x8,0x0};
+ static int coregshifts[5]= {4,5,6,7,8};
+ int i;
+
+ K053246_objset1 = K053246_read_register(5);
+
+ i = K053247_read_register(0x8/2);
+ K053247_vrcbk[0] = (i & 0x000f) << 14;
+ K053247_vrcbk[1] = (i & 0x0f00) << 6;
+ i = K053247_read_register(0xa/2);
+ K053247_vrcbk[2] = (i & 0x000f) << 14;
+ K053247_vrcbk[3] = (i & 0x0f00) << 6;
+
+ // COREG == OBJSET2+1C == bit8-11 of OPSET ??? (see p.50 last table, needs p.49 to confirm)
+ K053247_opset = K053247_read_register(0xc/2);
+
+ i = K053247_opset & 7; if (i > 4) i = 4;
+
+ K053247_coreg = K053247_read_register(0xc/2)>>8 & 0xf;
+ K053247_coreg =(K053247_coreg & coregmasks[i]) << 12;
+
+ K053247_coregshift = coregshifts[i];
+
+ opri = K055555_read_register(K55_PRIINP_8);
+ oinprion = K055555_read_register(K55_OINPRI_ON);
+ vcblk[0] = K055555_read_register(K55_PALBASE_A);
+ vcblk[1] = K055555_read_register(K55_PALBASE_B);
+ vcblk[2] = K055555_read_register(K55_PALBASE_C);
+ vcblk[3] = K055555_read_register(K55_PALBASE_D);
+ vcblk[4] = K055555_read_register(K55_PALBASE_SUB1);
+ vcblk[5] = K055555_read_register(K55_PALBASE_SUB2);
+ ocblk = K055555_read_register(K55_PALBASE_OBJ);
+ vinmix = K055555_read_register(K55_BLEND_ENABLES);
+ vmixon = K055555_read_register(K55_VINMIX_ON);
+ osinmix = K055555_read_register(K55_OSBLEND_ENABLES);
+ osmixon = K055555_read_register(K55_OSBLEND_ON);
+}
+
+INLINE int K053247GX_combine_c18(int attrib) // (see p.46)
+{
+ int c18;
+
+ c18 = (attrib & 0xff)<<K053247_coregshift | K053247_coreg;
+
+ if (konamigx_wrport2 & 4) c18 &= 0x3fff; else
+ if (!(konamigx_wrport2 & 8)) c18 = (c18 & 0x3fff) | (attrib<<6 & 0xc000);
+
+ return(c18);
+}
+
+INLINE int K055555GX_decode_objcolor(int c18) // (see p.59 7.2.2)
+{
+ int ocb, opon;
+
+ opon = oinprion<<8 | 0xff;
+ ocb = (ocblk & 7) << 10;
+ c18 &= opon;
+ ocb &=~opon;
+
+ return((ocb | c18) >> K053247_coregshift);
+}
+
+INLINE int K055555GX_decode_inpri(int c18) // (see p.59 7.2.2)
+{
+ int op = opri;
+
+ c18 >>= 8;
+ op &= oinprion;
+ c18 &=~oinprion;
+
+ return(c18 | op);
+}
+
+void konamigx_type2_sprite_callback(int *code, int *color, int *priority)
+{
+ int num = *code;
+ int c18 = *color;
+
+ *code = K053247_vrcbk[num>>14] | (num & 0x3fff);
+ c18 = K053247GX_combine_c18(c18);
+ *color = K055555GX_decode_objcolor(c18);
+ *priority = K055555GX_decode_inpri(c18);
+}
+
+void konamigx_dragoonj_sprite_callback(int *code, int *color, int *priority)
+{
+ int num, op, pri, c18;
+
+ num = *code;
+ *code = K053247_vrcbk[num>>14] | (num & 0x3fff);
+
+ c18 = pri = *color;
+ op = opri;
+ pri = (pri & 0x200) ? 4 : pri>>4 & 0xf;
+ op &= oinprion;
+ pri &=~oinprion;
+ *priority = pri | op;
+
+ c18 = K053247GX_combine_c18(c18);
+ *color = K055555GX_decode_objcolor(c18);
+}
+
+void konamigx_salmndr2_sprite_callback(int *code, int *color, int *priority)
+{
+ int num, op, pri, c18;
+
+ num = *code;
+ *code = K053247_vrcbk[num>>14] | (num & 0x3fff);
+
+ c18 = pri = *color;
+ op = opri;
+ pri = pri>>4 & 0x3f;
+ op &= oinprion;
+ pri &=~oinprion;
+ *priority = pri | op;
+
+ c18 = K053247GX_combine_c18(c18);
+ *color = K055555GX_decode_objcolor(c18);
+}
+
+void konamigx_le2_sprite_callback(int *code, int *color, int *priority)
+{
+ int num, op, pri;
+
+ num = *code;
+ *code = K053247_vrcbk[num>>14] | (num & 0x3fff);
+
+ pri = *color;
+ *color &= 0x1f;
+
+ op = opri;
+ pri &= 0xf0;
+ op &= oinprion;
+ pri &=~oinprion;
+ *priority = pri | op;
+}
+
+int K055555GX_decode_vmixcolor(int layer, int *color) // (see p.62 7.2.6 and p.27 3.3)
+{
+ int vcb, shift, pal, vmx, von, pl45, emx;
+
+ vcb = vcblk[layer]<<6;
+ shift = layer<<1;
+ pal = *color;
+ vmx = vinmix>>shift & 3;
+ von = vmixon>>shift & 3;
+ emx = pl45 = pal>>4 & 3;
+ pal &= 0xf;
+ pl45 &= von;
+ vmx &= von;
+ pl45 <<= 4;
+ emx &= ~von;
+ pal |= pl45;
+ emx |= vmx;
+ pal |= vcb;
+
+ if (von == 3) emx = -1; // invalidate external mix code if all bits are from internal
+ *color = pal;
+
+ return(emx);
+}
+
+int K055555GX_decode_osmixcolor(int layer, int *color) // (see p.63, p.49-50 and p.27 3.3)
+{
+ int scb, shift, pal, osmx, oson, pl45, emx;
+
+ shift = layer<<1;
+ pal = *color;
+ osmx = osinmix>>shift & 3;
+ oson = osmixon>>shift & 3;
+
+ if (layer)
+ {
+ // layer 1-3 are external tile layers
+ scb = vcblk[layer+3]<<6;
+ emx = pl45 = pal>>4 & 3;
+ pal &= 0xf;
+ pl45 &= oson;
+ osmx &= oson;
+ pl45 <<= 4;
+ emx &= ~oson;
+ pal |= pl45;
+ emx |= osmx;
+ pal |= scb;
+
+ if (oson == 3) emx = -1; // invalidate external mix code if all bits are from internal
+ *color = pal;
+ }
+ else
+ {
+ // layer 0 is the sprite layer with different attributes decode; detail on p.49 (missing)
+ emx = 0; // K053247_read_register(??)>>? & 3;
+ osmx &= oson;
+ emx &=~oson;
+ emx |= osmx;
+ }
+
+ return(emx);
+}
+
+static void gx_wipezbuf(int noshadow)
+{
+ UINT8 *zptr;
+ int w, h;
+ register int ecx;
+
+ w = Machine->screen[0].visarea.max_x - Machine->screen[0].visarea.min_x + 1;
+ h = Machine->screen[0].visarea.max_y - Machine->screen[0].visarea.min_y + 1;
+
+ zptr = gx_objzbuf;
+ ecx = h;
+ do { memset(zptr, -1, w); zptr += GX_ZBUFW; } while (--ecx);
+
+ if (!noshadow)
+ {
+ zptr = gx_shdzbuf;
+ w <<= 1;
+ ecx = h;
+ do { memset(zptr, -1, w); zptr += (GX_ZBUFW<<1); } while (--ecx);
+ }
+}
+
+/*
+ * Sprite Format
+ * ------------------
+ *
+ * Word | Bit(s) | Use
+ * -----+-fedcba9876543210-+----------------
+ * 0 | x--------------- | active (show this sprite)
+ * 0 | -x-------------- | maintain aspect ratio (when set, zoom y acts on both axis)
+ * 0 | --x------------- | flip y
+ * 0 | ---x------------ | flip x
+ * 0 | ----xxxx-------- | sprite size (see below)
+ * 0 | --------xxxxxxxx | zcode
+ * 1 | xxxxxxxxxxxxxxxx | sprite code
+ * 2 | ------xxxxxxxxxx | y position
+ * 3 | ------xxxxxxxxxx | x position
+ * 4 | xxxxxxxxxxxxxxxx | zoom y (0x40 = normal, <0x40 = enlarge, >0x40 = reduce)
+ * 5 | xxxxxxxxxxxxxxxx | zoom x (0x40 = normal, <0x40 = enlarge, >0x40 = reduce)
+ * 6 | x--------------- | mirror y (top half is drawn as mirror image of the bottom)
+ * 6 | -x-------------- | mirror x (right half is drawn as mirror image of the left)
+ * 6 | --xx------------ | reserved (sprites with these two bits set don't seem to be graphics data at all)
+ * 6 | ----xx---------- | shadow code: 0=off, 0x400=preset1, 0x800=preset2, 0xc00=preset3
+ * 6 | ------xx-------- | effect code: flicker, upper palette, full shadow...etc. (game dependent)
+ * 6 | --------xxxxxxxx | "color", but depends on external connections (implies priority)
+ * 7 | xxxxxxxxxxxxxxxx | game dependent
+ *
+ * shadow enables transparent shadows. Note that it applies to the last sprite pen ONLY.
+ * The rest of the sprite remains normal.
+ */
+#define GX_MAX_SPRITES 512
+#define GX_MAX_LAYERS 6
+#define GX_MAX_OBJECTS (GX_MAX_SPRITES + GX_MAX_LAYERS)
+
+static struct GX_OBJ { int order, offs, code, color; } *gx_objpool;
+static UINT16 *gx_spriteram;
+static int gx_objdma, gx_primode;
+
+// mirrored K053247 and K054338 settings
+static UINT16 *K053247_ram;
+static gfx_element *K053247_gfx;
+static void (*K053247_callback)(int *code,int *color,int *priority);
+static int K053247_dx, K053247_dy;
+
+static int *K054338_shdRGB;
+
+
+void K053247GP_set_SpriteOffset(int offsx, int offsy)
+{
+ K053247_dx = offsx;
+ K053247_dy = offsy;
+}
+
+void konamigx_mixer_init(int objdma)
+{
+ gx_objdma = 0;
+ gx_primode = 0;
+
+ gx_objzbuf = (UINT8 *)priority_bitmap->base;
+ gx_shdzbuf = auto_malloc(GX_ZBUFSIZE);
+ gx_objpool = auto_malloc(sizeof(struct GX_OBJ) * (GX_MAX_OBJECTS));
+
+ K053247_export_config(&K053247_ram, &K053247_gfx, &K053247_callback, &K053247_dx, &K053247_dy);
+ K054338_export_config(&K054338_shdRGB);
+
+ if (objdma)
+ {
+ gx_spriteram = auto_malloc(0x1000);
+ gx_objdma = 1;
+ }
+ else
+ gx_spriteram = K053247_ram;
+
+ palette_set_shadow_dRGB32(Machine, 3,-80,-80,-80, 0);
+ K054338_invert_alpha(1);
+}
+
+void konamigx_mixer_primode(int mode)
+{
+ gx_primode = mode;
+}
+
+void konamigx_objdma(void)
+{
+ if (gx_objdma && gx_spriteram && K053247_ram) memcpy(gx_spriteram, K053247_ram, 0x1000);
+}
+
+void konamigx_mixer(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect,
+ tilemap *sub1, int sub1flags,
+ tilemap *sub2, int sub2flags,
+ int mixerflags)
+{
+ static int xoffset[8] = { 0, 1, 4, 5, 16, 17, 20, 21 };
+ static int yoffset[8] = { 0, 2, 8, 10, 32, 34, 40, 42 };
+ static int parity = 0;
+
+ int objbuf[GX_MAX_OBJECTS];
+ int shadowon[3], shdpri[3], layerid[6], layerpri[6];
+
+ struct GX_OBJ *objpool, *objptr;
+ int wrapsize, xwraplim, ywraplim, cltc_shdpri, prflp, disp;
+ int xa,ya,ox,oy,zw,zh,flipx,flipy,mirrorx,mirrory,zoomx,zoomy,scalex,scaley,nozoom;
+ int screenwidth, flipscreenx, flipscreeny, offx, offy;
+ int nobj, i, j, k, l, temp, temp1, temp2, temp3, temp4, count;
+ int order, offs, code, color, zcode, pri = 0, spri, spri_min, shdprisel, shadow, alpha, drawmode;
+
+
+ // abort if object database failed to initialize
+ if (!(objpool = gx_objpool)) return;
+
+ // clear screen with backcolor and update flicker pulse
+ K054338_fill_backcolor(machine, bitmap, konamigx_wrport1_0 & 0x20);
+ parity ^= 1;
+
+ // abort if video has been disabled
+ if (!(disp = K055555_read_register(K55_INPUT_ENABLES))) return;
+ cltc_shdpri = K054338_read_register(K338_REG_CONTROL);
+ if (!(cltc_shdpri & K338_CTL_KILL)) return;
+
+ // demote shadows by one layer when this bit is set??? (see p.73 8.6)
+ cltc_shdpri &= K338_CTL_SHDPRI;
+
+ // wipe z-buffer
+ if (mixerflags & GXMIX_NOZBUF)
+ mixerflags |= GXMIX_NOSHADOW;
+ else
+ gx_wipezbuf(mixerflags & GXMIX_NOSHADOW);
+
+ // cache global parameters
+ konamigx_precache_registers();
+
+ // init OBJSET1 parameters (see p.47 6.2)
+ flipscreenx = K053246_objset1 & 1;
+ flipscreeny = K053246_objset1 & 2;
+
+ // get "display window" offsets
+ offx = (K053246_read_register(0)<<8 | K053246_read_register(1)) & 0x3ff;
+ offy = (K053246_read_register(2)<<8 | K053246_read_register(3)) & 0x3ff;
+
+ // init OBJSET2 and mixer parameters (see p.51 and chapter 7)
+ layerid[0] = 0; layerid[1] = 1; layerid[2] = 2; layerid[3] = 3; layerid[4] = 4; layerid[5] = 5;
+
+ if (K053247_opset & 0x40)
+ {
+ wrapsize = 512;
+ xwraplim = 512 - 64;
+ ywraplim = 512 - 128;
+ }
+ else
+ {
+ wrapsize = 1024;
+ xwraplim = 1024 - 384;
+ ywraplim = 1024 - 512;
+ }
+
+ // invert layer priority when this flag is set (not used by any GX game?)
+ prflp = K055555_read_register(K55_CONTROL) & K55_CTL_FLIPPRI;
+
+ layerpri[0] = K055555_read_register(K55_PRIINP_0);
+ layerpri[1] = K055555_read_register(K55_PRIINP_3);
+ layerpri[3] = K055555_read_register(K55_PRIINP_7);
+ layerpri[4] = K055555_read_register(K55_PRIINP_9);
+ layerpri[5] = K055555_read_register(K55_PRIINP_10);
+
+ if (gx_primode == -1)
+ {
+ // Lethal Enforcer hack (requires pixel color comparison)
+ layerpri[2] = K055555_read_register(K55_PRIINP_3) + 0x20;
+ shdprisel = 0x3f;
+ }
+ else
+ {
+ layerpri[2] = K055555_read_register(K55_PRIINP_6);
+ shdprisel = K055555_read_register(K55_SHD_PRI_SEL);
+ }
+
+ // SHDPRISEL filters shadows by different priority comparison methods (UNIMPLEMENTED, see detail on p.66)
+ if (!(shdprisel & 0x03)) shadowon[0] = 0;
+ if (!(shdprisel & 0x0c)) shadowon[1] = 0;
+ if (!(shdprisel & 0x30)) shadowon[2] = 0;
+
+ shdpri[0] = K055555_read_register(K55_SHAD1_PRI);
+ shdpri[1] = K055555_read_register(K55_SHAD2_PRI);
+ shdpri[2] = K055555_read_register(K55_SHAD3_PRI);
+
+ spri_min = 0;
+ shadowon[2] = shadowon[1] = shadowon[0] = 0;
+
+ if (!(mixerflags & GXMIX_NOSHADOW))
+ {
+ // only enable shadows beyond a +/-7 RGB threshold
+ for (j=0,i=0; i<3; j+=3,i++)
+ {
+ k = K054338_shdRGB[j ]; if (k < -7 || k > 7) { shadowon[i] = 1; continue; }
+ k = K054338_shdRGB[j+1]; if (k < -7 || k > 7) { shadowon[i] = 1; continue; }
+ k = K054338_shdRGB[j+2]; if (k < -7 || k > 7) { shadowon[i] = 1; }
+ }
+
+ // SHDON specifies layers on which shadows can be projected (see detail on p.65 7.2.8)
+ temp = K055555_read_register(K55_SHD_ON);
+ for (i=0; i<4; i++) if (!(temp>>i & 1) && spri_min < layerpri[i]) spri_min = layerpri[i]; // HACK
+
+ // update shadows status
+ K054338_update_all_shadows(machine);
+ }
+
+ // pre-sort layers
+ for (j=0; j<5; j++)
+ {
+ temp1 = layerpri[j];
+ for (i=j+1; i<6; i++)
+ {
+ temp2 = layerpri[i];
+ if ((UINT32)temp1 <= (UINT32)temp2)
+ {
+ layerpri[i] = temp1; layerpri[j] = temp1 = temp2;
+ temp2 = layerid[i]; layerid[i] = layerid[j]; layerid[j] = temp2;
+ }
+ }
+ }
+
+ // build object database and create indices
+ objptr = objpool;
+ nobj = 0;
+
+ for (i=5; i>=0; i--)
+ {
+ code = layerid[i];
+ switch (code)
+ {
+ /*
+ Background layers are represented by negative offset values as follow:
+
+ 0+ : normal sprites
+ -1 : tile layer A - D
+ -2 : K053936 ROZ+ layer 1
+ -3 : K053936 ROZ+ layer 2
+ -4 : K053250 LVC layer 1
+ -5 : K053250 LVC layer 2
+ */
+ case 4 :
+ offs = -128;
+ if (sub1flags & 0xf) { if (sub1flags & GXSUB_K053250) offs = -4; else if (sub1) offs = -2; }
+ break;
+ case 5 :
+ offs = -128;
+ if (sub2flags & 0xf) { if (sub2flags & GXSUB_K053250) offs = -5; else if (sub2) offs = -3; }
+ break;
+ default: offs = -1;
+ }
+
+ if (offs != -128)
+ {
+ objptr->order = layerpri[i]<<24;
+ objptr->code = code;
+ objptr->offs = offs;
+ objptr++;
+
+ objbuf[nobj] = nobj;
+ nobj++;
+ }
+ }
+
+ i = j = 0xff;
+
+ for (offs=0; offs<0x800; offs+=8)
+ {
+ if (!(gx_spriteram[offs] & 0x8000)) continue;
+
+ zcode = gx_spriteram[offs] & 0xff;
+
+ // invert z-order when opset_pri is set (see p.51 OPSET PRI)
+ if (K053247_opset & 0x10) zcode = 0xff - zcode;
+
+ code = gx_spriteram[offs+1];
+ color = k = gx_spriteram[offs+6];
+ l = gx_spriteram[offs+7];
+
+ (*K053247_callback)(&code, &color, &pri);
+
+ /*
+ shadow = shadow code
+ spri = shadow priority
+ temp1 = add solid object
+ temp2 = solid pens draw mode
+ temp3 = add shadow object
+ temp4 = shadow pens draw mode
+ */
+ temp4 = temp3 = temp2 = temp1 = spri = shadow = 0;
+
+ if (color & K055555_FULLSHADOW)
+ {
+ shadow = 3; // use default intensity and color
+ spri = pri; // retain host priority
+ temp3 = 1; // add shadow
+ temp4 = 5; // draw full shadow
+ }
+ else
+ {
+ if ((shadow = k>>10 & 3)) // object has shadow?
+ {
+ if (shadow != 1 || K053246_objset1 & 0x20)
+ {
+ shadow--;
+ temp1 = 1; // add solid
+ temp2 = 1; // draw partial solid
+ if (shadowon[shadow])
+ {
+ temp3 = 1; // add shadow
+ temp4 = 4; // draw partial shadow
+ }
+ }
+ else
+ {
+ // drop the entire sprite to shadow if its shadow code is 1 and SD0EN is off (see p.48)
+ shadow = 0;
+ if (!shadowon[0]) continue;
+ temp3 = 1; // add shadow
+ temp4 = 5; // draw full shadow
+ }
+ }
+ else
+ {
+ temp1 = 1; // add solid
+ temp2 = 0; // draw full solid
+ }
+
+ if (temp1)
+ {
+ // tag sprite for alpha blending
+ if (color>>K055555_MIXSHIFT & 3) temp2 |= 2;
+ }
+
+ if (temp3)
+ {
+ // determine shadow priority
+ spri = (K053247_opset & 0x20) ? pri : shdpri[shadow]; // (see p.51 OPSET SDSEL)
+ }
+ }
+
+ switch (gx_primode & 0xf)
+ {
+ // Dadandarn zcode suppression
+ case 1:
+ zcode = 0;
+ break;
+
+ // Daisukiss bad shadow filter
+ case 4:
+ if (k & 0x3000 || k == 0x0800) continue;
+
+ // Tokkae shadow masking (INACCURATE)
+ case 5:
+ if (spri < spri_min) spri = spri_min;
+ break;
+ }
+
+ /*
+ default sort order:
+ fedcba9876543210fedcba9876543210
+ xxxxxxxx------------------------ (priority)
+ --------xxxxxxxx---------------- (zcode)
+ ----------------xxxxxxxx-------- (offset)
+ ------------------------xxxx---- (shadow mode)
+ ----------------------------xxxx (shadow code)
+ */
+ if (temp1)
+ {
+ // add objects with solid or alpha pens
+ order = pri<<24 | zcode<<16 | offs<<(8-3) | temp2<<4;
+ objptr->order = order;
+ objptr->offs = offs;
+ objptr->code = code;
+ objptr->color = color;
+ objptr++;
+
+ objbuf[nobj] = nobj;
+ nobj++;
+ }
+
+ if (temp3 && !(color & K055555_SKIPSHADOW) && !(mixerflags & GXMIX_NOSHADOW))
+ {
+ // add objects with shadows if enabled
+ order = spri<<24 | zcode<<16 | offs<<(8-3) | temp4<<4 | shadow;
+ objptr->order = order;
+ objptr->offs = offs;
+ objptr->code = code;
+ objptr->color = color;
+ objptr++;
+
+ objbuf[nobj] = nobj;
+ nobj++;
+ }
+ }
+
+ // sort objects in decending order (SLOW)
+ k = nobj;
+ l = nobj - 1;
+
+ for (j=0; j<l; j++)
+ {
+ temp1 = objbuf[j];
+ temp2 = objpool[temp1].order;
+ for (i=j+1; i<k; i++)
+ {
+ temp3 = objbuf[i];
+ temp4 = objpool[temp3].order;
+ if ((UINT32)temp2 <= (UINT32)temp4) { temp2 = temp4; objbuf[i] = temp1; objbuf[j] = temp1 = temp3; }
+ }
+ }
+
+ // traverse draw list
+ screenwidth = Machine->screen[0].width;
+
+ for (count=0; count<nobj; count++)
+ {
+ objptr = objpool + objbuf[count];
+ order = objptr->order;
+ offs = objptr->offs;
+ code = objptr->code;
+ color = objptr->color;
+
+ if (offs >= 0)
+ {
+ if (!(disp & K55_INP_OBJ)) continue;
+ }
+ else
+ {
+ i = code<<1;
+ j = mixerflags>>i & 3;
+ k = 0;
+
+ switch (offs)
+ {
+ case -1:
+ if (disp & (1<<code))
+ {
+ if (j == GXMIX_BLEND_NONE) { temp1 = 0xff; temp2 = temp3 = 0; } else
+ if (j == GXMIX_BLEND_FORCE) { temp1 = 0x00; temp2 = mixerflags>>(i+16); temp3 = 3; }
+ else
+ {
+ temp1 = vinmix;
+ temp2 = vinmix>>i & 3;
+ temp3 = vmixon>>i & 3;
+ }
+
+ /* blend layer only when:
+ 1) vinmix != 0xff
+ 2) its internal mix code is set
+ 3) all mix code bits are internal(overriden until tile blending has been implemented)
+ 4) 0 > alpha < 255;
+ */
+ if (temp1!=0xff && temp2 /*&& temp3==3*/)
+ {
+ temp4 = K054338_set_alpha_level(temp2);
+
+ if (temp4 <= 0) continue;
+ if (temp4 < 255) k = TILEMAP_DRAW_ALPHA;
+ }
+
+ if (mixerflags & 1<<(code+12)) k |= TILE_LINE_DISABLED;
+
+ K056832_tilemap_draw(machine, bitmap, cliprect, code, k, 0);
+ }
+ continue;
+ case -2:
+ case -4:
+ if (disp & K55_INP_SUB1)
+ {
+ if (j == GXMIX_BLEND_NONE) { temp1 = 0xff; temp2 = temp3 = 0; } else
+ if (j == GXMIX_BLEND_FORCE) { temp1 = 0x00; temp2 = mixerflags>>24; temp3 = 3; }
+ else
+ {
+ temp1 = osinmix;
+ temp2 = osinmix>>2 & 3;
+ temp3 = osmixon>>2 & 3;
+ }
+
+ if (temp1!=0xff && temp2 /*&& temp3==3*/)
+ {
+ temp4 = K054338_set_alpha_level(temp2);
+
+ if (temp4 <= 0) continue;
+ if (temp4 < 255) k = (j == GXMIX_BLEND_FAST) ? ~parity : 1;
+ }
+
+ l = sub1flags & 0xf;
+
+ if (offs == -2)
+ K053936GP_0_zoom_draw(bitmap, cliprect, sub1, l, k);
+ else
+ K053250_draw(machine, bitmap, cliprect, 0, vcblk[4]<<l, 0, 0);
+ }
+ continue;
+ case -3:
+ case -5:
+ if (disp & K55_INP_SUB2)
+ {
+ if (j == GXMIX_BLEND_NONE) { temp1 = 0xff; temp2 = temp3 = 0; } else
+ if (j == GXMIX_BLEND_FORCE) { temp1 = 0x00; temp2 = mixerflags>>26; temp3 = 3; }
+ else
+ {
+ temp1 = osinmix;
+ temp2 = osinmix>>4 & 3;
+ temp3 = osmixon>>4 & 3;
+ }
+
+ if (temp1!=0xff && temp2 /*&& temp3==3*/)
+ {
+ temp4 = K054338_set_alpha_level(temp2);
+
+ if (temp4 <= 0) continue;
+ if (temp4 < 255) k = (j == GXMIX_BLEND_FAST) ? ~parity : 1;
+ }
+
+ l = sub2flags & 0xf;
+
+ if (offs == -3)
+ K053936GP_1_zoom_draw(bitmap, cliprect, sub2, l, k);
+ else
+ K053250_draw(machine, bitmap, cliprect, 1, vcblk[5]<<l, 0, 0);
+ }
+ continue;
+ }
+ continue;
+ }
+
+ drawmode = order>>4 & 0xf;
+
+ alpha = 255;
+ if (drawmode & 2)
+ {
+ if ((alpha = color>>K055555_MIXSHIFT & 3)) alpha = K054338_set_alpha_level(alpha);
+ if (alpha <= 0) continue;
+ }
+ color &= K055555_COLORMASK;
+
+ if (drawmode >= 4) palette_set_shadow_mode(Machine, order & 0x0f);
+
+ if (!(mixerflags & GXMIX_NOZBUF))
+ {
+ zcode = order>>16 & 0xff;
+ pri = order>>24 & 0xff;
+ }
+ else
+ zcode = -1; // negative zcode values turn off z-buffering
+
+ xa = ya = 0;
+ if (code & 0x01) xa += 1;
+ if (code & 0x02) ya += 1;
+ if (code & 0x04) xa += 2;
+ if (code & 0x08) ya += 2;
+ if (code & 0x10) xa += 4;
+ if (code & 0x20) ya += 4;
+ code &= ~0x3f;
+
+ temp4 = gx_spriteram[offs];
+
+ // mask off the upper 6 bits of coordinate and zoom registers
+ oy = gx_spriteram[offs+2] & 0x3ff;
+ ox = gx_spriteram[offs+3] & 0x3ff;
+
+ scaley = zoomy = gx_spriteram[offs+4] & 0x3ff;
+ if (zoomy) zoomy = (0x400000+(zoomy>>1)) / zoomy;
+ else zoomy = 0x800000;
+ if (!(temp4 & 0x4000))
+ {
+ scalex = zoomx = gx_spriteram[offs+5] & 0x3ff;
+ if (zoomx) zoomx = (0x400000+(zoomx>>1)) / zoomx;
+ else zoomx = 0x800000;
+ }
+ else { zoomx = zoomy; scalex = scaley; }
+
+ nozoom = (scalex == 0x40 && scaley == 0x40);
+
+ flipx = temp4 & 0x1000;
+ flipy = temp4 & 0x2000;
+
+ temp = gx_spriteram[offs+6];
+ mirrorx = temp & 0x4000;
+ if (mirrorx) flipx = 0; // only applies to x mirror, proven
+ mirrory = temp & 0x8000;
+
+ // for Escape Kids (GX975)
+ if ( K053246_objset1 & 8 ) // Check only "Bit #3 is '1'?"
+ {
+ zoomx = zoomx>>1; // Fix sprite width to HALF size
+ ox = (ox>>1) + 1; // Fix sprite draw position
+
+ if (flipscreenx) ox += screenwidth;
+ }
+
+ if (flipscreenx) { ox = -ox; if (!mirrorx) flipx = !flipx; }
+ if (flipscreeny) { oy = -oy; if (!mirrory) flipy = !flipy; }
+
+ // apply wrapping and global offsets
+ temp = wrapsize-1;
+ ox = ( ox - offx) & temp;
+ oy = (-oy - offy) & temp;
+ if (ox >= xwraplim) ox -= wrapsize;
+ if (oy >= ywraplim) oy -= wrapsize;
+ ox += K053247_dx;
+ oy += K053247_dy;
+
+
+ temp = temp4>>8 & 0x0f;
+ k = 1 << (temp & 3);
+ l = 1 << (temp>>2 & 3);
+
+ ox -= (zoomx * k) >> 13;
+ oy -= (zoomy * l) >> 13;
+
+ // substitutes: i=x, j=y, k=w, l=h, temp=code, temp1=fx, temp2=fy, temp3=sx, temp4=sy;
+ for (j=0; j<l; j++)
+ {
+ temp4 = oy + ((zoomy * j + (1<<11)) >> 12);
+ zh = (oy + ((zoomy * (j+1) + (1<<11)) >> 12)) - temp4;
+
+ for (i=0; i<k; i++)
+ {
+ temp3 = ox + ((zoomx * i + (1<<11)) >> 12);
+ zw = (ox + ((zoomx * (i+1) + (1<<11)) >> 12)) - temp3;
+ temp = code;
+
+ if (mirrorx)
+ {
+ if ((!flipx)^((i<<1)<k))
+ {
+ /* mirror left/right */
+ temp += xoffset[(k-1-i+xa)&7];
+ temp1 = 1;
+ }
+ else
+ {
+ temp += xoffset[(i+xa)&7];
+ temp1 = 0;
+ }
+ }
+ else
+ {
+ if (flipx) temp += xoffset[(k-1-i+xa)&7];
+ else temp += xoffset[(i+xa)&7];
+ temp1 = flipx;
+ }
+
+ if (mirrory)
+ {
+ if ((!flipy)^((j<<1)>=l))
+ {
+ /* mirror top/bottom */
+ temp += yoffset[(l-1-j+ya)&7];
+ temp2 = 1;
+ }
+ else
+ {
+ temp += yoffset[(j+ya)&7];
+ temp2 = 0;
+ }
+ }
+ else
+ {
+ if (flipy) temp += yoffset[(l-1-j+ya)&7];
+ else temp += yoffset[(j+ya)&7];
+ temp2 = flipy;
+ }
+
+ if (nozoom) { scaley = scalex = 0x10000; } else { scalex = zw << 12; scaley = zh << 12; };
+
+ zdrawgfxzoom32GP(bitmap, K053247_gfx, cliprect,
+ temp,
+ color,
+ temp1,temp2,
+ temp3,temp4,
+ scalex, scaley, alpha, drawmode, zcode, pri);
+ }
+ }
+ }
+}
+
+
+
+/***************************************************************************/
+/* */
+/* GX/MW Protections */
+/* */
+/***************************************************************************/
+
+// K055550/K053990 protection chips, perform simple memset() and other game logic operations
+static UINT16 prot_data[0x20];
+
+READ16_HANDLER( K055550_word_r )
+{
+ return(prot_data[offset]);
+}
+
+WRITE16_HANDLER( K055550_word_w )
+{
+ UINT32 adr, bsize, count, i, lim;
+ int src, tgt, srcend, tgtend, skip, cx1, sx1, wx1, cy1, sy1, wy1, cz1, sz1, wz1, c2, s2, w2;
+ int dx, dy, angle;
+
+ COMBINE_DATA(prot_data+offset);
+
+ if (offset == 0 && ACCESSING_MSB)
+ {
+ data >>= 8;
+ switch (data)
+ {
+ case 0x97: // memset() (Dadandarn at 0x639dc)
+ case 0x9f: // memset() (Violent Storm at 0x989c)
+ adr = (prot_data[7] << 16) | prot_data[8];
+ bsize = (prot_data[10] << 16) | prot_data[11];
+ count = (prot_data[0] & 0xff) + 1;
+
+ lim = adr+bsize*count;
+ for(i=adr; i<lim; i+=2)
+ program_write_word(i, prot_data[0x1a/2]);
+ break;
+
+ // WARNING: The following cases are speculation based with questionable accuracy!(AAT)
+
+ case 0x87: // unknown memory write (Violent Storm at 0x00b6ea)
+ // Violent Storm writes the following data to the 55550 in mode 0x87.
+ // All values are hardcoded and the write happens each frame during
+ // gameplay. It refers to a 32x8-word list at 0x210e00 and seems to
+ // be tied with another 13x128-byte table at 0x205080.
+ // Both tables appear "check-only" and have little effect on gameplay.
+ count =(prot_data[0] & 0xff) + 1; // unknown ( byte 0x00)
+ i = prot_data[1]; // unknown ( byte 0x1f)
+ adr = prot_data[7]<<16 | prot_data[8]; // address (dword 0x210e00)
+ lim = prot_data[9]; // unknown ( word 0x0010)
+ src = prot_data[10]<<16 | prot_data[11]; // unknown (dword zero)
+ tgt = prot_data[12]<<16 | prot_data[13]; // unknown (dword zero)
+ break;
+
+ case 0xa0: // update collision detection table (Violent Storm at 0x018b42)
+ count = prot_data[0] & 0xff; // number of objects - 1
+ skip = prot_data[1]>>(8-1); // words to skip in each entry to reach the "hit list"
+ adr = prot_data[2]<<16 | prot_data[3]; // where the table is located
+ bsize = prot_data[5]<<16 | prot_data[6]; // object entry size in bytes
+
+ srcend = adr + bsize * count;
+ tgtend = srcend + bsize;
+
+ // let's hope GCC will inline the mem24bew calls
+ for (src=adr; src<srcend; src+=bsize)
+ {
+ cx1 = (short)program_read_word(src);
+ sx1 = (short)program_read_word(src + 2);
+ wx1 = (short)program_read_word(src + 4);
+
+ cy1 = (short)program_read_word(src + 6);
+ sy1 = (short)program_read_word(src + 8);
+ wy1 = (short)program_read_word(src +10);
+
+ cz1 = (short)program_read_word(src +12);
+ sz1 = (short)program_read_word(src +14);
+ wz1 = (short)program_read_word(src +16);
+
+ count = i = src + skip;
+ tgt = src + bsize;
+
+ for (; count<tgt; count++) program_write_byte(count, 0);
+
+ for (; tgt<tgtend; i++, tgt+=bsize)
+ {
+ c2 = (short)program_read_word(tgt);
+ s2 = (short)program_read_word(tgt + 2);
+ w2 = (short)program_read_word(tgt + 4);
+ if (abs((cx1+sx1)-(c2+s2))>=wx1+w2) continue; // X rejection
+
+ c2 = (short)program_read_word(tgt + 6);
+ s2 = (short)program_read_word(tgt + 8);
+ w2 = (short)program_read_word(tgt +10);
+ if (abs((cy1+sy1)-(c2+s2))>=wy1+w2) continue; // Y rejection
+
+ c2 = (short)program_read_word(tgt +12);
+ s2 = (short)program_read_word(tgt +14);
+ w2 = (short)program_read_word(tgt +16);
+ if (abs((cz1+sz1)-(c2+s2))>=wz1+w2) continue; // Z rejection
+
+ program_write_byte(i, 0x80); // collision confirmed
+ }
+ }
+ break;
+
+ case 0xc0: // calculate object "homes-in" vector (Violent Storm at 0x03da9e)
+ dx = (short)prot_data[0xc];
+ dy = (short)prot_data[0xd];
+
+ // it's not necessary to use lookup tables because Violent Storm
+ // only calls the service once per enemy per frame.
+ if (dx)
+ {
+ if (dy)
+ {
+ angle = (atan((double)dy / dx) * 128.0) / M_PI;
+ if (dx < 0) angle += 128;
+ i = (angle - 0x40) & 0xff;
+ }
+ else
+ i = (dx > 0) ? 0xc0 : 0x40;
+ }
+ else
+ if (dy > 0) i = 0;
+ else
+ if (dy < 0) i = 0x80;
+ else
+ i = mame_rand(Machine) & 0xff; // vector direction indeterminate
+
+ prot_data[0x10] = i;
+ break;
+
+ default:
+// logerror("%06x: unknown K055550 command %02x\n", activecpu_get_pc(), data);
+ break;
+ }
+ }
+}
+
+WRITE16_HANDLER( K053990_martchmp_word_w )
+{
+ int src_addr, src_count, src_skip;
+ int dst_addr, dst_count, dst_skip;
+ int mod_addr, mod_count, mod_skip, mod_offs;
+ int mode, i, element_size = 1;
+ UINT16 mod_val, mod_data;
+
+ COMBINE_DATA(prot_data+offset);
+
+ if (offset == 0x0c && ACCESSING_MSB)
+ {
+ mode = (prot_data[0x0d]<<8 & 0xff00) | (prot_data[0x0f] & 0xff);
+
+ switch (mode)
+ {
+ case 0xffff: // word copy
+ element_size = 2;
+ case 0xff00: // byte copy
+ src_addr = prot_data[0x0];
+ src_addr |= prot_data[0x1]<<16 & 0xff0000;
+ dst_addr = prot_data[0x2];
+ dst_addr |= prot_data[0x3]<<16 & 0xff0000;
+ src_count = prot_data[0x8]>>8;
+ dst_count = prot_data[0x9]>>8;
+ src_skip = prot_data[0xa] & 0xff;
+ dst_skip = prot_data[0xb] & 0xff;
+
+ if ((prot_data[0x8] & 0xff) == 2) src_count <<= 1;
+ src_skip += element_size;
+ dst_skip += element_size;
+
+ if (element_size == 1)
+ for (i=src_count; i; i--)
+ {
+ program_write_byte(dst_addr, program_read_byte(src_addr));
+ src_addr += src_skip;
+ dst_addr += dst_skip;
+ }
+ else for (i=src_count; i; i--)
+ {
+ program_write_word(dst_addr, program_read_word(src_addr));
+ src_addr += src_skip;
+ dst_addr += dst_skip;
+ }
+ break;
+
+ case 0x00ff: // sprite list modifier
+ src_addr = prot_data[0x0];
+ src_addr |= prot_data[0x1]<<16 & 0xff0000;
+ src_skip = prot_data[0x1]>>8;
+ dst_addr = prot_data[0x2];
+ dst_addr |= prot_data[0x3]<<16 & 0xff0000;
+ dst_skip = prot_data[0x3]>>8;
+ mod_addr = prot_data[0x4];
+ mod_addr |= prot_data[0x5]<<16 & 0xff0000;
+ mod_skip = prot_data[0x5]>>8;
+ mod_offs = prot_data[0x8] & 0xff;
+ mod_offs<<= 1;
+ mod_count = 0x100;
+
+ src_addr += mod_offs;
+ dst_addr += mod_offs;
+
+ for (i=mod_count; i; i--)
+ {
+ mod_val = program_read_word(mod_addr);
+ mod_addr += mod_skip;
+
+ mod_data = program_read_word(src_addr);
+ src_addr += src_skip;
+
+ mod_data += mod_val;
+
+ program_write_word(dst_addr, mod_data);
+ dst_addr += dst_skip;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void konamigx_esc_alert(UINT32 *srcbase, int srcoffs, int count, int mode) // (WARNING: assumed big endianess)
+{
+
+// hand-filled but should be close
+static UINT8 ztable[7][8] =
+{
+ {5,4,3,2,1,7,6,0},
+ {4,3,2,1,0,7,6,5},
+ {4,3,2,1,0,7,6,5},
+ {3,2,1,0,5,7,4,6},
+ {6,5,1,4,3,7,0,2},
+ {5,4,3,2,1,7,6,0},
+ {5,4,3,2,1,7,6,0}
+};
+
+static UINT8 ptable[7][8] =
+{
+ {0x00,0x00,0x00,0x10,0x20,0x00,0x00,0x30},
+ {0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x20},
+ {0x00,0x00,0x00,0x20,0x20,0x00,0x00,0x00},
+ {0x10,0x10,0x10,0x20,0x00,0x00,0x10,0x00},
+ {0x00,0x00,0x20,0x00,0x10,0x00,0x20,0x20},
+ {0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x10},
+ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10}
+};
+
+ INT32 data1, data2, i, j, vpos, hpos, voffs, hoffs, vcorr, hcorr, vmask, hmask, magicid;
+ UINT32 *src, *srcend, *obj, *objend;
+ UINT16 *dst;
+ UINT8 *zcode, *pcode;
+
+ if (!count || !srcbase) return;
+
+ if (mode == 0)
+ {
+ src = srcbase + srcoffs;
+ dst = K053247_ram;
+ data1 = count<<2;
+ data2 = count<<3;
+ src += data1; dst += data2; i = -data1; j = -data2;
+ do
+ {
+ data1 = src[i];
+ data2 = src[i+1];
+ i += 2;
+ dst[j+1] = data1;
+ dst[j+3] = data2;
+ data1 >>= 16;
+ data2 >>= 16;
+ dst[j] = data1;
+ dst[j+2] = data2;
+ }
+ while (j += 4);
+ }
+ else
+ {
+
+#define EXTRACT_ODD \
+if((data1=obj[0])&0x8000) \
+{ \
+ i = data1 & 7; \
+ data1 &= 0xff00; \
+ dst[0] = data1 | zcode[i];\
+ data1 = obj[1]; \
+ dst[1] = data1>>16; \
+ vpos = data1 & 0xffff; \
+ data1 = obj[2]; \
+ vpos += voffs; \
+ dst[4] = data1; \
+ vpos &= vmask; \
+ hpos = data1>>16; \
+ data1 = obj[3]; \
+ hpos += hoffs; \
+ dst[2] = vpos; \
+ dst[3] = hpos; \
+ dst[5] = data1>>16; \
+ i = pcode[i]; \
+ dst[6] = data1| i<<4; \
+ dst += 8; \
+ if (!(--j)) return; \
+}
+
+#define EXTRACT_EVEN \
+if((data1=obj[0])&0x80000000)\
+{ \
+ dst[1] = data1; \
+ data1>>= 16; \
+ i = data1 & 7; \
+ data1 &= 0xff00; \
+ dst[0] = data1 | zcode[i]; \
+ data1 = obj[1]; \
+ hpos = data1 & 0xffff; \
+ vpos = data1>>16; \
+ hpos += hoffs; \
+ vpos += voffs; \
+ data1 = obj[2]; \
+ vpos &= vmask; \
+ dst[3] = hpos; \
+ dst[2] = vpos; \
+ dst[5] = data1; \
+ dst[4] = data1>>16; \
+ data1 = obj[3]>>16; \
+ i = pcode[i]; \
+ dst[6] = data1 | i<<4; \
+ dst += 8; \
+ if (!(--j)) return; \
+}
+
+ // These suspecious looking flags might tell the ESC chip what zcode/priority combos to use.
+ // At the beginning of each sprite chunk there're at least three pointers to the main ROM but
+ // I can't make out anything meaningful.
+ magicid = srcbase[0x71f0/4];
+
+ hmask = vmask = 0x3ff;
+ if (magicid != 0x11010111)
+ {
+ switch (magicid)
+ {
+ case 0x10010801: i = 6; break;
+ case 0x11010010: i = 5; vmask = 0x1ff; break;
+ case 0x01111018: i = 4; break;
+ case 0x10010011: i = 3;
+ if ((srcbase[0x1c75]&0xff)==32) K055555_write_reg(K55_BLEND_ENABLES,36); // (TEMPORARY)
+ break;
+ case 0x11010811: i = 2; break;
+ case 0x10000010: i = 1; break;
+ default: i = 0;
+ }
+ vcorr = srcbase[0x26a0/4] & 0xffff;
+ hcorr = srcbase[0x26a4/4] >> 16;
+ hcorr -= 10;
+ }
+ else
+ hcorr = vcorr = i = 0;
+
+ zcode = ztable[i];
+ pcode = ptable[i];
+
+ dst = K053247_ram;
+ j = 256;
+
+ // decode Vic-Viper
+ if (srcbase[0x049c/4] & 0xffff0000)
+ {
+ hoffs = srcbase[0x0502/4] & 0xffff;
+ voffs = srcbase[0x0506/4] & 0xffff;
+ hoffs -= hcorr;
+ voffs -= vcorr;
+ obj = &srcbase[0x049e/4];
+ EXTRACT_ODD
+ obj = &srcbase[0x04ae/4];
+ EXTRACT_ODD
+ obj = &srcbase[0x04be/4];
+ EXTRACT_ODD
+ }
+
+ // decode Lord British (the designer must be a Richard Garriot fan too:)
+ if (srcbase[0x0848/4] & 0x0000ffff)
+ {
+ hoffs = srcbase[0x08b0/4]>>16;
+ voffs = srcbase[0x08b4/4]>>16;
+ hoffs -= hcorr;
+ voffs -= vcorr;
+ obj = &srcbase[0x084c/4];
+ EXTRACT_EVEN
+ obj = &srcbase[0x085c/4];
+ EXTRACT_EVEN
+ obj = &srcbase[0x086c/4];
+ EXTRACT_EVEN
+ }
+
+ // decode common sprites
+ src = srcbase + srcoffs;
+ srcend = src + count * 0x30;
+ do
+ {
+ if (!src[0] || !(i = src[7] & 0xf)) continue; // reject retired or zero-element groups
+ i <<= 2;
+ hoffs = src[5]>>16;
+ voffs = src[6]>>16;
+ hoffs -= hcorr;
+ voffs -= vcorr;
+ obj = src + 8;
+ objend = obj + i;
+
+ do
+ {
+ EXTRACT_EVEN
+ }
+ while ((obj+=4)<objend);
+ }
+ while ((src+=0x30)<srcend);
+
+ // clear residual data
+ if (j) do { *dst = 0; dst += 8; } while (--j);
+ }
+
+#undef EXTRACT_ODD
+#undef EXTRACT_EVEN
+}
diff --git a/src/mame/machine/konamigx.h b/src/mame/machine/konamigx.h
new file mode 100644
index 00000000000..a0eb32c3586
--- /dev/null
+++ b/src/mame/machine/konamigx.h
@@ -0,0 +1,103 @@
+#ifndef __MACH_KONAMIGX_H
+#define __MACH_KONAMIGX_H
+
+void tms57002_init(void);
+
+READ8_HANDLER( tms57002_data_r );
+READ8_HANDLER( tms57002_status_r );
+WRITE8_HANDLER( tms57002_control_w );
+WRITE8_HANDLER( tms57002_data_w );
+
+READ16_HANDLER( tms57002_data_word_r );
+READ16_HANDLER( tms57002_status_word_r );
+WRITE16_HANDLER( tms57002_control_word_w );
+WRITE16_HANDLER( tms57002_data_word_w );
+
+
+
+// 2nd-Tier GX/MW Hardware Functions
+void K053247GP_set_SpriteOffset(int offsx, int offsy);
+
+void K053936GP_set_offset(int chip, int xoffs, int yoffs);
+void K053936GP_clip_enable(int chip, int status);
+void K053936GP_set_cliprect(int chip, int minx, int maxx, int miny, int maxy);
+void K053936GP_0_zoom_draw(mame_bitmap *bitmap, const rectangle *cliprect, tilemap *tmap, int tilebpp, int blend);
+void K053936GP_1_zoom_draw(mame_bitmap *bitmap, const rectangle *cliprect, tilemap *tmap, int tilebpp, int blend);
+
+
+
+// 1st-Tier GX/MW Variables and Functions
+extern UINT8 konamigx_wrport1_0, konamigx_wrport1_1;
+extern UINT16 konamigx_wrport2;
+
+
+// Tile and Sprite Mixcode Decoders
+int K055555GX_decode_vmixcolor(int layer, int *color);
+int K055555GX_decode_osmixcolor(int layer, int *color);
+
+
+// Sprite Callbacks
+
+/* callbacks should return color codes in this format:
+ fedcba9876543210fedcba9876543210
+ ----------------xxxxxxxxxxxxxxxx (bit 00-15: color)
+ --------------xx---------------- (bit 16-17: blend code)
+ ------------xx------------------ (bit 18-19: brightness code)
+ -x------------------------------ (bit 30 : skip shadow)
+ x------------------------------- (bit 31 : full shadow)
+*/
+#define K055555_COLORMASK 0x0000ffff
+#define K055555_MIXSHIFT 16
+#define K055555_BRTSHIFT 18
+#define K055555_SKIPSHADOW 0x40000000
+#define K055555_FULLSHADOW 0x80000000
+
+void konamigx_type2_sprite_callback(int *code, int *color, int *priority);
+
+void konamigx_dragoonj_sprite_callback(int *code, int *color, int *priority);
+void konamigx_salmndr2_sprite_callback(int *code, int *color, int *priority);
+void konamigx_le2_sprite_callback(int *code, int *color, int *priority);
+
+
+// Centralized Sprites and Layer Blitter
+
+/* Mixer Flags
+ fedcba9876543210fedcba9876543210
+ --------------------FFEEDDCCBBAA (layer A-F blend modes)
+ ----------------DCBA------------ (layer A-D line/row scroll disables)
+ ----FFEEDDCCBBAA---------------- (layer A-F mix codes in forced blending)
+ ---x---------------------------- (disable shadows)
+ --x----------------------------- (disable z-buffering)
+*/
+#define GXMIX_BLEND_AUTO 0 // emulate all blend effects
+#define GXMIX_BLEND_NONE 1 // disable all blend effects
+#define GXMIX_BLEND_FAST 2 // simulate translucency
+#define GXMIX_BLEND_FORCE 3 // force mix code on selected layer(s)
+#define GXMIX_NOLINESCROLL 0x1000 // disable linescroll on selected layer(s)
+#define GXMIX_NOSHADOW 0x10000000 // disable all shadows (shadow pens will be skipped)
+#define GXMIX_NOZBUF 0x20000000 // disable z-buffering (shadow pens will be drawn as solid)
+
+// Sub Layer Flags
+#define GXSUB_K053250 0x10 // chip type: 0=K053936 ROZ+, 1=K053250 LVC
+#define GXSUB_4BPP 0x04 // 16 colors
+#define GXSUB_5BPP 0x05 // 32 colors
+#define GXSUB_8BPP 0x08 // 256 colors
+
+void konamigx_mixer(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect,
+ tilemap *sub1, int sub1flags,
+ tilemap *sub2, int sub2flags,
+ int mixerflags);
+
+void konamigx_mixer_init(int objdma);
+void konamigx_mixer_primode(int mode);
+
+
+void konamigx_objdma(void);
+
+
+// K055550/K053990/ESC protection devices handlers
+READ16_HANDLER ( K055550_word_r );
+WRITE16_HANDLER( K055550_word_w );
+WRITE16_HANDLER( K053990_martchmp_word_w );
+void konamigx_esc_alert(UINT32 *srcbase, int srcoffs, int count, int mode);
+#endif
diff --git a/src/mame/machine/konamiic.c b/src/mame/machine/konamiic.c
new file mode 100644
index 00000000000..45500599b8d
--- /dev/null
+++ b/src/mame/machine/konamiic.c
@@ -0,0 +1,122 @@
+#include "driver.h"
+#include "konamiic.h"
+
+/* Konami K056800 (MIRAC) */
+
+static UINT8 K056800_host_reg[8];
+static UINT8 K056800_sound_reg[8];
+
+static emu_timer *K056800_sound_cpu_timer;
+static int K056800_sound_cpu_irq1_enable;
+static void (*K056800_sound_irq_callback)(int);
+
+static UINT8 K056800_host_reg_r(int reg)
+{
+ UINT8 value = 0;
+
+ value = K056800_host_reg[reg];
+ if (reg == 2) value &= ~3; // suppress VOLWR busy flags
+
+ return value;
+}
+
+static void K056800_host_reg_w(int reg, UINT8 data)
+{
+ K056800_sound_reg[reg] = data;
+
+ if (reg == 7)
+ {
+ K056800_sound_irq_callback(1);
+ }
+}
+
+static UINT8 K056800_sound_reg_r(int reg)
+{
+ return K056800_sound_reg[reg];
+}
+
+static void K056800_sound_reg_w(int reg, UINT8 data)
+{
+ if (reg == 4)
+ {
+ K056800_sound_cpu_irq1_enable = data & 0x01;
+ }
+
+ K056800_host_reg[reg] = data;
+}
+
+static TIMER_CALLBACK( K056800_sound_cpu_timer_tick )
+{
+ if (K056800_sound_cpu_irq1_enable)
+ {
+ K056800_sound_irq_callback(0);
+ }
+}
+
+void K056800_init(void (* irq_callback)(int))
+{
+ attotime timer_period;
+ K056800_sound_irq_callback = irq_callback;
+
+ memset(K056800_host_reg, 0, sizeof(K056800_host_reg));
+ memset(K056800_sound_reg, 0, sizeof(K056800_sound_reg));
+
+ timer_period = attotime_mul(ATTOTIME_IN_HZ(44100), 128); // roughly 2.9us
+
+ K056800_sound_cpu_timer = timer_alloc(K056800_sound_cpu_timer_tick);
+ timer_adjust(K056800_sound_cpu_timer, timer_period, 0, timer_period);
+}
+
+READ32_HANDLER(K056800_host_r)
+{
+ UINT32 r = 0;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= K056800_host_reg_r((offset*4)+0) << 24;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ r |= K056800_host_reg_r((offset*4)+1) << 16;
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ r |= K056800_host_reg_r((offset*4)+2) << 8;
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ r |= K056800_host_reg_r((offset*4)+3) << 0;
+ }
+
+ return r;
+}
+
+WRITE32_HANDLER(K056800_host_w)
+{
+ if (!(mem_mask & 0xff000000))
+ {
+ K056800_host_reg_w((offset*4)+0, (data >> 24) & 0xff);
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ K056800_host_reg_w((offset*4)+1, (data >> 16) & 0xff);
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ K056800_host_reg_w((offset*4)+2, (data >> 8) & 0xff);
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ K056800_host_reg_w((offset*4)+3, (data >> 0) & 0xff);
+ }
+}
+
+READ16_HANDLER(K056800_sound_r)
+{
+ return K056800_sound_reg_r(offset);
+}
+
+WRITE16_HANDLER(K056800_sound_w)
+{
+ K056800_sound_reg_w(offset, data);
+}
diff --git a/src/mame/machine/konamiic.h b/src/mame/machine/konamiic.h
new file mode 100644
index 00000000000..5eb40c36643
--- /dev/null
+++ b/src/mame/machine/konamiic.h
@@ -0,0 +1,10 @@
+#ifndef _KONAMIIC_H
+#define _KONAMIIC_H
+
+void K056800_init(void (* irq_callback)(int));
+READ32_HANDLER(K056800_host_r);
+WRITE32_HANDLER(K056800_host_w);
+READ16_HANDLER(K056800_sound_r);
+WRITE16_HANDLER(K056800_sound_w);
+
+#endif
diff --git a/src/mame/machine/konppc.c b/src/mame/machine/konppc.c
new file mode 100644
index 00000000000..ba8625d632b
--- /dev/null
+++ b/src/mame/machine/konppc.c
@@ -0,0 +1,697 @@
+/* Konami PowerPC-based 3D games common functions */
+
+#include "driver.h"
+#include "cpu/sharc/sharc.h"
+#include "video/voodoo.h"
+#include "konppc.h"
+
+#define MAX_CG_BOARDS 2
+
+static UINT32 dsp_comm_ppc[MAX_CG_BOARDS][2];
+static UINT32 dsp_comm_sharc[MAX_CG_BOARDS][2];
+static int dsp_shared_ram_bank[MAX_CG_BOARDS];
+
+static int cgboard_id;
+static int cgboard_type;
+static int num_cgboards;
+
+static UINT32 *dsp_shared_ram[MAX_CG_BOARDS];
+
+#define DSP_BANK_SIZE 0x10000
+#define DSP_BANK_SIZE_WORD (DSP_BANK_SIZE / 4)
+
+static UINT32 dsp_state[MAX_CG_BOARDS];
+static UINT32 pci_bridge_enable[MAX_CG_BOARDS];
+static UINT32 nwk_device_sel[MAX_CG_BOARDS];
+static int texture_bank[MAX_CG_BOARDS];
+
+static int nwk_fifo_half_full_r;
+static int nwk_fifo_half_full_w;
+static int nwk_fifo_full;
+static int nwk_fifo_mask;
+
+
+static UINT32 *nwk_fifo[MAX_CG_BOARDS];
+static int nwk_fifo_read_ptr[MAX_CG_BOARDS];
+static int nwk_fifo_write_ptr[MAX_CG_BOARDS];
+
+static UINT32 *nwk_ram[MAX_CG_BOARDS];
+
+/*****************************************************************************/
+
+void init_konami_cgboard(int num_boards, int type)
+{
+ int i;
+ num_cgboards = num_boards;
+
+ for (i=0; i < num_boards; i++)
+ {
+ dsp_comm_ppc[i][0] = 0x00;
+ dsp_shared_ram[i] = auto_malloc(DSP_BANK_SIZE * 2);
+ dsp_shared_ram_bank[i] = 0;
+
+ dsp_state[i] = 0x80;
+ texture_bank[i] = -1;
+
+ pci_bridge_enable[i] = 0;
+ nwk_device_sel[i] = 0;
+ nwk_fifo_read_ptr[i] = 0;
+ nwk_fifo_write_ptr[i] = 0;
+
+ nwk_fifo[i] = auto_malloc(sizeof(UINT32) * 0x800);
+ nwk_ram[i] = auto_malloc(sizeof(UINT32) * 0x2000);
+ }
+ cgboard_type = type;
+
+ if (type == CGBOARD_TYPE_NWKTR)
+ {
+ nwk_fifo_half_full_r = 0x100;
+ nwk_fifo_half_full_w = 0xff;
+ nwk_fifo_full = 0x1ff;
+ nwk_fifo_mask = 0x1ff;
+ }
+ if (type == CGBOARD_TYPE_HANGPLT)
+ {
+ nwk_fifo_half_full_r = 0x3ff;
+ nwk_fifo_half_full_w = 0x400;
+ nwk_fifo_full = 0x7ff;
+ nwk_fifo_mask = 0x7ff;
+ }
+}
+
+void set_cgboard_id(int board_id)
+{
+ if (board_id > num_cgboards-1)
+ {
+ cgboard_id = MAX_CG_BOARDS;
+ }
+ else
+ {
+ cgboard_id = board_id;
+ }
+}
+
+int get_cgboard_id(void)
+{
+ if (cgboard_id > num_cgboards-1)
+ {
+ return 0;
+ }
+ else
+ {
+ return cgboard_id;
+ }
+}
+
+void set_cgboard_texture_bank(int board, int bank, UINT8 *rom)
+{
+ texture_bank[board] = bank;
+
+ memory_configure_bank(bank, 0, 2, rom, 0x800000);
+}
+
+/*****************************************************************************/
+
+/* CG Board DSP interface for PowerPC */
+
+READ32_HANDLER( cgboard_dsp_comm_r_ppc )
+{
+ if (cgboard_id < MAX_CG_BOARDS)
+ {
+// mame_printf_debug("dsp_cmd_r: (board %d) %08X, %08X at %08X\n", cgboard_id, offset, mem_mask, activecpu_get_pc());
+ return dsp_comm_sharc[cgboard_id][offset] | (dsp_state[cgboard_id] << 16);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+WRITE32_HANDLER( cgboard_dsp_comm_w_ppc )
+{
+ int dsp = (cgboard_id == 0) ? 2 : 3;
+// mame_printf_debug("dsp_cmd_w: (board %d) %08X, %08X, %08X at %08X\n", cgboard_id, data, offset, mem_mask, activecpu_get_pc());
+
+ if (cgboard_id < MAX_CG_BOARDS)
+ {
+ if (offset == 0)
+ {
+ if (!(mem_mask & 0xff000000))
+ {
+ dsp_shared_ram_bank[cgboard_id] = (data >> 24) & 0x1;
+
+ if (data & 0x80000000)
+ {
+ dsp_state[cgboard_id] |= 0x10;
+ }
+
+ pci_bridge_enable[cgboard_id] = (data & 0x20000000) ? 1 : 0;
+
+ if (data & 0x10000000)
+ {
+ cpunum_set_input_line(dsp, INPUT_LINE_RESET, CLEAR_LINE);
+ }
+ else
+ {
+ cpunum_set_input_line(dsp, INPUT_LINE_RESET, ASSERT_LINE);
+ }
+
+ if (data & 0x02000000)
+ {
+ cpunum_set_input_line(dsp, INPUT_LINE_IRQ0, ASSERT_LINE);
+ }
+ if (data & 0x04000000)
+ {
+ cpunum_set_input_line(dsp, INPUT_LINE_IRQ1, ASSERT_LINE);
+ }
+ }
+
+ if (!(mem_mask & 0x000000ff))
+ {
+ dsp_comm_ppc[cgboard_id][offset] = data & 0xff;
+ }
+ }
+ else
+ {
+ dsp_comm_ppc[cgboard_id][offset] = data;
+ }
+ }
+}
+
+
+
+READ32_HANDLER( cgboard_dsp_shared_r_ppc )
+{
+ if (cgboard_id < MAX_CG_BOARDS)
+ {
+ return dsp_shared_ram[cgboard_id][offset + (dsp_shared_ram_bank[cgboard_id] * DSP_BANK_SIZE_WORD)];
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+WRITE32_HANDLER( cgboard_dsp_shared_w_ppc )
+{
+ if (cgboard_id < MAX_CG_BOARDS)
+ {
+ cpu_trigger(10000); // Remove the timeout (a part of the GTI Club FIFO test workaround)
+ COMBINE_DATA(dsp_shared_ram[cgboard_id] + (offset + (dsp_shared_ram_bank[cgboard_id] * DSP_BANK_SIZE_WORD)));
+ }
+}
+
+/*****************************************************************************/
+
+/* CG Board DSP interface for SHARC */
+
+static UINT32 dsp_comm_sharc_r(int board, int offset)
+{
+ return dsp_comm_ppc[board][offset];
+}
+
+static void dsp_comm_sharc_w(int board, int offset, UINT32 data)
+{
+ if (offset >= 2)
+ {
+ fatalerror("dsp_comm_w: %08X, %08X", data, offset);
+ }
+
+ switch (cgboard_type)
+ {
+ case CGBOARD_TYPE_ZR107:
+ case CGBOARD_TYPE_GTICLUB:
+ {
+ //cpunum_set_input_line(2, SHARC_INPUT_FLAG0, ASSERT_LINE);
+ cpuintrf_push_context(2);
+ sharc_set_flag_input(0, ASSERT_LINE);
+ cpuintrf_pop_context();
+
+ if (offset == 1)
+ {
+ if (data & 0x03)
+ {
+ cpunum_set_input_line(2, INPUT_LINE_IRQ2, ASSERT_LINE);
+ }
+ }
+ break;
+ }
+
+ case CGBOARD_TYPE_NWKTR:
+ case CGBOARD_TYPE_HANGPLT:
+ {
+ if (offset == 1)
+ {
+ nwk_device_sel[board] = data;
+
+ if (data & 0x01 || data & 0x10)
+ {
+ cpuintrf_push_context((board == 0) ? 2 : 3);
+ sharc_set_flag_input(1, ASSERT_LINE);
+ cpuintrf_pop_context();
+ }
+
+ if (texture_bank[board] != -1)
+ {
+ int offset = (data & 0x08) ? 1 : 0;
+
+ memory_set_bank(texture_bank[board], offset);
+ }
+ }
+ break;
+ }
+
+ case CGBOARD_TYPE_HORNET:
+ {
+ if (offset == 1)
+ {
+ if (texture_bank[board] != -1)
+ {
+ int offset = (data & 0x08) ? 1 : 0;
+
+ memory_set_bank(texture_bank[board], offset);
+ }
+ }
+ break;
+ }
+ }
+
+// printf("cgboard_dsp_comm_w_sharc: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+
+ dsp_comm_sharc[board][offset] = data;
+}
+
+static UINT32 dsp_shared_ram_r_sharc(int board, int offset)
+{
+// printf("dsp_shared_r: (board %d) %08X, (%08X, %08X)\n", cgboard_id, offset, (UINT32)dsp_shared_ram[(offset >> 1)], (UINT32)dsp_shared_ram[offset]);
+
+ if (offset & 0x1)
+ {
+ return (dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] >> 0) & 0xffff;
+ }
+ else
+ {
+ return (dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] >> 16) & 0xffff;
+ }
+}
+
+static void dsp_shared_ram_w_sharc(int board, int offset, UINT32 data)
+{
+// printf("dsp_shared_w: (board %d) %08X, %08X\n", cgboard_id, offset, data);
+ if (offset & 0x1)
+ {
+ dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] &= 0xffff0000;
+ dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] |= (data & 0xffff);
+ }
+ else
+ {
+ dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] &= 0x0000ffff;
+ dsp_shared_ram[board][(offset >> 1) + ((dsp_shared_ram_bank[board] ^ 1) * DSP_BANK_SIZE_WORD)] |= ((data & 0xffff) << 16);
+ }
+}
+
+READ32_HANDLER( cgboard_0_comm_sharc_r )
+{
+ return dsp_comm_sharc_r(0, offset);
+}
+
+WRITE32_HANDLER( cgboard_0_comm_sharc_w )
+{
+ dsp_comm_sharc_w(0, offset, data);
+}
+
+READ32_HANDLER( cgboard_0_shared_sharc_r )
+{
+ return dsp_shared_ram_r_sharc(0, offset);
+}
+
+WRITE32_HANDLER( cgboard_0_shared_sharc_w )
+{
+ dsp_shared_ram_w_sharc(0, offset, data);
+}
+
+READ32_HANDLER( cgboard_1_comm_sharc_r )
+{
+ return dsp_comm_sharc_r(1, offset);
+}
+
+WRITE32_HANDLER( cgboard_1_comm_sharc_w )
+{
+ dsp_comm_sharc_w(1, offset, data);
+}
+
+READ32_HANDLER( cgboard_1_shared_sharc_r )
+{
+ return dsp_shared_ram_r_sharc(1, offset);
+}
+
+WRITE32_HANDLER( cgboard_1_shared_sharc_w )
+{
+ dsp_shared_ram_w_sharc(1, offset, data);
+}
+
+/*****************************************************************************/
+
+static UINT32 nwk_fifo_r(int board)
+{
+ int cpu = (board == 0) ? 2 : 3;
+ UINT32 data;
+
+ if (nwk_fifo_read_ptr[board] < nwk_fifo_half_full_r)
+ {
+ cpuintrf_push_context(cpu);
+ sharc_set_flag_input(1, CLEAR_LINE);
+ cpuintrf_pop_context();
+ }
+ else
+ {
+ cpuintrf_push_context(cpu);
+ sharc_set_flag_input(1, ASSERT_LINE);
+ cpuintrf_pop_context();
+ }
+
+ if (nwk_fifo_read_ptr[board] < nwk_fifo_full)
+ {
+ cpuintrf_push_context(cpu);
+ sharc_set_flag_input(2, ASSERT_LINE);
+ cpuintrf_pop_context();
+ }
+ else
+ {
+ cpuintrf_push_context(cpu);
+ sharc_set_flag_input(2, CLEAR_LINE);
+ cpuintrf_pop_context();
+ }
+
+ data = nwk_fifo[board][nwk_fifo_read_ptr[board]];
+ nwk_fifo_read_ptr[board]++;
+ nwk_fifo_read_ptr[board] &= nwk_fifo_mask;
+
+ return data;
+}
+
+static void nwk_fifo_w(int board, UINT32 data)
+{
+ int cpu = (board == 0) ? 2 : 3;
+
+ if (nwk_fifo_write_ptr[board] < nwk_fifo_half_full_w)
+ {
+ cpuintrf_push_context(cpu);
+ sharc_set_flag_input(1, ASSERT_LINE);
+ cpuintrf_pop_context();
+ }
+ else
+ {
+ cpuintrf_push_context(cpu);
+ sharc_set_flag_input(1, CLEAR_LINE);
+ cpuintrf_pop_context();
+ }
+
+ cpuintrf_push_context(cpu);
+ sharc_set_flag_input(2, ASSERT_LINE);
+ cpuintrf_pop_context();
+
+ nwk_fifo[board][nwk_fifo_write_ptr[board]] = data;
+ nwk_fifo_write_ptr[board]++;
+ nwk_fifo_write_ptr[board] &= nwk_fifo_mask;
+}
+
+/*****************************************************************************/
+
+/* Konami K033906 PCI bridge */
+
+#define MAX_K033906_CHIPS 2
+
+static UINT32 *K033906_reg[MAX_K033906_CHIPS];
+static UINT32 *K033906_ram[MAX_K033906_CHIPS];
+
+void K033906_init(void)
+{
+ int i;
+ for (i=0; i < MAX_K033906_CHIPS; i++)
+ {
+ K033906_reg[i] = auto_malloc(sizeof(UINT32) * 256);
+ K033906_ram[i] = auto_malloc(sizeof(UINT32) * 32768);
+ }
+}
+
+static UINT32 K033906_r(int chip, int reg)
+{
+ switch(reg)
+ {
+ case 0x00: return 0x0001121a; // PCI Vendor ID (0x121a = 3dfx), Device ID (0x0001 = Voodoo)
+ case 0x02: return 0x04000000; // Revision ID
+ case 0x04: return K033906_reg[chip][0x04]; // memBaseAddr
+ case 0x0f: return K033906_reg[chip][0x0f]; // interrupt_line, interrupt_pin, min_gnt, max_lat
+
+ default:
+ fatalerror("K033906_r: %d, %08X at %08X", chip, reg, activecpu_get_pc());
+ }
+ return 0;
+}
+
+static void K033906_w(int chip, int reg, UINT32 data)
+{
+ switch(reg)
+ {
+ case 0x00:
+ break;
+
+ case 0x01: // command register
+ break;
+
+ case 0x04: // memBaseAddr
+ {
+ if (data == 0xffffffff)
+ {
+ K033906_reg[chip][0x04] = 0xff000000;
+ }
+ else
+ {
+ K033906_reg[chip][0x04] = data & 0xff000000;
+ }
+ break;
+ }
+
+ case 0x0f: // interrupt_line, interrupt_pin, min_gnt, max_lat
+ {
+ K033906_reg[chip][0x0f] = data;
+ break;
+ }
+
+ case 0x10: // initEnable
+ {
+ voodoo_set_init_enable(chip, data);
+ break;
+ }
+
+ case 0x11: // busSnoop0
+ case 0x12: // busSnoop1
+ break;
+
+ case 0x38: // ???
+ break;
+
+ default:
+ fatalerror("K033906_w: %d, %08X, %08X at %08X", chip, data, reg, activecpu_get_pc());
+ }
+}
+
+READ32_HANDLER(K033906_0_r)
+{
+ if (nwk_device_sel[0] & 0x01)
+ {
+ return nwk_fifo_r(0);
+ }
+ else
+ {
+ if (pci_bridge_enable[0])
+ {
+ return K033906_r(0, offset);
+ }
+ else
+ {
+ return K033906_ram[0][offset];
+ }
+ }
+}
+
+WRITE32_HANDLER(K033906_0_w)
+{
+ if (pci_bridge_enable[0])
+ {
+ K033906_w(0, offset, data);
+ }
+ else
+ {
+ K033906_ram[0][offset] = data;
+ }
+}
+
+READ32_HANDLER(K033906_1_r)
+{
+ if (nwk_device_sel[1] & 0x01)
+ {
+ return nwk_fifo_r(1);
+ }
+ else
+ {
+ if (pci_bridge_enable[1])
+ {
+ return K033906_r(1, offset);
+ }
+ else
+ {
+ return K033906_ram[1][offset];
+ }
+ }
+}
+
+WRITE32_HANDLER(K033906_1_w)
+{
+ if (pci_bridge_enable[1])
+ {
+ K033906_w(1, offset, data);
+ }
+ else
+ {
+ K033906_ram[1][offset] = data;
+ }
+}
+
+/*****************************************************************************/
+
+WRITE32_HANDLER(nwk_fifo_0_w)
+{
+ if (nwk_device_sel[0] & 0x01)
+ {
+ nwk_fifo_w(0, data);
+ }
+ else if (nwk_device_sel[0] & 0x02)
+ {
+ int addr = ((offset >> 8) << 9) | (offset & 0xff);
+ nwk_ram[0][addr] = data;
+ }
+ else
+ {
+ voodoo_0_w(offset ^ 0x80000, data, mem_mask);
+ }
+}
+
+WRITE32_HANDLER(nwk_fifo_1_w)
+{
+ if (nwk_device_sel[1] & 0x01)
+ {
+ nwk_fifo_w(1, data);
+ }
+ else if (nwk_device_sel[1] & 0x02)
+ {
+ int addr = ((offset >> 8) << 9) | (offset & 0xff);
+ nwk_ram[1][addr] = data;
+ }
+ else
+ {
+ voodoo_1_w(offset ^ 0x80000, data, mem_mask);
+ }
+}
+
+READ32_HANDLER(nwk_voodoo_0_r)
+{
+ if ((nwk_device_sel[0] == 0x4) && offset >= 0x100000 && offset < 0x200000)
+ {
+ return nwk_ram[0][offset & 0x1fff];
+ }
+ else
+ {
+ return voodoo_0_r(offset, mem_mask);
+ }
+}
+
+READ32_HANDLER(nwk_voodoo_1_r)
+{
+ if ((nwk_device_sel[1] == 0x4) && offset >= 0x100000 && offset < 0x200000)
+ {
+ return nwk_ram[1][offset & 0x1fff];
+ }
+ else
+ {
+ return voodoo_1_r(offset, mem_mask);
+ }
+}
+
+WRITE32_HANDLER(nwk_voodoo_0_w)
+{
+ if (nwk_device_sel[0] & 0x01)
+ {
+ nwk_fifo_w(0, data);
+ }
+ else if (nwk_device_sel[0] & 0x02)
+ {
+ int addr = ((offset >> 8) << 9) | (offset & 0xff);
+ nwk_ram[0][addr] = data;
+ }
+ else
+ {
+ voodoo_0_w(offset, data, mem_mask);
+ }
+}
+
+WRITE32_HANDLER(nwk_voodoo_1_w)
+{
+ if (nwk_device_sel[1] & 0x01)
+ {
+ nwk_fifo_w(1, data);
+ }
+ else if (nwk_device_sel[1] & 0x02)
+ {
+ int addr = ((offset >> 8) << 9) | (offset & 0xff);
+ nwk_ram[1][addr] = data;
+ }
+ else
+ {
+ voodoo_1_w(offset, data, mem_mask);
+ }
+}
+
+/*****************************************************************************/
+
+#define LED_ON 0xff00ff00
+
+void draw_7segment_led(mame_bitmap *bitmap, int x, int y, UINT8 value)
+{
+ if ((value & 0x7f) == 0x7f)
+ {
+ return;
+ }
+
+ plot_box(bitmap, x-1, y-1, 7, 11, 0x00000000);
+
+ /* Top */
+ if( (value & 0x40) == 0 ) {
+ plot_box(bitmap, x+1, y+0, 3, 1, LED_ON);
+ }
+ /* Middle */
+ if( (value & 0x01) == 0 ) {
+ plot_box(bitmap, x+1, y+4, 3, 1, LED_ON);
+ }
+ /* Bottom */
+ if( (value & 0x08) == 0 ) {
+ plot_box(bitmap, x+1, y+8, 3, 1, LED_ON);
+ }
+ /* Top Left */
+ if( (value & 0x02) == 0 ) {
+ plot_box(bitmap, x+0, y+1, 1, 3, LED_ON);
+ }
+ /* Top Right */
+ if( (value & 0x20) == 0 ) {
+ plot_box(bitmap, x+4, y+1, 1, 3, LED_ON);
+ }
+ /* Bottom Left */
+ if( (value & 0x04) == 0 ) {
+ plot_box(bitmap, x+0, y+5, 1, 3, LED_ON);
+ }
+ /* Bottom Right */
+ if( (value & 0x10) == 0 ) {
+ plot_box(bitmap, x+4, y+5, 1, 3, LED_ON);
+ }
+}
diff --git a/src/mame/machine/konppc.h b/src/mame/machine/konppc.h
new file mode 100644
index 00000000000..a025a9b543b
--- /dev/null
+++ b/src/mame/machine/konppc.h
@@ -0,0 +1,44 @@
+#ifndef _KONPPC_H
+#define _KONPPC_H
+
+#define CGBOARD_TYPE_ZR107 0
+#define CGBOARD_TYPE_GTICLUB 1
+#define CGBOARD_TYPE_NWKTR 2
+#define CGBOARD_TYPE_HORNET 3
+#define CGBOARD_TYPE_HANGPLT 4
+
+void init_konami_cgboard(int board_id, int type);
+void set_cgboard_id(int board_id);
+int get_cgboard_id(void);
+void set_cgboard_texture_bank(int board, int bank, UINT8 *rom);
+
+READ32_HANDLER( cgboard_dsp_comm_r_ppc );
+WRITE32_HANDLER( cgboard_dsp_comm_w_ppc );
+READ32_HANDLER( cgboard_dsp_shared_r_ppc );
+WRITE32_HANDLER( cgboard_dsp_shared_w_ppc );
+
+READ32_HANDLER( cgboard_0_comm_sharc_r );
+WRITE32_HANDLER( cgboard_0_comm_sharc_w );
+READ32_HANDLER( cgboard_0_shared_sharc_r );
+WRITE32_HANDLER( cgboard_0_shared_sharc_w );
+READ32_HANDLER( cgboard_1_comm_sharc_r );
+WRITE32_HANDLER( cgboard_1_comm_sharc_w );
+READ32_HANDLER( cgboard_1_shared_sharc_r );
+WRITE32_HANDLER( cgboard_1_shared_sharc_w );
+
+void K033906_init(void);
+READ32_HANDLER(K033906_0_r);
+WRITE32_HANDLER(K033906_0_w);
+READ32_HANDLER(K033906_1_r);
+WRITE32_HANDLER(K033906_1_w);
+
+WRITE32_HANDLER(nwk_fifo_0_w);
+WRITE32_HANDLER(nwk_fifo_1_w);
+READ32_HANDLER(nwk_voodoo_0_r);
+READ32_HANDLER(nwk_voodoo_1_r);
+WRITE32_HANDLER(nwk_voodoo_0_w);
+WRITE32_HANDLER(nwk_voodoo_1_w);
+
+void draw_7segment_led(mame_bitmap *bitmap, int x, int y, UINT8 value);
+
+#endif
diff --git a/src/mame/machine/leland.c b/src/mame/machine/leland.c
new file mode 100644
index 00000000000..bf0dfe6d6d2
--- /dev/null
+++ b/src/mame/machine/leland.c
@@ -0,0 +1,1494 @@
+/***************************************************************************
+
+ Cinemat/Leland driver
+
+ driver by Aaron Giles and Paul Leaman
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/eeprom.h"
+#include "cpu/z80/z80.h"
+#include "leland.h"
+#include "sound/ay8910.h"
+
+
+/*************************************
+ *
+ * Debugging
+ *
+ *************************************/
+
+/* define these to 0 to disable, or to 1 to enable */
+#define LOG_KEYCARDS 0
+#define LOG_KEYCARDS_FULL 0
+#define LOG_BANKSWITCHING_M 0
+#define LOG_BANKSWITCHING_S 0
+#define LOG_SOUNDPORT 0
+#define LOG_EEPROM 0
+#define LOG_BATTERY_RAM 0
+#define LOG_XROM 0
+
+
+
+/*************************************
+ *
+ * Global variables
+ *
+ *************************************/
+
+UINT8 leland_dac_control;
+
+static UINT8 leland_gfx_control;
+static UINT8 wcol_enable;
+static emu_timer *master_int_timer;
+
+static UINT8 *master_base;
+static UINT8 *slave_base;
+static UINT8 *xrom_base;
+static UINT32 master_length;
+static UINT32 slave_length;
+static UINT32 xrom_length;
+
+static int dangerz_x, dangerz_y;
+static UINT8 analog_result;
+static UINT8 dial_last_input[4];
+static UINT8 dial_last_result[4];
+
+static UINT8 keycard_shift;
+static UINT8 keycard_bit;
+static UINT8 keycard_state;
+static UINT8 keycard_clock;
+static UINT8 keycard_command[3];
+
+static UINT8 top_board_bank;
+static UINT8 sound_port_bank;
+static UINT8 alternate_bank;
+static UINT8 master_bank;
+void (*leland_update_master_bank)(void);
+
+static UINT32 xrom1_addr;
+static UINT32 xrom2_addr;
+
+static UINT8 battery_ram_enable;
+static UINT8 *battery_ram;
+
+static UINT8 *extra_tram;
+
+static UINT8 eeprom_data[128*2];
+
+
+/* Internal routines */
+static TIMER_CALLBACK( leland_interrupt_callback );
+static TIMER_CALLBACK( ataxx_interrupt_callback );
+
+
+
+/*************************************
+ *
+ * Generic dial encoding
+ *
+ *************************************/
+
+static int dial_compute_value(int new_val, int indx)
+{
+ int delta = new_val - (int)dial_last_input[indx];
+ UINT8 result = dial_last_result[indx] & 0x80;
+
+ dial_last_input[indx] = new_val;
+
+ if (delta > 0x80)
+ delta -= 0x100;
+ else if (delta < -0x80)
+ delta += 0x100;
+
+ if (delta < 0)
+ {
+ result = 0x80;
+ delta = -delta;
+ }
+ else if (delta > 0)
+ result = 0x00;
+
+ if (delta > 0x1f)
+ delta = 0x1f;
+ result |= (dial_last_result[indx] + delta) & 0x1f;
+
+ dial_last_result[indx] = result;
+ return result;
+}
+
+
+
+/*************************************
+ *
+ * Cerberus inputs
+ *
+ *************************************/
+
+READ8_HANDLER( cerberus_dial_1_r )
+{
+ int original = readinputport(0);
+ int modified = dial_compute_value(readinputport(4), 0);
+ return (original & 0xc0) | ((modified & 0x80) >> 2) | (modified & 0x1f);
+}
+
+
+READ8_HANDLER( cerberus_dial_2_r )
+{
+ int original = readinputport(2);
+ int modified = dial_compute_value(readinputport(5), 1);
+ return (original & 0xc0) | ((modified & 0x80) >> 2) | (modified & 0x1f);
+}
+
+
+
+/*************************************
+ *
+ * Alley Master inputs
+ *
+ *************************************/
+
+UINT8 *alleymas_kludge_mem;
+
+WRITE8_HANDLER( alleymas_joystick_kludge )
+{
+ /* catch the case where they clear this memory location at PC $1827 and change */
+ /* the value written to be a 1 */
+ if (safe_activecpu_get_pc() == 0x1827)
+ *alleymas_kludge_mem = 1;
+ else
+ *alleymas_kludge_mem = data;
+
+ /* while we're here, make sure the first 3 characters in battery RAM are a */
+ /* valid name; otherwise, it will crash if you start a game and don't enter */
+ /* your name */
+ if (battery_ram[0] == 0)
+ {
+ battery_ram[0] = 'C';
+ battery_ram[1] = 'I';
+ battery_ram[2] = 'N';
+ }
+}
+
+
+
+/*************************************
+ *
+ * Danger Zone inputs
+ *
+ *************************************/
+
+static void update_dangerz_xy(void)
+{
+ UINT8 newy = readinputport(4);
+ UINT8 newx = readinputport(5);
+ int deltay = newy - dial_last_input[0];
+ int deltax = newx - dial_last_input[1];
+
+ if (deltay <= -128) deltay += 256;
+ else if (deltay >= 128) deltay -= 256;
+ if (deltax <= -128) deltax += 256;
+ else if (deltax >= 128) deltax -= 256;
+
+ dangerz_y += deltay;
+ dangerz_x += deltax;
+ if (dangerz_y < 0) dangerz_y = 0;
+ else if (dangerz_y >= 1024) dangerz_y = 1023;
+ if (dangerz_x < 0) dangerz_x = 0;
+ else if (dangerz_x >= 1024) dangerz_x = 1023;
+
+ dial_last_input[0] = newy;
+ dial_last_input[1] = newx;
+}
+
+
+READ8_HANDLER( dangerz_input_y_r )
+{
+ update_dangerz_xy();
+ return dangerz_y & 0xff;
+}
+
+
+READ8_HANDLER( dangerz_input_x_r )
+{
+ update_dangerz_xy();
+ return dangerz_x & 0xff;
+}
+
+
+READ8_HANDLER( dangerz_input_upper_r )
+{
+ update_dangerz_xy();
+ return ((dangerz_y >> 2) & 0xc0) | ((dangerz_x >> 8) & 0x03);
+}
+
+
+
+/*************************************
+ *
+ * Red Line Racer inputs
+ *
+ *************************************/
+
+static const UINT8 redline_pedal_value[8] = { 0xf0, 0xe0, 0xc0, 0xd0, 0x90, 0xb0, 0x30, 0x70 };
+
+READ8_HANDLER( redline_pedal_1_r )
+{
+ int pedal = readinputport(0);
+ return redline_pedal_value[pedal >> 5] | 0x0f;
+}
+
+
+READ8_HANDLER( redline_pedal_2_r )
+{
+ int pedal = readinputport(2);
+ return redline_pedal_value[pedal >> 5] | 0x0f;
+}
+
+
+READ8_HANDLER( redline_wheel_1_r )
+{
+ return dial_compute_value(readinputport(4), 0);
+}
+
+
+READ8_HANDLER( redline_wheel_2_r )
+{
+ return dial_compute_value(readinputport(5), 1);
+}
+
+
+
+/*************************************
+ *
+ * Super Offroad inputs
+ *
+ *************************************/
+
+READ8_HANDLER( offroad_wheel_1_r )
+{
+ return dial_compute_value(readinputport(7), 0);
+}
+
+
+READ8_HANDLER( offroad_wheel_2_r )
+{
+ return dial_compute_value(readinputport(8), 1);
+}
+
+
+READ8_HANDLER( offroad_wheel_3_r )
+{
+ return dial_compute_value(readinputport(9), 2);
+}
+
+
+
+/*************************************
+ *
+ * Ataxx inputs
+ *
+ *************************************/
+
+READ8_HANDLER( ataxx_trackball_r )
+{
+ return dial_compute_value(readinputport(3 + offset), offset);
+}
+
+
+
+/*************************************
+ *
+ * Indy Heat inputs
+ *
+ *************************************/
+
+READ8_HANDLER( indyheat_wheel_r )
+{
+ return dial_compute_value(readinputport(3 + offset), offset);
+}
+
+
+READ8_HANDLER( indyheat_analog_r )
+{
+ switch (offset)
+ {
+ case 0:
+ return 0;
+
+ case 1:
+ return analog_result;
+
+ case 2:
+ return 0;
+
+ case 3:
+ logerror("Unexpected analog read(%02X)\n", 8 + offset);
+ break;
+ }
+ return 0xff;
+}
+
+
+WRITE8_HANDLER( indyheat_analog_w )
+{
+ switch (offset)
+ {
+ case 3:
+ analog_result = readinputport(6 + data);
+ break;
+
+ case 0:
+ case 1:
+ case 2:
+ logerror("Unexpected analog write(%02X) = %02X\n", 8 + offset, data);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Machine initialization
+ *
+ *************************************/
+
+MACHINE_START( leland )
+{
+ /* allocate extra stuff */
+ battery_ram = auto_malloc(LELAND_BATTERY_RAM_SIZE);
+
+ /* start scanline interrupts going */
+ master_int_timer = timer_alloc(leland_interrupt_callback);
+}
+
+
+MACHINE_RESET( leland )
+{
+ timer_adjust(master_int_timer, video_screen_get_time_until_pos(0, 8, 0), 8, attotime_zero);
+
+ /* reset globals */
+ leland_gfx_control = 0x00;
+ leland_sound_port_w(0, 0xff);
+ wcol_enable = 0;
+
+ dangerz_x = 512;
+ dangerz_y = 512;
+ analog_result = 0xff;
+ memset(dial_last_input, 0, sizeof(dial_last_input));
+ memset(dial_last_result, 0, sizeof(dial_last_result));
+
+ keycard_shift = 0;
+ keycard_bit = 0;
+ keycard_state = 0;
+ keycard_clock = 0;
+ memset(keycard_command, 0, sizeof(keycard_command));
+
+ top_board_bank = 0;
+ sound_port_bank = 0;
+ alternate_bank = 0;
+
+ /* initialize the master banks */
+ master_length = memory_region_length(REGION_CPU1);
+ master_base = memory_region(REGION_CPU1);
+ (*leland_update_master_bank)();
+
+ /* initialize the slave banks */
+ slave_length = memory_region_length(REGION_CPU2);
+ slave_base = memory_region(REGION_CPU2);
+ if (slave_length > 0x10000)
+ memory_set_bankptr(3, &slave_base[0x10000]);
+
+ /* if we have an I80186 CPU, reset it */
+ if (machine->drv->cpu[2].type == CPU_I80186)
+ leland_80186_sound_init();
+}
+
+
+MACHINE_START( ataxx )
+{
+ /* set the odd data banks */
+ battery_ram = auto_malloc(LELAND_BATTERY_RAM_SIZE);
+ extra_tram = auto_malloc(ATAXX_EXTRA_TRAM_SIZE);
+
+ /* start scanline interrupts going */
+ master_int_timer = timer_alloc(ataxx_interrupt_callback);
+}
+
+
+MACHINE_RESET( ataxx )
+{
+ memset(extra_tram, 0, ATAXX_EXTRA_TRAM_SIZE);
+ timer_adjust(master_int_timer, video_screen_get_time_until_pos(0, 8, 0), 8, attotime_zero);
+
+ /* initialize the XROM */
+ xrom_length = memory_region_length(REGION_USER1);
+ xrom_base = memory_region(REGION_USER1);
+ xrom1_addr = 0;
+ xrom2_addr = 0;
+
+ /* reset globals */
+ wcol_enable = 0;
+
+ analog_result = 0xff;
+ memset(dial_last_input, 0, sizeof(dial_last_input));
+ memset(dial_last_result, 0, sizeof(dial_last_result));
+
+ master_bank = 0;
+
+ /* initialize the master banks */
+ master_length = memory_region_length(REGION_CPU1);
+ master_base = memory_region(REGION_CPU1);
+ ataxx_bankswitch();
+
+ /* initialize the slave banks */
+ slave_length = memory_region_length(REGION_CPU2);
+ slave_base = memory_region(REGION_CPU2);
+ if (slave_length > 0x10000)
+ memory_set_bankptr(3, &slave_base[0x10000]);
+
+ /* reset the 80186 */
+ leland_80186_sound_init();
+}
+
+
+
+/*************************************
+ *
+ * Master CPU interrupt handling
+ *
+ *************************************/
+
+static TIMER_CALLBACK( leland_interrupt_callback )
+{
+ int scanline = param;
+ extern UINT8 leland_last_scanline_int;
+ leland_last_scanline_int = scanline;
+
+ /* interrupts generated on the VA10 line, which is every */
+ /* 16 scanlines starting with scanline #8 */
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+
+ /* set a timer for the next one */
+ scanline += 16;
+ if (scanline > 248)
+ scanline = 8;
+ timer_adjust(master_int_timer, video_screen_get_time_until_pos(0, scanline, 0), scanline, attotime_zero);
+}
+
+
+static TIMER_CALLBACK( ataxx_interrupt_callback )
+{
+ int scanline = param;
+ extern UINT8 leland_last_scanline_int;
+ leland_last_scanline_int = scanline;
+
+ /* interrupts generated according to the interrupt control register */
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+
+ /* set a timer for the next one */
+ timer_adjust(master_int_timer, video_screen_get_time_until_pos(0, scanline, 0), scanline, attotime_zero);
+}
+
+
+INTERRUPT_GEN( leland_master_interrupt )
+{
+ /* check for coins here */
+ if ((readinputport(1) & 0x0e) != 0x0e)
+ cpunum_set_input_line(0, INPUT_LINE_NMI, ASSERT_LINE);
+}
+
+
+
+/*************************************
+ *
+ * Master CPU bankswitch handlers
+ *
+ *************************************/
+
+WRITE8_HANDLER( leland_master_alt_bankswitch_w )
+{
+ /* update any bankswitching */
+ if (LOG_BANKSWITCHING_M)
+ if ((alternate_bank ^ data) & 0x0f)
+ logerror("%04X:alternate_bank = %02X\n", safe_activecpu_get_pc(), data & 0x0f);
+ alternate_bank = data & 15;
+ (*leland_update_master_bank)();
+
+ /* sound control is in the rest */
+ leland_80186_control_w(offset, data);
+}
+
+
+/* bankswitching for Cerberus */
+void cerberus_bankswitch(void)
+{
+ /* no bankswitching */
+}
+
+
+/* bankswitching for Mayhem 2002, Power Play, World Series Baseball, and Alley Master */
+void mayhem_bankswitch(void)
+{
+ UINT8 *address;
+
+ battery_ram_enable = ((sound_port_bank & 0x24) == 0);
+
+ address = (!(sound_port_bank & 0x04)) ? &master_base[0x10000] : &master_base[0x1c000];
+ memory_set_bankptr(1, address);
+
+ address = battery_ram_enable ? battery_ram : &address[0x8000];
+ memory_set_bankptr(2, address);
+}
+
+
+/* bankswitching for Danger Zone */
+void dangerz_bankswitch(void)
+{
+ UINT8 *address;
+
+ battery_ram_enable = ((top_board_bank & 0x80) != 0);
+
+ address = (!(alternate_bank & 1)) ? &master_base[0x02000] : &master_base[0x12000];
+ memory_set_bankptr(1, address);
+
+ address = battery_ram_enable ? battery_ram : &address[0x8000];
+ memory_set_bankptr(2, address);
+}
+
+
+/* bankswitching for Baseball the Season II, Super Baseball, and Strike Zone */
+void basebal2_bankswitch(void)
+{
+ UINT8 *address;
+
+ battery_ram_enable = (top_board_bank & 0x80);
+
+ if (!battery_ram_enable)
+ address = (!(sound_port_bank & 0x04)) ? &master_base[0x10000] : &master_base[0x1c000];
+ else
+ address = (!(top_board_bank & 0x40)) ? &master_base[0x28000] : &master_base[0x30000];
+ memory_set_bankptr(1, address);
+
+ address = battery_ram_enable ? battery_ram : &address[0x8000];
+ memory_set_bankptr(2, address);
+}
+
+
+/* bankswitching for Red Line Racer */
+void redline_bankswitch(void)
+{
+ static const UINT32 bank_list[] = { 0x10000, 0x18000, 0x02000, 0x02000 };
+ UINT8 *address;
+
+ battery_ram_enable = ((alternate_bank & 3) == 1);
+
+ address = &master_base[bank_list[alternate_bank & 3]];
+ memory_set_bankptr(1, address);
+
+ address = battery_ram_enable ? battery_ram : &master_base[0xa000];
+ memory_set_bankptr(2, address);
+}
+
+
+/* bankswitching for Viper, Quarterback, Team Quarterback, and All American Football */
+void viper_bankswitch(void)
+{
+ static const UINT32 bank_list[] = { 0x02000, 0x10000, 0x18000, 0x02000 };
+ UINT8 *address;
+
+ battery_ram_enable = ((alternate_bank & 0x04) != 0);
+
+ address = &master_base[bank_list[alternate_bank & 3]];
+ if (bank_list[alternate_bank & 3] >= master_length)
+ {
+ logerror("%04X:Master bank %02X out of range!\n", safe_activecpu_get_pc(), alternate_bank & 3);
+ address = &master_base[bank_list[0]];
+ }
+ memory_set_bankptr(1, address);
+
+ address = battery_ram_enable ? battery_ram : &master_base[0xa000];
+ memory_set_bankptr(2, address);
+}
+
+
+/* bankswitching for Super Offroad, Super Offroad Track Pack, and Pig Out */
+void offroad_bankswitch(void)
+{
+ static const UINT32 bank_list[] = { 0x02000, 0x02000, 0x10000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000 };
+ UINT8 *address;
+
+ battery_ram_enable = ((alternate_bank & 7) == 1);
+
+ address = &master_base[bank_list[alternate_bank & 7]];
+ if (bank_list[alternate_bank & 7] >= master_length)
+ {
+ logerror("%04X:Master bank %02X out of range!\n", safe_activecpu_get_pc(), alternate_bank & 7);
+ address = &master_base[bank_list[0]];
+ }
+ memory_set_bankptr(1, address);
+
+ address = battery_ram_enable ? battery_ram : &master_base[0xa000];
+ memory_set_bankptr(2, address);
+}
+
+
+/* bankswitching for Ataxx, WSF, Indy Heat, and Brute Force */
+void ataxx_bankswitch(void)
+{
+ static const UINT32 bank_list[] =
+ {
+ 0x02000, 0x18000, 0x20000, 0x28000, 0x30000, 0x38000, 0x40000, 0x48000,
+ 0x50000, 0x58000, 0x60000, 0x68000, 0x70000, 0x78000, 0x80000, 0x88000
+ };
+ UINT8 *address;
+
+ battery_ram_enable = ((master_bank & 0x30) == 0x10);
+
+ address = &master_base[bank_list[master_bank & 15]];
+ if (bank_list[master_bank & 15] >= master_length)
+ {
+ logerror("%04X:Master bank %02X out of range!\n", safe_activecpu_get_pc(), master_bank & 15);
+ address = &master_base[bank_list[0]];
+ }
+ memory_set_bankptr(1, address);
+
+ if (battery_ram_enable)
+ address = battery_ram;
+ else if ((master_bank & 0x30) == 0x20)
+ address = &ataxx_qram[(master_bank & 0xc0) << 8];
+ else
+ address = &master_base[0xa000];
+ memory_set_bankptr(2, address);
+
+ wcol_enable = ((master_bank & 0x30) == 0x30);
+}
+
+
+
+/*************************************
+ *
+ * EEPROM handling (64 x 16bits)
+ *
+ *************************************/
+
+void leland_init_eeprom(UINT8 default_val, const UINT16 *data, UINT8 serial_offset, UINT8 serial_type)
+{
+ static struct EEPROM_interface eeprom_interface =
+ {
+ 6,
+ 16,
+ "110",
+ "101",
+ "111"
+ };
+ UINT8 xorval = (serial_type == SERIAL_TYPE_ADD_XOR || serial_type == SERIAL_TYPE_ENCRYPT_XOR) ? 0xff : 0x00;
+ UINT32 serial;
+
+ /* initialize everything to the default value */
+ memset(eeprom_data, default_val, sizeof(eeprom_data));
+
+ /* fill in the preset data */
+ while (*data != 0xffff)
+ {
+ int offset = *data++;
+ int value = *data++;
+ eeprom_data[offset * 2 + 0] = value >> 8;
+ eeprom_data[offset * 2 + 1] = value & 0xff;
+ }
+
+ /* pick a serial number -- examples of real serial numbers:
+
+ Team QB: 21101957
+ AAFB: 26101119 and 26101039
+ */
+ serial = 0x12345678;
+
+ /* switch off the serial number type */
+ switch (serial_type)
+ {
+ case SERIAL_TYPE_ADD:
+ case SERIAL_TYPE_ADD_XOR:
+ {
+ int i;
+ for (i = 0; i < 10; i++)
+ {
+ int digit;
+
+ if (i >= 8)
+ digit = 0;
+ else
+ digit = ((serial << (i * 4)) >> 28) & 15;
+ digit = ('0' + digit) * 2;
+
+ eeprom_data[serial_offset * 2 + 0 + (i ^ 1)] = (digit / 3) ^ xorval;
+ eeprom_data[serial_offset * 2 + 10 + (i ^ 1)] = (digit / 3) ^ xorval;
+ eeprom_data[serial_offset * 2 + 20 + (i ^ 1)] = (digit - (2 * (digit / 3))) ^ xorval;
+ }
+ break;
+ }
+
+ case SERIAL_TYPE_ENCRYPT:
+ case SERIAL_TYPE_ENCRYPT_XOR:
+ {
+ int d, e, h, l;
+
+ /* break the serial number out into pieces */
+ l = (serial >> 24) & 0xff;
+ h = (serial >> 16) & 0xff;
+ e = (serial >> 8) & 0xff;
+ d = serial & 0xff;
+
+ /* decrypt the data */
+ h = ((h ^ 0x2a ^ l) ^ 0xff) + 5;
+ d = ((d + 0x2a) ^ e) ^ 0xff;
+ l ^= e;
+ e ^= 0x2a;
+
+ /* store the bytes */
+ eeprom_data[serial_offset * 2 + 0] = h ^ xorval;
+ eeprom_data[serial_offset * 2 + 1] = l ^ xorval;
+ eeprom_data[serial_offset * 2 + 2] = d ^ xorval;
+ eeprom_data[serial_offset * 2 + 3] = e ^ xorval;
+ break;
+ }
+ }
+
+ EEPROM_init(&eeprom_interface);
+}
+
+
+
+/*************************************
+ *
+ * EEPROM handling (128 x 16bits)
+ *
+ *************************************/
+
+void ataxx_init_eeprom(UINT8 default_val, const UINT16 *data, UINT8 serial_offset)
+{
+ static struct EEPROM_interface eeprom_interface =
+ {
+ 7,
+ 16,
+ "000001100",
+ "000001010",
+ 0,
+ "0000010000000000",
+ "0000010011000000",
+ 1
+ };
+ UINT32 serial;
+
+ /* initialize everything to the default value */
+ memset(eeprom_data, default_val, sizeof(eeprom_data));
+
+ /* fill in the preset data */
+ while (*data != 0xffff)
+ {
+ int offset = *data++;
+ int value = *data++;
+ eeprom_data[offset * 2 + 0] = value >> 8;
+ eeprom_data[offset * 2 + 1] = value & 0xff;
+ }
+
+ /* pick a serial number -- examples of real serial numbers:
+
+ WSF: 30101190
+ Indy Heat: 31201339
+ */
+ serial = 0x12345678;
+
+ /* encrypt the serial number */
+ {
+ int d, e, h, l;
+
+ /* break the serial number out into pieces */
+ l = (serial >> 24) & 0xff;
+ h = (serial >> 16) & 0xff;
+ e = (serial >> 8) & 0xff;
+ d = serial & 0xff;
+
+ /* decrypt the data */
+ h = ((h ^ 0x2a ^ l) ^ 0xff) + 5;
+ d = ((d + 0x2a) ^ e) ^ 0xff;
+ l ^= e;
+ e ^= 0x2a;
+
+ /* store the bytes */
+ eeprom_data[serial_offset * 2 + 0] = h;
+ eeprom_data[serial_offset * 2 + 1] = l;
+ eeprom_data[serial_offset * 2 + 2] = d;
+ eeprom_data[serial_offset * 2 + 3] = e;
+ }
+
+ /* compute the checksum */
+ {
+ int i, sum = 0;
+ for (i = 0; i < 0x7f * 2; i++)
+ sum += eeprom_data[i];
+ sum ^= 0xffff;
+ eeprom_data[0x7f * 2 + 0] = (sum >> 8) & 0xff;
+ eeprom_data[0x7f * 2 + 1] = sum & 0xff;
+
+ EEPROM_init(&eeprom_interface);
+ }
+}
+
+
+
+/*************************************
+ *
+ * Ataxx EEPROM interfacing
+ *
+ *************************************/
+
+READ8_HANDLER( ataxx_eeprom_r )
+{
+ int port = readinputport(2);
+ if (LOG_EEPROM) logerror("%04X:EE read\n", safe_activecpu_get_pc());
+ return (port & ~0x01) | EEPROM_read_bit();
+}
+
+
+WRITE8_HANDLER( ataxx_eeprom_w )
+{
+ if (LOG_EEPROM) logerror("%04X:EE write %d%d%d\n", safe_activecpu_get_pc(),
+ (data >> 6) & 1, (data >> 5) & 1, (data >> 4) & 1);
+ EEPROM_write_bit ((data & 0x10) >> 4);
+ EEPROM_set_clock_line((data & 0x20) ? ASSERT_LINE : CLEAR_LINE);
+ EEPROM_set_cs_line ((~data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+
+/*************************************
+ *
+ * Battery backed RAM
+ *
+ *************************************/
+
+WRITE8_HANDLER( leland_battery_ram_w )
+{
+ if (battery_ram_enable)
+ {
+ if (LOG_BATTERY_RAM) logerror("%04X:BatteryW@%04X=%02X\n", safe_activecpu_get_pc(), offset, data);
+ battery_ram[offset] = data;
+ }
+ else
+ logerror("%04X:BatteryW@%04X (invalid!)\n", safe_activecpu_get_pc(), offset);
+}
+
+
+WRITE8_HANDLER( ataxx_battery_ram_w )
+{
+ if (battery_ram_enable)
+ {
+ if (LOG_BATTERY_RAM) logerror("%04X:BatteryW@%04X=%02X\n", safe_activecpu_get_pc(), offset, data);
+ battery_ram[offset] = data;
+ }
+ else if ((master_bank & 0x30) == 0x20)
+ ataxx_qram[((master_bank & 0xc0) << 8) + offset] = data;
+ else
+ logerror("%04X:BatteryW@%04X (invalid!)\n", safe_activecpu_get_pc(), offset);
+}
+
+
+NVRAM_HANDLER( leland )
+{
+ if (read_or_write)
+ {
+ EEPROM_save(file);
+ mame_fwrite(file, battery_ram, LELAND_BATTERY_RAM_SIZE);
+ }
+ else if (file)
+ {
+ EEPROM_load(file);
+ mame_fread(file, battery_ram, LELAND_BATTERY_RAM_SIZE);
+ }
+ else
+ {
+ EEPROM_set_data(eeprom_data, 64*2);
+ memset(battery_ram, 0x00, LELAND_BATTERY_RAM_SIZE);
+ }
+}
+
+
+NVRAM_HANDLER( ataxx )
+{
+ if (read_or_write)
+ {
+ EEPROM_save(file);
+ mame_fwrite(file, battery_ram, LELAND_BATTERY_RAM_SIZE);
+ }
+ else if (file)
+ {
+ EEPROM_load(file);
+ mame_fread(file, battery_ram, LELAND_BATTERY_RAM_SIZE);
+ }
+ else
+ {
+ EEPROM_set_data(eeprom_data, 128*2);
+ memset(battery_ram, 0x00, LELAND_BATTERY_RAM_SIZE);
+ }
+}
+
+
+/*************************************
+ *
+ * Master CPU keycard I/O
+ *
+ ************************************/
+
+/*--------------------------------------------------------------------
+
+ A note about keycards:
+
+ These were apparently static programmable ROMs that could be
+ inserted into certain games. The games would then save/load
+ statistics on them.
+
+ The data is accessed via a serial protocol, which is
+ implemented below. There are two known commands that are
+ written; each command is 3 bytes and accesses 128 bytes of
+ data from the keycard:
+
+ 62 00 80
+ 9D 00 80
+
+ the last byte appears to specify the length of data to transfer.
+
+ The format of the data on the card is pretty heavily encrypted.
+ The first 7 bytes read serves as a header:
+
+ D5 43 49 4E 2A xx yy
+
+ where xx is a game-specific key, and yy is the complement of the
+ key. For example, World Series Baseball uses 04/FB. Alley Master
+ uses 05/FA.
+
+ The last 112 bytes of data is encrypted via the following method:
+
+ for (i = 16, b = 0x70, r = 0x08; i < 128; i++, b--, r += 0x10)
+ {
+ UINT8 a = original_data[i] ^ 0xff;
+ a = (a >> 3) | (a << 5);
+ a = (((a ^ r) + 1 + b) ^ b) - b;
+ encrypted_data[i] = a;
+ }
+
+ The data that is encrypted is stored alternating with a checksum
+ byte. The checksum for a value A is ((A ^ 0xa5) + 0x27) ^ 0x34.
+
+--------------------------------------------------------------------*/
+
+static int keycard_r(void)
+{
+ int result = 0;
+
+ if (LOG_KEYCARDS_FULL) logerror(" (%04X:keycard_r)\n", safe_activecpu_get_pc());
+
+ /* if we have a valid keycard read state, we're reading from the keycard */
+ if (keycard_state & 0x80)
+ {
+ /* clock in new data */
+ if (keycard_bit == 1)
+ {
+ keycard_shift = 0xff; /* no data, but this is where we would clock it in */
+ if (LOG_KEYCARDS) logerror(" (clocked in %02X)\n", keycard_shift);
+ }
+
+ /* clock in the bit */
+ result = (~keycard_shift & 1) << ((keycard_state >> 4) & 3);
+ if (LOG_KEYCARDS) logerror(" (read %02X)\n", result);
+ }
+ return result;
+}
+
+static void keycard_w(int data)
+{
+ int new_state = data & 0xb0;
+ int new_clock = data & 0x40;
+
+ if (LOG_KEYCARDS_FULL) logerror(" (%04X:keycard_w=%02X)\n", safe_activecpu_get_pc(), data);
+
+ /* check for going active */
+ if (!keycard_state && new_state)
+ {
+ keycard_command[0] = keycard_command[1] = keycard_command[2] = 0;
+ if (LOG_KEYCARDS) logerror("keycard going active (state=%02X)\n", new_state);
+ }
+
+ /* check for going inactive */
+ else if (keycard_state && !new_state)
+ {
+ keycard_command[0] = keycard_command[1] = keycard_command[2] = 0;
+ if (LOG_KEYCARDS) logerror("keycard going inactive\n");
+ }
+
+ /* check for clocks */
+ else if (keycard_state == new_state)
+ {
+ /* work off of falling edge */
+ if (!new_clock && keycard_clock)
+ {
+ keycard_shift >>= 1;
+ keycard_bit = (keycard_bit + 1) & 7;
+ }
+
+ /* look for a bit write */
+ else if (!new_clock && !keycard_clock && !(data & 0x80))
+ {
+ if (LOG_KEYCARDS) logerror(" (write %02X)\n", data);
+
+ keycard_shift &= ~0x80;
+ if (data & (1 << ((new_state >> 4) & 3)))
+ keycard_shift |= 0x80;
+
+ /* clock out the data on the last bit */
+ if (keycard_bit == 7)
+ {
+ if (LOG_KEYCARDS) logerror(" (clocked out %02X)\n", keycard_shift);
+ keycard_command[0] = keycard_command[1];
+ keycard_command[1] = keycard_command[2];
+ keycard_command[2] = keycard_shift;
+ if (keycard_command[0] == 0x62 && keycard_command[1] == 0x00 && keycard_command[2] == 0x80)
+ {
+ if (LOG_KEYCARDS) logerror(" (got command $62)\n");
+ }
+ }
+ }
+ }
+
+ /* error case */
+ else
+ {
+ /* only an error if the selected bit changes; read/write transitions are okay */
+ if ((new_state & 0x30) != (keycard_state & 0x30))
+ if (LOG_KEYCARDS) logerror("ERROR: Caught keycard state transition %02X -> %02X\n", keycard_state, new_state);
+ }
+
+ keycard_state = new_state;
+ keycard_clock = new_clock;
+}
+
+
+
+/*************************************
+ *
+ * Master CPU analog and keycard I/O
+ *
+ *************************************/
+
+READ8_HANDLER( leland_master_analog_key_r )
+{
+ int result = 0;
+
+ switch (offset)
+ {
+ case 0x00: /* FD = analog data read */
+ result = analog_result;
+ break;
+
+ case 0x01: /* FE = analog status read */
+ /* bit 7 indicates the analog input is busy for some games */
+ result = 0x00;
+ break;
+
+ case 0x02: /* FF = keycard serial data read */
+ result = keycard_r();
+
+ /* bit 7 indicates the analog input is busy for some games */
+ result &= ~0x80;
+ break;
+ }
+ return result;
+}
+
+
+
+WRITE8_HANDLER( leland_master_analog_key_w )
+{
+ switch (offset)
+ {
+ case 0x00: /* FD = analog port trigger */
+ break;
+
+ case 0x01: /* FE = analog port select/bankswitch */
+ analog_result = readinputport((data & 15) + 4);
+
+ /* update top board banking for some games */
+ if (LOG_BANKSWITCHING_M)
+ if ((top_board_bank ^ data) & 0xc0)
+ logerror("%04X:top_board_bank = %02X\n", safe_activecpu_get_pc(), data & 0xc0);
+ top_board_bank = data & 0xc0;
+ (*leland_update_master_bank)();
+ break;
+
+ case 0x02: /* FF = keycard data write */
+ keycard_w(data);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Master CPU internal I/O
+ *
+ *************************************/
+
+READ8_HANDLER( leland_master_input_r )
+{
+ int result = 0xff;
+
+ switch (offset)
+ {
+ case 0x00: /* /GIN0 */
+ result = readinputport(0);
+ break;
+
+ case 0x01: /* /GIN1 */
+ result = readinputport(1);
+ if (cpunum_get_reg(1, Z80_HALT))
+ result ^= 0x01;
+ break;
+
+ case 0x02: /* /GIN2 */
+ case 0x12:
+ cpunum_set_input_line(0, INPUT_LINE_NMI, CLEAR_LINE);
+ break;
+
+ case 0x03: /* /IGID */
+ case 0x13:
+ result = AY8910_read_port_0_r(offset);
+ break;
+
+ case 0x10: /* /GIN0 */
+ result = readinputport(2);
+ break;
+
+ case 0x11: /* /GIN1 */
+ result = readinputport(3);
+ if (LOG_EEPROM) logerror("%04X:EE read\n", safe_activecpu_get_pc());
+ result = (result & ~0x01) | EEPROM_read_bit();
+ break;
+
+ default:
+ logerror("Master I/O read offset %02X\n", offset);
+ break;
+ }
+ return result;
+}
+
+
+WRITE8_HANDLER( leland_master_output_w )
+{
+ switch (offset)
+ {
+ case 0x09: /* /MCONT */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (data & 0x01) ? CLEAR_LINE : ASSERT_LINE);
+ wcol_enable = (data & 0x02);
+ cpunum_set_input_line(1, INPUT_LINE_NMI, (data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
+ cpunum_set_input_line (1, 0, (data & 0x08) ? CLEAR_LINE : ASSERT_LINE);
+
+ if (LOG_EEPROM) logerror("%04X:EE write %d%d%d\n", safe_activecpu_get_pc(),
+ (data >> 6) & 1, (data >> 5) & 1, (data >> 4) & 1);
+ EEPROM_write_bit ((data & 0x10) >> 4);
+ EEPROM_set_clock_line((data & 0x20) ? ASSERT_LINE : CLEAR_LINE);
+ EEPROM_set_cs_line ((~data & 0x40) ? ASSERT_LINE : CLEAR_LINE);
+ break;
+
+ case 0x0a: /* /OGIA */
+ AY8910_control_port_0_w(0, data);
+ break;
+
+ case 0x0b: /* /OGID */
+ AY8910_write_port_0_w(0, data);
+ break;
+
+ case 0x0c: /* /BKXL */
+ case 0x0d: /* /BKXH */
+ case 0x0e: /* /BKYL */
+ case 0x0f: /* /BKYH */
+ leland_gfx_port_w(offset - 0x0c, data);
+ break;
+
+ default:
+ logerror("Master I/O write offset %02X=%02X\n", offset, data);
+ break;
+ }
+}
+
+
+READ8_HANDLER( ataxx_master_input_r )
+{
+ int result = 0xff;
+
+ switch (offset)
+ {
+ case 0x06: /* /GIN0 */
+ result = readinputport(0);
+ break;
+
+ case 0x07: /* /SLVBLK */
+ result = readinputport(1);
+ if (cpunum_get_reg(1, Z80_HALT))
+ result ^= 0x01;
+ break;
+
+ default:
+ logerror("Master I/O read offset %02X\n", offset);
+ break;
+ }
+ return result;
+}
+
+
+WRITE8_HANDLER( ataxx_master_output_w )
+{
+ switch (offset)
+ {
+ case 0x00: /* /BKXL */
+ case 0x01: /* /BKXH */
+ case 0x02: /* /BKYL */
+ case 0x03: /* /BKYH */
+ leland_gfx_port_w(offset, data);
+ break;
+
+ case 0x04: /* /MBNK */
+ if (LOG_BANKSWITCHING_M)
+ if ((master_bank ^ data) & 0xff)
+ logerror("%04X:master_bank = %02X\n", safe_activecpu_get_pc(), data & 0xff);
+ master_bank = data;
+ ataxx_bankswitch();
+ break;
+
+ case 0x05: /* /SLV0 */
+ cpunum_set_input_line(1, 0, (data & 0x01) ? CLEAR_LINE : ASSERT_LINE);
+ cpunum_set_input_line(1, INPUT_LINE_NMI, (data & 0x04) ? CLEAR_LINE : ASSERT_LINE);
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
+ break;
+
+ case 0x08: /* */
+ timer_adjust(master_int_timer, video_screen_get_time_until_pos(0, data + 1, 0), data + 1, attotime_zero);
+ break;
+
+ default:
+ logerror("Master I/O write offset %02X=%02X\n", offset, data);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Master CPU palette gates
+ *
+ *************************************/
+
+WRITE8_HANDLER( leland_gated_paletteram_w )
+{
+ if (wcol_enable)
+ paletteram_BBGGGRRR_w(offset, data);
+}
+
+
+READ8_HANDLER( leland_gated_paletteram_r )
+{
+ if (wcol_enable)
+ return paletteram_r(offset);
+ return 0xff;
+}
+
+
+WRITE8_HANDLER( ataxx_paletteram_and_misc_w )
+{
+ if (wcol_enable)
+ paletteram_xxxxRRRRGGGGBBBB_le_w(offset, data);
+ else if (offset == 0x7f8 || offset == 0x7f9)
+ leland_master_video_addr_w(offset - 0x7f8, data);
+ else if (offset == 0x7fc)
+ {
+ xrom1_addr = (xrom1_addr & 0xff00) | (data & 0x00ff);
+ if (LOG_XROM) logerror("%04X:XROM1 address low write = %02X (addr=%04X)\n", safe_activecpu_get_pc(), data, xrom1_addr);
+ }
+ else if (offset == 0x7fd)
+ {
+ xrom1_addr = (xrom1_addr & 0x00ff) | ((data << 8) & 0xff00);
+ if (LOG_XROM) logerror("%04X:XROM1 address high write = %02X (addr=%04X)\n", safe_activecpu_get_pc(), data, xrom1_addr);
+ }
+ else if (offset == 0x7fe)
+ {
+ xrom2_addr = (xrom2_addr & 0xff00) | (data & 0x00ff);
+ if (LOG_XROM) logerror("%04X:XROM2 address low write = %02X (addr=%04X)\n", safe_activecpu_get_pc(), data, xrom2_addr);
+ }
+ else if (offset == 0x7ff)
+ {
+ xrom2_addr = (xrom2_addr & 0x00ff) | ((data << 8) & 0xff00);
+ if (LOG_XROM) logerror("%04X:XROM2 address high write = %02X (addr=%04X)\n", safe_activecpu_get_pc(), data, xrom2_addr);
+ }
+ else
+ extra_tram[offset] = data;
+}
+
+
+READ8_HANDLER( ataxx_paletteram_and_misc_r )
+{
+ if (wcol_enable)
+ return paletteram_r(offset);
+ else if (offset == 0x7fc || offset == 0x7fd)
+ {
+ int result = xrom_base[0x00000 | xrom1_addr | ((offset & 1) << 16)];
+ if (LOG_XROM) logerror("%04X:XROM1 read(%d) = %02X (addr=%04X)\n", safe_activecpu_get_pc(), offset - 0x7fc, result, xrom1_addr);
+ return result;
+ }
+ else if (offset == 0x7fe || offset == 0x7ff)
+ {
+ int result = xrom_base[0x20000 | xrom2_addr | ((offset & 1) << 16)];
+ if (LOG_XROM) logerror("%04X:XROM2 read(%d) = %02X (addr=%04X)\n", safe_activecpu_get_pc(), offset - 0x7fc, result, xrom2_addr);
+ return result;
+ }
+ else
+ return extra_tram[offset];
+}
+
+
+
+/*************************************
+ *
+ * AY8910-controlled graphics latch
+ *
+ *************************************/
+
+READ8_HANDLER( leland_sound_port_r )
+{
+ return leland_gfx_control;
+}
+
+
+WRITE8_HANDLER( leland_sound_port_w )
+{
+ int gfx_banks = Machine->gfx[0]->total_elements / 0x400;
+ int gfx_bank_mask = (gfx_banks - 1) << 4;
+ int diff = data ^ leland_gfx_control;
+
+ /* update the graphics banking if necessary */
+ if ((diff & 0x08) || (diff & gfx_bank_mask))
+ leland_gfx_port_w(-1, data);
+
+ /* set the new value */
+ leland_gfx_control = data;
+ leland_dac_control &= data & 3;
+
+ /* some bankswitching occurs here */
+ if (LOG_BANKSWITCHING_M)
+ if ((sound_port_bank ^ data) & 0x24)
+ logerror("%04X:sound_port_bank = %02X\n", safe_activecpu_get_pc(), data & 0x24);
+ sound_port_bank = data & 0x24;
+ (*leland_update_master_bank)();
+}
+
+
+
+/*************************************
+ *
+ * Slave CPU bankswitching
+ *
+ *************************************/
+
+WRITE8_HANDLER( leland_slave_small_banksw_w )
+{
+ int bankaddress = 0x10000 + 0xc000 * (data & 1);
+
+ if (bankaddress >= slave_length)
+ {
+ logerror("%04X:Slave bank %02X out of range!", safe_activecpu_get_pc(), data & 1);
+ bankaddress = 0x10000;
+ }
+ memory_set_bankptr(3, &slave_base[bankaddress]);
+
+ if (LOG_BANKSWITCHING_S) logerror("%04X:Slave bank = %02X (%05X)\n", safe_activecpu_get_pc(), data & 1, bankaddress);
+}
+
+
+WRITE8_HANDLER( leland_slave_large_banksw_w )
+{
+ int bankaddress = 0x10000 + 0x8000 * (data & 15);
+
+ if (bankaddress >= slave_length)
+ {
+ logerror("%04X:Slave bank %02X out of range!", safe_activecpu_get_pc(), data & 15);
+ bankaddress = 0x10000;
+ }
+ memory_set_bankptr(3, &slave_base[bankaddress]);
+
+ if (LOG_BANKSWITCHING_S) logerror("%04X:Slave bank = %02X (%05X)\n", safe_activecpu_get_pc(), data & 15, bankaddress);
+}
+
+
+WRITE8_HANDLER( ataxx_slave_banksw_w )
+{
+ int bankaddress, bank = data & 15;
+
+ if (bank == 0)
+ bankaddress = 0x2000;
+ else
+ {
+ bankaddress = 0x10000 * bank + 0x8000 * ((data >> 4) & 1);
+ if (slave_length > 0x100000)
+ bankaddress += 0x100000 * ((data >> 5) & 1);
+ }
+
+ if (bankaddress >= slave_length)
+ {
+ logerror("%04X:Slave bank %02X out of range!", safe_activecpu_get_pc(), data & 0x3f);
+ bankaddress = 0x2000;
+ }
+ memory_set_bankptr(3, &slave_base[bankaddress]);
+
+ if (LOG_BANKSWITCHING_S) logerror("%04X:Slave bank = %02X (%05X)\n", safe_activecpu_get_pc(), data, bankaddress);
+}
+
+
+
+/*************************************
+ *
+ * Slave CPU I/O
+ *
+ *************************************/
+
+READ8_HANDLER( leland_raster_r )
+{
+ return video_screen_get_vpos(0);
+}
+
+
+
+/*************************************
+ *
+ * Driver initialization
+ *
+ *************************************/
+
+/* also called by Ataxx */
+void leland_rotate_memory(int cpunum)
+{
+ int startaddr = 0x10000;
+ int banks = (memory_region_length(REGION_CPU1 + cpunum) - startaddr) / 0x8000;
+ UINT8 *ram = memory_region(REGION_CPU1 + cpunum);
+ UINT8 temp[0x2000];
+ int i;
+
+ for (i = 0; i < banks; i++)
+ {
+ memmove(temp, &ram[startaddr + 0x0000], 0x2000);
+ memmove(&ram[startaddr + 0x0000], &ram[startaddr + 0x2000], 0x6000);
+ memmove(&ram[startaddr + 0x6000], temp, 0x2000);
+ startaddr += 0x8000;
+ }
+}
diff --git a/src/mame/machine/lkage.c b/src/mame/machine/lkage.c
new file mode 100644
index 00000000000..da03af1a1f4
--- /dev/null
+++ b/src/mame/machine/lkage.c
@@ -0,0 +1,139 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+
+/***************************************************************************
+
+ Legend of Kage 68705 protection interface
+
+ The following is ENTIRELY GUESSWORK!!!
+ And moreover, the game seems to work anyway regardless of what the mcu returns.
+
+***************************************************************************/
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( lkage_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( lkage_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( lkage_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 1 W when 1->0, enables latch which brings the command from main CPU (read from port A)
+ * 2 W when 0->1, copies port A to the latch for the main CPU
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( lkage_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( lkage_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ if (main_sent) cpunum_set_input_line(2,0,CLEAR_LINE);
+ main_sent = 0;
+logerror("read command %02x from main cpu\n",portA_in);
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+logerror("send command %02x to main cpu\n",portA_out);
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( lkage_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( lkage_68705_portC_r )
+{
+ portC_in = 0;
+ if (main_sent) portC_in |= 0x01;
+ if (!mcu_sent) portC_in |= 0x02;
+//logerror("%04x: 68705 port C read %02x\n",activecpu_get_pc(),portC_in);
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( lkage_68705_portC_w )
+{
+logerror("%04x: 68705 port C write %02x\n",activecpu_get_pc(),data);
+ portC_out = data;
+}
+
+WRITE8_HANDLER( lkage_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+
+WRITE8_HANDLER( lkage_mcu_w )
+{
+logerror("%04x: mcu_w %02x\n",activecpu_get_pc(),data);
+ from_main = data;
+ main_sent = 1;
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+}
+
+READ8_HANDLER( lkage_mcu_r )
+{
+logerror("%04x: mcu_r %02x\n",activecpu_get_pc(),from_mcu);
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( lkage_mcu_status_r )
+{
+ int res = 0;
+
+ /* bit 0 = when 1, mcu is ready to receive data from main cpu */
+ /* bit 1 = when 1, mcu has sent data to the main cpu */
+//logerror("%04x: mcu_status_r\n",activecpu_get_pc());
+ if (!main_sent) res |= 0x01;
+ if (mcu_sent) res |= 0x02;
+
+ return res;
+}
diff --git a/src/mame/machine/lsasquad.c b/src/mame/machine/lsasquad.c
new file mode 100644
index 00000000000..cd054fe2f9b
--- /dev/null
+++ b/src/mame/machine/lsasquad.c
@@ -0,0 +1,192 @@
+#include "driver.h"
+#include "cpu/z80/z80.h"
+
+
+/* coin inputs are inverted in storming */
+int lsasquad_invertcoin;
+
+
+/***************************************************************************
+
+ main <-> sound CPU communication
+
+***************************************************************************/
+
+static int sound_nmi_enable,pending_nmi,sound_cmd,sound_result;
+int lsasquad_sound_pending;
+
+static TIMER_CALLBACK( nmi_callback )
+{
+ if (sound_nmi_enable) cpunum_set_input_line(1,INPUT_LINE_NMI,PULSE_LINE);
+ else pending_nmi = 1;
+}
+
+WRITE8_HANDLER( lsasquad_sh_nmi_disable_w )
+{
+ sound_nmi_enable = 0;
+}
+
+WRITE8_HANDLER( lsasquad_sh_nmi_enable_w )
+{
+ sound_nmi_enable = 1;
+ if (pending_nmi)
+ {
+ cpunum_set_input_line(1,INPUT_LINE_NMI,PULSE_LINE);
+ pending_nmi = 0;
+ }
+}
+
+WRITE8_HANDLER( lsasquad_sound_command_w )
+{
+ lsasquad_sound_pending |= 0x01;
+ sound_cmd = data;
+//logerror("%04x: sound cmd %02x\n",activecpu_get_pc(),data);
+ timer_call_after_resynch(data,nmi_callback);
+}
+
+READ8_HANDLER( lsasquad_sh_sound_command_r )
+{
+ lsasquad_sound_pending &= ~0x01;
+//logerror("%04x: read sound cmd %02x\n",activecpu_get_pc(),sound_cmd);
+ return sound_cmd;
+}
+
+WRITE8_HANDLER( lsasquad_sh_result_w )
+{
+ lsasquad_sound_pending |= 0x02;
+//logerror("%04x: sound res %02x\n",activecpu_get_pc(),data);
+ sound_result = data;
+}
+
+READ8_HANDLER( lsasquad_sound_result_r )
+{
+ lsasquad_sound_pending &= ~0x02;
+//logerror("%04x: read sound res %02x\n",activecpu_get_pc(),sound_result);
+ return sound_result;
+}
+
+READ8_HANDLER( lsasquad_sound_status_r )
+{
+ /* bit 0: message pending for sound cpu */
+ /* bit 1: message pending for main cpu */
+ return lsasquad_sound_pending;
+}
+
+
+READ8_HANDLER( daikaiju_sh_sound_command_r )
+{
+ lsasquad_sound_pending &= ~0x01;
+ lsasquad_sound_pending |= 0x02;
+//logerror("%04x: read sound cmd %02x\n",activecpu_get_pc(),sound_cmd);
+ return sound_cmd;
+}
+
+READ8_HANDLER( daikaiju_sound_status_r )
+{
+ /* bit 0: message pending for sound cpu */
+ /* bit 1: message pending for main cpu */
+ return lsasquad_sound_pending^3;
+}
+
+
+/***************************************************************************
+
+ LSA Squad 68705 protection interface
+
+ The following is ENTIRELY GUESSWORK!!!
+
+***************************************************************************/
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( lsasquad_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( lsasquad_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( lsasquad_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 1 W when 1->0, enables latch which brings the command from main CPU (read from port A)
+ * 2 W when 0->1, copies port A to the latch for the main CPU
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( lsasquad_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( lsasquad_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ if (main_sent) cpunum_set_input_line(2,0,CLEAR_LINE);
+ main_sent = 0;
+//logerror("read command %02x from main cpu\n",portA_in);
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+//logerror("send command %02x to main cpu\n",portA_out);
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( lsasquad_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+WRITE8_HANDLER( lsasquad_mcu_w )
+{
+//logerror("%04x: mcu_w %02x\n",activecpu_get_pc(),data);
+ from_main = data;
+ main_sent = 1;
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+}
+
+READ8_HANDLER( lsasquad_mcu_r )
+{
+//logerror("%04x: mcu_r %02x\n",activecpu_get_pc(),from_mcu);
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( lsasquad_mcu_status_r )
+{
+ int res = input_port_3_r(0);
+
+ /* bit 0 = when 1, mcu is ready to receive data from main cpu */
+ /* bit 1 = when 0, mcu has sent data to the main cpu */
+//logerror("%04x: mcu_status_r\n",activecpu_get_pc());
+ if (!main_sent) res |= 0x01;
+ if (!mcu_sent) res |= 0x02;
+
+ return res ^ lsasquad_invertcoin;
+}
diff --git a/src/mame/machine/m68kfmly.c b/src/mame/machine/m68kfmly.c
new file mode 100644
index 00000000000..ce980e328fc
--- /dev/null
+++ b/src/mame/machine/m68kfmly.c
@@ -0,0 +1,236 @@
+/******************************************************************************
+
+ TMP68301 support (dummy) driver
+
+ Driver by Takahiro Nogi <nogi@kt.rim.or.jp> 2000/12/23 -
+
+******************************************************************************/
+/******************************************************************************
+Memo:
+
+******************************************************************************/
+
+#include "driver.h"
+#include "m68kfmly.h"
+#include "cpu/m68000/m68000.h"
+
+
+#define TMP68301_DEBUG 0
+
+
+// TMP68301 System Memory Map
+//
+// 0xFFFC00 - 0xFFFC0F TMP68301 Address decoder
+// 0xFFFC80 - 0xFFFC9F TMP68301 Interrupt controller
+// 0xFFFD00 - 0xFFFD0F TMP68301 Parallel interface
+// 0xFFFD80 - 0xFFFDAF TMP68301 Serial interface
+// 0xFFFE00 - 0xFFFE4F TMP68301 Timer
+//
+// Address decoder
+// 15 7
+// 0xFFFC00 AMAR0 AAMR0
+// 0xFFFC02 - AACR0
+// 0xFFFC04 AMAR1 AAMR1
+// 0xFFFC06 - AACR1
+// 0xFFFC08 - AACR2
+// 0xFFFC0A - ATOR
+// 0xFFFC0C ARELR
+// 0xFFFC0E - -
+//
+// Interrupt controller
+// 15 7
+// 0xFFFC80 - ICR0
+// 0xFFFC82 - ICR1
+// 0xFFFC84 - ICR2
+// 0xFFFC86 - ICR3
+// 0xFFFC88 - ICR4
+// 0xFFFC8A - ICR5
+// 0xFFFC8C - ICR6
+// 0xFFFC8E - ICR7
+// 0xFFFC90 - ICR8
+// 0xFFFC92 - ICR9
+// 0xFFFC94 IMR
+// 0xFFFC96 IPR
+// 0xFFFC98 IISR
+// 0xFFFC9A - IVNR
+// 0xFFFC9C - IEIR
+// 0xFFFC9E - -
+//
+// Parallel interface
+// 15 7
+// 0xFFFD00 PDIR
+// 0xFFFD02 - PCR
+// 0xFFFD04 - PSR
+// 0xFFFD06 - PCMR
+// 0xFFFD08 - PMR
+// 0xFFFD0A PDR
+// 0xFFFD0C - PPR1
+// 0xFFFD0E - PPR2
+//
+// Serial interface
+// 15 7
+// 0xFFFD80 - SMR0
+// 0xFFFD82 - SCMR0
+// 0xFFFD84 - SBRR0
+// 0xFFFD86 - SSR0
+// 0xFFFD88 - SDR0
+// 0xFFFD8A - -
+// 0xFFFD8C - SPR
+// 0xFFFD8E - SCR
+// 0xFFFD90 - SMR1
+// 0xFFFD92 - SCMR1
+// 0xFFFD94 - SBRR1
+// 0xFFFD96 - SSR1
+// 0xFFFD98 - SDR1
+// 0xFFFD9A - -
+// 0xFFFD9C - -
+// 0xFFFD9E - -
+// 0xFFFDA0 - SMR2
+// 0xFFFDA2 - SCMR2
+// 0xFFFDA4 - SBRR2
+// 0xFFFDA6 - SSR2
+// 0xFFFDA8 - SDR2
+// 0xFFFDAA - -
+// 0xFFFDAC - -
+// 0xFFFDAE - -
+//
+// Timer
+// 15 7
+// 0xFFFE00 TCR0
+// 0xFFFE02 - -
+// 0xFFFE04 TMCR0
+// 0xFFFE06 - -
+// 0xFFFE08 - -
+// 0xFFFE0A - -
+// 0xFFFE0C TCTR0
+// 0xFFFE0E - -
+// 0xFFFE10 - -
+// 0xFFFE12 - -
+// 0xFFFE14 - -
+// 0xFFFE16 - -
+// 0xFFFE18 - -
+// 0xFFFE1A - -
+// 0xFFFE1C - -
+// 0xFFFE1E - -
+// 0xFFFE20 TCR1
+// 0xFFFE22 - -
+// 0xFFFE24 TMCR11
+// 0xFFFE26 - -
+// 0xFFFE28 TMCR12
+// 0xFFFE2A - -
+// 0xFFFE2C TCTR1
+// 0xFFFE2E - -
+// 0xFFFE30 - -
+// 0xFFFE32 - -
+// 0xFFFE34 - -
+// 0xFFFE36 - -
+// 0xFFFE38 - -
+// 0xFFFE3A - -
+// 0xFFFE3C - -
+// 0xFFFE3E - -
+// 0xFFFE40 TCR2
+// 0xFFFE42 - -
+// 0xFFFE44 TMCR21
+// 0xFFFE46 - -
+// 0xFFFE48 TMCR22
+// 0xFFFE4A - -
+// 0xFFFE4C TCTR2
+// 0xFFFE4E - -
+
+
+static UINT16 tmp68301_address_decoder[0x10];
+static UINT16 tmp68301_interrupt_controller[0x20];
+static UINT16 tmp68301_parallel_interface[0x10];
+static UINT16 tmp68301_serial_interface[0x30];
+static UINT16 tmp68301_timer[0x50];
+
+
+READ16_HANDLER( tmp68301_address_decoder_r )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_address_decoder_r (%08X)\n", activecpu_get_pc(), (0xfffc00 + (offset * 2)));
+#endif
+
+ return tmp68301_address_decoder[offset];
+}
+
+WRITE16_HANDLER( tmp68301_address_decoder_w )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_address_decoder_w (%08X = %04X)\n", activecpu_get_pc(), (0xfffc00 + (offset * 2)), data);
+#endif
+
+ tmp68301_address_decoder[offset] = data;
+}
+
+READ16_HANDLER( tmp68301_interrupt_controller_r )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_interrupt_controller_r (%08X)\n", activecpu_get_pc(), (0xfffc80 + (offset * 2)));
+#endif
+
+ return tmp68301_interrupt_controller[offset];
+}
+
+WRITE16_HANDLER( tmp68301_interrupt_controller_w )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_interrupt_controller_w (%08X = %04X)\n", activecpu_get_pc(), (0xfffc80 + (offset * 2)), data);
+#endif
+
+ tmp68301_interrupt_controller[offset] = data;
+}
+
+READ16_HANDLER( tmp68301_parallel_interface_r )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_parallel_interface_r (%08X)\n", activecpu_get_pc(), (0xfffd00 + (offset * 2)));
+#endif
+
+ return tmp68301_parallel_interface[offset];
+}
+
+WRITE16_HANDLER( tmp68301_parallel_interface_w )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_parallel_interface_w (%08X = %04X)\n", activecpu_get_pc(), (0xfffd00 + (offset * 2)), data);
+#endif
+
+ tmp68301_parallel_interface[offset] = data;
+}
+
+READ16_HANDLER( tmp68301_serial_interface_r )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_serial_interface_r (%08X)\n", activecpu_get_pc(), (0xfffd80 + (offset * 2)));
+#endif
+
+ return tmp68301_serial_interface[offset];
+}
+
+WRITE16_HANDLER( tmp68301_serial_interface_w )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_serial_interface_w (%08X = %04X)\n", activecpu_get_pc(), (0xfffd80 + (offset * 2)), data);
+#endif
+
+ tmp68301_serial_interface[offset] = data;
+}
+
+READ16_HANDLER( tmp68301_timer_r )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_timer_r (%08X)\n", activecpu_get_pc(), (0xfffe00 + (offset * 2)));
+#endif
+
+ return tmp68301_timer[offset];
+}
+
+WRITE16_HANDLER( tmp68301_timer_w )
+{
+#if TMP68301_DEBUG
+ logerror("PC %08X: TMP68301_timer_w (%08X = %04X)\n", activecpu_get_pc(), (0xfffe00 + (offset * 2)), data);
+#endif
+
+ tmp68301_timer[offset] = data;
+}
diff --git a/src/mame/machine/m68kfmly.h b/src/mame/machine/m68kfmly.h
new file mode 100644
index 00000000000..2326dcec37a
--- /dev/null
+++ b/src/mame/machine/m68kfmly.h
@@ -0,0 +1,18 @@
+/******************************************************************************
+
+ TMP68301 support (dummy) driver
+
+ Driver by Takahiro Nogi <nogi@kt.rim.or.jp> 2000/12/23 -
+
+******************************************************************************/
+
+READ16_HANDLER( tmp68301_address_decoder_r );
+WRITE16_HANDLER( tmp68301_address_decoder_w );
+READ16_HANDLER( tmp68301_interrupt_controller_r );
+WRITE16_HANDLER( tmp68301_interrupt_controller_w );
+READ16_HANDLER( tmp68301_parallel_interface_r );
+WRITE16_HANDLER( tmp68301_parallel_interface_w );
+READ16_HANDLER( tmp68301_serial_interface_r );
+WRITE16_HANDLER( tmp68301_serial_interface_w );
+READ16_HANDLER( tmp68301_timer_r );
+WRITE16_HANDLER( tmp68301_timer_w );
diff --git a/src/mame/machine/maniach.c b/src/mame/machine/maniach.c
new file mode 100644
index 00000000000..53ce7d73792
--- /dev/null
+++ b/src/mame/machine/maniach.c
@@ -0,0 +1,136 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+
+/***************************************************************************
+
+ Mania Challenge 68705 protection interface
+
+ The following is ENTIRELY GUESSWORK!!!
+
+***************************************************************************/
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( maniach_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( maniach_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( maniach_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 1 W when 1->0, enables latch which brings the command from main CPU (read from port A)
+ * 2 W when 0->1, copies port A to the latch for the main CPU
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( maniach_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( maniach_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ main_sent = 0;
+//logerror("read command %02x from main cpu\n",portA_in);
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+//logerror("send command %02x to main cpu\n",portA_out);
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( maniach_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( maniach_68705_portC_r )
+{
+ portC_in = 0;
+ if (main_sent) portC_in |= 0x01;
+ if (!mcu_sent) portC_in |= 0x02;
+//logerror("%04x: 68705 port C read %02x\n",activecpu_get_pc(),portC_in);
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( maniach_68705_portC_w )
+{
+//logerror("%04x: 68705 port C write %02x\n",activecpu_get_pc(),data);
+ portC_out = data;
+}
+
+WRITE8_HANDLER( maniach_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+
+WRITE8_HANDLER( maniach_mcu_w )
+{
+//logerror("%04x: 3040_w %02x\n",activecpu_get_pc(),data);
+ from_main = data;
+ main_sent = 1;
+}
+
+READ8_HANDLER( maniach_mcu_r )
+{
+//logerror("%04x: 3040_r %02x\n",activecpu_get_pc(),from_mcu);
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( maniach_mcu_status_r )
+{
+ int res = 0;
+
+ /* bit 0 = when 0, mcu has sent data to the main cpu */
+ /* bit 1 = when 1, mcu is ready to receive data from main cpu */
+//logerror("%04x: 3041_r\n",activecpu_get_pc());
+ if (!mcu_sent) res |= 0x01;
+ if (!main_sent) res |= 0x02;
+
+ return res;
+}
diff --git a/src/mame/machine/mathbox.c b/src/mame/machine/mathbox.c
new file mode 100644
index 00000000000..ada570c25ea
--- /dev/null
+++ b/src/mame/machine/mathbox.c
@@ -0,0 +1,285 @@
+/*
+ * mathbox.c: math box simulation (Battlezone/Red Baron/Tempest)
+ *
+ * Copyright 1991, 1992, 1993, 1996 Eric Smith
+ *
+ */
+
+#include "driver.h"
+#include "mathbox.h"
+
+typedef short s16;
+typedef int s32;
+
+/* math box scratch registers */
+static s16 mb_reg [16];
+
+/* math box result */
+static s16 mb_result = 0;
+
+#define REG0 mb_reg [0x00]
+#define REG1 mb_reg [0x01]
+#define REG2 mb_reg [0x02]
+#define REG3 mb_reg [0x03]
+#define REG4 mb_reg [0x04]
+#define REG5 mb_reg [0x05]
+#define REG6 mb_reg [0x06]
+#define REG7 mb_reg [0x07]
+#define REG8 mb_reg [0x08]
+#define REG9 mb_reg [0x09]
+#define REGa mb_reg [0x0a]
+#define REGb mb_reg [0x0b]
+#define REGc mb_reg [0x0c]
+#define REGd mb_reg [0x0d]
+#define REGe mb_reg [0x0e]
+#define REGf mb_reg [0x0f]
+
+
+/*define MB_TEST*/
+
+WRITE8_HANDLER( mb_go_w )
+{
+ s32 mb_temp; /* temp 32-bit multiply results */
+ s16 mb_q; /* temp used in division */
+ int msb;
+
+#ifdef MB_TEST
+ logerror("math box command %02x data %02x ", offset, data);
+#endif
+
+ switch (offset)
+ {
+ case 0x00: mb_result = REG0 = (REG0 & 0xff00) | data; break;
+ case 0x01: mb_result = REG0 = (REG0 & 0x00ff) | (data << 8); break;
+ case 0x02: mb_result = REG1 = (REG1 & 0xff00) | data; break;
+ case 0x03: mb_result = REG1 = (REG1 & 0x00ff) | (data << 8); break;
+ case 0x04: mb_result = REG2 = (REG2 & 0xff00) | data; break;
+ case 0x05: mb_result = REG2 = (REG2 & 0x00ff) | (data << 8); break;
+ case 0x06: mb_result = REG3 = (REG3 & 0xff00) | data; break;
+ case 0x07: mb_result = REG3 = (REG3 & 0x00ff) | (data << 8); break;
+ case 0x08: mb_result = REG4 = (REG4 & 0xff00) | data; break;
+ case 0x09: mb_result = REG4 = (REG4 & 0x00ff) | (data << 8); break;
+
+ case 0x0a: mb_result = REG5 = (REG5 & 0xff00) | data; break;
+ /* note: no function loads low part of REG5 without performing a computation */
+
+ case 0x0c: mb_result = REG6 = data; break;
+ /* note: no function loads high part of REG6 */
+
+ case 0x15: mb_result = REG7 = (REG7 & 0xff00) | data; break;
+ case 0x16: mb_result = REG7 = (REG7 & 0x00ff) | (data << 8); break;
+
+ case 0x1a: mb_result = REG8 = (REG8 & 0xff00) | data; break;
+ case 0x1b: mb_result = REG8 = (REG8 & 0x00ff) | (data << 8); break;
+
+ case 0x0d: mb_result = REGa = (REGa & 0xff00) | data; break;
+ case 0x0e: mb_result = REGa = (REGa & 0x00ff) | (data << 8); break;
+ case 0x0f: mb_result = REGb = (REGb & 0xff00) | data; break;
+ case 0x10: mb_result = REGb = (REGb & 0x00ff) | (data << 8); break;
+
+ case 0x17: mb_result = REG7; break;
+ case 0x19: mb_result = REG8; break;
+ case 0x18: mb_result = REG9; break;
+
+ case 0x0b:
+
+ REG5 = (REG5 & 0x00ff) | (data << 8);
+
+ REGf = (s16)0xffff;
+ REG4 -= REG2;
+ REG5 -= REG3;
+
+ step_048:
+
+ mb_temp = ((s32) REG0) * ((s32) REG4);
+ REGc = mb_temp >> 16;
+ REGe = mb_temp & 0xffff;
+
+ mb_temp = ((s32) -REG1) * ((s32) REG5);
+ REG7 = mb_temp >> 16;
+ mb_q = mb_temp & 0xffff;
+
+ REG7 += REGc;
+
+ /* rounding */
+ REGe = (REGe >> 1) & 0x7fff;
+ REGc = (mb_q >> 1) & 0x7fff;
+ mb_q = REGc + REGe;
+ if (mb_q < 0)
+ REG7++;
+
+ mb_result = REG7;
+
+ if (REGf < 0)
+ break;
+
+ REG7 += REG2;
+
+ /* fall into command 12 */
+
+ case 0x12:
+
+ mb_temp = ((s32) REG1) * ((s32) REG4);
+ REGc = mb_temp >> 16;
+ REG9 = mb_temp & 0xffff;
+
+ mb_temp = ((s32) REG0) * ((s32) REG5);
+ REG8 = mb_temp >> 16;
+ mb_q = mb_temp & 0xffff;
+
+ REG8 += REGc;
+
+ /* rounding */
+ REG9 = (REG9 >> 1) & 0x7fff;
+ REGc = (mb_q >> 1) & 0x7fff;
+ REG9 += REGc;
+ if (REG9 < 0)
+ REG8++;
+ REG9 <<= 1; /* why? only to get the desired load address? */
+
+ mb_result = REG8;
+
+ if (REGf < 0)
+ break;
+
+ REG8 += REG3;
+
+ REG9 &= 0xff00;
+
+ /* fall into command 13 */
+
+ case 0x13:
+#ifdef MB_TEST
+ logerror("\nR7: %04x R8: %04x R9: %04x\n", REG7, REG8, REG9);
+#endif
+
+ REGc = REG9;
+ mb_q = REG8;
+ goto step_0bf;
+
+ case 0x14:
+ REGc = REGa;
+ mb_q = REGb;
+
+ step_0bf:
+ REGe = REG7 ^ mb_q; /* save sign of result */
+ REGd = mb_q;
+ if (mb_q >= 0)
+ mb_q = REGc;
+ else
+ {
+ REGd = - mb_q - 1;
+ mb_q = - REGc - 1;
+ if ((mb_q < 0) && ((mb_q + 1) < 0))
+ REGd++;
+ mb_q++;
+ }
+
+ /* step 0c9: */
+ /* REGc = abs (REG7) */
+ if (REG7 >= 0)
+ REGc = REG7;
+ else
+ REGc = -REG7;
+
+ REGf = REG6; /* step counter */
+
+ do
+ {
+ REGd -= REGc;
+ msb = ((mb_q & 0x8000) != 0);
+ mb_q <<= 1;
+ if (REGd >= 0)
+ mb_q++;
+ else
+ REGd += REGc;
+ REGd <<= 1;
+ REGd += msb;
+ }
+ while (--REGf >= 0);
+
+ if (REGe >= 0)
+ mb_result = mb_q;
+ else
+ mb_result = - mb_q;
+ break;
+
+ case 0x11:
+ REG5 = (REG5 & 0x00ff) | (data << 8);
+ REGf = 0x0000; /* do everything in one step */
+ goto step_048;
+ break;
+
+ case 0x1c:
+ /* window test? */
+ REG5 = (REG5 & 0x00ff) | (data << 8);
+ do
+ {
+ REGe = (REG4 + REG7) >> 1;
+ REGf = (REG5 + REG8) >> 1;
+ if ((REGb < REGe) && (REGf < REGe) && ((REGe + REGf) >= 0))
+ { REG7 = REGe; REG8 = REGf; }
+ else
+ { REG4 = REGe; REG5 = REGf; }
+ }
+ while (--REG6 >= 0);
+
+ mb_result = REG8;
+ break;
+
+ case 0x1d:
+ REG3 = (REG3 & 0x00ff) | (data << 8);
+
+ REG2 -= REG0;
+ if (REG2 < 0)
+ REG2 = -REG2;
+
+ REG3 -= REG1;
+ if (REG3 < 0)
+ REG3 = -REG3;
+
+ /* fall into command 1e */
+
+ case 0x1e:
+ /* result = max (REG2, REG3) + 3/8 * min (REG2, REG3) */
+ if (REG3 >= REG2)
+ { REGc = REG2; REGd = REG3; }
+ else
+ { REGd = REG2; REGc = REG3; }
+ REGc >>= 2;
+ REGd += REGc;
+ REGc >>= 1;
+ mb_result = REGd = (REGc + REGd);
+ break;
+
+ case 0x1f:
+ logerror("math box function 0x1f\n");
+ /* $$$ do some computation here (selftest? signature analysis? */
+ break;
+ }
+
+#ifdef MB_TEST
+ logerror(" result %04x\n", mb_result & 0xffff);
+#endif
+}
+
+READ8_HANDLER( mb_status_r )
+{
+ return 0x00; /* always done! */
+}
+
+READ8_HANDLER( mb_lo_r )
+{
+ return mb_result & 0xff;
+}
+
+READ8_HANDLER( mb_hi_r )
+{
+ return (mb_result >> 8) & 0xff;
+}
+
+void mb_register_states(void)
+{
+ state_save_register_global(mb_result);
+ state_save_register_global_array(mb_reg);
+}
diff --git a/src/mame/machine/mathbox.h b/src/mame/machine/mathbox.h
new file mode 100644
index 00000000000..4baff16e751
--- /dev/null
+++ b/src/mame/machine/mathbox.h
@@ -0,0 +1,12 @@
+/*
+ * mathbox.h: math box simulation (Battlezone/Red Baron/Tempest)
+ *
+ * Copyright 1991, 1992, 1993, 1996 Eric Smith
+ *
+ */
+
+WRITE8_HANDLER( mb_go_w );
+READ8_HANDLER( mb_status_r );
+READ8_HANDLER( mb_lo_r );
+READ8_HANDLER( mb_hi_r );
+void mb_register_states(void);
diff --git a/src/mame/machine/mb14241.c b/src/mame/machine/mb14241.c
new file mode 100644
index 00000000000..3b883207cdb
--- /dev/null
+++ b/src/mame/machine/mb14241.c
@@ -0,0 +1,50 @@
+/***************************************************************************
+
+ Midway 8080-based black and white hardware
+
+****************************************************************************/
+
+#include "driver.h"
+#include "mb14241.h"
+
+
+#define MAX_MB14241 1
+
+struct MB14241
+{
+ UINT16 shift_data; /* 15 bits only */
+ UINT8 shift_count; /* 3 bits */
+};
+
+static struct MB14241 chips[MAX_MB14241];
+
+
+static void mb14241_shift_count_w(int num, UINT8 data)
+{
+ chips[num].shift_count = ~data & 0x07;
+}
+
+WRITE8_HANDLER( mb14241_0_shift_count_w ) { mb14241_shift_count_w(0, data); }
+
+
+static void mb14241_shift_data_w(int num, UINT8 data)
+{
+ chips[num].shift_data = (chips[num].shift_data >> 8) | ((UINT16)data << 7);
+}
+
+WRITE8_HANDLER( mb14241_0_shift_data_w ) { mb14241_shift_data_w(0, data); }
+
+
+static UINT8 mb14241_shift_result_r(int num)
+{
+ return chips[num].shift_data >> chips[num].shift_count;
+}
+
+READ8_HANDLER( mb14241_0_shift_result_r ) { return mb14241_shift_result_r(0); }
+
+
+void mb14241_init(int num)
+{
+ state_save_register_item("mb14241", num, chips[num].shift_data);
+ state_save_register_item("mb14241", num, chips[num].shift_count);
+}
diff --git a/src/mame/machine/mb14241.h b/src/mame/machine/mb14241.h
new file mode 100644
index 00000000000..ad0de615dbe
--- /dev/null
+++ b/src/mame/machine/mb14241.h
@@ -0,0 +1,16 @@
+/*****************************************************************************
+
+ MB14241 shifter IC emulation
+
+ *****************************************************************************/
+
+#ifndef __MB14241_H__
+#define __MB14241_H__
+
+void mb14241_init(int num);
+
+WRITE8_HANDLER( mb14241_0_shift_count_w );
+WRITE8_HANDLER( mb14241_0_shift_data_w );
+READ8_HANDLER( mb14241_0_shift_result_r );
+
+#endif
diff --git a/src/mame/machine/mc8123.c b/src/mame/machine/mc8123.c
new file mode 100644
index 00000000000..8004c35c396
--- /dev/null
+++ b/src/mame/machine/mc8123.c
@@ -0,0 +1,498 @@
+/***************************************************************************
+
+NEC MC-8123 encryption emulation
+
+Decryption tables provided by David Widel
+Decryption algorithm by Nicola Salmoria
+
+The NEC MC-8123 is a Z80 with built-in encryption.
+It contains 0x2000 bytes of battery-backed RAM, when the battery dies the
+game stops working. It's possible that the CPU would work as a normal Z80
+in that case, this hasn't been verified.
+
+When the CPU reads a byte from memory, it uses 12 bits of the address and
+the information of whether the byte is an opcode or not to select a byte in
+the internal RAM. The byte controls how the decryption works.
+
+A special value in the internal RAM instructs the CPU to not apply the decryption
+algorithm at all. This is necessary for the CPU to be able to use RAM areas
+normally.
+
+In theory, the size of the key would make the encryption quite secure.
+
+In practice, the contents of the internal RAM were generated using a linear
+congruential generator, so the whole key can be generated starting from a single
+24-bit seed.
+
+The LCG is the same that was used to generate the FD1094 keys.
+Note that the algorithm skips the special value that would instruct the CPU to
+not decrypt at that address.
+
+void generate_key(UINT8 *key, int seed, int upper_bound)
+{
+ int i;
+
+ for (i = 0; i < upper_bound; ++i)
+ {
+ UINT8 byteval;
+
+ do
+ {
+ seed = seed * 0x29;
+ seed += seed << 16;
+
+ byteval = (~seed >> 16) & 0xff;
+ } while (byteval == 0xff);
+
+ key[i] = byteval;
+ }
+
+ for (; i < 0x2000; ++i)
+ key[i] = 0xff;
+}
+
+
+The known games that use this CPU are:
+
+CPU # Game Notes Seed Upper Limit
+-------- ------------------------- ------------------ ------ -----
+317-0014 DakkoChan Jansoh 206850 1C00
+317-0029 Block Gal NEC MC-8123B 651 091755 1800?
+317-0030 Perfect Billiard 9451EC 1C00
+317-0042 Opa Opa B31FD0 1C00
+317-0043 Wonder Boy Monster Land 640708 1C00
+317-0054 Shinobi (sound CPU) NEC MC-8123B 652 088992 1800
+317-0057 Fantasy Zone 2 ADFACE 1800
+317-0064 Ufo Senshi Yohko Chan 880603 1C00
+317-0066 Altered Beast (sound CPU) ED8600 1800
+317-5012 Ganbare Chinsan Ooshoubu NEC MC-8123A 804B54 1C00
+317-5??? Ninja Kid II (sound CPU) 27998D 1800
+
+***************************************************************************/
+
+#include "driver.h"
+#include "mc8123.h"
+
+
+
+static int decrypt_type0(int val,int param,int swap)
+{
+ int a = val;
+
+ if (swap == 1) a = BITSWAP8(a,5,4,3,6,7,1,2,0);
+ if (swap == 2) a = BITSWAP8(a,0,5,3,2,4,7,6,1);
+ if (swap == 3) a = BITSWAP8(a,0,1,7,5,3,6,2,4);
+
+ val = 0x1c;
+ if (BIT(a,0)) val ^= 0x23;
+ if (BIT(a,1)) val ^= 0x08;
+ if (BIT(a,2)) val ^= 0x04;
+ if (BIT(a,3)) val ^= 0x20;
+ if (BIT(a,4)) val ^= 0x01;
+ if (BIT(a,6)) val ^= 0x10;
+ if (BIT(a,5))
+ {
+ val ^= 0x73;
+
+ if (param & 0x40)
+ {
+ val ^= 0xb3;
+ if (param & 0x01) val ^= 0x40;
+ if (param & 0x04) val ^= 0x40;
+ if (param & 0x08) val ^= 0x40;
+ }
+ if (~param & 0x02)
+ {
+ val ^= 0xb3;
+ if (param & 0x01) val ^= 0x40;
+ if (param & 0x04) val ^= 0x40;
+ if (param & 0x08) val ^= 0x40;
+ }
+ if (param & 0x01)
+ {
+ val ^= 0xb3;
+ if (param & 0x01) val ^= 0x40;
+ if (param & 0x04) val ^= 0x40;
+ if (param & 0x08) val ^= 0x40;
+ }
+ }
+
+ if (BIT(a,7))
+ {
+ val ^= 0x80;
+
+ if (param & 0x01) val ^= 0x40;
+ if (param & 0x02) val ^= 0x25;
+ if (param & 0x04) val ^= 0x40;
+ if (param & 0x08) val ^= 0x40;
+ if (param & 0x40) val ^= 0x25;
+ if (param & 0x80) val ^= 0x25;
+ }
+
+ if (param & 0x01) val ^= 0xe3;
+ if (param & 0x02) val ^= 0x23;
+ if (param & 0x04) val ^= 0xc0;
+ if (param & 0x08) val ^= 0xc0;
+ if (param & 0x40) val ^= 0x23;
+
+ if (param & 0x01)
+ val ^= 0x21;
+ else
+ val = BITSWAP8(val,7,6,5,3,2,1,4,0);
+
+ return val;
+}
+
+static int decrypt_type1(int val,int param,int swap)
+{
+ if (BIT(~param,2) ^ BIT(param,0))
+ {
+ int a = val;
+
+ if (swap == 0) a = BITSWAP8(a,7,4,2,0,5,3,6,1);
+ if (swap == 1) a = BITSWAP8(a,2,6,0,7,4,3,5,1);
+ if (swap == 2) a = BITSWAP8(a,0,2,3,5,1,4,6,7);
+
+ if (BIT(~param,6) ^ BIT(param,1) ^ BIT(param,0))
+ a = BITSWAP8(a,7,6,5,4,0,2,3,1);
+
+ val = 0x4b;
+ if (BIT(a,0)) val ^= 0x20;
+ if (BIT(a,1)) val ^= 0xd4;
+ if (BIT(a,2)) val ^= 0x08;
+ if (BIT(a,3)) val ^= 0x03;
+ if (BIT(a,4)) val ^= 0x01;
+ if (BIT(a,5)) val ^= 0x48;
+ if (BIT(a,6)) val ^= 0xd8;
+ if (BIT(a,7)) val ^= 0x5e;
+
+ if (param & 0x01) val ^= 0x48;
+ if (param & 0x02) val ^= 0x84;
+ if (param & 0x04) val ^= 0x48;
+ if (param & 0x08) val ^= 0x48;
+ if (param & 0x40) val ^= 0x84;
+ if (param & 0x80) val ^= 0x84;
+
+ if (param & 0x01) val = BITSWAP8(val,7,6,1,4,3,2,5,0);
+
+ return val;
+ }
+ else
+ {
+ int a = val;
+
+ if (swap == 1) a = BITSWAP8(a,3,4,7,6,5,1,2,0);
+ if (swap == 2) a = BITSWAP8(a,3,5,0,1,7,2,6,4);
+ if (swap == 3) a = BITSWAP8(a,4,2,0,5,3,6,7,1);
+
+ val = 0x51;
+ if (BIT(a,0)) val ^= 0x42;
+ if (BIT(a,1)) val ^= 0x84;
+ if (BIT(a,2)) val ^= 0x70;
+ if (BIT(a,3)) val ^= 0xa4;
+ if (BIT(a,4)) val ^= 0x22;
+ if (BIT(a,5)) val ^= 0xcf;
+ if (BIT(a,6)) val ^= 0x04;
+ if (BIT(a,7)) val ^= 0x47;
+
+ if (BIT(a,7) && BIT(a,6))
+ val ^= 0xf4;
+
+ if (param & 0x01) val ^= 0x96;
+ if (param & 0x02) val ^= 0xdb;
+ if (param & 0x04) val ^= 0x18;
+ if (param & 0x08) val ^= 0x18;
+ if (param & 0x40) val ^= 0xdb;
+ if (param & 0x80) val ^= 0x12;
+
+ return val;
+ }
+}
+
+static int decrypt_type2(int val,int param,int swap)
+{
+ if (BIT(~param,2) ^ BIT(param,0))
+ {
+ int a = val;
+
+ if (swap == 1) a = BITSWAP8(a,2,4,7,0,5,1,3,6);
+ if (swap == 2) a = BITSWAP8(a,2,3,0,4,5,7,6,1);
+ if (swap == 3) a = BITSWAP8(a,0,3,2,7,5,1,6,4);
+
+ val = 0xea;
+ if (BIT(a,0)) val ^= 0xa0;
+ if (BIT(a,1)) val ^= 0x80;
+ if (BIT(a,2)) val ^= 0x18;
+ if (BIT(a,3)) val ^= 0x07;
+ if (BIT(a,4)) val ^= 0x41;
+ if (BIT(a,5)) val ^= 0x04;
+ if (BIT(a,6)) val ^= 0x10;
+ if (BIT(a,7)) val ^= 0x60;
+
+ if (!BIT(a,5) && ((~param & 0x08) || !BIT(a,6)))
+ {
+ if (BIT(a,0)) val ^= 0x20;
+ if (BIT(a,7)) val ^= 0x21;
+ if (BIT(a,1)) val ^= 0xe0;
+ if (BIT(a,4)) val ^= 0xe1;
+ }
+
+ if (param & 0x01) val ^= 0x1f;
+ if (param & 0x02) val ^= 0x1f;
+ if (param & 0x40) val ^= 0x1f;
+
+ if (BIT(param,6) ^ BIT(param,1) ^ BIT(param,7))
+ {
+ if (param & 0x01)
+ val = BITSWAP8(val,7,6,5,2,1,3,4,0);
+ else
+ val = BITSWAP8(val,7,6,5,3,4,1,2,0);
+ }
+ else
+ {
+ if (~param & 0x01)
+ val = BITSWAP8(val,7,6,5,1,2,4,3,0);
+ }
+
+ return val;
+ }
+ else
+ {
+ // only 0x20 possible encryptions for this method - all others have 0x40
+
+ int a = val;
+
+ if (swap == 1) a = BITSWAP8(a,3,4,7,5,1,6,0,2);
+ if (swap == 2) a = BITSWAP8(a,2,1,6,4,5,7,3,0);
+ if (swap == 3) a = BITSWAP8(a,7,0,4,3,2,1,5,6);
+
+ val = 0x0e;
+ if (BIT(a,0)) val ^= 0x33;
+ if (BIT(a,1)) val ^= 0x8e;
+ if (BIT(a,2)) val ^= 0x01;
+ if (BIT(a,3)) val ^= 0xe0;
+ if (BIT(a,4)) val ^= 0x5b;
+ if (BIT(a,5)) val ^= 0xea;
+ if (BIT(a,6)) val ^= 0x58;
+ if (BIT(a,7)) val ^= 0x0e;
+
+ if (BIT(a,1) && BIT(a,5))
+ val ^= 0xa8;
+
+ if (BIT(a,6))
+ {
+ if (BIT(a,0) ^ BIT(a,4) ^ BIT(a,1))
+ val ^= 0x11;
+ }
+ if (BIT(a,1))
+ {
+ if (!BIT(a,5))
+ {
+ if (BIT(a,0) ^ BIT(a,4))
+ val ^= 0x11;
+ }
+ }
+
+ if (param & 0x01) val ^= 0xca;
+ if (param & 0x02) val ^= 0xa4;
+ if (param & 0x08) val ^= 0x80;
+ if (param & 0x40) val ^= 0xa4;
+ if (param & 0x80) val ^= 0x4a;
+
+ return val;
+ }
+}
+
+static int decrypt_type3(int val,int param,int swap)
+{
+ if (BIT(~param,2) ^ BIT(param,0))
+ {
+ int a = val;
+
+ if (swap == 0) a = BITSWAP8(a,2,4,7,0,5,1,3,6);
+ if (swap == 2) a = BITSWAP8(a,0,3,2,7,5,1,6,4);
+ if (swap == 3) a = BITSWAP8(a,2,3,0,4,5,7,6,1);
+
+ if (BIT(param,6) ^ BIT(param,1) ^ BIT(param,7))
+ a = BITSWAP8(a,7,6,5,4,2,3,1,0);
+
+ if (BIT(a,4))
+ a = BITSWAP8(a,7,6,5,4,2,3,1,0);
+
+ val = 0x78;
+ if (BIT(a,2)) val ^= 0x26;
+ if (BIT(a,3)) val ^= 0x80;
+ if (BIT(a,5)) val ^= 0x10;
+ if (param & 0x01)
+ {
+ if (BIT(a,0)) val ^= 0x04;
+ if (BIT(a,1)) val ^= 0x01;
+ if (BIT(a,4)) val ^= 0x5d;
+ if (BIT(a,6)) val ^= 0x43;
+ if (BIT(a,7)) val ^= 0xf6;
+ }
+ else
+ {
+ if (BIT(a,0)) val ^= 0x43;
+ if (BIT(a,1)) val ^= 0x40;
+ if (BIT(a,4)) val ^= 0x1f;
+ if (BIT(a,6)) val ^= 0x01;
+ if (BIT(a,7)) val ^= 0xb2;
+ }
+
+ if (param & 0x01) val ^= 0x81;
+ if (param & 0x02) val ^= 0x98;
+ if (param & 0x08) val ^= 0x10;
+ if (param & 0x40) val ^= 0x98;
+ if (param & 0x80) val ^= 0x18;
+
+ return val;
+ }
+ else
+ {
+ int a = val;
+
+ if (swap == 0) a = BITSWAP8(a,3,4,7,5,1,6,0,2);
+ if (swap == 2) a = BITSWAP8(a,7,0,4,3,2,1,5,6);
+ if (swap == 3) a = BITSWAP8(a,2,1,6,4,5,7,3,0);
+
+ if (BIT(param,6) ^ BIT(param,1) ^ BIT(param,7))
+ {
+ val = 0xaa;
+ if (param & 0x01) val ^= 0x04;
+ if (param & 0x80) val ^= 0x04;
+
+ if (BIT(a,0)) val ^= 0xd6;
+ if (BIT(a,1)) val ^= 0x30;
+ if (BIT(a,2)) val ^= 0x11;
+ if (BIT(a,3)) val ^= 0x04;
+ if (BIT(a,4)) val ^= 0x08;
+ if (BIT(a,5)) val ^= 0x42;
+ if (BIT(a,6)) val ^= 0xc6;
+ if (BIT(a,7)) val ^= 0x03;
+ }
+ else
+ {
+ val = 0xac;
+ if (param & 0x01) val ^= 0x01;
+ if (param & 0x80) val ^= 0x01;
+
+ if (BIT(a,0)) val ^= 0x54;
+ if (BIT(a,1)) val ^= 0x08;
+ if (BIT(a,2)) val ^= 0x82;
+ if (BIT(a,3)) val ^= 0x01;
+ if (BIT(a,4)) val ^= 0x30;
+ if (BIT(a,5)) val ^= 0x40;
+ if (BIT(a,6)) val ^= 0x52;
+ if (BIT(a,7)) val ^= 0x86;
+ }
+
+ if (param & 0x01) val ^= 0x08;
+ if (param & 0x08) val ^= 0x80;
+
+ if (BIT(a,2) ^ BIT(a,7))
+ {
+ if (BIT(a,4) ^ BIT(a,1))
+ val ^= 0x38;
+
+ if (BIT(a,0) ^ BIT(a,5) ^ BIT(a,6))
+ val ^= 0x02;
+ }
+
+ return val;
+ }
+}
+
+
+static int decrypt(int val,int param,int opcode)
+{
+ int type = 0;
+ int swap = 0;
+
+ param ^= 0xff;
+
+ // no encryption
+ if (param == 0x00)
+ return val;
+
+ type ^= BIT(param,0) << 0;
+ type ^= BIT(param,1) << 0;
+ type ^= BIT(param,2) << 0;
+ type ^= BIT(param,4) << 0;
+ type ^= BIT(param,4) << 1;
+ type ^= BIT(param,5) << 1;
+
+ swap ^= BIT(param,0) << 0;
+ swap ^= BIT(param,1) << 0;
+ swap ^= BIT(param,2) << 1;
+ swap ^= BIT(param,3) << 1;
+
+ if (!opcode)
+ {
+ param ^= 1<<0;
+ param ^= 1<<1;
+ param ^= 1<<3;
+ param ^= 1<<7;
+ }
+
+ switch (type)
+ {
+ default:
+ case 0: return decrypt_type0(val,param,swap);
+
+ case 1: return decrypt_type1(val,param,swap);
+
+ case 2: return decrypt_type2(val,param,swap);
+
+ case 3: return decrypt_type3(val,param,swap);
+ }
+}
+
+
+static UINT8 mc8123_decrypt(offs_t addr,UINT8 val,const UINT8 *key,int opcode)
+{
+ int tbl_num;
+
+ /* pick the translation table from bits fd57 of the address */
+ tbl_num = (addr & 7) + ((addr & 0x10)>>1) + ((addr & 0x40)>>2) + ((addr & 0x100)>>3) + ((addr & 0xc00)>>4) + ((addr & 0xf000)>>4) ;
+
+ return decrypt(val,key[tbl_num + (opcode ? 0 : 0x1000)],opcode);
+}
+
+
+void mc8123_decrypt_rom(int cpunum, const UINT8* key, int banknum, int numbanks)
+{
+ UINT8 *decrypted1 = auto_malloc(numbanks == 1 ? 0xc000 : 0x8000);
+ UINT8 *decrypted2 = numbanks > 1 ? auto_malloc(0x4000 * numbanks) : decrypted1 + 0x8000;
+ UINT8 *rom = memory_region(REGION_CPU1 + cpunum);
+ int A, bank;
+
+ memory_set_decrypted_region(cpunum, 0x0000, 0x7fff, decrypted1);
+ if (numbanks > 1)
+ memory_configure_bank_decrypted(banknum, 0, numbanks, decrypted2, 0x4000);
+
+ for (A = 0x0000;A < 0x8000;A++)
+ {
+ UINT8 src = rom[A];
+
+ /* decode the opcodes */
+ decrypted1[A] = mc8123_decrypt(A,src,key,1);
+
+ /* decode the data */
+ rom[A] = mc8123_decrypt(A,src,key,0);
+ }
+
+ for (bank = 0; bank < numbanks; ++bank)
+ {
+ for (A = 0x8000;A < 0xc000;A++)
+ {
+ UINT8 src = rom[0x8000 + 0x4000*bank + A];
+
+ /* decode the opcodes */
+ decrypted2[0x4000 * bank + (A-0x8000)] = mc8123_decrypt(A,src,key,1);
+
+ /* decode the data */
+ rom[0x8000 + 0x4000*bank + A] = mc8123_decrypt(A,src,key,0);
+ }
+ }
+}
diff --git a/src/mame/machine/mc8123.h b/src/mame/machine/mc8123.h
new file mode 100644
index 00000000000..009a24f2433
--- /dev/null
+++ b/src/mame/machine/mc8123.h
@@ -0,0 +1,5 @@
+// this function assumes a fixed portion of ROM at 0000-7FFF, and
+// an arbitrary amount of banks at 8000-BFFF.
+// numbanks may be 0, meaning there is no ROM to decrypt at 8000-BFFF,
+// or 1, meaning 0000-BFFF will be decrypted as a single unit.
+void mc8123_decrypt_rom(int cpunum, const UINT8* key, int banknum, int numbanks);
diff --git a/src/mame/machine/mcr.c b/src/mame/machine/mcr.c
new file mode 100644
index 00000000000..82dc807d1ac
--- /dev/null
+++ b/src/mame/machine/mcr.c
@@ -0,0 +1,1026 @@
+/***************************************************************************
+
+ Midway MCR system
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/z80ctc.h"
+#include "machine/z80pio.h"
+#include "machine/z80sio.h"
+#include "audio/mcr.h"
+#include "cpu/m6800/m6800.h"
+#include "cpu/m6809/m6809.h"
+#include "cpu/z80/z80.h"
+#include "cpu/z80/z80daisy.h"
+#include "mcr.h"
+
+
+#define LOG(x) logerror x
+
+
+/*************************************
+ *
+ * Global variables
+ *
+ *************************************/
+
+attotime mcr68_timing_factor;
+
+UINT8 mcr_cocktail_flip;
+
+UINT32 mcr_cpu_board;
+UINT32 mcr_sprite_board;
+UINT32 mcr_ssio_board;
+
+
+
+/*************************************
+ *
+ * Statics
+ *
+ *************************************/
+
+static UINT8 m6840_status;
+static UINT8 m6840_status_read_since_int;
+static UINT8 m6840_msb_buffer;
+static UINT8 m6840_lsb_buffer;
+static struct counter_state
+{
+ UINT8 control;
+ UINT16 latch;
+ UINT16 count;
+ emu_timer * timer;
+ UINT8 timer_active;
+ attotime period;
+} m6840_state[3];
+
+/* MCR/68k interrupt states */
+static UINT8 m6840_irq_state;
+static UINT8 m6840_irq_vector;
+static UINT8 v493_irq_state;
+static UINT8 v493_irq_vector;
+
+static void (*v493_callback)(running_machine *machine, int param);
+
+static UINT8 zwackery_sound_data;
+
+static attotime m6840_counter_periods[3];
+static attotime m6840_internal_counter_period; /* 68000 CLK / 10 */
+
+static emu_timer *ipu_watchdog_timer;
+
+
+
+/*************************************
+ *
+ * Function prototypes
+ *
+ *************************************/
+
+static void subtract_from_counter(int counter, int count);
+
+static TIMER_CALLBACK( mcr68_493_callback );
+static TIMER_CALLBACK( zwackery_493_callback );
+
+static WRITE8_HANDLER( zwackery_pia_2_w );
+static WRITE8_HANDLER( zwackery_pia_3_w );
+static WRITE8_HANDLER( zwackery_ca2_w );
+static void zwackery_pia_irq(int state);
+
+static void reload_count(int counter);
+static TIMER_CALLBACK( counter_fired_callback );
+static TIMER_CALLBACK( ipu_watchdog_reset );
+static WRITE8_HANDLER( ipu_break_changed );
+
+
+
+/*************************************
+ *
+ * Graphics declarations
+ *
+ *************************************/
+
+gfx_layout mcr_bg_layout =
+{
+ 8,8,
+ RGN_FRAC(1,2),
+ 4,
+ { STEP2(RGN_FRAC(1,2),1), STEP2(RGN_FRAC(0,2),1) },
+ { STEP8(0,2) },
+ { STEP8(0,16) },
+ 16*8
+};
+
+
+gfx_layout mcr_sprite_layout =
+{
+ 32,32,
+ RGN_FRAC(1,4),
+ 4,
+ { STEP4(0,1) },
+ { STEP2(RGN_FRAC(0,4)+0,4), STEP2(RGN_FRAC(1,4)+0,4), STEP2(RGN_FRAC(2,4)+0,4), STEP2(RGN_FRAC(3,4)+0,4),
+ STEP2(RGN_FRAC(0,4)+8,4), STEP2(RGN_FRAC(1,4)+8,4), STEP2(RGN_FRAC(2,4)+8,4), STEP2(RGN_FRAC(3,4)+8,4),
+ STEP2(RGN_FRAC(0,4)+16,4), STEP2(RGN_FRAC(1,4)+16,4), STEP2(RGN_FRAC(2,4)+16,4), STEP2(RGN_FRAC(3,4)+16,4),
+ STEP2(RGN_FRAC(0,4)+24,4), STEP2(RGN_FRAC(1,4)+24,4), STEP2(RGN_FRAC(2,4)+24,4), STEP2(RGN_FRAC(3,4)+24,4) },
+ { STEP32(0,32) },
+ 32*32
+};
+
+
+
+/*************************************
+ *
+ * 6821 PIA declarations
+ *
+ *************************************/
+
+READ8_HANDLER( zwackery_port_2_r );
+
+
+static READ8_HANDLER( zwackery_port_1_r )
+{
+ UINT8 ret = readinputport(1);
+
+ pia_set_port_a_z_mask(3, ret);
+
+ return ret;
+}
+
+
+static READ8_HANDLER( zwackery_port_3_r )
+{
+ UINT8 ret = readinputport(3);
+
+ pia_set_port_a_z_mask(4, ret);
+
+ return ret;
+}
+
+
+static const pia6821_interface zwackery_pia_2_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, input_port_0_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ zwackery_pia_2_w, 0, 0, 0,
+ /*irqs : A/B */ zwackery_pia_irq, zwackery_pia_irq
+};
+
+static const pia6821_interface zwackery_pia_3_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ zwackery_port_1_r, zwackery_port_2_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ zwackery_pia_3_w, 0, zwackery_ca2_w, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface zwackery_pia_4_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ zwackery_port_3_r, input_port_4_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+
+
+/*************************************
+ *
+ * Generic MCR CTC interface
+ *
+ *************************************/
+
+static void ctc_interrupt(int state)
+{
+ cpunum_set_input_line(0, 0, state);
+}
+
+
+static void ipu_ctc_interrupt(int state)
+{
+ cpunum_set_input_line(3, 0, state);
+}
+
+
+struct z80_irq_daisy_chain mcr_daisy_chain[] =
+{
+ { z80ctc_reset, z80ctc_irq_state, z80ctc_irq_ack, z80ctc_irq_reti, 0 }, /* CTC number 0 */
+ { 0, 0, 0, 0, -1 } /* end mark */
+};
+
+
+struct z80_irq_daisy_chain mcr_ipu_daisy_chain[] =
+{
+ { z80ctc_reset, z80ctc_irq_state, z80ctc_irq_ack, z80ctc_irq_reti, 1 }, /* CTC number 1 */
+ { z80pio_reset, z80pio_irq_state, z80pio_irq_ack, z80pio_irq_reti, 1 }, /* PIO number 1 */
+ { z80sio_reset, z80sio_irq_state, z80sio_irq_ack, z80sio_irq_reti, 0 }, /* SIO number 0 */
+ { z80pio_reset, z80pio_irq_state, z80pio_irq_ack, z80pio_irq_reti, 0 }, /* PIO number 0 */
+ { 0, 0, 0, 0, -1 } /* end mark */
+};
+
+
+static z80ctc_interface ctc_intf =
+{
+ 0, /* clock (filled in from the CPU 0 clock) */
+ 0, /* timer disables */
+ ctc_interrupt, /* interrupt handler */
+ z80ctc_0_trg1_w, /* ZC/TO0 callback */
+ 0, /* ZC/TO1 callback */
+ 0 /* ZC/TO2 callback */
+};
+
+
+static z80ctc_interface nflfoot_ctc_intf =
+{
+ 0, /* clock (filled in from the CPU 3 clock) */
+ 0, /* timer disables */
+ ipu_ctc_interrupt, /* interrupt handler */
+ 0, /* ZC/TO0 callback */
+ 0, /* ZC/TO1 callback */
+ 0 /* ZC/TO2 callback */
+};
+
+
+static z80pio_interface nflfoot_pio_intf =
+{
+ ipu_ctc_interrupt,
+ 0,
+ 0
+};
+
+
+static z80sio_interface nflfoot_sio_intf =
+{
+ 0, /* clock (filled in from the CPU 3 clock) */
+ ipu_ctc_interrupt, /* interrupt handler */
+ 0, /* DTR changed handler */
+ 0, /* RTS changed handler */
+ ipu_break_changed, /* BREAK changed handler */
+ mcr_ipu_sio_transmit/* transmit handler */
+};
+
+
+
+/*************************************
+ *
+ * Generic MCR machine initialization
+ *
+ *************************************/
+
+MACHINE_START( mcr )
+{
+ /* initialize the CTC */
+ ctc_intf.baseclock = machine->drv->cpu[0].clock;
+ z80ctc_init(0, &ctc_intf);
+
+ state_save_register_global(mcr_cocktail_flip);
+}
+
+
+MACHINE_START( nflfoot )
+{
+ /* initialize the CTC */
+ ctc_intf.baseclock = machine->drv->cpu[0].clock;
+ z80ctc_init(0, &ctc_intf);
+
+ nflfoot_ctc_intf.baseclock = machine->drv->cpu[3].clock;
+ z80ctc_init(1, &nflfoot_ctc_intf);
+
+ z80pio_init(0, &nflfoot_pio_intf);
+ z80pio_init(1, &nflfoot_pio_intf);
+
+ nflfoot_sio_intf.baseclock = machine->drv->cpu[3].clock;
+ z80sio_init(0, &nflfoot_sio_intf);
+
+ /* allocate a timer for the IPU watchdog */
+ ipu_watchdog_timer = timer_alloc(ipu_watchdog_reset);
+}
+
+
+MACHINE_RESET( mcr )
+{
+ /* reset cocktail flip */
+ mcr_cocktail_flip = 0;
+
+ /* initialize the sound */
+ mcr_sound_reset();
+}
+
+
+
+/*************************************
+ *
+ * Generic MCR/68k machine initialization
+ *
+ *************************************/
+
+MACHINE_START( mcr68 )
+{
+ int i;
+
+ for (i = 0; i < 3; i++)
+ {
+ struct counter_state *m6840 = &m6840_state[i];
+
+ m6840->timer = timer_alloc(counter_fired_callback);
+
+ state_save_register_item("m6840", i, m6840->control);
+ state_save_register_item("m6840", i, m6840->latch);
+ state_save_register_item("m6840", i, m6840->count);
+ state_save_register_item("m6840", i, m6840->timer_active);
+ }
+
+ state_save_register_global(m6840_status);
+ state_save_register_global(m6840_status_read_since_int);
+ state_save_register_global(m6840_msb_buffer);
+ state_save_register_global(m6840_lsb_buffer);
+ state_save_register_global(m6840_irq_state);
+ state_save_register_global(v493_irq_state);
+ state_save_register_global(zwackery_sound_data);
+
+ state_save_register_global(mcr_cocktail_flip);
+}
+
+
+static void mcr68_common_init(void)
+{
+ int i;
+
+ /* reset the 6840's */
+ m6840_counter_periods[0] = ATTOTIME_IN_HZ(30); /* clocked by /VBLANK */
+ m6840_counter_periods[1] = attotime_never; /* grounded */
+ m6840_counter_periods[2] = ATTOTIME_IN_HZ(512 * 30); /* clocked by /HSYNC */
+
+ m6840_status = 0x00;
+ m6840_status_read_since_int = 0x00;
+ m6840_msb_buffer = m6840_lsb_buffer = 0;
+ for (i = 0; i < 3; i++)
+ {
+ struct counter_state *m6840 = &m6840_state[i];
+
+ m6840->control = 0x00;
+ m6840->latch = 0xffff;
+ m6840->count = 0xffff;
+ timer_enable(m6840->timer, FALSE);
+ m6840->timer_active = 0;
+ m6840->period = m6840_counter_periods[i];
+ }
+
+ /* initialize the clock */
+ m6840_internal_counter_period = ATTOTIME_IN_HZ(Machine->drv->cpu[0].clock / 10);
+
+ /* reset cocktail flip */
+ mcr_cocktail_flip = 0;
+
+ /* initialize the sound */
+ mcr_sound_reset();
+}
+
+
+MACHINE_RESET( mcr68 )
+{
+ /* for the most part all MCR/68k games are the same */
+ mcr68_common_init();
+ v493_callback = mcr68_493_callback;
+
+ /* vectors are 1 and 2 */
+ v493_irq_vector = 1;
+ m6840_irq_vector = 2;
+}
+
+
+MACHINE_START( zwackery )
+{
+ /* append our PIA state onto the existing one and reinit */
+ pia_config(2, &zwackery_pia_2_intf);
+ pia_config(3, &zwackery_pia_3_intf);
+ pia_config(4, &zwackery_pia_4_intf);
+
+ machine_start_mcr68(machine);
+}
+
+
+MACHINE_RESET( zwackery )
+{
+ /* for the most part all MCR/68k games are the same */
+ mcr68_common_init();
+ v493_callback = zwackery_493_callback;
+
+ /* append our PIA state onto the existing one and reinit */
+ pia_reset();
+
+ /* vectors are 5 and 6 */
+ v493_irq_vector = 5;
+ m6840_irq_vector = 6;
+}
+
+
+
+/*************************************
+ *
+ * Generic MCR interrupt handler
+ *
+ *************************************/
+
+INTERRUPT_GEN( mcr_interrupt )
+{
+ /* CTC line 2 is connected to VBLANK, which is once every 1/2 frame */
+ /* for the 30Hz interlaced display */
+ z80ctc_0_trg2_w(0, 1);
+ z80ctc_0_trg2_w(0, 0);
+
+ /* CTC line 3 is connected to 493, which is signalled once every */
+ /* frame at 30Hz */
+ if (cpu_getiloops() == 0)
+ {
+ z80ctc_0_trg3_w(0, 1);
+ z80ctc_0_trg3_w(0, 0);
+ }
+}
+
+
+INTERRUPT_GEN( mcr_ipu_interrupt )
+{
+ /* CTC line 3 is connected to 493, which is signalled once every */
+ /* frame at 30Hz */
+ if (cpu_getiloops() == 0)
+ {
+ z80ctc_1_trg3_w(0, 1);
+ z80ctc_1_trg3_w(0, 0);
+ }
+}
+
+
+INTERRUPT_GEN( mcr68_interrupt )
+{
+ /* update the 6840 VBLANK clock */
+ if (!m6840_state[0].timer_active)
+ subtract_from_counter(0, 1);
+
+ logerror("--- VBLANK ---\n");
+
+ /* also set a timer to generate the 493 signal at a specific time before the next VBLANK */
+ /* the timing of this is crucial for Blasted and Tri-Sports, which check the timing of */
+ /* VBLANK and 493 using counter 2 */
+ timer_set(attotime_sub(ATTOTIME_IN_HZ(30), mcr68_timing_factor), 0, v493_callback);
+}
+
+
+
+/*************************************
+ *
+ * MCR/68k interrupt central
+ *
+ *************************************/
+
+static void update_mcr68_interrupts(void)
+{
+ int newstate = 0;
+
+ /* all interrupts go through an LS148, which gives priority to the highest */
+ if (v493_irq_state)
+ newstate = v493_irq_vector;
+ if (m6840_irq_state)
+ newstate = m6840_irq_vector;
+
+ /* set the new state of the IRQ lines */
+ if (newstate)
+ cpunum_set_input_line(0, newstate, ASSERT_LINE);
+ else
+ cpunum_set_input_line(0, 7, CLEAR_LINE);
+}
+
+
+static TIMER_CALLBACK( mcr68_493_off_callback )
+{
+ v493_irq_state = 0;
+ update_mcr68_interrupts();
+}
+
+
+static TIMER_CALLBACK( mcr68_493_callback )
+{
+ v493_irq_state = 1;
+ update_mcr68_interrupts();
+ timer_set(video_screen_get_scan_period(0), 0, mcr68_493_off_callback);
+ logerror("--- (INT1) ---\n");
+}
+
+
+
+/*************************************
+ *
+ * Generic MCR port write handlers
+ *
+ *************************************/
+
+WRITE8_HANDLER( mcr_control_port_w )
+{
+ /*
+ Bit layout is as follows:
+ D7 = n/c
+ D6 = cocktail flip
+ D5 = red LED
+ D4 = green LED
+ D3 = n/c
+ D2 = coin meter 3
+ D1 = coin meter 2
+ D0 = coin meter 1
+ */
+
+ coin_counter_w(0, (data >> 0) & 1);
+ coin_counter_w(1, (data >> 1) & 1);
+ coin_counter_w(2, (data >> 2) & 1);
+ mcr_cocktail_flip = (data >> 6) & 1;
+}
+
+
+WRITE8_HANDLER( mcrmono_control_port_w )
+{
+ /*
+ Bit layout is as follows:
+ D7 = n/c
+ D6 = cocktail flip
+ D5 = n/c
+ D4 = n/c
+ D3 = n/c
+ D2 = n/c
+ D1 = n/c
+ D0 = coin meter 1
+ */
+
+ coin_counter_w(0, (data >> 0) & 1);
+ mcr_cocktail_flip = (data >> 6) & 1;
+}
+
+
+WRITE8_HANDLER( mcr_scroll_value_w )
+{
+ switch (offset)
+ {
+ case 0:
+ /* low 8 bits of horizontal scroll */
+ spyhunt_scrollx = (spyhunt_scrollx & ~0xff) | data;
+ break;
+
+ case 1:
+ /* upper 3 bits of horizontal scroll and upper 1 bit of vertical scroll */
+ spyhunt_scrollx = (spyhunt_scrollx & 0xff) | ((data & 0x07) << 8);
+ spyhunt_scrolly = (spyhunt_scrolly & 0xff) | ((data & 0x80) << 1);
+ break;
+
+ case 2:
+ /* low 8 bits of vertical scroll */
+ spyhunt_scrolly = (spyhunt_scrolly & ~0xff) | data;
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Zwackery-specific interfaces
+ *
+ *************************************/
+
+WRITE8_HANDLER( zwackery_pia_2_w )
+{
+ /* bit 7 is the watchdog */
+ if (!(data & 0x80)) watchdog_reset_w(offset, data);
+
+ /* bits 5 and 6 control hflip/vflip */
+ /* bits 3 and 4 control coin counters? */
+ /* bits 0, 1 and 2 control meters? */
+}
+
+
+WRITE8_HANDLER( zwackery_pia_3_w )
+{
+ zwackery_sound_data = (data >> 4) & 0x0f;
+}
+
+
+WRITE8_HANDLER( zwackery_ca2_w )
+{
+ csdeluxe_data_w(offset, (data << 4) | zwackery_sound_data);
+}
+
+
+void zwackery_pia_irq(int state)
+{
+ v493_irq_state = state;
+ update_mcr68_interrupts();
+}
+
+
+static TIMER_CALLBACK( zwackery_493_off_callback )
+{
+ pia_2_ca1_w(0, 0);
+}
+
+
+static TIMER_CALLBACK( zwackery_493_callback )
+{
+ pia_2_ca1_w(0, 1);
+ timer_set(video_screen_get_scan_period(0), 0, zwackery_493_off_callback);
+}
+
+
+
+/*************************************
+ *
+ * M6840 timer utilities
+ *
+ *************************************/
+
+INLINE void update_interrupts(void)
+{
+ m6840_status &= ~0x80;
+
+ if ((m6840_status & 0x01) && (m6840_state[0].control & 0x40)) m6840_status |= 0x80;
+ if ((m6840_status & 0x02) && (m6840_state[1].control & 0x40)) m6840_status |= 0x80;
+ if ((m6840_status & 0x04) && (m6840_state[2].control & 0x40)) m6840_status |= 0x80;
+
+ m6840_irq_state = m6840_status >> 7;
+ update_mcr68_interrupts();
+}
+
+
+static void subtract_from_counter(int counter, int count)
+{
+ /* dual-byte mode */
+ if (m6840_state[counter].control & 0x04)
+ {
+ int lsb = m6840_state[counter].count & 0xff;
+ int msb = m6840_state[counter].count >> 8;
+
+ /* count the clocks */
+ lsb -= count;
+
+ /* loop while we're less than zero */
+ while (lsb < 0)
+ {
+ /* borrow from the MSB */
+ lsb += (m6840_state[counter].latch & 0xff) + 1;
+ msb--;
+
+ /* if MSB goes less than zero, we've expired */
+ if (msb < 0)
+ {
+ m6840_status |= 1 << counter;
+ m6840_status_read_since_int &= ~(1 << counter);
+ update_interrupts();
+ msb = (m6840_state[counter].latch >> 8) + 1;
+ LOG(("** Counter %d fired\n", counter));
+ }
+ }
+
+ /* store the result */
+ m6840_state[counter].count = (msb << 8) | lsb;
+ }
+
+ /* word mode */
+ else
+ {
+ int word = m6840_state[counter].count;
+
+ /* count the clocks */
+ word -= count;
+
+ /* loop while we're less than zero */
+ while (word < 0)
+ {
+ /* borrow from the MSB */
+ word += m6840_state[counter].latch + 1;
+
+ /* we've expired */
+ m6840_status |= 1 << counter;
+ m6840_status_read_since_int &= ~(1 << counter);
+ update_interrupts();
+ LOG(("** Counter %d fired\n", counter));
+ }
+
+ /* store the result */
+ m6840_state[counter].count = word;
+ }
+}
+
+
+static TIMER_CALLBACK( counter_fired_callback )
+{
+ int count = param >> 2;
+ int counter = param & 3;
+
+ /* reset the timer */
+ m6840_state[counter].timer_active = 0;
+
+ /* subtract it all from the counter; this will generate an interrupt */
+ subtract_from_counter(counter, count);
+}
+
+
+static void reload_count(int counter)
+{
+ attotime period;
+ attotime total_period;
+ int count;
+
+ /* copy the latched value in */
+ m6840_state[counter].count = m6840_state[counter].latch;
+
+ /* counter 0 is self-updating if clocked externally */
+ if (counter == 0 && !(m6840_state[counter].control & 0x02))
+ {
+ timer_adjust(m6840_state[counter].timer, attotime_never, 0, attotime_zero);
+ m6840_state[counter].timer_active = 0;
+ return;
+ }
+
+ /* determine the clock period for this timer */
+ if (m6840_state[counter].control & 0x02)
+ period = m6840_internal_counter_period;
+ else
+ period = m6840_counter_periods[counter];
+
+ /* determine the number of clock periods before we expire */
+ count = m6840_state[counter].count;
+ if (m6840_state[counter].control & 0x04)
+ count = ((count >> 8) + 1) * ((count & 0xff) + 1);
+ else
+ count = count + 1;
+
+ /* set the timer */
+ total_period = attotime_make(0, attotime_to_attoseconds(period) * count);
+LOG(("reload_count(%d): period = %f count = %d\n", counter, attotime_to_double(period), count));
+ timer_adjust(m6840_state[counter].timer, total_period, (count << 2) + counter, attotime_zero);
+ m6840_state[counter].timer_active = 1;
+}
+
+
+static UINT16 compute_counter(int counter)
+{
+ attotime period;
+ int remaining;
+
+ /* if there's no timer, return the count */
+ if (!m6840_state[counter].timer_active)
+ return m6840_state[counter].count;
+
+ /* determine the clock period for this timer */
+ if (m6840_state[counter].control & 0x02)
+ period = m6840_internal_counter_period;
+ else
+ period = m6840_counter_periods[counter];
+
+ /* see how many are left */
+ remaining = attotime_to_attoseconds(timer_timeleft(m6840_state[counter].timer)) / attotime_to_attoseconds(period);
+
+ /* adjust the count for dual byte mode */
+ if (m6840_state[counter].control & 0x04)
+ {
+ int divisor = (m6840_state[counter].count & 0xff) + 1;
+ int msb = remaining / divisor;
+ int lsb = remaining % divisor;
+ remaining = (msb << 8) | lsb;
+ }
+
+ return remaining;
+}
+
+
+
+/*************************************
+ *
+ * M6840 timer I/O
+ *
+ *************************************/
+
+static WRITE8_HANDLER( mcr68_6840_w_common )
+{
+ int i;
+
+ /* offsets 0 and 1 are control registers */
+ if (offset < 2)
+ {
+ int counter = (offset == 1) ? 1 : (m6840_state[1].control & 0x01) ? 0 : 2;
+ UINT8 diffs = data ^ m6840_state[counter].control;
+
+ m6840_state[counter].control = data;
+
+ /* reset? */
+ if (counter == 0 && (diffs & 0x01))
+ {
+ /* holding reset down */
+ if (data & 0x01)
+ {
+ for (i = 0; i < 3; i++)
+ {
+ timer_adjust(m6840_state[i].timer, attotime_never, 0, attotime_zero);
+ m6840_state[i].timer_active = 0;
+ }
+ }
+
+ /* releasing reset */
+ else
+ {
+ for (i = 0; i < 3; i++)
+ reload_count(i);
+ }
+
+ m6840_status = 0;
+ update_interrupts();
+ }
+
+ /* changing the clock source? (needed for Zwackery) */
+ if (diffs & 0x02)
+ reload_count(counter);
+
+ LOG(("%06X:Counter %d control = %02X\n", activecpu_get_previouspc(), counter, data));
+ }
+
+ /* offsets 2, 4, and 6 are MSB buffer registers */
+ else if ((offset & 1) == 0)
+ {
+ LOG(("%06X:MSB = %02X\n", activecpu_get_previouspc(), data));
+ m6840_msb_buffer = data;
+ }
+
+ /* offsets 3, 5, and 7 are Write Timer Latch commands */
+ else
+ {
+ int counter = (offset - 2) / 2;
+ m6840_state[counter].latch = (m6840_msb_buffer << 8) | (data & 0xff);
+
+ /* clear the interrupt */
+ m6840_status &= ~(1 << counter);
+ update_interrupts();
+
+ /* reload the count if in an appropriate mode */
+ if (!(m6840_state[counter].control & 0x10))
+ reload_count(counter);
+
+ LOG(("%06X:Counter %d latch = %04X\n", activecpu_get_previouspc(), counter, m6840_state[counter].latch));
+ }
+}
+
+
+static READ16_HANDLER( mcr68_6840_r_common )
+{
+ /* offset 0 is a no-op */
+ if (offset == 0)
+ return 0;
+
+ /* offset 1 is the status register */
+ else if (offset == 1)
+ {
+ LOG(("%06X:Status read = %04X\n", activecpu_get_previouspc(), m6840_status));
+ m6840_status_read_since_int |= m6840_status & 0x07;
+ return m6840_status;
+ }
+
+ /* offsets 2, 4, and 6 are Read Timer Counter commands */
+ else if ((offset & 1) == 0)
+ {
+ int counter = (offset - 2) / 2;
+ int result = compute_counter(counter);
+
+ /* clear the interrupt if the status has been read */
+ if (m6840_status_read_since_int & (1 << counter))
+ m6840_status &= ~(1 << counter);
+ update_interrupts();
+
+ m6840_lsb_buffer = result & 0xff;
+
+ LOG(("%06X:Counter %d read = %04X\n", activecpu_get_previouspc(), counter, result));
+ return result >> 8;
+ }
+
+ /* offsets 3, 5, and 7 are LSB buffer registers */
+ else
+ return m6840_lsb_buffer;
+}
+
+
+WRITE16_HANDLER( mcr68_6840_upper_w )
+{
+ if (ACCESSING_MSB)
+ mcr68_6840_w_common(offset, (data >> 8) & 0xff);
+}
+
+
+WRITE16_HANDLER( mcr68_6840_lower_w )
+{
+ if (ACCESSING_LSB)
+ mcr68_6840_w_common(offset, data & 0xff);
+}
+
+
+READ16_HANDLER( mcr68_6840_upper_r )
+{
+ return (mcr68_6840_r_common(offset,0) << 8) | 0x00ff;
+}
+
+
+READ16_HANDLER( mcr68_6840_lower_r )
+{
+ return mcr68_6840_r_common(offset,0) | 0xff00;
+}
+
+
+
+/*************************************
+ *
+ * NFL Football IPU board
+ *
+ *************************************/
+
+static WRITE8_HANDLER( ipu_break_changed )
+{
+ /* channel B is connected to the CED player */
+ if (offset == 1)
+ {
+ logerror("DTR changed -> %d\n", data);
+ if (data == 1)
+ z80sio_receive_data(0, 1, 0);
+ }
+}
+
+
+READ8_HANDLER( mcr_ipu_pio_0_r )
+{
+ return (offset & 2) ? z80pio_c_r(0, offset & 1) : z80pio_d_r(0, offset & 1);
+}
+
+
+READ8_HANDLER( mcr_ipu_pio_1_r )
+{
+ return (offset & 2) ? z80pio_c_r(1, offset & 1) : z80pio_d_r(1, offset & 1);
+}
+
+
+READ8_HANDLER( mcr_ipu_sio_r )
+{
+ return (offset & 2) ? z80sio_c_r(0, offset & 1) : z80sio_d_r(0, offset & 1);
+}
+
+
+WRITE8_HANDLER( mcr_ipu_pio_0_w )
+{
+ if (offset & 2)
+ z80pio_c_w(0, offset & 1, data);
+ else
+ z80pio_d_w(0, offset & 1, data);
+}
+
+
+WRITE8_HANDLER( mcr_ipu_pio_1_w )
+{
+ if (offset & 2)
+ z80pio_c_w(1, offset & 1, data);
+ else
+ z80pio_d_w(1, offset & 1, data);
+}
+
+
+WRITE8_HANDLER( mcr_ipu_sio_w )
+{
+ if (offset & 2)
+ z80sio_c_w(0, offset & 1, data);
+ else
+ z80sio_d_w(0, offset & 1, data);
+}
+
+
+WRITE8_HANDLER( mcr_ipu_laserdisk_w )
+{
+ /* bit 3 enables (1) LD video regardless of PIX SW */
+ /* bit 2 enables (1) LD right channel audio */
+ /* bit 1 enables (1) LD left channel audio */
+ /* bit 0 enables (1) LD video if PIX SW == 1 */
+ if (data != 0)
+ logerror("%04X:mcr_ipu_laserdisk_w(%d) = %02X\n", activecpu_get_pc(), offset, data);
+}
+
+
+static TIMER_CALLBACK( ipu_watchdog_reset )
+{
+ logerror("ipu_watchdog_reset\n");
+ cpunum_set_input_line(3, INPUT_LINE_RESET, PULSE_LINE);
+ z80ctc_reset(1);
+ z80pio_reset(0);
+ z80pio_reset(1);
+ z80sio_reset(0);
+}
+
+
+READ8_HANDLER( mcr_ipu_watchdog_r )
+{
+ /* watchdog counter is clocked by 7.3728MHz crystal / 16 */
+ /* watchdog is tripped when 14-bit counter overflows => / 32768 = 14.0625Hz*/
+ timer_adjust(ipu_watchdog_timer, ATTOTIME_IN_HZ(7372800 / 16 / 32768), 0, attotime_zero);
+ return 0xff;
+}
+
+
+WRITE8_HANDLER( mcr_ipu_watchdog_w )
+{
+ mcr_ipu_watchdog_r(0);
+}
diff --git a/src/mame/machine/meters.c b/src/mame/machine/meters.c
new file mode 100644
index 00000000000..8b4cafaf141
--- /dev/null
+++ b/src/mame/machine/meters.c
@@ -0,0 +1,113 @@
+///////////////////////////////////////////////////////////////////////////
+// //
+// Electro mechanical meters //
+// //
+// 23-07-2004: Re-Animator //
+// //
+// TODO: - meter ticks if the signal changes from high to low AND the //
+// signal was high for at least 'reacttime' cycles //
+// It should tick if the signal goes from low to high AND stays //
+// high for at least xxx milliseconds //
+// //
+///////////////////////////////////////////////////////////////////////////
+
+#include "driver.h"
+#include "meters.h"
+
+// local vars /////////////////////////////////////////////////////////////
+
+static struct
+{
+ long timestamp, // time stamp in cycles after which timer will tick
+ reacttime,
+ count; // mechmeter value
+ int state; // state 0/1
+} meter_info[MAXMECHMETERS];
+
+
+static int number_mtr;
+
+///////////////////////////////////////////////////////////////////////////
+
+void Mechmtr_init(int number)
+{
+ int i;
+
+ if ( number > MAXMECHMETERS ) number = MAXMECHMETERS;
+
+ for ( i = 0; i < number; i++ )
+ {
+ meter_info[i].reacttime = METERREACTTIME;
+ meter_info[i].state = 0;
+ meter_info[i].count = 0;
+ meter_info[i].timestamp = 0;
+ }
+ number_mtr = number;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+int MechMtr_GetNumberMeters(void)
+{
+ return number_mtr;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void MechMtr_Setcount(int id, long count)
+{
+ if ( id >= number_mtr ) return;
+
+ meter_info[id].count = count;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+long MechMtr_Getcount(int id)
+{
+ long result = 0;
+
+ if ( id < number_mtr ) result = meter_info[id].count;
+
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void MechMtr_ReactTime(int id, long cycles)
+{
+ if ( id >= number_mtr ) return;
+
+ meter_info[id].reacttime = cycles;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+int Mechmtr_update(int id, long cycles, int state)
+{
+ int res = 0;
+
+ if ( id >= number_mtr ) return res;
+
+ state = state?1:0;
+
+ if ( meter_info[id].state != state )
+ { // meter state is changing
+ meter_info[id].state = state;
+
+ if ( state )
+ {
+ meter_info[id].timestamp = cycles + meter_info[id].reacttime;
+ }
+ else
+ {
+ if ( cycles > meter_info[id].timestamp )
+ { // meter has been active long enough
+ res = 1;
+ meter_info[id].count++;
+ }
+ }
+ }
+
+ return res;
+}
diff --git a/src/mame/machine/meters.h b/src/mame/machine/meters.h
new file mode 100644
index 00000000000..c46a6606f8e
--- /dev/null
+++ b/src/mame/machine/meters.h
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////
+// //
+// Electro mechanical meters //
+// //
+// 23-07-2004: Re-Animator //
+// //
+// TODO: - meter ticks if the signal changes from high to low AND the //
+// signal was high for at least 'reacttime' cycles //
+// It should tick if the signal goes from low to high AND stays //
+// high for at least xxx milliseconds //
+// //
+///////////////////////////////////////////////////////////////////////////
+
+#ifndef INC_MMTR
+#define INC_MMTR
+
+#define MAXMECHMETERS 8
+
+#define METERREACTTIME 30000 // number of cycles meter has to be active to tick
+
+void Mechmtr_init( int number);
+
+int MechMtr_GetNumberMeters(void);
+
+void MechMtr_Setcount( int id, long count);
+
+long MechMtr_Getcount( int id);
+
+void MechMtr_ReactTime(int id, long cycles);
+
+int Mechmtr_update( int id, long cycles, int state); // returns 1 if meter ticked
+
+#endif
diff --git a/src/mame/machine/mexico86.c b/src/mame/machine/mexico86.c
new file mode 100644
index 00000000000..bb5dd1fbfff
--- /dev/null
+++ b/src/mame/machine/mexico86.c
@@ -0,0 +1,334 @@
+#include "driver.h"
+
+
+UINT8 *mexico86_protection_ram;
+
+
+static int kikikai_mcu_running, kikikai_mcu_initialised;
+
+
+/*
+$f008 - write
+bit 7 = ? (unused?)
+bit 6 = ? (unused?)
+bit 5 = ? (unused?)
+bit 4 = ? (usually set in game)
+bit 3 = ? (usually set in game)
+bit 2 = sound cpu reset line
+bit 1 = microcontroller reset line
+bit 0 = ? (unused?)
+*/
+WRITE8_HANDLER( mexico86_f008_w )
+{
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (data & 4) ? CLEAR_LINE : ASSERT_LINE);
+ if (Machine->drv->cpu[2].type != CPU_DUMMY)
+ {
+ // mexico 86, knight boy
+ cpunum_set_input_line(2, INPUT_LINE_RESET, (data & 2) ? CLEAR_LINE : ASSERT_LINE);
+ }
+ else
+ {
+ // simulation for KiKi KaiKai
+ kikikai_mcu_running = data & 2;
+ if (!kikikai_mcu_running)
+ kikikai_mcu_initialised = 0;
+ }
+}
+
+
+/***************************************************************************
+
+ KiKi KaiKai MCU simulation
+
+ This is derived from examination of the bootleg 68705 MCU code, with an
+ addition to fix collision detection which is missing from the bootleg.
+
+***************************************************************************/
+
+static void mcu_simulate(void)
+{
+ if (!kikikai_mcu_initialised)
+ {
+ if (mexico86_protection_ram[0x01] == 0x00)
+ {
+logerror("initialising MCU\n");
+ mexico86_protection_ram[0x04] = 0xfc; // coin inputs
+ mexico86_protection_ram[0x02] = 0xff; // player 1
+ mexico86_protection_ram[0x03] = 0xff; // player 2
+ mexico86_protection_ram[0x1b] = 0xff; // active player
+ mexico86_protection_ram[0x06] = 0xff; // must be FF otherwise PS4 ERROR
+ mexico86_protection_ram[0x07] = 0x03; // must be 03 otherwise PS4 ERROR
+ mexico86_protection_ram[0x00] = 0x00;
+ kikikai_mcu_initialised = 1;
+ }
+ }
+
+ if (kikikai_mcu_initialised)
+ {
+ int i;
+ static int coin_last;
+ int coin_curr;
+
+
+ coin_curr = ~readinputport(0) & 1;
+ if (coin_curr && !coin_last && mexico86_protection_ram[0x01] < 9)
+ {
+ mexico86_protection_ram[0x01]++; // increase credits counter
+ mexico86_protection_ram[0x0a] = 0x01; // set flag (coin inserted sound is not played otherwise)
+ }
+ coin_last = coin_curr;
+
+ mexico86_protection_ram[0x04] = 0x3c; // coin inputs
+
+ mexico86_protection_ram[0x02] = BITSWAP8(readinputport(1), 7,6,5,4,2,3,1,0); // player 1
+ mexico86_protection_ram[0x03] = BITSWAP8(readinputport(2), 7,6,5,4,2,3,1,0); // player 2
+
+ if (mexico86_protection_ram[0x19] == 0xaa) // player 2 active
+ mexico86_protection_ram[0x1b] = mexico86_protection_ram[0x03];
+ else
+ mexico86_protection_ram[0x1b] = mexico86_protection_ram[0x02];
+
+
+ for (i = 0; i < 0x10; i += 2)
+ mexico86_protection_ram[i + 0xb1] = mexico86_protection_ram[i + 0xb0];
+
+ for (i = 0; i < 0x0a; i++)
+ mexico86_protection_ram[i + 0xc0] = mexico86_protection_ram[i + 0x90] + 1;
+
+ if (mexico86_protection_ram[0xd1] == 0xff)
+ {
+ if (mexico86_protection_ram[0xd0] > 0 && mexico86_protection_ram[0xd0] < 4)
+ {
+ mexico86_protection_ram[0xd2] = 0x81;
+ mexico86_protection_ram[0xd0] = 0xff;
+ }
+ }
+
+
+ if (mexico86_protection_ram[0xe0] > 0 && mexico86_protection_ram[0xe0] < 4)
+ {
+ static UINT8 answers[3][16] =
+ {
+ { 0x00,0x40,0x48,0x50,0x58,0x60,0x68,0x70,0x78,0x80,0x88,0x00,0x00,0x00,0x00,0x00 },
+ { 0x00,0x04,0x08,0x0C,0x10,0x14,0x18,0x1C,0x20,0x31,0x2B,0x35,0x00,0x00,0x00,0x00 },
+ { 0x00,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x03,0x0A,0x0B,0x14,0x00,0x00,0x00,0x00 },
+ };
+ int table = mexico86_protection_ram[0xe0] - 1;
+
+ for (i = 1; i < 0x10; i++)
+ mexico86_protection_ram[0xe0 + i] = answers[table][i];
+ mexico86_protection_ram[0xe0] = 0xff;
+ }
+
+ if (mexico86_protection_ram[0xf0] > 0 && mexico86_protection_ram[0xf0] < 4)
+ {
+ mexico86_protection_ram[0xf1] = 0xb3;
+ mexico86_protection_ram[0xf0] = 0xff;
+ }
+
+
+ // The following is missing from Knight Boy
+ // this should be equivalent to the obfuscated kiki_clogic() below
+ {
+ static int db[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x18,0x00,0x00,0x00,0x00};
+ int sy = mexico86_protection_ram[0xa0] + ((0x18)>>1);
+ int sx = mexico86_protection_ram[0xa1] + ((0x18)>>1);
+
+ for (i = 0; i < 0x38; i += 8)
+ {
+ int hw = db[mexico86_protection_ram[0x20 + i] & 0xf];
+
+ if (hw)
+ {
+ if (abs(sx - (mexico86_protection_ram[0x20 + i+6] * 256 + mexico86_protection_ram[0x20 + i+7])) < hw &&
+ abs(sy - (mexico86_protection_ram[0x20 + i+4] * 256 + mexico86_protection_ram[0x20 + i+5])) < hw)
+ mexico86_protection_ram[0xa2] = 1; // we have a collision
+ }
+ }
+ }
+ }
+}
+
+
+INTERRUPT_GEN( kikikai_interrupt )
+{
+ if (kikikai_mcu_running)
+ mcu_simulate();
+
+ cpunum_set_input_line_vector(0,0,mexico86_protection_ram[0]);
+ cpunum_set_input_line(0,0,HOLD_LINE);
+}
+
+
+
+#if 0
+//AT
+/***************************************************************************
+
+ Collision logic used by Kiki Kaikai (theoretical)
+
+***************************************************************************/
+#define KIKI_CL_OUT 0xa2
+#define KIKI_CL_TRIGGER 0xa3
+#define DCWIDTH 0
+#define DCHEIGHT 0
+
+static void kiki_clogic(int address, int latch)
+{
+ static UINT8 db[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x10,0x18,0x00,0x00,0x00,0x00};
+ static UINT8 queue[64];
+ static int qfront = 0, state = 0;
+ int sy, sx, hw, i, qptr, diff1, diff2;
+
+ if (address != KIKI_CL_TRIGGER) // queue latched data
+ {
+ queue[qfront++] = latch;
+ qfront &= 0x3f;
+ }
+ else if (state ^= 1) // scan queue
+ {
+ sy = queue[(qfront-0x3a)&0x3f] + ((0x18-DCHEIGHT)>>1);
+ sx = queue[(qfront-0x39)&0x3f] + ((0x18-DCWIDTH)>>1);
+
+ for (i=0x38; i; i-=8)
+ {
+ qptr = qfront - i;
+ if (!(hw = db[queue[qptr&0x3f]&0xf])) continue;
+
+ diff1 = sx - (short)(queue[(qptr+6)&0x3f]<<8|queue[(qptr+7)&0x3f]) + DCWIDTH;
+ diff2 = diff1 - (hw + DCWIDTH);
+ if ((diff1^diff2)<0)
+ {
+ diff1 = sy - (short)(queue[(qptr+4)&0x3f]<<8|queue[(qptr+5)&0x3f]) + DCHEIGHT;
+ diff2 = diff1 - (hw + DCHEIGHT);
+ if ((diff1^diff2)<0)
+ mexico86_protection_ram[KIKI_CL_OUT] = 1; // we have a collision
+ }
+ }
+ }
+}
+//ZT
+#endif
+
+
+/***************************************************************************
+
+ Mexico 86 68705 protection interface
+
+ The following is ENTIRELY GUESSWORK!!!
+
+***************************************************************************/
+
+INTERRUPT_GEN( mexico86_m68705_interrupt )
+{
+ /* I don't know how to handle the interrupt line so I just toggle it every time. */
+ if (cpu_getiloops() & 1)
+ cpunum_set_input_line(2,0,CLEAR_LINE);
+ else
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+}
+
+
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( mexico86_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( mexico86_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( mexico86_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 W enables latch which holds data from main Z80 memory
+ * 1 W loads the latch which holds the low 8 bits of the address of
+ * the main Z80 memory location to access
+ * 2 W 0 = read input ports, 1 = access Z80 memory
+ * 3 W clocks main Z80 memory access
+ * 4 W selects Z80 memory access direction (0 = write 1 = read)
+ * 5 W clocks a flip-flop which causes IRQ on the main Z80
+ * 6 W not used?
+ * 7 W not used?
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( mexico86_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+static int address,latch;
+
+WRITE8_HANDLER( mexico86_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x01) && (~data & 0x01) && (portB_out & 0x01))
+ {
+ portA_in = latch;
+ }
+ if ((ddrB & 0x02) && (data & 0x02) && (~portB_out & 0x02)) /* positive edge trigger */
+ {
+ address = portA_out;
+//if (address >= 0x80) logerror("%04x: 68705 address %02x\n",activecpu_get_pc(),portA_out);
+ }
+ if ((ddrB & 0x08) && (~data & 0x08) && (portB_out & 0x08))
+ {
+ if (data & 0x10) /* read */
+ {
+ if (data & 0x04)
+ {
+//logerror("%04x: 68705 read %02x from address %04x\n",activecpu_get_pc(),shared[0x800+address],address);
+ latch = mexico86_protection_ram[address];
+ }
+ else
+ {
+//logerror("%04x: 68705 read input port %04x\n",activecpu_get_pc(),address);
+ latch = readinputport((address & 1) + 1);
+ }
+ }
+ else /* write */
+ {
+//logerror("%04x: 68705 write %02x to address %04x\n",activecpu_get_pc(),portA_out,address);
+ mexico86_protection_ram[address] = portA_out;
+ }
+ }
+ if ((ddrB & 0x20) && (data & 0x20) && (~portB_out & 0x20))
+ {
+ cpunum_set_input_line_vector(0,0,mexico86_protection_ram[0]);
+ //cpunum_set_input_line(0,0,PULSE_LINE);
+ cpunum_set_input_line(0, 0, HOLD_LINE); //AT: HOLD_LINE works better in Z80 interrupt mode 1.
+ }
+ if ((ddrB & 0x40) && (~data & 0x40) && (portB_out & 0x40))
+ {
+logerror("%04x: 68705 unknown port B bit %02x\n",activecpu_get_pc(),data);
+ }
+ if ((ddrB & 0x80) && (~data & 0x80) && (portB_out & 0x80))
+ {
+logerror("%04x: 68705 unknown port B bit %02x\n",activecpu_get_pc(),data);
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( mexico86_68705_ddrB_w )
+{
+ ddrB = data;
+}
diff --git a/src/mame/machine/mhavoc.c b/src/mame/machine/mhavoc.c
new file mode 100644
index 00000000000..8c15c0665ba
--- /dev/null
+++ b/src/mame/machine/mhavoc.c
@@ -0,0 +1,362 @@
+/***************************************************************************
+
+ Atari Major Havoc hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "video/avgdvg.h"
+#include "sound/5220intf.h"
+#include "cpu/m6502/m6502.h"
+#include "mhavoc.h"
+
+UINT8 *mhavoc_zram0, *mhavoc_zram1;
+
+static UINT8 alpha_data;
+static UINT8 alpha_rcvd;
+static UINT8 alpha_xmtd;
+
+static UINT8 gamma_data;
+static UINT8 gamma_rcvd;
+static UINT8 gamma_xmtd;
+
+static UINT8 player_1;
+
+static UINT8 alpha_irq_clock;
+static UINT8 alpha_irq_clock_enable;
+static UINT8 gamma_irq_clock;
+
+static UINT8 has_gamma_cpu;
+
+
+
+/*************************************
+ *
+ * Interrupt handling
+ *
+ *************************************/
+
+static TIMER_CALLBACK( cpu_irq_clock )
+{
+ /* clock the LS161 driving the alpha CPU IRQ */
+ if (alpha_irq_clock_enable)
+ {
+ alpha_irq_clock++;
+ if ((alpha_irq_clock & 0x0c) == 0x0c)
+ {
+ cpunum_set_input_line(0, 0, ASSERT_LINE);
+ alpha_irq_clock_enable = 0;
+ }
+ }
+
+ /* clock the LS161 driving the gamma CPU IRQ */
+ if (has_gamma_cpu)
+ {
+ gamma_irq_clock++;
+ cpunum_set_input_line(1, 0, (gamma_irq_clock & 0x08) ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+
+WRITE8_HANDLER( mhavoc_alpha_irq_ack_w )
+{
+ /* clear the line and reset the clock */
+ cpunum_set_input_line(0, 0, CLEAR_LINE);
+ alpha_irq_clock = 0;
+ alpha_irq_clock_enable = 1;
+}
+
+
+WRITE8_HANDLER( mhavoc_gamma_irq_ack_w )
+{
+ /* clear the line and reset the clock */
+ cpunum_set_input_line(1, 0, CLEAR_LINE);
+ gamma_irq_clock = 0;
+}
+
+
+
+/*************************************
+ *
+ * Machine init
+ *
+ *************************************/
+
+MACHINE_RESET( mhavoc )
+{
+ has_gamma_cpu = (cpu_gettotalcpu() > 1);
+
+ memory_configure_bank(1, 0, 1, mhavoc_zram0, 0);
+ memory_configure_bank(1, 1, 1, mhavoc_zram1, 0);
+ memory_configure_bank(2, 0, 4, memory_region(REGION_CPU1) + 0x10000, 0x2000);
+
+ /* reset RAM/ROM banks to 0 */
+ mhavoc_ram_banksel_w(0, 0);
+ mhavoc_rom_banksel_w(0, 0);
+
+ /* reset alpha comm status */
+ alpha_data = 0;
+ alpha_rcvd = 0;
+ alpha_xmtd = 0;
+
+ /* reset gamma comm status */
+ gamma_data = 0;
+ gamma_rcvd = 0;
+ gamma_xmtd = 0;
+
+ /* reset player 1 flag */
+ player_1 = 0;
+
+ /* reset IRQ clock states */
+ alpha_irq_clock = 0;
+ alpha_irq_clock_enable = 1;
+ gamma_irq_clock = 0;
+
+ /* set a timer going for the CPU interrupt generators */
+ timer_pulse(ATTOTIME_IN_HZ(MHAVOC_CLOCK_5K), 0, cpu_irq_clock);
+
+ state_save_register_item("misc", 0, alpha_data);
+ state_save_register_item("misc", 0, alpha_rcvd);
+ state_save_register_item("misc", 0, alpha_xmtd);
+ state_save_register_item("misc", 0, gamma_data);
+ state_save_register_item("misc", 0, gamma_rcvd);
+ state_save_register_item("misc", 0, gamma_xmtd);
+ state_save_register_item("misc", 0, player_1);
+ state_save_register_item("misc", 0, alpha_irq_clock);
+ state_save_register_item("misc", 0, alpha_irq_clock_enable);
+ state_save_register_item("misc", 0, gamma_irq_clock);
+}
+
+
+
+/*************************************
+ *
+ * Alpha -> gamma communications
+ *
+ *************************************/
+
+static TIMER_CALLBACK( delayed_gamma_w )
+{
+ /* mark the data received */
+ gamma_rcvd = 0;
+ alpha_xmtd = 1;
+ alpha_data = param;
+
+ /* signal with an NMI pulse */
+ cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
+
+ /* the sound CPU needs to reply in 250microseconds (according to Neil Bradley) */
+ timer_set(ATTOTIME_IN_USEC(250), 0, 0);
+}
+
+
+WRITE8_HANDLER( mhavoc_gamma_w )
+{
+ logerror(" writing to gamma processor: %02x (%d %d)\n", data, gamma_rcvd, alpha_xmtd);
+ timer_call_after_resynch(data, delayed_gamma_w);
+}
+
+
+READ8_HANDLER( mhavoc_alpha_r )
+{
+ logerror("\t\t\t\t\treading from alpha processor: %02x (%d %d)\n", alpha_data, gamma_rcvd, alpha_xmtd);
+ gamma_rcvd = 1;
+ alpha_xmtd = 0;
+ return alpha_data;
+}
+
+
+
+/*************************************
+ *
+ * Gamma -> alpha communications
+ *
+ *************************************/
+
+WRITE8_HANDLER( mhavoc_alpha_w )
+{
+ logerror("\t\t\t\t\twriting to alpha processor: %02x %d %d\n", data, alpha_rcvd, gamma_xmtd);
+ alpha_rcvd = 0;
+ gamma_xmtd = 1;
+ gamma_data = data;
+}
+
+
+READ8_HANDLER( mhavoc_gamma_r )
+{
+ logerror(" reading from gamma processor: %02x (%d %d)\n", gamma_data, alpha_rcvd, gamma_xmtd);
+ alpha_rcvd = 1;
+ gamma_xmtd = 0;
+ return gamma_data;
+}
+
+
+
+/*************************************
+ *
+ * RAM/ROM banking
+ *
+ *************************************/
+
+WRITE8_HANDLER( mhavoc_ram_banksel_w )
+{
+ memory_set_bank(1, data & 1);
+}
+
+
+WRITE8_HANDLER( mhavoc_rom_banksel_w )
+{
+ memory_set_bank(2, data & 3);
+}
+
+
+
+/*************************************
+ *
+ * Input ports
+ *
+ *************************************/
+
+READ8_HANDLER( mhavoc_port_0_r )
+{
+ UINT8 res;
+
+ /* Bits 7-6 = selected based on Player 1 */
+ /* Bits 5-4 = common */
+ if (player_1)
+ res = (readinputport(0) & 0x30) | (readinputport(5) & 0xc0);
+ else
+ res = readinputport(0) & 0xf0;
+
+ /* Bit 3 = Gamma rcvd flag */
+ if (gamma_rcvd)
+ res |= 0x08;
+
+ /* Bit 2 = Gamma xmtd flag */
+ if (gamma_xmtd)
+ res |= 0x04;
+
+ /* Bit 1 = 2.4kHz (divide 2.5MHz by 1024) */
+ if (!(activecpu_gettotalcycles() & 0x400))
+ res |= 0x02;
+
+ /* Bit 0 = Vector generator halt flag */
+ if (avgdvg_done())
+ res |= 0x01;
+
+ return res;
+}
+
+
+READ8_HANDLER( alphaone_port_0_r )
+{
+ /* Bits 7-2 = common */
+ UINT8 res = readinputport(0) & 0xfc;
+
+ /* Bit 1 = 2.4kHz (divide 2.5MHz by 1024) */
+ if (!(activecpu_gettotalcycles() & 0x400))
+ res |= 0x02;
+
+ /* Bit 0 = Vector generator halt flag */
+ if (avgdvg_done())
+ res |= 0x01;
+
+ return res;
+}
+
+
+READ8_HANDLER( mhavoc_port_1_r )
+{
+ /* Bits 7-2 = input switches */
+ UINT8 res = readinputport(1) & 0xfc;
+
+ /* Bit 1 = Alpha rcvd flag */
+ if (has_gamma_cpu && alpha_rcvd)
+ res |= 0x02;
+
+ /* Bit 0 = Alpha xmtd flag */
+ if (has_gamma_cpu && alpha_xmtd)
+ res |= 0x01;
+
+ return res;
+}
+
+READ8_HANDLER( mhavoc_port_1_sp_r )
+{
+ /* Bits 7-3 = input switches */
+ UINT8 res = readinputport(1) & 0xf8;
+
+ /* Bit 2 = TMS5220 ready flag */
+ if (!tms5220_ready_r())
+ res |= 0x04;
+
+ /* Bit 1 = Alpha rcvd flag */
+ if (has_gamma_cpu && alpha_rcvd)
+ res |= 0x02;
+
+ /* Bit 0 = Alpha xmtd flag */
+ if (has_gamma_cpu && alpha_xmtd)
+ res |= 0x01;
+
+ return res;
+}
+
+
+
+
+/*************************************
+ *
+ * Output ports
+ *
+ *************************************/
+
+WRITE8_HANDLER( mhavoc_out_0_w )
+{
+ /* Bit 7 = Invert Y -- unemulated */
+ /* Bit 6 = Invert X -- unemulated */
+
+ /* Bit 5 = Player 1 */
+ player_1 = (data >> 5) & 1;
+
+ /* Bit 3 = Gamma reset */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (data & 0x08) ? CLEAR_LINE : ASSERT_LINE);
+ if (!(data & 0x08))
+ {
+ logerror("\t\t\t\t*** resetting gamma processor. ***\n");
+ alpha_rcvd = 0;
+ alpha_xmtd = 0;
+ gamma_rcvd = 0;
+ gamma_xmtd = 0;
+ }
+
+ /* Bit 0 = Roller light (Blinks on fatal errors) */
+ set_led_status(0, data & 0x01);
+}
+
+
+WRITE8_HANDLER( alphaone_out_0_w )
+{
+ /* Bit 5 = P2 lamp */
+ set_led_status(0, ~data & 0x20);
+
+ /* Bit 4 = P1 lamp */
+ set_led_status(1, ~data & 0x10);
+
+ /* Bit 1 = right coin counter */
+ coin_counter_w(1, data & 0x02);
+
+ /* Bit 0 = left coin counter */
+ coin_counter_w(0, data & 0x01);
+
+logerror("alphaone_out_0_w(%02X)\n", data);
+}
+
+
+WRITE8_HANDLER( mhavoc_out_1_w )
+{
+ /* Bit 1 = left coin counter */
+ coin_counter_w(0, data & 0x02);
+
+ /* Bit 0 = right coin counter */
+ coin_counter_w(1, data & 0x01);
+}
diff --git a/src/mame/machine/midtunit.c b/src/mame/machine/midtunit.c
new file mode 100644
index 00000000000..b9fa00434f1
--- /dev/null
+++ b/src/mame/machine/midtunit.c
@@ -0,0 +1,629 @@
+/*************************************************************************
+
+ Driver for Midway T-unit games.
+
+**************************************************************************/
+
+#include "driver.h"
+#include "cpu/tms34010/tms34010.h"
+#include "cpu/m6809/m6809.h"
+#include "audio/williams.h"
+#include "audio/dcs.h"
+#include "midtunit.h"
+
+
+/* compile-time constants */
+#define ENABLE_ALL_JDREDD_LEVELS 0
+
+
+/* constant definitions */
+#define SOUND_ADPCM 1
+#define SOUND_ADPCM_LARGE 2
+#define SOUND_DCS 3
+
+
+/* CMOS-related variables */
+static UINT8 cmos_write_enable;
+
+/* sound-related variables */
+static UINT8 chip_type;
+static UINT8 fake_sound_state;
+
+/* protection */
+static UINT8 mk_prot_index;
+static UINT16 mk2_prot_data;
+
+static const UINT32 *nbajam_prot_table;
+static UINT16 nbajam_prot_queue[5];
+static UINT8 nbajam_prot_index;
+
+static const UINT8 *jdredd_prot_table;
+static UINT8 jdredd_prot_index;
+static UINT8 jdredd_prot_max;
+
+
+
+/*************************************
+ *
+ * State saving
+ *
+ *************************************/
+
+static void register_state_saving(void)
+{
+ state_save_register_global(cmos_write_enable);
+ state_save_register_global(fake_sound_state);
+ state_save_register_global(mk_prot_index);
+ state_save_register_global(mk2_prot_data);
+ state_save_register_global_array(nbajam_prot_queue);
+ state_save_register_global(nbajam_prot_index);
+ state_save_register_global(jdredd_prot_index);
+ state_save_register_global(jdredd_prot_max);
+}
+
+
+
+/*************************************
+ *
+ * CMOS reads/writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( midtunit_cmos_enable_w )
+{
+ cmos_write_enable = 1;
+}
+
+
+WRITE16_HANDLER( midtunit_cmos_w )
+{
+ if (1)/*cmos_write_enable)*/
+ {
+ COMBINE_DATA(generic_nvram16+offset);
+ cmos_write_enable = 0;
+ }
+ else
+ {
+ logerror("%08X:Unexpected CMOS W @ %05X\n", activecpu_get_pc(), offset);
+ popmessage("Bad CMOS write");
+ }
+}
+
+
+READ16_HANDLER( midtunit_cmos_r )
+{
+ return generic_nvram16[offset];
+}
+
+
+
+/*************************************
+ *
+ * Generic input ports
+ *
+ *************************************/
+
+READ16_HANDLER( midtunit_input_r )
+{
+ return readinputport(offset);
+}
+
+
+
+/*************************************
+ *
+ * Mortal Kombat (T-unit) protection
+ *
+ *************************************/
+
+static const UINT8 mk_prot_values[] =
+{
+ 0x13, 0x27, 0x0f, 0x1f, 0x3e, 0x3d, 0x3b, 0x37,
+ 0x2e, 0x1c, 0x38, 0x31, 0x22, 0x05, 0x0a, 0x15,
+ 0x2b, 0x16, 0x2d, 0x1a, 0x34, 0x28, 0x10, 0x21,
+ 0x03, 0x06, 0x0c, 0x19, 0x32, 0x24, 0x09, 0x13,
+ 0x27, 0x0f, 0x1f, 0x3e, 0x3d, 0x3b, 0x37, 0x2e,
+ 0x1c, 0x38, 0x31, 0x22, 0x05, 0x0a, 0x15, 0x2b,
+ 0x16, 0x2d, 0x1a, 0x34, 0x28, 0x10, 0x21, 0x03,
+ 0xff
+};
+
+static READ16_HANDLER( mk_prot_r )
+{
+ logerror("%08X:Protection R @ %05X = %04X\n", activecpu_get_pc(), offset, mk_prot_values[mk_prot_index] << 9);
+
+ /* just in case */
+ if (mk_prot_index >= sizeof(mk_prot_values))
+ {
+ logerror("%08X:Unexpected protection R @ %05X\n", activecpu_get_pc(), offset);
+ mk_prot_index = 0;
+ }
+
+ return mk_prot_values[mk_prot_index++] << 9;
+}
+
+static WRITE16_HANDLER( mk_prot_w )
+{
+ if (ACCESSING_MSB)
+ {
+ int first_val = (data >> 9) & 0x3f;
+ int i;
+
+ /* find the desired first value and stop then */
+ for (i = 0; i < sizeof(mk_prot_values); i++)
+ if (mk_prot_values[i] == first_val)
+ {
+ mk_prot_index = i;
+ break;
+ }
+
+ /* just in case */
+ if (i == sizeof(mk_prot_values))
+ {
+ logerror("%08X:Unhandled protection W @ %05X = %04X\n", activecpu_get_pc(), offset, data);
+ mk_prot_index = 0;
+ }
+
+ logerror("%08X:Protection W @ %05X = %04X\n", activecpu_get_pc(), offset, data);
+ }
+}
+
+
+
+/*************************************
+ *
+ * Mortal Kombat 2 protection
+ *
+ *************************************/
+
+static READ16_HANDLER( mk2_prot_const_r )
+{
+ return 2;
+}
+
+static READ16_HANDLER( mk2_prot_r )
+{
+ return mk2_prot_data;
+}
+
+static READ16_HANDLER( mk2_prot_shift_r )
+{
+ return mk2_prot_data >> 1;
+}
+
+static WRITE16_HANDLER( mk2_prot_w )
+{
+ COMBINE_DATA(&mk2_prot_data);
+}
+
+
+
+/*************************************
+ *
+ * NBA Jam protection
+ *
+ *************************************/
+
+static const UINT32 nbajam_prot_values[128] =
+{
+ 0x21283b3b, 0x2439383b, 0x31283b3b, 0x302b3938, 0x31283b3b, 0x302b3938, 0x232f2f2f, 0x26383b3b,
+ 0x21283b3b, 0x2439383b, 0x312a1224, 0x302b1120, 0x312a1224, 0x302b1120, 0x232d283b, 0x26383b3b,
+ 0x2b3b3b3b, 0x2e2e2e2e, 0x39383b1b, 0x383b3b1b, 0x3b3b3b1b, 0x3a3a3a1a, 0x2b3b3b3b, 0x2e2e2e2e,
+ 0x2b39383b, 0x2e2e2e2e, 0x393a1a18, 0x383b1b1b, 0x3b3b1b1b, 0x3a3a1a18, 0x2b39383b, 0x2e2e2e2e,
+ 0x01202b3b, 0x0431283b, 0x11202b3b, 0x1021283b, 0x11202b3b, 0x1021283b, 0x03273b3b, 0x06302b39,
+ 0x09302b39, 0x0c232f2f, 0x19322e06, 0x18312a12, 0x19322e06, 0x18312a12, 0x0b31283b, 0x0e26383b,
+ 0x03273b3b, 0x06302b39, 0x11202b3b, 0x1021283b, 0x13273938, 0x12243938, 0x03273b3b, 0x06302b39,
+ 0x0b31283b, 0x0e26383b, 0x19322e06, 0x18312a12, 0x1b332f05, 0x1a302b11, 0x0b31283b, 0x0e26383b,
+ 0x21283b3b, 0x2439383b, 0x31283b3b, 0x302b3938, 0x31283b3b, 0x302b3938, 0x232f2f2f, 0x26383b3b,
+ 0x21283b3b, 0x2439383b, 0x312a1224, 0x302b1120, 0x312a1224, 0x302b1120, 0x232d283b, 0x26383b3b,
+ 0x2b3b3b3b, 0x2e2e2e2e, 0x39383b1b, 0x383b3b1b, 0x3b3b3b1b, 0x3a3a3a1a, 0x2b3b3b3b, 0x2e2e2e2e,
+ 0x2b39383b, 0x2e2e2e2e, 0x393a1a18, 0x383b1b1b, 0x3b3b1b1b, 0x3a3a1a18, 0x2b39383b, 0x2e2e2e2e,
+ 0x01202b3b, 0x0431283b, 0x11202b3b, 0x1021283b, 0x11202b3b, 0x1021283b, 0x03273b3b, 0x06302b39,
+ 0x09302b39, 0x0c232f2f, 0x19322e06, 0x18312a12, 0x19322e06, 0x18312a12, 0x0b31283b, 0x0e26383b,
+ 0x03273b3b, 0x06302b39, 0x11202b3b, 0x1021283b, 0x13273938, 0x12243938, 0x03273b3b, 0x06302b39,
+ 0x0b31283b, 0x0e26383b, 0x19322e06, 0x18312a12, 0x1b332f05, 0x1a302b11, 0x0b31283b, 0x0e26383b
+};
+
+static const UINT32 nbajamte_prot_values[128] =
+{
+ 0x00000000, 0x04081020, 0x08102000, 0x0c183122, 0x10200000, 0x14281020, 0x18312204, 0x1c393326,
+ 0x20000001, 0x24081021, 0x28102000, 0x2c183122, 0x30200001, 0x34281021, 0x38312204, 0x3c393326,
+ 0x00000102, 0x04081122, 0x08102102, 0x0c183122, 0x10200000, 0x14281020, 0x18312204, 0x1c393326,
+ 0x20000103, 0x24081123, 0x28102102, 0x2c183122, 0x30200001, 0x34281021, 0x38312204, 0x3c393326,
+ 0x00010204, 0x04091224, 0x08112204, 0x0c193326, 0x10210204, 0x14291224, 0x18312204, 0x1c393326,
+ 0x20000001, 0x24081021, 0x28102000, 0x2c183122, 0x30200001, 0x34281021, 0x38312204, 0x3c393326,
+ 0x00010306, 0x04091326, 0x08112306, 0x0c193326, 0x10210204, 0x14291224, 0x18312204, 0x1c393326,
+ 0x20000103, 0x24081123, 0x28102102, 0x2c183122, 0x30200001, 0x34281021, 0x38312204, 0x3c393326,
+ 0x00000000, 0x01201028, 0x02213018, 0x03012030, 0x04223138, 0x05022110, 0x06030120, 0x07231108,
+ 0x08042231, 0x09243219, 0x0a251229, 0x0b050201, 0x0c261309, 0x0d060321, 0x0e072311, 0x0f273339,
+ 0x10080422, 0x1128140a, 0x1229343a, 0x13092412, 0x142a351a, 0x150a2532, 0x160b0502, 0x172b152a,
+ 0x180c2613, 0x192c363b, 0x1a2d160b, 0x1b0d0623, 0x1c2e172b, 0x1d0e0703, 0x1e0f2733, 0x1f2f371b,
+ 0x20100804, 0x2130182c, 0x2231381c, 0x23112834, 0x2432393c, 0x25122914, 0x26130924, 0x2733190c,
+ 0x28142a35, 0x29343a1d, 0x2a351a2d, 0x2b150a05, 0x2c361b0d, 0x2d160b25, 0x2e172b15, 0x2f373b3d,
+ 0x30180c26, 0x31381c0e, 0x32393c3e, 0x33192c16, 0x343a3d1e, 0x351a2d36, 0x361b0d06, 0x373b1d2e,
+ 0x381c2e17, 0x393c3e3f, 0x3a3d1e0f, 0x3b1d0e27, 0x3c3e1f2f, 0x3d1e0f07, 0x3e1f2f37, 0x3f3f3f1f
+};
+
+static READ16_HANDLER( nbajam_prot_r )
+{
+ int result = nbajam_prot_queue[nbajam_prot_index];
+ if (nbajam_prot_index < 4)
+ nbajam_prot_index++;
+ return result;
+}
+
+static WRITE16_HANDLER( nbajam_prot_w )
+{
+ int table_index = (offset >> 6) & 0x7f;
+ UINT32 protval = nbajam_prot_table[table_index];
+
+ nbajam_prot_queue[0] = data;
+ nbajam_prot_queue[1] = ((protval >> 24) & 0xff) << 9;
+ nbajam_prot_queue[2] = ((protval >> 16) & 0xff) << 9;
+ nbajam_prot_queue[3] = ((protval >> 8) & 0xff) << 9;
+ nbajam_prot_queue[4] = ((protval >> 0) & 0xff) << 9;
+ nbajam_prot_index = 0;
+}
+
+
+
+/*************************************
+ *
+ * Judge Dredd protection
+ *
+ *************************************/
+
+static const UINT8 jdredd_prot_values_10740[] =
+{
+ 0x14,0x2A,0x15,0x0A,0x25,0x32,0x39,0x1C,
+ 0x2E,0x37,0x3B,0x1D,0x2E,0x37,0x1B,0x0D,
+ 0x26,0x33,0x39,0x3C,0x1E,0x2F,0x37,0x3B,
+ 0x3D,0x3E,0x3F,0x1F,0x2F,0x17,0x0B,0x25,
+ 0x32,0x19,0x0C,0x26,0x33,0x19,0x2C,0x16,
+ 0x2B,0x15,0x0A,0x05,0x22,0x00
+};
+
+static const UINT8 jdredd_prot_values_13240[] =
+{
+ 0x28
+};
+
+static const UINT8 jdredd_prot_values_76540[] =
+{
+ 0x04,0x08
+};
+
+static const UINT8 jdredd_prot_values_77760[] =
+{
+ 0x14,0x2A,0x14,0x2A,0x35,0x2A,0x35,0x1A,
+ 0x35,0x1A,0x2D,0x1A,0x2D,0x36,0x2D,0x36,
+ 0x1B,0x36,0x1B,0x36,0x2C,0x36,0x2C,0x18,
+ 0x2C,0x18,0x31,0x18,0x31,0x22,0x31,0x22,
+ 0x04,0x22,0x04,0x08,0x04,0x08,0x10,0x08,
+ 0x10,0x20,0x10,0x20,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x01,0x00,0x01,0x02,0x01,0x02,
+ 0x05,0x02,0x05,0x0B,0x05,0x0B,0x16,0x0B,
+ 0x16,0x2C,0x16,0x2C,0x18,0x2C,0x18,0x31,
+ 0x18,0x31,0x22,0x31,0x22,0x04,0x22,0x04,
+ 0x08,0x04,0x08,0x10,0x08,0x10,0x20,0x10,
+ 0x20,0x00,0x00
+};
+
+static const UINT8 jdredd_prot_values_80020[] =
+{
+ 0x3A,0x1D,0x2E,0x37,0x00,0x00,0x2C,0x1C,
+ 0x39,0x33,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static WRITE16_HANDLER( jdredd_prot_w )
+{
+ logerror("%08X:jdredd_prot_w(%04X,%04X)\n", activecpu_get_previouspc(), offset*16, data);
+
+ switch (offset)
+ {
+ case TOWORD(0x10740):
+ jdredd_prot_index = 0;
+ jdredd_prot_table = jdredd_prot_values_10740;
+ jdredd_prot_max = sizeof(jdredd_prot_values_10740);
+ logerror("-- reset prot table 10740\n");
+ break;
+
+ case TOWORD(0x13240):
+ jdredd_prot_index = 0;
+ jdredd_prot_table = jdredd_prot_values_13240;
+ jdredd_prot_max = sizeof(jdredd_prot_values_13240);
+ logerror("-- reset prot table 13240\n");
+ break;
+
+ case TOWORD(0x76540):
+ jdredd_prot_index = 0;
+ jdredd_prot_table = jdredd_prot_values_76540;
+ jdredd_prot_max = sizeof(jdredd_prot_values_76540);
+ logerror("-- reset prot table 76540\n");
+ break;
+
+ case TOWORD(0x77760):
+ jdredd_prot_index = 0;
+ jdredd_prot_table = jdredd_prot_values_77760;
+ jdredd_prot_max = sizeof(jdredd_prot_values_77760);
+ logerror("-- reset prot table 77760\n");
+ break;
+
+ case TOWORD(0x80020):
+ jdredd_prot_index = 0;
+ jdredd_prot_table = jdredd_prot_values_80020;
+ jdredd_prot_max = sizeof(jdredd_prot_values_80020);
+ logerror("-- reset prot table 80020\n");
+ break;
+ }
+}
+
+static READ16_HANDLER( jdredd_prot_r )
+{
+ UINT16 result = 0xffff;
+
+ if (jdredd_prot_table && jdredd_prot_index < jdredd_prot_max)
+ result = jdredd_prot_table[jdredd_prot_index++] << 9;
+
+ logerror("%08X:jdredd_prot_r(%04X) = %04X\n", activecpu_get_previouspc(), offset*16, result);
+ return result;
+}
+
+
+#if ENABLE_ALL_JDREDD_LEVELS
+static UINT16 *jdredd_hack;
+static READ16_HANDLER( jdredd_hack_r )
+{
+ if (activecpu_get_pc() == 0xFFBA7EB0)
+ {
+ fprintf(stderr, "jdredd_hack_r\n");
+ return 0;
+ }
+
+ return jdredd_hack[offset];
+}
+#endif
+
+
+
+/*************************************
+ *
+ * Generic driver init
+ *
+ *************************************/
+
+static void init_tunit_generic(int sound)
+{
+ offs_t gfx_chunk = midyunit_gfx_rom_size / 4;
+ UINT8 *base;
+ int i;
+
+ /* register for state saving */
+ register_state_saving();
+
+ /* load the graphics ROMs -- quadruples */
+ base = memory_region(REGION_GFX1);
+ for (i = 0; i < midyunit_gfx_rom_size; i += 4)
+ {
+ midyunit_gfx_rom[i + 0] = base[0 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 1] = base[1 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 2] = base[2 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 3] = base[3 * gfx_chunk + i / 4];
+ }
+
+ /* load sound ROMs and set up sound handlers */
+ chip_type = sound;
+ switch (sound)
+ {
+ case SOUND_ADPCM:
+ case SOUND_ADPCM_LARGE:
+ williams_adpcm_init();
+ break;
+
+ case SOUND_DCS:
+ dcs_init();
+ break;
+ }
+
+ /* default graphics functionality */
+ midtunit_gfx_rom_large = 0;
+}
+
+
+
+/*************************************
+ *
+ * T-unit init (ADPCM)
+ *
+ * music: 6809 driving YM2151, DAC, and OKIM6295
+ *
+ *************************************/
+
+DRIVER_INIT( mktunit )
+{
+ /* common init */
+ init_tunit_generic(SOUND_ADPCM);
+
+ /* protection */
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b00000, 0x1b6ffff, 0, 0, mk_prot_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b00000, 0x1b6ffff, 0, 0, mk_prot_w);
+
+ /* sound chip protection (hidden RAM) */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0xfb9c, 0xfbc6, 0, 0, MWA8_RAM);
+}
+
+static void init_nbajam_common(int te_protection)
+{
+ /* common init */
+ init_tunit_generic(SOUND_ADPCM_LARGE);
+
+ /* protection */
+ if (!te_protection)
+ {
+ nbajam_prot_table = nbajam_prot_values;
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b14020, 0x1b2503f, 0, 0, nbajam_prot_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b14020, 0x1b2503f, 0, 0, nbajam_prot_w);
+ }
+ else
+ {
+ nbajam_prot_table = nbajamte_prot_values;
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b15f40, 0x1b37f5f, 0, 0, nbajam_prot_r);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b95f40, 0x1bb7f5f, 0, 0, nbajam_prot_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b15f40, 0x1b37f5f, 0, 0, nbajam_prot_w);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b95f40, 0x1bb7f5f, 0, 0, nbajam_prot_w);
+ }
+
+ /* sound chip protection (hidden RAM) */
+ if (!te_protection)
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0xfbaa, 0xfbd4, 0, 0, MWA8_RAM);
+ else
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0xfbec, 0xfc16, 0, 0, MWA8_RAM);
+}
+
+DRIVER_INIT( nbajam )
+{
+ init_nbajam_common(0);
+}
+
+DRIVER_INIT( nbajamte )
+{
+ init_nbajam_common(1);
+}
+
+DRIVER_INIT( jdreddp )
+{
+ /* common init */
+ init_tunit_generic(SOUND_ADPCM_LARGE);
+
+ /* looks like the watchdog needs to be disabled */
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01d81060, 0x01d8107f, 0, 0, MWA16_NOP);
+
+ /* protection */
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b00000, 0x1bfffff, 0, 0, jdredd_prot_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x1b00000, 0x1bfffff, 0, 0, jdredd_prot_w);
+
+ /* sound chip protection (hidden RAM) */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0xfbcf, 0xfbf9, 0, 0, MWA8_RAM);
+
+#if ENABLE_ALL_JDREDD_LEVELS
+ /* how about the final levels? */
+ jdredd_hack = memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0xFFBA7FF0, 0xFFBA7FFf, 0, 0, jdredd_hack_r);
+#endif
+}
+
+
+
+/*************************************
+ *
+ * T-unit init (DCS)
+ *
+ * music: ADSP2105
+ *
+ *************************************/
+
+DRIVER_INIT( mk2 )
+{
+ /* common init */
+ init_tunit_generic(SOUND_DCS);
+ midtunit_gfx_rom_large = 1;
+
+ /* protection */
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x00f20c60, 0x00f20c7f, 0, 0, mk2_prot_w);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x00f42820, 0x00f4283f, 0, 0, mk2_prot_w);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01a190e0, 0x01a190ff, 0, 0, mk2_prot_r);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01a191c0, 0x01a191df, 0, 0, mk2_prot_shift_r);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01a3d0c0, 0x01a3d0ff, 0, 0, mk2_prot_r);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01d9d1e0, 0x01d9d1ff, 0, 0, mk2_prot_const_r);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01def920, 0x01def93f, 0, 0, mk2_prot_const_r);
+}
+
+
+
+/*************************************
+ *
+ * Machine init
+ *
+ *************************************/
+
+MACHINE_RESET( midtunit )
+{
+ /* reset sound */
+ switch (chip_type)
+ {
+ case SOUND_ADPCM:
+ case SOUND_ADPCM_LARGE:
+ williams_adpcm_reset_w(1);
+ williams_adpcm_reset_w(0);
+ break;
+
+ case SOUND_DCS:
+ dcs_reset_w(1);
+ dcs_reset_w(0);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Sound write handlers
+ *
+ *************************************/
+
+READ16_HANDLER( midtunit_sound_state_r )
+{
+/* logerror("%08X:Sound status read\n", activecpu_get_pc());*/
+
+ if (chip_type == SOUND_DCS)
+ return dcs_control_r() >> 4;
+
+ if (fake_sound_state)
+ {
+ fake_sound_state--;
+ return 0;
+ }
+ return ~0;
+}
+
+READ16_HANDLER( midtunit_sound_r )
+{
+ logerror("%08X:Sound data read\n", activecpu_get_pc());
+
+ if (chip_type == SOUND_DCS)
+ return dcs_data_r() & 0xff;
+
+ return ~0;
+}
+
+WRITE16_HANDLER( midtunit_sound_w )
+{
+ /* check for out-of-bounds accesses */
+ if (!offset)
+ {
+ logerror("%08X:Unexpected write to sound (lo) = %04X\n", activecpu_get_pc(), data);
+ return;
+ }
+
+ /* call through based on the sound type */
+ if (ACCESSING_LSB && ACCESSING_MSB)
+ switch (chip_type)
+ {
+ case SOUND_ADPCM:
+ case SOUND_ADPCM_LARGE:
+ williams_adpcm_reset_w(~data & 0x100);
+ williams_adpcm_data_w(data & 0xff);
+
+ /* the games seem to check for $82 loops, so this should be just barely enough */
+ fake_sound_state = 128;
+ break;
+
+ case SOUND_DCS:
+ logerror("%08X:Sound write = %04X\n", activecpu_get_pc(), data);
+ dcs_reset_w(~data & 0x100);
+ dcs_data_w(data & 0xff);
+ /* the games seem to check for $82 loops, so this should be just barely enough */
+ fake_sound_state = 128;
+ break;
+ }
+}
diff --git a/src/mame/machine/midwayic.c b/src/mame/machine/midwayic.c
new file mode 100644
index 00000000000..4ac3403c28c
--- /dev/null
+++ b/src/mame/machine/midwayic.c
@@ -0,0 +1,1098 @@
+/***************************************************************************
+
+ Emulation of various Midway ICs
+
+***************************************************************************/
+
+#include "driver.h"
+#include "debugger.h"
+#include "midwayic.h"
+#include "machine/idectrl.h"
+#include "audio/cage.h"
+#include "audio/dcs.h"
+
+
+#define LOG_NVRAM (0)
+
+#define PRINTF_DEBUG (0)
+#define LOG_IOASIC (0)
+#define LOG_FIFO (0)
+
+
+/*************************************
+ *
+ * Constants
+ *
+ *************************************/
+
+#define PIC_NVRAM_SIZE 0x100
+#define FIFO_SIZE 512
+
+
+
+/*************************************
+ *
+ * Type definitions
+ *
+ *************************************/
+
+struct serial_state
+{
+ UINT8 data[16];
+ UINT8 buffer;
+ UINT8 index;
+ UINT8 status;
+ UINT8 bits;
+ UINT8 ormask;
+};
+
+struct pic_state
+{
+ UINT16 latch;
+ attotime latch_expire_time;
+ UINT8 state;
+ UINT8 index;
+ UINT8 total;
+ UINT8 nvram_addr;
+ UINT8 buffer[0x10];
+ UINT8 nvram[PIC_NVRAM_SIZE];
+ UINT8 default_nvram[PIC_NVRAM_SIZE];
+ UINT8 time_buf[8];
+ UINT8 time_index;
+ UINT8 time_just_written;
+ UINT16 yearoffs;
+ emu_timer *time_write_timer;
+};
+
+struct ioasic_state
+{
+ UINT32 reg[16];
+ UINT8 has_dcs;
+ UINT8 has_cage;
+ UINT8 dcs_cpu;
+ UINT8 shuffle_type;
+ UINT8 shuffle_active;
+ UINT8 * shuffle_map;
+ void (*irq_callback)(int);
+ UINT8 irq_state;
+ UINT16 sound_irq_state;
+ UINT8 auto_ack;
+ UINT8 force_fifo_full;
+
+ UINT16 fifo[FIFO_SIZE];
+ UINT16 fifo_in;
+ UINT16 fifo_out;
+ UINT16 fifo_bytes;
+ offs_t fifo_force_buffer_empty_pc;
+};
+
+
+
+/*************************************
+ *
+ * Local variables
+ *
+ *************************************/
+
+static struct serial_state serial;
+static struct pic_state pic;
+static struct ioasic_state ioasic;
+
+
+
+
+/*************************************
+ *
+ * Serial number encoding
+ *
+ *************************************/
+
+static void generate_serial_data(int upper)
+{
+ int year = atoi(Machine->gamedrv->year), month = 12, day = 11;
+ UINT32 serial_number, temp;
+ UINT8 serial_digit[9];
+
+ serial_number = 123456;
+ serial_number += upper * 1000000;
+
+ serial_digit[0] = (serial_number / 100000000) % 10;
+ serial_digit[1] = (serial_number / 10000000) % 10;
+ serial_digit[2] = (serial_number / 1000000) % 10;
+ serial_digit[3] = (serial_number / 100000) % 10;
+ serial_digit[4] = (serial_number / 10000) % 10;
+ serial_digit[5] = (serial_number / 1000) % 10;
+ serial_digit[6] = (serial_number / 100) % 10;
+ serial_digit[7] = (serial_number / 10) % 10;
+ serial_digit[8] = (serial_number / 1) % 10;
+
+ serial.data[12] = mame_rand(Machine) & 0xff;
+ serial.data[13] = mame_rand(Machine) & 0xff;
+
+ serial.data[14] = 0; /* ??? */
+ serial.data[15] = 0; /* ??? */
+
+ temp = 0x174 * (year - 1980) + 0x1f * (month - 1) + day;
+ serial.data[10] = (temp >> 8) & 0xff;
+ serial.data[11] = temp & 0xff;
+
+ temp = serial_digit[4] + serial_digit[7] * 10 + serial_digit[1] * 100;
+ temp = (temp + 5 * serial.data[13]) * 0x1bcd + 0x1f3f0;
+ serial.data[7] = temp & 0xff;
+ serial.data[8] = (temp >> 8) & 0xff;
+ serial.data[9] = (temp >> 16) & 0xff;
+
+ temp = serial_digit[6] + serial_digit[8] * 10 + serial_digit[0] * 100 + serial_digit[2] * 10000;
+ temp = (temp + 2 * serial.data[13] + serial.data[12]) * 0x107f + 0x71e259;
+ serial.data[3] = temp & 0xff;
+ serial.data[4] = (temp >> 8) & 0xff;
+ serial.data[5] = (temp >> 16) & 0xff;
+ serial.data[6] = (temp >> 24) & 0xff;
+
+ temp = serial_digit[5] * 10 + serial_digit[3] * 100;
+ temp = (temp + serial.data[12]) * 0x245 + 0x3d74;
+ serial.data[0] = temp & 0xff;
+ serial.data[1] = (temp >> 8) & 0xff;
+ serial.data[2] = (temp >> 16) & 0xff;
+
+ /* special hack for RevX */
+ serial.ormask = 0x80;
+ if (upper == 419)
+ serial.ormask = 0x00;
+}
+
+
+
+/*************************************
+ *
+ * Original serial number PIC
+ * interface
+ *
+ *************************************/
+
+static void serial_register_state(void)
+{
+ state_save_register_global_array(serial.data);
+ state_save_register_global(serial.buffer);
+ state_save_register_global(serial.index);
+ state_save_register_global(serial.status);
+ state_save_register_global(serial.bits);
+ state_save_register_global(serial.ormask);
+}
+
+
+void midway_serial_pic_init(int upper)
+{
+ serial_register_state();
+ generate_serial_data(upper);
+}
+
+
+void midway_serial_pic_reset_w(int state)
+{
+ if (state)
+ {
+ serial.index = 0;
+ serial.status = 0;
+ serial.buffer = 0;
+ }
+}
+
+
+UINT8 midway_serial_pic_status_r(void)
+{
+ return serial.status;
+}
+
+
+UINT8 midway_serial_pic_r(void)
+{
+ logerror("%08X:security R = %04X\n", safe_activecpu_get_pc(), serial.buffer);
+ serial.status = 1;
+ return serial.buffer;
+}
+
+
+void midway_serial_pic_w(UINT8 data)
+{
+ logerror("%08X:security W = %04X\n", safe_activecpu_get_pc(), data);
+
+ /* status seems to reflect the clock bit */
+ serial.status = (data >> 4) & 1;
+
+ /* on the falling edge, clock the next data byte through */
+ if (!serial.status)
+ {
+ /* the self-test writes 1F, 0F, and expects to read an F in the low 4 bits */
+ /* Cruis'n World expects the high bit to be set as well */
+ if (data & 0x0f)
+ serial.buffer = serial.ormask | data;
+ else
+ serial.buffer = serial.data[serial.index++ % sizeof(serial.data)];
+ }
+}
+
+
+
+/*************************************
+ *
+ * Second generation serial number
+ * PIC interface; this version also
+ * contained some NVRAM and a real
+ * time clock
+ *
+ *************************************/
+
+INLINE UINT8 make_bcd(UINT8 data)
+{
+ return ((data / 10) << 4) | (data % 10);
+}
+
+
+INLINE UINT8 unmake_bcd(UINT8 data)
+{
+ return ((data & 0xf0) >> 4) * 10 + (data & 0x0f);
+}
+
+
+static TIMER_CALLBACK( reset_timer )
+{
+ pic.time_just_written = 0;
+}
+
+
+static void pic_register_state(void)
+{
+ state_save_register_global(pic.latch);
+ state_save_register_global(pic.latch_expire_time.seconds);
+ state_save_register_global(pic.latch_expire_time.attoseconds);
+ state_save_register_global(pic.state);
+ state_save_register_global(pic.index);
+ state_save_register_global(pic.total);
+ state_save_register_global(pic.nvram_addr);
+ state_save_register_global_array(pic.buffer);
+ state_save_register_global_array(pic.nvram);
+ state_save_register_global_array(pic.default_nvram);
+ state_save_register_global_array(pic.time_buf);
+ state_save_register_global(pic.time_index);
+ state_save_register_global(pic.time_just_written);
+ state_save_register_global(pic.yearoffs);
+}
+
+
+void midway_serial_pic2_init(int upper, int yearoffs)
+{
+ serial_register_state();
+ pic_register_state();
+
+ pic.yearoffs = yearoffs;
+ pic.time_just_written = 0;
+ pic.time_write_timer = timer_alloc(reset_timer);
+ memset(pic.default_nvram, 0xff, sizeof(pic.default_nvram));
+ generate_serial_data(upper);
+}
+
+
+void midway_serial_pic2_set_default_nvram(const UINT8 *nvram)
+{
+ memcpy(pic.default_nvram, nvram, sizeof(pic.default_nvram));
+}
+
+
+UINT8 midway_serial_pic2_status_r(void)
+{
+ UINT8 result = 0;
+
+ /* if we're still holding the data ready bit high, do it */
+ if (pic.latch & 0xf00)
+ {
+ if (attotime_compare(timer_get_time(), pic.latch_expire_time) > 0)
+ pic.latch &= 0xff;
+ else
+ pic.latch -= 0x100;
+ result = 1;
+ }
+
+ logerror("%06X:PIC status %d\n", safe_activecpu_get_pc(), result);
+ return result;
+}
+
+
+UINT8 midway_serial_pic2_r(void)
+{
+ UINT8 result = 0;
+
+ /* PIC data register */
+ logerror("%06X:PIC data read (index=%d total=%d latch=%03X) =", safe_activecpu_get_pc(), pic.index, pic.total, pic.latch);
+
+ /* return the current result */
+ if (pic.latch & 0xf00)
+ result = pic.latch & 0xff;
+
+ /* otherwise, return 0xff if we have data ready */
+ else if (pic.index < pic.total)
+ result = 0xff;
+
+ logerror("%02X\n", result);
+ return result;
+}
+
+
+void midway_serial_pic2_w(UINT8 data)
+{
+ static FILE *nvramlog;
+ if (LOG_NVRAM && !nvramlog)
+ nvramlog = fopen("nvram.log", "w");
+
+ /* PIC command register */
+ if (pic.state == 0)
+ logerror("%06X:PIC command %02X\n", safe_activecpu_get_pc(), data);
+ else
+ logerror("%06X:PIC data %02X\n", safe_activecpu_get_pc(), data);
+
+ /* store in the latch, along with a bit to indicate we have data */
+ pic.latch = (data & 0x00f) | 0x480;
+ pic.latch_expire_time = attotime_add(timer_get_time(), ATTOTIME_IN_MSEC(1));
+ if (data & 0x10)
+ {
+ int cmd = pic.state ? (pic.state & 0x0f) : (pic.latch & 0x0f);
+ switch (cmd)
+ {
+ /* written to latch the next byte of data */
+ case 0:
+ if (pic.index < pic.total)
+ pic.latch = 0x400 | pic.buffer[pic.index++];
+ break;
+
+ /* fetch the serial number */
+ case 1:
+ /* note: Biofreaks assumes that it can latch the next byte this way */
+ if (pic.index < pic.total)
+ pic.latch = 0x400 | pic.buffer[pic.index++];
+ else
+ {
+ memcpy(pic.buffer, serial.data, 16);
+ pic.total = 16;
+ pic.index = 0;
+ DEBUGGER_BREAK;
+ }
+ break;
+
+ /* read the clock */
+ case 3:
+ {
+ /* stuff it into the data bytes */
+ pic.index = 0;
+ pic.total = 0;
+
+ /* if we haven't written a new time recently, use the real live time */
+ if (!pic.time_just_written)
+ {
+ mame_system_time systime;
+ mame_get_base_datetime(Machine, &systime);
+
+ pic.buffer[pic.total++] = make_bcd(systime.local_time.second);
+ pic.buffer[pic.total++] = make_bcd(systime.local_time.minute);
+ pic.buffer[pic.total++] = make_bcd(systime.local_time.hour);
+ pic.buffer[pic.total++] = make_bcd(systime.local_time.weekday + 1);
+ pic.buffer[pic.total++] = make_bcd(systime.local_time.mday);
+ pic.buffer[pic.total++] = make_bcd(systime.local_time.month + 1);
+ pic.buffer[pic.total++] = make_bcd(systime.local_time.year - 1900 - pic.yearoffs);
+ }
+
+ /* otherwise, just parrot back what was written to pass self tests */
+ else
+ {
+ pic.buffer[pic.total++] = pic.time_buf[0];
+ pic.buffer[pic.total++] = pic.time_buf[1];
+ pic.buffer[pic.total++] = pic.time_buf[2];
+ pic.buffer[pic.total++] = pic.time_buf[3];
+ pic.buffer[pic.total++] = pic.time_buf[4];
+ pic.buffer[pic.total++] = pic.time_buf[5];
+ pic.buffer[pic.total++] = pic.time_buf[6];
+ }
+ break;
+ }
+
+ /* write the clock */
+ case 4:
+
+ /* if coming from state 0, go to state 1 (this is just the command byte) */
+ if (pic.state == 0)
+ {
+ pic.state = 0x14;
+ pic.time_index = 0;
+ }
+
+ /* if in states 1-2 put data in the buffer until it's full */
+ else if (pic.state == 0x14)
+ {
+ pic.time_buf[pic.time_index] = pic.latch & 0x0f;
+ pic.state = 0x24;
+ }
+ else if (pic.state == 0x24)
+ {
+ pic.time_buf[pic.time_index++] |= pic.latch << 4;
+
+ /* if less than 7 bytes accumulated, go back to state 1 */
+ if (pic.time_index < 7)
+ pic.state = 0x14;
+
+ /* otherwise, flag the time as having just been written for 1/2 second */
+ else
+ {
+ timer_adjust(pic.time_write_timer, ATTOTIME_IN_MSEC(500), 0, attotime_zero);
+ pic.time_just_written = 1;
+ pic.state = 0;
+ }
+ }
+ break;
+
+ /* write to NVRAM */
+ case 5:
+
+ /* if coming from state 0, go to state 1 (this is just the command byte) */
+ if (pic.state == 0)
+ pic.state = 0x15;
+
+ /* coming from state 1, go to state 2 and latch the low 4 address bits */
+ else if (pic.state == 0x15)
+ {
+ pic.nvram_addr = pic.latch & 0x0f;
+ pic.state = 0x25;
+ }
+
+ /* coming from state 2, go to state 3 and latch the high 4 address bits */
+ else if (pic.state == 0x25)
+ {
+ pic.state = 0x35;
+ pic.nvram_addr |= pic.latch << 4;
+ }
+
+ /* coming from state 3, go to state 4 and write the low 4 bits */
+ else if (pic.state == 0x35)
+ {
+ pic.state = 0x45;
+ pic.nvram[pic.nvram_addr] = pic.latch & 0x0f;
+ }
+
+ /* coming from state 4, reset the states and write the upper 4 bits */
+ else if (pic.state == 0x45)
+ {
+ pic.state = 0;
+ pic.nvram[pic.nvram_addr] |= pic.latch << 4;
+ if (nvramlog)
+ fprintf(nvramlog, "Write byte %02X = %02X\n", pic.nvram_addr, pic.nvram[pic.nvram_addr]);
+ }
+ break;
+
+ /* read from NVRAM */
+ case 6:
+
+ /* if coming from state 0, go to state 1 (this is just the command byte) */
+ if (pic.state == 0)
+ pic.state = 0x16;
+
+ /* coming from state 1, go to state 2 and latch the low 4 address bits */
+ else if (pic.state == 0x16)
+ {
+ pic.nvram_addr = pic.latch & 0x0f;
+ pic.state = 0x26;
+ }
+
+ /* coming from state 2, reset the states and make the data available */
+ else if (pic.state == 0x26)
+ {
+ pic.state = 0;
+ pic.nvram_addr |= pic.latch << 4;
+
+ pic.total = 0;
+ pic.index = 0;
+ pic.buffer[pic.total++] = pic.nvram[pic.nvram_addr];
+ if (nvramlog)
+ fprintf(nvramlog, "Read byte %02X = %02X\n", pic.nvram_addr, pic.nvram[pic.nvram_addr]);
+ }
+ break;
+
+ /* reflect inverted? (Cruisin' Exotica) */
+ case 8:
+ pic.latch = 0x400 | (~cmd & 0xff);
+ break;
+ }
+ }
+}
+
+
+NVRAM_HANDLER( midway_serial_pic2 )
+{
+ if (read_or_write)
+ mame_fwrite(file, pic.nvram, sizeof(pic.nvram));
+ else if (file)
+ mame_fread(file, pic.nvram, sizeof(pic.nvram));
+ else
+ memcpy(pic.nvram, pic.default_nvram, sizeof(pic.nvram));
+}
+
+
+
+/*************************************
+ *
+ * The I/O ASIC was first introduced
+ * in War Gods, then later used on
+ * the Seattle hardware
+ *
+ *************************************/
+
+enum
+{
+ IOASIC_PORT0, /* 0: input port 0 */
+ IOASIC_PORT1, /* 1: input port 1 */
+ IOASIC_PORT2, /* 2: input port 2 */
+ IOASIC_PORT3, /* 3: input port 3 */
+ IOASIC_UARTCONTROL, /* 4: controls some UART behavior */
+ IOASIC_UARTOUT, /* 5: UART output */
+ IOASIC_UARTIN, /* 6: UART input */
+ IOASIC_UNKNOWN7, /* 7: ??? */
+ IOASIC_SOUNDCTL, /* 8: sound communications control */
+ IOASIC_SOUNDOUT, /* 9: sound output port */
+ IOASIC_SOUNDSTAT, /* a: sound status port */
+ IOASIC_SOUNDIN, /* b: sound input port */
+ IOASIC_PICOUT, /* c: PIC output port */
+ IOASIC_PICIN, /* d: PIC input port */
+ IOASIC_INTSTAT, /* e: interrupt status */
+ IOASIC_INTCTL /* f: interrupt control */
+};
+
+static UINT16 ioasic_fifo_r(void);
+static UINT16 ioasic_fifo_status_r(void);
+static void ioasic_input_empty(int state);
+static void ioasic_output_full(int state);
+static void update_ioasic_irq(void);
+static void cage_irq_handler(int state);
+
+
+static void ioasic_register_state(void)
+{
+ state_save_register_global_array(ioasic.reg);
+ state_save_register_global(ioasic.shuffle_active);
+ state_save_register_global(ioasic.irq_state);
+ state_save_register_global(ioasic.sound_irq_state);
+ state_save_register_global(ioasic.auto_ack);
+ state_save_register_global(ioasic.force_fifo_full);
+ state_save_register_global_array(ioasic.fifo);
+ state_save_register_global(ioasic.fifo_in);
+ state_save_register_global(ioasic.fifo_out);
+ state_save_register_global(ioasic.fifo_bytes);
+ state_save_register_global(ioasic.fifo_force_buffer_empty_pc);
+}
+
+
+void midway_ioasic_init(int shuffle, int upper, int yearoffs, void (*irq_callback)(int))
+{
+ static UINT8 shuffle_maps[][16] =
+ {
+ { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf }, /* WarGods, WG3DH, SFRush, MK4 */
+ { 0x4,0x5,0x6,0x7,0xb,0xa,0x9,0x8,0x3,0x2,0x1,0x0,0xf,0xe,0xd,0xc }, /* Blitz, Blitz99 */
+ { 0x7,0x3,0x2,0x0,0x1,0xc,0xd,0xe,0xf,0x4,0x5,0x6,0x8,0x9,0xa,0xb }, /* Carnevil */
+ { 0x8,0x9,0xa,0xb,0x0,0x1,0x2,0x3,0xf,0xe,0xc,0xd,0x4,0x5,0x6,0x7 }, /* Calspeed, Gauntlet Legends */
+ { 0xf,0xe,0xd,0xc,0x4,0x5,0x6,0x7,0x9,0x8,0xa,0xb,0x2,0x3,0x1,0x0 }, /* Mace */
+ { 0xc,0xd,0xe,0xf,0x0,0x1,0x2,0x3,0x7,0x8,0x9,0xb,0xa,0x5,0x6,0x4 }, /* Gauntlet Dark Legacy */
+ { 0x7,0x4,0x5,0x6,0x2,0x0,0x1,0x3,0x8,0x9,0xa,0xb,0xd,0xc,0xe,0xf }, /* Vapor TRX */
+ { 0x7,0x4,0x5,0x6,0x2,0x0,0x1,0x3,0x8,0x9,0xa,0xb,0xd,0xc,0xe,0xf }, /* San Francisco Rush: The Rock */
+ { 0x1,0x2,0x3,0x0,0x4,0x5,0x6,0x7,0xa,0xb,0x8,0x9,0xc,0xd,0xe,0xf }, /* Hyperdrive */
+ };
+
+ ioasic_register_state();
+
+ /* do we have a DCS2 sound chip connected? (most likely) */
+ ioasic.has_dcs = (mame_find_cpu_index(Machine, "dcs2") != -1 || mame_find_cpu_index(Machine, "dsio") != -1 || mame_find_cpu_index(Machine, "denver") != -1);
+ ioasic.has_cage = (mame_find_cpu_index(Machine, "cage") != -1);
+ ioasic.dcs_cpu = mame_find_cpu_index(Machine, "dcs2");
+ if (ioasic.dcs_cpu == (UINT8)-1)
+ ioasic.dcs_cpu = mame_find_cpu_index(Machine, "dsio");
+ if (ioasic.dcs_cpu == (UINT8)-1)
+ ioasic.dcs_cpu = mame_find_cpu_index(Machine, "denver");
+ ioasic.shuffle_type = shuffle;
+ ioasic.shuffle_map = &shuffle_maps[shuffle][0];
+ ioasic.auto_ack = 0;
+ ioasic.irq_callback = irq_callback;
+
+ /* initialize the PIC */
+ midway_serial_pic2_init(upper, yearoffs);
+
+ /* reset the chip */
+ midway_ioasic_reset();
+ ioasic.reg[IOASIC_SOUNDCTL] = 0x0001;
+
+ /* configure the fifo */
+ if (ioasic.has_dcs)
+ {
+ dcs_set_fifo_callbacks(ioasic_fifo_r, ioasic_fifo_status_r);
+ dcs_set_io_callbacks(ioasic_output_full, ioasic_input_empty);
+ }
+ midway_ioasic_fifo_reset_w(1);
+
+ /* configure the CAGE IRQ */
+ if (ioasic.has_cage)
+ cage_set_irq_handler(cage_irq_handler);
+}
+
+
+void midway_ioasic_set_auto_ack(int auto_ack)
+{
+ ioasic.auto_ack = auto_ack;
+}
+
+
+void midway_ioasic_set_shuffle_state(int state)
+{
+ ioasic.shuffle_active = state;
+}
+
+
+void midway_ioasic_reset(void)
+{
+ ioasic.shuffle_active = 0;
+ ioasic.sound_irq_state = 0x0080;
+ ioasic.reg[IOASIC_INTCTL] = 0;
+ if (ioasic.has_dcs)
+ midway_ioasic_fifo_reset_w(1);
+ update_ioasic_irq();
+ midway_serial_pic_reset_w(1);
+}
+
+
+static void update_ioasic_irq(void)
+{
+ UINT16 fifo_state = ioasic_fifo_status_r();
+ UINT16 irqbits = 0x2000;
+ UINT8 new_state;
+
+ irqbits |= ioasic.sound_irq_state;
+ if (ioasic.reg[IOASIC_UARTIN] & 0x1000)
+ irqbits |= 0x1000;
+ if (fifo_state & 8)
+ irqbits |= 0x0008;
+ if (irqbits)
+ irqbits |= 0x0001;
+
+ ioasic.reg[IOASIC_INTSTAT] = irqbits;
+
+ new_state = ((ioasic.reg[IOASIC_INTCTL] & 0x0001) != 0) && ((ioasic.reg[IOASIC_INTSTAT] & ioasic.reg[IOASIC_INTCTL] & 0x3ffe) != 0);
+ if (new_state != ioasic.irq_state)
+ {
+ ioasic.irq_state = new_state;
+ if (ioasic.irq_callback)
+ (*ioasic.irq_callback)(ioasic.irq_state ? ASSERT_LINE : CLEAR_LINE);
+ }
+}
+
+
+static void cage_irq_handler(int reason)
+{
+ logerror("CAGE irq handler: %d\n", reason);
+ ioasic.sound_irq_state = 0;
+ if (reason & CAGE_IRQ_REASON_DATA_READY)
+ ioasic.sound_irq_state |= 0x0040;
+ if (reason & CAGE_IRQ_REASON_BUFFER_EMPTY)
+ ioasic.sound_irq_state |= 0x0080;
+ update_ioasic_irq();
+}
+
+
+static void ioasic_input_empty(int state)
+{
+// logerror("ioasic_input_empty(%d)\n", state);
+ if (state)
+ ioasic.sound_irq_state |= 0x0080;
+ else
+ ioasic.sound_irq_state &= ~0x0080;
+ update_ioasic_irq();
+}
+
+
+static void ioasic_output_full(int state)
+{
+// logerror("ioasic_output_full(%d)\n", state);
+ if (state)
+ ioasic.sound_irq_state |= 0x0040;
+ else
+ ioasic.sound_irq_state &= ~0x0040;
+ update_ioasic_irq();
+}
+
+
+
+/*************************************
+ *
+ * ASIC sound FIFO; used by CarnEvil
+ *
+ *************************************/
+
+static UINT16 ioasic_fifo_r(void)
+{
+ UINT16 result = 0;
+
+ /* we can only read data if there's some to read! */
+ if (ioasic.fifo_bytes != 0)
+ {
+ /* fetch the data from the buffer and update the IOASIC state */
+ result = ioasic.fifo[ioasic.fifo_out++ % FIFO_SIZE];
+ ioasic.fifo_bytes--;
+ update_ioasic_irq();
+
+ if (LOG_FIFO && (ioasic.fifo_bytes < 4 || ioasic.fifo_bytes >= FIFO_SIZE - 4))
+ logerror("fifo_r(%04X): FIFO bytes = %d!\n", result, ioasic.fifo_bytes);
+
+ /* if we just cleared the buffer, this may generate an IRQ on the master CPU */
+ /* because of the way the streaming code works, we need to make sure that the */
+ /* next status read indicates an empty buffer, even if we've timesliced and the */
+ /* main CPU is handling the I/O ASIC interrupt */
+ if (ioasic.fifo_bytes == 0 && ioasic.has_dcs)
+ {
+ ioasic.fifo_force_buffer_empty_pc = safe_activecpu_get_pc();
+ if (LOG_FIFO)
+ logerror("fifo_r(%04X): FIFO empty, PC = %04X\n", result, ioasic.fifo_force_buffer_empty_pc);
+ }
+ }
+ else
+ {
+ if (LOG_FIFO)
+ logerror("fifo_r(): nothing to read!\n");
+ }
+ return result;
+}
+
+
+static UINT16 ioasic_fifo_status_r(void)
+{
+ UINT16 result = 0;
+
+ if (ioasic.fifo_bytes == 0 && !ioasic.force_fifo_full)
+ result |= 0x08;
+ if (ioasic.fifo_bytes >= FIFO_SIZE/2)
+ result |= 0x10;
+ if (ioasic.fifo_bytes >= FIFO_SIZE || ioasic.force_fifo_full)
+ result |= 0x20;
+
+ /* kludge alert: if we're reading this from the DCS CPU itself, and we recently cleared */
+ /* the FIFO, and we're within 16 instructions of the read that cleared the FIFO, make */
+ /* sure the FIFO clear bit is set */
+ if (ioasic.fifo_force_buffer_empty_pc && cpu_getactivecpu() == ioasic.dcs_cpu)
+ {
+ offs_t currpc = safe_activecpu_get_pc();
+ if (currpc >= ioasic.fifo_force_buffer_empty_pc && currpc < ioasic.fifo_force_buffer_empty_pc + 0x10)
+ {
+ ioasic.fifo_force_buffer_empty_pc = 0;
+ result |= 0x08;
+ if (LOG_FIFO)
+ logerror("ioasic_fifo_status_r(%04X): force empty, PC = %04X\n", result, currpc);
+ }
+ }
+
+ return result;
+}
+
+
+void midway_ioasic_fifo_reset_w(int state)
+{
+ /* on the high state, reset the FIFO data */
+ if (state)
+ {
+ ioasic.fifo_in = 0;
+ ioasic.fifo_out = 0;
+ ioasic.fifo_bytes = 0;
+ ioasic.force_fifo_full = 0;
+ update_ioasic_irq();
+ }
+ if (LOG_FIFO)
+ logerror("%08X:fifo_reset(%d)\n", safe_activecpu_get_pc(), state);
+}
+
+
+void midway_ioasic_fifo_w(UINT16 data)
+{
+ /* if we have room, add it to the FIFO buffer */
+ if (ioasic.fifo_bytes < FIFO_SIZE)
+ {
+ ioasic.fifo[ioasic.fifo_in++ % FIFO_SIZE] = data;
+ ioasic.fifo_bytes++;
+ update_ioasic_irq();
+ if (LOG_FIFO && (ioasic.fifo_bytes < 4 || ioasic.fifo_bytes >= FIFO_SIZE - 4))
+ logerror("fifo_w(%04X): FIFO bytes = %d!\n", data, ioasic.fifo_bytes);
+ }
+ else
+ {
+ if (LOG_FIFO)
+ logerror("fifo_w(%04X): out of space!\n", data);
+ }
+ dcs_fifo_notify(ioasic.fifo_bytes, FIFO_SIZE);
+}
+
+
+void midway_ioasic_fifo_full_w(UINT16 data)
+{
+ if (LOG_FIFO)
+ logerror("fifo_full_w(%04X)\n", data);
+ ioasic.force_fifo_full = 1;
+ update_ioasic_irq();
+ dcs_fifo_notify(ioasic.fifo_bytes, FIFO_SIZE);
+}
+
+
+
+/*************************************
+ *
+ * I/O ASIC master read/write
+ *
+ *************************************/
+
+READ32_HANDLER( midway_ioasic_packed_r )
+{
+ UINT32 result = 0;
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ result |= midway_ioasic_r(offset*2, 0xffff0000) & 0xffff;
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ result |= (midway_ioasic_r(offset*2+1, 0xffff0000) & 0xffff) << 16;
+ return result;
+}
+
+
+READ32_HANDLER( midway_ioasic_r )
+{
+ UINT32 result;
+
+ offset = ioasic.shuffle_active ? ioasic.shuffle_map[offset & 15] : offset;
+ result = ioasic.reg[offset];
+
+ switch (offset)
+ {
+ case IOASIC_PORT0:
+ result = readinputport(0);
+ /* bit 0 seems to be a ready flag before shuffling happens */
+ if (!ioasic.shuffle_active)
+ {
+ result |= 0x0001;
+ /* blitz99 wants bit bits 13-15 to be 1 */
+ result &= ~0xe000;
+ result |= 0x2000;
+ }
+ break;
+
+ case IOASIC_PORT1:
+ result = readinputport(1);
+ break;
+
+ case IOASIC_PORT2:
+ result = readinputport(2);
+ break;
+
+ case IOASIC_PORT3:
+ result = readinputport(3);
+ break;
+
+ case IOASIC_UARTIN:
+ ioasic.reg[offset] &= ~0x1000;
+ break;
+
+ case IOASIC_SOUNDSTAT:
+ /* status from sound CPU */
+ result = 0;
+ if (ioasic.has_dcs)
+ {
+ result |= ((dcs_control_r() >> 4) ^ 0x40) & 0x00c0;
+ result |= ioasic_fifo_status_r() & 0x0038;
+ result |= dcs_data2_r() & 0xff00;
+ }
+ else if (ioasic.has_cage)
+ {
+ result |= (cage_control_r() << 6) ^ 0x80;
+ }
+ else
+ result |= 0x48;
+ break;
+
+ case IOASIC_SOUNDIN:
+ result = 0;
+ if (ioasic.has_dcs)
+ {
+ result = dcs_data_r();
+ if (ioasic.auto_ack)
+ dcs_ack_w();
+ }
+ else if (ioasic.has_cage)
+ result = main_from_cage_r();
+ else
+ {
+ static UINT16 val = 0;
+ result = val = ~val;
+ }
+ break;
+
+ case IOASIC_PICIN:
+ result = midway_serial_pic2_r() | (midway_serial_pic2_status_r() << 8);
+ break;
+
+ default:
+ break;
+ }
+
+ if (LOG_IOASIC && offset != IOASIC_SOUNDSTAT && offset != IOASIC_SOUNDIN)
+ logerror("%06X:ioasic_r(%d) = %08X\n", safe_activecpu_get_pc(), offset, result);
+
+ return result;
+}
+
+
+WRITE32_HANDLER( midway_ioasic_packed_w )
+{
+ if ((mem_mask & 0x0000ffff) != 0x0000ffff)
+ midway_ioasic_w(offset*2, data & 0xffff, 0xffff0000);
+ if ((mem_mask & 0xffff0000) != 0xffff0000)
+ midway_ioasic_w(offset*2+1, data >> 16, 0xffff0000);
+}
+
+
+WRITE32_HANDLER( midway_ioasic_w )
+{
+ UINT32 oldreg, newreg;
+
+ offset = ioasic.shuffle_active ? ioasic.shuffle_map[offset & 15] : offset;
+ oldreg = ioasic.reg[offset];
+ COMBINE_DATA(&ioasic.reg[offset]);
+ newreg = ioasic.reg[offset];
+
+ if (LOG_IOASIC && offset != IOASIC_SOUNDOUT)
+ logerror("%06X:ioasic_w(%d) = %08X\n", safe_activecpu_get_pc(), offset, data);
+
+ switch (offset)
+ {
+ case IOASIC_PORT0:
+ /* the last write here seems to turn on shuffling */
+ if (data == 0xe2)
+ {
+ ioasic.shuffle_active = 1;
+ logerror("*** I/O ASIC shuffling enabled!\n");
+ ioasic.reg[IOASIC_INTCTL] = 0;
+ ioasic.reg[IOASIC_UARTCONTROL] = 0; /* bug in 10th Degree assumes this */
+ }
+ break;
+
+ case IOASIC_PORT2:
+ case IOASIC_PORT3:
+ /* ignore writes here if we're not shuffling yet */
+ if (!ioasic.shuffle_active)
+ break;
+ break;
+
+ case IOASIC_UARTOUT:
+ if (ioasic.reg[IOASIC_UARTCONTROL] & 0x800)
+ {
+ /* we're in loopback mode -- copy to the input */
+ ioasic.reg[IOASIC_UARTIN] = (newreg & 0x00ff) | 0x1000;
+ update_ioasic_irq();
+ }
+ else if (PRINTF_DEBUG)
+ mame_printf_debug("%c", data & 0xff);
+ break;
+
+ case IOASIC_SOUNDCTL:
+ /* sound reset? */
+ if (ioasic.has_dcs)
+ {
+ dcs_reset_w(~newreg & 1);
+ }
+ else if (ioasic.has_cage)
+ {
+ if ((oldreg ^ newreg) & 1)
+ {
+ cage_control_w(0);
+ if (!(~newreg & 1))
+ cage_control_w(3);
+ }
+ }
+
+ /* FIFO reset? */
+ midway_ioasic_fifo_reset_w(~newreg & 4);
+ break;
+
+ case IOASIC_SOUNDOUT:
+ if (ioasic.has_dcs)
+ dcs_data_w(newreg);
+ else if (ioasic.has_cage)
+ main_to_cage_w(newreg);
+ break;
+
+ case IOASIC_SOUNDIN:
+ dcs_ack_w();
+ /* acknowledge data read */
+ break;
+
+ case IOASIC_PICOUT:
+ if (ioasic.shuffle_type == MIDWAY_IOASIC_VAPORTRX)
+ midway_serial_pic2_w(newreg ^ 0x0a);
+ else if (ioasic.shuffle_type == MIDWAY_IOASIC_SFRUSHRK)
+ midway_serial_pic2_w(newreg ^ 0x05);
+ else
+ midway_serial_pic2_w(newreg);
+ break;
+
+ case IOASIC_INTCTL:
+ /* interrupt enables */
+ /* bit 0 = global interrupt enable */
+ /* bit 3 = FIFO empty */
+ /* bit 6 = sound input buffer full */
+ /* bit 7 = sound output buffer empty */
+ /* bit 14 = LED? */
+ if ((oldreg ^ newreg) & 0x3ff6)
+ logerror("IOASIC int control = %04X\n", data);
+ update_ioasic_irq();
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * The IDE ASIC was used on War Gods
+ * and Killer Instinct to map the IDE
+ * registers
+ *
+ *************************************/
+
+READ32_HANDLER( midway_ide_asic_r )
+{
+ /* convert to standard IDE offsets */
+ offs_t ideoffs = 0x1f0/4 + (offset >> 2);
+ UINT8 shift = 8 * (offset & 3);
+ UINT32 result;
+
+ /* offset 0 is a special case */
+ if (offset == 0)
+ result = ide_controller32_0_r(ideoffs, 0xffff0000);
+
+ /* everything else is byte-sized */
+ else
+ result = ide_controller32_0_r(ideoffs, ~(0xff << shift)) >> shift;
+ return result;
+}
+
+
+WRITE32_HANDLER( midway_ide_asic_w )
+{
+ /* convert to standard IDE offsets */
+ offs_t ideoffs = 0x1f0/4 + (offset >> 2);
+ UINT8 shift = 8 * (offset & 3);
+
+ /* offset 0 is a special case */
+ if (offset == 0)
+ ide_controller32_0_w(ideoffs, data, 0xffff0000);
+
+ /* everything else is byte-sized */
+ else
+ ide_controller32_0_w(ideoffs, data << shift, ~(0xff << shift));
+}
diff --git a/src/mame/machine/midwayic.h b/src/mame/machine/midwayic.h
new file mode 100644
index 00000000000..c63c35d8cc0
--- /dev/null
+++ b/src/mame/machine/midwayic.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+
+ Emulation of various Midway ICs
+
+***************************************************************************/
+
+
+/* 1st generation Midway serial PIC */
+void midway_serial_pic_init(int upper);
+void midway_serial_pic_reset_w(int state);
+UINT8 midway_serial_pic_status_r(void);
+UINT8 midway_serial_pic_r(void);
+void midway_serial_pic_w(UINT8 data);
+
+
+/* 2nd generation Midway serial/NVRAM/RTC PIC */
+void midway_serial_pic2_init(int upper, int yearoffs);
+void midway_serial_pic2_set_default_nvram(const UINT8 *nvram);
+UINT8 midway_serial_pic2_status_r(void);
+UINT8 midway_serial_pic2_r(void);
+void midway_serial_pic2_w(UINT8 data);
+NVRAM_HANDLER( midway_serial_pic2 );
+
+
+/* I/O ASIC connected to 2nd generation PIC */
+void midway_ioasic_init(int shuffle, int upper, int yearoffs, void (*irq_callback)(int));
+void midway_ioasic_set_auto_ack(int auto_ack);
+void midway_ioasic_set_shuffle_state(int state);
+void midway_ioasic_reset(void);
+void midway_ioasic_fifo_w(UINT16 data);
+void midway_ioasic_fifo_reset_w(int state);
+void midway_ioasic_fifo_full_w(UINT16 data);
+READ32_HANDLER( midway_ioasic_r );
+WRITE32_HANDLER( midway_ioasic_w );
+READ32_HANDLER( midway_ioasic_packed_r );
+WRITE32_HANDLER( midway_ioasic_packed_w );
+
+enum
+{
+ MIDWAY_IOASIC_STANDARD = 0,
+ MIDWAY_IOASIC_BLITZ99,
+ MIDWAY_IOASIC_CARNEVIL,
+ MIDWAY_IOASIC_CALSPEED,
+ MIDWAY_IOASIC_MACE,
+ MIDWAY_IOASIC_GAUNTDL,
+ MIDWAY_IOASIC_VAPORTRX,
+ MIDWAY_IOASIC_SFRUSHRK,
+ MIDWAY_IOASIC_HYPRDRIV
+};
+
+
+
+/* IDE ASIC maps the IDE registers */
+READ32_HANDLER( midway_ide_asic_r );
+WRITE32_HANDLER( midway_ide_asic_w );
diff --git a/src/mame/machine/midwunit.c b/src/mame/machine/midwunit.c
new file mode 100644
index 00000000000..8bd63b8aa7d
--- /dev/null
+++ b/src/mame/machine/midwunit.c
@@ -0,0 +1,668 @@
+/*************************************************************************
+
+ Driver for Williams/Midway Wolf-unit games.
+
+**************************************************************************/
+
+#include "driver.h"
+#include "cpu/tms34010/tms34010.h"
+#include "cpu/m6809/m6809.h"
+#include "audio/dcs.h"
+#include "midwunit.h"
+#include "midwayic.h"
+
+
+/* code-related variables */
+ UINT8 * midwunit_decode_memory;
+
+/* CMOS-related variables */
+static UINT8 cmos_write_enable;
+
+/* I/O-related variables */
+static UINT16 iodata[8];
+static UINT8 ioshuffle[16];
+static UINT8 midxunit_analog_port;
+
+/* UART-related variables */
+static UINT8 uart[8];
+static UINT8 security_bits;
+
+/* prototype */
+static READ16_HANDLER( midwunit_sound_state_r );
+static void midxunit_dcs_output_full(int state);
+
+
+
+/*************************************
+ *
+ * State saving
+ *
+ *************************************/
+
+static void register_state_saving(void)
+{
+ state_save_register_global(cmos_write_enable);
+ state_save_register_global_array(iodata);
+ state_save_register_global_array(ioshuffle);
+ state_save_register_global(midxunit_analog_port);
+ state_save_register_global_array(uart);
+ state_save_register_global(security_bits);
+}
+
+
+
+/*************************************
+ *
+ * CMOS reads/writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( midwunit_cmos_enable_w )
+{
+ cmos_write_enable = 1;
+}
+
+
+WRITE16_HANDLER( midwunit_cmos_w )
+{
+ if (cmos_write_enable)
+ {
+ COMBINE_DATA(generic_nvram16+offset);
+ cmos_write_enable = 0;
+ }
+ else
+ {
+ logerror("%08X:Unexpected CMOS W @ %05X\n", activecpu_get_pc(), offset);
+ popmessage("Bad CMOS write");
+ }
+}
+
+
+WRITE16_HANDLER( midxunit_cmos_w )
+{
+ COMBINE_DATA(generic_nvram16+offset);
+}
+
+
+READ16_HANDLER( midwunit_cmos_r )
+{
+ return generic_nvram16[offset];
+}
+
+
+
+/*************************************
+ *
+ * General I/O writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( midwunit_io_w )
+{
+ int oldword, newword;
+
+ offset %= 8;
+ oldword = iodata[offset];
+ newword = oldword;
+ COMBINE_DATA(&newword);
+
+ switch (offset)
+ {
+ case 1:
+ logerror("%08X:Control W @ %05X = %04X\n", activecpu_get_pc(), offset, data);
+
+ /* bit 4 reset sound CPU */
+ dcs_reset_w(newword & 0x10);
+
+ /* bit 5 (active low) reset security chip */
+ midway_serial_pic_reset_w(newword & 0x20);
+ break;
+
+ case 3:
+ /* watchdog reset */
+ /* MK3 resets with this enabled */
+/* watchdog_reset_w(0,0);*/
+ break;
+
+ default:
+ logerror("%08X:Unknown I/O write to %d = %04X\n", activecpu_get_pc(), offset, data);
+ break;
+ }
+ iodata[offset] = newword;
+}
+
+
+WRITE16_HANDLER( midxunit_io_w )
+{
+ int oldword, newword;
+
+ offset = (offset / 2) % 8;
+ oldword = iodata[offset];
+ newword = oldword;
+ COMBINE_DATA(&newword);
+
+ switch (offset)
+ {
+ case 2:
+ /* watchdog reset */
+// watchdog_reset_w(0,0);
+ break;
+
+ default:
+ logerror("%08X:I/O write to %d = %04X\n", activecpu_get_pc(), offset, data);
+// logerror("%08X:Unknown I/O write to %d = %04X\n", activecpu_get_pc(), offset, data);
+ break;
+ }
+ iodata[offset] = newword;
+}
+
+
+WRITE16_HANDLER( midxunit_unknown_w )
+{
+ int offs = offset / 0x40000;
+ if (ACCESSING_LSB && offset % 0x40000 == 0)
+ logerror("%08X:midxunit_unknown_w @ %d = %02X\n", activecpu_get_pc(), offs, data & 0xff);
+}
+
+
+/*************************************
+ *
+ * General I/O reads
+ *
+ *************************************/
+
+READ16_HANDLER( midwunit_io_r )
+{
+ /* apply I/O shuffling */
+ offset = ioshuffle[offset % 16];
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ return readinputport(offset);
+
+ case 4:
+ return (midway_serial_pic_status_r() << 12) | midwunit_sound_state_r(0,0);
+
+ default:
+ logerror("%08X:Unknown I/O read from %d\n", activecpu_get_pc(), offset);
+ break;
+ }
+ return ~0;
+}
+
+
+READ16_HANDLER( midxunit_io_r )
+{
+ offset = (offset / 2) % 8;
+
+ switch (offset)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ return readinputport(offset);
+
+ default:
+ logerror("%08X:Unknown I/O read from %d\n", activecpu_get_pc(), offset);
+ break;
+ }
+ return ~0;
+}
+
+
+READ16_HANDLER( midxunit_analog_r )
+{
+ return readinputport(midxunit_analog_port);
+}
+
+
+WRITE16_HANDLER( midxunit_analog_select_w )
+{
+ if (offset == 0 && ACCESSING_LSB)
+ midxunit_analog_port = data - 8 + 4;
+}
+
+
+READ16_HANDLER( midxunit_status_r )
+{
+ /* low bit indicates whether the ADC is done reading the current input */
+ return (midway_serial_pic_status_r() << 1) | 1;
+}
+
+
+
+/*************************************
+ *
+ * Revolution X UART
+ *
+ *************************************/
+
+void midxunit_dcs_output_full(int state)
+{
+ /* only signal if not in loopback state */
+ if (uart[1] != 0x66)
+ cpunum_set_input_line(1, 1, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+READ16_HANDLER( midxunit_uart_r )
+{
+ int result = 0;
+
+ /* convert to a byte offset */
+ if (offset & 1)
+ return 0;
+ offset /= 2;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case 0: /* register 0 must return 0x13 in order to pass the self test */
+ result = 0x13;
+ break;
+
+ case 1: /* register 1 contains the status */
+
+ /* loopback case: data always ready, and always ok to send */
+ if (uart[1] == 0x66)
+ result |= 5;
+
+ /* non-loopback case: bit 0 means data ready, bit 2 means ok to send */
+ else
+ {
+ int temp = midwunit_sound_state_r(0, 0);
+ result |= (temp & 0x800) >> 9;
+ result |= (~temp & 0x400) >> 10;
+ timer_call_after_resynch(0, 0);
+ }
+ break;
+
+ case 3: /* register 3 contains the data read */
+
+ /* loopback case: feed back last data wrtten */
+ if (uart[1] == 0x66)
+ result = uart[3];
+
+ /* non-loopback case: read from the DCS system */
+ else
+ result = midwunit_sound_r(0, 0);
+ break;
+
+ case 5: /* register 5 seems to be like 3, but with in/out swapped */
+
+ /* loopback case: data always ready, and always ok to send */
+ if (uart[1] == 0x66)
+ result |= 5;
+
+ /* non-loopback case: bit 0 means data ready, bit 2 means ok to send */
+ else
+ {
+ int temp = midwunit_sound_state_r(0, 0);
+ result |= (temp & 0x800) >> 11;
+ result |= (~temp & 0x400) >> 8;
+ timer_call_after_resynch(0, 0);
+ }
+ break;
+
+ default: /* everyone else reads themselves */
+ result = uart[offset];
+ break;
+ }
+
+/* logerror("%08X:UART R @ %X = %02X\n", activecpu_get_pc(), offset, result);*/
+ return result;
+}
+
+
+WRITE16_HANDLER( midxunit_uart_w )
+{
+ /* convert to a byte offset, ignoring MSB writes */
+ if ((offset & 1) || !ACCESSING_LSB)
+ return;
+ offset /= 2;
+ data &= 0xff;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case 3: /* register 3 contains the data to be sent */
+
+ /* loopback case: don't feed through */
+ if (uart[1] == 0x66)
+ uart[3] = data;
+
+ /* non-loopback case: send to the DCS system */
+ else
+ midwunit_sound_w(0, data, mem_mask);
+ break;
+
+ case 5: /* register 5 write seems to reset things */
+ dcs_data_r();
+ break;
+
+ default: /* everyone else just stores themselves */
+ uart[offset] = data;
+ break;
+ }
+
+/* logerror("%08X:UART W @ %X = %02X\n", activecpu_get_pc(), offset, data);*/
+}
+
+
+
+/*************************************
+ *
+ * Generic driver init
+ *
+ *************************************/
+
+static void init_wunit_generic(void)
+{
+ UINT8 *base;
+ int i, j;
+
+ /* register for state saving */
+ register_state_saving();
+
+ /* load the graphics ROMs -- quadruples */
+ midyunit_gfx_rom = base = memory_region(REGION_GFX1);
+ for (i = 0; i < memory_region_length(REGION_GFX1) / 0x400000; i++)
+ {
+ memcpy(midwunit_decode_memory, base, 0x400000);
+ for (j = 0; j < 0x100000; j++)
+ {
+ *base++ = midwunit_decode_memory[0x000000 + j];
+ *base++ = midwunit_decode_memory[0x100000 + j];
+ *base++ = midwunit_decode_memory[0x200000 + j];
+ *base++ = midwunit_decode_memory[0x300000 + j];
+ }
+ }
+
+ /* init sound */
+ dcs_init();
+}
+
+
+
+
+/*************************************
+ *
+ * Wolf-unit init (DCS)
+ *
+ * music: ADSP2101
+ *
+ *************************************/
+
+/********************** Mortal Kombat 3 **********************/
+
+static void init_mk3_common(void)
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 439, 528 */
+ midway_serial_pic_init(528);
+}
+
+DRIVER_INIT( mk3 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( mk3r20 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( mk3r10 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( umk3 )
+{
+ init_mk3_common();
+}
+
+DRIVER_INIT( umk3r11 )
+{
+ init_mk3_common();
+}
+
+
+/********************** 2 On 2 Open Ice Challenge **********************/
+
+DRIVER_INIT( openice )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 438, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** NBA Hangtime & NBA Maximum Hangtime **********************/
+
+DRIVER_INIT( nbahangt )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 459, 470, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** WWF Wrestlemania **********************/
+
+static WRITE16_HANDLER( wwfmania_io_0_w )
+{
+ int i;
+
+ /* start with the originals */
+ for (i = 0; i < 16; i++)
+ ioshuffle[i] = i % 8;
+
+ /* based on the data written, shuffle */
+ switch (data)
+ {
+ case 0:
+ break;
+
+ case 1:
+ ioshuffle[4] = 0;
+ ioshuffle[8] = 1;
+ ioshuffle[1] = 2;
+ ioshuffle[9] = 3;
+ ioshuffle[2] = 4;
+ break;
+
+ case 2:
+ ioshuffle[8] = 0;
+ ioshuffle[2] = 1;
+ ioshuffle[4] = 2;
+ ioshuffle[6] = 3;
+ ioshuffle[1] = 4;
+ break;
+
+ case 3:
+ ioshuffle[1] = 0;
+ ioshuffle[8] = 1;
+ ioshuffle[2] = 2;
+ ioshuffle[10] = 3;
+ ioshuffle[5] = 4;
+ break;
+
+ case 4:
+ ioshuffle[2] = 0;
+ ioshuffle[4] = 1;
+ ioshuffle[1] = 2;
+ ioshuffle[7] = 3;
+ ioshuffle[8] = 4;
+ break;
+ }
+ logerror("Changed I/O swiching to %d\n", data);
+}
+
+DRIVER_INIT( wwfmania )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* enable I/O shuffling */
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01800000, 0x0180000f, 0, 0, wwfmania_io_0_w);
+
+ /* serial prefixes 430, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** Rampage World Tour **********************/
+
+DRIVER_INIT( rmpgwt )
+{
+ /* common init */
+ init_wunit_generic();
+
+ /* serial prefixes 465, 528 */
+ midway_serial_pic_init(528);
+}
+
+
+/********************** Revolution X **********************/
+
+DRIVER_INIT( revx )
+{
+ UINT8 *base;
+ int i, j;
+
+ /* register for state saving */
+ register_state_saving();
+
+ /* load the graphics ROMs -- quadruples */
+ midyunit_gfx_rom = base = memory_region(REGION_GFX1);
+ for (i = 0; i < memory_region_length(REGION_GFX1) / 0x200000; i++)
+ {
+ memcpy(midwunit_decode_memory, base, 0x200000);
+ for (j = 0; j < 0x80000; j++)
+ {
+ *base++ = midwunit_decode_memory[0x000000 + j];
+ *base++ = midwunit_decode_memory[0x080000 + j];
+ *base++ = midwunit_decode_memory[0x100000 + j];
+ *base++ = midwunit_decode_memory[0x180000 + j];
+ }
+ }
+
+ /* init sound */
+ dcs_init();
+
+ /* serial prefixes 419, 420 */
+ midway_serial_pic_init(419);
+}
+
+
+
+/*************************************
+ *
+ * Machine init
+ *
+ *************************************/
+
+MACHINE_RESET( midwunit )
+{
+ int i;
+
+ /* reset sound */
+ dcs_reset_w(1);
+ dcs_reset_w(0);
+
+ /* reset I/O shuffling */
+ for (i = 0; i < 16; i++)
+ ioshuffle[i] = i % 8;
+}
+
+
+MACHINE_RESET( midxunit )
+{
+ machine_reset_midwunit(machine);
+ dcs_set_io_callbacks(midxunit_dcs_output_full, NULL);
+}
+
+
+
+/*************************************
+ *
+ * Security chip I/O
+ *
+ *************************************/
+
+READ16_HANDLER( midwunit_security_r )
+{
+ return midway_serial_pic_r();
+}
+
+
+WRITE16_HANDLER( midwunit_security_w )
+{
+ if (offset == 0 && ACCESSING_LSB)
+ midway_serial_pic_w(data);
+}
+
+
+WRITE16_HANDLER( midxunit_security_w )
+{
+ if (ACCESSING_LSB)
+ security_bits = data & 0x0f;
+}
+
+
+WRITE16_HANDLER( midxunit_security_clock_w )
+{
+ if (offset == 0 && ACCESSING_LSB)
+ midway_serial_pic_w(((~data & 2) << 3) | security_bits);
+}
+
+
+
+/*************************************
+ *
+ * Sound write handlers
+ *
+ *************************************/
+
+READ16_HANDLER( midwunit_sound_r )
+{
+ logerror("%08X:Sound read\n", activecpu_get_pc());
+
+ return dcs_data_r() & 0xff;
+}
+
+
+READ16_HANDLER( midwunit_sound_state_r )
+{
+ return dcs_control_r();
+}
+
+
+WRITE16_HANDLER( midwunit_sound_w )
+{
+ /* check for out-of-bounds accesses */
+ if (offset)
+ {
+ logerror("%08X:Unexpected write to sound (hi) = %04X\n", activecpu_get_pc(), data);
+ return;
+ }
+
+ /* call through based on the sound type */
+ if (ACCESSING_LSB)
+ {
+ logerror("%08X:Sound write = %04X\n", activecpu_get_pc(), data);
+ dcs_data_w(data & 0xff);
+ }
+}
diff --git a/src/mame/machine/midyunit.c b/src/mame/machine/midyunit.c
new file mode 100644
index 00000000000..868fa40b56e
--- /dev/null
+++ b/src/mame/machine/midyunit.c
@@ -0,0 +1,578 @@
+/*************************************************************************
+
+ Williams/Midway Y/Z-unit system
+
+**************************************************************************/
+
+#include "driver.h"
+#include "cpu/tms34010/tms34010.h"
+#include "cpu/m6809/m6809.h"
+#include "machine/6821pia.h"
+#include "audio/williams.h"
+#include "midyunit.h"
+
+
+/* constant definitions */
+#define SOUND_NARC 1
+#define SOUND_CVSD_SMALL 2
+#define SOUND_CVSD 3
+#define SOUND_ADPCM 4
+#define SOUND_YAWDIM 5
+
+
+/* protection data types */
+struct protection_data
+{
+ UINT16 reset_sequence[3];
+ UINT16 data_sequence[100];
+};
+static const struct protection_data *prot_data;
+static UINT16 prot_result;
+static UINT16 prot_sequence[3];
+static UINT8 prot_index;
+
+
+/* input-related variables */
+static UINT8 term2_analog_select;
+
+/* CMOS-related variables */
+ UINT16 *midyunit_cmos_ram;
+ UINT32 midyunit_cmos_page;
+static UINT8 cmos_w_enable;
+
+/* sound-related variables */
+static UINT8 chip_type;
+
+/* hack-related variables */
+static UINT16 *t2_hack_mem;
+
+
+
+/*************************************
+ *
+ * CMOS reads/writes
+ *
+ *************************************/
+
+WRITE16_HANDLER( midyunit_cmos_w )
+{
+ logerror("%08x:CMOS Write @ %05X\n", activecpu_get_pc(), offset);
+ COMBINE_DATA(&midyunit_cmos_ram[offset + midyunit_cmos_page]);
+}
+
+
+READ16_HANDLER( midyunit_cmos_r )
+{
+ return midyunit_cmos_ram[offset + midyunit_cmos_page];
+}
+
+
+
+/*************************************
+ *
+ * CMOS enable and protection
+ *
+ *************************************/
+
+WRITE16_HANDLER( midyunit_cmos_enable_w )
+{
+ cmos_w_enable = (~data >> 9) & 1;
+
+ logerror("%08x:Protection write = %04X\n", activecpu_get_pc(), data);
+
+ /* only go down this path if we have a data structure */
+ if (prot_data)
+ {
+ /* mask off the data */
+ data &= 0x0f00;
+
+ /* update the FIFO */
+ prot_sequence[0] = prot_sequence[1];
+ prot_sequence[1] = prot_sequence[2];
+ prot_sequence[2] = data;
+
+ /* special case: sequence entry 1234 means Strike Force, which is different */
+ if (prot_data->reset_sequence[0] == 0x1234)
+ {
+ if (data == 0x500)
+ {
+ prot_result = program_read_word(TOBYTE(0x10a4390)) << 4;
+ logerror(" desired result = %04X\n", prot_result);
+ }
+ }
+
+ /* all other games use the same pattern */
+ else
+ {
+ /* look for a reset */
+ if (prot_sequence[0] == prot_data->reset_sequence[0] &&
+ prot_sequence[1] == prot_data->reset_sequence[1] &&
+ prot_sequence[2] == prot_data->reset_sequence[2])
+ {
+ logerror("Protection reset\n");
+ prot_index = 0;
+ }
+
+ /* look for a clock */
+ if ((prot_sequence[1] & 0x0800) != 0 && (prot_sequence[2] & 0x0800) == 0)
+ {
+ prot_result = prot_data->data_sequence[prot_index++];
+ logerror("Protection clock (new data = %04X)\n", prot_result);
+ }
+ }
+ }
+}
+
+
+READ16_HANDLER( midyunit_protection_r )
+{
+ /* return the most recently clocked value */
+ logerror("%08X:Protection read = %04X\n", activecpu_get_pc(), prot_result);
+ return prot_result;
+}
+
+
+
+/*************************************
+ *
+ * Generic input ports
+ *
+ *************************************/
+
+READ16_HANDLER( midyunit_input_r )
+{
+ return readinputport(offset);
+}
+
+
+
+/*************************************
+ *
+ * Special Terminator 2 input ports
+ *
+ *************************************/
+
+static READ16_HANDLER( term2_input_r )
+{
+ if (offset != 2)
+ return readinputport(offset);
+
+ switch (term2_analog_select)
+ {
+ default:
+ case 0: return readinputport(2); break;
+ case 1: return readinputport(6); break;
+ case 2: return readinputport(7); break;
+ case 3: return readinputport(8); break;
+ }
+}
+
+static WRITE16_HANDLER( term2_sound_w )
+{
+ if (offset == 0)
+ term2_analog_select = (data >> 0x0c) & 0x03;
+
+ williams_adpcm_data_w(data);
+}
+
+
+
+/*************************************
+ *
+ * Special Terminator 2 hack
+ *
+ *************************************/
+
+static WRITE16_HANDLER( term2_hack_w )
+{
+ if (offset == 0 && activecpu_get_pc() == 0xffce5230)
+ {
+ t2_hack_mem[offset] = 0;
+ return;
+ }
+ COMBINE_DATA(&t2_hack_mem[offset]);
+}
+
+static WRITE16_HANDLER( term2la2_hack_w )
+{
+ if (offset == 0 && activecpu_get_pc() == 0xffce4b80)
+ {
+ t2_hack_mem[offset] = 0;
+ return;
+ }
+ COMBINE_DATA(&t2_hack_mem[offset]);
+}
+
+static WRITE16_HANDLER( term2la1_hack_w )
+{
+ if (offset == 0 && activecpu_get_pc() == 0xffce33f0)
+ {
+ t2_hack_mem[offset] = 0;
+ return;
+ }
+ COMBINE_DATA(&t2_hack_mem[offset]);
+}
+
+
+
+/*************************************
+ *
+ * Generic driver init
+ *
+ *************************************/
+
+static UINT8 *cvsd_protection_base;
+static WRITE8_HANDLER( cvsd_protection_w )
+{
+ /* because the entire CVSD ROM is banked, we have to make sure that writes */
+ /* go to the proper location (i.e., bank 0); currently bank 0 always lives */
+ /* in the 0x10000-0x17fff space, so we just need to add 0x8000 to get the */
+ /* proper offset */
+ cvsd_protection_base[offset] = data;
+}
+
+
+static void init_generic(int bpp, int sound, int prot_start, int prot_end)
+{
+ offs_t gfx_chunk = midyunit_gfx_rom_size / 4;
+ UINT8 d1, d2, d3, d4, d5, d6;
+ UINT8 *base;
+ int i;
+
+ /* load graphics ROMs */
+ base = memory_region(REGION_GFX1);
+ switch (bpp)
+ {
+ case 4:
+ for (i = 0; i < midyunit_gfx_rom_size; i += 2)
+ {
+ d1 = ((base[0 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d2 = ((base[1 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d3 = ((base[0 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+ d4 = ((base[1 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+
+ midyunit_gfx_rom[i + 0] = d1 | (d2 << 2);
+ midyunit_gfx_rom[i + 1] = d3 | (d4 << 2);
+ }
+ break;
+
+ case 6:
+ for (i = 0; i < midyunit_gfx_rom_size; i += 2)
+ {
+ d1 = ((base[0 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d2 = ((base[1 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d3 = ((base[2 * gfx_chunk + (i + 0) / 4]) >> (2 * ((i + 0) % 4))) & 3;
+ d4 = ((base[0 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+ d5 = ((base[1 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+ d6 = ((base[2 * gfx_chunk + (i + 1) / 4]) >> (2 * ((i + 1) % 4))) & 3;
+
+ midyunit_gfx_rom[i + 0] = d1 | (d2 << 2) | (d3 << 4);
+ midyunit_gfx_rom[i + 1] = d4 | (d5 << 2) | (d6 << 4);
+ }
+ break;
+
+ case 8:
+ for (i = 0; i < midyunit_gfx_rom_size; i += 4)
+ {
+ midyunit_gfx_rom[i + 0] = base[0 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 1] = base[1 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 2] = base[2 * gfx_chunk + i / 4];
+ midyunit_gfx_rom[i + 3] = base[3 * gfx_chunk + i / 4];
+ }
+ break;
+ }
+
+ /* load sound ROMs and set up sound handlers */
+ chip_type = sound;
+ switch (sound)
+ {
+ case SOUND_CVSD_SMALL:
+ williams_cvsd_init(0);
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, cvsd_protection_w);
+ cvsd_protection_base = memory_region(REGION_CPU2) + 0x10000 + (prot_start - 0x8000);
+ break;
+
+ case SOUND_CVSD:
+ williams_cvsd_init(0);
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, MWA8_RAM);
+ break;
+
+ case SOUND_ADPCM:
+ williams_adpcm_init();
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, MWA8_RAM);
+ break;
+
+ case SOUND_NARC:
+ williams_narc_init();
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, prot_start, prot_end, 0, 0, MWA8_RAM);
+ break;
+
+ case SOUND_YAWDIM:
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Z-unit init
+ *
+ * music: 6809 driving YM2151, DAC
+ * effects: 6809 driving CVSD, DAC
+ *
+ *************************************/
+
+DRIVER_INIT( narc )
+{
+ /* common init */
+ init_generic(8, SOUND_NARC, 0xcdff, 0xce29);
+}
+
+
+/*************************************
+ *
+ * Y-unit init (CVSD)
+ *
+ * music: 6809 driving YM2151, DAC, and CVSD
+ *
+ *************************************/
+
+
+/********************** Trog **************************/
+
+DRIVER_INIT( trog )
+{
+ /* protection */
+ static const struct protection_data trog_protection_data =
+ {
+ { 0x0f00, 0x0f00, 0x0f00 },
+ { 0x3000, 0x1000, 0x2000, 0x0000,
+ 0x2000, 0x3000,
+ 0x3000, 0x1000,
+ 0x0000, 0x0000, 0x2000, 0x3000, 0x1000, 0x1000, 0x2000 }
+ };
+ prot_data = &trog_protection_data;
+
+ /* common init */
+ init_generic(4, SOUND_CVSD_SMALL, 0x9eaf, 0x9ed9);
+}
+
+
+/********************** Smash TV **********************/
+
+DRIVER_INIT( smashtv )
+{
+ /* common init */
+ init_generic(6, SOUND_CVSD_SMALL, 0x9cf6, 0x9d21);
+}
+
+
+/********************** High Impact Football **********************/
+
+DRIVER_INIT( hiimpact )
+{
+ /* protection */
+ static const struct protection_data hiimpact_protection_data =
+ {
+ { 0x0b00, 0x0b00, 0x0b00 },
+ { 0x2000, 0x4000, 0x4000, 0x0000, 0x6000, 0x6000, 0x2000, 0x4000,
+ 0x2000, 0x4000, 0x2000, 0x0000, 0x4000, 0x6000, 0x2000 }
+ };
+ prot_data = &hiimpact_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_CVSD, 0x9b79, 0x9ba3);
+}
+
+
+/********************** Super High Impact Football **********************/
+
+DRIVER_INIT( shimpact )
+{
+ /* protection */
+ static const struct protection_data shimpact_protection_data =
+ {
+ { 0x0f00, 0x0e00, 0x0d00 },
+ { 0x0000, 0x4000, 0x2000, 0x5000, 0x2000, 0x1000, 0x4000, 0x6000,
+ 0x3000, 0x0000, 0x2000, 0x5000, 0x5000, 0x5000, 0x2000 }
+ };
+ prot_data = &shimpact_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_CVSD, 0x9c06, 0x9c15);
+}
+
+
+/********************** Strike Force **********************/
+
+DRIVER_INIT( strkforc )
+{
+ /* protection */
+ static const struct protection_data strkforc_protection_data =
+ {
+ { 0x1234 }
+ };
+ prot_data = &strkforc_protection_data;
+
+ /* common init */
+ init_generic(4, SOUND_CVSD_SMALL, 0x9f7d, 0x9fa7);
+}
+
+
+
+/*************************************
+ *
+ * Y-unit init (ADPCM)
+ *
+ * music: 6809 driving YM2151, DAC, and OKIM6295
+ *
+ *************************************/
+
+
+/********************** Mortal Kombat **********************/
+
+DRIVER_INIT( mkyunit )
+{
+ /* protection */
+ static const struct protection_data mk_protection_data =
+ {
+ { 0x0d00, 0x0c00, 0x0900 },
+ { 0x4600, 0xf600, 0xa600, 0x0600, 0x2600, 0x9600, 0xc600, 0xe600,
+ 0x8600, 0x7600, 0x8600, 0x8600, 0x9600, 0xd600, 0x6600, 0xb600,
+ 0xd600, 0xe600, 0xf600, 0x7600, 0xb600, 0xa600, 0x3600 }
+ };
+ prot_data = &mk_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_ADPCM, 0xfb9c, 0xfbc6);
+}
+
+DRIVER_INIT( mkyawdim )
+{
+ /* common init */
+ init_generic(6, SOUND_YAWDIM, 0, 0);
+}
+
+
+/********************** Terminator 2 **********************/
+
+static void term2_init_common(write16_handler hack_w)
+{
+ /* protection */
+ static const struct protection_data term2_protection_data =
+ {
+ { 0x0f00, 0x0f00, 0x0f00 },
+ { 0x4000, 0xf000, 0xa000 }
+ };
+ prot_data = &term2_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_ADPCM, 0xfa8d, 0xfa9c);
+
+ /* special inputs */
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01c00000, 0x01c0005f, 0, 0, term2_input_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x01e00000, 0x01e0001f, 0, 0, term2_sound_w);
+
+ /* HACK: this prevents the freeze on the movies */
+ /* until we figure whats causing it, this is better than nothing */
+ t2_hack_mem = memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x010aa0e0, 0x010aa0ff, 0, 0, hack_w);
+}
+
+DRIVER_INIT( term2 ) { term2_init_common(term2_hack_w); }
+DRIVER_INIT( term2la2 ) { term2_init_common(term2la2_hack_w); }
+DRIVER_INIT( term2la1 ) { term2_init_common(term2la1_hack_w); }
+
+
+
+/********************** Total Carnage **********************/
+
+DRIVER_INIT( totcarn )
+{
+ /* protection */
+ static const struct protection_data totcarn_protection_data =
+ {
+ { 0x0f00, 0x0f00, 0x0f00 },
+ { 0x4a00, 0x6a00, 0xda00, 0x6a00, 0x9a00, 0x4a00, 0x2a00, 0x9a00, 0x1a00,
+ 0x8a00, 0xaa00 }
+ };
+ prot_data = &totcarn_protection_data;
+
+ /* common init */
+ init_generic(6, SOUND_ADPCM, 0xfc04, 0xfc2e);
+}
+
+
+
+/*************************************
+ *
+ * Machine init
+ *
+ *************************************/
+
+MACHINE_RESET( midyunit )
+{
+ /* reset sound */
+ switch (chip_type)
+ {
+ case SOUND_NARC:
+ williams_narc_reset_w(1);
+ williams_narc_reset_w(0);
+ break;
+
+ case SOUND_CVSD:
+ case SOUND_CVSD_SMALL:
+ williams_cvsd_reset_w(1);
+ williams_cvsd_reset_w(0);
+ break;
+
+ case SOUND_ADPCM:
+ williams_adpcm_reset_w(1);
+ williams_adpcm_reset_w(0);
+ break;
+
+ case SOUND_YAWDIM:
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Sound write handlers
+ *
+ *************************************/
+
+WRITE16_HANDLER( midyunit_sound_w )
+{
+ /* check for out-of-bounds accesses */
+ if (offset)
+ {
+ logerror("%08X:Unexpected write to sound (hi) = %04X\n", activecpu_get_pc(), data);
+ return;
+ }
+
+ /* call through based on the sound type */
+ if (ACCESSING_LSB && ACCESSING_MSB)
+ switch (chip_type)
+ {
+ case SOUND_NARC:
+ williams_narc_data_w(data);
+ break;
+
+ case SOUND_CVSD_SMALL:
+ case SOUND_CVSD:
+ williams_cvsd_data_w((data & 0xff) | ((data & 0x200) >> 1));
+ break;
+
+ case SOUND_ADPCM:
+ williams_adpcm_data_w(data);
+ break;
+
+ case SOUND_YAWDIM:
+ soundlatch_w(0, data);
+ cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
+ break;
+ }
+}
diff --git a/src/mame/machine/model1.c b/src/mame/machine/model1.c
new file mode 100644
index 00000000000..7f44eab0908
--- /dev/null
+++ b/src/mame/machine/model1.c
@@ -0,0 +1,2171 @@
+/*
+** Model 1 coprocessor TGP simulation
+*/
+
+#include "driver.h"
+#include "debugger.h"
+#include <math.h>
+#include "cpu/mb86233/mb86233.h"
+
+enum {FIFO_SIZE = 256};
+enum {MAT_STACK_SIZE = 32};
+
+int model1_dump;
+
+static int fifoin_rpos, fifoin_wpos;
+static UINT32 fifoin_data[FIFO_SIZE];
+static int model1_swa;
+
+static int fifoin_cbcount;
+static void (*fifoin_cb)(void);
+
+static INT32 fifoout_rpos, fifoout_wpos;
+static UINT32 fifoout_data[FIFO_SIZE];
+
+static UINT32 list_length;
+
+static float cmat[12], mat_stack[MAT_STACK_SIZE][12], mat_vector[21][12];
+static INT32 mat_stack_pos;
+static float acc;
+
+static float tgp_vf_xmin, tgp_vf_xmax, tgp_vf_zmin, tgp_vf_zmax, tgp_vf_ygnd, tgp_vf_yflr, tgp_vf_yjmp;
+static float tgp_vr_circx, tgp_vr_circy, tgp_vr_circrad, tgp_vr_cbox[12];
+static int tgp_vr_select;
+static UINT16 ram_adr, ram_latch[2], ram_scanadr;
+static UINT32 *ram_data;
+static float tgp_vr_base[4];
+
+static UINT32 fifoout_pop(void)
+{
+ UINT32 v;
+ if(fifoout_wpos == fifoout_rpos) {
+ fatalerror("TGP FIFOOUT underflow (%x)", activecpu_get_pc());
+ }
+ v = fifoout_data[fifoout_rpos++];
+ if(fifoout_rpos == FIFO_SIZE)
+ fifoout_rpos = 0;
+ return v;
+}
+
+static int puuu = 0;
+
+static void fifoout_push(UINT32 data)
+{
+ if(!puuu)
+ logerror("TGP: Push %d\n", data);
+ else
+ puuu = 0;
+ fifoout_data[fifoout_wpos++] = data;
+ if(fifoout_wpos == FIFO_SIZE)
+ fifoout_wpos = 0;
+ if(fifoout_wpos == fifoout_rpos)
+ logerror("TGP FIFOOUT overflow\n");
+}
+
+static void fifoout_push_f(float data)
+{
+ puuu = 1;
+
+ logerror("TGP: Push %f\n", data);
+ fifoout_push(f2u(data));
+}
+
+static UINT32 fifoin_pop(void)
+{
+ UINT32 v;
+ if(fifoin_wpos == fifoin_rpos)
+ logerror("TGP FIFOIN underflow\n");
+ v = fifoin_data[fifoin_rpos++];
+ if(fifoin_rpos == FIFO_SIZE)
+ fifoin_rpos = 0;
+ return v;
+}
+
+static void fifoin_push(UINT32 data)
+{
+ // logerror("TGP FIFOIN write %08x (%x)\n", data, activecpu_get_pc());
+ fifoin_data[fifoin_wpos++] = data;
+ if(fifoin_wpos == FIFO_SIZE)
+ fifoin_wpos = 0;
+ if(fifoin_wpos == fifoin_rpos)
+ logerror("TGP FIFOIN overflow\n");
+ fifoin_cbcount--;
+ if(!fifoin_cbcount)
+ fifoin_cb();
+}
+
+static float fifoin_pop_f(void)
+{
+ return u2f(fifoin_pop());
+}
+
+static void function_get_vf(void);
+static void function_get_swa(void);
+
+static void next_fn(void)
+{
+ fifoin_cbcount = 1;
+ fifoin_cb = model1_swa ? function_get_swa : function_get_vf;
+}
+
+static float tcos(INT16 a)
+{
+ if(a == 16384 || a == -16384)
+ return 0;
+ else if(a == -32768)
+ return -1;
+ else if(a == 0)
+ return 1;
+ else
+ return cos(a*(2*M_PI/65536.0));
+}
+
+static float tsin(INT16 a)
+{
+ if(a == 0 || a == -32768)
+ return 0;
+ else if(a == 16384)
+ return 1;
+ else if(a == -16384)
+ return -1;
+ else
+ return sin(a*(2*M_PI/65536.0));
+}
+
+static UINT16 ram_get_i(void)
+{
+ return ram_data[ram_scanadr++];
+}
+
+static float ram_get_f(void)
+{
+ return u2f(ram_data[ram_scanadr++]);
+}
+
+static void fadd(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float r = a+b;
+ logerror("TGP fadd %f+%f=%f (%x)\n", a, b, r, activecpu_get_pc());
+ fifoout_push_f(r);
+ next_fn();
+}
+
+static void fsub(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float r = a-b;
+ model1_dump = 1;
+ logerror("TGP fsub %f-%f=%f (%x)\n", a, b, r, activecpu_get_pc());
+ fifoout_push_f(r);
+ next_fn();
+}
+
+static void fmul(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float r = a*b;
+ logerror("TGP fmul %f*%f=%f (%x)\n", a, b, r, activecpu_get_pc());
+ fifoout_push_f(r);
+ next_fn();
+}
+
+static void fdiv(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+// float r = !b ? 1e39 : a/b;
+ float r = !b ? 0 : a * (1/b);
+ logerror("TGP fdiv %f/%f=%f (%x)\n", a, b, r, activecpu_get_pc());
+ fifoout_push_f(r);
+ next_fn();
+}
+
+static void matrix_push(void)
+{
+ if(mat_stack_pos != MAT_STACK_SIZE) {
+ memcpy(mat_stack[mat_stack_pos], cmat, sizeof(cmat));
+ mat_stack_pos++;
+ }
+ logerror("TGP matrix_push (depth=%d, pc=%x)\n", mat_stack_pos, activecpu_get_pc());
+ next_fn();
+}
+
+static void matrix_pop(void)
+{
+ if(mat_stack_pos) {
+ mat_stack_pos--;
+ memcpy(cmat, mat_stack[mat_stack_pos], sizeof(cmat));
+ }
+ logerror("TGP matrix_pop (depth=%d, pc=%x)\n", mat_stack_pos, activecpu_get_pc());
+ next_fn();
+}
+
+static void matrix_write(void)
+{
+ int i;
+ for(i=0; i<12; i++)
+ cmat[i] = fifoin_pop_f();
+ logerror("TGP matrix_write %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f) (%x)\n",
+ cmat[0], cmat[1], cmat[2], cmat[3], cmat[4], cmat[5], cmat[6], cmat[7], cmat[8], cmat[9], cmat[10], cmat[11],
+ activecpu_get_pc());
+ next_fn();
+}
+
+static void clear_stack(void)
+{
+ logerror("TGP clear_stack (%x)\n", activecpu_get_pc());
+ mat_stack_pos = 0;
+ next_fn();
+}
+
+static void matrix_mul(void)
+{
+ float m[12];
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ float g = fifoin_pop_f();
+ float h = fifoin_pop_f();
+ float i = fifoin_pop_f();
+ float j = fifoin_pop_f();
+ float k = fifoin_pop_f();
+ float l = fifoin_pop_f();
+ logerror("TGP matrix_mul %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, g, h, i, j, k, l, activecpu_get_pc());
+ m[0] = a*cmat[0] + b*cmat[3] + c*cmat[6];
+ m[1] = a*cmat[1] + b*cmat[4] + c*cmat[7];
+ m[2] = a*cmat[2] + b*cmat[5] + c*cmat[8];
+ m[3] = d*cmat[0] + e*cmat[3] + f*cmat[6];
+ m[4] = d*cmat[1] + e*cmat[4] + f*cmat[7];
+ m[5] = d*cmat[2] + e*cmat[5] + f*cmat[8];
+ m[6] = g*cmat[0] + h*cmat[3] + i*cmat[6];
+ m[7] = g*cmat[1] + h*cmat[4] + i*cmat[7];
+ m[8] = g*cmat[2] + h*cmat[5] + i*cmat[8];
+ m[9] = j*cmat[0] + k*cmat[3] + l*cmat[6] + cmat[9];
+ m[10] = j*cmat[1] + k*cmat[4] + l*cmat[7] + cmat[10];
+ m[11] = j*cmat[2] + k*cmat[5] + l*cmat[8] + cmat[11];
+
+ memcpy(cmat, m, sizeof(m));
+ next_fn();
+}
+
+static void anglev(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ logerror("TGP anglev %f, %f (%x)\n", a, b, activecpu_get_pc());
+ if(!b) {
+ if(a>=0)
+ fifoout_push(0);
+ else
+ fifoout_push(-32768);
+ } else if(!a) {
+ if(b>=0)
+ fifoout_push(16384);
+ else
+ fifoout_push(-16384);
+ } else
+ fifoout_push((INT16)(atan2(b, a)*32768/M_PI));
+ next_fn();
+}
+
+static void f11(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ float g = fifoin_pop_f();
+ float h = fifoin_pop_f();
+ float i = fifoin_pop_f();
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ (void)e;
+ (void)f;
+ (void)g;
+ (void)h;
+ (void)i;
+ logerror("TGP f11 %f, %f, %f, %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, g, h, i, activecpu_get_pc());
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void normalize(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float n = (a*a+b*b+c*c) / sqrt(a*a+b*b+c*c);
+ logerror("TGP normalize %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+ fifoout_push_f(a/n);
+ fifoout_push_f(b/n);
+ fifoout_push_f(c/n);
+ next_fn();
+}
+
+static void acc_seti(void)
+{
+ INT32 a = fifoin_pop();
+ model1_dump = 1;
+ logerror("TGP acc_seti %d (%x)\n", a, activecpu_get_pc());
+ acc = a;
+ next_fn();
+}
+
+static void track_select(void)
+{
+ INT32 a = fifoin_pop();
+ logerror("TGP track_select %d (%x)\n", a, activecpu_get_pc());
+ tgp_vr_select = a;
+ next_fn();
+}
+
+static void f14(void)
+{
+ tgp_vr_base[0] = fifoin_pop_f();
+ tgp_vr_base[1] = fifoin_pop_f();
+ tgp_vr_base[2] = fifoin_pop_f();
+ tgp_vr_base[3] = fifoin_pop_f();
+
+ next_fn();
+}
+
+static void f15_swa(void)
+{
+ logerror("TGP f15_swa (%x)\n", activecpu_get_pc());
+
+ next_fn();
+}
+
+static void anglep(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ logerror("TGP anglep %f, %f, %f, %f (%x)\n", a, b, c, d, activecpu_get_pc());
+ c = a - c;
+ d = b - d;
+ if(!d) {
+ if(c>=0)
+ fifoout_push(0);
+ else
+ fifoout_push(-32768);
+ } else if(!c) {
+ if(d>=0)
+ fifoout_push(16384);
+ else
+ fifoout_push(-16384);
+ } else
+ fifoout_push((INT16)(atan2(d, c)*32768/M_PI));
+ next_fn();
+}
+
+static void matrix_ident(void)
+{
+ logerror("TGP matrix_ident (%x)\n", activecpu_get_pc());
+ memset(cmat, 0, sizeof(cmat));
+ cmat[0] = 1.0;
+ cmat[4] = 1.0;
+ cmat[8] = 1.0;
+ next_fn();
+}
+
+static void matrix_read(void)
+{
+ int i;
+ logerror("TGP matrix_read (%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f) (%x)\n",
+ cmat[0], cmat[1], cmat[2], cmat[3], cmat[4], cmat[5], cmat[6], cmat[7], cmat[8], cmat[9], cmat[10], cmat[11], activecpu_get_pc());
+ for(i=0; i<12; i++)
+ fifoout_push_f(cmat[i]);
+ next_fn();
+}
+
+static void matrix_trans(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+
+ cmat[ 9] += cmat[0]*a+cmat[3]*b+cmat[6]*c;
+ cmat[10] += cmat[1]*a+cmat[4]*b+cmat[7]*c;
+ cmat[11] += cmat[2]*a+cmat[5]*b+cmat[8]*c;
+ next_fn();
+}
+
+static void matrix_scale(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ logerror("TGP matrix_scale %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+ cmat[0] *= a;
+ cmat[1] *= a;
+ cmat[2] *= a;
+ cmat[3] *= b;
+ cmat[4] *= b;
+ cmat[5] *= b;
+ cmat[6] *= c;
+ cmat[7] *= c;
+ cmat[8] *= c;
+ next_fn();
+}
+
+static void matrix_rotx(void)
+{
+ INT16 a = fifoin_pop();
+ float s = tsin(a);
+ float c = tcos(a);
+ float t1, t2;
+ logerror("TGP matrix_rotx %d (%x)\n", a, activecpu_get_pc());
+ t1 = cmat[3];
+ t2 = cmat[6];
+ cmat[3] = c*t1-s*t2;
+ cmat[6] = s*t1+c*t2;
+ t1 = cmat[4];
+ t2 = cmat[7];
+ cmat[4] = c*t1-s*t2;
+ cmat[7] = s*t1+c*t2;
+ t1 = cmat[5];
+ t2 = cmat[8];
+ cmat[5] = c*t1-s*t2;
+ cmat[8] = s*t1+c*t2;
+ next_fn();
+}
+
+static void matrix_roty(void)
+{
+ INT16 a = fifoin_pop();
+ float s = tsin(a);
+ float c = tcos(a);
+ float t1, t2;
+
+ logerror("TGP matrix_roty %d (%x)\n", a, activecpu_get_pc());
+ t1 = cmat[6];
+ t2 = cmat[0];
+ cmat[6] = c*t1-s*t2;
+ cmat[0] = s*t1+c*t2;
+ t1 = cmat[7];
+ t2 = cmat[1];
+ cmat[7] = c*t1-s*t2;
+ cmat[1] = s*t1+c*t2;
+ t1 = cmat[8];
+ t2 = cmat[2];
+ cmat[8] = c*t1-s*t2;
+ cmat[2] = s*t1+c*t2;
+ next_fn();
+}
+
+static void matrix_rotz(void)
+{
+ INT16 a = fifoin_pop();
+ float s = tsin(a);
+ float c = tcos(a);
+ float t1, t2;
+
+ logerror("TGP matrix_rotz %d (%x)\n", a, activecpu_get_pc());
+ t1 = cmat[0];
+ t2 = cmat[3];
+ cmat[0] = c*t1-s*t2;
+ cmat[3] = s*t1+c*t2;
+ t1 = cmat[1];
+ t2 = cmat[4];
+ cmat[1] = c*t1-s*t2;
+ cmat[4] = s*t1+c*t2;
+ t1 = cmat[2];
+ t2 = cmat[5];
+ cmat[2] = c*t1-s*t2;
+ cmat[5] = s*t1+c*t2;
+ next_fn();
+}
+
+static void track_read_quad(void)
+{
+ const UINT32 *tgp_data = (const UINT32 *)memory_region(REGION_USER2);
+ UINT32 a = fifoin_pop();
+ int offd;
+
+ logerror("TGP track_read_quad %d (%x)\n", a, activecpu_get_pc());
+
+ offd = tgp_data[0x20+tgp_vr_select] + 16*a;
+ fifoout_push(tgp_data[offd]);
+ fifoout_push(tgp_data[offd+1]);
+ fifoout_push(tgp_data[offd+2]);
+ fifoout_push(tgp_data[offd+3]);
+ fifoout_push(tgp_data[offd+4]);
+ fifoout_push(tgp_data[offd+5]);
+ fifoout_push(tgp_data[offd+6]);
+ fifoout_push(tgp_data[offd+7]);
+ fifoout_push(tgp_data[offd+8]);
+ fifoout_push(tgp_data[offd+9]);
+ fifoout_push(tgp_data[offd+10]);
+ fifoout_push(tgp_data[offd+11]);
+ next_fn();
+}
+
+static void f24_swa(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ UINT32 g = fifoin_pop();
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ (void)e;
+ (void)f;
+ (void)g;
+ logerror("TGP f24_swa %f, %f, %f, %f, %f, %f, %x (%x)\n", a, b, c, d, e, f, g, activecpu_get_pc());
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void transform_point(void)
+{
+ float x = fifoin_pop_f();
+ float y = fifoin_pop_f();
+ float z = fifoin_pop_f();
+ logerror("TGP transform_point %f, %f, %f (%x)\n", x, y, z, activecpu_get_pc());
+
+ fifoout_push_f(cmat[0]*x+cmat[3]*y+cmat[6]*z+cmat[9]);
+ fifoout_push_f(cmat[1]*x+cmat[4]*y+cmat[7]*z+cmat[10]);
+ fifoout_push_f(cmat[2]*x+cmat[5]*y+cmat[8]*z+cmat[11]);
+ next_fn();
+}
+
+static void fcos_m1(void)
+{
+ INT16 a = fifoin_pop();
+ logerror("TGP fcos %d (%x)\n", a, activecpu_get_pc());
+ fifoout_push_f(tcos(a));
+ next_fn();
+}
+
+static void fsin_m1(void)
+{
+ INT16 a = fifoin_pop();
+ logerror("TGP fsin %d (%x)\n", a, activecpu_get_pc());
+ fifoout_push_f(tsin(a));
+ next_fn();
+}
+
+static void fcosm_m1(void)
+{
+ INT16 a = fifoin_pop();
+ float b = fifoin_pop_f();
+ logerror("TGP fcosm %d, %f (%x)\n", a, b, activecpu_get_pc());
+ fifoout_push_f(b*tcos(a));
+ next_fn();
+}
+
+static void fsinm_m1(void)
+{
+ INT16 a = fifoin_pop();
+ float b = fifoin_pop_f();
+ model1_dump = 1;
+ logerror("TGP fsinm %d, %f (%x)\n", a, b, activecpu_get_pc());
+ fifoout_push_f(b*tsin(a));
+ next_fn();
+}
+
+static void distance3(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ logerror("TGP distance3 (%f, %f, %f), (%f, %f, %f) (%x)\n", a, b, c, d, e, f, activecpu_get_pc());
+ a -= d;
+ b -= e;
+ c -= f;
+ fifoout_push_f((a*a+b*b+c*c)/sqrt(a*a+b*b+c*c));
+ next_fn();
+}
+
+static void ftoi(void)
+{
+ float a = fifoin_pop_f();
+ logerror("TGP ftoi %f (%x)\n", a, activecpu_get_pc());
+ fifoout_push((int)a);
+ next_fn();
+}
+
+static void itof(void)
+{
+ INT32 a = fifoin_pop();
+ logerror("TGP itof %d (%x)\n", a, activecpu_get_pc());
+ fifoout_push_f(a);
+ next_fn();
+}
+
+static void acc_set(void)
+{
+ float a = fifoin_pop_f();
+ logerror("TGP acc_set %f (%x)\n", a, activecpu_get_pc());
+ acc = a;
+ next_fn();
+}
+
+static void acc_get(void)
+{
+ logerror("TGP acc_get (%x)\n", activecpu_get_pc());
+ fifoout_push_f(acc);
+ next_fn();
+}
+
+static void acc_add(void)
+{
+ float a = fifoin_pop_f();
+ logerror("TGP acc_add %f (%x)\n", a, activecpu_get_pc());
+ acc += a;
+ next_fn();
+}
+
+static void acc_sub(void)
+{
+ float a = fifoin_pop_f();
+ logerror("TGP acc_sub %f (%x)\n", a, activecpu_get_pc());
+ acc -= a;
+ next_fn();
+}
+
+static void acc_mul(void)
+{
+ float a = fifoin_pop_f();
+ logerror("TGP acc_mul %f (%x)\n", a, activecpu_get_pc());
+ acc *= a;
+ next_fn();
+}
+
+static void acc_div(void)
+{
+ float a = fifoin_pop_f();
+ logerror("TGP acc_div %f (%x)\n", a, activecpu_get_pc());
+ acc /= a;
+ next_fn();
+}
+
+static void f42(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ (void)a;
+ (void)b;
+ (void)c;
+ logerror("TGP f42 %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+ // fifoout_push_f((mame_rand(Machine) % 1000) - 500);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ next_fn();
+}
+
+
+// r = (x2 + y2 + z2)1/2, f = tan-1(y/(x2+z2)1/2), q = tan-1(z/x)
+
+static void xyz2rqf(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float norm;
+ (void)a;
+ (void)b;
+ (void)c;
+ logerror("TGP xyz2rqf %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+ fifoout_push_f((a*a+b*b+c*c)/sqrt(a*a+b*b+c*c));
+ norm = sqrt(a*a+c*c);
+ if(!c) {
+ if(a>=0)
+ fifoout_push(0);
+ else
+ fifoout_push(-32768);
+ } else if(!a) {
+ if(c>=0)
+ fifoout_push(16384);
+ else
+ fifoout_push(-16384);
+ } else
+ fifoout_push((INT16)(atan2(c, a)*32768/M_PI));
+
+ if(!b)
+ fifoout_push(0);
+ else if(!norm) {
+ if(b>=0)
+ fifoout_push(16384);
+ else
+ fifoout_push(-16384);
+ } else
+ fifoout_push((INT16)(atan2(b, norm)*32768/M_PI));
+
+ next_fn();
+}
+
+static void f43(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ (void)e;
+ (void)f;
+ logerror("TGP f43 %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, activecpu_get_pc());
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void f43_swa(void)
+{
+ float a = fifoin_pop_f();
+ int b = fifoin_pop();
+ int c = fifoin_pop();
+ (void)a;
+ (void)b;
+ (void)c;
+ logerror("TGP f43_swa %f, %d, %d (%x)\n", a, b, c, activecpu_get_pc());
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void f44(void)
+{
+ float a = fifoin_pop_f();
+ (void)a;
+ logerror("TGP f44 %f (%x)\n", a, activecpu_get_pc());
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void matrix_sdir(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float norm = sqrt(a*a+b*b+c*c);
+ float t[9], m[9];
+ logerror("TGP matrix_sdir %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+
+ memset(t, 0, sizeof(t));
+
+ if(!norm) {
+ memset(t, 0, 9*sizeof(t[0]));
+ t[0] = 1.0;
+ t[4] = 1.0;
+ t[8] = 1.0;
+ } else {
+ t[0] = -c / norm;
+ t[1] = b / norm;
+ t[2] = a / norm;
+
+ norm = sqrt(a*a+c*c);
+ t[6] = a/norm;
+ t[7] = 0;
+ t[8] = c/norm;
+
+ t[3] = -b*c;
+ t[4] = a*a+c*c;
+ t[5] = -b*a;
+ norm = sqrt(t[3]*t[3]+t[4]*t[4]+t[5]*t[5]);
+ t[3] /= norm;
+ t[4] /= norm;
+ t[5] /= norm;
+ }
+
+ m[0] = t[0]*cmat[0] + t[1]*cmat[3] + t[2]*cmat[6];
+ m[1] = t[0]*cmat[1] + t[1]*cmat[4] + t[2]*cmat[7];
+ m[2] = t[0]*cmat[2] + t[1]*cmat[5] + t[2]*cmat[8];
+ m[3] = t[3]*cmat[0] + t[4]*cmat[3] + t[5]*cmat[6];
+ m[4] = t[3]*cmat[1] + t[4]*cmat[4] + t[5]*cmat[7];
+ m[5] = t[3]*cmat[2] + t[4]*cmat[5] + t[5]*cmat[8];
+ m[6] = t[6]*cmat[0] + t[7]*cmat[3] + t[8]*cmat[6];
+ m[7] = t[6]*cmat[1] + t[7]*cmat[4] + t[8]*cmat[7];
+ m[8] = t[6]*cmat[2] + t[7]*cmat[5] + t[8]*cmat[8];
+
+ memcpy(cmat, m, sizeof(m));
+
+ next_fn();
+}
+
+static void f45(void)
+{
+ float a = fifoin_pop_f();
+ (void)a;
+ logerror("TGP f45 %f (%x)\n", a, activecpu_get_pc());
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void vlength(void)
+{
+ float a = fifoin_pop_f() - tgp_vr_base[0];
+ float b = fifoin_pop_f() - tgp_vr_base[1];
+ float c = fifoin_pop_f() - tgp_vr_base[2];
+ logerror("TGP vlength %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+
+ a = (a*a+b*b+c*c);
+ b = 1/sqrt(a);
+ c = a * b;
+ c -= tgp_vr_base[3];
+ fifoout_push_f(c);
+ next_fn();
+}
+
+static void f47(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ logerror("TGP f47 %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+ fifoout_push_f(a+c);
+ fifoout_push_f(b+c);
+ next_fn();
+}
+
+static void track_read_info(void)
+{
+ const UINT32 *tgp_data = (const UINT32 *)memory_region(REGION_USER2);
+ UINT16 a = fifoin_pop();
+ int offd;
+
+ logerror("TGP track_read_info %d (%x)\n", a, activecpu_get_pc());
+
+ offd = tgp_data[0x20+tgp_vr_select] + 16*a;
+ fifoout_push(tgp_data[offd+15]);
+ next_fn();
+}
+
+static void colbox_set(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ float g = fifoin_pop_f();
+ float h = fifoin_pop_f();
+ float i = fifoin_pop_f();
+ float j = fifoin_pop_f();
+ float k = fifoin_pop_f();
+ float l = fifoin_pop_f();
+ logerror("TGP colbox_set %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, g, h, i, j, k, l, activecpu_get_pc());
+ tgp_vr_cbox[ 0] = a;
+ tgp_vr_cbox[ 1] = b;
+ tgp_vr_cbox[ 2] = c;
+ tgp_vr_cbox[ 3] = d;
+ tgp_vr_cbox[ 4] = e;
+ tgp_vr_cbox[ 5] = f;
+ tgp_vr_cbox[ 6] = g;
+ tgp_vr_cbox[ 7] = h;
+ tgp_vr_cbox[ 8] = i;
+ tgp_vr_cbox[ 9] = j;
+ tgp_vr_cbox[10] = k;
+ tgp_vr_cbox[11] = l;
+ next_fn();
+}
+
+static void colbox_test(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ (void)a;
+ (void)b;
+ (void)c;
+ logerror("TGP colbox_test %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+
+ // #### Wrong, need to check with the tgp_vr_cbox coordinates
+ // Game only test sign, negative = collision
+ fifoout_push_f(-1);
+ next_fn();
+}
+
+static void f49_swa(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ (void)e;
+ (void)f;
+ logerror("TGP f49_swa %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, activecpu_get_pc());
+ next_fn();
+}
+
+static void f50_swa(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ logerror("TGP f50_swa %f, %f, %f, %f (%x)\n", a, b, c, d, activecpu_get_pc());
+ fifoout_push_f(d);
+ next_fn();
+}
+
+static void f52(void)
+{
+ logerror("TGP f52 (%x)\n", activecpu_get_pc());
+ next_fn();
+}
+
+static void matrix_rdir(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float norm = sqrt(a*a+c*c);
+ float t1, t2;
+ (void)b;
+
+ logerror("TGP matrix_rdir %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+
+ if(!norm) {
+ c = 1;
+ a = 0;
+ } else {
+ c /= norm;
+ a /= norm;
+ }
+
+ t1 = cmat[6];
+ t2 = cmat[0];
+ cmat[6] = c*t1-a*t2;
+ cmat[0] = a*t1+c*t2;
+ t1 = cmat[7];
+ t2 = cmat[1];
+ cmat[7] = c*t1-a*t2;
+ cmat[1] = a*t1+c*t2;
+ t1 = cmat[8];
+ t2 = cmat[2];
+ cmat[8] = c*t1-a*t2;
+ cmat[2] = a*t1+c*t2;
+ next_fn();
+}
+
+// A+(B-A)*t1 + (C-A)*t2 = P
+static void tri_calc_pq(float ax, float ay, float bx, float by, float cx, float cy, float px, float py, float *t1, float *t2)
+{
+ float d;
+ bx -= ax;
+ cx -= ax;
+ px -= ax;
+ by -= ay;
+ cy -= ay;
+ py -= ay;
+ d = bx*cy-by*cx;
+ *t1 = (px*cy-py*cx)/d;
+ *t2 = (bx*py-by*px)/d;
+}
+
+static void track_lookup(void)
+{
+ const UINT32 *tgp_data = (const UINT32 *)memory_region(REGION_USER2);
+ float a = fifoin_pop_f();
+ UINT32 b = fifoin_pop();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ int offi, offd, len;
+ float dist;
+ int i;
+ UINT32 behaviour, entry;
+ float height;
+
+ logerror("TGP track_lookup %f, 0x%x, %f, %f (%x)\n", a, b, c, d, activecpu_get_pc());
+
+ offi = tgp_data[0x10+tgp_vr_select] + b;
+ offd = tgp_data[0x20+tgp_vr_select];
+
+ len = tgp_data[offi++];
+
+ dist = -1;
+
+ behaviour = 0;
+ height = 0.0;
+ entry = 0;
+
+ for(i=0; i<len; i++) {
+ int j;
+ int bpos = tgp_data[offi++];
+ int posd = offd + bpos*0x10;
+ const float *pts = (const float *)(tgp_data+posd);
+ float ax = pts[12];
+ float ay = pts[14];
+ float az = pts[13];
+ for(j=0; j<4; j++) {
+ float t1, t2;
+ int k = (j+1) & 3;
+ tri_calc_pq(ax, ay, pts[3*j], pts[3*j+2], pts[3*k], pts[3*k+2], c, d, &t1, &t2);
+ if(t1 >= 0 && t2 >= 0 && t1+t2 <= 1) {
+ float z = az+t1*(pts[3*j+1]-az)+t2*(pts[3*k+1]-az);
+ float d = (a-z)*(a-z);
+ if(dist == -1 || d<dist) {
+ dist = d;
+ behaviour = tgp_data[posd+15];
+ height = z;
+ entry = bpos+i;
+ }
+ }
+ }
+ }
+
+ ram_data[0x0000] = 0; // non zero = still computing
+ ram_data[0x8001] = f2u(height);
+ ram_data[0x8002] = entry;
+
+ next_fn();
+}
+
+static void f56(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ UINT32 g = fifoin_pop();
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ (void)e;
+ (void)f;
+ (void)g;
+
+ logerror("TGP f56 %f, %f, %f, %f, %f, %f, %d (%x)\n", a, b, c, d, e, f, g, activecpu_get_pc());
+ fifoout_push(0);
+ next_fn();
+}
+
+static void f57(void)
+{
+ logerror("TGP f57 (%x)\n", activecpu_get_pc());
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void matrix_readt(void)
+{
+ logerror("TGP matrix_readt (%x)\n", activecpu_get_pc());
+ fifoout_push_f(cmat[9]);
+ fifoout_push_f(cmat[10]);
+ fifoout_push_f(cmat[11]);
+ next_fn();
+}
+
+static void acc_geti(void)
+{
+ logerror("TGP acc_geti (%x)\n", activecpu_get_pc());
+ fifoout_push((int)acc);
+ next_fn();
+}
+
+static void f60(void)
+{
+ logerror("TGP f60 (%x)\n", activecpu_get_pc());
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ fifoout_push_f(0);
+ next_fn();
+}
+
+static void col_setcirc(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ logerror("TGP col_setcirc %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+ tgp_vr_circx = a;
+ tgp_vr_circy = b;
+ tgp_vr_circrad = c;
+ next_fn();
+}
+
+static void col_testpt(void)
+{
+ float x, y;
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ logerror("TGP col_testpt %f, %f (%x)\n", a, b, activecpu_get_pc());
+ x = a - tgp_vr_circx;
+ y = b - tgp_vr_circy;
+ fifoout_push_f(((x*x+y*y)/sqrt(x*x+y*y)) - tgp_vr_circrad);
+ next_fn();
+}
+
+static void push_and_ident(void)
+{
+ if(mat_stack_pos != MAT_STACK_SIZE) {
+ memcpy(mat_stack[mat_stack_pos], cmat, sizeof(cmat));
+ mat_stack_pos++;
+ }
+ logerror("TGP push_and_ident (depth=%d, pc=%x)\n", mat_stack_pos, activecpu_get_pc());
+ memset(cmat, 0, sizeof(cmat));
+ cmat[0] = 1.0;
+ cmat[4] = 1.0;
+ cmat[8] = 1.0;
+ next_fn();
+}
+
+void tgp_tick(void)
+{
+}
+
+static void catmull_rom(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ float g = fifoin_pop_f();
+ float h = fifoin_pop_f();
+ float i = fifoin_pop_f();
+ float j = fifoin_pop_f();
+ float k = fifoin_pop_f();
+ float l = fifoin_pop_f();
+ float m = fifoin_pop_f();
+ float m2, m3;
+ float w1, w2, w3, w4;
+
+ logerror("TGP catmull_rom %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, g, h, i, j, k, l, m, activecpu_get_pc());
+
+ m2 = m*m;
+ m3 = m*m*m;
+
+ w1 = 0.5*(-m3+2*m2-m);
+ w2 = 0.5*(3*m3-5*m2+2);
+ w3 = 0.5*(-3*m3+4*m2+m);
+ w4 = 0.5*(m3-m2);
+
+ fifoout_push_f(a*w1+d*w2+g*w3+j*w4);
+ fifoout_push_f(b*w1+e*w2+h*w3+k*w4);
+ fifoout_push_f(c*w1+f*w2+i*w3+l*w4);
+ next_fn();
+}
+
+static void distance(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ logerror("TGP distance (%f, %f), (%f, %f) (%x)\n", a, b, c, d, activecpu_get_pc());
+ c -= a;
+ d -= b;
+ fifoout_push_f((c*c+d*d)/sqrt(c*c+d*d));
+ next_fn();
+}
+
+static void car_move(void)
+{
+ INT16 a = fifoin_pop();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float dx, dy;
+ logerror("TGP car_move (%d, %f), (%f, %f) (%x)\n", a, b, c, d, activecpu_get_pc());
+
+ dx = b*tsin(a);
+ dy = b*tcos(a);
+
+ fifoout_push_f(dx);
+ fifoout_push_f(dy);
+ fifoout_push_f(c+dx);
+ fifoout_push_f(d+dy);
+ next_fn();
+}
+
+static void cpa(void)
+{
+ float dv_x, dv_y, dv_z, dv2, dw_x, dw_y, dw_z, dt;
+
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ float g = fifoin_pop_f();
+ float h = fifoin_pop_f();
+ float i = fifoin_pop_f();
+ float j = fifoin_pop_f();
+ float k = fifoin_pop_f();
+ float l = fifoin_pop_f();
+ logerror("TGP cpa %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, g, h, i, j, k, l, activecpu_get_pc());
+
+ dv_x = (b-a) - (d-c);
+ dv_y = (f-e) - (h-g);
+ dv_z = (j-i) - (l-k);
+ dv2 = dv_x*dv_x + dv_y*dv_y + dv_z*dv_z;
+ if(dv2 < 0.001)
+ dt = 0;
+ else {
+ dw_x = a-c;
+ dw_y = e-g;
+ dw_z = i-k;
+ dt = -(dw_x*dv_x + dw_y*dv_y + dw_z*dv_z)/dv2;
+ }
+ if(dt < 0)
+ dt = 0;
+ else if(dt > 1.0)
+ dt = 1.0;
+
+ dv_x = (a-c)*(1-dt) + (b-d)*dt;
+ dv_y = (e-g)*(1-dt) + (f-h)*dt;
+ dv_z = (i-k)*(1-dt) + (j-l)*dt;
+ dv2 = dv_x*dv_x + dv_y*dv_y + dv_z*dv_z;
+
+ fifoout_push_f(sqrt(dv2));
+ next_fn();
+}
+
+static void vmat_store(void)
+{
+ UINT32 a = fifoin_pop();
+ if(a<21)
+ memcpy(mat_vector[a], cmat, sizeof(cmat));
+ else
+ logerror("TGP ERROR bad vector index\n");
+ logerror("TGP vmat_store %d (%x)\n", a, activecpu_get_pc());
+ next_fn();
+}
+
+static void vmat_restore(void)
+{
+ UINT32 a = fifoin_pop();
+ if(a<21)
+ memcpy(cmat, mat_vector[a], sizeof(cmat));
+ else
+ logerror("TGP ERROR bad vector index\n");
+ logerror("TGP vmat_restore %d (%x)\n", a, activecpu_get_pc());
+ next_fn();
+}
+
+static void vmat_mul(void)
+{
+ UINT32 a = fifoin_pop();
+ UINT32 b = fifoin_pop();
+ if(a<21 && b<21) {
+ mat_vector[b][0] = mat_vector[a][ 0]*cmat[0] + mat_vector[a][ 1]*cmat[3] + mat_vector[a][ 2]*cmat[6];
+ mat_vector[b][1] = mat_vector[a][ 0]*cmat[1] + mat_vector[a][ 1]*cmat[4] + mat_vector[a][ 2]*cmat[7];
+ mat_vector[b][2] = mat_vector[a][ 0]*cmat[2] + mat_vector[a][ 1]*cmat[5] + mat_vector[a][ 2]*cmat[8];
+ mat_vector[b][3] = mat_vector[a][ 3]*cmat[0] + mat_vector[a][ 4]*cmat[3] + mat_vector[a][ 5]*cmat[6];
+ mat_vector[b][4] = mat_vector[a][ 3]*cmat[1] + mat_vector[a][ 4]*cmat[4] + mat_vector[a][ 5]*cmat[7];
+ mat_vector[b][5] = mat_vector[a][ 3]*cmat[2] + mat_vector[a][ 4]*cmat[5] + mat_vector[a][ 5]*cmat[8];
+ mat_vector[b][6] = mat_vector[a][ 6]*cmat[0] + mat_vector[a][ 7]*cmat[3] + mat_vector[a][ 8]*cmat[6];
+ mat_vector[b][7] = mat_vector[a][ 6]*cmat[1] + mat_vector[a][ 7]*cmat[4] + mat_vector[a][ 8]*cmat[7];
+ mat_vector[b][8] = mat_vector[a][ 6]*cmat[2] + mat_vector[a][ 7]*cmat[5] + mat_vector[a][ 8]*cmat[8];
+ mat_vector[b][9] = mat_vector[a][ 9]*cmat[0] + mat_vector[a][10]*cmat[3] + mat_vector[a][11]*cmat[6] + cmat[9];
+ mat_vector[b][10] = mat_vector[a][ 9]*cmat[1] + mat_vector[a][10]*cmat[4] + mat_vector[a][11]*cmat[7] + cmat[10];
+ mat_vector[b][11] = mat_vector[a][ 9]*cmat[2] + mat_vector[a][10]*cmat[5] + mat_vector[a][11]*cmat[8] + cmat[11];
+ } else
+ logerror("TGP ERROR bad vector index\n");
+ logerror("TGP vmat_mul %d, %d (%x)\n", a, b, activecpu_get_pc());
+ next_fn();
+}
+
+static void vmat_read(void)
+{
+ UINT32 a = fifoin_pop();
+ logerror("TGP vmat_read %d (%x)\n", a, activecpu_get_pc());
+ if(a<21) {
+ int i;
+ for(i=0; i<12; i++)
+ fifoout_push_f(mat_vector[a][i]);
+ } else {
+ int i;
+ logerror("TGP ERROR bad vector index\n");
+ for(i=0; i<12; i++)
+ fifoout_push_f(0);
+ }
+ next_fn();
+}
+
+static void matrix_rtrans(void)
+{
+ logerror("TGP matrix_rtrans (%x)\n", activecpu_get_pc());
+ fifoout_push_f(cmat[ 9]);
+ fifoout_push_f(cmat[10]);
+ fifoout_push_f(cmat[11]);
+ next_fn();
+}
+
+static void matrix_unrot(void)
+{
+ logerror("TGP matrix_unrot (%x)\n", activecpu_get_pc());
+ memset(cmat, 0, 9*sizeof(cmat[0]));
+ cmat[0] = 1.0;
+ cmat[4] = 1.0;
+ cmat[8] = 1.0;
+ next_fn();
+}
+
+static void f80(void)
+{
+ logerror("TGP f80 (%x)\n", activecpu_get_pc());
+ // cmat[9] = cmat[10] = cmat[11] = 0;
+ next_fn();
+}
+
+static void vmat_save(void)
+{
+ UINT32 a = fifoin_pop();
+ int i;
+ logerror("TGP vmat_save 0x%x (%x)\n", a, activecpu_get_pc());
+ for(i=0; i<16; i++)
+ memcpy(ram_data+a+0x10*i, mat_vector[i], sizeof(cmat));
+ next_fn();
+}
+
+static void vmat_load(void)
+{
+ UINT32 a = fifoin_pop();
+ int i;
+ logerror("TGP vmat_load 0x%x (%x)\n", a, activecpu_get_pc());
+ for(i=0; i<16; i++)
+ memcpy(mat_vector[i], ram_data+a+0x10*i, sizeof(cmat));
+ next_fn();
+}
+
+static void ram_setadr(void)
+{
+ ram_scanadr = fifoin_pop() - 0x8000;
+ logerror("TGP f0 ram_setadr 0x%x (%x)\n", ram_scanadr+0x8000, activecpu_get_pc());
+ next_fn();
+}
+
+static void groundbox_test(void)
+{
+ int out_x, out_y, out_z;
+ float x, y, z;
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+
+ logerror("TGP groundbox_test %f, %f, %f (%x)\n", a, b, c, activecpu_get_pc());
+ x = cmat[0]*a+cmat[3]*b+cmat[6]*c+cmat[9];
+ y = cmat[1]*a+cmat[4]*b+cmat[7]*c+cmat[10];
+ z = cmat[2]*a+cmat[5]*b+cmat[8]*c+cmat[11];
+
+ out_x = x < tgp_vf_xmin || x > tgp_vf_xmax;
+ out_z = z < tgp_vf_zmin || z > tgp_vf_zmax;
+ out_y = 1; // Wrong, but untestable it seems.
+
+ fifoout_push(out_x);
+ fifoout_push(out_y);
+ fifoout_push(out_z);
+ next_fn();
+}
+
+static void f89(void)
+{
+ UINT32 a = fifoin_pop();
+ UINT32 b = fifoin_pop();
+ UINT32 c = fifoin_pop();
+ UINT32 d = fifoin_pop();
+ (void)a;
+ (void)b;
+ (void)c;
+ logerror("TGP list set base 0x%x, 0x%x, %d, length=%d (%x)\n", a, b, c, d, activecpu_get_pc());
+ list_length = d;
+ next_fn();
+}
+
+static void f92(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ (void)a;
+ (void)b;
+ (void)c;
+ (void)d;
+ logerror("TGP f92 %f, %f, %f, %f (%x)\n", a, b, c, d, activecpu_get_pc());
+ next_fn();
+}
+
+static void f93(void)
+{
+ float a = fifoin_pop_f();
+ (void)a;
+ logerror("TGP f93 %f (%x)\n", a, activecpu_get_pc());
+ next_fn();
+}
+
+static void f94(void)
+{
+ UINT32 a = fifoin_pop();
+ (void)a;
+ logerror("TGP f94 %d (%x)\n", a, activecpu_get_pc());
+ next_fn();
+}
+
+static void vmat_flatten(void)
+{
+ int i;
+ float m[12];
+ logerror("TGP vmat_flatten (%x)\n", activecpu_get_pc());
+
+ for(i=0; i<16; i++) {
+ memcpy(m, mat_vector[i], sizeof(cmat));
+ m[1] = m[4] = m[7] = m[10] = 0;
+
+ mat_vector[i][0] = m[ 0]*cmat[0] + m[ 1]*cmat[3] + m[ 2]*cmat[6];
+ mat_vector[i][1] = m[ 0]*cmat[1] + m[ 1]*cmat[4] + m[ 2]*cmat[7];
+ mat_vector[i][2] = m[ 0]*cmat[2] + m[ 1]*cmat[5] + m[ 2]*cmat[8];
+ mat_vector[i][3] = m[ 3]*cmat[0] + m[ 4]*cmat[3] + m[ 5]*cmat[6];
+ mat_vector[i][4] = m[ 3]*cmat[1] + m[ 4]*cmat[4] + m[ 5]*cmat[7];
+ mat_vector[i][5] = m[ 3]*cmat[2] + m[ 4]*cmat[5] + m[ 5]*cmat[8];
+ mat_vector[i][6] = m[ 6]*cmat[0] + m[ 7]*cmat[3] + m[ 8]*cmat[6];
+ mat_vector[i][7] = m[ 6]*cmat[1] + m[ 7]*cmat[4] + m[ 8]*cmat[7];
+ mat_vector[i][8] = m[ 6]*cmat[2] + m[ 7]*cmat[5] + m[ 8]*cmat[8];
+ mat_vector[i][9] = m[ 9]*cmat[0] + m[10]*cmat[3] + m[11]*cmat[6] + cmat[9];
+ mat_vector[i][10] = m[ 9]*cmat[1] + m[10]*cmat[4] + m[11]*cmat[7] + cmat[10];
+ mat_vector[i][11] = m[ 9]*cmat[2] + m[10]*cmat[5] + m[11]*cmat[8] + cmat[11];
+ }
+ next_fn();
+}
+
+static void vmat_load1(void)
+{
+ UINT32 a = fifoin_pop();
+ logerror("TGP vmat_load1 0x%x (%x)\n", a, activecpu_get_pc());
+ memcpy(cmat, ram_data+a, sizeof(cmat));
+ next_fn();
+}
+
+static void ram_trans(void)
+{
+ float a = ram_get_f();
+ float b = ram_get_f();
+ float c = ram_get_f();
+ logerror("TGP ram_trans (%x)\n", activecpu_get_pc());
+ cmat[ 9] += cmat[0]*a+cmat[3]*b+cmat[6]*c;
+ cmat[10] += cmat[1]*a+cmat[4]*b+cmat[7]*c;
+ cmat[11] += cmat[2]*a+cmat[5]*b+cmat[8]*c;
+ next_fn();
+}
+
+static void f98_load(void)
+{
+ int i;
+ for(i=0; i<list_length; i++) {
+ float f = fifoin_pop_f();
+ (void)f;
+ logerror("TGP load list (%2d/%2d) %f (%x)\n", i, list_length, f, activecpu_get_pc());
+ }
+ next_fn();
+}
+
+static void f98(void)
+{
+ UINT32 a = fifoin_pop();
+ (void)a;
+ logerror("TGP load list start %d (%x)\n", a, activecpu_get_pc());
+ fifoin_cbcount = list_length;
+ fifoin_cb = f98_load;
+}
+
+static void f99(void)
+{
+ logerror("TGP f99 (%x)\n", activecpu_get_pc());
+ next_fn();
+}
+
+static void f100(void)
+{
+ int i;
+ logerror("TGP f100 get list (%x)\n", activecpu_get_pc());
+ for(i=0; i<list_length; i++)
+ fifoout_push_f((mame_rand(Machine) % 1000)/100.0);
+ next_fn();
+}
+
+static void groundbox_set(void)
+{
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ float f = fifoin_pop_f();
+ float g = fifoin_pop_f();
+ logerror("TGP groundbox_set %f, %f, %f, %f, %f, %f, %f (%x)\n", a, b, c, d, e, f, g, activecpu_get_pc());
+ tgp_vf_xmin = e;
+ tgp_vf_xmax = d;
+ tgp_vf_zmin = g;
+ tgp_vf_zmax = f;
+ tgp_vf_ygnd = b;
+ tgp_vf_yflr = a;
+ tgp_vf_yjmp = c;
+
+ next_fn();
+}
+
+static void f102(void)
+{
+ static int ccount = 0;
+ float px, py, pz;
+ float a = fifoin_pop_f();
+ float b = fifoin_pop_f();
+ float c = fifoin_pop_f();
+ float d = fifoin_pop_f();
+ float e = fifoin_pop_f();
+ UINT32 f = fifoin_pop();
+ UINT32 g = fifoin_pop();
+ UINT32 h = fifoin_pop();
+
+ ccount++;
+
+ logerror("TGP f0 mve_calc %f, %f, %f, %f, %f, %d, %d, %d (%d) (%x)\n", a, b, c, d, e, f, g, h, ccount, activecpu_get_pc());
+
+ px = u2f(ram_data[ram_scanadr+0x16]);
+ py = u2f(ram_data[ram_scanadr+0x17]);
+ pz = u2f(ram_data[ram_scanadr+0x18]);
+
+ // memset(cmat, 0, sizeof(cmat));
+ // cmat[0] = 1.0;
+ // cmat[4] = 1.0;
+ // cmat[8] = 1.0;
+
+ px = c;
+ py = d;
+ pz = e;
+
+#if 1
+ cmat[ 9] += cmat[0]*a+cmat[3]*b+cmat[6]*c;
+ cmat[10] += cmat[1]*a+cmat[4]*b+cmat[7]*c;
+ cmat[11] += cmat[2]*a+cmat[5]*b+cmat[8]*c;
+#else
+ cmat[ 9] += px;
+ cmat[10] += py;
+ cmat[11] += pz;
+#endif
+
+ logerror(" f0 mve_calc %f, %f, %f\n", px, py, pz);
+
+ fifoout_push_f(c);
+ fifoout_push_f(d);
+ fifoout_push_f(e);
+ fifoout_push(f);
+ fifoout_push(g);
+ fifoout_push(h);
+
+
+ next_fn();
+}
+
+static void f103(void)
+{
+ ram_scanadr = fifoin_pop() - 0x8000;
+ logerror("TGP f0 mve_setadr 0x%x (%x)\n", ram_scanadr, activecpu_get_pc());
+ ram_get_i();
+ next_fn();
+}
+
+struct function {
+ void (*cb)(void);
+ int count;
+};
+
+static const struct function ftab_vf[] = {
+ { fadd, 2 }, /* 0x00 */
+ { fsub, 2 },
+ { fmul, 2 },
+ { fdiv, 2 },
+ { NULL, 0 },
+ { matrix_push, 0 },
+ { matrix_pop, 0 },
+ { matrix_write, 12 },
+ { clear_stack, 0 },
+ { NULL, 0 },
+ { anglev, 2 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { track_select, 1 },
+ { f14, 4 },
+ { anglep, 4 },
+
+ { matrix_ident, 0 }, /* 0x10 */
+ { matrix_read, 0 },
+ { matrix_trans, 3 },
+ { matrix_scale, 3 },
+ { matrix_rotx, 1 },
+ { matrix_roty, 1 },
+ { matrix_rotz, 1 },
+ { NULL, 0 },
+ { track_read_quad, 1 },
+ { NULL, 0 },
+ { transform_point, 3 },
+ { fsin_m1, 1 },
+ { fcos_m1, 1 },
+ { fsinm_m1, 2 },
+ { fcosm_m1, 2 },
+ { distance3, 6 },
+
+ { NULL, 0 }, /* 0x20 */
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { acc_set, 1 },
+ { acc_get, 0 },
+ { acc_add, 1 },
+ { acc_sub, 1 },
+ { acc_mul, 1 },
+ { acc_div, 1 }, // not used ?
+ { f42, 3 },
+ { f43, 6 },
+ { f44, 1 },
+ { f45, 1 },
+ { vlength, 3 },
+ { NULL, 0 },
+
+ { track_read_info, 1 }, /* 0x30 */
+ { colbox_set, 12 },
+ { colbox_test, 3 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { track_lookup, 4 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+
+ { col_setcirc, 3 }, /* 0x40 */
+ { col_testpt, 2 },
+ { NULL, 0 },
+ { distance, 4 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { car_move, 4 },
+ { cpa, 12 },
+ { NULL, 0 },
+ { vmat_store, 1 },
+ { vmat_restore, 1 },
+ { NULL, 0 },
+ { vmat_mul, 2 },
+ { vmat_read, 1 },
+ { matrix_unrot, 0 },
+
+ { f80, 0 }, /* 0x50 */
+ { NULL, 0 },
+ { matrix_rtrans, 0 },
+ { NULL, 0 },
+ { vmat_save, 1 },
+ { vmat_load, 1 },
+ { ram_setadr, 1 },
+ { groundbox_test, 3 },
+ { NULL, 0 },
+ { f89, 4 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { f92, 4 },
+ { f93, 1 },
+ { f94, 1 },
+ { vmat_flatten, 0 },
+
+ { vmat_load1, 1 }, /* 0x60 */
+ { ram_trans, 0 },
+ { f98, 1 },
+ { f99, 0 },
+ { f100, 0 },
+ { groundbox_set, 7 },
+ { f102, 8 },
+ { f103, 1 }
+};
+
+// Used in swa scene 1 and unemulated:
+// f14
+// f49_swa
+// f15_swa
+
+static const struct function ftab_swa[] = {
+ { fadd, 2 }, /* 0x00 */
+ { fsub, 2 },
+ { fmul, 2 },
+ { fdiv, 2 },
+ { NULL, 0 },
+ { matrix_push, 0 },
+ { matrix_pop, 0 },
+ { matrix_write, 12 },
+ { clear_stack, 0 },
+ { matrix_mul, 12 },
+ { anglev, 2 },
+ { f11, 9 },
+ { normalize, 3 },
+ { acc_seti, 1 },
+ { f14, 4 },
+ { f15_swa, 0 },
+
+ { matrix_ident, 0 }, /* 0x10 */
+ { matrix_read, 0 },
+ { matrix_trans, 3 },
+ { matrix_scale, 3 },
+ { matrix_rotx, 1 },
+ { matrix_roty, 1 },
+ { matrix_rotz, 1 },
+ { NULL, 0 },
+ { f24_swa, 7 },
+ { NULL, 0 },
+ { transform_point, 3 },
+ { fsin_m1, 1 },
+ { fcos_m1, 1 },
+ { fsinm_m1, 2 },
+ { fcosm_m1, 2 },
+ { distance3, 6 },
+
+ { NULL, 0 }, /* 0x20 */
+ { NULL, 0 },
+ { ftoi, 1 },
+ { itof, 1 },
+ { acc_set, 1 },
+ { acc_get, 0 },
+ { acc_add, 1 },
+ { acc_sub, 1 },
+ { acc_mul, 1 },
+ { acc_div, 1 }, // not used ?
+ { xyz2rqf, 3 },
+ { f43_swa, 3 },
+ { matrix_sdir, 3 },
+ { f45, 1 },
+ { vlength, 3 },
+ { f47, 3 },
+
+ { NULL, 0 }, /* 0x30 */
+ { f49_swa, 6 },
+ { f50_swa, 4 },
+ { NULL, 0 },
+ { f52, 0 },
+ { matrix_rdir, 3 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { f56, 7 },
+ { f57, 0 },
+ { matrix_readt, 0 },
+ { acc_geti, 0 },
+ { f60, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+
+ { push_and_ident, 0 }, /* 0x40 */
+ { NULL, 0 },
+ { catmull_rom, 13 }
+};
+
+
+static void dump(void)
+{
+ logerror("TGP FIFOIN write %08x (%x)\n", fifoin_pop(), activecpu_get_pc());
+ fifoin_cbcount = 1;
+ fifoin_cb = dump;
+}
+
+static void function_get_vf(void)
+{
+ UINT32 f = fifoin_pop() >> 23;
+
+ if(fifoout_rpos != fifoout_wpos) {
+ int count = fifoout_wpos - fifoout_rpos;
+ if(count < 0)
+ count += FIFO_SIZE;
+ logerror("TGP function called with sizeout = %d\n", count);
+ }
+ if(ARRAY_LENGTH(ftab_vf) > f && NULL != ftab_vf[f].cb) {
+ fifoin_cbcount = ftab_vf[f].count;
+ fifoin_cb = ftab_vf[f].cb;
+ // logerror("TGP function %d request, %d parameters\n", f, fifoin_cbcount);
+ if(!fifoin_cbcount)
+ fifoin_cb();
+ } else {
+ logerror("TGP function %d unimplemented (%x)\n", f, activecpu_get_pc());
+ fifoin_cbcount = 1;
+ fifoin_cb = dump;
+ }
+}
+
+static void function_get_swa(void)
+{
+ UINT32 f = fifoin_pop();
+
+ if(fifoout_rpos != fifoout_wpos) {
+ int count = fifoout_wpos - fifoout_rpos;
+ if(count < 0)
+ count += FIFO_SIZE;
+ logerror("TGP function called with sizeout = %d\n", count);
+ }
+ if(ARRAY_LENGTH(ftab_swa) > f && NULL != ftab_swa[f].cb) {
+ fifoin_cbcount = ftab_swa[f].count;
+ fifoin_cb = ftab_swa[f].cb;
+ // logerror("TGP function %d request, %d parameters\n", f, fifoin_cbcount);
+ if(!fifoin_cbcount)
+ fifoin_cb();
+ } else {
+ logerror("TGP function %d unimplemented (%x)\n", f, activecpu_get_pc());
+ fifoin_cbcount = 1;
+ fifoin_cb = dump;
+ }
+}
+
+READ16_HANDLER( model1_tgp_copro_r )
+{
+ static UINT32 cur;
+ if(!offset) {
+ cur = fifoout_pop();
+ return cur;
+ } else
+ return cur >> 16;
+}
+
+WRITE16_HANDLER( model1_tgp_copro_w )
+{
+ static UINT32 cur;
+ if(offset) {
+ cur = (cur & 0x0000ffff) | (data << 16);
+ fifoin_push(cur);
+ } else
+ cur = (cur & 0xffff0000) | data;
+}
+
+READ16_HANDLER( model1_tgp_copro_adr_r )
+{
+ return ram_adr;
+}
+
+WRITE16_HANDLER( model1_tgp_copro_adr_w )
+{
+ COMBINE_DATA(&ram_adr);
+}
+
+READ16_HANDLER( model1_tgp_copro_ram_r )
+{
+ if(!offset) {
+ logerror("TGP f0 ram read %04x, %08x (%f) (%x)\n", ram_adr, ram_data[ram_adr], u2f(ram_data[ram_adr]), activecpu_get_pc());
+ return ram_data[ram_adr];
+ } else
+ return ram_data[ram_adr++] >> 16;
+}
+
+WRITE16_HANDLER( model1_tgp_copro_ram_w )
+{
+ COMBINE_DATA(ram_latch+offset);
+ if(offset) {
+ UINT32 v = ram_latch[0]|(ram_latch[1]<<16);
+ logerror("TGP f0 ram write %04x, %08x (%f) (%x)\n", ram_adr, v, u2f(v), activecpu_get_pc());
+ ram_data[ram_adr] = v;
+ ram_adr++;
+ }
+}
+
+void model1_tgp_reset(int swa)
+{
+ ram_adr = 0;
+ ram_data = auto_malloc(0x10000*4);
+ memset(ram_data, 0, 0x10000*4);
+
+ fifoout_rpos = 0;
+ fifoout_wpos = 0;
+ fifoin_rpos = 0;
+ fifoin_wpos = 0;
+
+ acc = 0;
+ mat_stack_pos = 0;
+ memset(cmat, 0, sizeof(cmat));
+ cmat[0] = 1.0;
+ cmat[4] = 1.0;
+ cmat[8] = 1.0;
+
+ model1_dump = 0;
+ model1_swa = swa;
+ next_fn();
+
+ state_save_register_global_pointer(ram_data, 0x10000);
+ state_save_register_global(ram_adr);
+ state_save_register_global(ram_scanadr);
+ state_save_register_global_array(ram_latch);
+ state_save_register_global(fifoout_rpos);
+ state_save_register_global(fifoout_wpos);
+ state_save_register_global_array(fifoout_data);
+ state_save_register_global(fifoin_rpos);
+ state_save_register_global(fifoin_wpos);
+ state_save_register_global_array(fifoin_data);
+ state_save_register_global_array(cmat);
+ state_save_register_global_2d_array(mat_stack);
+ state_save_register_global_2d_array(mat_vector);
+ state_save_register_global(mat_stack_pos);
+ state_save_register_global(acc);
+ state_save_register_global(list_length);
+}
+
+/*********************************** Virtua Racing ***********************************/
+
+static int copro_fifoout_rpos, copro_fifoout_wpos;
+static UINT32 copro_fifoout_data[FIFO_SIZE];
+static int copro_fifoout_num;
+static int copro_fifoin_rpos, copro_fifoin_wpos;
+static UINT32 copro_fifoin_data[FIFO_SIZE];
+static int copro_fifoin_num;
+
+void model1_vr_tgp_reset( void )
+{
+ ram_adr = 0;
+ ram_data = auto_malloc(0x8000*4);
+ memset(ram_data, 0, 0x8000*4);
+
+ copro_fifoout_rpos = 0;
+ copro_fifoout_wpos = 0;
+ copro_fifoout_num = 0;
+ copro_fifoin_rpos = 0;
+ copro_fifoin_wpos = 0;
+ copro_fifoin_num = 0;
+}
+
+/* FIFO */
+static int copro_fifoin_pop(UINT32 *result)
+{
+ UINT32 r;
+
+ if (copro_fifoin_num == 0)
+ {
+ return 0;
+ }
+
+ r = copro_fifoin_data[copro_fifoin_rpos++];
+
+ if (copro_fifoin_rpos == FIFO_SIZE)
+ {
+ copro_fifoin_rpos = 0;
+ }
+
+ copro_fifoin_num--;
+
+ *result = r;
+
+ return 1;
+}
+
+static void copro_fifoin_push(UINT32 data)
+{
+ if (copro_fifoin_num == FIFO_SIZE)
+ {
+ fatalerror("Copro FIFOIN overflow (at %08X)", activecpu_get_pc());
+ return;
+ }
+
+ copro_fifoin_data[copro_fifoin_wpos++] = data;
+
+ if (copro_fifoin_wpos == FIFO_SIZE)
+ {
+ copro_fifoin_wpos = 0;
+ }
+
+ copro_fifoin_num++;
+}
+
+static UINT32 copro_fifoout_pop(void)
+{
+ UINT32 r;
+
+ if (copro_fifoout_num == 0)
+ {
+ // Reading from empty FIFO causes the v60 to enter wait state
+ extern void v60_stall(void);
+ v60_stall();
+
+ timer_call_after_resynch(0, NULL);
+
+ return 0;
+ }
+
+ r = copro_fifoout_data[copro_fifoout_rpos++];
+
+ if (copro_fifoout_rpos == FIFO_SIZE)
+ {
+ copro_fifoout_rpos = 0;
+ }
+
+ copro_fifoout_num--;
+
+ return r;
+}
+
+static void copro_fifoout_push(UINT32 data)
+{
+ if (copro_fifoout_num == FIFO_SIZE)
+ {
+ fatalerror("Copro FIFOOUT overflow (at %08X)", activecpu_get_pc());
+ return;
+ }
+
+ copro_fifoout_data[copro_fifoout_wpos++] = data;
+
+ if (copro_fifoout_wpos == FIFO_SIZE)
+ {
+ copro_fifoout_wpos = 0;
+ }
+
+ copro_fifoout_num++;
+}
+
+static READ32_HANDLER(copro_ram_r)
+{
+ return ram_data[offset & 0x7fff];
+}
+
+static WRITE32_HANDLER(copro_ram_w)
+{
+ ram_data[offset&0x7fff] = data;
+}
+
+READ16_HANDLER( model1_tgp_vr_adr_r )
+{
+ if ( ram_adr == 0 && copro_fifoin_num != 0 )
+ {
+ /* spin the main cpu and let the TGP catch up */
+ cpu_spinuntil_time(ATTOTIME_IN_USEC(100));
+ }
+
+ return ram_adr;
+}
+
+WRITE16_HANDLER( model1_tgp_vr_adr_w )
+{
+ COMBINE_DATA(&ram_adr);
+}
+
+READ16_HANDLER( model1_vr_tgp_ram_r )
+{
+ UINT16 r;
+
+ if (!offset)
+ {
+ r = ram_data[ram_adr&0x7fff];
+ }
+ else
+ {
+ r = ram_data[ram_adr&0x7fff] >> 16;
+
+ if ( ram_adr == 0 && r == 0xffff )
+ {
+ /* if the TGP is busy, spin some more */
+ cpu_spinuntil_time(ATTOTIME_IN_USEC(100));
+ }
+
+ if ( ram_adr & 0x8000 )
+ ram_adr++;
+ }
+
+ return r;
+}
+
+WRITE16_HANDLER( model1_vr_tgp_ram_w )
+{
+ COMBINE_DATA(ram_latch+offset);
+
+ if (offset)
+ {
+ UINT32 v = ram_latch[0]|(ram_latch[1]<<16);
+ ram_data[ram_adr&0x7fff] = v;
+ if ( ram_adr & 0x8000 )
+ ram_adr++;
+ }
+}
+
+READ16_HANDLER( model1_vr_tgp_r )
+{
+ static UINT32 cur;
+
+ if (!offset)
+ {
+ cur = copro_fifoout_pop();
+ return cur;
+ }
+ else
+ return cur >> 16;
+}
+
+WRITE16_HANDLER( model1_vr_tgp_w )
+{
+ static UINT32 cur;
+
+ if (offset)
+ {
+ cur = (cur & 0x0000ffff) | (data << 16);
+ copro_fifoin_push(cur);
+ }
+ else
+ cur = (cur & 0xffff0000) | data;
+}
+
+/* TGP config */
+struct mb86233_config model1_vr_tgp_config =
+{
+ copro_fifoin_pop,
+ copro_fifoout_push
+};
+
+/* TGP memory map */
+ADDRESS_MAP_START( model1_vr_tgp_map, ADDRESS_SPACE_PROGRAM, 32 )
+ AM_RANGE(0x00000000, 0x000007ff) AM_RAM AM_REGION(REGION_CPU3, 0)
+ AM_RANGE(0x00400000, 0x00407fff) AM_READWRITE(copro_ram_r, copro_ram_w)
+ AM_RANGE(0xff800000, 0xff87ffff) AM_ROM AM_REGION(REGION_USER2, 0)
+ADDRESS_MAP_END
diff --git a/src/mame/machine/model3.c b/src/mame/machine/model3.c
new file mode 100644
index 00000000000..6575f3d7a4f
--- /dev/null
+++ b/src/mame/machine/model3.c
@@ -0,0 +1,363 @@
+/*
+
+ machine/model3.c: functions emulating various aspects of the Model 3 hardware
+
+*/
+
+#include "driver.h"
+
+static int m3_step;
+
+/******************************************************************/
+/* Real3D TAP Port */
+/******************************************************************/
+
+/*
+ * TAP Finite State Machine
+ *
+ * Y are states and X are outgoing paths. Constructed from information on page
+ * 167 of the 3D-RAM manual.
+ */
+
+#define NEXT(new_state) fsm[state][new_state]
+
+static INT32 state; // current state
+static INT32 fsm[][2] = {
+ { 1, 0 }, // 0 Test-Logic/Reset
+ { 1, 2 }, // 1 Run-Test/Idle
+ { 3, 9 }, // 2 Select-DR-Scan
+ { 4, 5 }, // 3 Capture-DR
+ { 4, 5 }, // 4 Shift-DR
+ { 6, 8 }, // 5 Exit1-DR
+ { 6, 7 }, // 6 Pause-DR
+ { 4, 8 }, // 7 Exit2-DR
+ { 1, 2 }, // 8 Update-DR
+ { 10, 0 }, // 9 Select-IR-Scan
+ { 11, 12 }, // 10 Capture-IR
+ { 11, 12 }, // 11 Shift-IR
+ { 13, 15 }, // 12 Exit1-IR
+ { 13, 14 }, // 13 Pause-IR
+ { 11, 15 }, // 14 Exit2-IR
+ { 1, 2 } // 15 Update-IR
+ };
+
+/*
+ * TAP Registers
+ */
+
+static UINT64 current_instruction; // latched IR (not always equal to IR)
+static UINT64 ir; // instruction register (46 bits)
+
+static UINT8 id_data[32]; // ASIC ID code data buffer
+static INT32 id_size; // size of ID data in bits
+//static INT32 ptr; // current bit ptr for data
+
+static int tdo; // bit shifted out to TDO
+
+/*
+ * insert_bit():
+ *
+ * Inserts a bit into an arbitrarily long bit field. Bit 0 is assumed to be
+ * the MSB of the first byte in the buffer.
+ */
+
+static void insert_bit(UINT8 *buf, INT32 bit_num, INT32 bit)
+{
+ INT32 bit_in_byte;
+
+ bit_in_byte = 7 - (bit_num & 7);
+
+ buf[bit_num / 8] &= ~(1 << bit_in_byte);
+ buf[bit_num / 8] |= (bit << bit_in_byte);
+}
+
+/*
+ * insert_id():
+ *
+ * Inserts a 32-bit ID code into the ID bit field.
+ */
+
+static void insert_id(UINT32 id, INT32 start_bit)
+{
+ INT32 i;
+
+ for (i = 31; i >= 0; i--)
+ insert_bit(id_data, start_bit++, (id >> i) & 1);
+}
+
+/*
+ * shift():
+ *
+ * Shifts the data buffer right (towards LSB at byte 0) by 1 bit. The size of
+ * the number of bits must be specified. The bit shifted out of the LSB is
+ * returned.
+ */
+
+static int shift(UINT8 *data, INT32 num_bits)
+{
+ INT32 i;
+ int shift_out, shift_in;
+
+ /*
+ * This loop takes care of all the fully-filled bytes
+ */
+
+ shift_in = 0;
+ shift_out = 0;
+ for (i = 0; i < num_bits / 8; i++)
+ {
+ shift_out = data[i] & 1;
+ data[i] >>= 1;
+ data[i] |= (shift_in << 7);
+ shift_in = shift_out; // carry over to next element's MSB
+ }
+
+ /*
+ * Take care of the last partial byte (if there is one)
+ */
+
+ if ((num_bits & 7) != 0)
+ {
+ shift_out = (data[i] >> (8 - (num_bits & 7))) & 1;
+ data[i] >>= 1;
+ data[i] |= (shift_in << 7);
+ }
+
+ return shift_out;
+}
+
+/*
+ * int tap_read(void);
+ *
+ * Reads TDO.
+ *
+ * Returns:
+ * TDO.
+ */
+
+int model3_tap_read(void)
+{
+ return tdo;
+}
+
+/*
+ * void tap_write(int tck, int tms, int tdi, int trst);
+ *
+ * Writes to the TAP. State changes only occur on the rising edge of the clock
+ * (tck = 1.)
+ *
+ * Parameters:
+ * tck = Clock.
+ * tms = Test mode select.
+ * tdi = Serial data input. Must be 0 or 1 only!
+ * trst = Reset.
+ */
+
+void model3_tap_write(int tck, int tms, int tdi, int trst)
+{
+ if (!tck)
+ return;
+
+ state = NEXT(tms);
+
+ switch (state)
+ {
+ case 3: // Capture-DR
+
+ /*
+ * Read ASIC IDs.
+ *
+ * The ID Sequence is:
+ * - Jupiter
+ * - Mercury
+ * - Venus
+ * - Earth
+ * - Mars
+ * - Mars (again)
+ *
+ * Note that different Model 3 steps have different chip
+ * revisions, hence the different IDs returned below.
+ *
+ * On Step 1.5 and 1.0, instruction 0x0C631F8C7FFE is used to retrieve
+ * the ID codes but Step 2.0 is a little weirder. It seems to use this
+ * and either the state of the TAP after reset or other instructions
+ * to read the IDs as well. This can be emulated in one of 2 ways:
+ * Ignore the instruction and always load up the data or load the
+ * data on TAP reset and when the instruction is issued.
+ */
+
+ if (m3_step == 0x10)
+ {
+ insert_id(0x116C7057, 1 + 0 * 32);
+ insert_id(0x216C3057, 1 + 1 * 32);
+ insert_id(0x116C4057, 1 + 2 * 32);
+ insert_id(0x216C5057, 1 + 3 * 32);
+ insert_id(0x116C6057, 1 + 4 * 32 + 1);
+ insert_id(0x116C6057, 1 + 5 * 32 + 1);
+ }
+ else if (m3_step == 0x15)
+ {
+ insert_id(0x316C7057, 1 + 0 * 32);
+ insert_id(0x316C3057, 1 + 1 * 32);
+ insert_id(0x216C4057, 1 + 2 * 32); // Lost World may to use 0x016C4057
+ insert_id(0x316C5057, 1 + 3 * 32);
+ insert_id(0x216C6057, 1 + 4 * 32 + 1);
+ insert_id(0x216C6057, 1 + 5 * 32 + 1);
+ }
+ else if (m3_step >= 0x20)
+ {
+ insert_id(0x416C7057, 1 + 0 * 32);
+ insert_id(0x416C3057, 1 + 1 * 32);
+ insert_id(0x316C4057, 1 + 2 * 32);
+ insert_id(0x416C5057, 1 + 3 * 32);
+ insert_id(0x316C6057, 1 + 4 * 32 + 1);
+ insert_id(0x316C6057, 1 + 5 * 32 + 1);
+ }
+
+ break;
+
+ case 4: // Shift-DR
+
+ tdo = shift(id_data, id_size);
+ break;
+
+ case 10: // Capture-IR
+
+ /*
+ * Load lower 2 bits with 01 as per IEEE 1149.1-1990
+ */
+
+ ir = 1;
+ break;
+
+ case 11: // Shift-IR
+
+ /*
+ * Shift IR towards output and load in new data from TDI
+ */
+
+ tdo = ir & 1; // shift LSB to output
+ ir >>= 1;
+ ir |= ((UINT64) tdi << 45);
+ break;
+
+ case 15: // Update-IR
+
+ /*
+ * Latch IR (technically, this should occur on the falling edge of
+ * TCK)
+ */
+
+ ir &= U64(0x3fffffffffff);
+ current_instruction = ir;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*
+ * void tap_reset(void);
+ *
+ * Resets the TAP (simulating a power up or SCAN_RST signal.)
+ */
+
+void model3_tap_reset(void)
+{
+ id_size = 197; // 197 bits
+
+ state = 0; // test-logic/reset
+}
+
+/*
+ * void model3_machine_init(int step)
+ *
+ * step = BCD hardware rev. 0x10 for 1.0, 0x15 for 1.5, 0x20 for 2.0, etc.
+ *
+ */
+
+void model3_machine_init(int step)
+{
+ m3_step = step;
+}
+
+/*****************************************************************************/
+/* Epson RTC-72421 */
+
+static UINT8 rtc_get_reg(int reg)
+{
+ mame_system_time systime;
+
+ mame_get_current_datetime(Machine, &systime);
+
+ switch(reg)
+ {
+ case 0: // 1-second digit
+ return (systime.local_time.second % 10) & 0xf;
+
+ case 1: // 10-seconds digit
+ return (systime.local_time.second / 10) & 0x7;
+
+ case 2: // 1-minute digit
+ return (systime.local_time.minute % 10) & 0xf;
+
+ case 3: // 10-minute digit
+ return (systime.local_time.minute / 10) & 0x7;
+
+ case 4: // 1-hour digit
+ return (systime.local_time.hour % 10) & 0xf;
+
+ case 5: // 10-hours digit
+ return (systime.local_time.hour / 10) & 0x7;
+
+ case 6: // 1-day digit (days in month)
+ return (systime.local_time.mday % 10) & 0xf;
+
+ case 7: // 10-days digit
+ return (systime.local_time.mday / 10) & 0x3;
+
+ case 8: // 1-month digit
+ return ((systime.local_time.month + 1) % 10) & 0xf;
+
+ case 9: // 10-months digit
+ return ((systime.local_time.month + 1) / 10) & 0x1;
+
+ case 10: // 1-year digit
+ return (systime.local_time.year % 10) & 0xf;
+
+ case 11: // 10-years digit
+ return ((systime.local_time.year % 100) / 10) & 0xf;
+
+ case 12: // day of the week
+ return systime.local_time.weekday & 0x7;
+
+ case 13:
+ return 0;
+
+ case 14:
+ return 0;
+
+ case 15:
+ return 0;
+
+ default:
+ fatalerror("RTC-72421: Unknown reg %02X", reg);
+ return 0;
+ }
+}
+
+READ32_HANDLER(rtc72421_r)
+{
+ int reg = offset;
+ UINT32 data;
+ data = rtc_get_reg(reg) << 24;
+ data |= 0x30000; /* these bits are set to pass the battery voltage test */
+ return data;
+}
+
+WRITE32_HANDLER(rtc72421_w)
+{
+}
+
diff --git a/src/mame/machine/mspacman.c b/src/mame/machine/mspacman.c
new file mode 100644
index 00000000000..c387f86a956
--- /dev/null
+++ b/src/mame/machine/mspacman.c
@@ -0,0 +1,195 @@
+#include "driver.h"
+#include "includes/pacman.h"
+
+
+/*
+ It turns out the bootleg is the decrypted version with the checksum check
+ removed and interrupt mode changed to 1.
+
+ u7= boot 4($3000-$3fff) other than 4 bytes(checksum check and interupt mode)
+ u6= boot 6($9000-$9fff). The second half of u6 gets mirrored to the second
+ half of boot5($8800-$8fff) where it is used.
+ u5= first half of boot5($8000-$87ff)
+
+ $8000-$81ef contain 8 byte patches that are overlayed on locations in $0000-$2fff
+
+ The Ms Pacman daughter board is not activated with the mainboard. As near as I
+ can tell it requires a sequence of bytes starting at around 3176 and ending with
+ 3196. The location of the bytes doesn't seem to matter, just that those bytes
+ are executed. That sequence of bytes includes a write to 5006 so I'm using that
+ to bankswitch, but that is not accurate. The actual change is I believe at $317D.
+ The daughterboard can also be deactivated. A read to any of the several 8 byte
+ chunks listed will cause the Ms Pac roms to disappear and Pacman to show up.
+ As a result I couldn't verify what they contained. They should be the same as the
+ pacman roms, but I don't see how it could matter. These areas can be accessed by
+ the random number generator at $2a23 and the board is deactivated but is
+ immediately reactivated. So the net result is no change. The exact trigger for
+ this is not yet known.
+
+ deactivation, 8 bytes starting at:
+ $38,$3b0,$1600,$2120,$3ff0,$8000
+
+ David Widel
+ d_widel@hotmail.com
+*/
+
+
+
+
+static UINT8 decryptd(UINT8 e)
+{
+ UINT8 d;
+
+ d = (e & 0x80) >> 3;
+ d |= (e & 0x40) >> 3;
+ d |= (e & 0x20) ;
+ d |= (e & 0x10) << 2;
+ d |= (e & 0x08) >> 1;
+ d |= (e & 0x04) >> 1;
+ d |= (e & 0x02) >> 1;
+ d |= (e & 0x01) << 7;
+
+ return d;
+}
+
+static UINT32 decrypta1(UINT32 e)
+{
+ UINT32 d;
+
+ d = (e & 0x800) ;
+ d |= (e & 0x400) >> 7;
+ d |= (e & 0x200) >> 2;
+ d |= (e & 0x100) << 1;
+ d |= (e & 0x80) << 3;
+ d |= (e & 0x40) << 2;
+ d |= (e & 0x20) << 1;
+ d |= (e & 0x10) << 1;
+ d |= (e & 0x08) << 1;
+ d |= (e & 0x04) ;
+ d |= (e & 0x02) ;
+ d |= (e & 0x01) ;
+
+ return d;
+}
+
+static UINT32 decrypta2(UINT32 e)
+{
+ UINT32 d;
+ d = (e & 0x800) ;
+ d |= (e & 0x400) >> 2;
+ d |= (e & 0x200) >> 2;
+ d |= (e & 0x100) >> 3;
+ d |= (e & 0x80) << 2;
+ d |= (e & 0x40) << 4;
+ d |= (e & 0x20) << 1;
+ d |= (e & 0x10) >> 1;
+ d |= (e & 0x08) << 1;
+ d |= (e & 0x04) ;
+ d |= (e & 0x02) ;
+ d |= (e & 0x01) ;
+
+ return d;
+}
+
+
+
+
+static void mspacman_decode(void)
+{
+ int i;
+ UINT8 *RAM;
+
+
+
+ /* CPU ROMs */
+
+ RAM = memory_region(REGION_CPU1);
+ for (i = 0; i < 0x1000; i++)
+ {
+ RAM[0x10000+i] = RAM[0x0000+i];
+ RAM[0x11000+i] = RAM[0x1000+i];
+ RAM[0x12000+i] = RAM[0x2000+i];
+ RAM[0x1a000+i] = RAM[0x2000+i]; /*not needed but it's there*/
+ RAM[0x1b000+i] = RAM[0x3000+i]; /*not needed but it's there*/
+
+ }
+
+
+ for (i = 0; i < 0x1000; i++)
+ {
+ RAM[decrypta1(i)+0x13000] = decryptd(RAM[0xb000+i]); /*u7*/
+ RAM[decrypta1(i)+0x19000] = decryptd(RAM[0x9000+i]); /*u6*/
+ }
+
+ for (i = 0; i < 0x800; i++)
+ {
+ RAM[decrypta2(i)+0x18000] = decryptd(RAM[0x8000+i]); /*u5*/
+ RAM[0x18800+i] = RAM[0x19800+i];
+ }
+
+
+
+ for (i = 0; i < 8; i++)
+ {
+ RAM[0x10410+i] = RAM[0x18008+i];
+ RAM[0x108E0+i] = RAM[0x181D8+i];
+ RAM[0x10A30+i] = RAM[0x18118+i];
+ RAM[0x10BD0+i] = RAM[0x180D8+i];
+ RAM[0x10C20+i] = RAM[0x18120+i];
+ RAM[0x10E58+i] = RAM[0x18168+i];
+ RAM[0x10EA8+i] = RAM[0x18198+i];
+
+ RAM[0x11000+i] = RAM[0x18020+i];
+ RAM[0x11008+i] = RAM[0x18010+i];
+ RAM[0x11288+i] = RAM[0x18098+i];
+ RAM[0x11348+i] = RAM[0x18048+i];
+ RAM[0x11688+i] = RAM[0x18088+i];
+ RAM[0x116B0+i] = RAM[0x18188+i];
+ RAM[0x116D8+i] = RAM[0x180C8+i];
+ RAM[0x116F8+i] = RAM[0x181C8+i];
+ RAM[0x119A8+i] = RAM[0x180A8+i];
+ RAM[0x119B8+i] = RAM[0x181A8+i];
+
+ RAM[0x12060+i] = RAM[0x18148+i];
+ RAM[0x12108+i] = RAM[0x18018+i];
+ RAM[0x121A0+i] = RAM[0x181A0+i];
+ RAM[0x12298+i] = RAM[0x180A0+i];
+ RAM[0x123E0+i] = RAM[0x180E8+i];
+ RAM[0x12418+i] = RAM[0x18000+i];
+ RAM[0x12448+i] = RAM[0x18058+i];
+ RAM[0x12470+i] = RAM[0x18140+i];
+ RAM[0x12488+i] = RAM[0x18080+i];
+ RAM[0x124B0+i] = RAM[0x18180+i];
+ RAM[0x124D8+i] = RAM[0x180C0+i];
+ RAM[0x124F8+i] = RAM[0x181C0+i];
+ RAM[0x12748+i] = RAM[0x18050+i];
+ RAM[0x12780+i] = RAM[0x18090+i];
+ RAM[0x127B8+i] = RAM[0x18190+i];
+ RAM[0x12800+i] = RAM[0x18028+i];
+ RAM[0x12B20+i] = RAM[0x18100+i];
+ RAM[0x12B30+i] = RAM[0x18110+i];
+ RAM[0x12BF0+i] = RAM[0x181D0+i];
+ RAM[0x12CC0+i] = RAM[0x180D0+i];
+ RAM[0x12CD8+i] = RAM[0x180E0+i];
+ RAM[0x12CF0+i] = RAM[0x181E0+i];
+ RAM[0x12D60+i] = RAM[0x18160+i];
+ }
+}
+
+
+MACHINE_RESET( mspacman )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+ mspacman_decode();
+
+ memory_configure_bank(1, 0, 2, &RAM[0x00000], 0x10000);
+ memory_set_bank(1, 0);
+}
+
+
+WRITE8_HANDLER( mspacman_activate_rom )
+{
+ if (data==1) memory_set_bank(1, 1);
+}
+
+
diff --git a/src/mame/machine/mw8080bw.c b/src/mame/machine/mw8080bw.c
new file mode 100644
index 00000000000..24c32966bee
--- /dev/null
+++ b/src/mame/machine/mw8080bw.c
@@ -0,0 +1,125 @@
+/***************************************************************************
+
+ Midway 8080-based black and white hardware
+
+****************************************************************************/
+
+#include "driver.h"
+#include "mw8080bw.h"
+#include "machine/mb14241.h"
+
+
+/*************************************
+ *
+ * Interrupt generation
+ *
+ *************************************/
+
+static emu_timer *interrupt_timer;
+
+
+static UINT8 vpos_to_vysnc_chain_counter(int vpos)
+{
+ /* convert from a vertical position to the actual values on the vertical sync counters */
+ UINT8 counter;
+ int vblank = (vpos >= MW8080BW_VBSTART);
+
+ if (vblank)
+ {
+ counter = vpos - MW8080BW_VBSTART + MW8080BW_VCOUNTER_START_VBLANK;
+ }
+ else
+ {
+ counter = vpos + MW8080BW_VCOUNTER_START_NO_VBLANK;
+ }
+
+
+ return counter;
+}
+
+
+static int vysnc_chain_counter_to_vpos(UINT8 counter, int vblank)
+{
+ /* convert from the vertical sync counters to an actual vertical position */
+ int vpos;
+
+ if (vblank)
+ {
+ vpos = counter - MW8080BW_VCOUNTER_START_VBLANK + MW8080BW_VBSTART;
+ }
+ else
+ {
+ vpos = counter - MW8080BW_VCOUNTER_START_NO_VBLANK;
+ }
+
+ return vpos;
+}
+
+
+static TIMER_CALLBACK( mw8080bw_interrupt_callback )
+{
+ UINT8 next_counter;
+ int next_vpos;
+ int next_vblank;
+
+ /* compute vector and set the interrupt line */
+ int vpos = video_screen_get_vpos(0);
+ UINT8 counter = vpos_to_vysnc_chain_counter(vpos);
+ UINT8 vector = 0xc7 | ((counter & 0x40) >> 2) | ((~counter & 0x40) >> 3);
+ cpunum_set_input_line_and_vector(0, 0, HOLD_LINE, vector);
+
+ /* set up for next interrupt */
+ if (counter == MW8080BW_INT_TRIGGER_COUNT_1)
+ {
+ next_counter = MW8080BW_INT_TRIGGER_COUNT_2;
+ next_vblank = MW8080BW_INT_TRIGGER_VBLANK_2;
+ }
+ else
+ {
+ next_counter = MW8080BW_INT_TRIGGER_COUNT_1;
+ next_vblank = MW8080BW_INT_TRIGGER_VBLANK_1;
+ }
+
+ next_vpos = vysnc_chain_counter_to_vpos(next_counter, next_vblank);
+ timer_adjust(interrupt_timer, video_screen_get_time_until_pos(0, next_vpos, 0), 0, attotime_zero);
+}
+
+
+static void mw8080bw_create_interrupt_timer(void)
+{
+ interrupt_timer = timer_alloc(mw8080bw_interrupt_callback);
+}
+
+
+static void mw8080bw_start_interrupt_timer(void)
+{
+ int vpos = vysnc_chain_counter_to_vpos(MW8080BW_INT_TRIGGER_COUNT_1, MW8080BW_INT_TRIGGER_VBLANK_1);
+ timer_adjust(interrupt_timer, video_screen_get_time_until_pos(0, vpos, 0), 0, attotime_zero);
+}
+
+
+
+/*************************************
+ *
+ * Machine setup
+ *
+ *************************************/
+
+MACHINE_START( mw8080bw )
+{
+ mw8080bw_create_interrupt_timer();
+ mb14241_init(0);
+}
+
+
+
+/*************************************
+ *
+ * Machine reset
+ *
+ *************************************/
+
+MACHINE_RESET( mw8080bw )
+{
+ mw8080bw_start_interrupt_timer();
+}
diff --git a/src/mame/machine/n64.c b/src/mame/machine/n64.c
new file mode 100644
index 00000000000..e8ee71bd200
--- /dev/null
+++ b/src/mame/machine/n64.c
@@ -0,0 +1,1752 @@
+/* machine/n64.c - contains N64 hardware emulation shared between MAME and MESS */
+
+#include "driver.h"
+#include "cpu/mips/mips3.h"
+#include "cpu/rsp/rsp.h"
+#include "sound/custom.h"
+#include "streams.h"
+#include "includes/n64.h"
+#include "sound/dmadac.h"
+
+#ifdef LSB_FIRST
+ #define BYTE_ADDR_XOR 3
+ #define WORD_ADDR_XOR 1
+#else
+ #define BYTE_ADDR_XOR 0
+ #define WORD_ADDR_XOR 0
+#endif
+
+UINT32 *rdram;
+UINT32 *rsp_imem;
+UINT32 *rsp_dmem;
+
+//static int first_rsp = 1;
+
+// MIPS Interface
+static UINT32 mi_version;
+static UINT32 mi_interrupt = 0;
+static UINT32 mi_intr_mask = 0;
+
+extern int fb_width;
+
+void signal_rcp_interrupt(int interrupt)
+{
+ if (mi_intr_mask & interrupt)
+ {
+ mi_interrupt |= interrupt;
+
+ cpunum_set_input_line(0, INPUT_LINE_IRQ0, ASSERT_LINE);
+ }
+}
+
+void clear_rcp_interrupt(int interrupt)
+{
+ mi_interrupt &= ~interrupt;
+
+ //if (!mi_interrupt)
+ {
+ cpunum_set_input_line(0, INPUT_LINE_IRQ0, CLEAR_LINE);
+ }
+}
+
+READ32_HANDLER( n64_mi_reg_r )
+{
+ switch (offset)
+ {
+ case 0x04/4: // MI_VERSION_REG
+ return mi_version;
+
+ case 0x08/4: // MI_INTR_REG
+ return mi_interrupt;
+
+ case 0x0c/4: // MI_INTR_MASK_REG
+ return mi_intr_mask;
+
+ default:
+ logerror("mi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+
+ return 0;
+}
+
+WRITE32_HANDLER( n64_mi_reg_w )
+{
+ switch (offset)
+ {
+ case 0x00/4: // MI_INIT_MODE_REG
+ if (data & 0x0800)
+ {
+ clear_rcp_interrupt(DP_INTERRUPT);
+ }
+ break;
+
+ case 0x04/4: // MI_VERSION_REG
+ mi_version = data;
+ break;
+
+ case 0x0c/4: // MI_INTR_MASK_REG
+ {
+ if (data & 0x0001) mi_intr_mask &= ~0x1; // clear SP mask
+ if (data & 0x0002) mi_intr_mask |= 0x1; // set SP mask
+ if (data & 0x0004) mi_intr_mask &= ~0x2; // clear SI mask
+ if (data & 0x0008) mi_intr_mask |= 0x2; // set SI mask
+ if (data & 0x0010) mi_intr_mask &= ~0x4; // clear AI mask
+ if (data & 0x0020) mi_intr_mask |= 0x4; // set AI mask
+ if (data & 0x0040) mi_intr_mask &= ~0x8; // clear VI mask
+ if (data & 0x0080) mi_intr_mask |= 0x8; // set VI mask
+ if (data & 0x0100) mi_intr_mask &= ~0x10; // clear PI mask
+ if (data & 0x0200) mi_intr_mask |= 0x10; // set PI mask
+ if (data & 0x0400) mi_intr_mask &= ~0x20; // clear DP mask
+ if (data & 0x0800) mi_intr_mask |= 0x20; // set DP mask
+ break;
+ }
+
+ default:
+ logerror("mi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+}
+
+
+// RSP Interface
+
+// #define RSP_STATUS_HALT 0x00000001
+
+//static UINT32 rsp_sp_status = 0;
+//static UINT32 cpu_sp_status = SP_STATUS_HALT;
+static UINT32 sp_mem_addr;
+static UINT32 sp_dram_addr;
+static int sp_dma_length;
+static int sp_dma_count;
+static int sp_dma_skip;
+
+static UINT32 sp_semaphore;
+
+static void sp_dma(int direction)
+{
+ UINT8 *src, *dst;
+ int i;
+ //int cpu = cpu_getactivecpu();
+
+ if (sp_dma_length == 0)
+ {
+ return;
+ }
+
+ sp_dma_length++;
+
+ if ((sp_dma_length & 3) != 0)
+ {
+ //fatalerror("sp_dma (%s): sp_dma_length unaligned %08X\n", cpu ? "RSP" : "R4300i", sp_dma_length);
+ sp_dma_length = sp_dma_length & ~3;
+ //sp_dma_length = (sp_dma_length + 3) & ~3;
+
+ //sp_dma_length &= ~3;
+ }
+
+ if (sp_mem_addr & 0x3)
+ {
+ //sp_mem_addr = (sp_mem_addr + 3) & ~3;
+ sp_mem_addr = sp_mem_addr & ~3;
+ // sp_mem_addr &= ~0x3;
+ // fatalerror("sp_dma (%s): sp_mem_addr unaligned: %08X\n", cpu ? "RSP" : "R4300i", sp_mem_addr);
+ }
+ if (sp_dram_addr & 0x3)
+ {
+ //sp_dram_addr = (sp_dram_addr + 3) & ~3;
+ sp_dram_addr = sp_dram_addr & ~3;
+ // sp_dram_addr &= ~0x3;
+ // fatalerror("sp_dma (%s): sp_dram_addr unaligned: %08X\n", cpu ? "RSP" : "R4300i", sp_dram_addr);
+
+ // Diddy Kong Racing does unaligned DMA?
+ //sp_dram_addr &= ~0x3;
+ //sp_dram_addr = (sp_dram_addr + 3) & ~0x3;
+ }
+
+ if (sp_dma_count > 0)
+ {
+ fatalerror("sp_dma: dma_count = %d\n", sp_dma_count);
+ }
+ if (sp_dma_skip > 0)
+ {
+ fatalerror("sp_dma: dma_skip = %d\n", sp_dma_skip);
+ }
+
+ if ((sp_mem_addr & 0xfff) + (sp_dma_length) > 0x1000)
+ {
+ fatalerror("sp_dma: dma out of memory area: %08X, %08X\n", sp_mem_addr, sp_dma_length);
+ }
+
+ if (direction == 0) // RDRAM -> I/DMEM
+ {
+ src = (UINT8*)&rdram[sp_dram_addr / 4];
+ dst = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4];
+
+ //mame_printf_debug("sp_dma: %08X to %08X, length %08X\n", sp_dram_addr, sp_mem_addr, sp_dma_length);
+
+ for (i=0; i < sp_dma_length; i++)
+ {
+ dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)];
+ }
+
+ /*dst = (sp_mem_addr & 0x1000) ? (UINT8*)rsp_imem : (UINT8*)rsp_dmem;
+ for (i=0; i <= sp_dma_length; i++)
+ {
+ dst[BYTE4_XOR_BE(sp_mem_addr+i) & 0xfff] = src[BYTE4_XOR_BE(i)];
+ }*/
+
+ sp_mem_addr += sp_dma_length;
+ sp_dram_addr += sp_dma_length;
+ }
+ else // I/DMEM -> RDRAM
+ {
+ src = (sp_mem_addr & 0x1000) ? (UINT8*)&rsp_imem[(sp_mem_addr & 0xfff) / 4] : (UINT8*)&rsp_dmem[(sp_mem_addr & 0xfff) / 4];
+ dst = (UINT8*)&rdram[sp_dram_addr / 4];
+
+// mame_printf_debug("sp_dma: %08X to %08X, length %08X\n", sp_mem_addr, sp_dram_addr, sp_dma_length);
+
+ for (i=0; i < sp_dma_length; i++)
+ {
+ dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(i)];
+ }
+
+ /*src = (sp_mem_addr & 0x1000) ? (UINT8*)rsp_imem : (UINT8*)rsp_dmem;
+ for (i=0; i <= sp_dma_length; i++)
+ {
+ dst[BYTE4_XOR_BE(i)] = src[BYTE4_XOR_BE(sp_mem_addr+i) & 0xfff];
+ }*/
+
+ sp_mem_addr += sp_dma_length;
+ sp_dram_addr += sp_dma_length;
+ }
+}
+
+
+
+
+void sp_set_status(UINT32 status)
+{
+ if (status & 0x1)
+ {
+ //cpu_trigger(6789);
+
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_HALT);
+ //rsp_sp_status |= SP_STATUS_HALT;
+ }
+ if (status & 0x2)
+ {
+ //rsp_sp_status |= SP_STATUS_BROKE;
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_BROKE);
+
+ if (cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & RSP_STATUS_INTR_BREAK)
+ {
+ signal_rcp_interrupt(SP_INTERRUPT);
+ }
+ }
+}
+
+READ32_HANDLER( n64_sp_reg_r )
+{
+ switch (offset)
+ {
+ case 0x00/4: // SP_MEM_ADDR_REG
+ return sp_mem_addr;
+
+ case 0x04/4: // SP_DRAM_ADDR_REG
+ return sp_dram_addr;
+
+ case 0x08/4: // SP_RD_LEN_REG
+ return (sp_dma_skip << 20) | (sp_dma_count << 12) | sp_dma_length;
+
+ case 0x10/4: // SP_STATUS_REG
+ return cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR);
+
+ case 0x14/4: // SP_DMA_FULL_REG
+ return 0;
+
+ case 0x18/4: // SP_DMA_BUSY_REG
+ return 0;
+
+ case 0x1c/4: // SP_SEMAPHORE_REG
+ return sp_semaphore;
+
+ case 0x20/4: // DP_CMD_START
+ case 0x24/4: // DP_CMD_END
+ case 0x28/4: // DP_CMD_CURRENT
+ case 0x2c/4: // DP_CMD_STATUS
+ case 0x30/4: // DP_CMD_CLOCK
+ case 0x34/4: // DP_CMD_BUSY
+ case 0x38/4: // DP_CMD_PIPE_BUSY
+ case 0x3c/4: // DP_CMD_TMEM_BUSY
+ return 0;
+
+ case 0x40000/4: // PC
+ return cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_PC);
+
+ default:
+ logerror("sp_reg_r: %08X, %08X at %08X\n", offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+
+ return 0;
+}
+
+WRITE32_HANDLER( n64_sp_reg_w )
+{
+ if ((offset & 0x10000) == 0)
+ {
+ switch (offset & 0xffff)
+ {
+ case 0x00/4: // SP_MEM_ADDR_REG
+ sp_mem_addr = data;
+ break;
+
+ case 0x04/4: // SP_DRAM_ADDR_REG
+ sp_dram_addr = data & 0xffffff;
+ break;
+
+ case 0x08/4: // SP_RD_LEN_REG
+ sp_dma_length = data & 0xfff;
+ sp_dma_count = (data >> 12) & 0xff;
+ sp_dma_skip = (data >> 20) & 0xfff;
+ sp_dma(0);
+ break;
+
+ case 0x0c/4: // SP_WR_LEN_REG
+ sp_dma_length = data & 0xfff;
+ sp_dma_count = (data >> 12) & 0xff;
+ sp_dma_skip = (data >> 20) & 0xfff;
+ sp_dma(1);
+ break;
+
+ case 0x10/4: // RSP_STATUS_REG
+ {
+ // printf( "RSP_STATUS_REG Write; %08x\n", data );
+ if (data & 0x00000001) // clear halt
+ {
+ //if (first_rsp)
+ //{
+ // cpu_spinuntil_trigger(6789);
+
+ // printf( "Clearing RSP_STATUS_HALT\n" );
+ cpunum_set_input_line(1, INPUT_LINE_HALT, CLEAR_LINE);
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_HALT );
+ // RSP_STATUS &= ~RSP_STATUS_HALT;
+ //}
+ //else
+ //{
+ // first_rsp = 1;
+ //}
+ }
+ if (data & 0x00000002) // set halt
+ {
+ // printf( "Setting RSP_STATUS_HALT\n" );
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_HALT );
+ // RSP_STATUS |= RSP_STATUS_HALT;
+ }
+ if (data & 0x00000004)
+ {
+ //printf( "Clearing RSP_STATUS_BROKE\n" );
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_BROKE );
+ // RSP_STATUS &= ~RSP_STATUS_BROKE; // clear broke
+ }
+ if (data & 0x00000008) // clear interrupt
+ {
+ clear_rcp_interrupt(SP_INTERRUPT);
+ }
+ if (data & 0x00000010) // set interrupt
+ {
+ signal_rcp_interrupt(SP_INTERRUPT);
+ }
+ if (data & 0x00000020)
+ {
+ // printf( "Clearing RSP_STATUS_SSTEP\n" );
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SSTEP );
+ // RSP_STATUS &= ~RSP_STATUS_SSTEP; // clear single step
+ }
+ if (data & 0x00000040)
+ {
+ //printf( "Setting RSP_STATUS_SSTEP\n" );
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SSTEP );
+ // RSP_STATUS |= RSP_STATUS_SSTEP; // set single step
+ }
+ if (data & 0x00000080)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_INTR_BREAK );
+ // RSP_STATUS &= ~RSP_STATUS_INTR_BREAK; // clear interrupt on break
+ }
+ if (data & 0x00000100)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_INTR_BREAK );
+ // RSP_STATUS |= RSP_STATUS_INTR_BREAK; // set interrupt on break
+ }
+ if (data & 0x00000200)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL0 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL0; // clear signal 0
+ }
+ if (data & 0x00000400)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL0 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL0; // set signal 0
+ }
+ if (data & 0x00000800)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL1 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL1; // clear signal 1
+ }
+ if (data & 0x00001000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL1 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL1; // set signal 1
+ }
+ if (data & 0x00002000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL2 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL2; // clear signal 2
+ }
+ if (data & 0x00004000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL2 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL2; // set signal 2
+ }
+ if (data & 0x00008000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL3 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL3; // clear signal 3
+ }
+ if (data & 0x00010000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL3 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL3; // set signal 3
+ }
+ if (data & 0x00020000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL4 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL4; // clear signal 4
+ }
+ if (data & 0x00040000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL4 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL4; // set signal 4
+ }
+ if (data & 0x00080000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL5 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL5; // clear signal 5
+ }
+ if (data & 0x00100000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL5 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL5; // set signal 5
+ }
+ if (data & 0x00200000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL6 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL6; // clear signal 6
+ }
+ if (data & 0x00400000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL6 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL6; // set signal 6
+ }
+ if (data & 0x00800000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & ~RSP_STATUS_SIGNAL7 );
+ // RSP_STATUS &= ~RSP_STATUS_SIGNAL7; // clear signal 7
+ }
+ if (data & 0x01000000)
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_SIGNAL7 );
+ // RSP_STATUS |= RSP_STATUS_SIGNAL7; // set signal 7
+ }
+ break;
+ }
+
+ case 0x1c/4: // SP_SEMAPHORE_REG
+ sp_semaphore = data;
+ // mame_printf_debug("sp_semaphore = %08X\n", sp_semaphore);
+ break;
+
+ default:
+ logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+ }
+ else
+ {
+ switch (offset & 0xffff)
+ {
+ case 0x00/4: // SP_PC_REG
+ //printf( "Setting PC to: %08x\n", 0x04001000 | (data & 0xfff ) );
+ if( cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_NEXTPC) != 0xffffffff )
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_NEXTPC, 0x04001000 | (data & 0xfff));
+ }
+ else
+ {
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_PC, 0x04001000 | (data & 0xfff));
+ }
+ break;
+
+ default:
+ logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+ }
+}
+
+UINT32 sp_read_reg(UINT32 reg)
+{
+ switch (reg)
+ {
+ //case 4: return rsp_sp_status;
+ default: return n64_sp_reg_r(reg, 0x00000000);
+ }
+}
+
+void sp_write_reg(UINT32 reg, UINT32 data)
+{
+ switch (reg)
+ {
+ default: n64_sp_reg_w(reg, data, 0x00000000); break;
+ }
+}
+
+// RDP Interface
+UINT32 dp_start;
+UINT32 dp_end;
+UINT32 dp_current;
+UINT32 dp_status = 0;
+
+
+void dp_full_sync(void)
+{
+ signal_rcp_interrupt(DP_INTERRUPT);
+}
+
+READ32_HANDLER( n64_dp_reg_r )
+{
+ switch (offset)
+ {
+ case 0x00/4: // DP_START_REG
+ return dp_start;
+
+ case 0x04/4: // DP_END_REG
+ return dp_end;
+
+ case 0x08/4: // DP_CURRENT_REG
+ return dp_current;
+
+ case 0x0c/4: // DP_STATUS_REG
+ return dp_status;
+
+ default:
+ logerror("dp_reg_r: %08X, %08X at %08X\n", offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+
+ return 0;
+}
+
+WRITE32_HANDLER( n64_dp_reg_w )
+{
+ switch (offset)
+ {
+ case 0x00/4: // DP_START_REG
+ dp_start = data;
+ dp_current = dp_start;
+ break;
+
+ case 0x04/4: // DP_END_REG
+ dp_end = data;
+ rdp_process_list();
+ break;
+
+ case 0x0c/4: // DP_STATUS_REG
+ if (data & 0x00000001) dp_status &= ~DP_STATUS_XBUS_DMA;
+ if (data & 0x00000002) dp_status |= DP_STATUS_XBUS_DMA;
+ if (data & 0x00000004) dp_status &= ~DP_STATUS_FREEZE;
+ if (data & 0x00000008) dp_status |= DP_STATUS_FREEZE;
+ if (data & 0x00000010) dp_status &= ~DP_STATUS_FLUSH;
+ if (data & 0x00000020) dp_status |= DP_STATUS_FLUSH;
+ break;
+
+ default:
+ logerror("dp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+}
+
+
+
+// Video Interface
+static UINT32 vi_width;
+UINT32 vi_origin;
+UINT32 vi_control;
+static UINT32 vi_burst, vi_vsync, vi_hsync, vi_leap, vi_hstart, vi_vstart;
+static UINT32 vi_intr, vi_vburst, vi_xscale, vi_yscale;
+
+READ32_HANDLER( n64_vi_reg_r )
+{
+ switch (offset)
+ {
+ case 0x04/4: // VI_ORIGIN_REG
+ return vi_origin;
+
+ case 0x08/4: // VI_WIDTH_REG
+ return vi_width;
+
+ case 0x0c/4:
+ return vi_intr;
+
+ case 0x10/4: // VI_CURRENT_REG
+ return video_screen_get_vpos(0);
+
+ case 0x14/4: // VI_BURST_REG
+ return vi_burst;
+
+ case 0x18/4: // VI_V_SYNC_REG
+ return vi_vsync;
+
+ case 0x1c/4: // VI_H_SYNC_REG
+ return vi_hsync;
+
+ case 0x20/4: // VI_LEAP_REG
+ return vi_leap;
+
+ case 0x24/4: // VI_H_START_REG
+ return vi_hstart;
+
+ case 0x28/4: // VI_V_START_REG
+ return vi_vstart;
+
+ case 0x2c/4: // VI_V_BURST_REG
+ return vi_vburst;
+
+ case 0x30/4: // VI_X_SCALE_REG
+ return vi_xscale;
+
+ case 0x34/4: // VI_Y_SCALE_REG
+ return vi_yscale;
+
+ default:
+ logerror("vi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+ return 0;
+}
+
+WRITE32_HANDLER( n64_vi_reg_w )
+{
+ switch (offset)
+ {
+ case 0x00/4: // VI_CONTROL_REG
+ if ((vi_control & 0x40) != (data & 0x40))
+ {
+ screen_state *state = &Machine->screen[0];
+ rectangle visarea = state->visarea;
+ visarea.max_y = (data & 0x40) ? 479 : 239;
+ video_screen_configure(0, state->width, visarea.max_y + 1, &visarea, Machine->screen[0].refresh);
+ }
+ vi_control = data;
+ break;
+
+ case 0x04/4: // VI_ORIGIN_REG
+ vi_origin = data & 0xffffff;
+ break;
+
+ case 0x08/4: // VI_WIDTH_REG
+ if (vi_width != data && data > 0)
+ {
+ screen_state *state = &Machine->screen[0];
+ rectangle visarea = state->visarea;
+ visarea.max_x = data-1;
+ video_screen_configure(0, visarea.max_x + 1, state->height, &visarea, Machine->screen[0].refresh);
+ }
+ vi_width = data;
+ fb_width = data;
+ break;
+
+ case 0x0c/4: // VI_INTR_REG
+ vi_intr = data;
+ break;
+
+ case 0x10/4: // VI_CURRENT_REG
+ clear_rcp_interrupt(VI_INTERRUPT);
+ break;
+
+ case 0x14/4: // VI_BURST_REG
+ vi_burst = data;
+ break;
+
+ case 0x18/4: // VI_V_SYNC_REG
+ vi_vsync = data;
+ break;
+
+ case 0x1c/4: // VI_H_SYNC_REG
+ vi_hsync = data;
+ break;
+
+ case 0x20/4: // VI_LEAP_REG
+ vi_leap = data;
+ break;
+
+ case 0x24/4: // VI_H_START_REG
+ vi_hstart = data;
+ break;
+
+ case 0x28/4: // VI_V_START_REG
+ vi_vstart = data;
+ break;
+
+ case 0x2c/4: // VI_V_BURST_REG
+ vi_vburst = data;
+ break;
+
+ case 0x30/4: // VI_X_SCALE_REG
+ vi_xscale = data;
+ break;
+
+ case 0x34/4: // VI_Y_SCALE_REG
+ vi_yscale = data;
+ break;
+
+ /*
+ Uncomment this for convenient homebrew debugging
+ case 0x44/4: // TEMP DEBUG
+ printf( "E Ping: %08x\n", data );
+ break;
+ */
+
+ default:
+ logerror("vi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+}
+
+
+// Audio Interface
+static UINT32 ai_dram_addr;
+static UINT32 ai_len;
+static UINT32 ai_control = 0;
+static int ai_dacrate;
+static int ai_bitrate;
+static UINT32 ai_status = 0;
+
+static emu_timer *audio_timer;
+
+#define SOUNDBUFFER_LENGTH 0x20000
+#define AUDIO_DMA_DEPTH 2
+
+typedef struct
+{
+ UINT32 address;
+ UINT32 length;
+} AUDIO_DMA;
+
+static AUDIO_DMA audio_fifo[AUDIO_DMA_DEPTH];
+static int audio_fifo_wpos = 0;
+static int audio_fifo_rpos = 0;
+static int audio_fifo_num = 0;
+
+static void audio_fifo_push(UINT32 address, UINT32 length)
+{
+ AUDIO_DMA *current;
+ attotime period;
+
+ if (audio_fifo_num == AUDIO_DMA_DEPTH)
+ {
+ mame_printf_debug("audio_fifo_push: tried to push to full DMA FIFO!!!\n");
+ }
+
+// mame_printf_debug("fifo_push: adr %08x len %08x\n", address, length);
+
+ audio_fifo[audio_fifo_wpos].address = address;
+ audio_fifo[audio_fifo_wpos].length = length;
+ current = &audio_fifo[audio_fifo_wpos];
+
+ audio_fifo_wpos++;
+ audio_fifo_num++;
+
+ if (audio_fifo_wpos >= AUDIO_DMA_DEPTH)
+ {
+ audio_fifo_wpos = 0;
+ }
+
+ if (audio_fifo_num >= AUDIO_DMA_DEPTH)
+ {
+ ai_status |= 0x80000001; // FIFO full
+ }
+
+ // adjust the timer
+ period = attotime_mul(ATTOTIME_IN_HZ(DACRATE_NTSC), (ai_dacrate + 1) * (current->length / 4));
+ timer_adjust(audio_timer, period, 0, attotime_zero);
+}
+
+static void audio_fifo_pop(void)
+{
+ audio_fifo_rpos++;
+ audio_fifo_num--;
+
+ if (audio_fifo_num < 0)
+ {
+ fatalerror("audio_fifo_pop: FIFO underflow!\n");
+ }
+
+ if (audio_fifo_rpos >= AUDIO_DMA_DEPTH)
+ {
+ audio_fifo_rpos = 0;
+ }
+
+ if (audio_fifo_num < AUDIO_DMA_DEPTH)
+ {
+ ai_status &= ~0x80000001; // FIFO not full
+ }
+
+ ai_len = 0;
+}
+
+static AUDIO_DMA *audio_fifo_get_top(void)
+{
+ if (audio_fifo_num > 0)
+ {
+ return &audio_fifo[audio_fifo_rpos];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static void start_audio_dma(void)
+{
+ INT16 *ram = (INT16*)rdram;
+ AUDIO_DMA *current = audio_fifo_get_top();
+
+ ram = &ram[current->address/2];
+
+// mame_printf_debug("DACDMA: %x for %x bytes\n", current->address, current->length);
+
+ dmadac_transfer(0, 2, 2, 2, current->length/4, ram);
+}
+
+static TIMER_CALLBACK( audio_timer_callback )
+{
+ audio_fifo_pop();
+
+ // keep playing if there's another DMA queued
+ if (audio_fifo_get_top() != NULL)
+ {
+ start_audio_dma();
+ signal_rcp_interrupt(AI_INTERRUPT);
+ }
+}
+
+READ32_HANDLER( n64_ai_reg_r )
+{
+ switch (offset)
+ {
+ case 0x04/4: // AI_LEN_REG
+ {
+ return ai_len;
+ }
+
+ case 0x0c/4: // AI_STATUS_REG
+ return ai_status;
+
+ default:
+ logerror("ai_reg_r: %08X, %08X at %08X\n", offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+
+ return 0;
+}
+
+WRITE32_HANDLER( n64_ai_reg_w )
+{
+// UINT16 *ram = (UINT16*)rdram;
+
+ switch (offset)
+ {
+ case 0x00/4: // AI_DRAM_ADDR_REG
+// mame_printf_debug("ai_dram_addr = %08X at %08X\n", data, activecpu_get_pc());
+ ai_dram_addr = data & 0xffffff;
+ break;
+
+ case 0x04/4: // AI_LEN_REG
+// mame_printf_debug("ai_len = %08X at %08X\n", data, activecpu_get_pc());
+ ai_len = data & 0x3ffff; // Hardware v2.0 has 18 bits, v1.0 has 15 bits
+ audio_fifo_push(ai_dram_addr, ai_len);
+ break;
+
+ case 0x08/4: // AI_CONTROL_REG
+// mame_printf_debug("ai_control = %08X at %08X\n", data, activecpu_get_pc());
+ ai_control = data;
+ break;
+
+ case 0x0c/4:
+ clear_rcp_interrupt(AI_INTERRUPT);
+ break;
+
+ case 0x10/4: // AI_DACRATE_REG
+ ai_dacrate = data & 0x3fff;
+ dmadac_set_frequency(0, 2, (double)DACRATE_NTSC / (double)(ai_dacrate+1));
+ dmadac_enable(0, 2, 1);
+ break;
+
+ case 0x14/4: // AI_BITRATE_REG
+// mame_printf_debug("ai_bitrate = %08X\n", data);
+ ai_bitrate = data & 0xf;
+ break;
+
+ default:
+ logerror("ai_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+}
+
+
+// Peripheral Interface
+
+static UINT32 pi_dram_addr, pi_cart_addr;
+static UINT32 pi_first_dma = 1;
+
+READ32_HANDLER( n64_pi_reg_r )
+{
+ switch (offset)
+ {
+ case 0x00/4: // PI_DRAM_ADDR_REG
+ return pi_dram_addr;
+
+ case 0x04/4: // PI_CART_ADDR_REG
+ return pi_cart_addr;
+
+ case 0x10/4: // PI_STATUS_REG
+ return 0;
+
+ default:
+ logerror("pi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+ return 0;
+}
+
+WRITE32_HANDLER( n64_pi_reg_w )
+{
+ switch (offset)
+ {
+ case 0x00/4: // PI_DRAM_ADDR_REG
+ {
+ pi_dram_addr = data;
+ break;
+ }
+
+ case 0x04/4: // PI_CART_ADDR_REG
+ {
+ pi_cart_addr = data;
+ break;
+ }
+
+ case 0x08/4: // PI_RD_LEN_REG
+ {
+ int i;
+ UINT32 dma_length = (data + 1);
+
+ /*if (dma_length & 3)
+ {
+ dma_length = (dma_length + 3) & ~3;
+ }*/
+
+ //mame_printf_debug("PI DMA: %08X to %08X, length %08X\n", pi_dram_addr, pi_cart_addr, dma_length);
+
+ if (pi_dram_addr != 0xffffffff)
+ {
+ for (i=0; i < dma_length; i++)
+ {
+ UINT8 b = program_read_byte_32be(pi_dram_addr);
+ program_write_byte_32be(pi_cart_addr, b);
+ pi_cart_addr += 1;
+ pi_dram_addr += 1;
+ }
+ }
+
+ signal_rcp_interrupt(PI_INTERRUPT);
+ break;
+ }
+
+ case 0x0c/4: // PI_WR_LEN_REG
+ {
+ int i;
+ UINT32 dma_length = (data + 1);
+
+ /*if (dma_length & 3)
+ {
+ dma_length = (dma_length + 3) & ~3;
+ }*/
+
+ //mame_printf_debug("PI DMA: %08X to %08X, length %08X\n", pi_cart_addr, pi_dram_addr, dma_length);
+
+ if (pi_dram_addr != 0xffffffff)
+ {
+ for (i=0; i < dma_length; i++)
+ {
+ /*UINT32 d = program_read_dword_32be(pi_cart_addr);
+ program_write_dword_32be(pi_dram_addr, d);
+ pi_cart_addr += 4;
+ pi_dram_addr += 4;*/
+
+ UINT8 b = program_read_byte_32be(pi_cart_addr);
+ program_write_byte_32be(pi_dram_addr, b);
+ pi_cart_addr += 1;
+ pi_dram_addr += 1;
+ }
+ }
+ signal_rcp_interrupt(PI_INTERRUPT);
+
+ if (pi_first_dma)
+ {
+ // TODO: CIC-6105 has different address...
+ program_write_dword_32be(0x00000318, 0x400000);
+ program_write_dword_32be(0x000003f0, 0x800000);
+ pi_first_dma = 0;
+ }
+
+ break;
+ }
+
+ case 0x10/4: // PI_STATUS_REG
+ {
+ if (data & 0x2)
+ {
+ clear_rcp_interrupt(PI_INTERRUPT);
+ }
+ break;
+ }
+
+ default:
+ logerror("pi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+}
+
+// RDRAM Interface
+READ32_HANDLER( n64_ri_reg_r )
+{
+ switch (offset)
+ {
+ default:
+ logerror("ri_reg_r: %08X, %08X at %08X\n", offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+
+ return 0;
+}
+
+WRITE32_HANDLER( n64_ri_reg_w )
+{
+ switch (offset)
+ {
+ default:
+ logerror("ri_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, activecpu_get_pc());
+ break;
+ }
+}
+
+// Serial Interface
+static UINT8 pif_ram[0x40];
+static UINT8 pif_cmd[0x40];
+UINT32 si_dram_addr = 0;
+UINT32 si_pif_addr = 0;
+UINT32 si_status = 0;
+
+static UINT8 eeprom[512];
+static UINT8 mempack[0x8000];
+
+static UINT8 calc_mempack_crc(UINT8 *buffer, int length)
+{
+ int i, j;
+ UINT32 crc = 0;
+ UINT32 temp2 = 0;
+
+ for (i=0; i <= length; i++)
+ {
+ for (j=7; j >= 0; j--)
+ {
+ if ((crc & 0x80) != 0)
+ {
+ temp2 = 0x85;
+ }
+ else
+ {
+ temp2 = 0;
+ }
+
+ crc <<= 1;
+
+ if (i == length)
+ {
+ crc &= 0xff;
+ }
+ else
+ {
+ if ((buffer[i] & (1 << j)) != 0)
+ {
+ crc |= 0x1;
+ }
+ }
+
+ crc ^= temp2;
+ }
+ }
+
+ return crc;
+}
+
+static int pif_channel_handle_command(int channel, int slength, UINT8 *sdata, int rlength, UINT8 *rdata)
+{
+ int i;
+ UINT8 command = sdata[0];
+
+ switch (command)
+ {
+ case 0x00: // Read status
+ {
+ if (slength != 1 || rlength != 3)
+ {
+ // osd_die("handle_pif: read status (bytes to send %d, bytes to receive %d)\n", bytes_to_send, bytes_to_recv);
+ }
+
+ switch (channel)
+ {
+ case 0:
+ {
+ rdata[0] = 0x05;
+ rdata[1] = 0x00;
+ rdata[2] = 0x02;
+ return 0;
+ }
+ case 1:
+ case 2:
+ case 3:
+ {
+ // not connected
+ return 1;
+ }
+ case 4:
+ {
+ rdata[0] = 0x00;
+ rdata[1] = 0x80;
+ rdata[2] = 0x00;
+ //rdata[0] = 0xff;
+ //rdata[1] = 0xff;
+ //rdata[2] = 0xff;
+
+ return 1;
+ }
+ case 5:
+ {
+ mame_printf_debug("EEPROM2? read status\n");
+ return 1;
+ }
+ }
+
+ break;
+ }
+
+ case 0x01: // Read button values
+ {
+ UINT16 buttons = 0;
+ INT8 x = 0, y = 0;
+ if (slength != 1 || rlength != 4)
+ {
+ fatalerror("handle_pif: read button values (bytes to send %d, bytes to receive %d)\n", slength, rlength);
+ }
+
+ switch (channel)
+ {
+ case 0:
+ {
+ buttons = readinputport((channel*3) + 0);
+ x = readinputport((channel*3) + 1) - 128;
+ y = readinputport((channel*3) + 2) - 128;
+
+ rdata[0] = (buttons >> 8) & 0xff;
+ rdata[1] = (buttons >> 0) & 0xff;
+ rdata[2] = (UINT8)(x);
+ rdata[3] = (UINT8)(y);
+ return 0;
+ }
+ case 1:
+ case 2:
+ case 3:
+ {
+ // not connected
+ return 1;
+ }
+ }
+
+ break;
+ }
+
+ case 0x02:
+ {
+ UINT32 address, checksum;
+
+ /*mame_printf_debug("Read from mempack, rlength = %d, slength = %d\n", rlength, slength);
+ for (i=0; i < slength; i++)
+ {
+ mame_printf_debug("%02X ", sdata[i]);
+ }
+ mame_printf_debug("\n");*/
+
+ address = (sdata[1] << 8) | (sdata[2]);
+ checksum = address & 0x1f;
+ address &= ~0x1f;
+
+ if (address == 0x400)
+ {
+ for (i=0; i < rlength-1; i++)
+ {
+ rdata[i] = 0x00;
+ }
+
+ rdata[rlength-1] = calc_mempack_crc(rdata, rlength-1);
+ // mame_printf_debug("CRC = %02X\n", rdata[rlength-1]);
+ }
+ else if (address < 0x7fe0)
+ {
+ for (i=0; i < rlength-1; i++)
+ {
+ rdata[i] = mempack[address+i];
+ }
+
+ rdata[rlength-1] = calc_mempack_crc(rdata, rlength-1);
+ // mame_printf_debug("CRC = %02X\n", rdata[rlength-1]);
+ }
+ return 1;
+ }
+ case 0x03:
+ {
+ UINT32 address, checksum;
+ int i;
+ /*mame_printf_debug("Write to mempack, rlength = %d, slength = %d\n", rlength, slength);
+ for (i=0; i < slength; i++)
+ {
+ mame_printf_debug("%02X ", sdata[i]);
+ }
+ mame_printf_debug("\n");*/
+
+ address = (sdata[1] << 8) | (sdata[2]);
+ checksum = address & 0x1f;
+ address &= ~0x1f;
+
+ if (address == 0x8000)
+ {
+
+ }
+ else
+ {
+ for (i=3; i < slength; i++)
+ {
+ mempack[address++] = sdata[i];
+ }
+ }
+
+ rdata[0] = calc_mempack_crc(&sdata[3], slength-3);
+
+ return 1;
+ }
+
+ case 0x04: // Read from EEPROM
+ {
+ UINT8 block_offset;
+
+ if (channel != 4)
+ {
+ //fatalerror("Tried to write to EEPROM on channel %d\n", channel);
+ return 1;
+ }
+
+ if (slength != 2 || rlength != 8)
+ {
+ fatalerror("handle_pif: write EEPROM (bytes to send %d, bytes to receive %d)\n", slength, rlength);
+ }
+
+ block_offset = sdata[1] * 8;
+
+ for (i=0; i < 8; i++)
+ {
+ rdata[i] = eeprom[block_offset+i];
+ }
+
+ return 1;
+ }
+
+ case 0x05: // Write to EEPROM
+ {
+ UINT8 block_offset;
+
+ if (channel != 4)
+ {
+ //fatalerror("Tried to write to EEPROM on channel %d\n", channel);
+ return 1;
+ }
+
+ if (slength != 10 || rlength != 1)
+ {
+ fatalerror("handle_pif: write EEPROM (bytes to send %d, bytes to receive %d)\n", slength, rlength);
+ }
+
+ block_offset = sdata[1] * 8;
+ //mame_printf_debug("Write EEPROM: offset %02X: ", block_offset);
+ for (i=0; i < 8; i++)
+ {
+ //mame_printf_debug("%02X ", sdata[2+i]);
+ eeprom[block_offset+i] = sdata[2+i];
+ }
+ //mame_printf_debug("\n");
+
+ rdata[0] = 0;
+
+ return 1;
+ }
+
+ case 0xff: // reset
+ {
+ rdata[0] = 0xff;
+ rdata[1] = 0xff;
+ rdata[2] = 0xff;
+ return 0;
+ }
+
+ default:
+ {
+ mame_printf_debug("handle_pif: unknown/unimplemented command %02X\n", command);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static void handle_pif(void)
+{
+ int j;
+
+ /*
+ {
+ int i;
+ for (i=0; i < 8; i++)
+ {
+ int j = i * 8;
+ mame_printf_debug("PIFCMD%d: %02X %02X %02X %02X %02X %02X %02X %02X\n", i, pif_cmd[j], pif_cmd[j+1], pif_cmd[j+2], pif_cmd[j+3], pif_cmd[j+4], pif_cmd[j+5], pif_cmd[j+6], pif_cmd[j+7]);
+ }
+ mame_printf_debug("\n");
+ }
+ */
+
+ if (pif_cmd[0x3f] == 0x1) // only handle the command if the last byte is 1
+ {
+ int channel = 0;
+ int end = 0;
+ int cmd_ptr = 0;
+
+ while (cmd_ptr < 0x3f && !end)
+ {
+ UINT8 bytes_to_send;
+ INT8 bytes_to_recv;
+
+ bytes_to_send = pif_cmd[cmd_ptr++];
+
+ if (bytes_to_send == 0xfe)
+ {
+ end = 1;
+ }
+ else if (bytes_to_send == 0xff)
+ {
+ // do nothing
+ }
+ else
+ {
+ if (bytes_to_send > 0 && (bytes_to_send & 0xc0) == 0)
+ {
+ int res;
+ UINT8 recv_buffer[0x40];
+ UINT8 send_buffer[0x40];
+
+ bytes_to_recv = pif_cmd[cmd_ptr++];
+
+ for (j=0; j < bytes_to_send; j++)
+ {
+ send_buffer[j] = pif_cmd[cmd_ptr++];
+ }
+
+ res = pif_channel_handle_command(channel, bytes_to_send, send_buffer, bytes_to_recv, recv_buffer);
+
+ if (res == 0)
+ {
+ if (cmd_ptr + bytes_to_recv > 0x3f)
+ {
+ fatalerror("cmd_ptr overflow\n");
+ }
+ for (j=0; j < bytes_to_recv; j++)
+ {
+ pif_ram[cmd_ptr++] = recv_buffer[j];
+ }
+ }
+ else if (res == 1)
+ {
+ int offset = 0;//bytes_to_send;
+ pif_ram[cmd_ptr-offset-2] |= 0x80;
+ }
+ }
+
+ channel++;
+ }
+ }
+
+ pif_ram[0x3f] = 0;
+ }
+
+ /*
+ {
+ int i;
+ for (i=0; i < 8; i++)
+ {
+ int j = i * 8;
+ mame_printf_debug("PIFRAM%d: %02X %02X %02X %02X %02X %02X %02X %02X\n", i, pif_ram[j], pif_ram[j+1], pif_ram[j+2], pif_ram[j+3], pif_ram[j+4], pif_ram[j+5], pif_ram[j+6], pif_ram[j+7]);
+ }
+ mame_printf_debug("\n");
+ }
+ */
+}
+
+static void pif_dma(int direction)
+{
+ int i;
+ UINT32 *src, *dst;
+
+ if (si_dram_addr & 0x3)
+ {
+ fatalerror("pif_dma: si_dram_addr unaligned: %08X\n", si_dram_addr);
+ }
+
+ if (direction) // RDRAM -> PIF RAM
+ {
+ src = (UINT32*)&rdram[(si_dram_addr & 0x1fffffff) / 4];
+
+ for (i=0; i < 64; i+=4)
+ {
+ UINT32 d = *src++;
+ pif_ram[i+0] = (d >> 24) & 0xff;
+ pif_ram[i+1] = (d >> 16) & 0xff;
+ pif_ram[i+2] = (d >> 8) & 0xff;
+ pif_ram[i+3] = (d >> 0) & 0xff;
+ }
+
+ memcpy(pif_cmd, pif_ram, 0x40);
+ }
+ else // PIF RAM -> RDRAM
+ {
+ handle_pif();
+
+ dst = (UINT32*)&rdram[(si_dram_addr & 0x1fffffff) / 4];
+
+ for (i=0; i < 64; i+=4)
+ {
+ UINT32 d = 0;
+ d |= pif_ram[i+0] << 24;
+ d |= pif_ram[i+1] << 16;
+ d |= pif_ram[i+2] << 8;
+ d |= pif_ram[i+3] << 0;
+
+ *dst++ = d;
+ }
+ }
+
+ si_status |= 0x1000;
+ signal_rcp_interrupt(SI_INTERRUPT);
+}
+
+READ32_HANDLER( n64_si_reg_r )
+{
+ switch (offset)
+ {
+ case 0x00/4: // SI_DRAM_ADDR_REG
+ return si_dram_addr;
+
+ case 0x18/4: // SI_STATUS_REG
+ return si_status;
+ }
+ return 0;
+}
+
+WRITE32_HANDLER( n64_si_reg_w )
+{
+ switch (offset)
+ {
+ case 0x00/4: // SI_DRAM_ADDR_REG
+ si_dram_addr = data;
+ // mame_printf_debug("si_dram_addr = %08X\n", si_dram_addr);
+ break;
+
+ case 0x04/4: // SI_PIF_ADDR_RD64B_REG
+ // PIF RAM -> RDRAM
+ si_pif_addr = data;
+ pif_dma(0);
+ break;
+
+ case 0x10/4: // SI_PIF_ADDR_WR64B_REG
+ // RDRAM -> PIF RAM
+ si_pif_addr = data;
+ pif_dma(1);
+ break;
+
+ case 0x18/4: // SI_STATUS_REG
+ si_status &= ~0x1000;
+ clear_rcp_interrupt(SI_INTERRUPT);
+ break;
+
+ default:
+ logerror("si_reg_w: %08X, %08X, %08X\n", data, offset, mem_mask);
+ break;
+ }
+}
+
+UINT32 cic_status = 0x00000000;
+
+READ32_HANDLER( n64_pif_ram_r )
+{
+ /*mame_printf_debug( "pif_ram_r: %08X, %08X = %08X\n", offset << 2, mem_mask, ( ( pif_ram[offset*4+0] << 24 ) | ( pif_ram[offset*4+1] << 16 ) | ( pif_ram[offset*4+2] << 8 ) | ( pif_ram[offset*4+3] << 0 ) ) & ~mem_mask );*/
+ if( offset == ( 0x24 / 4 ) )
+ {
+ cic_status = 0x00000080;
+ }
+ if( offset == ( 0x3C / 4 ) )
+ {
+ return cic_status;
+ }
+ return ( ( pif_ram[offset*4+0] << 24 ) | ( pif_ram[offset*4+1] << 16 ) | ( pif_ram[offset*4+2] << 8 ) | ( pif_ram[offset*4+3] << 0 ) ) & ~mem_mask;
+}
+
+WRITE32_HANDLER( n64_pif_ram_w )
+{
+ /*mame_printf_debug("pif_ram_w: %08X, %08X, %08X\n", data, offset << 4, mem_mask);*/
+ /*
+ if( (~mem_mask) & 0xff000000 )
+ {
+ pif_ram[offset*4+0] = ( data >> 24 ) & 0x000000ff;
+ }
+ if( (~mem_mask) & 0x00ff0000 )
+ {
+ pif_ram[offset*4+1] = ( data >> 16 ) & 0x000000ff;
+ }
+ if( (~mem_mask) & 0x0000ff00 )
+ {
+ pif_ram[offset*4+2] = ( data >> 8 ) & 0x000000ff;
+ }
+ if( (~mem_mask) & 0x000000ff )
+ {
+ pif_ram[offset*4+3] = ( data >> 0 ) & 0x000000ff;
+ }
+ */
+
+ signal_rcp_interrupt(SI_INTERRUPT);
+}
+
+//static UINT16 crc_seed = 0x3f;
+
+void n64_machine_reset(void)
+{
+ int i;
+ //UINT32 *pif_rom = (UINT32*)memory_region(REGION_USER1);
+ UINT32 *cart = (UINT32*)memory_region(REGION_USER2);
+ UINT64 boot_checksum;
+
+ cpunum_set_info_int(0, CPUINFO_INT_MIPS3_DRC_OPTIONS, MIPS3DRC_FASTEST_OPTIONS + MIPS3DRC_STRICT_VERIFY);
+
+ /* configure fast RAM regions for DRC */
+ cpunum_set_info_int(0, CPUINFO_INT_MIPS3_FASTRAM_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_MIPS3_FASTRAM_START, 0x00000000);
+ cpunum_set_info_int(0, CPUINFO_INT_MIPS3_FASTRAM_END, 0x007fffff);
+ cpunum_set_info_ptr(0, CPUINFO_PTR_MIPS3_FASTRAM_BASE, rdram);
+ cpunum_set_info_int(0, CPUINFO_INT_MIPS3_FASTRAM_READONLY, 0);
+
+ audio_timer = timer_alloc(audio_timer_callback);
+ timer_adjust(audio_timer, attotime_never, 0, attotime_never);
+
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+
+ // bootcode differs between CIC-chips, so we can use its checksum to detect the CIC-chip
+ boot_checksum = 0;
+ for (i=0x40; i < 0x1000; i+=4)
+ {
+ boot_checksum += cart[i/4]+i;
+ }
+
+ if (boot_checksum == U64(0x000000d057e84864))
+ {
+ // CIC-NUS-6101
+ mame_printf_debug("CIC-NUS-6101 detected\n");
+ // crc_seed = 0x3f;
+ pif_ram[0x24] = 0x00;
+ pif_ram[0x25] = 0x04;
+ pif_ram[0x26] = 0x3f;
+ pif_ram[0x27] = 0x3f;
+ }
+ else if (boot_checksum == U64(0x000000d6499e376b))
+ {
+ // CIC-NUS-6103
+ mame_printf_debug("CIC-NUS-6103 detected\n");
+ // crc_seed = 0x78;
+ pif_ram[0x24] = 0x00;
+ pif_ram[0x25] = 0x04;
+ pif_ram[0x26] = 0x78;
+ pif_ram[0x27] = 0x78;
+ }
+ else if (boot_checksum == U64(0x0000011a4a1604b6))
+ {
+ // CIC-NUS-6105
+ mame_printf_debug("CIC-NUS-6105 detected\n");
+ // crc_seed = 0x91;
+
+ // first_rsp = 0;
+ pif_ram[0x24] = 0x00;
+ pif_ram[0x25] = 0x04;
+ pif_ram[0x26] = 0x91;
+ pif_ram[0x27] = 0x91;
+ }
+ else if (boot_checksum == U64(0x000000d6d5de4ba0))
+ {
+ // CIC-NUS-6106
+ mame_printf_debug("CIC-NUS-6106 detected\n");
+ // crc_seed = 0x85;
+ pif_ram[0x24] = 0x00;
+ pif_ram[0x25] = 0x04;
+ pif_ram[0x26] = 0x85;
+ pif_ram[0x27] = 0x85;
+ }
+ else
+ {
+ mame_printf_debug("Unknown BootCode Checksum %08X%08X\n", (UINT32)(boot_checksum>>32),(UINT32)(boot_checksum));
+ }
+
+ /*
+ // bootcode differs between CIC-chips, so we can use its checksum to detect the CIC-chip
+ boot_checksum = 0;
+ for (i=0x40; i < 0x1000; i+=4)
+ {
+ boot_checksum += cart[i/4]+i;
+ }
+
+ if (boot_checksum == U64(0x000000d057e84864))
+ {
+ // CIC-NUS-6101
+ mame_printf_debug("CIC-NUS-6101 detected\n");
+ crc_seed = 0x3f;
+ }
+ else if (boot_checksum == U64(0x000000d6499e376b))
+ {
+ // CIC-NUS-6103
+ mame_printf_debug("CIC-NUS-6103 detected\n");
+ crc_seed = 0x78;
+ }
+ else if (boot_checksum == U64(0x0000011a4a1604b6))
+ {
+ // CIC-NUS-6105
+ mame_printf_debug("CIC-NUS-6105 detected\n");
+ crc_seed = 0x91;
+
+ first_rsp = 0;
+ }
+ else if (boot_checksum == U64(0x000000d6d5de4ba0))
+ {
+ // CIC-NUS-6106
+ mame_printf_debug("CIC-NUS-6106 detected\n");
+ crc_seed = 0x85;
+ }
+ else
+ {
+ mame_printf_debug("Unknown BootCode Checksum %08X%08X\n", (UINT32)(boot_checksum>>32),(UINT32)(boot_checksum));
+ }
+
+ // The PIF Boot ROM is not dumped, the following code simulates it
+
+ // clear all registers
+ for (i=1; i < 32; i++)
+ {
+ *pif_rom++ = 0x00000000 | 0 << 21 | 0 << 16 | i << 11 | 0x20; // ADD ri, r0, r0
+ }
+
+ // R20 <- 0x00000001
+ *pif_rom++ = 0x34000000 | 20 << 16 | 0x0001; // ORI r20, r0, 0x0001
+
+ // R22 <- 0x0000003F
+ *pif_rom++ = 0x34000000 | 22 << 16 | crc_seed; // ORI r22, r0, 0x003f
+
+ // R29 <- 0xA4001FF0
+ *pif_rom++ = 0x3c000000 | 29 << 16 | 0xa400; // LUI r29, 0xa400
+ *pif_rom++ = 0x34000000 | 29 << 21 | 29 << 16 | 0x1ff0; // ORI r29, r29, 0x1ff0
+
+ // clear CP0 registers
+ for (i=0; i < 32; i++)
+ {
+ *pif_rom++ = 0x40000000 | 4 << 21 | 0 << 16 | i << 11; // MTC2 cp0ri, r0
+ }
+
+ // Random <- 0x0000001F
+ *pif_rom++ = 0x34000000 | 1 << 16 | 0x001f;
+ *pif_rom++ = 0x40000000 | 4 << 21 | 1 << 16 | 1 << 11; // MTC2 Random, r1
+
+ // Status <- 0x70400004
+ *pif_rom++ = 0x3c000000 | 1 << 16 | 0x7040; // LUI r1, 0x7040
+ *pif_rom++ = 0x34000000 | 1 << 21 | 1 << 16 | 0x0004; // ORI r1, r1, 0x0004
+ *pif_rom++ = 0x40000000 | 4 << 21 | 1 << 16 | 12 << 11; // MTC2 Status, r1
+
+ // PRId <- 0x00000B00
+ *pif_rom++ = 0x34000000 | 1 << 16 | 0x0b00; // ORI r1, r0, 0x0b00
+ *pif_rom++ = 0x40000000 | 4 << 21 | 1 << 16 | 15 << 11; // MTC2 PRId, r1
+
+ // Config <- 0x0006E463
+ *pif_rom++ = 0x3c000000 | 1 << 16 | 0x0006; // LUI r1, 0x0006
+ *pif_rom++ = 0x34000000 | 1 << 21 | 1 << 16 | 0xe463; // ORI r1, r1, 0xe463
+ *pif_rom++ = 0x40000000 | 4 << 21 | 1 << 16 | 16 << 11; // MTC2 Config, r1
+
+ // (0xa4300004) <- 0x01010101
+ *pif_rom++ = 0x3c000000 | 1 << 16 | 0x0101; // LUI r1, 0x0101
+ *pif_rom++ = 0x34000000 | 1 << 21 | 1 << 16 | 0x0101; // ORI r1, r1, 0x0101
+ *pif_rom++ = 0x3c000000 | 3 << 16 | 0xa430; // LUI r3, 0xa430
+ *pif_rom++ = 0xac000000 | 3 << 21 | 1 << 16 | 0x0004; // SW r1, 0x0004(r3)
+
+ // Copy 0xb0000000...1fff -> 0xa4000000...1fff
+ *pif_rom++ = 0x34000000 | 3 << 16 | 0x0400; // ORI r3, r0, 0x0400
+ *pif_rom++ = 0x3c000000 | 4 << 16 | 0xb000; // LUI r4, 0xb000
+ *pif_rom++ = 0x3c000000 | 5 << 16 | 0xa400; // LUI r5, 0xa400
+ *pif_rom++ = 0x8c000000 | 4 << 21 | 1 << 16; // LW r1, 0x0000(r4)
+ *pif_rom++ = 0xac000000 | 5 << 21 | 1 << 16; // SW r1, 0x0000(r5)
+ *pif_rom++ = 0x20000000 | 4 << 21 | 4 << 16 | 0x0004; // ADDI r4, r4, 0x0004
+ *pif_rom++ = 0x20000000 | 5 << 21 | 5 << 16 | 0x0004; // ADDI r5, r5, 0x0004
+ *pif_rom++ = 0x20000000 | 3 << 21 | 3 << 16 | 0xffff; // ADDI r3, r3, -1
+ *pif_rom++ = 0x14000000 | 3 << 21 | 0 << 16 | 0xfffa; // BNE r3, r0, -6
+ *pif_rom++ = 0x00000000;
+
+ *pif_rom++ = 0x34000000 | 3 << 16 | 0x0000; // ORI r3, r0, 0x0000
+ *pif_rom++ = 0x34000000 | 4 << 16 | 0x0000; // ORI r4, r0, 0x0000
+ *pif_rom++ = 0x34000000 | 5 << 16 | 0x0000; // ORI r5, r0, 0x0000
+
+ // Zelda and DK64 need these
+ *pif_rom++ = 0x3c000000 | 9 << 16 | 0xa400;
+ *pif_rom++ = 0x34000000 | 9 << 21 | 9 << 16 | 0x1ff0;
+ *pif_rom++ = 0x3c000000 | 11 << 16 | 0xa400;
+ *pif_rom++ = 0x3c000000 | 31 << 16 | 0xffff;
+ *pif_rom++ = 0x34000000 | 31 << 21 | 31 << 16 | 0xffff;
+
+ *pif_rom++ = 0x3c000000 | 1 << 16 | 0xa400; // LUI r1, 0xa400
+ *pif_rom++ = 0x34000000 | 1 << 21 | 1 << 16 | 0x0040; // ORI r1, r1, 0x0040
+ *pif_rom++ = 0x00000000 | 1 << 21 | 0x8; // JR r1
+ */
+}
diff --git a/src/mame/machine/namco50.c b/src/mame/machine/namco50.c
new file mode 100644
index 00000000000..bd519a73594
--- /dev/null
+++ b/src/mame/machine/namco50.c
@@ -0,0 +1,338 @@
+/***************************************************************************
+
+Namco 50XX
+
+This custom chip is a Fujitsu MB8842 MCU programmed to act as a protection
+device. It keeps track of the players scores, and checks if a high score has
+been obtained or bonus lives should be awarded. The main CPU has a range of
+commands to increment/decrement the score by various fixed amounts.
+
+The device is used to its full potential only by Bosconian; Xevious uses it
+too, but only to do a protection check on startup.
+
+CMD = command from main CPU
+ANS = answer to main CPU
+
+The chip reads/writes the I/O ports when the /IRQ is pulled down. Pin 21
+determines whether a read or write should happen (1=R, 0=W).
+
+ +------+
+ EXTAL|1 28|Vcc
+ XTAL|2 27|CMD7
+/RESET|3 26|CMD6
+ ANS0|4 25|CMD5
+ ANS1|5 24|CMD4
+ ANS2|6 23|/IRQ
+ ANS3|7 22|n.c.
+ ANS4|8 21|R/W
+ ANS5|9 20|n.c.
+ ANS6|10 19|n.c.
+ ANS7|11 18|n.c.
+ CMD0|12 17|n.c.
+ CMD1|13 16|CMD3
+ GND|14 15|CMD2
+ +------+
+
+
+
+Commands:
+
+0x = nop
+
+1x = reset scores
+
+2x = set first bonus score (followed by 3 bytes)
+
+3x = set interval bonus score (followed by 3 bytes)
+
+4x = ?
+
+5x = set high score (followed by 3 bytes)
+
+60 = switch to player 1
+68 = switch to player 2
+
+70 = switch to increment score
+7x = switch to decrement score
+
+score increments/decrements:
+
+80 = 5
+81 = 10
+82 = 15
+83 = 20
+84 = 25
+85 = 30
+86 = 40
+87 = 50
+88 = 60
+89 = 70
+8A = 80
+8B = 90
+8C = 100
+8D = 200
+8E = 300
+8F = 500
+
+9x same as 8x but *10
+Ax same as 8x but *100
+
+B0h = 10
+B1h = 20
+B2h = 30
+B3h = 40
+B4h = 50
+B5h = 60
+B6h = 80
+B7h = 100
+B8h = 120
+B9h = 140
+BAh = 160
+BBh = 180
+BCh = 200
+BDh = 400
+BEh = 600
+BFh = 1000
+
+Cx same as Bx but *10
+Dx same as Bx but *100
+
+E0 = 15
+E1 = 30
+E2 = 45
+E3 = 60
+E4 = 75
+E5 = 90
+E6 = 120
+E7 = 150
+E8 = 180
+E9 = 210
+EA = 240
+EB = 270
+EC = 300
+ED = 600
+EE = 900
+EF = 1500
+
+Fx same as Ex but *10
+
+
+When reading, the score for the currently selected player is returned. The first
+byte also contains flags.
+
+Byte 0: BCD Score (fs------) and flags
+Byte 1: BCD Score (--ss----)
+Byte 2: BCD Score (----ss--)
+Byte 3: BCD Score (------ss)
+
+Flags: 80=high score, 40=first bonus, 20=interval bonus, 10=?
+
+***************************************************************************/
+
+#include "driver.h"
+#include "namco50.h"
+#include "cpu/mb88xx/mb88xx.h"
+
+
+static UINT8 latched_cmd[2];
+static UINT8 latched_rw[2];
+static UINT8 portO[2];
+
+
+static TIMER_CALLBACK( namco_50xx_latch_callback )
+{
+ latched_cmd[0] = param;
+ latched_rw[0] = 1;
+}
+
+static TIMER_CALLBACK( namco_50xx_2_latch_callback )
+{
+ latched_cmd[1] = param;
+ latched_rw[1] = 1;
+}
+
+
+static TIMER_CALLBACK( namco_50xx_readrequest_callback )
+{
+ latched_rw[0] = 0;
+}
+
+static TIMER_CALLBACK( namco_50xx_2_readrequest_callback )
+{
+ latched_rw[1] = 0;
+}
+
+
+static READ8_HANDLER( namco_50xx_K_r )
+{
+ return latched_cmd[0] >> 4;
+}
+
+static READ8_HANDLER( namco_50xx_R0_r )
+{
+ return latched_cmd[0] & 0x0f;
+}
+
+static READ8_HANDLER( namco_50xx_R2_r )
+{
+ return latched_rw[0] & 1;
+}
+
+
+
+static READ8_HANDLER( namco_50xx_2_K_r )
+{
+ return latched_cmd[1] >> 4;
+}
+
+static READ8_HANDLER( namco_50xx_2_R0_r )
+{
+ return latched_cmd[1] & 0x0f;
+}
+
+static READ8_HANDLER( namco_50xx_2_R2_r )
+{
+ return latched_rw[1] & 1;
+}
+
+
+static WRITE8_HANDLER( namco_50xx_O_w )
+{
+ UINT8 out = (data & 0x0f);
+ if (data & 0x10)
+ portO[0] = (portO[0] & 0x0f) | (out << 4);
+ else
+ portO[0] = (portO[0] & 0xf0) | (out);
+}
+
+
+
+static WRITE8_HANDLER( namco_50xx_2_O_w )
+{
+ UINT8 out = (data & 0x0f);
+ if (data & 0x10)
+ portO[1] = (portO[1] & 0x0f) | (out << 4);
+ else
+ portO[1] = (portO[1] & 0xf0) | (out);
+}
+
+
+
+ADDRESS_MAP_START( namco_50xx_map_program, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+ADDRESS_MAP_START( namco_50xx_map_data, ADDRESS_SPACE_DATA, 8 )
+ AM_RANGE(0x00, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+ADDRESS_MAP_START( namco_50xx_map_io, ADDRESS_SPACE_IO, 8 )
+ AM_RANGE(MB88_PORTK, MB88_PORTK) AM_READ(namco_50xx_K_r)
+ AM_RANGE(MB88_PORTO, MB88_PORTO) AM_WRITE(namco_50xx_O_w)
+ AM_RANGE(MB88_PORTR0, MB88_PORTR0) AM_READ(namco_50xx_R0_r)
+ AM_RANGE(MB88_PORTR2, MB88_PORTR2) AM_READ(namco_50xx_R2_r)
+ADDRESS_MAP_END
+
+
+
+ADDRESS_MAP_START( namco_50xx_2_map_program, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+ADDRESS_MAP_START( namco_50xx_2_map_data, ADDRESS_SPACE_DATA, 8 )
+ AM_RANGE(0x00, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+ADDRESS_MAP_START( namco_50xx_2_map_io, ADDRESS_SPACE_IO, 8 )
+ AM_RANGE(MB88_PORTK, MB88_PORTK) AM_READ(namco_50xx_2_K_r)
+ AM_RANGE(MB88_PORTO, MB88_PORTO) AM_WRITE(namco_50xx_2_O_w)
+ AM_RANGE(MB88_PORTR0, MB88_PORTR0) AM_READ(namco_50xx_2_R0_r)
+ AM_RANGE(MB88_PORTR2, MB88_PORTR2) AM_READ(namco_50xx_2_R2_r)
+ADDRESS_MAP_END
+
+
+
+static TIMER_CALLBACK( namco_50xx_irq_clear )
+{
+ cpunum_set_input_line(param, 0, CLEAR_LINE);
+}
+
+static void namco_50xx_irq_set(int cpunum)
+{
+ cpunum_set_input_line(cpunum, 0, ASSERT_LINE);
+
+ // The execution time of one instruction is ~4us, so we must make sure to
+ // give the cpu time to poll the /IRQ input before we clear it.
+ // The input clock to the 06XX interface chip is 64H, that is
+ // 18432000/6/64 = 48kHz, so it makes sense for the irq line to be
+ // asserted for one clock cycle ~= 21us.
+ timer_set(ATTOTIME_IN_USEC(21), cpunum, namco_50xx_irq_clear);
+}
+
+void namco_50xx_write(UINT8 data)
+{
+ int cpunum = mame_find_cpu_index(Machine, CPUTAG_50XX);
+
+ if (cpunum == -1)
+ return;
+
+ timer_call_after_resynch(data, namco_50xx_latch_callback);
+
+ namco_50xx_irq_set(cpunum);
+}
+
+void namco_50xx_2_write(UINT8 data)
+{
+ int cpunum = mame_find_cpu_index(Machine, CPUTAG_50XX_2);
+
+ if (cpunum == -1)
+ return;
+
+ timer_call_after_resynch(data, namco_50xx_2_latch_callback);
+
+ namco_50xx_irq_set(cpunum);
+}
+
+
+void namco_50xx_read_request(void)
+{
+ int cpunum = mame_find_cpu_index(Machine, CPUTAG_50XX);
+
+ if (cpunum == -1)
+ return;
+
+ timer_call_after_resynch(0, namco_50xx_readrequest_callback);
+
+ namco_50xx_irq_set(cpunum);
+}
+
+void namco_50xx_2_read_request(void)
+{
+ int cpunum = mame_find_cpu_index(Machine, CPUTAG_50XX_2);
+
+ if (cpunum == -1)
+ return;
+
+ timer_call_after_resynch(0, namco_50xx_2_readrequest_callback);
+
+ namco_50xx_irq_set(cpunum);
+}
+
+
+UINT8 namco_50xx_read(void)
+{
+ UINT8 res = portO[0];
+
+ namco_50xx_read_request();
+
+ return res;
+}
+
+UINT8 namco_50xx_2_read(void)
+{
+ UINT8 res = portO[1];
+
+ namco_50xx_2_read_request();
+
+ return res;
+}
diff --git a/src/mame/machine/namco50.h b/src/mame/machine/namco50.h
new file mode 100644
index 00000000000..2b5237ea495
--- /dev/null
+++ b/src/mame/machine/namco50.h
@@ -0,0 +1,23 @@
+#ifndef NAMCO50_H
+#define NAMCO50_H
+
+#define CPUTAG_50XX "50XX"
+#define CPUTAG_50XX_2 "50XX_2"
+
+ADDRESS_MAP_EXTERN( namco_50xx_map_program );
+ADDRESS_MAP_EXTERN( namco_50xx_map_data );
+ADDRESS_MAP_EXTERN( namco_50xx_map_io );
+
+ADDRESS_MAP_EXTERN( namco_50xx_2_map_program );
+ADDRESS_MAP_EXTERN( namco_50xx_2_map_data );
+ADDRESS_MAP_EXTERN( namco_50xx_2_map_io );
+
+UINT8 namco_50xx_read(void);
+void namco_50xx_read_request(void);
+void namco_50xx_write(UINT8 data);
+
+UINT8 namco_50xx_2_read(void);
+void namco_50xx_2_read_request(void);
+void namco_50xx_2_write(UINT8 data);
+
+#endif /* NAMCO54_H */
diff --git a/src/mame/machine/namcoio.c b/src/mame/machine/namcoio.c
new file mode 100644
index 00000000000..84c601e15c8
--- /dev/null
+++ b/src/mame/machine/namcoio.c
@@ -0,0 +1,1081 @@
+/***************************************************************************
+
+The following Namco custom chips are all instances of the same 4-bit MCU,
+the Fujitsu MB8843 (42-pin DIP package) and MB8842/MB8844 (28-pin DIP),
+differently programmed.
+
+chip MCU pins function
+---- ------ ---- --------
+50XX MB8842 28 player score handling (protection)
+51XX MB8843 42 I/O (coin management built-in)
+52XX MB8843 42 sample playback
+53XX MB8843 42 I/O (steering wheel support)
+54XX MB8844 28 explosion (noise) generator
+56XX 42 I/O (coin management built-in)
+58XX 42 I/O (coin management built-in)
+62XX 28 I/O and explosion (noise) generator
+
+06XX interface:
+---------------
+Galaga 51XX ---- ---- 54XX
+Bosconian (CPU board) 51XX ---- 50XX 54XX
+Bosconian (Video board) 50XX 52XX ---- ----
+Xevious 51XX ---- 50XX 54XX
+Dig Dug 51XX 53XX ---- ----
+Pole Position / PP II 51XX 53XX 52XX 54XX
+
+16XX interface:
+---------------
+Super Pac Man 56XX 56XX ---- ----
+Pac & Pal 56XX 59XX ---- ----
+Mappy 58XX 58XX ---- ----
+Phozon 58XX 56XX ---- ----
+The Tower of Druaga 58XX 56XX ---- ----
+Grobda 58XX 56XX ---- ----
+Dig Dug II 58XX 56XX ---- ----
+Motos 56XX 56XX ---- ----
+Gaplus 56XX 58XX 62XX ----
+Gaplus (alt.) 58XX 56XX 62XX ----
+Libble Rabble 58XX 56XX 56XX ----
+Toy Pop 58XX 56XX 56XX ----
+
+
+Pinouts:
+
+ MB8843 MB8842/MB8844
+ +------+ +------+
+ EXTAL|1 42|Vcc EXTAL|1 28|Vcc
+ XTAL|2 41|K3 XTAL|2 27|K3
+ /RESET|3 40|K2 /RESET|3 26|K2
+ /IRQ|4 39|K1 O0|4 25|K1
+ SO|5 38|K0 O1|5 24|K0
+ SI|6 37|R15 O2|6 23|R10 /IRQ
+/SC /TO|7 36|R14 O3|7 22|R9 /TC
+ /TC|8 35|R13 O4|8 21|R8
+ P0|9 34|R12 O5|9 20|R7
+ P1|10 33|R11 O6|10 19|R6
+ P2|11 32|R10 O7|11 18|R5
+ P3|12 31|R9 R0|12 17|R4
+ O0|13 30|R8 R1|13 16|R3
+ O1|14 29|R7 GND|14 15|R2
+ O2|15 28|R6 +------+
+ O3|16 27|R5
+ O4|17 26|R4
+ O5|18 25|R3
+ O6|19 24|R2
+ O7|20 23|R1
+ GND|21 22|R0
+ +------+
+
+
+ O O R R R K
+50XX O O I I I
+54XX O O I O I
+62XX O O IO O I
+
+ P O O R R R R K
+51XX O O O I I I I I
+52XX O O O I I O O I
+53XX O? O O I I I I I
+56XX O O O I I I IO I
+58XX O O O I I I IO I
+59XX O O O I I I IO I
+
+
+For the 52XX, see sound/namco52.c
+
+For the 54XX, see audio/namco54.c
+
+
+Namco custom I/O chips 56XX, 58XX, 59XX
+
+These chips work together with a 16XX, that interfaces them with the buffer
+RAM. Each chip uses 16 nibbles of memory; the 16XX supports up to 4 chips,
+but most games use only 2.
+
+The 56XX, 58XX and 59XX are pin-to-pin compatible, but not functionally equivalent:
+they provide the same functions, but the command codes and memory addresses
+are different, so they cannot be exchanged.
+
+The devices have 42 pins. There are 16 input lines and 8 output lines to be
+used for I/O.
+
+
+pin description
+--- -----------
+1 clock (Mappy, Super Pac-Man)
+2 clock (Gaplus; equivalent to the above?)
+3 reset
+4 irq
+5-6 (to/from 16XX) (this is probably a normal I/O port used to synchronize with the 16XX)
+7-8 ?
+9-12 address to r/w from RAM; 12 also goes to the 16XX and acts as r/w line, so
+ the chip can only read from addresses 0-7 and only write to addresses 8-F
+ (this is probably a normal I/O port used for that purpose)
+13-16 out port A
+17-20 out port B
+21 GND
+22-25 in port B
+26-29 in port C
+30-33 in port D
+34-37 (to 16XX) probably data to r/w from RAM
+ (this is probably a normal I/O port used for that purpose)
+38-41 in port A
+42 Vcc
+
+TODO:
+- It's likely that the 56XX and 58XX chips, when in "coin mode", also internally
+ handle outputs for start lamps, coin counters and coin lockout, like the 51XX.
+ Such lines are NOT present in the Mappy and Super Pacman schematics, so they
+ were probably not used for those games, but they might have been used in
+ others (most likely Gaplus).
+
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/namcoio.h"
+#include "machine/namco50.h"
+#include "sound/namco52.h"
+#include "audio/namco54.h"
+
+
+#define VERBOSE 0
+
+struct namcoio
+{
+ INT32 type;
+ read8_handler in[4];
+ write8_handler out[2];
+ INT32 reset;
+ INT32 lastcoins,lastbuttons;
+ INT32 credits;
+ INT32 coins[2];
+ INT32 coins_per_cred[2];
+ INT32 creds_per_coin[2];
+ INT32 in_count;
+ INT32 mode,coincred_mode,remap_joy; // for 51XX
+};
+
+static struct namcoio io[MAX_NAMCOIO];
+static INT32 nmi_cpu[MAX_06XX];
+static emu_timer *nmi_timer[MAX_06XX];
+
+static READ8_HANDLER( nop_r ) { return 0x0f; }
+static WRITE8_HANDLER( nop_w ) { }
+
+#define READ_PORT(n) (io[chip].in[n](0) & 0x0f)
+#define WRITE_PORT(n,d) io[chip].out[n](0,(d) & 0x0f)
+
+
+
+/*
+51XX
+
+commands:
+00: nop
+01 + 4 arguments: set coinage (xevious, possibly because of a bug, is different)
+02: go in "credit" mode and enable start buttons
+03: disable joystick remapping
+04: enable joystick remapping
+05: go in "switch" mode
+06: nop
+07: nop
+*/
+
+static void namcoio_51XX_write(int chip,int data)
+{
+ data &= 0x07;
+
+#if VERBOSE
+ logerror("%04x: custom 51XX write %02x\n",activecpu_get_pc(),data);
+#endif
+
+ if (io[chip].coincred_mode)
+ {
+ switch (io[chip].coincred_mode--)
+ {
+ case 4: io[chip].coins_per_cred[0] = data; break;
+ case 3: io[chip].creds_per_coin[0] = data; break;
+ case 2: io[chip].coins_per_cred[1] = data; break;
+ case 1: io[chip].creds_per_coin[1] = data; break;
+ }
+ }
+ else
+ {
+ switch (data)
+ {
+ case 0: // nop
+ break;
+
+ case 1: // set coinage
+ io[chip].coincred_mode = 4;
+ /* this is a good time to reset the credits counter */
+ io[chip].credits = 0;
+
+ {
+ /* kludge for a possible bug in Xevious */
+ static const game_driver *namcoio_51XX_driver = NULL;
+ static int namcoio_51XX_kludge = 0;
+
+ /* Only compute namcoio_51XX_kludge when gamedrv changes */
+ if (namcoio_51XX_driver != Machine->gamedrv)
+ {
+ namcoio_51XX_driver = Machine->gamedrv;
+ if (strcmp(namcoio_51XX_driver->name, "xevious") == 0 ||
+ strcmp(namcoio_51XX_driver->parent, "xevious") == 0)
+ namcoio_51XX_kludge = 1;
+ else
+ namcoio_51XX_kludge = 0;
+ }
+
+ if (namcoio_51XX_kludge)
+ {
+ io[chip].coincred_mode = 6;
+ io[chip].remap_joy = 1;
+ }
+ }
+ break;
+
+ case 2: // go in "credits" mode and enable start buttons
+ io[chip].mode = 1;
+ io[chip].in_count = 0;
+ break;
+
+ case 3: // disable joystick remapping
+ io[chip].remap_joy = 0;
+ break;
+
+ case 4: // enable joystick remapping
+ io[chip].remap_joy = 1;
+ break;
+
+ case 5: // go in "switch" mode
+ io[chip].mode = 0;
+ io[chip].in_count = 0;
+ break;
+
+ default:
+ logerror("unknown 51XX command %02x\n",data);
+ break;
+ }
+ }
+}
+
+
+/* joystick input mapping
+
+ The joystick is parsed and a number corresponding to the direction is returned,
+ according to the following table:
+
+ 0
+ 7 1
+ 6 8 2
+ 5 3
+ 4
+
+ The values for directions impossible to obtain on a joystick have not been
+ verified on Namco original hardware, but they are the same in all the bootlegs,
+ so we can assume they are right.
+*/
+static int joy_map[16] =
+/* LDRU, LDR, LDU, LD, LRU, LR, LU, L, DRU, DR, DU, D, RU, R, U, center */
+{ 0xf, 0xe, 0xd, 0x5, 0xc, 0x9, 0x7, 0x6, 0xb, 0x3, 0xa, 0x4, 0x1, 0x2, 0x0, 0x8 };
+
+
+static UINT8 namcoio_51XX_read(int chip)
+{
+#if VERBOSE
+ logerror("%04x: custom 51XX read\n",activecpu_get_pc());
+#endif
+
+ if (io[chip].mode == 0) /* switch mode */
+ {
+ switch ((io[chip].in_count++) % 3)
+ {
+ default:
+ case 0: return READ_PORT(0) | (READ_PORT(1) << 4);
+ case 1: return READ_PORT(2) | (READ_PORT(3) << 4);
+ case 2: return 0; // nothing?
+ }
+ }
+ else /* credits mode */
+ {
+ switch ((io[chip].in_count++) % 3)
+ {
+ default:
+ case 0: // number of credits in BCD format
+ {
+ int in,toggle;
+
+ in = ~(READ_PORT(0) | (READ_PORT(1) << 4));
+ toggle = in ^ io[chip].lastcoins;
+ io[chip].lastcoins = in;
+
+ if (io[chip].coins_per_cred[0] > 0)
+ {
+ if (io[chip].credits >= 99)
+ {
+ WRITE_PORT(1,1); // coin lockout
+ }
+ else
+ {
+ WRITE_PORT(1,0); // coin lockout
+ /* check if the user inserted a coin */
+ if (toggle & in & 0x10)
+ {
+ io[chip].coins[0]++;
+ WRITE_PORT(0,0x04); // coin counter
+ WRITE_PORT(0,0x0c);
+ if (io[chip].coins[0] >= io[chip].coins_per_cred[0])
+ {
+ io[chip].credits += io[chip].creds_per_coin[0];
+ io[chip].coins[0] -= io[chip].coins_per_cred[0];
+ }
+ }
+ if (toggle & in & 0x20)
+ {
+ io[chip].coins[1]++;
+ WRITE_PORT(0,0x08); // coin counter
+ WRITE_PORT(0,0x0c);
+ if (io[chip].coins[1] >= io[chip].coins_per_cred[1])
+ {
+ io[chip].credits += io[chip].creds_per_coin[1];
+ io[chip].coins[1] -= io[chip].coins_per_cred[1];
+ }
+ }
+ if (toggle & in & 0x40)
+ {
+ io[chip].credits++;
+ }
+ }
+ }
+ else io[chip].credits = 100; // free play
+
+ if (io[chip].mode == 1)
+ {
+ int on = (cpu_getcurrentframe() & 0x10) >> 4;
+
+ if (io[chip].credits >= 2)
+ WRITE_PORT(0,0x0c | 3*on); // lamps
+ else if (io[chip].credits >= 1)
+ WRITE_PORT(0,0x0c | 2*on); // lamps
+ else
+ WRITE_PORT(0,0x0c); // lamps off
+
+ /* check for 1 player start button */
+ if (toggle & in & 0x04)
+ {
+ if (io[chip].credits >= 1)
+ {
+ io[chip].credits--;
+ io[chip].mode = 2;
+ WRITE_PORT(0,0x0c); // lamps off
+ }
+ }
+ /* check for 2 players start button */
+ else if (toggle & in & 0x08)
+ {
+ if (io[chip].credits >= 2)
+ {
+ io[chip].credits -= 2;
+ io[chip].mode = 2;
+ WRITE_PORT(0,0x0c); // lamps off
+ }
+ }
+ }
+ }
+
+ if (~readinputport(0) & 0x80) /* check test mode switch */
+ return 0xbb;
+
+ return (io[chip].credits / 10) * 16 + io[chip].credits % 10;
+
+ case 1:
+ {
+ int joy = READ_PORT(2) & 0x0f;
+ int in,toggle;
+
+ in = ~READ_PORT(0);
+ toggle = in ^ io[chip].lastbuttons;
+ io[chip].lastbuttons = (io[chip].lastbuttons & 2) | (in & 1);
+
+ /* remap joystick */
+ if (io[chip].remap_joy) joy = joy_map[joy];
+
+ /* fire */
+ joy |= ((toggle & in & 0x01)^1) << 4;
+ joy |= ((in & 0x01)^1) << 5;
+
+ return joy;
+ }
+
+ case 2:
+ {
+ int joy = READ_PORT(3) & 0x0f;
+ int in,toggle;
+
+ in = ~READ_PORT(0);
+ toggle = in ^ io[chip].lastbuttons;
+ io[chip].lastbuttons = (io[chip].lastbuttons & 1) | (in & 2);
+
+ /* remap joystick */
+ if (io[chip].remap_joy) joy = joy_map[joy];
+
+ /* fire */
+ joy |= ((toggle & in & 0x02)^2) << 3;
+ joy |= ((in & 0x02)^2) << 4;
+
+ return joy;
+ }
+ }
+ }
+}
+
+
+/***************************************************************************/
+
+
+static UINT8 namcoio_ram[MAX_NAMCOIO * 16];
+
+#define IORAM_READ(offset) (namcoio_ram[chip * 0x10 + (offset)] & 0x0f)
+#define IORAM_WRITE(offset,data) {namcoio_ram[chip * 0x10 + (offset)] = (data) & 0x0f;}
+
+
+static void handle_coins(int chip,int swap)
+{
+ int val,toggled;
+ int credit_add = 0;
+ int credit_sub = 0;
+ int button;
+
+//popmessage("%x %x %x %x %x %x %x %x",IORAM_READ(8),IORAM_READ(9),IORAM_READ(10),IORAM_READ(11),IORAM_READ(12),IORAM_READ(13),IORAM_READ(14),IORAM_READ(15));
+
+ val = ~READ_PORT(0); // pins 38-41
+ toggled = val ^ io[chip].lastcoins;
+ io[chip].lastcoins = val;
+
+ /* check coin insertion */
+ if (val & toggled & 0x01)
+ {
+ io[chip].coins[0]++;
+ if (io[chip].coins[0] >= (io[chip].coins_per_cred[0] & 7))
+ {
+ credit_add = io[chip].creds_per_coin[0] - (io[chip].coins_per_cred[0] >> 3);
+ io[chip].coins[0] -= io[chip].coins_per_cred[0] & 7;
+ }
+ else if (io[chip].coins_per_cred[0] & 8)
+ credit_add = 1;
+ }
+ if (val & toggled & 0x02)
+ {
+ io[chip].coins[1]++;
+ if (io[chip].coins[1] >= (io[chip].coins_per_cred[1] & 7))
+ {
+ credit_add = io[chip].creds_per_coin[1] - (io[chip].coins_per_cred[1] >> 3);
+ io[chip].coins[1] -= io[chip].coins_per_cred[1] & 7;
+ }
+ else if (io[chip].coins_per_cred[1] & 8)
+ credit_add = 1;
+ }
+ if (val & toggled & 0x08)
+ {
+ credit_add = 1;
+ }
+
+ val = ~READ_PORT(3); // pins 30-33
+ toggled = val ^ io[chip].lastbuttons;
+ io[chip].lastbuttons = val;
+
+ /* check start buttons, only if the game allows */
+ if (IORAM_READ(9) == 0)
+ // the other argument is IORAM_READ(10) = 1, meaning unknown
+ {
+ if (val & toggled & 0x04)
+ {
+ if (io[chip].credits >= 1) credit_sub = 1;
+ }
+ else if (val & toggled & 0x08)
+ {
+ if (io[chip].credits >= 2) credit_sub = 2;
+ }
+ }
+
+ io[chip].credits += credit_add - credit_sub;
+
+ IORAM_WRITE(0 ^ swap, io[chip].credits / 10); // BCD credits
+ IORAM_WRITE(1 ^ swap, io[chip].credits % 10); // BCD credits
+ IORAM_WRITE(2 ^ swap, credit_add); // credit increment (coin inputs)
+ IORAM_WRITE(3 ^ swap, credit_sub); // credit decrement (start buttons)
+ IORAM_WRITE(4, ~READ_PORT(1)); // pins 22-25
+ button = ((val & 0x05) << 1) | (val & toggled & 0x05);
+ IORAM_WRITE(5, button); // pins 30 & 32 normal and impulse
+ IORAM_WRITE(6, ~READ_PORT(2)); // pins 26-29
+ button = (val & 0x0a) | ((val & toggled & 0x0a) >> 1);
+ IORAM_WRITE(7, button); // pins 31 & 33 normal and impulse
+}
+
+
+
+static void namco_customio_56XX_run(int chip)
+{
+#if VERBOSE
+ logerror("execute 56XX %d mode %d\n",chip,IORAM_READ(8));
+#endif
+
+ switch (IORAM_READ(8))
+ {
+ case 0: // nop?
+ break;
+
+ case 1: // read switch inputs
+ IORAM_WRITE(0, ~READ_PORT(0)); // pins 38-41
+ IORAM_WRITE(1, ~READ_PORT(1)); // pins 22-25
+ IORAM_WRITE(2, ~READ_PORT(2)); // pins 26-29
+ IORAM_WRITE(3, ~READ_PORT(3)); // pins 30-33
+
+//popmessage("%x %x %x %x %x %x %x %x",IORAM_READ(8),IORAM_READ(9),IORAM_READ(10),IORAM_READ(11),IORAM_READ(12),IORAM_READ(13),IORAM_READ(14),IORAM_READ(15));
+
+ WRITE_PORT(0,IORAM_READ(9)); // output to pins 13-16 (motos, pacnpal, gaplus)
+ WRITE_PORT(1,IORAM_READ(10)); // output to pins 17-20 (gaplus)
+ break;
+
+ case 2: // initialize coinage settings
+ io[chip].coins_per_cred[0] = IORAM_READ(9);
+ io[chip].creds_per_coin[0] = IORAM_READ(10);
+ io[chip].coins_per_cred[1] = IORAM_READ(11);
+ io[chip].creds_per_coin[1] = IORAM_READ(12);
+ // IORAM_READ(13) = 1; meaning unknown - possibly a 3rd coin input? (there's a IPT_UNUSED bit in port A)
+ // IORAM_READ(14) = 1; meaning unknown - possibly a 3rd coin input? (there's a IPT_UNUSED bit in port A)
+ // IORAM_READ(15) = 0; meaning unknown
+ break;
+
+ case 4: // druaga, digdug chip #1: read dip switches and inputs
+ // superpac chip #0: process coin and start inputs, read switch inputs
+ handle_coins(chip,0);
+ break;
+
+ case 7: // bootup check (liblrabl only)
+ {
+ // liblrabl chip #1: 9-15 = f 1 2 3 4 0 0, expects 2 = e
+ // liblrabl chip #2: 9-15 = 0 1 4 5 5 0 0, expects 7 = 6
+ IORAM_WRITE(2,0xe);
+ IORAM_WRITE(7,0x6);
+ }
+ break;
+
+ case 8: // bootup check
+ {
+ int i,sum;
+
+ // superpac: 9-15 = f f f f f f f, expects 0-1 = 6 9. 0x69 = f+f+f+f+f+f+f.
+ // motos: 9-15 = f f f f f f f, expects 0-1 = 6 9. 0x69 = f+f+f+f+f+f+f.
+ // phozon: 9-15 = 1 2 3 4 5 6 7, expects 0-1 = 1 c. 0x1c = 1+2+3+4+5+6+7
+ sum = 0;
+ for (i = 9;i < 16;i++)
+ sum += IORAM_READ(i);
+ IORAM_WRITE(0,sum >> 4);
+ IORAM_WRITE(1,sum & 0xf);
+ }
+ break;
+
+ case 9: // read dip switches and inputs
+ WRITE_PORT(0,0); // set pin 13 = 0
+ IORAM_WRITE(0, ~READ_PORT(0)); // pins 38-41, pin 13 = 0
+ IORAM_WRITE(2, ~READ_PORT(1)); // pins 22-25, pin 13 = 0
+ IORAM_WRITE(4, ~READ_PORT(2)); // pins 26-29, pin 13 = 0
+ IORAM_WRITE(6, ~READ_PORT(3)); // pins 30-33, pin 13 = 0
+ WRITE_PORT(0,1); // set pin 13 = 1
+ IORAM_WRITE(1, ~READ_PORT(0)); // pins 38-41, pin 13 = 1
+ IORAM_WRITE(3, ~READ_PORT(1)); // pins 22-25, pin 13 = 1
+ IORAM_WRITE(5, ~READ_PORT(2)); // pins 26-29, pin 13 = 1
+ IORAM_WRITE(7, ~READ_PORT(3)); // pins 30-33, pin 13 = 1
+ break;
+
+ default:
+ logerror("Namco I/O %d: unknown I/O mode %d\n",chip,IORAM_READ(8));
+ }
+}
+
+
+
+static void namco_customio_59XX_run(int chip)
+{
+#if VERBOSE
+ logerror("execute 59XX %d mode %d\n",chip,IORAM_READ(8));
+#endif
+
+ switch (IORAM_READ(8))
+ {
+ case 0: // nop?
+ break;
+
+ case 3: // pacnpal chip #1: read dip switches and inputs
+ IORAM_WRITE(4, ~READ_PORT(0)); // pins 38-41, pin 13 = 0 ?
+ IORAM_WRITE(5, ~READ_PORT(2)); // pins 26-29 ?
+ IORAM_WRITE(6, ~READ_PORT(1)); // pins 22-25 ?
+ IORAM_WRITE(7, ~READ_PORT(3)); // pins 30-33
+ break;
+
+ default:
+ logerror("Namco I/O %d: unknown I/O mode %d\n",chip,IORAM_READ(8));
+ }
+}
+
+
+
+static void namco_customio_58XX_run(int chip)
+{
+#if VERBOSE
+ logerror("execute 58XX %d mode %d\n",chip,IORAM_READ(8));
+#endif
+
+ switch (IORAM_READ(8))
+ {
+ case 0: // nop?
+ break;
+
+ case 1: // read switch inputs
+ IORAM_WRITE(4, ~READ_PORT(0)); // pins 38-41
+ IORAM_WRITE(5, ~READ_PORT(1)); // pins 22-25
+ IORAM_WRITE(6, ~READ_PORT(2)); // pins 26-29
+ IORAM_WRITE(7, ~READ_PORT(3)); // pins 30-33
+
+//popmessage("%x %x %x %x %x %x %x %x",IORAM_READ(8),IORAM_READ(9),IORAM_READ(10),IORAM_READ(11),IORAM_READ(12),IORAM_READ(13),IORAM_READ(14),IORAM_READ(15));
+
+ WRITE_PORT(0,IORAM_READ(9)); // output to pins 13-16 (toypop)
+ WRITE_PORT(1,IORAM_READ(10)); // output to pins 17-20 (toypop)
+ break;
+
+ case 2: // initialize coinage settings
+ io[chip].coins_per_cred[0] = IORAM_READ(9);
+ io[chip].creds_per_coin[0] = IORAM_READ(10);
+ io[chip].coins_per_cred[1] = IORAM_READ(11);
+ io[chip].creds_per_coin[1] = IORAM_READ(12);
+ // IORAM_READ(13) = 1; meaning unknown - possibly a 3rd coin input? (there's a IPT_UNUSED bit in port A)
+ // IORAM_READ(14) = 0; meaning unknown - possibly a 3rd coin input? (there's a IPT_UNUSED bit in port A)
+ // IORAM_READ(15) = 0; meaning unknown
+ break;
+
+ case 3: // process coin and start inputs, read switch inputs
+ handle_coins(chip,2);
+ break;
+
+ case 4: // read dip switches and inputs
+ WRITE_PORT(0,0); // set pin 13 = 0
+ IORAM_WRITE(0, ~READ_PORT(0)); // pins 38-41, pin 13 = 0
+ IORAM_WRITE(2, ~READ_PORT(1)); // pins 22-25, pin 13 = 0
+ IORAM_WRITE(4, ~READ_PORT(2)); // pins 26-29, pin 13 = 0
+ IORAM_WRITE(6, ~READ_PORT(3)); // pins 30-33, pin 13 = 0
+ WRITE_PORT(0,1); // set pin 13 = 1
+ IORAM_WRITE(1, ~READ_PORT(0)); // pins 38-41, pin 13 = 1
+ IORAM_WRITE(3, ~READ_PORT(1)); // pins 22-25, pin 13 = 1
+ IORAM_WRITE(5, ~READ_PORT(2)); // pins 26-29, pin 13 = 1
+ IORAM_WRITE(7, ~READ_PORT(3)); // pins 30-33, pin 13 = 1
+ break;
+
+ case 5: // bootup check
+ /* mode 5 values are checked against these numbers during power up
+ mappy: 9-15 = 3 6 5 f a c e, expects 1-7 = 8 4 6 e d 9 d
+ grobda: 9-15 = 2 3 4 5 6 7 8, expects 2 = f and 6 = c
+ phozon: 9-15 = 0 1 2 3 4 5 6, expects 0-7 = 0 2 3 4 5 6 c a
+ gaplus: 9-15 = f f f f f f f, expects 0-1 = f f
+
+ This has been determined to be the result of repeated XORs,
+ controlled by a 7-bit LFSR. The following algorithm should be
+ equivalent to the original one (though probably less efficient).
+ The first nibble of the result however is uncertain. It is usually
+ 0, but in some cases it toggles between 0 and F. We use a kludge
+ to give Gaplus the F it expects.
+ */
+ {
+ int i,n,rng,seed;
+ #define NEXT(n) ((((n) & 1) ? (n) ^ 0x90 : (n)) >> 1)
+
+ /* initialize the LFSR depending on the first two arguments */
+ n = (IORAM_READ(9) * 16 + IORAM_READ(10)) & 0x7f;
+ seed = 0x22;
+ for (i = 0;i < n;i++)
+ seed = NEXT(seed);
+
+ /* calculate the answer */
+ for (i = 1;i < 8;i++)
+ {
+ n = 0;
+ rng = seed;
+ if (rng & 1) { n ^= ~IORAM_READ(11); }
+ rng = NEXT(rng);
+ seed = rng; // save state for next loop
+ if (rng & 1) { n ^= ~IORAM_READ(10); }
+ rng = NEXT(rng);
+ if (rng & 1) { n ^= ~IORAM_READ(9); }
+ rng = NEXT(rng);
+ if (rng & 1) { n ^= ~IORAM_READ(15); }
+ rng = NEXT(rng);
+ if (rng & 1) { n ^= ~IORAM_READ(14); }
+ rng = NEXT(rng);
+ if (rng & 1) { n ^= ~IORAM_READ(13); }
+ rng = NEXT(rng);
+ if (rng & 1) { n ^= ~IORAM_READ(12); }
+
+ IORAM_WRITE(i,~n);
+ }
+ IORAM_WRITE(0,0x0);
+ /* kludge for gaplus */
+ if (IORAM_READ(9) == 0xf) IORAM_WRITE(0,0xf);
+ }
+ break;
+
+ default:
+ logerror("Namco I/O %d: unknown I/O mode %d\n",chip,IORAM_READ(8));
+ }
+}
+
+
+
+READ8_HANDLER( namcoio_r )
+{
+ // RAM is 4-bit wide; Pac & Pal requires the | 0xf0 otherwise Easter egg doesn't work
+ offset &= 0x3f;
+
+#if VERBOSE
+ logerror("%04x: I/O read %d: mode %d, offset %d = %02x\n", activecpu_get_pc(), offset / 16, namcoio_ram[(offset & 0x30) + 8], offset & 0x0f, namcoio_ram[offset]&0x0f);
+#endif
+
+ return 0xf0 | namcoio_ram[offset];
+}
+
+WRITE8_HANDLER( namcoio_w )
+{
+ offset &= 0x3f;
+ data &= 0x0f; // RAM is 4-bit wide
+
+#if VERBOSE
+ logerror("%04x: I/O write %d: offset %d = %02x\n", activecpu_get_pc(), offset / 16, offset & 0x0f, data);
+#endif
+
+ namcoio_ram[offset] = data;
+}
+
+void namcoio_set_reset_line(int chipnum, int state)
+{
+ io[chipnum].reset = (state == ASSERT_LINE) ? 1 : 0;
+ if (state != CLEAR_LINE)
+ {
+ /* reset internal registers */
+ io[chipnum].credits = 0;
+ io[chipnum].coins[0] = 0;
+ io[chipnum].coins_per_cred[0] = 1;
+ io[chipnum].creds_per_coin[0] = 1;
+ io[chipnum].coins[1] = 0;
+ io[chipnum].coins_per_cred[1] = 1;
+ io[chipnum].creds_per_coin[1] = 1;
+ io[chipnum].in_count = 0;
+ }
+}
+
+static TIMER_CALLBACK( namcoio_run )
+{
+ switch (io[param].type)
+ {
+ case NAMCOIO_56XX:
+ namco_customio_56XX_run(param);
+ break;
+ case NAMCOIO_58XX:
+ namco_customio_58XX_run(param);
+ break;
+ case NAMCOIO_59XX:
+ namco_customio_59XX_run(param);
+ break;
+ }
+}
+
+void namcoio_set_irq_line(int chipnum, int state)
+{
+ if (chipnum < MAX_NAMCOIO && state != CLEAR_LINE && !io[chipnum].reset)
+ {
+ /* give the cpu a tiny bit of time to write the command before processing it */
+ timer_set(ATTOTIME_IN_USEC(50), chipnum, namcoio_run);
+ }
+}
+
+static void namcoio_state_save(int chipnum)
+{
+
+ state_save_register_item_pointer("namcoio", chipnum, ((UINT8 *) (&namcoio_ram[chipnum * 16])), 16);
+ state_save_register_item("namcoio", chipnum, io[chipnum].reset);
+ state_save_register_item("namcoio", chipnum, io[chipnum].lastcoins);
+ state_save_register_item("namcoio", chipnum, io[chipnum].lastbuttons);
+ state_save_register_item("namcoio", chipnum, io[chipnum].credits);
+ state_save_register_item_array("namcoio", chipnum, io[chipnum].coins);
+ state_save_register_item_array("namcoio", chipnum, io[chipnum].coins_per_cred);
+ state_save_register_item_array("namcoio", chipnum, io[chipnum].creds_per_coin);
+ state_save_register_item("namcoio", chipnum, io[chipnum].in_count);
+ state_save_register_item("namcoio", chipnum, io[chipnum].mode);
+ state_save_register_item("namcoio", chipnum, io[chipnum].coincred_mode);
+ state_save_register_item("namcoio", chipnum, io[chipnum].remap_joy);
+}
+
+void namcoio_init(int chipnum, int type, const struct namcoio_interface *intf)
+{
+ if (chipnum < MAX_NAMCOIO)
+ {
+ io[chipnum].type = type;
+ io[chipnum].in[0] = (intf && intf->in[0]) ? intf->in[0] : nop_r;
+ io[chipnum].in[1] = (intf && intf->in[1]) ? intf->in[1] : nop_r;
+ io[chipnum].in[2] = (intf && intf->in[2]) ? intf->in[2] : nop_r;
+ io[chipnum].in[3] = (intf && intf->in[3]) ? intf->in[3] : nop_r;
+ io[chipnum].out[0] = (intf && intf->out[0]) ? intf->out[0] : nop_w;
+ io[chipnum].out[1] = (intf && intf->out[1]) ? intf->out[1] : nop_w;
+ namcoio_state_save(chipnum);
+ namcoio_set_reset_line(chipnum,PULSE_LINE);
+ }
+}
+
+
+
+
+
+
+
+static TIMER_CALLBACK( nmi_generate )
+{
+ if (!cpunum_is_suspended(param, SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE))
+ {
+#if VERBOSE
+ logerror("NMI cpu %d\n",nmi_cpu[param]);
+#endif
+
+ cpunum_set_input_line(nmi_cpu[param], INPUT_LINE_NMI, PULSE_LINE);
+ }
+#if VERBOSE
+ else
+ logerror("NMI not generated because cpu %d is suspended\n",nmi_cpu[param]);
+#endif
+}
+
+static UINT8 customio_command[MAX_06XX];
+
+static void namco_06xx_state_save(int chipnum)
+{
+
+ //state_save_register_item("namcoio06xx", chipnum, nmi_cpu[chipnum]);
+ state_save_register_item("namcoio06xx", chipnum, customio_command[chipnum]);
+}
+
+
+void namco_06xx_init(int chipnum, int cpu,
+ int type0, const struct namcoio_interface *intf0,
+ int type1, const struct namcoio_interface *intf1,
+ int type2, const struct namcoio_interface *intf2,
+ int type3, const struct namcoio_interface *intf3)
+{
+ if (chipnum < MAX_06XX)
+ {
+ namcoio_init(4*chipnum + 0, type0, intf0);
+ namcoio_init(4*chipnum + 1, type1, intf1);
+ namcoio_init(4*chipnum + 2, type2, intf2);
+ namcoio_init(4*chipnum + 3, type3, intf3);
+ nmi_cpu[chipnum] = cpu;
+ nmi_timer[chipnum] = timer_alloc(nmi_generate);
+ namco_06xx_state_save(chipnum);
+ }
+}
+
+
+
+static UINT8 namcoio_53XX_digdug_read(int chip)
+{
+#if VERBOSE
+ logerror("%04x: custom 53XX read\n",activecpu_get_pc());
+#endif
+
+ switch ((io[chip].in_count++) % 2)
+ {
+ default:
+ case 0: return READ_PORT(0) | (READ_PORT(1) << 4);
+ case 1: return READ_PORT(2) | (READ_PORT(3) << 4);
+ }
+}
+
+
+static UINT8 namcoio_53XX_polepos_read(int chip)
+{
+#if VERBOSE
+ logerror("%04x: custom 53XX read\n",activecpu_get_pc());
+#endif
+
+ switch ((io[chip].in_count++) % 8)
+ {
+ case 0: return READ_PORT(0) | (READ_PORT(1) << 4); // steering
+ case 4: return READ_PORT(2) | (READ_PORT(3) << 4); // dip switches
+ default: return 0xff; // polepos2 hangs if 0 is returned
+ }
+}
+
+
+static UINT8 namco_06xx_data_read(int chipnum)
+{
+#if VERBOSE
+ logerror("forwarding read to chip %d\n",chipnum%3);
+#endif
+
+ switch (io[chipnum].type)
+ {
+ case NAMCOIO_50XX: return namco_50xx_read();
+ case NAMCOIO_50XX_2: return namco_50xx_2_read();
+ case NAMCOIO_51XX: return namcoio_51XX_read(chipnum);
+ case NAMCOIO_53XX_DIGDUG: return namcoio_53XX_digdug_read(chipnum);
+ case NAMCOIO_53XX_POLEPOS: return namcoio_53XX_polepos_read(chipnum);
+ default:
+ logerror("%04x: custom IO type %d unsupported read\n",activecpu_get_pc(),io[chipnum].type);
+ return 0xff;
+ }
+}
+
+
+static void namco_06xx_data_write(int chipnum,UINT8 data)
+{
+#if VERBOSE
+ logerror("forwarding write to chip %d\n",chipnum%3);
+#endif
+
+ switch (io[chipnum].type)
+ {
+ case NAMCOIO_50XX: namco_50xx_write(data); break;
+ case NAMCOIO_50XX_2: namco_50xx_2_write(data); break;
+ case NAMCOIO_51XX: namcoio_51XX_write(chipnum,data); break;
+ case NAMCOIO_52XX: namcoio_52XX_write(data); break;
+ case NAMCOIO_54XX: namco_54xx_write(data); break;
+ default:
+ logerror("%04x: custom IO type %d unsupported write\n",activecpu_get_pc(),io[chipnum].type);
+ break;
+ }
+}
+
+
+static void namco_06xx_read_request(int chipnum)
+{
+#if VERBOSE
+ logerror("requesting read to chip %d\n",chipnum%3);
+#endif
+
+ switch (io[chipnum].type)
+ {
+ case NAMCOIO_50XX: namco_50xx_read_request(); break;
+ case NAMCOIO_50XX_2: namco_50xx_2_read_request(); break;
+ default:
+ logerror("%04x: custom IO type %d read_request unsupported\n",activecpu_get_pc(),io[chipnum].type);
+ break;
+ }
+}
+
+
+static UINT8 namco_06xx_data_r(int chip,int offset)
+{
+#if VERBOSE
+ logerror("%04x: 06XX #%d read offset %d\n",activecpu_get_pc(),chip,offset);
+#endif
+
+ if (!(customio_command[chip] & 0x10))
+ {
+ logerror("%04x: 06XX #%d read in write mode %02x\n",activecpu_get_pc(),chip,customio_command[chip]);
+ return 0;
+ }
+
+ switch (customio_command[chip] & 0xf)
+ {
+ case 0x1: return namco_06xx_data_read(4*chip + 0); break;
+ case 0x2: return namco_06xx_data_read(4*chip + 1); break;
+ case 0x4: return namco_06xx_data_read(4*chip + 2); break;
+ case 0x8: return namco_06xx_data_read(4*chip + 3); break;
+ default:
+ logerror("%04x: 06XX #%d read in unsupported mode %02x\n",activecpu_get_pc(),chip,customio_command[chip]);
+ return 0xff;
+ }
+}
+
+
+static void namco_06xx_data_w(int chip,int offset,int data)
+{
+#if VERBOSE
+ logerror("%04x: 06XX #%d write offset %d = %02x\n",activecpu_get_pc(),chip,offset,data);
+#endif
+
+ if (customio_command[chip] & 0x10)
+ {
+ logerror("%04x: 06XX #%d write in read mode %02x\n",activecpu_get_pc(),chip,customio_command[chip]);
+ return;
+ }
+
+ switch (customio_command[chip] & 0xf)
+ {
+ case 0x1: namco_06xx_data_write(4*chip + 0,data); break;
+ case 0x2: namco_06xx_data_write(4*chip + 1,data); break;
+ case 0x4: namco_06xx_data_write(4*chip + 2,data); break;
+ case 0x8: namco_06xx_data_write(4*chip + 3,data); break;
+ default:
+ logerror("%04x: 06XX #%d write in unsupported mode %02x\n",activecpu_get_pc(),chip,customio_command[chip]);
+ break;
+ }
+}
+
+
+static UINT8 namco_06xx_ctrl_r(int chip)
+{
+#if VERBOSE
+ logerror("%04x: 06XX #%d ctrl_r\n",activecpu_get_pc(),chip);
+#endif
+ return customio_command[chip];
+}
+
+static void namco_06xx_ctrl_w(int chip,int data)
+{
+#if VERBOSE
+ logerror("%04x: 06XX #%d command %02x\n",activecpu_get_pc(),chip,data);
+#endif
+
+ customio_command[chip] = data;
+
+ if ((customio_command[chip] & 0x0f) == 0)
+ {
+#if VERBOSE
+ logerror("disabling nmi generate timer\n");
+#endif
+ timer_adjust(nmi_timer[chip], attotime_never, chip, attotime_never);
+ }
+ else
+ {
+#if VERBOSE
+ logerror("setting nmi generate timer to 200us\n");
+#endif
+ // this timing is critical. Due to a bug, Bosconian will stop responding to
+ // inputs if a transfer terminates at the wrong time.
+ // On the other hand, the time cannot be too short otherwise the 54XX will
+ // not have enough time to process the incoming commands.
+ timer_adjust(nmi_timer[chip], ATTOTIME_IN_USEC(200), chip, ATTOTIME_IN_USEC(200));
+
+ if (customio_command[chip] & 0x10)
+ {
+ switch (customio_command[chip] & 0xf)
+ {
+ case 0x1: namco_06xx_read_request(4*chip + 0); break;
+ case 0x2: namco_06xx_read_request(4*chip + 1); break;
+ case 0x4: namco_06xx_read_request(4*chip + 2); break;
+ case 0x8: namco_06xx_read_request(4*chip + 3); break;
+ default:
+ logerror("%04x: 06XX #%d read in unsupported mode %02x\n",activecpu_get_pc(),chip,customio_command[chip]);
+ }
+ }
+ }
+}
+
+
+
+READ8_HANDLER( namco_06xx_0_data_r ) { return namco_06xx_data_r(0,offset); }
+READ8_HANDLER( namco_06xx_1_data_r ) { return namco_06xx_data_r(1,offset); }
+WRITE8_HANDLER( namco_06xx_0_data_w ) { namco_06xx_data_w(0,offset,data); }
+WRITE8_HANDLER( namco_06xx_1_data_w ) { namco_06xx_data_w(1,offset,data); }
+READ8_HANDLER( namco_06xx_0_ctrl_r ) { return namco_06xx_ctrl_r(0); }
+READ8_HANDLER( namco_06xx_1_ctrl_r ) { return namco_06xx_ctrl_r(1); }
+WRITE8_HANDLER( namco_06xx_0_ctrl_w ) { namco_06xx_ctrl_w(0,data); }
+WRITE8_HANDLER( namco_06xx_1_ctrl_w ) { namco_06xx_ctrl_w(1,data); }
diff --git a/src/mame/machine/namcoio.h b/src/mame/machine/namcoio.h
new file mode 100644
index 00000000000..1bc59433fb1
--- /dev/null
+++ b/src/mame/machine/namcoio.h
@@ -0,0 +1,53 @@
+#ifndef NAMCOIO_H
+#define NAMCOIO_H
+
+enum
+{
+ NAMCOIO_NONE = 0,
+ NAMCOIO_50XX,
+ NAMCOIO_50XX_2,
+ NAMCOIO_51XX,
+ NAMCOIO_52XX,
+ NAMCOIO_53XX_DIGDUG,
+ NAMCOIO_53XX_POLEPOS,
+ NAMCOIO_54XX,
+ NAMCOIO_56XX,
+ NAMCOIO_58XX,
+ NAMCOIO_59XX,
+ NAMCOIO_62XX
+};
+
+#define MAX_NAMCOIO 8
+#define MAX_06XX 2
+
+
+struct namcoio_interface
+{
+ read8_handler in[4]; /* read handlers for ports A-D */
+ write8_handler out[2]; /* write handlers for ports A-B */
+};
+
+
+void namco_06xx_init(int chipnum, int cpu,
+ int type0, const struct namcoio_interface *intf0,
+ int type1, const struct namcoio_interface *intf1,
+ int type2, const struct namcoio_interface *intf2,
+ int type3, const struct namcoio_interface *intf3);
+READ8_HANDLER( namco_06xx_0_data_r );
+READ8_HANDLER( namco_06xx_1_data_r );
+WRITE8_HANDLER( namco_06xx_0_data_w );
+WRITE8_HANDLER( namco_06xx_1_data_w );
+READ8_HANDLER( namco_06xx_0_ctrl_r );
+READ8_HANDLER( namco_06xx_1_ctrl_r );
+WRITE8_HANDLER( namco_06xx_0_ctrl_w );
+WRITE8_HANDLER( namco_06xx_1_ctrl_w );
+
+
+READ8_HANDLER( namcoio_r );
+WRITE8_HANDLER( namcoio_w );
+void namcoio_init(int chipnum, int type, const struct namcoio_interface *intf);
+void namcoio_set_reset_line(int chipnum, int state);
+void namcoio_set_irq_line(int chipnum, int state);
+
+
+#endif
diff --git a/src/mame/machine/namcond1.c b/src/mame/machine/namcond1.c
new file mode 100644
index 00000000000..fea7a38cc6f
--- /dev/null
+++ b/src/mame/machine/namcond1.c
@@ -0,0 +1,113 @@
+/***************************************************************************
+
+ Namco ND-1
+
+ machine.c
+
+ Functions to emulate general aspects of the machine
+ (RAM, ROM, interrupts, I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6809/m6809.h"
+#include "namcond1.h"
+
+/* Perform basic machine initialisation */
+
+UINT8 namcond1_h8_irq5_enabled;
+UINT8 namcond1_gfxbank;
+
+MACHINE_START( namcond1 )
+{
+ state_save_register_global(namcond1_h8_irq5_enabled);
+ state_save_register_global(namcond1_gfxbank);
+}
+
+MACHINE_RESET( namcond1 )
+{
+#ifdef MAME_DEBUG
+ /*UINT8 *ROM = memory_region(REGION_CPU1);*/
+ /*UINT32 debug_trigger_addr;*/
+ /*int i;*/
+
+#if 0
+ // debug trigger patch
+ // insert a "move.b $B0000000,D2" into the code
+ debug_trigger_addr = 0x152d4; // after ygv_init
+ ROM[debug_trigger_addr++] = 0x39;
+ ROM[debug_trigger_addr++] = 0x14;
+ ROM[debug_trigger_addr++] = 0xB0;
+ ROM[debug_trigger_addr++] = 0x00;
+ ROM[debug_trigger_addr++] = 0x00;
+ ROM[debug_trigger_addr++] = 0x00;
+#endif
+#endif
+
+ // initialise MCU states
+ namcond1_h8_irq5_enabled = 0;
+
+ // halt the MCU
+ cpunum_set_input_line(1,INPUT_LINE_RESET,ASSERT_LINE);
+}
+
+// instance of the shared ram pointer
+UINT16 *namcond1_shared_ram;
+
+READ16_HANDLER( namcond1_shared_ram_r )
+{
+ return namcond1_shared_ram[offset];
+}
+
+// $c3ff00-$c3ffff
+READ16_HANDLER( namcond1_cuskey_r )
+{
+ switch( offset )
+ {
+ // this address returns a jump vector inside ISR2
+ // - if zero then the ISR returns without jumping
+ case (0x2e>>1):
+ return( 0x0000 );
+ case (0x30>>1):
+ return( 0x0000 );
+
+ default :
+ logerror( "offset $%X accessed from $%X\n",
+ offset<<1, activecpu_get_pc() );
+ return( 0 );
+ }
+}
+
+WRITE16_HANDLER( namcond1_shared_ram_w )
+{
+
+ switch( offset )
+ {
+ default :
+ COMBINE_DATA( namcond1_shared_ram + offset );
+ break;
+ }
+}
+
+WRITE16_HANDLER( namcond1_cuskey_w )
+{
+ switch( offset )
+ {
+ case (0x0a>>1):
+ // this is a kludge until we emulate the h8
+ if ((namcond1_h8_irq5_enabled == 0) && (data != 0x0000))
+ {
+ cpunum_set_input_line(1, INPUT_LINE_RESET, CLEAR_LINE);
+ }
+ namcond1_h8_irq5_enabled = ( data != 0x0000 );
+ break;
+
+ case (0x0c>>1):
+ namcond1_gfxbank = (data & 0x0002) >>1; // i think
+ // should mark tilemaps dirty but i think they already are
+ break;
+
+ default :
+ break;
+ }
+}
diff --git a/src/mame/machine/namcos1.c b/src/mame/machine/namcos1.c
new file mode 100644
index 00000000000..ef4349ab30a
--- /dev/null
+++ b/src/mame/machine/namcos1.c
@@ -0,0 +1,1430 @@
+#include "driver.h"
+#include "sound/ym2151.h"
+#include "sound/namco.h"
+
+#define NAMCOS1_MAX_BANK 0x400
+
+/* from video */
+READ8_HANDLER( namcos1_videoram_r );
+WRITE8_HANDLER( namcos1_videoram_w );
+WRITE8_HANDLER( namcos1_paletteram_w );
+READ8_HANDLER( namcos1_spriteram_r );
+WRITE8_HANDLER( namcos1_spriteram_w );
+extern void namcos1_set_scroll_offsets( const int *bgx, const int *bgy, int negative, int optimize );
+extern void namcos1_set_sprite_offsets( int x, int y );
+
+UINT8 *namcos1_paletteram;
+
+static UINT8 *namcos1_triram;
+static UINT8 *s1ram;
+
+
+/*******************************************************************************
+* *
+* BANK area handling *
+* *
+*******************************************************************************/
+
+/* Bank handler definitions */
+typedef struct
+{
+ read8_handler bank_handler_r;
+ write8_handler bank_handler_w;
+ int bank_offset;
+ UINT8 *bank_pointer;
+} bankhandler;
+
+/* hardware elements of 1Mbytes physical memory space */
+static bankhandler namcos1_bank_element[NAMCOS1_MAX_BANK];
+static bankhandler namcos1_active_bank[16];
+
+static READ8_HANDLER( bank1_r ) { return (*namcos1_active_bank[0].bank_handler_r )(offset + namcos1_active_bank[0].bank_offset); }
+static READ8_HANDLER( bank2_r ) { return (*namcos1_active_bank[1].bank_handler_r )(offset + namcos1_active_bank[1].bank_offset); }
+static READ8_HANDLER( bank3_r ) { return (*namcos1_active_bank[2].bank_handler_r )(offset + namcos1_active_bank[2].bank_offset); }
+static READ8_HANDLER( bank4_r ) { return (*namcos1_active_bank[3].bank_handler_r )(offset + namcos1_active_bank[3].bank_offset); }
+static READ8_HANDLER( bank5_r ) { return (*namcos1_active_bank[4].bank_handler_r )(offset + namcos1_active_bank[4].bank_offset); }
+static READ8_HANDLER( bank6_r ) { return (*namcos1_active_bank[5].bank_handler_r )(offset + namcos1_active_bank[5].bank_offset); }
+static READ8_HANDLER( bank7_r ) { return (*namcos1_active_bank[6].bank_handler_r )(offset + namcos1_active_bank[6].bank_offset); }
+static READ8_HANDLER( bank8_r ) { return (*namcos1_active_bank[7].bank_handler_r )(offset + namcos1_active_bank[7].bank_offset); }
+static READ8_HANDLER( bank9_r ) { return (*namcos1_active_bank[8].bank_handler_r )(offset + namcos1_active_bank[8].bank_offset); }
+static READ8_HANDLER( bank10_r ) { return (*namcos1_active_bank[9].bank_handler_r )(offset + namcos1_active_bank[9].bank_offset); }
+static READ8_HANDLER( bank11_r ) { return (*namcos1_active_bank[10].bank_handler_r)(offset + namcos1_active_bank[10].bank_offset); }
+static READ8_HANDLER( bank12_r ) { return (*namcos1_active_bank[11].bank_handler_r)(offset + namcos1_active_bank[11].bank_offset); }
+static READ8_HANDLER( bank13_r ) { return (*namcos1_active_bank[12].bank_handler_r)(offset + namcos1_active_bank[12].bank_offset); }
+static READ8_HANDLER( bank14_r ) { return (*namcos1_active_bank[13].bank_handler_r)(offset + namcos1_active_bank[13].bank_offset); }
+static READ8_HANDLER( bank15_r ) { return (*namcos1_active_bank[14].bank_handler_r)(offset + namcos1_active_bank[14].bank_offset); }
+static READ8_HANDLER( bank16_r ) { return (*namcos1_active_bank[15].bank_handler_r)(offset + namcos1_active_bank[15].bank_offset); }
+
+static WRITE8_HANDLER( bank1_w ) { (*namcos1_active_bank[0].bank_handler_w )(offset + namcos1_active_bank[0].bank_offset, data); }
+static WRITE8_HANDLER( bank2_w ) { (*namcos1_active_bank[1].bank_handler_w )(offset + namcos1_active_bank[1].bank_offset, data); }
+static WRITE8_HANDLER( bank3_w ) { (*namcos1_active_bank[2].bank_handler_w )(offset + namcos1_active_bank[2].bank_offset, data); }
+static WRITE8_HANDLER( bank4_w ) { (*namcos1_active_bank[3].bank_handler_w )(offset + namcos1_active_bank[3].bank_offset, data); }
+static WRITE8_HANDLER( bank5_w ) { (*namcos1_active_bank[4].bank_handler_w )(offset + namcos1_active_bank[4].bank_offset, data); }
+static WRITE8_HANDLER( bank6_w ) { (*namcos1_active_bank[5].bank_handler_w )(offset + namcos1_active_bank[5].bank_offset, data); }
+static WRITE8_HANDLER( bank7_w ) { (*namcos1_active_bank[6].bank_handler_w )(offset + namcos1_active_bank[6].bank_offset, data); }
+static WRITE8_HANDLER( bank8_w ) { (*namcos1_active_bank[7].bank_handler_w )(offset + namcos1_active_bank[7].bank_offset, data); }
+static WRITE8_HANDLER( bank9_w ) { (*namcos1_active_bank[8].bank_handler_w )(offset + namcos1_active_bank[8].bank_offset, data); }
+static WRITE8_HANDLER( bank10_w ) { (*namcos1_active_bank[9].bank_handler_w )(offset + namcos1_active_bank[9].bank_offset, data); }
+static WRITE8_HANDLER( bank11_w ) { (*namcos1_active_bank[10].bank_handler_w)(offset + namcos1_active_bank[10].bank_offset, data); }
+static WRITE8_HANDLER( bank12_w ) { (*namcos1_active_bank[11].bank_handler_w)(offset + namcos1_active_bank[11].bank_offset, data); }
+static WRITE8_HANDLER( bank13_w ) { (*namcos1_active_bank[12].bank_handler_w)(offset + namcos1_active_bank[12].bank_offset, data); }
+static WRITE8_HANDLER( bank14_w ) { (*namcos1_active_bank[13].bank_handler_w)(offset + namcos1_active_bank[13].bank_offset, data); }
+static WRITE8_HANDLER( bank15_w ) { (*namcos1_active_bank[14].bank_handler_w)(offset + namcos1_active_bank[14].bank_offset, data); }
+static WRITE8_HANDLER( bank16_w ) { (*namcos1_active_bank[15].bank_handler_w)(offset + namcos1_active_bank[15].bank_offset, data); }
+
+static const read8_handler ram_bank_handler_r[16] =
+{
+ MRA8_BANK1 ,MRA8_BANK2 ,MRA8_BANK3 ,MRA8_BANK4 ,
+ MRA8_BANK5 ,MRA8_BANK6 ,MRA8_BANK7 ,MRA8_BANK8 ,
+ MRA8_BANK9 ,MRA8_BANK10,MRA8_BANK11,MRA8_BANK12,
+ MRA8_BANK13,MRA8_BANK14,MRA8_BANK15,MRA8_BANK16
+};
+
+static const write8_handler ram_bank_handler_w[16] =
+{
+ MWA8_BANK1 ,MWA8_BANK2 ,MWA8_BANK3 ,MWA8_BANK4 ,
+ MWA8_BANK5 ,MWA8_BANK6 ,MWA8_BANK7 ,MWA8_BANK8 ,
+ MWA8_BANK9 ,MWA8_BANK10,MWA8_BANK11,MWA8_BANK12,
+ MWA8_BANK13,MWA8_BANK14,MWA8_BANK15,MWA8_BANK16
+};
+
+static const read8_handler io_bank_handler_r[16] =
+{
+ bank1_r, bank2_r, bank3_r, bank4_r,
+ bank5_r, bank6_r, bank7_r, bank8_r,
+ bank9_r, bank10_r, bank11_r, bank12_r,
+ bank13_r, bank14_r, bank15_r, bank16_r
+};
+
+static const write8_handler io_bank_handler_w[16] =
+{
+ bank1_w, bank2_w, bank3_w, bank4_w,
+ bank5_w, bank6_w, bank7_w, bank8_w,
+ bank9_w, bank10_w, bank11_w, bank12_w,
+ bank13_w, bank14_w, bank15_w, bank16_w
+};
+
+
+
+static WRITE8_HANDLER( namcos1_3dcs_w )
+{
+ if (offset & 1) popmessage("LEFT");
+ else popmessage("RIGHT");
+}
+
+
+
+static int key_id,key_reg,key_rng,key_swap4_arg,key_swap4,key_bottom4,key_top4;
+static UINT8 key[8];
+
+
+static READ8_HANDLER( no_key_r )
+{
+ popmessage("CPU #%d PC %08x: keychip read %04x\n",cpu_getactivecpu(),activecpu_get_pc(),offset);
+ return 0;
+}
+
+static WRITE8_HANDLER( no_key_w )
+{
+ popmessage("CPU #%d PC %08x: keychip write %04x=%02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset,data);
+}
+
+
+/*****************************************************************************
+
+ Key custom type 1 (CUS136, CUS143, CUS144)
+
+ 16/8 bit division + key no.
+
+*****************************************************************************/
+
+/*
+the startup checks are the same in the three games using this kind of chip,
+apart from the [operating mode?] values written.
+
+dspirit: (CUS136)
+CPU #0 PC da06: keychip write 0000=01 [maybe to initialize chip?]
+CPU #0 PC da09: keychip read 0003 [return key no.]
+CPU #0 PC da14: keychip write 0003=f2 [operating mode?]
+CPU #0 PC da1d: keychip write 0000=xx [ \ operands]
+CPU #0 PC da22: keychip write 0001=xx [ " " ]
+CPU #0 PC da22: keychip write 0002=xx [ " " ]
+CPU #0 PC da25: keychip read 0001 [ division result (verified to be correct)]
+CPU #0 PC da25: keychip read 0002 [ " " (verified to be correct)]
+CPU #0 PC da28: keychip read 0000 [ / " " (verified to be correct)]
+CPU #0 PC daf6: keychip write 0003=c2 [operating mode?]
+CPU #0 PC dafa: keychip write 0002=00-ff [???????]
+CPU #0 PC db00: keychip read 0003 [???? - stored in 0001]
+CPU #0 PC db07: keychip write 0001=82-ff [ \ ???????]
+CPU #0 PC db07: keychip write 0002=8d [ / ???????]
+CPU #0 PC db0d: keychip read 0003 [???? - stored in 0002]
+CPU #0 PC db14: keychip read 0001 [ \ ???????]
+CPU #0 PC db14: keychip read 0002 [ ???????]
+CPU #0 PC db17: keychip write 0001=xx [ ???????]
+CPU #0 PC db17: keychip write 0002=xx [ / ???????]
+CPU #0 PC db1d: keychip read 0001 [???? - stored in 0003]
+CPU #0 PC db1d: keychip read 0002 [???? - stored in 0004]
+CPU #0 PC db24: keychip write 0003=f2 [operating mode?]
+---- end of common checks
+CPU #0 PC 8191: keychip write 0003=01 [????]
+CPU #0 PC 8196: keychip write 0000=40 [ \ operands]
+CPU #0 PC 819c: keychip write 0002=00 [ " " ]
+CPU #0 PC 819f: keychip write 0001=04 [ " " ]
+CPU #0 PC 81a2: keychip read 0001 [ division result (verified to be correct)]
+CPU #0 PC 81a2: keychip read 0002 [ / " " (verified to be correct)]
+if division result is wrong, reads again key no. from 03, and doesn't crash if it's correct
+
+wldcourt: (CUS143)
+CPU #0 PC db0a: keychip write 0000=01 [maybe to initialize chip?]
+CPU #0 PC db0d: keychip read 0003 [return key no.]
+CPU #0 PC db18: keychip write 0003=d9 [operating mode?]
+CPU #0 PC db21: keychip write 0000=xx [ \ operands]
+CPU #0 PC db26: keychip write 0001=xx [ " " ]
+CPU #0 PC db26: keychip write 0002=xx [ " " ]
+CPU #0 PC db29: keychip read 0001 [ division result (verified to be correct)]
+CPU #0 PC db29: keychip read 0002 [ " " (verified to be correct)]
+CPU #0 PC db2c: keychip read 0000 [ / " " (verified to be correct)]
+CPU #0 PC dbfa: keychip write 0003=db [operating mode?]
+CPU #0 PC dbfe: keychip write 0002=00-ff [???????]
+CPU #0 PC dc04: keychip read 0003 [???? - stored in 0001]
+CPU #0 PC dc0b: keychip write 0001=82-ff [ \ ???????]
+CPU #0 PC dc0b: keychip write 0002=8d [ / ???????]
+CPU #0 PC dc11: keychip read 0003 [???? - stored in 0002]
+CPU #0 PC dc18: keychip read 0001 [ \ ???????]
+CPU #0 PC dc18: keychip read 0002 [ ???????]
+CPU #0 PC dc1b: keychip write 0001=xx [ ???????]
+CPU #0 PC dc1b: keychip write 0002=xx [ / ???????]
+CPU #0 PC dc21: keychip read 0001 [???? - stored in 0003]
+CPU #0 PC dc21: keychip read 0002 [???? - stored in 0004]
+CPU #0 PC dc28: keychip write 0003=d9 [operating mode?]
+---- end of common checks
+CPU #0 PC e31c: keychip read 0003 [return key no.]
+
+blazer: (CUS144)
+CPU #0 PC da0b: keychip write 0000=01 [maybe to initialize chip?]
+CPU #0 PC da0e: keychip read 0003 [return key no.]
+CPU #0 PC da19: keychip write 0003=b7 [operating mode?]
+CPU #0 PC da22: keychip write 0000=12 [ \ operands]
+CPU #0 PC da27: keychip write 0001=0a [ " " ]
+CPU #0 PC da27: keychip write 0002=95 [ " " ]
+CPU #0 PC da2a: keychip read 0001 [ division result (verified to be correct)]
+CPU #0 PC da2a: keychip read 0002 [ " " (verified to be correct)]
+CPU #0 PC da2d: keychip read 0000 [ / " " (verified to be correct)]
+CPU #0 PC dafb: keychip write 0003=b6 [operating mode?]
+CPU #0 PC daff: keychip write 0002=00-ff [???????]
+CPU #0 PC db05: keychip read 0003 [???? - stored in 0001]
+CPU #0 PC db0c: keychip write 0001=82-ff [ \ ???????]
+CPU #0 PC db0c: keychip write 0002=8d [ / ???????]
+CPU #0 PC db12: keychip read 0003 [???? - stored in 0002]
+CPU #0 PC db19: keychip read 0001 [ \ ???????]
+CPU #0 PC db19: keychip read 0002 [ ???????]
+CPU #0 PC db1c: keychip write 0001=xx [ ???????]
+CPU #0 PC db1c: keychip write 0002=xx [ / ???????]
+CPU #0 PC db22: keychip read 0001 [???? - stored in 0003]
+CPU #0 PC db22: keychip read 0002 [???? - stored in 0004]
+CPU #0 PC db29: keychip write 0003=b7 [operating mode?]
+---- end of common checks
+
+puzlclub:
+CPU #0 PC e017: keychip write 0003=35 [they probably used RAM instead of a key chip for this prototype]
+CPU #0 PC e3d4: keychip read 0003 [AND #$37 = key no.]
+*/
+static READ8_HANDLER( key_type1_r )
+{
+// logerror("CPU #%d PC %04x: keychip read %04x\n",cpu_getactivecpu(),activecpu_get_pc(),offset);
+
+ if (offset < 3)
+ {
+ int d = key[0];
+ int n = (key[1] << 8) | key[2];
+ int q,r;
+
+ if (d)
+ {
+ q = n / d;
+ r = n % d;
+ }
+ else
+ {
+ q = 0xffff;
+ r = 0x00;
+ }
+
+ if (offset == 0) return r;
+ if (offset == 1) return q >> 8;
+ if (offset == 2) return q & 0xff;
+ }
+ else if (offset == 3)
+ return key_id;
+
+ return 0;
+}
+
+static WRITE8_HANDLER( key_type1_w )
+{
+// logerror("CPU #%d PC %04x: keychip write %04x=%02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset,data);
+
+ if (offset < 4)
+ key[offset] = data;
+}
+
+
+/*****************************************************************************
+
+ Key custom type 2 (CUS151 - CUS155)
+
+ 16/16 bit division + key no.
+
+*****************************************************************************/
+
+/*
+pacmania: (CUS151)
+CPU #0 PC dac2: keychip write 0004=4b [operating mode?]
+CPU #0 PC dac5: keychip read 0004 [AND #$37 = key no.]
+CPU #0 PC dad9: keychip write 0000=xx
+CPU #0 PC dad9: keychip write 0001=xx
+CPU #0 PC dae0: keychip write 0002=xx
+CPU #0 PC dae0: keychip write 0003=xx
+CPU #0 PC dae4: keychip read 0000
+CPU #0 PC dae4: keychip read 0001
+CPU #0 PC daed: keychip read 0002
+CPU #0 PC daed: keychip read 0003
+CPU #1 PC f188: keychip write 0004=4b [operating mode?]
+CPU #1 PC f2d0: keychip write 0000=01
+CPU #1 PC f2d0: keychip write 0001=aa
+CPU #1 PC f30d: keychip write 0002=xx
+CPU #1 PC f30d: keychip write 0003=xx
+CPU #1 PC f310: keychip read 0003
+CPU #1 PC f55d: keychip write 0000=00
+CPU #1 PC f55d: keychip write 0001=10
+CPU #1 PC f562: keychip write 0004=4b [operating mode?]
+CPU #1 PC f5d3: keychip write 0002=xx
+CPU #1 PC f5d3: keychip write 0003=xx
+CPU #1 PC f5d6: keychip read 0003
+CPU #1 PC f5ef: keychip read 0001
+CPU #1 PC cbc6: keychip write 0000=00
+CPU #1 PC cbc6: keychip write 0001=02
+CPU #1 PC cbdd: keychip write 0002=xx
+CPU #1 PC cbdd: keychip write 0003=xx
+CPU #1 PC cbe8: keychip read 0002
+CPU #1 PC cbe8: keychip read 0003
+
+mmaze: (CUS152)
+CPU #0 PC 60f3: keychip write 0004=5b
+CPU #0 PC 60fe: keychip write 0000=00
+CPU #0 PC 60fe: keychip write 0001=01
+CPU #0 PC 6101: keychip write 0002=00
+CPU #0 PC 6101: keychip write 0003=01
+CPU #0 PC 6104: keychip read 0004
+CPU #0 PC 61ae: keychip write 0000=00
+CPU #0 PC 61ae: keychip write 0001=33
+CPU #0 PC 61b1: keychip write 0002=02
+CPU #0 PC 61b1: keychip write 0003=00
+CPU #0 PC 61b4: keychip read 0002
+CPU #0 PC 61b4: keychip read 0003
+CPU #0 PC 68fa: keychip write 0000=01
+CPU #0 PC 68fa: keychip write 0001=00
+CPU #0 PC 68fd: keychip write 0002=00
+CPU #0 PC 68fd: keychip write 0003=00
+CPU #0 PC 6900: keychip read 0002
+CPU #0 PC 6900: keychip read 0003
+CPU #0 PC bf6c: keychip write 0000=00
+CPU #0 PC bf6c: keychip write 0001=20
+CPU #0 PC bf6f: keychip write 0002=00
+CPU #0 PC bf6f: keychip write 0003=00
+CPU #0 PC bf72: keychip read 0002
+CPU #0 PC bf72: keychip read 0003
+CPU #0 PC 9576: keychip write 0000=00
+CPU #0 PC 9576: keychip write 0001=14
+CPU #0 PC 9579: keychip write 0002=00
+CPU #0 PC 9579: keychip write 0003=00
+CPU #0 PC 957c: keychip read 0002
+CPU #0 PC 957c: keychip read 0003
+CPU #0 PC 6538: keychip write 0000=00
+CPU #0 PC 6538: keychip write 0001=15
+CPU #0 PC 653b: keychip write 0002=00
+CPU #0 PC 653b: keychip write 0003=01
+CPU #0 PC 653e: keychip read 0002
+CPU #0 PC 653e: keychip read 0003
+
+galaga88: (CUS153)
+CPU #0 PC db02: keychip write 0004=2d [operating mode?]
+CPU #0 PC db05: keychip read 0004 [AND #$7F = key no.]
+CPU #0 PC db17: keychip write 0000=xx
+CPU #0 PC db17: keychip write 0001=xx
+CPU #0 PC db1e: keychip write 0002=xx
+CPU #0 PC db1e: keychip write 0003=xx
+CPU #0 PC db22: keychip read 0000
+CPU #0 PC db22: keychip read 0001
+CPU #0 PC db2b: keychip read 0002
+CPU #0 PC db2b: keychip read 0003
+CPU #0 PC e136: keychip write 0004=0c
+
+ws: (CUS154)
+CPU #0 PC e052: keychip write 0004=d3 [operating mode?]
+CPU #0 PC e82a: keychip read 0004 [AND #$3F = key no.]
+
+bakutotu: (CUS155)
+CPU #0 PC db38: keychip write 0004=03 [operating mode?]
+CPU #0 PC db3b: keychip read 0004 [AND #$37 = key no.]
+CPU #0 PC db4f: keychip write 0000=xx
+CPU #0 PC db4f: keychip write 0001=xx
+CPU #0 PC db56: keychip write 0002=xx
+CPU #0 PC db56: keychip write 0003=xx
+CPU #0 PC db5a: keychip read 0000
+CPU #0 PC db5a: keychip read 0001
+CPU #0 PC db63: keychip read 0002
+CPU #0 PC db63: keychip read 0003
+CPU #0 PC db70: keychip write 0004=0b
+CPU #0 PC db77: keychip write 0000=ff
+CPU #0 PC db77: keychip write 0001=ff
+CPU #0 PC db7e: keychip write 0002=ff
+CPU #0 PC db7e: keychip write 0003=ff
+CPU #0 PC db82: keychip read 0000
+CPU #0 PC db82: keychip read 0001
+CPU #0 PC db8b: keychip read 0002
+CPU #0 PC db8b: keychip read 0003
+CPU #0 PC db95: keychip write 0004=03
+CPU #0 PC e552: keychip read 0004 [AND #$3F = key no.]
+CPU #0 PC e560: keychip write 0000=00
+CPU #0 PC e560: keychip write 0001=73
+CPU #0 PC e566: keychip write 0002=a4
+CPU #0 PC e566: keychip write 0003=83
+CPU #0 PC e569: keychip read 0002
+CPU #0 PC e569: keychip read 0003
+CPU #0 PC e574: keychip read 0000
+CPU #0 PC e574: keychip read 0001
+
+*/
+
+static READ8_HANDLER( key_type2_r )
+{
+// logerror("CPU #%d PC %04x: keychip read %04x\n",cpu_getactivecpu(),activecpu_get_pc(),offset);
+
+ if (offset < 4)
+ {
+ int d = (key[0] << 8) | key[1];
+ int n = (key[2] << 8) | key[3];
+ int q,r;
+
+ if (d)
+ {
+ q = n / d;
+ r = n % d;
+ }
+ else
+ {
+ q = 0xffff;
+ r = 0x00;
+ }
+
+ if (offset == 0) return r >> 8;
+ if (offset == 1) return r & 0xff;
+ if (offset == 2) return q >> 8;
+ if (offset == 3) return q & 0xff;
+ }
+ else if (offset == 4)
+ return key_id;
+
+ return 0;
+}
+
+static WRITE8_HANDLER( key_type2_w )
+{
+// logerror("CPU #%d PC %04x: keychip write %04x=%02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset,data);
+
+ if (offset < 5)
+ key[offset] = data;
+}
+
+
+/*****************************************************************************
+
+ Key custom type 3 (CUS181 - CUS185, CUS308 - CUS311)
+
+ Nibble swapper + rng + key no.
+
+*****************************************************************************/
+
+/*
+splatter: (CUS181)
+CPU #0 PC cd66: keychip write 003f=01 [maybe to initialize chip?]
+CPU #0 PC cd78: keychip read 004f [rng]
+CPU #0 PC cd91: keychip read 003f [key no.]
+CPU #0 PC f90c: keychip read 0036 [key no.]
+CPU #0 PC f91f: keychip read 0036 [key no.]
+
+rompers: (CUS182)
+CPU #0 PC b891: keychip read 0070 [key no.]
+
+blastoff: (CUS183)
+CPU #0 PC db4f: keychip read 0000 [key no.]
+CPU #0 PC db55: keychip read 0070 [rng?]
+CPU #0 PC db57: keychip write 0030=xx [ARG for 58]
+CPU #0 PC db60: keychip write 0858=xx [debug leftover?]
+CPU #0 PC db67: keychip read 0858 [debug leftover?]
+CPU #0 PC db69: keychip read 0058 [ARG >> 4) | (ARG << 4]
+CPU #0 PC e01a: keychip read 0000 [key no.]
+CPU #0 PC e021: keychip read 0070 [rng?]
+CPU #0 PC e024: keychip write 0030=xx [arg for 58]
+CPU #0 PC e037: keychip read 0058 [ARG >> 4) | (ARG << 4]
+CPU #0 PC 6989: keychip read 0000 [ignored]
+CPU #0 PC 6989: keychip read 0001 [ignored]
+
+ws89: (CUS184)
+CPU #0 PC e050: keychip read 0020 [key no.]
+CPU #0 PC e835: keychip read 0020 [key no.]
+
+tankfrce: (CUS185)
+CPU #0 PC c441: keychip read 0057 [key no.]
+CPU #0 PC c444: keychip write 0017=b9 [ARG for 2b]
+CPU #0 PC c447: keychip read 002b [0xb0 | (ARG & 0x0f)]
+CPU #0 PC f700: keychip read 0050 [key no.]
+
+dangseed: (CUS308)
+CPU #0 PC c628: keychip read 0067 [key no.]
+CPU #0 PC c62b: keychip write 0057=34 [ARG for 03]
+CPU #0 PC c62e: keychip read 0003 [0x30 | (ARG & 0x0f)]
+CPU #1 PC feb8: keychip write 0050=xx [ARG for 41 and 01]
+CPU #1 PC febb: keychip read 0041 [0x10 | (ARG >> 4)] used for stars display
+CPU #1 PC fec0: keychip read 0001 [0x10 | (ARG & 0x0f)] used for stars display
+CPU #1 PC f74d: keychip write 0050=xx [ARG for 40 and 00]
+CPU #1 PC f750: keychip read 0040 [0x00 | (ARG >> 4)] used for score display
+CPU #1 PC f755: keychip read 0000 [0x00 | (ARG & 0x0f)] used for score display
+CPU #1 PC c310: keychip write 0050=xx [ARG for 00]
+CPU #1 PC c31e: keychip read 0000 [0x00 | (ARG & 0x0f)] used for credits display
+
+pistoldm: (CUS309)
+CPU #0 PC c84a: keychip read 0017 [key no.]
+CPU #0 PC c84d: keychip write 0007=35 [ARG for 43]
+CPU #0 PC c850: keychip read 0043 [0x30 | (ARG & 0x0f)]
+CPU #0 PC cdef: keychip read 0020 [rng] used for several random events
+
+ws90: (CUS310)
+CPU #0 PC c82f: keychip read 0047 [key no.]
+CPU #0 PC c832: keychip write 007f=36 [ARG for 33]
+CPU #0 PC c835: keychip read 0033 [0x30 | (ARG & 0x0f)]
+CPU #0 PC e828: keychip read 0040 [key no.]
+
+soukobdx: (CUS311)
+CPU #0 PC ca90: keychip read 0027 [key no.]
+CPU #0 PC ca93: keychip write 0007=37 [ARG for 43]
+CPU #0 PC ca96: keychip read 0043 [0x30 | (ARG & 0x0f)]
+CPU #0 PC e45a: keychip read 0030 [discarded]
+*/
+
+static READ8_HANDLER( key_type3_r )
+{
+ int op;
+
+// logerror("CPU #%d PC %04x: keychip read %04x\n",cpu_getactivecpu(),activecpu_get_pc(),offset);
+
+ /* I need to handle blastoff's read from 0858. The game previously writes to 0858,
+ using it as temporary storage, so maybe it expects to act as RAM, however
+ it happens to work correctly also using the standard handling for 0058.
+ The schematics don't show A11 being used, so I go for this handling.
+ */
+ op = (offset & 0x70) >> 4;
+
+ if (op == key_reg) return key_id;
+ if (op == key_rng) return mame_rand(Machine);
+ if (op == key_swap4) return (key[key_swap4_arg] << 4) | (key[key_swap4_arg] >> 4);
+ if (op == key_bottom4) return (offset << 4) | (key[key_swap4_arg] & 0x0f);
+ if (op == key_top4) return (offset << 4) | (key[key_swap4_arg] >> 4);
+
+ popmessage("CPU #%d PC %08x: keychip read %04x",cpu_getactivecpu(),activecpu_get_pc(),offset);
+
+ return 0;
+}
+
+static WRITE8_HANDLER( key_type3_w )
+{
+// logerror("CPU #%d PC %04x: keychip write %04x=%02x\n",cpu_getactivecpu(),activecpu_get_pc(),offset,data);
+
+ key[(offset & 0x70) >> 4] = data;
+}
+
+
+
+/*******************************************************************************
+* *
+* Sound banking emulation (CUS121) *
+* *
+*******************************************************************************/
+
+WRITE8_HANDLER( namcos1_sound_bankswitch_w )
+{
+ UINT8 *rom = memory_region(REGION_CPU3) + 0xc000;
+
+ int bank = (data & 0x70) >> 4;
+ memory_set_bankptr(17,rom + 0x4000 * bank);
+}
+
+
+
+/*******************************************************************************
+* *
+* Banking emulation (CUS117) *
+* *
+*******************************************************************************/
+
+static int mcu_patch_data;
+static int namcos1_reset = 0;
+
+WRITE8_HANDLER( namcos1_cpu_control_w )
+{
+// logerror("reset control pc=%04x %02x\n",activecpu_get_pc(),data);
+ if ((data & 1) ^ namcos1_reset)
+ {
+ mcu_patch_data = 0;
+ namcos1_reset = data & 1;
+ }
+
+ cpunum_set_input_line(1, INPUT_LINE_RESET, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
+ cpunum_set_input_line(2, INPUT_LINE_RESET, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
+ cpunum_set_input_line(3, INPUT_LINE_RESET, (data & 1) ? CLEAR_LINE : ASSERT_LINE);
+}
+
+
+
+WRITE8_HANDLER( namcos1_watchdog_w )
+{
+ static int wdog;
+
+ wdog |= 1 << (cpu_getactivecpu());
+ if (wdog == 7 || !namcos1_reset)
+ {
+ wdog = 0;
+ watchdog_reset_w(0,0);
+ }
+}
+
+
+
+static READ8_HANDLER( soundram_r )
+{
+ if (offset < 0x1000)
+ {
+ offset &= 0x3ff;
+
+ /* CUS 30 */
+ return namcos1_cus30_r(offset);
+ }
+ else
+ {
+ offset &= 0x7ff;
+
+ /* shared ram */
+ return namcos1_triram[offset];
+ }
+}
+
+static WRITE8_HANDLER( soundram_w )
+{
+ if (offset < 0x1000)
+ {
+ offset &= 0x3ff;
+
+ /* CUS 30 */
+ namcos1_cus30_w(offset,data);
+ }
+ else
+ {
+ offset &= 0x7ff;
+
+ /* shared ram */
+ namcos1_triram[offset] = data;
+ return;
+ }
+}
+
+/* ROM handlers */
+
+static WRITE8_HANDLER( rom_w )
+{
+ logerror("CPU #%d PC %04x: warning - write %02x to rom address %04x\n",cpu_getactivecpu(),activecpu_get_pc(),data,offset);
+}
+
+/* error handlers */
+static READ8_HANDLER( unknown_r )
+{
+ logerror("CPU #%d PC %04x: warning - read from unknown chip\n",cpu_getactivecpu(),activecpu_get_pc() );
+// popmessage("CPU #%d PC %04x: read from unknown chip",cpu_getactivecpu(),activecpu_get_pc() );
+ return 0;
+}
+
+static WRITE8_HANDLER( unknown_w )
+{
+ logerror("CPU #%d PC %04x: warning - wrote to unknown chip\n",cpu_getactivecpu(),activecpu_get_pc() );
+// popmessage("CPU #%d PC %04x: wrote to unknown chip",cpu_getactivecpu(),activecpu_get_pc() );
+}
+
+/* Main bankswitching routine */
+static void set_bank(int banknum, bankhandler *handler)
+{
+ int bankstart = (banknum & 7) * 0x2000;
+ int cpunum = (banknum >> 3) & 1;
+
+ /* for BANK handlers , memory direct and OP-code base */
+ if (handler->bank_pointer)
+ memory_set_bankptr(banknum + 1, handler->bank_pointer);
+
+ /* read handlers */
+ if (!handler->bank_handler_r)
+ {
+ if (namcos1_active_bank[banknum].bank_handler_r)
+ memory_install_read8_handler(cpunum, ADDRESS_SPACE_PROGRAM, bankstart, bankstart + 0x1fff, 0, 0, ram_bank_handler_r[banknum]);
+ }
+ else
+ {
+ if (!namcos1_active_bank[banknum].bank_handler_r)
+ memory_install_read8_handler(cpunum, ADDRESS_SPACE_PROGRAM, bankstart, bankstart + 0x1fff, 0, 0, io_bank_handler_r[banknum]);
+ }
+
+ /* write handlers (except for the 0xe000-0xffff range) */
+ if (bankstart != 0xe000)
+ {
+ if (!handler->bank_handler_w)
+ {
+ if (namcos1_active_bank[banknum].bank_handler_w)
+ memory_install_write8_handler(cpunum, ADDRESS_SPACE_PROGRAM, bankstart, bankstart + 0x1fff, 0, 0, ram_bank_handler_w[banknum]);
+ }
+ else
+ {
+ if (!namcos1_active_bank[banknum].bank_handler_r)
+ memory_install_write8_handler(cpunum, ADDRESS_SPACE_PROGRAM, bankstart, bankstart + 0x1fff, 0, 0, io_bank_handler_w[banknum]);
+ }
+ }
+
+ /* Remember this bank handler */
+ namcos1_active_bank[banknum] = *handler;
+}
+
+static void namcos1_bankswitch(int cpu, offs_t offset, UINT8 data)
+{
+ static int chip[16];
+ int bank = (cpu*8) + (( offset >> 9) & 0x07);
+
+ if (offset & 1)
+ {
+ chip[bank] &= 0x0300;
+ chip[bank] |= (data & 0xff);
+ }
+ else
+ {
+ chip[bank] &= 0x00ff;
+ chip[bank] |= (data & 0x03) << 8;
+ }
+
+ set_bank(bank, &namcos1_bank_element[chip[bank]]);
+
+ /* unmapped bank warning */
+ if( namcos1_active_bank[bank].bank_handler_r == unknown_r)
+ {
+ logerror("CPU #%d PC %04x:warning unknown chip selected bank %x=$%04x\n", cpu , activecpu_get_pc(), bank , chip[bank] );
+// if (chip) popmessage("CPU #%d PC %04x:unknown chip selected bank %x=$%04x", cpu , activecpu_get_pc(), bank , chip[bank] );
+ }
+
+ /* renew pc base */
+// change_pc(activecpu_get_pc());
+}
+
+WRITE8_HANDLER( namcos1_bankswitch_w )
+{
+// logerror("cpu %d: namcos1_bankswitch_w offset %04x data %02x\n",cpu_getactivecpu(),offset,data);
+
+ namcos1_bankswitch(cpu_getactivecpu(), offset, data);
+}
+
+/* Sub cpu set start bank port */
+WRITE8_HANDLER( namcos1_subcpu_bank_w )
+{
+// logerror("namcos1_subcpu_bank_w offset %04x data %02x\n",offset,data);
+
+ /* Prepare code for CPU 1 */
+ namcos1_bankswitch( 1, 0x0e00, 0x03 );
+ namcos1_bankswitch( 1, 0x0e01, data );
+}
+
+/*******************************************************************************
+* *
+* Initialization *
+* *
+*******************************************************************************/
+
+static void namcos1_install_bank(int start,int end,read8_handler hr,write8_handler hw,
+ int offset,UINT8 *pointer)
+{
+ int i;
+ for(i=start;i<=end;i++)
+ {
+ namcos1_bank_element[i].bank_handler_r = hr;
+ namcos1_bank_element[i].bank_handler_w = hw;
+ namcos1_bank_element[i].bank_offset = offset;
+ namcos1_bank_element[i].bank_pointer = pointer;
+ offset += 0x2000;
+ if(pointer) pointer += 0x2000;
+ }
+}
+
+
+
+static void namcos1_build_banks(read8_handler key_r,write8_handler key_w)
+{
+ int i;
+
+ /**** kludge alert ****/
+ UINT8 *dummyrom = auto_malloc(0x2000);
+
+ /* when the games want to reset because the test switch has been flipped (or
+ because the protection checks failed!) they just set the top bits of bank #7
+ to 0, effectively crashing and waiting for the watchdog to kick in.
+ To avoid crashes in MAME, I prepare a dummy ROM containing just BRA -2 so
+ the program doesn't start executing code in unmapped areas.
+ Conveniently, the opcode for BRA -2 is 20 FE, and FE 20 FE is LDU $20FE,
+ so misaligned entry points get immediatly corrected. */
+ for (i = 0;i < 0x2000;i+=2)
+ {
+ dummyrom[i] = 0x20;
+ dummyrom[i+1] = 0xfe;
+ }
+ /* also provide a valid IRQ vector */
+ dummyrom[0x1ff8] = 0xff;
+ dummyrom[0x1ff9] = 0x00;
+
+ /* clear all banks to unknown area */
+ for(i = 0;i < NAMCOS1_MAX_BANK;i++)
+ namcos1_install_bank(i,i,0,unknown_w,0,dummyrom);
+ /**** end of kludge alert ****/
+
+
+ /* 3D glasses */
+ namcos1_install_bank(0x160,0x160,0,namcos1_3dcs_w,0,0);
+ /* RAM 6 banks - palette */
+ namcos1_install_bank(0x170,0x173,0,namcos1_paletteram_w,0,namcos1_paletteram);
+ /* RAM 5 banks - videoram */
+ namcos1_install_bank(0x178,0x17b,namcos1_videoram_r,namcos1_videoram_w,0,0);
+ /* key chip bank */
+ namcos1_install_bank(0x17c,0x17c,key_r,key_w,0,0);
+ /* RAM 7 banks - display control, playfields, sprites */
+ namcos1_install_bank(0x17e,0x17e,namcos1_spriteram_r,namcos1_spriteram_w,0,0);
+ /* RAM 1 shared ram, PSG device */
+ namcos1_install_bank(0x17f,0x17f,soundram_r,soundram_w,0,0);
+ /* RAM 3 banks */
+ namcos1_install_bank(0x180,0x183,0,0,0,s1ram);
+
+ /* PRG0-PRG7 */
+ {
+ UINT8 *rom = memory_region(REGION_USER1);
+
+ namcos1_install_bank(0x200,0x3ff,0,rom_w,0,rom);
+
+ /* bit 16 of the address is inverted for PRG7 (and bits 17,18 just not connected) */
+ for (i = 0x380000;i < 0x400000;i++)
+ {
+ if ((i & 0x010000) == 0)
+ {
+ UINT8 t = rom[i];
+ rom[i] = rom[i + 0x010000];
+ rom[i + 0x010000] = t;
+ }
+ }
+ }
+}
+
+MACHINE_RESET( namcos1 )
+{
+ static bankhandler unknown_handler = { unknown_r, unknown_w, 0, NULL };
+ int bank;
+
+ /* Point all of our bankhandlers to the error handlers */
+ for (bank = 0; bank < 2*8 ; bank++)
+ set_bank(bank, &unknown_handler);
+
+ /* Default MMU setup for Cpu 0 */
+ namcos1_bankswitch(0, 0x0000, 0x01 ); /* bank0 = 0x180(RAM) - evidence: wldcourt */
+ namcos1_bankswitch(0, 0x0001, 0x80 );
+ namcos1_bankswitch(0, 0x0200, 0x01 ); /* bank1 = 0x180(RAM) - evidence: berabohm */
+ namcos1_bankswitch(0, 0x0201, 0x80 );
+
+ namcos1_bankswitch(0, 0x0e00, 0x03 ); /* bank7 = 0x3ff(PRG7) */
+ namcos1_bankswitch(0, 0x0e01, 0xff );
+
+ /* Default MMU setup for Cpu 1 */
+ namcos1_bankswitch(1, 0x0000, 0x01 ); /* bank0 = 0x180(RAM) - evidence: wldcourt */
+ namcos1_bankswitch(1, 0x0001, 0x80 );
+
+ namcos1_bankswitch(1, 0x0e00, 0x03); /* bank7 = 0x3ff(PRG7) */
+ namcos1_bankswitch(1, 0x0e01, 0xff);
+
+ /* stop all CPUs */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ASSERT_LINE);
+ cpunum_set_input_line(2, INPUT_LINE_RESET, ASSERT_LINE);
+ cpunum_set_input_line(3, INPUT_LINE_RESET, ASSERT_LINE);
+
+ /* mcu patch data clear */
+ mcu_patch_data = 0;
+ namcos1_reset = 0;
+}
+
+
+
+/*******************************************************************************
+* *
+* 63701 MCU emulation (CUS64) *
+* *
+*******************************************************************************/
+
+/*******************************************************************************
+* *
+* MCU banking emulation and patch *
+* *
+*******************************************************************************/
+
+/* mcu banked rom area select */
+WRITE8_HANDLER( namcos1_mcu_bankswitch_w )
+{
+ int addr;
+
+ /* bit 2-7 : chip select line of ROM chip */
+ switch (data & 0xfc)
+ {
+ case 0xf8: addr = 0x10000; data ^= 2; break; /* bit 2 : ROM 0 (bit 1 is inverted in that case) */
+ case 0xf4: addr = 0x30000; break; /* bit 3 : ROM 1 */
+ case 0xec: addr = 0x50000; break; /* bit 4 : ROM 2 */
+ case 0xdc: addr = 0x70000; break; /* bit 5 : ROM 3 */
+ case 0xbc: addr = 0x90000; break; /* bit 6 : ROM 4 */
+ case 0x7c: addr = 0xb0000; break; /* bit 7 : ROM 5 */
+ default: addr = 0x10000; break; /* illegal */
+ }
+
+ /* bit 0-1 : address line A15-A16 */
+ addr += (data & 3) * 0x8000;
+
+ memory_set_bankptr(20, memory_region(REGION_CPU4) + addr);
+}
+
+
+
+/* This point is very obscure, but i havent found any better way yet. */
+/* Works with all games so far. */
+
+/* patch points of memory address */
+/* CPU0/1 bank[17f][1000] */
+/* CPU2 [7000] */
+/* CPU3 [c000] */
+
+/* This memory point should be set $A6 by anywhere, but */
+/* I found set $A6 only initialize in MCU */
+/* This patch kill write this data by MCU case $A6 to xx(clear) */
+
+WRITE8_HANDLER( namcos1_mcu_patch_w )
+{
+ //logerror("mcu C000 write pc=%04x data=%02x\n",activecpu_get_pc(),data);
+ if (mcu_patch_data == 0xa6) return;
+ mcu_patch_data = data;
+ namcos1_triram[0] = data;
+}
+
+
+
+/*******************************************************************************
+* *
+* driver specific initialize routine *
+* *
+*******************************************************************************/
+struct namcos1_specific
+{
+ /* keychip */
+ read8_handler key_r;
+ write8_handler key_w;
+ int key_id;
+ int key_reg1;
+ int key_reg2;
+ int key_reg3;
+ int key_reg4;
+ int key_reg5;
+ int key_reg6;
+};
+
+static void namcos1_driver_init(const struct namcos1_specific *specific )
+{
+ const struct namcos1_specific no_key =
+ {
+ no_key_r,no_key_w
+ };
+
+ if (!specific) specific = &no_key;
+
+ /* keychip id */
+ key_id = specific->key_id;
+ /* for key type 3 */
+ key_reg = specific->key_reg1;
+ key_rng = specific->key_reg2;
+ key_swap4_arg = specific->key_reg3;
+ key_swap4 = specific->key_reg4;
+ key_bottom4 = specific->key_reg5;
+ key_top4 = specific->key_reg6;
+
+ /* S1 RAM pointer set */
+ s1ram = auto_malloc(0x8000);
+ namcos1_triram = auto_malloc(0x800);
+ namcos1_paletteram = auto_malloc(0x8000);
+
+ /* Register volatile user memory for save state */
+ state_save_register_global_pointer(s1ram, 0x8000);
+ state_save_register_global_pointer(namcos1_triram, 0x800);
+ state_save_register_global_pointer(namcos1_paletteram, 0x8000);
+
+ /* Point mcu & sound shared RAM to destination */
+ memory_set_bankptr( 18, namcos1_triram );
+ memory_set_bankptr( 19, namcos1_triram );
+
+ /* build bank elements */
+ namcos1_build_banks(specific->key_r,specific->key_w);
+}
+
+
+/*******************************************************************************
+* Shadowland / Youkai Douchuuki specific *
+*******************************************************************************/
+DRIVER_INIT( shadowld )
+{
+ namcos1_driver_init(NULL);
+}
+
+/*******************************************************************************
+* Dragon Spirit specific (CUS136) *
+*******************************************************************************/
+DRIVER_INIT( dspirit )
+{
+ const struct namcos1_specific dspirit_specific=
+ {
+ key_type1_r,key_type1_w, 0x36
+ };
+ namcos1_driver_init(&dspirit_specific);
+}
+
+/*******************************************************************************
+* World Court specific (CUS143) *
+*******************************************************************************/
+DRIVER_INIT( wldcourt )
+{
+ const struct namcos1_specific worldcourt_specific=
+ {
+ key_type1_r,key_type1_w, 0x35
+ };
+ namcos1_driver_init(&worldcourt_specific);
+}
+
+/*******************************************************************************
+* Blazer specific (CUS144) *
+*******************************************************************************/
+DRIVER_INIT( blazer )
+{
+ const struct namcos1_specific blazer_specific=
+ {
+ key_type1_r,key_type1_w, 0x13
+ };
+ namcos1_driver_init(&blazer_specific);
+}
+
+/*******************************************************************************
+* Puzzle Club specific *
+*******************************************************************************/
+DRIVER_INIT( puzlclub )
+{
+ const struct namcos1_specific puzlclub_specific=
+ {
+ key_type1_r,key_type1_w, 0x35
+ };
+ namcos1_driver_init(&puzlclub_specific);
+}
+
+/*******************************************************************************
+* Pac-Mania specific (CUS151) *
+*******************************************************************************/
+DRIVER_INIT( pacmania )
+{
+ const struct namcos1_specific pacmania_specific=
+ {
+ key_type2_r,key_type2_w, 0x12
+ };
+ namcos1_driver_init(&pacmania_specific);
+}
+
+/*******************************************************************************
+* Alice in Wonderland / Marchen Maze specific (CUS152) *
+*******************************************************************************/
+DRIVER_INIT( alice )
+{
+ const struct namcos1_specific alice_specific=
+ {
+ key_type2_r,key_type2_w, 0x25
+ };
+ namcos1_driver_init(&alice_specific);
+}
+
+/*******************************************************************************
+* Galaga '88 specific (CUS153) *
+*******************************************************************************/
+DRIVER_INIT( galaga88 )
+{
+ const struct namcos1_specific galaga88_specific=
+ {
+ key_type2_r,key_type2_w, 0x31
+ };
+ namcos1_driver_init(&galaga88_specific);
+}
+
+/*******************************************************************************
+* World Stadium specific (CUS154) *
+*******************************************************************************/
+DRIVER_INIT( ws )
+{
+ const struct namcos1_specific ws_specific=
+ {
+ key_type2_r,key_type2_w, 0x07
+ };
+ namcos1_driver_init(&ws_specific);
+}
+
+/*******************************************************************************
+* Bakutotsu Kijuutei specific (CUS155) *
+*******************************************************************************/
+DRIVER_INIT( bakutotu )
+{
+ const struct namcos1_specific bakutotu_specific=
+ {
+ key_type2_r,key_type2_w, 0x22
+ };
+ namcos1_driver_init(&bakutotu_specific);
+
+#if 0
+ // resolves CPU deadlocks caused by sloppy coding(see driver\namcos1.c)
+ {
+ UINT8 target[8] = {0x34,0x37,0x35,0x37,0x96,0x00,0x2e,0xed};
+ UINT8 *rombase, *srcptr, *endptr, *scanptr;
+
+ rombase = memory_region(REGION_USER1);
+ srcptr = rombase + 0x1e000;
+ endptr = srcptr + 0xa000;
+
+ while ( (scanptr = memchr(srcptr, 0x34, endptr-srcptr)) )
+ {
+ if (!memcmp(scanptr, target, 8))
+ {
+ scanptr[7] = 0xfc;
+ srcptr = scanptr + 8;
+
+ logerror ("faulty loop patched at %06x\n", scanptr-rombase+7);
+ }
+ else
+ srcptr = scanptr + 1;
+ }
+ }
+#endif
+}
+
+/*******************************************************************************
+* Splatter House specific (CUS181) *
+*******************************************************************************/
+DRIVER_INIT( splatter )
+{
+ const struct namcos1_specific splatter_specific=
+ {
+ key_type3_r,key_type3_w, 181, 3, 4,-1,-1,-1,-1
+ };
+
+ namcos1_driver_init(&splatter_specific);
+}
+
+/*******************************************************************************
+* Rompers specific (CUS182) *
+*******************************************************************************/
+DRIVER_INIT( rompers )
+{
+ const struct namcos1_specific rompers_specific=
+ {
+ key_type3_r,key_type3_w, 182, 7,-1,-1,-1,-1,-1
+ };
+ namcos1_driver_init(&rompers_specific);
+}
+
+/*******************************************************************************
+* Blast Off specific (CUS183) *
+*******************************************************************************/
+DRIVER_INIT( blastoff )
+{
+ const struct namcos1_specific blastoff_specific=
+ {
+ key_type3_r,key_type3_w, 183, 0, 7, 3, 5,-1,-1
+ };
+ namcos1_driver_init(&blastoff_specific);
+}
+
+/*******************************************************************************
+* World Stadium '89 specific (CUS184) *
+*******************************************************************************/
+DRIVER_INIT( ws89 )
+{
+ const struct namcos1_specific ws89_specific=
+ {
+ key_type3_r,key_type3_w, 184, 2,-1,-1,-1,-1,-1
+ };
+ namcos1_driver_init(&ws89_specific);
+}
+
+/*******************************************************************************
+* Tank Force specific (CUS185) *
+*******************************************************************************/
+DRIVER_INIT( tankfrce )
+{
+ const struct namcos1_specific tankfrce_specific=
+ {
+ key_type3_r,key_type3_w, 185, 5,-1, 1,-1, 2,-1
+ };
+ namcos1_driver_init(&tankfrce_specific);
+}
+
+/*******************************************************************************
+* Dangerous Seed specific (CUS308) *
+*******************************************************************************/
+DRIVER_INIT( dangseed )
+{
+ const struct namcos1_specific dangseed_specific=
+ {
+ key_type3_r,key_type3_w, 308, 6,-1, 5,-1, 0, 4
+ };
+ namcos1_driver_init(&dangseed_specific);
+}
+
+/*******************************************************************************
+* Pistol Daimyo no Bouken specific (CUS309) *
+*******************************************************************************/
+DRIVER_INIT( pistoldm )
+{
+ const struct namcos1_specific pistoldm_specific=
+ {
+ key_type3_r,key_type3_w, 309, 1, 2, 0,-1, 4,-1
+ };
+ namcos1_driver_init(&pistoldm_specific);
+}
+
+/*******************************************************************************
+* World Stadium '90 specific (CUS310) *
+*******************************************************************************/
+DRIVER_INIT( ws90 )
+{
+ const struct namcos1_specific ws90_specific=
+ {
+ key_type3_r,key_type3_w, 310, 4,-1, 7,-1, 3,-1
+ };
+ namcos1_driver_init(&ws90_specific);
+}
+
+/*******************************************************************************
+* Souko Ban DX specific (CUS311) *
+*******************************************************************************/
+DRIVER_INIT( soukobdx )
+{
+ const struct namcos1_specific soukobdx_specific=
+ {
+ key_type3_r,key_type3_w, 311, 2, 3/*?*/, 0,-1, 4,-1
+ };
+ namcos1_driver_init(&soukobdx_specific);
+}
+
+
+
+/*******************************************************************************
+* Quester specific *
+*******************************************************************************/
+static READ8_HANDLER( quester_paddle_r )
+{
+ static int qnum=0, qstrobe=0;
+
+ if (offset == 0)
+ {
+ int ret;
+
+ if (!qnum)
+ ret = (readinputportbytag("CONTROL0")&0x90) | qstrobe | (readinputportbytag("PADDLE0")&0x0f);
+ else
+ ret = (readinputportbytag("CONTROL0")&0x90) | qstrobe | (readinputportbytag("PADDLE1")&0x0f);
+
+ qstrobe ^= 0x40;
+
+ return ret;
+ }
+ else
+ {
+ int ret;
+
+ if (!qnum)
+ ret = (readinputportbytag("CONTROL1")&0x90) | qnum | (readinputportbytag("PADDLE0")>>4);
+ else
+ ret = (readinputportbytag("CONTROL1")&0x90) | qnum | (readinputportbytag("PADDLE1")>>4);
+
+ if (!qstrobe) qnum ^= 0x20;
+
+ return ret;
+ }
+}
+
+DRIVER_INIT( quester )
+{
+ namcos1_driver_init(NULL);
+ memory_install_read8_handler(3, ADDRESS_SPACE_PROGRAM, 0x1400, 0x1401, 0, 0, quester_paddle_r);
+}
+
+
+
+/*******************************************************************************
+* Beraboh Man specific *
+*******************************************************************************/
+
+static READ8_HANDLER( berabohm_buttons_r )
+{
+ int res;
+ static int input_count, strobe, strobe_count;
+
+
+ if (offset == 0)
+ {
+ int inp = input_count;
+
+ if (inp == 4) res = readinputportbytag("CONTROL0");
+ else
+ {
+ char portname[4];
+
+#ifdef PRESSURE_SENSITIVE
+ static int counter[4];
+
+ sprintf(portname,"IN%d",inp); /* IN0-IN3 */
+ res = readinputportbytag(portname);
+ if (res & 0x80)
+ {
+ if (counter[inp] >= 0)
+ res = 0x40 | counter[inp];
+ else
+ {
+ if (res & 0x40) res = 0x40;
+ else res = 0x00;
+ }
+ }
+ else if (res & 0x40)
+ {
+ if (counter[inp] < 0x3f)
+ {
+ counter[inp] += 4;
+ res = 0x00;
+ }
+ else res = 0x7f;
+ }
+ else
+ counter[inp] = -1;
+#else
+ sprintf(portname,"IN%d",inp); /* IN0-IN3 */
+ res = readinputportbytag(portname);
+ if (res & 1) res = 0x7f; /* weak */
+ else if (res & 2) res = 0x48; /* medium */
+ else if (res & 4) res = 0x40; /* strong */
+#endif
+ }
+
+ return res;
+ }
+ else
+ {
+ res = readinputportbytag("CONTROL1") & 0x8f;
+
+ /* the strobe cannot happen too often, otherwise the MCU will waste too
+ much time reading the inputs and won't have enough cycles to play two
+ digital sounds at once. This value is enough to read all inputs at least
+ once per frame */
+ if (++strobe_count > 4)
+ {
+ strobe_count = 0;
+ strobe ^= 0x40;
+ if (strobe == 0)
+ {
+ input_count = (input_count + 1) % 5;
+ if (input_count == 3) res |= 0x10;
+ }
+ }
+
+ res |= strobe;
+
+ return res;
+ }
+}
+
+DRIVER_INIT( berabohm )
+{
+ namcos1_driver_init(NULL);
+ memory_install_read8_handler(3, ADDRESS_SPACE_PROGRAM, 0x1400, 0x1401, 0, 0, berabohm_buttons_r);
+}
+
+
+
+/*******************************************************************************
+* Face Off specific *
+*******************************************************************************/
+
+static READ8_HANDLER( faceoff_inputs_r )
+{
+ int res;
+ static int input_count, strobe_count, stored_input[2];
+
+ if (offset == 0)
+ {
+ res = (readinputportbytag("CONTROL0") & 0x80) | stored_input[0];
+
+ return res;
+ }
+ else
+ {
+ res = readinputportbytag("CONTROL1") & 0x80;
+
+ /* the strobe cannot happen too often, otherwise the MCU will waste too
+ much time reading the inputs and won't have enough cycles to play two
+ digital sounds at once. This value is enough to read all inputs at least
+ once per frame */
+ if (++strobe_count > 8)
+ {
+ strobe_count = 0;
+
+ res |= input_count;
+
+ switch (input_count)
+ {
+ case 0:
+ stored_input[0] = readinputportbytag("IN0") & 0x1f;
+ stored_input[1] = (readinputportbytag("IN3") & 0x07) << 3;
+
+ case 3:
+ stored_input[0] = readinputportbytag("IN2") & 0x1f;
+
+ case 4:
+ stored_input[0] = readinputportbytag("IN1") & 0x1f;
+ stored_input[1] = readinputportbytag("IN3") & 0x18;
+ }
+
+ input_count = (input_count + 1) & 7;
+ }
+ else
+ {
+ res |= 0x40 | stored_input[1];
+ }
+
+ return res;
+ }
+}
+
+DRIVER_INIT( faceoff )
+{
+ namcos1_driver_init(NULL);
+ memory_install_read8_handler(3, ADDRESS_SPACE_PROGRAM, 0x1400, 0x1401, 0, 0, faceoff_inputs_r);
+}
diff --git a/src/mame/machine/namcos2.c b/src/mame/machine/namcos2.c
new file mode 100644
index 00000000000..024f45e32b8
--- /dev/null
+++ b/src/mame/machine/namcos2.c
@@ -0,0 +1,849 @@
+/***************************************************************************
+
+Namco System II
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6809/m6809.h"
+#include "cpu/m6805/m6805.h"
+#include "namcos2.h"
+
+extern void namcos21_kickstart(int);
+
+int namcos2_gametype;
+
+static unsigned mFinalLapProtCount;
+
+READ16_HANDLER( namcos2_flap_prot_r )
+{
+ static const UINT16 table0[8] = { 0x0000,0x0040,0x0440,0x2440,0x2480,0xa080,0x8081,0x8041 };
+ static const UINT16 table1[8] = { 0x0040,0x0060,0x0060,0x0860,0x0864,0x08e4,0x08e5,0x08a5 };
+ UINT16 data;
+
+ switch( offset )
+ {
+ case 0:
+ data = 0x0101;
+ break;
+
+ case 1:
+ data = 0x3e55;
+ break;
+
+ case 2:
+ data = table1[mFinalLapProtCount&7];
+ data = (data&0xff00)>>8;
+ break;
+
+ case 3:
+ data = table1[mFinalLapProtCount&7];
+ mFinalLapProtCount++;
+ data = data&0x00ff;
+ break;
+
+ case 0x3fffc/2:
+ data = table0[mFinalLapProtCount&7];
+ data = data&0xff00;
+ break;
+
+ case 0x3fffe/2:
+ data = table0[mFinalLapProtCount&7];
+ mFinalLapProtCount++;
+ data = (data&0x00ff)<<8;
+ break;
+
+ default:
+ data = 0;
+ }
+ return data;
+}
+
+/*************************************************************/
+/* Perform basic machine initialisation */
+/*************************************************************/
+
+#define namcos2_eeprom_size 0x2000
+static UINT8 *namcos2_eeprom;
+
+static void
+ResetAllSubCPUs( int state )
+{
+ cpunum_set_input_line(CPU_SLAVE, INPUT_LINE_RESET, state);
+ cpunum_set_input_line(CPU_MCU, INPUT_LINE_RESET, state);
+ switch( namcos2_gametype )
+ {
+ case NAMCOS21_SOLVALOU:
+ case NAMCOS21_STARBLADE:
+ case NAMCOS21_AIRCOMBAT:
+ case NAMCOS21_CYBERSLED:
+ cpunum_set_input_line(4,INPUT_LINE_RESET,state); /* MASTER DSP */
+ cpunum_set_input_line(5,INPUT_LINE_RESET,state); /* SLAVE DSP */
+ break;
+
+// case NAMCOS21_WINRUN91:
+// case NAMCOS21_DRIVERS_EYES:
+ default:
+ break;
+ }
+}
+
+MACHINE_RESET( namcos2 ){
+ int loop;
+ mFinalLapProtCount = 0;
+
+ /* Initialise the bank select in the sound CPU */
+ namcos2_sound_bankselect_w(0,0); /* Page in bank 0 */
+
+ cpunum_set_input_line(CPU_SOUND, INPUT_LINE_RESET, ASSERT_LINE );
+
+ /* Place CPU2 & CPU3 into the reset condition */
+ ResetAllSubCPUs( ASSERT_LINE );
+
+ /* Initialise interrupt handlers */
+ for(loop=0;loop<0x20;loop++)
+ {
+ namcos2_68k_master_C148[loop]=0;
+ namcos2_68k_slave_C148[loop]=0;
+ namcos2_68k_gpu_C148[loop]=0;
+ }
+}
+
+/*************************************************************/
+/* EEPROM Load/Save and read/write handling */
+/*************************************************************/
+
+NVRAM_HANDLER( namcos2 )
+{
+ if( !namcos2_eeprom )
+ {
+ namcos2_eeprom = auto_malloc(namcos2_eeprom_size);
+ }
+ if( read_or_write )
+ {
+ mame_fwrite( file, namcos2_eeprom, namcos2_eeprom_size );
+ }
+ else
+ {
+ if( file )
+ {
+ mame_fread( file, namcos2_eeprom, namcos2_eeprom_size );
+ }
+ else
+ {
+ int pat = 0xff; /* default */
+ if( namcos2_gametype == NAMCOS21_STARBLADE )
+ {
+ pat = 0x00;
+ }
+ memset( namcos2_eeprom, pat, namcos2_eeprom_size );
+ }
+ }
+}
+
+WRITE16_HANDLER( namcos2_68k_eeprom_w ){
+ if( ACCESSING_LSB )
+ {
+ namcos2_eeprom[offset] = data;
+ }
+}
+
+READ16_HANDLER( namcos2_68k_eeprom_r ){
+ return namcos2_eeprom[offset];
+}
+
+/*************************************************************/
+/* 68000 Shared memory area - Data ROM area */
+/*************************************************************/
+READ16_HANDLER( namcos2_68k_data_rom_r ){
+ UINT16 *ROM = (UINT16 *)memory_region(REGION_USER1);
+ return ROM[offset];
+}
+
+
+
+/**************************************************************/
+/* 68000 Shared serial communications processor (CPU5?) */
+/**************************************************************/
+
+UINT16 namcos2_68k_serial_comms_ctrl[0x8];
+UINT16 *namcos2_68k_serial_comms_ram;
+
+READ16_HANDLER( namcos2_68k_serial_comms_ram_r ){
+ return namcos2_68k_serial_comms_ram[offset];
+}
+
+WRITE16_HANDLER( namcos2_68k_serial_comms_ram_w ){
+ COMBINE_DATA( &namcos2_68k_serial_comms_ram[offset] );
+}
+
+READ16_HANDLER( namcos2_68k_serial_comms_ctrl_r )
+{
+ UINT16 retval = namcos2_68k_serial_comms_ctrl[offset];
+
+ switch(offset){
+ case 0x00:
+ retval |= 0x0004; /* Set READY? status bit */
+ break;
+
+ default:
+ break;
+ }
+ return retval;
+}
+
+WRITE16_HANDLER( namcos2_68k_serial_comms_ctrl_w )
+{
+ COMBINE_DATA( &namcos2_68k_serial_comms_ctrl[offset] );
+}
+
+/*************************************************************/
+/* 68000 Shared protection/random key generator */
+/*************************************************************
+
+Custom chip ID numbers:
+
+Game Year ID (dec) ID (hex)
+-------- ---- --- -----
+finallap 1987
+assault 1988 unused
+metlhawk 1988
+ordyne 1988 176 $00b0
+mirninja 1988 177 $00b1
+phelios 1988 178 $00b2 readme says 179
+dirtfoxj 1989 180 $00b4
+fourtrax 1989
+valkyrie 1989
+finehour 1989 188 $00bc
+burnforc 1989 189 $00bd
+marvland 1989 190 $00be
+kyukaidk 1990 191 $00bf
+dsaber 1990 192 $00c0
+finalap2 1990 318 $013e
+rthun2 1990 319 $013f
+gollygho 1990 $0143
+cosmogng 1991 330 $014a
+sgunner2 1991 346 $015a ID out of order; gfx board is not standard
+finalap3 1992 318 $013e same as finalap2
+suzuka8h 1992
+sws92 1992 331 $014b
+sws92g 1992 332 $014c
+suzuk8h2 1993
+sws93 1993 334 $014e
+ *************************************************************/
+static int sendval = 0;
+READ16_HANDLER( namcos2_68k_key_r )
+{
+ switch (namcos2_gametype)
+ {
+ case NAMCOS2_ORDYNE:
+ switch(offset)
+ {
+ case 2: return 0x1001;
+ case 3: return 0x1;
+ case 4: return 0x110;
+ case 5: return 0x10;
+ case 6: return 0xB0;
+ case 7: return 0xB0;
+ }
+ break;
+
+ case NAMCOS2_STEEL_GUNNER_2:
+ switch( offset )
+ {
+ case 4: return 0x15a;
+ }
+ break;
+
+ case NAMCOS2_MIRAI_NINJA:
+ switch(offset)
+ {
+ case 7: return 0xB1;
+ }
+ break;
+
+ case NAMCOS2_PHELIOS:
+ switch(offset)
+ {
+ case 0: return 0xF0;
+ case 1: return 0xFF0;
+ case 2: return 0xB2;
+ case 3: return 0xB2;
+ case 4: return 0xF;
+ case 5: return 0xF00F;
+ case 7: return 0xB2;
+ }
+ break;
+
+ case NAMCOS2_DIRT_FOX_JP:
+ switch(offset)
+ {
+ case 1: return 0xB4;
+ }
+ break;
+
+ case NAMCOS2_FINEST_HOUR:
+ switch(offset)
+ {
+ case 7: return 0xBC;
+ }
+ break;
+
+ case NAMCOS2_BURNING_FORCE:
+ switch(offset)
+ {
+ case 1: return 0xBD;
+ case 7: return 0xBD;
+ }
+ break;
+
+ case NAMCOS2_MARVEL_LAND:
+ switch(offset)
+ {
+ case 0: return 0x10;
+ case 1: return 0x110;
+ case 4: return 0xBE;
+ case 6: return 0x1001;
+ case 7: return (sendval==1)?0xBE:1;
+ }
+ break;
+
+ case NAMCOS2_DRAGON_SABER:
+ switch(offset)
+ {
+ case 2: return 0xC0;
+ }
+ break;
+
+ case NAMCOS2_ROLLING_THUNDER_2:
+ switch(offset)
+ {
+ case 4:
+ if( sendval == 1 ){
+ sendval = 0;
+ return 0x13F;
+ }
+ break;
+ case 7:
+ if( sendval == 1 ){
+ sendval = 0;
+ return 0x13F;
+ }
+ break;
+ case 2: return 0;
+ }
+ break;
+
+ case NAMCOS2_COSMO_GANG:
+ switch(offset)
+ {
+ case 3: return 0x14A;
+ }
+ break;
+
+ case NAMCOS2_SUPER_WSTADIUM:
+ switch(offset)
+ {
+ // case 3: return 0x142;
+ case 4: return 0x142;
+ // case 3: popmessage("blah %08x",activecpu_get_pc());
+ default: return mame_rand(Machine);
+ }
+ break;
+
+ case NAMCOS2_SUPER_WSTADIUM_92:
+ switch(offset)
+ {
+ case 3: return 0x14B;
+ }
+ break;
+
+ case NAMCOS2_SUPER_WSTADIUM_92T:
+ switch(offset)
+ {
+ case 3: return 0x14C;
+ }
+ break;
+
+ case NAMCOS2_SUPER_WSTADIUM_93:
+ switch(offset)
+ {
+ case 3: return 0x14E;
+ }
+ break;
+
+ case NAMCOS2_SUZUKA_8_HOURS_2:
+ switch(offset)
+ {
+ case 3: return 0x14D;
+ case 2: return 0;
+ }
+ break;
+
+ case NAMCOS2_GOLLY_GHOST:
+ switch(offset)
+ {
+ case 0: return 2;
+ case 1: return 2;
+ case 2: return 0;
+ case 4: return 0x143;
+ }
+ break;
+
+
+ case NAMCOS2_BUBBLE_TROUBLE:
+ switch(offset)
+ {
+ case 0: return 2; // not verified
+ case 1: return 2; // not verified
+ case 2: return 0; // not verified
+ case 4: return 0x141;
+ }
+ break;
+ }
+
+
+
+ return mame_rand(Machine)&0xffff;
+}
+
+WRITE16_HANDLER( namcos2_68k_key_w )
+{
+ if( namcos2_gametype == NAMCOS2_MARVEL_LAND && offset == 5 )
+ {
+ if (data == 0x615E) sendval = 1;
+ }
+ if( namcos2_gametype == NAMCOS2_ROLLING_THUNDER_2 && offset == 4 )
+ {
+ if (data == 0x13EC) sendval = 1;
+ }
+ if( namcos2_gametype == NAMCOS2_ROLLING_THUNDER_2 && offset == 7 )
+ {
+ if (data == 0x13EC) sendval = 1;
+ }
+ if( namcos2_gametype == NAMCOS2_MARVEL_LAND && offset == 6 )
+ {
+ if (data == 0x1001) sendval = 0;
+ }
+}
+
+/*************************************************************/
+/* 68000 Interrupt/IO Handlers - CUSTOM 148 - NOT SHARED */
+/*************************************************************/
+
+#define NO_OF_LINES 256
+#define FRAME_TIME (1.0/60.0)
+#define LINE_LENGTH (FRAME_TIME/NO_OF_LINES)
+
+UINT16 namcos2_68k_master_C148[0x20];
+UINT16 namcos2_68k_slave_C148[0x20];
+UINT16 namcos2_68k_gpu_C148[0x20];
+
+
+static int IsSystem21( void )
+{
+ switch( namcos2_gametype )
+ {
+ case NAMCOS21_AIRCOMBAT:
+ case NAMCOS21_STARBLADE:
+ case NAMCOS21_CYBERSLED:
+ case NAMCOS21_SOLVALOU:
+ case NAMCOS21_WINRUN91:
+ case NAMCOS21_DRIVERS_EYES:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static UINT16
+ReadWriteC148( int cpu, offs_t offset, UINT16 data, int bWrite )
+{
+ offs_t addr = ((offset*2)+0x1c0000)&0x1fe000;
+ UINT16 *pC148Reg = NULL;
+ UINT16 *pC148RegAlt = NULL;
+ UINT16 result = 0;
+ int altCPU = 0;
+
+ switch( cpu )
+ {
+ case CPU_MASTER:
+ pC148Reg = namcos2_68k_master_C148;
+ altCPU = CPU_SLAVE;
+ pC148RegAlt = namcos2_68k_slave_C148;
+ break;
+
+ case CPU_SLAVE:
+ pC148Reg = namcos2_68k_slave_C148;
+ altCPU = CPU_MASTER;
+ pC148RegAlt = namcos2_68k_master_C148;
+ break;
+
+ case CPU_GPU:
+ pC148Reg = namcos2_68k_gpu_C148;
+ altCPU = CPU_MASTER;
+ pC148RegAlt = namcos2_68k_master_C148;
+ break;
+ }
+
+ if( bWrite )
+ {
+ pC148Reg[(addr>>13)&0x1f] = data&0x0007;
+ }
+
+ switch(addr)
+ {
+ case 0x1c0000: break; /* NAMCOS2_C148_0 level */
+ case 0x1c2000: break; /* NAMCOS2_C148_1 level */
+ case 0x1c4000: break; /* NAMCOS2_C148_2 level */
+ case 0x1c6000: break; /* NAMCOS2_C148_CPUIRQ level */
+ case 0x1c8000: break; /* NAMCOS2_C148_EXIRQ level */
+ case 0x1ca000: break; /* NAMCOS2_C148_POSIRQ level */
+ case 0x1cc000: break; /* NAMCOS2_C148_SERIRQ level */
+ case 0x1ce000: break; /* NAMCOS2_C148_VBLANKIRQ level */
+
+ case 0x1d0000:
+ if( bWrite )
+ {
+ cpunum_set_input_line(altCPU, pC148RegAlt[NAMCOS2_C148_CPUIRQ], ASSERT_LINE);
+ } cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_0], CLEAR_LINE);
+ break;
+
+ case 0x1d2000:
+ cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_1], CLEAR_LINE);
+ break;
+
+ case 0x1d4000:
+ if( bWrite )
+ {
+ cpunum_set_input_line(altCPU, pC148RegAlt[NAMCOS2_C148_CPUIRQ], ASSERT_LINE);
+ }
+ cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_2], CLEAR_LINE);
+ break;
+
+ case 0x1d6000:
+ if( bWrite )
+ {
+ // mame_printf_debug( "cpu(%d) RAM[0x%06x] = 0x%x\n", cpu, addr, data );
+ }
+ cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_CPUIRQ], CLEAR_LINE);
+ break;
+
+ case 0x1d8000: /* ack EXIRQ */
+ if( bWrite )
+ {
+ // mame_printf_debug( "cpu(%d) RAM[0x%06x] = 0x%x\n", cpu, addr, data );
+ }
+ cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_EXIRQ], CLEAR_LINE);
+ break;
+
+ case 0x1da000: /* ack POSIRQ */
+ if( bWrite )
+ {
+ // mame_printf_debug( "cpu(%d) RAM[0x%06x] = 0x%x\n", cpu, addr, data );
+ }
+ cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_POSIRQ], CLEAR_LINE);
+ break;
+
+ case 0x1dc000: /* ack SCIRQ */
+ if( bWrite )
+ {
+ // mame_printf_debug( "cpu(%d) RAM[0x%06x] = 0x%x\n", cpu, addr, data );
+ }
+ cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_SERIRQ], CLEAR_LINE);
+ break;
+
+ case 0x1de000: /* ack VBLANK */
+ cpunum_set_input_line(cpu, pC148Reg[NAMCOS2_C148_VBLANKIRQ], CLEAR_LINE);
+ break;
+
+ case 0x1e0000: /* EEPROM Status Register */
+ result = ~0; /* Only BIT0 used: 1=EEPROM READY 0=EEPROM BUSY */
+ break;
+
+ case 0x1e2000: /* Sound CPU Reset control */
+ if( cpu == CPU_MASTER ) /* ? */
+ {
+ if( data&0x01 )
+ {
+ /* Resume execution */
+ cpunum_set_input_line(CPU_SOUND, INPUT_LINE_RESET, CLEAR_LINE);
+ cpu_yield();
+ }
+ else
+ {
+ /* Suspend execution */
+ cpunum_set_input_line(CPU_SOUND, INPUT_LINE_RESET, ASSERT_LINE);
+ }
+ if( IsSystem21() )
+ {
+ //printf( "dspkick=0x%x\n", data );
+ if( data&4 )
+ {
+ namcos21_kickstart(1);
+ }
+ }
+ }
+ break;
+
+ case 0x1e4000: /* Alt 68000 & IO CPU Reset */
+ if( cpu == CPU_MASTER ) /* ? */
+ {
+ if( data&0x01 )
+ { /* Resume execution */
+ ResetAllSubCPUs( CLEAR_LINE );
+ /* Give the new CPU an immediate slice of the action */
+ cpu_yield();
+ }
+ else
+ { /* Suspend execution */
+ ResetAllSubCPUs( ASSERT_LINE );
+ }
+ }
+ break;
+
+ case 0x1e6000: /* Watchdog reset kicker */
+ /* watchdog_reset_w(0,0); */
+ break;
+
+ default:
+ break;
+ }
+ return result;
+}
+
+WRITE16_HANDLER( namcos2_68k_master_C148_w )
+{
+ (void)ReadWriteC148( CPU_MASTER, offset, data, 1 );
+}
+
+READ16_HANDLER( namcos2_68k_master_C148_r )
+{
+ return ReadWriteC148( CPU_MASTER, offset, 0, 0 );
+}
+
+WRITE16_HANDLER( namcos2_68k_slave_C148_w )
+{
+ (void)ReadWriteC148( CPU_SLAVE, offset, data, 1 );
+}
+
+READ16_HANDLER( namcos2_68k_slave_C148_r )
+{
+ return ReadWriteC148( CPU_SLAVE, offset, 0, 0 );
+}
+
+WRITE16_HANDLER( namcos2_68k_gpu_C148_w )
+{
+ (void)ReadWriteC148( CPU_GPU, offset, data, 1 );
+}
+
+READ16_HANDLER( namcos2_68k_gpu_C148_r )
+{
+ return ReadWriteC148( CPU_GPU, offset, 0, 0 );
+}
+
+static TIMER_CALLBACK( namcos2_68k_master_posirq )
+{
+ video_screen_update_partial(0, param);
+ cpunum_set_input_line(CPU_MASTER , namcos2_68k_master_C148[NAMCOS2_C148_POSIRQ] , ASSERT_LINE);
+}
+
+static int
+GetPosIRQScanline( void )
+{
+ if( IsSystem21() ) return 0;
+ return namcos2_GetPosIrqScanline();
+}
+
+INTERRUPT_GEN( namcos2_68k_master_vblank )
+{
+ if( IsSystem21()==0 && namcos2_68k_master_C148[NAMCOS2_C148_POSIRQ] )
+ {
+ int scanline = GetPosIRQScanline();
+ timer_set(video_screen_get_time_until_pos(0, scanline, 0), scanline, namcos2_68k_master_posirq );
+ }
+ cpunum_set_input_line( CPU_MASTER, namcos2_68k_master_C148[NAMCOS2_C148_VBLANKIRQ], HOLD_LINE);
+}
+
+static TIMER_CALLBACK( namcos2_68k_slave_posirq )
+{
+ video_screen_update_partial(0, param);
+ cpunum_set_input_line(CPU_SLAVE , namcos2_68k_slave_C148[NAMCOS2_C148_POSIRQ] , ASSERT_LINE);
+}
+
+INTERRUPT_GEN( namcos2_68k_slave_vblank )
+{
+ if( IsSystem21()==0 && namcos2_68k_slave_C148[NAMCOS2_C148_POSIRQ] )
+ {
+ int scanline = GetPosIRQScanline();
+ timer_set(video_screen_get_time_until_pos(0, scanline, 0), scanline, namcos2_68k_slave_posirq );
+ }
+ cpunum_set_input_line( CPU_SLAVE, namcos2_68k_slave_C148[NAMCOS2_C148_VBLANKIRQ], HOLD_LINE);
+}
+
+static TIMER_CALLBACK( namcos2_68k_gpu_posirq )
+{
+ //printf( "namcos2_68k_gpu_posirq(%d)\n", param );
+ video_screen_update_partial(0, param);
+ cpunum_set_input_line(CPU_GPU, namcos2_68k_gpu_C148[NAMCOS2_C148_POSIRQ] , ASSERT_LINE);
+}
+
+INTERRUPT_GEN( namcos2_68k_gpu_vblank )
+{
+ //printf( "namcos2_68k_gpu_vblank(%d)\n",namcos2_68k_gpu_C148[NAMCOS2_C148_POSIRQ] );
+ if( namcos2_68k_gpu_C148[NAMCOS2_C148_POSIRQ] )
+ {
+ int scanline = 0x50+0x89; /* HACK for Winning Run */
+ timer_set(video_screen_get_time_until_pos(0, scanline, 0), scanline, namcos2_68k_gpu_posirq );
+ }
+ cpunum_set_input_line( CPU_GPU, namcos2_68k_gpu_C148[NAMCOS2_C148_VBLANKIRQ], HOLD_LINE);
+}
+
+/**************************************************************/
+/* Sound sub-system */
+/**************************************************************/
+
+WRITE8_HANDLER( namcos2_sound_bankselect_w )
+{
+ UINT8 *RAM=memory_region(REGION_CPU3);
+ UINT32 max = (memory_region_length(REGION_CPU3) - 0x10000) / 0x4000;
+ int bank = ( data >> 4 ) % max; /* 991104.CAB */
+ memory_set_bankptr( CPU3_ROM1, &RAM[ 0x10000 + ( 0x4000 * bank ) ] );
+}
+
+/**************************************************************/
+/* */
+/* 68705 IO CPU Support functions */
+/* */
+/**************************************************************/
+
+static int namcos2_mcu_analog_ctrl=0;
+static int namcos2_mcu_analog_data=0xaa;
+static int namcos2_mcu_analog_complete=0;
+
+WRITE8_HANDLER( namcos2_mcu_analog_ctrl_w )
+{
+ namcos2_mcu_analog_ctrl=data&0xff;
+
+ /* Check if this is a start of conversion */
+ /* Input ports 2 thru 9 are the analog channels */
+ if(data&0x40)
+ {
+ /* Set the conversion complete flag */
+ namcos2_mcu_analog_complete=2;
+ /* We convert instantly, good eh! */
+ switch((data>>2)&0x07)
+ {
+ case 0:
+ namcos2_mcu_analog_data=input_port_2_r(0);
+ break;
+ case 1:
+ namcos2_mcu_analog_data=input_port_3_r(0);
+ break;
+ case 2:
+ namcos2_mcu_analog_data=input_port_4_r(0);
+ break;
+ case 3:
+ namcos2_mcu_analog_data=input_port_5_r(0);
+ break;
+ case 4:
+ namcos2_mcu_analog_data=input_port_6_r(0);
+ break;
+ case 5:
+ namcos2_mcu_analog_data=input_port_7_r(0);
+ break;
+ case 6:
+ namcos2_mcu_analog_data=input_port_8_r(0);
+ break;
+ case 7:
+ namcos2_mcu_analog_data=input_port_9_r(0);
+ break;
+ }
+#if 0
+ /* Perform the offset handling on the input port */
+ /* this converts it to a twos complement number */
+ if( namcos2_gametype==NAMCOS2_DIRT_FOX ||
+ namcos2_gametype==NAMCOS2_DIRT_FOX_JP )
+ {
+ namcos2_mcu_analog_data^=0x80;
+ }
+#endif
+ /* If the interrupt enable bit is set trigger an A/D IRQ */
+ if(data&0x20)
+ {
+ cpunum_set_input_line( CPU_MCU, HD63705_INT_ADCONV , PULSE_LINE);
+ }
+ }
+}
+
+READ8_HANDLER( namcos2_mcu_analog_ctrl_r )
+{
+ int data=0;
+
+ /* ADEF flag is only cleared AFTER a read from control THEN a read from DATA */
+ if(namcos2_mcu_analog_complete==2) namcos2_mcu_analog_complete=1;
+ if(namcos2_mcu_analog_complete) data|=0x80;
+
+ /* Mask on the lower 6 register bits, Irq EN/Channel/Clock */
+ data|=namcos2_mcu_analog_ctrl&0x3f;
+ /* Return the value */
+ return data;
+}
+
+WRITE8_HANDLER( namcos2_mcu_analog_port_w )
+{
+}
+
+READ8_HANDLER( namcos2_mcu_analog_port_r )
+{
+ if(namcos2_mcu_analog_complete==1) namcos2_mcu_analog_complete=0;
+ return namcos2_mcu_analog_data;
+}
+
+WRITE8_HANDLER( namcos2_mcu_port_d_w )
+{
+ /* Undefined operation on write */
+}
+
+READ8_HANDLER( namcos2_mcu_port_d_r )
+{
+ /* Provides a digital version of the analog ports */
+ int threshold=0x7f;
+ int data=0;
+
+ /* Read/convert the bits one at a time */
+ if(input_port_2_r(0)>threshold) data|=0x01;
+ if(input_port_3_r(0)>threshold) data|=0x02;
+ if(input_port_4_r(0)>threshold) data|=0x04;
+ if(input_port_5_r(0)>threshold) data|=0x08;
+ if(input_port_6_r(0)>threshold) data|=0x10;
+ if(input_port_7_r(0)>threshold) data|=0x20;
+ if(input_port_8_r(0)>threshold) data|=0x40;
+ if(input_port_9_r(0)>threshold) data|=0x80;
+
+ /* Return the result */
+ return data;
+}
+
+READ8_HANDLER( namcos2_input_port_0_r )
+{
+ int data=readinputport(0);
+ return data;
+}
+
+READ8_HANDLER( namcos2_input_port_10_r )
+{
+ int data=readinputport(10);
+ return data;
+}
+
+READ8_HANDLER( namcos2_input_port_12_r )
+{
+ int data=readinputport(12);
+ return data;
+}
diff --git a/src/mame/machine/nb1413m3.c b/src/mame/machine/nb1413m3.c
new file mode 100644
index 00000000000..1b45a3ab7ba
--- /dev/null
+++ b/src/mame/machine/nb1413m3.c
@@ -0,0 +1,708 @@
+/******************************************************************************
+
+ Machine Hardware for Nichibutsu Mahjong series.
+
+ Driver by Takahiro Nogi <nogi@kt.rim.or.jp> 1999/11/05 -
+
+******************************************************************************/
+/******************************************************************************
+Memo:
+
+******************************************************************************/
+
+#include "driver.h"
+#include "cpu/z80/z80.h"
+#include "nb1413m3.h"
+
+
+#define NB1413M3_DEBUG 0
+#define NB1413M3_CHEAT 0
+
+
+int nb1413m3_type;
+int nb1413m3_sndromregion;
+int nb1413m3_sndrombank1;
+int nb1413m3_sndrombank2;
+int nb1413m3_busyctr;
+int nb1413m3_busyflag;
+int nb1413m3_inputport;
+UINT8 *nb1413m3_nvram;
+size_t nb1413m3_nvram_size;
+
+static int nb1413m3_74ls193_counter;
+static int nb1413m3_nmi_count; // for debug
+static int nb1413m3_nmi_clock;
+static int nb1413m3_nmi_enable;
+static int nb1413m3_counter;
+static int nb1413m3_gfxradr_l;
+static int nb1413m3_gfxradr_h;
+static int nb1413m3_gfxrombank;
+static int nb1413m3_outcoin_enable;
+static int nb1413m3_outcoin_flag;
+
+
+#define NB1413M3_TIMER_BASE 20000000
+static TIMER_CALLBACK( nb1413m3_timer_callback )
+{
+ timer_set(attotime_mul(ATTOTIME_IN_HZ(NB1413M3_TIMER_BASE), 256), 0, nb1413m3_timer_callback);
+
+ nb1413m3_74ls193_counter++;
+ nb1413m3_74ls193_counter &= 0x0f;
+
+ if (nb1413m3_74ls193_counter == 0x0f)
+ {
+
+ if (nb1413m3_nmi_enable)
+ {
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+ nb1413m3_nmi_count++;
+ }
+
+#if 1
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_TAIWANMB:
+ nb1413m3_74ls193_counter = 0x05; // 130 ???
+ break;
+ case NB1413M3_OMOTESND:
+ nb1413m3_74ls193_counter = 0x05; // 130 ???
+ break;
+ case NB1413M3_PASTELG:
+ nb1413m3_74ls193_counter = 0x02; // 96 ???
+ break;
+ case NB1413M3_HYHOO:
+ case NB1413M3_HYHOO2:
+ nb1413m3_74ls193_counter = 0x05; // 128 ???
+ break;
+ }
+#endif
+ }
+
+#if 0
+ // nbmj1413m3_nmi_clock_w ?w??
+ // ----------------------------------------------------------------------------------------------------------------
+ // nbmj8688 Z80:5.00MHz (20000000/4)
+ // 7 144-145 mjsikaku, mjsikakb, otonano, mjcamera
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // nbmj8891 Z80:5.00MHz (20000000/4)
+ // 7 144-145 msjiken, telmahjn, mjcamerb, mmcamera
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // nbmj8688 Z80:5.00MHz (20000000/4)
+ // 6 130-131 kaguya, kaguya2, idhimitu
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // nbmj8891 Z80:5.00MHz (20000000/4)
+ // 6 130-131 hanamomo, gionbana, mgion, abunai, mjfocus, mjfocusm, peepshow, scandal, scandalm, mgmen89,
+ // mjnanpas, mjnanpaa, mjnanpau, bananadr, mladyhtr, chinmoku, club90s, club90sa, lovehous,
+ // maiko, mmaiko, hanaoji, pairsten
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // nbmj8991 Z80:5MHz (25000000/5)
+ // 6 130-131 galkoku, hyouban, galkaika, tokyogal, tokimbsj, mcontest, uchuuai
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // nbmj8688 Z80:5.00MHz (20000000/4)
+ // 6 81- 82 crystalg(DAC?????x??), crystal2(DAC?????x??)
+ // 6 130-131 bijokkoy(?A?j????), bijokkog(?A?j????)
+
+ // ----------------------------------------------------------------------------------------------------------------
+ // nbmj8688 Z80:5.00MHz (20000000/4)
+ // 4 108-109 bijokkoy(?A?j????), bijokkog(?A?j????)
+
+ // ----------------------------------------------------------------------------------------------------------------
+
+ // nbmj1413m3_nmi_clock_w ???w??
+ //*5 130-131? hyhoo, hyhoo2 5.00MHz (????????DAC???????x???????????c)
+ //*5 130-131? taiwanmb 5.00MHz (???@??????????DAC???????x?s??)
+ //*5 128-129? omotesnd 5.00MHz
+ //*2 100-101? pastelg 2.496MHz (19968000/8) ???
+#endif
+}
+
+MACHINE_RESET( nb1413m3 )
+{
+ nb1413m3_nmi_clock = 0;
+ nb1413m3_nmi_enable = 0;
+ nb1413m3_nmi_count = 0;
+ nb1413m3_74ls193_counter = 0;
+ nb1413m3_counter = 0;
+ nb1413m3_sndromregion = REGION_SOUND1;
+ nb1413m3_sndrombank1 = 0;
+ nb1413m3_sndrombank2 = 0;
+ nb1413m3_busyctr = 0;
+ nb1413m3_busyflag = 1;
+ nb1413m3_gfxradr_l = 0;
+ nb1413m3_gfxradr_h = 0;
+ nb1413m3_gfxrombank = 0;
+ nb1413m3_inputport = 0xff;
+ nb1413m3_outcoin_flag = 1;
+
+ nb1413m3_74ls193_counter = 0;
+
+ timer_call_after_resynch(0, nb1413m3_timer_callback);
+}
+
+WRITE8_HANDLER( nb1413m3_nmi_clock_w )
+{
+ nb1413m3_nmi_clock = data;
+
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_APPAREL:
+ case NB1413M3_CITYLOVE:
+ case NB1413M3_MCITYLOV:
+ case NB1413M3_SECOLOVE:
+ case NB1413M3_SEIHA:
+ case NB1413M3_SEIHAM:
+ case NB1413M3_IEMOTO:
+ case NB1413M3_IEMOTOM:
+ case NB1413M3_BIJOKKOY:
+ case NB1413M3_BIJOKKOG:
+ case NB1413M3_RYUUHA:
+ case NB1413M3_OJOUSAN:
+ case NB1413M3_OJOUSANM:
+ case NB1413M3_KORINAI:
+ case NB1413M3_KORINAIM:
+ case NB1413M3_HOUSEMNQ:
+ case NB1413M3_HOUSEMN2:
+ case NB1413M3_LIVEGAL:
+ case NB1413M3_ORANGEC:
+ case NB1413M3_ORANGECI:
+ case NB1413M3_VIPCLUB:
+ case NB1413M3_MMSIKAKU:
+ case NB1413M3_KANATUEN:
+ case NB1413M3_KYUHITO:
+ nb1413m3_nmi_clock -= 1;
+ break;
+#if 1
+ case NB1413M3_NIGHTLOV:
+ nb1413m3_nmi_enable = ((data & 0x08) >> 3);
+ nb1413m3_nmi_enable |= ((data & 0x01) ^ 0x01);
+ nb1413m3_nmi_clock -= 1;
+
+ nb1413m3_sndrombank1 = 1;
+ break;
+#endif
+ }
+
+ nb1413m3_74ls193_counter = ((nb1413m3_nmi_clock & 0xf0) >> 4);
+
+}
+
+INTERRUPT_GEN( nb1413m3_interrupt )
+{
+#if 0
+ if (!cpu_getiloops())
+ {
+// nb1413m3_busyflag = 1;
+// nb1413m3_busyctr = 0;
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+ }
+ if (nb1413m3_nmi_enable)
+ {
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+ }
+
+ #if NB1413M3_CHEAT
+ #include "nbmjchet.inc"
+ #endif
+#else
+// nb1413m3_busyflag = 1;
+// nb1413m3_busyctr = 0;
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+
+#if NB1413M3_DEBUG
+ popmessage("NMI SW:%01X CLOCK:%02X COUNT:%02X", nb1413m3_nmi_enable, nb1413m3_nmi_clock, nb1413m3_nmi_count);
+ nb1413m3_nmi_count = 0;
+#endif
+
+ #if NB1413M3_CHEAT
+ #include "nbmjchet.inc"
+ #endif
+#endif
+}
+
+NVRAM_HANDLER( nb1413m3 )
+{
+ if (read_or_write)
+ mame_fwrite(file, nb1413m3_nvram, nb1413m3_nvram_size);
+ else
+ {
+ if (file)
+ mame_fread(file, nb1413m3_nvram, nb1413m3_nvram_size);
+ else
+ memset(nb1413m3_nvram, 0, nb1413m3_nvram_size);
+ }
+}
+
+READ8_HANDLER( nb1413m3_sndrom_r )
+{
+ int rombank;
+
+ /* get top 8 bits of the I/O port address */
+ offset = (offset << 8) | (activecpu_get_reg(Z80_BC) >> 8);
+
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_IEMOTO:
+ case NB1413M3_IEMOTOM:
+ case NB1413M3_SEIHA:
+ case NB1413M3_SEIHAM:
+ case NB1413M3_RYUUHA:
+ case NB1413M3_OJOUSAN:
+ case NB1413M3_OJOUSANM:
+ case NB1413M3_MJSIKAKU:
+ case NB1413M3_MMSIKAKU:
+ case NB1413M3_KORINAI:
+ case NB1413M3_KORINAIM:
+ rombank = (nb1413m3_sndrombank2 << 1) + (nb1413m3_sndrombank1 & 0x01);
+ break;
+ case NB1413M3_HYHOO:
+ case NB1413M3_HYHOO2:
+ rombank = (nb1413m3_sndrombank1 & 0x01);
+ break;
+ case NB1413M3_APPAREL: // no samples
+ case NB1413M3_NIGHTLOV: // 0-1
+ case NB1413M3_SECOLOVE: // 0-1
+ case NB1413M3_CITYLOVE: // 0-1
+ case NB1413M3_MCITYLOV: // 0-1
+ case NB1413M3_HOUSEMNQ: // 0-1
+ case NB1413M3_HOUSEMN2: // 0-1
+ case NB1413M3_LIVEGAL: // 0-1
+ case NB1413M3_ORANGEC: // 0-1
+ case NB1413M3_KAGUYA: // 0-3
+ case NB1413M3_KAGUYA2: // 0-3 + 4-5 for protection
+ case NB1413M3_BIJOKKOY: // 0-7
+ case NB1413M3_BIJOKKOG: // 0-7
+ case NB1413M3_OTONANO: // 0-7
+ case NB1413M3_MJCAMERA: // 0 + 4-5 for protection
+ case NB1413M3_IDHIMITU: // 0 + 4-5 for protection
+ case NB1413M3_KANATUEN: // 0 + 6 for protection
+ rombank = nb1413m3_sndrombank1;
+ break;
+ case NB1413M3_TAIWANMB:
+ case NB1413M3_OMOTESND:
+ case NB1413M3_SCANDAL:
+ case NB1413M3_SCANDALM:
+ case NB1413M3_MJFOCUSM:
+ case NB1413M3_BANANADR:
+ offset = (((offset & 0x7f00) >> 8) | ((offset & 0x0080) >> 0) | ((offset & 0x007f) << 8));
+ rombank = (nb1413m3_sndrombank1 >> 1);
+ break;
+ case NB1413M3_MMCAMERA:
+ case NB1413M3_MSJIKEN:
+ case NB1413M3_HANAMOMO:
+ case NB1413M3_TELMAHJN:
+ case NB1413M3_GIONBANA:
+ case NB1413M3_MGION:
+ case NB1413M3_MGMEN89:
+ case NB1413M3_MJFOCUS:
+ case NB1413M3_GALKOKU:
+ case NB1413M3_HYOUBAN:
+ case NB1413M3_MJNANPAS:
+ case NB1413M3_MLADYHTR:
+ case NB1413M3_CLUB90S:
+ case NB1413M3_LOVEHOUS:
+ case NB1413M3_CHINMOKU:
+ case NB1413M3_GALKAIKA:
+ case NB1413M3_MCONTEST:
+ case NB1413M3_UCHUUAI:
+ case NB1413M3_TOKIMBSJ:
+ case NB1413M3_TOKYOGAL:
+ case NB1413M3_MAIKO:
+ case NB1413M3_MMAIKO:
+ case NB1413M3_HANAOJI:
+ case NB1413M3_PAIRSNB:
+ case NB1413M3_PAIRSTEN:
+ default:
+ rombank = (nb1413m3_sndrombank1 >> 1);
+ break;
+ }
+
+ offset += 0x08000 * rombank;
+
+#if NB1413M3_DEBUG
+ popmessage("Sound ROM %02X:%05X [B1:%02X B2:%02X]", rombank, offset, nb1413m3_sndrombank1, nb1413m3_sndrombank2);
+#endif
+
+ if (offset < memory_region_length(nb1413m3_sndromregion))
+ return memory_region(nb1413m3_sndromregion)[offset];
+ else
+ {
+ popmessage("read past sound ROM length (%05x[%02X])",offset, rombank);
+ return 0;
+ }
+}
+
+WRITE8_HANDLER( nb1413m3_sndrombank1_w )
+{
+ // if (data & 0x02) coin counter ?
+ nb1413m3_outcoin_w(0, data); // (data & 0x04) >> 2;
+ nb1413m3_nmi_enable = ((data & 0x20) >> 5);
+ nb1413m3_sndrombank1 = (((data & 0xc0) >> 5) | ((data & 0x10) >> 4));
+}
+
+WRITE8_HANDLER( nb1413m3_sndrombank2_w )
+{
+ nb1413m3_sndrombank2 = (data & 0x03);
+}
+
+READ8_HANDLER( nb1413m3_gfxrom_r )
+{
+ UINT8 *GFXROM = memory_region(REGION_GFX1);
+
+ return GFXROM[(0x20000 * (nb1413m3_gfxrombank | ((nb1413m3_sndrombank1 & 0x02) << 3))) + ((0x0200 * nb1413m3_gfxradr_h) + (0x0002 * nb1413m3_gfxradr_l)) + (offset & 0x01)];
+}
+
+WRITE8_HANDLER( nb1413m3_gfxrombank_w )
+{
+ nb1413m3_gfxrombank = (((data & 0xc0) >> 4) + (data & 0x03));
+}
+
+WRITE8_HANDLER( nb1413m3_gfxradr_l_w )
+{
+ nb1413m3_gfxradr_l = data;
+}
+
+WRITE8_HANDLER( nb1413m3_gfxradr_h_w )
+{
+ nb1413m3_gfxradr_h = data;
+}
+
+WRITE8_HANDLER( nb1413m3_inputportsel_w )
+{
+ nb1413m3_inputport = data;
+}
+
+READ8_HANDLER( nb1413m3_inputport0_r )
+{
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_PASTELG:
+ return ((input_port_3_r(0) & 0xfe) | (nb1413m3_busyflag & 0x01));
+ case NB1413M3_TAIWANMB:
+ return ((input_port_3_r(0) & 0xfc) | ((nb1413m3_outcoin_flag & 0x01) << 1) | (nb1413m3_busyflag & 0x01));
+ case NB1413M3_HYHOO:
+ case NB1413M3_HYHOO2:
+ return ((input_port_2_r(0) & 0xfe) | (nb1413m3_busyflag & 0x01));
+ default:
+ return ((input_port_2_r(0) & 0xfc) | ((nb1413m3_outcoin_flag & 0x01) << 1) | (nb1413m3_busyflag & 0x01));
+ }
+}
+
+READ8_HANDLER( nb1413m3_inputport1_r )
+{
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_PASTELG:
+ case NB1413M3_THREEDS:
+ case NB1413M3_TAIWANMB:
+ switch ((nb1413m3_inputport ^ 0xff) & 0x1f)
+ {
+ case 0x01: return readinputport(4);
+ case 0x02: return readinputport(5);
+ case 0x04: return readinputport(6);
+ case 0x08: return readinputport(7);
+ case 0x10: return readinputport(8);
+ default: return (readinputport(4) & readinputport(5) & readinputport(6) & readinputport(7) & readinputport(8));
+ }
+ break;
+ case NB1413M3_HYHOO:
+ case NB1413M3_HYHOO2:
+ switch ((nb1413m3_inputport ^ 0xff) & 0x07)
+ {
+ case 0x01: return readinputport(3);
+ case 0x02: return readinputport(4);
+ case 0x04: return 0xff;
+ default: return 0xff;
+ }
+ break;
+ case NB1413M3_MSJIKEN:
+ case NB1413M3_TELMAHJN:
+ if (readinputport(0) & 0x80)
+ {
+ switch ((nb1413m3_inputport ^ 0xff) & 0x1f)
+ {
+ case 0x01: return readinputport(3);
+ case 0x02: return readinputport(4);
+ case 0x04: return readinputport(5);
+ case 0x08: return readinputport(6);
+ case 0x10: return readinputport(7);
+ default: return (readinputport(3) & readinputport(4) & readinputport(5) & readinputport(6) & readinputport(7));
+ }
+ }
+ else return readinputport(14);
+ break;
+ case NB1413M3_PAIRSNB:
+ case NB1413M3_PAIRSTEN:
+ return readinputport(3);
+ break;
+ default:
+ switch ((nb1413m3_inputport ^ 0xff) & 0x1f)
+ {
+ case 0x01: return readinputport(3);
+ case 0x02: return readinputport(4);
+ case 0x04: return readinputport(5);
+ case 0x08: return readinputport(6);
+ case 0x10: return readinputport(7);
+ default: return (readinputport(3) & readinputport(4) & readinputport(5) & readinputport(6) & readinputport(7));
+ }
+ break;
+ }
+}
+
+READ8_HANDLER( nb1413m3_inputport2_r )
+{
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_PASTELG:
+ case NB1413M3_THREEDS:
+ case NB1413M3_TAIWANMB:
+ switch ((nb1413m3_inputport ^ 0xff) & 0x1f)
+ {
+ case 0x01: return readinputport(9);
+ case 0x02: return readinputport(10);
+ case 0x04: return readinputport(11);
+ case 0x08: return readinputport(12);
+ case 0x10: return readinputport(13);
+ default: return (readinputport(9) & readinputport(10) & readinputport(11) & readinputport(12) & readinputport(13));
+ }
+ break;
+ case NB1413M3_HYHOO:
+ case NB1413M3_HYHOO2:
+ switch ((nb1413m3_inputport ^ 0xff) & 0x07)
+ {
+ case 0x01: return 0xff;
+ case 0x02: return 0xff;
+ case 0x04: return readinputport(5);
+ default: return 0xff;
+ }
+ break;
+ case NB1413M3_MSJIKEN:
+ case NB1413M3_TELMAHJN:
+ if (readinputport(0) & 0x80)
+ {
+ switch ((nb1413m3_inputport ^ 0xff) & 0x1f)
+ {
+ case 0x01: return readinputport(8);
+ case 0x02: return readinputport(9);
+ case 0x04: return readinputport(10);
+ case 0x08: return readinputport(11);
+ case 0x10: return readinputport(12);
+ default: return (readinputport(8) & readinputport(9) & readinputport(10) & readinputport(11) & readinputport(12));
+ }
+ }
+ else return readinputport(13);
+ break;
+ case NB1413M3_PAIRSNB:
+ case NB1413M3_PAIRSTEN:
+ return readinputport(4);
+ break;
+ default:
+ switch ((nb1413m3_inputport ^ 0xff) & 0x1f)
+ {
+ case 0x01: return readinputport(8);
+ case 0x02: return readinputport(9);
+ case 0x04: return readinputport(10);
+ case 0x08: return readinputport(11);
+ case 0x10: return readinputport(12);
+ default: return (readinputport(8) & readinputport(9) & readinputport(10) & readinputport(11) & readinputport(12));
+ }
+ break;
+ }
+}
+
+READ8_HANDLER( nb1413m3_inputport3_r )
+{
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_TAIWANMB:
+ case NB1413M3_IEMOTOM:
+ case NB1413M3_OJOUSANM:
+ case NB1413M3_SEIHAM:
+ case NB1413M3_RYUUHA:
+ case NB1413M3_KORINAIM:
+ case NB1413M3_HYOUBAN:
+ case NB1413M3_TOKIMBSJ:
+ case NB1413M3_MJFOCUSM:
+ case NB1413M3_SCANDALM:
+ case NB1413M3_BANANADR:
+ case NB1413M3_FINALBNY:
+ case NB1413M3_MMSIKAKU:
+ return ((nb1413m3_outcoin_flag & 0x01) << 1);
+ break;
+ case NB1413M3_LOVEHOUS:
+ case NB1413M3_MAIKO:
+ case NB1413M3_MMAIKO:
+ case NB1413M3_HANAOJI:
+ return ((input_port_13_r(0) & 0xfd) | ((nb1413m3_outcoin_flag & 0x01) << 1));
+ break;
+ default:
+ return 0xff;
+ break;
+ }
+}
+
+READ8_HANDLER( nb1413m3_dipsw1_r )
+{
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_KANATUEN:
+ case NB1413M3_KYUHITO:
+ return readinputport(1);
+ break;
+ case NB1413M3_TAIWANMB:
+ return ((readinputport(0) & 0xf0) | ((readinputport(1) & 0xf0) >> 4));
+ break;
+ case NB1413M3_OTONANO:
+ case NB1413M3_MJCAMERA:
+ case NB1413M3_IDHIMITU:
+ case NB1413M3_KAGUYA2:
+ return (((readinputport(0) & 0x0f) << 4) | (readinputport(1) & 0x0f));
+ break;
+ case NB1413M3_SCANDAL:
+ case NB1413M3_SCANDALM:
+ case NB1413M3_MJFOCUSM:
+ case NB1413M3_GALKOKU:
+ case NB1413M3_HYOUBAN:
+ case NB1413M3_GALKAIKA:
+ case NB1413M3_MCONTEST:
+ case NB1413M3_UCHUUAI:
+ case NB1413M3_TOKIMBSJ:
+ case NB1413M3_TOKYOGAL:
+ return ((readinputport(0) & 0x0f) | ((readinputport(1) & 0x0f) << 4));
+ break;
+ case NB1413M3_TRIPLEW1:
+ case NB1413M3_NTOPSTAR:
+ case NB1413M3_PSTADIUM:
+ case NB1413M3_TRIPLEW2:
+ case NB1413M3_VANILLA:
+ case NB1413M3_FINALBNY:
+ case NB1413M3_MJLSTORY:
+ case NB1413M3_QMHAYAKU:
+ case NB1413M3_MJGOTTUB:
+ return (((readinputport(1) & 0x01) >> 0) | ((readinputport(1) & 0x04) >> 1) |
+ ((readinputport(1) & 0x10) >> 2) | ((readinputport(1) & 0x40) >> 3) |
+ ((readinputport(0) & 0x01) << 4) | ((readinputport(0) & 0x04) << 3) |
+ ((readinputport(0) & 0x10) << 2) | ((readinputport(0) & 0x40) << 1));
+ break;
+ default:
+ return readinputport(0);
+ break;
+ }
+}
+
+READ8_HANDLER( nb1413m3_dipsw2_r )
+{
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_KANATUEN:
+ case NB1413M3_KYUHITO:
+ return readinputport(0);
+ break;
+ case NB1413M3_TAIWANMB:
+ return (((readinputport(0) & 0x0f) << 4) | (readinputport(1) & 0x0f));
+ break;
+ case NB1413M3_OTONANO:
+ case NB1413M3_MJCAMERA:
+ case NB1413M3_IDHIMITU:
+ case NB1413M3_KAGUYA2:
+ return ((readinputport(0) & 0xf0) | ((readinputport(1) & 0xf0) >> 4));
+ break;
+ case NB1413M3_SCANDAL:
+ case NB1413M3_SCANDALM:
+ case NB1413M3_MJFOCUSM:
+ case NB1413M3_GALKOKU:
+ case NB1413M3_HYOUBAN:
+ case NB1413M3_GALKAIKA:
+ case NB1413M3_MCONTEST:
+ case NB1413M3_UCHUUAI:
+ case NB1413M3_TOKIMBSJ:
+ case NB1413M3_TOKYOGAL:
+ return (((readinputport(0) & 0xf0) >> 4) | (readinputport(1) & 0xf0));
+ break;
+ case NB1413M3_TRIPLEW1:
+ case NB1413M3_NTOPSTAR:
+ case NB1413M3_PSTADIUM:
+ case NB1413M3_TRIPLEW2:
+ case NB1413M3_VANILLA:
+ case NB1413M3_FINALBNY:
+ case NB1413M3_MJLSTORY:
+ case NB1413M3_QMHAYAKU:
+ case NB1413M3_MJGOTTUB:
+ return (((readinputport(1) & 0x02) >> 1) | ((readinputport(1) & 0x08) >> 2) |
+ ((readinputport(1) & 0x20) >> 3) | ((readinputport(1) & 0x80) >> 4) |
+ ((readinputport(0) & 0x02) << 3) | ((readinputport(0) & 0x08) << 2) |
+ ((readinputport(0) & 0x20) << 1) | ((readinputport(0) & 0x80) << 0));
+ break;
+ default:
+ return readinputport(1);
+ break;
+ }
+}
+
+READ8_HANDLER( nb1413m3_dipsw3_l_r )
+{
+ return ((readinputport(2) & 0xf0) >> 4);
+}
+
+READ8_HANDLER( nb1413m3_dipsw3_h_r )
+{
+ return ((readinputport(2) & 0x0f) >> 0);
+}
+
+WRITE8_HANDLER( nb1413m3_outcoin_w )
+{
+ static int counter = 0;
+
+ nb1413m3_outcoin_enable = (data & 0x04) >> 2;
+
+ switch (nb1413m3_type)
+ {
+ case NB1413M3_TAIWANMB:
+ case NB1413M3_IEMOTOM:
+ case NB1413M3_OJOUSANM:
+ case NB1413M3_SEIHAM:
+ case NB1413M3_RYUUHA:
+ case NB1413M3_KORINAIM:
+ case NB1413M3_MMSIKAKU:
+ case NB1413M3_HYOUBAN:
+ case NB1413M3_TOKIMBSJ:
+ case NB1413M3_MJFOCUSM:
+ case NB1413M3_SCANDALM:
+ case NB1413M3_BANANADR:
+ case NB1413M3_MGION:
+ case NB1413M3_HANAOJI:
+ case NB1413M3_FINALBNY:
+ case NB1413M3_LOVEHOUS:
+ case NB1413M3_MMAIKO:
+ if (nb1413m3_outcoin_enable)
+ {
+ if (counter++ == 2)
+ {
+ nb1413m3_outcoin_flag ^= 1;
+ counter = 0;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ set_led_status(2, nb1413m3_outcoin_flag); // out coin
+}
+
+WRITE8_HANDLER( nb1413m3_vcrctrl_w )
+{
+ if (data & 0x08)
+ {
+ popmessage(" ** VCR CONTROL ** ");
+ set_led_status(2, 1);
+ }
+ else
+ {
+ set_led_status(2, 0);
+ }
+}
diff --git a/src/mame/machine/neoboot.c b/src/mame/machine/neoboot.c
new file mode 100644
index 00000000000..849f87ab24a
--- /dev/null
+++ b/src/mame/machine/neoboot.c
@@ -0,0 +1,1001 @@
+/***************************************************************************
+
+ Neo-Geo hardware
+
+ Many of the NeoGeo bootlegs use their own form of encryption and
+ protection, presumably to make them harder for other bootleggser to
+ copy. This encryption often involves non-trivial scrambling of the
+ program roms and the games are protected using an Altera chip which
+ provides some kind of rom overlay, patching parts of the code.
+ The graphics roms are usually scrambled in a different way to the
+ official SNK cartridges too.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "neogeo.h"
+
+
+/* General Bootleg Functions - used by more than 1 game */
+
+void neogeo_bootleg_cx_decrypt( void )
+{
+ int i;
+ int cx_size = memory_region_length( NEOGEO_REGION_SPRITES );
+ UINT8 *rom = memory_region( NEOGEO_REGION_SPRITES );
+ UINT8 *buf = malloc_or_die( cx_size );
+
+ memcpy( buf, rom, cx_size );
+
+ for( i = 0; i < cx_size / 0x40; i++ ){
+ memcpy( &rom[ i * 0x40 ], &buf[ (i ^ 1) * 0x40 ], 0x40 );
+ }
+
+ free( buf );
+}
+
+void neogeo_bootleg_sx_decrypt( int value )
+{
+ int sx_size = memory_region_length( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+ UINT8 *rom = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+ int i;
+
+ if (value == 1)
+ {
+ UINT8 *buf = malloc_or_die( sx_size );
+ memcpy( buf, rom, sx_size );
+
+ for( i = 0; i < sx_size; i += 0x10 )
+ {
+ memcpy( &rom[ i ], &buf[ i + 8 ], 8 );
+ memcpy( &rom[ i + 8 ], &buf[ i ], 8 );
+ }
+ free( buf );
+ }
+ else if (value == 2)
+ {
+ for( i = 0; i < sx_size; i++ )
+ rom[ i ] = BITSWAP8( rom[ i ], 7, 6, 0, 4, 3, 2, 1, 5 );
+ }
+}
+
+
+/* The King of Gladiator (The King of Fighters '97 bootleg) */
+
+/* the protection patching here may be incomplete */
+
+// Thanks to Razoola for the info
+
+void kog_px_decrypt( void )
+{
+ /* the protection chip does some *very* strange things to the rom */
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT8 *dst = malloc_or_die( 0x600000 );
+ UINT16 *rom = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ int i;
+ static const int sec[] = { 0x3, 0x8, 0x7, 0xC, 0x1, 0xA, 0x6, 0xD };
+
+ for (i = 0; i < 8; i++){
+ memcpy (dst + i * 0x20000, src + sec[i] * 0x20000, 0x20000);
+ }
+
+ memcpy (dst + 0x0007A6, src + 0x0407A6, 0x000006);
+ memcpy (dst + 0x0007C6, src + 0x0407C6, 0x000006);
+ memcpy (dst + 0x0007E6, src + 0x0407E6, 0x000006);
+ memcpy (dst + 0x090000, src + 0x040000, 0x004000);
+ memcpy (dst + 0x100000, src + 0x200000, 0x400000);
+ memcpy (src, dst, 0x600000);
+ free (dst);
+
+ for (i = 0x90000/2; i < 0x94000/2; i++){
+ if (((rom[i]&0xFFBF) == 0x4EB9 || rom[i] == 0x43F9) && !rom[i + 1])
+ rom[i + 1] = 0x0009;
+
+ if (rom[i] == 0x4EB8)
+ rom[i] = 0x6100;
+ }
+
+ rom[0x007A8/2] = 0x0009;
+ rom[0x007C8/2] = 0x0009;
+ rom[0x007E8/2] = 0x0009;
+ rom[0x93408/2] = 0xF168;
+ rom[0x9340C/2] = 0xFB7A;
+ rom[0x924AC/2] = 0x0009;
+ rom[0x9251C/2] = 0x0009;
+ rom[0x93966/2] = 0xFFDA;
+ rom[0x93974/2] = 0xFFCC;
+ rom[0x93982/2] = 0xFFBE;
+ rom[0x93990/2] = 0xFFB0;
+ rom[0x9399E/2] = 0xFFA2;
+ rom[0x939AC/2] = 0xFF94;
+ rom[0x939BA/2] = 0xFF86;
+ rom[0x939C8/2] = 0xFF78;
+ rom[0x939D4/2] = 0xFA5C;
+ rom[0x939E0/2] = 0xFA50;
+ rom[0x939EC/2] = 0xFA44;
+ rom[0x939F8/2] = 0xFA38;
+ rom[0x93A04/2] = 0xFA2C;
+ rom[0x93A10/2] = 0xFA20;
+ rom[0x93A1C/2] = 0xFA14;
+ rom[0x93A28/2] = 0xFA08;
+ rom[0x93A34/2] = 0xF9FC;
+ rom[0x93A40/2] = 0xF9F0;
+ rom[0x93A4C/2] = 0xFD14;
+ rom[0x93A58/2] = 0xFD08;
+ rom[0x93A66/2] = 0xF9CA;
+ rom[0x93A72/2] = 0xF9BE;
+
+}
+
+/* Kof 10th Anniversary (bootleg of King of Fighters 2002 */
+
+/* this uses RAM based tiles for the text layer, however the implementation
+ is incomplete, at the moment the S data is copied from the program rom on
+ start-up instead */
+
+static UINT16 kof10thExtraRAMB[0x01000];
+
+static void kof10thBankswitch(UINT16 nBank)
+{
+ UINT32 bank = 0x100000 + ((nBank & 7) << 20);
+ if (bank >= 0x700000)
+ bank = 0x100000;
+ neogeo_set_main_cpu_bank_address(bank);
+}
+
+static READ16_HANDLER( kof10th_RAMB_r )
+{
+ return kof10thExtraRAMB[offset];
+}
+
+static WRITE16_HANDLER( kof10th_custom_w )
+{
+ if (!kof10thExtraRAMB[0xFFE]) { // Write to RAM bank A
+ UINT16 *prom = (UINT16*)memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ COMBINE_DATA(&prom[(0xE0000/2) + (offset & 0xFFFF)]);
+ } else { // Write S data on-the-fly
+ UINT8 *srom = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+ srom[offset] = BITSWAP8(data,7,6,0,4,3,2,1,5);
+ }
+}
+
+static WRITE16_HANDLER( kof10th_bankswitch_w )
+{
+ if (offset >= 0x5F000) {
+ if (offset == 0x5FFF8) { // Standard bankswitch
+ kof10thBankswitch(data);
+ } else if (offset == 0x5FFFC && kof10thExtraRAMB[0xFFC] != data) { // Special bankswitch
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ memcpy (src + 0x10000, src + ((data & 1) ? 0x810000 : 0x710000), 0xcffff);
+ }
+ COMBINE_DATA(&kof10thExtraRAMB[offset & 0xFFF]);
+ }
+}
+
+void install_kof10th_protection ( void )
+{
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fe000, 0x2fffff, 0, 0, kof10th_RAMB_r);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x200000, 0x23ffff, 0, 0, kof10th_custom_w);
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x240000, 0x2fffff, 0, 0, kof10th_bankswitch_w);
+}
+
+void decrypt_kof10th( void )
+{
+ int i, j;
+ UINT8 *dst = malloc_or_die(0x900000);
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+
+ memcpy(dst + 0x000000, src + 0x700000, 0x100000); // Correct (Verified in Uni-bios)
+ memcpy(dst + 0x100000, src + 0x000000, 0x800000);
+
+ for (i = 0; i < 0x900000; i++) {
+ j = BITSWAP24(i,23,22,21,20,19,18,17,16,15,14,13,12,11,2,9,8,7,1,5,4,3,10,6,0);
+ src[j] = dst[i];
+ }
+
+ free(dst);
+
+ // Altera protection chip patches these over P ROM
+ ((UINT16*)src)[0x0124/2] = 0x000d; // Enables XOR for RAM moves, forces SoftDIPs, and USA region
+ ((UINT16*)src)[0x0126/2] = 0xf7a8;
+
+ ((UINT16*)src)[0x8bf4/2] = 0x4ef9; // Run code to change "S" data
+ ((UINT16*)src)[0x8bf6/2] = 0x000d;
+ ((UINT16*)src)[0x8bf8/2] = 0xf980;
+}
+
+void decrypt_kf10thep(void)
+{
+ int i;
+ UINT16 *rom = (UINT16*)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT16 *buf = (UINT16*)memory_region(NEOGEO_REGION_AUDIO_CPU_ENCRYPTED);
+ UINT8 *srom = (UINT8*)memory_region(NEOGEO_REGION_FIXED_LAYER_CARTRIDGE);
+ UINT8 *sbuf = malloc_or_die(0x20000);
+
+ UINT8 *dst = malloc_or_die(0x200000);
+
+ memcpy(dst,buf,0x200000);
+ memcpy(src+0x000000,dst+0x060000,0x20000);
+ memcpy(src+0x020000,dst+0x100000,0x20000);
+ memcpy(src+0x040000,dst+0x0e0000,0x20000);
+ memcpy(src+0x060000,dst+0x180000,0x20000);
+ memcpy(src+0x080000,dst+0x020000,0x20000);
+ memcpy(src+0x0a0000,dst+0x140000,0x20000);
+ memcpy(src+0x0c0000,dst+0x0c0000,0x20000);
+ memcpy(src+0x0e0000,dst+0x1a0000,0x20000);
+ memcpy(src+0x0002e0,dst+0x0402e0,0x6a); // copy banked code to a new memory region
+ memcpy(src+0x0f92bc,dst+0x0492bc,0xb9e); // copy banked code to a new memory region
+ for (i=0xf92bc/2;i < 0xf9e58/2 ;i++)
+ {
+ if (rom[i+0] == 0x4eb9 && rom[i+1] == 0x0000) rom[i+1] = 0x000F; // correct JSR in moved code
+ if (rom[i+0] == 0x4ef9 && rom[i+1] == 0x0000) rom[i+1] = 0x000F; // correct JMP in moved code
+ }
+ rom[0x00342/2] = 0x000f;
+ free(dst);
+
+ for (i=0;i<0x20000;i++)
+ sbuf[i]=srom[i^0x8];
+
+ memcpy(srom,sbuf,0x20000);
+ free(sbuf);
+}
+
+static void kf2k5uni_px_decrypt( void )
+{
+ int i, j, ofst;
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *dst = malloc_or_die(0x80);
+
+ for (i = 0; i < 0x800000; i+=0x80)
+ {
+ for (j = 0; j < 0x80; j+=2)
+ {
+ ofst = BITSWAP8(j, 0, 3, 4, 5, 6, 1, 2, 7);
+ memcpy(dst + j, src + i + ofst, 2);
+ }
+ memcpy(src + i, dst, 0x80);
+ }
+ free(dst);
+
+ memcpy(src, src + 0x600000, 0x100000); // Seems to be the same as kof10th
+}
+
+static void kf2k5uni_sx_decrypt( void )
+{
+ int i;
+ UINT8 *srom = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+
+ for (i = 0; i < 0x20000; i++)
+ srom[i] = BITSWAP8(srom[i], 4, 5, 6, 7, 0, 1, 2, 3);
+}
+
+static void kf2k5uni_mx_decrypt( void )
+{
+ int i;
+ UINT8 *mrom = memory_region( NEOGEO_REGION_AUDIO_CPU_CARTRIDGE );
+
+ for (i = 0; i < 0x30000; i++)
+ mrom[i] = BITSWAP8(mrom[i], 4, 5, 6, 7, 0, 1, 2, 3);
+}
+
+void decrypt_kf2k5uni(void)
+{
+ kf2k5uni_px_decrypt();
+ kf2k5uni_sx_decrypt();
+ kf2k5uni_mx_decrypt();
+}
+
+/* Kof2002 Magic Plus */
+
+void kf2k2mp_decrypt( void )
+{
+ int i,j;
+
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT8 *dst = malloc_or_die(0x80);
+
+ memmove(src, src + 0x300000, 0x500000);
+
+ for (i = 0; i < 0x800000; i+=0x80)
+ {
+ for (j = 0; j < 0x80 / 2; j++)
+ {
+ int ofst = BITSWAP8( j, 6, 7, 2, 3, 4, 5, 0, 1 );
+ memcpy(dst + j * 2, src + i + ofst * 2, 2);
+ }
+ memcpy(src + i, dst, 0x80);
+ }
+ free(dst);
+}
+
+/* Kof2002 Magic Plus 2 */
+
+
+void kof2km2_px_decrypt( void )
+{
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT8 *dst = malloc_or_die(0x600000);
+
+ memcpy (dst + 0x000000, src + 0x1C0000, 0x040000);
+ memcpy (dst + 0x040000, src + 0x140000, 0x080000);
+ memcpy (dst + 0x0C0000, src + 0x100000, 0x040000);
+ memcpy (dst + 0x100000, src + 0x200000, 0x400000);
+ memcpy (src + 0x000000, dst + 0x000000, 0x600000);
+ free (dst);
+}
+
+
+/* Crouching Tiger Hidden Dragon 2003 (bootleg of King of Fighters 2001) */
+
+/* descrambling information from razoola */
+static void cthd2003_neogeo_gfx_address_fix_do(int start, int end, int bit3shift, int bit2shift, int bit1shift, int bit0shift)
+{
+ int i,j;
+ int tilesize=128;
+
+ UINT8* rom = malloc_or_die(16*tilesize); // 16 tiles buffer
+ UINT8* realrom = memory_region(NEOGEO_REGION_SPRITES) + start*tilesize;
+
+ for (i = 0; i < (end-start)/16; i++) {
+ for (j = 0; j < 16; j++) {
+ int offset = (((j&1)>>0)<<bit0shift)
+ +(((j&2)>>1)<<bit1shift)
+ +(((j&4)>>2)<<bit2shift)
+ +(((j&8)>>3)<<bit3shift);
+
+ memcpy(rom+j*tilesize, realrom+offset*tilesize, tilesize);
+ }
+ memcpy(realrom,rom,tilesize*16);
+ realrom+=16*tilesize;
+ }
+ free(rom);
+}
+
+static void cthd2003_neogeo_gfx_address_fix(int start, int end)
+{
+ cthd2003_neogeo_gfx_address_fix_do(start+512*0, end+512*0, 0,3,2,1);
+ cthd2003_neogeo_gfx_address_fix_do(start+512*1, end+512*1, 1,0,3,2);
+ cthd2003_neogeo_gfx_address_fix_do(start+512*2, end+512*2, 2,1,0,3);
+ // skip 3 & 4
+ cthd2003_neogeo_gfx_address_fix_do(start+512*5, end+512*5, 0,1,2,3);
+ cthd2003_neogeo_gfx_address_fix_do(start+512*6, end+512*6, 0,1,2,3);
+ cthd2003_neogeo_gfx_address_fix_do(start+512*7, end+512*7, 0,2,3,1);
+}
+
+static void cthd2003_c(int pow)
+{
+ int i;
+
+ for (i=0; i<=192; i+=8)
+ cthd2003_neogeo_gfx_address_fix(i*512,i*512+512);
+
+ for (i=200; i<=392; i+=8)
+ cthd2003_neogeo_gfx_address_fix(i*512,i*512+512);
+
+ for (i=400; i<=592; i+=8)
+ cthd2003_neogeo_gfx_address_fix(i*512,i*512+512);
+
+ for (i=600; i<=792; i+=8)
+ cthd2003_neogeo_gfx_address_fix(i*512,i*512+512);
+
+ for (i=800; i<=992; i+=8)
+ cthd2003_neogeo_gfx_address_fix(i*512,i*512+512);
+
+ for (i=1000; i<=1016; i+=8)
+ cthd2003_neogeo_gfx_address_fix(i*512,i*512+512);
+}
+
+void decrypt_cthd2003(void)
+{
+ UINT8 *romdata = memory_region(NEOGEO_REGION_FIXED_LAYER_CARTRIDGE);
+ UINT8 *tmp = malloc_or_die(8*128*128);
+
+ memcpy(tmp+8*0*128, romdata+8*0*128, 8*32*128);
+ memcpy(tmp+8*32*128, romdata+8*64*128, 8*32*128);
+ memcpy(tmp+8*64*128, romdata+8*32*128, 8*32*128);
+ memcpy(tmp+8*96*128, romdata+8*96*128, 8*32*128);
+ memcpy(romdata, tmp, 8*128*128);
+
+ romdata = memory_region(NEOGEO_REGION_AUDIO_CPU_CARTRIDGE)+0x10000;
+ memcpy(tmp+8*0*128, romdata+8*0*128, 8*32*128);
+ memcpy(tmp+8*32*128, romdata+8*64*128, 8*32*128);
+ memcpy(tmp+8*64*128, romdata+8*32*128, 8*32*128);
+ memcpy(tmp+8*96*128, romdata+8*96*128, 8*32*128);
+ memcpy(romdata, tmp, 8*128*128);
+
+ free(tmp);
+
+ memcpy(romdata-0x10000,romdata,0x10000);
+
+ cthd2003_c(0);
+}
+
+static WRITE16_HANDLER ( cthd2003_bankswitch_w )
+{
+ int bankaddress;
+ static int cthd2003_banks[8] =
+ {
+ 1,0,1,0,1,0,3,2,
+ };
+ if (offset == 0)
+ {
+ bankaddress = 0x100000 + cthd2003_banks[data&7]*0x100000;
+ neogeo_set_main_cpu_bank_address(bankaddress);
+ }
+}
+
+void patch_cthd2003( void )
+{
+ /* patches thanks to razoola */
+ int i;
+ UINT16 *mem16 = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+
+ /* special ROM banking handler */
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2ffff0, 0x2fffff, 0, 0, cthd2003_bankswitch_w);
+
+ // theres still a problem on the character select screen but it seems to be related to cpu core timing issues,
+ // overclocking the 68k prevents it.
+
+ // fix garbage on s1 layer over everything
+ mem16[0xf415a/2] = 0x4ef9;
+ mem16[0xf415c/2] = 0x000f;
+ mem16[0xf415e/2] = 0x4cf2;
+ // Fix corruption in attract mode before title screen
+ for (i=0x1ae290/2;i < 0x1ae8d0/2; i=i+1)
+ {
+ mem16[i] = 0x0000;
+ }
+
+ // Fix for title page
+ for (i=0x1f8ef0/2;i < 0x1fa1f0/2; i=i+2)
+ {
+ mem16[i] -= 0x7000;
+ mem16[i+1] -= 0x0010;
+ }
+
+ // Fix for green dots on title page
+ for (i=0xac500/2;i < 0xac520/2; i=i+1)
+ {
+ mem16[i] = 0xFFFF;
+ }
+ // Fix for blanks as screen change level end clear
+ mem16[0x991d0/2] = 0xdd03;
+ mem16[0x99306/2] = 0xdd03;
+ mem16[0x99354/2] = 0xdd03;
+ mem16[0x9943e/2] = 0xdd03;
+}
+
+/* Crouching Tiger Hidden Dragon 2003 Super Plus (bootleg of King of Fighters 2001) */
+
+static void ct2k3sp_sx_decrypt( void )
+{
+ int rom_size = memory_region_length( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+ UINT8 *rom = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+ UINT8 *buf = malloc_or_die( rom_size );
+ int i;
+ int ofst;
+
+ memcpy( buf, rom, rom_size );
+
+ for( i = 0; i < rom_size; i++ ){
+ ofst = BITSWAP24( (i & 0x1ffff), 23, 22, 21, 20, 19, 18, 17, 3,
+ 0, 1, 4, 2, 13, 14, 16, 15,
+ 5, 6, 11, 10, 9, 8, 7, 12 );
+
+ ofst += (i >> 17) << 17;
+
+ rom[ i ] = buf[ ofst ];
+ }
+
+ memcpy( buf, rom, rom_size );
+
+ memcpy( &rom[ 0x08000 ], &buf[ 0x10000 ], 0x8000 );
+ memcpy( &rom[ 0x10000 ], &buf[ 0x08000 ], 0x8000 );
+ memcpy( &rom[ 0x28000 ], &buf[ 0x30000 ], 0x8000 );
+ memcpy( &rom[ 0x30000 ], &buf[ 0x28000 ], 0x8000 );
+
+ free( buf );
+}
+
+void decrypt_ct2k3sp(void)
+{
+ UINT8 *romdata = memory_region(NEOGEO_REGION_AUDIO_CPU_CARTRIDGE)+0x10000;
+ UINT8*tmp = malloc_or_die(8*128*128);
+ memcpy(tmp+8*0*128, romdata+8*0*128, 8*32*128);
+ memcpy(tmp+8*32*128, romdata+8*64*128, 8*32*128);
+ memcpy(tmp+8*64*128, romdata+8*32*128, 8*32*128);
+ memcpy(tmp+8*96*128, romdata+8*96*128, 8*32*128);
+ memcpy(romdata, tmp, 8*128*128);
+
+ free(tmp);
+ memcpy(romdata-0x10000,romdata,0x10000);
+ ct2k3sp_sx_decrypt();
+ cthd2003_c(0);
+}
+
+/* Crouching Tiger Hidden Dragon 2003 Super Plus alternate (bootleg of King of Fighters 2001) */
+
+void decrypt_ct2k3sa(void)
+{
+ UINT8 *romdata = memory_region(NEOGEO_REGION_AUDIO_CPU_CARTRIDGE)+0x10000;
+ UINT8*tmp = malloc_or_die(8*128*128);
+ memcpy(tmp+8*0*128, romdata+8*0*128, 8*32*128);
+ memcpy(tmp+8*32*128, romdata+8*64*128, 8*32*128);
+ memcpy(tmp+8*64*128, romdata+8*32*128, 8*32*128);
+ memcpy(tmp+8*96*128, romdata+8*96*128, 8*32*128);
+ memcpy(romdata, tmp, 8*128*128);
+
+ free(tmp);
+ memcpy(romdata-0x10000,romdata,0x10000);
+ cthd2003_c(0);
+}
+
+void patch_ct2k3sa( void )
+{
+ /* patches thanks to razoola - same as for cthd2003*/
+ int i;
+ UINT16 *mem16 = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+
+ // theres still a problem on the character select screen but it seems to be related to cpu core timing issues,
+ // overclocking the 68k prevents it.
+
+ // fix garbage on s1 layer over everything
+ mem16[0xf415a/2] = 0x4ef9;
+ mem16[0xf415c/2] = 0x000f;
+ mem16[0xf415e/2] = 0x4cf2;
+
+ // Fix corruption in attract mode before title screen
+ for (i=0x1ae290/2;i < 0x1ae8d0/2; i=i+1)
+ {
+ mem16[i] = 0x0000;
+ }
+
+ // Fix for title page
+ for (i=0x1f8ef0/2;i < 0x1fa1f0/2; i=i+2)
+ {
+ mem16[i] -= 0x7000;
+ mem16[i+1] -= 0x0010;
+ }
+
+ // Fix for green dots on title page
+ for (i=0xac500/2;i < 0xac520/2; i=i+1)
+ {
+ mem16[i] = 0xFFFF;
+ }
+ // Fix for blanks as screen change level end clear
+ mem16[0x991d0/2] = 0xdd03;
+ mem16[0x99306/2] = 0xdd03;
+ mem16[0x99354/2] = 0xdd03;
+ mem16[0x9943e/2] = 0xdd03;
+}
+
+/* King of Fighters Special Edition 2004 (bootleg of King of Fighters 2002) */
+
+void decrypt_kof2k4se_68k( void )
+{
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE)+0x100000;
+ UINT8 *dst = malloc_or_die(0x400000);
+ int i;
+ static const int sec[] = {0x300000,0x200000,0x100000,0x000000};
+ memcpy(dst,src,0x400000);
+
+ for(i = 0; i < 4; ++i)
+ {
+ memcpy(src+i*0x100000,dst+sec[i],0x100000);
+ }
+ free(dst);
+}
+
+/* Lans2004 (bootleg of Shock Troopers 2) */
+
+void lans2004_vx_decrypt( void )
+{
+ int i;
+ UINT8 *rom = memory_region( NEOGEO_REGION_AUDIO_DATA_1 );
+ for (i = 0; i < 0xA00000; i++)
+ rom[i] = BITSWAP8(rom[i], 0, 1, 5, 4, 3, 2, 6, 7);
+}
+
+void lans2004_decrypt_68k( void )
+{
+ /* Descrambling P ROMs - Thanks to Razoola for the info */
+ int i;
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT16 *rom = (UINT16*)memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *dst = malloc_or_die(0x600000);
+
+ {
+ static const int sec[] = { 0x3, 0x8, 0x7, 0xC, 0x1, 0xA, 0x6, 0xD };
+
+ for (i = 0; i < 8; i++)
+ memcpy (dst + i * 0x20000, src + sec[i] * 0x20000, 0x20000);
+
+ memcpy (dst + 0x0BBB00, src + 0x045B00, 0x001710);
+ memcpy (dst + 0x02FFF0, src + 0x1A92BE, 0x000010);
+ memcpy (dst + 0x100000, src + 0x200000, 0x400000);
+ memcpy (src, dst, 0x600000);
+ free (dst);
+ }
+
+ for (i = 0xBBB00/2; i < 0xBE000/2; i++) {
+ if ((((rom[i]&0xFFBF)==0x4EB9) || ((rom[i]&0xFFBF)==0x43B9)) && (rom[i+1]==0x0000)) {
+ rom[i + 1] = 0x000B;
+ rom[i + 2] += 0x6000;
+ }
+ }
+
+ rom[0x2D15C/2] = 0x000B;
+ rom[0x2D15E/2] = 0xBB00;
+ rom[0x2D1E4/2] = 0x6002;
+ rom[0x2EA7E/2] = 0x6002;
+ rom[0xBBCD0/2] = 0x6002;
+ rom[0xBBDF2/2] = 0x6002;
+ rom[0xBBE42/2] = 0x6002;
+}
+
+static READ16_HANDLER( mslug5_prot_r )
+{
+ logerror("PC %06x: access protected\n",activecpu_get_pc());
+ return 0xa0;
+}
+
+static WRITE16_HANDLER ( ms5plus_bankswitch_w )
+{
+ int bankaddress;
+ logerror("offset: %06x PC %06x: set banking %04x\n",offset,activecpu_get_pc(),data);
+ if ((offset == 0)&&(data == 0xa0))
+ {
+ bankaddress=0xa0;
+ neogeo_set_main_cpu_bank_address(bankaddress);
+ logerror("offset: %06x PC %06x: set banking %04x\n\n",offset,activecpu_get_pc(),bankaddress);
+ }
+ else if(offset == 2)
+ {
+ data=data>>4;
+ //data=data&7;
+ bankaddress=data*0x100000;
+ neogeo_set_main_cpu_bank_address(bankaddress);
+ logerror("offset: %06x PC %06x: set banking %04x\n\n",offset,activecpu_get_pc(),bankaddress);
+ }
+}
+
+void install_ms5plus_protection(void)
+{
+ // special ROM banking handler / additional protection
+ memory_install_readwrite16_handler(0, ADDRESS_SPACE_PROGRAM,0x2ffff0, 0x2fffff,0, 0, mslug5_prot_r, ms5plus_bankswitch_w);
+}
+
+
+
+void svcboot_px_decrypt( void )
+{
+ static const UINT8 sec[] = {
+ 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00
+ };
+ int i;
+ int size = memory_region_length( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *dst = malloc_or_die( size );
+ int ofst;
+ for( i = 0; i < size / 0x100000; i++ ){
+ memcpy( &dst[ i * 0x100000 ], &src[ sec[ i ] * 0x100000 ], 0x100000 );
+ }
+ for( i = 0; i < size / 2; i++ ){
+ ofst = BITSWAP8( (i & 0x0000ff), 7, 6, 1, 0, 3, 2, 5, 4 );
+ ofst += (i & 0xffff00);
+ memcpy( &src[ i * 2 ], &dst[ ofst * 2 ], 0x02 );
+ }
+ free( dst );
+}
+
+
+
+void svcboot_cx_decrypt( void )
+{
+ static const UINT8 idx_tbl[ 0x10 ] = {
+ 0, 1, 0, 1, 2, 3, 2, 3, 3, 4, 3, 4, 4, 5, 4, 5,
+ };
+ static const UINT8 bitswap4_tbl[ 6 ][ 4 ] = {
+ { 3, 0, 1, 2 },
+ { 2, 3, 0, 1 },
+ { 1, 2, 3, 0 },
+ { 0, 1, 2, 3 },
+ { 3, 2, 1, 0 },
+ { 3, 0, 2, 1 },
+ };
+ int i;
+ int size = memory_region_length( NEOGEO_REGION_SPRITES );
+ UINT8 *src = memory_region( NEOGEO_REGION_SPRITES );
+ UINT8 *dst = malloc_or_die( size );
+ int ofst;
+ memcpy( dst, src, size );
+ for( i = 0; i < size / 0x80; i++ ){
+ int idx = idx_tbl[ (i & 0xf00) >> 8 ];
+ int bit0 = bitswap4_tbl[ idx ][ 0 ];
+ int bit1 = bitswap4_tbl[ idx ][ 1 ];
+ int bit2 = bitswap4_tbl[ idx ][ 2 ];
+ int bit3 = bitswap4_tbl[ idx ][ 3 ];
+ ofst = BITSWAP8( (i & 0x0000ff), 7, 6, 5, 4, bit3, bit2, bit1, bit0 );
+ ofst += (i & 0xfffff00);
+ memcpy( &src[ i * 0x80 ], &dst[ ofst * 0x80 ], 0x80 );
+ }
+ free( dst );
+}
+
+
+
+void svcplus_px_decrypt( void )
+{
+ static const int sec[] = {
+ 0x00, 0x03, 0x02, 0x05, 0x04, 0x01
+ };
+ int size = memory_region_length( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *dst = malloc_or_die( size );
+ int i;
+ int ofst;
+ memcpy( dst, src, size );
+ for( i = 0; i < size / 2; i++ ){
+ ofst = BITSWAP24( (i & 0xfffff), 0x17, 0x16, 0x15, 0x14, 0x13, 0x00, 0x01, 0x02,
+ 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x10, 0x11, 0x12 );
+ ofst ^= 0x0f0007;
+ ofst += (i & 0xff00000);
+ memcpy( &src[ i * 0x02 ], &dst[ ofst * 0x02 ], 0x02 );
+ }
+ memcpy( dst, src, size );
+ for( i = 0; i < 6; i++ ){
+ memcpy( &src[ i * 0x100000 ], &dst[ sec[ i ] * 0x100000 ], 0x100000 );
+ }
+ free( dst );
+}
+
+
+
+void svcplus_px_hack( void )
+{
+ /* patched by the protection chip? */
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ src[ 0x0f8010 ] = 0x40;
+ src[ 0x0f8011 ] = 0x04;
+ src[ 0x0f8012 ] = 0x00;
+ src[ 0x0f8013 ] = 0x10;
+ src[ 0x0f8014 ] = 0x40;
+ src[ 0x0f8015 ] = 0x46;
+ src[ 0x0f8016 ] = 0xc1;
+ src[ 0x0f802c ] = 0x16;
+}
+
+void svcplusa_px_decrypt( void )
+{
+ int i;
+ static const int sec[] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x00
+ };
+ int size = memory_region_length( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *dst = malloc_or_die( size );
+ memcpy( dst, src, size );
+ for( i = 0; i < 6; i++ ){
+ memcpy( &src[ i * 0x100000 ], &dst[ sec[ i ] * 0x100000 ], 0x100000 );
+ }
+ free( dst );
+}
+
+
+
+void svcsplus_px_decrypt( void )
+{
+ static const int sec[] = {
+ 0x06, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x00
+ };
+ int size = memory_region_length( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *src = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *dst = malloc_or_die( size );
+ int i;
+ int ofst;
+ memcpy( dst, src, size );
+ for( i = 0; i < size / 2; i++ ){
+ ofst = BITSWAP16( (i & 0x007fff), 0x0f, 0x00, 0x08, 0x09, 0x0b, 0x0a, 0x0c, 0x0d,
+ 0x04, 0x03, 0x01, 0x07, 0x06, 0x02, 0x05, 0x0e );
+
+ ofst += (i & 0x078000);
+ ofst += sec[ (i & 0xf80000) >> 19 ] << 19;
+ memcpy( &src[ i * 2 ], &dst[ ofst * 2 ], 0x02 );
+ }
+ free( dst );
+}
+
+
+
+void svcsplus_px_hack( void )
+{
+ /* patched by the protection chip? */
+ UINT16 *mem16 = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ mem16[0x9e90/2] = 0x000f;
+ mem16[0x9e92/2] = 0xc9c0;
+ mem16[0xa10c/2] = 0x4eb9;
+ mem16[0xa10e/2] = 0x000e;
+ mem16[0xa110/2] = 0x9750;
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT16 mv0_bank_ram[ 0x10/2 ];
+
+static READ16_HANDLER( mv0_bankswitch_r )
+{
+ return mv0_bank_ram[ offset ];
+}
+
+static WRITE16_HANDLER( mv0_bankswitch_w )
+{
+ UINT32 bankaddress = (mv0_bank_ram[ 0 ] >> 8) + (mv0_bank_ram[ 1 ] << 8) + 0x100000;
+ COMBINE_DATA( &mv0_bank_ram[ offset ] );
+ neogeo_set_main_cpu_bank_address( bankaddress );
+}
+#endif
+
+/* I think the code for the kof2003 bootlegs is wrong, they don't work */
+
+/***************************************************************************
+ kof2003b
+****************************************************************************/
+
+/* kof2003 bootleg init info */
+static UINT16 kof2003_tbl[4096];
+
+static READ16_HANDLER( kof2003_r)
+{
+ return kof2003_tbl[offset];
+}
+
+static WRITE16_HANDLER( kof2003_w )
+{
+ data = COMBINE_DATA(&kof2003_tbl[offset]);
+ if (offset == 0x1ff0/2 || offset == 0x1ff2/2) {
+ UINT8* cr = (UINT8 *)kof2003_tbl;
+ UINT32 address = (cr[BYTE_XOR_LE(0x1ff3)]<<16)|(cr[BYTE_XOR_LE(0x1ff2)]<<8)|cr[BYTE_XOR_LE(0x1ff1)];
+ UINT8 prt = cr[BYTE_XOR_LE(0x1ff2)];
+ UINT8* mem = (UINT8 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+
+ cr[BYTE_XOR_LE(0x1ff0)] = 0xa0;
+ cr[BYTE_XOR_LE(0x1ff1)] &= 0xfe;
+ cr[BYTE_XOR_LE(0x1ff3)] &= 0x7f;
+ neogeo_set_main_cpu_bank_address(address+0x100000);
+
+ mem[BYTE_XOR_LE(0x58196)] = prt;
+ }
+}
+
+static WRITE16_HANDLER( kof2003p_w )
+{
+ data = COMBINE_DATA(&kof2003_tbl[offset]);
+ if (offset == 0x1ff0/2 || offset == 0x1ff2/2) {
+ UINT8* cr = (UINT8 *)kof2003_tbl;
+ UINT32 address = (cr[BYTE_XOR_LE(0x1ff3)]<<16)|(cr[BYTE_XOR_LE(0x1ff2)]<<8)|cr[BYTE_XOR_LE(0x1ff0)];
+ UINT8 prt = cr[BYTE_XOR_LE(0x1ff2)];
+ UINT8* mem = (UINT8 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+
+ cr[BYTE_XOR_LE(0x1ff0)] &= 0xfe;
+ cr[BYTE_XOR_LE(0x1ff3)] &= 0x7f;
+ neogeo_set_main_cpu_bank_address(address+0x100000);
+
+ mem[BYTE_XOR_LE(0x58196)] = prt;
+ }
+}
+
+void kof2003b_px_decrypt( void )
+{
+ int i;
+ static const UINT8 sec[] = {
+ 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
+ };
+
+ int rom_size = 0x800000;
+ UINT8 *rom = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *buf = malloc_or_die( rom_size );
+ memcpy( buf, rom, rom_size );
+
+ for( i = 0; i < rom_size / 0x100000; i++ ){
+ memcpy( &rom[ i * 0x100000 ], &buf[ sec[ i ] * 0x100000 ], 0x100000 );
+ }
+ free( buf );
+}
+
+void kof2003b_install_protection(void)
+{
+ memory_install_readwrite16_handler( 0, ADDRESS_SPACE_PROGRAM, 0x2fe000, 0x2fffff, 0, 0, kof2003_r, kof2003_w );
+}
+
+
+/***************************************************************************
+ kof2k3pl
+***************************************************************************/
+
+void kof2k3pl_px_decrypt( void )
+{
+ UINT16*tmp = malloc_or_die(0x100000);
+ UINT16*rom = (UINT16*)memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ int j;
+ int i;
+
+ for (i = 0;i < 0x700000/2;i+=0x100000/2)
+ {
+ memcpy(tmp,&rom[i],0x100000);
+ for (j = 0;j < 0x100000/2;j++)
+ rom[i+j] = tmp[BITSWAP24(j,23,22,21,20,19,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18)];
+ }
+ free(tmp);
+
+ /* patched by Altera protection chip on PCB */
+ rom[0xf38ac/2] = 0x4e75;
+}
+
+void kf2k3pl_install_protection(void)
+{
+ memory_install_readwrite16_handler( 0, ADDRESS_SPACE_PROGRAM, 0x2fe000, 0x2fffff, 0, 0, kof2003_r, kof2003p_w );
+}
+
+
+/***************************************************************************
+ kof2k3up
+***************************************************************************/
+
+
+void kof2k3up_px_decrypt( void )
+{
+ {
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ memmove(src+0x100000, src, 0x600000);
+ memmove(src, src+0x700000, 0x100000);
+ }
+
+ {
+
+ int ofst;
+ int i;
+ UINT8 *rom = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE ) + 0xfe000;
+ UINT8 *buf = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE ) + 0xd0610;
+
+ for( i = 0; i < 0x2000 / 2; i++ ){
+ ofst = (i & 0xff00) + BITSWAP8( (i & 0x00ff), 7, 6, 0, 4, 3, 2, 1, 5 );
+ memcpy( &rom[ i * 2 ], &buf[ ofst * 2 ], 2 );
+ }
+ }
+}
+
+void kof2k3up_install_protection(void)
+{
+ memory_install_readwrite16_handler( 0, ADDRESS_SPACE_PROGRAM, 0x2fe000, 0x2fffff, 0, 0, kof2003_r, kof2003_w );
+}
+
+/* samsho5bl */
+
+void samsh5bl_px_decrypt( void )
+{
+ int px_size = memory_region_length( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *rom = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *buf = malloc_or_die( px_size );
+ int ofst;
+ int i;
+
+ memcpy( buf, rom, px_size );
+
+ for( i = 0; i < px_size / 2; i++ ){
+ ofst = BITSWAP8( (i & 0x000ff), 7, 6, 5, 4, 3, 0, 1, 2 );
+ ofst += (i & 0xfffff00);
+ ofst ^= 0x060005;
+
+ memcpy( &rom[ i * 2 ], &buf[ ofst * 2 ], 0x02 );
+ }
+
+ memcpy( buf, rom, px_size );
+
+ memcpy( &rom[ 0x000000 ], &buf[ 0x700000 ], 0x100000 );
+ memcpy( &rom[ 0x100000 ], &buf[ 0x000000 ], 0x700000 );
+
+ free( buf );
+}
+
+
diff --git a/src/mame/machine/neocrypt.c b/src/mame/machine/neocrypt.c
new file mode 100644
index 00000000000..3f2d2733874
--- /dev/null
+++ b/src/mame/machine/neocrypt.c
@@ -0,0 +1,1365 @@
+/***************************************************************************
+
+ Neo-Geo hardware
+
+ Many of the NeoGeo bootlegs use their own form of encryption and
+ protection, presumably to make them harder for other bootleggser to
+ copy. This encryption often involves non-trivial scrambling of the
+ program roms and the games are protected using an Altera chip which
+ provides some kind of rom overlay, patching parts of the code.
+ The graphics roms are usually scrambled in a different way to the
+ official SNK cartridges too.
+
+ NeoGeo 'C' (Graphics) Rom encryption
+ CMC42 and CMC50 protection chips
+ Also contains 'S' (Text Layer) data on these games
+ M1 (Z80) rom is also encrypted for CMC50: NOT DECRYPTED
+
+ Later games use additional basic scrambling on top of the standard
+ CMC scramble.
+
+ NeoGeo 'P' Rom Encryption
+ Used on various games
+
+ kof98
+ - unique early encryption
+ kof99, garou, garouo, mslug3, kof2000
+ - complex SMA chip which appears to contain part of the game rom
+ internally and decrypts the 68k code on the board. Also has a
+ random number generator and custom bankswitching
+ (see machine/neoprot.c)
+ kof2002, matrim, samsho5, samsh5p
+ - some basic block / bank swapping
+ svcchaos, kof2003, mslug5
+ - different scrambling with additional xor
+
+ NeoGeo 'V' Rom encryption
+ NEO-PCM2 chip used on various games
+ type1 used on pnyaa, rotd, mslug4
+ type2 used on kof2002, matrim, mslug5, svcchaos,
+ samsho5, samsh5s, kof2003
+
+***************************************************************************/
+
+#include "driver.h"
+#include "neogeo.h"
+
+
+/***************************************************************************
+
+NeoGeo 'C' ROM encryption
+
+Starting with KOF99, all NeoGeo games have encrypted graphics. Additionally
+to that, the data for the front text layer, which was previously stored in
+a separate ROM, is stored at the end of the tile data.
+
+The encryption is one of the nastiest implementation of a XOR scheme ever
+seen, involving 9 seemingly uncorrelated 256-byte tables. All known games use
+the same tables except KOF2000 and MS4 which use a different set.
+
+The 32 data bits of every longword are decrypted in a single step (one byte at
+a time), but the values to use for the xor are determined in a convoluted way.
+It's actually so convoluted that it's too difficult to describe - please refer
+to the source below.
+Suffice to say that bytes are handled in couples (0&3 and 1&2), and the two xor
+values are taken from three tables, the indexes inside the tables depending on
+bits 0-7 and 8-15 of the address, in one case further xored through the table
+used in step 5) below. Additionally, the bytes in a couple can be swapped,
+depending either on bit 8 of the address, or on bit 16 xored with the table
+used in step 4) below.
+
+The 24 address bits are encrypted in five steps. Each step xors 8 bits with a
+value taken from a different table; the index inside the table depends on 8
+other bits.
+0) xor bits 0-7 with a fixed value that changes from game to game
+1) xor bits 8-15 depending on bits 16-23
+2) xor bits 8-15 depending on bits 0-7
+3) xor bits 16-23 depending on bits 0-7
+4) xor bits 16-23 depending on bits 8-15
+5) xor bits 0-7 depending on bits 8-15
+
+Each step acts on the current value, so e.g. step 4) uses bits 8-15 as modified
+by step 2).
+
+[Note: the table used in step 1) is currently incomplete due to lack of data to
+analyze]
+
+
+There are two major weaknesses in this encryption algorithm, that exposed it to
+a known plaintext attack.
+
+The first weakness is that the data xor depends on the address inside the
+encrypted ROM instead that on the decrypted address; together with the high
+concentration of 0x00 and 0xFF in the decrypted data (more than 60% of the
+total), this exposed easily recognizable patterns in the encrypted data, which
+could be exploited with some simple statistical checks. The deviousness of the
+xor scheme was the major difficulty.
+
+The second weakness is that the address scrambling works on 32-bit words. Since
+there are a large number of 32-bit values that appear only once in the whole
+encrypted ROM space, this means that once the xor layer was broken, a large
+table of encrypted-decrypted address correspondencies could be built and
+analyzed, quickly leading to the algorithm.
+
+***************************************************************************/
+
+static const UINT8 *type0_t03;
+static const UINT8 *type0_t12;
+static const UINT8 *type1_t03;
+static const UINT8 *type1_t12;
+static const UINT8 *address_8_15_xor1;
+static const UINT8 *address_8_15_xor2;
+static const UINT8 *address_16_23_xor1;
+static const UINT8 *address_16_23_xor2;
+static const UINT8 *address_0_7_xor;
+
+
+static const UINT8 kof99_type0_t03[256] =
+{
+ 0xfb, 0x86, 0x9d, 0xf1, 0xbf, 0x80, 0xd5, 0x43, 0xab, 0xb3, 0x9f, 0x6a, 0x33, 0xd9, 0xdb, 0xb6,
+ 0x66, 0x08, 0x69, 0x88, 0xcc, 0xb7, 0xde, 0x49, 0x97, 0x64, 0x1f, 0xa6, 0xc0, 0x2f, 0x52, 0x42,
+ 0x44, 0x5a, 0xf2, 0x28, 0x98, 0x87, 0x96, 0x8a, 0x83, 0x0b, 0x03, 0x61, 0x71, 0x99, 0x6b, 0xb5,
+ 0x1a, 0x8e, 0xfe, 0x04, 0xe1, 0xf7, 0x7d, 0xdd, 0xed, 0xca, 0x37, 0xfc, 0xef, 0x39, 0x72, 0xda,
+ 0xb8, 0xbe, 0xee, 0x7f, 0xe5, 0x31, 0x78, 0xf3, 0x91, 0x9a, 0xd2, 0x11, 0x19, 0xb9, 0x09, 0x4c,
+ 0xfd, 0x6d, 0x2a, 0x4d, 0x65, 0xa1, 0x89, 0xc7, 0x75, 0x50, 0x21, 0xfa, 0x16, 0x00, 0xe9, 0x12,
+ 0x74, 0x2b, 0x1e, 0x4f, 0x14, 0x01, 0x70, 0x3a, 0x4e, 0x3f, 0xf5, 0xf4, 0x1d, 0x3d, 0x15, 0x27,
+ 0xa7, 0xff, 0x45, 0xe0, 0x6e, 0xf9, 0x54, 0xc8, 0x48, 0xad, 0xa5, 0x0a, 0xf6, 0x2d, 0x2c, 0xe2,
+ 0x68, 0x67, 0xd6, 0x85, 0xb4, 0xc3, 0x34, 0xbc, 0x62, 0xd3, 0x5f, 0x84, 0x06, 0x5b, 0x0d, 0x95,
+ 0xea, 0x5e, 0x9e, 0xd4, 0xeb, 0x90, 0x7a, 0x05, 0x81, 0x57, 0xe8, 0x60, 0x2e, 0x20, 0x25, 0x7c,
+ 0x46, 0x0c, 0x93, 0xcb, 0xbd, 0x17, 0x7e, 0xec, 0x79, 0xb2, 0xc2, 0x22, 0x41, 0xb1, 0x10, 0xac,
+ 0xa8, 0xbb, 0x9b, 0x82, 0x4b, 0x9c, 0x8b, 0x07, 0x47, 0x35, 0x24, 0x56, 0x8d, 0xaf, 0xe6, 0x26,
+ 0x40, 0x38, 0xc4, 0x5d, 0x1b, 0xc5, 0xd1, 0x0f, 0x6c, 0x7b, 0xb0, 0xe3, 0xa3, 0x23, 0x6f, 0x58,
+ 0xc1, 0xba, 0xcf, 0xd7, 0xa2, 0xe7, 0xd0, 0x63, 0x5c, 0xf8, 0x73, 0xa0, 0x13, 0xdc, 0x29, 0xcd,
+ 0xc9, 0x76, 0xae, 0x8f, 0xe4, 0x59, 0x30, 0xaa, 0x94, 0x1c, 0x3c, 0x0e, 0x55, 0x92, 0x77, 0x32,
+ 0xc6, 0xce, 0x18, 0x36, 0xdf, 0xa9, 0x8c, 0xd8, 0xa4, 0xf0, 0x3b, 0x51, 0x4a, 0x02, 0x3e, 0x53,
+};
+
+
+static const UINT8 kof99_type0_t12[256] =
+{
+ 0x1f, 0xac, 0x4d, 0xcd, 0xca, 0x70, 0x02, 0x6b, 0x18, 0x40, 0x62, 0xb2, 0x3f, 0x9b, 0x5b, 0xef,
+ 0x69, 0x68, 0x71, 0x3b, 0xcb, 0xd4, 0x30, 0xbc, 0x47, 0x72, 0x74, 0x5e, 0x84, 0x4c, 0x1b, 0xdb,
+ 0x6a, 0x35, 0x1d, 0xf5, 0xa1, 0xb3, 0x87, 0x5d, 0x57, 0x28, 0x2f, 0xc4, 0xfd, 0x24, 0x26, 0x36,
+ 0xad, 0xbe, 0x61, 0x63, 0x73, 0xaa, 0x82, 0xee, 0x29, 0xd0, 0xdf, 0x8c, 0x15, 0xb5, 0x96, 0xf3,
+ 0xdd, 0x7e, 0x3a, 0x37, 0x58, 0x7f, 0x0c, 0xfc, 0x0b, 0x07, 0xe8, 0xf7, 0xf4, 0x14, 0xb8, 0x81,
+ 0xb6, 0xd7, 0x1e, 0xc8, 0x85, 0xe6, 0x9d, 0x33, 0x60, 0xc5, 0x95, 0xd5, 0x55, 0x00, 0xa3, 0xb7,
+ 0x7d, 0x50, 0x0d, 0xd2, 0xc1, 0x12, 0xe5, 0xed, 0xd8, 0xa4, 0x9c, 0x8f, 0x2a, 0x4f, 0xa8, 0x01,
+ 0x52, 0x83, 0x65, 0xea, 0x9a, 0x6c, 0x44, 0x4a, 0xe2, 0xa5, 0x2b, 0x46, 0xe1, 0x34, 0x25, 0xf8,
+ 0xc3, 0xda, 0xc7, 0x6e, 0x48, 0x38, 0x7c, 0x78, 0x06, 0x53, 0x64, 0x16, 0x98, 0x3c, 0x91, 0x42,
+ 0x39, 0xcc, 0xb0, 0xf1, 0xeb, 0x13, 0xbb, 0x05, 0x32, 0x86, 0x0e, 0xa2, 0x0a, 0x9e, 0xfa, 0x66,
+ 0x54, 0x8e, 0xd3, 0xe7, 0x19, 0x20, 0x77, 0xec, 0xff, 0xbd, 0x6d, 0x43, 0x23, 0x03, 0xab, 0x75,
+ 0x3d, 0xcf, 0xd1, 0xde, 0x92, 0x31, 0xa7, 0x45, 0x4b, 0xc2, 0x97, 0xf9, 0x7a, 0x88, 0xd9, 0x1c,
+ 0xe9, 0xe4, 0x10, 0xc9, 0x22, 0x2d, 0x90, 0x76, 0x17, 0x79, 0x04, 0x51, 0x1a, 0x5a, 0x5f, 0x2c,
+ 0x21, 0x6f, 0x3e, 0xe0, 0xf0, 0xbf, 0xd6, 0x94, 0x0f, 0x80, 0x11, 0xa0, 0x5c, 0xa9, 0x49, 0x2e,
+ 0xce, 0xaf, 0xa6, 0x9f, 0x7b, 0x99, 0xb9, 0xb4, 0xe3, 0xfb, 0xf6, 0x27, 0xf2, 0x93, 0xfe, 0x08,
+ 0x67, 0xae, 0x09, 0x89, 0xdc, 0x4e, 0xc6, 0xc0, 0x8a, 0xb1, 0x59, 0x8b, 0x41, 0x56, 0x8d, 0xba,
+};
+
+
+static const UINT8 kof99_type1_t03[256] =
+{
+ 0xa9, 0x17, 0xaf, 0x0d, 0x34, 0x6e, 0x53, 0xb6, 0x7f, 0x58, 0xe9, 0x14, 0x5f, 0x55, 0xdb, 0xd4,
+ 0x42, 0x80, 0x99, 0x59, 0xa8, 0x3a, 0x57, 0x5d, 0xd5, 0x6f, 0x4c, 0x68, 0x35, 0x46, 0xa6, 0xe7,
+ 0x7b, 0x71, 0xe0, 0x93, 0xa2, 0x1f, 0x64, 0x21, 0xe3, 0xb1, 0x98, 0x26, 0xab, 0xad, 0xee, 0xe5,
+ 0xbb, 0xd9, 0x1e, 0x2e, 0x95, 0x36, 0xef, 0x23, 0x79, 0x45, 0x04, 0xed, 0x13, 0x1d, 0xf4, 0x85,
+ 0x96, 0xec, 0xc2, 0x32, 0xaa, 0x7c, 0x15, 0xd8, 0xda, 0x92, 0x90, 0x9d, 0xb7, 0x56, 0x6a, 0x66,
+ 0x41, 0xfc, 0x00, 0xf6, 0x50, 0x24, 0xcf, 0xfb, 0x11, 0xfe, 0x82, 0x48, 0x9b, 0x27, 0x1b, 0x67,
+ 0x4e, 0x84, 0x69, 0x97, 0x6d, 0x8c, 0xd2, 0xba, 0x74, 0xf9, 0x8f, 0xa5, 0x54, 0x5c, 0xcd, 0x73,
+ 0x07, 0xd1, 0x01, 0x09, 0xf1, 0x19, 0x3b, 0x5e, 0x87, 0x30, 0x76, 0xcc, 0xc0, 0x5a, 0xa7, 0x49,
+ 0x22, 0xfa, 0x16, 0x02, 0xdf, 0xa4, 0xff, 0xb3, 0x75, 0x33, 0xbd, 0x88, 0x2f, 0xcb, 0x2a, 0x44,
+ 0xb8, 0xbf, 0x1c, 0x0f, 0x81, 0x10, 0x43, 0xb4, 0xc8, 0x7e, 0x9a, 0x25, 0xea, 0x83, 0x4b, 0x38,
+ 0x7a, 0xd7, 0x3d, 0x1a, 0x4f, 0x62, 0x51, 0xc9, 0x47, 0x0e, 0xce, 0x3f, 0xc7, 0x4d, 0x2c, 0xa1,
+ 0x86, 0xb9, 0xc5, 0xca, 0xdd, 0x6b, 0x70, 0x6c, 0x91, 0x9c, 0xbe, 0x0a, 0x9f, 0xf5, 0x94, 0xbc,
+ 0x18, 0x2b, 0x60, 0x20, 0x29, 0xf7, 0xf2, 0x28, 0xc4, 0xa0, 0x0b, 0x65, 0xde, 0x8d, 0x78, 0x12,
+ 0x3e, 0xd0, 0x77, 0x08, 0x8b, 0xae, 0x05, 0x31, 0x3c, 0xd6, 0xa3, 0x89, 0x06, 0xdc, 0x52, 0x72,
+ 0xb0, 0xb5, 0x37, 0xd3, 0xc3, 0x8a, 0xc6, 0xf0, 0xc1, 0x61, 0xfd, 0x4a, 0x5b, 0x7d, 0x9e, 0xf3,
+ 0x63, 0x40, 0x2d, 0xe8, 0xb2, 0xe6, 0x39, 0x03, 0xeb, 0x8e, 0xe1, 0x0c, 0xe4, 0xe2, 0xf8, 0xac,
+};
+
+
+static const UINT8 kof99_type1_t12[256] =
+{
+ 0xea, 0xe6, 0x5e, 0xa7, 0x8e, 0xac, 0x34, 0x03, 0x30, 0x97, 0x52, 0x53, 0x76, 0xf2, 0x62, 0x0b,
+ 0x0a, 0xfc, 0x94, 0xb8, 0x67, 0x36, 0x11, 0xbc, 0xae, 0xca, 0xfa, 0x15, 0x04, 0x2b, 0x17, 0xc4,
+ 0x3e, 0x5b, 0x59, 0x01, 0x57, 0xe2, 0xba, 0xb7, 0xd1, 0x3f, 0xf0, 0x6a, 0x9c, 0x2a, 0xcb, 0xa9,
+ 0xe3, 0x2c, 0xc0, 0x0f, 0x46, 0x91, 0x8a, 0xd0, 0x98, 0xc5, 0xa6, 0x1b, 0x96, 0x29, 0x12, 0x09,
+ 0x63, 0xed, 0xe0, 0xa2, 0x86, 0x77, 0xbe, 0xe5, 0x65, 0xdb, 0xbd, 0x50, 0xb3, 0x9d, 0x1a, 0x4e,
+ 0x79, 0x0c, 0x00, 0x43, 0xdf, 0x3d, 0x54, 0x33, 0x8f, 0x89, 0xa8, 0x7b, 0xf9, 0xd5, 0x27, 0x82,
+ 0xbb, 0xc2, 0x8c, 0x47, 0x88, 0x6b, 0xb4, 0xc3, 0xf8, 0xaa, 0x06, 0x1e, 0x83, 0x7d, 0x05, 0x78,
+ 0x85, 0xf6, 0x6e, 0x2e, 0xec, 0x5a, 0x31, 0x45, 0x38, 0x14, 0x16, 0x8b, 0x02, 0xe4, 0x4f, 0xb0,
+ 0xbf, 0xab, 0xa4, 0x9e, 0x48, 0x60, 0x19, 0x35, 0x08, 0xde, 0xdd, 0x66, 0x90, 0x51, 0xcc, 0xa3,
+ 0xaf, 0x70, 0x9b, 0x75, 0x95, 0x49, 0x6c, 0x64, 0x72, 0x7e, 0x44, 0xa0, 0x73, 0x25, 0x68, 0x55,
+ 0x1f, 0x40, 0x7a, 0x74, 0x0e, 0x8d, 0xdc, 0x1c, 0x71, 0xc8, 0xcf, 0xd7, 0xe8, 0xce, 0xeb, 0x32,
+ 0x3a, 0xee, 0x07, 0x61, 0x4d, 0xfe, 0x5c, 0x7c, 0x56, 0x2f, 0x2d, 0x5f, 0x6f, 0x9f, 0x81, 0x22,
+ 0x58, 0x4b, 0xad, 0xda, 0xb9, 0x10, 0x18, 0x23, 0xe1, 0xf3, 0x6d, 0xe7, 0xe9, 0x28, 0xd6, 0xd8,
+ 0xf4, 0x4c, 0x39, 0x21, 0xb2, 0x84, 0xc1, 0x24, 0x26, 0xf1, 0x93, 0x37, 0xc6, 0x4a, 0xcd, 0x20,
+ 0xc9, 0xd9, 0xc7, 0xb1, 0xff, 0x99, 0xd4, 0x5d, 0xb5, 0xa1, 0x87, 0x0d, 0x69, 0x92, 0x13, 0x80,
+ 0xd2, 0xd3, 0xfd, 0x1d, 0xf5, 0x3b, 0xa5, 0x7f, 0xef, 0x9a, 0xb6, 0x42, 0xfb, 0x3c, 0xf7, 0x41,
+};
+
+
+/* underlined values are wrong (not enough evidence, FF fill in kof99 and garou) */
+/* they correspond to tiles 7d000-7efff */
+static const UINT8 kof99_address_8_15_xor1[256] =
+{
+ 0x00, 0xb1, 0x1e, 0xc5, 0x3d, 0x40, 0x45, 0x5e, 0xf2, 0xf8, 0x04, 0x63, 0x36, 0x87, 0x88, 0xbf,
+ 0xab, 0xcc, 0x78, 0x08, 0xdd, 0x20, 0xd4, 0x35, 0x09, 0x8e, 0x44, 0xae, 0x33, 0xa9, 0x9e, 0xcd,
+ 0xb3, 0xe5, 0xad, 0x41, 0xda, 0xbe, 0xf4, 0x16, 0x57, 0x2e, 0x53, 0x67, 0xaf, 0xdb, 0x8a, 0xd8,
+ 0x34, 0x17, 0x3c, 0x01, 0x55, 0x73, 0xcf, 0xe3, 0xe8, 0xc7, 0x0d, 0xe9, 0xa3, 0x13, 0x0c, 0xf6,
+ 0x90, 0x4e, 0xfb, 0x97, 0x6d, 0x5f, 0xa8, 0x71, 0x11, 0xfc, 0xd1, 0x95, 0x81, 0xba, 0x8c, 0x1b,
+ 0x39, 0xfe, 0xa2, 0x15, 0xa6, 0x52, 0x4d, 0x5b, 0x59, 0xa5, 0xe0, 0x96, 0xd9, 0x8f, 0x7b, 0xed,
+ 0x29, 0xd3, 0x1f, 0x0e, 0xec, 0x23, 0x0f, 0xb8, 0x6c, 0x6f, 0x7d, 0x18, 0x46, 0xd6, 0xe4, 0xb5,
+ 0x9a, 0x79, 0x02, 0xf5, 0x03, 0xc0, 0x60, 0x66, 0x5c, 0x2f, 0x76, 0x85, 0x9d, 0x54, 0x1a, 0x6a,
+ 0x28, 0xce, 0x7f, 0x7c, 0x91, 0x99, 0x4c, 0x83, 0x3e, 0xb4, 0x1d, 0x05, 0xc1, 0xc3, 0xd7, 0x47,
+ 0xde, 0xbc, 0x62, 0x6e, 0x86, 0x14, 0x80, 0x77, 0xeb, 0xf3, 0x07, 0x31, 0x56, 0xd2, 0xc2, 0xc6,
+ 0x6b, 0xdc, 0xfd, 0x22, 0x92, 0xf0, 0x06, 0x51, 0x2d, 0x38, 0xe6, 0xa0, 0x25, 0xdf, 0xd5, 0x2c,
+ 0x1c, 0x94, 0x12, 0x9c, 0xb0, 0x9b, 0xc4, 0x0b, 0xc8, 0xd0, 0xf7, 0x30, 0xcb, 0x27, 0xfa, 0x7a,
+ 0x10, 0x61, 0xaa, 0xa4, 0x70, 0xb7, 0x2a, 0x5a, 0xc9, 0xf1, 0x0a, 0x49, 0x65, 0xee, 0x69, 0x4b,
+ 0x3a, 0x8d, 0x32, 0x5d, 0x68, 0xb9, 0x9f, 0x75, 0x19, 0x3f, 0xac, 0x37, 0x4f, 0xe7, 0x93, 0x89,
+ 0x7e, 0x4a, 0x3b, 0xea, 0x74, 0x72, 0x43, 0xbd, 0x24, 0xef, 0xb6, 0xff, 0x64, 0x58, 0x84, 0x8b,
+ 0xa7, 0xbb, 0xb2, 0xe1, 0x26, 0x2b, 0x50, 0xca, 0x21, 0xf9, 0x98, 0xa1, 0xe2, 0x42, 0x82, 0x48,
+// ^^^^ ^^^^ ^^^^ ^^^^
+};
+
+
+static const UINT8 kof99_address_8_15_xor2[256] =
+{
+ 0x9b, 0x9d, 0xc1, 0x3d, 0xa9, 0xb8, 0xf4, 0x6f, 0xf6, 0x25, 0xc7, 0x47, 0xd5, 0x97, 0xdf, 0x6b,
+ 0xeb, 0x90, 0xa4, 0xb2, 0x5d, 0xf5, 0x66, 0xb0, 0xb9, 0x8b, 0x93, 0x64, 0xec, 0x7b, 0x65, 0x8c,
+ 0xf1, 0x43, 0x42, 0x6e, 0x45, 0x9f, 0xb3, 0x35, 0x06, 0x71, 0x96, 0xdb, 0xa0, 0xfb, 0x0b, 0x3a,
+ 0x1f, 0xf8, 0x8e, 0x69, 0xcd, 0x26, 0xab, 0x86, 0xa2, 0x0c, 0xbd, 0x63, 0xa5, 0x7a, 0xe7, 0x6a,
+ 0x5f, 0x18, 0x9e, 0xbf, 0xad, 0x55, 0xb1, 0x1c, 0x5c, 0x03, 0x30, 0xc6, 0x37, 0x20, 0xe3, 0xc9,
+ 0x52, 0xe8, 0xee, 0x4f, 0x01, 0x70, 0xc4, 0x77, 0x29, 0x2a, 0xba, 0x53, 0x12, 0x04, 0x7d, 0xaf,
+ 0x33, 0x8f, 0xa8, 0x4d, 0xaa, 0x5b, 0xb4, 0x0f, 0x92, 0xbb, 0xed, 0xe1, 0x2f, 0x50, 0x6c, 0xd2,
+ 0x2c, 0x95, 0xd9, 0xf9, 0x98, 0xc3, 0x76, 0x4c, 0xf2, 0xe4, 0xe5, 0x2b, 0xef, 0x9c, 0x49, 0xb6,
+ 0x31, 0x3b, 0xbc, 0xa1, 0xca, 0xde, 0x62, 0x74, 0xea, 0x81, 0x00, 0xdd, 0xa6, 0x46, 0x88, 0x3f,
+ 0x39, 0xd6, 0x23, 0x54, 0x24, 0x4a, 0xd8, 0xdc, 0xd7, 0xd1, 0xcc, 0xbe, 0x57, 0x7c, 0xda, 0x44,
+ 0x61, 0xce, 0xd3, 0xd4, 0xe9, 0x28, 0x80, 0xe0, 0x56, 0x8a, 0x09, 0x05, 0x9a, 0x89, 0x1b, 0xf7,
+ 0xf3, 0x99, 0x6d, 0x5e, 0x48, 0x91, 0xc0, 0xd0, 0xc5, 0x79, 0x78, 0x41, 0x59, 0x21, 0x2e, 0xff,
+ 0xc2, 0x4b, 0x38, 0x83, 0x32, 0xe6, 0xe2, 0x7f, 0x1e, 0x17, 0x58, 0x1d, 0x1a, 0xfa, 0x85, 0x82,
+ 0x94, 0xc8, 0x72, 0x7e, 0xb7, 0xac, 0x0e, 0xfc, 0xfd, 0x16, 0x27, 0x75, 0x8d, 0xcb, 0x08, 0xfe,
+ 0x0a, 0x02, 0x0d, 0x36, 0x11, 0x22, 0x84, 0x40, 0x34, 0x3e, 0x2d, 0x68, 0x5a, 0xa7, 0x67, 0xae,
+ 0x87, 0x07, 0x10, 0x60, 0x14, 0x73, 0x3c, 0x51, 0x19, 0xa3, 0xb5, 0xcf, 0x13, 0xf0, 0x15, 0x4e,
+};
+
+
+static const UINT8 kof99_address_16_23_xor1[256] =
+{
+ 0x00, 0x5f, 0x03, 0x52, 0xce, 0xe3, 0x7d, 0x8f, 0x6b, 0xf8, 0x20, 0xde, 0x7b, 0x7e, 0x39, 0xbe,
+ 0xf5, 0x94, 0x18, 0x78, 0x80, 0xc9, 0x7f, 0x7a, 0x3e, 0x63, 0xf2, 0xe0, 0x4e, 0xf7, 0x87, 0x27,
+ 0x69, 0x6c, 0xa4, 0x1d, 0x85, 0x5b, 0xe6, 0x44, 0x25, 0x0c, 0x98, 0xc7, 0x01, 0x02, 0xa3, 0x26,
+ 0x09, 0x38, 0xdb, 0xc3, 0x1e, 0xcf, 0x23, 0x45, 0x68, 0x76, 0xd6, 0x22, 0x5d, 0x5a, 0xae, 0x16,
+ 0x9f, 0xa2, 0xb5, 0xcd, 0x81, 0xea, 0x5e, 0xb8, 0xb9, 0x9d, 0x9c, 0x1a, 0x0f, 0xff, 0xe1, 0xe7,
+ 0x74, 0xaa, 0xd4, 0xaf, 0xfc, 0xc6, 0x33, 0x29, 0x5c, 0xab, 0x95, 0xf0, 0x19, 0x47, 0x59, 0x67,
+ 0xf3, 0x96, 0x60, 0x1f, 0x62, 0x92, 0xbd, 0x89, 0xee, 0x28, 0x13, 0x06, 0xfe, 0xfa, 0x32, 0x6d,
+ 0x57, 0x3c, 0x54, 0x50, 0x2c, 0x58, 0x49, 0xfb, 0x17, 0xcc, 0xef, 0xb2, 0xb4, 0xf9, 0x07, 0x70,
+ 0xc5, 0xa9, 0xdf, 0xd5, 0x3b, 0x86, 0x2b, 0x0d, 0x6e, 0x4d, 0x0a, 0x90, 0x43, 0x31, 0xc1, 0xf6,
+ 0x88, 0x0b, 0xda, 0x53, 0x14, 0xdc, 0x75, 0x8e, 0xb0, 0xeb, 0x99, 0x46, 0xa1, 0x15, 0x71, 0xc8,
+ 0xe9, 0x3f, 0x4a, 0xd9, 0x73, 0xe5, 0x7c, 0x30, 0x77, 0xd3, 0xb3, 0x4b, 0x37, 0x72, 0xc2, 0x04,
+ 0x97, 0x08, 0x36, 0xb1, 0x3a, 0x61, 0xec, 0xe2, 0x1c, 0x9a, 0x8b, 0xd1, 0x1b, 0x2e, 0x9e, 0x8a,
+ 0xd8, 0x41, 0xe4, 0xc4, 0x40, 0x2f, 0xad, 0xc0, 0xb6, 0x84, 0x51, 0x66, 0xbb, 0x12, 0xe8, 0xdd,
+ 0xcb, 0xbc, 0x6f, 0xd0, 0x11, 0x83, 0x56, 0x4c, 0xca, 0xbf, 0x05, 0x10, 0xd7, 0xba, 0xfd, 0xed,
+ 0x8c, 0x0e, 0x4f, 0x3d, 0x35, 0x91, 0xb7, 0xac, 0x34, 0x64, 0x2a, 0xf1, 0x79, 0x6a, 0x9b, 0x2d,
+ 0x65, 0xf4, 0x42, 0xa0, 0x8d, 0xa7, 0x48, 0x55, 0x21, 0x93, 0x24, 0xd2, 0xa6, 0xa5, 0xa8, 0x82,
+};
+
+
+static const UINT8 kof99_address_16_23_xor2[256] =
+{
+ 0x29, 0x97, 0x1a, 0x2c, 0x0b, 0x94, 0x3e, 0x75, 0x01, 0x0d, 0x1b, 0xe1, 0x4d, 0x38, 0x39, 0x8f,
+ 0xe7, 0xd0, 0x60, 0x90, 0xb2, 0x0f, 0xbb, 0x70, 0x1f, 0xe6, 0x5b, 0x87, 0xb4, 0x43, 0xfd, 0xf5,
+ 0xf6, 0xf9, 0xad, 0xc0, 0x98, 0x17, 0x9f, 0x91, 0x15, 0x51, 0x55, 0x64, 0x6c, 0x18, 0x61, 0x0e,
+ 0xd9, 0x93, 0xab, 0xd6, 0x24, 0x2f, 0x6a, 0x3a, 0x22, 0xb1, 0x4f, 0xaa, 0x23, 0x48, 0xed, 0xb9,
+ 0x88, 0x8b, 0xa3, 0x6b, 0x26, 0x4c, 0xe8, 0x2d, 0x1c, 0x99, 0xbd, 0x5c, 0x58, 0x08, 0x50, 0xf2,
+ 0x2a, 0x62, 0xc1, 0x72, 0x66, 0x04, 0x10, 0x37, 0x6e, 0xfc, 0x44, 0xa9, 0xdf, 0xd4, 0x20, 0xdd,
+ 0xee, 0x41, 0xdb, 0x73, 0xde, 0x54, 0xec, 0xc9, 0xf3, 0x4b, 0x2e, 0xae, 0x5a, 0x4a, 0x5e, 0x47,
+ 0x07, 0x2b, 0x76, 0xa4, 0xe3, 0x28, 0xfe, 0xb0, 0xf0, 0x02, 0x06, 0xd1, 0xaf, 0x42, 0xc2, 0xa5,
+ 0xe0, 0x67, 0xbf, 0x16, 0x8e, 0x35, 0xce, 0x8a, 0xe5, 0x3d, 0x7b, 0x96, 0xd7, 0x79, 0x52, 0x1e,
+ 0xa1, 0xfb, 0x9b, 0xbe, 0x21, 0x9c, 0xe9, 0x56, 0x14, 0x7f, 0xa0, 0xe4, 0xc3, 0xc4, 0x46, 0xea,
+ 0xf7, 0xd2, 0x1d, 0x31, 0x0a, 0x5f, 0xeb, 0xa2, 0x68, 0x8d, 0xb5, 0xc5, 0x74, 0x0c, 0xdc, 0x82,
+ 0x80, 0x09, 0x19, 0x95, 0x71, 0x9a, 0x11, 0x57, 0x77, 0x4e, 0xc6, 0xff, 0x12, 0x03, 0xa7, 0xc7,
+ 0xf4, 0xc8, 0xb6, 0x7a, 0x59, 0x36, 0x3c, 0x53, 0xe2, 0x69, 0x8c, 0x25, 0x05, 0x45, 0x63, 0xf8,
+ 0x34, 0x89, 0x33, 0x3f, 0x85, 0x27, 0xbc, 0x65, 0xfa, 0xa8, 0x6d, 0x84, 0x5d, 0xba, 0x40, 0x32,
+ 0x30, 0xef, 0x83, 0x13, 0xa6, 0x78, 0xcc, 0x81, 0x9e, 0xda, 0xca, 0xd3, 0x7e, 0x9d, 0x6f, 0xcd,
+ 0xb7, 0xb3, 0xd8, 0xcf, 0x3b, 0x00, 0x92, 0xb8, 0x86, 0xac, 0x49, 0x7c, 0xf1, 0xd5, 0xcb, 0x7d,
+};
+
+
+static const UINT8 kof99_address_0_7_xor[256] =
+{
+ 0x74, 0xad, 0x5d, 0x1d, 0x9e, 0xc3, 0xfa, 0x4e, 0xf7, 0xdb, 0xca, 0xa2, 0x64, 0x36, 0x56, 0x0c,
+ 0x4f, 0xcf, 0x43, 0x66, 0x1e, 0x91, 0xe3, 0xa5, 0x58, 0xc2, 0xc1, 0xd4, 0xb9, 0xdd, 0x76, 0x16,
+ 0xce, 0x61, 0x75, 0x01, 0x2b, 0x22, 0x38, 0x55, 0x50, 0xef, 0x6c, 0x99, 0x05, 0xe9, 0xe8, 0xe0,
+ 0x2d, 0xa4, 0x4b, 0x4a, 0x42, 0xae, 0xba, 0x8c, 0x6f, 0x93, 0x14, 0xbd, 0x71, 0x21, 0xb0, 0x02,
+ 0x15, 0xc4, 0xe6, 0x60, 0xd7, 0x44, 0xfd, 0x85, 0x7e, 0x78, 0x8f, 0x00, 0x81, 0xf1, 0xa7, 0x3b,
+ 0xa0, 0x10, 0xf4, 0x9f, 0x39, 0x88, 0x35, 0x62, 0xcb, 0x19, 0x31, 0x11, 0x51, 0xfb, 0x2a, 0x20,
+ 0x45, 0xd3, 0x7d, 0x92, 0x1b, 0xf2, 0x09, 0x0d, 0x97, 0xa9, 0xb5, 0x3c, 0xee, 0x5c, 0xaf, 0x7b,
+ 0xd2, 0x3a, 0x49, 0x8e, 0xb6, 0xcd, 0xd9, 0xde, 0x8a, 0x29, 0x6e, 0xd8, 0x0b, 0xe1, 0x69, 0x87,
+ 0x1a, 0x96, 0x18, 0xcc, 0xdf, 0xe7, 0xc5, 0xc7, 0xf8, 0x52, 0xc9, 0xf0, 0xb7, 0xe5, 0x33, 0xda,
+ 0x67, 0x9d, 0xa3, 0x03, 0x0e, 0x72, 0x26, 0x79, 0xe2, 0xb8, 0xfc, 0xaa, 0xfe, 0xb4, 0x86, 0xc8,
+ 0xd1, 0xbc, 0x12, 0x08, 0x77, 0xeb, 0x40, 0x8d, 0x04, 0x25, 0x4d, 0x5a, 0x6a, 0x7a, 0x2e, 0x41,
+ 0x65, 0x1c, 0x13, 0x94, 0xb2, 0x63, 0x28, 0x59, 0x5e, 0x9a, 0x30, 0x07, 0xc6, 0xbf, 0x17, 0xf5,
+ 0x0f, 0x89, 0xf3, 0x1f, 0xea, 0x6d, 0xb3, 0xc0, 0x70, 0x47, 0xf9, 0x53, 0xf6, 0xd6, 0x54, 0xed,
+ 0x6b, 0x4c, 0xe4, 0x8b, 0x83, 0x24, 0x90, 0xb1, 0x7c, 0xbb, 0x73, 0xab, 0xd5, 0x2f, 0x5f, 0xec,
+ 0x9c, 0x2c, 0xa8, 0x34, 0x46, 0x37, 0x27, 0xa1, 0x0a, 0x06, 0x80, 0x68, 0x82, 0x32, 0x84, 0xff,
+ 0x48, 0xac, 0x7f, 0x3f, 0x95, 0xdc, 0x98, 0x9b, 0xbe, 0x23, 0x57, 0x3e, 0x5b, 0xd0, 0x3d, 0xa6,
+};
+
+
+static const UINT8 kof2000_type0_t03[256] =
+{
+ 0x10, 0x61, 0xf1, 0x78, 0x85, 0x52, 0x68, 0xe3, 0x12, 0x0d, 0xfa, 0xf0, 0xc9, 0x36, 0x5e, 0x3d,
+ 0xf9, 0xa6, 0x01, 0x2e, 0xc7, 0x84, 0xea, 0x2b, 0x6d, 0x14, 0x38, 0x4f, 0x55, 0x1c, 0x9d, 0xa7,
+ 0x7a, 0xc6, 0xf8, 0x9a, 0xe6, 0x42, 0xb5, 0xed, 0x7d, 0x3a, 0xb1, 0x05, 0x43, 0x4a, 0x22, 0xfd,
+ 0xac, 0xa4, 0x31, 0xc3, 0x32, 0x76, 0x95, 0x9e, 0x7e, 0x88, 0x8e, 0xa2, 0x97, 0x18, 0xbe, 0x2a,
+ 0xf5, 0xd6, 0xca, 0xcc, 0x72, 0x3b, 0x87, 0x6c, 0xde, 0x75, 0xd7, 0x21, 0xcb, 0x0b, 0xdd, 0xe7,
+ 0xe1, 0x65, 0xaa, 0xb9, 0x44, 0xfb, 0x66, 0x15, 0x1a, 0x3c, 0x98, 0xcf, 0x8a, 0xdf, 0x37, 0xa5,
+ 0x2f, 0x67, 0xd2, 0x83, 0xb6, 0x6b, 0xfc, 0xe0, 0xb4, 0x7c, 0x08, 0xdc, 0x93, 0x30, 0xab, 0xe4,
+ 0x19, 0xc2, 0x8b, 0xeb, 0xa0, 0x0a, 0xc8, 0x03, 0xc0, 0x4b, 0x64, 0x71, 0x86, 0x9c, 0x9b, 0x16,
+ 0x79, 0xff, 0x70, 0x09, 0x8c, 0xd0, 0xf6, 0x53, 0x07, 0x73, 0xd4, 0x89, 0xb3, 0x00, 0xe9, 0xfe,
+ 0xec, 0x8f, 0xbc, 0xb2, 0x1e, 0x5d, 0x11, 0x35, 0xa9, 0x06, 0x59, 0x9f, 0xc1, 0xd3, 0x7b, 0xf2,
+ 0xc5, 0x77, 0x4e, 0x39, 0x20, 0xd5, 0x6a, 0x82, 0xda, 0x45, 0xf3, 0x33, 0x81, 0x23, 0xba, 0xe2,
+ 0x1d, 0x5f, 0x5c, 0x51, 0x49, 0xae, 0x8d, 0xc4, 0xa8, 0xf7, 0x1f, 0x0f, 0x34, 0x28, 0xa1, 0xd9,
+ 0x27, 0xd8, 0x4c, 0x2c, 0xbf, 0x91, 0x3e, 0x69, 0x57, 0x41, 0x25, 0x0c, 0x5a, 0x90, 0x92, 0xb0,
+ 0x63, 0x6f, 0x40, 0xaf, 0x74, 0xb8, 0x2d, 0x80, 0xbb, 0x46, 0x94, 0xe5, 0x29, 0xee, 0xb7, 0x1b,
+ 0x96, 0xad, 0x13, 0x0e, 0x58, 0x99, 0x60, 0x4d, 0x17, 0x26, 0xce, 0xe8, 0xdb, 0xef, 0x24, 0xa3,
+ 0x6e, 0x7f, 0x54, 0x3f, 0x02, 0xd1, 0x5b, 0x50, 0x56, 0x48, 0xf4, 0xbd, 0x62, 0x47, 0x04, 0xcd,
+};
+
+
+static const UINT8 kof2000_type0_t12[256] =
+{
+ 0xf4, 0x28, 0xb4, 0x8f, 0xfa, 0xeb, 0x8e, 0x54, 0x2b, 0x49, 0xd1, 0x76, 0x71, 0x47, 0x8b, 0x57,
+ 0x92, 0x85, 0x7c, 0xb8, 0x5c, 0x22, 0xf9, 0x26, 0xbc, 0x5b, 0x6d, 0x67, 0xae, 0x5f, 0x6f, 0xf5,
+ 0x9f, 0x48, 0x66, 0x40, 0x0d, 0x11, 0x4e, 0xb2, 0x6b, 0x35, 0x15, 0x0f, 0x18, 0x25, 0x1d, 0xba,
+ 0xd3, 0x69, 0x79, 0xec, 0xa8, 0x8c, 0xc9, 0x7f, 0x4b, 0xdb, 0x51, 0xaf, 0xca, 0xe2, 0xb3, 0x81,
+ 0x12, 0x5e, 0x7e, 0x38, 0xc8, 0x95, 0x01, 0xff, 0xfd, 0xfb, 0xf2, 0x74, 0x62, 0x14, 0xa5, 0x98,
+ 0xa6, 0xda, 0x80, 0x53, 0xe8, 0x56, 0xac, 0x1b, 0x52, 0xd0, 0xf1, 0x45, 0x42, 0xb6, 0x1a, 0x4a,
+ 0x3a, 0x99, 0xfc, 0xd2, 0x9c, 0xcf, 0x31, 0x2d, 0xdd, 0x86, 0x2f, 0x29, 0xe1, 0x03, 0x19, 0xa2,
+ 0x41, 0x33, 0x83, 0x90, 0xc1, 0xbf, 0x0b, 0x08, 0x3d, 0xd8, 0x8d, 0x6c, 0x39, 0xa0, 0xe3, 0x55,
+ 0x02, 0x50, 0x46, 0xe6, 0xc3, 0x82, 0x36, 0x13, 0x75, 0xab, 0x27, 0xd7, 0x1f, 0x0a, 0xd4, 0x89,
+ 0x59, 0x4f, 0xc0, 0x5d, 0xc6, 0xf7, 0x88, 0xbd, 0x3c, 0x00, 0xef, 0xcd, 0x05, 0x1c, 0xaa, 0x9b,
+ 0xed, 0x7a, 0x61, 0x17, 0x93, 0xfe, 0x23, 0xb9, 0xf3, 0x68, 0x78, 0xf6, 0x5a, 0x7b, 0xe0, 0xe4,
+ 0xa3, 0xee, 0x16, 0x72, 0xc7, 0x3b, 0x8a, 0x37, 0x2a, 0x70, 0xa9, 0x2c, 0x21, 0xf8, 0x24, 0x09,
+ 0xce, 0x20, 0x9e, 0x06, 0x87, 0xc5, 0x04, 0x64, 0x43, 0x7d, 0x4d, 0x10, 0xd6, 0xa4, 0x94, 0x4c,
+ 0x60, 0xde, 0xdf, 0x58, 0xb1, 0x44, 0x3f, 0xb0, 0xd9, 0xe5, 0xcb, 0xbb, 0xbe, 0xea, 0x07, 0x34,
+ 0x73, 0x6a, 0x77, 0xf0, 0x9d, 0x0c, 0x2e, 0x0e, 0x91, 0x9a, 0xcc, 0xc2, 0xb7, 0x63, 0x97, 0xd5,
+ 0xdc, 0xc4, 0x32, 0xe7, 0x84, 0x3e, 0x30, 0xa1, 0x1e, 0xb5, 0x6e, 0x65, 0xe9, 0xad, 0xa7, 0x96,
+};
+
+
+static const UINT8 kof2000_type1_t03[256] =
+{
+ 0x9a, 0x2f, 0xcc, 0x4e, 0x40, 0x69, 0xac, 0xca, 0xa5, 0x7b, 0x0a, 0x61, 0x91, 0x0d, 0x55, 0x74,
+ 0xcd, 0x8b, 0x0b, 0x80, 0x09, 0x5e, 0x38, 0xc7, 0xda, 0xbf, 0xf5, 0x37, 0x23, 0x31, 0x33, 0xe9,
+ 0xae, 0x87, 0xe5, 0xfa, 0x6e, 0x5c, 0xad, 0xf4, 0x76, 0x62, 0x9f, 0x2e, 0x01, 0xe2, 0xf6, 0x47,
+ 0x8c, 0x7c, 0xaa, 0x98, 0xb5, 0x92, 0x51, 0xec, 0x5f, 0x07, 0x5d, 0x6f, 0x16, 0xa1, 0x1d, 0xa9,
+ 0x48, 0x45, 0xf0, 0x6a, 0x9c, 0x1e, 0x11, 0xa0, 0x06, 0x46, 0xd5, 0xf1, 0x73, 0xed, 0x94, 0xf7,
+ 0xc3, 0x57, 0x1b, 0xe0, 0x97, 0xb1, 0xa4, 0xa7, 0x24, 0xe7, 0x2b, 0x05, 0x5b, 0x34, 0x0c, 0xb8,
+ 0x0f, 0x9b, 0xc8, 0x4d, 0x5a, 0xa6, 0x86, 0x3e, 0x14, 0x29, 0x84, 0x58, 0x90, 0xdb, 0x2d, 0x54,
+ 0x9d, 0x82, 0xd4, 0x7d, 0xc6, 0x67, 0x41, 0x89, 0xc1, 0x13, 0xb0, 0x9e, 0x81, 0x6d, 0xa8, 0x59,
+ 0xbd, 0x39, 0x8e, 0xe6, 0x25, 0x8f, 0xd9, 0xa2, 0xe4, 0x53, 0xc5, 0x72, 0x7e, 0x36, 0x4a, 0x4f,
+ 0x52, 0xc2, 0x22, 0x2a, 0xce, 0x3c, 0x21, 0x2c, 0x00, 0xd7, 0x75, 0x8a, 0x27, 0xee, 0x43, 0xfe,
+ 0xcb, 0x6b, 0xb9, 0xa3, 0x78, 0xb7, 0x85, 0x02, 0x20, 0xd0, 0x83, 0xc4, 0x12, 0xf9, 0xfd, 0xd8,
+ 0x79, 0x64, 0x3a, 0x49, 0x03, 0xb4, 0xc0, 0xf2, 0xdf, 0x15, 0x93, 0x08, 0x35, 0xff, 0x70, 0xdd,
+ 0x28, 0x6c, 0x0e, 0x04, 0xde, 0x7a, 0x65, 0xd2, 0xab, 0x42, 0x95, 0xe1, 0x3f, 0x3b, 0x7f, 0x66,
+ 0xd1, 0x8d, 0xe3, 0xbb, 0x1c, 0xfc, 0x77, 0x1a, 0x88, 0x18, 0x19, 0x68, 0x1f, 0x56, 0xd6, 0xe8,
+ 0xb6, 0xbc, 0xd3, 0xea, 0x3d, 0x26, 0xb3, 0xc9, 0x44, 0xdc, 0xf3, 0x32, 0x30, 0xef, 0x96, 0x4c,
+ 0xaf, 0x17, 0xf8, 0xfb, 0x60, 0x50, 0xeb, 0x4b, 0x99, 0x63, 0xba, 0xb2, 0x71, 0xcf, 0x10, 0xbe,
+};
+
+
+static const UINT8 kof2000_type1_t12[256] =
+{
+ 0xda, 0xa7, 0xd6, 0x6e, 0x2f, 0x5e, 0xf0, 0x3f, 0xa4, 0xce, 0xd3, 0xfd, 0x46, 0x2a, 0xac, 0xc9,
+ 0xbe, 0xeb, 0x9f, 0xd5, 0x3c, 0x61, 0x96, 0x11, 0xd0, 0x38, 0xca, 0x06, 0xed, 0x1b, 0x65, 0xe7,
+ 0x23, 0xdd, 0xd9, 0x05, 0xbf, 0x5b, 0x5d, 0xa5, 0x95, 0x00, 0xec, 0xf1, 0x01, 0xa9, 0xa6, 0xfc,
+ 0xbb, 0x54, 0xe3, 0x2e, 0x92, 0x58, 0x0a, 0x7b, 0xb6, 0xcc, 0xb1, 0x5f, 0x14, 0x35, 0x72, 0xff,
+ 0xe6, 0x52, 0xd7, 0x8c, 0xf3, 0x43, 0xaf, 0x9c, 0xc0, 0x4f, 0x0c, 0x42, 0x8e, 0xef, 0x80, 0xcd,
+ 0x1d, 0x7e, 0x88, 0x3b, 0x98, 0xa1, 0xad, 0xe4, 0x9d, 0x8d, 0x2b, 0x56, 0xb5, 0x50, 0xdf, 0x66,
+ 0x6d, 0xd4, 0x60, 0x09, 0xe1, 0xee, 0x4a, 0x47, 0xf9, 0xfe, 0x73, 0x07, 0x89, 0xa8, 0x39, 0xea,
+ 0x82, 0x9e, 0xcf, 0x26, 0xb2, 0x4e, 0xc3, 0x59, 0xf2, 0x3d, 0x9a, 0xb0, 0x69, 0xf7, 0xbc, 0x34,
+ 0xe5, 0x36, 0x22, 0xfb, 0x57, 0x71, 0x99, 0x6c, 0x83, 0x30, 0x55, 0xc2, 0xbd, 0xf4, 0x77, 0xe9,
+ 0x76, 0x97, 0xa0, 0xe0, 0xb9, 0x86, 0x6b, 0xa3, 0x84, 0x67, 0x1a, 0x70, 0x02, 0x5a, 0x41, 0x5c,
+ 0x25, 0x81, 0xaa, 0x28, 0x78, 0x4b, 0xc6, 0x64, 0x53, 0x16, 0x4d, 0x8b, 0x20, 0x93, 0xae, 0x0f,
+ 0x94, 0x2c, 0x3a, 0xc7, 0x62, 0xe8, 0xc4, 0xdb, 0x04, 0xc5, 0xfa, 0x29, 0x48, 0xd1, 0x08, 0x24,
+ 0x0d, 0xe2, 0xd8, 0x10, 0xb4, 0x91, 0x8a, 0x13, 0x0e, 0xdc, 0xd2, 0x79, 0xb8, 0xf8, 0xba, 0x2d,
+ 0xcb, 0xf5, 0x7d, 0x37, 0x51, 0x40, 0x31, 0xa2, 0x0b, 0x18, 0x63, 0x7f, 0xb3, 0xab, 0x9b, 0x87,
+ 0xf6, 0x90, 0xde, 0xc8, 0x27, 0x45, 0x7c, 0x1c, 0x85, 0x68, 0x33, 0x19, 0x03, 0x75, 0x15, 0x7a,
+ 0x1f, 0x49, 0x8f, 0x4c, 0xc1, 0x44, 0x17, 0x12, 0x6f, 0x32, 0xb7, 0x3e, 0x74, 0x1e, 0x21, 0x6a,
+};
+
+
+static const UINT8 kof2000_address_8_15_xor1[256] =
+{
+ 0xfc, 0x9b, 0x1c, 0x35, 0x72, 0x53, 0xd6, 0x7d, 0x84, 0xa4, 0xc5, 0x93, 0x7b, 0xe7, 0x47, 0xd5,
+ 0x24, 0xa2, 0xfa, 0x19, 0x0c, 0xb1, 0x8c, 0xb9, 0x9d, 0xd8, 0x59, 0x4f, 0x3c, 0xb2, 0x78, 0x4a,
+ 0x2a, 0x96, 0x9a, 0xf1, 0x1f, 0x22, 0xa8, 0x5b, 0x67, 0xa3, 0x0f, 0x00, 0xfb, 0xdf, 0xeb, 0x0a,
+ 0x57, 0xb8, 0x25, 0xd7, 0xf0, 0x6b, 0x0b, 0x31, 0x95, 0x23, 0x2d, 0x5c, 0x27, 0xc7, 0xf4, 0x55,
+ 0x1a, 0xf7, 0x74, 0xbe, 0xd3, 0xac, 0x3d, 0xc1, 0x7f, 0xbd, 0x28, 0x01, 0x10, 0xe5, 0x09, 0x37,
+ 0x1e, 0x58, 0xaf, 0x17, 0xf2, 0x16, 0x30, 0x92, 0x36, 0x68, 0xe6, 0xd4, 0xea, 0xb7, 0x75, 0x54,
+ 0x77, 0x41, 0xb4, 0x8d, 0xe0, 0xf3, 0x51, 0x03, 0xa9, 0xe8, 0x66, 0xab, 0x29, 0xa5, 0xed, 0xcb,
+ 0xd1, 0xaa, 0xf5, 0xdb, 0x4c, 0x42, 0x97, 0x8a, 0xae, 0xc9, 0x6e, 0x04, 0x33, 0x85, 0xdd, 0x2b,
+ 0x6f, 0xef, 0x12, 0x21, 0x7a, 0xa1, 0x5a, 0x91, 0xc8, 0xcc, 0xc0, 0xa7, 0x60, 0x3e, 0x56, 0x2f,
+ 0xe4, 0x71, 0x99, 0xc2, 0xa0, 0x45, 0x80, 0x65, 0xbb, 0x87, 0x69, 0x81, 0x73, 0xca, 0xf6, 0x46,
+ 0x43, 0xda, 0x26, 0x7e, 0x8f, 0xe1, 0x8b, 0xfd, 0x50, 0x79, 0xba, 0xc6, 0x63, 0x4b, 0xb3, 0x8e,
+ 0x34, 0xe2, 0x48, 0x14, 0xcd, 0xe3, 0xc4, 0x05, 0x13, 0x40, 0x06, 0x6c, 0x88, 0xb0, 0xe9, 0x1b,
+ 0x4d, 0xf8, 0x76, 0x02, 0x44, 0x94, 0xcf, 0x32, 0xfe, 0xce, 0x3b, 0x5d, 0x2c, 0x89, 0x5f, 0xdc,
+ 0xd2, 0x9c, 0x6a, 0xec, 0x18, 0x6d, 0x0e, 0x86, 0xff, 0x5e, 0x9e, 0xee, 0x11, 0xd0, 0x49, 0x52,
+ 0x4e, 0x61, 0x90, 0x0d, 0xc3, 0x39, 0x15, 0x83, 0xb5, 0x62, 0x3f, 0x70, 0x7c, 0xad, 0x20, 0xbf,
+ 0x2e, 0x08, 0x1d, 0xf9, 0xb6, 0xa6, 0x64, 0x07, 0x82, 0x38, 0x98, 0x3a, 0x9f, 0xde, 0xbc, 0xd9,
+};
+
+
+static const UINT8 kof2000_address_8_15_xor2[256] =
+{
+ 0x00, 0xbe, 0x06, 0x5a, 0xfa, 0x42, 0x15, 0xf2, 0x3f, 0x0a, 0x84, 0x93, 0x4e, 0x78, 0x3b, 0x89,
+ 0x32, 0x98, 0xa2, 0x87, 0x73, 0xdd, 0x26, 0xe5, 0x05, 0x71, 0x08, 0x6e, 0x9b, 0xe0, 0xdf, 0x9e,
+ 0xfc, 0x83, 0x81, 0xef, 0xb2, 0xc0, 0xc3, 0xbf, 0xa7, 0x6d, 0x1b, 0x95, 0xed, 0xb9, 0x3e, 0x13,
+ 0xb0, 0x47, 0x9c, 0x7a, 0x24, 0x41, 0x68, 0xd0, 0x36, 0x0b, 0xb5, 0xc2, 0x67, 0xf7, 0x54, 0x92,
+ 0x1e, 0x44, 0x86, 0x2b, 0x94, 0xcc, 0xba, 0x23, 0x0d, 0xca, 0x6b, 0x4c, 0x2a, 0x9a, 0x2d, 0x8b,
+ 0xe3, 0x52, 0x29, 0xf0, 0x21, 0xbd, 0xbb, 0x1f, 0xa3, 0xab, 0xf8, 0x46, 0xb7, 0x45, 0x82, 0x5e,
+ 0xdb, 0x07, 0x5d, 0xe9, 0x9d, 0x1a, 0x48, 0xce, 0x91, 0x12, 0xd4, 0xee, 0xa9, 0x39, 0xf1, 0x18,
+ 0x2c, 0x22, 0x8a, 0x7e, 0x34, 0x4a, 0x8c, 0xc1, 0x14, 0xf3, 0x20, 0x35, 0xd9, 0x96, 0x33, 0x77,
+ 0x9f, 0x76, 0x7c, 0x90, 0xc6, 0xd5, 0xa1, 0x5b, 0xac, 0x75, 0xc7, 0x0c, 0xb3, 0x17, 0xd6, 0x99,
+ 0x56, 0xa6, 0x3d, 0x1d, 0xb1, 0x2e, 0xd8, 0xbc, 0x2f, 0xde, 0x60, 0x55, 0x6c, 0x40, 0xcd, 0x43,
+ 0xff, 0xad, 0x38, 0x79, 0x51, 0xc8, 0x0e, 0x5f, 0xc4, 0x66, 0xcb, 0xa8, 0x7d, 0xa4, 0x3a, 0xea,
+ 0x27, 0x7b, 0x70, 0x8e, 0x5c, 0x19, 0x0f, 0x80, 0x6f, 0x8f, 0x10, 0xf9, 0x49, 0x85, 0x69, 0x7f,
+ 0xeb, 0x1c, 0x01, 0x65, 0x37, 0xa5, 0x28, 0xe4, 0x6a, 0x03, 0x04, 0xd1, 0x31, 0x11, 0x30, 0xfb,
+ 0x88, 0x97, 0xd3, 0xf6, 0xc5, 0x4d, 0xf5, 0x3c, 0xe8, 0x61, 0xdc, 0xd2, 0xb4, 0xb8, 0xa0, 0xae,
+ 0x16, 0x25, 0x02, 0x09, 0xfe, 0xcf, 0x53, 0x63, 0xaf, 0x59, 0xf4, 0xe1, 0xec, 0xd7, 0xe7, 0x50,
+ 0xe2, 0xc9, 0xaa, 0x4b, 0x8d, 0x4f, 0xe6, 0x64, 0xda, 0x74, 0xb6, 0x72, 0x57, 0x62, 0xfd, 0x58,
+};
+
+
+static const UINT8 kof2000_address_16_23_xor1[256] =
+{
+ 0x45, 0x9f, 0x6e, 0x2f, 0x28, 0xbc, 0x5e, 0x6d, 0xda, 0xb5, 0x0d, 0xb8, 0xc0, 0x8e, 0xa2, 0x32,
+ 0xee, 0xcd, 0x8d, 0x48, 0x8c, 0x27, 0x14, 0xeb, 0x65, 0xd7, 0xf2, 0x93, 0x99, 0x90, 0x91, 0xfc,
+ 0x5f, 0xcb, 0xfa, 0x75, 0x3f, 0x26, 0xde, 0x72, 0x33, 0x39, 0xc7, 0x1f, 0x88, 0x79, 0x73, 0xab,
+ 0x4e, 0x36, 0x5d, 0x44, 0xd2, 0x41, 0xa0, 0x7e, 0xa7, 0x8b, 0xa6, 0xbf, 0x03, 0xd8, 0x86, 0xdc,
+ 0x2c, 0xaa, 0x70, 0x3d, 0x46, 0x07, 0x80, 0x58, 0x0b, 0x2b, 0xe2, 0xf0, 0xb1, 0xfe, 0x42, 0xf3,
+ 0xe9, 0xa3, 0x85, 0x78, 0xc3, 0xd0, 0x5a, 0xdb, 0x1a, 0xfb, 0x9d, 0x8a, 0xa5, 0x12, 0x0e, 0x54,
+ 0x8f, 0xc5, 0x6c, 0xae, 0x25, 0x5b, 0x4b, 0x17, 0x02, 0x9c, 0x4a, 0x24, 0x40, 0xe5, 0x9e, 0x22,
+ 0xc6, 0x49, 0x62, 0xb6, 0x6b, 0xbb, 0xa8, 0xcc, 0xe8, 0x81, 0x50, 0x47, 0xc8, 0xbe, 0x5c, 0xa4,
+ 0xd6, 0x94, 0x4f, 0x7b, 0x9a, 0xcf, 0xe4, 0x59, 0x7a, 0xa1, 0xea, 0x31, 0x37, 0x13, 0x2d, 0xaf,
+ 0x21, 0x69, 0x19, 0x1d, 0x6f, 0x16, 0x98, 0x1e, 0x08, 0xe3, 0xb2, 0x4d, 0x9b, 0x7f, 0xa9, 0x77,
+ 0xed, 0xbd, 0xd4, 0xd9, 0x34, 0xd3, 0xca, 0x09, 0x18, 0x60, 0xc9, 0x6a, 0x01, 0xf4, 0xf6, 0x64,
+ 0xb4, 0x3a, 0x15, 0xac, 0x89, 0x52, 0x68, 0x71, 0xe7, 0x82, 0xc1, 0x0c, 0x92, 0xf7, 0x30, 0xe6,
+ 0x1c, 0x3e, 0x0f, 0x0a, 0x67, 0x35, 0xba, 0x61, 0xdd, 0x29, 0xc2, 0xf8, 0x97, 0x95, 0xb7, 0x3b,
+ 0xe0, 0xce, 0xf9, 0xd5, 0x06, 0x76, 0xb3, 0x05, 0x4c, 0x04, 0x84, 0x3c, 0x87, 0x23, 0x63, 0x7c,
+ 0x53, 0x56, 0xe1, 0x7d, 0x96, 0x1b, 0xd1, 0xec, 0x2a, 0x66, 0xf1, 0x11, 0x10, 0xff, 0x43, 0x2e,
+ 0xdf, 0x83, 0x74, 0xf5, 0x38, 0x20, 0xfd, 0xad, 0xc4, 0xb9, 0x55, 0x51, 0xb0, 0xef, 0x00, 0x57,
+};
+
+
+static const UINT8 kof2000_address_16_23_xor2[256] =
+{
+ 0x00, 0xb8, 0xf0, 0x34, 0xca, 0x21, 0x3c, 0xf9, 0x01, 0x8e, 0x75, 0x70, 0xec, 0x13, 0x27, 0x96,
+ 0xf4, 0x5b, 0x88, 0x1f, 0xeb, 0x4a, 0x7d, 0x9d, 0xbe, 0x02, 0x14, 0xaf, 0xa2, 0x06, 0xc6, 0xdb,
+ 0x35, 0x6b, 0x74, 0x45, 0x7b, 0x29, 0xd2, 0xfe, 0xb6, 0x15, 0xd0, 0x8a, 0xa9, 0x2d, 0x19, 0xf6,
+ 0x5e, 0x5a, 0x90, 0xe9, 0x11, 0x33, 0xc2, 0x47, 0x37, 0x4c, 0x4f, 0x59, 0xc3, 0x04, 0x57, 0x1d,
+ 0xf2, 0x63, 0x6d, 0x6e, 0x31, 0x95, 0xcb, 0x3e, 0x67, 0xb2, 0xe3, 0x98, 0xed, 0x8d, 0xe6, 0xfb,
+ 0xf8, 0xba, 0x5d, 0xd4, 0x2a, 0xf5, 0x3b, 0x82, 0x05, 0x16, 0x44, 0xef, 0x4d, 0xe7, 0x93, 0xda,
+ 0x9f, 0xbb, 0x61, 0xc9, 0x53, 0xbd, 0x76, 0x78, 0x52, 0x36, 0x0c, 0x66, 0xc1, 0x10, 0xdd, 0x7a,
+ 0x84, 0x69, 0xcd, 0xfd, 0x58, 0x0d, 0x6c, 0x89, 0x68, 0xad, 0x3a, 0xb0, 0x4b, 0x46, 0xc5, 0x03,
+ 0xb4, 0xf7, 0x30, 0x8c, 0x4e, 0x60, 0x73, 0xa1, 0x8b, 0xb1, 0x62, 0xcc, 0xd1, 0x08, 0xfc, 0x77,
+ 0x7e, 0xcf, 0x56, 0x51, 0x07, 0xa6, 0x80, 0x92, 0xdc, 0x0b, 0xa4, 0xc7, 0xe8, 0xe1, 0xb5, 0x71,
+ 0xea, 0xb3, 0x2f, 0x94, 0x18, 0xe2, 0x3d, 0x49, 0x65, 0xaa, 0xf1, 0x91, 0xc8, 0x99, 0x55, 0x79,
+ 0x86, 0xa7, 0x26, 0xa0, 0xac, 0x5f, 0xce, 0x6a, 0x5c, 0xf3, 0x87, 0x8f, 0x12, 0x1c, 0xd8, 0xe4,
+ 0x9b, 0x64, 0x2e, 0x1e, 0xd7, 0xc0, 0x17, 0xbc, 0xa3, 0xa8, 0x9a, 0x0e, 0x25, 0x40, 0x41, 0x50,
+ 0xb9, 0xbf, 0x28, 0xdf, 0x32, 0x54, 0x9e, 0x48, 0xd5, 0x2b, 0x42, 0xfa, 0x9c, 0x7f, 0xd3, 0x85,
+ 0x43, 0xde, 0x81, 0x0f, 0x24, 0xc4, 0x38, 0xae, 0x83, 0x1b, 0x6f, 0x7c, 0xe5, 0xff, 0x1a, 0xd9,
+ 0x3f, 0xb7, 0x22, 0x97, 0x09, 0xe0, 0xa5, 0x20, 0x23, 0x2c, 0x72, 0xd6, 0x39, 0xab, 0x0a, 0xee,
+};
+
+
+static const UINT8 kof2000_address_0_7_xor[256] =
+{
+ 0x26, 0x48, 0x06, 0x9b, 0x21, 0xa9, 0x1b, 0x76, 0xc9, 0xf8, 0xb4, 0x67, 0xe4, 0xff, 0x99, 0xf7,
+ 0x15, 0x9e, 0x62, 0x00, 0x72, 0x4d, 0xa0, 0x4f, 0x02, 0xf1, 0xea, 0xef, 0x0b, 0xf3, 0xeb, 0xa6,
+ 0x93, 0x78, 0x6f, 0x7c, 0xda, 0xd4, 0x7b, 0x05, 0xe9, 0xc6, 0xd6, 0xdb, 0x50, 0xce, 0xd2, 0x01,
+ 0xb5, 0xe8, 0xe0, 0x2a, 0x08, 0x1a, 0xb8, 0xe3, 0xf9, 0xb1, 0xf4, 0x8b, 0x39, 0x2d, 0x85, 0x9c,
+ 0x55, 0x73, 0x63, 0x40, 0x38, 0x96, 0xdc, 0xa3, 0xa2, 0xa1, 0x25, 0x66, 0x6d, 0x56, 0x8e, 0x10,
+ 0x0f, 0x31, 0x1c, 0xf5, 0x28, 0x77, 0x0a, 0xd1, 0x75, 0x34, 0xa4, 0xfe, 0x7d, 0x07, 0x51, 0x79,
+ 0x41, 0x90, 0x22, 0x35, 0x12, 0xbb, 0xc4, 0xca, 0xb2, 0x1f, 0xcb, 0xc8, 0xac, 0xdd, 0xd0, 0x0d,
+ 0xfc, 0xc5, 0x9d, 0x14, 0xbc, 0x83, 0xd9, 0x58, 0xc2, 0x30, 0x9a, 0x6a, 0xc0, 0x0c, 0xad, 0xf6,
+ 0x5d, 0x74, 0x7f, 0x2f, 0xbd, 0x1d, 0x47, 0xd5, 0xe6, 0x89, 0xcf, 0xb7, 0xd3, 0x59, 0x36, 0x98,
+ 0xf0, 0xfb, 0x3c, 0xf2, 0x3f, 0xa7, 0x18, 0x82, 0x42, 0x5c, 0xab, 0xba, 0xde, 0x52, 0x09, 0x91,
+ 0xaa, 0x61, 0xec, 0xd7, 0x95, 0x23, 0xcd, 0x80, 0xa5, 0x68, 0x60, 0x27, 0x71, 0xe1, 0x2c, 0x2e,
+ 0x8d, 0x2b, 0x57, 0x65, 0xbf, 0xc1, 0x19, 0xc7, 0x49, 0x64, 0x88, 0x4a, 0xcc, 0x20, 0x4e, 0xd8,
+ 0x3b, 0x4c, 0x13, 0x5f, 0x9f, 0xbe, 0x5e, 0x6e, 0xfd, 0xe2, 0xfa, 0x54, 0x37, 0x0e, 0x16, 0x7a,
+ 0x6c, 0x33, 0xb3, 0x70, 0x84, 0x7e, 0xc3, 0x04, 0xb0, 0xae, 0xb9, 0x81, 0x03, 0x29, 0xdf, 0x46,
+ 0xe5, 0x69, 0xe7, 0x24, 0x92, 0x5a, 0x4b, 0x5b, 0x94, 0x11, 0x3a, 0x3d, 0x87, 0xed, 0x97, 0xb6,
+ 0x32, 0x3e, 0x45, 0xaf, 0x1e, 0x43, 0x44, 0x8c, 0x53, 0x86, 0x6b, 0xee, 0xa8, 0x8a, 0x8f, 0x17,
+};
+
+
+
+static void decrypt(UINT8 *r0, UINT8 *r1,
+ UINT8 c0, UINT8 c1,
+ const UINT8 *table0hi,
+ const UINT8 *table0lo,
+ const UINT8 *table1,
+ int base,
+ int invert)
+{
+ UINT8 tmp,xor0,xor1;
+
+ tmp = table1[(base & 0xff) ^ address_0_7_xor[(base >> 8) & 0xff]];
+ xor0 = (table0hi[(base >> 8) & 0xff] & 0xfe) | (tmp & 0x01);
+ xor1 = (tmp & 0xfe) | (table0lo[(base >> 8) & 0xff] & 0x01);
+
+ if (invert)
+ {
+ *r0 = c1 ^ xor0;
+ *r1 = c0 ^ xor1;
+ }
+ else
+ {
+ *r0 = c0 ^ xor0;
+ *r1 = c1 ^ xor1;
+ }
+}
+
+
+static void neogeo_gfx_decrypt(int extra_xor)
+{
+ int rom_size;
+ UINT8 *buf;
+ UINT8 *rom;
+ int rpos;
+
+ rom_size = memory_region_length(NEOGEO_REGION_SPRITES);
+
+ buf = malloc_or_die(rom_size);
+
+ rom = memory_region(NEOGEO_REGION_SPRITES);
+
+ // Data xor
+ for (rpos = 0;rpos < rom_size/4;rpos++)
+ {
+ decrypt(buf+4*rpos+0, buf+4*rpos+3, rom[4*rpos+0], rom[4*rpos+3], type0_t03, type0_t12, type1_t03, rpos, (rpos>>8) & 1);
+ decrypt(buf+4*rpos+1, buf+4*rpos+2, rom[4*rpos+1], rom[4*rpos+2], type0_t12, type0_t03, type1_t12, rpos, ((rpos>>16) ^ address_16_23_xor2[(rpos>>8) & 0xff]) & 1);
+ }
+
+ // Address xor
+ for (rpos = 0;rpos < rom_size/4;rpos++)
+ {
+ int baser;
+
+ baser = rpos;
+
+ baser ^= extra_xor;
+
+ baser ^= address_8_15_xor1[(baser >> 16) & 0xff] << 8;
+ baser ^= address_8_15_xor2[baser & 0xff] << 8;
+ baser ^= address_16_23_xor1[baser & 0xff] << 16;
+ baser ^= address_16_23_xor2[(baser >> 8) & 0xff] << 16;
+ baser ^= address_0_7_xor[(baser >> 8) & 0xff];
+
+
+ if (rom_size == 0x3000000) /* special handling for preisle2 */
+ {
+ if (rpos < 0x2000000/4)
+ baser &= (0x2000000/4)-1;
+ else
+ baser = 0x2000000/4 + (baser & ((0x1000000/4)-1));
+ }
+ else if (rom_size == 0x6000000) /* special handling for kf2k3pcb */
+ {
+ if (rpos < 0x4000000/4)
+ baser &= (0x4000000/4)-1;
+ else
+ baser = 0x4000000/4 + (baser & ((0x1000000/4)-1));
+ }
+ else /* Clamp to the real rom size */
+ baser &= (rom_size/4)-1;
+
+ rom[4*rpos+0] = buf[4*baser+0];
+ rom[4*rpos+1] = buf[4*baser+1];
+ rom[4*rpos+2] = buf[4*baser+2];
+ rom[4*rpos+3] = buf[4*baser+3];
+ }
+
+ free(buf);
+}
+
+
+/* the S data comes from the end of the C data */
+static void neogeo_sfix_decrypt(void)
+{
+ int i;
+ int rom_size = memory_region_length(NEOGEO_REGION_SPRITES);
+ int tx_size = memory_region_length(NEOGEO_REGION_FIXED_LAYER_CARTRIDGE);
+ UINT8 *src = memory_region(NEOGEO_REGION_SPRITES)+rom_size-tx_size;
+ UINT8 *dst = memory_region(NEOGEO_REGION_FIXED_LAYER_CARTRIDGE);
+
+ for (i = 0;i < tx_size;i++)
+ dst[i] = src[(i & ~0x1f) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4)];
+}
+
+
+/* CMC42 protection chip */
+void kof99_neogeo_gfx_decrypt(int extra_xor)
+{
+ type0_t03 = kof99_type0_t03;
+ type0_t12 = kof99_type0_t12;
+ type1_t03 = kof99_type1_t03;
+ type1_t12 = kof99_type1_t12;
+ address_8_15_xor1 = kof99_address_8_15_xor1;
+ address_8_15_xor2 = kof99_address_8_15_xor2;
+ address_16_23_xor1 = kof99_address_16_23_xor1;
+ address_16_23_xor2 = kof99_address_16_23_xor2;
+ address_0_7_xor = kof99_address_0_7_xor;
+ neogeo_gfx_decrypt(extra_xor);
+ neogeo_sfix_decrypt();
+}
+
+
+/* CMC50 protection chip */
+void kof2000_neogeo_gfx_decrypt(int extra_xor)
+{
+ type0_t03 = kof2000_type0_t03;
+ type0_t12 = kof2000_type0_t12;
+ type1_t03 = kof2000_type1_t03;
+ type1_t12 = kof2000_type1_t12;
+ address_8_15_xor1 = kof2000_address_8_15_xor1;
+ address_8_15_xor2 = kof2000_address_8_15_xor2;
+ address_16_23_xor1 = kof2000_address_16_23_xor1;
+ address_16_23_xor2 = kof2000_address_16_23_xor2;
+ address_0_7_xor = kof2000_address_0_7_xor;
+ neogeo_gfx_decrypt(extra_xor);
+ neogeo_sfix_decrypt();
+
+ /* here I should also decrypt the sound ROM */
+}
+
+
+/* CMC42 protection chip */
+void cmc42_neogeo_gfx_decrypt(int extra_xor)
+{
+ type0_t03 = kof99_type0_t03;
+ type0_t12 = kof99_type0_t12;
+ type1_t03 = kof99_type1_t03;
+ type1_t12 = kof99_type1_t12;
+ address_8_15_xor1 = kof99_address_8_15_xor1;
+ address_8_15_xor2 = kof99_address_8_15_xor2;
+ address_16_23_xor1 = kof99_address_16_23_xor1;
+ address_16_23_xor2 = kof99_address_16_23_xor2;
+ address_0_7_xor = kof99_address_0_7_xor;
+ neogeo_gfx_decrypt(extra_xor);
+}
+
+
+/* CMC50 protection chip */
+void cmc50_neogeo_gfx_decrypt(int extra_xor)
+{
+ type0_t03 = kof2000_type0_t03;
+ type0_t12 = kof2000_type0_t12;
+ type1_t03 = kof2000_type1_t03;
+ type1_t12 = kof2000_type1_t12;
+ address_8_15_xor1 = kof2000_address_8_15_xor1;
+ address_8_15_xor2 = kof2000_address_8_15_xor2;
+ address_16_23_xor1 = kof2000_address_16_23_xor1;
+ address_16_23_xor2 = kof2000_address_16_23_xor2;
+ address_0_7_xor = kof2000_address_0_7_xor;
+ neogeo_gfx_decrypt(extra_xor);
+
+ /* here I should also decrypt the sound ROM */
+}
+
+
+/* svcchaos has an additional scramble on top of the standard CMC scrambling */
+void svcpcb_gfx_decrypt(void)
+{
+ static const UINT8 xor[ 4 ] = { 0x34, 0x21, 0xc4, 0xe9 };
+ int i;
+ int ofst;
+ int rom_size = memory_region_length( NEOGEO_REGION_SPRITES );
+ UINT8 *rom = memory_region( NEOGEO_REGION_SPRITES );
+ UINT8 *buf = malloc_or_die( rom_size );
+
+ for( i = 0; i < rom_size; i++ )
+ {
+ rom[ i ] ^= xor[ (i % 4) ];
+ }
+ for( i = 0; i < rom_size; i += 4 )
+ {
+ UINT32 rom32 = rom[i] | rom[i+1]<<8 | rom[i+2]<<16 | rom[i+3]<<24;
+ rom32 = BITSWAP32( rom32, 0x09, 0x0d, 0x13, 0x00, 0x17, 0x0f, 0x03, 0x05, 0x04, 0x0c, 0x11, 0x1e, 0x12, 0x15, 0x0b, 0x06, 0x1b, 0x0a, 0x1a, 0x1c, 0x14, 0x02, 0x0e, 0x1d, 0x18, 0x08, 0x01, 0x10, 0x19, 0x1f, 0x07, 0x16 );
+ rom[i] = rom32&0xff;
+ rom[i+1] = (rom32>>8)&0xff;
+ rom[i+2] = (rom32>>16)&0xff;
+ rom[i+3] = (rom32>>24)&0xff;
+ }
+ memcpy( buf, rom, rom_size );
+ for( i = 0; i < rom_size / 4; i++ )
+ {
+ ofst = BITSWAP24( (i & 0x1fffff), 0x17, 0x16, 0x15, 0x04, 0x0b, 0x0e, 0x08, 0x0c, 0x10, 0x00, 0x0a, 0x13, 0x03, 0x06, 0x02, 0x07, 0x0d, 0x01, 0x11, 0x09, 0x14, 0x0f, 0x12, 0x05 );
+ ofst ^= 0x0c8923;
+ ofst += (i & 0xffe00000);
+ memcpy( &rom[ i * 4 ], &buf[ ofst * 4 ], 0x04 );
+ }
+ free( buf );
+}
+
+
+/* and a further swap on the s1 data */
+void svcpcb_s1data_decrypt(void)
+{
+ int i;
+ UINT8 *s1 = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+ size_t s1_size = memory_region_length( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+
+ for( i = 0; i < s1_size; i++ ) // Decrypt S
+ {
+ s1[ i ] = BITSWAP8( s1[ i ] ^ 0xd2, 4, 0, 7, 2, 5, 1, 6, 3 );
+ }
+}
+
+
+/* Razoola & Halrin */
+void kf2k3pcb_gfx_decrypt(void)
+{
+ static const UINT8 xor[ 4 ] = { 0x34, 0x21, 0xc4, 0xe9 };
+ int i;
+ int ofst;
+ int rom_size = memory_region_length( NEOGEO_REGION_SPRITES );
+ UINT8 *rom = memory_region( NEOGEO_REGION_SPRITES );
+ UINT8 *buf = malloc_or_die( rom_size );
+
+ for ( i = 0; i < rom_size; i++ )
+ {
+ rom[ i ] ^= xor[ (i % 4) ];
+ }
+ for ( i = 0; i < rom_size; i+=4 )
+ {
+ UINT32 *rom32 = (UINT32*)&rom[ i ];
+ *rom32 = BITSWAP32( *rom32, 0x09, 0x0d, 0x13, 0x00, 0x17, 0x0f, 0x03, 0x05, 0x04, 0x0c, 0x11, 0x1e, 0x12, 0x15, 0x0b, 0x06, 0x1b, 0x0a, 0x1a, 0x1c, 0x14, 0x02, 0x0e, 0x1d, 0x18, 0x08, 0x01, 0x10, 0x19, 0x1f, 0x07, 0x16 );
+ }
+ memcpy( buf, rom, rom_size );
+ for ( i = 0; i < rom_size; i+=4 )
+ {
+ ofst = BITSWAP24( (i & 0x7fffff), 0x17, 0x15, 0x0a, 0x14, 0x13, 0x16, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 );
+ ofst ^= 0x000000;
+ ofst += (i & 0xff800000);
+ memcpy( &rom[ ofst ], &buf[ i ], 0x04 );
+ }
+ free( buf );
+}
+
+
+/***************************************************************************
+
+NeoGeo 'P' ROM encryption
+
+***************************************************************************/
+
+/* Kof98 uses an early encryption, quite different from the others */
+void kof98_decrypt_68k(void)
+{
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT8 *dst = malloc_or_die(0x200000);
+ int i, j, k;
+ static const UINT32 sec[]={0x000000,0x100000,0x000004,0x100004,0x10000a,0x00000a,0x10000e,0x00000e};
+ static const UINT32 pos[]={0x000,0x004,0x00a,0x00e};
+
+ memcpy( dst, src, 0x200000);
+ for( i=0x800; i<0x100000; i+=0x200 )
+ {
+ for( j=0; j<0x100; j+=0x10 )
+ {
+ for( k=0; k<16; k+=2)
+ {
+ memcpy( &src[i+j+k], &dst[ i+j+sec[k/2]+0x100 ], 2 );
+ memcpy( &src[i+j+k+0x100], &dst[ i+j+sec[k/2] ], 2 );
+ }
+ if( i >= 0x080000 && i < 0x0c0000)
+ {
+ for( k=0; k<4; k++ )
+ {
+ memcpy( &src[i+j+pos[k]], &dst[i+j+pos[k]], 2 );
+ memcpy( &src[i+j+pos[k]+0x100], &dst[i+j+pos[k]+0x100], 2 );
+ }
+ }
+ else if( i >= 0x0c0000 )
+ {
+ for( k=0; k<4; k++ )
+ {
+ memcpy( &src[i+j+pos[k]], &dst[i+j+pos[k]+0x100], 2 );
+ memcpy( &src[i+j+pos[k]+0x100], &dst[i+j+pos[k]], 2 );
+ }
+ }
+ }
+ memcpy( &src[i+0x000000], &dst[i+0x000000], 2 );
+ memcpy( &src[i+0x000002], &dst[i+0x100000], 2 );
+ memcpy( &src[i+0x000100], &dst[i+0x000100], 2 );
+ memcpy( &src[i+0x000102], &dst[i+0x100100], 2 );
+ }
+ memcpy( &src[0x100000], &src[0x200000], 0x400000 );
+
+ free(dst);
+}
+
+
+/* kof99, garou, garouo, mslug3 and kof2000 have and SMA chip which contains program code and decrypts the 68k roms */
+void kof99_decrypt_68k(void)
+{
+ UINT16 *rom;
+ int i,j;
+
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ /* swap data lines on the whole ROMs */
+ for (i = 0;i < 0x800000/2;i++)
+ {
+ rom[i] = BITSWAP16(rom[i],13,7,3,0,9,4,5,6,1,12,8,14,10,11,2,15);
+ }
+
+ /* swap address lines for the banked part */
+ for (i = 0;i < 0x600000/2;i+=0x800/2)
+ {
+ UINT16 buffer[0x800/2];
+ memcpy(buffer,&rom[i],0x800);
+ for (j = 0;j < 0x800/2;j++)
+ {
+ rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,13,12,11,10,6,2,4,9,8,3,1,7,0,5)];
+ }
+ }
+
+ /* swap address lines & relocate fixed part */
+ rom = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ for (i = 0;i < 0x0c0000/2;i++)
+ {
+ rom[i] = rom[0x700000/2 + BITSWAP24(i,23,22,21,20,19,18,11,6,14,17,16,5,8,10,12,0,4,3,2,7,9,15,13,1)];
+ }
+}
+
+
+void garou_decrypt_68k(void)
+{
+ UINT16 *rom;
+ int i,j;
+
+ /* thanks to Razoola and Mr K for the info */
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ /* swap data lines on the whole ROMs */
+ for (i = 0;i < 0x800000/2;i++)
+ {
+ rom[i] = BITSWAP16(rom[i],13,12,14,10,8,2,3,1,5,9,11,4,15,0,6,7);
+ }
+
+ /* swap address lines & relocate fixed part */
+ rom = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ for (i = 0;i < 0x0c0000/2;i++)
+ {
+ rom[i] = rom[0x710000/2 + BITSWAP24(i,23,22,21,20,19,18,4,5,16,14,7,9,6,13,17,15,3,1,2,12,11,8,10,0)];
+ }
+
+ /* swap address lines for the banked part */
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ for (i = 0;i < 0x800000/2;i+=0x8000/2)
+ {
+ UINT16 buffer[0x8000/2];
+ memcpy(buffer,&rom[i],0x8000);
+ for (j = 0;j < 0x8000/2;j++)
+ {
+ rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,9,4,8,3,13,6,2,7,0,12,1,11,10,5)];
+ }
+ }
+}
+
+
+void garouo_decrypt_68k(void)
+{
+ UINT16 *rom;
+ int i,j;
+
+ /* thanks to Razoola and Mr K for the info */
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ /* swap data lines on the whole ROMs */
+ for (i = 0;i < 0x800000/2;i++)
+ {
+ rom[i] = BITSWAP16(rom[i],14,5,1,11,7,4,10,15,3,12,8,13,0,2,9,6);
+ }
+
+ /* swap address lines & relocate fixed part */
+ rom = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ for (i = 0;i < 0x0c0000/2;i++)
+ {
+ rom[i] = rom[0x7f8000/2 + BITSWAP24(i,23,22,21,20,19,18,5,16,11,2,6,7,17,3,12,8,14,4,0,9,1,10,15,13)];
+ }
+
+ /* swap address lines for the banked part */
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ for (i = 0;i < 0x800000/2;i+=0x8000/2)
+ {
+ UINT16 buffer[0x8000/2];
+ memcpy(buffer,&rom[i],0x8000);
+ for (j = 0;j < 0x8000/2;j++)
+ {
+ rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,12,8,1,7,11,3,13,10,6,9,5,4,0,2)];
+ }
+ }
+}
+
+
+void mslug3_decrypt_68k(void)
+{
+ UINT16 *rom;
+ int i,j;
+
+ /* thanks to Razoola and Mr K for the info */
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ /* swap data lines on the whole ROMs */
+ for (i = 0;i < 0x800000/2;i++)
+ {
+ rom[i] = BITSWAP16(rom[i],4,11,14,3,1,13,0,7,2,8,12,15,10,9,5,6);
+ }
+
+ /* swap address lines & relocate fixed part */
+ rom = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ for (i = 0;i < 0x0c0000/2;i++)
+ {
+ rom[i] = rom[0x5d0000/2 + BITSWAP24(i,23,22,21,20,19,18,15,2,1,13,3,0,9,6,16,4,11,5,7,12,17,14,10,8)];
+ }
+
+ /* swap address lines for the banked part */
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ for (i = 0;i < 0x800000/2;i+=0x10000/2)
+ {
+ UINT16 buffer[0x10000/2];
+ memcpy(buffer,&rom[i],0x10000);
+ for (j = 0;j < 0x10000/2;j++)
+ {
+ rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,2,11,0,14,6,4,13,8,9,3,10,7,5,12,1)];
+ }
+ }
+}
+
+
+void kof2000_decrypt_68k(void)
+{
+ UINT16 *rom;
+ int i,j;
+
+ /* thanks to Razoola and Mr K for the info */
+ rom = (UINT16 *)(memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE) + 0x100000);
+ /* swap data lines on the whole ROMs */
+ for (i = 0;i < 0x800000/2;i++)
+ {
+ rom[i] = BITSWAP16(rom[i],12,8,11,3,15,14,7,0,10,13,6,5,9,2,1,4);
+ }
+
+ /* swap address lines for the banked part */
+ for (i = 0;i < 0x63a000/2;i+=0x800/2)
+ {
+ UINT16 buffer[0x800/2];
+ memcpy(buffer,&rom[i],0x800);
+ for (j = 0;j < 0x800/2;j++)
+ {
+ rom[i+j] = buffer[BITSWAP24(j,23,22,21,20,19,18,17,16,15,14,13,12,11,10,4,1,3,8,6,2,7,0,9,5)];
+ }
+ }
+
+ /* swap address lines & relocate fixed part */
+ rom = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ for (i = 0;i < 0x0c0000/2;i++)
+ {
+ rom[i] = rom[0x73a000/2 + BITSWAP24(i,23,22,21,20,19,18,8,4,15,13,3,14,16,2,6,17,7,12,10,0,5,11,1,9)];
+ }
+}
+
+
+/* kof2002, matrim, samsho5, samsh5p have some simple block swapping */
+void kof2002_decrypt_68k(void)
+{
+ int i;
+ static const int sec[]={0x100000,0x280000,0x300000,0x180000,0x000000,0x380000,0x200000,0x080000};
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE)+0x100000;
+ UINT8 *dst = malloc_or_die(0x400000);
+ memcpy( dst, src, 0x400000 );
+ for( i=0; i<8; ++i )
+ {
+ memcpy( src+i*0x80000, dst+sec[i], 0x80000 );
+ }
+ free(dst);
+}
+
+
+void matrim_decrypt_68k(void)
+{
+ int i;
+ static const int sec[]={0x100000,0x280000,0x300000,0x180000,0x000000,0x380000,0x200000,0x080000};
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE)+0x100000;
+ UINT8 *dst = malloc_or_die(0x400000);
+ memcpy( dst, src, 0x400000);
+ for( i=0; i<8; ++i )
+ {
+ memcpy( src+i*0x80000, dst+sec[i], 0x80000 );
+ }
+ free(dst);
+}
+
+
+void samsho5_decrypt_68k(void)
+{
+ int i;
+ static const int sec[]={0x000000,0x080000,0x700000,0x680000,0x500000,0x180000,0x200000,0x480000,0x300000,0x780000,0x600000,0x280000,0x100000,0x580000,0x400000,0x380000};
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT8 *dst = malloc_or_die(0x800000);
+
+ memcpy( dst, src, 0x800000 );
+ for( i=0; i<16; ++i )
+ {
+ memcpy( src+i*0x80000, dst+sec[i], 0x80000 );
+ }
+ free(dst);
+}
+
+
+void samsh5p_decrypt_68k(void)
+{
+ int i;
+ static const int sec[]={0x000000,0x080000,0x500000,0x480000,0x600000,0x580000,0x700000,0x280000,0x100000,0x680000,0x400000,0x780000,0x200000,0x380000,0x300000,0x180000};
+ UINT8 *src = memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+ UINT8 *dst = malloc_or_die(0x800000);
+
+ memcpy( dst, src, 0x800000 );
+ for( i=0; i<16; ++i )
+ {
+ memcpy( src+i*0x80000, dst+sec[i], 0x80000 );
+ }
+ free(dst);
+}
+
+
+/* mslug5, svcchaos, kof2003 have updated P rom scramble */
+void mslug5_decrypt_68k(void)
+{
+ static const UINT8 xor1[ 0x20 ] = { 0xc2, 0x4b, 0x74, 0xfd, 0x0b, 0x34, 0xeb, 0xd7, 0x10, 0x6d, 0xf9, 0xce, 0x5d, 0xd5, 0x61, 0x29, 0xf5, 0xbe, 0x0d, 0x82, 0x72, 0x45, 0x0f, 0x24, 0xb3, 0x34, 0x1b, 0x99, 0xea, 0x09, 0xf3, 0x03 };
+ static const UINT8 xor2[ 0x20 ] = { 0x36, 0x09, 0xb0, 0x64, 0x95, 0x0f, 0x90, 0x42, 0x6e, 0x0f, 0x30, 0xf6, 0xe5, 0x08, 0x30, 0x64, 0x08, 0x04, 0x00, 0x2f, 0x72, 0x09, 0xa0, 0x13, 0xc9, 0x0b, 0xa0, 0x3e, 0xc2, 0x00, 0x40, 0x2b };
+ int i;
+ int ofst;
+ int rom_size = 0x800000;
+ UINT8 *rom = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *buf = malloc_or_die( rom_size );
+
+ for( i = 0; i < 0x100000; i++ )
+ {
+ rom[ i ] ^= xor1[ (BYTE_XOR_LE(i) % 0x20) ];
+ }
+ for( i = 0x100000; i < 0x800000; i++ )
+ {
+ rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ];
+ }
+
+ for( i = 0x100000; i < 0x0800000; i += 4 )
+ {
+ UINT16 rom16;
+ rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8;
+ rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0 );
+ rom[BYTE_XOR_LE(i+1)] = rom16&0xff;
+ rom[BYTE_XOR_LE(i+2)] = rom16>>8;
+ }
+ memcpy( buf, rom, rom_size );
+ for( i = 0; i < 0x0100000 / 0x10000; i++ )
+ {
+ ofst = (i & 0xf0) + BITSWAP8( (i & 0x0f), 7, 6, 5, 4, 1, 0, 3, 2 );
+ memcpy( &rom[ i * 0x10000 ], &buf[ ofst * 0x10000 ], 0x10000 );
+ }
+ for( i = 0x100000; i < 0x800000; i += 0x100 )
+ {
+ ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00700) + (BITSWAP8( ((i & 0x0ff000) >> 12), 5, 4, 7, 6, 1, 0, 3, 2 ) << 12);
+ memcpy( &rom[ i ], &buf[ ofst ], 0x100 );
+ }
+ memcpy( buf, rom, rom_size );
+ memcpy( &rom[ 0x100000 ], &buf[ 0x700000 ], 0x100000 );
+ memcpy( &rom[ 0x200000 ], &buf[ 0x100000 ], 0x600000 );
+ free( buf );
+}
+
+
+void svcchaos_px_decrypt(void)
+{
+ static const UINT8 xor1[ 0x20 ] = { 0x3b, 0x6a, 0xf7, 0xb7, 0xe8, 0xa9, 0x20, 0x99, 0x9f, 0x39, 0x34, 0x0c, 0xc3, 0x9a, 0xa5, 0xc8, 0xb8, 0x18, 0xce, 0x56, 0x94, 0x44, 0xe3, 0x7a, 0xf7, 0xdd, 0x42, 0xf0, 0x18, 0x60, 0x92, 0x9f };
+ static const UINT8 xor2[ 0x20 ] = { 0x69, 0x0b, 0x60, 0xd6, 0x4f, 0x01, 0x40, 0x1a, 0x9f, 0x0b, 0xf0, 0x75, 0x58, 0x0e, 0x60, 0xb4, 0x14, 0x04, 0x20, 0xe4, 0xb9, 0x0d, 0x10, 0x89, 0xeb, 0x07, 0x30, 0x90, 0x50, 0x0e, 0x20, 0x26 };
+ int i;
+ int ofst;
+ int rom_size = 0x800000;
+ UINT8 *rom = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *buf = malloc_or_die( rom_size );
+
+ for( i = 0; i < 0x100000; i++ )
+ {
+ rom[ i ] ^= xor1[ (BYTE_XOR_LE(i) % 0x20) ];
+ }
+ for( i = 0x100000; i < 0x800000; i++ )
+ {
+ rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ];
+ }
+
+ for( i = 0x100000; i < 0x0800000; i += 4 )
+ {
+ UINT16 rom16;
+ rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8;
+ rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 10, 11, 8, 9, 6, 7, 4, 5, 3, 2, 1, 0 );
+ rom[BYTE_XOR_LE(i+1)] = rom16&0xff;
+ rom[BYTE_XOR_LE(i+2)] = rom16>>8;
+ }
+ memcpy( buf, rom, rom_size );
+ for( i = 0; i < 0x0100000 / 0x10000; i++ )
+ {
+ ofst = (i & 0xf0) + BITSWAP8( (i & 0x0f), 7, 6, 5, 4, 2, 3, 0, 1 );
+ memcpy( &rom[ i * 0x10000 ], &buf[ ofst * 0x10000 ], 0x10000 );
+ }
+ for( i = 0x100000; i < 0x800000; i += 0x100 )
+ {
+ ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00a00) + (BITSWAP8( ((i & 0x0ff000) >> 12), 4, 5, 6, 7, 1, 0, 3, 2 ) << 12);
+ memcpy( &rom[ i ], &buf[ ofst ], 0x100 );
+ }
+ memcpy( buf, rom, rom_size );
+ memcpy( &rom[ 0x100000 ], &buf[ 0x700000 ], 0x100000 );
+ memcpy( &rom[ 0x200000 ], &buf[ 0x100000 ], 0x600000 );
+ free( buf );
+}
+
+
+void kf2k3pcb_decrypt_s1data(void)
+{
+ UINT8 *src;
+ UINT8 *dst;
+ int i;
+ int tx_size = memory_region_length( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+ int srom_size = memory_region_length( NEOGEO_REGION_SPRITES );
+
+ src = memory_region( NEOGEO_REGION_SPRITES ) + srom_size - 0x1000000 - 0x80000; // Decrypt S
+ dst = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+
+ for( i = 0; i < tx_size / 2; i++ )
+ {
+ dst[ i ] = src[ (i & ~0x1f) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4) ];
+ }
+
+ src = memory_region( NEOGEO_REGION_SPRITES ) + srom_size - 0x80000;
+ dst = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE ) + 0x80000;
+
+ for( i = 0; i < tx_size / 2; i++ )
+ {
+ dst[ i ] = src[ (i & ~0x1f) + ((i & 7) << 2) + ((~i & 8) >> 2) + ((i & 0x10) >> 4) ];
+ }
+
+ dst = memory_region( NEOGEO_REGION_FIXED_LAYER_CARTRIDGE );
+
+ for( i = 0; i < tx_size; i++ )
+ {
+ dst[ i ] = BITSWAP8( dst[ i ] ^ 0xd2, 4, 0, 7, 2, 5, 1, 6, 3 );
+ }
+}
+
+
+void kf2k3pcb_decrypt_68k(void)
+{
+ static const UINT8 xor2[ 0x20 ] = { 0xb4, 0x0f, 0x40, 0x6c, 0x38, 0x07, 0xd0, 0x3f, 0x53, 0x08, 0x80, 0xaa, 0xbe, 0x07, 0xc0, 0xfa, 0xd0, 0x08, 0x10, 0xd2, 0xf1, 0x03, 0x70, 0x7e, 0x87, 0x0b, 0x40, 0xf6, 0x2a, 0x0a, 0xe0, 0xf9 };
+ int i;
+ int ofst;
+ int rom_size = 0x900000;
+ UINT8 *rom = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *buf = malloc_or_die( rom_size );
+
+ for (i = 0; i < 0x100000; i++)
+ {
+ rom[ 0x800000 + i ] ^= rom[ 0x100002 | BYTE_XOR_LE(i) ];
+ }
+ for( i = 0x100000; i < 0x800000; i++ )
+ {
+ rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ];
+ }
+ for( i = 0x100000; i < 0x800000; i += 4 )
+ {
+ UINT16 rom16;
+ rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8;
+ rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 4, 5, 6, 7, 8, 9, 10, 11, 3, 2, 1, 0 );
+ rom[BYTE_XOR_LE(i+1)] = rom16&0xff;
+ rom[BYTE_XOR_LE(i+2)] = rom16>>8;
+ }
+ for( i = 0; i < 0x0100000 / 0x10000; i++ )
+ {
+ ofst = (i & 0xf0) + BITSWAP8( (i & 0x0f), 7, 6, 5, 4, 1, 0, 3, 2 );
+ memcpy( &buf[ i * 0x10000 ], &rom[ ofst * 0x10000 ], 0x10000 );
+ }
+ for( i = 0x100000; i < 0x900000; i += 0x100 )
+ {
+ ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00300) + (BITSWAP8( ((i & 0x0ff000) >> 12), 4, 5, 6, 7, 1, 0, 3, 2 ) << 12);
+ memcpy( &buf[ i ], &rom[ ofst ], 0x100 );
+ }
+ memcpy (&rom[0x000000], &buf[0x000000], 0x100000);
+ memcpy (&rom[0x100000], &buf[0x800000], 0x100000);
+ memcpy (&rom[0x200000], &buf[0x100000], 0x700000);
+ free( buf );
+}
+
+
+void kof2003_decrypt_68k(void)
+{
+ static const UINT8 xor1[0x20] = { 0x3b, 0x6a, 0xf7, 0xb7, 0xe8, 0xa9, 0x20, 0x99, 0x9f, 0x39, 0x34, 0x0c, 0xc3, 0x9a, 0xa5, 0xc8, 0xb8, 0x18, 0xce, 0x56, 0x94, 0x44, 0xe3, 0x7a, 0xf7, 0xdd, 0x42, 0xf0, 0x18, 0x60, 0x92, 0x9f };
+ static const UINT8 xor2[0x20] = { 0x2f, 0x02, 0x60, 0xbb, 0x77, 0x01, 0x30, 0x08, 0xd8, 0x01, 0xa0, 0xdf, 0x37, 0x0a, 0xf0, 0x65, 0x28, 0x03, 0xd0, 0x23, 0xd3, 0x03, 0x70, 0x42, 0xbb, 0x06, 0xf0, 0x28, 0xba, 0x0f, 0xf0, 0x7a };
+ int i;
+ int ofst;
+ int rom_size = 0x900000;
+ UINT8 *rom = memory_region( NEOGEO_REGION_MAIN_CPU_CARTRIDGE );
+ UINT8 *buf = malloc_or_die( rom_size );
+
+ for (i = 0; i < 0x100000; i++)
+ {
+ rom[ 0x800000 + i ] ^= rom[ 0x100002 | BYTE_XOR_LE(i) ];
+ }
+ for( i = 0; i < 0x100000; i++)
+ {
+ rom[ i ] ^= xor1[ (BYTE_XOR_LE(i) % 0x20) ];
+ }
+ for( i = 0x100000; i < 0x800000; i++)
+ {
+ rom[ i ] ^= xor2[ (BYTE_XOR_LE(i) % 0x20) ];
+ }
+ for( i = 0x100000; i < 0x800000; i += 4)
+ {
+ UINT16 rom16;
+ rom16 = rom[BYTE_XOR_LE(i+1)] | rom[BYTE_XOR_LE(i+2)]<<8;
+ rom16 = BITSWAP16( rom16, 15, 14, 13, 12, 5, 4, 7, 6, 9, 8, 11, 10, 3, 2, 1, 0 );
+ rom[BYTE_XOR_LE(i+1)] = rom16&0xff;
+ rom[BYTE_XOR_LE(i+2)] = rom16>>8;
+ }
+ for( i = 0; i < 0x0100000 / 0x10000; i++ )
+ {
+ ofst = (i & 0xf0) + BITSWAP8((i & 0x0f), 7, 6, 5, 4, 0, 1, 2, 3);
+ memcpy( &buf[ i * 0x10000 ], &rom[ ofst * 0x10000 ], 0x10000 );
+ }
+ for( i = 0x100000; i < 0x900000; i += 0x100)
+ {
+ ofst = (i & 0xf000ff) + ((i & 0x000f00) ^ 0x00800) + (BITSWAP8( ((i & 0x0ff000) >> 12), 4, 5, 6, 7, 1, 0, 3, 2 ) << 12);
+ memcpy( &buf[ i ], &rom[ ofst ], 0x100 );
+ }
+ memcpy (&rom[0x000000], &buf[0x000000], 0x100000);
+ memcpy (&rom[0x100000], &buf[0x800000], 0x100000);
+ memcpy (&rom[0x200000], &buf[0x100000], 0x700000);
+ free( buf );
+}
+
+
+void kof2003biosdecode(void)
+{
+ static const UINT8 address[0x80]={
+ 0xb9,0xb8,0x36,0x37,0x3d,0x3c,0xb2,0xb3,
+ 0xb9,0xb8,0x36,0x37,0x3d,0x3c,0xb2,0xb3,
+ 0x65,0xea,0x6f,0xe0,0xe1,0x6e,0xeb,0x64,
+ 0x65,0xea,0x6f,0xe0,0xe1,0x6e,0xeb,0x64,
+ 0x45,0xca,0x47,0xc8,0xc9,0x46,0xcb,0x44,
+ 0x45,0xca,0x47,0xc8,0xc9,0x46,0xcb,0x44,
+ 0x9a,0x15,0x98,0x17,0x1e,0x91,0x1c,0x93,
+ 0x9a,0x15,0x98,0x17,0x1e,0x91,0x1c,0x93,
+ 0x7e,0xf1,0x7c,0xf3,0xf0,0x7f,0xf2,0x7d,
+ 0x7e,0xf1,0x7c,0xf3,0xf0,0x7f,0xf2,0x7d,
+ 0x27,0xa8,0x25,0xaa,0xa3,0x2c,0xa1,0x2e,
+ 0x27,0xa8,0x25,0xaa,0xa3,0x2c,0xa1,0x2e,
+ 0x04,0x8b,0x06,0x89,0x80,0x0f,0x82,0x0d,
+ 0x04,0x8b,0x06,0x89,0x80,0x0f,0x82,0x0d,
+ 0xd3,0xd2,0x5c,0x5d,0x57,0x56,0xd8,0xd9,
+ 0xd3,0xd2,0x5c,0x5d,0x57,0x56,0xd8,0xd9,
+ };
+ UINT16*src= (UINT16*)memory_region( NEOGEO_REGION_MAIN_CPU_BIOS );
+ UINT16*buf= malloc_or_die(0x80000);
+ int a,addr;
+
+ for (a=0;a<0x80000/2;a++)
+ {
+ //data xor
+ #ifdef LSB_FIRST
+ if (src[a] & 0x0004) src[a] ^= 0x0001;
+ if (src[a] & 0x0010) src[a] ^= 0x0002;
+ if (src[a] & 0x0020) src[a] ^= 0x0008;
+ #else
+ if (src[a] & 0x0400) src[a] ^= 0x0100;
+ if (src[a] & 0x1000) src[a] ^= 0x0200;
+ if (src[a] & 0x2000) src[a] ^= 0x0800;
+ #endif
+ //address xor
+ addr = a & ~0xff;
+ addr |= address[BYTE_XOR_LE(a & 0x7f)];
+ if ( a & 0x00008) addr ^= 0x0008;
+ if ( a & 0x00080) addr ^= 0x0080;
+ if ( a & 0x00200) addr ^= 0x0100;
+ if (~a & 0x02000) addr ^= 0x0400;
+ if (~a & 0x10000) addr ^= 0x1000;
+ if ( a & 0x02000) addr ^= 0x8000;
+ buf[addr]=src[a];
+ }
+ memcpy(src,buf,0x80000);
+ free(buf);
+}
+
+
+/***************************************************************************
+
+NeoGeo 'V' (PCM) ROM encryption
+ NEOPCM2 chip
+
+***************************************************************************/
+
+/* Neo-Pcm2 Drivers for Encrypted V Roms */
+void neo_pcm2_snk_1999(int value)
+{ /* thanks to Elsemi for the NEO-PCM2 info */
+ UINT16 *rom = (UINT16 *)memory_region(NEOGEO_REGION_AUDIO_DATA_1);
+ int size = memory_region_length(NEOGEO_REGION_AUDIO_DATA_1);
+ int i, j;
+
+ if( rom != NULL )
+ { /* swap address lines on the whole ROMs */
+ UINT16 *buffer = malloc_or_die((value / 2) * sizeof(UINT16));
+
+ for( i = 0; i < size / 2; i += ( value / 2 ) )
+ {
+ memcpy( buffer, &rom[ i ], value );
+ for( j = 0; j < (value / 2); j++ )
+ {
+ rom[ i + j ] = buffer[ j ^ (value/4) ];
+ }
+ }
+ free(buffer);
+ }
+}
+
+
+/* the later PCM2 games have additional scrambling */
+void neo_pcm2_swap(int value)
+{
+ static const UINT32 addrs[7][2]={
+ {0x000000,0xa5000},
+ {0xffce20,0x01000},
+ {0xfe2cf6,0x4e001},
+ {0xffac28,0xc2000},
+ {0xfeb2c0,0x0a000},
+ {0xff14ea,0xa7001},
+ {0xffb440,0x02000}};
+ static const UINT8 xordata[7][8]={
+ {0xf9,0xe0,0x5d,0xf3,0xea,0x92,0xbe,0xef},
+ {0xc4,0x83,0xa8,0x5f,0x21,0x27,0x64,0xaf},
+ {0xc3,0xfd,0x81,0xac,0x6d,0xe7,0xbf,0x9e},
+ {0xc3,0xfd,0x81,0xac,0x6d,0xe7,0xbf,0x9e},
+ {0xcb,0x29,0x7d,0x43,0xd2,0x3a,0xc2,0xb4},
+ {0x4b,0xa4,0x63,0x46,0xf0,0x91,0xea,0x62},
+ {0x4b,0xa4,0x63,0x46,0xf0,0x91,0xea,0x62}};
+ UINT8 *src = memory_region(NEOGEO_REGION_AUDIO_DATA_1);
+ UINT8 *buf = malloc_or_die(0x1000000);
+ int i, j, d;
+
+ memcpy(buf,src,0x1000000);
+ for (i=0;i<0x1000000;i++)
+ {
+ j=BITSWAP24(i,23,22,21,20,19,18,17,0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,16);
+ j=j^addrs[value][1];
+ d=((i+addrs[value][0])&0xffffff);
+ src[j]=buf[d]^xordata[value][j&0x7];
+ }
+ free(buf);
+}
diff --git a/src/mame/machine/neoprot.c b/src/mame/machine/neoprot.c
new file mode 100644
index 00000000000..5a350202f38
--- /dev/null
+++ b/src/mame/machine/neoprot.c
@@ -0,0 +1,525 @@
+/***************************************************************************
+
+ Neo-Geo hardware protection devices
+
+ unknown devices
+ ssideki, fatfury2, fatfury3, kof98, mslugx
+
+ SMA chip
+ kof99, garou, garouo, mslug3, kof2002
+
+ custom banking, random number generator
+ encryption (see machine/neocrypt.c)
+ internal rom data
+
+ PVC chip
+ mslug5, kof2003, svcchaos
+
+***************************************************************************/
+
+#include "driver.h"
+#include "neogeo.h"
+
+
+
+static UINT32 fatfury2_prot_data;
+static UINT16 neogeo_rng;
+
+static UINT16 *pvc_cartridge_ram;
+
+
+/************************ Fatal Fury 2 *************************/
+
+static READ16_HANDLER( fatfury2_protection_16_r )
+{
+ UINT16 res = fatfury2_prot_data >> 24;
+
+ switch (offset)
+ {
+ case 0x55550/2:
+ case 0xffff0/2:
+ case 0x00000/2:
+ case 0xff000/2:
+ case 0x36000/2:
+ case 0x36008/2:
+ return res;
+
+ case 0x36004/2:
+ case 0x3600c/2:
+ return ((res & 0xf0) >> 4) | ((res & 0x0f) << 4);
+
+ default:
+logerror("unknown protection read at pc %06x, offset %08x\n",activecpu_get_pc(),offset<<1);
+ return 0;
+ }
+}
+
+
+static WRITE16_HANDLER( fatfury2_protection_16_w )
+{
+ switch (offset)
+ {
+ case 0x11112/2: /* data == 0x1111; expects 0xff000000 back */
+ fatfury2_prot_data = 0xff000000;
+ break;
+
+ case 0x33332/2: /* data == 0x3333; expects 0x0000ffff back */
+ fatfury2_prot_data = 0x0000ffff;
+ break;
+
+ case 0x44442/2: /* data == 0x4444; expects 0x00ff0000 back */
+ fatfury2_prot_data = 0x00ff0000;
+ break;
+
+ case 0x55552/2: /* data == 0x5555; read back from 55550, ffff0, 00000, ff000 */
+ fatfury2_prot_data = 0xff00ff00;
+ break;
+
+ case 0x56782/2: /* data == 0x1234; read back from 36000 *or* 36004 */
+ fatfury2_prot_data = 0xf05a3601;
+ break;
+
+ case 0x42812/2: /* data == 0x1824; read back from 36008 *or* 3600c */
+ fatfury2_prot_data = 0x81422418;
+ break;
+
+ case 0x55550/2:
+ case 0xffff0/2:
+ case 0xff000/2:
+ case 0x36000/2:
+ case 0x36004/2:
+ case 0x36008/2:
+ case 0x3600c/2:
+ fatfury2_prot_data <<= 8;
+ break;
+
+ default:
+ logerror("unknown protection write at pc %06x, offset %08x, data %02x\n",activecpu_get_pc(),offset,data);
+ break;
+ }
+}
+
+
+void fatfury2_install_protection(void)
+{
+ /* the protection involves reading and writing addresses in the */
+ /* 0x2xxxxx range. There are several checks all around the code. */
+ memory_install_readwrite16_handler(0, ADDRESS_SPACE_PROGRAM, 0x200000, 0x2fffff, 0, 0, fatfury2_protection_16_r, fatfury2_protection_16_w);
+
+ state_save_register_global(fatfury2_prot_data);
+}
+
+
+
+/************************ King of Fighters 98*******************
+ The encrypted set has a rom overlay feature, checked at
+ various points in the game
+***************************************************************/
+
+static WRITE16_HANDLER ( kof98_prot_w )
+{
+ /* info from razoola */
+ UINT16* mem16 = (UINT16*)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+
+ switch (data)
+ {
+ case 0x0090:
+ logerror ("%06x kof98 - protection 0x0090 old %04x %04x\n",activecpu_get_pc(), mem16[0x100/2], mem16[0x102/2]);
+ mem16[0x100/2] = 0x00c2; mem16[0x102/2] = 0x00fd;
+ break;
+
+ case 0x00f0:
+ logerror ("%06x kof98 - protection 0x00f0 old %04x %04x\n",activecpu_get_pc(), mem16[0x100/2], mem16[0x102/2]);
+ mem16[0x100/2] = 0x4e45; mem16[0x102/2] = 0x4f2d;
+ break;
+
+ default: // 00aa is written, but not needed?
+ logerror ("%06x kof98 - unknown protection write %04x\n",activecpu_get_pc(), data);
+ break;
+ }
+}
+
+
+void install_kof98_protection(void)
+{
+ /* when 0x20aaaa contains 0x0090 (word) then 0x100 (normally the neogeo header) should return 0x00c200fd
+ worked out using real hw */
+
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x20aaaa, 0x20aaab, 0, 0, kof98_prot_w);
+}
+
+
+
+/************************ Metal Slug X *************************
+ todo: emulate, not patch!
+***************************************************************/
+
+void mslugx_install_protection(void)
+{
+ int i;
+ UINT16 *mem16 = (UINT16 *)memory_region(NEOGEO_REGION_MAIN_CPU_CARTRIDGE);
+
+ for (i = 0;i < (0x100000/2) - 4;i++)
+ {
+ if (mem16[i+0] == 0x0243 &&
+ mem16[i+1] == 0x0001 && /* andi.w #$1, D3 */
+ mem16[i+2] == 0x6600) /* bne xxxx */
+ {
+ mem16[i+2] = 0x4e71;
+ mem16[i+3] = 0x4e71;
+ }
+ }
+ mem16[0x3bdc/2] = 0x4e71;
+ mem16[0x3bde/2] = 0x4e71;
+ mem16[0x3be0/2] = 0x4e71;
+ mem16[0x3c0c/2] = 0x4e71;
+ mem16[0x3c0e/2] = 0x4e71;
+ mem16[0x3c10/2] = 0x4e71;
+
+ mem16[0x3c36/2] = 0x4e71;
+ mem16[0x3c38/2] = 0x4e71;
+}
+
+
+
+/************************ SMA Protection************************
+ thanks to Razoola
+***************************************************************/
+
+static WRITE16_HANDLER( kof99_bankswitch_w )
+{
+ int bankaddress;
+ static int bankoffset[64] =
+ {
+ 0x000000, 0x100000, 0x200000, 0x300000,
+ 0x3cc000, 0x4cc000, 0x3f2000, 0x4f2000,
+ 0x407800, 0x507800, 0x40d000, 0x50d000,
+ 0x417800, 0x517800, 0x420800, 0x520800,
+ 0x424800, 0x524800, 0x429000, 0x529000,
+ 0x42e800, 0x52e800, 0x431800, 0x531800,
+ 0x54d000, 0x551000, 0x567000, 0x592800,
+ 0x588800, 0x581800, 0x599800, 0x594800,
+ 0x598000, /* rest not used? */
+ };
+
+ /* unscramble bank number */
+ data =
+ (((data>>14)&1)<<0)+
+ (((data>> 6)&1)<<1)+
+ (((data>> 8)&1)<<2)+
+ (((data>>10)&1)<<3)+
+ (((data>>12)&1)<<4)+
+ (((data>> 5)&1)<<5);
+
+ bankaddress = 0x100000 + bankoffset[data];
+
+ neogeo_set_main_cpu_bank_address(bankaddress);
+}
+
+
+static WRITE16_HANDLER( garou_bankswitch_w )
+{
+ /* thanks to Razoola and Mr K for the info */
+ int bankaddress;
+ static int bankoffset[64] =
+ {
+ 0x000000, 0x100000, 0x200000, 0x300000, // 00
+ 0x280000, 0x380000, 0x2d0000, 0x3d0000, // 04
+ 0x2f0000, 0x3f0000, 0x400000, 0x500000, // 08
+ 0x420000, 0x520000, 0x440000, 0x540000, // 12
+ 0x498000, 0x598000, 0x4a0000, 0x5a0000, // 16
+ 0x4a8000, 0x5a8000, 0x4b0000, 0x5b0000, // 20
+ 0x4b8000, 0x5b8000, 0x4c0000, 0x5c0000, // 24
+ 0x4c8000, 0x5c8000, 0x4d0000, 0x5d0000, // 28
+ 0x458000, 0x558000, 0x460000, 0x560000, // 32
+ 0x468000, 0x568000, 0x470000, 0x570000, // 36
+ 0x478000, 0x578000, 0x480000, 0x580000, // 40
+ 0x488000, 0x588000, 0x490000, 0x590000, // 44
+ 0x5d0000, 0x5d8000, 0x5e0000, 0x5e8000, // 48
+ 0x5f0000, 0x5f8000, 0x600000, /* rest not used? */
+ };
+
+ /* unscramble bank number */
+ data =
+ (((data>> 5)&1)<<0)+
+ (((data>> 9)&1)<<1)+
+ (((data>> 7)&1)<<2)+
+ (((data>> 6)&1)<<3)+
+ (((data>>14)&1)<<4)+
+ (((data>>12)&1)<<5);
+
+ bankaddress = 0x100000 + bankoffset[data];
+
+ neogeo_set_main_cpu_bank_address(bankaddress);
+}
+
+
+static WRITE16_HANDLER( garouo_bankswitch_w )
+{
+ /* thanks to Razoola and Mr K for the info */
+ int bankaddress;
+ static int bankoffset[64] =
+ {
+ 0x000000, 0x100000, 0x200000, 0x300000, // 00
+ 0x280000, 0x380000, 0x2d0000, 0x3d0000, // 04
+ 0x2c8000, 0x3c8000, 0x400000, 0x500000, // 08
+ 0x420000, 0x520000, 0x440000, 0x540000, // 12
+ 0x598000, 0x698000, 0x5a0000, 0x6a0000, // 16
+ 0x5a8000, 0x6a8000, 0x5b0000, 0x6b0000, // 20
+ 0x5b8000, 0x6b8000, 0x5c0000, 0x6c0000, // 24
+ 0x5c8000, 0x6c8000, 0x5d0000, 0x6d0000, // 28
+ 0x458000, 0x558000, 0x460000, 0x560000, // 32
+ 0x468000, 0x568000, 0x470000, 0x570000, // 36
+ 0x478000, 0x578000, 0x480000, 0x580000, // 40
+ 0x488000, 0x588000, 0x490000, 0x590000, // 44
+ 0x5d8000, 0x6d8000, 0x5e0000, 0x6e0000, // 48
+ 0x5e8000, 0x6e8000, 0x6e8000, 0x000000, // 52
+ 0x000000, 0x000000, 0x000000, 0x000000, // 56
+ 0x000000, 0x000000, 0x000000, 0x000000, // 60
+ };
+
+ /* unscramble bank number */
+ data =
+ (((data>> 4)&1)<<0)+
+ (((data>> 8)&1)<<1)+
+ (((data>>14)&1)<<2)+
+ (((data>> 2)&1)<<3)+
+ (((data>>11)&1)<<4)+
+ (((data>>13)&1)<<5);
+
+ bankaddress = 0x100000 + bankoffset[data];
+
+ neogeo_set_main_cpu_bank_address(bankaddress);
+}
+
+
+static WRITE16_HANDLER( mslug3_bankswitch_w )
+{
+ /* thanks to Razoola and Mr K for the info */
+ int bankaddress;
+ static int bankoffset[64] =
+ {
+ 0x000000, 0x020000, 0x040000, 0x060000, // 00
+ 0x070000, 0x090000, 0x0b0000, 0x0d0000, // 04
+ 0x0e0000, 0x0f0000, 0x120000, 0x130000, // 08
+ 0x140000, 0x150000, 0x180000, 0x190000, // 12
+ 0x1a0000, 0x1b0000, 0x1e0000, 0x1f0000, // 16
+ 0x200000, 0x210000, 0x240000, 0x250000, // 20
+ 0x260000, 0x270000, 0x2a0000, 0x2b0000, // 24
+ 0x2c0000, 0x2d0000, 0x300000, 0x310000, // 28
+ 0x320000, 0x330000, 0x360000, 0x370000, // 32
+ 0x380000, 0x390000, 0x3c0000, 0x3d0000, // 36
+ 0x400000, 0x410000, 0x440000, 0x450000, // 40
+ 0x460000, 0x470000, 0x4a0000, 0x4b0000, // 44
+ 0x4c0000, /* rest not used? */
+ };
+
+ /* unscramble bank number */
+ data =
+ (((data>>14)&1)<<0)+
+ (((data>>12)&1)<<1)+
+ (((data>>15)&1)<<2)+
+ (((data>> 6)&1)<<3)+
+ (((data>> 3)&1)<<4)+
+ (((data>> 9)&1)<<5);
+
+ bankaddress = 0x100000 + bankoffset[data];
+
+ neogeo_set_main_cpu_bank_address(bankaddress);
+}
+
+
+static WRITE16_HANDLER( kof2000_bankswitch_w )
+{
+ /* thanks to Razoola and Mr K for the info */
+ int bankaddress;
+ static int bankoffset[64] =
+ {
+ 0x000000, 0x100000, 0x200000, 0x300000, // 00
+ 0x3f7800, 0x4f7800, 0x3ff800, 0x4ff800, // 04
+ 0x407800, 0x507800, 0x40f800, 0x50f800, // 08
+ 0x416800, 0x516800, 0x41d800, 0x51d800, // 12
+ 0x424000, 0x524000, 0x523800, 0x623800, // 16
+ 0x526000, 0x626000, 0x528000, 0x628000, // 20
+ 0x52a000, 0x62a000, 0x52b800, 0x62b800, // 24
+ 0x52d000, 0x62d000, 0x52e800, 0x62e800, // 28
+ 0x618000, 0x619000, 0x61a000, 0x61a800, // 32
+ };
+
+ /* unscramble bank number */
+ data =
+ (((data>>15)&1)<<0)+
+ (((data>>14)&1)<<1)+
+ (((data>> 7)&1)<<2)+
+ (((data>> 3)&1)<<3)+
+ (((data>>10)&1)<<4)+
+ (((data>> 5)&1)<<5);
+
+ bankaddress = 0x100000 + bankoffset[data];
+
+ neogeo_set_main_cpu_bank_address(bankaddress);
+}
+
+
+static READ16_HANDLER( prot_9a37_r )
+{
+ return 0x9a37;
+}
+
+
+/* information about the sma random number generator provided by razoola */
+/* this RNG is correct for KOF99, other games might be different */
+
+static READ16_HANDLER( sma_random_r )
+{
+ UINT16 old = neogeo_rng;
+
+ UINT16 newbit = ((neogeo_rng >> 2) ^
+ (neogeo_rng >> 3) ^
+ (neogeo_rng >> 5) ^
+ (neogeo_rng >> 6) ^
+ (neogeo_rng >> 7) ^
+ (neogeo_rng >>11) ^
+ (neogeo_rng >>12) ^
+ (neogeo_rng >>15)) & 1;
+
+ neogeo_rng = (neogeo_rng << 1) | newbit;
+
+ return old;
+}
+
+
+void neogeo_reset_rng(void)
+{
+ neogeo_rng = 0x2345;
+}
+
+
+static void sma_install_random_read_handler(int addr1, int addr2)
+{
+ state_save_register_global(neogeo_rng);
+
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, addr1, addr1 + 1, 0, 0, sma_random_r);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, addr2, addr2 + 2, 0, 0, sma_random_r);
+}
+
+
+void kof99_install_protection(void)
+{
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2ffff0, 0x2ffff1, 0, 0, kof99_bankswitch_w);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fe446, 0x2fe447, 0, 0, prot_9a37_r);
+
+ sma_install_random_read_handler(0x2ffff8, 0x2ffffa);
+}
+
+
+void garou_install_protection(void)
+{
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fffc0, 0x2fffc1, 0, 0, garou_bankswitch_w);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fe446, 0x2fe447, 0, 0, prot_9a37_r);
+
+ sma_install_random_read_handler(0x2fffcc, 0x2ffff0);
+}
+
+
+void garouo_install_protection(void)
+{
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fffc0, 0x2fffc1, 0, 0, garouo_bankswitch_w);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fe446, 0x2fe447, 0, 0, prot_9a37_r);
+
+ sma_install_random_read_handler(0x2fffcc, 0x2ffff0);
+}
+
+
+void mslug3_install_protection(void)
+{
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fffe4, 0x2fffe5, 0, 0, mslug3_bankswitch_w);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fe446, 0x2fe447, 0, 0, prot_9a37_r);
+
+// sma_install_random_read_handler(0x2ffff8, 0x2ffffa);
+}
+
+
+void kof2000_install_protection(void)
+{
+ memory_install_write16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fffec, 0x2fffed, 0, 0, kof2000_bankswitch_w);
+ memory_install_read16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fe446, 0x2fe447, 0, 0, prot_9a37_r);
+
+ sma_install_random_read_handler(0x2fffd8, 0x2fffda);
+}
+
+
+
+/************************ PVC Protection ***********************
+ mslug5, svcchaos, kof2003
+***************************************************************/
+
+static void pvc_w8(offs_t offset, UINT8 data)
+{
+ *(((UINT8*)pvc_cartridge_ram)+BYTE_XOR_LE(offset))=data;
+}
+
+
+static UINT8 pvc_r8(offs_t offset)
+{
+ return *(((UINT8*)pvc_cartridge_ram)+BYTE_XOR_LE(offset));
+}
+
+
+static void pvc_prot1( void )
+{
+ UINT8 b1, b2;
+ b1 = pvc_r8(0x1fe1);
+ b2 = pvc_r8(0x1fe0);
+ pvc_w8(0x1fe2,(((b2>>0)&0xf)<<1)|((b1>>4)&1));
+ pvc_w8(0x1fe3,(((b2>>4)&0xf)<<1)|((b1>>5)&1));
+ pvc_w8(0x1fe4,(((b1>>0)&0xf)<<1)|((b1>>6)&1));
+ pvc_w8(0x1fe5, (b1>>7));
+}
+
+
+static void pvc_prot2( void ) // on writes to e8/e9/ea/eb
+{
+ UINT8 b1, b2, b3, b4;
+ b1 = pvc_r8(0x1fe9);
+ b2 = pvc_r8(0x1fe8);
+ b3 = pvc_r8(0x1feb);
+ b4 = pvc_r8(0x1fea);
+ pvc_w8(0x1fec,(b2>>1)|((b1>>1)<<4));
+ pvc_w8(0x1fed,(b4>>1)|((b2&1)<<4)|((b1&1)<<5)|((b4&1)<<6)|((b3&1)<<7));
+}
+
+
+static void pvc_write_bankswitch( void )
+{
+ UINT32 bankaddress;
+ bankaddress = ((pvc_cartridge_ram[0xff8]>>8)|(pvc_cartridge_ram[0xff9]<<8));
+ *(((UINT8 *)pvc_cartridge_ram) + BYTE_XOR_LE(0x1ff0)) = 0xa0;
+ *(((UINT8 *)pvc_cartridge_ram) + BYTE_XOR_LE(0x1ff1)) &= 0xfe;
+ *(((UINT8 *)pvc_cartridge_ram) + BYTE_XOR_LE(0x1ff3)) &= 0x7f;
+ neogeo_set_main_cpu_bank_address(bankaddress+0x100000);
+}
+
+
+static READ16_HANDLER( pvc_prot_r )
+{
+ return pvc_cartridge_ram[ offset ];
+}
+
+
+static WRITE16_HANDLER( pvc_prot_w )
+{
+ COMBINE_DATA( &pvc_cartridge_ram[ offset ] );
+ if (offset == 0xff0)pvc_prot1();
+ else if(offset >= 0xff4 && offset <= 0xff5)pvc_prot2();
+ else if(offset >= 0xff8)pvc_write_bankswitch();
+}
+
+
+void install_pvc_protection( void )
+{
+ pvc_cartridge_ram = auto_malloc(0x2000);
+ state_save_register_global_pointer(pvc_cartridge_ram, 0x2000 / 2);
+
+ memory_install_readwrite16_handler(0, ADDRESS_SPACE_PROGRAM, 0x2fe000, 0x2fffff, 0, 0, pvc_prot_r, pvc_prot_w);
+}
diff --git a/src/mame/machine/nitedrvr.c b/src/mame/machine/nitedrvr.c
new file mode 100644
index 00000000000..e83aba85afa
--- /dev/null
+++ b/src/mame/machine/nitedrvr.c
@@ -0,0 +1,283 @@
+/***************************************************************************
+
+ Atari Night Driver hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "nitedrvr.h"
+#include "sound/discrete.h"
+
+static UINT8 nitedrvr_gear = 1;
+static UINT8 nitedrvr_track;
+static INT32 nitedrvr_steering_buf;
+static INT32 nitedrvr_steering_val;
+static UINT8 nitedrvr_crash_en;
+static UINT8 nitedrvr_crash_data = 0x0f;
+static UINT8 nitedrvr_crash_data_en; // IC D8
+static UINT8 ac_line;
+static INT32 last_steering_val;
+
+/***************************************************************************
+Steering
+
+When D7 is high, the steering wheel has moved.
+If D6 is low, it moved left. If D6 is high, it moved right.
+Be sure to keep returning a direction until steering_reset is called,
+because D6 and D7 are apparently checked at different times, and a
+change in-between can affect the direction you move.
+***************************************************************************/
+static int nitedrvr_steering(void)
+{
+ int this_val;
+ int delta;
+
+ this_val = readinputport(5);
+
+ delta=this_val-last_steering_val;
+ last_steering_val=this_val;
+ if (delta>128) delta-=256;
+ else if (delta<-128) delta+=256;
+ /* Divide by four to make our steering less sensitive */
+ nitedrvr_steering_buf+=(delta/4);
+
+ if (nitedrvr_steering_buf>0)
+ {
+ nitedrvr_steering_buf--;
+ nitedrvr_steering_val=0xC0;
+ }
+ else if (nitedrvr_steering_buf<0)
+ {
+ nitedrvr_steering_buf++;
+ nitedrvr_steering_val=0x80;
+ }
+ else
+ {
+ nitedrvr_steering_val=0x00;
+ }
+
+ return nitedrvr_steering_val;
+}
+
+/***************************************************************************
+nitedrvr_steering_reset
+***************************************************************************/
+READ8_HANDLER( nitedrvr_steering_reset_r )
+{
+ nitedrvr_steering_val = 0;
+ return 0;
+}
+
+WRITE8_HANDLER( nitedrvr_steering_reset_w )
+{
+ nitedrvr_steering_val = 0;
+}
+
+
+/***************************************************************************
+nitedrvr_in0_r
+
+Night Driver looks for the following:
+ A: $00
+ D4 - OPT1
+ D5 - OPT2
+ D6 - OPT3
+ D7 - OPT4
+ A: $01
+ D4 - TRACK SET
+ D5 - BONUS TIME ALLOWED
+ D6 - VBLANK
+ D7 - !TEST
+ A: $02
+ D4 - !GEAR 1
+ D5 - !GEAR 2
+ D6 - !GEAR 3
+ D7 - SPARE
+ A: $03
+ D4 - SPARE
+ D5 - DIFFICULT BONUS
+ D6 - STEER A
+ D7 - STEER B
+
+Fill in the steering and gear bits in a special way.
+***************************************************************************/
+
+READ8_HANDLER( nitedrvr_in0_r )
+{
+ int gear;
+
+ gear = readinputport(2);
+ if (gear & 0x10) nitedrvr_gear=1;
+ else if (gear & 0x20) nitedrvr_gear=2;
+ else if (gear & 0x40) nitedrvr_gear=3;
+ else if (gear & 0x80) nitedrvr_gear=4;
+
+ switch (offset & 0x03)
+ {
+ case 0x00: /* No remapping necessary */
+ return readinputport(0);
+ case 0x01: /* No remapping necessary */
+ return readinputport(1);
+ case 0x02: /* Remap our gear shift */
+ if (nitedrvr_gear==1) return 0xE0;
+ else if (nitedrvr_gear==2) return 0xD0;
+ else if (nitedrvr_gear==3) return 0xB0;
+ else return 0x70;
+ case 0x03: /* Remap our steering */
+ return (readinputport(3) | nitedrvr_steering());
+ default:
+ return 0xFF;
+ }
+}
+
+/***************************************************************************
+nitedrvr_in1_r
+
+Night Driver looks for the following:
+ A: $00
+ D6 - SPARE
+ D7 - COIN 1
+ A: $01
+ D6 - SPARE
+ D7 - COIN 2
+ A: $02
+ D6 - SPARE
+ D7 - !START
+ A: $03
+ D6 - SPARE
+ D7 - !ACC
+ A: $04
+ D6 - SPARE
+ D7 - EXPERT
+ A: $05
+ D6 - SPARE
+ D7 - NOVICE
+ A: $06
+ D6 - SPARE
+ D7 - Special Alternating Signal
+ A: $07
+ D6 - SPARE
+ D7 - Ground
+
+Fill in the track difficulty switch and special signal in a special way.
+***************************************************************************/
+
+READ8_HANDLER( nitedrvr_in1_r )
+{
+ int port;
+
+ ac_line=(ac_line+1) % 3;
+
+ port = readinputport(4);
+ if (port & 0x10) nitedrvr_track=0;
+ else if (port & 0x20) nitedrvr_track=1;
+ else if (port & 0x40) nitedrvr_track=2;
+
+ switch (offset & 0x07)
+ {
+ case 0x00:
+ return ((port & 0x01) << 7);
+ case 0x01:
+ return ((port & 0x02) << 6);
+ case 0x02:
+ return ((port & 0x04) << 5);
+ case 0x03:
+ return ((port & 0x08) << 4);
+ case 0x04:
+ if (nitedrvr_track == 1) return 0x80; else return 0x00;
+ case 0x05:
+ if (nitedrvr_track == 0) return 0x80; else return 0x00;
+ case 0x06:
+ /* TODO: fix alternating signal? */
+ if (ac_line==0) return 0x80; else return 0x00;
+ case 0x07:
+ return 0x00;
+ default:
+ return 0xFF;
+ }
+}
+
+/***************************************************************************
+nitedrvr_out0_w
+
+Sound bits:
+
+D0 = !SPEED1
+D1 = !SPEED2
+D2 = !SPEED3
+D3 = !SPEED4
+D4 = SKID1
+D5 = SKID2
+***************************************************************************/
+WRITE8_HANDLER( nitedrvr_out0_w )
+{
+ discrete_sound_w(NITEDRVR_MOTOR_DATA, data & 0x0f); // Motor freq data
+ discrete_sound_w(NITEDRVR_SKID1_EN, data & 0x10); // Skid1 enable
+ discrete_sound_w(NITEDRVR_SKID2_EN, data & 0x20); // Skid2 enable
+}
+
+/***************************************************************************
+nitedrvr_out1_w
+
+D0 = !CRASH - also drives a video invert signal
+D1 = ATTRACT
+D2 = Spare (Not used)
+D3 = Not used?
+D4 = LED START
+D5 = Spare (Not used)
+***************************************************************************/
+WRITE8_HANDLER( nitedrvr_out1_w )
+{
+ set_led_status(0,data & 0x10);
+
+ nitedrvr_crash_en = data & 0x01;
+ discrete_sound_w(NITEDRVR_CRASH_EN, nitedrvr_crash_en); // Crash enable
+ discrete_sound_w(NITEDRVR_ATTRACT_EN, data & 0x02); // Attract enable (sound disable)
+
+ if (!nitedrvr_crash_en)
+ {
+ /* Crash reset, set counter high and enable output */
+ nitedrvr_crash_data_en = 1;
+ nitedrvr_crash_data = 0x0f;
+ /* Invert video */
+ palette_set_color(Machine,1,MAKE_RGB(0x00,0x00,0x00)); /* BLACK */
+ palette_set_color(Machine,0,MAKE_RGB(0xff,0xff,0xff)); /* WHITE */
+ }
+ discrete_sound_w(NITEDRVR_BANG_DATA, nitedrvr_crash_data_en ? nitedrvr_crash_data : 0); // Crash Volume
+}
+
+
+void nitedrvr_crash_toggle(running_machine *machine)
+{
+ if (nitedrvr_crash_en && nitedrvr_crash_data_en)
+ {
+ nitedrvr_crash_data--;
+ discrete_sound_w(NITEDRVR_BANG_DATA, nitedrvr_crash_data); // Crash Volume
+ if (!nitedrvr_crash_data) nitedrvr_crash_data_en = 0; // Done counting?
+ if (nitedrvr_crash_data & 0x01)
+ {
+ /* Invert video */
+ palette_set_color(machine,1,MAKE_RGB(0x00,0x00,0x00)); /* BLACK */
+ palette_set_color(machine,0,MAKE_RGB(0xff,0xff,0xff)); /* WHITE */
+ }
+ else
+ {
+ /* Normal video */
+ palette_set_color(machine,0,MAKE_RGB(0x00,0x00,0x00)); /* BLACK */
+ palette_set_color(machine,1,MAKE_RGB(0xff,0xff,0xff)); /* WHITE */
+ }
+ }
+}
+
+void nitedrvr_register_machine_vars(void)
+{/* save all the statics in this file. */
+ state_save_register_global(nitedrvr_gear);
+ state_save_register_global(nitedrvr_track);
+ state_save_register_global(nitedrvr_steering_buf);
+ state_save_register_global(nitedrvr_steering_val);
+ state_save_register_global(nitedrvr_crash_en);
+ state_save_register_global(nitedrvr_crash_data);
+ state_save_register_global(nitedrvr_crash_data_en);
+ state_save_register_global(ac_line);
+ state_save_register_global(last_steering_val);
+}
diff --git a/src/mame/machine/nmk004.c b/src/mame/machine/nmk004.c
new file mode 100644
index 00000000000..e11c94ed142
--- /dev/null
+++ b/src/mame/machine/nmk004.c
@@ -0,0 +1,1076 @@
+#include "driver.h"
+#include "nmk004.h"
+#include "sound/2203intf.h"
+#include "sound/okim6295.h"
+
+
+
+#define FM_CHANNELS 6
+#define PSG_CHANNELS 3
+#define EFFECTS_CHANNELS 8
+
+#define FM_FLAG_NEED_INITIALIZATION (1<<0)
+#define FM_FLAG_UNKNOWN2 (1<<1)
+#define FM_FLAG_NOTE_IS_PAUSE (1<<2)
+#define FM_FLAG_UNKNOWN3 (1<<3)
+#define FM_FLAG_MODULATE_NOTE (1<<4)
+#define FM_FLAG_MUST_SEND_KEYON (1<<5)
+#define FM_FLAG_MUST_SEND_CONFIGURATION (1<<6)
+#define FM_FLAG_ACTIVE (1<<7)
+
+#define PSG_FLAG_ACTIVE (1<<0)
+#define PSG_FLAG_NOTE_IS_PAUSE (1<<1)
+#define PSG_FLAG_NEED_INITIALIZATION (1<<2)
+#define PSG_FLAG_INITIALIZE_VOLUME (1<<3)
+#define PSG_FLAG_NOTE_IS_NOISE (1<<5)
+#define PSG_FLAG_NOISE_NOT_ENABLED (1<<6)
+
+#define EFFECTS_FLAG_NEED_INITIALIZATION (1<<0)
+#define EFFECTS_FLAG_ACTIVE (1<<7)
+
+#define NOTE_PAUSE 0x0c
+
+struct psg_control
+{
+/* C220 */ UINT8 flags;
+/* C221-C222 */ UINT16 note_timer;
+/* C223-C224 */ UINT16 note_length;
+/* C225 */ UINT8 volume_timer;
+/* C227-C228 */ UINT16 current; // current position in control table
+/* C229-C22A */ UINT16 return_address[16]; // return address when control table calls a subtable
+ int return_address_depth;
+/* C22B-C22C */ UINT16 loop_start; // first instruction of loop
+/* C22D */ UINT8 loop_times; // number of times to loop
+/* C22E */ UINT8 volume_shape;
+/* C22F */ UINT8 volume_position;
+/* C230 */ UINT8 octave; // base octave
+/* C231 */ UINT8 note; // note to play
+/* C233 */ UINT8 note_period_hi_bits;
+};
+
+struct fm_control
+{
+UINT8 note;
+/* C020 */ UINT8 flags;
+/* C021 */ UINT8 slot; // for ym2203 keyon command
+/* C022-C039 */ UINT8 voice_params[0x18]; // parameters for the YM2203 to configure sound shape
+/* C03A-C03B */ UINT16 f_number;
+/* C03C */ UINT8 self_feedback;
+/* C03D */ UINT8 note_duration_table_select;
+/* C03E-C03F */ UINT16 current; // current position in control table
+/* C040-C041 */ UINT16 loop_start; // first instruction of loop
+/* C042 */ UINT8 loop_times; // number of times to loop
+/* C043-C044 */ UINT16 return_address[16]; // return address when control table calls a subtable
+ int return_address_depth;
+/* C045 */ UINT8 octave;
+/* C046-C047 */ UINT16 timer1;
+/* C048-C049 */ UINT16 timer2;
+/* C04A-C04B */ UINT16 timer1_duration;
+/* C04C-C04D */ UINT16 timer2_duration;
+/* C04E */ UINT8 modulation_table_number;
+/* C04F-C050 */ UINT16 modulation_timer;
+/* C051-C052 */ UINT16 modulation_table;
+/* C053-C054 */ UINT16 modulation_table_position;
+/* C055-C056 */ UINT16 note_period;
+/* C057-C05A */ UINT8 voice_volume[4]; // parameters for the YM2203 to configure sound shape
+/* C05C */ UINT8 must_update_voice_params;
+};
+
+struct effects_control
+{
+/* C1A0 */ UINT8 flags;
+/* C1BE-C1BF */ UINT16 current; // current position in control table
+/* C1C0-C1C1 */ UINT16 loop_start; // first instruction of loop
+/* C1C2 */ UINT8 loop_times; // number of times to loop
+/* C1C3-C1C4 */ UINT16 return_address[16]; // return address when control table calls a subtable
+ int return_address_depth;
+/* C1C6-C1C7 */ UINT16 timer;
+/* C1CA-C1CB */ UINT16 timer_duration;
+};
+
+struct
+{
+ const UINT8 *rom; // NMK004 data ROM
+ UINT8 from_main; // command from main CPU
+ UINT8 to_main; // answer to main CPU
+ int protection_check;
+
+ /* C001 */ UINT8 last_command; // last command received
+ /* C016 */ UINT8 oki_playing; // bitmap of active Oki channels
+ /* C020-C19F */ struct fm_control fm_control[FM_CHANNELS];
+ /* C220-C2DF */ struct psg_control psg_control[PSG_CHANNELS];
+ /* C1A0-C21F */ struct effects_control effects_control[EFFECTS_CHANNELS];
+} NMK004_state;
+
+
+#define SAMPLE_TABLE_0 0xefe0
+#define SAMPLE_TABLE_1 0xefe2
+#define FM_MODULATION_TABLE 0xefe4
+#define FM_NOTE_TABLE 0xefe6
+#define NOTE_LENGTH_TABLE_1 0xefe8
+#define NOTE_LENGTH_TABLE_2 0xefea
+#define NOTE_LENGTH_TABLE_3 0xefec
+#define PSG_VOLUME_TABLE 0xefee
+#define COMMAND_TABLE 0xeff0
+#define PSG_NOTE_TABLE 0xeff2
+
+
+static UINT8 read8(int address)
+{
+ return NMK004_state.rom[address];
+}
+
+static UINT16 read16(int address)
+{
+ return NMK004_state.rom[address] + 256 * NMK004_state.rom[address+1];
+}
+
+
+
+/*****************************
+
+ OKI6295
+
+*****************************/
+
+static void oki_play_sample(int sample_no)
+{
+ UINT16 table_start = (sample_no & 0x80) ? read16(SAMPLE_TABLE_1) : read16(SAMPLE_TABLE_0);
+ UINT8 byte1 = read8(table_start + 2 * (sample_no & 0x7f) + 0);
+ UINT8 byte2 = read8(table_start + 2 * (sample_no & 0x7f) + 1);
+ int chip = (byte1 & 0x80) >> 7;
+
+ if ((byte1 & 0x7f) == 0)
+ {
+ // stop all channels
+ if (chip == 0)
+ OKIM6295_data_0_w(0, 0x78 );
+ else
+ OKIM6295_data_1_w(0, 0x78 );
+ }
+ else
+ {
+ int sample = byte1 & 0x7f;
+ int ch = byte2 & 0x03;
+ int force = (byte2 & 0x80) >> 7;
+
+ if (!force && (NMK004_state.oki_playing & (1 << (ch + 4*chip))))
+ return;
+
+ NMK004_state.oki_playing |= 1 << (ch + 4*chip);
+
+ // stop channel
+ if (chip == 0)
+ OKIM6295_data_0_w(0, (0x08 << ch) );
+ else
+ OKIM6295_data_1_w(0, (0x08 << ch) );
+
+ if (sample != 0)
+ {
+ UINT8 *rom = memory_region(REGION_SOUND1 + chip);
+ int bank = (byte2 & 0x0c) >> 2;
+ int vol = (byte2 & 0x70) >> 4;
+
+ if (bank != 3)
+ memcpy(rom + 0x20000,rom + 0x40000 + bank * 0x20000,0x20000);
+
+ if (chip == 0)
+ {
+ OKIM6295_data_0_w(0, 0x80 | sample );
+ OKIM6295_data_0_w(0, (0x10 << ch) | vol );
+ }
+ else
+ {
+ OKIM6295_data_1_w(0, 0x80 | sample );
+ OKIM6295_data_1_w(0, (0x10 << ch) | vol );
+ }
+ }
+ }
+}
+
+static void oki_update_state(void)
+{
+ NMK004_state.oki_playing = ((OKIM6295_status_1_r(0) & 0x0f) << 4) | (OKIM6295_status_0_r(0) & 0x0f);
+}
+
+
+
+/*****************************
+
+ EFFECTS (OKI6295)
+
+*****************************/
+
+static void effects_update(int channel)
+{
+ struct effects_control *effects = &NMK004_state.effects_control[channel];
+
+ // advance the timers
+ if (effects->timer)
+ effects->timer--;
+
+
+ if (effects->flags & EFFECTS_FLAG_NEED_INITIALIZATION)
+ {
+ effects->flags = EFFECTS_FLAG_ACTIVE;
+ effects->timer = 0;
+ }
+
+
+ if (effects->flags & EFFECTS_FLAG_ACTIVE)
+ {
+ if (effects->timer == 0)
+ {
+ UINT8 token;
+
+ do
+ {
+//logerror("channel %d address %04x token %02x\n",channel,effects->current,read8(effects->current));
+ token = read8(effects->current++);
+
+ if (token == 0x0ef || (token & 0xf0) == 0xf0)
+ {
+ switch (token)
+ {
+ case 0xef: // play sample
+ oki_play_sample(read8(effects->current++));
+ break;
+
+ case 0xf6: // jump
+ effects->current = read16(effects->current);
+ break;
+
+ case 0xf7: // begin repeat loop
+ effects->loop_times = read8(effects->current++);
+ effects->loop_start = effects->current;
+ break;
+
+ case 0xf8: // end repeat loop
+ if (--effects->loop_times > 0)
+ effects->current = effects->loop_start;
+ break;
+
+ case 0xf9: // call subtable
+ effects->return_address[effects->return_address_depth++] = effects->current + 2;
+ effects->current = read16(effects->current);
+ break;
+
+ case 0xfa: // return from subtable
+ effects->current = effects->return_address[--effects->return_address_depth];
+ break;
+
+ case 0xfc: // ??? (hachamf command 04)
+ break;
+
+ case 0xfd: // ??? (hachamf command 04)
+ break;
+
+ case 0xff: // end
+ effects->flags = 0; // disable channel
+ return;
+
+ default:
+ fatalerror("effects channel %d unsupported token %02x",channel,token);
+ }
+ }
+ } while (token == 0xef || (token & 0xf0) == 0xf0);
+
+ effects->current--;
+
+ if ((read8(effects->current) & 0x80) == 0)
+ {
+ if (read8(effects->current++) != 0x0c)
+ {
+ // this shouldn't happen on the effects channels (but it happens e.g. hachamf command 04)
+
+ logerror("effects channel %d invalid token %02x\n",channel,read8(effects->current));
+ }
+ }
+
+ // optional note length (otherwise use the same length as the previous one)
+ if (read8(effects->current) & 0x80)
+ {
+ UINT16 table_start = read16(NOTE_LENGTH_TABLE_1);
+
+ effects->timer_duration = read16(table_start + 2 * (read8(effects->current++) & 0x7f));
+ }
+
+ effects->timer = effects->timer_duration;
+ }
+ }
+}
+
+
+
+/*****************************
+
+ YM2203 - FM
+
+*****************************/
+
+static void fm_update(int channel)
+{
+ struct fm_control *fm = &NMK004_state.fm_control[channel];
+
+ // advance the timers
+ if (fm->timer1)
+ fm->timer1--;
+
+ if (fm->timer2)
+ fm->timer2--;
+
+ if (fm->modulation_timer)
+ fm->modulation_timer--;
+
+
+ if (fm->flags & FM_FLAG_NEED_INITIALIZATION)
+ {
+ fm->flags = FM_FLAG_ACTIVE;
+ fm->timer1 = 0;
+ }
+
+
+ if (fm->flags & FM_FLAG_ACTIVE)
+ {
+ if (fm->timer1 == 0)
+ {
+ UINT8 token;
+
+ do
+ {
+//logerror("channel %d address %04x token %02x\n",channel,fm->current,read8(fm->current));
+ token = read8(fm->current++);
+
+ if (token == 0x0ef || (token & 0xf0) == 0xf0)
+ {
+ int i;
+
+ switch (token)
+ {
+// case 0xef: // play sample
+// oki_play_sample(read8(fm->current++));
+// break;
+
+ case 0xf0: // slot (for keyon ym2203 command)
+ fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION;
+ fm->slot = read8(fm->current++);
+ if (channel < 3 || !(NMK004_state.fm_control[channel-3].flags & FM_FLAG_ACTIVE))
+ {
+ YM2203_control_port_0_w(0, 0x28); // keyon/off
+ YM2203_write_port_0_w(0, channel % 3);
+ }
+ break;
+
+ case 0xf1: // sound shape
+ fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION;
+ for (i = 0x00; i < 0x04; i++)
+ fm->voice_params[i] = read8(fm->current++);
+ break;
+
+ case 0xf2: // sound shape
+ fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION;
+ for (i = 0; i < 4; i++)
+ fm->voice_volume[i] = read8(fm->current++);
+ break;
+
+ case 0xf3: // sound shape
+ fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION;
+ for (i = 0x08; i < 0x18; i++)
+ fm->voice_params[i] = read8(fm->current++);
+ break;
+
+ case 0xf4: // set self-feedback
+ fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION;
+ fm->self_feedback = read8(fm->current++);
+ break;
+
+ case 0xf5: // select note duration table
+ fm->note_duration_table_select = read8(fm->current++);
+ break;
+
+ case 0xf6: // jump
+ fm->current = read16(fm->current);
+ break;
+
+ case 0xf7: // begin repeat loop
+ fm->loop_times = read8(fm->current++);
+ fm->loop_start = fm->current;
+ break;
+
+ case 0xf8: // end repeat loop
+ if (--fm->loop_times > 0)
+ fm->current = fm->loop_start;
+ break;
+
+ case 0xf9: // call subtable
+ fm->return_address[fm->return_address_depth++] = fm->current + 2;
+ fm->current = read16(fm->current);
+ break;
+
+ case 0xfa: // return from subtable
+ fm->current = fm->return_address[--fm->return_address_depth];
+ break;
+
+ case 0xfb: // set octave
+ fm->octave = read8(fm->current++);
+ break;
+
+ case 0xfc: // ???
+ fm->flags |= FM_FLAG_UNKNOWN2;
+ fm->flags |= FM_FLAG_UNKNOWN3;
+ break;
+
+ case 0xfd: // ???
+ fm->flags &= ~FM_FLAG_UNKNOWN2;
+ break;
+
+ case 0xfe: // set note modulation
+ fm->modulation_table_number = read8(fm->current++);
+ if (fm->modulation_table_number == 0)
+ {
+ fm->flags &= ~FM_FLAG_MODULATE_NOTE;
+ }
+ else
+ {
+ UINT16 table_start = read16(FM_MODULATION_TABLE);
+
+ fm->modulation_table = read16(table_start + 2 * (fm->modulation_table_number - 1));
+ fm->modulation_timer = read16(fm->modulation_table);
+ fm->modulation_table_position = fm->modulation_table + 2;
+ fm->flags |= FM_FLAG_MODULATE_NOTE;
+ }
+ break;
+
+ case 0xff: // end
+ fm->flags = FM_FLAG_MUST_SEND_CONFIGURATION; // disable channel
+ for (i = 0x04; i < 0x08; i++)
+ fm->voice_params[i] = 0x7f;
+ for (i = 0x14; i < 0x18; i++)
+ fm->voice_params[i] = 0x0f;
+ return;
+
+ default:
+ fatalerror("fm channel %d unsupported token %02x",channel,token);
+ }
+ }
+ } while (token == 0xef || (token & 0xf0) == 0xf0);
+
+ fm->current--;
+
+ if ((read8(fm->current) & 0x80) == 0)
+ {
+ int note = read8(fm->current++);
+
+fm->note = note;
+ if ((note & 0x0f) == NOTE_PAUSE)
+ fm->flags |= FM_FLAG_NOTE_IS_PAUSE;
+ else
+ {
+ UINT16 table_start = read16(FM_NOTE_TABLE);
+ UINT16 period = read16(table_start + 2 * (note & 0x0f));
+ UINT8 octave = ((fm->octave << 4) + note) & 0xf0;
+
+ fm->flags &= ~FM_FLAG_NOTE_IS_PAUSE;
+ fm->note_period = period | (octave << 7);
+
+ fm->must_update_voice_params = 1;
+ }
+ }
+
+ // optional note length (otherwise use the same length as the previous one)
+ if (read8(fm->current) & 0x80)
+ {
+ UINT16 table_start;
+ UINT8 duration = read8(fm->current++) & 0x7f;
+
+ table_start = read16(NOTE_LENGTH_TABLE_1);
+ fm->timer1_duration = read16(table_start + 2 * duration);
+
+ table_start = fm->note_duration_table_select ? read16(NOTE_LENGTH_TABLE_3) : read16(NOTE_LENGTH_TABLE_2);
+ fm->timer2_duration = read16(table_start + 2 * duration);
+ }
+
+ fm->timer1 = fm->timer1_duration;
+ fm->timer2 = fm->timer2_duration;
+
+
+ if (!(fm->flags & FM_FLAG_NOTE_IS_PAUSE) &&
+ ((fm->flags & FM_FLAG_UNKNOWN3) || !(fm->flags & FM_FLAG_UNKNOWN2)))
+ {
+ fm->flags &= ~FM_FLAG_UNKNOWN3;
+ fm->flags |= FM_FLAG_MUST_SEND_KEYON;
+ fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION;
+ }
+ }
+ }
+
+
+
+ if ((fm->flags & FM_FLAG_MODULATE_NOTE) && (fm->flags & FM_FLAG_MUST_SEND_KEYON))
+ {
+ fm->modulation_timer = read16(fm->modulation_table);
+ fm->modulation_table_position = fm->modulation_table + 2;
+ }
+
+ if (!(fm->flags & FM_FLAG_MODULATE_NOTE) || (fm->flags & FM_FLAG_MUST_SEND_KEYON) || fm->must_update_voice_params)
+ {
+ int i;
+
+ fm->must_update_voice_params = 0;
+
+ for (i = 0; i < 4; i++)
+ fm->voice_params[0x04 + i] = fm->voice_volume[i];
+
+ fm->f_number = fm->note_period;
+ }
+ else
+ {
+ if (fm->modulation_timer == 0)
+ {
+ int i;
+ UINT16 a;
+
+ for (i = 0; i < 4; i++)
+ fm->voice_params[0x04 + i] = fm->voice_volume[i];
+
+ fm->modulation_table_position++;
+ a = read8(fm->modulation_table_position++);
+ if (a & 0x80) // sign extend
+ a |= 0xff00;
+ a *= 4;
+
+ fm->f_number = fm->note_period + a;
+
+ fm->modulation_timer = read8(fm->modulation_table_position++); // modulation_timer is UINT16 but this is just 8-bit
+
+ if (read8(fm->modulation_table_position) == 0x80) // end of table - repeat
+ {
+ fm->modulation_table_position = fm->modulation_table + 2;
+ }
+ else if (read8(fm->modulation_table_position) == 0x88) // end of table - stop
+ {
+ fm->flags &= ~FM_FLAG_MODULATE_NOTE;
+ }
+ }
+ }
+
+
+#if 0
+popmessage("%02x %02x %02x %02x %02x %02x",
+ NMK004_state.fm_control[0].note,
+ NMK004_state.fm_control[1].note,
+ NMK004_state.fm_control[2].note,
+ NMK004_state.fm_control[3].note,
+ NMK004_state.fm_control[4].note,
+ NMK004_state.fm_control[5].note);
+#endif
+#if 0
+popmessage("%02x %02x%02x%02x%02x %02x %02x%02x%02x%02x %02x %02x%02x%02x%02x",
+ NMK004_state.fm_control[3].note,
+ NMK004_state.fm_control[3].voice_volume[0],
+ NMK004_state.fm_control[3].voice_volume[1],
+ NMK004_state.fm_control[3].voice_volume[2],
+ NMK004_state.fm_control[3].voice_volume[3],
+ NMK004_state.fm_control[4].note,
+ NMK004_state.fm_control[4].voice_volume[0],
+ NMK004_state.fm_control[4].voice_volume[1],
+ NMK004_state.fm_control[4].voice_volume[2],
+ NMK004_state.fm_control[4].voice_volume[3],
+ NMK004_state.fm_control[5].note,
+ NMK004_state.fm_control[5].voice_volume[0],
+ NMK004_state.fm_control[5].voice_volume[1],
+ NMK004_state.fm_control[5].voice_volume[2],
+ NMK004_state.fm_control[5].voice_volume[3]);
+#endif
+}
+
+
+static void fm_voices_update(void)
+{
+ static int ym2203_registers[0x18] =
+ {
+ 0x30,0x38,0x34,0x3C,0x40,0x48,0x44,0x4C,0x50,0x58,0x54,0x5C,0x60,0x68,0x64,0x6C,
+ 0x70,0x78,0x74,0x7C,0x80,0x88,0x84,0x8C
+ };
+ int channel,i;
+
+ for (channel = 0; channel < 3;channel++)
+ {
+ struct fm_control *fm1 = &NMK004_state.fm_control[channel];
+ struct fm_control *fm2 = &NMK004_state.fm_control[channel + 3];
+
+ if (fm1->flags & FM_FLAG_MUST_SEND_CONFIGURATION)
+ {
+ fm1->flags &= ~FM_FLAG_MUST_SEND_CONFIGURATION;
+
+ for (i = 0; i < 0x18; i++)
+ {
+ YM2203_control_port_0_w(0, ym2203_registers[i] + channel);
+ YM2203_write_port_0_w(0, fm1->voice_params[i]);
+ }
+ }
+
+ if (fm2->flags & FM_FLAG_MUST_SEND_CONFIGURATION)
+ {
+ fm2->flags &= ~FM_FLAG_MUST_SEND_CONFIGURATION;
+
+ if (!(fm1->flags & FM_FLAG_ACTIVE))
+ {
+ for (i = 0; i < 0x18; i++)
+ {
+ YM2203_control_port_0_w(0, ym2203_registers[i] + channel);
+ YM2203_write_port_0_w(0, fm2->voice_params[i]);
+ }
+ }
+ }
+
+
+ if (fm1->flags & FM_FLAG_ACTIVE)
+ {
+ YM2203_control_port_0_w(0, 0xb0 + channel); // self-feedback
+ YM2203_write_port_0_w(0, fm1->self_feedback);
+
+ YM2203_control_port_0_w(0, 0xa4 + channel); // F-number
+ YM2203_write_port_0_w(0, fm1->f_number >> 8);
+
+ YM2203_control_port_0_w(0, 0xa0 + channel); // F-number
+ YM2203_write_port_0_w(0, fm1->f_number & 0xff);
+ }
+ else
+ {
+ YM2203_control_port_0_w(0, 0xb0 + channel); // self-feedback
+ YM2203_write_port_0_w(0, fm2->self_feedback);
+
+ YM2203_control_port_0_w(0, 0xa4 + channel); // F-number
+ YM2203_write_port_0_w(0, fm2->f_number >> 8);
+
+ YM2203_control_port_0_w(0, 0xa0 + channel); // F-number
+ YM2203_write_port_0_w(0, fm2->f_number & 0xff);
+ }
+
+
+
+ if (fm1->flags & FM_FLAG_MUST_SEND_KEYON)
+ {
+ fm1->flags &= ~FM_FLAG_MUST_SEND_KEYON;
+
+ YM2203_control_port_0_w(0, 0x28); // keyon/off
+ YM2203_write_port_0_w(0, fm1->slot | channel);
+ }
+
+ if (fm2->flags & FM_FLAG_MUST_SEND_KEYON)
+ {
+ fm2->flags &= ~FM_FLAG_MUST_SEND_KEYON;
+
+ if (!(fm1->flags & FM_FLAG_ACTIVE))
+ {
+ YM2203_control_port_0_w(0, 0x28); // keyon/off
+ YM2203_write_port_0_w(0, fm2->slot | channel);
+ }
+ }
+ }
+}
+
+
+
+/*****************************
+
+ YM2203 - PSG
+
+*****************************/
+
+static void psg_update(int channel)
+{
+ struct psg_control *psg = &NMK004_state.psg_control[channel];
+
+ // advance the timers
+ if (psg->note_timer)
+ psg->note_timer--;
+
+ if (psg->volume_timer)
+ psg->volume_timer--;
+
+ if (psg->flags & PSG_FLAG_NEED_INITIALIZATION)
+ {
+ psg->flags &= ~PSG_FLAG_NEED_INITIALIZATION;
+ psg->flags |= PSG_FLAG_ACTIVE;
+
+ if (psg->flags & PSG_FLAG_NOTE_IS_NOISE)
+ {
+ int enable;
+
+ psg->flags &= ~PSG_FLAG_NOTE_IS_NOISE;
+ psg->flags &= ~PSG_FLAG_NOISE_NOT_ENABLED;
+
+ // enable noise, disable tone on this channel
+ YM2203_control_port_0_w(0, 0x07);
+ enable = YM2203_read_port_0_r(0);
+ enable |= (0x01 << channel); // disable tone
+ enable &= ~(0x08 << channel); // enable noise
+ YM2203_write_port_0_w(0, enable);
+ }
+
+
+ psg->note_timer = 0;
+ psg->volume_timer = 0;
+ psg->octave = 0;
+ }
+
+ if (psg->flags & PSG_FLAG_ACTIVE)
+ {
+ if (psg->note_timer == 0)
+ {
+ UINT8 token;
+
+ do
+ {
+ token = read8(psg->current++);
+
+ if ((token & 0xf0) == 0xf0)
+ {
+ int enable;
+
+ switch (token)
+ {
+ case 0xf0: // noise
+ psg->flags |= PSG_FLAG_NOTE_IS_NOISE;
+ break;
+
+ case 0xf1: // note
+ psg->flags &= ~PSG_FLAG_NOTE_IS_NOISE;
+ psg->flags &= ~PSG_FLAG_NOISE_NOT_ENABLED;
+
+ // enable noise, disable tone on this channel
+ YM2203_control_port_0_w(0, 0x07);
+ enable = YM2203_read_port_0_r(0);
+ enable |= (0x01 << channel); // disable tone
+ enable &= ~(0x08 << channel); // enable noise
+ YM2203_write_port_0_w(0, enable);
+ break;
+
+ case 0xf2: // set volume shape
+ case 0xf3:
+ case 0xf4:
+ case 0xf5:
+ psg->volume_shape = read8(psg->current++);
+ break;
+
+ case 0xf6: // jump
+ psg->current = read16(psg->current);
+ break;
+
+ case 0xf7: // begin repeat loop
+ psg->loop_times = read8(psg->current++);
+ psg->loop_start = psg->current;
+ break;
+
+ case 0xf8: // end repeat loop
+ if (--psg->loop_times > 0)
+ psg->current = psg->loop_start;
+ break;
+
+ case 0xf9: // call subtable
+ psg->return_address[psg->return_address_depth++] = psg->current + 2;
+ psg->current = read16(psg->current);
+ break;
+
+ case 0xfa: // return from subtable
+ psg->current = psg->return_address[--psg->return_address_depth];
+ break;
+
+ case 0xfb: // set octave
+ case 0xfc:
+ case 0xfd:
+ case 0xfe:
+ psg->octave = read8(psg->current++);
+ break;
+
+ case 0xff: // end
+ psg->flags = 0; // disable channel
+ psg->volume_shape = 0;
+
+ // mute channel
+ YM2203_control_port_0_w(0, 8 + channel);
+ YM2203_write_port_0_w(0, 0);
+ return;
+ }
+ }
+ } while ((token & 0xf0) == 0xf0);
+
+ // token is the note to play
+ psg->note = token;
+ if ((psg->note & 0x0f) > NOTE_PAUSE)
+ {
+ fatalerror("PSG channel %d invalid note %02x",channel,psg->note);
+ }
+
+ // optional note length (otherwise use the same length as the previous one)
+ if (read8(psg->current) & 0x80)
+ {
+ UINT16 table_start = read16(NOTE_LENGTH_TABLE_1);
+
+ psg->note_length = read16(table_start + 2 * (read8(psg->current++) & 0x7f));
+ }
+
+ psg->note_timer = psg->note_length;
+ psg->volume_timer = 0;
+
+ psg->flags |= PSG_FLAG_INITIALIZE_VOLUME;
+
+ if (psg->note == NOTE_PAUSE)
+ psg->flags |= PSG_FLAG_NOTE_IS_PAUSE;
+ else
+ {
+ psg->flags &= ~PSG_FLAG_NOTE_IS_PAUSE;
+
+ if (!(psg->flags & PSG_FLAG_NOTE_IS_NOISE))
+ {
+ UINT16 table_start = read16(PSG_NOTE_TABLE);
+ UINT16 period = read16(table_start + 2 * (psg->note & 0x0f));
+ UINT8 octave = psg->octave + ((psg->note & 0xf0) >> 4);
+
+ period >>= octave;
+
+ YM2203_control_port_0_w(0, 2 * channel + 1);
+ YM2203_write_port_0_w(0, (period & 0x0f00) >> 8);
+ YM2203_control_port_0_w(0, 2 * channel + 0);
+ YM2203_write_port_0_w(0, (period & 0x00ff));
+
+ psg->note_period_hi_bits = (period & 0x0f00) >> 8;
+ }
+ else
+ {
+ if (!(psg->flags & PSG_FLAG_NOISE_NOT_ENABLED))
+ {
+ int enable;
+
+ psg->flags |= PSG_FLAG_NOISE_NOT_ENABLED;
+
+ // disable noise, enable tone on this channel
+ YM2203_control_port_0_w(0, 0x07);
+ enable = YM2203_read_port_0_r(0);
+ enable &= ~(0x01 << channel); // enable tone
+ enable |= (0x08 << channel); // disable noise
+ YM2203_write_port_0_w(0, enable);
+ }
+
+ YM2203_control_port_0_w(0, 0x06); // noise period
+ YM2203_write_port_0_w(0, psg->note);
+ psg->note_period_hi_bits = psg->note;
+ }
+ }
+ }
+
+ if (psg->volume_timer == 0)
+ {
+ UINT16 table_start = read16(PSG_VOLUME_TABLE);
+ UINT16 vol_table_start = read16(table_start + 2 * psg->volume_shape);
+ int volume;
+
+ if (psg->flags & PSG_FLAG_INITIALIZE_VOLUME)
+ {
+ psg->flags &= ~PSG_FLAG_INITIALIZE_VOLUME;
+ psg->volume_position = 0;
+ }
+
+ volume = read8(vol_table_start + psg->volume_position++);
+ psg->volume_timer = read8(vol_table_start + psg->volume_position++);
+
+ if (psg->flags & PSG_FLAG_NOTE_IS_PAUSE)
+ volume = 0;
+
+ // set volume
+ YM2203_control_port_0_w(0, 8 + channel);
+ YM2203_write_port_0_w(0, volume & 0x0f);
+ }
+ }
+}
+
+
+
+/*****************************
+
+ Command processing
+
+*****************************/
+
+static void get_command(void)
+{
+ static UINT8 from_main[] =
+ {
+ 0x00,0x22,0x62,0x8c,0xc7,0x00,0x00,0x3f,0x7f,0x89,0xc7,0x00,0x00,0x2b,0x6b
+ };
+ static UINT8 to_main[] =
+ {
+ 0x82,0xc7,0x00,0x2c,0x6c,0x00,0x9f,0xc7,0x00,0x29,0x69,0x00,0x8b,0xc7,0x00
+ };
+
+ UINT8 cmd = NMK004_state.from_main;
+
+ if (NMK004_state.protection_check < sizeof(to_main))
+ {
+ // startup handshake
+ if (cmd == from_main[NMK004_state.protection_check])
+ {
+ logerror("advance handshake to %02x\n",to_main[NMK004_state.protection_check]);
+ NMK004_state.to_main = to_main[NMK004_state.protection_check++];
+ }
+ }
+ else
+ {
+ // send command back to main CPU to acknowledge reception
+ NMK004_state.to_main = cmd;
+ }
+
+ if (NMK004_state.last_command != cmd)
+ {
+ UINT16 table_start = read16(COMMAND_TABLE);
+ UINT16 cmd_table = read16(table_start + 2 * cmd);
+
+ NMK004_state.last_command = cmd;
+
+ if ((cmd_table & 0xff00) == 0)
+ {
+ oki_play_sample(cmd_table);
+ }
+ else
+ {
+ int channel;
+
+ while ((channel = read8(cmd_table++)) != 0xff)
+ {
+ table_start = read16(cmd_table);
+ cmd_table += 2;
+
+ if (channel == 0xef) break; // bioship bug?
+
+//logerror("%04x: channel %d table %04x\n",cmd_table-3,channel,table_start);
+ if (channel < FM_CHANNELS)
+ {
+ NMK004_state.fm_control[channel].current = table_start;
+ NMK004_state.fm_control[channel].return_address_depth = 0;
+ NMK004_state.fm_control[channel].flags |= FM_FLAG_NEED_INITIALIZATION;
+ }
+ else
+ {
+ channel -= FM_CHANNELS;
+ if (channel < PSG_CHANNELS)
+ {
+ NMK004_state.psg_control[channel].current = table_start;
+ NMK004_state.psg_control[channel].return_address_depth = 0;
+ NMK004_state.psg_control[channel].flags |= PSG_FLAG_NEED_INITIALIZATION;
+ }
+ else
+ {
+ channel -= PSG_CHANNELS;
+ if (channel >= EFFECTS_CHANNELS)
+ {
+ fatalerror("too many effects channels");
+ }
+ NMK004_state.effects_control[channel].current = table_start;
+ NMK004_state.effects_control[channel].return_address_depth = 0;
+ NMK004_state.effects_control[channel].flags |= EFFECTS_FLAG_NEED_INITIALIZATION;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+static void update_music(void)
+{
+ int channel;
+
+ for (channel = 0; channel < FM_CHANNELS; channel++)
+ fm_update(channel);
+ fm_voices_update();
+
+ for (channel = 0; channel < PSG_CHANNELS; channel++)
+ psg_update(channel);
+
+ for (channel = 0; channel < EFFECTS_CHANNELS; channel++)
+ effects_update(channel);
+}
+
+
+
+void NMK004_irq(int irq)
+{
+ int status;
+
+ if (!irq) return;
+
+ status = YM2203_status_port_0_r(0);
+
+ if (status & 1) // timer A expired
+ {
+ oki_update_state();
+ get_command();
+ update_music();
+
+ // restart timer
+ YM2203_control_port_0_w(0, 0x27);
+ YM2203_write_port_0_w(0, 0x15);
+ }
+}
+
+
+static TIMER_CALLBACK( real_nmk004_init )
+{
+ static UINT8 ym2203_init[] =
+ {
+ 0x07,0x38,0x08,0x00,0x09,0x00,0x0A,0x00,0x24,0xB3,0x25,0x00,0x26,0xF9,0x27,0x15,
+ 0x28,0x00,0x28,0x01,0x28,0x02,0x40,0x00,0x41,0x00,0x42,0x00,0x44,0x00,0x45,0x00,
+ 0x46,0x00,0x48,0x00,0x49,0x00,0x4A,0x00,0x4C,0x00,0x4D,0x00,0x4E,0x00,0xFF,
+ };
+ int i;
+
+ memset(&NMK004_state, 0, sizeof(NMK004_state));
+
+ NMK004_state.rom = memory_region(REGION_CPU2);
+
+ YM2203_control_port_0_w(0, 0x2f);
+
+ i = 0;
+ while (ym2203_init[i] != 0xff)
+ {
+ YM2203_control_port_0_w(0, ym2203_init[i++]);
+ YM2203_write_port_0_w(0, ym2203_init[i++]);
+ }
+
+ NMK004_state.oki_playing = 0;
+
+ oki_play_sample(0);
+
+ NMK004_state.protection_check = 0;
+}
+
+void NMK004_init(void)
+{
+ /* we have to do this via a timer because we get called before the sound reset */
+ timer_call_after_resynch(0, real_nmk004_init);
+}
+
+
+WRITE16_HANDLER( NMK004_w )
+{
+ if (ACCESSING_LSB)
+ {
+logerror("%06x: NMK004_w %02x\n",activecpu_get_pc(),data);
+ NMK004_state.from_main = data & 0xff;
+ }
+}
+
+READ16_HANDLER( NMK004_r )
+{
+static int last;
+ int res = NMK004_state.to_main;
+
+if (res != last) logerror("%06x: NMK004_r %02x\n",activecpu_get_pc(),res);
+last = res;
+
+ return res;
+}
+
diff --git a/src/mame/machine/nmk004.h b/src/mame/machine/nmk004.h
new file mode 100644
index 00000000000..2239fd8760f
--- /dev/null
+++ b/src/mame/machine/nmk004.h
@@ -0,0 +1,4 @@
+void NMK004_init(void);
+void NMK004_irq(int irq);
+READ16_HANDLER( NMK004_r );
+WRITE16_HANDLER( NMK004_w );
diff --git a/src/mame/machine/nmk112.c b/src/mame/machine/nmk112.c
new file mode 100644
index 00000000000..ae620b7fef0
--- /dev/null
+++ b/src/mame/machine/nmk112.c
@@ -0,0 +1,59 @@
+/* NMK112 - NMK custom IC for bankswitching the sample ROMs of a pair of
+ OKI6295 ADPCM chips
+
+ The address space of each OKI6295 is divided into four banks, each one
+ independently controlled. The sample table at the beginning of the
+ address space may be divided in four pages as well, banked together
+ with the sample data. This allows each of the four voices on the chip
+ to play a sample from a different bank at the same time. */
+
+#include "driver.h"
+#include "nmk112.h"
+
+#define MAXCHIPS 2
+#define TABLESIZE 0x100
+#define BANKSIZE 0x10000
+
+/* which chips have their sample address table divided into pages */
+static int has_paged_table[MAXCHIPS] = { 1, 1 };
+
+static UINT8 current_bank[8] = { ~0, ~0, ~0, ~0, ~0, ~0, ~0, ~0 };
+
+void NMK112_set_paged_table( int chip, int value )
+{
+ has_paged_table[chip] = value;
+}
+
+WRITE8_HANDLER( NMK112_okibank_w )
+{
+ int chip = (offset & 4) >> 2;
+ int banknum = offset & 3;
+
+ UINT8 *rom = memory_region(REGION_SOUND1 + chip);
+ int size = memory_region_length(REGION_SOUND1 + chip) - 0x40000;
+ int bankaddr = (data * BANKSIZE) % size;
+
+ if (current_bank[offset] == data) return;
+ current_bank[offset] = data;
+
+ /* copy the samples */
+ if ((has_paged_table[chip]) && (banknum == 0))
+ memcpy(rom + 0x400, rom + 0x40000 + bankaddr+0x400, BANKSIZE-0x400);
+ else
+ memcpy(rom + banknum * BANKSIZE, rom + 0x40000 + bankaddr, BANKSIZE);
+
+ /* also copy the sample address table, if it is paged on this chip */
+ if (has_paged_table[chip])
+ {
+ rom += banknum * TABLESIZE;
+ memcpy(rom, rom + 0x40000 + bankaddr, TABLESIZE);
+ }
+}
+
+WRITE16_HANDLER( NMK112_okibank_lsb_w )
+{
+ if (ACCESSING_LSB)
+ {
+ NMK112_okibank_w(offset, data & 0xff);
+ }
+}
diff --git a/src/mame/machine/nmk112.h b/src/mame/machine/nmk112.h
new file mode 100644
index 00000000000..0f0da826e44
--- /dev/null
+++ b/src/mame/machine/nmk112.h
@@ -0,0 +1,9 @@
+#ifndef NMK112_H
+#define NMK112_H
+
+void NMK112_set_paged_table( int chip, int value );
+
+WRITE8_HANDLER( NMK112_okibank_w );
+WRITE16_HANDLER( NMK112_okibank_lsb_w );
+
+#endif
diff --git a/src/mame/machine/nycaptor.c b/src/mame/machine/nycaptor.c
new file mode 100644
index 00000000000..0b098b045df
--- /dev/null
+++ b/src/mame/machine/nycaptor.c
@@ -0,0 +1,127 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( nycaptor_68705_portA_r )
+{
+
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( nycaptor_68705_portA_w )
+{
+
+ portA_out = data;
+}
+
+WRITE8_HANDLER( nycaptor_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 1 W when 1->0, enables latch which brings the command from main CPU (read from port A)
+ * 2 W when 0->1, copies port A to the latch for the main CPU
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( nycaptor_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( nycaptor_68705_portB_w )
+{
+
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ if (main_sent) cpunum_set_input_line(3,0,CLEAR_LINE);
+ main_sent = 0;
+
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( nycaptor_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( nycaptor_68705_portC_r )
+{
+ portC_in = 0;
+ if (main_sent) portC_in |= 0x01;
+ if (!mcu_sent) portC_in |= 0x02;
+
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( nycaptor_68705_portC_w )
+{
+
+ portC_out = data;
+}
+
+WRITE8_HANDLER( nycaptor_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+WRITE8_HANDLER( nycaptor_mcu_w )
+{
+
+ from_main = data;
+ main_sent = 1;
+ cpunum_set_input_line(3,0,ASSERT_LINE);
+}
+
+READ8_HANDLER( nycaptor_mcu_r )
+{
+
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( nycaptor_mcu_status_r1 )
+{
+ /* bit 1 = when 1, mcu has sent data to the main cpu */
+
+ return mcu_sent?2:0;
+}
+
+READ8_HANDLER( nycaptor_mcu_status_r2 )
+{
+ /* bit 0 = when 1, mcu is ready to receive data from main cpu */
+ return main_sent?0:1;
+
+}
diff --git a/src/mame/machine/opwolf.c b/src/mame/machine/opwolf.c
new file mode 100644
index 00000000000..492c2017376
--- /dev/null
+++ b/src/mame/machine/opwolf.c
@@ -0,0 +1,751 @@
+/*************************************************************************
+
+ Operation Wolf C-Chip Protection
+ ================================
+
+ The C-Chip (Taito TC0030CMD) is an unidentified mask programmed
+ microcontroller of some sort with 64 pins. It probably has
+ about 2k of ROM and 8k of RAM.
+
+ Interesting memory locations shared by cchip/68k:
+
+ 14 - dip switch A (written by 68k at start)
+ 15 - dip switch B (written by 68k at start)
+ 1b - Current level number (1-6)
+ 1c - Number of men remaining in level
+ 1e - Number of helicopters remaining in level
+ 1f - Number of tanks remaining in level
+ 20 - Number of boats remaining in level
+ 21 - Hostages in plane (last level)
+ 22 - Hostages remaining (last level)/Hostages saved (2nd last level)#
+ 27 - Set to 1 when final boss is destroyed
+ 32 - Set to 1 by cchip when level complete (no more enemies remaining)
+ 34 - Game state (0=attract mode, 1=intro, 2=in-game, 3=end-screen)
+ 51/52 - Used by cchip to signal change in credit level to 68k
+ 53 - Credit count
+ 75 - Set to 1 to trigger end of game boss
+ 7a - Used to trigger level data select command
+
+ Notes on bootleg c-chip:
+ 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.
+
+*************************************************************************/
+
+#include "driver.h"
+
+/* 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
+};
+
+extern int opwolf_region;
+
+static UINT8 current_bank=0;
+static UINT8 current_cmd=0;
+static UINT8* cchip_ram=0;
+static UINT8 cchip_last_7a=0;
+static UINT8 cchip_last_04=0;
+static UINT8 cchip_last_05=0;
+static UINT8 cchip_coins_for_credit[2]={1,1};
+static UINT8 cchip_credits_for_coin[2]={1,1};
+static UINT8 cchip_coins[2]={0,0};
+static UINT8 c588=0, c589=0, c58a=0; // These variables derived from the bootleg
+
+static const UINT16 level_data_00[0xcc] =
+{
+ 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
+};
+
+static const UINT16 level_data_01[0xcc] =
+{
+ 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,0x0609,0x0300,0x4e01,0x8006,0x8012,0x0b80,0x0609,
+ 0x0300,0x4e01,0x0007,0x8007
+};
+
+static const UINT16 level_data_02[0xcc] =
+{
+ 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
+};
+
+static const UINT16 level_data_03[0xcc] =
+{
+ 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
+};
+
+static const UINT16 level_data_04[0xcc] =
+{
+ 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
+};
+
+static const UINT16 level_data_05[0xcc] =
+{
+ 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
+};
+
+static const UINT16 level_data_06[0xcc] =
+{
+ 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,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8002,
+ 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x8003,0x0b80,0x0609,
+ 0x0300,0x4e01,0x5006,0x8004,0x0b80,0x0609,0x0300,0x4e01,
+ 0x5006,0x0008,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0010,
+ 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0012,0x0b80,0x0609,
+ 0x0300,0x4e01,0x5006,0x0014,0x0b80,0x0609,0x0300,0x4e01,
+ 0x5006,0x0016,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0018,
+ 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0020,0x0b80,0x0609,
+ 0x0300,0x4e01,0x5006,0x0023,0x0b80,0x0609,0x0300,0x4e01,
+ 0x5006,0x0030,0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0038,
+ 0x0b80,0x0609,0x0300,0x4e01,0x5006,0x0040,0x0b80,0x0609,
+ 0x0300,0x4e01,0x5006,0x0042
+};
+
+static const UINT16* level_data_lookup[] =
+{
+ level_data_00,
+ level_data_01,
+ level_data_02,
+ level_data_03,
+ level_data_04,
+ level_data_05,
+ level_data_06,
+};
+
+
+static TIMER_CALLBACK( timer_callback )
+{
+ // Level data command
+ if (current_cmd==0xf5)
+ {
+ int level=cchip_ram[0x1b];
+ const UINT16* level_data=level_data_lookup[level];
+ int i=0;
+ for (i=0; i<0xcc; i++)
+ {
+ cchip_ram[0x200 + i*2 + 0]=level_data[i]>>8;
+ cchip_ram[0x200 + i*2 + 1]=level_data[i]&0xff;
+ }
+
+ // The bootleg cchip writes 0 to these locations - hard to tell what the real one writes
+ cchip_ram[0x0]=0;
+ cchip_ram[0x76]=0;
+ cchip_ram[0x75]=0;
+ cchip_ram[0x74]=0;
+ cchip_ram[0x72]=0;
+ cchip_ram[0x71]=0;
+ cchip_ram[0x70]=0;
+ cchip_ram[0x66]=0;
+ cchip_ram[0x2b]=0;
+ cchip_ram[0x30]=0;
+ cchip_ram[0x31]=0;
+ cchip_ram[0x32]=0;
+ cchip_ram[0x27]=0;
+ c588=0;
+ c589=0;
+ c58a=0;
+
+ cchip_ram[0x1a]=0;
+ cchip_ram[0x7a]=1; // Signal command complete
+ }
+
+ current_cmd=0;
+}
+
+static void 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 (cchip_ram[0x15]&3) // Dipswitch B
+ {
+ case 3:
+ cchip_ram[0x2c]=0x31;
+ cchip_ram[0x77]=0x05;
+ cchip_ram[0x25]=0x0f;
+ cchip_ram[0x26]=0x0b;
+ break;
+ case 0:
+ cchip_ram[0x2c]=0x20;
+ cchip_ram[0x77]=0x06;
+ cchip_ram[0x25]=0x07;
+ cchip_ram[0x26]=0x03;
+ break;
+ case 1:
+ cchip_ram[0x2c]=0x31;
+ cchip_ram[0x77]=0x05;
+ cchip_ram[0x25]=0x0f;
+ cchip_ram[0x26]=0x0b;
+ break;
+ case 2:
+ cchip_ram[0x2c]=0x3c;
+ cchip_ram[0x77]=0x04;
+ cchip_ram[0x25]=0x13;
+ cchip_ram[0x26]=0x0f;
+ break;
+ }
+ }
+ else
+ {
+ switch (cchip_ram[0x15]&3) // Dipswitch B
+ {
+ case 3:
+ cchip_ram[0x2c]=0x46;
+ cchip_ram[0x77]=0x05;
+ cchip_ram[0x25]=0x11;
+ cchip_ram[0x26]=0x0e;
+ break;
+ case 0:
+ cchip_ram[0x2c]=0x30;
+ cchip_ram[0x77]=0x06;
+ cchip_ram[0x25]=0x0b;
+ cchip_ram[0x26]=0x03;
+ break;
+ case 1:
+ cchip_ram[0x2c]=0x3a;
+ cchip_ram[0x77]=0x05;
+ cchip_ram[0x25]=0x0f;
+ cchip_ram[0x26]=0x09;
+ break;
+ case 2:
+ cchip_ram[0x2c]=0x4c;
+ cchip_ram[0x77]=0x04;
+ cchip_ram[0x25]=0x19;
+ cchip_ram[0x26]=0x11;
+ break;
+ };
+ }
+}
+
+/*************************************
+ *
+ * Writes to C-Chip - Important Bits
+ *
+ *************************************/
+
+WRITE16_HANDLER( 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).
+
+ cchip_ram[0x3d]=1;
+ cchip_ram[0x7a]=1;
+ updateDifficulty(0);
+}
+
+WRITE16_HANDLER( opwolf_cchip_bank_w )
+{
+ current_bank=data&7;
+}
+
+WRITE16_HANDLER( opwolf_cchip_data_w )
+{
+ cchip_ram[(current_bank * 0x400) + offset]=data&0xff;
+
+// if (offset!=0x64 && offset!=0x65 && offset!=0x66 && offset!=0x67 && offset!=0x68 && offset!=0x69)
+// logerror("%08x: opwolf c write %04x %04x\n", activecpu_get_pc(), offset,data);
+
+ if (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* rom=(UINT16*)memory_region(REGION_CPU1);
+ UINT32 coin_table[2]={0,0};
+ UINT8 coin_offset[2];
+ int slot;
+
+ if ((opwolf_region == OPWOLF_REGION_JAPAN) || (opwolf_region == OPWOLF_REGION_US))
+ {
+ coin_table[0] = 0x03ffce;
+ coin_table[1] = 0x03ffce;
+ }
+ if ((opwolf_region == OPWOLF_REGION_WORLD) || (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])
+ {
+ cchip_coins_for_credit[slot] = rom[(coin_table[slot] + coin_offset[slot] + 0) / 2] & 0xff;
+ cchip_credits_for_coin[slot] = rom[(coin_table[slot] + coin_offset[slot] + 2) / 2] & 0xff;
+ }
+ }
+#else
+ if ((opwolf_region == OPWOLF_REGION_JAPAN) || (opwolf_region == OPWOLF_REGION_US))
+ {
+ switch (data&0x30) /* table at 0x03ffce.w - 4 * 2 words (coins for credits first) - inverted order */
+ {
+ case 0x00: cchip_coins_for_credit[0]=2; cchip_credits_for_coin[0]=3; break;
+ case 0x10: cchip_coins_for_credit[0]=2; cchip_credits_for_coin[0]=1; break;
+ case 0x20: cchip_coins_for_credit[0]=1; cchip_credits_for_coin[0]=2; break;
+ case 0x30: 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: cchip_coins_for_credit[1]=2; cchip_credits_for_coin[1]=3; break;
+ case 0x40: cchip_coins_for_credit[1]=2; cchip_credits_for_coin[1]=1; break;
+ case 0x80: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=2; break;
+ case 0xc0: 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: cchip_coins_for_credit[0]=4; cchip_credits_for_coin[0]=1; break;
+ case 0x10: cchip_coins_for_credit[0]=3; cchip_credits_for_coin[0]=1; break;
+ case 0x20: cchip_coins_for_credit[0]=2; cchip_credits_for_coin[0]=1; break;
+ case 0x30: 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: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=6; break;
+ case 0x40: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=4; break;
+ case 0x80: cchip_coins_for_credit[1]=1; cchip_credits_for_coin[1]=3; break;
+ case 0xc0: 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_HANDLER( opwolf_cchip_status_r )
+{
+ /*
+ Bit 0x4 = Error signal
+ Bit 0x1 = Ready signal
+ */
+ return 0x1; /* Return 0x5 for C-Chip error */
+}
+
+READ16_HANDLER( opwolf_cchip_data_r )
+{
+// if (offset!=0x7f && offset!=0x1c && offset!=0x1d && offset!=0x1e && offset!=0x1f && offset!=0x20 && activecpu_get_pc()!=0xc18 && activecpu_get_pc()!=0xc2e && activecpu_get_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", activecpu_get_pc(), offset, current_bank);
+
+ return cchip_ram[(current_bank * 0x400) + offset];
+}
+
+/*************************************
+ *
+ * C-Chip Tick
+ *
+ *************************************/
+
+static TIMER_CALLBACK( cchip_timer )
+{
+ // Update input ports, these are used by both the 68k directly and by the c-chip
+ cchip_ram[0x4]=readinputportbytag("IN0");
+ cchip_ram[0x5]=readinputportbytag("IN1");
+
+ // Coin slots
+ if (cchip_ram[0x4]!=cchip_last_04)
+ {
+ int slot=-1;
+
+ if (cchip_ram[0x4]&1) slot=0;
+ if (cchip_ram[0x4]&2) slot=1;
+
+ if (slot != -1)
+ {
+ cchip_coins[slot]++;
+ if (cchip_coins[slot] >= cchip_coins_for_credit[slot])
+ {
+ cchip_ram[0x53]+=cchip_credits_for_coin[slot];
+ cchip_ram[0x51]=0x55;
+ cchip_ram[0x52]=0x55;
+ cchip_coins[slot]-=cchip_coins_for_credit[slot];
+ }
+ coin_counter_w(slot, 1);
+ }
+
+ if (cchip_ram[0x53]>9)
+ cchip_ram[0x53]=9;
+ }
+ cchip_last_04=cchip_ram[0x4];
+
+ // Service switch
+ if (cchip_ram[0x5]!=cchip_last_05)
+ {
+ if ((cchip_ram[0x5]&4)==0)
+ {
+ cchip_ram[0x53]++;
+ cchip_ram[0x51]=0x55;
+ cchip_ram[0x52]=0x55;
+ }
+ }
+ cchip_last_05=cchip_ram[0x5];
+
+ // Cchip handles coin lockout (68k flags error if more than 9 coins)
+ coin_lockout_w(1, cchip_ram[0x53]==9);
+ coin_lockout_w(0, cchip_ram[0x53]==9);
+ coin_counter_w(0, 0);
+ coin_counter_w(1, 0);
+
+ // Special handling for last level
+ if (cchip_ram[0x1b]==0x6)
+ {
+ // Check for triggering final helicopter (end boss)
+ if (c58a==0)
+ {
+ if ((cchip_ram[0x72]&0x7f) >= 8 && cchip_ram[0x74]==0 && cchip_ram[0x1c]==0 && cchip_ram[0x1d]==0 && cchip_ram[0x1f]==0)
+ {
+ cchip_ram[0x30]=1;
+ cchip_ram[0x74]=1;
+ c58a=1;
+ }
+ }
+
+ if (cchip_ram[0x1a]==0x90)
+ cchip_ram[0x74]=0;
+
+ if (c58a!=0)
+ {
+ if (c589==0 && cchip_ram[0x27]==0 && cchip_ram[0x75]==0 && cchip_ram[0x1c]==0 && cchip_ram[0x1d]==0 && cchip_ram[0x1e]==0 && cchip_ram[0x1f]==0)
+ {
+ cchip_ram[0x31]=1;
+ cchip_ram[0x75]=1;
+ c589=1;
+ }
+ }
+
+ if (cchip_ram[0x2b]==0x1)
+ {
+ cchip_ram[0x2b]=0;
+
+ if (cchip_ram[0x30]==0x1)
+ {
+ if (cchip_ram[0x1a]!=0x90)
+ cchip_ram[0x1a]--;
+ }
+
+ if (cchip_ram[0x72]==0x9)
+ {
+ if (cchip_ram[0x76]!=0x4)
+ {
+ cchip_ram[0x76]=3;
+ }
+ }
+ else
+ {
+ // This timer is derived from the bootleg rather than the real board, I'm not 100% sure about it
+ c588|=0x80;
+
+ cchip_ram[0x72]=c588;
+ c588++;
+
+ cchip_ram[0x1a]--;
+ cchip_ram[0x1a]--;
+ cchip_ram[0x1a]--;
+ }
+ }
+
+ // Update difficulty settings
+ if (cchip_ram[0x76]==0)
+ {
+ cchip_ram[0x76]=1;
+ updateDifficulty(1);
+ }
+ }
+
+ // These variables are cleared every frame during attract mode and the intro.
+ if (cchip_ram[0x34] < 2)
+ {
+ updateDifficulty(0);
+ cchip_ram[0x76]=0;
+ cchip_ram[0x75]=0;
+ cchip_ram[0x74]=0;
+ cchip_ram[0x72]=0;
+ cchip_ram[0x71]=0;
+ cchip_ram[0x70]=0;
+ cchip_ram[0x66]=0;
+ cchip_ram[0x2b]=0;
+ cchip_ram[0x30]=0;
+ cchip_ram[0x31]=0;
+ cchip_ram[0x32]=0;
+ cchip_ram[0x27]=0;
+ c588=0;
+ c589=0;
+ c58a=0;
+ }
+
+ // Check for level completion (all enemies destroyed)
+ if (cchip_ram[0x1c] == 0 && cchip_ram[0x1d] == 0 && cchip_ram[0x1e] == 0 && cchip_ram[0x1f] == 0 && cchip_ram[0x20] == 0)
+ {
+ // Special handling for end of level 6
+ if (cchip_ram[0x1b]==0x6)
+ {
+ // Don't signal end of level until final boss is destroyed
+ if (cchip_ram[0x27]==0x1)
+ cchip_ram[0x32]=1;
+ }
+ else
+ {
+ // Signal end of level
+ cchip_ram[0x32]=1;
+ }
+ }
+
+ if (cchip_ram[0xe] == 1)
+ {
+ cchip_ram[0xe]=0xfd;
+ cchip_ram[0x61]=0x04;
+ }
+
+ // Access level data command (address 0xf5 goes from 1 -> 0)
+ if (cchip_ram[0x7a]==0 && cchip_last_7a!=0 && current_cmd!=0xf5)
+ {
+ // Simulate time for command to execute (exact timing unknown, this is close)
+ current_cmd=0xf5;
+ timer_set(ATTOTIME_IN_CYCLES(80000,0), 0, timer_callback);
+ }
+ cchip_last_7a=cchip_ram[0x7a];
+
+ // This seems to some kind of periodic counter - results are expected
+ // by the 68k when the counter reaches 0xa
+ if (cchip_ram[0x7f]==0xa)
+ {
+ cchip_ram[0xfe]=0xf7;
+ cchip_ram[0xff]=0x6e;
+ }
+
+ // These are set every frame
+ cchip_ram[0x64]=0;
+ cchip_ram[0x66]=0;
+}
+
+/*************************************
+ *
+ * C-Chip State Saving
+ *
+ *************************************/
+
+void opwolf_cchip_init(void)
+{
+ cchip_ram=auto_malloc(0x400 * 8);
+
+ state_save_register_global(current_bank);
+ state_save_register_global(current_cmd);
+ state_save_register_global(cchip_last_7a);
+ state_save_register_global(cchip_last_04);
+ state_save_register_global(cchip_last_05);
+ state_save_register_global(c588);
+ state_save_register_global(c589);
+ state_save_register_global(c58a);
+ state_save_register_global(cchip_coins[0]);
+ state_save_register_global(cchip_coins[1]);
+ state_save_register_global(cchip_coins_for_credit[0]);
+ state_save_register_global(cchip_credits_for_coin[0]);
+ state_save_register_global(cchip_coins_for_credit[1]);
+ state_save_register_global(cchip_credits_for_coin[1]);
+ state_save_register_global_pointer(cchip_ram, 0x400 * 8);
+
+ cchip_last_7a=0;
+ cchip_last_04=0xfc;
+ cchip_last_05=0xff;
+ cchip_coins[0]=0;
+ cchip_coins[1]=0;
+ cchip_coins_for_credit[0]=1;
+ cchip_credits_for_coin[0]=1;
+ cchip_coins_for_credit[1]=1;
+ cchip_credits_for_coin[1]=1;
+
+ timer_pulse(ATTOTIME_IN_HZ(60), 0, cchip_timer);
+}
diff --git a/src/mame/machine/pacplus.c b/src/mame/machine/pacplus.c
new file mode 100644
index 00000000000..1791c2a5ab5
--- /dev/null
+++ b/src/mame/machine/pacplus.c
@@ -0,0 +1,56 @@
+#include "driver.h"
+#include "includes/pacman.h"
+
+
+static UINT8 decrypt(int addr, UINT8 e)
+{
+ static const UINT8 swap_xor_table[6][9] =
+ {
+ { 7,6,5,4,3,2,1,0, 0x00 },
+ { 7,6,5,4,3,2,1,0, 0x28 },
+ { 6,1,3,2,5,7,0,4, 0x96 },
+ { 6,1,5,2,3,7,0,4, 0xbe },
+ { 0,3,7,6,4,2,1,5, 0xd5 },
+ { 0,3,4,6,7,2,1,5, 0xdd }
+ };
+ static const int picktable[32] =
+ {
+ 0,2,4,2,4,0,4,2,2,0,2,2,4,0,4,2,
+ 2,2,4,0,4,2,4,0,0,4,0,4,4,2,4,2
+ };
+ UINT32 method = 0;
+ const UINT8 *tbl;
+
+
+ /* pick method from bits 0 2 5 7 9 of the address */
+ method = picktable[
+ (addr & 0x001) |
+ ((addr & 0x004) >> 1) |
+ ((addr & 0x020) >> 3) |
+ ((addr & 0x080) >> 4) |
+ ((addr & 0x200) >> 5)];
+
+ /* switch method if bit 11 of the address is set */
+ if ((addr & 0x800) == 0x800)
+ method ^= 1;
+
+ tbl = swap_xor_table[method];
+ return BITSWAP8(e,tbl[0],tbl[1],tbl[2],tbl[3],tbl[4],tbl[5],tbl[6],tbl[7]) ^ tbl[8];
+}
+
+
+void pacplus_decode(void)
+{
+ int i;
+ UINT8 *RAM;
+
+ /* CPU ROMs */
+
+ RAM = memory_region(REGION_CPU1);
+ for (i = 0; i < 0x4000; i++)
+ {
+ RAM[i] = decrypt(i,RAM[i]);
+ }
+}
+
+
diff --git a/src/mame/machine/pckeybrd.c b/src/mame/machine/pckeybrd.c
new file mode 100644
index 00000000000..929b9089cb1
--- /dev/null
+++ b/src/mame/machine/pckeybrd.c
@@ -0,0 +1,1264 @@
+/**********************************************************************
+
+ pckeybrd.c
+
+ PC-style keyboard emulation
+
+ This emulation is decoupled from the AT 8042 emulation used in the
+ IBM ATs and above
+
+**********************************************************************/
+
+/* Todo: (added by KT 22-Jun-2000
+ 1. Check scancodes I have added are the actual scancodes for set 2 or 3.
+ 2. Check how codes are changed based on Shift/Control states for those sets
+ that require it - info in Help PC!
+
+*/
+
+#include "driver.h"
+#include "machine/pckeybrd.h"
+
+#ifdef MESS
+#include "inputx.h"
+#endif /* MESS */
+
+/* AT keyboard documentation comes from www.beyondlogic.org and HelpPC documentation */
+
+/* to enable logging of keyboard read/writes */
+#define LOG_KEYBOARD 0
+
+
+/*
+ The PS/2 models have three make/break scan code sets. The first
+ set matches the PC & XT make/break scan code set and is the one
+ listed here. Scan code sets are selected by writing the value F0
+ to the keyboard via the ~8042~ (port 60h). The following is a brief
+ description of the scan code sets (see the PS/2 Technical Reference
+ manuals for more information on scan code sets 2 and 3):
+
+ * set 1, each key has a base scan code. Some keys generate
+ extra scan codes to generate artificial shift states. This
+ is similar to the standard scan code set used on the PC and XT.
+ * set 2, each key sends one make scan code and two break scan
+ codes bytes (F0 followed by the make code). This scan code
+ set is available on the IBM AT also.
+ * set 3, each key sends one make scan code and two break scan
+ codes bytes (F0 followed by the make code) and no keys are
+ altered by Shift/Alt/Ctrl keys.
+ * typematic scan codes are the same as the make scan code
+
+*/
+
+
+/* using the already existing input port definitions, this table re-maps
+to scancode set 3.
+I don't have the details for scan-code set 2,3 but they sound very similar
+to the scancode set I have here. - KT 22/Jun/2000 */
+
+
+/* key set 3 */
+static int at_keyboard_scancode_set_2_3[]=
+{
+ 0,
+ 0x076,
+ 0x016,
+ 0x01e,
+ 0x026,
+ 0x025,
+ 0x02e,
+ 0x036,
+ 0x03d,
+ 0x03e,
+ 0x046,
+ 0x045,
+ 0x04e,
+ 0x055,
+ 0x066,
+ 0x00d,
+ 0x015,
+ 0x01d,
+ 0x024,
+ 0x02d,
+ 0x02c,
+ 0x035,
+ 0x03c,
+ 0x043,
+ 0x044,
+ 0x04d,
+ 0x054,
+ 0x05b,
+ 0x05a,
+ 0x014,
+ 0x01c,
+ 0x01b,
+ 0x023,
+ 0x02b,
+ 0x034,
+ 0x033,
+ 0x03b,
+ 0x042,
+ 0x04b,
+ 0x04c,
+ 0x052,
+ 0x00e,
+ 0x012,
+ 0x05d,
+ 0x01a,
+ 0x022,
+ 0x021,
+ 0x02a,
+ 0x032,
+ 0x031,
+ 0x03a,
+ 0x041,
+ 0x049,
+ 0x04a,
+ 0x059,
+ 0x000,
+ 0x011,
+ 0x029,
+ 0x058,
+ 0x05,
+ 0x06,
+ 0x04,
+ 0x0c,
+ 0x03,
+ 0x0b,
+ 0x083,
+ 0x0a,
+ 0x01,
+ 0x09,
+ 0x077,
+ 0x07e,
+ 0x06c,
+ 0x075,
+ 0x07d,
+ 0x07b,
+ 0x06b,
+ 0x073,
+ 0x074,
+ 0x079,
+ 0x069,
+ 0x072,
+ 0x07a,
+ 0x070,
+ 0x071,
+ 0x00,
+ 0x00,
+ 0x078,
+ 0x07,
+ 0x05a,
+ 0x014,
+ 0x04a,
+ 0x000,
+ 0x011,
+ 0x06c,
+ 0x075,
+ 0x07d,
+ 0x06b,
+ 0x074,
+ 0x069,
+ 0x072,
+ 0x07a,
+ 0x070,
+ 0x071,
+ 0x000,
+ 0x000,
+ 0x000
+};
+
+
+#define AT_KEYBOARD_QUEUE_MAXSIZE 256
+
+typedef struct at_keyboard
+{
+ AT_KEYBOARD_TYPE type;
+ int on;
+ UINT8 delay; /* 240/60 -> 0,25s */
+ UINT8 repeat; /* 240/ 8 -> 30/s */
+ int numlock;
+ UINT8 queue[AT_KEYBOARD_QUEUE_MAXSIZE];
+ UINT8 head;
+ UINT8 tail;
+ UINT8 make[128];
+
+ int input_state;
+ int scan_code_set;
+ int last_code;
+
+ int ports[8];
+} at_keyboard;
+
+static at_keyboard keyboard;
+
+typedef struct extended_keyboard_code
+{
+ const char *pressed;
+ const char *released;
+} extended_keyboard_code;
+
+
+static extended_keyboard_code keyboard_mf2_code[0x10][2/*numlock off, on*/]={
+ { { "\xe0\x1c", "\xe0\x9c" } }, // keypad enter
+ { { "\xe0\x1d", "\xe0\x9d" } }, // right control
+ { { "\xe0\x35", "\xe0\xb5" } },
+ { { "\xe0\x37", "\xe0\xb7" } },
+ { { "\xe0\x38", "\xe0\xb8" } },
+ { { "\xe0\x47", "\xe0\xc7" }, { "\xe0\x2a\xe0\x47", "\xe0\xc7\xe0\xaa" } },
+ { { "\xe0\x48", "\xe0\xc8" }, { "\xe0\x2a\xe0\x48", "\xe0\xc8\xe0\xaa" } },
+ { { "\xe0\x49", "\xe0\xc9" }, { "\xe0\x2a\xe0\x49", "\xe0\xc9\xe0\xaa" } },
+ { { "\xe0\x4b", "\xe0\xcb" }, { "\xe0\x2a\xe0\x4b", "\xe0\xcb\xe0\xaa" } },
+ { { "\xe0\x4d", "\xe0\xcd" }, { "\xe0\x2a\xe0\x4d", "\xe0\xcd\xe0\xaa" } },
+ { { "\xe0\x4f", "\xe0\xcf" }, { "\xe0\x2a\xe0\x4f", "\xe0\xcf\xe0\xaa" } },
+ { { "\xe0\x50", "\xe0\xd0" }, { "\xe0\x2a\xe0\x50", "\xe0\xd0\xe0\xaa" } },
+ { { "\xe0\x51", "\xe0\xd1" }, { "\xe0\x2a\xe0\x51", "\xe0\xd1\xe0\xaa" } },
+ { { "\xe0\x52", "\xe0\xd2" }, { "\xe0\x2a\xe0\x52", "\xe0\xd2\xe0\xaa" } },
+ { { "\xe0\x53", "\xe0\xd3" }, { "\xe0\x2a\xe0\x53", "\xe0\xd3\xe0\xaa" } },
+ { { "\xe1\x1d\x45\xe1\x9d\xc5" }, { "\xe0\x2a\xe1\x1d\x45\xe1\x9d\xc5" } }
+};
+
+/* I don't think these keys change if num-lock is active! */
+/* pc-at extended keyboard make/break codes for code set 3 */
+static extended_keyboard_code at_keyboard_extended_codes_set_2_3[]=
+{
+ /*keypad enter */
+ {
+ "\xe0\x5a",
+ "\xe0\xf0\x5a"
+ },
+ /* right control */
+ {
+ "\xe0\x14",
+ "\xe0\xf0\x14"
+ },
+ /* keypad slash */
+ {
+ "\xe0\x4a",
+ "\xe0\xf0\x4a"
+ },
+ /* print screen */
+ {
+ "\xe0\x12\xe0\x7c",
+ 0, /* I don't know the break sequence */
+
+ },
+ /* right alt */
+ {
+ "\xe0\x11",
+ "\xe0\xf0\x11"
+ },
+ /* home */
+ {
+ "\xe0\x6c",
+ "\xe0\xf0\x6c"
+ },
+ /* cursor up */
+ {
+ "\xe0\x75",
+ "\xe0\xf0\x75"
+ },
+ /* page up */
+ {
+ "\xe0\x7d",
+ "\xe0\xf0\x7d"
+ },
+ /* cursor left */
+ {
+ "\xe0\x6b",
+ "\xe0\xf0\x6b",
+ },
+ /* cursor right */
+ {
+ "\xe0\x74",
+ "\xe0\xf0\x74"
+ },
+ /* end */
+ {
+ "\xe0\x69",
+ "\xe0\xf0\x69",
+ },
+ /* cursor down */
+ {
+ "\xe0\x72",
+ "\xe0\xf0\x72"
+ },
+ /* page down */
+ {
+ "\xe0\x7a",
+ "\xe0\xf0\x7a"
+ },
+ /* insert */
+ {
+ "\xe0\x70",
+ "\xe0\xf0\x70",
+ },
+ /* delete */
+ {
+ "\xe0\x71",
+ "\xe0\xf0\x71"
+ },
+ /* pause */
+ {
+ "\xe1\x14\x77\xe1\xf0\x14\xf0\x77",
+ 0, /*?? I don't know the break sequence */
+ }
+
+};
+
+static void at_keyboard_queue_insert(UINT8 data);
+
+#ifdef MESS
+static int at_keyboard_queue_size(void);
+static int at_keyboard_queue_chars(const unicode_char *text, size_t text_len);
+static int at_keyboard_accept_char(unicode_char ch);
+static int at_keyboard_charqueue_empty(void);
+#endif
+
+
+
+void at_keyboard_init(AT_KEYBOARD_TYPE type)
+{
+ int i;
+ char buf[32];
+
+ memset(&keyboard, 0, sizeof(keyboard));
+ keyboard.type = type;
+ keyboard.on = 1;
+ keyboard.delay = 60;
+ keyboard.repeat = 8;
+ keyboard.numlock = 0;
+ keyboard.head = keyboard.tail = 0;
+ keyboard.input_state = 0;
+ memset(&keyboard.make[0], 0, sizeof(UINT8)*128);
+ /* set default led state */
+ set_led_status(2, 0);
+ set_led_status(0, 0);
+ set_led_status(1, 0);
+
+ keyboard.scan_code_set = 3;
+
+ /* locate the keyboard ports */
+ for (i = 0; i < sizeof(keyboard.ports) / sizeof(keyboard.ports[0]); i++)
+ {
+ sprintf(buf, "pc_keyboard_%d", i);
+ keyboard.ports[i] = port_tag_to_index(buf);
+ }
+
+#ifdef MESS
+ inputx_setup_natural_keyboard(at_keyboard_queue_chars,
+ at_keyboard_accept_char,
+ at_keyboard_charqueue_empty);
+#endif
+}
+
+
+
+void at_keyboard_reset(void)
+{
+ keyboard.head = keyboard.tail = 0;
+ keyboard.input_state = 0;
+ memset(&keyboard.make[0], 0, sizeof(UINT8)*128);
+ /* set default led state */
+ set_led_status(2, 0);
+ set_led_status(0, 0);
+ set_led_status(1, 0);
+
+ keyboard.scan_code_set=1;
+ at_keyboard_queue_insert(0xaa);
+}
+
+/* set initial scan set */
+void at_keyboard_set_scan_code_set(int set)
+{
+ keyboard.scan_code_set = set;
+}
+
+
+
+/* insert a code into the buffer */
+static void at_keyboard_queue_insert(UINT8 data)
+{
+ if (LOG_KEYBOARD)
+ logerror("keyboard queueing %.2x\n",data);
+
+ keyboard.queue[keyboard.head] = data;
+ keyboard.head++;
+ keyboard.head %= (sizeof(keyboard.queue) / sizeof(keyboard.queue[0]));
+}
+
+
+#ifdef MESS
+static int at_keyboard_queue_size(void)
+{
+ int queue_size;
+ queue_size = keyboard.head - keyboard.tail;
+ if (queue_size < 0)
+ queue_size += sizeof(keyboard.queue) / sizeof(keyboard.queue[0]);
+ return queue_size;
+}
+#endif
+
+
+/* add a list of codes to the keyboard buffer */
+static void at_keyboard_helper(const char *codes)
+{
+ int i;
+ for (i = 0; codes[i]; i++)
+ at_keyboard_queue_insert(codes[i]);
+}
+
+
+/* add codes for standard keys */
+static void at_keyboard_standard_scancode_insert(int our_code, int pressed)
+{
+ int scancode = our_code;
+
+ switch (keyboard.scan_code_set)
+ {
+ case 1:
+ {
+ /* the original code was designed for this set, and there is
+ a 1:1 correspondance for the scancodes */
+ scancode = our_code;
+
+ if (!pressed)
+ {
+ /* adjust code for break code */
+ scancode|=0x080;
+ }
+ }
+ break;
+
+ case 2:
+ case 3:
+ {
+ /* lookup scancode */
+ scancode = at_keyboard_scancode_set_2_3[our_code];
+
+ if (!pressed)
+ {
+ /* break code */
+ at_keyboard_queue_insert(0x0f0);
+ }
+
+ }
+ break;
+ }
+
+ at_keyboard_queue_insert(scancode);
+}
+
+static void at_keyboard_extended_scancode_insert(int code, int pressed)
+{
+ code = code - 0x060;
+
+ switch (keyboard.scan_code_set)
+ {
+ case 1:
+ {
+ if (pressed)
+ {
+ if (keyboard_mf2_code[code][keyboard.numlock].pressed)
+ at_keyboard_helper(keyboard_mf2_code[code][keyboard.numlock].pressed);
+ else
+ at_keyboard_helper(keyboard_mf2_code[code][0].pressed);
+ }
+ else
+ {
+ if (keyboard_mf2_code[code][keyboard.numlock].released)
+ at_keyboard_helper(keyboard_mf2_code[code][keyboard.numlock].released);
+ else if (keyboard_mf2_code[code][0].released)
+ at_keyboard_helper(keyboard_mf2_code[code][0].released);
+ }
+ }
+ break;
+
+ case 2:
+ case 3:
+ {
+ extended_keyboard_code *key = &at_keyboard_extended_codes_set_2_3[code];
+
+ if (pressed)
+ {
+ if (key->pressed)
+ {
+ at_keyboard_helper(key->pressed);
+ }
+ }
+ else
+ {
+ if (key->released)
+ {
+ at_keyboard_helper(key->released);
+ }
+ }
+ }
+ break;
+ }
+
+}
+
+
+/**************************************************************************
+ * scan keys and stuff make/break codes
+ **************************************************************************/
+
+static UINT32 at_keyboard_readport(int port)
+{
+ UINT32 result = 0;
+ if (keyboard.ports[port] >= 0)
+ result = readinputport(keyboard.ports[port]);
+ return result;
+}
+
+void at_keyboard_polling(void)
+{
+ int i;
+
+ if (keyboard.on)
+ {
+ /* add codes for keys that are set */
+ for( i = 0x01; i < 0x80; i++ )
+ {
+ if (i==0x60) i+=0x10; // keys 0x60..0x6f need special handling
+
+ if( at_keyboard_readport(i/16) & (1 << (i & 15)) )
+ {
+ if( keyboard.make[i] == 0 )
+ {
+ keyboard.make[i] = 1;
+
+ if (i==0x45) keyboard.numlock^=1;
+
+ at_keyboard_standard_scancode_insert(i,1);
+ }
+ else
+ {
+ keyboard.make[i] += 1;
+
+ if( keyboard.make[i] == keyboard.delay )
+ {
+ at_keyboard_standard_scancode_insert(i, 1);
+ }
+ else
+ {
+ if( keyboard.make[i] == keyboard.delay + keyboard.repeat )
+ {
+ keyboard.make[i] = keyboard.delay;
+ at_keyboard_standard_scancode_insert(i, 1);
+ }
+ }
+ }
+ }
+ else
+ {
+ if( keyboard.make[i] )
+ {
+ keyboard.make[i] = 0;
+
+ at_keyboard_standard_scancode_insert(i, 0);
+ }
+ }
+ }
+
+ /* extended scan-codes */
+ for( i = 0x60; i < 0x70; i++ )
+ {
+ if( at_keyboard_readport(i/16) & (1 << (i & 15)) )
+ {
+ if( keyboard.make[i] == 0 )
+ {
+ keyboard.make[i] = 1;
+
+ at_keyboard_extended_scancode_insert(i,1);
+
+ }
+ else
+ {
+ keyboard.make[i] += 1;
+ if( keyboard.make[i] == keyboard.delay )
+ {
+ at_keyboard_extended_scancode_insert(i, 1);
+ }
+ else
+ {
+ if( keyboard.make[i] == keyboard.delay + keyboard.repeat )
+ {
+ keyboard.make[i]=keyboard.delay;
+
+ at_keyboard_extended_scancode_insert(i, 1);
+ }
+ }
+ }
+ }
+ else
+ {
+ if( keyboard.make[i] )
+ {
+ keyboard.make[i] = 0;
+
+ at_keyboard_extended_scancode_insert(i,0);
+ }
+ }
+ }
+ }
+}
+
+int at_keyboard_read(void)
+{
+ int data;
+ if (keyboard.tail == keyboard.head)
+ return -1;
+
+ data = keyboard.queue[keyboard.tail];
+
+ if (LOG_KEYBOARD)
+ logerror("at_keyboard_read(): Keyboard Read 0x%02x\n",data);
+
+ keyboard.tail++;
+ keyboard.tail %= sizeof(keyboard.queue) / sizeof(keyboard.queue[0]);
+ return data;
+}
+
+static void at_clear_buffer_and_acknowledge(void)
+{
+ /* clear output buffer and respond with acknowledge */
+ keyboard.head = keyboard.tail = 0;
+ at_keyboard_queue_insert(0x0fa);
+}
+
+/* From Ralf Browns Interrupt list:
+
+Values for keyboard commands (data also goes to PORT 0060h):
+Value Count Description
+ EDh double set/reset mode indicators Caps Num Scrl
+ bit 2 = CapsLk, bit 1 = NumLk, bit 0 = ScrlLk
+ all other bits must be zero.
+ EEh sngl diagnostic echo. returns EEh.
+ EFh sngl NOP (No OPeration). reserved for future use
+ EF+26h double [Cherry MF2 G80-1501HAD] read 256 bytes of chipcard data
+ keyboard must be disabled before this and has to
+ be enabled after finished.
+ F0h double get/set scan code set
+ 00h get current set
+ 01h scancode set 1 (PCs and PS/2 mod 30, except Type 2 ctrlr)
+
+ 02h scancode set 2 (ATs, PS/2, default)
+ 03h scancode set 3
+ F2h sngl read keyboard ID (read two ID bytes)
+ AT keyboards returns FA (ACK)
+ MF2 returns AB 41 (translation) or
+ AB 83 (pass through)
+ F3h double set typematic rate/delay
+ format of the second byte:
+ bit7=0 : reserved
+ bit6-5 : typemativ delay
+ 00b=250ms 10b= 750ms
+ 01b=500ms 11b=1000ms
+ bit4-0 : typematic rate (see #P050)
+ F4h sngl enable keyboard
+ F5h sngl disable keyboard. set default parameters (no keyboard scanning)
+ F6h sngl set default parameters
+ F7h sngl [MCA] set all keys to typematic (scancode set 3)
+
+ F8h sngl [MCA] set all keys to make/release
+ F9h sngl [MCA] set all keys to make only
+ FAh sngl [MCA] set all keys to typematic/make/release
+ FBh sngl [MCA] set al keys to typematic
+ FCh double [MCA] set specific key to make/release
+ FDh double [MCA] set specific key to make only
+ FEh sngl resend last scancode
+ FFh sngl perform internal power-on reset function
+Note: each command is acknowledged by FAh (ACK), if not mentioned otherwise.
+ See PORT 0060h-R for details.
+SeeAlso: #P046
+*/
+
+void at_keyboard_write(UINT8 data)
+{
+ if (LOG_KEYBOARD)
+ logerror("keyboard write %.2x\n",data);
+
+ switch (keyboard.input_state)
+ {
+ case 0:
+ switch (data) {
+ case 0xed: // leds schalten
+ /* acknowledge */
+ at_keyboard_queue_insert(0x0fa);
+ /* now waiting for code... */
+ keyboard.input_state=1;
+ break;
+ case 0xee: // echo
+ /* echo code with no acknowledge */
+ at_keyboard_queue_insert(0xee);
+ break;
+ case 0xf0: // scancodes adjust
+ /* acknowledge */
+ at_clear_buffer_and_acknowledge();
+ /* waiting for data */
+ keyboard.input_state=2;
+ break;
+ case 0xf2: // identify keyboard
+ /* ack and two byte keyboard id */
+ at_keyboard_queue_insert(0xfa);
+
+ /* send keyboard code */
+ if (keyboard.type == AT_KEYBOARD_TYPE_MF2) {
+ at_keyboard_queue_insert(0xab);
+ at_keyboard_queue_insert(0x41);
+ }
+ else
+ {
+ /* from help-pc docs */
+ at_keyboard_queue_insert(0x0ab);
+ at_keyboard_queue_insert(0x083);
+ }
+
+ break;
+ case 0xf3: // adjust rates
+ /* acknowledge */
+ at_keyboard_queue_insert(0x0fa);
+
+ keyboard.input_state=3;
+ break;
+ case 0xf4: // activate
+ at_clear_buffer_and_acknowledge();
+
+ keyboard.on=1;
+ break;
+ case 0xf5:
+ /* acknowledge */
+ at_clear_buffer_and_acknowledge();
+ // standardvalues
+ keyboard.on=0;
+ break;
+ case 0xf6:
+ at_clear_buffer_and_acknowledge();
+ // standardvalues
+ keyboard.on=1;
+ break;
+ case 0xfe: // resend
+ // should not happen, for now send 0
+ at_keyboard_queue_insert(0); //keyboard.last_code);
+ break;
+ case 0xff: // reset
+ /* it doesn't state this in the docs I have read, but I assume
+ that the keyboard input buffer is cleared. The PCW16 sends &ff,
+ and requires that 0x0fa is the first byte to be read */
+
+ at_clear_buffer_and_acknowledge();
+
+ // /* acknowledge */
+ // at_keyboard_queue_insert(0xfa);
+ /* BAT completion code */
+ at_keyboard_queue_insert(0xaa);
+ break;
+ }
+ break;
+ case 1:
+ /* code received */
+ keyboard.input_state=0;
+
+ /* command? */
+ if (data & 0x080)
+ {
+ /* command received instead of code - execute command */
+ at_keyboard_write(data);
+ }
+ else
+ {
+ /* send acknowledge */
+ at_keyboard_queue_insert(0x0fa);
+
+ /* led bits */
+ /* bits: 0 scroll lock, 1 num lock, 2 capslock */
+
+ /* led's in same order as my keyboard leds. */
+ /* num lock, caps lock, scroll lock */
+ set_led_status(2, (data & 0x01));
+ set_led_status(0, ((data & 0x02)>>1));
+ set_led_status(1, ((data & 0x04)>>2));
+
+ }
+ break;
+ case 2:
+ keyboard.input_state=0;
+
+ /* command? */
+ if (data & 0x080)
+ {
+ /* command received instead of code - execute command */
+ at_keyboard_write(data);
+ }
+ else
+ {
+ /* 00 return byte indicating scan code set in use
+ 01 select scan code set 1 (used on PC & XT)
+ 02 select scan code set 2
+ 03 select scan code set 3
+ */
+
+ if (data == 0x00)
+ {
+ at_keyboard_queue_insert(keyboard.scan_code_set);
+ }
+ else
+ {
+ keyboard.scan_code_set = data;
+ }
+ }
+
+ break;
+ case 3:
+ /* 6,5: 250ms, 500ms, 750ms, 1s */
+ /* 4..0: 30 26.7 .... 2 chars/s*/
+
+ /* command? */
+ keyboard.input_state=0;
+ if (data & 0x080)
+ {
+ /* command received instead of code - execute command */
+ at_keyboard_write(data);
+ }
+ else
+ {
+ /* received keyboard repeat */
+
+ }
+
+ break;
+ }
+}
+
+#ifdef MESS
+/***************************************************************************
+ unicode_char_to_at_keycode
+***************************************************************************/
+
+static UINT8 unicode_char_to_at_keycode(unicode_char ch)
+{
+ UINT8 b;
+ switch(ch)
+ {
+ case '\033': b = 1; break;
+ case '1': b = 2; break;
+ case '2': b = 3; break;
+ case '3': b = 4; break;
+ case '4': b = 5; break;
+ case '5': b = 6; break;
+ case '6': b = 7; break;
+ case '7': b = 8; break;
+ case '8': b = 9; break;
+ case '9': b = 10; break;
+ case '0': b = 11; break;
+ case '-': b = 12; break;
+ case '=': b = 13; break;
+ case '\010': b = 14; break;
+ case '\t': b = 15; break;
+ case 'q': b = 16; break;
+ case 'w': b = 17; break;
+ case 'e': b = 18; break;
+ case 'r': b = 19; break;
+ case 't': b = 20; break;
+ case 'y': b = 21; break;
+ case 'u': b = 22; break;
+ case 'i': b = 23; break;
+ case 'o': b = 24; break;
+ case 'p': b = 25; break;
+ case '[': b = 26; break;
+ case ']': b = 27; break;
+ case '\r': b = 28; break;
+ case UCHAR_MAMEKEY(CAPSLOCK): b = 29; break;
+ case 'a': b = 30; break;
+ case 's': b = 31; break;
+ case 'd': b = 32; break;
+ case 'f': b = 33; break;
+ case 'g': b = 34; break;
+ case 'h': b = 35; break;
+ case 'j': b = 36; break;
+ case 'k': b = 37; break;
+ case 'l': b = 38; break;
+ case ';': b = 39; break;
+ case '\'': b = 40; break;
+ case '`': b = 41; break;
+ case '\\': b = 43; break;
+ case 'z': b = 44; break;
+ case 'x': b = 45; break;
+ case 'c': b = 46; break;
+ case 'v': b = 47; break;
+ case 'b': b = 48; break;
+ case 'n': b = 49; break;
+ case 'm': b = 50; break;
+ case ',': b = 51; break;
+ case '.': b = 52; break;
+ case '/': b = 53; break;
+ case ' ': b = 0x39; break;
+ case UCHAR_MAMEKEY(F1): b = 0x3b; break;
+ case UCHAR_MAMEKEY(F2): b = 0x3c; break;
+ case UCHAR_MAMEKEY(F3): b = 0x3d; break;
+ case UCHAR_MAMEKEY(F4): b = 0x3e; break;
+ case UCHAR_MAMEKEY(F5): b = 0x3f; break;
+ case UCHAR_MAMEKEY(F6): b = 0x40; break;
+ case UCHAR_MAMEKEY(F7): b = 0x41; break;
+ case UCHAR_MAMEKEY(F8): b = 0x42; break;
+ case UCHAR_MAMEKEY(F9): b = 0x43; break;
+ case UCHAR_MAMEKEY(F10): b = 0x44; break;
+ case UCHAR_MAMEKEY(NUMLOCK): b = 0x45; break;
+ case UCHAR_MAMEKEY(SCRLOCK): b = 0x46; break;
+ case UCHAR_MAMEKEY(7_PAD): b = 0x47; break;
+ case UCHAR_MAMEKEY(8_PAD): b = 0x48; break;
+ case UCHAR_MAMEKEY(9_PAD): b = 0x49; break;
+ case UCHAR_MAMEKEY(MINUS_PAD): b = 0x4a; break;
+ case UCHAR_MAMEKEY(4_PAD): b = 0x4b; break;
+ case UCHAR_MAMEKEY(5_PAD): b = 0x4c; break;
+ case UCHAR_MAMEKEY(6_PAD): b = 0x4d; break;
+ case UCHAR_MAMEKEY(PLUS_PAD): b = 0x4e; break;
+ case UCHAR_MAMEKEY(1_PAD): b = 0x4f; break;
+ case UCHAR_MAMEKEY(2_PAD): b = 0x50; break;
+ case UCHAR_MAMEKEY(3_PAD): b = 0x51; break;
+ case UCHAR_MAMEKEY(0_PAD): b = 0x52; break;
+ case UCHAR_MAMEKEY(DEL_PAD): b = 0x53; break;
+ case UCHAR_MAMEKEY(F11): b = 0x57; break;
+ case UCHAR_MAMEKEY(F12): b = 0x58; break;
+ case '~': b = 0x81; break;
+ case '!': b = 0x82; break;
+ case '@': b = 0x83; break;
+ case '#': b = 0x84; break;
+ case '$': b = 0x85; break;
+ case '%': b = 0x86; break;
+ case '^': b = 0x87; break;
+ case '&': b = 0x88; break;
+ case '*': b = 0x89; break;
+ case '(': b = 0x8a; break;
+ case ')': b = 0x8b; break;
+ case '_': b = 0x8c; break;
+ case '+': b = 0x8d; break;
+ case 'Q': b = 0x90; break;
+ case 'W': b = 0x91; break;
+ case 'E': b = 0x92; break;
+ case 'R': b = 0x93; break;
+ case 'T': b = 0x94; break;
+ case 'Y': b = 0x95; break;
+ case 'U': b = 0x96; break;
+ case 'I': b = 0x97; break;
+ case 'O': b = 0x98; break;
+ case 'P': b = 0x99; break;
+ case '{': b = 0x9a; break;
+ case '}': b = 0x9b; break;
+ case 'A': b = 0x9e; break;
+ case 'S': b = 0x9f; break;
+ case 'D': b = 0xa0; break;
+ case 'F': b = 0xa1; break;
+ case 'G': b = 0xa2; break;
+ case 'H': b = 0xa3; break;
+ case 'J': b = 0xa4; break;
+ case 'K': b = 0xa5; break;
+ case 'L': b = 0xa6; break;
+ case ':': b = 0xa7; break;
+ case '\"': b = 0xa8; break;
+ case '|': b = 0xab; break;
+ case 'Z': b = 0xac; break;
+ case 'X': b = 0xad; break;
+ case 'C': b = 0xae; break;
+ case 'V': b = 0xaf; break;
+ case 'B': b = 0xb0; break;
+ case 'N': b = 0xb1; break;
+ case 'M': b = 0xb2; break;
+ case '<': b = 0xb3; break;
+ case '>': b = 0xb4; break;
+ case '?': b = 0xb5; break;
+ default: b = 0; break;
+ }
+ return b;
+}
+
+/***************************************************************************
+ at_keyboard_queue_chars
+***************************************************************************/
+
+static int at_keyboard_queue_chars(const unicode_char *text, size_t text_len)
+{
+ int i;
+ UINT8 b;
+
+ for (i = 0; (i < text_len) && ((at_keyboard_queue_size()) + 4 < AT_KEYBOARD_QUEUE_MAXSIZE); i++)
+ {
+ b = unicode_char_to_at_keycode(text[i]);
+ if (b)
+ {
+ if (b & 0x80)
+ at_keyboard_standard_scancode_insert(0x36, 1);
+
+ at_keyboard_standard_scancode_insert(b & 0x7f, 1);
+ at_keyboard_standard_scancode_insert(b & 0x7f, 0);
+
+ if (b & 0x80)
+ at_keyboard_standard_scancode_insert(0x36, 0);
+ }
+ }
+ return i;
+}
+
+
+
+/***************************************************************************
+ Keyboard declaration
+***************************************************************************/
+
+INPUT_PORTS_START( pc_keyboard )
+ PORT_START_TAG("pc_keyboard_0")
+ PORT_BIT ( 0x0001, 0x0000, IPT_UNUSED ) /* unused scancode 0 */
+ PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(27) /* Esc 01 81 */
+ PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') /* 1 02 82 */
+ PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('@') /* 2 03 83 */
+ PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') /* 3 04 84 */
+ PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') /* 4 05 85 */
+ PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') /* 5 06 86 */
+ PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('^') /* 6 07 87 */
+ PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('&') /* 7 08 88 */
+ PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('*') /* 8 09 89 */
+ PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR('(') /* 9 0A 8A */
+ PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR(')') /* 0 0B 8B */
+ PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') PORT_CHAR('_') /* - 0C 8C */
+ PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('+') /* = 0D 8D */
+ PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) /* Backspace 0E 8E */
+ PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) /* Tab 0F 8F */
+
+ PORT_START_TAG("pc_keyboard_1")
+ PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('Q') /* Q 10 90 */
+ PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('W') /* W 11 91 */
+ PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('E') /* E 12 92 */
+ PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('R') /* R 13 93 */
+ PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('T') /* T 14 94 */
+ PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('Y') /* Y 15 95 */
+ PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('U') /* U 16 96 */
+ PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('I') /* I 17 97 */
+ PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('O') /* O 18 98 */
+ PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('P') /* P 19 99 */
+ PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') /* [ 1A 9A */
+ PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') /* ] 1B 9B */
+ PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) /* Enter 1C 9C */
+ PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LCONTROL) PORT_CHAR(UCHAR_MAMEKEY(LCONTROL)) /* Left Ctrl 1D 9D */
+ PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('A') /* A 1E 9E */
+ PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('S') /* S 1F 9F */
+
+ PORT_START_TAG("pc_keyboard_2")
+ PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('D') /* D 20 A0 */
+ PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('F') /* F 21 A1 */
+ PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('G') /* G 22 A2 */
+ PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('H') /* H 23 A3 */
+ PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('J') /* J 24 A4 */
+ PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('K') /* K 25 A5 */
+ PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('L') /* L 26 A6 */
+ PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR(':') /* ; 27 A7 */
+ PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR('\'') PORT_CHAR('\"') /* ' 28 A8 */
+ PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('`') PORT_CHAR('~') /* ` 29 A9 */
+ PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_MAMEKEY(LSHIFT)) /* Left Shift 2A AA */
+ PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') /* \ 2B AB */
+ PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('Z') /* Z 2C AC */
+ PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('X') /* X 2D AD */
+ PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('C') /* C 2E AE */
+ PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('V') /* V 2F AF */
+
+ PORT_START_TAG("pc_keyboard_3")
+ PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('B') /* B 30 B0 */
+ PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('N') /* N 31 B1 */
+ PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('M') /* M 32 B2 */
+ PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') /* , 33 B3 */
+ PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') /* . 34 B4 */
+ PORT_BIT( 0x0020, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') /* / 35 B5 */
+ PORT_BIT( 0x0040, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) /* Right Shift 36 B6 */
+ PORT_BIT( 0x0080, 0x0000, IPT_KEYBOARD) PORT_NAME("KP * (PrtScr)") PORT_CODE(KEYCODE_ASTERISK) /* Keypad * (PrtSc) 37 B7 */
+ PORT_BIT( 0x0100, 0x0000, IPT_KEYBOARD) PORT_NAME("Alt") PORT_CODE(KEYCODE_LALT) /* Left Alt 38 B8 */
+ PORT_BIT( 0x0200, 0x0000, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') /* Space 39 B9 */
+ PORT_BIT( 0x0400, 0x0000, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE /* Caps Lock 3A BA */
+ PORT_BIT( 0x0800, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) /* F1 3B BB */
+ PORT_BIT( 0x1000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) /* F2 3C BC */
+ PORT_BIT( 0x2000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) /* F3 3D BD */
+ PORT_BIT( 0x4000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) /* F4 3E BE */
+ PORT_BIT( 0x8000, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) /* F5 3F BF */
+
+ PORT_START_TAG("pc_keyboard_4")
+ PORT_BIT( 0x0001, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) /* F6 40 C0 */
+ PORT_BIT( 0x0002, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) /* F7 41 C1 */
+ PORT_BIT( 0x0004, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) /* F8 42 C2 */
+ PORT_BIT( 0x0008, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) /* F9 43 C3 */
+ PORT_BIT( 0x0010, 0x0000, IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) /* F10 44 C4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("NumLock") PORT_CODE(KEYCODE_NUMLOCK) /* Num Lock 45 C5 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ScrLock") PORT_CODE(KEYCODE_SCRLOCK) /* Scroll Lock 46 C6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 7 (Home)") PORT_CODE(KEYCODE_7_PAD) PORT_CODE(KEYCODE_HOME ) /* Keypad 7 (Home) 47 C7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 8 (Up)") PORT_CODE(KEYCODE_8_PAD) PORT_CODE(KEYCODE_UP ) /* Keypad 8 (Up arrow) 48 C8 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 9 (PgUp)") PORT_CODE(KEYCODE_9_PAD) PORT_CODE(KEYCODE_PGUP) /* Keypad 9 (PgUp) 49 C9 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) /* Keypad - 4A CA */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 4 (Left)") PORT_CODE(KEYCODE_4_PAD) PORT_CODE(KEYCODE_LEFT ) /* Keypad 4 (Left arrow) 4B CB */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) /* Keypad 5 4C CC */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 6 (Right)") PORT_CODE(KEYCODE_6_PAD) PORT_CODE(KEYCODE_RIGHT ) /* Keypad 6 (Right arrow) 4D CD */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP +") PORT_CODE(KEYCODE_PLUS_PAD) /* Keypad + 4E CE */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 1 (End)") PORT_CODE(KEYCODE_1_PAD) PORT_CODE(KEYCODE_END ) /* Keypad 1 (End) 4F CF */
+
+ PORT_START_TAG("pc_keyboard_5")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 2 (Down)") PORT_CODE(KEYCODE_2_PAD) PORT_CODE(KEYCODE_DOWN ) /* Keypad 2 (Down arrow) 50 D0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 3 (PgDn)") PORT_CODE(KEYCODE_3_PAD) PORT_CODE(KEYCODE_PGDN ) /* Keypad 3 (PgDn) 51 D1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 0 (Ins)") PORT_CODE(KEYCODE_0_PAD) PORT_CODE(KEYCODE_INSERT ) /* Keypad 0 (Ins) 52 D2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP . (Del)") PORT_CODE(KEYCODE_DEL_PAD) PORT_CODE(KEYCODE_DEL ) /* Keypad . (Del) 53 D3 */
+ PORT_BIT ( 0x0030, 0x0000, IPT_UNUSED )
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(84/102)\\") PORT_CODE(KEYCODE_BACKSLASH2) /* Backslash 2 56 D6 */
+ PORT_BIT ( 0xff80, 0x0000, IPT_UNUSED )
+
+ PORT_START_TAG("pc_keyboard_6")
+ PORT_BIT ( 0xffff, 0x0000, IPT_UNUSED )
+
+ PORT_START_TAG("pc_keyboard_7")
+ PORT_BIT ( 0xffff, 0x0000, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+
+INPUT_PORTS_START( at_keyboard )
+ PORT_START_TAG("pc_keyboard_0")
+ PORT_BIT ( 0x0001, 0x0000, IPT_UNUSED ) /* unused scancode 0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Esc") PORT_CODE(KEYCODE_ESC) /* Esc 01 81 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("1 !") PORT_CODE(KEYCODE_1) /* 1 02 82 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("2 @") PORT_CODE(KEYCODE_2) /* 2 03 83 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("3 #") PORT_CODE(KEYCODE_3) /* 3 04 84 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("4 $") PORT_CODE(KEYCODE_4) /* 4 05 85 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("5 %") PORT_CODE(KEYCODE_5) /* 5 06 86 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("6 ^") PORT_CODE(KEYCODE_6) /* 6 07 87 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("7 &") PORT_CODE(KEYCODE_7) /* 7 08 88 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("8 *") PORT_CODE(KEYCODE_8) /* 8 09 89 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("9 (") PORT_CODE(KEYCODE_9) /* 9 0A 8A */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("0 )") PORT_CODE(KEYCODE_0) /* 0 0B 8B */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("- _") PORT_CODE(KEYCODE_MINUS) /* - 0C 8C */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("= +") PORT_CODE(KEYCODE_EQUALS) /* = 0D 8D */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("<--") PORT_CODE(KEYCODE_BACKSPACE) /* Backspace 0E 8E */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) /* Tab 0F 8F */
+
+ PORT_START_TAG("pc_keyboard_1")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) /* Q 10 90 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) /* W 11 91 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) /* E 12 92 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) /* R 13 93 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) /* T 14 94 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) /* Y 15 95 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) /* U 16 96 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) /* I 17 97 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) /* O 18 98 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) /* P 19 99 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("[ {") PORT_CODE(KEYCODE_OPENBRACE) /* [ 1A 9A */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("] }") PORT_CODE(KEYCODE_CLOSEBRACE) /* ] 1B 9B */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Enter") PORT_CODE(KEYCODE_ENTER) /* Enter 1C 9C */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L-Ctrl") PORT_CODE(KEYCODE_LCONTROL) /* Left Ctrl 1D 9D */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) /* A 1E 9E */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) /* S 1F 9F */
+
+ PORT_START_TAG("pc_keyboard_2")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) /* D 20 A0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) /* F 21 A1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) /* G 22 A2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) /* H 23 A3 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) /* J 24 A4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) /* K 25 A5 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) /* L 26 A6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("; :") PORT_CODE(KEYCODE_COLON) /* ; 27 A7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("' \"") PORT_CODE(KEYCODE_QUOTE) /* ' 28 A8 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("` ~") PORT_CODE(KEYCODE_TILDE) /* ` 29 A9 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("L-Shift") PORT_CODE(KEYCODE_LSHIFT) /* Left Shift 2A AA */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("\\ |") PORT_CODE(KEYCODE_BACKSLASH) /* \ 2B AB */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) /* Z 2C AC */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) /* X 2D AD */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) /* C 2E AE */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) /* V 2F AF */
+
+ PORT_START_TAG("pc_keyboard_3")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) /* B 30 B0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) /* N 31 B1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) /* M 32 B2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(", <") PORT_CODE(KEYCODE_COMMA) /* , 33 B3 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME(". >") PORT_CODE(KEYCODE_STOP) /* . 34 B4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("/ ?") PORT_CODE(KEYCODE_SLASH) /* / 35 B5 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("R-Shift") PORT_CODE(KEYCODE_RSHIFT) /* Right Shift 36 B6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP * (PrtScr)") PORT_CODE(KEYCODE_ASTERISK ) /* Keypad * (PrtSc) 37 B7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Alt") PORT_CODE(KEYCODE_LALT) /* Left Alt 38 B8 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) /* Space 39 B9 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Caps") PORT_CODE(KEYCODE_CAPSLOCK) /* Caps Lock 3A BA */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F1") PORT_CODE(KEYCODE_F1) /* F1 3B BB */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F2") PORT_CODE(KEYCODE_F2) /* F2 3C BC */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F3") PORT_CODE(KEYCODE_F3) /* F3 3D BD */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F4") PORT_CODE(KEYCODE_F4) /* F4 3E BE */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F5") PORT_CODE(KEYCODE_F5) /* F5 3F BF */
+
+ PORT_START_TAG("pc_keyboard_4")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F6") PORT_CODE(KEYCODE_F6) /* F6 40 C0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F7") PORT_CODE(KEYCODE_F7) /* F7 41 C1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F8") PORT_CODE(KEYCODE_F8) /* F8 42 C2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F9") PORT_CODE(KEYCODE_F9) /* F9 43 C3 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("F10") PORT_CODE(KEYCODE_F10) /* F10 44 C4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("NumLock") PORT_CODE(KEYCODE_NUMLOCK) /* Num Lock 45 C5 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("ScrLock") PORT_CODE(KEYCODE_SCRLOCK) /* Scroll Lock 46 C6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 7 (Home)") PORT_CODE(KEYCODE_7_PAD ) /* Keypad 7 (Home) 47 C7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 8 (Up)") PORT_CODE(KEYCODE_8_PAD ) /* Keypad 8 (Up arrow) 48 C8 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 9 (PgUp)") PORT_CODE(KEYCODE_9_PAD ) /* Keypad 9 (PgUp) 49 C9 */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP -") PORT_CODE(KEYCODE_MINUS_PAD) /* Keypad - 4A CA */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 4 (Left)") PORT_CODE(KEYCODE_4_PAD ) /* Keypad 4 (Left arrow) 4B CB */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 5") PORT_CODE(KEYCODE_5_PAD) /* Keypad 5 4C CC */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 6 (Right)") PORT_CODE(KEYCODE_6_PAD ) /* Keypad 6 (Right arrow) 4D CD */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP +") PORT_CODE(KEYCODE_PLUS_PAD) /* Keypad + 4E CE */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 1 (End)") PORT_CODE(KEYCODE_1_PAD ) /* Keypad 1 (End) 4F CF */
+
+ PORT_START_TAG("pc_keyboard_5")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 2 (Down)") PORT_CODE(KEYCODE_2_PAD ) /* Keypad 2 (Down arrow) 50 D0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 3 (PgDn)") PORT_CODE(KEYCODE_3_PAD ) /* Keypad 3 (PgDn) 51 D1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP 0 (Ins)") PORT_CODE(KEYCODE_0_PAD ) /* Keypad 0 (Ins) 52 D2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("KP . (Del)") PORT_CODE(KEYCODE_DEL_PAD ) /* Keypad . (Del) 53 D3 */
+ PORT_BIT ( 0x0030, 0x0000, IPT_UNUSED )
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(84/102)\\") PORT_CODE(KEYCODE_BACKSLASH2) /* Backslash 2 56 D6 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)F11") PORT_CODE(KEYCODE_F11) /* F11 57 D7 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)F12") PORT_CODE(KEYCODE_F12) /* F12 58 D8 */
+ PORT_BIT ( 0xfe00, 0x0000, IPT_UNUSED )
+
+ PORT_START_TAG("pc_keyboard_6")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)KP Enter") PORT_CODE(KEYCODE_ENTER_PAD) /* PAD Enter 60 e0 */
+ PORT_BIT(0x0002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Right Control") PORT_CODE(KEYCODE_RCONTROL) /* Right Control 61 e1 */
+ PORT_BIT(0x0004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)KP /") PORT_CODE(KEYCODE_SLASH_PAD) /* PAD Slash 62 e2 */
+ PORT_BIT(0x0008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)PRTSCR") PORT_CODE(KEYCODE_PRTSCR) /* Print Screen 63 e3 */
+ PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)ALTGR") PORT_CODE(KEYCODE_RALT) /* ALTGR 64 e4 */
+ PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Home") PORT_CODE(KEYCODE_HOME) /* Home 66 e6 */
+ PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Cursor Up") PORT_CODE(KEYCODE_UP) /* Up 67 e7 */
+ PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Page Up") PORT_CODE(KEYCODE_PGUP) /* Page Up 68 e8 */
+ PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Cursor Left") PORT_CODE(KEYCODE_LEFT) /* Left 69 e9 */
+ PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Cursor Right") PORT_CODE(KEYCODE_RIGHT) /* Right 6a ea */
+ PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)End") PORT_CODE(KEYCODE_END) /* End 6b eb */
+ PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Cursor Down") PORT_CODE(KEYCODE_DOWN) /* Down 6c ec */
+ PORT_BIT(0x1000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Page Down") PORT_CODE(KEYCODE_PGDN) /* Page Down 6d ed */
+ PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Insert") PORT_CODE(KEYCODE_INSERT) /* Insert 6e ee */
+ PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Delete") PORT_CODE(KEYCODE_DEL) /* Delete 6f ef */
+ PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("(MF2)Pause") PORT_CODE(KEYCODE_PAUSE) /* Pause 65 e5 */
+
+ PORT_START_TAG("pc_keyboard_7")
+ PORT_BIT(0x0001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Print Screen") PORT_CODE(KEYCODE_PRTSCR) /* Print Screen alternate 77 f7 */
+ PORT_BIT ( 0xfffe, 0x0000, IPT_UNUSED )
+INPUT_PORTS_END
+
+
+
+/***************************************************************************
+ Inputx stuff
+***************************************************************************/
+
+static int at_keyboard_accept_char(unicode_char ch)
+{
+ return unicode_char_to_at_keycode(ch) != 0;
+}
+
+
+
+static int at_keyboard_charqueue_empty(void)
+{
+ return at_keyboard_queue_size() == 0;
+}
+#endif /* MESS */
+
+
+
diff --git a/src/mame/machine/pckeybrd.h b/src/mame/machine/pckeybrd.h
new file mode 100644
index 00000000000..f3b22fcca89
--- /dev/null
+++ b/src/mame/machine/pckeybrd.h
@@ -0,0 +1,35 @@
+/**********************************************************************
+
+ pckeybrd.h
+
+ PC-style keyboard emulation
+
+ This emulation is decoupled from the AT 8042 emulation used in the
+ IBM ATs and above
+
+**********************************************************************/
+
+#ifndef PCKEYBRD_H
+#define PCKEYBRD_H
+
+typedef enum
+{
+ AT_KEYBOARD_TYPE_PC,
+ AT_KEYBOARD_TYPE_AT,
+ AT_KEYBOARD_TYPE_MF2
+} AT_KEYBOARD_TYPE;
+
+void at_keyboard_init(AT_KEYBOARD_TYPE type);
+
+void at_keyboard_polling(void);
+int at_keyboard_read(void);
+void at_keyboard_write(UINT8 data);
+void at_keyboard_reset(void);
+void at_keyboard_set_scan_code_set(int set);
+
+INPUT_PORTS_EXTERN( pc_keyboard );
+INPUT_PORTS_EXTERN( at_keyboard );
+
+#endif /* PCKEYBRD_H */
+
+
diff --git a/src/mame/machine/pcshare.c b/src/mame/machine/pcshare.c
new file mode 100644
index 00000000000..da3fa1d02bb
--- /dev/null
+++ b/src/mame/machine/pcshare.c
@@ -0,0 +1,572 @@
+/***************************************************************************
+
+ machine/pc.c
+
+ Functions to emulate general aspects of the machine
+ (RAM, ROM, interrupts, I/O ports)
+
+ The information herein is heavily based on
+ 'Ralph Browns Interrupt List'
+ Release 52, Last Change 20oct96
+
+ TODO:
+ clean up (maybe split) the different pieces of hardware
+ PIC, PIT, DMA... add support for LPT, COM (almost done)
+ emulation of a serial mouse on a COM port (almost done)
+ support for Game Controller port at 0x0201
+ support for XT harddisk (under the way, see machine/pc_hdc.c)
+ whatever 'hardware' comes to mind,
+ maybe SoundBlaster? EGA? VGA?
+
+***************************************************************************/
+
+#include "driver.h"
+#include "memconv.h"
+#include "machine/8255ppi.h"
+
+#include "machine/pic8259.h"
+#include "machine/pit8253.h"
+#include "machine/mc146818.h"
+#include "machine/pcshare.h"
+
+#include "machine/8237dma.h"
+#include "machine/pckeybrd.h"
+
+#ifdef MESS
+#include "machine/uart8250.h"
+#include "video/pc_vga.h"
+#include "video/pc_cga.h"
+#include "video/pc_mda.h"
+#include "video/pc_aga.h"
+
+#include "includes/pc_mouse.h"
+#include "machine/pc_fdc.h"
+
+#include "includes/pclpt.h"
+#include "includes/centroni.h"
+
+#include "machine/pc_hdc.h"
+#include "machine/nec765.h"
+#include "audio/pc.h"
+
+#include "mscommon.h"
+#endif /* MESS */
+
+#define VERBOSE_DBG 0 /* general debug messages */
+#if VERBOSE_DBG
+#define DBG_LOG(N,M,A) \
+ if(VERBOSE_DBG>=N){ if( M )logerror("%11.6f: %-24s",attotime_to_double(timer_get_time()),(char*)M ); logerror A; }
+#else
+#define DBG_LOG(n,m,a)
+#endif
+
+#define VERBOSE_JOY 0 /* JOY (joystick port) */
+
+#if VERBOSE_JOY
+#define LOG(LEVEL,N,M,A) \
+#define JOY_LOG(N,M,A) \
+ if(VERBOSE_JOY>=N){ if( M )logerror("%11.6f: %-24s",attotime_to_double(timer_get_time()),(char*)M ); logerror A; }
+#else
+#define JOY_LOG(n,m,a)
+#endif
+
+#define FDC_DMA 2
+
+
+static emu_timer *pc_keyboard_timer;
+
+static TIMER_CALLBACK( pc_keyb_timer );
+
+#define LOG_PORT80 0
+
+
+
+/* ---------------------------------------------------------------------- */
+
+#ifdef MESS
+/* called when a interrupt is set/cleared from com hardware */
+static void pc_com_interrupt(int nr, int state)
+{
+ static const int irq[4] = {4, 3, 4, 3};
+
+ /* issue COM1/3 IRQ4, COM2/4 IRQ3 */
+ pic8259_set_irq_line(0, irq[nr], state);
+}
+
+/* called when com registers read/written - used to update peripherals that
+are connected */
+static void pc_com_refresh_connected(int n, int data)
+{
+ /* mouse connected to this port? */
+ if (readinputport(3) & (0x80>>n))
+ pc_mouse_handshake_in(n,data);
+}
+
+/* PC interface to PC-com hardware. Done this way because PCW16 also
+uses PC-com hardware and doesn't have the same setup! */
+static uart8250_interface com_interface[4]=
+{
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ },
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ },
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ },
+ {
+ TYPE8250,
+ 1843200,
+ pc_com_interrupt,
+ NULL,
+ pc_com_refresh_connected
+ }
+};
+#endif /* MESS */
+
+
+
+static void pc_timer0_w(int state)
+{
+ pic8259_set_irq_line(0, 0, state);
+}
+
+
+
+/*
+ * timer0 heartbeat IRQ
+ * timer1 DRAM refresh (ignored)
+ * timer2 PIO port C pin 4 and speaker polling
+ */
+static const struct pit8253_config pc_pit8253_config =
+{
+ TYPE8253,
+ {
+ {
+ 4772720/4, /* heartbeat IRQ */
+ pc_timer0_w,
+ NULL
+ }, {
+ 4772720/4, /* dram refresh */
+ NULL,
+ NULL
+ }, {
+ 4772720/4, /* pio port c pin 4, and speaker polling enough */
+ NULL,
+#ifdef MESS
+ pc_sh_speaker_change_clock
+#else
+ NULL //pc_sh_speaker_change_clock
+#endif /* MESS */
+ }
+ }
+};
+
+static const struct pit8253_config pc_pit8254_config =
+{
+ TYPE8254,
+ {
+ {
+ 4772720/4, /* heartbeat IRQ */
+ pc_timer0_w,
+ NULL
+ }, {
+ 4772720/4, /* dram refresh */
+ NULL,
+ NULL
+ }, {
+ 4772720/4, /* pio port c pin 4, and speaker polling enough */
+ NULL,
+#ifdef MESS
+ pc_sh_speaker_change_clock
+#else
+ NULL //pc_sh_speaker_change_clock
+#endif /* MESS */
+ }
+ }
+};
+
+
+#ifdef MESS
+static PC_LPT_CONFIG lpt_config[3]={
+ {
+ 1,
+ LPT_UNIDIRECTIONAL,
+ NULL
+ },
+ {
+ 1,
+ LPT_UNIDIRECTIONAL,
+ NULL
+ },
+ {
+ 1,
+ LPT_UNIDIRECTIONAL,
+ NULL
+ }
+};
+
+static CENTRONICS_CONFIG cent_config[3]={
+ {
+ PRINTER_IBM,
+ pc_lpt_handshake_in
+ },
+ {
+ PRINTER_IBM,
+ pc_lpt_handshake_in
+ },
+ {
+ PRINTER_IBM,
+ pc_lpt_handshake_in
+ }
+};
+#endif
+
+
+
+/*************************************************************************
+ *
+ * PC DMA stuff
+ *
+ *************************************************************************/
+
+static UINT8 dma_offset[2][4];
+static UINT8 at_pages[0x10];
+static offs_t pc_page_offset_mask;
+
+
+
+READ8_HANDLER(pc_page_r)
+{
+ return 0xFF;
+}
+
+
+
+WRITE8_HANDLER(pc_page_w)
+{
+ switch(offset % 4) {
+ case 1:
+ dma_offset[0][2] = data;
+ break;
+ case 2:
+ dma_offset[0][3] = data;
+ break;
+ case 3:
+ dma_offset[0][0] = dma_offset[0][1] = data;
+ break;
+ }
+}
+
+
+
+READ16_HANDLER(pc_page16le_r) { return read16le_with_read8_handler(pc_page_r, offset, mem_mask); }
+WRITE16_HANDLER(pc_page16le_w) { write16le_with_write8_handler(pc_page_w, offset, data, mem_mask); }
+
+
+
+READ8_HANDLER(at_page8_r)
+{
+ UINT8 data = at_pages[offset % 0x10];
+
+ switch(offset % 8) {
+ case 1:
+ data = dma_offset[(offset / 8) & 1][2];
+ break;
+ case 2:
+ data = dma_offset[(offset / 8) & 1][3];
+ break;
+ case 3:
+ data = dma_offset[(offset / 8) & 1][1];
+ break;
+ case 7:
+ data = dma_offset[(offset / 8) & 1][0];
+ break;
+ }
+ return data;
+}
+
+
+
+WRITE8_HANDLER(at_page8_w)
+{
+ at_pages[offset % 0x10] = data;
+
+ if (LOG_PORT80 && (offset == 0))
+ logerror(" at_page8_w(): Port 80h <== 0x%02x (PC=0x%08x)\n", data, (unsigned) activecpu_get_reg(REG_PC));
+
+ switch(offset % 8) {
+ case 1:
+ dma_offset[(offset / 8) & 1][2] = data;
+ break;
+ case 2:
+ dma_offset[(offset / 8) & 1][3] = data;
+ break;
+ case 3:
+ dma_offset[(offset / 8) & 1][1] = data;
+ break;
+ case 7:
+ dma_offset[(offset / 8) & 1][0] = data;
+ break;
+ }
+}
+
+
+
+READ32_HANDLER(at_page32_r)
+{
+ return read32le_with_read8_handler(at_page8_r, offset, mem_mask);
+}
+
+
+
+WRITE32_HANDLER(at_page32_w)
+{
+ write32le_with_write8_handler(at_page8_w, offset, data, mem_mask);
+}
+
+
+
+static UINT8 pc_dma_read_byte(int channel, offs_t offset)
+{
+ UINT8 result;
+ offs_t page_offset = (((offs_t) dma_offset[0][channel]) << 16)
+ & pc_page_offset_mask;
+
+ cpuintrf_push_context(0);
+ result = program_read_byte(page_offset + offset);
+ cpuintrf_pop_context();
+
+ return result;
+}
+
+
+
+static void pc_dma_write_byte(int channel, offs_t offset, UINT8 data)
+{
+ offs_t page_offset = (((offs_t) dma_offset[0][channel]) << 16)
+ & pc_page_offset_mask;
+
+ cpuintrf_push_context(0);
+ program_write_byte(page_offset + offset, data);
+ cpuintrf_pop_context();
+}
+
+
+
+static struct dma8237_interface pc_dma =
+{
+ 0,
+ 1.0e-6, // 1us
+
+ pc_dma_read_byte,
+ pc_dma_write_byte,
+
+#ifdef MESS
+ { 0, 0, pc_fdc_dack_r, pc_hdc_dack_r },
+ { 0, 0, pc_fdc_dack_w, pc_hdc_dack_w },
+ pc_fdc_set_tc_state
+#else
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 },
+ 0
+#endif
+};
+
+
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef MESS
+static void pc_fdc_interrupt(int state)
+{
+ pic8259_set_irq_line(0, 6, state);
+}
+
+
+
+static void pc_fdc_dma_drq(int state, int read_)
+{
+ dma8237_drq_write(0, FDC_DMA, state);
+}
+
+
+
+static const struct pc_fdc_interface fdc_interface =
+{
+ NEC765A,
+ pc_fdc_interrupt,
+ pc_fdc_dma_drq,
+};
+#endif /* MESS */
+
+
+
+/* ----------------------------------------------------------------------- */
+
+static void pc_pic_set_int_line(int which, int interrupt)
+{
+ switch(which)
+ {
+ case 0:
+ /* Master */
+ cpunum_set_input_line(0, 0, interrupt ? HOLD_LINE : CLEAR_LINE);
+ break;
+
+ case 1:
+ /* Slave */
+ pic8259_set_irq_line(0, 2, interrupt);
+ break;
+ }
+}
+
+
+
+void init_pc_common(UINT32 flags)
+{
+#ifdef MESS
+ /* MESS managed RAM */
+ if (mess_ram)
+ memory_set_bankptr(10, mess_ram);
+#endif /* MESS */
+
+ /* PIT */
+ if (flags & PCCOMMON_TIMER_8254)
+ pit8253_init(1, &pc_pit8254_config);
+ else if (flags & PCCOMMON_TIMER_8253)
+ pit8253_init(1, &pc_pit8253_config);
+
+#ifdef MESS
+ /* FDC/HDC hardware */
+ pc_fdc_init(&fdc_interface);
+ pc_hdc_setup();
+
+ /* com hardware */
+ uart8250_init(0, com_interface);
+ uart8250_reset(0);
+ uart8250_init(1, com_interface+1);
+ uart8250_reset(1);
+ uart8250_init(2, com_interface+2);
+ uart8250_reset(2);
+ uart8250_init(3, com_interface+3);
+ uart8250_reset(3);
+
+ pc_lpt_config(0, lpt_config);
+ centronics_config(0, cent_config);
+ pc_lpt_set_device(0, &CENTRONICS_PRINTER_DEVICE);
+ pc_lpt_config(1, lpt_config+1);
+ centronics_config(1, cent_config+1);
+ pc_lpt_set_device(1, &CENTRONICS_PRINTER_DEVICE);
+ pc_lpt_config(2, lpt_config+2);
+ centronics_config(2, cent_config+2);
+ pc_lpt_set_device(2, &CENTRONICS_PRINTER_DEVICE);
+
+ /* serial mouse */
+ pc_mouse_set_serial_port(0);
+ pc_mouse_initialise();
+#endif /* MESS */
+
+ /* PC-XT keyboard */
+ if (flags & PCCOMMON_KEYBOARD_AT)
+ at_keyboard_init(AT_KEYBOARD_TYPE_AT);
+ else
+ at_keyboard_init(AT_KEYBOARD_TYPE_PC);
+ at_keyboard_set_scan_code_set(1);
+
+ /* PIC */
+ pic8259_init(2, pc_pic_set_int_line);
+
+ /* DMA */
+ if (flags & PCCOMMON_DMA8237_AT)
+ {
+ dma8237_init(2);
+ dma8237_config(0, &pc_dma);
+ pc_page_offset_mask = 0xFF0000;
+ }
+ else
+ {
+ dma8237_init(1);
+ dma8237_config(0, &pc_dma);
+ pc_page_offset_mask = 0x0F0000;
+ }
+
+ pc_keyboard_timer = timer_alloc(pc_keyb_timer);
+}
+
+/*
+ keyboard seams to permanently sent data clocked by the mainboard
+ clock line low for longer means "resync", keyboard sends 0xaa as answer
+ will become automatically 0x00 after a while
+*/
+
+static struct {
+ UINT8 data;
+ int on;
+} pc_keyb= { 0 };
+
+UINT8 pc_keyb_read(void)
+{
+ return pc_keyb.data;
+}
+
+
+
+static TIMER_CALLBACK( pc_keyb_timer )
+{
+ at_keyboard_reset();
+ pc_keyboard();
+}
+
+
+
+void pc_keyb_set_clock(int on)
+{
+ attotime keyb_delay = STATIC_ATTOTIME_IN_MSEC(5);
+
+ on = on ? 1 : 0;
+
+ if (pc_keyb.on != on)
+ {
+ if (on)
+ timer_adjust(pc_keyboard_timer, keyb_delay, 0, attotime_zero);
+ else
+ timer_reset(pc_keyboard_timer, attotime_never);
+
+ pc_keyb.on = on;
+ }
+}
+
+void pc_keyb_clear(void)
+{
+ pc_keyb.data = 0;
+}
+
+void pc_keyboard(void)
+{
+ int data;
+
+ at_keyboard_polling();
+
+ if (pc_keyb.on)
+ {
+ if ( (data=at_keyboard_read())!=-1) {
+ pc_keyb.data = data;
+ DBG_LOG(1,"KB_scancode",("$%02x\n", pc_keyb.data));
+ pic8259_set_irq_line(0, 1, 1);
+ pic8259_set_irq_line(0, 1, 0);
+ }
+ }
+}
diff --git a/src/mame/machine/pcshare.h b/src/mame/machine/pcshare.h
new file mode 100644
index 00000000000..9d0d3b89f58
--- /dev/null
+++ b/src/mame/machine/pcshare.h
@@ -0,0 +1,29 @@
+#include "sound/custom.h"
+
+/* flags for init_pc_common */
+#define PCCOMMON_KEYBOARD_PC 0
+#define PCCOMMON_KEYBOARD_AT 1
+#define PCCOMMON_DMA8237_PC 0
+#define PCCOMMON_DMA8237_AT 2
+#define PCCOMMON_TIMER_NONE 0
+#define PCCOMMON_TIMER_8253 4
+#define PCCOMMON_TIMER_8254 8
+
+void init_pc_common(UINT32 flags);
+
+void pc_keyboard(void);
+UINT8 pc_keyb_read(void);
+void pc_keyb_set_clock(int on);
+void pc_keyb_clear(void);
+
+READ8_HANDLER(pc_page_r);
+WRITE8_HANDLER(pc_page_w);
+
+READ16_HANDLER(pc_page16le_r);
+WRITE16_HANDLER(pc_page16le_w);
+
+READ8_HANDLER(at_page8_r);
+WRITE8_HANDLER(at_page8_w);
+
+READ32_HANDLER(at_page32_r);
+WRITE32_HANDLER(at_page32_w);
diff --git a/src/mame/machine/pgmcrypt.c b/src/mame/machine/pgmcrypt.c
new file mode 100644
index 00000000000..68f48ec4c1e
--- /dev/null
+++ b/src/mame/machine/pgmcrypt.c
@@ -0,0 +1,611 @@
+/* IGS PGM System Encryptions */
+
+#include "driver.h"
+
+static const UINT8 kov_tab[256] = {
+ 0x17, 0x1c, 0xe3, 0x02, 0x62, 0x59, 0x97, 0x4a, 0x67, 0x4d, 0x1f, 0x11, 0x76, 0x64, 0xc1, 0xe1,
+ 0xd2, 0x41, 0x9f, 0xfd, 0xfa, 0x04, 0xfe, 0xab, 0x89, 0xeb, 0xc0, 0xf5, 0xac, 0x2b, 0x64, 0x22,
+ 0x90, 0x7d, 0x88, 0xc5, 0x8c, 0xe0, 0xd9, 0x70, 0x3c, 0xf4, 0x7d, 0x31, 0x1c, 0xca, 0xe2, 0xf1,
+ 0x31, 0x82, 0x86, 0xb1, 0x55, 0x95, 0x77, 0x01, 0x77, 0x3b, 0xab, 0xe6, 0x88, 0xef, 0x77, 0x11,
+ 0x56, 0x01, 0xac, 0x55, 0xf7, 0x6d, 0x9b, 0x6d, 0x92, 0x14, 0x23, 0xae, 0x4b, 0x80, 0xae, 0x6a,
+ 0x43, 0xcc, 0x35, 0xfe, 0xa1, 0x0d, 0xb3, 0x21, 0x4e, 0x4c, 0x99, 0x80, 0xc2, 0x3d, 0xce, 0x46,
+ 0x9b, 0x5d, 0x68, 0x75, 0xfe, 0x1e, 0x25, 0x41, 0x24, 0xa0, 0x79, 0xfd, 0xb5, 0x67, 0x93, 0x07,
+ 0x3a, 0x78, 0x24, 0x64, 0xe1, 0xa3, 0x62, 0x75, 0x38, 0x65, 0x8a, 0xbf, 0xf9, 0x7c, 0x00, 0xa0,
+ 0x6d, 0xdb, 0x1f, 0x80, 0x37, 0x37, 0x8e, 0x97, 0x1a, 0x45, 0x61, 0x0e, 0x10, 0x24, 0x8a, 0x27,
+ 0xf2, 0x44, 0x91, 0x3e, 0x62, 0x44, 0xc5, 0x55, 0xe6, 0x8e, 0x5a, 0x25, 0x8a, 0x90, 0x25, 0x74,
+ 0xa0, 0x95, 0x33, 0xf7, 0x51, 0xce, 0xe4, 0xa0, 0x13, 0xcf, 0x33, 0x1e, 0x59, 0x5b, 0xec, 0x42,
+ 0xc5, 0xb8, 0xe4, 0xc5, 0x71, 0x38, 0xc5, 0x6b, 0x8d, 0x1d, 0x84, 0xf8, 0x4e, 0x21, 0x6d, 0xdc,
+ 0x2c, 0xf1, 0xae, 0xad, 0x19, 0xc5, 0xed, 0x8e, 0x36, 0xb5, 0x81, 0x94, 0xfe, 0x62, 0x3a, 0xe8,
+ 0xc9, 0x95, 0x84, 0xbd, 0x65, 0x15, 0x16, 0x15, 0xd2, 0xe7, 0x16, 0xd7, 0x9c, 0xd3, 0xd2, 0x66,
+ 0xf6, 0x46, 0xe3, 0x32, 0x62, 0x51, 0x86, 0x4a, 0x67, 0xcc, 0x4d, 0xea, 0x37, 0x45, 0xd5, 0xa6,
+ 0x80, 0xe6, 0xba, 0xb3, 0x08, 0xd8, 0x30, 0x5b, 0x5f, 0xf2, 0x5a, 0xfb, 0x63, 0xb0, 0xa4, 0x41
+};
+
+void pgm_kov_decrypt(void)
+{
+
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x400000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x040480) != 0x000080)
+ x ^= 0x0001;
+
+ if((i & 0x004008) == 0x004008)
+ x ^= 0x0002;
+
+ if((i & 0x000030) == 0x000010 && (i & 0x180000) != 0x080000)
+ x ^= 0x0004;
+
+ if((i & 0x000242) != 0x000042)
+ x ^= 0x0008;
+
+ if((i & 0x008100) == 0x008000)
+ x ^= 0x0010;
+
+ if((i & 0x022004) != 0x000004)
+ x ^= 0x0020;
+
+ if((i & 0x011800) != 0x010000)
+ x ^= 0x0040;
+
+ if((i & 0x004820) == 0x004820)
+ x ^= 0x0080;
+
+ x ^= kov_tab[i & 0xff] << 8;
+
+ src[i] = x;
+ }
+}
+
+
+static const UINT8 kovsh_tab[256] = {
+ 0xe7, 0x06, 0xa3, 0x70, 0xf2, 0x58, 0xe6, 0x59, 0xe4, 0xcf, 0xc2, 0x79, 0x1d, 0xe3, 0x71, 0x0e,
+ 0xb6, 0x90, 0x9a, 0x2a, 0x8c, 0x41, 0xf7, 0x82, 0x9b, 0xef, 0x99, 0x0c, 0xfa, 0x2f, 0xf1, 0xfe,
+ 0x8f, 0x70, 0xf4, 0xc1, 0xb5, 0x3d, 0x7c, 0x60, 0x4c, 0x09, 0xf4, 0x2e, 0x7c, 0x87, 0x63, 0x5f,
+ 0xce, 0x99, 0x84, 0x95, 0x06, 0x9a, 0x20, 0x23, 0x5a, 0xb9, 0x52, 0x95, 0x48, 0x2c, 0x84, 0x60,
+ 0x69, 0xe3, 0x93, 0x49, 0xb9, 0xd6, 0xbb, 0xd6, 0x9e, 0xdc, 0x96, 0x12, 0xfa, 0x60, 0xda, 0x5f,
+ 0x55, 0x5d, 0x5b, 0x20, 0x07, 0x1e, 0x97, 0x42, 0x77, 0xea, 0x1d, 0xe0, 0x70, 0xfb, 0x6a, 0x00,
+ 0x77, 0x9a, 0xef, 0x1b, 0xe0, 0xf9, 0x0d, 0xc1, 0x2e, 0x2f, 0xef, 0x25, 0x29, 0xe5, 0xd8, 0x2c,
+ 0xaf, 0x01, 0xd9, 0x6c, 0x31, 0xce, 0x5c, 0xea, 0xab, 0x1c, 0x92, 0x16, 0x61, 0xbc, 0xe4, 0x7c,
+ 0x5a, 0x76, 0xe9, 0x92, 0x39, 0x5b, 0x97, 0x60, 0xea, 0x57, 0x83, 0x9c, 0x92, 0x29, 0xa7, 0x12,
+ 0xa9, 0x71, 0x7a, 0xf9, 0x07, 0x68, 0xa7, 0x45, 0x88, 0x10, 0x81, 0x12, 0x2c, 0x67, 0x4d, 0x55,
+ 0x33, 0xf0, 0xfa, 0xd7, 0x1d, 0x4d, 0x0e, 0x63, 0x03, 0x34, 0x65, 0xe2, 0x76, 0x0f, 0x98, 0xa9,
+ 0x5f, 0x9a, 0xd3, 0xca, 0xdd, 0xc1, 0x5b, 0x3d, 0x4d, 0xf8, 0x40, 0x08, 0xdc, 0x05, 0x38, 0x00,
+ 0xcb, 0x24, 0x02, 0xff, 0x39, 0xe2, 0x9e, 0x04, 0x9a, 0x08, 0x63, 0xc8, 0x2b, 0x5a, 0x34, 0x06,
+ 0x62, 0xc1, 0xbb, 0x8a, 0xd0, 0x54, 0x4c, 0x43, 0x21, 0x4e, 0x4c, 0x99, 0x80, 0xc2, 0x3d, 0xce,
+ 0x2a, 0x7b, 0x09, 0x62, 0x1a, 0x91, 0x9b, 0xc3, 0x41, 0x24, 0xa0, 0xfd, 0xb5, 0x67, 0x93, 0x07,
+ 0xa7, 0xb8, 0x85, 0x8a, 0xa1, 0x1e, 0x4f, 0xb6, 0x75, 0x38, 0x65, 0x8a, 0xf9, 0x7c, 0x00, 0xa0,
+};
+
+
+void pgm_kovsh_decrypt(void)
+{
+
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x400000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x040080) != 0x000080)
+ x ^= 0x0001;
+
+ if((i & 0x004008) == 0x004008 && (i & 0x180000) != 0x000000)
+ x ^= 0x0002;
+
+ if((i & 0x000030) == 0x000010)
+ x ^= 0x0004;
+
+ if((i & 0x000242) != 0x000042)
+ x ^= 0x0008;
+
+ if((i & 0x008100) == 0x008000)
+ x ^= 0x0010;
+
+ if((i & 0x002004) != 0x000004)
+ x ^= 0x0020;
+
+ if((i & 0x011800) != 0x010000)
+ x ^= 0x0040;
+
+ if((i & 0x000820) == 0x000820)
+ x ^= 0x0080;
+
+ x ^= kovsh_tab[i & 0xff] << 8;
+
+ src[i] = x;
+ }
+}
+
+void pgm_dw2_decrypt(void)
+{
+
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x80000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if(((i & 0x020890) == 0x000000)
+ || ((i & 0x020000) == 0x020000 && (i & 0x001500) != 0x001400))
+ x ^= 0x0002;
+
+ if(((i & 0x020400) == 0x000000 && (i & 0x002010) != 0x002010)
+ || ((i & 0x020000) == 0x020000 && (i & 0x000148) != 0x000140))
+ x ^= 0x0400;
+
+ src[i] = x;
+ }
+}
+
+static const UINT8 djlzz_tab[256] = {
+ 0xd9, 0x92, 0xb2, 0xbc, 0xa5, 0x88, 0xe3, 0x48, 0x7d, 0xeb, 0xc5, 0x4d, 0x31, 0xe4, 0x82, 0xbc,
+ 0x82, 0xcf, 0xe7, 0xf3, 0x15, 0xde, 0x8f, 0x91, 0xef, 0xc6, 0xb8, 0x81, 0x97, 0xe3, 0xdf, 0x4d,
+ 0x88, 0xbf, 0xe4, 0x05, 0x25, 0x73, 0x1e, 0xd0, 0xcf, 0x1e, 0xeb, 0x4d, 0x18, 0x4e, 0x6f, 0x9f,
+ 0x00, 0x72, 0xc3, 0x74, 0xbe, 0x02, 0x09, 0x0a, 0xb0, 0xb1, 0x8e, 0x9b, 0x08, 0xed, 0x68, 0x6d,
+ 0x25, 0xe8, 0x28, 0x94, 0xa6, 0x44, 0xa6, 0xfa, 0x95, 0x69, 0x72, 0xd3, 0x6d, 0xb6, 0xff, 0xf3,
+ 0x45, 0x4e, 0xa3, 0x60, 0xf2, 0x58, 0xe7, 0x59, 0xe4, 0x4f, 0x70, 0xd2, 0xdd, 0xc0, 0x6e, 0xf3,
+ 0xd7, 0xb2, 0xdc, 0x1e, 0xa8, 0x41, 0x07, 0x5d, 0x60, 0x15, 0xea, 0xcf, 0xdb, 0xc1, 0x1d, 0x4d,
+ 0xb7, 0x42, 0xec, 0xc4, 0xca, 0xa9, 0x40, 0x30, 0x0f, 0x3c, 0xe2, 0x81, 0xe0, 0x5c, 0x51, 0x07,
+ 0xb0, 0x1e, 0x4a, 0xb3, 0x64, 0x3e, 0x1c, 0x62, 0x17, 0xcd, 0xf2, 0xe4, 0x14, 0x9d, 0xa6, 0xd4,
+ 0x64, 0x36, 0xa5, 0xe8, 0x7e, 0x84, 0x0e, 0xb3, 0x5d, 0x79, 0x57, 0xea, 0xd7, 0xad, 0xbc, 0x9e,
+ 0x2d, 0x90, 0x03, 0x9e, 0x0e, 0xc6, 0x98, 0xdb, 0xe3, 0xb6, 0x9f, 0x9b, 0xf6, 0x21, 0xe6, 0x98,
+ 0x94, 0x77, 0xb7, 0x2b, 0xaa, 0xc9, 0xff, 0xef, 0x7a, 0xf2, 0x71, 0x4e, 0x52, 0x06, 0x85, 0x37,
+ 0x81, 0x8e, 0x86, 0x64, 0x39, 0x92, 0x2a, 0xca, 0xf3, 0x3e, 0x87, 0xb5, 0x0c, 0x7b, 0x42, 0x5e,
+ 0x04, 0xa7, 0xfb, 0xd7, 0x13, 0x7f, 0x83, 0x6a, 0x77, 0x0f, 0xa7, 0x34, 0x51, 0x88, 0x9c, 0xac,
+ 0x23, 0x90, 0x4d, 0x4d, 0x72, 0x4e, 0xa3, 0x26, 0x1a, 0x45, 0x61, 0x0e, 0x10, 0x24, 0x8a, 0x27,
+ 0x92, 0x14, 0x23, 0xae, 0x4b, 0x80, 0xae, 0x6a, 0x56, 0x01, 0xac, 0x55, 0xf7, 0x6d, 0x9b, 0x6d,
+};
+
+void pgm_djlzz_decrypt(void)
+{
+
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x400000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x40080) != 0x00080)
+ x ^= 0x0001;
+
+ if((i & 0x84008) == 0x84008)
+ x ^= 0x0002;
+
+ if((i & 0x00030) == 0x00010)
+ x ^= 0x0004;
+
+ if((i & 0x00242) != 0x00042)
+ x ^= 0x0008;
+
+ if((i & 0x48100) == 0x48000)
+ x ^= 0x0010;
+
+ if((i & 0x02004) != 0x00004)
+ x ^= 0x0020;
+
+ if((i & 0x01800) != 0x00000)
+ x ^= 0x0040;
+
+ if((i & 0x04820) == 0x04820)
+ x ^= 0x0080;
+
+ x ^= djlzz_tab[i & 0xff] << 8;
+
+ src[i] = x;
+ }
+}
+
+static const UINT8 pstar[256] = {
+ 0x62, 0x59, 0x17, 0xe3, 0xe1, 0x11, 0x02, 0x97, 0x67, 0x4d, 0x4a, 0x1c, 0x1f, 0x76, 0x64, 0xc1,
+ 0xfa, 0x04, 0xd2, 0x9f, 0x22, 0xf5, 0xfd, 0xfe, 0x89, 0xeb, 0xab, 0x41, 0xc0, 0xac, 0x2b, 0x64,
+ 0xfe, 0x1e, 0x9b, 0x68, 0x07, 0xfd, 0x75, 0x25, 0x24, 0xa0, 0x41, 0x5d, 0x79, 0xb5, 0x67, 0x93,
+ 0xe1, 0xa3, 0x3a, 0x24, 0xa0, 0xbf, 0x64, 0x62, 0x38, 0x65, 0x75, 0x78, 0x8a, 0xf9, 0x7c, 0x00,
+ 0x71, 0x38, 0xc5, 0xe4, 0xdc, 0xf8, 0xc5, 0xc5, 0x8d, 0x1d, 0x6b, 0xb8, 0x84, 0x4e, 0x21, 0x6d,
+ 0x55, 0x95, 0x31, 0x86, 0x11, 0xe6, 0xb1, 0x77, 0x77, 0x3b, 0x01, 0x82, 0xab, 0x88, 0xef, 0x77,
+ 0x08, 0xd8, 0x80, 0xba, 0x41, 0xfb, 0xb3, 0x30, 0x5f, 0xf2, 0x5b, 0xe6, 0x5a, 0x63, 0xb0, 0xa4,
+ 0x37, 0x37, 0x6d, 0x1f, 0x27, 0x0e, 0x80, 0x8e, 0x1a, 0x45, 0x97, 0xdb, 0x61, 0x10, 0x24, 0x8a,
+ 0x62, 0x44, 0xf2, 0x91, 0x74, 0x25, 0x3e, 0xc5, 0xe6, 0x8e, 0x55, 0x44, 0x5a, 0x8a, 0x90, 0x25,
+ 0xa1, 0x0d, 0x43, 0x35, 0x46, 0x80, 0xfe, 0xb3, 0x4e, 0x4c, 0x21, 0xcc, 0x99, 0xc2, 0x3d, 0xce,
+ 0x19, 0xc5, 0x2c, 0xae, 0xe8, 0x94, 0xad, 0xed, 0x36, 0xb5, 0x8e, 0xf1, 0x81, 0xfe, 0x62, 0x3a,
+ 0x8c, 0xe0, 0x90, 0x88, 0xf1, 0x31, 0xc5, 0xd9, 0x3c, 0xf4, 0x70, 0x7d, 0x7d, 0x1c, 0xca, 0xe2,
+ 0x51, 0xce, 0xa0, 0x33, 0x42, 0x1e, 0xf7, 0xe4, 0x13, 0xcf, 0xa0, 0x95, 0x33, 0x59, 0x5b, 0xec,
+ 0xf7, 0x6d, 0x56, 0xac, 0x6a, 0xae, 0x55, 0x9b, 0x92, 0x14, 0x6d, 0x01, 0x23, 0x4b, 0x80, 0xae,
+ 0x65, 0x15, 0xc9, 0x84, 0x66, 0xd7, 0xbd, 0x16, 0xd2, 0xe7, 0x15, 0x95, 0x16, 0x9c, 0xd3, 0xd2,
+ 0x62, 0x51, 0xf6, 0xe3, 0xa6, 0xea, 0x32, 0x86, 0x67, 0xcc, 0x4a, 0x46, 0x4d, 0x37, 0x45, 0xd5,
+};
+
+void pgm_pstar_decrypt(void)
+{
+
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x100000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x40480) != 0x00080)
+ x ^= 0x0100;
+
+ if((i & 0x00030) == 0x00010)
+ x ^= 0x0400;
+
+ if((i & 0x00242) != 0x00042)
+ x ^= 0x0800;
+
+ if((i & 0x08100) == 0x08000)
+ x ^= 0x1000;
+
+ if((i & 0x22004) != 0x00004)
+ x ^= 0x2000;
+
+ if((i & 0x11800) != 0x10000)
+ x ^= 0x4000;
+
+ if((i & 0x04820) == 0x04820)
+ x ^= 0x8000;
+
+ x = x ^ pstar[i & 255];
+ src[i] = (x<<8)|(x>>8) ;
+ }
+}
+
+void pgm_dw3_decrypt(void)
+{
+
+// int i;
+// UINT16 *src=(UINT16 *) (OP_ROM+0x100000);
+
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x100000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x005460) == 0x001400)
+ x ^= 0x0100;
+
+ if((i & 0x005450) == 0x001040)
+ x ^= 0x0100;
+
+ if((i & 0x005e00) == 0x001c00)
+ x ^= 0x40;
+
+ if((i & 0x005580) == 0x001100)
+ x ^= 0x40;
+
+
+
+ src[i] = x;
+ }
+}
+
+void pgm_killbld_decrypt(void)
+{
+
+// int i;
+// UINT16 *src=(UINT16 *) (OP_ROM+0x100000);
+
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x200000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x6d00) == 0x0400 || (i & 0x6c80) == 0x0880)
+ x ^= 0x0008;
+ if((i & 0x7500) == 0x2400 || (i & 0x7600) == 0x3200)
+ x ^= 0x1000;
+
+ src[i] = x;
+ }
+}
+
+
+#ifdef UNUSED_FUNCTION
+static UINT8 dfront_tab[256] = {
+ 0x51, 0xc4, 0xe3, 0x10, 0x1c, 0xad, 0x8a, 0x39, 0x8c, 0xe0, 0xa5, 0x04, 0x0f, 0xe4, 0x35, 0xc3,
+ 0x2d, 0x6b, 0x32, 0xe2, 0x60, 0x54, 0x63, 0x06, 0xa3, 0xf1, 0x0b, 0x5f, 0x6c, 0x5c, 0xb3, 0xec,
+ 0x77, 0x61, 0x69, 0xe7, 0x3c, 0xb7, 0x42, 0x72, 0x1a, 0x70, 0xb0, 0x96, 0xa4, 0x28, 0xc0, 0xfb,
+ 0x0a, 0x00, 0xcb, 0x15, 0x49, 0x48, 0xd3, 0x94, 0x58, 0xcf, 0x41, 0x86, 0x17, 0x71, 0xb1, 0xbd,
+ 0x21, 0x01, 0x37, 0x1e, 0xba, 0xeb, 0xf3, 0x59, 0xf6, 0xa7, 0x29, 0x4f, 0xb5, 0xca, 0x4c, 0x34,
+ 0x20, 0xa2, 0x62, 0x4b, 0x93, 0x9e, 0x47, 0x9f, 0x8d, 0x0e, 0x1b, 0xb6, 0x4d, 0x82, 0xd5, 0xf4,
+ 0x85, 0x79, 0x53, 0x92, 0x9b, 0xf7, 0xea, 0x44, 0x76, 0x1f, 0x22, 0x45, 0xed, 0xbe, 0x11, 0x55,
+ 0xaf, 0xf5, 0xf8, 0x50, 0x07, 0xe6, 0xc7, 0x5e, 0xd7, 0xde, 0xe5, 0x26, 0x2b, 0xf2, 0x6a, 0x8b,
+ 0xb8, 0x98, 0x89, 0xdb, 0x14, 0x5b, 0xc5, 0x78, 0xdc, 0xd0, 0x87, 0x5d, 0xc1, 0x0d, 0x95, 0x97,
+ 0x7e, 0xa8, 0x24, 0x3d, 0xe1, 0xd1, 0x19, 0xa6, 0x99, 0xd8, 0x83, 0x1d, 0xff, 0x30, 0x9d, 0x05,
+ 0xd4, 0x02, 0x27, 0x7b, 0x13, 0xb2, 0x7f, 0x40, 0x12, 0xa0, 0x68, 0x67, 0x4e, 0x3a, 0x46, 0xb9,
+ 0xee, 0xdf, 0x66, 0xd6, 0x8f, 0xa9, 0x0c, 0x91, 0x65, 0x18, 0x52, 0x56, 0xd9, 0x74, 0x09, 0x6e,
+ 0xc6, 0x73, 0xc9, 0xfc, 0x03, 0x43, 0xef, 0xaa, 0x7c, 0xbb, 0x2c, 0x90, 0xcc, 0xce, 0xe8, 0xae,
+ 0x2a, 0xf9, 0x57, 0x88, 0xc8, 0xe9, 0x5a, 0xdd, 0x2e, 0x7d, 0x64, 0xc2, 0x6d, 0x3e, 0xfa, 0x80,
+ 0x16, 0xcd, 0x6f, 0x84, 0x8e, 0x9c, 0xf0, 0xac, 0xb4, 0x9a, 0x2f, 0xbc, 0x31, 0x23, 0xfe, 0x38,
+ 0x08, 0x75, 0xa1, 0x33, 0xab, 0xd2, 0xda, 0x81, 0xbf, 0x7a, 0x3b, 0x3f, 0x4a, 0xfd, 0x25, 0x36,
+};
+
+void pgm_dfront_decrypt(void)
+{
+ int i;
+ UINT16 *src = (UINT16 *)(memory_region(REGION_USER1));
+
+ int rom_size = 0x200000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x040080) != 0x000080)
+ x ^= 0x0001;
+
+ if((i & 0x104008) == 0x104008)
+ x ^= 0x0002;
+
+ if((i & 0x080030) == 0x080010)
+ x ^= 0x0004;
+
+ if((i & 0x000042) != 0x000042)
+ x ^= 0x0008;
+
+ if((i & 0x008100) == 0x008000)
+ x ^= 0x0010;
+
+ if((i & 0x002004) != 0x000004)
+ x ^= 0x0020;
+
+ if((i & 0x011800) != 0x010000)
+ x ^= 0x0040;
+
+ if((i & 0x004820) == 0x004820)
+ x ^= 0x0080;
+
+ x ^= dfront_tab[(i>> 1) & 0xff] << 8;
+
+ src[i] = x;
+ }
+}
+
+
+static UINT8 ddp2_tab[256] = {
+ 0x2a, 0x4a, 0x39, 0x98, 0xac, 0x39, 0xb2, 0x55, 0x72, 0xf3, 0x7b, 0x3c, 0xee, 0x94, 0x6e, 0xd5,
+ 0xcd, 0xbc, 0x9a, 0xd0, 0x45, 0x7d, 0x49, 0x68, 0xb1, 0x61, 0x54, 0xef, 0xa2, 0x84, 0x29, 0x20,
+ 0x32, 0x52, 0x82, 0x04, 0x38, 0x69, 0x9f, 0x24, 0x46, 0xf4, 0x3f, 0xc2, 0xf1, 0x25, 0xac, 0x2d,
+ 0xdf, 0x2d, 0xb4, 0x51, 0xc7, 0xb5, 0xe5, 0x88, 0xbd, 0x3b, 0x5a, 0x25, 0x5b, 0xc7, 0xae, 0x5f,
+ 0x43, 0xcf, 0x89, 0xd9, 0xe2, 0x63, 0xc6, 0x76, 0x21, 0x2b, 0x77, 0xc0, 0x27, 0x98, 0xfd, 0x09,
+ 0xe1, 0x8c, 0x26, 0x2e, 0x92, 0x99, 0xbc, 0xbe, 0x0e, 0xba, 0xbf, 0x70, 0xe7, 0xb7, 0xe9, 0x37,
+ 0x5c, 0xd1, 0x5e, 0xad, 0x22, 0x17, 0xc5, 0x67, 0x9d, 0xc6, 0xfb, 0x53, 0xc7, 0x4d, 0x32, 0xb4,
+ 0xf2, 0x43, 0x53, 0x7c, 0x01, 0xfe, 0xd2, 0x91, 0x40, 0x85, 0xa3, 0xe8, 0xdf, 0xdb, 0xff, 0x6c,
+ 0x64, 0x15, 0xcd, 0x8e, 0x07, 0x82, 0x78, 0x8d, 0x4e, 0x2d, 0x66, 0x8a, 0x62, 0x6f, 0xd3, 0x6a,
+ 0xae, 0x16, 0x44, 0x1e, 0xed, 0xc4, 0x12, 0x7a, 0xbe, 0x05, 0x06, 0xce, 0x9b, 0x8a, 0xf7, 0xf8,
+ 0x74, 0x23, 0x73, 0x74, 0xb8, 0x13, 0xc2, 0x42, 0xea, 0xf9, 0x7f, 0xa9, 0xaf, 0x56, 0xd6, 0xb3,
+ 0xb7, 0xc4, 0x47, 0x31, 0x67, 0xaa, 0x58, 0x8b, 0x47, 0x1b, 0xf5, 0x75, 0x95, 0x8f, 0xf0, 0x3a,
+ 0x85, 0x76, 0x59, 0x24, 0x0c, 0xd7, 0x00, 0xb3, 0xdc, 0xfc, 0x65, 0x34, 0xde, 0xfa, 0xd8, 0xc3,
+ 0xc3, 0x5e, 0xe3, 0x9e, 0x02, 0x28, 0x50, 0x81, 0x95, 0x2f, 0xe4, 0xb5, 0xa0, 0x4d, 0xa1, 0x36,
+ 0x9d, 0x18, 0x6d, 0x79, 0x19, 0x3b, 0x1d, 0xb8, 0xe1, 0xcc, 0x61, 0x1a, 0xe2, 0x31, 0x4c, 0x3f,
+ 0xdc, 0xca, 0xd4, 0xda, 0xcd, 0xd2, 0x83, 0xca, 0xeb, 0x4f, 0xf2, 0x2f, 0x2d, 0x2a, 0xec, 0x1f
+};
+
+void pgm_ddp2_decrypt(void)
+{
+ int i;
+ UINT16 *src = (UINT16 *)(memory_region(REGION_USER1));
+
+ int rom_size = 0x200000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x0480) != 0x0080)
+ x ^= 0x0001;
+
+ if((i & 0x0042) != 0x0042)
+ x ^= 0x0008;
+
+ if((i & 0x8100) == 0x8000)
+ x ^= 0x0010;
+
+ if((i & 0x2004) != 0x0004)
+ x ^= 0x0020;
+
+ if((i & 0x1800) != 0x0000)
+ x ^= 0x0040;
+
+ if((i & 0x0820) == 0x0820)
+ x ^= 0x0080;
+
+ x ^= ddp2_tab[(i>> 1) & 0xff] << 8;
+
+ src[i] = x;
+ }
+}
+#endif
+
+
+static UINT8 mm_tab[256] = {
+ 0xd0, 0x45, 0xbc, 0x84, 0x93, 0x60, 0x7d, 0x49, 0x68, 0xb1, 0x54, 0xa2, 0x05, 0x29, 0x41, 0x20,
+ 0x04, 0x08, 0x52, 0x25, 0x89, 0xf4, 0x69, 0x9f, 0x24, 0x46, 0x3d, 0xf1, 0xf9, 0xab, 0xa6, 0x2d,
+ 0x18, 0x19, 0x6d, 0x33, 0x79, 0x23, 0x3b, 0x1d, 0xe0, 0xb8, 0x61, 0x1a, 0xe1, 0x4c, 0x5d, 0x3f,
+ 0x5e, 0x02, 0xe3, 0x4d, 0x9e, 0x80, 0x28, 0x50, 0xa0, 0x81, 0xe4, 0xa5, 0x97, 0xa1, 0x86, 0x36,
+ 0x1e, 0xed, 0x16, 0x8a, 0x44, 0x06, 0x64, 0x12, 0x9a, 0x7e, 0xce, 0x9b, 0xef, 0xf7, 0x3e, 0xf8,
+ 0x15, 0x07, 0xcb, 0x6f, 0x8e, 0x3c, 0x82, 0x70, 0x62, 0x8d, 0x66, 0x7a, 0x4e, 0xd3, 0xb6, 0x6a,
+ 0x51, 0xa7, 0x2c, 0xc7, 0xa4, 0x0b, 0xb5, 0xe5, 0x88, 0xbd, 0x5a, 0x5b, 0x1b, 0xae, 0xe6, 0x5f,
+ 0x2e, 0x92, 0x8c, 0xb7, 0x96, 0xba, 0x99, 0xbb, 0xbe, 0x0e, 0xbf, 0xe7, 0x2f, 0xe9, 0x30, 0x37,
+ 0x98, 0xac, 0x4a, 0x94, 0x38, 0xf3, 0x39, 0xb2, 0x55, 0x72, 0x7b, 0xee, 0xdd, 0x6e, 0x11, 0xd5,
+ 0x26, 0xa8, 0x71, 0xd6, 0x74, 0x7f, 0x13, 0xc2, 0x56, 0xea, 0xa9, 0xaf, 0xc3, 0x42, 0x03, 0xb3,
+ 0xc4, 0x6b, 0x47, 0xf0, 0x31, 0xf5, 0xaa, 0x58, 0x8f, 0x48, 0x75, 0x95, 0x35, 0x8b, 0x57, 0x3a,
+ 0x73, 0x0c, 0x59, 0xd8, 0x14, 0x65, 0xd7, 0x00, 0xfa, 0xdc, 0x34, 0xde, 0xc0, 0xb0, 0x87, 0xc1,
+ 0xc8, 0xcd, 0xd4, 0x2a, 0xda, 0xe8, 0xd2, 0x83, 0x0d, 0xca, 0xf2, 0x0f, 0xeb, 0xec, 0x9c, 0x1f,
+ 0xad, 0x22, 0xd1, 0x4b, 0x5c, 0xf6, 0x17, 0xc5, 0x67, 0x9d, 0xfb, 0xc9, 0xcc, 0x32, 0x1c, 0xb4,
+ 0xd9, 0xe2, 0xcf, 0x90, 0xb9, 0x2b, 0x63, 0xc6, 0x76, 0x21, 0x77, 0x27, 0xfc, 0xfd, 0x0a, 0x09,
+ 0x7c, 0x01, 0x43, 0xdb, 0x53, 0x85, 0xfe, 0x78, 0x91, 0x40, 0xa3, 0xdf, 0x4f, 0xff, 0x10, 0x6c,
+};
+
+void pgm_mm_decrypt(void)
+{
+ int i;
+ UINT16 *src = (UINT16 *)(memory_region(REGION_USER1));
+
+ int rom_size = 0x200000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x040480) != 0x000080)
+ x ^= 0x0001;
+
+ if((i & 0x004008) == 0x004008)
+ x ^= 0x0002;
+
+ if((i & 0x000030) == 0x000010)
+ x ^= 0x0004;
+
+ if((i & 0x000242) != 0x000042)
+ x ^= 0x0008;
+
+ if((i & 0x008100) == 0x008000)
+ x ^= 0x0010;
+
+ if((i & 0x022004) != 0x000004)
+ x ^= 0x0020;
+
+ if((i & 0x011800) != 0x010000)
+ x ^= 0x0040;
+
+ if((i & 0x000820) == 0x000820)
+ x ^= 0x0080;
+
+ x ^= mm_tab[(i>> 1) & 0xff] << 8;
+
+ src[i] = x;
+ }
+}
+
+static const UINT8 kov2_tab[256] = {
+ 0x11, 0x4a, 0x38, 0x98, 0xac, 0x39, 0xb2, 0x55, 0x72, 0xf3, 0x7b, 0x3c, 0xee, 0x94, 0x6e, 0xd5,
+ 0x41, 0xbc, 0x93, 0xd0, 0x45, 0x7d, 0x49, 0x68, 0xb1, 0x60, 0x54, 0xef, 0xa2, 0x84, 0x29, 0x20,
+ 0xa6, 0x52, 0x89, 0x04, 0x08, 0x69, 0x9f, 0x24, 0x46, 0xf4, 0x3d, 0xc3, 0xf1, 0x25, 0xab, 0x2d,
+ 0xe6, 0x2c, 0xa4, 0x51, 0xa7, 0xb5, 0xe5, 0x88, 0xbd, 0x0b, 0x5a, 0x35, 0x5b, 0xc7, 0xae, 0x5f,
+ 0x0a, 0xcf, 0xb9, 0xd9, 0xe2, 0x63, 0xc6, 0x76, 0x21, 0x2b, 0x77, 0xc0, 0x27, 0x90, 0xfd, 0x09,
+ 0x30, 0x8c, 0x96, 0x2e, 0x92, 0x99, 0xbb, 0xbe, 0x0e, 0xba, 0xbf, 0x80, 0xe7, 0xb7, 0xe9, 0x37,
+ 0x1c, 0xd1, 0x5c, 0xad, 0x22, 0x17, 0xc5, 0x67, 0x9d, 0xf6, 0xfb, 0x23, 0xc9, 0x4b, 0x32, 0xb4,
+ 0x10, 0x43, 0x53, 0x7c, 0x01, 0xfe, 0x78, 0x91, 0x40, 0x85, 0xa3, 0xe8, 0xdf, 0xdb, 0xff, 0x6c,
+ 0xb6, 0x15, 0xcb, 0x8e, 0x07, 0x82, 0x70, 0x8d, 0x4e, 0xdd, 0x66, 0x7a, 0x62, 0x6f, 0xd3, 0x6a,
+ 0x3e, 0x16, 0x44, 0x1e, 0xed, 0x64, 0x12, 0x9a, 0x7e, 0x05, 0x06, 0xce, 0x9b, 0x8a, 0xf7, 0xf8,
+ 0x03, 0x26, 0x71, 0x74, 0xa8, 0x13, 0xc2, 0x42, 0xea, 0xf9, 0x7f, 0xa9, 0xaf, 0x56, 0xd6, 0xb3,
+ 0x57, 0xc4, 0x47, 0x31, 0x6b, 0xaa, 0x58, 0x8b, 0x48, 0x1b, 0xf5, 0x75, 0x95, 0x8f, 0xf0, 0x3a,
+ 0x87, 0x73, 0x59, 0x14, 0x0c, 0xd7, 0x00, 0xb0, 0xdc, 0xfc, 0x65, 0x34, 0xde, 0xfa, 0xd8, 0xc1,
+ 0x86, 0x5e, 0xe3, 0x9e, 0x02, 0x28, 0x50, 0x81, 0x97, 0x2f, 0xe4, 0xa5, 0xa0, 0x4d, 0xa1, 0x36,
+ 0x5d, 0x18, 0x6d, 0x79, 0x19, 0x3b, 0x1d, 0xb8, 0xe1, 0xcc, 0x61, 0x1a, 0xe0, 0x33, 0x4c, 0x3f,
+ 0x9c, 0xc8, 0xd4, 0xda, 0xcd, 0xd2, 0x83, 0xca, 0xeb, 0x4f, 0xf2, 0x0f, 0x0d, 0x2a, 0xec, 0x1f,
+};
+
+void pgm_kov2_decrypt(void)
+{
+ int i;
+ UINT16 *src = (UINT16 *)(memory_region(REGION_USER1));
+
+ int rom_size = 0x200000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x40080) != 0x00080)
+ x ^= 0x0001;
+
+ if((i & 0x80030) == 0x80010)
+ x ^= 0x0004;
+
+ if((i & 0x00042) != 0x00042)
+ x ^= 0x0008;
+
+ if((i & 0x48100) == 0x48000)
+ x ^= 0x0010;
+
+ if((i & 0x22004) != 0x00004)
+ x ^= 0x0020;
+
+ if((i & 0x01800) != 0x00000)
+ x ^= 0x0040;
+
+ if((i & 0x00820) == 0x00820)
+ x ^= 0x0080;
+
+ x ^= kov2_tab[(i >> 1) & 0xff] << 8;
+
+ src[i] = x;
+ }
+}
+
+static const UINT8 puzzli2_tab[256] = {
+ 0xb7, 0x66, 0xa3, 0xc0, 0x51, 0x55, 0x6d, 0x63, 0x86, 0x60, 0x64, 0x6c, 0x67, 0x18, 0x0b, 0x05,
+ 0x62, 0xff, 0xe0, 0x1e, 0x30, 0x21, 0x2e, 0x40, 0x41, 0xb9, 0x60, 0x38, 0xd1, 0x24, 0x7e, 0x36,
+ 0x7a, 0x0b, 0x1c, 0x69, 0x4f, 0x09, 0xe1, 0x9e, 0xcf, 0xcd, 0x7c, 0x00, 0x73, 0x08, 0x77, 0x37,
+ 0x5f, 0x50, 0x32, 0x3e, 0xd3, 0x54, 0x77, 0x6b, 0x60, 0x60, 0x74, 0x7c, 0x55, 0x4f, 0x44, 0x5e,
+ 0x66, 0x5c, 0x58, 0x26, 0x35, 0x29, 0x3f, 0x35, 0x3f, 0x1c, 0x0b, 0x0d, 0x08, 0x5b, 0x59, 0x5c,
+ 0xa0, 0xa5, 0x87, 0x85, 0x24, 0x75, 0x5f, 0x42, 0x1b, 0xf3, 0x1a, 0x58, 0x17, 0x58, 0x71, 0x6b,
+ 0x69, 0x89, 0x7d, 0x3a, 0xf3, 0xc4, 0x5d, 0xa0, 0x4f, 0x27, 0x58, 0xc4, 0xa8, 0xdd, 0xa8, 0xfb,
+ 0xbe, 0xa4, 0xe2, 0xee, 0x07, 0x10, 0x90, 0x72, 0x99, 0x08, 0x68, 0x6d, 0x5c, 0x5c, 0x6d, 0x58,
+ 0x2f, 0xdc, 0x15, 0xd5, 0xd6, 0xd6, 0x3b, 0x3b, 0xf9, 0x32, 0xcc, 0xdd, 0xd4, 0xf1, 0xea, 0xed,
+ 0xe4, 0xf6, 0xf2, 0x91, 0xca, 0xc1, 0xed, 0xf2, 0xf6, 0xfb, 0xc0, 0xe8, 0xe3, 0xe7, 0xfa, 0xf1,
+ 0xf5, 0x08, 0x26, 0x2b, 0x2f, 0x34, 0x39, 0x13, 0x28, 0x07, 0x88, 0x5b, 0x8f, 0x94, 0x9b, 0x2e,
+ 0xf5, 0xab, 0x72, 0x76, 0x7a, 0x40, 0xb9, 0x09, 0xd8, 0x3b, 0xcd, 0x31, 0x3d, 0x42, 0xab, 0xb1,
+ 0xb5, 0xb9, 0x3b, 0xe3, 0x0b, 0x65, 0x18, 0xfb, 0x1f, 0x12, 0xe4, 0xe8, 0xec, 0xf2, 0xf7, 0xfc,
+ 0xc0, 0xe8, 0xe0, 0xe6, 0xfa, 0xf1, 0xf4, 0x0b, 0x26, 0x2b, 0x30, 0x35, 0x39, 0x13, 0x29, 0x21,
+ 0x0c, 0x11, 0x16, 0x1b, 0x1f, 0x64, 0x0e, 0x60, 0x05, 0x79, 0x7c, 0x37, 0x00, 0x0f, 0x4f, 0x38,
+ 0x1d, 0x18, 0xa2, 0xb6, 0xb2, 0xa9, 0xac, 0xab, 0xae, 0x91, 0x98, 0x8d, 0x91, 0xbb, 0xb1, 0xc0,
+};
+
+void pgm_puzzli2_decrypt(void)
+{
+ int i;
+ UINT16 *src = (UINT16 *) (memory_region(REGION_CPU1)+0x100000);
+
+ int rom_size = 0x100000;
+
+ for(i=0; i<rom_size/2; i++) {
+ UINT16 x = src[i];
+
+ if((i & 0x040080) != 0x000080)
+ x ^= 0x0100;
+
+ if((i & 0x004008) == 0x004008)
+ x ^= 0x0200;
+
+ if((i & 0x000030) == 0x000010)
+ x ^= 0x0400;
+
+ if((i & 0x000242) != 0x000042)
+ x ^= 0x0800;
+
+ if((i & 0x008100) == 0x008000)
+ x ^= 0x1000;
+
+ if((i & 0x022004) != 0x000004)
+ x ^= 0x2000;
+
+ if((i & 0x011800) != 0x010000)
+ x ^= 0x4000;
+
+ if((i & 0x004820) == 0x004820)
+ x ^= 0x8000;
+
+ x ^= puzzli2_tab[i & 0xff];
+ src[i] = (x<<8)|(x>>8) ;
+ }
+}
+
+
diff --git a/src/mame/machine/pgmprot.c b/src/mame/machine/pgmprot.c
new file mode 100644
index 00000000000..9ecdade6a75
--- /dev/null
+++ b/src/mame/machine/pgmprot.c
@@ -0,0 +1,891 @@
+#include "driver.h"
+
+extern UINT16 *pgm_mainram;
+
+/*** ASIC27a (Puzzle Star) -- ARM but with no external rom? behaves a bit like KOV ***/
+
+
+
+
+/*** (PSTARS) ***/
+static UINT16 PSTARSKEY;
+static UINT16 PSTARSINT[2];
+static UINT32 PSTARS_REGS[16];
+static UINT32 PSTARS_VAL;
+
+static UINT16 pstar_e7,pstar_b1,pstar_ce;
+static UINT16 pstar_ram[3];
+
+static int Pstar_ba[0x1E]={
+ 0x02,0x00,0x00,0x01,0x00,0x03,0x00,0x00, //0
+ 0x02,0x00,0x06,0x00,0x22,0x04,0x00,0x03, //8
+ 0x00,0x00,0x06,0x00,0x20,0x07,0x00,0x03, //10
+ 0x00,0x21,0x01,0x00,0x00,0x63
+};
+
+static int Pstar_b0[0x10]={
+ 0x09,0x0A,0x0B,0x00,0x01,0x02,0x03,0x04,
+ 0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00
+};
+
+static int Pstar_ae[0x10]={
+ 0x5D,0x86,0x8C ,0x8B,0xE0,0x8B,0x62,0xAF,
+ 0xB6,0xAF,0x10A,0xAF,0x00,0x00,0x00,0x00
+};
+
+static int Pstar_a0[0x10]={
+ 0x02,0x03,0x04,0x05,0x06,0x01,0x0A,0x0B,
+ 0x0C,0x0D,0x0E,0x09,0x00,0x00,0x00,0x00,
+};
+
+static int Pstar_9d[0x10]={
+ 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static int Pstar_90[0x10]={
+ 0x0C,0x10,0x0E,0x0C,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+static int Pstar_8c[0x23]={
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,
+ 0x03,0x03,0x03
+};
+
+static int Pstar_80[0x1a3]={
+ 0x03,0x03,0x04,0x04,0x04,0x04,0x05,0x05,
+ 0x05,0x05,0x06,0x06,0x03,0x03,0x04,0x04,
+ 0x05,0x05,0x05,0x05,0x06,0x06,0x07,0x07,
+ 0x03,0x03,0x04,0x04,0x05,0x05,0x05,0x05,
+ 0x06,0x06,0x07,0x07,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,
+ 0x07,0x07,0x08,0x08,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,
+ 0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,
+ 0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,
+ 0x07,0x08,0x08,0x08,0x08,0x09,0x09,0x09,
+ 0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
+ 0x08,0x08,0x09,0x09,0x05,0x05,0x06,0x06,
+ 0x06,0x07,0x07,0x08,0x08,0x08,0x08,0x09,
+ 0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,
+ 0x08,0x09,0x09,0x09,0x06,0x06,0x07,0x03,
+ 0x07,0x06,0x07,0x07,0x08,0x07,0x05,0x04,
+ 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x03,0x04,0x04,0x04,
+ 0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x07,
+ 0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06,
+ 0x06,0x07,0x07,0x08,0x05,0x05,0x06,0x07,
+ 0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x09,
+ 0x09,0x09,0x03,0x04,0x04,0x05,0x05,0x05,
+ 0x06,0x06,0x07,0x07,0x07,0x07,0x08,0x08,
+ 0x08,0x09,0x09,0x09,0x03,0x04,0x05,0x05,
+ 0x04,0x03,0x04,0x04,0x04,0x05,0x05,0x04,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00
+};
+
+
+
+
+READ16_HANDLER (PSTARS_protram_r)
+{
+ if (offset == 4) //region
+ return readinputport(4);
+ else if (offset >= 0x10) //timer
+ {
+ logerror("PSTARS ACCESS COUNTER %6X\n",pstar_ram[offset-0x10]);
+ return pstar_ram[offset-0x10]--;
+ }
+ return 0x0000;
+}
+
+READ16_HANDLER (PSTARS_r16)
+{
+ if(offset==0)
+ {
+ UINT16 d=PSTARS_VAL&0xffff;
+ UINT16 realkey;
+ realkey=PSTARSKEY>>8;
+ realkey|=PSTARSKEY;
+ d^=realkey;
+// logerror("PSTARS A27 R %6X\n",PSTARS_VAL);
+ return d;
+ }
+ else if(offset==1)
+ {
+ UINT16 d=PSTARS_VAL>>16;
+ UINT16 realkey;
+ realkey=PSTARSKEY>>8;
+ realkey|=PSTARSKEY;
+ d^=realkey;
+ return d;
+
+ }
+ return 0xff;
+}
+
+WRITE16_HANDLER (PSTARS_w16)
+{
+ if(offset==0)
+ {
+ PSTARSINT[0]=data;
+ return;
+ }
+
+ if(offset==1)
+ {
+ UINT16 realkey;
+ if((data>>8)==0xff)
+ PSTARSKEY=0xff00;
+ realkey=PSTARSKEY>>8;
+ realkey|=PSTARSKEY;
+ {
+ PSTARSKEY+=0x100;
+ PSTARSKEY&=0xff00;
+ if(PSTARSKEY==0xff00)PSTARSKEY=0x100;
+ }
+ data^=realkey;
+ PSTARSINT[1]=data;
+ PSTARSINT[0]^=realkey;
+
+ switch(PSTARSINT[1]&0xff)
+ {
+ case 0x99:
+ {
+ PSTARSKEY=0x100;
+ PSTARS_VAL=0x880000;
+
+ }
+ break;
+
+ case 0xE0:
+ {
+ PSTARS_VAL=0xa00000+(PSTARSINT[0]<<6);
+ }
+ break;
+ case 0xDC:
+ {
+ PSTARS_VAL=0xa00800+(PSTARSINT[0]<<6);
+ }
+ break;
+ case 0xD0:
+ {
+ PSTARS_VAL=0xa01000+(PSTARSINT[0]<<5);
+ }
+ break;
+
+ case 0xb1:
+ {
+ pstar_b1=PSTARSINT[0];
+ PSTARS_VAL=0x890000;
+ }
+ break;
+ case 0xbf:
+ {
+ PSTARS_VAL=pstar_b1*PSTARSINT[0];
+ }
+ break;
+
+ case 0xc1: //TODO:TIMER 0,1,2,FIX TO 0 should be OK?
+ {
+ PSTARS_VAL=0;
+ }
+ break;
+ case 0xce: //TODO:TIMER 0,1,2
+ {
+ pstar_ce=PSTARSINT[0];
+ PSTARS_VAL=0x890000;
+ }
+ break;
+ case 0xcf: //TODO:TIMER 0,1,2
+ {
+ pstar_ram[pstar_ce]=PSTARSINT[0];
+ PSTARS_VAL=0x890000;
+ }
+ break;
+
+
+ case 0xe7:
+ {
+ pstar_e7=(PSTARSINT[0]>>12)&0xf;
+ PSTARS_REGS[pstar_e7]&=0xffff;
+ PSTARS_REGS[pstar_e7]|=(PSTARSINT[0]&0xff)<<16;
+ PSTARS_VAL=0x890000;
+ }
+ break;
+ case 0xe5:
+ {
+
+ PSTARS_REGS[pstar_e7]&=0xff0000;
+ PSTARS_REGS[pstar_e7]|=PSTARSINT[0];
+ PSTARS_VAL=0x890000;
+ }
+ break;
+ case 0xf8: //@73C
+ {
+ PSTARS_VAL=PSTARS_REGS[PSTARSINT[0]&0xf]&0xffffff;
+ }
+ break;
+
+
+ case 0xba:
+ {
+ PSTARS_VAL=Pstar_ba[PSTARSINT[0]];
+ }
+ break;
+ case 0xb0:
+ {
+ PSTARS_VAL=Pstar_b0[PSTARSINT[0]];
+ }
+ break;
+ case 0xae:
+ {
+ PSTARS_VAL=Pstar_ae[PSTARSINT[0]];
+ }
+ break;
+ case 0xa0:
+ {
+ PSTARS_VAL=Pstar_a0[PSTARSINT[0]];
+ }
+ break;
+ case 0x9d:
+ {
+ PSTARS_VAL=Pstar_9d[PSTARSINT[0]];
+ }
+ break;
+ case 0x90:
+ {
+ PSTARS_VAL=Pstar_90[PSTARSINT[0]];
+ }
+ break;
+ case 0x8c:
+ {
+ PSTARS_VAL=Pstar_8c[PSTARSINT[0]];
+ }
+ break;
+ case 0x80:
+ {
+ PSTARS_VAL=Pstar_80[PSTARSINT[0]];
+ }
+ break;
+ default:
+ PSTARS_VAL=0x890000;
+ logerror("PSTARS PC(%06x) UNKNOWN %4X %4X\n",activecpu_get_pc(),PSTARSINT[1],PSTARSINT[0]);
+
+ }
+
+ }
+}
+
+/*** ASIC 3 (oriental legends protection) ****************************************/
+
+static UINT8 asic3_reg, asic3_latch[3], asic3_x, asic3_y, asic3_z, asic3_h1, asic3_h2;
+static UINT16 asic3_hold;
+
+static UINT32 bt(UINT32 v, int bit)
+{
+ return (v & (1<<bit)) != 0;
+}
+
+static void asic3_compute_hold(void)
+{
+ // The mode is dependant on the region
+ static int modes[4] = { 1, 1, 3, 2 };
+ int mode = modes[readinputport(4) & 3];
+
+ switch(mode) {
+ case 1:
+ asic3_hold =
+ (asic3_hold << 1)
+ ^0x2bad
+ ^bt(asic3_hold, 15)^bt(asic3_hold, 10)^bt(asic3_hold, 8)^bt(asic3_hold, 5)
+ ^bt(asic3_z, asic3_y)
+ ^(bt(asic3_x, 0) << 1)^(bt(asic3_x, 1) << 6)^(bt(asic3_x, 2) << 10)^(bt(asic3_x, 3) << 14);
+ break;
+ case 2:
+ asic3_hold =
+ (asic3_hold << 1)
+ ^0x2bad
+ ^bt(asic3_hold, 15)^bt(asic3_hold, 7)^bt(asic3_hold, 6)^bt(asic3_hold, 5)
+ ^bt(asic3_z, asic3_y)
+ ^(bt(asic3_x, 0) << 4)^(bt(asic3_x, 1) << 6)^(bt(asic3_x, 2) << 10)^(bt(asic3_x, 3) << 12);
+ break;
+ case 3:
+ asic3_hold =
+ (asic3_hold << 1)
+ ^0x2bad
+ ^bt(asic3_hold, 15)^bt(asic3_hold, 10)^bt(asic3_hold, 8)^bt(asic3_hold, 5)
+ ^bt(asic3_z, asic3_y)
+ ^(bt(asic3_x, 0) << 4)^(bt(asic3_x, 1) << 6)^(bt(asic3_x, 2) << 10)^(bt(asic3_x, 3) << 12);
+ break;
+ }
+}
+
+READ16_HANDLER( pgm_asic3_r )
+{
+ UINT8 res = 0;
+ /* region is supplied by the protection device */
+
+ switch(asic3_reg) {
+ case 0x00: res = (asic3_latch[0] & 0xf7) | ((readinputport(4) << 3) & 0x08); break;
+ case 0x01: res = asic3_latch[1]; break;
+ case 0x02: res = (asic3_latch[2] & 0x7f) | ((readinputport(4) << 6) & 0x80); break;
+ case 0x03:
+ res = (bt(asic3_hold, 15) << 0)
+ | (bt(asic3_hold, 12) << 1)
+ | (bt(asic3_hold, 13) << 2)
+ | (bt(asic3_hold, 10) << 3)
+ | (bt(asic3_hold, 7) << 4)
+ | (bt(asic3_hold, 9) << 5)
+ | (bt(asic3_hold, 2) << 6)
+ | (bt(asic3_hold, 5) << 7);
+ break;
+ case 0x20: res = 0x49; break;
+ case 0x21: res = 0x47; break;
+ case 0x22: res = 0x53; break;
+ case 0x24: res = 0x41; break;
+ case 0x25: res = 0x41; break;
+ case 0x26: res = 0x7f; break;
+ case 0x27: res = 0x41; break;
+ case 0x28: res = 0x41; break;
+ case 0x2a: res = 0x3e; break;
+ case 0x2b: res = 0x41; break;
+ case 0x2c: res = 0x49; break;
+ case 0x2d: res = 0xf9; break;
+ case 0x2e: res = 0x0a; break;
+ case 0x30: res = 0x26; break;
+ case 0x31: res = 0x49; break;
+ case 0x32: res = 0x49; break;
+ case 0x33: res = 0x49; break;
+ case 0x34: res = 0x32; break;
+ }
+
+ return res;
+}
+
+WRITE16_HANDLER( pgm_asic3_w )
+{
+ if(ACCESSING_LSB)
+ {
+ if(asic3_reg < 3)
+ asic3_latch[asic3_reg] = data << 1;
+ else if(asic3_reg == 0xa0) {
+ asic3_hold = 0;
+ } else if(asic3_reg == 0x40) {
+ asic3_h2 = asic3_h1;
+ asic3_h1 = data;
+ } else if(asic3_reg == 0x48) {
+ asic3_x = 0;
+ if(!(asic3_h2 & 0x0a))
+ asic3_x |= 8;
+ if(!(asic3_h2 & 0x90))
+ asic3_x |= 4;
+ if(!(asic3_h1 & 0x06))
+ asic3_x |= 2;
+ if(!(asic3_h1 & 0x90))
+ asic3_x |= 1;
+ } else if(asic3_reg >= 0x80 && asic3_reg <= 0x87) {
+ asic3_y = asic3_reg & 7;
+ asic3_z = data;
+ asic3_compute_hold();
+ }
+ }
+}
+
+WRITE16_HANDLER( pgm_asic3_reg_w )
+{
+ if(ACCESSING_LSB)
+ asic3_reg = data & 0xff;
+}
+
+/*** Knights of Valour / Sango / PhotoY2k Protection (from ElSemi) (ASIC28) ***/
+
+static UINT16 ASIC28KEY;
+static UINT16 ASIC28REGS[10];
+static UINT16 ASICPARAMS[256];
+static UINT16 ASIC28RCNT=0;
+static const UINT32 B0TABLE[16]={2,0,1,4,3}; //maps char portraits to tables
+
+// photo2yk bonus stage
+static const UINT32 AETABLE[16]={0x00,0x0a,0x14,
+ 0x01,0x0b,0x15,
+ 0x02,0x0c,0x16};
+
+//Not sure if BATABLE is complete
+static const UINT32 BATABLE[0x40]=
+ {0x00,0x29,0x2c,0x35,0x3a,0x41,0x4a,0x4e, //0x00
+ 0x57,0x5e,0x77,0x79,0x7a,0x7b,0x7c,0x7d, //0x08
+ 0x7e,0x7f,0x80,0x81,0x82,0x85,0x86,0x87, //0x10
+ 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x90, //0x18
+ 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,
+ 0x9e,0xa3,0xd4,0xa9,0xaf,0xb5,0xbb,0xc1};
+
+static UINT32 E0REGS[16];
+
+
+READ16_HANDLER (sango_protram_r)
+{
+
+
+ // at offset == 4 is region (supplied by device)
+ // 0 = china
+ // 1 = taiwan
+ // 2 = japan
+ // 3 = korea
+ // 4 = hong kong
+ // 5 = world
+
+ if (offset == 4) return readinputport(4);
+
+ // otherwise it doesn't seem to use the ram for anything important, we return 0 to avoid test mode corruption
+ // kovplus reads from offset 000e a lot ... why?
+#ifdef MAME_DEBUG
+ popmessage ("protection ram r %04x",offset);
+#endif
+ return 0x0000;
+}
+
+static UINT32 photoy2k_seqpos;
+static UINT32 photoy2k_trf[3], photoy2k_soff;
+
+#define BITSWAP10(val,B9,B8,B7,B6,B5,B4,B3,B2,B1,B0) \
+ ((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))
+
+static UINT32 photoy2k_spritenum(void)
+{
+ UINT32 base = photoy2k_seqpos & 0xffc00;
+ UINT32 low = photoy2k_seqpos & 0x003ff;
+
+ switch((photoy2k_seqpos >> 10) & 0xf) {
+ case 0x0:
+ case 0xa:
+ return base | (BITSWAP10(low, 0,8,3,1,5,9,4,2,6,7) ^ 0x124);
+ case 0x1:
+ case 0xb:
+ return base | (BITSWAP10(low, 5,1,7,4,0,8,3,6,9,2) ^ 0x088);
+ case 0x2:
+ case 0x8:
+ return base | (BITSWAP10(low, 3,5,9,7,6,4,1,8,2,0) ^ 0x011);
+ case 0x3:
+ case 0x9:
+ return base | (BITSWAP10(low, 1,8,3,6,0,4,5,2,9,7) ^ 0x154);
+ case 0x4:
+ case 0xe:
+ return base | (BITSWAP10(low, 2,1,7,4,5,8,3,6,9,0) ^ 0x0a9);
+ case 0x5:
+ case 0xf:
+ return base | (BITSWAP10(low, 9,4,6,8,2,1,7,5,3,0) ^ 0x201);
+ case 0x6:
+ case 0xd:
+ return base | (BITSWAP10(low, 4,6,0,8,9,7,3,5,1,2) ^ 0x008);
+ case 0x7:
+ case 0xc:
+ return base | (BITSWAP10(low, 8,9,3,2,0,1,6,7,5,4) ^ 0x000);
+ }
+ return 0;
+}
+
+READ16_HANDLER (ASIC28_r16)
+//UINT16 ASIC28_r16(UINT32 addr)
+{
+ UINT32 val=(ASIC28REGS[1]<<16)|(ASIC28REGS[0]);
+
+//logerror("Asic28 Read PC = %06x Command = %02x ??\n",activecpu_get_pc(), ASIC28REGS[1]);
+
+ switch(ASIC28REGS[1]&0xff)
+ {
+
+ case 0x20: // PhotoY2k spritenum conversion 4/4
+ if(!ASIC28RCNT)
+ logerror("ASIC28: PhotoY2K spr4 %04x %06x (%06x)\n", val & 0xffff, photoy2k_trf[2], activecpu_get_pc());
+ val = photoy2k_soff >> 16;
+ break;
+
+ case 0x21: // PhotoY2k spritenum conversion 3/4
+ if(!ASIC28RCNT) {
+ extern const UINT32 pgmy2ks[];
+ photoy2k_trf[2] = val & 0xffff;
+ logerror("ASIC28: PhotoY2K spr3 %04x %06x (%06x)\n", val & 0xffff, photoy2k_trf[1], activecpu_get_pc());
+ if(photoy2k_trf[0] < 0x3c00)
+ photoy2k_soff = pgmy2ks[photoy2k_trf[0]];
+ else
+ photoy2k_soff = 0;
+ logerror("ASIC28: spriteval %04x, %06x -> %06x\n", photoy2k_trf[0], (photoy2k_trf[2]<<16)|photoy2k_trf[1], photoy2k_soff);
+ }
+ val = photoy2k_soff & 0xffff;
+ break;
+
+ case 0x22: // PhotoY2k spritenum conversion 2/4
+ if(!ASIC28RCNT) {
+ photoy2k_trf[1] = val & 0xffff;
+ logerror("ASIC28: PhotoY2K spr2 %04x %06x (%06x)\n", val & 0xffff, photoy2k_trf[0], activecpu_get_pc());
+ }
+ val = photoy2k_trf[0] | 0x880000;
+ break;
+
+ case 0x23: // PhotoY2k spritenum conversion 1/4
+ if(!ASIC28RCNT) {
+ photoy2k_trf[0] = val & 0xffff;
+ logerror("ASIC28: PhotoY2K spr1 %04x (%06x)\n", val & 0xffff, activecpu_get_pc());
+ }
+ val = 0x880000;
+ break;
+
+ case 0x30: // PhotoY2k next element
+ if(!ASIC28RCNT)
+ photoy2k_seqpos++;
+ val = photoy2k_spritenum();
+ if(!ASIC28RCNT)
+ logerror("ASIC28: PhotoY2K seq_next %05x -> %06x (%06x)\n", photoy2k_seqpos, val, activecpu_get_pc());
+ break;
+
+ case 0x32: // PhotoY2k start of sequence
+ if(!ASIC28RCNT)
+ photoy2k_seqpos = (val & 0xffff) << 4;
+ val = photoy2k_spritenum();
+ if(!ASIC28RCNT)
+ logerror("ASIC28: PhotoY2K seq_start %05x -> %06x (%06x)\n", photoy2k_seqpos, val, activecpu_get_pc());
+ break;
+
+ case 0x99:
+ val=0x880000;
+ break;
+
+ case 0x9d: // spr palette
+ val=0xa00000+((ASIC28REGS[0]&0x1f)<<6);
+ break;
+
+ case 0xae: //Photo Y2k Bonus stage
+ val=AETABLE[ASIC28REGS[0]&0xf];
+ break;
+
+ case 0xb0:
+ val=B0TABLE[ASIC28REGS[0]&0xf];
+ break;
+
+ case 0xb4:
+ {
+ int v2=ASIC28REGS[0]&0x0f;
+ int v1=(ASIC28REGS[0]&0x0f00)>>8;
+// UINT16 tmp=E0REGS[v2];
+ //E0REGS[v2]=E0REGS[v1];
+ //E0REGS[v1]=tmp;
+ if(ASIC28REGS[0]==0x102)
+ E0REGS[1]=E0REGS[0];
+ else
+ E0REGS[v1]=E0REGS[v2];
+
+ val=0x880000;
+ }
+ break;
+
+ case 0xba:
+ val=BATABLE[ASIC28REGS[0]&0x3f];
+ if(ASIC28REGS[0]>0x2f)
+ {
+// PutMessage("Unmapped BA com, report ElSemi",60);
+ popmessage ("Unmapped BA com %02x, contact ElSemi / MameDev", ASIC28REGS[0]);
+ }
+ break;
+
+ case 0xc0:
+ val=0x880000;
+ break;
+
+ case 0xc3: //TXT tile position Uses C0 to select column
+ {
+ val=0x904000+(ASICPARAMS[0xc0]+ASICPARAMS[0xc3]*64)*4;
+ }
+ break;
+
+ case 0xcb:
+ val=0x880000;
+ break;
+
+ case 0xcc: //BG
+ {
+ int y=ASICPARAMS[0xcc];
+ if(y&0x400) //y is signed (probably x too and it also applies to TXT, but I've never seen it used)
+ y=-(0x400-(y&0x3ff));
+ val=0x900000+(((ASICPARAMS[0xcb]+(y)*64)*4)/*&0x1fff*/);
+ }
+ break;
+
+ case 0xd0: //txt palette
+ val=0xa01000+(ASIC28REGS[0]<<5);
+ break;
+
+ case 0xd6: //???? check it
+ {
+ int v2=ASIC28REGS[0]&0xf;
+// int v1=(ASIC28REGS[0]&0xf0)>>4;
+ E0REGS[0]=E0REGS[v2];
+ //E0REGS[v2]=0;
+ val=0x880000;
+ }
+ break;
+
+ case 0xdc: //bg palette
+ val=0xa00800+(ASIC28REGS[0]<<6);
+ break;
+
+ case 0xe0: //spr palette
+ val=0xa00000+((ASIC28REGS[0]&0x1f)<<6);
+ break;
+
+ case 0xe5:
+ val=0x880000;
+ break;
+
+ case 0xe7:
+ val=0x880000;
+ break;
+
+ case 0xf0:
+ {
+ val=0x00C000;
+ }
+ break;
+
+ case 0xf8:
+ val=E0REGS[ASIC28REGS[0]&0xf]&0xffffff;
+ break;
+
+ case 0xfc: //Adjust damage level to char experience level
+ {
+ val=(ASICPARAMS[0xfc]*ASICPARAMS[0xfe])>>6;
+ break;
+ }
+
+ case 0xfe: //todo
+ val=0x880000;
+ break;
+
+
+ default:
+ {
+ val=0x880000;
+ }
+ }
+
+// if(addr==0x500000)
+ if(offset==0)
+ {
+ UINT16 d=val&0xffff;
+ UINT16 realkey;
+ realkey=ASIC28KEY>>8;
+ realkey|=ASIC28KEY;
+ d^=realkey;
+ return d;
+ }
+// else if(addr==0x500002)
+ else if(offset==1)
+ {
+ UINT16 d=val>>16;
+ UINT16 realkey;
+ realkey=ASIC28KEY>>8;
+ realkey|=ASIC28KEY;
+ d^=realkey;
+ ASIC28RCNT++;
+ if(!(ASIC28RCNT&0xf))
+ {
+ ASIC28KEY+=0x100;
+ ASIC28KEY&=0xFF00;
+ }
+ return d;
+ }
+ return 0xff;
+}
+
+WRITE16_HANDLER (ASIC28_w16)
+//void ASIC28_w16(UINT32 addr,UINT16 data)
+{
+// if(addr==0x500000)
+ if(offset==0)
+ {
+ UINT16 realkey;
+ realkey=ASIC28KEY>>8;
+ realkey|=ASIC28KEY;
+ data^=realkey;
+ ASIC28REGS[0]=data;
+ return;
+ }
+// if(addr==0x500002)
+ if(offset==1)
+ {
+ UINT16 realkey;
+
+ ASIC28KEY=data&0xff00;
+
+ realkey=ASIC28KEY>>8;
+ realkey|=ASIC28KEY;
+ data^=realkey;
+ ASIC28REGS[1]=data;
+// ErrorLogMessage("ASIC28 CMD %X PARAM %X",ASIC28REGS[1],ASIC28REGS[0]);
+ logerror("ASIC28 CMD %04x PARAM %04x\n",ASIC28REGS[1],ASIC28REGS[0]);
+
+ ASICPARAMS[ASIC28REGS[1]&0xff]=ASIC28REGS[0];
+ if(ASIC28REGS[1]==0xE7)
+ {
+ UINT32 E0R=(ASICPARAMS[0xE7]>>12)&0xf;
+ E0REGS[E0R]&=0xffff;
+ E0REGS[E0R]|=ASIC28REGS[0]<<16;
+ }
+ if(ASIC28REGS[1]==0xE5)
+ {
+ UINT32 E0R=(ASICPARAMS[0xE7]>>12)&0xf;
+ E0REGS[E0R]&=0xff0000;
+ E0REGS[E0R]|=ASIC28REGS[0];
+ }
+ ASIC28RCNT=0;
+ }
+}
+
+/* Dragon World 2 */
+
+#define DW2BITSWAP(s,d,bs,bd) d=((d&(~(1<<bd)))|(((s>>bs)&1)<<bd))
+//Use this handler for reading from 0xd80000-0xd80002
+READ16_HANDLER (dw2_d80000_r )
+{
+//addr&=0xff;
+// if(dw2reg<0x20) //NOT SURE!!
+ {
+ //The value at 0x80EECE is computed in the routine at 0x107c18
+ UINT16 d=pgm_mainram[0xEECE/2];
+ UINT16 d2=0;
+ d=(d>>8)|(d<<8);
+ DW2BITSWAP(d,d2,7 ,0);
+ DW2BITSWAP(d,d2,4 ,1);
+ DW2BITSWAP(d,d2,5 ,2);
+ DW2BITSWAP(d,d2,2 ,3);
+ DW2BITSWAP(d,d2,15,4);
+ DW2BITSWAP(d,d2,1 ,5);
+ DW2BITSWAP(d,d2,10,6);
+ DW2BITSWAP(d,d2,13,7);
+ // ... missing bitswaps here (8-15) there is not enough data to know them
+ // the code only checks the lowest 8 bytes
+ return d2;
+ }
+}
+
+/* Dragon World 3
+
+Dragon World 3 has 2 protection chips
+ASIC022 and ASIC025
+one of them also has an external data rom (encrypted?)
+
+code below is ElSemi's preliminary code, it doesn't work properly and isn't used, much of the protection isn't understood */
+
+#if 0
+AddWriteArea(0xda0000,0xdaffff,0,dw3_w8,dw3_w16,dw3_w32);
+AddReadArea (0xda0000,0xdaffff,0,dw3_r8,dw3_r16,dw3_r32);
+
+#define DW3BITSWAP(s,d,bs,bd) d=((d&(~(1<<bd)))|(((s>>bs)&1)<<bd))
+
+UINT16 dw3_Rw[8];
+UINT8 *dw3_R=(UINT8 *) dw3_Rw;
+
+UINT8 dw3_r8(UINT32 addr)
+{
+ if(addr>=0xDA5610 && addr<=0xDA5613)
+ return *((UINT8 *) (dw3_R+((addr-0xDA5610)^1)));
+ return 0;
+}
+
+UINT16 dw3_r16(UINT32 addr)
+{
+ if(addr>=0xDA5610 && addr<=0xDA5613)
+ return *((UINT16 *) (dw3_R+(addr-0xDA5610)));
+ return 0;
+}
+
+UINT32 dw3_r32(UINT32 addr)
+{
+ return 0;
+}
+
+void dw3_w8(UINT32 addr,UINT8 val)
+{
+ if(addr==0xDA5610)
+ dw3_R[1]=val;
+ if(addr==0xDA5611)
+ dw3_R[0]=val;
+ if(addr==0xDA5612)
+ dw3_R[3]=val;
+ if(addr==0xDA5613)
+ dw3_R[2]=val;
+}
+
+void dw3_w16(UINT32 addr,UINT16 val)
+{
+ if(addr>=0xDA5610 && addr<=0xDA5613)
+ {
+ UINT16 *s=((UINT16 *) (dw3_R+(addr-0xDA5610)));
+ *s=val;
+ if(addr==0xDA5610)
+ {
+ if(val==1)
+ {
+ UINT16 v1=dw3_Rw[1];
+ UINT16 v2=0;
+ DW3BITSWAP(v1,v2,0,0);
+ DW3BITSWAP(v1,v2,1,1);
+ DW3BITSWAP(v1,v2,7,2);
+ DW3BITSWAP(v1,v2,6,3);
+ DW3BITSWAP(v1,v2,5,4);
+ DW3BITSWAP(v1,v2,4,5);
+ DW3BITSWAP(v1,v2,3,6);
+ DW3BITSWAP(v1,v2,2,7);
+
+ dw3_Rw[1]=v2;
+ }
+ }
+ }
+
+}
+
+
+void dw3_w32(UINT32 addr,UINT32 val)
+{
+
+}
+#endif
+
+
+
diff --git a/src/mame/machine/pgmy2ks.c b/src/mame/machine/pgmy2ks.c
new file mode 100644
index 00000000000..8e9c9b3126b
--- /dev/null
+++ b/src/mame/machine/pgmy2ks.c
@@ -0,0 +1,2122 @@
+// Photoy2k sprite offset "decryption"
+//
+// ASIC28 gets a sprite number and an encrypted sprite offset and returns
+// a decrypted sprite offset. Only bits 1, 3, 8 and 13 (0x210a) change.
+//
+// The encrypted sprite offset comes from the rom. There are 10-bytes
+// structures at address:
+// 223eb4 + nb*10 for sprites 0..1f3f
+// 23773e + (nb_1f40)*10 for sprites 1f40..3bff
+//
+// struct is:
+// +0 u32 encrypted sprite offset
+// +4 u8 width
+// +5 u8 height
+// +6 u32 always 0
+//
+// Following table gives the decrypted sprite offset given the sprite number.
+// The actual decryption algorithm is unknown.
+
+#include "driver.h"
+
+const UINT32 pgmy2ks[0x3c00] = {
+ 0x000000, 0x00007c, 0x0000f8, 0x000174, 0x0001f0, 0x00026c, 0x0002e8, 0x000364,
+ 0x0003e0, 0x00045c, 0x0004d8, 0x000554, 0x0005d0, 0x00064c, 0x0006c8, 0x000744,
+ 0x0007c0, 0x00083c, 0x0008b8, 0x000934, 0x0009b0, 0x000a2c, 0x000aa8, 0x000b24,
+ 0x000ba0, 0x000c1c, 0x000c98, 0x000d14, 0x000d90, 0x000e0c, 0x000e88, 0x000f04,
+ 0x000f80, 0x000ffc, 0x001078, 0x0010f4, 0x001170, 0x0011ec, 0x001268, 0x0012e4,
+ 0x001360, 0x0013dc, 0x001458, 0x0014d4, 0x001550, 0x0015cc, 0x001648, 0x0016c4,
+ 0x001740, 0x0017bc, 0x001838, 0x0018b4, 0x001930, 0x0019ac, 0x001a28, 0x001aa4,
+ 0x001b20, 0x001b9c, 0x001c18, 0x001c94, 0x001d10, 0x001d8c, 0x001e08, 0x001e84,
+ 0x001f00, 0x001f7c, 0x001ff8, 0x002074, 0x0020f0, 0x00216c, 0x0021e8, 0x002264,
+ 0x0022e0, 0x00235c, 0x0023d8, 0x002454, 0x0024d0, 0x00254c, 0x0025c8, 0x002644,
+ 0x0026c0, 0x00273c, 0x0027b8, 0x002834, 0x0028b0, 0x00292c, 0x0029a8, 0x002a24,
+ 0x002aa0, 0x002b1c, 0x002b98, 0x002c14, 0x002c90, 0x002d0c, 0x002d88, 0x002e04,
+ 0x002e80, 0x002efc, 0x002f78, 0x002ff4, 0x003070, 0x0030ec, 0x003168, 0x0031e4,
+ 0x003260, 0x0032dc, 0x003358, 0x0033d4, 0x003450, 0x0034cc, 0x003548, 0x0035c4,
+ 0x003640, 0x0036bc, 0x003738, 0x0037b4, 0x003830, 0x0038ac, 0x003928, 0x0039a4,
+ 0x003a20, 0x003a9c, 0x003b18, 0x003b94, 0x003c10, 0x003c8c, 0x003d08, 0x003d84,
+ 0x003e00, 0x003e7c, 0x003ef8, 0x003f74, 0x003ff0, 0x00406c, 0x0040e8, 0x004164,
+ 0x0041e0, 0x00425c, 0x0042d8, 0x004354, 0x0043d0, 0x00444c, 0x0044c8, 0x004544,
+ 0x0045c0, 0x00463c, 0x0046b8, 0x004734, 0x0047b0, 0x00482c, 0x0048a8, 0x004924,
+ 0x0049a0, 0x004a1c, 0x004a98, 0x004b14, 0x004b90, 0x004c0c, 0x004c88, 0x004d04,
+ 0x004d80, 0x004dfc, 0x004e78, 0x004ef4, 0x004f70, 0x004fec, 0x005068, 0x0050e4,
+ 0x005160, 0x0051dc, 0x005258, 0x0052d4, 0x005350, 0x0053cc, 0x005448, 0x0054c4,
+ 0x005540, 0x0055bc, 0x005638, 0x0056b4, 0x005730, 0x0057ac, 0x005828, 0x0058a4,
+ 0x005920, 0x00599c, 0x005a18, 0x005a94, 0x005b10, 0x005b8c, 0x005c08, 0x005c84,
+ 0x005d00, 0x005d7c, 0x005df8, 0x005e74, 0x005ef0, 0x005f6c, 0x005fe8, 0x006064,
+ 0x0060e0, 0x00615c, 0x0061d8, 0x006254, 0x0062d0, 0x00634c, 0x0063c8, 0x006444,
+ 0x0064c0, 0x00653c, 0x0065b8, 0x006634, 0x0066b0, 0x00672c, 0x0067a8, 0x006824,
+ 0x0068a0, 0x00691c, 0x006998, 0x006a14, 0x006a90, 0x006b0c, 0x006b88, 0x006c04,
+ 0x006c80, 0x006cfc, 0x006d78, 0x006df4, 0x006e70, 0x006eec, 0x006f68, 0x006fe4,
+ 0x007060, 0x0070dc, 0x007158, 0x0071d4, 0x007250, 0x0072cc, 0x007348, 0x0073c4,
+ 0x007440, 0x0074bc, 0x007538, 0x0075b4, 0x007630, 0x0076ac, 0x007728, 0x0077a4,
+ 0x007820, 0x00789c, 0x007918, 0x007994, 0x007a10, 0x007a8c, 0x007b08, 0x007b84,
+ 0x007c00, 0x007c7c, 0x007cf8, 0x007d74, 0x007df0, 0x007e6c, 0x007ee8, 0x007f64,
+ 0x007fe0, 0x00805c, 0x0080d8, 0x008154, 0x0081d0, 0x00824c, 0x0082c8, 0x008344,
+ 0x0083c0, 0x00843c, 0x0084b8, 0x008534, 0x0085b0, 0x00862c, 0x0086a8, 0x008724,
+ 0x0087a0, 0x00881c, 0x008898, 0x008914, 0x008990, 0x008a0c, 0x008a88, 0x008b04,
+ 0x008b80, 0x008bfc, 0x008c78, 0x008cf4, 0x008d70, 0x008dec, 0x008e68, 0x008ee4,
+ 0x008f60, 0x008fdc, 0x009058, 0x0090d4, 0x009150, 0x0091cc, 0x009248, 0x0092c4,
+ 0x009340, 0x0093bc, 0x009438, 0x0094b4, 0x009530, 0x0095ac, 0x009628, 0x0096a4,
+ 0x009720, 0x00979c, 0x009818, 0x009894, 0x009910, 0x00998c, 0x009a08, 0x009a84,
+ 0x009b00, 0x009b7c, 0x009bf8, 0x009c74, 0x009cf0, 0x009d6c, 0x009de8, 0x009e64,
+ 0x009ee0, 0x009f5c, 0x009fd8, 0x00a054, 0x00a0d0, 0x00a14c, 0x00a1c8, 0x00a244,
+ 0x00a2c0, 0x00a33c, 0x00a3b8, 0x00a434, 0x00a4b0, 0x00a52c, 0x00a5a8, 0x00a624,
+ 0x00a6a0, 0x00a71c, 0x00a798, 0x00a814, 0x00a890, 0x00a90c, 0x00a988, 0x00aa04,
+ 0x00aa80, 0x00aafc, 0x00ab78, 0x00abf4, 0x00ac70, 0x00acec, 0x00ad68, 0x00ade4,
+ 0x00ae60, 0x00aedc, 0x00af58, 0x00afd4, 0x00b050, 0x00b0cc, 0x00b148, 0x00b1c4,
+ 0x00b240, 0x00b2bc, 0x00b338, 0x00b3b4, 0x00b430, 0x00b4ac, 0x00b528, 0x00b5a4,
+ 0x00b620, 0x00b69c, 0x00b718, 0x00b794, 0x00b810, 0x00b88c, 0x00b908, 0x00b984,
+ 0x00ba00, 0x00ba7c, 0x00baf8, 0x00bb74, 0x00bbf0, 0x00bc6c, 0x00bce8, 0x00bd64,
+ 0x00bde0, 0x00be5c, 0x00bed8, 0x00bf54, 0x00bfd0, 0x00c04c, 0x00c0c8, 0x00c144,
+ 0x00c1c0, 0x00c23c, 0x00c2b8, 0x00c334, 0x00c3b0, 0x00c42c, 0x00c4a8, 0x00c524,
+ 0x00c5a0, 0x00c61c, 0x00c698, 0x00c714, 0x00c790, 0x00c80c, 0x00c888, 0x00c904,
+ 0x00c980, 0x00c9fc, 0x00ca78, 0x00caf4, 0x00cb70, 0x00cbec, 0x00cc68, 0x00cce4,
+ 0x00cd60, 0x00cddc, 0x00ce58, 0x00ced4, 0x00cf50, 0x00cfcc, 0x00d048, 0x00d0c4,
+ 0x00d140, 0x00d1bc, 0x00d238, 0x00d2b4, 0x00d330, 0x00d3ac, 0x00d428, 0x00d4a4,
+ 0x00d520, 0x00d59c, 0x00d618, 0x00d694, 0x00d710, 0x00d78c, 0x00d808, 0x00d884,
+ 0x00d900, 0x00d97c, 0x00d9f8, 0x00da74, 0x00daf0, 0x00db6c, 0x00dbe8, 0x00dc64,
+ 0x00dce0, 0x00dd5c, 0x00ddd8, 0x00de54, 0x00ded0, 0x00df4c, 0x00dfc8, 0x00e044,
+ 0x00e0c0, 0x00e13c, 0x00e1b8, 0x00e234, 0x00e2b0, 0x00e32c, 0x00e3a8, 0x00e424,
+ 0x00e4a0, 0x00e51c, 0x00e598, 0x00e614, 0x00e690, 0x00e70c, 0x00e788, 0x00e804,
+ 0x00e880, 0x00e8fc, 0x00e978, 0x00e9f4, 0x00ea70, 0x00eaec, 0x00eb68, 0x00ebe4,
+ 0x00ec60, 0x00ecdc, 0x00ed58, 0x00edd4, 0x00ee50, 0x00eecc, 0x00ef48, 0x00efc4,
+ 0x00f040, 0x00f0bc, 0x00f138, 0x00f1b4, 0x00f230, 0x00f2ac, 0x00f328, 0x00f3a4,
+ 0x00f420, 0x00f49c, 0x00f518, 0x00f594, 0x00f610, 0x00f68c, 0x00f708, 0x00f784,
+
+ 0x00f800, 0x00f87c, 0x00f8f8, 0x00f974, 0x00f9f0, 0x00fa6c, 0x00fae8, 0x00fb64,
+ 0x00fbe0, 0x00fc5c, 0x00fcd8, 0x00fd54, 0x00fdd0, 0x00fe4c, 0x00fec8, 0x00ff44,
+ 0x00ffc0, 0x01003c, 0x0100b8, 0x010134, 0x0101b0, 0x01022c, 0x0102a8, 0x010324,
+ 0x0103a0, 0x01041c, 0x010498, 0x010514, 0x010590, 0x01060c, 0x010688, 0x010704,
+ 0x010780, 0x0107fc, 0x010878, 0x0108f4, 0x010970, 0x0109ec, 0x010a68, 0x010ae4,
+ 0x010b60, 0x010bdc, 0x010c58, 0x010cd4, 0x010d50, 0x010dcc, 0x010e48, 0x010ec4,
+ 0x010f40, 0x010fbc, 0x011038, 0x0110b4, 0x011130, 0x0111ac, 0x011228, 0x0112a4,
+ 0x011320, 0x01139c, 0x011418, 0x011494, 0x011510, 0x01158c, 0x011608, 0x011684,
+
+ 0x011700, 0x0117a4, 0x011848, 0x0118ec, 0x011990, 0x011a34, 0x011ad8, 0x011b7c,
+ 0x011c20, 0x011cc4, 0x011d68, 0x011e0c, 0x011eb0, 0x011f54, 0x011ff8, 0x01209c,
+ 0x012140, 0x0121e4, 0x012288, 0x01232c, 0x0123d0, 0x012474, 0x012518, 0x0125bc,
+ 0x012660, 0x012704, 0x0127a8, 0x01284c, 0x0128f0, 0x012994, 0x012a38, 0x012adc,
+ 0x012b80, 0x012c24, 0x012cc8, 0x012d6c, 0x012e10, 0x012eb4, 0x012f58, 0x012ffc,
+ 0x0130a0, 0x013144, 0x0131e8, 0x01328c, 0x013330, 0x0133d4, 0x013478, 0x01351c,
+ 0x0135c0, 0x013664, 0x013708, 0x0137ac, 0x013850, 0x0138f4, 0x013998, 0x013a3c,
+ 0x013ae0, 0x013b84, 0x013c28, 0x013ccc, 0x013d70, 0x013e14, 0x013eb8, 0x013f5c,
+
+ 0x014000, 0x01407c, 0x0140f8, 0x014174, 0x0141f0, 0x01426c, 0x0142e8, 0x014364,
+ 0x0143e0, 0x01445c, 0x0144d8, 0x014554, 0x0145d0, 0x01464c, 0x0146c8, 0x014744,
+ 0x0147c0, 0x01483c, 0x0148b8, 0x014934, 0x0149b0, 0x014a2c, 0x014aa8, 0x014b24,
+ 0x014ba0, 0x014c1c, 0x014c98, 0x014d14, 0x014d90, 0x014e0c, 0x014e88, 0x014f04,
+ 0x014f80, 0x014ffc, 0x015078, 0x0150f4, 0x015170, 0x0151ec, 0x015268, 0x0152e4,
+ 0x015360, 0x0153dc, 0x015458, 0x0154d4, 0x015550, 0x0155cc, 0x015648, 0x0156c4,
+ 0x015740, 0x0157bc, 0x015838, 0x0158b4, 0x015930, 0x0159ac, 0x015a28, 0x015aa4,
+ 0x015b20, 0x015b9c, 0x015c18, 0x015c94, 0x015d10, 0x015d8c, 0x015e08, 0x015e84,
+
+ 0x015f00, 0x015fa4, 0x016048, 0x0160ec, 0x016190, 0x016234, 0x0162d8, 0x01637c,
+ 0x016420, 0x0164c4, 0x016568, 0x01660c, 0x0166b0, 0x016754, 0x0167f8, 0x01689c,
+ 0x016940, 0x0169e4, 0x016a88, 0x016b2c, 0x016bd0, 0x016c74, 0x016d18, 0x016dbc,
+ 0x016e60, 0x016f04, 0x016fa8, 0x01704c, 0x0170f0, 0x017194, 0x017238, 0x0172dc,
+ 0x017380, 0x017424, 0x0174c8, 0x01756c, 0x017610, 0x0176b4, 0x017758, 0x0177fc,
+ 0x0178a0, 0x017944, 0x0179e8, 0x017a8c, 0x017b30, 0x017bd4, 0x017c78, 0x017d1c,
+ 0x017dc0, 0x017e64, 0x017f08, 0x017fac, 0x018050, 0x0180f4, 0x018198, 0x01823c,
+ 0x0182e0, 0x018384, 0x018428, 0x0184cc, 0x018570, 0x018614, 0x0186b8, 0x01875c,
+
+ 0x018800, 0x01887c, 0x0188f8, 0x018974, 0x0189f0, 0x018a6c, 0x018ae8, 0x018b64,
+ 0x018be0, 0x018c5c, 0x018cd8, 0x018d54, 0x018dd0, 0x018e4c, 0x018ec8, 0x018f44,
+ 0x018fc0, 0x01903c, 0x0190b8, 0x019134, 0x0191b0, 0x01922c, 0x0192a8, 0x019324,
+ 0x0193a0, 0x01941c, 0x019498, 0x019514, 0x019590, 0x01960c, 0x019688, 0x019704,
+ 0x019780, 0x0197fc, 0x019878, 0x0198f4, 0x019970, 0x0199ec, 0x019a68, 0x019ae4,
+ 0x019b60, 0x019bdc, 0x019c58, 0x019cd4, 0x019d50, 0x019dcc, 0x019e48, 0x019ec4,
+ 0x019f40, 0x019fbc, 0x01a038, 0x01a0b4, 0x01a130, 0x01a1ac, 0x01a228, 0x01a2a4,
+ 0x01a320, 0x01a39c, 0x01a418, 0x01a494, 0x01a510, 0x01a58c, 0x01a608, 0x01a684,
+
+ 0x01a700, 0x01a7a4, 0x01a848, 0x01a8ec, 0x01a990, 0x01aa34, 0x01aad8, 0x01ab7c,
+ 0x01ac20, 0x01acc4, 0x01ad68, 0x01ae0c, 0x01aeb0, 0x01af54, 0x01aff8, 0x01b09c,
+ 0x01b140, 0x01b1e4, 0x01b288, 0x01b32c, 0x01b3d0, 0x01b474, 0x01b518, 0x01b5bc,
+ 0x01b660, 0x01b704, 0x01b7a8, 0x01b84c, 0x01b8f0, 0x01b994, 0x01ba38, 0x01badc,
+ 0x01bb80, 0x01bc24, 0x01bcc8, 0x01bd6c, 0x01be10, 0x01beb4, 0x01bf58, 0x01bffc,
+ 0x01c0a0, 0x01c144, 0x01c1e8, 0x01c28c, 0x01c330, 0x01c3d4, 0x01c478, 0x01c51c,
+ 0x01c5c0, 0x01c664, 0x01c708, 0x01c7ac, 0x01c850, 0x01c8f4, 0x01c998, 0x01ca3c,
+ 0x01cae0, 0x01cb84, 0x01cc28, 0x01cccc, 0x01cd70, 0x01ce14, 0x01ceb8, 0x01cf5c,
+
+ 0x01d000, 0x01d07c, 0x01d0f8, 0x01d174, 0x01d1f0, 0x01d26c, 0x01d2e8, 0x01d364,
+ 0x01d3e0, 0x01d45c, 0x01d4d8, 0x01d554, 0x01d5d0, 0x01d64c, 0x01d6c8, 0x01d744,
+ 0x01d7c0, 0x01d83c, 0x01d8b8, 0x01d934, 0x01d9b0, 0x01da2c, 0x01daa8, 0x01db24,
+ 0x01dba0, 0x01dc1c, 0x01dc98, 0x01dd14, 0x01dd90, 0x01de0c, 0x01de88, 0x01df04,
+ 0x01df80, 0x01dffc, 0x01e078, 0x01e0f4, 0x01e170, 0x01e1ec, 0x01e268, 0x01e2e4,
+ 0x01e360, 0x01e3dc, 0x01e458, 0x01e4d4, 0x01e550, 0x01e5cc, 0x01e648, 0x01e6c4,
+ 0x01e740, 0x01e7bc, 0x01e838, 0x01e8b4, 0x01e930, 0x01e9ac, 0x01ea28, 0x01eaa4,
+ 0x01eb20, 0x01eb9c, 0x01ec18, 0x01ec94, 0x01ed10, 0x01ed8c, 0x01ee08, 0x01ee84,
+
+ 0x01ef00, 0x01efa4, 0x01f048, 0x01f0ec, 0x01f190, 0x01f234, 0x01f2d8, 0x01f37c,
+ 0x01f420, 0x01f4c4, 0x01f568, 0x01f60c, 0x01f6b0, 0x01f754, 0x01f7f8, 0x01f89c,
+ 0x01f940, 0x01f9e4, 0x01fa88, 0x01fb2c, 0x01fbd0, 0x01fc74, 0x01fd18, 0x01fdbc,
+ 0x01fe60, 0x01ff04, 0x01ffa8, 0x02004c, 0x0200f0, 0x020194, 0x020238, 0x0202dc,
+ 0x020380, 0x020424, 0x0204c8, 0x02056c, 0x020610, 0x0206b4, 0x020758, 0x0207fc,
+ 0x0208a0, 0x020944, 0x0209e8, 0x020a8c, 0x020b30, 0x020bd4, 0x020c78, 0x020d1c,
+ 0x020dc0, 0x020e64, 0x020f08, 0x020fac, 0x021050, 0x0210f4, 0x021198, 0x02123c,
+ 0x0212e0, 0x021384, 0x021428, 0x0214cc, 0x021570, 0x021614, 0x0216b8, 0x02175c,
+
+ 0x021800, 0x02187c, 0x0218f8, 0x021974, 0x0219f0, 0x021a6c, 0x021ae8, 0x021b64,
+ 0x021be0, 0x021c5c, 0x021cd8, 0x021d54, 0x021dd0, 0x021e4c, 0x021ec8, 0x021f44,
+ 0x021fc0, 0x02203c, 0x0220b8, 0x022134, 0x0221b0, 0x02222c, 0x0222a8, 0x022324,
+ 0x0223a0, 0x02241c, 0x022498, 0x022514, 0x022590, 0x02260c, 0x022688, 0x022704,
+ 0x022780, 0x0227fc, 0x022878, 0x0228f4, 0x022970, 0x0229ec, 0x022a68, 0x022ae4,
+ 0x022b60, 0x022bdc, 0x022c58, 0x022cd4, 0x022d50, 0x022dcc, 0x022e48, 0x022ec4,
+ 0x022f40, 0x022fbc, 0x023038, 0x0230b4, 0x023130, 0x0231ac, 0x023228, 0x0232a4,
+ 0x023320, 0x02339c, 0x023418, 0x023494, 0x023510, 0x02358c, 0x023608, 0x023684,
+ 0x023700, 0x02377c, 0x0237f8, 0x023874, 0x0238f0, 0x02396c, 0x0239e8, 0x023a64,
+ 0x023ae0, 0x023b5c, 0x023bd8, 0x023c54, 0x023cd0, 0x023d4c, 0x023dc8, 0x023e44,
+ 0x023ec0, 0x023f3c, 0x023fb8, 0x024034, 0x0240b0, 0x02412c, 0x0241a8, 0x024224,
+ 0x0242a0, 0x02431c, 0x024398, 0x024414, 0x024490, 0x02450c, 0x024588, 0x024604,
+ 0x024680, 0x0246fc, 0x024778, 0x0247f4, 0x024870, 0x0248ec, 0x024968, 0x0249e4,
+ 0x024a60, 0x024adc, 0x024b58, 0x024bd4, 0x024c50, 0x024ccc, 0x024d48, 0x024dc4,
+ 0x024e40, 0x024ebc, 0x024f38, 0x024fb4, 0x025030, 0x0250ac, 0x025128, 0x0251a4,
+ 0x025220, 0x02529c, 0x025318, 0x025394, 0x025410, 0x02548c, 0x025508, 0x025584,
+ 0x025600, 0x02567c, 0x0256f8, 0x025774, 0x0257f0, 0x02586c, 0x0258e8, 0x025964,
+ 0x0259e0, 0x025a5c, 0x025ad8, 0x025b54, 0x025bd0, 0x025c4c, 0x025cc8, 0x025d44,
+ 0x025dc0, 0x025e3c, 0x025eb8, 0x025f34, 0x025fb0, 0x02602c, 0x0260a8, 0x026124,
+ 0x0261a0, 0x02621c, 0x026298, 0x026314, 0x026390, 0x02640c, 0x026488, 0x026504,
+ 0x026580, 0x0265fc, 0x026678, 0x0266f4, 0x026770, 0x0267ec, 0x026868, 0x0268e4,
+ 0x026960, 0x0269dc, 0x026a58, 0x026ad4, 0x026b50, 0x026bcc, 0x026c48, 0x026cc4,
+ 0x026d40, 0x026dbc, 0x026e38, 0x026eb4, 0x026f30, 0x026fac, 0x027028, 0x0270a4,
+ 0x027120, 0x02719c, 0x027218, 0x027294, 0x027310, 0x02738c, 0x027408, 0x027484,
+ 0x027500, 0x02757c, 0x0275f8, 0x027674, 0x0276f0, 0x02776c, 0x0277e8, 0x027864,
+ 0x0278e0, 0x02795c, 0x0279d8, 0x027a54, 0x027ad0, 0x027b4c, 0x027bc8, 0x027c44,
+ 0x027cc0, 0x027d3c, 0x027db8, 0x027e34, 0x027eb0, 0x027f2c, 0x027fa8, 0x028024,
+ 0x0280a0, 0x02811c, 0x028198, 0x028214, 0x028290, 0x02830c, 0x028388, 0x028404,
+ 0x028480, 0x0284fc, 0x028578, 0x0285f4, 0x028670, 0x0286ec, 0x028768, 0x0287e4,
+ 0x028860, 0x0288dc, 0x028958, 0x0289d4, 0x028a50, 0x028acc, 0x028b48, 0x028bc4,
+ 0x028c40, 0x028cbc, 0x028d38, 0x028db4, 0x028e30, 0x028eac, 0x028f28, 0x028fa4,
+ 0x029020, 0x02909c, 0x029118, 0x029194, 0x029210, 0x02928c, 0x029308, 0x029384,
+
+ 0x029400, 0x02947c, 0x0294f8, 0x029574, 0x0295f0, 0x02966c, 0x0296e8, 0x029764,
+ 0x0297e0, 0x02985c, 0x0298d8, 0x029954, 0x0299d0, 0x029a4c, 0x029ac8, 0x029b44,
+ 0x029bc0, 0x029c3c, 0x029cb8, 0x029d34, 0x029db0, 0x029e2c, 0x029ea8, 0x029f24,
+ 0x029fa0, 0x02a01c, 0x02a098, 0x02a114, 0x02a190, 0x02a20c, 0x02a288, 0x02a304,
+
+ 0x02a380, 0x02a424, 0x02a4c8, 0x02a56c, 0x02a610, 0x02a6b4, 0x02a758, 0x02a7fc,
+ 0x02a8a0, 0x02a944, 0x02a9e8, 0x02aa8c, 0x02ab30, 0x02abd4, 0x02ac78, 0x02ad1c,
+ 0x02adc0, 0x02ae64, 0x02af08, 0x02afac, 0x02b050, 0x02b0f4, 0x02b198, 0x02b23c,
+ 0x02b2e0, 0x02b384, 0x02b428, 0x02b4cc, 0x02b570, 0x02b614, 0x02b6b8, 0x02b75c,
+
+ 0x02b800, 0x02b87c, 0x02b8f8, 0x02b974, 0x02b9f0, 0x02ba6c, 0x02bae8, 0x02bb64,
+ 0x02bbe0, 0x02bc5c, 0x02bcd8, 0x02bd54, 0x02bdd0, 0x02be4c, 0x02bec8, 0x02bf44,
+ 0x02bfc0, 0x02c03c, 0x02c0b8, 0x02c134, 0x02c1b0, 0x02c22c, 0x02c2a8, 0x02c324,
+ 0x02c3a0, 0x02c41c, 0x02c498, 0x02c514, 0x02c590, 0x02c60c, 0x02c688, 0x02c704,
+
+ 0x02c780, 0x02c824, 0x02c8c8, 0x02c96c, 0x02ca10, 0x02cab4, 0x02cb58, 0x02cbfc,
+ 0x02cca0, 0x02cd44, 0x02cde8, 0x02ce8c, 0x02cf30, 0x02cfd4, 0x02d078, 0x02d11c,
+ 0x02d1c0, 0x02d264, 0x02d308, 0x02d3ac, 0x02d450, 0x02d4f4, 0x02d598, 0x02d63c,
+ 0x02d6e0, 0x02d784, 0x02d828, 0x02d8cc, 0x02d970, 0x02da14, 0x02dab8, 0x02db5c,
+
+ 0x02dc00, 0x02dc7c, 0x02dcf8, 0x02dd74, 0x02ddf0, 0x02de6c, 0x02dee8, 0x02df64,
+ 0x02dfe0, 0x02e05c, 0x02e0d8, 0x02e154, 0x02e1d0, 0x02e24c, 0x02e2c8, 0x02e344,
+ 0x02e3c0, 0x02e43c, 0x02e4b8, 0x02e534, 0x02e5b0, 0x02e62c, 0x02e6a8, 0x02e724,
+ 0x02e7a0, 0x02e81c, 0x02e898, 0x02e914, 0x02e990, 0x02ea0c, 0x02ea88, 0x02eb04,
+
+ 0x02eb80, 0x02ec24, 0x02ecc8, 0x02ed6c, 0x02ee10, 0x02eeb4, 0x02ef58, 0x02effc,
+ 0x02f0a0, 0x02f144, 0x02f1e8, 0x02f28c, 0x02f330, 0x02f3d4, 0x02f478, 0x02f51c,
+ 0x02f5c0, 0x02f664, 0x02f708, 0x02f7ac, 0x02f850, 0x02f8f4, 0x02f998, 0x02fa3c,
+ 0x02fae0, 0x02fb84, 0x02fc28, 0x02fccc, 0x02fd70, 0x02fe14, 0x02feb8, 0x02ff5c,
+
+ 0x030000, 0x03007c, 0x0300f8, 0x030174, 0x0301f0, 0x03026c, 0x0302e8, 0x030364,
+ 0x0303e0, 0x03045c, 0x0304d8, 0x030554, 0x0305d0, 0x03064c, 0x0306c8, 0x030744,
+ 0x0307c0, 0x03083c, 0x0308b8, 0x030934, 0x0309b0, 0x030a2c, 0x030aa8, 0x030b24,
+ 0x030ba0, 0x030c1c, 0x030c98, 0x030d14, 0x030d90, 0x030e0c, 0x030e88, 0x030f04,
+
+ 0x030f80, 0x031024, 0x0310c8, 0x03116c, 0x031210, 0x0312b4, 0x031358, 0x0313fc,
+ 0x0314a0, 0x031544, 0x0315e8, 0x03168c, 0x031730, 0x0317d4, 0x031878, 0x03191c,
+ 0x0319c0, 0x031a64, 0x031b08, 0x031bac, 0x031c50, 0x031cf4, 0x031d98, 0x031e3c,
+ 0x031ee0, 0x031f84, 0x032028, 0x0320cc, 0x032170, 0x032214, 0x0322b8, 0x03235c,
+
+ 0x032400, 0x03247c, 0x0324f8, 0x032574, 0x0325f0, 0x03266c, 0x0326e8, 0x032764,
+ 0x0327e0, 0x03285c, 0x0328d8, 0x032954, 0x0329d0, 0x032a4c, 0x032ac8, 0x032b44,
+ 0x032bc0, 0x032c3c, 0x032cb8, 0x032d34, 0x032db0, 0x032e2c, 0x032ea8, 0x032f24,
+ 0x032fa0, 0x03301c, 0x033098, 0x033114, 0x033190, 0x03320c, 0x033288, 0x033304,
+ 0x033380, 0x0333fc, 0x033478, 0x0334f4, 0x033570, 0x0335ec, 0x033668, 0x0336e4,
+ 0x033760, 0x0337dc, 0x033858, 0x0338d4, 0x033950, 0x0339cc, 0x033a48, 0x033ac4,
+ 0x033b40, 0x033bbc, 0x033c38, 0x033cb4, 0x033d30, 0x033dac, 0x033e28, 0x033ea4,
+ 0x033f20, 0x033f9c, 0x034018, 0x034094, 0x034110, 0x03418c, 0x034208, 0x034284,
+ 0x034300, 0x03437c, 0x0343f8, 0x034474, 0x0344f0, 0x03456c, 0x0345e8, 0x034664,
+ 0x0346e0, 0x03475c, 0x0347d8, 0x034854, 0x0348d0, 0x03494c, 0x0349c8, 0x034a44,
+ 0x034ac0, 0x034b3c, 0x034bb8, 0x034c34, 0x034cb0, 0x034d2c, 0x034da8, 0x034e24,
+ 0x034ea0, 0x034f1c, 0x034f98, 0x035014, 0x035090, 0x03510c, 0x035188, 0x035204,
+ 0x035280, 0x0352fc, 0x035378, 0x0353f4, 0x035470, 0x0354ec, 0x035568, 0x0355e4,
+ 0x035660, 0x0356dc, 0x035758, 0x0357d4, 0x035850, 0x0358cc, 0x035948, 0x0359c4,
+ 0x035a40, 0x035abc, 0x035b38, 0x035bb4, 0x035c30, 0x035cac, 0x035d28, 0x035da4,
+ 0x035e20, 0x035e9c, 0x035f18, 0x035f94, 0x036010, 0x03608c, 0x036108, 0x036184,
+ 0x036200, 0x03627c, 0x0362f8, 0x036374, 0x0363f0, 0x03646c, 0x0364e8, 0x036564,
+ 0x0365e0, 0x03665c, 0x0366d8, 0x036754, 0x0367d0, 0x03684c, 0x0368c8, 0x036944,
+ 0x0369c0, 0x036a3c, 0x036ab8, 0x036b34, 0x036bb0, 0x036c2c, 0x036ca8, 0x036d24,
+ 0x036da0, 0x036e1c, 0x036e98, 0x036f14, 0x036f90, 0x03700c, 0x037088, 0x037104,
+ 0x037180, 0x0371fc, 0x037278, 0x0372f4, 0x037370, 0x0373ec, 0x037468, 0x0374e4,
+ 0x037560, 0x0375dc, 0x037658, 0x0376d4, 0x037750, 0x0377cc, 0x037848, 0x0378c4,
+ 0x037940, 0x0379bc, 0x037a38, 0x037ab4, 0x037b30, 0x037bac, 0x037c28, 0x037ca4,
+ 0x037d20, 0x037d9c, 0x037e18, 0x037e94, 0x037f10, 0x037f8c, 0x038008, 0x038084,
+ 0x038100, 0x03817c, 0x0381f8, 0x038274, 0x0382f0, 0x03836c, 0x0383e8, 0x038464,
+ 0x0384e0, 0x03855c, 0x0385d8, 0x038654, 0x0386d0, 0x03874c, 0x0387c8, 0x038844,
+ 0x0388c0, 0x03893c, 0x0389b8, 0x038a34, 0x038ab0, 0x038b2c, 0x038ba8, 0x038c24,
+ 0x038ca0, 0x038d1c, 0x038d98, 0x038e14, 0x038e90, 0x038f0c, 0x038f88, 0x039004,
+ 0x039080, 0x0390fc, 0x039178, 0x0391f4, 0x039270, 0x0392ec, 0x039368, 0x0393e4,
+ 0x039460, 0x0394dc, 0x039558, 0x0395d4, 0x039650, 0x0396cc, 0x039748, 0x0397c4,
+ 0x039840, 0x0398bc, 0x039938, 0x0399b4, 0x039a30, 0x039aac, 0x039b28, 0x039ba4,
+ 0x039c20, 0x039c9c, 0x039d18, 0x039d94, 0x039e10, 0x039e8c, 0x039f08, 0x039f84,
+
+ 0x03a000, 0x03a07c, 0x03a0f8, 0x03a174, 0x03a1f0, 0x03a26c, 0x03a2e8, 0x03a364,
+ 0x03a3e0, 0x03a45c, 0x03a4d8, 0x03a554, 0x03a5d0, 0x03a64c, 0x03a6c8, 0x03a744,
+ 0x03a7c0, 0x03a83c, 0x03a8b8, 0x03a934, 0x03a9b0, 0x03aa2c, 0x03aaa8, 0x03ab24,
+ 0x03aba0, 0x03ac1c, 0x03ac98, 0x03ad14, 0x03ad90, 0x03ae0c, 0x03ae88, 0x03af04,
+
+ 0x03af80, 0x03b024, 0x03b0c8, 0x03b16c, 0x03b210, 0x03b2b4, 0x03b358, 0x03b3fc,
+ 0x03b4a0, 0x03b544, 0x03b5e8, 0x03b68c, 0x03b730, 0x03b7d4, 0x03b878, 0x03b91c,
+ 0x03b9c0, 0x03ba64, 0x03bb08, 0x03bbac, 0x03bc50, 0x03bcf4, 0x03bd98, 0x03be3c,
+ 0x03bee0, 0x03bf84, 0x03c028, 0x03c0cc, 0x03c170, 0x03c214, 0x03c2b8, 0x03c35c,
+
+ 0x03c400, 0x03c47c, 0x03c4f8, 0x03c574, 0x03c5f0, 0x03c66c, 0x03c6e8, 0x03c764,
+ 0x03c7e0, 0x03c85c, 0x03c8d8, 0x03c954, 0x03c9d0, 0x03ca4c, 0x03cac8, 0x03cb44,
+ 0x03cbc0, 0x03cc3c, 0x03ccb8, 0x03cd34, 0x03cdb0, 0x03ce2c, 0x03cea8, 0x03cf24,
+ 0x03cfa0, 0x03d01c, 0x03d098, 0x03d114, 0x03d190, 0x03d20c, 0x03d288, 0x03d304,
+
+ 0x03d380, 0x03d424, 0x03d4c8, 0x03d56c, 0x03d610, 0x03d6b4, 0x03d758, 0x03d7fc,
+ 0x03d8a0, 0x03d944, 0x03d9e8, 0x03da8c, 0x03db30, 0x03dbd4, 0x03dc78, 0x03dd1c,
+ 0x03ddc0, 0x03de64, 0x03df08, 0x03dfac, 0x03e050, 0x03e0f4, 0x03e198, 0x03e23c,
+ 0x03e2e0, 0x03e384, 0x03e428, 0x03e4cc, 0x03e570, 0x03e614, 0x03e6b8, 0x03e75c,
+
+ 0x03e800, 0x03e87c, 0x03e8f8, 0x03e974, 0x03e9f0, 0x03ea6c, 0x03eae8, 0x03eb64,
+ 0x03ebe0, 0x03ec5c, 0x03ecd8, 0x03ed54, 0x03edd0, 0x03ee4c, 0x03eec8, 0x03ef44,
+ 0x03efc0, 0x03f03c, 0x03f0b8, 0x03f134, 0x03f1b0, 0x03f22c, 0x03f2a8, 0x03f324,
+ 0x03f3a0, 0x03f41c, 0x03f498, 0x03f514, 0x03f590, 0x03f60c, 0x03f688, 0x03f704,
+
+ 0x03f780, 0x03f824, 0x03f8c8, 0x03f96c, 0x03fa10, 0x03fab4, 0x03fb58, 0x03fbfc,
+ 0x03fca0, 0x03fd44, 0x03fde8, 0x03fe8c, 0x03ff30, 0x03ffd4, 0x040078, 0x04011c,
+ 0x0401c0, 0x040264, 0x040308, 0x0403ac, 0x040450, 0x0404f4, 0x040598, 0x04063c,
+ 0x0406e0, 0x040784, 0x040828, 0x0408cc, 0x040970, 0x040a14, 0x040ab8, 0x040b5c,
+
+ 0x040c00, 0x040c7c, 0x040cf8, 0x040d74, 0x040df0, 0x040e6c, 0x040ee8, 0x040f64,
+ 0x040fe0, 0x04105c, 0x0410d8, 0x041154, 0x0411d0, 0x04124c, 0x0412c8, 0x041344,
+ 0x0413c0, 0x04143c, 0x0414b8, 0x041534, 0x0415b0, 0x04162c, 0x0416a8, 0x041724,
+ 0x0417a0, 0x04181c, 0x041898, 0x041914, 0x041990, 0x041a0c, 0x041a88, 0x041b04,
+
+ 0x041b80, 0x041c24, 0x041cc8, 0x041d6c, 0x041e10, 0x041eb4, 0x041f58, 0x041ffc,
+ 0x0420a0, 0x042144, 0x0421e8, 0x04228c, 0x042330, 0x0423d4, 0x042478, 0x04251c,
+ 0x0425c0, 0x042664, 0x042708, 0x0427ac, 0x042850, 0x0428f4, 0x042998, 0x042a3c,
+ 0x042ae0, 0x042b84, 0x042c28, 0x042ccc, 0x042d70, 0x042e14, 0x042eb8, 0x042f5c,
+
+
+ 0x043000, 0x04307c, 0x0430f8, 0x043174, 0x0431f0, 0x04326c, 0x0432e8, 0x043364,
+ 0x0433e0, 0x043484, 0x043500, 0x0435a4, 0x043620, 0x0436c4, 0x043740, 0x0437e4,
+ 0x043860, 0x0438dc, 0x043958, 0x0439d4, 0x043a50, 0x043acc, 0x043b48, 0x043bc4,
+ 0x043c40, 0x043ce4, 0x043d60, 0x043e04, 0x043e80, 0x043f24, 0x043fa0, 0x044044,
+ 0x0440c0, 0x04413c, 0x0441b8, 0x044234, 0x0442b0, 0x04432c, 0x0443a8, 0x044424,
+ 0x0444a0, 0x044544, 0x0445c0, 0x044664, 0x0446e0, 0x044784, 0x044800, 0x0448a4,
+ 0x044920, 0x04499c, 0x044a18, 0x044a94, 0x044b10, 0x044b8c, 0x044c08, 0x044c84,
+ 0x044d00, 0x044da4, 0x044e20, 0x044ec4, 0x044f40, 0x044fe4, 0x045060, 0x045104,
+ 0x045180, 0x0451fc, 0x045278, 0x0452f4, 0x045370, 0x0453ec, 0x045468, 0x0454e4,
+ 0x045560, 0x045604, 0x045680, 0x045724, 0x0457a0, 0x045844, 0x0458c0, 0x045964,
+ 0x0459e0, 0x045a5c, 0x045ad8, 0x045b54, 0x045bd0, 0x045c4c, 0x045cc8, 0x045d44,
+ 0x045dc0, 0x045e64, 0x045ee0, 0x045f84, 0x046000, 0x0460a4, 0x046120, 0x0461c4,
+ 0x046240, 0x0462bc, 0x046338, 0x0463b4, 0x046430, 0x0464ac, 0x046528, 0x0465a4,
+ 0x046620, 0x0466c4, 0x046740, 0x0467e4, 0x046860, 0x046904, 0x046980, 0x046a24,
+ 0x046aa0, 0x046b1c, 0x046b98, 0x046c14, 0x046c90, 0x046d0c, 0x046d88, 0x046e04,
+ 0x046e80, 0x046f24, 0x046fa0, 0x047044, 0x0470c0, 0x047164, 0x0471e0, 0x047284,
+ 0x047300, 0x04737c, 0x0473f8, 0x047474, 0x0474f0, 0x04756c, 0x0475e8, 0x047664,
+ 0x0476e0, 0x047784, 0x047800, 0x0478a4, 0x047920, 0x0479c4, 0x047a40, 0x047ae4,
+ 0x047b60, 0x047bdc, 0x047c58, 0x047cd4, 0x047d50, 0x047dcc, 0x047e48, 0x047ec4,
+ 0x047f40, 0x047fe4, 0x048060, 0x048104, 0x048180, 0x048224, 0x0482a0, 0x048344,
+ 0x0483c0, 0x04843c, 0x0484b8, 0x048534, 0x0485b0, 0x04862c, 0x0486a8, 0x048724,
+ 0x0487a0, 0x048844, 0x0488c0, 0x048964, 0x0489e0, 0x048a84, 0x048b00, 0x048ba4,
+ 0x048c20, 0x048c9c, 0x048d18, 0x048d94, 0x048e10, 0x048e8c, 0x048f08, 0x048f84,
+ 0x049000, 0x0490a4, 0x049120, 0x0491c4, 0x049240, 0x0492e4, 0x049360, 0x049404,
+ 0x049480, 0x0494fc, 0x049578, 0x0495f4, 0x049670, 0x0496ec, 0x049768, 0x0497e4,
+ 0x049860, 0x049904, 0x049980, 0x049a24, 0x049aa0, 0x049b44, 0x049bc0, 0x049c64,
+ 0x049ce0, 0x049d5c, 0x049dd8, 0x049e54, 0x049ed0, 0x049f4c, 0x049fc8, 0x04a044,
+ 0x04a0c0, 0x04a164, 0x04a1e0, 0x04a284, 0x04a300, 0x04a3a4, 0x04a420, 0x04a4c4,
+ 0x04a540, 0x04a5bc, 0x04a638, 0x04a6b4, 0x04a730, 0x04a7ac, 0x04a828, 0x04a8a4,
+ 0x04a920, 0x04a9c4, 0x04aa40, 0x04aae4, 0x04ab60, 0x04ac04, 0x04ac80, 0x04ad24,
+ 0x04ada0, 0x04ae1c, 0x04ae98, 0x04af14, 0x04af90, 0x04b00c, 0x04b088, 0x04b104,
+ 0x04b180, 0x04b224, 0x04b2a0, 0x04b344, 0x04b3c0, 0x04b464, 0x04b4e0, 0x04b584,
+ 0x04b600, 0x04b67c, 0x04b6f8, 0x04b774, 0x04b7f0, 0x04b86c, 0x04b8e8, 0x04b964,
+ 0x04b9e0, 0x04ba84, 0x04bb00, 0x04bba4, 0x04bc20, 0x04bcc4, 0x04bd40, 0x04bde4,
+ 0x04be60, 0x04bedc, 0x04bf58, 0x04bfd4, 0x04c050, 0x04c0cc, 0x04c148, 0x04c1c4,
+ 0x04c240, 0x04c2e4, 0x04c360, 0x04c404, 0x04c480, 0x04c524, 0x04c5a0, 0x04c644,
+ 0x04c6c0, 0x04c73c, 0x04c7b8, 0x04c834, 0x04c8b0, 0x04c92c, 0x04c9a8, 0x04ca24,
+ 0x04caa0, 0x04cb44, 0x04cbc0, 0x04cc64, 0x04cce0, 0x04cd84, 0x04ce00, 0x04cea4,
+ 0x04cf20, 0x04cf9c, 0x04d018, 0x04d094, 0x04d110, 0x04d18c, 0x04d208, 0x04d284,
+ 0x04d300, 0x04d3a4, 0x04d420, 0x04d4c4, 0x04d540, 0x04d5e4, 0x04d660, 0x04d704,
+ 0x04d780, 0x04d7fc, 0x04d878, 0x04d8f4, 0x04d970, 0x04d9ec, 0x04da68, 0x04dae4,
+ 0x04db60, 0x04dc04, 0x04dc80, 0x04dd24, 0x04dda0, 0x04de44, 0x04dec0, 0x04df64,
+ 0x04dfe0, 0x04e05c, 0x04e0d8, 0x04e154, 0x04e1d0, 0x04e24c, 0x04e2c8, 0x04e344,
+ 0x04e3c0, 0x04e464, 0x04e4e0, 0x04e584, 0x04e600, 0x04e6a4, 0x04e720, 0x04e7c4,
+ 0x04e840, 0x04e8bc, 0x04e938, 0x04e9b4, 0x04ea30, 0x04eaac, 0x04eb28, 0x04eba4,
+ 0x04ec20, 0x04ecc4, 0x04ed40, 0x04ede4, 0x04ee60, 0x04ef04, 0x04ef80, 0x04f024,
+ 0x04f0a0, 0x04f11c, 0x04f198, 0x04f214, 0x04f290, 0x04f30c, 0x04f388, 0x04f404,
+ 0x04f480, 0x04f524, 0x04f5a0, 0x04f644, 0x04f6c0, 0x04f764, 0x04f7e0, 0x04f884,
+ 0x04f900, 0x04f97c, 0x04f9f8, 0x04fa74, 0x04faf0, 0x04fb6c, 0x04fbe8, 0x04fc64,
+ 0x04fce0, 0x04fd84, 0x04fe00, 0x04fea4, 0x04ff20, 0x04ffc4, 0x050040, 0x0500e4,
+ 0x050160, 0x0501dc, 0x050258, 0x0502d4, 0x050350, 0x0503cc, 0x050448, 0x0504c4,
+ 0x050540, 0x0505e4, 0x050660, 0x050704, 0x050780, 0x050824, 0x0508a0, 0x050944,
+ 0x0509c0, 0x050a3c, 0x050ab8, 0x050b34, 0x050bb0, 0x050c2c, 0x050ca8, 0x050d24,
+ 0x050da0, 0x050e44, 0x050ec0, 0x050f64, 0x050fe0, 0x051084, 0x051100, 0x0511a4,
+ 0x051220, 0x05129c, 0x051318, 0x051394, 0x051410, 0x05148c, 0x051508, 0x051584,
+ 0x051600, 0x0516a4, 0x051720, 0x0517c4, 0x051840, 0x0518e4, 0x051960, 0x051a04,
+ 0x051a80, 0x051afc, 0x051b78, 0x051bf4, 0x051c70, 0x051cec, 0x051d68, 0x051de4,
+ 0x051e60, 0x051f04, 0x051f80, 0x052024, 0x0520a0, 0x052144, 0x0521c0, 0x052264,
+ 0x0522e0, 0x05235c, 0x0523d8, 0x052454, 0x0524d0, 0x05254c, 0x0525c8, 0x052644,
+ 0x0526c0, 0x052764, 0x0527e0, 0x052884, 0x052900, 0x0529a4, 0x052a20, 0x052ac4,
+ 0x052b40, 0x052bbc, 0x052c38, 0x052cb4, 0x052d30, 0x052dac, 0x052e28, 0x052ea4,
+ 0x052f20, 0x052fc4, 0x053040, 0x0530e4, 0x053160, 0x053204, 0x053280, 0x053324,
+ 0x0533a0, 0x05341c, 0x053498, 0x053514, 0x053590, 0x05360c, 0x053688, 0x053704,
+ 0x053780, 0x053824, 0x0538a0, 0x053944, 0x0539c0, 0x053a64, 0x053ae0, 0x053b84,
+ 0x053c00, 0x053c7c, 0x053cf8, 0x053d74, 0x053df0, 0x053e6c, 0x053ee8, 0x053f64,
+ 0x053fe0, 0x054084, 0x054100, 0x0541a4, 0x054220, 0x0542c4, 0x054340, 0x0543e4,
+ 0x054460, 0x0544dc, 0x054558, 0x0545d4, 0x054650, 0x0546cc, 0x054748, 0x0547c4,
+ 0x054840, 0x0548e4, 0x054960, 0x054a04, 0x054a80, 0x054b24, 0x054ba0, 0x054c44,
+ 0x054cc0, 0x054d3c, 0x054db8, 0x054e34, 0x054eb0, 0x054f2c, 0x054fa8, 0x055024,
+ 0x0550a0, 0x055144, 0x0551c0, 0x055264, 0x0552e0, 0x055384, 0x055400, 0x0554a4,
+ 0x055520, 0x05559c, 0x055618, 0x055694, 0x055710, 0x05578c, 0x055808, 0x055884,
+ 0x055900, 0x0559a4, 0x055a20, 0x055ac4, 0x055b40, 0x055be4, 0x055c60, 0x055d04,
+ 0x055d80, 0x055dfc, 0x055e78, 0x055ef4, 0x055f70, 0x055fec, 0x056068, 0x0560e4,
+ 0x056160, 0x056204, 0x056280, 0x056324, 0x0563a0, 0x056444, 0x0564c0, 0x056564,
+ 0x0565e0, 0x05665c, 0x0566d8, 0x056754, 0x0567d0, 0x05684c, 0x0568c8, 0x056944,
+ 0x0569c0, 0x056a64, 0x056ae0, 0x056b84, 0x056c00, 0x056ca4, 0x056d20, 0x056dc4,
+ 0x056e40, 0x056ebc, 0x056f38, 0x056fb4, 0x057030, 0x0570ac, 0x057128, 0x0571a4,
+ 0x057220, 0x0572c4, 0x057340, 0x0573e4, 0x057460, 0x057504, 0x057580, 0x057624,
+ 0x0576a0, 0x05771c, 0x057798, 0x057814, 0x057890, 0x05790c, 0x057988, 0x057a04,
+ 0x057a80, 0x057b24, 0x057ba0, 0x057c44, 0x057cc0, 0x057d64, 0x057de0, 0x057e84,
+ 0x057f00, 0x057f7c, 0x057ff8, 0x058074, 0x0580f0, 0x05816c, 0x0581e8, 0x058264,
+ 0x0582e0, 0x058384, 0x058400, 0x0584a4, 0x058520, 0x0585c4, 0x058640, 0x0586e4,
+ 0x058760, 0x0587dc, 0x058858, 0x0588d4, 0x058950, 0x0589cc, 0x058a48, 0x058ac4,
+ 0x058b40, 0x058be4, 0x058c60, 0x058d04, 0x058d80, 0x058e24, 0x058ea0, 0x058f44,
+ 0x058fc0, 0x05903c, 0x0590b8, 0x059134, 0x0591b0, 0x05922c, 0x0592a8, 0x059324,
+ 0x0593a0, 0x059444, 0x0594c0, 0x059564, 0x0595e0, 0x059684, 0x059700, 0x0597a4,
+ 0x059820, 0x05989c, 0x059918, 0x059994, 0x059a10, 0x059a8c, 0x059b08, 0x059b84,
+ 0x059c00, 0x059ca4, 0x059d20, 0x059dc4, 0x059e40, 0x059ee4, 0x059f60, 0x05a004,
+ 0x05a080, 0x05a0fc, 0x05a178, 0x05a1f4, 0x05a270, 0x05a2ec, 0x05a368, 0x05a3e4,
+ 0x05a460, 0x05a504, 0x05a580, 0x05a624, 0x05a6a0, 0x05a744, 0x05a7c0, 0x05a864,
+ 0x05a8e0, 0x05a95c, 0x05a9d8, 0x05aa54, 0x05aad0, 0x05ab4c, 0x05abc8, 0x05ac44,
+ 0x05acc0, 0x05ad64, 0x05ade0, 0x05ae84, 0x05af00, 0x05afa4, 0x05b020, 0x05b0c4,
+ 0x05b140, 0x05b1bc, 0x05b238, 0x05b2b4, 0x05b330, 0x05b3ac, 0x05b428, 0x05b4a4,
+ 0x05b520, 0x05b5c4, 0x05b640, 0x05b6e4, 0x05b760, 0x05b804, 0x05b880, 0x05b924,
+ 0x05b9a0, 0x05ba1c, 0x05ba98, 0x05bb14, 0x05bb90, 0x05bc0c, 0x05bc88, 0x05bd04,
+ 0x05bd80, 0x05be24, 0x05bea0, 0x05bf44, 0x05bfc0, 0x05c064, 0x05c0e0, 0x05c184,
+ 0x05c200, 0x05c27c, 0x05c2f8, 0x05c374, 0x05c3f0, 0x05c46c, 0x05c4e8, 0x05c564,
+ 0x05c5e0, 0x05c684, 0x05c700, 0x05c7a4, 0x05c820, 0x05c8c4, 0x05c940, 0x05c9e4,
+ 0x05ca60, 0x05cadc, 0x05cb58, 0x05cbd4, 0x05cc50, 0x05cccc, 0x05cd48, 0x05cdc4,
+ 0x05ce40, 0x05cee4, 0x05cf60, 0x05d004, 0x05d080, 0x05d124, 0x05d1a0, 0x05d244,
+ 0x05d2c0, 0x05d33c, 0x05d3b8, 0x05d434, 0x05d4b0, 0x05d52c, 0x05d5a8, 0x05d624,
+ 0x05d6a0, 0x05d744, 0x05d7c0, 0x05d864, 0x05d8e0, 0x05d984, 0x05da00, 0x05daa4,
+ 0x05db20, 0x05db9c, 0x05dc18, 0x05dc94, 0x05dd10, 0x05dd8c, 0x05de08, 0x05de84,
+ 0x05df00, 0x05dfa4, 0x05e020, 0x05e0c4, 0x05e140, 0x05e1e4, 0x05e260, 0x05e304,
+ 0x05e380, 0x05e3fc, 0x05e478, 0x05e4f4, 0x05e570, 0x05e5ec, 0x05e668, 0x05e6e4,
+ 0x05e760, 0x05e804, 0x05e880, 0x05e924, 0x05e9a0, 0x05ea44, 0x05eac0, 0x05eb64,
+ 0x05ebe0, 0x05ec5c, 0x05ecd8, 0x05ed54, 0x05edd0, 0x05ee4c, 0x05eec8, 0x05ef44,
+ 0x05efc0, 0x05f064, 0x05f0e0, 0x05f184, 0x05f200, 0x05f2a4, 0x05f320, 0x05f3c4,
+ 0x05f440, 0x05f4bc, 0x05f538, 0x05f5b4, 0x05f630, 0x05f6ac, 0x05f728, 0x05f7a4,
+ 0x05f820, 0x05f8c4, 0x05f940, 0x05f9e4, 0x05fa60, 0x05fb04, 0x05fb80, 0x05fc24,
+ 0x05fca0, 0x05fd1c, 0x05fd98, 0x05fe14, 0x05fe90, 0x05ff0c, 0x05ff88, 0x060004,
+ 0x060080, 0x060124, 0x0601a0, 0x060244, 0x0602c0, 0x060364, 0x0603e0, 0x060484,
+ 0x060500, 0x06057c, 0x0605f8, 0x060674, 0x0606f0, 0x06076c, 0x0607e8, 0x060864,
+ 0x0608e0, 0x060984, 0x060a00, 0x060aa4, 0x060b20, 0x060bc4, 0x060c40, 0x060ce4,
+ 0x060d60, 0x060ddc, 0x060e58, 0x060ed4, 0x060f50, 0x060fcc, 0x061048, 0x0610c4,
+ 0x061140, 0x0611e4, 0x061260, 0x061304, 0x061380, 0x061424, 0x0614a0, 0x061544,
+ 0x0615c0, 0x06163c, 0x0616b8, 0x061734, 0x0617b0, 0x06182c, 0x0618a8, 0x061924,
+ 0x0619a0, 0x061a44, 0x061ac0, 0x061b64, 0x061be0, 0x061c84, 0x061d00, 0x061da4,
+ 0x061e20, 0x061e9c, 0x061f18, 0x061f94, 0x062010, 0x06208c, 0x062108, 0x062184,
+ 0x062200, 0x0622a4, 0x062320, 0x0623c4, 0x062440, 0x0624e4, 0x062560, 0x062604,
+ 0x062680, 0x0626fc, 0x062778, 0x0627f4, 0x062870, 0x0628ec, 0x062968, 0x0629e4,
+ 0x062a60, 0x062b04, 0x062b80, 0x062c24, 0x062ca0, 0x062d44, 0x062dc0, 0x062e64,
+ 0x062ee0, 0x062f5c, 0x062fd8, 0x063054, 0x0630d0, 0x06314c, 0x0631c8, 0x063244,
+ 0x0632c0, 0x063364, 0x0633e0, 0x063484, 0x063500, 0x0635a4, 0x063620, 0x0636c4,
+ 0x063740, 0x0637bc, 0x063838, 0x0638b4, 0x063930, 0x0639ac, 0x063a28, 0x063aa4,
+ 0x063b20, 0x063bc4, 0x063c40, 0x063ce4, 0x063d60, 0x063e04, 0x063e80, 0x063f24,
+ 0x063fa0, 0x06401c, 0x064098, 0x064114, 0x064190, 0x06420c, 0x064288, 0x064304,
+ 0x064380, 0x064424, 0x0644a0, 0x064544, 0x0645c0, 0x064664, 0x0646e0, 0x064784,
+
+
+ 0x064800, 0x06487c, 0x0648f8, 0x064974, 0x0649f0, 0x064a6c, 0x064ae8, 0x064b64,
+ 0x064be0, 0x064c5c, 0x064cd8, 0x064d54, 0x064dd0, 0x064e4c, 0x064ec8, 0x064f44,
+ 0x064fc0, 0x06503c, 0x0650b8, 0x065134, 0x0651b0, 0x06522c, 0x0652a8, 0x065324,
+ 0x0653a0, 0x06541c, 0x065498, 0x065514, 0x065590, 0x06560c, 0x065688, 0x065704,
+ 0x065780, 0x0657fc, 0x065878, 0x0658f4, 0x065970, 0x0659ec, 0x065a68, 0x065ae4,
+ 0x065b60, 0x065bdc, 0x065c58, 0x065cd4, 0x065d50, 0x065dcc, 0x065e48, 0x065ec4,
+ 0x065f40, 0x065fbc, 0x066038, 0x0660b4, 0x066130, 0x0661ac, 0x066228, 0x0662a4,
+ 0x066320, 0x06639c, 0x066418, 0x066494, 0x066510, 0x06658c, 0x066608, 0x066684,
+ 0x066700, 0x06677c, 0x0667f8, 0x066874, 0x0668f0, 0x06696c, 0x0669e8, 0x066a64,
+ 0x066ae0, 0x066b5c, 0x066bd8, 0x066c54, 0x066cd0, 0x066d4c, 0x066dc8, 0x066e44,
+ 0x066ec0, 0x066f3c, 0x066fb8, 0x067034, 0x0670b0, 0x06712c, 0x0671a8, 0x067224,
+ 0x0672a0, 0x06731c, 0x067398, 0x067414, 0x067490, 0x06750c, 0x067588, 0x067604,
+ 0x067680, 0x0676fc, 0x067778, 0x0677f4, 0x067870, 0x0678ec, 0x067968, 0x0679e4,
+ 0x067a60, 0x067adc, 0x067b58, 0x067bd4, 0x067c50, 0x067ccc, 0x067d48, 0x067dc4,
+ 0x067e40, 0x067ebc, 0x067f38, 0x067fb4, 0x068030, 0x0680ac, 0x068128, 0x0681a4,
+ 0x068220, 0x06829c, 0x068318, 0x068394, 0x068410, 0x06848c, 0x068508, 0x068584,
+ 0x068600, 0x06867c, 0x0686f8, 0x068774, 0x0687f0, 0x06886c, 0x0688e8, 0x068964,
+ 0x0689e0, 0x068a5c, 0x068ad8, 0x068b54, 0x068bd0, 0x068c4c, 0x068cc8, 0x068d44,
+ 0x068dc0, 0x068e3c, 0x068eb8, 0x068f34, 0x068fb0, 0x06902c, 0x0690a8, 0x069124,
+ 0x0691a0, 0x06921c, 0x069298, 0x069314, 0x069390, 0x06940c, 0x069488, 0x069504,
+ 0x069580, 0x0695fc, 0x069678, 0x0696f4, 0x069770, 0x0697ec, 0x069868, 0x0698e4,
+ 0x069960, 0x0699dc, 0x069a58, 0x069ad4, 0x069b50, 0x069bcc, 0x069c48, 0x069cc4,
+ 0x069d40, 0x069dbc, 0x069e38, 0x069eb4, 0x069f30, 0x069fac, 0x06a028, 0x06a0a4,
+ 0x06a120, 0x06a19c, 0x06a218, 0x06a294, 0x06a310, 0x06a38c, 0x06a408, 0x06a484,
+ 0x06a500, 0x06a57c, 0x06a5f8, 0x06a674, 0x06a6f0, 0x06a76c, 0x06a7e8, 0x06a864,
+ 0x06a8e0, 0x06a95c, 0x06a9d8, 0x06aa54, 0x06aad0, 0x06ab4c, 0x06abc8, 0x06ac44,
+ 0x06acc0, 0x06ad3c, 0x06adb8, 0x06ae34, 0x06aeb0, 0x06af2c, 0x06afa8, 0x06b024,
+ 0x06b0a0, 0x06b11c, 0x06b198, 0x06b214, 0x06b290, 0x06b30c, 0x06b388, 0x06b404,
+ 0x06b480, 0x06b4fc, 0x06b578, 0x06b5f4, 0x06b670, 0x06b6ec, 0x06b768, 0x06b7e4,
+ 0x06b860, 0x06b8dc, 0x06b958, 0x06b9d4, 0x06ba50, 0x06bacc, 0x06bb48, 0x06bbc4,
+ 0x06bc40, 0x06bcbc, 0x06bd38, 0x06bdb4, 0x06be30, 0x06beac, 0x06bf28, 0x06bfa4,
+ 0x06c020, 0x06c09c, 0x06c118, 0x06c194, 0x06c210, 0x06c28c, 0x06c308, 0x06c384,
+ 0x06c400, 0x06c47c, 0x06c4f8, 0x06c574, 0x06c5f0, 0x06c66c, 0x06c6e8, 0x06c764,
+ 0x06c7e0, 0x06c85c, 0x06c8d8, 0x06c954, 0x06c9d0, 0x06ca4c, 0x06cac8, 0x06cb44,
+ 0x06cbc0, 0x06cc3c, 0x06ccb8, 0x06cd34, 0x06cdb0, 0x06ce2c, 0x06cea8, 0x06cf24,
+ 0x06cfa0, 0x06d01c, 0x06d098, 0x06d114, 0x06d190, 0x06d20c, 0x06d288, 0x06d304,
+ 0x06d380, 0x06d3fc, 0x06d478, 0x06d4f4, 0x06d570, 0x06d5ec, 0x06d668, 0x06d6e4,
+ 0x06d760, 0x06d7dc, 0x06d858, 0x06d8d4, 0x06d950, 0x06d9cc, 0x06da48, 0x06dac4,
+ 0x06db40, 0x06dbbc, 0x06dc38, 0x06dcb4, 0x06dd30, 0x06ddac, 0x06de28, 0x06dea4,
+ 0x06df20, 0x06df9c, 0x06e018, 0x06e094, 0x06e110, 0x06e18c, 0x06e208, 0x06e284,
+ 0x06e300, 0x06e37c, 0x06e3f8, 0x06e474, 0x06e4f0, 0x06e56c, 0x06e5e8, 0x06e664,
+ 0x06e6e0, 0x06e75c, 0x06e7d8, 0x06e854, 0x06e8d0, 0x06e94c, 0x06e9c8, 0x06ea44,
+ 0x06eac0, 0x06eb3c, 0x06ebb8, 0x06ec34, 0x06ecb0, 0x06ed2c, 0x06eda8, 0x06ee24,
+ 0x06eea0, 0x06ef1c, 0x06ef98, 0x06f014, 0x06f090, 0x06f10c, 0x06f188, 0x06f204,
+ 0x06f280, 0x06f2fc, 0x06f378, 0x06f3f4, 0x06f470, 0x06f4ec, 0x06f568, 0x06f5e4,
+ 0x06f660, 0x06f6dc, 0x06f758, 0x06f7d4, 0x06f850, 0x06f8cc, 0x06f948, 0x06f9c4,
+ 0x06fa40, 0x06fabc, 0x06fb38, 0x06fbb4, 0x06fc30, 0x06fcac, 0x06fd28, 0x06fda4,
+ 0x06fe20, 0x06fe9c, 0x06ff18, 0x06ff94, 0x070010, 0x07008c, 0x070108, 0x070184,
+ 0x070200, 0x07027c, 0x0702f8, 0x070374, 0x0703f0, 0x07046c, 0x0704e8, 0x070564,
+ 0x0705e0, 0x07065c, 0x0706d8, 0x070754, 0x0707d0, 0x07084c, 0x0708c8, 0x070944,
+ 0x0709c0, 0x070a3c, 0x070ab8, 0x070b34, 0x070bb0, 0x070c2c, 0x070ca8, 0x070d24,
+ 0x070da0, 0x070e1c, 0x070e98, 0x070f14, 0x070f90, 0x07100c, 0x071088, 0x071104,
+ 0x071180, 0x0711fc, 0x071278, 0x0712f4, 0x071370, 0x0713ec, 0x071468, 0x0714e4,
+ 0x071560, 0x0715dc, 0x071658, 0x0716d4, 0x071750, 0x0717cc, 0x071848, 0x0718c4,
+ 0x071940, 0x0719bc, 0x071a38, 0x071ab4, 0x071b30, 0x071bac, 0x071c28, 0x071ca4,
+ 0x071d20, 0x071d9c, 0x071e18, 0x071e94, 0x071f10, 0x071f8c, 0x072008, 0x072084,
+ 0x072100, 0x07217c, 0x0721f8, 0x072274, 0x0722f0, 0x07236c, 0x0723e8, 0x072464,
+ 0x0724e0, 0x07255c, 0x0725d8, 0x072654, 0x0726d0, 0x07274c, 0x0727c8, 0x072844,
+ 0x0728c0, 0x07293c, 0x0729b8, 0x072a34, 0x072ab0, 0x072b2c, 0x072ba8, 0x072c24,
+ 0x072ca0, 0x072d1c, 0x072d98, 0x072e14, 0x072e90, 0x072f0c, 0x072f88, 0x073004,
+ 0x073080, 0x0730fc, 0x073178, 0x0731f4, 0x073270, 0x0732ec, 0x073368, 0x0733e4,
+ 0x073460, 0x0734dc, 0x073558, 0x0735d4, 0x073650, 0x0736cc, 0x073748, 0x0737c4,
+ 0x073840, 0x0738bc, 0x073938, 0x0739b4, 0x073a30, 0x073aac, 0x073b28, 0x073ba4,
+ 0x073c20, 0x073c9c, 0x073d18, 0x073d94, 0x073e10, 0x073e8c, 0x073f08, 0x073f84,
+
+ 0x074000, 0x07407c, 0x0740f8, 0x074174, 0x0741f0, 0x07426c, 0x0742e8, 0x074364,
+ 0x0743e0, 0x07445c, 0x0744d8, 0x074554, 0x0745d0, 0x07464c, 0x0746c8, 0x074744,
+ 0x0747c0, 0x07483c, 0x0748b8, 0x074934, 0x0749b0, 0x074a2c, 0x074aa8, 0x074b24,
+ 0x074ba0, 0x074c1c, 0x074c98, 0x074d14, 0x074d90, 0x074e0c, 0x074e88, 0x074f04,
+
+ 0x074f80, 0x075024, 0x0750c8, 0x07516c, 0x075210, 0x0752b4, 0x075358, 0x0753fc,
+ 0x0754a0, 0x075544, 0x0755e8, 0x07568c, 0x075730, 0x0757d4, 0x075878, 0x07591c,
+ 0x0759c0, 0x075a64, 0x075b08, 0x075bac, 0x075c50, 0x075cf4, 0x075d98, 0x075e3c,
+ 0x075ee0, 0x075f84, 0x076028, 0x0760cc, 0x076170, 0x076214, 0x0762b8, 0x07635c,
+
+ 0x076400, 0x07647c, 0x0764f8, 0x076574, 0x0765f0, 0x07666c, 0x0766e8, 0x076764,
+ 0x0767e0, 0x07685c, 0x0768d8, 0x076954, 0x0769d0, 0x076a4c, 0x076ac8, 0x076b44,
+ 0x076bc0, 0x076c3c, 0x076cb8, 0x076d34, 0x076db0, 0x076e2c, 0x076ea8, 0x076f24,
+ 0x076fa0, 0x07701c, 0x077098, 0x077114, 0x077190, 0x07720c, 0x077288, 0x077304,
+
+ 0x077380, 0x077424, 0x0774c8, 0x07756c, 0x077610, 0x0776b4, 0x077758, 0x0777fc,
+ 0x0778a0, 0x077944, 0x0779e8, 0x077a8c, 0x077b30, 0x077bd4, 0x077c78, 0x077d1c,
+ 0x077dc0, 0x077e64, 0x077f08, 0x077fac, 0x078050, 0x0780f4, 0x078198, 0x07823c,
+ 0x0782e0, 0x078384, 0x078428, 0x0784cc, 0x078570, 0x078614, 0x0786b8, 0x07875c,
+
+ 0x078800, 0x07887c, 0x0788f8, 0x078974, 0x0789f0, 0x078a6c, 0x078ae8, 0x078b64,
+ 0x078be0, 0x078c5c, 0x078cd8, 0x078d54, 0x078dd0, 0x078e4c, 0x078ec8, 0x078f44,
+ 0x078fc0, 0x07903c, 0x0790b8, 0x079134, 0x0791b0, 0x07922c, 0x0792a8, 0x079324,
+ 0x0793a0, 0x07941c, 0x079498, 0x079514, 0x079590, 0x07960c, 0x079688, 0x079704,
+
+ 0x079780, 0x079824, 0x0798c8, 0x07996c, 0x079a10, 0x079ab4, 0x079b58, 0x079bfc,
+ 0x079ca0, 0x079d44, 0x079de8, 0x079e8c, 0x079f30, 0x079fd4, 0x07a078, 0x07a11c,
+ 0x07a1c0, 0x07a264, 0x07a308, 0x07a3ac, 0x07a450, 0x07a4f4, 0x07a598, 0x07a63c,
+ 0x07a6e0, 0x07a784, 0x07a828, 0x07a8cc, 0x07a970, 0x07aa14, 0x07aab8, 0x07ab5c,
+
+ 0x07ac00, 0x07ac7c, 0x07acf8, 0x07ad74, 0x07adf0, 0x07ae6c, 0x07aee8, 0x07af64,
+ 0x07afe0, 0x07b05c, 0x07b0d8, 0x07b154, 0x07b1d0, 0x07b24c, 0x07b2c8, 0x07b344,
+ 0x07b3c0, 0x07b43c, 0x07b4b8, 0x07b534, 0x07b5b0, 0x07b62c, 0x07b6a8, 0x07b724,
+ 0x07b7a0, 0x07b81c, 0x07b898, 0x07b914, 0x07b990, 0x07ba0c, 0x07ba88, 0x07bb04,
+
+ 0x07bb80, 0x07bc24, 0x07bcc8, 0x07bd6c, 0x07be10, 0x07beb4, 0x07bf58, 0x07bffc,
+ 0x07c0a0, 0x07c144, 0x07c1e8, 0x07c28c, 0x07c330, 0x07c3d4, 0x07c478, 0x07c51c,
+ 0x07c5c0, 0x07c664, 0x07c708, 0x07c7ac, 0x07c850, 0x07c8f4, 0x07c998, 0x07ca3c,
+ 0x07cae0, 0x07cb84, 0x07cc28, 0x07cccc, 0x07cd70, 0x07ce14, 0x07ceb8, 0x07cf5c,
+
+ 0x07d000, 0x07d07c, 0x07d0f8, 0x07d174, 0x07d1f0, 0x07d26c, 0x07d2e8, 0x07d364,
+ 0x07d3e0, 0x07d45c, 0x07d4d8, 0x07d554, 0x07d5d0, 0x07d64c, 0x07d6c8, 0x07d744,
+ 0x07d7c0, 0x07d83c, 0x07d8b8, 0x07d934, 0x07d9b0, 0x07da2c, 0x07daa8, 0x07db24,
+ 0x07dba0, 0x07dc1c, 0x07dc98, 0x07dd14, 0x07dd90, 0x07de0c, 0x07de88, 0x07df04,
+
+ 0x07df80, 0x07e024, 0x07e0c8, 0x07e16c, 0x07e210, 0x07e2b4, 0x07e358, 0x07e3fc,
+ 0x07e4a0, 0x07e544, 0x07e5e8, 0x07e68c, 0x07e730, 0x07e7d4, 0x07e878, 0x07e91c,
+ 0x07e9c0, 0x07ea64, 0x07eb08, 0x07ebac, 0x07ec50, 0x07ecf4, 0x07ed98, 0x07ee3c,
+ 0x07eee0, 0x07ef84, 0x07f028, 0x07f0cc, 0x07f170, 0x07f214, 0x07f2b8, 0x07f35c,
+
+ 0x07f400, 0x07f47c, 0x07f4f8, 0x07f574, 0x07f5f0, 0x07f66c, 0x07f6e8, 0x07f764,
+ 0x07f7e0, 0x07f85c, 0x07f8d8, 0x07f954, 0x07f9d0, 0x07fa4c, 0x07fac8, 0x07fb44,
+ 0x07fbc0, 0x07fc3c, 0x07fcb8, 0x07fd34, 0x07fdb0, 0x07fe2c, 0x07fea8, 0x07ff24,
+ 0x07ffa0, 0x08001c, 0x080098, 0x080114, 0x080190, 0x08020c, 0x080288, 0x080304,
+
+ 0x080380, 0x080424, 0x0804c8, 0x08056c, 0x080610, 0x0806b4, 0x080758, 0x0807fc,
+ 0x0808a0, 0x080944, 0x0809e8, 0x080a8c, 0x080b30, 0x080bd4, 0x080c78, 0x080d1c,
+ 0x080dc0, 0x080e64, 0x080f08, 0x080fac, 0x081050, 0x0810f4, 0x081198, 0x08123c,
+ 0x0812e0, 0x081384, 0x081428, 0x0814cc, 0x081570, 0x081614, 0x0816b8, 0x08175c,
+
+ 0x081800, 0x08187c, 0x0818f8, 0x081974, 0x0819f0, 0x081a6c, 0x081ae8, 0x081b64,
+ 0x081be0, 0x081c5c, 0x081cd8, 0x081d54, 0x081dd0, 0x081e4c, 0x081ec8, 0x081f44,
+ 0x081fc0, 0x08203c, 0x0820b8, 0x082134, 0x0821b0, 0x08222c, 0x0822a8, 0x082324,
+ 0x0823a0, 0x08241c, 0x082498, 0x082514, 0x082590, 0x08260c, 0x082688, 0x082704,
+
+ 0x082780, 0x082824, 0x0828c8, 0x08296c, 0x082a10, 0x082ab4, 0x082b58, 0x082bfc,
+ 0x082ca0, 0x082d44, 0x082de8, 0x082e8c, 0x082f30, 0x082fd4, 0x083078, 0x08311c,
+ 0x0831c0, 0x083264, 0x083308, 0x0833ac, 0x083450, 0x0834f4, 0x083598, 0x08363c,
+ 0x0836e0, 0x083784, 0x083828, 0x0838cc, 0x083970, 0x083a14, 0x083ab8, 0x083b5c,
+
+ 0x083c00, 0x083c7c, 0x083cf8, 0x083d74, 0x083df0, 0x083e6c, 0x083ee8, 0x083f64,
+ 0x083fe0, 0x08405c, 0x0840d8, 0x084154, 0x0841d0, 0x08424c, 0x0842c8, 0x084344,
+ 0x0843c0, 0x08443c, 0x0844b8, 0x084534, 0x0845b0, 0x08462c, 0x0846a8, 0x084724,
+ 0x0847a0, 0x08481c, 0x084898, 0x084914, 0x084990, 0x084a0c, 0x084a88, 0x084b04,
+
+ 0x084b80, 0x084c24, 0x084cc8, 0x084d6c, 0x084e10, 0x084eb4, 0x084f58, 0x084ffc,
+ 0x0850a0, 0x085144, 0x0851e8, 0x08528c, 0x085330, 0x0853d4, 0x085478, 0x08551c,
+ 0x0855c0, 0x085664, 0x085708, 0x0857ac, 0x085850, 0x0858f4, 0x085998, 0x085a3c,
+ 0x085ae0, 0x085b84, 0x085c28, 0x085ccc, 0x085d70, 0x085e14, 0x085eb8, 0x085f5c,
+
+
+
+ 0x086000, 0x08607c, 0x0860f8, 0x086174, 0x0861f0, 0x08626c, 0x0862e8, 0x086364,
+ 0x0863e0, 0x08645c, 0x0864d8, 0x086554, 0x0865d0, 0x08664c, 0x0866c8, 0x086744,
+ 0x0867c0, 0x08683c, 0x0868b8, 0x086934, 0x0869b0, 0x086a2c, 0x086aa8, 0x086b24,
+ 0x086ba0, 0x086c1c, 0x086c98, 0x086d14, 0x086d90, 0x086e0c, 0x086e88, 0x086f04,
+ 0x086f80, 0x086ffc, 0x087078, 0x0870f4, 0x087170, 0x0871ec, 0x087268, 0x0872e4,
+ 0x087360, 0x0873dc, 0x087458, 0x0874d4, 0x087550, 0x0875cc, 0x087648, 0x0876c4,
+ 0x087740, 0x0877bc, 0x087838, 0x0878b4, 0x087930, 0x0879ac, 0x087a28, 0x087aa4,
+ 0x087b20, 0x087b9c, 0x087c18, 0x087c94, 0x087d10, 0x087d8c, 0x087e08, 0x087e84,
+ 0x087f00, 0x087f7c, 0x087ff8, 0x088074, 0x0880f0, 0x08816c, 0x0881e8, 0x088264,
+ 0x0882e0, 0x08835c, 0x0883d8, 0x088454, 0x0884d0, 0x08854c, 0x0885c8, 0x088644,
+ 0x0886c0, 0x08873c, 0x0887b8, 0x088834, 0x0888b0, 0x08892c, 0x0889a8, 0x088a24,
+ 0x088aa0, 0x088b1c, 0x088b98, 0x088c14, 0x088c90, 0x088d0c, 0x088d88, 0x088e04,
+ 0x088e80, 0x088efc, 0x088f78, 0x088ff4, 0x089070, 0x0890ec, 0x089168, 0x0891e4,
+ 0x089260, 0x0892dc, 0x089358, 0x0893d4, 0x089450, 0x0894cc, 0x089548, 0x0895c4,
+ 0x089640, 0x0896bc, 0x089738, 0x0897b4, 0x089830, 0x0898ac, 0x089928, 0x0899a4,
+ 0x089a20, 0x089a9c, 0x089b18, 0x089b94, 0x089c10, 0x089c8c, 0x089d08, 0x089d84,
+ 0x089e00, 0x089e7c, 0x089ef8, 0x089f74, 0x089ff0, 0x08a06c, 0x08a0e8, 0x08a164,
+ 0x08a1e0, 0x08a25c, 0x08a2d8, 0x08a354, 0x08a3d0, 0x08a44c, 0x08a4c8, 0x08a544,
+ 0x08a5c0, 0x08a63c, 0x08a6b8, 0x08a734, 0x08a7b0, 0x08a82c, 0x08a8a8, 0x08a924,
+ 0x08a9a0, 0x08aa1c, 0x08aa98, 0x08ab14, 0x08ab90, 0x08ac0c, 0x08ac88, 0x08ad04,
+ 0x08ad80, 0x08adfc, 0x08ae78, 0x08aef4, 0x08af70, 0x08afec, 0x08b068, 0x08b0e4,
+ 0x08b160, 0x08b1dc, 0x08b258, 0x08b2d4, 0x08b350, 0x08b3cc, 0x08b448, 0x08b4c4,
+ 0x08b540, 0x08b5bc, 0x08b638, 0x08b6b4, 0x08b730, 0x08b7ac, 0x08b828, 0x08b8a4,
+ 0x08b920, 0x08b99c, 0x08ba18, 0x08ba94, 0x08bb10, 0x08bb8c, 0x08bc08, 0x08bc84,
+ 0x08bd00, 0x08bd7c, 0x08bdf8, 0x08be74, 0x08bef0, 0x08bf6c, 0x08bfe8, 0x08c064,
+ 0x08c0e0, 0x08c15c, 0x08c1d8, 0x08c254, 0x08c2d0, 0x08c34c, 0x08c3c8, 0x08c444,
+ 0x08c4c0, 0x08c53c, 0x08c5b8, 0x08c634, 0x08c6b0, 0x08c72c, 0x08c7a8, 0x08c824,
+ 0x08c8a0, 0x08c91c, 0x08c998, 0x08ca14, 0x08ca90, 0x08cb0c, 0x08cb88, 0x08cc04,
+ 0x08cc80, 0x08ccfc, 0x08cd78, 0x08cdf4, 0x08ce70, 0x08ceec, 0x08cf68, 0x08cfe4,
+ 0x08d060, 0x08d0dc, 0x08d158, 0x08d1d4, 0x08d250, 0x08d2cc, 0x08d348, 0x08d3c4,
+ 0x08d440, 0x08d4bc, 0x08d538, 0x08d5b4, 0x08d630, 0x08d6ac, 0x08d728, 0x08d7a4,
+ 0x08d820, 0x08d89c, 0x08d918, 0x08d994, 0x08da10, 0x08da8c, 0x08db08, 0x08db84,
+
+ 0x08dc00, 0x08dca4, 0x08dd20, 0x08ddc4, 0x08de40, 0x08dee4, 0x08df60, 0x08e004,
+ 0x08e080, 0x08e124, 0x08e1a0, 0x08e244, 0x08e2c0, 0x08e364, 0x08e3e0, 0x08e484,
+ 0x08e500, 0x08e5a4, 0x08e620, 0x08e6c4, 0x08e740, 0x08e7e4, 0x08e860, 0x08e904,
+ 0x08e980, 0x08ea24, 0x08eaa0, 0x08eb44, 0x08ebc0, 0x08ec64, 0x08ece0, 0x08ed84,
+ 0x08ee00, 0x08eea4, 0x08ef20, 0x08efc4, 0x08f040, 0x08f0e4, 0x08f160, 0x08f204,
+ 0x08f280, 0x08f324, 0x08f3a0, 0x08f444, 0x08f4c0, 0x08f564, 0x08f5e0, 0x08f684,
+ 0x08f700, 0x08f7a4, 0x08f820, 0x08f8c4, 0x08f940, 0x08f9e4, 0x08fa60, 0x08fb04,
+ 0x08fb80, 0x08fc24, 0x08fca0, 0x08fd44, 0x08fdc0, 0x08fe64, 0x08fee0, 0x08ff84,
+ 0x090000, 0x0900a4, 0x090120, 0x0901c4, 0x090240, 0x0902e4, 0x090360, 0x090404,
+ 0x090480, 0x090524, 0x0905a0, 0x090644, 0x0906c0, 0x090764, 0x0907e0, 0x090884,
+ 0x090900, 0x0909a4, 0x090a20, 0x090ac4, 0x090b40, 0x090be4, 0x090c60, 0x090d04,
+ 0x090d80, 0x090e24, 0x090ea0, 0x090f44, 0x090fc0, 0x091064, 0x0910e0, 0x091184,
+ 0x091200, 0x0912a4, 0x091320, 0x0913c4, 0x091440, 0x0914e4, 0x091560, 0x091604,
+ 0x091680, 0x091724, 0x0917a0, 0x091844, 0x0918c0, 0x091964, 0x0919e0, 0x091a84,
+ 0x091b00, 0x091ba4, 0x091c20, 0x091cc4, 0x091d40, 0x091de4, 0x091e60, 0x091f04,
+ 0x091f80, 0x092024, 0x0920a0, 0x092144, 0x0921c0, 0x092264, 0x0922e0, 0x092384,
+ 0x092400, 0x0924a4, 0x092520, 0x0925c4, 0x092640, 0x0926e4, 0x092760, 0x092804,
+ 0x092880, 0x092924, 0x0929a0, 0x092a44, 0x092ac0, 0x092b64, 0x092be0, 0x092c84,
+ 0x092d00, 0x092da4, 0x092e20, 0x092ec4, 0x092f40, 0x092fe4, 0x093060, 0x093104,
+ 0x093180, 0x093224, 0x0932a0, 0x093344, 0x0933c0, 0x093464, 0x0934e0, 0x093584,
+ 0x093600, 0x0936a4, 0x093720, 0x0937c4, 0x093840, 0x0938e4, 0x093960, 0x093a04,
+ 0x093a80, 0x093b24, 0x093ba0, 0x093c44, 0x093cc0, 0x093d64, 0x093de0, 0x093e84,
+ 0x093f00, 0x093fa4, 0x094020, 0x0940c4, 0x094140, 0x0941e4, 0x094260, 0x094304,
+ 0x094380, 0x094424, 0x0944a0, 0x094544, 0x0945c0, 0x094664, 0x0946e0, 0x094784,
+ 0x094800, 0x0948a4, 0x094920, 0x0949c4, 0x094a40, 0x094ae4, 0x094b60, 0x094c04,
+ 0x094c80, 0x094d24, 0x094da0, 0x094e44, 0x094ec0, 0x094f64, 0x094fe0, 0x095084,
+ 0x095100, 0x0951a4, 0x095220, 0x0952c4, 0x095340, 0x0953e4, 0x095460, 0x095504,
+ 0x095580, 0x095624, 0x0956a0, 0x095744, 0x0957c0, 0x095864, 0x0958e0, 0x095984,
+ 0x095a00, 0x095aa4, 0x095b20, 0x095bc4, 0x095c40, 0x095ce4, 0x095d60, 0x095e04,
+ 0x095e80, 0x095f24, 0x095fa0, 0x096044, 0x0960c0, 0x096164, 0x0961e0, 0x096284,
+ 0x096300, 0x0963a4, 0x096420, 0x0964c4, 0x096540, 0x0965e4, 0x096660, 0x096704,
+ 0x096780, 0x096824, 0x0968a0, 0x096944, 0x0969c0, 0x096a64, 0x096ae0, 0x096b84,
+
+ 0x096c00, 0x096c7c, 0x096cf8, 0x096d74, 0x096df0, 0x096e6c, 0x096ee8, 0x096f64,
+ 0x096fe0, 0x09705c, 0x0970d8, 0x097154, 0x0971d0, 0x09724c, 0x0972c8, 0x097344,
+ 0x0973c0, 0x09743c, 0x0974b8, 0x097534, 0x0975b0, 0x09762c, 0x0976a8, 0x097724,
+ 0x0977a0, 0x09781c, 0x097898, 0x097914, 0x097990, 0x097a0c, 0x097a88, 0x097b04,
+ 0x097b80, 0x097bfc, 0x097c78, 0x097cf4, 0x097d70, 0x097dec, 0x097e68, 0x097ee4,
+ 0x097f60, 0x097fdc, 0x098058, 0x0980d4, 0x098150, 0x0981cc, 0x098248, 0x0982c4,
+ 0x098340, 0x0983bc, 0x098438, 0x0984b4, 0x098530, 0x0985ac, 0x098628, 0x0986a4,
+ 0x098720, 0x09879c, 0x098818, 0x098894, 0x098910, 0x09898c, 0x098a08, 0x098a84,
+ 0x098b00, 0x098b7c, 0x098bf8, 0x098c74, 0x098cf0, 0x098d6c, 0x098de8, 0x098e64,
+ 0x098ee0, 0x098f5c, 0x098fd8, 0x099054, 0x0990d0, 0x09914c, 0x0991c8, 0x099244,
+ 0x0992c0, 0x09933c, 0x0993b8, 0x099434, 0x0994b0, 0x09952c, 0x0995a8, 0x099624,
+ 0x0996a0, 0x09971c, 0x099798, 0x099814, 0x099890, 0x09990c, 0x099988, 0x099a04,
+ 0x099a80, 0x099afc, 0x099b78, 0x099bf4, 0x099c70, 0x099cec, 0x099d68, 0x099de4,
+ 0x099e60, 0x099edc, 0x099f58, 0x099fd4, 0x09a050, 0x09a0cc, 0x09a148, 0x09a1c4,
+ 0x09a240, 0x09a2bc, 0x09a338, 0x09a3b4, 0x09a430, 0x09a4ac, 0x09a528, 0x09a5a4,
+ 0x09a620, 0x09a69c, 0x09a718, 0x09a794, 0x09a810, 0x09a88c, 0x09a908, 0x09a984,
+ 0x09aa00, 0x09aa7c, 0x09aaf8, 0x09ab74, 0x09abf0, 0x09ac6c, 0x09ace8, 0x09ad64,
+ 0x09ade0, 0x09ae5c, 0x09aed8, 0x09af54, 0x09afd0, 0x09b04c, 0x09b0c8, 0x09b144,
+ 0x09b1c0, 0x09b23c, 0x09b2b8, 0x09b334, 0x09b3b0, 0x09b42c, 0x09b4a8, 0x09b524,
+ 0x09b5a0, 0x09b61c, 0x09b698, 0x09b714, 0x09b790, 0x09b80c, 0x09b888, 0x09b904,
+ 0x09b980, 0x09b9fc, 0x09ba78, 0x09baf4, 0x09bb70, 0x09bbec, 0x09bc68, 0x09bce4,
+ 0x09bd60, 0x09bddc, 0x09be58, 0x09bed4, 0x09bf50, 0x09bfcc, 0x09c048, 0x09c0c4,
+ 0x09c140, 0x09c1bc, 0x09c238, 0x09c2b4, 0x09c330, 0x09c3ac, 0x09c428, 0x09c4a4,
+ 0x09c520, 0x09c59c, 0x09c618, 0x09c694, 0x09c710, 0x09c78c, 0x09c808, 0x09c884,
+ 0x09c900, 0x09c97c, 0x09c9f8, 0x09ca74, 0x09caf0, 0x09cb6c, 0x09cbe8, 0x09cc64,
+ 0x09cce0, 0x09cd5c, 0x09cdd8, 0x09ce54, 0x09ced0, 0x09cf4c, 0x09cfc8, 0x09d044,
+ 0x09d0c0, 0x09d13c, 0x09d1b8, 0x09d234, 0x09d2b0, 0x09d32c, 0x09d3a8, 0x09d424,
+ 0x09d4a0, 0x09d51c, 0x09d598, 0x09d614, 0x09d690, 0x09d70c, 0x09d788, 0x09d804,
+ 0x09d880, 0x09d8fc, 0x09d978, 0x09d9f4, 0x09da70, 0x09daec, 0x09db68, 0x09dbe4,
+ 0x09dc60, 0x09dcdc, 0x09dd58, 0x09ddd4, 0x09de50, 0x09decc, 0x09df48, 0x09dfc4,
+ 0x09e040, 0x09e0bc, 0x09e138, 0x09e1b4, 0x09e230, 0x09e2ac, 0x09e328, 0x09e3a4,
+ 0x09e420, 0x09e49c, 0x09e518, 0x09e594, 0x09e610, 0x09e68c, 0x09e708, 0x09e784,
+
+ 0x09e800, 0x09e8a4, 0x09e920, 0x09e9c4, 0x09ea40, 0x09eae4, 0x09eb60, 0x09ec04,
+ 0x09ec80, 0x09ed24, 0x09eda0, 0x09ee44, 0x09eec0, 0x09ef64, 0x09efe0, 0x09f084,
+ 0x09f100, 0x09f1a4, 0x09f220, 0x09f2c4, 0x09f340, 0x09f3e4, 0x09f460, 0x09f504,
+ 0x09f580, 0x09f624, 0x09f6a0, 0x09f744, 0x09f7c0, 0x09f864, 0x09f8e0, 0x09f984,
+ 0x09fa00, 0x09faa4, 0x09fb20, 0x09fbc4, 0x09fc40, 0x09fce4, 0x09fd60, 0x09fe04,
+ 0x09fe80, 0x09ff24, 0x09ffa0, 0x0a0044, 0x0a00c0, 0x0a0164, 0x0a01e0, 0x0a0284,
+ 0x0a0300, 0x0a03a4, 0x0a0420, 0x0a04c4, 0x0a0540, 0x0a05e4, 0x0a0660, 0x0a0704,
+ 0x0a0780, 0x0a0824, 0x0a08a0, 0x0a0944, 0x0a09c0, 0x0a0a64, 0x0a0ae0, 0x0a0b84,
+ 0x0a0c00, 0x0a0ca4, 0x0a0d20, 0x0a0dc4, 0x0a0e40, 0x0a0ee4, 0x0a0f60, 0x0a1004,
+ 0x0a1080, 0x0a1124, 0x0a11a0, 0x0a1244, 0x0a12c0, 0x0a1364, 0x0a13e0, 0x0a1484,
+ 0x0a1500, 0x0a15a4, 0x0a1620, 0x0a16c4, 0x0a1740, 0x0a17e4, 0x0a1860, 0x0a1904,
+ 0x0a1980, 0x0a1a24, 0x0a1aa0, 0x0a1b44, 0x0a1bc0, 0x0a1c64, 0x0a1ce0, 0x0a1d84,
+ 0x0a1e00, 0x0a1ea4, 0x0a1f20, 0x0a1fc4, 0x0a2040, 0x0a20e4, 0x0a2160, 0x0a2204,
+ 0x0a2280, 0x0a2324, 0x0a23a0, 0x0a2444, 0x0a24c0, 0x0a2564, 0x0a25e0, 0x0a2684,
+ 0x0a2700, 0x0a27a4, 0x0a2820, 0x0a28c4, 0x0a2940, 0x0a29e4, 0x0a2a60, 0x0a2b04,
+ 0x0a2b80, 0x0a2c24, 0x0a2ca0, 0x0a2d44, 0x0a2dc0, 0x0a2e64, 0x0a2ee0, 0x0a2f84,
+ 0x0a3000, 0x0a30a4, 0x0a3120, 0x0a31c4, 0x0a3240, 0x0a32e4, 0x0a3360, 0x0a3404,
+ 0x0a3480, 0x0a3524, 0x0a35a0, 0x0a3644, 0x0a36c0, 0x0a3764, 0x0a37e0, 0x0a3884,
+ 0x0a3900, 0x0a39a4, 0x0a3a20, 0x0a3ac4, 0x0a3b40, 0x0a3be4, 0x0a3c60, 0x0a3d04,
+ 0x0a3d80, 0x0a3e24, 0x0a3ea0, 0x0a3f44, 0x0a3fc0, 0x0a4064, 0x0a40e0, 0x0a4184,
+ 0x0a4200, 0x0a42a4, 0x0a4320, 0x0a43c4, 0x0a4440, 0x0a44e4, 0x0a4560, 0x0a4604,
+ 0x0a4680, 0x0a4724, 0x0a47a0, 0x0a4844, 0x0a48c0, 0x0a4964, 0x0a49e0, 0x0a4a84,
+ 0x0a4b00, 0x0a4ba4, 0x0a4c20, 0x0a4cc4, 0x0a4d40, 0x0a4de4, 0x0a4e60, 0x0a4f04,
+ 0x0a4f80, 0x0a5024, 0x0a50a0, 0x0a5144, 0x0a51c0, 0x0a5264, 0x0a52e0, 0x0a5384,
+ 0x0a5400, 0x0a54a4, 0x0a5520, 0x0a55c4, 0x0a5640, 0x0a56e4, 0x0a5760, 0x0a5804,
+ 0x0a5880, 0x0a5924, 0x0a59a0, 0x0a5a44, 0x0a5ac0, 0x0a5b64, 0x0a5be0, 0x0a5c84,
+ 0x0a5d00, 0x0a5da4, 0x0a5e20, 0x0a5ec4, 0x0a5f40, 0x0a5fe4, 0x0a6060, 0x0a6104,
+ 0x0a6180, 0x0a6224, 0x0a62a0, 0x0a6344, 0x0a63c0, 0x0a6464, 0x0a64e0, 0x0a6584,
+ 0x0a6600, 0x0a66a4, 0x0a6720, 0x0a67c4, 0x0a6840, 0x0a68e4, 0x0a6960, 0x0a6a04,
+ 0x0a6a80, 0x0a6b24, 0x0a6ba0, 0x0a6c44, 0x0a6cc0, 0x0a6d64, 0x0a6de0, 0x0a6e84,
+ 0x0a6f00, 0x0a6fa4, 0x0a7020, 0x0a70c4, 0x0a7140, 0x0a71e4, 0x0a7260, 0x0a7304,
+ 0x0a7380, 0x0a7424, 0x0a74a0, 0x0a7544, 0x0a75c0, 0x0a7664, 0x0a76e0, 0x0a7784,
+
+ 0x0a7800, 0x0a787c, 0x0a78f8, 0x0a7974, 0x0a79f0, 0x0a7a6c, 0x0a7ae8, 0x0a7b64,
+ 0x0a7be0, 0x0a7c5c, 0x0a7cd8, 0x0a7d54, 0x0a7dd0, 0x0a7e4c, 0x0a7ec8, 0x0a7f44,
+ 0x0a7fc0, 0x0a8064, 0x0a80e0, 0x0a8184, 0x0a8200, 0x0a82a4, 0x0a8320, 0x0a83c4,
+ 0x0a8440, 0x0a84e4, 0x0a8560, 0x0a8604, 0x0a8680, 0x0a8724, 0x0a87a0, 0x0a8844,
+ 0x0a88c0, 0x0a893c, 0x0a89b8, 0x0a8a34, 0x0a8ab0, 0x0a8b2c, 0x0a8ba8, 0x0a8c24,
+ 0x0a8ca0, 0x0a8d1c, 0x0a8d98, 0x0a8e14, 0x0a8e90, 0x0a8f0c, 0x0a8f88, 0x0a9004,
+ 0x0a9080, 0x0a9124, 0x0a91a0, 0x0a9244, 0x0a92c0, 0x0a9364, 0x0a93e0, 0x0a9484,
+ 0x0a9500, 0x0a95a4, 0x0a9620, 0x0a96c4, 0x0a9740, 0x0a97e4, 0x0a9860, 0x0a9904,
+ 0x0a9980, 0x0a99fc, 0x0a9a78, 0x0a9af4, 0x0a9b70, 0x0a9bec, 0x0a9c68, 0x0a9ce4,
+ 0x0a9d60, 0x0a9ddc, 0x0a9e58, 0x0a9ed4, 0x0a9f50, 0x0a9fcc, 0x0aa048, 0x0aa0c4,
+ 0x0aa140, 0x0aa1e4, 0x0aa260, 0x0aa304, 0x0aa380, 0x0aa424, 0x0aa4a0, 0x0aa544,
+ 0x0aa5c0, 0x0aa664, 0x0aa6e0, 0x0aa784, 0x0aa800, 0x0aa8a4, 0x0aa920, 0x0aa9c4,
+ 0x0aaa40, 0x0aaabc, 0x0aab38, 0x0aabb4, 0x0aac30, 0x0aacac, 0x0aad28, 0x0aada4,
+ 0x0aae20, 0x0aae9c, 0x0aaf18, 0x0aaf94, 0x0ab010, 0x0ab08c, 0x0ab108, 0x0ab184,
+ 0x0ab200, 0x0ab2a4, 0x0ab320, 0x0ab3c4, 0x0ab440, 0x0ab4e4, 0x0ab560, 0x0ab604,
+ 0x0ab680, 0x0ab724, 0x0ab7a0, 0x0ab844, 0x0ab8c0, 0x0ab964, 0x0ab9e0, 0x0aba84,
+ 0x0abb00, 0x0abb7c, 0x0abbf8, 0x0abc74, 0x0abcf0, 0x0abd6c, 0x0abde8, 0x0abe64,
+ 0x0abee0, 0x0abf5c, 0x0abfd8, 0x0ac054, 0x0ac0d0, 0x0ac14c, 0x0ac1c8, 0x0ac244,
+ 0x0ac2c0, 0x0ac364, 0x0ac3e0, 0x0ac484, 0x0ac500, 0x0ac5a4, 0x0ac620, 0x0ac6c4,
+ 0x0ac740, 0x0ac7e4, 0x0ac860, 0x0ac904, 0x0ac980, 0x0aca24, 0x0acaa0, 0x0acb44,
+ 0x0acbc0, 0x0acc3c, 0x0accb8, 0x0acd34, 0x0acdb0, 0x0ace2c, 0x0acea8, 0x0acf24,
+ 0x0acfa0, 0x0ad01c, 0x0ad098, 0x0ad114, 0x0ad190, 0x0ad20c, 0x0ad288, 0x0ad304,
+ 0x0ad380, 0x0ad424, 0x0ad4a0, 0x0ad544, 0x0ad5c0, 0x0ad664, 0x0ad6e0, 0x0ad784,
+ 0x0ad800, 0x0ad8a4, 0x0ad920, 0x0ad9c4, 0x0ada40, 0x0adae4, 0x0adb60, 0x0adc04,
+ 0x0adc80, 0x0adcfc, 0x0add78, 0x0addf4, 0x0ade70, 0x0adeec, 0x0adf68, 0x0adfe4,
+ 0x0ae060, 0x0ae0dc, 0x0ae158, 0x0ae1d4, 0x0ae250, 0x0ae2cc, 0x0ae348, 0x0ae3c4,
+ 0x0ae440, 0x0ae4e4, 0x0ae560, 0x0ae604, 0x0ae680, 0x0ae724, 0x0ae7a0, 0x0ae844,
+ 0x0ae8c0, 0x0ae964, 0x0ae9e0, 0x0aea84, 0x0aeb00, 0x0aeba4, 0x0aec20, 0x0aecc4,
+ 0x0aed40, 0x0aedbc, 0x0aee38, 0x0aeeb4, 0x0aef30, 0x0aefac, 0x0af028, 0x0af0a4,
+ 0x0af120, 0x0af19c, 0x0af218, 0x0af294, 0x0af310, 0x0af38c, 0x0af408, 0x0af484,
+ 0x0af500, 0x0af5a4, 0x0af620, 0x0af6c4, 0x0af740, 0x0af7e4, 0x0af860, 0x0af904,
+ 0x0af980, 0x0afa24, 0x0afaa0, 0x0afb44, 0x0afbc0, 0x0afc64, 0x0afce0, 0x0afd84,
+ 0x0afe00, 0x0afe7c, 0x0afef8, 0x0aff74, 0x0afff0, 0x0b006c, 0x0b00e8, 0x0b0164,
+ 0x0b01e0, 0x0b025c, 0x0b02d8, 0x0b0354, 0x0b03d0, 0x0b044c, 0x0b04c8, 0x0b0544,
+ 0x0b05c0, 0x0b0664, 0x0b06e0, 0x0b0784, 0x0b0800, 0x0b08a4, 0x0b0920, 0x0b09c4,
+ 0x0b0a40, 0x0b0ae4, 0x0b0b60, 0x0b0c04, 0x0b0c80, 0x0b0d24, 0x0b0da0, 0x0b0e44,
+ 0x0b0ec0, 0x0b0f3c, 0x0b0fb8, 0x0b1034, 0x0b10b0, 0x0b112c, 0x0b11a8, 0x0b1224,
+ 0x0b12a0, 0x0b131c, 0x0b1398, 0x0b1414, 0x0b1490, 0x0b150c, 0x0b1588, 0x0b1604,
+ 0x0b1680, 0x0b1724, 0x0b17a0, 0x0b1844, 0x0b18c0, 0x0b1964, 0x0b19e0, 0x0b1a84,
+ 0x0b1b00, 0x0b1ba4, 0x0b1c20, 0x0b1cc4, 0x0b1d40, 0x0b1de4, 0x0b1e60, 0x0b1f04,
+ 0x0b1f80, 0x0b1ffc, 0x0b2078, 0x0b20f4, 0x0b2170, 0x0b21ec, 0x0b2268, 0x0b22e4,
+ 0x0b2360, 0x0b23dc, 0x0b2458, 0x0b24d4, 0x0b2550, 0x0b25cc, 0x0b2648, 0x0b26c4,
+ 0x0b2740, 0x0b27e4, 0x0b2860, 0x0b2904, 0x0b2980, 0x0b2a24, 0x0b2aa0, 0x0b2b44,
+ 0x0b2bc0, 0x0b2c64, 0x0b2ce0, 0x0b2d84, 0x0b2e00, 0x0b2ea4, 0x0b2f20, 0x0b2fc4,
+ 0x0b3040, 0x0b30bc, 0x0b3138, 0x0b31b4, 0x0b3230, 0x0b32ac, 0x0b3328, 0x0b33a4,
+ 0x0b3420, 0x0b349c, 0x0b3518, 0x0b3594, 0x0b3610, 0x0b368c, 0x0b3708, 0x0b3784,
+ 0x0b3800, 0x0b38a4, 0x0b3920, 0x0b39c4, 0x0b3a40, 0x0b3ae4, 0x0b3b60, 0x0b3c04,
+ 0x0b3c80, 0x0b3d24, 0x0b3da0, 0x0b3e44, 0x0b3ec0, 0x0b3f64, 0x0b3fe0, 0x0b4084,
+ 0x0b4100, 0x0b417c, 0x0b41f8, 0x0b4274, 0x0b42f0, 0x0b436c, 0x0b43e8, 0x0b4464,
+ 0x0b44e0, 0x0b455c, 0x0b45d8, 0x0b4654, 0x0b46d0, 0x0b474c, 0x0b47c8, 0x0b4844,
+ 0x0b48c0, 0x0b4964, 0x0b49e0, 0x0b4a84, 0x0b4b00, 0x0b4ba4, 0x0b4c20, 0x0b4cc4,
+ 0x0b4d40, 0x0b4de4, 0x0b4e60, 0x0b4f04, 0x0b4f80, 0x0b5024, 0x0b50a0, 0x0b5144,
+ 0x0b51c0, 0x0b523c, 0x0b52b8, 0x0b5334, 0x0b53b0, 0x0b542c, 0x0b54a8, 0x0b5524,
+ 0x0b55a0, 0x0b561c, 0x0b5698, 0x0b5714, 0x0b5790, 0x0b580c, 0x0b5888, 0x0b5904,
+ 0x0b5980, 0x0b5a24, 0x0b5aa0, 0x0b5b44, 0x0b5bc0, 0x0b5c64, 0x0b5ce0, 0x0b5d84,
+ 0x0b5e00, 0x0b5ea4, 0x0b5f20, 0x0b5fc4, 0x0b6040, 0x0b60e4, 0x0b6160, 0x0b6204,
+ 0x0b6280, 0x0b62fc, 0x0b6378, 0x0b63f4, 0x0b6470, 0x0b64ec, 0x0b6568, 0x0b65e4,
+ 0x0b6660, 0x0b66dc, 0x0b6758, 0x0b67d4, 0x0b6850, 0x0b68cc, 0x0b6948, 0x0b69c4,
+ 0x0b6a40, 0x0b6ae4, 0x0b6b60, 0x0b6c04, 0x0b6c80, 0x0b6d24, 0x0b6da0, 0x0b6e44,
+ 0x0b6ec0, 0x0b6f64, 0x0b6fe0, 0x0b7084, 0x0b7100, 0x0b71a4, 0x0b7220, 0x0b72c4,
+ 0x0b7340, 0x0b73bc, 0x0b7438, 0x0b74b4, 0x0b7530, 0x0b75ac, 0x0b7628, 0x0b76a4,
+ 0x0b7720, 0x0b779c, 0x0b7818, 0x0b7894, 0x0b7910, 0x0b798c, 0x0b7a08, 0x0b7a84,
+ 0x0b7b00, 0x0b7ba4, 0x0b7c20, 0x0b7cc4, 0x0b7d40, 0x0b7de4, 0x0b7e60, 0x0b7f04,
+ 0x0b7f80, 0x0b8024, 0x0b80a0, 0x0b8144, 0x0b81c0, 0x0b8264, 0x0b82e0, 0x0b8384,
+ 0x0b8400, 0x0b847c, 0x0b84f8, 0x0b8574, 0x0b85f0, 0x0b866c, 0x0b86e8, 0x0b8764,
+ 0x0b87e0, 0x0b885c, 0x0b88d8, 0x0b8954, 0x0b89d0, 0x0b8a4c, 0x0b8ac8, 0x0b8b44,
+ 0x0b8bc0, 0x0b8c64, 0x0b8ce0, 0x0b8d84, 0x0b8e00, 0x0b8ea4, 0x0b8f20, 0x0b8fc4,
+ 0x0b9040, 0x0b90e4, 0x0b9160, 0x0b9204, 0x0b9280, 0x0b9324, 0x0b93a0, 0x0b9444,
+ 0x0b94c0, 0x0b953c, 0x0b95b8, 0x0b9634, 0x0b96b0, 0x0b972c, 0x0b97a8, 0x0b9824,
+ 0x0b98a0, 0x0b991c, 0x0b9998, 0x0b9a14, 0x0b9a90, 0x0b9b0c, 0x0b9b88, 0x0b9c04,
+ 0x0b9c80, 0x0b9d24, 0x0b9da0, 0x0b9e44, 0x0b9ec0, 0x0b9f64, 0x0b9fe0, 0x0ba084,
+ 0x0ba100, 0x0ba1a4, 0x0ba220, 0x0ba2c4, 0x0ba340, 0x0ba3e4, 0x0ba460, 0x0ba504,
+ 0x0ba580, 0x0ba5fc, 0x0ba678, 0x0ba6f4, 0x0ba770, 0x0ba7ec, 0x0ba868, 0x0ba8e4,
+ 0x0ba960, 0x0ba9dc, 0x0baa58, 0x0baad4, 0x0bab50, 0x0babcc, 0x0bac48, 0x0bacc4,
+ 0x0bad40, 0x0bade4, 0x0bae60, 0x0baf04, 0x0baf80, 0x0bb024, 0x0bb0a0, 0x0bb144,
+ 0x0bb1c0, 0x0bb264, 0x0bb2e0, 0x0bb384, 0x0bb400, 0x0bb4a4, 0x0bb520, 0x0bb5c4,
+ 0x0bb640, 0x0bb6bc, 0x0bb738, 0x0bb7b4, 0x0bb830, 0x0bb8ac, 0x0bb928, 0x0bb9a4,
+ 0x0bba20, 0x0bba9c, 0x0bbb18, 0x0bbb94, 0x0bbc10, 0x0bbc8c, 0x0bbd08, 0x0bbd84,
+ 0x0bbe00, 0x0bbea4, 0x0bbf20, 0x0bbfc4, 0x0bc040, 0x0bc0e4, 0x0bc160, 0x0bc204,
+ 0x0bc280, 0x0bc324, 0x0bc3a0, 0x0bc444, 0x0bc4c0, 0x0bc564, 0x0bc5e0, 0x0bc684,
+ 0x0bc700, 0x0bc77c, 0x0bc7f8, 0x0bc874, 0x0bc8f0, 0x0bc96c, 0x0bc9e8, 0x0bca64,
+ 0x0bcae0, 0x0bcb5c, 0x0bcbd8, 0x0bcc54, 0x0bccd0, 0x0bcd4c, 0x0bcdc8, 0x0bce44,
+ 0x0bcec0, 0x0bcf64, 0x0bcfe0, 0x0bd084, 0x0bd100, 0x0bd1a4, 0x0bd220, 0x0bd2c4,
+ 0x0bd340, 0x0bd3e4, 0x0bd460, 0x0bd504, 0x0bd580, 0x0bd624, 0x0bd6a0, 0x0bd744,
+ 0x0bd7c0, 0x0bd83c, 0x0bd8b8, 0x0bd934, 0x0bd9b0, 0x0bda2c, 0x0bdaa8, 0x0bdb24,
+ 0x0bdba0, 0x0bdc1c, 0x0bdc98, 0x0bdd14, 0x0bdd90, 0x0bde0c, 0x0bde88, 0x0bdf04,
+ 0x0bdf80, 0x0be024, 0x0be0a0, 0x0be144, 0x0be1c0, 0x0be264, 0x0be2e0, 0x0be384,
+ 0x0be400, 0x0be4a4, 0x0be520, 0x0be5c4, 0x0be640, 0x0be6e4, 0x0be760, 0x0be804,
+ 0x0be880, 0x0be8fc, 0x0be978, 0x0be9f4, 0x0bea70, 0x0beaec, 0x0beb68, 0x0bebe4,
+ 0x0bec60, 0x0becdc, 0x0bed58, 0x0bedd4, 0x0bee50, 0x0beecc, 0x0bef48, 0x0befc4,
+ 0x0bf040, 0x0bf0e4, 0x0bf160, 0x0bf204, 0x0bf280, 0x0bf324, 0x0bf3a0, 0x0bf444,
+ 0x0bf4c0, 0x0bf564, 0x0bf5e0, 0x0bf684, 0x0bf700, 0x0bf7a4, 0x0bf820, 0x0bf8c4,
+ 0x0bf940, 0x0bf9bc, 0x0bfa38, 0x0bfab4, 0x0bfb30, 0x0bfbac, 0x0bfc28, 0x0bfca4,
+ 0x0bfd20, 0x0bfd9c, 0x0bfe18, 0x0bfe94, 0x0bff10, 0x0bff8c, 0x0c0008, 0x0c0084,
+ 0x0c0100, 0x0c01a4, 0x0c0220, 0x0c02c4, 0x0c0340, 0x0c03e4, 0x0c0460, 0x0c0504,
+ 0x0c0580, 0x0c0624, 0x0c06a0, 0x0c0744, 0x0c07c0, 0x0c0864, 0x0c08e0, 0x0c0984,
+ 0x0c0a00, 0x0c0a7c, 0x0c0af8, 0x0c0b74, 0x0c0bf0, 0x0c0c6c, 0x0c0ce8, 0x0c0d64,
+ 0x0c0de0, 0x0c0e5c, 0x0c0ed8, 0x0c0f54, 0x0c0fd0, 0x0c104c, 0x0c10c8, 0x0c1144,
+ 0x0c11c0, 0x0c1264, 0x0c12e0, 0x0c1384, 0x0c1400, 0x0c14a4, 0x0c1520, 0x0c15c4,
+ 0x0c1640, 0x0c16e4, 0x0c1760, 0x0c1804, 0x0c1880, 0x0c1924, 0x0c19a0, 0x0c1a44,
+ 0x0c1ac0, 0x0c1b3c, 0x0c1bb8, 0x0c1c34, 0x0c1cb0, 0x0c1d2c, 0x0c1da8, 0x0c1e24,
+ 0x0c1ea0, 0x0c1f1c, 0x0c1f98, 0x0c2014, 0x0c2090, 0x0c210c, 0x0c2188, 0x0c2204,
+ 0x0c2280, 0x0c2324, 0x0c23a0, 0x0c2444, 0x0c24c0, 0x0c2564, 0x0c25e0, 0x0c2684,
+ 0x0c2700, 0x0c27a4, 0x0c2820, 0x0c28c4, 0x0c2940, 0x0c29e4, 0x0c2a60, 0x0c2b04,
+ 0x0c2b80, 0x0c2bfc, 0x0c2c78, 0x0c2cf4, 0x0c2d70, 0x0c2dec, 0x0c2e68, 0x0c2ee4,
+ 0x0c2f60, 0x0c2fdc, 0x0c3058, 0x0c30d4, 0x0c3150, 0x0c31cc, 0x0c3248, 0x0c32c4,
+ 0x0c3340, 0x0c33e4, 0x0c3460, 0x0c3504, 0x0c3580, 0x0c3624, 0x0c36a0, 0x0c3744,
+ 0x0c37c0, 0x0c3864, 0x0c38e0, 0x0c3984, 0x0c3a00, 0x0c3aa4, 0x0c3b20, 0x0c3bc4,
+ 0x0c3c40, 0x0c3cbc, 0x0c3d38, 0x0c3db4, 0x0c3e30, 0x0c3eac, 0x0c3f28, 0x0c3fa4,
+ 0x0c4020, 0x0c409c, 0x0c4118, 0x0c4194, 0x0c4210, 0x0c428c, 0x0c4308, 0x0c4384,
+ 0x0c4400, 0x0c44a4, 0x0c4520, 0x0c45c4, 0x0c4640, 0x0c46e4, 0x0c4760, 0x0c4804,
+ 0x0c4880, 0x0c4924, 0x0c49a0, 0x0c4a44, 0x0c4ac0, 0x0c4b64, 0x0c4be0, 0x0c4c84,
+ 0x0c4d00, 0x0c4d7c, 0x0c4df8, 0x0c4e74, 0x0c4ef0, 0x0c4f6c, 0x0c4fe8, 0x0c5064,
+ 0x0c50e0, 0x0c515c, 0x0c51d8, 0x0c5254, 0x0c52d0, 0x0c534c, 0x0c53c8, 0x0c5444,
+ 0x0c54c0, 0x0c5564, 0x0c55e0, 0x0c5684, 0x0c5700, 0x0c57a4, 0x0c5820, 0x0c58c4,
+ 0x0c5940, 0x0c59e4, 0x0c5a60, 0x0c5b04, 0x0c5b80, 0x0c5c24, 0x0c5ca0, 0x0c5d44,
+ 0x0c5dc0, 0x0c5e3c, 0x0c5eb8, 0x0c5f34, 0x0c5fb0, 0x0c602c, 0x0c60a8, 0x0c6124,
+ 0x0c61a0, 0x0c621c, 0x0c6298, 0x0c6314, 0x0c6390, 0x0c640c, 0x0c6488, 0x0c6504,
+ 0x0c6580, 0x0c6624, 0x0c66a0, 0x0c6744, 0x0c67c0, 0x0c6864, 0x0c68e0, 0x0c6984,
+ 0x0c6a00, 0x0c6aa4, 0x0c6b20, 0x0c6bc4, 0x0c6c40, 0x0c6ce4, 0x0c6d60, 0x0c6e04,
+ 0x0c6e80, 0x0c6efc, 0x0c6f78, 0x0c6ff4, 0x0c7070, 0x0c70ec, 0x0c7168, 0x0c71e4,
+ 0x0c7260, 0x0c72dc, 0x0c7358, 0x0c73d4, 0x0c7450, 0x0c74cc, 0x0c7548, 0x0c75c4,
+ 0x0c7640, 0x0c76e4, 0x0c7760, 0x0c7804, 0x0c7880, 0x0c7924, 0x0c79a0, 0x0c7a44,
+ 0x0c7ac0, 0x0c7b64, 0x0c7be0, 0x0c7c84, 0x0c7d00, 0x0c7da4, 0x0c7e20, 0x0c7ec4,
+ 0x0c7f40, 0x0c7fbc, 0x0c8038, 0x0c80b4, 0x0c8130, 0x0c81ac, 0x0c8228, 0x0c82a4,
+ 0x0c8320, 0x0c839c, 0x0c8418, 0x0c8494, 0x0c8510, 0x0c858c, 0x0c8608, 0x0c8684,
+ 0x0c8700, 0x0c87a4, 0x0c8820, 0x0c88c4, 0x0c8940, 0x0c89e4, 0x0c8a60, 0x0c8b04,
+ 0x0c8b80, 0x0c8c24, 0x0c8ca0, 0x0c8d44, 0x0c8dc0, 0x0c8e64, 0x0c8ee0, 0x0c8f84,
+
+
+ 0x0c9000, 0x0c907c, 0x0c90f8, 0x0c9174, 0x0c91f0, 0x0c926c, 0x0c92e8, 0x0c9364,
+ 0x0c93e0, 0x0c945c, 0x0c94d8, 0x0c9554, 0x0c95d0, 0x0c964c, 0x0c96c8, 0x0c9744,
+ 0x0c97c0, 0x0c983c, 0x0c98b8, 0x0c9934, 0x0c99b0, 0x0c9a2c, 0x0c9aa8, 0x0c9b24,
+ 0x0c9ba0, 0x0c9c1c, 0x0c9c98, 0x0c9d14, 0x0c9d90, 0x0c9e0c, 0x0c9e88, 0x0c9f04,
+ 0x0c9f80, 0x0c9ffc, 0x0ca078, 0x0ca0f4, 0x0ca170, 0x0ca1ec, 0x0ca268, 0x0ca2e4,
+ 0x0ca360, 0x0ca3dc, 0x0ca458, 0x0ca4d4, 0x0ca550, 0x0ca5cc, 0x0ca648, 0x0ca6c4,
+ 0x0ca740, 0x0ca7bc, 0x0ca838, 0x0ca8b4, 0x0ca930, 0x0ca9ac, 0x0caa28, 0x0caaa4,
+ 0x0cab20, 0x0cab9c, 0x0cac18, 0x0cac94, 0x0cad10, 0x0cad8c, 0x0cae08, 0x0cae84,
+ 0x0caf00, 0x0caf7c, 0x0caff8, 0x0cb074, 0x0cb0f0, 0x0cb16c, 0x0cb1e8, 0x0cb264,
+ 0x0cb2e0, 0x0cb35c, 0x0cb3d8, 0x0cb454, 0x0cb4d0, 0x0cb54c, 0x0cb5c8, 0x0cb644,
+ 0x0cb6c0, 0x0cb73c, 0x0cb7b8, 0x0cb834, 0x0cb8b0, 0x0cb92c, 0x0cb9a8, 0x0cba24,
+ 0x0cbaa0, 0x0cbb1c, 0x0cbb98, 0x0cbc14, 0x0cbc90, 0x0cbd0c, 0x0cbd88, 0x0cbe04,
+ 0x0cbe80, 0x0cbefc, 0x0cbf78, 0x0cbff4, 0x0cc070, 0x0cc0ec, 0x0cc168, 0x0cc1e4,
+ 0x0cc260, 0x0cc2dc, 0x0cc358, 0x0cc3d4, 0x0cc450, 0x0cc4cc, 0x0cc548, 0x0cc5c4,
+ 0x0cc640, 0x0cc6bc, 0x0cc738, 0x0cc7b4, 0x0cc830, 0x0cc8ac, 0x0cc928, 0x0cc9a4,
+ 0x0cca20, 0x0cca9c, 0x0ccb18, 0x0ccb94, 0x0ccc10, 0x0ccc8c, 0x0ccd08, 0x0ccd84,
+
+ 0x0cce00, 0x0cce7c, 0x0ccef8, 0x0ccf9c, 0x0cd040, 0x0cd0bc, 0x0cd138, 0x0cd1dc,
+ 0x0cd280, 0x0cd2fc, 0x0cd378, 0x0cd41c, 0x0cd4c0, 0x0cd53c, 0x0cd5b8, 0x0cd65c,
+ 0x0cd700, 0x0cd77c, 0x0cd7f8, 0x0cd89c, 0x0cd940, 0x0cd9bc, 0x0cda38, 0x0cdadc,
+ 0x0cdb80, 0x0cdbfc, 0x0cdc78, 0x0cdd1c, 0x0cddc0, 0x0cde3c, 0x0cdeb8, 0x0cdf5c,
+ 0x0ce000, 0x0ce07c, 0x0ce0f8, 0x0ce19c, 0x0ce240, 0x0ce2bc, 0x0ce338, 0x0ce3dc,
+ 0x0ce480, 0x0ce4fc, 0x0ce578, 0x0ce61c, 0x0ce6c0, 0x0ce73c, 0x0ce7b8, 0x0ce85c,
+ 0x0ce900, 0x0ce97c, 0x0ce9f8, 0x0cea9c, 0x0ceb40, 0x0cebbc, 0x0cec38, 0x0cecdc,
+ 0x0ced80, 0x0cedfc, 0x0cee78, 0x0cef1c, 0x0cefc0, 0x0cf03c, 0x0cf0b8, 0x0cf15c,
+ 0x0cf200, 0x0cf27c, 0x0cf2f8, 0x0cf39c, 0x0cf440, 0x0cf4bc, 0x0cf538, 0x0cf5dc,
+ 0x0cf680, 0x0cf6fc, 0x0cf778, 0x0cf81c, 0x0cf8c0, 0x0cf93c, 0x0cf9b8, 0x0cfa5c,
+ 0x0cfb00, 0x0cfb7c, 0x0cfbf8, 0x0cfc9c, 0x0cfd40, 0x0cfdbc, 0x0cfe38, 0x0cfedc,
+ 0x0cff80, 0x0cfffc, 0x0d0078, 0x0d011c, 0x0d01c0, 0x0d023c, 0x0d02b8, 0x0d035c,
+ 0x0d0400, 0x0d047c, 0x0d04f8, 0x0d059c, 0x0d0640, 0x0d06bc, 0x0d0738, 0x0d07dc,
+ 0x0d0880, 0x0d08fc, 0x0d0978, 0x0d0a1c, 0x0d0ac0, 0x0d0b3c, 0x0d0bb8, 0x0d0c5c,
+ 0x0d0d00, 0x0d0d7c, 0x0d0df8, 0x0d0e9c, 0x0d0f40, 0x0d0fbc, 0x0d1038, 0x0d10dc,
+ 0x0d1180, 0x0d11fc, 0x0d1278, 0x0d131c, 0x0d13c0, 0x0d143c, 0x0d14b8, 0x0d155c,
+
+ 0x0d1600, 0x0d167c, 0x0d16f8, 0x0d1774, 0x0d17f0, 0x0d186c, 0x0d18e8, 0x0d1964,
+ 0x0d19e0, 0x0d1a5c, 0x0d1ad8, 0x0d1b54, 0x0d1bd0, 0x0d1c4c, 0x0d1cc8, 0x0d1d44,
+ 0x0d1dc0, 0x0d1e3c, 0x0d1eb8, 0x0d1f34, 0x0d1fb0, 0x0d202c, 0x0d20a8, 0x0d2124,
+ 0x0d21a0, 0x0d221c, 0x0d2298, 0x0d2314, 0x0d2390, 0x0d240c, 0x0d2488, 0x0d2504,
+ 0x0d2580, 0x0d25fc, 0x0d2678, 0x0d26f4, 0x0d2770, 0x0d27ec, 0x0d2868, 0x0d28e4,
+ 0x0d2960, 0x0d29dc, 0x0d2a58, 0x0d2ad4, 0x0d2b50, 0x0d2bcc, 0x0d2c48, 0x0d2cc4,
+ 0x0d2d40, 0x0d2dbc, 0x0d2e38, 0x0d2eb4, 0x0d2f30, 0x0d2fac, 0x0d3028, 0x0d30a4,
+ 0x0d3120, 0x0d319c, 0x0d3218, 0x0d3294, 0x0d3310, 0x0d338c, 0x0d3408, 0x0d3484,
+ 0x0d3500, 0x0d357c, 0x0d35f8, 0x0d3674, 0x0d36f0, 0x0d376c, 0x0d37e8, 0x0d3864,
+ 0x0d38e0, 0x0d395c, 0x0d39d8, 0x0d3a54, 0x0d3ad0, 0x0d3b4c, 0x0d3bc8, 0x0d3c44,
+ 0x0d3cc0, 0x0d3d3c, 0x0d3db8, 0x0d3e34, 0x0d3eb0, 0x0d3f2c, 0x0d3fa8, 0x0d4024,
+ 0x0d40a0, 0x0d411c, 0x0d4198, 0x0d4214, 0x0d4290, 0x0d430c, 0x0d4388, 0x0d4404,
+ 0x0d4480, 0x0d44fc, 0x0d4578, 0x0d45f4, 0x0d4670, 0x0d46ec, 0x0d4768, 0x0d47e4,
+ 0x0d4860, 0x0d48dc, 0x0d4958, 0x0d49d4, 0x0d4a50, 0x0d4acc, 0x0d4b48, 0x0d4bc4,
+ 0x0d4c40, 0x0d4cbc, 0x0d4d38, 0x0d4db4, 0x0d4e30, 0x0d4eac, 0x0d4f28, 0x0d4fa4,
+ 0x0d5020, 0x0d509c, 0x0d5118, 0x0d5194, 0x0d5210, 0x0d528c, 0x0d5308, 0x0d5384,
+
+ 0x0d5400, 0x0d547c, 0x0d54f8, 0x0d559c, 0x0d5640, 0x0d56bc, 0x0d5738, 0x0d57dc,
+ 0x0d5880, 0x0d58fc, 0x0d5978, 0x0d5a1c, 0x0d5ac0, 0x0d5b3c, 0x0d5bb8, 0x0d5c5c,
+ 0x0d5d00, 0x0d5d7c, 0x0d5df8, 0x0d5e9c, 0x0d5f40, 0x0d5fbc, 0x0d6038, 0x0d60dc,
+ 0x0d6180, 0x0d61fc, 0x0d6278, 0x0d631c, 0x0d63c0, 0x0d643c, 0x0d64b8, 0x0d655c,
+ 0x0d6600, 0x0d667c, 0x0d66f8, 0x0d679c, 0x0d6840, 0x0d68bc, 0x0d6938, 0x0d69dc,
+ 0x0d6a80, 0x0d6afc, 0x0d6b78, 0x0d6c1c, 0x0d6cc0, 0x0d6d3c, 0x0d6db8, 0x0d6e5c,
+ 0x0d6f00, 0x0d6f7c, 0x0d6ff8, 0x0d709c, 0x0d7140, 0x0d71bc, 0x0d7238, 0x0d72dc,
+ 0x0d7380, 0x0d73fc, 0x0d7478, 0x0d751c, 0x0d75c0, 0x0d763c, 0x0d76b8, 0x0d775c,
+ 0x0d7800, 0x0d787c, 0x0d78f8, 0x0d799c, 0x0d7a40, 0x0d7abc, 0x0d7b38, 0x0d7bdc,
+ 0x0d7c80, 0x0d7cfc, 0x0d7d78, 0x0d7e1c, 0x0d7ec0, 0x0d7f3c, 0x0d7fb8, 0x0d805c,
+ 0x0d8100, 0x0d817c, 0x0d81f8, 0x0d829c, 0x0d8340, 0x0d83bc, 0x0d8438, 0x0d84dc,
+ 0x0d8580, 0x0d85fc, 0x0d8678, 0x0d871c, 0x0d87c0, 0x0d883c, 0x0d88b8, 0x0d895c,
+ 0x0d8a00, 0x0d8a7c, 0x0d8af8, 0x0d8b9c, 0x0d8c40, 0x0d8cbc, 0x0d8d38, 0x0d8ddc,
+ 0x0d8e80, 0x0d8efc, 0x0d8f78, 0x0d901c, 0x0d90c0, 0x0d913c, 0x0d91b8, 0x0d925c,
+ 0x0d9300, 0x0d937c, 0x0d93f8, 0x0d949c, 0x0d9540, 0x0d95bc, 0x0d9638, 0x0d96dc,
+ 0x0d9780, 0x0d97fc, 0x0d9878, 0x0d991c, 0x0d99c0, 0x0d9a3c, 0x0d9ab8, 0x0d9b5c,
+
+ 0x0d9c00, 0x0d9c7c, 0x0d9cf8, 0x0d9d74, 0x0d9df0, 0x0d9e6c, 0x0d9ee8, 0x0d9f64,
+ 0x0d9fe0, 0x0da05c, 0x0da0d8, 0x0da154, 0x0da1d0, 0x0da24c, 0x0da2c8, 0x0da344,
+ 0x0da3c0, 0x0da43c, 0x0da4b8, 0x0da534, 0x0da5b0, 0x0da62c, 0x0da6a8, 0x0da724,
+ 0x0da7a0, 0x0da81c, 0x0da898, 0x0da914, 0x0da990, 0x0daa0c, 0x0daa88, 0x0dab04,
+ 0x0dab80, 0x0dabfc, 0x0dac78, 0x0dacf4, 0x0dad70, 0x0dadec, 0x0dae68, 0x0daee4,
+ 0x0daf60, 0x0dafdc, 0x0db058, 0x0db0d4, 0x0db150, 0x0db1cc, 0x0db248, 0x0db2c4,
+ 0x0db340, 0x0db3bc, 0x0db438, 0x0db4b4, 0x0db530, 0x0db5ac, 0x0db628, 0x0db6a4,
+ 0x0db720, 0x0db79c, 0x0db818, 0x0db894, 0x0db910, 0x0db98c, 0x0dba08, 0x0dba84,
+ 0x0dbb00, 0x0dbb7c, 0x0dbbf8, 0x0dbc74, 0x0dbcf0, 0x0dbd6c, 0x0dbde8, 0x0dbe64,
+ 0x0dbee0, 0x0dbf5c, 0x0dbfd8, 0x0dc054, 0x0dc0d0, 0x0dc14c, 0x0dc1c8, 0x0dc244,
+ 0x0dc2c0, 0x0dc33c, 0x0dc3b8, 0x0dc434, 0x0dc4b0, 0x0dc52c, 0x0dc5a8, 0x0dc624,
+ 0x0dc6a0, 0x0dc71c, 0x0dc798, 0x0dc814, 0x0dc890, 0x0dc90c, 0x0dc988, 0x0dca04,
+ 0x0dca80, 0x0dcafc, 0x0dcb78, 0x0dcbf4, 0x0dcc70, 0x0dccec, 0x0dcd68, 0x0dcde4,
+ 0x0dce60, 0x0dcedc, 0x0dcf58, 0x0dcfd4, 0x0dd050, 0x0dd0cc, 0x0dd148, 0x0dd1c4,
+ 0x0dd240, 0x0dd2bc, 0x0dd338, 0x0dd3b4, 0x0dd430, 0x0dd4ac, 0x0dd528, 0x0dd5a4,
+ 0x0dd620, 0x0dd69c, 0x0dd718, 0x0dd794, 0x0dd810, 0x0dd88c, 0x0dd908, 0x0dd984,
+
+ 0x0dda00, 0x0dda7c, 0x0ddaf8, 0x0ddb9c, 0x0ddc40, 0x0ddcbc, 0x0ddd38, 0x0ddddc,
+ 0x0dde80, 0x0ddefc, 0x0ddf78, 0x0de01c, 0x0de0c0, 0x0de13c, 0x0de1b8, 0x0de25c,
+ 0x0de300, 0x0de37c, 0x0de3f8, 0x0de49c, 0x0de540, 0x0de5bc, 0x0de638, 0x0de6dc,
+ 0x0de780, 0x0de7fc, 0x0de878, 0x0de91c, 0x0de9c0, 0x0dea3c, 0x0deab8, 0x0deb5c,
+ 0x0dec00, 0x0dec7c, 0x0decf8, 0x0ded9c, 0x0dee40, 0x0deebc, 0x0def38, 0x0defdc,
+ 0x0df080, 0x0df0fc, 0x0df178, 0x0df21c, 0x0df2c0, 0x0df33c, 0x0df3b8, 0x0df45c,
+ 0x0df500, 0x0df57c, 0x0df5f8, 0x0df69c, 0x0df740, 0x0df7bc, 0x0df838, 0x0df8dc,
+ 0x0df980, 0x0df9fc, 0x0dfa78, 0x0dfb1c, 0x0dfbc0, 0x0dfc3c, 0x0dfcb8, 0x0dfd5c,
+ 0x0dfe00, 0x0dfe7c, 0x0dfef8, 0x0dff9c, 0x0e0040, 0x0e00bc, 0x0e0138, 0x0e01dc,
+ 0x0e0280, 0x0e02fc, 0x0e0378, 0x0e041c, 0x0e04c0, 0x0e053c, 0x0e05b8, 0x0e065c,
+ 0x0e0700, 0x0e077c, 0x0e07f8, 0x0e089c, 0x0e0940, 0x0e09bc, 0x0e0a38, 0x0e0adc,
+ 0x0e0b80, 0x0e0bfc, 0x0e0c78, 0x0e0d1c, 0x0e0dc0, 0x0e0e3c, 0x0e0eb8, 0x0e0f5c,
+ 0x0e1000, 0x0e107c, 0x0e10f8, 0x0e119c, 0x0e1240, 0x0e12bc, 0x0e1338, 0x0e13dc,
+ 0x0e1480, 0x0e14fc, 0x0e1578, 0x0e161c, 0x0e16c0, 0x0e173c, 0x0e17b8, 0x0e185c,
+ 0x0e1900, 0x0e197c, 0x0e19f8, 0x0e1a9c, 0x0e1b40, 0x0e1bbc, 0x0e1c38, 0x0e1cdc,
+ 0x0e1d80, 0x0e1dfc, 0x0e1e78, 0x0e1f1c, 0x0e1fc0, 0x0e203c, 0x0e20b8, 0x0e215c,
+
+ 0x0e2200, 0x0e227c, 0x0e22f8, 0x0e2374, 0x0e23f0, 0x0e246c, 0x0e24e8, 0x0e2564,
+ 0x0e25e0, 0x0e265c, 0x0e26d8, 0x0e2754, 0x0e27d0, 0x0e284c, 0x0e28c8, 0x0e2944,
+ 0x0e29c0, 0x0e2a3c, 0x0e2ab8, 0x0e2b34, 0x0e2bb0, 0x0e2c2c, 0x0e2ca8, 0x0e2d24,
+ 0x0e2da0, 0x0e2e1c, 0x0e2e98, 0x0e2f14, 0x0e2f90, 0x0e300c, 0x0e3088, 0x0e3104,
+ 0x0e3180, 0x0e31fc, 0x0e3278, 0x0e32f4, 0x0e3370, 0x0e33ec, 0x0e3468, 0x0e34e4,
+ 0x0e3560, 0x0e35dc, 0x0e3658, 0x0e36d4, 0x0e3750, 0x0e37cc, 0x0e3848, 0x0e38c4,
+ 0x0e3940, 0x0e39bc, 0x0e3a38, 0x0e3ab4, 0x0e3b30, 0x0e3bac, 0x0e3c28, 0x0e3ca4,
+ 0x0e3d20, 0x0e3d9c, 0x0e3e18, 0x0e3e94, 0x0e3f10, 0x0e3f8c, 0x0e4008, 0x0e4084,
+ 0x0e4100, 0x0e417c, 0x0e41f8, 0x0e4274, 0x0e42f0, 0x0e436c, 0x0e43e8, 0x0e4464,
+ 0x0e44e0, 0x0e455c, 0x0e45d8, 0x0e4654, 0x0e46d0, 0x0e474c, 0x0e47c8, 0x0e4844,
+ 0x0e48c0, 0x0e493c, 0x0e49b8, 0x0e4a34, 0x0e4ab0, 0x0e4b2c, 0x0e4ba8, 0x0e4c24,
+ 0x0e4ca0, 0x0e4d1c, 0x0e4d98, 0x0e4e14, 0x0e4e90, 0x0e4f0c, 0x0e4f88, 0x0e5004,
+ 0x0e5080, 0x0e50fc, 0x0e5178, 0x0e51f4, 0x0e5270, 0x0e52ec, 0x0e5368, 0x0e53e4,
+ 0x0e5460, 0x0e54dc, 0x0e5558, 0x0e55d4, 0x0e5650, 0x0e56cc, 0x0e5748, 0x0e57c4,
+ 0x0e5840, 0x0e58bc, 0x0e5938, 0x0e59b4, 0x0e5a30, 0x0e5aac, 0x0e5b28, 0x0e5ba4,
+ 0x0e5c20, 0x0e5c9c, 0x0e5d18, 0x0e5d94, 0x0e5e10, 0x0e5e8c, 0x0e5f08, 0x0e5f84,
+
+ 0x0e6000, 0x0e607c, 0x0e60f8, 0x0e619c, 0x0e6240, 0x0e62bc, 0x0e6338, 0x0e63dc,
+ 0x0e6480, 0x0e64fc, 0x0e6578, 0x0e661c, 0x0e66c0, 0x0e673c, 0x0e67b8, 0x0e685c,
+ 0x0e6900, 0x0e697c, 0x0e69f8, 0x0e6a9c, 0x0e6b40, 0x0e6bbc, 0x0e6c38, 0x0e6cdc,
+ 0x0e6d80, 0x0e6dfc, 0x0e6e78, 0x0e6f1c, 0x0e6fc0, 0x0e703c, 0x0e70b8, 0x0e715c,
+ 0x0e7200, 0x0e727c, 0x0e72f8, 0x0e739c, 0x0e7440, 0x0e74bc, 0x0e7538, 0x0e75dc,
+ 0x0e7680, 0x0e76fc, 0x0e7778, 0x0e781c, 0x0e78c0, 0x0e793c, 0x0e79b8, 0x0e7a5c,
+ 0x0e7b00, 0x0e7b7c, 0x0e7bf8, 0x0e7c9c, 0x0e7d40, 0x0e7dbc, 0x0e7e38, 0x0e7edc,
+ 0x0e7f80, 0x0e7ffc, 0x0e8078, 0x0e811c, 0x0e81c0, 0x0e823c, 0x0e82b8, 0x0e835c,
+ 0x0e8400, 0x0e847c, 0x0e84f8, 0x0e859c, 0x0e8640, 0x0e86bc, 0x0e8738, 0x0e87dc,
+ 0x0e8880, 0x0e88fc, 0x0e8978, 0x0e8a1c, 0x0e8ac0, 0x0e8b3c, 0x0e8bb8, 0x0e8c5c,
+ 0x0e8d00, 0x0e8d7c, 0x0e8df8, 0x0e8e9c, 0x0e8f40, 0x0e8fbc, 0x0e9038, 0x0e90dc,
+ 0x0e9180, 0x0e91fc, 0x0e9278, 0x0e931c, 0x0e93c0, 0x0e943c, 0x0e94b8, 0x0e955c,
+ 0x0e9600, 0x0e967c, 0x0e96f8, 0x0e979c, 0x0e9840, 0x0e98bc, 0x0e9938, 0x0e99dc,
+ 0x0e9a80, 0x0e9afc, 0x0e9b78, 0x0e9c1c, 0x0e9cc0, 0x0e9d3c, 0x0e9db8, 0x0e9e5c,
+ 0x0e9f00, 0x0e9f7c, 0x0e9ff8, 0x0ea09c, 0x0ea140, 0x0ea1bc, 0x0ea238, 0x0ea2dc,
+ 0x0ea380, 0x0ea3fc, 0x0ea478, 0x0ea51c, 0x0ea5c0, 0x0ea63c, 0x0ea6b8, 0x0ea75c,
+
+ 0x0ea800, 0x0ea87c, 0x0ea8f8, 0x0ea974, 0x0ea9f0, 0x0eaa6c, 0x0eaae8, 0x0eab64,
+ 0x0eabe0, 0x0eac5c, 0x0eacd8, 0x0ead54, 0x0eadd0, 0x0eae4c, 0x0eaec8, 0x0eaf44,
+ 0x0eafc0, 0x0eb03c, 0x0eb0b8, 0x0eb134, 0x0eb1b0, 0x0eb22c, 0x0eb2a8, 0x0eb324,
+ 0x0eb3a0, 0x0eb41c, 0x0eb498, 0x0eb514, 0x0eb590, 0x0eb60c, 0x0eb688, 0x0eb704,
+ 0x0eb780, 0x0eb7fc, 0x0eb878, 0x0eb8f4, 0x0eb970, 0x0eb9ec, 0x0eba68, 0x0ebae4,
+ 0x0ebb60, 0x0ebbdc, 0x0ebc58, 0x0ebcd4, 0x0ebd50, 0x0ebdcc, 0x0ebe48, 0x0ebec4,
+
+ 0x0ebf40, 0x0ebfe4, 0x0ec088, 0x0ec12c, 0x0ec1d0, 0x0ec274, 0x0ec318, 0x0ec3bc,
+ 0x0ec460, 0x0ec504, 0x0ec5a8, 0x0ec64c, 0x0ec6f0, 0x0ec794, 0x0ec838, 0x0ec8dc,
+
+ 0x0ec980, 0x0ec9fc, 0x0eca78, 0x0ecaf4, 0x0ecb70, 0x0ecbec, 0x0ecc68, 0x0ecce4,
+ 0x0ecd60, 0x0ecddc, 0x0ece58, 0x0eced4, 0x0ecf50, 0x0ecfcc, 0x0ed048, 0x0ed0c4,
+ 0x0ed140, 0x0ed1bc, 0x0ed238, 0x0ed2b4, 0x0ed330, 0x0ed3ac, 0x0ed428, 0x0ed4a4,
+ 0x0ed520, 0x0ed59c, 0x0ed618, 0x0ed694, 0x0ed710, 0x0ed78c, 0x0ed808, 0x0ed884,
+ 0x0ed900, 0x0ed97c, 0x0ed9f8, 0x0eda74, 0x0edaf0, 0x0edb6c, 0x0edbe8, 0x0edc64,
+ 0x0edce0, 0x0edd5c, 0x0eddd8, 0x0ede54, 0x0eded0, 0x0edf4c, 0x0edfc8, 0x0ee044,
+
+ 0x0ee0c0, 0x0ee164, 0x0ee208, 0x0ee2ac, 0x0ee350, 0x0ee3f4, 0x0ee498, 0x0ee53c,
+ 0x0ee5e0, 0x0ee684, 0x0ee728, 0x0ee7cc, 0x0ee870, 0x0ee914, 0x0ee9b8, 0x0eea5c,
+
+ 0x0eeb00, 0x0eeb7c, 0x0eebf8, 0x0eec74, 0x0eecf0, 0x0eed6c, 0x0eede8, 0x0eee64,
+ 0x0eeee0, 0x0eef5c, 0x0eefd8, 0x0ef054, 0x0ef0d0, 0x0ef14c, 0x0ef1c8, 0x0ef244,
+ 0x0ef2c0, 0x0ef33c, 0x0ef3b8, 0x0ef434, 0x0ef4b0, 0x0ef52c, 0x0ef5a8, 0x0ef624,
+ 0x0ef6a0, 0x0ef71c, 0x0ef798, 0x0ef814, 0x0ef890, 0x0ef90c, 0x0ef988, 0x0efa04,
+ 0x0efa80, 0x0efafc, 0x0efb78, 0x0efbf4, 0x0efc70, 0x0efcec, 0x0efd68, 0x0efde4,
+ 0x0efe60, 0x0efedc, 0x0eff58, 0x0effd4, 0x0f0050, 0x0f00cc, 0x0f0148, 0x0f01c4,
+
+ 0x0f0240, 0x0f02e4, 0x0f0388, 0x0f042c, 0x0f04d0, 0x0f0574, 0x0f0618, 0x0f06bc,
+ 0x0f0760, 0x0f0804, 0x0f08a8, 0x0f094c, 0x0f09f0, 0x0f0a94, 0x0f0b38, 0x0f0bdc,
+
+ 0x0f0c80, 0x0f0cfc, 0x0f0d78, 0x0f0df4, 0x0f0e70, 0x0f0eec, 0x0f0f68, 0x0f0fe4,
+ 0x0f1060, 0x0f10dc, 0x0f1158, 0x0f11d4, 0x0f1250, 0x0f12cc, 0x0f1348, 0x0f13c4,
+ 0x0f1440, 0x0f14bc, 0x0f1538, 0x0f15b4, 0x0f1630, 0x0f16ac, 0x0f1728, 0x0f17a4,
+ 0x0f1820, 0x0f189c, 0x0f1918, 0x0f1994, 0x0f1a10, 0x0f1a8c, 0x0f1b08, 0x0f1b84,
+ 0x0f1c00, 0x0f1c7c, 0x0f1cf8, 0x0f1d74, 0x0f1df0, 0x0f1e6c, 0x0f1ee8, 0x0f1f64,
+ 0x0f1fe0, 0x0f205c, 0x0f20d8, 0x0f2154, 0x0f21d0, 0x0f224c, 0x0f22c8, 0x0f2344,
+
+ 0x0f23c0, 0x0f2464, 0x0f2508, 0x0f25ac, 0x0f2650, 0x0f26f4, 0x0f2798, 0x0f283c,
+ 0x0f28e0, 0x0f2984, 0x0f2a28, 0x0f2acc, 0x0f2b70, 0x0f2c14, 0x0f2cb8, 0x0f2d5c,
+
+ 0x0f2e00, 0x0f2e7c, 0x0f2ef8, 0x0f2f74, 0x0f2ff0, 0x0f306c, 0x0f30e8, 0x0f3164,
+ 0x0f31e0, 0x0f325c, 0x0f32d8, 0x0f3354, 0x0f33d0, 0x0f344c, 0x0f34c8, 0x0f3544,
+ 0x0f35c0, 0x0f363c, 0x0f36b8, 0x0f3734, 0x0f37b0, 0x0f382c, 0x0f38a8, 0x0f3924,
+ 0x0f39a0, 0x0f3a1c, 0x0f3a98, 0x0f3b14, 0x0f3b90, 0x0f3c0c, 0x0f3c88, 0x0f3d04,
+ 0x0f3d80, 0x0f3dfc, 0x0f3e78, 0x0f3ef4, 0x0f3f70, 0x0f3fec, 0x0f4068, 0x0f40e4,
+ 0x0f4160, 0x0f41dc, 0x0f4258, 0x0f42d4, 0x0f4350, 0x0f43cc, 0x0f4448, 0x0f44c4,
+
+ 0x0f4540, 0x0f45e4, 0x0f4688, 0x0f472c, 0x0f47d0, 0x0f4874, 0x0f4918, 0x0f49bc,
+ 0x0f4a60, 0x0f4b04, 0x0f4ba8, 0x0f4c4c, 0x0f4cf0, 0x0f4d94, 0x0f4e38, 0x0f4edc,
+
+ 0x0f4f80, 0x0f4ffc, 0x0f5078, 0x0f50f4, 0x0f5170, 0x0f51ec, 0x0f5268, 0x0f52e4,
+ 0x0f5360, 0x0f53dc, 0x0f5458, 0x0f54d4, 0x0f5550, 0x0f55cc, 0x0f5648, 0x0f56c4,
+ 0x0f5740, 0x0f57bc, 0x0f5838, 0x0f58b4, 0x0f5930, 0x0f59ac, 0x0f5a28, 0x0f5aa4,
+ 0x0f5b20, 0x0f5b9c, 0x0f5c18, 0x0f5c94, 0x0f5d10, 0x0f5d8c, 0x0f5e08, 0x0f5e84,
+ 0x0f5f00, 0x0f5f7c, 0x0f5ff8, 0x0f6074, 0x0f60f0, 0x0f616c, 0x0f61e8, 0x0f6264,
+ 0x0f62e0, 0x0f635c, 0x0f63d8, 0x0f6454, 0x0f64d0, 0x0f654c, 0x0f65c8, 0x0f6644,
+
+ 0x0f66c0, 0x0f6764, 0x0f6808, 0x0f68ac, 0x0f6950, 0x0f69f4, 0x0f6a98, 0x0f6b3c,
+ 0x0f6be0, 0x0f6c84, 0x0f6d28, 0x0f6dcc, 0x0f6e70, 0x0f6f14, 0x0f6fb8, 0x0f705c,
+
+ 0x0f7100, 0x0f717c, 0x0f71f8, 0x0f7274, 0x0f72f0, 0x0f736c, 0x0f73e8, 0x0f7464,
+ 0x0f74e0, 0x0f755c, 0x0f75d8, 0x0f7654, 0x0f76d0, 0x0f774c, 0x0f77c8, 0x0f7844,
+ 0x0f78c0, 0x0f793c, 0x0f79b8, 0x0f7a34, 0x0f7ab0, 0x0f7b2c, 0x0f7ba8, 0x0f7c24,
+ 0x0f7ca0, 0x0f7d1c, 0x0f7d98, 0x0f7e14, 0x0f7e90, 0x0f7f0c, 0x0f7f88, 0x0f8004,
+ 0x0f8080, 0x0f80fc, 0x0f8178, 0x0f81f4, 0x0f8270, 0x0f82ec, 0x0f8368, 0x0f83e4,
+ 0x0f8460, 0x0f84dc, 0x0f8558, 0x0f85d4, 0x0f8650, 0x0f86cc, 0x0f8748, 0x0f87c4,
+
+ 0x0f8840, 0x0f88e4, 0x0f8988, 0x0f8a2c, 0x0f8ad0, 0x0f8b74, 0x0f8c18, 0x0f8cbc,
+ 0x0f8d60, 0x0f8e04, 0x0f8ea8, 0x0f8f4c, 0x0f8ff0, 0x0f9094, 0x0f9138, 0x0f91dc,
+
+ 0x0f9280, 0x0f92fc, 0x0f9378, 0x0f93f4, 0x0f9470, 0x0f94ec, 0x0f9568, 0x0f95e4,
+ 0x0f9660, 0x0f96dc, 0x0f9758, 0x0f97d4, 0x0f9850, 0x0f98cc, 0x0f9948, 0x0f99c4,
+ 0x0f9a40, 0x0f9abc, 0x0f9b38, 0x0f9bb4, 0x0f9c30, 0x0f9cac, 0x0f9d28, 0x0f9da4,
+ 0x0f9e20, 0x0f9e9c, 0x0f9f18, 0x0f9f94, 0x0fa010, 0x0fa08c, 0x0fa108, 0x0fa184,
+ 0x0fa200, 0x0fa27c, 0x0fa2f8, 0x0fa374, 0x0fa3f0, 0x0fa46c, 0x0fa4e8, 0x0fa564,
+ 0x0fa5e0, 0x0fa65c, 0x0fa6d8, 0x0fa754, 0x0fa7d0, 0x0fa84c, 0x0fa8c8, 0x0fa944,
+
+ 0x0fa9c0, 0x0faa64, 0x0fab08, 0x0fabac, 0x0fac50, 0x0facf4, 0x0fad98, 0x0fae3c,
+ 0x0faee0, 0x0faf84, 0x0fb028, 0x0fb0cc, 0x0fb170, 0x0fb214, 0x0fb2b8, 0x0fb35c,
+
+ 0x0fb400, 0x0fb47c, 0x0fb4f8, 0x0fb574, 0x0fb5f0, 0x0fb66c, 0x0fb6e8, 0x0fb764,
+ 0x0fb7e0, 0x0fb85c, 0x0fb8d8, 0x0fb954, 0x0fb9d0, 0x0fba4c, 0x0fbac8, 0x0fbb44,
+ 0x0fbbc0, 0x0fbc3c, 0x0fbcb8, 0x0fbd34, 0x0fbdb0, 0x0fbe2c, 0x0fbea8, 0x0fbf24,
+ 0x0fbfa0, 0x0fc01c, 0x0fc098, 0x0fc114, 0x0fc190, 0x0fc20c, 0x0fc288, 0x0fc304,
+ 0x0fc380, 0x0fc3fc, 0x0fc478, 0x0fc4f4, 0x0fc570, 0x0fc5ec, 0x0fc668, 0x0fc6e4,
+ 0x0fc760, 0x0fc7dc, 0x0fc858, 0x0fc8d4, 0x0fc950, 0x0fc9cc, 0x0fca48, 0x0fcac4,
+
+ 0x0fcb40, 0x0fcbe4, 0x0fcc88, 0x0fcd2c, 0x0fcdd0, 0x0fce74, 0x0fcf18, 0x0fcfbc,
+ 0x0fd060, 0x0fd104, 0x0fd1a8, 0x0fd24c, 0x0fd2f0, 0x0fd394, 0x0fd438, 0x0fd4dc,
+
+ 0x0fd580, 0x0fd5fc, 0x0fd678, 0x0fd6f4, 0x0fd770, 0x0fd7ec, 0x0fd868, 0x0fd8e4,
+ 0x0fd960, 0x0fd9dc, 0x0fda58, 0x0fdad4, 0x0fdb50, 0x0fdbcc, 0x0fdc48, 0x0fdcc4,
+ 0x0fdd40, 0x0fddbc, 0x0fde38, 0x0fdeb4, 0x0fdf30, 0x0fdfac, 0x0fe028, 0x0fe0a4,
+ 0x0fe120, 0x0fe19c, 0x0fe218, 0x0fe294, 0x0fe310, 0x0fe38c, 0x0fe408, 0x0fe484,
+ 0x0fe500, 0x0fe57c, 0x0fe5f8, 0x0fe674, 0x0fe6f0, 0x0fe76c, 0x0fe7e8, 0x0fe864,
+ 0x0fe8e0, 0x0fe95c, 0x0fe9d8, 0x0fea54, 0x0fead0, 0x0feb4c, 0x0febc8, 0x0fec44,
+
+ 0x0fecc0, 0x0fed64, 0x0fee08, 0x0feeac, 0x0fef50, 0x0feff4, 0x0ff098, 0x0ff13c,
+ 0x0ff1e0, 0x0ff284, 0x0ff328, 0x0ff3cc, 0x0ff470, 0x0ff514, 0x0ff5b8, 0x0ff65c,
+
+ 0x0ff700, 0x0ff77c, 0x0ff7f8, 0x0ff874, 0x0ff8f0, 0x0ff96c, 0x0ff9e8, 0x0ffa64,
+ 0x0ffae0, 0x0ffb5c, 0x0ffbd8, 0x0ffc54, 0x0ffcd0, 0x0ffd4c, 0x0ffdc8, 0x0ffe44,
+ 0x0ffec0, 0x0fff3c, 0x0fffb8, 0x100034, 0x1000b0, 0x10012c, 0x1001a8, 0x100224,
+ 0x1002a0, 0x10031c, 0x100398, 0x100414, 0x100490, 0x10050c, 0x100588, 0x100604,
+ 0x100680, 0x1006fc, 0x100778, 0x1007f4, 0x100870, 0x1008ec, 0x100968, 0x1009e4,
+ 0x100a60, 0x100adc, 0x100b58, 0x100bd4, 0x100c50, 0x100ccc, 0x100d48, 0x100dc4,
+
+ 0x100e40, 0x100ee4, 0x100f88, 0x10102c, 0x1010d0, 0x101174, 0x101218, 0x1012bc,
+ 0x101360, 0x101404, 0x1014a8, 0x10154c, 0x1015f0, 0x101694, 0x101738, 0x1017dc,
+
+ 0x101880, 0x1018fc, 0x101978, 0x1019f4, 0x101a70, 0x101aec, 0x101b68, 0x101be4,
+ 0x101c60, 0x101cdc, 0x101d58, 0x101dd4, 0x101e50, 0x101ecc, 0x101f48, 0x101fc4,
+ 0x102040, 0x1020bc, 0x102138, 0x1021b4, 0x102230, 0x1022ac, 0x102328, 0x1023a4,
+ 0x102420, 0x10249c, 0x102518, 0x102594, 0x102610, 0x10268c, 0x102708, 0x102784,
+ 0x102800, 0x10287c, 0x1028f8, 0x102974, 0x1029f0, 0x102a6c, 0x102ae8, 0x102b64,
+ 0x102be0, 0x102c5c, 0x102cd8, 0x102d54, 0x102dd0, 0x102e4c, 0x102ec8, 0x102f44,
+
+ 0x102fc0, 0x103064, 0x103108, 0x1031ac, 0x103250, 0x1032f4, 0x103398, 0x10343c,
+ 0x1034e0, 0x103584, 0x103628, 0x1036cc, 0x103770, 0x103814, 0x1038b8, 0x10395c,
+
+ 0x103a00, 0x103a7c, 0x103af8, 0x103b74, 0x103bf0, 0x103c6c, 0x103ce8, 0x103d64,
+ 0x103de0, 0x103e5c, 0x103ed8, 0x103f54, 0x103fd0, 0x10404c, 0x1040c8, 0x104144,
+ 0x1041c0, 0x10423c, 0x1042b8, 0x104334, 0x1043b0, 0x10442c, 0x1044a8, 0x104524,
+ 0x1045a0, 0x10461c, 0x104698, 0x104714, 0x104790, 0x10480c, 0x104888, 0x104904,
+ 0x104980, 0x1049fc, 0x104a78, 0x104af4, 0x104b70, 0x104bec, 0x104c68, 0x104ce4,
+ 0x104d60, 0x104ddc, 0x104e58, 0x104ed4, 0x104f50, 0x104fcc, 0x105048, 0x1050c4,
+
+ 0x105140, 0x1051e4, 0x105288, 0x10532c, 0x1053d0, 0x105474, 0x105518, 0x1055bc,
+ 0x105660, 0x105704, 0x1057a8, 0x10584c, 0x1058f0, 0x105994, 0x105a38, 0x105adc,
+
+ 0x105b80, 0x105bfc, 0x105c78, 0x105cf4, 0x105d70, 0x105dec, 0x105e68, 0x105ee4,
+ 0x105f60, 0x105fdc, 0x106058, 0x1060d4, 0x106150, 0x1061cc, 0x106248, 0x1062c4,
+ 0x106340, 0x1063bc, 0x106438, 0x1064b4, 0x106530, 0x1065ac, 0x106628, 0x1066a4,
+ 0x106720, 0x10679c, 0x106818, 0x106894, 0x106910, 0x10698c, 0x106a08, 0x106a84,
+ 0x106b00, 0x106b7c, 0x106bf8, 0x106c74, 0x106cf0, 0x106d6c, 0x106de8, 0x106e64,
+ 0x106ee0, 0x106f5c, 0x106fd8, 0x107054, 0x1070d0, 0x10714c, 0x1071c8, 0x107244,
+
+ 0x1072c0, 0x107364, 0x107408, 0x1074ac, 0x107550, 0x1075f4, 0x107698, 0x10773c,
+ 0x1077e0, 0x107884, 0x107928, 0x1079cc, 0x107a70, 0x107b14, 0x107bb8, 0x107c5c,
+
+ 0x107d00, 0x107d7c, 0x107df8, 0x107e74, 0x107ef0, 0x107f6c, 0x107fe8, 0x108064,
+ 0x1080e0, 0x10815c, 0x1081d8, 0x108254, 0x1082d0, 0x10834c, 0x1083c8, 0x108444,
+ 0x1084c0, 0x10853c, 0x1085b8, 0x108634, 0x1086b0, 0x10872c, 0x1087a8, 0x108824,
+ 0x1088a0, 0x10891c, 0x108998, 0x108a14, 0x108a90, 0x108b0c, 0x108b88, 0x108c04,
+ 0x108c80, 0x108cfc, 0x108d78, 0x108df4, 0x108e70, 0x108eec, 0x108f68, 0x108fe4,
+ 0x109060, 0x1090dc, 0x109158, 0x1091d4, 0x109250, 0x1092cc, 0x109348, 0x1093c4,
+
+ 0x109440, 0x1094e4, 0x109588, 0x10962c, 0x1096d0, 0x109774, 0x109818, 0x1098bc,
+ 0x109960, 0x109a04, 0x109aa8, 0x109b4c, 0x109bf0, 0x109c94, 0x109d38, 0x109ddc,
+
+ 0x109e80, 0x109efc, 0x109f78, 0x109ff4, 0x10a070, 0x10a0ec, 0x10a168, 0x10a1e4,
+ 0x10a260, 0x10a2dc, 0x10a358, 0x10a3d4, 0x10a450, 0x10a4cc, 0x10a548, 0x10a5c4,
+ 0x10a640, 0x10a6bc, 0x10a738, 0x10a7b4, 0x10a830, 0x10a8ac, 0x10a928, 0x10a9a4,
+ 0x10aa20, 0x10aa9c, 0x10ab18, 0x10ab94, 0x10ac10, 0x10ac8c, 0x10ad08, 0x10ad84,
+ 0x10ae00, 0x10ae7c, 0x10aef8, 0x10af74, 0x10aff0, 0x10b06c, 0x10b0e8, 0x10b164,
+ 0x10b1e0, 0x10b25c, 0x10b2d8, 0x10b354, 0x10b3d0, 0x10b44c, 0x10b4c8, 0x10b544,
+
+ 0x10b5c0, 0x10b664, 0x10b708, 0x10b7ac, 0x10b850, 0x10b8f4, 0x10b998, 0x10ba3c,
+ 0x10bae0, 0x10bb84, 0x10bc28, 0x10bccc, 0x10bd70, 0x10be14, 0x10beb8, 0x10bf5c,
+
+
+
+ 0x10c000, 0x10c07c, 0x10c0f8, 0x10c174, 0x10c1f0, 0x10c26c, 0x10c2e8, 0x10c364,
+ 0x10c3e0, 0x10c484, 0x10c500, 0x10c5a4, 0x10c620, 0x10c6c4, 0x10c740, 0x10c7e4,
+ 0x10c860, 0x10c8dc, 0x10c958, 0x10c9d4, 0x10ca50, 0x10cacc, 0x10cb48, 0x10cbc4,
+ 0x10cc40, 0x10cce4, 0x10cd60, 0x10ce04, 0x10ce80, 0x10cf24, 0x10cfa0, 0x10d044,
+ 0x10d0c0, 0x10d13c, 0x10d1b8, 0x10d234, 0x10d2b0, 0x10d32c, 0x10d3a8, 0x10d424,
+ 0x10d4a0, 0x10d544, 0x10d5c0, 0x10d664, 0x10d6e0, 0x10d784, 0x10d800, 0x10d8a4,
+ 0x10d920, 0x10d99c, 0x10da18, 0x10da94, 0x10db10, 0x10db8c, 0x10dc08, 0x10dc84,
+ 0x10dd00, 0x10dda4, 0x10de20, 0x10dec4, 0x10df40, 0x10dfe4, 0x10e060, 0x10e104,
+ 0x10e180, 0x10e1fc, 0x10e278, 0x10e2f4, 0x10e370, 0x10e3ec, 0x10e468, 0x10e4e4,
+ 0x10e560, 0x10e604, 0x10e680, 0x10e724, 0x10e7a0, 0x10e844, 0x10e8c0, 0x10e964,
+ 0x10e9e0, 0x10ea5c, 0x10ead8, 0x10eb54, 0x10ebd0, 0x10ec4c, 0x10ecc8, 0x10ed44,
+ 0x10edc0, 0x10ee64, 0x10eee0, 0x10ef84, 0x10f000, 0x10f0a4, 0x10f120, 0x10f1c4,
+ 0x10f240, 0x10f2bc, 0x10f338, 0x10f3b4, 0x10f430, 0x10f4ac, 0x10f528, 0x10f5a4,
+ 0x10f620, 0x10f6c4, 0x10f740, 0x10f7e4, 0x10f860, 0x10f904, 0x10f980, 0x10fa24,
+ 0x10faa0, 0x10fb1c, 0x10fb98, 0x10fc14, 0x10fc90, 0x10fd0c, 0x10fd88, 0x10fe04,
+ 0x10fe80, 0x10ff24, 0x10ffa0, 0x110044, 0x1100c0, 0x110164, 0x1101e0, 0x110284,
+ 0x110300, 0x11037c, 0x1103f8, 0x110474, 0x1104f0, 0x11056c, 0x1105e8, 0x110664,
+ 0x1106e0, 0x110784, 0x110800, 0x1108a4, 0x110920, 0x1109c4, 0x110a40, 0x110ae4,
+ 0x110b60, 0x110bdc, 0x110c58, 0x110cd4, 0x110d50, 0x110dcc, 0x110e48, 0x110ec4,
+ 0x110f40, 0x110fe4, 0x111060, 0x111104, 0x111180, 0x111224, 0x1112a0, 0x111344,
+ 0x1113c0, 0x11143c, 0x1114b8, 0x111534, 0x1115b0, 0x11162c, 0x1116a8, 0x111724,
+ 0x1117a0, 0x111844, 0x1118c0, 0x111964, 0x1119e0, 0x111a84, 0x111b00, 0x111ba4,
+ 0x111c20, 0x111c9c, 0x111d18, 0x111d94, 0x111e10, 0x111e8c, 0x111f08, 0x111f84,
+ 0x112000, 0x1120a4, 0x112120, 0x1121c4, 0x112240, 0x1122e4, 0x112360, 0x112404,
+ 0x112480, 0x1124fc, 0x112578, 0x1125f4, 0x112670, 0x1126ec, 0x112768, 0x1127e4,
+ 0x112860, 0x112904, 0x112980, 0x112a24, 0x112aa0, 0x112b44, 0x112bc0, 0x112c64,
+ 0x112ce0, 0x112d5c, 0x112dd8, 0x112e54, 0x112ed0, 0x112f4c, 0x112fc8, 0x113044,
+ 0x1130c0, 0x113164, 0x1131e0, 0x113284, 0x113300, 0x1133a4, 0x113420, 0x1134c4,
+ 0x113540, 0x1135bc, 0x113638, 0x1136b4, 0x113730, 0x1137ac, 0x113828, 0x1138a4,
+ 0x113920, 0x1139c4, 0x113a40, 0x113ae4, 0x113b60, 0x113c04, 0x113c80, 0x113d24,
+ 0x113da0, 0x113e1c, 0x113e98, 0x113f14, 0x113f90, 0x11400c, 0x114088, 0x114104,
+ 0x114180, 0x114224, 0x1142a0, 0x114344, 0x1143c0, 0x114464, 0x1144e0, 0x114584,
+ 0x114600, 0x11467c, 0x1146f8, 0x114774, 0x1147f0, 0x11486c, 0x1148e8, 0x114964,
+ 0x1149e0, 0x114a84, 0x114b00, 0x114ba4, 0x114c20, 0x114cc4, 0x114d40, 0x114de4,
+ 0x114e60, 0x114edc, 0x114f58, 0x114fd4, 0x115050, 0x1150cc, 0x115148, 0x1151c4,
+ 0x115240, 0x1152e4, 0x115360, 0x115404, 0x115480, 0x115524, 0x1155a0, 0x115644,
+ 0x1156c0, 0x11573c, 0x1157b8, 0x115834, 0x1158b0, 0x11592c, 0x1159a8, 0x115a24,
+ 0x115aa0, 0x115b44, 0x115bc0, 0x115c64, 0x115ce0, 0x115d84, 0x115e00, 0x115ea4,
+ 0x115f20, 0x115f9c, 0x116018, 0x116094, 0x116110, 0x11618c, 0x116208, 0x116284,
+ 0x116300, 0x1163a4, 0x116420, 0x1164c4, 0x116540, 0x1165e4, 0x116660, 0x116704,
+ 0x116780, 0x1167fc, 0x116878, 0x1168f4, 0x116970, 0x1169ec, 0x116a68, 0x116ae4,
+ 0x116b60, 0x116c04, 0x116c80, 0x116d24, 0x116da0, 0x116e44, 0x116ec0, 0x116f64,
+ 0x116fe0, 0x11705c, 0x1170d8, 0x117154, 0x1171d0, 0x11724c, 0x1172c8, 0x117344,
+ 0x1173c0, 0x117464, 0x1174e0, 0x117584, 0x117600, 0x1176a4, 0x117720, 0x1177c4,
+ 0x117840, 0x1178bc, 0x117938, 0x1179b4, 0x117a30, 0x117aac, 0x117b28, 0x117ba4,
+ 0x117c20, 0x117cc4, 0x117d40, 0x117de4, 0x117e60, 0x117f04, 0x117f80, 0x118024,
+ 0x1180a0, 0x11811c, 0x118198, 0x118214, 0x118290, 0x11830c, 0x118388, 0x118404,
+ 0x118480, 0x118524, 0x1185a0, 0x118644, 0x1186c0, 0x118764, 0x1187e0, 0x118884,
+ 0x118900, 0x11897c, 0x1189f8, 0x118a74, 0x118af0, 0x118b6c, 0x118be8, 0x118c64,
+ 0x118ce0, 0x118d84, 0x118e00, 0x118ea4, 0x118f20, 0x118fc4, 0x119040, 0x1190e4,
+ 0x119160, 0x1191dc, 0x119258, 0x1192d4, 0x119350, 0x1193cc, 0x119448, 0x1194c4,
+ 0x119540, 0x1195e4, 0x119660, 0x119704, 0x119780, 0x119824, 0x1198a0, 0x119944,
+ 0x1199c0, 0x119a3c, 0x119ab8, 0x119b34, 0x119bb0, 0x119c2c, 0x119ca8, 0x119d24,
+ 0x119da0, 0x119e44, 0x119ec0, 0x119f64, 0x119fe0, 0x11a084, 0x11a100, 0x11a1a4,
+ 0x11a220, 0x11a29c, 0x11a318, 0x11a394, 0x11a410, 0x11a48c, 0x11a508, 0x11a584,
+ 0x11a600, 0x11a6a4, 0x11a720, 0x11a7c4, 0x11a840, 0x11a8e4, 0x11a960, 0x11aa04,
+ 0x11aa80, 0x11aafc, 0x11ab78, 0x11abf4, 0x11ac70, 0x11acec, 0x11ad68, 0x11ade4,
+ 0x11ae60, 0x11af04, 0x11af80, 0x11b024, 0x11b0a0, 0x11b144, 0x11b1c0, 0x11b264,
+ 0x11b2e0, 0x11b35c, 0x11b3d8, 0x11b454, 0x11b4d0, 0x11b54c, 0x11b5c8, 0x11b644,
+ 0x11b6c0, 0x11b764, 0x11b7e0, 0x11b884, 0x11b900, 0x11b9a4, 0x11ba20, 0x11bac4,
+ 0x11bb40, 0x11bbbc, 0x11bc38, 0x11bcb4, 0x11bd30, 0x11bdac, 0x11be28, 0x11bea4,
+ 0x11bf20, 0x11bfc4, 0x11c040, 0x11c0e4, 0x11c160, 0x11c204, 0x11c280, 0x11c324,
+ 0x11c3a0, 0x11c41c, 0x11c498, 0x11c514, 0x11c590, 0x11c60c, 0x11c688, 0x11c704,
+ 0x11c780, 0x11c824, 0x11c8a0, 0x11c944, 0x11c9c0, 0x11ca64, 0x11cae0, 0x11cb84,
+ 0x11cc00, 0x11cc7c, 0x11ccf8, 0x11cd74, 0x11cdf0, 0x11ce6c, 0x11cee8, 0x11cf64,
+ 0x11cfe0, 0x11d084, 0x11d100, 0x11d1a4, 0x11d220, 0x11d2c4, 0x11d340, 0x11d3e4,
+ 0x11d460, 0x11d4dc, 0x11d558, 0x11d5d4, 0x11d650, 0x11d6cc, 0x11d748, 0x11d7c4,
+ 0x11d840, 0x11d8e4, 0x11d960, 0x11da04, 0x11da80, 0x11db24, 0x11dba0, 0x11dc44,
+ 0x11dcc0, 0x11dd3c, 0x11ddb8, 0x11de34, 0x11deb0, 0x11df2c, 0x11dfa8, 0x11e024,
+ 0x11e0a0, 0x11e144, 0x11e1c0, 0x11e264, 0x11e2e0, 0x11e384, 0x11e400, 0x11e4a4,
+ 0x11e520, 0x11e59c, 0x11e618, 0x11e694, 0x11e710, 0x11e78c, 0x11e808, 0x11e884,
+ 0x11e900, 0x11e9a4, 0x11ea20, 0x11eac4, 0x11eb40, 0x11ebe4, 0x11ec60, 0x11ed04,
+ 0x11ed80, 0x11edfc, 0x11ee78, 0x11eef4, 0x11ef70, 0x11efec, 0x11f068, 0x11f0e4,
+ 0x11f160, 0x11f204, 0x11f280, 0x11f324, 0x11f3a0, 0x11f444, 0x11f4c0, 0x11f564,
+ 0x11f5e0, 0x11f65c, 0x11f6d8, 0x11f754, 0x11f7d0, 0x11f84c, 0x11f8c8, 0x11f944,
+ 0x11f9c0, 0x11fa64, 0x11fae0, 0x11fb84, 0x11fc00, 0x11fca4, 0x11fd20, 0x11fdc4,
+ 0x11fe40, 0x11febc, 0x11ff38, 0x11ffb4, 0x120030, 0x1200ac, 0x120128, 0x1201a4,
+ 0x120220, 0x1202c4, 0x120340, 0x1203e4, 0x120460, 0x120504, 0x120580, 0x120624,
+ 0x1206a0, 0x12071c, 0x120798, 0x120814, 0x120890, 0x12090c, 0x120988, 0x120a04,
+ 0x120a80, 0x120b24, 0x120ba0, 0x120c44, 0x120cc0, 0x120d64, 0x120de0, 0x120e84,
+ 0x120f00, 0x120f7c, 0x120ff8, 0x121074, 0x1210f0, 0x12116c, 0x1211e8, 0x121264,
+ 0x1212e0, 0x121384, 0x121400, 0x1214a4, 0x121520, 0x1215c4, 0x121640, 0x1216e4,
+ 0x121760, 0x1217dc, 0x121858, 0x1218d4, 0x121950, 0x1219cc, 0x121a48, 0x121ac4,
+ 0x121b40, 0x121be4, 0x121c60, 0x121d04, 0x121d80, 0x121e24, 0x121ea0, 0x121f44,
+ 0x121fc0, 0x12203c, 0x1220b8, 0x122134, 0x1221b0, 0x12222c, 0x1222a8, 0x122324,
+ 0x1223a0, 0x122444, 0x1224c0, 0x122564, 0x1225e0, 0x122684, 0x122700, 0x1227a4,
+ 0x122820, 0x12289c, 0x122918, 0x122994, 0x122a10, 0x122a8c, 0x122b08, 0x122b84,
+ 0x122c00, 0x122ca4, 0x122d20, 0x122dc4, 0x122e40, 0x122ee4, 0x122f60, 0x123004,
+ 0x123080, 0x1230fc, 0x123178, 0x1231f4, 0x123270, 0x1232ec, 0x123368, 0x1233e4,
+ 0x123460, 0x123504, 0x123580, 0x123624, 0x1236a0, 0x123744, 0x1237c0, 0x123864,
+ 0x1238e0, 0x12395c, 0x1239d8, 0x123a54, 0x123ad0, 0x123b4c, 0x123bc8, 0x123c44,
+ 0x123cc0, 0x123d64, 0x123de0, 0x123e84, 0x123f00, 0x123fa4, 0x124020, 0x1240c4,
+ 0x124140, 0x1241bc, 0x124238, 0x1242b4, 0x124330, 0x1243ac, 0x124428, 0x1244a4,
+ 0x124520, 0x1245c4, 0x124640, 0x1246e4, 0x124760, 0x124804, 0x124880, 0x124924,
+ 0x1249a0, 0x124a1c, 0x124a98, 0x124b14, 0x124b90, 0x124c0c, 0x124c88, 0x124d04,
+ 0x124d80, 0x124e24, 0x124ea0, 0x124f44, 0x124fc0, 0x125064, 0x1250e0, 0x125184,
+ 0x125200, 0x12527c, 0x1252f8, 0x125374, 0x1253f0, 0x12546c, 0x1254e8, 0x125564,
+ 0x1255e0, 0x125684, 0x125700, 0x1257a4, 0x125820, 0x1258c4, 0x125940, 0x1259e4,
+ 0x125a60, 0x125adc, 0x125b58, 0x125bd4, 0x125c50, 0x125ccc, 0x125d48, 0x125dc4,
+ 0x125e40, 0x125ee4, 0x125f60, 0x126004, 0x126080, 0x126124, 0x1261a0, 0x126244,
+ 0x1262c0, 0x12633c, 0x1263b8, 0x126434, 0x1264b0, 0x12652c, 0x1265a8, 0x126624,
+ 0x1266a0, 0x126744, 0x1267c0, 0x126864, 0x1268e0, 0x126984, 0x126a00, 0x126aa4,
+ 0x126b20, 0x126b9c, 0x126c18, 0x126c94, 0x126d10, 0x126d8c, 0x126e08, 0x126e84,
+ 0x126f00, 0x126fa4, 0x127020, 0x1270c4, 0x127140, 0x1271e4, 0x127260, 0x127304,
+ 0x127380, 0x1273fc, 0x127478, 0x1274f4, 0x127570, 0x1275ec, 0x127668, 0x1276e4,
+ 0x127760, 0x127804, 0x127880, 0x127924, 0x1279a0, 0x127a44, 0x127ac0, 0x127b64,
+ 0x127be0, 0x127c5c, 0x127cd8, 0x127d54, 0x127dd0, 0x127e4c, 0x127ec8, 0x127f44,
+ 0x127fc0, 0x128064, 0x1280e0, 0x128184, 0x128200, 0x1282a4, 0x128320, 0x1283c4,
+ 0x128440, 0x1284bc, 0x128538, 0x1285b4, 0x128630, 0x1286ac, 0x128728, 0x1287a4,
+ 0x128820, 0x1288c4, 0x128940, 0x1289e4, 0x128a60, 0x128b04, 0x128b80, 0x128c24,
+ 0x128ca0, 0x128d1c, 0x128d98, 0x128e14, 0x128e90, 0x128f0c, 0x128f88, 0x129004,
+ 0x129080, 0x129124, 0x1291a0, 0x129244, 0x1292c0, 0x129364, 0x1293e0, 0x129484,
+ 0x129500, 0x12957c, 0x1295f8, 0x129674, 0x1296f0, 0x12976c, 0x1297e8, 0x129864,
+ 0x1298e0, 0x129984, 0x129a00, 0x129aa4, 0x129b20, 0x129bc4, 0x129c40, 0x129ce4,
+ 0x129d60, 0x129ddc, 0x129e58, 0x129ed4, 0x129f50, 0x129fcc, 0x12a048, 0x12a0c4,
+ 0x12a140, 0x12a1e4, 0x12a260, 0x12a304, 0x12a380, 0x12a424, 0x12a4a0, 0x12a544,
+ 0x12a5c0, 0x12a63c, 0x12a6b8, 0x12a734, 0x12a7b0, 0x12a82c, 0x12a8a8, 0x12a924,
+ 0x12a9a0, 0x12aa44, 0x12aac0, 0x12ab64, 0x12abe0, 0x12ac84, 0x12ad00, 0x12ada4,
+ 0x12ae20, 0x12ae9c, 0x12af18, 0x12af94, 0x12b010, 0x12b08c, 0x12b108, 0x12b184,
+ 0x12b200, 0x12b2a4, 0x12b320, 0x12b3c4, 0x12b440, 0x12b4e4, 0x12b560, 0x12b604,
+ 0x12b680, 0x12b6fc, 0x12b778, 0x12b7f4, 0x12b870, 0x12b8ec, 0x12b968, 0x12b9e4,
+ 0x12ba60, 0x12bb04, 0x12bb80, 0x12bc24, 0x12bca0, 0x12bd44, 0x12bdc0, 0x12be64,
+ 0x12bee0, 0x12bf5c, 0x12bfd8, 0x12c054, 0x12c0d0, 0x12c14c, 0x12c1c8, 0x12c244,
+ 0x12c2c0, 0x12c364, 0x12c3e0, 0x12c484, 0x12c500, 0x12c5a4, 0x12c620, 0x12c6c4,
+ 0x12c740, 0x12c7bc, 0x12c838, 0x12c8b4, 0x12c930, 0x12c9ac, 0x12ca28, 0x12caa4,
+ 0x12cb20, 0x12cbc4, 0x12cc40, 0x12cce4, 0x12cd60, 0x12ce04, 0x12ce80, 0x12cf24,
+ 0x12cfa0, 0x12d01c, 0x12d098, 0x12d114, 0x12d190, 0x12d20c, 0x12d288, 0x12d304,
+ 0x12d380, 0x12d424, 0x12d4a0, 0x12d544, 0x12d5c0, 0x12d664, 0x12d6e0, 0x12d784,
+ 0x12d800, 0x12d87c, 0x12d8f8, 0x12d974, 0x12d9f0, 0x12da6c, 0x12dae8, 0x12db64,
+ 0x12dbe0, 0x12dc5c, 0x12dcd8, 0x12dd54, 0x12ddd0, 0x12de4c, 0x12dec8, 0x12df44,
+ 0x12dfc0, 0x12e03c, 0x12e0b8, 0x12e134, 0x12e1b0, 0x12e22c, 0x12e2a8, 0x12e324,
+ 0x12e3a0, 0x12e41c, 0x12e498, 0x12e514, 0x12e590, 0x12e60c, 0x12e688, 0x12e704,
+ 0x12e780, 0x12e7fc, 0x12e878, 0x12e8f4, 0x12e970, 0x12e9ec, 0x12ea68, 0x12eae4,
+ 0x12eb60, 0x12ebdc, 0x12ec58, 0x12ecd4, 0x12ed50, 0x12edcc, 0x12ee48, 0x12eec4,
+ 0x12ef40, 0x12efbc, 0x12f038, 0x12f0b4, 0x12f130, 0x12f1ac, 0x12f228, 0x12f2a4,
+ 0x12f320, 0x12f39c, 0x12f418, 0x12f494, 0x12f510, 0x12f58c, 0x12f608, 0x12f684,
+ 0x12f700, 0x12f77c, 0x12f7f8, 0x12f874, 0x12f8f0, 0x12f96c, 0x12f9e8, 0x12fa64,
+ 0x12fae0, 0x12fb5c, 0x12fbd8, 0x12fc54, 0x12fcd0, 0x12fd4c, 0x12fdc8, 0x12fe44,
+ 0x12fec0, 0x12ff3c, 0x12ffb8, 0x130034, 0x1300b0, 0x13012c, 0x1301a8, 0x130224,
+ 0x1302a0, 0x13031c, 0x130398, 0x130414, 0x130490, 0x13050c, 0x130588, 0x130604,
+ 0x130680, 0x1306fc, 0x130778, 0x1307f4, 0x130870, 0x1308ec, 0x130968, 0x1309e4,
+ 0x130a60, 0x130adc, 0x130b58, 0x130bd4, 0x130c50, 0x130ccc, 0x130d48, 0x130dc4,
+ 0x130e40, 0x130ebc, 0x130f38, 0x130fb4, 0x131030, 0x1310ac, 0x131128, 0x1311a4,
+ 0x131220, 0x13129c, 0x131318, 0x131394, 0x131410, 0x13148c, 0x131508, 0x131584,
+ 0x131600, 0x13167c, 0x1316f8, 0x131774, 0x1317f0, 0x13186c, 0x1318e8, 0x131964,
+ 0x1319e0, 0x131a5c, 0x131ad8, 0x131b54, 0x131bd0, 0x131c4c, 0x131cc8, 0x131d44,
+ 0x131dc0, 0x131e3c, 0x131eb8, 0x131f34, 0x131fb0, 0x13202c, 0x1320a8, 0x132124,
+ 0x1321a0, 0x13221c, 0x132298, 0x132314, 0x132390, 0x13240c, 0x132488, 0x132504,
+ 0x132580, 0x1325fc, 0x132678, 0x1326f4, 0x132770, 0x1327ec, 0x132868, 0x1328e4,
+ 0x132960, 0x1329dc, 0x132a58, 0x132ad4, 0x132b50, 0x132bcc, 0x132c48, 0x132cc4,
+ 0x132d40, 0x132dbc, 0x132e38, 0x132eb4, 0x132f30, 0x132fac, 0x133028, 0x1330a4,
+ 0x133120, 0x13319c, 0x133218, 0x133294, 0x133310, 0x13338c, 0x133408, 0x133484,
+ 0x133500, 0x13357c, 0x1335f8, 0x133674, 0x1336f0, 0x13376c, 0x1337e8, 0x133864,
+ 0x1338e0, 0x13395c, 0x1339d8, 0x133a54, 0x133ad0, 0x133b4c, 0x133bc8, 0x133c44,
+ 0x133cc0, 0x133d3c, 0x133db8, 0x133e34, 0x133eb0, 0x133f2c, 0x133fa8, 0x134024,
+ 0x1340a0, 0x13411c, 0x134198, 0x134214, 0x134290, 0x13430c, 0x134388, 0x134404,
+ 0x134480, 0x1344fc, 0x134578, 0x1345f4, 0x134670, 0x1346ec, 0x134768, 0x1347e4,
+ 0x134860, 0x1348dc, 0x134958, 0x1349d4, 0x134a50, 0x134acc, 0x134b48, 0x134bc4,
+ 0x134c40, 0x134cbc, 0x134d38, 0x134db4, 0x134e30, 0x134eac, 0x134f28, 0x134fa4,
+ 0x135020, 0x13509c, 0x135118, 0x135194, 0x135210, 0x13528c, 0x135308, 0x135384,
+ 0x135400, 0x13547c, 0x1354f8, 0x135574, 0x1355f0, 0x13566c, 0x1356e8, 0x135764,
+ 0x1357e0, 0x13585c, 0x1358d8, 0x135954, 0x1359d0, 0x135a4c, 0x135ac8, 0x135b44,
+ 0x135bc0, 0x135c3c, 0x135cb8, 0x135d34, 0x135db0, 0x135e2c, 0x135ea8, 0x135f24,
+ 0x135fa0, 0x13601c, 0x136098, 0x136114, 0x136190, 0x13620c, 0x136288, 0x136304,
+ 0x136380, 0x1363fc, 0x136478, 0x1364f4, 0x136570, 0x1365ec, 0x136668, 0x1366e4,
+ 0x136760, 0x1367dc, 0x136858, 0x1368d4, 0x136950, 0x1369cc, 0x136a48, 0x136ac4,
+ 0x136b40, 0x136bbc, 0x136c38, 0x136cb4, 0x136d30, 0x136dac, 0x136e28, 0x136ea4,
+ 0x136f20, 0x136f9c, 0x137018, 0x137094, 0x137110, 0x13718c, 0x137208, 0x137284,
+ 0x137300, 0x13737c, 0x1373f8, 0x137474, 0x1374f0, 0x13756c, 0x1375e8, 0x137664,
+ 0x1376e0, 0x13775c, 0x1377d8, 0x137854, 0x1378d0, 0x13794c, 0x1379c8, 0x137a44,
+ 0x137ac0, 0x137b3c, 0x137bb8, 0x137c34, 0x137cb0, 0x137d2c, 0x137da8, 0x137e24,
+ 0x137ea0, 0x137f1c, 0x137f98, 0x138014, 0x138090, 0x13810c, 0x138188, 0x138204,
+ 0x138280, 0x1382fc, 0x138378, 0x1383f4, 0x138470, 0x1384ec, 0x138568, 0x1385e4,
+ 0x138660, 0x1386dc, 0x138758, 0x1387d4, 0x138850, 0x1388cc, 0x138948, 0x1389c4,
+ 0x138a40, 0x138abc, 0x138b38, 0x138bb4, 0x138c30, 0x138cac, 0x138d28, 0x138da4,
+ 0x138e20, 0x138e9c, 0x138f18, 0x138f94, 0x139010, 0x13908c, 0x139108, 0x139184,
+ 0x139200, 0x13927c, 0x1392f8, 0x139374, 0x1393f0, 0x13946c, 0x1394e8, 0x139564,
+ 0x1395e0, 0x13965c, 0x1396d8, 0x139754, 0x1397d0, 0x13984c, 0x1398c8, 0x139944,
+ 0x1399c0, 0x139a3c, 0x139ab8, 0x139b34, 0x139bb0, 0x139c2c, 0x139ca8, 0x139d24,
+ 0x139da0, 0x139e1c, 0x139e98, 0x139f14, 0x139f90, 0x13a00c, 0x13a088, 0x13a104,
+ 0x13a180, 0x13a1fc, 0x13a278, 0x13a2f4, 0x13a370, 0x13a3ec, 0x13a468, 0x13a4e4,
+ 0x13a560, 0x13a5dc, 0x13a658, 0x13a6d4, 0x13a750, 0x13a7cc, 0x13a848, 0x13a8c4,
+ 0x13a940, 0x13a9bc, 0x13aa38, 0x13aab4, 0x13ab30, 0x13abac, 0x13ac28, 0x13aca4,
+ 0x13ad20, 0x13ad9c, 0x13ae18, 0x13ae94, 0x13af10, 0x13af8c, 0x13b008, 0x13b084,
+ 0x13b100, 0x13b17c, 0x13b1f8, 0x13b274, 0x13b2f0, 0x13b36c, 0x13b3e8, 0x13b464,
+ 0x13b4e0, 0x13b55c, 0x13b5d8, 0x13b654, 0x13b6d0, 0x13b74c, 0x13b7c8, 0x13b844,
+ 0x13b8c0, 0x13b93c, 0x13b9b8, 0x13ba34, 0x13bab0, 0x13bb2c, 0x13bba8, 0x13bc24,
+ 0x13bca0, 0x13bd1c, 0x13bd98, 0x13be14, 0x13be90, 0x13bf0c, 0x13bf88, 0x13c004,
+ 0x13c080, 0x13c0fc, 0x13c178, 0x13c1f4, 0x13c270, 0x13c2ec, 0x13c368, 0x13c3e4,
+ 0x13c460, 0x13c4dc, 0x13c558, 0x13c5d4, 0x13c650, 0x13c6cc, 0x13c748, 0x13c7c4,
+ 0x13c840, 0x13c8bc, 0x13c938, 0x13c9b4, 0x13ca30, 0x13caac, 0x13cb28, 0x13cba4,
+ 0x13cc20, 0x13cc9c, 0x13cd18, 0x13cd94, 0x13ce10, 0x13ce8c, 0x13cf08, 0x13cf84,
+ 0x13d000, 0x13d07c, 0x13d0f8, 0x13d174, 0x13d1f0, 0x13d26c, 0x13d2e8, 0x13d364,
+ 0x13d3e0, 0x13d45c, 0x13d4d8, 0x13d554, 0x13d5d0, 0x13d64c, 0x13d6c8, 0x13d744,
+ 0x13d7c0, 0x13d83c, 0x13d8b8, 0x13d934, 0x13d9b0, 0x13da2c, 0x13daa8, 0x13db24,
+ 0x13dba0, 0x13dc1c, 0x13dc98, 0x13dd14, 0x13dd90, 0x13de0c, 0x13de88, 0x13df04,
+
+ 0x13df80, 0x13e024, 0x13e0c8, 0x13e16c, 0x13e210, 0x13e2b4, 0x13e358, 0x13e3fc,
+ 0x13e4a0, 0x13e544, 0x13e5e8, 0x13e68c, 0x13e730, 0x13e7d4, 0x13e878, 0x13e91c,
+ 0x13e9c0, 0x13ea64, 0x13eb08, 0x13ebac, 0x13ec50, 0x13ecf4, 0x13ed98, 0x13ee3c,
+ 0x13eee0, 0x13ef84, 0x13f028, 0x13f0cc, 0x13f170, 0x13f214, 0x13f2b8, 0x13f35c,
+
+ 0x13f400, 0x13f47c, 0x13f4f8, 0x13f574, 0x13f5f0, 0x13f66c, 0x13f6e8, 0x13f764,
+ 0x13f7e0, 0x13f85c, 0x13f8d8, 0x13f954, 0x13f9d0, 0x13fa4c, 0x13fac8, 0x13fb44,
+ 0x13fbc0, 0x13fc3c, 0x13fcb8, 0x13fd34, 0x13fdb0, 0x13fe2c, 0x13fea8, 0x13ff24,
+ 0x13ffa0, 0x14001c, 0x140098, 0x140114, 0x140190, 0x14020c, 0x140288, 0x140304,
+
+ 0x140380, 0x140424, 0x1404c8, 0x14056c, 0x140610, 0x1406b4, 0x140758, 0x1407fc,
+ 0x1408a0, 0x140944, 0x1409e8, 0x140a8c, 0x140b30, 0x140bd4, 0x140c78, 0x140d1c,
+ 0x140dc0, 0x140e64, 0x140f08, 0x140fac, 0x141050, 0x1410f4, 0x141198, 0x14123c,
+ 0x1412e0, 0x141384, 0x141428, 0x1414cc, 0x141570, 0x141614, 0x1416b8, 0x14175c,
+
+ 0x141800, 0x14187c, 0x1418f8, 0x141974, 0x1419f0, 0x141a6c, 0x141ae8, 0x141b64,
+ 0x141be0, 0x141c5c, 0x141cd8, 0x141d54, 0x141dd0, 0x141e4c, 0x141ec8, 0x141f44,
+ 0x141fc0, 0x14203c, 0x1420b8, 0x142134, 0x1421b0, 0x14222c, 0x1422a8, 0x142324,
+ 0x1423a0, 0x14241c, 0x142498, 0x142514, 0x142590, 0x14260c, 0x142688, 0x142704,
+
+ 0x142780, 0x142824, 0x1428c8, 0x14296c, 0x142a10, 0x142ab4, 0x142b58, 0x142bfc,
+ 0x142ca0, 0x142d44, 0x142de8, 0x142e8c, 0x142f30, 0x142fd4, 0x143078, 0x14311c,
+ 0x1431c0, 0x143264, 0x143308, 0x1433ac, 0x143450, 0x1434f4, 0x143598, 0x14363c,
+ 0x1436e0, 0x143784, 0x143828, 0x1438cc, 0x143970, 0x143a14, 0x143ab8, 0x143b5c,
+
+ 0x143c00, 0x143c7c, 0x143cf8, 0x143d74, 0x143df0, 0x143e6c, 0x143ee8, 0x143f64,
+ 0x143fe0, 0x14405c, 0x1440d8, 0x144154, 0x1441d0, 0x14424c, 0x1442c8, 0x144344,
+ 0x1443c0, 0x14443c, 0x1444b8, 0x144534, 0x1445b0, 0x14462c, 0x1446a8, 0x144724,
+ 0x1447a0, 0x14481c, 0x144898, 0x144914, 0x144990, 0x144a0c, 0x144a88, 0x144b04,
+
+ 0x144b80, 0x144c24, 0x144cc8, 0x144d6c, 0x144e10, 0x144eb4, 0x144f58, 0x144ffc,
+ 0x1450a0, 0x145144, 0x1451e8, 0x14528c, 0x145330, 0x1453d4, 0x145478, 0x14551c,
+ 0x1455c0, 0x145664, 0x145708, 0x1457ac, 0x145850, 0x1458f4, 0x145998, 0x145a3c,
+ 0x145ae0, 0x145b84, 0x145c28, 0x145ccc, 0x145d70, 0x145e14, 0x145eb8, 0x145f5c,
+
+ 0x146000, 0x14607c, 0x1460f8, 0x146174, 0x1461f0, 0x14626c, 0x1462e8, 0x146364,
+ 0x1463e0, 0x14645c, 0x1464d8, 0x146554, 0x1465d0, 0x14664c, 0x1466c8, 0x146744,
+ 0x1467c0, 0x14683c, 0x1468b8, 0x146934, 0x1469b0, 0x146a2c, 0x146aa8, 0x146b24,
+ 0x146ba0, 0x146c1c, 0x146c98, 0x146d14, 0x146d90, 0x146e0c, 0x146e88, 0x146f04,
+
+ 0x146f80, 0x147024, 0x1470c8, 0x14716c, 0x147210, 0x1472b4, 0x147358, 0x1473fc,
+ 0x1474a0, 0x147544, 0x1475e8, 0x14768c, 0x147730, 0x1477d4, 0x147878, 0x14791c,
+ 0x1479c0, 0x147a64, 0x147b08, 0x147bac, 0x147c50, 0x147cf4, 0x147d98, 0x147e3c,
+ 0x147ee0, 0x147f84, 0x148028, 0x1480cc, 0x148170, 0x148214, 0x1482b8, 0x14835c,
+
+ 0x148400, 0x14847c, 0x1484f8, 0x148574, 0x1485f0, 0x14866c, 0x1486e8, 0x148764,
+ 0x1487e0, 0x14885c, 0x1488d8, 0x148954, 0x1489d0, 0x148a4c, 0x148ac8, 0x148b44,
+ 0x148bc0, 0x148c3c, 0x148cb8, 0x148d34, 0x148db0, 0x148e2c, 0x148ea8, 0x148f24,
+ 0x148fa0, 0x14901c, 0x149098, 0x149114, 0x149190, 0x14920c, 0x149288, 0x149304,
+
+ 0x149380, 0x149424, 0x1494c8, 0x14956c, 0x149610, 0x1496b4, 0x149758, 0x1497fc,
+ 0x1498a0, 0x149944, 0x1499e8, 0x149a8c, 0x149b30, 0x149bd4, 0x149c78, 0x149d1c,
+ 0x149dc0, 0x149e64, 0x149f08, 0x149fac, 0x14a050, 0x14a0f4, 0x14a198, 0x14a23c,
+ 0x14a2e0, 0x14a384, 0x14a428, 0x14a4cc, 0x14a570, 0x14a614, 0x14a6b8, 0x14a75c,
+
+ 0x14a800, 0x14a87c, 0x14a8f8, 0x14a974, 0x14a9f0, 0x14aa6c, 0x14aae8, 0x14ab64,
+ 0x14abe0, 0x14ac5c, 0x14acd8, 0x14ad54, 0x14add0, 0x14ae4c, 0x14aec8, 0x14af44,
+ 0x14afc0, 0x14b03c, 0x14b0b8, 0x14b134, 0x14b1b0, 0x14b22c, 0x14b2a8, 0x14b324,
+ 0x14b3a0, 0x14b41c, 0x14b498, 0x14b514, 0x14b590, 0x14b60c, 0x14b688, 0x14b704,
+
+ 0x14b780, 0x14b824, 0x14b8c8, 0x14b96c, 0x14ba10, 0x14bab4, 0x14bb58, 0x14bbfc,
+ 0x14bca0, 0x14bd44, 0x14bde8, 0x14be8c, 0x14bf30, 0x14bfd4, 0x14c078, 0x14c11c,
+ 0x14c1c0, 0x14c264, 0x14c308, 0x14c3ac, 0x14c450, 0x14c4f4, 0x14c598, 0x14c63c,
+ 0x14c6e0, 0x14c784, 0x14c828, 0x14c8cc, 0x14c970, 0x14ca14, 0x14cab8, 0x14cb5c,
+
+ 0x14cc00, 0x14cc7c, 0x14ccf8, 0x14cd74, 0x14cdf0, 0x14ce6c, 0x14cee8, 0x14cf64,
+ 0x14cfe0, 0x14d05c, 0x14d0d8, 0x14d154, 0x14d1d0, 0x14d24c, 0x14d2c8, 0x14d344,
+ 0x14d3c0, 0x14d43c, 0x14d4b8, 0x14d534, 0x14d5b0, 0x14d62c, 0x14d6a8, 0x14d724,
+ 0x14d7a0, 0x14d81c, 0x14d898, 0x14d914, 0x14d990, 0x14da0c, 0x14da88, 0x14db04,
+
+ 0x14db80, 0x14dc24, 0x14dcc8, 0x14dd6c, 0x14de10, 0x14deb4, 0x14df58, 0x14dffc,
+ 0x14e0a0, 0x14e144, 0x14e1e8, 0x14e28c, 0x14e330, 0x14e3d4, 0x14e478, 0x14e51c,
+ 0x14e5c0, 0x14e664, 0x14e708, 0x14e7ac, 0x14e850, 0x14e8f4, 0x14e998, 0x14ea3c,
+ 0x14eae0, 0x14eb84, 0x14ec28, 0x14eccc, 0x14ed70, 0x14ee14, 0x14eeb8, 0x14ef5c,
+
+
+
+ 0x14f000, 0x14f07c, 0x14f0f8, 0x14f174, 0x14f1f0, 0x14f26c, 0x14f2e8, 0x14f364,
+ 0x14f3e0, 0x14f45c, 0x14f4d8, 0x14f554, 0x14f5d0, 0x14f64c, 0x14f6c8, 0x14f744,
+ 0x14f7c0, 0x14f83c, 0x14f8b8, 0x14f934, 0x14f9b0, 0x14fa2c, 0x14faa8, 0x14fb24,
+ 0x14fba0, 0x14fc1c, 0x14fc98, 0x14fd14, 0x14fd90, 0x14fe0c, 0x14fe88, 0x14ff04,
+ 0x14ff80, 0x14fffc, 0x150078, 0x1500f4, 0x150170, 0x1501ec, 0x150268, 0x1502e4,
+ 0x150360, 0x1503dc, 0x150458, 0x1504d4, 0x150550, 0x1505cc, 0x150648, 0x1506c4,
+ 0x150740, 0x1507bc, 0x150838, 0x1508b4, 0x150930, 0x1509ac, 0x150a28, 0x150aa4,
+ 0x150b20, 0x150b9c, 0x150c18, 0x150c94, 0x150d10, 0x150d8c, 0x150e08, 0x150e84,
+ 0x150f00, 0x150f7c, 0x150ff8, 0x151074, 0x1510f0, 0x15116c, 0x1511e8, 0x151264,
+ 0x1512e0, 0x15135c, 0x1513d8, 0x151454, 0x1514d0, 0x15154c, 0x1515c8, 0x151644,
+ 0x1516c0, 0x15173c, 0x1517b8, 0x151834, 0x1518b0, 0x15192c, 0x1519a8, 0x151a24,
+ 0x151aa0, 0x151b1c, 0x151b98, 0x151c14, 0x151c90, 0x151d0c, 0x151d88, 0x151e04,
+ 0x151e80, 0x151efc, 0x151f78, 0x151ff4, 0x152070, 0x1520ec, 0x152168, 0x1521e4,
+ 0x152260, 0x1522dc, 0x152358, 0x1523d4, 0x152450, 0x1524cc, 0x152548, 0x1525c4,
+ 0x152640, 0x1526bc, 0x152738, 0x1527b4, 0x152830, 0x1528ac, 0x152928, 0x1529a4,
+ 0x152a20, 0x152a9c, 0x152b18, 0x152b94, 0x152c10, 0x152c8c, 0x152d08, 0x152d84,
+ 0x152e00, 0x152e7c, 0x152ef8, 0x152f74, 0x152ff0, 0x15306c, 0x1530e8, 0x153164,
+ 0x1531e0, 0x15325c, 0x1532d8, 0x153354, 0x1533d0, 0x15344c, 0x1534c8, 0x153544,
+ 0x1535c0, 0x15363c, 0x1536b8, 0x153734, 0x1537b0, 0x15382c, 0x1538a8, 0x153924,
+ 0x1539a0, 0x153a1c, 0x153a98, 0x153b14, 0x153b90, 0x153c0c, 0x153c88, 0x153d04,
+ 0x153d80, 0x153dfc, 0x153e78, 0x153ef4, 0x153f70, 0x153fec, 0x154068, 0x1540e4,
+ 0x154160, 0x1541dc, 0x154258, 0x1542d4, 0x154350, 0x1543cc, 0x154448, 0x1544c4,
+ 0x154540, 0x1545bc, 0x154638, 0x1546b4, 0x154730, 0x1547ac, 0x154828, 0x1548a4,
+ 0x154920, 0x15499c, 0x154a18, 0x154a94, 0x154b10, 0x154b8c, 0x154c08, 0x154c84,
+ 0x154d00, 0x154d7c, 0x154df8, 0x154e74, 0x154ef0, 0x154f6c, 0x154fe8, 0x155064,
+ 0x1550e0, 0x15515c, 0x1551d8, 0x155254, 0x1552d0, 0x15534c, 0x1553c8, 0x155444,
+ 0x1554c0, 0x15553c, 0x1555b8, 0x155634, 0x1556b0, 0x15572c, 0x1557a8, 0x155824,
+ 0x1558a0, 0x15591c, 0x155998, 0x155a14, 0x155a90, 0x155b0c, 0x155b88, 0x155c04,
+ 0x155c80, 0x155cfc, 0x155d78, 0x155df4, 0x155e70, 0x155eec, 0x155f68, 0x155fe4,
+ 0x156060, 0x1560dc, 0x156158, 0x1561d4, 0x156250, 0x1562cc, 0x156348, 0x1563c4,
+ 0x156440, 0x1564bc, 0x156538, 0x1565b4, 0x156630, 0x1566ac, 0x156728, 0x1567a4,
+ 0x156820, 0x15689c, 0x156918, 0x156994, 0x156a10, 0x156a8c, 0x156b08, 0x156b84,
+ 0x156c00, 0x156c7c, 0x156cf8, 0x156d74, 0x156df0, 0x156e6c, 0x156ee8, 0x156f64,
+ 0x156fe0, 0x15705c, 0x1570d8, 0x157154, 0x1571d0, 0x15724c, 0x1572c8, 0x157344,
+ 0x1573c0, 0x15743c, 0x1574b8, 0x157534, 0x1575b0, 0x15762c, 0x1576a8, 0x157724,
+ 0x1577a0, 0x15781c, 0x157898, 0x157914, 0x157990, 0x157a0c, 0x157a88, 0x157b04,
+ 0x157b80, 0x157bfc, 0x157c78, 0x157cf4, 0x157d70, 0x157dec, 0x157e68, 0x157ee4,
+ 0x157f60, 0x157fdc, 0x158058, 0x1580d4, 0x158150, 0x1581cc, 0x158248, 0x1582c4,
+ 0x158340, 0x1583bc, 0x158438, 0x1584b4, 0x158530, 0x1585ac, 0x158628, 0x1586a4,
+ 0x158720, 0x15879c, 0x158818, 0x158894, 0x158910, 0x15898c, 0x158a08, 0x158a84,
+ 0x158b00, 0x158b7c, 0x158bf8, 0x158c74, 0x158cf0, 0x158d6c, 0x158de8, 0x158e64,
+ 0x158ee0, 0x158f5c, 0x158fd8, 0x159054, 0x1590d0, 0x15914c, 0x1591c8, 0x159244,
+ 0x1592c0, 0x15933c, 0x1593b8, 0x159434, 0x1594b0, 0x15952c, 0x1595a8, 0x159624,
+ 0x1596a0, 0x15971c, 0x159798, 0x159814, 0x159890, 0x15990c, 0x159988, 0x159a04,
+ 0x159a80, 0x159afc, 0x159b78, 0x159bf4, 0x159c70, 0x159cec, 0x159d68, 0x159de4,
+ 0x159e60, 0x159edc, 0x159f58, 0x159fd4, 0x15a050, 0x15a0cc, 0x15a148, 0x15a1c4,
+ 0x15a240, 0x15a2bc, 0x15a338, 0x15a3b4, 0x15a430, 0x15a4ac, 0x15a528, 0x15a5a4,
+ 0x15a620, 0x15a69c, 0x15a718, 0x15a794, 0x15a810, 0x15a88c, 0x15a908, 0x15a984,
+ 0x15aa00, 0x15aa7c, 0x15aaf8, 0x15ab74, 0x15abf0, 0x15ac6c, 0x15ace8, 0x15ad64,
+ 0x15ade0, 0x15ae5c, 0x15aed8, 0x15af54, 0x15afd0, 0x15b04c, 0x15b0c8, 0x15b144,
+ 0x15b1c0, 0x15b23c, 0x15b2b8, 0x15b334, 0x15b3b0, 0x15b42c, 0x15b4a8, 0x15b524,
+ 0x15b5a0, 0x15b61c, 0x15b698, 0x15b714, 0x15b790, 0x15b80c, 0x15b888, 0x15b904,
+ 0x15b980, 0x15b9fc, 0x15ba78, 0x15baf4, 0x15bb70, 0x15bbec, 0x15bc68, 0x15bce4,
+ 0x15bd60, 0x15bddc, 0x15be58, 0x15bed4, 0x15bf50, 0x15bfcc, 0x15c048, 0x15c0c4,
+ 0x15c140, 0x15c1bc, 0x15c238, 0x15c2b4, 0x15c330, 0x15c3ac, 0x15c428, 0x15c4a4,
+ 0x15c520, 0x15c59c, 0x15c618, 0x15c694, 0x15c710, 0x15c78c, 0x15c808, 0x15c884,
+ 0x15c900, 0x15c97c, 0x15c9f8, 0x15ca74, 0x15caf0, 0x15cb6c, 0x15cbe8, 0x15cc64,
+ 0x15cce0, 0x15cd5c, 0x15cdd8, 0x15ce54, 0x15ced0, 0x15cf4c, 0x15cfc8, 0x15d044,
+ 0x15d0c0, 0x15d13c, 0x15d1b8, 0x15d234, 0x15d2b0, 0x15d32c, 0x15d3a8, 0x15d424,
+ 0x15d4a0, 0x15d51c, 0x15d598, 0x15d614, 0x15d690, 0x15d70c, 0x15d788, 0x15d804,
+ 0x15d880, 0x15d8fc, 0x15d978, 0x15d9f4, 0x15da70, 0x15daec, 0x15db68, 0x15dbe4,
+ 0x15dc60, 0x15dcdc, 0x15dd58, 0x15ddd4, 0x15de50, 0x15decc, 0x15df48, 0x15dfc4,
+ 0x15e040, 0x15e0bc, 0x15e138, 0x15e1b4, 0x15e230, 0x15e2ac, 0x15e328, 0x15e3a4,
+ 0x15e420, 0x15e49c, 0x15e518, 0x15e594, 0x15e610, 0x15e68c, 0x15e708, 0x15e784,
+ 0x15e800, 0x15e87c, 0x15e8f8, 0x15e974, 0x15e9f0, 0x15ea6c, 0x15eae8, 0x15eb64,
+ 0x15ebe0, 0x15ec5c, 0x15ecd8, 0x15ed54, 0x15edd0, 0x15ee4c, 0x15eec8, 0x15ef44,
+ 0x15efc0, 0x15f03c, 0x15f0b8, 0x15f134, 0x15f1b0, 0x15f22c, 0x15f2a8, 0x15f324,
+ 0x15f3a0, 0x15f41c, 0x15f498, 0x15f514, 0x15f590, 0x15f60c, 0x15f688, 0x15f704,
+ 0x15f780, 0x15f7fc, 0x15f878, 0x15f8f4, 0x15f970, 0x15f9ec, 0x15fa68, 0x15fae4,
+ 0x15fb60, 0x15fbdc, 0x15fc58, 0x15fcd4, 0x15fd50, 0x15fdcc, 0x15fe48, 0x15fec4,
+ 0x15ff40, 0x15ffbc, 0x160038, 0x1600b4, 0x160130, 0x1601ac, 0x160228, 0x1602a4,
+ 0x160320, 0x16039c, 0x160418, 0x160494, 0x160510, 0x16058c, 0x160608, 0x160684,
+
+ 0x160700, 0x1607a4, 0x160848, 0x1608ec, 0x160990, 0x160a34, 0x160ad8, 0x160b7c,
+ 0x160c20, 0x160cc4, 0x160d68, 0x160e0c, 0x160eb0, 0x160f54, 0x160ff8, 0x16109c,
+ 0x161140, 0x1611e4, 0x161288, 0x16132c, 0x1613d0, 0x161474, 0x161518, 0x1615bc,
+ 0x161660, 0x161704, 0x1617a8, 0x16184c, 0x1618f0, 0x161994, 0x161a38, 0x161adc,
+ 0x161b80, 0x161c24, 0x161cc8, 0x161d6c, 0x161e10, 0x161eb4, 0x161f58, 0x161ffc,
+ 0x1620a0, 0x162144, 0x1621e8, 0x16228c, 0x162330, 0x1623d4, 0x162478, 0x16251c,
+ 0x1625c0, 0x162664, 0x162708, 0x1627ac, 0x162850, 0x1628f4, 0x162998, 0x162a3c,
+ 0x162ae0, 0x162b84, 0x162c28, 0x162ccc, 0x162d70, 0x162e14, 0x162eb8, 0x162f5c,
+
+ 0x163000, 0x16307c, 0x1630f8, 0x163174, 0x1631f0, 0x16326c, 0x1632e8, 0x163364,
+ 0x1633e0, 0x16345c, 0x1634d8, 0x163554, 0x1635d0, 0x16364c, 0x1636c8, 0x163744,
+ 0x1637c0, 0x16383c, 0x1638b8, 0x163934, 0x1639b0, 0x163a2c, 0x163aa8, 0x163b24,
+ 0x163ba0, 0x163c1c, 0x163c98, 0x163d14, 0x163d90, 0x163e0c, 0x163e88, 0x163f04,
+ 0x163f80, 0x163ffc, 0x164078, 0x1640f4, 0x164170, 0x1641ec, 0x164268, 0x1642e4,
+ 0x164360, 0x1643dc, 0x164458, 0x1644d4, 0x164550, 0x1645cc, 0x164648, 0x1646c4,
+ 0x164740, 0x1647bc, 0x164838, 0x1648b4, 0x164930, 0x1649ac, 0x164a28, 0x164aa4,
+ 0x164b20, 0x164b9c, 0x164c18, 0x164c94, 0x164d10, 0x164d8c, 0x164e08, 0x164e84,
+
+ 0x164f00, 0x164fa4, 0x165048, 0x1650ec, 0x165190, 0x165234, 0x1652d8, 0x16537c,
+ 0x165420, 0x1654c4, 0x165568, 0x16560c, 0x1656b0, 0x165754, 0x1657f8, 0x16589c,
+ 0x165940, 0x1659e4, 0x165a88, 0x165b2c, 0x165bd0, 0x165c74, 0x165d18, 0x165dbc,
+ 0x165e60, 0x165f04, 0x165fa8, 0x16604c, 0x1660f0, 0x166194, 0x166238, 0x1662dc,
+ 0x166380, 0x166424, 0x1664c8, 0x16656c, 0x166610, 0x1666b4, 0x166758, 0x1667fc,
+ 0x1668a0, 0x166944, 0x1669e8, 0x166a8c, 0x166b30, 0x166bd4, 0x166c78, 0x166d1c,
+ 0x166dc0, 0x166e64, 0x166f08, 0x166fac, 0x167050, 0x1670f4, 0x167198, 0x16723c,
+ 0x1672e0, 0x167384, 0x167428, 0x1674cc, 0x167570, 0x167614, 0x1676b8, 0x16775c,
+
+ 0x167800, 0x16787c, 0x1678f8, 0x167974, 0x1679f0, 0x167a6c, 0x167ae8, 0x167b64,
+ 0x167be0, 0x167c5c, 0x167cd8, 0x167d54, 0x167dd0, 0x167e4c, 0x167ec8, 0x167f44,
+ 0x167fc0, 0x16803c, 0x1680b8, 0x168134, 0x1681b0, 0x16822c, 0x1682a8, 0x168324,
+ 0x1683a0, 0x16841c, 0x168498, 0x168514, 0x168590, 0x16860c, 0x168688, 0x168704,
+ 0x168780, 0x1687fc, 0x168878, 0x1688f4, 0x168970, 0x1689ec, 0x168a68, 0x168ae4,
+ 0x168b60, 0x168bdc, 0x168c58, 0x168cd4, 0x168d50, 0x168dcc, 0x168e48, 0x168ec4,
+ 0x168f40, 0x168fbc, 0x169038, 0x1690b4, 0x169130, 0x1691ac, 0x169228, 0x1692a4,
+ 0x169320, 0x16939c, 0x169418, 0x169494, 0x169510, 0x16958c, 0x169608, 0x169684,
+
+ 0x169700, 0x1697a4, 0x169848, 0x1698ec, 0x169990, 0x169a34, 0x169ad8, 0x169b7c,
+ 0x169c20, 0x169cc4, 0x169d68, 0x169e0c, 0x169eb0, 0x169f54, 0x169ff8, 0x16a09c,
+ 0x16a140, 0x16a1e4, 0x16a288, 0x16a32c, 0x16a3d0, 0x16a474, 0x16a518, 0x16a5bc,
+ 0x16a660, 0x16a704, 0x16a7a8, 0x16a84c, 0x16a8f0, 0x16a994, 0x16aa38, 0x16aadc,
+ 0x16ab80, 0x16ac24, 0x16acc8, 0x16ad6c, 0x16ae10, 0x16aeb4, 0x16af58, 0x16affc,
+ 0x16b0a0, 0x16b144, 0x16b1e8, 0x16b28c, 0x16b330, 0x16b3d4, 0x16b478, 0x16b51c,
+ 0x16b5c0, 0x16b664, 0x16b708, 0x16b7ac, 0x16b850, 0x16b8f4, 0x16b998, 0x16ba3c,
+ 0x16bae0, 0x16bb84, 0x16bc28, 0x16bccc, 0x16bd70, 0x16be14, 0x16beb8, 0x16bf5c,
+
+ 0x16c000, 0x16c07c, 0x16c0f8, 0x16c174, 0x16c1f0, 0x16c26c, 0x16c2e8, 0x16c364,
+ 0x16c3e0, 0x16c45c, 0x16c4d8, 0x16c554, 0x16c5d0, 0x16c64c, 0x16c6c8, 0x16c744,
+ 0x16c7c0, 0x16c83c, 0x16c8b8, 0x16c934, 0x16c9b0, 0x16ca2c, 0x16caa8, 0x16cb24,
+ 0x16cba0, 0x16cc1c, 0x16cc98, 0x16cd14, 0x16cd90, 0x16ce0c, 0x16ce88, 0x16cf04,
+ 0x16cf80, 0x16cffc, 0x16d078, 0x16d0f4, 0x16d170, 0x16d1ec, 0x16d268, 0x16d2e4,
+ 0x16d360, 0x16d3dc, 0x16d458, 0x16d4d4, 0x16d550, 0x16d5cc, 0x16d648, 0x16d6c4,
+ 0x16d740, 0x16d7bc, 0x16d838, 0x16d8b4, 0x16d930, 0x16d9ac, 0x16da28, 0x16daa4,
+ 0x16db20, 0x16db9c, 0x16dc18, 0x16dc94, 0x16dd10, 0x16dd8c, 0x16de08, 0x16de84,
+
+ 0x16df00, 0x16dfa4, 0x16e048, 0x16e0ec, 0x16e190, 0x16e234, 0x16e2d8, 0x16e37c,
+ 0x16e420, 0x16e4c4, 0x16e568, 0x16e60c, 0x16e6b0, 0x16e754, 0x16e7f8, 0x16e89c,
+ 0x16e940, 0x16e9e4, 0x16ea88, 0x16eb2c, 0x16ebd0, 0x16ec74, 0x16ed18, 0x16edbc,
+ 0x16ee60, 0x16ef04, 0x16efa8, 0x16f04c, 0x16f0f0, 0x16f194, 0x16f238, 0x16f2dc,
+ 0x16f380, 0x16f424, 0x16f4c8, 0x16f56c, 0x16f610, 0x16f6b4, 0x16f758, 0x16f7fc,
+ 0x16f8a0, 0x16f944, 0x16f9e8, 0x16fa8c, 0x16fb30, 0x16fbd4, 0x16fc78, 0x16fd1c,
+ 0x16fdc0, 0x16fe64, 0x16ff08, 0x16ffac, 0x170050, 0x1700f4, 0x170198, 0x17023c,
+ 0x1702e0, 0x170384, 0x170428, 0x1704cc, 0x170570, 0x170614, 0x1706b8, 0x17075c,
+
+
+ 0x170800, 0x17087c, 0x1708f8, 0x170974, 0x1709f0, 0x170a6c, 0x170ae8, 0x170b64,
+ 0x170be0, 0x170c5c, 0x170cd8, 0x170d54, 0x170dd0, 0x170e4c, 0x170ec8, 0x170f44,
+ 0x170fc0, 0x17103c, 0x1710b8, 0x171134, 0x1711b0, 0x17122c, 0x1712a8, 0x171324,
+ 0x1713a0, 0x17141c, 0x171498, 0x171514, 0x171590, 0x17160c, 0x171688, 0x171704,
+ 0x171780, 0x1717fc, 0x171878, 0x1718f4, 0x171970, 0x1719ec, 0x171a68, 0x171ae4,
+ 0x171b60, 0x171bdc, 0x171c58, 0x171cd4, 0x171d50, 0x171dcc, 0x171e48, 0x171ec4,
+ 0x171f40, 0x171fbc, 0x172038, 0x1720b4, 0x172130, 0x1721ac, 0x172228, 0x1722a4,
+ 0x172320, 0x17239c, 0x172418, 0x172494, 0x172510, 0x17258c, 0x172608, 0x172684,
+ 0x172700, 0x17277c, 0x1727f8, 0x172874, 0x1728f0, 0x17296c, 0x1729e8, 0x172a64,
+ 0x172ae0, 0x172b5c, 0x172bd8, 0x172c54, 0x172cd0, 0x172d4c, 0x172dc8, 0x172e44,
+ 0x172ec0, 0x172f3c, 0x172fb8, 0x173034, 0x1730b0, 0x17312c, 0x1731a8, 0x173224,
+ 0x1732a0, 0x17331c, 0x173398, 0x173414, 0x173490, 0x17350c, 0x173588, 0x173604,
+ 0x173680, 0x1736fc, 0x173778, 0x1737f4, 0x173870, 0x1738ec, 0x173968, 0x1739e4,
+ 0x173a60, 0x173adc, 0x173b58, 0x173bd4, 0x173c50, 0x173ccc, 0x173d48, 0x173dc4,
+ 0x173e40, 0x173ebc, 0x173f38, 0x173fb4, 0x174030, 0x1740ac, 0x174128, 0x1741a4,
+ 0x174220, 0x17429c, 0x174318, 0x174394, 0x174410, 0x17448c, 0x174508, 0x174584,
+ 0x174600, 0x17467c, 0x1746f8, 0x174774, 0x1747f0, 0x17486c, 0x1748e8, 0x174964,
+ 0x1749e0, 0x174a5c, 0x174ad8, 0x174b54, 0x174bd0, 0x174c4c, 0x174cc8, 0x174d44,
+ 0x174dc0, 0x174e3c, 0x174eb8, 0x174f34, 0x174fb0, 0x17502c, 0x1750a8, 0x175124,
+ 0x1751a0, 0x17521c, 0x175298, 0x175314, 0x175390, 0x17540c, 0x175488, 0x175504,
+ 0x175580, 0x1755fc, 0x175678, 0x1756f4, 0x175770, 0x1757ec, 0x175868, 0x1758e4,
+ 0x175960, 0x1759dc, 0x175a58, 0x175ad4, 0x175b50, 0x175bcc, 0x175c48, 0x175cc4,
+ 0x175d40, 0x175dbc, 0x175e38, 0x175eb4, 0x175f30, 0x175fac, 0x176028, 0x1760a4,
+ 0x176120, 0x17619c, 0x176218, 0x176294, 0x176310, 0x17638c, 0x176408, 0x176484,
+ 0x176500, 0x17657c, 0x1765f8, 0x176674, 0x1766f0, 0x17676c, 0x1767e8, 0x176864,
+ 0x1768e0, 0x17695c, 0x1769d8, 0x176a54, 0x176ad0, 0x176b4c, 0x176bc8, 0x176c44,
+ 0x176cc0, 0x176d3c, 0x176db8, 0x176e34, 0x176eb0, 0x176f2c, 0x176fa8, 0x177024,
+ 0x1770a0, 0x17711c, 0x177198, 0x177214, 0x177290, 0x17730c, 0x177388, 0x177404,
+ 0x177480, 0x1774fc, 0x177578, 0x1775f4, 0x177670, 0x1776ec, 0x177768, 0x1777e4,
+ 0x177860, 0x1778dc, 0x177958, 0x1779d4, 0x177a50, 0x177acc, 0x177b48, 0x177bc4,
+ 0x177c40, 0x177cbc, 0x177d38, 0x177db4, 0x177e30, 0x177eac, 0x177f28, 0x177fa4,
+ 0x178020, 0x17809c, 0x178118, 0x178194, 0x178210, 0x17828c, 0x178308, 0x178384,
+ 0x178400, 0x17847c, 0x1784f8, 0x178574, 0x1785f0, 0x17866c, 0x1786e8, 0x178764,
+ 0x1787e0, 0x17885c, 0x1788d8, 0x178954, 0x1789d0, 0x178a4c, 0x178ac8, 0x178b44,
+ 0x178bc0, 0x178c3c, 0x178cb8, 0x178d34, 0x178db0, 0x178e2c, 0x178ea8, 0x178f24,
+ 0x178fa0, 0x17901c, 0x179098, 0x179114, 0x179190, 0x17920c, 0x179288, 0x179304,
+
+ 0x179380, 0x179424, 0x1794c8, 0x17956c, 0x179610, 0x1796b4, 0x179758, 0x1797fc,
+ 0x1798a0, 0x179944, 0x1799e8, 0x179a8c, 0x179b30, 0x179bd4, 0x179c78, 0x179d1c,
+ 0x179dc0, 0x179e64, 0x179f08, 0x179fac, 0x17a050, 0x17a0f4, 0x17a198, 0x17a23c,
+ 0x17a2e0, 0x17a384, 0x17a428, 0x17a4cc, 0x17a570, 0x17a614, 0x17a6b8, 0x17a75c,
+
+ 0x17a800, 0x17a87c, 0x17a8f8, 0x17a974, 0x17a9f0, 0x17aa6c, 0x17aae8, 0x17ab64,
+ 0x17abe0, 0x17ac5c, 0x17acd8, 0x17ad54, 0x17add0, 0x17ae4c, 0x17aec8, 0x17af44,
+ 0x17afc0, 0x17b03c, 0x17b0b8, 0x17b134, 0x17b1b0, 0x17b22c, 0x17b2a8, 0x17b324,
+ 0x17b3a0, 0x17b41c, 0x17b498, 0x17b514, 0x17b590, 0x17b60c, 0x17b688, 0x17b704,
+
+ 0x17b780, 0x17b824, 0x17b8c8, 0x17b96c, 0x17ba10, 0x17bab4, 0x17bb58, 0x17bbfc,
+ 0x17bca0, 0x17bd44, 0x17bde8, 0x17be8c, 0x17bf30, 0x17bfd4, 0x17c078, 0x17c11c,
+ 0x17c1c0, 0x17c264, 0x17c308, 0x17c3ac, 0x17c450, 0x17c4f4, 0x17c598, 0x17c63c,
+ 0x17c6e0, 0x17c784, 0x17c828, 0x17c8cc, 0x17c970, 0x17ca14, 0x17cab8, 0x17cb5c,
+
+ 0x17cc00, 0x17cc7c, 0x17ccf8, 0x17cd74, 0x17cdf0, 0x17ce6c, 0x17cee8, 0x17cf64,
+ 0x17cfe0, 0x17d05c, 0x17d0d8, 0x17d154, 0x17d1d0, 0x17d24c, 0x17d2c8, 0x17d344,
+ 0x17d3c0, 0x17d43c, 0x17d4b8, 0x17d534, 0x17d5b0, 0x17d62c, 0x17d6a8, 0x17d724,
+ 0x17d7a0, 0x17d81c, 0x17d898, 0x17d914, 0x17d990, 0x17da0c, 0x17da88, 0x17db04,
+
+ 0x17db80, 0x17dc24, 0x17dcc8, 0x17dd6c, 0x17de10, 0x17deb4, 0x17df58, 0x17dffc,
+ 0x17e0a0, 0x17e144, 0x17e1e8, 0x17e28c, 0x17e330, 0x17e3d4, 0x17e478, 0x17e51c,
+ 0x17e5c0, 0x17e664, 0x17e708, 0x17e7ac, 0x17e850, 0x17e8f4, 0x17e998, 0x17ea3c,
+ 0x17eae0, 0x17eb84, 0x17ec28, 0x17eccc, 0x17ed70, 0x17ee14, 0x17eeb8, 0x17ef5c,
+
+ 0x17f000, 0x17f07c, 0x17f0f8, 0x17f174, 0x17f1f0, 0x17f26c, 0x17f2e8, 0x17f364,
+ 0x17f3e0, 0x17f45c, 0x17f4d8, 0x17f554, 0x17f5d0, 0x17f64c, 0x17f6c8, 0x17f744,
+ 0x17f7c0, 0x17f83c, 0x17f8b8, 0x17f934, 0x17f9b0, 0x17fa2c, 0x17faa8, 0x17fb24,
+ 0x17fba0, 0x17fc1c, 0x17fc98, 0x17fd14, 0x17fd90, 0x17fe0c, 0x17fe88, 0x17ff04,
+
+ 0x17ff80, 0x180024, 0x1800c8, 0x18016c, 0x180210, 0x1802b4, 0x180358, 0x1803fc,
+ 0x1804a0, 0x180544, 0x1805e8, 0x18068c, 0x180730, 0x1807d4, 0x180878, 0x18091c,
+ 0x1809c0, 0x180a64, 0x180b08, 0x180bac, 0x180c50, 0x180cf4, 0x180d98, 0x180e3c,
+ 0x180ee0, 0x180f84, 0x181028, 0x1810cc, 0x181170, 0x181214, 0x1812b8, 0x18135c,
+
+ 0x181400, 0x18147c, 0x1814f8, 0x181574, 0x1815f0, 0x18166c, 0x1816e8, 0x181764,
+ 0x1817e0, 0x18185c, 0x1818d8, 0x181954, 0x1819d0, 0x181a4c, 0x181ac8, 0x181b44,
+ 0x181bc0, 0x181c3c, 0x181cb8, 0x181d34, 0x181db0, 0x181e2c, 0x181ea8, 0x181f24,
+ 0x181fa0, 0x18201c, 0x182098, 0x182114, 0x182190, 0x18220c, 0x182288, 0x182304,
+ 0x182380, 0x1823fc, 0x182478, 0x1824f4, 0x182570, 0x1825ec, 0x182668, 0x1826e4,
+ 0x182760, 0x1827dc, 0x182858, 0x1828d4, 0x182950, 0x1829cc, 0x182a48, 0x182ac4,
+ 0x182b40, 0x182bbc, 0x182c38, 0x182cb4, 0x182d30, 0x182dac, 0x182e28, 0x182ea4,
+ 0x182f20, 0x182f9c, 0x183018, 0x183094, 0x183110, 0x18318c, 0x183208, 0x183284,
+ 0x183300, 0x18337c, 0x1833f8, 0x183474, 0x1834f0, 0x18356c, 0x1835e8, 0x183664,
+ 0x1836e0, 0x18375c, 0x1837d8, 0x183854, 0x1838d0, 0x18394c, 0x1839c8, 0x183a44,
+ 0x183ac0, 0x183b3c, 0x183bb8, 0x183c34, 0x183cb0, 0x183d2c, 0x183da8, 0x183e24,
+ 0x183ea0, 0x183f1c, 0x183f98, 0x184014, 0x184090, 0x18410c, 0x184188, 0x184204,
+ 0x184280, 0x1842fc, 0x184378, 0x1843f4, 0x184470, 0x1844ec, 0x184568, 0x1845e4,
+ 0x184660, 0x1846dc, 0x184758, 0x1847d4, 0x184850, 0x1848cc, 0x184948, 0x1849c4,
+ 0x184a40, 0x184abc, 0x184b38, 0x184bb4, 0x184c30, 0x184cac, 0x184d28, 0x184da4,
+ 0x184e20, 0x184e9c, 0x184f18, 0x184f94, 0x185010, 0x18508c, 0x185108, 0x185184,
+ 0x185200, 0x18527c, 0x1852f8, 0x185374, 0x1853f0, 0x18546c, 0x1854e8, 0x185564,
+ 0x1855e0, 0x18565c, 0x1856d8, 0x185754, 0x1857d0, 0x18584c, 0x1858c8, 0x185944,
+ 0x1859c0, 0x185a3c, 0x185ab8, 0x185b34, 0x185bb0, 0x185c2c, 0x185ca8, 0x185d24,
+ 0x185da0, 0x185e1c, 0x185e98, 0x185f14, 0x185f90, 0x18600c, 0x186088, 0x186104,
+ 0x186180, 0x1861fc, 0x186278, 0x1862f4, 0x186370, 0x1863ec, 0x186468, 0x1864e4,
+ 0x186560, 0x1865dc, 0x186658, 0x1866d4, 0x186750, 0x1867cc, 0x186848, 0x1868c4,
+ 0x186940, 0x1869bc, 0x186a38, 0x186ab4, 0x186b30, 0x186bac, 0x186c28, 0x186ca4,
+ 0x186d20, 0x186d9c, 0x186e18, 0x186e94, 0x186f10, 0x186f8c, 0x187008, 0x187084,
+ 0x187100, 0x18717c, 0x1871f8, 0x187274, 0x1872f0, 0x18736c, 0x1873e8, 0x187464,
+ 0x1874e0, 0x18755c, 0x1875d8, 0x187654, 0x1876d0, 0x18774c, 0x1877c8, 0x187844,
+ 0x1878c0, 0x18793c, 0x1879b8, 0x187a34, 0x187ab0, 0x187b2c, 0x187ba8, 0x187c24,
+ 0x187ca0, 0x187d1c, 0x187d98, 0x187e14, 0x187e90, 0x187f0c, 0x187f88, 0x188004,
+ 0x188080, 0x1880fc, 0x188178, 0x1881f4, 0x188270, 0x1882ec, 0x188368, 0x1883e4,
+ 0x188460, 0x1884dc, 0x188558, 0x1885d4, 0x188650, 0x1886cc, 0x188748, 0x1887c4,
+ 0x188840, 0x1888bc, 0x188938, 0x1889b4, 0x188a30, 0x188aac, 0x188b28, 0x188ba4,
+ 0x188c20, 0x188c9c, 0x188d18, 0x188d94, 0x188e10, 0x188e8c, 0x188f08, 0x188f84,
+ 0x189000, 0x18907c, 0x1890f8, 0x189174, 0x1891f0, 0x18926c, 0x1892e8, 0x189364,
+ 0x1893e0, 0x18945c, 0x1894d8, 0x189554, 0x1895d0, 0x18964c, 0x1896c8, 0x189744,
+ 0x1897c0, 0x18983c, 0x1898b8, 0x189934, 0x1899b0, 0x189a2c, 0x189aa8, 0x189b24,
+ 0x189ba0, 0x189c1c, 0x189c98, 0x189d14, 0x189d90, 0x189e0c, 0x189e88, 0x189f04,
+
+ 0x189f80, 0x18a024, 0x18a0c8, 0x18a16c, 0x18a210, 0x18a2b4, 0x18a358, 0x18a3fc,
+ 0x18a4a0, 0x18a544, 0x18a5e8, 0x18a68c, 0x18a730, 0x18a7d4, 0x18a878, 0x18a91c,
+ 0x18a9c0, 0x18aa64, 0x18ab08, 0x18abac, 0x18ac50, 0x18acf4, 0x18ad98, 0x18ae3c,
+ 0x18aee0, 0x18af84, 0x18b028, 0x18b0cc, 0x18b170, 0x18b214, 0x18b2b8, 0x18b35c,
+
+ 0x18b400, 0x18b47c, 0x18b4f8, 0x18b574, 0x18b5f0, 0x18b66c, 0x18b6e8, 0x18b764,
+ 0x18b7e0, 0x18b85c, 0x18b8d8, 0x18b954, 0x18b9d0, 0x18ba4c, 0x18bac8, 0x18bb44,
+ 0x18bbc0, 0x18bc3c, 0x18bcb8, 0x18bd34, 0x18bdb0, 0x18be2c, 0x18bea8, 0x18bf24,
+ 0x18bfa0, 0x18c01c, 0x18c098, 0x18c114, 0x18c190, 0x18c20c, 0x18c288, 0x18c304,
+
+ 0x18c380, 0x18c424, 0x18c4c8, 0x18c56c, 0x18c610, 0x18c6b4, 0x18c758, 0x18c7fc,
+ 0x18c8a0, 0x18c944, 0x18c9e8, 0x18ca8c, 0x18cb30, 0x18cbd4, 0x18cc78, 0x18cd1c,
+ 0x18cdc0, 0x18ce64, 0x18cf08, 0x18cfac, 0x18d050, 0x18d0f4, 0x18d198, 0x18d23c,
+ 0x18d2e0, 0x18d384, 0x18d428, 0x18d4cc, 0x18d570, 0x18d614, 0x18d6b8, 0x18d75c,
+
+ 0x18d800, 0x18d87c, 0x18d8f8, 0x18d974, 0x18d9f0, 0x18da6c, 0x18dae8, 0x18db64,
+ 0x18dbe0, 0x18dc5c, 0x18dcd8, 0x18dd54, 0x18ddd0, 0x18de4c, 0x18dec8, 0x18df44,
+ 0x18dfc0, 0x18e03c, 0x18e0b8, 0x18e134, 0x18e1b0, 0x18e22c, 0x18e2a8, 0x18e324,
+ 0x18e3a0, 0x18e41c, 0x18e498, 0x18e514, 0x18e590, 0x18e60c, 0x18e688, 0x18e704,
+
+ 0x18e780, 0x18e824, 0x18e8c8, 0x18e96c, 0x18ea10, 0x18eab4, 0x18eb58, 0x18ebfc,
+ 0x18eca0, 0x18ed44, 0x18ede8, 0x18ee8c, 0x18ef30, 0x18efd4, 0x18f078, 0x18f11c,
+ 0x18f1c0, 0x18f264, 0x18f308, 0x18f3ac, 0x18f450, 0x18f4f4, 0x18f598, 0x18f63c,
+ 0x18f6e0, 0x18f784, 0x18f828, 0x18f8cc, 0x18f970, 0x18fa14, 0x18fab8, 0x18fb5c,
+
+ 0x18fc00, 0x18fc7c, 0x18fcf8, 0x18fd74, 0x18fdf0, 0x18fe6c, 0x18fee8, 0x18ff64,
+ 0x18ffe0, 0x19005c, 0x1900d8, 0x190154, 0x1901d0, 0x19024c, 0x1902c8, 0x190344,
+ 0x1903c0, 0x19043c, 0x1904b8, 0x190534, 0x1905b0, 0x19062c, 0x1906a8, 0x190724,
+ 0x1907a0, 0x19081c, 0x190898, 0x190914, 0x190990, 0x190a0c, 0x190a88, 0x190b04,
+
+ 0x190b80, 0x190c24, 0x190cc8, 0x190d6c, 0x190e10, 0x190eb4, 0x190f58, 0x190ffc,
+ 0x1910a0, 0x191144, 0x1911e8, 0x19128c, 0x191330, 0x1913d4, 0x191478, 0x19151c,
+ 0x1915c0, 0x191664, 0x191708, 0x1917ac, 0x191850, 0x1918f4, 0x191998, 0x191a3c,
+ 0x191ae0, 0x191b84, 0x191c28, 0x191ccc, 0x191d70, 0x191e14, 0x191eb8, 0x191f5c,
+
+ 0x192000, 0x19207c, 0x1920f8, 0x192174, 0x1921f0, 0x19226c, 0x1922e8, 0x192364,
+ 0x1923e0, 0x19245c, 0x1924d8, 0x192554, 0x1925d0, 0x19264c, 0x1926c8, 0x192744,
+ 0x1927c0, 0x19283c, 0x1928b8, 0x192934, 0x1929b0, 0x192a2c, 0x192aa8, 0x192b24,
+ 0x192ba0, 0x192c1c, 0x192c98, 0x192d14, 0x192d90, 0x192e0c, 0x192e88, 0x192f04,
+ 0x192f80, 0x192ffc, 0x193078, 0x1930f4, 0x193170, 0x1931ec, 0x193268, 0x1932e4,
+ 0x193360, 0x1933dc, 0x193458, 0x1934d4, 0x193550, 0x1935cc, 0x193648, 0x1936c4,
+
+ 0x193740, 0x1937e4, 0x193888, 0x19392c, 0x1939d0, 0x193a74, 0x193b18, 0x193bbc,
+ 0x193c60, 0x193d04, 0x193da8, 0x193e4c, 0x193ef0, 0x193f94, 0x194038, 0x1940dc,
+
+ 0x194180, 0x1941fc, 0x194278, 0x1942f4, 0x194370, 0x1943ec, 0x194468, 0x1944e4,
+ 0x194560, 0x1945dc, 0x194658, 0x1946d4, 0x194750, 0x1947cc, 0x194848, 0x1948c4,
+ 0x194940, 0x1949bc, 0x194a38, 0x194ab4, 0x194b30, 0x194bac, 0x194c28, 0x194ca4,
+ 0x194d20, 0x194d9c, 0x194e18, 0x194e94, 0x194f10, 0x194f8c, 0x195008, 0x195084,
+ 0x195100, 0x19517c, 0x1951f8, 0x195274, 0x1952f0, 0x19536c, 0x1953e8, 0x195464,
+ 0x1954e0, 0x19555c, 0x1955d8, 0x195654, 0x1956d0, 0x19574c, 0x1957c8, 0x195844,
+
+ 0x1958c0, 0x195964, 0x195a08, 0x195aac, 0x195b50, 0x195bf4, 0x195c98, 0x195d3c,
+ 0x195de0, 0x195e84, 0x195f28, 0x195fcc, 0x196070, 0x196114, 0x1961b8, 0x19625c,
+
+ 0x196300, 0x19637c, 0x1963f8, 0x196474, 0x1964f0, 0x19656c, 0x1965e8, 0x196664,
+ 0x1966e0, 0x19675c, 0x1967d8, 0x196854, 0x1968d0, 0x19694c, 0x1969c8, 0x196a44,
+ 0x196ac0, 0x196b3c, 0x196bb8, 0x196c34, 0x196cb0, 0x196d2c, 0x196da8, 0x196e24,
+ 0x196ea0, 0x196f1c, 0x196f98, 0x197014, 0x197090, 0x19710c, 0x197188, 0x197204,
+ 0x197280, 0x1972fc, 0x197378, 0x1973f4, 0x197470, 0x1974ec, 0x197568, 0x1975e4,
+ 0x197660, 0x1976dc, 0x197758, 0x1977d4, 0x197850, 0x1978cc, 0x197948, 0x1979c4,
+
+ 0x197a40, 0x197ae4, 0x197b88, 0x197c2c, 0x197cd0, 0x197d74, 0x197e18, 0x197ebc,
+ 0x197f60, 0x198004, 0x1980a8, 0x19814c, 0x1981f0, 0x198294, 0x198338, 0x1983dc,
+
+ 0x198480, 0x1984fc, 0x198578, 0x1985f4, 0x198670, 0x1986ec, 0x198768, 0x1987e4,
+ 0x198860, 0x1988dc, 0x198958, 0x1989d4, 0x198a50, 0x198acc, 0x198b48, 0x198bc4,
+ 0x198c40, 0x198cbc, 0x198d38, 0x198db4, 0x198e30, 0x198eac, 0x198f28, 0x198fa4,
+ 0x199020, 0x19909c, 0x199118, 0x199194, 0x199210, 0x19928c, 0x199308, 0x199384,
+ 0x199400, 0x19947c, 0x1994f8, 0x199574, 0x1995f0, 0x19966c, 0x1996e8, 0x199764,
+ 0x1997e0, 0x19985c, 0x1998d8, 0x199954, 0x1999d0, 0x199a4c, 0x199ac8, 0x199b44,
+
+ 0x199bc0, 0x199c64, 0x199d08, 0x199dac, 0x199e50, 0x199ef4, 0x199f98, 0x19a03c,
+ 0x19a0e0, 0x19a184, 0x19a228, 0x19a2cc, 0x19a370, 0x19a414, 0x19a4b8, 0x19a55c,
+
+ 0x19a600, 0x19a67c, 0x19a6f8, 0x19a774, 0x19a7f0, 0x19a86c, 0x19a8e8, 0x19a964,
+ 0x19a9e0, 0x19aa5c, 0x19aad8, 0x19ab54, 0x19abd0, 0x19ac4c, 0x19acc8, 0x19ad44,
+ 0x19adc0, 0x19ae3c, 0x19aeb8, 0x19af34, 0x19afb0, 0x19b02c, 0x19b0a8, 0x19b124,
+ 0x19b1a0, 0x19b21c, 0x19b298, 0x19b314, 0x19b390, 0x19b40c, 0x19b488, 0x19b504,
+ 0x19b580, 0x19b5fc, 0x19b678, 0x19b6f4, 0x19b770, 0x19b7ec, 0x19b868, 0x19b8e4,
+ 0x19b960, 0x19b9dc, 0x19ba58, 0x19bad4, 0x19bb50, 0x19bbcc, 0x19bc48, 0x19bcc4,
+
+ 0x19bd40, 0x19bde4, 0x19be88, 0x19bf2c, 0x19bfd0, 0x19c074, 0x19c118, 0x19c1bc,
+ 0x19c260, 0x19c304, 0x19c3a8, 0x19c44c, 0x19c4f0, 0x19c594, 0x19c638, 0x19c6dc,
+
+ 0x19c780, 0x19c7fc, 0x19c878, 0x19c8f4, 0x19c970, 0x19c9ec, 0x19ca68, 0x19cae4,
+ 0x19cb60, 0x19cbdc, 0x19cc58, 0x19ccd4, 0x19cd50, 0x19cdcc, 0x19ce48, 0x19cec4,
+ 0x19cf40, 0x19cfbc, 0x19d038, 0x19d0b4, 0x19d130, 0x19d1ac, 0x19d228, 0x19d2a4,
+ 0x19d320, 0x19d39c, 0x19d418, 0x19d494, 0x19d510, 0x19d58c, 0x19d608, 0x19d684,
+ 0x19d700, 0x19d77c, 0x19d7f8, 0x19d874, 0x19d8f0, 0x19d96c, 0x19d9e8, 0x19da64,
+ 0x19dae0, 0x19db5c, 0x19dbd8, 0x19dc54, 0x19dcd0, 0x19dd4c, 0x19ddc8, 0x19de44,
+
+ 0x19dec0, 0x19df64, 0x19e008, 0x19e0ac, 0x19e150, 0x19e1f4, 0x19e298, 0x19e33c,
+ 0x19e3e0, 0x19e484, 0x19e528, 0x19e5cc, 0x19e670, 0x19e714, 0x19e7b8, 0x19e85c,
+
+ 0x19e900, 0x19e97c, 0x19e9f8, 0x19ea74, 0x19eaf0, 0x19eb6c, 0x19ebe8, 0x19ec64,
+ 0x19ece0, 0x19ed5c, 0x19edd8, 0x19ee54, 0x19eed0, 0x19ef4c, 0x19efc8, 0x19f044,
+ 0x19f0c0, 0x19f13c, 0x19f1b8, 0x19f234, 0x19f2b0, 0x19f32c, 0x19f3a8, 0x19f424,
+ 0x19f4a0, 0x19f51c, 0x19f598, 0x19f614, 0x19f690, 0x19f70c, 0x19f788, 0x19f804,
+ 0x19f880, 0x19f8fc, 0x19f978, 0x19f9f4, 0x19fa70, 0x19faec, 0x19fb68, 0x19fbe4,
+ 0x19fc60, 0x19fcdc, 0x19fd58, 0x19fdd4, 0x19fe50, 0x19fecc, 0x19ff48, 0x19ffc4,
+
+ 0x1a0040, 0x1a00e4, 0x1a0188, 0x1a022c, 0x1a02d0, 0x1a0374, 0x1a0418, 0x1a04bc,
+ 0x1a0560, 0x1a0604, 0x1a06a8, 0x1a074c, 0x1a07f0, 0x1a0894, 0x1a0938, 0x1a09dc,
+
+ 0x1a0a80, 0x1a0afc, 0x1a0b78, 0x1a0bf4, 0x1a0c70, 0x1a0cec, 0x1a0d68, 0x1a0de4,
+ 0x1a0e60, 0x1a0edc, 0x1a0f58, 0x1a0fd4, 0x1a1050, 0x1a10cc, 0x1a1148, 0x1a11c4,
+ 0x1a1240, 0x1a12bc, 0x1a1338, 0x1a13b4, 0x1a1430, 0x1a14ac, 0x1a1528, 0x1a15a4,
+ 0x1a1620, 0x1a169c, 0x1a1718, 0x1a1794, 0x1a1810, 0x1a188c, 0x1a1908, 0x1a1984,
+ 0x1a1a00, 0x1a1a7c, 0x1a1af8, 0x1a1b74, 0x1a1bf0, 0x1a1c6c, 0x1a1ce8, 0x1a1d64,
+ 0x1a1de0, 0x1a1e5c, 0x1a1ed8, 0x1a1f54, 0x1a1fd0, 0x1a204c, 0x1a20c8, 0x1a2144,
+
+ 0x1a21c0, 0x1a2264, 0x1a2308, 0x1a23ac, 0x1a2450, 0x1a24f4, 0x1a2598, 0x1a263c,
+ 0x1a26e0, 0x1a2784, 0x1a2828, 0x1a28cc, 0x1a2970, 0x1a2a14, 0x1a2ab8, 0x1a2b5c,
+
+ 0x1a2c00, 0x1a2c7c, 0x1a2cf8, 0x1a2d74, 0x1a2df0, 0x1a2e6c, 0x1a2ee8, 0x1a2f64,
+ 0x1a2fe0, 0x1a305c, 0x1a30d8, 0x1a3154, 0x1a31d0, 0x1a324c, 0x1a32c8, 0x1a3344,
+ 0x1a33c0, 0x1a343c, 0x1a34b8, 0x1a3534, 0x1a35b0, 0x1a362c, 0x1a36a8, 0x1a3724,
+ 0x1a37a0, 0x1a381c, 0x1a3898, 0x1a3914, 0x1a3990, 0x1a3a0c, 0x1a3a88, 0x1a3b04,
+ 0x1a3b80, 0x1a3bfc, 0x1a3c78, 0x1a3cf4, 0x1a3d70, 0x1a3dec, 0x1a3e68, 0x1a3ee4,
+ 0x1a3f60, 0x1a3fdc, 0x1a4058, 0x1a40d4, 0x1a4150, 0x1a41cc, 0x1a4248, 0x1a42c4,
+
+ 0x1a4340, 0x1a43e4, 0x1a4488, 0x1a452c, 0x1a45d0, 0x1a4674, 0x1a4718, 0x1a47bc,
+ 0x1a4860, 0x1a4904, 0x1a49a8, 0x1a4a4c, 0x1a4af0, 0x1a4b94, 0x1a4c38, 0x1a4cdc,
+
+ 0x1a4d80, 0x1a4dfc, 0x1a4e78, 0x1a4ef4, 0x1a4f70, 0x1a4fec, 0x1a5068, 0x1a50e4,
+ 0x1a5160, 0x1a51dc, 0x1a5258, 0x1a52d4, 0x1a5350, 0x1a53cc, 0x1a5448, 0x1a54c4,
+ 0x1a5540, 0x1a55bc, 0x1a5638, 0x1a56b4, 0x1a5730, 0x1a57ac, 0x1a5828, 0x1a58a4,
+ 0x1a5920, 0x1a599c, 0x1a5a18, 0x1a5a94, 0x1a5b10, 0x1a5b8c, 0x1a5c08, 0x1a5c84,
+ 0x1a5d00, 0x1a5d7c, 0x1a5df8, 0x1a5e74, 0x1a5ef0, 0x1a5f6c, 0x1a5fe8, 0x1a6064,
+ 0x1a60e0, 0x1a615c, 0x1a61d8, 0x1a6254, 0x1a62d0, 0x1a634c, 0x1a63c8, 0x1a6444,
+
+ 0x1a64c0, 0x1a6564, 0x1a6608, 0x1a66ac, 0x1a6750, 0x1a67f4, 0x1a6898, 0x1a693c,
+ 0x1a69e0, 0x1a6a84, 0x1a6b28, 0x1a6bcc, 0x1a6c70, 0x1a6d14, 0x1a6db8, 0x1a6e5c,
+
+ 0x1a6f00, 0x1a6f7c, 0x1a6ff8, 0x1a7074, 0x1a70f0, 0x1a716c, 0x1a71e8, 0x1a7264,
+ 0x1a72e0, 0x1a735c, 0x1a73d8, 0x1a7454, 0x1a74d0, 0x1a754c, 0x1a75c8, 0x1a7644,
+ 0x1a76c0, 0x1a773c, 0x1a77b8, 0x1a7834, 0x1a78b0, 0x1a792c, 0x1a79a8, 0x1a7a24,
+ 0x1a7aa0, 0x1a7b1c, 0x1a7b98, 0x1a7c14, 0x1a7c90, 0x1a7d0c, 0x1a7d88, 0x1a7e04,
+ 0x1a7e80, 0x1a7efc, 0x1a7f78, 0x1a7ff4, 0x1a8070, 0x1a80ec, 0x1a8168, 0x1a81e4,
+ 0x1a8260, 0x1a82dc, 0x1a8358, 0x1a83d4, 0x1a8450, 0x1a84cc, 0x1a8548, 0x1a85c4,
+
+ 0x1a8640, 0x1a86e4, 0x1a8788, 0x1a882c, 0x1a88d0, 0x1a8974, 0x1a8a18, 0x1a8abc,
+ 0x1a8b60, 0x1a8c04, 0x1a8ca8, 0x1a8d4c, 0x1a8df0, 0x1a8e94, 0x1a8f38, 0x1a8fdc,
+
+ 0x1a9080, 0x1a90fc, 0x1a9178, 0x1a91f4, 0x1a9270, 0x1a92ec, 0x1a9368, 0x1a93e4,
+ 0x1a9460, 0x1a94dc, 0x1a9558, 0x1a95d4, 0x1a9650, 0x1a96cc, 0x1a9748, 0x1a97c4,
+ 0x1a9840, 0x1a98bc, 0x1a9938, 0x1a99b4, 0x1a9a30, 0x1a9aac, 0x1a9b28, 0x1a9ba4,
+ 0x1a9c20, 0x1a9c9c, 0x1a9d18, 0x1a9d94, 0x1a9e10, 0x1a9e8c, 0x1a9f08, 0x1a9f84,
+ 0x1aa000, 0x1aa07c, 0x1aa0f8, 0x1aa174, 0x1aa1f0, 0x1aa26c, 0x1aa2e8, 0x1aa364,
+ 0x1aa3e0, 0x1aa45c, 0x1aa4d8, 0x1aa554, 0x1aa5d0, 0x1aa64c, 0x1aa6c8, 0x1aa744,
+
+ 0x1aa7c0, 0x1aa864, 0x1aa908, 0x1aa9ac, 0x1aaa50, 0x1aaaf4, 0x1aab98, 0x1aac3c,
+ 0x1aace0, 0x1aad84, 0x1aae28, 0x1aaecc, 0x1aaf70, 0x1ab014, 0x1ab0b8, 0x1ab15c,
+
+ 0x1ab200, 0x1ab27c, 0x1ab2f8, 0x1ab374, 0x1ab3f0, 0x1ab46c, 0x1ab4e8, 0x1ab564,
+ 0x1ab5e0, 0x1ab65c, 0x1ab6d8, 0x1ab754, 0x1ab7d0, 0x1ab84c, 0x1ab8c8, 0x1ab944,
+ 0x1ab9c0, 0x1aba3c, 0x1abab8, 0x1abb34, 0x1abbb0, 0x1abc2c, 0x1abca8, 0x1abd24,
+ 0x1abda0, 0x1abe1c, 0x1abe98, 0x1abf14, 0x1abf90, 0x1ac00c, 0x1ac088, 0x1ac104,
+ 0x1ac180, 0x1ac1fc, 0x1ac278, 0x1ac2f4, 0x1ac370, 0x1ac3ec, 0x1ac468, 0x1ac4e4,
+ 0x1ac560, 0x1ac5dc, 0x1ac658, 0x1ac6d4, 0x1ac750, 0x1ac7cc, 0x1ac848, 0x1ac8c4,
+
+ 0x1ac940, 0x1ac9e4, 0x1aca88, 0x1acb2c, 0x1acbd0, 0x1acc74, 0x1acd18, 0x1acdbc,
+ 0x1ace60, 0x1acf04, 0x1acfa8, 0x1ad04c, 0x1ad0f0, 0x1ad194, 0x1ad238, 0x1ad2dc,
+
+ 0x1ad380, 0x1ad3fc, 0x1ad478, 0x1ad4f4, 0x1ad570, 0x1ad5ec, 0x1ad668, 0x1ad6e4,
+ 0x1ad760, 0x1ad7dc, 0x1ad858, 0x1ad8d4, 0x1ad950, 0x1ad9cc, 0x1ada48, 0x1adac4,
+ 0x1adb40, 0x1adbbc, 0x1adc38, 0x1adcb4, 0x1add30, 0x1addac, 0x1ade28, 0x1adea4,
+ 0x1adf20, 0x1adf9c, 0x1ae018, 0x1ae094, 0x1ae110, 0x1ae18c, 0x1ae208, 0x1ae284,
+ 0x1ae300, 0x1ae37c, 0x1ae3f8, 0x1ae474, 0x1ae4f0, 0x1ae56c, 0x1ae5e8, 0x1ae664,
+ 0x1ae6e0, 0x1ae75c, 0x1ae7d8, 0x1ae854, 0x1ae8d0, 0x1ae94c, 0x1ae9c8, 0x1aea44,
+
+ 0x1aeac0, 0x1aeb64, 0x1aec08, 0x1aecac, 0x1aed50, 0x1aedf4, 0x1aee98, 0x1aef3c,
+ 0x1aefe0, 0x1af084, 0x1af128, 0x1af1cc, 0x1af270, 0x1af314, 0x1af3b8, 0x1af45c,
+
+ 0x1af500, 0x1af57c, 0x1af5f8, 0x1af674, 0x1af6f0, 0x1af76c, 0x1af7e8, 0x1af864,
+ 0x1af8e0, 0x1af95c, 0x1af9d8, 0x1afa54, 0x1afad0, 0x1afb4c, 0x1afbc8, 0x1afc44,
+ 0x1afcc0, 0x1afd3c, 0x1afdb8, 0x1afe34, 0x1afeb0, 0x1aff2c, 0x1affa8, 0x1b0024,
+ 0x1b00a0, 0x1b011c, 0x1b0198, 0x1b0214, 0x1b0290, 0x1b030c, 0x1b0388, 0x1b0404,
+ 0x1b0480, 0x1b04fc, 0x1b0578, 0x1b05f4, 0x1b0670, 0x1b06ec, 0x1b0768, 0x1b07e4,
+ 0x1b0860, 0x1b08dc, 0x1b0958, 0x1b09d4, 0x1b0a50, 0x1b0acc, 0x1b0b48, 0x1b0bc4,
+
+ 0x1b0c40, 0x1b0ce4, 0x1b0d88, 0x1b0e2c, 0x1b0ed0, 0x1b0f74, 0x1b1018, 0x1b10bc,
+ 0x1b1160, 0x1b1204, 0x1b12a8, 0x1b134c, 0x1b13f0, 0x1b1494, 0x1b1538, 0x1b15dc,
+
+ 0x1b1680, 0x1b16fc, 0x1b1778, 0x1b17f4, 0x1b1870, 0x1b18ec, 0x1b1968, 0x1b19e4,
+ 0x1b1a60, 0x1b1adc, 0x1b1b58, 0x1b1bd4, 0x1b1c50, 0x1b1ccc, 0x1b1d48, 0x1b1dc4,
+ 0x1b1e40, 0x1b1ebc, 0x1b1f38, 0x1b1fb4, 0x1b2030, 0x1b20ac, 0x1b2128, 0x1b21a4,
+ 0x1b2220, 0x1b229c, 0x1b2318, 0x1b2394, 0x1b2410, 0x1b248c, 0x1b2508, 0x1b2584,
+ 0x1b2600, 0x1b267c, 0x1b26f8, 0x1b2774, 0x1b27f0, 0x1b286c, 0x1b28e8, 0x1b2964,
+ 0x1b29e0, 0x1b2a5c, 0x1b2ad8, 0x1b2b54, 0x1b2bd0, 0x1b2c4c, 0x1b2cc8, 0x1b2d44,
+
+ 0x1b2dc0, 0x1b2e64, 0x1b2f08, 0x1b2fac, 0x1b3050, 0x1b30f4, 0x1b3198, 0x1b323c,
+ 0x1b32e0, 0x1b3384, 0x1b3428, 0x1b34cc, 0x1b3570, 0x1b3614, 0x1b36b8, 0x1b375c,
+
+ 0x1b3800, 0x1b387c, 0x1b38f8, 0x1b3974, 0x1b39f0, 0x1b3a6c, 0x1b3ae8, 0x1b3b64,
+ 0x1b3be0, 0x1b3c5c, 0x1b3cd8, 0x1b3d54, 0x1b3dd0, 0x1b3e4c, 0x1b3ec8, 0x1b3f44,
+ 0x1b3fc0, 0x1b403c, 0x1b40b8, 0x1b4134, 0x1b41b0, 0x1b422c, 0x1b42a8, 0x1b4324,
+ 0x1b43a0, 0x1b441c, 0x1b4498, 0x1b4514, 0x1b4590, 0x1b460c, 0x1b4688, 0x1b4704,
+ 0x1b4780, 0x1b47fc, 0x1b4878, 0x1b48f4, 0x1b4970, 0x1b49ec, 0x1b4a68, 0x1b4ae4,
+ 0x1b4b60, 0x1b4bdc, 0x1b4c58, 0x1b4cd4, 0x1b4d50, 0x1b4dcc, 0x1b4e48, 0x1b4ec4,
+ 0x1b4f40, 0x1b4fbc, 0x1b5038, 0x1b50b4, 0x1b5130, 0x1b51ac, 0x1b5228, 0x1b52a4,
+ 0x1b5320, 0x1b539c, 0x1b5418, 0x1b5494, 0x1b5510, 0x1b558c, 0x1b5608, 0x1b5684,
+ 0x1b5700, 0x1b577c, 0x1b57f8, 0x1b5874, 0x1b58f0, 0x1b596c, 0x1b59e8, 0x1b5a64,
+ 0x1b5ae0, 0x1b5b5c, 0x1b5bd8, 0x1b5c54, 0x1b5cd0, 0x1b5d4c, 0x1b5dc8, 0x1b5e44,
+ 0x1b5ec0, 0x1b5f3c, 0x1b5fb8, 0x1b6034, 0x1b60b0, 0x1b612c, 0x1b61a8, 0x1b6224,
+ 0x1b62a0, 0x1b631c, 0x1b6398, 0x1b6414, 0x1b6490, 0x1b650c, 0x1b6588, 0x1b6604,
+ 0x1b6680, 0x1b66fc, 0x1b6778, 0x1b67f4, 0x1b6870, 0x1b68ec, 0x1b6968, 0x1b69e4,
+ 0x1b6a60, 0x1b6adc, 0x1b6b58, 0x1b6bd4, 0x1b6c50, 0x1b6ccc, 0x1b6d48, 0x1b6dc4,
+ 0x1b6e40, 0x1b6ebc, 0x1b6f38, 0x1b6fb4, 0x1b7030, 0x1b70ac, 0x1b7128, 0x1b71a4,
+ 0x1b7220, 0x1b729c, 0x1b7318, 0x1b7394, 0x1b7410, 0x1b748c, 0x1b7508, 0x1b7584,
+
+ 0x1b7600, 0x1b767c, 0x1b76f8, 0x1b779c, 0x1b7840, 0x1b78bc, 0x1b7938, 0x1b79dc,
+ 0x1b7a80, 0x1b7afc, 0x1b7b78, 0x1b7c1c, 0x1b7cc0, 0x1b7d3c, 0x1b7db8, 0x1b7e5c,
+ 0x1b7f00, 0x1b7f7c, 0x1b7ff8, 0x1b809c, 0x1b8140, 0x1b81bc, 0x1b8238, 0x1b82dc,
+ 0x1b8380, 0x1b83fc, 0x1b8478, 0x1b851c, 0x1b85c0, 0x1b863c, 0x1b86b8, 0x1b875c,
+ 0x1b8800, 0x1b887c, 0x1b88f8, 0x1b899c, 0x1b8a40, 0x1b8abc, 0x1b8b38, 0x1b8bdc,
+ 0x1b8c80, 0x1b8cfc, 0x1b8d78, 0x1b8e1c, 0x1b8ec0, 0x1b8f3c, 0x1b8fb8, 0x1b905c,
+ 0x1b9100, 0x1b917c, 0x1b91f8, 0x1b929c, 0x1b9340, 0x1b93bc, 0x1b9438, 0x1b94dc,
+ 0x1b9580, 0x1b95fc, 0x1b9678, 0x1b971c, 0x1b97c0, 0x1b983c, 0x1b98b8, 0x1b995c,
+ 0x1b9a00, 0x1b9a7c, 0x1b9af8, 0x1b9b9c, 0x1b9c40, 0x1b9cbc, 0x1b9d38, 0x1b9ddc,
+ 0x1b9e80, 0x1b9efc, 0x1b9f78, 0x1ba01c, 0x1ba0c0, 0x1ba13c, 0x1ba1b8, 0x1ba25c,
+ 0x1ba300, 0x1ba37c, 0x1ba3f8, 0x1ba49c, 0x1ba540, 0x1ba5bc, 0x1ba638, 0x1ba6dc,
+ 0x1ba780, 0x1ba7fc, 0x1ba878, 0x1ba91c, 0x1ba9c0, 0x1baa3c, 0x1baab8, 0x1bab5c,
+ 0x1bac00, 0x1bac7c, 0x1bacf8, 0x1bad9c, 0x1bae40, 0x1baebc, 0x1baf38, 0x1bafdc,
+ 0x1bb080, 0x1bb0fc, 0x1bb178, 0x1bb21c, 0x1bb2c0, 0x1bb33c, 0x1bb3b8, 0x1bb45c,
+ 0x1bb500, 0x1bb57c, 0x1bb5f8, 0x1bb69c, 0x1bb740, 0x1bb7bc, 0x1bb838, 0x1bb8dc,
+ 0x1bb980, 0x1bb9fc, 0x1bba78, 0x1bbb1c, 0x1bbbc0, 0x1bbc3c, 0x1bbcb8, 0x1bbd5c,
+
+ 0x1bbe00, 0x1bbe7c, 0x1bbef8, 0x1bbf74, 0x1bbff0, 0x1bc06c, 0x1bc0e8, 0x1bc164,
+ 0x1bc1e0, 0x1bc25c, 0x1bc2d8, 0x1bc354, 0x1bc3d0, 0x1bc44c, 0x1bc4c8, 0x1bc544,
+ 0x1bc5c0, 0x1bc63c, 0x1bc6b8, 0x1bc734, 0x1bc7b0, 0x1bc82c, 0x1bc8a8, 0x1bc924,
+ 0x1bc9a0, 0x1bca1c, 0x1bca98, 0x1bcb14, 0x1bcb90, 0x1bcc0c, 0x1bcc88, 0x1bcd04,
+ 0x1bcd80, 0x1bcdfc, 0x1bce78, 0x1bcef4, 0x1bcf70, 0x1bcfec, 0x1bd068, 0x1bd0e4,
+ 0x1bd160, 0x1bd1dc, 0x1bd258, 0x1bd2d4, 0x1bd350, 0x1bd3cc, 0x1bd448, 0x1bd4c4,
+ 0x1bd540, 0x1bd5bc, 0x1bd638, 0x1bd6b4, 0x1bd730, 0x1bd7ac, 0x1bd828, 0x1bd8a4,
+ 0x1bd920, 0x1bd99c, 0x1bda18, 0x1bda94, 0x1bdb10, 0x1bdb8c, 0x1bdc08, 0x1bdc84,
+ 0x1bdd00, 0x1bdd7c, 0x1bddf8, 0x1bde74, 0x1bdef0, 0x1bdf6c, 0x1bdfe8, 0x1be064,
+ 0x1be0e0, 0x1be15c, 0x1be1d8, 0x1be254, 0x1be2d0, 0x1be34c, 0x1be3c8, 0x1be444,
+ 0x1be4c0, 0x1be53c, 0x1be5b8, 0x1be634, 0x1be6b0, 0x1be72c, 0x1be7a8, 0x1be824,
+ 0x1be8a0, 0x1be91c, 0x1be998, 0x1bea14, 0x1bea90, 0x1beb0c, 0x1beb88, 0x1bec04,
+ 0x1bec80, 0x1becfc, 0x1bed78, 0x1bedf4, 0x1bee70, 0x1beeec, 0x1bef68, 0x1befe4,
+ 0x1bf060, 0x1bf0dc, 0x1bf158, 0x1bf1d4, 0x1bf250, 0x1bf2cc, 0x1bf348, 0x1bf3c4,
+ 0x1bf440, 0x1bf4bc, 0x1bf538, 0x1bf5b4, 0x1bf630, 0x1bf6ac, 0x1bf728, 0x1bf7a4,
+ 0x1bf820, 0x1bf89c, 0x1bf918, 0x1bf994, 0x1bfa10, 0x1bfa8c, 0x1bfb08, 0x1bfb84,
+
+ 0x1bfc00, 0x1bfc7c, 0x1bfcf8, 0x1bfd9c, 0x1bfe40, 0x1bfebc, 0x1bff38, 0x1bffdc,
+ 0x1c0080, 0x1c00fc, 0x1c0178, 0x1c021c, 0x1c02c0, 0x1c033c, 0x1c03b8, 0x1c045c,
+ 0x1c0500, 0x1c057c, 0x1c05f8, 0x1c069c, 0x1c0740, 0x1c07bc, 0x1c0838, 0x1c08dc,
+ 0x1c0980, 0x1c09fc, 0x1c0a78, 0x1c0b1c, 0x1c0bc0, 0x1c0c3c, 0x1c0cb8, 0x1c0d5c,
+ 0x1c0e00, 0x1c0e7c, 0x1c0ef8, 0x1c0f9c, 0x1c1040, 0x1c10bc, 0x1c1138, 0x1c11dc,
+ 0x1c1280, 0x1c12fc, 0x1c1378, 0x1c141c, 0x1c14c0, 0x1c153c, 0x1c15b8, 0x1c165c,
+ 0x1c1700, 0x1c177c, 0x1c17f8, 0x1c189c, 0x1c1940, 0x1c19bc, 0x1c1a38, 0x1c1adc,
+ 0x1c1b80, 0x1c1bfc, 0x1c1c78, 0x1c1d1c, 0x1c1dc0, 0x1c1e3c, 0x1c1eb8, 0x1c1f5c,
+ 0x1c2000, 0x1c207c, 0x1c20f8, 0x1c219c, 0x1c2240, 0x1c22bc, 0x1c2338, 0x1c23dc,
+ 0x1c2480, 0x1c24fc, 0x1c2578, 0x1c261c, 0x1c26c0, 0x1c273c, 0x1c27b8, 0x1c285c,
+ 0x1c2900, 0x1c297c, 0x1c29f8, 0x1c2a9c, 0x1c2b40, 0x1c2bbc, 0x1c2c38, 0x1c2cdc,
+ 0x1c2d80, 0x1c2dfc, 0x1c2e78, 0x1c2f1c, 0x1c2fc0, 0x1c303c, 0x1c30b8, 0x1c315c,
+ 0x1c3200, 0x1c327c, 0x1c32f8, 0x1c339c, 0x1c3440, 0x1c34bc, 0x1c3538, 0x1c35dc,
+ 0x1c3680, 0x1c36fc, 0x1c3778, 0x1c381c, 0x1c38c0, 0x1c393c, 0x1c39b8, 0x1c3a5c,
+ 0x1c3b00, 0x1c3b7c, 0x1c3bf8, 0x1c3c9c, 0x1c3d40, 0x1c3dbc, 0x1c3e38, 0x1c3edc,
+ 0x1c3f80, 0x1c3ffc, 0x1c4078, 0x1c411c, 0x1c41c0, 0x1c423c, 0x1c42b8, 0x1c435c,
+
+ 0x1c4400, 0x1c447c, 0x1c44f8, 0x1c4574, 0x1c45f0, 0x1c466c, 0x1c46e8, 0x1c4764,
+ 0x1c47e0, 0x1c485c, 0x1c48d8, 0x1c4954, 0x1c49d0, 0x1c4a4c, 0x1c4ac8, 0x1c4b44,
+ 0x1c4bc0, 0x1c4c3c, 0x1c4cb8, 0x1c4d34, 0x1c4db0, 0x1c4e2c, 0x1c4ea8, 0x1c4f24,
+ 0x1c4fa0, 0x1c501c, 0x1c5098, 0x1c5114, 0x1c5190, 0x1c520c, 0x1c5288, 0x1c5304,
+ 0x1c5380, 0x1c53fc, 0x1c5478, 0x1c54f4, 0x1c5570, 0x1c55ec, 0x1c5668, 0x1c56e4,
+ 0x1c5760, 0x1c57dc, 0x1c5858, 0x1c58d4, 0x1c5950, 0x1c59cc, 0x1c5a48, 0x1c5ac4,
+ 0x1c5b40, 0x1c5bbc, 0x1c5c38, 0x1c5cb4, 0x1c5d30, 0x1c5dac, 0x1c5e28, 0x1c5ea4,
+ 0x1c5f20, 0x1c5f9c, 0x1c6018, 0x1c6094, 0x1c6110, 0x1c618c, 0x1c6208, 0x1c6284,
+ 0x1c6300, 0x1c637c, 0x1c63f8, 0x1c6474, 0x1c64f0, 0x1c656c, 0x1c65e8, 0x1c6664,
+ 0x1c66e0, 0x1c675c, 0x1c67d8, 0x1c6854, 0x1c68d0, 0x1c694c, 0x1c69c8, 0x1c6a44,
+ 0x1c6ac0, 0x1c6b3c, 0x1c6bb8, 0x1c6c34, 0x1c6cb0, 0x1c6d2c, 0x1c6da8, 0x1c6e24,
+ 0x1c6ea0, 0x1c6f1c, 0x1c6f98, 0x1c7014, 0x1c7090, 0x1c710c, 0x1c7188, 0x1c7204,
+ 0x1c7280, 0x1c72fc, 0x1c7378, 0x1c73f4, 0x1c7470, 0x1c74ec, 0x1c7568, 0x1c75e4,
+ 0x1c7660, 0x1c76dc, 0x1c7758, 0x1c77d4, 0x1c7850, 0x1c78cc, 0x1c7948, 0x1c79c4,
+ 0x1c7a40, 0x1c7abc, 0x1c7b38, 0x1c7bb4, 0x1c7c30, 0x1c7cac, 0x1c7d28, 0x1c7da4,
+ 0x1c7e20, 0x1c7e9c, 0x1c7f18, 0x1c7f94, 0x1c8010, 0x1c808c, 0x1c8108, 0x1c8184,
+
+ 0x1c8200, 0x1c827c, 0x1c82f8, 0x1c839c, 0x1c8440, 0x1c84bc, 0x1c8538, 0x1c85dc,
+ 0x1c8680, 0x1c86fc, 0x1c8778, 0x1c881c, 0x1c88c0, 0x1c893c, 0x1c89b8, 0x1c8a5c,
+ 0x1c8b00, 0x1c8b7c, 0x1c8bf8, 0x1c8c9c, 0x1c8d40, 0x1c8dbc, 0x1c8e38, 0x1c8edc,
+ 0x1c8f80, 0x1c8ffc, 0x1c9078, 0x1c911c, 0x1c91c0, 0x1c923c, 0x1c92b8, 0x1c935c,
+ 0x1c9400, 0x1c947c, 0x1c94f8, 0x1c959c, 0x1c9640, 0x1c96bc, 0x1c9738, 0x1c97dc,
+ 0x1c9880, 0x1c98fc, 0x1c9978, 0x1c9a1c, 0x1c9ac0, 0x1c9b3c, 0x1c9bb8, 0x1c9c5c,
+ 0x1c9d00, 0x1c9d7c, 0x1c9df8, 0x1c9e9c, 0x1c9f40, 0x1c9fbc, 0x1ca038, 0x1ca0dc,
+ 0x1ca180, 0x1ca1fc, 0x1ca278, 0x1ca31c, 0x1ca3c0, 0x1ca43c, 0x1ca4b8, 0x1ca55c,
+ 0x1ca600, 0x1ca67c, 0x1ca6f8, 0x1ca79c, 0x1ca840, 0x1ca8bc, 0x1ca938, 0x1ca9dc,
+ 0x1caa80, 0x1caafc, 0x1cab78, 0x1cac1c, 0x1cacc0, 0x1cad3c, 0x1cadb8, 0x1cae5c,
+ 0x1caf00, 0x1caf7c, 0x1caff8, 0x1cb09c, 0x1cb140, 0x1cb1bc, 0x1cb238, 0x1cb2dc,
+ 0x1cb380, 0x1cb3fc, 0x1cb478, 0x1cb51c, 0x1cb5c0, 0x1cb63c, 0x1cb6b8, 0x1cb75c,
+ 0x1cb800, 0x1cb87c, 0x1cb8f8, 0x1cb99c, 0x1cba40, 0x1cbabc, 0x1cbb38, 0x1cbbdc,
+ 0x1cbc80, 0x1cbcfc, 0x1cbd78, 0x1cbe1c, 0x1cbec0, 0x1cbf3c, 0x1cbfb8, 0x1cc05c,
+ 0x1cc100, 0x1cc17c, 0x1cc1f8, 0x1cc29c, 0x1cc340, 0x1cc3bc, 0x1cc438, 0x1cc4dc,
+ 0x1cc580, 0x1cc5fc, 0x1cc678, 0x1cc71c, 0x1cc7c0, 0x1cc83c, 0x1cc8b8, 0x1cc95c,
+
+ 0x1cca00, 0x1cca7c, 0x1ccaf8, 0x1ccb74, 0x1ccbf0, 0x1ccc6c, 0x1ccce8, 0x1ccd64,
+ 0x1ccde0, 0x1cce5c, 0x1cced8, 0x1ccf54, 0x1ccfd0, 0x1cd04c, 0x1cd0c8, 0x1cd144,
+ 0x1cd1c0, 0x1cd23c, 0x1cd2b8, 0x1cd334, 0x1cd3b0, 0x1cd42c, 0x1cd4a8, 0x1cd524,
+ 0x1cd5a0, 0x1cd61c, 0x1cd698, 0x1cd714, 0x1cd790, 0x1cd80c, 0x1cd888, 0x1cd904,
+ 0x1cd980, 0x1cd9fc, 0x1cda78, 0x1cdaf4, 0x1cdb70, 0x1cdbec, 0x1cdc68, 0x1cdce4,
+ 0x1cdd60, 0x1cdddc, 0x1cde58, 0x1cded4, 0x1cdf50, 0x1cdfcc, 0x1ce048, 0x1ce0c4,
+ 0x1ce140, 0x1ce1bc, 0x1ce238, 0x1ce2b4, 0x1ce330, 0x1ce3ac, 0x1ce428, 0x1ce4a4,
+ 0x1ce520, 0x1ce59c, 0x1ce618, 0x1ce694, 0x1ce710, 0x1ce78c, 0x1ce808, 0x1ce884,
+ 0x1ce900, 0x1ce97c, 0x1ce9f8, 0x1cea74, 0x1ceaf0, 0x1ceb6c, 0x1cebe8, 0x1cec64,
+ 0x1cece0, 0x1ced5c, 0x1cedd8, 0x1cee54, 0x1ceed0, 0x1cef4c, 0x1cefc8, 0x1cf044,
+ 0x1cf0c0, 0x1cf13c, 0x1cf1b8, 0x1cf234, 0x1cf2b0, 0x1cf32c, 0x1cf3a8, 0x1cf424,
+ 0x1cf4a0, 0x1cf51c, 0x1cf598, 0x1cf614, 0x1cf690, 0x1cf70c, 0x1cf788, 0x1cf804,
+ 0x1cf880, 0x1cf8fc, 0x1cf978, 0x1cf9f4, 0x1cfa70, 0x1cfaec, 0x1cfb68, 0x1cfbe4,
+ 0x1cfc60, 0x1cfcdc, 0x1cfd58, 0x1cfdd4, 0x1cfe50, 0x1cfecc, 0x1cff48, 0x1cffc4,
+ 0x1d0040, 0x1d00bc, 0x1d0138, 0x1d01b4, 0x1d0230, 0x1d02ac, 0x1d0328, 0x1d03a4,
+ 0x1d0420, 0x1d049c, 0x1d0518, 0x1d0594, 0x1d0610, 0x1d068c, 0x1d0708, 0x1d0784,
+
+ 0x1d0800, 0x1d087c, 0x1d08f8, 0x1d099c, 0x1d0a40, 0x1d0abc, 0x1d0b38, 0x1d0bdc,
+ 0x1d0c80, 0x1d0cfc, 0x1d0d78, 0x1d0e1c, 0x1d0ec0, 0x1d0f3c, 0x1d0fb8, 0x1d105c,
+ 0x1d1100, 0x1d117c, 0x1d11f8, 0x1d129c, 0x1d1340, 0x1d13bc, 0x1d1438, 0x1d14dc,
+ 0x1d1580, 0x1d15fc, 0x1d1678, 0x1d171c, 0x1d17c0, 0x1d183c, 0x1d18b8, 0x1d195c,
+ 0x1d1a00, 0x1d1a7c, 0x1d1af8, 0x1d1b9c, 0x1d1c40, 0x1d1cbc, 0x1d1d38, 0x1d1ddc,
+ 0x1d1e80, 0x1d1efc, 0x1d1f78, 0x1d201c, 0x1d20c0, 0x1d213c, 0x1d21b8, 0x1d225c,
+ 0x1d2300, 0x1d237c, 0x1d23f8, 0x1d249c, 0x1d2540, 0x1d25bc, 0x1d2638, 0x1d26dc,
+ 0x1d2780, 0x1d27fc, 0x1d2878, 0x1d291c, 0x1d29c0, 0x1d2a3c, 0x1d2ab8, 0x1d2b5c,
+ 0x1d2c00, 0x1d2c7c, 0x1d2cf8, 0x1d2d9c, 0x1d2e40, 0x1d2ebc, 0x1d2f38, 0x1d2fdc,
+ 0x1d3080, 0x1d30fc, 0x1d3178, 0x1d321c, 0x1d32c0, 0x1d333c, 0x1d33b8, 0x1d345c,
+ 0x1d3500, 0x1d357c, 0x1d35f8, 0x1d369c, 0x1d3740, 0x1d37bc, 0x1d3838, 0x1d38dc,
+ 0x1d3980, 0x1d39fc, 0x1d3a78, 0x1d3b1c, 0x1d3bc0, 0x1d3c3c, 0x1d3cb8, 0x1d3d5c,
+ 0x1d3e00, 0x1d3e7c, 0x1d3ef8, 0x1d3f9c, 0x1d4040, 0x1d40bc, 0x1d4138, 0x1d41dc,
+ 0x1d4280, 0x1d42fc, 0x1d4378, 0x1d441c, 0x1d44c0, 0x1d453c, 0x1d45b8, 0x1d465c,
+ 0x1d4700, 0x1d477c, 0x1d47f8, 0x1d489c, 0x1d4940, 0x1d49bc, 0x1d4a38, 0x1d4adc,
+ 0x1d4b80, 0x1d4bfc, 0x1d4c78, 0x1d4d1c, 0x1d4dc0, 0x1d4e3c, 0x1d4eb8, 0x1d4f5c,
+ 0x1d5000, 0x1d507c, 0x1d50f8, 0x000000, 0x1d513c, 0x1d51b8, 0x000000, 0x000000,
+ 0x1d5234, 0x1d52b0, 0x000000, 0x000000, 0x1d532c, 0x1d53a8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d5424, 0x1d54a0, 0x000000, 0x000000, 0x1d551c, 0x1d5598, 0x000000, 0x000000,
+ 0x1d5614, 0x1d5690, 0x000000, 0x000000, 0x1d570c, 0x1d5788, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d5804, 0x1d5880, 0x000000, 0x000000, 0x1d58fc, 0x1d5978, 0x000000, 0x000000,
+ 0x1d59f4, 0x1d5a70, 0x000000, 0x000000, 0x1d5aec, 0x1d5b68, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d5be4, 0x1d5c60, 0x000000, 0x000000, 0x1d5cdc, 0x1d5d58, 0x000000, 0x000000,
+ 0x1d5dd4, 0x1d5e50, 0x000000, 0x000000, 0x1d5ecc, 0x1d5f48, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d5fc4, 0x1d6040, 0x000000, 0x000000, 0x1d60bc, 0x1d6138, 0x000000, 0x000000,
+ 0x1d61b4, 0x1d6230, 0x000000, 0x000000, 0x1d62ac, 0x1d6328, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d63a4, 0x1d6420, 0x000000, 0x000000, 0x1d649c, 0x1d6518, 0x000000, 0x000000,
+ 0x1d6594, 0x1d6610, 0x000000, 0x000000, 0x1d668c, 0x1d6708, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d6784, 0x1d6800, 0x000000, 0x000000, 0x1d687c, 0x1d68f8, 0x000000, 0x000000,
+ 0x1d6974, 0x1d69f0, 0x000000, 0x000000, 0x1d6a6c, 0x1d6ae8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d6b64, 0x1d6be0, 0x000000, 0x000000, 0x1d6c5c, 0x1d6cd8, 0x000000, 0x000000,
+ 0x1d6d54, 0x1d6dd0, 0x000000, 0x000000, 0x1d6e4c, 0x1d6ec8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d6f44, 0x1d6fe8, 0x000000, 0x000000, 0x1d7064, 0x1d7108, 0x000000, 0x000000,
+ 0x1d7184, 0x1d7228, 0x000000, 0x000000, 0x1d72a4, 0x1d7348, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d73c4, 0x1d7468, 0x000000, 0x000000, 0x1d74e4, 0x1d7588, 0x000000, 0x000000,
+ 0x1d7604, 0x1d76a8, 0x000000, 0x000000, 0x1d7724, 0x1d77c8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d7844, 0x1d78e8, 0x000000, 0x000000, 0x1d7964, 0x1d7a08, 0x000000, 0x000000,
+ 0x1d7a84, 0x1d7b28, 0x000000, 0x000000, 0x1d7ba4, 0x1d7c48, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d7cc4, 0x1d7d68, 0x000000, 0x000000, 0x1d7de4, 0x1d7e88, 0x000000, 0x000000,
+ 0x1d7f04, 0x1d7fa8, 0x000000, 0x000000, 0x1d8024, 0x1d80c8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d8144, 0x1d81e8, 0x000000, 0x000000, 0x1d8264, 0x1d8308, 0x000000, 0x000000,
+ 0x1d8384, 0x1d8428, 0x000000, 0x000000, 0x1d84a4, 0x1d8548, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d85c4, 0x1d8668, 0x000000, 0x000000, 0x1d86e4, 0x1d8788, 0x000000, 0x000000,
+ 0x1d8804, 0x1d88a8, 0x000000, 0x000000, 0x1d8924, 0x1d89c8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d8a44, 0x1d8ae8, 0x000000, 0x000000, 0x1d8b64, 0x1d8c08, 0x000000, 0x000000,
+ 0x1d8c84, 0x1d8d28, 0x000000, 0x000000, 0x1d8da4, 0x1d8e48, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d8ec4, 0x1d8f68, 0x000000, 0x000000, 0x1d8fe4, 0x1d9088, 0x000000, 0x000000,
+ 0x1d9104, 0x1d91a8, 0x000000, 0x000000, 0x1d9224, 0x1d92c8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d9344, 0x1d93c0, 0x000000, 0x000000, 0x1d943c, 0x1d94b8, 0x000000, 0x000000,
+ 0x1d9534, 0x1d95b0, 0x000000, 0x000000, 0x1d962c, 0x1d96a8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d9724, 0x1d97a0, 0x000000, 0x000000, 0x1d981c, 0x1d9898, 0x000000, 0x000000,
+ 0x1d9914, 0x1d9990, 0x000000, 0x000000, 0x1d9a0c, 0x1d9a88, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d9b04, 0x1d9b80, 0x000000, 0x000000, 0x1d9bfc, 0x1d9c78, 0x000000, 0x000000,
+ 0x1d9cf4, 0x1d9d70, 0x000000, 0x000000, 0x1d9dec, 0x1d9e68, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1d9ee4, 0x1d9f60, 0x000000, 0x000000, 0x1d9fdc, 0x1da058, 0x000000, 0x000000,
+ 0x1da0d4, 0x1da150, 0x000000, 0x000000, 0x1da1cc, 0x1da248, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1da2c4, 0x1da340, 0x000000, 0x000000, 0x1da3bc, 0x1da438, 0x000000, 0x000000,
+ 0x1da4b4, 0x1da530, 0x000000, 0x000000, 0x1da5ac, 0x1da628, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1da6a4, 0x1da720, 0x000000, 0x000000, 0x1da79c, 0x1da818, 0x000000, 0x000000,
+ 0x1da894, 0x1da910, 0x000000, 0x000000, 0x1da98c, 0x1daa08, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1daa84, 0x1dab00, 0x000000, 0x000000, 0x1dab7c, 0x1dabf8, 0x000000, 0x000000,
+ 0x1dac74, 0x1dacf0, 0x000000, 0x000000, 0x1dad6c, 0x1dade8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1dae64, 0x1daee0, 0x000000, 0x000000, 0x1daf5c, 0x1dafd8, 0x000000, 0x000000,
+ 0x1db054, 0x1db0d0, 0x000000, 0x000000, 0x1db14c, 0x1db1c8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1db244, 0x1db2e8, 0x000000, 0x000000, 0x1db364, 0x1db408, 0x000000, 0x000000,
+ 0x1db484, 0x1db528, 0x000000, 0x000000, 0x1db5a4, 0x1db648, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1db6c4, 0x1db768, 0x000000, 0x000000, 0x1db7e4, 0x1db888, 0x000000, 0x000000,
+ 0x1db904, 0x1db9a8, 0x000000, 0x000000, 0x1dba24, 0x1dbac8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1dbb44, 0x1dbbe8, 0x000000, 0x000000, 0x1dbc64, 0x1dbd08, 0x000000, 0x000000,
+ 0x1dbd84, 0x1dbe28, 0x000000, 0x000000, 0x1dbea4, 0x1dbf48, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1dbfc4, 0x1dc068, 0x000000, 0x000000, 0x1dc0e4, 0x1dc188, 0x000000, 0x000000,
+ 0x1dc204, 0x1dc2a8, 0x000000, 0x000000, 0x1dc324, 0x1dc3c8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1dc444, 0x1dc4e8, 0x000000, 0x000000, 0x1dc564, 0x1dc608, 0x000000, 0x000000,
+ 0x1dc684, 0x1dc728, 0x000000, 0x000000, 0x1dc7a4, 0x1dc848, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1dc8c4, 0x1dc968, 0x000000, 0x000000, 0x1dc9e4, 0x1dca88, 0x000000, 0x000000,
+ 0x1dcb04, 0x1dcba8, 0x000000, 0x000000, 0x1dcc24, 0x1dccc8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1dcd44, 0x1dcde8, 0x000000, 0x000000, 0x1dce64, 0x1dcf08, 0x000000, 0x000000,
+ 0x1dcf84, 0x1dd028, 0x000000, 0x000000, 0x1dd0a4, 0x1dd148, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x1dd1c4, 0x1dd268, 0x000000, 0x000000, 0x1dd2e4, 0x1dd388, 0x000000, 0x000000,
+ 0x1dd404, 0x1dd4a8, 0x000000, 0x000000, 0x1dd524, 0x1dd5c8, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+ 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000
+};
diff --git a/src/mame/machine/pitnrun.c b/src/mame/machine/pitnrun.c
new file mode 100644
index 00000000000..570d8e3a04d
--- /dev/null
+++ b/src/mame/machine/pitnrun.c
@@ -0,0 +1,158 @@
+/***************************************************************************
+
+ Pit&Run
+
+ Based on TaitsoSJ driver
+ 68705 has access to Z80 memory space
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6805/m6805.h"
+
+
+static UINT8 fromz80,toz80;
+static int zaccept,zready;
+
+MACHINE_RESET( pitnrun )
+{
+ zaccept = 1;
+ zready = 0;
+ cpunum_set_input_line(2,0,CLEAR_LINE);
+}
+
+static TIMER_CALLBACK( pitnrun_mcu_real_data_r )
+{
+ zaccept = 1;
+}
+
+READ8_HANDLER( pitnrun_mcu_data_r )
+{
+ timer_call_after_resynch(0,pitnrun_mcu_real_data_r);
+ return toz80;
+}
+
+static TIMER_CALLBACK( pitnrun_mcu_real_data_w )
+{
+ zready = 1;
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+ fromz80 = param;
+}
+
+WRITE8_HANDLER( pitnrun_mcu_data_w )
+{
+ timer_call_after_resynch(data,pitnrun_mcu_real_data_w);
+}
+
+READ8_HANDLER( pitnrun_mcu_status_r )
+{
+ /* mcu synchronization */
+ cpu_yielduntil_time (ATTOTIME_IN_USEC(5));
+ /* bit 0 = the 68705 has read data from the Z80 */
+ /* bit 1 = the 68705 has written data for the Z80 */
+ return ~((zready << 1) | (zaccept << 0));
+}
+
+static UINT8 portA_in,portA_out;
+
+READ8_HANDLER( pitnrun_68705_portA_r )
+{
+ return portA_in;
+}
+
+WRITE8_HANDLER( pitnrun_68705_portA_w )
+{
+ portA_out = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 W !68INTRQ
+ * 1 W !68LRD (enables latch which holds command from the Z80)
+ * 2 W !68LWR (loads the latch which holds data for the Z80, and sets a
+ * status bit so the Z80 knows there's data waiting)
+ * 3 W to Z80 !BUSRQ (aka !WAIT) pin
+ * 4 W !68WRITE (triggers write to main Z80 memory area )
+ * 5 W !68READ (triggers read from main Z80 memory area )
+ * 6 W !LAL (loads the latch which holds the low 8 bits of the address of
+ * the main Z80 memory location to access)
+ * 7 W !UAL (loads the latch which holds the high 8 bits of the address of
+ * the main Z80 memory location to access)
+ */
+
+READ8_HANDLER( pitnrun_68705_portB_r )
+{
+ return 0xff;
+}
+
+static int address;
+
+static TIMER_CALLBACK( pitnrun_mcu_data_real_r )
+{
+ zready = 0;
+}
+
+static TIMER_CALLBACK( pitnrun_mcu_status_real_w )
+{
+ toz80 = param;
+ zaccept = 0;
+}
+
+WRITE8_HANDLER( pitnrun_68705_portB_w )
+{
+ if (~data & 0x02)
+ {
+ /* 68705 is going to read data from the Z80 */
+ timer_call_after_resynch(0,pitnrun_mcu_data_real_r);
+ cpunum_set_input_line(2,0,CLEAR_LINE);
+ portA_in = fromz80;
+ }
+ if (~data & 0x04)
+ {
+ /* 68705 is writing data for the Z80 */
+ timer_call_after_resynch(portA_out,pitnrun_mcu_status_real_w);
+ }
+ if (~data & 0x10)
+ {
+ memory_set_context(0);
+ program_write_byte(address, portA_out);
+ memory_set_context(2);
+ }
+ if (~data & 0x20)
+ {
+ memory_set_context(0);
+ portA_in = program_read_byte(address);
+ memory_set_context(2);
+ }
+ if (~data & 0x40)
+ {
+ address = (address & 0xff00) | portA_out;
+ }
+ if (~data & 0x80)
+ {
+ address = (address & 0x00ff) | (portA_out << 8);
+ }
+}
+
+/*
+ * Port C connections:
+ *
+ * 0 R ZREADY (1 when the Z80 has written a command in the latch)
+ * 1 R ZACCEPT (1 when the Z80 has read data from the latch)
+ * 2 R from Z80 !BUSAK pin
+ * 3 R 68INTAK (goes 0 when the interrupt request done with 68INTRQ
+ * passes through)
+ */
+
+READ8_HANDLER( pitnrun_68705_portC_r )
+{
+ return (zready << 0) | (zaccept << 1);
+}
+
+
+
diff --git a/src/mame/machine/playch10.c b/src/mame/machine/playch10.c
new file mode 100644
index 00000000000..ca9f98cf7fb
--- /dev/null
+++ b/src/mame/machine/playch10.c
@@ -0,0 +1,905 @@
+#include "driver.h"
+#include "video/ppu2c0x.h"
+#include "machine/rp5h01.h"
+
+/* Globals */
+int pc10_sdcs; /* ShareD Chip Select */
+int pc10_dispmask; /* Display Mask */
+int pc10_nmi_enable; /* nmi enable */
+int pc10_dog_di; /* watchdog disable */
+int pc10_int_detect; /* interrupt detect */
+static int pc10_gun_controller;
+int pc10_game_mode; /* Used in Single monitor version to display Game or PPU */
+int pc10_dispmask_old;
+
+/* Locals */
+static int cart_sel;
+static int cntrl_mask;
+static int input_latch[2];
+static int mirroring;
+
+static int MMC2_bank[4], MMC2_bank_latch[2];
+
+/*************************************
+ *
+ * Init machine
+ *
+ *************************************/
+MACHINE_RESET( pc10 )
+{
+ /* initialize latches and flip-flops */
+ pc10_nmi_enable = pc10_dog_di = pc10_dispmask = pc10_sdcs = pc10_int_detect = 0;
+
+ pc10_game_mode = pc10_dispmask_old = 0;
+
+ cart_sel = 0;
+ cntrl_mask = 1;
+
+ input_latch[0] = input_latch[1] = 0;
+
+ /* variables used only in MMC2 game (mapper 9) */
+ MMC2_bank[0] = MMC2_bank[1] = MMC2_bank[2] = MMC2_bank[3] = 0;
+ MMC2_bank_latch[0] = MMC2_bank_latch[1] = 0xfe;
+
+ /* reset the security chip */
+ RP5H01_enable_w( 0, 0 );
+ RP5H01_0_reset_w( 0, 0 );
+ RP5H01_0_reset_w( 0, 1 );
+ RP5H01_enable_w( 0, 1 );
+
+ /* reset the ppu */
+ ppu2c0x_reset( 0, /* video_screen_get_scan_period(0) * */ 1 );
+
+ ppu2c0x_set_mirroring( 0, mirroring );
+}
+
+/*************************************
+ *
+ * BIOS ports handling
+ *
+ *************************************/
+READ8_HANDLER( pc10_port_0_r )
+{
+ return readinputport( 0 ) | ( ( ~pc10_int_detect & 1 ) << 3 );
+}
+
+WRITE8_HANDLER( pc10_SDCS_w )
+{
+ /*
+ Hooked to CLR on LS194A - Sheet 2, bottom left.
+ Drives character and color code to 0.
+ It's used to keep the screen black during redraws.
+ Also hooked to the video sram. Prevent writes.
+ */
+ pc10_sdcs = ~data & 1;
+}
+
+WRITE8_HANDLER( pc10_CNTRLMASK_w )
+{
+ cntrl_mask = ~data & 1;
+}
+
+WRITE8_HANDLER( pc10_DISPMASK_w )
+{
+ pc10_dispmask = ~data & 1;
+}
+
+WRITE8_HANDLER( pc10_SOUNDMASK_w )
+{
+ /* should mute the APU - unimplemented yet */
+}
+
+WRITE8_HANDLER( pc10_NMIENABLE_w )
+{
+ pc10_nmi_enable = data & 1;
+}
+
+WRITE8_HANDLER( pc10_DOGDI_w )
+{
+ pc10_dog_di = data & 1;
+}
+
+WRITE8_HANDLER( pc10_GAMERES_w )
+{
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ( data & 1 ) ? CLEAR_LINE : ASSERT_LINE );
+}
+
+WRITE8_HANDLER( pc10_GAMESTOP_w )
+{
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ( data & 1 ) ? CLEAR_LINE : ASSERT_LINE );
+}
+
+WRITE8_HANDLER( pc10_PPURES_w )
+{
+ if ( data & 1 )
+ ppu2c0x_reset( 0, /* video_screen_get_scan_period(0) * */ 1 );
+}
+
+READ8_HANDLER( pc10_detectclr_r )
+{
+ pc10_int_detect = 0;
+
+ return 0;
+}
+
+WRITE8_HANDLER( pc10_CARTSEL_w )
+{
+ cart_sel &= ~( 1 << offset );
+ cart_sel |= ( data & 1 ) << offset;
+}
+
+
+/*************************************
+ *
+ * RP5H01 handling
+ *
+ *************************************/
+READ8_HANDLER( pc10_prot_r )
+{
+ int data = 0xe7;
+
+ /* we only support a single cart connected at slot 0 */
+ if ( cart_sel == 0 )
+ {
+ RP5H01_0_enable_w( 0, 0 );
+ data |= ( ( ~RP5H01_counter_r( 0 ) ) << 4 ) & 0x10; /* D4 */
+ data |= ( ( RP5H01_data_r( 0 ) ) << 3 ) & 0x08; /* D3 */
+ RP5H01_0_enable_w( 0, 1 );
+ }
+ return data;
+}
+
+WRITE8_HANDLER( pc10_prot_w )
+{
+ /* we only support a single cart connected at slot 0 */
+ if ( cart_sel == 0 )
+ {
+ RP5H01_0_enable_w( 0, 0 );
+ RP5H01_0_test_w( 0, data & 0x10 ); /* D4 */
+ RP5H01_0_clock_w( 0, data & 0x08 ); /* D3 */
+ RP5H01_0_reset_w( 0, ~data & 0x01 ); /* D0 */
+ RP5H01_0_enable_w( 0, 1 );
+
+ /* this thing gets dense at some point */
+ /* it wants to jump and execute an opcode at $ffff, wich */
+ /* is the actual protection memory area */
+ /* setting the whole 0x2000 region every time is a waste */
+ /* so we just set $ffff with the current value */
+ memory_region( REGION_CPU1 )[0xffff] = pc10_prot_r(0);
+ }
+}
+
+
+/*************************************
+ *
+ * Input Ports
+ *
+ *************************************/
+WRITE8_HANDLER( pc10_in0_w )
+{
+ /* Toggling bit 0 high then low resets both controllers */
+ if ( data & 1 )
+ return;
+
+ /* load up the latches */
+ input_latch[0] = readinputport( 3 );
+ input_latch[1] = readinputport( 4 );
+
+ /* apply any masking from the BIOS */
+ if ( cntrl_mask )
+ {
+ /* mask out select and start */
+ input_latch[0] &= ~0x0c;
+ }
+}
+
+READ8_HANDLER( pc10_in0_r )
+{
+ int ret = ( input_latch[0] ) & 1;
+
+ /* shift */
+ input_latch[0] >>= 1;
+
+ /* some games expect bit 6 to be set because the last entry on the data bus shows up */
+ /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */
+ ret |= 0x40;
+
+ return ret;
+}
+
+READ8_HANDLER( pc10_in1_r )
+{
+ int ret = ( input_latch[1] ) & 1;
+
+ /* shift */
+ input_latch[1] >>= 1;
+
+ /* do the gun thing */
+ if ( pc10_gun_controller )
+ {
+ int trigger = readinputport( 3 );
+ int x = readinputport( 5 );
+ int y = readinputport( 6 );
+ UINT32 pix, color_base;
+ const pen_t *pens = Machine->pens;
+
+ /* no sprite hit (yet) */
+ ret |= 0x08;
+
+ /* get the pixel at the gun position */
+ pix = ppu2c0x_get_pixel( 0, x, y );
+
+ /* get the color base from the ppu */
+ color_base = ppu2c0x_get_colorbase( 0 );
+
+ /* look at the screen and see if the cursor is over a bright pixel */
+ if ( ( pix == pens[color_base+0x20] ) || ( pix == pens[color_base+0x30] ) ||
+ ( pix == pens[color_base+0x33] ) || ( pix == pens[color_base+0x34] ) )
+ {
+ ret &= ~0x08; /* sprite hit */
+ }
+
+ /* now, add the trigger if not masked */
+ if ( !cntrl_mask )
+ {
+ ret |= ( trigger & 2 ) << 3;
+ }
+ }
+
+ /* some games expect bit 6 to be set because the last entry on the data bus shows up */
+ /* in the unused upper 3 bits, so typically a read from $4016 leaves 0x40 there. */
+ ret |= 0x40;
+
+ return ret;
+}
+
+/* RP5H01 interface */
+static struct RP5H01_interface rp5h01_interface =
+{
+ 1,
+ { REGION_USER1 },
+ { 0 }
+};
+
+/*************************************
+ *
+ * Common init for all games
+ *
+ *************************************/
+DRIVER_INIT( playch10 )
+{
+ /* initialize the security chip */
+ if ( RP5H01_init( &rp5h01_interface ) )
+ {
+ fatalerror("rp5h01_interface initualization failed");
+ }
+
+ /* set the controller to default */
+ pc10_gun_controller = 0;
+
+ /* default mirroring */
+ mirroring = PPU_MIRROR_NONE;
+}
+
+/**********************************************************************************
+ *
+ * Game and Board-specific initialization
+ *
+ **********************************************************************************/
+
+/* Gun games */
+
+DRIVER_INIT( pc_gun )
+{
+ /* common init */
+ driver_init_playch10(machine);
+
+ /* set the control type */
+ pc10_gun_controller = 1;
+}
+
+
+/* Horizontal mirroring */
+
+DRIVER_INIT( pc_hrz )
+{
+ /* common init */
+ driver_init_playch10(machine);
+
+ /* setup mirroring */
+ mirroring = PPU_MIRROR_HORZ;
+}
+
+/* MMC1 mapper, used by D and F boards */
+
+static int mmc1_shiftreg;
+static int mmc1_shiftcount;
+static int mmc1_rom_mask;
+
+static WRITE8_HANDLER( mmc1_rom_switch_w )
+{
+ /* basically, a MMC1 mapper from the nes */
+ static int size16k, switchlow, vrom4k;
+
+ int reg = ( offset >> 13 );
+
+ /* reset mapper */
+ if ( data & 0x80 )
+ {
+ mmc1_shiftreg = mmc1_shiftcount = 0;
+
+ size16k = 1;
+ switchlow = 1;
+ vrom4k = 0;
+
+ return;
+ }
+
+ /* see if we need to clock in data */
+ if ( mmc1_shiftcount < 5 )
+ {
+ mmc1_shiftreg >>= 1;
+ mmc1_shiftreg |= ( data & 1 ) << 4;
+ mmc1_shiftcount++;
+ }
+
+ /* are we done shifting? */
+ if ( mmc1_shiftcount == 5 )
+ {
+ /* reset count */
+ mmc1_shiftcount = 0;
+
+ /* apply data to registers */
+ switch( reg )
+ {
+ case 0: /* mirroring and options */
+ {
+ int _mirroring;
+
+ vrom4k = mmc1_shiftreg & 0x10;
+ size16k = mmc1_shiftreg & 0x08;
+ switchlow = mmc1_shiftreg & 0x04;
+
+ switch( mmc1_shiftreg & 3 )
+ {
+ case 0:
+ _mirroring = PPU_MIRROR_LOW;
+ break;
+
+ case 1:
+ _mirroring = PPU_MIRROR_HIGH;
+ break;
+
+ case 2:
+ _mirroring = PPU_MIRROR_VERT;
+ break;
+
+ default:
+ case 3:
+ _mirroring = PPU_MIRROR_HORZ;
+ break;
+ }
+
+ /* apply mirroring */
+ ppu2c0x_set_mirroring( 0, _mirroring );
+ }
+ break;
+
+ case 1: /* video rom banking - bank 0 - 4k or 8k */
+ ppu2c0x_set_videorom_bank( 0, 0, ( vrom4k ) ? 4 : 8, ( mmc1_shiftreg & 0x1f ), 256 );
+ break;
+
+ case 2: /* video rom banking - bank 1 - 4k only */
+ if ( vrom4k )
+ ppu2c0x_set_videorom_bank( 0, 4, 4, ( mmc1_shiftreg & 0x1f ), 256 );
+ break;
+
+ case 3: /* program banking */
+ {
+ int bank = ( mmc1_shiftreg & mmc1_rom_mask ) * 0x4000;
+
+ if ( !size16k )
+ {
+ /* switch 32k */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x010000+bank], 0x8000 );
+ }
+ else
+ {
+ /* switch 16k */
+ if ( switchlow )
+ {
+ /* low */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x010000+bank], 0x4000 );
+ }
+ else
+ {
+ /* high */
+ memcpy( &memory_region( REGION_CPU2 )[0x0c000], &memory_region( REGION_CPU2 )[0x010000+bank], 0x4000 );
+ }
+ }
+ }
+ break;
+ }
+ }
+}
+
+/**********************************************************************************/
+
+/* A Board games (Track & Field, Gradius) */
+
+static WRITE8_HANDLER( aboard_vrom_switch_w )
+{
+ ppu2c0x_set_videorom_bank( 0, 0, 8, ( data & 3 ), 512 );
+}
+
+DRIVER_INIT( pcaboard )
+{
+ /* switches vrom with writes to the $803e-$8041 area */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0x8fff, 0, 0, aboard_vrom_switch_w );
+
+ /* common init */
+ driver_init_playch10(machine);
+
+ /* set the mirroring here */
+ mirroring = PPU_MIRROR_VERT;
+}
+
+/**********************************************************************************/
+
+/* B Board games (Contra, Rush N' Attach, Pro Wrestling) */
+
+static WRITE8_HANDLER( bboard_rom_switch_w )
+{
+ int bankoffset = 0x10000 + ( ( data & 7 ) * 0x4000 );
+
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[bankoffset], 0x4000 );
+}
+
+DRIVER_INIT( pcbboard )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x28000], 0x8000 );
+
+ /* Roms are banked at $8000 to $bfff */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, bboard_rom_switch_w );
+
+ /* common init */
+ driver_init_playch10(machine);
+
+ /* set the mirroring here */
+ mirroring = PPU_MIRROR_VERT;
+}
+
+/**********************************************************************************/
+
+/* C Board games (The Goonies) */
+
+static WRITE8_HANDLER( cboard_vrom_switch_w )
+{
+ ppu2c0x_set_videorom_bank( 0, 0, 8, ( ( data >> 1 ) & 1 ), 512 );
+}
+
+DRIVER_INIT( pccboard )
+{
+ /* switches vrom with writes to $6000 */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x6000, 0, 0, cboard_vrom_switch_w );
+
+ /* common init */
+ driver_init_playch10(machine);
+}
+
+/**********************************************************************************/
+
+/* D Board games (Rad Racer) */
+
+DRIVER_INIT( pcdboard )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x28000], 0x8000 );
+
+ mmc1_rom_mask = 0x07;
+
+ /* MMC mapper at writes to $8000-$ffff */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, mmc1_rom_switch_w );
+
+ /* common init */
+ driver_init_playch10(machine);
+}
+
+/* D Board games with extra ram (Metroid) */
+
+DRIVER_INIT( pcdboard_2 )
+{
+ /* extra ram at $6000-$7fff */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ /* common init */
+ driver_init_pcdboard(machine);
+}
+
+/**********************************************************************************/
+
+/* E Board games (Mike Tyson's Punchout) - BROKEN - FIX ME */
+
+/* callback for the ppu_latch */
+static void mapper9_latch( offs_t offset )
+{
+ if( (offset & 0x1ff0) == 0x0fd0 && MMC2_bank_latch[0] != 0xfd )
+ {
+ MMC2_bank_latch[0] = 0xfd;
+ ppu2c0x_set_videorom_bank( 0, 0, 4, MMC2_bank[0], 256 );
+ }
+ else if( (offset & 0x1ff0) == 0x0fe0 && MMC2_bank_latch[0] != 0xfe )
+ {
+ MMC2_bank_latch[0] = 0xfe;
+ ppu2c0x_set_videorom_bank( 0, 0, 4, MMC2_bank[1], 256 );
+ }
+ else if( (offset & 0x1ff0) == 0x1fd0 && MMC2_bank_latch[1] != 0xfd )
+ {
+ MMC2_bank_latch[1] = 0xfd;
+ ppu2c0x_set_videorom_bank( 0, 4, 4, MMC2_bank[2], 256 );
+ }
+ else if( (offset & 0x1ff0) == 0x1fe0 && MMC2_bank_latch[1] != 0xfe )
+ {
+ MMC2_bank_latch[1] = 0xfe;
+ ppu2c0x_set_videorom_bank( 0, 4, 4, MMC2_bank[3], 256 );
+ }
+}
+
+static WRITE8_HANDLER( eboard_rom_switch_w )
+{
+ /* a variation of mapper 9 on a nes */
+ switch( offset & 0x7000 )
+ {
+ case 0x2000: /* code bank switching */
+ {
+ int bankoffset = 0x10000 + ( data & 0x0f ) * 0x2000;
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[bankoffset], 0x2000 );
+ }
+ break;
+
+ case 0x3000: /* gfx bank 0 - 4k */
+ MMC2_bank[0] = data;
+ if( MMC2_bank_latch[0] == 0xfd )
+ ppu2c0x_set_videorom_bank( 0, 0, 4, data, 256 );
+ break;
+
+ case 0x4000: /* gfx bank 0 - 4k */
+ MMC2_bank[1] = data;
+ if( MMC2_bank_latch[0] == 0xfe )
+ ppu2c0x_set_videorom_bank( 0, 0, 4, data, 256 );
+ break;
+
+ case 0x5000: /* gfx bank 1 - 4k */
+ MMC2_bank[2] = data;
+ if( MMC2_bank_latch[1] == 0xfd )
+ ppu2c0x_set_videorom_bank( 0, 4, 4, data, 256 );
+ break;
+
+ case 0x6000: /* gfx bank 1 - 4k */
+ MMC2_bank[3] = data;
+ if( MMC2_bank_latch[1] == 0xfe )
+ ppu2c0x_set_videorom_bank( 0, 4, 4, data, 256 );
+ break;
+
+ case 0x7000: /* mirroring */
+ ppu2c0x_set_mirroring( 0, data ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT );
+
+ break;
+ }
+}
+
+DRIVER_INIT( pceboard )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x28000], 0x8000 );
+
+ /* basically a mapper 9 on a nes */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, eboard_rom_switch_w );
+
+ /* ppu_latch callback */
+ ppu_latch = mapper9_latch;
+
+ /* nvram at $6000-$6fff */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x6fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x6fff, 0, 0, MWA8_RAM );
+
+ /* common init */
+ driver_init_playch10(machine);
+}
+
+/**********************************************************************************/
+
+/* F Board games (Ninja Gaiden, Double Dragon) */
+
+DRIVER_INIT( pcfboard )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x28000], 0x8000 );
+
+ mmc1_rom_mask = 0x07;
+
+ /* MMC mapper at writes to $8000-$ffff */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, mmc1_rom_switch_w );
+
+ /* common init */
+ driver_init_playch10(machine);
+}
+
+/* F Board games with extra ram (Baseball Stars) */
+
+DRIVER_INIT( pcfboard_2 )
+{
+ /* extra ram at $6000-$6fff */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x6fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x6fff, 0, 0, MWA8_RAM );
+
+ /* common init */
+ driver_init_pcfboard(machine);
+}
+
+/**********************************************************************************/
+
+/* G Board games (Super Mario Bros. 3) */
+
+static int gboard_scanline_counter;
+static int gboard_scanline_latch;
+static int gboard_banks[2];
+static int gboard_4screen;
+
+static void gboard_scanline_cb( int num, int scanline, int vblank, int blanked )
+{
+ if ( !vblank && !blanked )
+ {
+ if ( --gboard_scanline_counter == -1 )
+ {
+ gboard_scanline_counter = gboard_scanline_latch;
+ cpunum_set_input_line( 1, 0, PULSE_LINE );
+ }
+ }
+}
+
+static WRITE8_HANDLER( gboard_rom_switch_w )
+{
+ /* basically, a MMC3 mapper from the nes */
+ static int last_bank = 0xff;
+ static int gboard_command;
+
+ switch( offset & 0x7001 )
+ {
+ case 0x0000:
+ gboard_command = data;
+
+ if ( last_bank != ( data & 0xc0 ) )
+ {
+ int bank;
+
+ /* reset the banks */
+ if ( gboard_command & 0x40 )
+ {
+ /* high bank */
+ bank = gboard_banks[0] * 0x2000 + 0x10000;
+
+ memcpy( &memory_region( REGION_CPU2 )[0x0c000], &memory_region( REGION_CPU2 )[bank], 0x2000 );
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x4c000], 0x2000 );
+ }
+ else
+ {
+ /* low bank */
+ bank = gboard_banks[0] * 0x2000 + 0x10000;
+
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[bank], 0x2000 );
+ memcpy( &memory_region( REGION_CPU2 )[0x0c000], &memory_region( REGION_CPU2 )[0x4c000], 0x2000 );
+ }
+
+ /* mid bank */
+ bank = gboard_banks[1] * 0x2000 + 0x10000;
+ memcpy( &memory_region( REGION_CPU2 )[0x0a000], &memory_region( REGION_CPU2 )[bank], 0x2000 );
+
+ last_bank = data & 0xc0;
+ }
+ break;
+
+ case 0x0001:
+ {
+ UINT8 cmd = gboard_command & 0x07;
+ int page = ( gboard_command & 0x80 ) >> 5;
+ int bank;
+
+ switch( cmd )
+ {
+ case 0: /* char banking */
+ case 1: /* char banking */
+ data &= 0xfe;
+ page ^= ( cmd << 1 );
+ ppu2c0x_set_videorom_bank( 0, page, 2, data, 64 );
+ break;
+
+ case 2: /* char banking */
+ case 3: /* char banking */
+ case 4: /* char banking */
+ case 5: /* char banking */
+ page ^= cmd + 2;
+ ppu2c0x_set_videorom_bank( 0, page, 1, data, 64 );
+ break;
+
+ case 6: /* program banking */
+ if ( gboard_command & 0x40 )
+ {
+ /* high bank */
+ gboard_banks[0] = data & 0x1f;
+ bank = ( gboard_banks[0] ) * 0x2000 + 0x10000;
+
+ memcpy( &memory_region( REGION_CPU2 )[0x0c000], &memory_region( REGION_CPU2 )[bank], 0x2000 );
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x4c000], 0x2000 );
+ }
+ else
+ {
+ /* low bank */
+ gboard_banks[0] = data & 0x1f;
+ bank = ( gboard_banks[0] ) * 0x2000 + 0x10000;
+
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[bank], 0x2000 );
+ memcpy( &memory_region( REGION_CPU2 )[0x0c000], &memory_region( REGION_CPU2 )[0x4c000], 0x2000 );
+ }
+ break;
+
+ case 7: /* program banking */
+ {
+ /* mid bank */
+ gboard_banks[1] = data & 0x1f;
+ bank = gboard_banks[1] * 0x2000 + 0x10000;
+
+ memcpy( &memory_region( REGION_CPU2 )[0x0a000], &memory_region( REGION_CPU2 )[bank], 0x2000 );
+ }
+ break;
+ }
+ }
+ break;
+
+ case 0x2000: /* mirroring */
+ if( !gboard_4screen )
+ {
+ if ( data & 0x40 )
+ ppu2c0x_set_mirroring( 0, PPU_MIRROR_HIGH );
+ else
+ ppu2c0x_set_mirroring( 0, ( data & 1 ) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT );
+ }
+ break;
+
+ case 0x2001: /* enable ram at $6000 */
+ /* ignored - we always enable it */
+ break;
+
+ case 0x4000: /* scanline counter */
+ gboard_scanline_counter = data;
+ break;
+
+ case 0x4001: /* scanline latch */
+ gboard_scanline_latch = data;
+ break;
+
+ case 0x6000: /* disable irqs */
+ ppu2c0x_set_scanline_callback( 0, 0 );
+ break;
+
+ case 0x6001: /* enable irqs */
+ ppu2c0x_set_scanline_callback( 0, gboard_scanline_cb );
+ break;
+ }
+}
+
+DRIVER_INIT( pcgboard )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x4c000], 0x4000 );
+ memcpy( &memory_region( REGION_CPU2 )[0x0c000], &memory_region( REGION_CPU2 )[0x4c000], 0x4000 );
+
+ /* MMC3 mapper at writes to $8000-$ffff */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, gboard_rom_switch_w );
+
+ /* extra ram at $6000-$7fff */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ gboard_banks[0] = 0x1e;
+ gboard_banks[1] = 0x1f;
+ gboard_scanline_counter = 0;
+ gboard_scanline_latch = 0;
+ gboard_4screen = 0;
+
+ /* common init */
+ driver_init_playch10(machine);
+}
+
+DRIVER_INIT( pcgboard_type2 )
+{
+ /* common init */
+ driver_init_pcgboard(machine);
+
+ /* enable 4 screen mirror */
+ gboard_4screen = 1;
+}
+
+/**********************************************************************************/
+
+/* i Board games (Captain Sky Hawk, Solar Jetman) */
+
+static WRITE8_HANDLER( iboard_rom_switch_w )
+{
+ int bank = data & 7;
+
+ if ( data & 0x10 )
+ ppu2c0x_set_mirroring( 0, PPU_MIRROR_HIGH );
+ else
+ ppu2c0x_set_mirroring( 0, PPU_MIRROR_LOW );
+
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[bank * 0x8000 + 0x10000], 0x8000 );
+}
+
+DRIVER_INIT( pciboard )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x10000], 0x8000 );
+
+ /* Roms are banked at $8000 to $bfff */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, iboard_rom_switch_w );
+
+ /* common init */
+ driver_init_playch10(machine);
+}
+
+/**********************************************************************************/
+
+/* H Board games (PinBot) */
+
+DRIVER_INIT( pchboard )
+{
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x4c000], 0x4000 );
+ memcpy( &memory_region( REGION_CPU2 )[0x0c000], &memory_region( REGION_CPU2 )[0x4c000], 0x4000 );
+
+ /* Roms are banked at $8000 to $bfff */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, gboard_rom_switch_w );
+
+ /* extra ram at $6000-$7fff */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ gboard_banks[0] = 0x1e;
+ gboard_banks[1] = 0x1f;
+ gboard_scanline_counter = 0;
+ gboard_scanline_latch = 0;
+
+ /* common init */
+ driver_init_playch10(machine);
+}
+
+/**********************************************************************************/
+
+/* K Board games (Mario Open Golf) */
+
+DRIVER_INIT( pckboard )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU2 )[0x08000], &memory_region( REGION_CPU2 )[0x48000], 0x8000 );
+
+ mmc1_rom_mask = 0x0f;
+
+ /* extra ram at $6000-$7fff */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ /* Roms are banked at $8000 to $bfff */
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, mmc1_rom_switch_w );
+
+ /* common init */
+ driver_init_playch10(machine);
+}
diff --git a/src/mame/machine/psx.c b/src/mame/machine/psx.c
new file mode 100644
index 00000000000..3bb6d93f993
--- /dev/null
+++ b/src/mame/machine/psx.c
@@ -0,0 +1,1650 @@
+/***************************************************************************
+
+ machine/psx.c
+
+ Thanks to Olivier Galibert for IDCT information
+
+***************************************************************************/
+
+#include <stdarg.h>
+#include "driver.h"
+#include "cpu/mips/psx.h"
+#include "includes/psx.h"
+
+#define VERBOSE_LEVEL ( 0 )
+
+INLINE void verboselog( int n_level, const char *s_fmt, ... )
+{
+ if( VERBOSE_LEVEL >= n_level )
+ {
+ va_list v;
+ char buf[ 32768 ];
+ va_start( v, s_fmt );
+ vsprintf( buf, s_fmt, v );
+ va_end( v );
+ if( cpu_getactivecpu() != -1 )
+ {
+ logerror( "%08x: %s", activecpu_get_pc(), buf );
+ }
+ else
+ {
+ logerror( "(timer) : %s", buf );
+ }
+ }
+}
+
+UINT32 *g_p_n_psxram;
+size_t g_n_psxramsize;
+
+INLINE void psxwriteword( UINT32 n_address, UINT16 n_data )
+{
+ *( (UINT16 *)( (UINT8 *)g_p_n_psxram + WORD_XOR_LE( n_address ) ) ) = n_data;
+}
+
+INLINE UINT16 psxreadword( UINT32 n_address )
+{
+ return *( (UINT16 *)( (UINT8 *)g_p_n_psxram + WORD_XOR_LE( n_address ) ) );
+}
+
+static UINT32 psx_com_delay = 0;
+
+WRITE32_HANDLER( psx_com_delay_w )
+{
+ COMBINE_DATA( &psx_com_delay );
+ verboselog( 1, "psx_com_delay_w( %08x %08x )\n", data, mem_mask );
+}
+
+READ32_HANDLER( psx_com_delay_r )
+{
+ verboselog( 1, "psx_com_delay_r( %08x )\n", mem_mask );
+ return psx_com_delay;
+}
+
+/* IRQ */
+
+static UINT32 m_n_irqdata;
+static UINT32 m_n_irqmask;
+
+static void psx_irq_update( void )
+{
+ if( ( m_n_irqdata & m_n_irqmask ) != 0 )
+ {
+ verboselog( 2, "psx irq assert\n" );
+ cpunum_set_input_line( 0, MIPS_IRQ0, ASSERT_LINE );
+ }
+ else
+ {
+ verboselog( 2, "psx irq clear\n" );
+ cpunum_set_input_line( 0, MIPS_IRQ0, CLEAR_LINE );
+ }
+}
+
+WRITE32_HANDLER( psx_irq_w )
+{
+ switch( offset )
+ {
+ case 0x00:
+ verboselog( 2, "psx irq data ( %08x, %08x ) %08x -> %08x\n", data, mem_mask, m_n_irqdata, ( m_n_irqdata & mem_mask ) | ( m_n_irqdata & m_n_irqmask & data ) );
+ m_n_irqdata = ( m_n_irqdata & mem_mask ) | ( m_n_irqdata & m_n_irqmask & data );
+ psx_irq_update();
+ break;
+ case 0x01:
+ verboselog( 2, "psx irq mask ( %08x, %08x ) %08x -> %08x\n", data, mem_mask, m_n_irqmask, ( m_n_irqmask & mem_mask ) | data );
+ m_n_irqmask = ( m_n_irqmask & mem_mask ) | data;
+ if( ( m_n_irqmask & ~( 0x1 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100 | 0x200 | 0x400 ) ) != 0 )
+ {
+ verboselog( 0, "psx_irq_w( %08x, %08x, %08x ) unknown irq\n", offset, data, mem_mask );
+ }
+ psx_irq_update();
+ break;
+ default:
+ verboselog( 0, "psx_irq_w( %08x, %08x, %08x ) unknown register\n", offset, data, mem_mask );
+ break;
+ }
+}
+
+READ32_HANDLER( psx_irq_r )
+{
+ switch( offset )
+ {
+ case 0x00:
+ verboselog( 1, "psx_irq_r irq data %08x\n", m_n_irqdata );
+ return m_n_irqdata;
+ case 0x01:
+ verboselog( 1, "psx_irq_r irq mask %08x\n", m_n_irqmask );
+ return m_n_irqmask;
+ default:
+ verboselog( 0, "psx_irq_r unknown register %d\n", offset );
+ break;
+ }
+ return 0;
+}
+
+void psx_irq_set( UINT32 data )
+{
+ verboselog( 2, "psx_irq_set %08x\n", data );
+ m_n_irqdata |= data;
+ psx_irq_update();
+}
+
+/* DMA */
+
+static UINT32 m_p_n_dmabase[ 7 ];
+static UINT32 m_p_n_dmablockcontrol[ 7 ];
+static UINT32 m_p_n_dmachannelcontrol[ 7 ];
+static emu_timer *m_p_timer_dma[ 7 ];
+static psx_dma_read_handler m_p_fn_dma_read[ 7 ];
+static psx_dma_write_handler m_p_fn_dma_write[ 7 ];
+static UINT32 m_p_n_dma_ticks[ 7 ];
+static UINT32 m_p_b_dma_running[ 7 ];
+static UINT32 m_n_dpcp;
+static UINT32 m_n_dicr;
+
+static void dma_start_timer( int n_channel, UINT32 n_ticks )
+{
+ timer_adjust( m_p_timer_dma[ n_channel ], attotime_mul(ATTOTIME_IN_HZ(33868800), n_ticks), n_channel, attotime_zero);
+ m_p_n_dma_ticks[ n_channel ] = n_ticks;
+ m_p_b_dma_running[ n_channel ] = 1;
+}
+
+static void dma_stop_timer( int n_channel )
+{
+ timer_adjust( m_p_timer_dma[ n_channel ], attotime_never, 0, attotime_never);
+ m_p_b_dma_running[ n_channel ] = 0;
+}
+
+static void dma_timer_adjust( int n_channel )
+{
+ if( m_p_b_dma_running[ n_channel ] )
+ {
+ dma_start_timer( n_channel, m_p_n_dma_ticks[ n_channel ] );
+ }
+ else
+ {
+ dma_stop_timer( n_channel );
+ }
+}
+
+static void dma_interrupt_update( void )
+{
+ int n_int;
+ int n_mask;
+
+ n_int = ( m_n_dicr >> 24 ) & 0x7f;
+ n_mask = ( m_n_dicr >> 16 ) & 0xff;
+
+ if( ( n_mask & 0x80 ) != 0 && ( n_int & n_mask ) != 0 )
+ {
+ verboselog( 2, "dma_interrupt_update( %02x, %02x ) interrupt triggered\n", n_int, n_mask );
+ m_n_dicr |= 0x80000000;
+ psx_irq_set( 0x0008 );
+ }
+ else if( ( m_n_dicr & 0x80000000 ) != 0 )
+ {
+ verboselog( 2, "dma_interrupt_update( %02x, %02x ) interrupt cleared\n", n_int, n_mask );
+ m_n_dicr &= ~0x80000000;
+ }
+ else if( n_int != 0 )
+ {
+ verboselog( 2, "dma_interrupt_update( %02x, %02x ) interrupt not enabled\n", n_int, n_mask );
+ }
+
+ m_n_dicr &= 0x00ffffff | ( m_n_dicr << 8 );
+}
+
+static void dma_finished(int n_channel)
+{
+ if( m_p_n_dmachannelcontrol[ n_channel ] == 0x01000401 && n_channel == 2 )
+ {
+ UINT32 n_size;
+ UINT32 n_total;
+ UINT32 n_address = ( m_p_n_dmabase[ n_channel ] & 0xffffff );
+ UINT32 n_adrmask = g_n_psxramsize - 1;
+ UINT32 n_nextaddress;
+
+ if( n_address != 0xffffff )
+ {
+ n_total = 0;
+ for( ;; )
+ {
+ if( n_address == 0xffffff )
+ {
+ m_p_n_dmabase[ n_channel ] = n_address;
+ dma_start_timer( n_channel, 19000 );
+ return;
+ }
+ if( n_total > 65535 )
+ {
+ m_p_n_dmabase[ n_channel ] = n_address;
+ //FIXME:
+ // 16000 below is based on try and error.
+ // Mametesters.org: sfex20103red
+ //dma_start_timer( n_channel, 16 );
+ dma_start_timer( n_channel, 16000 );
+ return;
+ }
+ n_address &= n_adrmask;
+ n_nextaddress = g_p_n_psxram[ n_address / 4 ];
+ n_size = n_nextaddress >> 24;
+ m_p_fn_dma_write[ n_channel ]( n_address + 4, n_size );
+ //FIXME:
+ // The following conditions will cause an endless loop.
+ // If stopping the transfer is correct I cannot judge
+ // The patch is meant as a hint for somebody who knows
+ // the hardware.
+ // Mametesters.org: psyforce0105u5red, raystorm0111u1red
+ if ((n_nextaddress & 0xffffff) != 0xffffff)
+ if (n_address == g_p_n_psxram[ (n_nextaddress & 0xffffff) / 4])
+ break;
+ if (n_address == (n_nextaddress & 0xffffff) )
+ break;
+ n_address = ( n_nextaddress & 0xffffff );
+
+ n_total += ( n_size + 1 );
+ }
+ }
+ }
+
+ m_p_n_dmachannelcontrol[ n_channel ] &= ~( ( 1L << 0x18 ) | ( 1L << 0x1c ) );
+
+ m_n_dicr |= 1 << ( 24 + n_channel );
+ dma_interrupt_update();
+ dma_stop_timer( n_channel );
+}
+
+static TIMER_CALLBACK( dma_finished_callback )
+{
+ dma_finished(param);
+}
+
+void psx_dma_install_read_handler( int n_channel, psx_dma_read_handler p_fn_dma_read )
+{
+ m_p_fn_dma_read[ n_channel ] = p_fn_dma_read;
+}
+
+void psx_dma_install_write_handler( int n_channel, psx_dma_read_handler p_fn_dma_write )
+{
+ m_p_fn_dma_write[ n_channel ] = p_fn_dma_write;
+}
+
+WRITE32_HANDLER( psx_dma_w )
+{
+ static int n_channel;
+ n_channel = offset / 4;
+ if( n_channel < 7 )
+ {
+ switch( offset % 4 )
+ {
+ case 0:
+ verboselog( 2, "dmabase( %d ) = %08x\n", n_channel, data );
+ m_p_n_dmabase[ n_channel ] = data;
+ break;
+ case 1:
+ verboselog( 2, "dmablockcontrol( %d ) = %08x\n", n_channel, data );
+ m_p_n_dmablockcontrol[ n_channel ] = data;
+ break;
+ case 2:
+ verboselog( 2, "dmachannelcontrol( %d ) = %08x\n", n_channel, data );
+ m_p_n_dmachannelcontrol[ n_channel ] = data;
+ if( ( m_p_n_dmachannelcontrol[ n_channel ] & ( 1L << 0x18 ) ) != 0 && ( m_n_dpcp & ( 1 << ( 3 + ( n_channel * 4 ) ) ) ) != 0 )
+ {
+ INT32 n_size;
+ UINT32 n_address;
+ UINT32 n_nextaddress;
+ UINT32 n_adrmask;
+
+ n_adrmask = g_n_psxramsize - 1;
+
+ n_address = ( m_p_n_dmabase[ n_channel ] & n_adrmask );
+ n_size = m_p_n_dmablockcontrol[ n_channel ];
+ if( ( m_p_n_dmachannelcontrol[ n_channel ] & 0x200 ) != 0 )
+ {
+ UINT32 n_ba;
+ n_ba = m_p_n_dmablockcontrol[ n_channel ] >> 16;
+ if( n_ba == 0 )
+ {
+ n_ba = 0x10000;
+ }
+ n_size = ( n_size & 0xffff ) * n_ba;
+ }
+
+ if( m_p_n_dmachannelcontrol[ n_channel ] == 0x01000000 &&
+ m_p_fn_dma_read[ n_channel ] != NULL )
+ {
+ verboselog( 1, "dma %d read block %08x %08x\n", n_channel, n_address, n_size );
+ m_p_fn_dma_read[ n_channel ]( n_address, n_size );
+ dma_finished( n_channel );
+ }
+ else if( m_p_n_dmachannelcontrol[ n_channel ] == 0x01000200 &&
+ m_p_fn_dma_read[ n_channel ] != NULL )
+ {
+ verboselog( 1, "dma %d read block %08x %08x\n", n_channel, n_address, n_size );
+ m_p_fn_dma_read[ n_channel ]( n_address, n_size );
+ if( n_channel == 1 )
+ {
+ dma_start_timer( n_channel, 26000 );
+ }
+ else
+ {
+ dma_finished( n_channel );
+ }
+ }
+ else if( m_p_n_dmachannelcontrol[ n_channel ] == 0x01000201 &&
+ m_p_fn_dma_write[ n_channel ] != NULL )
+ {
+ verboselog( 1, "dma %d write block %08x %08x\n", n_channel, n_address, n_size );
+ m_p_fn_dma_write[ n_channel ]( n_address, n_size );
+ dma_finished( n_channel );
+ }
+ else if( m_p_n_dmachannelcontrol[ n_channel ] == 0x11050100 &&
+ m_p_fn_dma_write[ n_channel ] != NULL )
+ {
+ /* todo: check this is a write not a read... */
+ verboselog( 1, "dma %d write block %08x %08x\n", n_channel, n_address, n_size );
+ m_p_fn_dma_write[ n_channel ]( n_address, n_size );
+ dma_finished( n_channel );
+ }
+ else if( m_p_n_dmachannelcontrol[ n_channel ] == 0x11150100 &&
+ m_p_fn_dma_write[ n_channel ] != NULL )
+ {
+ /* todo: check this is a write not a read... */
+ verboselog( 1, "dma %d write block %08x %08x\n", n_channel, n_address, n_size );
+ m_p_fn_dma_write[ n_channel ]( n_address, n_size );
+ dma_finished( n_channel );
+ }
+ else if( m_p_n_dmachannelcontrol[ n_channel ] == 0x01000401 &&
+ n_channel == 2 &&
+ m_p_fn_dma_write[ n_channel ] != NULL )
+ {
+ verboselog( 1, "dma %d write linked list %08x\n",
+ n_channel, m_p_n_dmabase[ n_channel ] );
+
+ dma_finished( n_channel );
+ }
+ else if( m_p_n_dmachannelcontrol[ n_channel ] == 0x11000002 &&
+ n_channel == 6 )
+ {
+ verboselog( 1, "dma 6 reverse clear %08x %08x\n",
+ m_p_n_dmabase[ n_channel ], m_p_n_dmablockcontrol[ n_channel ] );
+ if( n_size > 0 )
+ {
+ n_size--;
+ while( n_size > 0 )
+ {
+ n_nextaddress = ( n_address - 4 ) & 0xffffff;
+ g_p_n_psxram[ n_address / 4 ] = n_nextaddress;
+ n_address = n_nextaddress;
+ n_size--;
+ }
+ g_p_n_psxram[ n_address / 4 ] = 0xffffff;
+ }
+ dma_start_timer( n_channel, 2150 );
+ }
+ else
+ {
+ verboselog( 0, "dma %d unknown mode %08x\n", n_channel, m_p_n_dmachannelcontrol[ n_channel ] );
+ }
+ }
+ else if( m_p_n_dmachannelcontrol[ n_channel ] != 0 )
+ {
+ verboselog( 1, "psx_dma_w( %04x, %08x, %08x ) channel not enabled\n", offset, m_p_n_dmachannelcontrol[ n_channel ], mem_mask );
+ }
+ break;
+ default:
+ verboselog( 1, "psx_dma_w( %04x, %08x, %08x ) Unknown dma channel register\n", offset, data, mem_mask );
+ break;
+ }
+ }
+ else
+ {
+ switch( offset % 4 )
+ {
+ case 0x0:
+ verboselog( 1, "psx_dma_w( %04x, %08x, %08x ) dpcp\n", offset, data, mem_mask );
+ m_n_dpcp = ( m_n_dpcp & mem_mask ) | data;
+ break;
+ case 0x1:
+ m_n_dicr = ( m_n_dicr & mem_mask ) |
+ ( ~mem_mask & 0x80000000 & m_n_dicr ) |
+ ( ~data & ~mem_mask & 0x7f000000 & m_n_dicr ) |
+ ( data & ~mem_mask & 0x00ffffff );
+/* todo: find out whether to do this instead of dma_interrupt_update()
+
+ if( ( m_n_dicr & 0x7f000000 ) != 0 )
+ {
+ m_n_dicr &= ~0x80000000;
+ }
+*/
+ verboselog( 1, "psx_dma_w( %04x, %08x, %08x ) dicr -> %08x\n", offset, data, mem_mask, m_n_dicr );
+ dma_interrupt_update();
+ break;
+ default:
+ verboselog( 0, "psx_dma_w( %04x, %08x, %08x ) Unknown dma control register\n", offset, data, mem_mask );
+ break;
+ }
+ }
+}
+
+READ32_HANDLER( psx_dma_r )
+{
+ static int n_channel;
+ n_channel = offset / 4;
+ if( n_channel < 7 )
+ {
+ switch( offset % 4 )
+ {
+ case 0:
+ verboselog( 1, "psx_dma_r dmabase[ %d ] ( %08x )\n", n_channel, m_p_n_dmabase[ n_channel ] );
+ return m_p_n_dmabase[ n_channel ];
+ case 1:
+ verboselog( 1, "psx_dma_r dmablockcontrol[ %d ] ( %08x )\n", n_channel, m_p_n_dmablockcontrol[ n_channel ] );
+ return m_p_n_dmablockcontrol[ n_channel ];
+ case 2:
+ verboselog( 1, "psx_dma_r dmachannelcontrol[ %d ] ( %08x )\n", n_channel, m_p_n_dmachannelcontrol[ n_channel ] );
+ return m_p_n_dmachannelcontrol[ n_channel ];
+ default:
+ verboselog( 0, "psx_dma_r( %08x, %08x ) Unknown dma channel register\n", offset, mem_mask );
+ break;
+ }
+ }
+ else
+ {
+ switch( offset % 4 )
+ {
+ case 0x0:
+ verboselog( 1, "psx_dma_r dpcp ( %08x )\n", m_n_dpcp );
+ return m_n_dpcp;
+ case 0x1:
+ verboselog( 1, "psx_dma_r dicr ( %08x )\n", m_n_dicr );
+ return m_n_dicr;
+ default:
+ verboselog( 0, "psx_dma_r( %08x, %08x ) Unknown dma control register\n", offset, mem_mask );
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Root Counters */
+
+static emu_timer *m_p_timer_root[ 3 ];
+static UINT16 m_p_n_root_count[ 3 ];
+static UINT16 m_p_n_root_mode[ 3 ];
+static UINT16 m_p_n_root_target[ 3 ];
+static UINT32 m_p_n_root_start[ 3 ];
+
+#define RC_STOP ( 0x01 )
+#define RC_RESET ( 0x04 ) /* guess */
+#define RC_COUNTTARGET ( 0x08 )
+#define RC_IRQTARGET ( 0x10 )
+#define RC_IRQOVERFLOW ( 0x20 )
+#define RC_REPEAT ( 0x40 )
+#define RC_CLC ( 0x100 )
+#define RC_DIV ( 0x200 )
+
+static UINT32 psxcpu_gettotalcycles( void )
+{
+ /* TODO: should return the start of the current tick. */
+ return cpunum_gettotalcycles(0) * 2;
+}
+
+static int root_divider( int n_counter )
+{
+ if( n_counter == 0 && ( m_p_n_root_mode[ n_counter ] & RC_CLC ) != 0 )
+ {
+ /* TODO: pixel clock, probably based on resolution */
+ return 5;
+ }
+ else if( n_counter == 1 && ( m_p_n_root_mode[ n_counter ] & RC_CLC ) != 0 )
+ {
+ return 2150;
+ }
+ else if( n_counter == 2 && ( m_p_n_root_mode[ n_counter ] & RC_DIV ) != 0 )
+ {
+ return 8;
+ }
+ return 1;
+}
+
+static UINT16 root_current( int n_counter )
+{
+ if( ( m_p_n_root_mode[ n_counter ] & RC_STOP ) != 0 )
+ {
+ return m_p_n_root_count[ n_counter ];
+ }
+ else
+ {
+ UINT32 n_current;
+ n_current = psxcpu_gettotalcycles() - m_p_n_root_start[ n_counter ];
+ n_current /= root_divider( n_counter );
+ n_current += m_p_n_root_count[ n_counter ];
+ if( n_current > 0xffff )
+ {
+ /* TODO: use timer for wrap on 0x10000. */
+ m_p_n_root_count[ n_counter ] = n_current;
+ m_p_n_root_start[ n_counter ] = psxcpu_gettotalcycles();
+ }
+ return n_current;
+ }
+}
+
+static int root_target( int n_counter )
+{
+ if( ( m_p_n_root_mode[ n_counter ] & RC_COUNTTARGET ) != 0 ||
+ ( m_p_n_root_mode[ n_counter ] & RC_IRQTARGET ) != 0 )
+ {
+ return m_p_n_root_target[ n_counter ];
+ }
+ return 0x10000;
+}
+
+static void root_timer_adjust( int n_counter )
+{
+ if( ( m_p_n_root_mode[ n_counter ] & RC_STOP ) != 0 )
+ {
+ timer_adjust( m_p_timer_root[ n_counter ], attotime_never, n_counter, attotime_never);
+ }
+ else
+ {
+ int n_duration;
+
+ n_duration = root_target( n_counter ) - root_current( n_counter );
+ if( n_duration < 1 )
+ {
+ n_duration += 0x10000;
+ }
+
+ n_duration *= root_divider( n_counter );
+
+ timer_adjust( m_p_timer_root[ n_counter ], attotime_mul(ATTOTIME_IN_HZ(33868800), n_duration), n_counter, attotime_zero);
+ }
+}
+
+static TIMER_CALLBACK( root_finished )
+{
+ int n_counter = param;
+
+ verboselog( 2, "root_finished( %d ) %04x\n", n_counter, root_current( n_counter ) );
+// if( ( m_p_n_root_mode[ n_counter ] & RC_COUNTTARGET ) != 0 )
+ {
+ /* TODO: wrap should be handled differently as RC_COUNTTARGET & RC_IRQTARGET don't have to be the same. */
+ m_p_n_root_count[ n_counter ] = 0;
+ m_p_n_root_start[ n_counter ] = psxcpu_gettotalcycles();
+ }
+ if( ( m_p_n_root_mode[ n_counter ] & RC_REPEAT ) != 0 )
+ {
+ root_timer_adjust( n_counter );
+ }
+ if( ( m_p_n_root_mode[ n_counter ] & RC_IRQOVERFLOW ) != 0 ||
+ ( m_p_n_root_mode[ n_counter ] & RC_IRQTARGET ) != 0 )
+ {
+ psx_irq_set( 0x10 << n_counter );
+ }
+}
+
+WRITE32_HANDLER( psx_counter_w )
+{
+ int n_counter;
+
+ verboselog( 1, "psx_counter_w ( %08x, %08x, %08x )\n", offset, data, mem_mask );
+
+ n_counter = offset / 4;
+
+ switch( offset % 4 )
+ {
+ case 0:
+ m_p_n_root_count[ n_counter ] = data;
+ m_p_n_root_start[ n_counter ] = psxcpu_gettotalcycles();
+ break;
+ case 1:
+ m_p_n_root_count[ n_counter ] = root_current( n_counter );
+ m_p_n_root_start[ n_counter ] = psxcpu_gettotalcycles();
+ m_p_n_root_mode[ n_counter ] = data;
+
+ if( ( m_p_n_root_mode[ n_counter ] & RC_RESET ) != 0 )
+ {
+ m_p_n_root_count[ n_counter ] = 0;
+ }
+// if( ( data & 0xfca6 ) != 0 ||
+// ( ( data & 0x0100 ) != 0 && n_counter != 0 && n_counter != 1 ) ||
+// ( ( data & 0x0200 ) != 0 && n_counter != 2 ) )
+// {
+// mame_printf_debug( "mode %d 0x%04x\n", n_counter, data & 0xfca6 );
+// }
+ break;
+ case 2:
+ m_p_n_root_target[ n_counter ] = data;
+ break;
+ default:
+ verboselog( 0, "psx_counter_w( %08x, %08x, %08x ) unknown register\n", offset, mem_mask, data );
+ return;
+ }
+
+ root_timer_adjust( n_counter );
+}
+
+READ32_HANDLER( psx_counter_r )
+{
+ int n_counter;
+ UINT32 data;
+
+ n_counter = offset / 4;
+
+ switch( offset % 4 )
+ {
+ case 0:
+ data = root_current( n_counter );
+ break;
+ case 1:
+ data = m_p_n_root_mode[ n_counter ];
+ break;
+ case 2:
+ data = m_p_n_root_target[ n_counter ];
+ break;
+ default:
+ verboselog( 0, "psx_counter_r( %08x, %08x ) unknown register\n", offset, mem_mask );
+ return 0;
+ }
+ verboselog( 1, "psx_counter_r ( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ return data;
+}
+
+/* SIO */
+
+#define SIO_BUF_SIZE ( 8 )
+
+static UINT32 m_p_n_sio_status[ 2 ];
+static UINT32 m_p_n_sio_mode[ 2 ];
+static UINT32 m_p_n_sio_control[ 2 ];
+static UINT32 m_p_n_sio_baud[ 2 ];
+static UINT32 m_p_n_sio_tx[ 2 ];
+static UINT32 m_p_n_sio_rx[ 2 ];
+static UINT32 m_p_n_sio_tx_prev[ 2 ];
+static UINT32 m_p_n_sio_rx_prev[ 2 ];
+static UINT32 m_p_n_sio_tx_data[ 2 ];
+static UINT32 m_p_n_sio_rx_data[ 2 ];
+static UINT32 m_p_n_sio_tx_shift[ 2 ];
+static UINT32 m_p_n_sio_rx_shift[ 2 ];
+static UINT32 m_p_n_sio_tx_bits[ 2 ];
+static UINT32 m_p_n_sio_rx_bits[ 2 ];
+
+static emu_timer *m_p_timer_sio[ 2 ];
+static psx_sio_handler m_p_f_sio_handler[ 2 ];
+
+#define SIO_STATUS_TX_RDY ( 1 << 0 )
+#define SIO_STATUS_RX_RDY ( 1 << 1 )
+#define SIO_STATUS_TX_EMPTY ( 1 << 2 )
+#define SIO_STATUS_OVERRUN ( 1 << 4 )
+#define SIO_STATUS_DSR ( 1 << 7 )
+#define SIO_STATUS_IRQ ( 1 << 9 )
+
+#define SIO_CONTROL_TX_ENA ( 1 << 0 )
+#define SIO_CONTROL_IACK ( 1 << 4 )
+#define SIO_CONTROL_RESET ( 1 << 6 )
+#define SIO_CONTROL_TX_IENA ( 1 << 10 )
+#define SIO_CONTROL_RX_IENA ( 1 << 11 )
+#define SIO_CONTROL_DSR_IENA ( 1 << 12 )
+#define SIO_CONTROL_DTR ( 1 << 13 )
+
+static void sio_interrupt( int n_port )
+{
+ verboselog( 1, "sio_interrupt( %d )\n", n_port );
+ m_p_n_sio_status[ n_port ] |= SIO_STATUS_IRQ;
+ if( n_port == 0 )
+ {
+ psx_irq_set( 0x80 );
+ }
+ else
+ {
+ psx_irq_set( 0x100 );
+ }
+}
+
+static void sio_timer_adjust( int n_port )
+{
+ attotime n_time;
+ if( ( m_p_n_sio_status[ n_port ] & SIO_STATUS_TX_EMPTY ) == 0 || m_p_n_sio_tx_bits[ n_port ] != 0 )
+ {
+ int n_prescaler;
+
+ switch( m_p_n_sio_mode[ n_port ] & 3 )
+ {
+ case 1:
+ n_prescaler = 1;
+ break;
+ case 2:
+ n_prescaler = 16;
+ break;
+ case 3:
+ n_prescaler = 64;
+ break;
+ default:
+ n_prescaler = 0;
+ break;
+ }
+
+ if( m_p_n_sio_baud[ n_port ] != 0 && n_prescaler != 0 )
+ {
+ n_time = attotime_mul(ATTOTIME_IN_HZ(33868800), n_prescaler * m_p_n_sio_baud[n_port]);
+ verboselog( 2, "sio_timer_adjust( %d ) = %f ( %d x %d )\n", n_port, n_time, n_prescaler, m_p_n_sio_baud[ n_port ] );
+ }
+ else
+ {
+ n_time = attotime_never;
+ verboselog( 0, "sio_timer_adjust( %d ) invalid baud rate ( %d x %d )\n", n_port, n_prescaler, m_p_n_sio_baud[ n_port ] );
+ }
+ }
+ else
+ {
+ n_time = attotime_never;
+ verboselog( 2, "sio_timer_adjust( %d ) finished\n", n_port );
+ }
+ timer_adjust( m_p_timer_sio[ n_port ], n_time, n_port, attotime_zero);
+}
+
+static TIMER_CALLBACK( sio_clock )
+{
+ int n_port = param;
+ verboselog( 2, "sio tick\n" );
+
+ if( m_p_n_sio_tx_bits[ n_port ] == 0 &&
+ ( m_p_n_sio_control[ n_port ] & SIO_CONTROL_TX_ENA ) != 0 &&
+ ( m_p_n_sio_status[ n_port ] & SIO_STATUS_TX_EMPTY ) == 0 )
+ {
+ m_p_n_sio_tx_bits[ n_port ] = 8;
+ m_p_n_sio_tx_shift[ n_port ] = m_p_n_sio_tx_data[ n_port ];
+ if( n_port == 0 )
+ {
+ m_p_n_sio_rx_bits[ n_port ] = 8;
+ m_p_n_sio_rx_shift[ n_port ] = 0;
+ }
+ m_p_n_sio_status[ n_port ] |= SIO_STATUS_TX_EMPTY;
+ m_p_n_sio_status[ n_port ] |= SIO_STATUS_TX_RDY;
+ }
+
+ if( m_p_n_sio_tx_bits[ n_port ] != 0 )
+ {
+ m_p_n_sio_tx[ n_port ] = ( m_p_n_sio_tx[ n_port ] & ~PSX_SIO_OUT_DATA ) | ( ( m_p_n_sio_tx_shift[ n_port ] & 1 ) * PSX_SIO_OUT_DATA );
+ m_p_n_sio_tx_shift[ n_port ] >>= 1;
+ m_p_n_sio_tx_bits[ n_port ]--;
+
+ if( m_p_f_sio_handler[ n_port ] != NULL )
+ {
+ if( n_port == 0 )
+ {
+ m_p_n_sio_tx[ n_port ] &= ~PSX_SIO_OUT_CLOCK;
+ m_p_f_sio_handler[ n_port ]( m_p_n_sio_tx[ n_port ] );
+ m_p_n_sio_tx[ n_port ] |= PSX_SIO_OUT_CLOCK;
+ }
+ m_p_f_sio_handler[ n_port ]( m_p_n_sio_tx[ n_port ] );
+ }
+
+ if( m_p_n_sio_tx_bits[ n_port ] == 0 &&
+ ( m_p_n_sio_control[ n_port ] & SIO_CONTROL_TX_IENA ) != 0 )
+ {
+ sio_interrupt( n_port );
+ }
+ }
+
+ if( m_p_n_sio_rx_bits[ n_port ] != 0 )
+ {
+ m_p_n_sio_rx_shift[ n_port ] = ( m_p_n_sio_rx_shift[ n_port ] >> 1 ) | ( ( ( m_p_n_sio_rx[ n_port ] & PSX_SIO_IN_DATA ) / PSX_SIO_IN_DATA ) << 7 );
+ m_p_n_sio_rx_bits[ n_port ]--;
+
+ if( m_p_n_sio_rx_bits[ n_port ] == 0 )
+ {
+ if( ( m_p_n_sio_status[ n_port ] & SIO_STATUS_RX_RDY ) != 0 )
+ {
+ m_p_n_sio_status[ n_port ] |= SIO_STATUS_OVERRUN;
+ }
+ else
+ {
+ m_p_n_sio_rx_data[ n_port ] = m_p_n_sio_rx_shift[ n_port ];
+ m_p_n_sio_status[ n_port ] |= SIO_STATUS_RX_RDY;
+ }
+ if( ( m_p_n_sio_control[ n_port ] & SIO_CONTROL_RX_IENA ) != 0 )
+ {
+ sio_interrupt( n_port );
+ }
+ }
+ }
+
+ sio_timer_adjust( n_port );
+}
+
+void psx_sio_input( int n_port, int n_mask, int n_data )
+{
+ verboselog( 1, "psx_sio_input( %d, %02x, %02x )\n", n_port, n_mask, n_data );
+ m_p_n_sio_rx[ n_port ] = ( m_p_n_sio_rx[ n_port ] & ~n_mask ) | ( n_data & n_mask );
+
+ if( ( m_p_n_sio_rx[ n_port ] & PSX_SIO_IN_DSR ) != 0 )
+ {
+ m_p_n_sio_status[ n_port ] |= SIO_STATUS_DSR;
+ if( ( m_p_n_sio_rx_prev[ n_port ] & PSX_SIO_IN_DSR ) == 0 &&
+ ( m_p_n_sio_control[ n_port ] & SIO_CONTROL_DSR_IENA ) != 0 )
+ {
+ sio_interrupt( n_port );
+ }
+ }
+ else
+ {
+ m_p_n_sio_status[ n_port ] &= ~SIO_STATUS_DSR;
+ }
+ m_p_n_sio_rx_prev[ n_port ] = m_p_n_sio_rx[ n_port ];
+}
+
+WRITE32_HANDLER( psx_sio_w )
+{
+ int n_port;
+
+ n_port = offset / 4;
+
+ switch( offset % 4 )
+ {
+ case 0:
+ verboselog( 1, "psx_sio_w %d data %02x (%08x)\n", n_port, data, mem_mask );
+ m_p_n_sio_tx_data[ n_port ] = data;
+ m_p_n_sio_status[ n_port ] &= ~( SIO_STATUS_TX_RDY );
+ m_p_n_sio_status[ n_port ] &= ~( SIO_STATUS_TX_EMPTY );
+ sio_timer_adjust( n_port );
+ break;
+ case 1:
+ verboselog( 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
+ break;
+ case 2:
+ if( ACCESSING_LSW32 )
+ {
+ m_p_n_sio_mode[ n_port ] = data & 0xffff;
+ verboselog( 1, "psx_sio_w %d mode %04x\n", n_port, data & 0xffff );
+ }
+ if( ACCESSING_MSW32 )
+ {
+ verboselog( 1, "psx_sio_w %d control %04x\n", n_port, data >> 16 );
+ m_p_n_sio_control[ n_port ] = data >> 16;
+
+ if( ( m_p_n_sio_control[ n_port ] & SIO_CONTROL_RESET ) != 0 )
+ {
+ verboselog( 1, "psx_sio_w reset\n" );
+ m_p_n_sio_status[ n_port ] |= SIO_STATUS_TX_EMPTY | SIO_STATUS_TX_RDY;
+ m_p_n_sio_status[ n_port ] &= ~( SIO_STATUS_RX_RDY | SIO_STATUS_OVERRUN | SIO_STATUS_IRQ );
+ }
+ if( ( m_p_n_sio_control[ n_port ] & SIO_CONTROL_IACK ) != 0 )
+ {
+ verboselog( 1, "psx_sio_w iack\n" );
+ m_p_n_sio_status[ n_port ] &= ~( SIO_STATUS_IRQ );
+ m_p_n_sio_control[ n_port ] &= ~( SIO_CONTROL_IACK );
+ }
+ if( ( m_p_n_sio_control[ n_port ] & SIO_CONTROL_DTR ) != 0 )
+ {
+ m_p_n_sio_tx[ n_port ] |= PSX_SIO_OUT_DTR;
+ }
+ else
+ {
+ m_p_n_sio_tx[ n_port ] &= ~PSX_SIO_OUT_DTR;
+ }
+
+ if( ( ( m_p_n_sio_tx[ n_port ] ^ m_p_n_sio_tx_prev[ n_port ] ) & PSX_SIO_OUT_DTR ) != 0 )
+ {
+ if( m_p_f_sio_handler[ n_port ] != NULL )
+ {
+ m_p_f_sio_handler[ n_port ]( m_p_n_sio_tx[ n_port ] );
+ }
+ }
+ m_p_n_sio_tx_prev[ n_port ] = m_p_n_sio_tx[ n_port ];
+
+ }
+ break;
+ case 3:
+ if( ACCESSING_LSW32 )
+ {
+ verboselog( 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
+ }
+ if( ACCESSING_MSW32 )
+ {
+ m_p_n_sio_baud[ n_port ] = data >> 16;
+ verboselog( 1, "psx_sio_w %d baud %04x\n", n_port, data >> 16 );
+ }
+ break;
+ default:
+ verboselog( 0, "psx_sio_w( %08x, %08x, %08x )\n", offset, data, mem_mask );
+ break;
+ }
+}
+
+READ32_HANDLER( psx_sio_r )
+{
+ UINT32 data;
+ int n_port;
+
+ n_port = offset / 4;
+
+ switch( offset % 4 )
+ {
+ case 0:
+ data = m_p_n_sio_rx_data[ n_port ];
+ m_p_n_sio_status[ n_port ] &= ~( SIO_STATUS_RX_RDY );
+ m_p_n_sio_rx_data[ n_port ] = 0xff;
+ verboselog( 1, "psx_sio_r %d data %02x (%08x)\n", n_port, data, mem_mask );
+ break;
+ case 1:
+ data = m_p_n_sio_status[ n_port ];
+ if( ACCESSING_LSW32 )
+ {
+ verboselog( 1, "psx_sio_r %d status %04x\n", n_port, data & 0xffff );
+ }
+ if( ACCESSING_MSW32 )
+ {
+ verboselog( 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ }
+ break;
+ case 2:
+ data = ( m_p_n_sio_control[ n_port ] << 16 ) | m_p_n_sio_mode[ n_port ];
+ if( ACCESSING_LSW32 )
+ {
+ verboselog( 1, "psx_sio_r %d mode %04x\n", n_port, data & 0xffff );
+ }
+ if( ACCESSING_MSW32 )
+ {
+ verboselog( 1, "psx_sio_r %d control %04x\n", n_port, data >> 16 );
+ }
+ break;
+ case 3:
+ data = m_p_n_sio_baud[ n_port ] << 16;
+ if( ACCESSING_LSW32 )
+ {
+ verboselog( 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ }
+ if( ACCESSING_MSW32 )
+ {
+ verboselog( 1, "psx_sio_r %d baud %04x\n", n_port, data >> 16 );
+ }
+ break;
+ default:
+ data = 0;
+ verboselog( 0, "psx_sio_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
+ break;
+ }
+ return data;
+}
+
+void psx_sio_install_handler( int n_port, psx_sio_handler p_f_sio_handler )
+{
+ m_p_f_sio_handler[ n_port ] = p_f_sio_handler;
+}
+
+/* MDEC */
+
+static int mdec_decoded = 0;
+static int mdec_offset = 0;
+static UINT16 mdec_output[ 24 * 16 ];
+
+#define DCTSIZE ( 8 )
+#define DCTSIZE2 ( DCTSIZE * DCTSIZE )
+
+static INT32 m_p_n_mdec_quantize_y[ DCTSIZE2 ];
+static INT32 m_p_n_mdec_quantize_uv[ DCTSIZE2 ];
+static INT32 m_p_n_mdec_cos[ DCTSIZE2 ];
+static INT32 m_p_n_mdec_cos_precalc[ DCTSIZE2 * DCTSIZE2 ];
+
+static UINT32 m_n_mdec0_command;
+static UINT32 m_n_mdec0_address;
+static UINT32 m_n_mdec0_size;
+static UINT32 m_n_mdec1_command;
+static UINT32 m_n_mdec1_status;
+
+static UINT16 m_p_n_mdec_clamp8[ 256 * 3 ];
+static UINT16 m_p_n_mdec_r5[ 256 * 3 ];
+static UINT16 m_p_n_mdec_g5[ 256 * 3 ];
+static UINT16 m_p_n_mdec_b5[ 256 * 3 ];
+
+static UINT32 m_p_n_mdec_zigzag[ DCTSIZE2 ] =
+{
+ 0, 1, 8, 16, 9, 2, 3, 10,
+ 17, 24, 32, 25, 18, 11, 4, 5,
+ 12, 19, 26, 33, 40, 48, 41, 34,
+ 27, 20, 13, 6, 7, 14, 21, 28,
+ 35, 42, 49, 56, 57, 50, 43, 36,
+ 29, 22, 15, 23, 30, 37, 44, 51,
+ 58, 59, 52, 45, 38, 31, 39, 46,
+ 53, 60, 61, 54, 47, 55, 62, 63
+};
+
+static INT32 m_p_n_mdec_unpacked[ DCTSIZE2 * 6 * 2 ];
+
+#define MDEC_COS_PRECALC_BITS ( 21 )
+
+static void mdec_cos_precalc( void )
+{
+ UINT32 n_x;
+ UINT32 n_y;
+ UINT32 n_u;
+ UINT32 n_v;
+ INT32 *p_n_precalc;
+
+ p_n_precalc = m_p_n_mdec_cos_precalc;
+
+ for( n_y = 0; n_y < 8; n_y++ )
+ {
+ for( n_x = 0; n_x < 8; n_x++ )
+ {
+ for( n_v = 0; n_v < 8; n_v++ )
+ {
+ for( n_u = 0; n_u < 8; n_u++ )
+ {
+ *( p_n_precalc++ ) =
+ ( ( m_p_n_mdec_cos[ ( n_u * 8 ) + n_x ] *
+ m_p_n_mdec_cos[ ( n_v * 8 ) + n_y ] ) >> ( 30 - MDEC_COS_PRECALC_BITS ) );
+ }
+ }
+ }
+ }
+}
+
+static void mdec_idct( INT32 *p_n_src, INT32 *p_n_dst )
+{
+ UINT32 n_yx;
+ UINT32 n_vu;
+ INT32 p_n_z[ 8 ];
+ INT32 *p_n_data;
+ INT32 *p_n_precalc;
+
+ p_n_precalc = m_p_n_mdec_cos_precalc;
+
+ for( n_yx = 0; n_yx < DCTSIZE2; n_yx++ )
+ {
+ p_n_data = p_n_src;
+
+ memset( p_n_z, 0, sizeof( p_n_z ) );
+
+ for( n_vu = 0; n_vu < DCTSIZE2 / 8; n_vu++ )
+ {
+ p_n_z[ 0 ] += p_n_data[ 0 ] * p_n_precalc[ 0 ];
+ p_n_z[ 1 ] += p_n_data[ 1 ] * p_n_precalc[ 1 ];
+ p_n_z[ 2 ] += p_n_data[ 2 ] * p_n_precalc[ 2 ];
+ p_n_z[ 3 ] += p_n_data[ 3 ] * p_n_precalc[ 3 ];
+ p_n_z[ 4 ] += p_n_data[ 4 ] * p_n_precalc[ 4 ];
+ p_n_z[ 5 ] += p_n_data[ 5 ] * p_n_precalc[ 5 ];
+ p_n_z[ 6 ] += p_n_data[ 6 ] * p_n_precalc[ 6 ];
+ p_n_z[ 7 ] += p_n_data[ 7 ] * p_n_precalc[ 7 ];
+ p_n_data += 8;
+ p_n_precalc += 8;
+ }
+
+ *( p_n_dst++ ) = ( p_n_z[ 0 ] + p_n_z[ 1 ] + p_n_z[ 2 ] + p_n_z[ 3 ] +
+ p_n_z[ 4 ] + p_n_z[ 5 ] + p_n_z[ 6 ] + p_n_z[ 7 ] ) >> ( MDEC_COS_PRECALC_BITS + 2 );
+ }
+}
+
+INLINE UINT16 mdec_unpack_run( UINT16 n_packed )
+{
+ return n_packed >> 10;
+}
+
+INLINE INT32 mdec_unpack_val( UINT16 n_packed )
+{
+ return ( ( (INT32)n_packed ) << 22 ) >> 22;
+}
+
+static UINT32 mdec_unpack( UINT32 n_address )
+{
+ UINT8 n_z;
+ INT32 n_qscale;
+ UINT16 n_packed;
+ UINT32 n_block;
+ INT32 *p_n_block;
+ INT32 p_n_unpacked[ 64 ];
+ INT32 *p_n_q;
+
+ p_n_q = m_p_n_mdec_quantize_uv;
+ p_n_block = m_p_n_mdec_unpacked;
+
+ for( n_block = 0; n_block < 6; n_block++ )
+ {
+ memset( p_n_unpacked, 0, sizeof( p_n_unpacked ) );
+
+ if( n_block == 2 )
+ {
+ p_n_q = m_p_n_mdec_quantize_y;
+ }
+ n_packed = psxreadword( n_address );
+ n_address += 2;
+ if( n_packed == 0xfe00 )
+ {
+ break;
+ }
+
+ n_qscale = mdec_unpack_run( n_packed );
+ p_n_unpacked[ 0 ] = mdec_unpack_val( n_packed ) * p_n_q[ 0 ];
+
+ n_z = 0;
+ for( ;; )
+ {
+ n_packed = psxreadword( n_address );
+ n_address += 2;
+
+ if( n_packed == 0xfe00 )
+ {
+ break;
+ }
+ n_z += mdec_unpack_run( n_packed ) + 1;
+ if( n_z > 63 )
+ {
+ break;
+ }
+ p_n_unpacked[ m_p_n_mdec_zigzag[ n_z ] ] = ( mdec_unpack_val( n_packed ) * p_n_q[ n_z ] * n_qscale ) / 8;
+ }
+ mdec_idct( p_n_unpacked, p_n_block );
+ p_n_block += DCTSIZE2;
+ }
+ return n_address;
+}
+
+INLINE INT32 mdec_cr_to_r( INT32 n_cr )
+{
+ return ( 1435 * n_cr ) >> 10;
+}
+
+INLINE INT32 mdec_cr_to_g( INT32 n_cr )
+{
+ return ( -731 * n_cr ) >> 10;
+}
+
+INLINE INT32 mdec_cb_to_g( INT32 n_cb )
+{
+ return ( -351 * n_cb ) >> 10;
+}
+
+INLINE INT32 mdec_cb_to_b( INT32 n_cb )
+{
+ return ( 1814 * n_cb ) >> 10;
+}
+
+INLINE UINT16 mdec_clamp_r5( INT32 n_r )
+{
+ return m_p_n_mdec_r5[ n_r + 128 + 256 ];
+}
+
+INLINE UINT16 mdec_clamp_g5( INT32 n_g )
+{
+ return m_p_n_mdec_g5[ n_g + 128 + 256 ];
+}
+
+INLINE UINT16 mdec_clamp_b5( INT32 n_b )
+{
+ return m_p_n_mdec_b5[ n_b + 128 + 256 ];
+}
+
+INLINE void mdec_makergb15( UINT32 n_address, INT32 n_r, INT32 n_g, INT32 n_b, INT32 *p_n_y, UINT16 n_stp )
+{
+ mdec_output[ WORD_XOR_LE( n_address + 0 ) / 2 ] = n_stp |
+ mdec_clamp_r5( p_n_y[ 0 ] + n_r ) |
+ mdec_clamp_g5( p_n_y[ 0 ] + n_g ) |
+ mdec_clamp_b5( p_n_y[ 0 ] + n_b );
+
+ mdec_output[ WORD_XOR_LE( n_address + 2 ) / 2 ] = n_stp |
+ mdec_clamp_r5( p_n_y[ 1 ] + n_r ) |
+ mdec_clamp_g5( p_n_y[ 1 ] + n_g ) |
+ mdec_clamp_b5( p_n_y[ 1 ] + n_b );
+}
+
+static void mdec_yuv2_to_rgb15( void )
+{
+ INT32 n_r;
+ INT32 n_g;
+ INT32 n_b;
+ INT32 n_cb;
+ INT32 n_cr;
+ INT32 *p_n_cb;
+ INT32 *p_n_cr;
+ INT32 *p_n_y;
+ UINT32 n_x;
+ UINT32 n_y;
+ UINT32 n_z;
+ UINT16 n_stp;
+ int n_address = 0;
+
+ if( ( m_n_mdec0_command & ( 1L << 25 ) ) != 0 )
+ {
+ n_stp = 0x8000;
+ }
+ else
+ {
+ n_stp = 0x0000;
+ }
+
+ p_n_cr = &m_p_n_mdec_unpacked[ 0 ];
+ p_n_cb = &m_p_n_mdec_unpacked[ DCTSIZE2 ];
+ p_n_y = &m_p_n_mdec_unpacked[ DCTSIZE2 * 2 ];
+
+ for( n_z = 0; n_z < 2; n_z++ )
+ {
+ for( n_y = 0; n_y < 4; n_y++ )
+ {
+ for( n_x = 0; n_x < 4; n_x++ )
+ {
+ n_cr = *( p_n_cr );
+ n_cb = *( p_n_cb );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb15( ( n_address + 0 ), n_r, n_g, n_b, p_n_y, n_stp );
+ mdec_makergb15( ( n_address + 32 ), n_r, n_g, n_b, p_n_y + 8, n_stp );
+
+ n_cr = *( p_n_cr + 4 );
+ n_cb = *( p_n_cb + 4 );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb15( ( n_address + 16 ), n_r, n_g, n_b, p_n_y + DCTSIZE2, n_stp );
+ mdec_makergb15( ( n_address + 48 ), n_r, n_g, n_b, p_n_y + DCTSIZE2 + 8, n_stp );
+
+ p_n_cr++;
+ p_n_cb++;
+ p_n_y += 2;
+ n_address += 4;
+ }
+ p_n_cr += 4;
+ p_n_cb += 4;
+ p_n_y += 8;
+ n_address += 48;
+ }
+ p_n_y += DCTSIZE2;
+ }
+ mdec_decoded = ( 16 * 16 ) / 2;
+}
+
+INLINE UINT16 mdec_clamp8( INT32 n_r )
+{
+ return m_p_n_mdec_clamp8[ n_r + 128 + 256 ];
+}
+
+INLINE void mdec_makergb24( UINT32 n_address, INT32 n_r, INT32 n_g, INT32 n_b, INT32 *p_n_y, UINT32 n_stp )
+{
+ mdec_output[ WORD_XOR_LE( n_address + 0 ) / 2 ] = ( mdec_clamp8( p_n_y[ 0 ] + n_g ) << 8 ) | mdec_clamp8( p_n_y[ 0 ] + n_r );
+ mdec_output[ WORD_XOR_LE( n_address + 2 ) / 2 ] = ( mdec_clamp8( p_n_y[ 1 ] + n_r ) << 8 ) | mdec_clamp8( p_n_y[ 0 ] + n_b );
+ mdec_output[ WORD_XOR_LE( n_address + 4 ) / 2 ] = ( mdec_clamp8( p_n_y[ 1 ] + n_b ) << 8 ) | mdec_clamp8( p_n_y[ 1 ] + n_g );
+}
+
+static void mdec_yuv2_to_rgb24( void )
+{
+ INT32 n_r;
+ INT32 n_g;
+ INT32 n_b;
+ INT32 n_cb;
+ INT32 n_cr;
+ INT32 *p_n_cb;
+ INT32 *p_n_cr;
+ INT32 *p_n_y;
+ UINT32 n_x;
+ UINT32 n_y;
+ UINT32 n_z;
+ UINT32 n_stp;
+ int n_address = 0;
+
+ if( ( m_n_mdec0_command & ( 1L << 25 ) ) != 0 )
+ {
+ n_stp = 0x80008000;
+ }
+ else
+ {
+ n_stp = 0x00000000;
+ }
+
+ p_n_cr = &m_p_n_mdec_unpacked[ 0 ];
+ p_n_cb = &m_p_n_mdec_unpacked[ DCTSIZE2 ];
+ p_n_y = &m_p_n_mdec_unpacked[ DCTSIZE2 * 2 ];
+
+ for( n_z = 0; n_z < 2; n_z++ )
+ {
+ for( n_y = 0; n_y < 4; n_y++ )
+ {
+ for( n_x = 0; n_x < 4; n_x++ )
+ {
+ n_cr = *( p_n_cr );
+ n_cb = *( p_n_cb );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb24( ( n_address + 0 ), n_r, n_g, n_b, p_n_y, n_stp );
+ mdec_makergb24( ( n_address + 48 ), n_r, n_g, n_b, p_n_y + 8, n_stp );
+
+ n_cr = *( p_n_cr + 4 );
+ n_cb = *( p_n_cb + 4 );
+ n_r = mdec_cr_to_r( n_cr );
+ n_g = mdec_cr_to_g( n_cr ) + mdec_cb_to_g( n_cb );
+ n_b = mdec_cb_to_b( n_cb );
+
+ mdec_makergb24( ( n_address + 24 ), n_r, n_g, n_b, p_n_y + DCTSIZE2, n_stp );
+ mdec_makergb24( ( n_address + 72 ), n_r, n_g, n_b, p_n_y + DCTSIZE2 + 8, n_stp );
+
+ p_n_cr++;
+ p_n_cb++;
+ p_n_y += 2;
+ n_address += 6;
+ }
+ p_n_cr += 4;
+ p_n_cb += 4;
+ p_n_y += 8;
+ n_address += 72;
+ }
+ p_n_y += DCTSIZE2;
+ }
+ mdec_decoded = ( 24 * 16 ) / 2;
+}
+
+static void mdec0_write( UINT32 n_address, INT32 n_size )
+{
+ int n_index;
+
+ verboselog( 2, "mdec0_write( %08x, %08x )\n", n_address, n_size );
+ switch( m_n_mdec0_command >> 28 )
+ {
+ case 0x3:
+ verboselog( 1, "mdec decode %08x %08x %08x\n", m_n_mdec0_command, n_address, n_size );
+ m_n_mdec0_address = n_address;
+ m_n_mdec0_size = n_size * 4;
+ m_n_mdec1_status |= ( 1L << 29 );
+ break;
+ case 0x4:
+ verboselog( 1, "mdec quantize table %08x %08x %08x\n", m_n_mdec0_command, n_address, n_size );
+ n_index = 0;
+ while( n_size > 0 )
+ {
+ if( n_index < DCTSIZE2 )
+ {
+ m_p_n_mdec_quantize_y[ n_index + 0 ] = ( g_p_n_psxram[ n_address / 4 ] >> 0 ) & 0xff;
+ m_p_n_mdec_quantize_y[ n_index + 1 ] = ( g_p_n_psxram[ n_address / 4 ] >> 8 ) & 0xff;
+ m_p_n_mdec_quantize_y[ n_index + 2 ] = ( g_p_n_psxram[ n_address / 4 ] >> 16 ) & 0xff;
+ m_p_n_mdec_quantize_y[ n_index + 3 ] = ( g_p_n_psxram[ n_address / 4 ] >> 24 ) & 0xff;
+ }
+ else if( n_index < DCTSIZE2 * 2 )
+ {
+ m_p_n_mdec_quantize_uv[ n_index + 0 - DCTSIZE2 ] = ( g_p_n_psxram[ n_address / 4 ] >> 0 ) & 0xff;
+ m_p_n_mdec_quantize_uv[ n_index + 1 - DCTSIZE2 ] = ( g_p_n_psxram[ n_address / 4 ] >> 8 ) & 0xff;
+ m_p_n_mdec_quantize_uv[ n_index + 2 - DCTSIZE2 ] = ( g_p_n_psxram[ n_address / 4 ] >> 16 ) & 0xff;
+ m_p_n_mdec_quantize_uv[ n_index + 3 - DCTSIZE2 ] = ( g_p_n_psxram[ n_address / 4 ] >> 24 ) & 0xff;
+ }
+ n_index += 4;
+ n_address += 4;
+ n_size--;
+ }
+ break;
+ case 0x6:
+ verboselog( 1, "mdec cosine table %08x %08x %08x\n", m_n_mdec0_command, n_address, n_size );
+ n_index = 0;
+ while( n_size > 0 )
+ {
+ m_p_n_mdec_cos[ n_index + 0 ] = (INT16)( ( g_p_n_psxram[ n_address / 4 ] >> 0 ) & 0xffff );
+ m_p_n_mdec_cos[ n_index + 1 ] = (INT16)( ( g_p_n_psxram[ n_address / 4 ] >> 16 ) & 0xffff );
+ n_index += 2;
+ n_address += 4;
+ n_size--;
+ }
+ mdec_cos_precalc();
+ break;
+ default:
+ verboselog( 0, "mdec unknown command %08x %08x %08x\n", m_n_mdec0_command, n_address, n_size );
+ break;
+ }
+}
+
+static void mdec1_read( UINT32 n_address, INT32 n_size )
+{
+ UINT32 n_this;
+ UINT32 n_nextaddress;
+
+ verboselog( 2, "mdec1_read( %08x, %08x )\n", n_address, n_size );
+ if( ( m_n_mdec0_command & ( 1L << 29 ) ) != 0 && m_n_mdec0_size != 0 )
+ {
+ while( n_size > 0 )
+ {
+ if( mdec_decoded == 0 )
+ {
+ if( (int)m_n_mdec0_size <= 0 )
+ {
+ mame_printf_debug( "ran out of data %08x\n", n_size );
+ m_n_mdec0_size = 0;
+ break;
+ }
+
+ n_nextaddress = mdec_unpack( m_n_mdec0_address );
+ m_n_mdec0_size -= n_nextaddress - m_n_mdec0_address;
+ m_n_mdec0_address = n_nextaddress;
+
+ if( ( m_n_mdec0_command & ( 1L << 27 ) ) != 0 )
+ {
+ mdec_yuv2_to_rgb15();
+ }
+ else
+ {
+ mdec_yuv2_to_rgb24();
+ }
+ mdec_offset = 0;
+ }
+
+ n_this = mdec_decoded;
+ if( n_this > n_size )
+ {
+ n_this = n_size;
+ }
+ mdec_decoded -= n_this;
+
+ memcpy( (UINT8 *)g_p_n_psxram + n_address, (UINT8 *)mdec_output + mdec_offset, n_this * 4 );
+ mdec_offset += n_this * 4;
+ n_address += n_this * 4;
+ n_size -= n_this;
+ }
+
+ if( (int)m_n_mdec0_size < 0 )
+ {
+ mame_printf_debug( "ran out of data %d\n", m_n_mdec0_size );
+ }
+ }
+ else
+ {
+ mame_printf_debug( "mdec1_read no conversion :%08x:%08x:\n", m_n_mdec0_command, m_n_mdec0_size );
+ }
+ m_n_mdec1_status &= ~( 1L << 29 );
+}
+
+WRITE32_HANDLER( psx_mdec_w )
+{
+ switch( offset )
+ {
+ case 0:
+ verboselog( 2, "mdec 0 command %08x\n", data );
+ m_n_mdec0_command = data;
+ break;
+ case 1:
+ verboselog( 2, "mdec 1 command %08x\n", data );
+ m_n_mdec1_command = data;
+ break;
+ }
+}
+
+READ32_HANDLER( psx_mdec_r )
+{
+ switch( offset )
+ {
+ case 0:
+ verboselog( 2, "mdec 0 status %08x\n", 0 );
+ return 0;
+ case 1:
+ verboselog( 2, "mdec 1 status %08x\n", m_n_mdec1_status );
+ return m_n_mdec1_status;
+ }
+ return 0;
+}
+
+static void gpu_read( UINT32 n_address, INT32 n_size )
+{
+ psx_gpu_read( &g_p_n_psxram[ n_address / 4 ], n_size );
+}
+
+static void gpu_write( UINT32 n_address, INT32 n_size )
+{
+ psx_gpu_write( &g_p_n_psxram[ n_address / 4 ], n_size );
+}
+
+void psx_machine_init( void )
+{
+ int n;
+
+ /* irq */
+ m_n_irqdata = 0;
+ m_n_irqmask = 0;
+
+ /* dma */
+ m_n_dpcp = 0;
+ m_n_dicr = 0;
+
+ m_n_mdec0_command = 0;
+ m_n_mdec0_address = 0;
+ m_n_mdec0_size = 0;
+ m_n_mdec1_command = 0;
+ m_n_mdec1_status = 0;
+
+ for( n = 0; n < 7; n++ )
+ {
+ dma_stop_timer( n );
+ }
+
+ for( n = 0; n < 2; n++ )
+ {
+ m_p_n_sio_status[ n ] = SIO_STATUS_TX_EMPTY | SIO_STATUS_TX_RDY;
+ m_p_n_sio_mode[ n ] = 0;
+ m_p_n_sio_control[ n ] = 0;
+ m_p_n_sio_baud[ n ] = 0;
+ m_p_n_sio_tx[ n ] = 0;
+ m_p_n_sio_rx[ n ] = 0;
+ m_p_n_sio_tx_prev[ n ] = 0;
+ m_p_n_sio_rx_prev[ n ] = 0;
+ m_p_n_sio_rx_data[ n ] = 0;
+ m_p_n_sio_tx_data[ n ] = 0;
+ m_p_n_sio_rx_shift[ n ] = 0;
+ m_p_n_sio_tx_shift[ n ] = 0;
+ m_p_n_sio_rx_bits[ n ] = 0;
+ m_p_n_sio_tx_bits[ n ] = 0;
+ }
+
+ psx_gpu_reset();
+}
+
+static void psx_postload( void )
+{
+ int n;
+
+ psx_irq_update();
+
+ for( n = 0; n < 7; n++ )
+ {
+ dma_timer_adjust( n );
+ }
+
+ for( n = 0; n < 3; n++ )
+ {
+ root_timer_adjust( n );
+ }
+
+ for( n = 0; n < 2; n++ )
+ {
+ sio_timer_adjust( n );
+ }
+
+ mdec_cos_precalc();
+}
+
+void psx_driver_init( void )
+{
+ int n;
+
+ for( n = 0; n < 7; n++ )
+ {
+ m_p_timer_dma[ n ] = timer_alloc( dma_finished_callback );
+ m_p_fn_dma_read[ n ] = NULL;
+ m_p_fn_dma_write[ n ] = NULL;
+ }
+
+ for( n = 0; n < 3; n++ )
+ {
+ m_p_timer_root[ n ] = timer_alloc( root_finished );
+ }
+
+ for( n = 0; n < 2; n++ )
+ {
+ m_p_timer_sio[ n ] = timer_alloc( sio_clock );
+ }
+
+ for( n = 0; n < 256; n++ )
+ {
+ m_p_n_mdec_clamp8[ n ] = 0;
+ m_p_n_mdec_clamp8[ n + 256 ] = n;
+ m_p_n_mdec_clamp8[ n + 512 ] = 255;
+
+ m_p_n_mdec_r5[ n ] = 0;
+ m_p_n_mdec_r5[ n + 256 ] = ( n >> 3 );
+ m_p_n_mdec_r5[ n + 512 ] = ( 255 >> 3 );
+
+ m_p_n_mdec_g5[ n ] = 0;
+ m_p_n_mdec_g5[ n + 256 ] = ( n >> 3 ) << 5;
+ m_p_n_mdec_g5[ n + 512 ] = ( 255 >> 3 ) << 5;
+
+ m_p_n_mdec_b5[ n ] = 0;
+ m_p_n_mdec_b5[ n + 256 ] = ( n >> 3 ) << 10;
+ m_p_n_mdec_b5[ n + 512 ] = ( 255 >> 3 ) << 10;
+ }
+
+ for( n = 0; n < 2; n++ )
+ {
+ m_p_f_sio_handler[ n ] = NULL;
+ }
+
+ psx_dma_install_read_handler( 1, mdec1_read );
+ psx_dma_install_read_handler( 2, gpu_read );
+
+ psx_dma_install_write_handler( 0, mdec0_write );
+ psx_dma_install_write_handler( 2, gpu_write );
+
+ state_save_register_global( m_n_irqdata );
+ state_save_register_global( m_n_irqmask );
+ state_save_register_global_array( m_p_n_dmabase );
+ state_save_register_global_array( m_p_n_dmablockcontrol );
+ state_save_register_global_array( m_p_n_dmachannelcontrol );
+ state_save_register_global_array( m_p_n_dma_ticks );
+ state_save_register_global_array( m_p_b_dma_running );
+ state_save_register_global( m_n_dpcp );
+ state_save_register_global( m_n_dicr );
+ state_save_register_global_array( m_p_n_root_count );
+ state_save_register_global_array( m_p_n_root_mode );
+ state_save_register_global_array( m_p_n_root_target );
+ state_save_register_global_array( m_p_n_root_start );
+
+ state_save_register_global_array( m_p_n_sio_status );
+ state_save_register_global_array( m_p_n_sio_mode );
+ state_save_register_global_array( m_p_n_sio_control );
+ state_save_register_global_array( m_p_n_sio_baud );
+ state_save_register_global_array( m_p_n_sio_tx );
+ state_save_register_global_array( m_p_n_sio_rx );
+ state_save_register_global_array( m_p_n_sio_tx_prev );
+ state_save_register_global_array( m_p_n_sio_rx_prev );
+ state_save_register_global_array( m_p_n_sio_rx_data );
+ state_save_register_global_array( m_p_n_sio_tx_data );
+ state_save_register_global_array( m_p_n_sio_rx_shift );
+ state_save_register_global_array( m_p_n_sio_tx_shift );
+ state_save_register_global_array( m_p_n_sio_rx_bits );
+ state_save_register_global_array( m_p_n_sio_tx_bits );
+
+ state_save_register_global( m_n_mdec0_command );
+ state_save_register_global( m_n_mdec0_address );
+ state_save_register_global( m_n_mdec0_size );
+ state_save_register_global( m_n_mdec1_command );
+ state_save_register_global( m_n_mdec1_status );
+ state_save_register_global_array( m_p_n_mdec_quantize_y );
+ state_save_register_global_array( m_p_n_mdec_quantize_uv );
+ state_save_register_global_array( m_p_n_mdec_cos );
+
+ state_save_register_func_postload( psx_postload );
+}
diff --git a/src/mame/machine/qix.c b/src/mame/machine/qix.c
new file mode 100644
index 00000000000..aa1e93ff630
--- /dev/null
+++ b/src/mame/machine/qix.c
@@ -0,0 +1,605 @@
+/***************************************************************************
+
+ Taito Qix hardware
+
+ driver by John Butler, Ed Mueller, Aaron Giles
+
+***************************************************************************/
+
+#include "driver.h"
+#include "qix.h"
+#include "machine/6821pia.h"
+#include "cpu/m6800/m6800.h"
+#include "cpu/m6805/m6805.h"
+#include "cpu/m6809/m6809.h"
+#include "sound/sn76496.h"
+
+
+/* Globals */
+UINT8 *qix_68705_port_out;
+UINT8 *qix_68705_ddr;
+
+
+/* Local variables */
+static UINT8 qix_68705_port_in[3];
+static UINT8 qix_coinctrl;
+
+
+/* Prototypes */
+static READ8_HANDLER( qixmcu_coin_r );
+static WRITE8_HANDLER( qixmcu_coinctrl_w );
+static WRITE8_HANDLER( qixmcu_coin_w );
+
+static WRITE8_HANDLER( sync_pia_4_porta_w );
+
+static WRITE8_HANDLER( pia_5_warning_w );
+
+static WRITE8_HANDLER( qix_inv_flag_w );
+
+static WRITE8_HANDLER( qix_coinctl_w );
+static WRITE8_HANDLER( slither_coinctl_w );
+
+static void qix_pia_sint(int state);
+static void qix_pia_dint(int state);
+
+static WRITE8_HANDLER( slither_76489_0_w );
+static WRITE8_HANDLER( slither_76489_1_w );
+
+static READ8_HANDLER( slither_trak_lr_r );
+static READ8_HANDLER( slither_trak_ud_r );
+
+
+
+/***************************************************************************
+
+ Qix has 6 PIAs on board:
+
+ From the ROM I/O schematic:
+
+ PIA 0 = U11: (mapped to $9400 on the data CPU)
+ port A = external input (input_port_0)
+ port B = external input (input_port_1) (coin)
+
+ PIA 1 = U20: (mapped to $9800/$9900 on the data CPU)
+ port A = external input (input_port_2)
+ port B = external input (input_port_3)
+
+ PIA 2 = U30: (mapped to $9c00 on the data CPU)
+ port A = external input (input_port_4)
+ port B = external output (coin control)
+
+
+ From the data/sound processor schematic:
+
+ PIA 3 = U20: (mapped to $9000 on the data CPU)
+ port A = data CPU to sound CPU communication
+ port B = stereo volume control, 2 4-bit values
+ CA1 = interrupt signal from sound CPU
+ CA2 = interrupt signal to sound CPU
+ CB1 = VS input signal (vertical sync)
+ CB2 = INV output signal (cocktail flip)
+ IRQA = /DINT1 signal
+ IRQB = /DINT1 signal
+
+ PIA 4 = U8: (mapped to $4000 on the sound CPU)
+ port A = sound CPU to data CPU communication
+ port B = DAC value (port B)
+ CA1 = interrupt signal from data CPU
+ CA2 = interrupt signal to data CPU
+ IRQA = /SINT1 signal
+ IRQB = /SINT1 signal
+
+ PIA 5 = U7: (never actually used, mapped to $2000 on the sound CPU)
+ port A = unused
+ port B = sound CPU to TMS5220 communication
+ CA1 = interrupt signal from TMS5220
+ CA2 = write signal to TMS5220
+ CB1 = ready signal from TMS5220
+ CB2 = read signal to TMS5220
+ IRQA = /SINT2 signal
+ IRQB = /SINT2 signal
+
+***************************************************************************/
+
+static const pia6821_interface qix_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface qix_pia_1_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, input_port_3_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface qix_pia_2_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_4_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, qix_coinctl_w, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface qix_pia_3_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ sync_pia_4_porta_w, qix_vol_w, pia_4_ca1_w, qix_inv_flag_w,
+ /*irqs : A/B */ qix_pia_dint, qix_pia_dint
+};
+
+static const pia6821_interface qix_pia_4_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ pia_3_porta_w, qix_dac_w, pia_3_ca1_w, 0,
+ /*irqs : A/B */ qix_pia_sint, qix_pia_sint
+};
+
+static const pia6821_interface qix_pia_5_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ pia_5_warning_w, pia_5_warning_w, pia_5_warning_w, pia_5_warning_w,
+ /*irqs : A/B */ 0, 0
+};
+
+
+static WRITE8_HANDLER( pia_5_warning_w )
+{
+ popmessage("PIA 5 write!!");
+}
+
+
+/***************************************************************************
+
+ Games with an MCU need to handle coins differently, and provide
+ communication with the MCU
+
+***************************************************************************/
+
+static const pia6821_interface qixmcu_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, qixmcu_coin_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, qixmcu_coin_w, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface qixmcu_pia_2_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_4_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, qixmcu_coinctrl_w, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+
+
+/***************************************************************************
+
+ Slither uses 2 SN76489's for sound instead of the 6802+DAC; these
+ are accessed via the PIAs.
+
+***************************************************************************/
+
+static const pia6821_interface slither_pia_1_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ slither_trak_lr_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, slither_76489_0_w, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface slither_pia_2_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ slither_trak_ud_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, slither_76489_1_w, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+static const pia6821_interface slither_pia_3_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, slither_coinctl_w, 0, qix_inv_flag_w,
+ /*irqs : A/B */ qix_pia_dint, qix_pia_dint
+};
+
+
+
+/*************************************
+ *
+ * Machine initialization
+ *
+ *************************************/
+
+MACHINE_START( qix )
+{
+ /* configure the PIAs */
+ pia_config(0, &qix_pia_0_intf);
+ pia_config(1, &qix_pia_1_intf);
+ pia_config(2, &qix_pia_2_intf);
+ pia_config(3, &qix_pia_3_intf);
+ pia_config(4, &qix_pia_4_intf);
+ pia_config(5, &qix_pia_5_intf);
+}
+
+MACHINE_RESET( qix )
+{
+ /* reset the PIAs */
+ pia_reset();
+
+ /* reset the coin counter register */
+ qix_coinctrl = 0x00;
+}
+
+
+MACHINE_START( qixmcu )
+{
+ /* configure the PIAs */
+ pia_config(0, &qixmcu_pia_0_intf);
+ pia_config(1, &qix_pia_1_intf);
+ pia_config(2, &qixmcu_pia_2_intf);
+ pia_config(3, &qix_pia_3_intf);
+ pia_config(4, &qix_pia_4_intf);
+ pia_config(5, &qix_pia_5_intf);
+
+ /* set up save states */
+ state_save_register_global_array(qix_68705_port_in);
+ state_save_register_global(qix_coinctrl);
+}
+
+MACHINE_START( slither )
+{
+ /* configure the PIAs */
+ pia_config(0, &qix_pia_0_intf);
+ pia_config(1, &slither_pia_1_intf);
+ pia_config(2, &slither_pia_2_intf);
+ pia_config(3, &slither_pia_3_intf);
+}
+
+
+
+/*************************************
+ *
+ * VSYNC interrupt handling
+ *
+ *************************************/
+
+static TIMER_CALLBACK( vblank_stop )
+{
+ pia_3_cb1_w(0, 0);
+}
+
+
+INTERRUPT_GEN( qix_vblank_start )
+{
+ pia_3_cb1_w(0, 1);
+ timer_set(video_screen_get_time_until_pos(0, 0, 0), 0, vblank_stop);
+}
+
+
+
+/*************************************
+ *
+ * Zoo Keeper bankswitching
+ *
+ *************************************/
+
+WRITE8_HANDLER( zoo_bankswitch_w )
+{
+ memory_set_bank(1, (data >> 2) & 1);
+ /* not necessary, but technically correct */
+ qix_palettebank_w(offset,data);
+}
+
+
+
+/*************************************
+ *
+ * Data CPU FIRQ generation/ack
+ *
+ *************************************/
+
+WRITE8_HANDLER( qix_data_firq_w )
+{
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
+}
+
+
+WRITE8_HANDLER( qix_data_firq_ack_w )
+{
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, CLEAR_LINE);
+}
+
+
+READ8_HANDLER( qix_data_firq_r )
+{
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE);
+ return 0xff;
+}
+
+
+READ8_HANDLER( qix_data_firq_ack_r )
+{
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, CLEAR_LINE);
+ return 0xff;
+}
+
+
+
+/*************************************
+ *
+ * Video CPU FIRQ generation/ack
+ *
+ *************************************/
+
+WRITE8_HANDLER( qix_video_firq_w )
+{
+ cpunum_set_input_line(1, M6809_FIRQ_LINE, ASSERT_LINE);
+}
+
+
+WRITE8_HANDLER( qix_video_firq_ack_w )
+{
+ cpunum_set_input_line(1, M6809_FIRQ_LINE, CLEAR_LINE);
+}
+
+
+READ8_HANDLER( qix_video_firq_r )
+{
+ cpunum_set_input_line(1, M6809_FIRQ_LINE, ASSERT_LINE);
+ return 0xff;
+}
+
+
+READ8_HANDLER( qix_video_firq_ack_r )
+{
+ cpunum_set_input_line(1, M6809_FIRQ_LINE, CLEAR_LINE);
+ return 0xff;
+}
+
+
+
+/*************************************
+ *
+ * Sound PIA interfaces
+ *
+ *************************************/
+
+static TIMER_CALLBACK( deferred_pia_4_porta_w )
+{
+ pia_4_porta_w(0, param);
+}
+
+
+static WRITE8_HANDLER( sync_pia_4_porta_w )
+{
+ /* we need to synchronize this so the sound CPU doesn't drop anything important */
+ timer_call_after_resynch(data, deferred_pia_4_porta_w);
+}
+
+
+
+/*************************************
+ *
+ * IRQ generation
+ *
+ *************************************/
+
+static void qix_pia_dint(int state)
+{
+ /* DINT is connected to the data CPU's IRQ line */
+ cpunum_set_input_line(0, M6809_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+static void qix_pia_sint(int state)
+{
+ /* SINT is connected to the sound CPU's IRQ line */
+ cpunum_set_input_line(2, M6802_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+
+/*************************************
+ *
+ * 68705 Communication
+ *
+ *************************************/
+
+READ8_HANDLER( qixmcu_coin_r )
+{
+ logerror("6809:qixmcu_coin_r = %02X\n", qix_68705_port_out[0]);
+ return qix_68705_port_out[0];
+}
+
+
+static WRITE8_HANDLER( qixmcu_coin_w )
+{
+ logerror("6809:qixmcu_coin_w = %02X\n", data);
+ /* this is a callback called by pia_0_w(), so I don't need to synchronize */
+ /* the CPUs - they have already been synchronized by qix_pia_0_w() */
+ qix_68705_port_in[0] = data;
+}
+
+
+static WRITE8_HANDLER( qixmcu_coinctrl_w )
+{
+ if (!(data & 0x04))
+ {
+ cpunum_set_input_line(3, M68705_IRQ_LINE, ASSERT_LINE);
+ /* temporarily boost the interleave to sync things up */
+ /* note: I'm using 50 because 30 is not enough for space dungeon at game over */
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(50));
+ }
+ else
+ cpunum_set_input_line(3, M68705_IRQ_LINE, CLEAR_LINE);
+
+ /* this is a callback called by pia_0_w(), so I don't need to synchronize */
+ /* the CPUs - they have already been synchronized by qix_pia_0_w() */
+ qix_coinctrl = data;
+ logerror("6809:qixmcu_coinctrl_w = %02X\n", data);
+}
+
+
+
+/*************************************
+ *
+ * 68705 Port Inputs
+ *
+ *************************************/
+
+READ8_HANDLER( qix_68705_portA_r )
+{
+ UINT8 ddr = qix_68705_ddr[0];
+ UINT8 out = qix_68705_port_out[0];
+ UINT8 in = qix_68705_port_in[0];
+ logerror("68705:portA_r = %02X (%02X)\n", (out & ddr) | (in & ~ddr), in);
+ return (out & ddr) | (in & ~ddr);
+}
+
+
+READ8_HANDLER( qix_68705_portB_r )
+{
+ UINT8 ddr = qix_68705_ddr[1];
+ UINT8 out = qix_68705_port_out[1];
+ UINT8 in = (readinputport(1) & 0x0f) | ((readinputport(1) & 0x80) >> 3);
+ return (out & ddr) | (in & ~ddr);
+}
+
+
+READ8_HANDLER( qix_68705_portC_r )
+{
+ UINT8 ddr = qix_68705_ddr[2];
+ UINT8 out = qix_68705_port_out[2];
+ UINT8 in = (qix_coinctrl & 0x08) | ((readinputport(1) & 0x70) >> 4);
+ return (out & ddr) | (in & ~ddr);
+}
+
+
+
+/*************************************
+ *
+ * 68705 Port Outputs
+ *
+ *************************************/
+
+WRITE8_HANDLER( qix_68705_portA_w )
+{
+ logerror("68705:portA_w = %02X\n", data);
+ qix_68705_port_out[0] = data;
+}
+
+
+WRITE8_HANDLER( qix_68705_portB_w )
+{
+ qix_68705_port_out[1] = data;
+ coin_lockout_w(0, (~data >> 6) & 1);
+ coin_counter_w(0, (data >> 7) & 1);
+}
+
+
+WRITE8_HANDLER( qix_68705_portC_w )
+{
+ qix_68705_port_out[2] = data;
+}
+
+
+
+/*************************************
+ *
+ * Data CPU PIA 0 synchronization
+ *
+ *************************************/
+
+static TIMER_CALLBACK( pia_0_w_callback )
+{
+ pia_0_w(param >> 8, param & 0xff);
+}
+
+
+WRITE8_HANDLER( qix_pia_0_w )
+{
+ /* make all the CPUs synchronize, and only AFTER that write the command to the PIA */
+ /* otherwise the 68705 will miss commands */
+ timer_call_after_resynch(data | (offset << 8), pia_0_w_callback);
+}
+
+
+
+/*************************************
+ *
+ * Cocktail flip
+ *
+ *************************************/
+
+static WRITE8_HANDLER( qix_inv_flag_w )
+{
+ qix_cocktail_flip = data;
+}
+
+
+
+/*************************************
+ *
+ * Coin I/O for games without coin CPU
+ *
+ *************************************/
+
+static WRITE8_HANDLER( qix_coinctl_w )
+{
+ coin_lockout_w(0, (~data >> 2) & 1);
+ coin_counter_w(0, (data >> 1) & 1);
+}
+
+
+static WRITE8_HANDLER( slither_coinctl_w )
+{
+ coin_lockout_w(0, (~data >> 6) & 1);
+ coin_counter_w(0, (data >> 5) & 1);
+}
+
+
+
+/*************************************
+ *
+ * Slither SN76489 I/O
+ *
+ *************************************/
+
+static WRITE8_HANDLER( slither_76489_0_w )
+{
+ /* write to the sound chip */
+ SN76496_0_w(0, data);
+
+ /* clock the ready line going back into CB1 */
+ pia_1_cb1_w(0, 0);
+ pia_1_cb1_w(0, 1);
+}
+
+
+static WRITE8_HANDLER( slither_76489_1_w )
+{
+ /* write to the sound chip */
+ SN76496_1_w(0, data);
+
+ /* clock the ready line going back into CB1 */
+ pia_2_cb1_w(0, 0);
+ pia_2_cb1_w(0, 1);
+}
+
+
+
+/*************************************
+ *
+ * Slither trackball I/O
+ *
+ *************************************/
+
+static READ8_HANDLER( slither_trak_lr_r )
+{
+ return readinputport(qix_cocktail_flip ? 6 : 4);
+}
+
+
+static READ8_HANDLER( slither_trak_ud_r )
+{
+ return readinputport(qix_cocktail_flip ? 5 : 3);
+}
diff --git a/src/mame/machine/rainbow.c b/src/mame/machine/rainbow.c
new file mode 100644
index 00000000000..5f1be085e13
--- /dev/null
+++ b/src/mame/machine/rainbow.c
@@ -0,0 +1,831 @@
+/*************************************************************************
+
+ Rainbow Islands C-Chip Protection
+
+ 2002-Feb rewritten by Robert Gallagher
+
+ - A replacement romset was coded, then inserted into a Rainbow Islands Extra PCB.
+ This replacement would break into the gameplay, and begin dumping all possible data from
+ the games C-chip to the display. The data was collected, recorded (photos) then added
+ to this driver
+ - C-chip data are all handled internally with arrays (no longer using JB1-F89 from Jumping)
+ - More accurate emulation of C-chip (allowing writes, only returning data when requested...)
+ - Aspects of the C-chip are more accurately 'simulated' by dynamically updating data, rather
+ than relying on hard-coded data from the Jumping bootleg
+ - GOAL IN Y-coordinates are randomized, from a collected set of possibles, similar to a real machine
+ - None of the data present has been 'made up', everything has been verified with real hardware
+ - Many thanks to Tormod Tjaberg for dumping the Rainbow Islands Extra c-chip data
+ making RIE fully playable
+
+
+ BANK 0 000 - 002 set by the 68000 during initialization
+ 003 - 006 joystick and other input bits
+ 008 coin counters and lock-out
+ 00D round number for world data request
+ 01D internal use
+ BANK 1 000 internal use
+ 001 - 002 round height (LSB first)
+ 004 - 0ff unknown data
+ 100 request round data
+ 101 - 140 walking on the rainbow offsets
+ 141 round number for round data request
+ 142 - 145 round address (MSB first)
+ 148 boss or secret room flag
+ 149 request goal-in data
+ 14A - 155 goal-in data
+ BANK 2 000 - 01f rainbow dissolve graphics
+ 020 - 03f rainbow smashing graphics
+ 040 - 061 unused data
+ BANK 4 002 - XXX monster animation sequences /
+ starts with directory of 2-byte offsets
+ BANK 5 000 request world data
+ 002 - XXX monster property records /
+ starts with directory of 2-byte offsets
+ BANK 6 002 - 141 unknown, has $20 bytes per world
+ BANK 7 002 - XXX monster to Bubble Bobble sprite mapping
+
+
+*************************************************************************/
+
+#include "driver.h"
+
+static UINT8* CRAM[8];
+
+static int extra_version;
+static UINT8 current_bank;
+
+/*************************************
+ *
+ * C-Chip bank data
+ *
+ *************************************/
+
+struct CBANK
+{
+ const UINT8* data;
+ size_t size;
+};
+
+static const UINT8 CROM_BANK1[] =
+{
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x0A, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x0A, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x0A, 0x0B, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x09, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x07, 0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x05, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x01, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x05, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x05, 0x01, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x02, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
+ 0x04, 0x04, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06,
+ 0x08, 0x08, 0x0A, 0x0C, 0x0C, 0x0E, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18,
+ 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30,
+ 0x32, 0x58, 0x5A, 0x5C, 0x5E, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6A, 0x6C,
+ 0x6E, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7A, 0x7C, 0x7E, 0x7E, 0x7E, 0x80,
+ 0x82, 0x86, 0x86, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A
+};
+
+static const UINT8 CROM_BANK2[] =
+{
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
+ 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43,
+ 0x44, 0x45, 0x46, 0x47, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x04, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x10, 0x10, 0x12, 0x12,
+ 0x14, 0x14, 0x16, 0x20, 0x22, 0x16, 0x20, 0x22, 0x16, 0x16, 0x20, 0x20,
+ 0x22, 0x22
+};
+
+static const UINT8 CROM_BANK4_WORLD0[] =
+{
+ 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00,
+ 0x40, 0x00, 0x44, 0x00, 0x48, 0x00, 0x54, 0x00, 0x58, 0x00, 0x5C, 0x00,
+ 0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x74, 0x00, 0x78, 0x00, 0x7C, 0x00,
+ 0x80, 0x00, 0x84, 0x00, 0x32, 0x00, 0x34, 0x00, 0x56, 0x00, 0x58, 0x00,
+ 0x98, 0x00, 0x96, 0x00, 0x7A, 0x00, 0x7C, 0x00, 0x56, 0x00, 0x58, 0x00,
+ 0x98, 0x00, 0x96, 0x00, 0x12, 0x01, 0x13, 0x01, 0x1C, 0x01, 0x1D, 0x01,
+ 0x29, 0x01, 0x28, 0x01, 0x26, 0x01, 0x27, 0x01, 0x2A, 0x01, 0x2B, 0x01,
+ 0xFA, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0x00, 0x01, 0x02, 0x10, 0x00, 0x10,
+ 0xD6, 0x00, 0xD8, 0x00, 0xD2, 0x00, 0xD4, 0x00, 0xDE, 0x00, 0xE0, 0x00,
+ 0xDA, 0x00, 0xDC, 0x00, 0xF4, 0x00, 0xF2, 0x00, 0x36, 0x01, 0x37, 0x01,
+ 0x38, 0x01, 0x39, 0x01, 0x3B, 0x01, 0x3A, 0x01, 0x34, 0x01, 0x35, 0x01,
+ 0xC9, 0x02, 0xC8, 0x02
+};
+
+static const UINT8 CROM_BANK4_WORLD1[] =
+{
+ 0x24, 0x00, 0x28, 0x00, 0x2C, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00,
+ 0x3C, 0x00, 0x42, 0x00, 0x48, 0x00, 0x4C, 0x00, 0x50, 0x00, 0x54, 0x00,
+ 0x58, 0x00, 0x5A, 0x00, 0x5C, 0x00, 0x60, 0x00, 0x62, 0x00, 0x64, 0x00,
+ 0xAA, 0x01, 0xAC, 0x01, 0xCE, 0x01, 0xD0, 0x01, 0x6E, 0x02, 0x70, 0x02,
+ 0x62, 0x01, 0x64, 0x01, 0x86, 0x01, 0x88, 0x01, 0x6A, 0x02, 0x6C, 0x02,
+ 0x02, 0x02, 0x04, 0x02, 0x06, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0C, 0x02,
+ 0x82, 0x02, 0x84, 0x02, 0x0E, 0x02, 0x10, 0x02, 0x22, 0x02, 0x24, 0x02,
+ 0x86, 0x02, 0x88, 0x02, 0x26, 0x02, 0x2E, 0x02, 0x8A, 0x02, 0x8C, 0x02,
+ 0x28, 0x10, 0x28, 0x10, 0x8E, 0x02, 0x90, 0x02
+};
+
+static const UINT8 CROM_BANK4_WORLD2[] =
+{
+ 0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x46, 0x00, 0x4E, 0x00,
+ 0x52, 0x00, 0x56, 0x00, 0x5A, 0x00, 0x5E, 0x00, 0x60, 0x00, 0x62, 0x00,
+ 0x66, 0x00, 0x68, 0x00, 0x6A, 0x00, 0x6E, 0x00, 0x76, 0x00, 0x7E, 0x00,
+ 0x82, 0x00, 0x86, 0x00, 0x8A, 0x00, 0x01, 0x03, 0x03, 0x03, 0x05, 0x03,
+ 0x07, 0x03, 0x01, 0x03, 0x03, 0x03, 0x05, 0x03, 0x07, 0x03, 0x23, 0x03,
+ 0x21, 0x03, 0x25, 0x03, 0x27, 0x03, 0x29, 0x03, 0x2B, 0x03, 0x25, 0x03,
+ 0x27, 0x03, 0x29, 0x03, 0x2B, 0x03, 0x47, 0x03, 0x23, 0x03, 0x61, 0x03,
+ 0x63, 0x03, 0x61, 0x03, 0x63, 0x03, 0x67, 0x03, 0x65, 0x03, 0x49, 0x03,
+ 0x49, 0x03, 0x67, 0x03, 0x65, 0x03, 0x69, 0x03, 0x69, 0x03, 0xC9, 0x03,
+ 0xC7, 0x03, 0x85, 0x03, 0x87, 0x03, 0x89, 0x03, 0x8B, 0x03, 0x85, 0x03,
+ 0x87, 0x03, 0x89, 0x03, 0x8B, 0x03, 0xC9, 0x03, 0xC7, 0x03, 0xAB, 0x03,
+ 0xAD, 0x03, 0xAF, 0x03, 0xC1, 0x03, 0xC5, 0x03, 0xC3, 0x03
+};
+
+static const UINT8 CROM_BANK4_WORLD3[] =
+{
+ 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x40, 0x00, 0x44, 0x00,
+ 0x48, 0x00, 0x4A, 0x00, 0x4C, 0x00, 0x50, 0x00, 0x54, 0x00, 0x58, 0x00,
+ 0x5C, 0x00, 0x5E, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00, 0x6C, 0x00,
+ 0x70, 0x00, 0x7A, 0x00, 0x84, 0x00, 0x88, 0x00, 0xA2, 0x00, 0xBC, 0x00,
+ 0x51, 0x04, 0x53, 0x04, 0x51, 0x04, 0x53, 0x04, 0x51, 0x04, 0x51, 0x04,
+ 0x55, 0x04, 0x57, 0x04, 0x55, 0x04, 0x57, 0x04, 0x55, 0x04, 0x55, 0x04,
+ 0x59, 0x04, 0x59, 0x04, 0x59, 0x04, 0x9F, 0x04, 0x5D, 0x04, 0x5B, 0x04,
+ 0x5D, 0x04, 0x5B, 0x04, 0x95, 0x04, 0x93, 0x04, 0x5F, 0x04, 0x5F, 0x04,
+ 0x99, 0x04, 0x97, 0x04, 0x75, 0x04, 0x77, 0x04, 0x7F, 0x04, 0x91, 0x04,
+ 0x9D, 0x04, 0x9B, 0x04, 0xB1, 0x04, 0xB3, 0x04, 0xB5, 0x04, 0xB7, 0x04,
+ 0xB9, 0x04, 0xB1, 0x04, 0xB3, 0x04, 0xB5, 0x04, 0xB7, 0x04, 0xB9, 0x04,
+ 0xBD, 0x04, 0xBB, 0x04, 0xD6, 0x04, 0xD7, 0x04, 0xD8, 0x04, 0xD9, 0x04,
+ 0xDA, 0x04, 0xDB, 0x04, 0xDC, 0x04, 0xDD, 0x04, 0xDE, 0x04, 0xDF, 0x04,
+ 0xE0, 0x04, 0xE1, 0x04, 0xE2, 0x04, 0xD6, 0x04, 0xD7, 0x04, 0xD8, 0x04,
+ 0xD9, 0x04, 0xDA, 0x04, 0xDB, 0x04, 0xDC, 0x04, 0xDD, 0x04, 0xDE, 0x04,
+ 0xDF, 0x04, 0xE0, 0x04, 0xE1, 0x04, 0xE2, 0x04, 0x12, 0x05, 0x11, 0x05
+};
+
+static const UINT8 CROM_BANK4_WORLD4[] =
+{
+ 0x24, 0x00, 0x24, 0x00, 0x34, 0x00, 0x38, 0x00, 0x38, 0x00, 0x60, 0x00,
+ 0x64, 0x00, 0x64, 0x00, 0x7C, 0x00, 0x80, 0x00, 0x80, 0x00, 0x90, 0x00,
+ 0x94, 0x00, 0x94, 0x00, 0x96, 0x00, 0x9A, 0x00, 0x9A, 0x00, 0xB2, 0x00,
+ 0x56, 0x05, 0x57, 0x05, 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05,
+ 0x5C, 0x05, 0x5D, 0x05, 0x87, 0x05, 0x86, 0x05, 0x5E, 0x05, 0x5F, 0x05,
+ 0x60, 0x05, 0x61, 0x05, 0x62, 0x05, 0x63, 0x05, 0x5E, 0x05, 0x5F, 0x05,
+ 0x60, 0x05, 0x61, 0x05, 0x62, 0x05, 0x63, 0x05, 0x64, 0x05, 0x65, 0x05,
+ 0x66, 0x05, 0x67, 0x05, 0x66, 0x05, 0x65, 0x05, 0x64, 0x05, 0x63, 0x05,
+ 0x85, 0x05, 0x84, 0x05, 0x68, 0x05, 0x69, 0x05, 0x6A, 0x05, 0x6B, 0x05,
+ 0x6C, 0x05, 0x6D, 0x05, 0x6E, 0x05, 0x6F, 0x05, 0x70, 0x05, 0x71, 0x05,
+ 0x72, 0x05, 0x6D, 0x05, 0x89, 0x05, 0x88, 0x05, 0x73, 0x05, 0x74, 0x05,
+ 0x75, 0x05, 0x76, 0x05, 0x77, 0x05, 0x78, 0x05, 0x79, 0x05, 0x7A, 0x05,
+ 0x8B, 0x05, 0x8A, 0x05, 0x7B, 0x05, 0x8C, 0x05, 0x8C, 0x05, 0x4A, 0x05,
+ 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, 0x50, 0x05,
+ 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x83, 0x05,
+ 0x82, 0x05
+};
+
+static const UINT8 CROM_BANK4_WORLD5[] =
+{
+ 0x24, 0x00, 0x2C, 0x00, 0x34, 0x00, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00,
+ 0x4C, 0x00, 0x54, 0x00, 0x5C, 0x00, 0x60, 0x00, 0x64, 0x00, 0x68, 0x00,
+ 0x6C, 0x00, 0x78, 0x00, 0x84, 0x00, 0x88, 0x00, 0x8C, 0x00, 0x90, 0x00,
+ 0x43, 0x06, 0x45, 0x06, 0x47, 0x06, 0x49, 0x06, 0x43, 0x06, 0x45, 0x06,
+ 0x47, 0x06, 0x49, 0x06, 0x65, 0x06, 0x63, 0x06, 0x6D, 0x06, 0x6F, 0x06,
+ 0x71, 0x06, 0x83, 0x06, 0x6D, 0x06, 0x6F, 0x06, 0x71, 0x06, 0x83, 0x06,
+ 0x6F, 0x06, 0x83, 0x06, 0x85, 0x06, 0x87, 0x06, 0x89, 0x06, 0x8B, 0x06,
+ 0x85, 0x06, 0x87, 0x06, 0x89, 0x06, 0x8B, 0x06, 0x8F, 0x06, 0x8D, 0x06,
+ 0xAD, 0x06, 0xAF, 0x06, 0xAD, 0x06, 0xAF, 0x06, 0xC3, 0x06, 0xB1, 0x06,
+ 0xC5, 0x06, 0xC7, 0x06, 0xC9, 0x06, 0xCB, 0x06, 0xCD, 0x06, 0xCF, 0x06,
+ 0xC5, 0x06, 0xC7, 0x06, 0xC9, 0x06, 0xCB, 0x06, 0xCD, 0x06, 0xCF, 0x06,
+ 0xCB, 0x06, 0xC5, 0x06, 0xE3, 0x06, 0xD1, 0x06, 0xE3, 0x06, 0xD1, 0x06,
+ 0xE5, 0x06, 0xE3, 0x06
+};
+
+static const UINT8 CROM_BANK4_WORLD6[] =
+{
+ 0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x46, 0x00, 0x4E, 0x00,
+ 0x52, 0x00, 0x5A, 0x00, 0x62, 0x00, 0x66, 0x00, 0x6A, 0x00, 0x6E, 0x00,
+ 0x72, 0x00, 0x76, 0x00, 0x7A, 0x00, 0x7E, 0x00, 0x82, 0x00, 0x86, 0x00,
+ 0x8A, 0x00, 0x8E, 0x00, 0x92, 0x00, 0x5B, 0x08, 0x5D, 0x08, 0x5F, 0x08,
+ 0x61, 0x08, 0x5B, 0x08, 0x5D, 0x08, 0x5F, 0x08, 0x61, 0x08, 0x65, 0x08,
+ 0x63, 0x08, 0x67, 0x08, 0x69, 0x08, 0x7B, 0x08, 0x7D, 0x08, 0x67, 0x08,
+ 0x69, 0x08, 0x7B, 0x08, 0x7D, 0x08, 0x81, 0x08, 0x7F, 0x08, 0x83, 0x08,
+ 0x85, 0x08, 0x87, 0x08, 0x89, 0x08, 0x83, 0x08, 0x85, 0x08, 0x87, 0x08,
+ 0x89, 0x08, 0x9D, 0x08, 0x9B, 0x08, 0x9F, 0x08, 0xA1, 0x08, 0x9F, 0x08,
+ 0xA1, 0x08, 0xA5, 0x08, 0xA3, 0x08, 0xA7, 0x08, 0xA9, 0x08, 0xA7, 0x08,
+ 0xA9, 0x08, 0xBD, 0x08, 0xBB, 0x08, 0xBF, 0x08, 0xC1, 0x08, 0xBF, 0x08,
+ 0xC1, 0x08, 0xC5, 0x08, 0xC3, 0x08, 0xDD, 0x08, 0xDF, 0x08, 0xDD, 0x08,
+ 0xDF, 0x08, 0xE1, 0x08, 0xC7, 0x08, 0xC7, 0x08
+};
+
+static const UINT8 CROM_BANK4_WORLD7[] =
+{
+ 0x2A, 0x00, 0x32, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x42, 0x00, 0x46, 0x00,
+ 0x4A, 0x00, 0x4E, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5E, 0x00, 0x66, 0x00,
+ 0x6A, 0x00, 0x6E, 0x00, 0x72, 0x00, 0x76, 0x00, 0x78, 0x00, 0x7A, 0x00,
+ 0x7E, 0x00, 0x82, 0x00, 0x86, 0x00, 0xA1, 0x05, 0xA3, 0x05, 0xA5, 0x05,
+ 0xA7, 0x05, 0xA9, 0x05, 0xAB, 0x05, 0xAD, 0x05, 0xAF, 0x05, 0xC1, 0x05,
+ 0xC3, 0x05, 0xC5, 0x05, 0xC7, 0x05, 0xC5, 0x05, 0xC7, 0x05, 0xE3, 0x05,
+ 0xE5, 0x05, 0xE7, 0x05, 0xE9, 0x05, 0xED, 0x05, 0xEF, 0x05, 0x03, 0x06,
+ 0x05, 0x06, 0x58, 0x10, 0x5A, 0x10, 0x5C, 0x10, 0x5E, 0x10, 0x58, 0x10,
+ 0x5A, 0x10, 0x5C, 0x10, 0x5E, 0x10, 0x62, 0x10, 0x64, 0x10, 0x25, 0x06,
+ 0x27, 0x06, 0x25, 0x06, 0x27, 0x06, 0x29, 0x06, 0x2B, 0x06, 0x2F, 0x06,
+ 0x2F, 0x06, 0x2D, 0x06, 0x2F, 0x06, 0x9C, 0x05, 0x9D, 0x05, 0x9C, 0x05,
+ 0x9D, 0x05, 0x78, 0x10, 0x9D, 0x05
+};
+
+static const UINT8 CROM_BANK4_WORLD8[] =
+{
+ 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x40, 0x00,
+ 0x42, 0x00, 0x46, 0x00, 0x4A, 0x00, 0x4E, 0x00, 0x5C, 0x00, 0x6A, 0x00,
+ 0x6E, 0x00, 0x70, 0x00, 0x72, 0x00, 0x76, 0x00, 0x7A, 0x00, 0x7E, 0x00,
+ 0x82, 0x00, 0x88, 0x00, 0x8E, 0x00, 0x92, 0x00, 0x96, 0x00, 0x9A, 0x00,
+ 0xB0, 0x09, 0xB2, 0x09, 0xB0, 0x09, 0xB2, 0x09, 0xB4, 0x09, 0xB0, 0x09,
+ 0xB6, 0x09, 0xB6, 0x09, 0xB6, 0x09, 0xB8, 0x09, 0xBA, 0x09, 0xB8, 0x09,
+ 0xBA, 0x09, 0xBC, 0x09, 0xB8, 0x09, 0xBE, 0x09, 0xD0, 0x09, 0xD2, 0x09,
+ 0xD4, 0x09, 0xD6, 0x09, 0xD8, 0x09, 0xDA, 0x09, 0xBE, 0x09, 0xD0, 0x09,
+ 0xD2, 0x09, 0xD4, 0x09, 0xD6, 0x09, 0xD8, 0x09, 0xDA, 0x09, 0xDC, 0x09,
+ 0xD4, 0x09, 0xDE, 0x09, 0xDE, 0x09, 0xF4, 0x09, 0xDE, 0x09, 0xF6, 0x09,
+ 0xF8, 0x09, 0xF6, 0x09, 0xF8, 0x09, 0x1A, 0x0A, 0xF6, 0x09, 0x1C, 0x0A,
+ 0x1E, 0x0A, 0x30, 0x0A, 0x1C, 0x0A, 0x1E, 0x0A, 0x30, 0x0A, 0x32, 0x0A,
+ 0x1C, 0x0A, 0x34, 0x0A, 0x36, 0x0A, 0x34, 0x0A, 0x36, 0x0A, 0x38, 0x0A,
+ 0x36, 0x0A
+};
+
+static const UINT8 CROM_BANK4_WORLD9[] =
+{
+ 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x40, 0x00, 0x48, 0x00, 0x50, 0x00,
+ 0x58, 0x00, 0x60, 0x00, 0x68, 0x00, 0x70, 0x00, 0x78, 0x00, 0x80, 0x00,
+ 0x88, 0x00, 0x90, 0x00, 0x98, 0x00, 0xA0, 0x00, 0xA6, 0x00, 0xAC, 0x00,
+ 0xB4, 0x00, 0xBC, 0x00, 0xC4, 0x00, 0xCC, 0x00, 0xD0, 0x00, 0xD4, 0x00,
+ 0xAF, 0x0B, 0xB1, 0x0B, 0xAF, 0x0B, 0xB1, 0x0B, 0xB3, 0x0B, 0xB5, 0x0B,
+ 0xEF, 0x0F, 0xF0, 0x0F, 0xB7, 0x0B, 0xB9, 0x0B, 0xBB, 0x0B, 0xBD, 0x0B,
+ 0xB7, 0x0B, 0xB9, 0x0B, 0xBB, 0x0B, 0xBD, 0x0B, 0xCF, 0x0B, 0xD1, 0x0B,
+ 0xF1, 0x0F, 0xF2, 0x0F, 0x47, 0x11, 0x49, 0x11, 0x4B, 0x11, 0x4D, 0x11,
+ 0x47, 0x11, 0x49, 0x11, 0x4B, 0x11, 0x4D, 0x11, 0x4F, 0x11, 0x51, 0x11,
+ 0xFD, 0x0F, 0xFE, 0x0F, 0xEF, 0x0B, 0xF1, 0x0B, 0xF3, 0x0B, 0xF5, 0x0B,
+ 0xEF, 0x0B, 0xF1, 0x0B, 0xF3, 0x0B, 0xF5, 0x0B, 0xF7, 0x0B, 0xF9, 0x0B,
+ 0xF3, 0x0F, 0xF4, 0x0F, 0xFB, 0x0B, 0xFD, 0x0B, 0x0F, 0x0C, 0x11, 0x0C,
+ 0xFB, 0x0B, 0xFD, 0x0B, 0x0F, 0x0C, 0x11, 0x0C, 0x13, 0x0C, 0x15, 0x0C,
+ 0xF5, 0x0F, 0xF6, 0x0F, 0x6B, 0x11, 0x6D, 0x11, 0x6F, 0x11, 0x6B, 0x11,
+ 0x6D, 0x11, 0x6F, 0x11, 0x1D, 0x0C, 0x2F, 0x0C, 0xF7, 0x0F, 0xF8, 0x0F,
+ 0x31, 0x0C, 0x33, 0x0C, 0x35, 0x0C, 0x37, 0x0C, 0x31, 0x0C, 0x33, 0x0C,
+ 0x35, 0x0C, 0x37, 0x0C, 0x39, 0x0C, 0x3B, 0x0C, 0xF9, 0x0F, 0xFA, 0x0F,
+ 0x3D, 0x0C, 0x4F, 0x0C, 0x3D, 0x0C, 0x4F, 0x0C, 0x51, 0x0C, 0x53, 0x0C,
+ 0xFB, 0x0F, 0xFC, 0x0F, 0xDC, 0x02, 0xDD, 0x02
+};
+
+static const UINT8 CROM_BANK5_WORLD0[] =
+{
+ 0x1C, 0x00, 0x1C, 0x00, 0x32, 0x00, 0x32, 0x00, 0x48, 0x00, 0x48, 0x00,
+ 0xB6, 0x00, 0x5E, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x74, 0x00, 0x74, 0x00,
+ 0x8A, 0x00, 0x8A, 0x00, 0x01, 0x08, 0xC4, 0x19, 0x49, 0x08, 0xC4, 0x19,
+ 0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01,
+ 0xFF, 0xFF, 0xC9, 0x08, 0xD3, 0x19, 0x09, 0x09, 0xC4, 0x19, 0x45, 0x09,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF,
+ 0x80, 0x09, 0xC5, 0x19, 0xC8, 0x09, 0xC3, 0x19, 0x04, 0x0A, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A,
+ 0xC7, 0x29, 0x89, 0x0A, 0xC7, 0x29, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x0B, 0x45, 0x29,
+ 0x49, 0x0B, 0x43, 0x29, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0xD0, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x49, 0x0B, 0x47, 0x29, 0x49, 0x0B,
+ 0x47, 0x29, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02,
+ 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x0B, 0xC1, 0x18, 0x08, 0x0C, 0xC1, 0x18,
+ 0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xD0, 0x02, 0x00, 0x01,
+ 0xFF, 0xFF, 0x80, 0x04, 0xC0, 0x39, 0x80, 0x0C, 0xC3, 0x39, 0xC4, 0x0C,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x3C, 0x00, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD1[] =
+{
+ 0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00,
+ 0x01, 0x08, 0xC4, 0x19, 0x49, 0x08, 0xC4, 0x19, 0x84, 0x08, 0xC7, 0x18,
+ 0xE6, 0x5A, 0xBF, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x08,
+ 0xC4, 0x19, 0x09, 0x09, 0xC4, 0x19, 0x44, 0x09, 0xC7, 0x18, 0xEB, 0x5A,
+ 0xC1, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0x45, 0x1A,
+ 0x89, 0x0A, 0x43, 0x1A, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x11, 0xC1, 0x29, 0xC9, 0x11,
+ 0xC1, 0x29, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02,
+ 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0xC0, 0x19, 0x49, 0x03, 0xC0, 0x19,
+ 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02, 0x00, 0x01,
+ 0xFF, 0xFF, 0xC9, 0x03, 0xC0, 0x39, 0x09, 0x04, 0xC0, 0x39, 0x44, 0x0C,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x58, 0x02, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD2[] =
+{
+ 0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00,
+ 0x92, 0x00, 0x01, 0x18, 0xC7, 0x39, 0x49, 0x18, 0xC5, 0x39, 0x84, 0x08,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF,
+ 0xC1, 0x08, 0xC7, 0x39, 0x09, 0x09, 0xC5, 0x39, 0x44, 0x09, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x09,
+ 0x47, 0x49, 0xC9, 0x09, 0x45, 0x49, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x02, 0xC7, 0x49,
+ 0x89, 0x02, 0xC5, 0x49, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0x43, 0x29, 0x49, 0x03,
+ 0x42, 0x29, 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01,
+ 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x1B, 0x43, 0x29, 0x09, 0x1C, 0x42, 0x29,
+ 0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0x81, 0x0C, 0x43, 0x39, 0xC9, 0x0C, 0x41, 0x39, 0x04, 0x0D,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD3[] =
+{
+ 0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00,
+ 0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0xC1, 0x39, 0x49, 0x08, 0xC1, 0x39,
+ 0x84, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0xC1, 0x08, 0xC1, 0x39, 0x09, 0x09, 0xC1, 0x39, 0x44, 0x09,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF,
+ 0x81, 0x01, 0x40, 0x39, 0xC9, 0x01, 0x40, 0x39, 0x04, 0x0A, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A,
+ 0xC3, 0x39, 0x89, 0x0A, 0xC3, 0x39, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x01, 0x03, 0x40, 0x19,
+ 0x49, 0x03, 0x40, 0x19, 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xD3, 0x49, 0x09, 0x0C,
+ 0xC9, 0x49, 0x44, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x78, 0x00,
+ 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x24, 0xC7, 0x1B, 0xC9, 0x24, 0xC7, 0x1B,
+ 0x04, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0x40, 0x65, 0x41, 0x29, 0x88, 0x65, 0x40, 0x29, 0xC4, 0x0D,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD4[] =
+{
+ 0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00,
+ 0x00, 0x38, 0xC6, 0x18, 0x48, 0x38, 0xC6, 0x18, 0x84, 0x08, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x98,
+ 0xC9, 0x18, 0x08, 0x99, 0xC9, 0x18, 0x44, 0x09, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x59, 0xC9, 0x18,
+ 0xC8, 0x59, 0xC9, 0x18, 0x04, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x40, 0x3A, 0xC4, 0x18, 0x88, 0x3A,
+ 0xC4, 0x18, 0xC4, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
+ 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0x80, 0x18, 0x48, 0x03, 0x80, 0x18,
+ 0x84, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0xC0, 0x5B, 0x85, 0x31, 0x08, 0x5C, 0x85, 0x31, 0x44, 0x0C,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD5[] =
+{
+ 0x0C, 0x00, 0x22, 0x00, 0x38, 0x00, 0x4E, 0x00, 0x64, 0x00, 0x7A, 0x00,
+ 0x01, 0x18, 0x43, 0x39, 0x49, 0x18, 0x43, 0x39, 0x85, 0x08, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x18,
+ 0xC3, 0x39, 0x09, 0x19, 0xC3, 0x39, 0x45, 0x09, 0xC3, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x19, 0x43, 0x39,
+ 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0x43, 0x19, 0x89, 0x0A,
+ 0x43, 0x19, 0xC5, 0x0A, 0x47, 0x19, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
+ 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x2B, 0xC3, 0x19, 0x49, 0x2B, 0xC2, 0x19,
+ 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0xC1, 0x0B, 0xC3, 0x18, 0x09, 0x0C, 0xC3, 0x18, 0x45, 0x0C,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD6[] =
+{
+ 0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00,
+ 0x92, 0x00, 0x01, 0x18, 0x45, 0x39, 0x49, 0x18, 0x43, 0x39, 0x85, 0x08,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF,
+ 0xC1, 0x18, 0x45, 0x39, 0x09, 0x19, 0x43, 0x39, 0x45, 0x09, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x19,
+ 0x45, 0x39, 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x0A, 0xC7, 0x39,
+ 0x89, 0x0A, 0xC5, 0x39, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0x68, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x0B, 0x05, 0x42, 0x49, 0x0B,
+ 0x03, 0x42, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
+ 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xC5, 0x39, 0x09, 0x0C, 0xC3, 0x39,
+ 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0x81, 0x0C, 0x4D, 0x0A, 0xC9, 0x0C, 0x4B, 0x0A, 0x05, 0x0D,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD7[] =
+{
+ 0x0E, 0x00, 0x24, 0x00, 0x3A, 0x00, 0x50, 0x00, 0x66, 0x00, 0x7C, 0x00,
+ 0x92, 0x00, 0x01, 0x18, 0xC5, 0x41, 0x49, 0x18, 0xC3, 0x41, 0x85, 0x08,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF,
+ 0xC1, 0x08, 0xC5, 0x41, 0x09, 0x09, 0xC3, 0x41, 0x45, 0x09, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x09,
+ 0x45, 0x4A, 0xC9, 0x09, 0x43, 0x4A, 0x05, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x1A, 0xC5, 0x39,
+ 0x81, 0x1A, 0xC3, 0x39, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0xE0, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x0B, 0x45, 0x5A, 0x49, 0x0B,
+ 0x43, 0x5A, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01,
+ 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x03, 0xC5, 0x59, 0x09, 0x04, 0xC3, 0x59,
+ 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0x80, 0x0C, 0x45, 0x29, 0xC8, 0x0C, 0x43, 0x29, 0x04, 0x0D,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0xE0, 0x01, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD8[] =
+{
+ 0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00,
+ 0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0x43, 0x49, 0x49, 0x08, 0x43, 0x49,
+ 0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0xC1, 0x00, 0x43, 0x39, 0x09, 0x01, 0x43, 0x49, 0x45, 0x01,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF,
+ 0x81, 0x09, 0xC3, 0x59, 0xC9, 0x09, 0xC3, 0x59, 0x05, 0x0A, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x32,
+ 0xC3, 0x5B, 0x89, 0x32, 0xC3, 0x5B, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x03, 0xC3, 0x49,
+ 0x49, 0x03, 0xC3, 0x49, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x0B, 0xC3, 0x19, 0x09, 0x0C,
+ 0xC3, 0x19, 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01,
+ 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x14, 0xC5, 0x39, 0xC9, 0x14, 0xC3, 0x39,
+ 0x05, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01,
+ 0xFF, 0xFF, 0x41, 0x0D, 0xC7, 0x39, 0x89, 0x0D, 0xC5, 0x39, 0xC5, 0x0D,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x68, 0x01, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK5_WORLD9[] =
+{
+ 0x10, 0x00, 0x26, 0x00, 0x3C, 0x00, 0x52, 0x00, 0x68, 0x00, 0x7E, 0x00,
+ 0x94, 0x00, 0xAA, 0x00, 0x01, 0x08, 0x03, 0x1A, 0x49, 0x08, 0x03, 0x1A,
+ 0x85, 0x08, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01,
+ 0xFF, 0xFF, 0xC1, 0x18, 0xC3, 0x18, 0x09, 0x19, 0x03, 0x1A, 0x45, 0x09,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF,
+ 0x81, 0x19, 0x45, 0x39, 0xC9, 0x19, 0x43, 0x39, 0x05, 0x0A, 0xC7, 0x18,
+ 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0x41, 0x1A,
+ 0x45, 0x18, 0x89, 0x1A, 0x43, 0x18, 0xC5, 0x0A, 0xC7, 0x18, 0xC3, 0x5A,
+ 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x1B, 0xC5, 0x18,
+ 0x49, 0x1B, 0xC3, 0x18, 0x85, 0x0B, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E,
+ 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF, 0xC1, 0x13, 0x47, 0x39, 0x09, 0x14,
+ 0x45, 0x39, 0x45, 0x0C, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05,
+ 0x00, 0x01, 0xFF, 0xFF, 0x81, 0x1C, 0x45, 0x19, 0xC9, 0x1C, 0x43, 0x19,
+ 0x05, 0x0D, 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01,
+ 0xFF, 0xFF, 0x41, 0x0D, 0xC5, 0x18, 0x89, 0x0D, 0xC3, 0x18, 0xC5, 0x0D,
+ 0xC7, 0x18, 0xC3, 0x5A, 0xB7, 0x6E, 0x00, 0x05, 0x00, 0x01, 0xFF, 0xFF
+};
+
+static const UINT8 CROM_BANK6[] =
+{
+ 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x04,
+ 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x30, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x42, 0x00, 0x00, 0x33, 0x04, 0x00, 0x54, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x50, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x33, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x33, 0x20, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x33, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x34, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x23, 0x02, 0x03, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x12, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x22, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x30, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x32, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x30, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x22, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x12, 0x11, 0x02, 0x00, 0x00, 0x00, 0x00, 0x03, 0x21, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x01, 0x22, 0x03, 0x00, 0x00, 0x00, 0x00, 0x12, 0x21, 0x22, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x31,
+ 0x00, 0x00, 0x00, 0x00, 0x21, 0x01, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x33, 0x20, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00
+};
+
+static const UINT8 CROM_BANK6_EXTRA[] =
+{
+ 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x35, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x12, 0x02, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x22, 0x21, 0x02, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x33, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x34, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x24, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x05, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01,
+ 0x50, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x01, 0x50, 0x00, 0x04, 0x00,
+ 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x21,
+ 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x03,
+ 0x00, 0x00, 0x00, 0x00, 0x21, 0x02, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x02, 0x44, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x11, 0x12, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x12, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x32, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x31, 0x12, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x31, 0x22, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x03, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x33, 0x20, 0x00, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x30, 0x00, 0x02, 0x11, 0x00, 0x00, 0x00, 0x00
+};
+
+static const UINT8 CROM_BANK7_WORLD0[] = { 0x03, 0x03, 0x03, 0x03, 0x0C, 0x0C, 0x0A, 0x07, 0x0A, 0x0A, 0x08, 0x08, 0x08, 0x08 };
+static const UINT8 CROM_BANK7_WORLD1[] = { 0x03, 0x05, 0x01, 0x02, 0x04, 0x04 };
+static const UINT8 CROM_BANK7_WORLD2[] = { 0x03, 0x05, 0x07, 0x07, 0x08, 0x08, 0x01 };
+static const UINT8 CROM_BANK7_WORLD3[] = { 0x07, 0x07, 0x07, 0x08, 0x05, 0x08, 0x07, 0x0B };
+static const UINT8 CROM_BANK7_WORLD4[] = { 0x0A, 0x0B, 0x0A, 0x0A, 0x10, 0x10 };
+static const UINT8 CROM_BANK7_WORLD5[] = { 0x05, 0x08, 0x04, 0x08, 0x08, 0x07 };
+static const UINT8 CROM_BANK7_WORLD6[] = { 0x04, 0x07, 0x05, 0x08, 0x06, 0x08, 0x03 };
+static const UINT8 CROM_BANK7_WORLD7[] = { 0x07, 0x06, 0x06, 0x05, 0x08, 0x07, 0x0A };
+static const UINT8 CROM_BANK7_WORLD8[] = { 0x06, 0x05, 0x01, 0x08, 0x05, 0x05, 0x06, 0x08 };
+static const UINT8 CROM_BANK7_WORLD9[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
+
+static const struct CBANK CROM_BANK4[] =
+{
+ { CROM_BANK4_WORLD0, sizeof CROM_BANK4_WORLD0 },
+ { CROM_BANK4_WORLD1, sizeof CROM_BANK4_WORLD1 },
+ { CROM_BANK4_WORLD2, sizeof CROM_BANK4_WORLD2 },
+ { CROM_BANK4_WORLD3, sizeof CROM_BANK4_WORLD3 },
+ { CROM_BANK4_WORLD4, sizeof CROM_BANK4_WORLD4 },
+ { CROM_BANK4_WORLD5, sizeof CROM_BANK4_WORLD5 },
+ { CROM_BANK4_WORLD6, sizeof CROM_BANK4_WORLD6 },
+ { CROM_BANK4_WORLD7, sizeof CROM_BANK4_WORLD7 },
+ { CROM_BANK4_WORLD8, sizeof CROM_BANK4_WORLD8 },
+ { CROM_BANK4_WORLD9, sizeof CROM_BANK4_WORLD9 },
+};
+
+static const struct CBANK CROM_BANK5[] =
+{
+ { CROM_BANK5_WORLD0, sizeof CROM_BANK5_WORLD0 },
+ { CROM_BANK5_WORLD1, sizeof CROM_BANK5_WORLD1 },
+ { CROM_BANK5_WORLD2, sizeof CROM_BANK5_WORLD2 },
+ { CROM_BANK5_WORLD3, sizeof CROM_BANK5_WORLD3 },
+ { CROM_BANK5_WORLD4, sizeof CROM_BANK5_WORLD4 },
+ { CROM_BANK5_WORLD5, sizeof CROM_BANK5_WORLD5 },
+ { CROM_BANK5_WORLD6, sizeof CROM_BANK5_WORLD6 },
+ { CROM_BANK5_WORLD7, sizeof CROM_BANK5_WORLD7 },
+ { CROM_BANK5_WORLD8, sizeof CROM_BANK5_WORLD8 },
+ { CROM_BANK5_WORLD9, sizeof CROM_BANK5_WORLD9 },
+};
+
+static const struct CBANK CROM_BANK7[] =
+{
+ { CROM_BANK7_WORLD0, sizeof CROM_BANK7_WORLD0 },
+ { CROM_BANK7_WORLD1, sizeof CROM_BANK7_WORLD1 },
+ { CROM_BANK7_WORLD2, sizeof CROM_BANK7_WORLD2 },
+ { CROM_BANK7_WORLD3, sizeof CROM_BANK7_WORLD3 },
+ { CROM_BANK7_WORLD4, sizeof CROM_BANK7_WORLD4 },
+ { CROM_BANK7_WORLD5, sizeof CROM_BANK7_WORLD5 },
+ { CROM_BANK7_WORLD6, sizeof CROM_BANK7_WORLD6 },
+ { CROM_BANK7_WORLD7, sizeof CROM_BANK7_WORLD7 },
+ { CROM_BANK7_WORLD8, sizeof CROM_BANK7_WORLD8 },
+ { CROM_BANK7_WORLD9, sizeof CROM_BANK7_WORLD9 },
+};
+
+/*************************************
+ *
+ * C-Chip operation
+ *
+ *************************************/
+
+static const UINT16 cchip_extra_patch[][8] =
+{
+ { 0x0168, 0x0078, 0x0168, 0x0168, 0x0168, 0x02D0, 0x0168, 0x003C },
+ { 0x0258, 0x0258, 0x0258, 0x0258, 0x0258, 0x0258, 0x0000, 0x0000 },
+ { 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x0000 },
+ { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x001E, 0x0168, 0x0168 },
+ { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000, 0x0000 },
+ { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000, 0x0000 },
+ { 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0168, 0x0000 },
+ { 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x01E0, 0x0000 },
+ { 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4, 0x01A4 },
+ { 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500, 0x0500 }
+};
+
+static const UINT8 cchip_goalin[15][6] =
+{
+ { 0x00, 0x00, 0x28, 0x28, 0x50, 0x50 },
+ { 0x00, 0x00, 0x00, 0x00, 0x50, 0x50 },
+ { 0x00, 0x10, 0x20, 0x30, 0x00, 0x10 },
+ { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50 },
+ { 0x00, 0x18, 0x30, 0x00, 0x18, 0x30 },
+ { 0x00, 0x18, 0x30, 0x30, 0x18, 0x00 },
+ { 0x00, 0x28, 0x50, 0x00, 0x28, 0x50 },
+ { 0x00, 0x30, 0x20, 0x50, 0x10, 0x20 },
+ { 0x00, 0x50, 0x00, 0x50, 0x00, 0x50 },
+ { 0x30, 0x18, 0x00, 0x30, 0x18, 0x00 },
+ { 0x30, 0x18, 0x00, 0x00, 0x18, 0x30 },
+ { 0x30, 0x00, 0x10, 0x40, 0x50, 0x20 },
+ { 0x30, 0x20, 0x10, 0x00, 0x10, 0x00 },
+ { 0x50, 0x40, 0x30, 0x20, 0x10, 0x00 },
+ { 0x50, 0x50, 0x50, 0x50, 0x00, 0x00 }
+};
+
+static const UINT16 cchip_round_height[] =
+{
+ 0x02DC, 0x03B4, 0x0444, 0x04BC, 0x03B4, 0x0444, 0x05DC, 0x050C,
+ 0x0594, 0x06B4, 0x06B4, 0x0894, 0x065C, 0x06CC, 0x07BC, 0x08BC,
+ 0x0704, 0x059C, 0x030C, 0x0504, 0x0504, 0x0564, 0x05CC, 0x0644,
+ 0x080C, 0x086C, 0x08E4, 0x0954, 0x065C, 0x06D4, 0x0754, 0x07C4,
+ 0x06D4, 0x0754, 0x0824, 0x0884, 0x080C, 0x086C, 0x08E4, 0x096C,
+ 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999, 0x0999,
+ 0x0999, 0x0999
+};
+
+static const UINT32 cchip_round_address[] =
+{
+ 0x030000, 0x030360, 0x030798, 0x030CA8, 0x0311B8, 0x0315F0, 0x031B00, 0x0321C0,
+ 0x032880, 0x032E68, 0x033600, 0x033D98, 0x0347B8, 0x034E78, 0x035610, 0x035E80,
+ 0x0368A0, 0x037038, 0x037620, 0x037A58, 0x038118, 0x038700, 0x038CE8, 0x0393A8,
+ 0x039A68, 0x03A2D8, 0x03AC20, 0x03B568, 0x03BF88, 0x03C648, 0x03CDE0, 0x03D650,
+ 0x03DEC0, 0x03E658, 0x03EEC8, 0x03F738, 0x040080, 0x0408F0, 0x041238, 0x041B80,
+ 0x0425A0, 0x042678, 0x042750, 0x042828, 0x042900, 0x0429D8, 0x042AB0, 0x042B88,
+ 0x042C60, 0x042D38
+};
+
+static void request_round_data(void)
+{
+ int round = CRAM[1][0x141]; /* 0...49 */
+
+ memcpy(CRAM[1], CROM_BANK1, sizeof CROM_BANK1);
+ memcpy(CRAM[2], CROM_BANK2, sizeof CROM_BANK2);
+
+ CRAM[1][1] = cchip_round_height[round] >> 0;
+ CRAM[1][2] = cchip_round_height[round] >> 8;
+
+ CRAM[1][0x142] = cchip_round_address[round] >> 24;
+ CRAM[1][0x143] = cchip_round_address[round] >> 16;
+ CRAM[1][0x144] = cchip_round_address[round] >> 8;
+ CRAM[1][0x145] = cchip_round_address[round] >> 0;
+
+ /* set the secret room or boss flag */
+
+ CRAM[1][0x148] = (round >= 40 || round % 4 == 3);
+}
+
+static void request_world_data(void)
+{
+ int world = CRAM[0][0x00D] / 4; /* 0...9 */
+
+ /* the extra version has the world data swapped around */
+
+ if (extra_version)
+ {
+ static const UINT8 world_swap[] =
+ {
+ 8, 7, 6, 4, 0, 2, 3, 5, 1, 9
+ };
+
+ world = world_swap[world];
+ }
+
+ /* first two bytes in each bank are left unchanged */
+
+ memcpy(CRAM[4] + 2, CROM_BANK4[world].data, CROM_BANK4[world].size);
+ memcpy(CRAM[5] + 2, CROM_BANK5[world].data, CROM_BANK5[world].size);
+ memcpy(CRAM[7] + 2, CROM_BANK7[world].data, CROM_BANK7[world].size);
+
+ /* banks 5 and 6 are different in the extra version */
+
+ if (extra_version)
+ {
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ UINT16 patch = cchip_extra_patch[world][i];
+
+ if (patch != 0)
+ {
+ CRAM[5][CRAM[5][2] + 22 * i + 18] = patch >> 0;
+ CRAM[5][CRAM[5][2] + 22 * i + 19] = patch >> 8;
+ }
+ }
+
+ memcpy(CRAM[6] + 2, CROM_BANK6_EXTRA, sizeof CROM_BANK6_EXTRA);
+ }
+ else
+ {
+ memcpy(CRAM[6] + 2, CROM_BANK6, sizeof CROM_BANK6);
+ }
+}
+
+static void request_goalin_data(void)
+{
+ int n = mame_rand(Machine) % 15;
+
+ CRAM[1][0x14B] = 0x00; /* x coordinates */
+ CRAM[1][0x14D] = 0x10;
+ CRAM[1][0x14F] = 0x20;
+ CRAM[1][0x151] = 0x38;
+ CRAM[1][0x153] = 0x50;
+ CRAM[1][0x155] = 0x60;
+
+ CRAM[1][0x14A] = cchip_goalin[n][0]; /* y coordinates */
+ CRAM[1][0x14C] = cchip_goalin[n][1];
+ CRAM[1][0x14E] = cchip_goalin[n][2];
+ CRAM[1][0x150] = cchip_goalin[n][3];
+ CRAM[1][0x152] = cchip_goalin[n][4];
+ CRAM[1][0x154] = cchip_goalin[n][5];
+}
+
+static TIMER_CALLBACK( cchip_timer )
+{
+ if (CRAM[1][0x100] == 1)
+ {
+ request_round_data();
+
+ CRAM[1][0x100] = 0xFF;
+ }
+
+ if (CRAM[5][0x000] == 1)
+ {
+ request_world_data();
+
+ CRAM[5][0x000] = 0xFF;
+ }
+
+ if (CRAM[1][0x149] == 1)
+ {
+ request_goalin_data();
+
+ CRAM[1][0x149] = 0xFF;
+ }
+
+ coin_lockout_w(1, CRAM[0][8] & 0x80);
+ coin_lockout_w(0, CRAM[0][8] & 0x40);
+ coin_counter_w(1, CRAM[0][8] & 0x20);
+ coin_counter_w(0, CRAM[0][8] & 0x10);
+
+ CRAM[0][3] = readinputportbytag("800007"); /* STARTn + SERVICE1 */
+ CRAM[0][4] = readinputportbytag("800009"); /* COINn */
+ CRAM[0][5] = readinputportbytag("80000B"); /* Player controls + TILT */
+ CRAM[0][6] = readinputportbytag("80000D"); /* Player controls (cocktail) */
+}
+
+/*************************************
+ *
+ * Writes to C-Chip - Important Bits
+ *
+ *************************************/
+
+WRITE16_HANDLER( rainbow_cchip_ctrl_w )
+{
+ /* value 2 is written here */
+}
+
+WRITE16_HANDLER( rainbow_cchip_bank_w )
+{
+ current_bank = data & 7;
+}
+
+WRITE16_HANDLER( rainbow_cchip_ram_w )
+{
+ CRAM[current_bank][offset] = data;
+}
+
+/*************************************
+ *
+ * Reads from C-Chip
+ *
+ *************************************/
+
+READ16_HANDLER( rainbow_cchip_ctrl_r )
+{
+ /*
+ Bit 2 = Error signal
+ Bit 0 = Ready signal
+ */
+ return 0x01; /* Return 0x05 for C-Chip error */
+}
+
+READ16_HANDLER( rainbow_cchip_ram_r )
+{
+ return CRAM[current_bank][offset];
+}
+
+/*************************************
+ *
+ * C-Chip initialization
+ *
+ *************************************/
+
+void rainbow_cchip_init(int version)
+{
+ int i;
+
+ extra_version = version;
+
+ for (i = 0; i < 8; i++)
+ {
+ CRAM[i] = auto_malloc(0x400);
+
+ state_save_register_item_pointer("cchip", i, CRAM[i], 0x400);
+ }
+
+ state_save_register_item("cchip", 0, current_bank);
+
+ timer_pulse(ATTOTIME_IN_HZ(60), 0, cchip_timer);
+}
diff --git a/src/mame/machine/retofinv.c b/src/mame/machine/retofinv.c
new file mode 100644
index 00000000000..dfdee6cd02b
--- /dev/null
+++ b/src/mame/machine/retofinv.c
@@ -0,0 +1,137 @@
+#include "driver.h"
+#include "cpu/z80/z80.h"
+
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+
+
+/***************************************************************************
+
+ Return of Invaders 68705 protection interface
+
+***************************************************************************/
+
+static UINT8 portA_in,portA_out,ddrA;
+
+READ8_HANDLER( retofinv_68705_portA_r )
+{
+//logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( retofinv_68705_portA_w )
+{
+//logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+ portA_out = data;
+}
+
+WRITE8_HANDLER( retofinv_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 1 W IRQ ack and enable latch which holds data from main Z80 memory
+ * 2 W loads latch to Z80
+ */
+
+static UINT8 portB_in,portB_out,ddrB;
+
+READ8_HANDLER( retofinv_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( retofinv_68705_portB_w )
+{
+//logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ if (main_sent) cpunum_set_input_line(3,0,CLEAR_LINE);
+ main_sent = 0;
+//logerror("read command %02x from main cpu\n",portA_in);
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+//logerror("send command %02x to main cpu\n",portA_out);
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( retofinv_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+
+/*
+ * Port C connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 R 1 when pending command Z80->68705
+ * 1 R 0 when pending command 68705->Z80
+ */
+
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( retofinv_68705_portC_r )
+{
+ portC_in = 0;
+ if (main_sent) portC_in |= 0x01;
+ if (!mcu_sent) portC_in |= 0x02;
+//logerror("%04x: 68705 port C read %02x\n",activecpu_get_pc(),portC_in);
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( retofinv_68705_portC_w )
+{
+logerror("%04x: 68705 port C write %02x\n",activecpu_get_pc(),data);
+ portC_out = data;
+}
+
+WRITE8_HANDLER( retofinv_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+
+WRITE8_HANDLER( retofinv_mcu_w )
+{
+logerror("%04x: mcu_w %02x\n",activecpu_get_pc(),data);
+ from_main = data;
+ main_sent = 1;
+ cpunum_set_input_line(3,0,ASSERT_LINE);
+}
+
+READ8_HANDLER( retofinv_mcu_r )
+{
+logerror("%04x: mcu_r %02x\n",activecpu_get_pc(),from_mcu);
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( retofinv_mcu_status_r )
+{
+ int res = 0;
+
+ /* bit 4 = when 1, mcu is ready to receive data from main cpu */
+ /* bit 5 = when 1, mcu has sent data to the main cpu */
+//logerror("%04x: mcu_status_r\n",activecpu_get_pc());
+ if (!main_sent) res |= 0x10;
+ if (mcu_sent) res |= 0x20;
+
+ return res;
+}
diff --git a/src/mame/machine/s16fd.c b/src/mame/machine/s16fd.c
new file mode 100644
index 00000000000..f74faa9a8d2
--- /dev/null
+++ b/src/mame/machine/s16fd.c
@@ -0,0 +1,198 @@
+/* System 16 and friends FD1094 handling */
+
+/*
+todo:
+
+support multiple FD1094s (does anything /use/ multiple FD1094s?)
+make more configurable (select caches per game?)
+
+*/
+
+#include "driver.h"
+
+#include "cpu/m68000/m68000.h"
+#include "machine/fd1094.h"
+
+
+#define CACHE_ENTRIES 8
+
+static UINT8 *fd1094_key; // the memory region containing key
+static UINT16 *fd1094_cpuregion; // the CPU region with encrypted code
+static UINT32 fd1094_cpuregionsize; // the size of this region in bytes
+
+static UINT16 *fd1094_userregion; // a user region where the current decrypted state is put and executed from
+static UINT16 *fd1094_cacheregion[CACHE_ENTRIES]; // a cache region where CACHE_ENTRIES states are stored to improve performance
+static int fd1094_cached_states[CACHE_ENTRIES]; // array of cached state numbers
+static int fd1094_current_cacheposition; // current position in cache array
+
+static void (*fd1094_set_decrypted)(UINT8 *);
+
+void *fd1094_get_decrypted_base(void)
+{
+ if (!fd1094_key)
+ return NULL;
+ return fd1094_userregion;
+}
+
+static void set_decrypted_region(void)
+{
+ if (fd1094_set_decrypted != NULL)
+ (*fd1094_set_decrypted)((UINT8 *)fd1094_userregion);
+ else
+ memory_set_decrypted_region(0, 0, fd1094_cpuregionsize - 1, fd1094_userregion);
+}
+
+/* this function checks the cache to see if the current state is cached,
+ if it is then it copies the cached data to the user region where code is
+ executed from, if its not cached then it gets decrypted to the current
+ cache position using the functions in fd1094.c */
+static void fd1094_setstate_and_decrypt(int state)
+{
+ int i;
+ UINT32 addr;
+
+ cpunum_set_info_int(0, CPUINFO_INT_REGISTER + M68K_PREF_ADDR, 0x0010); // force a flush of the prefetch cache
+
+ /* set the FD1094 state ready to decrypt.. */
+ state = fd1094_set_state(fd1094_key,state) & 0xff;
+
+ /* first check the cache, if its cached we don't need to decrypt it, just copy */
+ for (i=0;i<CACHE_ENTRIES;i++)
+ {
+ if (fd1094_cached_states[i] == state)
+ {
+ /* copy cached state */
+ fd1094_userregion=fd1094_cacheregion[i];
+ set_decrypted_region();
+ m68k_set_encrypted_opcode_range(0,0,fd1094_cpuregionsize);
+
+ return;
+ }
+ }
+
+ /* mark it as cached (because it will be once we decrypt it) */
+ fd1094_cached_states[fd1094_current_cacheposition]=state;
+
+ for (addr=0;addr<fd1094_cpuregionsize/2;addr++)
+ {
+ UINT16 dat;
+ dat = fd1094_decode(addr,fd1094_cpuregion[addr],fd1094_key,0);
+ fd1094_cacheregion[fd1094_current_cacheposition][addr]=dat;
+ }
+
+ /* copy newly decrypted data to user region */
+ fd1094_userregion=fd1094_cacheregion[fd1094_current_cacheposition];
+ set_decrypted_region();
+ m68k_set_encrypted_opcode_range(0,0,fd1094_cpuregionsize);
+
+ fd1094_current_cacheposition++;
+
+ if (fd1094_current_cacheposition>=CACHE_ENTRIES)
+ {
+ mame_printf_debug("out of cache, performance may suffer, incrase CACHE_ENTRIES!\n");
+ fd1094_current_cacheposition=0;
+ }
+}
+
+/* Callback for CMP.L instructions (state change) */
+static void fd1094_cmp_callback(UINT32 val, int reg)
+{
+ if (reg == 0 && (val & 0x0000ffff) == 0x0000ffff) // ?
+ {
+ fd1094_setstate_and_decrypt((val & 0xffff0000) >> 16);
+ }
+}
+
+/* Callback when the FD1094 enters interrupt code */
+static int fd1094_int_callback (int irq)
+{
+ fd1094_setstate_and_decrypt(FD1094_STATE_IRQ);
+ return (0x60+irq*4)/4; // vector address
+}
+
+static void fd1094_rte_callback (void)
+{
+ fd1094_setstate_and_decrypt(FD1094_STATE_RTE);
+}
+
+
+/* KLUDGE, set the initial PC / SP based on table as we can't decrypt them yet */
+static void fd1094_kludge_reset_values(void)
+{
+ int i;
+
+ for (i = 0;i < 4;i++)
+ fd1094_userregion[i] = fd1094_decode(i,fd1094_cpuregion[i],fd1094_key,1);
+}
+
+
+/* function, to be called from MACHINE_RESET (every reset) */
+void fd1094_machine_init(void)
+{
+ /* punt if no key; this allows us to be called even for non-FD1094 games */
+ if (!fd1094_key)
+ return;
+
+ fd1094_setstate_and_decrypt(FD1094_STATE_RESET);
+ fd1094_kludge_reset_values();
+
+ cpunum_set_info_fct(0, CPUINFO_PTR_M68K_CMPILD_CALLBACK, (genf *)fd1094_cmp_callback);
+ cpunum_set_info_fct(0, CPUINFO_PTR_M68K_RTE_CALLBACK, (genf *)fd1094_rte_callback);
+ cpunum_set_irq_callback(0, fd1094_int_callback);
+}
+
+
+#ifdef MAME_DEBUG
+static void key_changed(void)
+{
+ int addr;
+
+ /* re-decode the against the current parameter into cache entry 0 */
+ for (addr = 0; addr < fd1094_cpuregionsize/2; addr++)
+ {
+ UINT16 dat;
+ dat = fd1094_decode(addr,fd1094_cpuregion[addr],fd1094_key,0);
+ fd1094_cacheregion[0][addr]=dat;
+ }
+
+ /* set cache entry 0 to be the active one, and reset the cache position to 1 */
+ fd1094_userregion = fd1094_cacheregion[0];
+ set_decrypted_region();
+ fd1094_current_cacheposition = 1;
+
+ /* flush the prefetch queue */
+ cpunum_set_info_int(0, CPUINFO_INT_REGISTER + M68K_PREF_ADDR, 0x0010);
+}
+#endif
+
+
+/* startup function, to be called from DRIVER_INIT (once on startup) */
+void fd1094_driver_init(void (*set_decrypted)(UINT8 *))
+{
+ int i;
+
+ fd1094_cpuregion = (UINT16*)memory_region(REGION_CPU1);
+ fd1094_cpuregionsize = memory_region_length(REGION_CPU1);
+ fd1094_key = memory_region(REGION_USER1);
+ fd1094_set_decrypted = set_decrypted;
+
+ /* punt if no key; this allows us to be called even for non-FD1094 games */
+ if (fd1094_key == NULL)
+ return;
+
+ for (i = 0; i < CACHE_ENTRIES; i++)
+ {
+ fd1094_cacheregion[i] = auto_malloc(fd1094_cpuregionsize);
+ fd1094_cached_states[i] = -1;
+ }
+ fd1094_current_cacheposition = 0;
+
+#ifdef MAME_DEBUG
+ /* key debugging */
+ if (Machine->debug_mode && memory_region(REGION_USER2) != NULL)
+ {
+ void fd1094_init_debugging(int, int, int, void (*changed)(void));
+ fd1094_init_debugging(REGION_CPU1, REGION_USER1, REGION_USER2, key_changed);
+ }
+#endif
+}
diff --git a/src/mame/machine/s24fd.c b/src/mame/machine/s24fd.c
new file mode 100644
index 00000000000..ecc2118ab1d
--- /dev/null
+++ b/src/mame/machine/s24fd.c
@@ -0,0 +1,149 @@
+/* s16fd.c modified to support s24
+
+this could get messy if games change their own code after initial loading as we'll have to invalidate caches etc.
+
+
+*/
+
+#include "driver.h"
+#include "cpu/m68000/m68000.h"
+#include "machine/fd1094.h"
+
+extern UINT16 *s24_mainram1;
+
+#define S16_NUMCACHE 8
+
+static UINT8 *s24_fd1094_key; // the memory region containing key
+static UINT16 *s24_fd1094_cpuregion; // the CPU region with encrypted code
+static UINT32 s24_fd1094_cpuregionsize; // the size of this region in bytes
+
+static UINT16* s24_fd1094_userregion; // a user region where the current decrypted state is put and executed from
+static UINT16* s24_fd1094_cacheregion[S16_NUMCACHE]; // a cache region where S16_NUMCACHE states are stored to improve performance
+static int fd1094_cached_states[S16_NUMCACHE]; // array of cached state numbers
+static int fd1094_current_cacheposition; // current position in cache array
+
+/* this function checks the cache to see if the current state is cached,
+ if it is then it copies the cached data to the user region where code is
+ executed from, if its not cached then it gets decrypted to the current
+ cache position using the functions in s24_fd1094.c */
+static void s24_fd1094_setstate_and_decrypt(int state)
+{
+ int i;
+ UINT32 addr;
+
+ cpunum_set_info_int(1, CPUINFO_INT_REGISTER + M68K_PREF_ADDR, 0x0010); // force a flush of the prefetch cache
+
+ /* set the s24_fd1094 state ready to decrypt.. */
+ state = fd1094_set_state(s24_fd1094_key,state) & 0xff;
+
+ /* first check the cache, if its cached we don't need to decrypt it, just copy */
+ for (i=0;i<S16_NUMCACHE;i++)
+ {
+ if (fd1094_cached_states[i] == state)
+ {
+ /* copy cached state */
+ s24_fd1094_userregion=s24_fd1094_cacheregion[i];
+ memory_set_decrypted_region(1, 0, s24_fd1094_cpuregionsize - 1, s24_fd1094_userregion);
+ m68k_set_encrypted_opcode_range(1,0,s24_fd1094_cpuregionsize);
+
+ return;
+ }
+ }
+
+// mame_printf_debug("new state %04x\n",state);
+
+ /* mark it as cached (because it will be once we decrypt it) */
+ fd1094_cached_states[fd1094_current_cacheposition]=state;
+
+ for (addr=0;addr<s24_fd1094_cpuregionsize/2;addr++)
+ {
+ UINT16 dat;
+ dat = fd1094_decode(addr,s24_fd1094_cpuregion[addr],s24_fd1094_key,0);
+ s24_fd1094_cacheregion[fd1094_current_cacheposition][addr]=dat;
+ }
+
+ /* copy newly decrypted data to user region */
+ s24_fd1094_userregion=s24_fd1094_cacheregion[fd1094_current_cacheposition];
+ memory_set_decrypted_region(1, 0, s24_fd1094_cpuregionsize - 1, s24_fd1094_userregion);
+ m68k_set_encrypted_opcode_range(1,0,s24_fd1094_cpuregionsize);
+
+ fd1094_current_cacheposition++;
+
+ if (fd1094_current_cacheposition>=S16_NUMCACHE)
+ {
+ mame_printf_debug("out of cache, performance may suffer, incrase S16_NUMCACHE!\n");
+ fd1094_current_cacheposition=0;
+ }
+}
+
+/* Callback for CMP.L instructions (state change) */
+static void s24_fd1094_cmp_callback(UINT32 val, int reg)
+{
+ if (reg == 0 && (val & 0x0000ffff) == 0x0000ffff) // ?
+ {
+ s24_fd1094_setstate_and_decrypt((val & 0xffff0000) >> 16);
+ }
+}
+
+/* Callback when the s24_fd1094 enters interrupt code */
+static int s24_fd1094_int_callback (int irq)
+{
+ s24_fd1094_setstate_and_decrypt(FD1094_STATE_IRQ);
+ return (0x60+irq*4)/4; // vector address
+}
+
+static void s24_fd1094_rte_callback (void)
+{
+ s24_fd1094_setstate_and_decrypt(FD1094_STATE_RTE);
+}
+
+
+/* KLUDGE, set the initial PC / SP based on table as we can't decrypt them yet */
+static void s24_fd1094_kludge_reset_values(void)
+{
+ int i;
+
+ for (i = 0;i < 4;i++)
+ s24_fd1094_userregion[i] = fd1094_decode(i,s24_fd1094_cpuregion[i],s24_fd1094_key,1);
+}
+
+
+/* function, to be called from MACHINE_RESET (every reset) */
+void s24_fd1094_machine_init(void)
+{
+ /* punt if no key; this allows us to be called even for non-s24_fd1094 games */
+ if (!s24_fd1094_key)
+ return;
+
+ s24_fd1094_setstate_and_decrypt(FD1094_STATE_RESET);
+ s24_fd1094_kludge_reset_values();
+
+ cpunum_set_info_fct(1, CPUINFO_PTR_M68K_CMPILD_CALLBACK, (genf *)s24_fd1094_cmp_callback);
+ cpunum_set_info_fct(1, CPUINFO_PTR_M68K_RTE_CALLBACK, (genf *)s24_fd1094_rte_callback);
+ cpunum_set_irq_callback(1, s24_fd1094_int_callback);
+}
+
+/* startup function, to be called from DRIVER_INIT (once on startup) */
+void s24_fd1094_driver_init(void)
+{
+ int i;
+
+ s24_fd1094_cpuregion = (UINT16*)s24_mainram1;
+ s24_fd1094_cpuregionsize = 0x40000;
+ s24_fd1094_key = memory_region(REGION_USER3);
+
+ /* punt if no key; this allows us to be called even for non-s24_fd1094 games */
+ if (!s24_fd1094_key)
+ return;
+
+ for (i=0;i<S16_NUMCACHE;i++)
+ {
+ s24_fd1094_cacheregion[i]=auto_malloc(s24_fd1094_cpuregionsize);
+ }
+
+ /* flush the cached state array */
+ for (i=0;i<S16_NUMCACHE;i++)
+ fd1094_cached_states[i] = -1;
+
+ fd1094_current_cacheposition = 0;
+}
diff --git a/src/mame/machine/sbrkout.c b/src/mame/machine/sbrkout.c
new file mode 100644
index 00000000000..362449bbdb3
--- /dev/null
+++ b/src/mame/machine/sbrkout.c
@@ -0,0 +1,110 @@
+/*************************************************************************
+
+ Atari Super Breakout hardware
+
+*************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6502/m6502.h"
+#include "sbrkout.h"
+
+#define SBRKOUT_PROGRESSIVE 0x00
+#define SBRKOUT_DOUBLE 0x01
+#define SBRKOUT_CAVITY 0x02
+
+int sbrkout_game_switch = SBRKOUT_PROGRESSIVE;
+
+
+/***************************************************************************
+Interrupt
+
+Super Breakout has a three-position dial used to select which game to
+play - Progressive, Double, and Cavity. We use the interrupt to check
+for a key press representing one of these three choices and set our
+game switch appropriately. We can't just check for key values at the time
+the game checks the game switch, because we would probably lose a *lot* of
+key presses. Also, MAME doesn't currently support a switch control like
+DIP switches that's used as a runtime control.
+***************************************************************************/
+INTERRUPT_GEN( sbrkout_interrupt )
+{
+ int game_switch=input_port_7_r(0);
+
+ if (game_switch & 0x01)
+ sbrkout_game_switch=SBRKOUT_PROGRESSIVE;
+ else if (game_switch & 0x02)
+ sbrkout_game_switch=SBRKOUT_DOUBLE;
+ else if (game_switch & 0x04)
+ sbrkout_game_switch=SBRKOUT_CAVITY;
+
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+}
+
+READ8_HANDLER( sbrkout_select1_r )
+{
+ if (sbrkout_game_switch==SBRKOUT_CAVITY)
+ return 0x80;
+ else return 0x00;
+}
+
+READ8_HANDLER( sbrkout_select2_r )
+{
+ if (sbrkout_game_switch==SBRKOUT_DOUBLE)
+ return 0x80;
+ else return 0x00;
+}
+
+#ifdef UNUSED_FUNCTION
+WRITE8_HANDLER( sbrkout_irq_w )
+{
+ /* generate irq */
+ cpunum_set_input_line(0,M6502_IRQ_LINE,HOLD_LINE);
+}
+#endif
+
+
+/***************************************************************************
+Read DIPs
+
+We remap all of our DIP switches from a single byte to four bytes. This is
+because some of the DIP switch settings would be spread across multiple
+bytes, and MAME doesn't currently support that.
+***************************************************************************/
+
+READ8_HANDLER( sbrkout_read_DIPs_r )
+{
+ switch (offset)
+ {
+ /* DSW */
+ case 0x00: return ((input_port_0_r(0) & 0x03) << 6);
+ case 0x01: return ((input_port_0_r(0) & 0x0C) << 4);
+ case 0x02: return ((input_port_0_r(0) & 0xC0) << 0);
+ case 0x03: return ((input_port_0_r(0) & 0x30) << 2);
+
+ /* Just in case */
+ default: return 0xFF;
+ }
+}
+
+/***************************************************************************
+Lamps
+
+The LEDs are turned on and off by two consecutive memory addresses. The
+first address turns them off, the second address turns them on. This is
+reversed for the Serve LED, which has a NOT on the signal.
+***************************************************************************/
+WRITE8_HANDLER( sbrkout_start_1_led_w )
+{
+ set_led_status(0,offset & 1);
+}
+
+WRITE8_HANDLER( sbrkout_start_2_led_w )
+{
+ set_led_status(1,offset & 1);
+}
+
+WRITE8_HANDLER( sbrkout_serve_led_w )
+{
+ set_led_status(2,~offset & 1);
+}
+
diff --git a/src/mame/machine/scramble.c b/src/mame/machine/scramble.c
new file mode 100644
index 00000000000..dfb2321cf0c
--- /dev/null
+++ b/src/mame/machine/scramble.c
@@ -0,0 +1,946 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/z80/z80.h"
+#include "machine/8255ppi.h"
+#include "includes/galaxian.h"
+
+static UINT8 moonwar_port_select;
+
+static UINT8 cavelon_bank;
+
+static UINT8 security_2B_counter;
+
+MACHINE_RESET( scramble )
+{
+ machine_reset_galaxian(machine);
+
+ if (cpu_gettotalcpu() > 1)
+ {
+ scramble_sh_init();
+ }
+
+ security_2B_counter = 0;
+}
+
+MACHINE_RESET( sfx )
+{
+ machine_reset_scramble(machine);
+
+ sfx_sh_init();
+}
+
+int monsterz_count = 0;
+MACHINE_RESET( monsterz )
+{
+/*
+// patch rom crc
+ UINT8 *ROM = memory_region(REGION_CPU1);
+ ROM[0x363f] = 0;
+ ROM[0x3640] = 0;
+ ROM[0x3641] = 0;
+
+ ROM[0xc5bc] = 0xaf;
+*/
+ machine_reset_scramble(machine);
+
+ sfx_sh_init();
+
+ monsterz_count = 0;
+}
+
+MACHINE_RESET( explorer )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+ RAM[0x47ff] = 0; /* If not set, it doesn't reset after the 1st time */
+
+ machine_reset_galaxian(machine);
+}
+
+static READ8_HANDLER( scrambls_input_port_2_r )
+{
+ static UINT8 mask[] = { 0x20, 0x20, 0x80, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0 };
+
+ UINT8 res;
+
+ res = readinputport(2);
+
+/*logerror("%04x: read IN2\n",activecpu_get_pc());*/
+
+ /*
+ p_security_2B : process(security_count)
+ begin
+ -- I am not sure what this chip does yet, but this gets us past the initial check for now.
+ case security_count is
+ when "000" => net_1e10_i <= '0'; net_1e12_i <= '1';
+ when "001" => net_1e10_i <= '0'; net_1e12_i <= '1';
+ when "010" => net_1e10_i <= '1'; net_1e12_i <= '0';
+ when "011" => net_1e10_i <= '1'; net_1e12_i <= '1';
+ when "100" => net_1e10_i <= '1'; net_1e12_i <= '1';
+ when "101" => net_1e10_i <= '1'; net_1e12_i <= '1';
+ when "110" => net_1e10_i <= '1'; net_1e12_i <= '1';
+ when "111" => net_1e10_i <= '1'; net_1e12_i <= '1';
+ when others => null;
+ end case;
+ end process;
+ */
+ res = (res & ~((1<<7)|(1<<5))) | mask[security_2B_counter];
+ security_2B_counter = (security_2B_counter + 1) & 0x07;
+
+ return res;
+}
+
+static READ8_HANDLER( ckongs_input_port_1_r )
+{
+ return (readinputport(1) & 0xfc) | ((readinputport(2) & 0x06) >> 1);
+}
+
+static READ8_HANDLER( ckongs_input_port_2_r )
+{
+ return (readinputport(2) & 0xf9) | ((readinputport(1) & 0x03) << 1);
+}
+
+
+static WRITE8_HANDLER( moonwar_port_select_w )
+{
+ moonwar_port_select = data & 0x10;
+}
+
+static READ8_HANDLER( moonwar_input_port_0_r )
+{
+ UINT8 sign;
+ UINT8 delta;
+
+ delta = (moonwar_port_select ? readinputport(3) : readinputport(4));
+
+ sign = (delta & 0x80) >> 3;
+ delta &= 0x0f;
+
+ return ((readinputport(0) & 0xe0) | delta | sign );
+}
+
+
+/* the coinage DIPs are spread accross two input ports */
+static READ8_HANDLER( stratgyx_input_port_2_r )
+{
+ return (readinputport(2) & ~0x06) | ((readinputport(4) << 1) & 0x06);
+}
+
+static READ8_HANDLER( stratgyx_input_port_3_r )
+{
+ return (readinputport(3) & ~0x03) | ((readinputport(4) >> 2) & 0x03);
+}
+
+
+static READ8_HANDLER( darkplnt_input_port_1_r )
+{
+ static const UINT8 remap[] = {0x03, 0x02, 0x00, 0x01, 0x21, 0x20, 0x22, 0x23,
+ 0x33, 0x32, 0x30, 0x31, 0x11, 0x10, 0x12, 0x13,
+ 0x17, 0x16, 0x14, 0x15, 0x35, 0x34, 0x36, 0x37,
+ 0x3f, 0x3e, 0x3c, 0x3d, 0x1d, 0x1c, 0x1e, 0x1f,
+ 0x1b, 0x1a, 0x18, 0x19, 0x39, 0x38, 0x3a, 0x3b,
+ 0x2b, 0x2a, 0x28, 0x29, 0x09, 0x08, 0x0a, 0x0b,
+ 0x0f, 0x0e, 0x0c, 0x0d, 0x2d, 0x2c, 0x2e, 0x2f,
+ 0x27, 0x26, 0x24, 0x25, 0x05, 0x04, 0x06, 0x07 };
+ UINT8 val;
+
+ val = readinputport(1);
+
+ return ((val & 0x03) | (remap[val >> 2] << 2));
+}
+
+/* state of the security PAL (6J) */
+static UINT8 xb;
+
+static WRITE8_HANDLER( scramble_protection_w )
+{
+ xb = data;
+}
+
+static READ8_HANDLER( scramble_protection_r )
+{
+ switch (activecpu_get_pc())
+ {
+ case 0x00a8: return 0xf0;
+ case 0x00be: return 0xb0;
+ case 0x0c1d: return 0xf0;
+ case 0x0c6a: return 0xb0;
+ case 0x0ceb: return 0x40;
+ case 0x0d37: return 0x60;
+ case 0x1ca2: return 0x00; /* I don't think it's checked */
+ case 0x1d7e: return 0xb0;
+ default:
+ logerror("%04x: read protection\n",activecpu_get_pc());
+ return 0;
+ }
+}
+
+static READ8_HANDLER( scrambls_protection_r )
+{
+ /*logerror("%04x: read protection\n",activecpu_get_pc());*/
+
+ /*
+ p_security_6J : process(xb)
+ begin
+ -- chip K10A PAL16L8
+ -- equations from Mark @ http://www.leopardcats.com/
+ xbo(3 downto 0) <= xb(3 downto 0);
+ xbo(4) <= not(xb(0) or xb(1) or xb(2) or xb(3));
+ xbo(5) <= not((not xb(2) and not xb(0)) or (not xb(2) and not xb(1)) or (not xb(3) and not xb(0)) or (not xb(3) and not xb(1)));
+
+ xbo(6) <= not(not xb(0) and not xb(3));
+ xbo(7) <= not((not xb(1)) or xb(2));
+ end process;
+ */
+ UINT8 xbo = xb & 0x0f;
+
+ xbo |= ( ~(xb | (xb>>1) | (xb>>2) | (xb>>3)) & 0x01) << 4;
+ xbo |= ( ~( (~(xb>>2)&~xb) | (~(xb>>2)&~(xb>>1)) | (~(xb>>3)&~xb) | (~(xb>>3)&~(xb>>1)) ) & 0x01) << 5;
+ xbo |= ( ~(~xb&~(xb>>3)) & 0x01) << 6;
+ xbo |= ( ~(~(xb>>1)|(xb>>2)) & 0x01) << 7;
+
+ return (xbo);
+}
+
+
+static WRITE8_HANDLER( theend_coin_counter_w )
+{
+ coin_counter_w(0, data & 0x80);
+}
+
+
+static READ8_HANDLER( mariner_protection_1_r )
+{
+ return 7;
+}
+
+static READ8_HANDLER( mariner_protection_2_r )
+{
+ return 3;
+}
+
+
+READ8_HANDLER( triplep_pip_r )
+{
+ logerror("PC %04x: triplep read port 2\n",activecpu_get_pc());
+ if (activecpu_get_pc() == 0x015a) return 0xff;
+ else if (activecpu_get_pc() == 0x0886) return 0x05;
+ else return 0;
+}
+
+READ8_HANDLER( triplep_pap_r )
+{
+ logerror("PC %04x: triplep read port 3\n",activecpu_get_pc());
+ if (activecpu_get_pc() == 0x015d) return 0x04;
+ else return 0;
+}
+
+
+
+static void cavelon_banksw(void)
+{
+ /* any read/write access in the 0x8000-0xffff region causes a bank switch.
+ Only the lower 0x2000 is switched but we switch the whole region
+ to keep the CPU core happy at the boundaries */
+
+ cavelon_bank = !cavelon_bank;
+ memory_set_bank(1, cavelon_bank);
+}
+
+static READ8_HANDLER( cavelon_banksw_r )
+{
+ cavelon_banksw();
+
+ if ((offset >= 0x0100) && (offset <= 0x0103))
+ return ppi8255_0_r(offset - 0x0100);
+ else if ((offset >= 0x0200) && (offset <= 0x0203))
+ return ppi8255_1_r(offset - 0x0200);
+
+ return 0xff;
+}
+
+static WRITE8_HANDLER( cavelon_banksw_w )
+{
+ cavelon_banksw();
+
+ if ((offset >= 0x0100) && (offset <= 0x0103))
+ ppi8255_0_w(offset - 0x0100, data);
+ else if ((offset >= 0x0200) && (offset <= 0x0203))
+ ppi8255_1_w(offset - 0x0200, data);
+}
+
+
+READ8_HANDLER( hunchbks_mirror_r )
+{
+ return program_read_byte(0x1000+offset);
+}
+
+WRITE8_HANDLER( hunchbks_mirror_w )
+{
+ program_write_byte(0x1000+offset,data);
+}
+
+
+static ppi8255_interface ppi8255_intf =
+{
+ 2, /* 2 chips */
+ {input_port_0_r, 0}, /* Port A read */
+ {input_port_1_r, 0}, /* Port B read */
+ {input_port_2_r, 0}, /* Port C read */
+ {0, soundlatch_w}, /* Port A write */
+ {0, scramble_sh_irqtrigger_w}, /* Port B write */
+ {0, 0}, /* Port C write */
+};
+
+/* extra chip for sample latch */
+static ppi8255_interface sfx_ppi8255_intf =
+{
+ 3, /* 3 chips */
+ {input_port_0_r, 0, soundlatch2_r}, /* Port A read */
+ {input_port_1_r, 0, 0}, /* Port B read */
+ {input_port_2_r, 0, 0}, /* Port C read */
+ {0, soundlatch_w, 0}, /* Port A write */
+ {0, scramble_sh_irqtrigger_w, 0}, /* Port B write */
+ {0, 0, 0}, /* Port C write */
+};
+
+/* extra chip for sample latch */
+static ppi8255_interface monsterz_ppi8255_intf =
+{
+ 3, /* 3 chips */
+ {input_port_0_r, 0, 0}, /* Port A read */
+ {input_port_1_r, 0, 0}, /* Port B read */
+ {input_port_2_r, 0, 0}, /* Port C read */
+ {0, soundlatch_w, 0}, /* Port A write */
+ {0, scramble_sh_irqtrigger_w, 0}, /* Port B write */
+ {0, 0, 0}, /* Port C write */
+};
+
+
+DRIVER_INIT( scramble_ppi )
+{
+ ppi8255_init(&ppi8255_intf);
+}
+
+DRIVER_INIT( scobra )
+{
+ driver_init_scramble_ppi(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa803, 0xa803, 0, 0, scramble_background_enable_w);
+}
+
+DRIVER_INIT( atlantis )
+{
+ driver_init_scramble_ppi(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6803, 0x6803, 0, 0, scramble_background_enable_w);
+}
+
+DRIVER_INIT( scramble )
+{
+ driver_init_atlantis(machine);
+
+ ppi8255_set_portCread (1, scramble_protection_r);
+ ppi8255_set_portCwrite(1, scramble_protection_w);
+}
+
+DRIVER_INIT( scrambls )
+{
+ driver_init_atlantis(machine);
+
+ ppi8255_set_portCread(0, scrambls_input_port_2_r);
+ ppi8255_set_portCread(1, scrambls_protection_r);
+ ppi8255_set_portCwrite(1, scramble_protection_w);
+}
+
+DRIVER_INIT( theend )
+{
+ driver_init_scramble_ppi(machine);
+
+ ppi8255_set_portCwrite(0, theend_coin_counter_w);
+}
+
+DRIVER_INIT( stratgyx )
+{
+ driver_init_scramble_ppi(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xb000, 0xb000, 0, 0, scramble_background_green_w);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xb002, 0xb002, 0, 0, scramble_background_blue_w);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xb00a, 0xb00a, 0, 0, scramble_background_red_w);
+
+ ppi8255_set_portCread(0, stratgyx_input_port_2_r);
+ ppi8255_set_portCread(1, stratgyx_input_port_3_r);
+}
+
+DRIVER_INIT( tazmani2 )
+{
+ driver_init_scramble_ppi(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xb002, 0xb002, 0, 0, scramble_background_enable_w);
+}
+
+DRIVER_INIT( amidar )
+{
+ driver_init_scramble_ppi(machine);
+
+ /* Amidar has a the DIP switches connected to port C of the 2nd 8255 */
+ ppi8255_set_portCread(1, input_port_3_r);
+}
+
+DRIVER_INIT( ckongs )
+{
+ driver_init_scramble_ppi(machine);
+
+ ppi8255_set_portBread(0, ckongs_input_port_1_r);
+ ppi8255_set_portCread(0, ckongs_input_port_2_r);
+}
+
+DRIVER_INIT( mariner )
+{
+ driver_init_scramble_ppi(machine);
+
+ /* extra ROM */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5800, 0x67ff, 0, 0, MRA8_BANK1);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5800, 0x67ff, 0, 0, MWA8_ROM);
+ memory_set_bankptr(1, memory_region(REGION_CPU1) + 0x5800);
+
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x9008, 0x9008, 0, 0, mariner_protection_2_r);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xb401, 0xb401, 0, 0, mariner_protection_1_r);
+
+ /* ??? (it's NOT a background enable) */
+ /*memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6803, 0x6803, 0, 0, MWA8_NOP);*/
+}
+
+DRIVER_INIT( frogger )
+{
+ offs_t A;
+ UINT8 *ROM;
+
+
+ driver_init_scramble_ppi(machine);
+
+
+ /* the first ROM of the second CPU has data lines D0 and D1 swapped. Decode it. */
+ ROM = memory_region(REGION_CPU2);
+ for (A = 0;A < 0x0800;A++)
+ ROM[A] = BITSWAP8(ROM[A],7,6,5,4,3,2,0,1);
+
+ /* likewise, the 2nd gfx ROM has data lines D0 and D1 swapped. Decode it. */
+ ROM = memory_region(REGION_GFX1);
+ for (A = 0x0800;A < 0x1000;A++)
+ ROM[A] = BITSWAP8(ROM[A],7,6,5,4,3,2,0,1);
+}
+
+DRIVER_INIT( froggers )
+{
+ offs_t A;
+ UINT8 *ROM;
+
+
+ driver_init_scramble_ppi(machine);
+
+ /* the first ROM of the second CPU has data lines D0 and D1 swapped. Decode it. */
+ ROM = memory_region(REGION_CPU2);
+ for (A = 0;A < 0x0800;A++)
+ ROM[A] = BITSWAP8(ROM[A],7,6,5,4,3,2,0,1);
+}
+
+DRIVER_INIT( devilfsh )
+{
+ offs_t i;
+ UINT8 *RAM;
+
+
+ driver_init_scramble_ppi(machine);
+
+
+ /* Address lines are scrambled on the main CPU */
+
+ /* A0 -> A2 */
+ /* A1 -> A0 */
+ /* A2 -> A3 */
+ /* A3 -> A1 */
+
+ RAM = memory_region(REGION_CPU1);
+ for (i = 0; i < 0x10000; i += 16)
+ {
+ offs_t j;
+ UINT8 swapbuffer[16];
+
+ for (j = 0; j < 16; j++)
+ {
+ offs_t new = BITSWAP8(j,7,6,5,4,2,0,3,1);
+
+ swapbuffer[j] = RAM[i + new];
+ }
+
+ memcpy(&RAM[i], swapbuffer, 16);
+ }
+}
+
+DRIVER_INIT( mars )
+{
+ driver_init_devilfsh(machine);
+
+ /* extra port */
+ ppi8255_set_portCread(1, input_port_3_r);
+}
+
+DRIVER_INIT( hotshock )
+{
+ /* protection??? The game jumps into never-neverland here. I think
+ it just expects a RET there */
+ memory_region(REGION_CPU1)[0x2ef9] = 0xc9;
+}
+
+DRIVER_INIT( cavelon )
+{
+ UINT8 *ROM = memory_region(REGION_CPU1);
+
+ driver_init_scramble_ppi(machine);
+
+ /* banked ROM */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, 0x3fff, 0, 0, MRA8_BANK1);
+ memory_configure_bank(1, 0, 2, &ROM[0x00000], 0x10000);
+ cavelon_banksw();
+
+ /* A15 switches memory banks */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, cavelon_banksw_r);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, cavelon_banksw_w);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2000, 0x2000, 0, 0, MWA8_NOP); /* ??? */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x3800, 0x3801, 0, 0, MWA8_NOP); /* looks suspicously like
+ an AY8910, but not sure */
+ state_save_register_global(cavelon_bank);
+}
+
+DRIVER_INIT( moonwar )
+{
+ driver_init_scramble_ppi(machine);
+
+ /* special handler for the spinner */
+ ppi8255_set_portAread (0, moonwar_input_port_0_r);
+ ppi8255_set_portCwrite(0, moonwar_port_select_w);
+
+ state_save_register_global(moonwar_port_select);
+}
+
+DRIVER_INIT( darkplnt )
+{
+ driver_init_scramble_ppi(machine);
+
+ /* special handler for the spinner */
+ ppi8255_set_portBread(0, darkplnt_input_port_1_r);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xb00a, 0xb00a, 0, 0, darkplnt_bullet_color_w);
+}
+
+DRIVER_INIT( mimonkey )
+{
+ static const UINT8 xortable[16][16] =
+ {
+ { 0x03,0x03,0x05,0x07,0x85,0x00,0x85,0x85,0x80,0x80,0x06,0x03,0x03,0x00,0x00,0x81 },
+ { 0x83,0x87,0x03,0x87,0x06,0x00,0x06,0x04,0x02,0x00,0x84,0x84,0x04,0x00,0x01,0x83 },
+ { 0x82,0x82,0x84,0x02,0x04,0x00,0x00,0x03,0x82,0x00,0x06,0x80,0x03,0x00,0x81,0x07 },
+ { 0x06,0x06,0x82,0x81,0x85,0x00,0x04,0x07,0x81,0x05,0x04,0x00,0x03,0x00,0x82,0x84 },
+ { 0x07,0x07,0x80,0x07,0x07,0x00,0x85,0x86,0x00,0x07,0x06,0x04,0x85,0x00,0x86,0x85 },
+ { 0x81,0x83,0x02,0x02,0x87,0x00,0x86,0x03,0x04,0x06,0x80,0x05,0x87,0x00,0x81,0x81 },
+ { 0x01,0x01,0x00,0x07,0x07,0x00,0x01,0x01,0x07,0x07,0x06,0x00,0x06,0x00,0x07,0x07 },
+ { 0x80,0x87,0x81,0x87,0x83,0x00,0x84,0x01,0x01,0x86,0x86,0x80,0x86,0x00,0x86,0x86 },
+ { 0x03,0x03,0x05,0x07,0x85,0x00,0x85,0x85,0x80,0x80,0x06,0x03,0x03,0x00,0x00,0x81 },
+ { 0x83,0x87,0x03,0x87,0x06,0x00,0x06,0x04,0x02,0x00,0x84,0x84,0x04,0x00,0x01,0x83 },
+ { 0x82,0x82,0x84,0x02,0x04,0x00,0x00,0x03,0x82,0x00,0x06,0x80,0x03,0x00,0x81,0x07 },
+ { 0x06,0x06,0x82,0x81,0x85,0x00,0x04,0x07,0x81,0x05,0x04,0x00,0x03,0x00,0x82,0x84 },
+ { 0x07,0x07,0x80,0x07,0x07,0x00,0x85,0x86,0x00,0x07,0x06,0x04,0x85,0x00,0x86,0x85 },
+ { 0x81,0x83,0x02,0x02,0x87,0x00,0x86,0x03,0x04,0x06,0x80,0x05,0x87,0x00,0x81,0x81 },
+ { 0x01,0x01,0x00,0x07,0x07,0x00,0x01,0x01,0x07,0x07,0x06,0x00,0x06,0x00,0x07,0x07 },
+ { 0x80,0x87,0x81,0x87,0x83,0x00,0x84,0x01,0x01,0x86,0x86,0x80,0x86,0x00,0x86,0x86 }
+ };
+
+ UINT8 *ROM = memory_region(REGION_CPU1);
+ int A, ctr = 0, line, col;
+
+ for( A = 0; A < 0x4000; A++ )
+ {
+ line = (ctr & 0x07) | ((ctr & 0x200) >> 6);
+ col = ((ROM[A] & 0x80) >> 4) | (ROM[A] & 0x07);
+ ROM[A] = ROM[A] ^ xortable[line][col];
+ ctr++;
+ }
+
+ driver_init_scramble_ppi(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa804, 0xa804, 0, 0, scramble_background_enable_w);
+}
+
+DRIVER_INIT( mimonsco )
+{
+ driver_init_scramble_ppi(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xa804, 0xa804, 0, 0, scramble_background_enable_w);
+}
+
+DRIVER_INIT( mimonscr )
+{
+ driver_init_scramble_ppi(machine);
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6804, 0x6804, 0, 0, scramble_background_enable_w);
+}
+
+
+static int bit(int i,int n)
+{
+ return ((i >> n) & 1);
+}
+
+
+DRIVER_INIT( anteater )
+{
+ offs_t i;
+ UINT8 *RAM;
+ UINT8 *scratch;
+
+
+ driver_init_scobra(machine);
+
+ /*
+ * Code To Decode Lost Tomb by Mirko Buffoni
+ * Optimizations done by Fabio Buffoni
+ */
+
+ RAM = memory_region(REGION_GFX1);
+
+ scratch = malloc_or_die(memory_region_length(REGION_GFX1));
+
+ memcpy(scratch, RAM, memory_region_length(REGION_GFX1));
+
+ for (i = 0; i < memory_region_length(REGION_GFX1); i++)
+ {
+ int j;
+
+
+ j = i & 0x9bf;
+ j |= ( bit(i,4) ^ bit(i,9) ^ ( bit(i,2) & bit(i,10) ) ) << 6;
+ j |= ( bit(i,2) ^ bit(i,10) ) << 9;
+ j |= ( bit(i,0) ^ bit(i,6) ^ 1 ) << 10;
+
+ RAM[i] = scratch[j];
+ }
+
+ free(scratch);
+}
+
+DRIVER_INIT( rescue )
+{
+ offs_t i;
+ UINT8 *RAM;
+ UINT8 *scratch;
+
+
+ driver_init_scobra(machine);
+
+ /*
+ * Code To Decode Lost Tomb by Mirko Buffoni
+ * Optimizations done by Fabio Buffoni
+ */
+
+ RAM = memory_region(REGION_GFX1);
+
+ scratch = malloc_or_die(memory_region_length(REGION_GFX1));
+
+ memcpy(scratch, RAM, memory_region_length(REGION_GFX1));
+
+ for (i = 0; i < memory_region_length(REGION_GFX1); i++)
+ {
+ int j;
+
+
+ j = i & 0xa7f;
+ j |= ( bit(i,3) ^ bit(i,10) ) << 7;
+ j |= ( bit(i,1) ^ bit(i,7) ) << 8;
+ j |= ( bit(i,0) ^ bit(i,8) ) << 10;
+
+ RAM[i] = scratch[j];
+ }
+
+ free(scratch);
+}
+
+DRIVER_INIT( minefld )
+{
+ offs_t i;
+ UINT8 *RAM;
+ UINT8 *scratch;
+
+
+ driver_init_scobra(machine);
+
+ /*
+ * Code To Decode Minefield by Mike Balfour and Nicola Salmoria
+ */
+
+ RAM = memory_region(REGION_GFX1);
+
+ scratch = malloc_or_die(memory_region_length(REGION_GFX1));
+
+ memcpy(scratch, RAM, memory_region_length(REGION_GFX1));
+
+ for (i = 0; i < memory_region_length(REGION_GFX1); i++)
+ {
+ int j;
+
+
+ j = i & 0xd5f;
+ j |= ( bit(i,3) ^ bit(i,7) ) << 5;
+ j |= ( bit(i,2) ^ bit(i,9) ^ ( bit(i,0) & bit(i,5) ) ^
+ ( bit(i,3) & bit(i,7) & ( bit(i,0) ^ bit(i,5) ))) << 7;
+ j |= ( bit(i,0) ^ bit(i,5) ^ ( bit(i,3) & bit(i,7) ) ) << 9;
+
+ RAM[i] = scratch[j];
+ }
+
+ free(scratch);
+}
+
+DRIVER_INIT( losttomb )
+{
+ offs_t i;
+ UINT8 *RAM;
+ UINT8 *scratch;
+
+
+ driver_init_scramble(machine);
+
+ /*
+ * Code To Decode Lost Tomb by Mirko Buffoni
+ * Optimizations done by Fabio Buffoni
+ */
+
+ RAM = memory_region(REGION_GFX1);
+
+ scratch = malloc_or_die(memory_region_length(REGION_GFX1));
+
+ memcpy(scratch, RAM, memory_region_length(REGION_GFX1));
+
+ for (i = 0; i < memory_region_length(REGION_GFX1); i++)
+ {
+ int j;
+
+
+ j = i & 0xa7f;
+ j |= ( (bit(i,1) & bit(i,8)) | ((1 ^ bit(i,1)) & (bit(i,10)))) << 7;
+ j |= ( bit(i,7) ^ (bit(i,1) & ( bit(i,7) ^ bit(i,10) ))) << 8;
+ j |= ( (bit(i,1) & bit(i,7)) | ((1 ^ bit(i,1)) & (bit(i,8)))) << 10;
+
+ RAM[i] = scratch[j];
+ }
+
+ free(scratch);
+}
+
+DRIVER_INIT( superbon )
+{
+ offs_t i;
+ UINT8 *RAM;
+
+
+ driver_init_scramble(machine);
+
+ /* Deryption worked out by hand by Chris Hardy. */
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (i = 0;i < 0x1000;i++)
+ {
+ /* Code is encrypted depending on bit 7 and 9 of the address */
+ switch (i & 0x0280)
+ {
+ case 0x0000:
+ RAM[i] ^= 0x92;
+ break;
+ case 0x0080:
+ RAM[i] ^= 0x82;
+ break;
+ case 0x0200:
+ RAM[i] ^= 0x12;
+ break;
+ case 0x0280:
+ RAM[i] ^= 0x10;
+ break;
+ }
+ }
+}
+
+
+DRIVER_INIT( hustler )
+{
+ offs_t A;
+
+
+ driver_init_scramble_ppi(machine);
+
+
+ for (A = 0;A < 0x4000;A++)
+ {
+ UINT8 xormask;
+ int bits[8];
+ int i;
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+
+ for (i = 0;i < 8;i++)
+ bits[i] = (A >> i) & 1;
+
+ xormask = 0xff;
+ if (bits[0] ^ bits[1]) xormask ^= 0x01;
+ if (bits[3] ^ bits[6]) xormask ^= 0x02;
+ if (bits[4] ^ bits[5]) xormask ^= 0x04;
+ if (bits[0] ^ bits[2]) xormask ^= 0x08;
+ if (bits[2] ^ bits[3]) xormask ^= 0x10;
+ if (bits[1] ^ bits[5]) xormask ^= 0x20;
+ if (bits[0] ^ bits[7]) xormask ^= 0x40;
+ if (bits[4] ^ bits[6]) xormask ^= 0x80;
+
+ rom[A] ^= xormask;
+ }
+
+ /* the first ROM of the second CPU has data lines D0 and D1 swapped. Decode it. */
+ {
+ UINT8 *rom = memory_region(REGION_CPU2);
+
+
+ for (A = 0;A < 0x0800;A++)
+ rom[A] = BITSWAP8(rom[A],7,6,5,4,3,2,0,1);
+ }
+}
+
+DRIVER_INIT( billiard )
+{
+ offs_t A;
+
+
+ driver_init_scramble_ppi(machine);
+
+
+ for (A = 0;A < 0x4000;A++)
+ {
+ UINT8 xormask;
+ int bits[8];
+ int i;
+ UINT8 *rom = memory_region(REGION_CPU1);
+
+
+ for (i = 0;i < 8;i++)
+ bits[i] = (A >> i) & 1;
+
+ xormask = 0x55;
+ if (bits[2] ^ ( bits[3] & bits[6])) xormask ^= 0x01;
+ if (bits[4] ^ ( bits[5] & bits[7])) xormask ^= 0x02;
+ if (bits[0] ^ ( bits[7] & !bits[3])) xormask ^= 0x04;
+ if (bits[3] ^ (!bits[0] & bits[2])) xormask ^= 0x08;
+ if (bits[5] ^ (!bits[4] & bits[1])) xormask ^= 0x10;
+ if (bits[6] ^ (!bits[2] & !bits[5])) xormask ^= 0x20;
+ if (bits[1] ^ (!bits[6] & !bits[4])) xormask ^= 0x40;
+ if (bits[7] ^ (!bits[1] & bits[0])) xormask ^= 0x80;
+
+ rom[A] ^= xormask;
+
+ rom[A] = BITSWAP8(rom[A],6,1,2,5,4,3,0,7);
+ }
+
+ /* the first ROM of the second CPU has data lines D0 and D1 swapped. Decode it. */
+ {
+ UINT8 *rom = memory_region(REGION_CPU2);
+
+
+ for (A = 0;A < 0x0800;A++)
+ rom[A] = BITSWAP8(rom[A],7,6,5,4,3,2,0,1);
+ }
+}
+
+/************************************************************
+ mr kougar protected main cpu - by HIGHWAYMAN
+ mr kougar contains a steel module at location S7,
+ this module contains a Z80c cpu with the following changes:
+ IOREQ pin cut, RD & WR pins swapped and the following
+ address lines swapped - a0-a2,a1-a0,a2-a3,a3-a1.
+*************************************************************/
+
+DRIVER_INIT( mrkougar )
+{
+ driver_init_devilfsh(machine);
+
+ /* no sound enabled bit */
+ ppi8255_set_portBwrite(1, mrkougar_sh_irqtrigger_w);
+}
+
+DRIVER_INIT( mrkougb )
+{
+ driver_init_scramble_ppi(machine);
+
+ /* no sound enabled bit */
+ ppi8255_set_portBwrite(1, mrkougar_sh_irqtrigger_w);
+}
+
+DRIVER_INIT( sfx )
+{
+ ppi8255_init(&sfx_ppi8255_intf);
+}
+
+DRIVER_INIT( monsterz )
+{
+ ppi8255_init(&monsterz_ppi8255_intf);
+
+ /* extra ROM */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x3000, 0x3fff, 0, 0, MRA8_BANK1);
+ memory_set_bankptr(1, memory_region(REGION_CPU2) + 0x3000);
+}
+
+static READ8_HANDLER( scorpion_prot_r )
+{
+ /* HACK! return register C */
+ return activecpu_get_reg(Z80_C) & 0xff;
+}
+
+static READ8_HANDLER( scorpion_sound_status_r )
+{
+ return 1;
+}
+
+DRIVER_INIT( scorpion )
+{
+ ppi8255_init(&ppi8255_intf);
+
+ ppi8255_set_portCread(1, scorpion_prot_r);
+
+ /* extra ROM */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5800, 0x67ff, 0, 0, MRA8_BANK1);
+ memory_set_bankptr(1, memory_region(REGION_CPU1) + 0x5800);
+
+ /* no background related */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6803, 0x6803, 0, 0, MWA8_NOP);
+
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x3000, 0x3000, 0, 0, scorpion_sound_status_r);
+}
+
+DRIVER_INIT( ad2083 )
+{
+ UINT8 c;
+ int i;
+
+ UINT8 *ROM = memory_region(REGION_CPU1);
+
+ for (i=0; i<memory_region_length(REGION_CPU1); i++)
+ {
+ c = ROM[i] ^ 0x35;
+ c = BITSWAP8(c, 6,2,5,1,7,3,4,0); /* also swapped inside of the bigger module */
+ ROM[i] = c;
+ }
+}
diff --git a/src/mame/machine/scudsp.c b/src/mame/machine/scudsp.c
new file mode 100644
index 00000000000..6311b08f149
--- /dev/null
+++ b/src/mame/machine/scudsp.c
@@ -0,0 +1,1278 @@
+/******************************************************************************************
+System Control Unit - DSP emulator version 0.06
+
+Written by Angelo Salese & Mariusz Wojcieszek
+
+Changelog:
+051129: Mariusz Wojcieszek
+- Fixed parallel instructions which increment CT registers to update CT register only
+ once, after dsp operation is finished. This fixes instructions like
+ MOV MC0,X MOV MC0,Y used by vfremix
+- Changed ALU 32bit instructions to not sign extend their result when loaded to ALU.
+ This matches Sega's dspsim behaviour.
+- Changed DMA addnumber handling to match Sega's dspsim.
+
+050813: Mariusz Wojcieszek
+- Fixed add number in DSP DMA
+
+050412: Angelo Salese
+- Fixed the T0F behaviour in the DMA operation,it was causing an hang in Treasure Hunt
+ due of that.
+- Removed the dsp.log file creation when you are not using the debug build
+
+041114: Angelo Salese
+- Finished flags in ALU opcodes
+- SR opcode: MSB does not change.
+
+040328: Mariusz Wojcieszek
+- rewritten ALU and MUL operations using signed arithmetics
+- improved DMA
+- fixed MOV ALH,x
+
+031211: Mariusz Wojcieszek
+- result of ALU command is stored into ALU register
+- X-Bus command: MOV [s],X can be executed in parallel to other X-Bus commands
+- Y-Bus command: MOV [s],Y can be executed in parallel to other Y-Bus commands
+- Jump and LPS/BTM support:
+ jump addresses are absolute,
+ prefetched instructions are executed before jump is taken
+- after each instruction, X and Y is multiplied and contents are loaded into MUL register
+- fixed RL8
+- fixed MVI
+- flags computation in MVI and JMP is partly guessed (because of errors in docs)
+- added reading DSP mem from SH2 side
+- overworked disassembler
+
+ TODO:
+- Disassembler: complete it
+- (Maybe) Convert this to cpu structure
+- Add control flags
+
+******************************************************************************************/
+#include "driver.h"
+#include "machine/scudsp.h"
+#include "osd_cpu.h"
+
+/*DSP macros*/
+#define PRF ((stv_scu[32] & 0x04000000) >> 26)
+#define EPF ((stv_scu[32] & 0x02000000) >> 25)
+#define T0F ((stv_scu[32] & 0x00800000) >> 23)
+#define SF ((stv_scu[32] & 0x00400000) >> 22)
+#define ZF ((stv_scu[32] & 0x00200000) >> 21)
+#define CF ((stv_scu[32] & 0x00100000) >> 20)
+#define VF ((stv_scu[32] & 0x00080000) >> 19)
+#define EF ((stv_scu[32] & 0x00040000) >> 18)
+#define ESF ((stv_scu[32] & 0x00020000) >> 17)
+#define EXF ((stv_scu[32] & 0x00010000) >> 16)
+#define LEF ((stv_scu[32] & 0x00008000) >> 15)
+#define T0F_1 if(!(stv_scu[32] & 0x00800000)) stv_scu[32]^=0x00800000
+#define T0F_0 if(stv_scu[32] & 0x00800000) stv_scu[32]^=0x00800000
+
+#define SET_C(_val) (stv_scu[32] = ((stv_scu[32] & ~0x00100000) | ((_val) ? 0x00100000 : 0)))
+#define SET_S(_val) (stv_scu[32] = ((stv_scu[32] & ~0x00400000) | ((_val) ? 0x00400000 : 0)))
+#define SET_Z(_val) (stv_scu[32] = ((stv_scu[32] & ~0x00200000) | ((_val) ? 0x00200000 : 0)))
+#define SET_V(_val) (stv_scu[32] = ((stv_scu[32] & ~0x00080000) | ((_val) ? 0x00080000 : 0)))
+
+typedef union {
+ INT32 si;
+ UINT32 ui;
+} SCUDSPREG32;
+
+typedef union {
+ INT16 si;
+ UINT16 ui;
+} SCUDSPREG16;
+
+static struct {
+ UINT8 pc; /*Program Counter*/
+ UINT8 delay; /* Delay */
+ UINT8 top; /*Jump Command memory*/
+ UINT16 lop; /*Counter Register*/ /*12-bits*/
+ UINT8 ct0,ct1,ct2,ct3; /*Index for RAM*/ /*6-bits */
+ UINT32 md0[0x40],md1[0x40],md2[0x40],md3[0x40]; /*RAM memory*/
+ UINT8 ra; /*RAM selector*/
+ SCUDSPREG32 rx; /*X-Bus register*/
+ INT64 mul; /*Multiplier register*//*48-bits*/
+ SCUDSPREG32 ry; /*Y-Bus register*/
+ INT64 alu; /*ALU register*/ /*48-bits*/
+ SCUDSPREG16 ph; /*ALU high register*/
+ SCUDSPREG32 pl; /*ALU low register*/
+ SCUDSPREG16 ach; /*ALU external high register*/
+ SCUDSPREG32 acl; /*ALU external low register*/
+ UINT32 ra0,wa0; /*DSP DMA registers*/
+ UINT32 internal_prg[0x100];
+} dsp_reg;
+
+extern UINT32* stv_scu;
+
+static UINT32 opcode;
+static UINT8 update_mul = 0;
+
+#ifdef MAME_DEBUG
+#define DEBUG_DSP 1
+#else
+#define DEBUG_DSP 0
+#endif
+
+static char dasm_buffer[100];
+#if DEBUG_DSP
+static FILE *log_file = NULL;
+#endif
+static void dsp_dasm_opcode( UINT32 op, char *buffer );
+
+
+
+static UINT32 dsp_get_source_mem_value( UINT32 mode )
+{
+ UINT32 value = 0;
+
+ switch( mode )
+ {
+ case 0x0: /* M0 */
+ value = dsp_reg.md0[ dsp_reg.ct0 ];
+ break;
+ case 0x1: /* M1 */
+ value = dsp_reg.md1[ dsp_reg.ct1 ];
+ break;
+ case 0x2: /* M2 */
+ value = dsp_reg.md2[ dsp_reg.ct2 ];
+ break;
+ case 0x3: /* M3 */
+ value = dsp_reg.md3[ dsp_reg.ct3 ];
+ break;
+ case 0x4: /* MC0 */
+ value = dsp_reg.md0[ dsp_reg.ct0++ ];
+ dsp_reg.ct0 &= 0x3f;
+ break;
+ case 0x5: /* MC1 */
+ value = dsp_reg.md1[ dsp_reg.ct1++ ];
+ dsp_reg.ct1 &= 0x3f;
+ break;
+ case 0x6: /* MC2 */
+ value = dsp_reg.md2[ dsp_reg.ct2++ ];
+ dsp_reg.ct2 &= 0x3f;
+ break;
+ case 0x7: /* MC3 */
+ value = dsp_reg.md3[ dsp_reg.ct3++ ];
+ dsp_reg.ct3 &= 0x3f;
+ break;
+ }
+ return value;
+}
+
+static UINT32 dsp_get_source_mem_reg_value( UINT32 mode )
+{
+ if ( mode < 0x8 )
+ {
+ return dsp_get_source_mem_value( mode );
+ }
+ else
+ {
+ switch( mode )
+ {
+ case 0x9:
+ return (UINT32)((dsp_reg.alu & U64(0x00000000ffffffff)) >> 0);
+ case 0xA:
+ return (UINT32)((dsp_reg.alu & U64(0x0000ffffffff0000)) >> 16);
+ }
+ }
+ return 0;
+}
+
+static void dsp_set_dest_mem_reg( UINT32 mode, UINT32 value )
+{
+ switch( mode )
+ {
+ case 0x0: /* MC0 */
+ dsp_reg.md0[ dsp_reg.ct0++ ] = value;
+ dsp_reg.ct0 &= 0x3f;
+ break;
+ case 0x1: /* MC1 */
+ dsp_reg.md1[ dsp_reg.ct1++ ] = value;
+ dsp_reg.ct1 &= 0x3f;
+ break;
+ case 0x2: /* MC2 */
+ dsp_reg.md2[ dsp_reg.ct2++ ] = value;
+ dsp_reg.ct2 &= 0x3f;
+ break;
+ case 0x3: /* MC3 */
+ dsp_reg.md3[ dsp_reg.ct3++ ] = value;
+ dsp_reg.ct3 &= 0x3f;
+ break;
+ case 0x4: /* RX */
+ dsp_reg.rx.ui = value;
+ update_mul = 1;
+ break;
+ case 0x5: /* PL */
+ dsp_reg.pl.ui = value;
+ dsp_reg.ph.si = (dsp_reg.pl.si < 0) ? -1 : 0;
+ break;
+ case 0x6: /* RA0 */
+ dsp_reg.ra0 = value;
+ break;
+ case 0x7: /* WA0 */
+ dsp_reg.wa0 = value;
+ break;
+ case 0x8:
+ case 0x9:
+ /* ??? */
+ break;
+ case 0xa: /* LOP */
+ dsp_reg.lop = value;
+ break;
+ case 0xb: /* TOP */
+ dsp_reg.top = value;
+ break;
+ case 0xc: /* CT0 */
+ dsp_reg.ct0 = value & 0x3f;
+ break;
+ case 0xd: /* CT1 */
+ dsp_reg.ct1 = value & 0x3f;
+ break;
+ case 0xe: /* CT2 */
+ dsp_reg.ct2 = value & 0x3f;
+ break;
+ case 0xf: /* CT3 */
+ dsp_reg.ct3 = value & 0x3f;
+ break;
+ }
+}
+
+static void dsp_set_dest_mem_reg_2( UINT32 mode, UINT32 value )
+{
+ if ( mode < 0xb )
+ {
+ dsp_set_dest_mem_reg( mode, value );
+ }
+ else
+ {
+ switch( mode )
+ {
+ case 0xc: /* PC */
+ dsp_reg.delay = dsp_reg.pc; /* address next after this command will be executed twice */
+ dsp_reg.top = dsp_reg.pc;
+ dsp_reg.pc = value;
+ break;
+ }
+ }
+}
+
+static UINT32 dsp_compute_condition( UINT32 condition )
+{
+ UINT32 result = 0;
+
+ switch( condition & 0xf )
+ {
+ case 0x1: /* Z */
+ result = ZF;
+ break;
+ case 0x2: /* S */
+ result = SF;
+ break;
+ case 0x3: /* ZS */
+ result = ZF | SF;
+ break;
+ case 0x4: /* C */
+ result = CF;
+ break;
+ case 0x8: /* T0 */
+ result = T0F;
+ break;
+ }
+ if ( !(condition & 0x20) )
+ {
+ result = !result;
+ }
+ return result;
+}
+
+static void dsp_set_dest_dma_mem( UINT32 memcode, UINT32 value, UINT32 counter )
+{
+ if ( memcode < 4 )
+ {
+ dsp_set_dest_mem_reg( memcode, value );
+ }
+ else if ( memcode == 4 )
+ {
+ dsp_reg.internal_prg[ counter & 0x100 ] = value;
+ }
+}
+
+static UINT32 dsp_get_mem_source_dma( UINT32 memcode, UINT32 counter )
+{
+ switch( memcode & 0x3 )
+ {
+ case 0x0:
+ return dsp_reg.md0[ (dsp_reg.ct0 + counter) & 0x3f ];
+ case 0x1:
+ return dsp_reg.md1[ (dsp_reg.ct1 + counter) & 0x3f ];
+ case 0x2:
+ return dsp_reg.md2[ (dsp_reg.ct2 + counter) & 0x3f ];
+ case 0x3:
+ return dsp_reg.md3[ (dsp_reg.ct3 + counter) & 0x3f ];
+ }
+ return 0;
+}
+
+void dsp_prg_ctrl(UINT32 data)
+{
+ if(LEF) dsp_reg.pc = (data & 0xff);
+ if(EXF) dsp_execute_program();
+ if(EF && (!(stv_scu[40] & 0x0020)))
+ cpunum_set_input_line_and_vector(0, 0xa, HOLD_LINE , 0x45);
+}
+
+void dsp_prg_data(UINT32 data)
+{
+ dsp_reg.internal_prg[dsp_reg.pc] = data;
+ dsp_reg.pc++;
+}
+
+void dsp_ram_addr_ctrl(UINT32 data)
+{
+ dsp_reg.ra = data & 0xff;
+
+ switch((dsp_reg.ra & 0xc0) >> 6)
+ {
+ case 0: dsp_reg.ct0 = (dsp_reg.ra & 0x3f); break;
+ case 1: dsp_reg.ct1 = (dsp_reg.ra & 0x3f); break;
+ case 2: dsp_reg.ct2 = (dsp_reg.ra & 0x3f); break;
+ case 3: dsp_reg.ct3 = (dsp_reg.ra & 0x3f); break;
+ }
+}
+
+void dsp_ram_addr_w(UINT32 data)
+{
+#if DEBUG_DSP
+ if ( log_file == NULL )
+ {
+ log_file = fopen( "dsp.log", "a" );
+ }
+ fprintf( log_file, "DSP: Writing mem %02X %04X\n", dsp_reg.ra & 0xff, data );
+#endif
+ dsp_set_dest_mem_reg( (dsp_reg.ra & 0xc0) >> 6, data );
+}
+
+UINT32 dsp_ram_addr_r()
+{
+ UINT32 data;
+
+ data = dsp_get_source_mem_value( ((dsp_reg.ra & 0xc0) >> 6) + 4 );
+#if DEBUG_DSP
+ if ( log_file == NULL )
+ {
+ log_file = fopen( "dsp.log", "a" );
+ }
+ fprintf( log_file, "DSP: Reading mem at %02X %04X\n", dsp_reg.ra & 0xff, data );
+#endif
+ return data;
+}
+
+static void dsp_operation(void)
+{
+ INT64 i1,i2;
+ INT32 i3;
+ int update_ct[4] = {0,0,0,0};
+ int dsp_mem;
+
+
+ /* ALU */
+ switch( (opcode & 0x3c000000) >> 26 )
+ {
+ case 0x0: /* NOP */
+ break;
+ case 0x1: /* AND */
+ i3 = dsp_reg.acl.si & dsp_reg.pl.si;
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z(i3 == 0);
+ SET_C(0);
+ SET_S(i3 < 0);
+ break;
+ case 0x2: /* OR */
+ i3 = dsp_reg.acl.si | dsp_reg.pl.si;
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z(i3 == 0);
+ SET_C(0);
+ SET_S(i3 < 0);
+ break;
+ case 0x3: /* XOR */
+ i3 = dsp_reg.acl.si ^ dsp_reg.pl.si;
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z(i3 == 0);
+ SET_C(0);
+ SET_S(i3 < 0);
+ break;
+ case 0x4: /* ADD */
+ i3 = dsp_reg.acl.si + dsp_reg.pl.si;
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ //SET_Z(i3 == 0);
+ SET_Z( (i3 & S64(0xffffffffffff)) == 0 );
+ //SET_S(i3 < 0);
+ SET_S( i3 & S64(0x1000000000000));
+ SET_C(i3 & S64(0x100000000));
+ SET_V(((i3) ^ (dsp_reg.acl.si)) & ((i3) ^ (dsp_reg.pl.si)) & 0x80000000);
+ break;
+ case 0x5: /* SUB */
+ i3 = dsp_reg.acl.si - dsp_reg.pl.si;
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z(i3 == 0);
+ SET_C(i3 & S64(0x100000000));
+ SET_S(i3 < 0);
+ SET_V(((dsp_reg.pl.si) ^ (dsp_reg.acl.si)) & ((dsp_reg.pl.si) ^ (i3)) & 0x80000000);
+ break;
+ case 0x6: /* AD2 */
+ i1 = COMBINE_64_32_32((INT32)dsp_reg.ph.si,dsp_reg.pl.si);
+ i2 = COMBINE_64_32_32((INT32)dsp_reg.ach.si,dsp_reg.acl.si);
+ dsp_reg.alu = i1 + i2;
+ SET_Z((dsp_reg.alu & S64(0xffffffffffff)) == 0);
+ SET_S((dsp_reg.alu & S64(0x800000000000)) > 0);
+ SET_C((dsp_reg.alu) & S64(0x1000000000000));
+ SET_V(((dsp_reg.alu) ^ (i1)) & ((dsp_reg.alu) ^ (i2)) & S64(0x800000000000));
+ break;
+ case 0x7: /* ??? */
+ /* Unrecognized opcode */
+ break;
+ case 0x8: /* SR */
+ i3 = (dsp_reg.acl.si >> 1) | (dsp_reg.acl.si & 0x80000000);/*MSB does not change*/
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z(i3 == 0);
+ SET_S(i3 < 0);
+ SET_C(dsp_reg.acl.ui & 0x80000000);
+ break;
+ case 0x9: /* RR */
+ i3 = ((dsp_reg.acl.ui >> 1) & 0x7fffffff) | ((dsp_reg.acl.ui << 31) & 0x80000000);
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z( i3 == 0 );
+ SET_S( i3 < 0 );
+ SET_C( dsp_reg.acl.ui & 0x1 );
+ break;
+ case 0xa: /* SL */
+ i3 = dsp_reg.acl.si << 1;
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z( i3 == 0 );
+ SET_S( i3 < 0 );
+ SET_C( dsp_reg.acl.ui & 0x80000000 );
+ break;
+ case 0xB: /* RL */
+ i3 = ((dsp_reg.acl.si << 1) & 0xfffffffe) | ((dsp_reg.acl.si >> 31) & 0x1);
+ dsp_reg.alu = (UINT64)(UINT32)i3;
+ SET_Z( i3 == 0 );
+ SET_S( i3 < 0 );
+ SET_C( dsp_reg.acl.ui & 0x80000000 );
+ break;
+ case 0xc:
+ case 0xd:
+ case 0xe:
+ /* Unrecognized opcode */
+ break;
+ case 0xF: /* RL8 */
+ i3 = ((dsp_reg.acl.si << 8) & 0xffffff00) | ((dsp_reg.acl.si >> 24) & 0xff);
+ dsp_reg.alu = i3;
+ SET_Z( i3 == 0 );
+ SET_S( i3 < 0 );
+ SET_C( dsp_reg.acl.si & 0x01000000 );
+ break;
+ }
+
+ /* X-Bus */
+ if ( opcode & 0x2000000 )
+ {
+ /* MOV [s],X */
+ dsp_mem = (opcode & 0x700000) >> 20;
+ if ( dsp_mem & 4 )
+ {
+ dsp_mem &= 3;
+ update_ct[dsp_mem] = 1;
+ }
+ dsp_reg.rx.ui = dsp_get_source_mem_value( dsp_mem );
+ update_mul = 1;
+ }
+ switch( (opcode & 0x1800000) >> 23 )
+ {
+ case 0x0: /* NOP */
+ case 0x1: /* NOP ? */
+ break;
+ case 0x2: /* MOV MUL,P */
+ dsp_reg.ph.ui = (UINT16)((dsp_reg.mul & U64(0x0000ffff00000000)) >> 32);
+ dsp_reg.pl.ui = (UINT32)((dsp_reg.mul & U64(0x00000000ffffffff)) >> 0);
+ break;
+ case 0x3: /* MOV [s],P */
+ dsp_mem = (opcode & 0x700000) >> 20;
+ if ( dsp_mem & 4 )
+ {
+ dsp_mem &= 3;
+ update_ct[dsp_mem] = 1;
+ }
+ dsp_reg.pl.ui = dsp_get_source_mem_value( dsp_mem );
+ dsp_reg.ph.si = (dsp_reg.pl.si < 0) ? -1 : 0;
+ break;
+ }
+
+ /* Y-Bus */
+ if ( opcode & 0x80000 )
+ {
+ /* MOV [s],Y */
+ dsp_mem = (opcode & 0x1C000 ) >> 14;
+ if (dsp_mem & 4)
+ {
+ dsp_mem &= 3;
+ update_ct[dsp_mem] = 1;
+ }
+ dsp_reg.ry.ui = dsp_get_source_mem_value( dsp_mem );
+ update_mul = 1;
+ }
+ switch( (opcode & 0x60000) >> 17 )
+ {
+ case 0x0: /* NOP */
+ break;
+ case 0x1: /* CLR A */
+ dsp_reg.acl.ui = 0;
+ dsp_reg.ach.ui = 0;
+ break;
+ case 0x2: /* MOV ALU,A */
+ dsp_reg.ach.ui = (UINT16)((dsp_reg.alu & U64(0x0000ffff00000000)) >> 32);
+ dsp_reg.acl.ui = (UINT32)((dsp_reg.alu & U64(0x00000000ffffffff)) >> 0);
+ break;
+ case 0x3: /* MOV [s], A */
+ dsp_mem = (opcode & 0x1C000 ) >> 14;
+ if (dsp_mem & 4)
+ {
+ dsp_mem &= 3;
+ update_ct[dsp_mem] = 1;
+ }
+ dsp_reg.acl.ui = dsp_get_source_mem_value( dsp_mem );
+ dsp_reg.ach.si = ((dsp_reg.acl.si < 0) ? -1 : 0);
+ break;
+ }
+
+ /* update CT registers */
+ if ( update_ct[0] ) { dsp_reg.ct0++; dsp_reg.ct0 &= 0x3f; };
+ if ( update_ct[1] ) { dsp_reg.ct1++; dsp_reg.ct1 &= 0x3f; };
+ if ( update_ct[2] ) { dsp_reg.ct2++; dsp_reg.ct2 &= 0x3f; };
+ if ( update_ct[3] ) { dsp_reg.ct3++; dsp_reg.ct3 &= 0x3f; };
+
+
+ /* D1-Bus */
+ switch( (opcode & 0x3000) >> 12 )
+ {
+ case 0x0: /* NOP */
+ break;
+ case 0x1: /* MOV SImm,[d] */
+ dsp_set_dest_mem_reg( (opcode & 0xf00) >> 8, (INT32)(INT8)(opcode & 0xff) );
+ break;
+ case 0x2:
+ /* ??? */
+ break;
+ case 0x3: /* MOV [s],[d] */
+ dsp_set_dest_mem_reg( (opcode & 0xf00) >> 8, dsp_get_source_mem_reg_value( opcode & 0xf ) );
+ break;
+ }
+
+}
+
+static void dsp_move_immediate( void )
+{
+ UINT32 value;
+
+ if ( opcode & 0x2000000 )
+ {
+ if ( dsp_compute_condition( (opcode & 0x3F80000 ) >> 18 ) )
+ {
+ value = opcode & 0x7ffff;
+ if ( value & 0x40000 ) value |= 0xfff80000;
+ dsp_set_dest_mem_reg_2( (opcode & 0x3C000000) >> 26, value );
+ }
+ }
+ else
+ {
+ value = opcode & 0x1ffffff;
+ if ( value & 0x1000000 ) value |= 0xfe000000;
+ dsp_set_dest_mem_reg_2( (opcode & 0x3C000000) >> 26, value );
+ }
+}
+
+
+static void dsp_dma( void )
+{
+ UINT8 hold = (opcode & 0x4000) >> 14;
+ UINT32 add = (opcode & 0x38000) >> 15;
+ UINT32 dir_from_D0 = (opcode & 0x1000 ) >> 12;
+ UINT32 transfer_cnt = 0;
+ UINT32 source = 0, dest = 0;
+ UINT32 dsp_mem = (opcode & 0x700) >> 8;
+ UINT32 counter = 0;
+ UINT32 data;
+
+
+ T0F_1;
+
+ if ( opcode & 0x2000 )
+ {
+ transfer_cnt = dsp_get_source_mem_value( opcode & 0xf );
+ switch ( add & 0x1 )
+ {
+ case 0: add = 2; break;
+ case 1: add = 4; break;
+ }
+ }
+ else
+ {
+ transfer_cnt = opcode & 0xff;
+ switch( add )
+ {
+ case 0: add = 0; break; /* 0 */
+ case 1: add = 4; break; /* 1 */
+ case 2: add = 4; break; /* 2 */
+ case 3: add = 16; break; /* 4 */
+ case 4: add = 16; break; /* 8 */
+ case 5: add = 64; break; /* 16 */
+ case 6: add = 128; break; /* 32 */
+ case 7: add = 256; break; /* 64 */
+ }
+ }
+
+ if ( dir_from_D0 == 0 )
+ {
+ /* DMA D0,[RAM] */
+ source = dsp_reg.ra0 << 2;
+ source &= 0x07ffffff;
+ dest &= 0x07ffffff;
+ transfer_cnt &= 0xff;
+
+#if DEBUG_DSP
+ fprintf( log_file, "/*DSP DMA D0,[RAM%d],%d add=%d*/\n", dsp_mem, transfer_cnt, add );
+#endif
+
+ for ( counter = 0; counter < transfer_cnt ; counter++ )
+ {
+#if DEBUG_DSP
+ fprintf( log_file, "%08X, ", source ); fflush( log_file );
+#endif
+
+ if ( source >= 0x06000000 && source <= 0x060fffff )
+ {
+ data = program_read_dword(source );
+ }
+ else
+ {
+ data = 0;
+ //popmessage( "Bad DSP DMA mem read = %08X", source );
+#if DEBUG_DSP
+ fprintf( log_file, "/*Bad DSP DMA mem read = %08X*/\n", source );
+#endif
+ }
+
+#if DEBUG_DSP
+ fprintf( log_file, "%08X,\n", data );
+#endif
+
+ dsp_set_dest_dma_mem( dsp_mem, data, counter );
+ source += add;
+ }
+
+ if ( hold == 0 )
+ {
+ dsp_reg.ra0 += ((counter * add) >> 2);
+ }
+ }
+ else
+ {
+ /* DMA [RAM],D0 */
+ dest = dsp_reg.wa0 << 2;
+ source &= 0x07ffffff;
+ dest &= 0x07ffffff;
+ transfer_cnt &= 0xff;
+ //logerror("[DSP DMA] SRC = %08x | DEST = %08x | SIZE = %08x | ADD VALUE = %08x\n",source,dest,transfer_cnt,add);
+
+#if DEBUG_DSP
+ fprintf( log_file, "/*DSP DMA [RAM%d],D0,%d\tadd=%d,source=%08X*/\n", dsp_mem, transfer_cnt, add, source );
+#endif
+ for ( counter = 0; counter < transfer_cnt; counter++ )
+ {
+ program_write_dword(dest, dsp_get_mem_source_dma( dsp_mem, counter ) );
+ dest += add;
+ }
+
+ if ( hold == 0 )
+ {
+ dsp_reg.wa0 += ((counter * add) >> 2);
+ }
+ }
+
+ T0F_0;
+}
+
+static void dsp_jump( void )
+{
+ if ( opcode & 0x3f80000 )
+ {
+ if ( dsp_compute_condition( (opcode & 0x3f80000) >> 19 ) )
+ {
+ dsp_reg.delay = dsp_reg.pc;
+ dsp_reg.pc = opcode & 0xff;
+ }
+ }
+ else
+ {
+ dsp_reg.delay = dsp_reg.pc;
+ dsp_reg.pc = opcode & 0xff;
+ }
+}
+
+static void dsp_end( void )
+{
+ if(opcode & 0x08000000)
+ {
+ /*ENDI*/
+ if(!EF) stv_scu[32]^=0x00040000;
+ if(EXF) stv_scu[32]^=0x00100000;
+ }
+ else
+ {
+ /*END*/
+ if(EXF) stv_scu[32]^=0x00100000;
+ }
+
+}
+
+static void dsp_loop( void )
+{
+ if ( opcode & 0x8000000 )
+ {
+ /* LPS */
+ if ( dsp_reg.lop != 0 )
+ {
+ dsp_reg.lop--;
+ dsp_reg.delay = dsp_reg.pc;
+ dsp_reg.pc--;
+ }
+ }
+ else
+ {
+ /* BTM */
+ if ( dsp_reg.lop != 0 )
+ {
+ dsp_reg.lop--;
+ dsp_reg.delay = dsp_reg.pc;
+ dsp_reg.pc = dsp_reg.top;
+ }
+ }
+}
+
+#if DEBUG_DSP
+static void dsp_dump_mem( FILE *f )
+{
+ UINT16 i;
+
+ fprintf( f, "\n/*MEM 0*/\n{" );
+ for ( i = 0; i < 0x40; i++ )
+ {
+ fprintf( f, "%08X, ", dsp_reg.md0[ i ] );
+ }
+ fprintf( f, "}\n/*MEM 1*/\n{" );
+ for ( i = 0; i < 0x40; i++ )
+ {
+ fprintf( f, "%08X,", dsp_reg.md1[ i ] );
+ }
+ fprintf( f, "}\n/*MEM 2*/\n{" );
+ for ( i = 0; i < 0x40; i++ )
+ {
+ fprintf( f, "%08X,", dsp_reg.md2[ i ] );
+ }
+ fprintf( f, "}\n/*MEM 3*/\n{" );
+ for ( i = 0; i < 0x40; i++ )
+ {
+ fprintf( f, "%08X,", dsp_reg.md3[ i ] );
+ }
+ fprintf( f, "}\n" );
+}
+#endif
+
+void dsp_execute_program()
+{
+ UINT32 cycles_run = 0;
+ UINT8 cont = 1;
+#if DEBUG_DSP
+ UINT16 i;
+
+ if ( log_file == NULL )
+ {
+ log_file = fopen("dsp.log", "a");
+ }
+ for ( i = 0; i < 0x100; i++ )
+ {
+ dsp_dasm_opcode( dsp_reg.internal_prg[ i ], dasm_buffer );
+ fprintf( log_file, "%02X\t%08X\t%s\n", i, dsp_reg.internal_prg[ i ], dasm_buffer );
+ }
+ dsp_dump_mem( log_file );
+#endif
+
+ update_mul = 0;
+ do
+ {
+ if ( dsp_reg.delay )
+ {
+ opcode = dsp_reg.internal_prg[ dsp_reg.delay ];
+ dsp_reg.delay = 0;
+ }
+ else
+ {
+ opcode = dsp_reg.internal_prg[ dsp_reg.pc ];
+ dsp_reg.pc++;
+ }
+
+ dsp_dasm_opcode( opcode, dasm_buffer );
+
+ switch( (opcode & 0xc0000000) >> 30 )
+ {
+ case 0x00: /* 00 */
+ dsp_operation();
+ break;
+ case 0x01: /* 01 */
+ /* unrecognized opcode */
+ break;
+ case 0x02: /* 10 */
+ dsp_move_immediate( );
+ break;
+ case 0x03: /* 11 */
+ switch( (opcode & 0x30000000) >> 28 )
+ {
+ case 0x00:
+ dsp_dma();
+ break;
+ case 0x01:
+ dsp_jump();
+ break;
+ case 0x02:
+ dsp_loop();
+ break;
+ case 0x03:
+ dsp_end();
+ cont = 0;
+ break;
+ }
+ break;
+ }
+ if ( update_mul == 1 )
+ {
+ dsp_reg.mul = (INT64)dsp_reg.rx.si * (INT64)dsp_reg.ry.si;
+ update_mul = 0;
+ }
+
+ cycles_run++;
+
+ } while( cont );
+#if DEBUG_DSP
+ dsp_dump_mem( log_file );
+ fprintf( log_file, "\nRun %d cycles\n\n", cycles_run );
+ fclose( log_file );
+ log_file = NULL;
+#endif
+}
+
+
+
+/***********************************************************************
+
+ SCU DSP Disassembler
+
+************************************************************************/
+static const char* ALU_Commands[] =
+{
+ "", /* 0000 */
+ "AND", /* 0001 */
+ "OR", /* 0010 */
+ "XOR", /* 0011 */
+ "ADD", /* 0100 */
+ "SUB", /* 0101 */
+ "AD2", /* 0110 */
+ "???", /* 0111 */
+ "SR", /* 1000 */
+ "RR", /* 1001 */
+ "SL", /* 1010 */
+ "RL", /* 1011 */
+ "???", /* 1100 */
+ "???", /* 1101 */
+ "???", /* 1110 */
+ "RL8", /* 1111 */
+};
+
+static const char* X_Commands[] =
+{
+ "", /* 000 */
+ "", /* 001 */ /* NOP? check instruction @ 0x0B */
+ "MOV MUL,P", /* 010 */
+ "MOV %s,P", /* 011 */
+ "MOV %s,X", /* 100 */
+};
+
+static const char* Y_Commands[] =
+{
+ "", /* 000 */
+ "CLR A", /* 001 */
+ "MOV ALU,A", /* 010 */
+ "MOV %s,A", /* 011 */
+ "MOV %s,Y", /* 100 */
+};
+
+static const char* D1_Commands[] =
+{
+ "", /* 00 */
+ "MOV %I8,%d", /* 01 */
+ "???", /* 10 */
+ "MOV %S,%d", /* 11 */
+};
+
+static const char* SourceMemory[] =
+{
+ "M0", /* 000 */
+ "M1", /* 001 */
+ "M2", /* 010 */
+ "M3", /* 011 */
+ "MC0", /* 100 */
+ "MC1", /* 101 */
+ "MC2", /* 110 */
+ "MC3", /* 111 */
+};
+
+static const char* SourceMemory2[] =
+{
+ "M0", /* 0000 */
+ "M1", /* 0001 */
+ "M2", /* 0010 */
+ "M3", /* 0011 */
+ "MC0", /* 0100 */
+ "MC1", /* 0101 */
+ "MC2", /* 0110 */
+ "MC3", /* 0111 */
+ "???", /* 1000 */
+ "ALL", /* 1001 */
+ "ALH", /* 1010 */
+ "???", /* 1011 */
+ "???", /* 1100 */
+ "???", /* 1101 */
+ "???", /* 1110 */
+ "???", /* 1111 */
+};
+
+static const char* DestMemory[] =
+{
+ "MC0", /* 0000 */
+ "MC1", /* 0001 */
+ "MC2", /* 0010 */
+ "MC3", /* 0011 */
+ "RX", /* 0100 */
+ "PL", /* 0101 */
+ "RA0", /* 0110 */
+ "WA0", /* 0111 */
+ "???", /* 1000 */
+ "???", /* 1001 */
+ "LOP", /* 1010 */
+ "TOP", /* 1011 */
+ "CT0", /* 1100 */
+ "CT1", /* 1101 */
+ "CT2", /* 1110 */
+ "CT3", /* 1111 */
+};
+
+static const char* DestDMAMemory[] =
+{
+ "M0", /* 000 */
+ "M1", /* 001 */
+ "M2", /* 010 */
+ "M3", /* 011 */
+ "PRG", /* 100 */
+ "???", /* 101 */
+ "???", /* 110 */
+ "???", /* 111 */
+};
+
+static const char* MVI_Command[] =
+{
+ "MVI %I,%d", /* 0 */
+ "MVI %I,%d,%f", /* 1 */
+};
+
+static const char* JMP_Command[] =
+{
+ "JMP %IA",
+ "JMP %f,%IA",
+};
+
+static const char* DMA_Command[] =
+{
+ "DMA%H%A D0,%M,%I",
+ "DMA%H%A %s,D0,%I",
+ "DMA%H%A D0,%M,%s",
+ "DMA%H%A %s,D0,%s",
+};
+
+
+static void dsp_dasm_prefix( const char* format, char* buffer, UINT32 *data )
+{
+
+ for ( ; *format; format++ )
+ {
+ if ( *format == '%' )
+ {
+ switch( *++format )
+ {
+ case 'H':
+ if ( *data )
+ {
+ strcpy( buffer, "H" );
+ }
+ else
+ {
+ *buffer = 0;
+ }
+ break;
+ case 'A':
+ if ( *data == 0 )
+ {
+ strcpy( buffer, "0" );
+ }
+ else if ( *data == 1 )
+ {
+ *buffer = 0;
+ }
+ else
+ {
+ sprintf( buffer, "%d", 1 << (*data - 1) );
+ }
+ break;
+ case 's':
+ strcpy( buffer, SourceMemory[ *data & 0x7 ] );
+ break;
+ case 'd':
+ strcpy( buffer, DestMemory[ *data & 0xf ] );
+ break;
+ case 'S':
+ strcpy( buffer, SourceMemory2[ *data & 0xf ] );
+ break;
+ case 'I':
+ ++format;
+ if ( *format == '8' )
+ {
+ sprintf( buffer, "#$%x", *data );
+ }
+ else if ( *format == 'A' )
+ {
+ sprintf( buffer, "$%X", *data );
+ }
+ else
+ {
+ --format;
+ sprintf( buffer, "#$%X", *data );
+ }
+ break;
+ case 'f':
+ if ( !(*data & 0x20) )
+ {
+ strcpy( buffer, "N" );
+ buffer++;
+ }
+ switch( *data & 0xf )
+ {
+ case 0x3:
+ strcpy( buffer, "ZS" );
+ break;
+ case 0x2:
+ strcpy( buffer, "S" );
+ break;
+ case 0x4:
+ strcpy( buffer, "C" );
+ break;
+ case 0x8:
+ strcpy( buffer, "T0" );
+ break;
+ case 0x1:
+ strcpy( buffer, "Z" );
+ break;
+ default:
+ strcpy( buffer, "?" );
+ break;
+ }
+ break;
+ case 'M':
+ strcpy( buffer, DestDMAMemory[ *data ] );
+ break;
+
+ }
+ data++;
+ buffer += strlen( buffer );
+ }
+ else
+ {
+ *buffer++ = *format;
+ }
+ }
+ *buffer = 0;
+}
+static void dsp_dasm_operation( UINT32 op, char *buffer )
+{
+ char *my_buffer = buffer;
+ char temp_buffer[64];
+ UINT32 data[2 ];
+
+ /* NOP */
+ if ( (op & 0x3F8E3000) == 0 )
+ {
+ sprintf( buffer, "%-10s", "NOP" );
+ return;
+ }
+ /* ALU */
+ sprintf( my_buffer, "%-10s", ALU_Commands[ (op & 0x3c000000) >> 26] );
+ my_buffer += strlen( my_buffer );
+
+ /* X-Bus */
+ data[0] = (op & 0x700000) >> 20;
+ if ( op & 0x2000000 )
+ {
+ dsp_dasm_prefix( X_Commands[ 4 ], temp_buffer, data );
+ }
+ else
+ {
+ *temp_buffer = 0;
+ }
+ sprintf( my_buffer, "%-10s", temp_buffer );
+ my_buffer += strlen( my_buffer );
+
+ dsp_dasm_prefix( X_Commands[ (op & 0x1800000) >> 23 ], temp_buffer, data );
+ sprintf( my_buffer, "%-10s", temp_buffer );
+ my_buffer += strlen( my_buffer );
+
+ /* Y-Bus */
+ data[0] = (op & 0x1C000 ) >> 14 ;
+ if ( op & 0x80000 )
+ {
+ dsp_dasm_prefix( Y_Commands[4], temp_buffer, data );
+ }
+ else
+ {
+ *temp_buffer = 0;
+ }
+ sprintf( my_buffer, "%-10s", temp_buffer );
+ my_buffer += strlen( my_buffer );
+
+ dsp_dasm_prefix( Y_Commands[ (op & 0x60000) >> 17 ], temp_buffer, data );
+ sprintf( my_buffer, "%-10s", temp_buffer );
+ my_buffer += strlen( my_buffer );
+
+ /* D1-Bus */
+ switch( (op & 0x3000) >> 12 )
+ {
+ case 0x1:
+ data[0] = (op & 0xFF);
+ data[1] = ((op & 0xF00) >> 8);
+ break;
+ case 0x3:
+ data[0] = (op & 0xF);
+ data[1] = ((op & 0xF00) >> 8);
+ break;
+ };
+ dsp_dasm_prefix( D1_Commands[ (op & 0x3000) >> 12 ], temp_buffer, data );
+ sprintf( my_buffer, "%-10s", temp_buffer );
+}
+
+static void dsp_dasm_move_immediate( UINT32 op, char *buffer )
+{
+ UINT32 data[3];
+ if ( (op & 0x2000000) )
+ {
+ data[0] = op & 0x7FFFF;
+ data[1] = (op & 0x3C000000) >> 26;
+ data[2] = (op & 0x3F80000 ) >> 18;
+ dsp_dasm_prefix( MVI_Command[1], buffer, data ); /* TODO: bad mem*/
+ }
+ else
+ {
+ data[0] = op & 0x1FFFFFF;
+ data[1] = (op & 0x3C000000) >> 26;
+ dsp_dasm_prefix( MVI_Command[0], buffer, data ); /* TODO: bad mem*/
+ }
+}
+
+static void dsp_dasm_jump( UINT32 op, char *buffer )
+{
+ UINT32 data[2];
+ if ( op & 0x3F80000 )
+ {
+ data[0] = (op & 0x3F80000) >> 19;
+ data[1] = op & 0xff;
+ dsp_dasm_prefix( JMP_Command[1], buffer, data );
+ }
+ else
+ {
+ data[0] = op & 0xff;
+ dsp_dasm_prefix( JMP_Command[0], buffer, data );
+ }
+}
+
+static void dsp_dasm_loop( UINT32 op, char* buffer )
+{
+ if ( op & 0x8000000 )
+ {
+ strcpy( buffer, "LPS" );
+ }
+ else
+ {
+ strcpy( buffer, "BTM" );
+ }
+}
+
+static void dsp_dasm_end( UINT32 op, char* buffer )
+{
+ if ( op & 0x8000000 )
+ {
+ strcpy( buffer, "ENDI" );
+ }
+ else
+ {
+ strcpy( buffer, "END" );
+ }
+}
+
+static void dsp_dasm_dma( UINT32 op, char* buffer )
+{
+ UINT32 data[4];
+ data[0] = (op & 0x4000) >> 14; /* H */
+ data[1] = (op & 0x38000) >> 15; /* A */
+ data[2] = (op & 0x700) >> 8; /* Mem */
+ data[3] = (op & 0xff);
+ dsp_dasm_prefix( DMA_Command[(op & 0x3000) >> 12], buffer, data );
+}
+
+void dsp_dasm_opcode( UINT32 op, char *buffer )
+{
+ switch( (op & 0xc0000000) >> 30 )
+ {
+ case 0x00: /* 00 */
+ dsp_dasm_operation( op, buffer );
+ break;
+ case 0x01: /* 01 */
+ strcpy( buffer, "???" );
+ break;
+ case 0x02: /* 10 */
+ dsp_dasm_move_immediate( op, buffer );
+ break;
+ case 0x03: /* 11 */
+ switch( (op & 0x30000000) >> 28 )
+ {
+ case 0x00:
+ dsp_dasm_dma( op, buffer );
+ break;
+ case 0x01:
+ dsp_dasm_jump( op, buffer );
+ break;
+ case 0x02:
+ dsp_dasm_loop( op, buffer );
+ break;
+ case 0x03:
+ dsp_dasm_end( op, buffer );
+ break;
+ }
+ break;
+ }
+}
+
diff --git a/src/mame/machine/scudsp.h b/src/mame/machine/scudsp.h
new file mode 100644
index 00000000000..638551d7fca
--- /dev/null
+++ b/src/mame/machine/scudsp.h
@@ -0,0 +1,9 @@
+/*SCU DSP stuff*/
+
+extern void dsp_prg_ctrl(UINT32 data);
+extern void dsp_prg_data(UINT32 data);
+extern void dsp_ram_addr_ctrl(UINT32 data);
+extern void dsp_ram_addr_w(UINT32 data);
+extern UINT32 dsp_ram_addr_r(void);
+extern void dsp_execute_program(void);
+
diff --git a/src/mame/machine/segacrpt.c b/src/mame/machine/segacrpt.c
new file mode 100644
index 00000000000..66c682adf94
--- /dev/null
+++ b/src/mame/machine/segacrpt.c
@@ -0,0 +1,1422 @@
+/******************************************************************************
+
+ Sega encryption emulation by Nicola Salmoria
+
+
+ Several Sega Z80 games have program ROMs encrypted using a common algorithm
+ (but with a different key).
+ The hardware used to implement this encryption is either a custom CPU, or an
+ epoxy block which probably contains a standard Z80 + PALs.
+
+ The encryption affects D3, D5, and D7, and depends on M1, A0, A4, A8 and A12.
+ D0, D1, D3, D4 and D6 are always unaffected.
+
+ The encryption consists of a permutation of the three bits, which can also be
+ inverted. Therefore there are 3! * 2^3 = 48 different possible encryptions.
+
+ For simplicity, the decryption is implemented using conversion tables.
+ We need 32 of these tables, one for every possible combination of M1, A0, A4,
+ A8 and A12. However, all the games currently known are full of repetitions
+ and only use 6 different tables, the only exceptions being Pengo, Yamato and
+ Spatter which have 7 (but one of them is the identity: { 0x00, 0x08, 0x20, 0x28 } ).
+ This is most likely a limitation of the hardware.
+ Some of the early games are even weaker: of the 6 different tables, they use
+ 3 for opcodes and 3 for data, and always coupled in the same way.
+
+ In all games currently known, only bytes in the memory range 0x0000-0x7fff
+ (A15 = 0) are encrypted. My guess is that this was done to allow games to
+ copy code to RAM (in the memory range 0x8000-0xffff) and execute it from
+ there without the CPU trying to decrypt it and messing everything up.
+ However Zaxxon has RAM at 0x6000, and the CPU doesn't seem to interfere with
+ it; but it doesn't execute code from there, so it's possible that the CPU is
+ encrypting the data while writing it and decrypting it while reading (that
+ would seem kind of strange though). Video and sprite RAM and memory mapped
+ ports are all placed above 0x8000.
+
+ Given its strict limitations, this encryption is reasonably easy to break,
+ and very vulnerable to known plaintext attacks.
+
+
+
+ Ninja Princess:
+
+ there is a (bootleg?) board which has a standard Z80 + 2 bipolar PROMs
+ instead of the custom CPU. The encryption table is different from the
+ original Ninja Princess; it is actually the same as Flicky.
+
+ The first PROM is 32x8 and contains the number (0..5) of the table to
+ use depending on M1, A0, A4, A8, A12:
+
+ 00: 11 00 33 22 00 44 44 00 11 33 33 22 44 44 44 22
+ 10: 11 55 55 33 44 22 55 22 11 33 55 33 44 44 11 22
+
+ The second PROM is 256x4 and contains the 6 different XOR tables:
+
+ A D B C C B D A
+ 00: 09 09 0A 0A 0A 0A 09 09
+ 08: 0E 08 0B 0D 0D 0B 08 0E
+ 10: 0A 0C 0A 0C 0C 0A 0C 0A
+ 18: 0B 0E 0E 0B 0B 0E 0E 0B
+ 20: 0C 0C 0F 0F 0F 0F 0C 0C
+ 28: 08 0D 0B 0E 0E 0B 0D 08
+ [the remaining bytes are all 0F]
+ bit 3 is not used.
+ bits 0-2 is the XOR code inverted (0 = 0xa8, 1 = 0xa0 ... 6 = 0x08 7 = 0x00)
+
+ Here is a diagram showing how it works:
+
+ data to XOR
+ decode value
+ A ---
+ D7 --------------- 0| |
+ D3 --------------- 1| |
+ D5 --------------- 2| P |D
+ A --- D | R |0 ---|>--- D3
+ M1 --- 0| P |0 --- 3| O |1 ---|>--- D5
+ A0 --- 1| R |1 --- 4| M |2 ---|>--- D7
+ A4 --- 2| O |2 --- 5| 2 |3 ---
+ A8 --- 3| M |3 --- 6| |
+ A12 --- 4| 1 |4 --- 7| |
+ --- ---
+
+
+ My Hero:
+
+ the bootleg does the decryption using a single 256x4 PROM, mapped in the
+ obvious way:
+
+ data to XOR
+ decode value
+ A ---
+ D3 --- 0| |
+ D5 --- 1| |D
+ D7 --- 2| P |0 --- D3
+ A0 --- 3| R |1 --- D5
+ A4 --- 4| O |2 --- D7
+ A8 --- 5| M |3 ---
+ A12 --- 6| |
+ M1 --- 7| |
+ ---
+
+
+
+ List of encrypted games currently known:
+
+ CPU Part # Game Comments
+ ???-???? Buck Rogers unencrypted version available
+ 315-5010 Pengo unencrypted version available
+ 315-5013 Super Zaxxon used Zaxxon for known plaintext attack
+ ???-???? Super Locomotive
+ 315-5018 Yamato
+ ???-???? Top Roller same key as Yamato
+ 315-5028 Sindbad Mystery
+ 315-5030 Up'n Down & unencrypted version available
+ ???-???? M120 Razzmatazz
+ 315-5033 Regulus unencrypted version available
+ 315-5041 M140 Mister Viking
+ 315-5048 SWAT used Bull Fight for k.p.a.
+ 315-5051 Flicky &
+ Ninja Princess (bootleg)
+ 315-5061 Future Spy
+ 315-5064 Water Match used Mister Viking for k.p.a.
+ 315-5065 Bull Fight
+ 315-5069 Star Force game by Tehkan; same key as Super Locomotive
+ ???-???? Pinball Action game by Tehkan; also has a simple bitswap on top
+ ???-???? Spatter
+ 315-5084 Jongkyo TABLE INCOMPLETE game by Kiwako; also has a simple bitswap on top
+ 315-5093 Pitfall II
+ 315-5098 Ninja Princess unencrypted version available; same key as Up'n Down
+ 315-5102 Sega Ninja unencrypted version available
+ 315-5110 I'm Sorry used My Hero for k.p.a.
+ 315-5114 ?? pcb 834-5492 same key as Regulus
+ 315-5115 TeddyBoy Blues
+ 315-5132 My Hero
+ 315-5135 Heavy Metal &
+ Wonder Boy (set 1a & 3; bootlegs?)
+ ???-???? Lovely Cards
+
+
+ The following games use a different encryption algorithm:
+
+ 315-5162 4D Warriors & used I'm Sorry for k.p.a.
+ Rafflesia &
+ Wonder Boy (set 4)
+ 315-5177 Astro Flash &
+ Wonder Boy (set 1)
+ 315-5178 Wonder Boy (set 2) unencrypted version available
+ 315-5179 Robo-Wrestle 2001
+
+
+ The following games seem to use the same algorithm as the above ones, but
+ using a key which almost doesn't change
+
+ 317-0004 Calorie Kun unencrypted bootleg available
+ 317-0005 Space Position
+ 317-0006 Gardia (set 1)
+ 317-0007 Gardia (set 2)
+
+
+ Some text found in the ROMs:
+
+ Buck Rogers SECULITY BY MASATOSHI,MIZUNAGA
+ Super Locomotive SEGA FUKUMURA MIZUNAGA
+ Yamato SECULITY BY M,MIZUNAGA
+ Regulus SECULITY BY SYUICHI,KATAGI
+ Up'n Down 19/SEP 1983 MASATOSHI,MIZUNAGA
+ Mister Viking SECURITY BY S.KATAGI CONTROL CHIP M140
+ SWAT SECURITY BY S.KATAGI
+ Flicky SECURITY BY S.KATAGI
+ Water Match PROGRAMED BY KAWAHARA&NAKAGAWA
+ Star Force STAR FORCE TEHKAN. SECURITY BY SEGA ENTERPRISESE
+
+******************************************************************************/
+
+#include "driver.h"
+#include "segacrpt.h"
+
+
+#if 0
+static void lfkp(int mask)
+{
+ int A;
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+
+ for (A = 0x0000;A < 0x8000-14;A++)
+ {
+ static char text[] = "INSERT COIN";
+ int i;
+
+
+ if ( (RAM[A+0] & mask) == (0x21 & mask) && /* LD HL,$xxxx */
+ (RAM[A+3] & mask) == (0x11 & mask) && /* LD DE,$xxxx */
+ (RAM[A+6] & mask) == (0x01 & mask)) /* LD BC,$xxxx */
+ {
+ if ( (RAM[A+ 9] & mask) == (0x36 & mask) && /* LD (HL),$xx */
+ (RAM[A+11] & mask) == (0xed & mask) &&
+ (RAM[A+12] & mask) == (0xb0 & mask)) /* LDIR */
+ logerror("%04x: hl de bc (hl),xx ldir\n",A);
+
+ if ( (RAM[A+ 9] & mask) == (0x77 & mask) && /* LD (HL),A */
+ (RAM[A+10] & mask) == (0xed & mask) &&
+ (RAM[A+11] & mask) == (0xb0 & mask)) /* LDIR */
+ logerror("%04x: hl de bc (hl),a ldir\n",A);
+
+ if ( (RAM[A+ 9] & mask) == (0xed & mask) &&
+ (RAM[A+10] & mask) == (0xb0 & mask)) /* LDIR */
+ logerror("%04x: hl de bc ldir\n",A);
+ }
+
+ /* the following can also be PUSH IX, PUSH IY - need better checking */
+ if ( (RAM[A+0] & mask) == (0xf5 & mask) && /* PUSH AF */
+ (RAM[A+1] & mask) == (0xc5 & mask) && /* PUSH BC */
+ (RAM[A+2] & mask) == (0xd5 & mask) && /* PUSH DE */
+ (RAM[A+3] & mask) == (0xe5 & mask)) /* PUSH HL */
+ logerror("%04x: push af bc de hl\n",A);
+
+ if ( (RAM[A+0] & mask) == (0xe1 & mask) && /* POP HL */
+ (RAM[A+1] & mask) == (0xd1 & mask) && /* POP DE */
+ (RAM[A+2] & mask) == (0xc1 & mask) && /* POP BC */
+ (RAM[A+3] & mask) == (0xf1 & mask)) /* POP AF */
+ logerror("%04x: pop hl de bc af\n",A);
+
+ for (i = 0;i < strlen(text);i++)
+ if ((RAM[A+i] & mask) != (text[i] & mask)) break;
+ if (i == strlen(text))
+ logerror("%04x: INSERT COIN\n",A);
+ }
+}
+
+static void look_for_known_plaintext(void)
+{
+ lfkp(0x57);
+}
+#endif
+
+static void sega_decode(const UINT8 convtable[32][4])
+{
+ int A;
+
+ int length = memory_region_length(REGION_CPU1);
+ int cryptlen = MIN(length, 0x8000);
+ UINT8 *rom = memory_region(REGION_CPU1);
+ UINT8 *decrypted = auto_malloc(0xc000);
+
+ memory_set_decrypted_region(0, 0x0000, cryptlen - 1, decrypted);
+
+ for (A = 0x0000;A < cryptlen;A++)
+ {
+ int xor = 0;
+
+ UINT8 src = rom[A];
+
+ /* pick the translation table from bits 0, 4, 8 and 12 of the address */
+ int row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3);
+
+ /* pick the offset in the table from bits 3 and 5 of the source data */
+ int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1);
+ /* the bottom half of the translation table is the mirror image of the top */
+ if (src & 0x80)
+ {
+ col = 3 - col;
+ xor = 0xa8;
+ }
+
+ /* decode the opcodes */
+ decrypted[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xor);
+
+ /* decode the data */
+ rom[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xor);
+
+ if (convtable[2*row][col] == 0xff) /* table incomplete! (for development) */
+ decrypted[A] = 0xee;
+ if (convtable[2*row+1][col] == 0xff) /* table incomplete! (for development) */
+ rom[A] = 0xee;
+ }
+
+ /* this is a kludge to catch anyone who has code that crosses the encrypted/ */
+ /* decrypted boundary. ssanchan does it */
+ if (length > 0x8000)
+ {
+ int bytes = MIN(length - 0x8000, 0x4000);
+ memcpy(&decrypted[0x8000], &rom[0x8000], bytes);
+ }
+}
+
+
+
+void buckrog_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */
+ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...0...0 */
+ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */
+ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */
+ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */
+ { 0x80,0x00,0x88,0x08 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void pengo_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...0 */
+ { 0x08,0x28,0x88,0xa8 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */
+ { 0x08,0x00,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...1...1...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */
+ { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...0...1...0 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...1 */
+ { 0x08,0x00,0x88,0x80 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */
+ { 0x00,0x08,0x20,0x28 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */
+ { 0x08,0x28,0x88,0xa8 }, { 0x08,0x28,0x88,0xa8 }, /* ...1...1...1...0 */
+ { 0x08,0x00,0x88,0x80 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void szaxxon_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...0...0 */
+ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */
+ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */
+ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */
+ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */
+ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */
+ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...1...0 */
+ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...1 */
+ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...0 */
+ { 0xa8,0x28,0xa0,0x20 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...0...1 */
+ { 0x08,0x28,0x88,0xa8 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void suprloco_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...0 */
+ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...0...0 */
+ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...0...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */
+ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...1...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void yamato_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...0 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...0...1...1 */
+ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...0...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...0...1 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...1...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...0...0...0 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */
+ { 0xa0,0x20,0x80,0x00 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...1 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...0 */
+ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...1 */
+ { 0xa0,0x20,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...1...1...0 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+void toprollr_decode(void)
+{
+ /* same tables as in Yamato, but encrypted ROM is banked */
+ UINT8 *decrypted;
+
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...0 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...0...1...1 */
+ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...0...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...0...1 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x20,0xa0,0x28,0xa8 }, /* ...0...1...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...0...0...0 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...1 */
+ { 0xa0,0x20,0x80,0x00 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x20,0xa0,0x28,0xa8 }, /* ...1...0...1...1 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...0 */
+ { 0x88,0xa8,0x08,0x28 }, { 0x88,0xa8,0x08,0x28 }, /* ...1...1...0...1 */
+ { 0xa0,0x20,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...1...1...0 */
+ { 0x20,0xa0,0x28,0xa8 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */
+ };
+
+ int A;
+
+ UINT8 *rom = memory_region(REGION_USER1);
+ int bankstart;
+ decrypted = auto_malloc(0x6000*3);
+
+
+ for(bankstart=0;bankstart<0x6000*3;bankstart+=0x6000)
+ for (A = 0x0000;A < 0x6000;A++)
+ {
+ int xor = 0;
+
+ UINT8 src = rom[A+bankstart];
+
+ /* pick the translation table from bits 0, 4, 8 and 12 of the address */
+ int row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3);
+
+ /* pick the offset in the table from bits 3 and 5 of the source data */
+ int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1);
+ /* the bottom half of the translation table is the mirror image of the top */
+ if (src & 0x80)
+ {
+ col = 3 - col;
+ xor = 0xa8;
+ }
+
+ /* decode the opcodes */
+ decrypted[A+bankstart] = (src & ~0xa8) | (convtable[2*row][col] ^ xor);
+
+ /* decode the data */
+ rom[A+bankstart] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xor);
+ }
+
+ memory_configure_bank(1,0,3, memory_region(REGION_USER1),0x6000);
+ memory_configure_bank_decrypted(1,0,3,decrypted,0x6000);
+ memory_set_decrypted_region(0, 0x0000, 0x5fff, decrypted);
+ memory_set_bank(1, 0);
+}
+
+
+void sindbadm_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...1 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */
+ { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...0...1...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...0 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x00,0x20,0x80,0xa0 }, /* ...1...0...1...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */
+ { 0xa8,0x88,0xa0,0x80 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void regulus_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...1...0 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */
+ { 0x80,0xa0,0x00,0x20 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */
+ { 0x80,0xa0,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */
+ { 0x80,0xa0,0x00,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void mrviking_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...1...1...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...0 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...1...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...1...0 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void swat_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...0 */
+ { 0xa0,0xa8,0x80,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...1...1...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...0 */
+ { 0xa0,0x20,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */
+ { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...0 */
+ { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...1...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...1...0...1 */
+ { 0xa0,0xa8,0x80,0x88 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...1...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0xa8,0x80,0x88 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void flicky_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x08,0x88,0x00,0x80 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...1...0 */
+ { 0x28,0x08,0x20,0x00 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */
+ { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...1...0...0 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */
+ { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...1...1...0 */
+ { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...1 */
+ { 0x08,0x88,0x00,0x80 }, { 0xa8,0x88,0x28,0x08 }, /* ...1...0...0...0 */
+ { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...1 */
+ { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */
+ { 0xa8,0x88,0x28,0x08 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...1 */
+ { 0x08,0x88,0x00,0x80 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...0 */
+ { 0xa8,0x88,0x28,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...1...0...1 */
+ { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0x88,0x80,0x08,0x00 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void futspy_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x28,0x08,0x20,0x00 }, { 0x28,0x08,0x20,0x00 }, /* ...0...0...0...0 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...0...1 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...0...1...0 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...1 */
+ { 0x28,0x08,0x20,0x00 }, { 0x88,0x80,0xa8,0xa0 }, /* ...0...1...0...0 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */
+ { 0x88,0x80,0xa8,0xa0 }, { 0x28,0x08,0x20,0x00 }, /* ...1...0...0...0 */
+ { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...0...1 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 }, /* ...1...0...1...0 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */
+ { 0x88,0x80,0xa8,0xa0 }, { 0x88,0x80,0xa8,0xa0 }, /* ...1...1...0...0 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x28,0x08,0x20,0x00 }, /* ...1...1...1...0 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void wmatch_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...0...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...0...1...0 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...1 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...1 */
+ { 0xa8,0x28,0x88,0x08 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...1...0 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...1...1 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...0...1 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...0...1...0 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...0...1...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...0 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...1...0 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void bullfgtj_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...0...0...0...0 */
+ { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...0...0...0...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...0...1...0 */
+ { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...0 */
+ { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x28,0x00,0x08 }, /* ...0...1...0...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x08,0x28,0x00,0x20 }, /* ...0...1...1...0 */
+ { 0x88,0x08,0xa8,0x28 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */
+ { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */
+ { 0x88,0x08,0xa8,0x28 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...0...1 */
+ { 0x28,0xa8,0x20,0xa0 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */
+ { 0x28,0xa8,0x20,0xa0 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...0...1...1 */
+ { 0x20,0x28,0x00,0x08 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */
+ { 0x88,0x08,0xa8,0x28 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...1 */
+ { 0x08,0x28,0x00,0x20 }, { 0x80,0xa0,0x00,0x20 }, /* ...1...1...1...0 */
+ { 0x08,0x28,0x00,0x20 }, { 0x88,0x08,0xa8,0x28 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void pbaction_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...0 */
+ { 0x28,0x08,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...0...1 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...1...0 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...1 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...0...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...0...1 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...0 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x28,0x20,0xa8,0xa0 }, /* ...1...0...0...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...0...0...1 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...0...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0xa8,0x28,0xa0,0x20 }, /* ...1...1...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0x28,0xa0,0x20 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void spatter_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0x08,0x80,0x00 }, { 0x00,0x08,0x20,0x28 }, /* ...0...0...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...0...0...1 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...0...1...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...1...1 */
+ { 0x00,0x08,0x20,0x28 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...0 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x80,0x88,0x00,0x08 }, /* ...0...1...0...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x28,0x20,0xa8,0xa0 }, /* ...0...1...1...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x80,0x88,0x00,0x08 }, /* ...1...0...0...0 */
+ { 0x80,0x88,0x00,0x08 }, { 0x00,0x08,0x20,0x28 }, /* ...1...0...0...1 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...0 */
+ { 0x00,0x08,0x20,0x28 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */
+ { 0x80,0x88,0x00,0x08 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...0 */
+ { 0x80,0xa0,0x88,0xa8 }, { 0xa0,0x80,0x20,0x00 }, /* ...1...1...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...1...1...0 */
+ { 0x28,0x20,0xa8,0xa0 }, { 0x00,0x08,0x20,0x28 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void jongkyo_decode(void)
+{
+ /* encrypted ROM is banked */
+ UINT8 *decrypted;
+
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x28,0x08,0xa8,0x88 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...0 */
+ { 0x80,0x88,0xa0,0xa8 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...0...1...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...0...0...1...1 */
+ { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */
+ { 0x20,0xa0,0x00,0x80 }, { 0x20,0xa0,0x00,0x80 }, /* ...0...1...1...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...1...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...0 */
+ { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...0...1...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...1...1 */
+ { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x20,0xa0,0x00,0x80 }, /* ...1...1...1...0 */
+ { 0x80,0x88,0xa0,0xa8 }, { 0x08,0x88,0x00,0x80 } /* ...1...1...1...1 */
+ };
+
+ int A;
+
+ UINT8 *rom = memory_region(REGION_CPU1);
+ decrypted = auto_malloc(0x9000);
+
+ for (A = 0x0000;A < 0x9000;A++)
+ {
+ int xor = 0;
+
+ UINT8 src = rom[A];
+
+ /* pick the translation table from bits 0, 4, 8 and 12 of the address */
+ int row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2) + (((A >> 12) & 1) << 3);
+
+ /* pick the offset in the table from bits 3 and 5 of the source data */
+ int col = ((src >> 3) & 1) + (((src >> 5) & 1) << 1);
+ /* the bottom half of the translation table is the mirror image of the top */
+ if (src & 0x80)
+ {
+ col = 3 - col;
+ xor = 0xa8;
+ }
+
+ /* special handling for banked area */
+ if (A >= 0x7000)
+ row = (A & 1) + (((A >> 4) & 1) << 1) + (((A >> 8) & 1) << 2);
+
+ /* decode the opcodes */
+ decrypted[A] = (src & ~0xa8) | (convtable[2*row][col] ^ xor);
+
+ /* decode the data */
+ rom[A] = (src & ~0xa8) | (convtable[2*row+1][col] ^ xor);
+ }
+
+ memory_configure_bank(1,0,8, memory_region(REGION_CPU1)+0x7000,0x0400);
+ memory_configure_bank_decrypted(1,0,8,decrypted+0x7000,0x0400);
+ memory_set_decrypted_region(0, 0x0000, 0x6bff, decrypted);
+ memory_set_bank(1, 0);
+}
+
+
+void pitfall2_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */
+ { 0x08,0x88,0x28,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...0...0...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...1...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...0 */
+ { 0x28,0xa8,0x20,0xa0 }, { 0x20,0x00,0xa0,0x80 }, /* ...0...1...0...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...0 */
+ { 0x28,0xa8,0x20,0xa0 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...1...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...0 */
+ { 0x80,0x88,0xa0,0xa8 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...0...0...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */
+ { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 }, /* ...1...0...1...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0x80,0x88,0xa0,0xa8 }, /* ...1...1...0...0 */
+ { 0x80,0x88,0xa0,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...1...0...1 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */
+ { 0x80,0x88,0xa0,0xa8 }, { 0x28,0xa8,0x20,0xa0 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void nprinces_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x08,0x88,0x00,0x80 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...0...0...0 */
+ { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...0...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...0...1...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x20,0x80,0x00 }, /* ...0...1...0...0 */
+ { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...0...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...1...1...1 */
+ { 0xa0,0x20,0x80,0x00 }, { 0xa0,0x20,0x80,0x00 }, /* ...1...0...0...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...0...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...1...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void seganinj_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...0...1 */
+ { 0xa8,0xa0,0x28,0x20 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...0...1...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0xa8,0x80,0x88 }, /* ...0...0...1...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x88,0x08,0x80,0x00 }, /* ...0...1...0...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x28,0x20 }, /* ...0...1...1...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */
+ { 0xa0,0xa8,0x80,0x88 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...0...1 */
+ { 0xa8,0xa0,0x28,0x20 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */
+ { 0xa8,0xa0,0x28,0x20 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...0...1...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...0...0 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...1...0...1 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...1...1...0 */
+ { 0xa8,0xa0,0x28,0x20 }, { 0x28,0x08,0xa8,0x88 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void imsorry_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0x08,0x80,0x00 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...0...0 */
+ { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0x80,0x00 }, /* ...0...0...0...1 */
+ { 0x88,0x08,0xa8,0x28 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...0...1...0 */
+ { 0x00,0x20,0x80,0xa0 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...0...1...1 */
+ { 0x00,0x20,0x80,0xa0 }, { 0x08,0x00,0x88,0x80 }, /* ...0...1...0...0 */
+ { 0x00,0x20,0x80,0xa0 }, { 0x20,0x28,0xa0,0xa8 }, /* ...0...1...0...1 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x00,0x20,0x80,0xa0 }, /* ...0...1...1...0 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x88,0x08,0xa8,0x28 }, /* ...0...1...1...1 */
+ { 0x88,0x08,0x80,0x00 }, { 0x08,0x00,0x88,0x80 }, /* ...1...0...0...0 */
+ { 0x08,0x00,0x88,0x80 }, { 0x88,0x08,0x80,0x00 }, /* ...1...0...0...1 */
+ { 0x08,0x28,0x00,0x20 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...0 */
+ { 0x88,0x08,0x80,0x00 }, { 0x08,0x28,0x00,0x20 }, /* ...1...0...1...1 */
+ { 0x08,0x28,0x00,0x20 }, { 0x08,0x00,0x88,0x80 }, /* ...1...1...0...0 */
+ { 0x08,0x28,0x00,0x20 }, { 0x20,0x28,0xa0,0xa8 }, /* ...1...1...0...1 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 }, /* ...1...1...1...0 */
+ { 0x20,0x28,0xa0,0xa8 }, { 0x08,0x28,0x00,0x20 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void teddybb_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x20,0x28,0x00,0x08 }, { 0x80,0x00,0xa0,0x20 }, /* ...0...0...0...0 */
+ { 0x20,0x28,0x00,0x08 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...0...0...1 */
+ { 0x28,0x08,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...1...1 */
+ { 0x20,0x28,0x00,0x08 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...0...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...0...1...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x80,0x00,0xa0,0x20 }, /* ...1...0...0...0 */
+ { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0xa8,0x20,0x28 }, /* ...1...0...0...1 */
+ { 0xa0,0x20,0xa8,0x28 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...0 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...0...1...1 */
+ { 0x80,0x00,0xa0,0x20 }, { 0x20,0x28,0x00,0x08 }, /* ...1...1...0...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...1 */
+ { 0x80,0x00,0xa0,0x20 }, { 0xa0,0x80,0xa8,0x88 }, /* ...1...1...1...0 */
+ { 0xa0,0xa8,0x20,0x28 }, { 0xa0,0x20,0xa8,0x28 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void myheroj_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...0 */
+ { 0x20,0x00,0xa0,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...0...1 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...0...0...1...1 */
+ { 0x20,0x00,0xa0,0x80 }, { 0x28,0xa8,0x08,0x88 }, /* ...0...1...0...0 */
+ { 0x20,0x00,0xa0,0x80 }, { 0x08,0x88,0x00,0x80 }, /* ...0...1...0...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...0 */
+ { 0x08,0x88,0x00,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...1...1...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...0 */
+ { 0x80,0xa0,0x88,0xa8 }, { 0x20,0x00,0xa0,0x80 }, /* ...1...0...0...1 */
+ { 0x80,0xa0,0x88,0xa8 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...0 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0x80,0xa0,0x88,0xa8 }, /* ...1...0...1...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0x08,0x88,0x00,0x80 }, /* ...1...1...0...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 }, /* ...1...1...1...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0xa8,0xa0,0x88,0x80 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void hvymetal_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0x88,0xa8,0x80,0xa0 }, { 0xa0,0x80,0xa8,0x88 }, /* ...0...0...0...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x88,0xa8,0x80,0xa0 }, /* ...0...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x88,0x80,0x08,0x00 }, /* ...0...0...1...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...0...1 */
+ { 0xa0,0x80,0xa8,0x88 }, { 0x88,0x80,0x08,0x00 }, /* ...0...1...1...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0x28,0x08,0xa8,0x88 }, /* ...0...1...1...1 */
+ { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...0 */
+ { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...0...1 */
+ { 0xa0,0x20,0xa8,0x28 }, { 0x88,0xa8,0x80,0xa0 }, /* ...1...0...1...0 */
+ { 0x88,0xa8,0x80,0xa0 }, { 0x28,0x08,0xa8,0x88 }, /* ...1...0...1...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...0...0 */
+ { 0xa0,0x20,0xa8,0x28 }, { 0x28,0xa8,0x08,0x88 }, /* ...1...1...0...1 */
+ { 0x28,0xa8,0x08,0x88 }, { 0xa0,0x20,0xa8,0x28 }, /* ...1...1...1...0 */
+ { 0x28,0x08,0xa8,0x88 }, { 0x28,0xa8,0x08,0x88 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+void lvcards_decode(void)
+{
+ static const UINT8 convtable[32][4] =
+ {
+ /* opcode data address */
+ /* A B C D A B C D */
+ { 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...0...0...0 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...0...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...0...1...0 */
+ { 0xa8,0xa0,0x88,0x80 }, { 0xa8,0xa0,0x88,0x80 }, /* ...0...0...1...1 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0xa0,0x20 }, /* ...0...1...0...0 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...0...1...0...1 */
+ { 0xa0,0x80,0x20,0x00 }, { 0xa0,0x80,0x20,0x00 }, /* ...0...1...1...0 */
+ { 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x88,0xa0,0x80 }, /* ...0...1...1...1 */
+ { 0xa8,0x88,0xa0,0x80 }, { 0xa8,0x28,0x88,0x08 }, /* ...1...0...0...0 */
+ { 0x88,0x80,0x08,0x00 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...0...1 */
+ { 0xa8,0x28,0x88,0x08 }, { 0x88,0x80,0x08,0x00 }, /* ...1...0...1...0 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x28,0x88,0x08 }, /* ...1...0...1...1 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x88,0xa0,0x80 }, /* ...1...1...0...0 */
+ { 0xa8,0x88,0xa0,0x80 }, { 0x88,0x80,0x08,0x00 }, /* ...1...1...0...1 */
+ { 0x88,0x80,0x08,0x00 }, { 0xa8,0x28,0x88,0x08 }, /* ...1...1...1...0 */
+ { 0xa8,0x28,0x88,0x08 }, { 0xa8,0x88,0xa0,0x80 } /* ...1...1...1...1 */
+ };
+
+
+ sega_decode(convtable);
+}
+
+
+
+/******************************************************************************
+
+ New encryption
+
+ This encryption is quite different from the older one. It permutates bits
+ D0, D2, D4 and D6, then inverts some of them.
+
+ The permutation and inversion depend on A0, A3, A6, A9, A12, and A14.
+
+******************************************************************************/
+
+static void sega_decode_2(const UINT8 opcode_xor[64],const int opcode_swap_select[64],
+ const UINT8 data_xor[64],const int data_swap_select[64])
+{
+ int A;
+ static const UINT8 swaptable[24][4] =
+ {
+ { 6,4,2,0 }, { 4,6,2,0 }, { 2,4,6,0 }, { 0,4,2,6 },
+ { 6,2,4,0 }, { 6,0,2,4 }, { 6,4,0,2 }, { 2,6,4,0 },
+ { 4,2,6,0 }, { 4,6,0,2 }, { 6,0,4,2 }, { 0,6,4,2 },
+ { 4,0,6,2 }, { 0,4,6,2 }, { 6,2,0,4 }, { 2,6,0,4 },
+ { 0,6,2,4 }, { 2,0,6,4 }, { 0,2,6,4 }, { 4,2,0,6 },
+ { 2,4,0,6 }, { 4,0,2,6 }, { 2,0,4,6 }, { 0,2,4,6 },
+ };
+
+
+ UINT8 *rom = memory_region(REGION_CPU1);
+ UINT8 *decrypted = auto_malloc(0x8000);
+
+ memory_set_decrypted_region(0, 0x0000, 0x7fff, decrypted);
+
+
+ for (A = 0x0000;A < 0x8000;A++)
+ {
+ int row;
+ UINT8 src;
+ const UINT8 *tbl;
+
+
+ src = rom[A];
+
+ /* pick the translation table from bits 0, 3, 6, 9, 12 and 14 of the address */
+ row = (A & 1) + (((A >> 3) & 1) << 1) + (((A >> 6) & 1) << 2)
+ + (((A >> 9) & 1) << 3) + (((A >> 12) & 1) << 4) + (((A >> 14) & 1) << 5);
+
+ /* decode the opcodes */
+ tbl = swaptable[opcode_swap_select[row]];
+ decrypted[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ opcode_xor[row];
+
+ /* decode the data */
+ tbl = swaptable[data_swap_select[row]];
+ rom[A] = BITSWAP8(src,7,tbl[0],5,tbl[1],3,tbl[2],1,tbl[3]) ^ data_xor[row];
+ }
+}
+
+
+
+void fdwarrio_decode(void)
+{
+ static const UINT8 opcode_xor[64] =
+ {
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ 0x40,0x50,0x44,0x54,0x41,0x51,0x45,0x55,
+ };
+
+ static const UINT8 data_xor[64] =
+ {
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ 0x10,0x04,0x14,0x01,0x11,0x05,0x15,0x00,
+ };
+
+ static const int opcode_swap_select[64] =
+ {
+ 4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,
+ 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,
+ };
+
+ static const int data_swap_select[64] =
+ {
+ 4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,
+ 8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,
+ 10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,
+ 12,
+ };
+
+
+ sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select);
+}
+
+
+void astrofl_decode(void)
+{
+ static const UINT8 opcode_xor[64] =
+ {
+ 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45,
+ 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45,
+ 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,
+ 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45,
+ 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,0x41,0x00,0x54,0x45,
+ 0x04,0x51,0x40,0x01,0x55,0x44,0x05,0x50,
+ };
+
+ static const UINT8 data_xor[64] =
+ {
+ 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40,
+ 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40,
+ 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,
+ 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40,
+ 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,0x45,0x50,0x11,0x40,
+ 0x54,0x15,0x44,0x51,0x10,0x41,0x55,0x14,
+ };
+
+ static const int opcode_swap_select[64] =
+ {
+ 0,0,1,1,1,2,2,3,3,4,4,4,5,5,6,6,
+ 6,7,7,8,8,9,9,9,10,10,11,11,11,12,12,13,
+
+ 8,8,9,9,9,10,10,11,11,12,12,12,13,13,14,14,
+ 14,15,15,16,16,17,17,17,18,18,19,19,19,20,20,21,
+ };
+
+ static const int data_swap_select[64] =
+ {
+ 0,0,1,1,2,2,2,3,3,4,4,5,5,5,6,6,
+ 7,7,7,8,8,9,9,10,10,10,11,11,12,12,12,13,
+
+ 8,8,9,9,10,10,10,11,11,12,12,13,13,13,14,14,
+ 15,15,15,16,16,17,17,18,18,18,19,19,20,20,20,21,
+ };
+
+
+ sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select);
+}
+
+
+void wboy2_decode(void)
+{
+ static const UINT8 opcode_xor[64] =
+ {
+ 0x00,0x45,0x11,0x01,0x44,0x10,0x55,0x05,0x41,0x14,0x04,0x40,0x15,0x51,
+ 0x01,0x44,0x10,0x00,0x45,0x11,0x54,0x04,0x40,0x15,0x05,0x41,0x14,0x50,
+ 0x00,0x45,0x11,0x01,
+ 0x00,0x45,0x11,0x01,0x44,0x10,0x55,0x05,0x41,0x14,0x04,0x40,0x15,0x51,
+ 0x01,0x44,0x10,0x00,0x45,0x11,0x54,0x04,0x40,0x15,0x05,0x41,0x14,0x50,
+ 0x00,0x45,0x11,0x01,
+ };
+
+ static const UINT8 data_xor[64] =
+ {
+ 0x55,0x05,0x41,0x14,0x50,0x00,0x15,0x51,0x01,0x44,0x10,0x55,0x05,0x11,
+ 0x54,0x04,0x40,0x15,0x51,0x01,0x14,0x50,0x00,0x45,0x11,0x54,0x04,0x10,
+ 0x55,0x05,0x41,0x14,
+ 0x55,0x05,0x41,0x14,0x50,0x00,0x15,0x51,0x01,0x44,0x10,0x55,0x05,0x11,
+ 0x54,0x04,0x40,0x15,0x51,0x01,0x14,0x50,0x00,0x45,0x11,0x54,0x04,0x10,
+ 0x55,0x05,0x41,0x14,
+ };
+
+ static const int opcode_swap_select[64] =
+ {
+ 2,
+ 5,1,5,1,5,
+ 0,4,0,4,0,4,
+ 7,3,7,3,7,3,
+ 6,2,6,2,6,
+ 1,5,1,5,1,5,
+ 0,4,0,
+
+ 10,
+ 13,9,13,9,13,
+ 8,12,8,12,8,12,
+ 15,11,15,11,15,11,
+ 14,10,14,10,14,
+ 9,13,9,13,9,13,
+ 8,12,8,
+ };
+
+ static const int data_swap_select[64] =
+ {
+ 3,7,3,7,3,7,
+ 2,6,2,6,2,
+ 5,1,5,1,5,1,
+ 4,0,4,0,4,
+ 8,
+ 3,7,3,7,3,
+ 6,2,6,2,
+
+ 11,15,11,15,11,15,
+ 10,14,10,14,10,
+ 13,9,13,9,13,9,
+ 12,8,12,8,12,
+ 16,
+ 11,15,11,15,11,
+ 14,10,14,10,
+ };
+
+
+ sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select);
+}
+
+
+void robowres_decode(void)
+{
+ static const UINT8 opcode_xor[64] =
+ {
+ 0x00,0x41,0x10,0x51,0x04,0x45,0x14, 0x00,0x41,0x10,0x51,0x04,0x45,0x14, 0x55,
+ 0x01,0x40,0x11,0x50,0x05,0x44,0x15, 0x01,0x40,0x11,0x50,0x05,0x44,0x15, 0x54,
+ 0x00,0x41,
+ 0x50,0x05,0x44,0x15,0x54,0x00,0x41, 0x50,0x05,0x44,0x15,0x54,0x00,0x41, 0x10,
+ 0x51,0x04,0x45,0x14,0x55,0x01,0x40, 0x51,0x04,0x45,0x14,0x55,0x01,0x40, 0x11,
+ 0x50,0x05
+ };
+
+ static const UINT8 data_xor[64] =
+ {
+ 0x45,0x14,0x55,0x01,0x40,0x11,0x50, 0x05,0x44,0x15,0x54,0x00,0x41,0x10, 0x05,
+ 0x44,0x15,0x54,0x00,0x41,0x10,0x51, 0x04,0x45,0x14,0x55,0x01,0x40,0x11, 0x04,
+ 0x45,0x14,
+ 0x00,0x41,0x10,0x51,0x04,0x45,0x14, 0x55,0x01,0x40,0x11,0x50,0x05,0x44, 0x55,
+ 0x01,0x40,0x11,0x50,0x05,0x44,0x15, 0x54,0x00,0x41,0x10,0x51,0x04,0x45, 0x54,
+ 0x00,0x41
+ };
+
+ static const int opcode_swap_select[64] =
+ {
+ 8,11,15,2,6,
+ 9,13,1,4,8,11,15,2,6,
+ 9,13,1,4,8,11,15,2,6,
+ 10,13,1,4,8,11,15,3,6,
+
+ 7,2,6,1,5,
+ 1,4,0,3,7,2,6,2,5,
+ 1,4,0,3,7,2,6,2,5,
+ 1,4,0,3,7,3,6,2,5,
+ };
+
+ static const int data_swap_select[64] =
+ {
+ 9,13,0,4,8,11,15,2,6,
+ 9,13,1,4,8,11,15,2,6,
+ 10,13,1,4,8,11,15,2,6,
+ 10,13,1,4,8,
+
+ 1,4,0,3,7,2,6,1,5,
+ 1,4,0,3,7,2,6,2,5,
+ 1,4,0,3,7,3,6,2,5,
+ 1,4,0,4,7,
+ };
+
+
+ sega_decode_2(opcode_xor,opcode_swap_select,data_xor,data_swap_select);
+}
+
+
+/******************************************************************************
+
+ These games (all 317-xxxx CPUs) use the same algorithm, but the key doesn't
+ change much - just one or two positions shift in the table.
+
+******************************************************************************/
+
+static void sega_decode_317(int order, int opcode_shift, int data_shift)
+{
+ static const UINT8 xor1_317[1+64] =
+ {
+ 0x54,
+ 0x14,0x15,0x41,0x14,0x50,0x55,0x05,0x41,0x01,0x10,0x51,0x05,0x11,0x05,0x14,0x55,
+ 0x41,0x05,0x04,0x41,0x14,0x10,0x45,0x50,0x00,0x45,0x00,0x00,0x00,0x45,0x00,0x00,
+ 0x54,0x04,0x15,0x10,0x04,0x05,0x11,0x44,0x04,0x01,0x05,0x00,0x44,0x15,0x40,0x45,
+ 0x10,0x15,0x51,0x50,0x00,0x15,0x51,0x44,0x15,0x04,0x44,0x44,0x50,0x10,0x04,0x04,
+ };
+
+ static const UINT8 xor2_317[2+64] =
+ {
+ 0x04,
+ 0x44,
+ 0x15,0x51,0x41,0x10,0x15,0x54,0x04,0x51,0x05,0x55,0x05,0x54,0x45,0x04,0x10,0x01,
+ 0x51,0x55,0x45,0x55,0x45,0x04,0x55,0x40,0x11,0x15,0x01,0x40,0x01,0x11,0x45,0x44,
+ 0x40,0x05,0x15,0x15,0x01,0x50,0x00,0x44,0x04,0x50,0x51,0x45,0x50,0x54,0x41,0x40,
+ 0x14,0x40,0x50,0x45,0x10,0x05,0x50,0x01,0x40,0x01,0x50,0x50,0x50,0x44,0x40,0x10,
+ };
+
+ static const int swap1_317[1+64] =
+ {
+ 7,
+ 1,11,23,17,23, 0,15,19,
+ 20,12,10, 0,18,18, 5,20,
+ 13, 0,18,14, 5, 6,10,21,
+ 1,11, 9, 3,21, 4, 1,17,
+ 5, 7,16,13,19,23,20, 2,
+ 10,23,23,15,10,12, 0,22,
+ 14, 6,15,11,17,15,21, 0,
+ 6, 1, 1,18, 5,15,15,20,
+ };
+
+ static const int swap2_317[2+64] =
+ {
+ 7,
+ 12,
+ 18, 8,21, 0,22,21,13,21,
+ 20,13,20,14, 6, 3, 5,20,
+ 8,20, 4, 8,17,22, 0, 0,
+ 6,17,17, 9, 0,16,13,21,
+ 3, 2,18, 6,11, 3, 3,18,
+ 18,19, 3, 0, 5, 0,11, 8,
+ 8, 1, 7, 2,10, 8,10, 2,
+ 1, 3,12,16, 0,17,10, 1,
+ };
+
+ if (order)
+ sega_decode_2( xor2_317+opcode_shift, swap2_317+opcode_shift, xor1_317+data_shift, swap1_317+data_shift );
+ else
+ sega_decode_2( xor1_317+opcode_shift, swap1_317+opcode_shift, xor2_317+data_shift, swap2_317+data_shift );
+}
+
+void spcpostn_decode(void) { sega_decode_317( 0, 0, 1 ); }
+void calorie_decode(void) { sega_decode_317( 1, 0, 0 ); }
+void gardia_decode(void) { sega_decode_317( 1, 1, 1 ); }
+void gardiab_decode(void) { sega_decode_317( 0, 1, 2 ); }
diff --git a/src/mame/machine/segacrpt.h b/src/mame/machine/segacrpt.h
new file mode 100644
index 00000000000..100be5af546
--- /dev/null
+++ b/src/mame/machine/segacrpt.h
@@ -0,0 +1,35 @@
+void buckrog_decode(void);
+void pengo_decode(void);
+void szaxxon_decode(void);
+void suprloco_decode(void);
+void yamato_decode(void);
+void toprollr_decode(void);
+void sindbadm_decode(void);
+void regulus_decode(void);
+void mrviking_decode(void);
+void swat_decode(void);
+void flicky_decode(void);
+void futspy_decode(void);
+void wmatch_decode(void);
+void bullfgtj_decode(void);
+void pbaction_decode(void);
+void spatter_decode(void);
+void jongkyo_decode(void);
+void pitfall2_decode(void);
+void nprinces_decode(void);
+void seganinj_decode(void);
+void imsorry_decode(void);
+void teddybb_decode(void);
+void myheroj_decode(void);
+void hvymetal_decode(void);
+void lvcards_decode(void);
+
+void fdwarrio_decode(void);
+void astrofl_decode(void);
+void wboy2_decode(void);
+void robowres_decode(void);
+void calorie_decode(void);
+void spcpostn_decode(void);
+void gardia_decode(void);
+void gardiab_decode(void);
+
diff --git a/src/mame/machine/segag80.c b/src/mame/machine/segag80.c
new file mode 100644
index 00000000000..d443efe8de7
--- /dev/null
+++ b/src/mame/machine/segag80.c
@@ -0,0 +1,347 @@
+/***************************************************************************
+
+ Sega G-80 raster hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "segag80r.h"
+
+UINT8 (*sega_decrypt)(offs_t,UINT8);
+
+
+/****************************************************************************/
+/* MB 971025 - Emulate Sega G80 security chip 315-0062 */
+/****************************************************************************/
+static UINT8 sega_decrypt62(offs_t pc, UINT8 lo)
+{
+ UINT32 i = 0;
+ UINT32 b = lo;
+
+ switch (pc & 0x03)
+ {
+ case 0x00:
+ /* D */
+ i=b & 0x23;
+ i+=((b & 0xC0) >> 4);
+ i+=((b & 0x10) << 2);
+ i+=((b & 0x08) << 1);
+ i+=(((~b) & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x01:
+ /* C */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 4);
+ i+=(((~b) & 0x40) >> 1);
+ i+=((b & 0x20) >> 1);
+ i+=((b & 0x10) >> 2);
+ i+=((b & 0x08) << 3);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x02:
+ /* B */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 1);
+ i+=((b & 0x60) >> 3);
+ i+=((~b) & 0x10);
+ i+=((b & 0x08) << 2);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x03:
+ /* A */
+ i=b;
+ break;
+ }
+
+ return i;
+}
+
+/****************************************************************************/
+/* MB 971025 - Emulate Sega G80 security chip 315-0063 */
+/****************************************************************************/
+static UINT8 sega_decrypt63(offs_t pc, UINT8 lo)
+{
+ UINT32 i = 0;
+ UINT32 b = lo;
+
+ switch (pc & 0x09)
+ {
+ case 0x00:
+ /* D */
+ i=b & 0x23;
+ i+=((b & 0xC0) >> 4);
+ i+=((b & 0x10) << 2);
+ i+=((b & 0x08) << 1);
+ i+=(((~b) & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x01:
+ /* C */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 4);
+ i+=(((~b) & 0x40) >> 1);
+ i+=((b & 0x20) >> 1);
+ i+=((b & 0x10) >> 2);
+ i+=((b & 0x08) << 3);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x08:
+ /* B */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 1);
+ i+=((b & 0x60) >> 3);
+ i+=((~b) & 0x10);
+ i+=((b & 0x08) << 2);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x09:
+ /* A */
+ i=b;
+ break;
+ }
+
+ return i;
+}
+
+/****************************************************************************/
+/* MB 971025 - Emulate Sega G80 security chip 315-0064 */
+/****************************************************************************/
+static UINT8 sega_decrypt64(offs_t pc, UINT8 lo)
+{
+ UINT32 i = 0;
+ UINT32 b = lo;
+
+ switch (pc & 0x03)
+ {
+ case 0x00:
+ /* A */
+ i=b;
+ break;
+ case 0x01:
+ /* B */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 1);
+ i+=((b & 0x60) >> 3);
+ i+=((~b) & 0x10);
+ i+=((b & 0x08) << 2);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x02:
+ /* C */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 4);
+ i+=(((~b) & 0x40) >> 1);
+ i+=((b & 0x20) >> 1);
+ i+=((b & 0x10) >> 2);
+ i+=((b & 0x08) << 3);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x03:
+ /* D */
+ i=b & 0x23;
+ i+=((b & 0xC0) >> 4);
+ i+=((b & 0x10) << 2);
+ i+=((b & 0x08) << 1);
+ i+=(((~b) & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ }
+
+ return i;
+}
+
+
+/****************************************************************************/
+/* MB 971025 - Emulate Sega G80 security chip 315-0070 */
+/****************************************************************************/
+static UINT8 sega_decrypt70(offs_t pc, UINT8 lo)
+{
+ UINT32 i = 0;
+ UINT32 b = lo;
+
+ switch (pc & 0x09)
+ {
+ case 0x00:
+ /* B */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 1);
+ i+=((b & 0x60) >> 3);
+ i+=((~b) & 0x10);
+ i+=((b & 0x08) << 2);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x01:
+ /* A */
+ i=b;
+ break;
+ case 0x08:
+ /* D */
+ i=b & 0x23;
+ i+=((b & 0xC0) >> 4);
+ i+=((b & 0x10) << 2);
+ i+=((b & 0x08) << 1);
+ i+=(((~b) & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x09:
+ /* C */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 4);
+ i+=(((~b) & 0x40) >> 1);
+ i+=((b & 0x20) >> 1);
+ i+=((b & 0x10) >> 2);
+ i+=((b & 0x08) << 3);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ }
+
+ return i;
+}
+
+/****************************************************************************/
+/* MB 971025 - Emulate Sega G80 security chip 315-0076 */
+/****************************************************************************/
+static UINT8 sega_decrypt76(offs_t pc, UINT8 lo)
+{
+ UINT32 i = 0;
+ UINT32 b = lo;
+
+ switch (pc & 0x09)
+ {
+ case 0x00:
+ /* A */
+ i=b;
+ break;
+ case 0x01:
+ /* B */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 1);
+ i+=((b & 0x60) >> 3);
+ i+=((~b) & 0x10);
+ i+=((b & 0x08) << 2);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x08:
+ /* C */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 4);
+ i+=(((~b) & 0x40) >> 1);
+ i+=((b & 0x20) >> 1);
+ i+=((b & 0x10) >> 2);
+ i+=((b & 0x08) << 3);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x09:
+ /* D */
+ i=b & 0x23;
+ i+=((b & 0xC0) >> 4);
+ i+=((b & 0x10) << 2);
+ i+=((b & 0x08) << 1);
+ i+=(((~b) & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ }
+
+ return i;
+}
+
+/****************************************************************************/
+/* MB 971025 - Emulate Sega G80 security chip 315-0082 */
+/****************************************************************************/
+static UINT8 sega_decrypt82(offs_t pc, UINT8 lo)
+{
+ UINT32 i = 0;
+ UINT32 b = lo;
+
+ switch (pc & 0x11)
+ {
+ case 0x00:
+ /* A */
+ i=b;
+ break;
+ case 0x01:
+ /* B */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 1);
+ i+=((b & 0x60) >> 3);
+ i+=((~b) & 0x10);
+ i+=((b & 0x08) << 2);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x10:
+ /* C */
+ i=b & 0x03;
+ i+=((b & 0x80) >> 4);
+ i+=(((~b) & 0x40) >> 1);
+ i+=((b & 0x20) >> 1);
+ i+=((b & 0x10) >> 2);
+ i+=((b & 0x08) << 3);
+ i+=((b & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ case 0x11:
+ /* D */
+ i=b & 0x23;
+ i+=((b & 0xC0) >> 4);
+ i+=((b & 0x10) << 2);
+ i+=((b & 0x08) << 1);
+ i+=(((~b) & 0x04) << 5);
+ i &= 0xFF;
+ break;
+ }
+
+ return i;
+}
+
+/****************************************************************************/
+/* MB 971031 - Emulate no Sega G80 security chip */
+/****************************************************************************/
+static UINT8 sega_decrypt0(offs_t pc, UINT8 lo)
+{
+ return lo;
+}
+
+/****************************************************************************/
+/* MB 971025 - Set the security chip to be used */
+/****************************************************************************/
+void sega_security(int chip)
+{
+ switch (chip)
+ {
+ case 62:
+ sega_decrypt=sega_decrypt62;
+ break;
+ case 63:
+ sega_decrypt=sega_decrypt63;
+ break;
+ case 64:
+ sega_decrypt=sega_decrypt64;
+ break;
+ case 70:
+ sega_decrypt=sega_decrypt70;
+ break;
+ case 76:
+ sega_decrypt=sega_decrypt76;
+ break;
+ case 82:
+ sega_decrypt=sega_decrypt82;
+ break;
+ default:
+ sega_decrypt=sega_decrypt0;
+ break;
+ }
+}
+
+
diff --git a/src/mame/machine/segaic16.c b/src/mame/machine/segaic16.c
new file mode 100644
index 00000000000..fd04b35d4f3
--- /dev/null
+++ b/src/mame/machine/segaic16.c
@@ -0,0 +1,702 @@
+/***************************************************************************
+
+ Sega 16-bit common hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "segaic16.h"
+#include "video/resnet.h"
+
+extern void *fd1089_get_decrypted_base(void);
+extern void fd1094_machine_init(void);
+extern void *fd1094_get_decrypted_base(void);
+
+
+/*************************************
+ *
+ * Debugging
+ *
+ *************************************/
+
+#define LOG_MEMORY_MAP (1)
+#define LOG_MULTIPLY (0)
+#define LOG_DIVIDE (0)
+#define LOG_COMPARE (0)
+
+
+
+/*************************************
+ *
+ * Types
+ *
+ *************************************/
+
+struct memory_mapper_chip
+{
+ UINT8 regs[0x20];
+ int cpunum;
+ const struct segaic16_memory_map_entry *map;
+ void (*sound_w)(UINT8);
+ UINT8 (*sound_r)(void);
+};
+
+
+struct multiply_chip
+{
+ UINT16 regs[4];
+};
+
+
+struct divide_chip
+{
+ UINT16 regs[8];
+};
+
+
+struct compare_timer_chip
+{
+ UINT16 regs[16];
+ UINT16 counter;
+ UINT8 bit;
+ void (*sound_w)(UINT8);
+ void (*timer_ack)(void);
+};
+
+
+
+/*************************************
+ *
+ * Statics
+ *
+ *************************************/
+
+static struct memory_mapper_chip memory_mapper;
+static struct multiply_chip multiply[3];
+static struct divide_chip divide[3];
+static struct compare_timer_chip compare_timer[2];
+
+
+
+/*************************************
+ *
+ * Prototypes
+ *
+ *************************************/
+
+static void update_memory_mapping(struct memory_mapper_chip *chip);
+
+
+
+/*************************************
+ *
+ * Misc helpers
+ *
+ *************************************/
+
+READ16_HANDLER( segaic16_open_bus_r )
+{
+ static UINT8 recurse = 0;
+ UINT16 result;
+
+ /* Unmapped memory returns the last word on the data bus, which is almost always the opcode */
+ /* of the next instruction due to prefetch; however, since we may be encrypted, we actually */
+ /* need to return the encrypted opcode, not the last decrypted data. */
+
+ /* Believe it or not, this is actually important for Cotton, which has the following evil */
+ /* code: btst #0,$7038f7, which tests the low bit of an unmapped address, which thus should */
+ /* return the prefetched value. */
+
+ /* prevent recursion */
+ if (recurse)
+ return 0xffff;
+
+ /* read original encrypted memory at that address */
+ recurse = 1;
+ result = program_read_word_16be(activecpu_get_pc());
+ recurse = 0;
+ return result;
+}
+
+
+
+/*************************************
+ *
+ * Memory mapping chip
+ *
+ *************************************/
+
+void segaic16_memory_mapper_init(int cpunum, const struct segaic16_memory_map_entry *entrylist, void (*sound_w_callback)(UINT8), UINT8 (*sound_r_callback)(void))
+{
+ struct memory_mapper_chip *chip = &memory_mapper;
+
+ /* reset the chip structure */
+ memset(chip, 0, sizeof(*chip));
+ chip->cpunum = cpunum;
+ chip->map = entrylist;
+ chip->sound_w = sound_w_callback;
+ chip->sound_r = sound_r_callback;
+
+ /* create the initial regions */
+ segaic16_memory_mapper_reset();
+}
+
+
+void segaic16_memory_mapper_reset(void)
+{
+ struct memory_mapper_chip *chip = &memory_mapper;
+
+ /* zap to 0 and remap everything */
+ memset(chip->regs, 0, sizeof(chip->regs));
+ update_memory_mapping(chip);
+}
+
+
+void segaic16_memory_mapper_config(const UINT8 *map_data)
+{
+ struct memory_mapper_chip *chip = &memory_mapper;
+
+ /* zap to 0 and remap everything */
+ memcpy(&chip->regs[0x10], map_data, 0x10);
+ update_memory_mapping(chip);
+}
+
+
+void segaic16_memory_mapper_set_decrypted(UINT8 *decrypted)
+{
+ struct memory_mapper_chip *chip = &memory_mapper;
+ offs_t romsize = memory_region_length(REGION_CPU1 + chip->cpunum);
+ int rgnum;
+
+ /* loop over the regions */
+ for (rgnum = 0; chip->map[rgnum].regbase != 0; rgnum++)
+ {
+ static const offs_t region_size_map[4] = { 0x00ffff, 0x01ffff, 0x07ffff, 0x1fffff };
+ const struct segaic16_memory_map_entry *rgn = &chip->map[rgnum];
+ offs_t region_size = region_size_map[chip->regs[rgn->regbase] & 3];
+ offs_t region_base = (chip->regs[rgn->regbase + 1] << 16) & ~region_size;
+ offs_t region_start = region_base + (rgn->regoffs & region_size);
+ read16_handler read = rgn->read;
+ int banknum = 0;
+
+ /* skip non-ROM regions */
+ if (read == NULL || rgn->romoffset == ~0)
+ continue;
+
+ /* check for mapping to banks */
+ if ((FPTR)read >= STATIC_BANK1 && (FPTR)read <= STATIC_BANKMAX)
+ banknum = ((FPTR)read - STATIC_BANK1) + 1;
+
+ /* skip any mappings beyond the ROM size */
+ if (region_start >= romsize)
+ continue;
+
+ memory_configure_bank_decrypted(banknum, 0, 1, decrypted + region_start, 0);
+ memory_set_bank(banknum, 0);
+ }
+}
+
+
+static void memory_mapper_w(struct memory_mapper_chip *chip, offs_t offset, UINT8 data)
+{
+ UINT8 oldval;
+
+ /* wraps every 32 bytes */
+ offset &= 0x1f;
+
+ /* remember the previous value and swap in the new one */
+ oldval = chip->regs[offset];
+ chip->regs[offset] = data;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case 0x02:
+ /* misc commands */
+ /* 00 - resume execution after 03 */
+ /* 03 - maybe controls halt and reset lines together? */
+ if ((oldval ^ chip->regs[offset]) & 3)
+ {
+ cpunum_set_input_line(chip->cpunum, INPUT_LINE_RESET, (chip->regs[offset] & 3) == 3 ? ASSERT_LINE : CLEAR_LINE);
+ if ((chip->regs[offset] & 3) == 3)
+ fd1094_machine_init();
+ }
+ break;
+
+ case 0x03:
+ if (chip->sound_w)
+ (*chip->sound_w)(data);
+ break;
+
+ case 0x04:
+ /* controls IRQ lines to 68000, negative logic -- write $B to signal IRQ4 */
+ if ((chip->regs[offset] & 7) != 7)
+ cpunum_set_input_line(chip->cpunum, (~chip->regs[offset] & 7), HOLD_LINE);
+ break;
+
+ case 0x05:
+ /* read/write control */
+ /* 01 - write data latched in 00,01 to 2 * (address in 0A,0B,0C) */
+ /* 02 - read data into latches 00,01 from 2 * (address in 07,08,09) */
+ if (data == 0x01)
+ {
+ offs_t addr = (chip->regs[0x0a] << 17) | (chip->regs[0x0b] << 9) | (chip->regs[0x0c] << 1);
+ cpuintrf_push_context(chip->cpunum);
+ program_write_word_16be(addr, (chip->regs[0x00] << 8) | chip->regs[0x01]);
+ cpuintrf_pop_context();
+ }
+ else if (data == 0x02)
+ {
+ offs_t addr = (chip->regs[0x07] << 17) | (chip->regs[0x08] << 9) | (chip->regs[0x09] << 1);
+ UINT16 result;
+ cpuintrf_push_context(chip->cpunum);
+ result = program_read_word_16be(addr);
+ cpuintrf_pop_context();
+ chip->regs[0x00] = result >> 8;
+ chip->regs[0x01] = result;
+ }
+ break;
+
+ case 0x07: case 0x08: case 0x09:
+ /* writes here latch a 68000 address for writing */
+ break;
+
+ case 0x0a: case 0x0b: case 0x0c:
+ /* writes here latch a 68000 address for reading */
+ break;
+
+ case 0x10: case 0x11:
+ case 0x12: case 0x13:
+ case 0x14: case 0x15:
+ case 0x16: case 0x17:
+ case 0x18: case 0x19:
+ case 0x1a: case 0x1b:
+ case 0x1c: case 0x1d:
+ case 0x1e: case 0x1f:
+ if (oldval != data)
+ update_memory_mapping(chip);
+ break;
+
+ default:
+ logerror("Unknown memory_mapper_w to address %02X = %02X\n", offset, data);
+ break;
+ }
+}
+
+
+static UINT16 memory_mapper_r(struct memory_mapper_chip *chip, offs_t offset, UINT16 unmapped_val)
+{
+ /* wraps every 32 bytes */
+ offset &= 0x1f;
+
+ /* switch off the offset */
+ switch (offset)
+ {
+ case 0x00:
+ case 0x01:
+ /* data latches - return the values latched */
+ return chip->regs[offset];
+
+ case 0x02:
+ /* various input bits from the 68000 */
+ /* 01 - ???? */
+ /* 02 - ???? */
+ /* 04 - ???? */
+ /* 08 - ???? */
+ /* 40 - set if busy processing a read/write request */
+ /* Together, 01+02 == 00 if the 68000 is halted */
+ /* Together, 01+02+04+08 == 0F if the 68000 is executing */
+ return (chip->regs[0x02] & 3) == 3 ? 0x00 : 0x0f;
+
+ case 0x03:
+ /* this returns data that the sound CPU writes */
+ if (chip->sound_r)
+ return (*chip->sound_r)();
+ return 0xff;
+
+ default:
+ logerror("Unknown memory_mapper_r from address %02X\n", offset);
+ break;
+ }
+ return unmapped_val;
+}
+
+
+static void update_memory_mapping(struct memory_mapper_chip *chip)
+{
+ int rgnum;
+
+ if (LOG_MEMORY_MAP) mame_printf_debug("----\nRemapping:\n");
+
+ /* first reset everything back to the beginning */
+ memory_install_read16_handler (chip->cpunum, ADDRESS_SPACE_PROGRAM, 0x000000, 0xffffff, 0, 0, segaic16_memory_mapper_lsb_r);
+ memory_install_write16_handler(chip->cpunum, ADDRESS_SPACE_PROGRAM, 0x000000, 0xffffff, 0, 0, segaic16_memory_mapper_lsb_w);
+
+ /* loop over the regions */
+ for (rgnum = 0; chip->map[rgnum].regbase != 0; rgnum++)
+ {
+ static const offs_t region_size_map[4] = { 0x00ffff, 0x01ffff, 0x07ffff, 0x1fffff };
+ const struct segaic16_memory_map_entry *rgn = &chip->map[rgnum];
+ offs_t region_size = region_size_map[chip->regs[rgn->regbase] & 3];
+ offs_t region_base = (chip->regs[rgn->regbase + 1] << 16) & ~region_size;
+ offs_t region_mirror = rgn->mirror & region_size;
+ offs_t region_start = region_base + (rgn->regoffs & region_size);
+ offs_t region_end = region_start + ((rgn->length - 1 < region_size) ? rgn->length - 1 : region_size);
+ write16_handler write = rgn->write;
+ read16_handler read = rgn->read;
+ int banknum = 0;
+
+ /* check for mapping to banks */
+ if ((FPTR)read >= STATIC_BANK1 && (FPTR)read <= STATIC_BANKMAX)
+ banknum = ((FPTR)read - STATIC_BANK1) + 1;
+ if ((FPTR)write >= STATIC_BANK1 && (FPTR)write <= STATIC_BANKMAX)
+ banknum = ((FPTR)write - STATIC_BANK1) + 1;
+
+ /* ROM areas need extra clamping */
+ if (rgn->romoffset != ~0)
+ {
+ offs_t romsize = memory_region_length(REGION_CPU1 + chip->cpunum);
+ if (region_start >= romsize)
+ read = NULL;
+ else if (region_start + rgn->length > romsize)
+ region_end = romsize - 1;
+ }
+
+ /* map it */
+ if (read)
+ memory_install_read16_handler(chip->cpunum, ADDRESS_SPACE_PROGRAM, region_start, region_end, 0, region_mirror, read);
+ if (write)
+ memory_install_write16_handler(chip->cpunum, ADDRESS_SPACE_PROGRAM, region_start, region_end, 0, region_mirror, write);
+
+ /* set the bank pointer */
+ if (banknum && read)
+ {
+ if (rgn->base)
+ {
+ memory_configure_bank(banknum, 0, 1, *rgn->base, 0);
+ memory_set_bank(banknum, 0);
+ }
+ else if (rgn->romoffset != ~0)
+ {
+ UINT8 *decrypted;
+
+ decrypted = fd1094_get_decrypted_base();
+ if (!decrypted)
+ decrypted = fd1089_get_decrypted_base();
+
+ memory_configure_bank(banknum, 0, 1, memory_region(REGION_CPU1 + chip->cpunum) + region_start, 0);
+ if (decrypted)
+ memory_configure_bank_decrypted(banknum, 0, 1, decrypted ? (decrypted + region_start) : 0, 0);
+ memory_set_bank(banknum, 0);
+ }
+ }
+
+ if (LOG_MEMORY_MAP) mame_printf_debug(" %06X-%06X (%06X) = %s\n", region_start, region_end, region_mirror, rgn->name);
+ }
+}
+
+
+READ8_HANDLER( segaic16_memory_mapper_r )
+{
+ return memory_mapper_r(&memory_mapper, offset, 0xff);
+}
+
+
+WRITE8_HANDLER( segaic16_memory_mapper_w )
+{
+ memory_mapper_w(&memory_mapper, offset, data);
+}
+
+
+READ16_HANDLER( segaic16_memory_mapper_lsb_r )
+{
+ return memory_mapper_r(&memory_mapper, offset, segaic16_open_bus_r(0,0));
+}
+
+
+WRITE16_HANDLER( segaic16_memory_mapper_lsb_w )
+{
+ if (ACCESSING_LSB)
+ memory_mapper_w(&memory_mapper, offset, data & 0xff);
+}
+
+
+
+/*************************************
+ *
+ * Multiply chip
+ *
+ *************************************/
+
+static UINT16 multiply_r(int which, offs_t offset, UINT16 mem_mask)
+{
+ offset &= 3;
+ switch (offset)
+ {
+ case 0: return multiply[which].regs[0];
+ case 1: return multiply[which].regs[1];
+ case 2: return ((INT16)multiply[which].regs[0] * (INT16)multiply[which].regs[1]) >> 16;
+ case 3: return ((INT16)multiply[which].regs[0] * (INT16)multiply[which].regs[1]) & 0xffff;
+ }
+ return 0xffff;
+}
+
+
+static void multiply_w(int which, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ offset &= 3;
+ switch (offset)
+ {
+ case 0: COMBINE_DATA(&multiply[which].regs[0]); break;
+ case 1: COMBINE_DATA(&multiply[which].regs[1]); break;
+ case 2: COMBINE_DATA(&multiply[which].regs[0]); break;
+ case 3: COMBINE_DATA(&multiply[which].regs[1]); break;
+ }
+}
+
+
+READ16_HANDLER( segaic16_multiply_0_r ) { return multiply_r(0, offset, mem_mask); }
+READ16_HANDLER( segaic16_multiply_1_r ) { return multiply_r(1, offset, mem_mask); }
+READ16_HANDLER( segaic16_multiply_2_r ) { return multiply_r(2, offset, mem_mask); }
+WRITE16_HANDLER( segaic16_multiply_0_w ) { multiply_w(0, offset, data, mem_mask); }
+WRITE16_HANDLER( segaic16_multiply_1_w ) { multiply_w(1, offset, data, mem_mask); }
+WRITE16_HANDLER( segaic16_multiply_2_w ) { multiply_w(2, offset, data, mem_mask); }
+
+
+
+/*************************************
+ *
+ * Divide chip
+ *
+ *************************************/
+
+static void update_divide(int which, int mode)
+{
+ /* clear the flags by default */
+ divide[which].regs[6] = 0;
+
+ /* if mode 0, store quotient/remainder */
+ if (mode == 0)
+ {
+ INT32 dividend = (INT32)((divide[which].regs[0] << 16) | divide[which].regs[1]);
+ INT32 divisor = (INT16)divide[which].regs[2];
+ INT32 quotient, remainder;
+
+ /* perform signed divide */
+ if (divisor == 0)
+ {
+ quotient = dividend;//((INT32)(dividend ^ divisor) < 0) ? 0x8000 : 0x7fff;
+ divide[which].regs[6] |= 0x4000;
+ }
+ else
+ quotient = dividend / divisor;
+ remainder = dividend - quotient * divisor;
+
+ /* clamp to 16-bit signed */
+ if (quotient < -32768)
+ {
+ quotient = -32768;
+ divide[which].regs[6] |= 0x8000;
+ }
+ else if (quotient > 32767)
+ {
+ quotient = 32767;
+ divide[which].regs[6] |= 0x8000;
+ }
+
+ /* store quotient and remainder */
+ divide[which].regs[4] = quotient;
+ divide[which].regs[5] = remainder;
+ }
+
+ /* if mode 1, store 32-bit quotient */
+ else
+ {
+ UINT32 dividend = (UINT32)((divide[which].regs[0] << 16) | divide[which].regs[1]);
+ UINT32 divisor = (UINT16)divide[which].regs[2];
+ UINT32 quotient;
+
+ /* perform unsigned divide */
+ if (divisor == 0)
+ {
+ quotient = dividend;//0x7fffffff;
+ divide[which].regs[6] |= 0x4000;
+ }
+ else
+ quotient = dividend / divisor;
+
+ /* store 32-bit quotient */
+ divide[which].regs[4] = quotient >> 16;
+ divide[which].regs[5] = quotient & 0xffff;
+ }
+}
+
+static UINT16 divide_r(int which, offs_t offset, UINT16 mem_mask)
+{
+ /* 8 effective read registers */
+ offset &= 7;
+ switch (offset)
+ {
+ case 0: return divide[which].regs[0]; /* dividend high */
+ case 1: return divide[which].regs[1]; /* dividend low */
+ case 2: return divide[which].regs[2]; /* divisor */
+ case 4: return divide[which].regs[4]; /* quotient (mode 0) or quotient high (mode 1) */
+ case 5: return divide[which].regs[5]; /* remainder (mode 0) or quotient low (mode 1) */
+ case 6: return divide[which].regs[6]; /* flags */
+ }
+ return 0xffff;
+}
+
+
+static void divide_w(int which, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ int a4 = offset & 8;
+ int a3 = offset & 4;
+
+ if (LOG_DIVIDE) logerror("%06X:divide%d_w(%X) = %04X\n", activecpu_get_pc(), which, offset, data);
+
+ /* only 4 effective write registers */
+ offset &= 3;
+ switch (offset)
+ {
+ case 0: COMBINE_DATA(&divide[which].regs[0]); break; /* dividend high */
+ case 1: COMBINE_DATA(&divide[which].regs[1]); break; /* dividend low */
+ case 2: COMBINE_DATA(&divide[which].regs[2]); break; /* divisor/trigger */
+ case 3: break;
+ }
+
+ /* if a4 line is high, divide, using a3 as the mode */
+ if (a4) update_divide(which, a3);
+}
+
+
+READ16_HANDLER( segaic16_divide_0_r ) { return divide_r(0, offset, mem_mask); }
+READ16_HANDLER( segaic16_divide_1_r ) { return divide_r(1, offset, mem_mask); }
+READ16_HANDLER( segaic16_divide_2_r ) { return divide_r(2, offset, mem_mask); }
+WRITE16_HANDLER( segaic16_divide_0_w ) { divide_w(0, offset, data, mem_mask); }
+WRITE16_HANDLER( segaic16_divide_1_w ) { divide_w(1, offset, data, mem_mask); }
+WRITE16_HANDLER( segaic16_divide_2_w ) { divide_w(2, offset, data, mem_mask); }
+
+
+
+/*************************************
+ *
+ * Compare/timer chip
+ *
+ *************************************/
+
+void segaic16_compare_timer_init(int which, void (*sound_write_callback)(UINT8), void (*timer_ack_callback)(void))
+{
+ compare_timer[which].sound_w = sound_write_callback;
+ compare_timer[which].timer_ack = timer_ack_callback;
+ compare_timer[which].counter = 0;
+}
+
+
+int segaic16_compare_timer_clock(int which)
+{
+ int old_counter = compare_timer[which].counter;
+ int result = 0;
+
+ /* if we're enabled, clock the upcounter */
+ if (compare_timer[which].regs[10] & 1)
+ compare_timer[which].counter++;
+
+ /* regardless of the enable, a value of 0xfff will generate the IRQ */
+ if (old_counter == 0xfff)
+ {
+ result = 1;
+ compare_timer[which].counter = compare_timer[which].regs[8] & 0xfff;
+ }
+ return result;
+}
+
+
+static void update_compare(int which, int update_history)
+{
+ int bound1 = (INT16)compare_timer[which].regs[0];
+ int bound2 = (INT16)compare_timer[which].regs[1];
+ int value = (INT16)compare_timer[which].regs[2];
+ int min = (bound1 < bound2) ? bound1 : bound2;
+ int max = (bound1 > bound2) ? bound1 : bound2;
+
+ if (value < min)
+ {
+ compare_timer[which].regs[7] = min;
+ compare_timer[which].regs[3] = 0x8000;
+ }
+ else if (value > max)
+ {
+ compare_timer[which].regs[7] = max;
+ compare_timer[which].regs[3] = 0x4000;
+ }
+ else
+ {
+ compare_timer[which].regs[7] = value;
+ compare_timer[which].regs[3] = 0x0000;
+ }
+
+ if (update_history)
+ compare_timer[which].regs[4] |= (compare_timer[which].regs[3] == 0) << compare_timer[which].bit++;
+}
+
+
+static void timer_interrupt_ack(int which)
+{
+ if (compare_timer[which].timer_ack)
+ (*compare_timer[which].timer_ack)();
+}
+
+
+static UINT16 compare_timer_r(int which, offs_t offset, UINT16 mem_mask)
+{
+ offset &= 0xf;
+ if (LOG_COMPARE) logerror("%06X:compare%d_r(%X) = %04X\n", activecpu_get_pc(), which, offset, compare_timer[which].regs[offset]);
+ switch (offset)
+ {
+ case 0x0: return compare_timer[which].regs[0];
+ case 0x1: return compare_timer[which].regs[1];
+ case 0x2: return compare_timer[which].regs[2];
+ case 0x3: return compare_timer[which].regs[3];
+ case 0x4: return compare_timer[which].regs[4];
+ case 0x5: return compare_timer[which].regs[1];
+ case 0x6: return compare_timer[which].regs[2];
+ case 0x7: return compare_timer[which].regs[7];
+ case 0x9:
+ case 0xd: timer_interrupt_ack(which); break;
+ }
+ return 0xffff;
+}
+
+
+static void compare_timer_w(int which, offs_t offset, UINT16 data, UINT16 mem_mask)
+{
+ offset &= 0xf;
+ if (LOG_COMPARE) logerror("%06X:compare%d_w(%X) = %04X\n", activecpu_get_pc(), which, offset, data);
+ switch (offset)
+ {
+ case 0x0: COMBINE_DATA(&compare_timer[which].regs[0]); update_compare(which, 0); break;
+ case 0x1: COMBINE_DATA(&compare_timer[which].regs[1]); update_compare(which, 0); break;
+ case 0x2: COMBINE_DATA(&compare_timer[which].regs[2]); update_compare(which, 1); break;
+ case 0x4: compare_timer[which].regs[4] = 0; compare_timer[which].bit = 0; break;
+ case 0x6: COMBINE_DATA(&compare_timer[which].regs[2]); update_compare(which, 0); break;
+ case 0x8:
+ case 0xc: COMBINE_DATA(&compare_timer[which].regs[8]); break;
+ case 0x9:
+ case 0xd: timer_interrupt_ack(which); break;
+ case 0xa:
+ case 0xe: COMBINE_DATA(&compare_timer[which].regs[10]); break;
+ case 0xb:
+ case 0xf:
+ COMBINE_DATA(&compare_timer[which].regs[11]);
+ if (compare_timer[which].sound_w)
+ (*compare_timer[which].sound_w)(compare_timer[which].regs[11]);
+ break;
+ }
+}
+
+
+READ16_HANDLER( segaic16_compare_timer_0_r ) { return compare_timer_r(0, offset, mem_mask); }
+READ16_HANDLER( segaic16_compare_timer_1_r ) { return compare_timer_r(1, offset, mem_mask); }
+WRITE16_HANDLER( segaic16_compare_timer_0_w ) { compare_timer_w(0, offset, data, mem_mask); }
+WRITE16_HANDLER( segaic16_compare_timer_1_w ) { compare_timer_w(1, offset, data, mem_mask); }
diff --git a/src/mame/machine/segaic16.h b/src/mame/machine/segaic16.h
new file mode 100644
index 00000000000..26f98e7cdc0
--- /dev/null
+++ b/src/mame/machine/segaic16.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+
+ Sega 16-bit common hardware
+
+***************************************************************************/
+
+/* open bus read helpers */
+READ16_HANDLER( segaic16_open_bus_r );
+
+/* memory mapping chip */
+struct segaic16_memory_map_entry
+{
+ UINT8 regbase; /* register offset for this region */
+ offs_t regoffs; /* offset within the region for this entry */
+ offs_t length; /* length in bytes of this entry */
+ offs_t mirror; /* maximal mirror values (will be truncated) */
+ offs_t romoffset; /* offset within REGION_CPU0, or ~0 for independent entries */
+ read16_handler read; /* read handler */
+ write16_handler write; /* write handler */
+ UINT16 ** base; /* pointer to memory base */
+ const char * name; /* friendly name for debugging */
+};
+
+void segaic16_memory_mapper_init(int cpunum, const struct segaic16_memory_map_entry *entrylist, void (*sound_w_callback)(UINT8), UINT8 (*sound_r_callback)(void));
+void segaic16_memory_mapper_reset(void);
+void segaic16_memory_mapper_config(const UINT8 *map_data);
+void segaic16_memory_mapper_set_decrypted(UINT8 *decrypted);
+READ8_HANDLER( segaic16_memory_mapper_r );
+WRITE8_HANDLER( segaic16_memory_mapper_w );
+READ16_HANDLER( segaic16_memory_mapper_lsb_r );
+WRITE16_HANDLER( segaic16_memory_mapper_lsb_w );
+
+/* multiply chip */
+READ16_HANDLER( segaic16_multiply_0_r );
+READ16_HANDLER( segaic16_multiply_1_r );
+READ16_HANDLER( segaic16_multiply_2_r );
+WRITE16_HANDLER( segaic16_multiply_0_w );
+WRITE16_HANDLER( segaic16_multiply_1_w );
+WRITE16_HANDLER( segaic16_multiply_2_w );
+
+/* divide chip */
+READ16_HANDLER( segaic16_divide_0_r );
+READ16_HANDLER( segaic16_divide_1_r );
+READ16_HANDLER( segaic16_divide_2_r );
+WRITE16_HANDLER( segaic16_divide_0_w );
+WRITE16_HANDLER( segaic16_divide_1_w );
+WRITE16_HANDLER( segaic16_divide_2_w );
+
+/* compare/timer chip */
+void segaic16_compare_timer_init(int which, void (*sound_write_callback)(UINT8), void (*timer_ack_callback)(void));
+int segaic16_compare_timer_clock(int which);
+READ16_HANDLER( segaic16_compare_timer_0_r );
+READ16_HANDLER( segaic16_compare_timer_1_r );
+WRITE16_HANDLER( segaic16_compare_timer_0_w );
+WRITE16_HANDLER( segaic16_compare_timer_1_w );
+
diff --git a/src/mame/machine/segas32.c b/src/mame/machine/segas32.c
new file mode 100644
index 00000000000..0026d3beaac
--- /dev/null
+++ b/src/mame/machine/segas32.c
@@ -0,0 +1,400 @@
+/* Sega System 32 Protection related functions */
+
+#include "driver.h"
+#include "segas32.h"
+
+
+/******************************************************************************
+ ******************************************************************************
+ Golden Axe 2 (Revenge of Death Adder)
+ ******************************************************************************
+ ******************************************************************************/
+
+#define xxxx 0x00
+
+static const UINT8 ga2_v25_opcode_table[256] = {
+ xxxx,xxxx,0xEA,xxxx,xxxx,0x8B,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xFA,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x49,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,0xE8,xxxx,xxxx,0x75,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,0x8D,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xBF,xxxx,0x88,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xBC,
+ xxxx,xxxx,xxxx,0x8A,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xB8,0x26,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xEB,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xB2,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,0xC3,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xB9,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,
+ xxxx,xxxx,0x8E,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xBE,xxxx,xxxx,xxxx,xxxx
+};
+
+#undef xxxx
+
+static void nec_v25_cpu_decrypt(void)
+{
+ int i;
+ UINT8 *rom = memory_region(REGION_CPU3);
+ UINT8* decrypted = auto_malloc(0x100000);
+ UINT8* temp = malloc_or_die(0x100000);
+
+ // set CPU3 opcode base
+ memory_set_decrypted_region(2, 0x00000, 0xfffff, decrypted);
+
+ // make copy of ROM so original can be overwritten
+ memcpy(temp, rom, 0x10000);
+
+ for(i = 0; i < 0x10000; i++)
+ {
+ int j = BITSWAP16(i, 14, 11, 15, 12, 13, 4, 3, 7, 5, 10, 2, 8, 9, 6, 1, 0);
+
+ // normal ROM data with address swap undone
+ rom[i] = temp[j];
+
+ // decryped opcodes with address swap undone
+ decrypted[i] = ga2_v25_opcode_table[ temp[j] ];
+ }
+
+ memcpy(rom+0xf0000, rom, 0x10000);
+ memcpy(decrypted+0xf0000, decrypted, 0x10000);
+
+ free(temp);
+}
+
+void decrypt_ga2_protrom(void)
+{
+ nec_v25_cpu_decrypt();
+}
+
+
+WRITE16_HANDLER( ga2_dpram_w )
+{
+ /* does it ever actually write.. */
+}
+
+READ16_HANDLER( ga2_dpram_r )
+{
+ return (ga2_dpram[offset])|(ga2_dpram[offset+1]<<8);
+}
+
+
+#if 0 // simulation
+READ16_HANDLER(ga2_sprite_protection_r)
+{
+ static UINT32 prot[16] =
+ {
+ 0x0a, 0,
+ 0xc5, 0,
+ 0x11, 0,
+ 0x11, 0,
+ 0x18, 0,
+ 0x18, 0,
+ 0x1f, 0,
+ 0xc6, 0,
+ };
+
+ return prot[offset];
+}
+
+READ16_HANDLER(ga2_wakeup_protection_r)
+{
+ static const char *prot =
+ "wake up! GOLDEN AXE The Revenge of Death-Adder! ";
+ return prot[offset];
+}
+#endif
+
+/******************************************************************************
+ ******************************************************************************
+ Sonic Arcade protection
+ ******************************************************************************
+ ******************************************************************************/
+
+
+// This code duplicates the actions of the protection device used in SegaSonic
+// arcade revision C, allowing the game to run correctly.
+#define CLEARED_LEVELS 0xE5C4
+#define CURRENT_LEVEL 0xF06E
+#define CURRENT_LEVEL_STATUS 0xF0BC
+#define LEVEL_ORDER_ARRAY 0x263A
+
+WRITE16_HANDLER(sonic_level_load_protection)
+{
+ UINT16 level;
+//Perform write
+ system32_workram[CLEARED_LEVELS / 2] = (data & ~mem_mask) | (system32_workram[CLEARED_LEVELS / 2] & mem_mask);
+
+//Refresh current level
+ if (system32_workram[CLEARED_LEVELS / 2] == 0)
+ {
+ level = 0x0007;
+ }
+ else
+ {
+ level = *((memory_region(REGION_CPU1) + LEVEL_ORDER_ARRAY) + (system32_workram[CLEARED_LEVELS / 2] * 2) - 1);
+ level |= *((memory_region(REGION_CPU1) + LEVEL_ORDER_ARRAY) + (system32_workram[CLEARED_LEVELS / 2] * 2) - 2) << 8;
+ }
+ system32_workram[CURRENT_LEVEL / 2] = level;
+
+//Reset level status
+ system32_workram[CURRENT_LEVEL_STATUS / 2] = 0x0000;
+ system32_workram[(CURRENT_LEVEL_STATUS + 2) / 2] = 0x0000;
+}
+
+
+/******************************************************************************
+ ******************************************************************************
+ Burning Rival
+ ******************************************************************************
+ ******************************************************************************/
+
+
+// the protection board on many system32 games has full dma/bus access
+// and can write things into work RAM. we simulate that here for burning rival.
+READ16_HANDLER(brival_protection_r)
+{
+ if (!mem_mask) // only trap on word-wide reads
+ {
+ switch (offset)
+ {
+ case 0:
+ case 2:
+ case 3:
+ return 0;
+ break;
+ }
+ }
+
+ return system32_workram[0xba00/2 + offset];
+}
+
+WRITE16_HANDLER(brival_protection_w)
+{
+ static const int protAddress[6][2] =
+ {
+ { 0x109517, 0x00/2 },
+ { 0x109597, 0x10/2 },
+ { 0x109597, 0x20/2 },
+ { 0x109597, 0x30/2 },
+ { 0x109597, 0x40/2 },
+ { 0x109617, 0x50/2 },
+ };
+ char ret[32];
+ int curProtType;
+ UINT8 *ROM = memory_region(REGION_CPU1);
+
+ switch (offset)
+ {
+ case 0x800/2:
+ curProtType = 0;
+ break;
+ case 0x802/2:
+ curProtType = 1;
+ break;
+ case 0x804/2:
+ curProtType = 2;
+ break;
+ case 0x806/2:
+ curProtType = 3;
+ break;
+ case 0x808/2:
+ curProtType = 4;
+ break;
+ case 0x80a/2:
+ curProtType = 5;
+ break;
+ default:
+ if (offset >= 0xa00/2 && offset < 0xc00/2)
+ return;
+ logerror("brival_protection_w: UNKNOWN WRITE: offset %x value %x\n", offset, data);
+ return;
+ break;
+ }
+
+ memcpy(ret, &ROM[protAddress[curProtType][0]], 16);
+ ret[16] = '\0';
+
+ memcpy(&system32_protram[protAddress[curProtType][1]], ret, 16);
+}
+
+
+/******************************************************************************
+ ******************************************************************************
+ Dark Edge
+ ******************************************************************************
+ ******************************************************************************/
+
+void darkedge_fd1149_vblank(void)
+{
+ program_write_word(0x20f072, 0);
+ program_write_word(0x20f082, 0);
+
+ if( program_read_byte(0x20a12c) != 0 )
+ {
+ program_write_byte(0x20a12c, program_read_byte(0x20a12c)-1 );
+
+ if( program_read_byte(0x20a12c) == 0 )
+ program_write_byte(0x20a12e, 1);
+ }
+}
+
+
+WRITE16_HANDLER( darkedge_protection_w )
+{
+ logerror("%06x:darkedge_prot_w(%06X) = %04X & %04X\n",
+ activecpu_get_pc(), 0xa00000 + 2*offset, data, mem_mask ^ 0xffff);
+}
+
+
+READ16_HANDLER( darkedge_protection_r )
+{
+ logerror("%06x:darkedge_prot_r(%06X) & %04X\n",
+ activecpu_get_pc(), 0xa00000 + 2*offset, mem_mask ^ 0xffff);
+ return 0xffff;
+}
+
+
+
+/******************************************************************************
+ ******************************************************************************
+ DBZ VRVS
+ ******************************************************************************
+ ******************************************************************************/
+
+WRITE16_HANDLER( dbzvrvs_protection_w )
+{
+ program_write_word( 0x2080c8, program_read_word( 0x200044 ) );
+}
+
+
+READ16_HANDLER( dbzvrvs_protection_r )
+{
+ return 0xffff;
+}
+
+
+
+/******************************************************************************
+ ******************************************************************************
+ Arabian Fight
+ ******************************************************************************
+ ******************************************************************************/
+
+
+// protection ram is 8-bits wide and only occupies every other address
+READ16_HANDLER(arabfgt_protection_r)
+{
+ int PC = activecpu_get_pc();
+ int cmpVal;
+
+ if (PC == 0xfe0325 || PC == 0xfe01e5 || PC == 0xfe035e || PC == 0xfe03cc)
+ {
+ cmpVal = activecpu_get_reg(1);
+
+ // R0 always contains the value the protection is supposed to return (!)
+ return cmpVal;
+ }
+ else
+ {
+ popmessage("UNKONWN ARF PROTECTION READ PC=%x\n", PC);
+ }
+
+ return 0;
+}
+
+WRITE16_HANDLER(arabfgt_protection_w)
+{
+}
+
+READ16_HANDLER(arf_wakeup_protection_r)
+{
+ static const char *prot =
+ "wake up! ARF! ";
+ return prot[offset];
+}
+
+/******************************************************************************
+ ******************************************************************************
+ The J.League 1994 (Japan)
+ ******************************************************************************
+ ******************************************************************************/
+WRITE16_HANDLER( jleague_protection_w )
+ {
+ COMBINE_DATA( &system32_workram[0xf700/2 + offset ] );
+
+ switch( offset )
+ {
+ // Map team browser selection to opponent browser selection
+ // using same lookup table that V60 uses for sound sample mapping.
+ case 0:
+ program_write_byte( 0x20f708, program_read_word( 0x7bbc0 + data*2 ) );
+ break;
+
+ // move on to team browser
+ case 4/2:
+ program_write_byte( 0x200016, data & 0xff );
+ break;
+
+ default:
+ break;
+ }
+}
+
+/******************************************************************************
+ ******************************************************************************
+ Air Rescue
+ ******************************************************************************
+ ******************************************************************************/
+/*
+ protection
+ a00000 - a00002 dsp i/o
+ a00004 - dsp int/ack
+
+ dsp uses its p0/p1 for address select
+ dsp.sr = ???0 read a00000 into dsp.a
+ dsp.sr = ???1 read a00002 into dsp.b
+ dsp.sr = ???2 write dsp.b in a00000
+ dsp.sr = ???3 write dsp.a in a00002
+
+ Use of p0/p1 means there's no other way for dsp to communicate with V60, unless it shares RAM.
+ 99.99% of the dsp code is unused because the V60 ROM is hardcoded as part of a twin set,
+ maybe the standalone board was for dev only? nop the 3 bytes at 0x06023A for standalone. (centred intro text)
+*/
+static UINT16 arescue_dsp_io[6] = {0,0,0,0,0,0};
+
+READ16_HANDLER( arescue_dsp_r )
+{
+ if( offset == 4/2 )
+ {
+ switch( arescue_dsp_io[0] )
+ {
+ case 0:
+ case 1:
+ case 2:
+ break;
+
+ case 3:
+ arescue_dsp_io[0] = 0x8000;
+ arescue_dsp_io[2/2] = 0x0001;
+ break;
+
+ case 6:
+ arescue_dsp_io[0] = 4 * arescue_dsp_io[2/2];
+ break;
+
+ default:
+ logerror("Unhandled DSP cmd %04x (%04x).\n", arescue_dsp_io[0], arescue_dsp_io[1] );
+ break;
+ }
+ }
+
+ return arescue_dsp_io[offset];
+}
+
+WRITE16_HANDLER( arescue_dsp_w )
+{
+ COMBINE_DATA(&arescue_dsp_io[offset]);
+}
+
diff --git a/src/mame/machine/seibuspi.c b/src/mame/machine/seibuspi.c
new file mode 100644
index 00000000000..b9ad91b62ba
--- /dev/null
+++ b/src/mame/machine/seibuspi.c
@@ -0,0 +1,388 @@
+#include "driver.h"
+
+
+
+/**************************************************************************
+
+Tile encryption
+---------------
+
+The tile graphics encryption uses the same algorithm in all games, with
+different keys for the SPI, RISE10 and RISE11 custom chips.
+
+- Take 24 bits of gfx data (used to decrypt 4 pixels at 6 bpp) and perform
+ a bit permutation on them (the permutation is the same in all games).
+- Take the low 12 bits of the tile code and add a 24-bit number (KEY1) to it.
+- Add the two 24-bit numbers resulting from the above steps, but with a
+ catch: while performing the sum, some bits generate carry as usual, other
+ bits don't, depending on a 24-bit key (KEY2). Note that the carry generated
+ by bit 23 (if enabled) wraps around to bit 0.
+- XOR the result with a 24-bit number (KEY3).
+
+The decryption is actually programmable; the games write the key to the
+custom IC on startup!! (writes to 000414)
+
+**************************************************************************/
+
+// add two numbers generating carry from one bit to the next only if
+// the corresponding bit in carry_mask is 1
+static int partial_carry_sum(int add1,int add2,int carry_mask,int bits)
+{
+ int i,res,carry;
+
+ res = 0;
+ carry = 0;
+ for (i = 0;i < bits;i++)
+ {
+ int bit = BIT(add1,i) + BIT(add2,i) + carry;
+
+ res += (bit & 1) << i;
+
+ // generate carry only if the corresponding bit in carry_mask is 1
+ if (BIT(carry_mask,i))
+ carry = bit >> 1;
+ else
+ carry = 0;
+ }
+
+ // wrap around carry from top bit to bit 0
+ if (carry)
+ res ^=1;
+
+ return res;
+}
+
+static int partial_carry_sum24(int add1,int add2,int carry_mask)
+{
+ return partial_carry_sum(add1,add2,carry_mask,24);
+}
+
+static int partial_carry_sum16(int add1,int add2,int carry_mask)
+{
+ return partial_carry_sum(add1,add2,carry_mask,16);
+}
+
+static int partial_carry_sum8(int add1,int add2,int carry_mask)
+{
+ return partial_carry_sum(add1,add2,carry_mask,8);
+}
+
+
+
+static UINT32 decrypt_tile(UINT32 val, int tileno, UINT32 key1, UINT32 key2, UINT32 key3)
+{
+ val = BITSWAP24(val, 18,19,9,5, 10,17,16,20, 21,22,6,11, 15,14,4,23, 0,1,7,8, 13,12,3,2);
+
+ return partial_carry_sum24( val, tileno + key1, key2 ) ^ key3;
+}
+
+static void decrypt_text(UINT8 *rom, UINT32 key1, UINT32 key2, UINT32 key3)
+{
+ int i;
+ for(i=0; i<0x10000; i++)
+ {
+ UINT32 w;
+
+ w = (rom[(i*3) + 0] << 16) | (rom[(i*3) + 1] << 8) | (rom[(i*3) +2]);
+
+ w = decrypt_tile(w, i >> 4, key1, key2, key3);
+
+ rom[(i*3) + 0] = (w >> 16) & 0xff;
+ rom[(i*3) + 1] = (w >> 8) & 0xff;
+ rom[(i*3) + 2] = w & 0xff;
+ }
+}
+
+static void decrypt_bg(UINT8 *rom, int size, UINT32 key1, UINT32 key2, UINT32 key3)
+{
+ int i,j;
+ for(j=0; j<size; j+=0xc0000)
+ {
+ for(i=0; i<0x40000; i++)
+ {
+ UINT32 w;
+
+ w = (rom[j + (i*3) + 0] << 16) | (rom[j + (i*3) + 1] << 8) | (rom[j + (i*3) + 2]);
+
+ w = decrypt_tile(w, i >> 6, key1, key2, key3);
+
+ rom[j + (i*3) + 0] = (w >> 16) & 0xff;
+ rom[j + (i*3) + 1] = (w >> 8) & 0xff;
+ rom[j + (i*3) + 2] = w & 0xff;
+ }
+ }
+}
+
+/******************************************************************************************
+cpu #0 (PC=0033B2EB): unmapped program memory dword write to 00000414 = 00000000 & 0000FFFF
+cpu #0 (PC=0033B2EB): unmapped program memory dword write to 00000414 = 0000DF5B & 0000FFFF
+cpu #0 (PC=0033B2EB): unmapped program memory dword write to 00000414 = 000078CF & 0000FFFF
+cpu #0 (PC=0033B2EB): unmapped program memory dword write to 00000414 = 00001377 & 0000FFFF
+cpu #0 (PC=0033B2EB): unmapped program memory dword write to 00000414 = 00002538 & 0000FFFF
+cpu #0 (PC=0033B2EB): unmapped program memory dword write to 00000414 = 00004535 & 0000FFFF
+cpu #0 (PC=0033B2EB): unmapped program memory dword write to 00000414 = 06DC0000 & FFFF0000
+******************************************************************************************/
+
+void seibuspi_text_decrypt(UINT8 *rom)
+{
+ decrypt_text( rom, 0x5a3845, 0x77cf5b, 0x1378df);
+}
+
+void seibuspi_bg_decrypt(UINT8 *rom, int size)
+{
+ decrypt_bg( rom, size, 0x5a3845, 0x77cf5b, 0x1378df);
+}
+
+/******************************************************************************************
+cpu #0 (PC=002A097D): unmapped program memory dword write to 00000414 = 00000001 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 00000414 = 0000DCF8 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 00000414 = 00007AE2 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 00000414 = 0000154D & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 00000414 = 00001731 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 00000414 = 0000466B & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 00000414 = 3EDC0000 & FFFF0000
+******************************************************************************************/
+
+/* RISE10 (Raiden Fighters 2) */
+void seibuspi_rise10_text_decrypt(UINT8 *rom)
+{
+ decrypt_text( rom, 0x823146, 0x4de2f8, 0x157adc);
+}
+
+void seibuspi_rise10_bg_decrypt(UINT8 *rom, int size)
+{
+ decrypt_bg( rom, size, 0x823146, 0x4de2f8, 0x157adc);
+}
+
+/******************************************************************************************
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 00000414 = 00000001 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 00000414 = 00006630 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 00000414 = 0000B685 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 00000414 = 0000CCFE & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 00000414 = 000032A7 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 00000414 = 0000547C & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 00000414 = 3EDC0000 & FFFF0000
+******************************************************************************************/
+
+/* RISE11 (Raiden Fighters Jet) */
+void seibuspi_rise11_text_decrypt(UINT8 *rom)
+{
+ decrypt_text( rom, 0xaea754, 0xfe8530, 0xccb666);
+}
+
+void seibuspi_rise11_bg_decrypt(UINT8 *rom, int size)
+{
+ decrypt_bg( rom, size, 0xaea754, 0xfe8530, 0xccb666);
+}
+
+
+
+
+
+
+
+
+static int dec12(int val)
+{
+ return partial_carry_sum16( val, 0x018a, 0x018a ) ^ 0xccd8;
+}
+
+static int dec3(int val)
+{
+ return partial_carry_sum8( val, 0x05, 0x1d ) ^ 0x6c;
+}
+
+static int dec4(int val)
+{
+ return partial_carry_sum8( val, 0x42, 0x46 ) ^ 0xa2;
+}
+
+static int dec5(int val)
+{
+ return partial_carry_sum8( val, 0x21, 0x27 ) ^ 0x52;
+}
+
+static int dec6(int val)
+{
+ return partial_carry_sum8( val, 0x08, 0x08 ) ^ 0x3a;
+}
+
+
+static void sprite_reorder(UINT8 *buffer)
+{
+ int j;
+ UINT8 temp[64];
+ for( j=0; j < 16; j++ ) {
+ temp[2*(j*2)+0] = buffer[2*j+0];
+ temp[2*(j*2)+1] = buffer[2*j+1];
+ temp[2*(j*2)+2] = buffer[2*j+32];
+ temp[2*(j*2)+3] = buffer[2*j+33];
+ }
+ memcpy(buffer, temp, 64);
+}
+
+/* actually this is for the 2000 version - original version might be different */
+void seibuspi_rise10_sprite_decrypt(UINT8 *rom, int size)
+{
+ int i,j;
+ int s = size/2;
+
+ for( i=0; i < s; i+=32 ) {
+ sprite_reorder(&rom[2*i]);
+ sprite_reorder(&rom[2*(s+i)]);
+ sprite_reorder(&rom[2*((s*2)+i)]);
+ for( j=0; j < 32; j++ ) {
+ int b1,b2;
+ int d12,d3,d4,d5,d6;
+
+ b1 = rom[2*((s*2)+i+j)] + (rom[2*((s*2)+i+j)+1] << 8) + (rom[2*(s+i+j)] << 16) + (rom[2*(s+i+j)+1] << 24);
+ b1 = BITSWAP32(b1,
+ 7,31,26,0,18,9,19,8,
+ 27,6,15,21,1,28,10,20,
+ 3,5,29,17,14,22,2,11,
+ 23,13,24,4,16,12,25,30);
+ b2 = rom[2*(i+j)] + (rom[2*(i+j)+1] << 8);
+
+ d12 = dec12(b2);
+ d3 = dec3((b1 >> 0) & 0xff);
+ d4 = dec4((b1 >> 8) & 0xff);
+ d5 = dec5((b1 >> 16) & 0xff);
+ d6 = dec6((b1 >> 24) & 0xff);
+
+ rom[2*(i+j)] = d12 >> 8;
+ rom[2*(i+j)+1] = d12;
+ rom[2*(s+i+j)] = d3;
+ rom[2*(s+i+j)+1] = d4;
+ rom[2*((s*2)+i+j)] = d5;
+ rom[2*((s*2)+i+j)+1] = d6;
+ }
+ }
+}
+
+
+
+
+/******************************************************************************************
+
+rf2_eur (we don't have the gfx ROMs for this one)
+
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 00000000 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 0000ABCB & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 0000ABCB & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 00006543 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 000021D9 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 00006655 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 000099AA & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 00006655 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 000099AA & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 00000C1D & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 0000A346 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 00005237 & 0000FFFF
+cpu #0 (PC=002A097D): unmapped program memory dword write to 0000054C = 0000A948 & 0000FFFF
+
+ plane543 = partial_carry_sum24( plane543, 0x??????, 0x??2199 ) ^ 0x??d9aa;
+ plane210 = partial_carry_sum24( plane210, i, 0x990c52 ) ^ 0xaa1d37;
+
+rfjet
+
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 00000000 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 00000000 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 000055AB & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 00000000 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 0000AA6A & 0000FFFF //
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 0000ABCB & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 0000DD4C & 0000FFFF //
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 00006543 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 0000D68B & 0000FFFF //
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 000037F2 & 0000FFFF //
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 000021D9 & 0000FFFF
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 00005B3B & 0000FFFF //
+cpu #0 (PC=002C40F9): unmapped program memory dword write to 0000054C = 00000300 & 0000FFFF
+
+ plane543 = partial_carry_sum24( plane543, 0x01cb64, 0x01aadd ) ^ 0x016a4c;
+ plane210 = partial_carry_sum24( plane210, i, 0xd6375b ) ^ 0x8bf23b;
+
+******************************************************************************************/
+
+
+void seibuspi_rise11_sprite_decrypt(UINT8 *rom, int size)
+{
+ int i;
+
+ for (i = 0; i < size/2; i++)
+ {
+ int b1,b2,b3;
+ int plane543,plane210;
+
+ b1 = rom[0*size+2*i] + (rom[0*size+2*i+1] << 8);
+ b2 = rom[1*size+2*i] + (rom[1*size+2*i+1] << 8);
+ b3 = rom[2*size+2*i] + (rom[2*size+2*i+1] << 8);
+
+ plane543 = (BIT(b2,11)<< 0) |
+ (BIT(b1, 6)<< 1) |
+ (BIT(b3,12)<< 2) |
+ (BIT(b3, 3)<< 3) |
+ (BIT(b2,12)<< 4) |
+ (BIT(b3,14)<< 5) |
+ (BIT(b3, 4)<< 6) |
+ (BIT(b1,11)<< 7) |
+ (BIT(b1,12)<< 8) |
+ (BIT(b1, 2)<< 9) |
+ (BIT(b2, 5)<<10) |
+ (BIT(b1, 9)<<11) |
+ (BIT(b3, 1)<<12) |
+ (BIT(b2, 2)<<13) |
+ (BIT(b2,10)<<14) |
+ (BIT(b3, 5)<<15) |
+ (BIT(b1, 3)<<16) |
+ (BIT(b2, 7)<<17) |
+ (BIT(b1,15)<<18) |
+ (BIT(b3, 9)<<19) |
+ (BIT(b2,13)<<20) |
+ (BIT(b1, 4)<<21) |
+ (BIT(b3, 2)<<22) |
+ (BIT(b2, 0)<<23);
+
+ plane210 = (BIT(b1,14)<< 0) |
+ (BIT(b1, 1)<< 1) |
+ (BIT(b1,13)<< 2) |
+ (BIT(b3, 0)<< 3) |
+ (BIT(b1, 7)<< 4) |
+ (BIT(b2,14)<< 5) |
+ (BIT(b2, 4)<< 6) |
+ (BIT(b2, 9)<< 7) |
+ (BIT(b3, 8)<< 8) |
+ (BIT(b2, 1)<< 9) |
+ (BIT(b3, 7)<<10) |
+ (BIT(b2, 6)<<11) |
+ (BIT(b1, 0)<<12) |
+ (BIT(b3,11)<<13) |
+ (BIT(b2, 8)<<14) |
+ (BIT(b3,13)<<15) |
+ (BIT(b1, 8)<<16) |
+ (BIT(b3,10)<<17) |
+ (BIT(b3, 6)<<18) |
+ (BIT(b1,10)<<19) |
+ (BIT(b2,15)<<20) |
+ (BIT(b2, 3)<<21) |
+ (BIT(b1, 5)<<22) |
+ (BIT(b3,15)<<23);
+
+ plane543 = partial_carry_sum24( plane543, 0x01cb64, 0x01aadd ) ^ 0x016a4c;
+ plane210 = partial_carry_sum24( plane210, i, 0xd6375b ) ^ 0x8bf23b;
+
+ rom[0*size+2*i] = plane543 >> 16;
+ rom[0*size+2*i+1] = plane543 >> 8;
+ rom[1*size+2*i] = plane543 >> 0;
+ rom[1*size+2*i+1] = plane210 >> 16;
+ rom[2*size+2*i] = plane210 >> 8;
+ rom[2*size+2*i+1] = plane210 >> 0;
+ }
+
+ for (i = 0; i < size/2; i += 32)
+ {
+ sprite_reorder(&rom[0*size+2*i]);
+ sprite_reorder(&rom[1*size+2*i]);
+ sprite_reorder(&rom[2*size+2*i]);
+ }
+}
diff --git a/src/mame/machine/simpsons.c b/src/mame/machine/simpsons.c
new file mode 100644
index 00000000000..1556b2359cf
--- /dev/null
+++ b/src/mame/machine/simpsons.c
@@ -0,0 +1,146 @@
+#include "driver.h"
+#include "video/konamiic.h"
+#include "cpu/konami/konami.h"
+#include "machine/eeprom.h"
+#include "sound/k053260.h"
+
+/* from video */
+extern void simpsons_video_banking( int select );
+extern UINT8 *simpsons_xtraram;
+
+int simpsons_firq_enabled;
+
+/***************************************************************************
+
+ EEPROM
+
+***************************************************************************/
+
+static int init_eeprom_count;
+
+
+static struct EEPROM_interface eeprom_interface =
+{
+ 7, /* address bits */
+ 8, /* data bits */
+ "011000", /* read command */
+ "011100", /* write command */
+ 0, /* erase command */
+ "0100000000000",/* lock command */
+ "0100110000000" /* unlock command */
+};
+
+NVRAM_HANDLER( simpsons )
+{
+ if (read_or_write)
+ EEPROM_save(file);
+ else
+ {
+ EEPROM_init(&eeprom_interface);
+
+ if (file)
+ {
+ init_eeprom_count = 0;
+ EEPROM_load(file);
+ }
+ else
+ init_eeprom_count = 10;
+ }
+}
+
+READ8_HANDLER( simpsons_eeprom_r )
+{
+ int res;
+
+ res = (EEPROM_read_bit() << 4);
+
+ res |= 0x20;//konami_eeprom_ack() << 5; /* add the ack */
+
+ res |= readinputport( 5 ) & 1; /* test switch */
+
+ if (init_eeprom_count)
+ {
+ init_eeprom_count--;
+ res &= 0xfe;
+ }
+ return res;
+}
+
+WRITE8_HANDLER( simpsons_eeprom_w )
+{
+ if ( data == 0xff )
+ return;
+
+ EEPROM_write_bit(data & 0x80);
+ EEPROM_set_cs_line((data & 0x08) ? CLEAR_LINE : ASSERT_LINE);
+ EEPROM_set_clock_line((data & 0x10) ? ASSERT_LINE : CLEAR_LINE);
+
+ simpsons_video_banking( data & 3 );
+
+ simpsons_firq_enabled = data & 0x04;
+}
+
+/***************************************************************************
+
+ Coin Counters, Sound Interface
+
+***************************************************************************/
+
+WRITE8_HANDLER( simpsons_coin_counter_w )
+{
+ /* bit 0,1 coin counters */
+ coin_counter_w(0,data & 0x01);
+ coin_counter_w(1,data & 0x02);
+ /* bit 2 selects mono or stereo sound */
+ /* bit 3 = enable char ROM reading through the video RAM */
+ K052109_set_RMRD_line((data & 0x08) ? ASSERT_LINE : CLEAR_LINE);
+ /* bit 4 = INIT (unknown) */
+ /* bit 5 = enable sprite ROM reading */
+ K053246_set_OBJCHA_line((~data & 0x20) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+READ8_HANDLER( simpsons_sound_interrupt_r )
+{
+ cpunum_set_input_line_and_vector( 1, 0, HOLD_LINE, 0xff );
+ return 0x00;
+}
+
+READ8_HANDLER( simpsons_sound_r )
+{
+ return K053260_0_r(2 + offset);
+}
+
+
+/***************************************************************************
+
+ Banking, initialization
+
+***************************************************************************/
+
+static void simpsons_banking( int lines )
+{
+ memory_set_bank(1, lines & 0x3f);
+}
+
+MACHINE_RESET( simpsons )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ cpunum_set_info_fct(0, CPUINFO_PTR_KONAMI_SETLINES_CALLBACK, (genf *)simpsons_banking);
+
+ paletteram = &RAM[0x88000];
+ simpsons_xtraram = &RAM[0x89000];
+ spriteram16 = (UINT16 *)&RAM[0x8a000];
+
+ simpsons_firq_enabled = 0;
+
+ /* init the default banks */
+ memory_configure_bank(1, 0, 64, memory_region(REGION_CPU1) + 0x10000, 0x2000);
+ memory_set_bank(1, 0);
+
+ memory_configure_bank(2, 0, 2, memory_region(REGION_CPU2) + 0x10000, 0);
+ memory_configure_bank(2, 2, 6, memory_region(REGION_CPU2) + 0x10000, 0x4000);
+ memory_set_bank(2, 0);
+
+ simpsons_video_banking( 0 );
+}
diff --git a/src/mame/machine/slapfght.c b/src/mame/machine/slapfght.c
new file mode 100644
index 00000000000..1b0e35ebe51
--- /dev/null
+++ b/src/mame/machine/slapfght.c
@@ -0,0 +1,251 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+
+UINT8 *slapfight_dpram;
+size_t slapfight_dpram_size;
+
+static int slapfight_status;
+static int getstar_sequence_index;
+static int getstar_sh_intenabled;
+
+static int slapfight_status_state;
+extern UINT8 *getstar_e803;
+
+static UINT8 mcu_val;
+
+/* Perform basic machine initialisation */
+MACHINE_RESET( slapfight )
+{
+ /* MAIN CPU */
+
+ slapfight_status_state=0;
+ slapfight_status = 0xc7;
+
+ getstar_sequence_index = 0;
+ getstar_sh_intenabled = 0; /* disable sound cpu interrupts */
+
+ /* SOUND CPU */
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ASSERT_LINE);
+
+ /* MCU */
+ mcu_val = 0;
+}
+
+/* Interrupt handlers cpu & sound */
+
+WRITE8_HANDLER( slapfight_dpram_w )
+{
+ slapfight_dpram[offset]=data;
+}
+
+READ8_HANDLER( slapfight_dpram_r )
+{
+ return slapfight_dpram[offset];
+}
+
+
+
+/* Slapfight CPU input/output ports
+
+ These ports seem to control memory access
+
+*/
+
+/* Reset and hold sound CPU */
+WRITE8_HANDLER( slapfight_port_00_w )
+{
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ASSERT_LINE);
+ getstar_sh_intenabled = 0;
+}
+
+/* Release reset on sound CPU */
+WRITE8_HANDLER( slapfight_port_01_w )
+{
+ cpunum_set_input_line(1, INPUT_LINE_RESET, CLEAR_LINE);
+}
+
+/* Disable and clear hardware interrupt */
+WRITE8_HANDLER( slapfight_port_06_w )
+{
+ interrupt_enable_w(0,0);
+}
+
+/* Enable hardware interrupt */
+WRITE8_HANDLER( slapfight_port_07_w )
+{
+ interrupt_enable_w(0,1);
+}
+
+WRITE8_HANDLER( slapfight_port_08_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ memory_set_bankptr(1,&RAM[0x10000]);
+}
+
+WRITE8_HANDLER( slapfight_port_09_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ memory_set_bankptr(1,&RAM[0x14000]);
+}
+
+
+/* Status register */
+READ8_HANDLER( slapfight_port_00_r )
+{
+ static const int states[3]={ 0xc7, 0x55, 0x00 };
+
+ slapfight_status = states[slapfight_status_state];
+
+ slapfight_status_state++;
+ if (slapfight_status_state > 2) slapfight_status_state = 0;
+
+ return slapfight_status;
+}
+
+
+
+/*
+ Reads at e803 expect a sequence of values such that:
+ - first value is different from successive
+ - third value is (first+5)^0x56
+ I don't know what writes to this address do (connected to port 0 reads?).
+*/
+READ8_HANDLER( getstar_e803_r )
+{
+ static const UINT8 seq[] = { 0, 1, ((0+5)^0x56) };
+UINT8 val;
+
+ val = seq[getstar_sequence_index];
+ getstar_sequence_index = (getstar_sequence_index+1)%3;
+ return val;
+}
+
+/* Enable hardware interrupt of sound cpu */
+WRITE8_HANDLER( getstar_sh_intenable_w )
+{
+ getstar_sh_intenabled = 1;
+ logerror("cpu #1 PC=%d: %d written to a0e0\n",activecpu_get_pc(),data);
+}
+
+
+
+/* Generate interrups only if they have been enabled */
+INTERRUPT_GEN( getstar_interrupt )
+{
+ if (getstar_sh_intenabled)
+ cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+#ifdef UNUSED_FUNCTION
+WRITE8_HANDLER( getstar_port_04_w )
+{
+// cpu_halt(0,0);
+}
+#endif
+
+
+/* Tiger Heli MCU */
+
+static UINT8 from_main,from_mcu;
+static int mcu_sent = 0,main_sent = 0;
+static UINT8 portA_in,portA_out,ddrA;
+static UINT8 portB_in,portB_out,ddrB;
+static UINT8 portC_in,portC_out,ddrC;
+
+READ8_HANDLER( tigerh_68705_portA_r )
+{
+ return (portA_out & ddrA) | (portA_in & ~ddrA);
+}
+
+WRITE8_HANDLER( tigerh_68705_portA_w )
+{
+ portA_out = data;//?
+ from_mcu = portA_out;
+ mcu_sent = 1;
+}
+
+WRITE8_HANDLER( tigerh_68705_ddrA_w )
+{
+ ddrA = data;
+}
+
+READ8_HANDLER( tigerh_68705_portB_r )
+{
+ return (portB_out & ddrB) | (portB_in & ~ddrB);
+}
+
+WRITE8_HANDLER( tigerh_68705_portB_w )
+{
+
+ if ((ddrB & 0x02) && (~data & 0x02) && (portB_out & 0x02))
+ {
+ portA_in = from_main;
+ if (main_sent) cpunum_set_input_line(2,0,CLEAR_LINE);
+ main_sent = 0;
+ }
+ if ((ddrB & 0x04) && (data & 0x04) && (~portB_out & 0x04))
+ {
+ from_mcu = portA_out;
+ mcu_sent = 1;
+ }
+
+ portB_out = data;
+}
+
+WRITE8_HANDLER( tigerh_68705_ddrB_w )
+{
+ ddrB = data;
+}
+
+
+READ8_HANDLER( tigerh_68705_portC_r )
+{
+ portC_in = 0;
+ if (!main_sent) portC_in |= 0x01;
+ if (mcu_sent) portC_in |= 0x02;
+ return (portC_out & ddrC) | (portC_in & ~ddrC);
+}
+
+WRITE8_HANDLER( tigerh_68705_portC_w )
+{
+ portC_out = data;
+}
+
+WRITE8_HANDLER( tigerh_68705_ddrC_w )
+{
+ ddrC = data;
+}
+
+WRITE8_HANDLER( tigerh_mcu_w )
+{
+ from_main = data;
+ main_sent = 1;
+ mcu_sent=0;
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+}
+
+READ8_HANDLER( tigerh_mcu_r )
+{
+ mcu_sent = 0;
+ return from_mcu;
+}
+
+READ8_HANDLER( tigerh_mcu_status_r )
+{
+ int res = 0;
+ if (!main_sent) res |= 0x02;
+ if (!mcu_sent) res |= 0x04;
+ return res;
+}
+
diff --git a/src/mame/machine/slapstic.c b/src/mame/machine/slapstic.c
new file mode 100644
index 00000000000..189b23d50a0
--- /dev/null
+++ b/src/mame/machine/slapstic.c
@@ -0,0 +1,1174 @@
+/*************************************************************************
+
+ Atari Slapstic decoding helper
+
+**************************************************************************
+
+ Atari Slapstic FAQ
+ Version 1.12
+ by Aaron Giles and Frank Palazzolo
+ 9/12/2002
+
+
+ What is a slapstic?
+
+ The slapstic was a security chip made by Atari, which was used for
+ bank switching and security in several coin-operated video games from
+ 1984 through 1990.
+
+
+ What is a SLOOP?
+
+ The SLOOP (or "SLOOPstic") is a follow-on chip to the slapstic. It
+ provides a similar type of security, but is programmed onto a GAL6001,
+ rather than a custom part. It was created because Atari was running
+ out of slapstics to use in their games, and the original masks for the
+ slapstic had been lost by the company that manufactured them. A separate
+ FAQ for this chip is planned for the future.
+
+
+ How do I identify a slapstic chip on my board?
+
+ Look for a small, socketed 20-pin DIP on the board. The number on
+ the chip will be 137412-1xx.
+
+
+ Are slapstic chips interchangeable?
+
+ Sadly, no. They were designed to prevent operators from burning
+ new EPROMs and "upgrading" their PCBs to a new game without buying
+ the necessary kits from Atari. For example, the five System 1 games
+ each used a different slapstic, so that you couldn't take, say,
+ a <b>Marble Madness</b> machine, burn new EPROMs, and convert it into
+ an <b>Indiana Jones</b>.
+
+ That said, however, there are two pairs of the slapstics that appear
+ to be functionally identical, despite the fact that they have
+ different part numbers:
+
+ 137412-103 (<b>Marble Madness</b>) appears to be functionally identical
+ to 137412-110 (<b>Road Blasters</b> & <b>APB</b>)
+
+ 137412-106 (<b>Gauntlet II</b>) appears to be functionally identical
+ to 137412-109 (<b>Championship Sprint</b>)
+
+ Note, however, that I have not tried these swaps to confirm that they
+ work. Your mileage may vary.
+
+
+ How many different slapstics are there?
+
+ All told, a total of 13 actual slapstics have been found. However,
+ there are gaps in the numbering which indicate that more may exist.
+
+
+ Do all slapstics work the same?
+
+ In general, yes. However, matters are complicated by the existence
+ of multiple revisions of the chip design:
+
+ SLAPSTIC Part #137412-101 through 137412-110
+ SLAPSTIC-2 Part #137412-111 through 137412-118
+
+ In the simplest case, both revs act the same. However, they differ
+ in how the more complex modes of operation are used.
+
+
+ How is the slapstic connected to the game?
+
+ The slapstic generally sits between the CPU's address bus and one
+ of the program ROMs. Here's a pinout:
+
+ A9 1 +-v-+ 20 A8
+ A10 2 | | 19 A7
+ A11 3 | | 18 A6
+ A12 4 | | 17 A5
+ A13 5 | | 16 A4
+ /CS 6 | | 15 A3
+ CLK 7 | | 14 A2
+ VCC 8 | | 13 A1
+ BS1 9 | | 12 A0
+ BS0 10 +---+ 11 GND
+
+ A0-A13 are the address lines from the CPU. CLK and /CS together
+ trigger a state change. BS0 and BS1 are the bank select outputs,
+ which usually connect to the protected program ROM in place of
+ two address lines (traditionally A12 and A13).
+
+ Most slapstics were used on 68000 or T-11 based games, which had
+ a 16-bit address bus. This meant that A0-A13 on the slapstic were
+ generally connected to A1-A14 on the CPU. However, two 8-bit
+ games (Tetris and Empire Strikes Back) used the slapstic as well.
+ This slapstic (#101) has a slightly different pinout, though it
+ operates similarly to the others in its class.
+
+ A8 1 +-v-+ 20 A7
+ A9 2 | | 19 A6
+ A10 3 | | 18 A5
+ A11 4 | | 17 A4
+ A12 5 | | 16 A3
+ /CS 6 | | 15 A2
+ CLK 7 | | 14 A1
+ VCC 8 | | 13 A0
+ /BS1 9 | | 12 GND
+ BS1 10 +---+ 11 BS0
+
+
+ Which games used slapstics?
+
+ 137412-101 Empire Strikes Back
+ 137412-101 Tetris
+ 137412-103 Marble Madness
+ 137412-104 Gauntlet
+ 137412-105 Paperboy
+ 137412-105 Indiana Jones & the Temple of Doom
+ 137412-106 Gauntlet II
+ 137412-107 2-Player Gauntlet
+ 137412-107 Peter Packrat
+ 137412-107 720 Degrees
+ 137412-107 Xybots
+ 137412-108 Road Runner
+ 137412-108 Super Sprint
+ 137412-109 Championship Sprint
+ 137412-109 Road Blasters (some versions)
+ 137412-110 Road Blasters
+ 137412-110 APB
+ 137412-111 Pit Fighter
+ 137412-112 Pit Fighter (Europe)
+ 137412-113 Unknown (Europe)
+ 137412-115 Race Drivin' DSK board
+ 137412-116 Hydra
+ 137412-116 Tournament Cyberball 2072
+ 137412-117 Race Drivin' main board
+ 137412-118 Rampart
+ 137412-118 Vindicators Part II
+
+
+ How does the slapstic work?
+
+ On power-up, the slapstic starts by pointing to bank 0 or bank 3.
+ After that, certain sequences of addresses will trigger a bankswitch.
+ Each sequence begins with an access to location $0000, followed by one
+ or more special addresses.
+
+ Each slapstic has a 'simple' mode of bankswitching, consisting of an
+ access to $0000 followed by an access to one of four bank addresses.
+ Other accesses are allowed in between these two accesses without
+ affecting the outcome.
+
+ Additionally, each slapstic has a trickier variant of the
+ bankswitching, which requires an access to $0000, followed by accesses
+ to two specific addresses, followed by one of four alternate bank
+ addresses. All three accesses following the $0000 must occur in
+ sequence with no interruptions, or else the sequence is invalidated.
+
+ Finally, each slapstic has a mechanism for modifying the value of the
+ current bank. Earlier chips (101-110) allowed you to twiddle the
+ specific bits of the bank number, clearing or setting bits 0 and 1
+ independently. Later chips (111-118) provided a mechanism of adding
+ 1, 2, or 3 to the number of the current bank.
+
+ Surprisingly, the slapstic appears to have used DRAM cells to store
+ the current bank. After 5 or 6 seconds without a clock, the chip
+ reverts to the default bank, with the chip reset (bank select
+ addresses are enabled). Typically, the slapstic region is accessed
+ often enough to cause a problem.
+
+ For full details, see the MAME source code.
+
+*************************************************************************/
+
+#include "driver.h"
+#include "slapstic.h"
+#include "cpu/m68000/m68000.h"
+
+
+/*************************************
+ *
+ * Structure of slapstic params
+ *
+ *************************************/
+
+struct mask_value
+{
+ int mask, value;
+};
+
+
+struct slapstic_data
+{
+ int bankstart;
+ int bank[4];
+
+ struct mask_value alt1;
+ struct mask_value alt2;
+ struct mask_value alt3;
+ struct mask_value alt4;
+ int altshift;
+
+ struct mask_value bit1;
+ struct mask_value bit2c0;
+ struct mask_value bit2s0;
+ struct mask_value bit2c1;
+ struct mask_value bit2s1;
+ struct mask_value bit3;
+
+ struct mask_value add1;
+ struct mask_value add2;
+ struct mask_value addplus1;
+ struct mask_value addplus2;
+ struct mask_value add3;
+};
+
+
+
+/*************************************
+ *
+ * Shorthand
+ *
+ *************************************/
+
+#define UNKNOWN 0xffff
+#define NO_BITWISE \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }
+#define NO_ADDITIVE \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }, \
+ { UNKNOWN,UNKNOWN }
+
+#define MATCHES_MASK_VALUE(val, maskval) (((val) & (maskval).mask) == (maskval).value)
+
+
+/*************************************
+ *
+ * Constants
+ *
+ *************************************/
+
+enum state_type
+{
+ DISABLED,
+ ENABLED,
+ ALTERNATE1,
+ ALTERNATE2,
+ ALTERNATE3,
+ BITWISE1,
+ BITWISE2,
+ BITWISE3,
+ ADDITIVE1,
+ ADDITIVE2,
+ ADDITIVE3
+};
+
+#define LOG_SLAPSTIC 0
+
+
+
+/*************************************
+ *
+ * Slapstic definitions
+ *
+ *************************************/
+
+/* slapstic 137412-101: Empire Strikes Back/Tetris (NOT confirmed) */
+static struct slapstic_data slapstic101 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0080,0x0090,0x00a0,0x00b0 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,UNKNOWN }, /* 1st mask/value in sequence */
+ { 0x1fff,0x1dfe }, /* 2nd mask/value in sequence */
+ { 0x1ffc,0x1b5c }, /* 3rd mask/value in sequence */
+ { 0x1fcf,0x0080 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x1ff0,0x1540 }, /* 1st mask/value in sequence */
+ { 0x1ff3,0x1540 }, /* clear bit 0 value */
+ { 0x1ff3,0x1541 }, /* set bit 0 value */
+ { 0x1ff3,0x1542 }, /* clear bit 1 value */
+ { 0x1ff3,0x1543 }, /* set bit 1 value */
+ { 0x1ff8,0x1550 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-103: Marble Madness (confirmed) */
+static struct slapstic_data slapstic103 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0040,0x0050,0x0060,0x0070 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x002d }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3d14 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x3d24 }, /* 3rd mask/value in sequence */
+ { 0x3fcf,0x0040 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x34c0 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x34c0 }, /* clear bit 0 value */
+ { 0x3ff3,0x34c1 }, /* set bit 0 value */
+ { 0x3ff3,0x34c2 }, /* clear bit 1 value */
+ { 0x3ff3,0x34c3 }, /* set bit 1 value */
+ { 0x3ff8,0x34d0 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-104: Gauntlet (confirmed) */
+static struct slapstic_data slapstic104 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0020,0x0028,0x0030,0x0038 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x0069 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3735 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x3764 }, /* 3rd mask/value in sequence */
+ { 0x3fe7,0x0020 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x3d90 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x3d90 }, /* clear bit 0 value */
+ { 0x3ff3,0x3d91 }, /* set bit 0 value */
+ { 0x3ff3,0x3d92 }, /* clear bit 1 value */
+ { 0x3ff3,0x3d93 }, /* set bit 1 value */
+ { 0x3ff8,0x3da0 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-105: Indiana Jones/Paperboy (confirmed) */
+static struct slapstic_data slapstic105 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0010,0x0014,0x0018,0x001c },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x003d }, /* 1st mask/value in sequence */
+ { 0x3fff,0x0092 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x00a4 }, /* 3rd mask/value in sequence */
+ { 0x3ff3,0x0010 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x35b0 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x35b0 }, /* clear bit 0 value */
+ { 0x3ff3,0x35b1 }, /* set bit 0 value */
+ { 0x3ff3,0x35b2 }, /* clear bit 1 value */
+ { 0x3ff3,0x35b3 }, /* set bit 1 value */
+ { 0x3ff8,0x35c0 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-106: Gauntlet II (confirmed) */
+static struct slapstic_data slapstic106 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0008,0x000a,0x000c,0x000e },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x002b }, /* 1st mask/value in sequence */
+ { 0x3fff,0x0052 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x0064 }, /* 3rd mask/value in sequence */
+ { 0x3ff9,0x0008 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x3da0 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x3da0 }, /* clear bit 0 value */
+ { 0x3ff3,0x3da1 }, /* set bit 0 value */
+ { 0x3ff3,0x3da2 }, /* clear bit 1 value */
+ { 0x3ff3,0x3da3 }, /* set bit 1 value */
+ { 0x3ff8,0x3db0 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-107: Peter Packrat/Xybots/2p Gauntlet/720 (confirmed) */
+static struct slapstic_data slapstic107 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0018,0x001a,0x001c,0x001e },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x006b }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3d52 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x3d64 }, /* 3rd mask/value in sequence */
+ { 0x3ff9,0x0018 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x00a0 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x00a0 }, /* clear bit 0 value */
+ { 0x3ff3,0x00a1 }, /* set bit 0 value */
+ { 0x3ff3,0x00a2 }, /* clear bit 1 value */
+ { 0x3ff3,0x00a3 }, /* set bit 1 value */
+ { 0x3ff8,0x00b0 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-108: Road Runner/Super Sprint (confirmed) */
+static struct slapstic_data slapstic108 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0028,0x002a,0x002c,0x002e },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x001f }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3772 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x3764 }, /* 3rd mask/value in sequence */
+ { 0x3ff9,0x0028 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x0060 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x0060 }, /* clear bit 0 value */
+ { 0x3ff3,0x0061 }, /* set bit 0 value */
+ { 0x3ff3,0x0062 }, /* clear bit 1 value */
+ { 0x3ff3,0x0063 }, /* set bit 1 value */
+ { 0x3ff8,0x0070 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-109: Championship Sprint/Road Blasters (confirmed) */
+static struct slapstic_data slapstic109 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0008,0x000a,0x000c,0x000e },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x002b }, /* 1st mask/value in sequence */
+ { 0x3fff,0x0052 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x0064 }, /* 3rd mask/value in sequence */
+ { 0x3ff9,0x0008 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x3da0 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x3da0 }, /* clear bit 0 value */
+ { 0x3ff3,0x3da1 }, /* set bit 0 value */
+ { 0x3ff3,0x3da2 }, /* clear bit 1 value */
+ { 0x3ff3,0x3da3 }, /* set bit 1 value */
+ { 0x3ff8,0x3db0 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+/* slapstic 137412-110: Road Blasters/APB (confirmed) */
+static struct slapstic_data slapstic110 =
+{
+ /* basic banking */
+ 3, /* starting bank */
+ { 0x0040,0x0050,0x0060,0x0070 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x002d }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3d14 }, /* 2nd mask/value in sequence */
+ { 0x3ffc,0x3d24 }, /* 3rd mask/value in sequence */
+ { 0x3fcf,0x0040 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ { 0x3ff0,0x34c0 }, /* 1st mask/value in sequence */
+ { 0x3ff3,0x34c0 }, /* clear bit 0 value */
+ { 0x3ff3,0x34c1 }, /* set bit 0 value */
+ { 0x3ff3,0x34c2 }, /* clear bit 1 value */
+ { 0x3ff3,0x34c3 }, /* set bit 1 value */
+ { 0x3ff8,0x34d0 }, /* final mask/value in sequence */
+
+ /* additive banking */
+ NO_ADDITIVE
+};
+
+
+
+/*************************************
+ *
+ * Slapstic-2 definitions
+ *
+ *************************************/
+
+/* slapstic 137412-111: Pit Fighter (confirmed) */
+static struct slapstic_data slapstic111 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x0042,0x0052,0x0062,0x0072 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x000a }, /* 1st mask/value in sequence */
+ { 0x3fff,0x28a4 }, /* 2nd mask/value in sequence */
+ { 0x0784,0x0080 }, /* 3rd mask/value in sequence */
+ { 0x3fcf,0x0042 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x00a1 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x00a2 }, /* 2nd mask/value in sequence */
+ { 0x3c4f,0x284d }, /* +1 mask/value */
+ { 0x3a5f,0x285d }, /* +2 mask/value */
+ { 0x3ff8,0x2800 } /* final mask/value in sequence */
+};
+
+
+/* slapstic 137412-112: Pit Fighter (Japan) (confirmed) */
+static struct slapstic_data slapstic112 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x002c,0x003c,0x006c,0x007c },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x0014 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x29a0 }, /* 2nd mask/value in sequence */
+ { 0x0073,0x0010 }, /* 3rd mask/value in sequence */
+ { 0x3faf,0x002c }, /* 4th mask/value in sequence */
+ 2, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x2dce }, /* 1st mask/value in sequence */
+ { 0x3fff,0x2dcf }, /* 2nd mask/value in sequence */
+ { 0x3def,0x15e2 }, /* +1 mask/value */
+ { 0x3fbf,0x15a2 }, /* +2 mask/value */
+ { 0x3ffc,0x1450 } /* final mask/value in sequence */
+};
+
+
+/* slapstic 137412-113: Unknown (Europe) (confirmed) */
+static struct slapstic_data slapstic113 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x0008,0x0018,0x0028,0x0038 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x0059 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x11a5 }, /* 2nd mask/value in sequence */
+ { 0x0860,0x0800 }, /* 3rd mask/value in sequence */
+ { 0x3fcf,0x0008 }, /* 4th mask/value in sequence */
+ 3, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x049b }, /* 1st mask/value in sequence */
+ { 0x3fff,0x049c }, /* 2nd mask/value in sequence */
+ { 0x3fcf,0x3ec7 }, /* +1 mask/value */
+ { 0x3edf,0x3ed7 }, /* +2 mask/value */
+ { 0x3fff,0x3fb2 } /* final mask/value in sequence */
+};
+
+
+/* slapstic 137412-114: Unknown (Europe) (unconfirmed) */
+static struct slapstic_data slapstic114 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x0040,0x0048,0x0050,0x0058 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x0016 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x24de }, /* 2nd mask/value in sequence */
+ { 0x3871,0x0000 }, /* 3rd mask/value in sequence */
+ { 0x3fe7,0x0040 }, /* 4th mask/value in sequence */
+ 1, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x0ab7 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x0ab8 }, /* 2nd mask/value in sequence */
+ { 0x3f63,0x0d40 }, /* +1 mask/value */
+ { 0x3fd9,0x0dc8 }, /* +2 mask/value */
+ { 0x3fff,0x0ab0 } /* final mask/value in sequence */
+};
+
+
+/* slapstic 137412-115: Race Drivin' DSK board (confirmed) */
+static struct slapstic_data slapstic115 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x0020,0x0022,0x0024,0x0026 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x0054 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3e01 }, /* 2nd mask/value in sequence */
+ { 0x3879,0x0029 }, /* 3rd mask/value in sequence */
+ { 0x3ff9,0x0020 }, /* 4th mask/value in sequence */
+ 1, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x2591 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x2592 }, /* 2nd mask/value in sequence */
+ { 0x3fe6,0x3402 }, /* +1 mask/value */
+ { 0x3fb4,0x3410 }, /* +2 mask/value */
+ { 0x3fff,0x34a2 } /* final mask/value in sequence */
+};
+
+
+/* slapstic 137412-116: Hydra (confirmed) */
+static struct slapstic_data slapstic116 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x0044,0x004c,0x0054,0x005c },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x0069 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x2bab }, /* 2nd mask/value in sequence */
+ { 0x387c,0x0808 }, /* 3rd mask/value in sequence */
+ { 0x3fe7,0x0044 }, /* 4th mask/value in sequence */
+ 0, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x3f7c }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3f7d }, /* 2nd mask/value in sequence */
+ { 0x3db2,0x3c12 }, /* +1 mask/value */
+ { 0x3fe3,0x3e43 }, /* +2 mask/value */
+ { 0x3fff,0x2ba8 } /* final mask/value in sequence */
+};
+
+
+/* slapstic 137412-117: Race Drivin' main board (confirmed) */
+static struct slapstic_data slapstic117 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x0008,0x001a,0x002c,0x003e },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x007d }, /* 1st mask/value in sequence */
+ { 0x3fff,0x3580 }, /* 2nd mask/value in sequence */
+ { 0x0079,0x0020 }, /* 3rd mask/value in sequence */
+ { 0x3fc9,0x0008 }, /* 4th mask/value in sequence */
+ 1, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x0676 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x0677 }, /* 2nd mask/value in sequence */
+ { 0x3e62,0x1a42 }, /* +1 mask/value */
+ { 0x3e35,0x1a11 }, /* +2 mask/value */
+ { 0x3fff,0x1a42 } /* final mask/value in sequence */
+};
+
+
+/* slapstic 137412-118: Rampart/Vindicators II (confirmed) */
+static struct slapstic_data slapstic118 =
+{
+ /* basic banking */
+ 0, /* starting bank */
+ { 0x0014,0x0034,0x0054,0x0074 },/* bank select values */
+
+ /* alternate banking */
+ { 0x007f,0x0002 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x1950 }, /* 2nd mask/value in sequence */
+ { 0x0067,0x0020 }, /* 3rd mask/value in sequence */
+ { 0x3f9f,0x0014 }, /* 4th mask/value in sequence */
+ 3, /* shift to get bank from 3rd */
+
+ /* bitwise banking */
+ NO_BITWISE,
+
+ /* additive banking */
+ { 0x3fff,0x1958 }, /* 1st mask/value in sequence */
+ { 0x3fff,0x1959 }, /* 2nd mask/value in sequence */
+ { 0x3f73,0x3052 }, /* +1 mask/value */
+ { 0x3f67,0x3042 }, /* +2 mask/value */
+ { 0x3ff8,0x30e0 } /* final mask/value in sequence */
+};
+
+
+
+/*************************************
+ *
+ * Master slapstic table
+ *
+ *************************************/
+
+/* master table */
+static struct slapstic_data *slapstic_table[] =
+{
+ &slapstic101, /* NOT confirmed! */
+ NULL, /* never seen */
+ &slapstic103,
+ &slapstic104,
+ &slapstic105,
+ &slapstic106,
+ &slapstic107,
+ &slapstic108,
+ &slapstic109,
+ &slapstic110,
+ &slapstic111,
+ &slapstic112,
+ &slapstic113,
+ &slapstic114,
+ &slapstic115,
+ &slapstic116,
+ &slapstic117,
+ &slapstic118
+};
+
+
+
+/*************************************
+ *
+ * Statics
+ *
+ *************************************/
+
+static enum state_type state;
+static INT8 current_bank;
+static int access_68k;
+
+static INT8 alt_bank;
+static INT8 bit_bank;
+static INT8 add_bank;
+static UINT8 bit_xor;
+
+static struct slapstic_data slapstic;
+
+
+#if LOG_SLAPSTIC
+ static void slapstic_log(offs_t offset);
+ static FILE *slapsticlog;
+#else
+ #define slapstic_log(o)
+#endif
+
+
+
+/*************************************
+ *
+ * Initialization
+ *
+ *************************************/
+
+void slapstic_init(int chip)
+{
+ /* only a small number of chips are known to exist */
+ if (chip < 101 || chip > 118)
+ return;
+
+ /* set up the parameters */
+ if (!slapstic_table[chip - 101])
+ return;
+ slapstic = *slapstic_table[chip - 101];
+
+ /* reset the chip */
+ slapstic_reset();
+
+ /* see if we're 68k or 6502/6809 based */
+ access_68k = (Machine->drv->cpu[0].type != CPU_M6809 &&
+ Machine->drv->cpu[0].type != CPU_M6502);
+}
+
+
+void slapstic_reset(void)
+{
+ /* reset the chip */
+ state = DISABLED;
+
+ /* the 111 and later chips seem to reset to bank 0 */
+ current_bank = slapstic.bankstart;
+}
+
+
+
+/*************************************
+ *
+ * Returns active bank without tweaking
+ *
+ *************************************/
+
+int slapstic_bank(void)
+{
+ return current_bank;
+}
+
+
+
+/*************************************
+ *
+ * Kludge to catch alt seqeuences
+ *
+ *************************************/
+
+static int alt2_kludge(offs_t offset)
+{
+ /* 68k case is fairly complex: we need to look for special triplets */
+ if (access_68k)
+ {
+ UINT32 pc = activecpu_get_previouspc();
+
+ /* first verify that the prefetched PC matches the first alternate */
+ if (MATCHES_MASK_VALUE((pc + 2) >> 1, slapstic.alt1))
+ {
+ /* now look for a move.w (An),(An) or cmpm.w (An)+,(An)+ */
+ UINT16 opcode = cpu_readop16(pc & 0xffffff);
+ if ((opcode & 0xf1f8) == 0x3090 || (opcode & 0xf1f8) == 0xb148)
+ {
+ /* fetch the value of the register for the second operand, and see */
+ /* if it matches the third alternate */
+ UINT32 regval = activecpu_get_reg(M68K_A0 + ((opcode >> 9) & 7)) >> 1;
+ if (MATCHES_MASK_VALUE(regval, slapstic.alt3))
+ {
+ alt_bank = (regval >> slapstic.altshift) & 3;
+ return ALTERNATE3;
+ }
+ }
+ }
+
+ /* if there's no second memory hit within this instruction, the next */
+ /* opcode fetch will botch the operation, so just fall back to */
+ /* the enabled state */
+ return ENABLED;
+ }
+
+ /* kludge for ESB */
+ return ALTERNATE2;
+}
+
+
+
+/*************************************
+ *
+ * Call this *after* every access
+ *
+ *************************************/
+
+int slapstic_tweak(offs_t offset)
+{
+ /* reset is universal */
+ if (offset == 0x0000)
+ {
+ state = ENABLED;
+ }
+
+ /* otherwise, use the state machine */
+ else
+ {
+ switch (state)
+ {
+ /* DISABLED state: everything is ignored except a reset */
+ case DISABLED:
+ break;
+
+ /* ENABLED state: the chip has been activated and is ready for a bankswitch */
+ case ENABLED:
+
+ /* check for request to enter bitwise state */
+ if (MATCHES_MASK_VALUE(offset, slapstic.bit1))
+ {
+ state = BITWISE1;
+ }
+
+ /* check for request to enter additive state */
+ else if (MATCHES_MASK_VALUE(offset, slapstic.add1))
+ {
+ state = ADDITIVE1;
+ }
+
+ /* check for request to enter alternate state */
+ else if (MATCHES_MASK_VALUE(offset, slapstic.alt1))
+ {
+ state = ALTERNATE1;
+ }
+
+ /* special kludge for catching the second alternate address if */
+ /* the first one was missed (since it's usually an opcode fetch) */
+ else if (MATCHES_MASK_VALUE(offset, slapstic.alt2))
+ {
+ state = alt2_kludge(offset);
+ }
+
+ /* check for standard bankswitches */
+ else if (offset == slapstic.bank[0])
+ {
+ state = DISABLED;
+ current_bank = 0;
+ }
+ else if (offset == slapstic.bank[1])
+ {
+ state = DISABLED;
+ current_bank = 1;
+ }
+ else if (offset == slapstic.bank[2])
+ {
+ state = DISABLED;
+ current_bank = 2;
+ }
+ else if (offset == slapstic.bank[3])
+ {
+ state = DISABLED;
+ current_bank = 3;
+ }
+ break;
+
+ /* ALTERNATE1 state: look for alternate2 offset, or else fall back to ENABLED */
+ case ALTERNATE1:
+ if (MATCHES_MASK_VALUE(offset, slapstic.alt2))
+ {
+ state = ALTERNATE2;
+ }
+ else
+ {
+ state = ENABLED;
+ }
+ break;
+
+ /* ALTERNATE2 state: look for altbank offset, or else fall back to ENABLED */
+ case ALTERNATE2:
+ if (MATCHES_MASK_VALUE(offset, slapstic.alt3))
+ {
+ state = ALTERNATE3;
+ alt_bank = (offset >> slapstic.altshift) & 3;
+ }
+ else
+ {
+ state = ENABLED;
+ }
+ break;
+
+ /* ALTERNATE3 state: wait for the final value to finish the transaction */
+ case ALTERNATE3:
+ if (MATCHES_MASK_VALUE(offset, slapstic.alt4))
+ {
+ state = DISABLED;
+ current_bank = alt_bank;
+ }
+ break;
+
+ /* BITWISE1 state: waiting for a bank to enter the BITWISE state */
+ case BITWISE1:
+ if (offset == slapstic.bank[0] || offset == slapstic.bank[1] ||
+ offset == slapstic.bank[2] || offset == slapstic.bank[3])
+ {
+ state = BITWISE2;
+ bit_bank = current_bank;
+ bit_xor = 0;
+ }
+ break;
+
+ /* BITWISE2 state: watch for twiddling and the escape mechanism */
+ case BITWISE2:
+
+ /* check for clear bit 0 case */
+ if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2c0))
+ {
+ bit_bank &= ~1;
+ bit_xor ^= 3;
+ }
+
+ /* check for set bit 0 case */
+ else if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2s0))
+ {
+ bit_bank |= 1;
+ bit_xor ^= 3;
+ }
+
+ /* check for clear bit 1 case */
+ else if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2c1))
+ {
+ bit_bank &= ~2;
+ bit_xor ^= 3;
+ }
+
+ /* check for set bit 1 case */
+ else if (MATCHES_MASK_VALUE(offset ^ bit_xor, slapstic.bit2s1))
+ {
+ bit_bank |= 2;
+ bit_xor ^= 3;
+ }
+
+ /* check for escape case */
+ else if (MATCHES_MASK_VALUE(offset, slapstic.bit3))
+ {
+ state = BITWISE3;
+ }
+ break;
+
+ /* BITWISE3 state: waiting for a bank to seal the deal */
+ case BITWISE3:
+ if (offset == slapstic.bank[0] || offset == slapstic.bank[1] ||
+ offset == slapstic.bank[2] || offset == slapstic.bank[3])
+ {
+ state = DISABLED;
+ current_bank = bit_bank;
+ }
+ break;
+
+ /* ADDITIVE1 state: look for add2 offset, or else fall back to ENABLED */
+ case ADDITIVE1:
+ if (MATCHES_MASK_VALUE(offset, slapstic.add2))
+ {
+ state = ADDITIVE2;
+ add_bank = current_bank;
+ }
+ else
+ {
+ state = ENABLED;
+ }
+ break;
+
+ /* ADDITIVE2 state: watch for twiddling and the escape mechanism */
+ case ADDITIVE2:
+
+ /* check for add 1 case -- can intermix */
+ if (MATCHES_MASK_VALUE(offset, slapstic.addplus1))
+ {
+ add_bank = (add_bank + 1) & 3;
+ }
+
+ /* check for add 2 case -- can intermix */
+ if (MATCHES_MASK_VALUE(offset, slapstic.addplus2))
+ {
+ add_bank = (add_bank + 2) & 3;
+ }
+
+ /* check for escape case -- can intermix with the above */
+ if (MATCHES_MASK_VALUE(offset, slapstic.add3))
+ {
+ state = ADDITIVE3;
+ }
+ break;
+
+ /* ADDITIVE3 state: waiting for a bank to seal the deal */
+ case ADDITIVE3:
+ if (offset == slapstic.bank[0] || offset == slapstic.bank[1] ||
+ offset == slapstic.bank[2] || offset == slapstic.bank[3])
+ {
+ state = DISABLED;
+ current_bank = add_bank;
+ }
+ break;
+ }
+ }
+
+ /* log this access */
+ slapstic_log(offset);
+
+ /* return the active bank */
+ return current_bank;
+}
+
+
+
+/*************************************
+ *
+ * Debugging
+ *
+ *************************************/
+
+#if LOG_SLAPSTIC
+static void slapstic_log(offs_t offset)
+{
+ static attotime last_time;
+
+ if (!slapsticlog)
+ slapsticlog = fopen("slapstic.log", "w");
+ if (slapsticlog)
+ {
+ attotime time = timer_get_time();
+
+ if (attotime_compare(attotime_sub(time, last_time), ATTOTIME_IN_SEC(1)) > 0)
+ fprintf(slapsticlog, "------------------------------------\n");
+ last_time = time;
+
+ fprintf(slapsticlog, "%06X: %04X B=%d ", activecpu_get_previouspc(), offset, current_bank);
+ switch (state)
+ {
+ case DISABLED:
+ fprintf(slapsticlog, "DISABLED\n");
+ break;
+ case ENABLED:
+ fprintf(slapsticlog, "ENABLED\n");
+ break;
+ case ALTERNATE1:
+ fprintf(slapsticlog, "ALTERNATE1\n");
+ break;
+ case ALTERNATE2:
+ fprintf(slapsticlog, "ALTERNATE2\n");
+ break;
+ case ALTERNATE3:
+ fprintf(slapsticlog, "ALTERNATE3\n");
+ break;
+ case BITWISE1:
+ fprintf(slapsticlog, "BITWISE1\n");
+ break;
+ case BITWISE2:
+ fprintf(slapsticlog, "BITWISE2\n");
+ break;
+ case BITWISE3:
+ fprintf(slapsticlog, "BITWISE3\n");
+ break;
+ case ADDITIVE1:
+ fprintf(slapsticlog, "ADDITIVE1\n");
+ break;
+ case ADDITIVE2:
+ fprintf(slapsticlog, "ADDITIVE2\n");
+ break;
+ case ADDITIVE3:
+ fprintf(slapsticlog, "ADDITIVE3\n");
+ break;
+ }
+ fflush(slapsticlog);
+ }
+}
+#endif
diff --git a/src/mame/machine/slikshot.c b/src/mame/machine/slikshot.c
new file mode 100644
index 00000000000..58cd6da6a0a
--- /dev/null
+++ b/src/mame/machine/slikshot.c
@@ -0,0 +1,697 @@
+/***************************************************************************
+
+ Slick Shot input handling
+
+ Unlike the other 8-bit Strata games, Slick Shot has an interesting
+ and fairly complex input system. The actual cabinet has a good-sized
+ gap underneath the monitor, from which a small pool table emerges.
+ An actual cue ball and pool sticks were included with the game.
+
+ To "control" the game, players actually put the cue ball on the pool
+ table and shot the ball into the gap. Four sensors underneath the
+ monitor would count how long they saw the ball, and from this data,
+ the velocity and crossing point of the ball could be derived.
+
+ In order to read these sensors, an extra Z80 was added to the board.
+ The Z80 program is astoundingly simple: on reset, it writes a value of
+ $00 to the output port, then waits for either sensor 0 or 1 to fire.
+ As soon as one of those sensors fires, it begins counting how long it
+ takes for the bits corresponding to those sensors, as well as sensors
+ 2 and 3, to return to their 0 state. It then writes a $ff to the
+ output port to signal that data is ready and waits for the main CPU
+ to clock the data through.
+
+ On the main program side of things, the result from the Z80 is
+ periodically polled. Once a $ff is seen, 3 words and 1 bytes' worth
+ of data is read from the Z80, after which the Z80 goes into an
+ infinite loop. When the main program is ready to read a result again,
+ it resets the Z80 to start the read going again.
+
+ The way the Z80 reads the data, is as follows:
+
+ - write $00 to output
+ - wait for sensor 0 or 1 to fire (go to the 1 state)
+ - count how long that sensor takes to return to 0
+ - count how long sensors 2 and 3 take to return to 0
+ - write $ff to output
+ - wait for data to be clocked through
+ - return 3 words + 1 byte of data:
+ - word 0 = (value of larger of sensor 2/3 counts) - (value of smaller)
+ - word 1 = value of smaller of sensor 2/3 counts
+ - word 2 = value of sensor 0/1
+ - byte = beam data
+ - bit 0 = 1 if sensor 0 fired; 0 if sensor 1 fired
+ - bit 1 = 1 if sensor 3 value > sensor 2 value; 0 otherwise
+ - enter infinite loop
+
+ Once this data is read from the Z80, it is converted to an intermediate
+ form, and then processed using 32-bit math (yes, on a 6809!) to produce
+ the final velocity and X position of the crossing.
+
+ Because it is not understood exactly where the sensors are placed and
+ how to simulate the actual behavior, this module attempts to do the
+ next best thing: given a velocity and X position, figure out raw
+ sensor values that will travel from the Z80 to the main 6809 and
+ through the calculations produce approximately the correct results.
+
+ There are several stages of data:
+
+ - sens0, sens1, sens2, sens3 = raw sensor values
+ - word1, word2, word3, beam = values from the Z80 (beam = byte val)
+ - inter1, inter2, inter3, beam = intermediate forms in the 6809
+ - vx, vy, x = final X,Y velocities and X crossing point
+
+ And all the functions here are designed to take you through the various
+ stages, both forwards and backwards, replicating the operations in the
+ 6809 or reversing them.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/z80/z80.h"
+#include "itech8.h"
+
+
+#define YBUFFER_COUNT 15
+#define MINDY 100
+
+static UINT8 z80_ctrl;
+static UINT8 z80_port_val;
+static UINT8 z80_clear_to_send;
+
+static UINT16 sensor0, sensor1, sensor2, sensor3;
+
+static UINT8 curvx, curvy = 1, curx;
+
+static INT8 xbuffer[YBUFFER_COUNT];
+static INT8 ybuffer[YBUFFER_COUNT];
+static int ybuffer_next;
+static int curxpos;
+static int last_ytotal;
+
+static UINT8 crosshair_vis;
+static int crosshair_min;
+static int crosshair_max;
+
+
+
+/*************************************
+ *
+ * sensors_to_words
+ *
+ * converts from raw sensor data to
+ * the three words + byte that the
+ * Z80 sends to the main 6809
+ *
+ *************************************/
+
+#ifdef STANDALONE
+static void sensors_to_words(UINT16 sens0, UINT16 sens1, UINT16 sens2, UINT16 sens3,
+ UINT16 *word1, UINT16 *word2, UINT16 *word3, UINT8 *beams)
+{
+ /* word 1 contains the difference between the larger of sensors 2 & 3 and the smaller */
+ *word1 = (sens3 > sens2) ? (sens3 - sens2) : (sens2 - sens3);
+
+ /* word 2 contains the value of the smaller of sensors 2 & 3 */
+ *word2 = (sens3 > sens2) ? sens2 : sens3;
+
+ /* word 3 contains the value of sensor 0 or 1, depending on which fired */
+ *word3 = sens0 ? sens0 : sens1;
+
+ /* set the beams bits */
+ *beams = 0;
+
+ /* if sensor 1 fired first, set bit 0 */
+ if (!sens0)
+ *beams |= 1;
+
+ /* if sensor 3 has the larger value, set bit 1 */
+ if (sens3 > sens2)
+ *beams |= 2;
+}
+#endif
+
+
+/*************************************
+ *
+ * words_to_inters
+ *
+ * converts the three words + byte
+ * data from the Z80 into the three
+ * intermediate values used in the
+ * final calculations
+ *
+ *************************************/
+
+#ifdef STANDALONE
+static void words_to_inters(UINT16 word1, UINT16 word2, UINT16 word3, UINT8 beams,
+ UINT16 *inter1, UINT16 *inter2, UINT16 *inter3)
+{
+ /* word 2 is scaled up by 0x1.6553 */
+ UINT16 word2mod = ((UINT64)word2 * 0x16553) >> 16;
+
+ /* intermediate values 1 and 2 are determined based on the beams bits */
+ switch (beams)
+ {
+ case 0:
+ *inter1 = word1 + word2mod;
+ *inter2 = word2mod + word3;
+ break;
+
+ case 1:
+ *inter1 = word1 + word2mod + word3;
+ *inter2 = word2mod;
+ break;
+
+ case 2:
+ *inter1 = word2mod;
+ *inter2 = word1 + word2mod + word3;
+ break;
+
+ case 3:
+ *inter1 = word2mod + word3;
+ *inter2 = word1 + word2mod;
+ break;
+ }
+
+ /* intermediate value 3 is always equal to the third word */
+ *inter3 = word3;
+}
+#endif
+
+
+/*************************************
+ *
+ * inters_to_vels
+ *
+ * converts the three intermediate
+ * values to the final velocity and
+ * X position values
+ *
+ *************************************/
+
+static void inters_to_vels(UINT16 inter1, UINT16 inter2, UINT16 inter3, UINT8 beams,
+ UINT8 *xres, UINT8 *vxres, UINT8 *vyres)
+{
+ UINT32 _27d8, _27c2;
+ UINT32 vx, vy, _283a, _283e;
+ UINT8 vxsgn;
+ UINT16 xoffs = 0x0016;
+ UINT8 xscale = 0xe6;
+ UINT16 x;
+
+ /* compute Vy */
+ vy = inter1 ? (0x31c28 / inter1) : 0;
+
+ /* compute Vx */
+ _283a = inter2 ? (0x30f2e / inter2) : 0;
+ _27d8 = ((UINT64)vy * 0xfbd3) >> 16;
+ _27c2 = _283a - _27d8;
+ vxsgn = 0;
+ if ((INT32)_27c2 < 0)
+ {
+ vxsgn = 1;
+ _27c2 = _27d8 - _283a;
+ }
+ vx = ((UINT64)_27c2 * 0x58f8c) >> 16;
+
+ /* compute X */
+ _27d8 = ((UINT64)(inter3 << 16) * _283a) >> 16;
+ _283e = ((UINT64)_27d8 * 0x4a574b) >> 16;
+
+ /* adjust X based on the low bit of the beams */
+ if (beams & 1)
+ x = 0x7a + (_283e >> 16) - xoffs;
+ else
+ x = 0x7a - (_283e >> 16) - xoffs;
+
+ /* apply a constant X scale */
+ if (xscale)
+ x = ((xscale * (x & 0xff)) >> 8) & 0xff;
+
+ /* clamp if out of range */
+ if ((vx & 0xffff) >= 0x80)
+ x = 0;
+
+ /* put the sign back in Vx */
+ vx &= 0xff;
+ if (!vxsgn)
+ vx = -vx;
+
+ /* clamp VY */
+ if ((vy & 0xffff) > 0x7f)
+ vy = 0x7f;
+ else
+ vy &= 0xff;
+
+ /* copy the results */
+ *xres = x;
+ *vxres = vx;
+ *vyres = vy;
+}
+
+
+
+/*************************************
+ *
+ * vels_to_inters
+ *
+ * converts from the final velocity
+ * and X position values back to
+ * three intermediate values that
+ * will produce the desired result
+ *
+ *************************************/
+
+static void vels_to_inters(UINT8 x, UINT8 vx, UINT8 vy,
+ UINT16 *inter1, UINT16 *inter2, UINT16 *inter3, UINT8 *beams)
+{
+ UINT32 _27d8;
+ UINT16 xoffs = 0x0016;
+ UINT8 xscale = 0xe6;
+ UINT8 x1, vx1, vy1;
+ UINT8 x2, vx2, vy2;
+ UINT8 diff1, diff2;
+ UINT16 inter2a;
+
+ /* inter1 comes from Vy */
+ *inter1 = vy ? 0x31c28 / vy : 0;
+
+ /* inter2 can be derived from Vx and Vy */
+ _27d8 = ((UINT64)vy * 0xfbd3) >> 16;
+ *inter2 = 0x30f2e / (_27d8 + ((abs((INT8)vx) << 16) / 0x58f8c));
+ inter2a = 0x30f2e / (_27d8 - ((abs((INT8)vx) << 16) / 0x58f8c));
+
+ /* compute it back both ways and pick the closer */
+ inters_to_vels(*inter1, *inter2, 0, 0, &x1, &vx1, &vy1);
+ inters_to_vels(*inter1, inter2a, 0, 0, &x2, &vx2, &vy2);
+ diff1 = (vx > vx1) ? (vx - vx1) : (vx1 - vx);
+ diff2 = (vx > vx2) ? (vx - vx2) : (vx2 - vx);
+ if (diff2 < diff1)
+ *inter2 = inter2a;
+
+ /* inter3: (beams & 1 == 1), inter3a: (beams & 1) == 0 */
+ if (((x << 8) / xscale) + xoffs >= 0x7a)
+ {
+ *beams = 1;
+ *inter3 = (((((((UINT64)(((x << 8) / xscale) + xoffs - 0x7a)) << 16) << 16) / 0x4a574b) << 16) / (0x30f2e / *inter2)) >> 16;
+ }
+ else
+ {
+ *beams = 0;
+ *inter3 = (((((((UINT64)(((x << 8) / xscale) + xoffs - 0x7a) * -1) << 16) << 16) / 0x4a574b) << 16) / (0x30f2e / *inter2)) >> 16;
+ }
+}
+
+
+
+/*************************************
+ *
+ * inters_to_words
+ *
+ * converts the intermediate values
+ * used in the final calculations
+ * back to the three words + byte
+ * data from the Z80
+ *
+ *************************************/
+
+static void inters_to_words(UINT16 inter1, UINT16 inter2, UINT16 inter3, UINT8 *beams,
+ UINT16 *word1, UINT16 *word2, UINT16 *word3)
+{
+ UINT16 word2mod;
+
+ /* intermediate value 3 is always equal to the third word */
+ *word3 = inter3;
+
+ /* on input, it is expected that the low bit of beams has already been determined */
+ if (*beams & 1)
+ {
+ /* make sure we can do it */
+ if (inter3 <= inter1)
+ {
+ /* always go back via case 3 */
+ *beams |= 2;
+
+ /* compute an appropriate value for the scaled version of word 2 */
+ word2mod = inter1 - inter3;
+
+ /* compute the other values from that */
+ *word1 = inter2 - word2mod;
+ *word2 = ((UINT64)word2mod << 16) / 0x16553;
+ }
+ else
+ logerror("inters_to_words: unable to convert %04x %04x %04x %02x\n",
+ (UINT32)inter1, (UINT32)inter2, (UINT32)inter3, (UINT32)*beams);
+ }
+
+ /* handle the case where low bit of beams is 0 */
+ else
+ {
+ /* make sure we can do it */
+ if (inter3 <= inter2)
+ {
+ /* always go back via case 0 */
+
+ /* compute an appropriate value for the scaled version of word 2 */
+ word2mod = inter2 - inter3;
+
+ /* compute the other values from that */
+ *word1 = inter1 - word2mod;
+ *word2 = ((UINT64)word2mod << 16) / 0x16553;
+ }
+ else
+ logerror("inters_to_words: unable to convert %04x %04x %04x %02x\n",
+ (UINT32)inter1, (UINT32)inter2, (UINT32)inter3, (UINT32)*beams);
+ }
+}
+
+
+
+/*************************************
+ *
+ * words_to_sensors
+ *
+ * converts from the three words +
+ * byte that the Z80 sends to the
+ * main 6809 back to raw sensor data
+ *
+ *************************************/
+
+static void words_to_sensors(UINT16 word1, UINT16 word2, UINT16 word3, UINT8 beams,
+ UINT16 *sens0, UINT16 *sens1, UINT16 *sens2, UINT16 *sens3)
+{
+ /* if bit 0 of the beams is set, sensor 1 fired first; otherwise sensor 0 fired */
+ if (beams & 1)
+ *sens0 = 0, *sens1 = word3;
+ else
+ *sens0 = word3, *sens1 = 0;
+
+ /* if bit 1 of the beams is set, sensor 3 had a larger value */
+ if (beams & 2)
+ *sens3 = word2 + word1, *sens2 = word2;
+ else
+ *sens2 = word2 + word1, *sens3 = word2;
+}
+
+
+
+/*************************************
+ *
+ * compute_sensors
+ *
+ *************************************/
+
+static void compute_sensors(void)
+{
+ UINT16 inter1, inter2, inter3;
+ UINT16 word1 = 0, word2 = 0, word3 = 0;
+ UINT8 beams;
+
+ /* skip if we're not ready */
+ if (sensor0 != 0 || sensor1 != 0 || sensor2 != 0 || sensor3 != 0)
+ return;
+
+ /* reverse map the inputs */
+ vels_to_inters(curx, curvx, curvy, &inter1, &inter2, &inter3, &beams);
+ inters_to_words(inter1, inter2, inter3, &beams, &word1, &word2, &word3);
+ words_to_sensors(word1, word2, word3, beams, &sensor0, &sensor1, &sensor2, &sensor3);
+
+ logerror("%15f: Sensor values: %04x %04x %04x %04x\n", attotime_to_double(timer_get_time()), sensor0, sensor1, sensor2, sensor3);
+}
+
+
+
+/*************************************
+ *
+ * slikz80_port_r
+ *
+ *************************************/
+
+READ8_HANDLER( slikz80_port_r )
+{
+ int result = 0;
+
+ /* if we have nothing, return 0x03 */
+ if (!sensor0 && !sensor1 && !sensor2 && !sensor3)
+ return 0x03 | (z80_clear_to_send << 7);
+
+ /* 1 bit for each sensor */
+ if (sensor0)
+ result |= 1, sensor0--;
+ if (sensor1)
+ result |= 2, sensor1--;
+ if (sensor2)
+ result |= 4, sensor2--;
+ if (sensor3)
+ result |= 8, sensor3--;
+ result |= z80_clear_to_send << 7;
+
+ return result;
+}
+
+
+
+/*************************************
+ *
+ * slikz80_port_w
+ *
+ *************************************/
+
+WRITE8_HANDLER( slikz80_port_w )
+{
+ z80_port_val = data;
+ z80_clear_to_send = 0;
+}
+
+
+
+/*************************************
+ *
+ * slikshot_z80_r
+ *
+ *************************************/
+
+READ8_HANDLER( slikshot_z80_r )
+{
+ /* allow the Z80 to send us stuff now */
+ z80_clear_to_send = 1;
+ return z80_port_val;
+}
+
+
+
+/*************************************
+ *
+ * slikshot_z80_control_r
+ *
+ *************************************/
+
+READ8_HANDLER( slikshot_z80_control_r )
+{
+ return z80_ctrl;
+}
+
+
+
+/*************************************
+ *
+ * slikshot_z80_control_w
+ *
+ *************************************/
+
+static TIMER_CALLBACK( delayed_z80_control_w )
+{
+ int data = param;
+
+ /* bit 4 controls the reset line on the Z80 */
+
+ /* this is a big kludge: only allow a reset if the Z80 is stopped */
+ /* at its endpoint; otherwise, we never get a result from the Z80 */
+ if ((data & 0x10) || cpunum_get_reg(2, Z80_PC) == 0x13a)
+ {
+ cpunum_set_input_line(2, INPUT_LINE_RESET, (data & 0x10) ? CLEAR_LINE : ASSERT_LINE);
+
+ /* on the rising edge, make the crosshair visible again */
+ if ((data & 0x10) && !(z80_ctrl & 0x10))
+ crosshair_vis = 1;
+ }
+
+ /* boost the interleave whenever this is written to */
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(100));
+
+ /* stash the new value */
+ z80_ctrl = data;
+}
+
+
+WRITE8_HANDLER( slikshot_z80_control_w )
+{
+ timer_call_after_resynch(data, delayed_z80_control_w);
+}
+
+
+
+/*************************************
+ *
+ * slikshot_set_crosshair_range
+ *
+ * set the range for the crosshair
+ *
+ *************************************/
+
+void slikshot_set_crosshair_range(int miny, int maxy)
+{
+ crosshair_min = miny;
+ crosshair_max = maxy;
+}
+
+
+
+/*************************************
+ *
+ * video_update_slikshot
+ *
+ *************************************/
+
+VIDEO_UPDATE( slikshot )
+{
+ int totaldy, totaldx;
+ int temp, i;
+
+ /* draw the normal video first */
+ video_update_itech8_2page(machine, screen, bitmap, cliprect);
+
+ /* add the current X,Y positions to the list */
+ xbuffer[ybuffer_next % YBUFFER_COUNT] = readinputportbytag_safe("FAKEX", 0);
+ ybuffer[ybuffer_next % YBUFFER_COUNT] = readinputportbytag_safe("FAKEY", 0);
+ ybuffer_next++;
+
+ /* determine where to draw the starting point */
+ curxpos += xbuffer[(ybuffer_next + 1) % YBUFFER_COUNT];
+ if (curxpos < -0x80) curxpos = -0x80;
+ if (curxpos > 0x80) curxpos = 0x80;
+
+ /* compute the total X/Y movement */
+ totaldx = totaldy = 0;
+ for (i = 0; i < YBUFFER_COUNT - 1; i++)
+ {
+ totaldx += xbuffer[(ybuffer_next + i + 1) % YBUFFER_COUNT];
+ totaldy += ybuffer[(ybuffer_next + i + 1) % YBUFFER_COUNT];
+ }
+
+ /* if the shoot button is pressed, fire away */
+ if (totaldy < last_ytotal && last_ytotal > 50 && crosshair_vis)
+ {
+ /* compute the updated values */
+ temp = totaldx;
+ if (temp <= -0x80) temp = -0x7f;
+ if (temp >= 0x80) temp = 0x7f;
+ curvx = temp;
+
+ temp = last_ytotal - 50;
+ if (temp <= 0x10) temp = 0x10;
+ if (temp >= 0x7f) temp = 0x7f;
+ curvy = temp;
+
+ temp = 0x60 + (curxpos * 0x30 / 0x80);
+ if (temp <= 0x30) temp = 0x30;
+ if (temp >= 0x90) temp = 0x90;
+ curx = temp;
+
+ compute_sensors();
+// popmessage("V=%02x,%02x X=%02x", curvx, curvy, curx);
+ crosshair_vis = 0;
+ }
+ last_ytotal = totaldy;
+
+ /* clear the buffer while the crosshair is not visible */
+ if (!crosshair_vis)
+ {
+ memset(xbuffer, 0, sizeof(xbuffer));
+ memset(ybuffer, 0, sizeof(ybuffer));
+ }
+
+ /* draw a crosshair (rotated) */
+ if (crosshair_vis)
+ {
+// if ((machine->gamedrv->flags & ORIENTATION_MASK) == ROT90)
+// draw_crosshair(bitmap, 256 - 48, (crosshair_min + crosshair_max) / 2 - (curxpos * (crosshair_max - crosshair_min) / 0x100), cliprect, 0);
+// else
+// draw_crosshair(bitmap, 48, (crosshair_min + crosshair_max) / 2 + (curxpos * (crosshair_max - crosshair_min) / 0x100), cliprect, 0);
+ }
+ return 0;
+}
+
+
+
+/*************************************
+ *
+ * main
+ *
+ * uncomment this to make a stand
+ * alone version for testing
+ *
+ *************************************/
+
+#ifdef STANDALONE
+
+int main(int argc, char *argv[])
+{
+ UINT16 word1, word2, word3;
+ UINT16 inter1, inter2, inter3;
+ UINT8 beams, x, vx, vy;
+
+ if (argc == 5)
+ {
+ UINT32 sens0, sens1, sens2, sens3;
+
+ sscanf(argv[1], "%x", &sens0);
+ sscanf(argv[2], "%x", &sens1);
+ sscanf(argv[3], "%x", &sens2);
+ sscanf(argv[4], "%x", &sens3);
+ mame_printf_debug("sensors: %04x %04x %04x %04x\n", sens0, sens1, sens2, sens3);
+ if (sens0 && sens1)
+ {
+ mame_printf_debug("error: sensor 0 or 1 must be 0\n");
+ return 1;
+ }
+
+ sensors_to_words(sens0, sens1, sens2, sens3, &word1, &word2, &word3, &beams);
+ mame_printf_debug("word1 = %04x word2 = %04x word3 = %04x beams = %d\n",
+ (UINT32)word1, (UINT32)word2, (UINT32)word3, (UINT32)beams);
+
+ words_to_inters(word1, word2, word3, beams, &inter1, &inter2, &inter3);
+ mame_printf_debug("inter1 = %04x inter2 = %04x inter3 = %04x\n", (UINT32)inter1, (UINT32)inter2, (UINT32)inter3);
+
+ inters_to_vels(inter1, inter2, inter3, beams, &x, &vx, &vy);
+ mame_printf_debug("x = %02x vx = %02x vy = %02x\n", (UINT32)x, (UINT32)vx, (UINT32)vy);
+ }
+ else if (argc == 4)
+ {
+ UINT32 xin, vxin, vyin;
+ UINT16 sens0, sens1, sens2, sens3;
+
+ sscanf(argv[1], "%x", &xin);
+ sscanf(argv[2], "%x", &vxin);
+ sscanf(argv[3], "%x", &vyin);
+ x = xin;
+ vx = vxin;
+ vy = vyin;
+ mame_printf_debug("x = %02x vx = %02x vy = %02x\n", (UINT32)x, (UINT32)vx, (UINT32)vy);
+
+ vels_to_inters(x, vx, vy, &inter1, &inter2, &inter3, &beams);
+ mame_printf_debug("inter1 = %04x inter2 = %04x inter3 = %04x beams = %d\n", (UINT32)inter1, (UINT32)inter2, (UINT32)inter3, (UINT32)beams);
+
+ inters_to_words(inter1, inter2, inter3, &beams, &word1, &word2, &word3);
+ mame_printf_debug("word1 = %04x word2 = %04x word3 = %04x beams = %d\n",
+ (UINT32)word1, (UINT32)word2, (UINT32)word3, (UINT32)beams);
+
+ words_to_sensors(word1, word2, word3, beams, &sens0, &sens1, &sens2, &sens3);
+ mame_printf_debug("sensors: %04x %04x %04x %04x\n", sens0, sens1, sens2, sens3);
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/src/mame/machine/snes.c b/src/mame/machine/snes.c
new file mode 100644
index 00000000000..feca580085b
--- /dev/null
+++ b/src/mame/machine/snes.c
@@ -0,0 +1,1911 @@
+/***************************************************************************
+
+ snes.c
+
+ Machine file to handle emulation of the Nintendo Super NES
+
+ R. Belmont
+ Anthony Kruize
+ Based on the original code by Lee Hammerton (aka Savoury Snax)
+ Thanks to Anomie for invaluable technical information.
+
+***************************************************************************/
+#define __MACHINE_SNES_C
+
+#include <math.h>
+#include "driver.h"
+#include "includes/snes.h"
+#include "cpu/g65816/g65816.h"
+#ifdef MESS
+#include "image.h"
+#endif
+
+// add-on chip emulators
+#include "machine/snesdsp1.c"
+
+/* -- Globals -- */
+UINT8 *snes_ram = NULL; /* 65816 ram */
+UINT8 *spc_ram = NULL; /* spc700 ram */
+UINT8 *snes_vram = NULL; /* Video RAM (Should be 16-bit, but it's easier this way) */
+UINT16 *snes_cgram = NULL; /* Colour RAM */
+UINT16 *snes_oam = NULL; /* Object Attribute Memory */
+static UINT16 cgram_address; /* CGRAM address */
+static UINT8 vram_read_offset; /* VRAM read offset */
+UINT8 spc_port_in[4]; /* Port for sending data to the SPC700 */
+UINT8 spc_port_out[4]; /* Port for receiving data from the SPC700 */
+static UINT8 ppu_last_scroll; /* as per Theme Park, this is shared by all scroll regs */
+static UINT8 snes_hdma_chnl; /* channels enabled for HDMA */
+static UINT8 joy1l, joy1h, joy2l, joy2h, joy3l, joy3h, joy4l, joy4h;
+static UINT8 read_ophct = 0, read_opvct = 0;
+static emu_timer *snes_scanline_timer;
+static emu_timer *snes_hblank_timer;
+static emu_timer *snes_nmi_timer;
+static emu_timer *snes_hirq_timer;
+static UINT16 hblank_offset;
+static UINT16 snes_htmult; /* in 512 wide, we run HTOTAL double and halve it on latching */
+
+// full graphic variables
+static UINT16 vram_fgr_high, vram_fgr_increment, vram_fgr_count, vram_fgr_mask, vram_fgr_shift, vram_read_buffer;
+static UINT16 vram_fgr_inctab[4] = { 1, 32, 128, 128 };
+static UINT16 vram_fgr_inccnts[4] = { 0, 32, 64, 128 };
+static UINT16 vram_fgr_shiftab[4] = { 0, 5, 6, 7 };
+
+struct snes_cart_info snes_cart = { SNES_MODE_20, 0x40000, 0x40000 };
+
+static struct
+{
+ UINT8 low;
+ UINT8 high;
+ UINT32 value;
+ UINT8 oldrol;
+} joypad[4];
+
+// quick extern to fix missing header
+extern attotime video_screen_get_time_until_pos(int scrnum, int vpos, int hpos);
+
+// utility function - latches the H/V counters. Used by IRQ, writes to WRIO, etc.
+static void snes_latch_counters(void)
+{
+ snes_ppu.beam.current_horz = video_screen_get_hpos(0) / snes_htmult;
+ snes_ppu.beam.latch_vert = video_screen_get_vpos(0);
+ snes_ppu.beam.latch_horz = snes_ppu.beam.current_horz;
+ snes_ram[STAT78] |= 0x40; // indicate we latched
+ read_ophct = read_opvct = 0; // clear read flags
+
+// printf("latched @ H %d V %d\n", snes_ppu.beam.latch_horz, snes_ppu.beam.latch_vert);
+}
+
+static TIMER_CALLBACK( snes_nmi_tick )
+{
+ // pull NMI
+ cpunum_set_input_line( 0, G65816_LINE_NMI, HOLD_LINE );
+
+ // don't happen again
+ timer_adjust(snes_nmi_timer, attotime_never, 0, attotime_never);
+}
+
+static void snes_hirq_tick(void)
+{
+ // latch the counters and pull IRQ
+ // (don't need to switch to the 65816 context, we don't do anything dependant on it)
+ snes_latch_counters();
+ snes_ram[TIMEUP] = 0x80; /* Indicate that irq occured */
+ cpunum_set_input_line( 0, G65816_LINE_IRQ, HOLD_LINE );
+
+ // don't happen again
+ timer_adjust(snes_hirq_timer, attotime_never, 0, attotime_never);
+}
+
+static TIMER_CALLBACK( snes_hirq_tick_callback )
+{
+ snes_hirq_tick();
+}
+
+static TIMER_CALLBACK( snes_scanline_tick )
+{
+ // make sure we're in the 65816's context since we're messing with the OAM and stuff
+ cpuintrf_push_context(0);
+
+ /* Increase current line - we want to latch on this line during it, not after it */
+ snes_ppu.beam.current_vert = video_screen_get_vpos(0);
+
+ // not in hblank
+ snes_ram[HVBJOY] &= ~0x40;
+
+ /* Vertical IRQ timer - only if horizontal isn't also enabled! */
+ if ((snes_ram[NMITIMEN] & 0x20) && !(snes_ram[NMITIMEN] & 0x10))
+ {
+ if (snes_ppu.beam.current_vert == (((snes_ram[VTIMEH] << 8) | snes_ram[VTIMEL]) & 0x1ff))
+ {
+ snes_ram[TIMEUP] = 0x80; /* Indicate that irq occured */
+ // IRQ latches the counters, do it now
+ snes_latch_counters();
+ cpunum_set_input_line( 0, G65816_LINE_IRQ, HOLD_LINE );
+ }
+ }
+ /* Horizontal IRQ timer */
+ if( snes_ram[NMITIMEN] & 0x10 )
+ {
+ int setirq = 1;
+ int pixel = ((snes_ram[HTIMEH] << 8) | snes_ram[HTIMEL]) & 0x1ff;
+
+ // is the HIRQ on a specific scanline?
+ if (snes_ram[NMITIMEN] & 0x20)
+ {
+ if (snes_ppu.beam.current_vert != (((snes_ram[VTIMEH] << 8) | snes_ram[VTIMEL]) & 0x1ff) )
+ {
+ setirq = 0;
+ }
+ }
+
+ if (setirq)
+ {
+// printf("HIRQ @ %d, %d\n", pixel*snes_htmult, snes_ppu.beam.current_vert);
+ if (pixel == 0)
+ {
+ snes_hirq_tick();
+ }
+ else
+ {
+ timer_adjust(snes_hirq_timer, video_screen_get_time_until_pos(0, snes_ppu.beam.current_vert, pixel*snes_htmult), 0, attotime_never);
+ }
+ }
+ }
+
+ /* Start of VBlank */
+ if( snes_ppu.beam.current_vert == snes_ppu.beam.last_visible_line )
+ {
+ program_write_byte(OAMADDL, snes_ppu.oam.address_low ); /* Reset oam address */
+ program_write_byte(OAMADDH, snes_ppu.oam.address_high );
+ snes_ram[HVBJOY] |= 0x81; /* Set vblank bit to on & indicate controllers being read */
+ snes_ram[RDNMI] |= 0x80; /* Set NMI occured bit */
+
+ if( snes_ram[NMITIMEN] & 0x80 ) /* NMI only signaled if this bit set */
+ {
+ // NMI goes off about 12 cycles after this (otherwise Chrono Trigger, NFL QB Club, etc. lock up)
+ timer_adjust(snes_nmi_timer, ATTOTIME_IN_CYCLES(12, 0), 0, attotime_zero);
+ }
+ }
+
+ // hdma reset happens at scanline 0, H=~6
+ if (snes_ppu.beam.current_vert == 0)
+ {
+ snes_hdma_init();
+ }
+
+ /* three lines after start of vblank we update the controllers (value from snes9x) */
+ if (snes_ppu.beam.current_vert == snes_ppu.beam.last_visible_line + 3)
+ {
+ int i;
+
+ joypad[0].low = readinputport( 0 );
+ joypad[0].high = readinputport( 1 );
+ joypad[1].low = readinputport( 2 );
+ joypad[1].high = readinputport( 3 );
+ joypad[2].low = readinputport( 4 );
+ joypad[2].high = readinputport( 5 );
+ joypad[3].low = readinputport( 6 );
+ joypad[3].high = readinputport( 7 );
+
+ // avoid sending signals that could crash games
+ for (i = 0; i < 4; i++)
+ {
+ // if left, no right
+ if (joypad[i].high & 2) joypad[i].high &= ~1;
+ // if up, no down
+ if (joypad[i].high & 8) joypad[i].high &= ~4;
+ }
+
+ // is automatic reading on?
+ if (snes_ram[NMITIMEN] & 1)
+ {
+ joy1l = joypad[0].low;
+ joy1h = joypad[0].high;
+ joy2l = joypad[1].low;
+ joy2h = joypad[1].high;
+ joy3l = joypad[2].low;
+ joy3h = joypad[2].high;
+ joy4l = joypad[3].low;
+ joy4h = joypad[3].high;
+
+ // make sure oldrol starts returning all 1s because the auto-read reads it :-)
+ joypad[0].oldrol = 16;
+ joypad[1].oldrol = 16;
+ }
+
+ snes_ram[HVBJOY] &= 0xfe; /* Clear busy bit */
+ }
+
+ if( snes_ppu.beam.current_vert == 0 )
+ { /* VBlank is over, time for a new frame */
+ snes_ram[HVBJOY] &= 0x7f; /* Clear vblank bit */
+ snes_ram[RDNMI] &= 0x7f; /* Clear nmi occured bit */
+ snes_ram[STAT77] &= 0x3f; /* Clear Time Over and Range Over bits */
+ snes_ram[STAT78] ^= 0x80; /* Toggle field flag */
+
+ cpunum_set_input_line( 0, G65816_LINE_NMI, CLEAR_LINE );
+ }
+
+ cpuintrf_pop_context();
+
+ timer_adjust(snes_scanline_timer, attotime_never, 0, attotime_never);
+ timer_adjust(snes_hblank_timer, video_screen_get_time_until_pos(0, snes_ppu.beam.current_vert, hblank_offset*snes_htmult), 0, attotime_never);
+}
+
+/* This is called at the start of hblank *before* the scanline indicated in current_vert! */
+static TIMER_CALLBACK( snes_hblank_tick )
+{
+ int nextscan;
+
+ snes_ppu.beam.current_vert = video_screen_get_vpos(0);
+
+ /* make sure we halt */
+ timer_adjust(snes_hblank_timer, attotime_never, 0, attotime_never);
+
+ // we must guarantee the 65816's context for HDMA to work
+ cpuintrf_push_context(0);
+
+ /* draw a scanline */
+ if (snes_ppu.beam.current_vert <= snes_ppu.beam.last_visible_line)
+ {
+ if (video_screen_get_vpos(0) > 0)
+ {
+ /* Do HDMA */
+ if( snes_ram[HDMAEN] )
+ {
+ snes_hdma();
+ }
+
+ video_screen_update_partial(0, snes_ppu.beam.current_vert-1);
+ }
+ }
+
+ cpuintrf_pop_context();
+
+ // signal hblank
+ snes_ram[HVBJOY] |= 0x40;
+
+ /* kick off the start of scanline timer */
+ nextscan = snes_ppu.beam.current_vert + 1;
+ if (nextscan >= (((snes_ram[STAT78] & 0x10) == SNES_NTSC) ? SNES_VTOTAL_NTSC : SNES_VTOTAL_PAL))
+ {
+ nextscan = 0;
+ }
+
+ timer_adjust(snes_scanline_timer, video_screen_get_time_until_pos(0, nextscan, 0), 0, attotime_never);
+}
+
+static void snes_init_ram(void)
+{
+ int i;
+
+ /* Init DSP1 interface */
+ InitDSP1();
+
+ /* Init VRAM */
+ memset( snes_vram, 0, SNES_VRAM_SIZE );
+
+ /* Init Colour RAM */
+ memset( (UINT8 *)snes_cgram, 0, SNES_CGRAM_SIZE );
+
+ /* Init oam RAM */
+ memset( snes_oam, 0xff, SNES_OAM_SIZE );
+
+ /* Init work RAM - 0x55 isn't exactly right but it's close */
+ /* make sure it happens to the 65816 (CPU 0) */
+ cpuintrf_push_context(0);
+ for (i = 0; i < (128*1024); i++)
+ {
+ program_write_byte(0x7e0000 + i, 0x55);
+ }
+ cpuintrf_pop_context();
+
+ /* Inititialize registers/variables */
+ snes_ppu.update_windows = 1;
+ snes_ppu.update_palette = 1;
+ snes_ppu.beam.latch_vert = 0;
+ snes_ppu.beam.latch_horz = 0;
+ snes_ppu.beam.current_vert = 0;
+ snes_ppu.beam.current_horz = 0;
+ snes_ppu.beam.last_visible_line = 240;
+ snes_ppu.mode = 0;
+ cgram_address = 0;
+ vram_read_offset = 2;
+ joy1l = joy1h = joy2l = joy2h = joy3l = joy3h = 0;
+
+ // set up some known register power-up defaults
+ snes_ram[WRIO] = 0xff;
+ snes_ram[VMAIN] = 0x80;
+
+ /* init timers and stop them */
+ snes_scanline_timer = timer_alloc(snes_scanline_tick);
+ timer_adjust(snes_scanline_timer, attotime_never, 0, attotime_never);
+ snes_hblank_timer = timer_alloc(snes_hblank_tick);
+ timer_adjust(snes_hblank_timer, attotime_never, 0, attotime_never);
+ snes_nmi_timer = timer_alloc(snes_nmi_tick);
+ timer_adjust(snes_nmi_timer, attotime_never, 0, attotime_never);
+ snes_hirq_timer = timer_alloc(snes_hirq_tick_callback);
+ timer_adjust(snes_hirq_timer, attotime_never, 0, attotime_never);
+
+ // SNES hcounter has a 0-339 range. hblank starts at counter 260.
+ // clayfighter sets an HIRQ at 260, apparently it wants it to be before hdma kicks off, so we'll delay 2 pixels.
+ hblank_offset = 268;
+ timer_adjust(snes_hblank_timer, video_screen_get_time_until_pos(0, ((snes_ram[STAT78] & 0x10) == SNES_NTSC) ? SNES_VTOTAL_NTSC-1 : SNES_VTOTAL_PAL-1, hblank_offset), 0, attotime_never);
+
+ // check if DSP1 is present (maybe not 100%?)
+ has_dsp1 = ((snes_r_bank1(0xffd6) >= 3) && (snes_r_bank1(0xffd6) <= 5)) ? 1 : 0;
+
+ // init frame counter so first line is 0
+ if( ATTOSECONDS_TO_HZ(Machine->screen[0].refresh) >= 59 )
+ {
+ snes_ppu.beam.current_vert = SNES_VTOTAL_NTSC;
+ }
+ else
+ {
+ snes_ppu.beam.current_vert = SNES_VTOTAL_PAL;
+ }
+}
+
+/* should we treat this as nvram in MAME? */
+static OPBASE_HANDLER(spc_opbase)
+{
+ opcode_base = opcode_arg_base = spc_ram;
+ return ~0;
+}
+
+static OPBASE_HANDLER(snes_opbase)
+{
+ opcode_base = opcode_arg_base = snes_ram;
+ return ~0;
+}
+
+MACHINE_START( snes )
+{
+ snes_vram = auto_malloc(SNES_VRAM_SIZE);
+ snes_cgram = auto_malloc(SNES_CGRAM_SIZE);
+ snes_oam = auto_malloc(SNES_OAM_SIZE);
+ memory_set_opbase_handler(0, snes_opbase);
+ memory_set_opbase_handler(1, spc_opbase);
+
+ // power-on sets these registers like this
+ snes_ram[WRIO] = 0xff;
+ snes_ram[WRMPYA] = 0xff;
+ snes_ram[WRDIVL] = 0xff;
+ snes_ram[WRDIVH] = 0xff;
+}
+
+MACHINE_RESET( snes )
+{
+ snes_init_ram();
+
+ /* Set STAT78 to NTSC or PAL */
+ if( ATTOSECONDS_TO_HZ(machine->screen[0].refresh) >= 59.0f )
+ snes_ram[STAT78] = SNES_NTSC;
+ else /* if( machine->screen[0].refresh == 50 ) */
+ snes_ram[STAT78] = SNES_PAL;
+
+ // reset does this to these registers
+ snes_ram[NMITIMEN] = 0;
+ snes_ram[HTIMEL] = 0xff;
+ snes_ram[HTIMEH] = 0x1;
+ snes_ram[VTIMEL] = 0xff;
+ snes_ram[VTIMEH] = 0x1;
+
+ snes_htmult = 1;
+}
+
+/* Handle reading of Mode 20 SRAM */
+/* 0x700000 - 0x77ffff */
+READ8_HANDLER( snes_r_sram )
+{
+ UINT8 value = 0xff;
+ int mask;
+
+ // limit SRAM size to what's actually present
+ mask = (snes_cart.sram * 1024) - 1;
+ offset &= mask;
+
+ if( snes_cart.sram > 0 )
+ {
+ value = snes_ram[0x700000 + offset];
+ }
+
+ return value;
+}
+
+WRITE8_HANDLER( snes_w_sram )
+{
+ int mask;
+
+ // limit SRAM size to what's actually present
+ mask = (snes_cart.sram * 1024) - 1;
+ offset &= mask;
+
+ if( snes_cart.sram > 0 )
+ {
+ snes_ram[0x700000 + offset] = data;
+ }
+}
+
+/* 0x000000 - 0x2fffff */
+READ8_HANDLER( snes_r_bank1 )
+{
+ UINT16 address = offset & 0xffff;
+
+ if ((snes_cart.mode == SNES_MODE_20) && (has_dsp1))
+ {
+ if ((address >= 0x8000) && (offset >= 0x200000))
+ {
+ return dsp1_read(address);
+ }
+ }
+
+ if( address <= 0x1fff ) /* Mirror of Low RAM */
+ return program_read_byte(0x7e0000 + address );
+ else if( address >= 0x2000 && address <= 0x5fff ) /* I/O */
+ return snes_r_io( address );
+ else if( address >= 0x6000 && address <= 0x7fff ) /* Reserved */
+ {
+ if( snes_cart.mode == SNES_MODE_20 )
+ return 0xff;
+ else
+ return dsp1_read(address);
+ }
+ else
+ {
+ if( snes_cart.mode == SNES_MODE_20 )
+ return snes_ram[offset];
+ else /* MODE_21 */
+ return snes_ram[0xc00000 + offset];
+ }
+
+ return 0xff;
+}
+
+/* 0x300000 - 0x3fffff */
+READ8_HANDLER( snes_r_bank2 )
+{
+ UINT16 address = offset & 0xffff;
+
+ if ((snes_cart.mode == SNES_MODE_20) && (has_dsp1))
+ {
+ if (address >= 0x8000)
+ {
+ return dsp1_read(address);
+ }
+ }
+
+ if( address <= 0x1fff ) /* Mirror of Low RAM */
+ return program_read_byte(0x7e0000 + address );
+ else if( address >= 0x2000 && address <= 0x5fff ) /* I/O */
+ return snes_r_io( address );
+ else if( address >= 0x6000 && address <= 0x7fff )
+ {
+ if( snes_cart.mode == SNES_MODE_20 )
+ return 0xff; /* Reserved */
+ else /* MODE_21 */
+ {
+ int mask;
+
+ offset -= 0x6000;
+
+ // limit SRAM size to what's actually present
+ mask = (snes_cart.sram * 1024) - 1;
+ offset &= mask;
+ return snes_ram[0x306000 + offset]; /* sram */
+ }
+ }
+ else
+ {
+ if( snes_cart.mode == SNES_MODE_20 )
+ return snes_ram[0x300000 + offset];
+ else /* MODE_21 */
+ return snes_ram[0xf00000 + offset];
+ }
+
+ return 0xff;
+}
+
+/* 0x400000 - 0x5fffff */
+READ8_HANDLER( snes_r_bank3 )
+{
+ UINT16 address = offset & 0xffff;
+
+ if( snes_cart.mode == SNES_MODE_20 )
+ {
+ if( address <= 0x7fff )
+ return 0xff; /* Reserved */
+ else
+ return snes_ram[0x400000 + offset];
+ }
+ else /* MODE_21 */
+ {
+ return snes_ram[0x400000 + offset];
+ }
+
+ return 0xff;
+}
+
+/* 0x600000 - 0x6fffff */
+READ8_HANDLER( snes_r_bank6 )
+{
+ UINT16 address = offset & 0xffff;
+
+ if (address < 0x8000)
+ {
+ return dsp1_read(address);
+ }
+
+ return 0xff;
+}
+
+/* 0x800000 - 0xffffff */
+READ8_HANDLER( snes_r_bank4 )
+{
+ if( snes_cart.mode == SNES_MODE_20 )
+ {
+ if( offset <= 0x5fffff )
+ return program_read_byte(offset );
+ else
+ return 0xff;
+ }
+ else /* MODE_21 */
+ {
+ if( offset <= 0x3fffff )
+ return program_read_byte(offset );
+ else
+ return snes_ram[offset + 0x800000];
+ }
+
+ return 0xff;
+}
+
+/* 0x000000 - 0x2fffff */
+WRITE8_HANDLER( snes_w_bank1 )
+{
+ UINT16 address = offset & 0xffff;
+
+ if ((address >= 0x8000) && (offset >= 0x200000))
+ {
+ dsp1_write(address, data);
+ return;
+ }
+
+ if( address <= 0x1fff ) /* Mirror of Low RAM */
+ program_write_byte(0x7e0000 + address, data );
+ else if( address >= 0x2000 && address <= 0x5fff ) /* I/O */
+ snes_w_io( address, data );
+ else if( address >= 0x6000 && address <= 0x7fff ) /* Reserved */
+ if( snes_cart.mode == SNES_MODE_20 )
+ logerror( "Attempt to write to reserved address: %X\n", offset );
+ else
+ {
+ dsp1_write(address, data);
+ return;
+ }
+ else
+ logerror( "Attempt to write to ROM address: %X\n", offset );
+}
+
+/* 0x300000 - 0x3fffff */
+WRITE8_HANDLER( snes_w_bank2 )
+{
+ UINT16 address = offset & 0xffff;
+
+ if (address >= 0x8000)
+ {
+ dsp1_write(address, data);
+ return;
+ }
+
+ if( address <= 0x1fff ) /* Mirror of Low RAM */
+ program_write_byte(0x7e0000 + address, data );
+ else if( address >= 0x2000 && address <= 0x5fff ) /* I/O */
+ snes_w_io( address, data );
+ else if( address >= 0x6000 && address <= 0x7fff )
+ {
+ if( snes_cart.mode == SNES_MODE_20 ) /* Reserved */
+ logerror( "Attempt to write to reserved address: %X\n", offset );
+ else /* MODE_21 */
+ {
+ int mask;
+
+ offset -= 0x6000;
+
+ // limit SRAM size to what's actually present
+ mask = (snes_cart.sram * 1024) - 1;
+ offset &= mask;
+ snes_ram[0x306000 + offset] = data; /* sram */
+ }
+ }
+ else
+ logerror( "Attempt to write to ROM address: %X\n", offset );
+}
+
+/* 0x600000 - 0x6fffff */
+WRITE8_HANDLER( snes_w_bank6 )
+{
+ UINT16 address = offset & 0xffff;
+
+ if (address < 0x8000)
+ {
+ dsp1_write(address, data);
+ return;
+ }
+}
+
+/* 0x800000 - 0xffffff */
+WRITE8_HANDLER( snes_w_bank4 )
+{
+ if( snes_cart.mode == SNES_MODE_20 )
+ {
+ if( offset <= 0x2fffff )
+ snes_w_bank1( offset, data );
+ else if( offset >= 0x300000 && offset <= 0x3fffff )
+ snes_w_bank2( offset - 0x300000, data );
+ }
+ else /* MODE_21 */
+ {
+ if( offset <= 0x2fffff )
+ snes_w_bank1( offset, data );
+ else if( offset >= 0x300000 && offset <= 0x3fffff )
+ snes_w_bank2( offset - 0x300000, data );
+ else
+ logerror( "Attempt to write to ROM address: %X\n", offset );
+ }
+}
+
+/*
+ * DR - Double read : address is read twice to return a 16bit value.
+ * low - This is the low byte of a 16 or 24 bit value
+ * mid - This is the middle byte of a 24 bit value
+ * high - This is the high byte of a 16 or 24 bit value
+ */
+READ8_HANDLER( snes_r_io )
+{
+ UINT8 value = 0;
+
+ // APU is mirrored from 2140 to 217f
+ if (offset >= APU00 && offset < WMDATA)
+ {
+ return spc_port_out[offset & 0x3];
+ }
+
+ /* offset is from 0x000000 */
+ switch( offset )
+ {
+ /* hacks for SimCity 2000 to boot - I presume openbus emulation will fix */
+ case 0x221a:
+ case 0x231c:
+ case 0x241e:
+ return 1;
+ case 0x2017:
+ case 0x221b:
+ case 0x231d:
+ case 0x241f:
+ return 0;
+ case 0x2016:
+ return 2;
+
+ case OAMADDL:
+ case OAMADDH:
+ case VMADDL:
+ case VMADDH:
+ case VMDATAL:
+ case VMDATAH:
+ case CGADD:
+ case CGDATA:
+ return snes_ram[offset];
+ case MPYL: /* Multiplication result (low) */
+ case MPYM: /* Multiplication result (mid) */
+ case MPYH: /* Multiplication result (high) */
+ {
+ /* Perform 16bit * 8bit multiply */
+ INT32 c = snes_ppu.mode7.matrix_a * (snes_ppu.mode7.matrix_b >> 8);
+ snes_ram[MPYL] = c & 0xff;
+ snes_ram[MPYM] = (c >> 8) & 0xff;
+ snes_ram[MPYH] = (c >> 16) & 0xff;
+ return snes_ram[offset];
+ }
+ case SLHV: /* Software latch for H/V counter */
+ snes_latch_counters();
+ return 0x0; /* Return value is meaningless */
+ case ROAMDATA: /* Read data from OAM (DR) */
+ {
+ int oam_addr = snes_ppu.oam.address;
+
+ if (oam_addr & 0x100)
+ {
+ oam_addr &= 0x10f;
+ }
+ else
+ {
+ oam_addr &= 0x1ff;
+ }
+
+ value = (snes_oam[oam_addr] >> (snes_ram[OAMDATA] << 3)) & 0xff;
+ snes_ram[OAMDATA] = (snes_ram[OAMDATA] + 1) % 2;
+ if( snes_ram[OAMDATA] == 0 )
+ {
+ snes_ppu.oam.address++;
+ snes_ppu.oam.address_low = snes_ram[OAMADDL] = snes_ppu.oam.address & 0xff;
+ snes_ppu.oam.address_high = snes_ram[OAMADDH] = (snes_ppu.oam.address >> 8) & 0x1;
+ }
+ return value;
+ }
+ case RVMDATAL: /* Read data from VRAM (low) */
+ {
+ UINT32 addr = (snes_ram[VMADDH] << 8) | snes_ram[VMADDL];
+
+ value = vram_read_buffer & 0xff;
+
+ if (!vram_fgr_high)
+ {
+ if (vram_fgr_count)
+ {
+ UINT32 rem = addr & vram_fgr_mask;
+ UINT32 faddr = (addr & ~vram_fgr_mask) + (rem >> vram_fgr_shift) +
+ ((rem & (vram_fgr_count - 1)) << 3);
+
+ vram_read_buffer = snes_vram[(faddr<<1)&0xffff] | snes_vram[((faddr<<1)+1) & 0xffff]<<8;
+ }
+ else
+ {
+ vram_read_buffer = snes_vram[(addr<<1)&0xffff] | snes_vram[((addr<<1)+1) & 0xffff]<<8;
+ }
+
+ addr += vram_fgr_increment;
+ snes_ram[VMADDL] = addr&0xff;
+ snes_ram[VMADDH] = (addr>>8)&0xff;
+ }
+ }
+ return value;
+ case RVMDATAH: /* Read data from VRAM (high) */
+ {
+ UINT32 addr = (snes_ram[VMADDH] << 8) | snes_ram[VMADDL];
+
+ value = (vram_read_buffer>>8) & 0xff;
+
+ if (vram_fgr_high)
+ {
+ if (vram_fgr_count)
+ {
+ UINT32 rem = addr & vram_fgr_mask;
+ UINT32 faddr = (addr & ~vram_fgr_mask) + (rem >> vram_fgr_shift) +
+ ((rem & (vram_fgr_count - 1)) << 3);
+
+ vram_read_buffer = snes_vram[(faddr<<1)&0xffff] | snes_vram[((faddr<<1)+1) & 0xffff]<<8;
+ }
+ else
+ {
+ vram_read_buffer = snes_vram[(addr<<1)&0xffff] | snes_vram[((addr<<1)+1) & 0xffff]<<8;
+ }
+
+ addr += vram_fgr_increment;
+ snes_ram[VMADDL] = addr&0xff;
+ snes_ram[VMADDH] = (addr>>8)&0xff;
+ }
+ }
+ return value;
+ case RCGDATA: /* Read data from CGRAM */
+ value = ((UINT8 *)snes_cgram)[cgram_address];
+ cgram_address = (cgram_address + 1) % (SNES_CGRAM_SIZE - 2);
+ return value;
+ case OPHCT: /* Horizontal counter data by ext/soft latch */
+ {
+ /* FIXME: need to handle STAT78 reset */
+ if( read_ophct )
+ {
+ value = (snes_ppu.beam.latch_horz >> 8) & 0x1;
+ read_ophct = 0;
+ }
+ else
+ {
+ value = snes_ppu.beam.latch_horz & 0xff;
+ read_ophct = 1;
+ }
+ return value;
+ }
+ case OPVCT: /* Vertical counter data by ext/soft latch */
+ {
+ /* FIXME: need to handle STAT78 reset */
+ if( read_opvct )
+ {
+ value = (snes_ppu.beam.latch_vert >> 8) & 0x1;
+ read_opvct = 0;
+ }
+ else
+ {
+ value = snes_ppu.beam.latch_vert & 0xff;
+ read_opvct = 1;
+ }
+ return value;
+ }
+ case STAT77: /* PPU status flag and version number */
+ return snes_ram[offset];
+ case STAT78: /* PPU status flag and version number */
+ /* FIXME: need to reset OPHCT and OPVCT */
+ value = snes_ram[offset];
+ snes_ram[offset] &= ~0x40; // clear 'latched counters' flag
+ return value;
+ case WMDATA: /* Data to read from WRAM */
+ {
+ UINT32 addr = ((snes_ram[WMADDH] & 0x1) << 16) | (snes_ram[WMADDM] << 8) | snes_ram[WMADDL];
+
+ value = program_read_byte(0x7e0000 + addr++);
+ addr &= 0x1ffff;
+ snes_ram[WMADDH] = (addr >> 16) & 0x1;
+ snes_ram[WMADDM] = (addr >> 8) & 0xff;
+ snes_ram[WMADDL] = addr & 0xff;
+ return value;
+ }
+ case WMADDL: /* Address to read/write to wram (low) */
+ case WMADDM: /* Address to read/write to wram (mid) */
+ case WMADDH: /* Address to read/write to wram (high) */
+ return snes_ram[offset];
+ case OLDJOY1: /* Data for old NES controllers */
+ {
+ if( snes_ram[offset] & 0x1 )
+ {
+ return 0;
+ }
+ value = ((joypad[0].low | (joypad[0].high << 8) | 0x10000) >> (15 - (joypad[0].oldrol++ % 16))) & 0x1;
+ if( !(joypad[0].oldrol % 17) )
+ value = 0x1;
+ return value;
+ }
+ case OLDJOY2: /* Data for old NES controllers */
+ {
+ if( snes_ram[OLDJOY1] & 0x1 )
+ {
+ return 0;
+ }
+ value = ((joypad[1].low | (joypad[1].high << 8) | 0x10000) >> (15 - (joypad[1].oldrol++ % 16))) & 0x1;
+ if( !(joypad[1].oldrol % 17) )
+ value = 0x1;
+ value |= 0x1c; // bits 4, 3, and 2 are always set
+ return value;
+ }
+ case HTIMEL:
+ case HTIMEH:
+ case VTIMEL:
+ case VTIMEH:
+ return snes_ram[offset];
+ case MDMAEN: /* GDMA channel designation and trigger */
+ /* FIXME: Is this really read-only? - Villgust needs to read it */
+ return snes_ram[offset];
+ case RDNMI: /* NMI flag by v-blank and version number */
+ value = snes_ram[offset];
+ snes_ram[offset] &= 0x7f; /* NMI flag is reset on read */
+ return value;
+ case TIMEUP: /* IRQ flag by H/V count timer */
+ value = snes_ram[offset];
+ snes_ram[offset] = 0; /* Register is reset on read */
+ return value;
+ case HVBJOY: /* H/V blank and joypad controller enable */
+ // electronics test says hcounter 272 is start of hblank, which is beampos 363
+// if (video_screen_get_hpos(0) >= 363) snes_ram[offset] |= 0x40;
+// else snes_ram[offset] &= ~0x40;
+ return snes_ram[offset];
+ case RDIO: /* Programmable I/O port - echos back what's written to WRIO */
+ return snes_ram[WRIO];
+ break;
+ case RDDIVL: /* Quotient of divide result (low) */
+ case RDDIVH: /* Quotient of divide result (high) */
+ case RDMPYL: /* Product/Remainder of mult/div result (low) */
+ case RDMPYH: /* Product/Remainder of mult/div result (high) */
+ return snes_ram[offset];
+ case JOY1L: /* Joypad 1 status register (low) */
+ return joypad[0].low;
+ case JOY1H: /* Joypad 1 status register (high) */
+ return joypad[0].high;
+ case JOY2L: /* Joypad 2 status register (low) */
+ return joypad[1].low;
+ case JOY2H: /* Joypad 2 status register (high) */
+ return joypad[1].high;
+ case JOY3L: /* Joypad 3 status register (low) */
+ return joypad[2].low;
+ case JOY3H: /* Joypad 3 status register (high) */
+ return joypad[2].high;
+ case JOY4L: /* Joypad 4 status register (low) */
+ return joypad[3].low;
+ case JOY4H: /* Joypad 4 status register (high) */
+ return joypad[3].high;
+ case DMAP0: case BBAD0: case A1T0L: case A1T0H: case A1B0: case DAS0L:
+ case DAS0H: case DSAB0: case A2A0L: case A2A0H: case NTRL0:
+ case DMAP1: case BBAD1: case A1T1L: case A1T1H: case A1B1: case DAS1L:
+ case DAS1H: case DSAB1: case A2A1L: case A2A1H: case NTRL1:
+ case DMAP2: case BBAD2: case A1T2L: case A1T2H: case A1B2: case DAS2L:
+ case DAS2H: case DSAB2: case A2A2L: case A2A2H: case NTRL2:
+ case DMAP3: case BBAD3: case A1T3L: case A1T3H: case A1B3: case DAS3L:
+ case DAS3H: case DSAB3: case A2A3L: case A2A3H: case NTRL3:
+ case DMAP4: case BBAD4: case A1T4L: case A1T4H: case A1B4: case DAS4L:
+ case DAS4H: case DSAB4: case A2A4L: case A2A4H: case NTRL4:
+ case DMAP5: case BBAD5: case A1T5L: case A1T5H: case A1B5: case DAS5L:
+ case DAS5H: case DSAB5: case A2A5L: case A2A5H: case NTRL5:
+ case DMAP6: case BBAD6: case A1T6L: case A1T6H: case A1B6: case DAS6L:
+ case DAS6H: case DSAB6: case A2A6L: case A2A6H: case NTRL6:
+ case DMAP7: case BBAD7: case A1T7L: case A1T7H: case A1B7: case DAS7L:
+ case DAS7H: case DSAB7: case A2A7L: case A2A7H: case NTRL7:
+ return snes_ram[offset];
+
+#ifndef MESS
+ case 0x4100: /* NSS Dip-Switches */
+#ifdef MAME_DEBUG
+ return readinputport(12);
+#else
+ return readinputport(9);
+#endif /* MAME_DEBUG */
+// case 0x4101: //PC: a104 - a10e - a12a //only nss_actr
+// case 0x420c: //PC: 9c7d - 8fab //only nss_ssoc
+
+ default:
+ mame_printf_debug("snes_r: offset = %x pc = %x\n",offset,activecpu_get_pc());
+#endif /* MESS */
+
+ }
+
+ /* Unsupported reads return 0xff */
+ return 0xff;
+}
+
+/*
+ * DW - Double write : address is written twice to set a 16bit value.
+ * low - This is the low byte of a 16 or 24 bit value
+ * mid - This is the middle byte of a 24 bit value
+ * high - This is the high byte of a 16 or 24 bit value
+ */
+WRITE8_HANDLER( snes_w_io )
+{
+ // APU is mirrored from 2140 to 217f
+ if (offset >= APU00 && offset < WMDATA)
+ {
+// printf("816: %02x to APU @ %d\n", data, offset&3);
+ spc_port_in[offset & 0x3] = data;
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(20));
+ return;
+ }
+
+ /* offset is from 0x000000 */
+ switch( offset )
+ {
+ case INIDISP: /* Initial settings for screen */
+ snes_ppu.update_palette = 1;
+ break;
+ case OBSEL: /* Object size and data area designation */
+ snes_ppu.layer[4].data = ((data & 0x3) * 0x2000) << 1;
+ snes_ppu.oam.name_select = (((data & 0x18)>>3) * 0x1000) << 1;
+ /* Determine object size */
+ switch( (data & 0xe0) >> 5 )
+ {
+ case 0: /* 8 & 16 */
+ snes_ppu.oam.size[0] = 1;
+ snes_ppu.oam.size[1] = 2;
+ break;
+ case 1: /* 8 & 32 */
+ snes_ppu.oam.size[0] = 1;
+ snes_ppu.oam.size[1] = 4;
+ break;
+ case 2: /* 8 & 64 */
+ snes_ppu.oam.size[0] = 1;
+ snes_ppu.oam.size[1] = 8;
+ break;
+ case 3: /* 16 & 32 */
+ snes_ppu.oam.size[0] = 2;
+ snes_ppu.oam.size[1] = 4;
+ break;
+ case 4: /* 16 & 64 */
+ snes_ppu.oam.size[0] = 2;
+ snes_ppu.oam.size[1] = 8;
+ break;
+ case 5: /* 32 & 64 */
+ snes_ppu.oam.size[0] = 4;
+ snes_ppu.oam.size[1] = 8;
+ break;
+ default:
+ /* Unknown size so default to 8 & 16 */
+ snes_ppu.oam.size[0] = 1;
+ snes_ppu.oam.size[1] = 2;
+#ifdef SNES_DBG_REG_W
+ mame_printf_debug( "Object size unsupported: %d\n", (data & 0xe0) >> 5 );
+#endif
+ }
+ break;
+ case OAMADDL: /* Address for accessing OAM (low) */
+ snes_ppu.oam.address_low = data;
+ snes_ppu.oam.address = ((snes_ppu.oam.address_high & 0x1) << 8) + data;
+ snes_ram[OAMDATA] = 0;
+ break;
+ case OAMADDH: /* Address for accessing OAM (high) */
+ snes_ppu.oam.address_high = data & 0x1;
+ snes_ppu.oam.address = ((data & 0x1) << 8) + snes_ppu.oam.address_low;
+ snes_ppu.oam.priority_rotation = (data & 0x80) ? 1 : 0;
+ snes_ram[OAMDATA] = 0;
+ break;
+ case OAMDATA: /* Data for OAM write (DW) */
+ {
+ int oam_addr = snes_ppu.oam.address;
+
+ if (oam_addr >= 0x100)
+ {
+ oam_addr &= 0x10f;
+ if (!(snes_ram[OAMDATA]))
+ {
+ snes_oam[oam_addr] &= 0xff00;
+ snes_oam[oam_addr] |= data;
+ }
+ else
+ {
+ snes_oam[oam_addr] &= 0x00ff;
+ snes_oam[oam_addr] |= (data<<8);
+ }
+ }
+ else
+ {
+ oam_addr &= 0x1ff;
+ if (!(snes_ram[OAMDATA]))
+ {
+ snes_ppu.oam.write_latch = data;
+ }
+ else
+ {
+ snes_oam[oam_addr] = (data<<8) | snes_ppu.oam.write_latch;
+ }
+ }
+ snes_ram[OAMDATA] = (snes_ram[OAMDATA] + 1) % 2;
+ if( snes_ram[OAMDATA] == 0 )
+ {
+ snes_ram[OAMDATA] = 0;
+ snes_ppu.oam.address++;
+ snes_ppu.oam.address_low = snes_ram[OAMADDL] = snes_ppu.oam.address & 0xff;
+ snes_ppu.oam.address_high = snes_ram[OAMADDH] = (snes_ppu.oam.address >> 8) & 0x1;
+ }
+ return;
+ }
+ case BGMODE: /* BG mode and character size settings */
+ snes_ppu.mode = data & 0x7;
+ {
+ screen_state *state = &Machine->screen[0];
+ rectangle visarea = state->visarea;
+
+ visarea.min_x = visarea.min_y = 0;
+ visarea.max_y = snes_ppu.beam.last_visible_line - 1;
+
+ // fixme: should compensate for SNES_DBG_video
+ if( snes_ppu.mode == 5 || snes_ppu.mode == 6 )
+ {
+ visarea.max_x = (SNES_SCR_WIDTH * 2) - 1;
+ snes_htmult = 2;
+ }
+ else
+ {
+ visarea.max_x = SNES_SCR_WIDTH - 1;
+ snes_htmult = 1;
+ }
+
+ if ((snes_ram[STAT78] & 0x10) == SNES_NTSC)
+ {
+ video_screen_configure(0, SNES_HTOTAL*snes_htmult, SNES_VTOTAL_NTSC, &visarea, Machine->screen[0].refresh);
+ }
+ else
+ {
+ video_screen_configure(0, SNES_HTOTAL*snes_htmult, SNES_VTOTAL_PAL, &visarea, Machine->screen[0].refresh);
+ }
+ }
+
+ snes_ppu.layer[0].tile_size = (data >> 4) & 0x1;
+ snes_ppu.layer[1].tile_size = (data >> 5) & 0x1;
+ snes_ppu.layer[2].tile_size = (data >> 6) & 0x1;
+ snes_ppu.layer[3].tile_size = (data >> 7) & 0x1;
+ snes_ppu.update_offsets = 1;
+ break;
+ case MOSAIC: /* Size and screen designation for mosaic */
+ /* FIXME: We don't support horizontal mosaic yet */
+ break;
+ case BG1SC: /* Address for storing SC data BG1 SC size designation */
+ case BG2SC: /* Address for storing SC data BG2 SC size designation */
+ case BG3SC: /* Address for storing SC data BG3 SC size designation */
+ case BG4SC: /* Address for storing SC data BG4 SC size designation */
+ snes_ppu.layer[offset - BG1SC].map = (data & 0xfc) << 9;
+ snes_ppu.layer[offset - BG1SC].map_size = data & 0x3;
+ break;
+ case BG12NBA: /* Address for BG 1 and 2 character data */
+ snes_ppu.layer[0].data = (data & 0xf) << 13;
+ snes_ppu.layer[1].data = (data & 0xf0) << 9;
+ break;
+ case BG34NBA: /* Address for BG 3 and 4 character data */
+ snes_ppu.layer[2].data = (data & 0xf) << 13;
+ snes_ppu.layer[3].data = (data & 0xf0) << 9;
+ break;
+
+ // Anomie says "Current = (Byte<<8) | (Prev&~7) | ((Current>>8)&7);"
+ case BG1HOFS: /* BG1 - horizontal scroll (DW) */
+ snes_ppu.layer[0].offset.horizontal = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[0].offset.horizontal>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case BG1VOFS: /* BG1 - vertical scroll (DW) */
+ snes_ppu.layer[0].offset.vertical = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[0].offset.vertical>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case BG2HOFS: /* BG2 - horizontal scroll (DW) */
+ snes_ppu.layer[1].offset.horizontal = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[1].offset.horizontal>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case BG2VOFS: /* BG2 - vertical scroll (DW) */
+ snes_ppu.layer[1].offset.vertical = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[1].offset.vertical>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case BG3HOFS: /* BG3 - horizontal scroll (DW) */
+ snes_ppu.layer[2].offset.horizontal = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[2].offset.horizontal>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case BG3VOFS: /* BG3 - vertical scroll (DW) */
+ snes_ppu.layer[2].offset.vertical = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[2].offset.vertical>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case BG4HOFS: /* BG4 - horizontal scroll (DW) */
+ snes_ppu.layer[3].offset.horizontal = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[3].offset.horizontal>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case BG4VOFS: /* BG4 - vertical scroll (DW) */
+ snes_ppu.layer[3].offset.vertical = (data<<8) | (ppu_last_scroll & ~7) | ((snes_ppu.layer[3].offset.vertical>>8) & 7);
+ ppu_last_scroll = data;
+ snes_ppu.update_offsets = 1;
+ return;
+ case VMAIN: /* VRAM address increment value designation */
+ vram_fgr_high = (data & 0x80);
+ vram_fgr_increment = vram_fgr_inctab[data & 3];
+
+ if (data & 0xc)
+ {
+ int md = (data & 0xc)>>2;
+
+ vram_fgr_count = vram_fgr_inccnts[md];
+ vram_fgr_mask = (vram_fgr_count*8)-1;
+ vram_fgr_shift = vram_fgr_shiftab[md];
+ }
+ else
+ {
+ vram_fgr_count = 0;
+ }
+// printf("VMAIN: high %x inc %x count %x mask %x shift %x\n", vram_fgr_high, vram_fgr_increment, vram_fgr_count, vram_fgr_mask, vram_fgr_shift);
+ break;
+ case VMADDL: /* Address for VRAM read/write (low) */
+ case VMADDH: /* Address for VRAM read/write (high) */
+ {
+ UINT32 addr;
+
+ snes_ram[offset] = data;
+ addr = (snes_ram[VMADDH] << 8) | snes_ram[VMADDL];
+
+ if (vram_fgr_count)
+ {
+ UINT32 rem = addr & vram_fgr_mask;
+ UINT32 faddr = (addr & ~vram_fgr_mask) + (rem >> vram_fgr_shift) +
+ ((rem & (vram_fgr_count - 1)) << 3);
+
+ vram_read_buffer = snes_vram[(faddr<<1)&0xffff] | snes_vram[((faddr<<1)+1) & 0xffff]<<8;
+ }
+ else
+ {
+ vram_read_buffer = snes_vram[(addr<<1)&0xffff] | snes_vram[((addr<<1)+1) & 0xffff]<<8;
+ }
+
+ }
+ break;
+ case VMDATAL: /* 2118: Data for VRAM write (low) */
+ {
+ UINT32 addr = (snes_ram[VMADDH] << 8) | snes_ram[VMADDL];
+
+ if (vram_fgr_count)
+ {
+ UINT32 rem = addr & vram_fgr_mask;
+ UINT32 faddr = (addr & ~vram_fgr_mask) + (rem >> vram_fgr_shift) +
+ ((rem & (vram_fgr_count - 1)) << 3);
+
+ snes_vram[(faddr<<1)&0xffff] = data;
+ }
+ else
+ {
+ snes_vram[(addr<<1)&0xffff] = data;
+ }
+
+ if (!vram_fgr_high)
+ {
+ addr += vram_fgr_increment;
+ snes_ram[VMADDL] = addr&0xff;
+ snes_ram[VMADDH] = (addr>>8)&0xff;
+ }
+ }
+ return;
+ case VMDATAH: /* 2119: Data for VRAM write (high) */
+ {
+ UINT32 addr = (snes_ram[VMADDH] << 8) | snes_ram[VMADDL];
+
+ if (vram_fgr_count)
+ {
+ UINT32 rem = addr & vram_fgr_mask;
+ UINT32 faddr = (addr & ~vram_fgr_mask) + (rem >> vram_fgr_shift) +
+ ((rem & (vram_fgr_count - 1)) << 3);
+
+ snes_vram[((faddr<<1)+1)&0xffff] = data;
+ }
+ else
+ {
+ snes_vram[((addr<<1)+1)&0xffff] = data;
+ }
+
+ if (vram_fgr_high)
+ {
+ addr += vram_fgr_increment;
+ snes_ram[VMADDL] = addr&0xff;
+ snes_ram[VMADDH] = (addr>>8)&0xff;
+ }
+ }
+ return;
+ case M7SEL: /* Mode 7 initial settings */
+ break;
+ case M7A: /* Mode 7 COS angle/x expansion (DW) */
+ snes_ppu.mode7.matrix_a = ((snes_ppu.mode7.matrix_a >> 8) & 0xff) + (data << 8);
+ break;
+ case M7B: /* Mode 7 SIN angle/ x expansion (DW) */
+ snes_ppu.mode7.matrix_b = ((snes_ppu.mode7.matrix_b >> 8) & 0xff) + (data << 8);
+ break;
+ case M7C: /* Mode 7 SIN angle/y expansion (DW) */
+ snes_ppu.mode7.matrix_c = ((snes_ppu.mode7.matrix_c >> 8) & 0xff) + (data << 8);
+ break;
+ case M7D: /* Mode 7 COS angle/y expansion (DW) */
+ snes_ppu.mode7.matrix_d = ((snes_ppu.mode7.matrix_d >> 8) & 0xff) + (data << 8);
+ break;
+ case M7X: /* Mode 7 x center position (DW) */
+ snes_ppu.mode7.origin_x = ((snes_ppu.mode7.origin_x >> 8) & 0xff) + (data << 8);
+ break;
+ case M7Y: /* Mode 7 y center position (DW) */
+ snes_ppu.mode7.origin_y = ((snes_ppu.mode7.origin_y >> 8) & 0xff) + (data << 8);
+ break;
+ case CGADD: /* Initial address for colour RAM writing */
+ /* CGRAM is 16-bit, but when reading/writing we treat it as
+ * 8-bit, so we need to double the address */
+ cgram_address = data << 1;
+ break;
+ case CGDATA: /* Data for colour RAM */
+ ((UINT8 *)snes_cgram)[cgram_address] = data;
+ cgram_address = (cgram_address + 1) % (SNES_CGRAM_SIZE - 2);
+ snes_ppu.update_palette = 1;
+ break;
+ case W12SEL: /* Window mask settings for BG1-2 */
+ case W34SEL: /* Window mask settings for BG3-4 */
+ case WOBJSEL: /* Window mask settings for objects */
+ case WH0: /* Window 1 left position */
+ case WH1: /* Window 1 right position */
+ case WH2: /* Window 2 left position */
+ case WH3: /* Window 2 right position */
+ case WBGLOG: /* Window mask logic for BG's */
+ case WOBJLOG: /* Window mask logic for objects */
+ if( data != snes_ram[offset] )
+ snes_ppu.update_windows = 1;
+ break;
+ case TM: /* Main screen designation */
+ case TS: /* Subscreen designation */
+ case TMW: /* Window mask for main screen designation */
+ case TSW: /* Window mask for subscreen designation */
+ break;
+ case CGWSEL: /* Initial settings for Fixed colour addition or screen addition */
+ /* FIXME: We don't support direct select for modes 3 & 4 or subscreen window stuff */
+#ifdef SNES_DBG_REG_W
+ if( (data & 0x2) != (snes_ram[CGWSEL] & 0x2) )
+ mame_printf_debug( "Add/Sub Layer: %s\n", ((data & 0x2) >> 1) ? "Subscreen" : "Fixed colour" );
+#endif
+ break;
+ case CGADSUB: /* Addition/Subtraction designation for each screen */
+ {
+ UINT8 sub = (data & 0x80) >> 7;
+ snes_ppu.layer[0].blend = (data & 0x1) << sub;
+ snes_ppu.layer[1].blend = ((data & 0x2) >> 1) << sub;
+ snes_ppu.layer[2].blend = ((data & 0x4) >> 2) << sub;
+ snes_ppu.layer[3].blend = ((data & 0x8) >> 3) << sub;
+ snes_ppu.layer[4].blend = ((data & 0x10) >> 4) << sub;
+ } break;
+ case COLDATA: /* Fixed colour data for fixed colour addition/subtraction */
+ {
+ /* Store it in the extra space we made in the CGRAM
+ * It doesn't really go there, but it's as good a place as any. */
+ UINT8 r,g,b,fade;
+
+ /* Get existing value. */
+ r = snes_cgram[FIXED_COLOUR] & 0x1f;
+ g = (snes_cgram[FIXED_COLOUR] & 0x3e0) >> 5;
+ b = (snes_cgram[FIXED_COLOUR] & 0x7c00) >> 10;
+ /* Set new value */
+ if( data & 0x20 )
+ r = data & 0x1f;
+ if( data & 0x40 )
+ g = data & 0x1f;
+ if( data & 0x80 )
+ b = data & 0x1f;
+ snes_cgram[FIXED_COLOUR] = (r | (g << 5) | (b << 10));
+
+ /* set the palette entry, adjusting to the fade setting */
+ fade = (snes_ram[INIDISP] & 0xf) + 1;
+ r = (r * fade) >> 4;
+ g = (g * fade) >> 4;
+ b = (b * fade) >> 4;
+ /* palette hacks! */
+ ((pen_t *)Machine->remapped_colortable)[FIXED_COLOUR] = ((r & 0x1f) | ((g & 0x1f) << 5) | ((b & 0x1f) << 10));
+ } break;
+ case SETINI: /* Screen mode/video select */
+ /* FIXME: We only support line count here */
+ snes_ppu.beam.last_visible_line = (data & 0x4) ? 240 : 225;
+#ifdef SNES_DBG_REG_W
+ if( (data & 0x8) != (snes_ram[SETINI] & 0x8) )
+ mame_printf_debug( "Pseudo 512 mode: %s\n", (data & 0x8) ? "on" : "off" );
+#endif
+ break;
+ case WMDATA: /* Data to write to WRAM */
+ {
+ UINT32 addr = ((snes_ram[WMADDH] & 0x1) << 16) | (snes_ram[WMADDM] << 8) | snes_ram[WMADDL];
+ program_write_byte(0x7e0000 + addr++, data );
+ addr &= 0x1ffff;
+ snes_ram[WMADDH] = (addr >> 16) & 0x1;
+ snes_ram[WMADDM] = (addr >> 8) & 0xff;
+ snes_ram[WMADDL] = addr & 0xff;
+ return;
+ }
+ case WMADDL: /* Address to read/write to wram (low) */
+ case WMADDM: /* Address to read/write to wram (mid) */
+ case WMADDH: /* Address to read/write to wram (high) */
+ break;
+ case OLDJOY1: /* Old NES joystick support */
+ if( (data & 0x1) && !(snes_ram[offset] & 0x1) )
+ {
+ joypad[0].oldrol = 0;
+ joypad[1].oldrol = 0;
+ joypad[2].oldrol = 0;
+ joypad[3].oldrol = 0;
+ }
+ break;
+ case NMITIMEN: /* Flag for v-blank, timer int. and joy read */
+ case OLDJOY2: /* Old NES joystick support */
+ break;
+ case WRIO: /* Programmable I/O port - latches H/V counters on a 1->0 transition */
+ if (!(snes_ram[WRIO] & 0x80) && (data & 0x80))
+ {
+ // external latch
+ snes_latch_counters();
+ }
+ case WRMPYA: /* Multiplier A */
+ break;
+ case WRMPYB: /* Multiplier B */
+ {
+ UINT32 c = snes_ram[WRMPYA] * data;
+ snes_ram[RDMPYL] = c & 0xff;
+ snes_ram[RDMPYH] = (c >> 8) & 0xff;
+ } break;
+ case WRDIVL: /* Dividend (low) */
+ case WRDIVH: /* Dividend (high) */
+ break;
+ case WRDVDD: /* Divisor */
+ {
+ UINT16 value, dividend, remainder;
+ dividend = remainder = 0;
+ value = (snes_ram[WRDIVH] << 8) + snes_ram[WRDIVL];
+ if( data > 0 )
+ {
+ dividend = value / data;
+ remainder = value % data;
+ }
+ else
+ {
+ dividend = 0xffff;
+ remainder = value;
+ }
+ snes_ram[RDDIVL] = dividend & 0xff;
+ snes_ram[RDDIVH] = (dividend >> 8) & 0xff;
+ snes_ram[RDMPYL] = remainder & 0xff;
+ snes_ram[RDMPYH] = (remainder >> 8) & 0xff;
+ } break;
+ case HTIMEL: /* H-Count timer settings (low) */
+ case HTIMEH: /* H-Count timer settings (high) */
+ case VTIMEL: /* V-Count timer settings (low) */
+ case VTIMEH: /* V-Count timer settings (high) */
+ break;
+ case MDMAEN: /* GDMA channel designation and trigger */
+ snes_gdma( data );
+ data = 0; /* Once DMA is done we need to reset all bits to 0 */
+ break;
+ case HDMAEN: /* HDMA channel designation */
+ break;
+ case MEMSEL: /* Access cycle designation in memory (2) area */
+ /* FIXME: Need to adjust the speed only during access of banks 0x80+
+ * Currently we are just increasing it no matter what */
+// cpunum_set_clockscale( 0, (data & 0x1) ? 1.335820896 : 1.0 );
+#ifdef SNES_DBG_REG_W
+ if( (data & 0x1) != (snes_ram[MEMSEL] & 0x1) )
+ mame_printf_debug( "CPU speed: %f Mhz\n", (data & 0x1) ? 3.58 : 2.68 );
+#endif
+ break;
+ /* Following are read-only */
+ case HVBJOY: /* H/V blank and joypad enable */
+ case MPYL: /* Multiplication result (low) */
+ case MPYM: /* Multiplication result (mid) */
+ case MPYH: /* Multiplication result (high) */
+ case RDIO:
+ case RDDIVL:
+ case RDDIVH:
+ case RDMPYL:
+ case RDMPYH:
+ case JOY1L:
+ case JOY1H:
+ case JOY2L:
+ case JOY2H:
+ case JOY3L:
+ case JOY3H:
+ case JOY4L:
+ case JOY4H:
+#ifdef MAME_DEBUG
+ logerror( "Write to read-only register: %X value: %X", offset, data );
+#endif /* MAME_DEBUG */
+ return;
+ /* Below is all DMA related */
+ case DMAP0: case BBAD0: case A1T0L: case A1T0H: case A1B0: case DAS0L:
+ case DAS0H: case DSAB0: case A2A0L: case A2A0H: case NTRL0:
+ case DMAP1: case BBAD1: case A1T1L: case A1T1H: case A1B1: case DAS1L:
+ case DAS1H: case DSAB1: case A2A1L: case A2A1H: case NTRL1:
+ case DMAP2: case BBAD2: case A1T2L: case A1T2H: case A1B2: case DAS2L:
+ case DAS2H: case DSAB2: case A2A2L: case A2A2H: case NTRL2:
+ case DMAP3: case BBAD3: case A1T3L: case A1T3H: case A1B3: case DAS3L:
+ case DAS3H: case DSAB3: case A2A3L: case A2A3H: case NTRL3:
+ case DMAP4: case BBAD4: case A1T4L: case A1T4H: case A1B4: case DAS4L:
+ case DAS4H: case DSAB4: case A2A4L: case A2A4H: case NTRL4:
+ case DMAP5: case BBAD5: case A1T5L: case A1T5H: case A1B5: case DAS5L:
+ case DAS5H: case DSAB5: case A2A5L: case A2A5H: case NTRL5:
+ case DMAP6: case BBAD6: case A1T6L: case A1T6H: case A1B6: case DAS6L:
+ case DAS6H: case DSAB6: case A2A6L: case A2A6H: case NTRL6:
+ case DMAP7: case BBAD7: case A1T7L: case A1T7H: case A1B7: case DAS7L:
+ case DAS7H: case DSAB7: case A2A7L: case A2A7H: case NTRL7:
+ break;
+ }
+
+ snes_ram[offset] = data;
+}
+
+/* This function checks everything is in a valid range and returns how
+ * 'valid' this section is as an information block. */
+int snes_validate_infoblock( UINT8 *infoblock, UINT16 offset )
+{
+ INT8 valid = 6;
+
+ /* Check the CRC and inverse CRC */
+ if( ((infoblock[offset + 0x1c] + (infoblock[offset + 0x1d] << 8)) |
+ (infoblock[offset + 0x1e] + (infoblock[offset + 0x1f] << 8))) != 0xffff )
+ {
+ valid -= 3;
+ }
+ /* Check the ROM Size is in a valid range */
+ if( infoblock[offset + 0x17] > 13 )
+ {
+ valid--;
+ }
+ /* Check the SRAM size */
+ if( infoblock[offset + 0x18] > 8 )
+ {
+ valid--;
+ }
+ /* Check the Country is in a valid range */
+ if( infoblock[offset + 0x19] > 13 )
+ {
+ valid--;
+ }
+ /* Check the game version */
+ if( infoblock[offset + 0x1b] >= 128 )
+ {
+ valid--;
+ }
+
+ if( valid < 0 )
+ {
+ valid = 0;
+ }
+
+ return valid;
+}
+
+#ifndef MESS
+/* for mame we use an init, maybe we will need more for the different games */
+DRIVER_INIT( snes )
+{
+ int i;
+ UINT16 totalblocks, readblocks;
+ UINT8 *rom;
+
+ rom = memory_region( REGION_USER3 );
+ snes_ram = auto_malloc(0x1000000);
+ memset( snes_ram, 0, 0x1000000 );
+
+ /* all NSS games seem to use MODE 20 */
+ snes_cart.mode = SNES_MODE_20;
+ snes_cart.sram_max = 0x40000;
+
+ /* Find the number of blocks in this ROM */
+ //totalblocks = ((mame_fsize(file) - offset) >> (snes_cart.mode == MODE_20 ? 15 : 16));
+ totalblocks = (memory_region_length(REGION_USER3) / 0x8000) - 1;
+
+ /* FIXME: Insert crc check here */
+
+ readblocks = 0;
+ {
+ /* In mode 20, all blocks are 32kb. There are upto 96 blocks, giving a
+ * total of 24mbit(3mb) of ROM.
+ * The first 48 blocks are located in banks 0x00 to 0x2f at address
+ * 0x8000. They are mirrored in banks 0x80 to 0xaf.
+ * The next 16 blocks are located in banks 0x30 to 0x3f at address
+ * 0x8000. They are mirrored in banks 0xb0 to 0xbf.
+ * The final 32 blocks are located in banks 0x40 - 0x5f at address
+ * 0x8000. They are mirrored in banks 0xc0 to 0xdf.
+ */
+ i = 0;
+ while( i < 96 && readblocks <= totalblocks )
+ {
+ //mame_fread( file, &snes_ram[(i++ * 0x10000) + 0x8000], 0x8000);
+ memcpy(&snes_ram[(i * 0x10000) + 0x8000], &rom[i * 0x8000], 0x8000);
+ i++;
+ readblocks++;
+ }
+ }
+
+ /* Find the amount of sram */
+ snes_cart.sram = snes_r_bank1(0x00ffd8);
+ if( snes_cart.sram > 0 )
+ {
+ snes_cart.sram = ((1 << (snes_cart.sram + 3)) / 8);
+ if( snes_cart.sram > snes_cart.sram_max )
+ snes_cart.sram = snes_cart.sram_max;
+ }
+}
+
+DRIVER_INIT( snes_hirom )
+{
+ int i;
+ UINT16 totalblocks, readblocks;
+ UINT8 *rom;
+
+ rom = memory_region( REGION_USER3 );
+ snes_ram = auto_malloc(0x1000000);
+ memset( snes_ram, 0, 0x1000000 );
+
+ snes_cart.mode = SNES_MODE_21;
+ snes_cart.sram_max = 0x40000;
+
+ /* Find the number of blocks in this ROM */
+ //totalblocks = ((mame_fsize(file) - offset) >> (snes_cart.mode == MODE_20 ? 15 : 16));
+ totalblocks = (memory_region_length(REGION_USER3) / 0x10000) - 1;
+
+ /* FIXME: Insert crc check here */
+
+ readblocks = 0;
+ {
+ i = 0;
+ while( i < 64 && readblocks <= totalblocks )
+ {
+ memcpy( &snes_ram[0xc00000 + (i * 0x10000)], &rom[i * 0x10000], 0x10000);
+ i++;
+ readblocks++;
+ }
+ }
+
+ /* Find the amount of sram */
+ snes_cart.sram = snes_r_bank1(0x00ffd8);
+ if( snes_cart.sram > 0 )
+ {
+ snes_cart.sram = ((1 << (snes_cart.sram + 3)) / 8);
+ if( snes_cart.sram > snes_cart.sram_max )
+ snes_cart.sram = snes_cart.sram_max;
+ }
+}
+#endif /* MESS */
+
+void snes_hdma_init()
+{
+ UINT8 mask = 1, dma = 0, i;
+
+ snes_hdma_chnl = snes_ram[HDMAEN];
+ for( i = 0; i < 8; i++ )
+ {
+ if( snes_ram[HDMAEN] & mask )
+ {
+ snes_ram[SNES_DMA_BASE + dma + 8] = snes_ram[SNES_DMA_BASE + dma + 2];
+ snes_ram[SNES_DMA_BASE + dma + 9] = snes_ram[SNES_DMA_BASE + dma + 3];
+ snes_ram[SNES_DMA_BASE + dma + 0xa] = 0;
+ }
+ dma += 0x10;
+ mask <<= 1;
+ }
+}
+
+void snes_hdma()
+{
+ UINT8 mask = 1, dma = 0, i, contmode;
+ UINT16 bbus;
+ UINT32 abus;
+
+ /* Assume priority of the 8 DMA channels is 0-7 */
+ for( i = 0; i < 8; i++ )
+ {
+ if( snes_hdma_chnl & mask )
+ {
+ /* Check if we need to read a new line from the table */
+ if( !(snes_ram[SNES_DMA_BASE + dma + 0xa] & 0x7f ) )
+ {
+ abus = (snes_ram[SNES_DMA_BASE + dma + 4] << 16) + (snes_ram[SNES_DMA_BASE + dma + 9] << 8) + snes_ram[SNES_DMA_BASE + dma + 8];
+
+ /* Get the number of lines */
+ snes_ram[SNES_DMA_BASE + dma + 0xa] = program_read_byte(abus);
+ if( !snes_ram[SNES_DMA_BASE + dma + 0xa] )
+ {
+ /* No more lines so clear HDMA */
+ snes_hdma_chnl &= ~mask;
+ continue;
+ }
+ abus++;
+ snes_ram[SNES_DMA_BASE + dma + 8] = abus & 0xff;
+ snes_ram[SNES_DMA_BASE + dma + 9] = (abus >> 8) & 0xff;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x40 )
+ {
+ snes_ram[SNES_DMA_BASE + dma + 5] = program_read_byte(abus++);
+ snes_ram[SNES_DMA_BASE + dma + 6] = program_read_byte(abus++);
+ snes_ram[SNES_DMA_BASE + dma + 8] = abus & 0xff;
+ snes_ram[SNES_DMA_BASE + dma + 9] = (abus >> 8) & 0xff;
+ }
+ }
+
+ contmode = (--snes_ram[SNES_DMA_BASE + dma + 0xa]) & 0x80;
+
+ /* Transfer addresses */
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x40 ) /* Indirect */
+ abus = (snes_ram[SNES_DMA_BASE + dma + 7] << 16) + (snes_ram[SNES_DMA_BASE + dma + 6] << 8) + snes_ram[SNES_DMA_BASE + dma + 5];
+ else /* Absolute */
+ abus = (snes_ram[SNES_DMA_BASE + dma + 4] << 16) + (snes_ram[SNES_DMA_BASE + dma + 9] << 8) + snes_ram[SNES_DMA_BASE + dma + 8];
+ bbus = 0x2100 + snes_ram[SNES_DMA_BASE + dma + 1];
+
+#ifdef SNES_DBG_HDMA
+ mame_printf_debug( "HDMA-Ch: %d(%s) abus: %X bbus: %X type: %d(%X %X)\n", i, snes_ram[SNES_DMA_BASE + dma] & 0x40 ? "Indirect" : "Absolute", abus, bbus, snes_ram[SNES_DMA_BASE + dma] & 0x7, snes_ram[SNES_DMA_BASE + dma + 8],snes_ram[SNES_DMA_BASE + dma + 9] );
+#endif
+
+ switch( snes_ram[SNES_DMA_BASE + dma] & 0x7 )
+ {
+ case 0: /* 1 address */
+ {
+ program_write_byte(bbus, program_read_byte(abus++));
+ } break;
+ case 5: /* 4 bytes to 2 addresses (l,h,l,h) */
+ {
+ program_write_byte(bbus, program_read_byte(abus++));
+ program_write_byte(bbus + 1, program_read_byte(abus++));
+ program_write_byte(bbus, program_read_byte(abus++));
+ program_write_byte(bbus + 1, program_read_byte(abus++));
+ } break;
+ case 1: /* 2 addresses (l,h) */
+ {
+ program_write_byte(bbus, program_read_byte(abus++));
+ program_write_byte(bbus + 1, program_read_byte(abus++));
+ } break;
+ case 2: /* Write twice (l,l) */
+ case 6:
+ {
+ program_write_byte(bbus, program_read_byte(abus++));
+ program_write_byte(bbus, program_read_byte(abus++));
+ } break;
+ case 3: /* 2 addresses/Write twice (l,l,h,h) */
+ case 7:
+ {
+ program_write_byte(bbus, program_read_byte(abus++));
+ program_write_byte(bbus, program_read_byte(abus++));
+ program_write_byte(bbus + 1, program_read_byte(abus++));
+ program_write_byte(bbus + 1, program_read_byte(abus++));
+ } break;
+ case 4: /* 4 addresses (l,h,l,h) */
+ {
+ program_write_byte(bbus, program_read_byte(abus++));
+ program_write_byte(bbus + 1, program_read_byte(abus++));
+ program_write_byte(bbus + 2, program_read_byte(abus++));
+ program_write_byte(bbus + 3, program_read_byte(abus++));
+ } break;
+ default:
+#ifdef MAME_DEBUG
+ mame_printf_debug( " HDMA of unsupported type: %d\n", snes_ram[SNES_DMA_BASE + dma] & 0x7 );
+#endif
+ break;
+ }
+
+ /* Update address */
+ if( contmode )
+ {
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x40 ) /* Indirect */
+ {
+ snes_ram[SNES_DMA_BASE + dma + 5] = abus & 0xff;
+ snes_ram[SNES_DMA_BASE + dma + 6] = (abus >> 8) & 0xff;
+ }
+ else /* Absolute */
+ {
+ snes_ram[SNES_DMA_BASE + dma + 8] = abus & 0xff;
+ snes_ram[SNES_DMA_BASE + dma + 9] = (abus >> 8) & 0xff;
+ }
+ }
+
+ if( !(snes_ram[SNES_DMA_BASE + dma + 0xa] & 0x7f) )
+ {
+ if( !(snes_ram[SNES_DMA_BASE + dma] & 0x40) ) /* Absolute */
+ {
+ if( !contmode )
+ {
+ snes_ram[SNES_DMA_BASE + dma + 8] = abus & 0xff;
+ snes_ram[SNES_DMA_BASE + dma + 9] = (abus >> 8) & 0xff;
+ }
+ }
+ }
+ }
+ dma += 0x10;
+ mask <<= 1;
+ }
+}
+
+void snes_gdma( UINT8 channels )
+{
+ UINT8 mask = 1, dma = 0, i;
+ INT8 increment;
+ UINT16 bbus;
+ UINT32 abus, length;
+
+ /* Assume priority of the 8 DMA channels is 0-7 */
+ for( i = 0; i < 8; i++ )
+ {
+ if( channels & mask )
+ {
+ /* Find transfer addresses */
+ abus = (snes_ram[SNES_DMA_BASE + dma + 4] << 16) + (snes_ram[SNES_DMA_BASE + dma + 3] << 8) + snes_ram[SNES_DMA_BASE + dma + 2];
+ bbus = 0x2100 + snes_ram[SNES_DMA_BASE + dma + 1];
+
+ /* Auto increment */
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x8 )
+ {
+ increment = 0;
+ }
+ else
+ {
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x10 )
+ increment = -1;
+ else
+ increment = 1;
+ }
+
+ /* Number of bytes to transfer */
+ length = (snes_ram[SNES_DMA_BASE + dma + 6] << 8) + snes_ram[SNES_DMA_BASE + dma + 5];
+ if( !length )
+ length = 0x10000; /* 0x0000 really means 0x10000 */
+
+#ifdef SNES_DBG_GDMA
+ mame_printf_debug( "GDMA-Ch %d: len: %X, abus: %X, bbus: %X, incr: %d, dir: %s, type: %d\n", i, length, abus, bbus, increment, snes_ram[SNES_DMA_BASE + dma] & 0x80 ? "PPU->CPU" : "CPU->PPU", snes_ram[SNES_DMA_BASE + dma] & 0x7 );
+#endif
+
+ switch( snes_ram[SNES_DMA_BASE + dma] & 0x7 )
+ {
+ case 0: /* 1 address */
+ case 2: /* 1 address ?? */
+ case 6:
+ {
+ while( length-- )
+ {
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus) );
+ else /* CPU->PPU */
+ program_write_byte(bbus, program_read_byte(abus) );
+ abus += increment;
+ }
+ } break;
+ case 1: /* 2 addresses (l,h) */
+ case 5:
+ {
+ while( length-- )
+ {
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus) );
+ else /* CPU->PPU */
+ program_write_byte(bbus, program_read_byte(abus) );
+ abus += increment;
+ if( !(length--) )
+ break;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus + 1) );
+ else /* CPU->PPU */
+ program_write_byte(bbus + 1, program_read_byte(abus) );
+ abus += increment;
+ }
+ } break;
+ case 3: /* 2 addresses/write twice (l,l,h,h) */
+ case 7:
+ {
+ while( length-- )
+ {
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus) );
+ else /* CPU->PPU */
+ program_write_byte(bbus, program_read_byte(abus) );
+ abus += increment;
+ if( !(length--) )
+ break;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus) );
+ else /* CPU->PPU */
+ program_write_byte(bbus, program_read_byte(abus) );
+ abus += increment;
+ if( !(length--) )
+ break;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus + 1) );
+ else /* CPU->PPU */
+ program_write_byte(bbus + 1, program_read_byte(abus) );
+ abus += increment;
+ if( !(length--) )
+ break;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus + 1) );
+ else /* CPU->PPU */
+ program_write_byte(bbus + 1, program_read_byte(abus) );
+ abus += increment;
+ }
+ } break;
+ case 4: /* 4 addresses (l,h,l,h) */
+ {
+ while( length-- )
+ {
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus) );
+ else /* CPU->PPU */
+ program_write_byte(bbus, program_read_byte(abus) );
+ abus += increment;
+ if( !(length--) )
+ break;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus + 1) );
+ else /* CPU->PPU */
+ program_write_byte(bbus + 1, program_read_byte(abus) );
+ abus += increment;
+ if( !(length--) )
+ break;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus + 2) );
+ else /* CPU->PPU */
+ program_write_byte(bbus + 2, program_read_byte(abus) );
+ abus += increment;
+ if( !(length--) )
+ break;
+ if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */
+ program_write_byte(abus, program_read_byte(bbus + 3) );
+ else /* CPU->PPU */
+ program_write_byte(bbus + 3, program_read_byte(abus) );
+ abus += increment;
+ }
+ } break;
+ default:
+#ifdef MAME_DEBUG
+ mame_printf_debug( " GDMA of unsupported type: %d\n", snes_ram[SNES_DMA_BASE + dma] & 0x7 );
+#endif
+ break;
+ }
+ /* We're done so write the new abus back to the registers */
+ snes_ram[SNES_DMA_BASE + dma + 2] = abus & 0xff;
+ snes_ram[SNES_DMA_BASE + dma + 3] = (abus >> 8) & 0xff;
+ snes_ram[SNES_DMA_BASE + dma + 5] = 0;
+ snes_ram[SNES_DMA_BASE + dma + 6] = 0;
+ }
+ dma += 0x10;
+ mask <<= 1;
+ }
+}
diff --git a/src/mame/machine/snesdsp1.c b/src/mame/machine/snesdsp1.c
new file mode 100644
index 00000000000..81555e5a0fa
--- /dev/null
+++ b/src/mame/machine/snesdsp1.c
@@ -0,0 +1,1268 @@
+/***************************************************************************
+
+ snesdsp1.c
+
+ File to handle emulation of the SNES "DSP-1" add-on chip.
+
+ R. Belmont
+ Code from http://users.tpg.com.au/trauma/dsp/dsp1.html
+ By The Dumper (Electrical Engineering), Neviksti (Physics), Overload (Computer Science), Andreas Naive (Mathematics)
+
+ This is up to date with the source version that was posted May 29, 2006.
+
+***************************************************************************/
+
+static INT16 dsp1_waitcmd, dsp1_in_cnt, dsp1_out_cnt, dsp1_in_idx, dsp1_out_idx, dsp1_first_parm, dsp1_cur_cmd;
+static int has_dsp1;
+static UINT8 dsp1_in[32], dsp1_out[16];
+
+#define DSP1_VERSION 0x0102
+
+// 1FH - Memory Dump (DSP1B Data ROM)
+// Input byte(1FH) integer(Undefined)
+// Output integer[1024]
+
+static UINT16 DSP1ROM[1024];
+
+// Command Translation Table
+
+static const INT16 DSP1_CmdTable[64] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0001, 0x0006, 0x000f,
+ 0x0008, 0x000d, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
+ 0x0010, 0x0011, 0x0002, 0x0013, 0x0014, 0x0011, 0x0006, 0x001f,
+ 0x0018, 0x001d, 0x001a, 0x001b, 0x001c, 0x001d, 0x000e, 0x001f,
+ 0x0020, 0x0021, 0x0002, 0x0023, 0x0004, 0x0021, 0x0006, 0x002f,
+ 0x0028, 0x002d, 0x001a, 0x002b, 0x000c, 0x002d, 0x000e, 0x002f,
+ 0x0010, 0x0001, 0x0002, 0x0003, 0x0014, 0x0001, 0x0006, 0x001f,
+ 0x0038, 0x000d, 0x001a, 0x000b, 0x001c, 0x000d, 0x000e, 0x001f};
+
+// Optimised for Performance
+
+static const INT16 DSP1_MulTable[256] = {
+ 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015,
+ 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f,
+ 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048,
+ 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061,
+ 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a,
+ 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093,
+ 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac,
+ 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5,
+ 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df,
+ 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8,
+ 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111,
+ 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a,
+ 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143,
+ 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c,
+ 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175,
+ 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e,
+ 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8,
+ 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1,
+ 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da,
+ 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3,
+ 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c,
+ 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225,
+ 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e,
+ 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258,
+ 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271,
+ 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a,
+ 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3,
+ 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc,
+ 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5,
+ 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee,
+ 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307,
+ 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321};
+
+static const INT16 DSP1_SinTable[256] = {
+ 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2,
+ 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
+ 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
+ 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
+ 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6,
+ 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504,
+ 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3,
+ 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6,
+ 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d,
+ 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c,
+ 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24,
+ 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4,
+ 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4,
+ 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de,
+ 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b,
+ 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324,
+ -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2,
+ -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11,
+ -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a,
+ -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842,
+ -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6,
+ -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504,
+ -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3,
+ -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6,
+ -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d,
+ -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c,
+ -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24,
+ -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4,
+ -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4,
+ -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de,
+ -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b,
+ -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324
+};
+
+#define INCR 2048
+static double CosTable2[INCR];
+static double SinTable2[INCR];
+
+#define Angle(x) (((x)/(65536/INCR)) & (INCR-1))
+#define Cos(x) ((double) CosTable2[x])
+#define Sin(x) ((double) SinTable2[x])
+
+// init DSP1 math tables
+static void InitDSP1(void)
+{
+ UINT32 i;
+ UINT8 *dspin = memory_region(REGION_USER6);
+
+ dsp1_waitcmd = dsp1_first_parm = 1;
+
+ for (i=0; i<INCR; i++)
+ {
+ CosTable2[i] = (cos((double)(2*M_PI*i/INCR)));
+ SinTable2[i] = (sin((double)(2*M_PI*i/INCR)));
+ }
+
+ // expand the DSP-1 data ROM
+ for (i = 0; i < 2048; i+=2)
+ {
+ DSP1ROM[i/2] = dspin[i]<<8 | dspin[i+1];
+ }
+}
+
+static INT16 Gx, Nx, CentreX;
+static INT16 Gy, Ny, CentreY;
+static INT16 Gz, Nz, CentreZ;
+static INT16 Les_C, Les_E, Les_G;
+
+static INT16 VOffset;
+
+static INT16 VPlane_C, VPlane_E;
+
+// Azimuth and Zenith angles
+static INT16 SinAas, CosAas, SinAzs, CosAzs;
+
+// Clipped Zenith angle
+static INT16 SinAzsB, CosAzsB;
+static INT16 SecAZS_C1;
+static INT16 SecAZS_E1;
+static INT16 SecAZS_C2;
+static INT16 SecAZS_E2;
+
+static INT16 DSP1_Sin(INT16 Angle)
+{
+ int S;
+
+ if (Angle < 0) {
+ if (Angle == -32768) return 0;
+ return -DSP1_Sin(-Angle);
+ }
+
+ S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15);
+ if (S > 32767) S = 32767;
+ return (INT16) S;
+}
+
+static INT16 DSP1_Cos(INT16 Angle)
+{
+ int S;
+
+ if (Angle < 0) {
+ if (Angle == -32768) return -32768;
+ Angle = -Angle;
+ }
+ S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15);
+ if (S < -32768) S = -32767;
+ return (INT16) S;
+}
+
+static void DSP1_Normalize(INT16 m, INT16 *Coefficient, INT16 *Exponent)
+{
+ INT16 i = 0x4000;
+ INT16 e = 0;
+
+ if (m < 0)
+ while ((m & i) && i)
+ {
+ i >>= 1;
+ e++;
+ }
+ else
+ while (!(m & i) && i)
+ {
+ i >>= 1;
+ e++;
+ }
+
+ if (e > 0)
+ *Coefficient = m * DSP1ROM[0x0021 + e] << 1;
+ else
+ *Coefficient = m;
+
+ *Exponent -= e;
+}
+
+static void DSP1_NormalizeDouble(int Product, INT16 *Coefficient, INT16 *Exponent)
+{
+ INT16 n = Product & 0x7fff;
+ INT16 m = Product >> 15;
+ INT16 i = 0x4000;
+ INT16 e = 0;
+
+ if (m < 0)
+ while ((m & i) && i)
+ {
+ i >>= 1;
+ e++;
+ }
+ else
+ while (!(m & i) && i)
+ {
+ i >>= 1;
+ e++;
+ }
+
+ if (e > 0)
+ {
+ *Coefficient = m * DSP1ROM[0x0021 + e] << 1;
+
+ if (e < 15)
+ *Coefficient += n * DSP1ROM[0x0040 - e] >> 15;
+ else
+ {
+ i = 0x4000;
+
+ if (m < 0)
+ while ((n & i) && i)
+ {
+ i >>= 1;
+ e++;
+ }
+ else
+ while (!(n & i) && i)
+ {
+ i >>= 1;
+ e++;
+ }
+
+ if (e > 15)
+ *Coefficient = n * DSP1ROM[0x0012 + e] << 1;
+ else
+ *Coefficient += n;
+ }
+ }
+ else
+ *Coefficient = m;
+
+ *Exponent = e;
+}
+
+static INT16 DSP1_Truncate(INT16 C, INT16 E)
+{
+ if (E > 0) {
+ if (C > 0) return 32767; else if (C < 0) return -32767;
+ } else {
+ if (E < 0) return C * DSP1ROM[0x0031 + E] >> 15;
+ }
+ return C;
+}
+
+// 00H - 16-bit Multiplication (Bit Perfect)
+// Input byte(00H) integer(Multiplicand) integer(Multiplier)
+// Output integer(Product)
+
+static void DSP1_Multiply(INT16 Multiplicand, INT16 Multiplier, INT16 *Product)
+{
+ *Product = (Multiplicand * Multiplier >> 15);
+}
+
+// 20H - 16-bit Multiplication (Bit Perfect)
+// Input byte(20H) integer(Multiplicand) integer(Multiplier)
+// Output integer(Product)
+
+#ifdef UNUSED_FUNCTION
+static void DSP1_Multiply1(INT16 Multiplicand, INT16 Multiplier, INT16 *Product)
+{
+ *Product = (Multiplicand * Multiplier >> 15) + 1;
+}
+#endif
+
+// 10H - Inverse Calculation (Bit Perfect)
+// Input byte(10H) integer(Coefficient) integer(Exponent)
+// Output integer(Coefficient) integer(Exponent)
+
+static void DSP1_Inverse(INT16 Coefficient, INT16 Exponent, INT16 *iCoefficient, INT16 *iExponent)
+{
+ // Step One: Division by Zero
+ if (Coefficient == 0x0000)
+ {
+ *iCoefficient = 0x7fff;
+ *iExponent = 0x002f;
+ }
+ else
+ {
+ INT16 Sign = 1;
+
+ // Step Two: Remove Sign
+ if (Coefficient < 0)
+ {
+ if (Coefficient < -32767) Coefficient = -32767;
+ Coefficient = -Coefficient;
+ Sign = -1;
+ }
+
+ // Step Three: Normalize
+ while (Coefficient < 0x4000)
+ {
+ Coefficient <<= 1;
+ Exponent--;
+ }
+
+ // Step Four: Special Case
+ if (Coefficient == 0x4000)
+ if (Sign == 1) *iCoefficient = 0x7fff;
+ else {
+ *iCoefficient = -0x4000;
+ Exponent--;
+ }
+ else {
+ // Step Five: Initial Guess
+ INT16 i = DSP1ROM[((Coefficient - 0x4000) >> 7) + 0x0065];
+
+ // Step Six: Iterate Newton's Method
+ i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1;
+ i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1;
+
+ *iCoefficient = i * Sign;
+ }
+
+ *iExponent = 1 - Exponent;
+ }
+}
+
+// 04H - Trigonometric Calculation (Bit Perfect)
+// Input byte(04H) integer(Angle) integer(Radius)
+// Output integer(Sine) integer(Cosine)
+
+static void DSP1_Triangle(INT16 Angle, INT16 Radius, INT16 *S, INT16 *C)
+{
+ *S = DSP1_Sin(Angle) * Radius >> 15;
+ *C = DSP1_Cos(Angle) * Radius >> 15;
+}
+
+// 08H - Vector Size Calculation (Bit Perfect)
+// Input byte(08H) integer(X) integer(Y) integer(Z)
+// Output double(Radius)
+
+static void DSP1_Radius(INT16 X, INT16 Y, INT16 Z, int *Radius)
+{
+ *Radius = (X * X + Y * Y + Z * Z) << 1;
+}
+
+// 18H - Vector Size Comparison (Bit Perfect)
+// Input byte(18H) integer(X) integer(Y) integer(Z) integer(Radius)
+// Output integer(Range)
+
+static void DSP1_Range(INT16 X, INT16 Y, INT16 Z, INT16 Radius, INT16 *Range)
+{
+ *Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15);
+}
+
+// 38H - Vector Size Comparison (Bit Perfect)
+// Input byte(38H) integer(X) integer(Y) integer(Z) integer(Radius)
+// Output integer(Range)
+
+#ifdef UNUSED_FUNCTION
+static void DSP1_Range1(INT16 X, INT16 Y, INT16 Z, INT16 Radius, INT16 *Range)
+{
+ *Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1;
+}
+#endif
+
+// 28H - Vector Absolute Value Calculation (Bit Perfect)
+// Input byte(28H) integer(X) integer(Y) integer(Z)
+// Output integer(Distance)
+
+static void DSP1_Distance(INT16 X, INT16 Y, INT16 Z, INT16 *Distance)
+{
+ int Radius = X * X + Y * Y + Z * Z;
+ INT16 C, E, Pos, Node1, Node2;
+
+ if (Radius == 0) *Distance = 0;
+ else
+ {
+ DSP1_NormalizeDouble(Radius, &C, &E);
+ if (E & 1) C = C * 0x4000 >> 15;
+
+ Pos = C * 0x0040 >> 15;
+
+ Node1 = DSP1ROM[0x00d5 + Pos];
+ Node2 = DSP1ROM[0x00d6 + Pos];
+
+ *Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1;
+
+#if DSP1_VERSION < 0x0102
+ if (Pos & 1) *Distance -= (Node2 - Node1);
+#endif
+ *Distance >>= (E >> 1);
+ }
+}
+
+// 0CH - 2D Coordinate Rotation (Bit Perfect)
+// Input byte(0CH) integer(Angle) integer(X) integer(Y)
+// Output integer(X) integer(Y)
+
+static void DSP1_Rotate(INT16 Angle, INT16 X1, INT16 Y1, INT16 *X2, INT16 *Y2)
+{
+ *X2 = (Y1 * DSP1_Sin(Angle) >> 15) + (X1 * DSP1_Cos(Angle) >> 15);
+ *Y2 = (Y1 * DSP1_Cos(Angle) >> 15) - (X1 * DSP1_Sin(Angle) >> 15);
+}
+
+// 1CH - 3D Coordinate Rotation (Bit Perfect)
+// Input byte(1CH) integer(Az) integer(Ay) integer(Ax) integer(X) integer(Y) integer(Z)
+// Output integer(X) integer(Y) integer(Z)
+
+#ifdef UNUSED_FUNCTION
+static void DSP1_Polar(INT16 Az, INT16 Ay, INT16 Ax, INT16 X1, INT16 Y1, INT16 Z1, INT16 *X2, INT16 *Y2, INT16 *Z2)
+{
+ INT16 X, Y, Z;
+
+ // Rotate Around Z
+ X = (Y1 * DSP1_Sin(Az) >> 15) + (X1 * DSP1_Cos(Az) >> 15);
+ Y = (Y1 * DSP1_Cos(Az) >> 15) - (X1 * DSP1_Sin(Az) >> 15);
+ X1 = X; Y1 = Y;
+
+ // Rotate Around Y
+ Z = (X1 * DSP1_Sin(Ay) >> 15) + (Z1 * DSP1_Cos(Ay) >> 15);
+ X = (X1 * DSP1_Cos(Ay) >> 15) - (Z1 * DSP1_Sin(Ay) >> 15);
+ *X2 = X; Z1 = Z;
+
+ // Rotate Around X
+ Y = (Z1 * DSP1_Sin(Ax) >> 15) + (Y1 * DSP1_Cos(Ax) >> 15);
+ Z = (Z1 * DSP1_Cos(Ax) >> 15) - (Y1 * DSP1_Sin(Ax) >> 15);
+ *Y2 = Y; *Z2 = Z;
+}
+#endif
+
+// 02H - Projection Parameter Setting (Bit Perfect)
+// Input byte(02H) integer(Fx) integer(Fy) integer(Fz) integer(Lfe) integer(Les) integer(Aas) integer(Azs)
+// Output integer(Vof) integer(Vva) integer(Cx) integer(Cy)
+
+static const INT16 MaxAZS_Exp[16] = {
+ 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca,
+ 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4
+};
+
+static INT16 FxParm, FyParm, FzParm, AasParm, AzsParm, LfeParm, LesParm;
+
+static void DSP1_Parameter(INT16 Fx, INT16 Fy, INT16 Fz, INT16 Lfe, INT16 Les, INT16 Aas, INT16 Azs, INT16 *Vof, INT16 *Vva, INT16 *Cx, INT16 *Cy)
+{
+ INT16 CSec, C, E;
+
+ // Copy Zenith angle for clipping
+ INT16 AzsB = Azs;
+
+ INT16 MaxAZS;
+
+ // store off parameters for use by the Project operation
+ FxParm = Fx;
+ FyParm = Fy;
+ FzParm = Fz;
+ AasParm = Aas;
+ AzsParm = Azs;
+ LfeParm = Lfe;
+ LesParm = Les;
+
+ // Store Sine and Cosine of Azimuth and Zenith angle
+ SinAas = DSP1_Sin(Aas);
+ CosAas = DSP1_Cos(Aas);
+ SinAzs = DSP1_Sin(Azs);
+ CosAzs = DSP1_Cos(Azs);
+
+ Nx = SinAzs * -SinAas >> 15;
+ Ny = SinAzs * CosAas >> 15;
+ Nz = CosAzs * 0x7fff >> 15;
+
+ // Center of Projection
+ CentreX = Fx + (Lfe * Nx >> 15);
+ CentreY = Fy + (Lfe * Ny >> 15);
+ CentreZ = Fz + (Lfe * Nz >> 15);
+
+ Gx = CentreX - (Les * Nx >> 15);
+ Gy = CentreY - (Les * Ny >> 15);
+ Gz = CentreZ - (Les * Nz >> 15);
+
+ Les_E = 0;
+ DSP1_Normalize(Les, &Les_C, &Les_E);
+ Les_G = Les;
+
+ E = 0;
+ DSP1_Normalize(CentreZ, &C, &E);
+
+ VPlane_C = C;
+ VPlane_E = E;
+
+ // Determine clip boundary and clip Zenith angle if necessary
+ MaxAZS = MaxAZS_Exp[-E];
+
+ if (AzsB < 0) {
+ MaxAZS = -MaxAZS;
+ if (AzsB < MaxAZS + 1) AzsB = MaxAZS + 1;
+ } else {
+ if (AzsB > MaxAZS) AzsB = MaxAZS;
+ }
+
+ // Store Sine and Cosine of clipped Zenith angle
+ SinAzsB = DSP1_Sin(AzsB);
+ CosAzsB = DSP1_Cos(AzsB);
+
+ DSP1_Inverse(CosAzsB, 0, &SecAZS_C1, &SecAZS_E1);
+ DSP1_Normalize(C * SecAZS_C1 >> 15, &C, &E);
+ E += SecAZS_E1;
+
+ C = DSP1_Truncate(C, E) * SinAzsB >> 15;
+
+ CentreX += C * SinAas >> 15;
+ CentreY -= C * CosAas >> 15;
+
+ *Cx = CentreX;
+ *Cy = CentreY;
+
+ // Raster number of imaginary center and horizontal line
+ *Vof = 0;
+
+ if ((Azs != AzsB) || (Azs == MaxAZS))
+ {
+ INT16 Aux;
+
+ if (Azs == -32768) Azs = -32767;
+
+ C = Azs - MaxAZS;
+ if (C >= 0) C--;
+ Aux = ~(C << 2);
+
+ C = Aux * DSP1ROM[0x0328] >> 15;
+ C = (C * Aux >> 15) + DSP1ROM[0x0327];
+ *Vof -= (C * Aux >> 15) * Les >> 15;
+
+ C = Aux * Aux >> 15;
+ Aux = (C * DSP1ROM[0x0324] >> 15) + DSP1ROM[0x0325];
+ CosAzsB += (C * Aux >> 15) * CosAzsB >> 15;
+ }
+
+ VOffset = Les * CosAzsB >> 15;
+
+ DSP1_Inverse(SinAzsB, 0, &CSec, &E);
+ DSP1_Normalize(VOffset, &C, &E);
+ DSP1_Normalize(C * CSec >> 15, &C, &E);
+
+ if (C == -32768) { C >>= 1; E++; }
+
+ *Vva = DSP1_Truncate(-C, E);
+
+ // Store Secant of clipped Zenith angle
+ DSP1_Inverse(CosAzsB, 0, &SecAZS_C2, &SecAZS_E2);
+}
+
+// 06H - Object Projection Calculation
+// Input byte(06H) integer(X) integer(Y) integer(Z)
+// Output integer(H) integer(V) integer(M)
+
+static void DSP1_Project(INT16 X, INT16 Y, INT16 Z, INT16 *H, INT16 *V, UINT16 *M)
+{
+ double Px, Py, Pz, Px1, Py1, Pz1, Px2, Py2, Pz2;
+ INT32 dTan;
+
+ Px = X - FxParm;
+ Py = Y - FyParm;
+ Pz = Z - FzParm;
+
+ // rotate around the Z axis
+ dTan = Angle(-AasParm+32768);
+ Px1 = (Px*Cos(dTan)+Py*-Sin(dTan));
+ Py1 = (Px*Sin(dTan)+Py*Cos(dTan));
+ Pz1 = Pz;
+
+ // rotate around the X axis
+ dTan = Angle(-AzsParm);
+ Px2 = Px1;
+ Py2 = (Py1*Cos(dTan)+Pz1*-Sin(dTan));
+ Pz2 = (Py1*Sin(dTan)+Pz1*Cos(dTan));
+
+ Pz2 = Pz2-LfeParm;
+
+ if (Pz2 < 0)
+ {
+ double dM;
+
+ *H = (INT16)(-Px2*LesParm/-Pz2);
+ *V = (INT16)(-Py2*LesParm/-Pz2);
+
+ dM = (double)LesParm;
+ dM *= 256.0;
+ dM /= -Pz2;
+
+ if (dM > 65535.0)
+ {
+ dM = 65535.0;
+ }
+ else if (dM < 0.0)
+ {
+ dM = 0.0;
+ }
+
+ *M = (UINT16)dM;
+ }
+ else
+ {
+ *H = 0;
+ *V = 224;
+ *M = 65535;
+ }
+}
+
+// 0AH - Raster Data Calculation (Bit Perfect)
+// Input byte(0AH) integer(Vs)
+// Output integer(An) integer(Bn) integer(Cn) integer(Dn)
+
+static void DSP1_Raster(INT16 Vs, INT16 *An, INT16 *Bn, INT16 *Cn, INT16 *Dn)
+{
+ INT16 C, E, C1, E1;
+
+ DSP1_Inverse((Vs * SinAzs >> 15) + VOffset, 7, &C, &E);
+ E += VPlane_E;
+
+ C1 = C * VPlane_C >> 15;
+ E1 = E + SecAZS_E2;
+
+ DSP1_Normalize(C1, &C, &E);
+
+ C = DSP1_Truncate(C, E);
+
+ *An = C * CosAas >> 15;
+ *Cn = C * SinAas >> 15;
+
+ DSP1_Normalize(C1 * SecAZS_C2 >> 15, &C, &E1);
+
+ C = DSP1_Truncate(C, E1);
+
+ *Bn = C * -SinAas >> 15;
+ *Dn = C * CosAas >> 15;
+}
+
+// 0EH - Coordinate Calculation of a Selected Point on the Screen (Bit Perfect)
+// Input byte(0EH) integer(H) integer(V)
+// Output integer(X) integer(Y)
+
+static void DSP1_Target(INT16 H, INT16 V, INT16 *X, INT16 *Y)
+{
+ INT16 C, E, C1, E1;
+
+ DSP1_Inverse((V * SinAzs >> 15) + VOffset, 8, &C, &E);
+ E += VPlane_E;
+
+ C1 = C * VPlane_C >> 15;
+ E1 = E + SecAZS_E1;
+
+ H <<= 8;
+
+ DSP1_Normalize(C1, &C, &E);
+
+ C = DSP1_Truncate(C, E) * H >> 15;
+
+ *X = CentreX + (C * CosAas >> 15);
+ *Y = CentreY - (C * SinAas >> 15);
+
+ V <<= 8;
+
+ DSP1_Normalize(C1 * SecAZS_C1 >> 15, &C, &E1);
+
+ C = DSP1_Truncate(C, E1) * V >> 15;
+
+ *X += C * -SinAas >> 15;
+ *Y += C * CosAas >> 15;
+}
+
+// 01H - Set Attitude A (Bit Perfect)
+// Input byte(01H) integer(M) integer(Az) integer(Ay) integer(Ax)
+// Output None
+
+static INT16 MatrixA[3][3];
+
+static void DSP1_Attitude_A(INT16 M, INT16 Az, INT16 Ay, INT16 Ax)
+{
+ INT16 SinAz = DSP1_Sin(Az);
+ INT16 CosAz = DSP1_Cos(Az);
+ INT16 SinAy = DSP1_Sin(Ay);
+ INT16 CosAy = DSP1_Cos(Ay);
+ INT16 SinAx = DSP1_Sin(Ax);
+ INT16 CosAx = DSP1_Cos(Ax);
+
+ M >>= 1;
+
+ MatrixA[0][0] = (M * CosAz >> 15) * CosAy >> 15;
+ MatrixA[0][1] = -((M * SinAz >> 15) * CosAy >> 15);
+ MatrixA[0][2] = M * SinAy >> 15;
+
+ MatrixA[1][0] = ((M * SinAz >> 15) * CosAx >> 15) + (((M * CosAz >> 15) * SinAx >> 15) * SinAy >> 15);
+ MatrixA[1][1] = ((M * CosAz >> 15) * CosAx >> 15) - (((M * SinAz >> 15) * SinAx >> 15) * SinAy >> 15);
+ MatrixA[1][2] = -((M * SinAx >> 15) * CosAy >> 15);
+
+ MatrixA[2][0] = ((M * SinAz >> 15) * SinAx >> 15) - (((M * CosAz >> 15) * CosAx >> 15) * SinAy >> 15);
+ MatrixA[2][1] = ((M * CosAz >> 15) * SinAx >> 15) + (((M * SinAz >> 15) * CosAx >> 15) * SinAy >> 15);
+ MatrixA[2][2] = (M * CosAx >> 15) * CosAy >> 15;
+}
+
+// 11H - Set Attitude B (Bit Perfect)
+// Input byte(11H) integer(M) integer(Az) integer(Ay) integer(Ax)
+// Output None
+
+static INT16 MatrixB[3][3];
+
+static void DSP1_Attitude_B(INT16 M, INT16 Az, INT16 Ay, INT16 Ax)
+{
+ INT16 SinAz = DSP1_Sin(Az);
+ INT16 CosAz = DSP1_Cos(Az);
+ INT16 SinAy = DSP1_Sin(Ay);
+ INT16 CosAy = DSP1_Cos(Ay);
+ INT16 SinAx = DSP1_Sin(Ax);
+ INT16 CosAx = DSP1_Cos(Ax);
+
+ M >>= 1;
+
+ MatrixB[0][0] = (M * CosAz >> 15) * CosAy >> 15;
+ MatrixB[0][1] = -((M * SinAz >> 15) * CosAy >> 15);
+ MatrixB[0][2] = M * SinAy >> 15;
+
+ MatrixB[1][0] = ((M * SinAz >> 15) * CosAx >> 15) + (((M * CosAz >> 15) * SinAx >> 15) * SinAy >> 15);
+ MatrixB[1][1] = ((M * CosAz >> 15) * CosAx >> 15) - (((M * SinAz >> 15) * SinAx >> 15) * SinAy >> 15);
+ MatrixB[1][2] = -((M * SinAx >> 15) * CosAy >> 15);
+
+ MatrixB[2][0] = ((M * SinAz >> 15) * SinAx >> 15) - (((M * CosAz >> 15) * CosAx >> 15) * SinAy >> 15);
+ MatrixB[2][1] = ((M * CosAz >> 15) * SinAx >> 15) + (((M * SinAz >> 15) * CosAx >> 15) * SinAy >> 15);
+ MatrixB[2][2] = (M * CosAx >> 15) * CosAy >> 15;
+}
+
+// 21H - Set Attitude C (Bit Perfect)
+// Input byte(21H) integer(M) integer(Az) integer(Ay) integer(Ax)
+// Output None
+
+static INT16 MatrixC[3][3];
+
+#ifdef UNUSED_FUNCTION
+static void DSP1_Attitude_C(INT16 M, INT16 Az, INT16 Ay, INT16 Ax)
+{
+ INT16 SinAz = DSP1_Sin(Az);
+ INT16 CosAz = DSP1_Cos(Az);
+ INT16 SinAy = DSP1_Sin(Ay);
+ INT16 CosAy = DSP1_Cos(Ay);
+ INT16 SinAx = DSP1_Sin(Ax);
+ INT16 CosAx = DSP1_Cos(Ax);
+
+ M >>= 1;
+
+ MatrixC[0][0] = (M * CosAz >> 15) * CosAy >> 15;
+ MatrixC[0][1] = -((M * SinAz >> 15) * CosAy >> 15);
+ MatrixC[0][2] = M * SinAy >> 15;
+
+ MatrixC[1][0] = ((M * SinAz >> 15) * CosAx >> 15) + (((M * CosAz >> 15) * SinAx >> 15) * SinAy >> 15);
+ MatrixC[1][1] = ((M * CosAz >> 15) * CosAx >> 15) - (((M * SinAz >> 15) * SinAx >> 15) * SinAy >> 15);
+ MatrixC[1][2] = -((M * SinAx >> 15) * CosAy >> 15);
+
+ MatrixC[2][0] = ((M * SinAz >> 15) * SinAx >> 15) - (((M * CosAz >> 15) * CosAx >> 15) * SinAy >> 15);
+ MatrixC[2][1] = ((M * CosAz >> 15) * SinAx >> 15) + (((M * SinAz >> 15) * CosAx >> 15) * SinAy >> 15);
+ MatrixC[2][2] = (M * CosAx >> 15) * CosAy >> 15;
+}
+#endif
+
+// 0DH - Convert from Global to Object Coordinates A (Bit Perfect)
+// Input byte(0DH) integer(X) integer(Y) integer(Z)
+// Output integer(F) integer(L) integer(U)
+
+static void DSP1_Objective_A(INT16 X, INT16 Y, INT16 Z, INT16 *F, INT16 *L, INT16 *U)
+{
+ *F = (X * MatrixA[0][0] >> 15) + (Y * MatrixA[0][1] >> 15) + (Z * MatrixA[0][2] >> 15);
+ *L = (X * MatrixA[1][0] >> 15) + (Y * MatrixA[1][1] >> 15) + (Z * MatrixA[1][2] >> 15);
+ *U = (X * MatrixA[2][0] >> 15) + (Y * MatrixA[2][1] >> 15) + (Z * MatrixA[2][2] >> 15);
+}
+
+// 1DH - Convert from Global to Object Coordinates B (Bit Perfect)
+// Input byte(1DH) integer(X) integer(Y) integer(Z)
+// Output integer(F) integer(L) integer(U)
+
+void DSP1_Objective_B(INT16 X, INT16 Y, INT16 Z, INT16 *F, INT16 *L, INT16 *U)
+{
+ *F = (X * MatrixB[0][0] >> 15) + (Y * MatrixB[0][1] >> 15) + (Z * MatrixB[0][2] >> 15);
+ *L = (X * MatrixB[1][0] >> 15) + (Y * MatrixB[1][1] >> 15) + (Z * MatrixB[1][2] >> 15);
+ *U = (X * MatrixB[2][0] >> 15) + (Y * MatrixB[2][1] >> 15) + (Z * MatrixB[2][2] >> 15);
+}
+
+// 2DH - Convert from Global to Object Coordinates C (Bit Perfect)
+// Input byte(2DH) integer(X) integer(Y) integer(Z)
+// Output integer(F) integer(L) integer(U)
+
+static void DSP1_Objective_C(INT16 X, INT16 Y, INT16 Z, INT16 *F, INT16 *L, INT16 *U)
+{
+ *F = (X * MatrixC[0][0] >> 15) + (Y * MatrixC[0][1] >> 15) + (Z * MatrixC[0][2] >> 15);
+ *L = (X * MatrixC[1][0] >> 15) + (Y * MatrixC[1][1] >> 15) + (Z * MatrixC[1][2] >> 15);
+ *U = (X * MatrixC[2][0] >> 15) + (Y * MatrixC[2][1] >> 15) + (Z * MatrixC[2][2] >> 15);
+}
+
+// 03H - Conversion from Object to Global Coordinates A (Bit Perfect)
+// Input byte(03H) integer(F) integer(L) integer(U)
+// Output integer(X) integer(Y) integer(Z)
+
+static void DSP1_Subjective_A(INT16 F, INT16 L, INT16 U, INT16 *X, INT16 *Y, INT16 *Z)
+{
+ *X = (F * MatrixA[0][0] >> 15) + (L * MatrixA[1][0] >> 15) + (U * MatrixA[2][0] >> 15);
+ *Y = (F * MatrixA[0][1] >> 15) + (L * MatrixA[1][1] >> 15) + (U * MatrixA[2][1] >> 15);
+ *Z = (F * MatrixA[0][2] >> 15) + (L * MatrixA[1][2] >> 15) + (U * MatrixA[2][2] >> 15);
+}
+
+// 13H - Conversion from Object to Global Coordinates B (Bit Perfect)
+// Input byte(13H) integer(F) integer(L) integer(U)
+// Output integer(X) integer(Y) integer(Z)
+
+static void DSP1_Subjective_B(INT16 F, INT16 L, INT16 U, INT16 *X, INT16 *Y, INT16 *Z)
+{
+ *X = (F * MatrixB[0][0] >> 15) + (L * MatrixB[1][0] >> 15) + (U * MatrixB[2][0] >> 15);
+ *Y = (F * MatrixB[0][1] >> 15) + (L * MatrixB[1][1] >> 15) + (U * MatrixB[2][1] >> 15);
+ *Z = (F * MatrixB[0][2] >> 15) + (L * MatrixB[1][2] >> 15) + (U * MatrixB[2][2] >> 15);
+}
+
+// 23H - Conversion from Object to Global Coordinates C (Bit Perfect)
+// Input byte(23H) integer(F) integer(L) integer(U)
+// Output integer(X) integer(Y) integer(Z)
+
+static void DSP1_Subjective_C(INT16 F, INT16 L, INT16 U, INT16 *X, INT16 *Y, INT16 *Z)
+{
+ *X = (F * MatrixC[0][0] >> 15) + (L * MatrixC[1][0] >> 15) + (U * MatrixC[2][0] >> 15);
+ *Y = (F * MatrixC[0][1] >> 15) + (L * MatrixC[1][1] >> 15) + (U * MatrixC[2][1] >> 15);
+ *Z = (F * MatrixC[0][2] >> 15) + (L * MatrixC[1][2] >> 15) + (U * MatrixC[2][2] >> 15);
+}
+
+// 0BH - Calculation of Inner Product with Forward Attitude A and a Vector (Bit Perfect)
+// Input byte(0BH) integer(X) integer(Y) integer(Z)
+// Output integer(S)
+
+static void DSP1_Scalar_A(INT16 X, INT16 Y, INT16 Z, INT16 *S)
+{
+ *S = ((X * MatrixA[0][0]) + (Y * MatrixA[0][1]) + (Z * MatrixA[0][2])) >> 15;
+}
+
+// 1BH - Calculation of Inner Product with Forward Attitude B and a Vector (Bit Perfect)
+// Input byte(1BH) integer(X) integer(Y) integer(Z)
+// Output integer(S)
+
+static void DSP1_Scalar_B(INT16 X, INT16 Y, INT16 Z, INT16 *S)
+{
+ *S = ((X * MatrixB[0][0]) + (Y * MatrixB[0][1]) + (Z * MatrixB[0][2])) >> 15;
+}
+
+// 2BH - Calculation of Inner Product with Forward Attitude C and a Vector (Bit Perfect)
+// Input byte(2BH) integer(X) integer(Y) integer(Z)
+// Output integer(S)
+
+static void DSP1_Scalar_C(INT16 X, INT16 Y, INT16 Z, INT16 *S)
+{
+ *S = ((X * MatrixC[0][0]) + (Y * MatrixC[0][1]) + (Z * MatrixC[0][2])) >> 15;
+}
+
+// 14H - 3D Angle Rotation (Bit Perfect)
+// Input byte(14H) integer(Az) integer(Ax) integer(Ay) integer(U) integer(F) integer(L)
+// Output integer(Rz) integer(Rx) integer(Ry)
+
+static void DSP1_Gyrate(INT16 Az, INT16 Ax, INT16 Ay, INT16 U, INT16 F, INT16 L, INT16 *Rz, INT16 *Rx, INT16 *Ry)
+{
+ INT16 CSec, ESec, CSin, C, E;
+
+ DSP1_Inverse(DSP1_Cos(Ax), 0, &CSec, &ESec);
+
+ // Rotation Around Z
+ DSP1_NormalizeDouble(U * DSP1_Cos(Ay) - F * DSP1_Sin(Ay), &C, &E);
+
+ E = ESec - E;
+
+ DSP1_Normalize(C * CSec >> 15, &C, &E);
+
+ *Rz = Az + DSP1_Truncate(C, E);
+
+ // Rotation Around X
+ *Rx = Ax + (U * DSP1_Sin(Ay) >> 15) + (F * DSP1_Cos(Ay) >> 15);
+
+ // Rotation Around Y
+ DSP1_NormalizeDouble(U * DSP1_Cos(Ay) + F * DSP1_Sin(Ay), &C, &E);
+
+ E = ESec - E;
+
+ DSP1_Normalize(DSP1_Sin(Ax), &CSin, &E);
+
+ DSP1_Normalize(-(C * (CSec * CSin >> 15) >> 15), &C, &E);
+
+ *Ry = Ay + DSP1_Truncate(C, E) + L;
+}
+
+// 0FH - Memory Test (Bit Perfect)
+// Input byte(0FH) integer(Size)
+// Output integer(Result)
+
+static void DSP1_MemoryTest(INT16 Size, INT16 *Result)
+{
+ *Result = 0x0000;
+}
+
+// 2FH - Memory Size Calculation (Bit Perfect)
+// Input byte(2FH) integer(Undefined)
+// Output integer(Size)
+
+static void DSP1_MemorySize(INT16 *Size)
+{
+ *Size = 0x0100;
+}
+
+// ********************************************************************************************
+// MAME/MESS interface for above DSP1 code
+// ********************************************************************************************
+
+// DSP1 interface
+static UINT8 dsp1_read(UINT16 address)
+{
+ // check data vs. status
+ if (((address & 0xf000) == 0x6000) || ((address & 0x7fff) < 0x4000))
+ {
+ // data reg
+ if (dsp1_out_cnt)
+ {
+ UINT8 temp = (UINT8)dsp1_out[dsp1_out_idx++];
+ if (--dsp1_out_cnt == 0)
+ {
+ if ((dsp1_cur_cmd == 0x1a) || (dsp1_cur_cmd == 0x0a))
+ {
+ INT16 tr, tr1, tr2, tr3;
+
+ DSP1_Raster(dsp1_in[0]|dsp1_in[1]<<8, &tr, &tr1, &tr2, &tr3);
+ dsp1_in[0]++;
+ if (dsp1_in[0] == 0) dsp1_in[1]++;
+ dsp1_out_cnt = 8;
+ dsp1_out[0] = tr&0xff;
+ dsp1_out[1] = (tr>>8)&0xff;
+ dsp1_out[2] = tr1&0xff;
+ dsp1_out[3] = (tr1>>8)&0xff;
+ dsp1_out[4] = tr2&0xff;
+ dsp1_out[5] = (tr2>>8)&0xff;
+ dsp1_out[6] = tr3&0xff;
+ dsp1_out[7] = (tr3>>8)&0xff;
+ dsp1_out_idx = 0;
+ }
+ else if (dsp1_cur_cmd == 0x1f)
+ {
+ if ((dsp1_out_idx % 2) != 0)
+ {
+ return DSP1ROM[dsp1_out_idx>>1] & 0xff;
+ }
+ else
+ {
+ return (DSP1ROM[dsp1_out_idx>>1] >> 8) & 0xff;
+ }
+ }
+ }
+ dsp1_waitcmd = 1;
+// printf("dsp_r: %02x\n", temp);
+ return temp;
+ }
+ else
+ {
+// printf("dsp_r: %02x\n", 0xff);
+ return 0xff; // indicate "no data"
+ }
+ }
+
+ // status register
+// printf("dsp_r: %02x\n", 0x80);
+ return 0x80;
+}
+
+static void dsp1_write(UINT16 address, UINT8 data)
+{
+ // check data vs. status
+ if (((address & 0xf000) == 0x6000) || ((address & 0x7fff) < 0x4000))
+ {
+// printf("DSP_w: %02x cmd %02x wait %d dsp1_in_cnt %d\n", data, dsp1_cur_cmd, dsp1_waitcmd, dsp1_in_cnt);
+
+ if (((dsp1_cur_cmd == 0x0a) || (dsp1_cur_cmd == 0x1a)) && (dsp1_out_cnt != 0))
+ {
+ dsp1_out_cnt--;
+ dsp1_out_idx++;
+ return;
+ }
+ else if (dsp1_waitcmd)
+ {
+ dsp1_cur_cmd = data;
+ dsp1_in_idx = 0;
+ dsp1_waitcmd = 0;
+ dsp1_first_parm = 1;
+ switch (data)
+ {
+ case 0x00: dsp1_in_cnt = 2; break;
+ case 0x10: case 0x30: dsp1_in_cnt = 2; break;
+ case 0x20: dsp1_in_cnt = 2; break;
+ case 0x04: case 0x24: dsp1_in_cnt = 2; break;
+ case 0x08: dsp1_in_cnt = 3; break;
+ case 0x18: dsp1_in_cnt = 4; break;
+ case 0x28: dsp1_in_cnt = 3; break;
+ case 0x38: dsp1_in_cnt = 4; break;
+ case 0x0c: case 0x2c: dsp1_in_cnt = 3; break;
+ case 0x1c: case 0x3c: dsp1_in_cnt = 6; break;
+ case 0x02: case 0x12: case 0x22: case 0x32: dsp1_in_cnt = 7; break;
+ case 0x0a: dsp1_in_cnt = 1; break;
+ case 0x1a: case 0x2a: case 0x3a: dsp1_cur_cmd = 0x1a; dsp1_in_cnt = 1; break;
+ case 0x06: case 0x16: case 0x26: case 0x36: dsp1_in_cnt = 3; break;
+ case 0x0e: case 0x1e: case 0x2e: case 0x3e: dsp1_in_cnt = 2; break;
+ case 0x01: case 0x05: case 0x31: case 0x35: dsp1_in_cnt = 4; break;
+ case 0x11: case 0x15: dsp1_in_cnt = 4; break;
+ case 0x21: case 0x25: dsp1_in_cnt = 4; break;
+ case 0x0d: case 0x3d: case 0x09: case 0x39: dsp1_in_cnt = 3; break;
+ case 0x19: case 0x1d: dsp1_in_cnt = 3; break;
+ case 0x29: case 0x2d: dsp1_in_cnt = 3; break;
+ case 0x03: case 0x33: dsp1_in_cnt = 3; break;
+ case 0x13: dsp1_in_cnt = 3; break;
+ case 0x23: dsp1_in_cnt = 3; break;
+ case 0x0b: case 0x3b: dsp1_in_cnt = 3; break;
+ case 0x1b: dsp1_in_cnt = 3; break;
+ case 0x2b: dsp1_in_cnt = 3; break;
+ case 0x14: case 0x34: dsp1_in_cnt = 6; break;
+ case 0x07: case 0x0f: dsp1_in_cnt = 1; break;
+ case 0x27: case 0x2F: dsp1_in_cnt=1; break;
+ case 0x17: case 0x37: case 0x3F: dsp1_cur_cmd = 0x1f; dsp1_in_cnt = 1; break;
+ case 0x1f: dsp1_in_cnt = 1; break;
+
+ case 0x80:
+ dsp1_in_cnt = 0;
+ dsp1_waitcmd = 1;
+ dsp1_first_parm = 1;
+ break;
+ }
+
+ // that gives us parameter lengths in words, convert to bytes
+ dsp1_in_cnt *= 2;
+ }
+ else
+ {
+ dsp1_in[dsp1_in_idx++] = data;
+ dsp1_first_parm = 0;
+ }
+
+ if ((dsp1_waitcmd) || ((dsp1_first_parm) && (data == 0x80)))
+ {
+ dsp1_waitcmd = 1;
+ dsp1_first_parm = 0;
+ }
+ else if (((dsp1_first_parm) && (dsp1_in_cnt != 0)) || ((dsp1_in_cnt == 0) && (dsp1_in_idx == 0)))
+ {
+ }
+ else
+ {
+ if (dsp1_in_cnt)
+ {
+ if (--dsp1_in_cnt == 0)
+ {
+ INT16 tr = 0, tr1 = 0, tr2 = 0, tr3 = 0;
+ INT32 ltr;
+
+ // time to run the command
+ dsp1_waitcmd = 1;
+ dsp1_out_idx = 0;
+ switch (dsp1_cur_cmd)
+ {
+ case 0x00:
+ DSP1_Multiply(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, &tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ case 0x01:
+ case 0x05:
+ case 0x31:
+ case 0x35:
+ DSP1_Attitude_A(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, dsp1_in[6]|dsp1_in[7]<<8);
+ dsp1_out_cnt = 0;
+ break;
+
+ case 0x02:
+ case 0x12:
+ case 0x22:
+ case 0x32:
+ DSP1_Parameter(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, dsp1_in[6]|dsp1_in[7]<<8,
+ dsp1_in[8]|dsp1_in[9]<<8, dsp1_in[10]|dsp1_in[11]<<8, dsp1_in[12]|dsp1_in[13]<<8, &tr, &tr1, &tr2, &tr3);
+ dsp1_out_cnt = 8;
+ break;
+
+ case 0x03:
+ case 0x33:
+ DSP1_Subjective_A(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1, &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x04:
+ case 0x24:
+ DSP1_Triangle(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, &tr, &tr1);
+ dsp1_out_cnt = 4;
+ break;
+
+ case 0x06:
+ case 0x16:
+ case 0x26:
+ case 0x36:
+ DSP1_Project(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1, (UINT16 *) &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x0a:
+ case 0x1a:
+ case 0x2a:
+ case 0x3a:
+ DSP1_Raster(dsp1_in[0]|dsp1_in[1]<<8, &tr, &tr1, &tr2, &tr3);
+ dsp1_in[0]++;
+ if (dsp1_in[0] == 0) dsp1_in[1]++;
+ dsp1_out_cnt = 8;
+ dsp1_in_idx = 0;
+ break;
+
+ case 0x08:
+ DSP1_Radius(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &ltr);
+ tr = (ltr & 0xffff);
+ tr1 = (ltr >> 16) & 0xffff;
+ dsp1_out_cnt = 4;
+ break;
+
+ case 0x09:
+ case 0x0d:
+ case 0x39:
+ case 0x3d:
+ DSP1_Objective_A(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1, &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x0b:
+ case 0x3b:
+ DSP1_Scalar_A(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ case 0x0c:
+ case 0x2c:
+ DSP1_Rotate(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1);
+ dsp1_out_cnt = 4;
+ break;
+
+ case 0x0e:
+ case 0x1e:
+ case 0x2e:
+ case 0x3e:
+ DSP1_Target(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, &tr, &tr1);
+ dsp1_out_cnt = 4;
+ break;
+
+ case 0x07:
+ case 0x0f:
+ DSP1_MemoryTest(dsp1_in[0]|dsp1_in[1]<<8, &tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ case 0x10:
+ case 0x30:
+ DSP1_Inverse(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, &tr, &tr1);
+ dsp1_out_cnt = 4;
+ break;
+
+ case 0x11:
+ case 0x15:
+ DSP1_Attitude_B(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, dsp1_in[6]|dsp1_in[7]<<8);
+ dsp1_out_cnt = 0;
+ break;
+
+ case 0x13:
+ DSP1_Subjective_B(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1, &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x14:
+ case 0x34:
+ DSP1_Gyrate(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, dsp1_in[6]|dsp1_in[7]<<8,
+ dsp1_in[8]|dsp1_in[9]<<8, dsp1_in[10]|dsp1_in[11]<<8, &tr, &tr1, &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x18:
+ DSP1_Range(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, dsp1_in[6]|dsp1_in[7]<<8, &tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ case 0x19:
+ case 0x1d:
+ DSP1_Objective_B(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1, &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x1b:
+ DSP1_Scalar_B(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ case 0x1f:
+ dsp1_out_cnt = 2048;
+ break;
+
+ case 0x23:
+ DSP1_Subjective_C(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1, &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x28:
+ DSP1_Distance(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ case 0x29:
+ case 0x2d:
+ DSP1_Objective_C(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr, &tr1, &tr2);
+ dsp1_out_cnt = 6;
+ break;
+
+ case 0x2b:
+ DSP1_Scalar_C(dsp1_in[0]|dsp1_in[1]<<8, dsp1_in[2]|dsp1_in[3]<<8, dsp1_in[4]|dsp1_in[5]<<8, &tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ case 0x27:
+ case 0x2f:
+ DSP1_MemorySize(&tr);
+ dsp1_out_cnt = 2;
+ break;
+
+ default:
+ printf("Unhandled DSP1 command: %02x\n", dsp1_cur_cmd);
+ break;
+
+ }
+
+ // copy up to 8 bytes of result into the buffer
+ dsp1_out[0] = tr&0xff;
+ dsp1_out[1] = (tr>>8)&0xff;
+ dsp1_out[2] = tr1&0xff;
+ dsp1_out[3] = (tr1>>8)&0xff;
+ dsp1_out[4] = tr2&0xff;
+ dsp1_out[5] = (tr2>>8)&0xff;
+ dsp1_out[6] = tr3&0xff;
+ dsp1_out[7] = (tr3>>8)&0xff;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/mame/machine/spisprit.c b/src/mame/machine/spisprit.c
new file mode 100644
index 00000000000..422babfbdbd
--- /dev/null
+++ b/src/mame/machine/spisprit.c
@@ -0,0 +1,281 @@
+#if 0
+key tables: table[n] is the column of bit n
+cpu #0 (PC=0033C2F5): unmapped program memory dword write to 00000530 = 0000xxxx & FFFFFFFF (256 times, see key_table[])
+
+cpu #0 (PC=0033C315): unmapped program memory dword write to 00000524 = 843A0000 & FFFFFFFF
+cpu #0 (PC=0033C315): unmapped program memory dword write to 00000524 = 3A590000 & FFFFFFFF
+cpu #0 (PC=0033C315): unmapped program memory dword write to 00000524 = C8E20000 & FFFFFFFF
+cpu #0 (PC=0033C315): unmapped program memory dword write to 00000524 = 28D40000 & FFFFFFFF
+cpu #0 (PC=0033C315): unmapped program memory dword write to 00000524 = 9F840000 & FFFFFFFF
+cpu #0 (PC=0033C315): unmapped program memory dword write to 00000524 = 9CAC0000 & FFFFFFFF
+#endif
+
+
+#include "driver.h"
+// add two numbers generating carry from one bit to the next only if
+// the corresponding bit in carry_mask is 1
+static int partial_carry_sum(int add1,int add2,int carry_mask,int bits)
+{
+ int i,res,carry;
+
+ res = 0;
+ carry = 0;
+ for (i = 0;i < bits;i++)
+ {
+ int bit = BIT(add1,i) + BIT(add2,i) + carry;
+
+ res += (bit & 1) << i;
+
+ // generate carry only if the corresponding bit in carry_mask is 1
+ if (BIT(carry_mask,i))
+ carry = bit >> 1;
+ else
+ carry = 0;
+ }
+
+ // wrap around carry from top bit to bit 0
+ if (carry)
+ res ^=1;
+
+ return res;
+}
+
+/*
+This is the main key as written by the game.
+There are 256 values; the one to use is key_table[(address >> 8) & 0xff].
+
+Bits 0-3 select the permutation on 16 bits of the source data.
+Bits 4-14 are added to the source data, with partial carry.
+Bit 15 is still unknown.
+*/
+static const UINT16 key_table[256]=
+{
+ 0x3ad7,0x54b1,0x2d41,0x8ca0,0xa69b,0x9018,0x9db9,0x6559,
+ 0xe9a7,0xb087,0x8a5e,0x821c,0xaafc,0x2ae7,0x557b,0xcd80,
+ 0xcfee,0x653e,0x9b31,0x7ab5,0x8b2a,0xbda8,0x707a,0x3c83,
+ 0xcbb7,0x7157,0x8226,0x5c4a,0x8bf2,0x6397,0x13e2,0x3102,
+ 0x8093,0x44cd,0x5f2d,0x7639,0xa7a4,0x9974,0x5263,0x8318,
+ 0xb78c,0xa120,0xafb4,0x615f,0x6e0b,0x1d7d,0x8c29,0x4466,
+ 0x3f35,0x794e,0xaea6,0x601c,0xe478,0xcf6e,0x4ee3,0xa009,
+ 0x4b99,0x51d3,0x3474,0x3e4d,0xe5b7,0x9088,0xb5c0,0xba9f,
+ 0x5646,0xa0af,0x970b,0xb14f,0x8216,0x2386,0x496d,0x9245,
+ 0x7e4c,0xad5f,0x89d9,0xb801,0xdf64,0x8ca8,0xe019,0xde9b,
+ 0x6836,0x70e2,0x7dcd,0x7ac1,0x98ef,0x71aa,0x7d6f,0x70bd,
+ 0x9e14,0x75b6,0x8153,0xab6c,0x1f85,0x79cd,0xb2a1,0x934a,
+ 0x6f74,0x37d7,0xa05a,0x6563,0x1972,0x2dcd,0x7e59,0x6a60,
+ 0x5163,0x84c4,0xc451,0x8d80,0x4287,0x57e8,0xacc9,0x539d,
+ 0xbe71,0xdb7c,0x9424,0xb224,0xcc0f,0xe3dd,0xb79c,0x461e,
+ 0x96a9,0x4c7c,0x5443,0x6b2b,0x3cdc,0xbee8,0x2602,0x3282,
+ 0x7f9c,0x59c3,0xc69a,0x39f4,0x5138,0xb7ca,0x6ca7,0x62e7,
+ 0xc455,0x56cf,0x8a9a,0x695c,0x5af2,0xdebf,0x4dbb,0xdaec,
+ 0xb564,0xc89c,0x7d2d,0x6dc3,0xa15a,0x6584,0xb8ea,0xb7ac,
+ 0x88d8,0xc5aa,0x98c5,0xc506,0xc13c,0x7f59,0xab65,0x8fc8,
+ 0x3a3c,0xd5f6,0x554d,0x5682,0x8ce7,0x40fc,0x8fd7,0x535c,
+ 0x6aa0,0x52fe,0x8834,0x5316,0x6c27,0x80a9,0x9e6f,0x2c08,
+ 0x4092,0xc7c1,0xc468,0x9520,0xbc4d,0xb621,0x3cdb,0xdce8,
+ 0x481f,0xd0bd,0x3a57,0x807e,0x3025,0x5aa0,0x5e49,0xa29b,
+ 0xd2d6,0x7bee,0x97f0,0xe28e,0x2fff,0x48e4,0x6367,0x933f,
+ 0x57c5,0x28d4,0x68a0,0xd22e,0x39a6,0x9d2b,0x7a64,0x7e72,
+ 0x5379,0xe86c,0x7554,0x8fbb,0xc06a,0x9533,0x7eec,0x4d52,
+ 0xa800,0x5d35,0xa47d,0xe515,0x8d19,0x703b,0x5a2e,0x627c,
+ 0x7cea,0x1b2c,0x5a05,0x8598,0x9e00,0xcf01,0x62d9,0x7a10,
+ 0x1f42,0x87ce,0x575d,0x6e23,0x86ef,0x93c2,0x3d1a,0x89aa,
+ 0xe199,0xba1d,0x1b72,0x4513,0x5131,0xc23c,0xba9f,0xa069,
+ 0xfbfb,0xda92,0x42b2,0x3a48,0xdb96,0x5fad,0xba96,0xc6eb,
+};
+
+
+#if 0
+ { // table[15] NOT USED!
+ 0,0,0,1,1,1,1,0,1,1,1,1,1,0,0,1,1,0,1,0,1,1,0,0,1,0,1,0,1,0,0,0,
+ 1,0,0,0,1,1,0,1,1,1,1,0,0,0,1,0,0,0,1,0,1,1,0,1,0,0,0,0,1,1,1,1,
+ 0,1,1,1,1,0,0,1,0,1,1,1,1,1,1,1,0,0,0,0,1,0,0,0,1,0,1,1,0,0,1,1,
+ 0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,0,1,1,1,1,1,1,1,0,1,0,0,0,0,1,0,0,
+ 0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,1,1,1,0,0,1,0,1,1,1,1,1,1,1,0,1,1,
+ 0,1,0,0,1,0,1,0,0,0,1,0,0,1,1,0,0,1,1,1,1,1,0,1,0,1,0,1,0,0,0,1,
+ 1,0,1,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1,0,1,1,1,0,0,1,0,1,1,1,0,0,0,
+ 0,0,0,1,1,1,0,0,0,1,0,0,1,1,0,1,1,1,0,0,0,1,1,1,1,1,0,0,1,0,1,1,
+ },
+#endif
+
+
+static const UINT8 bitswap[16][16] =
+{
+ { 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, },
+ { 7, 6, 5,14, 0,15, 4, 3, 2, 8, 9,10,11,12,13, 1, },
+ { 9,15,14,13,12, 0, 1, 2,10, 8, 7, 6, 5, 4, 3,11, },
+ { 5, 4, 3, 2, 9,14,13,12,11, 6, 7, 8, 1,15, 0,10, },
+ { 12,11, 0, 7, 8, 5, 6,15,10,13,14, 1, 2, 3, 4, 9, },
+ { 14, 0, 1, 2, 3, 9, 8, 7,15, 5, 6,13,12,11,10, 4, },
+ { 13,12,11,10, 2, 7, 8, 9, 0,14,15, 3, 4, 5, 6, 1, },
+ { 2, 9,10,11,12, 7, 6, 5,14, 3, 4, 0,15, 1, 8,13, },
+ { 8, 7, 4, 3, 2,13,12,11, 0, 9,10,14,15, 6, 5, 1, },
+ { 3, 2,10,11,12, 5,14, 0, 1, 4,15, 6, 7, 8, 9,13, },
+ { 2,10, 6, 5, 4,14,13,12,11, 1, 0,15, 9, 8, 7, 3, },
+ { 12,11, 8, 1,15, 3, 2, 9,10,13,14, 4, 5, 6, 7, 0, },
+ { 8, 7, 0,11,12, 5, 6,15,14, 9,10, 1, 2, 3, 4,13, },
+ { 3, 2, 1, 0,14, 9, 8, 7, 6, 4,15,13,12,11,10, 5, },
+ { 2,10,11,12,13, 7, 8, 9,15, 1, 0, 3, 4, 5, 6,14, },
+ { 12,11,10, 9, 2, 7, 6, 5, 4,13,14, 0,15, 1, 8, 3, },
+};
+
+
+static int key(int table,int addr)
+{
+ int xorbit = 8 + ((table & 0xc) >> 2);
+ return BIT(key_table[addr & 0xff] >> 4,table) ^ BIT(addr,xorbit);
+}
+
+
+void seibuspi_sprite_decrypt(UINT8 *src, int rom_size)
+{
+ int i;
+
+
+ for(i = 0; i < rom_size/2; i++)
+ {
+ int j;
+ int addr = i>>8;
+ int y1,y2,y3;
+ int s1,s2;
+ int add1,add2;
+ int plane0,plane1,plane2,plane3,plane4,plane5;
+ const UINT8 *bs;
+
+ y1 = src[2*i+0*rom_size+0] + (src[2*i+0*rom_size+1] << 8);
+ y2 = src[2*i+1*rom_size+0] + (src[2*i+1*rom_size+1] << 8);
+ y3 = src[2*i+2*rom_size+0] + (src[2*i+2*rom_size+1] << 8);
+
+
+ /* first of all, permutate 16 of the 48 bits */
+ bs = bitswap[key_table[addr & 0xff]&0xf];
+ y3 = BITSWAP16(y3, bs[0],bs[1],bs[2],bs[3],bs[4],bs[5],bs[6],bs[7],
+ bs[8],bs[9],bs[10],bs[11],bs[12],bs[13],bs[14],bs[15]);
+
+
+ // planes 4 & 5, interleaved
+ s1 = (BIT(y1, 4) << 0) |
+ (BIT(y3, 7) << 1) |
+ (BIT(y3, 6) << 2) |
+ (BIT(y2,12) << 3) |
+ (BIT(y2, 3) << 4) |
+ (BIT(y1,10) << 5) |
+ (BIT(y1, 1) << 6) |
+ (BIT(y3,14) << 7) |
+ (BIT(y3, 2) << 8) |
+ (BIT(y2, 9) << 9) |
+ (BIT(y2, 0) << 10) |
+ (BIT(y1, 7) << 11) |
+ (BIT(y3,12) << 12) |
+ (BIT(y2,15) << 13) |
+ (BIT(y2, 6) << 14) |
+ (BIT(y1,13) << 15);
+
+ add1 = (BIT(addr,11) << 0) |
+ (BIT(addr,10) << 1) |
+ (key(10,addr) << 2) |
+ (key( 5,addr) << 3) |
+ (key( 4,addr) << 4) |
+ (BIT(addr,11) << 5) |
+ (BIT(addr,11) << 6) |
+ (key( 7,addr) << 7) |
+ (key( 6,addr) << 8) |
+ (key( 1,addr) << 9) |
+ (key( 0,addr) << 10) |
+ (BIT(addr,11) << 11) |
+ (key( 9,addr) << 12) |
+ (key( 8,addr) << 13) |
+ (key( 3,addr) << 14) |
+ (key( 2,addr) << 15);
+
+ // planes 0-3, interleaved
+ s2 = (BIT(y1, 5) << 0) |
+ (BIT(y3, 0) << 1) |
+ (BIT(y3, 5) << 2) |
+ (BIT(y2,13) << 3) |
+ (BIT(y2, 4) << 4) |
+ (BIT(y1,11) << 5) |
+ (BIT(y1, 2) << 6) |
+ (BIT(y3, 9) << 7) |
+ (BIT(y3, 3) << 8) |
+ (BIT(y2, 8) << 9) |
+ (BIT(y1,15) << 10) |
+ (BIT(y1, 6) << 11) |
+ (BIT(y3,11) << 12) |
+ (BIT(y2,14) << 13) |
+ (BIT(y2, 5) << 14) |
+ (BIT(y1,12) << 15) |
+ (BIT(y1, 3) << 16) |
+ (BIT(y3, 8) << 17) |
+ (BIT(y3,15) << 18) |
+ (BIT(y2,11) << 19) |
+ (BIT(y2, 2) << 20) |
+ (BIT(y1, 9) << 21) |
+ (BIT(y1, 0) << 22) |
+ (BIT(y3,10) << 23) |
+ (BIT(y3, 1) << 24) |
+ (BIT(y2,10) << 25) |
+ (BIT(y2, 1) << 26) |
+ (BIT(y1, 8) << 27) |
+ (BIT(y3,13) << 28) |
+ (BIT(y3, 4) << 29) |
+ (BIT(y2, 7) << 30) |
+ (BIT(y1,14) << 31);
+
+ add2 = (key( 0,addr) << 0) |
+ (key( 1,addr) << 1) |
+ (key( 2,addr) << 2) |
+ (key( 3,addr) << 3) |
+ (key( 4,addr) << 4) |
+ (key( 5,addr) << 5) |
+ (key( 6,addr) << 6) |
+ (key( 7,addr) << 7) |
+ (key( 8,addr) << 8) |
+ (key( 9,addr) << 9) |
+ (key(10,addr) << 10) |
+ (BIT(addr,10) << 11) |
+ (BIT(addr,11) << 12) |
+ (BIT(addr,11) << 13) |
+ (BIT(addr,11) << 14) |
+ (BIT(addr,11) << 15) |
+ (BIT(addr,11) << 16) |
+ (key( 7,addr) << 17) |
+ (BIT(addr,11) << 18) |
+ (key( 6,addr) << 19) |
+ (BIT(addr,11) << 20) |
+ (key( 5,addr) << 21) |
+ (BIT(addr,11) << 22) |
+ (key( 4,addr) << 23) |
+ (BIT(addr,10) << 24) |
+ (key( 3,addr) << 25) |
+ (key(10,addr) << 26) |
+ (key( 2,addr) << 27) |
+ (key( 9,addr) << 28) |
+ (key( 1,addr) << 29) |
+ (key( 8,addr) << 30) |
+ (key( 0,addr) << 31);
+
+ s1 = partial_carry_sum( s1, add1, 0x3a59, 16 ) ^ 0x843a;
+ s2 = partial_carry_sum( s2, add2, 0x28d49cac, 32 ) ^ 0xc8e29f84;
+
+
+ // reorder the bits in the order MAME expects to decode the graphics
+ plane0 = plane1 = plane2 = plane3 = plane4 = plane5 = 0;
+ for (j = 0;j < 8;j++)
+ {
+ plane5 |= (BIT(s1, 2*j+1) << j);
+ plane4 |= (BIT(s1, 2*j+0) << j);
+ plane3 |= (BIT(s2, 4*j+3) << j);
+ plane2 |= (BIT(s2, 4*j+2) << j);
+ plane1 |= (BIT(s2, 4*j+1) << j);
+ plane0 |= (BIT(s2, 4*j+0) << j);
+ }
+
+ src[2*i+0*rom_size+0] = plane5;
+ src[2*i+0*rom_size+1] = plane4;
+ src[2*i+1*rom_size+0] = plane3;
+ src[2*i+1*rom_size+1] = plane2;
+ src[2*i+2*rom_size+0] = plane1;
+ src[2*i+2*rom_size+1] = plane0;
+ }
+}
diff --git a/src/mame/machine/stactics.c b/src/mame/machine/stactics.c
new file mode 100644
index 00000000000..56b9ae296cf
--- /dev/null
+++ b/src/mame/machine/stactics.c
@@ -0,0 +1,94 @@
+
+#include "driver.h"
+
+/* needed in video/stactics.c */
+int stactics_vert_pos;
+int stactics_horiz_pos;
+UINT8 *stactics_motor_on;
+
+/* defined in video/stactics.c */
+extern int stactics_vblank_count;
+extern int stactics_shot_standby;
+extern int stactics_shot_arrive;
+
+#ifdef UNUSED_FUNCTION
+READ8_HANDLER( stactics_port_0_r )
+{
+ if (*stactics_motor_on & 0x01)
+ {
+ return (input_port_0_r(0)&0x7f);
+ }
+ else if ((stactics_horiz_pos == 0) && (stactics_vert_pos == 0))
+ {
+ return (input_port_0_r(0)&0x7f);
+ }
+ else
+ {
+ return (input_port_0_r(0)|0x80);
+ }
+}
+#endif
+
+READ8_HANDLER( stactics_port_2_r )
+{
+ return (input_port_2_r(0)&0xf0)+(stactics_vblank_count&0x08)+(mame_rand(Machine)%8);
+}
+
+READ8_HANDLER( stactics_port_3_r )
+{
+ return (input_port_3_r(0)&0x7d)+(stactics_shot_standby<<1)
+ +((stactics_shot_arrive^0x01)<<7);
+}
+
+READ8_HANDLER( stactics_vert_pos_r )
+{
+ return 0x70-stactics_vert_pos;
+}
+
+READ8_HANDLER( stactics_horiz_pos_r )
+{
+ return stactics_horiz_pos+0x80;
+}
+
+INTERRUPT_GEN( stactics_interrupt )
+{
+ /* Run the monitor motors */
+
+ if (*stactics_motor_on & 0x01) /* under joystick control */
+ {
+ int ip3 = readinputport(3);
+ int ip4 = readinputport(4);
+
+ if ((ip4 & 0x01) == 0) /* up */
+ if (stactics_vert_pos > -128)
+ stactics_vert_pos--;
+ if ((ip4 & 0x02) == 0) /* down */
+ if (stactics_vert_pos < 127)
+ stactics_vert_pos++;
+ if ((ip3 & 0x20) == 0) /* left */
+ if (stactics_horiz_pos < 127)
+ stactics_horiz_pos++;
+ if ((ip3 & 0x40) == 0) /* right */
+ if (stactics_horiz_pos > -128)
+ stactics_horiz_pos--;
+ }
+ else /* under self-centering control */
+ {
+ if (stactics_horiz_pos > 0)
+ stactics_horiz_pos--;
+ else if (stactics_horiz_pos < 0)
+ stactics_horiz_pos++;
+ if (stactics_vert_pos > 0)
+ stactics_vert_pos--;
+ else if (stactics_vert_pos < 0)
+ stactics_vert_pos++;
+ }
+
+ cpunum_set_input_line(0,0,HOLD_LINE);
+}
+
+WRITE8_HANDLER( stactics_coin_lockout_w )
+{
+ coin_lockout_w(offset, ~data & 0x01);
+}
+
diff --git a/src/mame/machine/starwars.c b/src/mame/machine/starwars.c
new file mode 100644
index 00000000000..97ed1b697e2
--- /dev/null
+++ b/src/mame/machine/starwars.c
@@ -0,0 +1,480 @@
+/***************************************************************************
+
+ Atari Star Wars hardware
+
+ This file is Copyright 1997, Steve Baines.
+ Modified by Frank Palazzolo for sound support
+
+***************************************************************************/
+
+#include "driver.h"
+#include "starwars.h"
+#include "video/avgdvg.h"
+
+
+/* Control select values for ADC_R */
+#define kPitch 0
+#define kYaw 1
+#define kThrust 2
+
+/* Constants for mathbox operations */
+#define NOP 0x00
+#define LAC 0x01
+#define READ_ACC 0x02
+#define M_HALT 0x04
+#define INC_BIC 0x08
+#define CLEAR_ACC 0x10
+#define LDC 0x20
+#define LDB 0x40
+#define LDA 0x80
+
+/* Debugging flag */
+#define MATHDEBUG 0
+
+
+UINT8 *starwars_mathram;
+UINT8 *starwars_ram_overlay;
+
+/* Local variables */
+static UINT8 control_num = kPitch;
+
+static int MPA; /* PROM address counter */
+static int BIC; /* Block index counter */
+
+static UINT16 dvd_shift, quotient_shift; /* Divider shift registers */
+static UINT16 divisor, dividend; /* Divider latches */
+
+/* Store decoded PROM elements */
+static UINT8 *PROM_STR; /* Storage for instruction strobe only */
+static UINT8 *PROM_MAS; /* Storage for direct address only */
+static UINT8 *PROM_AM; /* Storage for address mode select only */
+
+
+/* Local function prototypes */
+static void run_mbox(void);
+
+
+
+/*************************************
+ *
+ * X2212 nvram store
+ *
+ *************************************/
+
+WRITE8_HANDLER( starwars_nstore_w )
+{
+ memcpy (generic_nvram, starwars_ram_overlay, generic_nvram_size);
+}
+
+/*************************************
+ *
+ * Output latch
+ *
+ *************************************/
+
+WRITE8_HANDLER( starwars_out_w )
+{
+ switch (offset & 7)
+ {
+ case 0: /* Coin counter 1 */
+ coin_counter_w(0, data);
+ break;
+
+ case 1: /* Coin counter 2 */
+ coin_counter_w(1, data);
+ break;
+
+ case 2: /* LED 3 */
+ set_led_status(2, ~data & 0x80);
+ break;
+
+ case 3: /* LED 2 */
+ set_led_status(1, ~data & 0x80);
+ break;
+
+ case 4: /* bank switch */
+ memory_set_bank(1, (data >> 7) & 1);
+ if (starwars_is_esb)
+ memory_set_bank(2, (data >> 7) & 1);
+ break;
+ case 5: /* reset PRNG */
+ break;
+
+ case 6: /* LED 1 */
+ set_led_status(0, ~data & 0x80);
+ break;
+
+ case 7: /* NVRAM array recall */
+ memcpy (starwars_ram_overlay, generic_nvram, generic_nvram_size);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Input port 1
+ *
+ *************************************/
+
+READ8_HANDLER( starwars_input_1_r )
+{
+ int x = readinputport(1);
+
+ /* Kludge to enable Starwars Mathbox Self-test */
+ /* The mathbox looks like it's running, from this address... :) */
+ if (activecpu_get_pc() == 0xf978 || activecpu_get_pc() == 0xf655)
+ x |= 0x80;
+
+ /* set the AVG done flag */
+ if (avgdvg_done())
+ x |= 0x40;
+ else
+ x &= ~0x40;
+
+ return x;
+}
+
+
+
+/*************************************
+ *
+ * ADC input and control
+ *
+ *************************************/
+
+READ8_HANDLER( starwars_adc_r )
+{
+ /* pitch */
+ if (control_num == kPitch)
+ return readinputport(4);
+
+ /* yaw */
+ else if (control_num == kYaw)
+ return readinputport(5);
+
+ /* default to unused thrust */
+ else
+ return 0;
+}
+
+
+WRITE8_HANDLER( starwars_adc_select_w )
+{
+ control_num = offset;
+}
+
+
+
+/*************************************
+ *
+ * Mathbox initialization
+ *
+ *************************************/
+
+void swmathbox_init(void)
+{
+ UINT8 *src = memory_region(REGION_USER2);
+ int cnt, val;
+
+ PROM_STR = auto_malloc(1024 * sizeof(PROM_STR[0]));
+ PROM_MAS = auto_malloc(1024 * sizeof(PROM_MAS[0]));
+ PROM_AM = auto_malloc(1024 * sizeof(PROM_AM[0]));
+
+ for (cnt = 0; cnt < 1024; cnt++)
+ {
+ /* translate PROMS into 16 bit code */
+ val = (src[0x0c00 + cnt] ) & 0x000f; /* Set LS nibble */
+ val |= (src[0x0800 + cnt] << 4) & 0x00f0;
+ val |= (src[0x0400 + cnt] << 8) & 0x0f00;
+ val |= (src[0x0000 + cnt] << 12) & 0xf000; /* Set MS nibble */
+
+ /* perform pre-decoding */
+ PROM_STR[cnt] = (val >> 8) & 0x00ff;
+ PROM_MAS[cnt] = val & 0x007f;
+ PROM_AM[cnt] = (val >> 7) & 0x0001;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Mathbox reset
+ *
+ *************************************/
+
+void swmathbox_reset(void)
+{
+ MPA = BIC = 0;
+}
+
+
+
+/*************************************
+ *
+ * Mathbox execution
+ *
+ *************************************/
+
+void run_mbox(void)
+{
+ static INT16 A, B, C;
+ static INT32 ACC;
+
+ int RAMWORD = 0;
+ int MA_byte;
+ int tmp;
+ int M_STOP = 100000; /* Limit on number of instructions allowed before halt */
+ int MA;
+ int IP15_8, IP7, IP6_0; /* Instruction PROM values */
+
+
+ logerror("Running Mathbox...\n");
+
+ /* loop until finished */
+ while (M_STOP > 0)
+ {
+ /* fetch the current instruction data */
+ IP15_8 = PROM_STR[MPA];
+ IP7 = PROM_AM[MPA];
+ IP6_0 = PROM_MAS[MPA];
+
+#if (MATHDEBUG)
+ mame_printf_debug("\n(MPA:%x), Strobe: %x, IP7: %d, IP6_0:%x\n",MPA, IP15_8, IP7, IP6_0);
+ mame_printf_debug("(BIC: %x), A: %x, B: %x, C: %x, ACC: %x\n",BIC,A,B,C,ACC);
+#endif
+
+ /* construct the current RAM address */
+ if (IP7 == 0)
+ MA = (IP6_0 & 3) | ((BIC & 0x01ff) << 2); /* MA10-2 set to BIC8-0 */
+ else
+ MA = IP6_0;
+
+ /* convert RAM offset to eight bit addressing (2kx8 rather than 1k*16)
+ and apply base address offset */
+
+ MA_byte = MA << 1;
+ RAMWORD = (starwars_mathram[MA_byte + 1] & 0x00ff) | ((starwars_mathram[MA_byte] & 0x00ff) << 8);
+
+// logerror("MATH ADDR: %x, CPU ADDR: %x, RAMWORD: %x\n", MA, MA_byte, RAMWORD);
+
+ /*
+ * RAMWORD is the sixteen bit Math RAM value for the selected address
+ * MA_byte is the base address of this location as seen by the main CPU
+ * IP is the 16 bit instruction word from the PROM. IP7_0 have already
+ * been used in the address selection stage
+ * IP15_8 provide the instruction strobes
+ */
+
+
+ /* The accumulator is built from two ls299 (msb) and two ls164
+ * (lsb). You can only read/write the 16 msb. The lsb are
+ * used while adding up multiplication results giving better
+ * accuracy.
+ */
+
+ /* 0x10 - CLEAR_ACC */
+ if (IP15_8 & CLEAR_ACC)
+ {
+ ACC = 0;
+ }
+
+ /* 0x01 - LAC (also clears lsb)*/
+ if (IP15_8 & LAC)
+ ACC = (RAMWORD << 16);
+
+ /* 0x02 - READ_ACC */
+ if (IP15_8 & READ_ACC)
+ {
+ starwars_mathram[MA_byte+1] = ((ACC >> 16) & 0xff);
+ starwars_mathram[MA_byte ] = ((ACC >> 24) & 0xff);
+ }
+
+ /* 0x04 - M_HALT */
+ if (IP15_8 & M_HALT)
+ M_STOP = 0;
+
+ /* 0x08 - INC_BIC */
+ if (IP15_8 & INC_BIC)
+ BIC = (BIC + 1) & 0x1ff; /* Restrict to 9 bits */
+
+ /* 0x20 - LDC*/
+ if (IP15_8 & LDC)
+ {
+ C = RAMWORD;
+
+ /* This is a serial subtractor - multiplier (74ls384) -
+ * accumulator. For the full calculation 33 GMCLK pulses
+ * are generated. The calculation performed is:
+ *
+ * ACC = ACC + (A - B) * C
+ *
+ * 1. pulse: Bit 0 of A and B are subtracted. Bit 0 of the
+ * multiplication between multiplicand C and 0 is
+ * calculated (bit 0 of A-B is not yet at the multiplier
+ * input). Bit 0 of ACC is added to 0 (again, 'real' results
+ * from the previous operations are no yet there).
+ *
+ * 2. pulse: Bit 1 of A-B is calculated. Bit 1 of
+ * mutliplication is calculated based on bit 0 of A-B and
+ * bit 1 of C. Bit 1 of ACC is added to the multiplication
+ * result from first pulse.
+ *
+ * 3. pulse: Bit 2 of A-B is calculated. Bit 2 of
+ * mutliplication is calculated based on bit 1 of A-B and
+ * bit 2 of C. Bit 2 of ACC is added to the multiplication
+ * between bit 1 of C and bit 0 of A-B.
+ *
+ * etc.
+ *
+ * This pipeline causes the shifts between A-B, C and ACC.
+ * The 32 bit ACC and one bit adder form a ring so it
+ * takes 33 clock pulses to do a full rotation.
+ */
+
+ ACC += (((INT32)(A - B) << 1) * C) << 1;
+
+ /* A and B are sign extended (requred by the ls384). After
+ * multiplication they just contain the sign.
+ */
+ A = (A & 0x8000)? 0xffff: 0;
+ B = (B & 0x8000)? 0xffff: 0;
+ }
+
+ /* 0x40 - LDB */
+ if (IP15_8 & LDB)
+ B = RAMWORD;
+
+ /* 0x80 - LDA */
+ if (IP15_8 & LDA)
+ A = RAMWORD;
+
+ /*
+ * Now update the PROM address counter
+ * Done like this because the top two bits are not part of the counter
+ * This means that each of the four pages should wrap around rather than
+ * leaking from one to another. It may not matter, but I've put it in anyway
+ */
+ tmp = MPA + 1;
+ MPA = (MPA & 0x0300) | (tmp & 0x00ff); /* New MPA value */
+
+ M_STOP--; /* Decrease count */
+ }
+}
+
+
+
+/*************************************
+ *
+ * Pseudo-RNG read
+ *
+ *************************************/
+
+READ8_HANDLER( swmathbx_prng_r )
+{
+ /*
+ * The PRNG is a modified 23 bit LFSR. Taps are at 4 and 22 so the
+ * resulting LFSR polynomial is,
+ *
+ * x^5 + x^{23} + 1
+ *
+ * which is prime. It has a loop length of 8388607. The feedback
+ * bit is inverted so the PRNG can start with 0. Only 8 bits from
+ * bit 8 to 15 can be read by the CPU. The PRNG runs constantly at
+ * a clock speed of 3 MHz.
+ */
+
+ /* Use MAME's PRNG for now */
+ return mame_rand(Machine);
+}
+
+
+
+/*************************************
+ *
+ * Mathbox divider
+ *
+ *************************************/
+
+READ8_HANDLER( swmathbx_reh_r )
+{
+ return (quotient_shift & 0xff00) >> 8;
+}
+
+
+READ8_HANDLER( swmathbx_rel_r )
+{
+ return quotient_shift & 0x00ff;
+}
+
+
+WRITE8_HANDLER( swmathbx_w )
+{
+ int i;
+
+ data &= 0xff; /* ASG 971002 -- make sure we only get bytes here */
+ switch (offset)
+ {
+ case 0: /* mw0 */
+ MPA = data << 2; /* Set starting PROM address */
+ run_mbox(); /* and run the Mathbox */
+ break;
+
+ case 1: /* mw1 */
+ BIC = (BIC & 0x00ff) | ((data & 0x01) << 8);
+ break;
+
+ case 2: /* mw2 */
+ BIC = (BIC & 0x0100) | data;
+ break;
+
+ case 4: /* dvsrh */
+ divisor = (divisor & 0x00ff) | (data << 8);
+ dvd_shift = dividend;
+ quotient_shift = 0;
+ break;
+
+ case 5: /* dvsrl */
+ /* Note: Divide is triggered by write to low byte. This is */
+ /* dependant on the proper 16 bit write order in the */
+ /* 6809 emulation (high bytes, then low byte). */
+ /* If the Tie fighters look corrupt, he byte order of */
+ /* the 16 bit writes in the 6809 are backwards */
+
+ divisor = (divisor & 0xff00) | data;
+
+ /*
+ * Simple restoring division as shown in the
+ * schematics. The algorithm produces the same "wrong"
+ * results as the hardware if divisor < 2*dividend or
+ * divisor > 0x8000.
+ */
+ for (i = 1; i < 16; i++)
+ {
+ quotient_shift <<= 1;
+ if (((INT32)dvd_shift + (divisor ^ 0xffff) + 1) & 0x10000)
+ {
+ quotient_shift |= 1;
+ dvd_shift = (dvd_shift + (divisor ^ 0xffff) + 1) << 1;
+ }
+ else
+ {
+ dvd_shift <<= 1;
+ }
+ }
+ break;
+
+ case 6: /* dvddh */
+ dividend = (dividend & 0x00ff) | (data << 8);
+ break;
+
+ case 7: /* dvddl */
+ dividend = (dividend & 0xff00) | (data);
+ break;
+
+ default:
+ break;
+ }
+}
diff --git a/src/mame/machine/steppers.c b/src/mame/machine/steppers.c
new file mode 100644
index 00000000000..f680079d93f
--- /dev/null
+++ b/src/mame/machine/steppers.c
@@ -0,0 +1,746 @@
+///////////////////////////////////////////////////////////////////////////
+// //
+// steppers.c steppermotor emulation //
+// //
+// Emulates : 48 step motors driven with full step or half step //
+// also emulates the index optic //
+// //
+// 26-01-2007: J. Wallace - Rewritten to make it more flexible //
+// and to allow indices to be set in drivers //
+// 29-12-2006: J. Wallace - Added state save support //
+// 05-03-2004: Re-Animator //
+// //
+// TODO: add different types of stepper motors if needed //
+// //
+///////////////////////////////////////////////////////////////////////////
+
+#include "driver.h"
+#include "steppers.h"
+
+// local prototypes ///////////////////////////////////////////////////////
+
+static void update_optic(int id);
+
+// local vars /////////////////////////////////////////////////////////////
+
+static struct
+{
+ UINT8 pattern, // coil pattern
+ old_pattern, // old coil pattern
+ type; // reel type
+ INT16 step_pos, // step position 0 - max_steps
+ max_steps; // maximum step position
+
+ INT16 index_pos, // position of index (in steps)
+ index_len, // length of index (in steps)
+ index_patt; // pattern needed on coils (0=don't care)
+
+ UINT8 optic;
+
+} steppers[MAX_STEPPERS];
+
+
+// step table, use previouspattern::newpattern as index
+static const int StarpointStepTab[] =
+{
+ 0, //0000->0000 0->0
+ 0, //0000->0001 0->1
+ 0, //0000->0010 0->2
+ 0, //0000->0011 0->3
+ 0, //0000->0100 0->4
+ 0, //0000->0101 0->5
+ 0, //0000->0110 0->6
+ 0, //0000->0111 0->7
+ 0, //0000->1000 0->8
+ 0, //0000->1001 0->9
+ 0, //0000->1010 0->A
+ 0, //0000->1011 0->B
+ 0, //0000->1100 0->C
+ 0, //0000->1101 0->D
+ 0, //0000->1110 0->E
+ 0, //0000->1111 0->F
+
+ 0, //0001->0000 1->0
+ 0, //0001->0001 1->1
+ 0, //0001->0010 1->2
+ 0, //0001->0011 1->3
+ -2,//0001->0100 1->4
+ -1,//0001->0101 1->5
+ 0, //0001->0110 1->6
+ 0, //0001->0111 1->7
+ 2, //0001->1000 1->8
+ 1, //0001->1001 1->9
+ 0, //0001->1010 1->A
+ 0, //0001->1011 1->B
+ 0, //0001->1100 1->C
+ 0, //0001->1101 1->D
+ 0, //0001->1110 1->E
+ 0, //0001->1111 1->F
+
+ 0, //0010->0000 2->0
+ 0, //0010->0001 2->1
+ 0, //0010->0010 2->2
+ 0, //0010->0011 2->3
+ 2, //0010->0100 2->4
+ 0, //0010->0101 2->5
+ 1, //0010->0110 2->6
+ 0, //0010->0111 2->7
+ -2,//0010->1000 2->8
+ 0, //0010->1001 2->9
+ -1,//0010->1010 2->A
+ 0, //0010->1011 2->B
+ 0, //0010->1100 2->C
+ 0, //0010->1101 2->D
+ 0, //0010->1110 2->E
+ 0, //0010->1111 2->F
+
+ 0, //0011->0000 3->0
+ 0, //0011->0001 3->1
+ 0, //0011->0010 3->2
+ 0, //0011->0011 3->3
+ 0, //0011->0100 3->4
+ 0, //0011->0101 3->5
+ 0, //0011->0110 3->6
+ 0, //0011->0111 3->7
+ 0, //0011->1000 3->8
+ 0, //0011->1001 3->9
+ 0, //0011->1010 3->A
+ 0, //0011->1011 3->B
+ 0, //0011->1100 3->C
+ 0, //0011->1101 3->D
+ 0, //0011->1110 3->E
+ 0, //0011->1111 3->F
+
+ 0, //0100->0000 4->0
+ 2, //0100->0001 4->1
+ -2,//0100->0010 4->2
+ 0, //0100->0011 4->3
+ 0, //0100->0100 4->4
+ 1, //0100->0101 4->5
+ -1,//0100->0110 4->6
+ 0, //0100->0111 4->7
+ 0, //0100->1000 4->8
+ 0, //0100->1001 4->9
+ 0, //0100->1010 4->A
+ 0, //0100->1011 4->B
+ 0, //0100->1100 4->C
+ 0, //0100->1101 4->D
+ 0, //0100->1110 4->E
+ 0, //0100->1111 4->F
+
+ 0, //0101->0000 5->0
+ 1, //0101->0001 5->1
+ 0, //0101->0010 5->2
+ 0, //0101->0011 5->3
+ -1,//0101->0100 5->4
+ 0, //0101->0101 5->5
+ -2,//0101->0110 5->6
+ 0, //0101->0111 5->7
+ 0, //0101->1000 5->8
+ 2, //0101->1001 5->9
+ 0, //0101->1010 5->A
+ 0, //0101->1011 5->B
+ 0, //0101->1100 5->C
+ 0, //0101->1101 5->D
+ 0, //0101->1110 5->E
+ 0, //0101->1111 5->F
+
+ 0, //0110->0000 6->0
+ 0, //0110->0001 6->1
+ -1,//0110->0010 6->2
+ 0, //0110->0011 6->3
+ 1, //0110->0100 6->4
+ 2, //0110->0101 6->5
+ 0, //0110->0110 6->6
+ 0, //0110->0111 6->7
+ 0, //0110->1000 6->8
+ 0, //0110->1001 6->9
+ -2,//0110->1010 6->A
+ 0, //0110->1011 6->B
+ 0, //0110->1100 6->C
+ 0, //0110->1101 6->D
+ 0, //0110->1110 6->E
+ 0, //0110->1111 6->F
+
+ 0, //0111->0000 7->0
+ 0, //0111->0001 7->1
+ 0, //0111->0010 7->2
+ 0, //0111->0011 7->3
+ 0, //0111->0100 7->4
+ 0, //0111->0101 7->5
+ 0, //0111->0110 7->6
+ 0, //0111->0111 7->7
+ 0, //0111->1000 7->8
+ 0, //0111->1001 7->9
+ 0, //0111->1010 7->A
+ 0, //0111->1011 7->B
+ 0, //0111->1100 7->C
+ 0, //0111->1101 7->D
+ 0, //0111->1110 7->E
+ 0, //0111->1111 7->F
+
+ 0, //1000->0000 8->0
+ -2,//1000->0001 8->1
+ 2, //1000->0010 8->2
+ 0, //1000->0011 8->3
+ 0, //1000->0100 8->4
+ 0, //1000->0101 8->5
+ 0, //1000->0110 8->6
+ 0, //1000->0111 8->7
+ 0, //1000->1000 8->8
+ -1,//1000->1001 8->9
+ 1, //1000->1010 8->A
+ 0, //1000->1011 8->B
+ 0, //1000->1100 8->C
+ 0, //1000->1101 8->D
+ 0, //1000->1110 8->E
+ 0, //1000->1111 8->F
+
+ 0, //1001->0000 9->0
+ -1,//1001->0001 9->1
+ 0, //1001->0010 9->2
+ 0, //1001->0011 9->3
+ 0, //1001->0100 9->4
+ -2,//1001->0101 9->5
+ 0, //1001->0110 9->6
+ 0, //1001->0111 9->7
+ 1, //1001->1000 9->8
+ 0, //1001->1001 9->9
+ 2, //1001->1010 9->A
+ 0, //1001->1011 9->B
+ 0, //1001->1100 9->C
+ 0, //1001->1101 9->D
+ 0, //1001->1110 9->E
+ 0, //1001->1111 9->F
+
+ 0, //1010->0000 A->0
+ 0, //1010->0001 A->1
+ 1, //1010->0010 A->2
+ 0, //1010->0011 A->3
+ 0, //1010->0100 A->4
+ 0, //1010->0101 A->5
+ 2, //1010->0110 A->6
+ 0, //1010->0111 A->7
+ -1,//1010->1000 A->8
+ -2,//1010->1001 A->9
+ 0, //1010->1010 A->A
+ 0, //1010->1011 A->B
+ 0, //1010->1100 A->C
+ 0, //1010->1101 A->D
+ 0, //1010->1110 A->E
+ 0, //1010->1111 A->F
+
+ 0, //1011->0000 B->0
+ 0, //1011->0001 B->1
+ 0, //1011->0010 B->2
+ 0, //1011->0011 B->3
+ 0, //1011->0100 B->4
+ 0, //1011->0101 B->5
+ 0, //1011->0110 B->6
+ 0, //1011->0111 B->7
+ 0, //1011->1000 B->8
+ 0, //1011->1001 B->9
+ 0, //1011->1010 B->A
+ 0, //1011->1011 B->B
+ 0, //1011->1100 B->C
+ 0, //1011->1101 B->D
+ 0, //1011->1110 B->E
+ 0, //1011->1111 B->F
+
+ 0, //1100->0000 C->0
+ 0, //1100->0001 C->1
+ 0, //1100->0010 C->2
+ 0, //1100->0011 C->3
+ 0, //1100->0100 C->4
+ 0, //1100->0101 C->5
+ 0, //1100->0110 C->6
+ 0, //1100->0111 C->7
+ 0, //1100->1000 C->8
+ 0, //1100->1001 C->9
+ 0, //1100->1010 C->A
+ 0, //1100->1011 C->B
+ 0, //1100->1100 C->C
+ 0, //1100->1101 C->D
+ 0, //1100->1110 C->E
+ 0, //1100->1111 C->F
+
+ 0, //1101->0000 D->0
+ 0, //1101->0001 D->1
+ 0, //1101->0010 D->2
+ 0, //1101->0011 D->3
+ 0, //1101->0100 D->4
+ 0, //1101->0101 D->5
+ 0, //1101->0110 D->6
+ 0, //1101->0111 D->7
+ 0, //1101->1000 D->8
+ 0, //1101->1001 D->9
+ 0, //1101->1010 D->A
+ 0, //1101->1011 D->B
+ 0, //1101->1100 D->C
+ 0, //1101->1101 D->D
+ 0, //1101->1110 D->E
+ 0, //1101->1111 D->F
+
+ 0, //1110->0000 E->0
+ 0, //1110->0001 E->1
+ 0, //1110->0010 E->2
+ 0, //1110->0011 E->3
+ 0, //1110->0100 E->4
+ 0, //1110->0101 E->5
+ 0, //1110->0110 E->6
+ 0, //1110->0111 E->7
+ 0, //1110->1000 E->8
+ 0, //1110->1001 E->9
+ 0, //1110->1010 E->A
+ 0, //1110->1011 E->B
+ 0, //1110->1100 E->C
+ 0, //1110->1101 E->D
+ 0, //1110->1110 E->E
+ 0, //1110->1111 E->F
+
+ 0, //1111->0000 F->0
+ 0, //1111->0001 F->1
+ 0, //1111->0010 F->2
+ 0, //1111->0011 F->3
+ 0, //1111->0100 F->4
+ 0, //1111->0101 F->5
+ 0, //1111->0110 F->6
+ 0, //1111->0111 F->7
+ 0, //1111->1000 F->8
+ 0, //1111->1001 F->9
+ 0, //1111->1010 F->A
+ 0, //1111->1011 F->B
+ 0, //1111->1100 F->C
+ 0, //1111->1101 F->D
+ 0, //1111->1110 F->E
+ 0 //1111->1111 F->F
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+static const int BarcrestStepTab[] =
+{
+ 0, //0000->0000 0->0
+ 0, //0000->0001 0->1
+ 0, //0000->0010 0->2
+ 2, //0000->0011 0->3
+ 0, //0000->0100 0->4
+ 0, //0000->0101 0->5
+ 0, //0000->0110 0->6
+ 0, //0000->0111 0->7
+ 0, //0000->1000 0->8
+ 0, //0000->1001 0->9
+ 0, //0000->1010 0->A
+ 0, //0000->1011 0->B
+ 0, //0000->1100 0->C
+ 0, //0000->1101 0->D
+ 0, //0000->1110 0->E
+ 0, //0000->1111 0->F
+
+ 0, //0001->0000 1->0
+ 0, //0001->0001 1->1
+ 0, //0001->0010 1->2
+ 1, //0001->0011 1->3
+ 0,//0001->0100 1->4
+ 0,//0001->0101 1->5
+ 0, //0001->0110 1->6
+ 0, //0001->0111 1->7
+ 0, //0001->1000 1->8
+ -1, //0001->1001 1->9
+ 0, //0001->1010 1->A
+ 0, //0001->1011 1->B
+ 0, //0001->1100 1->C
+ 0, //0001->1101 1->D
+ 0, //0001->1110 1->E
+ 0, //0001->1111 1->F
+
+ 0, //0010->0000 2->0
+ 0, //0010->0001 2->1
+ 0, //0010->0010 2->2
+ -1, //0010->0011 2->3
+ 0, //0010->0100 2->4
+ 0, //0010->0101 2->5
+ 1, //0010->0110 2->6
+ 0, //0010->0111 2->7
+ 0,//0010->1000 2->8
+ 0, //0010->1001 2->9
+ 0,//0010->1010 2->A
+ 0, //0010->1011 2->B
+ 0, //0010->1100 2->C
+ 0, //0010->1101 2->D
+ 0, //0010->1110 2->E
+ 0, //0010->1111 2->F
+
+ 0, //0011->0000 3->0
+ -1, //0011->0001 3->1
+ 1, //0011->0010 3->2
+ 0, //0011->0011 3->3
+ 0, //0011->0100 3->4
+ 0, //0011->0101 3->5
+ 2, //0011->0110 3->6
+ 0, //0011->0111 3->7
+ 0, //0011->1000 3->8
+ -2, //0011->1001 3->9
+ 0, //0011->1010 3->A
+ 0, //0011->1011 3->B
+ 0, //0011->1100 3->C
+ 0, //0011->1101 3->D
+ 0, //0011->1110 3->E
+ 0, //0011->1111 3->F
+
+ 0, //0100->0000 4->0
+ 0, //0100->0001 4->1
+ 0,//0100->0010 4->2
+ 0, //0100->0011 4->3
+ 0, //0100->0100 4->4
+ 0, //0100->0101 4->5
+ -1,//0100->0110 4->6
+ 0, //0100->0111 4->7
+ 0, //0100->1000 4->8
+ 0, //0100->1001 4->9
+ 0, //0100->1010 4->A
+ 0, //0100->1011 4->B
+ 1, //0100->1100 4->C
+ 0, //0100->1101 4->D
+ 0, //0100->1110 4->E
+ 0, //0100->1111 4->F
+
+ 0, //0101->0000 5->0
+ 0, //0101->0001 5->1
+ 0, //0101->0010 5->2
+ 0, //0101->0011 5->3
+ 0,//0101->0100 5->4
+ 0, //0101->0101 5->5
+ 0,//0101->0110 5->6
+ 0, //0101->0111 5->7
+ 0, //0101->1000 5->8
+ 0, //0101->1001 5->9
+ 0, //0101->1010 5->A
+ 0, //0101->1011 5->B
+ 0, //0101->1100 5->C
+ 0, //0101->1101 5->D
+ 0, //0101->1110 5->E
+ 0, //0101->1111 5->F
+
+ 0, //0110->0000 6->0
+ 0, //0110->0001 6->1
+ -1,//0110->0010 6->2
+ -2,//0110->0011 6->3
+ 1, //0110->0100 6->4
+ 0, //0110->0101 6->5
+ 0, //0110->0110 6->6
+ 0, //0110->0111 6->7
+ 0, //0110->1000 6->8
+ 0, //0110->1001 6->9
+ 0,//0110->1010 6->A
+ 0, //0110->1011 6->B
+ 2, //0110->1100 6->C
+ 0, //0110->1101 6->D
+ 0, //0110->1110 6->E
+ 0, //0110->1111 6->F
+
+ 0, //0111->0000 7->0
+ 0, //0111->0001 7->1
+ 0, //0111->0010 7->2
+ 0, //0111->0011 7->3
+ 0, //0111->0100 7->4
+ 0, //0111->0101 7->5
+ 0, //0111->0110 7->6
+ 0, //0111->0111 7->7
+ 0, //0111->1000 7->8
+ 0, //0111->1001 7->9
+ 0, //0111->1010 7->A
+ 0, //0111->1011 7->B
+ 0, //0111->1100 7->C
+ 0, //0111->1101 7->D
+ 0, //0111->1110 7->E
+ 0, //0111->1111 7->F
+
+ 0, //1000->0000 8->0
+ 0,//1000->0001 8->1
+ 0, //1000->0010 8->2
+ 0, //1000->0011 8->3
+ 0, //1000->0100 8->4
+ 0, //1000->0101 8->5
+ 0, //1000->0110 8->6
+ 0, //1000->0111 8->7
+ 0, //1000->1000 8->8
+ 1, //1000->1001 8->9
+ 0, //1000->1010 8->A
+ 0, //1000->1011 8->B
+ -1, //1000->1100 8->C
+ 0, //1000->1101 8->D
+ 0, //1000->1110 8->E
+ 0, //1000->1111 8->F
+
+ 0, //1001->0000 9->0
+ 1, //1001->0001 9->1
+ 0, //1001->0010 9->2
+ 2, //1001->0011 9->3
+ 0, //1001->0100 9->4
+ 0,//1001->0101 9->5
+ 0, //1001->0110 9->6
+ 0, //1001->0111 9->7
+ -1, //1001->1000 9->8
+ 0, //1001->1001 9->9
+ 0, //1001->1010 9->A
+ 0, //1001->1011 9->B
+ -2, //1001->1100 9->C
+ 0, //1001->1101 9->D
+ 0, //1001->1110 9->E
+ 0, //1001->1111 9->F
+
+ 0, //1010->0000 A->0
+ 0, //1010->0001 A->1
+ 0, //1010->0010 A->2
+ 0, //1010->0011 A->3
+ 0, //1010->0100 A->4
+ 0, //1010->0101 A->5
+ 0, //1010->0110 A->6
+ 0, //1010->0111 A->7
+ 0,//1010->1000 A->8
+ 0,//1010->1001 A->9
+ 0, //1010->1010 A->A
+ 0, //1010->1011 A->B
+ 0, //1010->1100 A->C
+ 0, //1010->1101 A->D
+ 0, //1010->1110 A->E
+ 0, //1010->1111 A->F
+
+ 0, //1011->0000 B->0
+ 0, //1011->0001 B->1
+ 0, //1011->0010 B->2
+ 0, //1011->0011 B->3
+ 0, //1011->0100 B->4
+ 0, //1011->0101 B->5
+ 0, //1011->0110 B->6
+ 0, //1011->0111 B->7
+ 0, //1011->1000 B->8
+ 0, //1011->1001 B->9
+ 0, //1011->1010 B->A
+ 0, //1011->1011 B->B
+ 0, //1011->1100 B->C
+ 0, //1011->1101 B->D
+ 0, //1011->1110 B->E
+ 0, //1011->1111 B->F
+
+ 0, //1100->0000 C->0
+ 0, //1100->0001 C->1
+ 0, //1100->0010 C->2
+ 0, //1100->0011 C->3
+ -1, //1100->0100 C->4
+ 0, //1100->0101 C->5
+ -2, //1100->0110 C->6
+ 0, //1100->0111 C->7
+ 1, //1100->1000 C->8
+ 2, //1100->1001 C->9
+ 0, //1100->1010 C->A
+ 0, //1100->1011 C->B
+ 0, //1100->1100 C->C
+ 0, //1100->1101 C->D
+ 0, //1100->1110 C->E
+ 0, //1100->1111 C->F
+
+ 0, //1101->0000 D->0
+ 0, //1101->0001 D->1
+ 0, //1101->0010 D->2
+ 0, //1101->0011 D->3
+ 0, //1101->0100 D->4
+ 0, //1101->0101 D->5
+ 0, //1101->0110 D->6
+ 0, //1101->0111 D->7
+ 0, //1101->1000 D->8
+ 0, //1101->1001 D->9
+ 0, //1101->1010 D->A
+ 0, //1101->1011 D->B
+ 0, //1101->1100 D->C
+ 0, //1101->1101 D->D
+ 0, //1101->1110 D->E
+ 0, //1101->1111 D->F
+
+ 0, //1110->0000 E->0
+ 0, //1110->0001 E->1
+ 0, //1110->0010 E->2
+ 0, //1110->0011 E->3
+ 0, //1110->0100 E->4
+ 0, //1110->0101 E->5
+ 0, //1110->0110 E->6
+ 0, //1110->0111 E->7
+ 0, //1110->1000 E->8
+ 0, //1110->1001 E->9
+ 0, //1110->1010 E->A
+ 0, //1110->1011 E->B
+ 0, //1110->1100 E->C
+ 0, //1110->1101 E->D
+ 0, //1110->1110 E->E
+ 0, //1110->1111 E->F
+
+ 0, //1111->0000 F->0
+ 0, //1111->0001 F->1
+ 0, //1111->0010 F->2
+ 0, //1111->0011 F->3
+ 0, //1111->0100 F->4
+ 0, //1111->0101 F->5
+ 0, //1111->0110 F->6
+ 0, //1111->0111 F->7
+ 0, //1111->1000 F->8
+ 0, //1111->1001 F->9
+ 0, //1111->1010 F->A
+ 0, //1111->1011 F->B
+ 0, //1111->1100 F->C
+ 0, //1111->1101 F->D
+ 0, //1111->1110 F->E
+ 0 //1111->1111 F->F
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+void Stepper_init(int id, int type)
+{
+ if ( id < MAX_STEPPERS )
+ {
+ steppers[id].index_pos = 16;
+ steppers[id].index_len = 8;
+ steppers[id].index_patt = 0x09;
+ steppers[id].pattern = 0;
+ steppers[id].old_pattern = 0;
+ steppers[id].step_pos = 0;
+ steppers[id].max_steps = (48*2)-1;
+ steppers[id].type = type;
+
+ switch ( steppers[id].type )
+ {
+ case STEPPER_48STEP_REEL : // STARPOINT RMxxx
+ break;
+ case BARCREST_48STEP_REEL : // Barcrest reel units have different coil windings
+ steppers[id].index_pos = 0;
+ steppers[id].index_len = 16;
+ steppers[id].index_patt = 0x09;
+ break;
+ case STEPPER_144STEPS_DICE : // STARPOINT 1DCU DICE mechanism
+ steppers[id].max_steps = (144*2)-1;
+ break;
+ }
+ state_save_register_item("Stepper", id, steppers[id].index_pos);
+ state_save_register_item("Stepper", id, steppers[id].index_len);
+ state_save_register_item("Stepper", id, steppers[id].index_patt);
+ state_save_register_item("Stepper", id, steppers[id].pattern);
+ state_save_register_item("Stepper", id, steppers[id].old_pattern);
+ state_save_register_item("Stepper", id, steppers[id].step_pos);
+ state_save_register_item("Stepper", id, steppers[id].max_steps);
+ state_save_register_item("Stepper", id, steppers[id].type);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+void Stepper_set_index(int id,int position,int length,int pattern)
+{
+ steppers[id].index_pos = position;//location of first index value in half steps
+ steppers[id].index_len = length;//number of half steps the index lasts
+ steppers[id].index_patt = pattern;//hex value of coil pattern
+}
+
+int Stepper_get_position(int id)
+{
+ return steppers[id].step_pos;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+int Stepper_get_max(int id)
+{
+ return steppers[id].max_steps;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static void update_optic(int id)
+{
+ int pos = steppers[id].step_pos,
+ index = steppers[id].index_pos;
+
+ if ( ( pos >= index ) && ( pos < index + steppers[id].index_len ) &&
+ ( ( steppers[id].pattern == steppers[id].index_patt || steppers[id].index_patt==0) ||
+ ( steppers[id].pattern == 0 &&
+ (steppers[id].old_pattern == steppers[id].index_patt || steppers[id].index_patt==0)
+ ) ) )
+ {
+ steppers[id].optic = 1;
+ }
+ else steppers[id].optic = 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void Stepper_reset_position(int id)
+{
+ steppers[id].step_pos = 0;
+ steppers[id].pattern = 0x00;
+ steppers[id].old_pattern = 0x00;
+
+ update_optic(id);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+int Stepper_optic_state(int id)
+{
+ int result = 0;
+
+ if ( id < MAX_STEPPERS )
+ {
+ result = steppers[id].optic;
+ }
+
+ return result;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+int Stepper_update(int id, UINT8 pattern)
+{
+ int changed = 0;
+
+ pattern &= 0x0F;
+
+ if ( steppers[id].pattern != pattern )
+ { // pattern changed
+ int index,
+ steps,
+ pos;
+
+ if ( steppers[id].pattern )
+ {
+ steppers[id].old_pattern = steppers[id].pattern;
+ }
+ steppers[id].pattern = pattern;
+
+ index = (steppers[id].old_pattern << 4) | pattern;
+ switch ( steppers[id].type )
+ {
+ default:
+ case STEPPER_48STEP_REEL : // STARPOINT RMxxx
+ case STEPPER_144STEPS_DICE : // STARPOINT 1DCU DICE mechanism
+ steps = StarpointStepTab[ index ];
+ break;
+ case BARCREST_48STEP_REEL : // Barcrest reel units have different optics
+ steps = BarcrestStepTab[ index ];
+ break;
+ }
+// if ( id ==0 )logerror("Id %d Index %d Steps %d Pattern Old %02X New %02X\n",id,index,steps,steppers[id].old_pattern,steppers[id].pattern);
+
+ if ( steps )
+ {
+ pos = steppers[id].step_pos + steps;
+
+ if ( pos > steppers[id].max_steps ) pos -= steppers[id].max_steps;
+ else if ( pos < 0 ) pos += steppers[id].max_steps;
+
+ steppers[id].step_pos = pos;
+ update_optic(id);
+
+ changed++;
+ }
+ }
+ return changed;
+}
diff --git a/src/mame/machine/steppers.h b/src/mame/machine/steppers.h
new file mode 100644
index 00000000000..ad6094be1f8
--- /dev/null
+++ b/src/mame/machine/steppers.h
@@ -0,0 +1,40 @@
+///////////////////////////////////////////////////////////////////////////
+// //
+// Steppermotor emulation //
+// //
+// Emulates : 48 step motors driven with full step or half step //
+// also emulates the index optic //
+// //
+// 26-01-2007: J. Wallace - Rewritten to make it more flexible //
+// and to allow indices to be set in drivers //
+// 29-12-2006: J. Wallace - Added state save support //
+// 05-03-2004: Re-Animator //
+// //
+// TODO: add different types of stepper motors if needed //
+// //
+///////////////////////////////////////////////////////////////////////////
+
+
+#ifndef INC_STEPPERS
+#define INC_STEPPERS
+
+#define MAX_STEPPERS 16 // maximum number of steppers
+
+#define STEPPER_48STEP_REEL 0 // STARPOINT RMXXX reel unit
+#define BARCREST_48STEP_REEL 1 // Barcrest bespoke reel unit
+#define STEPPER_144STEPS_DICE 2 // STARPOINT 1DCU DICE mechanism - tech sheet available on request
+
+void Stepper_init( int id, int type); // init a stepper motor
+
+void Stepper_reset_position(int id); // reset a motor to position 0
+
+int Stepper_optic_state( int id); // read a motor's optics
+
+void Stepper_set_index(int id,int position,int length,int pattern);
+
+int Stepper_update(int id, UINT8 pattern); // update a motor
+
+int Stepper_get_position(int id); // get current position in half steps
+
+int Stepper_get_max(int id); // get maximum position in half steps
+#endif
diff --git a/src/mame/machine/stfight.c b/src/mame/machine/stfight.c
new file mode 100644
index 00000000000..623d9802963
--- /dev/null
+++ b/src/mame/machine/stfight.c
@@ -0,0 +1,244 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/z80/z80.h"
+#include "sound/msm5205.h"
+
+// this prototype will move to the driver
+static WRITE8_HANDLER( stfight_bank_w );
+
+
+/*
+
+Encryption PAL 16R4 on CPU board
+
+ +---U---+
+ CP --| |-- VCC
+ ROM D1 --| |-- ROM D0 M1 = 0 M1 = 1
+ ROM D3 --| |-- (NC)
+ ROM D4 --| |-- D6 D6 = D1 ^^ D3 D6 = / ( D1 ^^ D0 )
+ ROM D6 --| |-- D4 D4 = / ( D6 ^^ A7 ) D4 = D3 ^^ A0
+ A0 --| |-- D3 D3 = / ( D0 ^^ A1 ) D3 = D4 ^^ A4
+ A1 --| |-- D0 D0 = D1 ^^ D4 D0 = / ( D6 ^^ A0 )
+ A4 --| |-- (NC)
+ A7 --| |-- /M1
+ GND --| |-- /OE
+ +-------+
+
+*/
+
+static UINT8 *decrypt;
+
+DRIVER_INIT( empcity )
+{
+ UINT8 *rom = memory_region(REGION_CPU1);
+ int A;
+
+ decrypt = auto_malloc(0x8000);
+ memory_set_decrypted_region(0, 0x0000, 0x7fff, decrypt);
+
+ for (A = 0;A < 0x8000;A++)
+ {
+ UINT8 src = rom[A];
+
+ // decode opcode
+ decrypt[A] =
+ ( src & 0xA6 ) |
+ ( ( ( ( src << 2 ) ^ src ) << 3 ) & 0x40 ) |
+ ( ~( ( src ^ ( A >> 1 ) ) >> 2 ) & 0x10 ) |
+ ( ~( ( ( src << 1 ) ^ A ) << 2 ) & 0x08 ) |
+ ( ( ( src ^ ( src >> 3 ) ) >> 1 ) & 0x01 );
+
+ // decode operand
+ rom[A] =
+ ( src & 0xA6 ) |
+ ( ~( ( src ^ ( src << 1 ) ) << 5 ) & 0x40 ) |
+ ( ( ( src ^ ( A << 3 ) ) << 1 ) & 0x10 ) |
+ ( ( ( src ^ A ) >> 1 ) & 0x08 ) |
+ ( ~( ( src >> 6 ) ^ A ) & 0x01 );
+ }
+}
+
+DRIVER_INIT( stfight )
+{
+ driver_init_empcity(machine);
+
+ /* patch out a tight loop during startup - is the code waiting */
+ /* for NMI to wake it up? */
+ decrypt[0xb1] = 0x00;
+ decrypt[0xb2] = 0x00;
+ decrypt[0xb3] = 0x00;
+ decrypt[0xb4] = 0x00;
+ decrypt[0xb5] = 0x00;
+}
+
+MACHINE_RESET( stfight )
+{
+ // initialise rom bank
+ stfight_bank_w( 0, 0 );
+}
+
+// It's entirely possible that this bank is never switched out
+// - in fact I don't even know how/where it's switched in!
+static WRITE8_HANDLER( stfight_bank_w )
+{
+ UINT8 *ROM2 = memory_region(REGION_CPU1) + 0x10000;
+
+ memory_set_bankptr( 1, &ROM2[data<<14] );
+}
+
+/*
+ * CPU 1 timed interrupt - 60Hz???
+ */
+
+static TIMER_CALLBACK( stfight_interrupt_1 )
+{
+ // Do a RST08
+ cpunum_set_input_line_and_vector(0,0,HOLD_LINE,0xcf);
+}
+
+INTERRUPT_GEN( stfight_vb_interrupt )
+{
+ // Do a RST10
+ cpunum_set_input_line_and_vector(0,0,HOLD_LINE,0xd7);
+ timer_set(ATTOTIME_IN_HZ(120), 0, stfight_interrupt_1);
+}
+
+/*
+ * Hardware handlers
+ */
+
+// Perhaps define dipswitches as active low?
+READ8_HANDLER( stfight_dsw_r )
+{
+ return( ~readinputport( 3+offset ) );
+}
+
+static int stfight_coin_mech_query_active = 0;
+static int stfight_coin_mech_query;
+
+READ8_HANDLER( stfight_coin_r )
+{
+ static int coin_mech_latch[2] = { 0x02, 0x01 };
+
+ int coin_mech_data;
+ int i;
+
+ // Was the coin mech queried by software?
+ if( stfight_coin_mech_query_active )
+ {
+ stfight_coin_mech_query_active = 0;
+ return( (~stfight_coin_mech_query) & 0x03 );
+ }
+
+ /*
+ * Is this really necessary?
+ * - we can control impulse length so that the port is
+ * never strobed twice within the impulse period
+ * since it's read by the 30Hz interrupt ISR
+ */
+
+ coin_mech_data = readinputport( 5 );
+
+ for( i=0; i<2; i++ )
+ {
+ /* Only valid on signal edge */
+ if( ( coin_mech_data & (1<<i) ) != coin_mech_latch[i] )
+ coin_mech_latch[i] = coin_mech_data & (1<<i);
+ else
+ coin_mech_data |= coin_mech_data & (1<<i);
+ }
+
+ return( coin_mech_data );
+}
+
+WRITE8_HANDLER( stfight_coin_w )
+{
+ // interrogate coin mech
+ stfight_coin_mech_query_active = 1;
+ stfight_coin_mech_query = data;
+}
+
+/*
+ * Machine hardware for MSM5205 ADPCM sound control
+ */
+
+static int sampleLimits[] =
+{
+ 0x0000, // machine gun fire?
+ 0x1000, // player getting shot
+ 0x2C00, // player shooting
+ 0x3C00, // girl screaming
+ 0x5400, // girl getting shot
+ 0x7200 // (end of samples)
+};
+static int adpcm_data_offs;
+static int adpcm_data_end;
+
+void stfight_adpcm_int( int data )
+{
+ static int toggle;
+ UINT8 *SAMPLES = memory_region(REGION_SOUND1);
+ int adpcm_data = SAMPLES[adpcm_data_offs & 0x7fff];
+
+ // finished playing sample?
+ if( adpcm_data_offs == adpcm_data_end )
+ {
+ MSM5205_reset_w( 0, 1 );
+ return;
+ }
+
+ if( toggle == 0 )
+ MSM5205_data_w( 0, ( adpcm_data >> 4 ) & 0x0f );
+ else
+ {
+ MSM5205_data_w( 0, adpcm_data & 0x0f );
+ adpcm_data_offs++;
+ }
+
+ toggle ^= 1;
+}
+
+WRITE8_HANDLER( stfight_adpcm_control_w )
+{
+ if( data < 0x08 )
+ {
+ adpcm_data_offs = sampleLimits[data];
+ adpcm_data_end = sampleLimits[data+1];
+ }
+
+ MSM5205_reset_w( 0, data & 0x08 ? 1 : 0 );
+}
+
+WRITE8_HANDLER( stfight_e800_w )
+{
+}
+
+/*
+ * Machine hardware for YM2303 fm sound control
+ */
+
+static UINT8 fm_data;
+
+WRITE8_HANDLER( stfight_fm_w )
+{
+ // the sound cpu ignores any fm data without bit 7 set
+ fm_data = 0x80 | data;
+}
+
+READ8_HANDLER( stfight_fm_r )
+{
+ int data = fm_data;
+
+ // clear the latch?!?
+ fm_data &= 0x7f;
+
+ return( data );
+}
diff --git a/src/mame/machine/strtheat.c b/src/mame/machine/strtheat.c
new file mode 100644
index 00000000000..8c888c9b1e7
--- /dev/null
+++ b/src/mame/machine/strtheat.c
@@ -0,0 +1,194 @@
+/***************************************************************************
+
+ machine.c
+
+ Street Heat runs on the same type board as theglobp. It features 4 decryption algorythms
+that can be implemented sequentially using the IN command. See machine\theglobp.c for more
+details. The advantage of this is weak sections can be isolated. The key that contains the
+text is obviously easily broken as is the boot section. The remaining 2 keys are not used
+much which means there's not much data to look at. Knowing the last command in a section
+will be IN is enough of a clue to break it though.
+
+ This system is fairly effective in preventing decrypted roms. Certain key addresses are
+read in all 4 states. That is easily patched, but in at least some of the games encrypted
+program code is read in the wrong key as data and used as sound data. A
+plaintext version of the roms produces things like 30 second long coinup sounds.
+
+ - David Widel (d_widel@hotmail.com)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "includes/dkong.h"
+
+static void strtheat_decrypt_rom_8(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* start c */
+ newbyte = (inverted_oldbyte & 0x80) >> 3;
+ newbyte |= (inverted_oldbyte & 0x40) >> 0;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (inverted_oldbyte & 0x10) >> 2;
+ newbyte |= (inverted_oldbyte & 0x08) >> 0;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (oldbyte & 0x02) << 4;
+ newbyte |= (oldbyte & 0x01) << 7;
+
+ RAM[mem + 0x10000] = newbyte;
+ }
+}
+
+static void strtheat_decrypt_rom_9(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* d */
+ newbyte = (oldbyte & 0x80) >> 5;
+ newbyte |= (inverted_oldbyte & 0x40) << 0;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (inverted_oldbyte & 0x10) << 1;
+ newbyte |= (inverted_oldbyte & 0x08) << 0;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x02) << 3;
+ newbyte |= (oldbyte & 0x01) << 7;
+
+ RAM[mem + 0x14000] = newbyte;
+ }
+}
+
+static void strtheat_decrypt_rom_A(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* DAHF bGcE dis B */
+ newbyte = (inverted_oldbyte & 0x80) >> 3;
+ newbyte |= (inverted_oldbyte & 0x40) << 1;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (inverted_oldbyte & 0x10) >> 2;
+ newbyte |= (oldbyte & 0x08) << 3;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (oldbyte & 0x02) << 4;
+ newbyte |= (inverted_oldbyte & 0x01) << 3;
+
+ RAM[mem + 0x18000] = newbyte;
+ }
+}
+
+static void strtheat_decrypt_rom_B(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* a ascii fAHCbGDE */
+ newbyte = (oldbyte & 0x80) >> 5;
+ newbyte |= (inverted_oldbyte & 0x40) << 1;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ newbyte |= (inverted_oldbyte & 0x10) << 1;
+ newbyte |= (oldbyte & 0x08) << 3;
+ newbyte |= (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x02) << 3;
+ newbyte |= (inverted_oldbyte & 0x01) << 3;
+
+ RAM[mem + 0x1C000] = newbyte;
+ }
+}
+
+static READ8_HANDLER( strtheat_inputport_0_r )
+{
+ if(readinputport(3) & 0x40)
+ {
+ /* Joystick inputs */
+ return readinputport(0);
+ }
+ else
+ {
+ /* Steering Wheel inputs */
+ return (readinputport(0) & ~3) | (readinputport(4) & 3);
+ }
+}
+
+static READ8_HANDLER( strtheat_inputport_1_r )
+{
+ if(readinputport(3) & 0x40)
+ {
+ /* Joystick inputs */
+ return readinputport(1);
+ }
+ else
+ {
+ /* Steering Wheel inputs */
+ return (readinputport(1) & ~3) | (readinputport(5) & 3);
+ }
+}
+
+DRIVER_INIT( strtheat )
+{
+ /* While the PAL supports up to 16 decryption methods, only four
+ are actually used in the PAL. Therefore, we'll take a little
+ memory overhead and decrypt the ROMs using each method in advance. */
+ strtheat_decrypt_rom_8();
+ strtheat_decrypt_rom_9();
+ strtheat_decrypt_rom_A();
+ strtheat_decrypt_rom_B();
+
+ /* custom handlers supporting Joystick or Steering Wheel */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x7c00, 0x7c00, 0, 0, strtheat_inputport_0_r);
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x7c80, 0x7c80, 0, 0, strtheat_inputport_1_r);
+}
diff --git a/src/mame/machine/stvcd.c b/src/mame/machine/stvcd.c
new file mode 100644
index 00000000000..58548adf9e8
--- /dev/null
+++ b/src/mame/machine/stvcd.c
@@ -0,0 +1,1856 @@
+/***************************************************************************
+
+ machine/stvcd.c - Sega Saturn and ST-V CD-ROM handling
+
+ Rewritten (again) 2007 by R. Belmont.
+
+ Status: All known discs at least load their executable, and many load
+ some data files successfully, but there are other problems.
+
+ Information sources:
+ - Tyranid's document
+ - A commented disassembly I made of the Saturn BIOS's CD code
+ - Yabuse's cs2.c
+ - The ISO/IEC "Yellow Book" CD-ROM standard, 1995 version
+
+ Address is mostly in terms of FAD (Frame ADdress).
+ FAD is absolute number of frames from the start of the disc.
+ In other words, FAD = LBA + 150; FAD is the same units as
+ LBA except it counts starting at absolute zero instead of
+ the first sector (00:02:00 in MSF format).
+
+***************************************************************************/
+
+#include "driver.h"
+#ifdef MESS
+#include "devices/chd_cd.h"
+#endif
+#include "cdrom.h"
+#include "stvcd.h"
+#include <stdio.h>
+
+// super-verbose
+#if 0
+#define CDROM_LOG(x) printf x;
+#else
+#define CDROM_LOG(x)
+#endif
+
+static cdrom_file *cdrom = (cdrom_file *)NULL;
+
+static void cd_readTOC(void);
+static void cd_readblock(UINT32 fad, UINT8 *dat);
+static void cd_playdata(void);
+
+#define MAX_FILTERS (24)
+#define MAX_BLOCKS (200)
+
+typedef struct
+{
+ UINT8 flags; // iso9660 flags
+ UINT32 length; // length of file
+ UINT32 firstfad; // first sector of file
+ UINT8 name[128];
+} direntryT;
+
+typedef struct
+{
+ UINT8 mode;
+ UINT8 chan;
+ UINT8 smmask;
+ UINT8 cimask;
+ UINT8 fid;
+ UINT8 smval;
+ UINT8 cival;
+ UINT8 condtrue;
+ UINT8 condfalse;
+ UINT32 fad;
+ UINT32 range;
+} filterT;
+
+typedef struct
+{
+ INT32 size; // size of block
+ INT32 FAD; // FAD on disc
+ UINT8 data[CD_MAX_SECTOR_DATA];
+ UINT8 chan; // channel
+ UINT8 fnum; // file number
+ UINT8 subm; // subchannel mode
+ UINT8 cinf; // coding information
+} blockT;
+
+typedef struct
+{
+ INT32 size;
+ blockT *blocks[MAX_BLOCKS];
+ UINT8 bnum[MAX_BLOCKS];
+ UINT8 numblks;
+} partitionT;
+
+// 16-bit transfer types
+typedef enum
+{
+ XFERTYPE_INVALID,
+ XFERTYPE_TOC,
+ XFERTYPE_FILEINFO_1,
+ XFERTYPE_FILEINFO_254
+} transT;
+
+// 32-bit transfer types
+typedef enum
+{
+ XFERTYPE32_INVALID,
+ XFERTYPE32_GETSECTOR,
+ XFERTYPE32_GETDELETESECTOR
+} trans32T;
+
+// local variables
+static emu_timer *sector_timer;
+static partitionT partitions[MAX_FILTERS];
+static partitionT *transpart;
+
+static blockT blocks[MAX_BLOCKS];
+static blockT curblock;
+
+static UINT8 tocbuf[102*4];
+static UINT8 finfbuf[256];
+static UINT8 onesectorstored;
+
+static INT32 sectlenin, sectlenout;
+
+static UINT8 lastbuf, playtype;
+
+static transT xfertype;
+static trans32T xfertype32;
+static UINT32 xfercount, calcsize;
+static UINT32 xferoffs, xfersect, xfersectpos, xfersectnum, xferdnum;
+
+static filterT filters[MAX_FILTERS];
+static filterT *cddevice;
+static int cddevicenum;
+
+static UINT16 cr1, cr2, cr3, cr4;
+static UINT16 hirqmask, hirqreg;
+static UINT16 cd_stat;
+static UINT32 cd_curfad = 0;
+static UINT32 in_buffer = 0; // amount of data in the buffer
+static int oddframe = 0;
+static UINT32 fadstoplay = 0;
+static int buffull, sectorstore, freeblocks;
+
+// iso9660 utilities
+static void read_new_dir(UINT32 fileno);
+static void make_dir_current(UINT32 fad);
+
+static direntryT curroot; // root entry of current filesystem
+static direntryT *curdir; // current directory
+static int numfiles; // # of entries in current directory
+static int firstfile; // first non-directory file
+
+// HIRQ definitions
+#define CMOK 0x0001 // command ok / ready for new command
+#define DRDY 0x0002 // drive ready
+#define CSCT 0x0004 // sector ready (?)
+#define BFUL 0x0008 // buffer full
+#define PEND 0x0010 // command pending
+#define DCHG 0x0020 // disc change / tray open
+#define ESEL 0x0040 // soft reset, end of blah
+#define EHST 0x0080 //
+#define ECPY 0x0100 //
+#define EFLS 0x0200 // stop execution of cd block filesystem
+#define SCDQ 0x0400 // subcode Q renewal complete
+#define MPED 0x0800 // MPEG
+#define MPCM 0x1000 // MPEG
+#define MPST 0x2000 // MPEG
+
+// CD status (hi byte of CR1) definitions:
+// (these defines are shifted up 8)
+#define CD_STAT_BUSY 0x0000 // status change in progress
+#define CD_STAT_PAUSE 0x0100 // CD block paused (temporary stop)
+#define CD_STAT_STANDBY 0x0200 // CD drive stopped
+#define CD_STAT_PLAY 0x0300 // CD play in progress
+#define CD_STAT_SEEK 0x0400 // drive seeking
+#define CD_STAT_SCAN 0x0500 // drive scanning
+#define CD_STAT_OPEN 0x0600 // tray is open
+#define CD_STAT_NODISC 0x0700 // no disc present
+#define CD_STAT_RETRY 0x0800 // read retry in progress
+#define CD_STAT_ERROR 0x0900 // read data error occured
+#define CD_STAT_FATAL 0x0a00 // fatal error (hard reset required)
+#define CD_STAT_PERI 0x2000 // periodic response if set, else command response
+#define CD_STAT_TRANS 0x4000 // data transfer request if set
+#define CD_STAT_WAIT 0x8000 // waiting for command if set, else executed immediately
+#define CD_STAT_REJECT 0xff00 // ultra-fatal error.
+
+static TIMER_CALLBACK( sector_cb )
+{
+ if (fadstoplay)
+ {
+ cd_playdata();
+ }
+ else
+ {
+ hirqreg |= SCDQ;
+ }
+
+ cd_stat |= CD_STAT_PERI;
+ cr1 = cd_stat;
+ cr2 = 0x4101;
+ cr3 = (cd_curfad>>16)&0xff;
+ cr4 = cd_curfad;
+
+ timer_adjust(sector_timer, ATTOTIME_IN_HZ(150), 0, attotime_zero);
+}
+
+// global functions
+void stvcd_reset(void)
+{
+ INT32 i, j;
+
+ hirqmask = 0xffff;
+ hirqreg = 0xffff;
+ cr1 = 'C';
+ cr2 = ('D'<<8) | 'B';
+ cr3 = ('L'<<8) | 'O';
+ cr4 = ('C'<<8) | 'K';
+ cd_stat = CD_STAT_PAUSE;
+
+ if (curdir != (direntryT *)NULL)
+ free((void *)curdir);
+ curdir = (direntryT *)NULL; // no directory yet
+
+ xfertype = XFERTYPE_INVALID;
+ xfertype32 = XFERTYPE32_INVALID;
+
+ // reset flag vars
+ buffull = sectorstore = 0;
+
+ freeblocks = 200;
+
+ sectlenin = sectlenout = 2048;
+
+ lastbuf = 0xff;
+
+ // reset buffer partitions
+ for (i = 0; i < MAX_FILTERS; i++)
+ {
+ partitions[i].size = -1;
+ partitions[i].numblks = 0;
+
+ for (j = 0; j < MAX_BLOCKS; j++)
+ {
+ partitions[i].blocks[j] = (blockT *)NULL;
+ partitions[i].bnum[j] = 0xff;
+ }
+ }
+
+ // reset blocks
+ for (i = 0; i < MAX_BLOCKS; i++)
+ {
+ blocks[i].size = -1;
+ memset(&blocks[i].data, 0, CD_MAX_SECTOR_DATA);
+ }
+
+ // open device
+ if (cdrom)
+ {
+ cdrom_close(cdrom);
+ cdrom = (cdrom_file *)NULL;
+ }
+
+ #ifdef MESS
+ cdrom = mess_cd_get_cdrom_file_by_number(0);
+ #else
+ cdrom = cdrom_open(get_disk_handle(0));
+ #endif
+
+ if (cdrom)
+ {
+ CDROM_LOG(("Opened CD-ROM successfully, reading root directory\n"))
+ read_new_dir(0xffffff); // read root directory
+ }
+ else
+ {
+ cd_stat = CD_STAT_OPEN;
+ }
+
+ sector_timer = timer_alloc(sector_cb);
+ timer_adjust(sector_timer, ATTOTIME_IN_HZ(150), 0, attotime_zero); // 150 sectors / second = 300kBytes/second
+}
+
+static blockT *cd_alloc_block(UINT8 *blknum)
+{
+ INT32 i;
+
+ // search the 200 available blocks for a free one
+ for (i = 0; i < 200; i++)
+ {
+ if (blocks[i].size == -1)
+ {
+ freeblocks--;
+ if (freeblocks <= 0)
+ {
+ buffull = 1;
+ }
+
+ blocks[i].size = sectlenin;
+ *blknum = i;
+
+ CDROM_LOG(("CD: allocating block %d, size %x\n", i, sectlenin))
+
+ return &blocks[i];
+ }
+ }
+
+ buffull = 1;
+ return (blockT *)NULL;
+}
+
+static void cd_free_block(blockT *blktofree)
+{
+ INT32 i;
+
+ CDROM_LOG(("cd_free_block: %x\n", (UINT32)blktofree))
+
+ for (i = 0; i < 200; i++)
+ {
+ if (&blocks[i] == blktofree)
+ {
+ CDROM_LOG(("CD: freeing block %d\n", i))
+ }
+ }
+
+ blktofree->size = -1;
+ freeblocks++;
+ buffull = 0;
+ hirqreg &= ~BFUL;
+}
+
+static void cd_getsectoroffsetnum(UINT32 bufnum, UINT32 *sectoffs, UINT32 *sectnum)
+{
+ if (*sectoffs == 0xffff)
+ {
+ // last sector
+ CDROM_LOG(("CD: Don't know how to handle offset ffff\n"))
+ }
+ else if (*sectnum == 0xffff)
+ {
+ *sectnum = partitions[bufnum].numblks - *sectoffs;
+ }
+}
+
+static void cd_defragblocks(partitionT *part)
+{
+ UINT32 i, j;
+ blockT *temp;
+ UINT8 temp2;
+
+ for (i = 0; i < (MAX_BLOCKS-1); i++)
+ {
+ for (j = i+1; j < MAX_BLOCKS; j++)
+ {
+ if ((part->blocks[i] == (blockT *)NULL) && (part->blocks[j] != (blockT *)NULL))
+ {
+ temp = part->blocks[i];
+ part->blocks[i] = part->blocks[j];
+ part->blocks[j] = temp;
+
+ temp2 = part->bnum[i];
+ part->bnum[i] = part->bnum[j];
+ part->bnum[j] = temp2;
+ }
+ }
+ }
+}
+
+static UINT16 cd_readWord(UINT32 addr)
+{
+ UINT16 rv;
+
+ switch (addr & 0xffff)
+ {
+ case 0x0008: // read HIRQ register
+ case 0x000a:
+ rv = hirqreg;
+
+ rv &= ~DCHG; // always clear bit 6 (tray open)
+
+ if (buffull) rv |= BFUL; else rv &= ~BFUL;
+ if (sectorstore) rv |= CSCT; else rv &= ~CSCT;
+
+ hirqreg = rv;
+
+// CDROM_LOG(("RW HIRQ: %04x (PC=%x)\n", rv, activecpu_get_pc()))
+
+ return rv;
+ break;
+
+ case 0x000c:
+ case 0x000e:
+ CDROM_LOG(("RW HIRM: %04x\n", hirqmask))
+ return hirqmask;
+ break;
+
+ case 0x0018:
+ case 0x001a:
+// CDROM_LOG(("RW CR1: %04x\n", cr1))
+ return cr1;
+ break;
+
+ case 0x001c:
+ case 0x001e:
+// CDROM_LOG(("RW CR2: %04x\n", cr2))
+ return cr2;
+ break;
+
+ case 0x0020:
+ case 0x0022:
+// CDROM_LOG(("RW CR3: %04x\n", cr3))
+ return cr3;
+ break;
+
+ case 0x0024:
+ case 0x0026:
+// CDROM_LOG(("RW CR4: %04x\n", cr4))
+ return cr4;
+ break;
+
+ case 0x8000:
+ rv = 0xffff;
+ switch (xfertype)
+ {
+ case XFERTYPE_TOC:
+ rv = tocbuf[xfercount]<<8 | tocbuf[xfercount+1];
+ xfercount += 2;
+ xferdnum += 2;
+
+ if (xfercount > 102*4)
+ {
+ xfercount = 0;
+ xfertype = XFERTYPE_INVALID;
+ }
+ break;
+
+ case XFERTYPE_FILEINFO_1:
+ rv = finfbuf[xfercount]<<8 | finfbuf[xfercount+1];
+ xfercount += 2;
+ xferdnum += 2;
+
+ if (xfercount > 6*2)
+ {
+ xfercount = 0;
+ xfertype = XFERTYPE_INVALID;
+ }
+ break;
+
+ default:
+ CDROM_LOG(("STVCD: Unhandled xfer type %d\n", (int)xfertype))
+ rv = 0xffff;
+ break;
+ }
+
+ return rv;
+ break;
+
+ default:
+ CDROM_LOG(("CD: RW %08x (PC=%x)\n", addr, activecpu_get_pc()))
+ return 0xffff;
+ break;
+ }
+
+ return 0xffff;
+}
+
+static UINT32 cd_readLong(UINT32 addr)
+{
+ UINT32 rv = 0;
+
+ switch (addr & 0xffff)
+ {
+ case 0x8000:
+ switch (xfertype32)
+ {
+ case XFERTYPE32_GETSECTOR:
+ case XFERTYPE32_GETDELETESECTOR:
+ // make sure we have sectors left
+ if (xfersect < xfersectnum)
+ {
+ // get next longword
+ rv = transpart->blocks[xfersectpos+xfersect]->data[xferoffs]<<24 |
+ transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 1]<<16 |
+ transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 2]<<8 |
+ transpart->blocks[xfersectpos+xfersect]->data[xferoffs + 3];
+
+ xferdnum += 4;
+ xferoffs += 4;
+
+ // did we run out of sector?
+ if (xferoffs >= transpart->blocks[xfersect]->size)
+ {
+ CDROM_LOG(("CD: finished xfer of block %d of %d\n", xfersect+1, xfersectnum))
+
+ xferoffs = 0;
+ xfersect++;
+ }
+ }
+ else // sectors are done, kill 'em all if we can
+ {
+ if (xfertype32 == XFERTYPE32_GETDELETESECTOR)
+ {
+ INT32 i;
+
+ CDROM_LOG(("Killing sectors in done\n"))
+
+ // deallocate the blocks
+ for (i = xfersectpos; i < xfersectpos+xfersectnum; i++)
+ {
+ cd_free_block(transpart->blocks[i]);
+ transpart->blocks[i] = (blockT *)NULL;
+ transpart->bnum[i] = 0xff;
+ }
+
+ // defrag what's left
+ cd_defragblocks(transpart);
+
+ // clean up our state
+ transpart->size -= xferdnum;
+ transpart->numblks -= xfersectnum;
+
+ xfertype32 = XFERTYPE32_INVALID;
+ }
+ }
+ break;
+
+ default:
+ CDROM_LOG(("CD: unhandled 32-bit transfer type\n"))
+ break;
+ }
+
+ return rv;
+ break;
+
+ default:
+ CDROM_LOG(("CD: RL %08x (PC=%x)\n", addr, activecpu_get_pc()))
+ return 0xffff;
+ break;
+ }
+}
+
+static void cd_writeWord(UINT32 addr, UINT16 data)
+{
+ UINT32 temp;
+
+ switch(addr & 0xffff)
+ {
+ case 0x0008:
+ case 0x000a:
+// CDROM_LOG(("WW HIRQ: %04x & %04x => %04x (PC %x)\n", hirqreg, data, hirqreg & data, activecpu_get_pc()))
+ hirqreg &= data;
+ return;
+ case 0x000c:
+ case 0x000e:
+ CDROM_LOG(("WW HIRM: %04x => %04x\n", hirqmask, data))
+ hirqmask = data;
+ return;
+ case 0x0018:
+ case 0x001a:
+// CDROM_LOG(("WW CR1: %04x\n", data))
+ cr1 = data;
+ cd_stat &= ~CD_STAT_PERI;
+ break;
+ case 0x001c:
+ case 0x001e:
+// CDROM_LOG(("WW CR2: %04x\n", data))
+ cr2 = data;
+ break;
+ case 0x0020:
+ case 0x0022:
+// CDROM_LOG(("WW CR3: %04x\n", data))
+ cr3 = data;
+ break;
+ case 0x0024:
+ case 0x0026:
+// CDROM_LOG(("WW CR4: %04x\n", data))
+ cr4 = data;
+// CDROM_LOG(("CD: command exec %02x %02x %02x %02x %02x (stat %04x)\n", hirqreg, cr1, cr2, cr3, cr4, cd_stat))
+
+ if (!cdrom)
+ {
+ cd_stat = CD_STAT_OPEN;
+ cr1 = cd_stat | 0xff;
+ cr2 = 0xffff;
+ cr3 = 0xffff;
+ cr4 = 0xffff;
+ return;
+ }
+
+ switch (cr1 & 0xff00)
+ {
+ case 0x0000:
+ CDROM_LOG(("CD: Get Status (PC=%x)\n", activecpu_get_pc()))
+
+ // values taken from a US saturn with a disc in and the lid closed
+ hirqreg |= CMOK;
+ cr1 = cd_stat;
+ cr2 = 0x4101;
+ cr3 = 0x100 | (cd_curfad>>16);
+ cr4 = cd_curfad;
+ CDROM_LOG((" = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
+ break;
+
+ case 0x0100:
+ CDROM_LOG(("CD: Get Hardware Info (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= CMOK;
+ cr1 = cd_stat;
+ cr2 = 0x0201;
+ cr3 = 0x0000;
+ cr4 = 0x0400;
+ break;
+
+ case 0x200: // Get TOC
+ CDROM_LOG(("CD: Get TOC (PC=%x)\n", activecpu_get_pc()))
+ cd_readTOC();
+ cd_stat = CD_STAT_TRANS|CD_STAT_PAUSE;
+ cr2 = 102*2; // TOC length in words (102 entries @ 2 words/4bytes each)
+ cr3 = 0;
+ cr4 = 0;
+ xferdnum = 0;
+ hirqreg |= (CMOK|DRDY);
+ break;
+
+ case 0x0300: // get session info (lower byte = session # to get?)
+ // bios is interested in returns in cr3 and cr4
+ // cr3 should be data track #
+ // cr4 must be > 1 and < 100 or bios gets angry.
+ CDROM_LOG(("CD: Get Session Info (PC=%x)\n", activecpu_get_pc()))
+ cd_readTOC();
+ switch (cr1 & 0xff)
+ {
+ case 0: // get total session info / disc end
+ cr2 = 0;
+ cr3 = 0x0100 | tocbuf[(101*4)+1];
+ cr4 = tocbuf[(101*4)+2]<<8 | tocbuf[(101*4)+3];
+ break;
+
+ case 1: // get total session info / disc start
+ cr2 = 0;
+ cr3 = 0x0100; // sessions in high byte, session start in lower
+ cr4 = 0;
+ break;
+
+ default:
+ mame_printf_error("CD: Unknown request to Get Session Info %x\n", cr1 & 0xff);
+ break;
+ }
+ cd_stat = CD_STAT_PAUSE;
+ cr1 = cd_stat << 8;
+ hirqreg |= (CMOK);
+ break;
+
+ case 0x400: // initialize CD system
+ // CR1 & 1 = reset software
+ // CR1 & 2 = decode RW subcode
+ // CR1 & 4 = don't confirm mode 2 subheader
+ // CR1 & 8 = retry reading mode 2 sectors
+ // CR1 & 10 = force single-speed
+ CDROM_LOG(("CD: Initialize CD system (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|DRDY|ESEL);
+ cd_stat = CD_STAT_PAUSE;
+ cd_curfad = 150;
+ in_buffer = 0;
+ buffull = 0;
+ cr2 = 0x4101;
+ cr3 = 0x100 | ((cd_curfad>>16)&0xff);
+ cr4 = cd_curfad;
+ break;
+
+ case 0x0600: // end data transfer
+ // returns # of bytes transfered (24 bits) in
+ // low byte of cr1 (MSB) and cr2 (middle byte, LSB)
+ CDROM_LOG(("CD: End data transfer (PC=%x) (%d bytes xfer'd)\n", activecpu_get_pc(), xferdnum))
+
+ // clear the "transfer" flag
+ cd_stat &= ~CD_STAT_TRANS;
+
+ if (xferdnum)
+ {
+ cr1 = (cd_stat) | ((xferdnum>>17) & 0xff);
+ cr2 = (xferdnum>>1)&0xffff;
+ cr3 = 0;
+ cr4 = 0;
+ }
+ else
+ {
+ cr1 = (cd_stat) | (0xff); // is this right?
+ cr2 = 0xffff;
+ cr3 = 0;
+ cr4 = 0;
+ }
+
+ // try to clean up any transfers still in progress
+ switch (xfertype32)
+ {
+ case XFERTYPE32_GETSECTOR:
+ hirqreg |= EHST;
+ break;
+
+ case XFERTYPE32_GETDELETESECTOR:
+ if (transpart->size > 0)
+ {
+ INT32 i;
+
+ xfertype32 = XFERTYPE32_INVALID;
+
+ // deallocate the blocks
+ for (i = xfersectpos; i < xfersectpos+xfersectnum; i++)
+ {
+ cd_free_block(transpart->blocks[i]);
+ transpart->blocks[i] = (blockT *)NULL;
+ transpart->bnum[i] = 0xff;
+ }
+
+ // defrag what's left
+ cd_defragblocks(transpart);
+
+ // clean up our state
+ transpart->size -= xferdnum;
+ transpart->numblks -= xfersectnum;
+
+ if (freeblocks == 200)
+ {
+ onesectorstored = 0;
+ }
+
+ hirqreg |= EHST;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ // hack for the bootloader
+ cd_stat |= CD_STAT_PERI;
+ cr1 = cd_stat;
+
+ // and kick the CD if there's more to read
+ cd_playdata();
+
+ xferdnum = 0;
+ hirqreg |= CMOK;
+
+ CDROM_LOG((" = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
+ break;
+
+ case 0x1000: // Play Disk. FAD is in lowest 7 bits of cr1 and all of cr2.
+ CDROM_LOG(("CD: Play Disk (PC=%x)\n", activecpu_get_pc()))
+ cd_stat = CD_STAT_PLAY; //|0x80; // set "cd-rom" bit?
+ cd_curfad = ((cr1&0xff)<<16) | cr2;
+ fadstoplay = ((cr3&0xff)<<16) | cr4;
+
+ if (cd_curfad & 0x800000)
+ {
+ if (cd_curfad != 0xffffff)
+ {
+ // fad mode
+ cd_curfad &= 0xfffff;
+ fadstoplay &= 0xfffff;
+ }
+ }
+ else
+ {
+ // track mode
+ mame_printf_error("CD: Play Disk track mode, not yet implemented\n");
+ }
+
+ CDROM_LOG(("CD: Play Disk: start %x length %x\n", cd_curfad, fadstoplay))
+
+ cr2 = 0x4101; // ctrl/adr in hi byte, track # in low byte
+ cr3 = (0x100) | ((cd_curfad>>16)&0xff); // index of subcode in hi byte, frame address
+ cr4 = cd_curfad & 0xffff;
+ hirqreg |= (CMOK|DRDY);
+ oddframe = 0;
+ in_buffer = 0;
+
+ playtype = 0;
+
+ // and do the disc I/O
+ // make sure it doesn't come in too early
+ timer_adjust(sector_timer, attotime_never, 0, attotime_never);
+ timer_adjust(sector_timer, ATTOTIME_IN_HZ(150), 0, attotime_zero); // 150 sectors / second = 300kBytes/second
+ break;
+
+ case 0x1100: // disk seek
+ CDROM_LOG(("CD: Disk seek (PC=%x)\n", activecpu_get_pc()))
+ if (cr1 & 0x80)
+ {
+ temp = (cr1&0x7f)<<16; // get FAD to seek to
+ temp |= cr2;
+
+ if (temp == 0xffffff)
+ {
+ cd_stat = CD_STAT_PAUSE;
+ }
+ else
+ {
+ CDROM_LOG(("CD: not clear how to handle FAD seek\n"))
+ cd_curfad = temp;
+ }
+ }
+ else
+ {
+ // is it a valid track?
+ if (cr2 >> 8)
+ {
+ cd_stat = CD_STAT_PAUSE;
+ // (index is cr2 low byte)
+ }
+ else
+ {
+ cd_stat = CD_STAT_STANDBY;
+ cd_curfad = 0xffffffff;
+ }
+ }
+
+
+ hirqreg |= CMOK;
+ cr1 = cd_stat;
+ cr2 = 0x4101;
+ cr3 = (cd_curfad>>16)&0xff;
+ cr4 = cd_curfad;
+ break;
+
+ case 0x3000: // Set CD Device connection
+ {
+ UINT8 parm;
+
+ // get operation
+ parm = cr3>>8;
+
+ CDROM_LOG(("CD: Set CD Device Connection (PC=%x) filter # %x\n", activecpu_get_pc(), parm))
+
+ cddevicenum = parm;
+
+ if (parm == 0xff)
+ {
+ cddevice = (filterT *)NULL;
+ }
+ else
+ {
+ if (parm < 0x24)
+ {
+ cddevice = &filters[(cr3>>8)];
+ }
+ }
+
+ hirqreg |= (CMOK|ESEL);
+ }
+ break;
+
+ case 0x4000: // Set Filter Range
+ // cr1 low + cr2 = FAD0, cr3 low + cr4 = FAD1
+ // cr3 hi = filter num.
+ {
+ UINT8 fnum = (cr3>>8)&0xff;
+
+ CDROM_LOG(("CD: Set Filter Range (PC=%x)\n", activecpu_get_pc()))
+
+ filters[fnum].fad = ((cr1 & 0xff)<<16) | cr2;
+ filters[fnum].range = ((cr3 & 0xff)<<16) | cr4;
+
+ hirqreg |= (CMOK|ESEL|DRDY);
+ cr2 = 0x4101; // ctrl/adr in hi byte, track # in low byte
+ cr3 = 0x0100|((cd_curfad>>16)&0xff);
+ cr4 = (cd_curfad & 0xffff);
+ }
+ break;
+
+ case 0x4200: // Set Filter Subheader conditions
+ {
+ UINT8 fnum = (cr3>>8)&0xff;
+
+ CDROM_LOG(("CD: Set Filter Subheader conditions (PC=%x) %x => chan %x masks %x fid %x vals %x\n", activecpu_get_pc(), fnum, cr1&0xff, cr2, cr3&0xff, cr4))
+
+ filters[fnum].chan = cr1 & 0xff;
+ filters[fnum].smmask = (cr2>>8)&0xff;
+ filters[fnum].cimask = cr2&0xff;
+ filters[fnum].fid = cr3&0xff;
+ filters[fnum].smval = (cr4>>8)&0xff;
+ filters[fnum].cival = cr4&0xff;
+
+ hirqreg |= (CMOK|ESEL);
+ cr2 = 0x4101; // ctrl/adr in hi byte, track # in low byte
+ cr3 = 0x0100|((cd_curfad>>16)&0xff);
+ cr4 = (cd_curfad & 0xffff);
+ }
+ break;
+
+ case 0x4400: // Set Filter Mode
+ {
+ UINT8 fnum = (cr3>>8)&0xff;
+ UINT8 mode = (cr1 & 0xff);
+
+ // initialize filter?
+ if (mode & 0x80)
+ {
+ memset(&filters[fnum], 0, sizeof(filterT));
+ }
+ else
+ {
+ filters[fnum].mode = mode;
+ }
+
+ CDROM_LOG(("CD: Set Filter Mode (PC=%x) filt %x mode %x\n", activecpu_get_pc(), fnum, mode))
+ hirqreg |= (CMOK|ESEL|DRDY);
+ cr2 = 0x4101; // ctrl/adr in hi byte, track # in low byte
+ cr3 = 0x0100|((cd_curfad>>16)&0xff);
+ cr4 = (cd_curfad & 0xffff);
+ }
+ break;
+
+ case 0x4600: // Set Filter Connection
+ {
+ UINT8 fnum = (cr3>>8)&0xff;
+
+ CDROM_LOG(("CD: Set Filter Connection (PC=%x) %x => mode %x parm %04x\n", activecpu_get_pc(), fnum, cr1 & 0xf, cr2))
+
+ // set true condition?
+ if (cr1 & 1)
+ {
+ filters[fnum].condtrue = (cr2>>8)&0xff;
+ }
+ else if (cr1 & 2) // set false condition
+ {
+ filters[fnum].condfalse = cr2&0xff;
+ }
+
+ hirqreg |= (CMOK|ESEL);
+ cr2 = 0x4101; // ctrl/adr in hi byte, track # in low byte
+ cr3 = 0x0100|((cd_curfad>>16)&0xff);
+ cr4 = (cd_curfad & 0xffff);
+ }
+ break;
+
+ case 0x4800: // Reset Selector
+ CDROM_LOG(("CD: Reset Selector (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|ESEL|DRDY);
+ cr2 = 0x4101; // ctrl/adr in hi byte, track # in low byte
+ cr3 = 0x0100|((cd_curfad>>16)&0xff);
+ cr4 = (cd_curfad & 0xffff);
+ break;
+
+ case 0x5000: // get Buffer Size
+ cr1 = cd_stat;
+ cr2 = freeblocks;
+ if (cr2 > 200) cr2 = 200; // ???
+
+ cr3 = 0x1800;
+ cr4 = 200;
+ CDROM_LOG(("CD: Get Buffer Size = %d (PC=%x)\n", cr2, activecpu_get_pc()))
+ hirqreg |= (CMOK|ESEL|DRDY); // DRDY is probably wrong
+ break;
+
+ case 0x5100: // get # sectors used in a buffer
+ {
+ UINT32 bufnum = cr3>>8;
+
+ // is the partition empty?
+ if (partitions[bufnum].size == -1)
+ {
+ cr4 = 0;
+ }
+ else
+ {
+ cr4 = partitions[bufnum].numblks;
+ }
+
+ CDROM_LOG(("CD: Get Sector Number (PC=%x) (bufno %d) = %d blocks\n", activecpu_get_pc(), bufnum, cr4))
+
+ cr2 = 0;
+ cr3 = 0;
+ hirqreg |= (CMOK|DRDY);
+ }
+ break;
+
+ case 0x5200: // calculate acutal size
+ {
+ UINT32 bufnum = cr3>>8;
+ UINT32 sectoffs = cr2;
+ UINT32 numsect = cr4;
+
+ CDROM_LOG(("CD: Calculate actual size: buf %x offs %x numsect %x (PC=%x)\n", bufnum, sectoffs, numsect, activecpu_get_pc()))
+
+ calcsize = 0;
+ if (partitions[bufnum].size != -1)
+ {
+ INT32 i;
+
+ for (i = 0; i < numsect; i++)
+ {
+ if (partitions[bufnum].blocks[sectoffs+i])
+ {
+ calcsize += (partitions[bufnum].blocks[sectoffs+i]->size / 2);
+ }
+ }
+ }
+
+ hirqreg |= (CMOK|ESEL);
+ cr1 = cd_stat;
+ cr2 = 0x4101; // CTRL/track
+ cr3 = (cd_curfad>>16)&0xff;
+ cr4 = (cd_curfad & 0xffff);
+ }
+ break;
+
+ case 0x5300: // get actual block size
+ CDROM_LOG(("CD: Get actual block size (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|ESEL);
+ cr1 = cd_stat | ((calcsize>>16)&0xff);
+ cr2 = (calcsize & 0xffff);
+ cr3 = 0;
+ cr4 = 0;
+ break;
+
+ case 0x6000: // set sector length
+ CDROM_LOG(("CD: Set sector length (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|ESEL|EFLS|SCDQ|DRDY);
+
+ switch (cr1 & 0xff)
+ {
+ case 0:
+ sectlenin = 2048;
+ break;
+ case 1:
+ sectlenin = 2336;
+ break;
+ case 2:
+ sectlenin = 2340;
+ break;
+ case 3:
+ sectlenin = 2352;
+ break;
+ }
+
+ switch ((cr2>>8) & 0xff)
+ {
+ case 0:
+ sectlenout = 2048;
+ break;
+ case 1:
+ sectlenout = 2336;
+ break;
+ case 2:
+ sectlenout = 2340;
+ break;
+ case 3:
+ sectlenout = 2352;
+ break;
+ }
+ break;
+
+ case 0x6100: // get sector data
+ {
+ UINT32 sectnum = cr4;
+ UINT32 sectofs = cr2;
+ UINT32 bufnum = cr3>>8;
+
+ CDROM_LOG(("CD: Get sector data (PC=%x) (SN %d SO %d BN %d)\n", activecpu_get_pc(), sectnum, sectofs, bufnum))
+
+ if (bufnum >= MAX_FILTERS)
+ {
+ CDROM_LOG(("CD: invalid buffer number\n"));
+ cd_stat = 0xff; // ERROR
+ hirqreg |= (CMOK|EHST);
+ return;
+ }
+
+ if (partitions[bufnum].numblks == 0)
+ {
+ CDROM_LOG(("CD: buffer is empty\n"))
+ cd_stat = 0xff; // ERROR
+ hirqreg |= (CMOK|EHST);
+ return;
+ }
+
+ cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
+
+ xfertype32 = XFERTYPE32_GETSECTOR;
+ xferoffs = 0;
+ xfersect = 0;
+ xferdnum = 0;
+ xfersectpos = sectofs;
+ xfersectnum = sectnum;
+ transpart = &partitions[bufnum];
+
+ cd_stat |= CD_STAT_TRANS;
+ hirqreg |= (CMOK|EHST|DRDY);
+ }
+ break;
+
+ case 0x6200: // delete sector data
+ {
+ UINT32 sectnum = cr4;
+ UINT32 sectofs = cr2;
+ UINT32 bufnum = cr3>>8;
+ INT32 i;
+
+ CDROM_LOG(("CD: Delete sector data (PC=%x) (SN %d SO %d BN %d)\n", activecpu_get_pc(), sectnum, sectofs, bufnum))
+
+ if (bufnum >= MAX_FILTERS)
+ {
+ CDROM_LOG(("CD: invalid buffer number\n"))
+ cd_stat = 0xff; // ERROR
+ hirqreg |= (CMOK|EHST);
+ return;
+ }
+
+ if (partitions[bufnum].numblks == 0)
+ {
+ CDROM_LOG(("CD: buffer is empty\n"))
+ cd_stat = 0xff; // ERROR
+ hirqreg |= (CMOK|EHST);
+ return;
+ }
+
+ cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
+
+ for (i = sectofs; i < (sectofs + sectnum); i++)
+ {
+ partitions[bufnum].size -= partitions[bufnum].blocks[i]->size;
+ cd_free_block(partitions[bufnum].blocks[i]);
+ partitions[bufnum].blocks[i] = (blockT *)NULL;
+ partitions[bufnum].bnum[i] = 0xff;
+ }
+
+ cd_defragblocks(&partitions[bufnum]);
+
+ partitions[bufnum].numblks -= sectnum;
+
+ cd_stat &= ~CD_STAT_TRANS;
+ hirqreg |= (CMOK|EHST);
+ }
+ break;
+
+ case 0x6300: // get then delete sector data
+ {
+ UINT32 sectnum = cr4;
+ UINT32 sectofs = cr2;
+ UINT32 bufnum = cr3>>8;
+
+ CDROM_LOG(("CD: Get and delete sector data (PC=%x) (SN %d SO %d BN %d)\n", activecpu_get_pc(), sectnum, sectofs, bufnum))
+
+ if (bufnum >= MAX_FILTERS)
+ {
+ CDROM_LOG(("CD: invalid buffer number\n"))
+ cd_stat = 0xff; // ERROR
+ hirqreg |= (CMOK|EHST);
+ return;
+ }
+
+ if (partitions[bufnum].numblks == 0)
+ {
+ CDROM_LOG(("CD: buffer is empty\n"))
+ cd_stat = 0xff; // ERROR
+ hirqreg |= (CMOK|EHST);
+ return;
+ }
+
+ cd_getsectoroffsetnum(bufnum, &sectofs, &sectnum);
+
+ xfertype32 = XFERTYPE32_GETDELETESECTOR;
+ xferoffs = 0;
+ xfersect = 0;
+ xferdnum = 0;
+ xfersectpos = sectofs;
+ xfersectnum = sectnum;
+ transpart = &partitions[bufnum];
+
+ cd_stat &= ~CD_STAT_TRANS;
+ hirqreg |= (CMOK|EHST|DRDY);
+ }
+ break;
+
+ case 0x6700: // get copy error
+ CDROM_LOG(("CD: Get copy error (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|ESEL|EFLS|SCDQ|DRDY);
+ break;
+
+ case 0x7000: // change directory
+ CDROM_LOG(("CD: Change Directory (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|EFLS);
+
+ temp = (cr3&0xff)<<16;
+ temp |= cr4;
+ read_new_dir(temp);
+ break;
+
+ case 0x7100: // Read directory entry
+ CDROM_LOG(("CD: Read Directory Entry (PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|DRDY);
+
+ temp = (cr3&0xff)<<16;
+ temp |= cr4;
+ cr2 = 0x4101; // CTRL/track
+ cr3 = (curdir[temp].firstfad>>16)&0xff;
+ cr4 = (curdir[temp].firstfad&0xffff);
+ break;
+
+ case 0x7200: // Get file system scope
+ CDROM_LOG(("CD: Get file system scope(PC=%x)\n", activecpu_get_pc()))
+ hirqreg |= (CMOK|DRDY);
+ cr2 = numfiles; // # of files in directory
+ cr3 = 0x0100; // report directory held
+ cr4 = firstfile; // first file id
+ break;
+
+ case 0x7300: // Get File Info
+ CDROM_LOG(("CD: Get File Info (PC=%x)\n", activecpu_get_pc()))
+ cd_stat |= CD_STAT_TRANS;
+ cd_stat &= 0xff00; // clear top byte of return value
+ hirqreg |= (CMOK|DRDY);
+
+ temp = (cr3&0xff)<<16;
+ temp |= cr4;
+
+ if (temp == 0xffffff) // special
+ {
+ xfertype = XFERTYPE_FILEINFO_254;
+ xfercount = 0;
+
+ cr1 = cd_stat;
+ cr2 = 0x5f4;
+ cr3 = 0;
+ cr4 = 0;
+ }
+ else
+ {
+ cr1 = cd_stat;
+ cr2 = 6; // 6 words for single file
+ // first 4 bytes = FAD address
+ // second 4 bytes = length
+ // last 4 bytes:
+ // - unit size
+ // - gap size
+ // - file #
+ // attributes flags
+
+ cr3 = cr4 = 0;
+
+ // first 4 bytes = FAD
+ finfbuf[0] = (curdir[temp].firstfad>>24)&0xff;
+ finfbuf[1] = (curdir[temp].firstfad>>16)&0xff;
+ finfbuf[2] = (curdir[temp].firstfad>>8)&0xff;
+ finfbuf[3] = (curdir[temp].firstfad&0xff);
+ // second 4 bytes = length of file
+ finfbuf[4] = (curdir[temp].length>>24)&0xff;
+ finfbuf[5] = (curdir[temp].length>>16)&0xff;
+ finfbuf[6] = (curdir[temp].length>>8)&0xff;
+ finfbuf[7] = (curdir[temp].length&0xff);
+ finfbuf[8] = 0x00;
+ finfbuf[9] = 0x00;
+ finfbuf[10] = temp;
+ finfbuf[11] = curdir[temp].flags;
+
+ xfertype = XFERTYPE_FILEINFO_1;
+ xfercount = 0;
+ }
+ CDROM_LOG((" = %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
+ break;
+
+ case 0x7400: // Read File
+ CDROM_LOG(("CD: Read File (PC=%x)\n", activecpu_get_pc()))
+ temp = (cr3&0xff)<<16;
+ temp |= cr4;
+
+ cd_stat = CD_STAT_PLAY|0x80; // set "cd-rom" bit
+ cr2 = 0x4101; // CTRL/track
+ cr3 = (curdir[temp].firstfad>>16)&0xff;
+ cr4 = (curdir[temp].firstfad&0xffff);
+
+ cd_curfad = curdir[temp].firstfad;
+ if (curdir[temp].length / 2048)
+ {
+ fadstoplay = curdir[temp].length/2048;
+ fadstoplay++;
+ }
+ else
+ {
+ fadstoplay = curdir[temp].length/2048;
+ }
+
+ hirqreg |= (CMOK|DRDY);
+ oddframe = 0;
+ in_buffer = 0;
+
+ playtype = 1;
+
+ // and do the disc I/O
+// timer_adjust(sector_timer, ATTOTIME_IN_HZ(150), 0, attotime_zero); // 150 sectors / second = 300kBytes/second
+ break;
+
+ case 0x7500:
+ CDROM_LOG(("CD: Abort File (PC=%x)\n", activecpu_get_pc()))
+ // bios expects "2bc" mask to work against this
+ hirqreg |= (CMOK|EFLS|EHST|ESEL|DCHG|PEND|BFUL|CSCT|DRDY);
+ cd_stat = CD_STAT_PERI|CD_STAT_PAUSE; // force to pause
+ break;
+
+ case 0xe000: // appears to be copy protection check. needs only to return OK.
+ CDROM_LOG(("CD: Verify copy protection (PC=%x)\n", activecpu_get_pc()))
+ cd_stat = CD_STAT_PAUSE;
+ cr1 = cd_stat; // necessary to pass
+ cr2 = 0x4;
+// hirqreg |= (CMOK|EFLS|CSCT);
+ sectorstore = 1;
+ hirqreg = 0xfc5;
+ break;
+
+ case 0xe100: // get disc region
+ CDROM_LOG(("CD: Get disc region (PC=%x)\n", activecpu_get_pc()))
+ cd_stat = CD_STAT_PAUSE;
+ cr1 = cd_stat; // necessary to pass
+ cr2 = 0x4; // (must return this value to pass bios checks)
+ hirqreg |= (CMOK);
+ break;
+
+ default:
+ CDROM_LOG(("CD: Unknown command %04x (PC=%x)\n", cr1, activecpu_get_pc()))
+ hirqreg |= (CMOK);
+ break;
+ }
+// CDROM_LOG(("ret: %04x %04x %04x %04x %04x\n", hirqreg, cr1, cr2, cr3, cr4))
+ break;
+ default:
+ CDROM_LOG(("CD: WW %08x %04x (PC=%x)\n", addr, data, activecpu_get_pc()))
+ break;
+ }
+}
+
+READ32_HANDLER( stvcd_r )
+{
+ UINT32 rv = 0;
+
+ offset <<= 2;
+
+ switch (offset)
+ {
+ case 0x90008:
+ case 0x9000a:
+ case 0x9000c:
+ case 0x9000e:
+ case 0x90018:
+ case 0x9001a:
+ case 0x9001c:
+ case 0x9001e:
+ case 0x90020:
+ case 0x90022:
+ case 0x90024:
+ case 0x90026:
+ rv = cd_readWord(offset);
+ return rv<<16;
+ break;
+
+ case 0x98000:
+ case 0x18000:
+ if (mem_mask == 0)
+ {
+ rv = cd_readLong(offset);
+ }
+ else if (mem_mask == 0x0000ffff)
+ {
+ rv = cd_readWord(offset)<<16;
+ }
+ else if (mem_mask == 0xffff0000)
+ {
+ rv = cd_readWord(offset);
+ }
+ else
+ {
+ mame_printf_error("CD: Unknown data buffer read @ mask = %08x\n", mem_mask);
+ }
+
+ break;
+
+ default:
+ CDROM_LOG(("Unknown CD read @ %x\n", offset))
+ break;
+ }
+
+ return rv;
+}
+
+WRITE32_HANDLER( stvcd_w )
+{
+ offset <<= 2;
+
+ switch (offset)
+ {
+ case 0x90008:
+ case 0x9000a:
+ case 0x9000c:
+ case 0x9000e:
+ case 0x90018:
+ case 0x9001a:
+ case 0x9001c:
+ case 0x9001e:
+ case 0x90020:
+ case 0x90022:
+ case 0x90024:
+ case 0x90026:
+ cd_writeWord(offset, data>>16);
+ break;
+
+ default:
+ CDROM_LOG(("Unknown CD write %x @ %x\n", data, offset))
+ break;
+ }
+}
+
+// iso9660 parsing
+static void read_new_dir(UINT32 fileno)
+{
+ int foundpd, i;
+ UINT32 cfad, dirfad;
+ UINT8 sect[2048];
+
+ if (fileno == 0xffffff)
+ {
+ cfad = 166; // first sector of directory as per iso9660 specs
+
+ foundpd = 0; // search for primary vol. desc
+ while ((!foundpd) && (cfad < 200))
+ {
+ memset(sect, 0, 2048);
+ cd_readblock(cfad++, sect);
+
+ if ((sect[1] == 'C') && (sect[2] == 'D') && (sect[3] == '0') && (sect[4] == '0') && (sect[5] == '1'))
+ {
+ switch (sect[0])
+ {
+ case 0: // boot record
+ break;
+
+ case 1: // primary vol. desc
+ foundpd = 1;
+ break;
+
+ case 2: // secondary vol desc
+ break;
+
+ case 3: // vol. section descriptor
+ break;
+
+ case 0xff:
+ cfad = 200;
+ break;
+ }
+ }
+ }
+
+ // got primary vol. desc.
+ if (foundpd)
+ {
+ dirfad = sect[140] | (sect[141]<<8) | (sect[142]<<16) | (sect[143]<<24);
+ dirfad += 150;
+
+ // parse root entry
+ curroot.firstfad = sect[158] | (sect[159]<<8) | (sect[160]<<16) | (sect[161]<<24);
+ curroot.firstfad += 150;
+ curroot.length = sect[166] | (sect[167]<<8) | (sect[168]<<16) | (sect[169]<<24);
+ curroot.flags = sect[181];
+ for (i = 0; i < sect[188]; i++)
+ {
+ curroot.name[i] = sect[189+i];
+ }
+ curroot.name[i] = '\0'; // terminate
+
+ // easy to fix, but make sure we *need* to first
+ if (curroot.length > 14336)
+ {
+ mame_printf_error("ERROR: root directory too big (%d)\n", curroot.length);
+ }
+
+ // done with all that, read the root directory now
+ make_dir_current(curroot.firstfad);
+ }
+ }
+ else
+ {
+ if (curdir[fileno].length > 14336)
+ {
+ mame_printf_error("ERROR: new directory too big (%d)!\n", curdir[fileno].length);
+ }
+ make_dir_current(curdir[fileno].firstfad);
+ }
+}
+
+// makes the directory pointed to by FAD current
+static void make_dir_current(UINT32 fad)
+{
+ int i;
+ UINT32 nextent, numentries;
+ UINT8 sect[14336];
+ direntryT *curentry;
+
+ memset(sect, 0, 14336);
+ for (i = 0; i < (curroot.length/2048); i++)
+ {
+ cd_readblock(fad+i, &sect[2048*i]);
+ }
+
+ nextent = 0;
+ numentries = 0;
+ while (nextent < 14336)
+ {
+ if (sect[nextent])
+ {
+ nextent += sect[nextent];
+ numentries++;
+ }
+ else
+ {
+ nextent = 14336;
+ }
+ }
+
+ if (curdir != (direntryT *)NULL)
+ {
+ free((void *)curdir);
+ }
+
+ curdir = (direntryT *)malloc_or_die(sizeof(direntryT)*numentries);
+ curentry = curdir;
+ numfiles = numentries;
+
+ nextent = 0;
+ while (numentries)
+ {
+ curentry->firstfad = sect[nextent+2] | (sect[nextent+3]<<8) | (sect[nextent+4]<<16) | (sect[nextent+5]<<24);
+ curentry->firstfad += 150;
+ curentry->length = sect[nextent+10] | (sect[nextent+11]<<8) | (sect[nextent+12]<<16) | (sect[nextent+13]<<24);
+ curentry->flags = sect[nextent+25];
+ for (i = 0; i < sect[nextent+32]; i++)
+ {
+ curentry->name[i] = sect[nextent+33+i];
+ }
+ curentry->name[i] = '\0'; // terminate
+
+ nextent += sect[nextent];
+ curentry++;
+ numentries--;
+ }
+
+ for (i = 0; i < numfiles; i++)
+ {
+ if (!(curdir[i].flags & 0x02))
+ {
+ firstfile = i;
+ i = numfiles;
+ }
+ }
+}
+
+static void cd_readTOC(void)
+{
+ int i, ntrks, toclen, tocptr, fad;
+
+ xfertype = XFERTYPE_TOC;
+ xfercount = 0;
+
+ if (cdrom)
+ {
+ ntrks = cdrom_get_last_track(cdrom);
+ }
+ else
+ {
+ ntrks = 0;
+ }
+
+ toclen = (4 * ntrks); // toclen header entry
+
+ // data format for Saturn TOC:
+ // no header.
+ // 4 bytes per track
+ // top nibble of first byte is CTRL info
+ // low nibble is ADR
+ // next 3 bytes are FAD address (LBA + 150)
+ // there are always 99 track entries (0-98)
+ // unused tracks are ffffffff.
+ // entries 99-101 are metadata
+
+ tocptr = 0; // starting point of toc entries
+
+ for (i = 0; i < ntrks; i++)
+ {
+ if (cdrom)
+ {
+ tocbuf[tocptr] = cdrom_get_adr_control(cdrom, i)<<4 | 0x01;
+ }
+
+ if (cdrom)
+ {
+ fad = cdrom_get_track_start(cdrom, i) + 150;
+ }
+ else
+ {
+ fad = 150;
+ }
+
+ tocbuf[tocptr+1] = (fad>>16)&0xff;
+ tocbuf[tocptr+2] = (fad>>8)&0xff;
+ tocbuf[tocptr+3] = fad&0xff;
+
+ tocptr += 4;
+ }
+
+ // fill in the rest
+ for ( ; i < 99; i++)
+ {
+ tocbuf[tocptr] = 0xff;
+ tocbuf[tocptr+1] = 0xff;
+ tocbuf[tocptr+2] = 0xff;
+ tocbuf[tocptr+3] = 0xff;
+
+ tocptr += 4;
+ }
+
+ // tracks 99-101 are special metadata
+ // $$$FIXME: what to do with the address info for these?
+ tocptr = 99 * 4;
+ tocbuf[tocptr] = tocbuf[0]; // get ctrl/adr from first track
+ tocbuf[tocptr+1] = 1; // first track's track #
+ tocbuf[tocptr+2] = 0;
+ tocbuf[tocptr+3] = 0;
+
+ tocbuf[tocptr+4] = tocbuf[(ntrks-1)*4]; // ditto for last track
+ tocbuf[tocptr+5] = ntrks; // last track's track #
+ tocbuf[tocptr+6] = 0;
+ tocbuf[tocptr+7] = 0;
+
+ // get total disc length (start of lead-out)
+ fad = cdrom_get_track_start(cdrom, 0xaa) + 150;
+
+ tocbuf[tocptr+8] = tocbuf[0];
+ tocbuf[tocptr+9] = (fad>>16)&0xff;
+ tocbuf[tocptr+10] = (fad>>8)&0xff;
+ tocbuf[tocptr+11] = fad&0xff;
+}
+
+static partitionT *cd_filterdata(filterT *flt, int trktype)
+{
+ int match = 1, keepgoing = 2;
+ partitionT *filterprt = (partitionT *)NULL;
+
+ CDROM_LOG(("cd_filterdata, trktype %d\n", trktype))
+
+ // loop on the filters
+ do
+ {
+ if ((trktype != CD_TRACK_AUDIO) && (curblock.data[15] == 2))
+ {
+ if (flt->mode & 1) // file number
+ {
+ if (curblock.fnum != flt->fid)
+ {
+ logerror("fnum reject\n");
+ match = 0;
+ }
+ }
+
+ if (flt->mode & 2) // channel number
+ {
+ mame_printf_error("STVCD: unimplemented channel number match\n");
+ }
+
+ if (flt->mode & 4) // sub mode
+ {
+ mame_printf_error("STVCD: unimplemented sub mode match\n");
+ }
+
+ if (flt->mode & 8) // coding information
+ {
+ mame_printf_error("STVCD: unimplemented coding information match\n");
+ }
+
+ if (flt->mode & 0x10) // reverse subheader conditions
+ {
+ match ^= 1;
+ }
+ }
+
+ // FAD range check?
+ if (flt->mode & 0x40)
+ {
+ if ((cd_curfad < flt->fad) || (cd_curfad > (flt->fad + flt->range)))
+ {
+ logerror("curfad reject\n");
+ match = 0;
+ }
+ }
+
+ if (match)
+ {
+ lastbuf = flt->condtrue;
+ filterprt = &partitions[lastbuf];
+ // we're done
+ keepgoing = 0;
+ }
+ else
+ {
+ lastbuf = flt->condfalse;
+
+ // reject sector if no match on either connector
+ if ((lastbuf == 0xff) || (keepgoing < 2))
+ {
+ return (partitionT *)NULL;
+ }
+
+ // try again using the filter that was on the "false" connector
+ flt = &filters[lastbuf];
+
+ // and exit if we fail
+ keepgoing--;
+ }
+ } while (keepgoing);
+
+ // try to allocate a block
+ filterprt->blocks[filterprt->numblks] = cd_alloc_block(&filterprt->bnum[filterprt->numblks]);
+
+ // did the allocation succeed?
+ if (filterprt->blocks[filterprt->numblks] == (blockT *)NULL)
+ {
+ return (partitionT *)NULL;
+ }
+
+ // copy working block to the newly allocated one
+ memcpy(filterprt->blocks[filterprt->numblks], &curblock, sizeof(blockT));
+
+ // and massage the data format a bit
+ switch (curblock.size)
+ {
+ case 2048: // user data
+ if (curblock.data[15] == 2)
+ {
+ // mode 2
+ memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[24], curblock.size);
+ }
+ else
+ {
+ // mode 1
+ memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[16], curblock.size);
+ }
+ break;
+
+ case 2324: // Mode 2 Form 2 data
+ memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[24], curblock.size);
+ break;
+
+ case 2336: // Mode 2 Form 2 skip sync/header
+ memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[16], curblock.size);
+ break;
+
+ case 2340: // Mode 2 Form 2 skip sync only
+ memcpy(&filterprt->blocks[filterprt->numblks]->data[0], &curblock.data[12], curblock.size);
+ break;
+
+ case 2352: // want all data, it's already done, so don't do it again :)
+ break;
+ }
+
+ // update the status of the partition
+ if (filterprt->size == -1)
+ {
+ filterprt->size = 0;
+ }
+ filterprt->size += filterprt->blocks[filterprt->numblks]->size;
+ filterprt->numblks++;
+
+ return filterprt;
+}
+
+// read a single sector off the CD, applying the current filter(s) as necessary
+static partitionT *cd_read_filtered_sector(INT32 fad)
+{
+ int trktype;
+
+ if ((cddevice != NULL) && (!buffull))
+ {
+ // find out the track's type
+ trktype = cdrom_get_track_type(cdrom, cdrom_get_track(cdrom, fad-150));
+
+ // now get a raw 2352 byte sector
+ cdrom_read_data(cdrom, fad-150, curblock.data, CD_TRACK_RAW_DONTCARE);
+ cr3 = 0x100 | (fad>>16); // update cr3/4 with the current fad
+ cr4 = fad;
+ curblock.size = sectlenin;
+ curblock.FAD = fad;
+
+ // if track is Mode 2, get the subheader values
+ if ((trktype != CD_TRACK_AUDIO) && (curblock.data[15] == 2))
+ {
+ curblock.chan = curblock.data[17];
+ curblock.fnum = curblock.data[16];
+ curblock.subm = curblock.data[18];
+ curblock.cinf = curblock.data[19];
+
+ // if it's Form 2, the length is actually 2324 bytes
+ if (curblock.subm & 0x20)
+ {
+ curblock.size = 2324;
+ }
+ }
+
+ return cd_filterdata(cddevice, trktype);
+ }
+
+ return (partitionT *)NULL;
+}
+
+// loads in data set up by a CD-block PLAY command
+static void cd_playdata(void)
+{
+ if ((cd_stat & 0x0f00) == CD_STAT_PLAY)
+ {
+ if (fadstoplay)
+ {
+ logerror("STVCD: Reading FAD %d\n", cd_curfad);
+
+ if (cdrom)
+ {
+ partitionT *playpart;
+
+ playpart = cd_read_filtered_sector(cd_curfad);
+
+ cd_curfad++;
+ fadstoplay--;
+
+ hirqreg |= CSCT;
+
+ if (!fadstoplay)
+ {
+ CDROM_LOG(("cd_playdata: playback ended\n"))
+ cd_stat = CD_STAT_PAUSE;
+
+ hirqreg |= PEND;
+
+ if (playtype == 1)
+ {
+ CDROM_LOG(("cd_playdata: setting EFLS\n"))
+ hirqreg |= EFLS;
+ }
+ }
+ }
+ }
+ }
+}
+
+// loads a single sector off the CD, anywhere from FAD 150 on up
+static void cd_readblock(UINT32 fad, UINT8 *dat)
+{
+ if (cdrom)
+ {
+ cdrom_read_data(cdrom, fad-150, dat, CD_TRACK_MODE1);
+ }
+}
+
+
diff --git a/src/mame/machine/stvcd.h b/src/mame/machine/stvcd.h
new file mode 100644
index 00000000000..46d264d6d73
--- /dev/null
+++ b/src/mame/machine/stvcd.h
@@ -0,0 +1,17 @@
+/***************************************************************************
+
+ machine/stvcd.h - Sega Saturn and ST-V CD-ROM handling
+
+ By R. Belmont
+
+***************************************************************************/
+
+#ifndef __STVCD_H__
+#define __STVCD_H__
+
+void stvcd_reset(void);
+
+READ32_HANDLER( stvcd_r );
+WRITE32_HANDLER( stvcd_w );
+
+#endif
diff --git a/src/mame/machine/stvprot.c b/src/mame/machine/stvprot.c
new file mode 100644
index 00000000000..3ac6d603877
--- /dev/null
+++ b/src/mame/machine/stvprot.c
@@ -0,0 +1,480 @@
+/* ST-V protection stuff */
+
+/* todo:
+ figure out properly
+ clean up
+ fix remaining games
+ split apart? (this might be a per game thing rather than a generic device..)
+
+ Known Protected ST-V Games
+
+ Astra Superstars (text layer gfx transfer)
+ Elandoree (gfx transfer of textures for some characters)
+ Final Fight Revenge (boot vectors etc.?)
+ Radiant Silvergun (game start protection)
+ Steep Slope Sliders (gfx transfer of some character portraits)
+ Decathlete (transfer of all gfx data)
+ Tecmo World Cup '98 (tecmo logo, player movement?)
+
+
+ Is this just scrambled, or also compressed somehow? I've not had much luck
+ locating the data some of the games want (for example decathlete)
+
+ RSGun doesn't appear to make use of the data transfer features..
+
+ The protection addresses are in the A-Bus area, this should map to the cartridge slot,
+ is there something special in these game cartridges?
+
+ Astra Superstars data were extracted from Saturn version of the game. It is not known if
+ protection device has data stored inside, or they are read from roms (using decryption/decompression)
+
+*/
+
+/****************************************************************************************
+
+Protection & cartridge handling
+
+*****************************************************************************************
+
+These are the known ST-V games that uses this area as a valid protection,I have written
+the data used by the games in the various circumstances for reference:
+-Astra Super Stars [astrass]
+ [0] [1] [2] [3]
+ 0x000y0000 0x00000000 0x06130027 0x01230000 test mode,char transfer (3)
+ 0x???????? 0x???????? 0x???????? 0x???????? attract mode
+ 0x000y0000 0x00000000 0x06130027 0x01230000 gameplay,char transfer (3)
+
+-Elan Doree : Legend of Dragon [elandore]
+ [0] [1] [2] [3]
+ No protection test mode
+ No protection attract mode
+ 0x000y0000 0x00000000 0xe69000f9 0xff7f0000 gameplay,VDP-1 write (textures on humans)
+
+-Final Fight Revenge [ffreveng]
+ [0] [1] [2] [3]
+ 0x000y0000 0x00000000 0x4bcc0013 0x10da0000 test mode,boot vectors at $06080000
+ 0x000y0000 0x00000000 0x0b780013 0x10d70000 attract mode,boot vectors at $06080000
+ 0x???????? 0x???????? 0x???????? 0x???????? gameplay
+
+-Radiant Silvergun [rsgun]
+ [0] [1] [2] [3]
+ No protection test mode
+ 0x000y0000 0x00000000 0x08000010 0x77770000 attract mode,work ram-h $60ff1ec and so on (1)
+ 0x???????? 0x???????? 0x???????? 0x???????? gameplay
+
+-Steep Slope Sliders [sss]
+ [0] [1] [2] [3]
+ No protection test mode
+*0x000y0000 0x00000000 0x000000a6 0x2c5b0000 attract mode,VDP-1 write
+*0x000y0000 0x00000000 0x000000a6 0x2c5b0000 gameplay,VDP-1 write character 1 (2)
+*0x000y0000 0x00000000 0x0f9800a6 0x47f10000 gameplay,VDP-1 write character 2
+*0x000y0000 0x00000000 0x1d4800a6 0xfcda0000 gameplay,VDP-1 write character 3
+*0x000y0000 0x00000000 0x29e300a6 0xb5e60000 gameplay,VDP-1 write character 4
+*0x000y0000 0x00000000 0x38e900a6 0x392c0000 gameplay,VDP-1 write character 5
+*0x000y0000 0x00000000 0x462500a6 0x77c30000 gameplay,VDP-1 write character 6
+*0x000y0000 0x00000000 0x555c00a6 0x8a620000 gameplay,VDP-1 write character 7
+
+=========================================================================================
+y = setted as a 0,then after the ctrl data is moved is toggled to 1 then again toggled
+ to 0 after the reading,this bit is likely to be a "calculate protection values"
+ if 1,use normal ram if 0.
+* = working checks
+[3,low word]AFAIK this is the cartridge area and it's read-only.
+(1)That area is usually (but not always) used as system registers.
+(2)Same as P.O.S.T. check,it was really simple to look-up because of that.
+(3)Wrong offset,or it requires something else like a bitswap?
+=========================================================================================
+Protection works as a sort of data transfer,it could also be that it uses
+encryption on the data used...
+
+For now I'm writing this function with a command basis so I can work better with it.
+****************************************************************************************/
+
+#include "driver.h"
+#include "stvprot.h"
+
+static UINT32 a_bus[4];
+static UINT32 ctrl_index;
+static UINT32 internal_counter;
+static UINT8 char_offset; //helper to jump the decoding of the NULL chars.
+/*
+ffreveng protection notes
+Global:
+R2 is the vector read (where to jump to)
+R3 is the vector pointer
+
+Notes:
+-0x234 is a dummy vector to get safe in the debugger without doing
+anything and to read the registers.
+
+Right vectors:
+0x0603B158 (but not as first,will garbage the registers)
+
+Wrong vectors (at least not where I tested it):
+0x060016fc (1st)
+0x0603AFE0 (1st) (attempts to read to the sh2 internal register fffffe11)
+0x060427FC (1st) (resets the sh2)
+0x0603B1B2 (1st) (crashes the sh2)
+*/
+static UINT32 vector_prot[] = { 0x0603B1B2,0x234 };
+
+static READ32_HANDLER( a_bus_ctrl_r )
+{
+ UINT32 *ROM = (UINT32 *)memory_region(REGION_USER1);
+
+ if(a_bus[0] & 0x00010000)//protection calculation is activated
+ {
+ if(offset == 3)
+ {
+ logerror("A-Bus control protection read at %06x with data = %08x\n",activecpu_get_pc(),a_bus[3]);
+ #ifdef MAME_DEBUG
+ popmessage("Prot read at %06x with data = %08x",activecpu_get_pc(),a_bus[3]);
+ #endif
+ switch(a_bus[3])
+ {
+ case 0x01230000://astrass,char data in test mode PC=60118f2
+ /*
+ TODO: the chars that are used are 8x8x4,but we need to convert them to
+ 16x16x4 format.
+ [01] NULL
+ [02] NULL
+ [03] NULL
+ [04] NULL
+ [05] NULL
+ [06] NULL
+ [07] NULL
+ [08] NULL
+ [09] data 1
+ [10] data 2
+ [11] data 3
+ [12] data 4
+ [13] data 5
+ [14] data 6
+ [15] data 7
+ [16] data 8
+
+ 2b5 = A (up-left)
+ 2b6 = A (up-right)
+ 2d1 = A (down-left)
+ 2d0 = A (down-right)
+ 2f2 = S (up-left)
+ 2f3 = S (up-right)
+ 311 = S (down-left)
+ 310 = S (down-right)
+ 2f4 = T (up-left)
+ 2f5 = T (up-right)
+ 2b7 = E (up-left) (not 2bc,maybe because the up-left corner of E is equal of B?)
+ 2bd = E (up-right)
+ */
+ internal_counter++;
+ if(char_offset == 0)
+ {
+ if(internal_counter > ((8*0x234)-1))
+ {
+ internal_counter = 0;
+ char_offset = 1;
+ }
+
+ return 0;
+ }
+ else
+ {
+ if(internal_counter > 8)
+ {
+ if(internal_counter > 15)
+ {
+ ctrl_index-=8;
+ internal_counter = 0;
+ }
+
+ ctrl_index++;
+ return ROM[ctrl_index];
+ }
+ else
+ {
+ ctrl_index++;
+ return ROM[ctrl_index];
+ }
+ }
+ case 0x10da0000://ffreveng, boot vectors at $6080000,test mode
+ ctrl_index++;
+ if(ctrl_index > 2)
+ return 0x234;
+ else
+ return vector_prot[ctrl_index-1];
+ case 0x10d70000://ffreveng, boot vectors at $6080000,attract mode
+ ctrl_index++;
+ return ROM[ctrl_index];
+ case 0x2c5b0000://sss
+ case 0x47f10000:
+ case 0xfcda0000:
+ case 0xb5e60000:
+ case 0x392c0000:
+ case 0x77c30000:
+ case 0x8a620000:
+ ctrl_index++;
+ return ROM[ctrl_index];
+ case 0x77770000: {//rsgun
+ UINT32 val =
+ ((ctrl_index & 0xff)<<24) |
+ (((ctrl_index+1) & 0xff)<<16) |
+ (((ctrl_index+2) & 0xff)<<8) |
+ ((ctrl_index+3) & 0xff);
+ if(ctrl_index & 0x100)
+ val &= 0x0f0f0f0f;
+ else
+ val &= 0xf0f0f0f0;
+
+ ctrl_index += 4;
+ return val;
+ }
+ case 0xff7f0000://elandore
+ if(a_bus[2] == 0xe69000f9)
+ {
+ ctrl_index++;
+ return ROM[ctrl_index];
+ }
+ else return 0x12345678;
+ case 0xffbf0000:
+ ctrl_index++;
+ return ROM[ctrl_index];
+ }
+ }
+ return a_bus[offset];
+ }
+ else
+ {
+ if(a_bus[offset] != 0) return a_bus[offset];
+ else return ROM[(0x02fffff0/4)+offset];
+ }
+}
+
+static WRITE32_HANDLER ( a_bus_ctrl_w )
+{
+ COMBINE_DATA(&a_bus[offset]);
+ logerror("A-Bus control protection write at %06x: [%02x] <- %08x\n",activecpu_get_pc(),offset,data);
+ if(offset == 3)
+ {
+ switch(a_bus[3])
+ {
+ /*astrass,I need an original test mode screen to compare...*/
+ case 0x01230000:
+ char_offset = 0;
+ internal_counter = 0;
+ ctrl_index = ((0x400000)/4)-1; break;
+ /*ffreveng*/
+ case 0x10d70000: ctrl_index = 0; break;
+ case 0x10da0000: ctrl_index = 0; break;
+ /*sss,TRUSTED*/
+ case 0x2c5b0000: ctrl_index = (0x145ffac/4)-1; break;
+ /*sss,might be offset...*/
+ case 0x47f10000: ctrl_index = ((0x145ffac+0xbaf0)/4)-1; break;
+ case 0xfcda0000: ctrl_index = ((0x145ffac+0x12fd0)/4)-1; break;
+ case 0xb5e60000: ctrl_index = ((0x145ffac+0x1a4c4)/4)-1; break;
+ case 0x392c0000: ctrl_index = ((0x145ffac+0x219b0)/4)-1; break;
+ case 0x77c30000: ctrl_index = ((0x145ffac+0x28ea0)/4)-1; break;
+ case 0x8a620000: ctrl_index = ((0x145ffac+0x30380)/4)-1; break;
+ /*rsgun*/
+ case 0x77770000: ctrl_index = 0; break;
+ /*elandore*/
+ case 0xff7f0000: ctrl_index = ((0x400000)/4)-1; break;
+ case 0xffbf0000: ctrl_index = (0x1c40000/4)-1; break;
+ }
+ }
+ //popmessage("%04x %04x",data,offset/4);
+}
+
+void install_standard_protection(void)
+{
+ memory_install_read32_handler(0, ADDRESS_SPACE_PROGRAM, 0x4fffff0, 0x4ffffff, 0, 0, a_bus_ctrl_r);
+ memory_install_write32_handler(0, ADDRESS_SPACE_PROGRAM, 0x04fffff0, 0x04ffffff, 0, 0, a_bus_ctrl_w);
+}
+
+static READ32_HANDLER(astrass_prot_r)
+{
+ if ( offset == 3 && ctrl_index != -1 )
+ {
+ UINT32 data = 0;
+ UINT32 *prot_data = (UINT32 *)memory_region(REGION_USER2);
+
+ data = prot_data[ctrl_index++];
+
+ if ( ctrl_index >= memory_region_length(REGION_USER2)/4 )
+ {
+ ctrl_index = -1;
+ }
+
+ return data;
+ }
+ return a_bus[offset];
+}
+
+static WRITE32_HANDLER(astrass_prot_w)
+{
+ COMBINE_DATA(&a_bus[0 + offset]);
+ if ( offset == 3 )
+ {
+ ctrl_index = 0;
+ }
+}
+
+void install_astrass_protection(void)
+{
+ ctrl_index = -1;
+ memory_install_read32_handler(0, ADDRESS_SPACE_PROGRAM, 0x4fffff0, 0x4ffffff, 0, 0, astrass_prot_r);
+ memory_install_write32_handler(0, ADDRESS_SPACE_PROGRAM, 0x04fffff0, 0x04ffffff, 0, 0, astrass_prot_w);
+}
+
+
+/* Decathlete seems to be a variation on this ... not understood */
+static UINT32 decathlt_protregs[4];
+static UINT32 decathlt_lastcount = 0;
+static UINT32 decathlt_part = 1;
+static UINT32 decathlt_prot_uploadmode=0;
+static UINT32 decathlt_prot_uploadoffset=0;
+static UINT16 decathlt_prottable1[24];
+static UINT16 decathlt_prottable2[128];
+
+static READ32_HANDLER( decathlt_prot_r )
+{
+ UINT32 *ROM = (UINT32 *)memory_region(REGION_USER1);
+
+ if (offset==2)
+ {
+ //UINT32 retval;
+ /* I think the address and data are scrambled.. */
+ UINT32 retvalue = /*rand() | (rand()<<16);*/ ROM[(decathlt_protregs[0])];
+ decathlt_protregs[0]++;
+ decathlt_lastcount++;
+ return retvalue; // reads this, then the game writes it to vram...
+ }
+ else
+ {
+ mame_printf_info("%06x Decathlete prot R offset %04x mask %08x regs %08x, %08x, %08x, %08x\n",activecpu_get_pc(), offset, mem_mask, decathlt_protregs[0], decathlt_protregs[1], decathlt_protregs[2], decathlt_protregs[3]);
+ }
+
+ return decathlt_protregs[offset];
+}
+
+static WRITE32_HANDLER( decathlt_prot_w )
+{
+ decathlt_protregs[offset] = (data&~mem_mask)|(decathlt_protregs[offset]&mem_mask);
+// decathlt_protregs[0] = 0x0c00000/4;
+
+ if (offset==0) // seems to set a (scrambled?) source address
+ {
+ decathlt_part ^=1;
+
+ if (decathlt_part==0) mame_printf_info("last count was %06x\n",decathlt_lastcount);
+ decathlt_lastcount = 0;
+ mame_printf_info("%06x Decathlete prot W offset %04x data %08x, regs %08x, %08x, %08x, %08x\n",activecpu_get_pc(), offset, data, decathlt_protregs[0], decathlt_protregs[1], decathlt_protregs[2], decathlt_protregs[3]);
+ }
+
+ if (offset==1) // uploads 2 tables...
+ {
+ if (mem_mask==0x0000ffff)
+ {
+ if (data == 0x80000000)
+ {
+ mame_printf_info("changed to upload mode 1\n");
+ decathlt_prot_uploadmode = 1;
+ decathlt_prot_uploadoffset = 0;
+ }
+ else if (data == 0x80800000)
+ {
+ mame_printf_info("changed to upload mode 2\n");
+ decathlt_prot_uploadmode = 2;
+ decathlt_prot_uploadoffset = 0;
+ }
+ else
+ {
+ mame_printf_info("unknown upload mode\n");
+ decathlt_prot_uploadmode = 2;
+ decathlt_prot_uploadoffset = 0;
+ }
+
+// mame_printf_info("ARGH! %08x %08x\n",mem_mask,data);
+ }
+ else if (mem_mask==0xffff0000)
+ {
+ if (decathlt_prot_uploadmode==1)
+ {
+ if (decathlt_prot_uploadoffset>=24)
+ {
+ mame_printf_info("upload mode 1 error, too big\n");
+ return;
+ }
+
+ mame_printf_info("uploading table 1 %04x %04x\n",decathlt_prot_uploadoffset, data&0xffff);
+ decathlt_prottable1[decathlt_prot_uploadoffset]=data&0xffff;
+ decathlt_prot_uploadoffset++;
+
+ {
+ /* 0x18 (24) values in this table, rom data is 0x1800000 long, maybe it has
+ something to do with that? or 24-address bits?
+
+ uploaded values appear to be 12-bit, some are repeated
+ */
+ FILE* fp;
+ fp = fopen("table1","wb");
+ {
+ fwrite(&decathlt_prottable2,24,2,fp);
+ }
+ fclose(fp);
+ }
+
+ }
+ else if (decathlt_prot_uploadmode==2)
+ {
+ if (decathlt_prot_uploadoffset>=128)
+ {
+ mame_printf_info("upload mode 2 error, too big\n");
+ return;
+ }
+
+ mame_printf_info("uploading table 2 %04x %04x\n",decathlt_prot_uploadoffset, data&0xffff);
+ decathlt_prottable2[decathlt_prot_uploadoffset]=data&0xffff;
+ decathlt_prot_uploadoffset++;
+
+ {
+ /* the table uploaded here is a 256 byte table with 256 unique values, remaps something? */
+ FILE* fp;
+ fp = fopen("table2","wb");
+ {
+ fwrite(&decathlt_prottable2,128,2,fp);
+ }
+ fclose(fp);
+ }
+ }
+ else
+ {
+ mame_printf_info("unknown upload mode!\n");
+ }
+ }
+ }
+
+ if (offset>1)
+ {
+ mame_printf_info("higher offset write\n");
+ }
+
+}
+
+void install_decathlt_protection(void)
+{
+ /* It uploads 2 tables here, then performs what looks like a number of transfers, setting
+ a source address of some kind (scrambled?) and then making many reads from a single address */
+ memory_install_read32_handler(0, ADDRESS_SPACE_PROGRAM, 0x37FFFF0, 0x37FFFFF, 0, 0, decathlt_prot_r);
+ memory_install_write32_handler(0, ADDRESS_SPACE_PROGRAM, 0x37FFFF0, 0x37FFFFF, 0, 0, decathlt_prot_w);
+ /* It uploads 2 tables here too, but nothing else, mirror? unused? */
+// memory_install_read32_handler(0, ADDRESS_SPACE_PROGRAM, 0x27FFFF0, 0x27FFFFF, 0, 0, decathlt_prot_r);
+// memory_install_write32_handler(0, ADDRESS_SPACE_PROGRAM, 0x27FFFF0, 0x27FFFFF, 0, 0, decathlt_prot_w);
+}
+
+void stv_register_protection_savestates(void)
+{
+ state_save_register_global_array(a_bus);
+ state_save_register_global(ctrl_index);
+ state_save_register_global(internal_counter);
+ state_save_register_global(char_offset);
+}
diff --git a/src/mame/machine/stvprot.h b/src/mame/machine/stvprot.h
new file mode 100644
index 00000000000..dd83b3cbc9a
--- /dev/null
+++ b/src/mame/machine/stvprot.h
@@ -0,0 +1,8 @@
+/* stvprot.h */
+
+void install_standard_protection(void);
+void install_decathlt_protection(void);
+void install_astrass_protection(void);
+
+void stv_register_protection_savestates(void);
+
diff --git a/src/mame/machine/subs.c b/src/mame/machine/subs.c
new file mode 100644
index 00000000000..d6a84d31703
--- /dev/null
+++ b/src/mame/machine/subs.c
@@ -0,0 +1,186 @@
+/***************************************************************************
+
+ Atari Subs hardware
+
+***************************************************************************/
+
+#include "driver.h"
+#include "subs.h"
+
+static int subs_steering_buf1;
+static int subs_steering_buf2;
+static int subs_steering_val1;
+static int subs_steering_val2;
+
+/***************************************************************************
+subs_init_machine
+***************************************************************************/
+MACHINE_RESET( subs )
+{
+ subs_steering_buf1 = 0;
+ subs_steering_buf2 = 0;
+ subs_steering_val1 = 0x00;
+ subs_steering_val2 = 0x00;
+}
+
+/***************************************************************************
+subs_interrupt
+***************************************************************************/
+INTERRUPT_GEN( subs_interrupt )
+{
+ /* only do NMI interrupt if not in TEST mode */
+ if ((input_port_2_r(0) & 0x40)==0x40)
+ cpunum_set_input_line(0,INPUT_LINE_NMI,PULSE_LINE);
+}
+
+/***************************************************************************
+Steering
+
+When D7 is high, the steering wheel has moved.
+If D6 is high, it moved left. If D6 is low, it moved right.
+Be sure to keep returning a direction until steer_reset is called.
+***************************************************************************/
+static int subs_steering_1(void)
+{
+ static int last_val=0;
+ int this_val;
+ int delta;
+
+ this_val=input_port_3_r(0);
+
+ delta=this_val-last_val;
+ last_val=this_val;
+ if (delta>128) delta-=256;
+ else if (delta<-128) delta+=256;
+ /* Divide by four to make our steering less sensitive */
+ subs_steering_buf1+=(delta/4);
+
+ if (subs_steering_buf1>0)
+ {
+ subs_steering_buf1--;
+ subs_steering_val1=0xC0;
+ }
+ else if (subs_steering_buf1<0)
+ {
+ subs_steering_buf1++;
+ subs_steering_val1=0x80;
+ }
+
+ return subs_steering_val1;
+}
+
+static int subs_steering_2(void)
+{
+ static int last_val=0;
+ int this_val;
+ int delta;
+
+ this_val=input_port_4_r(0);
+
+ delta=this_val-last_val;
+ last_val=this_val;
+ if (delta>128) delta-=256;
+ else if (delta<-128) delta+=256;
+ /* Divide by four to make our steering less sensitive */
+ subs_steering_buf2+=(delta/4);
+
+ if (subs_steering_buf2>0)
+ {
+ subs_steering_buf2--;
+ subs_steering_val2=0xC0;
+ }
+ else if (subs_steering_buf2<0)
+ {
+ subs_steering_buf2++;
+ subs_steering_val2=0x80;
+ }
+
+ return subs_steering_val2;
+}
+
+/***************************************************************************
+subs_steer_reset
+***************************************************************************/
+WRITE8_HANDLER( subs_steer_reset_w )
+{
+ subs_steering_val1 = 0x00;
+ subs_steering_val2 = 0x00;
+}
+
+/***************************************************************************
+subs_control_r
+***************************************************************************/
+READ8_HANDLER( subs_control_r )
+{
+ int inport = input_port_1_r(offset);
+
+ switch (offset & 0x07)
+ {
+ case 0x00: return ((inport & 0x01) << 7); /* diag step */
+ case 0x01: return ((inport & 0x02) << 6); /* diag hold */
+ case 0x02: return ((inport & 0x04) << 5); /* slam */
+ case 0x03: return ((inport & 0x08) << 4); /* spare */
+ case 0x04: return ((subs_steering_1() & 0x40) << 1); /* steer dir 1 */
+ case 0x05: return ((subs_steering_1() & 0x80) << 0); /* steer flag 1 */
+ case 0x06: return ((subs_steering_2() & 0x40) << 1); /* steer dir 2 */
+ case 0x07: return ((subs_steering_2() & 0x80) << 0); /* steer flag 2 */
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+subs_coin_r
+***************************************************************************/
+READ8_HANDLER( subs_coin_r )
+{
+ int inport = input_port_2_r(offset);
+
+ switch (offset & 0x07)
+ {
+ case 0x00: return ((inport & 0x01) << 7); /* coin 1 */
+ case 0x01: return ((inport & 0x02) << 6); /* start 1 */
+ case 0x02: return ((inport & 0x04) << 5); /* coin 2 */
+ case 0x03: return ((inport & 0x08) << 4); /* start 2 */
+ case 0x04: return ((inport & 0x10) << 3); /* VBLANK */
+ case 0x05: return ((inport & 0x20) << 2); /* fire 1 */
+ case 0x06: return ((inport & 0x40) << 1); /* test */
+ case 0x07: return ((inport & 0x80) << 0); /* fire 2 */
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+subs_options_r
+***************************************************************************/
+READ8_HANDLER( subs_options_r )
+{
+ int opts = input_port_0_r(offset);
+
+ switch (offset & 0x03)
+ {
+ case 0x00: return ((opts & 0xC0) >> 6); /* language */
+ case 0x01: return ((opts & 0x30) >> 4); /* credits */
+ case 0x02: return ((opts & 0x0C) >> 2); /* game time */
+ case 0x03: return ((opts & 0x03) >> 0); /* extended time */
+ }
+
+ return 0;
+}
+
+/***************************************************************************
+subs_lamp1_w
+***************************************************************************/
+WRITE8_HANDLER( subs_lamp1_w )
+{
+ set_led_status(0,~offset & 1);
+}
+
+/***************************************************************************
+subs_lamp2_w
+***************************************************************************/
+WRITE8_HANDLER( subs_lamp2_w )
+{
+ set_led_status(1,~offset & 1);
+}
diff --git a/src/mame/machine/system16.c b/src/mame/machine/system16.c
new file mode 100644
index 00000000000..d4d315bda77
--- /dev/null
+++ b/src/mame/machine/system16.c
@@ -0,0 +1,69 @@
+#include "driver.h"
+#include "system16.h"
+#include "sound/upd7759.h"
+
+UINT16 *sys16_workingram;
+UINT16 *sys16_workingram2;
+UINT16 *sys16_extraram;
+UINT16 *sys16_extraram2;
+UINT16 *sys16_extraram3;
+
+static void patch_codeX( int offset, int data, int cpu ){
+ int aligned_offset = offset&0xfffffe;
+ UINT16 *mem = (UINT16 *)memory_region(REGION_CPU1+cpu);
+ int old_word = mem[aligned_offset/2];
+
+ if( offset&1 )
+ data = (old_word&0xff00)|data;
+ else
+ data = (old_word&0x00ff)|(data<<8);
+
+ mem[aligned_offset/2] = data;
+}
+
+void sys16_patch_code( int offset, int data ){
+ patch_codeX(offset,data,0);
+}
+
+
+MACHINE_RESET( sys16_onetime ){
+ sys16_bg1_trans=0;
+ sys16_rowscroll_scroll=0;
+ sys18_splittab_bg_x=0;
+ sys18_splittab_bg_y=0;
+ sys18_splittab_fg_x=0;
+ sys18_splittab_fg_y=0;
+}
+
+static const gfx_layout charlayout =
+{
+ 8,8,
+ RGN_FRAC(1,3),
+ 3,
+ { RGN_FRAC(2,3), RGN_FRAC(1,3), RGN_FRAC(0,3) },
+ { 0, 1, 2, 3, 4, 5, 6, 7 },
+ { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
+ 8*8
+};
+
+GFXDECODE_START( sys16 )
+ GFXDECODE_ENTRY( REGION_GFX1, 0, charlayout, 0, 1024 )
+GFXDECODE_END
+
+
+/* sound */
+
+static void sound_cause_nmi( int chip ){
+ /* upd7759 callback */
+ cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
+}
+
+
+struct upd7759_interface sys16_upd7759_interface =
+{
+ 0, /* memory region 3 contains the sample data */
+ sound_cause_nmi
+};
+
+int sys18_sound_info[4*2];
+
diff --git a/src/mame/machine/system24.c b/src/mame/machine/system24.c
new file mode 100644
index 00000000000..282368df146
--- /dev/null
+++ b/src/mame/machine/system24.c
@@ -0,0 +1,109 @@
+#include "driver.h"
+#include "system16.h"
+#include "includes/system24.h"
+
+/* system24temp_ functions / variables are from shared rewrite files,
+ once the rest of the rewrite is complete they can be removed, I
+ just made a copy & renamed them for now to avoid any conflicts
+*/
+
+UINT16 *system24temp_sys16_shared_ram;
+READ16_HANDLER( system24temp_sys16_shared_ram_r )
+{
+ return system24temp_sys16_shared_ram[offset];
+}
+
+WRITE16_HANDLER( system24temp_sys16_shared_ram_w )
+{
+ COMBINE_DATA(system24temp_sys16_shared_ram + offset);
+}
+
+/* The 315-5296
+ 8 8bits I/O ports, 3 output-only pins, some protection, and
+ external/daughterboard chip selection on half of the address
+ range
+*/
+
+static UINT8 (*system24temp_sys16_io_io_r)(int port);
+static void (*system24temp_sys16_io_io_w)(int port, UINT8 data);
+static void (*system24temp_sys16_io_cnt_w)(UINT8 data);
+static READ16_HANDLER ((*system24temp_sys16_io_iod_r));
+static WRITE16_HANDLER((*system24temp_sys16_io_iod_w));
+static UINT8 system24temp_sys16_io_cnt, system24temp_sys16_io_dir;
+
+void system24temp_sys16_io_set_callbacks(UINT8 (*io_r)(int port),
+ void (*io_w)(int port, UINT8 data),
+ void (*cnt_w)(UINT8 data),
+ READ16_HANDLER ((*iod_r)),
+ WRITE16_HANDLER((*iod_w)))
+{
+ system24temp_sys16_io_io_r = io_r;
+ system24temp_sys16_io_io_w = io_w;
+ system24temp_sys16_io_cnt_w = cnt_w;
+ system24temp_sys16_io_iod_r = iod_r;
+ system24temp_sys16_io_iod_w = iod_w;
+ system24temp_sys16_io_cnt = 0x00;
+ system24temp_sys16_io_dir = 0x00;
+}
+
+READ16_HANDLER ( system24temp_sys16_io_r )
+{
+ // logerror("IO read %02x (%d:%x)\n", offset, cpu_getactivecpu(), activecpu_get_pc());
+ if(offset < 8)
+ return system24temp_sys16_io_io_r ? system24temp_sys16_io_io_r(offset) : 0xff;
+ else if (offset < 0x20) {
+ switch(offset) {
+ case 0x8:
+ return 'S';
+ case 0x9:
+ return 'E';
+ case 0xa:
+ return 'G';
+ case 0xb:
+ return 'A';
+ case 0xe:
+ return system24temp_sys16_io_cnt;
+ case 0xf:
+ return system24temp_sys16_io_dir;
+ default:
+ logerror("IO control read %02x (%d:%x)\n", offset, cpu_getactivecpu(), activecpu_get_pc());
+ return 0xff;
+ }
+ } else
+ return system24temp_sys16_io_iod_r ? system24temp_sys16_io_iod_r(offset & 0x1f, mem_mask) : 0xff;
+}
+
+READ32_HANDLER(system24temp_sys16_io_dword_r)
+{
+ return system24temp_sys16_io_r(2*offset, mem_mask)|(system24temp_sys16_io_r(2*offset+1, mem_mask>>16)<<16);
+}
+
+
+WRITE16_HANDLER( system24temp_sys16_io_w )
+{
+ if(ACCESSING_LSB) {
+ if(offset < 8) {
+ if(!(system24temp_sys16_io_dir & (1 << offset))) {
+ logerror("IO port write on input-only port (%d, [%02x], %02x, %d:%x)\n", offset, system24temp_sys16_io_dir, data & 0xff, cpu_getactivecpu(), activecpu_get_pc());
+ return;
+ }
+ if(system24temp_sys16_io_io_w)
+ system24temp_sys16_io_io_w(offset, data);
+ } else if (offset < 0x20) {
+ switch(offset) {
+ case 0xe:
+ system24temp_sys16_io_cnt = data;
+ if(system24temp_sys16_io_cnt_w)
+ system24temp_sys16_io_cnt_w(data & 7);
+ break;
+ case 0xf:
+ system24temp_sys16_io_dir = data;
+ break;
+ default:
+ logerror("IO control write %02x, %02x (%d:%x)\n", offset, data & 0xff, cpu_getactivecpu(), activecpu_get_pc());
+ }
+ }
+ }
+ if(offset >= 0x20 && system24temp_sys16_io_iod_w)
+ system24temp_sys16_io_iod_w(offset & 0x1f, data, mem_mask);
+}
diff --git a/src/mame/machine/tait8741.c b/src/mame/machine/tait8741.c
new file mode 100644
index 00000000000..fcb16982a77
--- /dev/null
+++ b/src/mame/machine/tait8741.c
@@ -0,0 +1,553 @@
+/*
+
+Taito 8741 emulation
+
+1.The pair chip for the PIO and serial communication between MAIN CPU and the sub CPU
+2.The PIO for DIP SW and the controller reading.
+
+*/
+
+#include "driver.h"
+#include "tait8741.h"
+
+#define __log__ 0
+
+/****************************************************************************
+
+gladiatr and Great Swordsman set.
+
+ -comminucation main and sub cpu
+ -dipswitch and key handling x 2chip
+
+ Total 4chip
+
+ It was supposed from the schematic of gladiator.
+ Now, because dump is done, change the MCU code of gladiator to the CPU emulation.
+
+****************************************************************************/
+
+#define CMD_IDLE 0
+#define CMD_08 1
+#define CMD_4a 2
+
+typedef struct TAITO8741_status{
+ UINT8 toData; /* to host data */
+ UINT8 fromData; /* from host data */
+ UINT8 fromCmd; /* from host command */
+ UINT8 status; /* b0 = rd ready,b1 = wd full,b2 = cmd ?? */
+ UINT8 mode;
+ UINT8 phase;
+ UINT8 txd[8];
+ UINT8 rxd[8];
+ UINT8 parallelselect;
+ UINT8 txpoint;
+ int connect;
+ UINT8 pending4a;
+ int serial_out;
+ int coins;
+ read8_handler portHandler;
+}I8741;
+
+static const struct TAITO8741interface *intf;
+//static I8741 *taito8741;
+static I8741 taito8741[MAX_TAITO8741];
+
+/* for host data , write */
+static void taito8741_hostdata_w(I8741 *st,int data)
+{
+ st->toData = data;
+ st->status |= 0x01;
+}
+
+/* from host data , read */
+static int taito8741_hostdata_r(I8741 *st)
+{
+ if( !(st->status & 0x02) ) return -1;
+ st->status &= 0xfd;
+ return st->fromData;
+}
+
+/* from host command , read */
+static int taito8741_hostcmd_r(I8741 *st)
+{
+ if(!(st->status & 0x04)) return -1;
+ st->status &= 0xfb;
+ return st->fromCmd;
+}
+
+
+/* TAITO8741 I8741 emulation */
+
+static void taito8741_serial_rx(I8741 *st,UINT8 *data)
+{
+ memcpy(st->rxd,data,8);
+}
+
+/* timer callback of serial tx finish */
+static TIMER_CALLBACK( taito8741_serial_tx )
+{
+ int num = param;
+ I8741 *st = &taito8741[num];
+ I8741 *sst;
+
+ if( st->mode==TAITO8741_MASTER)
+ st->serial_out = 1;
+
+ st->txpoint = 1;
+ if(st->connect >= 0 )
+ {
+ sst = &taito8741[st->connect];
+ /* transfer data */
+ taito8741_serial_rx(sst,st->txd);
+#if __log__
+ logerror("8741-%d Serial data TX to %d\n",num,st->connect);
+#endif
+ if( sst->mode==TAITO8741_SLAVE)
+ sst->serial_out = 1;
+ }
+}
+
+void TAITO8741_reset(int num)
+{
+ I8741 *st = &taito8741[num];
+ st->status = 0x00;
+ st->phase = 0;
+ st->parallelselect = 0;
+ st->txpoint = 1;
+ st->pending4a = 0;
+ st->serial_out = 0;
+ st->coins = 0;
+ memset(st->rxd,0,8);
+ memset(st->txd,0,8);
+}
+
+/* 8741 update */
+static void taito8741_update(int num)
+{
+ I8741 *st,*sst;
+ int next = num;
+ int data;
+
+ do{
+ num = next;
+ st = &taito8741[num];
+ if( st->connect != -1 )
+ sst = &taito8741[st->connect];
+ else sst = 0;
+ next = -1;
+ /* check pending command */
+ switch(st->phase)
+ {
+ case CMD_08: /* serial data latch */
+ if( st->serial_out)
+ {
+ st->status &= 0xfb; /* patch for gsword */
+ st->phase = CMD_IDLE;
+ next = num; /* continue this chip */
+ }
+ break;
+ case CMD_4a: /* wait for syncronus ? */
+ if(!st->pending4a)
+ {
+ taito8741_hostdata_w(st,0);
+ st->phase = CMD_IDLE;
+ next = num; /* continue this chip */
+ }
+ break;
+ case CMD_IDLE:
+ /* ----- data in port check ----- */
+ data = taito8741_hostdata_r(st);
+ if( data != -1 )
+ {
+ switch(st->mode)
+ {
+ case TAITO8741_MASTER:
+ case TAITO8741_SLAVE:
+ /* buffering transmit data */
+ if( st->txpoint < 8 )
+ {
+//if (st->txpoint == 0 && num==1 && data&0x80) logerror("Coin Put\n");
+ st->txd[st->txpoint++] = data;
+ }
+ break;
+ case TAITO8741_PORT:
+ if( data & 0xf8)
+ { /* ?? */
+ }
+ else
+ { /* port select */
+ st->parallelselect = data & 0x07;
+ taito8741_hostdata_w(st,st->portHandler ? st->portHandler(st->parallelselect) : 0);
+ }
+ }
+ }
+ /* ----- new command fetch ----- */
+ data = taito8741_hostcmd_r(st);
+ switch( data )
+ {
+ case -1: /* no command data */
+ break;
+ case 0x00: /* read from parallel port */
+ taito8741_hostdata_w(st,st->portHandler ? st->portHandler(0) : 0 );
+ break;
+ case 0x01: /* read receive buffer 0 */
+ case 0x02: /* read receive buffer 1 */
+ case 0x03: /* read receive buffer 2 */
+ case 0x04: /* read receive buffer 3 */
+ case 0x05: /* read receive buffer 4 */
+ case 0x06: /* read receive buffer 5 */
+ case 0x07: /* read receive buffer 6 */
+//if (data == 2 && num==0 && st->rxd[data-1]&0x80) logerror("Coin Get\n");
+ taito8741_hostdata_w(st,st->rxd[data-1]);
+ break;
+ case 0x08: /* latch received serial data */
+ st->txd[0] = st->portHandler ? st->portHandler(0) : 0;
+ if( sst )
+ {
+ timer_call_after_resynch(num,taito8741_serial_tx);
+ st->serial_out = 0;
+ st->status |= 0x04;
+ st->phase = CMD_08;
+ }
+ break;
+ case 0x0a: /* 8741-0 : set serial comminucation mode 'MASTER' */
+ //st->mode = TAITO8741_MASTER;
+ break;
+ case 0x0b: /* 8741-1 : set serial comminucation mode 'SLAVE' */
+ //st->mode = TAITO8741_SLAVE;
+ break;
+ case 0x1f: /* 8741-2,3 : ?? set parallelport mode ?? */
+ case 0x3f: /* 8741-2,3 : ?? set parallelport mode ?? */
+ case 0xe1: /* 8741-2,3 : ?? set parallelport mode ?? */
+ st->mode = TAITO8741_PORT;
+ st->parallelselect = 1; /* preset read number */
+ break;
+ case 0x62: /* 8741-3 : ? */
+ break;
+ case 0x4a: /* ?? syncronus with other cpu and return 00H */
+ if( sst )
+ {
+ if(sst->pending4a)
+ {
+ sst->pending4a = 0; /* syncronus */
+ taito8741_hostdata_w(st,0); /* return for host */
+ next = st->connect;
+ }
+ else st->phase = CMD_4a;
+ }
+ break;
+ case 0x80: /* 8741-3 : return check code */
+ taito8741_hostdata_w(st,0x66);
+ break;
+ case 0x81: /* 8741-2 : return check code */
+ taito8741_hostdata_w(st,0x48);
+ break;
+ case 0xf0: /* GSWORD 8741-1 : initialize ?? */
+ break;
+ case 0x82: /* GSWORD 8741-2 unknown */
+ break;
+ }
+ break;
+ }
+ }while(next>=0);
+}
+
+int TAITO8741_start(const struct TAITO8741interface *taito8741intf)
+{
+ int i;
+
+ intf = taito8741intf;
+
+ //taito8741 = (I8741 *)malloc(intf->num*sizeof(I8741));
+ //if( taito8741 == 0 ) return 1;
+
+ for(i=0;i<intf->num;i++)
+ {
+ taito8741[i].connect = intf->serial_connect[i];
+ taito8741[i].portHandler = intf->portHandler_r[i];
+ taito8741[i].mode = intf->mode[i];
+ TAITO8741_reset(i);
+ }
+ return 0;
+}
+
+/* read status port */
+static int I8741_status_r(int num)
+{
+ I8741 *st = &taito8741[num];
+ taito8741_update(num);
+#if __log__
+ logerror("8741-%d ST Read %02x PC=%04x\n",num,st->status,activecpu_get_pc());
+#endif
+ return st->status;
+}
+
+/* read data port */
+static int I8741_data_r(int num)
+{
+ I8741 *st = &taito8741[num];
+ int ret = st->toData;
+ st->status &= 0xfe;
+#if __log__
+ logerror("8741-%d DATA Read %02x PC=%04x\n",num,ret,activecpu_get_pc());
+#endif
+ /* update chip */
+ taito8741_update(num);
+
+ switch( st->mode )
+ {
+ case TAITO8741_PORT: /* parallel data */
+ taito8741_hostdata_w(st,st->portHandler ? st->portHandler(st->parallelselect) : 0);
+ break;
+ }
+ return ret;
+}
+
+/* Write data port */
+static void I8741_data_w(int num, int data)
+{
+ I8741 *st = &taito8741[num];
+#if __log__
+ logerror("8741-%d DATA Write %02x PC=%04x\n",num,data,activecpu_get_pc());
+#endif
+ st->fromData = data;
+ st->status |= 0x02;
+ /* update chip */
+ taito8741_update(num);
+}
+
+/* Write command port */
+static void I8741_command_w(int num, int data)
+{
+ I8741 *st = &taito8741[num];
+#if __log__
+ logerror("8741-%d CMD Write %02x PC=%04x\n",num,data,activecpu_get_pc());
+#endif
+ st->fromCmd = data;
+ st->status |= 0x04;
+ /* update chip */
+ taito8741_update(num);
+}
+
+/* Write port handler */
+WRITE8_HANDLER( TAITO8741_0_w )
+{
+ if(offset&1) I8741_command_w(0,data);
+ else I8741_data_w(0,data);
+}
+WRITE8_HANDLER( TAITO8741_1_w )
+{
+ if(offset&1) I8741_command_w(1,data);
+ else I8741_data_w(1,data);
+}
+WRITE8_HANDLER( TAITO8741_2_w )
+{
+ if(offset&1) I8741_command_w(2,data);
+ else I8741_data_w(2,data);
+}
+WRITE8_HANDLER( TAITO8741_3_w )
+{
+ if(offset&1) I8741_command_w(3,data);
+ else I8741_data_w(3,data);
+}
+
+/* Read port handler */
+READ8_HANDLER( TAITO8741_0_r )
+{
+ if(offset&1) return I8741_status_r(0);
+ return I8741_data_r(0);
+}
+READ8_HANDLER( TAITO8741_1_r )
+{
+ if(offset&1) return I8741_status_r(1);
+ return I8741_data_r(1);
+}
+READ8_HANDLER( TAITO8741_2_r )
+{
+ if(offset&1) return I8741_status_r(2);
+ return I8741_data_r(2);
+}
+READ8_HANDLER( TAITO8741_3_r )
+{
+ if(offset&1) return I8741_status_r(3);
+ return I8741_data_r(3);
+}
+/****************************************************************************
+
+joshi Vollyball set.
+
+ Only the chip of the communication between MAIN and the SUB.
+ For the I/O, there may be I8741 of the addition.
+
+ MCU code is not dumped.
+ There is some HACK operation because the emulation is imperfect.
+
+****************************************************************************/
+
+int josvolly_nmi_enable;
+
+typedef struct josvolly_8741_struct {
+ UINT8 cmd;
+ UINT8 sts;
+ UINT8 txd;
+ UINT8 outport;
+ UINT8 rxd;
+ UINT8 connect;
+
+ UINT8 rst;
+
+ read8_handler initReadPort;
+}JV8741;
+
+static JV8741 i8741[4];
+
+void josvolly_8741_reset(void)
+{
+ int i;
+
+ josvolly_nmi_enable = 0;
+
+ for(i=0;i<4;i++)
+ {
+ i8741[i].cmd = 0;
+ i8741[i].sts = 0; // 0xf0; /* init flag */
+ i8741[i].txd = 0;
+ i8741[i].outport = 0xff;
+ i8741[i].rxd = 0;
+
+ i8741[i].rst = 1;
+
+ }
+ i8741[0].connect = 1;
+ i8741[1].connect = 0;
+
+ i8741[0].initReadPort = input_port_3_r; /* DSW1 */
+ i8741[1].initReadPort = input_port_4_r; /* DSW2 */
+ i8741[2].initReadPort = input_port_3_r; /* DUMMY */
+ i8741[3].initReadPort = input_port_4_r; /* DUMMY */
+}
+
+/* transmit data finish callback */
+static TIMER_CALLBACK( josvolly_8741_tx )
+{
+ int num = param;
+ JV8741 *src = &i8741[num];
+ JV8741 *dst = &i8741[src->connect];
+
+ dst->rxd = src->txd;
+
+ src->sts &= ~0x02; /* TX full ? */
+ dst->sts |= 0x01; /* RX ready ? */
+}
+
+static void josvolly_8741_do(int num)
+{
+ if( (i8741[num].sts & 0x02) )
+ {
+ /* transmit data */
+ timer_set (ATTOTIME_IN_USEC(1),num,josvolly_8741_tx);
+ }
+}
+
+static void josvolly_8741_w(int num,int offset,int data,int log)
+{
+ JV8741 *mcu = &i8741[num];
+
+ if(offset==1)
+ {
+#if __log__
+if(log)
+ logerror("PC=%04X 8741[%d] CW %02X\n",activecpu_get_pc(),num,data);
+#endif
+
+ /* read pointer */
+ mcu->cmd = data;
+ /* CMD */
+ switch(data)
+ {
+ case 0:
+ mcu->txd = data ^ 0x40;
+ mcu->sts |= 0x02;
+ break;
+ case 1:
+ mcu->txd = data ^ 0x40;
+ mcu->sts |= 0x02;
+#if 1
+ /* ?? */
+ mcu->rxd = 0; /* SBSTS ( DIAG ) , killed */
+ mcu->sts |= 0x01; /* RD ready */
+#endif
+ break;
+ case 2:
+#if 1
+ mcu->rxd = input_port_4_r(0); /* DSW2 */
+ mcu->sts |= 0x01; /* RD ready */
+#endif
+ break;
+ case 3: /* normal mode ? */
+ break;
+
+ case 0xf0: /* clear main sts ? */
+ mcu->txd = data ^ 0x40;
+ mcu->sts |= 0x02;
+ break;
+ }
+ }
+ else
+ {
+ /* data */
+#if __log__
+if(log)
+ logerror("PC=%04X 8741[%d] DW %02X\n",activecpu_get_pc(),num,data);
+#endif
+
+ mcu->txd = data^0x40; /* parity reverce ? */
+ mcu->sts |= 0x02; /* TXD busy */
+#if 1
+ /* interrupt ? */
+ if(num==0)
+ {
+ if(josvolly_nmi_enable)
+ {
+ cpunum_set_input_line(1, INPUT_LINE_NMI, PULSE_LINE);
+ josvolly_nmi_enable = 0;
+ }
+ }
+#endif
+ }
+ josvolly_8741_do(num);
+}
+
+static INT8 josvolly_8741_r(int num,int offset,int log)
+{
+ JV8741 *mcu = &i8741[num];
+ int ret;
+
+ if(offset==1)
+ {
+ if(mcu->rst)
+ mcu->rxd = (mcu->initReadPort)(0); /* port in */
+ ret = mcu->sts;
+#if __log__
+if(log)
+ logerror("PC=%04X 8741[%d] SR %02X\n",activecpu_get_pc(),num,ret);
+#endif
+ }
+ else
+ {
+ /* clear status port */
+ mcu->sts &= ~0x01; /* RD ready */
+ ret = mcu->rxd;
+#if __log__
+if(log)
+ logerror("PC=%04X 8741[%d] DR %02X\n",activecpu_get_pc(),num,ret);
+#endif
+ mcu->rst = 0;
+ }
+ return ret;
+}
+
+WRITE8_HANDLER( josvolly_8741_0_w ){ josvolly_8741_w(0,offset,data,1); }
+READ8_HANDLER( josvolly_8741_0_r ) { return josvolly_8741_r(0,offset,1); }
+WRITE8_HANDLER( josvolly_8741_1_w ) { josvolly_8741_w(1,offset,data,1); }
+READ8_HANDLER( josvolly_8741_1_r ) { return josvolly_8741_r(1,offset,1); }
diff --git a/src/mame/machine/tait8741.h b/src/mame/machine/tait8741.h
new file mode 100644
index 00000000000..88d909d536e
--- /dev/null
+++ b/src/mame/machine/tait8741.h
@@ -0,0 +1,50 @@
+#ifndef __TAITO8741__
+#define __TAITO8741__
+
+/****************************************************************************
+ gladiatr and Great Swordsman set.
+****************************************************************************/
+
+#define MAX_TAITO8741 4
+
+/* NEC 8741 program mode */
+#define TAITO8741_MASTER 0
+#define TAITO8741_SLAVE 1
+#define TAITO8741_PORT 2
+
+struct TAITO8741interface
+{
+ int num;
+ int mode[MAX_TAITO8741]; /* program select */
+ int serial_connect[MAX_TAITO8741]; /* serial port connection */
+ read8_handler portHandler_r[MAX_TAITO8741]; /* parallel port handler */
+};
+
+int TAITO8741_start(const struct TAITO8741interface *taito8741intf);
+
+void TAITO8741_reset(int num);
+
+/* write handler */
+WRITE8_HANDLER( TAITO8741_0_w );
+WRITE8_HANDLER( TAITO8741_1_w );
+WRITE8_HANDLER( TAITO8741_2_w );
+WRITE8_HANDLER( TAITO8741_3_w );
+/* read handler */
+READ8_HANDLER( TAITO8741_0_r );
+READ8_HANDLER( TAITO8741_1_r );
+READ8_HANDLER( TAITO8741_2_r );
+READ8_HANDLER( TAITO8741_3_r );
+
+/****************************************************************************
+ joshi Vollyball set.
+****************************************************************************/
+
+extern int josvolly_nmi_enable;
+
+void josvolly_8741_reset(void);
+WRITE8_HANDLER( josvolly_8741_0_w );
+WRITE8_HANDLER( josvolly_8741_1_w );
+READ8_HANDLER( josvolly_8741_0_r );
+READ8_HANDLER( josvolly_8741_1_r );
+
+#endif
diff --git a/src/mame/machine/taitosj.c b/src/mame/machine/taitosj.c
new file mode 100644
index 00000000000..0a33c0de9a6
--- /dev/null
+++ b/src/mame/machine/taitosj.c
@@ -0,0 +1,349 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m6805/m6805.h"
+
+
+#define DEBUG_MCU 1
+
+
+static UINT8 fromz80,toz80;
+static UINT8 zaccept,zready,busreq;
+static UINT8 portA_in,portA_out;
+
+static UINT8 spacecr_prot_value;
+static UINT8 protection_value;
+static UINT32 address;
+
+void taitosj_register_main_savestate(void);
+WRITE8_HANDLER( taitosj_bankswitch_w );
+
+MACHINE_START( taitosj )
+{
+ memory_configure_bank(1, 0, 1, memory_region(REGION_CPU1) + 0x6000, 0);
+ memory_configure_bank(1, 1, 1, memory_region(REGION_CPU1) + 0x10000, 0);
+
+ taitosj_register_main_savestate();
+
+ state_save_register_global(fromz80);
+ state_save_register_global(toz80);
+ state_save_register_global(zaccept);
+ state_save_register_global(zready);
+ state_save_register_global(busreq);
+
+ state_save_register_global(portA_in);
+ state_save_register_global(portA_out);
+ state_save_register_global(address);
+ state_save_register_global(spacecr_prot_value);
+ state_save_register_global(protection_value);
+}
+
+MACHINE_RESET( taitosj )
+{
+ /* set the default ROM bank (many games only have one bank and */
+ /* never write to the bank selector register) */
+ taitosj_bankswitch_w(0, 0);
+
+
+ zaccept = 1;
+ zready = 0;
+ busreq = 0;
+ if (machine->drv->cpu[2].type != CPU_DUMMY)
+ cpunum_set_input_line(2,0,CLEAR_LINE);
+
+ spacecr_prot_value = 0;
+}
+
+
+WRITE8_HANDLER( taitosj_bankswitch_w )
+{
+ coin_lockout_global_w(~data & 1);
+
+ if(data & 0x80) memory_set_bank(1, 1);
+ else memory_set_bank(1, 0);
+}
+
+
+
+/***************************************************************************
+
+ PROTECTION HANDLING
+
+ Some of the games running on this hardware are protected with a 68705 mcu.
+ It can either be on a daughter board containing Z80+68705+one ROM, which
+ replaces the Z80 on an unprotected main board; or it can be built-in on the
+ main board. The two are fucntionally equivalent.
+
+ The 68705 can read commands from the Z80, send back result codes, and has
+ direct access to the Z80 memory space. It can also trigger IRQs on the Z80.
+
+***************************************************************************/
+READ8_HANDLER( taitosj_fake_data_r )
+{
+#if DEBUG_MCU
+logerror("%04x: protection read\n",activecpu_get_pc());
+#endif
+ return 0;
+}
+
+WRITE8_HANDLER( taitosj_fake_data_w )
+{
+#if DEBUG_MCU
+logerror("%04x: protection write %02x\n",activecpu_get_pc(),data);
+#endif
+}
+
+READ8_HANDLER( taitosj_fake_status_r )
+{
+#if DEBUG_MCU
+logerror("%04x: protection status read\n",activecpu_get_pc());
+#endif
+ return 0xff;
+}
+
+
+/* timer callback : */
+READ8_HANDLER( taitosj_mcu_data_r )
+{
+#if DEBUG_MCU
+logerror("%04x: protection read %02x\n",activecpu_get_pc(),toz80);
+#endif
+ zaccept = 1;
+ return toz80;
+}
+
+/* timer callback : */
+static TIMER_CALLBACK( taitosj_mcu_real_data_w )
+{
+ zready = 1;
+ cpunum_set_input_line(2,0,ASSERT_LINE);
+ fromz80 = param;
+}
+
+WRITE8_HANDLER( taitosj_mcu_data_w )
+{
+#if DEBUG_MCU
+logerror("%04x: protection write %02x\n",activecpu_get_pc(),data);
+#endif
+ timer_call_after_resynch(data,taitosj_mcu_real_data_w);
+ /* temporarily boost the interleave to sync things up */
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(10));
+}
+
+READ8_HANDLER( taitosj_mcu_status_r )
+{
+ /* temporarily boost the interleave to sync things up */
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(10));
+
+ /* bit 0 = the 68705 has read data from the Z80 */
+ /* bit 1 = the 68705 has written data for the Z80 */
+ return ~((zready << 0) | (zaccept << 1));
+}
+
+READ8_HANDLER( taitosj_68705_portA_r )
+{
+#if DEBUG_MCU
+logerror("%04x: 68705 port A read %02x\n",activecpu_get_pc(),portA_in);
+#endif
+ return portA_in;
+}
+
+WRITE8_HANDLER( taitosj_68705_portA_w )
+{
+#if DEBUG_MCU
+logerror("%04x: 68705 port A write %02x\n",activecpu_get_pc(),data);
+#endif
+ portA_out = data;
+}
+
+
+
+/*
+ * Port B connections:
+ *
+ * all bits are logical 1 when read (+5V pullup)
+ *
+ * 0 W !68INTRQ
+ * 1 W !68LRD (enables latch which holds command from the Z80)
+ * 2 W !68LWR (loads the latch which holds data for the Z80, and sets a
+ * status bit so the Z80 knows there's data waiting)
+ * 3 W to Z80 !BUSRQ (aka !WAIT) pin
+ * 4 W !68WRITE (triggers write to main Z80 memory area and increases low
+ * 8 bits of the latched address)
+ * 5 W !68READ (triggers read from main Z80 memory area and increases low
+ * 8 bits of the latched address)
+ * 6 W !LAL (loads the latch which holds the low 8 bits of the address of
+ * the main Z80 memory location to access)
+ * 7 W !UAL (loads the latch which holds the high 8 bits of the address of
+ * the main Z80 memory location to access)
+ */
+
+READ8_HANDLER( taitosj_68705_portB_r )
+{
+ return 0xff;
+}
+
+/* timer callback : 68705 is going to read data from the Z80 */
+static TIMER_CALLBACK( taitosj_mcu_data_real_r )
+{
+ zready = 0;
+}
+
+/* timer callback : 68705 is writing data for the Z80 */
+static TIMER_CALLBACK( taitosj_mcu_status_real_w )
+{
+ toz80 = param;
+ zaccept = 0;
+}
+
+WRITE8_HANDLER( taitosj_68705_portB_w )
+{
+#if DEBUG_MCU
+logerror("%04x: 68705 port B write %02x\n",activecpu_get_pc(),data);
+#endif
+
+ if (~data & 0x01)
+ {
+#if DEBUG_MCU
+logerror("%04x: 68705 68INTRQ **NOT SUPPORTED**!\n",activecpu_get_pc());
+#endif
+ }
+ if (~data & 0x02)
+ {
+ /* 68705 is going to read data from the Z80 */
+ timer_call_after_resynch(0,taitosj_mcu_data_real_r);
+ cpunum_set_input_line(2,0,CLEAR_LINE);
+ portA_in = fromz80;
+#if DEBUG_MCU
+logerror("%04x: 68705 <- Z80 %02x\n",activecpu_get_pc(),portA_in);
+#endif
+ }
+ if (~data & 0x08)
+ busreq = 1;
+ else
+ busreq = 0;
+ if (~data & 0x04)
+ {
+#if DEBUG_MCU
+logerror("%04x: 68705 -> Z80 %02x\n",activecpu_get_pc(),portA_out);
+#endif
+ /* 68705 is writing data for the Z80 */
+ timer_call_after_resynch(portA_out,taitosj_mcu_status_real_w);
+ }
+ if (~data & 0x10)
+ {
+#if DEBUG_MCU
+logerror("%04x: 68705 write %02x to address %04x\n",activecpu_get_pc(),portA_out,address);
+#endif
+ memory_set_context(0);
+ program_write_byte(address, portA_out);
+ memory_set_context(2);
+
+ /* increase low 8 bits of latched address for burst writes */
+ address = (address & 0xff00) | ((address + 1) & 0xff);
+ }
+ if (~data & 0x20)
+ {
+ memory_set_context(0);
+ portA_in = program_read_byte(address);
+ memory_set_context(2);
+#if DEBUG_MCU
+logerror("%04x: 68705 read %02x from address %04x\n",activecpu_get_pc(),portA_in,address);
+#endif
+ }
+ if (~data & 0x40)
+ {
+#if DEBUG_MCU
+logerror("%04x: 68705 address low %02x\n",activecpu_get_pc(),portA_out);
+#endif
+ address = (address & 0xff00) | portA_out;
+ }
+ if (~data & 0x80)
+ {
+#if DEBUG_MCU
+logerror("%04x: 68705 address high %02x\n",activecpu_get_pc(),portA_out);
+#endif
+ address = (address & 0x00ff) | (portA_out << 8);
+ }
+}
+
+/*
+ * Port C connections:
+ *
+ * 0 R ZREADY (1 when the Z80 has written a command in the latch)
+ * 1 R ZACCEPT (1 when the Z80 has read data from the latch)
+ * 2 R from Z80 !BUSAK pin
+ * 3 R 68INTAK (goes 0 when the interrupt request done with 68INTRQ
+ * passes through)
+ */
+
+READ8_HANDLER( taitosj_68705_portC_r )
+{
+ int res;
+
+ res = (zready << 0) | (zaccept << 1) | ((busreq^1) << 2);
+#if DEBUG_MCU
+logerror("%04x: 68705 port C read %02x\n",activecpu_get_pc(),res);
+#endif
+ return res;
+}
+
+
+/* Space Cruiser protection (otherwise the game resets on the asteroids level) */
+
+READ8_HANDLER( spacecr_prot_r )
+{
+ int pc = activecpu_get_pc();
+
+ if( pc != 0x368A && pc != 0x36A6 )
+ logerror("Read protection from an unknown location: %04X\n",pc);
+
+ spacecr_prot_value ^= 0xff;
+
+ return spacecr_prot_value;
+}
+
+
+/* Alpine Ski protection crack routines */
+
+WRITE8_HANDLER( alpine_protection_w )
+{
+ switch (data)
+ {
+ case 0x05:
+ protection_value = 0x18;
+ break;
+ case 0x07:
+ case 0x0c:
+ case 0x0f:
+ protection_value = 0x00; /* not used as far as I can tell */
+ break;
+ case 0x16:
+ protection_value = 0x08;
+ break;
+ case 0x1d:
+ protection_value = 0x18;
+ break;
+ default:
+ protection_value = data; /* not used as far as I can tell */
+ break;
+ }
+}
+
+WRITE8_HANDLER( alpinea_bankswitch_w )
+{
+ taitosj_bankswitch_w(offset, data);
+ protection_value = data >> 2;
+}
+
+READ8_HANDLER( alpine_port_2_r )
+{
+ return input_port_2_r(offset) | protection_value;
+}
diff --git a/src/mame/machine/tatsumi.c b/src/mame/machine/tatsumi.c
new file mode 100644
index 00000000000..f261a96abf7
--- /dev/null
+++ b/src/mame/machine/tatsumi.c
@@ -0,0 +1,373 @@
+#include "driver.h"
+#include "tatsumi.h"
+#include "sound/2151intf.h"
+#include "sound/okim6295.h"
+
+/*static*/ UINT16 tatsumi_control_word=0;
+static UINT16 tatsumi_last_control=0;
+static UINT16 tatsumi_last_irq=0;
+static UINT8 apache3_adc;
+
+UINT16 *tatsumi_68k_ram;
+UINT8 *apache3_z80_ram;
+
+/******************************************************************************/
+
+void tatsumi_reset(void)
+{
+ tatsumi_last_irq=0;
+ tatsumi_last_control=0;
+ tatsumi_control_word=0;
+ apache3_adc=0;
+
+ state_save_register_global(tatsumi_last_irq);
+ state_save_register_global(tatsumi_last_control);
+ state_save_register_global(tatsumi_control_word);
+ state_save_register_global(apache3_adc);
+}
+
+/******************************************************************************/
+
+READ16_HANDLER( apache3_bank_r )
+{
+ return tatsumi_control_word;
+}
+
+WRITE16_HANDLER( apache3_bank_w )
+{
+ /*
+ 0x8000 - Set when accessing palette ram (not implemented, perhaps blank screen?)
+ 0x0080 - Set when accessing IO cpu RAM/ROM (implemented as halt cpu)
+ 0x0060 - IOP bank to access from main cpu (0x0 = RAM, 0x20 = lower ROM, 0x60 = upper ROM)
+ 0x0010 - Set when accessing OBJ cpu RAM/ROM (implemented as halt cpu)
+ 0x000f - OBJ bank to access from main cpu (0x8 = RAM, 0x0 to 0x7 = ROM)
+ */
+
+ COMBINE_DATA(&tatsumi_control_word);
+
+ if (tatsumi_control_word&0x7f00)
+ {
+ logerror("Unknown control Word: %04x\n",tatsumi_control_word);
+ cpunum_set_input_line(3, INPUT_LINE_HALT, CLEAR_LINE); // ?
+ }
+ if ((tatsumi_control_word&0x8)==0 && !(tatsumi_last_control&0x8))
+ cpunum_set_input_line(1, INPUT_LINE_IRQ4, ASSERT_LINE);
+
+ if (tatsumi_control_word&0x10)
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+ else
+ cpunum_set_input_line(1, INPUT_LINE_HALT, CLEAR_LINE);
+
+ if (tatsumi_control_word&0x80)
+ cpunum_set_input_line(2, INPUT_LINE_HALT, ASSERT_LINE);
+ else
+ cpunum_set_input_line(2, INPUT_LINE_HALT, CLEAR_LINE);
+
+ tatsumi_last_control=tatsumi_control_word;
+}
+
+WRITE16_HANDLER( apache3_irq_ack_w )
+{
+ cpunum_set_input_line(1, INPUT_LINE_IRQ4, CLEAR_LINE);
+
+ if ((data&2) && (tatsumi_last_irq&2)==0)
+ {
+ cpunum_set_input_line(3, INPUT_LINE_HALT, ASSERT_LINE);
+ }
+
+ if ((tatsumi_last_irq&2) && (data&2)==0)
+ {
+ cpunum_set_input_line(3, INPUT_LINE_HALT, CLEAR_LINE);
+ cpunum_set_input_line_and_vector(3, 0, HOLD_LINE, 0xc7 | 0x10);
+ }
+
+ tatsumi_last_irq=data;
+}
+
+READ16_HANDLER( apache3_v30_v20_r )
+{
+ UINT8 value;
+
+ /* Each V20 byte maps to a V30 word */
+ if ((tatsumi_control_word&0xe0)==0xe0)
+ offset+=0xf8000; /* Upper half */
+ else if ((tatsumi_control_word&0xe0)==0xc0)
+ offset+=0xf0000;
+ else if ((tatsumi_control_word&0xe0)==0x80)
+ offset+=0x00000; // main ram
+ else
+ logerror("%08x: unmapped read z80 rom %08x\n",activecpu_get_pc(),offset);
+
+ cpuintrf_push_context(2);
+ value = program_read_byte(offset);
+ cpuintrf_pop_context();
+ return value | 0xff00;
+}
+
+WRITE16_HANDLER( apache3_v30_v20_w )
+{
+ if ((tatsumi_control_word&0xe0)!=0x80)
+ logerror("%08x: write unmapped v30 rom %08x\n",activecpu_get_pc(),offset);
+
+ /* Only 8 bits of the V30 data bus are connected - ignore writes to the other half */
+ if (ACCESSING_LSB)
+ {
+ cpuintrf_push_context(2);
+ program_write_byte(offset, data&0xff);
+ cpuintrf_pop_context();
+ }
+}
+
+READ16_HANDLER(apache3_z80_r)
+{
+ return apache3_z80_ram[offset];
+}
+
+WRITE16_HANDLER(apache3_z80_w)
+{
+ apache3_z80_ram[offset]=data&0xff;
+}
+
+READ8_HANDLER( apache3_adc_r )
+{
+ if (apache3_adc==0)
+ return readinputport(1);
+ return readinputport(2);
+}
+
+WRITE8_HANDLER( apache3_adc_w )
+{
+ apache3_adc=offset;
+}
+
+UINT16 apache3_a0000[16]; // TODO
+static int a3counter=0; // TODO
+
+WRITE16_HANDLER( apache3_a0000_w )
+{
+ if (a3counter>15) // TODO
+ return;
+ apache3_a0000[a3counter++]=data;
+}
+
+/******************************************************************************/
+
+READ16_HANDLER( roundup_v30_z80_r )
+{
+ UINT8 value;
+
+ /* Each Z80 byte maps to a V30 word */
+ if (tatsumi_control_word&0x20)
+ offset+=0x8000; /* Upper half */
+
+ cpuintrf_push_context(2);
+ value = program_read_byte(offset);
+ cpuintrf_pop_context();
+ return value | 0xff00;
+}
+
+WRITE16_HANDLER( roundup_v30_z80_w )
+{
+ /* Only 8 bits of the V30 data bus are connected - ignore writes to the other half */
+ if (ACCESSING_LSB)
+ {
+ if (tatsumi_control_word&0x20)
+ offset+=0x8000; /* Upper half of Z80 address space */
+
+ cpuintrf_push_context(2);
+ program_write_byte(offset, data&0xff);
+ cpuintrf_pop_context();
+ }
+}
+
+
+WRITE16_HANDLER( roundup5_control_w )
+{
+ COMBINE_DATA(&tatsumi_control_word);
+
+ if (tatsumi_control_word&0x10)
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+ else
+ cpunum_set_input_line(1, INPUT_LINE_HALT, CLEAR_LINE);
+
+ if (tatsumi_control_word&0x4)
+ cpunum_set_input_line(2, INPUT_LINE_HALT, ASSERT_LINE);
+ else
+ cpunum_set_input_line(2, INPUT_LINE_HALT, CLEAR_LINE);
+
+// if (offset==1 && (tatsumi_control_w&0xfeff)!=(last_bank&0xfeff))
+// logerror("%08x: Changed bank to %04x (%d)\n",activecpu_get_pc(),tatsumi_control_w,offset);
+
+//todo - watchdog
+
+ /* Bank:
+
+ 0x0017 : OBJ banks
+ 0x0018 : 68000 RAM mask 0x0380 used to save bits when writing
+ 0x0c10 : 68000 ROM
+
+ 0x0040 : Z80 rom (lower half) mapped to 0x10000
+ 0x0060 : Z80 rom (upper half) mapped to 0x10000
+
+ 0x0100 : watchdog.
+
+ 0x0c00 : vram bank (bits 0x7000 also set when writing vram)
+
+ 0x8000 : set whenever writing to palette ram?
+
+ Changed bank to 0060 (0)
+ */
+
+ if ((tatsumi_control_word&0x8)==0 && !(tatsumi_last_control&0x8))
+ cpunum_set_input_line(1, INPUT_LINE_IRQ4, ASSERT_LINE);
+// if (tatsumi_control_w&0x200)
+// cpu_set_reset_line(1, CLEAR_LINE);
+// else
+// cpu_set_reset_line(1, ASSERT_LINE);
+
+// if ((tatsumi_control_w&0x200) && (last_bank&0x200)==0)
+// logerror("68k irq\n");
+// if ((tatsumi_control_w&0x200)==0 && (last_bank&0x200)==0x200)
+// logerror("68k reset\n");
+
+ if (tatsumi_control_word==0x3a00) {
+// cpu_set_reset_line(1, CLEAR_LINE);
+ // logerror("68k on\n");
+
+ }
+
+ tatsumi_last_control=tatsumi_control_word;
+}
+
+WRITE16_HANDLER( roundup5_d0000_w )
+{
+ COMBINE_DATA(&roundup5_d0000_ram[offset]);
+// logerror("d_68k_d0000_w %06x %04x\n",activecpu_get_pc(),data);
+}
+
+WRITE16_HANDLER( roundup5_e0000_w )
+{
+ /* Bit 0x10 is road bank select,
+ Bit 0x100 is used, but unknown
+ */
+
+ COMBINE_DATA(&roundup5_e0000_ram[offset]);
+ cpunum_set_input_line(1, INPUT_LINE_IRQ4, CLEAR_LINE); // guess, probably wrong
+
+// logerror("d_68k_e0000_w %06x %04x\n",activecpu_get_pc(),data);
+}
+
+/******************************************************************************/
+
+READ16_HANDLER(cyclwarr_control_r)
+{
+// logerror("%08x: control_r\n",activecpu_get_pc());
+ return tatsumi_control_word;
+}
+
+WRITE16_HANDLER(cyclwarr_control_w)
+{
+ COMBINE_DATA(&tatsumi_control_word);
+
+// if ((tatsumi_control_word&0xfe)!=(tatsumi_last_control&0xfe))
+// logerror("%08x: control_w %04x\n",activecpu_get_pc(),data);
+
+/*
+
+0x1 - watchdog
+0x4 - cpu bus lock
+
+
+
+*/
+
+ if ((tatsumi_control_word&4)==4 && (tatsumi_last_control&4)==0) {
+// logerror("68k 2 halt\n");
+ cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
+ }
+
+ if ((tatsumi_control_word&4)==0 && (tatsumi_last_control&4)==4) {
+// logerror("68k 2 irq go\n");
+ cpunum_set_input_line(1, INPUT_LINE_HALT, CLEAR_LINE);
+ }
+
+
+ // hack
+ if (activecpu_get_pc()==0x2c3c34) {
+// cpu_set_reset_line(1, CLEAR_LINE);
+ // logerror("hack 68k2 on\n");
+ }
+
+ tatsumi_last_control=tatsumi_control_word;
+}
+
+/******************************************************************************/
+
+READ16_HANDLER( tatsumi_v30_68000_r )
+{
+ const UINT16* rom=(UINT16*)memory_region(REGION_CPU2);
+
+logerror("%05X:68000_r(%04X),cw=%04X\n", activecpu_get_pc(), offset*2, tatsumi_control_word);
+ /* Read from 68k RAM */
+ if ((tatsumi_control_word&0x1f)==0x18)
+ {
+ // hack to make roundup 5 boot
+ if (activecpu_get_pc()==0xec575)
+ {
+ UINT8 *dst = memory_region(REGION_CPU1);
+ dst[BYTE_XOR_LE(0xec57a)]=0x46;
+ dst[BYTE_XOR_LE(0xec57b)]=0x46;
+
+ dst[BYTE_XOR_LE(0xfc520)]=0x46; //code that stops cpu after coin counter goes mad..
+ dst[BYTE_XOR_LE(0xfc521)]=0x46;
+ dst[BYTE_XOR_LE(0xfc522)]=0x46;
+ dst[BYTE_XOR_LE(0xfc523)]=0x46;
+ dst[BYTE_XOR_LE(0xfc524)]=0x46;
+ dst[BYTE_XOR_LE(0xfc525)]=0x46;
+ }
+
+ return tatsumi_68k_ram[offset & 0x1fff];
+ }
+
+ /* Read from 68k ROM */
+ offset+=(tatsumi_control_word&0x7)*0x8000;
+
+ return rom[offset];
+}
+
+WRITE16_HANDLER( tatsumi_v30_68000_w )
+{
+ if ((tatsumi_control_word&0x1f)!=0x18)
+ logerror("68k write in bank %05x\n",tatsumi_control_word);
+
+ COMBINE_DATA(&tatsumi_68k_ram[offset]);
+}
+
+/***********************************************************************************/
+
+// Todo: Current YM2151 doesn't seem to raise the busy flag quickly enough for the
+// self-test in Tatsumi games. Needs fixed, but hack it here for now.
+READ8_HANDLER(tatsumi_hack_ym2151_r)
+{
+ int r=YM2151_status_port_0_r(0);
+
+ if (activecpu_get_pc()==0x2aca || activecpu_get_pc()==0x29fe
+ || activecpu_get_pc()==0xf9721)
+ return 0x80;
+ return r;
+}
+
+// Todo: Tatsumi self-test fails if OKI doesn't respond (when sound off).
+// Mame really should emulate the OKI status reads even with Mame sound off.
+READ8_HANDLER(tatsumi_hack_oki_r)
+{
+ int r=OKIM6295_status_0_r(0);
+
+ if (activecpu_get_pc()==0x2b70 || activecpu_get_pc()==0x2bb5
+ || activecpu_get_pc()==0x2acc
+ || activecpu_get_pc()==0xf9881)
+ return 0xf;
+ if (activecpu_get_pc()==0x2ba3 || activecpu_get_pc()==0x2a9b || activecpu_get_pc()==0x2adc)
+ return 0;
+ return r;
+}
diff --git a/src/mame/machine/theglobp.c b/src/mame/machine/theglobp.c
new file mode 100644
index 00000000000..429df9c5f66
--- /dev/null
+++ b/src/mame/machine/theglobp.c
@@ -0,0 +1,259 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+ The Glob protection description:
+
+ The Glob is designed to run on modified Pacman hardware. It contains
+ two graphics ROMs at 5E and 5F, but contains code ROMs on a daughterboard
+ similar in concept to Ms. Pacman. However, these code ROMs are decrypted
+ through additional circuitry. The daughterboard was encased in epoxy.
+
+ Here's a description of the protection as best as I can give it.
+
+ 1) The decrypted D0 bit fed to the CPU is simply an inversion of the
+ D5 bit from the code ROMs.
+ 2) The decrypted D1 bit fed to the CPU is simply an inversion of the
+ D2 bit from the code ROMs.
+ 3) The other 6 data bits are decrypted by a 10H8 PAL. The PAL also
+ takes as input a 4-bit counter. The counter is incremented and
+ decremented as follows:
+ - the Z-80 command IN($xx) where xx is an odd number decrements the
+ counter; an even number increments the counter.
+ Ex: IN($64) would increment the counter, IN($6B) would decrement
+ the counter.
+ 4) The PAL output also contains the two ROM enable lines used to enable
+ the two encrypted code ROMs. As long as the system is working
+ correctly, these ROMs will always be enabled.
+
+ As it so happens, only four counter values are ever used, which is
+ fortunate because the PAL only contains signals to enable the ROMs for
+ those four counter values. The valid counter values are $8, $9, $A, and
+ $B. The counter's intial value is $A, which is set by jumpers on the
+ daughterboard. Following is a description of the resulting decryptions
+ for these four counter states.
+
+ COUNTER ENCRYPTED DECRYPTED
+ VALUE VALUE
+
+ DDDDDDDD DDDDDDDD
+ 76543210 76543210
+
+ Counter = 8: abcdefgh EAhBDgFC
+ Counter = 9: abcdefgh FAgeDBFC
+ Counter = A: abcdefgh EHDBagFC
+ Counter = B: abcdefgh GHDEaBFC
+
+ In the above diagram, capital letters represent inverted bits. Notice
+ that bits D2 and D5 are the same independent of counter state, this is
+ because these bits are not decrypted by the PAL.
+
+
+ In the code below, all four of these decryption patterns are used to
+ decrypt the entire code ROMs before execution. This is done for speed,
+ since we can then just bankswitch between the decrypted code sets on
+ each IN($xx) command, as opposed to dynamically decrypting every byte.
+
+ - Mike Balfour (mab22@po.cwru.edu)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "includes/pacman.h"
+
+static INT8 counter=0;
+
+
+static void theglobp_decrypt_rom_8(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* Direct inversion */
+ newbyte = (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ /* PAL */
+ newbyte |= (oldbyte & 0x01) << 5;
+ newbyte |= (oldbyte & 0x02) << 1;
+ newbyte |= (inverted_oldbyte & 0x08) << 4;
+ newbyte |= (inverted_oldbyte & 0x10) >> 1;
+ newbyte |= (inverted_oldbyte & 0x40) >> 2;
+ newbyte |= (inverted_oldbyte & 0x80) >> 1;
+
+ RAM[mem + 0x10000] = newbyte;
+ }
+
+ return;
+}
+
+
+static void theglobp_decrypt_rom_9(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* Direct inversion */
+ newbyte = (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ /* PAL */
+ newbyte |= (oldbyte & 0x01) << 5;
+ newbyte |= (inverted_oldbyte & 0x02) << 6;
+ newbyte |= (oldbyte & 0x08) << 1;
+ newbyte |= (inverted_oldbyte & 0x10) >> 1;
+ newbyte |= (inverted_oldbyte & 0x40) >> 4;
+ newbyte |= (inverted_oldbyte & 0x80) >> 1;
+
+ RAM[mem + 0x14000] = newbyte;
+ }
+
+ return;
+}
+
+static void theglobp_decrypt_rom_A(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* Direct inversion */
+ newbyte = (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ /* PAL */
+ newbyte |= (inverted_oldbyte & 0x01) << 6;
+ newbyte |= (oldbyte & 0x02) << 1;
+ newbyte |= (inverted_oldbyte & 0x08) << 4;
+ newbyte |= (inverted_oldbyte & 0x10) << 1;
+ newbyte |= (inverted_oldbyte & 0x40) >> 2;
+ newbyte |= (oldbyte & 0x80) >> 4;
+
+ RAM[mem + 0x18000] = newbyte;
+ }
+
+ return;
+}
+
+static void theglobp_decrypt_rom_B(void)
+{
+ int oldbyte,inverted_oldbyte,newbyte;
+ int mem;
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+
+ for (mem=0;mem<0x4000;mem++)
+ {
+ oldbyte = RAM[mem];
+ inverted_oldbyte = ~oldbyte;
+
+ /* Note: D2 is inverted and connected to D1, D5 is inverted and
+ connected to D0. The other six data bits are converted by a
+ PAL10H8 driven by the counter. */
+ newbyte = 0;
+
+ /* Direct inversion */
+ newbyte = (inverted_oldbyte & 0x04) >> 1;
+ newbyte |= (inverted_oldbyte & 0x20) >> 5;
+ /* PAL */
+ newbyte |= (inverted_oldbyte & 0x01) << 6;
+ newbyte |= (inverted_oldbyte & 0x02) << 6;
+ newbyte |= (oldbyte & 0x08) << 1;
+ newbyte |= (inverted_oldbyte & 0x10) << 1;
+ newbyte |= (inverted_oldbyte & 0x40) >> 4;
+ newbyte |= (oldbyte & 0x80) >> 4;
+
+ RAM[mem + 0x1C000] = newbyte;
+ }
+
+ return;
+}
+
+
+READ8_HANDLER( theglobp_decrypt_rom )
+{
+ if (offset & 0x01)
+ {
+ counter = counter - 1;
+ if (counter < 0)
+ counter = 0x0F;
+ }
+ else
+ {
+ counter = (counter + 1) & 0x0F;
+ }
+
+ switch(counter)
+ {
+ case 0x08: memory_set_bank (1, 0); break;
+ case 0x09: memory_set_bank (1, 1); break;
+ case 0x0A: memory_set_bank (1, 2); break;
+ case 0x0B: memory_set_bank (1, 3); break;
+ default:
+ logerror("Invalid counter = %02X\n",counter);
+ break;
+ }
+
+ return 0;
+}
+
+
+MACHINE_RESET( theglobp )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ /* While the PAL supports up to 16 decryption methods, only four
+ are actually used in the PAL. Therefore, we'll take a little
+ memory overhead and decrypt the ROMs using each method in advance. */
+ theglobp_decrypt_rom_8();
+ theglobp_decrypt_rom_9();
+ theglobp_decrypt_rom_A();
+ theglobp_decrypt_rom_B();
+
+ /* The initial state of the counter is 0x0A */
+ counter = 0x0A;
+ memory_configure_bank(1, 0, 4, &RAM[0x10000], 0x4000);
+ memory_set_bank(1, 2);
+
+ state_save_register_global(counter);
+}
diff --git a/src/mame/machine/ticket.c b/src/mame/machine/ticket.c
new file mode 100644
index 00000000000..caf30035fe2
--- /dev/null
+++ b/src/mame/machine/ticket.c
@@ -0,0 +1,190 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate a prototypical ticket dispenser hardware.
+
+ Right now, this is an *extremely* basic ticket dispenser.
+ TODO: Active Bit may not be Bit 7 in all applications.
+ Add a ticket dispenser interface instead of passing a bunch
+ of arguments to ticket_dispenser_init.
+***************************************************************************/
+
+#include "driver.h"
+#include "machine/ticket.h"
+
+/*#define DEBUG_TICKET*/
+
+#define MAX_DISPENSERS 2
+
+struct ticket_state
+{
+ UINT8 status;
+ UINT8 power;
+ emu_timer *timer;
+};
+
+static int active_bit = 0x80;
+static int time_msec;
+static int motoron;
+static int ticketdispensed;
+static int ticketnotdispensed;
+
+static struct ticket_state dispenser[MAX_DISPENSERS];
+
+static TIMER_CALLBACK_PTR( ticket_dispenser_toggle );
+
+
+/***************************************************************************
+ ticket_dispenser_init
+
+***************************************************************************/
+void ticket_dispenser_init(int msec, int motoronhigh, int statusactivehigh)
+{
+ int i;
+
+ time_msec = msec;
+ motoron = motoronhigh ? active_bit : 0;
+ ticketdispensed = statusactivehigh ? active_bit : 0;
+ ticketnotdispensed = ticketdispensed ^ active_bit;
+ dispensed_tickets = 0;
+
+ for (i = 0; i < MAX_DISPENSERS; i++)
+ {
+ dispenser[i].status = ticketnotdispensed;
+ dispenser[i].power = 0x00;
+ dispenser[i].timer = timer_alloc_ptr(ticket_dispenser_toggle, &dispenser[i]);
+
+ state_save_register_item("ticket", i, dispenser[i].status);
+ state_save_register_item("ticket", i, dispenser[i].power);
+ }
+}
+
+/***************************************************************************
+ ticket_dispenser_r
+***************************************************************************/
+READ8_HANDLER( ticket_dispenser_r )
+{
+ return ticket_dispenser_0_r(offset);
+}
+
+READ8_HANDLER( ticket_dispenser_0_r )
+{
+#ifdef DEBUG_TICKET
+ logerror("PC: %04X Ticket Status Read = %02X\n", activecpu_get_pc(), status);
+#endif
+ return dispenser[0].status;
+}
+
+READ8_HANDLER( ticket_dispenser_1_r )
+{
+#ifdef DEBUG_TICKET
+ logerror("PC: %04X Ticket Status Read = %02X\n", activecpu_get_pc(), status);
+#endif
+ return dispenser[1].status;
+}
+
+/***************************************************************************
+ ticket_dispenser_w
+***************************************************************************/
+WRITE8_HANDLER( ticket_dispenser_w )
+{
+ ticket_dispenser_0_w(offset, data);
+}
+
+WRITE8_HANDLER( ticket_dispenser_0_w )
+{
+ /* On an activate signal, start dispensing! */
+ if ((data & active_bit) == motoron)
+ {
+ if (!dispenser[0].power)
+ {
+#ifdef DEBUG_TICKET
+ logerror("PC: %04X Ticket Power On\n", activecpu_get_pc());
+#endif
+ timer_adjust_ptr(dispenser[0].timer, ATTOTIME_IN_MSEC(time_msec), attotime_zero);
+ dispenser[0].power = 1;
+
+ dispenser[0].status = ticketnotdispensed;
+ }
+ }
+ else
+ {
+ if (dispenser[0].power)
+ {
+#ifdef DEBUG_TICKET
+ logerror("PC: %04X Ticket Power Off\n", activecpu_get_pc());
+#endif
+ timer_adjust_ptr(dispenser[0].timer, attotime_never, attotime_never);
+ set_led_status(2,0);
+ dispenser[0].power = 0;
+ }
+ }
+}
+
+WRITE8_HANDLER( ticket_dispenser_1_w )
+{
+ /* On an activate signal, start dispensing! */
+ if ((data & active_bit) == motoron)
+ {
+ if (!dispenser[1].power)
+ {
+#ifdef DEBUG_TICKET
+ logerror("PC: %04X Ticket Power On\n", activecpu_get_pc());
+#endif
+ timer_adjust_ptr(dispenser[1].timer, ATTOTIME_IN_MSEC(time_msec), attotime_zero);
+ dispenser[1].power = 1;
+
+ dispenser[1].status = ticketnotdispensed;
+ }
+ }
+ else
+ {
+ if (dispenser[1].power)
+ {
+#ifdef DEBUG_TICKET
+ logerror("PC: %04X Ticket Power Off\n", activecpu_get_pc());
+#endif
+ timer_adjust_ptr(dispenser[1].timer, attotime_never, attotime_never);
+ set_led_status(2,0);
+ dispenser[1].power = 0;
+ }
+ }
+}
+
+
+/***************************************************************************
+ ticket_dispenser_toggle
+
+ How I think this works:
+ When a ticket dispenses, there is N milliseconds of status = high,
+ and N milliseconds of status = low (a wait cycle?).
+***************************************************************************/
+static TIMER_CALLBACK_PTR( ticket_dispenser_toggle )
+{
+ struct ticket_state *dispenser = param;
+
+ /* If we still have power, keep toggling ticket states. */
+ if (dispenser->power)
+ {
+ dispenser->status ^= active_bit;
+#ifdef DEBUG_TICKET
+ logerror("Ticket Status Changed to %02X\n", status);
+#endif
+ timer_adjust_ptr(dispenser->timer, ATTOTIME_IN_MSEC(time_msec), attotime_zero);
+ }
+
+ if (dispenser->status == ticketdispensed)
+ {
+ set_led_status(2,1);
+ dispensed_tickets++;
+
+#ifdef DEBUG_TICKET
+ logerror("Ticket Dispensed\n");
+#endif
+ }
+ else
+ {
+ set_led_status(2,0);
+ }
+}
diff --git a/src/mame/machine/ticket.h b/src/mame/machine/ticket.h
new file mode 100644
index 00000000000..152263c40e6
--- /dev/null
+++ b/src/mame/machine/ticket.h
@@ -0,0 +1,38 @@
+/***************************************************************************
+
+ Function prototypes and constants for the ticket dispenser emulator
+
+***************************************************************************/
+
+
+#define TICKET_MOTOR_ACTIVE_LOW 0 /* Ticket motor is triggered by D7=0 */
+#define TICKET_MOTOR_ACTIVE_HIGH 1 /* Ticket motor is triggered by D7=1 */
+
+#define TICKET_STATUS_ACTIVE_LOW 0 /* Ticket is done dispensing when D7=0 */
+#define TICKET_STATUS_ACTIVE_HIGH 1 /* Ticket is done dispensing when D7=1 */
+
+/***************************************************************************
+ ticket_dispenser_init
+
+ msec = how many milliseconds it takes to dispense a ticket
+ activehigh = see constants above
+
+***************************************************************************/
+void ticket_dispenser_init(int msec, int motoractivehigh, int statusactivehigh);
+
+
+/***************************************************************************
+ ticket_dispenser_r
+***************************************************************************/
+READ8_HANDLER( ticket_dispenser_r );
+READ8_HANDLER( ticket_dispenser_0_r );
+READ8_HANDLER( ticket_dispenser_1_r );
+
+
+/***************************************************************************
+ ticket_dispenser_w
+***************************************************************************/
+WRITE8_HANDLER( ticket_dispenser_w );
+WRITE8_HANDLER( ticket_dispenser_0_w );
+WRITE8_HANDLER( ticket_dispenser_1_w );
+
diff --git a/src/mame/machine/tnzs.c b/src/mame/machine/tnzs.c
new file mode 100644
index 00000000000..bc86eeccebf
--- /dev/null
+++ b/src/mame/machine/tnzs.c
@@ -0,0 +1,782 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+ The I8742 MCU takes care of handling the coin inputs and the tilt switch.
+ To simulate this, we read the status in the interrupt handler for the main
+ CPU and update the counters appropriately. We also must take care of
+ handling the coin/credit settings ourselves.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "cpu/i8x41/i8x41.h"
+#include "includes/tnzs.h"
+
+static int mcu_type;
+static int tnzs_input_select;
+
+enum
+{
+ MCU_NONE_INSECTX,
+ MCU_NONE_KAGEKI,
+ MCU_NONE_TNZSB,
+ MCU_NONE_KABUKIZ,
+ MCU_EXTRMATN,
+ MCU_ARKANOID,
+ MCU_PLUMPOP,
+ MCU_DRTOPPEL,
+ MCU_CHUKATAI,
+ MCU_TNZS
+};
+
+static int mcu_initializing,mcu_coinage_init,mcu_command,mcu_readcredits;
+static int mcu_reportcoin;
+static UINT8 mcu_coinage[4];
+static UINT8 mcu_coinsA,mcu_coinsB,mcu_credits;
+
+
+
+static READ8_HANDLER( mcu_tnzs_r )
+{
+ UINT8 data;
+
+ if (offset == 0)
+ {
+ data = cpunum_get_reg(2, I8X41_DATA);
+ cpu_yield();
+ }
+ else
+ {
+ data = cpunum_get_reg(2, I8X41_STAT);
+ cpu_yield();
+ }
+
+// logerror("PC %04x: read %02x from mcu $c00%01x\n", activecpu_get_previouspc(), data, offset);
+
+ return data;
+}
+
+static WRITE8_HANDLER( mcu_tnzs_w )
+{
+// logerror("PC %04x: write %02x to mcu $c00%01x\n", activecpu_get_previouspc(), data, offset);
+
+ if (offset == 0)
+ cpunum_set_reg(2, I8X41_DATA, data);
+ else
+ cpunum_set_reg(2, I8X41_CMND, data);
+}
+
+
+READ8_HANDLER( tnzs_port1_r )
+{
+ int data = 0;
+
+ switch (tnzs_input_select & 0x0f)
+ {
+ case 0x0a: data = input_port_4_r(0); break;
+ case 0x0c: data = input_port_2_r(0); break;
+ case 0x0d: data = input_port_3_r(0); break;
+ default: data = 0xff; break;
+ }
+
+// logerror("I8742:%04x Read %02x from port 1\n", activecpu_get_previouspc(), data);
+
+ return data;
+}
+
+READ8_HANDLER( tnzs_port2_r )
+{
+ int data = input_port_4_r(0);
+
+// logerror("I8742:%04x Read %02x from port 2\n", activecpu_get_previouspc(), data);
+
+ return data;
+}
+
+WRITE8_HANDLER( tnzs_port2_w )
+{
+// logerror("I8742:%04x Write %02x to port 2\n", activecpu_get_previouspc(), data);
+
+ coin_lockout_w( 0, (data & 0x40) );
+ coin_lockout_w( 1, (data & 0x80) );
+ coin_counter_w( 0, (~data & 0x10) );
+ coin_counter_w( 1, (~data & 0x20) );
+
+ tnzs_input_select = data;
+}
+
+
+
+READ8_HANDLER( arknoid2_sh_f000_r )
+{
+ int val;
+
+// logerror("PC %04x: read input %04x\n", activecpu_get_pc(), 0xf000 + offset);
+
+ val = readinputport(7 + offset/2);
+ if (offset & 1)
+ {
+ return ((val >> 8) & 0xff);
+ }
+ else
+ {
+ return val & 0xff;
+ }
+}
+
+
+static void mcu_reset(void)
+{
+ mcu_initializing = 3;
+ mcu_coinage_init = 0;
+ mcu_coinage[0] = 1;
+ mcu_coinage[1] = 1;
+ mcu_coinage[2] = 1;
+ mcu_coinage[3] = 1;
+ mcu_coinsA = 0;
+ mcu_coinsB = 0;
+ mcu_credits = 0;
+ mcu_reportcoin = 0;
+ mcu_command = 0;
+}
+
+static void mcu_handle_coins(int coin)
+{
+ static int insertcoin;
+
+ /* The coin inputs and coin counters are managed by the i8742 mcu. */
+ /* Here we simulate it. */
+ /* Credits are limited to 9, so more coins should be rejected */
+ /* Coin/Play settings must also be taken into consideration */
+
+ if (coin & 0x08) /* tilt */
+ mcu_reportcoin = coin;
+ else if (coin && coin != insertcoin)
+ {
+ if (coin & 0x01) /* coin A */
+ {
+// logerror("Coin dropped into slot A\n");
+ coin_counter_w(0,1); coin_counter_w(0,0); /* Count slot A */
+ mcu_coinsA++;
+ if (mcu_coinsA >= mcu_coinage[0])
+ {
+ mcu_coinsA -= mcu_coinage[0];
+ mcu_credits += mcu_coinage[1];
+ if (mcu_credits >= 9)
+ {
+ mcu_credits = 9;
+ coin_lockout_global_w(1); /* Lock all coin slots */
+ }
+ else
+ {
+ coin_lockout_global_w(0); /* Unlock all coin slots */
+ }
+ }
+ }
+ if (coin & 0x02) /* coin B */
+ {
+// logerror("Coin dropped into slot B\n");
+ coin_counter_w(1,1); coin_counter_w(1,0); /* Count slot B */
+ mcu_coinsB++;
+ if (mcu_coinsB >= mcu_coinage[2])
+ {
+ mcu_coinsB -= mcu_coinage[2];
+ mcu_credits += mcu_coinage[3];
+ if (mcu_credits >= 9)
+ {
+ mcu_credits = 9;
+ coin_lockout_global_w(1); /* Lock all coin slots */
+ }
+ else
+ {
+ coin_lockout_global_w(0); /* Unlock all coin slots */
+ }
+ }
+ }
+ if (coin & 0x04) /* service */
+ {
+// logerror("Coin dropped into service slot C\n");
+ mcu_credits++;
+ }
+ mcu_reportcoin = coin;
+ }
+ else
+ {
+ if (mcu_credits < 9)
+ coin_lockout_global_w(0); /* Unlock all coin slots */
+ mcu_reportcoin = 0;
+ }
+ insertcoin = coin;
+}
+
+
+
+static READ8_HANDLER( mcu_arknoid2_r )
+{
+ static const char mcu_startup[] = "\x55\xaa\x5a";
+
+// logerror("PC %04x: read mcu %04x\n", activecpu_get_pc(), 0xc000 + offset);
+
+ if (offset == 0)
+ {
+ /* if the mcu has just been reset, return startup code */
+ if (mcu_initializing)
+ {
+ mcu_initializing--;
+ return mcu_startup[2 - mcu_initializing];
+ }
+
+ switch (mcu_command)
+ {
+ case 0x41:
+ return mcu_credits;
+
+ case 0xc1:
+ /* Read the credit counter or the inputs */
+ if (mcu_readcredits == 0)
+ {
+ mcu_readcredits = 1;
+ if (mcu_reportcoin & 0x08)
+ {
+ mcu_initializing = 3;
+ return 0xee; /* tilt */
+ }
+ else return mcu_credits;
+ }
+ else return readinputport(2); /* buttons */
+
+ default:
+ logerror("error, unknown mcu command\n");
+ /* should not happen */
+ return 0xff;
+ break;
+ }
+ }
+ else
+ {
+ /*
+ status bits:
+ 0 = mcu is ready to send data (read from c000)
+ 1 = mcu has read data (from c000)
+ 2 = unused
+ 3 = unused
+ 4-7 = coin code
+ 0 = nothing
+ 1,2,3 = coin switch pressed
+ e = tilt
+ */
+ if (mcu_reportcoin & 0x08) return 0xe1; /* tilt */
+ if (mcu_reportcoin & 0x01) return 0x11; /* coin 1 (will trigger "coin inserted" sound) */
+ if (mcu_reportcoin & 0x02) return 0x21; /* coin 2 (will trigger "coin inserted" sound) */
+ if (mcu_reportcoin & 0x04) return 0x31; /* coin 3 (will trigger "coin inserted" sound) */
+ return 0x01;
+ }
+}
+
+static WRITE8_HANDLER( mcu_arknoid2_w )
+{
+ if (offset == 0)
+ {
+// logerror("PC %04x: write %02x to mcu %04x\n", activecpu_get_pc(), data, 0xc000 + offset);
+ if (mcu_command == 0x41)
+ {
+ mcu_credits = (mcu_credits + data) & 0xff;
+ }
+ }
+ else
+ {
+ /*
+ 0xc1: read number of credits, then buttons
+ 0x54+0x41: add value to number of credits
+ 0x15: sub 1 credit (when "Continue Play" only)
+ 0x84: coin 1 lockout (issued only in test mode)
+ 0x88: coin 2 lockout (issued only in test mode)
+ 0x80: release coin lockout (issued only in test mode)
+ during initialization, a sequence of 4 bytes sets coin/credit settings
+ */
+// logerror("PC %04x: write %02x to mcu %04x\n", activecpu_get_pc(), data, 0xc000 + offset);
+
+ if (mcu_initializing)
+ {
+ /* set up coin/credit settings */
+ mcu_coinage[mcu_coinage_init++] = data;
+ if (mcu_coinage_init == 4) mcu_coinage_init = 0; /* must not happen */
+ }
+
+ if (data == 0xc1)
+ mcu_readcredits = 0; /* reset input port number */
+
+ if (data == 0x15)
+ {
+ mcu_credits = (mcu_credits - 1) & 0xff;
+ if (mcu_credits == 0xff) mcu_credits = 0;
+ }
+ mcu_command = data;
+ }
+}
+
+
+static READ8_HANDLER( mcu_extrmatn_r )
+{
+ static const char mcu_startup[] = "\x5a\xa5\x55";
+
+// logerror("PC %04x: read mcu %04x\n", activecpu_get_pc(), 0xc000 + offset);
+
+ if (offset == 0)
+ {
+ /* if the mcu has just been reset, return startup code */
+ if (mcu_initializing)
+ {
+ mcu_initializing--;
+ return mcu_startup[2 - mcu_initializing];
+ }
+
+ switch (mcu_command)
+ {
+ case 0x01:
+ return readinputport(2) ^ 0xff; /* player 1 joystick + buttons */
+
+ case 0x02:
+ return readinputport(3) ^ 0xff; /* player 2 joystick + buttons */
+
+ case 0x1a:
+ return (readinputport(5) | (readinputport(6) << 1));
+
+ case 0x21:
+ return readinputport(4) & 0x0f;
+
+ case 0x41:
+ return mcu_credits;
+
+ case 0xa0:
+ /* Read the credit counter */
+ if (mcu_reportcoin & 0x08)
+ {
+ mcu_initializing = 3;
+ return 0xee; /* tilt */
+ }
+ else return mcu_credits;
+
+ case 0xa1:
+ /* Read the credit counter or the inputs */
+ if (mcu_readcredits == 0)
+ {
+ mcu_readcredits = 1;
+ if (mcu_reportcoin & 0x08)
+ {
+ mcu_initializing = 3;
+ return 0xee; /* tilt */
+// return 0x64; /* theres a reset input somewhere */
+ }
+ else return mcu_credits;
+ }
+ /* buttons */
+ else return ((readinputport(2) & 0xf0) | (readinputport(3) >> 4)) ^ 0xff;
+
+ default:
+ logerror("error, unknown mcu command\n");
+ /* should not happen */
+ return 0xff;
+ break;
+ }
+ }
+ else
+ {
+ /*
+ status bits:
+ 0 = mcu is ready to send data (read from c000)
+ 1 = mcu has read data (from c000)
+ 2 = unused
+ 3 = unused
+ 4-7 = coin code
+ 0 = nothing
+ 1,2,3 = coin switch pressed
+ e = tilt
+ */
+ if (mcu_reportcoin & 0x08) return 0xe1; /* tilt */
+ if (mcu_reportcoin & 0x01) return 0x11; /* coin 1 (will trigger "coin inserted" sound) */
+ if (mcu_reportcoin & 0x02) return 0x21; /* coin 2 (will trigger "coin inserted" sound) */
+ if (mcu_reportcoin & 0x04) return 0x31; /* coin 3 (will trigger "coin inserted" sound) */
+ return 0x01;
+ }
+}
+
+static WRITE8_HANDLER( mcu_extrmatn_w )
+{
+ if (offset == 0)
+ {
+// logerror("PC %04x: write %02x to mcu %04x\n", activecpu_get_pc(), data, 0xc000 + offset);
+ if (mcu_command == 0x41)
+ {
+ mcu_credits = (mcu_credits + data) & 0xff;
+ }
+ }
+ else
+ {
+ /*
+ 0xa0: read number of credits
+ 0xa1: read number of credits, then buttons
+ 0x01: read player 1 joystick + buttons
+ 0x02: read player 2 joystick + buttons
+ 0x1a: read coin switches
+ 0x21: read service & tilt switches
+ 0x4a+0x41: add value to number of credits
+ 0x84: coin 1 lockout (issued only in test mode)
+ 0x88: coin 2 lockout (issued only in test mode)
+ 0x80: release coin lockout (issued only in test mode)
+ during initialization, a sequence of 4 bytes sets coin/credit settings
+ */
+
+// logerror("PC %04x: write %02x to mcu %04x\n", activecpu_get_pc(), data, 0xc000 + offset);
+
+ if (mcu_initializing)
+ {
+ /* set up coin/credit settings */
+ mcu_coinage[mcu_coinage_init++] = data;
+ if (mcu_coinage_init == 4) mcu_coinage_init = 0; /* must not happen */
+ }
+
+ if (data == 0xa1)
+ mcu_readcredits = 0; /* reset input port number */
+
+ /* Dr Toppel decrements credits differently. So handle it */
+ if ((data == 0x09) && (mcu_type == MCU_DRTOPPEL || mcu_type == MCU_PLUMPOP))
+ mcu_credits = (mcu_credits - 1) & 0xff; /* Player 1 start */
+ if ((data == 0x18) && (mcu_type == MCU_DRTOPPEL || mcu_type == MCU_PLUMPOP))
+ mcu_credits = (mcu_credits - 2) & 0xff; /* Player 2 start */
+
+ mcu_command = data;
+ }
+}
+
+
+
+/*********************************
+
+TNZS sync bug kludge
+
+In all TNZS versions there is code like this:
+
+0C5E: ld ($EF10),a
+0C61: ld a,($EF10)
+0C64: inc a
+0C65: ret nz
+0C66: jr $0C61
+
+which is sometimes executed by the main cpu when it writes to shared RAM a
+command for the second CPU. The intended purpose of the code is to wait an
+acknowledge from the sub CPU: the sub CPU writes FF to the same location
+after reading the command.
+
+However the above code is wrong. The "ret nz" instruction means that the
+loop will be exited only when the contents of $EF10 are *NOT* $FF!!
+On the real board, this casues little harm: the main CPU will just write
+the command, read it back and, since it's not $FF, return immediately. There
+is a chance that the command might go lost, but this will cause no major
+harm, the worse that can happen is that the background tune will not change.
+
+In MAME, however, since CPU interleaving is not perfect, it can happen that
+the main CPU ends its timeslice after writing to EF10 but before reading it
+back. In the meantime, the sub CPU will run, read the command and write FF
+there - therefore causing the main CPU to enter an endless loop.
+
+Unlike the usual sync problems in MAME, which can be fixed by increasing the
+interleave factor, in this case increasing it will actually INCREASE the
+chance of entering the endless loop - because it will increase the chances of
+the main CPU ending its timeslice at the wrong moment.
+
+So what we do here is catch writes by the main CPU to the RAM location, and
+process them using a timer, in order to
+a) force a resync of the two CPUs
+b) make sure the main CPU will be the first one to run after the location is
+ changed
+
+Since the answer from the sub CPU is ignored, we don't even need to boost
+interleave.
+
+*********************************/
+
+static TIMER_CALLBACK( kludge_callback )
+{
+ tnzs_sharedram[0x0f10] = param;
+}
+
+static WRITE8_HANDLER( tnzs_sync_kludge_w )
+{
+ timer_call_after_resynch(data,kludge_callback);
+}
+
+
+
+
+DRIVER_INIT( plumpop )
+{
+ mcu_type = MCU_PLUMPOP;
+}
+
+DRIVER_INIT( extrmatn )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ mcu_type = MCU_EXTRMATN;
+
+ /* there's code which falls through from the fixed ROM to bank #7, I have to */
+ /* copy it there otherwise the CPU bank switching support will not catch it. */
+ memcpy(&RAM[0x08000],&RAM[0x2c000],0x4000);
+}
+
+DRIVER_INIT( arknoid2 )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ mcu_type = MCU_ARKANOID;
+
+ /* there's code which falls through from the fixed ROM to bank #2, I have to */
+ /* copy it there otherwise the CPU bank switching support will not catch it. */
+ memcpy(&RAM[0x08000],&RAM[0x18000],0x4000);
+}
+
+DRIVER_INIT( drtoppel )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+ mcu_type = MCU_DRTOPPEL;
+
+ /* there's code which falls through from the fixed ROM to bank #2, I have to */
+ /* copy it there otherwise the CPU bank switching support will not catch it. */
+ memcpy(&RAM[0x08000],&RAM[0x18000],0x4000);
+
+ /* drtoppel writes to the palette RAM area even if it has PROMs! We have to patch it out. */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xf800, 0xfbff, 0, 0, MWA8_NOP);
+}
+
+DRIVER_INIT( chukatai )
+{
+ mcu_type = MCU_CHUKATAI;
+}
+
+DRIVER_INIT( tnzs )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+ mcu_type = MCU_TNZS;
+
+ /* there's code which falls through from the fixed ROM to bank #7, I have to */
+ /* copy it there otherwise the CPU bank switching support will not catch it. */
+ memcpy(&RAM[0x08000],&RAM[0x2c000],0x4000);
+
+ /* we need to install a kludge to avoid problems with a bug in the original code */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xef10, 0xef10, 0, 0, tnzs_sync_kludge_w);
+}
+
+DRIVER_INIT( tnzsb )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+ mcu_type = MCU_NONE_TNZSB;
+
+ /* there's code which falls through from the fixed ROM to bank #7, I have to */
+ /* copy it there otherwise the CPU bank switching support will not catch it. */
+ memcpy(&RAM[0x08000],&RAM[0x2c000],0x4000);
+
+ /* we need to install a kludge to avoid problems with a bug in the original code */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xef10, 0xef10, 0, 0, tnzs_sync_kludge_w);
+}
+
+DRIVER_INIT( kabukiz )
+{
+ mcu_type = MCU_NONE_KABUKIZ;
+}
+
+DRIVER_INIT( insectx )
+{
+ mcu_type = MCU_NONE_INSECTX;
+
+ /* this game has no mcu, replace the handler with plain input port handlers */
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0xc000, 0xc000, 0, 0, input_port_2_r );
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0xc001, 0xc001, 0, 0, input_port_3_r );
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0xc002, 0xc002, 0, 0, input_port_4_r );
+}
+
+DRIVER_INIT( kageki )
+{
+ mcu_type = MCU_NONE_KAGEKI;
+}
+
+
+READ8_HANDLER( tnzs_mcu_r )
+{
+ switch (mcu_type)
+ {
+ case MCU_TNZS:
+ case MCU_CHUKATAI:
+ return mcu_tnzs_r(offset);
+ break;
+ case MCU_ARKANOID:
+ return mcu_arknoid2_r(offset);
+ break;
+ case MCU_EXTRMATN:
+ case MCU_DRTOPPEL:
+ case MCU_PLUMPOP:
+ return mcu_extrmatn_r(offset);
+ break;
+ default:
+ return 0xff;
+ break;
+ }
+}
+
+WRITE8_HANDLER( tnzs_mcu_w )
+{
+ switch (mcu_type)
+ {
+ case MCU_TNZS:
+ case MCU_CHUKATAI:
+ mcu_tnzs_w(offset,data);
+ break;
+ case MCU_ARKANOID:
+ mcu_arknoid2_w(offset,data);
+ break;
+ case MCU_EXTRMATN:
+ case MCU_DRTOPPEL:
+ case MCU_PLUMPOP:
+ mcu_extrmatn_w(offset,data);
+ break;
+ default:
+ break;
+ }
+}
+
+INTERRUPT_GEN( arknoid2_interrupt )
+{
+ int coin;
+
+ switch (mcu_type)
+ {
+ case MCU_ARKANOID:
+ case MCU_EXTRMATN:
+ case MCU_DRTOPPEL:
+ case MCU_PLUMPOP:
+ coin = 0;
+ coin |= ((readinputport(5) & 1) << 0);
+ coin |= ((readinputport(6) & 1) << 1);
+ coin |= ((readinputport(4) & 3) << 2);
+ coin ^= 0x0c;
+ mcu_handle_coins(coin);
+ break;
+ default:
+ break;
+ }
+
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+}
+
+MACHINE_RESET( tnzs )
+{
+ /* initialize the mcu simulation */
+ switch (mcu_type)
+ {
+ case MCU_ARKANOID:
+ case MCU_EXTRMATN:
+ case MCU_DRTOPPEL:
+ case MCU_PLUMPOP:
+ mcu_reset();
+ break;
+ default:
+ break;
+ }
+
+ /* preset the banks */
+ {
+ UINT8 *RAM;
+
+ RAM = memory_region(REGION_CPU1);
+ memory_set_bankptr(1,&RAM[0x18000]);
+
+ RAM = memory_region(REGION_CPU2);
+ memory_set_bankptr(2,&RAM[0x10000]);
+ }
+}
+
+
+READ8_HANDLER( tnzs_sharedram_r )
+{
+ return tnzs_sharedram[offset];
+}
+
+WRITE8_HANDLER( tnzs_sharedram_w )
+{
+ tnzs_sharedram[offset] = data;
+}
+
+
+
+WRITE8_HANDLER( tnzs_bankswitch_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU1);
+
+// logerror("PC %04x: writing %02x to bankswitch\n", activecpu_get_pc(),data);
+
+ /* bit 4 resets the second CPU */
+ if (data & 0x10)
+ cpunum_set_input_line(1, INPUT_LINE_RESET, CLEAR_LINE);
+ else
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ASSERT_LINE);
+
+ /* bits 0-2 select RAM/ROM bank */
+ memory_set_bankptr (1, &RAM[0x10000 + 0x4000 * (data & 0x07)]);
+}
+
+WRITE8_HANDLER( tnzs_bankswitch1_w )
+{
+ UINT8 *RAM = memory_region(REGION_CPU2);
+
+// logerror("PC %04x: writing %02x to bankswitch 1\n", activecpu_get_pc(),data);
+
+ switch (mcu_type)
+ {
+ case MCU_TNZS:
+ case MCU_CHUKATAI:
+ /* bit 2 resets the mcu */
+ if (data & 0x04)
+ {
+ if (Machine->drv->cpu[2].type == CPU_I8X41)
+ cpunum_set_input_line(2, INPUT_LINE_RESET, PULSE_LINE);
+ }
+ /* Coin count and lockout is handled by the i8742 */
+ break;
+ case MCU_NONE_INSECTX:
+ coin_lockout_w( 0, (~data & 0x04) );
+ coin_lockout_w( 1, (~data & 0x08) );
+ coin_counter_w( 0, (data & 0x10) );
+ coin_counter_w( 1, (data & 0x20) );
+ break;
+ case MCU_NONE_TNZSB:
+ case MCU_NONE_KABUKIZ:
+ coin_lockout_w( 0, (~data & 0x10) );
+ coin_lockout_w( 1, (~data & 0x20) );
+ coin_counter_w( 0, (data & 0x04) );
+ coin_counter_w( 1, (data & 0x08) );
+ break;
+ case MCU_NONE_KAGEKI:
+ coin_lockout_global_w( (~data & 0x20) );
+ coin_counter_w( 0, (data & 0x04) );
+ coin_counter_w( 1, (data & 0x08) );
+ break;
+ case MCU_ARKANOID:
+ case MCU_EXTRMATN:
+ case MCU_DRTOPPEL:
+ case MCU_PLUMPOP:
+ /* bit 2 resets the mcu */
+ if (data & 0x04)
+ mcu_reset();
+ break;
+ default:
+ break;
+ }
+
+ /* bits 0-1 select ROM bank */
+ memory_set_bankptr (2, &RAM[0x10000 + 0x2000 * (data & 3)]);
+}
diff --git a/src/mame/machine/toaplan1.c b/src/mame/machine/toaplan1.c
new file mode 100644
index 00000000000..0054b0a7b8f
--- /dev/null
+++ b/src/mame/machine/toaplan1.c
@@ -0,0 +1,341 @@
+/***************************************************************************
+ ToaPlan game hardware from 1988-1991
+ ------------------------------------
+ ***************************************************************************/
+
+#include "driver.h"
+#include "cpu/m68000/m68000.h"
+#include "cpu/tms32010/tms32010.h"
+#include "includes/toaplan1.h"
+
+#define CLEAR 0
+#define ASSERT 1
+
+
+static int toaplan1_coin_count; /* coin count increments on startup ? , so dont count it */
+static int toaplan1_intenable;
+static int vimana_credits;
+static int vimana_latch;
+static int demonwld_dsp_on;
+static int demonwld_dsp_BIO;
+static int dsp_execute; /* Demon world */
+static UINT32 dsp_addr_w, main_ram_seg; /* Demon world */
+
+int toaplan1_unk_reset_port;
+
+UINT8 *toaplan1_sharedram;
+
+
+
+INTERRUPT_GEN( toaplan1_interrupt )
+{
+ if (toaplan1_intenable)
+ cpunum_set_input_line(0, 4, HOLD_LINE);
+}
+
+WRITE16_HANDLER( toaplan1_intenable_w )
+{
+ if (ACCESSING_LSB)
+ {
+ toaplan1_intenable = data & 0xff;
+ }
+}
+
+
+WRITE16_HANDLER( demonwld_dsp_addrsel_w )
+{
+ /* This sets the main CPU RAM address the DSP should */
+ /* read/write, via the DSP IO port 0 */
+ /* Top three bits of data need to be shifted left 9 places */
+ /* to select which memory bank from main CPU address */
+ /* space to use */
+ /* Lower thirteen bits of this data is shifted left one position */
+ /* to move it to an even address word boundary */
+
+ main_ram_seg = ((data & 0xe000) << 9);
+ dsp_addr_w = ((data & 0x1fff) << 1);
+ logerror("DSP PC:%04x IO write %04x (%08x) at port 0\n",activecpu_get_previouspc(),data,main_ram_seg + dsp_addr_w);
+}
+
+READ16_HANDLER( demonwld_dsp_r )
+{
+ /* DSP can read data from main CPU RAM via DSP IO port 1 */
+
+ UINT16 input_data = 0;
+ switch (main_ram_seg) {
+ case 0xc00000: cpuintrf_push_context(0); input_data = program_read_word(main_ram_seg + dsp_addr_w); cpuintrf_pop_context(); break;
+ default: logerror("DSP PC:%04x Warning !!! IO reading from %08x (port 1)\n",activecpu_get_previouspc(),main_ram_seg + dsp_addr_w);
+ }
+ logerror("DSP PC:%04x IO read %04x at %08x (port 1)\n",activecpu_get_previouspc(),input_data,main_ram_seg + dsp_addr_w);
+ return input_data;
+}
+
+WRITE16_HANDLER( demonwld_dsp_w )
+{
+ /* Data written to main CPU RAM via DSP IO port 1 */
+ dsp_execute = 0;
+ switch (main_ram_seg) {
+ case 0xc00000: if ((dsp_addr_w < 3) && (data == 0)) dsp_execute = 1;
+ cpuintrf_push_context(0);
+ program_write_word(main_ram_seg + dsp_addr_w, data);
+ cpuintrf_pop_context(); break;
+ default: logerror("DSP PC:%04x Warning !!! IO writing to %08x (port 1)\n",activecpu_get_previouspc(),main_ram_seg + dsp_addr_w);
+ }
+ logerror("DSP PC:%04x IO write %04x at %08x (port 1)\n",activecpu_get_previouspc(),data,main_ram_seg + dsp_addr_w);
+}
+
+WRITE16_HANDLER( demonwld_dsp_bio_w )
+{
+ /* data 0xffff means inhibit BIO line to DSP and enable */
+ /* communication to main processor */
+ /* Actually only DSP data bit 15 controls this */
+ /* data 0x0000 means set DSP BIO line active and disable */
+ /* communication to main processor*/
+ logerror("DSP PC:%04x IO write %04x at port 3\n",activecpu_get_previouspc(),data);
+ if (data & 0x8000) {
+ demonwld_dsp_BIO = CLEAR_LINE;
+ }
+ if (data == 0) {
+ if (dsp_execute) {
+ logerror("Turning 68000 on\n");
+ cpunum_set_input_line(0, INPUT_LINE_HALT, CLEAR_LINE);
+ dsp_execute = 0;
+ }
+ demonwld_dsp_BIO = ASSERT_LINE;
+ }
+}
+
+READ16_HANDLER ( demonwld_BIO_r )
+{
+ return demonwld_dsp_BIO;
+}
+
+
+static void demonwld_dsp(int enable)
+{
+ demonwld_dsp_on = enable;
+ if (enable)
+ {
+ logerror("Turning DSP on and 68000 off\n");
+ cpunum_set_input_line(2, INPUT_LINE_HALT, CLEAR_LINE);
+ cpunum_set_input_line(2, 0, ASSERT_LINE); /* TMS32010 INT */
+ cpunum_set_input_line(0, INPUT_LINE_HALT, ASSERT_LINE);
+ }
+ else
+ {
+ logerror("Turning DSP off\n");
+ cpunum_set_input_line(2, 0, CLEAR_LINE); /* TMS32010 INT */
+ cpunum_set_input_line(2, INPUT_LINE_HALT, ASSERT_LINE);
+ }
+}
+static void demonwld_restore_dsp(void)
+{
+ demonwld_dsp(demonwld_dsp_on);
+}
+
+WRITE16_HANDLER( demonwld_dsp_ctrl_w )
+{
+#if 0
+ logerror("68000:%08x Writing %08x to %08x.\n",activecpu_get_pc() ,data ,0xe0000a + offset);
+#endif
+
+ if (ACCESSING_LSB)
+ {
+ switch (data)
+ {
+ case 0x00: demonwld_dsp(1); break; /* Enable the INT line to the DSP */
+ case 0x01: demonwld_dsp(0); break; /* Inhibit the INT line to the DSP */
+ default: logerror("68000:%04x Writing unknown command %08x to %08x\n",activecpu_get_previouspc() ,data ,0xe0000a + offset); break;
+ }
+ }
+ else
+ {
+ logerror("68000:%04x Writing unknown command %08x to %08x\n",activecpu_get_previouspc() ,data ,0xe0000a + offset);
+ }
+}
+
+
+READ16_HANDLER( samesame_port_6_word_r )
+{
+ /* Bit 0x80 is secondary CPU (HD647180) ready signal */
+ logerror("PC:%04x Warning !!! IO reading from $14000a\n",activecpu_get_previouspc());
+ return (0x80 | input_port_6_word_r(0,0)) & 0xff;
+}
+
+READ16_HANDLER( vimana_input_port_5_word_r )
+{
+ int data, p;
+
+ p = input_port_5_word_r(0,0);
+ vimana_latch ^= p;
+ data = (vimana_latch & p );
+
+ /* simulate the mcu keeping track of credits */
+ /* latch so it doesn't add more than one */
+ /* credit per keypress */
+ if (data & 0x18)
+ {
+ vimana_credits++ ;
+ }
+ vimana_latch = p;
+
+ return p & 0xffff;
+}
+
+READ16_HANDLER( vimana_mcu_r )
+{
+ int data = 0 ;
+ switch (offset)
+ {
+ case 0: data = 0xff; break;
+ case 1: data = 0; break;
+ case 2: data = vimana_credits; break;
+ }
+ return data & 0xff;
+}
+
+WRITE16_HANDLER( vimana_mcu_w )
+{
+ switch (offset)
+ {
+ case 0: break;
+ case 1: break;
+ case 2: if (ACCESSING_LSB) vimana_credits = data & 0xff; break;
+ }
+}
+
+READ16_HANDLER( toaplan1_shared_r )
+{
+ return toaplan1_sharedram[offset] & 0xff;
+}
+
+WRITE16_HANDLER( toaplan1_shared_w )
+{
+ if (ACCESSING_LSB)
+ {
+ toaplan1_sharedram[offset] = data & 0xff;
+ }
+}
+
+
+WRITE16_HANDLER( toaplan1_reset_sound )
+{
+ /* Reset the secondary CPU and sound chip during soft resets */
+
+ if (ACCESSING_LSB && (data == 0))
+ {
+ logerror("PC:%04x Resetting Sound CPU and Sound chip (%08x)\n",activecpu_get_previouspc(),data);
+ if (Machine->drv->sound[0].type == SOUND_YM3812)
+ sndti_reset(SOUND_YM3812, 0);
+ if (Machine->drv->cpu[1].type == CPU_Z80)
+ cpunum_set_input_line(1, INPUT_LINE_RESET, PULSE_LINE);
+ }
+}
+
+
+WRITE8_HANDLER( rallybik_coin_w )
+{
+ switch (data) {
+ case 0x08: if (toaplan1_coin_count) { coin_counter_w(0,1); coin_counter_w(0,0); } break;
+ case 0x09: if (toaplan1_coin_count) { coin_counter_w(2,1); coin_counter_w(2,0); } break;
+ case 0x0a: if (toaplan1_coin_count) { coin_counter_w(1,1); coin_counter_w(1,0); } break;
+ case 0x0b: if (toaplan1_coin_count) { coin_counter_w(3,1); coin_counter_w(3,0); } break;
+ case 0x0c: coin_lockout_w(0,1); coin_lockout_w(2,1); break;
+ case 0x0d: coin_lockout_w(0,0); coin_lockout_w(2,0); break;
+ case 0x0e: coin_lockout_w(1,1); coin_lockout_w(3,1); break;
+ case 0x0f: coin_lockout_w(1,0); coin_lockout_w(3,0); toaplan1_coin_count=1; break;
+ default: logerror("PC:%04x Writing unknown data (%04x) to coin count/lockout port\n",activecpu_get_previouspc(),data); break;
+ }
+}
+
+WRITE8_HANDLER( toaplan1_coin_w )
+{
+ logerror("Z80 writing %02x to coin control\n",data);
+ /* This still isnt too clear yet. */
+ /* Coin C has no coin lock ? */
+ /* Are some outputs for lights ? (no space on JAMMA for it though) */
+
+ switch (data) {
+ case 0xee: coin_counter_w(1,1); coin_counter_w(1,0); break; /* Count slot B */
+ case 0xed: coin_counter_w(0,1); coin_counter_w(0,0); break; /* Count slot A */
+ /* The following are coin counts after coin-lock active (faulty coin-lock ?) */
+ case 0xe2: coin_counter_w(1,1); coin_counter_w(1,0); coin_lockout_w(1,1); break;
+ case 0xe1: coin_counter_w(0,1); coin_counter_w(0,0); coin_lockout_w(0,1); break;
+
+ case 0xec: coin_lockout_global_w(0); break; /* ??? count games played */
+ case 0xe8: break; /* ??? Maximum credits reached with coin/credit ratio */
+ case 0xe4: break; /* ??? Reset coin system */
+
+ case 0x0c: coin_lockout_global_w(0); break; /* Unlock all coin slots */
+ case 0x08: coin_lockout_w(2,0); break; /* Unlock coin slot C */
+ case 0x09: coin_lockout_w(0,0); break; /* Unlock coin slot A */
+ case 0x0a: coin_lockout_w(1,0); break; /* Unlock coin slot B */
+
+ case 0x02: coin_lockout_w(1,1); break; /* Lock coin slot B */
+ case 0x01: coin_lockout_w(0,1); break; /* Lock coin slot A */
+ case 0x00: coin_lockout_global_w(1); break; /* Lock all coin slots */
+ default: logerror("PC:%04x Writing unknown data (%04x) to coin count/lockout port\n",activecpu_get_previouspc(),data); break;
+ }
+}
+
+WRITE16_HANDLER( samesame_coin_w )
+{
+ if (ACCESSING_LSB)
+ {
+ toaplan1_coin_w(offset, data & 0xff);
+ }
+ if (ACCESSING_MSB && (data&0xff00))
+ {
+ logerror("PC:%04x Writing unknown MSB data (%04x) to coin count/lockout port\n",activecpu_get_previouspc(),data);
+ }
+}
+
+
+MACHINE_RESET( toaplan1 )
+{
+ toaplan1_intenable = 0;
+ toaplan1_coin_count = 0;
+ toaplan1_unk_reset_port = 0;
+ coin_lockout_global_w(0);
+}
+void toaplan1_driver_savestate(void)
+{
+ state_save_register_global(toaplan1_intenable);
+ state_save_register_global(toaplan1_coin_count);
+ state_save_register_global(toaplan1_unk_reset_port);
+}
+
+MACHINE_RESET( zerozone ) /* Hack for ZeroWing and OutZone. See the video driver */
+{
+ machine_reset_toaplan1(machine);
+ toaplan1_unk_reset_port = 1;
+}
+
+MACHINE_RESET( demonwld )
+{
+ machine_reset_toaplan1(machine);
+ dsp_addr_w = 0;
+ main_ram_seg = 0;
+ dsp_execute = 0;
+}
+void demonwld_driver_savestate(void)
+{
+ state_save_register_global(demonwld_dsp_on);
+ state_save_register_global(dsp_addr_w);
+ state_save_register_global(main_ram_seg);
+ state_save_register_global(demonwld_dsp_BIO);
+ state_save_register_global(dsp_execute);
+ state_save_register_func_postload(demonwld_restore_dsp);
+}
+
+MACHINE_RESET( vimana )
+{
+ machine_reset_toaplan1(machine);
+ vimana_credits = 0;
+ vimana_latch = 0;
+}
+void vimana_driver_savestate(void)
+{
+ state_save_register_global(vimana_credits);
+ state_save_register_global(vimana_latch);
+}
diff --git a/src/mame/machine/twincobr.c b/src/mame/machine/twincobr.c
new file mode 100644
index 00000000000..2fded5e44b3
--- /dev/null
+++ b/src/mame/machine/twincobr.c
@@ -0,0 +1,394 @@
+/****************************************************************************
+ * Twin Cobra *
+ * Communications and memory functions between shared CPU memory spaces *
+ ****************************************************************************/
+
+#include "driver.h"
+#include "cpu/m68000/m68000.h"
+#include "cpu/tms32010/tms32010.h"
+#include "twincobr.h"
+
+
+#define LOG_DSP_CALLS 0
+#define CLEAR 0
+#define ASSERT 1
+
+
+int toaplan_main_cpu; /* Main CPU type. 0 = 68000, 1 = Z80 */
+int twincobr_intenable;
+int wardner_membank;
+static int twincobr_dsp_on;
+static int twincobr_dsp_BIO;
+static int fsharkbt_8741;
+static int dsp_execute;
+static UINT32 dsp_addr_w, main_ram_seg;
+
+#if LOG_DSP_CALLS
+const static int toaplan_port_type[2] = { 0x7800c, 0x5c };
+#endif
+
+UINT8 *twincobr_sharedram;
+
+
+
+INTERRUPT_GEN( twincobr_interrupt )
+{
+ if (twincobr_intenable) {
+ twincobr_intenable = 0;
+ cpunum_set_input_line(0, MC68000_IRQ_4, HOLD_LINE);
+ }
+}
+
+INTERRUPT_GEN( wardner_interrupt )
+{
+ if (twincobr_intenable) {
+ twincobr_intenable = 0;
+ cpunum_set_input_line(0, 0, HOLD_LINE);
+ }
+}
+
+
+WRITE16_HANDLER( twincobr_dsp_addrsel_w )
+{
+ /* This sets the main CPU RAM address the DSP should */
+ /* read/write, via the DSP IO port 0 */
+ /* Top three bits of data need to be shifted left 3 places */
+ /* to select which memory bank from main CPU address */
+ /* space to use */
+ /* Lower thirteen bits of this data is shifted left one position */
+ /* to move it to an even address word boundary */
+
+ main_ram_seg = ((data & 0xe000) << 3);
+ dsp_addr_w = ((data & 0x1fff) << 1);
+
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO write %04x (%08x) at port 0\n",activecpu_get_previouspc(),data,main_ram_seg + dsp_addr_w);
+#endif
+}
+
+READ16_HANDLER( twincobr_dsp_r )
+{
+ /* DSP can read data from main CPU RAM via DSP IO port 1 */
+
+ UINT16 input_data = 0;
+ switch (main_ram_seg) {
+ case 0x30000:
+ case 0x40000:
+ case 0x50000: cpuintrf_push_context(0);
+ input_data = program_read_word(main_ram_seg + dsp_addr_w);
+ cpuintrf_pop_context(); break;
+ default: logerror("DSP PC:%04x Warning !!! IO reading from %08x (port 1)\n",activecpu_get_previouspc(),main_ram_seg + dsp_addr_w); break;
+ }
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO read %04x at %08x (port 1)\n",activecpu_get_previouspc(),input_data,main_ram_seg + dsp_addr_w);
+#endif
+ return input_data;
+}
+
+WRITE16_HANDLER( twincobr_dsp_w )
+{
+ /* Data written to main CPU RAM via DSP IO port 1 */
+ dsp_execute = 0;
+ switch (main_ram_seg) {
+ case 0x30000: if ((dsp_addr_w < 3) && (data == 0)) dsp_execute = 1;
+ case 0x40000:
+ case 0x50000: cpuintrf_push_context(0);
+ program_write_word(main_ram_seg + dsp_addr_w, data);
+ cpuintrf_pop_context(); break;
+ default: logerror("DSP PC:%04x Warning !!! IO writing to %08x (port 1)\n",activecpu_get_previouspc(),main_ram_seg + dsp_addr_w); break;
+ }
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO write %04x at %08x (port 1)\n",activecpu_get_previouspc(),data,main_ram_seg + dsp_addr_w);
+#endif
+}
+
+WRITE16_HANDLER( wardner_dsp_addrsel_w )
+{
+ /* This sets the main CPU RAM address the DSP should */
+ /* read/write, via the DSP IO port 0 */
+ /* Lower twelve bits of this data is shifted left one position */
+ /* to move it to an even address boundary */
+
+ main_ram_seg = (data & 0xe000);
+ dsp_addr_w = ((data & 0x07ff) << 1);
+
+ if (main_ram_seg == 0x6000) main_ram_seg = 0x7000;
+
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO write %04x (%08x) at port 0\n",activecpu_get_previouspc(),data,main_ram_seg + dsp_addr_w);
+#endif
+}
+
+READ16_HANDLER( wardner_dsp_r )
+{
+ /* DSP can read data from main CPU RAM via DSP IO port 1 */
+
+ UINT16 input_data = 0;
+ switch (main_ram_seg) {
+ case 0x7000:
+ case 0x8000:
+ case 0xa000: cpuintrf_push_context(0);
+ input_data = program_read_byte(main_ram_seg + (dsp_addr_w + 0))
+ | (program_read_byte(main_ram_seg + (dsp_addr_w + 1)) << 8);
+ cpuintrf_pop_context(); break;
+ default: logerror("DSP PC:%04x Warning !!! IO reading from %08x (port 1)\n",activecpu_get_previouspc(),main_ram_seg + dsp_addr_w); break;
+ }
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO read %04x at %08x (port 1)\n",activecpu_get_previouspc(),input_data,main_ram_seg + dsp_addr_w);
+#endif
+ return input_data;
+}
+
+WRITE16_HANDLER( wardner_dsp_w )
+{
+ /* Data written to main CPU RAM via DSP IO port 1 */
+ dsp_execute = 0;
+ switch (main_ram_seg) {
+ case 0x7000: if ((dsp_addr_w < 3) && (data == 0)) dsp_execute = 1;
+ case 0x8000:
+ case 0xa000: cpuintrf_push_context(0);
+ program_write_byte(main_ram_seg + (dsp_addr_w + 0), (data & 0xff));
+ program_write_byte(main_ram_seg + (dsp_addr_w + 1), ((data >> 8) & 0xff));
+ cpuintrf_pop_context(); break;
+ default: logerror("DSP PC:%04x Warning !!! IO writing to %08x (port 1)\n",activecpu_get_previouspc(),main_ram_seg + dsp_addr_w); break;
+ }
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO write %04x at %08x (port 1)\n",activecpu_get_previouspc(),data,main_ram_seg + dsp_addr_w);
+#endif
+}
+
+WRITE16_HANDLER( twincobr_dsp_bio_w )
+{
+ /* data 0xffff means inhibit BIO line to DSP and enable */
+ /* communication to main processor */
+ /* Actually only DSP data bit 15 controls this */
+ /* data 0x0000 means set DSP BIO line active and disable */
+ /* communication to main processor*/
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO write %04x at port 3\n",activecpu_get_previouspc(),data);
+#endif
+ if (data & 0x8000) {
+ twincobr_dsp_BIO = CLEAR_LINE;
+ }
+ if (data == 0) {
+ if (dsp_execute) {
+#if LOG_DSP_CALLS
+ logerror("Turning the main CPU on\n");
+#endif
+ cpunum_set_input_line(0, INPUT_LINE_HALT, CLEAR_LINE);
+ dsp_execute = 0;
+ }
+ twincobr_dsp_BIO = ASSERT_LINE;
+ }
+}
+
+READ16_HANDLER( fsharkbt_dsp_r )
+{
+ /* IO Port 2 used by Flying Shark bootleg */
+ /* DSP reads data from an extra MCU (8741) at IO port 2 */
+ /* Port is read three times during startup. First and last data */
+ /* read must equal, but second data read must be different */
+ fsharkbt_8741 += 1;
+#if LOG_DSP_CALLS
+ logerror("DSP PC:%04x IO read %04x from 8741 MCU (port 2)\n",activecpu_get_previouspc(),(fsharkbt_8741 & 0x08));
+#endif
+ return (fsharkbt_8741 & 1);
+}
+
+WRITE16_HANDLER( fsharkbt_dsp_w )
+{
+ /* Flying Shark bootleg DSP writes data to an extra MCU (8741) at IO port 2 */
+#if 0
+ logerror("DSP PC:%04x IO write from DSP RAM:%04x to 8741 MCU (port 2)\n",activecpu_get_previouspc(),fsharkbt_8741);
+#endif
+}
+
+READ16_HANDLER ( twincobr_BIO_r )
+{
+ return twincobr_dsp_BIO;
+}
+
+
+static void twincobr_dsp(int enable)
+{
+ twincobr_dsp_on = enable;
+ if (enable) {
+#if LOG_DSP_CALLS
+ logerror("Turning DSP on and main CPU off\n");
+#endif
+ cpunum_set_input_line(2, INPUT_LINE_HALT, CLEAR_LINE);
+ cpunum_set_input_line(2, 0, ASSERT_LINE); /* TMS32010 INT */
+ cpunum_set_input_line(0, INPUT_LINE_HALT, ASSERT_LINE);
+ }
+ else {
+#if LOG_DSP_CALLS
+ logerror("Turning DSP off\n");
+#endif
+ cpunum_set_input_line(2, 0, CLEAR_LINE); /* TMS32010 INT */
+ cpunum_set_input_line(2, INPUT_LINE_HALT, ASSERT_LINE);
+ }
+}
+
+static void twincobr_restore_dsp(void)
+{
+ twincobr_dsp(twincobr_dsp_on);
+}
+
+
+static void toaplan0_control_w(int offset, int data)
+{
+#if LOG_DSP_CALLS
+ logerror("CPU0:%08x Writing %08x to %08x.\n",activecpu_get_pc(),data,toaplan_port_type[toaplan_main_cpu] - offset);
+#endif
+
+ if (toaplan_main_cpu == 1) {
+ if (data == 0x0c) { data = 0x1c; wardner_sprite_hack=0; } /* Z80 ? */
+ if (data == 0x0d) { data = 0x1d; wardner_sprite_hack=1; } /* Z80 ? */
+ }
+
+ switch (data) {
+ case 0x0004: twincobr_intenable = 0; break;
+ case 0x0005: twincobr_intenable = 1; break;
+ case 0x0006: twincobr_flipscreen(0); break;
+ case 0x0007: twincobr_flipscreen(1); break;
+ case 0x0008: twincobr_bg_ram_bank = 0x0000; break;
+ case 0x0009: twincobr_bg_ram_bank = 0x1000; break;
+ case 0x000a: twincobr_fg_rom_bank = 0x0000; break;
+ case 0x000b: twincobr_fg_rom_bank = 0x1000; break;
+ case 0x000c: twincobr_dsp(1); break; /* Enable the INT line to the DSP */
+ case 0x000d: twincobr_dsp(0); break; /* Inhibit the INT line to the DSP */
+ case 0x000e: twincobr_display(0); break; /* Turn display off */
+ case 0x000f: twincobr_display(1); break; /* Turn display on */
+ }
+}
+
+WRITE16_HANDLER( twincobr_control_w )
+{
+ if (ACCESSING_LSB)
+ {
+ toaplan0_control_w(offset, data & 0xff);
+ }
+}
+
+WRITE8_HANDLER( wardner_control_w )
+{
+ toaplan0_control_w(offset, data);
+}
+
+
+READ16_HANDLER( twincobr_sharedram_r )
+{
+ return twincobr_sharedram[offset];
+}
+
+WRITE16_HANDLER( twincobr_sharedram_w )
+{
+ if (ACCESSING_LSB)
+ {
+ twincobr_sharedram[offset] = data & 0xff;
+ }
+}
+
+
+static void toaplan0_coin_dsp_w(int offset, int data)
+{
+#if LOG_DSP_CALLS
+ if (data > 1)
+ logerror("CPU0:%08x Writing %08x to %08x.\n",activecpu_get_pc(),data,toaplan_port_type[toaplan_main_cpu] - offset);
+#endif
+ switch (data) {
+ case 0x08: coin_counter_w(0,0); break;
+ case 0x09: coin_counter_w(0,1); break;
+ case 0x0a: coin_counter_w(1,0); break;
+ case 0x0b: coin_counter_w(1,1); break;
+ case 0x0c: coin_lockout_w(0,1); break;
+ case 0x0d: coin_lockout_w(0,0); break;
+ case 0x0e: coin_lockout_w(1,1); break;
+ case 0x0f: coin_lockout_w(1,0); break;
+ /****** The following apply to Flying Shark/Wardner only ******/
+ case 0x00: /* This means assert the INT line to the DSP */
+#if LOG_DSP_CALLS
+ logerror("Turning DSP on and main CPU off\n");
+#endif
+ cpunum_set_input_line(2, INPUT_LINE_HALT, CLEAR_LINE);
+ cpunum_set_input_line(2, 0, ASSERT_LINE); /* TMS32010 INT */
+ cpunum_set_input_line(0, INPUT_LINE_HALT, ASSERT_LINE);
+ break;
+ case 0x01: /* This means inhibit the INT line to the DSP */
+#if LOG_DSP_CALLS
+ logerror("Turning DSP off\n");
+#endif
+ cpunum_set_input_line(2, 0, CLEAR_LINE); /* TMS32010 INT */
+ cpunum_set_input_line(2, INPUT_LINE_HALT, ASSERT_LINE);
+ break;
+ }
+}
+
+
+WRITE16_HANDLER( fshark_coin_dsp_w )
+{
+ if (ACCESSING_LSB)
+ {
+ toaplan0_coin_dsp_w(offset, data & 0xff);
+ }
+}
+
+WRITE8_HANDLER( twincobr_coin_w )
+{
+ toaplan0_coin_dsp_w(offset, data);
+}
+
+WRITE8_HANDLER( wardner_coin_dsp_w )
+{
+ toaplan0_coin_dsp_w(offset, data);
+}
+
+
+MACHINE_RESET( twincobr )
+{
+ toaplan_main_cpu = 0; /* 68000 */
+ twincobr_display(0);
+ twincobr_intenable = 0;
+ dsp_addr_w = 0;
+ main_ram_seg = 0;
+ dsp_execute = 0;
+ fsharkbt_8741 = -1; /* Reset the Flying Shark Bootleg MCU */
+ twincobr_dsp_BIO = CLEAR_LINE;
+}
+void twincobr_driver_savestate(void)
+{
+ state_save_register_global(toaplan_main_cpu);
+ state_save_register_global(twincobr_intenable);
+ state_save_register_global(twincobr_dsp_on);
+ state_save_register_global(dsp_addr_w);
+ state_save_register_global(main_ram_seg);
+ state_save_register_global(twincobr_dsp_BIO);
+ state_save_register_global(dsp_execute);
+ state_save_register_global(fsharkbt_8741);
+ state_save_register_func_postload(twincobr_restore_dsp);
+}
+
+MACHINE_RESET( wardner )
+{
+ toaplan_main_cpu = 1; /* Z80 */
+ twincobr_display(1);
+ twincobr_intenable = 0;
+ dsp_addr_w = 0;
+ main_ram_seg = 0;
+ dsp_execute = 0;
+ twincobr_dsp_BIO = CLEAR_LINE;
+ wardner_membank = 0;
+}
+void wardner_driver_savestate(void)
+{
+ state_save_register_global(toaplan_main_cpu);
+ state_save_register_global(twincobr_intenable);
+ state_save_register_global(twincobr_dsp_on);
+ state_save_register_global(dsp_addr_w);
+ state_save_register_global(main_ram_seg);
+ state_save_register_global(twincobr_dsp_BIO);
+ state_save_register_global(dsp_execute);
+ state_save_register_global(wardner_membank);
+ state_save_register_func_postload(wardner_restore_bank); /* Restore the Main CPU bank */
+ state_save_register_func_postload(twincobr_restore_dsp);
+}
diff --git a/src/mame/machine/tx1.c b/src/mame/machine/tx1.c
new file mode 100644
index 00000000000..4cf3134049e
--- /dev/null
+++ b/src/mame/machine/tx1.c
@@ -0,0 +1,679 @@
+/*===================================================================*/
+/* TX-1/Buggy Boy (Tatsumi) Hardware */
+/* SN74S516 Arithmetic Unit and Interface Emulation */
+/* VERY PRELIMINARY! */
+/*===================================================================*/
+
+#include "driver.h"
+
+static INT16 AU_DATA;
+static INT16 *AU_PTR = &AU_DATA;
+static UINT16 inst_index;
+
+/* Internal registers and so forth */
+static struct Regs
+{
+ INT16 X; /* Multiplicand and divisor */
+ INT16 X1; /* Previous X */
+ INT16 Y; /* Multiplier */
+
+ INT16 Operand2;
+
+ union /* 32-bit accumulator */
+ {
+ #ifdef LSB_FIRST
+ struct { UINT16 W; INT16 Z;} ZW_16;
+ #else
+ struct { INT16 Z; UINT16 W;} ZW_16;
+ #endif
+ INT32 ZW_32;
+ } acc;
+
+ INT16 ins_seq; /* Instruciton sequence */
+} AU_Regs;
+
+
+/* Main portion of the arithmetic unit emulation. Accessed by AU_R and AU_W */
+/* Only a few instructions implemented currently */
+
+static void MMI_74S516(int ins, UINT16 *data)
+{
+
+ if ((ins!=7) && ((AU_Regs.ins_seq & 0xf)==7)) /* If last instruction was a reading operation, clear sequence. */
+ AU_Regs.ins_seq = 0;
+
+ /* Take INS and append to instruction */
+ AU_Regs.ins_seq <<=4;
+ AU_Regs.ins_seq = AU_Regs.ins_seq | (ins & 0xf);
+
+ switch ( AU_Regs.ins_seq )
+ {
+ /* X1 . Y */
+ case 0x0: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* -X1 . Y */
+ case 0x1: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* X1 . Y + Kz.Kw */
+ case 0x2: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* -X1 . Y + Kz.Kw */
+ case 0x3: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* Partial: Load X */
+ case 0x5: AU_Regs.X = *data;
+ break;
+ case 0x6: AU_Regs.X = *data;
+ break;
+
+
+ /* X * Y (Fractional) */
+ case 0x50: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* X * Y (Integer) */ // Ok
+ case 0x60: AU_Regs.Y = *data;
+ AU_Regs.acc.ZW_32 = ((INT16)AU_Regs.X * (INT16)AU_Regs.Y);
+ AU_Regs.X1 = AU_Regs.X;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* -X * Y (Fractional) */
+ case 0x51: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* -X * Y (Integer) */ // Ok
+ case 0x61: AU_Regs.Y = *data;
+ AU_Regs.acc.ZW_32 = (-(INT16)AU_Regs.X * (INT16)AU_Regs.Y);
+ AU_Regs.X1 = AU_Regs.X;
+ AU_Regs.ins_seq = 0;
+ break;
+
+
+ /* X * Y + Kz.Kw (Fractional) */
+ case 0x52: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* X * Y + Kz.Kw (Integer) */ // Ok
+ case 0x62: AU_Regs.Y = *data;
+ AU_Regs.acc.ZW_32 += ((INT16)AU_Regs.X * (INT16)AU_Regs.Y);
+ AU_Regs.X1 = AU_Regs.X;
+ AU_Regs.ins_seq = 0;
+ break;
+
+
+ /* -X * Y + Kz.Kw (Fractional) */
+ case 0x53: AU_Regs.Y = *data;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* -X * Y + Kz.Kw (Integer) */ // Ok
+ case 0x63: AU_Regs.Y = *data;
+ AU_Regs.acc.ZW_32 += (-(INT16)AU_Regs.X * (INT16)AU_Regs.Y);
+ AU_Regs.X1 = AU_Regs.X;
+ AU_Regs.ins_seq = 0;
+ break;
+
+
+
+ /* Kw / X (Fractional) Nothing Loaded */
+ case 0x54: AU_Regs.ins_seq = 0;
+ break;
+
+ /* Kw / X (Integer) Nothing Loaded */
+ case 0x64: AU_Regs.acc.ZW_32 /= (INT16)AU_Regs.X;
+ AU_Regs.X1 = AU_Regs.X;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ /* Kz / X (Fractional) Nothing Loaded */
+ case 0x55: AU_Regs.ins_seq = 0;
+ break;
+
+
+ /* Kz / X (Integer) Nothing Loaded */
+ case 0x65: AU_Regs.acc.ZW_32=AU_Regs.ins_seq;
+ AU_Regs.ins_seq=0;
+ break;
+
+
+ /* This can either load Z,Nothing or 0? */
+ case 0x56: AU_Regs.Operand2 = *data;
+ break;
+
+
+ case 0x560: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x561: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x562: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x563: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x564: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x565: AU_Regs.ins_seq = 0;
+ break;
+
+ // Not complete instruction
+ case 0x566:
+ AU_Regs.ins_seq = 0;
+ break;
+
+
+ case 0x660: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x661: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x662: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x663: AU_Regs.ins_seq = 0;
+ break;
+
+ /* Z,W /X */
+ // result in Z, remainder in W
+ case 0x664: AU_Regs.acc.ZW_16.W = *data;
+ AU_Regs.acc.ZW_16.Z = AU_Regs.Operand2;
+ AU_Regs.acc.ZW_16.Z = (INT16)((INT32)AU_Regs.acc.ZW_32 / (INT16)AU_Regs.X); // wrong :(
+ AU_Regs.acc.ZW_16.W = (INT16)((INT32)AU_Regs.acc.ZW_32 % (INT16)AU_Regs.X); //correct!
+ AU_Regs.X1 = AU_Regs.X;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x665: AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5660:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5661:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5662:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5663:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5664:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5665:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5666:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x5667:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x6660:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x6661:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x6662:AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x6663:AU_Regs.ins_seq = 0;
+ break;
+
+ /* W/X */
+ case 0x6664:AU_Regs.acc.ZW_32 = (INT16)AU_Regs.acc.ZW_16.W / (INT16)AU_Regs.X;
+ AU_Regs.X1 = AU_Regs.X;
+ AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x6665:
+ AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x6666:
+ AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x6667:
+ AU_Regs.ins_seq = 0;
+ break;
+
+ case 0x66: AU_Regs.Operand2 = *data;
+ break;
+
+ case 0x4: AU_Regs.ins_seq = 0;
+ break;
+
+ /* Reading Operations */
+
+ case 0x7: *data = AU_Regs.acc.ZW_16.Z;
+ break;
+
+ case 0x77: *data = AU_Regs.acc.ZW_16.W;
+ break;
+
+ case 0x777: *data = AU_Regs.acc.ZW_16.Z;
+ break;
+
+ case 0x7777: *data = AU_Regs.acc.ZW_16.W;
+ break;
+
+ default: break;
+ }
+
+}
+
+
+
+/******************************************************/
+/* */
+/* MMI SN74S516T Arithmetic Unit and Interface */
+/* */
+/******************************************************/
+
+/*
+The arithmetic unit is used extensively to calculate both object and road attributes in both games.
+It can take instructions directly from slave address bus A1-A3 or from a pair of PROMS (BB1.163 and BB2.162).
+Two 16KB function data ROMs are accessible by the chip and the slave CPU (via a hardware index and pointer).
+
+The interface between the arithmetic unit and the slave CPU is different between Buggy Boy and TX-1.
+
+In the case of an Buggy Boy PCB:
+Without AU: No objects visible, road is unchanging in direction.
+Without instruction PROMS: Hand/Go is displayed correctly as well as the end of race animation sequence (buggy spins and goes up in smoke).
+
+Therfore, once enough simple instructions are implemented, it should be possible do display some objects correctly.
+
+/MLPCS = !A10.!A11.A12.A13.!A14.!A15
+/DPRCS = A10.A11.A12.A13.!A14.!A15
+/INSALD = /AT3RD.!AT3WDRART + !AT3WDRART.A15 + !AT3WDRART.!A13 + !AT3WDRART.A14 + !AT3WDRART.!A12 + !A8
+/CNTST = /AT3RD.!AT3WDRART + !AT3WDRART.A15 + !AT3WDRART.!A13 + !AT3WDRART.A14 + !AT3WDRART.!A12 + !A7
+/SPCS = !A15.!A14.!A13.A12 + A14.!A13.!A12 + !A14.A12.A9 + !A14.A13.!A12 + !A14.!A11 + A15
+
+3000-31ff = Direct instruction input (AAB1-AAB3 connect to I0-2 of AU).
+
+3c00-3cff
+3d00-3dff
+3e00-3eff
+3f00-3fff = DATA ROM output enable.
+
+/SPCS = 0800-0fff
+ 3800-39ff
+ 3c00-3dff
+ 5000-7fff
+
+
+When CPU A8=1, the counters are loaded with an address (e.g. [3754] and [3120]).
+
+The counters are enabled on:
+
+* A7=1 (e.g. [3680] and [3A80]).
+* Read access to locations asserting /SPCS (e.g. [7a72] - those ROM mirror accesses have some significance afterall!)
+* BB2.162 bit 7 = 0 (/CUDEN).
+
+Writes to [36XX] and [37XX] load a value into the AU ROM address shift-registers .
+Reads from [36XX] (and [37xx] presumably) returns this value.
+Writes to [3A00] loads a shift value/direction.
+
+The AU ROM address shifting is governed by DSEL0-1 (BB2.162):
+
+00 = Invalid
+01 = >> 4
+10 = << 4
+11 = Shift direction and magnitude specified by 4-bit data value written to [3A00]:
+ A13-11 = 000 -> << by A10-7
+ A13-11 != 000 -> >> by A13-11 (LSB=0)
+
+ The shift magnitude is specified by the number of number of 0s between the LSB (inclusive) and the '1'. Shifting is circular.
+
+Examples:
+
+13 [3754] <- 2DB5
+ [3A00] <- 0100
+ [3600] == B6D4 ? // 0x2DB5 << 2 == 0xB6D4
+
+14 [3600] <- 2DB5
+ [3A00] <- 0200
+ [3600] == 5B6A ? // 0x2DB5 << 1 == 0x5B6A
+
+15 [3600] <- 2DB5
+ [3A00] <- 0400
+ [3600] == 2DB5 // No shift.
+
+16 [3600] <- 2DB5
+ [3A00] <- 0800
+ [3600] == 96DA ? // 0x2DB5 >> 1 == 0x96DA
+
+17 [3600] <- 2DB5
+ [3A00] <- 1000
+ [3600] = 4B6D ? // 0x2DB5 >> 2 == 0x4B6D
+
+18 [3600] <- 2DB5
+ [3A00] <- 2000
+ [3600] = A5B6 ? // 0x2DB5 >> 3 == 0xA5B6
+
+19 [3600] <- 1568
+ [3A00] <- 2000
+ [3E00] = 1BF2 ? // 0x1568 >> 3 == 0x02AD -> AU_ROM[0x02AD] == 0x1BF2
+
+
+The 14-bit AU ROM address is formed from:
+
+A13-11 = TFAD13-11 (BB2.162 D4-2)
+A10-8 = If RADCHG = 1: AU PROM address bits 7-5
+ If RADCHG = 0: Bits 10-8 of shift registers
+A7-0 = Bits 7-0 of shift registers.
+
+The current implementation of accessing the AU ROM is wrong (it's based on software behaviour rather than the actual hardware )
+
+Here's the full list of AU tests performed during test mode:
+
+ST
+ [300C] <- AA55
+ [3000] <- 55AA
+04 [300E] = E355 ?
+04 [300E] = 5572 ?
+
+ [300C] <- AA55
+ [3002] <- 55AA
+05 [300E] = 1CAA ?
+05 [300E] = AA8E ?
+
+ [300C] <- 5A5A
+ [3004] <- A5A5
+06 [300E] = FCC6 ?
+06 [300E] = E890 ?
+
+ [300C] <- AA55
+ [3006] <- 55AA
+07 [300E] = 1971 ?
+07 [300E] = 931E ?
+
+ [300C] <- 1000
+ [300C] <- 5678
+ [3008] <- 8765
+08 [300E] = ff88 ?
+08 [300E] = 0765 ?
+
+ [300C] <- 0200
+ [300C] <- FFFF
+ [300C] <- 55AA
+ [3008] <- FFFF
+09 [300E] = 002a ?
+09 [300E] = 01aa ?
+
+ [3752] <- AA55
+10 [3600] = AA55 ?
+
+ [3600] <- 55AA
+10 [3680] = 55AA ?
+
+11 [3680] = A55A ?
+12 [3600] = 55AA ?
+
+ [3754] <- 2DB5
+ [3A00] <- 0100
+13 [3600] = B6D4 ?
+
+ [3600] <- 2DB5
+ [3A00] <- 0200
+14 [3600] = 5B6A ?
+
+15 [3600] <- 2DB5
+ [3A00] <- 0400
+ [3600] = 2DB5 ?
+
+16 [3600] <- 2DB5
+ [3A00] <- 0800
+ [3600] = 96DA ?
+
+17 [3600] <- 2DB5
+ [3A00] <- 1000
+ [3600] = 4B6D ?
+
+18 [3600] <- 2DB5
+ [3A00] <- 2000
+ [3600] = A5B6 ?
+
+19 [3600] <- 1568
+ [3A00] <- 2000
+ [3E00] = 1BF2 ?
+
+1A [7A68] = 0000 ?
+
+1B [3680] <- AA55
+ [7A6A] = 55AA ?
+
+1C [3200] <- AA55
+ [300E] = E355 ?
+
+1D [3754] <- AA55
+ [7A6A] = 55AA ?
+
+1E [3680] <- AA55
+ [7A6A] = 55AA ?
+
+1F [7A6C] = AA55 ?
+
+20 [300E] = 1CAA ?
+
+21 [300C] <- 55AA
+ [3200] <- AA55
+ [300E] = E355 ?
+
+22 [3E00] = 14D5 ?
+23 [308C] <- 55AA
+ [7A70] = 15AA ?
+
+24 [7A6E] = 2000 ?
+25 [3600] = 42B5 ?
+26 [3E80] = 1CC2 ?
+27 [308E] = 099F ?
+28 [3680] = 4099 ?
+29 [3680] = 2D40 ?
+2A [3C00] = 5Cf4 ?
+2B [3600] = 5Cf4 ?
+2C [300C] <- 55AA
+ [3A80] = FFFF ?
+2D [300E] = FFFF ?
+2E [300E] = AA56 ?
+ [3600] <- 0000
+2F [4000] = 00BC ?
+30 [3600] = 0000 ?
+
+ [310C] <- 0078
+ [308C] <- 3F70
+40 [3680] = 0087 ?
+
+ [3600] <- 0020
+41 [3680] = 0100 ?
+
+ [3680] <- 533f
+42 [300e] = 0058 ?
+
+ [315c] <- 0020
+43 [7a72] = 0087 ?
+
+44 [3700] = 0080 ?
+
+ [300c] <- 00cc
+ [3000] <- 0074
+45 [308e] = 0000 ?
+
+46 [7a74] = 0078 ?
+ [308c] <- 0000
+47 [300e] = 00c5 ?
+
+ [300c] <- 0074
+ [3000] <- 008c
+48 [311e] = 0000 ?
+
+ [300c] <- 0224
+ [308c] <- 0000
+49 [300e] = 001c ?
+
+ [3724] <- 000c
+ [3000] <- 0078
+4a [300e] = 007c
+
+ [3728] <- 0023
+4b [3e80] = 0055 ?
+4c [3e00] = 0045 ?
+
+ [3600] <- fca2
+ [313c] <- 0118
+ [308c] <- ff42
+4d [300e] = 007e ?
+
+ [312c] <- 0040
+ [308c] <- 00f8
+4e [300e] = 0080 ?
+
+ [300c] <- 0261
+ [3130] <- 2000
+4f [3680] = 004c ?
+
+ [300c] <- 000f
+ [3008] <- e440
+50 [300e] = 0111 ?
+
+51 [7a7a] = 41fd ?
+ [3740] <- 010e
+
+52 [7a76] = 4000 ?
+53 [7a78] = 03a9 ?
+
+ [3280] <- 0800
+54 [3e00] = ff52 ?
+
+ [3680] <- 001e
+55 [3680] = ffcd ?
+
+56 [3600] = fff0 ?
+
+ [314c] <- 0091
+ [3680] <- 0300
+
+57 [3680] = 015e ?
+
+ [3680] <- 00d5
+ [3704] <- 0002
+58 [3600] = 0015 ?
+
+ [3600] <- 0086
+ [317c] <- 0013
+59 [300e] = 09f2 ?
+
+ [300c] <- 0010
+ [3120] <- 011c
+5a [300e] = 11c0 ?
+
+*/
+
+READ16_HANDLER(BB_AU_R)
+{
+UINT8 *AU_instr = (UINT8 *)memory_region(REGION_USER1);
+//UINT8 *AU_PROM1 = (UINT8 *)memory_region(REGION_PROMS) + 0x1700;
+//UINT8 *AU_PROM2 = (UINT8 *)memory_region(REGION_PROMS) + 0x1900;
+
+INT16 value = 0;
+
+ switch (offset)
+ {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7: MMI_74S516(offset, (UINT16*)AU_PTR); /* Typically Instruction 7 - read result(s) */
+ value = *AU_PTR;
+ break;
+
+ case 0x0e00/2: value = AU_instr[inst_index] | (AU_instr[inst_index] << 8);
+ break;
+
+ case 0x0680/2:
+ break; /* Use to change upper ROM address portion? */
+
+ case 0x0726/2:
+ break;
+
+ default: value = 0;
+ break;
+ }
+
+ return value;
+
+}
+
+WRITE16_HANDLER(BB_AU_W)
+{
+//UINT8 *AU_PROM1 = (UINT8 *)memory_region(REGION_PROMS) + 0x1700;
+//UINT8 *AU_PROM2 = (UINT8 *)memory_region(REGION_PROMS) + 0x1900;
+
+ switch (offset)
+ {
+
+ case 0x0: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR); /* Load values */
+ break;
+
+ case 0x1: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR);
+ break;
+
+ case 0x2: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR);
+ break;
+
+ case 0x3: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR);
+ break;
+
+ case 0x4: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR);
+ break;
+
+ case 0x5: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR);
+ break;
+
+ case 0x6: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR);
+ break;
+
+ case 0x7: COMBINE_DATA(AU_PTR);
+ MMI_74S516(offset, (UINT16*)AU_PTR);
+ break;
+
+ /* Accessing FN ROMs */
+ case 0x0600/2:
+ COMBINE_DATA(&inst_index);
+ break;
+
+
+ case 0x0680/2: break; /* Increment instruction PROM address */
+ case 0x0726/2: break;
+ }
+}
+
diff --git a/src/mame/machine/vertigo.c b/src/mame/machine/vertigo.c
new file mode 100644
index 00000000000..b1fd9bc8439
--- /dev/null
+++ b/src/mame/machine/vertigo.c
@@ -0,0 +1,228 @@
+/*************************************************************************
+
+ Exidy Vertigo hardware
+
+*************************************************************************/
+
+#include "driver.h"
+#include "vertigo.h"
+#include "exidy440.h"
+#include "machine/74148.h"
+#include "machine/pit8253.h"
+
+/*************************************
+ *
+ * Prototypes
+ *
+ *************************************/
+
+static void v_irq4_w(int level);
+static void v_irq3_w(int level);
+static void update_irq(void);
+
+
+/*************************************
+ *
+ * Statics
+ *
+ *************************************/
+
+/* Timestamp of last INTL4 change. The vector CPU runs for
+ the delta between this and now.
+*/
+static attotime irq4_time;
+
+/* State of the priority encoder output */
+static UINT8 irq_state;
+
+/* Result of the last ADC channel sampled */
+static UINT8 adc_result;
+
+/* 8254 timer config */
+static struct pit8253_config pit8254_config =
+{
+ TYPE8254,
+ {
+ {
+ 240000,
+ v_irq4_w,
+ NULL
+ }, {
+ 240000,
+ v_irq3_w,
+ NULL
+ }, {
+ 240000,
+ NULL,
+ NULL
+ }
+ }
+};
+
+static struct TTL74148_interface irq_encoder =
+{
+ update_irq
+};
+
+
+/*************************************
+ *
+ * IRQ handling. The priority encoder
+ * has to be emulated. Otherwise
+ * interrupts are lost.
+ *
+ *************************************/
+
+static void update_irq(void)
+{
+ if (irq_state < 7)
+ cpunum_set_input_line(0, irq_state ^ 7, CLEAR_LINE);
+
+ irq_state = TTL74148_output_r(0);
+
+ if (irq_state < 7)
+ cpunum_set_input_line(0, irq_state ^ 7, ASSERT_LINE);
+}
+
+static void update_irq_encoder(int line, int state)
+{
+ TTL74148_input_line_w(0, line, !state);
+ TTL74148_update(0);
+}
+
+static void v_irq4_w(int level)
+{
+ update_irq_encoder(INPUT_LINE_IRQ4, level);
+ vertigo_vproc(ATTOTIME_TO_CYCLES(0, attotime_sub(timer_get_time(), irq4_time)), level);
+ irq4_time = timer_get_time();
+}
+
+static void v_irq3_w(int level)
+{
+ if (level)
+ cpunum_set_input_line(1, INPUT_LINE_IRQ0, ASSERT_LINE);
+
+ update_irq_encoder(INPUT_LINE_IRQ3, level);
+}
+
+
+/*************************************
+ *
+ * ADC and coin handlers
+ *
+ *************************************/
+
+READ16_HANDLER( vertigo_io_convert )
+{
+ if (offset > 2)
+ adc_result = 0;
+ else
+ adc_result = readinputport(offset);
+
+ update_irq_encoder(INPUT_LINE_IRQ2, ASSERT_LINE);
+ return 0;
+}
+
+READ16_HANDLER( vertigo_io_adc )
+{
+ update_irq_encoder(INPUT_LINE_IRQ2, CLEAR_LINE);
+ return adc_result;
+}
+
+READ16_HANDLER( vertigo_coin_r )
+{
+ update_irq_encoder(INPUT_LINE_IRQ6, CLEAR_LINE);
+ return (readinputportbytag("COIN"));
+}
+
+INTERRUPT_GEN( vertigo_interrupt )
+{
+ /* Coin inputs cause IRQ6 */
+ if ((readinputportbytag("COIN") & 0x7) < 0x7)
+ update_irq_encoder(INPUT_LINE_IRQ6, ASSERT_LINE);
+}
+
+
+/*************************************
+ *
+ * Sound board interface
+ *
+ *************************************/
+
+WRITE16_HANDLER( vertigo_wsot_w )
+{
+ /* Reset sound cpu */
+ if ((data & 2) == 0)
+ cpunum_set_input_line(1, INPUT_LINE_RESET, ASSERT_LINE);
+ else
+ cpunum_set_input_line(1, INPUT_LINE_RESET, CLEAR_LINE);
+}
+
+static TIMER_CALLBACK( sound_command_w )
+{
+ exidy440_sound_command = param;
+ exidy440_sound_command_ack = 0;
+ cpunum_set_input_line(1, INPUT_LINE_IRQ1, ASSERT_LINE);
+
+ /* It is important that the sound cpu ACKs the sound command
+ quickly. Otherwise the main CPU gives up with sound. Boosting
+ the interleave for a while helps. */
+
+ cpu_boost_interleave(attotime_zero, ATTOTIME_IN_USEC(100));
+}
+
+WRITE16_HANDLER( vertigo_audio_w )
+{
+ if (ACCESSING_LSB)
+ timer_call_after_resynch(data & 0xff, sound_command_w);
+}
+
+READ16_HANDLER( vertigo_sio_r )
+{
+ if (exidy440_sound_command_ack)
+ return 0xfc;
+ else
+ return 0xfd;
+}
+
+/*************************************
+ *
+ * Machine initialization
+ *
+ *************************************/
+
+MACHINE_RESET( vertigo )
+{
+ int i;
+
+ TTL74148_config(0, &irq_encoder);
+ TTL74148_enable_input_w(0, 0);
+
+ for (i = 0; i < 8; i++)
+ TTL74148_input_line_w(0, i, 1);
+
+ TTL74148_update(0);
+ pit8253_init(1, &pit8254_config);
+ vertigo_vproc_init();
+
+ irq4_time = timer_get_time();
+ irq_state = 7;
+
+ state_save_register_global(irq_state);
+ state_save_register_global(adc_result);
+ state_save_register_global(irq4_time.seconds);
+ state_save_register_global(irq4_time.attoseconds);
+}
+
+
+/*************************************
+ *
+ * Motor controller interface
+ *
+ *************************************/
+
+WRITE16_HANDLER( vertigo_motor_w )
+{
+ /* Motor controller interface. Not emulated. */
+}
+
diff --git a/src/mame/machine/volfied.c b/src/mame/machine/volfied.c
new file mode 100644
index 00000000000..9936933f298
--- /dev/null
+++ b/src/mame/machine/volfied.c
@@ -0,0 +1,495 @@
+/*************************************************************************
+
+ Volfied C-Chip Protection
+ =========================
+
+ The C-Chip (Taito TC0030CMD) is an unidentified mask programmed
+ microcontroller of some sort with 64 pins. It probably has
+ about 2k of ROM and 8k of RAM.
+
+ Cheat:
+ volfied:0:100191:00:001:Complete level with 99.9% Now!
+ volfied:0:100192:99:501:Complete level with 99.9% Now! (2/3)
+ volfied:0:100193:09:501:Complete level with 99.9% Now! (3/3)
+
+*************************************************************************/
+
+#include "driver.h"
+
+static UINT8 current_bank = 0;
+static UINT8 current_flag = 0;
+static UINT8 cc_port = 0;
+static UINT8 current_cmd=0;
+static UINT8* cchip_ram=0;
+
+static const UINT16 palette_data_01[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x104a, 0xce41, 0x8c39, 0x5252, 0xd662, 0x4a31, 0x0000,
+ 0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x104a, 0xce41, 0x8c39, 0x5252, 0xd662, 0x4a31, 0x0000,
+ 0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xd62a, 0x1002, 0xce01, 0x5a3b, 0xde7b, 0x4a31, 0x0000,
+ 0x1e00, 0x1000, 0x9e01, 0x1e02, 0xde02, 0x0038, 0x0e38, 0x0000
+};
+
+static const UINT16 palette_data_02[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x4008, 0x0029, 0xc641, 0x4c52, 0x5473, 0xde7b, 0x1863,
+ 0x524a, 0xce39, 0x0821, 0x9c01, 0x1200, 0x8001, 0xc002, 0xce39,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
+ 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
+ 0x0000, 0x4208, 0x0c39, 0xd061, 0x547a, 0x1472, 0xde7b, 0xde7b,
+ 0x187b, 0x947a, 0x0821, 0x9e79, 0x1040, 0x8079, 0xc07a, 0x0000
+};
+
+static const UINT16 palette_data_03[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x4208, 0x0821,
+ 0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x1860, 0x1e78,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
+ 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
+ 0x0000, 0xc001, 0x4002, 0x8002, 0xc002, 0xc002, 0x0001, 0xc001,
+ 0x9201, 0xc002, 0xc003, 0x0003, 0x8002, 0x4001, 0xc002, 0x4003
+};
+
+static const UINT16 palette_data_04[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1042, 0xce39, 0x8c31, 0x524a, 0xd65a, 0x4a29, 0x0000,
+ 0x1e00, 0x1000, 0x8c21, 0xce29, 0x0039, 0x0038, 0x0e38, 0x0038,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0x1002, 0xce01, 0x8c01, 0x5202, 0xd602, 0x4a01, 0x0000,
+ 0x1e00, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const UINT16 palette_data_05[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1200, 0x1600, 0x1a00, 0x9e01, 0x8021, 0xc029, 0x0032,
+ 0x803a, 0x4208, 0x0821, 0x1042, 0xd65a, 0x9c73, 0xde03, 0x5c02,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0x5202, 0xd602, 0x5a03, 0xde03, 0x8021, 0xc029, 0x0032,
+ 0x803a, 0x4208, 0x0821, 0x1042, 0xd65a, 0x9c73, 0xde03, 0x5c02
+};
+
+static const UINT16 palette_data_06[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x9e52, 0x9028, 0x9428, 0x9828, 0x9e28, 0x4208, 0xde7b,
+ 0xde03, 0x9c02, 0xc03a, 0x0063, 0x586b, 0x9252, 0x8a31, 0x5e31,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0263, 0x9e52, 0x8058, 0x0879, 0x8c79, 0x107a, 0x4208, 0xde7b,
+ 0xde01, 0x1e01, 0xc03a, 0x0063, 0x586b, 0x9252, 0x8a31, 0x527a
+};
+
+static const UINT16 palette_data_07[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x4208, 0x0821,
+ 0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x1860, 0x1e78,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
+ 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
+ 0x0000, 0x8001, 0x0002, 0x8002, 0x0003, 0x8003, 0x4208, 0x0821,
+ 0x8c31, 0x1042, 0x9c73, 0x1e00, 0x5c02, 0x0c00, 0x1860, 0x1e78
+};
+
+static const UINT16 palette_data_08[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1042, 0xce39, 0x8c31, 0x524a, 0xd65a, 0x4a29, 0x0000,
+ 0x1e00, 0x1000, 0x9e01, 0x5e02, 0x5e03, 0x0038, 0x0e38, 0x0000,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0x5202, 0x1002, 0xce19, 0x9432, 0x1843, 0x8c11, 0x0000,
+ 0x1e00, 0x1000, 0x9e01, 0x5e02, 0x5e03, 0x0038, 0x0e38, 0x0000
+};
+
+static const UINT16 palette_data_09[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1048, 0x1250, 0x1458, 0x1660, 0xd418, 0x9e02, 0xc203,
+ 0x4208, 0x4a29, 0x8c31, 0x1042, 0x1e78, 0x166b, 0x0c38, 0x1868,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0x1600, 0x1a21, 0x5c29, 0xde39, 0xd418, 0x9e02, 0xc203,
+ 0x4208, 0x4a29, 0x8c31, 0x1042, 0x1e42, 0x186b, 0x9210, 0x9e31
+};
+
+static const UINT16 palette_data_0a[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0xde7b,
+ 0xc001, 0xc003, 0xde03, 0x1403, 0xcc01, 0x4a01, 0x0668, 0x4672,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0x0000, 0x0038, 0x4a29, 0x5401, 0x9c02, 0x9218, 0xde7b,
+ 0x0003, 0xc003, 0x5e02, 0xde01, 0x5201, 0xd200, 0x0668, 0x4672
+};
+
+static const UINT16 palette_data_0b[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0050, 0x8001, 0xc001, 0x0002, 0xc002, 0xd043, 0x9c73, 0x524a,
+ 0xce39, 0x8c31, 0x4208, 0xde03, 0x9c02, 0x1e60, 0x1a00, 0x1000,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0x8c01, 0xce01, 0x1002, 0xd62a, 0xde4b, 0x9c73, 0x5202,
+ 0xce01, 0x8c01, 0x4208, 0xde03, 0x9c02, 0x1e60, 0x1a00, 0x1000
+};
+
+static const UINT16 palette_data_0c[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0x9e52,
+ 0xc001, 0xc003, 0x1e00, 0x1400, 0x0c00, 0x4a01, 0x0668, 0x4672,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0x0000, 0x0038, 0x4a29, 0xce39, 0x9452, 0x9218, 0xde7b,
+ 0xc001, 0xc003, 0xde03, 0x1403, 0xcc01, 0x4a01, 0x0668, 0x4672
+};
+
+static const UINT16 palette_data_0d[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863,
+ 0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863,
+ 0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42,
+ 0x0000, 0x4208, 0x5029, 0x9431, 0xd839, 0x5a4a, 0x9e52, 0x5862,
+ 0xde4b, 0x8e39, 0x0821, 0x1600, 0x1000, 0xd201, 0x1e00, 0x0a42
+};
+
+static const UINT16 palette_data_0e[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0e01, 0x5001, 0x9201, 0xd401, 0x1602, 0x1200, 0x1600,
+ 0x4208, 0x0821, 0x8c31, 0x1042, 0x5a6b, 0x8001, 0x0002, 0x9a02,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x4a29, 0xce39, 0xde7b, 0x4001, 0x4002, 0xc003,
+ 0x9e01, 0x1e00, 0x0078, 0x0e00, 0x5401, 0x0040, 0xde03, 0x1600,
+ 0x0000, 0x8a21, 0x0a32, 0x4c3a, 0x8e4a, 0x504b, 0xd203, 0xc003,
+ 0x4208, 0x0821, 0x8c31, 0x1042, 0x5a6b, 0x8001, 0x0002, 0x545b
+};
+
+static const UINT16 palette_data_0f[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xc038, 0x4049, 0xc059, 0x406a, 0xc07a, 0x0000, 0x0821,
+ 0x9c31, 0x1042, 0x9c73, 0x1e02, 0x1a02, 0x0c00, 0x4002, 0xc001,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0xde7b, 0x1e00, 0xc003, 0x1042, 0xde03, 0x0000, 0xd65a,
+ 0xce39, 0x8c31, 0x4a29, 0x0078, 0xc07b, 0x1e02, 0x1e78, 0xc003,
+ 0x0000, 0xce00, 0x5201, 0xd601, 0x5a02, 0xde02, 0x0000, 0x0821,
+ 0x8c31, 0x1042, 0x9c73, 0x1e03, 0x1a02, 0x0c00, 0x9e01, 0x0e00
+};
+
+static const UINT16 palette_data_10[0x50] =
+{
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0601, 0x8a09, 0x0e1a, 0x922a, 0x163b, 0xde7b, 0xd65a,
+ 0xce39, 0x0821, 0x0000, 0x0c00, 0x5208, 0x1a02, 0x9e03, 0xce39,
+ 0x0000, 0xde7b, 0xde03, 0x5e01, 0x5e02, 0xc07b, 0x0000, 0xde7b,
+ 0x0058, 0x4079, 0x407a, 0x407b, 0xd47b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x1400, 0x8002, 0x0068, 0x0000, 0x5e01, 0x5e02, 0x1e03,
+ 0xde03, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39, 0xce39,
+ 0x0078, 0x4208, 0x1052, 0x9462, 0x1873, 0x5a73, 0xde7b, 0x1863,
+ 0x524a, 0xce39, 0x0821, 0x1600, 0x1000, 0xd201, 0xde03, 0x0a42
+};
+
+static const UINT16 palette_data_11[0x50] =
+{
+ 0x0000, 0x4a29, 0x8c31, 0xce39, 0x1042, 0x524a, 0x9452, 0xd65a,
+ 0x1863, 0x0000, 0xde39, 0xde7b, 0xc001, 0x8002, 0x1800, 0x1e00,
+ 0x0000, 0xde7b, 0x1e00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00,
+ 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00, 0x1e00,
+ 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03,
+ 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03, 0xde03,
+ 0xde03, 0x0e00, 0x9e4a, 0x0000, 0x1042, 0xde7b, 0x9452, 0x4a29,
+ 0xce39, 0x1c02, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+};
+
+static const UINT16* palette_data_lookup[] =
+{
+ 0,
+ palette_data_01,
+ palette_data_02,
+ palette_data_03,
+ palette_data_04,
+ palette_data_05,
+ palette_data_06,
+ palette_data_07,
+ palette_data_08,
+ palette_data_09,
+ palette_data_0a,
+ palette_data_0b,
+ palette_data_0c,
+ palette_data_0d,
+ palette_data_0e,
+ palette_data_0f,
+ palette_data_10,
+ palette_data_11
+};
+
+
+static TIMER_CALLBACK( timer_callback )
+{
+ // Palette commands - palette data written to bank 0: $10 - $af
+ if (current_cmd>=0x1 && current_cmd<0x12)
+ {
+ const UINT16* palette_data=palette_data_lookup[current_cmd];
+ int i=0;
+ for (i=0; i<0x50; i++)
+ {
+ cchip_ram[0x10 + i*2 + 0]=palette_data[i]>>8;
+ cchip_ram[0x10 + i*2 + 1]=palette_data[i]&0xff;
+ }
+ }
+
+ // Unknown command - result written to bank 0: $23
+ if (current_cmd>=0x81 && current_cmd<0x92)
+ {
+ switch (current_cmd)
+ {
+ case 0x81: cchip_ram[0x23]=0xf; break;
+ case 0x82: cchip_ram[0x23]=0x1; break;
+ case 0x83: cchip_ram[0x23]=0x6; break;
+ case 0x84: cchip_ram[0x23]=0xf; break;
+ case 0x85: cchip_ram[0x23]=0x9; break;
+ case 0x86: cchip_ram[0x23]=0x6; break;
+ case 0x87: cchip_ram[0x23]=0x6; break;
+ case 0x88: cchip_ram[0x23]=0xf; break;
+ case 0x89: cchip_ram[0x23]=0x8; break;
+ case 0x8a: cchip_ram[0x23]=0x1; break;
+ case 0x8b: cchip_ram[0x23]=0xa; break;
+ case 0x8c: cchip_ram[0x23]=0x1; break;
+ case 0x8d: cchip_ram[0x23]=0x1; break;
+ case 0x8e: cchip_ram[0x23]=0x8; break;
+ case 0x8f: cchip_ram[0x23]=0x6; break;
+ case 0x90: cchip_ram[0x23]=0xa; break;
+ case 0x91: cchip_ram[0x23]=0x0; break;
+ }
+ }
+
+ current_cmd=0;
+}
+
+/*************************************
+ *
+ * Writes to C-Chip - Important Bits
+ *
+ *************************************/
+
+WRITE16_HANDLER( volfied_cchip_ctrl_w )
+{
+ /* value 2 is written here */
+}
+
+WRITE16_HANDLER( volfied_cchip_bank_w )
+{
+ current_bank = data & 7;
+}
+
+WRITE16_HANDLER( volfied_cchip_ram_w )
+{
+ cchip_ram[(current_bank * 0x400) + offset]=data;
+
+// if (offset!=0x8)
+// logerror("%08x: volfied c write %04x %04x\n", activecpu_get_pc(), offset,data);
+
+ if (current_bank == 0)
+ {
+ if (offset == 0x008)
+ {
+ cc_port = data;
+
+ coin_lockout_w(1, data & 0x80);
+ coin_lockout_w(0, data & 0x40);
+ coin_counter_w(1, data & 0x20);
+ coin_counter_w(0, data & 0x10);
+ }
+
+ if (offset == 0x3fe)
+ {
+ /*******************
+ (This table stored in ROM at $146a8)
+ (Level number stored at $100198.b, from $100118.b, from $100098.b)
+ (Level number at $b34 stored to $100098.b)
+
+ round 01 => data $0A
+ round 02 => data $01
+ round 03 => data $03
+ round 04 => data $08
+ round 05 => data $05
+ round 06 => data $04
+ round 07 => data $0B
+ round 08 => data $09
+ round 09 => data $07
+ round 10 => data $06
+ round 11 => data $0E
+ round 12 => data $0D
+ round 13 => data $02
+ round 14 => data $0C
+ round 15 => data $0F
+ round 16 => data $10
+ final => data $11
+
+ ********************/
+
+ current_cmd = data;
+
+ // Palette request cmd - verified to take around 122242 68000 cycles to complete
+ if (current_cmd >= 0x1 && current_cmd < 0x12)
+ {
+ timer_set(ATTOTIME_IN_CYCLES(122242,0), 0, timer_callback);
+ }
+ // Unknown cmd - verified to take around 105500 68000 cycles to complete
+ else if (current_cmd >= 0x81 && current_cmd < 0x92)
+ {
+ timer_set(ATTOTIME_IN_CYCLES(105500,0), 0, timer_callback);
+ }
+ else
+ {
+ logerror("unknown cchip cmd %02x\n", data);
+ current_cmd=0;
+ }
+ }
+
+ // Some kind of timer command
+ if (offset == 0x3ff)
+ {
+ current_flag = data;
+ }
+ }
+}
+
+
+/*************************************
+ *
+ * Reads from C-Chip
+ *
+ *************************************/
+
+READ16_HANDLER( volfied_cchip_ctrl_r )
+{
+ /*
+ Bit 2 = Error signal
+ Bit 0 = Ready signal
+ */
+ return 0x01; /* Return 0x05 for C-Chip error */
+}
+
+READ16_HANDLER( volfied_cchip_ram_r )
+{
+ /* Check for input ports */
+ if (current_bank == 0)
+ {
+ switch (offset)
+ {
+ case 0x03: return readinputportbytag("F00007"); /* STARTn + SERVICE1 */
+ case 0x04: return readinputportbytag("F00009"); /* COINn */
+ case 0x05: return readinputportbytag("F0000B"); /* Player controls + TILT */
+ case 0x06: return readinputportbytag("F0000D"); /* Player controls (cocktail) */
+ case 0x08: return cc_port;
+ }
+ }
+
+// if (activecpu_get_pc()!=0x15ca8 && activecpu_get_pc()!=0x15cd8 && activecpu_get_pc()!=0x15cde)
+// logerror("%08x: volfied c read %04x (bank %04x)\n", activecpu_get_pc(), offset, current_bank);
+
+ /* Unknown */
+ if (current_bank == 2 && offset == 0x005)
+ {
+ /* Not fully understood - Game writes:
+ 0001a0c2: volfied c write 0005 00aa
+ 0001a0ca: volfied c write 0006 0055
+ 0001a0d2: volfied c write 0004 0065
+
+ Then expects 0x7c to replace the 0xaa some time later.
+ */
+ return 0x7c; /* makes worm in round 1 appear */
+ }
+
+ /* Unknown - some kind of timer */
+ if (current_bank == 0 && offset == 0x3ff)
+ {
+ return 2 * current_flag; /* fixes freeze after shield runs out */
+ }
+
+ /* Current command status */
+ if (current_bank == 0 && offset == 0x3fe)
+ {
+ return current_cmd;
+ }
+
+ return cchip_ram[(current_bank * 0x400) + offset];
+}
+
+
+/*************************************
+ *
+ * C-Chip State Saving
+ *
+ *************************************/
+
+void volfied_cchip_init(void)
+{
+ cchip_ram=auto_malloc(0x400 * 8);
+
+ state_save_register_global(current_bank);
+ state_save_register_global(current_cmd);
+ state_save_register_global(current_flag);
+ state_save_register_global(cc_port);
+ state_save_register_global_pointer(cchip_ram, 0x400 * 8);
+}
diff --git a/src/mame/machine/vsnes.c b/src/mame/machine/vsnes.c
new file mode 100644
index 00000000000..fbcdd2b03fa
--- /dev/null
+++ b/src/mame/machine/vsnes.c
@@ -0,0 +1,1361 @@
+/***************************************************************************
+
+Nintendo VS UniSystem and DualSystem - (c) 1984 Nintendo of America
+
+ Portions of this code are heavily based on
+ Brad Oliver's MESS implementation of the NES.
+
+***************************************************************************/
+
+#include "driver.h"
+#include "video/ppu2c0x.h"
+
+/* Globals */
+static int vsnes_gun_controller;
+static int vsnes_do_vrom_bank;
+
+/* Locals */
+static int input_latch[4];
+static UINT8 *remapped_colortable;
+
+static int sound_fix=0;
+/*************************************
+ *
+ * Color Mapping
+ *
+ *************************************/
+
+/* RP2C04-001 */
+/* check 0x08 */
+static UINT8 rp2c04001_colortable[] =
+{
+ 0x35, 0xff, 0x16, 0x22, 0x1c, 0xff, 0xff, 0x15, /* 0x00 - 0x07 */
+ 0x20, 0x00, 0x27, 0x05, 0x04, 0x27, 0x08, 0x30, /* 0x08 - 0x0f */
+ 0x21, 0xff, 0xff, 0x29, 0x3c, 0xff, 0x36, 0x12, /* 0x10 - 0x17 */
+ 0xff, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, /* 0x18 - 0x1f */
+ 0xff, 0x31, 0xff, 0x2a, 0x2c, 0x0c, 0xff, 0xff, /* 0x20 - 0x27 */
+ 0xff, 0x07, 0x34, 0x06, 0x13, 0xff, 0x26, 0x0f, /* 0x28 - 0x2f */
+ 0xff, 0x19, 0x10, 0x0a, 0xff, 0xff, 0xff, 0x17, /* 0x30 - 0x37 */
+ 0xff, 0x11, 0x09, 0xff, 0xff, 0x25, 0x18, 0xff /* 0x38 - 0x3f */
+};
+
+/* RP2C04-002 */
+/* 0x04, 0x24 */
+static UINT8 rp2c04002_colortable[] =
+{
+ 0xff, 0x27, 0x18, 0xff, 0x3a, 0x25, 0x2b, 0x31, /* 0x00 - 0x07 */
+ 0x15, 0x13, 0x38, 0x34, 0x20, 0x23, 0xff, 0x0b, /* 0x08 - 0x0f */
+ 0xff, 0x21, 0x06, 0xff, 0x1b, 0x29, 0xff, 0x22, /* 0x10 - 0x17 */
+ 0xff, 0x24, 0xff, 0xff, 0xff, 0x08, 0xff, 0x03, /* 0x18 - 0x1f */
+ 0xff, 0x36, 0x26, 0x33, 0x11, 0xff, 0x10, 0x02, /* 0x20 - 0x27 */
+ 0x14, 0xff, 0x10, 0x09, 0x12, 0x0f, 0xff, 0x30, /* 0x28 - 0x2f */
+ 0xff, 0xff, 0x2a, 0x17, 0x0c, 0x11, 0x15, 0x19, /* 0x30 - 0x37 */
+ 0xff, 0x2c, 0x07, 0x37, 0xff, 0x05, 0x3a, 0xff /* 0x38 - 0x3f */
+};
+
+/* RP2C04-003 */
+/* check 0x0f, 0x2e, 0x34 */
+static UINT8 rp2c04003_colortable[] =
+{
+ 0xff, 0xff, 0xff, 0x10, 0x1a, 0x30, 0x31, 0x09, /* 0x00 - 0x07 */
+ 0x01, 0x0f, 0x36, 0x08, 0x15, 0xff, 0xff, 0x30, /* 0x08 - 0x0f */
+ 0x22, 0x1c, 0xff, 0x12, 0x19, 0x18, 0x17, 0x2a, /* 0x10 - 0x17 */
+ 0x00, 0xff, 0xff, 0x02, 0x06, 0x07, 0xff, 0x35, /* 0x18 - 0x1f */
+ 0x23, 0xff, 0x8b, 0xf7, 0xff, 0x27, 0x26, 0x20, /* 0x20 - 0x27 */
+ 0x29, 0x03, 0x21, 0x24, 0x11, 0xff, 0xff, 0xff, /* 0x28 - 0x2f */
+ 0x2c, 0xff, 0xff, 0xff, 0x07, 0xf9, 0x28, 0xff, /* 0x30 - 0x37 */
+ 0x0a, 0xff, 0x32, 0x37, 0x13, 0x3a, 0xff, 0x0b /* 0x38 - 0x3f */
+};
+
+/* RP2C05-004 */
+/* check 0x03 0x1d, 0x38, 0x3b*/
+static UINT8 rp2c05004_colortable[] =
+{
+ 0x18, 0xff, 0x1c, 0x89, 0xff, 0xff, 0x01, 0x17, /* 0x00 - 0x07 */
+ 0x10, 0x0f, 0x2a, 0xff, 0x36, 0x37, 0x1a, 0xff, /* 0x08 - 0x0f */
+ 0x25, 0xff, 0x12, 0xff, 0x0f, 0xff, 0xff, 0x26, /* 0x10 - 0x17 */
+ 0xff, 0xff, 0x22, 0xff, 0xff, 0x0f, 0x3a, 0x21, /* 0x18 - 0x1f */
+ 0x05, 0x0a, 0x07, 0xc2, 0x13, 0xff, 0x00, 0x15, /* 0x20 - 0x27 */
+ 0x0c, 0xff, 0x11, 0xff, 0xff, 0x38, 0xff, 0xff, /* 0x28 - 0x2f */
+ 0xff, 0xff, 0x08, 0x45, 0xff, 0xff, 0x30, 0x3c, /* 0x30 - 0x37 */
+ 0x0f, 0x27, 0xff, 0x60, 0x29, 0xff, 0x30, 0x09 /* 0x38 - 0x3f */
+};
+
+
+
+/* remap callback */
+static int remap_colors( int num, int addr, int data )
+{
+ /* this is the protection. color codes are shuffled around */
+ /* the ones with value 0xff are unknown */
+
+ if ( addr >= 0x3f00 )
+ {
+ int newdata = remapped_colortable[ data & 0x3f ];
+
+ if ( newdata != 0xff )
+ data = newdata;
+
+ #ifdef MAME_DEBUG
+ else
+ popmessage( "Unmatched color %02x, at address %04x", data & 0x3f, addr );
+ #endif
+ }
+
+ return data;
+}
+
+/*************************************
+ *
+ * Input Ports
+ *
+ *************************************/
+WRITE8_HANDLER( vsnes_in0_w )
+{
+ /* Toggling bit 0 high then low resets both controllers */
+ if ( data & 1 )
+ {
+ /* load up the latches */
+ input_latch[0] = readinputport( 0 );
+ input_latch[1] = readinputport( 1 );
+ }
+}
+
+static READ8_HANDLER( gun_in0_r )
+{
+ int ret = ( input_latch[0] ) & 1;
+
+ /* shift */
+ input_latch[0] >>= 1;
+
+ ret |= readinputport( 2 ); /* merge coins, etc */
+ ret |= ( readinputport( 3 ) & 3 ) << 3; /* merge 2 dipswitches */
+
+/* The gun games expect a 1 returned on every 5th read after sound_fix is reset*/
+/* Info Supplied by Ben Parnell <xodnizel@home.com> of FCE Ultra fame */
+
+ if (sound_fix == 4)
+ {
+ ret = 1;
+ }
+
+ sound_fix++;
+
+ return ret;
+
+}
+
+
+READ8_HANDLER( vsnes_in0_r )
+{
+
+ int ret = ( input_latch[0] ) & 1;
+
+ /* shift */
+ input_latch[0] >>= 1;
+
+ ret |= readinputport( 2 ); /* merge coins, etc */
+ ret |= ( readinputport( 3 ) & 3 ) << 3; /* merge 2 dipswitches */
+
+ return ret;
+
+}
+
+
+READ8_HANDLER( vsnes_in1_r )
+{
+ int ret = ( input_latch[1] ) & 1;
+
+ ret |= readinputport( 3 ) & ~3; /* merge the rest of the dipswitches */
+
+ /* shift */
+ input_latch[1] >>= 1;
+
+ return ret;
+}
+
+WRITE8_HANDLER( vsnes_in0_1_w )
+{
+ /* Toggling bit 0 high then low resets both controllers */
+ if ( data & 1 )
+ {
+ /* load up the latches */
+ input_latch[2] = readinputport( 4 );
+ input_latch[3] = readinputport( 5 );
+ }
+}
+
+READ8_HANDLER( vsnes_in0_1_r )
+{
+ int ret = ( input_latch[2] ) & 1;
+
+ /* shift */
+ input_latch[2] >>= 1;
+
+ ret |= readinputport( 6 ); /* merge coins, etc */
+ ret |= ( readinputport( 7 ) & 3 ) << 3; /* merge 2 dipswitches */
+ return ret;
+}
+
+READ8_HANDLER( vsnes_in1_1_r )
+{
+ int ret = ( input_latch[3] ) & 1;
+
+ ret |= readinputport( 7 ) & ~3; /* merge the rest of the dipswitches */
+
+ /* shift */
+ input_latch[3] >>= 1;
+
+ return ret;
+
+}
+
+/*************************************
+ *
+ * Init machine
+ *
+ *************************************/
+
+MACHINE_RESET( vsnes )
+{
+ input_latch[0] = input_latch[1] = 0;
+ input_latch[2] = input_latch[3] = 0;
+
+ /* reset the ppu */
+ ppu2c0x_reset( 0, 1 );
+
+ /* if we need to remap, install the callback */
+ if ( remapped_colortable )
+ ppu2c0x_set_vidaccess_callback( 0, remap_colors );
+}
+
+/*************************************
+ *
+ * Init machine
+ *
+ *************************************/
+MACHINE_RESET( vsdual )
+{
+ input_latch[0] = input_latch[1] = 0;
+ input_latch[2] = input_latch[3] = 0;
+
+ /* reset the ppu */
+ ppu2c0x_reset( 0,1);
+ ppu2c0x_reset( 1,1 );
+
+ /* if we need to remap, install the callback */
+ if ( remapped_colortable )
+ {
+ ppu2c0x_set_vidaccess_callback( 0, remap_colors );
+ ppu2c0x_set_vidaccess_callback( 1, remap_colors );
+ }
+}
+
+/*************************************
+ *
+ * Common init for all games
+ *
+ *************************************/
+static void init_vsnes(running_machine *machine)
+{
+ /* set the controller to default */
+ vsnes_gun_controller = 0;
+
+ /* no color remapping */
+ remapped_colortable = 0;
+}
+
+/**********************************************************************************
+ *
+ * Game and Board-specific initialization
+ *
+ **********************************************************************************/
+
+static WRITE8_HANDLER( vsnormal_vrom_banking )
+{
+ /* switch vrom */
+ ppu2c0x_set_videorom_bank( 0, 0, 8, ( data & 4 ) ? 1 : 0, 512 );
+
+ /* bit 1 ( data & 2 ) enables writes to extra ram, we ignore it */
+
+ /* move along */
+ vsnes_in0_w( offset, data );
+}
+
+/* Most games switch VROM Banks in controller 0 write */
+/* they dont do any other trickery */
+DRIVER_INIT( vsnormal )
+{
+ /* vrom switching is enabled with bit 2 of $4016 */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, vsnormal_vrom_banking );
+}
+
+static WRITE8_HANDLER( ppuRC2C05_protection )
+{
+ /* This PPU has registers mapped at $2000 and $2001 inverted */
+ /* and no remapped color */
+
+ if ( offset == 0 )
+ {
+ ppu2c0x_0_w( 1, data );
+ return;
+ }
+
+ ppu2c0x_0_w( 0, data );
+}
+
+/**********************************************************************************/
+
+/* Super Mario Bros. Extra ram at $6000 (NV?) and remapped colors */
+
+DRIVER_INIT( suprmrio )
+{
+ /* common init */
+ init_vsnes(machine);
+
+ /* normal banking */
+ driver_init_vsnormal(machine);
+
+ /* extra ram at $6000 is enabled with bit 1 of $4016 */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ /* now override the vidaccess callback */
+ /* we need to remap color tables */
+ /* this *is* the VS games protection, I guess */
+ remapped_colortable = rp2c05004_colortable;
+}
+
+/**********************************************************************************/
+
+/* Gun Games - VROM Banking in controller 0 write */
+
+static WRITE8_HANDLER( gun_in0_w )
+{
+ static int zapstore;
+
+ if (vsnes_do_vrom_bank)
+ {
+ /* switch vrom */
+ ppu2c0x_set_videorom_bank( 0, 0, 8, ( data & 4 ) ? 1 : 0, 512 );
+ }
+
+ /* here we do things a little different */
+ if ( data & 1 )
+ {
+
+ /* load up the latches */
+ input_latch[0] = readinputport( 0 );
+
+ /* do the gun thing */
+ if ( vsnes_gun_controller )
+ {
+ int x = readinputport( 4 );
+ int y = readinputport( 5 );
+ UINT32 pix, color_base;
+ const pen_t *pens = Machine->pens;
+
+ /* get the pixel at the gun position */
+ pix = ppu2c0x_get_pixel( 0, x, y );
+
+ /* get the color base from the ppu */
+ color_base = ppu2c0x_get_colorbase( 0 );
+
+ /* look at the screen and see if the cursor is over a bright pixel */
+ if ( ( pix == pens[color_base+0x20] ) || ( pix == pens[color_base+0x30] ) ||
+ ( pix == pens[color_base+0x33] ) || ( pix == pens[color_base+0x34] ) )
+ {
+ input_latch[0] |= 0x40;
+ }
+ }
+
+ input_latch[1] = readinputport( 1 );
+ }
+
+ if ( ( zapstore & 1 ) && ( !( data & 1 ) ) )
+ /* reset sound_fix to keep sound from hanging */
+ {
+ sound_fix = 0;
+ }
+
+ zapstore = data;
+}
+
+DRIVER_INIT( duckhunt )
+{
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, gun_in0_r);
+ /* vrom switching is enabled with bit 2 of $4016 */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, gun_in0_w );
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* enable gun controller */
+ vsnes_gun_controller = 1;
+ vsnes_do_vrom_bank = 1;
+}
+
+/**********************************************************************************/
+
+/* The Goonies, VS Gradius: ROMs bankings at $8000-$ffff */
+
+static WRITE8_HANDLER( goonies_rom_banking )
+{
+ int reg = ( offset >> 12 ) & 0x07;
+ int bankoffset = ( data & 7 ) * 0x2000 + 0x10000;
+
+ switch( reg )
+ {
+ case 0: /* code bank 0 */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[bankoffset], 0x2000 );
+ break;
+
+ case 2: /* code bank 1 */
+ memcpy( &memory_region( REGION_CPU1 )[0x0a000], &memory_region( REGION_CPU1 )[bankoffset], 0x2000 );
+ break;
+
+ case 4: /* code bank 2 */
+ memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_CPU1 )[bankoffset], 0x2000 );
+ break;
+
+ case 6: /* vrom bank 0 */
+ ppu2c0x_set_videorom_bank( 0, 0, 4, data, 256 );
+ break;
+
+ case 7: /* vrom bank 1 */
+ ppu2c0x_set_videorom_bank( 0, 4, 4, data, 256 );
+ break;
+ }
+}
+
+DRIVER_INIT( goonies )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x18000], 0x8000 );
+
+ /* banking is done with writes to the $8000-$ffff area */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, goonies_rom_banking );
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* now override the vidaccess callback */
+ remapped_colortable = rp2c04003_colortable;
+}
+
+DRIVER_INIT( vsgradus )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x18000], 0x8000 );
+
+ /* banking is done with writes to the $8000-$ffff area */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, goonies_rom_banking );
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* now override the vidaccess callback */
+ remapped_colortable = rp2c04001_colortable;
+}
+
+DRIVER_INIT( vspinbal )
+{
+ /* common init */
+ init_vsnes(machine);
+
+ /* normal banking */
+ driver_init_vsnormal(machine);
+
+ /* now override the vidaccess callback */
+ remapped_colortable = rp2c04001_colortable;
+
+}
+
+DRIVER_INIT( hogalley )
+{
+
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, gun_in0_r);
+ /* vrom switching is enabled with bit 2 of $4016 */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, gun_in0_w );
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* enable gun controller */
+ vsnes_gun_controller = 1;
+ vsnes_do_vrom_bank = 1;
+
+ /* now override the vidaccess callback */
+ remapped_colortable = rp2c04001_colortable;
+}
+
+/***********************************************************************/
+
+/* Vs. Gumshoe */
+
+static READ8_HANDLER( vsgshoe_security_r )
+{
+ /* low part must be 0x1c */
+ return ppu2c0x_0_r( 2 ) | 0x1c;
+}
+
+static WRITE8_HANDLER( vsgshoe_gun_in0_w )
+{
+ static int old_bank = 0;
+ int addr;
+ if((data & 0x04) != old_bank)
+ {
+ old_bank = data & 0x04;
+ addr = old_bank ? 0x12000: 0x10000;
+ memcpy (&memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[addr], 0x2000);
+ }
+
+ gun_in0_w(offset, data);
+}
+
+DRIVER_INIT( vsgshoe )
+{
+ /* set up the default bank */
+ memcpy (&memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x12000], 0x2000);
+
+ /* Protection */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2002, 0x2002, 0, 0, vsgshoe_security_r );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2000, 0x2001, 0, 0, ppuRC2C05_protection );
+
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, gun_in0_r);
+ /* vrom switching is enabled with bit 2 of $4016 */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, vsgshoe_gun_in0_w );
+
+ /* common init */
+ init_vsnes(machine);
+
+ vsnes_gun_controller = 1;
+ vsnes_do_vrom_bank = 1;
+}
+
+/**********************************************************************************/
+
+/* Dr Mario: ROMs bankings at $8000-$ffff */
+
+static int drmario_shiftreg;
+static int drmario_shiftcount;
+
+static WRITE8_HANDLER( drmario_rom_banking )
+{
+ /* basically, a MMC1 mapper from the nes */
+ static int size16k, switchlow, vrom4k;
+
+ int reg = ( offset >> 13 );
+
+ /* reset mapper */
+ if ( data & 0x80 )
+ {
+ drmario_shiftreg = drmario_shiftcount = 0;
+
+ size16k = 1;
+
+ switchlow = 1;
+ vrom4k = 0;
+
+ return;
+ }
+
+ /* see if we need to clock in data */
+ if ( drmario_shiftcount < 5 )
+ {
+ drmario_shiftreg >>= 1;
+ drmario_shiftreg |= ( data & 1 ) << 4;
+ drmario_shiftcount++;
+ }
+
+ /* are we done shifting? */
+ if ( drmario_shiftcount == 5 )
+ {
+ /* reset count */
+ drmario_shiftcount = 0;
+
+ /* apply data to registers */
+ switch( reg )
+ {
+ case 0: /* mirroring and options */
+ {
+ int mirroring;
+
+ vrom4k = drmario_shiftreg & 0x10;
+ size16k = drmario_shiftreg & 0x08;
+ switchlow = drmario_shiftreg & 0x04;
+
+ switch( drmario_shiftreg & 3 )
+ {
+ case 0:
+ mirroring = PPU_MIRROR_LOW;
+ break;
+
+ case 1:
+ mirroring = PPU_MIRROR_HIGH;
+ break;
+
+ case 2:
+ mirroring = PPU_MIRROR_VERT;
+ break;
+
+ default:
+ case 3:
+ mirroring = PPU_MIRROR_HORZ;
+ break;
+ }
+
+ /* apply mirroring */
+ ppu2c0x_set_mirroring( 0, mirroring );
+ }
+ break;
+
+ case 1: /* video rom banking - bank 0 - 4k or 8k */
+ ppu2c0x_set_videorom_bank( 0, 0, ( vrom4k ) ? 4 : 8, drmario_shiftreg, ( vrom4k ) ? 256 : 512 );
+ break;
+
+ case 2: /* video rom banking - bank 1 - 4k only */
+ if ( vrom4k )
+ ppu2c0x_set_videorom_bank( 0, 4, 4, drmario_shiftreg, 256 );
+ break;
+
+ case 3: /* program banking */
+ {
+ int bank = ( drmario_shiftreg & 0x03 ) * 0x4000;
+
+ if ( !size16k )
+ {
+ /* switch 32k */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x010000+bank], 0x8000 );
+ }
+ else
+ {
+ /* switch 16k */
+ if ( switchlow )
+ {
+ /* low */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x010000+bank], 0x4000 );
+ }
+ else
+ {
+ /* high */
+ memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_CPU1 )[0x010000+bank], 0x4000 );
+ }
+ }
+ }
+ break;
+ }
+
+ drmario_shiftreg = 0;
+ }
+}
+
+DRIVER_INIT( drmario )
+{
+ /* We do manual banking, in case the code falls through */
+ /* Copy the initial banks */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x10000], 0x4000 );
+ memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_CPU1 )[0x1c000], 0x4000 );
+
+ /* MMC1 mapper at writes to $8000-$ffff */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, drmario_rom_banking );
+
+ drmario_shiftreg = 0;
+ drmario_shiftcount = 0;
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* now override the vidaccess callback */
+ remapped_colortable = rp2c04003_colortable;
+}
+
+/***********************************************************************/
+
+/* Excite Bike */
+
+DRIVER_INIT( excitebk )
+{
+ /* common init */
+ init_vsnes(machine);
+
+ /* normal banking */
+ driver_init_vsnormal(machine);
+
+ /* now override the vidaccess callback */
+ /* we need to remap color tables */
+ /* this *is* the VS games protection, I guess */
+ remapped_colortable = rp2c04003_colortable;
+}
+
+DRIVER_INIT( excitbkj )
+{
+ /* common init */
+ init_vsnes(machine);
+
+ /* normal banking */
+ driver_init_vsnormal(machine);
+
+ /* now override the vidaccess callback */
+ /* we need to remap color tables */
+ /* this *is* the VS games protection, I guess */
+ remapped_colortable = rp2c05004_colortable;
+}
+
+/**********************************************************************************/
+
+/* Mach Rider */
+
+DRIVER_INIT( machridr )
+{
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* normal banking */
+ driver_init_vsnormal(machine);
+
+ /* now override the vidaccess callback */
+ /* we need to remap color tables */
+ /* this *is* the VS games protection, I guess */
+ remapped_colortable = rp2c04002_colortable;
+}
+
+/**********************************************************************************/
+
+/* VS Slalom */
+
+DRIVER_INIT( vsslalom )
+{
+ /* common init */
+ init_vsnes(machine);
+
+ /* now override the vidaccess callback */
+ /* we need to remap color tables */
+ /* this *is* the VS games protection, I guess */
+ remapped_colortable = rp2c04002_colortable;
+}
+
+/**********************************************************************************/
+
+/* Castelvania: ROMs bankings at $8000-$ffff */
+
+static WRITE8_HANDLER( castlevania_rom_banking )
+{
+ int rombank = 0x10000 + ( data & 7 ) * 0x4000;
+
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[rombank], 0x4000 );
+}
+
+DRIVER_INIT( cstlevna )
+{
+ /* when starting the game, the 1st 16k and the last 16k are loaded into the 2 banks */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x28000], 0x8000 );
+
+ /* banking is done with writes to the $8000-$ffff area */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, castlevania_rom_banking );
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* now override the vidaccess callback */
+ /* we need to remap color tables */
+ /* this *is* the VS games protection, I guess */
+ remapped_colortable = rp2c04002_colortable;
+}
+
+/**********************************************************************************/
+
+/* VS Top Gun: ROMs bankings at $8000-$ffff, plus some protection */
+
+static READ8_HANDLER( topgun_security_r )
+{
+ /* low part must be 0x1b */
+ return ppu2c0x_0_r( 2 ) | 0x1b;
+}
+
+DRIVER_INIT( topgun )
+{
+ /* when starting the game, the 1st 16k and the last 16k are loaded into the 2 banks */
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x28000], 0x8000 );
+
+ /* banking is done with writes to the $8000-$ffff area */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, castlevania_rom_banking );
+
+ /* tap on the PPU, due to some tricky protection */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2002, 0x2002, 0, 0, topgun_security_r );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2000, 0x2001, 0, 0, ppuRC2C05_protection );
+
+ /* common init */
+ init_vsnes(machine);
+}
+
+/**********************************************************************************/
+
+static int MMC3_cmd, MMC3_prg0, MMC3_prg1;
+static int MMC3_chr[6];
+static int MMC3_prg_chunks, MMC3_prg_mask;
+static int IRQ_enable, IRQ_count, IRQ_count_latch;
+
+static void mapper4_set_prg (void)
+{
+ MMC3_prg0 &= MMC3_prg_mask;
+ MMC3_prg1 &= MMC3_prg_mask;
+
+ if (MMC3_cmd & 0x40)
+ {
+ memcpy( &memory_region( REGION_CPU1 )[0x8000], &memory_region( REGION_CPU1 )[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 );
+ memcpy( &memory_region( REGION_CPU1 )[0xc000], &memory_region( REGION_CPU1 )[0x2000 * (MMC3_prg0) + 0x10000], 0x2000 );
+ }
+ else
+ {
+ memcpy( &memory_region( REGION_CPU1 )[0x8000], &memory_region( REGION_CPU1 )[0x2000 * (MMC3_prg0) + 0x10000], 0x2000 );
+ memcpy( &memory_region( REGION_CPU1 )[0xc000], &memory_region( REGION_CPU1 )[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 );
+ }
+ memcpy( &memory_region( REGION_CPU1 )[0xa000], &memory_region( REGION_CPU1 )[0x2000 * (MMC3_prg1) + 0x10000], 0x2000 );
+}
+
+static void mapper4_set_chr (void)
+{
+ UINT8 chr_page = (MMC3_cmd & 0x80) >> 5;
+ ppu2c0x_set_videorom_bank(0, chr_page ^ 0, 2, MMC3_chr[0], 1);
+ ppu2c0x_set_videorom_bank(0, chr_page ^ 2, 2, MMC3_chr[1], 1);
+ ppu2c0x_set_videorom_bank(0, chr_page ^ 4, 1, MMC3_chr[2], 1);
+ ppu2c0x_set_videorom_bank(0, chr_page ^ 5, 1, MMC3_chr[3], 1);
+ ppu2c0x_set_videorom_bank(0, chr_page ^ 6, 1, MMC3_chr[4], 1);
+ ppu2c0x_set_videorom_bank(0, chr_page ^ 7, 1, MMC3_chr[5], 1);
+}
+
+#define BOTTOM_VISIBLE_SCANLINE 239 /* The bottommost visible scanline */
+#define NUM_SCANLINE 262
+
+static void mapper4_irq ( int num, int scanline, int vblank, int blanked )
+{
+ mame_printf_debug("entra\n");
+ if ((scanline < BOTTOM_VISIBLE_SCANLINE) || (scanline == NUM_SCANLINE-1))
+ {
+ if ((IRQ_enable) && !blanked)
+ {
+ if (IRQ_count == 0)
+ {
+ IRQ_count = IRQ_count_latch;
+ cpunum_set_input_line (0, 0, HOLD_LINE);
+ }
+ IRQ_count --;
+ }
+ }
+}
+
+static WRITE8_HANDLER( mapper4_w )
+{
+ static UINT8 last_bank = 0xff;
+
+ switch (offset & 0x7001)
+ {
+ case 0x0000: /* $8000 */
+ MMC3_cmd = data;
+
+ /* Toggle between switching $8000 and $c000 */
+ if (last_bank != (data & 0xc0))
+ {
+ /* Reset the banks */
+ mapper4_set_prg ();
+ mapper4_set_chr ();
+
+ }
+ last_bank = data & 0xc0;
+ break;
+
+ case 0x0001: /* $8001 */
+ {
+ UINT8 cmd = MMC3_cmd & 0x07;
+ switch (cmd)
+ {
+ case 0: case 1:
+ data &= 0xfe;
+ MMC3_chr[cmd] = data * 64;
+ mapper4_set_chr ();
+
+ break;
+
+ case 2: case 3: case 4: case 5:
+ MMC3_chr[cmd] = data * 64;
+ mapper4_set_chr ();
+
+ break;
+
+ case 6:
+ MMC3_prg0 = data;
+ mapper4_set_prg ();
+ break;
+
+ case 7:
+ MMC3_prg1 = data;
+ mapper4_set_prg ();
+ break;
+ }
+ break;
+ }
+ case 0x2000: /* $a000 */
+ if (data & 0x40)
+ ppu2c0x_set_mirroring(0, PPU_MIRROR_HIGH);
+ else
+ {
+ if (data & 0x01)
+ ppu2c0x_set_mirroring(0, PPU_MIRROR_HORZ);
+ else
+ ppu2c0x_set_mirroring(0, PPU_MIRROR_VERT);
+ }
+ break;
+
+ case 0x2001: /* $a001 - extra RAM enable/disable */
+ /* ignored - we always enable it */
+
+ break;
+
+ case 0x4000: /* $c000 - IRQ scanline counter */
+ IRQ_count = data;
+
+ break;
+
+ case 0x4001: /* $c001 - IRQ scanline latch */
+ IRQ_count_latch = data;
+
+ break;
+
+ case 0x6000: /* $e000 - Disable IRQs */
+ IRQ_enable = 0;
+ IRQ_count = IRQ_count_latch;
+
+ ppu2c0x_set_scanline_callback (0, 0);
+
+ break;
+
+ case 0x6001: /* $e001 - Enable IRQs */
+ IRQ_enable = 1;
+ ppu2c0x_set_scanline_callback (0, mapper4_irq);
+
+ break;
+
+ default:
+ logerror("mapper4_w uncaught: %04x value: %02x\n", offset + 0x8000, data);
+ break;
+ }
+}
+
+/* Common init for MMC3 games */
+
+DRIVER_INIT( MMC3 )
+{
+ IRQ_enable = IRQ_count = IRQ_count_latch = 0;
+ MMC3_prg0 = 0xfe;
+ MMC3_prg1 = 0xff;
+ MMC3_cmd = 0;
+
+ MMC3_prg_chunks = (memory_region_length(REGION_CPU1) - 0x10000) / 0x4000;
+
+ MMC3_prg_mask = ((MMC3_prg_chunks << 1) - 1);
+
+ memcpy( &memory_region( REGION_CPU1 )[0x8000], &memory_region( REGION_CPU1 )[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 );
+ memcpy( &memory_region( REGION_CPU1 )[0xa000], &memory_region( REGION_CPU1 )[(MMC3_prg_chunks-1) * 0x4000 + 0x12000], 0x2000 );
+ memcpy( &memory_region( REGION_CPU1 )[0xc000], &memory_region( REGION_CPU1 )[(MMC3_prg_chunks-1) * 0x4000 + 0x10000], 0x2000 );
+ memcpy( &memory_region( REGION_CPU1 )[0xe000], &memory_region( REGION_CPU1 )[(MMC3_prg_chunks-1) * 0x4000 + 0x12000], 0x2000 );
+
+ /* MMC3 mapper at writes to $8000-$ffff */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, mapper4_w );
+
+ /* extra ram at $6000-$7fff */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ /* common init */
+ init_vsnes(machine);
+}
+
+/* Vs. RBI Baseball */
+
+static READ8_HANDLER( rbi_hack_r)
+{
+ /* Supplied by Ben Parnell <xodnizel@home.com> of FCE Ultra fame */
+
+ static int VSindex;
+
+ if (offset == 0)
+ {
+ VSindex=0;
+ return 0xFF;
+
+ }
+ else
+ {
+ switch(VSindex++)
+ {
+ case 9:
+ return 0x6F;
+ break;
+
+ case 14:
+ return 0x94;
+ break;
+
+ default:
+ return 0xB4;
+ break;
+ }
+ }
+}
+
+DRIVER_INIT( rbibb )
+{
+ driver_init_MMC3(machine);
+
+ /* RBI Base ball hack */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5e00, 0x5e01, 0, 0, rbi_hack_r) ;
+
+ remapped_colortable = rp2c04003_colortable;
+}
+
+/* Vs. Super Xevious */
+
+static int supxevs_prot_index = 0;
+
+static READ8_HANDLER( supxevs_read_prot_1_r )
+{
+ return 0x05;
+}
+
+static READ8_HANDLER( supxevs_read_prot_2_r )
+{
+ if( supxevs_prot_index )
+ return 0;
+ else
+ return 0x01;
+}
+
+static READ8_HANDLER( supxevs_read_prot_3_r )
+{
+ if( supxevs_prot_index )
+ return 0xd1;
+ else
+ return 0x89;
+}
+
+static READ8_HANDLER( supxevs_read_prot_4_r )
+{
+ if( supxevs_prot_index )
+ {
+ supxevs_prot_index = 0;
+ return 0x3e;
+ }
+ else
+ {
+ supxevs_prot_index = 1;
+ return 0x37;
+ }
+}
+
+
+DRIVER_INIT( supxevs )
+{
+ driver_init_MMC3(machine);
+
+ /* Vs. Super Xevious Protection */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x54ff, 0x54ff, 0, 0, supxevs_read_prot_1_r );
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5678, 0x5678, 0, 0, supxevs_read_prot_2_r );
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x578f, 0x578f, 0, 0, supxevs_read_prot_3_r );
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5567, 0x5567, 0, 0, supxevs_read_prot_4_r );
+
+ remapped_colortable = rp2c04001_colortable;
+}
+
+/* Vs. TKO Boxing */
+
+static READ8_HANDLER( tko_security_r )
+{
+ static int security_counter;
+ static UINT8 security_data[] = {
+ 0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,
+ 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,
+ 0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,
+ 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00
+ };
+
+ if ( offset == 0 )
+ {
+ security_counter = 0;
+ return 0;
+ }
+
+ return security_data[(security_counter++)];
+
+}
+
+DRIVER_INIT( tkoboxng )
+{
+ driver_init_MMC3(machine);
+
+ /* security device at $5e00-$5e01 */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x5e00, 0x5e01, 0, 0, tko_security_r );
+
+ /* now override the vidaccess callback */
+ /* we need to remap color tables */
+ /* this *is* the VS games protection, I guess */
+ remapped_colortable = rp2c04003_colortable;
+}
+
+/* Vs. Freedom Force */
+
+DRIVER_INIT( vsfdf )
+{
+ driver_init_MMC3(machine);
+
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, gun_in0_r );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, gun_in0_w );
+
+ vsnes_gun_controller = 1;
+ vsnes_do_vrom_bank = 0;
+
+ remapped_colortable = rp2c04001_colortable;
+}
+
+/**********************************************************************************/
+/* Platoon rom banking */
+
+static WRITE8_HANDLER( mapper68_rom_banking ){
+
+ switch (offset & 0x7000)
+ {
+ case 0x0000:
+ ppu2c0x_set_videorom_bank(0,0,2,data,128);
+
+ break;
+ case 0x1000:
+ ppu2c0x_set_videorom_bank(0,2,2,data,128);
+
+ break;
+ case 0x2000:
+ ppu2c0x_set_videorom_bank(0,4,2,data,128);
+
+ break;
+ case 0x3000: /* ok? */
+ ppu2c0x_set_videorom_bank(0,6,2,data,128);
+
+ break;
+
+ case 0x7000:
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x10000 +data*0x4000], 0x4000 );
+ break;
+
+ }
+
+}
+
+DRIVER_INIT( platoon )
+{
+
+ /* when starting a mapper 68 game the first 16K ROM bank in the cart is loaded into $8000
+ the LAST 16K ROM bank is loaded into $C000. The last 16K of ROM cannot be swapped. */
+
+ memcpy( &memory_region( REGION_CPU1 )[0x08000], &memory_region( REGION_CPU1 )[0x10000], 0x4000 );
+ memcpy( &memory_region( REGION_CPU1 )[0x0c000], &memory_region( REGION_CPU1 )[0x2c000], 0x4000 );
+
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0xffff, 0, 0, mapper68_rom_banking );
+
+ init_vsnes(machine);
+
+ remapped_colortable = rp2c04001_colortable;
+
+}
+
+/**********************************************************************************/
+/* Vs. Raid on Bungeling Bay (Japan) */
+
+static int ret;
+static WRITE8_HANDLER ( set_bnglngby_irq_w )
+{
+ ret = data;
+ cpunum_set_input_line( 0, 0, ( data & 2 ) ? ASSERT_LINE : CLEAR_LINE );
+ /* other values ??? */
+ /* 0, 4, 84 */
+}
+
+static READ8_HANDLER ( set_bnglngby_irq_r )
+{
+ return ret;
+}
+
+DRIVER_INIT( bnglngby )
+{
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0231, 0x0231, 0, 0, set_bnglngby_irq_r );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0231, 0x0231, 0, 0, set_bnglngby_irq_w );
+
+ /* extra ram */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ ret = 0;
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* normal banking */
+ driver_init_vsnormal(machine);
+
+ remapped_colortable = rp2c04002_colortable;
+}
+
+/**********************************************************************************/
+/* Vs. Ninja Jajamaru Kun */
+
+static READ8_HANDLER( jajamaru_security_r )
+{
+ /* low part must be 0x40 */
+ return ppu2c0x_0_r( 2 ) | 0x40;
+}
+
+DRIVER_INIT( jajamaru )
+{
+ //It executes an illegal opcode: 0x04 at 0x9e67 and 0x9e1c
+ //At 0x9e5d and 0x9e12 there is a conditional jump to it
+ //Maybe it should be a DOP (double NOP)
+
+ /* Protection */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2002, 0x2002, 0, 0, jajamaru_security_r );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2000, 0x2001, 0, 0, ppuRC2C05_protection );
+
+ /* common init */
+ init_vsnes(machine);
+
+ /* normal banking */
+ driver_init_vsnormal(machine);
+}
+
+/***********************************************************************/
+
+/* Vs. Mighty Bomb Jack */
+
+static READ8_HANDLER( mightybj_security_r )
+{
+ /* low part must be 0x3d */
+ return ppu2c0x_0_r( 2 ) | 0x3d;
+}
+
+DRIVER_INIT( mightybj )
+{
+ /* Protection */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2002, 0x2002, 0, 0, mightybj_security_r );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x2000, 0x2001, 0, 0, ppuRC2C05_protection );
+
+ /* common init */
+ init_vsnes(machine);
+}
+
+/**********************************************************************************/
+/* VS Tennis */
+
+static WRITE8_HANDLER( vstennis_vrom_banking )
+{
+ int other_cpu = cpu_getactivecpu() ^ 1;
+
+ /* switch vrom */
+ ppu2c0x_set_videorom_bank( cpu_getactivecpu(), 0, 8, ( data & 4 ) ? 1 : 0, 512 );
+
+ /* bit 1 ( data & 2 ) triggers irq on the other cpu */
+ cpunum_set_input_line( other_cpu, 0, ( data & 2 ) ? CLEAR_LINE : ASSERT_LINE );
+
+ /* move along */
+ if ( cpu_getactivecpu() == 0 )
+ vsnes_in0_w( offset, data );
+ else
+ vsnes_in0_1_w( offset, data );
+}
+
+DRIVER_INIT( vstennis )
+{
+ /* vrom switching is enabled with bit 2 of $4016 */
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, vstennis_vrom_banking );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x4016, 0x4016, 0, 0, vstennis_vrom_banking );
+
+ /* shared ram at $6000 */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_BANK1 );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_BANK1 );
+ memory_install_read8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_BANK1 );
+ memory_install_write8_handler(1, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_BANK1 );
+
+ memory_set_bankptr(1, &memory_region(REGION_CPU1)[0x6000]);
+}
+
+/**********************************************************************/
+/* VS Wrecking Crew */
+
+DRIVER_INIT( wrecking )
+{
+ /* only differance between this and vstennis is the colors */
+
+ driver_init_vstennis(machine);
+ remapped_colortable = rp2c04002_colortable;
+}
+
+/**********************************************************************/
+/* VS Balloon Fight */
+
+DRIVER_INIT( balonfgt )
+{
+ /* only differance between this and vstennis is the colors */
+
+ driver_init_vstennis(machine);
+
+ remapped_colortable = rp2c04003_colortable;
+}
+
+
+/**********************************************************************/
+/* VS Baseball */
+
+DRIVER_INIT( vsbball )
+{
+ /* only differance between this and vstennis is the colors */
+
+ driver_init_vstennis(machine);
+
+ remapped_colortable = rp2c04001_colortable;
+
+}
+
+
+/**********************************************************************/
+/* Dual Ice Climber Jpn */
+
+DRIVER_INIT( iceclmrj )
+{
+ /* only differance between this and vstennis is the colors */
+
+ driver_init_vstennis(machine);
+
+ remapped_colortable = rp2c05004_colortable;
+
+}
+
+/**********************************************************************/
+/* Battle City */
+DRIVER_INIT( btlecity )
+{
+ init_vsnes(machine);
+ driver_init_vsnormal(machine);
+ remapped_colortable = rp2c04003_colortable;
+}
+
+/***********************************************************************/
+/* Tetris */
+DRIVER_INIT( vstetris )
+{
+ /* extra ram at $6000 is enabled with bit 1 of $4016 */
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MRA8_RAM );
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x6000, 0x7fff, 0, 0, MWA8_RAM );
+
+ init_vsnes(machine);
+ driver_init_vsnormal(machine);
+ remapped_colortable = rp2c04003_colortable;
+}
diff --git a/src/mame/machine/williams.c b/src/mame/machine/williams.c
new file mode 100644
index 00000000000..0dfb1b998ea
--- /dev/null
+++ b/src/mame/machine/williams.c
@@ -0,0 +1,919 @@
+/***************************************************************************
+
+ Williams 6809 system
+
+***************************************************************************/
+
+#include "driver.h"
+#include "audio/williams.h"
+#include "cpu/m6800/m6800.h"
+#include "cpu/m6809/m6809.h"
+#include "machine/6821pia.h"
+#include "machine/ticket.h"
+#include "williams.h"
+#include "sound/dac.h"
+#include "sound/hc55516.h"
+
+
+/* timers */
+static emu_timer *scanline_timer;
+static emu_timer *scan240_timer;
+static emu_timer *scan254_timer;
+
+/* banking addresses set by the drivers */
+UINT8 *mayday_protection;
+
+/* internal bank switching tracking */
+static UINT8 blaster_bank;
+static UINT8 vram_bank;
+
+/* other stuff */
+static UINT16 joust2_current_sound_data;
+
+/* older-Williams routines */
+static void williams_main_irq(int state);
+static void williams_main_firq(int state);
+static void williams_snd_irq(int state);
+static WRITE8_HANDLER( williams_snd_cmd_w );
+static WRITE8_HANDLER( playball_snd_cmd_w );
+
+/* input port mapping */
+static UINT8 port_select;
+static WRITE8_HANDLER( williams_port_select_w );
+static READ8_HANDLER( williams_input_port_0_3_r );
+static READ8_HANDLER( williams_input_port_49way_0_5_r );
+static READ8_HANDLER( williams_input_port_1_4_r );
+static READ8_HANDLER( williams_49way_port_0_r );
+
+/* newer-Williams routines */
+static WRITE8_HANDLER( williams2_snd_cmd_w );
+
+/* Lotto Fun-specific code */
+static READ8_HANDLER( lottofun_input_port_0_r );
+
+/* Turkey Shoot-specific code */
+static READ8_HANDLER( tshoot_input_port_0_3_r );
+static WRITE8_HANDLER( tshoot_lamp_w );
+static WRITE8_HANDLER( tshoot_maxvol_w );
+
+/* Joust 2-specific code */
+static WRITE8_HANDLER( joust2_snd_cmd_w );
+static WRITE8_HANDLER( joust2_pia_3_cb1_w );
+
+
+
+/*************************************
+ *
+ * Generic old-Williams PIA interfaces
+ *
+ *************************************/
+
+/* Generic PIA 0, maps to input ports 0 and 1 */
+const pia6821_interface williams_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+/* Generic muxing PIA 0, maps to input ports 0/3 and 1; port select is CB2 */
+const pia6821_interface williams_muxed_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, williams_port_select_w,
+ /*irqs : A/B */ 0, 0
+};
+
+/* Generic dual muxing PIA 0, maps to input ports 0/3 and 1/4; port select is CB2 */
+const pia6821_interface williams_dual_muxed_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, williams_input_port_1_4_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, williams_port_select_w,
+ /*irqs : A/B */ 0, 0
+};
+
+/* Generic 49-way joystick PIA 0 for Sinistar/Blaster */
+const pia6821_interface williams_49way_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ williams_49way_port_0_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+/* Muxing 49-way joystick PIA 0 for Blaster kit */
+const pia6821_interface williams_49way_muxed_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_49way_0_5_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, williams_port_select_w,
+ /*irqs : A/B */ 0, 0
+};
+
+/* Generic PIA 1, maps to input port 2, sound command out, and IRQs */
+const pia6821_interface williams_pia_1_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, williams_snd_cmd_w, 0, 0,
+ /*irqs : A/B */ williams_main_irq, williams_main_irq
+};
+
+/* Generic PIA 2, maps to DAC data in and sound IRQs */
+const pia6821_interface williams_snd_pia_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ DAC_0_data_w, 0, 0, 0,
+ /*irqs : A/B */ williams_snd_irq, williams_snd_irq
+};
+
+
+
+/*************************************
+ *
+ * Game-specific old-Williams PIA interfaces
+ *
+ *************************************/
+
+/* Special PIA 0 for Lotto Fun, to handle the controls and ticket dispenser */
+const pia6821_interface lottofun_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ lottofun_input_port_0_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, ticket_dispenser_w, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+/* Special PIA 2 for Sinistar, to handle the CVSD */
+const pia6821_interface sinistar_snd_pia_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ DAC_0_data_w, 0, hc55516_0_digit_w, hc55516_0_clock_w,
+ /*irqs : A/B */ williams_snd_irq, williams_snd_irq
+};
+
+/* Special PIA 1 for PlayBall, doesn't set the high bits on sound commands */
+const pia6821_interface playball_pia_1_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, playball_snd_cmd_w, 0, 0,
+ /*irqs : A/B */ williams_main_irq, williams_main_irq
+};
+
+/* extra PIA 3 for Speed Ball */
+const pia6821_interface spdball_pia_3_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_3_r, input_port_4_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+
+
+/*************************************
+ *
+ * Generic later-Williams PIA interfaces
+ *
+ *************************************/
+
+/* Generic muxing PIA 0, maps to input ports 0/3 and 1; port select is CA2 */
+const pia6821_interface williams2_muxed_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ williams_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, williams_port_select_w, 0,
+ /*irqs : A/B */ 0, 0
+};
+
+/* Generic PIA 1, maps to input port 2, sound command out, and IRQs */
+const pia6821_interface williams2_pia_1_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, williams2_snd_cmd_w, 0, pia_2_ca1_w,
+ /*irqs : A/B */ williams_main_irq, williams_main_irq
+};
+
+/* Generic PIA 2, maps to DAC data in and sound IRQs */
+const pia6821_interface williams2_snd_pia_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ pia_1_portb_w, DAC_0_data_w, pia_1_cb1_w, 0,
+ /*irqs : A/B */ williams_snd_irq, williams_snd_irq
+};
+
+
+
+/*************************************
+ *
+ * Game-specific later-Williams PIA interfaces
+ *
+ *************************************/
+
+/* Mystic Marathon PIA 0 */
+const pia6821_interface mysticm_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_0_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, 0, 0, 0,
+ /*irqs : A/B */ williams_main_firq, williams_main_irq
+};
+
+/* Turkey Shoot PIA 0 */
+const pia6821_interface tshoot_pia_0_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ tshoot_input_port_0_3_r, input_port_1_r, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, tshoot_lamp_w, williams_port_select_w, 0,
+ /*irqs : A/B */ williams_main_irq, williams_main_irq
+};
+
+/* Turkey Shoot PIA 2 */
+const pia6821_interface tshoot_snd_pia_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ 0, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ pia_1_portb_w, DAC_0_data_w, pia_1_cb1_w, tshoot_maxvol_w,
+ /*irqs : A/B */ williams_snd_irq, williams_snd_irq
+};
+
+/* Joust 2 PIA 1 */
+const pia6821_interface joust2_pia_1_intf =
+{
+ /*inputs : A/B,CA/B1,CA/B2 */ input_port_2_r, 0, 0, 0, 0, 0,
+ /*outputs: A/B,CA/B2 */ 0, joust2_snd_cmd_w, joust2_pia_3_cb1_w, pia_2_ca1_w,
+ /*irqs : A/B */ williams_main_irq, williams_main_irq
+};
+
+
+
+/*************************************
+ *
+ * Older Williams interrupts
+ *
+ *************************************/
+
+static TIMER_CALLBACK( williams_va11_callback )
+{
+ int scanline = param;
+
+ /* the IRQ signal comes into CB1, and is set to VA11 */
+ pia_1_cb1_w(0, scanline & 0x20);
+
+ /* update the screen while we're here */
+ video_screen_update_partial(0, scanline - 1);
+
+ /* set a timer for the next update */
+ scanline++;
+ if (scanline >= 256) scanline = 0;
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, scanline, 0), scanline, attotime_zero);
+}
+
+
+static TIMER_CALLBACK( williams_count240_off_callback )
+{
+ /* the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 */
+ pia_1_ca1_w(0, 0);
+}
+
+
+static TIMER_CALLBACK( williams_count240_callback )
+{
+ /* the COUNT240 signal comes into CA1, and is set to the logical AND of VA10-VA13 */
+ pia_1_ca1_w(0, 1);
+
+ /* set a timer to turn it off once the scanline counter resets */
+ timer_set(video_screen_get_time_until_pos(0, 0, 0), 0, williams_count240_off_callback);
+
+ /* set a timer for next frame */
+ timer_adjust(scan240_timer, video_screen_get_time_until_pos(0, 240, 0), 0, attotime_zero);
+}
+
+
+static void williams_main_irq(int state)
+{
+ /* IRQ to the main CPU */
+ cpunum_set_input_line(0, M6809_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+static void williams_main_firq(int state)
+{
+ /* FIRQ to the main CPU */
+ cpunum_set_input_line(0, M6809_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+static void williams_snd_irq(int state)
+{
+ /* IRQ to the sound CPU */
+ cpunum_set_input_line(1, M6800_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE);
+}
+
+
+
+/*************************************
+ *
+ * Older Williams initialization
+ *
+ *************************************/
+
+static void williams_common_init(void)
+{
+ /* reset the PIAs */
+ pia_reset();
+
+ /* reset the ticket dispenser (Lotto Fun) */
+ ticket_dispenser_init(70, TICKET_MOTOR_ACTIVE_LOW, TICKET_STATUS_ACTIVE_HIGH);
+
+ /* set a timer to go off every 16 scanlines, to toggle the VA11 line and update the screen */
+ scanline_timer = timer_alloc(williams_va11_callback);
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, 0, 0), 0, attotime_zero);
+
+ /* also set a timer to go off on scanline 240 */
+ scan240_timer = timer_alloc(williams_count240_callback);
+ timer_adjust(scan240_timer, video_screen_get_time_until_pos(0, 240, 0), 0, attotime_zero);
+
+ state_save_register_global(vram_bank);
+}
+
+
+MACHINE_RESET( williams )
+{
+ williams_common_init();
+
+ /* configure the memory bank */
+ memory_configure_bank(1, 0, 1, williams_videoram, 0);
+ memory_configure_bank(1, 1, 1, memory_region(REGION_CPU1) + 0x10000, 0);
+}
+
+
+
+/*************************************
+ *
+ * Newer Williams interrupts
+ *
+ *************************************/
+
+static TIMER_CALLBACK( williams2_va11_callback )
+{
+ int scanline = param;
+
+ /* the IRQ signal comes into CB1, and is set to VA11 */
+ pia_0_cb1_w(0, scanline & 0x20);
+ pia_1_ca1_w(0, scanline & 0x20);
+
+ /* update the screen while we're here */
+ video_screen_update_partial(0, scanline);
+
+ /* set a timer for the next update */
+ scanline++;
+ if (scanline >= 256) scanline = 0;
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, scanline, 0), scanline, attotime_zero);
+}
+
+
+static TIMER_CALLBACK( williams2_endscreen_off_callback )
+{
+ /* the /ENDSCREEN signal comes into CA1 */
+ pia_0_ca1_w(0, 1);
+}
+
+
+static TIMER_CALLBACK( williams2_endscreen_callback )
+{
+ /* the /ENDSCREEN signal comes into CA1 */
+ pia_0_ca1_w(0, 0);
+
+ /* set a timer to turn it off once the scanline counter resets */
+ timer_set(video_screen_get_time_until_pos(0, 8, 0), 0, williams2_endscreen_off_callback);
+
+ /* set a timer for next frame */
+ timer_adjust(scan254_timer, video_screen_get_time_until_pos(0, 254, 0), 0, attotime_zero);
+}
+
+
+
+/*************************************
+ *
+ * Newer Williams initialization
+ *
+ *************************************/
+
+static void williams2_postload(void)
+{
+ williams2_bank_select_w(0, vram_bank);
+}
+
+
+MACHINE_RESET( williams2 )
+{
+ /* reset the PIAs */
+ pia_reset();
+
+ /* configure memory banks */
+ memory_configure_bank(1, 0, 1, williams_videoram, 0);
+ memory_configure_bank(1, 1, 4, memory_region(REGION_CPU1) + 0x10000, 0x10000);
+
+ /* make sure our banking is reset */
+ williams2_bank_select_w(0, 0);
+
+ /* set a timer to go off every 16 scanlines, to toggle the VA11 line and update the screen */
+ scanline_timer = timer_alloc(williams2_va11_callback);
+ timer_adjust(scanline_timer, video_screen_get_time_until_pos(0, 0, 0), 0, attotime_zero);
+
+ /* also set a timer to go off on scanline 254 */
+ scan254_timer = timer_alloc(williams2_endscreen_callback);
+ timer_adjust(scan254_timer, video_screen_get_time_until_pos(0, 254, 0), 0, attotime_zero);
+
+ state_save_register_global(vram_bank);
+ state_save_register_func_postload(williams2_postload);
+}
+
+
+
+/*************************************
+ *
+ * VRAM/ROM banking
+ *
+ *************************************/
+
+WRITE8_HANDLER( williams_vram_select_w )
+{
+ /* VRAM/ROM banking from bit 0 */
+ vram_bank = data & 0x01;
+ memory_set_bank(1, vram_bank);
+
+ /* cocktail flip from bit 1 */
+ williams_cocktail = data & 0x02;
+}
+
+
+WRITE8_HANDLER( williams2_bank_select_w )
+{
+ vram_bank = data & 0x07;
+
+ /* the low two bits control the paging */
+ switch (vram_bank & 0x03)
+ {
+ /* page 0 is video ram */
+ case 0:
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, 0x8fff, 0, 0, MRA8_BANK1);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, MWA8_BANK4);
+ memory_set_bank(1, 0);
+ memory_set_bankptr(4, &williams_videoram[0x8000]);
+ break;
+
+ /* pages 1 and 2 are ROM */
+ case 1:
+ case 2:
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x0000, 0x8fff, 0, 0, MRA8_BANK1);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, MWA8_BANK4);
+ memory_set_bank(1, 1 + ((vram_bank & 6) >> 1));
+ memory_set_bankptr(4, &williams_videoram[0x8000]);
+ break;
+
+ /* page 3 accesses palette RAM; the remaining areas are as if page 1 ROM was selected */
+ case 3:
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, williams2_paletteram_r);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0x8000, 0x87ff, 0, 0, williams2_paletteram_w);
+ memory_set_bank(1, 1 + ((vram_bank & 4) >> 1));
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Sound commands
+ *
+ *************************************/
+
+static TIMER_CALLBACK( williams_deferred_snd_cmd_w )
+{
+ pia_2_portb_w(0, param);
+ pia_2_cb1_w(0, (param == 0xff) ? 0 : 1);
+}
+
+WRITE8_HANDLER( williams_snd_cmd_w )
+{
+ /* the high two bits are set externally, and should be 1 */
+ timer_call_after_resynch(data | 0xc0, williams_deferred_snd_cmd_w);
+}
+
+WRITE8_HANDLER( playball_snd_cmd_w )
+{
+ timer_call_after_resynch(data, williams_deferred_snd_cmd_w);
+}
+
+
+static TIMER_CALLBACK( williams2_deferred_snd_cmd_w )
+{
+ pia_2_porta_w(0, param);
+}
+
+static WRITE8_HANDLER( williams2_snd_cmd_w )
+{
+ timer_call_after_resynch(data, williams2_deferred_snd_cmd_w);
+}
+
+
+
+/*************************************
+ *
+ * General input port handlers
+ *
+ *************************************/
+
+WRITE8_HANDLER( williams_port_select_w )
+{
+ port_select = data;
+}
+
+
+READ8_HANDLER( williams_input_port_0_3_r )
+{
+ return readinputport(port_select ? 3 : 0);
+}
+
+
+READ8_HANDLER( williams_input_port_1_4_r )
+{
+ return readinputport(port_select ? 4 : 1);
+}
+
+
+/*
+ * Williams 49-way joystick
+ *
+ * The joystick works on a 7x7 grid system:
+ *
+ * + + + | + + +
+ * + + + | + + +
+ * + + + | + + +
+ * ------+------
+ * + + + | + + +
+ * + + + | + + +
+ * + + + | + + +
+ *
+ * Each axis has 7 positions, reported as follows
+ * in 4 bits/axis:
+ *
+ * 0000 = left/up full
+ * 0100 = left/up 2/3
+ * 0110 = left/up 1/3
+ * 0111 = center
+ * 1011 = right/down 1/3
+ * 1001 = right/down 2/3
+ * 1000 = right/down full
+ */
+
+READ8_HANDLER( williams_49way_port_0_r )
+{
+ static const UINT8 translate49[7] = { 0x0, 0x4, 0x6, 0x7, 0xb, 0x9, 0x8 };
+ return (translate49[readinputportbytag("49WAYX") >> 4] << 4) | translate49[readinputportbytag("49WAYY") >> 4];
+}
+
+
+READ8_HANDLER( williams_input_port_49way_0_5_r )
+{
+ if (port_select)
+ return williams_49way_port_0_r(0);
+ else
+ return readinputport(5);
+}
+
+
+
+/*************************************
+ *
+ * CMOS access
+ *
+ *************************************/
+
+WRITE8_HANDLER( williams_cmos_w )
+{
+ /* only 4 bits are valid */
+ generic_nvram[offset] = data | 0xf0;
+}
+
+
+WRITE8_HANDLER( bubbles_cmos_w )
+{
+ /* bubbles has additional CMOS for a full 8 bits */
+ generic_nvram[offset] = data;
+}
+
+
+
+/*************************************
+ *
+ * Watchdog
+ *
+ *************************************/
+
+WRITE8_HANDLER( williams_watchdog_reset_w )
+{
+ /* yes, the data bits are checked for this specific value */
+ if (data == 0x39)
+ watchdog_reset_w(0,0);
+}
+
+
+WRITE8_HANDLER( williams2_watchdog_reset_w )
+{
+ /* yes, the data bits are checked for this specific value */
+ if ((data & 0x3f) == 0x14)
+ watchdog_reset_w(0,0);
+}
+
+
+
+/*************************************
+ *
+ * Diagnostic controls
+ *
+ *************************************/
+
+WRITE8_HANDLER( williams2_7segment_w )
+{
+ int n;
+ char dot;
+
+ switch (data & 0x7F)
+ {
+ case 0x40: n = 0; break;
+ case 0x79: n = 1; break;
+ case 0x24: n = 2; break;
+ case 0x30: n = 3; break;
+ case 0x19: n = 4; break;
+ case 0x12: n = 5; break;
+ case 0x02: n = 6; break;
+ case 0x03: n = 6; break;
+ case 0x78: n = 7; break;
+ case 0x00: n = 8; break;
+ case 0x18: n = 9; break;
+ case 0x10: n = 9; break;
+ default: n =-1; break;
+ }
+
+ if ((data & 0x80) == 0x00)
+ dot = '.';
+ else
+ dot = ' ';
+
+ if (n == -1)
+ logerror("[ %c]\n", dot);
+ else
+ logerror("[%d%c]\n", n, dot);
+}
+
+
+
+/*************************************
+ *
+ * Defender-specific routines
+ *
+ *************************************/
+
+static void defender_postload(void)
+{
+ defender_bank_select_w(0, vram_bank);
+}
+
+
+MACHINE_RESET( defender )
+{
+ williams_common_init();
+
+ /* configure the banking and make sure it is reset to 0 */
+ memory_configure_bank(1, 0, 9, &memory_region(REGION_CPU1)[0x10000], 0x1000);
+ defender_bank_select_w(0, 0);
+
+ state_save_register_func_postload(defender_postload);
+}
+
+
+WRITE8_HANDLER( defender_video_control_w )
+{
+ williams_cocktail = data & 0x01;
+}
+
+
+WRITE8_HANDLER( defender_bank_select_w )
+{
+ vram_bank = data & 0x0f;
+
+ /* set bank address */
+ switch (data)
+ {
+ /* page 0 is I/O space */
+ case 0:
+ defender_install_io_space();
+ break;
+
+ /* pages 1-9 map to ROM banks */
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MRA8_BANK1);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MWA8_UNMAP);
+ memory_set_bank(1, vram_bank - 1);
+ break;
+
+ /* pages A-F are not connected */
+ default:
+ memory_install_read8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MRA8_NOP);
+ memory_install_write8_handler(0, ADDRESS_SPACE_PROGRAM, 0xc000, 0xcfff, 0, 0, MWA8_NOP);
+ break;
+ }
+}
+
+
+
+/*************************************
+ *
+ * Mayday-specific routines
+ *
+ *************************************/
+
+READ8_HANDLER( mayday_protection_r )
+{
+ /* Mayday does some kind of protection check that is not currently understood */
+ /* However, the results of that protection check are stored at $a190 and $a191 */
+ /* These are compared against $a193 and $a194, respectively. Thus, to prevent */
+ /* the protection from resetting the machine, we just return $a193 for $a190, */
+ /* and $a194 for $a191. */
+ return mayday_protection[offset + 3];
+}
+
+
+
+/*************************************
+ *
+ * Sinistar-specific routines
+ *
+ *************************************/
+
+WRITE8_HANDLER( sinistar_vram_select_w )
+{
+ /* low two bits are standard */
+ williams_vram_select_w(offset, data);
+
+ /* window enable from bit 2 (clips to 0x7400) */
+ williams_blitter_window_enable = data & 0x04;
+}
+
+
+
+/*************************************
+ *
+ * Blaster-specific routines
+ *
+ *************************************/
+
+MACHINE_RESET( blaster )
+{
+ williams_common_init();
+
+ /* banking is different for blaster */
+ memory_configure_bank(1, 0, 1, williams_videoram, 0);
+ memory_configure_bank(1, 1, 16, memory_region(REGION_CPU1) + 0x18000, 0x4000);
+
+ memory_configure_bank(2, 0, 1, williams_videoram + 0x4000, 0);
+ memory_configure_bank(2, 1, 16, memory_region(REGION_CPU1) + 0x10000, 0x0000);
+
+ state_save_register_global(blaster_bank);
+}
+
+
+INLINE void update_blaster_banking(void)
+{
+ memory_set_bank(1, vram_bank * (blaster_bank + 1));
+ memory_set_bank(2, vram_bank * (blaster_bank + 1));
+}
+
+
+WRITE8_HANDLER( blaster_vram_select_w )
+{
+ /* VRAM/ROM banking from bit 0 */
+ vram_bank = data & 0x01;
+ update_blaster_banking();
+
+ /* cocktail flip from bit 1 */
+ williams_cocktail = data & 0x02;
+
+ /* window enable from bit 2 (clips to 0x9700) */
+ williams_blitter_window_enable = data & 0x04;
+}
+
+
+WRITE8_HANDLER( blaster_bank_select_w )
+{
+ blaster_bank = data & 15;
+ update_blaster_banking();
+}
+
+
+
+/*************************************
+ *
+ * Lotto Fun-specific routines
+ *
+ *************************************/
+
+static READ8_HANDLER( lottofun_input_port_0_r )
+{
+ /* merge in the ticket dispenser status */
+ return input_port_0_r(offset) | ticket_dispenser_r(offset);
+}
+
+
+
+/*************************************
+ *
+ * Turkey Shoot-specific routines
+ *
+ *************************************/
+
+static READ8_HANDLER( tshoot_input_port_0_3_r )
+{
+ /* merge in the gun inputs with the standard data */
+ int data = williams_input_port_0_3_r(offset);
+ int gun = (data & 0x3f) ^ ((data & 0x3f) >> 1);
+ return (data & 0xc0) | gun;
+}
+
+
+static WRITE8_HANDLER( tshoot_maxvol_w )
+{
+ /* something to do with the sound volume */
+ logerror("tshoot maxvol = %d (pc:%x)\n", data, activecpu_get_pc());
+}
+
+
+static WRITE8_HANDLER( tshoot_lamp_w )
+{
+ /* set the grenade lamp */
+ set_led_status(0,data & 0x04);
+
+ /* set the gun lamp */
+ set_led_status(1,data & 0x08);
+
+#if 0
+ /* gun coil */
+ if (data & 0x10)
+ mame_printf_debug("[gun coil] ");
+ else
+ mame_printf_debug(" ");
+
+ /* feather coil */
+ if (data & 0x20)
+ mame_printf_debug("[feather coil] ");
+ else
+ mame_printf_debug(" ");
+
+ mame_printf_debug("\n");
+#endif
+}
+
+
+
+/*************************************
+ *
+ * Joust 2-specific routines
+ *
+ *************************************/
+
+MACHINE_START( joust2 )
+{
+ williams_cvsd_init(3);
+}
+
+
+MACHINE_RESET( joust2 )
+{
+ /* standard init */
+ machine_reset_williams2(machine);
+ pia_set_input_ca1(3, 1);
+ state_save_register_global(joust2_current_sound_data);
+}
+
+
+static TIMER_CALLBACK( joust2_deferred_snd_cmd_w )
+{
+ pia_2_porta_w(0, param & 0xff);
+}
+
+
+static WRITE8_HANDLER( joust2_pia_3_cb1_w )
+{
+ joust2_current_sound_data = (joust2_current_sound_data & ~0x100) | ((data << 8) & 0x100);
+ pia_3_cb1_w(offset, data);
+}
+
+
+static WRITE8_HANDLER( joust2_snd_cmd_w )
+{
+ joust2_current_sound_data = (joust2_current_sound_data & ~0xff) | (data & 0xff);
+ williams_cvsd_data_w(joust2_current_sound_data);
+ timer_call_after_resynch(joust2_current_sound_data, joust2_deferred_snd_cmd_w);
+}
diff --git a/src/mame/machine/wrally.c b/src/mame/machine/wrally.c
new file mode 100644
index 00000000000..a7e2927dd3e
--- /dev/null
+++ b/src/mame/machine/wrally.c
@@ -0,0 +1,154 @@
+/***************************************************************************
+
+ World Rally
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+
+UINT16 *wrally_encr_table[2];
+
+/***************************************************************************
+
+ World Rally Video RAM encryption
+
+***************************************************************************/
+
+static int subxor1(int data,int res)
+{
+ res ^= 0x0002;
+ if (BIT(data,0) ^ !BIT(data,5))
+ {
+ res ^= 0x0800;
+ if (BIT(data,2) ^ BIT(data,3)) res ^= 0x0001;
+ if (BIT(data,6) && !BIT(data,11) && BIT(data,5)) res ^= 0x0001;
+ }
+
+ return res;
+}
+
+static int subxor2(int data,int res)
+{
+ res ^= 0x0020;
+ if (BIT(data,8) ^ !BIT(data,5))
+ {
+ res ^= 0x0008;
+ if (BIT(data,4) ^ BIT(data,3)) res ^= 0x0100;
+ if (BIT(data,6) && !BIT(data,11) && BIT(data,5)) res ^= 0x0100;
+ }
+
+ return res;
+}
+
+static int wrally_decode_vram(int data)
+{
+ int res = 0;
+
+
+ res = BITSWAP16(data,5,7,9,12,2,14,13,15,3,6,8,11,4,10,0,1);
+
+ res ^= 0x0062;
+
+ if (BIT(data,9)) res ^= 0x5004;
+
+ if ( BIT(data,5) ^ (!BIT(data,9) && BIT(data,7))) res ^= 0x0200;
+ if (!BIT(data,5) ^ (!BIT(data,9) && BIT(data,12))) res ^= 0x0400;
+
+ if (BIT(data,3) ^ BIT(data,6)) res ^= 0x0101;
+
+ if (BIT(data,3) ^ BIT(data,5))
+ {
+ res ^= 0x0808;
+ if (BIT(data,2) ^ BIT(data,3)) res ^= 0x0001;
+ if (BIT(data,4) ^ BIT(data,3)) res ^= 0x0100;
+ }
+
+ if ((BIT(data,9) && !BIT(data,10)) || BIT(data,5))
+ {
+ res ^= 0x0010;
+
+ if (!BIT(data,11)) res ^= 0x0141;
+
+ if (BIT(data,6) && !BIT(data,11))
+ {
+ res ^= 0x0888;
+ if (!BIT(data,2)) res ^= 0x0001;
+ if (!BIT(data,4)) res ^= 0x0100;
+ }
+ }
+
+ if (BIT(data,9) && !BIT(data,10))
+ {
+ res ^= 0x8600;
+ if (!BIT(data,14)) res = subxor1(data,res);
+ if (!BIT(data,5)) res = subxor2(data,res);
+
+ if (BIT(data,6) && !BIT(data,11))
+ {
+ if (BIT(data,0) && !BIT(data,5)) res ^= 0x0001;
+ if (BIT(data,8) && !BIT(data,5)) res ^= 0x0100;
+ }
+ }
+
+ if (BIT(data,5) ^ BIT(data,14))
+ {
+ if ( BIT(data,14)) res = subxor1(data,res);
+ if (!BIT(data,9) && BIT(data,12)) res = subxor1(data,res);
+ }
+
+ if (BIT(data,5) ^ !BIT(data,13))
+ {
+ if ( BIT(data,5)) res = subxor2(data,res);
+ if ( BIT(data,9) && BIT(data,10)) res = subxor2(data,res);
+ if (!BIT(data,9) && !BIT(data,7)) res = subxor2(data,res);
+ }
+
+ return res;
+}
+
+/***************************************************************************
+
+ World Rally memory handlers
+
+***************************************************************************/
+
+WRITE16_HANDLER( OKIM6295_bankswitch_w )
+{
+ UINT8 *RAM = memory_region(REGION_SOUND1);
+
+ if (ACCESSING_LSB){
+ memcpy(&RAM[0x30000], &RAM[0x40000 + (data & 0x0f)*0x10000], 0x10000);
+ }
+}
+
+WRITE16_HANDLER( wrally_coin_counter_w )
+{
+ coin_counter_w( (offset >> 3) & 0x01, data & 0x01);
+}
+
+WRITE16_HANDLER( wrally_coin_lockout_w )
+{
+ coin_lockout_w( (offset >> 3) & 0x01, ~data & 0x01);
+}
+
+/***************************************************************************
+
+ World Rally init machine
+
+***************************************************************************/
+
+DRIVER_INIT( wrally )
+{
+ int i;
+
+ /* recreate encryption tables on start up */
+ wrally_encr_table[0] = (UINT16 *)auto_malloc(0x10000*2);
+ wrally_encr_table[1] = (UINT16 *)auto_malloc(0x10000*2);
+ for (i = 0; i < 0x10000; i++){
+ wrally_encr_table[0][i] = wrally_decode_vram(i);
+ wrally_encr_table[1][i] = wrally_decode_vram(i);
+ }
+}
diff --git a/src/mame/machine/xevious.c b/src/mame/machine/xevious.c
new file mode 100644
index 00000000000..c370a43e9f5
--- /dev/null
+++ b/src/mame/machine/xevious.c
@@ -0,0 +1,185 @@
+/***************************************************************************
+
+ machine.c
+
+ Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
+ I/O ports)
+
+***************************************************************************/
+
+#include "driver.h"
+#include "sound/samples.h"
+#include "includes/galaga.h"
+
+/***************************************************************************
+
+ BATTLES CPU4(custum I/O Emulation) I/O Handlers
+
+***************************************************************************/
+
+static emu_timer *nmi_timer;
+
+static UINT8 customio[16];
+static char battles_customio_command;
+static char battles_customio_prev_command;
+static char battles_customio_command_count;
+static char battles_customio_data;
+static char battles_sound_played;
+
+static TIMER_CALLBACK( battles_nmi_generate );
+
+
+void battles_customio_init(void)
+{
+ battles_customio_command = 0;
+ battles_customio_prev_command = 0;
+ battles_customio_command_count = 0;
+ battles_customio_data = 0;
+ battles_sound_played = 0;
+ nmi_timer = timer_alloc(battles_nmi_generate);
+}
+
+
+static TIMER_CALLBACK( battles_nmi_generate )
+{
+
+ battles_customio_prev_command = battles_customio_command;
+
+ if( battles_customio_command & 0x10 ){
+ if( battles_customio_command_count == 0 ){
+ cpunum_set_input_line(3, INPUT_LINE_NMI, PULSE_LINE);
+ }else{
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+ cpunum_set_input_line(3, INPUT_LINE_NMI, PULSE_LINE);
+ }
+ }else{
+ cpunum_set_input_line(0, INPUT_LINE_NMI, PULSE_LINE);
+ cpunum_set_input_line(3, INPUT_LINE_NMI, PULSE_LINE);
+ }
+ battles_customio_command_count++;
+}
+
+
+READ8_HANDLER( battles_customio0_r )
+{
+ logerror("CPU0 %04x: custom I/O Read = %02x\n",activecpu_get_pc(),battles_customio_command);
+ return battles_customio_command;
+}
+
+READ8_HANDLER( battles_customio3_r )
+{
+ int return_data;
+
+ if( activecpu_get_pc() == 0xAE ){
+ /* CPU4 0xAA - 0xB9 : waiting for MB8851 ? */
+ return_data = ( (battles_customio_command & 0x10) << 3)
+ | 0x00
+ | (battles_customio_command & 0x0f);
+ }else{
+ return_data = ( (battles_customio_prev_command & 0x10) << 3)
+ | 0x60
+ | (battles_customio_prev_command & 0x0f);
+ }
+ logerror("CPU3 %04x: custom I/O Read = %02x\n",activecpu_get_pc(),return_data);
+
+ return return_data;
+}
+
+
+WRITE8_HANDLER( battles_customio0_w )
+{
+ logerror("CPU0 %04x: custom I/O Write = %02x\n",activecpu_get_pc(),data);
+
+ battles_customio_command = data;
+ battles_customio_command_count = 0;
+
+ switch (data)
+ {
+ case 0x10:
+ timer_adjust(nmi_timer, attotime_never, 0, attotime_never);
+ return; /* nop */
+ }
+ timer_adjust(nmi_timer, ATTOTIME_IN_USEC(166), 0, ATTOTIME_IN_USEC(166));
+
+}
+
+WRITE8_HANDLER( battles_customio3_w )
+{
+ logerror("CPU3 %04x: custom I/O Write = %02x\n",activecpu_get_pc(),data);
+
+ battles_customio_command = data;
+}
+
+
+
+READ8_HANDLER( battles_customio_data0_r )
+{
+ logerror("CPU0 %04x: custom I/O parameter %02x Read = %02x\n",activecpu_get_pc(),offset,battles_customio_data);
+
+ return battles_customio_data;
+}
+
+READ8_HANDLER( battles_customio_data3_r )
+{
+ logerror("CPU3 %04x: custom I/O parameter %02x Read = %02x\n",activecpu_get_pc(),offset,battles_customio_data);
+ return battles_customio_data;
+}
+
+
+WRITE8_HANDLER( battles_customio_data0_w )
+{
+ logerror("CPU0 %04x: custom I/O parameter %02x Write = %02x\n",activecpu_get_pc(),offset,data);
+ battles_customio_data = data;
+}
+
+WRITE8_HANDLER( battles_customio_data3_w )
+{
+ logerror("CPU3 %04x: custom I/O parameter %02x Write = %02x\n",activecpu_get_pc(),offset,data);
+ battles_customio_data = data;
+}
+
+
+WRITE8_HANDLER( battles_CPU4_coin_w )
+{
+ set_led_status(0,data & 0x02); // Start 1
+ set_led_status(1,data & 0x01); // Start 2
+
+ coin_counter_w(0,data & 0x20);
+ coin_counter_w(1,data & 0x10);
+ coin_lockout_global_w(~data & 0x04);
+}
+
+
+WRITE8_HANDLER( battles_noise_sound_w )
+{
+ logerror("CPU3 %04x: 50%02x Write = %02x\n",activecpu_get_pc(),offset,data);
+ if( (battles_sound_played == 0) && (data == 0xFF) ){
+ if( customio[0] == 0x40 ){
+ sample_start (0, 0, 0);
+ }
+ else{
+ sample_start (0, 1, 0);
+ }
+ }
+ battles_sound_played = data;
+}
+
+
+READ8_HANDLER( battles_input_port_r )
+{
+ switch ( offset )
+ {
+ default:
+ case 0: return ~BITSWAP8(readinputport(0),6,7,5,4,3,2,1,0) >> 4;
+ case 1: return ~readinputport(1) & 0x0f;
+ case 2: return ~readinputport(1) >> 4;
+ case 3: return ~readinputport(0) & 0x0f;
+ }
+}
+
+
+INTERRUPT_GEN( battles_interrupt_4 )
+{
+ cpunum_set_input_line(3, 0, HOLD_LINE);
+}
+
diff --git a/src/mame/machine/znsec.c b/src/mame/machine/znsec.c
new file mode 100644
index 00000000000..77172aa9a2a
--- /dev/null
+++ b/src/mame/machine/znsec.c
@@ -0,0 +1,181 @@
+/*
+
+ CAT702 ZN security chip
+
+ A serial magic latch.
+
+ It's a DIP20 chip with a sticker of the form XXnn, where XX is the
+ company and nn a number:
+ AC = Acclaim
+ AT = Atlus
+ CP = Capcom
+ ET = Raizing
+ KN = Konami
+ MG = Tecmo
+ TT = Taito
+ TW = Atari
+
+ There usually are 2 of them, one on the cpu board and one on the rom
+ board. The cpu board one is usually numbered 01.
+
+ Pinout: GND -11 10- GND
+ ? -12 9- +5V
+ +5V -13 8- Data in
+ Data out- 14 7- Clock
+ +5V -15 6- Select
+ ? -16 5- Select
+ +5V -17 4- +5V
+ +5V -18 3- +5V
+ +5V -19 2- +5V
+ +5V -20 1- ?
+
+ The chip works with the '?' lines left unconnected.
+
+ The communication protocol is serial, and in practice the standard
+ psx controller communication protocol minus the ack. Drive both
+ select to ground to start a communication, send bits and get the
+ results on the raising clock. Put both select back to +5V when
+ finished. The bios seems to use two communication clock speeds,
+ ~300KHz (standard psx) and ~2MHz. Driving it with lower clocks
+ works reasonably, at least at 1KHz.
+
+ The data is divided in bytes but there is no signal for end-of-byte.
+ In all of the following the data will be considered coming and going
+ lower-bit first.
+
+ Internally the chip has a 8-bit state, initialized at communication
+ start to 0xfc. The structure is simple:
+
+
+ +---------+ bit number +--------+
+ Clock ------->| bit |-----+-------------------->| bit |---------> Data out
+ | counter | | | select |
+ +---------+ v +-------+ out | |
+ | +-----+ | 8bit |=====>| |
+ Data in ------------|------->| TF1 |<=>| state | +--------+
+ | +-----+ | |
+ | | |
+ | start +-----+ | |
+ +------->| TF2 |<=>| |
+ +-----+ +-------+
+
+ The chip starts by tranforming the state with TF2. Then, for each
+ input bit from 0 to 7:
+ - the nth bit from the state is sent to the output
+ - the state is transformed by TF1 if the input bit is 0
+
+ TF2 is a fixed linear substitution box (* = and, + = xor):
+ o = ff*s0 + fe*s1 + fc*s2 + f8*s3 + f0*s4 + e0*s5 + c0*s6 + 7f*s7
+
+ TF1 is a chip-dependent set of 8 linear sboxes, one per bit number.
+ In practice, only the sbox for bit 0 is defined for the chip, the 7
+ other are derived from it. Defining the byte transformation Shift
+ as:
+ Shift(i7..i0) = i6..i0, i7^i6
+
+ and noting the sboxes as:
+ Sbox(n, i7..i0) = Xor( c[n, bit]*i[bit])
+ 0<=bit<=7
+ then
+ c[n, bit=0..6] = Shift(c[n-1, (bit-1)&7])
+ c[n, 7] = Shift(c[n-1, 6])^c[n, 0]
+ = Shift(c[n-1, 6])^Shift(c[n-1, 7])
+*/
+
+#include "driver.h"
+#include "znsec.h"
+
+typedef struct {
+ const UINT8 *transform;
+ UINT8 state;
+ UINT8 bit;
+} znsec_state;
+
+static znsec_state zns[2];
+
+
+// Given the value for x7..x0 and linear transform coefficients a7..a0
+// compute the value of the transform
+#if 0
+static int c_linear(UINT8 x, UINT8 a)
+{
+ int i;
+ UINT8 r;
+ x &= a;
+ r = 0;
+ for(i=0; i<8; i++)
+ if(x & (1<<i))
+ r = !r;
+ return r;
+}
+#endif
+
+// Derive the sbox xor mask for a given input and select bit
+static UINT8 compute_sbox_coef(int chip, int sel, int bit)
+{
+ UINT8 r;
+ if(!sel)
+ return zns[chip].transform[bit];
+ r = compute_sbox_coef(chip, (sel-1) & 7, (bit-1) & 7);
+ r = (r << 1)|(((r >> 7)^(r >> 6)) & 1);
+ if(bit != 7)
+ return r;
+
+ return r ^ compute_sbox_coef(chip, sel, 0);
+}
+
+// Apply the sbox for a input 0 bit
+static UINT8 apply_bit_sbox(int chip, UINT8 state, int sel)
+{
+ int i;
+ UINT8 r = 0;
+ for(i=0; i<8; i++)
+ if(state & (1<<i))
+ r ^= compute_sbox_coef(chip, sel, i);
+ return r;
+}
+
+// Apply a sbox
+static UINT8 apply_sbox(UINT8 state, const UINT8 *sbox)
+{
+ int i;
+ UINT8 r = 0;
+ for(i=0; i<8; i++)
+ if(state & (1<<i))
+ r ^= sbox[i];
+ return r;
+}
+
+void znsec_init(int chip, const UINT8 *transform)
+{
+ zns[chip].transform = transform;
+ zns[chip].state = 0xfc;
+ zns[chip].bit = 0;
+}
+
+void znsec_start(int chip)
+{
+ zns[chip].state = 0xfc;
+ zns[chip].bit = 0;
+}
+
+UINT8 znsec_step(int chip, UINT8 input)
+{
+ UINT8 res;
+ static const UINT8 initial_sbox[8] = { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x7f };
+
+ if (zns[chip].bit==0)
+ {
+ // Apply the initial xbox
+ zns[chip].state = apply_sbox(zns[chip].state, initial_sbox);
+ }
+
+ // Compute the output and change the state
+ res = (zns[chip].state>>zns[chip].bit) & 1;
+ if((input & 1)==0)
+ zns[chip].state = apply_bit_sbox(chip, zns[chip].state, zns[chip].bit);
+
+ zns[chip].bit++;
+ zns[chip].bit&=7;
+ return res;
+}
diff --git a/src/mame/machine/znsec.h b/src/mame/machine/znsec.h
new file mode 100644
index 00000000000..7ab83cf8571
--- /dev/null
+++ b/src/mame/machine/znsec.h
@@ -0,0 +1,5 @@
+/* CAT702 ZN security chip */
+
+void znsec_init(int chip, const UINT8 *transform);
+void znsec_start(int chip);
+UINT8 znsec_step(int chip, UINT8 input);
diff --git a/src/mame/machine/zs01.c b/src/mame/machine/zs01.c
new file mode 100644
index 00000000000..b445c05d02c
--- /dev/null
+++ b/src/mame/machine/zs01.c
@@ -0,0 +1,697 @@
+/*
+ * zs01.c
+ *
+ * Secure SerialFlash
+ *
+ * This is a high level emulation of the PIC used in some of the System 573 security cartridges.
+ *
+ */
+
+#include "driver.h"
+#include "machine/zs01.h"
+
+#define VERBOSE_LEVEL ( 0 )
+
+INLINE void verboselog( int n_level, const char *s_fmt, ... )
+{
+ if( VERBOSE_LEVEL >= n_level )
+ {
+ va_list v;
+ char buf[ 32768 ];
+ va_start( v, s_fmt );
+ vsprintf( buf, s_fmt, v );
+ va_end( v );
+ if( cpu_getactivecpu() != -1 )
+ {
+ logerror( "%08x: %s", activecpu_get_pc(), buf );
+ }
+ else
+ {
+ logerror( "(timer) : %s", buf );
+ }
+ }
+}
+
+#define SIZE_WRITE_BUFFER ( 12 )
+#define SIZE_READ_BUFFER ( 12 )
+#define SIZE_DATA_BUFFER ( 8 )
+
+#define SIZE_RESPONSE_TO_RESET ( 4 )
+#define SIZE_KEY ( 8 )
+#define SIZE_DATA ( 4096 )
+
+struct zs01_chip
+{
+ int cs;
+ int rst;
+ int scl;
+ int sdaw;
+ int sdar;
+ int state;
+ int shift;
+ int bit;
+ int byte;
+ UINT8 write_buffer[ SIZE_WRITE_BUFFER ];
+ UINT8 read_buffer[ SIZE_READ_BUFFER ];
+ UINT8 response_key[ SIZE_KEY ];
+ UINT8 *response_to_reset;
+ UINT8 *command_key;
+ UINT8 *data_key;
+ UINT8 *data;
+ UINT8 *ds2401;
+ zs01_write_handler write;
+ zs01_read_handler read;
+};
+
+static struct zs01_chip zs01[ ZS01_MAXCHIP ];
+
+#define COMMAND_WRITE ( 0x00 )
+#define COMMAND_READ ( 0x01 )
+
+#define STATE_STOP ( 0 )
+#define STATE_RESPONSE_TO_RESET ( 1 )
+#define STATE_LOAD_COMMAND ( 2 )
+#define STATE_READ_DATA ( 3 )
+
+void zs01_init( int chip, UINT8 *data, zs01_write_handler write, zs01_read_handler read, UINT8 *ds2401 )
+{
+ int offset;
+ struct zs01_chip *c;
+
+ if( chip >= ZS01_MAXCHIP )
+ {
+ verboselog( 0, "zs01_init( %d ) chip out of range\n", chip );
+ return;
+ }
+
+ c = &zs01[ chip ];
+
+ if( data == NULL )
+ {
+ data = auto_malloc(
+ SIZE_RESPONSE_TO_RESET +
+ SIZE_KEY +
+ SIZE_KEY +
+ SIZE_DATA );
+ }
+
+ if( ds2401 == NULL )
+ {
+ ds2401 = auto_malloc( SIZE_DATA_BUFFER );
+ }
+
+ c->cs = 0;
+ c->rst = 0;
+ c->scl = 0;
+ c->sdaw = 0;
+ c->sdar = 0;
+ c->state = STATE_STOP;
+ c->shift = 0;
+ c->bit = 0;
+ c->byte = 0;
+ memset( c->write_buffer, 0, SIZE_WRITE_BUFFER );
+ memset( c->read_buffer, 0, SIZE_READ_BUFFER );
+ memset( c->response_key, 0, SIZE_KEY );
+
+ offset = 0;
+ c->response_to_reset = &data[ offset ]; offset += SIZE_RESPONSE_TO_RESET;
+ c->command_key = &data[ offset ]; offset += SIZE_KEY;
+ c->data_key = &data[ offset ]; offset += SIZE_KEY;
+ c->data = &data[ offset ]; offset += SIZE_DATA;
+ c->ds2401 = ds2401;
+ c->write = write;
+ c->read = read;
+
+ state_save_register_item( "zs01", chip, c->cs );
+ state_save_register_item( "zs01", chip, c->rst );
+ state_save_register_item( "zs01", chip, c->scl );
+ state_save_register_item( "zs01", chip, c->sdaw );
+ state_save_register_item( "zs01", chip, c->sdar );
+ state_save_register_item( "zs01", chip, c->state );
+ state_save_register_item( "zs01", chip, c->shift );
+ state_save_register_item( "zs01", chip, c->bit );
+ state_save_register_item( "zs01", chip, c->byte );
+ state_save_register_item_array( "zs01", chip, c->write_buffer );
+ state_save_register_item_array( "zs01", chip, c->read_buffer );
+ state_save_register_item_array( "zs01", chip, c->response_key );
+ state_save_register_item_pointer( "zs01", chip, c->response_to_reset, SIZE_RESPONSE_TO_RESET );
+ state_save_register_item_pointer( "zs01", chip, c->command_key, SIZE_KEY );
+ state_save_register_item_pointer( "zs01", chip, c->data_key, SIZE_DATA );
+}
+
+void zs01_rst_write( int chip, int rst )
+{
+ struct zs01_chip *c;
+
+ if( chip >= ZS01_MAXCHIP )
+ {
+ verboselog( 0, "zs01_rst_write( %d ) chip out of range\n", chip );
+ return;
+ }
+
+ c = &zs01[ chip ];
+
+ if( c->rst != rst )
+ {
+ verboselog( 2, "zs01(%d) rst=%d\n", chip, rst );
+ }
+ if( c->rst == 0 && rst != 0 && c->cs == 0 )
+ {
+ verboselog( 1, "zs01(%d) goto response to reset\n", chip );
+ c->state = STATE_RESPONSE_TO_RESET;
+ c->bit = 0;
+ c->byte = 0;
+ }
+ c->rst = rst;
+}
+
+void zs01_cs_write( int chip, int cs )
+{
+ struct zs01_chip *c;
+
+ if( chip >= ZS01_MAXCHIP )
+ {
+ verboselog( 0, "zs01_cs_write( %d ) chip out of range\n", chip );
+ return;
+ }
+
+ c = &zs01[ chip ];
+
+ if( c->cs != cs )
+ {
+ verboselog( 2, "zs01(%d) cs=%d\n", chip, cs );
+ }
+// if( c->cs != 0 && cs == 0 )
+// {
+// /* enable chip */
+// c->state = STATE_STOP;
+// }
+// if( c->cs == 0 && cs != 0 )
+// {
+// /* disable chip */
+// c->state = STATE_STOP;
+// /* high impendence? */
+// c->sdar = 0;
+// }
+ c->cs = cs;
+}
+
+static void zs01_decrypt( UINT8 *destination, UINT8 *source, int length, UINT8 *key, UINT8 previous_byte )
+{
+ UINT32 a0;
+ UINT32 v1;
+ UINT32 v0;
+ UINT32 a1;
+ UINT32 t1;
+ UINT32 t0;
+
+ length--;
+ if( length >= 0 )
+ {
+ do
+ {
+ t1 = source[ length ];
+ a1 = 7;
+ t0 = t1;
+
+ do
+ {
+ v1 = key[ a1 ];
+ a1--;
+ v0 = v1 & 0x1f;
+ v0 = t0 - v0;
+ v1 >>= 5;
+ v0 &= 0xff;
+ a0 = (signed)v0 >> v1;
+ v1 = 8 - v1;
+ v1 &= 7;
+ v0 = (signed)v0 << v1;
+ t0 = a0 | v0;
+ } while( a1 > 0 );
+
+ v1 = key[ 0 ];
+ a0 = previous_byte;
+ v0 = t0 & 0xff;
+ previous_byte = t1;
+ v0 = v0 - v1;
+ v0 = v0 ^ a0;
+
+ destination[ length ] = v0;
+ length--;
+ }
+ while( length >= 0 );
+ }
+}
+
+static void zs01_decrypt2( UINT8 *destination, UINT8 *source, int length, UINT8 *key, UINT8 previous_byte )
+{
+ UINT32 a0;
+ UINT32 v1;
+ UINT32 v0;
+ UINT32 a1;
+ UINT32 t2;
+ UINT32 t1;
+ UINT32 t0;
+
+ t2 = 0;
+ if( length >= 0 )
+ {
+ do
+ {
+ t1 = source[ t2 ];
+ a1 = 7;
+ t0 = t1;
+
+ do
+ {
+ v1 = key[ a1 ];
+ a1--;
+ v0 = v1 & 0x1f;
+ v0 = t0 - v0;
+ v1 >>= 5;
+ v0 &= 0xff;
+ a0 = (signed)v0 >> v1;
+ v1 = 8 - v1;
+ v1 &= 7;
+ v0 = (signed)v0 << v1;
+ t0 = a0 | v0;
+ } while( a1 > 0 );
+
+ v1 = key[ 0 ];
+ a0 = previous_byte;
+ v0 = t0 & 0xff;
+ previous_byte = t1;
+ v0 = v0 - v1;
+ v0 = v0 ^ a0;
+
+ destination[ t2 ] = v0;
+ t2++;
+
+ } while( t2 < length );
+ }
+}
+
+static void zs01_encrypt( UINT8 *destination, UINT8 *source, int length, UINT8 *key, UINT32 previous_byte )
+{
+ UINT32 t0;
+ UINT32 v0;
+ UINT32 v1;
+ UINT32 a0;
+ UINT32 a1;
+
+ length--;
+ if( length >= 0 )
+ {
+ do
+ {
+ t0 = 1;
+ v0 = source[ length ];
+ v1 = previous_byte;
+ a0 = key[ 0 ];
+ v0 ^= v1;
+ a0 += v0;
+
+ do
+ {
+ a1 = key[ t0 ];
+ t0++;
+ a0 &= 0xff;
+ v0 = a1 >> 5;
+ v1 = a0 << v0;
+ v0 = 8 - v0;
+ v0 &= 7;
+ a0 = (signed) a0 >> v0;
+ v1 |= a0;
+ v1 &= 0xff;
+ a1 &= 0x1f;
+ v1 += a1;
+ v0 = (signed) t0 < 8;
+ a0 = v1;
+
+ } while( v0 != 0 );
+
+ previous_byte = v1;
+
+ destination[ length ] = a0;
+ length--;
+
+ } while( length >= 0 );
+ }
+}
+
+static UINT16 zs01_crc( UINT8 *buffer, UINT32 length )
+{
+ UINT32 v1;
+ UINT32 a3;
+ UINT32 v0;
+ UINT32 a2;
+
+ v1 = 0xffff;
+ a3 = 0;
+
+ if( length > 0 )
+ {
+ do
+ {
+ v0 = buffer[ a3 ];
+ a2 = 7;
+ v0 = v0 << 8;
+ v1 = v1 ^ v0;
+ v0 = v1 & 0x8000;
+
+ do
+ {
+ if( v0 != 0 )
+ {
+ v0 = v1 << 1;
+ v1 = v0 ^ 0x1021;
+ }
+ else
+ {
+ v0 = v1 << 1;
+ v1 = v1 << 1;
+ }
+
+ a2--;
+ v0 = v1 & 0x8000;
+ } while( (signed) a2 >= 0 );
+
+ a3++;
+ v0 = (signed) a3 < (signed) length;
+ } while ( v0 != 0 );
+ }
+
+ v0 = ~v1 ;
+ v0 = v0 & 0xffff;
+
+ return v0;
+}
+
+static int zs01_data_offset( struct zs01_chip *c )
+{
+ int block = ( ( c->write_buffer[ 0 ] & 2 ) << 7 ) | c->write_buffer[ 1 ];
+
+ return block * SIZE_DATA_BUFFER;
+}
+
+void zs01_scl_write( int chip, int scl )
+{
+ struct zs01_chip *c;
+
+ if( chip >= ZS01_MAXCHIP )
+ {
+ verboselog( 0, "zs01_scl_write( %d ) chip out of range\n", chip );
+ return;
+ }
+
+ c = &zs01[ chip ];
+
+ if( c->scl != scl )
+ {
+ verboselog( 2, "zs01(%d) scl=%d\n", chip, scl );
+ }
+ if( c->cs == 0 )
+ {
+ switch( c->state )
+ {
+ case STATE_STOP:
+ break;
+
+ case STATE_RESPONSE_TO_RESET:
+ if( c->scl != 0 && scl == 0 )
+ {
+ if( c->bit == 0 )
+ {
+ c->shift = c->response_to_reset[ c->byte ];
+ verboselog( 1, "zs01(%d) <- response_to_reset[%d]: %02x\n", chip, c->byte, c->shift );
+ }
+
+ c->sdar = ( c->shift >> 7 ) & 1;
+ c->shift <<= 1;
+ c->bit++;
+
+ if( c->bit == 8 )
+ {
+ c->bit = 0;
+ c->byte++;
+ if( c->byte == 4 )
+ {
+ c->sdar = 1;
+ verboselog( 1, "zs01(%d) goto stop\n", chip );
+ c->state = STATE_STOP;
+ }
+ }
+ }
+ break;
+
+ case STATE_LOAD_COMMAND:
+ if( c->scl == 0 && scl != 0 )
+ {
+ if( c->bit < 8 )
+ {
+ verboselog( 2, "zs01(%d) clock\n", chip );
+ c->shift <<= 1;
+ if( c->sdaw != 0 )
+ {
+ c->shift |= 1;
+ }
+ c->bit++;
+ }
+ else
+ {
+ c->sdar = 0;
+
+ switch( c->state )
+ {
+ case STATE_LOAD_COMMAND:
+ c->write_buffer[ c->byte ] = c->shift;
+ verboselog( 2, "zs01(%d) -> write_buffer[%d]: %02x\n", chip, c->byte, c->write_buffer[ c->byte ] );
+
+ c->byte++;
+ if( c->byte == SIZE_WRITE_BUFFER )
+ {
+ UINT16 crc;
+
+ zs01_decrypt( c->write_buffer, c->write_buffer, SIZE_WRITE_BUFFER, c->command_key, 0xff );
+
+ if( ( c->write_buffer[ 0 ] & 4 ) != 0 )
+ {
+ zs01_decrypt2( &c->write_buffer[ 2 ], &c->write_buffer[ 2 ], SIZE_DATA_BUFFER, c->data_key, 0x00 );
+ }
+
+ crc = zs01_crc( c->write_buffer, 10 );
+
+ if( crc == ( ( c->write_buffer[ 10 ] << 8 ) | c->write_buffer[ 11 ] ) )
+ {
+ verboselog( 1, "zs01(%d) -> command: %02x\n", chip, c->write_buffer[ 0 ] );
+ verboselog( 1, "zs01(%d) -> address: %02x\n", chip, c->write_buffer[ 1 ] );
+ verboselog( 1, "zs01(%d) -> data: %02x%02x%02x%02x%02x%02x%02x%02x\n", chip,
+ c->write_buffer[ 2 ], c->write_buffer[ 3 ], c->write_buffer[ 4 ], c->write_buffer[ 5 ],
+ c->write_buffer[ 6 ], c->write_buffer[ 7 ], c->write_buffer[ 8 ], c->write_buffer[ 9 ] );
+ verboselog( 1, "zs01(%d) -> crc: %02x%02x\n", chip, c->write_buffer[ 10 ], c->write_buffer[ 11 ] );
+
+ switch( c->write_buffer[ 0 ] & 1 )
+ {
+ case COMMAND_WRITE:
+ memcpy( &c->data[ zs01_data_offset( c ) ], &c->write_buffer[ 2 ], SIZE_DATA_BUFFER );
+
+ /* todo: find out what should be returned. */
+ memset( &c->read_buffer[ 0 ], 0, SIZE_WRITE_BUFFER );
+ break;
+
+ case COMMAND_READ:
+ /* todo: find out what should be returned. */
+ memset( &c->read_buffer[ 0 ], 0, 2 );
+
+ switch( c->write_buffer[ 1 ] )
+ {
+ case 0xfd:
+ {
+ /* TODO: use read/write to talk to the ds2401, which will require a timer. */
+ int i;
+ for( i = 0; i < SIZE_DATA_BUFFER; i++ )
+ {
+ c->read_buffer[ 2 + i ] = c->ds2401[ SIZE_DATA_BUFFER - i - 1 ];
+ }
+ }
+ break;
+ default:
+ memcpy( &c->read_buffer[ 2 ], &c->data[ zs01_data_offset( c ) ], SIZE_DATA_BUFFER );
+ break;
+ }
+
+ memcpy( c->response_key, &c->write_buffer[ 2 ], SIZE_KEY );
+ break;
+ }
+ }
+ else
+ {
+ verboselog( 0, "zs01(%d) bad crc\n", chip );
+
+ /* todo: find out what should be returned. */
+ memset( &c->read_buffer[ 0 ], 0xff, 2 );
+ }
+
+ verboselog( 1, "zs01(%d) <- status: %02x%02\n", chip,
+ c->read_buffer[ 0 ], c->read_buffer[ 1 ] );
+
+ verboselog( 1, "zs01(%d) <- data: %02x%02x%02x%02x%02x%02x%02x%02x\n", chip,
+ c->read_buffer[ 2 ], c->read_buffer[ 3 ], c->read_buffer[ 4 ], c->read_buffer[ 5 ],
+ c->read_buffer[ 6 ], c->read_buffer[ 7 ], c->read_buffer[ 8 ], c->read_buffer[ 9 ] );
+
+ crc = zs01_crc( c->read_buffer, 10 );
+ c->read_buffer[ 10 ] = crc >> 8;
+ c->read_buffer[ 11 ] = crc & 255;
+
+ zs01_encrypt( c->read_buffer, c->read_buffer, SIZE_READ_BUFFER, c->response_key, 0xff );
+
+ c->byte = 0;
+ c->state = STATE_READ_DATA;
+ }
+ break;
+ }
+
+ c->bit = 0;
+ c->shift = 0;
+ }
+ }
+ break;
+
+ case STATE_READ_DATA:
+ if( c->scl == 0 && scl != 0 )
+ {
+ if( c->bit < 8 )
+ {
+ if( c->bit == 0 )
+ {
+ switch( c->state )
+ {
+ case STATE_READ_DATA:
+ c->shift = c->read_buffer[ c->byte ];
+ verboselog( 2, "zs01(%d) <- read_buffer[%d]: %02x\n", chip, c->byte, c->shift );
+ break;
+ }
+ }
+ c->sdar = ( c->shift >> 7 ) & 1;
+ c->shift <<= 1;
+ c->bit++;
+ }
+ else
+ {
+ c->bit = 0;
+ c->sdar = 0;
+ if( c->sdaw == 0 )
+ {
+ verboselog( 2, "zs01(%d) ack <-\n", chip );
+ c->byte++;
+ if( c->byte == SIZE_READ_BUFFER )
+ {
+ c->byte = 0;
+ c->sdar = 1;
+ c->state = STATE_LOAD_COMMAND;
+ }
+ }
+ else
+ {
+ verboselog( 2, "zs01(%d) nak <-\n", chip );
+ }
+ }
+ }
+ break;
+ }
+ }
+ c->scl = scl;
+}
+
+void zs01_sda_write( int chip, int sda )
+{
+ struct zs01_chip *c;
+
+ if( chip >= ZS01_MAXCHIP )
+ {
+ verboselog( 0, "zs01_sda_write( %d ) chip out of range\n", chip );
+ return;
+ }
+
+ c = &zs01[ chip ];
+
+ if( c->sdaw != sda )
+ {
+ verboselog( 2, "zs01(%d) sdaw=%d\n", chip, sda );
+ }
+ if( c->cs == 0 && c->scl != 0 )
+ {
+// if( c->sdaw == 0 && sda != 0 )
+// {
+// verboselog( 1, "zs01(%d) goto stop\n", chip );
+// c->state = STATE_STOP;
+// c->sdar = 0;
+// }
+ if( c->sdaw != 0 && sda == 0 )
+ {
+ switch( c->state )
+ {
+ case STATE_STOP:
+ verboselog( 1, "zs01(%d) goto start\n", chip );
+ c->state = STATE_LOAD_COMMAND;
+ break;
+
+// default:
+// verboselog( 1, "zs01(%d) skipped start (default)\n", chip );
+// break;
+ }
+
+ c->bit = 0;
+ c->byte = 0;
+ c->shift = 0;
+ c->sdar = 0;
+ }
+ }
+ c->sdaw = sda;
+}
+
+int zs01_sda_read( int chip )
+{
+ struct zs01_chip *c;
+
+ if( chip >= ZS01_MAXCHIP )
+ {
+ verboselog( 0, "zs01_sda_read( %d ) chip out of range\n", chip );
+ return 1;
+ }
+
+ c = &zs01[ chip ];
+ if( c->cs != 0 )
+ {
+ verboselog( 2, "zs01(%d) not selected\n", chip );
+ return 1;
+ }
+ verboselog( 2, "zs01(%d) sdar=%d\n", chip, c->sdar );
+
+ return c->sdar;
+}
+
+static void nvram_handler_zs01( int chip, running_machine *machine, mame_file *file, int read_or_write )
+{
+ struct zs01_chip *c;
+
+ if( chip >= ZS01_MAXCHIP )
+ {
+ verboselog( 0, "nvram_handler_zs01( %d ) chip out of range\n", chip );
+ return;
+ }
+
+ c = &zs01[ chip ];
+
+ if( read_or_write )
+ {
+ mame_fwrite( file, c->data, SIZE_DATA );
+ }
+ else if( file )
+ {
+ mame_fread( file, c->data, SIZE_DATA );
+ }
+}
+
+NVRAM_HANDLER( zs01_0 ) { nvram_handler_zs01( 0, machine, file, read_or_write ); }
+NVRAM_HANDLER( zs01_1 ) { nvram_handler_zs01( 1, machine, file, read_or_write ); }
diff --git a/src/mame/machine/zs01.h b/src/mame/machine/zs01.h
new file mode 100644
index 00000000000..cca23eadf43
--- /dev/null
+++ b/src/mame/machine/zs01.h
@@ -0,0 +1,25 @@
+/*
+ * zs01.h
+ *
+ * Secure SerialFlash
+ *
+ */
+
+#if !defined( ZS01_H )
+
+#define ZS01_MAXCHIP ( 2 )
+
+typedef void (*zs01_write_handler)( int pin, int value );
+typedef int (*zs01_read_handler)( int pin );
+
+extern void zs01_init( int chip, UINT8 *data, zs01_write_handler write, zs01_read_handler read, UINT8 *ds2401 );
+extern void zs01_cs_write( int chip, int cs );
+extern void zs01_rst_write( int chip, int rst );
+extern void zs01_scl_write( int chip, int scl );
+extern void zs01_sda_write( int chip, int sda );
+extern int zs01_sda_read( int chip );
+extern NVRAM_HANDLER( zs01_0 );
+extern NVRAM_HANDLER( zs01_1 );
+
+#define ZS01_H
+#endif