我打算写一个nes模拟器。但首先,要了解仿真的工作原理,我将编写一个Chip-8仿真器。
模拟器差不多完成了。我在游戏中遇到了一些错误,但很快就会修复。 我的问题1是将仿真器与Chip-8的时钟速度同步。 在互联网上,我经常读到,通用时钟速度应该是~540Hz。芯片的定时器应以60Hz的频率打勾。
要将我的模拟器与Chip-8同步,我写了以下逻辑:
private void GameTick()
{
Stopwatch watch = new Stopwatch();
var instructionCount = 0;
_gameIsRunning = true;
while (_gameIsRunning)
{
watch.Restart();
EmulateCycle();
//Updates the internal timer at a 60hz frequenz
//540hz (game tick) divided by 9 equals 60hz (timer tick)
instructionCount++;
if(instructionCount == 9)
{
UpdateSoundAndDelay();
instructionCount = 0;
}
if (_readyToDraw)
{
DrawGraphics();
_readyToDraw = false;
}
SetKeys();
//Pause the game to get a virtual clock speed of ca. 540mhz
var elapsedMicroseconds = watch.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
while(elapsedMicroseconds < 1852)
{
elapsedMicroseconds = watch.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
}
}
}
有关详细信息,请查看我的回购:https://github.com/Marcel-Hoffmann/Chip-8-Emulator
如您所见,对于每个cpu周期,我将等待1852微秒。结果将是〜540个周期,一秒钟等于540Hz。 但我对这种逻辑并不满意。
有人有更好的想法,如何同步时钟速度?
答案 0 :(得分:2)
这是典型的方法,并且有许多缺点 - 最值得注意的是,不必要的CPU使用率和潜在的调度问题(您的应用程序将被视为100%CPU野兽,因此其他应用程序可能会在您加载之前获得其线程量程)。
更好的方法是使用睡眠 - 但是,默认情况下,系统计时器远不及频率来容纳小于2毫秒的等待时间。因此,如果您想使用睡眠,则需要更改系统计时器。这在旧版Windows上有点棘手(它是一个系统范围的设置,对其他应用程序和一般的CPU使用有明显的影响),但即使在这种情况下,它也比“繁忙的循环”更好 - 只要你恢复系统之后的设置。在Windows 8(在某种程度上,7和Vista),定时器是异步的,不再需要繁忙的循环,因此更高的定时器分辨率更容易。
.NET不公开系统计时器API,因此您需要使用P / Invokes(timeBeginPeriod
和timeEndPeriod
作为旧式API)。如果这不可用,您可以随时回到繁忙的循环:)