Gameboy模拟器的运行速度比预期快

5

我正在尝试制作一个Gameboy模拟器,但它的运行速度比预期的要快。

这是我在主循环中使用的时间代码。

if (cpu.T >= CLOCKSPEED / 40) // if more than 1/40th of cycles passed
{
    // Get milliseconds passed
    QueryPerformanceCounter(&EndCounter);
    unsigned long long counter = EndCounter.QuadPart - LastCounter.QuadPart;
    MSperFrame = 1000.0f * ((double)counter / (double)PerfCountFrequency);
    LastCounter = EndCounter;

    // if 1/40th of a second hasn't passed, wait until it passes
    if (MSperFrame < 25)
        Sleep(25 - MSperFrame);
    MSperFrame = 0;
    cpu.T -= CLOCKSPEED / 40;
}
  • CLOCKSPEED 是Gameboy CPU每秒的周期数(4194304)。
  • cpu.T 是到目前为止经过的周期数。
  • PerfCountFrequency 是在进入循环之前调用的QueryPerformanceFrequency的结果。

当我将其与另一个以正确速度运行的模拟器(VBA)进行比较时,我的模拟器运行得更快。问题出在哪里?


我不会使用 QueryPerformancCounter()。我听说现代CPU为了节省电力而动态地改变它们的速度,这并不总是准确的,尽管我没有确定的来源。现在我通常使用 std::chrono::steady_clock 进行分析,只要它的粒度足够小,比你想计时的周期小即可。 - RyanP
你是否正确计算了Gameboy CPU的周期? - Ross Ridge
@RyanP 一旦我包含了<chrono>,就会收到消息“错误计数超过100。停止编译。(使用Visual Studio)。我现在会等待另一个解决方案。 - devil0150
@devil0150 你在用哪个编译器?<chrono>是在C++11中引入的,因此旧的编译器可能不支持它。另外,Boost也提供了一个chrono库。 - RyanP
@devil0150 我看到你说了Visual Studio,我认为你需要2012或更高版本才能获得chrono。 - RyanP
显示剩余3条评论
1个回答

1
睡眠在这里是错误的功能。从https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx中可以看到,"如果dwMilliseconds小于系统时钟的分辨率,则线程可能睡眠时间少于指定的时间长度"。
DirectX可能有一个方法(VBLANK??),但您可以通过计算下一帧时间并保存休眠时间来解决小问题,如果休眠时间太短,则可以累积休眠时间直到超过计时器分辨率。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接