mirror of
https://github.com/morluto/rea.git
synced 2026-10-12 02:19:24 +00:00
feat(website): introduce REA and the DX-Ball reconstruction (#906)
* feat(website): add local introduction and DX-Ball showcase * feat(website): illustrate REA and DX-Ball reconstruction Add two explanatory figures and an interactive comparison of recorded DX-Ball x86 instructions with maintained C. Preserve the full instruction listing, caller excerpt, constant reads, figure prompts and evidence provenance. Validation: Chrome preview at local root and /rea/; five comparison steps; 22 clipboard checks; keyboard navigation; responsive widths 1440, 768, 390 and 320. Verify assembly against saved REA Evidence and C against the pinned public source. Existing execution and compiler results are cited, not rerun. * docs(website): show the REA queries behind source recovery Present compact function, caller and byte-read request excerpts alongside recorded evidence. Keep the overview and case narrative focused on REA, with provider provenance in contributor notes. Replace raster references with maintained SVG source diagrams while retaining the established layout and image-generation prompts. Validation: local and /rea/ Chrome previews, five comparison steps, 22 clipboard checks, responsive widths and keyboard navigation passed. SVG XML and all 41 local links/assets passed checks.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
name: Publish REA website
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: website-pages
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
if: github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
pages: read
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Configure Pages
|
||||
uses: actions/configure-pages@v5
|
||||
- name: Upload the website
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: website/public
|
||||
|
||||
deploy:
|
||||
needs: prepare
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Publish to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
@@ -0,0 +1,63 @@
|
||||
# REA website
|
||||
|
||||
An English static website with explanatory figures and a DX-Ball investigation.
|
||||
The public files are in `website/public/`. The site uses HTML, CSS and a small
|
||||
script for copying code and following the assembly-to-C comparison; it has no
|
||||
build step or npm dependencies.
|
||||
|
||||
## Local preview
|
||||
|
||||
From the repository root:
|
||||
|
||||
```sh
|
||||
python3 -m http.server 4173 --bind 127.0.0.1 --directory website/public
|
||||
```
|
||||
|
||||
Open <http://127.0.0.1:4173/>. Refresh the browser after editing a file.
|
||||
|
||||
## Pages
|
||||
|
||||
- `public/index.html`: product introduction and DX-Ball overview.
|
||||
- `public/showcase/dx-ball/index.html`: sound-pan investigation and project status.
|
||||
- `public/get-started/index.html`: agent setup, first CLI result and provider guides.
|
||||
- `public/assets/`: shared styles, interactions, favicon and explanatory figures.
|
||||
|
||||
Navigation and assets use relative paths, so the same files work at the local
|
||||
root and a GitHub Pages project path such as `/rea/`.
|
||||
|
||||
## Content
|
||||
|
||||
Keep the copy direct and specific. Explain the task and the result before listing
|
||||
tool names. Setup commands and runtime requirements should match the released
|
||||
package.
|
||||
|
||||
DX-Ball figures and findings refer to the linked 7 October 2026 checkpoint,
|
||||
commit `a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4`. Update those links and figures
|
||||
together when moving to another checkpoint. Case-study source excerpts come
|
||||
from the MIT-licensed DX-Ball reconstruction repository.
|
||||
|
||||
The assembly excerpts were transcribed from the project's saved REA/Ghidra
|
||||
Evidence. [evidence/dx-ball-sound-pan.md](evidence/dx-ball-sound-pan.md) records
|
||||
their provenance and the scope of the validation claims. The original executable
|
||||
and complete private Evidence records are not website assets.
|
||||
|
||||
The diagrams are maintained as SVG source. Initial layout references were
|
||||
created with the built-in image generation tool; [figures.md](figures.md) retains
|
||||
their prompts and the current asset notes. Figures provide an overview;
|
||||
REA requests, assembly and C remain selectable HTML text. On narrow
|
||||
screens, the diagrams scroll horizontally and can also be opened at full size.
|
||||
|
||||
## GitHub Pages
|
||||
|
||||
`.github/workflows/website-pages.yml` prepares and deploys only `website/public`.
|
||||
It is manually triggered and restricted to `main`; ordinary pushes and pull
|
||||
requests do not publish the site.
|
||||
|
||||
After the site is approved and merged, select **GitHub Actions** under the
|
||||
repository's **Settings → Pages → Build and deployment**. Then run **Publish REA
|
||||
website** from the Actions tab on `main`. The workflow uses the `github-pages`
|
||||
environment and the official Pages actions.
|
||||
|
||||
Local development does not change Pages settings or run the deployment workflow.
|
||||
Any environment protection rules are configured separately when publication is
|
||||
approved.
|
||||
@@ -0,0 +1,116 @@
|
||||
# DX-Ball sound-pan evidence
|
||||
|
||||
The website presents one function from the English DX-Ball 1.07 Windows i386
|
||||
executable. Project progress and validation claims are pinned to reconstruction
|
||||
commit `a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4` (7 October 2026).
|
||||
|
||||
## Artifact and provider
|
||||
|
||||
- Target: `DXBALL.EXE`, 158,208 bytes, PE i386.
|
||||
- SHA-256: `756da1ba09edce716d5bf8770320ca0d5ed4e525672b6bb605b9bdb4b88972ba`.
|
||||
- Function: `0x406400` through `0x40643e`, inclusive, 63 bytes.
|
||||
- Recorded analysis: REA 4.1.0, Ghidra 12.1.4, Linux x64 host.
|
||||
- Pan dossier: `ev_ddca58134d89a2eb0aba5bf5694bb06ce7b5cb28aac0eb847891506244e70490`.
|
||||
- Caller dossier: `ev_d09866ff22dc07f3ac28ef1d992c5876c1e58e1796dbe0f0c5c2814544aa27eb`.
|
||||
- Constants read: `ev_6a56fda997bcda2df677257601da0174ff8041d44c8c83c48356df31edf0f7ae`.
|
||||
- Scale read: `ev_64752f4ecf1ec74384ce01083c21fcfffb716931f6c31a7dac351a136df7979e`.
|
||||
|
||||
The website update reused the matching saved REA results and verified the local
|
||||
target digest. It did not start a new provider session or repeat the project's
|
||||
execution/compiler checks. Complete dossiers, snapshots, the original
|
||||
executable and compiler products remain in the reconstruction project.
|
||||
|
||||
## Observations and interpretation
|
||||
|
||||
| Saved observation | Interpretation used by the reconstruction |
|
||||
| --------------------------------------------------------------------- | ------------------------------------------------- |
|
||||
| Stack load from `[EBP+8]`, then `FILD` | An integer parameter, named `x` |
|
||||
| Brick-hit caller multiplies its coordinate by 30, adds 20, pushes EAX | The input is a brick's horizontal screen position |
|
||||
| `FMUL [0x420068]`; byte read decodes to 1.5625 | `pan = pan * 1.5625` |
|
||||
| `FSUB [0x420070]`; byte read decodes to 500.0 | `pan = pan - 500.0` |
|
||||
| `FMUL [0x4210a0]`; initial double is 1.0 | A stored scale, named `dxball_pan_scale` |
|
||||
| Call to `__ftol` at 0x41678c | Convert the calculation to an integer |
|
||||
|
||||
The names `dxball_screen_pan`, `x` and `dxball_pan_scale` belong to the maintained
|
||||
source. The executable's instruction view supplies addresses and operations.
|
||||
The original decompiler result reports `FUN_00406400(void)` and a conversion
|
||||
call, omitting the stack input and x87 expression. The website's pseudocode
|
||||
excerpt preserves that body and omits only its leading provider warning/comment
|
||||
and blank lines.
|
||||
|
||||
## Displayed REA requests
|
||||
|
||||
The page shows the actual tool names with compact input excerpts:
|
||||
|
||||
- `analyze_function` at procedure `0x406400` returns the pan dossier, including
|
||||
its instruction view and the caller entry at `0x411f40`.
|
||||
- `analyze_function` at procedure `0x411f40` returns the brick-hit dossier.
|
||||
The visible caller excerpt preserves the ADD/PUSH/CALL instructions verbatim;
|
||||
the full supporting excerpt also shows the preceding ×30 calculation.
|
||||
- `read_bytes` at `0x420068`, length 16, returns
|
||||
`000000000000f93f0000000000407f40`.
|
||||
- `read_bytes` at `0x4210a0`, length 8, returns `000000000000f03f`.
|
||||
|
||||
The page splits the first byte read into two eight-byte values and shows their
|
||||
little-endian double interpretations beside the observed hex. These are decoded
|
||||
values, not additional fields in the raw REA result. Query groups present the
|
||||
reasoning sequence rather than reproducing an entire chronological session.
|
||||
Provider details are recorded here; the product narrative uses REA to describe
|
||||
the CLI/MCP operations the agent called.
|
||||
|
||||
## Complete recorded instruction listing
|
||||
|
||||
Transcribed verbatim from the pan dossier's normalized assembly facet:
|
||||
|
||||
```asm
|
||||
0x406400: PUSH EBP
|
||||
0x406401: MOV EBP, ESP
|
||||
0x406403: SUB ESP, 0xc
|
||||
0x406406: PUSH EBX
|
||||
0x406407: PUSH ESI
|
||||
0x406408: PUSH EDI
|
||||
0x406409: MOV EAX, dword ptr [EBP + 0x8]
|
||||
0x40640c: MOV dword ptr [EBP + -0xc], EAX
|
||||
0x40640f: FILD dword ptr [EBP + -0xc]
|
||||
0x406412: FST double ptr [EBP + -0x8]
|
||||
0x406415: FMUL double ptr [0x00420068]
|
||||
0x40641b: FST double ptr [EBP + -0x8]
|
||||
0x40641e: FSUB double ptr [0x00420070]
|
||||
0x406424: FST double ptr [EBP + -0x8]
|
||||
0x406427: FMUL double ptr [0x004210a0]
|
||||
0x40642d: FST double ptr [EBP + -0x8]
|
||||
0x406430: CALL 0x0041678c
|
||||
0x406435: JMP 0x0040643a
|
||||
0x40643a: POP EDI
|
||||
0x40643b: POP ESI
|
||||
0x40643c: POP EBX
|
||||
0x40643d: LEAVE
|
||||
0x40643e: RET
|
||||
```
|
||||
|
||||
The interactive website excerpt selects eight instructions from this listing.
|
||||
It omits setup/cleanup, intermediate `FST` stores and the epilogue jump to keep
|
||||
the calculation visible. The expandable listing retains all 23 instructions.
|
||||
Copying the C panel copies the complete maintained function, including its
|
||||
signature, declaration and return.
|
||||
|
||||
## Validation scope
|
||||
|
||||
The reconstruction project's recorded checks establish:
|
||||
|
||||
- 3,205 direct original-x86 differential cases: integer positions 0–640 at
|
||||
scales 0, 0.5, 1, 20 and −1.
|
||||
- 63 matching bytes for the complete VC4.0-compiled function, after applying
|
||||
every reviewed relocation and checking referenced constants.
|
||||
|
||||
These claims apply to this function at the linked checkpoint. The figure shows
|
||||
execution comparison and compiler replay as separate branches. Game-level
|
||||
integration remains a separate project task.
|
||||
|
||||
## Public sources
|
||||
|
||||
- [Gameplay observations and Evidence IDs](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md)
|
||||
- [Maintained function](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/src/gameplay.c#L41)
|
||||
- [Semantic acceptance ledger](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/config/semantic-acceptance.csv)
|
||||
- [Complete function units and relocation mappings](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/config/match-units.toml)
|
||||
- [Compiler replay method](https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md)
|
||||
@@ -0,0 +1,99 @@
|
||||
# REA website figures
|
||||
|
||||
The published diagrams are SVG source assets:
|
||||
|
||||
- `public/assets/figures/rea-investigation-flow.svg` — 1774 × 887 viewBox.
|
||||
- `public/assets/figures/dx-ball-sound-pan-investigation.svg` — 1774 × 887 viewBox.
|
||||
|
||||
Two original layout references were generated with the built-in image generation
|
||||
tool and reviewed visually. Their prompts are retained below. The final SVGs
|
||||
preserve the white background, charcoal/slate/blue palette and layout while
|
||||
using REA as the reader-facing subject. Provider details remain in configuration
|
||||
guides and the evidence provenance document. The SVGs keep text sharp when
|
||||
zoomed and can be maintained without committing raster binaries.
|
||||
|
||||
The REA figure shows the agent's question, inspection through REA, evidence and
|
||||
follow-up work. The DX-Ball figure shows the ordered input/arithmetic evidence,
|
||||
the maintained C and separate execution/compiler checks. Recorded tool requests,
|
||||
instruction excerpts and decoded byte reads appear as HTML text in the case
|
||||
study; source reconstruction is the agent's work informed by REA results.
|
||||
|
||||
## Review
|
||||
|
||||
Check spelling, arithmetic order, arrow directions and the separate verification
|
||||
branches when changing these figures. Match progress claims to the pinned
|
||||
reconstruction checkpoint. Validate the SVG as XML and inspect its browser
|
||||
rendering at desktop and mobile widths.
|
||||
|
||||
## Original image generation prompts
|
||||
|
||||
## Prompt 1
|
||||
|
||||
Use case: scientific-educational
|
||||
Asset type: project-bound raster diagram for the REA website, readable at 1080px display width.
|
||||
Primary request: Make one exceptionally clear, publication-style flow figure explaining how an analyst and their agent use REA to investigate a local target. The reader should understand the roles and sequence in one glance.
|
||||
Canvas: wide landscape 2:1 aspect ratio, approximately 2048 × 1024 pixels. Plain pure-white background. Generous clear outer margin. Flat vector-like graphic rendered as raster.
|
||||
Style: restrained technical-paper figure. Crisp large sans-serif type. Charcoal #20252b text, slate #5b6570 secondary text, thin gray connecting lines, one muted blue #294f82 accent for REA and meaningful connections. No decorative illustration.
|
||||
|
||||
Layout and exact labels:
|
||||
A short title at the top left: "REA investigation flow".
|
||||
Four clear evenly spaced stages along a single left-to-right horizontal baseline. Each stage has a prominent numbered heading, concise centered labels, and ample whitespace. Main connectors are right-pointing arrows between adjacent stages.
|
||||
Stage 1:
|
||||
"1. Ask"
|
||||
"Your agent + local target"
|
||||
"App / binary / browser"
|
||||
Stage 2:
|
||||
"2. Inspect & trace"
|
||||
A large blue label "REA"
|
||||
"CLI / MCP"
|
||||
Stage 3:
|
||||
"3. Read the evidence"
|
||||
"Code / references / unknowns"
|
||||
Stage 4:
|
||||
"4. Use what you learn"
|
||||
A large label "Your agent"
|
||||
"Explain / implement / test"
|
||||
|
||||
Below stage 2 only, put a supporting box and a thin vertical connector to REA. Box labels verbatim:
|
||||
"Analysis tools"
|
||||
"Ghidra / Hopper / IDA / other adapters"
|
||||
It is a set of available adapters, not a requirement that all engines be used. Do not put this box under other stages.
|
||||
Add exactly one subtle feedback arrow above the main row: from stage 4 back to stage 2, pointing into REA. Its label is "Follow-up question". Do not cross text.
|
||||
Semantics: REA provides inspection and analysis evidence via CLI/MCP. The user's agent uses that evidence to explain, implement, or test. Never imply REA automatically clones a program.
|
||||
Text: Render every supplied English label verbatim with correct spelling. Keep type large and dark enough to read when image is displayed at 1080px wide. Do not add additional captions, claims, legends, text, code, logos, icons, or numbers.
|
||||
Avoid: screenshots, assembly or source code, watermarks, shadows, gradients, 3D, cute icons, bold marketing banners, ornate borders, dense text, tiny labels, decorative arrows.
|
||||
|
||||
## Prompt 2
|
||||
|
||||
Use case: scientific-educational
|
||||
Asset type: project-bound raster figure for a restrained REA technical case-study web page, readable at 1080px display width.
|
||||
Primary request: Draw one accurate, instantly understandable publication-style diagram of the DX-Ball sound-pan function investigation. Show the original executable feeding REA/Ghidra analysis, the ordered arithmetic evidence, the maintained C reconstruction, and two separate verification checks. This concerns ONE FUNCTION, not the entire game.
|
||||
Canvas: wide landscape 2:1 aspect ratio, approximately 2048 × 1024 pixels. Pure-white background, generous outer margins. Flat vector-like diagram rendered as raster.
|
||||
Style: crisp large sans-serif, charcoal #20252b primary text, slate #5b6570 secondary text and thin outlines, one restrained blue #294f82 accent. Only boxes, simple lines, arrows and typography. No shadows, gradients, 3D, icons or screenshots.
|
||||
|
||||
Composition:
|
||||
At top left, a concise title "DX-Ball sound-pan investigation".
|
||||
The main upper row proceeds from left to right across three clearly separated regions: a compact source box on the far left, a wide central analysis region, then a compact implementation box on the right. Use meaningful arrows connecting them. Reserve lower space for a caller input on the lower left and verification checks on the lower right, with no crossing connectors or cramped text.
|
||||
|
||||
Exact labels and relationships:
|
||||
SOURCE: box text "DXBALL.EXE" with "0x00406400" underneath.
|
||||
Arrow from SOURCE into the first node of the central region.
|
||||
|
||||
CENTRAL EVIDENCE REGION: heading "REA + Ghidra".
|
||||
Five little arithmetic nodes in exactly this order, joined by right-pointing arrows:
|
||||
"Stack input x" → "× 1.5625" → "− 500.0" → "× pan_scale" → "Integer return"
|
||||
The last node connects to the maintained C box on the right.
|
||||
The operations MUST remain in this order; these are arithmetic evidence labels, not source code. Use the true multiplication symbol × and minus symbol −, never a plus.
|
||||
Put a supporting caller box below the first input, connected by a single arrow ONLY to "Stack input x". Its exact labels are "Brick-hit caller" and "20 + 30 × tile_x". This supplies the input position. Do not connect the caller to the multiplier or to later operations.
|
||||
|
||||
IMPLEMENTATION REGION on the right: small heading "Reconstructed function" with prominent box text "Maintained C".
|
||||
Below this output, draw a fork into TWO distinct verification boxes; both receive a connector from Maintained C, and neither receives a connector from the other check. These checks are independent branches, never a single serial validation.
|
||||
First check labels verbatim:
|
||||
"Original-x86 comparison"
|
||||
"3,205 cases"
|
||||
Second check labels verbatim:
|
||||
"VC4.0 compiler replay"
|
||||
"63 matching bytes"
|
||||
Use enough horizontal space for clear check names and generous typography. A two-line label is fine where needed.
|
||||
|
||||
Text constraints: render every supplied English label and number verbatim with correct spelling. No extra claims, no additional labels, no footnotes, no source code or assembly, no logos or watermarks. Keep all connectors complete and directed correctly. Large legible labels matter more than decorative density. Never say full reconstruction, exact game clone, all bytes, or automatic source recovery.
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><rect width="32" height="32" rx="5" fill="#20252b"/><path fill="#fff" d="M9 7h7.5c5 0 7.5 2.3 7.5 6.2 0 2.8-1.4 4.7-4 5.6L25 25h-5l-4.5-5.8H13V25H9zm4 3.5v5.2h3.5c2.3 0 3.5-.8 3.5-2.6s-1.2-2.6-3.5-2.6z"/></svg>
|
||||
|
After Width: | Height: | Size: 271 B |
@@ -0,0 +1,58 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1774" height="887" viewBox="0 0 1774 887" role="img" aria-labelledby="title desc">
|
||||
<title id="title">DX-Ball sound-pan investigation</title>
|
||||
<desc id="desc">REA provides the instruction, caller and byte-read evidence for one DX-Ball function. A stack input is multiplied by 1.5625, offset by 500, scaled, and converted to an integer. Maintained C is checked in 3,205 original-x86 cases and a separate 63-byte compiler replay.</desc>
|
||||
<defs>
|
||||
<marker id="arrow" markerWidth="14" markerHeight="14" refX="11" refY="7" orient="auto" markerUnits="userSpaceOnUse"><path d="M1 1 L11 7 L1 13 Z" fill="#5b6570"/></marker>
|
||||
</defs>
|
||||
<rect width="1774" height="887" fill="#ffffff"/>
|
||||
<g font-family="Arial, Helvetica, sans-serif" fill="#20252b">
|
||||
<text x="40" y="166" font-size="63" font-weight="700">DX-Ball sound-pan investigation</text>
|
||||
<g fill="none" stroke="#6c7e8b" stroke-width="3">
|
||||
<rect x="40" y="293" width="237" height="131"/>
|
||||
<rect x="315" y="232" width="1006" height="215"/>
|
||||
<rect x="1353" y="232" width="384" height="215"/>
|
||||
<rect x="338" y="303" width="165" height="102"/>
|
||||
<rect x="538" y="303" width="167" height="102"/>
|
||||
<rect x="740" y="303" width="163" height="102"/>
|
||||
<rect x="938" y="303" width="177" height="102"/>
|
||||
<rect x="1150" y="303" width="153" height="102"/>
|
||||
<rect x="1375" y="298" width="344" height="115"/>
|
||||
<rect x="267" y="514" width="303" height="131"/>
|
||||
<rect x="1229" y="577" width="251" height="169"/>
|
||||
<rect x="1498" y="577" width="255" height="169"/>
|
||||
</g>
|
||||
<g text-anchor="middle" font-weight="700">
|
||||
<text x="158" y="357" font-size="32">DXBALL.EXE</text>
|
||||
<text x="158" y="396" font-size="26" fill="#5b6570">0x00406400</text>
|
||||
<text x="818" y="282" font-size="43" fill="#294f82">REA</text>
|
||||
<text x="420" y="347" font-size="33">Stack</text>
|
||||
<text x="420" y="386" font-size="33">input x</text>
|
||||
<text x="621" y="368" font-size="32">× 1.5625</text>
|
||||
<text x="821" y="368" font-size="35">− 500.0</text>
|
||||
<text x="1026" y="368" font-size="28">× pan_scale</text>
|
||||
<text x="1226" y="347" font-size="32">Integer</text>
|
||||
<text x="1226" y="386" font-size="32">return</text>
|
||||
<text x="1545" y="279" font-size="30" fill="#294f82">Reconstructed function</text>
|
||||
<text x="1547" y="372" font-size="43">Maintained C</text>
|
||||
<text x="418" y="569" font-size="34">Brick-hit caller</text>
|
||||
<text x="418" y="615" font-size="28" fill="#5b6570">20 + 30 × tile_x</text>
|
||||
<text x="1354" y="632" font-size="30">Original-x86</text>
|
||||
<text x="1354" y="670" font-size="30">comparison</text>
|
||||
<text x="1354" y="717" font-size="31" fill="#5b6570">3,205 cases</text>
|
||||
<text x="1625" y="632" font-size="28">VC4.0 compiler</text>
|
||||
<text x="1625" y="670" font-size="32">replay</text>
|
||||
<text x="1625" y="717" font-size="28" fill="#5b6570">63 matching bytes</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" stroke="#5b6570" stroke-width="4" marker-end="url(#arrow)">
|
||||
<path d="M279 354 H332"/>
|
||||
<path d="M505 354 H532"/>
|
||||
<path d="M707 354 H734"/>
|
||||
<path d="M905 354 H932"/>
|
||||
<path d="M1117 354 H1144"/>
|
||||
<path d="M1305 354 H1369"/>
|
||||
<path d="M420 512 V411"/>
|
||||
<path d="M1547 415 V496 H1354 V571"/>
|
||||
<path d="M1547 496 H1625 V571"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
@@ -0,0 +1,43 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1774" height="887" viewBox="0 0 1774 887" role="img" aria-labelledby="title desc">
|
||||
<title id="title">REA investigation flow</title>
|
||||
<desc id="desc">Ask a question about a local target. REA inspects and traces through local analysis adapters, returns evidence, and supports follow-up questions as your agent explains, implements and tests.</desc>
|
||||
<defs>
|
||||
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="5" orient="auto-start-reverse" markerUnits="userSpaceOnUse"><path d="M1 1 L8 5 L1 9" fill="none" stroke="#5b6570" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></marker>
|
||||
<marker id="blue-arrow" markerWidth="12" markerHeight="12" refX="9" refY="6" orient="auto" markerUnits="userSpaceOnUse"><path d="M1 1 L9 6 L1 11" fill="none" stroke="#294f82" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></marker>
|
||||
</defs>
|
||||
<rect width="1774" height="887" fill="#ffffff"/>
|
||||
<g font-family="Arial, Helvetica, sans-serif" fill="#20252b">
|
||||
<text x="40" y="96" font-size="68" font-weight="700">REA investigation flow</text>
|
||||
<g fill="none" stroke="#87929e" stroke-width="3.5">
|
||||
<rect x="28" y="282" width="384" height="255" rx="15"/>
|
||||
<rect x="477" y="282" width="377" height="255" rx="15" stroke="#294f82"/>
|
||||
<rect x="919" y="282" width="380" height="255" rx="15"/>
|
||||
<rect x="1364" y="282" width="382" height="255" rx="15"/>
|
||||
<rect x="453" y="617" width="425" height="205" rx="15"/>
|
||||
</g>
|
||||
<g text-anchor="middle">
|
||||
<text x="220" y="365" font-size="50" font-weight="700">1. Ask</text>
|
||||
<text x="220" y="435" font-size="31" fill="#5b6570">Your agent + local target</text>
|
||||
<text x="220" y="496" font-size="31" fill="#5b6570">App / binary / browser</text>
|
||||
<text x="665" y="357" font-size="37" font-weight="700">2. Inspect & trace</text>
|
||||
<text x="665" y="454" font-size="80" font-weight="700" fill="#294f82">REA</text>
|
||||
<text x="665" y="508" font-size="35" fill="#5b6570">CLI / MCP</text>
|
||||
<text x="1109" y="363" font-size="35" font-weight="700">3. Read the evidence</text>
|
||||
<text x="1109" y="438" font-size="32" fill="#5b6570">Code / references /</text>
|
||||
<text x="1109" y="480" font-size="32" fill="#5b6570">unknowns</text>
|
||||
<text x="1555" y="362" font-size="34" font-weight="700">4. Use what you learn</text>
|
||||
<text x="1555" y="440" font-size="53" font-weight="700">Your agent</text>
|
||||
<text x="1555" y="496" font-size="30" fill="#5b6570">Explain / implement / test</text>
|
||||
<text x="665" y="690" font-size="42" font-weight="700">Analysis tools</text>
|
||||
<text x="665" y="755" font-size="32" fill="#5b6570">Local analysis adapters</text>
|
||||
<text x="1118" y="199" font-size="33" font-weight="700" fill="#294f82">Follow-up question</text>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="none" stroke="#5b6570" stroke-width="4" marker-end="url(#arrow)">
|
||||
<path d="M414 410 H469"/>
|
||||
<path d="M856 410 H911"/>
|
||||
<path d="M1301 410 H1356"/>
|
||||
<path d="M665 615 V545"/>
|
||||
</g>
|
||||
<path d="M1555 280 V248 Q1555 217 1524 217 H696 Q665 217 665 248 V273" fill="none" stroke="#294f82" stroke-width="4" marker-end="url(#blue-arrow)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,57 @@
|
||||
function initializeCopyButtons() {
|
||||
document.querySelectorAll("[data-copy]").forEach((button) => {
|
||||
button.addEventListener("click", async () => {
|
||||
const target = document.getElementById(button.getAttribute("data-copy"));
|
||||
if (target === null) return;
|
||||
|
||||
const status = document.getElementById("copy-status");
|
||||
try {
|
||||
await navigator.clipboard.writeText(target.textContent.trim());
|
||||
button.textContent = "Copied";
|
||||
if (status !== null) status.textContent = "Code copied to clipboard.";
|
||||
} catch {
|
||||
const range = document.createRange();
|
||||
range.selectNodeContents(target);
|
||||
const selection = window.getSelection();
|
||||
if (selection !== null) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
button.textContent = "Selected";
|
||||
if (status !== null)
|
||||
status.textContent = "Code selected. Use your keyboard to copy it.";
|
||||
}
|
||||
|
||||
window.setTimeout(() => {
|
||||
button.textContent = "Copy";
|
||||
}, 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initializeCopyButtons();
|
||||
|
||||
function initializeStepComparisons() {
|
||||
document.querySelectorAll("[data-step-comparison]").forEach((comparison) => {
|
||||
const buttons = comparison.querySelectorAll("[data-select-step]");
|
||||
buttons.forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const selected = button.getAttribute("data-select-step");
|
||||
buttons.forEach((candidate) => {
|
||||
candidate.setAttribute("aria-pressed", String(candidate === button));
|
||||
});
|
||||
comparison.querySelectorAll("[data-step]").forEach((fragment) => {
|
||||
fragment.classList.toggle(
|
||||
"is-active",
|
||||
fragment.getAttribute("data-step") === selected,
|
||||
);
|
||||
});
|
||||
comparison.querySelectorAll("[data-step-note]").forEach((note) => {
|
||||
note.hidden = note.getAttribute("data-step-note") !== selected;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initializeStepComparisons();
|
||||
@@ -0,0 +1,857 @@
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--ink: #20252b;
|
||||
--muted: #5b6570;
|
||||
--line: #e0e5e9;
|
||||
--soft: #f4f6f8;
|
||||
--accent: #294f82;
|
||||
--page: #ffffff;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
background: var(--page);
|
||||
color: var(--ink);
|
||||
line-height: 1.65;
|
||||
}
|
||||
a {
|
||||
color: var(--accent);
|
||||
text-underline-offset: 0.2em;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration-thickness: 2px;
|
||||
}
|
||||
button,
|
||||
input {
|
||||
font: inherit;
|
||||
}
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
::selection {
|
||||
background: #dce8f6;
|
||||
}
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 5px;
|
||||
}
|
||||
code,
|
||||
pre {
|
||||
font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace;
|
||||
}
|
||||
code {
|
||||
font-size: 0.9em;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 1.2rem;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
line-height: 1.14;
|
||||
font-weight: 650;
|
||||
letter-spacing: -0.035em;
|
||||
}
|
||||
h1 {
|
||||
margin: 0 0 1.5rem;
|
||||
font-size: clamp(2.75rem, 6.5vw, 5.4rem);
|
||||
}
|
||||
h2 {
|
||||
margin: 0 0 1.2rem;
|
||||
font-size: clamp(1.75rem, 3vw, 2.4rem);
|
||||
}
|
||||
h3 {
|
||||
margin: 0 0 0.65rem;
|
||||
font-size: 1.2rem;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
ul,
|
||||
ol {
|
||||
padding-left: 1.3rem;
|
||||
}
|
||||
li + li {
|
||||
margin-top: 0.45rem;
|
||||
}
|
||||
section[id] {
|
||||
scroll-margin-top: 2rem;
|
||||
}
|
||||
.container {
|
||||
width: min(1080px, calc(100% - 3.5rem));
|
||||
margin-inline: auto;
|
||||
}
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
top: -5rem;
|
||||
padding: 0.6rem 1rem;
|
||||
background: var(--ink);
|
||||
color: white;
|
||||
z-index: 10;
|
||||
}
|
||||
.skip-link:focus {
|
||||
top: 0.75rem;
|
||||
}
|
||||
.site-header {
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.header-inner {
|
||||
min-height: 88px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 2rem;
|
||||
}
|
||||
.brand {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 0.9rem;
|
||||
color: var(--ink);
|
||||
text-decoration: none;
|
||||
}
|
||||
.brand-name {
|
||||
font-size: 1.45rem;
|
||||
font-weight: 750;
|
||||
letter-spacing: -0.065em;
|
||||
}
|
||||
.brand-caption {
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.navigation {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.8rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.navigation a {
|
||||
color: var(--muted);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.navigation a:hover,
|
||||
.navigation a[aria-current="page"] {
|
||||
color: var(--ink);
|
||||
}
|
||||
.navigation a[aria-current="page"] {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.navigation .nav-start {
|
||||
color: var(--ink);
|
||||
}
|
||||
.eyebrow {
|
||||
margin-bottom: 1.2rem;
|
||||
font-size: 0.875rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
.hero {
|
||||
padding-block: 5.8rem 4.6rem;
|
||||
}
|
||||
.hero h1 {
|
||||
max-width: 900px;
|
||||
}
|
||||
.hero .lede {
|
||||
max-width: 710px;
|
||||
}
|
||||
.lede {
|
||||
font-size: 1.2rem;
|
||||
color: var(--muted);
|
||||
line-height: 1.7;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 1.6rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.button {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0.7rem 1.25rem;
|
||||
border: 1px solid var(--ink);
|
||||
border-radius: 5px;
|
||||
background: var(--ink);
|
||||
color: white;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 500;
|
||||
text-decoration: none;
|
||||
}
|
||||
.button:hover {
|
||||
background: #38424e;
|
||||
text-decoration: none;
|
||||
}
|
||||
.text-link {
|
||||
font-size: 0.95rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.hero-command {
|
||||
max-width: 680px;
|
||||
margin-top: 2.25rem;
|
||||
}
|
||||
.code-block {
|
||||
margin-block: 1.3rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
background: var(--soft);
|
||||
}
|
||||
.code-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
padding: 0.6rem 1rem;
|
||||
border-bottom: 1px solid var(--line);
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.copy-button {
|
||||
padding: 0.15rem 0.45rem;
|
||||
color: var(--muted);
|
||||
background: transparent;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.copy-button:hover {
|
||||
background: #e5e9ee;
|
||||
color: var(--ink);
|
||||
}
|
||||
pre {
|
||||
margin: 0;
|
||||
padding: 1.15rem;
|
||||
overflow-x: auto;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.75;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
.code-inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
padding: 0.95rem 1.1rem;
|
||||
}
|
||||
.code-inline code {
|
||||
min-width: 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.section {
|
||||
padding-block: 3.8rem;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.section-heading {
|
||||
max-width: 650px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.section-heading p {
|
||||
color: var(--muted);
|
||||
}
|
||||
.feature-case {
|
||||
display: grid;
|
||||
grid-template-columns: 1.55fr 1fr;
|
||||
gap: 4.5rem;
|
||||
align-items: start;
|
||||
}
|
||||
.feature-case p {
|
||||
max-width: 630px;
|
||||
color: var(--muted);
|
||||
}
|
||||
.case-note {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 1.5rem;
|
||||
}
|
||||
.stats dt {
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
letter-spacing: -0.04em;
|
||||
}
|
||||
.stats dd {
|
||||
margin: 0.5rem 0 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.case-stats {
|
||||
grid-template-columns: 1fr;
|
||||
margin: 0;
|
||||
padding-left: 2rem;
|
||||
border-left: 1px solid var(--line);
|
||||
}
|
||||
.case-stats > div + div {
|
||||
border-top: 1px solid var(--line);
|
||||
padding-top: 1.1rem;
|
||||
}
|
||||
.case-stats dt {
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
.workflows {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 2.8rem;
|
||||
}
|
||||
.workflows p {
|
||||
margin-bottom: 0.8rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
.workflows a {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.start-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 2rem;
|
||||
}
|
||||
.start-row h2 {
|
||||
margin-bottom: 0.65rem;
|
||||
}
|
||||
.start-row p {
|
||||
margin: 0;
|
||||
color: var(--muted);
|
||||
}
|
||||
.site-footer {
|
||||
margin-top: 1.5rem;
|
||||
padding-block: 2rem;
|
||||
border-top: 1px solid var(--line);
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.footer-inner {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
gap: 1rem 2rem;
|
||||
}
|
||||
.footer-inner p {
|
||||
margin: 0;
|
||||
}
|
||||
.footer-links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
.footer-links a {
|
||||
color: var(--muted);
|
||||
}
|
||||
.page-heading {
|
||||
padding-block: 4.3rem 2.7rem;
|
||||
}
|
||||
.page-heading h1 {
|
||||
max-width: 850px;
|
||||
font-size: clamp(2.6rem, 5.5vw, 4.25rem);
|
||||
}
|
||||
.page-heading .lede {
|
||||
max-width: 730px;
|
||||
}
|
||||
.breadcrumb {
|
||||
margin-bottom: 2rem;
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.breadcrumb a {
|
||||
color: var(--muted);
|
||||
}
|
||||
.page-meta {
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.article-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 190px minmax(0, 1fr);
|
||||
gap: 4rem;
|
||||
padding-bottom: 3.5rem;
|
||||
}
|
||||
.contents {
|
||||
align-self: start;
|
||||
position: sticky;
|
||||
top: 2rem;
|
||||
padding-top: 2.4rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.contents p {
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
margin-bottom: 0.8rem;
|
||||
}
|
||||
.contents ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.contents li + li {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
.contents a {
|
||||
color: var(--muted);
|
||||
text-decoration: none;
|
||||
}
|
||||
.contents a:hover {
|
||||
color: var(--ink);
|
||||
text-decoration: underline;
|
||||
}
|
||||
.article {
|
||||
max-width: 760px;
|
||||
min-width: 0;
|
||||
}
|
||||
.article-section {
|
||||
padding-block: 2.4rem;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.article-section h2 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
.article p,
|
||||
.article li {
|
||||
color: #414b55;
|
||||
}
|
||||
.article .stats {
|
||||
margin: 0 0 1.6rem;
|
||||
}
|
||||
.article .stats dt {
|
||||
color: var(--ink);
|
||||
}
|
||||
.article .stats dd {
|
||||
color: var(--muted);
|
||||
}
|
||||
.caption {
|
||||
font-size: 0.875rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
.explanatory-figure {
|
||||
margin: 0;
|
||||
}
|
||||
.figure-viewport {
|
||||
overflow-x: auto;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.explanatory-figure img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-width: 880px;
|
||||
height: auto;
|
||||
}
|
||||
.explanatory-figure figcaption {
|
||||
max-width: 800px;
|
||||
margin-top: 1rem;
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.explanatory-figure figcaption a {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.case-figure {
|
||||
margin-bottom: 3.2rem;
|
||||
}
|
||||
.step-selector {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
gap: 0.5rem;
|
||||
margin-block: 1.5rem 0.9rem;
|
||||
}
|
||||
.step-selector button {
|
||||
padding: 0.55rem 0.3rem;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 4px;
|
||||
background: var(--page);
|
||||
color: var(--muted);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.step-selector button span {
|
||||
font-size: 0.75rem;
|
||||
margin-right: 0.3rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.step-selector button[aria-pressed="true"] {
|
||||
border-color: var(--accent);
|
||||
background: #edf2f8;
|
||||
color: var(--accent);
|
||||
}
|
||||
.code-comparison {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0.9rem;
|
||||
}
|
||||
.code-comparison .code-block {
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
.code-comparison .code-header {
|
||||
padding-inline: 0.8rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.code-comparison pre {
|
||||
padding: 1rem 0.8rem;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.95;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.step-comparison .is-active {
|
||||
background: #dce8f6;
|
||||
color: #173a67;
|
||||
border-radius: 2px;
|
||||
box-decoration-break: clone;
|
||||
-webkit-box-decoration-break: clone;
|
||||
}
|
||||
.step-detail {
|
||||
margin-block: 1.1rem;
|
||||
padding-left: 1rem;
|
||||
border-left: 2px solid var(--accent);
|
||||
}
|
||||
.step-detail p {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.evidence-details {
|
||||
margin-block: 1.5rem;
|
||||
}
|
||||
.evidence-details summary {
|
||||
cursor: pointer;
|
||||
color: var(--accent);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
.evidence-details[open] summary {
|
||||
margin-bottom: 1.2rem;
|
||||
}
|
||||
.evidence-details h3 {
|
||||
margin-top: 1.5rem;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.evidence-table-wrap {
|
||||
overflow-x: auto;
|
||||
margin-block: 1rem;
|
||||
}
|
||||
.evidence-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.evidence-table caption {
|
||||
text-align: left;
|
||||
color: var(--muted);
|
||||
margin-bottom: 0.6rem;
|
||||
}
|
||||
.evidence-table th,
|
||||
.evidence-table td {
|
||||
text-align: left;
|
||||
padding: 0.6rem 0.7rem;
|
||||
border-bottom: 1px solid var(--line);
|
||||
}
|
||||
.rea-queries {
|
||||
margin-block: 1.5rem 1.8rem;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
counter-reset: query;
|
||||
}
|
||||
.rea-queries li {
|
||||
position: relative;
|
||||
padding: 1.2rem 0 1.2rem 2.4rem;
|
||||
border-top: 1px solid var(--line);
|
||||
counter-increment: query;
|
||||
}
|
||||
.rea-queries li + li {
|
||||
margin-top: 0;
|
||||
}
|
||||
.rea-queries li::before {
|
||||
content: counter(query, decimal-leading-zero);
|
||||
position: absolute;
|
||||
top: 1.2rem;
|
||||
left: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.rea-queries h4 {
|
||||
margin: 0 0 0.6rem;
|
||||
color: var(--ink);
|
||||
font-size: 1.05rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.rea-queries .query-call {
|
||||
margin-bottom: 0.8rem;
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.rea-query-pair {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0.9rem;
|
||||
margin-block: 0.9rem;
|
||||
}
|
||||
.rea-query-pair .code-block {
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
.rea-query-pair .code-header {
|
||||
padding-inline: 0.8rem;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
.rea-query-pair pre {
|
||||
padding: 0.8rem;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.8;
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
.rea-queries p:last-child {
|
||||
margin: 0;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.numbered-notes {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 1.75rem 0 0;
|
||||
counter-reset: note;
|
||||
}
|
||||
.numbered-notes li {
|
||||
position: relative;
|
||||
padding-left: 2.4rem;
|
||||
counter-increment: note;
|
||||
}
|
||||
.numbered-notes li + li {
|
||||
margin-top: 1.7rem;
|
||||
}
|
||||
.numbered-notes li::before {
|
||||
content: counter(note, decimal-leading-zero);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.numbered-notes h3 {
|
||||
color: var(--ink);
|
||||
}
|
||||
.verification {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 2rem;
|
||||
margin-top: 1.7rem;
|
||||
}
|
||||
.verification h3 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.verification p {
|
||||
margin: 0;
|
||||
}
|
||||
.reading-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.reading-list li {
|
||||
padding-block: 1rem;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.reading-list span {
|
||||
display: block;
|
||||
color: var(--muted);
|
||||
font-size: 0.875rem;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
.requirements {
|
||||
margin-top: 1.5rem;
|
||||
padding-bottom: 0.25rem;
|
||||
font-size: 0.9rem;
|
||||
color: var(--muted);
|
||||
}
|
||||
.prompt {
|
||||
margin: 1.2rem 0;
|
||||
padding: 1rem 1.2rem;
|
||||
background: var(--soft);
|
||||
border-left: 2px solid #97a6b7;
|
||||
}
|
||||
.prompt p {
|
||||
margin: 0;
|
||||
}
|
||||
.provider-list {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.provider {
|
||||
display: grid;
|
||||
grid-template-columns: 105px 1fr;
|
||||
gap: 1.3rem;
|
||||
padding-block: 1.2rem;
|
||||
border-top: 1px solid var(--line);
|
||||
}
|
||||
.provider h3 {
|
||||
font-size: 1rem;
|
||||
margin-top: 0.2rem;
|
||||
}
|
||||
.provider p {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.provider a {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.small-heading {
|
||||
margin-top: 1.8rem;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip-path: inset(50%);
|
||||
white-space: nowrap;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 850px) {
|
||||
.brand-caption {
|
||||
display: none;
|
||||
}
|
||||
.feature-case {
|
||||
gap: 2.4rem;
|
||||
}
|
||||
.workflows {
|
||||
gap: 1.8rem;
|
||||
}
|
||||
.article-layout {
|
||||
grid-template-columns: 150px minmax(0, 1fr);
|
||||
gap: 2rem;
|
||||
}
|
||||
.code-comparison,
|
||||
.rea-query-pair {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.container {
|
||||
width: calc(100% - 2.5rem);
|
||||
}
|
||||
.header-inner {
|
||||
min-height: 78px;
|
||||
gap: 1rem;
|
||||
}
|
||||
.navigation {
|
||||
gap: 1rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.hero {
|
||||
padding-block: 3.5rem 3rem;
|
||||
}
|
||||
.hero h1 {
|
||||
font-size: clamp(2.55rem, 10vw, 3.75rem);
|
||||
}
|
||||
.lede {
|
||||
font-size: 1.075rem;
|
||||
}
|
||||
.actions {
|
||||
gap: 1.2rem;
|
||||
}
|
||||
.section {
|
||||
padding-block: 2.6rem;
|
||||
}
|
||||
.feature-case,
|
||||
.workflows,
|
||||
.verification {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.case-stats {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
border-left: 0;
|
||||
padding: 1.5rem 0 0;
|
||||
border-top: 1px solid var(--line);
|
||||
gap: 1rem;
|
||||
}
|
||||
.case-stats > div + div {
|
||||
border: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
.stats dt {
|
||||
font-size: 1.65rem;
|
||||
}
|
||||
.stats dd {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
.start-row {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
}
|
||||
.page-heading {
|
||||
padding-block: 3rem 2rem;
|
||||
}
|
||||
.page-heading h1 {
|
||||
font-size: clamp(2.45rem, 9vw, 3.4rem);
|
||||
}
|
||||
.article-layout {
|
||||
display: block;
|
||||
}
|
||||
.contents {
|
||||
position: static;
|
||||
padding-top: 0;
|
||||
padding-bottom: 1.7rem;
|
||||
}
|
||||
.contents p {
|
||||
display: none;
|
||||
}
|
||||
.contents ul {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.65rem 1.3rem;
|
||||
}
|
||||
.contents li + li {
|
||||
margin: 0;
|
||||
}
|
||||
.article-section {
|
||||
padding-block: 2rem;
|
||||
}
|
||||
.article .stats {
|
||||
gap: 1rem;
|
||||
}
|
||||
.provider {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
.step-selector {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
pre {
|
||||
padding: 1rem;
|
||||
}
|
||||
.code-inline {
|
||||
align-items: flex-start;
|
||||
padding: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 360px) {
|
||||
.header-inner {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
gap: 0.3rem;
|
||||
padding-block: 0.65rem;
|
||||
}
|
||||
.navigation {
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.stats,
|
||||
.case-stats {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Get started — REA</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Connect REA to your coding agent or inspect a local JavaScript or Electron app from the terminal. Setup, first questions and native provider guides."
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="stylesheet" href="../assets/styles.css" />
|
||||
<script src="../assets/main.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
<header class="site-header">
|
||||
<div class="container header-inner">
|
||||
<a class="brand" href="../" aria-label="REA home"
|
||||
><span class="brand-name">REA</span
|
||||
><span class="brand-caption">Reverse Engineer Anything</span></a
|
||||
>
|
||||
<nav class="navigation" aria-label="Main navigation">
|
||||
<a href="../showcase/dx-ball/">DX-Ball</a
|
||||
><a class="nav-start" href="./" aria-current="page">Get started</a
|
||||
><a href="https://github.com/morluto/rea/tree/main/docs">Docs</a
|
||||
><a href="https://github.com/morluto/rea">GitHub</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main id="main" class="container">
|
||||
<div class="page-heading">
|
||||
<p class="breadcrumb"><a href="../">Home</a> / Get started</p>
|
||||
<h1>Start with a question.</h1>
|
||||
<p class="lede">
|
||||
Connect REA to your coding agent, or inspect a local app from your
|
||||
terminal.
|
||||
</p>
|
||||
<p class="requirements">
|
||||
You'll need Node.js 22 (22.19+), 24 (24.11+) or 26+, and npm.
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/installation.md"
|
||||
>Full installation guide</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<div class="article-layout">
|
||||
<nav class="contents" aria-label="On this page">
|
||||
<p>Choose your starting point</p>
|
||||
<ul>
|
||||
<li><a href="#agent">With your agent</a></li>
|
||||
<li><a href="#terminal">From the terminal</a></li>
|
||||
<li><a href="#native">Native binaries</a></li>
|
||||
<li><a href="#help">Getting help</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<article class="article" aria-label="REA getting started guide">
|
||||
<section class="article-section" id="agent">
|
||||
<h2>With your agent</h2>
|
||||
<p>
|
||||
Run setup to connect REA to Claude Code, Codex, Cursor or another
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/installation.md#supported-agents"
|
||||
>supported client</a
|
||||
>.
|
||||
</p>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Terminal</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="agent-setup"
|
||||
aria-label="Copy agent setup command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="agent-setup">npx rea-agents@latest setup</code></pre>
|
||||
</div>
|
||||
<p>
|
||||
Choose your client and review the setup plan. REA adds its MCP
|
||||
connection and the matching investigation skill, keeping a backup
|
||||
of existing configuration. It asks before applying the changes.
|
||||
</p>
|
||||
<p>
|
||||
Restart your client when setup finishes. Give your agent a target
|
||||
path and a specific question. For a JavaScript or Electron app,
|
||||
you might start with:
|
||||
</p>
|
||||
<blockquote class="prompt">
|
||||
<p>
|
||||
Look at <code>/absolute/path/to/app</code> and find how it
|
||||
exports data. Show the entry points, calls and dependencies
|
||||
involved, with the source locations for your findings.
|
||||
</p>
|
||||
</blockquote>
|
||||
<p>
|
||||
Replace the path with your local target. Read the findings, then
|
||||
ask a narrower follow-up about a function or connection you want
|
||||
to understand.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="terminal">
|
||||
<h2>From the terminal</h2>
|
||||
<p>
|
||||
You can start with a JavaScript or Electron application folder or
|
||||
ASAR archive. This path uses Node.js and npm and reads the app
|
||||
without running it.
|
||||
</p>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Static application analysis</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="terminal-analysis"
|
||||
aria-label="Copy JavaScript analysis command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="terminal-analysis">npx -y rea-agents@latest analyze-javascript-application \
|
||||
/absolute/path/to/app --json</code></pre>
|
||||
</div>
|
||||
<p>
|
||||
Replace the path with your extracted app directory or
|
||||
<code>.asar</code> file. On Windows, a path such as
|
||||
<code>"D:/apps/example"</code> works here.
|
||||
</p>
|
||||
<p>
|
||||
The result includes the application's identity, recovered module
|
||||
relationships and evidence locations. It also records
|
||||
relationships that remain unresolved. Use those findings to choose
|
||||
where to investigate next.
|
||||
</p>
|
||||
<p>
|
||||
If you'd like a permanent <code>rea</code> command in your shell:
|
||||
</p>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Install the CLI</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="install-cli"
|
||||
aria-label="Copy CLI installation command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="install-cli">npm install --global rea-agents</code></pre>
|
||||
</div>
|
||||
<p>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/javascript-application-workflows.md"
|
||||
>Continue with the JavaScript application guide</a
|
||||
>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="native">
|
||||
<h2>Working with native binaries</h2>
|
||||
<p>
|
||||
Choose a deep-analysis provider for your target and host. If you
|
||||
already use one of these tools, start with its connection guide.
|
||||
</p>
|
||||
<div class="provider-list">
|
||||
<div class="provider">
|
||||
<h3>Ghidra</h3>
|
||||
<div>
|
||||
<p>
|
||||
Use an existing Ghidra installation and JDK. Setup checks
|
||||
their paths and records them for your selected clients.
|
||||
</p>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/installation.md#ghidra"
|
||||
>Ghidra setup and supported hosts</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="provider">
|
||||
<h3>Hopper</h3>
|
||||
<div>
|
||||
<p>
|
||||
Connect Hopper on macOS or Linux. Setup can also install it
|
||||
after you review and approve the installation plan.
|
||||
</p>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/installation.md#hopper"
|
||||
>Hopper installation</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="provider">
|
||||
<h3>IDA</h3>
|
||||
<div>
|
||||
<p>
|
||||
Reuse an existing IDA MCP registration for read-only
|
||||
analysis through an attached GUI or headless database.
|
||||
</p>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/ida-provider.md"
|
||||
>IDA connection guide</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="small-heading">
|
||||
For an existing Ghidra setup, inspect a function with:
|
||||
</p>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Function analysis</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="native-function"
|
||||
aria-label="Copy native function analysis command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="native-function">rea function /absolute/path/to/program main \
|
||||
--provider ghidra --json</code></pre>
|
||||
</div>
|
||||
<p>
|
||||
Replace <code>main</code> with the function name or address you
|
||||
want to inspect. The first query imports and analyzes the target,
|
||||
so it can take longer than later requests.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="help">
|
||||
<h2>Getting help</h2>
|
||||
<h3>If your agent doesn't see REA</h3>
|
||||
<p>
|
||||
Restart or reconnect the client after setup. To check its
|
||||
registration, use a client-scoped report; for Codex:
|
||||
</p>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Check one client</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="client-doctor"
|
||||
aria-label="Copy client diagnosis command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="client-doctor">npx -y rea-agents@latest doctor --client codex --json</code></pre>
|
||||
</div>
|
||||
<h3 class="small-heading">If a provider needs attention</h3>
|
||||
<p>Check the provider you're using. For Ghidra:</p>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Check one provider</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="provider-doctor"
|
||||
aria-label="Copy provider diagnosis command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="provider-doctor">npx -y rea-agents@latest doctor --provider ghidra --json</code></pre>
|
||||
</div>
|
||||
<p>The report gives the failed check and a suggested next step.</p>
|
||||
<ul class="reading-list">
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/installation.md"
|
||||
>Installation and troubleshooting</a
|
||||
><span
|
||||
>Client configuration, versions and provider
|
||||
requirements.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/morluto/rea/issues">GitHub issues</a
|
||||
><span>Report a problem with the command and diagnostics.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://discord.gg/GkcryMnJDM">REA community</a
|
||||
><span>Questions, investigations and work in progress.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="container footer-inner">
|
||||
<p>REA · Reverse Engineer Anything</p>
|
||||
<div class="footer-links">
|
||||
<a href="https://github.com/morluto/rea">Source</a
|
||||
><a href="https://github.com/morluto/rea/blob/main/LICENSE"
|
||||
>MIT license</a
|
||||
><a href="https://discord.gg/GkcryMnJDM">Community</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<p class="sr-only" id="copy-status" role="status" aria-live="polite"></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,232 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>REA — Reverse Engineer Anything</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Inspect apps, binaries and runtime behavior with your coding agent or terminal. REA connects local analysis tools through CLI and MCP."
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="stylesheet" href="assets/styles.css" />
|
||||
<script src="assets/main.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
<header class="site-header">
|
||||
<div class="container header-inner">
|
||||
<a class="brand" href="./" aria-label="REA home"
|
||||
><span class="brand-name">REA</span
|
||||
><span class="brand-caption">Reverse Engineer Anything</span></a
|
||||
>
|
||||
<nav class="navigation" aria-label="Main navigation">
|
||||
<a href="showcase/dx-ball/">DX-Ball</a>
|
||||
<a class="nav-start" href="get-started/">Get started</a>
|
||||
<a href="https://github.com/morluto/rea/tree/main/docs">Docs</a>
|
||||
<a href="https://github.com/morluto/rea">GitHub</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main id="main">
|
||||
<section class="container hero">
|
||||
<p class="eyebrow">Software analysis · CLI & MCP</p>
|
||||
<h1>Find out how<br />software works.</h1>
|
||||
<p class="lede">
|
||||
REA gives your coding agent tools to inspect apps, binaries and
|
||||
runtime behavior. Ask a question, follow the code, and use what you
|
||||
learn in your own project.
|
||||
</p>
|
||||
<div class="actions">
|
||||
<a class="button" href="get-started/">Get started</a>
|
||||
<a class="text-link" href="showcase/dx-ball/"
|
||||
>Read the DX-Ball case study</a
|
||||
>
|
||||
</div>
|
||||
<div class="hero-command">
|
||||
<div class="code-block code-inline">
|
||||
<code id="setup-command">npx rea-agents@latest setup</code>
|
||||
<button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="setup-command"
|
||||
aria-label="Copy setup command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<p class="caption">
|
||||
Connects REA to your agent and installs its investigation workflow.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section" aria-label="How an investigation works">
|
||||
<div class="container">
|
||||
<figure class="explanatory-figure">
|
||||
<div
|
||||
class="figure-viewport"
|
||||
tabindex="0"
|
||||
role="region"
|
||||
aria-label="REA investigation flow; scroll horizontally on smaller screens"
|
||||
>
|
||||
<img
|
||||
src="assets/figures/rea-investigation-flow.svg"
|
||||
width="1774"
|
||||
height="887"
|
||||
alt="Ask a question about a local app, binary or browser. Your agent uses REA through CLI or MCP to inspect and trace with analysis tools. REA returns code, references and unknowns. Your agent uses the evidence to explain, implement and test, and can ask follow-up questions."
|
||||
decoding="async"
|
||||
/>
|
||||
</div>
|
||||
<figcaption>
|
||||
REA connects your agent to analysis tools. The findings guide the
|
||||
next question, explanation or implementation.
|
||||
<a href="assets/figures/rea-investigation-flow.svg"
|
||||
>Open figure</a
|
||||
>
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container feature-case">
|
||||
<div>
|
||||
<p class="eyebrow">Case study</p>
|
||||
<h2>Rebuilding DX-Ball</h2>
|
||||
<p>
|
||||
DX-Ball is a 1996 Windows game. The project is reconstructing it
|
||||
in C, using REA to inspect the executable and independent tests to
|
||||
check the recovered behavior.
|
||||
</p>
|
||||
<p>
|
||||
To recover a sound-pan calculation, the agent used REA to inspect
|
||||
the instructions, follow a caller and read the constants. Those
|
||||
findings led to a C function checked against the original behavior
|
||||
and all 63 compiled bytes.
|
||||
</p>
|
||||
<p>
|
||||
<a class="text-link" href="showcase/dx-ball/"
|
||||
>Follow the investigation</a
|
||||
>
|
||||
</p>
|
||||
<p class="case-note">
|
||||
Work so far covers boards, resources, brick hits, animations,
|
||||
particles and bonus production. The playable game is still in
|
||||
progress.
|
||||
</p>
|
||||
</div>
|
||||
<dl class="stats case-stats">
|
||||
<div>
|
||||
<dt>55</dt>
|
||||
<dd>functions in maintained C</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>45,380</dt>
|
||||
<dd>original-x86 differential cases</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>33</dt>
|
||||
<dd>complete functions with matching compiled bytes</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="section-heading">
|
||||
<h2>Bring a target. Ask a question.</h2>
|
||||
<p>
|
||||
Start with a local app or file, then narrow the investigation to
|
||||
the feature or behavior you want to understand.
|
||||
</p>
|
||||
</div>
|
||||
<div class="workflows">
|
||||
<div>
|
||||
<h3>Native applications</h3>
|
||||
<p>
|
||||
Inspect functions, strings, references and call relationships in
|
||||
executables and libraries.
|
||||
</p>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/native-investigation.md"
|
||||
>Native analysis guide</a
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<h3>JavaScript & Electron</h3>
|
||||
<p>
|
||||
Map modules, routes, IPC and native dependencies from an
|
||||
application folder or ASAR archive.
|
||||
</p>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/javascript-application-workflows.md"
|
||||
>Application workflows</a
|
||||
>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Runtime behavior</h3>
|
||||
<p>
|
||||
Capture selected browser or process activity, then compare the
|
||||
results across runs.
|
||||
</p>
|
||||
<a
|
||||
href="https://github.com/morluto/rea/blob/main/docs/browser-observation.md"
|
||||
>Browser observation guide</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container feature-case">
|
||||
<div>
|
||||
<h2>Keep the investigation in your workflow.</h2>
|
||||
<p>
|
||||
Use REA from your terminal or through your agent's MCP connection.
|
||||
Analysis runs locally, and results include the source locations,
|
||||
evidence and open questions you need to continue.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Use your analysis tools</h3>
|
||||
<p>
|
||||
Connect a local analysis provider for native binaries. Static
|
||||
JavaScript analysis runs with Node.js and npm.
|
||||
</p>
|
||||
<a class="text-link" href="get-started/#native"
|
||||
>Choose a native provider</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container start-row">
|
||||
<div>
|
||||
<h2>What would you like to understand?</h2>
|
||||
<p>
|
||||
Connect your agent, or get your first result from the terminal.
|
||||
</p>
|
||||
</div>
|
||||
<a class="button" href="get-started/">Get started</a>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="container footer-inner">
|
||||
<p>REA · Reverse Engineer Anything</p>
|
||||
<div class="footer-links">
|
||||
<a href="https://github.com/morluto/rea">Source</a
|
||||
><a href="https://github.com/morluto/rea/blob/main/LICENSE"
|
||||
>MIT license</a
|
||||
><a href="https://discord.gg/GkcryMnJDM">Community</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<p class="sr-only" id="copy-status" role="status" aria-live="polite"></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,607 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Rebuilding DX-Ball — REA</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Follow a DX-Ball reconstruction from binary analysis through REA to maintained C, original-x86 tests and matching compiled function bytes."
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<link rel="icon" href="../../assets/favicon.svg" type="image/svg+xml" />
|
||||
<link rel="stylesheet" href="../../assets/styles.css" />
|
||||
<script src="../../assets/main.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<a class="skip-link" href="#main">Skip to content</a>
|
||||
<header class="site-header">
|
||||
<div class="container header-inner">
|
||||
<a class="brand" href="../../" aria-label="REA home"
|
||||
><span class="brand-name">REA</span
|
||||
><span class="brand-caption">Reverse Engineer Anything</span></a
|
||||
>
|
||||
<nav class="navigation" aria-label="Main navigation">
|
||||
<a href="./" aria-current="page">DX-Ball</a>
|
||||
<a class="nav-start" href="../../get-started/">Get started</a>
|
||||
<a href="https://github.com/morluto/rea/tree/main/docs">Docs</a>
|
||||
<a href="https://github.com/morluto/rea">GitHub</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<main id="main" class="container">
|
||||
<div class="page-heading">
|
||||
<p class="breadcrumb"><a href="../../">Home</a> / DX-Ball</p>
|
||||
<p class="eyebrow">Case study · DX-Ball 1.07</p>
|
||||
<h1>Rebuilding DX-Ball<br />from its executable.</h1>
|
||||
<p class="lede">
|
||||
The goal is a maintainable C version of the 1996 Windows game. REA
|
||||
helps the agent inspect the original, one function at a time.
|
||||
</p>
|
||||
<p class="page-meta">Windows i386 · C · REA</p>
|
||||
</div>
|
||||
<figure class="explanatory-figure case-figure">
|
||||
<div
|
||||
class="figure-viewport"
|
||||
tabindex="0"
|
||||
role="region"
|
||||
aria-label="DX-Ball sound-pan investigation; scroll horizontally on smaller screens"
|
||||
>
|
||||
<img
|
||||
src="../../assets/figures/dx-ball-sound-pan-investigation.svg"
|
||||
width="1774"
|
||||
height="887"
|
||||
alt="DXBALL.EXE function 0x00406400 is inspected with REA. A brick-hit caller supplies 20 plus 30 times tile_x. Instructions load x, multiply by 1.5625, subtract 500.0, apply pan_scale and return an integer. The maintained C is checked independently against the original x86 in 3,205 cases and by VC4.0 compiler replay matching 63 bytes."
|
||||
decoding="async"
|
||||
/>
|
||||
</div>
|
||||
<figcaption>
|
||||
One function, from executable to checked C. REA supplies the
|
||||
instructions, callers and data reads; the reconstruction project
|
||||
implements and tests the result.
|
||||
<a href="../../assets/figures/dx-ball-sound-pan-investigation.svg"
|
||||
>Open figure</a
|
||||
>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<div class="article-layout">
|
||||
<nav class="contents" aria-label="On this page">
|
||||
<p>In this case study</p>
|
||||
<ul>
|
||||
<li><a href="#progress">The project</a></li>
|
||||
<li><a href="#sound-pan">Sound pan</a></li>
|
||||
<li><a href="#checking">Checking the result</a></li>
|
||||
<li><a href="#continue">Continue the work</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<article class="article" aria-label="DX-Ball reconstruction case study">
|
||||
<section class="article-section" id="progress">
|
||||
<dl class="stats">
|
||||
<div>
|
||||
<dt>55</dt>
|
||||
<dd>maintained C functions</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>45,380</dt>
|
||||
<dd>original-x86 differential cases</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>33</dt>
|
||||
<dd>byte-exact functions</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<p class="caption">
|
||||
Project checkpoint: 7 October 2026.
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/PROGRESS.md"
|
||||
>Progress ledger</a
|
||||
>
|
||||
·
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ORACLES.md"
|
||||
>Test coverage</a
|
||||
>
|
||||
</p>
|
||||
<h2>The project so far</h2>
|
||||
<p>
|
||||
The recovered code covers board and resource handling, brick hits,
|
||||
animations, particles and bonus production. Current builds provide
|
||||
inspection utilities and an analysis library. Work on the playable
|
||||
game continues with ball and paddle physics, power-up handling and
|
||||
Windows integration.
|
||||
</p>
|
||||
<p>
|
||||
The analysis starts from the DX-Ball 1.07 executable. REA returns
|
||||
function code, instructions, callers and state references. These
|
||||
findings guide the C implementation; execution of the original x86
|
||||
functions and compiler replay check the result.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="sound-pan">
|
||||
<h2>Finding the sound-pan calculation</h2>
|
||||
<p>
|
||||
When a brick is hit, its horizontal position is passed to the
|
||||
sound code. The investigation needed to recover how that screen
|
||||
coordinate becomes a left/right panning value.
|
||||
</p>
|
||||
<p>
|
||||
The agent used REA to inspect the function, follow its brick-hit
|
||||
caller and read the constants from the executable. Those results
|
||||
supplied the input and arithmetic needed to write the C function
|
||||
below.
|
||||
</p>
|
||||
<p>
|
||||
The first function result for <code>0x406400</code> included
|
||||
pseudocode declaring <code>FUN_00406400(void)</code> and calling
|
||||
<code>__ftol()</code>. Its instruction view showed a stack input
|
||||
and floating-point operations. That discrepancy gave the agent a
|
||||
concrete reason to keep investigating.
|
||||
</p>
|
||||
<details class="evidence-details">
|
||||
<summary>The first decompiler view</summary>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA result · pseudocode excerpt</span>
|
||||
</div>
|
||||
<pre><code>longlong FUN_00406400(void)
|
||||
{
|
||||
longlong lVar1;
|
||||
|
||||
lVar1 = __ftol();
|
||||
return lVar1;
|
||||
}</code></pre>
|
||||
</div>
|
||||
<p>
|
||||
The output shows a conversion call. Reading the instructions
|
||||
below reveals the input and the calculation feeding that call.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<h3 class="small-heading">Three questions answered through REA</h3>
|
||||
<ol class="rea-queries">
|
||||
<li>
|
||||
<h4>Recover the missing input</h4>
|
||||
<div class="rea-query-pair">
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Agent → REA · <code>analyze_function</code></span>
|
||||
</div>
|
||||
<pre><code>{"procedure": "0x406400"}</code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA → agent · instruction excerpt</span>
|
||||
</div>
|
||||
<pre><code>0x406409: MOV EAX, dword ptr [EBP + 0x8]
|
||||
0x40640c: MOV dword ptr [EBP + -0xc], EAX
|
||||
0x40640f: FILD dword ptr [EBP + -0xc]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
The function result includes instructions alongside pseudocode
|
||||
and callers. Here, <code>[EBP+8]</code> exposes the integer
|
||||
input missing from the decompiler view.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<h4>Follow the caller to understand the input</h4>
|
||||
<div class="rea-query-pair">
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Agent → REA · <code>analyze_function</code></span>
|
||||
</div>
|
||||
<pre><code>{"procedure": "0x411f40"}</code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA → agent · caller excerpt</span>
|
||||
</div>
|
||||
<pre><code>0x411f5b: ADD EAX, 0x14
|
||||
0x411f5e: PUSH EAX
|
||||
0x411f5f: CALL 0x00406400</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
REA identified this caller in the first result. Its preceding
|
||||
instructions scale <code>tile_x</code> by 30; adding 20 gives
|
||||
the brick's screen coordinate, <code>20 + 30 × tile_x</code>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<h4>Read the values behind the memory addresses</h4>
|
||||
<div class="rea-query-pair">
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span
|
||||
>Agent → REA · two
|
||||
<code>read_bytes</code> requests</span
|
||||
>
|
||||
</div>
|
||||
<pre><code>{"address": "0x420068", "length": 16}
|
||||
{"address": "0x4210a0", "length": 8}</code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA byte results · decoded as doubles</span>
|
||||
</div>
|
||||
<pre><code>000000000000f93f → 1.5625
|
||||
0000000000407f40 → 500.0
|
||||
000000000000f03f → 1.0</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
The returned bytes establish the two arithmetic constants and
|
||||
initial pan scale. The agent now has the values needed for the
|
||||
C expression.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
<p>
|
||||
REA exposes these operations through CLI and MCP, with target
|
||||
identity and Evidence IDs in the results. The agent can follow up
|
||||
on a caller or data address directly, then use the findings to
|
||||
write maintained C.
|
||||
</p>
|
||||
|
||||
<h3 class="small-heading">From REA's findings to C</h3>
|
||||
<p>
|
||||
Follow the five steps below. Each selection highlights the
|
||||
original instructions and the C lines they informed.
|
||||
</p>
|
||||
<div class="step-comparison" data-step-comparison>
|
||||
<div
|
||||
class="step-selector"
|
||||
role="group"
|
||||
aria-label="Follow the sound-pan calculation"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="1"
|
||||
aria-pressed="true"
|
||||
aria-controls="pan-assembly pan-source pan-step-detail"
|
||||
>
|
||||
<span>01</span> Input
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="2"
|
||||
aria-pressed="false"
|
||||
aria-controls="pan-assembly pan-source pan-step-detail"
|
||||
>
|
||||
<span>02</span> Multiply
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="3"
|
||||
aria-pressed="false"
|
||||
aria-controls="pan-assembly pan-source pan-step-detail"
|
||||
>
|
||||
<span>03</span> Subtract
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="4"
|
||||
aria-pressed="false"
|
||||
aria-controls="pan-assembly pan-source pan-step-detail"
|
||||
>
|
||||
<span>04</span> Scale
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="5"
|
||||
aria-pressed="false"
|
||||
aria-controls="pan-assembly pan-source pan-step-detail"
|
||||
>
|
||||
<span>05</span> Return
|
||||
</button>
|
||||
</div>
|
||||
<div class="code-comparison">
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Original x86 · excerpt</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="pan-assembly"
|
||||
aria-label="Copy original assembly excerpt"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="pan-assembly"><span class="code-step is-active" data-step="1">0x406409: MOV EAX, dword ptr [EBP + 0x8]
|
||||
0x40640c: MOV dword ptr [EBP + -0xc], EAX
|
||||
0x40640f: FILD dword ptr [EBP + -0xc]</span>
|
||||
<span class="code-step" data-step="2">0x406415: FMUL double ptr [0x00420068]</span>
|
||||
<span class="code-step" data-step="3">0x40641e: FSUB double ptr [0x00420070]</span>
|
||||
<span class="code-step" data-step="4">0x406427: FMUL double ptr [0x004210a0]</span>
|
||||
<span class="code-step" data-step="5">0x406430: CALL 0x0041678c
|
||||
0x40643e: RET</span></code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Reconstructed C</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="pan-source"
|
||||
aria-label="Copy sound-pan function"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="pan-source">DxBallInt dxball_screen_pan(<span class="is-active" data-step="1">DxBallInt x</span>)
|
||||
{
|
||||
double pan;
|
||||
<span class="code-step is-active" data-step="1"> pan = (double)x;</span>
|
||||
<span class="code-step" data-step="2"> pan = pan * 1.5625;</span>
|
||||
<span class="code-step" data-step="3"> pan = pan - 500.0;</span>
|
||||
<span class="code-step" data-step="4"> pan = pan * dxball_pan_scale;</span>
|
||||
<span class="code-step" data-step="5"> return (DxBallInt)pan;</span>
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="step-detail"
|
||||
id="pan-step-detail"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>
|
||||
<p data-step-note="1">
|
||||
<strong>01 · Read the input.</strong>
|
||||
The instruction view in REA's function result reads
|
||||
<code>[EBP+8]</code> and uses <code>FILD</code> to load the
|
||||
integer. Following its caller through REA establishes the
|
||||
screen-coordinate meaning of the C parameter <code>x</code>.
|
||||
</p>
|
||||
<p data-step-note="2" hidden>
|
||||
<strong>02 · Multiply by 1.5625.</strong>
|
||||
<code>FMUL</code> reads the double at <code>0x420068</code>.
|
||||
The bytes returned by REA's <code>read_bytes</code> decode to
|
||||
<code>1.5625</code>; the C uses the same constant.
|
||||
</p>
|
||||
<p data-step-note="3" hidden>
|
||||
<strong>03 · Subtract 500.0.</strong> <code>FSUB</code> reads
|
||||
the double at <code>0x420070</code>. REA's byte result decodes
|
||||
to <code>500.0</code>, shifting the calculation's center to
|
||||
screen coordinate <code>320</code>.
|
||||
</p>
|
||||
<p data-step-note="4" hidden>
|
||||
<strong>04 · Apply the stored scale.</strong> The second
|
||||
<code>FMUL</code> reads <code>0x4210a0</code>. That global is
|
||||
named <code>dxball_pan_scale</code> in the maintained source.
|
||||
REA's second byte read establishes its initial value of
|
||||
<code>1.0</code>.
|
||||
</p>
|
||||
<p data-step-note="5" hidden>
|
||||
<strong>05 · Return an integer.</strong> The call at
|
||||
<code>0x406430</code> reaches <code>__ftol</code>, identified
|
||||
in REA's callee results. The C casts the result to
|
||||
<code>DxBallInt</code>; original-x86 comparisons check the
|
||||
returned value.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="caption">
|
||||
The assembly excerpt selects the input, arithmetic and return
|
||||
instructions. The full listing below also includes the intervening
|
||||
stores and function setup and cleanup.
|
||||
</p>
|
||||
<details class="evidence-details">
|
||||
<summary>Full assembly and supporting evidence</summary>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA result · 0x406400–0x40643e</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="pan-assembly-full"
|
||||
aria-label="Copy complete sound-pan assembly"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="pan-assembly-full">0x406400: PUSH EBP
|
||||
0x406401: MOV EBP, ESP
|
||||
0x406403: SUB ESP, 0xc
|
||||
0x406406: PUSH EBX
|
||||
0x406407: PUSH ESI
|
||||
0x406408: PUSH EDI
|
||||
0x406409: MOV EAX, dword ptr [EBP + 0x8]
|
||||
0x40640c: MOV dword ptr [EBP + -0xc], EAX
|
||||
0x40640f: FILD dword ptr [EBP + -0xc]
|
||||
0x406412: FST double ptr [EBP + -0x8]
|
||||
0x406415: FMUL double ptr [0x00420068]
|
||||
0x40641b: FST double ptr [EBP + -0x8]
|
||||
0x40641e: FSUB double ptr [0x00420070]
|
||||
0x406424: FST double ptr [EBP + -0x8]
|
||||
0x406427: FMUL double ptr [0x004210a0]
|
||||
0x40642d: FST double ptr [EBP + -0x8]
|
||||
0x406430: CALL 0x0041678c
|
||||
0x406435: JMP 0x0040643a
|
||||
0x40643a: POP EDI
|
||||
0x40643b: POP ESI
|
||||
0x40643c: POP EBX
|
||||
0x40643d: LEAVE
|
||||
0x40643e: RET</code></pre>
|
||||
</div>
|
||||
<h3>What the caller supplies</h3>
|
||||
<p>
|
||||
The brick-hit function at <code>0x411f40</code> scales its tile
|
||||
coordinate by 30, adds 20, then pushes it before the call:
|
||||
</p>
|
||||
<div class="code-block">
|
||||
<pre><code>0x411f50: MOV EAX, dword ptr [EBP + 0x8]
|
||||
0x411f53: ADD EAX, EAX
|
||||
0x411f55: LEA EAX, [EAX + EAX*0x2]
|
||||
0x411f58: LEA EAX, [EAX + EAX*0x4]
|
||||
0x411f5b: ADD EAX, 0x14
|
||||
0x411f5e: PUSH EAX
|
||||
0x411f5f: CALL 0x00406400
|
||||
0x411f64: ADD ESP, 0x4</code></pre>
|
||||
</div>
|
||||
<h3>What the data reads establish</h3>
|
||||
<div class="evidence-table-wrap">
|
||||
<table class="evidence-table">
|
||||
<caption>
|
||||
REA byte reads, decoded as little-endian doubles
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Address</th>
|
||||
<th scope="col">Value</th>
|
||||
<th scope="col">Used for</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>0x420068</code></td>
|
||||
<td><code>1.5625</code></td>
|
||||
<td>First multiplication</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x420070</code></td>
|
||||
<td><code>500.0</code></td>
|
||||
<td>Subtraction</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>0x4210a0</code></td>
|
||||
<td><code>1.0</code> initially</td>
|
||||
<td>Stored pan scale</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="caption">
|
||||
Recorded with REA 4.1.0 for the hash-pinned DX-Ball 1.07 target.
|
||||
The linked investigation notes retain the Evidence IDs.
|
||||
</p>
|
||||
</details>
|
||||
<p class="caption">
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/src/gameplay.c#L41"
|
||||
>Maintained source</a
|
||||
>
|
||||
·
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/GAMEPLAY_OWNER.md"
|
||||
>Investigation notes and evidence references</a
|
||||
>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="checking">
|
||||
<h2>Checking the recovered function</h2>
|
||||
<p>
|
||||
The input, caller context and constant values returned through REA
|
||||
guided the maintained C implementation. The project then checked
|
||||
it against the original x86 function and the pinned compiler. For
|
||||
this function, both checks pass.
|
||||
</p>
|
||||
<div class="verification">
|
||||
<div>
|
||||
<h3>3,205 behavior cases</h3>
|
||||
<p>
|
||||
The tests execute the original x86 function and compare its
|
||||
return value with the maintained C. They cover every integer
|
||||
position from 0 to 640 at five pan scales: 0, 0.5, 1, 20 and
|
||||
−1.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>63 matching bytes</h3>
|
||||
<p>
|
||||
The C function is compiled with the pinned VC4.0 toolchain.
|
||||
Compiler replay matches the complete function after applying
|
||||
the reviewed relocations and checking the referenced
|
||||
constants.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="small-heading">
|
||||
At a scale of 1, the recovered calculation returns −500 at the
|
||||
left edge, 0 at the center and 500 at the right edge. The next
|
||||
part of the audio work is integrating that value with the game's
|
||||
sound backend.
|
||||
</p>
|
||||
<p>
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/BUILD_MATCHING.md"
|
||||
>Read the compiler replay details</a
|
||||
>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="continue">
|
||||
<h2>Continue the investigation</h2>
|
||||
<p>
|
||||
The same approach is being used for particle updates, explosion
|
||||
queues and bonus generation: inspect the relevant functions,
|
||||
recover their state and dependencies, then compare the
|
||||
implementation with the original.
|
||||
</p>
|
||||
<p>
|
||||
To inspect the sound-pan function yourself, follow the DX-Ball
|
||||
project's setup instructions and supply its matching original
|
||||
target. Then run:
|
||||
</p>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>In the DX-Ball checkout</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="pan-command"
|
||||
aria-label="Copy DX-Ball analysis command"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="pan-command">scripts/rea function original/DXBALL.EXE 0x00406400 \
|
||||
--snapshot .analysis/rea/dxball.snapshot.json --json</code></pre>
|
||||
</div>
|
||||
<ul class="reading-list">
|
||||
<li>
|
||||
<a href="https://github.com/N0zoM1z0/dx-ball"
|
||||
>DX-Ball repository</a
|
||||
><span>Current source, progress and local setup.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/REA.md"
|
||||
>REA analysis workflow</a
|
||||
><span>Pinned tools, MCP sessions and retained evidence.</span>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/dx-ball/blob/a55dca27ec0a07018c1b2c95ae2be027f7d8c3c4/docs/ENTITIES_OWNER.md"
|
||||
>Particles and bonus production</a
|
||||
><span
|
||||
>A larger investigation into state, queues and pixel
|
||||
writes.</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="actions">
|
||||
<a class="button" href="../../get-started/"
|
||||
>Start with your own target</a
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="site-footer">
|
||||
<div class="container footer-inner">
|
||||
<p>REA · Reverse Engineer Anything</p>
|
||||
<div class="footer-links">
|
||||
<a href="https://github.com/morluto/rea">Source</a
|
||||
><a href="https://github.com/morluto/rea/blob/main/LICENSE"
|
||||
>MIT license</a
|
||||
><a href="https://discord.gg/GkcryMnJDM">Community</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<p class="sr-only" id="copy-status" role="status" aria-live="polite"></p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user