// license:BSD-3-Clause // copyright-holders:David Haywood /*** Tecmo Bowl (c)1987 Tecmo driver by David Haywood wip 20/01/2002 Tecmo Bowl was a popular 4 player American Football game with two screens and attractive graphics --- Current Issues Might be some priority glitches ***/ #include "emu.h" #include "includes/tbowl.h" #include "cpu/z80/z80.h" #include "sound/3812intf.h" #include "rendlay.h" #include "screen.h" #include "speaker.h" WRITE8_MEMBER(tbowl_state::coincounter_w) { machine().bookkeeping().coin_counter_w(0, data & 1); } /*** Banking note: check this, its borrowed from tecmo.cpp / wc90.cpp at the moment and could well be wrong ***/ WRITE8_MEMBER(tbowl_state::boardb_bankswitch_w) { membank("mainbank")->set_entry(data >> 3); } WRITE8_MEMBER(tbowl_state::boardc_bankswitch_w) { membank("subbank")->set_entry(data >> 3); } /*** Memory Structures Board B is the main board, reading inputs, and in control of the 2 bg layers & text layer etc. Board C is the sub board, main job is the sprites Board A is for the sound ***/ /* Board B */ void tbowl_state::_6206B_map(address_map &map) { map(0x0000, 0x7fff).rom(); map(0x8000, 0x9fff).ram(); map(0xa000, 0xbfff).ram().w(this, FUNC(tbowl_state::bg2videoram_w)).share("bg2videoram"); map(0xc000, 0xdfff).ram().w(this, FUNC(tbowl_state::bgvideoram_w)).share("bgvideoram"); map(0xe000, 0xefff).ram().w(this, FUNC(tbowl_state::txvideoram_w)).share("txvideoram"); // AM_RANGE(0xf000, 0xf000) AM_WRITE(unknown_write) * written during start-up, not again */ map(0xf000, 0xf7ff).bankr("mainbank"); map(0xf800, 0xfbff).ram().share("shared_ram"); /* check */ map(0xfc00, 0xfc00).portr("P1").w(this, FUNC(tbowl_state::boardb_bankswitch_w)); map(0xfc01, 0xfc01).portr("P2"); // AM_RANGE(0xfc01, 0xfc01) AM_WRITE(unknown_write) /* written during start-up, not again */ map(0xfc02, 0xfc02).portr("P3"); // AM_RANGE(0xfc02, 0xfc02) AM_WRITE(unknown_write) /* written during start-up, not again */ map(0xfc03, 0xfc03).portr("P4").w(this, FUNC(tbowl_state::coincounter_w)); // AM_RANGE(0xfc05, 0xfc05) AM_WRITE(unknown_write) /* no idea */ // AM_RANGE(0xfc06, 0xfc06) AM_READ(dummy_r) /* Read During NMI */ map(0xfc07, 0xfc07).portr("SYSTEM"); map(0xfc08, 0xfc08).portr("DSW1"); // AM_RANGE(0xfc08, 0xfc08) AM_WRITE(unknown_write) /* hardly used .. */ map(0xfc09, 0xfc09).portr("DSW2"); map(0xfc0a, 0xfc0a).portr("DSW3"); // AM_RANGE(0xfc0a, 0xfc0a) AM_WRITE(unknown_write) /* hardly used .. */ map(0xfc0d, 0xfc0d).w(m_soundlatch, FUNC(generic_latch_8_device::write)); map(0xfc10, 0xfc10).w(this, FUNC(tbowl_state::bg2xscroll_lo)); map(0xfc11, 0xfc11).w(this, FUNC(tbowl_state::bg2xscroll_hi)); map(0xfc12, 0xfc12).w(this, FUNC(tbowl_state::bg2yscroll_lo)); map(0xfc13, 0xfc13).w(this, FUNC(tbowl_state::bg2yscroll_hi)); map(0xfc14, 0xfc14).w(this, FUNC(tbowl_state::bgxscroll_lo)); map(0xfc15, 0xfc15).w(this, FUNC(tbowl_state::bgxscroll_hi)); map(0xfc16, 0xfc16).w(this, FUNC(tbowl_state::bgyscroll_lo)); map(0xfc17, 0xfc17).w(this, FUNC(tbowl_state::bgyscroll_hi)); } /* Board C */ WRITE8_MEMBER(tbowl_state::trigger_nmi) { /* trigger NMI on 6206B's Cpu? (guess but seems to work..) */ m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); } void tbowl_state::_6206C_map(address_map &map) { map(0x0000, 0xbfff).rom(); map(0xc000, 0xdfff).readonly(); map(0xc000, 0xd7ff).writeonly(); map(0xd800, 0xdfff).writeonly().share("spriteram"); map(0xe000, 0xefff).ram().w(m_palette, FUNC(palette_device::write8)).share("palette"); // 2x palettes, one for each monitor? map(0xf000, 0xf7ff).bankr("subbank"); map(0xf800, 0xfbff).ram().share("shared_ram"); map(0xfc00, 0xfc00).w(this, FUNC(tbowl_state::boardc_bankswitch_w)); map(0xfc01, 0xfc01).nopw(); /* ? */ map(0xfc02, 0xfc02).w(this, FUNC(tbowl_state::trigger_nmi)); /* ? */ map(0xfc03, 0xfc03).nopw(); /* ? */ map(0xfc06, 0xfc06).nopw(); /* ? */ } /* Board A */ WRITE8_MEMBER(tbowl_state::adpcm_start_w) { msm5205_device *adpcm = (offset & 1) ? m_msm2 : m_msm1; m_adpcm_pos[offset & 1] = data << 8; adpcm->reset_w(0); } WRITE8_MEMBER(tbowl_state::adpcm_end_w) { m_adpcm_end[offset & 1] = (data + 1) << 8; } WRITE8_MEMBER(tbowl_state::adpcm_vol_w) { msm5205_device *adpcm = (offset & 1) ? m_msm2 : m_msm1; adpcm->set_output_gain(ALL_OUTPUTS, (data & 127) / 127.0); } void tbowl_state::adpcm_int( msm5205_device *device, int num ) { if (m_adpcm_pos[num] >= m_adpcm_end[num] || m_adpcm_pos[num] >= memregion("adpcm")->bytes()/2) device->reset_w(1); else if (m_adpcm_data[num] != -1) { device->data_w(m_adpcm_data[num] & 0x0f); m_adpcm_data[num] = -1; } else { uint8_t *ROM = memregion("adpcm")->base() + 0x10000 * num; m_adpcm_data[num] = ROM[m_adpcm_pos[num]++]; device->data_w(m_adpcm_data[num] >> 4); } } WRITE_LINE_MEMBER(tbowl_state::adpcm_int_1) { adpcm_int(m_msm1, 0); } WRITE_LINE_MEMBER(tbowl_state::adpcm_int_2) { adpcm_int(m_msm2, 1); } void tbowl_state::_6206A_map(address_map &map) { map(0x0000, 0x7fff).rom(); map(0xc000, 0xc7ff).ram(); map(0xd000, 0xd001).w("ym1", FUNC(ym3812_device::write)); map(0xd800, 0xd801).w("ym2", FUNC(ym3812_device::write)); map(0xe000, 0xe001).w(this, FUNC(tbowl_state::adpcm_end_w)); map(0xe002, 0xe003).w(this, FUNC(tbowl_state::adpcm_start_w)); map(0xe004, 0xe005).w(this, FUNC(tbowl_state::adpcm_vol_w)); map(0xe006, 0xe006).w(m_soundlatch, FUNC(generic_latch_8_device::acknowledge_w)); map(0xe007, 0xe007).nopw(); // sound watchdog map(0xe010, 0xe010).r(m_soundlatch, FUNC(generic_latch_8_device::read)); } /*** Input Ports Haze's notes : There are controls for 4 players, each player has 4 directions and 2 buttons as well as coin and start. The service switch acts as inserting a coin for all 4 players, the dipswitches are listed in the manual Steph's notes (2002.02.12) : I haven't found any manual, so my notes only rely on the Z80 code ... -- Inputs -- According to the Z80 code, here is the list of controls for each player : - NO START button (you need to press BUTTON1n to start a game for player n) - 4 or 8 directions (I can't tell for the moment, so I've chosen 8 directions) - 2 buttons (I can't tell for the moment what they do) There are also 1 coin slot and a "Service" button for each player. 1 "credit" will mean <