예제 #1
0
void DoState(PointerWrap& p)
{
    std::lock_guard<std::mutex> lk(s_ts_write_lock);
    p.Do(g_slice_length);
    p.Do(g_global_timer);
    p.Do(s_idled_cycles);
    p.Do(s_fake_dec_start_value);
    p.Do(s_fake_dec_start_ticks);
    p.Do(g_fake_TB_start_value);
    p.Do(g_fake_TB_start_ticks);
    p.Do(s_last_OC_factor);
    g_last_OC_factor_inverted = 1.0f / s_last_OC_factor;
    p.Do(s_event_fifo_id);

    p.DoMarker("CoreTimingData");

    MoveEvents();
    p.DoEachElement(s_event_queue, [](PointerWrap& pw, Event& ev) {
        pw.Do(ev.time);
        pw.Do(ev.fifo_order);

        // this is why we can't have (nice things) pointers as userdata
        pw.Do(ev.userdata);

        // we can't savestate ev.type directly because events might not get registered in the same
        // order (or at all) every time.
        // so, we savestate the event's type's name, and derive ev.type from that when loading.
        std::string name;
        if (pw.GetMode() != PointerWrap::MODE_READ)
            name = *ev.type->name;

        pw.Do(name);
        if (pw.GetMode() == PointerWrap::MODE_READ)
        {
            auto itr = s_event_types.find(name);
            if (itr != s_event_types.end())
            {
                ev.type = &itr->second;
            }
            else
            {
                WARN_LOG(POWERPC,
                         "Lost event from savestate because its type, \"%s\", has not been registered.",
                         name.c_str());
                ev.type = s_ev_lost;
            }
        }
    });
    p.DoMarker("CoreTimingEvents");

    // When loading from a save state, we must assume the Event order is random and meaningless.
    // The exact layout of the heap in memory is implementation defined, therefore it is platform
    // and library version specific.
    if (p.GetMode() == PointerWrap::MODE_READ)
        std::make_heap(s_event_queue.begin(), s_event_queue.end(), std::greater<Event>());
}