Skip to content

feat: playable Win3.x and Win9.x using js-dos - #4061

Open
bphenriques wants to merge 3 commits into
rommapp:masterfrom
bphenriques:3143-jsdos-backend
Open

feat: playable Win3.x and Win9.x using js-dos#4061
bphenriques wants to merge 3 commits into
rommapp:masterfrom
bphenriques:3143-jsdos-backend

Conversation

@bphenriques

@bphenriques bphenriques commented Aug 1, 2026

Copy link
Copy Markdown

Closes #3143

The current EmulatorJS dosbox-pure core handles MS-DOS games but blank-screens tested Windows 3.x and Windows 9x titles. This PR adds js-dos v8.4.1 with its DOSBox-X backend as a dedicated in-browser player for the win3x and win9x platforms.

Related docs PR: rommapp/docs#110

Out of scope

To keep the integration narrow:

  • MS-DOS remains on EmulatorJS, even though js-dos can also run DOS games.
  • Saves remain browser-local and are not synchronized with RomM.
  • Runtime readiness and bundle validation are deferred.

Changes

The integration follows the existing EmulatorJS and Ruffle patterns:

  • Adds the v2 js-dos player and /rom/:rom/jsdos route.
  • Adds the DISABLE_JSDOS administrator toggle.
  • Bundles a pinned, checksummed js-dos release under /assets/jsdos in the full Docker image.
  • Serves runtime assets same-origin with the required cross-origin isolation headers.
  • Enables DOSBox-X, automatic startup, and automatic saving.
  • Stores saves locally, isolated by RomM user and ROM.
  • Performs a final save before leaving and handles unconfirmed save failures.
  • Hides the dos.zone cloud UI with setNoCloud(true).
  • Adds API types and automated coverage for routing, persistence, and player lifecycle.

Test plan

Automated tests cover player lifecycle, final-save handling, route departure, duplicate exits, and per-user save isolation. The remaining frontend, backend, build, and lint checks run in CI.

Tested titles:

  • Fine Artist, which saves only after exiting the application back to Windows
  • Four Magic School Bus titles
  • Timon & Pumbaa's Jungle Games

Manual checks:

  • Games start automatically.
  • Saves persist between sessions.
  • Saves are isolated between RomM users.
  • Quitting returns to the game details page.
  • The dos.zone cloud UI is hidden.

AI assistance disclosure

This contribution was developed with assistance from Amp and Claude. I reviewed, tested, and validated the design, implementation, and tests, and I take responsibility for the changes.

@gantoine
gantoine self-requested a review August 1, 2026 23:10
@gantoine gantoine added the on-hold Pending further research or blocked by another issue label Aug 1, 2026
@bphenriques
bphenriques force-pushed the 3143-jsdos-backend branch 2 times, most recently from 1c56c39 to f827acc Compare August 3, 2026 10:45
@bphenriques

bphenriques commented Aug 3, 2026

Copy link
Copy Markdown
Author

Actions to review:

Will review later this week once my weekly limits resets. Taking a look by hand in the meantime (just slower).

Done.

@bphenriques bphenriques changed the title [WIP] feat: playable Win3.x and Win9.x using js-dos feat: playable Win3.x and Win9.x using js-dos Aug 16, 2026
@bphenriques

Copy link
Copy Markdown
Author

@gantoine, I think this is ready for an initial review when you have a chance. I tested saving plus if the launch/exit UX behave as expected. Please also take a look at the accompanying documentation PR.

As mentioned, I used AI assistance for the initial design and subsequent implementation review. The integration went through several iterations to keep the scope focused and consistent with existing players.

I am not an expert on this part of the codebase, so I would appreciate your feedback!

Thank you

@bphenriques
bphenriques marked this pull request as ready for review August 16, 2026 18:17
Copilot AI lite review requested due to automatic review settings August 16, 2026 18:17
"deselect-save": "Отмени избрания запис",
"deselect-state": "Отмени избрания бърз запис",
"full-screen": "Цял екран",
"jsdos-browser-save-warning": "Запазените данни на js-dos се съхраняват само в този браузър и не се синхронизират с RomM.",

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.

These translations were AI assisted. It was not required when I started the PR but now it is.

"deselect-save": "Desmarcar save",
"deselect-state": "Desmarcar estado",
"full-screen": "Tela cheia",
"jsdos-browser-save-warning": "Os saves do js-dos são armazenados apenas neste navegador e não são sincronizados com o RomM.",

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.

My language (albeit in pt-BR rather than pt-PT). Sensible translation 👍

@@ -0,0 +1,34 @@
export interface JsDosOptions {

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.

Ddeliberately small subset of the official js-dos v8 types. Limited to the APIs RomM uses.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an in-browser js-dos (DOSBox-X) player path to RomM so Win3.x / Win9x ROMs can be played without the blank-screen issues seen with the existing EmulatorJS DOS core. This fits into the existing v2 player architecture alongside EmulatorJS and Ruffle, including cross-origin isolation support for SharedArrayBuffer and an admin-disable toggle surfaced via heartbeat.

Changes:

  • Added a new v2 js-dos player view plus router wiring and play-action selection for win3x / win9x.
  • Introduced DISABLE_JSDOS across backend config + heartbeat, and frontend support gating via useCanPlay / utils.
  • Bundled a pinned js-dos release into the full Docker image and extended Nginx COOP/COEP headers for the new player route.

Reviewed changes

Copilot reviewed 35 out of 37 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/src/v2/views/Player/JsDos.vue New js-dos player view (runtime loader, lifecycle, local save scoping, quit flow).
frontend/src/v2/views/Player/JsDos.test.ts Vitest coverage for js-dos player lifecycle, final-save flow, and save-key scoping.
frontend/src/v2/router/routes.ts Registers the new v2 route component loader for jsdos.
frontend/src/v2/composables/useGameActions/index.ts Routes Win3x/Win9x play actions to a hard navigation for /rom/:id/jsdos (SAB).
frontend/src/v2/composables/useGameActions/index.test.ts Adds coverage ensuring js-dos is preferred over EmulatorJS for its platforms.
frontend/src/v2/composables/useCanPlay/index.ts Adds canPlayJsDos and integrates it into the overall in-browser playability gate.
frontend/src/utils/index.ts Adds isJsDosEmulationSupported() with DISABLE_JSDOS + platform slug support checks.
frontend/src/utils/index.test.ts Unit tests for js-dos platform support logic, case-insensitivity, toggle behavior, and remap.
frontend/src/types/js-dos.d.ts Adds TypeScript typings for the js-dos runtime factory and API surface used by the player.
frontend/src/stores/heartbeat.ts Extends the default heartbeat shape with EMULATION.DISABLE_JSDOS.
frontend/src/plugins/router.ts Adds the /rom/:rom/jsdos route and ROUTES.JSDOS constant.
frontend/src/locales/bg_BG/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/cs_CZ/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/de_DE/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/en_GB/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/en_US/play.json Adds new play.* strings for js-dos save warning and quit confirmation (source locale).
frontend/src/locales/es_ES/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/fr_FR/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/hu_HU/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/it_IT/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/ja_JP/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/ko_KR/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/pl_PL/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/pt_BR/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/ro_RO/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/ru_RU/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/tr_TR/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/zh_CN/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/locales/zh_TW/play.json Adds new play.* strings for js-dos save warning and quit confirmation.
frontend/src/generated/models/EmulationDict.ts Updates generated OpenAPI types to include DISABLE_JSDOS.
env.template Documents the new DISABLE_JSDOS env var.
docker/nginx/templates/default.conf.template Adds COOP/COEP header mapping for the new /rom/*/jsdos player route.
docker/Dockerfile Downloads and verifies js-dos release, then ships runtime assets into the full image.
backend/tests/endpoints/test_heartbeat.py Extends heartbeat endpoint test to validate DISABLE_JSDOS is present and boolean.
backend/endpoints/responses/heartbeat.py Extends the typed heartbeat response schema with DISABLE_JSDOS.
backend/endpoints/heartbeat.py Includes DISABLE_JSDOS in the /heartbeat response payload.
backend/config/init.py Adds env-var wiring for DISABLE_JSDOS.
Files not reviewed (1)
  • frontend/src/generated/models/EmulationDict.ts: Generated file
Suppressed comments (1)

frontend/src/v2/views/Player/JsDos.vue:186

  • The "Back to gallery" navigation depends on rom.value?.platform_id, which may be unset until the ROM request resolves. Use the seeded ROM data when available, and avoid pushing with an undefined param.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread frontend/src/v2/views/Player/JsDos.vue Outdated
Comment thread frontend/src/v2/views/Player/JsDos.vue
Comment thread frontend/src/v2/views/Player/JsDos.vue Outdated
// DOSBox-X provides Windows support.
dos = dosFactory(stage.value, {
url: getDownloadPath({ rom: currentRom }),
backend: "dosboxX",

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.

There are multiple backends. I want to keep this PR minimal and adjust as needed rather than trying to replicate every possible 'knob'.

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

Labels

on-hold Pending further research or blocked by another issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Introduce JS-DOS as a new DOS backend

3 participants