From c29a9a4a2b7eed1df8286b49317791479e639734 Mon Sep 17 00:00:00 2001
From: Corwin <corwin@kuiper.dev>
Date: Wed, 10 Apr 2024 18:30:12 +0100
Subject: [PATCH 1/2] add controller support

---
 website/agb/src/app/mgba/mgba.tsx             |  2 +
 .../agb/src/app/mgba/useController.hook.ts    | 98 +++++++++++++++++++
 2 files changed, 100 insertions(+)
 create mode 100644 website/agb/src/app/mgba/useController.hook.ts

diff --git a/website/agb/src/app/mgba/mgba.tsx b/website/agb/src/app/mgba/mgba.tsx
index 0c16bdf2..974f5668 100644
--- a/website/agb/src/app/mgba/mgba.tsx
+++ b/website/agb/src/app/mgba/mgba.tsx
@@ -9,6 +9,7 @@ import mGBA, { mGBAEmulator } from "./vendor/mgba";
 import { GbaKey, KeyBindings } from "./bindings";
 import { styled } from "styled-components";
 import { useFrameSkip } from "./useFrameSkip.hook";
+import { useController } from "./useController.hook";
 
 type Module = any;
 
@@ -105,6 +106,7 @@ export const Mgba = forwardRef<MgbaHandle, MgbaProps>(
     }, [state]);
 
     useFrameSkip(mgbaModule);
+    useController(mgbaModule);
 
     useEffect(() => {
       if (!gameLoaded) return;
diff --git a/website/agb/src/app/mgba/useController.hook.ts b/website/agb/src/app/mgba/useController.hook.ts
new file mode 100644
index 00000000..ff874e7c
--- /dev/null
+++ b/website/agb/src/app/mgba/useController.hook.ts
@@ -0,0 +1,98 @@
+import { MutableRefObject, useEffect } from "react";
+import { mGBAEmulator } from "./vendor/mgba";
+import { GbaKey } from "./bindings";
+
+export function useController(mgbaModule: MutableRefObject<mGBAEmulator>) {
+    useEffect(() => {
+        let stopped = false;
+
+
+        let previouslyPressedButtons = new Set<GbaKey>();
+
+        function raf(time: DOMHighResTimeStamp) {
+
+            const controllers = navigator.getGamepads();
+            const currentlyPressed = new Set<GbaKey>();
+            for (let controller of controllers) {
+                if (!controller) continue;
+
+
+                if (controller.buttons[1].pressed) {
+                    currentlyPressed.add(GbaKey.A);
+                }
+                if (controller.buttons[0].pressed) {
+                    currentlyPressed.add(GbaKey.B);
+                }
+                if (controller.buttons[5].pressed) {
+                    currentlyPressed.add(GbaKey.R);
+                }
+                if (controller.buttons[4].pressed) {
+                    currentlyPressed.add(GbaKey.L);
+                }
+
+                if (controller.buttons[8].pressed) {
+                    currentlyPressed.add(GbaKey.Select);
+                }
+
+                if (controller.buttons[9].pressed) {
+                    currentlyPressed.add(GbaKey.Start);
+                }
+
+                if (controller.buttons[12].pressed) {
+                    currentlyPressed.add(GbaKey.Up);
+                }
+                if (controller.buttons[13].pressed) {
+                    currentlyPressed.add(GbaKey.Down);
+                }
+                if (controller.buttons[14].pressed) {
+                    currentlyPressed.add(GbaKey.Left);
+                }
+                if (controller.buttons[15].pressed) {
+                    currentlyPressed.add(GbaKey.Right);
+                }
+
+                if (controller.axes[0] < -.5) {
+                    currentlyPressed.add(GbaKey.Left);
+                }
+                if (controller.axes[0] > .5) {
+                    currentlyPressed.add(GbaKey.Right);
+                }
+                if (controller.axes[1] < -.5) {
+                    currentlyPressed.add(GbaKey.Up);
+                }
+                if (controller.axes[1] > .5) {
+                    currentlyPressed.add(GbaKey.Down);
+                }
+
+
+            }
+
+            for (let oldButton of previouslyPressedButtons) {
+                if (!currentlyPressed.has(oldButton)) {
+                    mgbaModule.current.buttonUnpress(oldButton);
+                }
+            }
+
+            for (let newButton of currentlyPressed) {
+                if (!previouslyPressedButtons.has(newButton)) {
+                    mgbaModule.current.buttonPress(newButton);
+                }
+            }
+
+            previouslyPressedButtons = currentlyPressed;
+
+            if (!stopped) {
+                window.requestAnimationFrame(raf);
+            }
+        }
+
+        function gamepadConnectedEvent() {
+
+        }
+
+        window.addEventListener("gamepadconnected", gamepadConnectedEvent);
+
+        window.requestAnimationFrame(raf);
+        return () => { stopped = true; window.removeEventListener("gamepadconnected", gamepadConnectedEvent); };
+    }, [mgbaModule]);
+}
\ No newline at end of file

From 4e4e32300264d9542d0324810f904d3412c5c38e Mon Sep 17 00:00:00 2001
From: Corwin <corwin@kuiper.dev>
Date: Wed, 10 Apr 2024 18:31:24 +0100
Subject: [PATCH 2/2] format ts files

---
 .../agb/src/app/mgba/useController.hook.ts    | 164 +++++++++---------
 website/agb/src/app/mgba/useFrameSkip.hook.ts |  73 ++++----
 .../agb/src/app/mgba/useLocalStorage.hook.ts  |   8 +-
 website/agb/src/app/useClientValue.hook.ts    |  12 +-
 4 files changed, 125 insertions(+), 132 deletions(-)

diff --git a/website/agb/src/app/mgba/useController.hook.ts b/website/agb/src/app/mgba/useController.hook.ts
index ff874e7c..4555d526 100644
--- a/website/agb/src/app/mgba/useController.hook.ts
+++ b/website/agb/src/app/mgba/useController.hook.ts
@@ -3,96 +3,92 @@ import { mGBAEmulator } from "./vendor/mgba";
 import { GbaKey } from "./bindings";
 
 export function useController(mgbaModule: MutableRefObject<mGBAEmulator>) {
-    useEffect(() => {
-        let stopped = false;
+  useEffect(() => {
+    let stopped = false;
 
+    let previouslyPressedButtons = new Set<GbaKey>();
 
-        let previouslyPressedButtons = new Set<GbaKey>();
+    function raf(time: DOMHighResTimeStamp) {
+      const controllers = navigator.getGamepads();
+      const currentlyPressed = new Set<GbaKey>();
+      for (let controller of controllers) {
+        if (!controller) continue;
 
-        function raf(time: DOMHighResTimeStamp) {
-
-            const controllers = navigator.getGamepads();
-            const currentlyPressed = new Set<GbaKey>();
-            for (let controller of controllers) {
-                if (!controller) continue;
-
-
-                if (controller.buttons[1].pressed) {
-                    currentlyPressed.add(GbaKey.A);
-                }
-                if (controller.buttons[0].pressed) {
-                    currentlyPressed.add(GbaKey.B);
-                }
-                if (controller.buttons[5].pressed) {
-                    currentlyPressed.add(GbaKey.R);
-                }
-                if (controller.buttons[4].pressed) {
-                    currentlyPressed.add(GbaKey.L);
-                }
-
-                if (controller.buttons[8].pressed) {
-                    currentlyPressed.add(GbaKey.Select);
-                }
-
-                if (controller.buttons[9].pressed) {
-                    currentlyPressed.add(GbaKey.Start);
-                }
-
-                if (controller.buttons[12].pressed) {
-                    currentlyPressed.add(GbaKey.Up);
-                }
-                if (controller.buttons[13].pressed) {
-                    currentlyPressed.add(GbaKey.Down);
-                }
-                if (controller.buttons[14].pressed) {
-                    currentlyPressed.add(GbaKey.Left);
-                }
-                if (controller.buttons[15].pressed) {
-                    currentlyPressed.add(GbaKey.Right);
-                }
-
-                if (controller.axes[0] < -.5) {
-                    currentlyPressed.add(GbaKey.Left);
-                }
-                if (controller.axes[0] > .5) {
-                    currentlyPressed.add(GbaKey.Right);
-                }
-                if (controller.axes[1] < -.5) {
-                    currentlyPressed.add(GbaKey.Up);
-                }
-                if (controller.axes[1] > .5) {
-                    currentlyPressed.add(GbaKey.Down);
-                }
-
-
-            }
-
-            for (let oldButton of previouslyPressedButtons) {
-                if (!currentlyPressed.has(oldButton)) {
-                    mgbaModule.current.buttonUnpress(oldButton);
-                }
-            }
-
-            for (let newButton of currentlyPressed) {
-                if (!previouslyPressedButtons.has(newButton)) {
-                    mgbaModule.current.buttonPress(newButton);
-                }
-            }
-
-            previouslyPressedButtons = currentlyPressed;
-
-            if (!stopped) {
-                window.requestAnimationFrame(raf);
-            }
+        if (controller.buttons[1].pressed) {
+          currentlyPressed.add(GbaKey.A);
+        }
+        if (controller.buttons[0].pressed) {
+          currentlyPressed.add(GbaKey.B);
+        }
+        if (controller.buttons[5].pressed) {
+          currentlyPressed.add(GbaKey.R);
+        }
+        if (controller.buttons[4].pressed) {
+          currentlyPressed.add(GbaKey.L);
         }
 
-        function gamepadConnectedEvent() {
-
+        if (controller.buttons[8].pressed) {
+          currentlyPressed.add(GbaKey.Select);
         }
 
-        window.addEventListener("gamepadconnected", gamepadConnectedEvent);
+        if (controller.buttons[9].pressed) {
+          currentlyPressed.add(GbaKey.Start);
+        }
 
+        if (controller.buttons[12].pressed) {
+          currentlyPressed.add(GbaKey.Up);
+        }
+        if (controller.buttons[13].pressed) {
+          currentlyPressed.add(GbaKey.Down);
+        }
+        if (controller.buttons[14].pressed) {
+          currentlyPressed.add(GbaKey.Left);
+        }
+        if (controller.buttons[15].pressed) {
+          currentlyPressed.add(GbaKey.Right);
+        }
+
+        if (controller.axes[0] < -0.5) {
+          currentlyPressed.add(GbaKey.Left);
+        }
+        if (controller.axes[0] > 0.5) {
+          currentlyPressed.add(GbaKey.Right);
+        }
+        if (controller.axes[1] < -0.5) {
+          currentlyPressed.add(GbaKey.Up);
+        }
+        if (controller.axes[1] > 0.5) {
+          currentlyPressed.add(GbaKey.Down);
+        }
+      }
+
+      for (let oldButton of previouslyPressedButtons) {
+        if (!currentlyPressed.has(oldButton)) {
+          mgbaModule.current.buttonUnpress(oldButton);
+        }
+      }
+
+      for (let newButton of currentlyPressed) {
+        if (!previouslyPressedButtons.has(newButton)) {
+          mgbaModule.current.buttonPress(newButton);
+        }
+      }
+
+      previouslyPressedButtons = currentlyPressed;
+
+      if (!stopped) {
         window.requestAnimationFrame(raf);
-        return () => { stopped = true; window.removeEventListener("gamepadconnected", gamepadConnectedEvent); };
-    }, [mgbaModule]);
-}
\ No newline at end of file
+      }
+    }
+
+    function gamepadConnectedEvent() {}
+
+    window.addEventListener("gamepadconnected", gamepadConnectedEvent);
+
+    window.requestAnimationFrame(raf);
+    return () => {
+      stopped = true;
+      window.removeEventListener("gamepadconnected", gamepadConnectedEvent);
+    };
+  }, [mgbaModule]);
+}
diff --git a/website/agb/src/app/mgba/useFrameSkip.hook.ts b/website/agb/src/app/mgba/useFrameSkip.hook.ts
index 9f96d447..8f75309f 100644
--- a/website/agb/src/app/mgba/useFrameSkip.hook.ts
+++ b/website/agb/src/app/mgba/useFrameSkip.hook.ts
@@ -1,53 +1,48 @@
 import { MutableRefObject, useEffect } from "react";
 import { mGBAEmulator } from "./vendor/mgba";
 
-
 export function useFrameSkip(mgbaModule: MutableRefObject<mGBAEmulator>) {
-    useEffect(() => {
-        let previous: number | undefined = undefined;
-        let stopped = false;
-        let smoothedFrameTime = 60;
+  useEffect(() => {
+    let previous: number | undefined = undefined;
+    let stopped = false;
+    let smoothedFrameTime = 60;
 
-        let totalTime = 0;
-        let paused = false;
+    let totalTime = 0;
+    let paused = false;
 
-        function raf(time: DOMHighResTimeStamp) {
-            if (previous) {
-                const delta = time - previous;
+    function raf(time: DOMHighResTimeStamp) {
+      if (previous) {
+        const delta = time - previous;
 
-                smoothedFrameTime = (smoothedFrameTime * 3 + delta) / 4;
+        smoothedFrameTime = (smoothedFrameTime * 3 + delta) / 4;
 
-                const smoothedFrameRate = Math.round(1 / (smoothedFrameTime / 1000));
+        const smoothedFrameRate = Math.round(1 / (smoothedFrameTime / 1000));
 
+        totalTime += 1 / smoothedFrameRate;
 
-                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);
-            }
+        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);
-        return () => { stopped = true; };
-    }, [mgbaModule]);
+      }
+    }
 
-
-
-}
\ No newline at end of file
+    window.requestAnimationFrame(raf);
+    return () => {
+      stopped = true;
+    };
+  }, [mgbaModule]);
+}
diff --git a/website/agb/src/app/mgba/useLocalStorage.hook.ts b/website/agb/src/app/mgba/useLocalStorage.hook.ts
index 5d5e247c..5a13148e 100644
--- a/website/agb/src/app/mgba/useLocalStorage.hook.ts
+++ b/website/agb/src/app/mgba/useLocalStorage.hook.ts
@@ -1,7 +1,9 @@
 import { useCallback, useState } from "react";
 
-export function useLocalStorage<T>(defaultValue: T,
-  appName: string): [T, (newValue: T) => void] {
+export function useLocalStorage<T>(
+  defaultValue: T,
+  appName: string
+): [T, (newValue: T) => void] {
   const [value, setValue] = useState(() => {
     try {
       const storageValue = localStorage.getItem(appName);
@@ -19,7 +21,7 @@ export function useLocalStorage<T>(defaultValue: T,
     setValue(newValue);
     try {
       localStorage.setItem(appName, JSON.stringify(newValue));
-    } catch { }
+    } catch {}
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, []);
 
diff --git a/website/agb/src/app/useClientValue.hook.ts b/website/agb/src/app/useClientValue.hook.ts
index 79f6d95e..cb0c395b 100644
--- a/website/agb/src/app/useClientValue.hook.ts
+++ b/website/agb/src/app/useClientValue.hook.ts
@@ -1,10 +1,10 @@
 import { useEffect, useState } from "react";
 
 export function useClientValue<T>(fn: () => T) {
-    const [value, setValue] = useState<T>();
-    useEffect(() => {
-        setValue(fn());
-    }, [fn]);
+  const [value, setValue] = useState<T>();
+  useEffect(() => {
+    setValue(fn());
+  }, [fn]);
 
-    return value;
-}
\ No newline at end of file
+  return value;
+}