content: /*
   * 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();
      }
  
  }
  