summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2019-07-30 14:37:00 +0200
committer Dirk Best <mail@dirk-best.de>2019-07-30 17:02:04 +0200
commitc6b4027e4313484a8551b7e9802aceacf84224a2 (patch)
tree085e108cb7f7321ec6aaeee671725a75f6368a00
parent962f30ccd45d8aa40ff327b1d0aade959fc9a87b (diff)
bionicc: More cleanups
- Clean up notes, add TODO - Use pulse_input_line for NMI - Document coin lockout - Document attribute RAM layout - Background layer color is actually 3 bits
-rw-r--r--scripts/target/mame/arcade.lua2
-rw-r--r--src/mame/drivers/bionicc.cpp594
-rw-r--r--src/mame/includes/bionicc.h96
-rw-r--r--src/mame/video/bionicc.cpp200
4 files changed, 429 insertions, 463 deletions
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index aff892df782..1ff1cd9bc1c 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -1430,8 +1430,6 @@ files {
MAME_DIR .. "src/mame/video/1943.cpp",
MAME_DIR .. "src/mame/drivers/alien.cpp",
MAME_DIR .. "src/mame/drivers/bionicc.cpp",
- MAME_DIR .. "src/mame/includes/bionicc.h",
- MAME_DIR .. "src/mame/video/bionicc.cpp",
MAME_DIR .. "src/mame/drivers/supduck.cpp",
MAME_DIR .. "src/mame/video/tigeroad_spr.cpp",
MAME_DIR .. "src/mame/video/tigeroad_spr.h",
diff --git a/src/mame/drivers/bionicc.cpp b/src/mame/drivers/bionicc.cpp
index f490955cef9..596106b8f85 100644
--- a/src/mame/drivers/bionicc.cpp
+++ b/src/mame/drivers/bionicc.cpp
@@ -1,12 +1,14 @@
// license:BSD-3-Clause
-// copyright-holders:Phil Stroffolino, Paul Leaman
+// copyright-holders:Phil Stroffolino, Paul Leaman, Dirk Best
// thanks-to: Steven Frew (the author of Slutte)
-/******************************************************************************************
+/***************************************************************************
Bionic Commando
+ © 1987 Capcom
+
+ Hardware:
- PCB is a 3 board stack:
Main CPU board: 86612-A-2
Graphics ROM board: 86612-B-2
Program ROM board: 86612-C-2
@@ -18,6 +20,8 @@
OSC: 24.000 MHz (on the 86612-B-2 PCB)
Custom: CAPCOM DL-010D-103 (on the 86612-B-2 PCB)
+ Video timings:
+
Horizontal scan rate: 15.606kHz
Vertical scan rate: 60.024Hz
@@ -26,7 +30,7 @@
htotal: 64.076us, 386 pixels
hsync: 5.312us, 32 pixels
back porch + sync: 15.106us, 91 pixels
- active video: 42.662us, 257 pixels (it looks like the first pixel is repeated)
+ active video: 42.662us, 257 pixels (first pixel is repeated?)
front porch: 6.308us, 38 pixels
vtotal: 16.660ms, 260 lines
@@ -40,150 +44,141 @@
Timings verified at SYNC pin and BLUE pin (jamma edge),
using an Agilent DSO9404A scope and two N2873A 500MHz probes
- Note: Protection MCU is labelled "TS" without a number and without a coloured
- stripe. Maybe its code is not region dependant.
- Note: Euro rom labels (IE: "TSE") had a blue stripe, while those labeled
- as USA (TSU) had an red stripe on the sticker. The intermixing
- of TSE and TSU roms in the parent set is correct and verified.
- Note: Euro set simply states the game cannot be operated in Japan....
- Note: These issues have been verified on a real PCB and are not emulation bugs:
- - misplaced sprites ( see beginning of level 1 or 2 for example )
- - sprite / sprite priority ( see level 2 the reflectors )
- - sprite / background priority ( see level 1: birds walk through
- branches of different trees )
- - see the beginning of level 3: background screwed
- - gray tiles around the title in Top Secret
-
- Note: The MCU rom contains the string
- "<for dealer-location test & USA show. 87/03/10 >"
- which indicates it could be from an earlier version, especially with it
- coming from a 'Top Secret' bootleg with identical program but unprotected
- MCU, however f1dream has a similar string, and is verified as being from
- a production board.
-
- ToDo:
- - Proper IRQ2 (should be LVBL) and IRQ4 (V256) hookup
-
- About IRQ:
- IRQ4 seems to be control related.
- On each interrupt, it reads 0xFE4000 (coin/start), shift the bits around
- and move the resulting byte into a dword RAM location. The dword RAM location
- is rotated by 8 bits each time this happens.
- This is probably done to be pedantic about coin insertions (might be protection
- related).
-
-******************************************************************************************/
+ BTANB [MT00209] (verified on real PCB):
+ - misplaced sprites (see beginning of level 1 or 2 for example)
+ - sprite / sprite priority (see level 2 the reflectors)
+ - sprite / background priority (see level 1: birds walk through
+ branches of different trees)
+ - see the beginning of level 3: background screwed
+ - gray tiles around the title in Top Secret
+
+ Notes:
+ - Protection MCU is labelled "TS" without a number and without a coloured.
+ Maybe its code is not region dependant.
+ - The MCU rom contains the string
+ "<for dealer-location test & USA show. 87/03/10 >"
+ which indicates it could be from an earlier version, especially with it
+ coming from a 'Top Secret' bootleg with identical program but unprotected
+ MCU, however f1dream has a similar string, and is verified as being from
+ a production board.
+ - Euro rom labels (IE: "TSE") had a blue stripe, while those labeled
+ as USA (TSU) had an red stripe on the sticker. The intermixing
+ of TSE and TSU roms in the parent set is correct and verified.
+ - Euro set simply states the game cannot be operated in Japan.
+ - IRQ 4 is control related. On each interrupt, it reads 0xFE4000
+ (coin/start), shift the bits around and move the resulting byte into a
+ dword RAM location. The dword RAM location is rotated by 8 bits each time
+ this happens. This is probably done to be pedantic about coin insertions
+ (might be protection related).
+
+ TODO:
+ - Firing IRQ4 at line 16 causes the game to often miss coin inserts. Set
+ to 128 currently to compensate.
+ - The game doesn't set the coin lockout in service mode, so the coin inputs
+ can't be tested there if you uncomment and enable it.
+
+***************************************************************************/
#include "emu.h"
-#include "includes/bionicc.h"
-#include "cpu/z80/z80.h"
#include "cpu/m68000/m68000.h"
+#include "cpu/mcs51/mcs51.h"
+#include "cpu/z80/z80.h"
+#include "machine/timer.h"
+#include "video/bufsprite.h"
+#include "video/tigeroad_spr.h"
#include "sound/ym2151.h"
+#include "emupal.h"
#include "screen.h"
#include "speaker.h"
//**************************************************************************
-// PROTECTION MCU
+// TYPE DEFINITIONS
//**************************************************************************
-u8 bionicc_state::mcu_dma_r(offs_t offset)
+class bionicc_state : public driver_device
{
- u8 data = 0xff;
-
- if (BIT(m_mcu_p3, 5) == 0)
- {
- // various address bits are pulled high because the mcu doesn't drive them
- // the 3 upper address bits (p2.0, p2.1, p2.2) are connected to a14 to a16
- offs_t address = 0xe3e01 | ((offset & 0x700) << 6) | ((offset & 0xff) << 1);
- data = m_maincpu->space(AS_PROGRAM).read_byte(address);
- }
-
- return data;
-}
-
-void bionicc_state::mcu_dma_w(offs_t offset, u8 data)
-{
- if (BIT(m_mcu_p3, 5) == 0)
- {
- offs_t address = 0xe3e01 | ((offset & 0x700) << 6) | ((offset & 0xff) << 1);
- m_maincpu->space(AS_PROGRAM).write_byte(address, data);
- }
-}
-
-void bionicc_state::mcu_p3_w(u8 data)
-{
- // 7------- read strobe
- // -6------ write strobe
- // --5----- dma
- // ---4---- int1 ack
- // ----3--- int1
- // -----2-- int0
- // ------1- int0 flip-flop preset
- // -------0 int0 ack
-
- if (BIT(m_mcu_p3, 0) == 1 && BIT(data, 0) == 0)
- {
- m_mcu->set_input_line(MCS51_INT0_LINE, CLEAR_LINE);
- m_maincpu->resume(SUSPEND_REASON_HALT);
- }
-
- if (BIT(m_mcu_p3, 4) == 1 && BIT(data, 4) == 0)
- m_mcu->set_input_line(MCS51_INT1_LINE, CLEAR_LINE);
-
- if (BIT(m_mcu_p3, 6) == 1 && BIT(data, 6) == 0)
- m_mcu_to_audiocpu = m_mcu_p1;
-
- m_mcu_p3 = data;
-}
-
-void bionicc_state::dmaon_w(u16 data)
-{
- m_mcu->set_input_line(MCS51_INT0_LINE, ASSERT_LINE);
- m_maincpu->suspend(SUSPEND_REASON_HALT, true);
-}
+public:
+ bionicc_state(const machine_config &mconfig, device_type type, const char *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_audiocpu(*this, "audiocpu"),
+ m_mcu(*this, "mcu"),
+ m_gfxdecode(*this, "gfxdecode"),
+ m_palette(*this, "palette"),
+ m_spritegen(*this, "spritegen"),
+ m_spriteram(*this, "spriteram") ,
+ m_txvideoram(*this, "txvideoram"),
+ m_fgvideoram(*this, "fgvideoram"),
+ m_bgvideoram(*this, "bgvideoram"),
+ m_mcu_p3(0xff)
+ { }
+
+ void bionicc(machine_config &config);
+
+protected:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ virtual void video_start() override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+ required_device<cpu_device> m_audiocpu;
+ required_device<i8751_device> m_mcu;
+ required_device<gfxdecode_device> m_gfxdecode;
+ required_device<palette_device> m_palette;
+ required_device<tigeroad_spr_device> m_spritegen;
+ required_device<buffered_spriteram16_device> m_spriteram;
+
+ required_shared_ptr<uint16_t> m_txvideoram;
+ required_shared_ptr<uint16_t> m_fgvideoram;
+ required_shared_ptr<uint16_t> m_bgvideoram;
+
+ void main_map(address_map &map);
+ void sound_map(address_map &map);
+ void mcu_io(address_map &map);
+
+ void output_w(u8 data);
+
+ // video
+ TILE_GET_INFO_MEMBER(get_bg_tile_info);
+ TILE_GET_INFO_MEMBER(get_fg_tile_info);
+ TILE_GET_INFO_MEMBER(get_tx_tile_info);
+ static rgb_t RRRRGGGGBBBBIIII(uint32_t raw);
+ uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
+ TIMER_DEVICE_CALLBACK_MEMBER(scanline);
+
+ DECLARE_WRITE16_MEMBER(bgvideoram_w);
+ DECLARE_WRITE16_MEMBER(fgvideoram_w);
+ DECLARE_WRITE16_MEMBER(txvideoram_w);
+ DECLARE_WRITE16_MEMBER(scroll_w);
+
+ tilemap_t *m_tx_tilemap;
+ tilemap_t *m_bg_tilemap;
+ tilemap_t *m_fg_tilemap;
+ uint16_t m_scroll[4];
+
+ // audio
+ void audiocpu_nmi_w(u8 data);
+
+ // protection mcu
+ u8 m_audiocpu_to_mcu; // ls374 at 4a
+ u8 m_mcu_to_audiocpu; // ls374 at 5a
+ u8 m_mcu_p1;
+ u8 m_mcu_p3;
+
+ void dmaon_w(u16 data);
+ u8 mcu_dma_r(offs_t offset);
+ void mcu_dma_w(offs_t offset, u8 data);
+ void mcu_p3_w(u8 data);
+};
//**************************************************************************
-// AUDIO
+// ADDRESS MAPS
//**************************************************************************
-void bionicc_state::audiocpu_nmi_w(u8 data)
-{
- m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
- m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
-}
-
-
-/********************************************************************
-
- Interrupt
-
- The game runs on 2 interrupts.
-
- IRQ 2 drives the game
- IRQ 4 processes the input ports
-
-********************************************************************/
-
-TIMER_DEVICE_CALLBACK_MEMBER(bionicc_state::scanline)
-{
- int scanline = param;
-
- if(scanline == 240) // vblank-out irq
- m_maincpu->set_input_line(2, HOLD_LINE);
-
- if(scanline == 128) // vblank-in irq (can't happen when the CPU is suspended)
- m_maincpu->set_input_line(4, HOLD_LINE);
-}
-
-/*************************************
- *
- * Address maps
- *
- *************************************/
-
void bionicc_state::main_map(address_map &map)
{
map.global_mask(0xfffff);
@@ -191,9 +186,10 @@ void bionicc_state::main_map(address_map &map)
map(0xe0000, 0xe07ff).ram(); /* RAM? */
map(0xe0800, 0xe0cff).ram().share("spriteram");
map(0xe0d00, 0xe3fff).ram(); /* RAM? */
+ map(0xe4000, 0xe4000).mirror(0x3ffc).w(FUNC(bionicc_state::output_w));
map(0xe4000, 0xe4001).mirror(0x3ffc).portr("INPUTS");
- map(0xe4000, 0xe4001).mirror(0x3ffc).w(FUNC(bionicc_state::gfxctrl_w)); /* + coin counters */
- map(0xe4002, 0xe4003).mirror(0x3ffc).portr("DSW").w(FUNC(bionicc_state::audiocpu_nmi_w));
+ map(0xe4002, 0xe4002).mirror(0x3ffc).w(FUNC(bionicc_state::audiocpu_nmi_w));
+ map(0xe4002, 0xe4003).mirror(0x3ffc).portr("DSW");
map(0xe8010, 0xe8017).w(FUNC(bionicc_state::scroll_w));
map(0xe8018, 0xe8019).nopw(); // vblank irq ack?
map(0xe801a, 0xe801b).w(FUNC(bionicc_state::dmaon_w));
@@ -219,11 +215,9 @@ void bionicc_state::mcu_io(address_map &map)
}
-/*************************************
- *
- * Input ports
- *
- *************************************/
+//**************************************************************************
+// INPUT PORT DEFINITIONS
+//**************************************************************************
static INPUT_PORTS_START( bionicc )
PORT_START("INPUTS")
@@ -291,11 +285,127 @@ static INPUT_PORTS_START( bionicc )
INPUT_PORTS_END
-/*************************************
- *
- * Graphics definitions
- *
- *************************************/
+//**************************************************************************
+// PALETTE
+//**************************************************************************
+
+rgb_t bionicc_state::RRRRGGGGBBBBIIII(uint32_t raw)
+{
+ uint8_t bright = (raw & 0x0f);
+
+ uint8_t r = ((raw >> 12) & 0x0f) * 0x11;
+ uint8_t g = ((raw >> 8) & 0x0f) * 0x11;
+ uint8_t b = ((raw >> 4) & 0x0f) * 0x11;
+
+ if ((bright & 0x08) == 0)
+ {
+ r = r * (0x07 + bright) / 0x0e;
+ g = g * (0x07 + bright) / 0x0e;
+ b = b * (0x07 + bright) / 0x0e;
+ }
+
+ return rgb_t(r, g, b);
+}
+
+
+//**************************************************************************
+// VIDEO EMULATION
+//**************************************************************************
+
+/*
+
+ This board handles tile/tile and tile/sprite priority with a PROM. Its
+ working is complicated and hardcoded in the driver.
+
+ The PROM is a 256x4 chip, with address inputs wired as follows:
+
+ A0 bg opaque
+ A1 \
+ A2 | fg pen
+ A3 |
+ A4 /
+ A5 fg has priority over sprites (bit 5 of tile attribute)
+ A6 fg has not priority over bg (bits 6 & 7 of tile attribute both set)
+ A7 sprite opaque
+
+ The output selects the active layer, it can be:
+ 0 bg
+ 1 fg
+ 2 sprite
+
+*/
+
+WRITE16_MEMBER(bionicc_state::bgvideoram_w)
+{
+ COMBINE_DATA(&m_bgvideoram[offset]);
+ m_bg_tilemap->mark_tile_dirty(offset / 2);
+}
+
+WRITE16_MEMBER(bionicc_state::fgvideoram_w)
+{
+ COMBINE_DATA(&m_fgvideoram[offset]);
+ m_fg_tilemap->mark_tile_dirty(offset / 2);
+}
+
+WRITE16_MEMBER(bionicc_state::txvideoram_w)
+{
+ COMBINE_DATA(&m_txvideoram[offset]);
+ m_tx_tilemap->mark_tile_dirty(offset & 0x3ff);
+}
+
+WRITE16_MEMBER(bionicc_state::scroll_w)
+{
+ data = COMBINE_DATA(&m_scroll[offset]);
+
+ switch (offset)
+ {
+ case 0:
+ m_fg_tilemap->set_scrollx(0, data);
+ break;
+ case 1:
+ m_fg_tilemap->set_scrolly(0, data);
+ break;
+ case 2:
+ m_bg_tilemap->set_scrollx(0, data);
+ break;
+ case 3:
+ m_bg_tilemap->set_scrolly(0, data);
+ break;
+ }
+}
+
+u32 bionicc_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
+{
+ bitmap.fill(m_palette->black_pen(), cliprect);
+
+ m_fg_tilemap->draw(screen, bitmap, cliprect, 1 | TILEMAP_DRAW_LAYER1, 0); /* nothing in FRONT */
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+ m_fg_tilemap->draw(screen, bitmap, cliprect, 0 | TILEMAP_DRAW_LAYER1, 0);
+ m_spritegen->draw_sprites(bitmap, cliprect, m_spriteram->buffer(), m_spriteram->bytes(), flip_screen(), false);
+ m_fg_tilemap->draw(screen, bitmap, cliprect, 0 | TILEMAP_DRAW_LAYER0, 0);
+
+ // text layer last
+ m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+
+ return 0;
+}
+
+void bionicc_state::video_start()
+{
+ m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(bionicc_state::get_tx_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
+ m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(bionicc_state::get_fg_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 64, 64);
+ m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(bionicc_state::get_bg_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
+
+ m_tx_tilemap->set_transparent_pen(3);
+ m_fg_tilemap->set_transmask(0, 0xffff, 0x8000); /* split type 0 is completely transparent in front half */
+ m_fg_tilemap->set_transmask(1, 0xffc1, 0x803e); /* split type 1 has pens 1-5 opaque in front half */
+ m_bg_tilemap->set_transparent_pen(15);
+}
+
+
+//**************************************************************************
+// DRAWGFX LAYOUTS
+//**************************************************************************
static const gfx_layout vramlayout=
{
@@ -332,16 +442,168 @@ static const gfx_layout scroll1layout=
static GFXDECODE_START( gfx_bionicc )
GFXDECODE_ENTRY( "gfx1", 0, vramlayout, 768, 64 ) /* colors 768-1023 */
- GFXDECODE_ENTRY( "gfx2", 0, scroll2layout, 0, 4 ) /* colors 0- 63 */
+ GFXDECODE_ENTRY( "gfx2", 0, scroll2layout, 0, 8 ) /* colors 0- 127 */
GFXDECODE_ENTRY( "gfx3", 0, scroll1layout, 256, 4 ) /* colors 256- 319 */
GFXDECODE_END
+TILE_GET_INFO_MEMBER(bionicc_state::get_tx_tile_info)
+{
+ // 76------ tile code high bits
+ // --543210 color
+
+ int attr = m_txvideoram[tile_index + 0x400];
+ int code = m_txvideoram[tile_index] & 0xff;
+
+ SET_TILE_INFO_MEMBER(0, ((attr & 0xc0) << 2) | code, attr & 0x3f, 0);
+}
+
+TILE_GET_INFO_MEMBER(bionicc_state::get_fg_tile_info)
+{
+ // 7------- tile flip x
+ // -6------ tile flip y
+ // --5----- layer
+ // ---43--- color
+ // -----210 tile code high bits
+
+ int attr = m_fgvideoram[2 * tile_index + 1];
+ int code = m_fgvideoram[2 * tile_index] & 0xff;
+ int flag = 0;
+
+ if ((attr & 0xc0) == 0xc0)
+ {
+ // drawn to the background if both flip bits are set
+ tileinfo.category = 1;
+ tileinfo.group = 0;
+ }
+ else
+ {
+ tileinfo.category = 0;
+ tileinfo.group = (attr & 0x20) >> 5;
+ flag = TILE_FLIPXY((attr & 0xc0) >> 6);
+ }
+
+ SET_TILE_INFO_MEMBER(2, ((attr & 0x07) << 8) | code, (attr & 0x18) >> 3, flag);
+}
+
+TILE_GET_INFO_MEMBER(bionicc_state::get_bg_tile_info)
+{
+ // 7------- tile flip x
+ // -6------ tile flip y
+ // --543--- color
+ // -----210 tile code high bits
+
+ int attr = m_bgvideoram[2 * tile_index + 1];
+ int code = m_bgvideoram[2 * tile_index] & 0xff;
+ int flag = TILE_FLIPXY((attr & 0xc0) >> 6);
+
+ SET_TILE_INFO_MEMBER(1, ((attr & 0x07) << 8) | code, (attr & 0x38) >> 3, flag);
+}
+
+
+//**************************************************************************
+// PROTECTION MCU
+//**************************************************************************
+
+u8 bionicc_state::mcu_dma_r(offs_t offset)
+{
+ u8 data = 0xff;
+
+ if (BIT(m_mcu_p3, 5) == 0)
+ {
+ // various address bits are pulled high because the mcu doesn't drive them
+ // the 3 upper address bits (p2.0, p2.1, p2.2) are connected to a14 to a16
+ offs_t address = 0xe3e01 | ((offset & 0x700) << 6) | ((offset & 0xff) << 1);
+ data = m_maincpu->space(AS_PROGRAM).read_byte(address);
+ }
+
+ return data;
+}
+
+void bionicc_state::mcu_dma_w(offs_t offset, u8 data)
+{
+ if (BIT(m_mcu_p3, 5) == 0)
+ {
+ offs_t address = 0xe3e01 | ((offset & 0x700) << 6) | ((offset & 0xff) << 1);
+ m_maincpu->space(AS_PROGRAM).write_byte(address, data);
+ }
+}
+
+void bionicc_state::mcu_p3_w(u8 data)
+{
+ // 7------- read strobe
+ // -6------ write strobe
+ // --5----- dma
+ // ---4---- int1 ack
+ // ----3--- int1
+ // -----2-- int0
+ // ------1- int0 flip-flop preset
+ // -------0 int0 ack
+
+ if (BIT(m_mcu_p3, 0) == 1 && BIT(data, 0) == 0)
+ {
+ m_mcu->set_input_line(MCS51_INT0_LINE, CLEAR_LINE);
+ m_maincpu->resume(SUSPEND_REASON_HALT);
+ }
+
+ if (BIT(m_mcu_p3, 4) == 1 && BIT(data, 4) == 0)
+ m_mcu->set_input_line(MCS51_INT1_LINE, CLEAR_LINE);
+
+ if (BIT(m_mcu_p3, 6) == 1 && BIT(data, 6) == 0)
+ m_mcu_to_audiocpu = m_mcu_p1;
+
+ m_mcu_p3 = data;
+}
+
+void bionicc_state::dmaon_w(u16 data)
+{
+ m_mcu->set_input_line(MCS51_INT0_LINE, ASSERT_LINE);
+ m_maincpu->suspend(SUSPEND_REASON_HALT, true);
+}
+
-/*************************************
- *
- * Machine driver
- *
- *************************************/
+//**************************************************************************
+// AUDIO
+//**************************************************************************
+
+void bionicc_state::audiocpu_nmi_w(u8 data)
+{
+ m_audiocpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
+}
+
+
+//**************************************************************************
+// MACHINE EMULATION
+//**************************************************************************
+
+void bionicc_state::output_w(u8 data)
+{
+ // 7------- coin counter 1
+ // -6------ coin counter 2
+ // --5----- coin lockout 1
+ // ---4---- coin lockout 2
+ // ----321- unused
+ // -------0 flip screen
+
+ flip_screen_set(BIT(data, 0));
+
+ // commented out, else you can't test the coin inputs in service mode
+// machine().bookkeeping().coin_lockout_w(1, BIT(~data, 4));
+// machine().bookkeeping().coin_lockout_w(0, BIT(~data, 5));
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 6));
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 7));
+}
+
+TIMER_DEVICE_CALLBACK_MEMBER(bionicc_state::scanline)
+{
+ // vblank-out irq - drives the game (V256)
+ if (param == 256)
+ m_maincpu->set_input_line(2, HOLD_LINE);
+
+ // vblank-in irq - processes inputs (!LVBL)
+ // should be 16? but then often loses coin inserts
+ if (param == 128)
+ m_maincpu->set_input_line(4, HOLD_LINE);
+}
void bionicc_state::machine_start()
{
@@ -360,25 +622,31 @@ void bionicc_state::machine_reset()
m_scroll[3] = 0;
}
+
+//**************************************************************************
+// MACHINE DEFINITIONS
+//**************************************************************************
+
void bionicc_state::bionicc(machine_config &config)
{
- /* basic machine hardware */
- M68000(config, m_maincpu, 24_MHz_XTAL / 2); /* 12 MHz - verified in schematics */
+ // Main CPU 68000CP10 @ 12 MHz
+ M68000(config, m_maincpu, 24_MHz_XTAL / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &bionicc_state::main_map);
TIMER(config, "scantimer").configure_scanline(FUNC(bionicc_state::scanline), "screen", 0, 1);
- z80_device &audiocpu(Z80(config, "audiocpu", 14.318181_MHz_XTAL / 4)); /* EXO3 C,B=GND, A=5V ==> Divisor 2^2 */
- audiocpu.set_addrmap(AS_PROGRAM, &bionicc_state::sound_map);
+ // Audio CPU Z80 @ 3.579545 MHz (EXO3 C,B=GND, A=5V ==> Divisor 2^2)
+ Z80(config, m_audiocpu, 14.318181_MHz_XTAL / 4);
+ m_audiocpu->set_addrmap(AS_PROGRAM, &bionicc_state::sound_map);
- /* Protection MCU Intel C8751H-88 runs at 24MHz / 4 = 6MHz */
+ // Protection MCU Intel C8751H-88 @ 6 MHz
I8751(config, m_mcu, 24_MHz_XTAL / 4);
m_mcu->set_addrmap(AS_IO, &bionicc_state::mcu_io);
m_mcu->port_in_cb<1>().set([this](){ return m_audiocpu_to_mcu; });
m_mcu->port_out_cb<1>().set([this](u8 data){ m_mcu_p1 = data; });
m_mcu->port_out_cb<3>().set(FUNC(bionicc_state::mcu_p3_w));
- /* video hardware */
+ // video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
/* FIXME: should be 257 visible horizontal pixels, first visible pixel should be repeated, back porch/front porch should be separated */
screen.set_raw(24_MHz_XTAL / 4, 386, 0, 256, 260, 16, 240);
@@ -402,12 +670,9 @@ void bionicc_state::bionicc(machine_config &config)
}
-
-/*************************************
- *
- * ROM definition(s)
- *
- *************************************/
+//**************************************************************************
+// ROM DEFINITIONS
+//**************************************************************************
ROM_START( bionicc ) /* "Not for use in Japan" */
ROM_REGION( 0x40000, "maincpu", 0 ) /* 68000 code */
@@ -714,12 +979,11 @@ ROM_START( bioniccbl2 ) // only the 4 maincpu ROMs differ, they came from an ori
ROM_END
-/*************************************
- *
- * Game driver(s)
- *
- *************************************/
+//**************************************************************************
+// SYSTEM DRIVERS
+//**************************************************************************
+// YEAR NAME PARENT MACHINE INPUT CLASS INIT ROT COMPANY FULLNAME FLAGS
GAME( 1987, bionicc, 0, bionicc, bionicc, bionicc_state, empty_init, ROT0, "Capcom", "Bionic Commando (Euro)", MACHINE_SUPPORTS_SAVE )
GAME( 1987, bionicc1, bionicc, bionicc, bionicc, bionicc_state, empty_init, ROT0, "Capcom", "Bionic Commando (US set 1)", MACHINE_SUPPORTS_SAVE )
GAME( 1987, bionicc2, bionicc, bionicc, bionicc, bionicc_state, empty_init, ROT0, "Capcom", "Bionic Commando (US set 2)", MACHINE_SUPPORTS_SAVE )
diff --git a/src/mame/includes/bionicc.h b/src/mame/includes/bionicc.h
deleted file mode 100644
index 8cf91ea9cce..00000000000
--- a/src/mame/includes/bionicc.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Phil Stroffolino, Paul Leaman
-// thanks-to: Steven Frew (the author of Slutte)
-/***************************************************************************
-
- Bionic Commando
-
-***************************************************************************/
-#ifndef MAME_INCLUDES_BIONICC_H
-#define MAME_INCLUDES_BIONICC_H
-
-#pragma once
-
-#include "cpu/mcs51/mcs51.h"
-#include "machine/timer.h"
-#include "video/bufsprite.h"
-#include "video/tigeroad_spr.h"
-#include "emupal.h"
-
-class bionicc_state : public driver_device
-{
-public:
- bionicc_state(const machine_config &mconfig, device_type type, const char *tag) :
- driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_audiocpu(*this, "audiocpu"),
- m_mcu(*this, "mcu"),
- m_gfxdecode(*this, "gfxdecode"),
- m_palette(*this, "palette"),
- m_spritegen(*this, "spritegen"),
- m_spriteram(*this, "spriteram") ,
- m_txvideoram(*this, "txvideoram"),
- m_fgvideoram(*this, "fgvideoram"),
- m_bgvideoram(*this, "bgvideoram"),
- m_mcu_p3(0xff)
- { }
-
- void bionicc(machine_config &config);
-
-protected:
- virtual void machine_start() override;
- virtual void machine_reset() override;
- virtual void video_start() override;
-
-private:
- required_device<cpu_device> m_maincpu;
- required_device<cpu_device> m_audiocpu;
- required_device<i8751_device> m_mcu;
- required_device<gfxdecode_device> m_gfxdecode;
- required_device<palette_device> m_palette;
- required_device<tigeroad_spr_device> m_spritegen;
- required_device<buffered_spriteram16_device> m_spriteram;
-
- required_shared_ptr<uint16_t> m_txvideoram;
- required_shared_ptr<uint16_t> m_fgvideoram;
- required_shared_ptr<uint16_t> m_bgvideoram;
-
- void main_map(address_map &map);
- void sound_map(address_map &map);
- void mcu_io(address_map &map);
-
- // video
- TILE_GET_INFO_MEMBER(get_bg_tile_info);
- TILE_GET_INFO_MEMBER(get_fg_tile_info);
- TILE_GET_INFO_MEMBER(get_tx_tile_info);
- static rgb_t RRRRGGGGBBBBIIII(uint32_t raw);
- uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- TIMER_DEVICE_CALLBACK_MEMBER(scanline);
-
- DECLARE_WRITE16_MEMBER(bgvideoram_w);
- DECLARE_WRITE16_MEMBER(fgvideoram_w);
- DECLARE_WRITE16_MEMBER(txvideoram_w);
- DECLARE_WRITE16_MEMBER(scroll_w);
- DECLARE_WRITE16_MEMBER(gfxctrl_w);
-
- tilemap_t *m_tx_tilemap;
- tilemap_t *m_bg_tilemap;
- tilemap_t *m_fg_tilemap;
- uint16_t m_scroll[4];
-
- // audio
- void audiocpu_nmi_w(u8 data);
-
- // protection mcu
- u8 m_audiocpu_to_mcu; // ls374 at 4a
- u8 m_mcu_to_audiocpu; // ls374 at 5a
- u8 m_mcu_p1;
- u8 m_mcu_p3;
-
- void dmaon_w(u16 data);
- u8 mcu_dma_r(offs_t offset);
- void mcu_dma_w(offs_t offset, u8 data);
- void mcu_p3_w(u8 data);
-};
-
-#endif // MAME_INCLUDES_BIONICC_H
diff --git a/src/mame/video/bionicc.cpp b/src/mame/video/bionicc.cpp
deleted file mode 100644
index c78397128bd..00000000000
--- a/src/mame/video/bionicc.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Phil Stroffolino, Paul Leaman
-// thanks-to: Steven Frew (the author of Slutte)
-/***************************************************************************
-
- Bionic Commando Video Hardware
-
- This board handles tile/tile and tile/sprite priority with a PROM. Its
- working is complicated and hardcoded in the driver.
-
- The PROM is a 256x4 chip, with address inputs wired as follows:
-
- A0 bg opaque
- A1 \
- A2 | fg pen
- A3 |
- A4 /
- A5 fg has priority over sprites (bit 5 of tile attribute)
- A6 fg has not priority over bg (bits 6 & 7 of tile attribute both set)
- A7 sprite opaque
-
- The output selects the active layer, it can be:
- 0 bg
- 1 fg
- 2 sprite
-
-***************************************************************************/
-
-#include "emu.h"
-#include "includes/bionicc.h"
-
-
-/***************************************************************************
-
- Callbacks for the TileMap code
-
-***************************************************************************/
-
-TILE_GET_INFO_MEMBER(bionicc_state::get_bg_tile_info)
-{
- int attr = m_bgvideoram[2 * tile_index + 1];
- SET_TILE_INFO_MEMBER(1,
- (m_bgvideoram[2 * tile_index] & 0xff) + ((attr & 0x07) << 8),
- (attr & 0x18) >> 3,
- TILE_FLIPXY((attr & 0xc0) >> 6));
-}
-
-TILE_GET_INFO_MEMBER(bionicc_state::get_fg_tile_info)
-{
- int attr = m_fgvideoram[2 * tile_index + 1];
- int flags;
-
- if ((attr & 0xc0) == 0xc0)
- {
- tileinfo.category = 1;
- tileinfo.group = 0;
- flags = 0;
- }
- else
- {
- tileinfo.category = 0;
- tileinfo.group = (attr & 0x20) >> 5;
- flags = TILE_FLIPXY((attr & 0xc0) >> 6);
- }
-
- SET_TILE_INFO_MEMBER(2,
- (m_fgvideoram[2 * tile_index] & 0xff) + ((attr & 0x07) << 8),
- (attr & 0x18) >> 3,
- flags);
-}
-
-TILE_GET_INFO_MEMBER(bionicc_state::get_tx_tile_info)
-{
- int attr = m_txvideoram[tile_index + 0x400];
- SET_TILE_INFO_MEMBER(0,
- (m_txvideoram[tile_index] & 0xff) + ((attr & 0x00c0) << 2),
- attr & 0x3f,
- 0);
-}
-
-
-
-/***************************************************************************
-
- Start the video hardware emulation.
-
-***************************************************************************/
-
-void bionicc_state::video_start()
-{
- m_tx_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(bionicc_state::get_tx_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
- m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(bionicc_state::get_fg_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 64, 64);
- m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(bionicc_state::get_bg_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
-
- m_tx_tilemap->set_transparent_pen(3);
- m_fg_tilemap->set_transmask(0, 0xffff, 0x8000); /* split type 0 is completely transparent in front half */
- m_fg_tilemap->set_transmask(1, 0xffc1, 0x803e); /* split type 1 has pens 1-5 opaque in front half */
- m_bg_tilemap->set_transparent_pen(15);
-}
-
-rgb_t bionicc_state::RRRRGGGGBBBBIIII(uint32_t raw)
-{
- uint8_t bright = (raw & 0x0f);
-
- uint8_t r = ((raw >> 12) & 0x0f) * 0x11;
- uint8_t g = ((raw >> 8) & 0x0f) * 0x11;
- uint8_t b = ((raw >> 4) & 0x0f) * 0x11;
-
- if ((bright & 0x08) == 0)
- {
- r = r * (0x07 + bright) / 0x0e;
- g = g * (0x07 + bright) / 0x0e;
- b = b * (0x07 + bright) / 0x0e;
- }
-
- return rgb_t(r, g, b);
-}
-
-
-
-/***************************************************************************
-
- Memory handlers
-
-***************************************************************************/
-
-WRITE16_MEMBER(bionicc_state::bgvideoram_w)
-{
- COMBINE_DATA(&m_bgvideoram[offset]);
- m_bg_tilemap->mark_tile_dirty(offset / 2);
-}
-
-WRITE16_MEMBER(bionicc_state::fgvideoram_w)
-{
- COMBINE_DATA(&m_fgvideoram[offset]);
- m_fg_tilemap->mark_tile_dirty(offset / 2);
-}
-
-WRITE16_MEMBER(bionicc_state::txvideoram_w)
-{
- COMBINE_DATA(&m_txvideoram[offset]);
- m_tx_tilemap->mark_tile_dirty(offset & 0x3ff);
-}
-
-WRITE16_MEMBER(bionicc_state::scroll_w)
-{
- data = COMBINE_DATA(&m_scroll[offset]);
-
- switch (offset)
- {
- case 0:
- m_fg_tilemap->set_scrollx(0, data);
- break;
- case 1:
- m_fg_tilemap->set_scrolly(0, data);
- break;
- case 2:
- m_bg_tilemap->set_scrollx(0, data);
- break;
- case 3:
- m_bg_tilemap->set_scrolly(0, data);
- break;
- }
-}
-
-WRITE16_MEMBER(bionicc_state::gfxctrl_w)
-{
- if (ACCESSING_BITS_8_15)
- {
- flip_screen_set(data & 0x0100);
-
- m_bg_tilemap->enable(data & 0x2000); /* guess */
- m_fg_tilemap->enable(data & 0x1000); /* guess */
-
- machine().bookkeeping().coin_counter_w(0, data & 0x8000);
- machine().bookkeeping().coin_counter_w(1, data & 0x4000);
- }
-}
-
-
-
-/***************************************************************************
-
- Display refresh
-
-***************************************************************************/
-
-
-
-uint32_t bionicc_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
-{
- bitmap.fill(m_palette->black_pen(), cliprect);
- m_fg_tilemap->draw(screen, bitmap, cliprect, 1 | TILEMAP_DRAW_LAYER1, 0); /* nothing in FRONT */
- m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
- m_fg_tilemap->draw(screen, bitmap, cliprect, 0 | TILEMAP_DRAW_LAYER1, 0);
- m_spritegen->draw_sprites(bitmap, cliprect, m_spriteram->buffer(), m_spriteram->bytes(), flip_screen(), false);
- m_fg_tilemap->draw(screen, bitmap, cliprect, 0 | TILEMAP_DRAW_LAYER0, 0);
- m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
- return 0;
-}