/*
* HalfNES by Andrew Hoffman
* Licensed under the GNU GPL Version 3. See LICENSE file
*/
package com.grapeshot.halfnes.ui;
import com.grapeshot.halfnes.NES;
import com.grapeshot.halfnes.PrefsSingleton;
/**
*
* @author Andrew
*/
public class FrameLimiterImpl implements FrameLimiterInterface {
NES nes;
private long sleepingtest = 0;
public long FRAME_NS;
public FrameLimiterImpl(NES nes, long framens) {
this.nes = nes;
FRAME_NS = framens;
//forceHighResolutionTimer();
}
public void setInterval(long ns) {
FRAME_NS = ns;
}
@Override
public void sleep() {
//Frame Limiter
if (!PrefsSingleton.get().getBoolean("Sleep", true)) {
return; //skip frame limiter if pref set
}
final long timeleft = System.nanoTime() - nes.frameStartTime;
if (timeleft < FRAME_NS) {
final long sleepytime = (FRAME_NS - timeleft + sleepingtest);
if (sleepytime < 0) {
return;
//don't sleep at all.
}
sleepingtest = System.nanoTime();
try {
//System.err.println(sleepytime/ 1000000.);
Thread.sleep(sleepytime / 1000000);
// sleep for rest of the time until the next frame
} catch (InterruptedException ex) {
}
sleepingtest = System.nanoTime() - sleepingtest;
//now sleeping test has how many ns the sleep *actually* was
sleepingtest = sleepytime - sleepingtest;
//now sleepingtest has how much the next frame needs to be delayed by to make things match
}
}
@Override
public void sleepFixed() {
try {
//sleep for 16 ms
Thread.sleep(16);
} catch (InterruptedException ex) {
}
}
public static void forceHighResolutionTimer() {
//UGLY HACK ALERT: Just realized why sleep() rounds to nearest
//multiple of 10: it's because no other program is using high resolution timer.
//This should, hopefully, fix that.
final Thread daemon = new Thread("ForceHighResolutionTimer") {
@Override
public void run() {
while (true) {
try {
Thread.sleep(99999999999L);
} catch (InterruptedException e) {
break;
}
}
}
};
daemon.setDaemon(true);
daemon.start();
}
}