mcr68: Use standard 6840 PTM core

Replace custom implementation with the standard one.
This commit is contained in:
Dirk Best 2016-12-15 03:34:34 +01:00
parent 23df89c965
commit 8e4f3caecc
3 changed files with 30 additions and 393 deletions

View File

@ -88,7 +88,7 @@ READ16_MEMBER(mcr68_state::zwackery_6840_r)
/* make this happen, we must assume that reads from the */
/* 6840 take 14 additional cycles */
space.device().execute().adjust_icount(-14);
return mcr68_6840_upper_r(space,offset,0xffff);
return m_ptm->read(space, offset) << 8 | 0x00ff;
}
@ -308,7 +308,7 @@ static ADDRESS_MAP_START( mcr68_map, AS_PROGRAM, 16, mcr68_state )
AM_RANGE(0x071000, 0x071fff) AM_RAM
AM_RANGE(0x080000, 0x080fff) AM_RAM AM_SHARE("spriteram")
AM_RANGE(0x090000, 0x09007f) AM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
AM_RANGE(0x0a0000, 0x0a000f) AM_READWRITE(mcr68_6840_upper_r, mcr68_6840_upper_w)
AM_RANGE(0x0a0000, 0x0a000f) AM_DEVREADWRITE8("ptm", ptm6840_device, read, write, 0xff00)
AM_RANGE(0x0b0000, 0x0bffff) AM_DEVWRITE("watchdog", watchdog_timer_device, reset16_w)
AM_RANGE(0x0d0000, 0x0dffff) AM_READ_PORT("IN0")
AM_RANGE(0x0e0000, 0x0effff) AM_READ_PORT("IN1")
@ -328,7 +328,7 @@ static ADDRESS_MAP_START( zwackery_map, AS_PROGRAM, 16, mcr68_state )
AM_RANGE(0x000000, 0x037fff) AM_ROM
AM_RANGE(0x080000, 0x080fff) AM_RAM
AM_RANGE(0x084000, 0x084fff) AM_RAM
AM_RANGE(0x100000, 0x10000f) AM_READ(zwackery_6840_r) AM_WRITE(mcr68_6840_upper_w)
AM_RANGE(0x100000, 0x10000f) AM_READ(zwackery_6840_r) AM_DEVWRITE8("ptm", ptm6840_device, write, 0xff00)
AM_RANGE(0x104000, 0x104007) AM_DEVREADWRITE8("pia0", pia6821_device, read, write, 0xff00)
AM_RANGE(0x108000, 0x108007) AM_DEVREADWRITE8("pia1", pia6821_device, read, write, 0x00ff)
AM_RANGE(0x10c000, 0x10c007) AM_DEVREADWRITE8("pia2", pia6821_device, read, write, 0x00ff)
@ -357,7 +357,7 @@ static ADDRESS_MAP_START( pigskin_map, AS_PROGRAM, 16, mcr68_state )
AM_RANGE(0x120000, 0x120001) AM_READWRITE(pigskin_protection_r, pigskin_protection_w)
AM_RANGE(0x140000, 0x143fff) AM_RAM
AM_RANGE(0x160000, 0x1607ff) AM_RAM AM_SHARE("spriteram")
AM_RANGE(0x180000, 0x18000f) AM_READWRITE(mcr68_6840_upper_r, mcr68_6840_upper_w)
AM_RANGE(0x180000, 0x18000f) AM_DEVREADWRITE8("ptm", ptm6840_device, read, write, 0xff00)
AM_RANGE(0x1a0000, 0x1affff) AM_WRITE(archrivl_control_w)
AM_RANGE(0x1e0000, 0x1effff) AM_READ_PORT("IN0")
ADDRESS_MAP_END
@ -380,7 +380,7 @@ static ADDRESS_MAP_START( trisport_map, AS_PROGRAM, 16, mcr68_state )
AM_RANGE(0x120000, 0x12007f) AM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette")
AM_RANGE(0x140000, 0x1407ff) AM_RAM AM_SHARE("spriteram")
AM_RANGE(0x160000, 0x160fff) AM_RAM_WRITE(mcr68_videoram_w) AM_SHARE("videoram")
AM_RANGE(0x180000, 0x18000f) AM_READWRITE(mcr68_6840_upper_r, mcr68_6840_upper_w)
AM_RANGE(0x180000, 0x18000f) AM_DEVREADWRITE8("ptm", ptm6840_device, read, write, 0xff00)
AM_RANGE(0x1a0000, 0x1affff) AM_WRITE(archrivl_control_w)
AM_RANGE(0x1c0000, 0x1cffff) AM_DEVWRITE("watchdog", watchdog_timer_device, reset16_w)
AM_RANGE(0x1e0000, 0x1effff) AM_READ_PORT("IN0")
@ -1027,6 +1027,10 @@ static MACHINE_CONFIG_START( zwackery, mcr68_state )
MCFG_MACHINE_START_OVERRIDE(mcr68_state,zwackery)
MCFG_MACHINE_RESET_OVERRIDE(mcr68_state,zwackery)
MCFG_DEVICE_ADD("ptm", PTM6840, 7652400 / 10)
MCFG_PTM6840_EXTERNAL_CLOCKS(30, 0, 512*30)
MCFG_PTM6840_IRQ_CB(WRITELINE(mcr68_state, ptm_irq_w))
MCFG_DEVICE_ADD("pia0", PIA6821, 0)
MCFG_PIA_READPB_HANDLER(IOPORT("IN0"))
MCFG_PIA_WRITEPA_HANDLER(WRITE8(mcr68_state, zwackery_pia0_w))
@ -1077,6 +1081,10 @@ static MACHINE_CONFIG_START( mcr68, mcr68_state )
MCFG_MACHINE_START_OVERRIDE(mcr68_state,mcr68)
MCFG_MACHINE_RESET_OVERRIDE(mcr68_state,mcr68)
MCFG_DEVICE_ADD("ptm", PTM6840, 7723800 / 10)
MCFG_PTM6840_EXTERNAL_CLOCKS(30, 0, 512*30)
MCFG_PTM6840_IRQ_CB(WRITELINE(mcr68_state, ptm_irq_w))
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(30)
@ -1748,7 +1756,7 @@ DRIVER_INIT_MEMBER(mcr68_state,blasted)
m_maincpu->space(AS_PROGRAM).install_write_handler(0x0c0000, 0x0cffff, write16_delegate(FUNC(mcr68_state::blasted_control_w),this));
/* 6840 is mapped to the lower 8 bits */
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read16_delegate(FUNC(mcr68_state::mcr68_6840_lower_r),this), write16_delegate(FUNC(mcr68_state::mcr68_6840_lower_w),this));
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read8_delegate(FUNC(ptm6840_device::read), &(*m_ptm)), write8_delegate(FUNC(ptm6840_device::write), &(*m_ptm)), 0x00ff);
}
DRIVER_INIT_MEMBER(mcr68_state,intlaser)
@ -1779,7 +1787,7 @@ DRIVER_INIT_MEMBER(mcr68_state,archrivl)
m_maincpu->space(AS_PROGRAM).install_read_handler(0x0e0000, 0x0effff, read16_delegate(FUNC(mcr68_state::archrivl_port_1_r),this));
/* 6840 is mapped to the lower 8 bits */
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read16_delegate(FUNC(mcr68_state::mcr68_6840_lower_r),this), write16_delegate(FUNC(mcr68_state::mcr68_6840_lower_w),this));
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read8_delegate(FUNC(ptm6840_device::read), &(*m_ptm)), write8_delegate(FUNC(ptm6840_device::write), &(*m_ptm)), 0x00ff);
}
READ16_MEMBER(mcr68_state::archrivlb_port_1_r)
@ -1801,7 +1809,7 @@ DRIVER_INIT_MEMBER(mcr68_state,archrivlb)
m_maincpu->space(AS_PROGRAM).install_read_handler(0x0e0000, 0x0effff, read16_delegate(FUNC(mcr68_state::archrivlb_port_1_r),this));
/* 6840 is mapped to the lower 8 bits */
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read16_delegate(FUNC(mcr68_state::mcr68_6840_lower_r),this), write16_delegate(FUNC(mcr68_state::mcr68_6840_lower_w),this));
m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x0a0000, 0x0a000f, read8_delegate(FUNC(ptm6840_device::read), &(*m_ptm)), write8_delegate(FUNC(ptm6840_device::write), &(*m_ptm)), 0x00ff);
}

View File

@ -10,16 +10,7 @@
#include "machine/watchdog.h"
#include "audio/midway.h"
#include "audio/williams.h"
struct counter_state
{
uint8_t control;
uint16_t latch;
uint16_t count;
emu_timer * timer;
uint8_t timer_active;
attotime period;
};
#include "machine/6840ptm.h"
class mcr68_state : public driver_device
{
@ -36,7 +27,8 @@ public:
m_watchdog(*this, "watchdog"),
m_gfxdecode(*this, "gfxdecode"),
m_screen(*this, "screen"),
m_palette(*this, "palette")
m_palette(*this, "palette"),
m_ptm(*this, "ptm")
{ }
optional_device<midway_chip_squeak_deluxe_device> m_chip_squeak_deluxe;
@ -51,19 +43,12 @@ public:
attotime m_timing_factor;
uint8_t m_sprite_clip;
int8_t m_sprite_xoffset;
uint8_t m_m6840_status;
uint8_t m_m6840_status_read_since_int;
uint8_t m_m6840_msb_buffer;
uint8_t m_m6840_lsb_buffer;
uint8_t m_m6840_irq_state;
uint8_t m_m6840_irq_vector;
struct counter_state m_m6840_state[3];
uint8_t m_v493_irq_state;
uint8_t m_v493_irq_vector;
timer_expired_delegate m_v493_callback;
uint8_t m_zwackery_sound_data;
attotime m_m6840_counter_periods[3];
attotime m_m6840_internal_counter_period;
tilemap_t *m_bg_tilemap;
tilemap_t *m_fg_tilemap;
DECLARE_READ16_MEMBER(zwackery_6840_r);
@ -79,14 +64,7 @@ public:
DECLARE_READ16_MEMBER(pigskin_port_1_r);
DECLARE_READ16_MEMBER(pigskin_port_2_r);
DECLARE_READ16_MEMBER(trisport_port_1_r);
DECLARE_WRITE16_MEMBER(mcr68_6840_upper_w);
DECLARE_WRITE16_MEMBER(mcr68_6840_lower_w);
DECLARE_READ16_MEMBER(mcr68_6840_upper_r);
DECLARE_READ16_MEMBER(mcr68_6840_lower_r);
DECLARE_WRITE8_MEMBER(mcr68_6840_w_common);
DECLARE_READ16_MEMBER(mcr68_6840_r_common);
void reload_count(int counter);
uint16_t compute_counter(int counter);
DECLARE_WRITE_LINE_MEMBER(ptm_irq_w);
DECLARE_WRITE16_MEMBER(mcr68_videoram_w);
DECLARE_WRITE16_MEMBER(zwackery_videoram_w);
DECLARE_WRITE16_MEMBER(zwackery_spriteram_w);
@ -126,7 +104,6 @@ public:
DECLARE_WRITE_LINE_MEMBER(zwackery_pia_irq);
void mcr68_update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
void zwackery_update_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int priority);
void mcr68_common_init();
void update_mcr68_interrupts();
inline void update_interrupts();
void subtract_from_counter(int counter, int count);
@ -138,4 +115,7 @@ public:
required_device<palette_device> m_palette;
std::unique_ptr<uint8_t[]> m_srcdata0;
std::unique_ptr<uint8_t[]> m_srcdata2;
private:
required_device<ptm6840_device> m_ptm;
};

View File

@ -11,7 +11,7 @@
#include "includes/mcr68.h"
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/*************************************
*
@ -48,59 +48,14 @@ READ8_MEMBER(mcr68_state::zwackery_port_3_r)
MACHINE_START_MEMBER(mcr68_state,mcr68)
{
for (int i = 0; i < 3; i++)
{
struct counter_state *m6840 = &m_m6840_state[i];
m6840->timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mcr68_state::counter_fired_callback),this));
save_item(m6840->control, "m6840/control", i);
save_item(m6840->latch, "m6840/latch", i);
save_item(m6840->count, "m6840/count", i);
save_item(m6840->timer_active, "m6840/timer_active", i);
}
save_item(NAME(m_m6840_status));
save_item(NAME(m_m6840_status_read_since_int));
save_item(NAME(m_m6840_msb_buffer));
save_item(NAME(m_m6840_lsb_buffer));
save_item(NAME(m_m6840_irq_state));
save_item(NAME(m_v493_irq_state));
save_item(NAME(m_zwackery_sound_data));
}
void mcr68_state::mcr68_common_init()
{
/* reset the 6840's */
m_m6840_counter_periods[0] = attotime::from_hz(30); /* clocked by /VBLANK */
m_m6840_counter_periods[1] = attotime::never; /* grounded */
m_m6840_counter_periods[2] = attotime::from_hz(512 * 30); /* clocked by /HSYNC */
m_m6840_status = 0x00;
m_m6840_status_read_since_int = 0x00;
m_m6840_msb_buffer = m_m6840_lsb_buffer = 0;
for (int i = 0; i < 3; i++)
{
struct counter_state *m6840 = &m_m6840_state[i];
m6840->control = 0x00;
m6840->latch = 0xffff;
m6840->count = 0xffff;
m6840->timer->enable(false);
m6840->timer_active = 0;
m6840->period = m_m6840_counter_periods[i];
}
/* initialize the clock */
m_m6840_internal_counter_period = attotime::from_hz(m_maincpu->unscaled_clock() / 10);
}
MACHINE_RESET_MEMBER(mcr68_state,mcr68)
{
/* for the most part all MCR/68k games are the same */
mcr68_common_init();
m_v493_callback = timer_expired_delegate(FUNC(mcr68_state::mcr68_493_callback),this);
/* vectors are 1 and 2 */
@ -118,7 +73,6 @@ MACHINE_START_MEMBER(mcr68_state,zwackery)
MACHINE_RESET_MEMBER(mcr68_state,zwackery)
{
/* for the most part all MCR/68k games are the same */
mcr68_common_init();
m_v493_callback = timer_expired_delegate(FUNC(mcr68_state::zwackery_493_callback),this);
/* vectors are 5 and 6 */
@ -136,10 +90,6 @@ MACHINE_RESET_MEMBER(mcr68_state,zwackery)
INTERRUPT_GEN_MEMBER(mcr68_state::mcr68_interrupt)
{
/* update the 6840 VBLANK clock */
if (!m_m6840_state[0].timer_active)
subtract_from_counter(0, 1);
logerror("--- VBLANK ---\n");
/* also set a timer to generate the 493 signal at a specific time before the next VBLANK */
@ -179,6 +129,12 @@ TIMER_CALLBACK_MEMBER(mcr68_state::mcr68_493_callback)
}
WRITE_LINE_MEMBER( mcr68_state::ptm_irq_w )
{
m_m6840_irq_state = state;
update_mcr68_interrupts();
}
/*************************************
*
@ -232,310 +188,3 @@ TIMER_CALLBACK_MEMBER(mcr68_state::zwackery_493_callback)
pia->ca1_w(1);
machine().scheduler().timer_set(m_screen->scan_period(), timer_expired_delegate(FUNC(mcr68_state::zwackery_493_off_callback),this));
}
/*************************************
*
* M6840 timer utilities
*
*************************************/
inline void mcr68_state::update_interrupts()
{
m_m6840_status &= ~0x80;
if ((m_m6840_status & 0x01) && (m_m6840_state[0].control & 0x40)) m_m6840_status |= 0x80;
if ((m_m6840_status & 0x02) && (m_m6840_state[1].control & 0x40)) m_m6840_status |= 0x80;
if ((m_m6840_status & 0x04) && (m_m6840_state[2].control & 0x40)) m_m6840_status |= 0x80;
m_m6840_irq_state = m_m6840_status >> 7;
update_mcr68_interrupts();
}
void mcr68_state::subtract_from_counter(int counter, int count)
{
struct counter_state *m6840 = &m_m6840_state[counter];
/* dual-byte mode */
if (m6840->control & 0x04)
{
int lsb = m6840->count & 0xff;
int msb = m6840->count >> 8;
/* count the clocks */
lsb -= count;
/* loop while we're less than zero */
while (lsb < 0)
{
/* borrow from the MSB */
lsb += (m6840->latch & 0xff) + 1;
msb--;
/* if MSB goes less than zero, we've expired */
if (msb < 0)
{
m_m6840_status |= 1 << counter;
m_m6840_status_read_since_int &= ~(1 << counter);
update_interrupts();
msb = (m6840->latch >> 8) + 1;
LOG(("** Counter %d fired\n", counter));
}
}
/* store the result */
m6840->count = (msb << 8) | lsb;
}
/* word mode */
else
{
int word = m6840->count;
/* count the clocks */
word -= count;
/* loop while we're less than zero */
while (word < 0)
{
/* borrow from the MSB */
word += m6840->latch + 1;
/* we've expired */
m_m6840_status |= 1 << counter;
m_m6840_status_read_since_int &= ~(1 << counter);
update_interrupts();
LOG(("** Counter %d fired\n", counter));
}
/* store the result */
m6840->count = word;
}
}
TIMER_CALLBACK_MEMBER(mcr68_state::counter_fired_callback)
{
int count = param >> 2;
int counter = param & 3;
struct counter_state *m6840 = &m_m6840_state[counter];
/* reset the timer */
m6840->timer_active = 0;
/* subtract it all from the counter; this will generate an interrupt */
subtract_from_counter(counter, count);
}
void mcr68_state::reload_count(int counter)
{
struct counter_state *m6840 = &m_m6840_state[counter];
attotime period;
attotime total_period;
int count;
/* copy the latched value in */
m6840->count = m6840->latch;
/* counter 0 is self-updating if clocked externally */
if (counter == 0 && !(m6840->control & 0x02))
{
m6840->timer->adjust(attotime::never);
m6840->timer_active = 0;
return;
}
/* determine the clock period for this timer */
if (m6840->control & 0x02)
period = m_m6840_internal_counter_period;
else
period = m_m6840_counter_periods[counter];
/* determine the number of clock periods before we expire */
count = m6840->count;
if (m6840->control & 0x04)
count = ((count >> 8) + 1) * ((count & 0xff) + 1);
else
count = count + 1;
/* set the timer */
total_period = period * count;
LOG(("reload_count(%d): period = %f count = %d\n", counter, period.as_double(), count));
m6840->timer->adjust(total_period, (count << 2) + counter);
m6840->timer_active = 1;
}
uint16_t mcr68_state::compute_counter(int counter)
{
struct counter_state *m6840 = &m_m6840_state[counter];
attotime period;
int remaining;
/* if there's no timer, return the count */
if (!m6840->timer_active)
return m6840->count;
/* determine the clock period for this timer */
if (m6840->control & 0x02)
period = m_m6840_internal_counter_period;
else
period = m_m6840_counter_periods[counter];
/* see how many are left */
remaining = m6840->timer->remaining().as_attoseconds() / period.as_attoseconds();
/* adjust the count for dual byte mode */
if (m6840->control & 0x04)
{
int divisor = (m6840->count & 0xff) + 1;
int msb = remaining / divisor;
int lsb = remaining % divisor;
remaining = (msb << 8) | lsb;
}
return remaining;
}
/*************************************
*
* M6840 timer I/O
*
*************************************/
WRITE8_MEMBER(mcr68_state::mcr68_6840_w_common)
{
int i;
/* offsets 0 and 1 are control registers */
if (offset < 2)
{
int counter = (offset == 1) ? 1 : (m_m6840_state[1].control & 0x01) ? 0 : 2;
struct counter_state *m6840 = &m_m6840_state[counter];
uint8_t diffs = data ^ m6840->control;
m6840->control = data;
/* reset? */
if (counter == 0 && (diffs & 0x01))
{
/* holding reset down */
if (data & 0x01)
{
for (i = 0; i < 3; i++)
{
m_m6840_state[i].timer->adjust(attotime::never);
m_m6840_state[i].timer_active = 0;
}
}
/* releasing reset */
else
{
for (i = 0; i < 3; i++)
reload_count(i);
}
m_m6840_status = 0;
update_interrupts();
}
/* changing the clock source? (needed for Zwackery) */
if (diffs & 0x02)
reload_count(counter);
LOG(("%06X:Counter %d control = %02X\n", space.device().safe_pcbase(), counter, data));
}
/* offsets 2, 4, and 6 are MSB buffer registers */
else if ((offset & 1) == 0)
{
LOG(("%06X:MSB = %02X\n", space.device().safe_pcbase(), data));
m_m6840_msb_buffer = data;
}
/* offsets 3, 5, and 7 are Write Timer Latch commands */
else
{
int counter = (offset - 2) / 2;
struct counter_state *m6840 = &m_m6840_state[counter];
m6840->latch = (m_m6840_msb_buffer << 8) | (data & 0xff);
/* clear the interrupt */
m_m6840_status &= ~(1 << counter);
update_interrupts();
/* reload the count if in an appropriate mode */
if (!(m6840->control & 0x10))
reload_count(counter);
LOG(("%06X:Counter %d latch = %04X\n", space.device().safe_pcbase(), counter, m6840->latch));
}
}
READ16_MEMBER(mcr68_state::mcr68_6840_r_common)
{
/* offset 0 is a no-op */
if (offset == 0)
return 0;
/* offset 1 is the status register */
else if (offset == 1)
{
LOG(("%06X:Status read = %04X\n", space.device().safe_pcbase(), m_m6840_status));
m_m6840_status_read_since_int |= m_m6840_status & 0x07;
return m_m6840_status;
}
/* offsets 2, 4, and 6 are Read Timer Counter commands */
else if ((offset & 1) == 0)
{
int counter = (offset - 2) / 2;
int result = compute_counter(counter);
/* clear the interrupt if the status has been read */
if (m_m6840_status_read_since_int & (1 << counter))
m_m6840_status &= ~(1 << counter);
update_interrupts();
m_m6840_lsb_buffer = result & 0xff;
LOG(("%06X:Counter %d read = %04X\n", space.device().safe_pcbase(), counter, result));
return result >> 8;
}
/* offsets 3, 5, and 7 are LSB buffer registers */
else
return m_m6840_lsb_buffer;
}
WRITE16_MEMBER(mcr68_state::mcr68_6840_upper_w)
{
if (ACCESSING_BITS_8_15)
mcr68_6840_w_common(space, offset, (data >> 8) & 0xff);
}
WRITE16_MEMBER(mcr68_state::mcr68_6840_lower_w)
{
if (ACCESSING_BITS_0_7)
mcr68_6840_w_common(space, offset, data & 0xff);
}
READ16_MEMBER(mcr68_state::mcr68_6840_upper_r)
{
return (mcr68_6840_r_common(space,offset,0) << 8) | 0x00ff;
}
READ16_MEMBER(mcr68_state::mcr68_6840_lower_r)
{
return mcr68_6840_r_common(space,offset,0) | 0xff00;
}