# Remote IMSAI FIF Disk Server — User Guide

Complete reference for fdcServer.

# Table of Contents


# Installation

# Upgrading from fifDirSrv

If you previously installed fifDirSrv, uninstall it first to avoid conflicts:

pip uninstall fifDirSrv

If you received a .whl file, install it with pip. Place the wheel in a directory (e.g., dist/) and use --find-links to point pip at it:

pip install fdcServer --find-links path/to/wheel               # Core (includes web UI)
pip install "fdcServer[all]" --find-links path/to/wheel         # Everything (+ directory watching)

You can also install the wheel file directly by path, but extras cannot be specified this way:

pip install path/to/fdcServer-X.Y.Z-py3-none-any.whl   # Core only (no extras syntax)

All dependencies are installed automatically. To upgrade to a newer version, use --upgrade. To do a clean reinstall (e.g., if something seems broken), use --force-reinstall:

pip install --upgrade "fdcServer[all]" --find-links path/to/wheel              # Upgrade
pip install --force-reinstall "fdcServer[all]" --find-links path/to/wheel      # Fresh reinstall

# From source

Clone the repository and install with pip:

pip install .

This installs all core dependencies automatically (including web UI and windows-curses on Windows).

To include optional features:

pip install ".[watch]"        # Auto-detect external file changes in DIR mode
pip install ".[all]"          # Everything

After installation, three commands are available: fdcServer, fdc-pack, and fdc-unpack.

# Manual dependency install

If you prefer to run directly from the source tree without installing:

pip install -r requirements.txt
python fdcServer.py

The requirements.txt covers core dependencies only. For optional features, install manually:

pip install watchfiles                 # Directory watching

# Notes

  • On macOS and Linux, curses is included in the Python standard library. On Windows, the windows-curses package is installed automatically.
  • When watchfiles is installed, DIR-mode floppy drives automatically detect external filesystem changes and rebuild their in-memory directory. Without it, the server still works normally but won't detect changes made outside the server.
  • The terminal must be at least 80 columns x 24 rows for the curses UI.

# Running the Server

The entry point is the fdcServer command (or python fdcServer.py when running from source). One transport backend (serial or socket) runs at a time.

# Transport Auto-Detection (Default)

When neither --serial nor --socket is specified, the server automatically scans for an FDC USB device (VID 0xCAFE, bus description SDH-100 FDC). If found, it connects via serial at 2 Mbaud. If no device is found, it falls back to TCP socket transport on port 13740.

# Auto-detect FDC USB device; fall back to socket
fdcServer

The auto-detect result is printed to stderr:

  • Auto-detected FDC on COM3 — serial device found
  • No FDC serial device found, listening to socket on port 13740 — using socket

# Serial Transport

# Specify port (skip auto-detection)
fdcServer --serial COM3

# Specify port and baud rate
fdcServer --serial COM3 --baud 115200

The serial transport runs in a background thread and automatically reconnects if the connection drops.

# TCP Socket Transport

# Default port: 13740
fdcServer --socket

# Specify port
fdcServer --socket 9000

The socket transport accepts a single client connection at a time. The --baud option cannot be used with --socket.

# Disk Timing Simulation

# Enable timing simulation with socket transport
fdcServer --socket --timing

The --timing flag enables realistic disk access timing on the server side. When enabled, the server delays each response to simulate the mechanical behavior of the original disk hardware:

  • Seek time — Head stepping delay proportional to the number of tracks traversed
  • Rotational latency — Waiting for the target sector to rotate under the head
  • Sector transfer time — Time for one sector to pass under the head

Each drive maintains its own independent head position, so sequential accesses to nearby tracks are faster than random seeks across the disk.

Timing parameters are per-geometry:

Parameter DSK (floppy) HDD (hard disk)
RPM 360 3000
Track step time 8 ms 1 ms
Worst-case access ~781 ms ~274 ms

Timing is disabled by default. When using the web UI, timing can also be toggled at runtime via the Timing LED toggle in the toolbar — no server restart required. Toggling takes effect immediately on the next disk command.

# Web Interface (Default)

The web UI launches by default at http://localhost:8000. It provides drive management (insert/eject, mount/unmount, save, reload), real-time disk access visualization, a trace log viewer with log level control, a dark/light theme toggle, and a Timing LED toggle. See Drive Management — Web UI for details on the drive panel controls.

# Web UI on a specific port with socket transport
fdcServer --web 9000 --socket

Use --web PORT to override the default web UI port.

# Terminal Interface

# Terminal (curses) UI with serial transport
fdcServer --text

# Terminal UI with socket transport
fdcServer --text --socket

The --text flag selects the curses terminal UI instead of the web UI (which runs by default). --text and --web cannot be combined.

# Command-Line Reference

Argument Default Description
--serial [PORT] COM5 Use serial transport on the specified port (skip auto-detection)
--socket [PORT] 13740 Use TCP socket transport on the specified port (skip auto-detection)
--baud RATE 2000000 Baud rate (serial only; requires --serial)
--text off Use terminal (curses) UI instead of web UI
--web [PORT] 8000 Override web UI port
--timing off Enable disk timing simulation (seek, rotational latency, sector transfer)

--serial and --socket are mutually exclusive. If neither is specified, the server auto-detects the FDC USB device and falls back to socket transport if not found. --text and --web are mutually exclusive. If neither is specified, the web UI launches on port 8000.

# Logging

All debug output is written to trace.log (overwritten on each start). The terminal display is reserved for the curses UI.


# Disk Map Configuration

Drive assignments are stored in diskmap.json in the working directory. This is a simple JSON object mapping drive letters to file or directory paths:

{
  "A": "cpm22d01.dsk",
  "B": "cpm22d01.unpacked",
  "C": "work.dsk",
  "I": "harddisk.hdd"
}
  • Keys are drive letters: A, B, C, D, or I
  • Values are paths to .dsk files, .hdd files, or directories (unpacked format)
  • Drives not listed in the map default to LOCAL mode (passed through to the IMSAI's own disk handling)

The disk map is loaded on startup. You can reload it at any time (Ctrl+R in the terminal UI, or the Reload button in the web UI) and save the current state (Ctrl+P or the Save button).

If no diskmap.json file is found, the server starts with all drives in LOCAL mode and displays a warning.


# Drive Modes

Each drive operates in one of three modes:

Mode Display Description
IMG DSK:A: = IMG:cpm22d01.dsk Raw disk image file. Reads and writes go directly to the binary image.
DIR DSK:B: = DIR:cpm22d01.unpacked Host directory. The server synthesizes a CP/M disk in memory and mirrors file operations (create, delete, write) to the host filesystem in real time. If watchfiles is installed, floppy drives (A–D) also detect external changes to the host directory and rebuild automatically.
LOCAL DSK:C: = LOCAL: Not mounted by the server. The IMSAI handles this drive using its own local storage.

The mode is determined automatically:

  • A path pointing to a regular file (.dsk or .hdd) uses IMG mode
  • A path pointing to a directory uses DIR mode
  • Drives with no entry in the disk map use LOCAL mode

# Filename Shortening (DIR Mode)

CP/M filenames are limited to 8 characters for the name and 3 for the extension (the "8.3" format). When a host directory is mounted in DIR mode — or packed into a disk image with fdc-pack — any filenames that don't fit this format are automatically shortened and renamed on the host filesystem.

The shortening rules are:

  1. Case — The filename is converted to uppercase.
  2. Invalid characters — Characters not allowed in CP/M filenames (< > . , ; : = ? * [ ] % | ( ) / \ _) are removed.
  3. Truncation — Names longer than 8 characters are truncated to 6 characters followed by ~1 (e.g., VERYLONGNAME.TXT becomes VERYLO~1.TXT). Extensions longer than 3 characters are truncated to 3.
  4. Collision handling — If the shortened name already exists in the same user area, the trailing digit is incremented in hexadecimal: ~2, ~3, ... up to ~F (15 variants). If all 15 slots are exhausted, the file is skipped with an error.

Important: The rename is permanent — the original long filename on the host filesystem is replaced with the shortened version. A warning is logged for each rename (e.g., RENAMED FILE: VeryLongName.txt to VERYLO~1.TXT). If you need to preserve the original filenames, make a copy of the directory before mounting it.


# Drive Management

Both UIs support the same core drive operations. The web UI uses buttons and dropdowns; the terminal UI uses keyboard commands.

# Web UI

In the web UI (the default), each drive panel includes a context-sensitive control area that adapts to the drive's current state. All controls update in real time via server-sent events (SSE) — no page refresh is needed.

# Insert/Eject and Mount/Unmount

Each drive panel shows a single button that changes based on drive state:

  • Floppy drives (A–D) use Insert / Eject labels
  • Hard disk drive (I) uses Mount / Unmount labels

When a drive is unmounted, clicking the Insert/Mount button reveals a file selector inline. Select a file or directory to mount it automatically. Press Escape or click away to cancel and return to the button. When a drive is mounted, the Eject/Unmount button (styled with a red border) shows a browser confirmation dialog before unmounting.

After any mount or unmount operation, all drive panels update immediately: the button switches state, the drive label reflects the new assignment, and the file selectors on other drives are refreshed.

# File Selector

The file selector appears inline when you click Insert/Mount. It lists all .dsk and .hdd files plus all non-hidden subdirectories in the working directory, sorted alphabetically. Selecting a file immediately mounts it — no separate confirm button needed. Disks already mounted on other drives are filtered out automatically.

The file list is cached for 5 seconds. Mounting or unmounting any drive invalidates the cache immediately, ensuring selectors on all drive panels stay current.

# Duplicate Mount Prevention

Mounting the same path on two drives simultaneously is not allowed. If a path is already mounted on another drive, the mount is rejected and a status message appears: *** <path> already mounted on drive <X> ***. The file selector normally prevents this by hiding mounted paths, but the check also guards against race conditions.

# Save and Reload

The web UI toolbar includes Save and Reload buttons that are equivalent to Ctrl+P and Ctrl+R in the terminal UI. Save persists the current drive assignments to diskmap.json; Reload re-reads diskmap.json and remounts all drives.

# Terminal UI

All drive interaction in the terminal UI uses a two-step keyboard pattern: first select a drive, then issue a command.

# Drive Selection

Press a drive letter key to select it for the next command:

Key Drive Geometry
A Drive A (unit 1) Standard 8" floppy (DSK)
B Drive B (unit 2) Standard 8" floppy (DSK)
C Drive C (unit 4) Standard 8" floppy (DSK)
D Drive D (unit 8) Standard 8" floppy (DSK)
I Drive I (unit 15) Hard disk (HDD)

The selected drive is shown in the status bar at the bottom of the screen: DRIVE: DSK:A:

Drive selection is consumed by the next command — after any command key is processed, the selection resets. Drive letters are case-sensitive (uppercase only).

# Drive Commands

These require a drive to be selected first (press a drive letter, then the command):

Key Action
Ctrl+L Load — Opens a text input prompt where you type a file path or directory path to mount on the selected drive. Press Enter to confirm or Ctrl+G to submit.
Ctrl+U Unload — Unmounts the selected drive, reverting it to LOCAL mode. Requires a drive to be selected first, and only works if the drive currently has something loaded.

# Save and Reload

Key Action
Ctrl+P Persist — Save the current disk map to diskmap.json
Ctrl+R Reload — Reload diskmap.json from disk and remount all drives

# Text Input (during Ctrl+L)

When loading a drive path, a text input field appears at the bottom of the screen. This uses standard curses textpad editing keys:

Key Action
Printable characters Insert at cursor position
Enter / Ctrl+J Submit the path
Ctrl+G Submit the path (alternative)
Backspace / Ctrl+H Delete character before cursor
Ctrl+D Delete character under cursor
Ctrl+A Move cursor to start of input
Ctrl+E Move cursor to end of input
Ctrl+F / Right Arrow Move cursor right
Ctrl+B / Left Arrow Move cursor left
Ctrl+K Clear from cursor to end of input

# Workflows

# Mount a disk image on drive B
  1. Press B to select drive B
  2. Press Ctrl+L to open the load prompt
  3. Type the path: cpm22d01.dsk
  4. Press Enter
  5. Cold boot or warm boot the IMSAI to recognize the new drive
# Mount a directory on drive C
  1. Press C to select drive C
  2. Press Ctrl+L
  3. Type the path: myfiles.unpacked
  4. Press Enter
  5. Reboot the IMSAI
# Unload drive B
  1. Press B to select drive B
  2. Press Ctrl+U
# Save your drive layout

Press Ctrl+P to persist the current drive assignments to diskmap.json. This ensures your configuration survives server restarts.

# Edit files externally on a DIR drive

If watchfiles is installed, changes made to the host directory by external tools (text editors, cp, rm, etc.) are detected automatically:

  1. Mount a directory on a floppy drive (e.g., drive B)
  2. Edit, add, or remove files in the host directory using any tool
  3. The server detects the change and rebuilds the in-memory directory
  4. The description row shows <HOST> Host filesystem changed — directory rebuilt
  5. Warm boot or cold boot the IMSAI to pick up the new directory

Notes:

  • Automatic watching is only available for floppy drives (A–D), not the hard disk drive (I)
  • Rapid external changes (e.g., pasting multiple files) are debounced into a single rebuild
  • Directory-only metadata events are filtered out — only actual file changes trigger a rebuild
  • Server-initiated filesystem changes (from CP/M writes) are suppressed automatically. The watcher stays suppressed while the write buffer is non-empty, so cross-drive operations like PIP B:=A:FILE are handled safely
  • Without watchfiles installed, you can still manually reload by unloading and re-loading the drive
# Reload after editing diskmap.json

If you edit diskmap.json externally (e.g., in a text editor), press Ctrl+R to reload and remount all drives without restarting the server.


# Display & Visualization

Both UIs provide real-time feedback on drive activity, connection state, and disk access, rendering the same underlying event stream differently.

# Web Display

The browser-based interface provides a dashboard with real-time updates via server-sent events (SSE). A dark/light theme toggle (sun/moon icon) in the top-right corner lets you switch themes — the choice is remembered across sessions and also applies to the User Guide page. The main display includes:

  • Connection status bar — Green when connected, red when disconnected
  • RECV indicator — Flashes during packet processing
  • Drive panels — One per drive (A/B/C/D/I), each showing the drive label, command status (READ in green, WRITE in yellow), and a red LED indicator that lights when the drive is accessed. The hard disk drive (I) uses a neutral grey panel to distinguish it from the blue-tinted floppy drive panels
  • Disk access visualization — An SVG rendering of the disk surface showing track rings, sector divisions, and animated arcs for recent access operations (reads in green, writes in yellow). The visualization switches to a grey palette when showing hard disk activity
  • 7-segment display — Shows TRK, SEC, DMA, and RES values as retro LED digits with dark backgrounds, updated after each command
  • Trace log panel — A collapsible panel that shows trace output in real time with auto-scrolling, capped at 10,000 lines for browser performance. Includes a Clear button and log level selector (INFO, WARN, ERROR) with LED indicators to dynamically change server log verbosity. Controls are hidden when the panel is collapsed
  • Timing toggle — A green LED toggle in the toolbar to enable or disable disk timing simulation at runtime (no server restart needed)

# Terminal Display

The curses UI is organized as a bordered panel with the title [ Remote IMSAI FIF - fdcServer ] centered at the top.

# Screen Layout

+----------------------[ Remote IMSAI FIF - fdcServer ]-----------------------+
|FDC listening on COM5 @ 2000000 baud                                         |
|***You must COLD BOOT the IMSAI to recognize the remote FIF***               |
|RECV                                                                         |
|DSK:A: = IMG:cpm22d01.dsk          READ   TRK:  5 SEC:  3 DMA: 0080h RES: 01h|
|...........R.................................................................|
|           D                                                                 |
|0: ASM     .COM                                                              |
|DSK:B: = DIR:cpm22d01.unpacked     Login/Warm boot to reload disk            |
|..W..........................................................................|
|  E                                                                          |
|0: DUMP    .COM                                                              |
|                                  ... more drives ...                        |
| KEY: <^P>  DRIVE: DSK:A:                                                    |
+-----------------------------------------------------------------------------+

# Row Descriptions

Row Content
Row 0 Transport status — green when connected, red when disconnected, yellow when listening for connections
Row 1 Startup message / disconnect warning
Row 2 Activity indicator — flashes RECV in reverse-video green during packet processing; also shows diskmap load/save confirmations
Drive rows (repeating groups of 4 per drive)
Label row Drive assignment (e.g., DSK:A: = IMG:cpm22d01.dsk) with command status and result
Track row Head position visualized as dots with R (read) or W (write) at the active track
Sector type row Sector classification at active position: B (boot), D (directory), E (data)
Description row File/extent info (e.g., 0: ASM.COM), directory action (e.g., <DIR> - CREATE FILE: 0:ASM.COM), or host watcher notification (<HOST> Host filesystem changed — directory rebuilt)
Bottom row Key press feedback and selected drive

# Color Coding

Color Meaning
Green Transport connected / RECV indicator
Red Transport disconnected
Yellow Warnings, hints (e.g., "Login/Warm boot to reload disk")
Cyan Key press feedback
Reverse green RECV activity indicator
Dim yellow Secondary hints

# Track Position Display

The track bar shows a row of dots (.) representing all tracks on the disk. The current head position is marked with a letter:

  • R — Read operation in progress
  • W — Write operation in progress

For high-track-count disks (e.g., HDD with 255 tracks), the display is scaled down with a [x2] or similar suffix indicating the scale factor.

# Command Status

Each drive's label row shows the current command at column 35 (e.g., READ TRK: 5 SEC: 3 DMA: 0080h) and the result at column 69 as a hex FIF result code (e.g., RES: 01h for OK, RES: 00h for IGNORED, RES: C5h for bad track).

# Trace Log Overlay

Press Ctrl+T to toggle the trace log overlay. Shows a scrollable view of trace.log with ANSI colors. Use Up/Down arrows to scroll one line, PgUp/PgDn to scroll one page, Home/End to jump to the start/end. The overlay auto-follows new output; scrolling up switches to manual mode, End re-enables auto-follow. Press Ctrl+T again to close.

# Other Commands

Key Action
? Help — Show a popup with all keyboard commands and drive mappings. Press any key to dismiss.
Ctrl+W Redraw — Refresh the entire terminal display (useful if the screen becomes garbled)
Ctrl+C Quit — Shut down the server cleanly (closes all drives, stops transport)

# Key Feedback

Every key press is displayed in cyan at the bottom-left of the window as KEY: <x>, providing immediate visual confirmation of input.


# Disk Image Utilities

Two utility scripts convert between raw disk images and the unpacked directory format used by DIR mode.

# Unpacking a Disk Image

Extract a .dsk or .hdd image to a host directory:

fdc-unpack cpm22d01

This looks for cpm22d01.dsk (then cpm22d01.hdd) and creates cpm22d01.unpacked/ containing:

cpm22d01.unpacked/
  $BOOT              # Boot track data (if present)
  $ATTR              # File attribute sidecar (if any non-default attributes)
  0/                 # CP/M user area 0
    ASM.COM
    DDT.COM
    DUMP.COM
    ...
  1/                 # CP/M user area 1
    ...

Files are named in CP/M 8.3 uppercase format. User area subdirectories (0 through 15) correspond to CP/M user numbers.

# The $BOOT File

The $BOOT file contains the raw binary data from the disk image's boot tracks (tracks 0 and 1 for DSK format — 6656 bytes total). It is only created during unpacking if the boot tracks contain actual data (i.e., the first byte is not the CP/M empty marker 0xE5).

When a directory is mounted in DIR mode, the server reads $BOOT to serve boot track requests from the IMSAI. If the IMSAI writes to the boot tracks, the server creates or updates the $BOOT file in the unpacked directory.

When packing a directory back to an image with fdc-pack, the $BOOT file's contents are written to the boot tracks of the new image.

HDD format has no boot tracks (offset=0), so $BOOT is not used with .hdd images.

# The $ATTR File and File Attributes

CP/M 2.2 stores 11 attribute bits in each directory entry: T1' (R/O), T2' (SYS), T3' (Archive), and F1'–F8' (application-defined). In DIR mode and across fdc-pack/fdc-unpack, these bits are preserved via two host-side mechanisms:

  • R/O (T1') maps to the host file's write permission. The server reads the bit from the host file and, when CP/M toggles R/O (e.g., STAT FOO.TXT $R/O), it calls chmod to match. This is cross-platform: standard Unix permissions on Linux/macOS, and the FILE_ATTRIBUTE_READONLY flag on Windows.
  • SYS, Archive, and F1'–F8' are stored in a JSON sidecar named $ATTR at the root of the unpacked directory, keyed by user/FILENAME.EXT:
{
  "0/ASM.COM":  { "sys": true, "arc": true },
  "0/HELP.HLP": { "sys": true },
  "1/TOOL.COM": { "app": "0x80" }
}

The sidecar is sparse — only files with at least one non-default non-R/O bit appear. Missing entries mean "all default bits." An empty directory is written as {}. The app field packs F1'–F8' into a single byte with F1' as the most significant bit.

External changes are detected. If watchfiles is installed, changing a file's R/O state on the host (with chmod, file-properties dialogs, attrib on Windows, etc.) or editing $ATTR directly triggers a rebuild so the new bits are reflected on the CP/M side at the next directory read.

$ATTR is treated like $BOOT — it does not appear in CP/M directory listings.

# Packing a Directory to a Disk Image

Create a new disk image from an unpacked directory:

fdc-pack cpm22d01.dsk

This reads from cpm22d01.unpacked/ and writes a fresh cpm22d01.dsk image. Use .hdd extension for hard disk format.

A CP/M directory listing is printed to stdout after both operations. If the unpacked directory contains more files or data than the target format can hold, fdc-pack reports a clear "DISK FULL" or "DIRECTORY FULL" error and exits without creating the image.

Both utilities pause with "Press Enter to exit..." before closing so you can read the output. The pause is skipped automatically when the utilities are run in a script or pipe (non-interactive use).


# Supported Disk Formats

# Standard Floppy (DSK)

Used for drives A, B, C, and D.

Parameter Value
Tracks 77
Sectors per track 26
Sector size 128 bytes
Block size 1 KB
Directory entries 64
Boot tracks 2
Disk capacity ~243 KB
Sector translation IBM 3740 (8" floppy)
File extension .dsk

This matches the standard CP/M 2.2 single-density 8-inch floppy format.

# Hard Disk (HDD)

Used for drive I.

Parameter Value
Tracks 255
Sectors per track 128
Sector size 128 bytes
Block size 2 KB
Directory entries 1024
Boot tracks 0
Disk capacity ~4 MB
Sector translation None (1:1)
File extension .hdd

# Architecture Overview

The server is organized as a layered Python package (fdc/):

fdcServer.py                 Entry point (thin wrapper)
fdc/
  server.py                  CLI parsing, component wiring, startup
  events.py                  Event types and DriveObserver protocol
  disk/
    constants.py             CP/M constants (sector size, extent size, etc.)
    geometry.py              Disk geometry definitions (DSK, HDD)
    fif/
      drive.py               DriveMap — drive orchestration, command execution
      image.py               ImageDisk — raw binary image read/write, pack/unpack
    filesystem/
      directory.py           CP/M directory entry parsing and formatting
      dirfs.py               DirDisk — virtual disk backed by host directory
      watcher.py             Directory watcher for external change detection
  transport/
    detect.py                USB device auto-detection (Win/macOS/Linux)
    protocol.py              Wire framing (base64 + CRC-16) and command parsing
    serial_transport.py      Serial port transport with auto-reconnect
    socket_transport.py      TCP socket transport (single client)
  ui/
    curses/
      curses_ui.py           Terminal display and keyboard input handling
      trace_overlay.py       Scrollable trace log overlay for curses UI
    web/
      web_ui.py              FastHTML-based web UI with SSE live updates
      palette.py             Centralised colour palette (functional + themeable)
      disk_svg.py            SVG disk access visualization
      seg7_svg.py            SVG 7-segment display rendering

# Layers

  • Presentation (ui/) — Curses terminal UI or FastHTML web UI, keyboard/browser input, event rendering
  • Orchestration (server.py, drive.py) — CLI, component wiring, drive management, command dispatch
  • Domain (disk/) — CP/M disk geometry, directory structures, image and directory filesystem backends
  • Transport (transport/) — Wire protocol framing, serial and socket I/O

# Observer Pattern

Components communicate through a DriveObserver protocol. The DriveMap and transport backends emit DiskEvent objects for disk activity, connection state changes, and status updates. Both CursesUI and WebUI implement this protocol, queuing events thread-safely for display on the main thread.

# Wire Protocol

Commands from the IMSAI arrive as base64-encoded frames with CRC-16 (IBM 3740 / CRC-CCITT) checksums. The server responds with:

  • & + base64 data — Success (with optional read data)
  • # — Error
  • @IGNORED — Drive is LOCAL, no action taken

# Management Commands

In addition to disk I/O, the wire protocol supports management commands that allow a connected client to query and modify the drive configuration without the web UI:

  • Diskmap — Get the current drive assignments
  • List — List available disk images and directories, with their mount status
  • Eject — Unmount a drive
  • Insert — Mount a disk image or directory to a drive

Management changes are in-memory only and are not saved to diskmap.json. Use the web UI Save button or Ctrl+P in the terminal UI to persist changes.

# Disk-Change Notification

When the drive configuration changes — from any source (web UI, management command, or diskmap reload) — the server notifies the connected client on its next disk command. The client can then update its view of the drive state before continuing. Management commands themselves are not affected by this notification.

# Drive Letter Mapping

Drive Unit Number Geometry
A 1 DSK (floppy)
B 2 DSK (floppy)
C 4 DSK (floppy)
D 8 DSK (floppy)
I 15 HDD (hard disk)

# Troubleshooting

# General

# "Warning: no diskmap.json file found"

No diskmap.json exists in the working directory. The server starts with all drives in LOCAL mode. Create a diskmap.json or load drives interactively (via Ctrl+L in the terminal UI or the Insert/Mount button in the web UI), then save (Ctrl+P or the Save button).

# IMSAI doesn't see the remote drives

You must cold boot the IMSAI after starting the server for it to recognize the remote FIF. A warm boot may also work for reloading individual drives.

# Serial connection drops

The serial transport automatically attempts to reconnect after 1 second. The display will show a red disconnection message and a yellow restart notice. Reconnection is automatic — no user action is needed.

# Changes not persisted after restart

Drive changes made at runtime (via Ctrl+L/Ctrl+U in the terminal UI, or Insert/Eject/Mount/Unmount in the web UI) are in-memory only until you save to diskmap.json (Ctrl+P or the Save button).

# "Error: DISK FULL" or "Error: DIRECTORY FULL" when packing

The unpacked directory contains more data or more files than the target disk format supports. Remove files from the unpacked directory, or use a larger format (.hdd instead of .dsk).

When this error occurs during a DIR-mode mount (e.g., after external files are added to the host directory), the drive falls back to LOCAL mode and a status message is displayed. Remove files from the host directory to bring it within capacity, then remount.

# "already mounted on drive X" / "Duplicate: ... skipped"

Each disk image or directory can only be mounted on one drive at a time. This message appears in two situations:

  • Interactive mount (web UI): You attempted to mount a path that is already loaded on another drive. Eject/unmount it from the other drive first.
  • Diskmap reload: Your diskmap.json assigns the same path to multiple drives. The server keeps the first occurrence (in A, B, C, D, I order) and skips duplicates. Edit diskmap.json to remove the duplicate entry.

# External file changes not detected

Directory watching requires the optional watchfiles package. Install it with pip install watchfiles. Without it, the server logs a warning at startup (watchfiles not installed — directory watching disabled) and DIR-mode drives won't detect external changes. Watching is also only supported on floppy drives (A–D); the hard disk drive (I) does not use directory watching.

# Terminal

# "Curses error: Try making the viewport larger (>= 80x24)"

The terminal window is too small. Resize it to at least 80 columns by 24 rows.

# Display is garbled

Press Ctrl+W to redraw the entire screen.

Last Updated: 5/3/2026, 6:56:21 PM