summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/missb2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/missb2.c')
-rw-r--r--src/mame/drivers/missb2.c456
1 files changed, 456 insertions, 0 deletions
diff --git a/src/mame/drivers/missb2.c b/src/mame/drivers/missb2.c
new file mode 100644
index 00000000000..e055cdcee22
--- /dev/null
+++ b/src/mame/drivers/missb2.c
@@ -0,0 +1,456 @@
+/* Miss Bubble 2
+
+A rather odd bootleg of Bubble Bobble with level select, redesigned levels,
+redesigned (8bpp!) graphics and different sound hardware... Crazy
+
+The Sound NMI and/or Interrupts aren't likely to be right. The Sound CPU
+starts writing to unusual memory ports - either because the NMI/Interrupt
+timing is out, or the sheer fact that the Sound CPU code is rather poorly
+written, so it may be normal behaviour.
+
+Also, the OKI M6295 seems to be playing the wrong samples, however the current
+OKI M6295 sound ROM dump is bad.
+
+*/
+
+#include "driver.h"
+#include "sound/okim6295.h"
+#include "sound/3812intf.h"
+
+static UINT8 *bg_paletteram, *missb2_bgvram;
+
+/* video/bublbobl.c */
+extern UINT8 *bublbobl_objectram;
+extern size_t bublbobl_objectram_size;
+
+/* machine/bublbobl.c */
+WRITE8_HANDLER( bublbobl_bankswitch_w );
+WRITE8_HANDLER( bublbobl_nmitrigger_w );
+WRITE8_HANDLER( bublbobl_sound_command_w );
+WRITE8_HANDLER( bublbobl_sh_nmi_disable_w );
+WRITE8_HANDLER( bublbobl_sh_nmi_enable_w );
+extern int bublbobl_video_enable;
+
+/* Video Hardware */
+
+static VIDEO_UPDATE( missb2 )
+{
+ int offs;
+ int sx,sy,xc,yc;
+ int gfx_num,gfx_attr,gfx_offs;
+ const UINT8 *prom_line;
+ UINT16 bg_offs;
+
+ /* Bubble Bobble doesn't have a real video RAM. All graphics (characters */
+ /* and sprites) are stored in the same memory region, and information on */
+ /* the background character columns is stored in the area dd00-dd3f */
+
+ /* This clears & redraws the entire screen each pass */
+ fillbitmap(bitmap,machine->pens[255],&machine->screen[0].visarea);
+
+ if (!bublbobl_video_enable) return 0;
+
+ /* background map register */
+ //popmessage("%02x",(*missb2_bgvram) & 0x1f);
+ for(bg_offs = ((*missb2_bgvram) << 4);bg_offs<(((*missb2_bgvram)<< 4)|0xf);bg_offs++)
+ {
+ drawgfx(bitmap,machine->gfx[1],
+ bg_offs,
+ 1,
+ 0,0,
+ 0,(bg_offs & 0xf) * 0x10,
+ &machine->screen[0].visarea,TRANSPARENCY_NONE,0xff);
+ }
+
+
+ sx = 0;
+
+ for (offs = 0;offs < bublbobl_objectram_size;offs += 4)
+ {
+ /* skip empty sprites */
+ /* this is dword aligned so the UINT32 * cast shouldn't give problems */
+ /* on any architecture */
+ if (*(UINT32 *)(&bublbobl_objectram[offs]) == 0)
+ continue;
+
+ gfx_num = bublbobl_objectram[offs + 1];
+ gfx_attr = bublbobl_objectram[offs + 3];
+ prom_line = memory_region(REGION_PROMS) + 0x80 + ((gfx_num & 0xe0) >> 1);
+
+ gfx_offs = ((gfx_num & 0x1f) * 0x80);
+ if ((gfx_num & 0xa0) == 0xa0)
+ gfx_offs |= 0x1000;
+
+ sy = -bublbobl_objectram[offs + 0];
+
+ for (yc = 0;yc < 32;yc++)
+ {
+ if (prom_line[yc/2] & 0x08) continue; /* NEXT */
+
+ if (!(prom_line[yc/2] & 0x04)) /* next column */
+ {
+ sx = bublbobl_objectram[offs + 2];
+ if (gfx_attr & 0x40) sx -= 256;
+ }
+
+ for (xc = 0;xc < 2;xc++)
+ {
+ int goffs,code,color,flipx,flipy,x,y;
+
+ goffs = gfx_offs + xc * 0x40 + (yc & 7) * 0x02 +
+ (prom_line[yc/2] & 0x03) * 0x10;
+ code = videoram[goffs] + 256 * (videoram[goffs + 1] & 0x03) + 1024 * (gfx_attr & 0x0f);
+ color = (videoram[goffs + 1] & 0x3c) >> 2;
+ flipx = videoram[goffs + 1] & 0x40;
+ flipy = videoram[goffs + 1] & 0x80;
+ x = sx + xc * 8;
+ y = (sy + yc * 8) & 0xff;
+
+ if (flip_screen)
+ {
+ x = 248 - x;
+ y = 248 - y;
+ flipx = !flipx;
+ flipy = !flipy;
+ }
+
+ drawgfx(bitmap,machine->gfx[0],
+ code,
+ 0,
+ flipx,flipy,
+ x,y,
+ &machine->screen[0].visarea,TRANSPARENCY_PEN,0xff);
+ }
+ }
+
+ sx += 16;
+ }
+ return 0;
+}
+
+INLINE void bg_changecolor_RRRRGGGGBBBBxxxx(pen_t color,int data)
+{
+ palette_set_color_rgb(Machine,color+256,pal4bit(data >> 12),pal4bit(data >> 8),pal4bit(data >> 4));
+}
+
+static WRITE8_HANDLER( bg_paletteram_RRRRGGGGBBBBxxxx_be_w )
+{
+ bg_paletteram[offset] = data;
+ bg_changecolor_RRRRGGGGBBBBxxxx(offset / 2,bg_paletteram[offset | 1] | (bg_paletteram[offset & ~1] << 8));
+}
+
+static WRITE8_HANDLER( missb2_bg_bank_w )
+{
+ int bankaddress;
+ UINT8 *RAM = memory_region(REGION_CPU2);
+
+ // I don't know how this is really connected,bit 1 is always high afaik...
+ bankaddress = ((data & 2) ? 0x1000 : 0x0000) | ((data & 1) ? 0x4000 : 0x0000) | (0x8000);
+ memory_set_bankptr(2, &RAM[bankaddress]);
+}
+
+/* Memory Maps */
+
+static ADDRESS_MAP_START( master_map, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x7fff) AM_ROM
+ AM_RANGE(0x8000, 0xbfff) AM_ROMBANK(1)
+ AM_RANGE(0xc000, 0xdcff) AM_RAM AM_BASE(&videoram) AM_SIZE(&videoram_size)
+ AM_RANGE(0xdd00, 0xdfff) AM_RAM AM_BASE(&bublbobl_objectram) AM_SIZE(&bublbobl_objectram_size)
+ AM_RANGE(0xe000, 0xf7ff) AM_RAM AM_SHARE(1)
+ AM_RANGE(0xf800, 0xf9ff) AM_RAM AM_WRITE(paletteram_RRRRGGGGBBBBxxxx_be_w) AM_BASE(&paletteram)
+ AM_RANGE(0xfa00, 0xfa00) AM_WRITE(bublbobl_sound_command_w)
+ AM_RANGE(0xfa03, 0xfa03) AM_WRITENOP // sound cpu reset
+ AM_RANGE(0xfa80, 0xfa80) AM_WRITENOP
+ AM_RANGE(0xfb40, 0xfb40) AM_WRITE(bublbobl_bankswitch_w)
+ AM_RANGE(0xfc00, 0xfcff) AM_RAM
+ AM_RANGE(0xfd00, 0xfdff) AM_RAM // ???
+ AM_RANGE(0xfe00, 0xfe03) AM_RAM // ???
+ AM_RANGE(0xfe80, 0xfe83) AM_RAM // ???
+ AM_RANGE(0xff00, 0xff00) AM_READ(input_port_0_r)
+ AM_RANGE(0xff01, 0xff01) AM_READ(input_port_1_r)
+ AM_RANGE(0xff02, 0xff02) AM_READ(input_port_2_r)
+ AM_RANGE(0xff03, 0xff03) AM_READ(input_port_3_r)
+ AM_RANGE(0xff94, 0xff94) AM_WRITENOP // ???
+ AM_RANGE(0xff98, 0xff98) AM_WRITENOP // ???
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( slave_map, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x7fff) AM_ROM
+ AM_RANGE(0x9000, 0xafff) AM_ROMBANK(2) // ROM data for the background palette ram
+ AM_RANGE(0xb000, 0xb1ff) AM_ROM // banked ???
+ AM_RANGE(0xc000, 0xc1ff) AM_RAM AM_WRITE(bg_paletteram_RRRRGGGGBBBBxxxx_be_w) AM_BASE(&bg_paletteram)
+ AM_RANGE(0xc800, 0xcfff) AM_RAM // main ???
+ AM_RANGE(0xd000, 0xd000) AM_WRITE(missb2_bg_bank_w)
+ AM_RANGE(0xd002, 0xd002) AM_WRITENOP
+ AM_RANGE(0xd003, 0xd003) AM_RAM AM_BASE(&missb2_bgvram)
+ AM_RANGE(0xe000, 0xf7ff) AM_RAM AM_SHARE(1)
+ADDRESS_MAP_END
+
+// Looks like the original bublbobl code modified to support the OKI M6295.
+
+static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x0000, 0x7fff) AM_ROM
+ AM_RANGE(0x8000, 0x8fff) AM_RAM
+ AM_RANGE(0x9000, 0x9000) AM_READWRITE(OKIM6295_status_0_r, OKIM6295_data_0_w)
+ AM_RANGE(0xa000, 0xa000) AM_READWRITE(YM3526_status_port_0_r, YM3526_control_port_0_w)
+ AM_RANGE(0xa001, 0xa001) AM_WRITE(YM3526_write_port_0_w)
+ AM_RANGE(0xb000, 0xb000) AM_READ(soundlatch_r) AM_WRITENOP // message for main cpu
+ AM_RANGE(0xb001, 0xb001) AM_READNOP AM_WRITE(bublbobl_sh_nmi_enable_w) // bit 0: message pending for main cpu, bit 1: message pending for sound cpu
+ AM_RANGE(0xb002, 0xb002) AM_WRITE(bublbobl_sh_nmi_disable_w)
+ AM_RANGE(0xe000, 0xefff) AM_ROM // space for diagnostic ROM?
+ADDRESS_MAP_END
+
+/* Input Ports */
+
+static INPUT_PORTS_START( missb2 )
+ PORT_START_TAG("DSW0")
+ PORT_DIPNAME( 0x01, 0x00, DEF_STR( Language ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( English ) )
+ PORT_DIPSETTING( 0x01, DEF_STR( Japanese ) )
+ PORT_DIPNAME( 0x02, 0x02, DEF_STR( Flip_Screen ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_SERVICE( 0x04, IP_ACTIVE_LOW )
+ PORT_DIPNAME( 0x08, 0x08, DEF_STR( Demo_Sounds ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( On ) )
+ PORT_DIPNAME( 0x30, 0x30, DEF_STR( Coin_A ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0x30, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) )
+ PORT_DIPSETTING( 0x20, DEF_STR( 1C_2C ) )
+ PORT_DIPNAME( 0xc0, 0xc0, DEF_STR( Coin_B ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0xc0, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( 2C_3C ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( 1C_2C ) )
+
+ PORT_START_TAG("DSW1")
+ PORT_DIPNAME( 0x03, 0x03, DEF_STR( Difficulty ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( Easy ) )
+ PORT_DIPSETTING( 0x03, DEF_STR( Medium ) )
+ PORT_DIPSETTING( 0x01, DEF_STR( Hard ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Hardest ) )
+ PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Bonus_Life ) )
+ PORT_DIPSETTING( 0x08, "20K 80K" )
+ PORT_DIPSETTING( 0x0c, "30K 100K" )
+ PORT_DIPSETTING( 0x04, "40K 200K" )
+ PORT_DIPSETTING( 0x00, "50K 250K" )
+ PORT_DIPNAME( 0x30, 0x30, DEF_STR( Lives ) )
+ PORT_DIPSETTING( 0x10, "1" )
+ PORT_DIPSETTING( 0x00, "2" )
+ PORT_DIPSETTING( 0x30, "3" )
+ PORT_DIPSETTING( 0x20, "5" )
+ PORT_DIPNAME( 0xc0, 0x00, "Monster Speed" )
+ PORT_DIPSETTING( 0x00, DEF_STR( Normal ) )
+ PORT_DIPSETTING( 0x40, DEF_STR( Medium ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( High ) )
+ PORT_DIPSETTING( 0xc0, DEF_STR( Very_High ) )
+
+ PORT_START_TAG("IN0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_2WAY
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_2WAY
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_COIN1 )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START1 )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_START_TAG("IN1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_2WAY PORT_PLAYER(2)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_2WAY PORT_PLAYER(2)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_TILT ) // ???
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SERVICE1 )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_START2 )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+INPUT_PORTS_END
+
+/* Graphics Layouts */
+
+static const gfx_layout charlayout =
+{
+ 8,8,
+ RGN_FRAC(1,4),
+ 8,
+ { RGN_FRAC(0,4)+0, RGN_FRAC(0,4)+4, RGN_FRAC(1,4)+0, RGN_FRAC(1,4)+4, RGN_FRAC(2,4)+0, RGN_FRAC(2,4)+4, RGN_FRAC(3,4)+0, RGN_FRAC(3,4)+4 },
+ { 3, 2, 1, 0, 8+3, 8+2, 8+1, 8+0 },
+ { 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
+ 16*8
+};
+
+static const UINT32 bglayout_xoffset[256] =
+{
+ 0*8, 1*8, 2048*8, 2049*8, 8*8, 9*8, 2056*8, 2057*8,
+ 4*8, 5*8, 2052*8, 2053*8, 12*8, 13*8, 2060*8, 2061*8,
+ 256*8 , 257*8, 2304*8, 2305*8, 264*8, 265*8, 2312*8, 2313*8,
+ 260*8 , 261*8, 2308*8, 2309*8, 268*8, 269*8, 2316*8, 2317*8,
+ 1024*8, 1025*8, 3072*8, 3073*8, 1032*8, 1033*8, 3080*8, 3081*8,
+ 1028*8, 1029*8, 3076*8, 3077*8, 1036*8, 1037*8, 3084*8, 3085*8,
+ 1280*8, 1281*8, 3328*8, 3329*8, 1288*8, 1289*8, 3336*8, 3337*8,
+ 1284*8, 1285*8, 3332*8, 3333*8, 1292*8, 1293*8, 3340*8, 3341*8,
+ 512*8, 513*8, 2560*8, 2561*8, 520*8, 521*8, 2568*8, 2569*8,
+ 516*8, 517*8, 2564*8, 2565*8, 524*8, 525*8, 2572*8, 2573*8,
+ 768*8, 769*8, 2816*8, 2817*8, 776*8, 777*8, 2824*8, 2825*8,
+ 772*8, 773*8, 2820*8, 2821*8, 780*8, 781*8, 2828*8, 2829*8,
+ 1536*8, 1537*8, 3584*8, 3585*8, 1544*8, 1545*8, 3592*8, 3593*8,
+ 1540*8, 1541*8, 3588*8, 3589*8, 1548*8, 1549*8, 3596*8, 3597*8,
+ 1792*8, 1793*8, 3840*8, 3841*8, 1800*8, 1801*8, 3848*8, 3849*8,
+ 1796*8, 1797*8, 3844*8, 3845*8, 1804*8, 1805*8, 3852*8, 3853*8,
+ 2*8, 3*8, 2050*8, 2051*8, 10*8, 11*8, 2058*8, 2059*8,
+ 6*8, 7*8, 2054*8, 2055*8, 14*8, 15*8, 2062*8, 2063*8,
+ 258*8, 259*8, 2306*8, 2307*8, 266*8, 267*8, 2314*8, 2315*8,
+ 262*8, 263*8, 2310*8, 2311*8, 270*8, 271*8, 2318*8, 2319*8,
+ 1026*8, 1027*8, 3074*8, 3075*8, 1034*8, 1035*8, 3082*8, 3083*8,
+ 1030*8, 1031*8, 3078*8, 3079*8, 1038*8, 1039*8, 3086*8, 3087*8,
+ 1282*8, 1283*8, 3330*8, 3331*8, 1290*8, 1291*8, 3338*8, 3339*8,
+ 1286*8, 1287*8, 3334*8, 3335*8, 1294*8, 1295*8, 3342*8, 3343*8,
+ 514*8, 515*8, 2562*8, 2563*8, 522*8, 523*8, 2570*8, 2571*8,
+ 518*8, 519*8, 2566*8, 2567*8, 526*8, 527*8, 2574*8, 2575*8,
+ 770*8, 771*8, 2818*8, 2819*8, 778*8, 779*8, 2826*8, 2827*8,
+ 774*8, 775*8, 2822*8, 2823*8, 782*8, 783*8, 2830*8, 2831*8,
+ 1538*8, 1539*8, 3586*8, 3587*8, 1546*8, 1547*8, 3594*8, 3595*8,
+ 1542*8, 1543*8, 3590*8, 3591*8, 1550*8, 1551*8, 3598*8, 3599*8,
+ 1794*8, 1795*8, 3842*8, 3843*8, 1802*8, 1803*8, 3850*8, 3851*8,
+ 1798*8, 1799*8, 3846*8, 3847*8, 1806*8, 1807*8, 3854*8, 3855*8
+};
+
+static const gfx_layout bglayout =
+{
+ 256,16,
+ RGN_FRAC(1,1),
+ 8,
+ { 0,1,2,3,4,5,6,7 },
+ EXTENDED_XOFFS,
+ { 0*128, 1*128, 2*128, 3*128, 4*128, 5*128, 6*128, 7*128, 8*128, 9*128, 10*128, 11*128, 12*128, 13*128, 14*128, 15*128 },
+ 256*128,
+ bglayout_xoffset,
+ NULL
+};
+
+/* Graphics Decode Information */
+
+static GFXDECODE_START( missb2 )
+ GFXDECODE_ENTRY( REGION_GFX1, 0x00000, charlayout, 0, 1 )
+ GFXDECODE_ENTRY( REGION_GFX2, 0x00000, bglayout, 0, 2 )
+GFXDECODE_END
+
+
+#define MAIN_XTAL 24000000 // not sure about this
+
+/* Sound Interfaces */
+
+// Handler called by the 3526 emulator when the internal timers cause an IRQ
+static void irqhandler(int irq)
+{
+ logerror("YM3526 firing an IRQ\n");
+// cpunum_set_input_line(2,0,irq ? ASSERT_LINE : CLEAR_LINE);
+}
+
+static struct YM3526interface ym3526_interface =
+{
+ irqhandler
+};
+
+/* Interrupt Generator */
+
+static INTERRUPT_GEN( missb2_interrupt )
+{
+ cpunum_set_input_line(2, 0, HOLD_LINE);
+}
+
+/* Machine Driver */
+
+static MACHINE_DRIVER_START( missb2 )
+ // basic machine hardware
+ MDRV_CPU_ADD(Z80, MAIN_XTAL/4) // 6 MHz
+ MDRV_CPU_PROGRAM_MAP(master_map, 0)
+ MDRV_CPU_VBLANK_INT(irq0_line_hold, 1)
+
+ MDRV_CPU_ADD(Z80, MAIN_XTAL/4) // 6 MHz
+ MDRV_CPU_PROGRAM_MAP(slave_map, 0)
+ MDRV_CPU_VBLANK_INT(irq0_line_hold, 1)
+
+ MDRV_CPU_ADD(Z80, MAIN_XTAL/8)
+ /* audio CPU */ // 3 MHz
+ MDRV_CPU_PROGRAM_MAP(sound_map, 0)
+// MDRV_CPU_VBLANK_INT(irq0_line_hold, 1)
+ MDRV_CPU_VBLANK_INT(missb2_interrupt, 1)
+
+ MDRV_SCREEN_REFRESH_RATE(60)
+ MDRV_SCREEN_VBLANK_TIME(DEFAULT_60HZ_VBLANK_DURATION)
+ MDRV_INTERLEAVE(100) // 100 CPU slices per frame - a high value to ensure proper synchronization of the CPUs
+
+ // video hardware
+ MDRV_VIDEO_ATTRIBUTES(VIDEO_TYPE_RASTER)
+ MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16)
+ MDRV_SCREEN_SIZE(32*8, 32*8)
+ MDRV_SCREEN_VISIBLE_AREA(0, 32*8-1, 2*8, 30*8-1)
+ MDRV_GFXDECODE(missb2)
+ MDRV_PALETTE_LENGTH(512)
+
+ MDRV_VIDEO_UPDATE(missb2)
+
+ // sound hardware
+ MDRV_SPEAKER_STANDARD_MONO("mono")
+
+ MDRV_SOUND_ADD(YM3526, MAIN_XTAL/8)
+ MDRV_SOUND_CONFIG(ym3526_interface)
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
+
+ MDRV_SOUND_ADD(OKIM6295, 1056000)
+ MDRV_SOUND_CONFIG(okim6295_interface_region_1_pin7high) // clock frequency & pin 7 not verified
+ MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.4)
+MACHINE_DRIVER_END
+
+/* ROMs */
+
+ROM_START( missb2 )
+ ROM_REGION( 0x30000, REGION_CPU1, 0 )
+ ROM_LOAD( "msbub2-u.204", 0x00000, 0x10000, CRC(b633bdde) SHA1(29a389c52ff06718f1c4c39f6a854856c237356b) ) /* FIRST AND SECOND HALF IDENTICAL */
+ /* ROMs banked at 8000-bfff */
+ ROM_LOAD( "msbub2-u.203", 0x10000, 0x10000, CRC(29fd8afe) SHA1(94ead80d20cd3974dd4fb0358915e3bd8b793158) )
+ /* 20000-2ffff empty */
+
+ ROM_REGION( 0x10000, REGION_CPU2, 0 ) /* 64k for the second CPU */
+ ROM_LOAD( "msbub2-u.11", 0x0000, 0x10000, CRC(003dc092) SHA1(dff3c2b31d0804a308e5c42cf9705cd3d6144ad7) )
+
+ ROM_REGION( 0x10000, REGION_CPU3, 0 ) /* 64k for the third CPU */
+ ROM_LOAD( "msbub2-u.211", 0x0000, 0x08000, CRC(08e5d846) SHA1(8509a71df984f0348bdc6ab60eb2ba7ceb9b1246) )
+
+ ROM_REGION( 0x100000, REGION_GFX1, ROMREGION_DISPOSE | ROMREGION_INVERT )
+ ROM_LOAD( "msbub2-u.14", 0x00000, 0x40000, CRC(b3164b47) SHA1(083a63010515b0aa43b482938ae302b2df985312) )
+ ROM_LOAD( "msbub2-u.126", 0x40000, 0x40000, CRC(b0a9a353) SHA1(40d7f4c970d8571de319231c295fa0d2836efcf7) )
+ ROM_LOAD( "msbub2-u.124", 0x80000, 0x40000, CRC(4b0d8e5b) SHA1(218da3edcfea228e6df1ac59bc24217713d79410) )
+ ROM_LOAD( "msbub2-u.125", 0xc0000, 0x40000, CRC(77b710e2) SHA1(f6f46804a23de6c930bc40a3f45ac70e160f0645) )
+
+ ROM_REGION( 0x200000, REGION_GFX2, 0 ) /* background images */
+ ROM_LOAD16_BYTE( "msbub2-u.ic1", 0x100001, 0x80000, CRC(d621cbc3) SHA1(36343d85bdde0e40dfe0f0e4e646546f175903f8) )
+ ROM_LOAD16_BYTE( "msbub2-u.ic3", 0x100000, 0x80000, CRC(90e56035) SHA1(8fa18d97a05890178c52b97ff75aed300344a93e) )
+ ROM_LOAD16_BYTE( "msbub2-u.ic2", 0x000001, 0x80000, CRC(694c2783) SHA1(401dc8713a02130289f364786c38e70c4c4f9b2e) )
+ ROM_LOAD16_BYTE( "msbub2-u.ic4", 0x000000, 0x80000, CRC(be71c9f0) SHA1(1961e931017f644486cea0ce431d50973679c848) )
+
+ ROM_REGION( 0x20000, REGION_SOUND1, 0 ) /* samples */
+ ROM_LOAD( "msbub2-u.13", 0x00000, 0x20000, BAD_DUMP CRC(14f07386) SHA1(097897d92226f900e11dbbdd853aff3ac46ff016) )
+
+ ROM_REGION( 0x0100, REGION_PROMS, 0 )
+ ROM_LOAD( "a71-25.bin", 0x0000, 0x0100, CRC(2d0f8545) SHA1(089c31e2f614145ef2743164f7b52ae35bc06808) ) /* video timing - taken from bublbobl */
+ROM_END
+
+/* Driver Initialization */
+
+static DRIVER_INIT( missb2 )
+{
+ UINT8 *ROM = memory_region(REGION_CPU1);
+
+ /* in Bubble Bobble, bank 0 has code falling from 7fff to 8000,
+ so I have to copy it there because bank switching wouldn't catch it */
+ memcpy(ROM+0x08000,ROM+0x10000,0x4000);
+
+}
+
+/* Game Drivers */
+
+GAME( 1996, missb2, bublbobl, missb2, missb2, missb2, ROT0, "Alpha Co", "Miss Bubble 2", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )