koin.js 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/index.d.mts +858 -0
- package/dist/index.d.ts +858 -0
- package/dist/index.js +8148 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +8079 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +57 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,858 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { Nostalgist } from 'nostalgist';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Unified Control System Types
|
|
7
|
+
*
|
|
8
|
+
* Single source of truth for all control-related type definitions.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* All possible button identifiers (superset of all consoles)
|
|
12
|
+
*/
|
|
13
|
+
type ButtonId = 'up' | 'down' | 'left' | 'right' | 'a' | 'b' | 'x' | 'y' | 'l' | 'r' | 'l2' | 'r2' | 'l3' | 'r3' | 'start' | 'select';
|
|
14
|
+
/**
|
|
15
|
+
* D-pad buttons
|
|
16
|
+
*/
|
|
17
|
+
declare const DPAD_BUTTONS: ButtonId[];
|
|
18
|
+
/**
|
|
19
|
+
* Face buttons
|
|
20
|
+
*/
|
|
21
|
+
declare const FACE_BUTTONS: ButtonId[];
|
|
22
|
+
/**
|
|
23
|
+
* Shoulder buttons (L/R only)
|
|
24
|
+
*/
|
|
25
|
+
declare const SHOULDER_BUTTONS: ButtonId[];
|
|
26
|
+
/**
|
|
27
|
+
* Trigger buttons (L2/R2)
|
|
28
|
+
*/
|
|
29
|
+
declare const TRIGGER_BUTTONS: ButtonId[];
|
|
30
|
+
/**
|
|
31
|
+
* Stick click buttons
|
|
32
|
+
*/
|
|
33
|
+
declare const STICK_BUTTONS: ButtonId[];
|
|
34
|
+
/**
|
|
35
|
+
* System buttons
|
|
36
|
+
*/
|
|
37
|
+
declare const SYSTEM_BUTTONS: ButtonId[];
|
|
38
|
+
/**
|
|
39
|
+
* All buttons in display order
|
|
40
|
+
*/
|
|
41
|
+
declare const ALL_BUTTONS: ButtonId[];
|
|
42
|
+
/**
|
|
43
|
+
* Keyboard mapping: button → JavaScript KeyboardEvent.code
|
|
44
|
+
* Partial because not all consoles have all buttons
|
|
45
|
+
*/
|
|
46
|
+
type KeyboardMapping = Partial<Record<ButtonId, string>>;
|
|
47
|
+
/**
|
|
48
|
+
* Gamepad mapping: button → physical button index (W3C Gamepad API)
|
|
49
|
+
* Partial because users may not map all buttons
|
|
50
|
+
*/
|
|
51
|
+
type GamepadMapping = Partial<Record<ButtonId, number>>;
|
|
52
|
+
/**
|
|
53
|
+
* Which buttons a console actually has
|
|
54
|
+
*/
|
|
55
|
+
interface ConsoleCapabilities {
|
|
56
|
+
/** Console key (e.g., 'NES', 'SNES') */
|
|
57
|
+
console: string;
|
|
58
|
+
/** List of buttons this console supports */
|
|
59
|
+
buttons: ButtonId[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Information about a connected gamepad
|
|
63
|
+
*/
|
|
64
|
+
interface GamepadInfo {
|
|
65
|
+
/** Gamepad index (0-3) */
|
|
66
|
+
index: number;
|
|
67
|
+
/** Raw gamepad identifier string */
|
|
68
|
+
id: string;
|
|
69
|
+
/** Cleaned up display name */
|
|
70
|
+
name: string;
|
|
71
|
+
/** Whether currently connected */
|
|
72
|
+
connected: boolean;
|
|
73
|
+
/** Number of buttons */
|
|
74
|
+
buttons: number;
|
|
75
|
+
/** Number of axes */
|
|
76
|
+
axes: number;
|
|
77
|
+
/** Mapping type from Gamepad API */
|
|
78
|
+
mapping: GamepadMappingType;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Detected controller brand for UI theming
|
|
82
|
+
*/
|
|
83
|
+
type ControllerBrand = 'xbox' | 'playstation' | 'nintendo' | 'generic';
|
|
84
|
+
/**
|
|
85
|
+
* Player index (1-4)
|
|
86
|
+
*/
|
|
87
|
+
type PlayerIndex = 1 | 2 | 3 | 4;
|
|
88
|
+
/**
|
|
89
|
+
* Full control configuration for the emulator
|
|
90
|
+
*/
|
|
91
|
+
interface ControlConfig {
|
|
92
|
+
/** Keyboard controls (usually player 1 only) */
|
|
93
|
+
keyboard?: KeyboardMapping;
|
|
94
|
+
/** Gamepad controls per player */
|
|
95
|
+
gamepads?: GamepadMapping[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Default Control Mappings
|
|
100
|
+
*
|
|
101
|
+
* Single source of truth for all default button mappings.
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Standard W3C Gamepad API button indices
|
|
106
|
+
* https://w3c.github.io/gamepad/#remapping
|
|
107
|
+
*/
|
|
108
|
+
declare const STANDARD_GAMEPAD_BUTTONS: Record<ButtonId, number>;
|
|
109
|
+
/**
|
|
110
|
+
* Default keyboard mapping (SNES-like, works for most consoles)
|
|
111
|
+
*/
|
|
112
|
+
declare const DEFAULT_KEYBOARD: KeyboardMapping;
|
|
113
|
+
/**
|
|
114
|
+
* Default gamepad mapping (uses standard W3C indices)
|
|
115
|
+
*/
|
|
116
|
+
declare const DEFAULT_GAMEPAD: GamepadMapping;
|
|
117
|
+
/**
|
|
118
|
+
* Get a complete keyboard mapping with all buttons filled in
|
|
119
|
+
* Uses defaults for any missing buttons
|
|
120
|
+
*/
|
|
121
|
+
declare function getFullKeyboardMapping(partial?: Partial<KeyboardMapping>): KeyboardMapping;
|
|
122
|
+
/**
|
|
123
|
+
* Get a complete gamepad mapping with all buttons filled in
|
|
124
|
+
* Uses defaults for any missing buttons
|
|
125
|
+
*/
|
|
126
|
+
declare function getFullGamepadMapping(partial?: Partial<GamepadMapping>): GamepadMapping;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Button Labels for UI Display
|
|
130
|
+
*
|
|
131
|
+
* Single source of truth for button display names.
|
|
132
|
+
*/
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Human-readable labels for each button
|
|
136
|
+
*/
|
|
137
|
+
declare const BUTTON_LABELS: Record<ButtonId, string>;
|
|
138
|
+
/**
|
|
139
|
+
* Button groups for organized UI display
|
|
140
|
+
*/
|
|
141
|
+
declare const BUTTON_GROUPS: {
|
|
142
|
+
label: string;
|
|
143
|
+
buttons: ButtonId[];
|
|
144
|
+
}[];
|
|
145
|
+
/**
|
|
146
|
+
* Format a JavaScript key code for display
|
|
147
|
+
*/
|
|
148
|
+
declare function formatKeyCode(code: string): string;
|
|
149
|
+
/**
|
|
150
|
+
* Get human-readable name for a gamepad button index
|
|
151
|
+
*/
|
|
152
|
+
declare function formatGamepadButton(index: number | undefined): string;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Per-Console Control Presets
|
|
156
|
+
*
|
|
157
|
+
* Defines which buttons each console supports and
|
|
158
|
+
* console-specific default keyboard layouts.
|
|
159
|
+
*/
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Console capabilities - which buttons each system has
|
|
163
|
+
*/
|
|
164
|
+
declare const CONSOLE_CAPABILITIES: Record<string, ConsoleCapabilities>;
|
|
165
|
+
/**
|
|
166
|
+
* Console-specific keyboard overrides
|
|
167
|
+
* Only specify keys that differ from DEFAULT_KEYBOARD
|
|
168
|
+
*/
|
|
169
|
+
declare const CONSOLE_KEYBOARD_OVERRIDES: Partial<Record<string, Partial<KeyboardMapping>>>;
|
|
170
|
+
/**
|
|
171
|
+
* Get capabilities for a console
|
|
172
|
+
* Falls back to SNES-like if unknown
|
|
173
|
+
*/
|
|
174
|
+
declare function getConsoleCapabilities(system: string): ConsoleCapabilities;
|
|
175
|
+
/**
|
|
176
|
+
* Get the list of buttons for a console
|
|
177
|
+
*/
|
|
178
|
+
declare function getConsoleButtons(system: string): ButtonId[];
|
|
179
|
+
/**
|
|
180
|
+
* Get default keyboard mapping for a console
|
|
181
|
+
* Merges console-specific overrides with defaults
|
|
182
|
+
*/
|
|
183
|
+
declare function getConsoleKeyboardDefaults(system: string): KeyboardMapping;
|
|
184
|
+
/**
|
|
185
|
+
* Check if a console supports a specific button
|
|
186
|
+
*/
|
|
187
|
+
declare function consoleHasButton(system: string, button: ButtonId): boolean;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Control Storage Utilities
|
|
191
|
+
*
|
|
192
|
+
* Load and save keyboard/gamepad mappings from localStorage.
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Load keyboard mapping from localStorage
|
|
197
|
+
* Falls back to console-specific defaults if not found
|
|
198
|
+
*/
|
|
199
|
+
declare function loadKeyboardMapping(system?: string): KeyboardMapping;
|
|
200
|
+
/**
|
|
201
|
+
* Save keyboard mapping to localStorage
|
|
202
|
+
*/
|
|
203
|
+
declare function saveKeyboardMapping(mapping: KeyboardMapping, system?: string): void;
|
|
204
|
+
/**
|
|
205
|
+
* Load gamepad mapping from localStorage
|
|
206
|
+
* Falls back to standard defaults if not found
|
|
207
|
+
*/
|
|
208
|
+
declare function loadGamepadMapping(playerIndex?: PlayerIndex): GamepadMapping;
|
|
209
|
+
/**
|
|
210
|
+
* Save gamepad mapping to localStorage
|
|
211
|
+
*/
|
|
212
|
+
declare function saveGamepadMapping(mapping: GamepadMapping, playerIndex?: PlayerIndex): void;
|
|
213
|
+
/**
|
|
214
|
+
* Load all gamepad mappings for connected players
|
|
215
|
+
*/
|
|
216
|
+
declare function loadAllGamepadMappings(playerCount: number): GamepadMapping[];
|
|
217
|
+
/**
|
|
218
|
+
* Clear all saved controls (keyboard and gamepad)
|
|
219
|
+
*/
|
|
220
|
+
declare function clearAllControls(): void;
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* RetroArch Input Configuration
|
|
224
|
+
*
|
|
225
|
+
* Converts our control mappings to RetroArch config format.
|
|
226
|
+
*/
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Convert keyboard mapping to RetroArch config for a player
|
|
230
|
+
*/
|
|
231
|
+
declare function keyboardToRetroArchConfig(mapping: KeyboardMapping, playerIndex?: number): Record<string, string>;
|
|
232
|
+
/**
|
|
233
|
+
* Convert gamepad mapping to RetroArch config for a player
|
|
234
|
+
* Uses _btn suffix for button indices
|
|
235
|
+
*/
|
|
236
|
+
declare function gamepadToRetroArchConfig(mapping: GamepadMapping, playerIndex?: number): Record<string, number | string>;
|
|
237
|
+
/**
|
|
238
|
+
* Build complete RetroArch input config from control configuration
|
|
239
|
+
*/
|
|
240
|
+
declare function buildRetroArchConfig(config: ControlConfig): Record<string, unknown>;
|
|
241
|
+
|
|
242
|
+
type EmulatorStatus = 'idle' | 'loading' | 'ready' | 'running' | 'paused' | 'error';
|
|
243
|
+
type SpeedMultiplier = 1 | 2;
|
|
244
|
+
interface RetroAchievementsConfig {
|
|
245
|
+
username: string;
|
|
246
|
+
token: string;
|
|
247
|
+
hardcore?: boolean;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
interface UseNostalgistOptions {
|
|
251
|
+
system: string;
|
|
252
|
+
romUrl: string;
|
|
253
|
+
core?: string;
|
|
254
|
+
biosUrl?: string | {
|
|
255
|
+
url: string;
|
|
256
|
+
name: string;
|
|
257
|
+
location?: 'system' | 'rom_folder';
|
|
258
|
+
};
|
|
259
|
+
initialState?: Blob | Uint8Array;
|
|
260
|
+
getCanvasElement?: () => HTMLCanvasElement | null;
|
|
261
|
+
keyboardControls?: KeyboardMapping;
|
|
262
|
+
gamepadBindings?: GamepadMapping[];
|
|
263
|
+
retroAchievements?: RetroAchievementsConfig;
|
|
264
|
+
onReady?: () => void;
|
|
265
|
+
onError?: (error: Error) => void;
|
|
266
|
+
initialVolume?: number;
|
|
267
|
+
romFileName?: string;
|
|
268
|
+
shader?: string;
|
|
269
|
+
}
|
|
270
|
+
interface UseNostalgistReturn {
|
|
271
|
+
status: EmulatorStatus;
|
|
272
|
+
error: string | null;
|
|
273
|
+
isPaused: boolean;
|
|
274
|
+
speed: SpeedMultiplier;
|
|
275
|
+
isRewinding: boolean;
|
|
276
|
+
rewindBufferSize: number;
|
|
277
|
+
volume: number;
|
|
278
|
+
isMuted: boolean;
|
|
279
|
+
prepare: () => Promise<void>;
|
|
280
|
+
start: () => Promise<void>;
|
|
281
|
+
stop: () => void;
|
|
282
|
+
restart: () => Promise<void>;
|
|
283
|
+
pause: () => void;
|
|
284
|
+
resume: () => void;
|
|
285
|
+
togglePause: () => void;
|
|
286
|
+
saveState: () => Promise<Uint8Array | null>;
|
|
287
|
+
saveStateWithBlob: () => Promise<{
|
|
288
|
+
data: Uint8Array;
|
|
289
|
+
blob: Blob;
|
|
290
|
+
} | null>;
|
|
291
|
+
loadState: (state: Uint8Array) => Promise<boolean>;
|
|
292
|
+
setSpeed: (multiplier: SpeedMultiplier) => void;
|
|
293
|
+
startRewind: () => void;
|
|
294
|
+
stopRewind: () => void;
|
|
295
|
+
rewindEnabled: boolean;
|
|
296
|
+
setVolume: (volume: number) => void;
|
|
297
|
+
toggleMute: () => void;
|
|
298
|
+
screenshot: () => Promise<string | null>;
|
|
299
|
+
pressKey: (key: string) => void;
|
|
300
|
+
resize: (size: {
|
|
301
|
+
width: number;
|
|
302
|
+
height: number;
|
|
303
|
+
}) => void;
|
|
304
|
+
applyCheat: (code: string) => void;
|
|
305
|
+
resetCheats: () => void;
|
|
306
|
+
getNostalgistInstance: () => Nostalgist | null;
|
|
307
|
+
isPerformanceMode: boolean;
|
|
308
|
+
}
|
|
309
|
+
declare const useNostalgist: ({ system, romUrl, core, biosUrl, initialState, getCanvasElement, keyboardControls, gamepadBindings, retroAchievements, onReady, onError, initialVolume, romFileName, shader, }: UseNostalgistOptions) => UseNostalgistReturn;
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Available CRT Shader Presets
|
|
313
|
+
* ----------------------------
|
|
314
|
+
* These are loaded from libretro/glsl-shaders via Nostalgist.
|
|
315
|
+
* Format: { id: shader_path, name: display_name, description: tooltip }
|
|
316
|
+
*/
|
|
317
|
+
declare const SHADER_PRESETS: readonly [{
|
|
318
|
+
readonly id: "";
|
|
319
|
+
readonly name: "None";
|
|
320
|
+
readonly description: "No shader - sharp pixels";
|
|
321
|
+
}, {
|
|
322
|
+
readonly id: "crt/crt-lottes";
|
|
323
|
+
readonly name: "CRT Lottes";
|
|
324
|
+
readonly description: "High-quality arcade monitor look";
|
|
325
|
+
}, {
|
|
326
|
+
readonly id: "crt/crt-easymode";
|
|
327
|
+
readonly name: "CRT Easy";
|
|
328
|
+
readonly description: "Popular, performant CRT effect";
|
|
329
|
+
}, {
|
|
330
|
+
readonly id: "crt/crt-geom";
|
|
331
|
+
readonly name: "CRT Geom";
|
|
332
|
+
readonly description: "Classic CRT shader with curvature";
|
|
333
|
+
}, {
|
|
334
|
+
readonly id: "crt/crt-hyllian";
|
|
335
|
+
readonly name: "CRT Hyllian";
|
|
336
|
+
readonly description: "Attractive with minimal tweaking";
|
|
337
|
+
}, {
|
|
338
|
+
readonly id: "crt/crt-nes-mini";
|
|
339
|
+
readonly name: "NES Mini";
|
|
340
|
+
readonly description: "Simple scanlines like NES Classic";
|
|
341
|
+
}, {
|
|
342
|
+
readonly id: "crt/zfast-crt";
|
|
343
|
+
readonly name: "zFast CRT";
|
|
344
|
+
readonly description: "Lightweight, great for mobile";
|
|
345
|
+
}, {
|
|
346
|
+
readonly id: "crt/crt-potato-cool";
|
|
347
|
+
readonly name: "CRT Potato";
|
|
348
|
+
readonly description: "Fast and good for weak devices";
|
|
349
|
+
}, {
|
|
350
|
+
readonly id: "handheld/lcd-grid-v2";
|
|
351
|
+
readonly name: "LCD Grid";
|
|
352
|
+
readonly description: "Game Boy style LCD effect";
|
|
353
|
+
}, {
|
|
354
|
+
readonly id: "scanlines";
|
|
355
|
+
readonly name: "Scanlines";
|
|
356
|
+
readonly description: "Simple horizontal scanlines";
|
|
357
|
+
}];
|
|
358
|
+
type ShaderPresetId = typeof SHADER_PRESETS[number]['id'];
|
|
359
|
+
interface ShaderSelectorProps {
|
|
360
|
+
currentShader: ShaderPresetId;
|
|
361
|
+
onShaderChange: (shaderId: ShaderPresetId) => void;
|
|
362
|
+
disabled?: boolean;
|
|
363
|
+
systemColor?: string;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Shader Selector Component
|
|
367
|
+
* -------------------------
|
|
368
|
+
* Dropdown to select CRT/LCD shader effects.
|
|
369
|
+
*/
|
|
370
|
+
declare const ShaderSelector: react.NamedExoticComponent<ShaderSelectorProps>;
|
|
371
|
+
|
|
372
|
+
declare const RA_MEDIA_BASE = "https://media.retroachievements.org";
|
|
373
|
+
interface RACredentials {
|
|
374
|
+
username: string;
|
|
375
|
+
connectToken: string;
|
|
376
|
+
apiKey?: string;
|
|
377
|
+
score?: number;
|
|
378
|
+
softcoreScore?: number;
|
|
379
|
+
avatarUrl?: string;
|
|
380
|
+
}
|
|
381
|
+
interface RAUser {
|
|
382
|
+
User: string;
|
|
383
|
+
Token: string;
|
|
384
|
+
Score: number;
|
|
385
|
+
SoftcoreScore: number;
|
|
386
|
+
Messages: number;
|
|
387
|
+
Permissions: number;
|
|
388
|
+
AccountType: string;
|
|
389
|
+
}
|
|
390
|
+
interface RAAchievement {
|
|
391
|
+
ID: number;
|
|
392
|
+
NumAwarded: number;
|
|
393
|
+
NumAwardedHardcore: number;
|
|
394
|
+
Title: string;
|
|
395
|
+
Description: string;
|
|
396
|
+
Points: number;
|
|
397
|
+
TrueRatio: number;
|
|
398
|
+
Author: string;
|
|
399
|
+
DateModified: string;
|
|
400
|
+
DateCreated: string;
|
|
401
|
+
BadgeName: string;
|
|
402
|
+
DisplayOrder: number;
|
|
403
|
+
MemAddr: string;
|
|
404
|
+
type: string | null;
|
|
405
|
+
DateEarned?: string;
|
|
406
|
+
DateEarnedHardcore?: string;
|
|
407
|
+
}
|
|
408
|
+
interface RAGame {
|
|
409
|
+
ID: number;
|
|
410
|
+
Title: string;
|
|
411
|
+
ConsoleID: number;
|
|
412
|
+
ConsoleName: string;
|
|
413
|
+
ForumTopicID: number;
|
|
414
|
+
Flags: number;
|
|
415
|
+
ImageIcon: string;
|
|
416
|
+
ImageTitle: string;
|
|
417
|
+
ImageIngame: string;
|
|
418
|
+
ImageBoxArt: string;
|
|
419
|
+
Publisher: string;
|
|
420
|
+
Developer: string;
|
|
421
|
+
Genre: string;
|
|
422
|
+
Released: string;
|
|
423
|
+
IsFinal: boolean;
|
|
424
|
+
RichPresencePatch?: string;
|
|
425
|
+
NumAchievements?: number;
|
|
426
|
+
NumDistinctPlayersCasual?: number;
|
|
427
|
+
NumDistinctPlayersHardcore?: number;
|
|
428
|
+
}
|
|
429
|
+
interface RAGameExtended extends RAGame {
|
|
430
|
+
Achievements: Record<string, RAAchievement>;
|
|
431
|
+
NumAwardedToUser?: number;
|
|
432
|
+
NumAwardedToUserHardcore?: number;
|
|
433
|
+
UserCompletion?: string;
|
|
434
|
+
UserCompletionHardcore?: string;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Get achievement badge URL
|
|
438
|
+
*/
|
|
439
|
+
declare function getAchievementBadgeUrl(badgeName: string, locked?: boolean): string;
|
|
440
|
+
/**
|
|
441
|
+
* Get user avatar URL
|
|
442
|
+
*/
|
|
443
|
+
declare function getUserAvatarUrl(userPic: string): string;
|
|
444
|
+
|
|
445
|
+
interface SaveSlot {
|
|
446
|
+
slot: number;
|
|
447
|
+
timestamp: string;
|
|
448
|
+
size: number;
|
|
449
|
+
screenshot?: string | null;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* @deprecated Use `KeyboardMapping` from `@/lib/controls` instead
|
|
453
|
+
*/
|
|
454
|
+
type ControlMapping = KeyboardMapping;
|
|
455
|
+
/**
|
|
456
|
+
* @deprecated Use `DEFAULT_KEYBOARD` from `@/lib/controls` instead
|
|
457
|
+
*/
|
|
458
|
+
declare const DEFAULT_CONTROLS: Partial<Record<ButtonId, string>>;
|
|
459
|
+
interface GamePlayerProps {
|
|
460
|
+
className?: string;
|
|
461
|
+
style?: React.CSSProperties;
|
|
462
|
+
romId: string;
|
|
463
|
+
romUrl: string;
|
|
464
|
+
romFileName?: string;
|
|
465
|
+
system: string;
|
|
466
|
+
title: string;
|
|
467
|
+
core?: string;
|
|
468
|
+
biosUrl?: string | {
|
|
469
|
+
url: string;
|
|
470
|
+
name: string;
|
|
471
|
+
location?: 'system' | 'rom_folder';
|
|
472
|
+
};
|
|
473
|
+
availableBios?: {
|
|
474
|
+
id: string;
|
|
475
|
+
name: string;
|
|
476
|
+
description?: string;
|
|
477
|
+
}[];
|
|
478
|
+
currentBiosId?: string;
|
|
479
|
+
onSelectBios?: (biosId: string) => void;
|
|
480
|
+
onReady?: () => void;
|
|
481
|
+
onError?: (error: Error) => void;
|
|
482
|
+
onExit?: () => void;
|
|
483
|
+
systemColor?: string;
|
|
484
|
+
shader?: string;
|
|
485
|
+
onShaderChange?: (shader: string, requiresRestart: boolean) => void;
|
|
486
|
+
initialSlot?: number;
|
|
487
|
+
onSaveState?: (slot: number, blob: Blob, screenshot?: string) => Promise<void>;
|
|
488
|
+
onLoadState?: (slot: number) => Promise<Blob | null>;
|
|
489
|
+
onAutoSave?: (blob: Blob, screenshot?: string) => Promise<void>;
|
|
490
|
+
onGetSaveSlots?: () => Promise<SaveSlot[]>;
|
|
491
|
+
onDeleteSaveState?: (slot: number) => Promise<void>;
|
|
492
|
+
initialSaveState?: Blob;
|
|
493
|
+
onScreenshotCaptured?: (image: string | Blob) => void;
|
|
494
|
+
autoSaveInterval?: number;
|
|
495
|
+
maxSlots?: number;
|
|
496
|
+
currentTier?: string;
|
|
497
|
+
onUpgrade?: () => void;
|
|
498
|
+
retroAchievementsConfig?: {
|
|
499
|
+
username: string;
|
|
500
|
+
token: string;
|
|
501
|
+
hardcore?: boolean;
|
|
502
|
+
};
|
|
503
|
+
cheats?: Cheat[];
|
|
504
|
+
onToggleCheat?: (cheatId: number, active: boolean) => void;
|
|
505
|
+
onSessionStart?: () => void;
|
|
506
|
+
onSessionEnd?: () => void;
|
|
507
|
+
raUser?: RACredentials | null;
|
|
508
|
+
raGame?: RAGameExtended | null;
|
|
509
|
+
raAchievements?: RAAchievement[];
|
|
510
|
+
raUnlockedAchievements?: Set<number>;
|
|
511
|
+
raIsLoading?: boolean;
|
|
512
|
+
raError?: string | null;
|
|
513
|
+
onRALogin?: (username: string, password: string) => Promise<boolean>;
|
|
514
|
+
onRALogout?: () => void;
|
|
515
|
+
onRAHardcoreChange?: (enabled: boolean) => void;
|
|
516
|
+
}
|
|
517
|
+
interface PlayerControlsProps {
|
|
518
|
+
isPaused: boolean;
|
|
519
|
+
isRunning: boolean;
|
|
520
|
+
speed: SpeedMultiplier;
|
|
521
|
+
isRewinding: boolean;
|
|
522
|
+
rewindBufferSize: number;
|
|
523
|
+
onPauseToggle: () => void;
|
|
524
|
+
onRestart: () => void;
|
|
525
|
+
onSave: () => void;
|
|
526
|
+
onLoad: () => void;
|
|
527
|
+
onSpeedChange: (speed: SpeedMultiplier) => void;
|
|
528
|
+
onRewindStart: () => void;
|
|
529
|
+
onRewindStop: () => void;
|
|
530
|
+
onScreenshot: () => void;
|
|
531
|
+
onFullscreen: () => void;
|
|
532
|
+
onControls: () => void;
|
|
533
|
+
onCheats: () => void;
|
|
534
|
+
onRetroAchievements: () => void;
|
|
535
|
+
onExit: () => void;
|
|
536
|
+
disabled?: boolean;
|
|
537
|
+
hardcoreRestrictions?: RAHardcodeRestrictions;
|
|
538
|
+
raConnected?: boolean;
|
|
539
|
+
raGameFound?: boolean;
|
|
540
|
+
raAchievementCount?: number;
|
|
541
|
+
raIsIdentifying?: boolean;
|
|
542
|
+
autoSaveEnabled?: boolean;
|
|
543
|
+
autoSaveProgress?: number;
|
|
544
|
+
autoSaveState?: 'idle' | 'counting' | 'saving' | 'done';
|
|
545
|
+
autoSavePaused?: boolean;
|
|
546
|
+
onAutoSaveToggle?: () => void;
|
|
547
|
+
systemColor?: string;
|
|
548
|
+
gamepadCount?: number;
|
|
549
|
+
onGamepadSettings?: () => void;
|
|
550
|
+
volume?: number;
|
|
551
|
+
isMuted?: boolean;
|
|
552
|
+
onVolumeChange?: (volume: number) => void;
|
|
553
|
+
onToggleMute?: () => void;
|
|
554
|
+
onShowShortcuts?: () => void;
|
|
555
|
+
onRecordToggle?: () => void;
|
|
556
|
+
isRecording?: boolean;
|
|
557
|
+
currentShader?: ShaderPresetId;
|
|
558
|
+
onShaderChange?: (shader: ShaderPresetId, requiresRestart: boolean) => void;
|
|
559
|
+
}
|
|
560
|
+
interface SaveSlotModalProps {
|
|
561
|
+
isOpen: boolean;
|
|
562
|
+
mode: 'save' | 'load';
|
|
563
|
+
slots: SaveSlot[];
|
|
564
|
+
isLoading: boolean;
|
|
565
|
+
actioningSlot?: number | null;
|
|
566
|
+
onSelect: (slot: number) => void;
|
|
567
|
+
onDelete: (slot: number) => void;
|
|
568
|
+
onClose: () => void;
|
|
569
|
+
maxSlots?: number;
|
|
570
|
+
currentTier?: string;
|
|
571
|
+
onUpgrade?: () => void;
|
|
572
|
+
}
|
|
573
|
+
interface ControlMapperProps {
|
|
574
|
+
isOpen: boolean;
|
|
575
|
+
controls: ControlMapping;
|
|
576
|
+
onSave: (controls: ControlMapping) => void;
|
|
577
|
+
onClose: () => void;
|
|
578
|
+
system?: string;
|
|
579
|
+
}
|
|
580
|
+
interface CheatModalProps {
|
|
581
|
+
isOpen: boolean;
|
|
582
|
+
cheats: Cheat[];
|
|
583
|
+
activeCheats: Set<number>;
|
|
584
|
+
onToggle: (cheatId: number) => void;
|
|
585
|
+
onClose: () => void;
|
|
586
|
+
}
|
|
587
|
+
interface Cheat {
|
|
588
|
+
id: number;
|
|
589
|
+
code: string;
|
|
590
|
+
description: string;
|
|
591
|
+
}
|
|
592
|
+
interface RAHardcodeRestrictions {
|
|
593
|
+
isHardcore?: boolean;
|
|
594
|
+
canUseSaveStates: boolean;
|
|
595
|
+
canUseRewind: boolean;
|
|
596
|
+
canUseCheats: boolean;
|
|
597
|
+
canUseSlowMotion: boolean;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
declare const GamePlayer: react.NamedExoticComponent<GamePlayerProps & {
|
|
601
|
+
controls?: KeyboardMapping;
|
|
602
|
+
saveControls?: (controls: KeyboardMapping) => void;
|
|
603
|
+
}>;
|
|
604
|
+
|
|
605
|
+
/**
|
|
606
|
+
* Detect controller brand from gamepad id for UI theming
|
|
607
|
+
*/
|
|
608
|
+
declare function detectControllerBrand(id: string): ControllerBrand;
|
|
609
|
+
interface UseGamepadOptions {
|
|
610
|
+
/** Callback when a gamepad connects */
|
|
611
|
+
onConnect?: (gamepad: GamepadInfo) => void;
|
|
612
|
+
/** Callback when a gamepad disconnects */
|
|
613
|
+
onDisconnect?: () => void;
|
|
614
|
+
}
|
|
615
|
+
interface UseGamepadReturn {
|
|
616
|
+
/** Array of connected gamepads (up to 4) */
|
|
617
|
+
gamepads: GamepadInfo[];
|
|
618
|
+
/** Whether any gamepad is connected */
|
|
619
|
+
isAnyConnected: boolean;
|
|
620
|
+
/** Number of connected gamepads */
|
|
621
|
+
connectedCount: number;
|
|
622
|
+
/** Get raw gamepad by index for reading button states */
|
|
623
|
+
getRawGamepad: (index: number) => Gamepad | null;
|
|
624
|
+
/** Force refresh gamepad list */
|
|
625
|
+
refresh: () => void;
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Hook to track connected gamepads
|
|
629
|
+
* Uses requestAnimationFrame polling since Gamepad API requires active polling
|
|
630
|
+
*
|
|
631
|
+
* NOTE: Browsers require a button press before reporting gamepads (security feature)
|
|
632
|
+
*/
|
|
633
|
+
declare function useGamepad(options?: UseGamepadOptions): UseGamepadReturn;
|
|
634
|
+
/**
|
|
635
|
+
* Standard gamepad axis indices
|
|
636
|
+
*/
|
|
637
|
+
declare const STANDARD_AXIS_MAP: {
|
|
638
|
+
readonly leftStickX: 0;
|
|
639
|
+
readonly leftStickY: 1;
|
|
640
|
+
readonly rightStickX: 2;
|
|
641
|
+
readonly rightStickY: 3;
|
|
642
|
+
};
|
|
643
|
+
type StandardAxis = keyof typeof STANDARD_AXIS_MAP;
|
|
644
|
+
|
|
645
|
+
type ToastType = 'success' | 'error' | 'info' | 'warning' | 'gamepad';
|
|
646
|
+
interface Toast {
|
|
647
|
+
id: string;
|
|
648
|
+
message: string;
|
|
649
|
+
type: ToastType;
|
|
650
|
+
title?: string;
|
|
651
|
+
icon?: string;
|
|
652
|
+
duration?: number;
|
|
653
|
+
action?: {
|
|
654
|
+
label: string;
|
|
655
|
+
onClick: () => void;
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
interface ShowToastOptions {
|
|
659
|
+
title?: string;
|
|
660
|
+
icon?: string;
|
|
661
|
+
duration?: number;
|
|
662
|
+
action?: Toast['action'];
|
|
663
|
+
}
|
|
664
|
+
interface UseToastReturn {
|
|
665
|
+
toasts: Toast[];
|
|
666
|
+
showToast: (message: string, type?: ToastType, options?: ShowToastOptions) => void;
|
|
667
|
+
dismissToast: (id: string) => void;
|
|
668
|
+
clearToasts: () => void;
|
|
669
|
+
}
|
|
670
|
+
/**
|
|
671
|
+
* Hook for managing toast notifications
|
|
672
|
+
* @param defaultDuration - Default duration for toasts (default 3000ms)
|
|
673
|
+
*/
|
|
674
|
+
declare function useToast(defaultDuration?: number): UseToastReturn;
|
|
675
|
+
|
|
676
|
+
interface SystemConfig {
|
|
677
|
+
key: string;
|
|
678
|
+
label: string;
|
|
679
|
+
fullName: string;
|
|
680
|
+
slug: string;
|
|
681
|
+
extensions: string[];
|
|
682
|
+
core: string;
|
|
683
|
+
dbNames: string[];
|
|
684
|
+
iconName: string;
|
|
685
|
+
color: string;
|
|
686
|
+
accentHex: string;
|
|
687
|
+
aliases: string[];
|
|
688
|
+
biosNeeded?: boolean;
|
|
689
|
+
biosFileNames?: string[];
|
|
690
|
+
biosLocation?: 'system' | 'rom_folder';
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* The master system configuration
|
|
694
|
+
* Order matters for display in dropdowns
|
|
695
|
+
*/
|
|
696
|
+
declare const SYSTEMS: SystemConfig[];
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Unified System Configuration
|
|
700
|
+
*
|
|
701
|
+
* SINGLE SOURCE OF TRUTH for all system-related data:
|
|
702
|
+
* - Canonical system keys (used internally)
|
|
703
|
+
* - File extensions → system detection
|
|
704
|
+
* - System → RetroArch emulator core
|
|
705
|
+
* - System → Database names (for LaunchBox matching)
|
|
706
|
+
* - System → Display metadata (UI labels, colors, icons)
|
|
707
|
+
*
|
|
708
|
+
* All other files should import from here instead of maintaining their own mappings.
|
|
709
|
+
*/
|
|
710
|
+
|
|
711
|
+
/**
|
|
712
|
+
* Get system by canonical key (e.g., 'NES', 'GBA')
|
|
713
|
+
*/
|
|
714
|
+
declare function getSystemByKey(key: string): SystemConfig | undefined;
|
|
715
|
+
/**
|
|
716
|
+
* Get system by any name/alias (case-insensitive)
|
|
717
|
+
* Tries: exact key match, then alias match
|
|
718
|
+
*/
|
|
719
|
+
declare function getSystem(name: string): SystemConfig | undefined;
|
|
720
|
+
/**
|
|
721
|
+
* Get system from file extension (e.g., '.nes', '.gba')
|
|
722
|
+
*/
|
|
723
|
+
declare function getSystemFromExtension(filename: string): SystemConfig | undefined;
|
|
724
|
+
/**
|
|
725
|
+
* Get system by database name (for LaunchBox matching)
|
|
726
|
+
*/
|
|
727
|
+
declare function getSystemByDbName(dbName: string): SystemConfig | undefined;
|
|
728
|
+
/**
|
|
729
|
+
* Get RetroArch core for a system name (case-insensitive)
|
|
730
|
+
* Falls back to 'fceumm' (NES) if not found
|
|
731
|
+
*/
|
|
732
|
+
declare function getCore(systemName: string): string;
|
|
733
|
+
/**
|
|
734
|
+
* Get DB names for matching (used in game search)
|
|
735
|
+
*/
|
|
736
|
+
declare function getDBSystemNames(systemKey: string): string[];
|
|
737
|
+
/**
|
|
738
|
+
* Check if a system is supported
|
|
739
|
+
*/
|
|
740
|
+
declare function isSystemSupported(name: string): boolean;
|
|
741
|
+
/**
|
|
742
|
+
* Get all supported extensions
|
|
743
|
+
*/
|
|
744
|
+
declare function getSupportedExtensions(): string[];
|
|
745
|
+
/**
|
|
746
|
+
* Get all systems for UI dropdown
|
|
747
|
+
*/
|
|
748
|
+
declare function getSystemsList(): Array<{
|
|
749
|
+
value: string;
|
|
750
|
+
label: string;
|
|
751
|
+
iconName: string;
|
|
752
|
+
color: string;
|
|
753
|
+
}>;
|
|
754
|
+
/**
|
|
755
|
+
* Detect system from filename
|
|
756
|
+
* Returns null for ZIP files (user must select)
|
|
757
|
+
*/
|
|
758
|
+
declare function detectSystem(filename: string): SystemConfig | undefined;
|
|
759
|
+
/**
|
|
760
|
+
* Check if two system names refer to the same platform
|
|
761
|
+
*/
|
|
762
|
+
declare function systemsMatch(name1: string, name2: string): boolean;
|
|
763
|
+
/**
|
|
764
|
+
* Normalize a system name to its canonical key
|
|
765
|
+
*/
|
|
766
|
+
declare function normalizeSystemKey(name: string): string;
|
|
767
|
+
declare const SUPPORTED_EXTENSIONS: string[];
|
|
768
|
+
/**
|
|
769
|
+
* TIER 1: "Zero Lag" - Lightweight Systems
|
|
770
|
+
* ----------------------------------------
|
|
771
|
+
* These 8-bit and 16-bit systems have low CPU requirements in WASM,
|
|
772
|
+
* allowing us to enable Run-Ahead (frame prediction) for near-zero input latency.
|
|
773
|
+
*
|
|
774
|
+
* Run-Ahead works by running the emulator ahead by 1 frame and using that
|
|
775
|
+
* result for display, effectively cutting 1 frame (~16ms) of input lag.
|
|
776
|
+
*/
|
|
777
|
+
declare const PERFORMANCE_TIER_1_SYSTEMS: Set<string>;
|
|
778
|
+
/**
|
|
779
|
+
* TIER 2: "Max Smoothness" - Heavy Systems
|
|
780
|
+
* ----------------------------------------
|
|
781
|
+
* These 32-bit+ systems push WASM hard. Run-Ahead would cause stuttering.
|
|
782
|
+
* Instead, we optimize for smooth, consistent frame delivery:
|
|
783
|
+
* - Threaded video rendering to prevent UI freezes
|
|
784
|
+
* - Larger audio buffers to prevent crackling
|
|
785
|
+
* - Disabled manual rewind capture (saves RAM and CPU cycles)
|
|
786
|
+
*/
|
|
787
|
+
declare const PERFORMANCE_TIER_2_SYSTEMS: Set<string>;
|
|
788
|
+
|
|
789
|
+
interface RASidebarProps {
|
|
790
|
+
isOpen: boolean;
|
|
791
|
+
onClose: () => void;
|
|
792
|
+
isLoggedIn: boolean;
|
|
793
|
+
credentials: RACredentials | null;
|
|
794
|
+
isLoading: boolean;
|
|
795
|
+
error?: string | null;
|
|
796
|
+
onLogin: (username: string, password: string) => Promise<boolean>;
|
|
797
|
+
onLogout: () => void;
|
|
798
|
+
hardcoreEnabled: boolean;
|
|
799
|
+
onHardcoreChange: (enabled: boolean) => void;
|
|
800
|
+
currentGame: RAGameExtended | null;
|
|
801
|
+
achievements: RAAchievement[];
|
|
802
|
+
unlockedIds: Set<number>;
|
|
803
|
+
}
|
|
804
|
+
declare function RASidebar({ isOpen, onClose, isLoggedIn, credentials, isLoading, error, onLogin, onLogout, hardcoreEnabled, onHardcoreChange, currentGame, achievements, unlockedIds, }: RASidebarProps): react_jsx_runtime.JSX.Element | null;
|
|
805
|
+
|
|
806
|
+
interface AchievementPopupProps {
|
|
807
|
+
achievement: RAAchievement;
|
|
808
|
+
hardcore: boolean;
|
|
809
|
+
onDismiss: () => void;
|
|
810
|
+
autoDismissMs?: number;
|
|
811
|
+
}
|
|
812
|
+
declare function AchievementPopup({ achievement, hardcore, onDismiss, autoDismissMs, }: AchievementPopupProps): react_jsx_runtime.JSX.Element;
|
|
813
|
+
|
|
814
|
+
interface ToastContainerProps {
|
|
815
|
+
toasts: Toast[];
|
|
816
|
+
onDismiss?: (id: string) => void;
|
|
817
|
+
}
|
|
818
|
+
declare function ToastContainer({ toasts, onDismiss }: ToastContainerProps): react_jsx_runtime.JSX.Element | null;
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Shortcuts Reference
|
|
822
|
+
* -------------------
|
|
823
|
+
* Collapsible panel showing player F-key shortcuts.
|
|
824
|
+
* Game controls have their own config in the Keys modal.
|
|
825
|
+
*/
|
|
826
|
+
interface ShortcutsReferenceProps {
|
|
827
|
+
systemColor?: string;
|
|
828
|
+
isExpanded?: boolean;
|
|
829
|
+
}
|
|
830
|
+
declare const ShortcutsReference: react.NamedExoticComponent<ShortcutsReferenceProps>;
|
|
831
|
+
|
|
832
|
+
interface UseGameRecordingProps {
|
|
833
|
+
getCanvasElement: () => HTMLCanvasElement | null;
|
|
834
|
+
}
|
|
835
|
+
interface UseGameRecordingReturn {
|
|
836
|
+
isRecording: boolean;
|
|
837
|
+
isPaused: boolean;
|
|
838
|
+
recordingDuration: number;
|
|
839
|
+
startRecording: () => void;
|
|
840
|
+
stopRecording: () => Promise<Blob | null>;
|
|
841
|
+
pauseRecording: () => void;
|
|
842
|
+
resumeRecording: () => void;
|
|
843
|
+
isSupported: boolean;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Gameplay Recording Hook
|
|
847
|
+
* -----------------------
|
|
848
|
+
* Uses MediaRecorder API to capture canvas gameplay as WebM video.
|
|
849
|
+
*
|
|
850
|
+
* Features:
|
|
851
|
+
* - Start/stop recording
|
|
852
|
+
* - Pause/resume
|
|
853
|
+
* - Duration tracking
|
|
854
|
+
* - Returns Blob for download
|
|
855
|
+
*/
|
|
856
|
+
declare function useGameRecording({ getCanvasElement, }: UseGameRecordingProps): UseGameRecordingReturn;
|
|
857
|
+
|
|
858
|
+
export { ALL_BUTTONS, AchievementPopup, BUTTON_GROUPS, BUTTON_LABELS, type ButtonId, CONSOLE_CAPABILITIES, CONSOLE_KEYBOARD_OVERRIDES, type Cheat, type CheatModalProps, type ConsoleCapabilities, type ControlConfig, type ControlMapperProps, type ControlMapping, type ControllerBrand, DEFAULT_CONTROLS, DEFAULT_GAMEPAD, DEFAULT_KEYBOARD, DPAD_BUTTONS, type EmulatorStatus, FACE_BUTTONS, GamePlayer, type GamePlayerProps, type GamepadInfo, type GamepadMapping, type KeyboardMapping, PERFORMANCE_TIER_1_SYSTEMS, PERFORMANCE_TIER_2_SYSTEMS, type PlayerControlsProps, type PlayerIndex, type RAAchievement, type RACredentials, type RAGame, type RAGameExtended, type RAHardcodeRestrictions, RASidebar, type RAUser, RA_MEDIA_BASE, type RetroAchievementsConfig, SHADER_PRESETS, SHOULDER_BUTTONS, STANDARD_AXIS_MAP, STANDARD_GAMEPAD_BUTTONS, STICK_BUTTONS, SUPPORTED_EXTENSIONS, SYSTEMS, SYSTEM_BUTTONS, type SaveSlot, type SaveSlotModalProps, type ShaderPresetId, ShaderSelector, ShortcutsReference, type ShowToastOptions, type SpeedMultiplier, type StandardAxis, type SystemConfig, TRIGGER_BUTTONS, type Toast, ToastContainer, type ToastType, type UseGamepadOptions, type UseGamepadReturn, type UseNostalgistReturn, type UseToastReturn, buildRetroArchConfig, clearAllControls, consoleHasButton, detectControllerBrand, detectSystem, formatGamepadButton, formatKeyCode, gamepadToRetroArchConfig, getAchievementBadgeUrl, getConsoleButtons, getConsoleCapabilities, getConsoleKeyboardDefaults, getCore, getDBSystemNames, getFullGamepadMapping, getFullKeyboardMapping, getSupportedExtensions, getSystem, getSystemByDbName, getSystemByKey, getSystemFromExtension, getSystemsList, getUserAvatarUrl, isSystemSupported, keyboardToRetroArchConfig, loadAllGamepadMappings, loadGamepadMapping, loadKeyboardMapping, normalizeSystemKey, saveGamepadMapping, saveKeyboardMapping, systemsMatch, useGameRecording, useGamepad, useNostalgist, useToast };
|