summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/mame/drivers/chanbara.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/mame/drivers/chanbara.c')
-rw-r--r--trunk/src/mame/drivers/chanbara.c490
1 files changed, 490 insertions, 0 deletions
diff --git a/trunk/src/mame/drivers/chanbara.c b/trunk/src/mame/drivers/chanbara.c
new file mode 100644
index 00000000000..d5e68bb2950
--- /dev/null
+++ b/trunk/src/mame/drivers/chanbara.c
@@ -0,0 +1,490 @@
+/****************************************************************************************
+Chanbara
+Data East, 1985
+
+PCB Layout
+----------
+
+DE-0207-0
+|-----------------------------------------------------------|
+| CP12.17H CP00-2.17C |
+| 2016 6809 |
+| CP13.15H CP01.15C |
+| 2016 |
+|1 RCDM-I4 CP14.13H CP02.14C |
+|8 RCDM-I1 2016 |
+|W RCDM-I1 CP03.11C 2016 |
+|A RCDM-I1 2148 CP04.10C |
+|Y RCDM-I1 CP05.9C |
+| RCDM-I1 2148 CP06.8C |
+| RM-C2 2148 TC15G032AY|
+| PM-C1 2148 CP07.6C |
+| DSW1 CP08.5C |
+|CP15.6K DECO DECO |
+|CP16.5K VSC30 CP09.3C HMC20 |
+|CP17.4K CP10.2C |
+|MB3730 558 558 YM3014 YM2203 CP11.1C 12MHz |
+|-----------------------------------------------------------|
+Notes:
+ 6809 - clock 1.500MHz [12/8]
+ YM2203 - clock 1.500MHz [12/8]
+ VSC30 - clock 3.000MHz [12/4, pin 7), custom DECO DIP40 IC
+ HMC20 - DECO HMC20 custom DIP28 IC. Provides many clocks each divided by 2
+ (i.e. 12MHz, 6MHz, 3MHz, 1.5MHz, 750kHz etc)
+ HSync is generated on pins 12 and 13 with 12/256/3. Actual xtal measures
+ 11.9931MHz, which accounts for the measured HSync error (12/256/3 = 15.625kHz)
+ VSync - 57.4122Hz
+ HSync - 15.6161kHz
+
+------------------------
+
+ Driver by Tomasz Slanina & David Haywood
+ Inputs and Dip Switches by stephh
+
+ToDo:
+ there might still be some sprite banking issues
+ support screen flipping for sprites
+
+
+****************************************************************************************/
+
+#include "emu.h"
+#include "cpu/m6809/m6809.h"
+#include "sound/2203intf.h"
+
+
+class chanbara_state : public driver_device
+{
+public:
+ chanbara_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag) ,
+ m_videoram(*this, "videoram"),
+ m_colorram(*this, "colorram"),
+ m_spriteram(*this, "spriteram"),
+ m_videoram2(*this, "videoram2"),
+ m_colorram2(*this, "colorram2"){ }
+
+ /* memory pointers */
+ required_shared_ptr<UINT8> m_videoram;
+ required_shared_ptr<UINT8> m_colorram;
+ required_shared_ptr<UINT8> m_spriteram;
+ required_shared_ptr<UINT8> m_videoram2;
+ required_shared_ptr<UINT8> m_colorram2;
+
+ /* video-related */
+ tilemap_t *m_bg_tilemap;
+ tilemap_t *m_bg2_tilemap;
+ UINT8 m_scroll;
+ UINT8 m_scrollhi;
+
+ /* devices */
+ device_t *m_maincpu;
+ DECLARE_WRITE8_MEMBER(chanbara_videoram_w);
+ DECLARE_WRITE8_MEMBER(chanbara_colorram_w);
+ DECLARE_WRITE8_MEMBER(chanbara_videoram2_w);
+ DECLARE_WRITE8_MEMBER(chanbara_colorram2_w);
+};
+
+
+static PALETTE_INIT( chanbara )
+{
+ const UINT8 *color_prom = machine.root_device().memregion("proms")->base();
+ int i, red, green, blue;
+
+ for (i = 0; i < machine.total_colors(); i++)
+ {
+ red = color_prom[i];
+ green = color_prom[machine.total_colors() + i];
+ blue = color_prom[2 * machine.total_colors() + i];
+
+ palette_set_color_rgb(machine, i, pal4bit(red << 1), pal4bit(green << 1), pal4bit(blue << 1));
+ }
+}
+
+WRITE8_MEMBER(chanbara_state::chanbara_videoram_w)
+{
+
+ m_videoram[offset] = data;
+ m_bg_tilemap->mark_tile_dirty(offset);
+}
+
+WRITE8_MEMBER(chanbara_state::chanbara_colorram_w)
+{
+
+ m_colorram[offset] = data;
+ m_bg_tilemap->mark_tile_dirty(offset);
+}
+
+WRITE8_MEMBER(chanbara_state::chanbara_videoram2_w)
+{
+
+ m_videoram2[offset] = data;
+ m_bg2_tilemap->mark_tile_dirty(offset);
+}
+
+WRITE8_MEMBER(chanbara_state::chanbara_colorram2_w)
+{
+
+ m_colorram2[offset] = data;
+ m_bg2_tilemap->mark_tile_dirty(offset);
+}
+
+
+static TILE_GET_INFO( get_bg_tile_info )
+{
+ chanbara_state *state = machine.driver_data<chanbara_state>();
+ int code = state->m_videoram[tile_index] + ((state->m_colorram[tile_index] & 1) << 8);
+ int color = (state->m_colorram[tile_index] >> 1) & 0x1f;
+
+ SET_TILE_INFO(0, code, color, 0);
+}
+
+static TILE_GET_INFO( get_bg2_tile_info )
+{
+ chanbara_state *state = machine.driver_data<chanbara_state>();
+ int code = state->m_videoram2[tile_index];
+ int color = (state->m_colorram2[tile_index] >> 1) & 0x1f;
+
+ SET_TILE_INFO(2, code, color, 0);
+}
+
+static VIDEO_START(chanbara )
+{
+ chanbara_state *state = machine.driver_data<chanbara_state>();
+ state->m_bg_tilemap = tilemap_create(machine, get_bg_tile_info, tilemap_scan_rows,8, 8, 32, 32);
+ state->m_bg2_tilemap = tilemap_create(machine, get_bg2_tile_info, tilemap_scan_rows,16, 16, 16, 32);
+ state->m_bg_tilemap->set_transparent_pen(0);
+}
+
+static void draw_sprites( running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect )
+{
+ chanbara_state *state = machine.driver_data<chanbara_state>();
+ int offs;
+
+ for (offs = 0; offs < 0x80; offs += 4)
+ {
+ if (state->m_spriteram[offs + 0x80] & 0x80)
+ {
+ int attr = state->m_spriteram[offs + 0];
+ int code = state->m_spriteram[offs + 1];
+ int color = state->m_spriteram[offs + 0x80] & 0x1f;
+ int flipx = 0;
+ int flipy = attr & 2;
+ int sx = 240 - state->m_spriteram[offs + 3];
+ int sy = 232 - state->m_spriteram[offs + 2];
+
+ sy+=16;
+
+ if (state->m_spriteram[offs + 0x80] & 0x10) code += 0x200;
+ if (state->m_spriteram[offs + 0x80] & 0x20) code += 0x400;
+ if (state->m_spriteram[offs + 0x80] & 0x40) code += 0x100;
+
+ if (attr & 0x10)
+ {
+ if (!flipy)
+ {
+ drawgfx_transpen(bitmap, cliprect, machine.gfx[1], code, color, flipx, flipy, sx, sy-16, 0);
+ drawgfx_transpen(bitmap, cliprect, machine.gfx[1], code+1, color, flipx, flipy, sx, sy, 0);
+ }
+ else
+ {
+ drawgfx_transpen(bitmap, cliprect, machine.gfx[1], code, color, flipx, flipy, sx, sy, 0);
+ drawgfx_transpen(bitmap, cliprect, machine.gfx[1], code+1, color, flipx, flipy, sx, sy-16, 0);
+ }
+ }
+ else
+ {
+ drawgfx_transpen(bitmap, cliprect, machine.gfx[1], code, color, flipx, flipy, sx, sy, 0);
+ }
+ }
+ }
+}
+
+static SCREEN_UPDATE_IND16( chanbara )
+{
+ chanbara_state *state = screen.machine().driver_data<chanbara_state>();
+
+ state->m_bg2_tilemap->set_scrolly(0, state->m_scroll | (state->m_scrollhi << 8));
+ state->m_bg2_tilemap->draw(bitmap, cliprect, 0, 0);
+ draw_sprites(screen.machine(), bitmap, cliprect);
+ state->m_bg_tilemap->draw(bitmap, cliprect, 0, 0);
+ return 0;
+}
+
+/***************************************************************************/
+
+static ADDRESS_MAP_START( chanbara_map, AS_PROGRAM, 8, chanbara_state )
+ AM_RANGE(0x0000, 0x07ff) AM_RAM
+ AM_RANGE(0x0800, 0x0bff) AM_RAM_WRITE(chanbara_videoram_w) AM_SHARE("videoram")
+ AM_RANGE(0x0c00, 0x0fff) AM_RAM_WRITE(chanbara_colorram_w) AM_SHARE("colorram")
+ AM_RANGE(0x1000, 0x10ff) AM_RAM AM_SHARE("spriteram")
+ AM_RANGE(0x1800, 0x19ff) AM_RAM_WRITE(chanbara_videoram2_w) AM_SHARE("videoram2")
+ AM_RANGE(0x1a00, 0x1bff) AM_RAM_WRITE(chanbara_colorram2_w) AM_SHARE("colorram2")
+ AM_RANGE(0x2000, 0x2000) AM_READ_PORT("DSW1")
+ AM_RANGE(0x2001, 0x2001) AM_READ_PORT("SYSTEM")
+ AM_RANGE(0x2002, 0x2002) AM_READ_PORT("P2")
+ AM_RANGE(0x2003, 0x2003) AM_READ_PORT("P1")
+ AM_RANGE(0x3800, 0x3801) AM_DEVREADWRITE_LEGACY("ymsnd", ym2203_r, ym2203_w)
+ AM_RANGE(0x4000, 0x7fff) AM_ROMBANK("bank1")
+ AM_RANGE(0x8000, 0xffff) AM_ROM
+ADDRESS_MAP_END
+
+/***************************************************************************/
+
+/* verified from M6809 code */
+static INPUT_PORTS_START( chanbara )
+ PORT_START ("DSW1")
+ PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coin_B ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0x03, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) )
+ PORT_DIPSETTING( 0x01, DEF_STR( 1C_3C ) )
+ PORT_DIPNAME( 0x0c, 0x0c, DEF_STR( Coin_A ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0x0c, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0x08, DEF_STR( 1C_2C ) )
+ PORT_DIPSETTING( 0x04, DEF_STR( 1C_3C ) )
+ PORT_DIPNAME( 0x10, 0x10, DEF_STR( Difficulty ) ) /* code at 0xedc0 */
+ PORT_DIPSETTING( 0x10, DEF_STR( Easy ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Hard ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Lives ) )
+ PORT_DIPSETTING( 0x00, "1" )
+ PORT_DIPSETTING( 0x20, "3" )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Bonus_Life ) ) /* table at 0xc249 (2 * 2 words) */
+ PORT_DIPSETTING( 0x40, "50k and 70k" )
+ PORT_DIPSETTING( 0x00, DEF_STR( None ) )
+ PORT_DIPNAME( 0x80, 0x00, DEF_STR( Cabinet ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Upright ) )
+ PORT_DIPSETTING( 0x80, DEF_STR( Cocktail ) )
+
+ PORT_START ("SYSTEM")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN2 )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SERVICE1 ) /* same coinage as COIN1 */
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen")
+
+ PORT_START ("P1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT )
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN )
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT )
+
+ PORT_START ("P2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_DOWN ) PORT_COCKTAIL
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_UP ) PORT_COCKTAIL
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_LEFT ) PORT_COCKTAIL
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICKLEFT_RIGHT ) PORT_COCKTAIL
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_DOWN ) PORT_COCKTAIL
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_UP ) PORT_COCKTAIL
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_LEFT ) PORT_COCKTAIL
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICKRIGHT_RIGHT ) PORT_COCKTAIL
+INPUT_PORTS_END
+
+/***************************************************************************/
+
+static const gfx_layout tilelayout =
+{
+ 8,8, /* tile size */
+ RGN_FRAC(1,2), /* number of tiles */
+ 2, /* bits per pixel */
+ { 0, 4 }, /* plane offsets */
+ { RGN_FRAC(1,2)+0, RGN_FRAC(1,2)+1, RGN_FRAC(1,2)+2, RGN_FRAC(1,2)+3, 0,1,2,3 }, /* x offsets */
+ { 0*8,1*8,2*8,3*8, 4*8, 5*8, 6*8, 7*8 }, /* y offsets */
+ 8*8 /* offset to next tile */
+};
+
+static const gfx_layout tile16layout =
+{
+ 16,16, /* tile size */
+ RGN_FRAC(1,4), /* number of tiles */
+ 3, /* bits per pixel */
+ { RGN_FRAC(1,2),0,4 }, /* plane offsets */
+ { 16*8+RGN_FRAC(1,4)+0,16*8+ RGN_FRAC(1,4)+1,16*8+ RGN_FRAC(1,4)+2,16*8+ RGN_FRAC(1,4)+3,
+ 0,1,2,3,
+ RGN_FRAC(1,4)+0, RGN_FRAC(1,4)+1, RGN_FRAC(1,4)+2, RGN_FRAC(1,4)+3,
+ 16*8+0, 16*8+1, 16*8+2, 16*8+3,
+
+ }, /* x offsets */
+ { 0*8,1*8,2*8,3*8, 4*8, 5*8, 6*8, 7*8,8*8,9*8,10*8,11*8,12*8,13*8,14*8,15*8 }, /* y offsets */
+ 32*8 /* offset to next tile */
+};
+
+
+static const gfx_layout spritelayout =
+{
+ 16,16,
+ RGN_FRAC(1,3),
+ 3,
+ { RGN_FRAC(2,3),RGN_FRAC(1,3), 0},
+ { 2*8*8+0,2*8*8+1,2*8*8+2,2*8*8+3,2*8*8+4,2*8*8+5,2*8*8+6,2*8*8+7,
+ 0,1,2,3,4,5,6,7 },
+ { 0*8,1*8,2*8,3*8,4*8,5*8,6*8,7*8,
+ 1*8*8+0*8,1*8*8+1*8,1*8*8+2*8,1*8*8+3*8,1*8*8+4*8,1*8*8+5*8,1*8*8+6*8,1*8*8+7*8 },
+ 16*16
+};
+
+static GFXDECODE_START( chanbara )
+ GFXDECODE_ENTRY( "gfx1", 0x00000, tilelayout, 0x40, 32 )
+ GFXDECODE_ENTRY( "gfx2", 0x00000, spritelayout, 0x80, 16 )
+
+ GFXDECODE_ENTRY( "gfx3", 0x00000, tile16layout, 0, 32 )
+GFXDECODE_END
+/***************************************************************************/
+
+
+static WRITE8_DEVICE_HANDLER( chanbara_ay_out_0_w )
+{
+ chanbara_state *state = device->machine().driver_data<chanbara_state>();
+ //printf("chanbara_ay_out_0_w %02x\n",data);
+
+ state->m_scroll = data;
+}
+
+static WRITE8_DEVICE_HANDLER( chanbara_ay_out_1_w )
+{
+ chanbara_state *state = device->machine().driver_data<chanbara_state>();
+ //printf("chanbara_ay_out_1_w %02x\n",data);
+
+ state->m_scrollhi = data & 0x01;
+
+ state->flip_screen_set(data & 0x02);
+
+ state->membank("bank1")->set_entry((data & 0x04) >> 2);
+
+ //if (data & 0xf8) printf("chanbara_ay_out_1_w unused bits set %02x\n", data & 0xf8);
+}
+
+static void sound_irq( device_t *device, int linestate )
+{
+ chanbara_state *state = device->machine().driver_data<chanbara_state>();
+ device_set_input_line(state->m_maincpu, 0, linestate);
+}
+
+
+static const ym2203_interface ym2203_config =
+{
+ {
+ AY8910_LEGACY_OUTPUT,
+ AY8910_DEFAULT_LOADS,
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_HANDLER(chanbara_ay_out_0_w),
+ DEVCB_HANDLER(chanbara_ay_out_1_w),
+ },
+ sound_irq
+};
+
+
+static MACHINE_START( chanbara )
+{
+ chanbara_state *state = machine.driver_data<chanbara_state>();
+
+ state->m_maincpu = machine.device("maincpu");
+
+ state->save_item(NAME(state->m_scroll));
+ state->save_item(NAME(state->m_scrollhi));
+}
+
+static MACHINE_RESET( chanbara )
+{
+ chanbara_state *state = machine.driver_data<chanbara_state>();
+
+ state->m_scroll = 0;
+ state->m_scrollhi = 0;
+}
+
+static MACHINE_CONFIG_START( chanbara, chanbara_state )
+
+ MCFG_CPU_ADD("maincpu", M6809, 12000000/8)
+ MCFG_CPU_PROGRAM_MAP(chanbara_map)
+
+ MCFG_MACHINE_START(chanbara)
+ MCFG_MACHINE_RESET(chanbara)
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_REFRESH_RATE(57.4122)
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
+ MCFG_SCREEN_SIZE(32*8, 32*8)
+ MCFG_SCREEN_VISIBLE_AREA(0, 32*8-1, 2*8, 30*8-1)
+ MCFG_SCREEN_UPDATE_STATIC(chanbara)
+
+ MCFG_GFXDECODE(chanbara)
+ MCFG_PALETTE_LENGTH(256)
+ MCFG_PALETTE_INIT(chanbara)
+
+ MCFG_VIDEO_START(chanbara)
+
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+
+ MCFG_SOUND_ADD("ymsnd", YM2203, 12000000/8)
+ MCFG_SOUND_CONFIG(ym2203_config)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
+MACHINE_CONFIG_END
+
+
+ROM_START( chanbara )
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD( "cp01.16c", 0x08000, 0x4000, CRC(a0c3c24c) SHA1(8445dc39dd763187a2d66c6165b487f146e7d474))
+ ROM_LOAD( "cp00-2.17c", 0x0c000, 0x4000, CRC(a045e463) SHA1(2eb546e16f163be6ed72238f2f0203527a957efd) )
+
+ ROM_REGION( 0x8000, "user1", 0 ) // background data
+ ROM_LOAD( "cp02.14c", 0x00000, 0x8000, CRC(c2b66cea) SHA1(f72f57add5f38313a72f5c521dce157edf49f70e) )
+
+ ROM_REGION( 0x02000, "gfx1", 0 ) // text layer
+ ROM_LOAD( "cp12.17h", 0x00000, 0x2000, CRC(b87b96de) SHA1(f8bb9f094917df305c4fed071edaa775071e40fd) )
+
+ ROM_REGION( 0x08000, "gfx3", 0 ) // bg layer
+ ROM_LOAD( "cp13.15h", 0x00000, 0x4000, CRC(2dc38c3d) SHA1(4bb1335b8285e91b51c28e74d8de11a8d6df0486) )
+ /* rom cp14.13h is expanded at 0x4000 - 0x8000 */
+
+ ROM_REGION( 0x08000, "gfx4", 0 )
+ ROM_LOAD( "cp14.13h", 0x00000, 0x2000, CRC(d31db368) SHA1(b62834137bfe4ac2013d2d16b0ead10bf2a2df83) )
+
+ ROM_REGION( 0x24000, "gfx2", 0 )
+ ROM_LOAD( "cp03.12c", 0x08000, 0x4000, CRC(dea247fb) SHA1(d54fa30813613ef6c3b5f86b563e9ab618a9f627))
+ ROM_LOAD( "cp04.10c", 0x04000, 0x4000, CRC(f7dce87b) SHA1(129ae41d70d96720e020ec1bc1d3f2d9e87ebf47) )
+ ROM_LOAD( "cp05.9c", 0x00000, 0x4000, CRC(df2dc3cb) SHA1(3505042c91566bb09fcd2102fecbe2034551b8eb) )
+
+ ROM_LOAD( "cp06.7c", 0x14000, 0x4000, CRC(2f337c08) SHA1(657ee6776780fa0a979a278ff27a49b459232cad) )
+ ROM_LOAD( "cp07.6c", 0x10000, 0x4000, CRC(0e3727f2) SHA1(d177651bc20a56f5651ae5ce6f3d3ff7ad0e2053) )
+ ROM_LOAD( "cp08.5c", 0x0c000, 0x4000, CRC(4cf35192) SHA1(1891dcc412caf72ba5a2ea56c1cab35cb3ae6123) )
+
+ ROM_LOAD( "cp09.4c", 0x20000, 0x4000, CRC(3f58b647) SHA1(4eb212667aedd7c397a4911ac7f1b542c5c0a70d) )
+ ROM_LOAD( "cp10.2c", 0x1c000, 0x4000, CRC(bfa324c0) SHA1(c7ff09bb5f1dd2d3707970fae1fd60b6004250c0) )
+ ROM_LOAD( "cp11.1c", 0x18000, 0x4000, CRC(33e6160a) SHA1(b0171b554825072eebe935d12a6085d158b87bdc) )
+
+ ROM_REGION( 0x0300, "proms", 0 )
+ ROM_LOAD( "cp17.4k", 0x0000, 0x0100, CRC(cf03706e) SHA1(2dd2b29067f418ec590c56a38cc64d09d8dc8e09) ) /* red */
+ ROM_LOAD( "cp16.5k", 0x0100, 0x0100, CRC(5fedc8ba) SHA1(8b685ce71d833fefb3e4502d1dd0cca96ba9162a) ) /* green */
+ ROM_LOAD( "cp15.6k", 0x0200, 0x0100, CRC(655936eb) SHA1(762b419c0571fafd8e1c5e96d0d94999768ba325) ) /* blue */
+ROM_END
+
+
+static DRIVER_INIT(chanbara )
+{
+ UINT8 *src = machine.root_device().memregion("gfx4")->base();
+ UINT8 *dst = machine.root_device().memregion("gfx3")->base() + 0x4000;
+ UINT8 *bg = machine.root_device().memregion("user1")->base();
+
+ int i;
+ for (i = 0; i < 0x1000; i++)
+ {
+ dst[i + 0x1000] = src[i] & 0xf0;
+ dst[i + 0x0000] = (src[i] & 0x0f) << 4;
+ dst[i + 0x3000] = src[i + 0x1000] & 0xf0;
+ dst[i + 0x2000] = (src[i + 0x1000] & 0x0f) << 4;
+ }
+
+ machine.root_device().membank("bank1")->configure_entries(0, 2, &bg[0x0000], 0x4000);
+}
+
+GAME( 1985, chanbara, 0, chanbara, chanbara, chanbara, ROT270, "Data East", "Chanbara", GAME_SUPPORTS_SAVE | GAME_NO_COCKTAIL )
*/ #define MR_R7 RES_K(4.7) /* verified */ #define MR_R17 RES_K(27) /* 20 according to parts list */ /* 27 verified, 30K in schematics */ #define MR_R18 RES_K(27) /* 20 according to parts list */ /* 27 verified, 30K in schematics */ #define MR_R19 RES_K(22) /* verified */ #define MR_R20 RES_K(22) /* verified */ #define MR_R40 RES_K(22) /* verified */ #define MR_R41 RES_K(100) /* verified, hard to read */ #define MR_R42 RES_K(43) #define MR_R43 RES_K(100) #define MR_R61 RES_K(47) /* verified, hard to read */ #define MR_R64 RES_K(20) /* verified */ #define MR_R65 RES_K(10) /* verified */ #define MR_C3 CAP_U(10) /* verified */ #define MR_C4 CAP_U(4.7) /* illegible, 4.7 or 47 pcb/schematics */ /* 4.7 in parts list */ #define MR_C5 CAP_N(39) /* illegible on pcb */ #define MR_C6 CAP_N(3.9) /* illegible on pcb */ #define MR_C14 CAP_U(4.7) /* verified */ #define MR_C15 CAP_U(4.7) /* verified */ #define MR_C16 CAP_N(6.8) /* verified */ #define MR_C17 CAP_N(22) /* illegible on pcb */ #define MR_C31 CAP_U(0.022) /* not found */ #define MR_C32 CAP_U(1) /* illegible on pcb */ #define MR_C39 CAP_N(4.7) /* not found */ #define MR_C40 CAP_N(22) /* verified */ //#define MR_C41 CAP_U(4.7) /* verified, hard to read */ #define MR_C41 CAP_U(4.7) #define MR_C43 CAP_U(3.3) /* verified */ #define MR_C44 CAP_U(3.3) /* verified */ #define MR_MIXER_RPAR RES_4_PARALLEL(MR_R20, MR_R19, MR_R41, MR_R40) /* KT = 0.25 for diode circuit, 0.33 else */ #define DISCRETE_LS123(_N, _T, _R, _C) \ DISCRETE_ONESHOTR(_N, 0, _T, TTL_HIGH, (0.25 * (_R) * (_C) * (1.0+700./(_R))), DISC_ONESHOT_RETRIG | DISC_ONESHOT_REDGE) #define DISCRETE_LS123_INV(_N, _T, _R, _C) \ DISCRETE_ONESHOTR(_N, 0, _T, TTL_HIGH, (0.25 * (_R) * (_C) * (1.0+700./(_R))), DISC_ONESHOT_RETRIG | DISC_ONESHOT_REDGE | DISC_OUT_ACTIVE_LOW) #define DISCRETE_BITSET(_N, _N1, _B) DISCRETE_TRANSFORM3(_N, _N1, (1 << ((_B)-1)), 0, "01&2>") /* The following formula was derived from figures 2 and 3 in LS624 datasheet. Coefficients * where calculated using least square approximation. * This approach gives a bit better results compared to the first approach. */ #define LS624_F(_C, _VI, _VR) pow(10, -0.912029404 * log10(_C) + 0.243264328 * (_VI) \ - 0.091695877 * (_VR) -0.014110946 * (_VI) * (_VR) - 3.207072925) /************************************************************************ * * Custom mario run * * Two VCO with XOR'd signal * * input[0] - Enable / Amplitude * input[1] - In1 VCO Control 1 * input[2] - In2 VCO Control 2 * input[3] - C1 VCO 1 Cap * input[4] - C2 VCO 2 CAP * input[5] - R1 * input[6] - C3 * * Vout >-------------------------- * | * C1 | * -||- | * | | -- +--- * ------ --- |AND| R1 * In1 >---+ Y1 +--------+ | |(*)+---ZZZ--+------> Out * | | |XOR+------+--- | * | | ---+ | | * | | | --- --- * In2 >---+ Y2 +---- --- C3 * ------ | * | | Gnd * -||- * C2 ************************************************************************/ #define MARIO_CUSTOM_VOUT (*(node->input[0])) #define MARIO_CUSTOM_IN1 (*(node->input[1])) #define MARIO_CUSTOM_IN2 (*(node->input[2])) #define MARIO_CUSTOM_C1 (*(node->input[3])) #define MARIO_CUSTOM_C2 (*(node->input[4])) #define MARIO_CUSTOM_R1 (*(node->input[5])) #define MARIO_CUSTOM_C3 (*(node->input[6])) struct mario_custom_run_context { int state1; int state2; double remain1; double remain2; double vc3; }; static DISCRETE_STEP( mario_custom_run ) { struct mario_custom_run_context *context = node->context; double t1 = 0.5 / LS624_F(MARIO_CUSTOM_C1, MARIO_CUSTOM_IN1, RUN_VCO_VOLTAGE); double t2 = 0.5 / LS624_F(MARIO_CUSTOM_C2, MARIO_CUSTOM_IN2, RUN_VCO_VOLTAGE); double sample_t = discrete_current_context->sample_time; double vn, t; //if (MARIO_CUSTOM_VOUT) // printf("%f %f %f %f\n", MARIO_CUSTOM_IN1, MARIO_CUSTOM_IN2, 0.5 / t1, 0.5 / t2); while (sample_t > 0.0f) { /* state before time advance */ vn = (double) (context->state1 ^ context->state2); vn *= MARIO_CUSTOM_VOUT; if (context->remain1 < context->remain2) { if (context->remain1 < sample_t) { t = context->remain1; context->state1 ^= 1; sample_t -= context->remain1; context->remain2 -= context->remain1; context->remain1 = t1; } else { t = sample_t; context->remain1 -= sample_t; context->remain2 -= sample_t; sample_t = 0.0f; } } else { if (context->remain2 < sample_t) { t = context->remain2; context->state2 ^= 1; sample_t -= context->remain2; context->remain1 -= context->remain2; context->remain2 = t2; } else { t = sample_t; context->remain1 -= sample_t; context->remain2 -= sample_t; sample_t = 0.0f; } } context->vc3 += (vn - context->vc3) * (1.0 - exp(- t / (MARIO_CUSTOM_R1 * MARIO_CUSTOM_C3))); } node->output[0] = context->vc3; } static DISCRETE_RESET( mario_custom_run ) { struct mario_custom_run_context *context = node->context; context->remain1 = 0.0; context->remain2 = 0.0; context->state1 = 0; context->state2 = 0; context->vc3 = 0; node->output[0] = 0; } static const discrete_custom_info mario_custom_run_info = { DISCRETE_RESET_NAME( mario_custom_run ), DISCRETE_STEP_NAME( mario_custom_run ), sizeof(struct mario_custom_run_context), NULL }; static DISCRETE_SOUND_START(mario) /************************************************/ /* Input register mapping for mario */ /************************************************/ /* DISCRETE_INPUT_DATA */ DISCRETE_INPUT_PULSE(DS_SOUND0_INV, 1) DISCRETE_INPUT_PULSE(DS_SOUND1_INV, 1) DISCRETE_INPUT_NOT(DS_SOUND7_INV) DISCRETE_INPUT_DATA(DS_DAC) /************************************************/ /* SOUND0 */ /************************************************/ DISCRETE_LS123(NODE_10, DS_SOUND0_INV, MR_R17, CAP_AGE(MR_C14, 0.7)) DISCRETE_RCFILTER(NODE_11, 1, NODE_10, MR_R6, CAP_AGE(MR_C3, 0.5) ) DISCRETE_CUSTOM7(NODE_12, NODE_10, NODE_11, NODE_11, MR_C6, MR_C17, MR_MIXER_RPAR, MR_C31, &mario_custom_run_info) DISCRETE_MULTIPLY(DS_OUT_SOUND0, 1, NODE_12, MR_MIXER_RPAR / MR_R20) /************************************************/ /* SOUND1 */ /************************************************/ DISCRETE_LS123(NODE_20, DS_SOUND1_INV, MR_R18, CAP_AGE(MR_C15, 0.7)) DISCRETE_RCFILTER(NODE_21, 1, NODE_20, MR_R7, CAP_AGE(MR_C4, 0.5) ) DISCRETE_CUSTOM7(NODE_22, NODE_20, NODE_21, NODE_21, MR_C5, MR_C16, MR_MIXER_RPAR, MR_C31, &mario_custom_run_info) DISCRETE_MULTIPLY(DS_OUT_SOUND1, 1, NODE_22, MR_MIXER_RPAR / MR_R19) /************************************************/ /* SOUND7 */ /************************************************/ DISCRETE_COUNTER(NODE_100,1,0,NODE_118,0xFFFF,DISC_COUNT_UP,0,DISC_CLK_BY_COUNT) DISCRETE_BITSET(NODE_102, NODE_100, 4) //LS157 2B DISCRETE_BITSET(NODE_104, NODE_100, 12) //LS157 3B DISCRETE_LS123(NODE_110, DS_SOUND7_INV, MR_R61, CAP_AGE(MR_C41, 0.6)) DISCRETE_TRANSFORM2(NODE_111, NODE_110, TTL_HIGH, "0!1*") DISCRETE_RCFILTER(NODE_112, 1, NODE_111, MR_R65, MR_C44) DISCRETE_74LS624(NODE_113, 1, NODE_112, VSS, MR_C40, DISC_LS624_OUT_LOGIC) DISCRETE_LOGIC_XOR(NODE_115, 1, NODE_102, NODE_113) DISCRETE_TRANSFORM2(NODE_116, NODE_104, TTL_HIGH, "0!1*") DISCRETE_RCFILTER(NODE_117, 1, NODE_116, MR_R64, MR_C43) DISCRETE_74LS624(NODE_118, 1, NODE_117, VSS, MR_C39, DISC_LS624_OUT_COUNT_F) DISCRETE_LOGIC_AND(NODE_120, 1, NODE_115, NODE_110) DISCRETE_MULTIPLY(NODE_121, 1, NODE_120, TTL_HIGH * MR_MIXER_RPAR / MR_R41) DISCRETE_RCFILTER(DS_OUT_SOUND7, 1, NODE_121, MR_MIXER_RPAR, MR_C31) /************************************************/ /* DAC */ /************************************************/ /* following the resistor DAC are two opamps. The first is a 1:1 amplifier, the second * is a filter circuit. Simulation in LTSPICE shows, that the following is equivalent: */ DISCRETE_MULTIPLY(NODE_170, 1, DS_DAC, TTL_HIGH/256.0) DISCRETE_RCFILTER(NODE_171, 1, NODE_170, RES_K(750), CAP_P(200)) DISCRETE_MULTIPLY(NODE_172, 1, NODE_171, MR_MIXER_RPAR / MR_R40) DISCRETE_RCFILTER(DS_OUT_DAC, 1, NODE_172, MR_MIXER_RPAR, MR_C31) /************************************************/ /* MIXER */ /************************************************/ DISCRETE_ADDER4(NODE_295, 1, DS_OUT_SOUND0, DS_OUT_SOUND1, DS_OUT_SOUND7, DS_OUT_DAC) /* Amplifier: internal amplifier * Just a 1:n amplifier without filters and no output capacitor */ DISCRETE_CRFILTER(NODE_296, 1, NODE_295, RES_2_PARALLEL(MR_R42, MR_R43), MR_C32) /* EZV20 (Monitor) ouput capacitor / Speaker */ DISCRETE_CRFILTER(NODE_297, 1, NODE_296, 6, CAP_U(22)) DISCRETE_OUTPUT(NODE_297, 32767.0/5.0 * 10) //DISCRETE_WAVELOG1(DS_OUT_SOUND0, 32767/5.0) //DISCRETE_WAVELOG2(NODE_296, 32767/5.0 * 2, DS_SOUND7_INV, 10000) DISCRETE_SOUND_END /**************************************************************** * * EA / Banking * ****************************************************************/ static void set_ea(const address_space *space, int ea) { mario_state *state = space->machine->driver_data; //printf("ea: %d\n", ea); //cputag_set_input_line(machine, "audio", MCS48_INPUT_EA, (ea) ? ASSERT_LINE : CLEAR_LINE); if (state->eabank != 0) memory_set_bank(space->machine, state->eabank, ea); } /**************************************************************** * * Initialization * ****************************************************************/ static SOUND_START( mario ) { mario_state *state = machine->driver_data; const device_config *audiocpu = cputag_get_cpu(machine, "audio"); #if USE_8039 UINT8 *SND = memory_region(machine, "audio"); SND[0x1001] = 0x01; #endif state->eabank = 0; if (audiocpu != NULL && cpu_get_type(audiocpu) != CPU_Z80) { state->eabank = 1; memory_install_read8_handler(cpu_get_address_space(audiocpu, ADDRESS_SPACE_PROGRAM), 0x000, 0x7ff, 0, 0, SMH_BANK1); memory_configure_bank(machine, 1, 0, 1, memory_region(machine, "audio"), 0); memory_configure_bank(machine, 1, 1, 1, memory_region(machine, "audio") + 0x1000, 0x800); } state_save_register_global(machine, state->last); state_save_register_global(machine, state->portT); } static SOUND_RESET( mario ) { mario_state *state = machine->driver_data; const address_space *space = cpu_get_address_space(machine->cpu[1], ADDRESS_SPACE_PROGRAM); #if USE_8039 set_ea(machine, 1); #endif /* FIXME: convert to latch8 */ soundlatch_clear_w(space,0,0); soundlatch2_clear_w(space,0,0); soundlatch3_clear_w(space,0,0); soundlatch4_clear_w(space,0,0); I8035_P1_W(space,0x00); /* Input port */ I8035_P2_W(space,0xff); /* Port is in high impedance state after reset */ state->last = 0; } /**************************************************************** * * I/O Handlers - static * ****************************************************************/ static READ8_HANDLER( mario_sh_p1_r ) { return I8035_P1_R(space); } static READ8_HANDLER( mario_sh_p2_r ) { return I8035_P2_R(space) & 0xEF; /* Bit 4 connected to GND! */ } static READ8_HANDLER( mario_sh_t0_r ) { return I8035_T_R(space,0); } static READ8_HANDLER( mario_sh_t1_r ) { return I8035_T_R(space,1); } static READ8_HANDLER( mario_sh_tune_r ) { UINT8 *SND = memory_region(space->machine, "audio"); UINT16 mask = memory_region_length(space->machine, "audio")-1; UINT8 p2 = I8035_P2_R(space); if ((p2 >> 7) & 1) return soundlatch_r(space,offset); else return (SND[(0x1000 + (p2 & 0x0f)*256+offset) & mask]); } static WRITE8_DEVICE_HANDLER( mario_sh_sound_w ) { discrete_sound_w(device,DS_DAC,data); } static WRITE8_HANDLER( mario_sh_p1_w ) { I8035_P1_W(space,data); } static WRITE8_HANDLER( mario_sh_p2_w ) { I8035_P2_W(space,data); } /**************************************************************** * * I/O Handlers - global * ****************************************************************/ WRITE8_HANDLER( masao_sh_irqtrigger_w ) { mario_state *state = space->machine->driver_data; if (state->last == 1 && data == 0) { /* setting bit 0 high then low triggers IRQ on the sound CPU */ cputag_set_input_line_and_vector(space->machine, "audio",0,HOLD_LINE,0xff); } state->last = data; } WRITE8_HANDLER( mario_sh_tuneselect_w ) { soundlatch_w(space,offset,data); } /* Sound 0 and 1 are pulsed !*/ /* Mario running sample */ WRITE8_DEVICE_HANDLER( mario_sh1_w ) { discrete_sound_w(device,DS_SOUND0_INP, 0); } /* Luigi running sample */ WRITE8_DEVICE_HANDLER( mario_sh2_w ) { discrete_sound_w(device,DS_SOUND1_INP, 0); } /* Misc samples */ WRITE8_HANDLER( mario_sh3_w ) { mario_state *state = space->machine->driver_data; switch (offset) { case 0: /* death */ if (data) cputag_set_input_line(space->machine, "audio",0,ASSERT_LINE); else cputag_set_input_line(space->machine, "audio",0,CLEAR_LINE); break; case 1: /* get coin */ I8035_T_W_AH(space,0,data & 1); break; case 2: /* ice */ I8035_T_W_AH(space,1,data & 1); break; case 3: /* crab */ I8035_P1_W_AH(space,0,data & 1); break; case 4: /* turtle */ I8035_P1_W_AH(space,1,data & 1); break; case 5: /* fly */ I8035_P1_W_AH(space,2,data & 1); break; case 6: /* coin */ I8035_P1_W_AH(space,3,data & 1); break; case 7: /* skid */ discrete_sound_w(devtag_get_device(space->machine, SOUND, "discrete"),DS_SOUND7_INP,data & 1); break; } } /************************************* * * Sound CPU memory handlers * *************************************/ static ADDRESS_MAP_START( mario_sound_map, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x07ff) AM_ROMBANK(1) AM_REGION("audio", 0) AM_RANGE(0x0800, 0x0fff) AM_ROM ADDRESS_MAP_END static ADDRESS_MAP_START( mario_sound_io_map, ADDRESS_SPACE_IO, 8 ) AM_RANGE(0x00, 0xff) AM_READ(mario_sh_tune_r) AM_DEVWRITE(SOUND, "discrete", mario_sh_sound_w) AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(mario_sh_p1_r, mario_sh_p1_w) AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(mario_sh_p2_r, mario_sh_p2_w) AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(mario_sh_t0_r) AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(mario_sh_t1_r) ADDRESS_MAP_END static ADDRESS_MAP_START( masao_sound_map, ADDRESS_SPACE_PROGRAM, 8 ) AM_RANGE(0x0000, 0x0fff) AM_ROM AM_RANGE(0x2000, 0x23ff) AM_RAM AM_RANGE(0x4000, 0x4000) AM_DEVREADWRITE(SOUND, "ay", ay8910_r, ay8910_data_w) AM_RANGE(0x6000, 0x6000) AM_DEVWRITE(SOUND, "ay", ay8910_address_w) ADDRESS_MAP_END /************************************* * * Sound Interfaces * *************************************/ static const ay8910_interface ay8910_config = { AY8910_LEGACY_OUTPUT, AY8910_DEFAULT_LOADS, DEVCB_MEMORY_HANDLER("audio", PROGRAM, soundlatch_r), DEVCB_NULL, DEVCB_NULL, DEVCB_NULL }; /************************************* * * Machine driver * *************************************/ MACHINE_DRIVER_START( mario_audio ) #if USE_8039 MDRV_CPU_ADD("audio", I8039, I8035_CLOCK) /* 730 kHz */ #else MDRV_CPU_ADD("audio", M58715, I8035_CLOCK) /* 730 kHz */ #endif MDRV_CPU_PROGRAM_MAP(mario_sound_map, 0) MDRV_CPU_IO_MAP(mario_sound_io_map, 0) MDRV_SOUND_START(mario) MDRV_SOUND_RESET(mario) MDRV_SPEAKER_STANDARD_MONO("mono") MDRV_SOUND_ADD("discrete", DISCRETE, 0) MDRV_SOUND_CONFIG_DISCRETE(mario) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.5) MACHINE_DRIVER_END MACHINE_DRIVER_START( masao_audio ) MDRV_CPU_ADD("audio", Z80,24576000/16) /* ???? */ MDRV_CPU_PROGRAM_MAP(masao_sound_map,0) MDRV_SOUND_START(mario) MDRV_SOUND_RESET(mario) MDRV_SPEAKER_STANDARD_MONO("mono") MDRV_SOUND_ADD("ay", AY8910, 14318000/6) MDRV_SOUND_CONFIG(ay8910_config) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) MACHINE_DRIVER_END