Added an integral device_timer_id to device timers. This is a

cleaner way to differentiate between multiple timers rather than
relying on the pointers. These values are also saved with the
timers. Updated the few devices using device timers to leverage
this.

Added new function device_timer_call_after_resynch() which creates
a temporary 0-length timer that calls back through the device's
device_timer() method with a given device_timer_id.

Updated i8257_device to initialize its state and use device 
timers.
(Fixes 04032: All sets in dkong.c: [debug] Game does not start.)
This commit is contained in:
Aaron Giles 2010-09-17 13:33:27 +00:00
parent 893c1f3e81
commit 1a066df97d
12 changed files with 163 additions and 150 deletions

View File

@ -873,7 +873,7 @@ void device_t::device_debug_setup()
// fires // fires
//------------------------------------------------- //-------------------------------------------------
void device_t::device_timer(emu_timer &timer, int param, void *ptr) void device_t::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
// do nothing by default // do nothing by default
} }

View File

@ -137,6 +137,10 @@ class device_missing_dependencies : public emu_exception { };
typedef device_config *(*device_type)(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); typedef device_config *(*device_type)(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
// timer IDs for devices
typedef UINT32 device_timer_id;
// read/write types for I/O lines (similar to read/write handlers but no offset) // read/write types for I/O lines (similar to read/write handlers but no offset)
typedef int (*read_line_device_func)(device_t *device); typedef int (*read_line_device_func)(device_t *device);
typedef void (*write_line_device_func)(device_t *device, int state); typedef void (*write_line_device_func)(device_t *device, int state);
@ -425,7 +429,7 @@ public:
void set_clock_scale(double clockscale); void set_clock_scale(double clockscale);
attotime clocks_to_attotime(UINT64 clocks) const; attotime clocks_to_attotime(UINT64 clocks) const;
UINT64 attotime_to_clocks(attotime duration) const; UINT64 attotime_to_clocks(attotime duration) const;
void timer_fired(emu_timer &timer, int param, void *ptr) { device_timer(timer, param, ptr); } void timer_fired(emu_timer &timer, device_timer_id id, int param, void *ptr) { device_timer(timer, id, param, ptr); }
// debugging // debugging
device_debug *debug() const { return m_debug; } device_debug *debug() const { return m_debug; }
@ -460,7 +464,7 @@ protected:
virtual void device_post_load(); virtual void device_post_load();
virtual void device_clock_changed(); virtual void device_clock_changed();
virtual void device_debug_setup(); virtual void device_debug_setup();
virtual void device_timer(emu_timer &timer, int param, void *ptr); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
//------------------- end derived class overrides //------------------- end derived class overrides

View File

@ -218,9 +218,9 @@ void via6522_device::device_start()
m_t2ll = 0xff; /* taken from vice */ m_t2ll = 0xff; /* taken from vice */
m_t2lh = 0xff; m_t2lh = 0xff;
m_time2 = m_time1 = timer_get_time(&m_machine); m_time2 = m_time1 = timer_get_time(&m_machine);
m_t1 = device_timer_alloc(*this); m_t1 = device_timer_alloc(*this, TIMER_T1);
m_t2 = device_timer_alloc(*this); m_t2 = device_timer_alloc(*this, TIMER_T2);
m_shift_timer = device_timer_alloc(*this); m_shift_timer = device_timer_alloc(*this, TIMER_SHIFT);
/* Default clock is from CPU1 */ /* Default clock is from CPU1 */
if (clock() == 0) if (clock() == 0)
@ -415,54 +415,56 @@ void via6522_device::shift()
} }
void via6522_device::device_timer(emu_timer &timer, int param, void *ptr) void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
// shift timer switch (id)
if (&timer == m_shift_timer)
shift();
// t1 timeout
else if (&timer == m_t1)
{ {
if (T1_CONTINUOUS (m_acr)) // shift timer
{ case TIMER_SHIFT:
if (T1_SET_PB7(m_acr)) shift();
{ break;
m_out_b ^= 0x80;
} // t1 timeout
timer_adjust_oneshot(m_t1, cycles_to_time(TIMER1_VALUE + IFR_DELAY), 0); case TIMER_T1:
} if (T1_CONTINUOUS (m_acr))
else {
{ if (T1_SET_PB7(m_acr))
if (T1_SET_PB7(m_acr)) {
{ m_out_b ^= 0x80;
m_out_b |= 0x80; }
} timer_adjust_oneshot(m_t1, cycles_to_time(TIMER1_VALUE + IFR_DELAY), 0);
m_t1_active = 0; }
m_time1 = timer_get_time(&m_machine); else
} {
if (m_ddr_b) if (T1_SET_PB7(m_acr))
{ {
UINT8 write_data = (m_out_b & m_ddr_b) | (m_ddr_b ^ 0xff); m_out_b |= 0x80;
devcb_call_write8(&m_out_b_func, 0, write_data); }
} m_t1_active = 0;
m_time1 = timer_get_time(&m_machine);
}
if (m_ddr_b)
{
UINT8 write_data = (m_out_b & m_ddr_b) | (m_ddr_b ^ 0xff);
devcb_call_write8(&m_out_b_func, 0, write_data);
}
if (!(m_ifr & INT_T1)) if (!(m_ifr & INT_T1))
{ {
set_int(INT_T1); set_int(INT_T1);
} }
} break;
// t2 timeout // t2 timeout
else if (&timer == m_t2) case TIMER_T2:
{ m_t2_active = 0;
m_t2_active = 0; m_time2 = timer_get_time(&m_machine);
m_time2 = timer_get_time(&m_machine);
if (!(m_ifr & INT_T2)) if (!(m_ifr & INT_T2))
{ {
set_int(INT_T2); set_int(INT_T2);
} }
break;
} }
} }

View File

@ -133,9 +133,13 @@ protected:
// device-level overrides // device-level overrides
virtual void device_start(); virtual void device_start();
virtual void device_reset(); virtual void device_reset();
virtual void device_timer(emu_timer &timer, int param, void *ptr); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
private: private:
static const device_timer_id TIMER_SHIFT = 0;
static const device_timer_id TIMER_T1 = 1;
static const device_timer_id TIMER_T2 = 2;
attotime cycles_to_time(int c); attotime cycles_to_time(int c);
UINT32 time_to_cycles(attotime t); UINT32 time_to_cycles(attotime t);
UINT16 get_counter1_value(); UINT16 get_counter1_value();

View File

@ -101,9 +101,17 @@ const device_type I8257 = i8257_device_config::static_alloc_device_config;
i8257_device::i8257_device(running_machine &_machine, const i8257_device_config &config) i8257_device::i8257_device(running_machine &_machine, const i8257_device_config &config)
: device_t(_machine, config), : device_t(_machine, config),
m_mode(0),
m_rr(0),
m_msb(0),
m_drq(0),
m_status(0x0f),
m_config(config) m_config(config)
{ {
memset(m_registers, 0, sizeof(m_registers));
memset(m_address, 0, sizeof(m_address));
memset(m_count, 0, sizeof(m_count));
memset(m_rwmode, 0, sizeof(m_rwmode));
} }
//------------------------------------------------- //-------------------------------------------------
@ -129,9 +137,8 @@ void i8257_device::device_start()
} }
/* set initial values */ /* set initial values */
m_status = 0x0f; m_timer = device_timer_alloc(*this, TIMER_OPERATION);
m_timer = timer_alloc(&m_machine, i8257_timerproc_callback, (void *) this); m_msbflip_timer = device_timer_alloc(*this, TIMER_MSBFLIP);
m_msbflip_timer = timer_alloc(&m_machine, i8257_msbflip_timerproc_callback, (void *) this);
/* register for state saving */ /* register for state saving */
state_save_register_device_item_array(this, 0, m_address); state_save_register_device_item_array(this, 0, m_address);
@ -243,55 +250,72 @@ int i8257_device::i8257_do_operation(int channel)
} }
TIMER_CALLBACK( i8257_device::i8257_timerproc_callback ) void i8257_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
reinterpret_cast<i8257_device*>(ptr)->i8257_timerproc(); switch (id)
}
void i8257_device::i8257_timerproc()
{
int i, channel = 0, rr;
int done;
rr = DMA_MODE_ROTPRIO(m_mode) ? m_rr : 0;
for (i = 0; i < I8257_NUM_CHANNELS; i++)
{ {
channel = (i + rr) % I8257_NUM_CHANNELS; case TIMER_OPERATION:
if ((m_status & (1 << channel)) == 0)
{ {
if (m_mode & m_drq & (1 << channel)) int i, channel = 0, rr;
int done;
rr = DMA_MODE_ROTPRIO(m_mode) ? m_rr : 0;
for (i = 0; i < I8257_NUM_CHANNELS; i++)
{ {
break; channel = (i + rr) % I8257_NUM_CHANNELS;
if ((m_status & (1 << channel)) == 0)
{
if (m_mode & m_drq & (1 << channel))
{
break;
}
}
} }
done = i8257_do_operation(channel);
m_rr = (channel + 1) & 0x03;
if (done)
{
m_drq &= ~(0x01 << channel);
i8257_update_status();
if (!(DMA_MODE_AUTOLOAD(m_mode) && channel==2))
{
if (DMA_MODE_TCSTOP(m_mode))
{
m_mode &= ~(0x01 << channel);
}
}
}
break;
}
case TIMER_MSBFLIP:
m_msb ^= 1;
break;
case TIMER_DRQ_SYNC:
{
int channel = param >> 1;
int state = param & 0x01;
/* normalize state */
if (state)
{
m_drq |= 0x01 << channel;
m_address[channel] = m_registers[channel * 2];
m_count[channel] = m_registers[channel * 2 + 1] & 0x3FFF;
m_rwmode[channel] = m_registers[channel * 2 + 1] >> 14;
/* clear channel TC */
m_status &= ~(0x01 << channel);
}
else
m_drq &= ~(0x01 << channel);
i8257_update_status();
break;
} }
} }
done = i8257_do_operation(channel);
m_rr = (channel + 1) & 0x03;
if (done)
{
m_drq &= ~(0x01 << channel);
i8257_update_status();
if (!(DMA_MODE_AUTOLOAD(m_mode) && channel==2))
{
if (DMA_MODE_TCSTOP(m_mode))
{
m_mode &= ~(0x01 << channel);
}
}
}
}
TIMER_CALLBACK( i8257_device::i8257_msbflip_timerproc_callback )
{
reinterpret_cast<i8257_device*>(ptr)->i8257_msbflip_timerproc();
}
void i8257_device::i8257_msbflip_timerproc()
{
m_msb ^= 1;
} }
@ -421,37 +445,11 @@ WRITE8_DEVICE_HANDLER_TRAMPOLINE(i8257, i8257_w)
} }
TIMER_CALLBACK( i8257_device::i8257_drq_write_callback )
{
reinterpret_cast<i8257_device*>(ptr)->i8257_drq_write_timerproc(param);
}
void i8257_device::i8257_drq_write_timerproc(INT32 param)
{
int channel = param >> 1;
int state = param & 0x01;
/* normalize state */
if (state)
{
m_drq |= 0x01 << channel;
m_address[channel] = m_registers[channel * 2];
m_count[channel] = m_registers[channel * 2 + 1] & 0x3FFF;
m_rwmode[channel] = m_registers[channel * 2 + 1] >> 14;
/* clear channel TC */
m_status &= ~(0x01 << channel);
}
else
m_drq &= ~(0x01 << channel);
i8257_update_status();
}
void i8257_device::i8257_drq_w(int channel, int state) void i8257_device::i8257_drq_w(int channel, int state)
{ {
int param = (channel << 1) | (state ? 1 : 0); int param = (channel << 1) | (state ? 1 : 0);
timer_call_after_resynch(&m_machine, (void *)this, param, i8257_drq_write_callback); device_timer_call_after_resynch(*this, TIMER_DRQ_SYNC, param);
} }
WRITE_LINE_DEVICE_HANDLER( i8257_hlda_w ) { } WRITE_LINE_DEVICE_HANDLER( i8257_hlda_w ) { }

View File

@ -117,22 +117,16 @@ public:
/* data request */ /* data request */
void i8257_drq_w(int channel, int state); void i8257_drq_w(int channel, int state);
void i8257_timerproc();
void i8257_msbflip_timerproc();
void i8257_drq_write_timerproc(INT32 param);
protected: protected:
// device-level overrides // device-level overrides
virtual void device_start(); virtual void device_start();
virtual void device_reset(); virtual void device_reset();
virtual void device_post_load() { } virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
virtual void device_clock_changed() { }
static TIMER_CALLBACK( i8257_timerproc_callback );
static TIMER_CALLBACK( i8257_msbflip_timerproc_callback );
static TIMER_CALLBACK( i8257_drq_write_callback );
private: private:
static const device_timer_id TIMER_OPERATION = 0;
static const device_timer_id TIMER_MSBFLIP = 1;
static const device_timer_id TIMER_DRQ_SYNC = 2;
int i8257_do_operation(int channel); int i8257_do_operation(int channel);
void i8257_update_status(); void i8257_update_status();

View File

@ -278,7 +278,7 @@ void intelfsh_device::device_start()
// device_timer - handler timer events // device_timer - handler timer events
//------------------------------------------------- //-------------------------------------------------
void intelfsh_device::device_timer(emu_timer &timer, int param, void *ptr) void intelfsh_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
switch( m_flash_mode ) switch( m_flash_mode )
{ {

View File

@ -112,7 +112,7 @@ protected:
protected: protected:
// device-level overrides // device-level overrides
virtual void device_start(); virtual void device_start();
virtual void device_timer(emu_timer &timer, int param, void *ptr); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
// device_config_nvram_interface overrides // device_config_nvram_interface overrides
virtual void nvram_default(); virtual void nvram_default();

View File

@ -192,7 +192,7 @@ void mc146818_device::device_start()
// device_timer - handler timer events // device_timer - handler timer events
//------------------------------------------------- //-------------------------------------------------
void mc146818_device::device_timer(emu_timer &timer, int param, void *ptr) void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{ {
int year/*, month*/; int year/*, month*/;

View File

@ -82,7 +82,7 @@ public:
protected: protected:
// device-level overrides // device-level overrides
virtual void device_start(); virtual void device_start();
virtual void device_timer(emu_timer &timer, int param, void *ptr); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
// device_mc146818_interface overrides // device_mc146818_interface overrides
virtual void nvram_default(); virtual void nvram_default();

View File

@ -57,6 +57,7 @@ public:
attotime start; /* time when the timer was started */ attotime start; /* time when the timer was started */
attotime expire; /* time when the timer will expire */ attotime expire; /* time when the timer will expire */
device_t * device; /* for device timers, a pointer to the device */ device_t * device; /* for device timers, a pointer to the device */
device_timer_id id; /* for device timers, the ID of the timer */
}; };
@ -372,7 +373,7 @@ void timer_execute_timers(running_machine *machine)
if (was_enabled) if (was_enabled)
{ {
if (timer->device != NULL) if (timer->device != NULL)
timer->device->timer_fired(*timer, timer->param, timer->ptr); timer->device->timer_fired(*timer, timer->id, timer->param, timer->ptr);
else if (timer->callback != NULL) else if (timer->callback != NULL)
{ {
LOG(("Timer %s:%d[%s] fired (expire=%s)\n", timer->file, timer->line, timer->func, attotime_string(timer->expire, 9))); LOG(("Timer %s:%d[%s] fired (expire=%s)\n", timer->file, timer->line, timer->func, attotime_string(timer->expire, 9)));
@ -519,6 +520,8 @@ static void timer_register_save(emu_timer *timer)
state_save_register_item(timer->machine, "timer", timer->func, count, timer->start.attoseconds); state_save_register_item(timer->machine, "timer", timer->func, count, timer->start.attoseconds);
state_save_register_item(timer->machine, "timer", timer->func, count, timer->expire.seconds); state_save_register_item(timer->machine, "timer", timer->func, count, timer->expire.seconds);
state_save_register_item(timer->machine, "timer", timer->func, count, timer->expire.attoseconds); state_save_register_item(timer->machine, "timer", timer->func, count, timer->expire.attoseconds);
if (timer->device != NULL)
state_save_register_item(timer->machine, "timer", timer->func, count, timer->id);
} }
@ -594,7 +597,7 @@ int timer_count_anonymous(running_machine *machine)
isn't primed yet isn't primed yet
-------------------------------------------------*/ -------------------------------------------------*/
INLINE emu_timer *_timer_alloc_common(running_machine *machine, timer_fired_func callback, void *ptr, const char *file, int line, const char *func, int temp) INLINE emu_timer *_timer_alloc_common(running_machine *machine, device_t *device, device_timer_id id, timer_fired_func callback, void *ptr, const char *file, int line, const char *func, int temp)
{ {
attotime time = get_current_time(machine); attotime time = get_current_time(machine);
emu_timer *timer = timer_new(machine); emu_timer *timer = timer_new(machine);
@ -609,7 +612,8 @@ INLINE emu_timer *_timer_alloc_common(running_machine *machine, timer_fired_func
timer->file = file; timer->file = file;
timer->line = line; timer->line = line;
timer->func = func; timer->func = func;
timer->device = NULL; timer->device = device;
timer->id = id;
/* compute the time of the next firing and insert into the list */ /* compute the time of the next firing and insert into the list */
timer->start = time; timer->start = time;
@ -630,15 +634,12 @@ INLINE emu_timer *_timer_alloc_common(running_machine *machine, timer_fired_func
emu_timer *_timer_alloc_internal(running_machine *machine, timer_fired_func callback, void *ptr, const char *file, int line, const char *func) emu_timer *_timer_alloc_internal(running_machine *machine, timer_fired_func callback, void *ptr, const char *file, int line, const char *func)
{ {
return _timer_alloc_common(machine, callback, ptr, file, line, func, FALSE); return _timer_alloc_common(machine, NULL, 0, callback, ptr, file, line, func, FALSE);
} }
emu_timer *device_timer_alloc(device_t &device, void *ptr, int param) emu_timer *device_timer_alloc(device_t &device, UINT32 id, void *ptr)
{ {
emu_timer *timer = _timer_alloc_common(device.machine, NULL, ptr, __FILE__, __LINE__, device.tag(), FALSE); return _timer_alloc_common(device.machine, &device, id, NULL, ptr, __FILE__, __LINE__, device.tag(), FALSE);
timer->param = param;
timer->device = &device;
return timer;
} }
@ -728,6 +729,13 @@ void timer_adjust_periodic(emu_timer *which, attotime start_delay, INT32 param,
SIMPLIFIED ANONYMOUS TIMER MANAGEMENT SIMPLIFIED ANONYMOUS TIMER MANAGEMENT
***************************************************************************/ ***************************************************************************/
void device_timer_call_after_resynch(device_t &device, device_timer_id id, INT32 param, void *ptr)
{
emu_timer *timer = _timer_alloc_common(device.machine, &device, id, NULL, ptr, __FILE__, __LINE__, device.tag(), TRUE);
timer_adjust_oneshot(timer, attotime_zero, param);
}
/*------------------------------------------------- /*-------------------------------------------------
timer_pulse - allocate a pulse timer, which timer_pulse - allocate a pulse timer, which
repeatedly calls the callback using the given repeatedly calls the callback using the given
@ -736,7 +744,7 @@ void timer_adjust_periodic(emu_timer *which, attotime start_delay, INT32 param,
void _timer_pulse_internal(running_machine *machine, attotime period, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func) void _timer_pulse_internal(running_machine *machine, attotime period, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func)
{ {
emu_timer *timer = _timer_alloc_common(machine, callback, ptr, file, line, func, FALSE); emu_timer *timer = _timer_alloc_common(machine, NULL, 0, callback, ptr, file, line, func, FALSE);
timer_adjust_periodic(timer, period, param, period); timer_adjust_periodic(timer, period, param, period);
} }
@ -748,7 +756,7 @@ void _timer_pulse_internal(running_machine *machine, attotime period, void *ptr,
void _timer_set_internal(running_machine *machine, attotime duration, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func) void _timer_set_internal(running_machine *machine, attotime duration, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func)
{ {
emu_timer *timer = _timer_alloc_common(machine, callback, ptr, file, line, func, TRUE); emu_timer *timer = _timer_alloc_common(machine, NULL, 0, callback, ptr, file, line, func, TRUE);
timer_adjust_oneshot(timer, duration, param); timer_adjust_oneshot(timer, duration, param);
} }

View File

@ -149,7 +149,7 @@ int timer_count_anonymous(running_machine *machine);
emu_timer *_timer_alloc_internal(running_machine *machine, timer_fired_func callback, void *param, const char *file, int line, const char *func); emu_timer *_timer_alloc_internal(running_machine *machine, timer_fired_func callback, void *param, const char *file, int line, const char *func);
/* allocate a permament device timer that isn't primed yet */ /* allocate a permament device timer that isn't primed yet */
emu_timer *device_timer_alloc(device_t &device, void *ptr = NULL, int param = 0); emu_timer *device_timer_alloc(device_t &device, device_timer_id id = 0, void *ptr = NULL);
/* adjust the time when this timer will fire and disable any periodic firings */ /* adjust the time when this timer will fire and disable any periodic firings */
void timer_adjust_oneshot(emu_timer *which, attotime duration, INT32 param); void timer_adjust_oneshot(emu_timer *which, attotime duration, INT32 param);
@ -161,6 +161,9 @@ void timer_adjust_periodic(emu_timer *which, attotime start_delay, INT32 param,
/* ----- anonymous timer management ----- */ /* ----- anonymous timer management ----- */
/* request a one-shot temporary timer for a device */
void device_timer_call_after_resynch(device_t &device, device_timer_id id = 0, INT32 param = 0, void *ptr = NULL);
/* allocate a one-shot timer, which calls the callback after the given duration */ /* allocate a one-shot timer, which calls the callback after the given duration */
void _timer_set_internal(running_machine *machine, attotime duration, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func); void _timer_set_internal(running_machine *machine, attotime duration, void *ptr, INT32 param, timer_fired_func callback, const char *file, int line, const char *func);