Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions backend/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ def _get_env(var: str, fallback: str | None = None) -> str | None:
# EMULATION
DISABLE_EMULATOR_JS: Final[bool] = safe_str_to_bool(_get_env("DISABLE_EMULATOR_JS"))
DISABLE_RUFFLE_RS: Final[bool] = safe_str_to_bool(_get_env("DISABLE_RUFFLE_RS"))
DISABLE_JSDOS: Final[bool] = safe_str_to_bool(_get_env("DISABLE_JSDOS"))

# FRONTEND
KIOSK_MODE: Final[bool] = safe_str_to_bool(_get_env("KIOSK_MODE"))
Expand Down
2 changes: 2 additions & 0 deletions backend/endpoints/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from config import (
DISABLE_EMULATOR_JS,
DISABLE_JSDOS,
DISABLE_LOGS_VIEWER,
DISABLE_RUFFLE_RS,
DISABLE_SETUP_WIZARD,
Expand Down Expand Up @@ -116,6 +117,7 @@ async def heartbeat() -> HeartbeatResponse:
"EMULATION": {
"DISABLE_EMULATOR_JS": DISABLE_EMULATOR_JS,
"DISABLE_RUFFLE_RS": DISABLE_RUFFLE_RS,
"DISABLE_JSDOS": DISABLE_JSDOS,
},
"FRONTEND": {
"DISABLE_USERPASS_LOGIN": DISABLE_USERPASS_LOGIN,
Expand Down
1 change: 1 addition & 0 deletions backend/endpoints/responses/heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class FilesystemDict(TypedDict):
class EmulationDict(TypedDict):
DISABLE_EMULATOR_JS: bool
DISABLE_RUFFLE_RS: bool
DISABLE_JSDOS: bool


class FrontendDict(TypedDict):
Expand Down
1 change: 1 addition & 0 deletions backend/tests/endpoints/test_heartbeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def test_heartbeat(client):
emulation = heartbeat["EMULATION"]
assert isinstance(emulation["DISABLE_EMULATOR_JS"], bool)
assert isinstance(emulation["DISABLE_RUFFLE_RS"], bool)
assert isinstance(emulation["DISABLE_JSDOS"], bool)

assert "FRONTEND" in heartbeat
frontend = heartbeat["FRONTEND"]
Expand Down
9 changes: 9 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ RUN wget "https://github.com/ruffle-rs/ruffle/releases/download/${RUFFLE_VERSION
unzip -o "${RUFFLE_FILE}" -d /ruffle && \
rm -f "${RUFFLE_FILE}"

ARG JSDOS_VERSION=8.4.1
ARG JSDOS_SHA256=26118692bbb180aec78ec1697eb1ea6b28ff410101870cfa3e68309914c7eaa6

RUN wget "https://github.com/caiiiycuk/js-dos/releases/download/v${JSDOS_VERSION}/release.zip" -O jsdos.zip && \
echo "${JSDOS_SHA256} jsdos.zip" | sha256sum -c - && \
unzip -o jsdos.zip -d /jsdos && \
rm -f jsdos.zip


# BUILD NGINX MODULE WITH MOD_ZIP
FROM alpine:${ALPINE_VERSION}@sha256:${ALPINE_SHA256} AS nginx-build
Expand Down Expand Up @@ -254,6 +262,7 @@ FROM slim-image AS full-image
ARG WEBSERVER_FOLDER=/var/www/html
COPY --from=emulator-stage /emulatorjs ${WEBSERVER_FOLDER}/assets/emulatorjs
COPY --from=emulator-stage /ruffle ${WEBSERVER_FOLDER}/assets/ruffle
COPY --from=emulator-stage /jsdos/dist ${WEBSERVER_FOLDER}/assets/jsdos


FROM slim-image AS dev-slim
Expand Down
6 changes: 4 additions & 2 deletions docker/nginx/templates/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ map $http_x_forwarded_proto $forwardscheme {
}

# COEP and COOP headers for cross-origin isolation, which are set only for the
# EmulatorJS player paths, to enable SharedArrayBuffer support, which is needed
# for multi-threaded cores.
# EmulatorJS and js-dos player paths, to enable SharedArrayBuffer support, which
# is needed for multi-threaded cores.
map $request_uri $coep_header {
default "";
~^/rom/.*/ejs$ "require-corp";
~^/rom/.*/jsdos$ "require-corp";
~^/console/rom/[0-9]+/play "require-corp";
}
map $request_uri $coop_header {
default "";
~^/rom/.*/ejs$ "same-origin";
~^/rom/.*/jsdos$ "same-origin";
~^/console/rom/[0-9]+/play "same-origin";
}

Expand Down
1 change: 1 addition & 0 deletions env.template
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ SYNC_SSH_KNOWN_HOSTS_PATH= # Path to SSH known_hosts (defaults to $ROMM_BASE_PA
# Emulation
DISABLE_EMULATOR_JS=false # Disable in-browser play via EmulatorJS
DISABLE_RUFFLE_RS=false # Disable in-browser Flash playback via RuffleRS
DISABLE_JSDOS=false # Disable in-browser Win3.x and Win9.x playback via js-dos

# Integrations
YOUTUBE_BASE_URL=https://www.youtube.com # Base URL for alternate YouTube frontends (Piped, Invidious, etc.)
Expand Down
1 change: 1 addition & 0 deletions frontend/src/__generated__/models/EmulationDict.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/src/locales/bg_BG/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"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.

"jsdos-quit-without-saving": "Изход без запазване на скорошния напредък?",
"no-save-selected": "Няма избран запис",
"no-saves-available": "Няма налични записи",
"no-screenshot-available": "Няма налична екранна снимка",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/cs_CZ/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Zrušit výběr uložené pozice",
"deselect-state": "Zrušit výběr stavu",
"full-screen": "Celá obrazovka",
"jsdos-browser-save-warning": "Pozice js-dos se ukládají pouze v tomto prohlížeči a nesynchronizují se s RomM.",
"jsdos-quit-without-saving": "Ukončit bez uložení posledního postupu?",
"no-save-selected": "Není vybrána žádná uložená pozice",
"no-saves-available": "Nejsou k dispozici žádné uložené pozice",
"no-screenshot-available": "Žádný screenshot není k dispozici",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/de_DE/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Speicherstand abwählen",
"deselect-state": "Speicherstand abwählen",
"full-screen": "Vollbild",
"jsdos-browser-save-warning": "js-dos-Spielstände werden nur in diesem Browser gespeichert und nicht mit RomM synchronisiert.",
"jsdos-quit-without-saving": "Beenden, ohne den letzten Fortschritt zu speichern?",
"no-save-selected": "Kein Speicherstand ausgewählt",
"no-saves-available": "Keine Speicherstände verfügbar",
"no-screenshot-available": "Kein Screenshot verfügbar",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/en_GB/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Deselect save",
"deselect-state": "Deselect state",
"full-screen": "Full screen",
"jsdos-browser-save-warning": "js-dos saves are stored only in this browser and are not synced with RomM.",
"jsdos-quit-without-saving": "Quit without saving recent progress?",
"no-save-selected": "No save selected",
"no-saves-available": "No saves available",
"no-screenshot-available": "No screenshot available",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/en_US/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Deselect save",
"deselect-state": "Deselect state",
"full-screen": "Full screen",
"jsdos-browser-save-warning": "js-dos saves are stored only in this browser and are not synced with RomM.",
"jsdos-quit-without-saving": "Quit without saving recent progress?",
"no-save-selected": "No save selected",
"no-saves-available": "No saves available",
"no-screenshot-available": "No screenshot available",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/es_ES/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Deseleccionar guardado",
"deselect-state": "Deseleccionar estado",
"full-screen": "Pantalla completa",
"jsdos-browser-save-warning": "Las partidas de js-dos se almacenan solo en este navegador y no se sincronizan con RomM.",
"jsdos-quit-without-saving": "¿Salir sin guardar el progreso reciente?",
"no-save-selected": "Ningún guardado seleccionado",
"no-saves-available": "No hay guardados disponibles",
"no-screenshot-available": "Captura no disponible",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/fr_FR/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Désélectionner la sauvegarde",
"deselect-state": "Désélectionner l'état",
"full-screen": "Plein écran",
"jsdos-browser-save-warning": "Les sauvegardes js-dos sont stockées uniquement dans ce navigateur et ne sont pas synchronisées avec RomM.",
"jsdos-quit-without-saving": "Quitter sans enregistrer la progression récente ?",
"no-save-selected": "Aucune sauvegarde sélectionnée",
"no-saves-available": "Aucune sauvegarde disponible",
"no-screenshot-available": "Aucune capture d'écran disponible",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/hu_HU/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Mentés kiválasztásának törlése",
"deselect-state": "Állás kiválasztásának törlése",
"full-screen": "Teljes képernyő",
"jsdos-browser-save-warning": "A js-dos mentések csak ebben a böngészőben tárolódnak, és nem szinkronizálódnak a RomM-mal.",
"jsdos-quit-without-saving": "Kilépés a legutóbbi előrehaladás mentése nélkül?",
"no-save-selected": "Nincs kiválasztott mentés",
"no-saves-available": "Nincs elérhető mentés",
"no-screenshot-available": "Nincs elérhető képernyőkép",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/it_IT/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Deseleziona Salvataggio",
"deselect-state": "Deseleziona Stato",
"full-screen": "Schermo Intero",
"jsdos-browser-save-warning": "I salvataggi di js-dos vengono archiviati solo in questo browser e non vengono sincronizzati con RomM.",
"jsdos-quit-without-saving": "Uscire senza salvare i progressi recenti?",
"no-save-selected": "Nessun salvataggio selezionato",
"no-saves-available": "Nessun salvataggio disponibile",
"no-screenshot-available": "Nessuno screenshot disponibile",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/ja_JP/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "セーブデータを解除",
"deselect-state": "ステートを解除",
"full-screen": "全画面",
"jsdos-browser-save-warning": "js-dos のセーブデータはこのブラウザーにのみ保存され、RomM とは同期されません。",
"jsdos-quit-without-saving": "最近の進行状況を保存せずに終了しますか?",
"no-save-selected": "セーブデータが選択されていません",
"no-saves-available": "利用可能なセーブデータがありません",
"no-screenshot-available": "スクリーンショットはありません",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/ko_KR/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "세이브 선택 해제",
"deselect-state": "상태 선택 해제",
"full-screen": "전체 화면",
"jsdos-browser-save-warning": "js-dos 저장 데이터는 이 브라우저에만 저장되며 RomM과 동기화되지 않습니다.",
"jsdos-quit-without-saving": "최근 진행 상황을 저장하지 않고 종료하시겠습니까?",
"no-save-selected": "선택된 세이브 없음",
"no-saves-available": "사용 가능한 세이브 없음",
"no-screenshot-available": "사용 가능한 스크린샷이 없습니다",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/pl_PL/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Odznacz zapis",
"deselect-state": "Odznacz stan",
"full-screen": "Pełny ekran",
"jsdos-browser-save-warning": "Zapisy js-dos są przechowywane tylko w tej przeglądarce i nie są synchronizowane z RomM.",
"jsdos-quit-without-saving": "Wyjść bez zapisywania ostatnich postępów?",
"no-save-selected": "Nie wybrano zapisu",
"no-saves-available": "Brak dostępnych zapisów",
"no-screenshot-available": "Brak dostępnych zrzutów ekranu",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/pt_BR/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"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 👍

"jsdos-quit-without-saving": "Sair sem salvar o progresso recente?",
"no-save-selected": "Nenhum save selecionado",
"no-saves-available": "Nenhum save disponível",
"no-screenshot-available": "Nenhuma captura de tela disponível",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/ro_RO/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Deselectează salvare",
"deselect-state": "Deselectează stare",
"full-screen": "Ecran complet",
"jsdos-browser-save-warning": "Salvările js-dos sunt stocate numai în acest browser și nu sunt sincronizate cu RomM.",
"jsdos-quit-without-saving": "Ieși fără a salva progresul recent?",
"no-save-selected": "Nicio salvare selectată",
"no-saves-available": "Nicio salvare disponibilă",
"no-screenshot-available": "Nicio captură disponibilă",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/ru_RU/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Снять выбор сохранения",
"deselect-state": "Снять выбор состояния",
"full-screen": "Полный экран",
"jsdos-browser-save-warning": "Сохранения js-dos хранятся только в этом браузере и не синхронизируются с RomM.",
"jsdos-quit-without-saving": "Выйти, не сохраняя недавний прогресс?",
"no-save-selected": "Сохранение не выбрано",
"no-saves-available": "Нет доступных сохранений",
"no-screenshot-available": "Скриншот недоступен",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/tr_TR/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "Kaydın seçimini kaldır",
"deselect-state": "Durum kaydının seçimini kaldır",
"full-screen": "Tam ekran",
"jsdos-browser-save-warning": "js-dos kayıtları yalnızca bu tarayıcıda saklanır ve RomM ile eşitlenmez.",
"jsdos-quit-without-saving": "Son ilerlemeyi kaydetmeden çıkılsın mı?",
"no-save-selected": "Kayıt seçilmedi",
"no-saves-available": "Mevcut kayıt yok",
"no-screenshot-available": "Ekran görüntüsü yok",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/zh_CN/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "取消选择存档",
"deselect-state": "取消选择状态",
"full-screen": "全屏",
"jsdos-browser-save-warning": "js-dos 存档仅保存在此浏览器中,不会与 RomM 同步。",
"jsdos-quit-without-saving": "不保存最近的进度并退出吗?",
"no-save-selected": "未选择存档",
"no-saves-available": "无可用存档",
"no-screenshot-available": "无可用截图",
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/locales/zh_TW/play.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"deselect-save": "取消選擇存檔",
"deselect-state": "取消選擇即時存檔",
"full-screen": "全螢幕",
"jsdos-browser-save-warning": "js-dos 存檔僅保存在此瀏覽器中,不會與 RomM 同步。",
"jsdos-quit-without-saving": "不儲存最近的進度並退出嗎?",
"no-save-selected": "未選擇存檔",
"no-saves-available": "無可用存檔",
"no-screenshot-available": "沒有可用的截圖",
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/plugins/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const ROUTES = {
SMART_COLLECTION: "smart-collection",
ROM: "rom",
EMULATORJS: "emulatorjs",
JSDOS: "jsdos",
RUFFLE: "ruffle",
STREAM: "stream",
SCAN: "scan",
Expand Down Expand Up @@ -254,6 +255,14 @@ const routes = [
v2: v2For(ROUTES.EMULATORJS),
},
},
{
path: "rom/:rom/jsdos",
name: ROUTES.JSDOS,
components: {
default: () => import("@/views/Home.vue"),
v2: v2For(ROUTES.JSDOS),
},
},
{
path: "rom/:rom/ruffle",
name: ROUTES.RUFFLE,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/stores/heartbeat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const defaultHeartbeat: Heartbeat = {
EMULATION: {
DISABLE_EMULATOR_JS: false,
DISABLE_RUFFLE_RS: false,
DISABLE_JSDOS: false,
},
FRONTEND: {
DISABLE_USERPASS_LOGIN: false,
Expand Down
34 changes: 34 additions & 0 deletions frontend/src/types/js-dos.d.ts
Original file line number Diff line number Diff line change
@@ -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.

url: string;
backend: "dosbox" | "dosboxX";
backendLocked: boolean;
pathPrefix: string;
autoStart: boolean;
autoSave: boolean;
fullScreen: boolean;
fsChanges: {
local: boolean;
urlToKey?: (url: string) => Promise<string>;
pull?: (key: string) => Promise<Uint8Array | null>;
push?: (key: string, data: Uint8Array) => Promise<void>;
delete?: (key: string) => Promise<void>;
};
}

export interface JsDosProps {
getLocalChanges(key: string): Promise<Uint8Array | null>;
setNoCloud(noCloud: boolean): void;
save(): Promise<boolean>;
stop(): Promise<void>;
}

export type JsDosFactory = (
element: HTMLDivElement,
options: Partial<JsDosOptions>,
) => JsDosProps;

declare global {
interface Window {
Dos?: JsDosFactory;
}
}
54 changes: 53 additions & 1 deletion frontend/src/utils/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { describe, expect, it } from "vitest";
import type { Config } from "@/stores/config";
import type { Heartbeat } from "@/stores/heartbeat";
import type { SimpleRom } from "@/stores/roms";
import { getDownloadPath } from "./index";
import { getDownloadPath, isJsDosEmulationSupported } from "./index";

function makeRom(overrides: Partial<SimpleRom>): SimpleRom {
return {
Expand Down Expand Up @@ -57,3 +59,53 @@ describe("getDownloadPath", () => {
);
});
});

function makeHeartbeat(
emulation: Partial<Heartbeat["EMULATION"]> = {},
): Heartbeat {
return {
EMULATION: {
DISABLE_EMULATOR_JS: false,
DISABLE_RUFFLE_RS: false,
DISABLE_JSDOS: false,
...emulation,
},
} as Heartbeat;
}

function makeConfig(versions: Record<string, string> = {}): Config {
return { PLATFORMS_VERSIONS: versions } as Config;
}

describe("isJsDosEmulationSupported", () => {
it("supports win3x and win9x", () => {
expect(isJsDosEmulationSupported("win3x", makeHeartbeat())).toBe(true);
expect(isJsDosEmulationSupported("win9x", makeHeartbeat())).toBe(true);
});

it("is case-insensitive on the slug", () => {
expect(isJsDosEmulationSupported("WIN3X", makeHeartbeat())).toBe(true);
});

it("does not claim dos or other platforms", () => {
expect(isJsDosEmulationSupported("dos", makeHeartbeat())).toBe(false);
expect(isJsDosEmulationSupported("flash", makeHeartbeat())).toBe(false);
expect(isJsDosEmulationSupported("snes", makeHeartbeat())).toBe(false);
});

it("respects the DISABLE_JSDOS admin toggle", () => {
expect(
isJsDosEmulationSupported("win3x", makeHeartbeat({ DISABLE_JSDOS: true })),
).toBe(false);
});

it("honours a PLATFORMS_VERSIONS remap onto win3x", () => {
expect(
isJsDosEmulationSupported(
"dos",
makeHeartbeat(),
makeConfig({ dos: "win3x" }),
),
).toBe(true);
});
});
Loading