summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/firebeat.c
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2007-12-17 15:19:59 +0000
committer Aaron Giles <aaron@aarongiles.com>2007-12-17 15:19:59 +0000
commit7b77f1218624ea26dbb2efd85a19f795f5d4e02e (patch)
tree19209304095572b4fd61c2a2d6a5aa75c4e471ad /src/mame/drivers/firebeat.c
parent3da7f476068b3ffef713218ba2fc1bd5030f2c38 (diff)
Initial checkin of MAME 0.121.mame0121
Diffstat (limited to 'src/mame/drivers/firebeat.c')
-rw-r--r--src/mame/drivers/firebeat.c2413
1 files changed, 2413 insertions, 0 deletions
diff --git a/src/mame/drivers/firebeat.c b/src/mame/drivers/firebeat.c
new file mode 100644
index 00000000000..7c509fe6cd9
--- /dev/null
+++ b/src/mame/drivers/firebeat.c
@@ -0,0 +1,2413 @@
+/* Konami FireBeat
+
+ Driver by Ville Linde
+
+
+
+ Hardware overview:
+
+ GQ972 PWB(A2) 0000070609 Main board
+ -----------------------------------
+ IBM PowerPC 403GCX at 66MHz
+ (2x) Konami 0000057714 (2D object processor)
+ Yamaha YMZ280B (ADPCM sound chip)
+ Epson RTC65271 RTC/NVRAM
+ National Semiconductor PC16552DV (dual UART)
+
+ GQ974 PWB(A2) 0000070140 Extend board
+ -------------------------------------
+ ADC0808CCN
+ FDC37C665GT (floppy disk controller)
+ National Semiconductor PC16552DV (dual UART)
+ ADM223LJR (RS-232 driver/receiver)
+
+ GQ971 PWB(A2) 0000070254 SPU
+ ----------------------------
+ Motorola MC68HC000FN16 at 16MHz (?)
+ Xilinx XC9572 CPLD
+ Ricoh RF5c400 sound chip
+
+ GQ971 PWB(B2) 0000067784 Backplane
+ ----------------------------------
+ 3x PCB Slots with 2x DIN96S connectors (for main and extend PCBs)
+ 40-pin ATAPI connector for each slot
+
+ GQ986 PWB(A1) 0000073015 Backplane
+ ----------------------------------
+ 2x PCB Slots with 2x DIN96S connectors (for main and extend PCBs)
+ 40-pin ATAPI connector for each slot
+
+ GQ972 PWB(D2) Controller interface on Beatmania III (?)
+ GQ972 PWB(G1) Sound Amp (?)
+ GQ971 PWB(C) Sound Amp
+
+
+ Hardware configurations:
+
+ Beatmania III
+ -------------
+ GQ971 Backplane
+ GQ972 Main Board
+ GQ974 Extend Board
+ GQ971 SPU
+ GQ972 Controller Interface
+ GQ972 Sound Amp
+ Hard drive in Slot 1
+ DVD drive in Slot 2
+
+ Keyboardmania
+ -------------
+ GQ971 Backplane
+ GQ972 Main Board
+ GQ974 Extend Board
+ Yamaha XT446 board (for keyboard sounds) (the board layout matches the Yamaha MU100 Tone Generator)
+ GQ971 Sound Amp
+ CD-ROM drive in Slot 1
+ CD-ROM drive in Slot 2
+
+ ParaParaParadise
+ ----------------
+ GQ986 Backplane
+ GQ972 Main Board
+ 2x CD-ROM drive in Slot 1
+
+
+
+ Games that run on this hardware:
+
+ BIOS Game ID Year Game
+ ------------------------------------------------------------------
+ GQ972 GQ972 2000 Beatmania III
+ GQ972(?) ? 2001 Beatmania III Append 6th Mix
+ GQ972(?) ? 2002 Beatmania III Append 7th Mix
+ GQ972(?) ? 2000 Beatmania III Append Core Remix
+ GQ972(?) ? 2003 Beatmania III The Final
+ GQ974 GQ974 2000 Keyboardmania
+ GQ974 GCA01 2000 Keyboardmania 2nd Mix
+ GQ974 GCA12 2001 Keyboardmania 3rd Mix
+ GQ977 GQ977 2000 Para Para Paradise
+ GQ977 GQ977 2000 Para Para Dancing
+ GQ977 GC977 2000 Para Para Paradise 1.1
+ GQ977 GQA11 2000 Para Para Paradise 1st Mix+
+ GQA02(?) ? 2000 Pop n' Music 4
+ ??? ? 2000 Pop n' Music 5
+ ??? ? 2001 Pop n' Music 6
+ GQA02 GCB00 2001 Pop n' Music 7
+ ??? ? 2002 Pop n' Music 8
+ ??? ? 2000 Pop n' Music Animelo
+ ??? ? 2001 Pop n' Music Animelo 2
+ ??? ? 2001 Pop n' Music Mickey Tunes
+
+ TODO:
+ - The display list pointer setting in the graphics chip is not understood. Currently
+ it has to be changed manually. (BIOS = 0x200000, PPP bootup = 0x1D0800, ingame = 0x0000, 0x8000 & 0x10000)
+
+ - Keyboardmania 3rd mix is missing some graphics in the ingame. Most notably the backgrounds.
+ The display list objects seem to be there, but the address is wrong (0x14c400, instead of the correct address)
+
+ - The external Yamaha MIDI sound board is not emulated (no keyboard sounds).
+*/
+
+#include "driver.h"
+#include "cpu/powerpc/ppc.h"
+#include "machine/intelfsh.h"
+#include "machine/scsicd.h"
+#include "machine/rtc65271.h"
+#include "machine/pc16552d.h"
+#include "sound/ymz280b.h"
+#include "sound/cdda.h"
+#include "cdrom.h"
+#include "firebeat.lh"
+
+
+
+typedef struct
+{
+ UINT32 *vram;
+ UINT32 vram_read_address;
+ UINT32 vram_write_fifo_address;
+ UINT32 visible_area;
+} GCU_REGS;
+
+static UINT8 xram[4096];
+static UINT8 extend_board_irq_enable;
+static UINT8 extend_board_irq_active;
+
+static emu_timer *keyboard_timer;
+
+static GCU_REGS gcu[2];
+
+static VIDEO_START(firebeat)
+{
+ gcu[0].vram = auto_malloc(0x2000000);
+ gcu[1].vram = auto_malloc(0x2000000);
+ memset(gcu[0].vram, 0, 0x2000000);
+ memset(gcu[1].vram, 0, 0x2000000);
+}
+
+
+static void gcu_draw_object(int chip, mame_bitmap *bitmap, const rectangle *cliprect, UINT32 *cmd)
+{
+ // 0x00: xxx----- -------- -------- -------- command type
+ // 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx object data address in vram
+
+ // 0x01: -------- -------- ------xx xxxxxxxx object x
+ // 0x01: -------- ----xxxx xxxxxx-- -------- object y
+ // 0x01: -----x-- -------- -------- -------- object x flip
+ // 0x01: ----x--- -------- -------- -------- object y flip
+ // 0x01: ---x---- -------- -------- -------- object alpha enable (?)
+
+ // 0x02: -------- -------- ------xx xxxxxxxx object width
+ // 0x02: -------- -----xxx xxxxxx-- -------- object x scale
+
+ // 0x03: -------- -------- ------xx xxxxxxxx object height
+ // 0x03: -------- -----xxx xxxxxx-- -------- object y scale
+
+ int x = cmd[1] & 0x3ff;
+ int y = (cmd[1] >> 10) & 0x3ff;
+ int width = (cmd[2] & 0x3ff) + 1;
+ int height = (cmd[3] & 0x3ff) + 1;
+ int xscale = (cmd[2] >> 10) & 0x1ff;
+ int yscale = (cmd[3] >> 10) & 0x1ff;
+ int xflip = (cmd[1] & 0x04000000) ? 1 : 0;
+ int yflip = (cmd[1] & 0x08000000) ? 1 : 0;
+ int alpha_enable = (cmd[1] & 0x10000000) ? 1 : 0;
+ UINT32 address = cmd[0] & 0xffffff;
+ int alpha_level = (cmd[2] >> 27) & 0x1f;
+
+ int i, j;
+ int u, v;
+ UINT16 *vr = (UINT16*)gcu[chip].vram;
+
+ if (xscale == 0 || yscale == 0)
+ {
+ xscale = 0x40;
+ yscale = 0x40;
+ return;
+ }
+
+ //if ((cmd[2] >> 24) != 0x84 && (cmd[2] >> 24) != 0x04 && (cmd[2] >> 24) != 0x00)
+ // printf("Unknown value = %d, %d\n", (cmd[2] >> 27) & 0x1f, (cmd[2] >> 22) & 0x1f);
+
+ width = (((width * 65536) / xscale) * 64) / 65536;
+ height = (((height * 65536) / yscale) * 64) / 65536;
+
+ if (y > cliprect->max_y || x > cliprect->max_x) {
+ return;
+ }
+ if ((y+height) > cliprect->max_y) {
+ height = cliprect->max_y - y;
+ }
+ if ((x+width) > cliprect->max_x) {
+ width = cliprect->max_x - x;
+ }
+
+ v = 0;
+ for (j=0; j < height; j++)
+ {
+ int xi;
+ int index;
+ UINT16 *d = BITMAP_ADDR16(bitmap, j+y, x);
+ //int index = address + ((v >> 6) * 1024);
+
+ if (yflip)
+ {
+ index = address + ((height - 1 - (v >> 6)) * 1024);
+ }
+ else
+ {
+ index = address + ((v >> 6) * 1024);
+ }
+
+ if (xflip)
+ {
+ d += width;
+ xi = -1;
+ }
+ else
+ {
+ xi = 1;
+ }
+
+ u = 0;
+ for (i=0; i < width; i++)
+ {
+ UINT16 pix = vr[((index + (u >> 6)) ^ 1) & 0xffffff];
+
+ if (alpha_enable)
+ {
+ if (pix & 0x8000)
+ {
+ if ((pix & 0x7fff) != 0)
+ {
+ //*d = pix & 0x7fff;
+ UINT16 srcpix = *d;
+ /*
+ UINT32 r = pix & 0x7c00;
+ UINT32 g = pix & 0x03e0;
+ UINT32 b = pix & 0x001f;
+
+ UINT32 sr = srcpix & 0x7c00;
+ UINT32 sg = srcpix & 0x03e0;
+ UINT32 sb = srcpix & 0x001f;
+
+ sr += r;
+ sg += g;
+ sb += b;
+ if (sr > 0x7c00) sr = 0x7c00;
+ if (sg > 0x03e0) sg = 0x03e0;
+ if (sb > 0x001f) sb = 0x001f;
+
+ *d = sr | sg | sb;
+ */
+
+ UINT32 sr = (srcpix >> 10) & 0x1f;
+ UINT32 sg = (srcpix >> 5) & 0x1f;
+ UINT32 sb = (srcpix >> 0) & 0x1f;
+ UINT32 r = (pix >> 10) & 0x1f;
+ UINT32 g = (pix >> 5) & 0x1f;
+ UINT32 b = (pix >> 0) & 0x1f;
+
+ sr += (r * alpha_level) >> 4;
+ sg += (g * alpha_level) >> 4;
+ sb += (b * alpha_level) >> 4;
+
+ if (sr > 0x1f) sr = 0x1f;
+ if (sg > 0x1f) sg = 0x1f;
+ if (sb > 0x1f) sb = 0x1f;
+
+ *d = (sr << 10) | (sg << 5) | sb;
+ }
+ }
+ }
+ else
+ {
+ if (pix & 0x8000)
+ {
+ *d = pix & 0x7fff;
+ }
+ }
+
+ if ((cmd[0] & 0x10000000) == 0)
+ *d = 0x7fff;
+
+ d += xi;
+ u += xscale;
+ }
+
+ v += yscale;
+ }
+}
+
+static void gcu_fill_rect(mame_bitmap *bitmap, const rectangle *cliprect, UINT32 *cmd)
+{
+ int i, j;
+ int x1, y1, x2, y2;
+
+ int x = cmd[1] & 0x3ff;
+ int y = (cmd[1] >> 10) & 0x3ff;
+ int width = (cmd[0] & 0x3ff) + 1;
+ int height = ((cmd[0] >> 10) & 0x3ff) + 1;
+
+ UINT16 color[4];
+
+ color[0] = (cmd[2] >> 16);
+ color[1] = (cmd[2] >> 0);
+ color[2] = (cmd[3] >> 16);
+ color[3] = (cmd[3] >> 0);
+
+ x1 = x;
+ x2 = x + width;
+ y1 = y;
+ y2 = y + height;
+
+ if ((color[0] & 0x8000) == 0 && (color[1] & 0x8000) == 0 && (color[2] & 0x8000) == 0 && (color[3] & 0x8000) == 0)
+ {
+ // optimization, nothing to fill
+ return;
+ }
+
+ // clip
+ if (x1 < cliprect->min_x) x1 = cliprect->min_x;
+ if (y1 < cliprect->min_y) y1 = cliprect->min_y;
+ if (x2 > cliprect->max_x) x2 = cliprect->max_x;
+ if (y2 > cliprect->max_y) y2 = cliprect->max_y;
+
+ for (j=y1; j < y2; j++)
+ {
+ UINT16 *d = BITMAP_ADDR16(bitmap, j, 0);
+ for (i=x1; i < x2; i++)
+ {
+ if (color[i&3] & 0x8000)
+ {
+ d[i] = color[i&3] & 0x7fff;
+ }
+ }
+ }
+}
+
+static void gcu_draw_character(int chip, mame_bitmap *bitmap, const rectangle *cliprect, UINT32 *cmd)
+{
+ // 0x00: xxx----- -------- -------- -------- command type
+ // 0x00: -------- xxxxxxxx xxxxxxxx xxxxxxxx character data address in vram
+
+ // 0x01: -------- -------- ------xx xxxxxxxx character x
+ // 0x01: -------- ----xxxx xxxxxx-- -------- character y
+
+ // 0x02: xxxxxxxx xxxxxxxx -------- -------- color 0
+ // 0x02: -------- -------- xxxxxxxx xxxxxxxx color 1
+
+ // 0x03: xxxxxxxx xxxxxxxx -------- -------- color 2
+ // 0x03: -------- -------- xxxxxxxx xxxxxxxx color 3
+
+ int i, j;
+ int x = cmd[1] & 0x3ff;
+ int y = (cmd[1] >> 10) & 0x3ff;
+ UINT32 address = cmd[0] & 0xffffff;
+ UINT16 color[4];
+
+ UINT16 *vr = (UINT16*)gcu[chip].vram;
+
+ color[0] = (cmd[2] >> 16) & 0xffff;
+ color[1] = (cmd[2] >> 0) & 0xffff;
+ color[2] = (cmd[3] >> 16) & 0xffff;
+ color[3] = (cmd[3] >> 0) & 0xffff;
+
+
+ if (y > cliprect->max_y || x > cliprect->max_x) {
+ return;
+ }
+
+
+ for (j=0; j < 8; j++)
+ {
+ UINT16 *d = BITMAP_ADDR16(bitmap, y+j, x);
+ UINT16 line = vr[address^1];
+
+ address += 4;
+
+ for (i=0; i < 8; i++)
+ {
+ int pix = (line >> ((7-i) * 2)) & 3;
+ d[i] = color[pix];
+ }
+ }
+}
+
+static void gcu_exec_display_list(int chip, mame_bitmap *bitmap, const rectangle *cliprect, UINT32 address)
+{
+ int counter = 0;
+ int end = 0;
+
+ int i = address / 4;
+ if (i < 0) i = 0;
+ while (!end && counter < 0x1000 && i < (0x2000000/4))
+ {
+ int command;
+ UINT32 cmd[4];
+ cmd[0] = gcu[chip].vram[i+0];
+ cmd[1] = gcu[chip].vram[i+1];
+ cmd[2] = gcu[chip].vram[i+2];
+ cmd[3] = gcu[chip].vram[i+3];
+
+ command = (cmd[0] >> 29) & 0x7;
+
+ switch (command)
+ {
+ case 0x0: // ???
+ {
+ break;
+ }
+
+ case 0x1: // Branch
+ {
+ gcu_exec_display_list(chip, bitmap, cliprect, cmd[0] & 0xffffff);
+ break;
+ }
+
+ case 0x2: // End of display list
+ {
+ end = 1;
+ break;
+ }
+
+ case 0x3: // ???
+ {
+ break;
+ }
+
+ case 0x4: // Fill rectangle
+ {
+ gcu_fill_rect(bitmap, cliprect, cmd);
+ break;
+ }
+
+ case 0x5: // Draw object
+ {
+ gcu_draw_object(chip, bitmap, cliprect, cmd);
+ break;
+ }
+
+ case 0x7: // Draw 8x8 Character (2-bits per pixel)
+ {
+ gcu_draw_character(chip, bitmap, cliprect, cmd);
+ break;
+ }
+
+ default:
+ //printf("Unknown command %08X %08X %08X %08X at %08X\n", cmd[0], cmd[1], cmd[2], cmd[3], i*4);
+ break;
+ }
+
+ i += 4;
+ counter++;
+ };
+}
+
+static int tick = 0;
+static int layer = 0;
+static VIDEO_UPDATE(firebeat)
+{
+ int chip = screen;
+ //int i;
+
+ fillbitmap(bitmap, 0, cliprect);
+
+ if (mame_stricmp(machine->gamedrv->name, "popn7") == 0)
+ {
+ gcu_exec_display_list(chip, bitmap, cliprect, 0x1f80000);
+ }
+ else
+ {
+ if (layer >= 2)
+ {
+ gcu_exec_display_list(chip, bitmap, cliprect, 0x8000);
+ gcu_exec_display_list(chip, bitmap, cliprect, 0x0000);
+ gcu_exec_display_list(chip, bitmap, cliprect, 0x10000);
+ }
+ else if (layer == 0)
+ {
+ gcu_exec_display_list(chip, bitmap, cliprect, 0x200000);
+
+ //gcu_exec_display_list(chip, bitmap, cliprect, 0x186040);
+ }
+ else if (layer == 1)
+ {
+ gcu_exec_display_list(chip, bitmap, cliprect, 0x1d0800);
+
+ gcu_exec_display_list(chip, bitmap, cliprect, 0x1a9440);
+ }
+ }
+
+ tick++;
+ if (tick >= 5)
+ {
+ tick = 0;
+ if (input_code_pressed(KEYCODE_0))
+ {
+ layer++;
+ if (layer > 2)
+ {
+ layer = 0;
+ }
+ }
+
+ /*
+ if (input_code_pressed_once(KEYCODE_9))
+ {
+ FILE *file = fopen("vram0.bin", "wb");
+ int i;
+
+ for (i=0; i < 0x2000000/4; i++)
+ {
+ fputc((gcu[0].vram[i] >> 24) & 0xff, file);
+ fputc((gcu[0].vram[i] >> 16) & 0xff, file);
+ fputc((gcu[0].vram[i] >> 8) & 0xff, file);
+ fputc((gcu[0].vram[i] >> 0) & 0xff, file);
+ }
+
+ fclose(file);
+ file = fopen("vram1.bin", "wb");
+
+ for (i=0; i < 0x2000000/4; i++)
+ {
+ fputc((gcu[1].vram[i] >> 24) & 0xff, file);
+ fputc((gcu[1].vram[i] >> 16) & 0xff, file);
+ fputc((gcu[1].vram[i] >> 8) & 0xff, file);
+ fputc((gcu[1].vram[i] >> 0) & 0xff, file);
+ }
+
+ fclose(file);
+ }
+ */
+ }
+
+ return 0;
+}
+
+static UINT32 GCU_r(int chip, UINT32 offset, UINT32 mem_mask)
+{
+ int reg = offset * 4;
+
+ /* VRAM Read */
+ if (reg >= 0x80 && reg < 0x100)
+ {
+ return gcu[chip].vram[gcu[chip].vram_read_address + ((reg/4) - 0x20)];
+ }
+
+ switch(reg)
+ {
+ case 0x78: /* GCU Status */
+ return 0xffff0005;
+
+ default:
+ break;
+ }
+
+ return 0xffffffff;
+}
+
+static void GCU_w(int chip, UINT32 offset, UINT32 data, UINT32 mem_mask)
+{
+ int reg = offset * 4;
+
+ if (reg != 0x70 && chip == 0)
+ {
+ //printf("gcu%d_w: %08X, %08X, %08X at %08X\n", chip, data, offset, mem_mask, activecpu_get_pc());
+ //logerror("gcu%d_w: %08X, %08X, %08X at %08X\n", chip, data, offset, mem_mask, activecpu_get_pc());
+ }
+
+ switch(reg)
+ {
+ case 0x10: /* ??? */
+ break;
+
+ case 0x30:
+ //case 0x34:
+ //case 0x38:
+ //case 0x3c:
+ {
+ COMBINE_DATA( &gcu[chip].visible_area );
+ if (ACCESSING_LSW32)
+ {
+ int screen = chip;
+ int width, height;
+ screen_state *state = &Machine->screen[screen];
+ rectangle visarea = state->visarea;
+
+ width = (gcu[chip].visible_area & 0xffff);
+ height = (gcu[chip].visible_area >> 16) & 0xffff;
+ //set_visible_area(0, width, 0, height);
+
+ visarea.max_x = width-1;
+ visarea.max_y = height-1;
+
+ // only try and update the screen if the driver says we have one
+ if(Machine->drv->screen[screen].tag)
+ video_screen_configure(screen, visarea.max_x + 1, visarea.max_y + 1, &visarea, Machine->screen[screen].refresh);
+ }
+ break;
+ }
+
+ case 0x40: /* ??? */
+ break;
+
+ //case 0x44: /* ??? */
+ // break;
+
+ case 0x5c: /* VRAM Read Address */
+ gcu[chip].vram_read_address = (data & 0xffffff) / 2;
+ break;
+
+ case 0x60: /* VRAM FIFO Write Address */
+ gcu[chip].vram_write_fifo_address = (data & 0xffffff) / 2;
+
+ // printf("gcu%d_w: %08X, %08X, %08X\n", chip, data, offset, mem_mask);
+ break;
+
+ case 0x68: /* Unknown */
+ {
+ break;
+ }
+
+ case 0x70: /* VRAM FIFO Write */
+ gcu[chip].vram[gcu[chip].vram_write_fifo_address] = data;
+ gcu[chip].vram_write_fifo_address++;
+ break;
+
+ default:
+ // printf("gcu%d_w: %08X, %08X, %08X\n", chip, data, offset, mem_mask);
+ break;
+ }
+}
+
+static READ32_HANDLER(gcu0_r)
+{
+ return GCU_r(0, offset, mem_mask);
+}
+
+static WRITE32_HANDLER(gcu0_w)
+{
+ GCU_w(0, offset, data, mem_mask);
+}
+
+static READ32_HANDLER(gcu1_r)
+{
+ return GCU_r(1, offset, mem_mask);
+}
+
+static WRITE32_HANDLER(gcu1_w)
+{
+ GCU_w(1, offset, data, mem_mask);
+}
+
+/*****************************************************************************/
+
+static READ32_HANDLER(input_r)
+{
+ UINT32 r = 0;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= (readinputport(0) & 0xff) << 24;
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ r |= (readinputport(1) & 0xff) << 8;
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ r |= (readinputport(2) & 0xff);
+ }
+
+ return r;
+}
+
+static READ32_HANDLER( sensor_r )
+{
+ if (offset == 0)
+ {
+ return readinputport(3) | 0x01000100;
+ }
+ else
+ {
+ return readinputport(4) | 0x01000100;
+ }
+}
+
+static READ32_HANDLER(flashram_r)
+{
+ UINT32 r = 0;
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= (intelflash_read(0, (offset*4)+0) & 0xff) << 24;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ r |= (intelflash_read(0, (offset*4)+1) & 0xff) << 16;
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ r |= (intelflash_read(0, (offset*4)+2) & 0xff) << 8;
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ r |= (intelflash_read(0, (offset*4)+3) & 0xff) << 0;
+ }
+ return r;
+}
+
+static WRITE32_HANDLER(flashram_w)
+{
+ if (!(mem_mask & 0xff000000))
+ {
+ intelflash_write(0, (offset*4)+0, (data >> 24) & 0xff);
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ intelflash_write(0, (offset*4)+1, (data >> 16) & 0xff);
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ intelflash_write(0, (offset*4)+2, (data >> 8) & 0xff);
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ intelflash_write(0, (offset*4)+3, (data >> 0) & 0xff);
+ }
+}
+
+static READ32_HANDLER(soundflash_r)
+{
+ UINT32 r = 0;
+ int chip;
+ if (offset >= 0 && offset < 0x200000/4)
+ {
+ chip = 1;
+ }
+ else
+ {
+ chip = 2;
+ }
+
+ offset &= 0x7ffff;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= (intelflash_read(chip, (offset*4)+0) & 0xff) << 24;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ r |= (intelflash_read(chip, (offset*4)+1) & 0xff) << 16;
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ r |= (intelflash_read(chip, (offset*4)+2) & 0xff) << 8;
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ r |= (intelflash_read(chip, (offset*4)+3) & 0xff) << 0;
+ }
+ return r;
+}
+
+static WRITE32_HANDLER(soundflash_w)
+{
+ int chip;
+ if (offset >= 0 && offset < 0x200000/4)
+ {
+ chip = 1;
+ }
+ else
+ {
+ chip = 2;
+ }
+
+ offset &= 0x7ffff;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ intelflash_write(chip, (offset*4)+0, (data >> 24) & 0xff);
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ intelflash_write(chip, (offset*4)+1, (data >> 16) & 0xff);
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ intelflash_write(chip, (offset*4)+2, (data >> 8) & 0xff);
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ intelflash_write(chip, (offset*4)+3, (data >> 0) & 0xff);
+ }
+}
+
+/*****************************************************************************/
+/* ATAPI Interface */
+
+#define BYTESWAP16(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
+
+#if 1
+#define ATAPI_ENDIAN(x) (BYTESWAP16(x))
+#else
+#define ATAPI_ENDIAN(x) (x)
+#endif
+
+#define ATAPI_CYCLES_PER_SECTOR (32000) // plenty of time to allow DMA setup etc. BIOS requires this be at least 2000, individual games may vary.
+
+static UINT8 atapi_regs[16];
+static SCSIInstance *atapi_device_data[2];
+
+#define ATAPI_STAT_BSY 0x80
+#define ATAPI_STAT_DRDY 0x40
+#define ATAPI_STAT_DMARDDF 0x20
+#define ATAPI_STAT_SERVDSC 0x10
+#define ATAPI_STAT_DRQ 0x08
+#define ATAPI_STAT_CORR 0x04
+#define ATAPI_STAT_CHECK 0x01
+
+#define ATAPI_INTREASON_COMMAND 0x01
+#define ATAPI_INTREASON_IO 0x02
+#define ATAPI_INTREASON_RELEASE 0x04
+
+#define ATAPI_REG_DATA 0
+#define ATAPI_REG_ERRFEAT 1
+#define ATAPI_REG_INTREASON 2
+#define ATAPI_REG_SAMTAG 3
+#define ATAPI_REG_COUNTLOW 4
+#define ATAPI_REG_COUNTHIGH 5
+#define ATAPI_REG_DRIVESEL 6
+#define ATAPI_REG_CMDSTATUS 7
+
+static UINT16 atapi_data[32*1024];
+static UINT8 atapi_scsi_packet[32*1024];
+static int atapi_data_ptr, atapi_xferlen, atapi_xfermod, atapi_cdata_wait;
+static int atapi_drivesel;
+
+static void atapi_cause_irq(void)
+{
+ cpunum_set_input_line(0, INPUT_LINE_IRQ4, ASSERT_LINE);
+}
+
+static void atapi_init(void)
+{
+ memset(atapi_regs, 0, sizeof(atapi_regs));
+
+ atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
+ atapi_regs[ATAPI_REG_ERRFEAT] = 1;
+ atapi_regs[ATAPI_REG_COUNTLOW] = 0x14;
+ atapi_regs[ATAPI_REG_COUNTHIGH] = 0xeb;
+
+ atapi_data_ptr = 0;
+ atapi_cdata_wait = 0;
+
+ // allocate two SCSI CD-ROM devices
+ SCSIAllocInstance( SCSI_DEVICE_CDROM, &atapi_device_data[0], 0 );
+ // TODO: the slave drive can be either CD-ROM, DVD-ROM or HDD
+ SCSIAllocInstance( SCSI_DEVICE_CDROM, &atapi_device_data[1], 1 );
+}
+
+static void atapi_reset(void)
+{
+ logerror("ATAPI reset\n");
+
+ atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
+ atapi_regs[ATAPI_REG_ERRFEAT] = 1;
+ atapi_regs[ATAPI_REG_COUNTLOW] = 0x14;
+ atapi_regs[ATAPI_REG_COUNTHIGH] = 0xeb;
+
+ atapi_data_ptr = 0;
+ atapi_cdata_wait = 0;
+}
+
+
+
+static UINT16 atapi_command_reg_r(int reg)
+{
+ int i, data;
+ static UINT8 temp_data[64*1024];
+
+// printf("ATAPI: Command reg read %d\n", reg);
+
+ if (reg == ATAPI_REG_DATA)
+ {
+ // assert IRQ and drop DRQ
+ if (atapi_data_ptr == 0)
+ {
+ //printf("ATAPI: dropping DRQ\n");
+ atapi_cause_irq();
+ atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
+
+ // get the data from the device
+ SCSIReadData( atapi_device_data[atapi_drivesel], temp_data, atapi_xferlen );
+
+ // fix it up in an endian-safe way
+ for (i = 0; i < atapi_xferlen; i += 2)
+ {
+ atapi_data[i/2] = temp_data[i+0] | temp_data[i+1]<<8;
+ }
+ }
+
+ data = atapi_data[atapi_data_ptr];
+// printf("ATAPI: %d, packet read = %04x\n", atapi_data_ptr, atapi_data[atapi_data_ptr]);
+ atapi_data_ptr++;
+
+ if (atapi_xfermod && atapi_data_ptr == (atapi_xferlen/2))
+ {
+ //printf("ATAPI: DRQ interrupt\n");
+ atapi_cause_irq();
+ atapi_regs[ATAPI_REG_CMDSTATUS] |= ATAPI_STAT_DRQ;
+ atapi_data_ptr = 0;
+
+ if (atapi_xfermod > 63488)
+ {
+ atapi_xfermod = atapi_xfermod - 63488;
+ atapi_xferlen = 63488;
+ }
+ else
+ {
+ atapi_xferlen = atapi_xfermod;
+ atapi_xfermod = 0;
+ }
+
+ //printf("ATAPI Transfer: %d, %d, %d\n", atapi_transfer_length, atapi_xfermod, atapi_xferlen);
+
+ atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
+ atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
+ }
+ return data;
+ }
+ else
+ {
+ return atapi_regs[reg];
+ }
+}
+
+static void atapi_command_reg_w(int reg, UINT16 data)
+{
+ int i;
+
+ if (reg == ATAPI_REG_DATA)
+ {
+// printf("ATAPI: packet write %04x at %08X\n", data, activecpu_get_pc());
+ atapi_data[atapi_data_ptr] = data;
+ atapi_data_ptr++;
+
+ if (atapi_cdata_wait)
+ {
+// printf("ATAPI: waiting, ptr %d wait %d\n", atapi_data_ptr, atapi_cdata_wait);
+ if (atapi_data_ptr == atapi_cdata_wait)
+ {
+ // decompose SCSI packet into proper byte order
+ for (i = 0; i < atapi_cdata_wait; i += 2)
+ {
+ atapi_scsi_packet[i] = atapi_data[i/2]&0xff;
+ atapi_scsi_packet[i+1] = atapi_data[i/2]>>8;
+ }
+
+ // send it to the device
+ SCSIWriteData( atapi_device_data[atapi_drivesel], atapi_scsi_packet, atapi_cdata_wait );
+
+ // assert IRQ
+ atapi_cause_irq();
+
+ // not sure here, but clear DRQ at least?
+ atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
+ }
+ }
+
+ if ((!atapi_cdata_wait) && (atapi_data_ptr == 6))
+ {
+ int phase;
+
+ // reset data pointer for reading SCSI results
+ atapi_data_ptr = 0;
+
+ atapi_regs[ATAPI_REG_CMDSTATUS] |= ATAPI_STAT_BSY;
+
+ // assert IRQ
+ atapi_cause_irq();
+
+ // decompose SCSI packet into proper byte order
+ for (i = 0; i < 16; i += 2)
+ {
+ atapi_scsi_packet[i+0] = atapi_data[i/2]&0xff;
+ atapi_scsi_packet[i+1] = atapi_data[i/2]>>8;
+ }
+
+ // send it to the SCSI device
+ SCSISetCommand( atapi_device_data[atapi_drivesel], atapi_scsi_packet, 12 );
+ SCSIExecCommand( atapi_device_data[atapi_drivesel], &atapi_xferlen );
+ SCSIGetPhase( atapi_device_data[atapi_drivesel], &phase );
+
+ if (atapi_xferlen != -1)
+ {
+ logerror("ATAPI: SCSI command %02x returned %d bytes from the device\n", atapi_data[0]&0xff, atapi_xferlen);
+
+ // store the returned command length in the ATAPI regs, splitting into
+ // multiple transfers if necessary
+
+ atapi_xfermod = 0;
+ if (atapi_xferlen > 63488)
+ {
+ atapi_xfermod = atapi_xferlen - 63488;
+ atapi_xferlen = 63488;
+ }
+
+// printf("ATAPI Transfer: %d, %d\n", atapi_xfermod, atapi_xferlen);
+
+ atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
+ atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
+
+ switch( phase )
+ {
+ case SCSI_PHASE_DATAOUT:
+ atapi_data_ptr = 0;
+ atapi_cdata_wait = atapi_xferlen;
+ logerror("ATAPI: Waiting for %x bytes of data\n", atapi_cdata_wait);
+ break;
+ }
+
+ // perform special ATAPI processing of certain commands
+ switch (atapi_data[0]&0xff)
+ {
+ case 0xa8: // READ (12)
+ // indicate data ready: set DRQ and DMA ready, and IO in INTREASON
+ atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_SERVDSC;
+ atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
+
+ fatalerror("ATAPI: DMA read command attempted\n");
+ break;
+
+ case 0x00: // BUS RESET / TEST UNIT READY
+ case 0xbb: // SET CD SPEED
+ case 0xa5: // PLAY AUDIO
+ case 0x1b:
+ case 0x4e:
+ atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
+ break;
+ }
+ }
+ else
+ {
+// printf("ATAPI: SCSI device returned error!\n");
+
+ atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_CHECK;
+ atapi_regs[ATAPI_REG_ERRFEAT] = 0x50; // sense key = ILLEGAL REQUEST
+ atapi_regs[ATAPI_REG_COUNTLOW] = 0;
+ atapi_regs[ATAPI_REG_COUNTHIGH] = 0;
+ }
+ }
+ }
+ else
+ {
+ data &= 0xff;
+ atapi_regs[reg] = data;
+// printf("ATAPI: Command reg %d = %02X\n", reg, data);
+
+ switch(reg)
+ {
+ case ATAPI_REG_DRIVESEL:
+ atapi_drivesel = (data >> 4) & 0x1;
+ break;
+
+ case ATAPI_REG_CMDSTATUS:
+// printf("ATAPI: Issued command %02X\n", data);
+
+ switch(data)
+ {
+ case 0x00: /* NOP */
+ break;
+
+ case 0x08: /* ATAPI Soft Reset */
+ atapi_reset();
+ break;
+
+ case 0xa0: /* ATAPI Packet */
+ atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_BSY | ATAPI_STAT_DRQ;
+ atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_COMMAND;
+
+ atapi_data_ptr = 0;
+ atapi_cdata_wait = 0;
+ break;
+
+ default:
+ fatalerror("ATAPI: Unknown ATA command %02X\n", data);
+ }
+ break;
+ }
+ }
+}
+
+static UINT16 atapi_control_reg_r(int reg)
+{
+ UINT16 value;
+ switch(reg)
+ {
+ case 0x6:
+ {
+ value = atapi_regs[ATAPI_REG_CMDSTATUS];
+ if (atapi_regs[ATAPI_REG_CMDSTATUS] & ATAPI_STAT_BSY)
+ {
+ atapi_regs[ATAPI_REG_CMDSTATUS] ^= ATAPI_STAT_BSY;
+ }
+ return value;
+ }
+
+ default:
+ fatalerror("ATAPI: Read control reg %d\n", reg);
+ break;
+ }
+
+ return 0;
+}
+
+static void atapi_control_reg_w(int reg, UINT16 data)
+{
+ switch(reg)
+ {
+ case 0x06: /* Device Control */
+ {
+ if (data & 0x4)
+ {
+ atapi_reset();
+ }
+ break;
+ }
+
+ default:
+ fatalerror("ATAPI: Control reg %d = %02X\n", reg, data);
+ }
+}
+
+
+
+static READ32_HANDLER( atapi_command_r )
+{
+ UINT16 r;
+// printf("atapi_command_r: %08X, %08X\n", offset, mem_mask);
+ if (mem_mask == 0x0000ffff)
+ {
+ r = atapi_command_reg_r(offset*2);
+ return ATAPI_ENDIAN(r) << 16;
+ }
+ else
+ {
+ r = atapi_command_reg_r((offset*2) + 1);
+ return ATAPI_ENDIAN(r) << 0;
+ }
+}
+
+static WRITE32_HANDLER( atapi_command_w )
+{
+// printf("atapi_command_w: %08X, %08X, %08X\n", data, offset, mem_mask);
+
+ if (mem_mask == 0x0000ffff)
+ {
+ atapi_command_reg_w(offset*2, ATAPI_ENDIAN((data >> 16) & 0xffff));
+ }
+ else
+ {
+ atapi_command_reg_w((offset*2) + 1, ATAPI_ENDIAN((data >> 0) & 0xffff));
+ }
+}
+
+
+static READ32_HANDLER( atapi_control_r )
+{
+ UINT16 r;
+// printf("atapi_control_r: %08X, %08X\n", offset, mem_mask);
+
+ if (mem_mask == 0x0000ffff)
+ {
+ r = atapi_control_reg_r(offset*2);
+ return ATAPI_ENDIAN(r) << 16;
+ }
+ else
+ {
+ r = atapi_control_reg_r((offset*2) + 1);
+ return ATAPI_ENDIAN(r) << 0;
+ }
+}
+
+static WRITE32_HANDLER( atapi_control_w )
+{
+ if (mem_mask == 0x0000ffff)
+ {
+ atapi_control_reg_w(offset*2, ATAPI_ENDIAN(data >> 16) & 0xff);
+ }
+ else
+ {
+ atapi_control_reg_w((offset*2) + 1, ATAPI_ENDIAN(data >> 0) & 0xff);
+ }
+}
+
+
+/*****************************************************************************/
+
+static READ32_HANDLER( comm_uart_r )
+{
+ UINT32 r = 0;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= pc16552d_0_r((offset*4)+0) << 24;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ r |= pc16552d_0_r((offset*4)+1) << 16;
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ r |= pc16552d_0_r((offset*4)+2) << 8;
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ r |= pc16552d_0_r((offset*4)+3) << 0;
+ }
+
+ return r;
+}
+
+static WRITE32_HANDLER( comm_uart_w )
+{
+ if (!(mem_mask & 0xff000000))
+ {
+ pc16552d_0_w((offset*4)+0, (data >> 24) & 0xff);
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ pc16552d_0_w((offset*4)+1, (data >> 16) & 0xff);
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ pc16552d_0_w((offset*4)+2, (data >> 8) & 0xff);
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ pc16552d_0_w((offset*4)+3, (data >> 0) & 0xff);
+ }
+}
+
+static void comm_uart_irq_callback(int channel, int value)
+{
+ // TODO
+ //cpunum_set_input_line(0, INPUT_LINE_IRQ2, ASSERT_LINE);
+}
+
+/*****************************************************************************/
+/* Epson RTC-65271 Real-time Clock/NVRAM */
+
+static READ32_HANDLER( rtc_r )
+{
+ int reg = offset * 4;
+ UINT32 r = 0;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= rtc65271_r((reg >> 8) & 0x1, (reg & 0xff) + 0) << 24;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ r |= rtc65271_r((reg >> 8) & 0x1, (reg & 0xff) + 1) << 16;
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ r |= rtc65271_r((reg >> 8) & 0x1, (reg & 0xff) + 2) << 8;
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ r |= rtc65271_r((reg >> 8) & 0x1, (reg & 0xff) + 3) << 0;
+ }
+
+ return r;
+}
+
+static WRITE32_HANDLER( rtc_w )
+{
+ int reg = offset * 4;
+ if (!(mem_mask & 0xff000000))
+ {
+ rtc65271_w((reg >> 8) & 0x1, (reg & 0xff) + 0, (data >> 24) & 0xff);
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ rtc65271_w((reg >> 8) & 0x1, (reg & 0xff) + 1, (data >> 16) & 0xff);
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ rtc65271_w((reg >> 8) & 0x1, (reg & 0xff) + 2, (data >> 8) & 0xff);
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ rtc65271_w((reg >> 8) & 0x1, (reg & 0xff) + 3, (data >> 0) & 0xff);
+ }
+}
+
+/*****************************************************************************/
+
+static READ32_HANDLER( sound_r )
+{
+ UINT32 r = 0;
+
+// printf("sound_r: %08X, %08X\n", offset, mem_mask);
+
+ if (!(mem_mask & 0xff000000)) /* External RAM read */
+ {
+ r |= YMZ280B_data_0_r(offset) << 24;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ r |= YMZ280B_status_0_r(offset) << 16;
+ }
+
+ return r;
+}
+
+static WRITE32_HANDLER( sound_w )
+{
+// printf("sound_w: %08X, %08X, %08X\n", offset, data, mem_mask);
+
+ if (!(mem_mask & 0xff000000))
+ {
+ YMZ280B_register_0_w(offset, (data >> 24) & 0xff);
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ YMZ280B_data_0_w(offset, (data >> 16) & 0xff);
+ }
+}
+
+static int cab_data[2] = { 0x0, 0x8 };
+static int kbm_cab_data[2] = { 0x2, 0x8 };
+static int ppd_cab_data[2] = { 0x1, 0x9 };
+static int cab_data_ptr = 0;
+static int * cur_cab_data = cab_data;
+
+static READ32_HANDLER( cabinet_r )
+{
+ UINT32 r = 0;
+
+// printf("cabinet_r: %08X, %08X\n", offset, mem_mask);
+
+ switch (offset)
+ {
+ case 0:
+ {
+ r = cur_cab_data[cab_data_ptr & 1] << 28;
+ cab_data_ptr++;
+ return r;
+ }
+ case 2: return 0x00000000;
+ case 4: return 0x00000000;
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+static READ32_HANDLER( keyboard_wheel_r )
+{
+ if (offset == 0) // Keyboard Wheel (P1)
+ {
+ return readinputport(3) << 24;
+ }
+ else if (offset == 2) // Keyboard Wheel (P2)
+ {
+ return readinputport(4) << 24;
+ }
+
+ return 0;
+}
+
+static READ32_HANDLER( midi_uart_r )
+{
+ UINT32 r = 0;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= pc16552d_1_r(offset >> 6) << 24;
+ }
+
+ return r;
+}
+
+static WRITE32_HANDLER( midi_uart_w )
+{
+ if (!(mem_mask & 0xff000000))
+ {
+ pc16552d_1_w(offset >> 6, (data >> 24) & 0xff);
+ }
+}
+
+static void midi_uart_irq_callback(int channel, int value)
+{
+ if (channel == 0)
+ {
+ if ((extend_board_irq_enable & 0x02) == 0)
+ {
+ extend_board_irq_active |= 0x02;
+ cpunum_set_input_line(0, INPUT_LINE_IRQ1, ASSERT_LINE);
+ }
+ }
+ else
+ {
+ if ((extend_board_irq_enable & 0x01) == 0)
+ {
+ extend_board_irq_active |= 0x01;
+ cpunum_set_input_line(0, INPUT_LINE_IRQ1, ASSERT_LINE);
+ }
+ }
+}
+
+static int keyboard_state[2] = { 0, 0 };
+
+static const int keyboard_notes[24] =
+{
+ 0x3c, // C1
+ 0x3d, // C1#
+ 0x3e, // D1
+ 0x3f, // D1#
+ 0x40, // E1
+ 0x41, // F1
+ 0x42, // F1#
+ 0x43, // G1
+ 0x44, // G1#
+ 0x45, // A1
+ 0x46, // A1#
+ 0x47, // B1
+ 0x48, // C2
+ 0x49, // C2#
+ 0x4a, // D2
+ 0x4b, // D2#
+ 0x4c, // E2
+ 0x4d, // F2
+ 0x4e, // F2#
+ 0x4f, // G2
+ 0x50, // G2#
+ 0x51, // A2
+ 0x52, // A2#
+ 0x53, // B2
+};
+
+static TIMER_CALLBACK( keyboard_timer_callback )
+{
+ const int kb_uart_channel[2] = { 1, 0 };
+ int keyboard;
+ int i;
+
+ for (keyboard=0; keyboard < 2; keyboard++)
+ {
+ UINT32 kbstate = readinputport(5 + keyboard);
+ int uart_channel = kb_uart_channel[keyboard];
+
+ if (kbstate != keyboard_state[keyboard])
+ {
+ for (i=0; i < 24; i++)
+ {
+ int kbnote = keyboard_notes[i];
+
+ if ((keyboard_state[keyboard] & (1 << i)) != 0 && (kbstate & (1 << i)) == 0)
+ {
+ // key was on, now off -> send Note Off message
+ pc16552d_rx_data(1, uart_channel, 0x80);
+ pc16552d_rx_data(1, uart_channel, kbnote);
+ pc16552d_rx_data(1, uart_channel, 0x7f);
+ }
+ else if ((keyboard_state[keyboard] & (1 << i)) == 0 && (kbstate & (1 << i)) != 0)
+ {
+ // key was off, now on -> send Note On message
+ pc16552d_rx_data(1, uart_channel, 0x90);
+ pc16552d_rx_data(1, uart_channel, kbnote);
+ pc16552d_rx_data(1, uart_channel, 0x7f);
+ }
+ }
+ }
+ else
+ {
+ // no messages, send Active Sense message instead
+ pc16552d_rx_data(1, uart_channel, 0xfe);
+ }
+
+ keyboard_state[keyboard] = kbstate;
+ }
+}
+
+// Extend board IRQs
+// 0x01: MIDI UART channel 2
+// 0x02: MIDI UART channel 1
+// 0x04: ?
+// 0x08: ?
+// 0x10: ?
+// 0x20: ?
+
+static READ32_HANDLER( extend_board_irq_r)
+{
+ UINT32 r = 0;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= (~extend_board_irq_active) << 24;
+ }
+
+ return r;
+}
+
+static WRITE32_HANDLER( extend_board_irq_w )
+{
+// printf("extend_board_irq_w: %08X, %08X, %08X\n", data, offset, mem_mask);
+
+ if (!(mem_mask & 0xff000000))
+ {
+ extend_board_irq_active &= ~((data >> 24) & 0xff);
+
+ extend_board_irq_enable = (data >> 24) & 0xff;
+ }
+}
+
+/*****************************************************************************/
+
+static WRITE32_HANDLER( lamp_output_w )
+{
+ // -------- -------- -------- xxxxxxxx Status LEDs (active low)
+ if (!(mem_mask & 0x000000ff))
+ {
+ output_set_value("status_led_0", (data & 0x01) ? 0 : 1);
+ output_set_value("status_led_1", (data & 0x02) ? 0 : 1);
+ output_set_value("status_led_2", (data & 0x04) ? 0 : 1);
+ output_set_value("status_led_3", (data & 0x08) ? 0 : 1);
+ output_set_value("status_led_4", (data & 0x10) ? 0 : 1);
+ output_set_value("status_led_5", (data & 0x20) ? 0 : 1);
+ output_set_value("status_led_6", (data & 0x40) ? 0 : 1);
+ output_set_value("status_led_7", (data & 0x80) ? 0 : 1);
+ }
+
+// printf("lamp_output_w: %08X, %08X, %08X\n", data, offset, mem_mask);
+}
+
+static WRITE32_HANDLER( lamp_output_kbm_w )
+{
+ lamp_output_w(offset, data, mem_mask);
+
+ if (!(mem_mask & 0xff000000))
+ {
+ output_set_value("door_lamp", (data & 0x10000000) ? 1 : 0);
+ output_set_value("start1p", (data & 0x01000000) ? 1 : 0);
+ output_set_value("start2p", (data & 0x02000000) ? 1 : 0);
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ output_set_value("lamp1", (data & 0x00000100) ? 1 : 0);
+ output_set_value("lamp2", (data & 0x00000200) ? 1 : 0);
+ output_set_value("lamp3", (data & 0x00000400) ? 1 : 0);
+ output_set_value("neon", (data & 0x00000800) ? 1 : 0);
+ }
+}
+
+static WRITE32_HANDLER( lamp_output_ppp_w )
+{
+ lamp_output_w(offset, data, mem_mask);
+
+ // ParaParaParadise lamps (active high)
+ // 0x00000100 Left
+ // 0x00000200 Right
+ // 0x00000400 Door Lamp
+ // 0x00000800 OK
+ // 0x00008000 Slim
+ // 0x01000000 Stage LED 0
+ // 0x02000000 Stage LED 1
+ // 0x04000000 Stage LED 2
+ // 0x08000000 Stage LED 3
+ // 0x00010000 Stage LED 4
+ // 0x00020000 Stage LED 5
+ // 0x00040000 Stage LED 6
+ // 0x00080000 Stage LED 7
+ if (!(mem_mask & 0x0000ff00))
+ {
+ output_set_value("left", (data & 0x00000100) ? 1 : 0);
+ output_set_value("right", (data & 0x00000200) ? 1 : 0);
+ output_set_value("door_lamp", (data & 0x00000400) ? 1 : 0);
+ output_set_value("ok", (data & 0x00000800) ? 1 : 0);
+ output_set_value("slim", (data & 0x00008000) ? 1 : 0);
+ }
+ if (!(mem_mask & 0xff000000))
+ {
+ output_set_value("stage_led_0", (data & 0x01000000) ? 1 : 0);
+ output_set_value("stage_led_1", (data & 0x02000000) ? 1 : 0);
+ output_set_value("stage_led_2", (data & 0x04000000) ? 1 : 0);
+ output_set_value("stage_led_3", (data & 0x08000000) ? 1 : 0);
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ output_set_value("stage_led_4", (data & 0x00010000) ? 1 : 0);
+ output_set_value("stage_led_5", (data & 0x00020000) ? 1 : 0);
+ output_set_value("stage_led_6", (data & 0x00040000) ? 1 : 0);
+ output_set_value("stage_led_7", (data & 0x00080000) ? 1 : 0);
+ }
+}
+
+static WRITE32_HANDLER( lamp_output2_w )
+{
+// printf("lamp_output2_w: %08X, %08X, %08X\n", data, offset, mem_mask);
+}
+
+static WRITE32_HANDLER( lamp_output2_ppp_w )
+{
+ lamp_output2_w(offset, data, mem_mask);
+
+ // ParaParaParadise lamps (active high)
+ // 0x00010000 Top LED 0
+ // 0x00020000 Top LED 1
+ // 0x00040000 Top LED 2
+ // 0x00080000 Top LED 3
+ // 0x00000001 Top LED 4
+ // 0x00000002 Top LED 5
+ // 0x00000004 Top LED 6
+ // 0x00000008 Top LED 7
+ if (!(mem_mask & 0x00ff0000))
+ {
+ output_set_value("top_led_0", (data & 0x00010000) ? 1 : 0);
+ output_set_value("top_led_1", (data & 0x00020000) ? 1 : 0);
+ output_set_value("top_led_2", (data & 0x00040000) ? 1 : 0);
+ output_set_value("top_led_3", (data & 0x00080000) ? 1 : 0);
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ output_set_value("top_led_4", (data & 0x00000001) ? 1 : 0);
+ output_set_value("top_led_5", (data & 0x00000002) ? 1 : 0);
+ output_set_value("top_led_6", (data & 0x00000004) ? 1 : 0);
+ output_set_value("top_led_7", (data & 0x00000008) ? 1 : 0);
+ }
+}
+
+static WRITE32_HANDLER( lamp_output3_w )
+{
+// printf("lamp_output3_w: %08X, %08X, %08X\n", data, offset, mem_mask);
+}
+
+static WRITE32_HANDLER( lamp_output3_ppp_w )
+{
+ lamp_output3_w(offset, data, mem_mask);
+
+ // ParaParaParadise lamps (active high)
+ // 0x00010000 Lamp 0
+ // 0x00040000 Lamp 1
+ // 0x00100000 Lamp 2
+ // 0x00400000 Lamp 3
+ if (!(mem_mask & 0x00ff0000))
+ {
+ output_set_value("lamp_0", (data & 0x00010000) ? 1 : 0);
+ output_set_value("lamp_1", (data & 0x00040000) ? 1 : 0);
+ output_set_value("lamp_2", (data & 0x00100000) ? 1 : 0);
+ output_set_value("lamp_3", (data & 0x00400000) ? 1 : 0);
+ }
+}
+
+/*****************************************************************************/
+
+static UINT8 spu_shared_ram[0x400];
+
+static READ32_HANDLER(ppc_spu_share_r)
+{
+ UINT32 r = 0;
+
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= spu_shared_ram[(offset * 4) + 0] << 24;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ r |= spu_shared_ram[(offset * 4) + 1] << 16;
+ }
+ if (!(mem_mask & 0x0000ff0000))
+ {
+ r |= spu_shared_ram[(offset * 4) + 2] << 8;
+ }
+ if (!(mem_mask & 0xff000000))
+ {
+ r |= spu_shared_ram[(offset * 4) + 3] << 0;
+ }
+
+ return r;
+}
+
+static WRITE32_HANDLER(ppc_spu_share_w)
+{
+ if (!(mem_mask & 0xff000000))
+ {
+ spu_shared_ram[(offset * 4) + 0] = (data >> 24) & 0xff;
+ }
+ if (!(mem_mask & 0x00ff0000))
+ {
+ spu_shared_ram[(offset * 4) + 1] = (data >> 16) & 0xff;
+ }
+ if (!(mem_mask & 0x0000ff00))
+ {
+ spu_shared_ram[(offset * 4) + 2] = (data >> 8) & 0xff;
+ }
+ if (!(mem_mask & 0x000000ff))
+ {
+ spu_shared_ram[(offset * 4) + 3] = (data >> 0) & 0xff;
+ }
+}
+
+#ifdef UNUSED_FUNCTION
+static READ16_HANDLER(m68k_spu_share_r)
+{
+ return spu_shared_ram[offset] << 8;
+}
+
+static WRITE16_HANDLER(m68k_spu_share_w)
+{
+ spu_shared_ram[offset] = (data >> 8) & 0xff;
+}
+#endif
+
+static READ16_HANDLER(spu_unk_r)
+{
+ return 0xffff;
+}
+
+/*****************************************************************************/
+
+static ADDRESS_MAP_START( firebeat_map, ADDRESS_SPACE_PROGRAM, 32 )
+ AM_RANGE(0x70000000, 0x70000fff) AM_READWRITE(midi_uart_r, midi_uart_w)
+ AM_RANGE(0x70006000, 0x70006003) AM_WRITE(extend_board_irq_w)
+ AM_RANGE(0x70008000, 0x7000800f) AM_READ(keyboard_wheel_r)
+ AM_RANGE(0x7000a000, 0x7000a003) AM_READ(extend_board_irq_r)
+ AM_RANGE(0x74000000, 0x740003ff) AM_READWRITE(ppc_spu_share_r, ppc_spu_share_w) // SPU shared RAM
+ AM_RANGE(0x7d000200, 0x7d00021f) AM_READ(cabinet_r)
+ AM_RANGE(0x7d000340, 0x7d000347) AM_READ(sensor_r)
+ AM_RANGE(0x7d000400, 0x7d000403) AM_READWRITE(sound_r, sound_w)
+ AM_RANGE(0x7d000800, 0x7d000803) AM_READ(input_r)
+ AM_RANGE(0x7d400000, 0x7d5fffff) AM_READWRITE(flashram_r, flashram_w)
+ AM_RANGE(0x7d800000, 0x7dbfffff) AM_READWRITE(soundflash_r, soundflash_w)
+ AM_RANGE(0x7dc00000, 0x7dc0000f) AM_READWRITE(comm_uart_r, comm_uart_w)
+ AM_RANGE(0x7e000000, 0x7e00013f) AM_READWRITE(rtc_r, rtc_w)
+ AM_RANGE(0x7e800000, 0x7e8000ff) AM_READWRITE(gcu0_r, gcu0_w)
+ AM_RANGE(0x7e800100, 0x7e8001ff) AM_READWRITE(gcu1_r, gcu1_w)
+ AM_RANGE(0x7fe00000, 0x7fe0000f) AM_READWRITE(atapi_command_r, atapi_command_w)
+ AM_RANGE(0x7fe80000, 0x7fe8000f) AM_READWRITE(atapi_control_r, atapi_control_w)
+ AM_RANGE(0x80000000, 0x81ffffff) AM_RAM
+ AM_RANGE(0xfff80000, 0xffffffff) AM_ROM AM_REGION(REGION_USER1, 0) /* System BIOS */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( spu_map, ADDRESS_SPACE_PROGRAM, 16 )
+ AM_RANGE(0x000000, 0x07ffff) AM_ROM
+ AM_RANGE(0x100000, 0x13ffff) AM_RAM
+ AM_RANGE(0x340000, 0x34000f) AM_READ(spu_unk_r)
+ADDRESS_MAP_END
+
+/*****************************************************************************/
+
+static READ8_HANDLER( soundram_r )
+{
+ if (offset >= 0 && offset < 0x200000)
+ {
+ return intelflash_read(1, offset & 0x1fffff);
+ }
+ else if (offset >= 0x200000 && offset < 0x400000)
+ {
+ return intelflash_read(2, offset & 0x1fffff);
+ }
+ return 0;
+}
+
+static WRITE8_HANDLER( soundram_w )
+{
+}
+
+static void sound_irq_callback(int state)
+{
+}
+
+static struct YMZ280Binterface ymz280b_intf =
+{
+ REGION_SOUND1,
+ sound_irq_callback, // irq
+ soundram_r,
+ soundram_w,
+};
+
+static NVRAM_HANDLER(firebeat)
+{
+ nvram_handler_intelflash(machine, 0, file, read_or_write);
+ nvram_handler_intelflash(machine, 1, file, read_or_write);
+ nvram_handler_intelflash(machine, 2, file, read_or_write);
+
+ if (read_or_write)
+ {
+ rtc65271_file_save(file);
+ }
+ else
+ {
+ rtc65271_init(xram, NULL);
+
+ if (file != NULL)
+ {
+ rtc65271_file_load(file);
+ }
+ }
+}
+
+static INPUT_PORTS_START(ppp)
+ PORT_START_TAG("IN0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) // Left
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) // Right
+ PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW) // Test
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Service") PORT_CODE(KEYCODE_7) // Service
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) // Coin
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_START1 ) // Start / Ok
+ PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED )
+
+ PORT_START_TAG("IN1")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START_TAG("IN2")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* Dip switches */
+
+ // ParaParaParadise has 24 sensors, grouped into groups of 3 for each sensor bar
+ // Sensors 15...23 are only used by the Korean version of PPP, which has 8 sensor bars
+
+ PORT_START_TAG("SENSOR1")
+ PORT_BIT( 0x00070000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) // Sensor 0, 1, 2 (Sensor bar 1)
+ PORT_BIT( 0x00380000, IP_ACTIVE_HIGH, IPT_BUTTON4 ) // Sensor 3, 4, 5 (Sensor bar 2)
+ PORT_BIT( 0x00c00001, IP_ACTIVE_HIGH, IPT_BUTTON5 ) // Sensor 6, 7, 8 (Sensor bar 3)
+ PORT_BIT( 0x0000000e, IP_ACTIVE_HIGH, IPT_BUTTON6 ) // Sensor 9, 10,11 (Sensor bar 4)
+
+ PORT_START_TAG("SENSOR2")
+ PORT_BIT( 0x00070000, IP_ACTIVE_HIGH, IPT_BUTTON7 ) // Sensor 12,13,14 (Sensor bar 5)
+ PORT_BIT( 0x00380000, IP_ACTIVE_HIGH, IPT_BUTTON8 ) // Sensor 15,16,17 (Sensor bar 6) (unused by PPP)
+ PORT_BIT( 0x00c00001, IP_ACTIVE_HIGH, IPT_BUTTON9 ) // Sensor 18,19,20 (Sensor bar 7) (unused by PPP)
+ PORT_BIT( 0x0000000e, IP_ACTIVE_HIGH, IPT_BUTTON10 ) // Sensor 21,22,23 (Sensor bar 8) (unused by PPP)
+
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(kbm)
+ PORT_START_TAG("IN0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) // Start P1
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 ) // Start P2
+ PORT_SERVICE_NO_TOGGLE( 0x04, IP_ACTIVE_LOW) // Test
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Service") PORT_CODE(KEYCODE_7) // Service
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 ) // Coin
+ PORT_BIT( 0xe0, IP_ACTIVE_LOW, IPT_UNUSED )
+
+ PORT_START_TAG("IN1")
+ PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // e-Amusement
+ PORT_BIT( 0xfe, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START_TAG("IN2")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* Dip switches */
+
+ PORT_START_TAG("WHEEL_P1") // Keyboard modulation wheel (P1)
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE_V ) PORT_MINMAX(0xff, 0x00) PORT_SENSITIVITY(30) PORT_KEYDELTA(10)
+
+ PORT_START_TAG("WHEEL_P2") // Keyboard modulation wheel (P2)
+ PORT_BIT( 0xff, 0x80, IPT_PADDLE_V ) PORT_MINMAX(0xff, 0x00) PORT_SENSITIVITY(30) PORT_KEYDELTA(10)
+
+ PORT_START_TAG("KEYBOARD_P1")
+ PORT_BIT( 0x000001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 C1") PORT_CODE(KEYCODE_Q)
+ PORT_BIT( 0x000002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 C1#") PORT_CODE(KEYCODE_W)
+ PORT_BIT( 0x000004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 D1") PORT_CODE(KEYCODE_E)
+ PORT_BIT( 0x000008, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 D1#") PORT_CODE(KEYCODE_R)
+ PORT_BIT( 0x000010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 E1") PORT_CODE(KEYCODE_T)
+ PORT_BIT( 0x000020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 F1") PORT_CODE(KEYCODE_Y)
+ PORT_BIT( 0x000040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 F1#") PORT_CODE(KEYCODE_U)
+ PORT_BIT( 0x000080, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 G1") PORT_CODE(KEYCODE_I)
+ PORT_BIT( 0x000100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 G1#") PORT_CODE(KEYCODE_O)
+ PORT_BIT( 0x000200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 A1") PORT_CODE(KEYCODE_A)
+ PORT_BIT( 0x000400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 A1#") PORT_CODE(KEYCODE_S)
+ PORT_BIT( 0x000800, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 B1") PORT_CODE(KEYCODE_D)
+ PORT_BIT( 0x001000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 C2") PORT_CODE(KEYCODE_F)
+ PORT_BIT( 0x002000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 C2#") PORT_CODE(KEYCODE_G)
+ PORT_BIT( 0x004000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 D2") PORT_CODE(KEYCODE_H)
+ PORT_BIT( 0x008000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 D2#") PORT_CODE(KEYCODE_J)
+ PORT_BIT( 0x010000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 E2") PORT_CODE(KEYCODE_K)
+ PORT_BIT( 0x020000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 F2") PORT_CODE(KEYCODE_L)
+ PORT_BIT( 0x040000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 F2#") PORT_CODE(KEYCODE_Z)
+ PORT_BIT( 0x080000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 G2") PORT_CODE(KEYCODE_X)
+ PORT_BIT( 0x100000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 G2#") PORT_CODE(KEYCODE_C)
+ PORT_BIT( 0x200000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 A2") PORT_CODE(KEYCODE_V)
+ PORT_BIT( 0x400000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 A2#") PORT_CODE(KEYCODE_B)
+ PORT_BIT( 0x800000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 B2") PORT_CODE(KEYCODE_N)
+
+ PORT_START_TAG("KEYBOARD_P2")
+ PORT_BIT( 0x000001, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 C1") PORT_CODE(KEYCODE_Q)
+ PORT_BIT( 0x000002, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 C1#") PORT_CODE(KEYCODE_W)
+ PORT_BIT( 0x000004, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 D1") PORT_CODE(KEYCODE_E)
+ PORT_BIT( 0x000008, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 D1#") PORT_CODE(KEYCODE_R)
+ PORT_BIT( 0x000010, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 E1") PORT_CODE(KEYCODE_T)
+ PORT_BIT( 0x000020, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 F1") PORT_CODE(KEYCODE_Y)
+ PORT_BIT( 0x000040, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 F1#") PORT_CODE(KEYCODE_U)
+ PORT_BIT( 0x000080, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 G1") PORT_CODE(KEYCODE_I)
+ PORT_BIT( 0x000100, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 G1#") PORT_CODE(KEYCODE_O)
+ PORT_BIT( 0x000200, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 A1") PORT_CODE(KEYCODE_A)
+ PORT_BIT( 0x000400, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 A1#") PORT_CODE(KEYCODE_S)
+ PORT_BIT( 0x000800, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 B1") PORT_CODE(KEYCODE_D)
+ PORT_BIT( 0x001000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 C2") PORT_CODE(KEYCODE_F)
+ PORT_BIT( 0x002000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 C2#") PORT_CODE(KEYCODE_G)
+ PORT_BIT( 0x004000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 D2") PORT_CODE(KEYCODE_H)
+ PORT_BIT( 0x008000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 D2#") PORT_CODE(KEYCODE_J)
+ PORT_BIT( 0x010000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 E2") PORT_CODE(KEYCODE_K)
+ PORT_BIT( 0x020000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 F2") PORT_CODE(KEYCODE_L)
+ PORT_BIT( 0x040000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 F2#") PORT_CODE(KEYCODE_Z)
+ PORT_BIT( 0x080000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 G2") PORT_CODE(KEYCODE_X)
+ PORT_BIT( 0x100000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 G2#") PORT_CODE(KEYCODE_C)
+ PORT_BIT( 0x200000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 A2") PORT_CODE(KEYCODE_V)
+ PORT_BIT( 0x400000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 A2#") PORT_CODE(KEYCODE_B)
+ PORT_BIT( 0x800000, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 B2") PORT_CODE(KEYCODE_N)
+
+INPUT_PORTS_END
+
+static INPUT_PORTS_START(popn)
+ PORT_START_TAG("IN0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) // Switch 1
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) // Switch 2
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) // Switch 3
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) // Switch 4
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) // Switch 5
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) // Switch 6
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON7 ) // Switch 7
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON8 ) // Switch 8
+
+ PORT_START_TAG("IN1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON9 ) // Switch 9
+ PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 ) // Coin
+ PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_SERVICE_NO_TOGGLE( 0x10, IP_ACTIVE_LOW) // Test
+ PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Service") PORT_CODE(KEYCODE_7) // Service
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
+
+ PORT_START_TAG("IN2")
+ PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* Dip switches */
+
+INPUT_PORTS_END
+
+static INTERRUPT_GEN(firebeat_interrupt)
+{
+ // IRQs
+ // IRQ 0: VBlank
+ // IRQ 1: Extend board IRQ
+ // IRQ 2: Main board UART
+ // IRQ 4: ATAPI
+
+ cpunum_set_input_line(0, INPUT_LINE_IRQ0, ASSERT_LINE);
+}
+
+static MACHINE_RESET( firebeat )
+{
+ void *cd;
+ int i;
+ UINT8 *sound = memory_region(REGION_SOUND1);
+
+ for (i=0; i < 0x200000; i++)
+ {
+ sound[i] = intelflash_read(1, i);
+ sound[i+0x200000] = intelflash_read(2, i);
+ }
+
+ SCSIGetDevice( atapi_device_data[1], &cd );
+ cdda_set_cdrom(0, cd);
+}
+
+static ppc_config firebeat_ppc_cfg =
+{
+ PPC_MODEL_403GCX
+};
+
+static MACHINE_DRIVER_START(firebeat)
+
+ /* basic machine hardware */
+ MDRV_CPU_ADD(PPC403, 66000000)
+ MDRV_CPU_CONFIG(firebeat_ppc_cfg)
+ MDRV_CPU_PROGRAM_MAP(firebeat_map, 0)
+ MDRV_CPU_VBLANK_INT(firebeat_interrupt,1)
+
+ MDRV_SCREEN_REFRESH_RATE(60)
+ MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION)
+
+ MDRV_MACHINE_RESET(firebeat)
+ MDRV_NVRAM_HANDLER(firebeat)
+
+ /* video hardware */
+ MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER )
+ MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB15)
+ MDRV_PALETTE_LENGTH(32768)
+
+ MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION)
+ MDRV_SCREEN_SIZE(640, 480)
+ MDRV_SCREEN_VISIBLE_AREA(0, 639, 0, 479)
+
+ MDRV_VIDEO_START(firebeat)
+ MDRV_VIDEO_UPDATE(firebeat)
+
+ /* sound hardware */
+ MDRV_SPEAKER_STANDARD_STEREO("left", "right")
+
+ MDRV_SOUND_ADD(YMZ280B, 16934400)
+ MDRV_SOUND_CONFIG(ymz280b_intf)
+ MDRV_SOUND_ROUTE(0, "left", 1.0)
+ MDRV_SOUND_ROUTE(1, "right", 1.0)
+
+ MDRV_SOUND_ADD(CDDA, 0)
+ MDRV_SOUND_ROUTE(0, "left", 1.0)
+ MDRV_SOUND_ROUTE(1, "right", 1.0)
+
+MACHINE_DRIVER_END
+
+static MACHINE_DRIVER_START(firebeat2)
+
+ /* basic machine hardware */
+ MDRV_CPU_ADD(PPC403, 66000000)
+ MDRV_CPU_CONFIG(firebeat_ppc_cfg)
+ MDRV_CPU_PROGRAM_MAP(firebeat_map, 0)
+ MDRV_CPU_VBLANK_INT(firebeat_interrupt,1)
+
+ MDRV_MACHINE_RESET(firebeat)
+ MDRV_NVRAM_HANDLER(firebeat)
+
+ /* video hardware */
+ MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER )
+ MDRV_PALETTE_LENGTH(32768)
+
+ MDRV_SCREEN_ADD("left", 0x000)
+ MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB15)
+ MDRV_SCREEN_REFRESH_RATE(60)
+ MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION)
+ MDRV_SCREEN_SIZE(640, 480)
+ MDRV_SCREEN_VISIBLE_AREA(0, 639, 0, 479)
+
+ MDRV_SCREEN_ADD("right", 0x000)
+ MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB15)
+ MDRV_SCREEN_REFRESH_RATE(60)
+ MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION)
+ MDRV_SCREEN_SIZE(640, 480)
+ MDRV_SCREEN_VISIBLE_AREA(0, 639, 0, 479)
+
+ MDRV_VIDEO_START(firebeat)
+ MDRV_VIDEO_UPDATE(firebeat)
+
+ /* sound hardware */
+ MDRV_SPEAKER_STANDARD_STEREO("left", "right")
+
+ MDRV_SOUND_ADD(YMZ280B, 16934400)
+ MDRV_SOUND_CONFIG(ymz280b_intf)
+ MDRV_SOUND_ROUTE(0, "left", 1.0)
+ MDRV_SOUND_ROUTE(1, "right", 1.0)
+
+ MDRV_SOUND_ADD(CDDA, 0)
+ MDRV_SOUND_ROUTE(0, "left", 1.0)
+ MDRV_SOUND_ROUTE(1, "right", 1.0)
+MACHINE_DRIVER_END
+
+static MACHINE_DRIVER_START(firebeat_spu)
+
+ MDRV_IMPORT_FROM(firebeat)
+
+ MDRV_CPU_ADD(M68000, 16000000)
+ MDRV_CPU_PROGRAM_MAP(spu_map, 0)
+
+MACHINE_DRIVER_END
+
+/*****************************************************************************/
+/* Security dongle is a Dallas DS1411 RS232 Adapter with a DS1991 Multikey iButton */
+
+typedef struct
+{
+ UINT8 identifier[8];
+ UINT8 password[8];
+ UINT8 data[0x30];
+} IBUTTON_SUBKEY;
+
+typedef struct
+{
+ IBUTTON_SUBKEY subkey[3];
+} IBUTTON;
+
+enum
+{
+ DS1991_STATE_NORMAL,
+ DS1991_STATE_READ_SUBKEY,
+};
+
+static IBUTTON ibutton;
+
+static int ibutton_state = DS1991_STATE_NORMAL;
+static int ibutton_read_subkey_ptr = 0;
+
+static UINT8 ibutton_subkey_data[0x40];
+
+static void set_ibutton(UINT8 *data)
+{
+ int i, j;
+
+ for (i=0; i < 3; i++)
+ {
+ // identifier
+ for (j=0; j < 8; j++)
+ {
+ ibutton.subkey[i].identifier[j] = *data++;
+ }
+
+ // password
+ for (j=0; j < 8; j++)
+ {
+ ibutton.subkey[i].password[j] = *data++;
+ }
+
+ // data
+ for (j=0; j < 48; j++)
+ {
+ ibutton.subkey[i].data[j] = *data++;
+ }
+ }
+}
+
+static int ibutton_w(UINT8 data)
+{
+ int r = -1;
+
+ switch (ibutton_state)
+ {
+ case DS1991_STATE_NORMAL:
+ {
+ switch (data)
+ {
+ //
+ // DS2408B Serial 1-Wire Line Driver with Load Sensor
+ //
+ case 0xc1: // DS2480B reset
+ {
+ r = 0xcd;
+ break;
+ }
+ case 0xe1: // DS2480B set data mode
+ {
+ break;
+ }
+ case 0xe3: // DS2480B set command mode
+ {
+ break;
+ }
+
+ //
+ // DS1991 MultiKey iButton
+ //
+ case 0x66: // DS1991 Read SubKey
+ {
+ r = 0x66;
+ ibutton_state = DS1991_STATE_READ_SUBKEY;
+ ibutton_read_subkey_ptr = 0;
+ break;
+ }
+ case 0xcc: // DS1991 skip rom
+ {
+ r = 0xcc;
+ ibutton_state = DS1991_STATE_NORMAL;
+ break;
+ }
+ default:
+ {
+ fatalerror("ibutton: unknown normal mode cmd %02X\n", data);
+ break;
+ }
+ }
+ break;
+ }
+
+ case DS1991_STATE_READ_SUBKEY:
+ {
+ if (ibutton_read_subkey_ptr == 0) // Read SubKey, 2nd command byte
+ {
+ int subkey = (data >> 6) & 0x3;
+ // printf("iButton SubKey %d\n", subkey);
+ r = data;
+
+ if (subkey < 3)
+ {
+ memcpy(&ibutton_subkey_data[0], ibutton.subkey[subkey].identifier, 8);
+ memcpy(&ibutton_subkey_data[8], ibutton.subkey[subkey].password, 8);
+ memcpy(&ibutton_subkey_data[16], ibutton.subkey[subkey].data, 0x30);
+ }
+ else
+ {
+ memset(&ibutton_subkey_data[0], 0, 0x40);
+ }
+ }
+ else if (ibutton_read_subkey_ptr == 1) // Read SubKey, 3rd command byte
+ {
+ r = data;
+ }
+ else
+ {
+ r = ibutton_subkey_data[ibutton_read_subkey_ptr-2];
+ }
+ ibutton_read_subkey_ptr++;
+ if (ibutton_read_subkey_ptr >= 0x42)
+ {
+ ibutton_state = DS1991_STATE_NORMAL;
+ }
+ break;
+ }
+ }
+
+ return r;
+}
+
+static void security_w(UINT8 data)
+{
+ int r = ibutton_w(data);
+ if (r >= 0)
+ {
+ ppc403_spu_rx(r & 0xff);
+ }
+}
+
+/*****************************************************************************/
+
+static void init_lights(write32_handler out1, write32_handler out2, write32_handler out3)
+{
+ if(!out1) out1 = lamp_output_w;
+ if(!out2) out1 = lamp_output2_w;
+ if(!out3) out1 = lamp_output3_w;
+
+ memory_install_write32_handler(0, ADDRESS_SPACE_PROGRAM, 0x7d000804, 0x7d000807, 0, 0, out1);
+ memory_install_write32_handler(0, ADDRESS_SPACE_PROGRAM, 0x7d000320, 0x7d000323, 0, 0, out2);
+ memory_install_write32_handler(0, ADDRESS_SPACE_PROGRAM, 0x7d000324, 0x7d000327, 0, 0, out3);
+}
+
+static void init_firebeat(running_machine *machine)
+{
+ UINT8 *rom = memory_region(REGION_USER2);
+
+ atapi_init();
+ intelflash_init(0, FLASH_FUJITSU_29F016A, NULL);
+ intelflash_init(1, FLASH_FUJITSU_29F016A, NULL);
+ intelflash_init(2, FLASH_FUJITSU_29F016A, NULL);
+
+ rtc65271_init(xram, NULL);
+
+ pc16552d_init(0, 19660800, comm_uart_irq_callback); // Network UART
+ pc16552d_init(1, 24000000, midi_uart_irq_callback); // MIDI UART
+
+ extend_board_irq_enable = 0x3f;
+ extend_board_irq_active = 0x00;
+
+ cur_cab_data = cab_data;
+
+ ppc403_install_spu_tx_handler(security_w);
+
+ set_ibutton(rom);
+
+ init_lights(NULL, NULL, NULL);
+}
+
+static DRIVER_INIT(ppp)
+{
+ init_firebeat(machine);
+ init_lights(lamp_output_ppp_w, lamp_output2_ppp_w, lamp_output3_ppp_w);
+}
+
+static DRIVER_INIT(ppd)
+{
+ init_firebeat(machine);
+ init_lights(lamp_output_ppp_w, lamp_output2_ppp_w, lamp_output3_ppp_w);
+
+ cur_cab_data = ppd_cab_data;
+}
+
+static void init_keyboard(void)
+{
+ // set keyboard timer
+ keyboard_timer = timer_alloc(keyboard_timer_callback);
+ timer_adjust(keyboard_timer, ATTOTIME_IN_MSEC(10), 0, ATTOTIME_IN_MSEC(10));
+}
+
+static DRIVER_INIT(kbm)
+{
+ init_firebeat(machine);
+ init_lights(lamp_output_kbm_w, NULL, NULL);
+
+ init_keyboard();
+
+ cur_cab_data = kbm_cab_data;
+}
+
+
+/*****************************************************************************/
+
+ROM_START( ppp )
+ ROM_REGION32_BE(0x80000, REGION_USER1, 0)
+ ROM_LOAD16_WORD_SWAP("977jaa03.e21", 0x00000, 0x80000, CRC(7b83362a) SHA1(2857a93be58636c10a8d180dbccf2caeeaaff0e2))
+
+ ROM_REGION(0x400000, REGION_SOUND1, ROMREGION_ERASE00)
+
+ ROM_REGION(0xc0, REGION_USER2, 0) // Security dongle
+ ROM_LOAD("gq977-ja", 0x00, 0xc0, BAD_DUMP CRC(55b5abdb) SHA1(d8da5bac005235480a1815bd0a79c3e8a63ebad1))
+
+ DISK_REGION( REGION_DISKS )
+ DISK_IMAGE_READONLY( "977jaa01", 0, MD5(9abc766b72dab28db920f3d264fc2254) SHA1(05bce40c3b241cd1f634d6688ec179a86f57da9f) )
+
+ // TODO: the audio CD is not dumped
+ROM_END
+
+ROM_START( kbm )
+ ROM_REGION32_BE(0x80000, REGION_USER1, 0)
+ ROM_LOAD16_WORD_SWAP("974a03.e21", 0x00000, 0x80000, CRC(ef9a932d) SHA1(6299d3b9823605e519dbf1f105b59a09197df72f))
+
+ ROM_REGION(0x400000, REGION_SOUND1, ROMREGION_ERASE00)
+
+ ROM_REGION(0xc0, REGION_USER2, ROMREGION_ERASE00) // Security dongle
+ ROM_LOAD("gq974-ja", 0x00, 0xc0, BAD_DUMP CRC(4578f29b) SHA1(faaeaf6357c1e86e898e7017566cfd2fc7ee3d6f))
+
+ DISK_REGION( REGION_DISKS )
+ DISK_IMAGE_READONLY( "974jac01", 0, SHA1(18179bf23519d5b0c82c72e8f47dfaa4d2c4a3e2) MD5(cb68cf69e55aa33429f149f474e2c96e) )
+ DISK_IMAGE_READONLY( "974jaa02", 1, SHA1(8d78a91d98967a232c4b98628e2db25df0a7f8bd) MD5(5cb0100791294559fedccc2a9a46fd86) )
+ROM_END
+
+ROM_START( kbm2nd )
+ ROM_REGION32_BE(0x80000, REGION_USER1, 0)
+ ROM_LOAD16_WORD_SWAP("974a03.e21", 0x00000, 0x80000, CRC(ef9a932d) SHA1(6299d3b9823605e519dbf1f105b59a09197df72f))
+
+ ROM_REGION(0x400000, REGION_SOUND1, ROMREGION_ERASE00)
+
+ ROM_REGION(0xc0, REGION_USER2, ROMREGION_ERASE00) // Security dongle
+ ROM_LOAD("gca01-ja", 0x00, 0xc0, BAD_DUMP CRC(2bda339d) SHA1(031cb3f44e7a89cd62a9ba948f3d19d53a325abd))
+
+ DISK_REGION( REGION_DISKS )
+ DISK_IMAGE_READONLY( "a01jaa01", 0, SHA1(87c21dc6b9fe8d9f696985cfd9dc14a23f0932fe) MD5(0eff2ca8ebef1fd8815d1d7cb0c2383a) )
+ DISK_IMAGE_READONLY( "a01jaa02", 1, SHA1(fabfcc02f97c867c361df7b9539e6b77f369b73f) MD5(25679474e987d0dd83a0db2bad24bc14) )
+ROM_END
+
+ROM_START( kbm3rd )
+ ROM_REGION32_BE(0x80000, REGION_USER1, 0)
+ ROM_LOAD16_WORD_SWAP("974a03.e21", 0x00000, 0x80000, CRC(ef9a932d) SHA1(6299d3b9823605e519dbf1f105b59a09197df72f))
+
+ ROM_REGION(0x400000, REGION_SOUND1, ROMREGION_ERASE00)
+
+ ROM_REGION(0xc0, REGION_USER2, 0) // Security dongle
+ ROM_LOAD("gca12-ja", 0x00, 0xc0, BAD_DUMP CRC(cf01dc15) SHA1(da8d208233487ebe65a0a9826fc72f1f459baa26))
+
+ DISK_REGION( REGION_DISKS )
+ DISK_IMAGE_READONLY( "a12jaa01", 0, MD5(130a11bd229d9c30bd6d9ffeaf94926e) SHA1(6b595b17260b0ca17d04d7911616d5ff88158f26) )
+ DISK_IMAGE_READONLY( "a12jaa02", 1, MD5(10ff654cf3d9b833ecbe72a395e7bb60) SHA1(4adddc8e028111169889bfb99007238da5f4d330) )
+ROM_END
+
+ROM_START( popn7 )
+ ROM_REGION32_BE(0x80000, REGION_USER1, 0)
+ ROM_LOAD16_WORD_SWAP("a02jaa03.e21", 0x00000, 0x80000, CRC(43ecc093) SHA1(637df5b546cf7409dd4752dc471674fe2a046599))
+
+ ROM_REGION(0x400000, REGION_SOUND1, ROMREGION_ERASE00)
+
+ ROM_REGION(0xc0, REGION_USER2, ROMREGION_ERASE00) // Security dongle
+ ROM_LOAD("gcb00-ja", 0x00, 0xc0, BAD_DUMP CRC(cc28625a) SHA1(e7de79ae72fdbd22328c9de74dfa17b5e6ae43b6))
+
+ ROM_REGION(0x80000, REGION_CPU2, 0) // SPU 68K program
+ ROM_LOAD16_WORD_SWAP("a02jaa04.3q", 0x00000, 0x80000, CRC(8c6000dd) SHA1(94ab2a66879839411eac6c673b25143d15836683))
+
+ DISK_REGION( REGION_DISKS )
+ DISK_IMAGE_READONLY( "b00jab01", 0, SHA1(7462586f67b5c3b015ac581ad0afc089fcd6f537) MD5(af9a249b23783d53ff27ea7dc7e6735c) )
+ DISK_IMAGE_READONLY( "b00jaa02", 1, SHA1(fea9439f14304d865830fb34f8781346d95a1df7) MD5(cf4c4f7c2321fcca6d86e8c144261752) )
+ROM_END
+
+ROM_START( ppd )
+ ROM_REGION32_BE(0x80000, REGION_USER1, 0)
+ ROM_LOAD16_WORD_SWAP("977jaa03.e21", 0x00000, 0x80000, CRC(7b83362a) SHA1(2857a93be58636c10a8d180dbccf2caeeaaff0e2))
+
+ ROM_REGION(0x400000, REGION_SOUND1, ROMREGION_ERASE00)
+
+ ROM_REGION(0xc0, REGION_USER2, ROMREGION_ERASE00) // Security dongle
+ ROM_LOAD("gq977-ko", 0x00, 0xc0, BAD_DUMP CRC(ee743323) SHA1(2042e45879795557ad3cc21b37962f6bf54da60d))
+
+ DISK_REGION( REGION_DISKS )
+ DISK_IMAGE_READONLY( "977kaa01", 0, SHA1(7069c1e42bf994ccdfcf6ff0dda9c5de94f1cc65) MD5(f499cb458d823200dc96fe9cef5c08c8) )
+ DISK_IMAGE_READONLY( "977kaa02", 1, SHA1(45d5cda77f789351260bbd6f9c47a5fa93998133) MD5(b58978a81931058fe28825b6147b1bed) )
+ROM_END
+
+ROM_START( ppp11 )
+ ROM_REGION32_BE(0x80000, REGION_USER1, 0)
+ ROM_LOAD16_WORD_SWAP("977jaa03.e21", 0x00000, 0x80000, CRC(7b83362a) SHA1(2857a93be58636c10a8d180dbccf2caeeaaff0e2))
+
+ ROM_REGION(0x400000, REGION_SOUND1, ROMREGION_ERASE00)
+
+ ROM_REGION(0xc0, REGION_USER2, ROMREGION_ERASE00) // Security dongle
+ ROM_LOAD("gq977-ja", 0x00, 0xc0, BAD_DUMP CRC(55b5abdb) SHA1(d8da5bac005235480a1815bd0a79c3e8a63ebad1))
+
+ DISK_REGION( REGION_DISKS )
+ DISK_IMAGE_READONLY( "gc977jaa01", 0, SHA1(aa43526971dad6502e4b9583d8f5c18d93ced820) MD5(161ab0096d8def5ef133eec872afc645) )
+ DISK_IMAGE_READONLY( "gc977jaa02", 1, SHA1(4a0edf424e091c33db91b00edf7c7246754cc8bb) MD5(9cb7cb79d2f0a47e994cfb91847ca190) )
+ROM_END
+
+/*****************************************************************************/
+
+GAME( 2000, ppp, 0, firebeat, ppp, ppp, ROT0, "Konami", "ParaParaParadise", GAME_NOT_WORKING);
+GAME( 2000, ppd, 0, firebeat, ppp, ppd, ROT0, "Konami", "ParaParaDancing", GAME_NOT_WORKING);
+GAME( 2000, ppp11, 0, firebeat, ppp, ppp, ROT0, "Konami", "ParaParaParadise v1.1", GAME_NOT_WORKING);
+GAMEL(2000, kbm, 0, firebeat2, kbm, kbm, ROT270, "Konami", "Keyboardmania", GAME_NOT_WORKING, layout_firebeat);
+GAMEL(2000, kbm2nd, 0, firebeat2, kbm, kbm, ROT270, "Konami", "Keyboardmania 2nd Mix", GAME_NOT_WORKING, layout_firebeat);
+GAMEL(2001, kbm3rd, 0, firebeat2, kbm, kbm, ROT270, "Konami", "Keyboardmania 3rd Mix", GAME_NOT_WORKING, layout_firebeat);
+GAME( 2001, popn7, 0, firebeat_spu, popn, ppp, ROT0, "Konami", "Pop n' Music 7", GAME_NOT_WORKING);