Documentation › LOCI
LOCI — Lovely Oric Computer Interface
Emulation of Sodiumlightbaby's LOCI device (sodiumlb, 2024): an RP2040 cartridge that plugs into the Oric bus and provides mass storage (USB / SD / internal flash), USB HID keyboard-mouse-gamepads, a WiFi modem (PicoWiFiModemUSB), runtime ROM swap and a built-in menu.
References: loci-hardware · loci-firmware · loci-rom (menu). The emulation is aligned with the firmware source (reference release: v0.3.1) and verified on hardware; known deviations are listed at the end.
Quick start
# LOCI + picowifi WiFi modem (ACIA 6551 at $0380, address $0380 NOT $03A0)
./oric1-emu -r roms/basic11b.rom --loci --serial picowifi
# LOCI menu straight from boot
./oric1-emu -r roms/loci/locirom --loci
# Raw FAT16/32 SD image as storage
./oric1-emu -r roms/basic11b.rom --loci --loci-sdimg card.img
Memory map
| Window | Contents |
|---|---|
$0310-$031F | WD1793 + DSK control (LOCI Microdisc mode; $0319 = 'L') |
$0315-$0317 | Low-level TAP protocol (PLAY/REC/READ_BIT, 14-bit frame) |
$0380-$0383 | ACIA 6551 (picowifi modem) — default under --loci |
$03A0-$03BF | MIA: UART console, API registers (xstack $03AC, errno $03AD/E, op $03AF), stub $03B0 (spin/BLOCKED), BUSY $03B2 bit 7, button trap $03BA-$03BF |
API (op $03AF) — 36/36 ops implemented
System (PIX_XREG, CPU_PHI2→1000 kHz, OEM_CODEPAGE,
RNG_LRAND, STDIN_OPT), clock (CLOCK, CLK_GET/SETTIME,
GETRES), files (OPEN/CLOSE/READ/WRITE_XSTACK/XRAM/LSEEK/UNLINK/RENAME),
directories (OPENDIR/CLOSEDIR/READDIR/MKDIR/GETCWD), mounting (MOUNT/UMOUNT, TAP
SEEK/TELL/READ_HEADER, UNAME), boot/tuning (MIA_BOOT,
MAP_TUNE_*, ADJ_SCAN), sentinel $FF (exit → spin).
Firmware-conforming ABI (verified against source)
- errno: filesystem errors =
32 + FRESULTFatFS (missing file → 36, missing directory → 37, denied/not-empty/full → 39, already exists → 40…); codes 1-18 are reserved for API errors (EBADF,EMFILE,ENODEV,ENOSYS, escape guard) — exactly like the firmware'sapi.h. - Descriptors: files 3-18 (FAT,
STD_FIL_OFFS=3), directories 64+ (FD_OFFS_FAT); the device iterator is fd 0 (FD_OFFS_DEV). - xstack: 512 bytes, conforming push/pop and NUL-less strings.
MAP_TUNE_*: value in register A; A ≤ 31 sets the delay, any other value is a query; the op always returns the current value in AX.ADJ_SCANsweeps tior 0-31 (~100 ms + 5 ms/step) with progress visible in ROM byte$FFF0.
Storage
The real LOCI has three tiers; their equivalents in Phosphoric:
| Real hardware | Emulation |
|---|---|
Internal flash (RP2040 LittleFS, pre-seeded with basic11b.rom,
basic10.rom, microdis.rom, locirom) |
flash root: --loci-flash DIR (default: current directory). 0: and
bare paths. System ROMs missing from the flash root are resolved as a fallback in the -r ROM's
folder (i.e. roms/). |
| USB key (FAT, host USB port) | --loci-usb DIR (repeatable, 4 max) or auto-detection of media mounted under
/media/$USER and /run/media/$USER at launch. Volume paths 1:-4:.
Label + size shown in the menu. No hot-plug: plug in before launching. |
| SD card (raw image) | --loci-sdimg PATH (FAT16/32). When active, this backend owns all file ops (USB keys stay
listed but non-navigable). |
The device list (menu selector) is served by opendir(""): “0: Internal
storage [15MB]”, then one line per USB device (the MSC key, the picowifi “CDC modem mounted”), then an empty
name.
Action button (F8)
The firmware behaviour (ext.c) is reproduced:
- Short press: session snapshot (→
<flash root>/loci_resume.ost), IRQ trap$03BA, then boot the LOCI menu (lociromfrom the flash root, fallbackroms/loci/locirom). Like the real firmware, the FW version (0.3.1) and timings are patched into the ROM at placeholders$FFF7-9/$FFEF-F3. The menu's resume entry re-swaps the previous ROM and restores the snapshot. Pressing F8 in the menu is ignored. - Long press (≥ 2 s): boot Mike Brown's diag ROM
(
roms/loci/test108k.rom, v1.08k, included in real firmware builds with his permission). Step-by-step CPU/ULA/DRAM/VIA/PSG test. - In
--controlmode: theloci-button [long]command. - F5 = MIA reset (registers/xstack/op) keeping mounts, like the Pico's reset button.
MIA bus timing
The MIA samples the 6502 bus via PIO at sub-cycle offsets set by MAP_TUNE_*. A mis-tuned
tior corrupts the picowifi's ACIA window — a real hardware symptom reproduced:
--loci-mia-window LO-HI defines the reliable range (default 0-31 = always reliable); outside the
window, $0380 reads $FF and ignores writes.
Known deviations (out of scope)
- Internal LittleFS flash not emulated as such — the flash root plays that role with FAT semantics.
- Firmware dev directory “0”, the real ULA pattern matcher, BUSY observable during a long op.
- USB detection at startup only (no hot-plug).
- The LOCI's
dsk_fdcstays on fast FDC timing — faithful: on real hardware its “drive” is the RP2040 + SD, with no mechanics (the Microdisc, by contrast, uses real mechanical timing by default).
Reproduced from docs/loci.md (authoritative, up-to-date version on GitHub).