thepit.cpp: Modernizations and fixes

- Replace legacy VBLANK interrupt generators
- Derive audio CPU interrupt from VSYNC, not VBLANK
- Add multiplexer device for inputs
- Fix screen offsets for cocktail-flipped mode
This commit is contained in:
AJR 2022-05-29 17:33:49 -04:00
parent d5e717cbae
commit c3d9120c3b
4 changed files with 93 additions and 85 deletions

View File

@ -96,7 +96,7 @@ class ls157_x2_device : public ls157_device
{
public:
// construction/destruction
ls157_x2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
ls157_x2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
};
// ======================> hc157_device
@ -105,7 +105,7 @@ class hc157_device : public ls157_device
{
public:
// construction/destruction
hc157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
hc157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
};
// ======================> hct157_device
@ -114,7 +114,7 @@ class hct157_device : public ls157_device
{
public:
// construction/destruction
hct157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
hct157_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
};

View File

@ -159,14 +159,13 @@ Player 2 and Player 1 share the same controls !
#include "machine/gen_latch.h"
#include "machine/watchdog.h"
#include "sound/ay8910.h"
#include "screen.h"
#include "speaker.h"
#define MASTER_CLOCK (18432000)
#define SOUND_CLOCK (10000000)
constexpr XTAL MASTER_CLOCK = 18.432_MHz_XTAL;
constexpr XTAL SOUND_CLOCK = 10_MHz_XTAL;
#define PIXEL_CLOCK (MASTER_CLOCK/3)
constexpr XTAL PIXEL_CLOCK = MASTER_CLOCK/3;
/* H counts from 128->511, HBLANK starts at 128 and ends at 256 */
#define HTOTAL (384)
@ -204,6 +203,28 @@ WRITE_LINE_MEMBER(thepit_state::nmi_mask_w)
m_maincpu->set_input_line(INPUT_LINE_NMI, CLEAR_LINE);
}
WRITE_LINE_MEMBER(thepit_state::vblank_w)
{
if (state)
{
if (m_nmi_mask)
m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
m_vsync_timer->adjust(m_screen->time_until_pos(256, 0));
}
}
TIMER_CALLBACK_MEMBER(thepit_state::vsync_callback)
{
m_audiocpu->set_input_line(0, ASSERT_LINE);
}
IRQ_CALLBACK_MEMBER(thepit_state::vsync_int_ack)
{
m_audiocpu->set_input_line(0, CLEAR_LINE);
return 0xff;
}
void thepit_state::thepit_main_map(address_map &map)
{
@ -291,26 +312,26 @@ void thepit_state::audio_io_map(address_map &map)
static INPUT_PORTS_START( in0_real)
PORT_START("IN0")\
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static INPUT_PORTS_START( in2_fake )
PORT_START("IN2")\
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_COCKTAIL
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static INPUT_PORTS_START( thepit )
@ -597,14 +618,14 @@ INPUT_PORTS_END
static INPUT_PORTS_START( rtriv )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 )
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 )
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 )
@ -648,14 +669,14 @@ static INPUT_PORTS_START( rtriv )
/* Since the real inputs are multiplexed, we used this fake port
to read the 2nd player controls when the screen is flipped */
PORT_START("IN2")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(2)
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
@ -725,31 +746,29 @@ static GFXDECODE_START( gfx_suprmous )
GFXDECODE_END
INTERRUPT_GEN_MEMBER(thepit_state::vblank_irq)
{
if(m_nmi_mask)
device.execute().set_input_line(INPUT_LINE_NMI, ASSERT_LINE);
}
void thepit_state::thepit(machine_config &config)
{
/* basic machine hardware */
Z80(config, m_maincpu, PIXEL_CLOCK/2); /* 3.072 MHz */
m_maincpu->set_addrmap(AS_PROGRAM, &thepit_state::thepit_main_map);
m_maincpu->set_vblank_int("screen", FUNC(thepit_state::vblank_irq));
z80_device &audiocpu(Z80(config, "audiocpu", SOUND_CLOCK/4)); /* 2.5 MHz */
audiocpu.set_addrmap(AS_PROGRAM, &thepit_state::audio_map);
audiocpu.set_addrmap(AS_IO, &thepit_state::audio_io_map);
audiocpu.set_vblank_int("screen", FUNC(thepit_state::irq0_line_hold));
Z80(config, m_audiocpu, SOUND_CLOCK/4); /* 2.5 MHz */
m_audiocpu->set_addrmap(AS_PROGRAM, &thepit_state::audio_map);
m_audiocpu->set_addrmap(AS_IO, &thepit_state::audio_io_map);
m_audiocpu->set_irq_acknowledge_callback(FUNC(thepit_state::vsync_int_ack));
LS259(config, m_mainlatch); // IC42
m_mainlatch->q_out_cb<0>().set(FUNC(thepit_state::nmi_mask_w));
m_mainlatch->q_out_cb<2>().set_nop(); // marked "LOCK OUT" on Centuri schematic but never written
m_mainlatch->q_out_cb<3>().set(FUNC(thepit_state::sound_enable_w));
m_mainlatch->q_out_cb<6>().set(FUNC(thepit_state::flip_screen_x_w));
m_mainlatch->q_out_cb<6>().append(m_inputmux, FUNC(ls157_x2_device::select_w));
m_mainlatch->q_out_cb<7>().set(FUNC(thepit_state::flip_screen_y_w));
LS157_X2(config, m_inputmux); // IC5 (0-3) & IC6 (4-7)
m_inputmux->a_in_callback().set_ioport("IN0");
m_inputmux->b_in_callback().set_ioport("IN2");
WATCHDOG_TIMER(config, "watchdog");
/* video hardware */
@ -760,6 +779,7 @@ void thepit_state::thepit(machine_config &config)
screen.set_raw(PIXEL_CLOCK, HTOTAL, HBEND, HBSTART, VTOTAL, VBEND, VBSTART);
screen.set_screen_update(FUNC(thepit_state::screen_update));
screen.set_palette(m_palette);
screen.screen_vblank().set(FUNC(thepit_state::vblank_w));
/* sound hardware */
SPEAKER(config, "mono").front_center();

View File

@ -5,8 +5,10 @@
#pragma once
#include "machine/74157.h"
#include "machine/74259.h"
#include "emupal.h"
#include "screen.h"
#include "tilemap.h"
class thepit_state : public driver_device
@ -15,9 +17,12 @@ public:
thepit_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_audiocpu(*this, "audiocpu"),
m_mainlatch(*this, "mainlatch"),
m_inputmux(*this, "inputmux"),
m_gfxdecode(*this, "gfxdecode"),
m_palette(*this, "palette"),
m_screen(*this, "screen"),
m_videoram(*this, "videoram"),
m_colorram(*this, "colorram"),
m_attributesram(*this, "attributesram"),
@ -40,9 +45,12 @@ protected:
private:
required_device<cpu_device> m_maincpu;
required_device<cpu_device> m_audiocpu;
required_device<ls259_device> m_mainlatch;
required_device<ls157_device> m_inputmux;
required_device<gfxdecode_device> m_gfxdecode;
required_device<palette_device> m_palette;
required_device<screen_device> m_screen;
required_shared_ptr<uint8_t> m_videoram;
required_shared_ptr<uint8_t> m_colorram;
@ -56,6 +64,7 @@ private:
tilemap_t *m_tilemap = nullptr;
std::unique_ptr<uint8_t[]> m_dummy_tile;
uint8_t m_nmi_mask = 0;
emu_timer *m_vsync_timer = nullptr;
int m_question_address = 0;
int m_question_rom = 0;
@ -64,6 +73,9 @@ private:
DECLARE_WRITE_LINE_MEMBER(coin_lockout_w);
DECLARE_WRITE_LINE_MEMBER(sound_enable_w);
DECLARE_WRITE_LINE_MEMBER(nmi_mask_w);
DECLARE_WRITE_LINE_MEMBER(vblank_w);
TIMER_CALLBACK_MEMBER(vsync_callback);
IRQ_CALLBACK_MEMBER(vsync_int_ack);
void videoram_w(offs_t offset, uint8_t data);
void colorram_w(offs_t offset, uint8_t data);
DECLARE_WRITE_LINE_MEMBER(flip_screen_x_w);
@ -85,8 +97,6 @@ private:
uint32_t screen_update_desertdan(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int priority_to_draw);
INTERRUPT_GEN_MEMBER(vblank_irq);
void audio_io_map(address_map &map);
void audio_map(address_map &map);
void desertdan_main_map(address_map &map);

View File

@ -137,6 +137,8 @@ void thepit_state::video_start()
m_graphics_bank = 0; /* only used in intrepid */
m_vsync_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(thepit_state::vsync_callback), this));
save_item(NAME(m_graphics_bank));
save_item(NAME(m_flip_x));
save_item(NAME(m_flip_y));
@ -171,11 +173,10 @@ WRITE_LINE_MEMBER(thepit_state::flip_screen_x_w)
int flip = m_flip_x ? TILEMAP_FLIPX : 0;
if (m_flip_y)
flip |= TILEMAP_FLIPY ;
flip |= TILEMAP_FLIPY;
m_tilemap->set_flip(flip);
m_solid_tilemap->set_flip(flip);
}
@ -185,11 +186,10 @@ WRITE_LINE_MEMBER(thepit_state::flip_screen_y_w)
int flip = m_flip_x ? TILEMAP_FLIPX : 0;
if (m_flip_y)
flip |= TILEMAP_FLIPY ;
flip |= TILEMAP_FLIPY;
m_tilemap->set_flip(flip);
m_solid_tilemap->set_flip(flip);
}
@ -205,14 +205,7 @@ uint8_t thepit_state::input_port_0_r()
{
/* Read either the real or the fake input ports depending on the
horizontal flip switch. (This is how the real PCB does it) */
if (m_flip_x)
{
return ioport("IN2")->read();
}
else
{
return ioport("IN0")->read();
}
return ~m_inputmux->output_r();
}
@ -279,18 +272,10 @@ uint32_t thepit_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap
const rectangle spritevisiblearea(2*8+1, 32*8-1, 2*8, 30*8-1);
const rectangle spritevisibleareaflipx(0*8, 30*8-2, 2*8, 30*8-1);
offs_t offs;
for (offs = 0; offs < 32; offs++)
for (int offs = 0; offs < 32; offs++)
{
int xshift = m_flip_x ? 128 : 0;
int yshift = m_flip_y ? -8 : 0;
m_tilemap->set_scrollx(offs, xshift);
m_solid_tilemap->set_scrollx(offs, xshift);
m_tilemap->set_scrolly(offs, yshift + m_attributesram[offs << 1]);
m_solid_tilemap->set_scrolly(offs, yshift + m_attributesram[offs << 1]);
m_tilemap->set_scrolly(offs, m_attributesram[offs << 1]);
m_solid_tilemap->set_scrolly(offs, m_attributesram[offs << 1]);
}
/* low priority tiles */
@ -311,20 +296,13 @@ uint32_t thepit_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap
uint32_t thepit_state::screen_update_desertdan(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
offs_t offs;
const rectangle spritevisiblearea(0*8+1, 24*8-1, 2*8, 30*8-1);
const rectangle spritevisibleareaflipx(8*8, 32*8-2, 2*8, 30*8-1);
for (offs = 0; offs < 32; offs++)
for (int offs = 0; offs < 32; offs++)
{
int xshift = m_flip_x ? 128 : 0;
int yshift = m_flip_y ? -8 : 0;
m_tilemap->set_scrollx(offs, xshift);
m_solid_tilemap->set_scrollx(offs, xshift);
m_tilemap->set_scrolly(offs, yshift + m_attributesram[offs << 1]);
m_solid_tilemap->set_scrolly(offs, yshift + m_attributesram[offs << 1]);
m_tilemap->set_scrolly(offs, m_attributesram[offs << 1]);
m_solid_tilemap->set_scrolly(offs, m_attributesram[offs << 1]);
}
/* low priority tiles */