diff --git a/CHANGELOG.md b/CHANGELOG.md index 765eeb4..74a20f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to Hack Engine are documented here. +## [1.3.5] - 2026-09-29 + +- Unify Simple and Advanced into one scan workflow with expandable Scan options. +- Keep active scan settings visible while options are collapsed. +- Share candidate filtering, sorting, watches, and one value editor across popup, sidebar, and pop-out. +- Preserve scan configuration during refinement and refresh the object-picker summary. +- Prevent paused Ruffle games from resuming through player-overlay input. +- Preserve newer scans during asynchronous reset cleanup and background state recovery. + ## [1.3.0] - 2026-09-27 Not published to browser stores. Game pause controls and automatic pause during scanning. diff --git a/README.md b/README.md index a835f1e..8c2e57a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Hack Engine helps you find, watch, and change accessible numeric values in WebAs Everything happens locally in the inspected tab. Hack Engine has no accounts, telemetry, advertising, or remote service. -> Current release: **v1.3.0 release candidate — not published**. Core workflows are tested locally on Linux Firefox and Chromium; the remaining release gates are recorded in [IMPLEMENTATION_1_0.md](IMPLEMENTATION_1_0.md). +> Current release: **v1.3.5 release candidate — awaiting validation and store review**. The current release checks cover the controlled eight-game matrix and packaged browser regressions described in [test/GAME_TESTING.md](test/GAME_TESTING.md). Historical 1.0 qualification notes remain in [IMPLEMENTATION_1_0.md](IMPLEMENTATION_1_0.md). ## What you can do @@ -13,7 +13,7 @@ Everything happens locally in the inspected tab. Hack Engine has no accounts, te - **Recover mistakes:** Undo one refinement, restore the last write when the game has not changed it, and stop all freezes. - **Edit and freeze:** Replace a discovered value or keep it fixed while the game runs. - **Watch values live:** Keep useful candidates visible as they change and give each watch a descriptive label. -- **Start simple, go deeper:** Use Quick scan for the common workflow, then open Advanced controls when you need more options. +- **Start simple, go deeper:** Scan with Automatic defaults, then expand **Scan options** when you need more control. - **Keep one shared workspace:** Candidates, watches, selections, and freezes stay synchronized between the toolbar, sidebar, and pop-out. ## How to use Hack Engine @@ -24,11 +24,11 @@ Everything happens locally in the inspected tab. Hack Engine has no accounts, te 4. Change that value in the game, enter the new value, and choose **Next scan**. 5. Repeat until only a small number of candidates remain, then select one to watch, edit, or freeze it. -If the exact value is not known, start with **Unknown initial value** and refine after the game changes. **Value range** helps with rounded or approximate values. Advanced mode also provides explicit number-format, alignment, multiplier, and inspection-source controls. Add known addresses, select individual candidates to watch, edit each watch's label, and sort addresses or values in either direction. Write feedback follows verification through 250 ms; expandable details distinguish verification from game restoration or failed reads. +If the exact value is not known, start with **Unknown initial value** and refine after the game changes. **Value range** helps with rounded or approximate values. Expand **Scan options** to choose a number format, alignment, or JavaScript object. Non-default settings remain visible in the collapsed summary. The toolbar, sidebar, and pop-out all provide **Candidates** and **Watches**, filtering, sorting, and one selected-value editor. Select individual candidates to watch, edit each watch's label, and sort addresses or values in either direction. Write feedback follows verification through 250 ms; expandable details distinguish verification from game restoration or failed reads. ## JavaScript games -Choose **JavaScript objects** as the source and scan normally. Advanced controls offer an object picker to narrow discovery. Results show property paths instead of memory addresses. If discovery reaches a limit, the panel reports partial coverage; choose a narrower object and scan again. A replaced object makes its old watches unavailable rather than redirecting writes. +Choose **JavaScript objects** as the source and scan normally. Expand **Scan options** to use the object picker and narrow discovery. Results show property paths instead of memory addresses. If discovery reaches a limit, the panel reports partial coverage; choose a narrower object and scan again. A replaced object makes its old watches unavailable rather than redirecting writes. ## Browser support @@ -62,7 +62,7 @@ Reload the game page after loading the extension so Hack Engine can detect the p ## Good to know - Hack Engine searches captured WebAssembly memory and reachable JavaScript object properties. Private variables, worker state, encoded values, and server-controlled state are outside this release. See [compatibility](COMPATIBILITY.md) for tested coverage and limits. -- A displayed number may be rounded, scaled, copied, or recalculated by the game. Range scans, comparison scans, and Advanced mode can help identify the useful value. +- A displayed number may be rounded, scaled, copied, or recalculated by the game. Range scans, comparison scans, and additional scan options can help identify the useful value. - Editing the wrong address can reset or crash the embedded player. Use Hack Engine only with games and software you own or are authorized to inspect. ## Planned features diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 793bde5..5e314ea 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -11,15 +11,15 @@ Hack Engine finds, watches, and edits accessible numeric values in WebAssembly a 5. Select a candidate. Selection adds it to the shared watch list automatically. 6. Enter a replacement and choose **Write value**. Use **Freeze** only when the game repeatedly restores the address. -## Persistent and advanced views +## One workflow across popup, sidebar, and pop-out -The toolbar popup closes when focus returns to the page. Use the pin to open the persistent sidebar. The sidebar's **Advanced** view adds explicit number format, alignment, and inspection-source controls plus filtering, sorting, and watches. +The toolbar popup closes when focus returns to the page. Use the pin to open the persistent sidebar. Every surface uses the same scan form, with Automatic defaults and expandable **Scan options** for number format, alignment, and the JavaScript object picker. Non-default settings remain visible in the collapsed summary. Expanding or collapsing these options preserves the current scan and results. -Both views show candidates with recommended variable types first: Float64 for AVM1, or Int32, Uint32, then Float64 for AVM2. WebAssembly prioritizes Int32, Uint32, Float32, then Float64. Candidates within each priority are ordered by address; when Ruffle AVM is unknown, candidates are ordered by address. Advanced defaults to **Recommended types**, with ascending/descending Address and Value sorting and Type sorting available. Counts distinguish displayed preview rows from all scan matches. Simple always uses the recommended order. +Candidates default to recommended variable types first: Float64 for AVM1, or Int32, Uint32, then Float64 for AVM2. WebAssembly prioritizes Int32, Uint32, Float32, then Float64. Candidates within each priority are ordered by address; when Ruffle AVM is unknown, candidates are ordered by address. The **Candidates** and **Watches** tabs, filtering, and sorting are available in the toolbar, sidebar, and pop-out. Sorting defaults to **Recommended types**, with ascending/descending Address and Value sorting and Type sorting available. Counts distinguish displayed preview rows from all scan matches; the candidate preview shows up to 200 rows. Select a candidate or watch to use the same value editor. AVM detection uses only players linked to the selected memory through Ruffle's metadata callback. Unknown types are checked once per second for up to 15 retries; detection stops early on success and updates the runtime hints automatically. A new movie's metadata event starts a fresh retry budget. Existing scan results are retained. Some Ruffle players share one memory: if that memory contains both AVM1 and AVM2, or ownership cannot be established, it stays **Unknown** and Automatic searches all numeric types. -The toolbar, sidebar, and pop-out share the inspected tab's scan, candidates, watches, primary selection, and freeze state. Advanced controls provide the complete supported workflow; there is no separate inspector or DevTools entry. +The toolbar, sidebar, and pop-out share the inspected tab's scan, candidates, watches, primary selection, and freeze state. Each surface provides the complete supported workflow; there is no separate inspector or DevTools entry. ### Known addresses and watch labels @@ -30,7 +30,7 @@ A live session supports up to 256 watches. Each watch can be edited or frozen in ## Pausing the game -Use **Pause game** to suspend a supported Ruffle game, then **Resume game** to continue. The controls are available in both Simple and Advanced views. If a Ruffle memory is shared by multiple associated players, pausing that source pauses all of those players. +Use **Pause game** to suspend a supported Ruffle game, then **Resume game** to continue. The controls are available in the toolbar, sidebar, and pop-out. If a Ruffle memory is shared by multiple associated players, pausing that source pauses all of those players. Enable **Pause while scanning** to pause during first scans, refinements, and searches across all number formats. The preference is saved. A game that was running resumes when the scan completes, fails, or is cancelled; a game already paused stays paused. Manual pause remains active when you close the popup, so reopen the controls to resume. Disconnecting the page bridge or leaving the page releases pauses owned by Hack Engine. @@ -38,7 +38,7 @@ Pause requires a Ruffle player linked to the selected memory with a supported pl ## Numeric formats -If the Simple scan does not find the value, try **All numeric types** in Advanced. Common Ruffle representations include `Float64` for AVM1 numbers and `Int32`, `Uint32`, or `Float64` for AVM2 values. **Any byte** alignment is slower but can find unaligned values. +If an Automatic scan does not find the value, try **Search all number formats** after an exact/range scan, or reset the scan and choose **All numeric types** in **Scan options**. Common Ruffle representations include `Float64` for AVM1 numbers and `Int32`, `Uint32`, or `Float64` for AVM2 values. **Any byte** alignment is slower but can find unaligned values. ## Why a displayed value may not appear @@ -76,7 +76,7 @@ Scans are limited to captured memories of at most 256 MiB. Snapshot scans check ## JavaScript discovery -Select **JavaScript objects** for reachable numeric own properties in plain objects, arrays, and numeric typed arrays. First scan discovers available values; subsequent scans filter those same live properties. Advanced offers an object picker; it accepts selections, never executable expressions. Number format, alignment, and scaling apply only to WebAssembly. +Select **JavaScript objects** for reachable numeric own properties in plain objects, arrays, and numeric typed arrays. First scan discovers available values; subsequent scans filter those same live properties. **Scan options** offers an object picker; it accepts selections, never executable expressions. Alignment applies only to WebAssembly. Discovery skips ordinary getters and browser/DOM internals. JavaScript Proxy inspection traps can still execute; this is not an isolated debugger. Closures, module-private state, class instances, Map/Set contents, BigInt, workers, and server state are not searched. @@ -86,6 +86,6 @@ Read-only values can be watched but cannot be edited. Typed-array writes must fi ### Targeted number formats -In Advanced, **Number format** controls the first scan. WebAssembly Automatic starts with Int32, Uint32, Float32 and Float64; decimal searches use Float32 and Float64. These are heuristic starting formats, not detected source-language types. Choose **All numeric types** (or **Search all number formats** after an exact/range scan) to include 8-bit and 16-bit integers. Individual formats remain selectable. Unknown Ruffle runtimes still search all formats. +In **Scan options**, **Number format** controls the first scan. WebAssembly Automatic starts with Int32, Uint32, Float32 and Float64; decimal searches use Float32 and Float64. These are heuristic starting formats, not detected source-language types. Choose **All numeric types** (or **Search all number formats** after an exact/range scan) to include 8-bit and 16-bit integers. Individual formats remain selectable. Unknown Ruffle runtimes still search all formats. For JavaScript, Automatic and All numeric types search all reachable finite numbers. **Number properties** targets ordinary object and array properties. The typed-array choices target actual element storage, such as Float32Array or Int32Array; Uint8 also includes Uint8ClampedArray. A whole-valued ordinary JavaScript Number is still a Number property, not an Int32 element. Choose an object to narrow discovery further. Reset the scan to change formats. diff --git a/design-qa.md b/design-qa.md index 75ad7a2..efd1b50 100644 --- a/design-qa.md +++ b/design-qa.md @@ -2,6 +2,8 @@ ## Evidence +The original captures below document earlier iterations. Current unified-workflow validation is recorded at the end of this file. + - Selected source: `/Users/ahmed/.codex/generated_images/019fc6f5-7b69-7a51-b2e2-cef2d880323c/exec-0fda6964-a151-43c1-8c00-ee857a39774d.png` - Normalized source: `/tmp/hack-engine-source-normalized.png` - Firefox implementation captures: `/tmp/hack-engine-popup-compact.png` and `/tmp/hack-engine-popup-pinned.png` @@ -19,30 +21,29 @@ - Image quality: extension icon source is clean at the toolbar sizes and the popup mark remains legible. - Copy: visible product naming is consistently “Hack Engine”; runtime-specific wording remains concise. - Intentional differences: the browser owns the popup's outer frame, and the live connection state appears as a compact subtitle under the product name. -- Quick scan: the simple view exposes condition and value controls without numeric-type or ActionScript-detail rows; runtime guidance remains automatic internally. +- Quick scan: one form exposes condition and value controls with Automatic defaults; runtime guidance remains automatic internally. - Progressive disclosure: range maximum, cancellation/reset controls, results, and the candidate editor remain hidden until relevant. - Header efficiency: product name, live connection subtitle, and pin occupy one compact header; the decorative mark, active-tab block, separate status card, and captured-memory card are removed. - Docked mode: the active mint pin communicates that the Firefox sidebar is open and remains visible while interacting with the inspected page. - Floating mode: **Pop out window** is a separate secondary action because an ordinary extension window cannot be forced to stay above Firefox. -- Advanced mode: a persistent-only segmented switch reveals explicit scan configuration without adding complexity to the transient toolbar popup. -- Advanced workspace: candidates and watches use separate tabs, a compact narrow-column layout, and an editor shared with the selected value. +- Scan options: an expandable section reveals number format, alignment, and the JavaScript object picker in every surface; non-default settings remain visible in its collapsed summary. +- Shared workspace: Candidates and Watches use separate tabs with filtering, sorting, and one editor for the selected value in the toolbar, sidebar, and pop-out. ## Interaction QA — Firefox - Live connection summary renders from the active tab. -- Open inspector launches the existing inspector in a persistent extension tab and preserves the inspected tab ID. - Refresh connection reloads the original active tab. - How it works opens the capabilities section of the project page. - Popup harness completed without an uncaught runtime error. - ActionScript-guided first scans send the internal smart mode, while candidate writes and freezes retain the detected numeric type. - Quick scan state and completed results survive closing and reopening the toolbar popup. -- Visible simple-view candidates refresh in one batched read every 250 ms without changing the retained scan set. -- Simple and Advanced views share one scan session; switching views neither resets nor repeats the scan. -- The full inspector joins that same tab-scoped session, so opening it inherits the active scan, candidates, watches, primary selection, and freeze state. +- Visible candidates refresh in one batched read every 250 ms without changing the retained scan set. +- Expanding or collapsing Scan options preserves the scan and results. +- The toolbar, sidebar, and pop-out join the same tab-scoped session, including its active scan, candidates, watches, primary selection, and freeze state. - Filters, sorting, expanded sections, bulk checkbox selection, and unsubmitted write drafts remain local, preventing disruptive cross-window UI changes. -- Advanced mode exposes number format, alignment, stored-value multiplier, and captured-memory selection before the first scan, then locks representation controls during refinement. -- The Advanced candidate list displays up to 200 live values, supports filtering and sorting, and automatically watches a value when it is selected. -- Both candidate editors expose compact type-aware minimum and maximum presets without writing until the user confirms **Write value**. +- Scan options exposes number format, alignment, and the JavaScript object picker before the first scan, then locks representation controls during refinement. +- The candidate list in every surface displays up to 200 live values, supports filtering and sorting, and automatically watches a value when it is selected. +- The shared value editor exposes compact type-aware minimum and maximum presets without writing until the user confirms **Write value**. - Sidebar watches continue polling after a scan reset and are capped so one batched read remains within the page agent's 256-entry limit. - Pinning docks the controls in Firefox's sidebar, retains the original inspected-tab target, and the active pin closes the sidebar. - Pop out creates or focuses one floating utility window per inspected tab and opens related tabs in the target's original browser window. @@ -56,6 +57,16 @@ - Compact-header pass: reduced connection state to a subtitle and removed captured-memory and ActionScript-detail rows, bringing scan controls directly below the header. - Pinning pass: replaced the focus-sensitive floating pin behavior with Firefox sidebar docking and kept floating mode as a separate pop-out action. - Advanced-sidebar pass: added progressive scan controls, shared-session candidate rendering, live watches, and responsive candidate/editor layouts without expanding the native popup. -- Post-fix review: no remaining P0, P1, or P2 visual or interaction findings. +- Prior post-fix review: no remaining P0, P1, or P2 visual or interaction findings. +- Unified-workflow pass: removed the Simple/Advanced split, retained expandable scan configuration, and made the results tools and shared editor available in every surface. + +Current unified-workflow verification (2026-09-27): + +- In-app preview checked the collapsed options, visible Float64/Any byte overrides, first scan, candidate selection, and shared editor using simulated extension APIs. +- Unit suite: 146 passed, 2 skipped, no failures outside sandbox restrictions. +- Browser harnesses cover the unified popup, sidebar, pop-out, restored scan sessions, single-dispatch scan/write/freeze, and collapsed option retention. +- Native Firefox and Chromium packaged-extension workflows passed. +- At 300 CSS pixels, toolbar, sidebar, and pop-out have no horizontal overflow with the JavaScript editor selected and scan options both open and closed. +- Release packages rebuilt and validated locally; no store publication or release tag created. -final result: passed +The original screenshots above are historical, not captures of this unified interface. diff --git a/manifest.json b/manifest.json index 56aa4a3..7777b05 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Hack Engine", - "version": "1.3.0", + "version": "1.3.5", "description": "Find, watch, and edit accessible numeric state in WebAssembly and JavaScript browser games.", "homepage_url": "https://abduljawada.github.io/hack-engine/", "permissions": [ diff --git a/package-lock.json b/package-lock.json index d01b7ab..0550951 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hack-engine-extension", - "version": "1.3.0", + "version": "1.3.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hack-engine-extension", - "version": "1.3.0", + "version": "1.3.5", "license": "MIT", "devDependencies": { "tesseract.js": "7.0.0", diff --git a/package.json b/package.json index 40916ad..e912d33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hack-engine-extension", - "version": "1.3.0", + "version": "1.3.5", "private": true, "license": "MIT", "type": "module", diff --git a/popup/popup.css b/popup/popup.css index 770be86..dd82bbb 100644 --- a/popup/popup.css +++ b/popup/popup.css @@ -16,6 +16,7 @@ [hidden] { display: none !important; } body { width: 380px; + max-width: 100%; min-height: 500px; max-height: 600px; overflow-y: auto; @@ -230,17 +231,6 @@ select, input { font-size: 14px; } .preset-action:hover { border-color: rgb(130 247 197 / 28%); color: var(--accent); background: rgb(130 247 197 / 5%); } .compact-action.freeze-active { border-color: var(--accent); color: var(--accent); background: rgb(130 247 197 / 7%); } -.view-switcher { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 3px; - margin-top: 11px; - padding: 3px; - border: 1px solid var(--line); - border-radius: 9px; - background: var(--surface); -} -.view-switcher button, .workspace-tabs button { min-width: 0; min-height: 34px; @@ -252,13 +242,11 @@ select, input { font-size: 14px; } font-size: 12px; font-weight: 700; } -.view-switcher button[aria-pressed="true"], .workspace-tabs button[aria-selected="true"] { background: var(--surface-hover); color: var(--text); box-shadow: inset 0 0 0 1px rgb(130 247 197 / 18%); } -.view-switcher button:focus-visible, .workspace-tabs button:focus-visible, .advanced-candidate:focus-visible, .watch-select:focus-visible, @@ -392,7 +380,6 @@ select, input { font-size: 14px; } font-size: 17px; } .watch-remove:hover { background: rgb(255 115 115 / 10%); color: #ff9b9b; } -body.advanced-active .secondary-actions { display: none; } @media (max-width: 330px) { main { padding-inline: 14px; } @@ -445,11 +432,11 @@ button:focus-visible, input:focus-visible, select:focus-visible, summary:focus-v .quick-form > .value-fields, .advanced-form > .value-fields { grid-column: 2; min-width: 0; } .quick-form input, .quick-form select, .advanced-form input, .advanced-form select { min-width: 0; } .quick-form:has(#quick-max-label:not([hidden])), -.advanced-form:has(#advanced-max-label:not([hidden])) { grid-template-columns: minmax(0, 1fr); } +.advanced-form:has(#quick-max-label:not([hidden])) { grid-template-columns: minmax(0, 1fr); } .quick-form:has(#quick-max-label:not([hidden])) > .value-fields, -.advanced-form:has(#advanced-max-label:not([hidden])) > .value-fields { grid-column: 1 / -1; } +.advanced-form:has(#quick-max-label:not([hidden])) > .value-fields { grid-column: 1 / -1; } .quick-form:has(#quick-value-label[hidden]) > label:first-child, -.advanced-form:has(#advanced-value-label[hidden]) > label:first-child { grid-column: 1 / -1; } +.advanced-form:has(#quick-value-label[hidden]) > label:first-child { grid-column: 1 / -1; } .value-fields:not(:has(> label:not([hidden]))) { display: none; } @media (max-width: 380px) { .watch-metadata { flex-wrap: wrap; } @@ -459,7 +446,7 @@ button:focus-visible, input:focus-visible, select:focus-visible, summary:focus-v @media (max-width: 260px) { main { padding-inline: 8px; } .advanced-heading, .quick-heading { flex-wrap: wrap; } - .workspace-tabs, .view-switcher, .value-fields { grid-template-columns: minmax(0, 1fr); } + .workspace-tabs, .value-fields { grid-template-columns: minmax(0, 1fr); } .scan-actions, .editor-actions, .value-presets { flex-wrap: wrap; } .advanced-candidate, .watch-select { grid-template-columns: minmax(0, 1fr); } .candidate-type { justify-self: start; } @@ -472,7 +459,7 @@ main { container-type: inline-size; } .quick-form, .advanced-form { grid-template-columns: minmax(0, 1fr); } .quick-form > .value-fields, .advanced-form > .value-fields { grid-column: 1 / -1; } .advanced-heading, .quick-heading { flex-wrap: wrap; } - .workspace-tabs, .view-switcher, .value-fields, .advanced-grid, .candidate-tools { grid-template-columns: minmax(0, 1fr); } + .workspace-tabs, .value-fields, .advanced-grid, .candidate-tools { grid-template-columns: minmax(0, 1fr); } .scan-actions, .editor-actions, .value-presets { flex-wrap: wrap; } .advanced-candidate, .watch-select { grid-template-columns: minmax(0, 1fr); } .candidate-type { justify-self: start; } @@ -489,3 +476,11 @@ main { container-type: inline-size; } .workspace-heading .workspace-tabs { flex: 1 1 180px; margin-bottom: 0; } .stop-freezes { margin-top: 10px; } main > .session-tools:has(.session-feedback:empty) { display: none; } + +/* One scan flow; specialized configuration stays available in place. */ +.scan-options { border: 1px solid var(--line); border-radius: 8px; padding: 9px 10px; } +.scan-options > summary { cursor: pointer; font-size: 12px; font-weight: 600; overflow-wrap: anywhere; } +#scan-options-summary { color: var(--muted); font-weight: 400; margin-left: 6px; } +.scan-options[open] > summary { margin-bottom: 12px; } +.scan-options .runtime-guidance { margin: 12px 0 0; } +.scan-options #javascript-root-controls { margin-top: 12px; } diff --git a/popup/popup.html b/popup/popup.html index e6362e1..486a9bc 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -29,11 +29,6 @@
Pause is available for supported Ruffle games.
-AVM could not be determined. Automatic searches all numeric types.
-Discovery stops at eight levels, 20,000 objects, or 100,000 properties. A narrower object can reveal values beyond those limits.
-