Newer
Older
export const FREQUENCY_DELTA = 100000;
export type Callback<T> = (owner: T, params?: any) => void;
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 type Entry = {
text: string;
url?: string;
};
/**
* Enumeration to be used to describe the set of
* features that a certain emulator supports, this
* is going to condition its runtime execution.
*/
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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 information on the hardware that is being emulated
* by the emulator (eg: Super Nintendo), can contain a URL
* that describes the device that is being emulated by
* the emulator (eg: Wikipedia link).
/**
* A semantic version string for the current version
* of the emulator, can include a URL pointing to a
* changelog or equivalent document.
*
* @see {@link https://semver.org}
*/
get version(): Entry | undefined;
* Information about the source code repository where
* the emulator source code is being stored.
get repository(): Entry | undefined;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
* 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>;
/**
* The palette as a string name that is currently
* set in the emulator for display.
*/
get palette(): string | undefined;
set palette(value: string | undefined);
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
* 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,
* the order in which the palette is chosen is defined by
* the concrete emulator implementation.
*
* @returns The name of the palette that has been selected.
changePalette?: { (): string };
/**
* 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 };
}
/**
* 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 class EmulatorBase extends Observable {
get version(): Entry | undefined {
return undefined;
}
get repository(): Entry | undefined {
return undefined;
}
get features(): Feature[] {
return [];
}
get frequencyDelta(): number | null {
return FREQUENCY_DELTA;
}
get palette(): string | undefined {
return undefined;
}
set palette(value: string | undefined) {}