diff options
Diffstat (limited to 'src/mame/konami/kpontoon.cpp')
-rw-r--r-- | src/mame/konami/kpontoon.cpp | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/src/mame/konami/kpontoon.cpp b/src/mame/konami/kpontoon.cpp new file mode 100644 index 00000000000..72910a34eee --- /dev/null +++ b/src/mame/konami/kpontoon.cpp @@ -0,0 +1,433 @@ +// license:BSD-3-Clause +// copyright-holders: R. Belmont + +/* + Pontoon (GS270) (c) 1993 Konami + + PWB353261A + + 2 Z84C0008PEC + 1 053246A + 1 053247A + 1 054539 + 1 053252 + 3 8-dip banks + 3 XTALs (1 21.05300MHz and 2 18.43200MHz) + + TTL char readback: + C000-D000 window, control bit 7 enables ROM readback, bit 5 selects which ROM, F450 banks +*/ + +#include "emu.h" +#include "cpu/z80/z80.h" +#include "machine/k053252.h" +#include "sound/k054539.h" +#include "k053246_k053247_k055673.h" +#include "emupal.h" +#include "screen.h" +#include "speaker.h" +#include "tilemap.h" +#include "machine/timer.h" + +namespace { + +class kpontoon_state : public driver_device +{ +public: + kpontoon_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_mainbank(*this, "mainbank"), + m_k053246(*this, "k053246"), + m_k054539(*this, "k054539"), + m_k053252(*this, "k053252"), + m_ttl_vram(*this, "ttl_vram"), + m_gfxdecode(*this, "gfxdecode"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_charview(*this, "charview"), + m_charrom(*this, "chars"), + m_sprrom(*this, "k053246"), + m_sndrom(*this, "audiocpu") + { } + + void kpontoon(machine_config &config); + +protected: + virtual void machine_start() override ATTR_COLD; + virtual void machine_reset() override ATTR_COLD; + +private: + tilemap_t *m_ttl_tilemap; + + void main_map(address_map &map) ATTR_COLD; + void sound_map(address_map &map) ATTR_COLD; + + required_device<cpu_device> m_maincpu, m_audiocpu; + required_memory_bank m_mainbank; + required_device<k053247_device> m_k053246; + required_device<k054539_device> m_k054539; + required_device<k053252_device> m_k053252; + required_shared_ptr<u8> m_ttl_vram; + required_device<gfxdecode_device> m_gfxdecode; + required_device<screen_device> m_screen; + required_device<palette_device> m_palette; + memory_view m_charview; + required_region_ptr<u8> m_charrom, m_sprrom, m_sndrom; + + void control_w(u8 data); + void charrom_bank_w(u8 data); + void sprrom_adr_h(u8 data); + void sprrom_adr_m(u8 data); + void sprrom_adr_l(u8 data); + u8 charrom_r(offs_t offset); + u8 sprrom_r(offs_t offset); + void ttl_ram_w(offs_t offset, u8 data); + void ccu_int_time_w(u8 data) { m_ccu_int_time = data; } + u8 vbl_r() { return m_screen->vblank() ? 0x80 : 0x00; } + void snd_to_main_w(offs_t offset, u8 data); + u8 snd_to_main_r() { return m_sound_to_main; } + void main_to_snd_w(offs_t offset, u8 data); + u8 main_to_snd_r(); + u8 snd_rombank_r(offs_t offset); + void snd_bnk_w(u8 data); + + TILE_GET_INFO_MEMBER(ttl_get_tile_info); + void k054539_nmi_gen(int state); + + u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + TIMER_DEVICE_CALLBACK_MEMBER(ccu_scanline); + void vbl_ack_w(int state) { m_maincpu->set_input_line(0, CLEAR_LINE); } + void nmi_ack_w(int state) { m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); } + + u8 m_control; + u8 m_charrom_bank; + int m_ccu_int_time, m_ccu_int_time_count; + u32 m_sprrom_adr; + u8 m_sound_nmi_clk; + u8 m_sound_to_main, m_main_to_sound; + u8 m_sound_rombank; +}; + +void kpontoon_state::control_w(u8 data) +{ +/* + bit 7 = 1 to enable char ROM readback at C000-D000, 0 for char VRAM + bit 6 = ? + bit 5 = char ROM select for readback + bit 4 = ? + bit 3 = ? + bit 2 = ? + bit 0,1 = program ROM bank +*/ + + m_mainbank->set_entry(data & 0x03); + m_charview.select(BIT(data, 7)); + m_control = data; +} + +void kpontoon_state::charrom_bank_w(u8 data) +{ + m_charrom_bank = data; +} + +u8 kpontoon_state::charrom_r(offs_t offset) +{ + offs_t loc = ((0x1000 * m_charrom_bank) + offset) << 1; + + // ROMs are byte interleaved, bit 6 selects which ROM we're reading + if (!BIT(m_control, 5)) + { + loc += 1; + } + + return m_charrom[loc]; +} + +void kpontoon_state::sprrom_adr_h(u8 data) +{ + m_sprrom_adr &= 0xffff; + m_sprrom_adr |= (data << 16); +} + +void kpontoon_state::sprrom_adr_m(u8 data) +{ + m_sprrom_adr &= 0xff00ff; + m_sprrom_adr |= (data << 8); +} + +void kpontoon_state::sprrom_adr_l(u8 data) +{ + m_sprrom_adr &= 0xffff00; + m_sprrom_adr |= data; +} + +u8 kpontoon_state::sprrom_r(offs_t offset) +{ + return m_sprrom[(offset ^ 1) + (m_sprrom_adr << 1)]; +} + +void kpontoon_state::main_map(address_map &map) +{ + map(0x0000, 0x7fff).rom().region("maincpu", 0); + map(0x8000, 0x9fff).bankr(m_mainbank); + map(0xa000, 0xafff).ram(); + map(0xb000, 0xbfff).ram(); // work RAM (stack is here) + + map(0x0000, 0xffff).view(m_charview); + m_charview[0](0xc000, 0xcfff).ram().share("ttl_vram").w(FUNC(kpontoon_state::ttl_ram_w)); + m_charview[1](0xc000, 0xcfff).r(FUNC(kpontoon_state::charrom_r)); + + map(0xe000, 0xefff).ram(); + map(0xf000, 0xf1ff).ram().w(m_palette, FUNC(palette_device::write8)).share("palette"); + map(0xf405, 0xf405).w(FUNC(kpontoon_state::sprrom_adr_l)); + map(0xf406, 0xf406).w(FUNC(kpontoon_state::sprrom_adr_m)); + map(0xf407, 0xf407).w(FUNC(kpontoon_state::sprrom_adr_h)); + map(0xf410, 0xf411).r(FUNC(kpontoon_state::sprrom_r)); +// this sets a very wrong video mode when enabled +// map(0xf420, 0xf42f).rw(m_k053252, FUNC(k053252_device::read), FUNC(k053252_device::write)); + map(0xf450, 0xf450).w(FUNC(kpontoon_state::charrom_bank_w)); + map(0xf470, 0xf470).nopw(); // watchdog + map(0xf810, 0xf810).w(FUNC(kpontoon_state::main_to_snd_w)); + map(0xf820, 0xf820).r(FUNC(kpontoon_state::snd_to_main_r)); + map(0xf830, 0xf830).w(FUNC(kpontoon_state::control_w)); + map(0xf851, 0xf851).r(FUNC(kpontoon_state::vbl_r)); +} + +void kpontoon_state::main_to_snd_w(offs_t offset, u8 data) +{ + m_main_to_sound = data; + m_audiocpu->set_input_line(0, ASSERT_LINE); +} + +u8 kpontoon_state::main_to_snd_r() +{ + m_audiocpu->set_input_line(0, CLEAR_LINE); + return m_main_to_sound; +} + +void kpontoon_state::snd_to_main_w(offs_t offset, u8 data) +{ + if (offset == 0) + { + m_sound_to_main = data; + } +} + +void kpontoon_state::k054539_nmi_gen(int state) +{ + // Trigger an /NMI on the rising edge + if (!m_sound_nmi_clk && state) + { + m_audiocpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + } + else if (!state) + { + m_audiocpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE); + } + + m_sound_nmi_clk = state; +} + +u8 kpontoon_state::snd_rombank_r(offs_t offset) +{ + return m_sndrom[offset + (0x4000 * m_sound_rombank)]; +} + +void kpontoon_state::snd_bnk_w(u8 data) +{ + m_sound_rombank = data; +} + +void kpontoon_state::sound_map(address_map &map) +{ + map(0x0000, 0x7fff).rom().region("audiocpu", 0); + map(0x8000, 0xbfff).r(FUNC(kpontoon_state::snd_rombank_r)); + map(0xc000, 0xc7ff).ram(); + map(0xd000, 0xd001).w(FUNC(kpontoon_state::snd_to_main_w)); + map(0xe000, 0xe001).r(FUNC(kpontoon_state::main_to_snd_r)); + map(0xf000, 0xf000).w(FUNC(kpontoon_state::snd_bnk_w)); + map(0xf800, 0xfa2f).rw(m_k054539, FUNC(k054539_device::read), FUNC(k054539_device::write)); +} + +static INPUT_PORTS_START( kpontoon ) + PORT_START("IN0") + PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) + + PORT_START("IN1") + PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNKNOWN ) + + PORT_START("DSW1") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW1:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW1:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW1:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW1:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW1:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW1:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW1:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW1:8") + + PORT_START("DSW2") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW2:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW2:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW2:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW2:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW2:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW2:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW2:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW2:8") + + PORT_START("DSW3") + PORT_DIPUNKNOWN_DIPLOC(0x01, 0x01, "DSW3:1") + PORT_DIPUNKNOWN_DIPLOC(0x02, 0x02, "DSW3:2") + PORT_DIPUNKNOWN_DIPLOC(0x04, 0x04, "DSW3:3") + PORT_DIPUNKNOWN_DIPLOC(0x08, 0x08, "DSW3:4") + PORT_DIPUNKNOWN_DIPLOC(0x10, 0x10, "DSW3:5") + PORT_DIPUNKNOWN_DIPLOC(0x20, 0x20, "DSW3:6") + PORT_DIPUNKNOWN_DIPLOC(0x40, 0x40, "DSW3:7") + PORT_DIPUNKNOWN_DIPLOC(0x80, 0x80, "DSW3:8") +INPUT_PORTS_END + + +void kpontoon_state::machine_start() +{ + m_mainbank->configure_entries(0, 4, memregion("maincpu")->base() + 0x8000, 0x2000); + m_mainbank->set_entry(0); + + m_ttl_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(kpontoon_state::ttl_get_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 32); + m_ttl_tilemap->set_transparent_pen(0); +} + +void kpontoon_state::machine_reset() +{ + m_charview.select(0); + m_ccu_int_time_count = 0; + m_ccu_int_time = 31; + m_control = 0; + m_sound_nmi_clk = 0; +} + +void kpontoon_state::ttl_ram_w(offs_t offset, u8 data) +{ + u8 *vram = (u8 *)m_ttl_vram.target(); + vram[offset] = data; + m_ttl_tilemap->mark_tile_dirty(offset / 2); +} + +TILE_GET_INFO_MEMBER(kpontoon_state::ttl_get_tile_info) +{ + u8 *vram = (u8 *)m_ttl_vram.target(); + int attr, code; + + attr = vram[(tile_index << 1) + 1]; + code = vram[(tile_index << 1)]; + + tileinfo.set(0, code, attr, 0); +} + +uint32_t kpontoon_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + bitmap.fill(0, cliprect); + m_ttl_tilemap->draw(screen, bitmap, cliprect, 0, 0); + return 0; +} + +TIMER_DEVICE_CALLBACK_MEMBER(kpontoon_state::ccu_scanline) +{ + int scanline = param; + + // z80 /IRQ is connected to the IRQ1(vblank) pin of k053252 CCU + if (scanline == 255) + { + m_maincpu->set_input_line(0, ASSERT_LINE); + } + + // z80 /NMI is connected to the IRQ2 pin of k053252 CCU + // the following code is emulating INT_TIME of the k053252, this code will go away + // when the new konami branch is merged. + m_ccu_int_time_count--; + if (m_ccu_int_time_count <= 0) + { + m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); + m_ccu_int_time_count = m_ccu_int_time; + } +} + +static GFXDECODE_START( gfx_pontoon ) + GFXDECODE_ENTRY( "chars", 0, gfx_16x16x4_packed_msb, 0, 1 ) // TODO: looks decent, but needs verifying +GFXDECODE_END + +void kpontoon_state::kpontoon(machine_config &config) +{ + // basic machine hardware + Z80(config, m_maincpu, 21'053'000 / 4); // clock unverified + m_maincpu->set_addrmap(AS_PROGRAM, &kpontoon_state::main_map); + TIMER(config, "scantimer").configure_scanline(FUNC(kpontoon_state::ccu_scanline), "screen", 0, 1); + + Z80(config, m_audiocpu, 21'053'000 / 3); // clock unverified + m_audiocpu->set_addrmap(AS_PROGRAM, &kpontoon_state::sound_map); + + K053252(config, m_k053252, 21'053'000 / 8); // clock unverified + m_k053252->int1_ack().set(FUNC(kpontoon_state::vbl_ack_w)); + m_k053252->int2_ack().set(FUNC(kpontoon_state::nmi_ack_w)); + m_k053252->int_time().set(FUNC(kpontoon_state::ccu_int_time_w)); + m_k053252->set_offsets(256, 96); // not accurate + + // video hardware + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(60); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); + m_screen->set_size(128*8, 64*8); + m_screen->set_visarea(25*8, 91*8-1, 24, 56*8-1); + m_screen->set_screen_update(FUNC(kpontoon_state::screen_update)); + m_screen->set_palette("palette"); + + PALETTE(config, m_palette).set_format(palette_device::xBGR_555, 256); + GFXDECODE(config, m_gfxdecode, "palette", gfx_pontoon); + + // sound hardware + SPEAKER(config, "speaker", 2).front(); + + K053246(config, m_k053246, 0); + //m_k053246.set_sprite_callback(FUNC(kpontoon_state::sprite_callback)); + m_k053246->set_config(NORMAL_PLANE_ORDER, 0, 0); // TODO: verify + m_k053246->set_palette(m_palette); + + K054539(config, m_k054539, 18.432_MHz_XTAL); + m_k054539->set_device_rom_tag("k054539"); + m_k054539->timer_handler().set(FUNC(kpontoon_state::k054539_nmi_gen)); + m_k054539->add_route(0, "speaker", 0.75, 1); + m_k054539->add_route(1, "speaker", 0.75, 0); +} + + +ROM_START( kpontoon ) + ROM_REGION( 0x10000, "maincpu", 0 ) + ROM_LOAD( "270eac04.bin", 0x00000, 0x10000, CRC(614e35bd) SHA1(50a7740f0442949d9c49209b04589296d065af52) ) + + ROM_REGION( 0x10000, "audiocpu", 0 ) + ROM_LOAD( "270b01.bin", 0x00000, 0x10000, CRC(f08ebef7) SHA1(126878cf32582cc5676be35c30aeeeeb462060a8) ) + + ROM_REGION( 0x80000, "k053246", 0 ) + ROM_LOAD64_BYTE( "270ea07.bin", 0x00007, 0x10000, CRC(27e791fa) SHA1(fcafe9fd74ab729a90e4a36b25dbc4ce050b68ba) ) + ROM_LOAD64_BYTE( "270ea08.bin", 0x00006, 0x10000, CRC(aa1474cc) SHA1(b935ab41daeaace62a90885c0d29f49df67ca3a3) ) + ROM_LOAD64_BYTE( "270ea09.bin", 0x00005, 0x10000, CRC(0462f9ea) SHA1(c16f6b8ef8b04fcc2b11783e3a5e553a45fafb84) ) + ROM_LOAD64_BYTE( "270ea10.bin", 0x00004, 0x10000, CRC(95dc83df) SHA1(0b27f7d801def2e3fde2fc0c4e130017cfa867bf) ) + ROM_LOAD64_BYTE( "270ea11.bin", 0x00003, 0x10000, CRC(5e0f83e0) SHA1(79c6119d488f8515419e6422a686dcc8363ce9c5) ) + ROM_LOAD64_BYTE( "270ea12.bin", 0x00002, 0x10000, CRC(553fcee0) SHA1(7330b223a71966aaa3216c9e58bdc090c8d402b0) ) + ROM_LOAD64_BYTE( "270ea13.bin", 0x00001, 0x10000, CRC(ead4a114) SHA1(ddce7c4c4606cedcc05c1d2e5fdeda5d1358c97e) ) + ROM_LOAD64_BYTE( "270ea14.bin", 0x00000, 0x10000, CRC(ac6b06c2) SHA1(5584b1d1047f0e447dd20252eb0ec3089bd228fe) ) + + ROM_REGION( 0x40000, "chars", 0 ) + ROM_LOAD16_BYTE( "270ea05.bin", 0x00000, 0x20000, CRC(d08e9a8b) SHA1(d333fa4f89907dd223e7a7d6c57a7fc78e61ee2d) ) + ROM_LOAD16_BYTE( "270ea06.bin", 0x00001, 0x20000, CRC(11eccb4b) SHA1(b943aa492819aa0563fc5295a890cd59c4b8aa4c) ) + + ROM_REGION( 0x80000, "k054539", 0 ) + ROM_LOAD( "270a02.bin", 0x00000, 0x80000, CRC(a1a75c87) SHA1(6ae459ab67b24ace06657b7e4be7803cd35f4bd3) ) +ROM_END + +} // Anonymous namespace + + +GAME( 1993, kpontoon, 0, kpontoon, kpontoon, kpontoon_state, empty_init, ROT0, "Konami", "Pontoon (Konami)", MACHINE_NO_SOUND | MACHINE_NOT_WORKING ) |