void hleLagSync(u64 userdata, int cyclesLate) { // The goal here is to prevent network, audio, and input lag from the real world. // Our normal timing is very "stop and go". This is efficient, but causes real world lag. // This event (optionally) runs every 1ms to sync with the real world. if (!FrameTimingThrottled()) { lagSyncScheduled = false; return; } float scale = 1.0f; if (PSP_CoreParameter().fpsLimit == FPS_LIMIT_CUSTOM) { // 0 is handled in FrameTimingThrottled(). scale = 60.0f / g_Config.iFpsLimit; } const double goal = lastLagSync + (scale / 1000.0f); time_update(); // Don't lag too long ever, if they leave it paused. while (time_now_d() < goal && goal < time_now_d() + 0.01) { #ifndef _WIN32 const double left = goal - time_now_d(); usleep((long)(left * 1000000)); #endif time_update(); } const int emuOver = (int)cyclesToUs(cyclesLate); const int over = (int)((time_now_d() - goal) * 1000000); ScheduleLagSync(over - emuOver); }
void hleAfterFlip(u64 userdata, int cyclesLate) { gpu->BeginFrame(); // doesn't really matter if begin or end of frame. // This seems like as good a time as any to check if the config changed. if (lagSyncScheduled != g_Config.bForceLagSync) { ScheduleLagSync(); } }
void __DisplayInit() { gpuStats.Reset(); hasSetMode = false; mode = 0; resumeMode = 0; holdMode = 0; brightnessLevel = 100; width = 480; height = 272; numSkippedFrames = 0; numVBlanksSinceFlip = 0; framebufIsLatched = false; framebuf.topaddr = 0x04000000; framebuf.pspFramebufFormat = GE_FORMAT_8888; framebuf.pspFramebufLinesize = 480; // ?? lastFlipCycles = 0; lastFlipsTooFrequent = 0; wasPaused = false; enterVblankEvent = CoreTiming::RegisterEvent("EnterVBlank", &hleEnterVblank); leaveVblankEvent = CoreTiming::RegisterEvent("LeaveVBlank", &hleLeaveVblank); afterFlipEvent = CoreTiming::RegisterEvent("AfterFlip", &hleAfterFlip); lagSyncEvent = CoreTiming::RegisterEvent("LagSync", &hleLagSync); ScheduleLagSync(); CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0); isVblank = 0; vCount = 0; hCountBase = 0; curFrameTime = 0.0; nextFrameTime = 0.0; lastFrameTime = 0.0; flips = 0; fps = 0.0; actualFlips = 0; lastActualFlips = 0; lastNumFlips = 0; fpsHistoryValid = 0; fpsHistoryPos = 0; InitGfxState(); __KernelRegisterWaitTypeFuncs(WAITTYPE_VBLANK, __DisplayVblankBeginCallback, __DisplayVblankEndCallback); }
void __DisplayDoState(PointerWrap &p) { auto s = p.Section("sceDisplay", 1, 6); if (!s) return; p.Do(framebuf); p.Do(latchedFramebuf); p.Do(framebufIsLatched); p.Do(frameStartTicks); p.Do(vCount); if (s <= 2) { double oldHCountBase; p.Do(oldHCountBase); hCountBase = (int) oldHCountBase; } else { p.Do(hCountBase); } p.Do(isVblank); p.Do(hasSetMode); p.Do(mode); p.Do(resumeMode); p.Do(holdMode); if (s >= 4) { p.Do(brightnessLevel); } p.Do(width); p.Do(height); WaitVBlankInfo wvi(0); p.Do(vblankWaitingThreads, wvi); p.Do(vblankPausedWaits); p.Do(enterVblankEvent); CoreTiming::RestoreRegisterEvent(enterVblankEvent, "EnterVBlank", &hleEnterVblank); p.Do(leaveVblankEvent); CoreTiming::RestoreRegisterEvent(leaveVblankEvent, "LeaveVBlank", &hleLeaveVblank); p.Do(afterFlipEvent); CoreTiming::RestoreRegisterEvent(afterFlipEvent, "AfterFlip", &hleAfterFlip); if (s >= 5) { p.Do(lagSyncEvent); p.Do(lagSyncScheduled); CoreTiming::RestoreRegisterEvent(lagSyncEvent, "LagSync", &hleLagSync); lastLagSync = real_time_now(); if (lagSyncScheduled != g_Config.bForceLagSync) { ScheduleLagSync(); } } else { lagSyncEvent = CoreTiming::RegisterEvent("LagSync", &hleLagSync); ScheduleLagSync(); } p.Do(gstate); gstate_c.DoState(p); #ifndef _XBOX if (s < 2) { // This shouldn't have been savestated anyway, but it was. // It's unlikely to overlap with the first value in gpuStats. p.ExpectVoid(&gl_extensions.gpuVendor, sizeof(gl_extensions.gpuVendor)); } #endif if (s < 6) { p.Do(gpuStats); } gpu->DoState(p); ReapplyGfxState(); if (p.mode == p.MODE_READ) { if (hasSetMode) { gpu->InitClear(); } gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); } }