diff --git a/CHANGELOG.md b/CHANGELOG.md index dcf6a7218c2f239d7eb91ecd29b339500032194b..558556b0079ba56b16b4952da283d86327e67672 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * Better debug panel support +* Support for some `GET` parameters ### Changed diff --git a/README.md b/README.md index dd8077ba3b31b08c74609b59f3f9e7363703a131..aea440dc79767513863da6ba588d27be36f6f45a 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,18 @@ npm install && npm run build cd dist && python3 -m http.server ``` +## Web version + +You can use some GET parameters to control the initial behaviour of the emulator. + +| Parameter | Type | Description | +| ------------ | ------- | ------------------------------------------------------------------------------ | +| `rom_url` | String | The URL from which the initial ROM is going to be loaded, should support CORS. | +| `url` | String | The same as `url`. | +| `fullscreen` | Boolean | If the emulator should start in fullscreen mode. | +| `debug` | Boolean | If the "debugger" should start visible. | +| `keyboard` | Boolean | If the on screen keyboard should start visible. | + ## Inspiration ### Documentation diff --git a/examples/web/index.ts b/examples/web/index.ts index 16e211d8e8d759c6639f7220f4af687c12e3ca42..94c795f15cdd5db29e85598cb536c21f002f3baf 100644 --- a/examples/web/index.ts +++ b/examples/web/index.ts @@ -99,12 +99,7 @@ class GameboyEmulator extends EmulatorBase implements Emulator { private romSize: number = 0; private cartridge: Cartridge | null = null; - async main() { - // parses the current location URL as retrieves - // some of the "relevant" GET parameters for logic - const params = new URLSearchParams(window.location.search); - const romUrl = params.get("url"); - + async main({ romUrl }: { romUrl?: string }) { // initializes the WASM module, this is required // so that the global symbols become available await wasm(); @@ -426,7 +421,7 @@ class GameboyEmulator extends EmulatorBase implements Emulator { * @returns The current pixel data for the emulator display. */ get imageBuffer(): Uint8Array { - return this.gameBoy!.frame_buffer_eager(); + return this.gameBoy?.frame_buffer_eager() ?? new Uint8Array(); } get romInfo(): RomInfo { @@ -457,7 +452,7 @@ class GameboyEmulator extends EmulatorBase implements Emulator { } getTile(index: number): Uint8Array { - return this.gameBoy!.get_tile_buffer(index); + return this.gameBoy?.get_tile_buffer(index) ?? new Uint8Array(); } toggleRunning() { @@ -578,7 +573,25 @@ const wasm = async () => { }; (async () => { + // parses the current location URL as retrieves + // some of the "relevant" GET parameters for logic + const params = new URLSearchParams(window.location.search); + const romUrl = params.get("rom_url") ?? params.get("url") ?? undefined; + const fullscreen = ["1", "true", "True"].includes( + params.get("fullscreen") ?? "" + ); + const debug = ["1", "true", "True"].includes(params.get("debug") ?? ""); + const keyboard = ["1", "true", "True"].includes( + params.get("keyboard") ?? "" + ); + const emulator = new GameboyEmulator(); - startApp("app", emulator, BACKGROUNDS); - await emulator.main(); + startApp("app", { + emulator: emulator, + fullscreen: fullscreen, + debug: debug, + keyboard: keyboard, + backgrounds: BACKGROUNDS + }); + await emulator.main({ romUrl: romUrl }); })(); diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx index 601b56f73c0a8cdb4c0f54aa8005d1972f8d97a2..13fc2cd41d0551e10d5a0a0174628510fc7e9a82 100644 --- a/examples/web/react/app.tsx +++ b/examples/web/react/app.tsx @@ -241,6 +241,9 @@ export enum PixelFormat { type AppProps = { emulator: Emulator; + fullscreen?: boolean; + debug?: boolean; + keyboard?: boolean; backgrounds?: string[]; }; @@ -248,9 +251,15 @@ const isTouchDevice = () => { return "ontouchstart" in window || navigator.maxTouchPoints > 0; }; -export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { +export const App: FC<AppProps> = ({ + emulator, + fullscreen = false, + debug = false, + keyboard = false, + backgrounds = ["264653"] +}) => { const [paused, setPaused] = useState(false); - const [fullscreen, setFullscreen] = useState(false); + const [fullscreenState, setFullscreenState] = useState(fullscreen); const [backgroundIndex, setBackgroundIndex] = useState(0); const [romInfo, setRomInfo] = useState<RomInfo>({}); const [framerate, setFramerate] = useState(0); @@ -261,9 +270,11 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { const [toastText, setToastText] = useState<string>(); const [toastError, setToastError] = useState(false); const [toastVisible, setToastVisible] = useState(false); - const [keyboardVisible, setKeyboardVisible] = useState(isTouchDevice()); + const [keyboardVisible, setKeyboardVisible] = useState( + isTouchDevice() || keyboard + ); const [infoVisible, setInfoVisible] = useState(true); - const [debugVisible, setDebugVisible] = useState(false); + const [debugVisible, setDebugVisible] = useState(debug); const toastCounterRef = useRef(0); const frameRef = useRef<boolean>(false); @@ -277,11 +288,11 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { useEffect(() => { switch (keyaction) { case "Escape": - setFullscreen(false); + setFullscreenState(false); setKeyaction(undefined); break; case "Fullscreen": - setFullscreen(!fullscreen); + setFullscreenState(!fullscreenState); setKeyaction(undefined); break; } @@ -411,7 +422,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { ); }; const onFullscreenClick = () => { - setFullscreen(!fullscreen); + setFullscreenState(!fullscreenState); }; const onKeyboardClick = () => { setKeyboardVisible(!keyboardVisible); @@ -446,7 +457,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { }); }; const onMinimize = () => { - setFullscreen(!fullscreen); + setFullscreenState(!fullscreenState); }; const onKeyDown = (key: string) => { emulator.keyPress(key); @@ -496,7 +507,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { left={ <div className="display-container"> <Display - fullscreen={fullscreen} + fullscreen={fullscreenState} onDrawHandler={onDrawHandler} onClearHandler={onClearHandler} onMinimize={onMinimize} @@ -728,16 +739,33 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { export const startApp = ( element: string, - emulator: Emulator, - backgrounds: string[] + { + emulator, + fullscreen = false, + debug = false, + keyboard = false, + backgrounds = [] + }: { + emulator: Emulator; + fullscreen?: boolean; + debug?: boolean; + keyboard?: boolean; + backgrounds: string[]; + } ) => { const elementRef = document.getElementById(element); - if (!elementRef) { - return; - } + if (!elementRef) return; const root = ReactDOM.createRoot(elementRef); - root.render(<App emulator={emulator} backgrounds={backgrounds} />); + root.render( + <App + emulator={emulator} + fullscreen={fullscreen} + debug={debug} + keyboard={keyboard} + backgrounds={backgrounds} + /> + ); }; export default App;