diff options
Diffstat (limited to 'src/mame/drivers/exidy.cpp')
-rw-r--r-- | src/mame/drivers/exidy.cpp | 1063 |
1 files changed, 800 insertions, 263 deletions
diff --git a/src/mame/drivers/exidy.cpp b/src/mame/drivers/exidy.cpp index 096b2ea215d..2060cb19ee1 100644 --- a/src/mame/drivers/exidy.cpp +++ b/src/mame/drivers/exidy.cpp @@ -149,25 +149,254 @@ Fax 1982 6502 FXL, FLA ***************************************************************************/ #include "emu.h" +#include "audio/exidy.h" + #include "cpu/m6502/m6502.h" #include "machine/6821pia.h" -#include "audio/exidy.h" -#include "includes/exidy.h" +#include "sound/dac.h" +#include "sound/samples.h" + +#include "emupal.h" +#include "screen.h" #include "speaker.h" +namespace { + +#define EXIDY_MASTER_CLOCK (XTAL(11'289'000)) +#define EXIDY_CPU_CLOCK (EXIDY_MASTER_CLOCK / 16) +#define EXIDY_PIXEL_CLOCK (EXIDY_MASTER_CLOCK / 2) +#define EXIDY_HTOTAL (0x150) +#define EXIDY_HBEND (0x000) +#define EXIDY_HBSTART (0x100) +#define EXIDY_HSEND (0x140) +#define EXIDY_HSSTART (0x120) +#define EXIDY_VTOTAL (0x118) +#define EXIDY_VBEND (0x000) +#define EXIDY_VBSTART (0x100) +#define EXIDY_VSEND (0x108) +#define EXIDY_VSSTART (0x100) + + +class exidy_state : public driver_device +{ +public: + enum + { + TIMER_COLLISION_IRQ + }; + + exidy_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_color_latch(*this, "color_latch"), + m_videoram(*this, "videoram"), + m_sprite1_xpos(*this, "sprite1_xpos"), + m_sprite1_ypos(*this, "sprite1_ypos"), + m_sprite2_xpos(*this, "sprite2_xpos"), + m_sprite2_ypos(*this, "sprite2_ypos"), + m_spriteno(*this, "spriteno"), + m_sprite_enable(*this, "sprite_enable"), + m_characterram(*this, "characterram") + { + } + + void venture(machine_config &config); + void mtrap(machine_config &config); + void pepper2(machine_config &config); + +protected: + required_device<cpu_device> m_maincpu; + required_device<gfxdecode_device> m_gfxdecode; + required_device<screen_device> m_screen; + required_device<palette_device> m_palette; + required_shared_ptr<uint8_t> m_color_latch; + + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + virtual void video_start() override; + + void base(machine_config &config); + + void exidy_video_config(uint8_t _collision_mask, uint8_t _collision_invert, int _is_2bpp); + + uint8_t exidy_interrupt_r(); + + void exidy_map(address_map &map); + +private: + required_shared_ptr<uint8_t> m_videoram; + required_shared_ptr<uint8_t> m_sprite1_xpos; + required_shared_ptr<uint8_t> m_sprite1_ypos; + required_shared_ptr<uint8_t> m_sprite2_xpos; + required_shared_ptr<uint8_t> m_sprite2_ypos; + required_shared_ptr<uint8_t> m_spriteno; + required_shared_ptr<uint8_t> m_sprite_enable; + optional_shared_ptr<uint8_t> m_characterram; + + uint8_t m_collision_mask; + uint8_t m_collision_invert; + int m_is_2bpp; + uint8_t m_int_condition; + bitmap_ind16 m_background_bitmap; + bitmap_ind16 m_motion_object_1_vid; + bitmap_ind16 m_motion_object_2_vid; + bitmap_ind16 m_motion_object_2_clip; + + void mtrap_ocl_w(uint8_t data); + + uint32_t screen_update_exidy(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + INTERRUPT_GEN_MEMBER(exidy_vblank_interrupt); + + void latch_condition(int collision); + void set_1_color(int index, int which); + void set_colors(); + void draw_background(); + int sprite_1_enabled(); + void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect); + void check_collision(); + + void venture_map(address_map &map); + void mtrap_map(address_map &map); + void pepper2_map(address_map &map); +}; + + +class spectar_state : public exidy_state +{ +public: + spectar_state(const machine_config &mconfig, device_type type, const char *tag) : + exidy_state(mconfig, type, tag), + m_dac(*this, "dac"), + m_samples(*this, "samples") + { + } + + void sidetrac(machine_config &config); + void spectar(machine_config &config); + void rallys(machine_config &config); + void phantoma(machine_config &config); + + void init_sidetrac(); + void init_spectar(); + +protected: + virtual void machine_start() override; + + void set_max_freq(int freq) { m_max_freq = freq; } + + void spectar_audio_1_w(uint8_t data); + void spectar_audio_2_w(uint8_t data); + + void adjust_sample(uint8_t freq); + bool RISING_EDGE(uint8_t data, uint8_t bit) const { return (data & bit) && !(m_port_1_last & bit); } + bool FALLING_EDGE(uint8_t data, uint8_t bit) const { return !(data & bit) && (m_port_1_last & bit); } + +private: + required_device<dac_bit_interface> m_dac; + required_device<samples_device> m_samples; + + // Targ and Spectar samples + int m_max_freq; + uint8_t m_port_1_last; + uint8_t m_tone_freq; + uint8_t m_tone_active; + + void sidetrac_map(address_map &map); + void spectar_map(address_map &map); + void rallys_map(address_map &map); + void phantoma_map(address_map &map); +}; + + +class targ_state : public spectar_state +{ +public: + targ_state(const machine_config &mconfig, device_type type, const char *tag) : + spectar_state(mconfig, type, tag), + m_sound_prom(*this, "targ") + { + } + + void targ(machine_config &config); + + void init_targ(); + +protected: + virtual void machine_start() override; + + void targ_audio_1_w(uint8_t data); + void targ_audio_2_w(uint8_t data); + +private: + required_region_ptr<uint8_t> m_sound_prom; + + uint8_t m_port_2_last; + uint8_t m_tone_pointer; + + void targ_map(address_map &map); +}; + + +class teetert_state : public exidy_state +{ +public: + teetert_state(const machine_config &mconfig, device_type type, const char *tag) : + exidy_state(mconfig, type, tag), + m_dial(*this, "DIAL") + { + } + + void teetert(machine_config &config); + + DECLARE_CUSTOM_INPUT_MEMBER(teetert_input_r); + +protected: + virtual void machine_start() override; + +private: + required_ioport m_dial; + uint8_t m_last_dial; +}; + + +class fax_state : public exidy_state +{ +public: + fax_state(const machine_config &mconfig, device_type type, const char *tag) : + exidy_state(mconfig, type, tag), + m_rom_bank(*this, "bank1") + { + } + + void fax(machine_config &config); + +protected: + virtual void machine_start() override; + +private: + required_memory_bank m_rom_bank; + + void fax_bank_select_w(uint8_t data); + + void fax_map(address_map &map); +}; + + /************************************* * * Special Teeter Torture input * *************************************/ -CUSTOM_INPUT_MEMBER(exidy_state::teetert_input_r) +CUSTOM_INPUT_MEMBER(teetert_state::teetert_input_r) { - uint8_t dial = ioport("DIAL")->read(); - int result = 0; + uint8_t dial = m_dial->read(); - result = (dial != m_last_dial) << 4; + int result = (dial != m_last_dial) << 4; if (result != 0) { if (((dial - m_last_dial) & 0xff) < 0x80) @@ -190,9 +419,9 @@ CUSTOM_INPUT_MEMBER(exidy_state::teetert_input_r) * *************************************/ -void exidy_state::fax_bank_select_w(uint8_t data) +void fax_state::fax_bank_select_w(uint8_t data) { - membank("bank1")->set_entry(data & 0x1f); + m_rom_bank->set_entry(data & 0x1f); if ((data & 0x1f) > 0x17) logerror("Banking to unpopulated ROM bank %02X!\n", data & 0x1f); @@ -231,40 +460,40 @@ void exidy_state::exidy_map(address_map &map) } -void exidy_state::sidetrac_map(address_map &map) +void spectar_state::sidetrac_map(address_map &map) { exidy_map(map); map(0x0800, 0x3fff).rom(); map(0x4800, 0x4fff).rom(); - map(0x5200, 0x5200).w(FUNC(exidy_state::targ_audio_1_w)); - map(0x5201, 0x5201).w(FUNC(exidy_state::spectar_audio_2_w)); + map(0x5200, 0x5200).w(FUNC(spectar_state::spectar_audio_1_w)); + map(0x5201, 0x5201).w(FUNC(spectar_state::spectar_audio_2_w)); map(0xff00, 0xffff).rom().region("maincpu", 0x3f00); } -void exidy_state::targ_map(address_map &map) +void targ_state::targ_map(address_map &map) { exidy_map(map); map(0x0800, 0x3fff).rom(); map(0x4800, 0x4fff).ram().share("characterram"); - map(0x5200, 0x5200).w(FUNC(exidy_state::targ_audio_1_w)); - map(0x5201, 0x5201).w(FUNC(exidy_state::targ_audio_2_w)); + map(0x5200, 0x5200).w(FUNC(targ_state::targ_audio_1_w)); + map(0x5201, 0x5201).w(FUNC(targ_state::targ_audio_2_w)); map(0xff00, 0xffff).rom().region("maincpu", 0x3f00); } -void exidy_state::spectar_map(address_map &map) +void spectar_state::spectar_map(address_map &map) { exidy_map(map); map(0x0800, 0x3fff).rom(); map(0x4800, 0x4fff).ram().share("characterram"); - map(0x5200, 0x5200).w(FUNC(exidy_state::targ_audio_1_w)); - map(0x5201, 0x5201).w(FUNC(exidy_state::spectar_audio_2_w)); + map(0x5200, 0x5200).w(FUNC(spectar_state::spectar_audio_1_w)); + map(0x5201, 0x5201).w(FUNC(spectar_state::spectar_audio_2_w)); map(0xff00, 0xffff).rom().region("maincpu", 0x3f00); } -void exidy_state::rallys_map(address_map &map) +void spectar_state::rallys_map(address_map &map) { map(0x0000, 0x03ff).ram(); map(0x0800, 0x3fff).rom(); @@ -276,9 +505,9 @@ void exidy_state::rallys_map(address_map &map) map(0x5100, 0x5100).mirror(0x00fc).writeonly().share("spriteno"); map(0x5101, 0x5101).mirror(0x00fc).portr("IN0"); map(0x5101, 0x5101).mirror(0x00fc).writeonly().share("sprite_enable"); - map(0x5103, 0x5103).mirror(0x00fc).r(FUNC(exidy_state::exidy_interrupt_r)); - map(0x5200, 0x5200).w(FUNC(exidy_state::targ_audio_1_w)); - map(0x5201, 0x5201).w(FUNC(exidy_state::spectar_audio_2_w)); + map(0x5103, 0x5103).mirror(0x00fc).r(FUNC(spectar_state::exidy_interrupt_r)); + map(0x5200, 0x5200).w(FUNC(spectar_state::spectar_audio_1_w)); + map(0x5201, 0x5201).w(FUNC(spectar_state::spectar_audio_2_w)); map(0x5210, 0x5212).writeonly().share("color_latch"); map(0x5213, 0x5213).portr("IN2"); map(0x5300, 0x5300).writeonly().share("sprite2_xpos"); @@ -287,6 +516,13 @@ void exidy_state::rallys_map(address_map &map) } +void spectar_state::phantoma_map(address_map &map) +{ + rallys_map(map); + map(0xf800, 0xffff).rom().region("maincpu", 0xf800); // the ROM is actually mapped high +} + + void exidy_state::venture_map(address_map &map) { exidy_map(map); @@ -311,14 +547,14 @@ void exidy_state::mtrap_map(address_map &map) map(0x5101, 0x5101).w(FUNC(exidy_state::mtrap_ocl_w)); } -void exidy_state::fax_map(address_map &map) +void fax_state::fax_map(address_map &map) { exidy_map(map); map(0x0400, 0x07ff).ram(); map(0x1a00, 0x1a00).portr("IN4"); map(0x1c00, 0x1c00).portr("IN3"); - map(0x2000, 0x2000).w(FUNC(exidy_state::fax_bank_select_w)); - map(0x2000, 0x3fff).bankr("bank1"); + map(0x2000, 0x2000).w(FUNC(fax_state::fax_bank_select_w)); + map(0x2000, 0x3fff).bankr(m_rom_bank); map(0x5200, 0x520f).rw("pia", FUNC(pia6821_device::read), FUNC(pia6821_device::write)); map(0x5213, 0x5217).nopw(); /* empty control lines on color/sound board */ map(0x6000, 0x6fff).ram().share("characterram"); @@ -639,7 +875,7 @@ static INPUT_PORTS_START( teetert ) PORT_START("IN0") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START2 ) - PORT_BIT( 0x44, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(exidy_state, teetert_input_r) + PORT_BIT( 0x44, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_CUSTOM_MEMBER(teetert_state, teetert_input_r) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN ) @@ -824,15 +1060,414 @@ GFXDECODE_END /************************************* * + * Video configuration + * + *************************************/ + +void exidy_state::exidy_video_config(uint8_t _collision_mask, uint8_t _collision_invert, int _is_2bpp) +{ + m_collision_mask = _collision_mask; + m_collision_invert = _collision_invert; + m_is_2bpp = _is_2bpp; +} + + + +/************************************* + * + * Video startup + * + *************************************/ + +void exidy_state::video_start() +{ + m_screen->register_screen_bitmap(m_background_bitmap); + m_motion_object_1_vid.allocate(16, 16); + m_motion_object_2_vid.allocate(16, 16); + m_motion_object_2_clip.allocate(16, 16); + + save_item(NAME(m_int_condition)); + save_item(NAME(m_background_bitmap)); + save_item(NAME(m_motion_object_1_vid)); + save_item(NAME(m_motion_object_2_vid)); + save_item(NAME(m_motion_object_2_clip)); +} + + + +/************************************* + * + * Interrupt generation + * + *************************************/ + +inline void exidy_state::latch_condition(int collision) +{ + collision ^= m_collision_invert; + m_int_condition = (ioport("INTSOURCE")->read() & ~0x1c) | (collision & m_collision_mask); +} + + +INTERRUPT_GEN_MEMBER(exidy_state::exidy_vblank_interrupt) +{ + /* latch the current condition */ + latch_condition(0); + m_int_condition &= ~0x80; + + /* set the IRQ line */ + device.execute().set_input_line(0, ASSERT_LINE); +} + + + +uint8_t exidy_state::exidy_interrupt_r() +{ + /* clear any interrupts */ + m_maincpu->set_input_line(0, CLEAR_LINE); + + /* return the latched condition */ + return m_int_condition; +} + + + +/************************************* + * + * Palette handling + * + *************************************/ + +inline void exidy_state::set_1_color(int index, int which) +{ + m_palette->set_pen_color(index, + pal1bit(m_color_latch[2] >> which), + pal1bit(m_color_latch[1] >> which), + pal1bit(m_color_latch[0] >> which)); +} + +void exidy_state::set_colors() +{ + /* motion object 1 */ + set_1_color(0, 0); + set_1_color(1, 7); + + /* motion object 2 */ + set_1_color(2, 0); + set_1_color(3, 6); + + /* characters */ + set_1_color(4, 4); + set_1_color(5, 3); + set_1_color(6, 2); + set_1_color(7, 1); +} + + + +/************************************* + * + * Background update + * + *************************************/ + +void exidy_state::draw_background() +{ + const uint8_t *const cram = m_characterram ? &m_characterram[0] : memregion("maincpu")->base() + 0x4800; + + pen_t off_pen = 0; + + for (offs_t offs = 0; offs < 0x400; offs++) + { + uint8_t y = offs >> 5 << 3; + uint8_t const code = m_videoram[offs]; + + pen_t on_pen_1, on_pen_2; + if (m_is_2bpp) + { + on_pen_1 = 4 + ((code >> 6) & 0x02); + on_pen_2 = 5 + ((code >> 6) & 0x02); + } + else + { + on_pen_1 = 4 + ((code >> 6) & 0x03); + on_pen_2 = off_pen; /* unused */ + } + + for (uint8_t cy = 0; cy < 8; cy++) + { + uint8_t x = offs << 3; + + if (m_is_2bpp) + { + uint8_t data1 = cram[0x000 | (code << 3) | cy]; + uint8_t data2 = cram[0x800 | (code << 3) | cy]; + + for (int i = 0; i < 8; i++) + { + if (data1 & 0x80) + m_background_bitmap.pix(y, x) = (data2 & 0x80) ? on_pen_2 : on_pen_1; + else + m_background_bitmap.pix(y, x) = off_pen; + + x++; + data1 <<= 1; + data2 <<= 1; + } + } + else // 1bpp + { + uint8_t data = cram[(code << 3) | cy]; + + for (int i = 0; i < 8; i++) + { + m_background_bitmap.pix(y, x) = (data & 0x80) ? on_pen_1 : off_pen; + + x++; + data <<= 1; + } + } + + y++; + } + } +} + + + +/************************************* + * + * Sprite hardware + * + *************************************/ + +inline int exidy_state::sprite_1_enabled() +{ + /* if the collision_mask is 0x00, then we are on old hardware that always has */ + /* sprite 1 enabled regardless */ + return (!(*m_sprite_enable & 0x80) || (*m_sprite_enable & 0x10) || (m_collision_mask == 0x00)); +} + + +void exidy_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + /* draw sprite 2 first */ + int sprite_set_2 = ((*m_sprite_enable & 0x40) != 0); + + int sx = 236 - *m_sprite2_xpos - 4; + int sy = 244 - *m_sprite2_ypos - 4; + + m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, + ((*m_spriteno >> 4) & 0x0f) + 32 + 16 * sprite_set_2, 1, + 0, 0, sx, sy, 0); + + /* draw sprite 1 next */ + if (sprite_1_enabled()) + { + int sprite_set_1 = ((*m_sprite_enable & 0x20) != 0); + + sx = 236 - *m_sprite1_xpos - 4; + sy = 244 - *m_sprite1_ypos - 4; + + if (sy < 0) sy = 0; + + m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, + (*m_spriteno & 0x0f) + 16 * sprite_set_1, 0, + 0, 0, sx, sy, 0); + } + +} + + + +/************************************* + * + * Collision detection + * + *************************************/ + +/*************************************************************************** + + Exidy hardware checks for two types of collisions based on the video + signals. If the Motion Object 1 and Motion Object 2 signals are on at + the same time, an M1M2 collision bit gets set. If the Motion Object 1 + and Background Character signals are on at the same time, an M1CHAR + collision bit gets set. So effectively, there's a pixel-by-pixel + collision check comparing Motion Object 1 (the player) to the + background and to the other Motion Object (typically a bad guy). + +***************************************************************************/ + +void exidy_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_COLLISION_IRQ: + /* latch the collision bits */ + latch_condition(param); + + /* set the IRQ line */ + m_maincpu->set_input_line(0, ASSERT_LINE); + + break; + default: + throw emu_fatalerror("Unknown id in exidy_state::device_timer"); + } +} + + +void exidy_state::check_collision() +{ + uint8_t sprite_set_1 = ((*m_sprite_enable & 0x20) != 0); + uint8_t sprite_set_2 = ((*m_sprite_enable & 0x40) != 0); + const rectangle clip(0, 15, 0, 15); + int org_1_x = 0, org_1_y = 0; + int org_2_x = 0, org_2_y = 0; + int count = 0; + + /* if there is nothing to detect, bail */ + if (m_collision_mask == 0) + return; + + /* draw sprite 1 */ + m_motion_object_1_vid.fill(0xff, clip); + if (sprite_1_enabled()) + { + org_1_x = 236 - *m_sprite1_xpos - 4; + org_1_y = 244 - *m_sprite1_ypos - 4; + m_gfxdecode->gfx(0)->transpen(m_motion_object_1_vid,clip, + (*m_spriteno & 0x0f) + 16 * sprite_set_1, 0, + 0, 0, 0, 0, 0); + } + + /* draw sprite 2 */ + m_motion_object_2_vid.fill(0xff, clip); + org_2_x = 236 - *m_sprite2_xpos - 4; + org_2_y = 244 - *m_sprite2_ypos - 4; + m_gfxdecode->gfx(0)->transpen(m_motion_object_2_vid,clip, + ((*m_spriteno >> 4) & 0x0f) + 32 + 16 * sprite_set_2, 0, + 0, 0, 0, 0, 0); + + /* draw sprite 2 clipped to sprite 1's location */ + m_motion_object_2_clip.fill(0xff, clip); + if (sprite_1_enabled()) + { + int sx = org_2_x - org_1_x; + int sy = org_2_y - org_1_y; + m_gfxdecode->gfx(0)->transpen(m_motion_object_2_clip,clip, + ((*m_spriteno >> 4) & 0x0f) + 32 + 16 * sprite_set_2, 0, + 0, 0, sx, sy, 0); + } + + /* scan for collisions */ + for (int sy = 0; sy < 16; sy++) + for (int sx = 0; sx < 16; sx++) + { + if (m_motion_object_1_vid.pix(sy, sx) != 0xff) + { + uint8_t current_collision_mask = 0; + + /* check for background collision (M1CHAR) */ + if (m_background_bitmap.pix(org_1_y + sy, org_1_x + sx) != 0) + current_collision_mask |= 0x04; + + /* check for motion object collision (M1M2) */ + if (m_motion_object_2_clip.pix(sy, sx) != 0xff) + current_collision_mask |= 0x10; + + /* if we got one, trigger an interrupt */ + if ((current_collision_mask & m_collision_mask) && (count++ < 128)) + timer_set(m_screen->time_until_pos(org_1_x + sx, org_1_y + sy), TIMER_COLLISION_IRQ, current_collision_mask); + } + + if (m_motion_object_2_vid.pix(sy, sx) != 0xff) + { + /* check for background collision (M2CHAR) */ + if (m_background_bitmap.pix(org_2_y + sy, org_2_x + sx) != 0) + if ((m_collision_mask & 0x08) && (count++ < 128)) + timer_set(m_screen->time_until_pos(org_2_x + sx, org_2_y + sy), TIMER_COLLISION_IRQ, 0x08); + } + } +} + + + +/************************************* + * + * Standard screen refresh callback + * + *************************************/ + +uint32_t exidy_state::screen_update_exidy(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + /* refresh the colors from the palette (static or dynamic) */ + set_colors(); + + /* update the background and draw it */ + draw_background(); + copybitmap(bitmap, m_background_bitmap, 0, 0, 0, 0, cliprect); + + /* draw the sprites */ + draw_sprites(bitmap, cliprect); + + /* check for collision, this will set the appropriate bits in collision_mask */ + check_collision(); + + return 0; +} + + + +/************************************* + * * Machine init * *************************************/ -MACHINE_START_MEMBER(exidy_state,teetert) +void spectar_state::machine_start() { + exidy_state::machine_start(); + + m_tone_freq = 0; + m_tone_active = 0; + + /* start_raw can't be called here: chan.source will be set by + samples_device::device_start and then nulled out by samples_device::device_reset + at the soft_reset stage of init_machine() and will never be set again. + Thus, I've moved it to exidy_state::adjust_sample() were it will be set after + machine initialization. */ + //m_samples->set_volume(3, 0); + //m_samples->start_raw(3, sine_wave, 32, 1000, true); + + save_item(NAME(m_port_1_last)); + save_item(NAME(m_tone_freq)); + save_item(NAME(m_tone_active)); +} + +void targ_state::machine_start() +{ + spectar_state::machine_start(); + + m_tone_pointer = 0; + + save_item(NAME(m_port_2_last)); + save_item(NAME(m_tone_pointer)); +} + +void teetert_state::machine_start() +{ + exidy_state::machine_start(); + save_item(NAME(m_last_dial)); } +void fax_state::machine_start() +{ + exidy_state::machine_start(); + + m_rom_bank->configure_entries(0, 32, memregion("maincpu")->base() + 0x10000, 0x2000); +} + + /************************************* * * Machine drivers @@ -841,11 +1476,11 @@ MACHINE_START_MEMBER(exidy_state,teetert) void exidy_state::base(machine_config &config) { - /* basic machine hardware */ + // basic machine hardware M6502(config, m_maincpu, EXIDY_CPU_CLOCK); m_maincpu->set_vblank_int("screen", FUNC(exidy_state::exidy_vblank_interrupt)); - /* video hardware */ + // video hardware GFXDECODE(config, m_gfxdecode, m_palette, gfx_exidy); PALETTE(config, m_palette).set_entries(8); @@ -857,48 +1492,77 @@ void exidy_state::base(machine_config &config) } -void exidy_state::sidetrac(machine_config &config) +void spectar_state::sidetrac(machine_config &config) { + static const char *const sample_names[] = + { + "*targ", + "expl", + "shot", + "sexpl", + "spslow", + "spfast", + nullptr + }; + base(config); - /* basic machine hardware */ - m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::sidetrac_map); + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &spectar_state::sidetrac_map); + + // video hardware + exidy_video_config(0x00, 0x00, false); + + // audio hardware + set_max_freq(525'000); + + SPEAKER(config, "speaker").front_center(); + + SAMPLES(config, m_samples); + m_samples->set_channels(4); + m_samples->set_samples_names(sample_names); + m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25); - /* audio hardware */ - spectar_audio(config); + DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.99); } -void exidy_state::targ(machine_config &config) +void targ_state::targ(machine_config &config) { - base(config); + sidetrac(config); - /* basic machine hardware */ - m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::targ_map); + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &targ_state::targ_map); - /* audio hardware */ - targ_audio(config); + // audio hardware + set_max_freq(125'000); } -void exidy_state::spectar(machine_config &config) +void spectar_state::spectar(machine_config &config) { - base(config); + sidetrac(config); - /* basic machine hardware */ - m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::spectar_map); + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &spectar_state::spectar_map); +} - /* audio hardware */ - spectar_audio(config); + +void spectar_state::rallys(machine_config &config) +{ + sidetrac(config); + + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &spectar_state::rallys_map); } -void exidy_state::rallys(machine_config &config) +void spectar_state::phantoma(machine_config &config) { - spectar(config); + sidetrac(config); - /* basic machine hardware */ - m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::rallys_map); + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &spectar_state::phantoma_map); } @@ -906,12 +1570,15 @@ void exidy_state::venture(machine_config &config) { base(config); - /* basic machine hardware */ + // basic machine hardware m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::venture_map); config.set_maximum_quantum(attotime::from_hz(600)); - /* audio hardware */ + // video hardware + exidy_video_config(0x04, 0x04, false); + + // audio hardware pia6821_device &pia(PIA6821(config, "pia", 0)); pia.writepa_handler().set("soundbd", FUNC(venture_sound_device::pb_w)); pia.writepb_handler().set("soundbd", FUNC(venture_sound_device::pa_w)); @@ -926,14 +1593,15 @@ void exidy_state::venture(machine_config &config) } -void exidy_state::teetert(machine_config &config) +void teetert_state::teetert(machine_config &config) { venture(config); - /* basic machine hardware */ - m_maincpu->set_periodic_int(FUNC(exidy_state::nmi_line_pulse), attotime::from_hz(10*60)); + // basic machine hardware + m_maincpu->set_periodic_int(FUNC(teetert_state::nmi_line_pulse), attotime::from_hz(10*60)); - MCFG_MACHINE_START_OVERRIDE(exidy_state, teetert ) + // video hardware + exidy_video_config(0x0c, 0x0c, false); } @@ -941,12 +1609,15 @@ void exidy_state::mtrap(machine_config &config) { base(config); - /* basic machine hardware */ + // basic machine hardware m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::mtrap_map); config.set_maximum_quantum(attotime::from_hz(1920)); - /* audio hardware */ + // video hardware + exidy_video_config(0x14, 0x00, false); + + // audio hardware pia6821_device &pia(PIA6821(config, "pia", 0)); pia.writepa_handler().set("soundbd", FUNC(venture_sound_device::pb_w)); pia.writepb_handler().set("soundbd", FUNC(venture_sound_device::pa_w)); @@ -965,17 +1636,23 @@ void exidy_state::pepper2(machine_config &config) { venture(config); - /* basic machine hardware */ + // basic machine hardware m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::pepper2_map); + + // video hardware + exidy_video_config(0x14, 0x04, true); } -void exidy_state::fax(machine_config &config) +void fax_state::fax(machine_config &config) { pepper2(config); - /* basic machine hardware */ - m_maincpu->set_addrmap(AS_PROGRAM, &exidy_state::fax_map); + // basic machine hardware + m_maincpu->set_addrmap(AS_PROGRAM, &fax_state::fax_map); + + // video hardware + exidy_video_config(0x04, 0x04, true); } /************************************************************************* @@ -991,22 +1668,14 @@ void exidy_state::fax(machine_config &config) 3 = Tone generator */ -#define SPECTAR_MAXFREQ 525000 -#define TARG_MAXFREQ 125000 - static const int16_t sine_wave[32] = { - 0x0f0f, 0x0f0f, 0x0f0f, 0x0606, 0x0606, 0x0909, 0x0909, 0x0606, 0x0606, 0x0909, 0x0606, 0x0d0d, 0x0f0f, 0x0f0f, 0x0d0d, 0x0000, + 0x0f0f, 0x0f0f, 0x0f0f, 0x0606, 0x0606, 0x0909, 0x0909, 0x0606, 0x0606, 0x0909, 0x0606, 0x0d0d, 0x0f0f, 0x0f0f, 0x0d0d, 0x0000, -0x191a, -0x2122, -0x1e1f, -0x191a, -0x1314, -0x191a, -0x1819, -0x1819, -0x1819, -0x1314, -0x1314, -0x1314, -0x1819, -0x1e1f, -0x1e1f, -0x1819 }; -/* some macros to make detecting bit changes easier */ -#define RISING_EDGE(bit) ( (data & bit) && !(m_port_1_last & bit)) -#define FALLING_EDGE(bit) (!(data & bit) && (m_port_1_last & bit)) - - -void exidy_state::adjust_sample(uint8_t freq) +void spectar_state::adjust_sample(uint8_t freq) { m_tone_freq = freq; @@ -1026,18 +1695,20 @@ void exidy_state::adjust_sample(uint8_t freq) } -void exidy_state::targ_audio_1_w(uint8_t data) +void spectar_state::spectar_audio_1_w(uint8_t data) { - /* CPU music */ + // CPU music if (BIT(m_port_1_last ^ data, 0)) m_dac->write(BIT(data, 0)); - /* shot */ - if (FALLING_EDGE(0x02) && !m_samples->playing(0)) m_samples->start(0,1); - if (RISING_EDGE(0x02)) m_samples->start(0,1); + // shot + if (FALLING_EDGE(data, 0x02) && !m_samples->playing(0)) + m_samples->start(0,1); + if (RISING_EDGE(data, 0x02)) + m_samples->start(0,1); - /* crash */ - if (RISING_EDGE(0x20)) + // crash + if (RISING_EDGE(data, 0x20)) { if (data & 0x40) m_samples->start(1,0); @@ -1045,7 +1716,7 @@ void exidy_state::targ_audio_1_w(uint8_t data) m_samples->start(1,2); } - /* Sspec */ + // Sspec if (data & 0x10) m_samples->stop(2); else @@ -1059,122 +1730,49 @@ void exidy_state::targ_audio_1_w(uint8_t data) } } - /* Game (tone generator enable) */ - if (FALLING_EDGE(0x80)) + // Game (tone generator enable) + if (FALLING_EDGE(data, 0x80)) { - m_tone_pointer = 0; m_tone_active = 0; adjust_sample(m_tone_freq); } - if (RISING_EDGE(0x80)) - m_tone_active=1; + if (RISING_EDGE(data, 0x80)) + m_tone_active = 1; m_port_1_last = data; } -void exidy_state::targ_audio_2_w(uint8_t data) -{ - if ((data & 0x01) && !(m_port_2_last & 0x01)) - { - uint8_t *prom = memregion("targ")->base(); - - m_tone_pointer = (m_tone_pointer + 1) & 0x0f; - - adjust_sample(prom[((data & 0x02) << 3) | m_tone_pointer]); - } - - m_port_2_last = data; -} - - -void exidy_state::spectar_audio_2_w(uint8_t data) +void spectar_state::spectar_audio_2_w(uint8_t data) { adjust_sample(data); } -static const char *const sample_names[] = -{ - "*targ", - "expl", - "shot", - "sexpl", - "spslow", - "spfast", - nullptr -}; - - - -void exidy_state::common_audio_start(int freq) -{ - m_max_freq = freq; - - m_tone_freq = 0; - m_tone_active = 0; - - /* start_raw can't be called here: chan.source will be set by - samples_device::device_start and then nulled out by samples_device::device_reset - at the soft_reset stage of init_machine() and will never be set again. - Thus, I've moved it to exidy_state::adjust_sample() were it will be set after - machine initialization. */ - //m_samples->set_volume(3, 0); - //m_samples->start_raw(3, sine_wave, 32, 1000, true); - - save_item(NAME(m_port_1_last)); - save_item(NAME(m_port_2_last)); - save_item(NAME(m_tone_freq)); - save_item(NAME(m_tone_active)); -} - - -SAMPLES_START_CB_MEMBER(exidy_state::spectar_audio_start) -{ - common_audio_start(SPECTAR_MAXFREQ); -} - - -SAMPLES_START_CB_MEMBER(exidy_state::targ_audio_start) +void targ_state::targ_audio_1_w(uint8_t data) { - common_audio_start(TARG_MAXFREQ); - - m_tone_pointer = 0; + if (FALLING_EDGE(data, 0x80)) + m_tone_pointer = 0; - save_item(NAME(m_tone_pointer)); + spectar_audio_1_w(data); } -void exidy_state::spectar_audio(machine_config &config) +void targ_state::targ_audio_2_w(uint8_t data) { - SPEAKER(config, "speaker").front_center(); - - SAMPLES(config, m_samples); - m_samples->set_channels(4); - m_samples->set_samples_names(sample_names); - m_samples->set_samples_start_callback(FUNC(exidy_state::spectar_audio_start)); - m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25); - - DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.99); -} - -void exidy_state::targ_audio(machine_config &config) -{ - SPEAKER(config, "speaker").front_center(); + if ((data & 0x01) && !(m_port_2_last & 0x01)) + { + m_tone_pointer = (m_tone_pointer + 1) & 0x0f; - SAMPLES(config, m_samples); - m_samples->set_channels(4); - m_samples->set_samples_names(sample_names); - m_samples->set_samples_start_callback(FUNC(exidy_state::targ_audio_start)); - m_samples->add_route(ALL_OUTPUTS, "speaker", 0.25); + adjust_sample(m_sound_prom[((data & 0x02) << 3) | m_tone_pointer]); + } - DAC_1BIT(config, m_dac, 0).add_route(ALL_OUTPUTS, "speaker", 0.99); + m_port_2_last = data; } - /************************************* * * ROM definitions @@ -1878,94 +2476,33 @@ ROM_END * *************************************/ -void exidy_state::init_sidetrac() +void spectar_state::init_sidetrac() { - exidy_video_config(0x00, 0x00, false); - - /* hard-coded palette controlled via 8x3 DIP switches on the board */ + // hard-coded palette controlled via 8x3 DIP switches on the board m_color_latch[2] = 0xf8; m_color_latch[1] = 0xdc; m_color_latch[0] = 0xb8; } -void exidy_state::init_targ() +void targ_state::init_targ() { - exidy_video_config(0x00, 0x00, false); - - /* hard-coded palette controlled via 8x3 DIP switches on the board */ + // hard-coded palette controlled via 8x3 DIP switches on the board m_color_latch[2] = 0x5c; m_color_latch[1] = 0xee; m_color_latch[0] = 0x6b; } -void exidy_state::init_spectar() -{ - exidy_video_config(0x00, 0x00, false); - - /* hard-coded palette controlled via 8x3 DIP switches on the board */ - m_color_latch[2] = 0x58; - m_color_latch[1] = 0xee; - m_color_latch[0] = 0x09; -} - -void exidy_state::init_rallys() -{ - exidy_video_config(0x00, 0x00, false); - - /* hard-coded palette controlled via 8x3 DIP switches on the board */ - m_color_latch[2] = 0x58; - m_color_latch[1] = 0xee; - m_color_latch[0] = 0x09; -} - -void exidy_state::init_phantoma() +void spectar_state::init_spectar() { - exidy_video_config(0x00, 0x00, false); - - /* hard-coded palette controlled via 8x3 DIP switches on the board */ + // hard-coded palette controlled via 8x3 DIP switches on the board m_color_latch[2] = 0x58; m_color_latch[1] = 0xee; m_color_latch[0] = 0x09; - - /* the ROM is actually mapped high */ - m_maincpu->space(AS_PROGRAM).install_rom(0xf800, 0xffff, memregion("maincpu")->base() + 0xf800); } - -void exidy_state::init_mtrap() -{ - exidy_video_config(0x14, 0x00, false); -} - - -void exidy_state::init_venture() -{ - exidy_video_config(0x04, 0x04, false); -} - - -void exidy_state::init_teetert() -{ - exidy_video_config(0x0c, 0x0c, false); -} - - -void exidy_state::init_pepper2() -{ - exidy_video_config(0x14, 0x04, true); -} - - -void exidy_state::init_fax() -{ - //address_space &space = m_maincpu->space(AS_PROGRAM); - - exidy_video_config(0x04, 0x04, true); - - membank("bank1")->configure_entries(0, 32, memregion("maincpu")->base() + 0x10000, 0x2000); -} +} // anonymous namespace @@ -1975,38 +2512,38 @@ void exidy_state::init_fax() * *************************************/ -GAME( 1979, sidetrac, 0, sidetrac, sidetrac, exidy_state, init_sidetrac, ROT0, "Exidy", "Side Trak", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // "Side Track" on title screen, but cabinet/flyers/documentation clearly indicates otherwise, "Side Trak" it is +GAME( 1979, sidetrac, 0, sidetrac, sidetrac, spectar_state, init_sidetrac, ROT0, "Exidy", "Side Trak", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // "Side Track" on title screen, but cabinet/flyers/documentation clearly indicates otherwise, "Side Trak" it is -GAME( 1980, targ, 0, targ, targ, exidy_state, init_targ, ROT0, "Exidy", "Targ", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, targc, targ, targ, targ, exidy_state, init_targ, ROT0, "Exidy", "Targ (cocktail?)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, targ, 0, targ, targ, targ_state, init_targ, ROT0, "Exidy", "Targ", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, targc, targ, targ, targ, targ_state, init_targ, ROT0, "Exidy", "Targ (cocktail?)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, spectar, 0, spectar, spectar, exidy_state, init_spectar, ROT0, "Exidy", "Spectar (revision 3)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, spectar1, spectar, spectar, spectar, exidy_state, init_spectar, ROT0, "Exidy", "Spectar (revision 1?)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1984, spectarrf, spectar, spectar, spectarrf, exidy_state, init_spectar, ROT0, "bootleg (Recreativos Franco)", "Spectar (revision 2, bootleg)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, rallys, spectar, rallys, rallys, exidy_state, init_rallys, ROT0, "bootleg (Novar)", "Rallys (bootleg of Spectar, set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, rallysa, spectar, rallys, rallys, exidy_state, init_rallys, ROT0, "bootleg (Musik Box Brescia)", "Rallys (bootleg of Spectar, set 2)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, panzer, spectar, rallys, rallys, exidy_state, init_rallys, ROT0, "bootleg (Proel)", "Panzer (bootleg of Spectar)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, phantoma, spectar, rallys, phantoma, exidy_state, init_phantoma, ROT0, "bootleg (Jeutel)", "Phantomas (bootleg of Spectar)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1980, phantom, spectar, rallys, phantoma, exidy_state, init_phantoma, ROT0, "bootleg (Proel)", "Phantom (bootleg of Spectar)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, spectar, 0, spectar, spectar, spectar_state, init_spectar, ROT0, "Exidy", "Spectar (revision 3)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, spectar1, spectar, spectar, spectar, spectar_state, init_spectar, ROT0, "Exidy", "Spectar (revision 1?)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1984, spectarrf, spectar, spectar, spectarrf, spectar_state, init_spectar, ROT0, "bootleg (Recreativos Franco)", "Spectar (revision 2, bootleg)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, rallys, spectar, rallys, rallys, spectar_state, init_spectar, ROT0, "bootleg (Novar)", "Rallys (bootleg of Spectar, set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, rallysa, spectar, rallys, rallys, spectar_state, init_spectar, ROT0, "bootleg (Musik Box Brescia)", "Rallys (bootleg of Spectar, set 2)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, panzer, spectar, rallys, rallys, spectar_state, init_spectar, ROT0, "bootleg (Proel)", "Panzer (bootleg of Spectar)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, phantoma, spectar, phantoma, phantoma, spectar_state, init_spectar, ROT0, "bootleg (Jeutel)", "Phantomas (bootleg of Spectar)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1980, phantom, spectar, phantoma, phantoma, spectar_state, init_spectar, ROT0, "bootleg (Proel)", "Phantom (bootleg of Spectar)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1981, mtrap, 0, mtrap, mtrap, exidy_state, init_mtrap, ROT0, "Exidy", "Mouse Trap (version 5)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, mtrap4, mtrap, mtrap, mtrap, exidy_state, init_mtrap, ROT0, "Exidy", "Mouse Trap (version 4)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, mtrap3, mtrap, mtrap, mtrap, exidy_state, init_mtrap, ROT0, "Exidy", "Mouse Trap (version 3)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, mtrap2, mtrap, mtrap, mtrap, exidy_state, init_mtrap, ROT0, "Exidy", "Mouse Trap (version 2)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, mtrapb, mtrap, mtrap, mtrap, exidy_state, init_mtrap, ROT0, "bootleg", "Mouse Trap (bootleg)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, mtrapb2, mtrap, mtrap, mtrap, exidy_state, init_mtrap, ROT0, "bootleg", "Mouse Trap (version 4, bootleg)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, mtrap, 0, mtrap, mtrap, exidy_state, empty_init, ROT0, "Exidy", "Mouse Trap (version 5)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, mtrap4, mtrap, mtrap, mtrap, exidy_state, empty_init, ROT0, "Exidy", "Mouse Trap (version 4)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, mtrap3, mtrap, mtrap, mtrap, exidy_state, empty_init, ROT0, "Exidy", "Mouse Trap (version 3)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, mtrap2, mtrap, mtrap, mtrap, exidy_state, empty_init, ROT0, "Exidy", "Mouse Trap (version 2)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, mtrapb, mtrap, mtrap, mtrap, exidy_state, empty_init, ROT0, "bootleg", "Mouse Trap (bootleg)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, mtrapb2, mtrap, mtrap, mtrap, exidy_state, empty_init, ROT0, "bootleg", "Mouse Trap (version 4, bootleg)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, venture, 0, venture, venture, exidy_state, init_venture, ROT0, "Exidy", "Venture (version 5 set 1)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, venture5a, venture, venture, venture, exidy_state, init_venture, ROT0, "Exidy", "Venture (version 5 set 2)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, venture4, venture, venture, venture, exidy_state, init_venture, ROT0, "Exidy", "Venture (version 4)", MACHINE_SUPPORTS_SAVE ) -GAME( 1981, venture5b, venture, venture, venture, exidy_state, init_venture, ROT0, "bootleg", "Venture (version 5 set 2, bootleg)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, venture, 0, venture, venture, exidy_state, empty_init, ROT0, "Exidy", "Venture (version 5 set 1)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, venture5a, venture, venture, venture, exidy_state, empty_init, ROT0, "Exidy", "Venture (version 5 set 2)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, venture4, venture, venture, venture, exidy_state, empty_init, ROT0, "Exidy", "Venture (version 4)", MACHINE_SUPPORTS_SAVE ) +GAME( 1981, venture5b, venture, venture, venture, exidy_state, empty_init, ROT0, "bootleg", "Venture (version 5 set 2, bootleg)", MACHINE_SUPPORTS_SAVE ) -GAME( 1982, teetert, 0, teetert, teetert, exidy_state, init_teetert, ROT0, "Exidy", "Teeter Torture (prototype)", MACHINE_SUPPORTS_SAVE ) +GAME( 1982, teetert, 0, teetert, teetert, teetert_state, empty_init, ROT0, "Exidy", "Teeter Torture (prototype)", MACHINE_SUPPORTS_SAVE ) -GAME( 1982, pepper2, 0, pepper2, pepper2, exidy_state, init_pepper2, ROT0, "Exidy", "Pepper II (version 8)", MACHINE_SUPPORTS_SAVE ) -GAME( 1982, pepper27, pepper2, pepper2, pepper2, exidy_state, init_pepper2, ROT0, "Exidy", "Pepper II (version 7)", MACHINE_SUPPORTS_SAVE ) +GAME( 1982, pepper2, 0, pepper2, pepper2, exidy_state, empty_init, ROT0, "Exidy", "Pepper II (version 8)", MACHINE_SUPPORTS_SAVE ) +GAME( 1982, pepper27, pepper2, pepper2, pepper2, exidy_state, empty_init, ROT0, "Exidy", "Pepper II (version 7)", MACHINE_SUPPORTS_SAVE ) -GAME( 1982, hardhat, 0, pepper2, pepper2, exidy_state, init_pepper2, ROT0, "Exidy", "Hard Hat", MACHINE_SUPPORTS_SAVE ) +GAME( 1982, hardhat, 0, pepper2, pepper2, exidy_state, empty_init, ROT0, "Exidy", "Hard Hat", MACHINE_SUPPORTS_SAVE ) -GAME( 1983, fax, 0, fax, fax, exidy_state, init_fax, ROT0, "Exidy", "FAX", MACHINE_SUPPORTS_SAVE ) -GAME( 1983, fax2, fax, fax, fax, exidy_state, init_fax, ROT0, "Exidy", "FAX 2", MACHINE_SUPPORTS_SAVE ) +GAME( 1983, fax, 0, fax, fax, fax_state, empty_init, ROT0, "Exidy", "FAX", MACHINE_SUPPORTS_SAVE ) +GAME( 1983, fax2, fax, fax, fax, fax_state, empty_init, ROT0, "Exidy", "FAX 2", MACHINE_SUPPORTS_SAVE ) |