diff --git a/DOSBOX_DOOM.ZIP b/DOSBOX_DOOM.ZIP new file mode 100644 index 0000000..be6e0fa Binary files /dev/null and b/DOSBOX_DOOM.ZIP differ diff --git a/frontend/src/pages/Play.svelte b/frontend/src/pages/Play.svelte index 32db238..346245a 100644 --- a/frontend/src/pages/Play.svelte +++ b/frontend/src/pages/Play.svelte @@ -7,9 +7,12 @@ let game = $state(null); let loading = $state(true); let error = $state(""); - let emulatorReady = $state(false); + let booting = $state(false); + let running = $state(false); + let started = false; let dosContainer; + let dosCI = null; async function load() { loading = true; @@ -21,34 +24,83 @@ loading = false; } - function startEmulator() { - if (!game || !game.ready) return; + async function startEmulator() { + if (!dosContainer || !game?.ready || running || started) return; + started = true; + booting = true; - // Load js-dos from CDN dynamically - const css = document.createElement("link"); - css.rel = "stylesheet"; - css.href = "https://v8.js-dos.com/latest/js-dos.css"; - document.head.appendChild(css); + // Load js-dos CSS + const link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = "https://v8.js-dos.com/latest/js-dos.css"; + document.head.appendChild(link); - const script = document.createElement("script"); - script.src = "https://v8.js-dos.com/latest/js-dos.js"; - script.onload = () => { - const url = bundleUrl(game); - if (window.Dos && dosContainer && url) { - window.Dos(dosContainer, { url }); - emulatorReady = true; + // Load js-dos script from CDN if not already loaded + if (!window.Dos) { + try { + await new Promise((resolve, reject) => { + const s = document.createElement("script"); + s.src = "https://v8.js-dos.com/latest/js-dos.js"; + s.onload = resolve; + s.onerror = reject; + document.head.appendChild(s); + }); + } catch { + error = "Failed to load emulator. Check your internet connection."; + booting = false; + return; } - }; - document.head.appendChild(script); - emulatorReady = true; + } + + // Start the DOS emulator + try { + const url = bundleUrl(game); + if (!url || !window.Dos) { + throw new Error("Failed to resolve game bundle"); + } + dosCI = await window.Dos(dosContainer, { url }); + running = true; + } catch (e) { + error = "Failed to start emulator: " + e.message; + } + booting = false; } + function stopEmulator() { + // Kill the emulator process + if (dosCI) { + try { dosCI.exit(); } catch (_) {} + dosCI = null; + } + if (dosContainer) { + dosContainer.innerHTML = ""; + } + running = false; + // Navigate back to game detail + push(`/game/${game.id}`); + } + + // Load game data on mount $effect(() => { load(); }); - // Cleanup on unmount + // Auto-start emulator once game data and DOM are ready + $effect(() => { + if (game?.ready && dosContainer && !started) { + startEmulator(); + } + }); + + // Cleanup on unmount (navigating away, browser back, etc.) $effect(() => { return () => { - // js-dos handles its own cleanup + if (dosCI) { + try { dosCI.exit(); } catch (_) {} + dosCI = null; + } + if (dosContainer) { + dosContainer.innerHTML = ""; + } + running = false; }; }); @@ -56,31 +108,47 @@ {#if loading}
Starting emulator...
+💾 Game saves are stored automatically in your browser
+- {game.year ? `${game.year} · ` : ""}{game.genre || ""} -
-Click "Launch Emulator" above to start playing
+ {#if game.ready} + + {:else} +This game is not ready yet.
+ {/if}💾 Game saves are stored automatically in your browser