Skip to content

Reduce MiSTer SD-card writes from frontend.toml settings mirror #325

Description

@wizzomafizzo

Summary

A user reports their MiSTer SD card is frequently becoming locked read-only and then requires a Windows disk scan. The scan/corruption report appears to contain many frontend.toml entries.

Initial investigation points to frontend.toml being a hot write path on MiSTer, including a full atomic rewrite on every frontend process start.

Evidence

MiSTer paths:

  • Config lives on SD: /media/fat/zaparoo/frontend.toml
  • State/logs live on RAM/tmpfs:
    • /tmp/zaparoo/state.toml
    • /tmp/zaparoo/frontend.log
    • /tmp/zaparoo/frontend.stderr.log

Startup path:

  • src/ui/app/Main.qml references Browse.Settings during app startup.
  • rust/frontend/src/models/settings.rs initializes Browse.Settings and currently always calls:
    • persist_if_changed(&snapshot, &merged)
    • mirror_settings_to_config(&config_path, &merged)
  • mirror_settings_to_config calls save_settings_mirror.
  • rust/zaparoo-core/src/config.rs rewrites the whole config using write_atomic:
    • create sibling temp file (frontend.toml.tmp.<pid>.<thread>)
    • write serialized TOML
    • sync_all()
    • rename temp file over frontend.toml

Other SD-backed writes found:

  • /media/fat/zaparoo/frontend.toml
    • every frontend startup via Settings initialization
    • every Settings change
    • hide/unhide category/system
    • first-run commercial notice ack
    • CRT video standard or offset commit
  • /media/fat/config/zaparoo_launcher_crt.bin
    • only when toggling CRT mode

Why this could explain the report

frontend.toml is rewritten even when config content is unchanged. On MiSTer this means repeated FAT SD-card create/write/sync/rename cycles. If the launcher is killed, rebooted, or loses power around those operations, FAT can leave orphan clusters or directory-entry inconsistencies. That matches the user's report that scandisk points at frontend.toml-related entries.

Proposed fix

Reduce SD writes, especially no-op startup writes:

  1. In config save helpers, compare the mutated TOML table with the original parsed table and return early if unchanged.
    • save_settings_mirror
    • save_hidden_browse_prefs
    • save_notice_ack
  2. Consider making Settings::initialize avoid mirror_settings_to_config unless normalization/migration actually changes the durable config.
  3. Avoid hidden browse preference writes when hide/unhide does not change the list.
  4. Optional: after rename, sync the parent directory where supported. This improves durability but does not solve write frequency by itself.

Acceptance criteria

  • Normal frontend startup with already-normalized config performs no write to /media/fat/zaparoo/frontend.toml.
  • Settings changes still persist correctly.
  • Hide/unhide only writes when list content changes.
  • Tests cover no-op saves preserving file metadata/content where practical.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions