diff options
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 |
commit | c6b4027e4313484a8551b7e9802aceacf84224a2 (patch) | |
tree | 085e108cb7f7321ec6aaeee671725a75f6368a00 | |
parent | 962f30ccd45d8aa40ff327b1d0aade959fc9a87b (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.lua | 2 | ||||
-rw-r--r-- | src/mame/drivers/bionicc.cpp | 594 | ||||
-rw-r--r-- | src/mame/includes/bionicc.h | 96 | ||||
-rw-r--r-- | src/mame/video/bionicc.cpp | 200 |
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; -} |