Configuration Reference¶
This document describes the desktop settings file, per-game overrides, input profiles, NVRAM, paths, and environment variables. The CLI does not read settings.json; its behavior is controlled entirely by command-line options (see CliReference.md).
1. Where settings live¶
The desktop app uses .NET's local application data folder:
AppSettingsStore.DefaultDirectory and DefaultPath implement this. On Windows:
%LOCALAPPDATA%\5DO\settings.json
%LOCALAPPDATA%\5DO\nvram.ram
%LOCALAPPDATA%\5DO\states\slot-00.tdos
On Linux, .NET maps LocalApplicationData to the XDG data directory, typically ~/.local/share/5DO. On macOS it is the .NET LocalApplicationData location for the current user; use the About dialog or the path shown in Settings > Paths to see the exact path rather than hard-coding one.
| File / directory | Purpose |
|---|---|
settings.json | All persistent desktop settings, including the input profile. |
nvram.ram | Shared 32 KB 3DO NVRAM image (global version 0), written atomically. |
nvram.<version>.ram | Global version 1-9 image. |
nvram/per-game/<gameId>.<version>.ram | Per-game NVRAM image. |
nvram*.bad | A corrupt NVRAM image moved aside on load; the app starts fresh. |
states/ | Default save-state directory (slot-NN.tdos, sidecar JSON, PNG thumbnail). |
settings.json.tmp | Temporary file used during atomic settings writes. |
The screenshot directory defaults to the user's Pictures folder when ScreenshotDirectory is empty. The save directory defaults to <data-directory>/states when empty.
Portable mode. Place a portable.flag file next to the executable (or pass --portable) to keep settings.json, NVRAM, states/, cheats, library state, and logs beside the executable. FIVEDO_DATA_DIR overrides the data directory and is useful for separate instances. Portable mode never writes to %LOCALAPPDATA%; the executable directory must be writable.
Named profiles. --config-profile <name> (or FIVEDO_PROFILE) selects <data-directory>/profiles/<name>/ for settings, NVRAM, save states, cheats, library state, and logs. Profiles are created on first launch and isolated from each other. 5do settings profiles lists existing profile directories; FIVEDO_DATA_DIR takes precedence over a named profile. Settings > Paths selects a profile and writes <base>/default-profile.txt for the next launch, creates a profile from the current settings, opens the profiles folder, and imports/exports settings JSON. The desktop acquires <data>/5do.instance.lock at startup; a second process using the same directory shows the owner and exits. FIVEDO_ALLOW_MULTIPLE=1 disables that guard. Different profiles or data directories use different lock files and may run together.
Settings are written atomically (temporary file + replace) and carry "SettingsVersion": 4. An older file is migrated in place on the next load. A malformed settings.json is copied to settings.json.invalid-<timestamp>.bak before defaults are used, so the original bytes are never silently lost. Back up or delete the file to reset the desktop configuration.
2. settings.json schema¶
The file is indented JSON with PascalCase property names and string enum values. Unknown properties are ignored by System.Text.Json. Fresh settings use the optimized defaults: OpenGL presentation, match-window output, sharp-bilinear filtering, vsync on, integer scaling, and automatic presentation frame skipping. The following table lists every serialized property in AppSettings.
| Property | Type | Default | Meaning |
|---|---|---|---|
SettingsVersion | int | 4 | Settings schema version. Unversioned files are migrated on load. |
FirstRunCompleted | bool | false | Whether the first-run guide has been shown. |
BiosPath | string | "" | Last primary BIOS path; fallback when auto-selection is off or unavailable. |
Bios2Path | string | "" | Optional BIOS2/Kanji font path. |
BiosFolder | string | "" | Folder scanned for automatic region/BIOS selection. |
AutoBios | bool | true | Select a region-appropriate BIOS when BiosFolder is set. |
BiosOverrides | object | {} | Per-game BIOS MD5 overrides keyed by 4DO game ID. |
DonationEmail | string | "" | Optional email used to recognize a 5DO donation. |
HasDonated | bool | false | Cached confirmation for DonationEmail. |
DonationLastCheckedUtc | string? | null | UTC timestamp of the last successful donation check. |
DiscPath | string | "" | Last disc path. |
RecentDiscs | string[] | [] | Recent disc paths, newest first, capped at 10. |
SaveDirectory | string | "" | Save-state directory; empty means <LocalApplicationData>/5DO/states. |
ScreenshotDirectory | string | "" | Screenshot directory; empty means the user's Pictures folder. |
CheatsDirectory | string | "" | Per-game cheat JSON directory; empty means <LocalApplicationData>/5DO/cheats. |
SaveSlot | int | 0 | Selected zero-based slot. Clamped to the slot count on load. |
SaveSlotCount | int | 10 | Number of slots. Clamped to 1..100 on load. |
LibraryFolders | string[] | [] | Folders scanned by the game library. |
LibraryCardSize | double | 176 | Game-card width in device-independent pixels for the grid library (128-384). Invalid values fall back to the default. |
LibraryMetadataPath | string | "" | Optional offline metadata JSON; empty means <LocalApplicationData>/5DO/library-metadata.json. |
DiscDatPath | string | "" | Optional Redump/No-Intro DAT used by the library disc-health check; empty disables the known-dump match. |
AutoGameFixes | bool | true | Apply the 4DO per-game fix-mode mapping automatically. |
FixModeOverrides | object | {} | Per-game fix-mode overrides, keyed by game ID. |
FilterOverrides | object | {} | Per-game filter overrides, keyed by game ID. |
GameProfiles | object | {} | Per-game profile snapshots, keyed by game ID. Each entry holds Profile, Region, ArmTiming, ClioTimers, CelTiming, CdromTiming, CdSpeed, CpuClockMultiplier, RandomSeed, OperaDipir, OperaSoftReset, SwiHle, CpuBackend, CdAudioVolume, CdAudioMuted, BiosMd5, FixMode, Filter, HighResolution, Overscan, InputDevices, NvramStorageMode, NvramVersion, and CheatBundle. |
Filter | enum string | "SharpBilinear" | Global presentation filter. |
FrameSkip | enum string | "Auto" | Presentation frame-skip policy: Off, Auto, OneInTwo, OneInThree, OneInFour, or OneInFive. Only presentation is skipped; emulation and audio always run every frame. |
Aspect | enum string | "FourThree" | Aspect policy. |
CustomAspect | double | 1.3333 | Width/height ratio used when Aspect is Custom. |
Vsync | bool | true | Request platform vsync (where supported). |
IntegerScale | bool | true | Prefer integer scaling for 4:3/integer modes. |
DisplayRefreshRate | int | 60 | Presentation refresh rate in hertz. 60 keeps render-on-demand, 30-480 re-present the latest frame at that rate, and 0 follows the compositor. The 3DO still produces 60 fields per second (50 for PAL). |
OverscanPixels | int | 0 | Legacy uniform crop applied to every edge when the per-edge values are all zero (0-32). Presentation-only. |
OverscanLeft | int | 0 | Left-edge crop in native pixels (0-32). Takes precedence over OverscanPixels when any per-edge value is nonzero. |
OverscanTop | int | 0 | Top-edge crop in native pixels (0-32). |
OverscanRight | int | 0 | Right-edge crop in native pixels (0-32). |
OverscanBottom | int | 0 | Bottom-edge crop in native pixels (0-32). |
VideoBorderPixels | int | 0 | Gray/void border around the presented image in screen pixels (0-64). Presentation-only. |
VoidAreaColor | string | "#FF101010" | Void-area and border color as #RRGGBB or #AARRGGBB. Invalid values fall back to the default. |
Renderer | enum string | "OpenGl" | Presentation backend: OpenGl, Vulkan, or Software. |
OutputResolution | enum string | "Window" | Final output size: Window, Native, Scale2X, Scale3X, Scale4X, Hd720, FullHd1080, Qhd1440, or Uhd2160. |
ShowOverlay | bool | false | Show the FPS/status overlay. |
ShowInputDisplay | bool | false | Show the frame/skip/lag counters and controller buttons over the game. |
InputDisplayPlayer | int | 1 | Controller port (1-6) shown by the input display. |
OsdEnabled | bool | true | Show transient on-screen notifications. |
OsdPosition | enum string | "TopRight" | Notification anchor: TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, or BottomRight. |
OsdOpacity | double | 0.9 | Notification opacity, 0.1..1. |
OsdDurationMilliseconds | int | 2200 | Notification lifetime, 500..10000 ms. |
QuickMenuEnabled | bool | true | Enable the F4/Select+Start in-game quick menu. |
SaveNativeScreenshot | bool | false | Also write a -native.png CPU frame with each screenshot. |
Bloom | float | 0.35 | CRT bloom strength, 0..1. |
FsrSharpness | float | 0.8 | FSR 1.0 RCAS sharpness, 0 (soft) .. 1 (maximum). |
HighResolution | bool | false | Opt-in 640x480 CEL/VDLP mode. |
Profile | enum string | "Compatible" | Last selected timing profile: Compatible, Accuracy, Performance, or Custom. The individual timing fields remain authoritative. |
Region | enum string | "Ntsc" | Video region used when AutoRegion is off: Ntsc (320x240, 60 Hz), Pal1 (320x288, 50 Hz), or Pal2 (384x288, 50 Hz). |
AutoRegion | bool | true | Follow the resolved BIOS video standard: PAL BIOS selects PAL1, NTSC selects NTSC. Disable to force Region. |
ArmTiming | enum string | "FreeDoCompatible" | ARM60 N-cycle class: FreeDoCompatible (N=4) or Arm60Datasheet (N=2, accuracy). |
ClioTimers | enum string | "FreeDoCompatible" | CLIO timer scan: FreeDoCompatible (all sixteen timers per event) or OperaScheduler (one slot at a time with an explicit cascade carry). |
CelTiming | enum string | "FreeDoCompatible" | MADAM CEL timing: FreeDoCompatible (synchronous draw) or OperaBusy (deferred draw with a pixel/texel busy deadline). |
CdromTiming | enum string | "FreeDoCompatible" | CD-ROM data timing: FreeDoCompatible (immediate transfers) or OperaCycleBased (cycle-based sector readiness with delayed status/FIQ). |
CdSpeed | enum string | "X2" | Effective read speed for OperaCycleBased: Unbounded, X1, X2 (stock), X4, X8, X16, X24, or X32. Ignored by FreeDoCompatible. |
MemoryConfiguration | enum string | "Dram2MbVram1Mb" | DRAM/VRAM capacity: Dram2MbVram1Mb (stock 21), Dram2MbVram2Mb (22), Dram4MbVram1Mb (41), Dram4MbVram2Mb (42), Dram8MbVram1Mb (81), Dram8MbVram2Mb (82), Dram14MbVram2Mb (E2), or Dram15MbVram1Mb (F1). Recorded in save states; changing it restarts the machine. |
CpuClockMultiplier | double | 1.0 | ARM clock multiplier, 0.5..4.0 (6.25-50 MHz). 1.0 is the stock 12.5 MHz. |
RandomSeed | uint? | null | Optional initial DSP PRNG seed; null uses FreeDO's 0xa5a5a5a5. |
OperaDipir | bool | false | Opt-in CLIO DIPIR latches and XBUS access aborts. Recorded in save states and included in per-game profiles. |
OperaSoftReset | bool | false | Opt-in Opera ARM/MADAM/DSP soft-reset path for CLIO CSTAT resets. Recorded in save states and included in per-game profiles. |
SwiHle | bool | false | Opt-in Portfolio OS fixed-point math SWI HLE (0x50000-0x50012). Recorded in save states and included in per-game profiles. It is a performance mode that skips the guest handler's cycles and register clobbers, so some titles change behavior. |
CpuBackend | enum string | "Interpreter" | Guest ARM60 backend. Interpreter is the reference; Jit compiles hot blocks and falls back safely. |
NvramStorageMode | enum string | "Global" | Global keeps one shared image; PerGame keeps a separate image per 4DO game ID. |
NvramVersion | int | 0 | Independent NVRAM version slot, 0-9. |
NvramDirectory | string | "" | Directory that owns the NVRAM layout; empty means the resolved data directory (portable-aware). |
Volume | float | 1.0 | OpenAL gain, 0..1. |
AudioEnabled | bool | true | Enable live OpenAL output. |
CdAudioVolume | float | 0.8 | CD-DA mix level, 0..1. Applies only while PLAY_AUDIO is active. |
CdAudioMuted | bool | false | Keep CD-DA playback running but remove it from the mixed output. |
AudioDevice | string | "" | OpenAL playback device name; empty uses the system default. |
AudioBufferMilliseconds | int | 100 | Target OpenAL buffer latency, 20-500 ms. |
PointerPort | int | 0 | 0 sends host pointer input to every pointer device; 1-8 routes it to that controller port. |
HideLightgunCrosshair | bool | false | Hide the desktop lightgun crosshair. The pointer still drives the emulated lightgun; useful when the game draws its own reticle or when recording. |
PointerScale | float | 1.0 | Pointer calibration scale (0.5-2.0). |
PointerOffsetX, PointerOffsetY | int | 0 | Pointer calibration offset in native pixels. |
AutoSwapOnEject | bool | true | Advance to the next playlist entry when the guest ejects the disc (ODE-style). Without a playlist, F3 opens a disc picker. |
RewindEnabled | bool | true | Record compressed keyframes and input for rewind. |
RewindSeconds | int | 60 | Rewind history length in seconds, 30..300. |
FastForwardMultiplier | int | 4 | Fast-forward speed, 2..10. Audio is muted while active. |
InputDevices | string[] | eight "Joypad" entries | PBUS device per port: Joypad, Flightstick, Mouse, Lightgun, ArcadeLightgun, OrbatakTrackball, or None. Ports 7-8 use the Opera daisy chain; the legacy 4DO packet carries six. |
ActiveInputDevices | int? | null (automatic) | Maximum polled PBUS devices, 0-8. 0 reports no devices; 8 allows every port. Automatic keeps one joypad and grows to the highest configured peripheral port. |
InputDeviceOverrides | object | {} | Per-game eight-device lists keyed by game ID. An override wins over InputDevices. |
AutoInputDevices | bool | true | Seed a lightgun or Orbatak trackball override for known titles when the game has no override. |
Input | object | defaults | Six-player keyboard/gamepad bindings plus hotkeys. |
The legacy PreferOpenGl boolean is still read when loading older files; false maps to Renderer: "Software". New files write Renderer instead.
Enum values¶
Filter (string): Accurate, Nearest, SharpBilinear, Crt, Xbr, Hqx, Hqx3x, Hqx4x, Fsr.
FrameSkip (string): Off, Auto, OneInTwo, OneInThree, OneInFour, OneInFive. Auto skips a presentation frame only after three presented frames exceed the audio-derived frame budget; it recovers after 120 good frames. The fixed modes present one of every 2/3/4/5 emulated frames. In every mode the ARM CPU, CEL engine, DSP, timers, and CD-ROM still execute all frames, so game speed, input, audio, and save states are identical.
Aspect (string): Integer, FourThree, Stretch, Custom.
Renderer (string): OpenGl, Vulkan, Software.
Profile (string): Compatible, Accuracy, Performance, Custom. A profile is a shortcut for the individual timing fields; it never changes fixes, high-resolution mode, or the random seed. If the fields no longer match the selected profile, the dialog saves Custom.
Region (string): Ntsc, Pal1, Pal2. NTSC runs 60 fields per second with 240 visible lines. PAL1/PAL2 run 50 fields per second with 288 visible lines; PAL2 is 384 pixels wide. PAL requires a European BIOS and changes the machine timing, so restart the machine after changing it.
ClioTimers (string): FreeDoCompatible, OperaScheduler.
CelTiming (string): FreeDoCompatible, OperaBusy.
CdromTiming (string): FreeDoCompatible, OperaCycleBased.
CdSpeed (string): Unbounded, X1, X2, X4, X8, X16, X24, X32.
CpuBackend (string): Interpreter, Jit. The JIT is experimental and remains slower than the interpreter on the local boot test; the interpreter is the default.
NvramStorageMode (string): Global, PerGame.
OutputResolution (string): Window, Native, Scale2X, Scale3X, Scale4X, Hd720, FullHd1080, Qhd1440, Uhd2160.
FixModeOverrides values (string flags): None, BitTiming1, BitTiming2, BitTiming3, BitTiming4, BitTiming5, BitTiming6, BitTiming7, GraphicsStepY. Flags may be comma-separated when combined. The Settings dialog edits the raw hexadecimal mask instead.
FilterOverrides values use the same filter names as Filter.
Per-game override keys¶
Game IDs are normalized to the first eight hexadecimal characters, uppercased. A full 32-character MD5 is accepted and truncated. Example:
The lookup is case-insensitive and tolerates a full MD5 key.
Example (abridged)¶
The real file contains six player profiles; this example shows the shape and the player-1 defaults. See section 3 for the full input structure.
{
"SettingsVersion": 4,
"FirstRunCompleted": true,
"BiosPath": "C:\\3DO\\panafz1.bin",
"Bios2Path": "",
"BiosFolder": "C:\\3DO\\bios",
"AutoBios": true,
"BiosOverrides": {
"6B1A7FED": "51F2F43AE2F3508A14D9F56597E2D3CE"
},
"DonationEmail": "",
"HasDonated": false,
"DonationLastCheckedUtc": null,
"DiscPath": "C:\\3DO\\Road Rash (USA).chd",
"RecentDiscs": [
"C:\\3DO\\Road Rash (USA).chd"
],
"SaveDirectory": "C:\\Users\\me\\AppData\\Local\\5DO\\states",
"ScreenshotDirectory": "",
"CheatsDirectory": "",
"SaveSlot": 0,
"SaveSlotCount": 10,
"LibraryFolders": [
"C:\\3DO"
],
"LibraryMetadataPath": "",
"DiscDatPath": "",
"LibraryCardSize": 176,
"AutoGameFixes": true,
"FixModeOverrides": {},
"FilterOverrides": {},
"GameProfiles": {},
"Filter": "SharpBilinear",
"Aspect": "FourThree",
"CustomAspect": 1.3333,
"Vsync": true,
"IntegerScale": true,
"OverscanPixels": 0,
"OverscanLeft": 0,
"OverscanTop": 0,
"OverscanRight": 0,
"OverscanBottom": 0,
"VideoBorderPixels": 0,
"VoidAreaColor": "#FF101010",
"Renderer": "OpenGl",
"OutputResolution": "Window",
"ShowOverlay": false,
"ShowInputDisplay": false,
"OsdEnabled": true,
"OsdPosition": "TopRight",
"OsdOpacity": 0.9,
"OsdDurationMilliseconds": 2200,
"QuickMenuEnabled": true,
"SaveNativeScreenshot": false,
"Bloom": 0.35,
"FsrSharpness": 0.8,
"HighResolution": false,
"Region": "Ntsc",
"AutoRegion": true,
"Volume": 1.0,
"AudioEnabled": true,
"AudioDevice": "",
"AudioBufferMilliseconds": 100,
"InputDeviceOverrides": {},
"AutoInputDevices": true,
"CdAudioVolume": 0.8,
"CdAudioMuted": false,
"AutoSwapOnEject": true,
"RewindEnabled": true,
"RewindSeconds": 60,
"FastForwardMultiplier": 4,
"Input": {
"Players": [
{
"Name": "Player 1",
"Keyboard": {
"Up": "Up",
"Down": "Down",
"Left": "Left",
"Right": "Right",
"Z": "A",
"X": "B",
"C": "C",
"A": "L",
"S": "R",
"Enter": "P",
"Backspace": "X"
},
"Gamepad": {
"South": "A",
"West": "B",
"North": "C",
"LeftShoulder": "L",
"RightShoulder": "R",
"LeftTrigger": "L",
"RightTrigger": "R",
"DpadUp": "Up",
"DpadDown": "Down",
"DpadLeft": "Left",
"DpadRight": "Right",
"LeftStickUp": "Up",
"LeftStickDown": "Down",
"LeftStickLeft": "Left",
"LeftStickRight": "Right",
"Start": "P",
"Select": "X"
}
}
],
"Hotkeys": {
"SaveState": "F5",
"LoadState": "F8",
"Screenshot": "F12",
"Fullscreen": "F11",
"Pause": "Escape",
"Reset": "F10",
"SlotPrevious": "F6",
"SlotNext": "F7",
"FrameAdvance": "F9",
"Rewind": "R",
"FastForward": "Tab"
}
}
}
In a real file Players has six entries. Players 2-6 have no keyboard bindings by default but do have the default gamepad mapping.
BIOS selection¶
BiosFolder is the source of automatic selection. AutoBios defaults to true, but selection only runs when BiosFolder is set; an existing BiosPath-only configuration continues to use that exact BIOS. Selection order is:
BiosOverrides[gameId](MD5), if present and found in the folder.- A known title requirement (Slayer Europe/USA, Powers Kingdom Europe, Arcade CD-ROM).
- Region matching from the game database (
US,JP,EU, and combined strings), including Kanji and patched-image preferences. BiosPath/Bios2Pathas the configured fallback.
bios list/bios scan and the Settings > Paths scan button validate the folder. Per-game overrides can be assigned in Settings > Emulation > BIOS override, with File > Assign BIOS to Current Game..., or in File > BIOS / NVRAM Manager.... The manager also imports validated images and sets BIOS1/BIOS2. Save states already warn when the loaded BIOS hash differs from the state header.
3. Input profile¶
AppSettings.Input is an InputProfile:
Players: array of sixPlayerProfileobjects.Hotkeys: action-name to key-name map.
Each PlayerProfile:
| Property | Type | Meaning |
|---|---|---|
Name | string | Display name, e.g. Player 1. |
Keyboard | object | Key name (Avalonia Key.ToString()) to ControllerButton. |
Gamepad | object | Physical control name to ControllerButton. |
ControllerButton values: None, A, B, C, P, X, L, R, Up, Down, Left, Right.
Gamepad binding names understood by GamepadMapper:
South, East, West, North, LeftShoulder, RightShoulder, LeftTrigger, RightTrigger, DpadUp, DpadDown, DpadLeft, DpadRight, LeftStick, RightStick, LeftStickUp, LeftStickDown, LeftStickLeft, LeftStickRight, RightStickUp, RightStickDown, RightStickLeft, RightStickRight.
Default player-1 keyboard:
| 3DO | Key |
|---|---|
| Up/Down/Left/Right | Arrow keys |
| A | Z |
| B | X |
| C | C |
| L | A |
| R | S |
| P | Enter |
| X | Backspace |
Default gamepad mapping:
| Physical | 3DO |
|---|---|
| South (XInput A / evdev BTN_SOUTH) | A |
| West (XInput X / evdev BTN_WEST) | B |
| North (XInput Y / evdev BTN_NORTH) | C |
| LeftShoulder | L |
| RightShoulder | R |
| LeftTrigger | L (fallback) |
| RightTrigger | R (fallback) |
| D-pad directions | matching D-pad |
| Left stick directions | matching D-pad (fallback) |
| Start | P |
| Select | X |
Explicit stick/trigger bindings win over the fallback. The default radial dead zone is 0.5; the default trigger threshold is 0.5.
Hotkeys: the profile stores default F5 (save), F8 (load), F6/F7 (previous/next slot), F9 (advance one frame while paused), Shift+F9 (rewind one frame), R (rewind one second), Tab (hold to fast-forward), F4 (quick menu), F12 (screenshot), F11 (fullscreen), Escape (pause), and F10 (reset). The shell dispatches these bindings before forwarding a key to the emulated pad; F11 also works from the library, and Escape leaves fullscreen before it reaches the pause action. HotkeyRouter resolves the persisted action names case-insensitively, so a custom key assignment in the profile is honored. Unknown action names and unbound keys are ignored.
The binding editor reports conflicts when one key/control is bound to multiple buttons or one hotkey is bound to multiple actions.
InputProfileStore can load/save a standalone input JSON file, but the desktop shell uses the embedded AppSettings.Input object. There is no separate input.json by default.
3.1 PBUS devices¶
AppSettings.InputDevices stores one device name per PBUS port. Missing, blank, or unknown entries fall back to Joypad, so older settings files keep working. The desktop shell applies the list through AppSettings.ApplyInputDevices; the connected port count only grows to the highest non-joypad port, preserving the historical single-pad packet for default configurations.
Selecting a peripheral switches the packet to the Opera daisy-chain layout. The legacy 16-byte 4DO layout remains active while every port is a joypad. The CLI mirrors the setting with --input-device 1=mouse,3=lightgun and can force either layout with --pbus-format legacy|opera.
4. Per-game fixes and filters¶
Resolution order in the desktop shell:
- Explicit per-game
FixModeOverridesentry. - If
AutoGameFixesis true,GameCompatibility.ForGameId(gameId)(4DO database mapping). FixMode.None.
For the CLI:
--fix-mode 0xMASK.--no-game-fixes.GameCompatibility.ForGameId(gameId).FixMode.None.
Filter resolution:
- Per-game
FilterOverridesentry. - Global
Filter.
GameId is the lowercase MD5 of the first two 2048-byte sectors. The 4DO fix mapping matches the first eight uppercase characters; see Compatibility.md section 5 for the known titles.
GameProfiles stores a per-game snapshot keyed by game ID. GetGameProfile and SetGameProfile normalize the key case-insensitively; ApplyGameProfile(gameId) copies the snapshot into the live settings, and CreateEffectiveForGame(gameId) deep-copies the override maps and returns a machine-creation snapshot without mutating live settings. The snapshot covers every registered machine option (timing, region, memory capacity, clock, random seed, Opera DIPIR/soft reset, CPU backend, fix mask), plus CD-DA, BIOS MD5, video filter, high-resolution mode, six PBUS devices, and NVRAM mode/version. Settings > Emulation edits, saves, deletes, imports, and exports the current game's profile; run/trace --game-profile applies the machine options headlessly. RegionOverrides pins a disc to NTSC/PAL1/PAL2 and wins over the automatic/global region choice. settings validate [path] reports syntax and schema version; settings migrate [path] normalizes a file and rewrites it at the current version.
MachineOptionRegistry is the single source of truth for machine options. It defines the CLI flag, settings property, per-game profile property, default, range, validation, and save-state coverage for every option. settings options prints the generated table, and MachineOptions.md is generated from the same registry. Invalid values throw MachineOptionValidationException with the failing registry key; unknown keys throw UnknownMachineOptionException.
The Settings dialog's Emulation page edits:
AutoGameFixescheckbox.HighResolutioncheckbox (restarts the machine when changed).Regioncombo: NTSC, PAL1, or PAL2. PAL runs at 50 Hz with 288 visible lines and needs a PAL BIOS. Choose PAL/NTSC automatically from the BIOS is enabled by default and switches the running machine between frames when a newly resolved BIOS changes the video standard. Region override pins the current game to NTSC, PAL1, or PAL2 regardless of the automatic choice.- Pointer port and Pointer calibration: choose all pointer devices or a single controller port, then scale and offset the host pointer in native pixels.
- Output device and Buffer latency: select an OpenAL device and a 20-500 ms target; changes recreate only the host audio output.
Profilecombo: Compatible, Accuracy, Performance, or Custom. Selecting a profile fills the timing controls; manually changing one of them savesCustom.ArmTimingcombo: FreeDO-compatible N=4 or ARM60 datasheet N=2 (restarts the machine when changed).ClioTimerscombo: FreeDO-compatible all-timer scan or Opera per-slot scheduler (restarts the machine when changed).CelTimingcombo: FreeDO-compatible synchronous draw or Opera pixel/texel busy timing (restarts the machine when changed).CdromTimingcombo: FreeDO-compatible immediate transfers or Opera cycle-based sector readiness (restarts the machine when changed).CdSpeedcombo: unbounded or 1x-32x for the cycle-based model; 2x is the stock drive speed (restarts the machine when changed).CpuClockMultiplierfield: 0.5..4.0 (restarts the machine when changed).RandomSeedfield: blank for the FreeDO default, or a 32-bit hexadecimal value.OperaDipircheckbox: opt-in CLIO DIPIR latches and XBUS access aborts (restarts the machine).OperaSoftResetcheckbox: opt-in Opera ARM/MADAM/DSP soft-reset path (restarts the machine).SwiHlecheckbox: opt-in Portfolio OS fixed-point math SWI HLE (restarts the machine; per-game profiles can override it).- Current game display and fix-mode override (
0x...hex mask, blank = automatic). - Per-game filter override (
Automaticor an explicit filter).
CpuBackend defaults to Interpreter. Jit is accepted on runtimes with dynamic code support; it falls back to the interpreter for unsupported instructions or when dynamic code is unavailable.
Changing high-resolution mode, ARM timing, the CLIO timer mode, the CEL timing mode, the CD-ROM timing mode, the CD-ROM speed, the ARM clock, the random seed, Opera DIPIR, Opera soft reset, or the CPU backend recreates the machine and reopens the current BIOS/disc; the state is not preserved. Save states record every registered machine option, and loading a state written with another value reports a warning instead of rejecting it.
5. NVRAM¶
NvramStore manages a 32 KB image. The default is the historical shared image at <LocalApplicationData>/5DO/nvram.ram; NvramStorageMode and NvramVersion select the layout:
| Mode | Version | Path |
|---|---|---|
Global | 0 | <root>/nvram.ram (legacy) |
Global | 1-9 | <root>/nvram.<version>.ram |
PerGame | 0-9 | <root>/nvram/per-game/<gameId>.<version>.ram |
<root> is NvramDirectory, or the settings directory when empty. Per-game IDs are the lowercase 4DO game ID (the MD5 of the first two sectors); unsafe characters are replaced with _. Versions are independent images, so switching versions never overwrites another version's data.
- A missing file produces
NvramImage.CreateFresh(), which initializes the volume header and initial directory words. - When a per-game image does not exist yet, loading falls back to the per-game version 0 image, then the shared version, then the legacy
nvram.ram. The next save writes the per-game file, so switching from shared to per-game preserves the existing data once. - The machine writes NVRAM snapshots through
MarkChanged; the host flushes at most once per 250 ms (NvramStore.FlushInterval) and forces a flush on pause/stop/dispose. - Writes use a temporary file plus atomic replace.
- If the primary file is not exactly 32 KB, it is moved to
<name>.badand a fresh image is used. A corrupt primary image does not silently fall back to an older image. - A save state also contains NVRAM; loading a state restores the state's NVRAM and the host later persists it through the normal path.
The CLI supports both explicit and layout-based NVRAM:
--nvram <path>loads that file if it exists and writes it back after the run.--nvram-mode global|per-game,--nvram-version 0-9, and--nvram-dir <path>resolve the same layout as the desktop settings. These options cannot be combined with--nvram.nvram path|list|export|import|resetresolves, lists, backs up, restores, or clears images without running the machine.
File > BIOS / NVRAM Manager... lists the shared and per-game images with validation state and game metadata, and adds per-image backup, import, reset, delete, and a layout-preserving Backup All... action. Reset, delete, and import-overwrite require a second click on the same button.
With --state-in, NVRAM comes from the state; a layout or explicit NVRAM path is still written after the run when supplied.
6. Paths and library behavior¶
| Setting | Behavior |
|---|---|
BiosPath | Primary BIOS fallback; used by About and optional startup auto-open. |
Bios2Path | Optional BIOS2/Kanji font loaded with the primary BIOS. |
BiosFolder | Folder scanned for automatic selection; required for auto BIOS. |
AutoBios | Enables region/known-title selection when BiosFolder is set. |
BiosOverrides | Per-game MD5 pins, assigned in Settings or File > Assign BIOS to Current Game.... |
DiscPath | Last disc; used by optional startup auto-open. |
RecentDiscs | Newest first, deduplicated case-insensitively, capped at 10. |
SaveDirectory | Default .../5DO/states; used by SaveStateSlotManager. |
ScreenshotDirectory | Empty means Pictures; screenshots are named <game>-<yyyyMMdd-HHmmss>-f<frame>.png. |
CoverDirectory | Optional shared folder for cover art named after the disc files. |
CheatsDirectory | Per-game cheat JSON folder; empty means .../5DO/cheats. |
LibraryFolders | Scanned recursively to depth 4 for .iso, .bin, .cue, .chd; edited in Settings > Paths > Game folders or File > Add Game Folder.... |
ShowDuplicateLibraryEntries | When false (default), disc images that share a 3DO game ID are listed once. When true, every image file is listed. |
LibraryMetadataPath | Optional offline metadata overlay; empty means .../5DO/library-metadata.json. |
DiscDatPath | Optional Redump/No-Intro DAT for the library disc-health badge; empty asks on first verification. |
Library entries are sorted by title then path. Cover art is matched by file name: a sibling image with the same base name and an extension of .png, .jpg, .jpeg, or .webp (for example game.png beside game.chd) takes precedence. If no sibling exists, CoverDirectory is searched for <disc base name>.<ext>; the folder is set under Configuration > Settings > Paths > Game covers. Unknown discs use the file name as the title and show Unknown; known discs use the embedded 4DO database metadata. Covers are decoded once per file at a bounded height on background threads and shared by path, so the game list appears before cover art finishes loading and duplicate discs in different library folders reuse the same bitmap.
Discs are listed immediately from the folder enumeration. Cover lookup enumerates each disc and cover directory once and indexes image base names, rather than probing every cover extension for every disc; this keeps cold scans fast with large libraries. Game IDs and sector counts are then computed in the background with bounded parallelism, and the list updates as titles resolve. Results are cached in <LocalApplicationData>/5DO/library-cache.json; later scans reuse the cache for files whose length and last-write time are unchanged. The status bar reports metadata-scan progress.
A disc's game ID is the lowercase MD5 of its first two 2048-byte data sectors (4,096 bytes), the identifier used by 4DO's GameDatabase.xml. It is content-based, so renamed copies of the same disc, or GoodTools/Redump/No-Intro variants of one release, share an ID. By default the library shows one entry per game ID and reports the total image count (for example 653 games · 1,366 images). Enable Settings > Paths > Show duplicate disc images to list every file. When duplicates are collapsed, a readable image with cover art is preferred. Audio-only CD-DA discs with no data track use a stable table-of-contents-derived ID instead.
The Library view supports grid/list modes, search by title/path/game ID/format/ metadata, an icon-size slider, All/Favorites/Played/Unplayed filters, and Title/Recently played/Most played/Release year/Publisher sorts. Double-click or Enter boots the selected disc. Star buttons toggle favorites.
User library data is stored in <LocalApplicationData>/5DO/library-state.json:
{
"Version": 1,
"Games": {
"id:F3AF1B13": {
"Favorite": true,
"PlaytimeSeconds": 4500,
"LastPlayedUtc": "2026-11-01T15:00:00Z",
"LaunchCount": 3
}
}
}
Records are keyed by id:<4DO game ID> when known and path:<full path> for unknown discs. A path-keyed record migrates to the game-ID key when the disc becomes known. Play time is measured only while emulation is running and is flushed every 60 seconds and on pause/stop/close.
The optional <LocalApplicationData>/5DO/library-metadata.json overlay (or the path in LibraryMetadataPath) adds facts without a network provider:
{
"Version": 1,
"Records": [
{
"GameId": "F3AF1B13",
"Path": "",
"Title": "Example Title",
"Developer": "Example Developer",
"Publisher": "Example Publisher",
"ReleaseYear": "1995",
"Genre": "Action",
"Regions": "USA",
"Players": 2,
"Description": "Optional description."
}
]
}
GameId and Path are both optional; the game ID is preferred when both match. Non-empty overlay fields override the 4DO database and file name. The file is read on library refresh and works fully offline.
7. Screenshots and save slots¶
Screenshots:
- Default directory: Pictures.
- Name:
<sanitized game name>-<yyyyMMdd-HHmmss>-f<frames:D6>.png. - With
SaveNativeScreenshot, a second<name>-<stamp>-f<frames:D6>-native.pngis written from the CPU assembler. - The filtered screenshot comes from the OpenGL readback when available; otherwise the CPU frame is used.
Save slots:
SaveSlotCountdefaults to 10 and is clamped to 1..100 on load.- Files:
slot-NN.tdos,slot-NN.json,slot-NN.png(zero-basedNN). - The state header is authoritative for game ID and frame count; the sidecar is metadata only and may be missing.
- Writes are atomic; a failed load does not change the current slot index.
- See
SaveStates.mdfor the format.
8. Audio settings¶
| Setting | Effect |
|---|---|
AudioEnabled | Opens OpenAL Soft at startup. If no device is present, the app logs a warning and runs silently. |
Volume | OpenAL gain, clamped 0..1. |
CdAudioVolume | CD-DA mix level, clamped 0..1. |
CdAudioMuted | Removes CD-DA from the mix while playback continues. |
AutoSwapOnEject | ODE-style automatic advance to the next playlist disc after a guest eject. |
Bloom | CRT bloom only; 0 disables. |
FsrSharpness | FSR RCAS sharpness; 0 soft, 1 maximum. |
The CLI matches the CD-DA controls with run --cd-volume 0..1 and --mute-cd. The CD save-state section records both values; a v3 state loads with the defaults.
The Settings > Audio page also has a Play 440 Hz test tone button. It opens a separate short-lived OpenAL output, plays one second, and reports the OpenAL error if no device is available.
See Audio.md for the full pipeline and diagnostics.
9. Environment variables¶
| Variable | Used by | Meaning |
|---|---|---|
FIVEDO_AUDIO_TAP | OpenAL output (CLI --audio openal/desktop) | Path prefix for <prefix>.wav (exact queued PCM) and <prefix>.csv (per-buffer timing). |
FIVEDO_DATA_DIR | Desktop/CLI | Override the data directory for settings, NVRAM, cheats, library state, and logs. Takes precedence over named profiles. |
FIVEDO_PROFILE | Desktop/CLI | Select <data-directory>/profiles/<name>/ as an isolated named configuration. |
FIVEDO_ALLOW_MULTIPLE | Desktop | Set to 1 to skip the per-instance write lock (automation and test harnesses). |
FIVEDO_PORTABLE | Desktop/CLI | Set to 1 to behave as if portable.flag is next to the executable. |
FIVEDO_LOG_DIR | Desktop/CLI | Override the rolling log directory. |
ALSOFT_DRIVERS | OpenAL Soft | Set to null to use OpenAL's null backend for headless tests. |
FIVEDO_BIOS | Tests | Path to a 1 MB BIOS for real-BIOS tests. |
FIVEDO_FRAME_DUMP | Tests | Directory for boot-frame PNGs. |
FIVEDO_GPU_TESTS | Tests | Set to 1 to run the real WGL/ANGLE probe test. |
FIVEDO_AUDIO_TESTS | Tests | Set to 1 to open a real OpenAL device. |
FIVEDO_VULKAN_TESTS | Tests | Set to 1 to run the opt-in Vulkan renderer and window-probe integration tests. |
FIVEDO_BUG_REPORTS | Desktop/CLI | Set to 0 to disable bug-report submissions. Automated smoke/probe runs disable them automatically. |
FIVEDO_GAMES | tools/release-soak.ps1 | Disc corpus root. |
The CLI does not read any of these except FIVEDO_AUDIO_TAP (through the OpenAL backend) and ALSOFT_DRIVERS (through OpenAL Soft).
10. Precedence summary¶
frontend launch arguments (--disc, --bios, --fullscreen, --gl-backend)
> CLI flags
> per-game BIOS override (MD5)
> known title BIOS requirement
> region-based BIOS selection (when BiosFolder is set)
> configured BiosPath/Bios2Path fallback
> per-game fix/filter overrides (desktop)
> explicit --fix-mode / --no-game-fixes (CLI)
> automatic 4DO database fixes
> global settings
> built-in defaults
For the desktop shell, changes made in Settings are applied when the dialog is accepted; settings.json is written immediately. Changes to high-resolution mode restart the machine. Changes to audio settings recreate the OpenAL output if needed. Changing Renderer recreates the active presenter without restarting emulation. Changes to OutputResolution, filters, aspect, and vsync apply to the current renderer without restarting the machine. DisplayRefreshRate applies immediately: a value above 60 re-presents the latest frame on a timer, and 0 follows the compositor's animation frames. The 3DO only produces 60 fields per second (50 for PAL), so a higher rate lowers presentation latency but does not add motion. Frame-skip changes apply immediately to the running core loop. OSD enable/position/opacity/duration and the quick-menu toggle apply immediately; notification lifetime changes affect new messages.
Performance defaults¶
Fresh settings target 60 fps without lowering image quality:
- OpenGL presentation at match-window output resolution. The emulated frame stays at its native resolution and the GPU performs the final filtered upscale.
- Sharp-bilinear filtering (smooth at non-integer scale factors with far less CPU/GPU cost than xBR/HQx).
- VSync requested and integer scaling enabled.
- Auto frame skip. This is presentation-only and stays off when the core meets its deadline; if the host cannot present every frame, it drops presentation frames instead of slowing the game down.
- High-resolution CEL mode disabled. Use it only for titles validated at 640x480.
If the machine is CPU-bound rather than presentation-bound, choose a faster filter (Nearest), reduce OutputResolution, or run a Release build. Auto frame skip cannot make the emulated CPU, CEL, or DSP faster; it only removes presentation work from the frame budget.
11. Resetting configuration¶
To reset the desktop app to defaults:
- Close the app.
- Back up and delete
settings.json(and optionallynvram.ramandstates/). - Start the app; it creates a fresh settings file and NVRAM image on first save.
Deleting nvram.ram resets the emulated console's saved settings/volume, not the game's save data on the disc. Save states are independent files; deleting settings.json does not delete them.
If the app fails to start because of settings, rename settings.json instead of editing it; malformed JSON is silently replaced with defaults on the next load.