Skip to content

Commit

Permalink
FreeJ2ME + Anbu + Libretro: Implement a better frame limit logic
Browse files Browse the repository at this point in the history
Previously, frame limiting in FreeJ2ME relied on a fixed interval
for Thread.sleep(), which is already a bit innacurate by itself,
but with a fixed sleep interval meant that the time the game logic
took to render also influenced the reslulting framerate. For
example: If a game took 3ms to render and the fps limit was set
to 60 fps, the resulting framerate would be around 50 to 51fps,
as the limit would actually be ~19,666ms (3ms + 16,666ms fixed).

This new logic works by calculating the time it took to render the
last frame and subtracting it from the time we should wait for the
next one, which will then be our Thread.sleep() interval.

While it still relies on Thread.sleep() and its inaccuracies, this
approach is miles better than what was already in place, case in
point, jbenchmark 2.0 now locks around 59.5 to 60.3 fps in all tests
on my machine, whereas it ran at about 48.6fps on the first test,
55.3 on the second, 56.4 on the third and 52.5 on the fourth.
  • Loading branch information
AShiningRay committed Sep 15, 2024
1 parent 572a6c5 commit 1136a67
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 13 deletions.
19 changes: 18 additions & 1 deletion src/org/recompile/freej2me/Anbu.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,13 @@ public static void main(String[] args)
private boolean useSiemensControls = false;
private boolean useMotorolaControls = false;
private boolean rotateDisplay = false;

// Frame Limit Variables
private int limitFPS = 0;
private long lastRenderTime = 0;
private long requiredFrametime = 0;
private long elapsedTime = 0;
private long sleepTime = 0;

private boolean[] pressedKeys = new boolean[128];

Expand Down Expand Up @@ -75,6 +81,16 @@ public void run()
try
{
int[] data;

if(limitFPS>0)
{
requiredFrametime = 1000 / limitFPS;
elapsedTime = System.currentTimeMillis() - lastRenderTime;
sleepTime = requiredFrametime - elapsedTime;

if (sleepTime > 0) { Thread.sleep(sleepTime); }
}

// Send Frame to SDL interface
if(!config.isRunning) { data = Mobile.getPlatform().getLCD().getRGB(0, 0, lcdWidth, lcdHeight, null, 0, lcdWidth); }
else { data = config.getLCD().getRGB(0, 0, lcdWidth, lcdHeight, null, 0, lcdWidth);}
Expand All @@ -88,6 +104,8 @@ public void run()
cb += 3;
}
sdl.frame.write(frame);

lastRenderTime = System.currentTimeMillis();
}
catch (Exception e) { }
}
Expand Down Expand Up @@ -365,7 +383,6 @@ else if(useMotorolaControls)
void settingsChanged()
{
limitFPS = Integer.parseInt(config.settings.get("fps"));
if(limitFPS>0) { limitFPS = 1000 / limitFPS; }

String sound = config.settings.get("sound");
Mobile.sound = false;
Expand Down
25 changes: 18 additions & 7 deletions src/org/recompile/freej2me/FreeJ2ME.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,15 @@ public class FreeJ2ME
private boolean useSiemensControls = false;
private boolean useMotorolaControls = false;
private boolean rotateDisplay = false;

// Frame Limit Variables
private int limitFPS = 0;
private int renderHint = 0;
private long lastRenderTime = 0;
private long requiredFrametime = 0;
private long elapsedTime = 0;
private long sleepTime = 0;

// AWT GUI
private AWTGUI awtGUI;

private boolean[] pressedKeys = new boolean[128];
Expand Down Expand Up @@ -374,7 +380,6 @@ private void settingsChanged()
int h = Integer.parseInt(config.settings.get("height"));

limitFPS = Integer.parseInt(config.settings.get("fps"));
if(limitFPS>0) { limitFPS = 1000 / limitFPS; }

String sound = config.settings.get("sound");
Mobile.sound = false;
Expand Down Expand Up @@ -531,6 +536,16 @@ public void paint(Graphics g)
try
{
Graphics2D cgc = (Graphics2D)this.getGraphics();

if(limitFPS>0)
{
requiredFrametime = 1000 / limitFPS;
elapsedTime = System.currentTimeMillis() - lastRenderTime;
sleepTime = requiredFrametime - elapsedTime;

if (sleepTime > 0) { Thread.sleep(sleepTime); }
}

if (config.isRunning)
{
if(!rotateDisplay)
Expand All @@ -556,12 +571,8 @@ public void paint(Graphics g)
// Draw the rotated FB with adjusted cy and cx values
cgc.drawImage(Mobile.getPlatform().getLCD(), 0, cx, ch, cw, null);
}

if(limitFPS>0)
{
Thread.sleep(limitFPS);
}
}
lastRenderTime = System.currentTimeMillis();
}
catch (Exception e)
{
Expand Down
24 changes: 19 additions & 5 deletions src/org/recompile/freej2me/Libretro.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,14 @@ public class Libretro
private boolean useMotorolaControls = false;
private boolean rotateDisplay = false;
private boolean soundEnabled = true;

// Frame Limit Variables
private int limitFPS = 0;
private long lastRenderTime = 0;
private long requiredFrametime = 0;
private long elapsedTime = 0;
private long sleepTime = 0;

private int maxmidistreams = 32;

private boolean[] pressedKeys = new boolean[128];
Expand Down Expand Up @@ -378,17 +385,23 @@ public void run()
try
{
int[] data;

if(limitFPS>0)
{
requiredFrametime = 1000 / limitFPS;
elapsedTime = System.currentTimeMillis() - lastRenderTime;
sleepTime = requiredFrametime - elapsedTime;

if (sleepTime > 0) { Thread.sleep(sleepTime); }
}

if(config.isRunning)
{
data = config.getLCD().getRGB(0, 0, lcdWidth, lcdHeight, null, 0, lcdWidth);
}
else
{
data = surface.getRGB(0, 0, lcdWidth, lcdHeight, null, 0, lcdWidth);
if(limitFPS>0)
{
Thread.sleep(limitFPS);
}
}
int bufferLength = data.length*3;
int cb = 0;
Expand All @@ -408,6 +421,8 @@ public void run()
System.out.write(frameHeader, 0, 6);
System.out.write(frameBuffer, 0, bufferLength);
System.out.flush();

lastRenderTime = System.currentTimeMillis();
}
catch (Exception e)
{
Expand All @@ -432,7 +447,6 @@ private void settingsChanged()
int h = Integer.parseInt(config.settings.get("height"));

limitFPS = Integer.parseInt(config.settings.get("fps"));
if(limitFPS>0) { limitFPS = 1000 / limitFPS; }

String sound = config.settings.get("sound");
Mobile.sound = false;
Expand Down

0 comments on commit 1136a67

Please sign in to comment.