Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
# 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: * Host * Port * URL ([http://127.0.0.1:PORT](http://127.0.0.1:PORT)) * Stop instruction (Ctrl+C) 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.