Real PCs from the 8088 to the Pentium era, running in your browser.

A full port of the PCem emulator to WebAssembly — real BIOSes, cycle-paced hardware emulation, 3dfx Voodoo acceleration through a runtime recompiler, and machines you can hand to anyone as a single link. Nothing to install; nothing leaves your browser.

Pentium 75 · Voodoo2 running 100% speed 100 fps

Ready-to-boot systems

Each machine below is a complete exported system — OS installed, drivers configured, CMOS saved. Disks stream lazily, so booting starts in seconds; anything you do inside stays in your browser session and the hosted machine is untouched for the next visitor.

Windows 95 rig
[Socket 7] Pentium 90 · 64 MB · S3 ViRGE + Voodoo 4 MB · SB16

Early 90s gaming machine with Glide acceleration. Boots to the desktop with DirectX and 3dfx drivers installed and ready.

Boot this machine →
Windows 95 workstation
[Socket 7] Pentium 100 · 64 MB · S3 ViRGE + Voodoo 4 MB · SB16

Classic. The machine everyone's office had in 1995.

Boot this machine →
Windows 98 Se
[Socket 7] Pentium 100 · 64 MB · S3 ViRGE + Voodoo 4 MB · SB16

Windows 98 Lives! *This needs a modern Host alert.

Boot this machine →

What this build does

This is not a lightweight DOS box. It's PCem's cycle-paced hardware emulation — the same core the desktop version runs — with the parts a browser can't recompile rebuilt as runtime WebAssembly, and every one of those parts proven against the original.

3D acceleration3dfx Voodoo, recompiled at runtime

The Voodoo pixel pipeline — textures, dual TMU, fog, blending, dithering — is compiled to WebAssembly per render state while the game runs. Every covered mode is verified byte-identical against PCem's reference rasteriser by an automated oracle.

CPUInterpreter first, JIT when it wins

Every CPU from the 8088 to K6-class runs on the interpreter with honest cost labels. An optional per-system recompiler accelerates compute-heavy guests, and a differential oracle can prove every compiled block bit-exact against the interpreter.

StorageMulti-gigabyte disks, zero upload

Hard disk images attach from local files or the server and stream lazily in 128 KB blocks — an 8 GB drive boots in seconds. Guest writes live in a session overlay; the source image is never modified.

MediaHot-swap floppies & CDs, live

The status bar's 💿 Media menu changes discs on the running machine — the guest gets a real media-change notification, so multi-disc installs just ask for disc 2 and carry on. Single ISOs mount instantly from local files at any size.

AudioWorklet delivery with a servo

Sound streams from shared memory straight to the audio thread with pre-roll, drift compensation and an adaptive cushion — zero underruns at full guest speed, verified by an automated test.

HardwareThe whole PCem inventory

97 machine models with their real BIOSes, plus the video, sound and storage devices the desktop version registers — each with its own configuration dialog, generated from the same device tables.

SharingA machine is a link

Export writes a self-contained folder: profile, merged disks with your changes baked in, CMOS. Host it, share ?system=, and visitors boot your exact machine — their session, your pristine image.

How it works

Everything runs client-side. The server hosts static files; your browser is the machine.

Pick a system

The link carries the machine profile. The emulator fetches it, restores the CMOS and attaches the disks — lazily, so nothing big downloads up front.

It boots for real

Real BIOS POST, real drivers, real OS. Emulation runs on a dedicated worker thread, so the page stays responsive no matter what the guest does.

Play, safely

Disk writes stay in your browser session. Close the tab and the machine resets to exactly what its curator published.

Performance, honestly: cycle-paced emulation is expensive by design. A mid-range desktop holds a Pentium 75-class machine at 100% with clean audio — 3D acceleration included. Faster models are labelled by cost in the editor, and a machine that can't sustain real time on your hardware says so instead of silently stuttering. Everything else is in the manual.

Help & manual section by section

Quick start

Getting started

Launch emulator opens the app. The loading card boots the WebAssembly core, then scans this server's /roms directory — the exact directory layout a desktop PCem install uses. The footer of the left sidebar shows the result: ROMs: N of 97 machines ready. A machine appears in the editor only when its complete ROM set was found.

  1. Boot something hosted here: use a card in Ready-to-boot systems — it opens the emulator with that machine's profile and boots it automatically.
  2. Or build your own: in the emulator, click + New, pick a machine on the Machine tab, attach media on the Media tab, then Save system and Boot from its sidebar card.
One-time browser requirement: the emulator needs cross-origin isolation (SharedArrayBuffer, used for its threads). A proper host sends two headers (COOP/COEP — serve.py does); on static hosts that can't, a built-in service worker adds them and the page reloads itself once. If you see the isolation message, that reload is all it's asking for.

Your systems are saved in this browser (localStorage) and reappear on the next visit. Media you attach from local files is re-attached per session — the profile remembers the slot, you re-pick the file.

This page

Getting started

The cards under Ready-to-boot systems are exported machines hosted on this site. Each card's Boot this machine → link carries a ?system= deep link: the emulator fetches the machine's profile.json, restores its CMOS, attaches its disks lazily (nothing big downloads up front) and boots.

  • Your session is yours. Everything the guest writes to disk stays in your browser's memory for that session. Close the tab and the hosted machine is exactly as published for the next visitor.
  • Linked machines aren't saved to your systems list automatically — they run as one-off sessions. Build your own copy in the emulator if you want to keep one.

Machine tab

Machine editor · tab 1 of 6

The editor is generated from the same hardware tables the native PCem GUI reads, so everything here has a desktop counterpart.

  • Machine — the motherboard/BIOS model. Only machines whose ROM set is on the server are listed. The button next to it opens the board's own options when it has any (same dialog the desktop version generates).
  • CPU family / CPU / FPU — what this board accepts, from PCem's CPU tables. Fast models carry honest cost labels: “— demanding” (≥60 MHz-class) and “— very demanding” (≥120 MHz-class) mean the browser may not hold 100% speed. Start slower; the status bar tells you what your host actually achieves.
  • Memory — sized to the machine (XT-class machines count KB, AT-class MB, stepping at the board's granularity).
  • Wait states — 8088/8086-era memory timing. Default is correct unless you know the software needs otherwise.
  • Mouse — serial (Microsoft 2-button / Logitech 3-button / Intellimouse), PS/2 flavours, Amstrad, Olivetti M24, MSystems. Match what the guest OS's driver expects; DOS setups usually want a serial Microsoft mouse.
  • CPU recompiler — optional, per system, 386+. It converts hot guest code to WebAssembly at runtime and is verified instruction-for-instruction against the interpreter. It wins clearly on tight compute (number crunching, inner loops) but the per-block overhead makes a Windows 9x desktop slower — the interpreter is the honest default. Tick it only if the status bar measures better for your workload.

Display tab

Machine editor · tab 2 of 6
  • Video card — every card the desktop build registers, plus Built-in video on machines that have it (fixed-video machines lock the select). The opens the card's own options (memory size, refresh, card-specific toggles) generated from its device table.
  • Video speed — how fast the emulated bus lets the card go, from 8-bit bus to Fast VLB/PCI. Default picks the card's period-correct setting; raising it can help software that's video-bound, at the cost of authenticity.
  • 3Dfx Voodoo add-on card — a PCI board, so it's only available on PCI machines (greyed out elsewhere, same rule as the desktop GUI). Configure… sets the model, framebuffer and texture memory, bilinear filtering, and how many render threads the rasteriser may use. The pixel pipeline is recompiled to WebAssembly at runtime and oracle-verified against PCem's reference rasteriser.

Sound tab

Machine editor · tab 3 of 6
  • Sound card — AdLib through SB16/AWE32-class, from the same device list as the desktop build. The dialog is where the card's address / IRQ / DMA / OPL options live — the values your DOS SET BLASTER line and game setup programs must match. It's also where MIDI out device appears once WebMIDI is enabled (see Input / Network).
  • Game Blaster / Gravis Ultrasound / SSI-2001 — extra boards that can sit alongside the main card, like real ISA slots.
The game port (joystick) comes with the sound card, as on real hardware — pick the emulated stick type on the Input / Network tab.

Storage tab

Machine editor · tab 4 of 6
  • HDD controller — MFM, ESDI, IDE or SCSI-class controllers appropriate to the era, with a for controllers that have options (e.g. the XTIDE's BIOS address). The controller decides how many drives exist and how big they can be — and the CD-ROM drive rides the IDE bus, so an IDE-class controller is what makes the CD drive exist at all.
  • Drive A: / B: type — the physical floppy drive fitted: 5.25" 360k / 1.2M (incl. dual-RPM), 3.5" 720k / 1.44M / 3-mode / 2.88M, or Disabled. The drive must be able to read the image you insert (a 1.2M image needs a 1.2M 5.25" drive). Disabled drives disappear from the Media tab and the 💿 Media menu.
  • The panel below lists attached hard disks with their geometry — attach the images themselves on the Media tab.

Media tab

Machine editor · tab 5 of 6

Nothing here uploads anywhere — local files are read in place by your browser.

Floppy A: / B:

  • Choose local image… accepts .img .ima .fdi .dsk .360 .720 .12 .144. Floppies are staged into the emulator's in-memory file system (they're small).
  • Download saves the image back to your computer including everything the guest wrote to it this session.
  • Eject empties the slot.

Hard disk 0 / 1

  • Local files attach lazily — no copy, no meaningful size limit: the emulator reads 128 KB blocks on demand, so an 8 GB image boots in seconds. Guest writes go to a session-only overlay; your original file is never modified.
  • Geometry (C/H/S) is parsed from VHD footers or guessed from raw image size, and can be edited — it must match what the guest OS was installed with.
  • VHD support: fixed VHDs work natively (and Download returns a valid VHD). Dynamic VHDs only work up to 256 MB (they must be staged into memory — convert bigger ones to fixed/raw). Differencing VHDs are not supported.
  • Create blank… makes a zeroed image (up to 2047 MB) with sensible geometry — FDISK/format it in the guest like a real new drive.
  • Download image streams the disk out with this session's writes merged in — the way you keep an installed OS.

CD-ROM

  • A single .iso attaches lazily from your local file at any size — the header is pre-read so mounting is instant.
  • For .cue/.bin discs, use the 💿 Media menu while the machine runs — it lets you select the .cue and its .bin files together.
Editing the running machine: saving this dialog applies floppy/CD changes to it immediately — no reboot (see Hot-swapping media). Hard-disk changes always wait for the next boot: IDE geometry binds when the machine resets, as on real hardware.
Limits worth knowing: staged files (floppies, .cue sets, small dynamic VHDs) top out at 800 MB per file because they live in browser memory; lazily-attached disks/ISOs are effectively unlimited but use one of 8 lazy-attachment slots — slots recycle automatically when a disc is replaced everywhere it was used.

Input / Network tab

Machine editor · tab 6 of 6

Joystick & gamepad

  • Emulated joystick — what the guest sees on the game port (2-button, 4-button, flightstick-with-hat types, etc.). The game port itself comes with the sound card.
  • Use host gamepads — connected pads map 1:1 onto the emulated stick: left stick → axes 0/1, right stick → axes 2/3, buttons in gamepad order, d-pad → the POV hat on stick types that have one. Connect a pad and press any button so the browser exposes it.

MIDI output

Enable MIDI output… asks the browser for WebMIDI access, then lists your synths (hardware or software). Pick the output in the sound card's dialog under MIDI out device. This routes the emulated MPU-401 — General MIDI music in DOS games via SB16/AWE32 — to a real synth.

Network

ConnectionMeaning
Shared public relayFrames travel over a WebSocket relay. Every machine pointed at the same relay is on the same virtual LAN — that's browser-to-browser multiplayer (IPX DOOM, Windows file sharing). The public relay also answers DHCP and NATs to the internet; it's shared and low-bandwidth.
Tabs in this browserNo server at all: machines in other tabs of this same browser share a LAN instantly. The quickest way to try IPX multiplayer against yourself.
Custom relay URL…Your own relay for a private LAN — run node tools/net_relay.mjs and enter its ws://host:8087/.
OffCable unplugged.
  • Network card: on PCI machines pick the Realtek RTL8029AS — it's Plug & Play and Windows 9x sets it up by itself. The NE2000 is legacy ISA (real ones were too): add it in Windows via Add New Hardware → “Novell/Anthem NE2000 Compatible”, then set I/O 300–31F, IRQ 10 in Device Manager. DOS packet drivers take the same values: ne2000.com 0x60 10 0x300.
  • MAC address: every machine needs its own on a shared relay — Randomize makes one.

Screen, mouse & keyboard

Running a machine
  • Mouse capture: click the screen to capture the mouse (pointer lock — the guest gets relative movement, exactly what DOS/Win9x drivers expect). Ctrl+End releases it, mirroring native PCem. The hint pill under the screen reminds you.
  • Keyboard goes to the guest while the screen has focus. Switching away from the tab releases everything, so no stuck keys when you come back.
  • Aspect & scaling: the canvas presents at the aspect ratio the emulated card asks for (CGA line-doubling included), scaled to fit. goes fullscreen.

The status bar, left to right

ItemMeaning
Machine nameWhat's running.
Stateidle / running / paused.
Speed %Emulated speed relative to the real hardware. 100% = the guest experiences real time. If it sits below ~90% for a while, a one-time toast explains the fix (pick a cheaper CPU model — see Performance).
fpsFrames the emulated video card is producing.
Net pillAppears when networking is on: link state, LAN mode and peers, frames sent/received. Hover for full counters.
🔊Mute/unmute host audio (the guest keeps playing either way).
💿 MediaHot-swap floppies and CDs on the running machine — see Hot-swapping media.
Pause / ResumeFreezes the whole machine; resumes exactly where it was.
ResetHard reset — the power switch, not Ctrl-Alt-Del. Unsaved guest work is gone.
StopShuts the machine down and returns to the welcome screen. Session disk writes stay in memory until the tab closes — Download images you want to keep first.
Fullscreen.

Hot-swapping media 💿

Running a machine · no reboot required

The 💿 Media button in the status bar is the disc tray of the running machine. Swaps are live: the guest OS receives a real media-change notification (the SCSI “medium may have changed” attention, same as native PCem's CD menu), so installers that ask for disc 2 or disk 2 detect the swap and carry on. No restart, ever.

  • Rows: one per floppy drive fitted (A:, and B: if enabled on the Storage tab) plus the CD-ROM. Each shows what's inserted, with Load… and Eject.
  • CD — single .iso: mounts instantly, read lazily from your local file at any size. Nothing is copied.
  • CD — .cue/.bin: in the file picker, select the .cue together with its .bin file(s) (Ctrl-click) — the set is staged and the .cue mounted as one disc.
  • Floppies: pick a new image and it's in the drive — mid-install disk swaps work the way they did in 1994, minus the drive noise.
  • Eject leaves the drive empty — some installers genuinely want the disc out before they continue.

Prefer the full dialog? Configure on the running system's card works too: floppy/CD image changes apply the moment you save, and a toast confirms what was swapped. Everything else (CPU, RAM, cards, hard disks…) is queued for the next boot — hard disks can't hot-swap because IDE geometry binds at reset, exactly like the real machine.

You can boot with an empty CD drive and insert a disc later — the drive itself exists as long as the machine has an IDE-class controller (Storage tab).

Export & deep links

Sharing · a machine is a link

Exporting a system

Export on a system card writes a self-contained, hostable folder (Chromium-family browsers — it uses the folder picker):

  • profile.json — the hardware profile with a media manifest pointing at the files below.
  • Every disk image, with your session's guest writes merged in (fixed VHDs come out as valid VHDs). Floppies and CDs included.
  • Saved CMOS (.nvr) so the BIOS remembers its setup.
  • LINK.txt — the exact URL recipe for wherever you upload the folder.

The deep link

Upload the folder anywhere static (same origin as the emulator, or CORS-enabled) and share pcem/?system=…/profile.json. Visitors boot your exact machine; their changes stay in their own browser session — your hosted images are read-only. Every visitor gets a fresh random MAC, so several people on the shared relay LAN don't collide.

URL parameterEffect
?system=<url>Profile to fetch and boot (required for auto-boot).
&autostart=0Add the machine to the sidebar but don't boot it.
&disk= &disk2=Attach hosted hard-disk images to hd0/hd1 (streamed lazily via Range requests).
&fd= &fd2=Fetch hosted floppy images into A:/B:.
&cd=Attach a hosted ISO (lazy, any size).
Hosting requirements: a plain static host works. Disks stream fastest when the server honours HTTP Range requests (most do; serve.py does). The emulator page itself needs the COOP/COEP headers or its bundled service-worker fallback (see Quick start).

Performance

Reference

PCem is cycle-paced: emulation cost scales with the guest's clock speed, not with what the guest is doing. A Pentium 200 costs the browser the same whether it idles at the DOS prompt or runs Quake. That's why:

  • Speed % is the honest number. 100% means the guest lives in real time — smooth audio, correct game pacing. Below that, everything in the guest slows uniformly (it isn't “lag”; it's a slower universe).
  • CPU choice is the main lever. The editor labels expensive models (demanding / very demanding). If the status bar can't hold ~100%, configure a slower CPU — a solid Pentium 75 beats a stuttering 166.
  • The recompiler is situational: clear wins on tight compute, slower on desktop-y workloads (Win9x idle loops, I/O-heavy code). Measure with the status bar; a differential oracle keeps it bit-exact either way.
  • Voodoo render threads (Voodoo ⚙) spread the rasteriser across cores — 2 is a good desktop default.
  • Underspeed is announced. If a machine can't sustain ~90% for a stretch, a one-time toast says so and points at the fix, instead of letting it stutter silently.
  • Keep the tab in the foreground for full speed — browsers throttle background tabs.

Troubleshooting

Reference
SymptomFix
“No ROM sets found”Copy a PCem roms/ directory onto the server (web/roms/, or point serve.py --roms at it), then Rescan. Machines only appear when their complete set is present. BIOS ROMs are not distributed with this site.
Page asks for “cross-origin isolation”Serve with COOP/COEP headers (python3 serve.py does), or let the built-in service-worker shim reload the page once. Private/incognito windows sometimes block service workers.
“CD image could not be opened”The file isn't a readable ISO/CUE. For .cue discs, select the .cue with its .bin file(s) in the 💿 Media menu. The machine still boots, with an empty drive — insert a good disc live.
“No free browser-disk slots (8 max)”Too many lazily-attached images registered in this tab session. Slots recycle automatically when a disc is replaced everywhere it's referenced; a page reload clears everything.
Machine exited / “Emulator not responding”The core logs its tail to the browser console (F12) — a missing ROM file or bad configuration is the usual cause. Reload the page to restart the core.
No soundAudio starts with a user click (browser rule) — booting via a button counts. Check the 🔊 pill isn't muted. If audio crackles, the machine is probably under 100% speed: pick a cheaper CPU model.
Mouse trapped / keys stuckCtrl+End releases the mouse. Switching away from the tab auto-releases all keys.
Export button does nothingFolder export needs a Chromium-family browser (File System Access API). On others, use JSON for the profile and the Media tab's Download per disk image.
Huge file refuses to stageStaged media (floppies, .cue sets, dynamic VHDs) live in browser memory — 800 MB per file cap, dynamic VHDs 256 MB. Hard disks and single ISOs avoid the cap entirely: attach them as local files and they stream lazily.

Privacy & data

Reference
  • Nothing you attach is uploaded. Local images are read in place with the browser's File API; staged copies live in the tab's memory and die with it.
  • Guest disk writes never touch your files. They live in a session overlay; the only way they reach your computer is when you click Download/Export.
  • Profiles (hardware descriptions, no disk contents) are stored in this browser's localStorage.
  • Networking is opt-in per machine. When enabled, the guest's LAN frames go to the relay you chose — the shared public one, your own, or tabs-only which never leaves your browser. Everything else is client-side; the server only serves static files and ROMs.
No topics match — try a different word, or clear the search.