@wasm-gaming/fbneo-wasm 0.2.0 → 0.3.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/README.md +10 -1
- package/dist/fbneo/app/app.js +1 -1
- package/dist/fbneo/fbneo.js +1 -1
- package/dist/fbneo/fbneo.options.d.ts +6 -0
- package/dist/fbneo/fbneo.options.d.ts.map +1 -1
- package/dist/fbneo/fbneo.options.js +6 -0
- package/dist/fbneo/fbneo.options.js.map +1 -1
- package/dist/fbneo/fbneo.sdk.d.ts +21 -1
- package/dist/fbneo/fbneo.sdk.d.ts.map +1 -1
- package/dist/fbneo/fbneo.sdk.js +57 -1
- package/dist/fbneo/fbneo.sdk.js.map +1 -1
- package/dist/fbneo/fbneo.wasm +2 -2
- package/dist/fbneo/romset.d.ts +0 -0
- package/dist/fbneo/romset.d.ts.map +1 -1
- package/dist/fbneo/romset.js.map +1 -1
- package/dist/fbneo/romsets/atari.json +5036 -118
- package/dist/fbneo/romsets/capcom.json +3392 -848
- package/dist/fbneo/romsets/cave.json +460 -115
- package/dist/fbneo/romsets/channelf.json +200 -50
- package/dist/fbneo/romsets/coleco.json +2650 -658
- package/dist/fbneo/romsets/cps3.json +240 -60
- package/dist/fbneo/romsets/dataeast.json +1352 -338
- package/dist/fbneo/romsets/galaxian.json +1192 -298
- package/dist/fbneo/romsets/gba.json +197 -0
- package/dist/fbneo/romsets/index.json +16 -12
- package/dist/fbneo/romsets/irem.json +796 -199
- package/dist/fbneo/romsets/konami.json +1644 -411
- package/dist/fbneo/romsets/megadrive.json +11899 -2926
- package/dist/fbneo/romsets/midway.json +560 -140
- package/dist/fbneo/romsets/msx.json +7204 -1798
- package/dist/fbneo/romsets/neogeo.json +2704 -614
- package/dist/fbneo/romsets/nes.json +12815 -3155
- package/dist/fbneo/romsets/pce.json +1952 -488
- package/dist/fbneo/romsets/pgm.json +796 -199
- package/dist/fbneo/romsets/pgm2.json +32 -8
- package/dist/fbneo/romsets/pre90s.json +10002 -2084
- package/dist/fbneo/romsets/psikyo.json +160 -40
- package/dist/fbneo/romsets/pst90s.json +6400 -1597
- package/dist/fbneo/romsets/sega.json +2756 -658
- package/dist/fbneo/romsets/sg1000.json +1032 -255
- package/dist/fbneo/romsets/sms.json +6012 -1503
- package/dist/fbneo/romsets/snes.json +10991 -2816
- package/dist/fbneo/romsets/spectrum.json +13579 -3361
- package/dist/fbneo/romsets/taito.json +2496 -624
- package/dist/fbneo/romsets/toaplan.json +576 -144
- package/package.json +1 -1
- package/src/app/app.js +1 -1
- package/src/fbneo.options.ts +12 -0
- package/src/fbneo.sdk.ts +70 -1
- package/src/romset.ts +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wasm-gaming/fbneo-wasm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "FBNeo (FinalBurn Neo arcade emulator) compiled to WebAssembly, with a self-contained JS SDK implementing the wasm-gaming engine contract.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
package/src/app/app.js
CHANGED
|
@@ -619,7 +619,7 @@ export async function mount(target, host) {
|
|
|
619
619
|
render();
|
|
620
620
|
play = await new FbneoSDK()
|
|
621
621
|
.mount(stage)
|
|
622
|
-
.options({ driver })
|
|
622
|
+
.options({ driver, ...(host.options?.neogeo ? { neogeo: host.options.neogeo } : {}) })
|
|
623
623
|
.assets({ ...host.assets, rom })
|
|
624
624
|
.storage(host.storage)
|
|
625
625
|
.on('error', ({ detail }) => console.error('[fbneo app]', detail))
|
package/src/fbneo.options.ts
CHANGED
|
@@ -34,6 +34,12 @@ export interface FbneoOptions {
|
|
|
34
34
|
driver?: string;
|
|
35
35
|
/** The ROM zip's file name (`mslug.zip`), used for the driver when `driver` is empty. */
|
|
36
36
|
romFileName?: string;
|
|
37
|
+
/**
|
|
38
|
+
* How a Neo Geo set boots: `mvs`, the arcade board (coins, credits — FBNeo's default),
|
|
39
|
+
* or `aes`, the home console: the AES BIOS from the `bios` zip (or Universe BIOS 4.0 in
|
|
40
|
+
* AES mode) and a memory card per game. Other systems ignore it.
|
|
41
|
+
*/
|
|
42
|
+
neogeo?: 'mvs' | 'aes';
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
export interface FbneoAssets {
|
|
@@ -99,6 +105,12 @@ export const FBNEO_SPEC: EngineSpec<FbneoPayloads> = {
|
|
|
99
105
|
live: false,
|
|
100
106
|
description: 'The ROM zip file name; its stem is the driver when driver is empty.',
|
|
101
107
|
},
|
|
108
|
+
neogeo: {
|
|
109
|
+
default: 'mvs',
|
|
110
|
+
enum: ['mvs', 'aes'],
|
|
111
|
+
live: false,
|
|
112
|
+
description: 'Neo Geo sets: mvs (arcade, FBNeo default) or aes (home console: AES BIOS, memory card).',
|
|
113
|
+
},
|
|
102
114
|
},
|
|
103
115
|
assets: {
|
|
104
116
|
rom: {
|
package/src/fbneo.sdk.ts
CHANGED
|
@@ -54,6 +54,7 @@ export type {
|
|
|
54
54
|
FbneoStorage,
|
|
55
55
|
} from './fbneo.options.js';
|
|
56
56
|
export { FBNEO_SPEC, FBNEO_VIDEO } from './fbneo.options.js';
|
|
57
|
+
import { parseZipEntries } from './romset.js';
|
|
57
58
|
|
|
58
59
|
const ENGINE_ID = 'fbneo';
|
|
59
60
|
const DEFAULT_STORAGE_NAMESPACE = 'default';
|
|
@@ -86,6 +87,8 @@ interface FbneoModule {
|
|
|
86
87
|
_web_load_state(slot: number): number;
|
|
87
88
|
_web_running(): number;
|
|
88
89
|
_web_quit(): void;
|
|
90
|
+
_web_memcard_insert(): number;
|
|
91
|
+
ccall(name: string, returnType: 'number', argTypes: string[], args: unknown[]): number;
|
|
89
92
|
SDL2?: { audioContext?: AudioContext };
|
|
90
93
|
}
|
|
91
94
|
|
|
@@ -153,6 +156,30 @@ function sameBytes(a: Uint8Array | undefined, b: Uint8Array): boolean {
|
|
|
153
156
|
return true;
|
|
154
157
|
}
|
|
155
158
|
|
|
159
|
+
/** The Neo Geo BIOS FBNeo should run, from what the BIOS zip holds (by CRC). */
|
|
160
|
+
export interface NeoGeoBiosChoice {
|
|
161
|
+
/** `aes`: the real AES BIOS; `unibios`: Universe BIOS 4.0 in its AES mode. */
|
|
162
|
+
bios: 'aes' | 'unibios';
|
|
163
|
+
/** The driver's settings to apply: `[group, option]`, as FBNeo names them. */
|
|
164
|
+
dips: Array<[string, string]>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const AES_WORLD_CRC = 'd27a71f1'; // neo-epo.bin
|
|
168
|
+
const UNIBIOS_40_CRC = 'a7aab458'; // uni-bios_4_0.rom
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* How to boot a Neo Geo as the AES (the home console) with the BIOS zip at hand: the
|
|
172
|
+
* real AES World BIOS when it is there, else Universe BIOS 4.0 in AES mode, else null.
|
|
173
|
+
*/
|
|
174
|
+
export function neoGeoAesBios(entries: Array<{ crc: string }>): NeoGeoBiosChoice | null {
|
|
175
|
+
const crcs = new Set(entries.map((entry) => entry.crc.toLowerCase()));
|
|
176
|
+
if (crcs.has(AES_WORLD_CRC)) return { bios: 'aes', dips: [['BIOS', 'AES World']] };
|
|
177
|
+
if (crcs.has(UNIBIOS_40_CRC)) {
|
|
178
|
+
return { bios: 'unibios', dips: [['BIOS', 'Universe BIOS (Hack, Ver. 4.0)'], ['Unibios mode', 'AES']] };
|
|
179
|
+
}
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
|
|
156
183
|
/** The player's save-state slots: 0-3. */
|
|
157
184
|
export const STATE_SLOTS = 4;
|
|
158
185
|
/**
|
|
@@ -198,6 +225,7 @@ export class FbneoPlay extends EnginePlayBase<FbneoPayloads> {
|
|
|
198
225
|
#destroyed = false;
|
|
199
226
|
#pauseOwner: string | null = null;
|
|
200
227
|
#driver = '';
|
|
228
|
+
#neogeo: { mode: 'aes'; bios: 'aes' | 'unibios'; card: boolean } | null = null;
|
|
201
229
|
|
|
202
230
|
#canvas: HTMLCanvasElement | null = null;
|
|
203
231
|
#ownsCanvas = false;
|
|
@@ -234,6 +262,11 @@ export class FbneoPlay extends EnginePlayBase<FbneoPayloads> {
|
|
|
234
262
|
return this.#driver;
|
|
235
263
|
}
|
|
236
264
|
|
|
265
|
+
/** How a Neo Geo set was booted as the AES: `{ mode, bios, card }`; null otherwise. */
|
|
266
|
+
get neogeo(): { mode: 'aes'; bios: 'aes' | 'unibios'; card: boolean } | null {
|
|
267
|
+
return this.#neogeo;
|
|
268
|
+
}
|
|
269
|
+
|
|
237
270
|
/** Who holds the pause, or null while running. */
|
|
238
271
|
get pausedBy(): string | null {
|
|
239
272
|
return this.#pauseOwner;
|
|
@@ -572,6 +605,8 @@ export class FbneoPlay extends EnginePlayBase<FbneoPayloads> {
|
|
|
572
605
|
);
|
|
573
606
|
}
|
|
574
607
|
|
|
608
|
+
if (options.neogeo === 'aes') await this.#bootAes(Module, bios);
|
|
609
|
+
|
|
575
610
|
if (this.#persist) {
|
|
576
611
|
this.#saveTimer = setInterval(() => void this.flushSaves(), SAVE_INTERVAL_MS);
|
|
577
612
|
document.addEventListener('visibilitychange', this.#onHidden);
|
|
@@ -580,6 +615,40 @@ export class FbneoPlay extends EnginePlayBase<FbneoPayloads> {
|
|
|
580
615
|
this.#fit();
|
|
581
616
|
}
|
|
582
617
|
|
|
618
|
+
/**
|
|
619
|
+
* Neo Geo as the AES: pick the BIOS from the BIOS zip, set the driver's BIOS settings,
|
|
620
|
+
* insert the game's memory card and reset, so the machine boots that BIOS (FBNeo
|
|
621
|
+
* loads it at reset). A set that isn't Neo Geo has no "BIOS" setting: left as is.
|
|
622
|
+
*/
|
|
623
|
+
async #bootAes(Module: FbneoModule, bios: Uint8Array | null): Promise<void> {
|
|
624
|
+
let choice: NeoGeoBiosChoice | null = null;
|
|
625
|
+
try {
|
|
626
|
+
choice = bios ? neoGeoAesBios(parseZipEntries(bios)) : null;
|
|
627
|
+
} catch {
|
|
628
|
+
choice = null; // not a zip: no BIOS to choose from
|
|
629
|
+
}
|
|
630
|
+
const setDip = (group: string, option: string): boolean =>
|
|
631
|
+
Module.ccall('web_set_dip', 'number', ['string', 'string'], [group, option]) === 1;
|
|
632
|
+
if (!choice) {
|
|
633
|
+
// Only a Neo Geo driver has the setting; anything else plays as it always has.
|
|
634
|
+
if (!setDip('BIOS', 'AES World')) return;
|
|
635
|
+
throw new Error(
|
|
636
|
+
'fbneo: Neo Geo as the AES needs a BIOS zip (neogeo.zip) with the AES BIOS (neo-epo.bin) or Universe BIOS 4.0',
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
for (const [group, option] of choice.dips) {
|
|
640
|
+
if (!setDip(group, option)) {
|
|
641
|
+
if (group === 'BIOS') return; // not a Neo Geo set
|
|
642
|
+
throw new Error(`fbneo: this FBNeo build has no "${group}: ${option}" setting`);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
const card = Module._web_memcard_insert() === 1;
|
|
646
|
+
// The settings reach the driver on the next frame; the BIOS is loaded at reset.
|
|
647
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
648
|
+
Module._web_reset();
|
|
649
|
+
this.#neogeo = { mode: 'aes', bios: choice.bios, card };
|
|
650
|
+
}
|
|
651
|
+
|
|
583
652
|
/** The plain values behind one payload's descriptors. */
|
|
584
653
|
async #values<T>(kind: 'config' | 'options' | 'assets' | 'storage'): Promise<T> {
|
|
585
654
|
const described = (await this[kind]()) as Record<string, { value: unknown }>;
|
|
@@ -669,7 +738,7 @@ export class FbneoPlay extends EnginePlayBase<FbneoPayloads> {
|
|
|
669
738
|
export class FbneoSDK extends EngineSDKBase<FbneoPayloads> {
|
|
670
739
|
static readonly id = ENGINE_ID;
|
|
671
740
|
/** Kept in step with package.json by `node scripts/sync-version.mjs`. */
|
|
672
|
-
static readonly version = '0.
|
|
741
|
+
static readonly version = '0.3.0';
|
|
673
742
|
static readonly name = 'FinalBurn Neo';
|
|
674
743
|
static readonly description =
|
|
675
744
|
'FBNeo, the arcade emulator (Capcom CPS-1/2/3, SNK Neo Geo, Sega System 16 and more), compiled to WebAssembly. Ships no games: the player provides the ROM sets, and they never leave their browser.';
|
package/src/romset.ts
CHANGED
|
Binary file
|