feat: playable Win3.x and Win9.x using js-dos - #4061
Conversation
1c56c39 to
f827acc
Compare
|
Done. |
Amp-Thread-ID: https://ampcode.com/threads/T-019fcd57-445f-754d-9a5b-a45cf2878d99 Co-authored-by: Amp <amp@ampcode.com>
ea70764 to
dc11901
Compare
|
@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 |
| "deselect-save": "Отмени избрания запис", | ||
| "deselect-state": "Отмени избрания бърз запис", | ||
| "full-screen": "Цял екран", | ||
| "jsdos-browser-save-warning": "Запазените данни на js-dos се съхраняват само в този браузър и не се синхронизират с RomM.", |
There was a problem hiding this comment.
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.", |
There was a problem hiding this comment.
My language (albeit in pt-BR rather than pt-PT). Sensible translation 👍
| @@ -0,0 +1,34 @@ | |||
| export interface JsDosOptions { | |||
There was a problem hiding this comment.
Ddeliberately small subset of the official js-dos v8 types. Limited to the APIs RomM uses.
There was a problem hiding this comment.
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_JSDOSacross backend config + heartbeat, and frontend support gating viauseCanPlay/ 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.
Co-authored-by: Amp <amp@ampcode.com> Amp-Thread-ID: https://ampcode.com/threads/T-019fcd57-445f-754d-9a5b-a45cf2878d99
| // DOSBox-X provides Windows support. | ||
| dos = dosFactory(stage.value, { | ||
| url: getDownloadPath({ rom: currentRom }), | ||
| backend: "dosboxX", |
There was a problem hiding this comment.
There are multiple backends. I want to keep this PR minimal and adjust as needed rather than trying to replicate every possible 'knob'.
Closes #3143
The current EmulatorJS
dosbox-purecore handles MS-DOS games but blank-screens tested Windows 3.x and Windows 9x titles. This PR addsjs-dosv8.4.1 with its DOSBox-X backend as a dedicated in-browser player for thewin3xandwin9xplatforms.Related docs PR: rommapp/docs#110
Out of scope
To keep the integration narrow:
js-doscan also run DOS games.Changes
The integration follows the existing EmulatorJS and Ruffle patterns:
js-dosplayer and/rom/:rom/jsdosroute.DISABLE_JSDOSadministrator toggle.js-dosrelease under/assets/jsdosin the full Docker image.setNoCloud(true).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:
Manual checks:
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.