mirror of
https://github.com/holub/mame
synced 2025-04-24 17:30:55 +03:00
mcr68: Use standard 6840 PTM core
Replace custom implementation with the standard one.
This commit is contained in:
parent
23df89c965
commit
8e4f3caecc
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user