VibeDrone400BETAEJ is a single-file browser emulator for the Microbee PC85/Premium. It implements a Z80, a SY6545 CRTC, the machine’s banked ROM and PAK windows, the light-pen keyboard latch, a 1-bit speaker path, and a thin CP/M layer for Disk BASIC 6.35e. ROMs are never shipped: the user supplies legally obtained 16K ROM A and 8K ROM B, which are cached in IndexedDB and assembled into the 24K BASIC 5.29e image the machine boots from. The CPU is an interpreted Z80. Each opcode is fetched from a 64K address space, then executed with a T-state cost from a 256-entry table. Prefixes `DD`/`FD` select IX or IY and are allowed to nest; `ED` covers the block moves, 16-bit arithmetic, I/O, and interrupt-mode instructions; `CB` covers shifts and bit operations, including the indexed `(IX/IY+d)` forms. Flags follow the usual Z80 layout, including the undocumented X/Y bits and a parity helper used by logic ops. HALT sets an internal halt latch and idles four T-states per spin until an interrupt is accepted. `IFF1`/`IFF2` and IM 0/1/2 are present; after `EI` a one-instruction delay (`Pt`) prevents an interrupt from being taken immediately, matching real silicon. Memory decode is the heart of the machine model. Reads and writes go through a pair of functions that honour the current map rather than a flat RAM array. `8000–BFFF` is the BASIC ROM window: the low 16K of the combined image, or the high 8K of ROM A when the boot/bank bit on port `1C` is set. `C000–DFFF` is the PAK window. Six cartridge slots (C, E–I) plus a 16K “net” image on slot D (`E000–EFFF`, paged in 4K banks via the low bits of a write to port `0A`) sit behind that decode. A write to port `0A` also selects which 8K half of a 16K PAK is visible (`se`). Video RAM lives at `F000–F7FF` (character codes) with a parallel attribute/PCG plane; `F800+` is either colour RAM or a PCG bank, selected by bits on port `1C` and the PCG enable on port `0B`. Writes into the ROM windows are ignored. When Disk BASIC is running, a second overlay maps a 22,400-byte `mwb635e.com` image and a small BDOS work area so 6.35e sees RAM where a real disk machine would. The 6545 is not treated as a 6845. A 20-register file is written through the usual address/data pair (ports `0C`/`0D`), each register masked to the SY6545 width. R1 and R6 drive live columns and rows, so the canvas is resized when software reprograms the screen. R9 is the character-cell height. R10/R11 define the cursor start/end lines and blink mode. R12/R13 are the display start address; R14/R15 are the cursor address, kept in sync with BASIC’s own cursor word. The Microbee keyboard is the light-pen trick: a keypress is converted to a 6-bit matrix code, written as a latched LPEN address (R16/R17), and advertised on the status port as bit 6. Status bit 5 is vsync. The run loop raises both bits for a computed fraction of each frame — derived from R4 versus R6 — then clears them, so software that waits on 6545 status sees a plausible blanking interval. The frame scheduler is T-state locked. The default CPU clock is 3.375 MHz (2 MHz and 5 MHz GT are selectable). A separate VDU speed slider scales how many T-states are retired per wall-clock frame without changing the programmed clock, which is how the emulator can slow a title without rewriting its timing loops. Each 20 ms slice runs an “active” window with vsync asserted, then the remainder of the line budget with vsync clear. A 40 ms wall-clock cap per animation frame stops a busy wait from freezing the tab. Keyboard paste and tokenised `.MWB` load feed a line queue that is clocked into the ROM input path only when the machine is polling, so BASIC’s own debounce and echo stay in control. Sound is a 1-bit edge timeline, not a chip emulator. Port `02` bit 6 is the speaker tap: every change of that bit is stamped with the current T-state and queued. BASIC `SOUND`/`PLAY` at the known ROM entry (`A756`) is intercepted and turned into a square-wave segment with frequency from a note table and duration from the register pair the ROM used. At the end of each video frame those edges are resampled into an AudioContext buffer at the output sample rate, mixed with the tone segments, and high-pass filtered so a stuck level does not produce a DC thump. The result is the hybrid click-plus-tone behaviour of the stock piezo, not an SN76489 or BeeThoven — those were aftermarket and are correctly ignored. Host I/O is split. `.MWB`/`.BAS`/`.TXT` go through a detokeniser that understands both MicroWorld token maps, then are typed in as numbered lines after a `NEW`. `.BEE` is a binary load: a small heuristic finds a load address from a loader header, a `JP` target, or a self-reference scan, then the PC is dropped on that address. `.ROM`/`.PAK` are assigned to a slot and started at `C000` only if the first byte is `C3` (the real RUNPAK test). Thin CP/M is the Disk BASIC path: `BASIC.COM` is injected at `0100`, a BDOS trampoline sits at `F500`, and a JavaScript directory object implements the BDOS file calls (open, read/write 128-byte records, rename, search). Cassette SAVE/LOAD is a text stream parsed into `*.DAT` files on the same directory. That is the “thin” choice: no FDC, no CCP, no full BIOS — just enough for 6.35e catalogue titles. Emu Joust is the special case. It has no legitimate disk image; it is a cartridge-shaped `.BEE` that must run with real PAK-window semantics. The loader recognises the five-byte prefix `00 09 C3 E0 39` (a `0900h` load word followed by `JP 39E0`), strips the prefix, and forces the load address to `0900h`. It then applies the EJ shim: PAK half-select is forced on (`se = 1`) so a 16K image presents the bank the cart’s own code expects, `IY` is preloaded with `0x0FAB` (4011), and location `00FF` is set to `0xDE`. Joust’s kill/respawn path is stack-heavy and can corrupt `IY`; once `IY` is wrong, the player-swap walk follows a garbage next-pointer and the game never returns to a stable object list. Preloading `IY` stops that class of lockup at the start of a session. A second, narrower shim sits in the execute loop. If the PC is at `2682h` and the three bytes there are `FD 34 1C` (`INC (IY+1Ch)`), the instruction is skipped and eight T-states are charged. That increment is the remaining hang: after an earlier corruption, or in a tight retry, Joust can sit on that `IY`-relative count and never leave. Skipping it is not cycle-accurate, but it is the minimum surgical escape that lets the title reach a full game without the heavier watchdog pair used on the older EJ-only branch. The same loop also contains a few BASIC ROM PC redirects (`A914`/`A976` → `B619`, character-out and printer hooks). Those are host conveniences, not Joust-specific, and they are the kind of address-locked patch the rest of the project tries to keep rare. The rest of the machine is the same discipline the ROM work forced. Boot always starts at `84C6h` with a known CRTC register set and a cleared 80×16 (or whatever R1/R6 last programmed) screen. Reset does not invent a map: if no ROM is loaded, the picker comes back. Slot H is still the practical place to put a cart whose boot writes a bank-select byte to port `0A` that would otherwise steal the emulator’s slot-picker. Every serious remaining failure mode in this file is still the same class of error: an address that was convenient for the emulator, or never re-checked against a clean dump, colliding with something the real program is allowed to do.