The great CoCo/Dragon clock correction (nw)

- Replace fake XTAL values with actual ones
- Correct SAM and GIME clocks
- Make sam6883_friend_device a subclass of device_interface
- Remove legacy 6809E device from MAME
This commit is contained in:
AJR 2017-12-28 21:21:03 -05:00
parent 056dbde538
commit 9f1fd2676e
16 changed files with 60 additions and 68 deletions

View File

@ -153,7 +153,7 @@ DEFINE_DEVICE_TYPE(COCOSSC_SAC, cocossc_sac_device, "cocossc_sac", "CoCo SSC Sou
//**************************************************************************
MACHINE_CONFIG_MEMBER(coco_ssc_device::device_add_mconfig)
MCFG_CPU_ADD(PIC_TAG, TMS7040, DERIVED_CLOCK(1, 2))
MCFG_CPU_ADD(PIC_TAG, TMS7040, DERIVED_CLOCK(2, 1))
MCFG_TMS7000_IN_PORTA_CB(READ8(coco_ssc_device, ssc_port_a_r))
MCFG_TMS7000_OUT_PORTB_CB(WRITE8(coco_ssc_device, ssc_port_b_w))
MCFG_TMS7000_IN_PORTC_CB(READ8(coco_ssc_device, ssc_port_c_r))
@ -171,11 +171,11 @@ MACHINE_CONFIG_MEMBER(coco_ssc_device::device_add_mconfig)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "ssc_audio", SP0256_GAIN)
MCFG_SP0256_DATA_REQUEST_CB(INPUTLINE(PIC_TAG, TMS7000_INT1_LINE))
MCFG_SOUND_ADD(AY_TAG, AY8913, DERIVED_CLOCK(1, 2))
MCFG_SOUND_ADD(AY_TAG, AY8913, DERIVED_CLOCK(2, 1))
MCFG_AY8910_OUTPUT_TYPE(AY8910_SINGLE_OUTPUT)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "coco_sac_tag", AY8913_GAIN)
MCFG_DEVICE_ADD("coco_sac_tag", COCOSSC_SAC, DERIVED_CLOCK(1, 2))
MCFG_DEVICE_ADD("coco_sac_tag", COCOSSC_SAC, DERIVED_CLOCK(2, 1))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "ssc_audio", 1.0)
MACHINE_CONFIG_END

View File

@ -249,7 +249,7 @@ void cococart_slot_device::set_line_timer(coco_cartridge_line &line, cococart_sl
{
// calculate delay; delay dependant on cycles per second
attotime delay = (line.delay != 0)
? machine().firstcpu->cycles_to_attotime(line.delay)
? clocks_to_attotime(line.delay)
: attotime::zero;
line.timer[line.timer_index]->adjust(delay, (int) value);

View File

@ -82,7 +82,7 @@ uint8_t* dragon_jcbsnd_device::get_cart_base()
MACHINE_CONFIG_MEMBER( dragon_jcbsnd_device::device_add_mconfig )
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("ay8910", AY8910, DERIVED_CLOCK(1, 4)) /* AY-3-8910 - clock not verified */
MCFG_SOUND_ADD("ay8910", AY8910, DERIVED_CLOCK(1, 1)) /* AY-3-8910 - clock not verified */
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MACHINE_CONFIG_END

View File

@ -131,7 +131,6 @@ March 2013 NPW:
DEFINE_DEVICE_TYPE(MC6809, mc6809_device, "mc6809", "MC6809")
DEFINE_DEVICE_TYPE(MC6809E, mc6809e_device, "mc6809e", "MC6809E")
DEFINE_DEVICE_TYPE(M6809, m6809_device, "m6809", "MC6809 (legacy)")
DEFINE_DEVICE_TYPE(M6809E, m6809e_device, "m6809e", "MC6809E (legacy)")
//-------------------------------------------------
@ -633,14 +632,3 @@ m6809_device::m6809_device(const machine_config &mconfig, const char *tag, devic
: m6809_base_device(mconfig, tag, owner, clock, M6809, 1)
{
}
//-------------------------------------------------
// m6809e_device
//-------------------------------------------------
m6809e_device::m6809e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: m6809_base_device(mconfig, tag, owner, clock, M6809E, 4)
{
}

View File

@ -22,7 +22,6 @@
DECLARE_DEVICE_TYPE(MC6809, mc6809_device)
DECLARE_DEVICE_TYPE(MC6809E, mc6809e_device)
DECLARE_DEVICE_TYPE(M6809, m6809_device)
DECLARE_DEVICE_TYPE(M6809E, m6809e_device)
// ======================> m6809_base_device
@ -329,15 +328,6 @@ public:
m6809_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
// ======================> m6809e_device (LEGACY)
class m6809e_device : public m6809_base_device
{
public:
// construction/destruction
m6809e_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
enum
{
M6809_PC = STATE_GENPC, M6809_S = 0, M6809_CC ,M6809_A, M6809_B, M6809_D, M6809_U, M6809_X, M6809_Y,

View File

@ -130,13 +130,14 @@ const uint32_t mc6847_base_device::s_palette[mc6847_base_device::PALETTE_LENGTH]
//-------------------------------------------------
mc6847_friend_device::mc6847_friend_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock,
const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines)
const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, int divider, bool supports_partial_body_scanlines)
: device_t(mconfig, type, tag, owner, clock)
, m_write_hsync(*this)
, m_write_fsync(*this)
, m_character_map(fontdata, is_mc6847t1)
{
m_tpfs = tpfs;
m_divider = divider;
m_supports_partial_body_scanlines = supports_partial_body_scanlines;
// The MC6847 and the GIME apply field sync on different scanlines
@ -154,9 +155,9 @@ inline emu_timer *mc6847_friend_device::setup_timer(device_timer_id id, double o
{
emu_timer *timer = timer_alloc(id);
timer->adjust(
attotime::from_ticks(offset * 4, m_clock * 4),
clocks_to_attotime(offset * m_divider),
0,
attotime::from_ticks(period * 4, m_clock * 4));
clocks_to_attotime(period * m_divider));
return timer;
}
@ -238,7 +239,7 @@ void mc6847_friend_device::update_field_sync_timer()
if (expected_field_sync != m_field_sync)
{
// if so, determine the duration
attotime duration = attotime::from_ticks(160, m_clock);
attotime duration = clocks_to_attotime(160 * m_divider);
// and reset the timer
m_fsync_timer->adjust(duration, expected_field_sync ? 1 : 0);
@ -486,8 +487,8 @@ void mc6847_friend_device::record_border_scanline(uint16_t physical_scanline)
int32_t mc6847_friend_device::get_clocks_since_hsync()
{
uint64_t hsync_on_clocks = attotime_to_clocks(m_hsync_on_timer->start());
uint64_t current_clocks = attotime_to_clocks(machine().time());
uint64_t hsync_on_clocks = attotime_to_clocks(m_hsync_on_timer->start()) / m_divider;
uint64_t current_clocks = attotime_to_clocks(machine().time()) / m_divider;
return (int32_t) (current_clocks - hsync_on_clocks);
}
@ -545,7 +546,7 @@ std::string mc6847_friend_device::describe_context() const
//-------------------------------------------------
mc6847_base_device::mc6847_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata, double tpfs) :
mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL), tpfs, 25+191, true),
mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, (type == MC6847T1_NTSC) || (type == MC6847T1_PAL), tpfs, 25+191, 1, true),
m_input_cb(*this),
m_black_and_white(false),
m_fixed_mode(0),

View File

@ -93,7 +93,7 @@ public:
protected:
mc6847_friend_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock,
const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, bool supports_partial_body_scanlines);
const uint8_t *fontdata, bool is_mc6847t1, double tpfs, int field_sync_falling_edge_scanline, int divider, bool supports_partial_body_scanlines);
// timer constants
static constexpr device_timer_id TIMER_FRAME = 0;
@ -479,6 +479,7 @@ private:
// incidentals
double m_tpfs;
int m_divider;
int m_field_sync_falling_edge_scanline;
bool m_wide;
bool m_video_changed;

View File

@ -430,10 +430,10 @@ DEVICE_INPUT_DEFAULTS_END
static MACHINE_CONFIG_START( coco )
MCFG_DEVICE_MODIFY(":")
MCFG_DEVICE_CLOCK(XTAL_3_579545MHz)
MCFG_DEVICE_CLOCK(XTAL_14_31818MHz / 16)
// basic machine hardware
MCFG_CPU_ADD(MAINCPU_TAG, M6809E, DERIVED_CLOCK(1, 1))
MCFG_CPU_ADD(MAINCPU_TAG, MC6809E, DERIVED_CLOCK(1, 1))
MCFG_CPU_PROGRAM_MAP(coco_mem)
MCFG_CPU_DISASSEMBLE_OVERRIDE(coco_state, dasm_override)
@ -456,7 +456,7 @@ static MACHINE_CONFIG_START( coco )
MCFG_PIA_IRQA_HANDLER(WRITELINE(coco_state, pia1_firq_a))
MCFG_PIA_IRQB_HANDLER(WRITELINE(coco_state, pia1_firq_b))
MCFG_SAM6883_ADD(SAM_TAG, XTAL_3_579545MHz, MAINCPU_TAG, AS_PROGRAM)
MCFG_SAM6883_ADD(SAM_TAG, XTAL_14_31818MHz, MAINCPU_TAG, AS_PROGRAM)
MCFG_SAM6883_RES_CALLBACK(READ8(coco12_state, sam_read))
// Becker Port device
@ -478,7 +478,7 @@ static MACHINE_CONFIG_START( coco )
// video hardware
MCFG_SCREEN_MC6847_NTSC_ADD(SCREEN_TAG, VDG_TAG)
MCFG_DEVICE_ADD(VDG_TAG, MC6847_NTSC, XTAL_3_579545MHz)
MCFG_DEVICE_ADD(VDG_TAG, MC6847_NTSC, XTAL_14_31818MHz / 4) // VClk output from MC6883
MCFG_MC6847_HSYNC_CALLBACK(WRITELINE(coco12_state, horizontal_sync))
MCFG_MC6847_FSYNC_CALLBACK(WRITELINE(coco12_state, field_sync))
MCFG_MC6847_INPUT_CALLBACK(DEVREAD8(SAM_TAG, sam6883_device, display_read))
@ -522,7 +522,7 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( coco2b, coco2 )
MCFG_DEVICE_REMOVE(VDG_TAG)
MCFG_DEVICE_ADD(VDG_TAG, MC6847T1_NTSC, XTAL_3_579545MHz)
MCFG_DEVICE_ADD(VDG_TAG, MC6847T1_NTSC, XTAL_14_31818MHz / 4)
MCFG_MC6847_HSYNC_CALLBACK(WRITELINE(coco12_state, horizontal_sync))
MCFG_MC6847_FSYNC_CALLBACK(WRITELINE(coco12_state, field_sync))
MCFG_MC6847_INPUT_CALLBACK(DEVREAD8(SAM_TAG, sam6883_device, display_read))

View File

@ -243,10 +243,10 @@ DEVICE_INPUT_DEFAULTS_END
static MACHINE_CONFIG_START( coco3 )
MCFG_DEVICE_MODIFY(":")
MCFG_DEVICE_CLOCK(XTAL_3_579545MHz)
MCFG_DEVICE_CLOCK(XTAL_28_63636MHz / 32)
// basic machine hardware
MCFG_CPU_ADD(MAINCPU_TAG, M6809E, DERIVED_CLOCK(1, 1))
MCFG_CPU_ADD(MAINCPU_TAG, MC6809E, DERIVED_CLOCK(1, 1))
MCFG_CPU_PROGRAM_MAP(coco3_mem)
MCFG_CPU_DISASSEMBLE_OVERRIDE(coco_state, dasm_override)
@ -291,7 +291,7 @@ static MACHINE_CONFIG_START( coco3 )
// video hardware
MCFG_DEFAULT_LAYOUT(layout_coco3)
MCFG_DEVICE_ADD(GIME_TAG, GIME_NTSC, XTAL_3_579545MHz)
MCFG_DEVICE_ADD(GIME_TAG, GIME_NTSC, XTAL_28_63636MHz)
MCFG_GIME_MAINCPU(MAINCPU_TAG)
MCFG_GIME_RAM(RAM_TAG)
MCFG_GIME_EXT(CARTRIDGE_TAG)
@ -337,7 +337,11 @@ static MACHINE_CONFIG_START( coco3 )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( coco3p, coco3 )
MCFG_DEVICE_REPLACE(GIME_TAG, GIME_PAL, XTAL_4_433619MHz)
MCFG_DEVICE_MODIFY(":")
MCFG_DEVICE_CLOCK(XTAL_28_475MHz / 32)
// An additional 4.433618 MHz XTAL is required for PAL color encoding
MCFG_DEVICE_REPLACE(GIME_TAG, GIME_PAL, XTAL_28_475MHz)
MCFG_GIME_MAINCPU(MAINCPU_TAG)
MCFG_GIME_RAM(RAM_TAG)
MCFG_GIME_EXT(CARTRIDGE_TAG)
@ -349,7 +353,7 @@ static MACHINE_CONFIG_DERIVED( coco3p, coco3 )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( coco3h, coco3 )
MCFG_CPU_REPLACE(MAINCPU_TAG, HD6309, DERIVED_CLOCK(1, 1))
MCFG_CPU_REPLACE(MAINCPU_TAG, HD6309E, DERIVED_CLOCK(1, 1))
MCFG_CPU_PROGRAM_MAP(coco3_mem)
MACHINE_CONFIG_END

View File

@ -319,12 +319,12 @@ SLOT_INTERFACE_END
static MACHINE_CONFIG_START( dgnbeta )
/* basic machine hardware */
MCFG_CPU_ADD(MAINCPU_TAG, M6809E, DGNBETA_CPU_SPEED_HZ) /* 2 MHz */
MCFG_CPU_ADD(MAINCPU_TAG, MC6809E, DGNBETA_CPU_SPEED_HZ) /* 2 MHz */
MCFG_CPU_PROGRAM_MAP(dgnbeta_map)
MCFG_CPU_DISASSEMBLE_OVERRIDE(dgn_beta_state, dgnbeta_dasm_override)
/* both cpus in the beta share the same address/data buses */
MCFG_CPU_ADD(DMACPU_TAG, M6809E, DGNBETA_CPU_SPEED_HZ) /* 2 MHz */
MCFG_CPU_ADD(DMACPU_TAG, MC6809E, DGNBETA_CPU_SPEED_HZ) /* 2 MHz */
MCFG_CPU_PROGRAM_MAP(dgnbeta_map)
/* video hardware */

View File

@ -180,10 +180,10 @@ SLOT_INTERFACE_END
static MACHINE_CONFIG_START( dragon_base )
MCFG_DEVICE_MODIFY(":")
MCFG_DEVICE_CLOCK(XTAL_14_218MHz/4)
MCFG_DEVICE_CLOCK(XTAL_14_218MHz / 16)
// basic machine hardware
MCFG_CPU_ADD("maincpu", M6809E, DERIVED_CLOCK(1, 1))
MCFG_CPU_ADD("maincpu", MC6809E, DERIVED_CLOCK(1, 1))
MCFG_CPU_PROGRAM_MAP(dragon_mem)
// devices
@ -205,7 +205,7 @@ static MACHINE_CONFIG_START( dragon_base )
MCFG_PIA_IRQA_HANDLER(WRITELINE(coco_state, pia1_firq_a))
MCFG_PIA_IRQB_HANDLER(WRITELINE(coco_state, pia1_firq_b))
MCFG_SAM6883_ADD(SAM_TAG, XTAL_14_218MHz/4, MAINCPU_TAG, AS_PROGRAM)
MCFG_SAM6883_ADD(SAM_TAG, XTAL_14_218MHz, MAINCPU_TAG, AS_PROGRAM)
MCFG_SAM6883_RES_CALLBACK(READ8(dragon_state, sam_read))
MCFG_CASSETTE_ADD("cassette")
MCFG_CASSETTE_FORMATS(coco_cassette_formats)

View File

@ -73,6 +73,7 @@ DEFINE_DEVICE_TYPE(SAM6883, sam6883_device, "sam6883", "MC6883 SAM")
sam6883_device::sam6883_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SAM6883, tag, owner, clock)
, sam6883_friend_device_interface(mconfig, *this, 4)
, m_cpu_tag(nullptr)
, m_cpu_space_ref(AS_PROGRAM)
, m_cpu_space(nullptr)
@ -89,6 +90,14 @@ sam6883_device::sam6883_device(const machine_config &mconfig, const char *tag, d
{
}
sam6883_friend_device_interface::sam6883_friend_device_interface(const machine_config &mconfig, device_t &device, int divider)
: device_interface(device, "sam6883")
, m_cpu(nullptr)
, m_sam_state(0x0000)
, m_divider(divider)
{
}
//-------------------------------------------------
// device_start - device-specific startup
@ -296,7 +305,7 @@ void sam6883_device::update_memory(void)
// clock
//-------------------------------------------------
void sam6883_friend_device::update_cpu_clock(void)
void sam6883_friend_device_interface::update_cpu_clock(void)
{
// The infamous speed up poke.
//
@ -321,9 +330,7 @@ void sam6883_friend_device::update_cpu_clock(void)
// access but RAM was not. I don't know how to simulate this.
int speed = (m_sam_state & (SAM_STATE_R1|SAM_STATE_R0)) / SAM_STATE_R0;
// the line below is weird because we are not strictly emulating the M6809E with emphasis on the 'E'
m_cpu->owner()->set_clock_scale(speed ? 2 : 1);
m_cpu->owner()->set_unscaled_clock(device().clock() / (m_divider * (speed ? 2 : 4)));
}

View File

@ -27,10 +27,10 @@
//**************************************************************************
// base class so that GIME emulation can use some functionality
class sam6883_friend_device
class sam6883_friend_device_interface : public device_interface
{
public:
sam6883_friend_device() { m_cpu = nullptr; m_sam_state = 0x0000; }
sam6883_friend_device_interface(const machine_config &mconfig, device_t &device, int divider);
protected:
// SAM state constants
@ -57,6 +57,9 @@ protected:
// device state
uint16_t m_sam_state;
// base clock divider (/4 for MC6883, /8 for GIME)
int m_divider;
ATTR_FORCE_INLINE uint16_t display_offset(void)
{
return ((m_sam_state & (SAM_STATE_F0|SAM_STATE_F1|SAM_STATE_F2|SAM_STATE_F3|SAM_STATE_F4|SAM_STATE_F5|SAM_STATE_F6)) / SAM_STATE_F0) << 9;
@ -83,7 +86,7 @@ protected:
void update_cpu_clock(void);
};
class sam6883_device : public device_t, public sam6883_friend_device
class sam6883_device : public device_t, public sam6883_friend_device_interface
{
public:
sam6883_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

View File

@ -1108,7 +1108,7 @@ void coco_state::poll_hires_joystick(void)
double value = m_joystick.input(joystick_index, axis) / 255.0;
value *= is_cocomax3 ? 2500.0 : 4160.0;
value += is_cocomax3 ? 400.0 : 592.0;
attotime duration = maincpu().clocks_to_attotime((uint64_t) value) * 8;
attotime duration = maincpu().clocks_to_attotime((uint64_t) value) * 2;
m_hiresjoy_transition_timer[axis]->adjust(duration);
}
else if (!m_hiresjoy_ca && newvalue)

View File

@ -109,7 +109,8 @@
//-------------------------------------------------
gime_device::gime_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, const uint8_t *fontdata)
: mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, true, 263, 25+192+26+3, false)
: mc6847_friend_device(mconfig, type, tag, owner, clock, fontdata, true, 263, 25+192+26+3, 8, false)
, sam6883_friend_device_interface(mconfig, *this, 8)
, m_write_irq(*this)
, m_write_firq(*this)
, m_read_floating_bus(*this)
@ -464,20 +465,17 @@ void gime_device::reset_timer(void)
m_timer_value += 2; /* the 1986 GIME reset to the value plus two */
}
attotime duration;
if ((timer_type() == GIME_TIMER_CLOCK) && (m_timer_value > 0))
{
/* we're starting a countdown on the GIME clock timer */
attotime current_time = machine().time();
uint64_t current_tick = current_time.as_ticks(m_clock);
duration = attotime::from_ticks(current_tick + m_timer_value, m_clock) - current_time;
attotime duration = clocks_to_attotime(m_timer_value * 8);
m_gime_clock_timer->adjust(duration);
}
else
{
/* either the timer is off, or were not using the GIME clock timer */
duration = attotime::never;
m_gime_clock_timer->adjust(attotime::never);
}
m_gime_clock_timer->adjust(duration);
if (LOG_TIMER)
logerror("%s: reset_timer(): timer_type=%s value=%d\n", describe_context(), timer_type_string(), m_timer_value);
@ -2051,5 +2049,5 @@ namespace
};
};
DEFINE_DEVICE_TYPE(GIME_NTSC, gime_ntsc_device, "gime_ntsc", "CoCo GIME (NTSC)")
DEFINE_DEVICE_TYPE(GIME_PAL, gime_pal_device, "gime_pal", "CoCo GIME (PAL)")
DEFINE_DEVICE_TYPE(GIME_NTSC, gime_ntsc_device, "gime_ntsc", "TCC1014 (VC2645QC) GIME (NTSC)")
DEFINE_DEVICE_TYPE(GIME_PAL, gime_pal_device, "gime_pal", "TCC1014 (VC2645QC) GIME (PAL)")

View File

@ -52,7 +52,7 @@
class cococart_slot_device;
class gime_device : public mc6847_friend_device, public sam6883_friend_device
class gime_device : public mc6847_friend_device, public sam6883_friend_device_interface
{
public:
template <class Object> static devcb_base &set_irq_wr_callback(device_t &device, Object &&cb) { return downcast<gime_device &>(device).m_write_irq.set_callback(std::forward<Object>(cb)); }