Skip to content

Add MSX, MSX2 and SG-1000 support via the blueMSX core - #1244

Open
LokiCode404 wants to merge 3 commits into
EmulatorJS:mainfrom
LokiCode404:main
Open

LokiCode404 wants to merge 3 commits into
EmulatorJS:mainfrom
LokiCode404:main

Conversation

@LokiCode404

@LokiCode404 LokiCode404 commented Jul 30, 2026

Copy link
Copy Markdown
  • Register msx, msx2, and sg1000 systems in the core registry, all pointing to the bluemsx core. Also add bluemsx as an alternative core for the coleco system.
  • Add @emulatorjs/core-bluemsx npm dependency.
  • Set system_directory in retroarch.cfg so blueMSX can locate its Machines/ and Databases/ on the virtual filesystem. Without this the directory resolved to / and the core failed to find its machine configurations (root cause of the silent content load failure).
  • Add MSX, MSX2 and Sega SG-1000 entries to the demo page system selector dropdown.

How to build and test

1. Clone the core source

git clone https://github.com/LokiCode404/blueMSX-libretro.git

This fork includes the Emscripten build flags and the C-BIOS
fallback from the companion PR libretro/blueMSX-libretro#207.

2. Build

cd EmulatorJS/build
bash build.sh --core=bluemsx

The build script will compile the core to WASM with ASYNCIFY=1
and package the C-BIOS Machines/Databases into the .data archive.

3. Test
The compiled bluemsx-wasm.data and bluemsx-legacy-wasm.data
go into data/cores/ of the EmulatorJS frontend.

Load it with:

<script>
  EJS_core = 'bluemsx';
  EJS_gameUrl = '/roms/game.rom';
  EJS_biosUrl = '/bios/bluemsx-system.zip';
  EJS_pathtodata = '/data/';
  EJS_player = '#game';
  EJS_startOnLoaded = false;
</script>

Pre-built system files

A system files zip containing the freely redistributable C-BIOS
ROMs and all Machine/Database configs is attached below.
It includes C-BIOS variants for MSX1, MSX2, and MSX2+ that work
with most cartridge ROMs without proprietary BIOS files.

The zip structure maps to the Emscripten virtual filesystem:
home/web_user/retroarch/system/{Machines,Databases}/

[bluemsx-system.zip](https://github.com/user-attachments/files/30562391/bluemsx-system.zip)


## C-BIOS verification

Tested successfully with a C-BIOS-only system zip (3 C-BIOS machines,
no proprietary ROMs at all, 346KB). The fallback cascade in
libretro.c correctly falls through MSX2+ -> MSX2+ C-BIOS -> MSX2 C-BIOS
-> MSX C-BIOS when proprietary BIOS ROMs are absent.

A pre-built C-BIOS-only zip is attached below for testing:

[bluemsx-cbios-only.zip](https://github.com/user-attachments/files/30563305/bluemsx-cbios-only.zip)

Video: https://www.dropbox.com/scl/fi/e2gwjgd05dbxijzqxd5p8/bluemsx-1942rom-trimmed.mkv?rlkey=0rqnr335g4xtpuqnmll4q4515&dl=0

- Register msx, msx2, and sg1000 systems in the core registry,
  all pointing to the bluemsx core. Also add bluemsx as an
  alternative core for the coleco system.
- Add @emulatorjs/core-bluemsx npm dependency.
- Set system_directory in retroarch.cfg so blueMSX can locate
  its Machines/ and Databases/ on the virtual filesystem.
  Without this the directory resolved to / and the core failed
  to find its machine configurations (root cause of the silent
  content load failure).
- Add MSX, MSX2 and Sega SG-1000 entries to the demo page
  system selector dropdown.
When the browser supports WebAssembly.Suspending (Chrome 123+, Firefox 132+,
Edge), load the JSPI-compiled core (bluemsx-wasm.data) instead of the Asyncify
fallback (bluemsx-legacy-wasm.data). Selection is transparent to the user.
@LokiCode404

Copy link
Copy Markdown
Author

Quick update — I've pushed a new commit with JSPI detection for the blueMSX core.
On browsers that support WebAssembly.Suspending (Chrome 123+, Firefox 132+, Edge), the loader now picks up a JSPI-compiled build (bluemsx-wasm.data) that has zero Asyncify instrumentation overhead. Browsers without JSPI (Safari, older versions) fall back to the Asyncify build automatically via the existing legacy/non-legacy naming convention. No changes needed on the user side — it's transparent.
The detection is a few lines in emulator.js during core selection:

  • Check typeof WebAssembly.Suspending === "function"
  • If not supported → force -legacy suffix → loads the Asyncify fallback
    This pairs with the corresponding changes in the RetroArch build (PR More Stuff (Add record button) #46) that produce the two WASM variants.

Comment thread data/cores/package.json
"@emulatorjs/core-prboom": "latest",
"@emulatorjs/core-ppsspp": "latest"
"@emulatorjs/core-ppsspp": "latest",
"@emulatorjs/core-bluemsx": "latest"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have access to the npm repo, I think, so we'll probably need to wait until this other developer is available for me to create this

@ethanaobrien ethanaobrien left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for taking so long to review this. Only a few minor changes requested

Comment thread data/src/GameManager.js Outdated
Comment on lines +160 to +162
// blueMSX looks for Machines/ and Databases/ under RetroArch's
// system_directory. Without this the directory resolves to "/"
// and the core cannot find its machine configurations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to have a blueMSX specific comment here (ai likes to do this lol)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha, I use AI to comment out parts of the code in large projects so I don't get lost. I use my own core testing page and when it works, I integrate it into your project. Actually, that comment was for me.

Comment thread data/src/emulator.js Outdated
// JSPI detection: cores with dual JSPI+Asyncify builds use the
// non-legacy slot for JSPI and the legacy slot for Asyncify.
// Browsers without JSPI support automatically get the Asyncify fallback.
const jspiCores = ["bluemsx"];

@ethanaobrien ethanaobrien Sep 20, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be in consts.js

Also btw, on JSPI detection, doesn't the backend need a toggle for this? I've never heard of this feature (probably very new), sorry about that

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved jspiCores over to consts.js like you said, and took out that bluemsx comment on system_directory.

JSPI is pretty new, no worries. It's a WASM thing (WebAssembly.Suspending) that lets you pause a sync call without Asyncify rewriting the whole binary. blueMSX needs it because it does sync fopen while loading the machine XML, but Asyncify also hits the Z80 loop, which runs millions of times a second and tanks performance. JSPI doesn't do that. Chrome/Firefox/Edge have it, Safari doesn't.

And yeah, the backend needs a compile flag. This isn't a runtime toggle, it's two different WASM builds (-s JSPI=1 or Asyncify). The JS side just checks if WebAssembly.Suspending exists and downloads bluemsx-wasm.data or the -legacy one. I reused the legacy slot because bluemsx doesn't use GLES3.

#46 only added it to needsAsync, so right now both files would still be full Asyncify. I can open another PR on RetroArch with USE_JSPI if you want.

Address review feedback: jspiCores lives next to requiresThreads /
requiresWebGL2, and the bluemsx-specific comment on system_directory
is removed. Detection still falls back to the Asyncify (-legacy) build
when WebAssembly.Suspending is missing.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants