Commit Graph

285 Commits

Author SHA1 Message Date
dependabot[bot]
91b9c1df23 Bump ip-address from 10.1.0 to 10.2.0
Bumps [ip-address](https://github.com/beaugunderson/ip-address) from 10.1.0 to 10.2.0.
- [Commits](https://github.com/beaugunderson/ip-address/commits)

---
updated-dependencies:
- dependency-name: ip-address
  dependency-version: 10.2.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-05-07 01:08:12 +00:00
Felix Rieseberg
d0090e5569 Cap SMB TCP burst at 4×MSS to stay under NE2000 RX ring (#371) 2026-04-14 16:50:19 -07:00
Felix Rieseberg
b14ea86ced Speed up SMB transfers: TCP windowing, hot-path assembly, gated diagnostics (#370) 2026-04-14 16:42:22 -07:00
Felix Rieseberg
41394e4d8e Add Machine menu items to swap floppy/CD-ROM/shared folder at runtime (#369)
v86 already exposes set_fda/eject_fda and devices.cdrom.set_cdrom/eject,
but the app only let you pick media from the pre-boot Settings card. This
adds Machine ▸ Floppy Drive, Machine ▸ CD-ROM Drive, and Machine ▸ Change
Shared Folder so you can swap media while Windows is running.

- Floppy: read the .img into memory and call set_fda({buffer}).
- CD-ROM: call devices.cdrom.set_cdrom(new SyncFileBuffer(path)) directly
  so the ATAPI BSY workaround in sync-file-buffer.ts still applies; the
  public set_cdrom() routes through v86's async loaders and re-introduces
  the race.
- SMB: setupSmbShare now installs the port-139 hook unconditionally,
  accepts a null initial path (RSTs incoming SYNs until one is set), and
  returns {setHostPath} so the menu can re-aim the share without a
  restart. New TCP sessions pick up the new folder; open ones keep the
  old root until Win95 reconnects.
2026-04-14 14:15:30 -07:00
Felix Rieseberg
3151ffff3c Add npm run qemu / qemu:cdrom scripts (#368)
Boots images/windows95.img with the same device set the image was
configured against:

- ne2k_isa at iobase=0x300, irq=10 (matches the NE2000 ForcedConfig in
  SYSTEM.DAT and v86's port 0x300 / PIRQA->IRQ10)
- vmport=on so VBMouse picks up the VMware backdoor for absolute pointer
- sb16, pentium, acpi=off as before

qemu:cdrom forwards an ISO path: npm run qemu:cdrom -- /path/to.iso
2026-04-14 10:21:24 -07:00
Felix Rieseberg
7d48709cff README: v5.0.1 2026-04-13 10:26:31 -07:00
Felix Rieseberg
739931aec6 5.0.1 v5.0.1 2026-04-13 10:19:19 -07:00
Felix Rieseberg
731a9b2369 Wait for v86 emulator-loaded before restoring state (#367)
The 500ms setTimeout raced against v86's async wasm/BIOS/hda load. When
loading exceeded 500ms (cold cache, Gatekeeper scan on packaged apps),
restore_state ran on an uninitialized CPU, threw, was silently caught,
and the VM cold-booted from default-state.bin instead of resuming the
user's session.
2026-04-13 10:18:41 -07:00
Felix Rieseberg
35c82c5d09 check-links: skip /releases/download/ URLs (chicken-and-egg with release builds) v5.0.0 2026-04-12 21:25:17 -07:00
Felix Rieseberg
60ee631575 Fetch disk image from private GitHub release; harden download scripts
OneDrive 1drv.ms links no longer serve raw bytes to headless clients after the SPO migration. The disk image now lives as a release asset on a private repo and is fetched via 'gh release download' using DISK_REPO + DISK_TAG vars and an IMAGES_REPO_TOKEN secret. Scripts fail fast on missing env, bad zip, or missing windows95.img.
2026-04-12 21:21:58 -07:00
Felix Rieseberg
dddaca9120 README: update download links for v5.0.0
Drops the Windows ARM64 row (not built in v5) and adds Linux ARM64/ARM rpm+deb links.
2026-04-12 18:38:28 -07:00
Felix Rieseberg
d383958f2b Remove committed guest-tools .EXE; drop now-unneeded windows-sign patch
VBMOUSE.EXE is the DOS TSR build artifact (only vbmouse.drv is referenced by OEMSETUP.INF). With no .exe under guest-tools/ the @electron/windows-sign exclude patch is no longer needed. .gitignore now covers all guest-tools/**/*.exe.
2026-04-12 17:53:18 -07:00
Felix Rieseberg
a1637b1de1 Add SMB READ_RAW support for faster bulk transfers (#366)
Win95's redirector was falling back to ~2.8KB core READs (no raw mode
advertised), so a 200KB copy took ~360 round-trips through the emulated
NIC/TCP stack (~10s). With READ_RAW it pulls up to 64KB per round-trip.

- server.ts: readRaw() handler (raw bytes only, 0-byte frame on error);
  negotiate now sets MaxRawSize=65535 + CAP_RAW_MODE (NT) and RawMode
  bit 0 (LM); per-packet hex capture gated on WIN95_SMB_CAPTURE
- smb.ts: CMD_READ_RAW constant
- test-standalone.ts: READ_RAW happy-path + bad-fid tests (57 pass)
2026-04-12 17:52:17 -07:00
Felix Rieseberg
fff371073d Patch @electron/windows-sign to skip guest-tools when signing
VBMOUSE.EXE and friends are 16-bit DOS/Win9x binaries served to the guest over SMB; signtool refuses them with 'file format cannot be signed'. The patch skips any path under guest-tools/ during file collection.
2026-04-12 17:49:01 -07:00
Felix Rieseberg
8153e91706 CI: wire up Azure Trusted Signing for Windows builds
Installs the Microsoft.Trusted.Signing.Client dlib via NuGet, locates signtool.exe from the Windows SDK, and passes AZURE_* secrets to the Make step. Removes the unused .pfx-based signing step.
2026-04-12 17:38:12 -07:00
Felix Rieseberg
fb701041c2 Use cwd-relative path in @electron/packager resedit patch
The patch hardcoded a local Windows path, breaking Windows CI builds. Now resolves tools/resedit.js relative to process.cwd() and uses process.execPath instead of 'node'. Also drops the deb maker diagnostic step now that Linux builds pass.
2026-04-12 16:56:20 -07:00
Felix Rieseberg
e1c30f701c Remove hardcoded TEMP path; expand deb maker diagnostic
The TEMP override in forge.config.js broke Windows builds on CI runners (mkdtemp ENOENT). The expanded diagnostic exercises require() from maker-base's own resolution context to surface the real Linux failure.
2026-04-12 14:23:55 -07:00
Felix Rieseberg
bbcc4f32cd Align all @electron-forge/* packages to 7.11.1
cli and maker-deb were pinned at 7.8.3 while other makers resolved to 7.11.1, leaving two copies of maker-base in the tree. The mismatch breaks maker-deb's isSupportedOnCurrentPlatform() check on Linux runners.
2026-04-12 14:16:31 -07:00
Felix Rieseberg
9c99b6cb65 CI: disable fail-fast and add deb maker diagnostic 2026-04-12 14:12:48 -07:00
Felix Rieseberg
2e01152d82 Regenerate package-lock.json to include all @rollup platform binaries
The lockfile only contained @rollup/rollup-darwin-arm64 because it was last regenerated on macOS, which trips npm's optional-dependency bug (npm/cli#4828) and breaks 'npm ci' on Linux/Windows runners.
2026-04-12 13:26:52 -07:00
Felix Rieseberg
63f02842bc Bump to v5.0.0 (STATE_VERSION 5) for new disk image 2026-04-12 13:13:23 -07:00
Felix Rieseberg
c847467de6 Recover user files from orphaned state-vN.bin after a version bump (#365)
* Detect orphaned state-vN.bin and offer file recovery to a host folder

When STATE_VERSION is bumped, users previously lost their C:\ silently.
The Welcome card now detects an older state file (v4+), explains what
happened, and offers a one-click recovery: spin up a throwaway v86
(no boot), restore the legacy state to populate the hda dirty-block
overlay, walk the FAT32 tree reading overlay-if-dirty-else-base, and
copy any file the guest ever wrote out to ~/Downloads/Recovered C Drive.

Directories are created lazily so empty branches never appear; success
and failure render in the panel (no native dialogs). The geometry
constraint that keeps overlay+new-base valid is documented next to
STATE_VERSION. Also makes the dev-mode CDP port overridable via
WIN95_DEBUG_PORT so worktree instances don't fight over 9222.

* prettier
2026-04-12 12:38:28 -07:00
Felix Rieseberg
fa0e4c691e Add tools/pack-disk.sh to build the images zip CI downloads via DISK_URL 2026-04-12 09:54:21 -07:00
Felix Rieseberg
6c964f99e9 Refresh home.htm: drop 'since the last version', bump Last Updated to 2026 2026-04-12 09:25:58 -07:00
Felix Rieseberg
1f116d607b Update shared-folder docs/UI: Z: is auto-mounted, drop \\HOST instructions 2026-04-12 09:24:32 -07:00
Felix Rieseberg
d38355ff16 Auto-map \\HOST to Z: from the W95TOOLS guest agent (#364)
* Auto-map \\HOST to Z: from W95TOOLS at login

W95TOOLS.EXE now calls WNetAddConnectionA("\\\\HOST\\HOST", NULL, "Z:")
on a short retry timer (5 tries, 3s apart) so the shared folder shows up
as a drive without a trip through Start -> Run. MPR.DLL is LoadLibrary'd
so the EXE keeps its USER32/KERNEL32-only import table and still launches
if MPR is somehow absent. Skipped if Z: is already taken; gives up
silently if no share is configured.

Works for any user folder because the SMB server's tree-connect already
routes every share name other than TOOLS/IPC$ to the user share; added a
comment in server.ts pointing at the dependency.

Verified by cold-booting the image with the new vs. old binary in
StartUp: new -> tree connect to \\HOST\\HOST within ~5s of desktop and
z:\ opens in Explorer; old -> no SMB traffic after 55s at desktop.

* Drop rebuilt W95TOOLS.EXE from the diff

Binary will be rebuilt and baked into the image alongside the next
default-state re-bake; keep this PR source-only.

* Stop tracking guest-tools/agent/W95TOOLS.EXE

It's a build output of `make -C guest-tools/agent` and CI doesn't
consume it (the disk image is baked out-of-band), so there's no reason
to carry the binary in git.
2026-04-12 09:16:54 -07:00
Felix Rieseberg
b74e6c7b0a Fix guest TCP recv() stalling when v86 NE2000 TX ring wraps (#363)
* Fix guest TCP recv() stalling under concurrent traffic

v86's fake_network stores TCPConnection routing fields (hsrc/hdest/
psrc/pdest) as zero-copy subarrays of the SYN frame, which is itself a
view into the NE2000 TX ring. Win95's driver uses a 12-slot ring; once
it wraps (any concurrent SMB/NBNS/ping while waiting for an upstream
reply), pump() emits segments with whatever IP now occupies that slot,
the guest RSTs them, and recv() blocks forever.

- libv86.js: copy the four address arrays at TCPConnection construction
  (matches felixrieseberg/v86@dd13099c on fake-network-copy-tcp-addrs,
  now merged into windows95-base)
- tools/probe-tcp.sh + net/tcp-trace.ts + tcp-relay.ts test stub +
  debug-harness WIN95_PROBE_RUN2: end-to-end regression harness
  (boot → ping -t → telnet → async write after ring wrap → assert ACK).
  All env-gated, no production-path change.
- docs/v86-patches.md: tracker for all fork patches + upstream PR state
- update-v86 SKILL.md: cross-link and new fork-branch entry

* Drop checked-in upstream PR description

Belongs on the GitHub PR, not in the repo.
2026-04-12 08:03:03 -07:00
Felix Rieseberg
3c63139fae Await restoreState before run(); update home.htm contact to Twitter
restoreState() was fire-and-forget so emulator.run() started cold-booting
while the snapshot was still being read and applied over live RAM/regs.
2026-04-11 20:29:52 -07:00
Felix Rieseberg
bc76e9c79a Shared text clipboard via VMware backdoor + W95TOOLS.EXE guest agent (#361)
Three layers:

  v86 — src/vmware.js gains the legacy text-clipboard backdoor commands
  (GETSELLENGTH/GETNEXTPIECE/SETSELLENGTH/SETNEXTPIECE, 6–9). The host
  stages bytes via the vmware-clipboard-host bus event; the guest pushes
  via 8/9 and the device emits vmware-clipboard-guest when the buffer
  fills. Same wire protocol as open-vm-tools' pre-RPC copy/paste.
  Committed on the windows95-base fork branch; libv86.js rebuilt here.

  renderer — src/renderer/clipboard.ts polls Electron's clipboard (no
  change event exists), translates host UTF-8/LF ↔ guest CP-1252/CRLF,
  and bounces bytes through the two bus events. Echo-suppressed so a
  value we just wrote does not come back as a change.

  guest — guest-tools/agent/W95TOOLS.EXE is a 22 KB hidden-window agent
  that joins the Win32 clipboard-viewer chain (push-on-copy) and polls
  the backdoor on a 250 ms timer (pull-from-host). Win9x runs ring-3
  with the I/O bitmap wide open, so a plain IN EAX,DX from a user
  process reaches the port — no driver needed. Named for growth: time
  sync and host-initiated shutdown will live here too. Built with Open
  Watcom v2 inside Docker (Makefile + Dockerfile alongside the source);
  subsystem 4.0, no msvcrt, runs on Win95 RTM.

Install: copy \\HOST\TOOLS\agent\W95TOOLS.EXE into the guest and drop a
shortcut in StartUp. Text only, 64 KB cap.
2026-04-11 20:17:06 -07:00
Felix Rieseberg
6e73df11ae Enable CD-ROM via a synchronous fs-backed buffer (#362)
v86's async loaders leave the ATAPI drive in BSY across an event-loop
turn after a READ(10) CDB. Win95's ESDI_506 reads status twice, sees
BSY both times, and issues DEVICE RESET ~165 instructions later, which
cancels the in-flight read — the drive enumerates but D: never mounts.

Serve the ISO through a small fs.readSync-backed buffer so the data is
available before the next emulated instruction runs, and re-enable the
CD-ROM settings tab.

Also: WIN95_PROBE_CDROM / WIN95_PROBE_CDTRACE harness hooks, and pump
one screen-adapter frame before screenshotting so probe captures work
when the Electron window is occluded.
2026-04-11 19:31:57 -07:00
Felix Rieseberg
5da7f94c5a Make "Start without state" always enabled (#360)
The menu item now works whether the machine is running or not. bootFromScratch() awaits stopEmulator() first (a no-op when already stopped), so invoking it mid-session saves the current state, tears down the running VM, and boots a fresh one.
2026-04-11 18:39:45 -07:00
Felix Rieseberg
766497bd5d v86: defer V86-mode VBE disable; add DOS-box probe scenario (#359)
Rebuilds libv86.js from felixrieseberg/v86@windows95-base, which now
carries vga-defer-vbe-disable-v86: when a windowed DOS VM's vgabios
writes dispi[4]=0, Win9x's VDD passes that through (it doesn't know
about ports 1CE/1CF) while virtualising the rest of the mode-set, so
v86 used to drop out of LFB rendering with the legacy registers still
holding SVGA values and the screen turned to planar garbage. The fix
defers the disable until a legacy attribute-mode write actually
reaches the hardware.

debug-harness: WIN95_PROBE_DOSBOX=1 opens command from Run, types
dir, optionally Alt+Enters (WIN95_PROBE_DOSBOX_ALTENTER=1).
WIN95_PROBE_VGATRACE=1 wraps the VGA io.ports[] entries (not the
VGAScreen methods, which are captured by-value at registration) and
dumps [port, op, value, eip+VM/PE/CPL] tuples to
/tmp/win95-vgatrace.json — that EIP/mode column is what pinned the
leak on V86-mode vgabios at C000:2C8x.
2026-04-11 17:32:07 -07:00
Felix Rieseberg
85c44513cb Raw TCP relay for non-port-80 guest egress + DoH DNS with magic-name shim (#358)
The fetch network adapter only intercepts port 80 (parsed as HTTP and
replayed via fetch). Everything else was RST'd. This adds a second
tcp-connection bus listener that bridges any other destination port
straight to a Node net.Socket in the renderer — no extra process, no
WebSocket relay, no new dependencies.

- net/tcp-relay.ts: hook v86 tcp-connection, accept SYN synchronously,
  open a real socket to conn.psrc:conn.sport, buffer until connect,
  pipe both directions, tear down on either side closing. Loopback,
  link-local and multicast are refused; the rest of RFC1918 is left
  reachable so the guest can still talk to LAN devices.
- net/dns-shim.ts: dns_method is now "doh" so the guest gets real IPs
  for the relay to dial, but Cloudflare can't answer single-label names
  like "windows95" or the NNN.external localhost magic. The shim wraps
  global fetch, spots /dns-query POSTs for those names, and answers
  with the same 192.168.87.1 placeholder the static resolver used to
  hand out — the port-80 fetch path then takes over via the Host header
  exactly as before.
- emulator.tsx: wire both in next to the SMB hook; set dns_method.
- debug-harness.ts: WIN95_PROBE_RUN/_RUN_AFTER/_RUN_WAIT to type an
  arbitrary command into Start→Run (used to e2e-test the relay with
  telnet against a host echo server).
2026-04-11 15:36:20 -07:00
Felix Rieseberg
ccd2b28169 Add "Boot from scratch" to the Machine menu (#357)
* Add "Boot from scratch" to the Machine menu

Wires a new MACHINE_BOOT_FROM_SCRATCH IPC command from the app menu to the existing Emulator.bootFromScratch() handler, so users can start a fresh boot without going through the settings card. Enabled only while the machine is stopped, matching Start.

* Rename menu item to "Start without state"

* Move "Send key" items below power management in Machine menu
2026-04-11 15:27:22 -07:00
Felix Rieseberg
27b9e0eb7a Seamless mouse (VMware backdoor + VBADOS) and fs-backed TOOLS share (#355)
* Seamless mouse via VMware backdoor + fs-backed TOOLS share

v86 (rebuilt libv86.js from fork branch vmware-mouse): new VMwareMouse
device on port 0x5658 implementing GETVERSION/ABSPOINTER_* fed by the
existing mouse-absolute bus event. Move-only packets are coalesced so
the guest cursor never falls more than one frame behind. Emits
vmware-absolute-mouse on the bus when the guest driver toggles mode.

Renderer: listens for that event, keeps the v86 mouse enabled without
pointer lock, drops the startup auto-capture, and hides the host cursor
over the canvas (.seamless-mouse) while the driver is active. Falls back
to click-to-capture when no driver is present.

SMB: TOOLS share is now backed by the bundled guest-tools/ directory
(subdirectories work) with the synthetic README.TXT/_MAPZ.BAT overlaid
at the root. resolve() routes by tid; SEARCH and FIND_FIRST2 share a
single listForSearch helper.

guest-tools/mouse-driver/: VBMOUSE.EXE + VBMOUSE.DRV from VBADOS
(Javier S. Pedro, GPLv2). Load the TSR from AUTOEXEC.BAT and set
mouse.drv=vbmouse.drv in SYSTEM.INI to enable seamless mouse.

Also: tsconfig rootDir "." for TS 6.0 (preserves dist/src/ layout).

* docs: windows95-base now includes vmware-abspointer
2026-04-11 14:15:20 -07:00
Felix Rieseberg
1dbb853fe6 SMB: filename safety + hidden attrs; drop http://my-computer host browser (#354)
SMB share:
- Mark dotfiles HIDDEN and host junk (.DS_Store, Thumbs.db, ...) HIDDEN+SYSTEM
  so Explorer hides them by default but View > Show all files still works.
- Guard DOS device names (CON/PRN/AUX/NUL/CLOCK$/COM1-9/LPT1-9) in both the
  long name and the generated 8.3 name; covers nul.tar.gz and 'con .txt' too.
- Replace trailing dot/space runs with '_' so names don't alias their stripped
  form; block DEL and C1 control bytes.
- Fix duplicate listing of sanitized names (sfnMap was mutated mid-iteration).
- Thread attrs through OPEN/QUERY/FIND replies via DirEntry.attr / hostAttrs().
- New [5d] section in test-standalone.ts; 55 tests pass.

http file server:
- Remove the http://my-computer/ host-filesystem browser now that SMB covers
  folder sharing. fileserver.ts now serves only static/www at http://windows95/
  with a sep-suffixed traversal guard.
- Delete page-directory-listing.ts, page-error.ts, encoding.ts, hide-files.ts
  and the three isFileServer* settings keys (and unused SettingsManager.delete).
- Point static/www/apps.htm at the SMB share instead.
2026-04-11 14:15:20 -07:00
Felix Rieseberg
9b217731f5 Replace Parcel 1 with Vite (#353)
Swap the unmaintained parcel-bundler@1.x for Vite's build API, called
from the same generateAssets hook. Output layout is unchanged
(dist/src/main/main.js + dist/static/index.html + dist/renderer.{js,css})
so no runtime path changes — __dirname-based asset lookup, loadFile, and
packagerConfig.ignore all keep working.

Renderer is built in lib/CJS mode with Node builtins + electron
externalized; a one-line banner aliases exports=module.exports since the
Electron <script> context provides module/require but not a bare exports
global. CSS (98.css + root.css) is now imported from app.tsx so Vite
emits a single renderer.css with fonts inlined.

Drops parcel-bundler and rimraf (vite-build clears dist/ itself).
~800ms full build.
2026-04-11 14:15:19 -07:00
Felix Rieseberg
148f8e4874 SMB: long filenames, basename-derived share name, synthetic TOOLS share (#352)
Negotiate NT LM 0.12 (17-word response, Capabilities=0) so Win95 switches
from CMD_SEARCH (8.3-only) to TRANS2/FIND_FIRST2. Implement info level
0x104 (FILE_BOTH_DIRECTORY_INFO) with the win9x quirks Samba carries:
honor SearchCount/MaxDataCount (VREDIR drops the session if exceeded),
4-byte-align entries and the trans2 reply param/data blocks, dir
EndOfFile=0, FileName null-terminated with the null counted in
FileNameLength, and ShortNameLength=0 (a UCS-2 ShortName in an OEM
session GPFs shell32 on the single-directory probe Explorer does when
entering a subfolder). Add TRANS2_QUERY_FS_INFO (0x105/1/2), SMB_COM_SEEK
and core SMB_COM_READ, which the redirector falls back to with no
CAP_LARGE_READX. Sanitize >0xFF / Windows-reserved chars in display names
so emoji folder names don't truncate to '<' and wedge Explorer.

The user share is now named after path.basename of the mounted folder
(LANMAN-safe, ≤12 chars, with TOOLS/IPC$ collision avoided). A second
purely-synthetic TOOLS share holds _MAPZ.BAT and README.TXT so they
don't clutter the user's directory; treeConnect routes by share name to
a TID and every path-resolving handler branches on it so TOOLS never
touches the host fs.

48 protocol tests; verified end-to-end in the emulator (browse \\HOST,
open both shares, list Downloads with 85+ mixed-name entries, navigate
subfolders, open files in Notepad).
2026-04-11 12:26:54 -07:00
Felix Rieseberg
43c025929b Show git branch in window title during development (#351)
When running via yarn start on a branch other than master/main, append
the branch name to the window title (e.g. "windows95 (my-feature)").
No-op in packaged builds.
2026-04-11 11:06:08 -07:00
Felix Rieseberg
3b62e1c9b5 Replace Less with native CSS (#350)
The stylesheets only used Less for variables and nesting, both of which
are now native CSS features supported by Electron 41's bundled Chromium.

- src/less/ -> src/css/, all .less files renamed to .css
- @win-* variables -> :root custom properties + var()
- // comments -> /* */
- Dropped unused @win-silver
- Removed less devDependency and the dead 'less' npm script
  (pointed at a non-existent tools/lessc.js)
2026-04-11 10:45:04 -07:00
Felix Rieseberg
e9ddfab65d Stabilize VM info bar width, add sparklines and Interface settings (#349)
* Stabilize VM info bar width and add sparkline mode

* Add Interface settings tab and switch info bar to N.N unit format
2026-04-11 09:45:08 -07:00
Felix Rieseberg
89c0a8575d docs: update-v86.js rewrite + SMB/v86/testing knowledge (#348)
* Rewrite update-v86.js for the current build pipeline

Both v86 fixes we've been carrying are now real branches on the fork
(PR #1540 electron-renderer-fs-loader, PR #1541 ide-shared-registers)
combined as felixrieseberg/v86:windows95-base. update-v86.js no longer
needs to patch sources at build time — it just builds whatever's checked
out and copies the result.

Gone: the fallback-to-copy.sh path, the skew-day check, the structural
regex patches for load_file/exportSymbol/fetch-bind, the phantom-slave
guard (both are in the branch), the --js-only flag. If you don't have
cargo/clang/java/closure, the script fails loudly — no silent fallbacks.

Added: sanity checks against the installed libv86.js for the invariants
our SMB integration and parcel-build shim depend on, so if upstream
changes something load-bearing we see it as a WARN at update time
instead of a runtime failure.

Tested end-to-end: 5/5 sanity checks, fresh boot SUCCESS in 32s.

* docs and skills: capture SMB/v86/testing knowledge from the session

- docs/smb-share.md: user-facing SMB integration overview (how to mount in
  Win95, what's implemented, what's not). Points at the protocol-level
  README inside src/renderer/smb/ for wire-level gotchas.
- .claude/skills/probe-win95: how to boot and test the VM without a human.
  Env vars, file locations, failure modes, the XT scancode keyboard trick,
  bisect rules of thumb.
- .claude/skills/update-v86: how to pull upstream v86 changes, what the
  five sanity-check WARNs mean, how to retire the fork branches when the
  PRs merge upstream.

.gitignore narrowed to exclude only the runtime dirs (scheduled_tasks.lock,
worktrees) instead of the whole .claude/ tree, so skills can be committed.
2026-04-11 09:33:51 -07:00
Felix Rieseberg
2ef06eb412 Merge pull request #346 from felixrieseberg/claude/crazy-kilby
Modernize GitHub Actions workflow
2026-04-11 09:32:54 -07:00
Felix Rieseberg
3eab26fed1 check-links: allow 403 from github user-attachments CDN 2026-04-11 09:31:38 -07:00
Felix Rieseberg
1bef3cce62 Switch CI from yarn to npm (repo uses package-lock.json) 2026-04-11 09:04:03 -07:00
Felix Rieseberg
17e0182ecb Merge pull request #347 from felixrieseberg/claude/sharp-shirley
Redesign launcher UI with 98.css
2026-04-11 09:03:14 -07:00
Felix Rieseberg
4ed96deecc Restore CD-ROM settings tab behind a feature flag
The tab, file picker, and prop wiring are all back and styled to match
the new Properties sheet, gated on CDROM_ENABLED=false until v86's IDE
CD path works again.
2026-04-11 09:01:29 -07:00
Felix Rieseberg
80505384c6 Remove unused 95css vendor bundle 2026-04-11 09:00:34 -07:00
Felix Rieseberg
a0ee5a2f10 Drop dead CD-ROM handler and tighten navigate typing 2026-04-11 08:51:08 -07:00
Felix Rieseberg
74fc2d291e Redesign launcher UI with 98.css
Replace the sparse start/settings cards with a Win95-styled launcher:

- Start screen is now a 'Welcome to Windows 95' dialog with a gradient
  side stripe, a rotating tip box, and a button column.
- Settings is a tabbed Properties sheet (Floppy / Network / State) with
  group boxes, sunken read-only path fields, and OK/Cancel.
- Vendored 98.css and its Pixelated MS Sans Serif fonts; dropped the
  old 95css-based .btn/.card/.nav classes.
- Removed the bottom taskbar nav (start-menu.tsx) — navigation now goes
  through the dialog buttons so the launcher isn't mistaken for the
  running OS.
2026-04-11 08:48:11 -07:00