From 8cf334bd444cd1135b76387870c332f92cd02aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Sat, 29 Oct 2022 02:17:04 +0100 Subject: [PATCH] refactor: more ROM information display --- examples/web/index.ts | 69 ++++++++++--------- examples/web/react/app.tsx | 57 +++++++++++++-- .../web/react/components/display/display.css | 2 +- 3 files changed, 89 insertions(+), 39 deletions(-) diff --git a/examples/web/index.ts b/examples/web/index.ts index f7951ea9..94712ccb 100644 --- a/examples/web/index.ts +++ b/examples/web/index.ts @@ -1,6 +1,18 @@ -import { Emulator, Observable, PixelFormat, startApp } from "./react/app"; - -import { default as _wasm, GameBoy, PadKey, PpuMode } from "./lib/boytacean.js"; +import { + Emulator, + Observable, + PixelFormat, + RomInfo, + startApp +} from "./react/app"; + +import { + Cartridge, + default as _wasm, + GameBoy, + PadKey, + PpuMode +} from "./lib/boytacean.js"; import info from "./package.json"; declare const require: any; @@ -82,6 +94,7 @@ class GameboyEmulator extends Observable implements Emulator { private romName: string | null = null; private romData: Uint8Array | null = null; private romSize: number = 0; + private cartridge: Cartridge | null = null; async main() { // initializes the WASM module, this is required @@ -90,7 +103,6 @@ class GameboyEmulator extends Observable implements Emulator { // initializes the complete set of sub-systems // and registers the event handlers - await this.buildVisuals(); await this.init(); await this.register(); @@ -309,7 +321,7 @@ class GameboyEmulator extends Observable implements Emulator { // updates the complete set of global information that // is going to be displayed this.setEngine(this.engine!); - this.setRom(romName!, romData!); + this.setRom(romName!, romData!, cartridge); this.setLogicFrequency(this.logicFrequency); this.setFps(this.fps); @@ -318,26 +330,6 @@ class GameboyEmulator extends Observable implements Emulator { if (restore) this.resume(); } - async buildVisuals() { - /* KeyValue.create("ROM", "-", { id: "diag:rom-name" }).mount(".diag"); - KeyValue.create("ROM Size", "-", { id: "diag:rom-size" }).mount( - ".diag" - ); - KeyValue.create("Framerate", "-", { id: "diag:framerate" }).mount( - ".diag" - ); - KeyValue.create("ROM Type", "-", { id: "diag:rom-type" }).mount( - ".diag" - ); - KeySwitch.create("Tobias", ["1", "2", "3"], { - id: "diag:tobias" - }).mount(".diag"); - - Button.create("Tobias", require("./res/close.svg")) - .bind("click", () => alert("Hello World")) - .mount(".button-area");*/ - } - // @todo remove this method, or at least most of it async register() { await Promise.all([ @@ -916,13 +908,13 @@ class GameboyEmulator extends Observable implements Emulator { document.getElementById("engine")!.textContent = name; } - setRom(name: string, data: Uint8Array) { + setRom(name: string, data: Uint8Array, cartridge: Cartridge) { this.romName = name; this.romData = data; this.romSize = data.length; - //@todo update this one - //Component.get<KeyValue>("diag:rom-name").value = name; - //Component.get<KeyValue>("diag:rom-size").value = `${data.length} bytes`; + this.cartridge = cartridge; + + this.trigger("rom:loaded"); } setLogicFrequency(value: number) { @@ -936,8 +928,6 @@ class GameboyEmulator extends Observable implements Emulator { if (value < 0) this.showToast("Invalid FPS value!", true); value = Math.max(value, 0); this.fps = value; - //@todo - //Component.get<KeyValue>("diag:framerate").value = `${value} FPS`; } getName() { @@ -966,6 +956,23 @@ class GameboyEmulator extends Observable implements Emulator { return this.gameBoy!.frame_buffer_eager(); } + getRomInfo(): RomInfo { + return { + name: this.romName || undefined, + data: this.romData || undefined, + size: this.romData?.length, + extra: { + romType: this.cartridge?.rom_type_s(), + romSize: this.cartridge?.rom_size_s(), + ramSize: this.cartridge?.ram_size_s() + } + }; + } + + getFramerate(): number { + return this.fps; + } + toggleRunning() { if (this.paused) { this.resume(); diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx index dd4e852c..5b171ac9 100644 --- a/examples/web/react/app.tsx +++ b/examples/web/react/app.tsx @@ -46,17 +46,31 @@ export class Observable { } } +export type RomInfo = { + name?: string; + data?: Uint8Array; + size?: number; + extra?: Record<string, string | undefined>; +}; + +export interface ObservableI { + bind(event: string, callback: Callback<this>): void; + trigger(event: string): void; +} + /** * Top level interface that declares the main abstract * interface of an emulator structured entity. * Should allow typical hardware operations to be performed. */ -export interface Emulator extends Observable { +export interface Emulator extends ObservableI { getName(): string; getVersion(): string; getVersionUrl(): string; getPixelFormat(): PixelFormat; getImageBuffer(): Uint8Array; + getRomInfo(): RomInfo; + getFramerate(): number; toggleRunning(): void; pause(): void; resume(): void; @@ -81,7 +95,9 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { const [paused, setPaused] = useState(false); const [fullscreen, setFullscreen] = useState(false); const [backgroundIndex, setBackgroundIndex] = useState(0); - const intervalRef = useRef<number | undefined>(undefined); + const [romInfo, setRomInfo] = useState<RomInfo>({}); + const [framerate, setFramerate] = useState(0); + const frameRef = useRef<boolean>(false); const getPauseText = () => (paused ? "Resume" : "Pause"); const getPauseIcon = () => paused ? require("../res/play.svg") : require("../res/pause.svg"); @@ -103,10 +119,11 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { setFullscreen(!fullscreen); }; const onDrawHandler = (handler: DrawHandler) => { - if (intervalRef.current) return; - intervalRef.current = 1; + if (frameRef.current) return; + frameRef.current = true; emulator.bind("frame", () => { handler(emulator.getImageBuffer(), PixelFormat.RGB); + setFramerate(emulator.getFramerate()); }); }; useEffect(() => { @@ -118,6 +135,10 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { setFullscreen(false); } }); + emulator.bind("rom:loaded", () => { + const romInfo = emulator.getRomInfo(); + setRomInfo(romInfo); + }); }, []); return ( <div className="app"> @@ -129,7 +150,7 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { </Footer> <PanelSplit left={ - <div style={{marginTop: 78}}> + <div style={{ marginTop: 78 }}> <Display fullscreen={fullscreen} onDrawHandler={onDrawHandler} @@ -206,8 +227,30 @@ export const App: FC<AppProps> = ({ emulator, backgrounds = ["264653"] }) => { /> </ButtonContainer> <Info> - <Pair key="tobias" name={"Tobias"} value={"Matias"} /> - <Pair key="matias" name={"Matias"} value={"3"} /> + <Pair + key="rom" + name={"ROM"} + value={romInfo.name ?? "-"} + /> + <Pair + key="rom-size" + name={"ROM Size"} + value={romInfo.name ? `${romInfo.size} bytes` : "-"} + /> + <Pair + key="rom-type" + name={"ROM Type"} + value={ + romInfo.extra?.romType + ? `${romInfo.extra?.romType}` + : "-" + } + /> + <Pair + key="framerate" + name={"Framerate"} + value={`${framerate} fps`} + /> <Pair key="button-tobias" name={"Button Increment"} diff --git a/examples/web/react/components/display/display.css b/examples/web/react/components/display/display.css index 8965c18d..7ad04880 100644 --- a/examples/web/react/components/display/display.css +++ b/examples/web/react/components/display/display.css @@ -43,7 +43,7 @@ font-size: 0px; padding: 8px 8px 8px 8px; box-sizing: content-box; - transition: width 0.35s cubic-bezier(0.075, 0.82, 0.165, 1), height 0.35s cubic-bezier(0.075, 0.82, 0.165, 1), top 0.35s cubic-bezier(0.075, 0.82, 0.165, 1), left 0.35s cubic-bezier(0.075, 0.82, 0.165, 1); + transition: width 0.35s cubic-bezier(0.075, 0.82, 0.165, 1), height 0.35s cubic-bezier(0.075, 0.82, 0.165, 1); } .display.fullscreen > .display-frame { -- GitLab