Saltar al contenido
← Volver a proyectos

Romm

ROMM Collection Manager

#R0MM ver 0.30rc

PySide6 Desktop ROM Organization System


#Recent Changes (2026-03-02)

  • Fixed a PySide6 Tools tab crash when clicking "Refresh" in Collections/DATs (missing AppState refresh aliases).
  • Fixed torrent search button stuck state and invokeMethod warnings in PySide6 Downloads tab.
  • PySide6 startup now restores lightweight UI state immediately, but only restores heavy scan results/DAT session data when a saved snapshot exists and the user explicitly accepts the restore prompt.
  • Restored a working torrent searcher in the Downloads tab with selectable Apibay/custom mirrors; magnets are sent to the JD queue.
  • Downloads tab split into Torrent (search + magnets) and Direct/JD (Myrient catalog + JDownloader queue) sub-tabs.
  • Downloads tab layout is now responsive for non-maximized windows: Torrent uses a compact control grid, Direct/JD uses a horizontal-or-vertical splitter, and the selected sub-tab plus staged inputs persist in UI state.
  • Dashboard is now always the initial view on startup and was refocused into a real home screen: quick start, next actions, session snapshot, and transfer status, without the old news-feed dependency.
  • Windows path display in PySide6 was normalized visually to backslashes in Import & Scan Operation Preview and related elided labels/tooltips, so D:/... now renders as D:\....
  • Temporary local runtime artifacts under .tmp/ are now ignored by Git so repository snapshots stay clean.
  • The built-in metadata scraper was removed from the active PySide6 flow. Collection now prepares local Skraper manifests instead of fetching metadata remotely, and Local DAT is back to local-only suggestions.
  • PySide6 navigation was re-split: Import & Scan is now Rom Manager and contains the scan/organize setup plus a transient Scan Results sub-tab that only appears after a scan in the current session. The top-level Collection view is now a system-grouped library browser for identified games, with per-game metadata/art refresh driven by the configured scraper source and a persistent metadata cache in data/metadata_cache.json.
  • Rom Manager now treats scan state as a manual snapshot workflow: the current session can be saved/loaded explicitly from the UI, while automatic per-change session writes were removed to avoid large JSON stalls.
  • Scan progress now does a fast pre-count pass before hashing, so the Nerve Center can show the real planned workload first and the active progress bar no longer sits at 100% during file discovery.
  • Large PySide6 table refreshes were trimmed by disabling hot-path per-row insert churn (setRowCount(...) + sorting pause) and by pushing DAT activation/removal onto the existing background DAT worker queue instead of blocking the UI thread.
  • Rom Manager left-side setup controls now live inside a discreet vertical scroll area for smaller/non-maximized windows, preventing the Organization Strategies block from being clipped. The strategy checkboxes also gained a tiny height bump so labels no longer visually eat into each other.
  • Collection now uses an explicit Skraper bridge flow instead of an internal scraper: the main action understands selection context and exports the selected game, multiple selected games, or the currently focused system into a Skraper-ready manifest under the configured export folder. The detail pane still shows any already-cached local metadata/art, but the app no longer performs remote metadata fetches itself.
  • PySide6 startup is now always clean: there is no restore-session prompt anymore, no automatic snapshot load on boot, and no auto-restore of old working form state. The app opens directly on Dashboard with only lightweight window geometry/language restored; loading prior scan/DAT state is manual via Rom Manager > Load Snapshot.
  • New Session now clears only the in-memory working session and keeps the saved snapshot on disk, so Save Session / Load Snapshot remains a simple manual workflow instead of destroying the last saved state.
  • The old ScreenScraper/TheGamesDB credential flow is no longer part of the active UI. It was replaced by a lightweight Skraper Setup modal with only two fields: optional local Skraper.exe path and the export folder used for generated manifests/title lists. Open Skraper now launches the configured executable when present, or falls back to the Skraper website.
  • PySide6 session controls were moved out of Rom Manager and into the Dashboard header. The old top-right dashboard shortcut buttons were removed, and Load Snapshot, Save Session, and New Session now live in that top-right slot instead.
  • Non-PySide6 frontends and leftover Flutter scaffolding were archived under _OLD/ so the active release tree now focuses on the native PySide6 desktop build only.
  • Older build/ and dist/ artifacts plus refactor helper scripts were archived under _OLD/, and the active r0mm_pyside6.spec now excludes Tk/legacy frontend modules so the rebuilt dist/R0MM/R0MM.exe is slimmer and PySide6-only.
  • Frozen PySide6 builds no longer bundle/copy the repository data/ tree into dist/R0MM/data/ on first launch. The packaged app now creates only the empty runtime folder skeleton (dats, collections, imports, etc.) and generates defaults at runtime, so no developer DATs, collections, snapshots, or session residue leak into a fresh .exe.
  • The Nerve Center label previously shown as Saude do Banco was renamed to Taxa de Identificacao to match what it actually measures: identified files as a percentage of current session results.
  • The special DAT R0MM - Local Overrides is now pinned to the top of the active DAT list and rendered with a subtle in-theme highlight so the user's manual-match overlay is always easy to spot.

#Desktop launch modes

You can start the active desktop interface directly:

  • python main.py
  • python main.py --pyside6
  • python -m rommanager (opens PySide6 directly)

PySide6 UI files:

  • rommanager/gui_pyside6_views.py
  • rommanager/gui_pyside6_style.qss

Windows build:

  • A dedicated PySide6 build entrypoint is available at r0mm_pyside6_entry.py.
  • PyInstaller spec file: r0mm_pyside6.spec.
  • The packaged app now treats data/ as portable beside the frozen .exe. On first launch, bundled defaults from the PyInstaller runtime bundle are copied into dist/R0MM/data/, which then remains writable and persistent.
  • Use the final packaged executable at dist/R0MM/R0MM.exe. Do not launch the intermediate PyInstaller executable from build/; that stub is not a distributable app and can fail with missing DLL paths.

Backup options:

  • Full backup to backups/ (zip, timestamped).
  • Incremental-friendly backup that excludes build/, .dart_tool/, .venv/, and backups/.
  • Script: backups/backup.ps1 (run with powershell -ExecutionPolicy Bypass -File backups/backup.ps1).

#Local Agent Access & Autonomy (Developer Sessions)

This project is frequently edited with a local coding agent. What the agent can test is determined by the session runtime (sandbox, GUI support, approvals), not only by repository code.

What the agent can usually do in a standard local session:

  • Read and edit files inside the invoked project folder.
  • Run shell commands and project scripts (subject to sandbox/approval policy).
  • Run headless/smoke checks (imports, py_compile, CLI commands, QT_QPA_PLATFORM=offscreen tests).
  • Analyze terminal tracebacks and runtime logs.

What may still be limited even with full repository access:

  • Interactive desktop GUI validation (PySide6/Flet) if the session does not provide GUI control/desktop streaming.
  • Visual click-through testing unless the session supports screenshots + input events or remote desktop control.
  • Installing dependencies or fetching online resources if network access is disabled.

To maximize agent autonomy in a trusted local session:

  • Use a session mode with unrestricted filesystem access (or equivalent full access) for the project workspace.
  • Enable network access when installs/updates/docs lookup are required.
  • Allow command execution without repeated prompts, or approve persistent command prefixes used in this repo.
  • Prefer the project virtual environment Python (.venv\\Scripts\\python.exe) for all validation commands.

Recommended recurring command approvals/prefixes (if your session supports them):

  • git
  • .venv\\Scripts\\python.exe
  • py
  • pytest
  • flutter

PySide6/Flet validation notes:

  • The agent can launch the process and capture terminal output/crashes.
  • The agent can perform headless smoke tests where supported.
  • Full visual verification still requires a GUI-capable session or user-provided screenshots/logs.

Runtime/tool prerequisites for deeper testing:

  • Python dependencies installed (PySide6, flet, flask, etc.).
  • External tool binaries available in PATH when testing Tools features (for example chdman, dolphin-tool).
  • Small DAT/ROM fixtures for reproducible import/scan tests.

Practical workflow when GUI control is unavailable:

  • Let the agent patch code and run headless checks.
  • Run the desktop app locally and share traceback/log/screenshot output.
  • The agent uses the observed runtime error to apply the next fix quickly.

#1. Overview

R0MM ver 0.30rc is a web application for scanning, identifying, analyzing, and organizing ROM collections using DAT files (XML/Logiqx and clrmamepro text DAT).

It supports:

  • No-Intro
  • Redump
  • TOSEC
  • XML-based DAT format (Logiqx-compatible)
  • Plain text DAT format (clrmamepro style)

The system consists of:

  • A Flask backend
  • A React-based frontend
  • ROM scanning + CRC32 hashing
  • DAT parsing and matching engine
  • Organization strategies with preview and undo
  • Collection completeness analysis

The application runs locally and exposes a web interface.


#2. Architecture

#Backend: Flask Application

Core modules identified in the project:

  • models – data structures
  • parser – DAT parsing (XML + clrmamepro text)
  • scanner – filesystem ROM scanning + hashing
  • matcher – ROM ↔ DAT matching logic
  • utils – helpers
  • shared_config – configuration layer
  • router – API endpoints
  • config – runtime config
  • run_server() – server bootstrap

The server starts on:

127.0.0.1

Default Flask configuration uses:

  • host
  • port
  • debug
  • threaded

The backend exposes API endpoints consumed by the frontend.


#Frontend: React Interface

Single-page interface rendered into #root.

Main sections:

  1. Identified ROMs
  2. Unidentified Files
  3. Missing ROMs
  4. Organization Controls

UI is styled using Tailwind-like utility classes.


#3. Core Functionalities

#3.1 DAT Loading

  • Accepts XML DAT and clrmamepro text DAT files

  • Parses games and ROM entries

  • Extracts metadata:

    • Game name
    • ROM name
    • System
    • Region
    • Size
    • CRC32

#3.2 ROM Scanning

Scans selected folder and computes:

  • File size
  • CRC32 hash
  • Filename
  • Path

Files are matched against loaded DAT entries.


#3.3 Matching Results

Results are separated into three logical groups:

#Identified

ROMs successfully matched against DAT:

Columns shown:

  • Original file
  • ROM name
  • Game
  • System
  • Region
  • Size
  • CRC32
  • Status

#Unidentified

Files scanned but not matched:

Columns:

  • Filename
  • Path
  • Size
  • CRC32

Selectable for further action.


#Missing

DAT entries not found in collection.

Includes completeness stats:

  • Total in DAT
  • Found count
  • Percentage complete
  • Visual progress bar

#4. Organization Engine

User-selectable organization strategies:

Strategy ID Description
system Per-system folders
1g1r 1 Game 1 ROM (best version selection)
region Region-based folders
alphabetical A-Z folders
emulationstation ES / RetroPie layout
flat Rename only (no subfolders)

Note: Organization output paths are sanitized for Windows-safe filenames (invalid characters like : or ? are replaced). Preview mirrors the sanitized destination paths.

#Actions

Two file operations supported:

  • Copy
  • Move

#Workflow

  1. Load DAT

  2. Scan ROM folder

  3. Review identified / unidentified / missing

  4. Select strategy

  5. Set output folder

  6. Choose Copy or Move

  7. Click:

    • Preview (dry run)
    • Organize! (execute)
  8. Optional: Undo


#5. Organization Controls

UI includes:

  • Output folder field
  • Strategy selector
  • Action selector (Copy / Move)
  • Preview button
  • Organize button
  • Undo button

Preview prevents accidental destructive operations.

Undo reverses last organization action.

#5.1 Tools UI (PySide6)

Tools actions are wired to core service methods. Some advanced tools currently return a “not implemented” response until the core implementations are completed.

Core tool contracts (stubs with type hints + docstrings):

  • DAT Diff (Compare)
  • DAT Merger
  • Batch Convert (CHD/RVZ)
  • Apply TorrentZip
  • Deep Clean (Remove Junk)
  • Find Duplicates (By Hash)

Tool implementations:

  • DAT diff/merge implemented in Python.
  • Batch convert requires external binaries in PATH: chdman (CHD) and dolphin-tool (RVZ).
  • TorrentZip uses a deterministic ZIP repack (no external dependency).

#6. Completeness Tracking

For loaded DAT:

  • Total entries in DAT
  • Matched entries
  • Percentage calculation
  • Visual progress bar

This allows tracking full-set completion.


#7. Web Server Execution

Entry function:

run_server()

Prints:

The app runs as a local web service.


#8. Intended Use Case

Designed for users who:

  • Maintain multi-system ROM collections
  • Use curated DAT sets
  • Want structured organization
  • Want completeness visibility
  • Need deterministic matching (CRC-based)

#9. Key Technical Characteristics

  • DAT parsing (XML + clrmamepro text)
  • CRC32 matching
  • Browser-based UI
  • Flask REST backend
  • Modular architecture
  • Strategy-based file output
  • Undo capability
  • Preview safety layer

#10. Version Identifier

Displayed in footer:

R0MM ver 0.30rc

Indicates this is a second-generation web-based rewrite, likely replacing a previous CLI or desktop version.


#11. Summary

R0MM ver 0.30rc is a local web application that:

  • Parses DAT files
  • Scans ROM collections
  • Matches via CRC32
  • Displays identified, unidentified, and missing ROMs
  • Calculates completeness
  • Organizes ROMs using selectable strategies
  • Supports preview and undo
  • Runs via Flask on localhost

It is a full-stack ROM management tool intended for structured archival organization.


#12. Language Selection

The app now includes a language selector in desktop menus:

  • English (default)
  • Português Brasileiro

Where to change:

  • Launcher window: Language menu
  • Tkinter desktop app: Language menu
  • Flet desktop app: language dropdown in the left navigation panel
  • PySide6 desktop app: language dropdown in the status bar

Default language at startup is English.

Language switching refreshes labels in the PySide6 Import/Scan view (including section titles) and the drawer feedback.

Module entry behavior:

  • python -m rommanager now opens the PySide6 desktop app directly.

#13. BlindMatch mode

BlindMatch allows scanning without any DAT file.

How it works (best effort):

  • User provides the system name (for example: SNES).
  • The app infers region from filename tokens such as (U), US, (E), (J), BR, etc.
  • All scanned files are treated as identified in this mode.
  • There are no "missing ROMs" and no "unidentified" results in BlindMatch mode.

Available in:

  • CLI: --blindmatch-system <SYSTEM>
  • PySide6 UI: BlindMatch toggle + system input

#15. Advanced Settings foundation

R0MM now includes a shared settings foundation (~/.rommanager/settings.json) used by CLI and PySide6 runtime initialization.

Implemented foundations:

  • Collection profiles by objective: historical_preservation, mister_playset, retroarch_frontend, full_set_no_hacks.
  • Region/variant policy (global + per-system priority).
  • Naming template engine for organized output ({name}, {game}, {region}, {system}, {crc}).
  • Optional curated metadata database support (CLI: --metadata-db).
  • Audit trail logging for organization actions (~/.rommanager/logs/audit.log).
  • Collection health checks (duplicates, unknown extension, missing/zero files) via CLI --health-check.
  • Museum organization strategy (museum) for generation/system/region hierarchy.
  • Accessibility settings placeholders (font scale, high contrast, dense tables, reduced motion).

CLI additions:

  • --settings-file <path>
  • --profile <preset_name>
  • --health-check
  • --metadata-db <path>

#16. Archived Frontends

The Flet/Web/Tkinter frontends are no longer part of the active release tree. They were archived under:

  • _OLD/docs/FLET_AGENT_PROTOCOL.md
  • _OLD/rommanager/gui_flet.py
  • _OLD/rommanager/web.py
  • _OLD/rommanager/gui.py

The active release target is PySide6 only.


#UI Notes (PySide6)

  • Cyberpunk Industrial theme: base #1E1E1E, surface #2D2D2D, accents #39FF14, alerts #FF00FF.

  • Library drawer is persistent; empty state remains visible when no row is selected.

  • Drawer alert border toggles for Unidentified/Missing selections.

  • Nerve Center now displays a live log monitor that tails the runtime log file in real time (tab changes, scans, and errors are logged).

  • Nerve Center includes a GhostTyper easter egg (retro quotes typing animation) above the live log monitor.

  • PySide6 no longer silences terminal output; startup/runtime exceptions and Qt warnings/errors are printed to stderr, while runtime logs remain mirrored in the Nerve Center log monitor.

  • Fixed PySide6 startup crash in Nerve Center by initializing ghost_label before binding GhostTyper.

  • Nerve Center refactored into 3 aligned columns (Hardware, Active Operation, Live Console) and now embeds the GhostTyper prompt line inside the terminal frame.

  • Dashboard tab no longer duplicates system monitors; global runtime telemetry lives only in the Nerve Center footer.

  • Active Operation column now includes path elision (fixed-width middle truncation), session speed/anomaly telemetry, and an emergency [ ABORT ] kill switch for long scans.

  • Proactive path overflow guards were added to PySide6 labels that display file paths (Library drawer details and organize progress subtitle).

  • Nerve Center columns are now encapsulated as symmetrical module frames (shared #090909 chassis + border) to remove the floating-text/gridline mismatch and unify visual weight.

  • Nerve Center sizing is now constrained (Hardware 220px, Operation 300px fixed; Terminal expands), and PySide6 main window enforces setMinimumSize(1280, 720) to preserve GhostTyper/terminal readability.

  • Nerve Center event stream now uses semantic log colors by prefix: [*] green (normal/navigation), [?] magenta (user interaction/dialog waits), [!] red (critical/error).

  • PySide6 Dashboard was rebuilt as a 4-card Command Center (DAT Syndicate, Bounty Board, Storage Heatmap, The Wire) with industrial telemetry cards (CardPanel depth #1A1A1A, square borders, green/magenta badges).

  • Dashboard data now loads asynchronously via AppState.refresh_dashboard_intel() using real CoreService intel providers (local DAT age checks, missing-ROM bounty stats, filesystem storage telemetry from saved collections/current session, and live RSS parsing with offline fallback).

  • PySide6 Dashboard Bounty Board now uses real QProgressBar telemetry bars (no ASCII bars), DAT statuses render as semantic badges, and The Wire feed blends into the card with a transparent terminal surface.

  • PySide6 typography was tightened for telemetry readability: global UI font is now Sans-Serif, while JetBrains Mono is reserved for data surfaces (tables, logs, paths, hashes, dashboard telemetry values).

  • PySide6 GUI now applies localized tooltips across main navigation, Dashboard, Library, Import & Scan, and Tools panels (including heavy-operation controls), with tooltip text refreshed on language change.

  • PySide6 i18n audit fixed missing keys that were leaking raw placeholders in Import & Scan (DAT add, scan, scan archives, BlindMatch placeholder/help, folder selection titles); visible dialog filter labels now reuse localized UI strings.

  • Nerve Center click logging no longer duplicates lines: global click events are now written once via monitor_action(...) and displayed only through the runtime-log tail (the direct console append path for clicks was removed).

  • Tools tab no longer contains its own "Live Console"; tool results/logs are now centralized in the Nerve Center monitor only.

  • Tab changes (main sidebar, Library tabs, Tools tabs) now emit directly through state.log_message, guaranteeing they appear in the Nerve Center even if the runtime-log tail misses generic click events.

  • Policy exception added for a user-authorized, rate-limited MyrientFetcher integration (strict max 4 concurrent connections, graceful halt support).

  • Nerve Center Active Operation column now supports a "Hydra Queue" (up to 4 dynamic Myrient transfer lines) with [ HALT TRAFFIC ] control, wired to AppState.download_progress and halt_traffic().

  • ToolsView now includes a dedicated Downloads tab for Myrient/Hydra workflows (output folder + URL list parser with optional URL | custom-filename, queue action, local status list, and halt button).

  • Downloads tab now includes guided line creation (Add URL...) and a Myrient listing-based link resolver (Base URL + Resolve Missing -> Queue) that can match Missing ROM rows against a Myrient directory index and auto-send matches to the Hydra Queue.

  • Add URL... now opens a dedicated Myrient directory browser modal (async listing load, folder navigation, filter, multi-select) and appends selected file links into the Downloads queue input.

  • Downloads tab now also includes an inline Myrient Catalog panel that splits a loaded listing into Systems (directories) and DAT files, lets the user browse a selected system directory, and sends selected files directly to the Hydra Queue.

  • Myrient catalog no longer depends on manual base URL entry: the app now ships with built-in Myrient root presets and auto-detects/auto-loads a working catalog root when the Myrient Catalog drawer is opened (manual base URL remains as an advanced override).

  • The Myrient Catalog is hidden by default inside a drawer (toggle-open on demand); root loads auto-select the first system and auto-load its entries. Myrient listing parsing was hardened (anchors with/without quotes and directory detection via link text).

  • Fixed false "Another operation is already running" conflicts in the downloader: Myrient directory listing / link-resolution now run on a dedicated Myrient worker queue (separate from the generic Tools worker), so root->system autoload chaining and downloader actions no longer trip the generic busy guard.

  • LibraryView (Missing tab) now exposes a Get Links action that sends selected (or optionally all visible) missing rows to Tools > Downloads, where they can be resolved/queued for Myrient download.

  • Heartbeat polling disabled; status updates are event-driven.

  • GhostTyper now includes a blinking cursor animation.

  • GhostTyper cursor uses a thin glyph for a lighter blink.

  • Nerve Center log monitor is per-session only (starts at end of log file on launch).

  • Nerve Center height fixed across views; GhostTyper line and log monitor share a seamless surface (no separator).

  • Nerve Center monitor and GhostTyper line share the same dark gray surface to avoid visual separation.

  • Nerve Center log monitor now records all user clicks via a global event filter.

  • Nerve Center height reduced by ~30% and click events mirror instantly into the on-screen monitor.

  • GhostTyper label now uses explicit JetBrains Mono styling with solid #39FF14 and transparent background.

  • GhostTyper moved under Database Health; Nerve Center log monitor now matches the app background.

  • Myrient downloader throughput tuned: progress updates are now throttled (reducing PySide6 UI/event-loop spam), download chunks increased to 1 MiB, and fresh downloads skip the preflight HEAD request (HEAD is still used for resume/size checks).

  • HALT TRAFFIC no longer leaves the downloader permanently latched off; a new batch clears the halt flag automatically after active jobs drain.

  • Myrient downloader backend was reworked to use local rclone.exe (copyurl) instead of the Python HTTP transfer loop. Hydra Queue and the Downloads tab remain the same UX, but transfers now run through rclone with the same 4-slot queue limit and a single-stream-per-file profile (--multi-thread-streams 1) to respect Myrient guidance.

  • The PySide6 downloader still drives live Hydra Queue / Downloads status rows, but progress/speed are now inferred from local file growth while rclone runs (avoiding stdout progress parsing stalls).

  • PySide6 now persists UI state into data/settings.json (ui_state.pyside6) with autosave + flush on close: main window geometry/view/language/search, Library tab + splitter, Import & Scan form inputs/toggles, and Tools fields (including Downloads URLs/base URL/output folder/catalog drawer + tabs). The app restores these values on next launch.

  • Myrient/rclone downloads now write explicit per-file runtime log lines (start, done, halted, error) via monitor_action, so the Nerve Center and data/logs/runtime-YYYY-MM-DD.log capture the real failure reason instead of only generic ERROR statuses.

  • On Myrient fN.erista.me connection/timeout failures, the rclone downloader now retries automatically once against myrient.erista.me (same path) before surfacing an error. The Downloads list also shows a shortened error reason inline and keeps the full rclone error text in the item tooltip.

  • Myrient/rclone transport now normalizes queued/catalog URLs to the canonical myrient.erista.me host before download (avoiding brittle direct fN.erista.me links), uses --multi-thread-streams 0 to respect the FAQ guidance (one connection/chunk), and enables rclone copyurl compatibility flags (--disable-http2, --bind 0.0.0.0, --user-agent curl) with short retries/timeouts so failures surface quickly in the UI/logs.

  • Myrient transfers now prefer the FAQ-aligned rclone HTTP remote path (copyto --http-url ... :http:...) instead of copyurl for Myrient file downloads. This keeps R0MM on the supported rclone HTTP-remote workflow while preserving exact destination filenames and the same Hydra Queue UX.

  • When rclone reports a Myrient CDN timeout on a redirected host (for example f3.erista.me), R0MM now parses the failing URL from the rclone error line and performs limited automatic CDN host hopping (fN -> fM, same path) before surfacing the error. This mitigates route-specific failures where one Myrient file server is unreachable but others are fine.

  • After runtime logs showed every Myrient timeout failing on dial tcp4 ... even across CDN host hops, the rclone compatibility profile stopped forcing --bind 0.0.0.0 (IPv4-only source bind). R0MM now leaves source-address selection to the OS so Windows can use the best available route/protocol (including IPv6 where available).

  • If Myrient downloads still fail after rclone retries/CDN host-hop attempts, R0MM can hand off to the Windows native HTTP stack (PowerShell Invoke-WebRequest) as a secondary transport fallback. This fallback is now opt-in via environment variable R0MM_ENABLE_PS_IWR_FALLBACK=1 so default downloader behavior remains fully rclone-based for better throughput.

  • The Downloads tab now runs in JDownloader-only mode (local Flashgot/Extern API at 127.0.0.1:9666). The Hydra/rclone download actions were removed from the UI; queue submission is now only through [ SEND TO JDOWNLOADER ].

  • The Downloads tab now includes [ DOWNLOAD JDOWNLOADER ], which opens the official JDownloader download page in the default browser for quick setup on fresh machines.

  • The Myrient directory browser was restored in Add URL... so links can be picked directly from Myrient listings and appended to the JDownloader queue input.

  • JDownloader enqueue now probes local endpoint variants (127.0.0.1 / localhost) and returns actionable diagnostics when unreachable (instead of only raw socket refusal), including an explicit hint to enable/check Extern/FlashGot on :9666.

  • Endpoint error diagnostics now include bootstrap launch context (mode/PID) when R0MM successfully invoked JDownloader but :9666/flashgot did not answer.

  • Tools > Downloads now exposes a GUI runtime panel for JDownloader (endpoint override, explicit JDownloader2.exe path override, bootstrap mode, bootstrap timeout, throughput-tuning toggle, and tuning profile). These settings are persisted in PySide6 UI state and applied per-queue submission without requiring CLI/env configuration.

  • The queue path now includes automatic local API self-heal on endpoint failures: R0MM updates JDownloader RemoteAPIConfig (Extern enabled + localhost-only + deprecated API enabled), retries bootstrap, and automatically retries queue handoff once before surfacing an error.

  • Tools > Downloads includes [ Repair JD API ] to trigger the same self-heal manually from GUI.

  • Local endpoint probing now also includes IPv6 localhost ([::1]) alongside 127.0.0.1/localhost to avoid false negatives on systems where JDownloader binds only IPv6 loopback.

  • API repair can now force a controlled JDownloader restart when config changes require restart before :9666/flashgot becomes reachable.

  • During repair, R0MM forces a GUI bootstrap attempt to surface any JDownloader permission prompts that cannot be accepted in headless mode.

  • If the local JDownloader endpoint is down, R0MM now attempts automatic local bootstrap: it tries to locate JDownloader2.exe using R0MM_JDOWNLOADER_BIN, PATH, Windows uninstall registry entries, and common install folders, then starts it in background before retrying queue handoff.

  • Bootstrap binary resolution now rejects non-executable registry artifacts (for example .ico DisplayIcon values) and only accepts trusted launcher names (JDownloader2.exe/JDownloader.exe), preventing WinError 193 on auto-start.

  • Bootstrap mode is configurable via R0MM_JDOWNLOADER_BOOT_MODE: gui (default, launches JDownloader executable directly), auto (tries headless first and, if :9666 does not come up in time, terminates the spawned headless process and retries with GUI), or silent/headless (no GUI fallback).

  • Windows launch visibility fix: hidden-window startup flags are applied only to headless/silent launches. GUI launches are no longer hidden.

  • Bootstrap wait timeout is configurable with R0MM_JDOWNLOADER_BOOT_TIMEOUT (seconds, clamped to 6..180, default 30). This controls how long R0MM waits for 127.0.0.1:9666 before switching/failing.

  • In auto, the first headless readiness window is intentionally short (6..12s) to avoid long stalls before GUI fallback.

  • AppState now monitors JDownloader handoff targets by polling destination files (.part/final) and emits live download_progress updates (QUEUED/DOWNLOADING/DONE + inferred speed and percent when size hints are available), so Nerve Center and Tools status rows reflect ongoing JDownloader transfers.

  • R0MM now applies an optional JDownloader throughput tuning profile before enqueue (R0MM_JDOWNLOADER_TUNE=1, default on). Default balanced profile sets maxsimultanedownloads=4, maxsimultanedownloadsperhost=4, maxdownloadsperhostenabled=true, maxchunksperfile=4, and disables JD speed limiter. Profile can be changed with R0MM_JDOWNLOADER_TUNE_PROFILE=conservative|balanced|aggressive.

  • Nerve Center Hydra Queue now recognizes JDownloader handoff rows as terminal ADDED states ([JD ] ... LINKGRABBER), and rotates/prunes them like other completed statuses to prevent row buildup during large batch submissions.

  • JDownloader queue submission now runs asynchronously in PySide6 (QThread) and emits handoff phase progress events (prepare/bootstrap/collect/enqueue/repair/retry/done/error) so the UI remains responsive during bootstrap/endpoint waits.

  • Nerve Center Operation module now shows a dedicated handoff progress bar/status line while JDownloader queue submission is in progress; this prevents the app from looking frozen during long bootstrap checks.

  • Tools > Downloads now defaults the Myrient base URL to https://myrient.erista.me/files (also used as fallback when restored UI state has an empty base URL).

  • Tools > DAT Operations now replaces "DAT Sources" with a dedicated DAT Downloader panel. The app fetches DAT catalogs for No-Intro, Redump, and TOSEC (libretro mirrors), allows multi-select download, recognizes DAT family, and can auto-import downloaded files into the local DAT Library.

  • DAT Downloader now supports one-step quick download by name or URL: user types the desired DAT (for example Nintendo - SNES) and clicks Download by Name/URL; R0MM resolves best match in the selected family and downloads/imports automatically.

  • DAT Downloader tasks now run on a dedicated async queue (separate from generic Tools workers), removing false "Outra operação já está em andamento" conflicts in quick-search/refresh flows and reducing wait time with cached + parallel family catalog fetches.

  • Imported DATs are now automatically loaded into the active matcher in PySide6 flows (manual import path and downloader auto-import), so the app uses them immediately without requiring a second manual load step.

  • Import & Scan no longer performs DAT import/deletion; it is now focused on selecting which DATs are ON/OFF for the next scan.

  • Sidebar naming update (PySide6): Library is now Collection / Coleção in the main left navigation.

  • DAT flow split (PySide6): Import & Scan now only toggles DATs ON/OFF for the next scan; all DAT management (import file/folder, enable/disable, delete with confirmation, open DAT download folder) is centralized in Tools > DAT Operations.

  • DAT library discovery now includes all DAT-like files recursively under the app DAT folder (data/dats and subfolders), so dropped files appear automatically in the DAT Library list.

  • DAT toggle UX now supports all three interaction paths (button, context menu, and double-click) and marks invalid entries as [ERR] with clear feedback when enabling is blocked by parse errors.

  • DAT parser now supports clrmamepro plain-text DAT files (including downloader output like Genesis/No-Intro sets). DAT library refresh also revalidates previously invalid entries, so old [ERR] rows recover automatically after parser updates.

  • DAT import/downloader no longer creates duplicate library rows when the source DAT is already inside data/dats (for example _downloads); and PySide6 DAT lists now collapse duplicate identities so [OFF] clones are hidden while an equivalent [ON] entry exists.

  • Nerve Center now shows explicit scan activity in the Operation module: an immediate "starting scan" indicator plus a live progress bar/counter (current/total) during scanning, so long scans no longer look idle/frozen before first results.

  • Nerve Center scan indicator was visually realigned to the terminal aesthetic: scan progress now renders as a mono ASCII bar line (same style family as Disk/DB/Hydra) while preserving the same scan-state behavior (starting + live current/total updates).

  • Nerve Center scan telemetry now exposes scan phases explicitly: Scanning (file hashing) and Comparing (DAT matching), with a dedicated compared-files counter (Compared X/Y) so long multi-DAT scans no longer look stalled after hashing ends.

  • Scan startup latency was reduced for large folders: file discovery now streams directly into hashing/matching (no full pre-list pass), so progress leaves "Starting scan..." almost immediately instead of waiting for a complete recursive file list.

  • Multi-DAT matching path was optimized for large mixed-system scans: MultiROMMatcher now keeps merged global hash indexes (CRC+size / MD5 / SHA1) for O(1) lookup across loaded DATs instead of iterating matcher-by-matcher per file.

  • Scanner now skips obvious non-ROM/document/media/source extensions by default while preserving compatibility for known ROM extensions, ZIP archives, and extensionless files; this reduces wasted hashing work in mixed folders.

  • PySide6 now updates Library results incrementally during the Comparing phase (without waiting for scan completion), so identified/unidentified tables populate live as files are matched.

  • A local recursive scan fixture folder TESTE/ is included in the workspace for smoke tests with mixed content (multi-system ROM-like files, archives, and non-ROM files).

  • Collection > Unidentified agora tem Add to DAT (_EDIT_): escolhe o DAT ativo, edita todos os campos (jogo/ROM/sistema/região/CRC/MD5/SHA1/tamanho/status) e grava num DAT derivado com prefixo _EDIT_ ao lado do original (auto-import + auto-load + rematch).

  • Editor _EDIT_ inclui assistência de metadados: sugestões a partir dos DATs carregados (fuzzy) e dicas online (Wikipedia OpenSearch; falha tratada quando offline), sempre com escolha explícita do usuário antes de gravar.

Nueva versión disponible.