Fix inverted check on anonymous timers prior to saving state. Also

fix bug where we fail to ignore the permanent non-expiring anonymous
timer. Added code to log timers, and we now log them at each save
attempt as well as at restore time. Should fix most recent save state
releated regressions. [Aaron Giles]
This commit is contained in:
Aaron Giles 2011-06-05 16:01:42 +00:00
parent c0fbaa4def
commit bdca1b980a
4 changed files with 69 additions and 8 deletions

View File

@ -148,9 +148,13 @@ const char *attotime::as_string(int precision) const
static char buffers[8][30];
static int nextbuf;
char *buffer = &buffers[nextbuf++ % 8][0];
// special case: never
if (*this == never)
sprintf(buffer, "%-*s", precision, "(never)");
// case 1: we want no precision; seconds only
if (precision == 0)
else if (precision == 0)
sprintf(buffer, "%d", seconds);
// case 2: we want 9 or fewer digits of precision

View File

@ -789,7 +789,7 @@ void running_machine::handle_saveload()
// if there are anonymous timers, we can't save just yet, and we can't load yet either
// because the timers might overwrite data we have loaded
if (m_scheduler.can_save())
if (!m_scheduler.can_save())
{
// if more than a second has passed, we're probably screwed
if ((this->time() - m_saveload_schedule_time) > attotime::from_seconds(1))

View File

@ -257,8 +257,8 @@ attotime emu_timer::remaining() const
//-------------------------------------------------
// timer_register_save - register ourself with
// the save state system
// register_save - register ourself with the save
// state system
//-------------------------------------------------
void emu_timer::register_save()
@ -312,6 +312,21 @@ void emu_timer::schedule_next_period()
}
//-------------------------------------------------
// dump - dump internal state to a single output
// line in the error log
//-------------------------------------------------
void emu_timer::dump() const
{
logerror("%p: en=%d temp=%d exp=%15s start=%15s per=%15s param=%d ptr=%p", this, m_enabled, m_temporary, m_expire.as_string(), m_start.as_string(), m_period.as_string(), m_param, m_ptr);
if (m_device == NULL)
logerror(" cb=%s\n", m_callback.name());
else
logerror(" dev=%s id=%d\n", m_device->tag(), m_id);
}
//**************************************************************************
// DEVICE SCHEDULER
@ -341,6 +356,7 @@ device_scheduler::device_scheduler(running_machine &machine) :
// register global states
machine.save().save_item(NAME(m_basetime));
machine.save().register_presave(save_prepost_delegate(FUNC(device_scheduler::presave), this));
machine.save().register_postload(save_prepost_delegate(FUNC(device_scheduler::postload), this));
}
@ -382,8 +398,12 @@ bool device_scheduler::can_save() const
{
// if any live temporary timers exit, fail
for (emu_timer *timer = m_timer_list; timer != NULL; timer = timer->next())
if (timer->m_temporary)
if (timer->m_temporary && timer->expire() != attotime::never)
{
logerror("Failed save state attempt due to anonymous timers:\n");
dump_timers();
return false;
}
// otherwise, we're good
return true;
@ -632,6 +652,18 @@ void device_scheduler::timed_trigger(void *ptr, INT32 param)
}
//-------------------------------------------------
// presave - before creating a save state
//-------------------------------------------------
void device_scheduler::presave()
{
// report the timer state after a log
logerror("Prior to saving state:\n");
dump_timers();
}
//-------------------------------------------------
// postload - after loading a save state
//-------------------------------------------------
@ -644,8 +676,8 @@ void device_scheduler::postload()
{
emu_timer &timer = *m_timer_list;
// temporary timers go away entirely
if (timer.m_temporary)
// temporary timers go away entirely (except our special never-expiring one)
if (timer.m_temporary && timer.expire() != attotime::never)
m_timer_allocator.reclaim(timer.release());
// permanent ones get added to our private list
@ -657,6 +689,10 @@ void device_scheduler::postload()
emu_timer *timer;
while ((timer = private_list.detach_head()) != NULL)
timer_list_insert(*timer);
// report the timer state after a log
logerror("After resetting/reordering timers:\n");
dump_timers();
}
@ -936,3 +972,19 @@ void device_scheduler::add_scheduling_quantum(attotime quantum, attotime duratio
m_quantum_list.insert_after(quant, insert_after);
}
}
//-------------------------------------------------
// dump_timers - dump the current timer state
//-------------------------------------------------
void device_scheduler::dump_timers() const
{
logerror("=============================================\n");
logerror("Timer Dump: Time = %15s\n", time().as_string());
for (emu_timer *timer = first_timer(); timer != NULL; timer = timer->next())
timer->dump();
logerror("=============================================\n");
}

View File

@ -117,11 +117,12 @@ public:
attotime remaining() const;
attotime start() const { return m_start; }
attotime expire() const { return m_expire; }
private:
// internal helpers
void register_save();
void schedule_next_period();
void dump() const;
// internal state
running_machine * m_machine; // reference to the owning machine
@ -181,12 +182,16 @@ public:
emu_timer *timer_alloc(device_t &device, device_timer_id id = 0, void *ptr = NULL);
void timer_set(attotime duration, device_t &device, device_timer_id id = 0, int param = 0, void *ptr = NULL);
// debugging
void dump_timers() const;
// for emergencies only!
void eat_all_cycles();
private:
// callbacks
void timed_trigger(void *ptr, INT32 param);
void presave();
void postload();
// scheduling helpers