From 16fa0aa5a631d2dcff22e823bca87036ed0c4b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com> Date: Mon, 14 Nov 2022 11:50:11 +0000 Subject: [PATCH] refactor: extracted structs out of main file --- examples/web/gb.ts | 2 +- examples/web/react/app.tsx | 271 +----------------- .../web/react/components/display/display.tsx | 2 +- examples/web/react/components/tiles/tiles.tsx | 2 +- examples/web/react/structs.ts | 263 +++++++++++++++++ 5 files changed, 273 insertions(+), 267 deletions(-) create mode 100644 examples/web/react/structs.ts diff --git a/examples/web/gb.ts b/examples/web/gb.ts index 6f5199d3..c627f11d 100644 --- a/examples/web/gb.ts +++ b/examples/web/gb.ts @@ -4,7 +4,7 @@ import { Feature, PixelFormat, RomInfo -} from "./react/app"; +} from "./react/structs"; import { PALETTES } from "./palettes"; import { diff --git a/examples/web/react/app.tsx b/examples/web/react/app.tsx index 89ab434a..0a0229a9 100644 --- a/examples/web/react/app.tsx +++ b/examples/web/react/app.tsx @@ -1,8 +1,6 @@ import React, { FC, useEffect, useRef, useState } from "react"; import ReactDOM from "react-dom/client"; -const FREQUENCY_DELTA = 100000; - declare const require: any; import { @@ -29,271 +27,16 @@ import { Title, Toast } from "./components"; +import { + Emulator, + Feature, + FREQUENCY_DELTA, + PixelFormat, + RomInfo +} from "./structs"; import "./app.css"; -export type Callback<T> = (owner: T, params?: any) => void; - -/** - * Abstract class that implements the basic functionality - * part of the definition of the Observer pattern. - * - * @see {@link https://en.wikipedia.org/wiki/Observer_pattern} - */ -export class Observable { - private events: Record<string, [Callback<this>]> = {}; - - bind(event: string, callback: Callback<this>) { - const callbacks = this.events[event] ?? []; - if (callbacks.includes(callback)) return; - callbacks.push(callback); - this.events[event] = callbacks; - } - - unbind(event: string, callback: Callback<this>) { - const callbacks = this.events[event] ?? []; - if (!callbacks.includes(callback)) return; - const index = callbacks.indexOf(callback); - callbacks.splice(index, 1); - this.events[event] = callbacks; - } - - trigger(event: string, params?: any) { - const callbacks = this.events[event] ?? []; - callbacks.forEach((c) => c(this, params)); - } -} - -export type RomInfo = { - name?: string; - data?: Uint8Array; - size?: number; - extra?: Record<string, string | undefined>; -}; - -export type BenchmarkResult = { - delta: number; - count: number; - cycles: number; - frequency_mhz: number; -}; - -export enum Feature { - Debug = 1, - Palettes, - Benchmark, - Keyboard, - KeyboardChip8, - KeyboardGB -} - -export interface ObservableI { - bind(event: string, callback: Callback<this>): void; - unbind(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 ObservableI { - /** - * The descriptive name of the emulator. - */ - get name(): string; - - /** - * The name of the the hardware that is being emulated - * by the emulator (eg: Super Nintendo). - */ - get device(): string; - - /** - * A URL to a website that describes the device that is - * being emulated by the emulator (eg: Wikipedia link). - */ - get deviceUrl(): string | undefined; - - /** - * A semantic version string for the current version - * of the emulator. - * - * @see {@link https://semver.org} - */ - get version(): string; - - /** - * The URL to the page describing the current version - * of the emulator. - */ - get versionUrl(): string | undefined; - - get repository(): string | undefined; - - get repositoryUrl(): string | undefined; - - /** - * The features available and compatible with the emulator, - * these values will influence the associated GUIs. - */ - get features(): Feature[]; - - /** - * The complete set of engine names that can be used - * in the re-boot operation. - */ - get engines(): string[]; - - /** - * The name of the current execution engine being used - * by the emulator. - */ - get engine(): string | null; - - /** - * The complete set of file extensions that this emulator - * supports. - */ - get romExts(): string[]; - - /** - * The pixel format of the emulator's display - * image buffer (eg: RGB). - */ - get pixelFormat(): PixelFormat; - - /** - * Gets the complete image buffer as a sequence of - * bytes that respects the current pixel format from - * `getPixelFormat()`. This method returns an in memory - * pointer to the heap and not a copy. - */ - get imageBuffer(): Uint8Array; - - /** - * Gets information about the ROM that is currently - * loaded in the emulator, using a structure containing - * the information about the ROM that is currently - * loaded in the emulator. - */ - get romInfo(): RomInfo; - - /** - * The current CPU frequency (logic) of the emulator, - * should impact other elements of the emulator. - */ - get frequency(): number; - set frequency(value: number); - - /** - * The recommended frequency delta in hertz for scale up - * and scale down operations in the CPU frequency. - */ - get frequencyDelta(): number | null; - - /** - * The current logic framerate of the running emulator. - */ - get framerate(): number; - - /** - * A dictionary that contains the register names associated - * with their value either as strings or numbers. - */ - get registers(): Record<string, string | number>; - - /** - * Obtains the pixel buffer for the VRAM tile at the given - * index. - * - * @param index The index of the tile to obtain pixel buffer. - * @returns The pixel buffer of the tile at the given index. - */ - getTile(index: number): Uint8Array; - - /** - * Boot (or reboots) the emulator according to the provided - * set of options. - * - * @param options The options that are going to be used for - * the booting operation of the emulator. - */ - boot(options: any): void; - - /** - * Toggle the running state of the emulator between paused - * and running, prevents consumers from the need to access - * the current running state of the emulator to implement - * a logic toggle. - */ - toggleRunning(): void; - pause(): void; - resume(): void; - - /** - * Resets the emulator machine to the start state and - * re-loads the ROM that is currently set in the emulator. - */ - reset(): void; - - keyPress(key: string): void; - - keyLift(key: string): void; - - /** - * Changes the palette of the emulator to the "next" one. - */ - changePalette?: { (): void }; - - /** - * Runs a benchmark operation in the emulator, effectively - * measuring the performance of it. - * - * @param count The number of benchmark iterations to be - * run, increasing this value will make the benchmark take - * more time to be executed. - * @returns The result metrics from the benchmark run. - */ - benchmark?: { (count?: number): BenchmarkResult }; -} - -export class EmulatorBase extends Observable { - get deviceUrl(): string | undefined { - return undefined; - } - - get versionUrl(): string | undefined { - return undefined; - } - - get repository(): string | undefined { - return undefined; - } - - get repositoryUrl(): string | undefined { - return undefined; - } - - get features(): Feature[] { - return []; - } - - get frequencyDelta(): number | null { - return FREQUENCY_DELTA; - } -} - -/** - * Enumeration that describes the multiple pixel - * formats and the associated size in bytes. - */ -export enum PixelFormat { - RGB = 3, - RGBA = 4 -} - type AppProps = { emulator: Emulator; fullscreen?: boolean; diff --git a/examples/web/react/components/display/display.tsx b/examples/web/react/components/display/display.tsx index 3aacfda2..4180efb4 100644 --- a/examples/web/react/components/display/display.tsx +++ b/examples/web/react/components/display/display.tsx @@ -1,5 +1,5 @@ import React, { FC, useState, useRef, useEffect } from "react"; -import { PixelFormat } from "../../app"; +import { PixelFormat } from "../../structs"; import "./display.css"; diff --git a/examples/web/react/components/tiles/tiles.tsx b/examples/web/react/components/tiles/tiles.tsx index 78b340e1..c1b6f7b5 100644 --- a/examples/web/react/components/tiles/tiles.tsx +++ b/examples/web/react/components/tiles/tiles.tsx @@ -1,5 +1,5 @@ import React, { FC, useEffect, useRef } from "react"; -import { PixelFormat } from "../../app"; +import { PixelFormat } from "../../structs"; import Canvas, { CanvasStructure } from "../canvas/canvas"; import "./tiles.css"; diff --git a/examples/web/react/structs.ts b/examples/web/react/structs.ts new file mode 100644 index 00000000..714d6f42 --- /dev/null +++ b/examples/web/react/structs.ts @@ -0,0 +1,263 @@ +export const FREQUENCY_DELTA = 100000; + +export type Callback<T> = (owner: T, params?: any) => void; + +/** + * Abstract class that implements the basic functionality + * part of the definition of the Observer pattern. + * + * @see {@link https://en.wikipedia.org/wiki/Observer_pattern} + */ +export class Observable { + private events: Record<string, [Callback<this>]> = {}; + + bind(event: string, callback: Callback<this>) { + const callbacks = this.events[event] ?? []; + if (callbacks.includes(callback)) return; + callbacks.push(callback); + this.events[event] = callbacks; + } + + unbind(event: string, callback: Callback<this>) { + const callbacks = this.events[event] ?? []; + if (!callbacks.includes(callback)) return; + const index = callbacks.indexOf(callback); + callbacks.splice(index, 1); + this.events[event] = callbacks; + } + + trigger(event: string, params?: any) { + const callbacks = this.events[event] ?? []; + callbacks.forEach((c) => c(this, params)); + } +} + +export type RomInfo = { + name?: string; + data?: Uint8Array; + size?: number; + extra?: Record<string, string | undefined>; +}; + +export type BenchmarkResult = { + delta: number; + count: number; + cycles: number; + frequency_mhz: number; +}; + +export enum Feature { + Debug = 1, + Palettes, + Benchmark, + Keyboard, + KeyboardChip8, + KeyboardGB +} + +/** + * Enumeration that describes the multiple pixel + * formats and the associated size in bytes. + */ +export enum PixelFormat { + RGB = 3, + RGBA = 4 +} + +export interface ObservableI { + bind(event: string, callback: Callback<this>): void; + unbind(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 ObservableI { + /** + * The descriptive name of the emulator. + */ + get name(): string; + + /** + * The name of the the hardware that is being emulated + * by the emulator (eg: Super Nintendo). + */ + get device(): string; + + /** + * A URL to a website that describes the device that is + * being emulated by the emulator (eg: Wikipedia link). + */ + get deviceUrl(): string | undefined; + + /** + * A semantic version string for the current version + * of the emulator. + * + * @see {@link https://semver.org} + */ + get version(): string; + + /** + * The URL to the page describing the current version + * of the emulator. + */ + get versionUrl(): string | undefined; + + get repository(): string | undefined; + + get repositoryUrl(): string | undefined; + + /** + * The features available and compatible with the emulator, + * these values will influence the associated GUIs. + */ + get features(): Feature[]; + + /** + * The complete set of engine names that can be used + * in the re-boot operation. + */ + get engines(): string[]; + + /** + * The name of the current execution engine being used + * by the emulator. + */ + get engine(): string | null; + + /** + * The complete set of file extensions that this emulator + * supports. + */ + get romExts(): string[]; + + /** + * The pixel format of the emulator's display + * image buffer (eg: RGB). + */ + get pixelFormat(): PixelFormat; + + /** + * Gets the complete image buffer as a sequence of + * bytes that respects the current pixel format from + * `getPixelFormat()`. This method returns an in memory + * pointer to the heap and not a copy. + */ + get imageBuffer(): Uint8Array; + + /** + * Gets information about the ROM that is currently + * loaded in the emulator, using a structure containing + * the information about the ROM that is currently + * loaded in the emulator. + */ + get romInfo(): RomInfo; + + /** + * The current CPU frequency (logic) of the emulator, + * should impact other elements of the emulator. + */ + get frequency(): number; + set frequency(value: number); + + /** + * The recommended frequency delta in hertz for scale up + * and scale down operations in the CPU frequency. + */ + get frequencyDelta(): number | null; + + /** + * The current logic framerate of the running emulator. + */ + get framerate(): number; + + /** + * A dictionary that contains the register names associated + * with their value either as strings or numbers. + */ + get registers(): Record<string, string | number>; + + /** + * Obtains the pixel buffer for the VRAM tile at the given + * index. + * + * @param index The index of the tile to obtain pixel buffer. + * @returns The pixel buffer of the tile at the given index. + */ + getTile(index: number): Uint8Array; + + /** + * Boot (or reboots) the emulator according to the provided + * set of options. + * + * @param options The options that are going to be used for + * the booting operation of the emulator. + */ + boot(options: any): void; + + /** + * Toggle the running state of the emulator between paused + * and running, prevents consumers from the need to access + * the current running state of the emulator to implement + * a logic toggle. + */ + toggleRunning(): void; + pause(): void; + resume(): void; + + /** + * Resets the emulator machine to the start state and + * re-loads the ROM that is currently set in the emulator. + */ + reset(): void; + + keyPress(key: string): void; + + keyLift(key: string): void; + + /** + * Changes the palette of the emulator to the "next" one. + */ + changePalette?: { (): void }; + + /** + * Runs a benchmark operation in the emulator, effectively + * measuring the performance of it. + * + * @param count The number of benchmark iterations to be + * run, increasing this value will make the benchmark take + * more time to be executed. + * @returns The result metrics from the benchmark run. + */ + benchmark?: { (count?: number): BenchmarkResult }; +} + +export class EmulatorBase extends Observable { + get deviceUrl(): string | undefined { + return undefined; + } + + get versionUrl(): string | undefined { + return undefined; + } + + get repository(): string | undefined { + return undefined; + } + + get repositoryUrl(): string | undefined { + return undefined; + } + + get features(): Feature[] { + return []; + } + + get frequencyDelta(): number | null { + return FREQUENCY_DELTA; + } +} -- GitLab