From f032c9ed3ee08288a12c32e4d3a13da7ac2a4ca2 Mon Sep 17 00:00:00 2001 From: Ivan Vangelista Date: Fri, 10 Feb 2023 23:30:25 +0100 Subject: atari/skydiver.cpp, atari/skyraid.cpp, atari/sprint2.cpp, atari/sprint8.cpp, atari/starshp1.cpp, atari/subs.cpp, atari/tank8.cpp, atari/thunderj.cpp: consolidated drivers in single files Diffstat --- src/mame/atari/skydiver.cpp | 248 +++++++++++++-- src/mame/atari/skydiver.h | 114 ------- src/mame/atari/skydiver_a.cpp | 9 +- src/mame/atari/skydiver_a.h | 26 ++ src/mame/atari/skydiver_v.cpp | 201 ------------ src/mame/atari/skyraid.cpp | 362 +++++++++++++++++----- src/mame/atari/skyraid.h | 67 ---- src/mame/atari/skyraid_a.cpp | 29 +- src/mame/atari/skyraid_a.h | 22 ++ src/mame/atari/skyraid_v.cpp | 142 --------- src/mame/atari/sprint2.cpp | 290 +++++++++++++++++- src/mame/atari/sprint2.h | 121 -------- src/mame/atari/sprint2_a.cpp | 5 +- src/mame/atari/sprint2_a.h | 30 ++ src/mame/atari/sprint2_v.cpp | 172 ----------- src/mame/atari/sprint8.cpp | 333 ++++++++++++++++++-- src/mame/atari/sprint8.h | 91 ------ src/mame/atari/sprint8_a.cpp | 54 +--- src/mame/atari/sprint8_a.h | 27 ++ src/mame/atari/sprint8_v.cpp | 183 ----------- src/mame/atari/starshp1.cpp | 687 +++++++++++++++++++++++++++++++++++++----- src/mame/atari/starshp1.h | 163 ---------- src/mame/atari/starshp1_a.cpp | 8 +- src/mame/atari/starshp1_a.h | 26 ++ src/mame/atari/starshp1_v.cpp | 388 ------------------------ src/mame/atari/subs.cpp | 382 ++++++++++++++++++++--- src/mame/atari/subs.h | 84 ------ src/mame/atari/subs_a.cpp | 22 +- src/mame/atari/subs_a.h | 23 ++ src/mame/atari/subs_m.cpp | 177 ----------- src/mame/atari/subs_v.cpp | 186 ------------ src/mame/atari/tank8.cpp | 435 +++++++++++++++++++++++--- src/mame/atari/tank8.h | 109 ------- src/mame/atari/tank8_a.cpp | 8 +- src/mame/atari/tank8_a.h | 30 ++ src/mame/atari/tank8_v.cpp | 267 ---------------- src/mame/atari/thunderj.cpp | 421 +++++++++++++++++++++----- src/mame/atari/thunderj.h | 59 ---- src/mame/atari/thunderj_v.cpp | 238 --------------- src/mame/atari/triplhnt.cpp | 8 +- 40 files changed, 2996 insertions(+), 3251 deletions(-) delete mode 100644 src/mame/atari/skydiver.h create mode 100644 src/mame/atari/skydiver_a.h delete mode 100644 src/mame/atari/skydiver_v.cpp delete mode 100644 src/mame/atari/skyraid.h create mode 100644 src/mame/atari/skyraid_a.h delete mode 100644 src/mame/atari/skyraid_v.cpp delete mode 100644 src/mame/atari/sprint2.h create mode 100644 src/mame/atari/sprint2_a.h delete mode 100644 src/mame/atari/sprint2_v.cpp delete mode 100644 src/mame/atari/sprint8.h create mode 100644 src/mame/atari/sprint8_a.h delete mode 100644 src/mame/atari/sprint8_v.cpp delete mode 100644 src/mame/atari/starshp1.h create mode 100644 src/mame/atari/starshp1_a.h delete mode 100644 src/mame/atari/starshp1_v.cpp delete mode 100644 src/mame/atari/subs.h create mode 100644 src/mame/atari/subs_a.h delete mode 100644 src/mame/atari/subs_m.cpp delete mode 100644 src/mame/atari/subs_v.cpp delete mode 100644 src/mame/atari/tank8.h create mode 100644 src/mame/atari/tank8_a.h delete mode 100644 src/mame/atari/tank8_v.cpp delete mode 100644 src/mame/atari/thunderj.h delete mode 100644 src/mame/atari/thunderj_v.cpp diff --git a/src/mame/atari/skydiver.cpp b/src/mame/atari/skydiver.cpp index 863f8e43ac9..c2f74c82864 100644 --- a/src/mame/atari/skydiver.cpp +++ b/src/mame/atari/skydiver.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Mike Balfour + /*************************************************************************** Atari Sky Diver hardware @@ -89,16 +90,200 @@ ***************************************************************************/ #include "emu.h" -#include "skydiver.h" + +#include "skydiver_a.h" #include "cpu/m6800/m6800.h" +#include "machine/74259.h" +#include "machine/watchdog.h" #include "sound/discrete.h" + +#include "emupal.h" #include "screen.h" #include "speaker.h" +#include "tilemap.h" #include "skydiver.lh" +namespace { + +class skydiver_state : public driver_device +{ +public: + skydiver_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_watchdog(*this, "watchdog"), + m_latch3(*this, "latch3"), + m_discrete(*this, "discrete"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_videoram(*this, "videoram") + { } + + void skydiver(machine_config &config); + +protected: + virtual void video_start() override; + +private: + required_device m_maincpu; + required_device m_watchdog; + required_device m_latch3; + required_device m_discrete; + required_device m_gfxdecode; + required_device m_palette; + + required_shared_ptr m_videoram; + + uint8_t m_nmion = 0; + tilemap_t *m_bg_tilemap = nullptr; + uint8_t m_width = 0; + + DECLARE_WRITE_LINE_MEMBER(nmion_w); + void videoram_w(offs_t offset, uint8_t data); + uint8_t wram_r(offs_t offset); + void wram_w(offs_t offset, uint8_t data); + DECLARE_WRITE_LINE_MEMBER(width_w); + DECLARE_WRITE_LINE_MEMBER(coin_lockout_w); + DECLARE_WRITE_LINE_MEMBER(lamp_s_w); + DECLARE_WRITE_LINE_MEMBER(lamp_k_w); + DECLARE_WRITE_LINE_MEMBER(lamp_y_w); + DECLARE_WRITE_LINE_MEMBER(lamp_d_w); + DECLARE_WRITE_LINE_MEMBER(lamp_i_w); + DECLARE_WRITE_LINE_MEMBER(lamp_v_w); + DECLARE_WRITE_LINE_MEMBER(lamp_e_w); + DECLARE_WRITE_LINE_MEMBER(lamp_r_w); + void latch3_watchdog_w(offs_t offset, uint8_t data); + + TILE_GET_INFO_MEMBER(get_tile_info); + + void palette(palette_device &palette) const; + + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + + INTERRUPT_GEN_MEMBER(interrupt); + void program_map(address_map &map); +}; + + +// video + +/*************************************************************************** + + Callbacks for the TileMap code + +***************************************************************************/ + +TILE_GET_INFO_MEMBER(skydiver_state::get_tile_info) +{ + uint8_t const code = m_videoram[tile_index]; + tileinfo.set(0, code & 0x3f, code >> 6, 0); +} + + + +/************************************* + * + * Video system start + * + *************************************/ + +void skydiver_state::video_start() +{ + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(skydiver_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32); + + save_item(NAME(m_nmion)); + save_item(NAME(m_width)); +} + + +/************************************* + * + * Memory handlers + * + *************************************/ + +void skydiver_state::videoram_w(offs_t offset, uint8_t data) +{ + m_videoram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset); +} + + +uint8_t skydiver_state::wram_r(offs_t offset) +{ + return m_videoram[offset | 0x380]; +} + +void skydiver_state::wram_w(offs_t offset, uint8_t data) +{ + m_videoram[offset | 0x0380] = data; +} + + +WRITE_LINE_MEMBER(skydiver_state::width_w) +{ + m_width = state; +} + + +WRITE_LINE_MEMBER(skydiver_state::coin_lockout_w) +{ + machine().bookkeeping().coin_lockout_global_w(!state); +} + + +void skydiver_state::latch3_watchdog_w(offs_t offset, uint8_t data) +{ + m_watchdog->watchdog_reset(); + m_latch3->write_a0(offset); +} + + +/************************************* + * + * Video update + * + *************************************/ + +void skydiver_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + /* draw each one of our four motion objects, the two PLANE sprites + can be drawn double width */ + for (int pic = 3; pic >= 0; pic--) + { + int sx = 29 * 8 - m_videoram[pic + 0x0390]; + int const sy = 30 * 8 - m_videoram[pic * 2 + 0x0398]; + int charcode = m_videoram[pic * 2 + 0x0399]; + int const xflip = charcode & 0x10; + int const yflip = charcode & 0x08; + int const wide = (~pic & 0x02) && m_width; + charcode = (charcode & 0x07) | ((charcode & 0x60) >> 2); + int const color = pic & 0x01; + + if (wide) + { + sx -= 8; + } + + m_gfxdecode->gfx(1)->zoom_transpen(bitmap, cliprect, + charcode, color, + xflip, yflip, sx, sy, + wide ? 0x20000 : 0x10000, 0x10000, 0); + } +} + + +uint32_t skydiver_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0); + + draw_sprites(bitmap, cliprect); + return 0; +} /************************************* @@ -115,7 +300,7 @@ static constexpr unsigned colortable_source[] = 0x01, 0x02 }; -void skydiver_state::skydiver_palette(palette_device &palette) const +void skydiver_state::palette(palette_device &palette) const { constexpr rgb_t colors[]{ rgb_t::black(), rgb_t::white(), rgb_t(0xa0, 0xa0, 0xa0) }; // black, white, grey for (unsigned i = 0; i < std::size(colortable_source); i++) @@ -126,6 +311,8 @@ void skydiver_state::skydiver_palette(palette_device &palette) const } +// machine + /************************************* * @@ -141,7 +328,7 @@ WRITE_LINE_MEMBER(skydiver_state::nmion_w) INTERRUPT_GEN_MEMBER(skydiver_state::interrupt) { - /* Convert range data to divide value and write to sound */ + // Convert range data to divide value and write to sound m_discrete->write(SKYDIVER_RANGE_DATA, (0x01 << (~m_videoram[0x394] & 0x07)) & 0xff); // Range 0-2 m_discrete->write(SKYDIVER_RANGE3_EN, m_videoram[0x394] & 0x08); // Range 3 - note disable @@ -160,12 +347,12 @@ INTERRUPT_GEN_MEMBER(skydiver_state::interrupt) * *************************************/ -void skydiver_state::skydiver_map(address_map &map) +void skydiver_state::program_map(address_map &map) { map.global_mask(0x7fff); map(0x0000, 0x007f).mirror(0x4300).rw(FUNC(skydiver_state::wram_r), FUNC(skydiver_state::wram_w)); - map(0x0080, 0x00ff).mirror(0x4000).ram(); /* RAM B1 */ - map(0x0400, 0x07ff).mirror(0x4000).ram().w(FUNC(skydiver_state::videoram_w)).share("videoram"); /* RAMs K1,M1,P1,J1,N1,K/L1,L1,H/J1 */ + map(0x0080, 0x00ff).mirror(0x4000).ram(); // RAM B1 + map(0x0400, 0x07ff).mirror(0x4000).ram().w(FUNC(skydiver_state::videoram_w)).share(m_videoram); // RAMs K1,M1,P1,J1,N1,K/L1,L1,H/J1 map(0x0800, 0x080f).mirror(0x47f0).w("latch1", FUNC(f9334_device::write_a0)); map(0x1000, 0x100f).mirror(0x47f0).w("latch2", FUNC(f9334_device::write_a0)); map(0x1800, 0x1800).mirror(0x47e0).portr("IN0"); @@ -210,13 +397,13 @@ static INPUT_PORTS_START( skydiver ) PORT_START("IN2") PORT_BIT (0x3f, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* Jump 1 */ - PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* Chute 1 */ + PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) // Jump 1 + PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) // Chute 1 PORT_START("IN3") PORT_BIT (0x3f, IP_ACTIVE_LOW, IPT_UNUSED ) - PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) /* Jump 2 */ - PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) /* Chute 2 */ + PORT_BIT (0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) // Jump 2 + PORT_BIT (0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2) // Chute 2 PORT_START("IN4") PORT_BIT (0x3f, IP_ACTIVE_LOW, IPT_UNUSED ) @@ -323,8 +510,8 @@ static const gfx_layout motion_layout = static GFXDECODE_START( gfx_skydiver ) - GFXDECODE_ENTRY( "gfx1", 0, charlayout, 0, 4 ) - GFXDECODE_ENTRY( "gfx2", 0, motion_layout, 0, 4 ) + GFXDECODE_ENTRY( "chars", 0, charlayout, 0, 4 ) + GFXDECODE_ENTRY( "sprites", 0, motion_layout, 0, 4 ) GFXDECODE_END @@ -337,20 +524,20 @@ GFXDECODE_END void skydiver_state::skydiver(machine_config &config) { - /* basic machine hardware */ - M6800(config, m_maincpu, 12.096_MHz_XTAL / 16); /* ???? */ - m_maincpu->set_addrmap(AS_PROGRAM, &skydiver_state::skydiver_map); + // basic machine hardware + M6800(config, m_maincpu, 12.096_MHz_XTAL / 16); // ???? + m_maincpu->set_addrmap(AS_PROGRAM, &skydiver_state::program_map); m_maincpu->set_periodic_int(FUNC(skydiver_state::interrupt), attotime::from_hz(5*60)); WATCHDOG_TIMER(config, m_watchdog).set_vblank_count("screen", 8); // 128V clocks the same as VBLANK f9334_device &latch1(F9334(config, "latch1")); // F12 - latch1.q_out_cb<0>().set(FUNC(skydiver_state::lamp_s_w)); - latch1.q_out_cb<1>().set(FUNC(skydiver_state::lamp_k_w)); - latch1.q_out_cb<2>().set(FUNC(skydiver_state::start_lamp_1_w)); - latch1.q_out_cb<3>().set(FUNC(skydiver_state::start_lamp_2_w)); - latch1.q_out_cb<4>().set(FUNC(skydiver_state::lamp_y_w)); - latch1.q_out_cb<5>().set(FUNC(skydiver_state::lamp_d_w)); + latch1.q_out_cb<0>().set_output("lamps"); + latch1.q_out_cb<1>().set_output("lampk"); + latch1.q_out_cb<2>().set_output("led0"); // start lamp 1 + latch1.q_out_cb<3>().set_output("led1"); // start lamp 2 + latch1.q_out_cb<4>().set_output("lampy"); + latch1.q_out_cb<5>().set_output("lampd"); latch1.q_out_cb<6>().set("discrete", FUNC(discrete_device::write_line)); f9334_device &latch2(F9334(config, "latch2")); // H12 @@ -363,24 +550,24 @@ void skydiver_state::skydiver(machine_config &config) latch2.q_out_cb<7>().set(FUNC(skydiver_state::width_w)); f9334_device &latch3(F9334(config, "latch3")); // A11 - latch3.q_out_cb<1>().set(FUNC(skydiver_state::lamp_i_w)); - latch3.q_out_cb<2>().set(FUNC(skydiver_state::lamp_v_w)); - latch3.q_out_cb<3>().set(FUNC(skydiver_state::lamp_e_w)); - latch3.q_out_cb<4>().set(FUNC(skydiver_state::lamp_r_w)); + latch3.q_out_cb<1>().set_output("lampi"); + latch3.q_out_cb<2>().set_output("lampv"); + latch3.q_out_cb<3>().set_output("lampe"); + latch3.q_out_cb<4>().set_output("lampr"); latch3.q_out_cb<5>().set("discrete", FUNC(discrete_device::write_line)); latch3.q_out_cb<6>().set("discrete", FUNC(discrete_device::write_line)); latch3.q_out_cb<7>().set("discrete", FUNC(discrete_device::write_line)); - /* video hardware */ + // video hardware screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); screen.set_raw(12.096_MHz_XTAL / 2, 384, 0, 256, 262, 0, 224); screen.set_screen_update(FUNC(skydiver_state::screen_update)); screen.set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_skydiver); - PALETTE(config, m_palette, FUNC(skydiver_state::skydiver_palette), std::size(colortable_source)); + PALETTE(config, m_palette, FUNC(skydiver_state::palette), std::size(colortable_source)); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); DISCRETE(config, m_discrete, skydiver_discrete).add_route(ALL_OUTPUTS, "mono", 1.0); @@ -401,14 +588,15 @@ ROM_START( skydiver ) ROM_LOAD( "33165-02.d1", 0x3800, 0x0800, CRC(a1fc5504) SHA1(febaa78936de7703b708c0d1f350fe288e0a106b) ) ROM_LOAD( "33166-02.c1", 0x7800, 0x0800, CRC(3d26da2b) SHA1(e515d5c13814b9732a6ca109272500a60edc208a) ) - ROM_REGION( 0x0400, "gfx1", 0 ) + ROM_REGION( 0x0400, "chars", 0 ) ROM_LOAD( "33163-01.h5", 0x0000, 0x0400, CRC(5b9bb7c2) SHA1(319f45b6dff96739f73f2089361239da47042dcd) ) - ROM_REGION( 0x0800, "gfx2", 0 ) + ROM_REGION( 0x0800, "sprites", 0 ) ROM_LOAD( "33176-01.l5", 0x0000, 0x0400, CRC(6b082a01) SHA1(8facc94843ea041d205137056bd2035cf968125b) ) ROM_LOAD( "33177-01.k5", 0x0400, 0x0400, CRC(f5541af0) SHA1(0967269518b6eac3c4e9ddaee39303086476c580) ) ROM_END +} // anonymous namespace /************************************* diff --git a/src/mame/atari/skydiver.h b/src/mame/atari/skydiver.h deleted file mode 100644 index 3dd1956c065..00000000000 --- a/src/mame/atari/skydiver.h +++ /dev/null @@ -1,114 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mike Balfour -/************************************************************************* - - Atari Skydiver hardware - -*************************************************************************/ -#ifndef MAME_ATARI_SKYDIVER_H -#define MAME_ATARI_SKYDIVER_H - -#pragma once - -#include "machine/74259.h" -#include "machine/watchdog.h" -#include "sound/discrete.h" -#include "emupal.h" -#include "tilemap.h" - -/* Discrete Sound Input Nodes */ -#define SKYDIVER_RANGE_DATA NODE_01 -#define SKYDIVER_NOTE_DATA NODE_02 -#define SKYDIVER_RANGE3_EN NODE_03 -#define SKYDIVER_NOISE_DATA NODE_04 -#define SKYDIVER_NOISE_RST NODE_05 -#define SKYDIVER_WHISTLE1_EN NODE_06 -#define SKYDIVER_WHISTLE2_EN NODE_07 -#define SKYDIVER_OCT1_EN NODE_08 -#define SKYDIVER_OCT2_EN NODE_09 -#define SKYDIVER_SOUND_EN NODE_10 - - -class skydiver_state : public driver_device -{ -public: - skydiver_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_watchdog(*this, "watchdog"), - m_latch3(*this, "latch3"), - m_discrete(*this, "discrete"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette"), - m_videoram(*this, "videoram"), - m_leds(*this, "led%u", 0U), - m_lamp_s(*this, "lamps"), - m_lamp_k(*this, "lampk"), - m_lamp_y(*this, "lampy"), - m_lamp_d(*this, "lampd"), - m_lamp_i(*this, "lampi"), - m_lamp_v(*this, "lampv"), - m_lamp_e(*this, "lampe"), - m_lamp_r(*this, "lampr") - { } - - void skydiver(machine_config &config); - -private: - DECLARE_WRITE_LINE_MEMBER(nmion_w); - void videoram_w(offs_t offset, uint8_t data); - uint8_t wram_r(offs_t offset); - void wram_w(offs_t offset, uint8_t data); - DECLARE_WRITE_LINE_MEMBER(width_w); - DECLARE_WRITE_LINE_MEMBER(coin_lockout_w); - DECLARE_WRITE_LINE_MEMBER(start_lamp_1_w); - DECLARE_WRITE_LINE_MEMBER(start_lamp_2_w); - DECLARE_WRITE_LINE_MEMBER(lamp_s_w); - DECLARE_WRITE_LINE_MEMBER(lamp_k_w); - DECLARE_WRITE_LINE_MEMBER(lamp_y_w); - DECLARE_WRITE_LINE_MEMBER(lamp_d_w); - DECLARE_WRITE_LINE_MEMBER(lamp_i_w); - DECLARE_WRITE_LINE_MEMBER(lamp_v_w); - DECLARE_WRITE_LINE_MEMBER(lamp_e_w); - DECLARE_WRITE_LINE_MEMBER(lamp_r_w); - void latch3_watchdog_w(offs_t offset, uint8_t data); - - TILE_GET_INFO_MEMBER(get_tile_info); - - virtual void machine_reset() override; - virtual void video_start() override; - void skydiver_palette(palette_device &palette) const; - - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); - - INTERRUPT_GEN_MEMBER(interrupt); - void skydiver_map(address_map &map); - - required_device m_maincpu; - required_device m_watchdog; - required_device m_latch3; - required_device m_discrete; - required_device m_gfxdecode; - required_device m_palette; - - required_shared_ptr m_videoram; - - output_finder<2> m_leds; - output_finder<> m_lamp_s; - output_finder<> m_lamp_k; - output_finder<> m_lamp_y; - output_finder<> m_lamp_d; - output_finder<> m_lamp_i; - output_finder<> m_lamp_v; - output_finder<> m_lamp_e; - output_finder<> m_lamp_r; - int m_nmion = 0; - tilemap_t *m_bg_tilemap = nullptr; - int m_width = 0; -}; - -/*----------- defined in audio/skydiver.c -----------*/ -DISCRETE_SOUND_EXTERN( skydiver_discrete ); - -#endif // MAME_ATARI_SKYDIVER_H diff --git a/src/mame/atari/skydiver_a.cpp b/src/mame/atari/skydiver_a.cpp index ea00a060e25..b7d1aa10f53 100644 --- a/src/mame/atari/skydiver_a.cpp +++ b/src/mame/atari/skydiver_a.cpp @@ -1,13 +1,14 @@ // license:BSD-3-Clause // copyright-holders:Derrick Renaud + /************************************************************************* - audio\skydiver.c + atari\skydiver_a.cpp *************************************************************************/ #include "emu.h" -#include "skydiver.h" -#include "sound/discrete.h" + +#include "skydiver_a.h" /************************************************************************/ @@ -121,7 +122,7 @@ DISCRETE_SOUND_START(skydiver_discrete) /* waveform. The original game pot varies from */ /* 0-250k, but we are going to limit it because */ /* below 50k the frequency is too high. */ - /* When triggered it starts at it's highest */ + /* When triggered it starts at its highest */ /* frequency, then decays at the rate set by */ /* a 68k resistor and 22uf capacitor. */ /************************************************/ diff --git a/src/mame/atari/skydiver_a.h b/src/mame/atari/skydiver_a.h new file mode 100644 index 00000000000..9617d1e4d51 --- /dev/null +++ b/src/mame/atari/skydiver_a.h @@ -0,0 +1,26 @@ +// license:BSD-3-Clause +// copyright-holders:Derrick Renaud + +/*************************************************************************** + +Sky Diver Audio + +***************************************************************************/ + +#include "sound/discrete.h" + +// discrete sound input nodes + +#define SKYDIVER_RANGE_DATA NODE_01 +#define SKYDIVER_NOTE_DATA NODE_02 +#define SKYDIVER_RANGE3_EN NODE_03 +#define SKYDIVER_NOISE_DATA NODE_04 +#define SKYDIVER_NOISE_RST NODE_05 +#define SKYDIVER_WHISTLE1_EN NODE_06 +#define SKYDIVER_WHISTLE2_EN NODE_07 +#define SKYDIVER_OCT1_EN NODE_08 +#define SKYDIVER_OCT2_EN NODE_09 +#define SKYDIVER_SOUND_EN NODE_10 + + +DISCRETE_SOUND_EXTERN( skydiver_discrete ); diff --git a/src/mame/atari/skydiver_v.cpp b/src/mame/atari/skydiver_v.cpp deleted file mode 100644 index 02efc143ced..00000000000 --- a/src/mame/atari/skydiver_v.cpp +++ /dev/null @@ -1,201 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mike Balfour -/*************************************************************************** - - Atari Sky Diver hardware - -***************************************************************************/ - -#include "emu.h" -#include "skydiver.h" -#include "sound/discrete.h" - - -void skydiver_state::machine_reset() -{ -} - - -/*************************************************************************** - - Callbacks for the TileMap code - -***************************************************************************/ - -TILE_GET_INFO_MEMBER(skydiver_state::get_tile_info) -{ - uint8_t code = m_videoram[tile_index]; - tileinfo.set(0, code & 0x3f, code >> 6, 0); -} - - - -/************************************* - * - * Video system start - * - *************************************/ - -void skydiver_state::video_start() -{ - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(skydiver_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8,8, 32,32); - - save_item(NAME(m_nmion)); - save_item(NAME(m_width)); - - m_leds.resolve(); - m_lamp_s.resolve(); - m_lamp_k.resolve(); - m_lamp_y.resolve(); - m_lamp_d.resolve(); - m_lamp_i.resolve(); - m_lamp_v.resolve(); - m_lamp_e.resolve(); - m_lamp_r.resolve(); -} - - -/************************************* - * - * Memory handlers - * - *************************************/ - -void skydiver_state::videoram_w(offs_t offset, uint8_t data) -{ - m_videoram[offset] = data; - m_bg_tilemap->mark_tile_dirty(offset); -} - - -uint8_t skydiver_state::wram_r(offs_t offset) -{ - return m_videoram[offset | 0x380]; -} - -void skydiver_state::wram_w(offs_t offset, uint8_t data) -{ - m_videoram[offset | 0x0380] = data; -} - - -WRITE_LINE_MEMBER(skydiver_state::width_w) -{ - m_width = state; -} - - -WRITE_LINE_MEMBER(skydiver_state::coin_lockout_w) -{ - machine().bookkeeping().coin_lockout_global_w(!state); -} - - -WRITE_LINE_MEMBER(skydiver_state::start_lamp_1_w) -{ - m_leds[0] = state; -} - -WRITE_LINE_MEMBER(skydiver_state::start_lamp_2_w) -{ - m_leds[1] = state; -} - - -WRITE_LINE_MEMBER(skydiver_state::lamp_s_w) -{ - m_lamp_s = state; -} - -WRITE_LINE_MEMBER(skydiver_state::lamp_k_w) -{ - m_lamp_k = state; -} - -WRITE_LINE_MEMBER(skydiver_state::lamp_y_w) -{ - m_lamp_y = state; -} - -WRITE_LINE_MEMBER(skydiver_state::lamp_d_w) -{ - m_lamp_d = state; -} - -WRITE_LINE_MEMBER(skydiver_state::lamp_i_w) -{ - m_lamp_i = state; -} - -WRITE_LINE_MEMBER(skydiver_state::lamp_v_w) -{ - m_lamp_v = state; -} - -WRITE_LINE_MEMBER(skydiver_state::lamp_e_w) -{ - m_lamp_e = state; -} - -WRITE_LINE_MEMBER(skydiver_state::lamp_r_w) -{ - m_lamp_r = state; -} - -void skydiver_state::latch3_watchdog_w(offs_t offset, uint8_t data) -{ - m_watchdog->watchdog_reset(); - m_latch3->write_a0(offset); -} - - -/************************************* - * - * Video update - * - *************************************/ - -void skydiver_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - int pic; - - - /* draw each one of our four motion objects, the two PLANE sprites - can be drawn double width */ - for (pic = 3; pic >= 0; pic--) - { - int sx,sy; - int charcode; - int xflip, yflip; - int color; - int wide; - - sx = 29*8 - m_videoram[pic + 0x0390]; - sy = 30*8 - m_videoram[pic*2 + 0x0398]; - charcode = m_videoram[pic*2 + 0x0399]; - xflip = charcode & 0x10; - yflip = charcode & 0x08; - wide = (~pic & 0x02) && m_width; - charcode = (charcode & 0x07) | ((charcode & 0x60) >> 2); - color = pic & 0x01; - - if (wide) - { - sx -= 8; - } - - m_gfxdecode->gfx(1)->zoom_transpen(bitmap,cliprect, - charcode, color, - xflip,yflip,sx,sy, - wide ? 0x20000 : 0x10000, 0x10000,0); - } -} - - -uint32_t skydiver_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - m_bg_tilemap->draw(screen, bitmap, cliprect, 0,0); - - draw_sprites(bitmap, cliprect); - return 0; -} diff --git a/src/mame/atari/skyraid.cpp b/src/mame/atari/skyraid.cpp index 08d2b58b40b..9290ed58d7f 100644 --- a/src/mame/atari/skyraid.cpp +++ b/src/mame/atari/skyraid.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Stefan Jokisch + /*************************************************************************** Atari Sky Raider driver @@ -7,19 +8,220 @@ Atari Sky Raider driver ***************************************************************************/ #include "emu.h" -#include "skyraid.h" + +#include "skyraid_a.h" #include "cpu/m6502/m6502.h" #include "machine/watchdog.h" +#include "sound/discrete.h" + +#include "emupal.h" #include "screen.h" #include "speaker.h" + +namespace { + +class skyraid_state : public driver_device +{ +public: + skyraid_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_pos_ram(*this, "pos_ram"), + m_alpha_num_ram(*this, "alpha_num_ram"), + m_obj_ram(*this, "obj_ram"), + m_terrain_rom(*this, "terrain"), + m_trapezoid_rom(*this, "trapezoid"), + m_maincpu(*this, "maincpu"), + m_screen(*this, "screen"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_discrete(*this, "discrete"), + m_language(*this, "LANGUAGE"), + m_stick(*this, "STICK%c", 'X'), + m_led(*this, "led") + { } + + void skyraid(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void video_start() override; + +private: + required_shared_ptr m_pos_ram; + required_shared_ptr m_alpha_num_ram; + required_shared_ptr m_obj_ram; + + required_region_ptr m_terrain_rom; + required_region_ptr m_trapezoid_rom; + + required_device m_maincpu; + required_device m_screen; + required_device m_gfxdecode; + required_device m_palette; + required_device m_discrete; + + required_ioport m_language; + required_ioport_array<2> m_stick; + output_finder<> m_led; + + uint8_t m_analog_range = 0; + uint8_t m_analog_offset = 0; + + uint8_t m_scroll = 0; + + bitmap_ind16 m_helper; + + uint8_t port_0_r(); + void range_w(uint8_t data); + void offset_w(uint8_t data); + void scroll_w(uint8_t data); + void palette(palette_device &palette) const; + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void sound_w(uint8_t data); + void draw_text(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_terrain(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_missiles(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_trapezoid(bitmap_ind16& dst, bitmap_ind16& src); + + void program_map(address_map &map); +}; + + +// video + +void skyraid_state::video_start() +{ + m_helper.allocate(128, 240); + + m_screen->register_screen_bitmap(m_helper); +} + + +void skyraid_state::draw_text(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + const uint8_t* p = m_alpha_num_ram; + + for (int i = 0; i < 4; i++) + { + int const y = 136 + 16 * (i ^ 1); + + for (int x = 0; x < bitmap.width(); x += 16) + m_gfxdecode->gfx(0)->transpen(bitmap, cliprect, *p++, 0, 0, 0, x, y, 0); + } +} + + +void skyraid_state::draw_terrain(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int y = 0; y < bitmap.height(); y++) + { + int offset = (16 * m_scroll + 16 * ((y + 1) / 2)) & 0x7ff; + + int x = 0; + + while (x < bitmap.width()) + { + uint8_t val = m_terrain_rom[offset++]; + + int const color = val / 32; + int const count = val % 32; + + rectangle r(x, x + 31 - count, y, y + 1); + + bitmap.fill(color, r); + + x += 32 - count; + } + } +} + + +void skyraid_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int i = 0; i < 4; i++) + { + int const code = m_obj_ram[8 + 2 * i + 0] & 15; + int const flag = m_obj_ram[8 + 2 * i + 1] & 15; + int vert = m_pos_ram[8 + 2 * i + 0]; + int const horz = m_pos_ram[8 + 2 * i + 1]; + + vert -= 31; + + if (flag & 1) + m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, + code ^ 15, code >> 3, 0, 0, + horz / 2, vert, 2); + } +} + + +void skyraid_state::draw_missiles(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // hardware is restricted to one sprite per scanline + + for (int i = 0; i < 4; i++) + { + int const code = m_obj_ram[2 * i + 0] & 15; + int vert = m_pos_ram[2 * i + 0]; + int horz = m_pos_ram[2 * i + 1]; + + vert -= 15; + horz -= 31; + + m_gfxdecode->gfx(2)->transpen(bitmap, cliprect, + code ^ 15, 0, 0, 0, + horz / 2, vert, 0); + } +} + + +void skyraid_state::draw_trapezoid(bitmap_ind16& dst, bitmap_ind16& src) +{ + for (int y = 0; y < dst.height(); y++) + { + uint16_t const *const pSrc = &src.pix(y); + uint16_t *const pDst = &dst.pix(y); + + int const x1 = 0x000 + m_trapezoid_rom[(y & ~1) + 0]; + int const x2 = 0x100 + m_trapezoid_rom[(y & ~1) + 1]; + + for (int x = x1; x < x2; x++) + pDst[x] = pSrc[128 * (x - x1) / (x2 - x1)]; + } +} + + +uint32_t skyraid_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + bitmap.fill(0, cliprect); + + rectangle helper_clip = cliprect; + helper_clip &= m_helper.cliprect(); + + draw_terrain(m_helper, helper_clip); + draw_sprites(m_helper, helper_clip); + draw_missiles(m_helper, helper_clip); + draw_trapezoid(bitmap, m_helper); + draw_text(bitmap, cliprect); + return 0; +} + + +// machine + void skyraid_state::machine_start() { m_led.resolve(); + + save_item(NAME(m_analog_range)); + save_item(NAME(m_analog_offset)); + save_item(NAME(m_scroll)); } -void skyraid_state::skyraid_palette(palette_device &palette) const +void skyraid_state::palette(palette_device &palette) const { palette.set_pen_color(0, rgb_t(0x00, 0x00, 0x00)); // terrain palette.set_pen_color(1, rgb_t(0x18, 0x18, 0x18)); @@ -43,52 +245,70 @@ void skyraid_state::skyraid_palette(palette_device &palette) const palette.set_pen_color(19, rgb_t(0xe0, 0xe0, 0xe0)); } -uint8_t skyraid_state::skyraid_port_0_r() +uint8_t skyraid_state::port_0_r() { - uint8_t val = ioport("LANGUAGE")->read(); + uint8_t val = m_language->read(); - if (ioport("STICKY")->read() > m_analog_range) + if (m_stick[1]->read() > m_analog_range) val |= 0x40; - if (ioport("STICKX")->read() > m_analog_range) + if (m_stick[0]->read() > m_analog_range) val |= 0x80; return val; } -void skyraid_state::skyraid_range_w(uint8_t data) +void skyraid_state::range_w(uint8_t data) { m_analog_range = data & 0x3f; } -void skyraid_state::skyraid_offset_w(uint8_t data) +void skyraid_state::offset_w(uint8_t data) { m_analog_offset = data & 0x3f; } -void skyraid_state::skyraid_scroll_w(uint8_t data) +void skyraid_state::scroll_w(uint8_t data) { m_scroll = data; } -void skyraid_state::skyraid_map(address_map &map) +void skyraid_state::sound_w(uint8_t data) +{ + // BIT0 => PLANE SWEEP + // BIT1 => MISSILE + // BIT2 => EXPLOSION + // BIT3 => START LAMP + // BIT4 => PLANE ON + // BIT5 => ATTRACT + + m_discrete->write(SKYRAID_PLANE_SWEEP_EN, data & 0x01); + m_discrete->write(SKYRAID_MISSILE_EN, data & 0x02); + m_discrete->write(SKYRAID_EXPLOSION_EN, data & 0x04); + m_led = !BIT(data, 3); + m_discrete->write(SKYRAID_PLANE_ON_EN, data & 0x10); + m_discrete->write(SKYRAID_ATTRACT_EN, data & 0x20); +} + + +void skyraid_state::program_map(address_map &map) { map(0x0000, 0x00ff).ram().mirror(0x300); - map(0x0400, 0x040f).writeonly().share("pos_ram"); - map(0x0800, 0x087f).ram().mirror(0x480).share("alpha_num_ram"); - map(0x1000, 0x1000).r(FUNC(skyraid_state::skyraid_port_0_r)); + map(0x0400, 0x040f).writeonly().share(m_pos_ram); + map(0x0800, 0x087f).ram().mirror(0x480).share(m_alpha_num_ram); + map(0x1000, 0x1000).r(FUNC(skyraid_state::port_0_r)); map(0x1001, 0x1001).portr("DSW"); map(0x1400, 0x1400).portr("COIN"); map(0x1401, 0x1401).portr("SYSTEM"); - map(0x1c00, 0x1c0f).writeonly().share("obj_ram"); - map(0x4000, 0x4000).w(FUNC(skyraid_state::skyraid_scroll_w)); - map(0x4400, 0x4400).w(FUNC(skyraid_state::skyraid_sound_w)); - map(0x4800, 0x4800).w(FUNC(skyraid_state::skyraid_range_w)); + map(0x1c00, 0x1c0f).writeonly().share(m_obj_ram); + map(0x4000, 0x4000).w(FUNC(skyraid_state::scroll_w)); + map(0x4400, 0x4400).w(FUNC(skyraid_state::sound_w)); + map(0x4800, 0x4800).w(FUNC(skyraid_state::range_w)); map(0x5000, 0x5000).w("watchdog", FUNC(watchdog_timer_device::reset_w)); - map(0x5800, 0x5800).w(FUNC(skyraid_state::skyraid_offset_w)); + map(0x5800, 0x5800).w(FUNC(skyraid_state::offset_w)); map(0x7000, 0x7fff).rom(); map(0xf000, 0xffff).rom(); } @@ -100,8 +320,8 @@ static INPUT_PORTS_START( skyraid ) PORT_DIPSETTING( 0x10, DEF_STR( French ) ) PORT_DIPSETTING( 0x20, DEF_STR( German ) ) PORT_DIPSETTING( 0x30, DEF_STR( Spanish ) ) - PORT_BIT (0x40, IP_ACTIVE_HIGH, IPT_UNUSED) /* POT1 */ - PORT_BIT (0x80, IP_ACTIVE_HIGH, IPT_UNUSED) /* POT0 */ + PORT_BIT (0x40, IP_ACTIVE_HIGH, IPT_UNUSED) // POT1 + PORT_BIT (0x80, IP_ACTIVE_HIGH, IPT_UNUSED) // POT0 PORT_START("DSW") PORT_DIPNAME( 0x30, 0x10, "Play Time" ) @@ -109,17 +329,17 @@ static INPUT_PORTS_START( skyraid ) PORT_DIPSETTING( 0x10, "80 Seconds" ) PORT_DIPSETTING( 0x20, "100 Seconds" ) PORT_DIPSETTING( 0x30, "120 Seconds" ) - PORT_DIPNAME( 0x40, 0x40, "DIP #5" ) /* must be OFF */ + PORT_DIPNAME( 0x40, 0x40, "DIP #5" ) // must be OFF PORT_DIPSETTING( 0x40, DEF_STR( Off )) PORT_DIPSETTING( 0x00, DEF_STR( On )) PORT_DIPNAME( 0x80, 0x00, "Extended Play" ) PORT_DIPSETTING( 0x80, DEF_STR( No )) PORT_DIPSETTING( 0x00, DEF_STR( Yes )) - /* coinage settings are insane, refer to the manual */ + // coinage settings are insane, refer to the manual PORT_START("COIN") - PORT_DIPNAME( 0x0F, 0x01, DEF_STR( Coinage )) /* dial */ + PORT_DIPNAME( 0x0F, 0x01, DEF_STR( Coinage )) // dial PORT_DIPSETTING( 0x00, "Mode 0" ) PORT_DIPSETTING( 0x01, "Mode 1" ) PORT_DIPSETTING( 0x02, "Mode 2" ) @@ -159,10 +379,10 @@ INPUT_PORTS_END static const gfx_layout skyraid_text_layout = { - 16, 8, /* width, height */ - 64, /* total */ - 1, /* planes */ - { 0 }, /* plane offsets */ + 16, 8, // width, height + 64, // total + 1, // planes + { 0 }, // plane offsets { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 @@ -176,22 +396,22 @@ static const gfx_layout skyraid_text_layout = static const gfx_layout skyraid_sprite_layout = { - 32, 32, /* width, height */ - 8, /* total */ - 2, /* planes */ - /* plane offsets */ + 32, 32, // width, height + 8, // total + 2, // planes + // plane offsets { 0, 1 }, { - 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, - 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, - 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, - 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, + 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, + 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, + 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e }, { - 0x000, 0x040, 0x080, 0x0C0, 0x100, 0x140, 0x180, 0x1C0, - 0x200, 0x240, 0x280, 0x2C0, 0x300, 0x340, 0x380, 0x3C0, - 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580, 0x5C0, - 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780, 0x7C0 + 0x000, 0x040, 0x080, 0x0c0, 0x100, 0x140, 0x180, 0x1c0, + 0x200, 0x240, 0x280, 0x2c0, 0x300, 0x340, 0x380, 0x3c0, + 0x400, 0x440, 0x480, 0x4c0, 0x500, 0x540, 0x580, 0x5c0, + 0x600, 0x640, 0x680, 0x6c0, 0x700, 0x740, 0x780, 0x7c0 }, 0x800 }; @@ -199,52 +419,52 @@ static const gfx_layout skyraid_sprite_layout = static const gfx_layout skyraid_missile_layout = { - 16, 16, /* width, height */ - 8, /* total */ - 1, /* planes */ - { 0 }, /* plane offsets */ + 16, 16, // width, height + 8, // total + 1, // planes + { 0 }, // plane offsets { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, - 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0 + 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 }, 0x100 }; static GFXDECODE_START( gfx_skyraid ) - GFXDECODE_ENTRY( "gfx1", 0, skyraid_text_layout, 18, 1 ) - GFXDECODE_ENTRY( "gfx2", 0, skyraid_sprite_layout, 8, 2 ) - GFXDECODE_ENTRY( "gfx3", 0, skyraid_missile_layout, 16, 1 ) + GFXDECODE_ENTRY( "chars", 0, skyraid_text_layout, 18, 1 ) + GFXDECODE_ENTRY( "sprites", 0, skyraid_sprite_layout, 8, 2 ) + GFXDECODE_ENTRY( "missiles", 0, skyraid_missile_layout, 16, 1 ) GFXDECODE_END void skyraid_state::skyraid(machine_config &config) { - /* basic machine hardware */ - M6502(config, m_maincpu, 12096000 / 12); - m_maincpu->set_addrmap(AS_PROGRAM, &skyraid_state::skyraid_map); + // basic machine hardware + M6502(config, m_maincpu, 12'096'000 / 12); + m_maincpu->set_addrmap(AS_PROGRAM, &skyraid_state::program_map); m_maincpu->set_vblank_int("screen", FUNC(skyraid_state::irq0_line_hold)); - WATCHDOG_TIMER(config, "watchdog").set_vblank_count("screen", 4); + WATCHDOG_TIMER(config, "watchdog").set_vblank_count(m_screen, 4); - /* video hardware */ - screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); - screen.set_refresh_hz(60); - screen.set_vblank_time(ATTOSECONDS_IN_USEC(22 * 1000000 / 15750)); - screen.set_size(512, 240); - screen.set_visarea(0, 511, 0, 239); - screen.set_screen_update(FUNC(skyraid_state::screen_update_skyraid)); - screen.set_palette(m_palette); + // video hardware + SCREEN(config, m_screen, SCREEN_TYPE_RASTER); + m_screen->set_refresh_hz(60); + m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(22 * 1'000'000 / 15'750)); + m_screen->set_size(512, 240); + m_screen->set_visarea(0, 511, 0, 239); + m_screen->set_screen_update(FUNC(skyraid_state::screen_update)); + m_screen->set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_skyraid); - PALETTE(config, m_palette, FUNC(skyraid_state::skyraid_palette), 20); + PALETTE(config, m_palette, FUNC(skyraid_state::palette), 20); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); DISCRETE(config, m_discrete, skyraid_discrete).add_route(ALL_OUTPUTS, "mono", 1.0); @@ -258,27 +478,29 @@ ROM_START( skyraid ) ROM_LOAD( "030594.d1", 0x7800, 0x800, CRC(27979e96) SHA1(55ffe3094c6764e6b99ee148e3dd730ca263fa3a) ) ROM_RELOAD( 0xF800, 0x800 ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* alpha numerics */ + ROM_REGION( 0x0200, "chars", 0 ) ROM_LOAD( "030598.h2", 0x0000, 0x200, CRC(2a7c5fa0) SHA1(93a79e5948dfcd9b6c2ff390e85a43f7a8cac327) ) - ROM_REGION( 0x0800, "gfx2", 0 ) /* sprites */ + ROM_REGION( 0x0800, "sprites", 0 ) ROM_LOAD( "030599.m7", 0x0000, 0x800, CRC(0cd179ea) SHA1(e3c763f76e6103e5909e7b5a979206b262d6e96a) ) - ROM_REGION( 0x0100, "gfx3", 0 ) /* missiles */ + ROM_REGION( 0x0100, "missiles", 0 ) ROM_LOAD_NIB_LOW ( "030597.n5", 0x0000, 0x100, CRC(319ff49c) SHA1(ff4d8b20436179910bf30c720d98df4678f683a9) ) ROM_LOAD_NIB_HIGH( "030596.m4", 0x0000, 0x100, CRC(30454ed0) SHA1(4216a54c13d9c4803f88f2de35cdee31290bb15e) ) - ROM_REGION( 0x0800, "user1", 0 ) /* terrain */ + ROM_REGION( 0x0800, "terrain", 0 ) ROM_LOAD_NIB_LOW ( "030584.j5", 0x0000, 0x800, CRC(81f6e8a5) SHA1(ad77b469ed0c9d5dfaa221ecf47d0db4a7f7ac91) ) ROM_LOAD_NIB_HIGH( "030585.k5", 0x0000, 0x800, CRC(b49bec3f) SHA1(b55d25230ec11c52e7b47d2c10194a49adbeb50a) ) - ROM_REGION( 0x0100, "user2", 0 ) /* trapezoid */ + ROM_REGION( 0x0100, "trapezoid", 0 ) ROM_LOAD_NIB_LOW ( "030582.a6", 0x0000, 0x100, CRC(0eacd595) SHA1(5469e312a1f522ce0a61054b50895a5b1a3f19ba) ) ROM_LOAD_NIB_HIGH( "030583.b6", 0x0000, 0x100, CRC(3edd6fbc) SHA1(0418ea78cf51e18c51087b43a41cd9e13aac0a16) ) - ROM_REGION( 0x0300, "proms", 0 ) - ROM_LOAD( "006559.c4", 0x0200, 0x100, CRC(5a8d0e42) SHA1(772220c4c24f18769696ddba26db2bc2e5b0909d) ) /* sync */ + ROM_REGION( 0x0100, "sync_prom", 0 ) + ROM_LOAD( "006559.c4", 0x0000, 0x100, CRC(5a8d0e42) SHA1(772220c4c24f18769696ddba26db2bc2e5b0909d) ) ROM_END +} // anonymous namespace + -GAME( 1978, skyraid, 0, skyraid, skyraid, skyraid_state, empty_init, ORIENTATION_FLIP_Y, "Atari", "Sky Raider", MACHINE_IMPERFECT_COLORS ) +GAME( 1978, skyraid, 0, skyraid, skyraid, skyraid_state, empty_init, ORIENTATION_FLIP_Y, "Atari", "Sky Raider", MACHINE_IMPERFECT_COLORS | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/atari/skyraid.h b/src/mame/atari/skyraid.h deleted file mode 100644 index 02b82b51883..00000000000 --- a/src/mame/atari/skyraid.h +++ /dev/null @@ -1,67 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Stefan Jokisch -#ifndef MAME_ATARI_SKYRAID_H -#define MAME_ATARI_SKYRAID_H - -#pragma once - -#include "sound/discrete.h" -#include "emupal.h" - -class skyraid_state : public driver_device -{ -public: - skyraid_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_pos_ram(*this, "pos_ram"), - m_alpha_num_ram(*this, "alpha_num_ram"), - m_obj_ram(*this, "obj_ram"), - m_discrete(*this, "discrete"), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette"), - m_led(*this, "led") - { } - - void skyraid(machine_config &config); - -private: - uint8_t skyraid_port_0_r(); - void skyraid_range_w(uint8_t data); - void skyraid_offset_w(uint8_t data); - void skyraid_scroll_w(uint8_t data); - virtual void machine_start() override; - virtual void video_start() override; - void skyraid_palette(palette_device &palette) const; - uint32_t screen_update_skyraid(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - void skyraid_sound_w(uint8_t data); - void draw_text(bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_terrain(bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_missiles(bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_trapezoid(bitmap_ind16& dst, bitmap_ind16& src); - - void skyraid_map(address_map &map); - - int m_analog_range = 0; - int m_analog_offset = 0; - - int m_scroll = 0; - - required_shared_ptr m_pos_ram; - required_shared_ptr m_alpha_num_ram; - required_shared_ptr m_obj_ram; - required_device m_discrete; - bitmap_ind16 m_helper; - - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_palette; - - output_finder<> m_led; -}; - -/*----------- defined in audio/skyraid.c -----------*/ -DISCRETE_SOUND_EXTERN( skyraid_discrete ); - -#endif // MAME_ATARI_SKYRAID_H diff --git a/src/mame/atari/skyraid_a.cpp b/src/mame/atari/skyraid_a.cpp index b0b0000e92e..ded9ca1f802 100644 --- a/src/mame/atari/skyraid_a.cpp +++ b/src/mame/atari/skyraid_a.cpp @@ -6,16 +6,9 @@ ************************************************************************/ #include "emu.h" -#include "skyraid.h" +#include "skyraid_a.h" -/* Discrete Sound Input Nodes */ -#define SKYRAID_PLANE_SWEEP_EN NODE_01 -#define SKYRAID_MISSILE_EN NODE_02 -#define SKYRAID_EXPLOSION_EN NODE_03 -#define SKYRAID_PLANE_ON_EN NODE_04 -#define SKYRAID_PLANE_ON__IC_E8 SKYRAID_PLANE_ON_EN -#define SKYRAID_ATTRACT_EN NODE_05 /* Discrete Sound Output Nodes */ #define SKYRAID_NOISE NODE_10 @@ -203,7 +196,7 @@ DISCRETE_SOUND_START( skyraid_discrete ) /* According to the schematics, Attract only clears the lower 8 bits. */ /* I may modify the noise module in the future to properly emulate this, */ /* but you will never hear the difference. */ - /* It only wrong for 8 cycles of the 555 while no sound is being generated. */ + /* It's only wrong for 8 cycles of the 555 while no sound is being generated. */ DISCRETE_LFSR_NOISE(SKYRAID_NOISE, /* IC F7, pin 13 */ 1, /* ENAB */ SKYRAID_ATTRACT_EN, /* RESET */ @@ -283,21 +276,3 @@ DISCRETE_SOUND_START( skyraid_discrete ) DISCRETE_CLAMP(NODE_95, NODE_94, -5, 12.0 - 1.5) DISCRETE_OUTPUT(NODE_95, 32700.0/8) DISCRETE_SOUND_END - - -void skyraid_state::skyraid_sound_w(uint8_t data) -{ - /* BIT0 => PLANE SWEEP */ - /* BIT1 => MISSILE */ - /* BIT2 => EXPLOSION */ - /* BIT3 => START LAMP */ - /* BIT4 => PLANE ON */ - /* BIT5 => ATTRACT */ - - m_discrete->write(SKYRAID_PLANE_SWEEP_EN, data & 0x01); - m_discrete->write(SKYRAID_MISSILE_EN, data & 0x02); - m_discrete->write(SKYRAID_EXPLOSION_EN, data & 0x04); - m_led = !BIT(data, 3); - m_discrete->write(SKYRAID_PLANE_ON_EN, data & 0x10); - m_discrete->write(SKYRAID_ATTRACT_EN, data & 0x20); -} diff --git a/src/mame/atari/skyraid_a.h b/src/mame/atari/skyraid_a.h new file mode 100644 index 00000000000..587bf2d0176 --- /dev/null +++ b/src/mame/atari/skyraid_a.h @@ -0,0 +1,22 @@ +// license:BSD-3-Clause +// copyright-holders:Derrick Renaud + +/*************************************************************************** + +Sky Raider Audio + +***************************************************************************/ + +#include "sound/discrete.h" + +// discrete sound input nodes + +#define SKYRAID_PLANE_SWEEP_EN NODE_01 +#define SKYRAID_MISSILE_EN NODE_02 +#define SKYRAID_EXPLOSION_EN NODE_03 +#define SKYRAID_PLANE_ON_EN NODE_04 +#define SKYRAID_PLANE_ON__IC_E8 SKYRAID_PLANE_ON_EN +#define SKYRAID_ATTRACT_EN NODE_05 + + +DISCRETE_SOUND_EXTERN( skyraid_discrete ); diff --git a/src/mame/atari/skyraid_v.cpp b/src/mame/atari/skyraid_v.cpp deleted file mode 100644 index 05004185b16..00000000000 --- a/src/mame/atari/skyraid_v.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Stefan Jokisch -/*************************************************************************** - -Atari Sky Raider video emulation - -***************************************************************************/ - -#include "emu.h" -#include "skyraid.h" - - -void skyraid_state::video_start() -{ - m_helper.allocate(128, 240); -} - - -void skyraid_state::draw_text(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - const uint8_t* p = m_alpha_num_ram; - - int i; - - for (i = 0; i < 4; i++) - { - int x; - int y; - - y = 136 + 16 * (i ^ 1); - - for (x = 0; x < bitmap.width(); x += 16) - m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, *p++, 0, 0, 0, x, y, 0); - } -} - - -void skyraid_state::draw_terrain(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - const uint8_t* p = memregion("user1")->base(); - - int x; - int y; - - for (y = 0; y < bitmap.height(); y++) - { - int offset = (16 * m_scroll + 16 * ((y + 1) / 2)) & 0x7FF; - - x = 0; - - while (x < bitmap.width()) - { - uint8_t val = p[offset++]; - - int color = val / 32; - int count = val % 32; - - rectangle r(x, x + 31 - count, y, y+ 1); - - bitmap.fill(color, r); - - x += 32 - count; - } - } -} - - -void skyraid_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - int i; - - for (i = 0; i < 4; i++) - { - int code = m_obj_ram[8 + 2 * i + 0] & 15; - int flag = m_obj_ram[8 + 2 * i + 1] & 15; - int vert = m_pos_ram[8 + 2 * i + 0]; - int horz = m_pos_ram[8 + 2 * i + 1]; - - vert -= 31; - - if (flag & 1) - m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, - code ^ 15, code >> 3, 0, 0, - horz / 2, vert, 2); - } -} - - -void skyraid_state::draw_missiles(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - int i; - - /* hardware is restricted to one sprite per scanline */ - - for (i = 0; i < 4; i++) - { - int code = m_obj_ram[2 * i + 0] & 15; - int vert = m_pos_ram[2 * i + 0]; - int horz = m_pos_ram[2 * i + 1]; - - vert -= 15; - horz -= 31; - - m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, - code ^ 15, 0, 0, 0, - horz / 2, vert, 0); - } -} - - -void skyraid_state::draw_trapezoid(bitmap_ind16& dst, bitmap_ind16& src) -{ - uint8_t const *const p = memregion("user2")->base(); - - for (int y = 0; y < dst.height(); y++) - { - uint16_t const *const pSrc = &src.pix(y); - uint16_t *const pDst = &dst.pix(y); - - int const x1 = 0x000 + p[(y & ~1) + 0]; - int const x2 = 0x100 + p[(y & ~1) + 1]; - - for (int x = x1; x < x2; x++) - pDst[x] = pSrc[128 * (x - x1) / (x2 - x1)]; - } -} - - -uint32_t skyraid_state::screen_update_skyraid(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - bitmap.fill(0, cliprect); - - rectangle helper_clip = cliprect; - helper_clip &= m_helper.cliprect(); - - draw_terrain(m_helper, helper_clip); - draw_sprites(m_helper, helper_clip); - draw_missiles(m_helper, helper_clip); - draw_trapezoid(bitmap, m_helper); - draw_text(bitmap, cliprect); - return 0; -} diff --git a/src/mame/atari/sprint2.cpp b/src/mame/atari/sprint2.cpp index 5ad67136259..706b44deeec 100644 --- a/src/mame/atari/sprint2.cpp +++ b/src/mame/atari/sprint2.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Mike Balfour + /*************************************************************************** Atari Sprint 2 hardware @@ -20,17 +21,275 @@ ***************************************************************************/ #include "emu.h" -#include "sprint2.h" + +#include "sprint2_a.h" #include "cpu/m6502/m6502.h" +#include "machine/74259.h" +#include "machine/watchdog.h" #include "sound/discrete.h" + +#include "emupal.h" +#include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +namespace { #define MACHINE_IS_SPRINT1 (m_game == 1) #define MACHINE_IS_SPRINT2 (m_game == 2) #define MACHINE_IS_DOMINOS (m_game == 3) +class sprint2_state : public driver_device +{ +public: + sprint2_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_video_ram(*this, "video_ram"), + m_maincpu(*this, "maincpu"), + m_watchdog(*this, "watchdog"), + m_outlatch(*this, "outlatch"), + m_discrete(*this, "discrete"), + m_gfxdecode(*this, "gfxdecode"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_in(*this, { "INA", "INB" }), + m_dials(*this, "DIAL_P%u", 1U), + m_gears(*this, "GEAR_P%u", 1U), + m_dsw(*this, "DSW"), + m_gear_sel(*this, "P%ugear", 1U) + { } + + void sprint1(machine_config &config); + void sprint2(machine_config &config); + void dominos4(machine_config &config); + void dominos(machine_config &config); + + void init_sprint1(); + void init_sprint2(); + void init_dominos(); + void init_dominos4(); + +protected: + virtual void machine_start() override; + virtual void video_start() override; + +private: + required_shared_ptr m_video_ram; + required_device m_maincpu; + required_device m_watchdog; + required_device m_outlatch; + required_device m_discrete; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + required_ioport_array<2> m_in; + optional_ioport_array<2> m_dials, m_gears; + required_ioport m_dsw; + output_finder<2> m_gear_sel; + + uint8_t m_steering[2]{}; + uint8_t m_gear[2]{}; + uint8_t m_game = 0; + uint8_t m_dial[2]{}; + tilemap_t* m_bg_tilemap = nullptr; + bitmap_ind16 m_helper; + uint8_t m_collision[2]{}; + + uint8_t wram_r(offs_t offset); + uint8_t dip_r(offs_t offset); + uint8_t input_a_r(offs_t offset); + uint8_t input_b_r(offs_t offset); + uint8_t sync_r(); + template uint8_t steering_r(); + template void steering_reset_w(uint8_t data); + void wram_w(offs_t offset, uint8_t data); + void output_latch_w(offs_t offset, uint8_t data); + void video_ram_w(offs_t offset, uint8_t data); + void noise_reset_w(uint8_t data); + TILE_GET_INFO_MEMBER(get_tile_info); + void palette(palette_device &palette) const; + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank); + INTERRUPT_GEN_MEMBER(irq); + uint8_t collision_check(rectangle& rect); + inline int get_sprite_code(int n); + inline int get_sprite_x(int n); + inline int get_sprite_y(int n); + uint8_t service_mode(); + + void main_map(address_map &map); +}; + + +// video + +void sprint2_state::palette(palette_device &palette) const +{ + palette.set_indirect_color(0, rgb_t(0x00, 0x00, 0x00)); + palette.set_indirect_color(1, rgb_t(0x5b, 0x5b, 0x5b)); + palette.set_indirect_color(2, rgb_t(0xa4, 0xa4, 0xa4)); + palette.set_indirect_color(3, rgb_t(0xff, 0xff, 0xff)); + + palette.set_pen_indirect(0x0, 1); // black playfield + palette.set_pen_indirect(0x1, 0); + palette.set_pen_indirect(0x2, 1); // white playfield + palette.set_pen_indirect(0x3, 3); + + palette.set_pen_indirect(0x4, 1); // car #1 + palette.set_pen_indirect(0x5, 3); + palette.set_pen_indirect(0x6, 1); // car #2 + palette.set_pen_indirect(0x7, 0); + palette.set_pen_indirect(0x8, 1); // car #3 + palette.set_pen_indirect(0x9, 2); + palette.set_pen_indirect(0xa, 1); // car #4 + palette.set_pen_indirect(0xb, 2); +} + + +TILE_GET_INFO_MEMBER(sprint2_state::get_tile_info) +{ + uint8_t const code = m_video_ram[tile_index]; + + tileinfo.set(0, code & 0x3f, code >> 7, 0); +} + + +void sprint2_state::video_start() +{ + m_screen->register_screen_bitmap(m_helper); + + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint2_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32); +} + + +void sprint2_state::video_ram_w(offs_t offset, uint8_t data) +{ + m_video_ram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset); +} + + +uint8_t sprint2_state::collision_check(rectangle& rect) +{ + uint8_t data = 0; + + for (int y = rect.top(); y <= rect.bottom(); y++) + for (int x = rect.left(); x <= rect.right(); x++) + { + uint16_t const a = m_palette->pen_indirect(m_helper.pix(y, x)); + + if (a == 0) + data |= 0x40; + + if (a == 3) + data |= 0x80; + } + + return data; +} + + +inline int sprint2_state::get_sprite_code(int n) +{ + return m_video_ram[0x398 + 2 * n + 1] >> 3; +} +inline int sprint2_state::get_sprite_x(int n) +{ + return 2 * (248 - m_video_ram[0x390 + 1 * n]); +} +inline int sprint2_state::get_sprite_y(int n) +{ + return 1 * (248 - m_video_ram[0x398 + 2 * n]); +} + + +uint32_t sprint2_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + m_bg_tilemap->draw(*m_screen, bitmap, cliprect, 0, 0); + + // draw the sprites + + for (int i = 0; i < 4; i++) + { + m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, + get_sprite_code(i), + i, + 0, 0, + get_sprite_x(i), + get_sprite_y(i), 0); + } + return 0; +} + + +WRITE_LINE_MEMBER(sprint2_state::screen_vblank) +{ + // rising edge + if (state) + { + const rectangle &visarea = m_screen->visible_area(); + + /* + * Collisions are detected for both player cars: + * + * D7 => m_collision w/ white playfield + * D6 => m_collision w/ black playfield or another car + * + */ + + for (int i = 0; i < 2; i++) + { + rectangle rect( + get_sprite_x(i), + get_sprite_x(i) + m_gfxdecode->gfx(1)->width() - 1, + get_sprite_y(i), + get_sprite_y(i) + m_gfxdecode->gfx(1)->height() - 1); + rect &= visarea; + + // check for sprite-tilemap collisions + + m_bg_tilemap->draw(*m_screen, m_helper, rect, 0, 0); + + m_gfxdecode->gfx(1)->transpen(m_helper, rect, + get_sprite_code(i), + 0, + 0, 0, + get_sprite_x(i), + get_sprite_y(i), 1); + + m_collision[i] |= collision_check(rect); + + // check for sprite-sprite collisions + + for (int j = 0; j < 4; j++) + if (j != i) + { + m_gfxdecode->gfx(1)->transpen(m_helper, rect, + get_sprite_code(j), + 1, + 0, 0, + get_sprite_x(j), + get_sprite_y(j), 0); + } + + m_gfxdecode->gfx(1)->transpen(m_helper, rect, + get_sprite_code(i), + 0, + 0, 0, + get_sprite_x(i), + get_sprite_y(i), 1); + + m_collision[i] |= collision_check(rect); + } + } +} + + +// machine + void sprint2_state::machine_start() { m_gear_sel.resolve(); @@ -63,7 +322,7 @@ void sprint2_state::init_dominos4() uint8_t sprint2_state::service_mode() { - uint8_t v = m_in[1]->read(); + uint8_t const v = m_in[1]->read(); if (MACHINE_IS_SPRINT1) { @@ -90,7 +349,7 @@ INTERRUPT_GEN_MEMBER(sprint2_state::irq) { for (int i = 0; i < 2; i++) { - signed char delta = m_dials[i]->read() - m_dial[i]; + signed char const delta = m_dials[i]->read() - m_dial[i]; if (delta < 0) { @@ -140,7 +399,7 @@ uint8_t sprint2_state::dip_r(offs_t offset) } -uint8_t sprint2_state::input_A_r(offs_t offset) +uint8_t sprint2_state::input_a_r(offs_t offset) { uint8_t val = m_in[0]->read(); @@ -158,7 +417,7 @@ uint8_t sprint2_state::input_A_r(offs_t offset) } -uint8_t sprint2_state::input_B_r(offs_t offset) +uint8_t sprint2_state::input_b_r(offs_t offset) { uint8_t val = m_in[1]->read(); @@ -230,8 +489,8 @@ void sprint2_state::main_map(address_map &map) map.global_mask(0x3fff); map(0x0000, 0x03ff).rw(FUNC(sprint2_state::wram_r), FUNC(sprint2_state::wram_w)); map(0x0400, 0x07ff).ram().w(FUNC(sprint2_state::video_ram_w)).share(m_video_ram); - map(0x0818, 0x081f).r(FUNC(sprint2_state::input_A_r)); - map(0x0828, 0x082f).r(FUNC(sprint2_state::input_B_r)); + map(0x0818, 0x081f).r(FUNC(sprint2_state::input_a_r)); + map(0x0828, 0x082f).r(FUNC(sprint2_state::input_b_r)); map(0x0830, 0x0837).r(FUNC(sprint2_state::dip_r)); map(0x0840, 0x087f).portr("COIN"); map(0x0880, 0x08bf).r(FUNC(sprint2_state::steering_r<0>)); @@ -323,7 +582,7 @@ static INPUT_PORTS_START( sprint2 ) INPUT_PORTS_END - static INPUT_PORTS_START( sprint1 ) +static INPUT_PORTS_START( sprint1 ) PORT_START("DSW") PORT_DIPNAME( 0x01, 0x00, "Change Track" ) PORT_DIPLOCATION("SW1:1") PORT_DIPSETTING( 0x01, "Every Lap" ) @@ -680,9 +939,12 @@ ROM_START( dominos4 ) // built from original Atari source code ROM_LOAD( "6401-01.e2", 0x0100, 0x0020, CRC(857df8db) SHA1(06313d5bde03220b2bc313d18e50e4bb1d0cfbbb) ) // address ROM_END -GAME( 1978, sprint1, 0, sprint1, sprint1, sprint2_state, init_sprint1, ROT0, "Atari (Kee Games)", "Sprint 1", MACHINE_SUPPORTS_SAVE ) -GAME( 1976, sprint2, sprint1, sprint2, sprint2, sprint2_state, init_sprint2, ROT0, "Atari (Kee Games)", "Sprint 2 (set 1)", MACHINE_SUPPORTS_SAVE ) -GAME( 1976, sprint2a, sprint1, sprint2, sprint2, sprint2_state, init_sprint2, ROT0, "Atari (Kee Games)", "Sprint 2 (set 2)", MACHINE_SUPPORTS_SAVE ) -GAME( 1976, sprint2h, sprint1, sprint2, sprint2, sprint2_state, init_sprint2, ROT0, "hack", "Sprint 2 (color kit, Italy)", MACHINE_WRONG_COLORS | MACHINE_SUPPORTS_SAVE ) // Italian hack, supposedly is color instead of b/w? how? -GAME( 1977, dominos, 0, dominos, dominos, sprint2_state, init_dominos, ROT0, "Atari", "Dominos", MACHINE_SUPPORTS_SAVE ) -GAME( 1977, dominos4, dominos, dominos4,dominos4,sprint2_state, init_dominos4,ROT0, "Atari", "Dominos 4 (Cocktail)", MACHINE_SUPPORTS_SAVE ) +} // anonymous namespace + + +GAME( 1978, sprint1, 0, sprint1, sprint1, sprint2_state, init_sprint1, ROT0, "Atari (Kee Games)", "Sprint 1", MACHINE_SUPPORTS_SAVE ) +GAME( 1976, sprint2, sprint1, sprint2, sprint2, sprint2_state, init_sprint2, ROT0, "Atari (Kee Games)", "Sprint 2 (set 1)", MACHINE_SUPPORTS_SAVE ) +GAME( 1976, sprint2a, sprint1, sprint2, sprint2, sprint2_state, init_sprint2, ROT0, "Atari (Kee Games)", "Sprint 2 (set 2)", MACHINE_SUPPORTS_SAVE ) +GAME( 1976, sprint2h, sprint1, sprint2, sprint2, sprint2_state, init_sprint2, ROT0, "hack", "Sprint 2 (color kit, Italy)", MACHINE_WRONG_COLORS | MACHINE_SUPPORTS_SAVE ) // Italian hack, supposedly is color instead of b/w? how? +GAME( 1977, dominos, 0, dominos, dominos, sprint2_state, init_dominos, ROT0, "Atari", "Dominos", MACHINE_SUPPORTS_SAVE ) +GAME( 1977, dominos4, dominos, dominos4,dominos4,sprint2_state, init_dominos4,ROT0, "Atari", "Dominos 4 (Cocktail)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/atari/sprint2.h b/src/mame/atari/sprint2.h deleted file mode 100644 index 2fd49d2e16d..00000000000 --- a/src/mame/atari/sprint2.h +++ /dev/null @@ -1,121 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mike Balfour -/************************************************************************* - - Atari Sprint hardware - -*************************************************************************/ -#ifndef MAME_ATARI_SPRINT2_H -#define MAME_ATARI_SPRINT2_H - -#pragma once - -#include "machine/74259.h" -#include "machine/watchdog.h" -#include "sound/discrete.h" -#include "emupal.h" -#include "screen.h" -#include "tilemap.h" - -// Discrete Sound Input Nodes -#define SPRINT2_SKIDSND1_EN NODE_01 -#define SPRINT2_SKIDSND2_EN NODE_02 -#define SPRINT2_MOTORSND1_DATA NODE_03 -#define SPRINT2_MOTORSND2_DATA NODE_04 -#define SPRINT2_CRASHSND_DATA NODE_05 -#define SPRINT2_ATTRACT_EN NODE_06 -#define SPRINT2_NOISE_RESET NODE_07 - -#define DOMINOS_FREQ_DATA SPRINT2_MOTORSND1_DATA -#define DOMINOS_AMP_DATA SPRINT2_CRASHSND_DATA -#define DOMINOS_TUMBLE_EN SPRINT2_SKIDSND1_EN -#define DOMINOS_ATTRACT_EN SPRINT2_ATTRACT_EN - - -class sprint2_state : public driver_device -{ -public: - sprint2_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_video_ram(*this, "video_ram"), - m_maincpu(*this, "maincpu"), - m_watchdog(*this, "watchdog"), - m_outlatch(*this, "outlatch"), - m_discrete(*this, "discrete"), - m_gfxdecode(*this, "gfxdecode"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_in(*this, { "INA", "INB" }), - m_dials(*this, "DIAL_P%u", 1U), - m_gears(*this, "GEAR_P%u", 1U), - m_dsw(*this, "DSW"), - m_gear_sel(*this, "P%ugear", 1U) - { } - - void sprint1(machine_config &config); - void sprint2(machine_config &config); - void dominos4(machine_config &config); - void dominos(machine_config &config); - - void init_sprint1(); - void init_sprint2(); - void init_dominos(); - void init_dominos4(); - -protected: - virtual void machine_start() override; - virtual void video_start() override; - -private: - required_shared_ptr m_video_ram; - required_device m_maincpu; - required_device m_watchdog; - required_device m_outlatch; - required_device m_discrete; - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - required_ioport_array<2> m_in; - optional_ioport_array<2> m_dials, m_gears; - required_ioport m_dsw; - output_finder<2> m_gear_sel; - - uint8_t m_steering[2]{}; - uint8_t m_gear[2]{}; - uint8_t m_game = 0; - uint8_t m_dial[2]{}; - tilemap_t* m_bg_tilemap = nullptr; - bitmap_ind16 m_helper; - uint8_t m_collision[2]{}; - - uint8_t wram_r(offs_t offset); - uint8_t dip_r(offs_t offset); - uint8_t input_A_r(offs_t offset); - uint8_t input_B_r(offs_t offset); - uint8_t sync_r(); - template uint8_t steering_r(); - template void steering_reset_w(uint8_t data); - void wram_w(offs_t offset, uint8_t data); - void output_latch_w(offs_t offset, uint8_t data); - void video_ram_w(offs_t offset, uint8_t data); - void noise_reset_w(uint8_t data); - TILE_GET_INFO_MEMBER(get_tile_info); - void palette(palette_device &palette) const; - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank); - INTERRUPT_GEN_MEMBER(irq); - uint8_t collision_check(rectangle& rect); - inline int get_sprite_code(int n); - inline int get_sprite_x(int n); - inline int get_sprite_y(int n); - uint8_t service_mode(); - - void main_map(address_map &map); -}; - -//----------- defined in audio/sprint2.cpp ----------- -DISCRETE_SOUND_EXTERN( sprint2_discrete ); -DISCRETE_SOUND_EXTERN( sprint1_discrete ); -DISCRETE_SOUND_EXTERN( dominos_discrete ); - -#endif // MAME_ATARI_SPRINT2_H diff --git a/src/mame/atari/sprint2_a.cpp b/src/mame/atari/sprint2_a.cpp index 95fb6ee3eac..310eabba142 100644 --- a/src/mame/atari/sprint2_a.cpp +++ b/src/mame/atari/sprint2_a.cpp @@ -2,11 +2,12 @@ // copyright-holders:Hans Andersson /************************************************************************* - audio\sprint2.cpp + atari\sprint2_a.cpp *************************************************************************/ #include "emu.h" -#include "sprint2.h" + +#include "sprint2_a.h" /************************************************************************/ diff --git a/src/mame/atari/sprint2_a.h b/src/mame/atari/sprint2_a.h new file mode 100644 index 00000000000..fe3de798aa5 --- /dev/null +++ b/src/mame/atari/sprint2_a.h @@ -0,0 +1,30 @@ +// license:BSD-3-Clause +// copyright-holders:Hans Andersson + +/*************************************************************************** + +Sprint 2 / Sprint 1 / Dominos Audio + +***************************************************************************/ + +#include "sound/discrete.h" + +// discrete sound input nodes + +#define SPRINT2_SKIDSND1_EN NODE_01 +#define SPRINT2_SKIDSND2_EN NODE_02 +#define SPRINT2_MOTORSND1_DATA NODE_03 +#define SPRINT2_MOTORSND2_DATA NODE_04 +#define SPRINT2_CRASHSND_DATA NODE_05 +#define SPRINT2_ATTRACT_EN NODE_06 +#define SPRINT2_NOISE_RESET NODE_07 + +#define DOMINOS_FREQ_DATA SPRINT2_MOTORSND1_DATA +#define DOMINOS_AMP_DATA SPRINT2_CRASHSND_DATA +#define DOMINOS_TUMBLE_EN SPRINT2_SKIDSND1_EN +#define DOMINOS_ATTRACT_EN SPRINT2_ATTRACT_EN + + +DISCRETE_SOUND_EXTERN( sprint2_discrete ); +DISCRETE_SOUND_EXTERN( sprint1_discrete ); +DISCRETE_SOUND_EXTERN( dominos_discrete ); diff --git a/src/mame/atari/sprint2_v.cpp b/src/mame/atari/sprint2_v.cpp deleted file mode 100644 index 1f00c6cc3fe..00000000000 --- a/src/mame/atari/sprint2_v.cpp +++ /dev/null @@ -1,172 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mike Balfour -/*************************************************************************** - - Atari Sprint 2 video emulation - -***************************************************************************/ - -#include "emu.h" -#include "sprint2.h" - - -void sprint2_state::palette(palette_device &palette) const -{ - palette.set_indirect_color(0, rgb_t(0x00, 0x00, 0x00)); - palette.set_indirect_color(1, rgb_t(0x5b, 0x5b, 0x5b)); - palette.set_indirect_color(2, rgb_t(0xa4, 0xa4, 0xa4)); - palette.set_indirect_color(3, rgb_t(0xff, 0xff, 0xff)); - - palette.set_pen_indirect(0x0, 1); // black playfield - palette.set_pen_indirect(0x1, 0); - palette.set_pen_indirect(0x2, 1); // white playfield - palette.set_pen_indirect(0x3, 3); - - palette.set_pen_indirect(0x4, 1); // car #1 - palette.set_pen_indirect(0x5, 3); - palette.set_pen_indirect(0x6, 1); // car #2 - palette.set_pen_indirect(0x7, 0); - palette.set_pen_indirect(0x8, 1); // car #3 - palette.set_pen_indirect(0x9, 2); - palette.set_pen_indirect(0xa, 1); // car #4 - palette.set_pen_indirect(0xb, 2); -} - - -TILE_GET_INFO_MEMBER(sprint2_state::get_tile_info) -{ - uint8_t code = m_video_ram[tile_index]; - - tileinfo.set(0, code & 0x3f, code >> 7, 0); -} - - -void sprint2_state::video_start() -{ - m_screen->register_screen_bitmap(m_helper); - - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint2_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32); -} - - -void sprint2_state::video_ram_w(offs_t offset, uint8_t data) -{ - m_video_ram[offset] = data; - m_bg_tilemap->mark_tile_dirty(offset); -} - - -uint8_t sprint2_state::collision_check(rectangle& rect) -{ - uint8_t data = 0; - - for (int y = rect.top(); y <= rect.bottom(); y++) - for (int x = rect.left(); x <= rect.right(); x++) - { - uint16_t const a = m_palette->pen_indirect(m_helper.pix(y, x)); - - if (a == 0) - data |= 0x40; - - if (a == 3) - data |= 0x80; - } - - return data; -} - - -inline int sprint2_state::get_sprite_code(int n) -{ - return m_video_ram[0x398 + 2 * n + 1] >> 3; -} -inline int sprint2_state::get_sprite_x(int n) -{ - return 2 * (248 - m_video_ram[0x390 + 1 * n]); -} -inline int sprint2_state::get_sprite_y(int n) -{ - return 1 * (248 - m_video_ram[0x398 + 2 * n]); -} - - -uint32_t sprint2_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - m_bg_tilemap->draw(*m_screen, bitmap, cliprect, 0, 0); - - // draw the sprites - - for (int i = 0; i < 4; i++) - { - m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, - get_sprite_code(i), - i, - 0, 0, - get_sprite_x(i), - get_sprite_y(i), 0); - } - return 0; -} - - -WRITE_LINE_MEMBER(sprint2_state::screen_vblank) -{ - // rising edge - if (state) - { - const rectangle &visarea = m_screen->visible_area(); - - /* - * Collisions are detected for both player cars: - * - * D7 => m_collision w/ white playfield - * D6 => m_collision w/ black playfield or another car - * - */ - - for (int i = 0; i < 2; i++) - { - rectangle rect( - get_sprite_x(i), - get_sprite_x(i) + m_gfxdecode->gfx(1)->width() - 1, - get_sprite_y(i), - get_sprite_y(i) + m_gfxdecode->gfx(1)->height() - 1); - rect &= visarea; - - // check for sprite-tilemap collisions - - m_bg_tilemap->draw(*m_screen, m_helper, rect, 0, 0); - - m_gfxdecode->gfx(1)->transpen(m_helper,rect, - get_sprite_code(i), - 0, - 0, 0, - get_sprite_x(i), - get_sprite_y(i), 1); - - m_collision[i] |= collision_check(rect); - - // check for sprite-sprite collisions - - for (int j = 0; j < 4; j++) - if (j != i) - { - m_gfxdecode->gfx(1)->transpen(m_helper,rect, - get_sprite_code(j), - 1, - 0, 0, - get_sprite_x(j), - get_sprite_y(j), 0); - } - - m_gfxdecode->gfx(1)->transpen(m_helper,rect, - get_sprite_code(i), - 0, - 0, 0, - get_sprite_x(i), - get_sprite_y(i), 1); - - m_collision[i] |= collision_check(rect); - } - } -} diff --git a/src/mame/atari/sprint8.cpp b/src/mame/atari/sprint8.cpp index b0d07bcb740..1f9c6561843 100644 --- a/src/mame/atari/sprint8.cpp +++ b/src/mame/atari/sprint8.cpp @@ -7,23 +7,276 @@ Atari Sprint 8 driver ***************************************************************************/ #include "emu.h" -#include "sprint8.h" + +#include "sprint8_a.h" + #include "cpu/m6800/m6800.h" +#include "machine/74259.h" +#include "machine/timer.h" +#include "sound/discrete.h" + +#include "emupal.h" +#include "screen.h" +#include "speaker.h" +#include "tilemap.h" + + +namespace { + +class sprint8_state : public driver_device +{ +public: + sprint8_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_gfxdecode(*this, "gfxdecode"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_discrete(*this, "discrete"), + m_video_ram(*this, "video_ram"), + m_pos_h_ram(*this, "pos_h_ram"), + m_pos_v_ram(*this, "pos_v_ram"), + m_pos_d_ram(*this, "pos_d_ram"), + m_in(*this, "P%u", 1U), + m_dial(*this, "DIAL%u", 1U) + { } + + void sprint8(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + virtual void video_start() override; + +private: + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + required_device m_discrete; + + required_shared_ptr m_video_ram; + required_shared_ptr m_pos_h_ram; + required_shared_ptr m_pos_v_ram; + required_shared_ptr m_pos_d_ram; + + required_ioport_array<8> m_in; + required_ioport_array<8> m_dial; + + uint8_t m_steering[8]{}; + bool m_collision_reset = false; + uint8_t m_collision_index = 0; + uint8_t m_prev_dial[8]{}; + bool m_team = false; + + tilemap_t* m_tilemap[2]{}; + bitmap_ind16 m_helper[2]; + emu_timer *m_collision_timer = nullptr; + + uint8_t collision_r(); + uint8_t input_r(offs_t offset); + void lockout_w(offs_t offset, uint8_t data); + DECLARE_WRITE_LINE_MEMBER(int_reset_w); + DECLARE_WRITE_LINE_MEMBER(team_w); + void video_ram_w(offs_t offset, uint8_t data); + + void palette(palette_device &palette) const; + + TILE_GET_INFO_MEMBER(get_tile_info1); + TILE_GET_INFO_MEMBER(get_tile_info2); + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank); + TIMER_CALLBACK_MEMBER(collision_callback); + TIMER_DEVICE_CALLBACK_MEMBER(input_callback); + + void set_pens(); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void program_map(address_map &map); +}; + + +// video + +void sprint8_state::palette(palette_device &palette) const +{ + for (int i = 0; i < 0x10; i++) + { + palette.set_pen_indirect(2 * i + 0, 0x10); + palette.set_pen_indirect(2 * i + 1, i); + } + + palette.set_pen_indirect(0x20, 0x10); + palette.set_pen_indirect(0x21, 0x10); + palette.set_pen_indirect(0x22, 0x10); + palette.set_pen_indirect(0x23, 0x11); +} + + +void sprint8_state::set_pens() +{ + for (int i = 0; i < 0x10; i += 8) + { + if (m_team) + { + m_palette->set_indirect_color(i + 0, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(i + 1, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(i + 2, rgb_t(0xff, 0xff, 0x00)); // yellow + m_palette->set_indirect_color(i + 3, rgb_t(0x00, 0xff, 0x00)); // green + m_palette->set_indirect_color(i + 4, rgb_t(0xff, 0x00, 0xff)); // magenta + m_palette->set_indirect_color(i + 5, rgb_t(0xe0, 0xc0, 0x70)); // puce + m_palette->set_indirect_color(i + 6, rgb_t(0x00, 0xff, 0xff)); // cyan + m_palette->set_indirect_color(i + 7, rgb_t(0xff, 0xaa, 0xaa)); // pink + } + else + { + m_palette->set_indirect_color(i + 0, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(i + 1, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(i + 2, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(i + 3, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(i + 4, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(i + 5, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(i + 6, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(i + 7, rgb_t(0x00, 0x00, 0xff)); // blue + } + } + + m_palette->set_indirect_color(0x10, rgb_t(0x00, 0x00, 0x00)); + m_palette->set_indirect_color(0x11, rgb_t(0xff, 0xff, 0xff)); +} + + +TILE_GET_INFO_MEMBER(sprint8_state::get_tile_info1) +{ + uint8_t const code = m_video_ram[tile_index]; + + int color = 0; + + if ((code & 0x30) != 0x30) // ? + color = 17; + else + { + if ((tile_index + 1) & 0x010) + color |= 1; + if (code & 0x80) + color |= 2; + if (tile_index & 0x200) + color |= 4; + } + + tileinfo.set(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0); +} -void sprint8_state::set_collision(int n) + +TILE_GET_INFO_MEMBER(sprint8_state::get_tile_info2) +{ + uint8_t const code = m_video_ram[tile_index]; + + int color = 0; + + if ((code & 0x38) != 0x28) + color = 16; + else + color = 17; + + tileinfo.set(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0); +} + + +void sprint8_state::video_ram_w(offs_t offset, uint8_t data) +{ + m_video_ram[offset] = data; + m_tilemap[0]->mark_tile_dirty(offset); + m_tilemap[1]->mark_tile_dirty(offset); +} + + +void sprint8_state::video_start() +{ + m_screen->register_screen_bitmap(m_helper[0]); + m_screen->register_screen_bitmap(m_helper[1]); + + m_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint8_state::get_tile_info1)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32); + m_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint8_state::get_tile_info2)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32); + + m_tilemap[0]->set_scrolly(0, +24); + m_tilemap[1]->set_scrolly(0, +24); + + m_collision_timer = timer_alloc(FUNC(sprint8_state::collision_callback), this); +} + + +void sprint8_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int i = 0; i < 16; i++) + { + uint8_t const code = m_pos_d_ram[i]; + + int x = m_pos_h_ram[i]; + int const y = m_pos_v_ram[i]; + + if (code & 0x80) + x |= 0x100; + + m_gfxdecode->gfx(2)->transpen(bitmap, cliprect, + code ^ 7, + i, + !(code & 0x10), !(code & 0x08), + 496 - x, y - 31, 0); + } +} + + +TIMER_CALLBACK_MEMBER(sprint8_state::collision_callback) { if (!m_collision_reset) { m_maincpu->set_input_line(0, ASSERT_LINE); - m_collision_index = n; + m_collision_index = param; } } +uint32_t sprint8_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + set_pens(); + m_tilemap[0]->draw(screen, bitmap, cliprect, 0, 0); + draw_sprites(bitmap, cliprect); + return 0; +} + + +WRITE_LINE_MEMBER(sprint8_state::screen_vblank) +{ + // rising edge + if (state) + { + const rectangle &visarea = m_screen->visible_area(); + + m_tilemap[1]->draw(*m_screen, m_helper[1], visarea, 0, 0); + + m_helper[0].fill(0x20, visarea); + + draw_sprites(m_helper[0], visarea); + + for (int y = visarea.top(); y <= visarea.bottom(); y++) + { + uint16_t const *const p1 = &m_helper[0].pix(y); + uint16_t const *const p2 = &m_helper[1].pix(y); + + for (int x = visarea.left(); x <= visarea.right(); x++) + if (p1[x] != 0x20 && p2[x] == 0x23) + m_collision_timer->adjust(m_screen->time_until_pos(y + 24, x), m_palette->pen_indirect(p1[x])); + } + } +} + + +// machine + TIMER_DEVICE_CALLBACK_MEMBER(sprint8_state::input_callback) { for (int i = 0; i < 8; i++) @@ -96,22 +349,22 @@ WRITE_LINE_MEMBER(sprint8_state::team_w) } -void sprint8_state::sprint8_map(address_map &map) +void sprint8_state::program_map(address_map &map) { map(0x0000, 0x00ff).ram(); - map(0x1800, 0x1bff).ram().w(FUNC(sprint8_state::video_ram_w)).share("video_ram"); + map(0x1800, 0x1bff).ram().w(FUNC(sprint8_state::video_ram_w)).share(m_video_ram); map(0x1c00, 0x1c00).r(FUNC(sprint8_state::collision_r)); map(0x1c01, 0x1c08).r(FUNC(sprint8_state::input_r)); map(0x1c09, 0x1c09).portr("IN0"); map(0x1c0a, 0x1c0a).portr("IN1"); map(0x1c0f, 0x1c0f).portr("VBLANK"); - map(0x1c00, 0x1c0f).writeonly().share("pos_h_ram"); - map(0x1c10, 0x1c1f).writeonly().share("pos_v_ram"); - map(0x1c20, 0x1c2f).writeonly().share("pos_d_ram"); + map(0x1c00, 0x1c0f).writeonly().share(m_pos_h_ram); + map(0x1c10, 0x1c1f).writeonly().share(m_pos_v_ram); + map(0x1c20, 0x1c2f).writeonly().share(m_pos_d_ram); map(0x1c30, 0x1c37).w(FUNC(sprint8_state::lockout_w)); map(0x1d00, 0x1d07).w("latch", FUNC(f9334_device::write_d0)); map(0x1e00, 0x1e07).w("motor", FUNC(f9334_device::write_d0)); - map(0x1f00, 0x1f00).nopw(); /* probably a watchdog, disabled in service mode */ + map(0x1f00, 0x1f00).nopw(); // probably a watchdog, disabled in service mode map(0x2000, 0x3fff).rom(); map(0xf800, 0xffff).rom(); } @@ -242,21 +495,21 @@ static const gfx_layout car_layout = static GFXDECODE_START( gfx_sprint8 ) - GFXDECODE_ENTRY( "gfx1", 0, tile_layout_1, 0, 18 ) - GFXDECODE_ENTRY( "gfx1", 0, tile_layout_2, 0, 18 ) - GFXDECODE_ENTRY( "gfx2", 0, car_layout, 0, 16 ) + GFXDECODE_ENTRY( "tiles", 0, tile_layout_1, 0, 18 ) + GFXDECODE_ENTRY( "tiles", 0, tile_layout_2, 0, 18 ) + GFXDECODE_ENTRY( "cars", 0, car_layout, 0, 16 ) GFXDECODE_END void sprint8_state::sprint8(machine_config &config) { - /* basic machine hardware */ - M6800(config, m_maincpu, 11055000 / 11); /* ? */ - m_maincpu->set_addrmap(AS_PROGRAM, &sprint8_state::sprint8_map); + // basic machine hardware + M6800(config, m_maincpu, 11'055'000 / 11); // ? + m_maincpu->set_addrmap(AS_PROGRAM, &sprint8_state::program_map); TIMER(config, "input_timer").configure_periodic(FUNC(sprint8_state::input_callback), attotime::from_hz(60)); - /* video hardware */ + // video hardware SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(60); m_screen->set_size(512, 261); @@ -266,9 +519,41 @@ void sprint8_state::sprint8(machine_config &config) m_screen->set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_sprint8); - PALETTE(config, m_palette, FUNC(sprint8_state::sprint8_palette), 36, 18); - - sprint8_audio(config); + PALETTE(config, m_palette, FUNC(sprint8_state::palette), 36, 18); + + // sound hardware + /* the proper way is to hook up 4 speakers, but they are not really + * F/R/L/R speakers. Though you can pretend the 1-2 mix is the front. */ + SPEAKER(config, "speaker_1_2", 0.0, 0.0, 1.0); // front + SPEAKER(config, "speaker_3_7", -0.2, 0.0, 1.0); // left + SPEAKER(config, "speaker_5_6", 0.0, 0.0, -0.5); // back + SPEAKER(config, "speaker_4_8", 0.2, 0.0, 1.0); // right + + DISCRETE(config, m_discrete, sprint8_discrete); + m_discrete->add_route(0, "speaker_1_2", 1.0); + /* volumes on other channels defaulted to off, + user can turn them up if needed. + The game does not sound good with all channels mixed to stereo. */ + m_discrete->add_route(1, "speaker_3_7", 0.0); + m_discrete->add_route(2, "speaker_5_6", 0.0); + m_discrete->add_route(3, "speaker_4_8", 0.0); + + f9334_device &latch(F9334(config, "latch")); + latch.q_out_cb<0>().set(FUNC(sprint8_state::int_reset_w)); + latch.q_out_cb<1>().set(m_discrete, FUNC(discrete_device::write_line)); + latch.q_out_cb<2>().set(m_discrete, FUNC(discrete_device::write_line)); + latch.q_out_cb<5>().set(FUNC(sprint8_state::team_w)); + latch.q_out_cb<6>().set(m_discrete, FUNC(discrete_device::write_line)); + + f9334_device &motor(F9334(config, "motor")); + motor.q_out_cb<0>().set(m_discrete, FUNC(discrete_device::write_line)); + motor.q_out_cb<1>().set(m_discrete, FUNC(discrete_device::write_line)); + motor.q_out_cb<2>().set(m_discrete, FUNC(discrete_device::write_line)); + motor.q_out_cb<3>().set(m_discrete, FUNC(discrete_device::write_line)); + motor.q_out_cb<4>().set(m_discrete, FUNC(discrete_device::write_line)); + motor.q_out_cb<5>().set(m_discrete, FUNC(discrete_device::write_line)); + motor.q_out_cb<6>().set(m_discrete, FUNC(discrete_device::write_line)); + motor.q_out_cb<7>().set(m_discrete, FUNC(discrete_device::write_line)); } @@ -278,10 +563,10 @@ ROM_START( sprint8 ) ROM_LOAD( "7314.h1", 0x2c00, 0x0800, CRC(c77c0d49) SHA1(a57b5d340a41d02edb20fcb66875908110582bc5) ) ROM_RELOAD( 0xf800, 0x0800 ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */ + ROM_REGION( 0x0200, "tiles", 0 ) ROM_LOAD( "7315-01.n6", 0x0000, 0x0200, CRC(e2f603d0) SHA1(8d82b72d2f4039afa3341774000105a745caf85f) ) - ROM_REGION( 0x0100, "gfx2", 0 ) /* cars */ + ROM_REGION( 0x0100, "cars", 0 ) ROM_LOAD( "7316-01.j5", 0x0000, 0x0100, CRC(32c028e3) SHA1(bfa76cf0981640d08e9c7fb15da134afe46afe31) ) ROM_END @@ -297,13 +582,15 @@ ROM_START( sprint8a ) ROM_LOAD_NIB_HIGH( "m3800s8", 0x3800, 0x0800, CRC(90aadc75) SHA1(34ca21c37573d9a2df92d3a1e73fdc0a9885c0a0) ) ROM_RELOAD( 0xf800, 0x0800 ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */ + ROM_REGION( 0x0200, "tiles", 0 ) ROM_LOAD( "s8.n6", 0x0000, 0x0200, CRC(92cf9a7e) SHA1(6bd2d396e0a299c2e731425cabd578d569c2061b) ) - ROM_REGION( 0x0100, "gfx2", 0 ) /* cars */ + ROM_REGION( 0x0100, "cars", 0 ) ROM_LOAD( "s8.j5", 0x0000, 0x0100, CRC(d37fff36) SHA1(20a7a8caf2fbfe22e307fe8541d31784c8e39d1a) ) ROM_END +} // anonymous namespace + GAME( 1977, sprint8, 0, sprint8, sprint8, sprint8_state, empty_init, ROT0, "Atari", "Sprint 8", MACHINE_SUPPORTS_SAVE ) GAME( 1977, sprint8a, sprint8, sprint8, sprint8p, sprint8_state, empty_init, ROT0, "Atari", "Sprint 8 (play tag & chase)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/atari/sprint8.h b/src/mame/atari/sprint8.h deleted file mode 100644 index 37f142e614e..00000000000 --- a/src/mame/atari/sprint8.h +++ /dev/null @@ -1,91 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Stefan Jokisch -#ifndef MAME_ATARI_SPRINT8_H -#define MAME_ATARI_SPRINT8_H - -#pragma once - -#include "machine/74259.h" -#include "machine/timer.h" -#include "sound/discrete.h" -#include "emupal.h" -#include "screen.h" -#include "tilemap.h" - -class sprint8_state : public driver_device -{ -public: - sprint8_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_discrete(*this, "discrete"), - m_video_ram(*this, "video_ram"), - m_pos_h_ram(*this, "pos_h_ram"), - m_pos_v_ram(*this, "pos_v_ram"), - m_pos_d_ram(*this, "pos_d_ram"), - m_in(*this, "P%u", 1U), - m_dial(*this, "DIAL%u", 1U) - { } - - void sprint8(machine_config &config); - -private: - uint8_t collision_r(); - uint8_t input_r(offs_t offset); - void lockout_w(offs_t offset, uint8_t data); - DECLARE_WRITE_LINE_MEMBER(int_reset_w); - DECLARE_WRITE_LINE_MEMBER(team_w); - void video_ram_w(offs_t offset, uint8_t data); - - virtual void machine_start() override; - virtual void machine_reset() override; - virtual void video_start() override; - void sprint8_palette(palette_device &palette) const; - - TILE_GET_INFO_MEMBER(get_tile_info1); - TILE_GET_INFO_MEMBER(get_tile_info2); - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank); - TIMER_CALLBACK_MEMBER(collision_callback); - TIMER_DEVICE_CALLBACK_MEMBER(input_callback); - - void set_pens(); - void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); - void set_collision(int n); - void sprint8_audio(machine_config &config); - void sprint8_map(address_map &map); - - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - required_device m_discrete; - - required_shared_ptr m_video_ram; - required_shared_ptr m_pos_h_ram; - required_shared_ptr m_pos_v_ram; - required_shared_ptr m_pos_d_ram; - - required_ioport_array<8> m_in; - required_ioport_array<8> m_dial; - - uint8_t m_steering[8]{}; - bool m_collision_reset = false; - uint8_t m_collision_index = 0; - uint8_t m_prev_dial[8]{}; - bool m_team = false; - - tilemap_t* m_tilemap1 = nullptr; - tilemap_t* m_tilemap2 = nullptr; - bitmap_ind16 m_helper1; - bitmap_ind16 m_helper2; - emu_timer *m_collision_timer = nullptr; -}; - -/*----------- defined in audio/sprint8.c -----------*/ -DISCRETE_SOUND_EXTERN( sprint8_discrete ); - -#endif // MAME_ATARI_SPRINT8_H diff --git a/src/mame/atari/sprint8_a.cpp b/src/mame/atari/sprint8_a.cpp index de0962e259a..c3aabe2b0aa 100644 --- a/src/mame/atari/sprint8_a.cpp +++ b/src/mame/atari/sprint8_a.cpp @@ -6,24 +6,10 @@ ************************************************************************/ #include "emu.h" -#include "sprint8.h" -#include "speaker.h" +#include "sprint8_a.h" -/* Discrete Sound Input Nodes */ -#define SPRINT8_CRASH_EN NODE_01 -#define SPRINT8_SCREECH_EN NODE_02 -#define SPRINT8_ATTRACT_EN NODE_03 -#define SPRINT8_MOTOR1_EN NODE_04 -#define SPRINT8_MOTOR2_EN NODE_05 -#define SPRINT8_MOTOR3_EN NODE_06 -#define SPRINT8_MOTOR4_EN NODE_07 -#define SPRINT8_MOTOR5_EN NODE_08 -#define SPRINT8_MOTOR6_EN NODE_09 -#define SPRINT8_MOTOR7_EN NODE_10 -#define SPRINT8_MOTOR8_EN NODE_11 - /* Discrete Sound Output Nodes */ #define SPRINT8_NOISE NODE_12 #define SPRINT8_MOTOR1_SND NODE_13 @@ -295,41 +281,3 @@ DISCRETE_SOUND_START( sprint8_discrete ) DISCRETE_OUTPUT(SPRINT8_AUDIO_4_8, 65500.0/8) DISCRETE_TASK_END() DISCRETE_SOUND_END - -void sprint8_state::sprint8_audio(machine_config &config) -{ - /* sound hardware */ - /* the proper way is to hook up 4 speakers, but they are not really - * F/R/L/R speakers. Though you can pretend the 1-2 mix is the front. */ - SPEAKER(config, "speaker_1_2", 0.0, 0.0, 1.0); // front - SPEAKER(config, "speaker_3_7", -0.2, 0.0, 1.0); // left - SPEAKER(config, "speaker_5_6", 0.0, 0.0, -0.5); // back - SPEAKER(config, "speaker_4_8", 0.2, 0.0, 1.0); // right - - DISCRETE(config, m_discrete, sprint8_discrete); - m_discrete->add_route(0, "speaker_1_2", 1.0); - /* volumes on other channels defaulted to off, */ - /* user can turn them up if needed. */ - /* The game does not sound good with all channels mixed to stereo. */ - m_discrete->add_route(1, "speaker_3_7", 0.0); - m_discrete->add_route(2, "speaker_5_6", 0.0); - m_discrete->add_route(3, "speaker_4_8", 0.0); - - f9334_device &latch(F9334(config, "latch")); - latch.q_out_cb<0>().set(FUNC(sprint8_state::int_reset_w)); - latch.q_out_cb<1>().set(m_discrete, FUNC(discrete_device::write_line)); - latch.q_out_cb<2>().set(m_discrete, FUNC(discrete_device::write_line)); - latch.q_out_cb<5>().set(FUNC(sprint8_state::team_w)); - latch.q_out_cb<6>().set(m_discrete, FUNC(discrete_device::write_line)); - - f9334_device &motor(F9334(config, "motor")); - motor.q_out_cb<0>().set(m_discrete, FUNC(discrete_device::write_line)); - motor.q_out_cb<1>().set(m_discrete, FUNC(discrete_device::write_line)); - motor.q_out_cb<2>().set(m_discrete, FUNC(discrete_device::write_line)); - motor.q_out_cb<3>().set(m_discrete, FUNC(discrete_device::write_line)); - motor.q_out_cb<4>().set(m_discrete, FUNC(discrete_device::write_line)); - motor.q_out_cb<5>().set(m_discrete, FUNC(discrete_device::write_line)); - motor.q_out_cb<6>().set(m_discrete, FUNC(discrete_device::write_line)); - motor.q_out_cb<7>().set(m_discrete, FUNC(discrete_device::write_line)); -} -; diff --git a/src/mame/atari/sprint8_a.h b/src/mame/atari/sprint8_a.h new file mode 100644 index 00000000000..8faf5cacc0a --- /dev/null +++ b/src/mame/atari/sprint8_a.h @@ -0,0 +1,27 @@ +// license:BSD-3-Clause +// copyright-holders:Derrick Renaud + +/*************************************************************************** + +Sprint 8 Audio + +***************************************************************************/ + +#include "sound/discrete.h" + +// discrete sound input nodes + +#define SPRINT8_CRASH_EN NODE_01 +#define SPRINT8_SCREECH_EN NODE_02 +#define SPRINT8_ATTRACT_EN NODE_03 +#define SPRINT8_MOTOR1_EN NODE_04 +#define SPRINT8_MOTOR2_EN NODE_05 +#define SPRINT8_MOTOR3_EN NODE_06 +#define SPRINT8_MOTOR4_EN NODE_07 +#define SPRINT8_MOTOR5_EN NODE_08 +#define SPRINT8_MOTOR6_EN NODE_09 +#define SPRINT8_MOTOR7_EN NODE_10 +#define SPRINT8_MOTOR8_EN NODE_11 + + +DISCRETE_SOUND_EXTERN( sprint8_discrete ); diff --git a/src/mame/atari/sprint8_v.cpp b/src/mame/atari/sprint8_v.cpp deleted file mode 100644 index c38636f7fbc..00000000000 --- a/src/mame/atari/sprint8_v.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Stefan Jokisch -/*************************************************************************** - -Atari Sprint 8 video emulation - -***************************************************************************/ - -#include "emu.h" -#include "sprint8.h" - - -void sprint8_state::sprint8_palette(palette_device &palette) const -{ - for (int i = 0; i < 0x10; i++) - { - palette.set_pen_indirect(2 * i + 0, 0x10); - palette.set_pen_indirect(2 * i + 1, i); - } - - palette.set_pen_indirect(0x20, 0x10); - palette.set_pen_indirect(0x21, 0x10); - palette.set_pen_indirect(0x22, 0x10); - palette.set_pen_indirect(0x23, 0x11); -} - - -void sprint8_state::set_pens() -{ - for (int i = 0; i < 0x10; i += 8) - { - if (m_team) - { - m_palette->set_indirect_color(i + 0, rgb_t(0xff, 0x00, 0x00)); // red - m_palette->set_indirect_color(i + 1, rgb_t(0x00, 0x00, 0xff)); // blue - m_palette->set_indirect_color(i + 2, rgb_t(0xff, 0xff, 0x00)); // yellow - m_palette->set_indirect_color(i + 3, rgb_t(0x00, 0xff, 0x00)); // green - m_palette->set_indirect_color(i + 4, rgb_t(0xff, 0x00, 0xff)); // magenta - m_palette->set_indirect_color(i + 5, rgb_t(0xe0, 0xc0, 0x70)); // puce - m_palette->set_indirect_color(i + 6, rgb_t(0x00, 0xff, 0xff)); // cyan - m_palette->set_indirect_color(i + 7, rgb_t(0xff, 0xaa, 0xaa)); // pink - } - else - { - m_palette->set_indirect_color(i + 0, rgb_t(0xff, 0x00, 0x00)); // red - m_palette->set_indirect_color(i + 1, rgb_t(0x00, 0x00, 0xff)); // blue - m_palette->set_indirect_color(i + 2, rgb_t(0xff, 0x00, 0x00)); // red - m_palette->set_indirect_color(i + 3, rgb_t(0x00, 0x00, 0xff)); // blue - m_palette->set_indirect_color(i + 4, rgb_t(0xff, 0x00, 0x00)); // red - m_palette->set_indirect_color(i + 5, rgb_t(0x00, 0x00, 0xff)); // blue - m_palette->set_indirect_color(i + 6, rgb_t(0xff, 0x00, 0x00)); // red - m_palette->set_indirect_color(i + 7, rgb_t(0x00, 0x00, 0xff)); // blue - } - } - - m_palette->set_indirect_color(0x10, rgb_t(0x00, 0x00, 0x00)); - m_palette->set_indirect_color(0x11, rgb_t(0xff, 0xff, 0xff)); -} - - -TILE_GET_INFO_MEMBER(sprint8_state::get_tile_info1) -{ - uint8_t code = m_video_ram[tile_index]; - - int color = 0; - - if ((code & 0x30) != 0x30) /* ? */ - color = 17; - else - { - if ((tile_index + 1) & 0x010) - color |= 1; - - if (code & 0x80) - color |= 2; - - if (tile_index & 0x200) - color |= 4; - - } - - tileinfo.set(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0); -} - - -TILE_GET_INFO_MEMBER(sprint8_state::get_tile_info2) -{ - uint8_t code = m_video_ram[tile_index]; - - int color = 0; - - if ((code & 0x38) != 0x28) - color = 16; - else - color = 17; - - tileinfo.set(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0); -} - - -void sprint8_state::video_ram_w(offs_t offset, uint8_t data) -{ - m_video_ram[offset] = data; - m_tilemap1->mark_tile_dirty(offset); - m_tilemap2->mark_tile_dirty(offset); -} - - -void sprint8_state::video_start() -{ - m_screen->register_screen_bitmap(m_helper1); - m_screen->register_screen_bitmap(m_helper2); - - m_tilemap1 = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint8_state::get_tile_info1)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32); - m_tilemap2 = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(sprint8_state::get_tile_info2)), TILEMAP_SCAN_ROWS, 16, 8, 32, 32); - - m_tilemap1->set_scrolly(0, +24); - m_tilemap2->set_scrolly(0, +24); - - m_collision_timer = timer_alloc(FUNC(sprint8_state::collision_callback), this); -} - - -void sprint8_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - for (int i = 0; i < 16; i++) - { - uint8_t code = m_pos_d_ram[i]; - - int x = m_pos_h_ram[i]; - int y = m_pos_v_ram[i]; - - if (code & 0x80) - x |= 0x100; - - m_gfxdecode->gfx(2)->transpen(bitmap,cliprect, - code ^ 7, - i, - !(code & 0x10), !(code & 0x08), - 496 - x, y - 31, 0); - } -} - - -TIMER_CALLBACK_MEMBER(sprint8_state::collision_callback) -{ - set_collision(param); -} - - -uint32_t sprint8_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - set_pens(); - m_tilemap1->draw(screen, bitmap, cliprect, 0, 0); - draw_sprites(bitmap, cliprect); - return 0; -} - - -WRITE_LINE_MEMBER(sprint8_state::screen_vblank) -{ - // rising edge - if (state) - { - const rectangle &visarea = m_screen->visible_area(); - - m_tilemap2->draw(*m_screen, m_helper2, visarea, 0, 0); - - m_helper1.fill(0x20, visarea); - - draw_sprites(m_helper1, visarea); - - for (int y = visarea.top(); y <= visarea.bottom(); y++) - { - uint16_t const *const p1 = &m_helper1.pix(y); - uint16_t const *const p2 = &m_helper2.pix(y); - - for (int x = visarea.left(); x <= visarea.right(); x++) - if (p1[x] != 0x20 && p2[x] == 0x23) - m_collision_timer->adjust(m_screen->time_until_pos(y + 24, x), m_palette->pen_indirect(p1[x])); - } - } -} diff --git a/src/mame/atari/starshp1.cpp b/src/mame/atari/starshp1.cpp index 4991334a145..d1fee954e49 100644 --- a/src/mame/atari/starshp1.cpp +++ b/src/mame/atari/starshp1.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Frank Palazzolo, Stefan Jokisch + /*************************************************************************** Atari Starship 1 driver @@ -7,21 +8,537 @@ Atari Starship 1 driver "starshp1" -> regular version, bonus time for 3500 points "starshpp" -> possible prototype, bonus time for 2700 points + * The schematics don't seem to make a lot of sense when it + * comes to the video timing chain:: + * + * * there are clear typos -- what is H132??? + * * there are two HBLANK/HSYNC periods as the horizontal + * chain is drawn, which would give an alternating long + * line followed by a much shorter one. This cannot be right + * * the carry-out/load circuit on LS161@J8 is superfluous + * + * These values also give a frame rate of about 45Hz, which is + * probably too low. I suspect that screen is not really + * 512 pixels wide -- most likely 384, which would give 60Hz + * + * Based on photographs of the PCB, and analysis of videos of + * actual gameplay, the horizontal screen really is 384 clocks. + * + * However, some of the graphics, like the starfield, are + * clocked with the 12MHz signal. This effectively doubles + * the horizontal resolution: + * + * 6.048Mhz clocks 12.096Mhz clocks + * Horizontal Visible Area 384 (0x180) 768 (0x300) + * Horizontal Blanking Time 128 (0x080) 256 (0x100) + ***************************************************************************/ #include "emu.h" -#include "starshp1.h" + +#include "starshp1_a.h" #include "cpu/m6502/m6502.h" #include "machine/74259.h" +#include "sound/discrete.h" +#include "emupal.h" +#include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +namespace { + +class starshp1_state : public driver_device +{ +public: + starshp1_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_discrete(*this, "discrete"), + m_gfxdecode(*this, "gfxdecode"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_playfield_ram(*this, "playfield_ram"), + m_hpos_ram(*this, "hpos_ram"), + m_vpos_ram(*this, "vpos_ram"), + m_obj_ram(*this, "obj_ram"), + m_system(*this, "SYSTEM"), + m_playtime(*this, "PLAYTIME"), + m_stick(*this, "STICK%c", 'X') + { } + + void starshp1(machine_config &config); + + DECLARE_CUSTOM_INPUT_MEMBER(analog_r); + DECLARE_CUSTOM_INPUT_MEMBER(collision_latch_r); + +protected: + virtual void machine_start() override; + virtual void video_start() override; + +private: + required_device m_maincpu; + required_device m_discrete; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + + required_shared_ptr m_playfield_ram; + required_shared_ptr m_hpos_ram; + required_shared_ptr m_vpos_ram; + required_shared_ptr m_obj_ram; + + required_ioport m_system; + required_ioport m_playtime; + required_ioport_array<2> m_stick; + + uint8_t m_analog_in_select = 0; + uint8_t m_attract = 0; + uint8_t m_ship_explode = 0; + uint8_t m_ship_picture = 0; + uint8_t m_ship_hoffset = 0; + uint8_t m_ship_voffset = 0; + uint8_t m_ship_size = 0; + uint8_t m_circle_hpos = 0; + uint8_t m_circle_vpos = 0; + uint8_t m_circle_size = 0; + uint8_t m_circle_mod = 0; + uint8_t m_circle_kill = 0; + uint8_t m_phasor = 0; + uint8_t m_collision_latch = 0; + uint8_t m_starfield_kill = 0; + uint8_t m_mux = 0; + uint8_t m_inverse = 0; + std::unique_ptr m_lsfr; + bitmap_ind16 m_helper; + tilemap_t *m_bg_tilemap = nullptr; + + void collision_reset_w(uint8_t data); + void analog_in_w(offs_t offset, uint8_t data); + DECLARE_WRITE_LINE_MEMBER(ship_explode_w); + DECLARE_WRITE_LINE_MEMBER(circle_mod_w); + DECLARE_WRITE_LINE_MEMBER(circle_kill_w); + DECLARE_WRITE_LINE_MEMBER(starfield_kill_w); + DECLARE_WRITE_LINE_MEMBER(inverse_w); + DECLARE_WRITE_LINE_MEMBER(mux_w); + uint8_t rng_r(); + void ssadd_w(offs_t offset, uint8_t data); + void sspic_w(uint8_t data); + void playfield_w(offs_t offset, uint8_t data); + DECLARE_WRITE_LINE_MEMBER(attract_w); + DECLARE_WRITE_LINE_MEMBER(phasor_w); + void analog_out_w(offs_t offset, uint8_t data); + TILE_GET_INFO_MEMBER(get_tile_info); + void palette(palette_device &palette) const; + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank); + INTERRUPT_GEN_MEMBER(interrupt); + void set_pens(); + void draw_starfield(bitmap_ind16 &bitmap, const rectangle &cliprect); + int get_sprite_hpos(int i); + int get_sprite_vpos(int i); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_spaceship(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_phasor(bitmap_ind16 &bitmap); + int get_radius(); + int get_circle_hpos(); + int get_circle_vpos(); + void draw_circle_line(bitmap_ind16 &bitmap, int x, int y, int l); + void draw_circle(bitmap_ind16 &bitmap); + int spaceship_collision(bitmap_ind16 &bitmap, const rectangle &rect); + int point_in_circle(int x, int y, int center_x, int center_y, int r); + int circle_collision(const rectangle &rect); + void program_map(address_map &map); +}; + + +// video + +void starshp1_state::set_pens() +{ + m_palette->set_indirect_color(m_inverse ? 7 : 0, rgb_t(0x00, 0x00, 0x00)); + m_palette->set_indirect_color(m_inverse ? 6 : 1, rgb_t(0x1e, 0x1e, 0x1e)); + m_palette->set_indirect_color(m_inverse ? 5 : 2, rgb_t(0x4e, 0x4e, 0x4e)); + m_palette->set_indirect_color(m_inverse ? 4 : 3, rgb_t(0x6c, 0x6c, 0x6c)); + m_palette->set_indirect_color(m_inverse ? 3 : 4, rgb_t(0x93, 0x93, 0x93)); + m_palette->set_indirect_color(m_inverse ? 2 : 5, rgb_t(0xb1, 0xb1, 0xb1)); + m_palette->set_indirect_color(m_inverse ? 1 : 6, rgb_t(0xe1, 0xe1, 0xe1)); + m_palette->set_indirect_color(m_inverse ? 0 : 7, rgb_t(0xff, 0xff, 0xff)); +} + + +void starshp1_state::palette(palette_device &palette) const +{ + static constexpr uint16_t colortable_source[] = + { + 0, 3, // 0x00 - 0x01 - alpha numerics + 0, 2, // 0x02 - 0x03 - sprites (Z=0) + 0, 5, // 0x04 - 0x05 - sprites (Z=1) + 0, 2, 4, 6, // 0x06 - 0x09 - spaceship (EXPLODE=0) + 0, 6, 6, 7, // 0x0a - 0x0d - spaceship (EXPLODE=1) + 5, 2, // 0x0e - 0x0f - star field + 7, // 0x10 - phasor + 5, 7 // 0x11 - circle + }; + + for (unsigned i = 0; i < std::size(colortable_source); i++) + palette.set_pen_indirect(i, colortable_source[i]); +} + + +TILE_GET_INFO_MEMBER(starshp1_state::get_tile_info) +{ + uint8_t const code = m_playfield_ram[tile_index]; + + tileinfo.set(0, code & 0x3f, 0, 0); +} + + +void starshp1_state::video_start() +{ + m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(starshp1_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 8, 32, 8); + m_bg_tilemap->set_transparent_pen(0); + m_bg_tilemap->set_scrollx(0, -8); + + m_lsfr = std::make_unique(0x10000); + + uint16_t val = 0; + for (int i = 0; i < 0x10000; i++) + { + int bit = (val >> 0xf) ^ + (val >> 0xc) ^ + (val >> 0x7) ^ + (val >> 0x1) ^ 1; + + m_lsfr[i] = val; + + val = (val << 1) | (bit & 1); + } + + m_screen->register_screen_bitmap(m_helper); +} + + +uint8_t starshp1_state::rng_r() +{ + int const width = m_screen->width(); + int const height = m_screen->height(); + int x = m_screen->hpos(); + int y = m_screen->vpos(); + + /* the LFSR is only running in the non-blank region + of the screen, so this is not quite right */ + if (x > width - 1) + x = width - 1; + if (y > height - 1) + y = height - 1; + + return m_lsfr[x + (uint16_t) (512 * y)]; +} + + +void starshp1_state::ssadd_w(offs_t offset, uint8_t data) +{ + /* + * The range of sprite position values doesn't suffice to + * move the zoomed spaceship sprite over the top and left + * edges of the screen. These additional values are used + * to compensate for this. Technically, they cut off the + * first columns and rows of the spaceship sprite, but in + * practice they work like offsets in zoomed pixels. + */ + + m_ship_voffset = ((offset & 0xf0) >> 4); + m_ship_hoffset = ((offset & 0x0f) << 2) | (data & 3); +} + + +void starshp1_state::sspic_w(uint8_t data) +{ + /* + * Some mysterious game code at address $2CCE causes + * erratic images in the target explosion sequence. But + * this is the way the actual game worked! + */ + + m_ship_picture = data; +} + + +void starshp1_state::playfield_w(offs_t offset, uint8_t data) +{ + if (m_mux != 0) + { + offset ^= 0x1f; + m_playfield_ram[offset] = data; + m_bg_tilemap->mark_tile_dirty(offset); + } +} + + +void starshp1_state::draw_starfield(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + /* + * The LSFR is reset once per frame at the position of + * sprite 15. This behavior is quite pointless and not + * really needed by the game. Not emulated. + */ + + for (int y = 0; y <= cliprect.bottom(); y++) + { + uint16_t const *const p = m_lsfr.get() + (uint16_t) (512 * y); + uint16_t *const pLine = &bitmap.pix(y); + + for (int x = 0; x <= cliprect.right(); x++) + if ((p[x] & 0x5b56) == 0x5b44) + pLine[x] = (p[x] & 0x0400) ? 0x0e : 0x0f; + } +} + + +int starshp1_state::get_sprite_hpos(int i) +{ + return 2 * (m_hpos_ram[i] ^ 0xff); +} +int starshp1_state::get_sprite_vpos(int i) +{ + return 1 * (m_vpos_ram[i] - 0x07); +} + + +void starshp1_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int i = 0; i < 14; i++) + { + int const code = (m_obj_ram[i] & 0xf) ^ 0xf; + + m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, + code % 8, + code / 8, + 0, 0, + get_sprite_hpos(i), + get_sprite_vpos(i), 0); + } +} + + +void starshp1_state::draw_spaceship(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + double scaler = -5 * log(1 - m_ship_size / 256.0); /* ? */ + + unsigned xzoom = 2 * 0x10000 * scaler; + unsigned yzoom = 1 * 0x10000 * scaler; + + int x = get_sprite_hpos(14); + int y = get_sprite_vpos(14); + + if (x <= 0) + x -= (xzoom * m_ship_hoffset) >> 16; + + if (y <= 0) + y -= (yzoom * m_ship_voffset) >> 16; + + m_gfxdecode->gfx(2)->zoom_transpen(bitmap, cliprect, + m_ship_picture & 0x03, + m_ship_explode, + m_ship_picture & 0x80, 0, + x, y, + xzoom, yzoom, 0); +} + +void starshp1_state::draw_phasor(bitmap_ind16 &bitmap) +{ + for (int i = 128; i < 240; i++) + if (i >= get_sprite_vpos(13)) + { + bitmap.pix(i, 2 * i + 0) = 0x10; + bitmap.pix(i, 2 * i + 1) = 0x10; + bitmap.pix(i, 2 * (255 - i) + 0) = 0x10; + bitmap.pix(i, 2 * (255 - i) + 1) = 0x10; + } +} + + +int starshp1_state::get_radius() +{ + return 6 * sqrt((double)m_circle_size); // size calibrated by hand +} +int starshp1_state::get_circle_hpos() +{ + return 2 * (3 * m_circle_hpos / 2 - 64); +} +int starshp1_state::get_circle_vpos() +{ + return 1 * (3 * m_circle_vpos / 2 - 64); +} + + +void starshp1_state::draw_circle_line(bitmap_ind16 &bitmap, int x, int y, int l) +{ + if (y >= 0 && y <= bitmap.height() - 1) + { + uint16_t const *const p = m_lsfr.get() + uint16_t(512 * y); + + uint16_t *const pLine = &bitmap.pix(y); + + int h1 = x - 2 * l; + int h2 = x + 2 * l; + + if (h1 < 0) + h1 = 0; + if (h2 > bitmap.width() - 1) + h2 = bitmap.width() - 1; + + for (x = h1; x <= h2; x++) + if (m_circle_mod) + { + if (p[x] & 1) + pLine[x] = 0x11; + } + else + pLine[x] = 0x12; + } +} + + +void starshp1_state::draw_circle(bitmap_ind16 &bitmap) +{ + int const cx = get_circle_hpos(); + int const cy = get_circle_vpos(); + + int x = 0; + int y = get_radius(); + + // Bresenham's circle algorithm + int d = 3 - 2 * get_radius(); -INTERRUPT_GEN_MEMBER(starshp1_state::starshp1_interrupt) + while (x <= y) + { + draw_circle_line(bitmap, cx, cy - x, y); + draw_circle_line(bitmap, cx, cy + x, y); + draw_circle_line(bitmap, cx, cy - y, x); + draw_circle_line(bitmap, cx, cy + y, x); + + x++; + + if (d < 0) + d += 4 * x + 6; + else + d += 4 * (x - y--) + 10; + } +} + + +int starshp1_state::spaceship_collision(bitmap_ind16 &bitmap, const rectangle &rect) { - if ((ioport("SYSTEM")->read() & 0x90) != 0x90) + for (int y = rect.top(); y <= rect.bottom(); y++) + { + uint16_t const *const pLine = &m_helper.pix(y); + + for (int x = rect.left(); x <= rect.right(); x++) + if (pLine[x] != 0) + return 1; + } + + return 0; +} + + +int starshp1_state::point_in_circle(int x, int y, int center_x, int center_y, int r) +{ + int const dx = abs(x - center_x) / 2; + int const dy = abs(y - center_y) / 1; + + return dx * dx + dy * dy < r * r; +} + + +int starshp1_state::circle_collision(const rectangle &rect) +{ + int const center_x = get_circle_hpos(); + int const center_y = get_circle_vpos(); + + int const r = get_radius(); + + return point_in_circle(rect.left(), rect.top(), center_x, center_y, r) || + point_in_circle(rect.left(), rect.bottom(), center_x, center_y, r) || + point_in_circle(rect.right(), rect.top(), center_x, center_y, r) || + point_in_circle(rect.right(), rect.bottom(), center_x, center_y, r); +} + + +uint32_t starshp1_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + set_pens(); + + bitmap.fill(0, cliprect); + + if (m_starfield_kill == 0) + draw_starfield(bitmap, cliprect); + + draw_sprites(bitmap, cliprect); + + if (m_circle_kill == 0 && m_circle_mod != 0) + draw_circle(bitmap); + + if (m_attract == 0) + draw_spaceship(bitmap, cliprect); + + if (m_circle_kill == 0 && m_circle_mod == 0) + draw_circle(bitmap); + + rectangle tilemaprect(0, m_bg_tilemap->width(), 0, m_bg_tilemap->height()); + tilemaprect &= cliprect; + m_bg_tilemap->draw(screen, bitmap, tilemaprect, 0, 0); + + if (m_phasor != 0) + draw_phasor(bitmap); + + return 0; +} + + +WRITE_LINE_MEMBER(starshp1_state::screen_vblank) +{ + // rising edge + if (state) + { + const rectangle &visarea = m_screen->visible_area(); + + rectangle rect(get_sprite_hpos(13), 0, get_sprite_vpos(13), 0); + rect.set_size(m_gfxdecode->gfx(1)->width(), m_gfxdecode->gfx(1)->height()); + + rect &= m_helper.cliprect(); + + m_helper.fill(0, visarea); + + if (m_attract == 0) + draw_spaceship(m_helper, visarea); + + if (circle_collision(visarea)) + m_collision_latch |= 1; + + if (circle_collision(rect)) + m_collision_latch |= 2; + + if (spaceship_collision(m_helper, rect)) + m_collision_latch |= 4; + + if (spaceship_collision(m_helper, visarea)) + m_collision_latch |= 8; + } +} + + +// machine + +INTERRUPT_GEN_MEMBER(starshp1_state::interrupt) +{ + if ((m_system->read() & 0x90) != 0x90) device.execute().pulse_input_line(0, device.execute().minimum_quantum_time()); } @@ -43,29 +560,29 @@ WRITE_LINE_MEMBER(starshp1_state::phasor_w) } -void starshp1_state::starshp1_collision_reset_w(uint8_t data) +void starshp1_state::collision_reset_w(uint8_t data) { m_collision_latch = 0; } -CUSTOM_INPUT_MEMBER(starshp1_state::starshp1_analog_r) +CUSTOM_INPUT_MEMBER(starshp1_state::analog_r) { int val = 0; switch (m_analog_in_select) { case 0: - val = ioport("STICKY")->read(); + val = m_stick[1]->read(); break; case 1: - val = ioport("STICKX")->read(); + val = m_stick[0]->read(); break; case 2: - val = 0x20; /* DAC feedback, not used */ + val = 0x20; // DAC feedback, not used break; case 3: - val = ioport("PLAYTIME")->read(); + val = m_playtime->read(); break; } @@ -79,13 +596,13 @@ CUSTOM_INPUT_MEMBER(starshp1_state::collision_latch_r) } -void starshp1_state::starshp1_analog_in_w(offs_t offset, uint8_t data) +void starshp1_state::analog_in_w(offs_t offset, uint8_t data) { m_analog_in_select = offset & 3; } -void starshp1_state::starshp1_analog_out_w(offs_t offset, uint8_t data) +void starshp1_state::analog_out_w(offs_t offset, uint8_t data) { switch (offset & 7) { @@ -150,45 +667,55 @@ WRITE_LINE_MEMBER(starshp1_state::mux_w) } -WRITE_LINE_MEMBER(starshp1_state::led_w) -{ - m_led = state ? 0 : 1; -} - - -void starshp1_state::starshp1_map(address_map &map) +void starshp1_state::program_map(address_map &map) { map(0x0000, 0x00ff).ram().mirror(0x100); map(0x2c00, 0x3fff).rom(); map(0xa000, 0xa000).portr("SYSTEM"); map(0xb000, 0xb000).portr("VBLANK"); - map(0xc300, 0xc3ff).w(FUNC(starshp1_state::starshp1_sspic_w)); /* spaceship picture */ + map(0xc300, 0xc3ff).w(FUNC(starshp1_state::sspic_w)); // spaceship picture map(0xc400, 0xc400).portr("COINAGE"); - map(0xc400, 0xc4ff).w(FUNC(starshp1_state::starshp1_ssadd_w)); /* spaceship address */ - map(0xc800, 0xc8ff).ram().w(FUNC(starshp1_state::starshp1_playfield_w)).share("playfield_ram"); - map(0xcc00, 0xcc0f).writeonly().share("hpos_ram"); - map(0xd000, 0xd00f).writeonly().share("vpos_ram"); - map(0xd400, 0xd40f).writeonly().share("obj_ram"); - map(0xd800, 0xd800).r(FUNC(starshp1_state::starshp1_rng_r)); - map(0xd800, 0xd80f).w(FUNC(starshp1_state::starshp1_collision_reset_w)); + map(0xc400, 0xc4ff).w(FUNC(starshp1_state::ssadd_w)); // spaceship address + map(0xc800, 0xc8ff).ram().w(FUNC(starshp1_state::playfield_w)).share(m_playfield_ram); + map(0xcc00, 0xcc0f).writeonly().share(m_hpos_ram); + map(0xd000, 0xd00f).writeonly().share(m_vpos_ram); + map(0xd400, 0xd40f).writeonly().share(m_obj_ram); + map(0xd800, 0xd800).r(FUNC(starshp1_state::rng_r)); + map(0xd800, 0xd80f).w(FUNC(starshp1_state::collision_reset_w)); map(0xdc00, 0xdc07).mirror(0x0008).w("misclatch", FUNC(f9334_device::write_d0)); - map(0xdd00, 0xdd0f).w(FUNC(starshp1_state::starshp1_analog_in_w)); + map(0xdd00, 0xdd0f).w(FUNC(starshp1_state::analog_in_w)); map(0xde00, 0xde07).mirror(0x0008).w("audiolatch", FUNC(f9334_device::write_d0)); - map(0xdf00, 0xdf0f).w(FUNC(starshp1_state::starshp1_analog_out_w)); + map(0xdf00, 0xdf0f).w(FUNC(starshp1_state::analog_out_w)); map(0xf000, 0xffff).rom(); } void starshp1_state::machine_start() { - m_led.resolve(); + save_item(NAME(m_analog_in_select)); + save_item(NAME(m_attract)); + save_item(NAME(m_ship_explode)); + save_item(NAME(m_ship_picture)); + save_item(NAME(m_ship_hoffset)); + save_item(NAME(m_ship_voffset)); + save_item(NAME(m_ship_size)); + save_item(NAME(m_circle_hpos)); + save_item(NAME(m_circle_vpos)); + save_item(NAME(m_circle_size)); + save_item(NAME(m_circle_mod)); + save_item(NAME(m_circle_kill)); + save_item(NAME(m_phasor)); + save_item(NAME(m_collision_latch)); + save_item(NAME(m_starfield_kill)); + save_item(NAME(m_mux)); + save_item(NAME(m_inverse)); } static INPUT_PORTS_START( starshp1 ) PORT_START("SYSTEM") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* SWA1? */ + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) // SWA1? PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN2 ) @@ -199,7 +726,7 @@ static INPUT_PORTS_START( starshp1 ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_START("VBLANK") - PORT_BIT( 0x3f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(starshp1_state, starshp1_analog_r) // analog in + PORT_BIT( 0x3f, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(starshp1_state, analog_r) // analog in PORT_SERVICE( 0x40, IP_ACTIVE_LOW ) PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_VBLANK("screen") @@ -209,10 +736,10 @@ static INPUT_PORTS_START( starshp1 ) PORT_DIPSETTING( 0x10, DEF_STR( 2C_1C ) ) PORT_DIPSETTING( 0x20, DEF_STR( 1C_1C ) ) PORT_DIPSETTING( 0x40, DEF_STR( 1C_2C ) ) - PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) /* ground */ + PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) // ground PORT_START("PLAYTIME") - PORT_DIPNAME( 0x3f, 0x20, "Play Time" ) /* potentiometer */ + PORT_DIPNAME( 0x3f, 0x20, "Play Time" ) // potentiometer PORT_DIPSETTING( 0x00, "60 Seconds" ) PORT_DIPSETTING( 0x20, "90 Seconds" ) PORT_DIPSETTING( 0x3f, "120 Seconds" ) @@ -227,9 +754,9 @@ INPUT_PORTS_END static const gfx_layout tilelayout = { - 16, 8, /* 16x8 tiles */ - 64, /* 64 tiles */ - 1, /* 1 bit per pixel */ + 16, 8, // 16x8 tiles + 64, // 64 tiles + 1, // 1 bit per pixel { 0 }, { 0x204, 0x204, 0x205, 0x205, 0x206, 0x206, 0x207, 0x207, @@ -239,15 +766,15 @@ static const gfx_layout tilelayout = 0x0000, 0x0400, 0x0800, 0x0c00, 0x1000, 0x1400, 0x1800, 0x1c00 }, - 8 /* step */ + 8 // step }; static const gfx_layout spritelayout = { - 16, 8, /* 16x8 sprites */ - 8, /* 8 sprites */ - 1, /* 1 bit per pixel */ + 16, 8, // 16x8 sprites + 8, // 8 sprites + 1, // 1 bit per pixel { 0 }, { 0x04, 0x05, 0x06, 0x07, 0x0c, 0x0d, 0x0e, 0x0f, @@ -256,7 +783,7 @@ static const gfx_layout spritelayout = { 0x00, 0x20, 0x40, 0x60, 0x80, 0xa0, 0xc0, 0xe0 }, - 0x100 /* step */ + 0x100 // step }; static const uint32_t shiplayout_xoffset[64] = @@ -273,32 +800,36 @@ static const uint32_t shiplayout_xoffset[64] = static const gfx_layout shiplayout = { - 64, 16, /* 64x16 sprites */ - 4, /* 4 sprites */ - 2, /* 2 bits per pixel */ + 64, 16, // 64x16 sprites + 4, // 4 sprites + 2, // 2 bits per pixel { 0, 0x2000 }, EXTENDED_XOFFS, { STEP16(0x000, 0x080) }, - 0x800, /* step */ + 0x800, // step shiplayout_xoffset, nullptr }; static GFXDECODE_START( gfx_starshp1 ) - GFXDECODE_ENTRY( "gfx1", 0, tilelayout, 0, 1 ) - GFXDECODE_ENTRY( "gfx2", 0, spritelayout, 2, 2 ) - GFXDECODE_ENTRY( "gfx3", 0, shiplayout, 6, 2 ) + GFXDECODE_ENTRY( "tiles", 0, tilelayout, 0, 1 ) + GFXDECODE_ENTRY( "sprites", 0, spritelayout, 2, 2 ) + GFXDECODE_ENTRY( "ship", 0, shiplayout, 6, 2 ) GFXDECODE_END void starshp1_state::starshp1(machine_config &config) { - /* basic machine hardware */ + static constexpr XTAL MASTER_CLOCK = 12.096_MHz_XTAL; + static constexpr XTAL CPU_CLOCK = MASTER_CLOCK / 16; + static constexpr XTAL PIXEL_CLOCK = MASTER_CLOCK; + + // basic machine hardware - M6502(config, m_maincpu, STARSHP1_CPU_CLOCK); - m_maincpu->set_addrmap(AS_PROGRAM, &starshp1_state::starshp1_map); - m_maincpu->set_vblank_int("screen", FUNC(starshp1_state::starshp1_interrupt)); + M6502(config, m_maincpu, CPU_CLOCK); + m_maincpu->set_addrmap(AS_PROGRAM, &starshp1_state::program_map); + m_maincpu->set_vblank_int("screen", FUNC(starshp1_state::interrupt)); f9334_device &misclatch(F9334(config, "misclatch")); // C8 misclatch.q_out_cb<0>().set(FUNC(starshp1_state::ship_explode_w)); @@ -308,19 +839,27 @@ void starshp1_state::starshp1(machine_config &config) misclatch.q_out_cb<4>().set(FUNC(starshp1_state::inverse_w)); misclatch.q_out_cb<5>().set_nop(); // BLACK HOLE, not used misclatch.q_out_cb<6>().set(FUNC(starshp1_state::mux_w)); - misclatch.q_out_cb<7>().set(FUNC(starshp1_state::led_w)); + misclatch.q_out_cb<7>().set_output("led0").invert(); + + // video hardware + + static constexpr int HTOTAL = 0x300; + static constexpr int HBEND = 0x000; + static constexpr int HBSTART = 0x200; + static constexpr int VTOTAL = 0x106; + static constexpr int VBEND = 0x000; + static constexpr int VBSTART = 0x0f0; - /* video hardware */ SCREEN(config, m_screen, SCREEN_TYPE_RASTER); - m_screen->set_raw(STARSHP1_PIXEL_CLOCK, STARSHP1_HTOTAL, STARSHP1_HBEND, STARSHP1_HBSTART, STARSHP1_VTOTAL, STARSHP1_VBEND, STARSHP1_VBSTART); - m_screen->set_screen_update(FUNC(starshp1_state::screen_update_starshp1)); - m_screen->screen_vblank().set(FUNC(starshp1_state::screen_vblank_starshp1)); + m_screen->set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART); + m_screen->set_screen_update(FUNC(starshp1_state::screen_update)); + m_screen->screen_vblank().set(FUNC(starshp1_state::screen_vblank)); m_screen->set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_starshp1); - PALETTE(config, m_palette, FUNC(starshp1_state::starshp1_palette), 19, 8); + PALETTE(config, m_palette, FUNC(starshp1_state::palette), 19, 8); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); DISCRETE(config, m_discrete, starshp1_discrete).add_route(ALL_OUTPUTS, "mono", 1.0); @@ -351,20 +890,20 @@ ROM_START( starshp1 ) ROM_LOAD( "7531-02.e3", 0x3800, 0x0800, CRC(b35b2c0e) SHA1(e52240cdfbba3dc380ba63f24cfc07b44feafd53) ) ROM_RELOAD( 0xf800, 0x0800 ) - ROM_REGION( 0x0400, "gfx1", 0 ) + ROM_REGION( 0x0400, "tiles", 0 ) ROM_LOAD( "7513-01.n7", 0x0000, 0x0400, CRC(8fb0045d) SHA1(fb311c6977dec6e2a04179406e9ffdb920989a47) ) - ROM_REGION( 0x0100, "gfx2", 0 ) + ROM_REGION( 0x0100, "sprites", 0 ) ROM_LOAD( "7515-01.j5", 0x0000, 0x0100, CRC(fcbcbf2e) SHA1(adf3cc43b77ad18eddbe39ee11625e552d1abab9) ) - ROM_REGION( 0x0800, "gfx3", 0 ) + ROM_REGION( 0x0800, "ship", 0 ) ROM_LOAD( "7517-01.r1", 0x0000, 0x0400, CRC(1531f85f) SHA1(291822614fc6d3a71bf56607c796e18779f8cfc9) ) ROM_LOAD( "7516-01.p1", 0x0400, 0x0400, CRC(64fbfe4c) SHA1(b2dfdcc1c9927c693fe43b2e1411d0f14375fdeb) ) ROM_REGION( 0x0220, "proms", 0 ) - ROM_LOAD( "7518-01.r10", 0x0000, 0x0100, CRC(80877f7e) SHA1(8b28f48936a4247c583ca6713bfbaf4772c7a4f5) ) /* video output */ - ROM_LOAD( "7514-01.n9", 0x0100, 0x0100, CRC(3610b453) SHA1(9e33ee04f22a9174c29fafb8e71781fa330a7a08) ) /* sync */ - ROM_LOAD( "7519-01.b5", 0x0200, 0x0020, CRC(23b9cd3c) SHA1(220f9f73d86cdcf1b390c52c591750a73402af50) ) /* address */ + ROM_LOAD( "7518-01.r10", 0x0000, 0x0100, CRC(80877f7e) SHA1(8b28f48936a4247c583ca6713bfbaf4772c7a4f5) ) // video output + ROM_LOAD( "7514-01.n9", 0x0100, 0x0100, CRC(3610b453) SHA1(9e33ee04f22a9174c29fafb8e71781fa330a7a08) ) // sync + ROM_LOAD( "7519-01.b5", 0x0200, 0x0020, CRC(23b9cd3c) SHA1(220f9f73d86cdcf1b390c52c591750a73402af50) ) // address ROM_END ROM_START( starshpp ) @@ -388,22 +927,24 @@ ROM_START( starshpp ) ROM_LOAD_NIB_LOW ( "d1", 0x3c00, 0x0400, CRC(be4050b6) SHA1(03ca4833769efb10f18f52b7ba4d016568d3cab9) ) ROM_RELOAD( 0xfc00, 0x0400 ) - ROM_REGION( 0x0400, "gfx1", 0 ) + ROM_REGION( 0x0400, "tiles", 0 ) ROM_LOAD( "7513-01.n7", 0x0000, 0x0400, CRC(8fb0045d) SHA1(fb311c6977dec6e2a04179406e9ffdb920989a47) ) - ROM_REGION( 0x0100, "gfx2", 0 ) + ROM_REGION( 0x0100, "sprites", 0 ) ROM_LOAD( "7515-01.j5", 0x0000, 0x0100, CRC(fcbcbf2e) SHA1(adf3cc43b77ad18eddbe39ee11625e552d1abab9) ) - ROM_REGION( 0x0800, "gfx3", 0 ) + ROM_REGION( 0x0800, "ship", 0 ) ROM_LOAD( "7517-01.r1", 0x0000, 0x0400, CRC(1531f85f) SHA1(291822614fc6d3a71bf56607c796e18779f8cfc9) ) ROM_LOAD( "7516-01.p1", 0x0400, 0x0400, CRC(64fbfe4c) SHA1(b2dfdcc1c9927c693fe43b2e1411d0f14375fdeb) ) ROM_REGION( 0x0220, "proms", 0 ) - ROM_LOAD( "7518-01.r10", 0x0000, 0x0100, CRC(80877f7e) SHA1(8b28f48936a4247c583ca6713bfbaf4772c7a4f5) ) /* video output */ - ROM_LOAD( "7514-01.n9", 0x0100, 0x0100, CRC(3610b453) SHA1(9e33ee04f22a9174c29fafb8e71781fa330a7a08) ) /* sync */ - ROM_LOAD( "7519-01.b5", 0x0200, 0x0020, CRC(23b9cd3c) SHA1(220f9f73d86cdcf1b390c52c591750a73402af50) ) /* address */ + ROM_LOAD( "7518-01.r10", 0x0000, 0x0100, CRC(80877f7e) SHA1(8b28f48936a4247c583ca6713bfbaf4772c7a4f5) ) // video output + ROM_LOAD( "7514-01.n9", 0x0100, 0x0100, CRC(3610b453) SHA1(9e33ee04f22a9174c29fafb8e71781fa330a7a08) ) // sync + ROM_LOAD( "7519-01.b5", 0x0200, 0x0020, CRC(23b9cd3c) SHA1(220f9f73d86cdcf1b390c52c591750a73402af50) ) // address ROM_END +} // anonymous namespace + -GAME( 1977, starshp1, 0, starshp1, starshp1, starshp1_state, empty_init, ORIENTATION_FLIP_X, "Atari", "Starship 1", MACHINE_IMPERFECT_SOUND ) -GAME( 1977, starshpp, starshp1, starshp1, starshp1, starshp1_state, empty_init, ORIENTATION_FLIP_X, "Atari", "Starship 1 (prototype?)", MACHINE_IMPERFECT_SOUND ) +GAME( 1977, starshp1, 0, starshp1, starshp1, starshp1_state, empty_init, ORIENTATION_FLIP_X, "Atari", "Starship 1", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1977, starshpp, starshp1, starshp1, starshp1, starshp1_state, empty_init, ORIENTATION_FLIP_X, "Atari", "Starship 1 (prototype?)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/atari/starshp1.h b/src/mame/atari/starshp1.h deleted file mode 100644 index d2553fc9a57..00000000000 --- a/src/mame/atari/starshp1.h +++ /dev/null @@ -1,163 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Frank Palazzolo, Stefan Jokisch -/* - * The schematics don't seem to make a lot of sense when it - * comes to the video timing chain:: - * - * * there are clear typos -- what is H132??? - * * there are two HBLANK/HSYNC periods as the horizontal - * chain is drawn, which would give an alternating long - * line followed by a much shorter one. This cannot be right - * * the carry-out/load circuit on LS161@J8 is superfluous - * - * These values also give a frame rate of about 45Hz, which is - * probably too low. I suspect that screen is not really - * 512 pixels wide -- most likely 384, which would give 60Hz - * - * Based on photographs of the PCB, and analysis of videos of - * actual gameplay, the horizontal screen really is 384 clocks. - * - * However, some of the graphics, like the starfield, are - * clocked with the 12MHz signal. This effectively doubles - * the horizontal resolution: - * - * 6.048Mhz clocks 12.096Mhz clocks - * Horizontal Visible Area 384 (0x180) 768 (0x300) - * Horizontal Blanking Time 128 (0x080) 256 (0x100) - */ -#ifndef MAME_ATARI_STARSHP1_H -#define MAME_ATARI_STARSHP1_H - -#pragma once - -#include "sound/discrete.h" -#include "emupal.h" -#include "screen.h" -#include "tilemap.h" - - -#define STARSHP1_MASTER_CLOCK (12096000) -#define STARSHP1_CPU_CLOCK (STARSHP1_MASTER_CLOCK / 16) -#define STARSHP1_PIXEL_CLOCK (STARSHP1_MASTER_CLOCK) -#define STARSHP1_HTOTAL (0x300) -#define STARSHP1_HBEND (0x000) -#define STARSHP1_HBSTART (0x200) -#define STARSHP1_VTOTAL (0x106) -#define STARSHP1_VBEND (0x000) -#define STARSHP1_VBSTART (0x0f0) - - -class starshp1_state : public driver_device -{ -public: - starshp1_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_playfield_ram(*this, "playfield_ram"), - m_hpos_ram(*this, "hpos_ram"), - m_vpos_ram(*this, "vpos_ram"), - m_obj_ram(*this, "obj_ram"), - m_maincpu(*this, "maincpu"), - m_discrete(*this, "discrete"), - m_gfxdecode(*this, "gfxdecode"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_led(*this, "led0") - { } - - void starshp1(machine_config &config); - - DECLARE_CUSTOM_INPUT_MEMBER(starshp1_analog_r); - DECLARE_CUSTOM_INPUT_MEMBER(collision_latch_r); - -private: - virtual void machine_start() override; - void starshp1_collision_reset_w(uint8_t data); - void starshp1_analog_in_w(offs_t offset, uint8_t data); - DECLARE_WRITE_LINE_MEMBER(ship_explode_w); - DECLARE_WRITE_LINE_MEMBER(circle_mod_w); - DECLARE_WRITE_LINE_MEMBER(circle_kill_w); - DECLARE_WRITE_LINE_MEMBER(starfield_kill_w); - DECLARE_WRITE_LINE_MEMBER(inverse_w); - DECLARE_WRITE_LINE_MEMBER(mux_w); - DECLARE_WRITE_LINE_MEMBER(led_w); - uint8_t starshp1_rng_r(); - void starshp1_ssadd_w(offs_t offset, uint8_t data); - void starshp1_sspic_w(uint8_t data); - void starshp1_playfield_w(offs_t offset, uint8_t data); - DECLARE_WRITE_LINE_MEMBER(attract_w); - DECLARE_WRITE_LINE_MEMBER(phasor_w); - void starshp1_analog_out_w(offs_t offset, uint8_t data); - TILE_GET_INFO_MEMBER(get_tile_info); - virtual void video_start() override; - void starshp1_palette(palette_device &palette) const; - uint32_t screen_update_starshp1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank_starshp1); - INTERRUPT_GEN_MEMBER(starshp1_interrupt); - void set_pens(); - void draw_starfield(bitmap_ind16 &bitmap, const rectangle &cliprect); - int get_sprite_hpos(int i); - int get_sprite_vpos(int i); - void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_spaceship(bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_phasor(bitmap_ind16 &bitmap); - int get_radius(); - int get_circle_hpos(); - int get_circle_vpos(); - void draw_circle_line(bitmap_ind16 &bitmap, int x, int y, int l); - void draw_circle(bitmap_ind16 &bitmap); - int spaceship_collision(bitmap_ind16 &bitmap, const rectangle &rect); - int point_in_circle(int x, int y, int center_x, int center_y, int r); - int circle_collision(const rectangle &rect); - void starshp1_map(address_map &map); - -private: - int m_analog_in_select = 0; - int m_attract = 0; - required_shared_ptr m_playfield_ram; - required_shared_ptr m_hpos_ram; - required_shared_ptr m_vpos_ram; - required_shared_ptr m_obj_ram; - int m_ship_explode = 0; - int m_ship_picture = 0; - int m_ship_hoffset = 0; - int m_ship_voffset = 0; - int m_ship_size = 0; - int m_circle_hpos = 0; - int m_circle_vpos = 0; - int m_circle_size = 0; - int m_circle_mod = 0; - int m_circle_kill = 0; - int m_phasor = 0; - int m_collision_latch = 0; - int m_starfield_kill = 0; - int m_mux = 0; - int m_inverse = 0; - std::unique_ptr m_LSFR; - bitmap_ind16 m_helper; - tilemap_t *m_bg_tilemap = nullptr; - - required_device m_maincpu; - required_device m_discrete; - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - output_finder<> m_led; -}; - -/*----------- defined in audio/starshp1.c -----------*/ - -DISCRETE_SOUND_EXTERN( starshp1_discrete ); - -/* Discrete Sound Input Nodes */ -#define STARSHP1_NOISE_AMPLITUDE NODE_01 -#define STARSHP1_TONE_PITCH NODE_02 -#define STARSHP1_MOTOR_SPEED NODE_03 -#define STARSHP1_NOISE_FREQ NODE_04 -#define STARSHP1_MOLVL NODE_05 -#define STARSHP1_SL2 NODE_06 -#define STARSHP1_SL1 NODE_07 -#define STARSHP1_KICKER NODE_08 -#define STARSHP1_PHASOR_ON NODE_09 -#define STARSHP1_ATTRACT NODE_10 - -#endif // MAME_ATARI_STARSHP1_H diff --git a/src/mame/atari/starshp1_a.cpp b/src/mame/atari/starshp1_a.cpp index 5b262b7403e..b228b5019c3 100644 --- a/src/mame/atari/starshp1_a.cpp +++ b/src/mame/atari/starshp1_a.cpp @@ -6,9 +6,11 @@ ************************************************************************/ #include "emu.h" -#include "starshp1.h" -#include "sound/discrete.h" +#include "starshp1_a.h" + +#define STARSHP1_PIXEL_CLOCK (12096000) +#define STARSHP1_HTOTAL (0x300) /* voltage out for each 1/256 step of MC1408 circuit */ #define MC1408_DAC(v_ref, r, rf) ((double)v_ref / (double)r * (double)rf / 256.0) @@ -16,7 +18,7 @@ #define OP_AMP_NON_INVERT_GAIN(ri, rf) ((double)rf / (double)ri + 1) /* Discrete Sound Input Nodes */ -/* see "starshp1.h" */ +/* see "starshp1_a.h" */ /* Nodes - Sounds */ #define STARSHP1_PHASOR_SND NODE_13 diff --git a/src/mame/atari/starshp1_a.h b/src/mame/atari/starshp1_a.h new file mode 100644 index 00000000000..1a9adcce8e4 --- /dev/null +++ b/src/mame/atari/starshp1_a.h @@ -0,0 +1,26 @@ +// license:BSD-3-Clause +// copyright-holders:Derrick Renaud + +/*************************************************************************** + +Starship 1 Audio + +***************************************************************************/ + +#include "sound/discrete.h" + +// discrete sound input nodes + +#define STARSHP1_NOISE_AMPLITUDE NODE_01 +#define STARSHP1_TONE_PITCH NODE_02 +#define STARSHP1_MOTOR_SPEED NODE_03 +#define STARSHP1_NOISE_FREQ NODE_04 +#define STARSHP1_MOLVL NODE_05 +#define STARSHP1_SL2 NODE_06 +#define STARSHP1_SL1 NODE_07 +#define STARSHP1_KICKER NODE_08 +#define STARSHP1_PHASOR_ON NODE_09 +#define STARSHP1_ATTRACT NODE_10 + + +DISCRETE_SOUND_EXTERN( starshp1_discrete ); diff --git a/src/mame/atari/starshp1_v.cpp b/src/mame/atari/starshp1_v.cpp deleted file mode 100644 index 7f0de2d414e..00000000000 --- a/src/mame/atari/starshp1_v.cpp +++ /dev/null @@ -1,388 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Frank Palazzolo, Stefan Jokisch -/*************************************************************************** - -Atari Starship 1 video emulation - -***************************************************************************/ - -#include "emu.h" -#include "starshp1.h" - - -void starshp1_state::set_pens() -{ - m_palette->set_indirect_color(m_inverse ? 7 : 0, rgb_t(0x00, 0x00, 0x00)); - m_palette->set_indirect_color(m_inverse ? 6 : 1, rgb_t(0x1e, 0x1e, 0x1e)); - m_palette->set_indirect_color(m_inverse ? 5 : 2, rgb_t(0x4e, 0x4e, 0x4e)); - m_palette->set_indirect_color(m_inverse ? 4 : 3, rgb_t(0x6c, 0x6c, 0x6c)); - m_palette->set_indirect_color(m_inverse ? 3 : 4, rgb_t(0x93, 0x93, 0x93)); - m_palette->set_indirect_color(m_inverse ? 2 : 5, rgb_t(0xb1, 0xb1, 0xb1)); - m_palette->set_indirect_color(m_inverse ? 1 : 6, rgb_t(0xe1, 0xe1, 0xe1)); - m_palette->set_indirect_color(m_inverse ? 0 : 7, rgb_t(0xff, 0xff, 0xff)); -} - - -void starshp1_state::starshp1_palette(palette_device &palette) const -{ - static constexpr uint16_t colortable_source[] = - { - 0, 3, // 0x00 - 0x01 - alpha numerics - 0, 2, // 0x02 - 0x03 - sprites (Z=0) - 0, 5, // 0x04 - 0x05 - sprites (Z=1) - 0, 2, 4, 6, // 0x06 - 0x09 - spaceship (EXPLODE=0) - 0, 6, 6, 7, // 0x0a - 0x0d - spaceship (EXPLODE=1) - 5, 2, // 0x0e - 0x0f - star field - 7, // 0x10 - phasor - 5, 7 // 0x11 - circle - }; - - for (unsigned i = 0; i < std::size(colortable_source); i++) - palette.set_pen_indirect(i, colortable_source[i]); -} - - -TILE_GET_INFO_MEMBER(starshp1_state::get_tile_info) -{ - uint8_t code = m_playfield_ram[tile_index]; - - tileinfo.set(0, code & 0x3f, 0, 0); -} - - -void starshp1_state::video_start() -{ - m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(starshp1_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 8, 32, 8); - m_bg_tilemap->set_transparent_pen(0); - m_bg_tilemap->set_scrollx(0, -8); - - m_LSFR = std::make_unique(0x10000); - - uint16_t val = 0; - for (int i = 0; i < 0x10000; i++) - { - int bit = (val >> 0xf) ^ - (val >> 0xc) ^ - (val >> 0x7) ^ - (val >> 0x1) ^ 1; - - m_LSFR[i] = val; - - val = (val << 1) | (bit & 1); - } - - m_screen->register_screen_bitmap(m_helper); -} - - -uint8_t starshp1_state::starshp1_rng_r() -{ - int width = m_screen->width(); - int height = m_screen->height(); - int x = m_screen->hpos(); - int y = m_screen->vpos(); - - /* the LFSR is only running in the non-blank region - of the screen, so this is not quite right */ - if (x > width - 1) - x = width - 1; - if (y > height - 1) - y = height - 1; - - return m_LSFR[x + (uint16_t) (512 * y)]; -} - - -void starshp1_state::starshp1_ssadd_w(offs_t offset, uint8_t data) -{ - /* - * The range of sprite position values doesn't suffice to - * move the zoomed spaceship sprite over the top and left - * edges of the screen. These additional values are used - * to compensate for this. Technically, they cut off the - * first columns and rows of the spaceship sprite, but in - * practice they work like offsets in zoomed pixels. - */ - - m_ship_voffset = ((offset & 0xf0) >> 4); - m_ship_hoffset = ((offset & 0x0f) << 2) | (data & 3); -} - - -void starshp1_state::starshp1_sspic_w(uint8_t data) -{ - /* - * Some mysterious game code at address $2CCE is causes - * erratic images in the target explosion sequence. But - * This is the way the actual game worked! - */ - - m_ship_picture = data; -} - - -void starshp1_state::starshp1_playfield_w(offs_t offset, uint8_t data) -{ - if (m_mux != 0) - { - offset ^= 0x1f; - m_playfield_ram[offset] = data; - m_bg_tilemap->mark_tile_dirty(offset); - } -} - - -void starshp1_state::draw_starfield(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - /* - * The LSFR is reset once per frame at the position of - * sprite 15. This behavior is quite pointless and not - * really needed by the game. Not emulated. - */ - - for (int y = 0; y <= cliprect.bottom(); y++) - { - uint16_t const *const p = m_LSFR.get() + (uint16_t) (512 * y); - uint16_t *const pLine = &bitmap.pix(y); - - for (int x = 0; x <= cliprect.right(); x++) - if ((p[x] & 0x5b56) == 0x5b44) - pLine[x] = (p[x] & 0x0400) ? 0x0e : 0x0f; - } -} - - -int starshp1_state::get_sprite_hpos(int i) -{ - return 2 * (m_hpos_ram[i] ^ 0xff); -} -int starshp1_state::get_sprite_vpos(int i) -{ - return 1 * (m_vpos_ram[i] - 0x07); -} - - -void starshp1_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - for (int i = 0; i < 14; i++) - { - int code = (m_obj_ram[i] & 0xf) ^ 0xf; - - m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, - code % 8, - code / 8, - 0, 0, - get_sprite_hpos(i), - get_sprite_vpos(i), 0); - } -} - - -void starshp1_state::draw_spaceship(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - double scaler = -5 * log(1 - m_ship_size / 256.0); /* ? */ - - unsigned xzoom = 2 * 0x10000 * scaler; - unsigned yzoom = 1 * 0x10000 * scaler; - - int x = get_sprite_hpos(14); - int y = get_sprite_vpos(14); - - if (x <= 0) - x -= (xzoom * m_ship_hoffset) >> 16; - - if (y <= 0) - y -= (yzoom * m_ship_voffset) >> 16; - - m_gfxdecode->gfx(2)->zoom_transpen(bitmap,cliprect, - m_ship_picture & 0x03, - m_ship_explode, - m_ship_picture & 0x80, 0, - x, y, - xzoom, yzoom, 0); -} - - -void starshp1_state::draw_phasor(bitmap_ind16 &bitmap) -{ - for (int i = 128; i < 240; i++) - if (i >= get_sprite_vpos(13)) - { - bitmap.pix(i, 2 * i + 0) = 0x10; - bitmap.pix(i, 2 * i + 1) = 0x10; - bitmap.pix(i, 2 * (255 - i) + 0) = 0x10; - bitmap.pix(i, 2 * (255 - i) + 1) = 0x10; - } -} - - -int starshp1_state::get_radius() -{ - return 6 * sqrt((double)m_circle_size); /* size calibrated by hand */ -} -int starshp1_state::get_circle_hpos() -{ - return 2 * (3 * m_circle_hpos / 2 - 64); -} -int starshp1_state::get_circle_vpos() -{ - return 1 * (3 * m_circle_vpos / 2 - 64); -} - - -void starshp1_state::draw_circle_line(bitmap_ind16 &bitmap, int x, int y, int l) -{ - if (y >= 0 && y <= bitmap.height() - 1) - { - uint16_t const *const p = m_LSFR.get() + uint16_t(512 * y); - - uint16_t *const pLine = &bitmap.pix(y); - - int h1 = x - 2 * l; - int h2 = x + 2 * l; - - if (h1 < 0) - h1 = 0; - if (h2 > bitmap.width() - 1) - h2 = bitmap.width() - 1; - - for (x = h1; x <= h2; x++) - if (m_circle_mod) - { - if (p[x] & 1) - pLine[x] = 0x11; - } - else - pLine[x] = 0x12; - } -} - - -void starshp1_state::draw_circle(bitmap_ind16 &bitmap) -{ - int cx = get_circle_hpos(); - int cy = get_circle_vpos(); - - int x = 0; - int y = get_radius(); - - /* Bresenham's circle algorithm */ - - int d = 3 - 2 * get_radius(); - - while (x <= y) - { - draw_circle_line(bitmap, cx, cy - x, y); - draw_circle_line(bitmap, cx, cy + x, y); - draw_circle_line(bitmap, cx, cy - y, x); - draw_circle_line(bitmap, cx, cy + y, x); - - x++; - - if (d < 0) - d += 4 * x + 6; - else - d += 4 * (x - y--) + 10; - } -} - - -int starshp1_state::spaceship_collision(bitmap_ind16 &bitmap, const rectangle &rect) -{ - for (int y = rect.top(); y <= rect.bottom(); y++) - { - uint16_t const *const pLine = &m_helper.pix(y); - - for (int x = rect.left(); x <= rect.right(); x++) - if (pLine[x] != 0) - return 1; - } - - return 0; -} - - -int starshp1_state::point_in_circle(int x, int y, int center_x, int center_y, int r) -{ - int dx = abs(x - center_x) / 2; - int dy = abs(y - center_y) / 1; - - return dx * dx + dy * dy < r * r; -} - - -int starshp1_state::circle_collision(const rectangle &rect) -{ - int center_x = get_circle_hpos(); - int center_y = get_circle_vpos(); - - int r = get_radius(); - - return point_in_circle(rect.left(), rect.top(), center_x, center_y, r) || - point_in_circle(rect.left(), rect.bottom(), center_x, center_y, r) || - point_in_circle(rect.right(), rect.top(), center_x, center_y, r) || - point_in_circle(rect.right(), rect.bottom(), center_x, center_y, r); -} - - -uint32_t starshp1_state::screen_update_starshp1(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - set_pens(); - - bitmap.fill(0, cliprect); - - if (m_starfield_kill == 0) - draw_starfield(bitmap, cliprect); - - draw_sprites(bitmap, cliprect); - - if (m_circle_kill == 0 && m_circle_mod != 0) - draw_circle(bitmap); - - if (m_attract == 0) - draw_spaceship(bitmap, cliprect); - - if (m_circle_kill == 0 && m_circle_mod == 0) - draw_circle(bitmap); - - rectangle tilemaprect(0, m_bg_tilemap->width(), 0, m_bg_tilemap->height()); - tilemaprect &= cliprect; - m_bg_tilemap->draw(screen, bitmap, tilemaprect, 0, 0); - - if (m_phasor != 0) - draw_phasor(bitmap); - - return 0; -} - - -WRITE_LINE_MEMBER(starshp1_state::screen_vblank_starshp1) -{ - // rising edge - if (state) - { - const rectangle &visarea = m_screen->visible_area(); - - rectangle rect(get_sprite_hpos(13), 0, get_sprite_vpos(13), 0); - rect.set_size(m_gfxdecode->gfx(1)->width(), m_gfxdecode->gfx(1)->height()); - - rect &= m_helper.cliprect(); - - m_helper.fill(0, visarea); - - if (m_attract == 0) - draw_spaceship(m_helper, visarea); - - if (circle_collision(visarea)) - m_collision_latch |= 1; - - if (circle_collision(rect)) - m_collision_latch |= 2; - - if (spaceship_collision(m_helper, rect)) - m_collision_latch |= 4; - - if (spaceship_collision(m_helper, visarea)) - m_collision_latch |= 8; - } -} diff --git a/src/mame/atari/subs.cpp b/src/mame/atari/subs.cpp index ed9f3bc7269..8f234de30bd 100644 --- a/src/mame/atari/subs.cpp +++ b/src/mame/atari/subs.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Mike Balfour + /*************************************************************************** Atari Subs hardware @@ -20,23 +21,174 @@ ***************************************************************************/ #include "emu.h" -#include "subs.h" + +#include "subs_a.h" #include "cpu/m6502/m6502.h" #include "machine/74259.h" + +#include "emupal.h" #include "screen.h" #include "speaker.h" #include "layout/generic.h" +namespace { + +class subs_state : public driver_device +{ +public: + subs_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_gfxdecode(*this, "gfxdecode"), + m_palette(*this, "palette"), + m_discrete(*this, "discrete"), + m_spriteram(*this, "spriteram"), + m_videoram(*this, "videoram"), + m_dial(*this, "DIAL%u", 1U), + m_in(*this, "IN%u", 0U), + m_dsw(*this, "DSW") + { } + + void subs(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + +private: + required_device m_maincpu; + required_device m_gfxdecode; + required_device m_palette; + required_device m_discrete; + + required_shared_ptr m_spriteram; + required_shared_ptr m_videoram; + + required_ioport_array<2> m_dial; + required_ioport_array<2> m_in; + required_ioport m_dsw; + + int32_t m_steering_buf[2]{}; + uint8_t m_steering_val[2]{}; + int32_t m_last_val[2]{}; + + void steer_reset_w(uint8_t data); + uint8_t control_r(offs_t offset); + uint8_t coin_r(offs_t offset); + uint8_t options_r(offs_t offset); + template DECLARE_WRITE_LINE_MEMBER(invert_w); + void noise_reset_w(uint8_t data); + + void palette(palette_device &palette) const; + + template uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + INTERRUPT_GEN_MEMBER(interrupt); + + template int steering(); + + void main_map(address_map &map); +}; + + +// video + +template +WRITE_LINE_MEMBER(subs_state::invert_w) +{ + if (state) + { + m_palette->set_pen_color(Pen, rgb_t(0x00, 0x00, 0x00)); + m_palette->set_pen_color(Pen + 1, rgb_t(0xff, 0xff, 0xff)); + } + else + { + m_palette->set_pen_color(Pen + 1, rgb_t(0x00, 0x00, 0x00)); + m_palette->set_pen_color(Pen, rgb_t(0xff, 0xff, 0xff)); + } +} + + +template // left 0, right 1 +uint32_t subs_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // for every character in the Video RAM, check if it has been modified + // since last time and update it accordingly. + for (int offs = 0x400 - 1; offs >= 0; offs--) + { + int sonar_window[2]{}; + + int charcode = m_videoram[offs]; + + // Which monitor is this for? + int const enable = Which ? charcode & 0x40 : charcode & 0x80; + + int const sx = 8 * (offs % 32); + int const sy = 8 * (offs / 32); + + // Special hardware logic for sonar windows */ + if ((sy >= (128 + 64)) && (sx < 32)) + sonar_window[0] = 1; + else if ((sy >= (128 + 64)) && (sx >= (128 + 64 + 32))) + sonar_window[1] = 1; + else + charcode = charcode & 0x3f; + + // draw the screen + if ((enable || sonar_window[Which]) && (!sonar_window[!Which])) + m_gfxdecode->gfx(0)->opaque(bitmap, cliprect, + charcode, 1, + 0, 0, sx, sy); + else + m_gfxdecode->gfx(0)->opaque(bitmap, cliprect, + 0, 1, + 0, 0, sx, sy); + } + + // draw the motion objects + for (int offs = 0; offs < 4; offs++) + { + int const sx = m_spriteram[0x00 + (offs * 2)] - 16; + int const sy = m_spriteram[0x08 + (offs * 2)] - 16; + int charcode = m_spriteram[0x09 + (offs * 2)]; + int sub_enable; + if (offs < 2) + sub_enable = m_spriteram[0x01 + (offs * 2)] & 0x80; + else + sub_enable = 1; + + int const prom_set = charcode & 0x01; + charcode = (charcode >> 3) & 0x1f; + + // special check for drawing other screen's sub + if ((offs != Which) || (sub_enable)) + m_gfxdecode->gfx(1)->transpen(bitmap, cliprect, + charcode + 32 * prom_set, + 0, + 0, 0, sx, sy, 0); + } + + if (!Which) + { + // Update sound + m_discrete->write(SUBS_LAUNCH_DATA, m_spriteram[5] & 0x0f); // Launch data + m_discrete->write(SUBS_CRASH_DATA, m_spriteram[5] >> 4); // Crash/explode data + } + + return 0; +} + + /************************************* * * Palette generation * *************************************/ -void subs_state::subs_palette(palette_device &palette) const +void subs_state::palette(palette_device &palette) const { palette.set_pen_color(0, rgb_t(0x00, 0x00, 0x00)); // BLACK - modified on video invert palette.set_pen_color(1, rgb_t(0xff, 0xff, 0xff)); // WHITE - modified on video invert @@ -45,6 +197,152 @@ void subs_state::subs_palette(palette_device &palette) const } +// machine + +/*************************************************************************** +machine initialization +***************************************************************************/ + +void subs_state::machine_start() +{ + save_item(NAME(m_steering_buf)); + save_item(NAME(m_steering_val)); + save_item(NAME(m_last_val)); +} + +void subs_state::machine_reset() +{ + m_steering_buf[0] = 0; + m_steering_buf[1] = 0; + m_steering_val[0] = 0x00; + m_steering_val[1] = 0x00; +} + +/*************************************************************************** +interrupt +***************************************************************************/ +INTERRUPT_GEN_MEMBER(subs_state::interrupt) +{ + // only do NMI interrupt if not in TEST mode + if ((m_in[1]->read() & 0x40) == 0x40) + device.execute().pulse_input_line(INPUT_LINE_NMI, attotime::zero); +} + +/*************************************************************************** +Steering + +When D7 is high, the steering wheel has moved. +If D6 is high, it moved left. If D6 is low, it moved right. +Be sure to keep returning a direction until steer_reset is called. +***************************************************************************/ +template +int subs_state::steering() +{ + int const this_val = m_dial[!Which]->read(); + + int delta = this_val - m_last_val[Which]; + m_last_val[Which] = this_val; + if (delta > 128) delta -= 256; + else if (delta < -128) delta += 256; + // Divide by four to make our steering less sensitive + m_steering_buf[Which] += (delta / 4); + + if (m_steering_buf[Which] > 0) + { + m_steering_buf[Which]--; + m_steering_val[Which] = 0xc0; + } + else if (m_steering_buf[Which] < 0) + { + m_steering_buf[Which]++; + m_steering_val[Which] = 0x80; + } + + return m_steering_val[Which]; +} + +/*************************************************************************** +steer_reset +***************************************************************************/ +void subs_state::steer_reset_w(uint8_t data) +{ + m_steering_val[0] = 0x00; + m_steering_val[1] = 0x00; +} + +/*************************************************************************** +control_r +***************************************************************************/ +uint8_t subs_state::control_r(offs_t offset) +{ + int const inport = m_in[0]->read(); + + switch (offset & 0x07) + { + case 0x00: return ((inport & 0x01) << 7); // diag step + case 0x01: return ((inport & 0x02) << 6); // diag hold + case 0x02: return ((inport & 0x04) << 5); // slam + case 0x03: return ((inport & 0x08) << 4); // spare + case 0x04: return ((steering<0>() & 0x40) << 1); // steer dir 1 + case 0x05: return ((steering<0>() & 0x80) << 0); // steer flag 1 + case 0x06: return ((steering<1>() & 0x40) << 1); // steer dir 2 + case 0x07: return ((steering<1>() & 0x80) << 0); // steer flag 2 + } + + return 0; +} + +/*************************************************************************** +coin_r +***************************************************************************/ +uint8_t subs_state::coin_r(offs_t offset) +{ + int const inport = m_in[1]->read(); + + switch (offset & 0x07) + { + case 0x00: return ((inport & 0x01) << 7); // coin 1 + case 0x01: return ((inport & 0x02) << 6); // start 1 + case 0x02: return ((inport & 0x04) << 5); // coin 2 + case 0x03: return ((inport & 0x08) << 4); // start 2 + case 0x04: return ((inport & 0x10) << 3); // VBLANK + case 0x05: return ((inport & 0x20) << 2); // fire 1 + case 0x06: return ((inport & 0x40) << 1); // test + case 0x07: return ((inport & 0x80) << 0); // fire 2 + } + + return 0; +} + +/*************************************************************************** +options_r +***************************************************************************/ +uint8_t subs_state::options_r(offs_t offset) +{ + int const opts = m_dsw->read(); + + switch (offset & 0x03) + { + case 0x00: return ((opts & 0xc0) >> 6); // language + case 0x01: return ((opts & 0x30) >> 4); // credits + case 0x02: return ((opts & 0x0c) >> 2); // game time + case 0x03: return ((opts & 0x03) >> 0); // extended time + } + + return 0; +} + + +/*************************************************************************** +sub sound functions +***************************************************************************/ + +void subs_state::noise_reset_w(uint8_t data) +{ + // Pulse noise reset + m_discrete->write(SUBS_NOISE_RESET, 0); +} + /************************************* * @@ -63,9 +361,9 @@ void subs_state::main_map(address_map &map) // map(0x0040, 0x0040).w(FUNC(subs_state::timer_reset_w)); map(0x0060, 0x0063).r(FUNC(subs_state::options_r)); map(0x0060, 0x006f).w("latch", FUNC(ls259_device::write_a0)); - map(0x0090, 0x009f).ram().share("spriteram"); + map(0x0090, 0x009f).ram().share(m_spriteram); map(0x00a0, 0x01ff).ram(); - map(0x0800, 0x0bff).ram().share("videoram"); + map(0x0800, 0x0bff).ram().share(m_videoram); map(0x2000, 0x3fff).rom(); } @@ -78,7 +376,7 @@ void subs_state::main_map(address_map &map) *************************************/ static INPUT_PORTS_START( subs ) - PORT_START("DSW") /* OPTIONS */ + PORT_START("DSW") // OPTIONS PORT_DIPNAME( 0x01, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW1:1") PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) @@ -103,14 +401,14 @@ static INPUT_PORTS_START( subs ) PORT_DIPSETTING( 0xc0, "3:30 Minutes" ) PORT_DIPSETTING( 0xe0, "4:00 Minutes" ) - PORT_START("IN0") /* IN1 */ - PORT_BIT ( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* Diag Step */ - PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* Diag Hold */ - PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_TILT ) /* Slam */ - PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) /* Spare */ - PORT_BIT ( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) /* Filled in with steering information */ + PORT_START("IN0") + PORT_BIT ( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN ) // Diag Step + PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN ) // Diag Hold + PORT_BIT ( 0x04, IP_ACTIVE_LOW, IPT_TILT ) // Slam + PORT_BIT ( 0x08, IP_ACTIVE_LOW, IPT_UNUSED ) // Spare + PORT_BIT ( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED ) // Filled in with steering information - PORT_START("IN1") /* IN2 */ + PORT_START("IN1") PORT_BIT ( 0x01, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_BIT ( 0x02, IP_ACTIVE_LOW, IPT_START2 ) PORT_BIT ( 0x04, IP_ACTIVE_HIGH, IPT_COIN1 ) @@ -120,12 +418,11 @@ static INPUT_PORTS_START( subs ) PORT_SERVICE_NO_TOGGLE( 0x40, IP_ACTIVE_LOW ) PORT_BIT ( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_START("DIAL2") /* IN3 */ + PORT_START("DIAL2") PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(100) PORT_KEYDELTA(20) PORT_PLAYER(2) - PORT_START("DIAL1") /* IN4 */ + PORT_START("DIAL1") PORT_BIT( 0xff, 0x00, IPT_DIAL ) PORT_SENSITIVITY(100) PORT_KEYDELTA(20) - INPUT_PORTS_END @@ -164,8 +461,8 @@ static const gfx_layout motion_layout = static GFXDECODE_START( gfx_subs ) - GFXDECODE_ENTRY( "gfx1", 0, playfield_layout, 0, 2 ) /* playfield graphics */ - GFXDECODE_ENTRY( "gfx2", 0, motion_layout, 0, 2 ) /* motion graphics */ + GFXDECODE_ENTRY( "playfield", 0, playfield_layout, 0, 2 ) + GFXDECODE_ENTRY( "motion", 0, motion_layout, 0, 2 ) GFXDECODE_END @@ -177,37 +474,37 @@ GFXDECODE_END void subs_state::subs(machine_config &config) { - /* basic machine hardware */ - M6502(config, m_maincpu, 12096000/16); /* clock input is the "4H" signal */ + // basic machine hardware + M6502(config, m_maincpu, 12'096'000 / 16); // clock input is the "4H" signal m_maincpu->set_addrmap(AS_PROGRAM, &subs_state::main_map); m_maincpu->set_periodic_int(FUNC(subs_state::interrupt), attotime::from_hz(4*57)); - /* video hardware */ + // video hardware GFXDECODE(config, m_gfxdecode, m_palette, gfx_subs); - PALETTE(config, m_palette, FUNC(subs_state::subs_palette), 4); + PALETTE(config, m_palette, FUNC(subs_state::palette), 4); config.set_default_layout(layout_dualhsxs); screen_device &lscreen(SCREEN(config, "lscreen", SCREEN_TYPE_RASTER)); lscreen.set_refresh_hz(57); - lscreen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */); + lscreen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); //not accurate lscreen.set_size(32*8, 32*8); lscreen.set_visarea(0*8, 32*8-1, 0*8, 28*8-1); - lscreen.set_screen_update(FUNC(subs_state::screen_update_left)); + lscreen.set_screen_update(FUNC(subs_state::screen_update<0>)); lscreen.set_palette(m_palette); screen_device &rscreen(SCREEN(config, "rscreen", SCREEN_TYPE_RASTER)); rscreen.set_refresh_hz(57); - rscreen.set_vblank_time(ATTOSECONDS_IN_USEC(2500) /* not accurate */); + rscreen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); //not accurate rscreen.set_size(32*8, 32*8); rscreen.set_visarea(0*8, 32*8-1, 0*8, 28*8-1); - rscreen.set_screen_update(FUNC(subs_state::screen_update_right)); + rscreen.set_screen_update(FUNC(subs_state::screen_update<1>)); rscreen.set_palette(m_palette); - /* sound hardware */ + // sound hardware SPEAKER(config, "lspeaker").front_left(); SPEAKER(config, "rspeaker").front_right(); @@ -221,8 +518,8 @@ void subs_state::subs(machine_config &config) // Schematics show crash and explode reversed. But this is proper. latch.q_out_cb<4>().set(m_discrete, FUNC(discrete_device::write_line)); latch.q_out_cb<5>().set(m_discrete, FUNC(discrete_device::write_line)); - latch.q_out_cb<6>().set(FUNC(subs_state::invert1_w)); - latch.q_out_cb<7>().set(FUNC(subs_state::invert2_w)); + latch.q_out_cb<6>().set(FUNC(subs_state::invert_w<0>)); + latch.q_out_cb<7>().set(FUNC(subs_state::invert_w<2>)); } @@ -235,22 +532,23 @@ void subs_state::subs(machine_config &config) ROM_START( subs ) ROM_REGION( 0x10000, "maincpu", 0 ) - ROM_LOAD_NIB_HIGH( "34196.e2", 0x2000, 0x0100, CRC(7c7a04c3) SHA1(269d9f7573cc5da4412f53d647127c4884435353) ) /* ROM 0 D4-D7 */ - ROM_LOAD_NIB_LOW ( "34194.e1", 0x2000, 0x0100, CRC(6b1c4acc) SHA1(3a743b721d9e7e9bdc4533aeeab294eb0ea27500) ) /* ROM 0 D0-D3 */ - ROM_LOAD( "34190.p1", 0x2800, 0x0800, CRC(a88aef21) SHA1(3811c137041ca43a6e49fbaf7d9d8ef37ba190a2) ) - ROM_LOAD( "34191.p2", 0x3000, 0x0800, CRC(2c652e72) SHA1(097b665e803cbc57b5a828403a8d9a258c19e97f) ) - ROM_LOAD( "34192.n2", 0x3800, 0x0800, CRC(3ce63d33) SHA1(a413cb3e0d03dc40a50f5b03b76a4edbe7906f3e) ) - - ROM_REGION( 0x0800, "gfx1", 0 ) - ROM_LOAD( "34211.m4", 0x0000, 0x0800, CRC(fa8d4409) SHA1(a83b7a835212d31fe421d537fa0d78f234c26f5b) ) /* Playfield */ - - ROM_REGION( 0x0800, "gfx2", 0 ) - ROM_LOAD( "34216.d7", 0x0000, 0x0200, CRC(941d28b4) SHA1(89388ec06546dc567aa5dbc6a7898974f2871ecc) ) /* Motion */ - ROM_LOAD( "34218.e7", 0x0200, 0x0200, CRC(f4f4d874) SHA1(d99ad9a74611f9851f6bfa6000ebd70e1a364f5d) ) /* Motion */ - ROM_LOAD( "34217.d8", 0x0400, 0x0200, CRC(a7a60da3) SHA1(34fc21cc1ca69d58d3907094dc0a3faaf6f461b3) ) /* Motion */ - ROM_LOAD( "34219.e8", 0x0600, 0x0200, CRC(99a5a49b) SHA1(2cb429f8de73c7d78dc83e47f1448ea4340c333d) ) /* Motion */ + ROM_LOAD_NIB_HIGH( "34196.e2", 0x2000, 0x0100, CRC(7c7a04c3) SHA1(269d9f7573cc5da4412f53d647127c4884435353) ) // ROM 0 D4-D7 + ROM_LOAD_NIB_LOW ( "34194.e1", 0x2000, 0x0100, CRC(6b1c4acc) SHA1(3a743b721d9e7e9bdc4533aeeab294eb0ea27500) ) // ROM 0 D0-D3 + ROM_LOAD( "34190.p1", 0x2800, 0x0800, CRC(a88aef21) SHA1(3811c137041ca43a6e49fbaf7d9d8ef37ba190a2) ) + ROM_LOAD( "34191.p2", 0x3000, 0x0800, CRC(2c652e72) SHA1(097b665e803cbc57b5a828403a8d9a258c19e97f) ) + ROM_LOAD( "34192.n2", 0x3800, 0x0800, CRC(3ce63d33) SHA1(a413cb3e0d03dc40a50f5b03b76a4edbe7906f3e) ) + + ROM_REGION( 0x0800, "playfield", 0 ) + ROM_LOAD( "34211.m4", 0x0000, 0x0800, CRC(fa8d4409) SHA1(a83b7a835212d31fe421d537fa0d78f234c26f5b) ) + + ROM_REGION( 0x0800, "motion", 0 ) + ROM_LOAD( "34216.d7", 0x0000, 0x0200, CRC(941d28b4) SHA1(89388ec06546dc567aa5dbc6a7898974f2871ecc) ) + ROM_LOAD( "34218.e7", 0x0200, 0x0200, CRC(f4f4d874) SHA1(d99ad9a74611f9851f6bfa6000ebd70e1a364f5d) ) + ROM_LOAD( "34217.d8", 0x0400, 0x0200, CRC(a7a60da3) SHA1(34fc21cc1ca69d58d3907094dc0a3faaf6f461b3) ) + ROM_LOAD( "34219.e8", 0x0600, 0x0200, CRC(99a5a49b) SHA1(2cb429f8de73c7d78dc83e47f1448ea4340c333d) ) ROM_END +} // anonymous namespace /************************************* diff --git a/src/mame/atari/subs.h b/src/mame/atari/subs.h deleted file mode 100644 index caeedd052eb..00000000000 --- a/src/mame/atari/subs.h +++ /dev/null @@ -1,84 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mike Balfour -/************************************************************************* - - Atari Subs hardware - -*************************************************************************/ -#ifndef MAME_ATARI_SUBS_H -#define MAME_ATARI_SUBS_H - -#pragma once - -#include "sound/discrete.h" -#include "emupal.h" - -/* Discrete Sound Input Nodes */ -#define SUBS_SONAR1_EN NODE_01 -#define SUBS_SONAR2_EN NODE_02 -#define SUBS_LAUNCH_DATA NODE_03 -#define SUBS_CRASH_DATA NODE_04 -#define SUBS_CRASH_EN NODE_05 -#define SUBS_EXPLODE_EN NODE_06 -#define SUBS_NOISE_RESET NODE_07 - - -class subs_state : public driver_device -{ -public: - subs_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_gfxdecode(*this, "gfxdecode"), - m_palette(*this, "palette"), - m_discrete(*this, "discrete"), - m_spriteram(*this, "spriteram"), - m_videoram(*this, "videoram") - { } - - void subs(machine_config &config); - -private: - required_device m_maincpu; - required_device m_gfxdecode; - required_device m_palette; - required_device m_discrete; - - required_shared_ptr m_spriteram; - required_shared_ptr m_videoram; - - int m_steering_buf1 = 0; - int m_steering_buf2 = 0; - int m_steering_val1 = 0; - int m_steering_val2 = 0; - int m_last_val_1 = 0; - int m_last_val_2 = 0; - - void steer_reset_w(uint8_t data); - uint8_t control_r(offs_t offset); - uint8_t coin_r(offs_t offset); - uint8_t options_r(offs_t offset); - DECLARE_WRITE_LINE_MEMBER(invert1_w); - DECLARE_WRITE_LINE_MEMBER(invert2_w); - void noise_reset_w(uint8_t data); - - virtual void machine_start() override; - virtual void machine_reset() override; - void subs_palette(palette_device &palette) const; - - uint32_t screen_update_left(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - uint32_t screen_update_right(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - - INTERRUPT_GEN_MEMBER(interrupt); - - int steering_1(); - int steering_2(); - - void main_map(address_map &map); -}; - -/*----------- defined in audio/subs.c -----------*/ - -DISCRETE_SOUND_EXTERN( subs_discrete ); - -#endif // MAME_ATARI_SUBS_H diff --git a/src/mame/atari/subs_a.cpp b/src/mame/atari/subs_a.cpp index f9f0f1a5c8c..9ba5d8c7fb5 100644 --- a/src/mame/atari/subs_a.cpp +++ b/src/mame/atari/subs_a.cpp @@ -1,24 +1,14 @@ // license:BSD-3-Clause // copyright-holders:Derrick Renaud + /************************************************************************* - audio\subs.cpp + atari\subs_a.cpp *************************************************************************/ #include "emu.h" -#include "subs.h" -#include "sound/discrete.h" - -/*************************************************************************** -sub sound functions -***************************************************************************/ - -void subs_state::noise_reset_w(uint8_t data) -{ - /* Pulse noise reset */ - m_discrete->write(SUBS_NOISE_RESET, 0); -} +#include "subs_a.h" /************************************************************************/ @@ -50,7 +40,7 @@ static const discrete_lfsr_desc subs_lfsr = DISCRETE_SOUND_START(subs_discrete) /************************************************/ - /* subs Effects Relataive Gain Table */ + /* subs Effects Relative Gain Table */ /* */ /* NOTE: The schematic does not show the amp */ /* stage so I will assume a 5K volume control. */ @@ -59,7 +49,7 @@ DISCRETE_SOUND_START(subs_discrete) /* Sonar 2.33 5/(5+2.7) 320.8 */ /* Launch 3.8 5/(5+47) 77.5 */ /* Crash 3.8 5/(5+22) 149.2 */ -/* Explosion 10.0 5/(5+5.6) 1000.0 */ + /* Explosion 10.0 5/(5+5.6) 1000.0 */ /************************************************/ /************************************************/ @@ -81,7 +71,7 @@ DISCRETE_SOUND_START(subs_discrete) DISCRETE_LFSR_NOISE(SUBS_NOISE, SUBS_NOISE_RESET, SUBS_NOISE_RESET, 15750.0, 1.0, 0, 0, &subs_lfsr) /************************************************/ - /* Launch is just amplitude contolled noise */ + /* Launch is just amplitude controlled noise */ /************************************************/ DISCRETE_MULTIPLY(SUBS_LAUNCH_SND, SUBS_NOISE, SUBS_LAUNCH_DATA) diff --git a/src/mame/atari/subs_a.h b/src/mame/atari/subs_a.h new file mode 100644 index 00000000000..711b1d90efa --- /dev/null +++ b/src/mame/atari/subs_a.h @@ -0,0 +1,23 @@ +// license:BSD-3-Clause +// copyright-holders:Derrick Renaud + +/*************************************************************************** + +Subs Audio + +***************************************************************************/ + +#include "sound/discrete.h" + +// discrete sound input nodes + +#define SUBS_SONAR1_EN NODE_01 +#define SUBS_SONAR2_EN NODE_02 +#define SUBS_LAUNCH_DATA NODE_03 +#define SUBS_CRASH_DATA NODE_04 +#define SUBS_CRASH_EN NODE_05 +#define SUBS_EXPLODE_EN NODE_06 +#define SUBS_NOISE_RESET NODE_07 + + +DISCRETE_SOUND_EXTERN( subs_discrete ); diff --git a/src/mame/atari/subs_m.cpp b/src/mame/atari/subs_m.cpp deleted file mode 100644 index 6cfc87ecd56..00000000000 --- a/src/mame/atari/subs_m.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mike Balfour -/*************************************************************************** - - Atari Subs hardware - -***************************************************************************/ - -#include "emu.h" -#include "subs.h" - - -/*************************************************************************** -machine initialization -***************************************************************************/ - -void subs_state::machine_start() -{ - save_item(NAME(m_steering_buf1)); - save_item(NAME(m_steering_buf2)); - save_item(NAME(m_steering_val1)); - save_item(NAME(m_steering_val2)); - save_item(NAME(m_last_val_1)); - save_item(NAME(m_last_val_2)); -} - -void subs_state::machine_reset() -{ - m_steering_buf1 = 0; - m_steering_buf2 = 0; - m_steering_val1 = 0x00; - m_steering_val2 = 0x00; -} - -/*************************************************************************** -interrupt -***************************************************************************/ -INTERRUPT_GEN_MEMBER(subs_state::interrupt) -{ - /* only do NMI interrupt if not in TEST mode */ - if ((ioport("IN1")->read() & 0x40)==0x40) - device.execute().pulse_input_line(INPUT_LINE_NMI, attotime::zero); -} - -/*************************************************************************** -Steering - -When D7 is high, the steering wheel has moved. -If D6 is high, it moved left. If D6 is low, it moved right. -Be sure to keep returning a direction until steer_reset is called. -***************************************************************************/ -int subs_state::steering_1() -{ - int this_val; - int delta; - - this_val=ioport("DIAL2")->read(); - - delta=this_val-m_last_val_1; - m_last_val_1=this_val; - if (delta>128) delta-=256; - else if (delta<-128) delta+=256; - /* Divide by four to make our steering less sensitive */ - m_steering_buf1+=(delta/4); - - if (m_steering_buf1>0) - { - m_steering_buf1--; - m_steering_val1=0xC0; - } - else if (m_steering_buf1<0) - { - m_steering_buf1++; - m_steering_val1=0x80; - } - - return m_steering_val1; -} - -int subs_state::steering_2() -{ - int this_val; - int delta; - - this_val=ioport("DIAL1")->read(); - - delta=this_val-m_last_val_2; - m_last_val_2=this_val; - if (delta>128) delta-=256; - else if (delta<-128) delta+=256; - /* Divide by four to make our steering less sensitive */ - m_steering_buf2+=(delta/4); - - if (m_steering_buf2>0) - { - m_steering_buf2--; - m_steering_val2=0xC0; - } - else if (m_steering_buf2<0) - { - m_steering_buf2++; - m_steering_val2=0x80; - } - - return m_steering_val2; -} - -/*************************************************************************** -steer_reset -***************************************************************************/ -void subs_state::steer_reset_w(uint8_t data) -{ - m_steering_val1 = 0x00; - m_steering_val2 = 0x00; -} - -/*************************************************************************** -control_r -***************************************************************************/ -uint8_t subs_state::control_r(offs_t offset) -{ - int inport = ioport("IN0")->read(); - - switch (offset & 0x07) - { - case 0x00: return ((inport & 0x01) << 7); /* diag step */ - case 0x01: return ((inport & 0x02) << 6); /* diag hold */ - case 0x02: return ((inport & 0x04) << 5); /* slam */ - case 0x03: return ((inport & 0x08) << 4); /* spare */ - case 0x04: return ((steering_1() & 0x40) << 1); /* steer dir 1 */ - case 0x05: return ((steering_1() & 0x80) << 0); /* steer flag 1 */ - case 0x06: return ((steering_2() & 0x40) << 1); /* steer dir 2 */ - case 0x07: return ((steering_2() & 0x80) << 0); /* steer flag 2 */ - } - - return 0; -} - -/*************************************************************************** -coin_r -***************************************************************************/ -uint8_t subs_state::coin_r(offs_t offset) -{ - int inport = ioport("IN1")->read(); - - switch (offset & 0x07) - { - case 0x00: return ((inport & 0x01) << 7); /* coin 1 */ - case 0x01: return ((inport & 0x02) << 6); /* start 1 */ - case 0x02: return ((inport & 0x04) << 5); /* coin 2 */ - case 0x03: return ((inport & 0x08) << 4); /* start 2 */ - case 0x04: return ((inport & 0x10) << 3); /* VBLANK */ - case 0x05: return ((inport & 0x20) << 2); /* fire 1 */ - case 0x06: return ((inport & 0x40) << 1); /* test */ - case 0x07: return ((inport & 0x80) << 0); /* fire 2 */ - } - - return 0; -} - -/*************************************************************************** -options_r -***************************************************************************/ -uint8_t subs_state::options_r(offs_t offset) -{ - int opts = ioport("DSW")->read(); - - switch (offset & 0x03) - { - case 0x00: return ((opts & 0xC0) >> 6); /* language */ - case 0x01: return ((opts & 0x30) >> 4); /* credits */ - case 0x02: return ((opts & 0x0C) >> 2); /* game time */ - case 0x03: return ((opts & 0x03) >> 0); /* extended time */ - } - - return 0; -} diff --git a/src/mame/atari/subs_v.cpp b/src/mame/atari/subs_v.cpp deleted file mode 100644 index 27ace00b6c3..00000000000 --- a/src/mame/atari/subs_v.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mike Balfour -/*************************************************************************** - - Atari Subs hardware - -***************************************************************************/ - -#include "emu.h" -#include "subs.h" -#include "sound/discrete.h" - -WRITE_LINE_MEMBER(subs_state::invert1_w) -{ - if (state) - { - m_palette->set_pen_color(0, rgb_t(0x00, 0x00, 0x00)); - m_palette->set_pen_color(1, rgb_t(0xFF, 0xFF, 0xFF)); - } - else - { - m_palette->set_pen_color(1, rgb_t(0x00, 0x00, 0x00)); - m_palette->set_pen_color(0, rgb_t(0xFF, 0xFF, 0xFF)); - } -} - -WRITE_LINE_MEMBER(subs_state::invert2_w) -{ - if (state) - { - m_palette->set_pen_color(2, rgb_t(0x00, 0x00, 0x00)); - m_palette->set_pen_color(3, rgb_t(0xFF, 0xFF, 0xFF)); - } - else - { - m_palette->set_pen_color(3, rgb_t(0x00, 0x00, 0x00)); - m_palette->set_pen_color(2, rgb_t(0xFF, 0xFF, 0xFF)); - } -} - - -uint32_t subs_state::screen_update_left(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - /* for every character in the Video RAM, check if it has been modified */ - /* since last time and update it accordingly. */ - for (int offs = 0x400 - 1; offs >= 0; offs--) - { - int charcode; - int sx,sy; - int left_enable; //,right_enable; - int left_sonar_window,right_sonar_window; - - left_sonar_window = 0; - right_sonar_window = 0; - - charcode = m_videoram[offs]; - - /* Which monitor is this for? */ -// right_enable = charcode & 0x40; - left_enable = charcode & 0x80; - - sx = 8 * (offs % 32); - sy = 8 * (offs / 32); - - /* Special hardware logic for sonar windows */ - if ((sy >= (128+64)) && (sx < 32)) - left_sonar_window = 1; - else if ((sy >= (128+64)) && (sx >= (128+64+32))) - right_sonar_window = 1; - else - charcode = charcode & 0x3F; - - /* draw the left screen */ - if ((left_enable || left_sonar_window) && (!right_sonar_window)) - m_gfxdecode->gfx(0)->opaque(bitmap,cliprect, - charcode, 1, - 0,0,sx,sy); - else - m_gfxdecode->gfx(0)->opaque(bitmap,cliprect, - 0, 1, - 0,0,sx,sy); - } - - /* draw the motion objects */ - for (int offs = 0; offs < 4; offs++) - { - int sx,sy; - int charcode; - int prom_set; - int sub_enable; - - sx = m_spriteram[0x00 + (offs * 2)] - 16; - sy = m_spriteram[0x08 + (offs * 2)] - 16; - charcode = m_spriteram[0x09 + (offs * 2)]; - if (offs < 2) - sub_enable = m_spriteram[0x01 + (offs * 2)] & 0x80; - else - sub_enable = 1; - - prom_set = charcode & 0x01; - charcode = (charcode >> 3) & 0x1F; - - /* left screen - special check for drawing right screen's sub */ - if ((offs!=0) || (sub_enable)) - m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, - charcode + 32 * prom_set, - 0, - 0,0,sx,sy,0); - } - - /* Update sound */ - m_discrete->write(SUBS_LAUNCH_DATA, m_spriteram[5] & 0x0f); // Launch data - m_discrete->write(SUBS_CRASH_DATA, m_spriteram[5] >> 4); // Crash/explode data - return 0; -} - -uint32_t subs_state::screen_update_right(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - /* for every character in the Video RAM, check if it has been modified */ - /* since last time and update it accordingly. */ - for (int offs = 0x400 - 1; offs >= 0; offs--) - { - int charcode; - int sx,sy; - int right_enable; //, left_enable; - int left_sonar_window,right_sonar_window; - - left_sonar_window = 0; - right_sonar_window = 0; - - charcode = m_videoram[offs]; - - /* Which monitor is this for? */ - right_enable = charcode & 0x40; - //left_enable = charcode & 0x80; - - sx = 8 * (offs % 32); - sy = 8 * (offs / 32); - - /* Special hardware logic for sonar windows */ - if ((sy >= (128+64)) && (sx < 32)) - left_sonar_window = 1; - else if ((sy >= (128+64)) && (sx >= (128+64+32))) - right_sonar_window = 1; - else - charcode = charcode & 0x3F; - - /* draw the right screen */ - if ((right_enable || right_sonar_window) && (!left_sonar_window)) - m_gfxdecode->gfx(0)->opaque(bitmap,cliprect, - charcode, 0, - 0,0,sx,sy); - else - m_gfxdecode->gfx(0)->opaque(bitmap,cliprect, - 0, 0, - 0,0,sx,sy); - } - - /* draw the motion objects */ - for (int offs = 0; offs < 4; offs++) - { - int sx,sy; - int charcode; - int prom_set; - int sub_enable; - - sx = m_spriteram[0x00 + (offs * 2)] - 16; - sy = m_spriteram[0x08 + (offs * 2)] - 16; - charcode = m_spriteram[0x09 + (offs * 2)]; - if (offs < 2) - sub_enable = m_spriteram[0x01 + (offs * 2)] & 0x80; - else - sub_enable = 1; - - prom_set = charcode & 0x01; - charcode = (charcode >> 3) & 0x1F; - - if ((offs!=1) || (sub_enable)) - m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, - charcode + 32 * prom_set, - 0, - 0,0,sx,sy,0); - } - - return 0; -} diff --git a/src/mame/atari/tank8.cpp b/src/mame/atari/tank8.cpp index 95379f5c69a..6cf51aa0738 100644 --- a/src/mame/atari/tank8.cpp +++ b/src/mame/atari/tank8.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Stefan Jokisch + /*************************************************************************** Atari Tank 8 driver @@ -7,14 +8,348 @@ Atari Tank 8 driver ***************************************************************************/ #include "emu.h" -#include "tank8.h" + +#include "tank8_a.h" #include "cpu/m6800/m6800.h" #include "sound/discrete.h" + +#include "emupal.h" +#include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +namespace { + +class tank8_state : public driver_device +{ +public: + tank8_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu"), + m_discrete(*this, "discrete"), + m_gfxdecode(*this, "gfxdecode"), + m_screen(*this, "screen"), + m_palette(*this, "palette"), + m_video_ram(*this, "video_ram"), + m_pos_h_ram(*this, "pos_h_ram"), + m_pos_v_ram(*this, "pos_v_ram"), + m_pos_d_ram(*this, "pos_d_ram"), + m_team(*this, "team") + { } + + void tank8(machine_config &config); + + void init_decode(); + +protected: + virtual void machine_reset() override; + virtual void video_start() override; + +private: + required_device m_maincpu; + required_device m_discrete; + required_device m_gfxdecode; + required_device m_screen; + required_device m_palette; + + required_shared_ptr m_video_ram; + required_shared_ptr m_pos_h_ram; + required_shared_ptr m_pos_v_ram; + required_shared_ptr m_pos_d_ram; + required_shared_ptr m_team; + + int32_t m_collision_index = 0; + tilemap_t *m_tilemap = nullptr; + bitmap_ind16 m_helper[3]; + emu_timer *m_collision_timer = nullptr; + + uint8_t collision_r(); + void lockout_w(offs_t offset, uint8_t data); + void int_reset_w(uint8_t data); + void video_ram_w(offs_t offset, uint8_t data); + void crash_w(uint8_t data); + void explosion_w(uint8_t data); + void bugle_w(uint8_t data); + void bug_w(uint8_t data); + void attract_w(uint8_t data); + void motor_w(offs_t offset, uint8_t data); + + TILE_GET_INFO_MEMBER(get_tile_info); + + void palette(palette_device &palette) const; + + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + DECLARE_WRITE_LINE_MEMBER(screen_vblank); + void set_pens(); + inline int get_x_pos(int n); + inline int get_y_pos(int n); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void draw_bullets(bitmap_ind16 &bitmap, const rectangle &cliprect); + TIMER_CALLBACK_MEMBER(set_collision); + + void cpu_map(address_map &map); +}; + + +// video + +void tank8_state::palette(palette_device &palette) const +{ + palette.set_indirect_color(8, rgb_t(0x00, 0x00, 0x00)); + palette.set_indirect_color(9, rgb_t(0xff, 0xff, 0xff)); + + for (int i = 0; i < 8; i++) + { + palette.set_pen_indirect(2 * i + 0, 8); + palette.set_pen_indirect(2 * i + 1, i); + } + + // walls + palette.set_pen_indirect(0x10, 8); + palette.set_pen_indirect(0x11, 9); + + // mines + palette.set_pen_indirect(0x12, 8); + palette.set_pen_indirect(0x13, 9); +} + + +void tank8_state::set_pens() +{ + if (*m_team & 0x01) + { + m_palette->set_indirect_color(0, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(1, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(2, rgb_t(0xff, 0xff, 0x00)); // yellow + m_palette->set_indirect_color(3, rgb_t(0x00, 0xff, 0x00)); // green + m_palette->set_indirect_color(4, rgb_t(0xff, 0x00, 0xff)); // magenta + m_palette->set_indirect_color(5, rgb_t(0xe0, 0xc0, 0x70)); // puce + m_palette->set_indirect_color(6, rgb_t(0x00, 0xff, 0xff)); // cyan + m_palette->set_indirect_color(7, rgb_t(0xff, 0xaa, 0xaa)); // pink + } + else + { + m_palette->set_indirect_color(0, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(2, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(4, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(6, rgb_t(0xff, 0x00, 0x00)); // red + m_palette->set_indirect_color(1, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(3, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(5, rgb_t(0x00, 0x00, 0xff)); // blue + m_palette->set_indirect_color(7, rgb_t(0x00, 0x00, 0xff)); // blue + } +} + + +void tank8_state::video_ram_w(offs_t offset, uint8_t data) +{ + m_video_ram[offset] = data; + m_tilemap->mark_tile_dirty(offset); +} + + + +TILE_GET_INFO_MEMBER(tank8_state::get_tile_info) +{ + uint8_t const code = m_video_ram[tile_index]; + + int color = 0; + + if ((code & 0x38) == 0x28) + { + if ((code & 7) != 3) + color = 8; // walls + else + color = 9; // mines + } + else + { + if (tile_index & 0x010) + color |= 1; + + if (code & 0x80) + color |= 2; + + if (tile_index & 0x200) + color |= 4; + } + + tileinfo.set(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0); +} +void tank8_state::video_start() +{ + m_collision_timer = timer_alloc(FUNC(tank8_state::set_collision), this); + + m_screen->register_screen_bitmap(m_helper[0]); + m_screen->register_screen_bitmap(m_helper[1]); + m_screen->register_screen_bitmap(m_helper[2]); + + m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tank8_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); + + // VBLANK starts on scanline #256 and ends on scanline #24 + m_tilemap->set_scrolly(0, 2 * 24); + + save_item(NAME(m_collision_index)); +} + + +int tank8_state::get_x_pos(int n) +{ + return 498 - m_pos_h_ram[n] - 2 * (m_pos_d_ram[n] & 128); // ? +} + + +int tank8_state::get_y_pos(int n) +{ + return 2 * m_pos_v_ram[n] - 62; +} + + +void tank8_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int i = 0; i < 8; i++) + { + uint8_t const code = ~m_pos_d_ram[i]; + + int const x = get_x_pos(i); + int const y = get_y_pos(i); + + m_gfxdecode->gfx((code & 0x04) ? 2 : 3)->transpen(bitmap, cliprect, + code & 0x03, + i, + code & 0x10, + code & 0x08, + x, + y, 0); + } +} + + +void tank8_state::draw_bullets(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + for (int i = 0; i < 8; i++) + { + int x = get_x_pos(8 + i); + int const y = get_y_pos(8 + i); + + x -= 4; // ? + + rectangle rect(x, x + 3, y, y + 4); + rect &= cliprect; + + bitmap.fill((i << 1) | 0x01, rect); + } +} + + +uint32_t tank8_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + set_pens(); + m_tilemap->draw(screen, bitmap, cliprect, 0, 0); + + draw_sprites(bitmap, cliprect); + draw_bullets(bitmap, cliprect); + return 0; +} + + +WRITE_LINE_MEMBER(tank8_state::screen_vblank) +{ + // on falling edge + if (!state) + { + const rectangle &visarea = m_screen->visible_area(); + + m_tilemap->draw(*m_screen, m_helper[0], visarea, 0, 0); + + m_helper[1].fill(8, visarea); + m_helper[2].fill(8, visarea); + + draw_sprites(m_helper[1], visarea); + draw_bullets(m_helper[2], visarea); + + for (int y = visarea.top(); y <= visarea.bottom(); y++) + { + int _state = 0; + + uint16_t const *const p1 = &m_helper[0].pix(y); + uint16_t const *const p2 = &m_helper[1].pix(y); + uint16_t const *const p3 = &m_helper[2].pix(y); + + if ((m_screen->frame_number() ^ y) & 1) + continue; // video display is interlaced + + for (int x = visarea.left(); x <= visarea.right(); x++) + { + // neither wall nor mine + if ((p1[x] != 0x11) && (p1[x] != 0x13)) + { + _state = 0; + continue; + } + + // neither tank nor bullet + if ((p2[x] == 8) && (p3[x] == 8)) + { + _state = 0; + continue; + } + + // bullets cannot hit mines + if ((p3[x] != 8) && (p1[x] == 0x13)) + { + _state = 0; + continue; + } + + if (_state) + continue; + + uint8_t index; + if (p3[x] != 8) + { + index = ((p3[x] & ~0x01) >> 1) | 0x18; + + if (1) + index |= 0x20; + + if (0) + index |= 0x40; + + if (1) + index |= 0x80; + } + else + { + int const sprite_num = (p2[x] & ~0x01) >> 1; + index = sprite_num | 0x10; + + if (p1[x] == 0x11) + index |= 0x20; + + if (y - get_y_pos(sprite_num) >= 8) + index |= 0x40; // collision on bottom side + + if (x - get_x_pos(sprite_num) >= 8) + index |= 0x80; // collision on right side + } + + m_collision_timer->adjust(m_screen->time_until_pos(y, x), index); + + _state = 1; + } + } + } +} + + +// machine + TIMER_CALLBACK_MEMBER(tank8_state::set_collision) { m_maincpu->set_input_line(0, ASSERT_LINE); @@ -64,23 +399,23 @@ void tank8_state::bugle_w(uint8_t data) void tank8_state::bug_w(uint8_t data) { - /* D0 and D1 determine the on/off time off the square wave */ + // D0 and D1 determine the on/off time off the square wave switch(data & 3) { case 0: - m_discrete->write(TANK8_BUGLE_DATA1,8.0); - m_discrete->write(TANK8_BUGLE_DATA2,4.0); + m_discrete->write(TANK8_BUGLE_DATA1, 8.0); + m_discrete->write(TANK8_BUGLE_DATA2, 4.0); break; case 1: - m_discrete->write(TANK8_BUGLE_DATA1,8.0); - m_discrete->write(TANK8_BUGLE_DATA2,7.0); + m_discrete->write(TANK8_BUGLE_DATA1, 8.0); + m_discrete->write(TANK8_BUGLE_DATA2, 7.0); break; case 2: - m_discrete->write(TANK8_BUGLE_DATA1,8.0); - m_discrete->write(TANK8_BUGLE_DATA2,2.0); + m_discrete->write(TANK8_BUGLE_DATA1, 8.0); + m_discrete->write(TANK8_BUGLE_DATA2, 2.0); break; case 3: - m_discrete->write(TANK8_BUGLE_DATA1,16.0); - m_discrete->write(TANK8_BUGLE_DATA2,4.0); + m_discrete->write(TANK8_BUGLE_DATA1, 16.0); + m_discrete->write(TANK8_BUGLE_DATA2, 4.0); break; } @@ -96,7 +431,7 @@ void tank8_state::motor_w(offs_t offset, uint8_t data) m_discrete->write(NODE_RELATIVE(TANK8_MOTOR1_EN, offset), data); } -void tank8_state::tank8_cpu_map(address_map &map) +void tank8_state::cpu_map(address_map &map) { map(0x0000, 0x00ff).ram(); map(0x0400, 0x17ff).rom(); @@ -117,10 +452,10 @@ void tank8_state::tank8_cpu_map(address_map &map) map(0x1c0b, 0x1c0b).portr("RC"); map(0x1c0f, 0x1c0f).portr("VBLANK"); - map(0x1800, 0x1bff).w(FUNC(tank8_state::video_ram_w)).share("video_ram"); - map(0x1c00, 0x1c0f).writeonly().share("pos_h_ram"); - map(0x1c10, 0x1c1f).writeonly().share("pos_v_ram"); - map(0x1c20, 0x1c2f).writeonly().share("pos_d_ram"); + map(0x1800, 0x1bff).w(FUNC(tank8_state::video_ram_w)).share(m_video_ram); + map(0x1c00, 0x1c0f).writeonly().share(m_pos_h_ram); + map(0x1c10, 0x1c1f).writeonly().share(m_pos_v_ram); + map(0x1c20, 0x1c2f).writeonly().share(m_pos_d_ram); map(0x1c30, 0x1c37).w(FUNC(tank8_state::lockout_w)); map(0x1d00, 0x1d00).w(FUNC(tank8_state::int_reset_w)); @@ -128,7 +463,7 @@ void tank8_state::tank8_cpu_map(address_map &map) map(0x1d02, 0x1d02).w(FUNC(tank8_state::explosion_w)); map(0x1d03, 0x1d03).w(FUNC(tank8_state::bugle_w)); map(0x1d04, 0x1d04).w(FUNC(tank8_state::bug_w)); - map(0x1d05, 0x1d05).writeonly().share("team"); + map(0x1d05, 0x1d05).writeonly().share(m_team); map(0x1d06, 0x1d06).w(FUNC(tank8_state::attract_w)); map(0x1e00, 0x1e07).w(FUNC(tank8_state::motor_w)); @@ -216,7 +551,7 @@ static INPUT_PORTS_START( tank8 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(8) - /* play time setting according to documents */ + // play time setting according to documents PORT_START("DSW1") PORT_DIPNAME( 0x0f, 0x08, "Play Time" ) PORT_DIPSETTING( 0x0f, "60 seconds" ) @@ -321,20 +656,20 @@ static const gfx_layout tank_layout = static GFXDECODE_START( gfx_tank8 ) - GFXDECODE_ENTRY( "gfx1", 0, tile_layout_1, 0, 10 ) - GFXDECODE_ENTRY( "gfx1", 0, tile_layout_2, 0, 10 ) - GFXDECODE_ENTRY( "gfx2", 0, tank_layout, 0, 8 ) - GFXDECODE_ENTRY( "gfx3", 0, tank_layout, 0, 8 ) + GFXDECODE_ENTRY( "tiles", 0, tile_layout_1, 0, 10 ) + GFXDECODE_ENTRY( "tiles", 0, tile_layout_2, 0, 10 ) + GFXDECODE_ENTRY( "tank1", 0, tank_layout, 0, 8 ) + GFXDECODE_ENTRY( "tank2", 0, tank_layout, 0, 8 ) GFXDECODE_END void tank8_state::tank8(machine_config &config) { - /* basic machine hardware */ - M6800(config, m_maincpu, 11055000 / 10); /* ? */ - m_maincpu->set_addrmap(AS_PROGRAM, &tank8_state::tank8_cpu_map); + // basic machine hardware + M6800(config, m_maincpu, 11'055'000 / 10); // ? + m_maincpu->set_addrmap(AS_PROGRAM, &tank8_state::cpu_map); - /* video hardware */ + // video hardware SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_video_attributes(VIDEO_UPDATE_AFTER_VBLANK); m_screen->set_refresh_hz(60); @@ -346,9 +681,9 @@ void tank8_state::tank8(machine_config &config) m_screen->set_palette(m_palette); GFXDECODE(config, m_gfxdecode, m_palette, gfx_tank8); - PALETTE(config, m_palette, FUNC(tank8_state::tank8_palette), 20, 10); + PALETTE(config, m_palette, FUNC(tank8_state::palette), 20, 10); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); DISCRETE(config, m_discrete, tank8_discrete).add_route(ALL_OUTPUTS, "mono", 0.3); @@ -363,16 +698,16 @@ ROM_START( tank8a ) ROM_LOAD( "5073.f1", 0x11400, 0x0200, CRC(deedbe7c) SHA1(686c498d4c87054e00a9cfc0588e49f72470e1f9) ) ROM_LOAD( "5074.j1", 0x11600, 0x0200, CRC(e49098b4) SHA1(5019ab0d4f3cd22733a60f15a54e4b772f534430) ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */ + ROM_REGION( 0x0200, "tiles", 0 ) ROM_LOAD( "5075.n6", 0x0000, 0x0200, CRC(2d6519b3) SHA1(3837687893d0fca683ff9b86b335a77d98fd4230) ) - ROM_REGION( 0x0100, "gfx2", 0 ) /* tanks #1 */ + ROM_REGION( 0x0100, "tank1", 0 ) ROM_LOAD( "5079.h5", 0x0000, 0x0100, CRC(5c32d471) SHA1(983c7f15ad3a50ab87157b6894b9c292358de5a1) ) - ROM_REGION( 0x0100, "gfx3", 0 ) /* tanks #2 */ + ROM_REGION( 0x0100, "tank2", 0 ) ROM_LOAD( "5078.j5", 0x0000, 0x0100, CRC(ab083245) SHA1(e084627a4a17dd274d31638c938a04aa5049359b) ) - ROM_REGION( 0x0100, "user1", 0 ) /* decode PROMs */ + ROM_REGION( 0x0100, "decode_proms", 0 ) ROM_LOAD_NIB_LOW ( "5077.k1", 0x0000, 0x0100, CRC(343fc116) SHA1(ac9e95fc2a5dc115e8158d69482882072bea972b) ) ROM_LOAD_NIB_HIGH( "5076.l1", 0x0000, 0x0100, CRC(4e1d9dad) SHA1(dc467914cbc8fd1add2d5e3b988e9596037b3a1e) ) ROM_END @@ -386,16 +721,16 @@ ROM_START( tank8b ) ROM_LOAD( "5764.f1", 0x11400, 0x0200, CRC(da4e81e0) SHA1(7e504b7064a8fed9dd7a6fe013f22427edc52384) ) ROM_LOAD( "5765.j1", 0x11600, 0x0200, CRC(537e0c75) SHA1(b35db8d316cef9a2603b64868023e72e21d03143) ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */ + ROM_REGION( 0x0200, "tiles", 0 ) ROM_LOAD( "5075.n6", 0x0000, 0x0200, CRC(2d6519b3) SHA1(3837687893d0fca683ff9b86b335a77d98fd4230) ) - ROM_REGION( 0x0100, "gfx2", 0 ) /* tanks #1 */ + ROM_REGION( 0x0100, "tank1", 0 ) ROM_LOAD( "5079.h5", 0x0000, 0x0100, CRC(5c32d471) SHA1(983c7f15ad3a50ab87157b6894b9c292358de5a1) ) - ROM_REGION( 0x0100, "gfx3", 0 ) /* tanks #2 */ + ROM_REGION( 0x0100, "tank2", 0 ) ROM_LOAD( "5078.j5", 0x0000, 0x0100, CRC(ab083245) SHA1(e084627a4a17dd274d31638c938a04aa5049359b) ) - ROM_REGION( 0x0100, "user1", 0 ) /* decode PROMs */ + ROM_REGION( 0x0100, "decode_proms", 0 ) ROM_LOAD_NIB_LOW ( "5077.k1", 0x0000, 0x0100, CRC(343fc116) SHA1(ac9e95fc2a5dc115e8158d69482882072bea972b) ) ROM_LOAD_NIB_HIGH( "5076.l1", 0x0000, 0x0100, CRC(4e1d9dad) SHA1(dc467914cbc8fd1add2d5e3b988e9596037b3a1e) ) ROM_END @@ -403,38 +738,38 @@ ROM_END ROM_START( tank8c ) ROM_REGION( 0x10000, "maincpu", 0 ) - ROM_LOAD( "a05071.c1", 0x0400, 0x0800, /* wrong revision */ CRC(2211fb2c) SHA1(6d44d1e9c94a7cb364c8809445c015a6510b8c5f) ) + ROM_LOAD( "a05071.c1", 0x0400, 0x0800, CRC(2211fb2c) SHA1(6d44d1e9c94a7cb364c8809445c015a6510b8c5f) ) // wrong revision ROM_LOAD( "a05072.e1", 0x0c00, 0x0800, CRC(d907b116) SHA1(290a77e6095d4ffc2365d784e74e115fe90617fb) ) ROM_RELOAD( 0xf800, 0x0800 ) ROM_LOAD( "a05473.f1", 0x1400, 0x0200, CRC(109020db) SHA1(c8517a09c1ff36a1b08c4a71acaae55dc48fc45b) ) ROM_LOAD( "a05474.j1", 0x1600, 0x0200, CRC(64d8a386) SHA1(fdb6669762ddebbd775c66d67d82876428dfe009) ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */ + ROM_REGION( 0x0200, "tiles", 0 ) ROM_LOAD( "5075.n6", 0x0000, 0x0200, CRC(2d6519b3) SHA1(3837687893d0fca683ff9b86b335a77d98fd4230) ) - ROM_REGION( 0x0100, "gfx2", 0 ) /* tanks #1 */ + ROM_REGION( 0x0100, "tank1", 0 ) ROM_LOAD( "5079.h5", 0x0000, 0x0100, CRC(5c32d471) SHA1(983c7f15ad3a50ab87157b6894b9c292358de5a1) ) - ROM_REGION( 0x0100, "gfx3", 0 ) /* tanks #2 */ + ROM_REGION( 0x0100, "tank2", 0 ) ROM_LOAD( "5078.j5", 0x0000, 0x0100, CRC(ab083245) SHA1(e084627a4a17dd274d31638c938a04aa5049359b) ) ROM_END ROM_START( tank8d ) ROM_REGION( 0x10000, "maincpu", 0 ) - ROM_LOAD( "a05071.c1", 0x0400, 0x0800, /* wrong revision */ CRC(2211fb2c) SHA1(6d44d1e9c94a7cb364c8809445c015a6510b8c5f) ) + ROM_LOAD( "a05071.c1", 0x0400, 0x0800, CRC(2211fb2c) SHA1(6d44d1e9c94a7cb364c8809445c015a6510b8c5f) ) // wrong revision ROM_LOAD( "a05072.e1", 0x0c00, 0x0800, CRC(d907b116) SHA1(290a77e6095d4ffc2365d784e74e115fe90617fb) ) ROM_RELOAD( 0xf800, 0x0800 ) ROM_LOAD( "a05918.f1", 0x1400, 0x0200, CRC(c2fca931) SHA1(a5aea79ef560d4498ba38482260f49a09cfe59d6) ) ROM_LOAD( "a05919.j1", 0x1600, 0x0200, CRC(47204dc0) SHA1(b602e26b615e5e8bb747e9bd3879e4b95d923dc1) ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */ + ROM_REGION( 0x0200, "tiles", 0 ) ROM_LOAD( "5075.n6", 0x0000, 0x0200, CRC(2d6519b3) SHA1(3837687893d0fca683ff9b86b335a77d98fd4230) ) - ROM_REGION( 0x0100, "gfx2", 0 ) /* tanks #1 */ + ROM_REGION( 0x0100, "tank1", 0 ) ROM_LOAD( "5079.h5", 0x0000, 0x0100, CRC(5c32d471) SHA1(983c7f15ad3a50ab87157b6894b9c292358de5a1) ) - ROM_REGION( 0x0100, "gfx3", 0 ) /* tanks #2 */ + ROM_REGION( 0x0100, "tank2", 0 ) ROM_LOAD( "5078.j5", 0x0000, 0x0100, CRC(ab083245) SHA1(e084627a4a17dd274d31638c938a04aa5049359b) ) ROM_END @@ -447,33 +782,35 @@ ROM_START( tank8 ) ROM_LOAD( "b05476.f1", 0x1400, 0x0200, CRC(98754edd) SHA1(56eb017bad9c29649573875a6b13189f2ba69b0e) ) ROM_LOAD( "b05477.j1", 0x1600, 0x0200, CRC(5087223b) SHA1(fea032e6d0b3e0730a1180e57118e1765693f67e) ) - ROM_REGION( 0x0200, "gfx1", 0 ) /* tiles */ + ROM_REGION( 0x0200, "tiles", 0 ) ROM_LOAD( "5075.n6", 0x0000, 0x0200, CRC(2d6519b3) SHA1(3837687893d0fca683ff9b86b335a77d98fd4230) ) - ROM_REGION( 0x0100, "gfx2", 0 ) /* tanks #1 */ + ROM_REGION( 0x0100, "tank1", 0 ) ROM_LOAD( "5079.h5", 0x0000, 0x0100, CRC(5c32d471) SHA1(983c7f15ad3a50ab87157b6894b9c292358de5a1) ) - ROM_REGION( 0x0100, "gfx3", 0 ) /* tanks #2 */ + ROM_REGION( 0x0100, "tank2", 0 ) ROM_LOAD( "5078.j5", 0x0000, 0x0100, CRC(ab083245) SHA1(e084627a4a17dd274d31638c938a04aa5049359b) ) ROM_END void tank8_state::init_decode() { - const uint8_t* DECODE = memregion("user1")->base(); + const uint8_t* decode = memregion("decode_proms")->base(); uint8_t* p1 = memregion("maincpu")->base() + 0x00000; uint8_t* p2 = memregion("maincpu")->base() + 0x10000; for (int i = 0x0400; i <= 0x17ff; i++) { - p1[i] = DECODE[p2[i]]; + p1[i] = decode[p2[i]]; } for (int i = 0xf800; i <= 0xffff; i++) { - p1[i] = DECODE[p2[i]]; + p1[i] = decode[p2[i]]; } } +} // anonymous namespace + GAME( 1976, tank8, 0, tank8, tank8, tank8_state, empty_init, ROT0, "Atari (Kee Games)", "Tank 8 (set 1)", MACHINE_SUPPORTS_SAVE) GAME( 1976, tank8a, tank8, tank8, tank8, tank8_state, init_decode, ROT0, "Atari (Kee Games)", "Tank 8 (set 2)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/atari/tank8.h b/src/mame/atari/tank8.h deleted file mode 100644 index 75a72e18cc1..00000000000 --- a/src/mame/atari/tank8.h +++ /dev/null @@ -1,109 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Stefan Jokisch -/************************************************************************* - - Atari tank8 hardware - -*************************************************************************/ -#ifndef MAME_ATARI_TANK8_H -#define MAME_ATARI_TANK8_H - -#pragma once - -#include "sound/discrete.h" -#include "emupal.h" -#include "screen.h" -#include "tilemap.h" - -/* Discrete Sound Input Nodes */ -#define TANK8_CRASH_EN NODE_01 -#define TANK8_BUGLE_EN NODE_02 -#define TANK8_MOTOR1_EN NODE_03 -#define TANK8_MOTOR2_EN NODE_04 -#define TANK8_MOTOR3_EN NODE_05 -#define TANK8_MOTOR4_EN NODE_06 -#define TANK8_MOTOR5_EN NODE_07 -#define TANK8_MOTOR6_EN NODE_08 -#define TANK8_MOTOR7_EN NODE_09 -#define TANK8_MOTOR8_EN NODE_10 -#define TANK8_EXPLOSION_EN NODE_11 -#define TANK8_ATTRACT_EN NODE_12 -#define TANK8_BUGLE_DATA1 NODE_13 -#define TANK8_BUGLE_DATA2 NODE_14 - - -class tank8_state : public driver_device -{ -public: - tank8_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_maincpu(*this, "maincpu"), - m_discrete(*this, "discrete"), - m_gfxdecode(*this, "gfxdecode"), - m_screen(*this, "screen"), - m_palette(*this, "palette"), - m_video_ram(*this, "video_ram"), - m_pos_h_ram(*this, "pos_h_ram"), - m_pos_v_ram(*this, "pos_v_ram"), - m_pos_d_ram(*this, "pos_d_ram"), - m_team(*this, "team") - { } - - void tank8(machine_config &config); - - void init_decode(); - -private: - uint8_t collision_r(); - void lockout_w(offs_t offset, uint8_t data); - void int_reset_w(uint8_t data); - void video_ram_w(offs_t offset, uint8_t data); - void crash_w(uint8_t data); - void explosion_w(uint8_t data); - void bugle_w(uint8_t data); - void bug_w(uint8_t data); - void attract_w(uint8_t data); - void motor_w(offs_t offset, uint8_t data); - - TILE_GET_INFO_MEMBER(get_tile_info); - - virtual void machine_reset() override; - virtual void video_start() override; - void tank8_palette(palette_device &palette) const; - - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(screen_vblank); - void set_pens(); - inline int get_x_pos(int n); - inline int get_y_pos(int n); - void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); - void draw_bullets(bitmap_ind16 &bitmap, const rectangle &cliprect); - TIMER_CALLBACK_MEMBER(set_collision); - - void tank8_cpu_map(address_map &map); - - required_device m_maincpu; - required_device m_discrete; - required_device m_gfxdecode; - required_device m_screen; - required_device m_palette; - - required_shared_ptr m_video_ram; - required_shared_ptr m_pos_h_ram; - required_shared_ptr m_pos_v_ram; - required_shared_ptr m_pos_d_ram; - required_shared_ptr m_team; - - int m_collision_index = 0; - tilemap_t *m_tilemap = nullptr; - bitmap_ind16 m_helper1; - bitmap_ind16 m_helper2; - bitmap_ind16 m_helper3; - emu_timer *m_collision_timer = nullptr; -}; - -/*----------- defined in audio/tank8.c -----------*/ - -DISCRETE_SOUND_EXTERN( tank8_discrete ); - -#endif // MAME_ATARI_TANK8_H diff --git a/src/mame/atari/tank8_a.cpp b/src/mame/atari/tank8_a.cpp index b16c8c8c167..246015635c0 100644 --- a/src/mame/atari/tank8_a.cpp +++ b/src/mame/atari/tank8_a.cpp @@ -1,13 +1,15 @@ // license:BSD-3-Clause // copyright-holders:Hans Andersson + /************************************************************************* - audio\tank8.c + atari\tank8_a.cpp *************************************************************************/ #include "emu.h" -#include "tank8.h" -#include "sound/discrete.h" + +#include "tank8_a.h" + /************************************************************************/ diff --git a/src/mame/atari/tank8_a.h b/src/mame/atari/tank8_a.h new file mode 100644 index 00000000000..6192e98150d --- /dev/null +++ b/src/mame/atari/tank8_a.h @@ -0,0 +1,30 @@ +// license:BSD-3-Clause +// copyright-holders:Hans Andersson + +/*************************************************************************** + +Tank 8 Audio + +***************************************************************************/ + +#include "sound/discrete.h" + +// discrete sound input nodes + +#define TANK8_CRASH_EN NODE_01 +#define TANK8_BUGLE_EN NODE_02 +#define TANK8_MOTOR1_EN NODE_03 +#define TANK8_MOTOR2_EN NODE_04 +#define TANK8_MOTOR3_EN NODE_05 +#define TANK8_MOTOR4_EN NODE_06 +#define TANK8_MOTOR5_EN NODE_07 +#define TANK8_MOTOR6_EN NODE_08 +#define TANK8_MOTOR7_EN NODE_09 +#define TANK8_MOTOR8_EN NODE_10 +#define TANK8_EXPLOSION_EN NODE_11 +#define TANK8_ATTRACT_EN NODE_12 +#define TANK8_BUGLE_DATA1 NODE_13 +#define TANK8_BUGLE_DATA2 NODE_14 + + +DISCRETE_SOUND_EXTERN( tank8_discrete ); diff --git a/src/mame/atari/tank8_v.cpp b/src/mame/atari/tank8_v.cpp deleted file mode 100644 index 8d114ce3650..00000000000 --- a/src/mame/atari/tank8_v.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Stefan Jokisch -/*************************************************************************** - -Atari Tank 8 video emulation - -***************************************************************************/ - -#include "emu.h" -#include "tank8.h" - - -void tank8_state::tank8_palette(palette_device &palette) const -{ - palette.set_indirect_color(8, rgb_t(0x00, 0x00, 0x00)); - palette.set_indirect_color(9, rgb_t(0xff, 0xff, 0xff)); - - for (int i = 0; i < 8; i++) - { - palette.set_pen_indirect(2 * i + 0, 8); - palette.set_pen_indirect(2 * i + 1, i); - } - - /* walls */ - palette.set_pen_indirect(0x10, 8); - palette.set_pen_indirect(0x11, 9); - - /* mines */ - palette.set_pen_indirect(0x12, 8); - palette.set_pen_indirect(0x13, 9); -} - - -void tank8_state::set_pens() -{ - if (*m_team & 0x01) - { - m_palette->set_indirect_color(0, rgb_t(0xff, 0x00, 0x00)); /* red */ - m_palette->set_indirect_color(1, rgb_t(0x00, 0x00, 0xff)); /* blue */ - m_palette->set_indirect_color(2, rgb_t(0xff, 0xff, 0x00)); /* yellow */ - m_palette->set_indirect_color(3, rgb_t(0x00, 0xff, 0x00)); /* green */ - m_palette->set_indirect_color(4, rgb_t(0xff, 0x00, 0xff)); /* magenta */ - m_palette->set_indirect_color(5, rgb_t(0xe0, 0xc0, 0x70)); /* puce */ - m_palette->set_indirect_color(6, rgb_t(0x00, 0xff, 0xff)); /* cyan */ - m_palette->set_indirect_color(7, rgb_t(0xff, 0xaa, 0xaa)); /* pink */ - } - else - { - m_palette->set_indirect_color(0, rgb_t(0xff, 0x00, 0x00)); /* red */ - m_palette->set_indirect_color(2, rgb_t(0xff, 0x00, 0x00)); /* red */ - m_palette->set_indirect_color(4, rgb_t(0xff, 0x00, 0x00)); /* red */ - m_palette->set_indirect_color(6, rgb_t(0xff, 0x00, 0x00)); /* red */ - m_palette->set_indirect_color(1, rgb_t(0x00, 0x00, 0xff)); /* blue */ - m_palette->set_indirect_color(3, rgb_t(0x00, 0x00, 0xff)); /* blue */ - m_palette->set_indirect_color(5, rgb_t(0x00, 0x00, 0xff)); /* blue */ - m_palette->set_indirect_color(7, rgb_t(0x00, 0x00, 0xff)); /* blue */ - } -} - - -void tank8_state::video_ram_w(offs_t offset, uint8_t data) -{ - m_video_ram[offset] = data; - m_tilemap->mark_tile_dirty(offset); -} - - - -TILE_GET_INFO_MEMBER(tank8_state::get_tile_info) -{ - uint8_t code = m_video_ram[tile_index]; - - int color = 0; - - if ((code & 0x38) == 0x28) - { - if ((code & 7) != 3) - color = 8; /* walls */ - else - color = 9; /* mines */ - } - else - { - if (tile_index & 0x010) - color |= 1; - - if (code & 0x80) - color |= 2; - - if (tile_index & 0x200) - color |= 4; - } - - tileinfo.set(code >> 7, code, color, (code & 0x40) ? (TILE_FLIPX | TILE_FLIPY) : 0); -} - - - -void tank8_state::video_start() -{ - m_collision_timer = timer_alloc(FUNC(tank8_state::set_collision), this); - - m_screen->register_screen_bitmap(m_helper1); - m_screen->register_screen_bitmap(m_helper2); - m_screen->register_screen_bitmap(m_helper3); - - m_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(tank8_state::get_tile_info)), TILEMAP_SCAN_ROWS, 16, 16, 32, 32); - - // VBLANK starts on scanline #256 and ends on scanline #24 - m_tilemap->set_scrolly(0, 2 * 24); - - save_item(NAME(m_collision_index)); -} - - -int tank8_state::get_x_pos(int n) -{ - return 498 - m_pos_h_ram[n] - 2 * (m_pos_d_ram[n] & 128); /* ? */ -} - - -int tank8_state::get_y_pos(int n) -{ - return 2 * m_pos_v_ram[n] - 62; -} - - -void tank8_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - int i; - - for (i = 0; i < 8; i++) - { - uint8_t code = ~m_pos_d_ram[i]; - - int x = get_x_pos(i); - int y = get_y_pos(i); - - m_gfxdecode->gfx((code & 0x04) ? 2 : 3)->transpen(bitmap,cliprect, - code & 0x03, - i, - code & 0x10, - code & 0x08, - x, - y, 0); - } -} - - -void tank8_state::draw_bullets(bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - int i; - - for (i = 0; i < 8; i++) - { - int x = get_x_pos(8 + i); - int y = get_y_pos(8 + i); - - x -= 4; /* ? */ - - rectangle rect(x, x + 3, y, y + 4); - rect &= cliprect; - - bitmap.fill((i << 1) | 0x01, rect); - } -} - - -uint32_t tank8_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - set_pens(); - m_tilemap->draw(screen, bitmap, cliprect, 0, 0); - - draw_sprites(bitmap, cliprect); - draw_bullets(bitmap, cliprect); - return 0; -} - - -WRITE_LINE_MEMBER(tank8_state::screen_vblank) -{ - // on falling edge - if (!state) - { - const rectangle &visarea = m_screen->visible_area(); - - m_tilemap->draw(*m_screen, m_helper1, visarea, 0, 0); - - m_helper2.fill(8, visarea); - m_helper3.fill(8, visarea); - - draw_sprites(m_helper2, visarea); - draw_bullets(m_helper3, visarea); - - for (int y = visarea.top(); y <= visarea.bottom(); y++) - { - int _state = 0; - - uint16_t const *const p1 = &m_helper1.pix(y); - uint16_t const *const p2 = &m_helper2.pix(y); - uint16_t const *const p3 = &m_helper3.pix(y); - - if ((m_screen->frame_number() ^ y) & 1) - continue; /* video display is interlaced */ - - for (int x = visarea.left(); x <= visarea.right(); x++) - { - /* neither wall nor mine */ - if ((p1[x] != 0x11) && (p1[x] != 0x13)) - { - _state = 0; - continue; - } - - /* neither tank nor bullet */ - if ((p2[x] == 8) && (p3[x] == 8)) - { - _state = 0; - continue; - } - - /* bullets cannot hit mines */ - if ((p3[x] != 8) && (p1[x] == 0x13)) - { - _state = 0; - continue; - } - - if (_state) - continue; - - uint8_t index; - if (p3[x] != 8) - { - index = ((p3[x] & ~0x01) >> 1) | 0x18; - - if (1) - index |= 0x20; - - if (0) - index |= 0x40; - - if (1) - index |= 0x80; - } - else - { - int sprite_num = (p2[x] & ~0x01) >> 1; - index = sprite_num | 0x10; - - if (p1[x] == 0x11) - index |= 0x20; - - if (y - get_y_pos(sprite_num) >= 8) - index |= 0x40; /* collision on bottom side */ - - if (x - get_x_pos(sprite_num) >= 8) - index |= 0x80; /* collision on right side */ - } - - m_collision_timer->adjust(m_screen->time_until_pos(y, x), index); - - _state = 1; - } - } - } -} diff --git a/src/mame/atari/thunderj.cpp b/src/mame/atari/thunderj.cpp index 066184f7d1e..86e2e54d82c 100644 --- a/src/mame/atari/thunderj.cpp +++ b/src/mame/atari/thunderj.cpp @@ -1,5 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Aaron Giles + /*************************************************************************** Atari ThunderJaws hardware @@ -20,8 +21,8 @@ the beginning of interrupt and once near the end. It stores these values in a table starting at $163484. CPU #2 periodically looks at this table to make sure that it is getting interrupts at the appropriate times, and that the - VBLANK bit is set appropriately. Unfortunately, due to all the device_yield(&space.device()) - calls we make to synchronize the two CPUs, we occasionally get out of time + VBLANK bit is set appropriately. Unfortunately, due to all the calls + we make to synchronize the two CPUs, we occasionally get out of time and generate the interrupt outside of the tight tolerances CPU #2 expects. So we fake it. Returning scanlines $f5 and $f7 alternately provides the @@ -37,15 +38,298 @@ #include "emu.h" -#include "thunderj.h" + +#include "atarijsa.h" +#include "atarimo.h" +#include "atarivad.h" + #include "cpu/m68000/m68000.h" #include "machine/eeprompar.h" #include "machine/watchdog.h" + #include "emupal.h" +#include "screen.h" #include "speaker.h" +#include "tilemap.h" + + +namespace { + +class thunderj_state : public driver_device +{ +public: + thunderj_state(const machine_config &mconfig, device_type type, const char *tag) : + driver_device(mconfig, type, tag), + m_screen(*this, "screen"), + m_jsa(*this, "jsa"), + m_vad(*this, "vad"), + m_maincpu(*this, "maincpu"), + m_extra(*this, "extra"), + m_260012(*this, "260012") + { } + + void thunderj(machine_config &config); + +protected: + virtual void machine_start() override; + +private: + required_device m_screen; + required_device m_jsa; + required_device m_vad; + required_device m_maincpu; + required_device m_extra; + + required_ioport m_260012; + + uint8_t m_alpha_tile_bank = 0; + + static const atari_motion_objects_config s_mob_config; + + DECLARE_WRITE_LINE_MEMBER(scanline_int_write_line); + uint16_t special_port2_r(); + void latch_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); + TILE_GET_INFO_MEMBER(get_alpha_tile_info); + TILE_GET_INFO_MEMBER(get_playfield_tile_info); + TILE_GET_INFO_MEMBER(get_playfield2_tile_info); + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + void extra_map(address_map &map); + void main_map(address_map &map); +}; + + +// video + +/************************************* + * + * Tilemap callbacks + * + *************************************/ + +TILE_GET_INFO_MEMBER(thunderj_state::get_alpha_tile_info) +{ + uint16_t const data = m_vad->alpha().basemem_read(tile_index); + int const code = ((data & 0x200) ? (m_alpha_tile_bank * 0x200) : 0) + (data & 0x1ff); + int const color = ((data >> 10) & 0x0f) | ((data >> 9) & 0x20); + int const opaque = data & 0x8000; + tileinfo.set(2, code, color, opaque ? TILE_FORCE_LAYER0 : 0); +} + + +TILE_GET_INFO_MEMBER(thunderj_state::get_playfield_tile_info) +{ + uint16_t const data1 = m_vad->playfield().basemem_read(tile_index); + uint16_t const data2 = m_vad->playfield().extmem_read(tile_index) & 0xff; + int const code = data1 & 0x7fff; + int const color = 0x10 + (data2 & 0x0f); + tileinfo.set(0, code, color, (data1 >> 15) & 1); + tileinfo.category = (data2 >> 4) & 3; +} + + +TILE_GET_INFO_MEMBER(thunderj_state::get_playfield2_tile_info) +{ + uint16_t const data1 = m_vad->playfield2().basemem_read(tile_index); + uint16_t const data2 = m_vad->playfield2().extmem_read(tile_index) >> 8; + int const code = data1 & 0x7fff; + int const color = data2 & 0x0f; + tileinfo.set(0, code, color, (data1 >> 15) & 1); + tileinfo.category = (data2 >> 4) & 3; +} + + + +/************************************* + * + * Video system start + * + *************************************/ + +const atari_motion_objects_config thunderj_state::s_mob_config = +{ + 1, // index to which gfx system + 1, // number of motion object banks + 1, // are the entries linked? + 0, // are the entries split? + 1, // render in reverse order? + 0, // render in swapped X/Y order? + 0, // does the neighbor bit affect the next object? + 8, // pixels per SLIP entry (0 for no-slip) + 0, // pixel offset for SLIPs + 0, // maximum number of links to visit/scanline (0=all) + + 0x100, // base palette entry + 0x100, // maximum number of colors + 0, // transparent pen index + + {{ 0x03ff,0,0,0 }}, // mask for the link + {{ 0,0x7fff,0,0 }}, // mask for the code index + {{ 0,0,0x000f,0 }}, // mask for the color + {{ 0,0,0xff80,0 }}, // mask for the X position + {{ 0,0,0,0xff80 }}, // mask for the Y position + {{ 0,0,0,0x0070 }}, // mask for the width, in tiles + {{ 0,0,0,0x0007 }}, // mask for the height, in tiles + {{ 0,0x8000,0,0 }}, // mask for the horizontal flip + {{ 0 }}, // mask for the vertical flip + {{ 0,0,0x0070,0 }}, // mask for the priority + {{ 0 }}, // mask for the neighbor + {{ 0 }}, // mask for absolute coordinates + + {{ 0 }}, // mask for the special value + 0, // resulting value to indicate "special" +}; + + + +/************************************* + * + * Main refresh + * + *************************************/ + +uint32_t thunderj_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + // start drawing + m_vad->mob().draw_async(cliprect); + + // draw the playfield + bitmap_ind8 &priority_bitmap = screen.priority(); + priority_bitmap.fill(0, cliprect); + m_vad->playfield().draw(screen, bitmap, cliprect, 0, 0x00); + m_vad->playfield().draw(screen, bitmap, cliprect, 1, 0x01); + m_vad->playfield().draw(screen, bitmap, cliprect, 2, 0x02); + m_vad->playfield().draw(screen, bitmap, cliprect, 3, 0x03); + m_vad->playfield2().draw(screen, bitmap, cliprect, 0, 0x80); + m_vad->playfield2().draw(screen, bitmap, cliprect, 1, 0x84); + m_vad->playfield2().draw(screen, bitmap, cliprect, 2, 0x88); + m_vad->playfield2().draw(screen, bitmap, cliprect, 3, 0x8c); + + // draw and merge the MO + bitmap_ind16 &mobitmap = m_vad->mob().bitmap(); + for (const sparse_dirty_rect *rect = m_vad->mob().first_dirty_rect(cliprect); rect != nullptr; rect = rect->next()) + for (int y = rect->top(); y <= rect->bottom(); y++) + { + uint16_t const *const mo = &mobitmap.pix(y); + uint16_t *const pf = &bitmap.pix(y); + uint8_t const *const pri = &priority_bitmap.pix(y); + for (int x = rect->left(); x <= rect->right(); x++) + if (mo[x] != 0xffff) + { + /* verified from the GALs on the real PCB; equations follow + * + * --- PF/M is 1 if playfield has priority, or 0 if MOs have priority + * PF/M=MPX0*!MPX1*!MPX2*!MPX3*!MPX4*!MPX5*!MPX6*!MPX7 + * +PFX3*PFX8*PFX9*!MPR0 + * +PFX3*PFX8*!MPR0*!MPR1 + * +PFX3*PFX9*!MPR1 + * + * --- CS1 is 1 if the playfield should be displayed + * CS1=PF/M*!ALBG*!APIX0*!APIX1 + * +!MPX0*!MPX1*!MPX2*!MPX3*!ALBG*!APIX0*!APIX1 + * + * --- CS0 is 1 if the MOs should be displayed + * CS0=!PF/M*MPX0*!ALBG*!APIX0*!APIX1 + * +!PF/M*MPX1*!ALBG*!APIX0*!APIX1 + * +!PF/M*MPX2*!ALBG*!APIX0*!APIX1 + * +!PF/M*MPX3*!ALBG*!APIX0*!APIX1 + * + * --- CRA10 is the 0x200 bit of the color RAM index; set if pf is displayed + * CRA10:=CS1 + * + * --- CRA9 is the 0x100 bit of the color RAM index; set if mo is displayed + * or if the playfield selected is playfield #2 + * CRA9:=PFXS*CS1 + * +!CS1*CS0 + * + * --- CRA8-1 are the low 8 bits of the color RAM index; set as expected + * CRA8:=CS1*PFX7 + * +!CS1*MPX7*CS0 + * +!CS1*!CS0*ALC4 + * + * CRA7:=CS1*PFX6 + * +!CS1*MPX6*CS0 + * + * CRA6:=CS1*PFX5 + * +MPX5*!CS1*CS0 + * +!CS1*!CS0*ALC3 + * + * CRA5:=CS1*PFX4 + * +MPX4*!CS1*CS0 + * +!CS1*ALC2*!CS0 + * + * CRA4:=CS1*PFX3 + * +!CS1*MPX3*CS0 + * +!CS1*!CS0*ALC1 + * + * CRA3:=CS1*PFX2 + * +MPX2*!CS1*CS0 + * +!CS1*!CS0*ALC0 + * + * CRA2:=CS1*PFX1 + * +MPX1*!CS1*CS0 + * +!CS1*!CS0*APIX1 + * + * CRA1:=CS1*PFX0 + * +MPX0*!CS1*CS0 + * +!CS1*!CS0*APIX0 + */ + int const mopriority = mo[x] >> atari_motion_objects_device::PRIORITY_SHIFT; + + // upper bit of MO priority signals special rendering and doesn't draw anything + if (mopriority & 4) + continue; + + // determine pf/m signal + int pfm = 0; + if ((mo[x] & 0xff) == 1) + pfm = 1; + else if (pf[x] & 8) + { + int const pfpriority = (pri[x] & 0x80) ? ((pri[x] >> 2) & 3) : (pri[x] & 3); + if (((pfpriority == 3) && !(mopriority & 1)) || + ((pfpriority & 1) && (mopriority == 0)) || + ((pfpriority & 2) && !(mopriority & 2))) + pfm = 1; + } + + // if pfm is low, we display the mo + if (!pfm) + pf[x] = mo[x] & atari_motion_objects_device::DATA_MASK; + + // don't erase yet -- we need to make another pass later + } + } + // add the alpha on top + m_vad->alpha().draw(screen, bitmap, cliprect, 0, 0); + + // now go back and process the upper bit of MO priority + for (const sparse_dirty_rect *rect = m_vad->mob().first_dirty_rect(cliprect); rect != nullptr; rect = rect->next()) + for (int y = rect->top(); y <= rect->bottom(); y++) + { + uint16_t const *const mo = &mobitmap.pix(y); + uint16_t *const pf = &bitmap.pix(y); + for (int x = rect->left(); x <= rect->right(); x++) + if (mo[x] != 0xffff) + { + int const mopriority = mo[x] >> atari_motion_objects_device::PRIORITY_SHIFT; + + // upper bit of MO priority might mean palette kludges + if (mopriority & 4) + { + // if bit 2 is set, start setting high palette bits + if (mo[x] & 2) + m_vad->mob().apply_stain(bitmap, pf, mo, x, y); + } + } + } + return 0; +} +// machine + /************************************* * * Initialization & interrupts @@ -74,7 +358,7 @@ void thunderj_state::machine_start() uint16_t thunderj_state::special_port2_r() { - int result = ioport("260012")->read(); + int result = m_260012->read(); result ^= 0x0010; return result; } @@ -82,16 +366,16 @@ uint16_t thunderj_state::special_port2_r() void thunderj_state::latch_w(offs_t offset, uint16_t data, uint16_t mem_mask) { - /* reset extra CPU */ + // reset extra CPU if (ACCESSING_BITS_0_7) { - /* 0 means hold CPU 2's reset low */ + // 0 means hold CPU 2's reset low if (data & 1) m_extra->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); else m_extra->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - /* bits 2-5 are the alpha bank */ + // bits 2-5 are the alpha bank if (m_alpha_tile_bank != ((data >> 2) & 7)) { m_screen->update_partial(m_screen->vpos()); @@ -113,7 +397,7 @@ void thunderj_state::main_map(address_map &map) { map(0x000000, 0x09ffff).rom(); map(0x0e0000, 0x0e0fff).rw("eeprom", FUNC(eeprom_parallel_28xx_device::read), FUNC(eeprom_parallel_28xx_device::write)).umask16(0x00ff); - map(0x160000, 0x16ffff).ram().share("share1"); + map(0x160000, 0x16ffff).ram().share("sharedram"); map(0x1f0000, 0x1fffff).w("eeprom", FUNC(eeprom_parallel_28xx_device::unlock_write16)); map(0x260000, 0x26000f).portr("260000"); map(0x260010, 0x260011).portr("260010"); @@ -147,7 +431,7 @@ void thunderj_state::extra_map(address_map &map) { map(0x000000, 0x03ffff).rom(); map(0x060000, 0x07ffff).rom(); - map(0x160000, 0x16ffff).ram().share("share1"); + map(0x160000, 0x16ffff).ram().share("sharedram"); map(0x260000, 0x26000f).portr("260000"); map(0x260010, 0x260011).portr("260010"); map(0x260012, 0x260013).r(FUNC(thunderj_state::special_port2_r)); @@ -182,8 +466,8 @@ static INPUT_PORTS_START( thunderj ) PORT_START("260012") PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_VBLANK("screen") PORT_SERVICE( 0x0002, IP_ACTIVE_LOW ) - PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_ATARI_JSA_SOUND_TO_MAIN_READY("jsa") /* Input buffer full (@260030) */ - PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_ATARI_JSA_MAIN_TO_SOUND_READY("jsa") /* Output buffer full (@360030) */ + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_CUSTOM ) PORT_ATARI_JSA_SOUND_TO_MAIN_READY("jsa") // Input buffer full (@260030) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_ATARI_JSA_MAIN_TO_SOUND_READY("jsa") // Output buffer full (@360030) PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_BIT( 0x00e0, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) @@ -216,9 +500,9 @@ static const gfx_layout anlayout = static GFXDECODE_START( gfx_thunderj ) - GFXDECODE_ENTRY( "gfx1", 0, gfx_8x8x4_planar, 512, 96 ) /* sprites & playfield */ - GFXDECODE_ENTRY( "gfx2", 0, gfx_8x8x4_planar, 256, 112 ) /* sprites & playfield */ - GFXDECODE_ENTRY( "gfx3", 0, anlayout, 0, 512 ) /* characters 8x8 */ + GFXDECODE_ENTRY( "sprites_tiles1", 0, gfx_8x8x4_planar, 512, 96 ) + GFXDECODE_ENTRY( "sprites_tiles2", 0, gfx_8x8x4_planar, 256, 112 ) + GFXDECODE_ENTRY( "chars", 0, anlayout, 0, 512 ) GFXDECODE_END @@ -231,21 +515,21 @@ GFXDECODE_END void thunderj_state::thunderj(machine_config &config) { - /* basic machine hardware */ - M68000(config, m_maincpu, 14.318181_MHz_XTAL/2); + // basic machine hardware + M68000(config, m_maincpu, 14.318181_MHz_XTAL / 2); m_maincpu->set_addrmap(AS_PROGRAM, &thunderj_state::main_map); - M68000(config, m_extra, 14.318181_MHz_XTAL/2); + M68000(config, m_extra, 14.318181_MHz_XTAL / 2); m_extra->set_addrmap(AS_PROGRAM, &thunderj_state::extra_map); EEPROM_2816(config, "eeprom").lock_after_write(true); WATCHDOG_TIMER(config, "watchdog"); - /* perfect synchronization due to shared RAM */ + // perfect synchronization due to shared RAM config.set_perfect_quantum(m_maincpu); - /* video hardware */ + // video hardware GFXDECODE(config, "gfxdecode", "palette", gfx_thunderj); PALETTE(config, "palette").set_format(palette_device::IRGB_1555, 2048); @@ -258,13 +542,13 @@ void thunderj_state::thunderj(machine_config &config) SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_video_attributes(VIDEO_UPDATE_BEFORE_VBLANK); - /* note: these parameters are from published specs, not derived */ - /* the board uses a VAD chip to generate video signals */ + // note: these parameters are from published specs, not derived + // the board uses a VAD chip to generate video signals m_screen->set_raw(14.318181_MHz_XTAL/2, 456, 0, 336, 262, 0, 240); - m_screen->set_screen_update(FUNC(thunderj_state::screen_update_thunderj)); + m_screen->set_screen_update(FUNC(thunderj_state::screen_update)); m_screen->set_palette("palette"); - /* sound hardware */ + // sound hardware SPEAKER(config, "mono").front_center(); ATARI_JSA_II(config, m_jsa, 0); @@ -282,45 +566,45 @@ void thunderj_state::thunderj(machine_config &config) *************************************/ ROM_START( thunderj ) - ROM_REGION( 0xa0000, "maincpu", 0 ) /* 10*64k for 68000 code */ - ROM_LOAD16_BYTE( "136076-3001.14e", 0x00000, 0x10000, CRC(cda7f027) SHA1(50dc7de1eea1ad0539c0be4e23fc50de2ba6ca40) ) /* Rev 3 program rom */ - ROM_LOAD16_BYTE( "136076-3002.14c", 0x00001, 0x10000, CRC(752cead3) SHA1(474af2dbb0b8bf5e0030d9a0ee9879c92250c2e0) ) /* Rev 3 program rom */ - ROM_LOAD16_BYTE( "136076-2003.15e", 0x20000, 0x10000, CRC(6e155469) SHA1(ba87d0a510304fd8a0f91c81580c4f09fc4d1886) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2004.15c", 0x20001, 0x10000, CRC(e9ff1e42) SHA1(416dd68ec2ae174a5b14fa6fb4fb88bc1afdda66) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2005.16e", 0x40000, 0x10000, CRC(a40242e7) SHA1(ea2311f064885912054ae2e50a60664b216a6253) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2006.16c", 0x40001, 0x10000, CRC(aa18b94c) SHA1(867fd1d5485eacb705ed4ec736ee8c2e78aa9bf4) ) /* Rev 2 program rom */ + ROM_REGION( 0xa0000, "maincpu", 0 ) // 68000 code + ROM_LOAD16_BYTE( "136076-3001.14e", 0x00000, 0x10000, CRC(cda7f027) SHA1(50dc7de1eea1ad0539c0be4e23fc50de2ba6ca40) ) // Rev 3 program ROM + ROM_LOAD16_BYTE( "136076-3002.14c", 0x00001, 0x10000, CRC(752cead3) SHA1(474af2dbb0b8bf5e0030d9a0ee9879c92250c2e0) ) // Rev 3 program ROM + ROM_LOAD16_BYTE( "136076-2003.15e", 0x20000, 0x10000, CRC(6e155469) SHA1(ba87d0a510304fd8a0f91c81580c4f09fc4d1886) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2004.15c", 0x20001, 0x10000, CRC(e9ff1e42) SHA1(416dd68ec2ae174a5b14fa6fb4fb88bc1afdda66) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2005.16e", 0x40000, 0x10000, CRC(a40242e7) SHA1(ea2311f064885912054ae2e50a60664b216a6253) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2006.16c", 0x40001, 0x10000, CRC(aa18b94c) SHA1(867fd1d5485eacb705ed4ec736ee8c2e78aa9bf4) ) // Rev 2 program ROM ROM_LOAD16_BYTE( "136076-1009.15h", 0x60000, 0x10000, CRC(05474ebb) SHA1(74a32dba5ffe2953c81ad9639d99ed01b31b0dba) ) ROM_LOAD16_BYTE( "136076-1010.16h", 0x60001, 0x10000, CRC(ccff21c8) SHA1(7df8facf563cc1bb8de6cac6f2ddcc58ae0aa8b4) ) ROM_LOAD16_BYTE( "136076-1007.17e", 0x80000, 0x10000, CRC(9c2a8aba) SHA1(10e4fc04e64bb6a5083a56f630224b5d1af241b2) ) ROM_LOAD16_BYTE( "136076-1008.17c", 0x80001, 0x10000, CRC(22109d16) SHA1(8725696271c4a617f9f050d9d483fe4141bf1e00) ) - ROM_REGION( 0x80000, "extra", 0 ) /* 8*64k for 68000 code */ + ROM_REGION( 0x80000, "extra", 0 ) // 68000 code ROM_LOAD16_BYTE( "136076-1011.17l", 0x00000, 0x10000, CRC(bbbbca45) SHA1(977e785e0272a84c8d7e28e25f45064d1b37aad1) ) ROM_LOAD16_BYTE( "136076-1012.17n", 0x00001, 0x10000, CRC(53e5e638) SHA1(75593e5d328ede105b8db64005dd5d1c5cae11ed) ) ROM_COPY( "maincpu", 0x60000, 0x60000, 0x20000 ) - ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */ - ROM_LOAD( "136076-2015.1b", 0x00000, 0x10000, CRC(d8feb7fb) SHA1(684ebf2f0c0df742c98e7f45f74de86a11c8d6e8) ) /* Rev 2 program rom */ + ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code + ROM_LOAD( "136076-2015.1b", 0x00000, 0x10000, CRC(d8feb7fb) SHA1(684ebf2f0c0df742c98e7f45f74de86a11c8d6e8) ) // Rev 2 program ROM - ROM_REGION( 0x100000, "gfx1", ROMREGION_INVERT ) - ROM_LOAD( "136076-1021.5s", 0x000000, 0x10000, CRC(d8432766) SHA1(04e7d820974c0890fde1257b4710cf7b520d7d48) ) /* graphics, plane 0 */ + ROM_REGION( 0x100000, "sprites_tiles1", ROMREGION_INVERT ) + ROM_LOAD( "136076-1021.5s", 0x000000, 0x10000, CRC(d8432766) SHA1(04e7d820974c0890fde1257b4710cf7b520d7d48) ) // graphics, plane 0 */ ROM_LOAD( "136076-1025.5r", 0x010000, 0x10000, CRC(839feed5) SHA1(c683ef5b78f8fd63dd557a630544f1e21aebe665) ) ROM_LOAD( "136076-1029.3p", 0x020000, 0x10000, CRC(fa887662) SHA1(5d19022e8d40be86b85d0bcc28c97207ab9ec403) ) ROM_LOAD( "136076-1033.6p", 0x030000, 0x10000, CRC(2addda79) SHA1(5a04c718055a5637b7549598ec39ca3cc9883698) ) - ROM_LOAD( "136076-1022.9s", 0x040000, 0x10000, CRC(dcf50371) SHA1(566e71e1dcb8e0266ca870af04b11f7bbee21b18) ) /* graphics, plane 1 */ + ROM_LOAD( "136076-1022.9s", 0x040000, 0x10000, CRC(dcf50371) SHA1(566e71e1dcb8e0266ca870af04b11f7bbee21b18) ) // graphics, plane 1 */ ROM_LOAD( "136076-1026.9r", 0x050000, 0x10000, CRC(216e72c8) SHA1(b6155584c8760c4dee3cf2a6320c53ea2161464b) ) ROM_LOAD( "136076-1030.10s", 0x060000, 0x10000, CRC(dc51f606) SHA1(aa401808d915b2e6cdb17a1d58814a753648c9bb) ) ROM_LOAD( "136076-1034.10r", 0x070000, 0x10000, CRC(f8e35516) SHA1(dcb23ed69f5a70ac842c6004039ec403bac68d72) ) - ROM_LOAD( "136076-1023.13s", 0x080000, 0x10000, CRC(b6dc3f13) SHA1(c3369b58012e02ad2fd85f1c9643ee5792f4b3de) ) /* graphics, plane 2 */ + ROM_LOAD( "136076-1023.13s", 0x080000, 0x10000, CRC(b6dc3f13) SHA1(c3369b58012e02ad2fd85f1c9643ee5792f4b3de) ) // graphics, plane 2 */ ROM_LOAD( "136076-1027.13r", 0x090000, 0x10000, CRC(621cc2ce) SHA1(15db80d61f1c624c09085ed86341f8577bfac168) ) ROM_LOAD( "136076-1031.14s", 0x0a0000, 0x10000, CRC(4682ceb5) SHA1(609ccd20f654982e01bcc6aea89801c01afe083e) ) ROM_LOAD( "136076-1035.14r", 0x0b0000, 0x10000, CRC(7a0e1b9e) SHA1(b9a2270ee7e3b3dcf05a47085890d87bf5b3e167) ) - ROM_LOAD( "136076-1024.17s", 0x0c0000, 0x10000, CRC(d84452b5) SHA1(29bc994e37bc08fa40326b811339e7aa3290302c) ) /* graphics, plane 3 */ + ROM_LOAD( "136076-1024.17s", 0x0c0000, 0x10000, CRC(d84452b5) SHA1(29bc994e37bc08fa40326b811339e7aa3290302c) ) // graphics, plane 3 */ ROM_LOAD( "136076-1028.17r", 0x0d0000, 0x10000, CRC(0cc20245) SHA1(ebdcb47909374508abe9d0252fd88d6274a0f729) ) ROM_LOAD( "136076-1032.14p", 0x0e0000, 0x10000, CRC(f639161a) SHA1(cc2549f7fdd251fa44735a6cd5fdb8ffb97948be) ) ROM_LOAD( "136076-1036.16p", 0x0f0000, 0x10000, CRC(b342443d) SHA1(fa7865f8a90c0e761e1cc5e155931d0574f2d81c) ) - ROM_REGION( 0x100000, "gfx2", ROMREGION_INVERT ) + ROM_REGION( 0x100000, "sprites_tiles2", ROMREGION_INVERT ) ROM_LOAD( "136076-1037.2s", 0x000000, 0x10000, CRC(07addba6) SHA1(4a3286ee570bf4263944854bf959c8ef114cc123) ) ROM_LOAD( "136076-1041.2r", 0x010000, 0x10000, CRC(1e9c29e4) SHA1(e4afa2c469bfa22504cba5dfd23704c5c2bb33c4) ) ROM_LOAD( "136076-1045.34s", 0x020000, 0x10000, CRC(e7235876) SHA1(0bb03baec1de3e520dc270a3ed44bec953e08c00) ) @@ -338,8 +622,8 @@ ROM_START( thunderj ) ROM_LOAD( "136076-1048.16s", 0x0e0000, 0x10000, CRC(200d45b3) SHA1(72f1b3deaebc6266140fb79a97154f80f2cadf33) ) ROM_LOAD( "136076-1052.16r", 0x0f0000, 0x10000, CRC(74711ef1) SHA1(c1429d6b54dc4352defdd6cf83f1a5734784e703) ) - ROM_REGION( 0x010000, "gfx3", 0 ) - ROM_LOAD( "136076-1020.4m", 0x000000, 0x10000, CRC(65470354) SHA1(9895d26fa9e01c254a3d15e657152cac717c68a3) ) /* alphanumerics */ + ROM_REGION( 0x010000, "chars", 0 ) + ROM_LOAD( "136076-1020.4m", 0x000000, 0x10000, CRC(65470354) SHA1(9895d26fa9e01c254a3d15e657152cac717c68a3) ) ROM_REGION( 0x40000, "jsa:oki1", 0 ) /* 256k for ADPCM */ ROM_LOAD( "136076-1016.7k", 0x00000, 0x10000, CRC(c10bdf73) SHA1(a0371c6ddef2a95193c68879044b3338d481fc96) ) @@ -358,45 +642,45 @@ ROM_START( thunderj ) ROM_END ROM_START( thunderja ) - ROM_REGION( 0xa0000, "maincpu", 0 ) /* 10*64k for 68000 code */ - ROM_LOAD16_BYTE( "136076-2001.14e", 0x00000, 0x10000, CRC(f6a71532) SHA1(b1c55968d7da9b64bde737d66aa8f0ddcdcfee27) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2002.14c", 0x00001, 0x10000, CRC(173ec10d) SHA1(e32eca9194336f3d7e289b2a187ed125ed03688c) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2003.15e", 0x20000, 0x10000, CRC(6e155469) SHA1(ba87d0a510304fd8a0f91c81580c4f09fc4d1886) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2004.15c", 0x20001, 0x10000, CRC(e9ff1e42) SHA1(416dd68ec2ae174a5b14fa6fb4fb88bc1afdda66) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2005.16e", 0x40000, 0x10000, CRC(a40242e7) SHA1(ea2311f064885912054ae2e50a60664b216a6253) ) /* Rev 2 program rom */ - ROM_LOAD16_BYTE( "136076-2006.16c", 0x40001, 0x10000, CRC(aa18b94c) SHA1(867fd1d5485eacb705ed4ec736ee8c2e78aa9bf4) ) /* Rev 2 program rom */ + ROM_REGION( 0xa0000, "maincpu", 0 ) // 68000 code + ROM_LOAD16_BYTE( "136076-2001.14e", 0x00000, 0x10000, CRC(f6a71532) SHA1(b1c55968d7da9b64bde737d66aa8f0ddcdcfee27) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2002.14c", 0x00001, 0x10000, CRC(173ec10d) SHA1(e32eca9194336f3d7e289b2a187ed125ed03688c) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2003.15e", 0x20000, 0x10000, CRC(6e155469) SHA1(ba87d0a510304fd8a0f91c81580c4f09fc4d1886) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2004.15c", 0x20001, 0x10000, CRC(e9ff1e42) SHA1(416dd68ec2ae174a5b14fa6fb4fb88bc1afdda66) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2005.16e", 0x40000, 0x10000, CRC(a40242e7) SHA1(ea2311f064885912054ae2e50a60664b216a6253) ) // Rev 2 program ROM + ROM_LOAD16_BYTE( "136076-2006.16c", 0x40001, 0x10000, CRC(aa18b94c) SHA1(867fd1d5485eacb705ed4ec736ee8c2e78aa9bf4) ) // Rev 2 program ROM ROM_LOAD16_BYTE( "136076-1009.15h", 0x60000, 0x10000, CRC(05474ebb) SHA1(74a32dba5ffe2953c81ad9639d99ed01b31b0dba) ) ROM_LOAD16_BYTE( "136076-1010.16h", 0x60001, 0x10000, CRC(ccff21c8) SHA1(7df8facf563cc1bb8de6cac6f2ddcc58ae0aa8b4) ) ROM_LOAD16_BYTE( "136076-1007.17e", 0x80000, 0x10000, CRC(9c2a8aba) SHA1(10e4fc04e64bb6a5083a56f630224b5d1af241b2) ) ROM_LOAD16_BYTE( "136076-1008.17c", 0x80001, 0x10000, CRC(22109d16) SHA1(8725696271c4a617f9f050d9d483fe4141bf1e00) ) - ROM_REGION( 0x80000, "extra", 0 ) /* 8*64k for 68000 code */ + ROM_REGION( 0x80000, "extra", 0 ) // 68000 code ROM_LOAD16_BYTE( "136076-1011.17l", 0x00000, 0x10000, CRC(bbbbca45) SHA1(977e785e0272a84c8d7e28e25f45064d1b37aad1) ) ROM_LOAD16_BYTE( "136076-1012.17n", 0x00001, 0x10000, CRC(53e5e638) SHA1(75593e5d328ede105b8db64005dd5d1c5cae11ed) ) ROM_COPY( "maincpu", 0x60000, 0x60000, 0x20000 ) - ROM_REGION( 0x10000, "jsa:cpu", 0 ) /* 64k for 6502 code */ - ROM_LOAD( "136076-2015.1b", 0x00000, 0x10000, CRC(d8feb7fb) SHA1(684ebf2f0c0df742c98e7f45f74de86a11c8d6e8) ) /* Rev 2 program rom */ + ROM_REGION( 0x10000, "jsa:cpu", 0 ) // 6502 code + ROM_LOAD( "136076-2015.1b", 0x00000, 0x10000, CRC(d8feb7fb) SHA1(684ebf2f0c0df742c98e7f45f74de86a11c8d6e8) ) // Rev 2 program ROM - ROM_REGION( 0x100000, "gfx1", ROMREGION_INVERT ) - ROM_LOAD( "136076-1021.5s", 0x000000, 0x10000, CRC(d8432766) SHA1(04e7d820974c0890fde1257b4710cf7b520d7d48) ) /* graphics, plane 0 */ + ROM_REGION( 0x100000, "sprites_tiles1", ROMREGION_INVERT ) + ROM_LOAD( "136076-1021.5s", 0x000000, 0x10000, CRC(d8432766) SHA1(04e7d820974c0890fde1257b4710cf7b520d7d48) ) // graphics, plane 0 */ ROM_LOAD( "136076-1025.5r", 0x010000, 0x10000, CRC(839feed5) SHA1(c683ef5b78f8fd63dd557a630544f1e21aebe665) ) ROM_LOAD( "136076-1029.3p", 0x020000, 0x10000, CRC(fa887662) SHA1(5d19022e8d40be86b85d0bcc28c97207ab9ec403) ) ROM_LOAD( "136076-1033.6p", 0x030000, 0x10000, CRC(2addda79) SHA1(5a04c718055a5637b7549598ec39ca3cc9883698) ) - ROM_LOAD( "136076-1022.9s", 0x040000, 0x10000, CRC(dcf50371) SHA1(566e71e1dcb8e0266ca870af04b11f7bbee21b18) ) /* graphics, plane 1 */ + ROM_LOAD( "136076-1022.9s", 0x040000, 0x10000, CRC(dcf50371) SHA1(566e71e1dcb8e0266ca870af04b11f7bbee21b18) ) // graphics, plane 1 */ ROM_LOAD( "136076-1026.9r", 0x050000, 0x10000, CRC(216e72c8) SHA1(b6155584c8760c4dee3cf2a6320c53ea2161464b) ) ROM_LOAD( "136076-1030.10s", 0x060000, 0x10000, CRC(dc51f606) SHA1(aa401808d915b2e6cdb17a1d58814a753648c9bb) ) ROM_LOAD( "136076-1034.10r", 0x070000, 0x10000, CRC(f8e35516) SHA1(dcb23ed69f5a70ac842c6004039ec403bac68d72) ) - ROM_LOAD( "136076-1023.13s", 0x080000, 0x10000, CRC(b6dc3f13) SHA1(c3369b58012e02ad2fd85f1c9643ee5792f4b3de) ) /* graphics, plane 2 */ + ROM_LOAD( "136076-1023.13s", 0x080000, 0x10000, CRC(b6dc3f13) SHA1(c3369b58012e02ad2fd85f1c9643ee5792f4b3de) ) // graphics, plane 2 */ ROM_LOAD( "136076-1027.13r", 0x090000, 0x10000, CRC(621cc2ce) SHA1(15db80d61f1c624c09085ed86341f8577bfac168) ) ROM_LOAD( "136076-1031.14s", 0x0a0000, 0x10000, CRC(4682ceb5) SHA1(609ccd20f654982e01bcc6aea89801c01afe083e) ) ROM_LOAD( "136076-1035.14r", 0x0b0000, 0x10000, CRC(7a0e1b9e) SHA1(b9a2270ee7e3b3dcf05a47085890d87bf5b3e167) ) - ROM_LOAD( "136076-1024.17s", 0x0c0000, 0x10000, CRC(d84452b5) SHA1(29bc994e37bc08fa40326b811339e7aa3290302c) ) /* graphics, plane 3 */ + ROM_LOAD( "136076-1024.17s", 0x0c0000, 0x10000, CRC(d84452b5) SHA1(29bc994e37bc08fa40326b811339e7aa3290302c) ) // graphics, plane 3 */ ROM_LOAD( "136076-1028.17r", 0x0d0000, 0x10000, CRC(0cc20245) SHA1(ebdcb47909374508abe9d0252fd88d6274a0f729) ) ROM_LOAD( "136076-1032.14p", 0x0e0000, 0x10000, CRC(f639161a) SHA1(cc2549f7fdd251fa44735a6cd5fdb8ffb97948be) ) ROM_LOAD( "136076-1036.16p", 0x0f0000, 0x10000, CRC(b342443d) SHA1(fa7865f8a90c0e761e1cc5e155931d0574f2d81c) ) - ROM_REGION( 0x100000, "gfx2", ROMREGION_INVERT ) + ROM_REGION( 0x100000, "sprites_tiles2", ROMREGION_INVERT ) ROM_LOAD( "136076-1037.2s", 0x000000, 0x10000, CRC(07addba6) SHA1(4a3286ee570bf4263944854bf959c8ef114cc123) ) ROM_LOAD( "136076-1041.2r", 0x010000, 0x10000, CRC(1e9c29e4) SHA1(e4afa2c469bfa22504cba5dfd23704c5c2bb33c4) ) ROM_LOAD( "136076-1045.34s", 0x020000, 0x10000, CRC(e7235876) SHA1(0bb03baec1de3e520dc270a3ed44bec953e08c00) ) @@ -414,10 +698,10 @@ ROM_START( thunderja ) ROM_LOAD( "136076-1048.16s", 0x0e0000, 0x10000, CRC(200d45b3) SHA1(72f1b3deaebc6266140fb79a97154f80f2cadf33) ) ROM_LOAD( "136076-1052.16r", 0x0f0000, 0x10000, CRC(74711ef1) SHA1(c1429d6b54dc4352defdd6cf83f1a5734784e703) ) - ROM_REGION( 0x010000, "gfx3", 0 ) - ROM_LOAD( "136076-1020.4m", 0x000000, 0x10000, CRC(65470354) SHA1(9895d26fa9e01c254a3d15e657152cac717c68a3) ) /* alphanumerics */ + ROM_REGION( 0x010000, "chars", 0 ) + ROM_LOAD( "136076-1020.4m", 0x000000, 0x10000, CRC(65470354) SHA1(9895d26fa9e01c254a3d15e657152cac717c68a3) ) - ROM_REGION( 0x40000, "jsa:oki1", 0 ) /* 256k for ADPCM */ + ROM_REGION( 0x40000, "jsa:oki1", 0 ) ROM_LOAD( "136076-1016.7k", 0x00000, 0x10000, CRC(c10bdf73) SHA1(a0371c6ddef2a95193c68879044b3338d481fc96) ) ROM_LOAD( "136076-1017.7j", 0x10000, 0x10000, CRC(4e5e25e8) SHA1(373c946abd24ce8dd5221f1a0409af4537610d3d) ) ROM_LOAD( "136076-1018.7e", 0x20000, 0x10000, CRC(ec81895d) SHA1(56acffb0700d3b70ca705fba9d240a82950fd320) ) @@ -433,18 +717,7 @@ ROM_START( thunderja ) ROM_LOAD( "gal20v8a-136076-1076.1l", 0x0c00, 0x0157, CRC(f36f873a) SHA1(63e6cc6e50370e89ebe33aa8d4ff9c6e1faeb9a6) ) ROM_END - - -/************************************* - * - * Driver initialization - * - *************************************/ - -void thunderj_state::init_thunderj() -{ -} - +} // anonymous namespace /************************************* @@ -453,5 +726,5 @@ void thunderj_state::init_thunderj() * *************************************/ -GAME( 1990, thunderj, 0, thunderj, thunderj, thunderj_state, init_thunderj, ROT0, "Atari Games", "ThunderJaws (rev 3)", 0 ) -GAME( 1990, thunderja, thunderj, thunderj, thunderj, thunderj_state, init_thunderj, ROT0, "Atari Games", "ThunderJaws (rev 2)", 0 ) +GAME( 1990, thunderj, 0, thunderj, thunderj, thunderj_state, empty_init, ROT0, "Atari Games", "ThunderJaws (rev 3)", MACHINE_SUPPORTS_SAVE ) +GAME( 1990, thunderja, thunderj, thunderj, thunderj, thunderj_state, empty_init, ROT0, "Atari Games", "ThunderJaws (rev 2)", MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/atari/thunderj.h b/src/mame/atari/thunderj.h deleted file mode 100644 index cb0d4e19e1a..00000000000 --- a/src/mame/atari/thunderj.h +++ /dev/null @@ -1,59 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/************************************************************************* - - Atari ThunderJaws hardware - -*************************************************************************/ -#ifndef MAME_ATARI_THUNDERJ_H -#define MAME_ATARI_THUNDERJ_H - -#pragma once - -#include "atarijsa.h" -#include "atarimo.h" -#include "atarivad.h" -#include "screen.h" -#include "tilemap.h" - -class thunderj_state : public driver_device -{ -public: - thunderj_state(const machine_config &mconfig, device_type type, const char *tag) : - driver_device(mconfig, type, tag), - m_screen(*this, "screen"), - m_jsa(*this, "jsa"), - m_vad(*this, "vad"), - m_maincpu(*this, "maincpu"), - m_extra(*this, "extra") - { } - - void thunderj(machine_config &config); - - void init_thunderj(); - -private: - virtual void machine_start() override; - DECLARE_WRITE_LINE_MEMBER(scanline_int_write_line); - uint16_t special_port2_r(); - void latch_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0); - TILE_GET_INFO_MEMBER(get_alpha_tile_info); - TILE_GET_INFO_MEMBER(get_playfield_tile_info); - TILE_GET_INFO_MEMBER(get_playfield2_tile_info); - uint32_t screen_update_thunderj(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - - void extra_map(address_map &map); - void main_map(address_map &map); - - required_device m_screen; - required_device m_jsa; - required_device m_vad; - required_device m_maincpu; - required_device m_extra; - - uint8_t m_alpha_tile_bank = 0; - - static const atari_motion_objects_config s_mob_config; -}; - -#endif // MAME_ATARI_THUNDERJ_H diff --git a/src/mame/atari/thunderj_v.cpp b/src/mame/atari/thunderj_v.cpp deleted file mode 100644 index bb27cb09be6..00000000000 --- a/src/mame/atari/thunderj_v.cpp +++ /dev/null @@ -1,238 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - Atari ThunderJaws hardware - -****************************************************************************/ - -#include "emu.h" -#include "thunderj.h" - - - -/************************************* - * - * Tilemap callbacks - * - *************************************/ - -TILE_GET_INFO_MEMBER(thunderj_state::get_alpha_tile_info) -{ - uint16_t data = m_vad->alpha().basemem_read(tile_index); - int code = ((data & 0x200) ? (m_alpha_tile_bank * 0x200) : 0) + (data & 0x1ff); - int color = ((data >> 10) & 0x0f) | ((data >> 9) & 0x20); - int opaque = data & 0x8000; - tileinfo.set(2, code, color, opaque ? TILE_FORCE_LAYER0 : 0); -} - - -TILE_GET_INFO_MEMBER(thunderj_state::get_playfield_tile_info) -{ - uint16_t data1 = m_vad->playfield().basemem_read(tile_index); - uint16_t data2 = m_vad->playfield().extmem_read(tile_index) & 0xff; - int code = data1 & 0x7fff; - int color = 0x10 + (data2 & 0x0f); - tileinfo.set(0, code, color, (data1 >> 15) & 1); - tileinfo.category = (data2 >> 4) & 3; -} - - -TILE_GET_INFO_MEMBER(thunderj_state::get_playfield2_tile_info) -{ - uint16_t data1 = m_vad->playfield2().basemem_read(tile_index); - uint16_t data2 = m_vad->playfield2().extmem_read(tile_index) >> 8; - int code = data1 & 0x7fff; - int color = data2 & 0x0f; - tileinfo.set(0, code, color, (data1 >> 15) & 1); - tileinfo.category = (data2 >> 4) & 3; -} - - - -/************************************* - * - * Video system start - * - *************************************/ - -const atari_motion_objects_config thunderj_state::s_mob_config = -{ - 1, /* index to which gfx system */ - 1, /* number of motion object banks */ - 1, /* are the entries linked? */ - 0, /* are the entries split? */ - 1, /* render in reverse order? */ - 0, /* render in swapped X/Y order? */ - 0, /* does the neighbor bit affect the next object? */ - 8, /* pixels per SLIP entry (0 for no-slip) */ - 0, /* pixel offset for SLIPs */ - 0, /* maximum number of links to visit/scanline (0=all) */ - - 0x100, /* base palette entry */ - 0x100, /* maximum number of colors */ - 0, /* transparent pen index */ - - {{ 0x03ff,0,0,0 }}, /* mask for the link */ - {{ 0,0x7fff,0,0 }}, /* mask for the code index */ - {{ 0,0,0x000f,0 }}, /* mask for the color */ - {{ 0,0,0xff80,0 }}, /* mask for the X position */ - {{ 0,0,0,0xff80 }}, /* mask for the Y position */ - {{ 0,0,0,0x0070 }}, /* mask for the width, in tiles*/ - {{ 0,0,0,0x0007 }}, /* mask for the height, in tiles */ - {{ 0,0x8000,0,0 }}, /* mask for the horizontal flip */ - {{ 0 }}, /* mask for the vertical flip */ - {{ 0,0,0x0070,0 }}, /* mask for the priority */ - {{ 0 }}, /* mask for the neighbor */ - {{ 0 }}, /* mask for absolute coordinates */ - - {{ 0 }}, /* mask for the special value */ - 0, /* resulting value to indicate "special" */ -}; - - - -/************************************* - * - * Main refresh - * - *************************************/ - -uint32_t thunderj_state::screen_update_thunderj(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) -{ - // start drawing - m_vad->mob().draw_async(cliprect); - - /* draw the playfield */ - bitmap_ind8 &priority_bitmap = screen.priority(); - priority_bitmap.fill(0, cliprect); - m_vad->playfield().draw(screen, bitmap, cliprect, 0, 0x00); - m_vad->playfield().draw(screen, bitmap, cliprect, 1, 0x01); - m_vad->playfield().draw(screen, bitmap, cliprect, 2, 0x02); - m_vad->playfield().draw(screen, bitmap, cliprect, 3, 0x03); - m_vad->playfield2().draw(screen, bitmap, cliprect, 0, 0x80); - m_vad->playfield2().draw(screen, bitmap, cliprect, 1, 0x84); - m_vad->playfield2().draw(screen, bitmap, cliprect, 2, 0x88); - m_vad->playfield2().draw(screen, bitmap, cliprect, 3, 0x8c); - - // draw and merge the MO - bitmap_ind16 &mobitmap = m_vad->mob().bitmap(); - for (const sparse_dirty_rect *rect = m_vad->mob().first_dirty_rect(cliprect); rect != nullptr; rect = rect->next()) - for (int y = rect->top(); y <= rect->bottom(); y++) - { - uint16_t const *const mo = &mobitmap.pix(y); - uint16_t *const pf = &bitmap.pix(y); - uint8_t const *const pri = &priority_bitmap.pix(y); - for (int x = rect->left(); x <= rect->right(); x++) - if (mo[x] != 0xffff) - { - /* verified from the GALs on the real PCB; equations follow - * - * --- PF/M is 1 if playfield has priority, or 0 if MOs have priority - * PF/M=MPX0*!MPX1*!MPX2*!MPX3*!MPX4*!MPX5*!MPX6*!MPX7 - * +PFX3*PFX8*PFX9*!MPR0 - * +PFX3*PFX8*!MPR0*!MPR1 - * +PFX3*PFX9*!MPR1 - * - * --- CS1 is 1 if the playfield should be displayed - * CS1=PF/M*!ALBG*!APIX0*!APIX1 - * +!MPX0*!MPX1*!MPX2*!MPX3*!ALBG*!APIX0*!APIX1 - * - * --- CS0 is 1 if the MOs should be displayed - * CS0=!PF/M*MPX0*!ALBG*!APIX0*!APIX1 - * +!PF/M*MPX1*!ALBG*!APIX0*!APIX1 - * +!PF/M*MPX2*!ALBG*!APIX0*!APIX1 - * +!PF/M*MPX3*!ALBG*!APIX0*!APIX1 - * - * --- CRA10 is the 0x200 bit of the color RAM index; set if pf is displayed - * CRA10:=CS1 - * - * --- CRA9 is the 0x100 bit of the color RAM index; set if mo is displayed - * or if the playfield selected is playfield #2 - * CRA9:=PFXS*CS1 - * +!CS1*CS0 - * - * --- CRA8-1 are the low 8 bits of the color RAM index; set as expected - * CRA8:=CS1*PFX7 - * +!CS1*MPX7*CS0 - * +!CS1*!CS0*ALC4 - * - * CRA7:=CS1*PFX6 - * +!CS1*MPX6*CS0 - * - * CRA6:=CS1*PFX5 - * +MPX5*!CS1*CS0 - * +!CS1*!CS0*ALC3 - * - * CRA5:=CS1*PFX4 - * +MPX4*!CS1*CS0 - * +!CS1*ALC2*!CS0 - * - * CRA4:=CS1*PFX3 - * +!CS1*MPX3*CS0 - * +!CS1*!CS0*ALC1 - * - * CRA3:=CS1*PFX2 - * +MPX2*!CS1*CS0 - * +!CS1*!CS0*ALC0 - * - * CRA2:=CS1*PFX1 - * +MPX1*!CS1*CS0 - * +!CS1*!CS0*APIX1 - * - * CRA1:=CS1*PFX0 - * +MPX0*!CS1*CS0 - * +!CS1*!CS0*APIX0 - */ - int const mopriority = mo[x] >> atari_motion_objects_device::PRIORITY_SHIFT; - - /* upper bit of MO priority signals special rendering and doesn't draw anything */ - if (mopriority & 4) - continue; - - /* determine pf/m signal */ - int pfm = 0; - if ((mo[x] & 0xff) == 1) - pfm = 1; - else if (pf[x] & 8) - { - int const pfpriority = (pri[x] & 0x80) ? ((pri[x] >> 2) & 3) : (pri[x] & 3); - if (((pfpriority == 3) && !(mopriority & 1)) || - ((pfpriority & 1) && (mopriority == 0)) || - ((pfpriority & 2) && !(mopriority & 2))) - pfm = 1; - } - - /* if pfm is low, we display the mo */ - if (!pfm) - pf[x] = mo[x] & atari_motion_objects_device::DATA_MASK; - - /* don't erase yet -- we need to make another pass later */ - } - } - - /* add the alpha on top */ - m_vad->alpha().draw(screen, bitmap, cliprect, 0, 0); - - /* now go back and process the upper bit of MO priority */ - for (const sparse_dirty_rect *rect = m_vad->mob().first_dirty_rect(cliprect); rect != nullptr; rect = rect->next()) - for (int y = rect->top(); y <= rect->bottom(); y++) - { - uint16_t const *const mo = &mobitmap.pix(y); - uint16_t *const pf = &bitmap.pix(y); - for (int x = rect->left(); x <= rect->right(); x++) - if (mo[x] != 0xffff) - { - int const mopriority = mo[x] >> atari_motion_objects_device::PRIORITY_SHIFT; - - /* upper bit of MO priority might mean palette kludges */ - if (mopriority & 4) - { - /* if bit 2 is set, start setting high palette bits */ - if (mo[x] & 2) - m_vad->mob().apply_stain(bitmap, pf, mo, x, y); - } - } - } - return 0; -} diff --git a/src/mame/atari/triplhnt.cpp b/src/mame/atari/triplhnt.cpp index 83cd0aa5fd0..61d6d5ba342 100644 --- a/src/mame/atari/triplhnt.cpp +++ b/src/mame/atari/triplhnt.cpp @@ -49,8 +49,7 @@ public: m_0c09(*this, "0C09"), m_0c0b(*this, "0C0B"), m_vblank(*this, "VBLANK"), - m_stick(*this, "STICK%c", 'X'), - m_lamp(*this, "lamp0") + m_stick(*this, "STICK%c", 'X') { } void triplhnt(machine_config &config); @@ -80,7 +79,6 @@ private: required_ioport m_0c0b; required_ioport m_vblank; required_ioport_array<2> m_stick; - output_finder<> m_lamp; uint8_t m_cmos[16]{}; uint8_t m_da_latch = 0; @@ -293,8 +291,6 @@ uint8_t triplhnt_state::da_latch_r(offs_t offset) void triplhnt_state::machine_start() { - m_lamp.resolve(); - m_hit_code = 0; } @@ -486,7 +482,7 @@ void triplhnt_state::triplhnt(machine_config &config) F9334(config, m_latch); // J7 m_latch->q_out_cb<0>().set_nop(); // unused - m_latch->q_out_cb<1>().set([this] (int state) { m_lamp = state ? 1 : 0; }); + m_latch->q_out_cb<1>().set_output("lamp0"); m_latch->q_out_cb<1>().append(m_discrete, FUNC(discrete_device::write_line)); // Lamp is used to reset noise m_latch->q_out_cb<2>().set(m_discrete, FUNC(discrete_device::write_line)); // screech m_latch->q_out_cb<3>().set(FUNC(triplhnt_state::coin_lockout_w)); -- cgit v1.2.3