diff --git a/website/app/src/mgba.tsx b/website/app/src/mgba.tsx index 29b17681..7018ee6b 100644 --- a/website/app/src/mgba.tsx +++ b/website/app/src/mgba.tsx @@ -5,10 +5,10 @@ import { useRef, useState, } from "react"; -import mGBA from "./vendor/mgba"; +import mGBA, { mGBAEmulator } from "./vendor/mgba"; import { GbaKey, KeyBindings } from "./bindings"; import { styled } from "styled-components"; -import { useSmoothedFramerate } from "./useSmoothedFramerate.hook"; +import { useFrameSkip } from "./useFrameSkip.hook"; type Module = any; @@ -41,18 +41,10 @@ export interface MgbaHandle { buttonRelease: (key: GbaKey) => void; } -const whichFrameSkip = (frameRate: number): number | undefined => { - if ((frameRate + 5) % 60 <= 10) { - // framerate close to multiple of 60 - // use frameskip - return Math.round(frameRate / 60); - } -}; - export const Mgba = forwardRef( ({ gameUrl, volume, controls, paused }, ref) => { const canvas = useRef(null); - const mgbaModule = useRef({}); + const mgbaModule = useRef({} as mGBAEmulator); const [state, setState] = useState(MgbaState.Uninitialised); const [gameLoaded, setGameLoaded] = useState(false); @@ -101,23 +93,7 @@ export const Mgba = forwardRef( }; }, [state]); - const frameRate = useSmoothedFramerate(); - const frameSkipToUse = whichFrameSkip(frameRate); - - useEffect(() => { - if (!gameLoaded) return; - - if (frameSkipToUse) { - // framerate close to multiple of 60 - // use frameskip - console.log("Using frameskip"); - mgbaModule.current.setMainLoopTiming(1, frameSkipToUse); - } else { - // frame rate not close to multiple of 60, use timeout - console.log("Using timeout"); - mgbaModule.current.setMainLoopTiming(0, 1000 / 59.727500569606); - } - }, [frameSkipToUse, gameLoaded]); + useFrameSkip(mgbaModule); useEffect(() => { if (!gameLoaded) return; diff --git a/website/app/src/useFrameSkip.hook.ts b/website/app/src/useFrameSkip.hook.ts new file mode 100644 index 00000000..ff8c9d85 --- /dev/null +++ b/website/app/src/useFrameSkip.hook.ts @@ -0,0 +1,54 @@ +import { MutableRefObject, useEffect } from "react"; +import { mGBAEmulator } from "./vendor/mgba"; + + +export const useFrameSkip = (mgbaModule: MutableRefObject) => { + useEffect(() => { + let previous: number | undefined = undefined; + let stopped = false; + let smoothedFrameTime = 60; + + let totalTime = 0; + let paused = false; + + const raf = (time: DOMHighResTimeStamp) => { + if (previous) { + const delta = time - previous; + console.log(delta); + + smoothedFrameTime = (smoothedFrameTime * 3 + delta) / 4; + + const smoothedFrameRate = Math.round(1 / (smoothedFrameTime / 1000)); + + + totalTime += 1 / smoothedFrameRate; + + if (totalTime >= 1 / 60) { + totalTime -= 1 / 60; + if (paused) { + mgbaModule.current.resumeGame(); + paused = false; + } + } else { + if (!paused) { + mgbaModule.current.pauseGame(); + paused = true; + } + } + + + } + previous = time; + + if (!stopped) { + window.requestAnimationFrame(raf); + } + } + + window.requestAnimationFrame(raf); + return () => { stopped = true; } + }, [mgbaModule]); + + + +} \ No newline at end of file diff --git a/website/app/src/useSmoothedFramerate.hook.ts b/website/app/src/useSmoothedFramerate.hook.ts deleted file mode 100644 index 80666e8f..00000000 --- a/website/app/src/useSmoothedFramerate.hook.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { useEffect, useState } from "react"; - - -export const useSmoothedFramerate = (): number => { - - const [smoothedFrameTime, setSmoothedFrameTime] = useState(60); - - useEffect(() => { - - let previous: number | undefined = undefined; - let stopped = false; - - const raf = (time: DOMHighResTimeStamp) => { - if (previous) { - let delta = time - previous; - - setSmoothedFrameTime((time) => (time * 3 + delta) / 4); - } - previous = time; - - - if (!stopped) { - window.requestAnimationFrame(raf); - } - } - - window.requestAnimationFrame(raf); - - return () => { stopped = true; } - - }, []); - - - return Math.round(1 / (smoothedFrameTime / 1000)); -} \ No newline at end of file