docs(website): add TH04 bullet-ring case study
Adds a TH04 case study showing how its original 16-bit PC-98 DOS code spaces a bullet ring and aims it at the player. Fresh REA instructions are paired with a five-step C++ comparison and a ring diagram; homepage and showcase-index entries link to the new page and the requested reconstruction repository. The page credits TH04's maintained source and recorded compiler checks separately from the new REA inspection. Public provenance pins the target, source checkpoint and evidence. No original game assets, executables, private paths or raw result bundles are included. Pages remains manually dispatched. Validation: - Website verifier: 12 HTML pages, 185 local references, SVG XML and downloadable ZIP. - Browser: root and `/rea/`, 32 copy checks, five comparison steps, eight viewport widths, keyboard, reduced motion and no-JavaScript content. - Fresh real Ghidra verification through published REA 4.1.0: DOS load image verified, all 84 checks match; shown instructions match the function dossier. No Hopper verification was needed or run. - Independent claims/privacy reviews passed; seven immutable public source links match the local TH04 checkpoint. - `npm run check:fast`. The two clean compiler replays and 2,139 matching bytes are recorded TH04 checks, reviewed against their retained receipt and source hashes; the website update does not rerun the compiler or game.
This commit is contained in:
1 parent
33d4761cc7
commit
f8d84da127
8 files changed
+955
-3
No files matched your search
+11
-1
@@ -1,6 +1,6 @@
|
||||
# REA website
|
||||
|
||||
An English static website with explanatory figures, worked guides and DX-Ball and Notion investigations.
|
||||
An English static website with explanatory figures, worked guides and DX-Ball, Notion and TH04 investigations.
|
||||
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. Python
|
||||
packages the downloadable example; there is no frontend bundler or npm dependency.
|
||||
@@ -22,6 +22,7 @@ Open <http://127.0.0.1:4173/>. Refresh the browser after editing a file.
|
||||
- `public/showcase/index.html`: the case-study index.
|
||||
- `public/showcase/dx-ball/index.html`: sound-pan investigation and project status.
|
||||
- `public/showcase/notion/index.html`: Notion's Electron clipboard bridge and rich clipboard format.
|
||||
- `public/showcase/th04/index.html`: TH04's 16-bit DOS bullet-angle calculation and compiler checks.
|
||||
- `public/get-started/index.html`: agent setup, first CLI result and provider guides.
|
||||
- `public/guides/`: a guide hub and native, JavaScript/Electron and browser examples.
|
||||
- `public/examples/`: downloadable Electron source and an interactive Notes browser app.
|
||||
@@ -84,6 +85,15 @@ the website.
|
||||
[evidence/notion-clipboard.md](evidence/notion-clipboard.md) records the REA
|
||||
package version, selected findings, source anchors and module-probe scope.
|
||||
|
||||
## TH04 case study
|
||||
|
||||
The TH04 case inspects the original PC-98 DOS angle helper through REA 4.1.0.
|
||||
Its selected instructions are paired with readable C++ and a source SVG of
|
||||
fixed and aimed rings. [evidence/th04-bullet-ring.md](evidence/th04-bullet-ring.md)
|
||||
records the fresh load-image/function evidence and separately credited TH04
|
||||
source and historical compiler replay. The figure illustrates the calculation;
|
||||
original game assets and executable bytes are not website downloads.
|
||||
|
||||
## GitHub Pages
|
||||
|
||||
`.github/workflows/website-pages.yml` prepares and deploys only `website/public`.
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
# TH04 aimed-ring evidence
|
||||
|
||||
This case examines one helper in the Japanese PC-98 DOS TH04 (Lotus Land Story)
|
||||
reconstruction. Source and historical compiler checks are pinned to
|
||||
`0d72e9801a5c14c10384efcbb6734ceccb74ee63` in
|
||||
[N0zoM1z0/th04](https://github.com/N0zoM1z0/th04). The page adds a fresh inspection
|
||||
of the supplied original target through REA on 7 October 2026.
|
||||
|
||||
## Original target and analysis
|
||||
|
||||
- Target: `MAIN.EXE`, 156,258 bytes, DOS MZ, x86 real mode.
|
||||
- SHA-256: `077440a3c4e9ab52e72e9bae411276c47edc11995b5c2b83dfc83fbc039dc58b`.
|
||||
- Header: 6,144 bytes (`0x1800`); module: 150,114 bytes; relocations: 1,136.
|
||||
- Connected analysis: published REA 4.1.0, Ghidra 12.1.4, Linux x64.
|
||||
- The connected runtime's 761 files under `dist`, `bridge` and `scripts` match
|
||||
the cached published REA 4.1.0 package byte for byte.
|
||||
- Load-image profile: `MzLoader`, `x86:LE:16:Real Mode`, compiler `default`,
|
||||
fixed load segment `0x1000`, linear byte addresses.
|
||||
- Profile digest: `0d7ec8473c44e8d0a979c0308f7260b7572866613a369c30550026c81beff0e9`.
|
||||
- Helper: `bullet_velocity_and_angle_set`, REA entry `0x2cfc8`, original
|
||||
file offset `0x1e7c8` (124,872).
|
||||
|
||||
The executable's identity passes the reconstruction manifest and MZ checks. Its
|
||||
manifest provenance is `candidate-local-attested`; no independent pristine-dump
|
||||
claim is added. Windows is an emulator or port host here, not this executable's
|
||||
format.
|
||||
|
||||
## Fresh REA requests
|
||||
|
||||
1. `open_binary` binds the original target with provider `ghidra`. The displayed
|
||||
input is compact: its local path is shortened to `MAIN.EXE` and the explicit
|
||||
provider selection is omitted from the product narrative.
|
||||
2. `inspect_native_load_image {}` returns `status: verified`, header 6,144,
|
||||
module 150,114, and load segment 4,096. Every returned check matches.
|
||||
Evidence: `ev_dc53b8af38910ed3dc40b29dc003110b79842957d6f8ab7da8737847a4b4d3fb`.
|
||||
3. `analyze_function {"procedure":"0x2cfc8"}` returns instructions, pseudocode,
|
||||
callers, callees, data references and complete reported function-body ranges.
|
||||
Evidence: `ev_d79b6834ff615b5b59df1e31f3ba01c32491582ddfd4f9383c6f05d83b59f77d`.
|
||||
4. `address_to_file_offset {"address":"0x2cfc8"}` returns original file offset
|
||||
124,872. Evidence:
|
||||
`ev_aae51edacb1a224d1b52ecccc4c43f506f28b3216f255d05fb07efdfaf10eb4b`.
|
||||
5. `read_bytes {"address":"0x2d0eb","length":19}` returns all 19 requested
|
||||
bytes: `8bc6c1e0088a16af53b60052995bf7fb8946fe`. They match the original
|
||||
target at file `0x1e8eb`. Evidence:
|
||||
`ev_d984b3df53cc8cd63c0b7bdfdf8822d84f0ea594c3c10c00419ed9f8d4036108`.
|
||||
|
||||
The selected helper comes from the project's reviewed source boundary. The
|
||||
example prompt is an invitation to the reader's agent, not a transcript or a
|
||||
claim that this inspection independently discovered every source owner.
|
||||
The ephemeral REA session was closed after these queries. The original
|
||||
executable and the reconstruction's saved database were not modified.
|
||||
|
||||
The returned function body is noncontiguous: `0x2cfc8..0x2d14f` and
|
||||
`0x2d15e..0x2d1cc`, 503 body bytes across a 517-byte enclosing span. The page's
|
||||
selected ring, aim and store instructions lie within those reported ranges.
|
||||
The historical project reconciles the omitted 14 bytes with raw decoding and
|
||||
reviewed compiler ownership; the page does not claim REA reported a contiguous
|
||||
517-byte body.
|
||||
|
||||
## Instructions and source meaning
|
||||
|
||||
| REA instruction evidence | Meaning supported by the maintained source |
|
||||
| ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- |
|
||||
| `0x2cfcf: MOV SI, word ptr [BP + 0x4]` | Group-member index |
|
||||
| `0x2d0ed: SHL AX, 0x8` followed by count load and `IDIV BX` | `(index * 256) / count`, multiplication before integer division |
|
||||
| Coordinate loads/subtractions at `0x2d18d..0x2d198`, far call at `0x2d19d`, then addition at `0x2d1a2` | Add `iatan2(player - origin)` for an aimed ring |
|
||||
| `0x2d1bc: ADD AL, byte ptr [0x53ad]` | Add template rotation |
|
||||
| `0x2d1c0: MOV [0xbcc8], AL` | Store the final byte angle, wrapping at 256 |
|
||||
|
||||
Assembly is transcribed verbatim from the fresh REA result. Short request/result
|
||||
panels select instructions, while the five-step comparison retains the complete
|
||||
19-byte ring quotient sequence. The names `count`, player/origin fields,
|
||||
`iatan2`, template rotation and spawn angle come from the maintained source and
|
||||
reviewed original reconstruction, not recovered original symbols.
|
||||
|
||||
The readable `aimed_ring_angle` function is explanatory C++, not the
|
||||
compiler-sensitive complete helper or the source compiled by historical checks.
|
||||
The ring macro display expands its TH04 branch and removes preprocessor
|
||||
continuations for reading. The source labels and details distinguish those
|
||||
summaries from linked complete source.
|
||||
|
||||
Real-mode near-call segment aliases can produce misleading static call edges.
|
||||
The case uses instruction/data anchors and the project's reviewed source
|
||||
relationships, not a claim of automatically verified whole-program call flow.
|
||||
|
||||
## Figure
|
||||
|
||||
The SVG draws sixteen directions using `index * 256 / 16`. The left ring has
|
||||
zero aim, zero rotation; the right adds illustrative player direction 40 and
|
||||
keeps zero rotation. The clockwise coordinates match the source's byte-angle
|
||||
contract: right 0, down 64, left 128, up 192. The highlighted first ray points
|
||||
at the illustrated player; every subsequent ray retains the same 16-unit step.
|
||||
This is a mathematical diagram, not captured game output.
|
||||
|
||||
Elly's real source initially requests `BG_RING_AIMED`, count 16 and angle 0,
|
||||
then calls `bullet_template_tune`. The page preserves that tuning call and
|
||||
labels the figure's count explicitly; it does not claim every difficulty or
|
||||
performance state emits sixteen bullets.
|
||||
|
||||
## Recorded compiler validation
|
||||
|
||||
The linked semantic-bullet note records two isolated cold builds on
|
||||
3 October 2026 of owner `th04-main-module-th04-bullet-a-cpp-1cc33`, using the
|
||||
pinned Turbo C++ 4.0J/TASM/TLINK toolchain. Both reproduce the complete
|
||||
2,139-byte (`0x85b`) original extent starting at file `0x1e433`, plus exact MAP
|
||||
contribution and overlapping relocation. Target and candidate slice SHA-256:
|
||||
`f7dfaeae5b18749d6687a94139488a825f86f00b85a4eb4072985223a5f1cc5e`.
|
||||
|
||||
The retained receipt was read from the project's archive into private scratch
|
||||
storage. Receipt SHA-256:
|
||||
`76a361da712d8203f410068df0a864192ecdb64671e173ea15db358796b71e49`.
|
||||
Its digest matches the archive manifest. It reports `pass: true`, no failures,
|
||||
and both builds have `raw_exact`, `map_exact`, `relocations_exact` and
|
||||
`object_valid` true. Recorded input snapshots match the current `add.cpp`,
|
||||
`add_impl.hpp` and `types.hpp` bytes. No fresh compiler build or ledger
|
||||
promotion was needed for the website update.
|
||||
|
||||
Public evidence reference: `ev-th04-semantic-bullet-exact-v1236` in the TH04
|
||||
evidence ledger. The matching extent contains the full helper and surrounding
|
||||
bullet-add functions; it is not a whole-executable or full-game equivalence
|
||||
claim. The original reconstruction used project-specific analysis and replay
|
||||
scripts. Its source and compiler evidence are credited separately from the
|
||||
fresh REA inspection.
|
||||
|
||||
## Public source anchors
|
||||
|
||||
- [Ring macro](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add_impl.hpp#L4).
|
||||
- [Complete angle helper](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add.cpp#L292).
|
||||
- [Aim and velocity](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add.cpp#L422).
|
||||
- [Angle representation](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6).
|
||||
- [Elly's firing template](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26).
|
||||
- [Compiler checks](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation).
|
||||
|
||||
Original executables, game assets, complete raw Evidence, machine paths,
|
||||
account/configuration details and private compiler products remain outside
|
||||
the website.
|
||||
@@ -4,6 +4,7 @@ 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.
|
||||
- `public/assets/figures/th04-bullet-ring.svg` — 1000 × 520 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
|
||||
@@ -18,6 +19,14 @@ 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.
|
||||
|
||||
## TH04 figure
|
||||
|
||||
The TH04 figure is drawn directly as SVG from the byte-angle formula. It uses
|
||||
16 bullets, zero template rotation and illustrative player direction 40, with
|
||||
clockwise screen coordinates. The HTML overview separates REA's original-code
|
||||
inspection from the reconstruction project's C++ and compiler replay. No
|
||||
image generation or game screenshot is used for this mathematical figure.
|
||||
|
||||
## Review
|
||||
|
||||
Check spelling, arithmetic order, arrow directions and the separate verification
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="520" viewBox="0 0 1000 520" role="img" aria-labelledby="title description">
|
||||
<title id="title">TH04: spacing and aiming a ring of bullets</title>
|
||||
<desc id="description">A full clockwise turn has 256 angle units. Sixteen bullets start at angles zero, sixteen, thirty-two, through 240. Adding an example player direction of forty turns all sixteen directions together; the first bullet points at the player. Template rotation is zero.</desc>
|
||||
<defs><marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse"><path d="M 0 0 L 10 5 L 0 10 z" fill="#294f82" /></marker></defs>
|
||||
<style>text { font-family: Arial, Helvetica, sans-serif; fill: #20252b; } .heading { font-size: 26px; font-weight: 600; } .note { font-size: 19px; fill: #5b6570; } .mono { font-family: Consolas, 'Liberation Mono', monospace; font-size: 19px; } .accent { fill: #294f82; } .spoke { stroke: #d2dbe4; stroke-width: 1.6; } .bullet { fill: #9eafc0; } .first { fill: #294f82; } </style>
|
||||
<rect width="1000" height="520" fill="#ffffff" />
|
||||
<line x1="500" y1="42" x2="500" y2="428" stroke="#e0e5ea" />
|
||||
<text x="42" y="58" class="heading">Fixed ring</text>
|
||||
<text x="42" y="88" class="note">First bullet: angle 0</text>
|
||||
<text x="542" y="58" class="heading">Aimed ring</text>
|
||||
<text x="542" y="88" class="note">First bullet: player direction</text>
|
||||
<g id="fixed-ring" data-count="16" data-aim="0">
|
||||
<circle cx="245" cy="246" r="118" fill="none" stroke="#e0e5ea" stroke-dasharray="3 5" />
|
||||
<line x1="245" y1="246" x2="363.000" y2="246.000" stroke="#294f82" stroke-width="2.5" />
|
||||
<circle cx="363.000" cy="246.000" r="6" class="first" data-index="0" data-angle="0" />
|
||||
<line x1="245" y1="246" x2="354.018" y2="291.157" class="spoke" />
|
||||
<circle cx="354.018" cy="291.157" r="4.5" class="bullet" data-index="1" data-angle="16" />
|
||||
<line x1="245" y1="246" x2="328.439" y2="329.439" class="spoke" />
|
||||
<circle cx="328.439" cy="329.439" r="4.5" class="bullet" data-index="2" data-angle="32" />
|
||||
<line x1="245" y1="246" x2="290.157" y2="355.018" class="spoke" />
|
||||
<circle cx="290.157" cy="355.018" r="4.5" class="bullet" data-index="3" data-angle="48" />
|
||||
<line x1="245" y1="246" x2="245.000" y2="364.000" class="spoke" />
|
||||
<circle cx="245.000" cy="364.000" r="4.5" class="bullet" data-index="4" data-angle="64" />
|
||||
<line x1="245" y1="246" x2="199.843" y2="355.018" class="spoke" />
|
||||
<circle cx="199.843" cy="355.018" r="4.5" class="bullet" data-index="5" data-angle="80" />
|
||||
<line x1="245" y1="246" x2="161.561" y2="329.439" class="spoke" />
|
||||
<circle cx="161.561" cy="329.439" r="4.5" class="bullet" data-index="6" data-angle="96" />
|
||||
<line x1="245" y1="246" x2="135.982" y2="291.157" class="spoke" />
|
||||
<circle cx="135.982" cy="291.157" r="4.5" class="bullet" data-index="7" data-angle="112" />
|
||||
<line x1="245" y1="246" x2="127.000" y2="246.000" class="spoke" />
|
||||
<circle cx="127.000" cy="246.000" r="4.5" class="bullet" data-index="8" data-angle="128" />
|
||||
<line x1="245" y1="246" x2="135.982" y2="200.843" class="spoke" />
|
||||
<circle cx="135.982" cy="200.843" r="4.5" class="bullet" data-index="9" data-angle="144" />
|
||||
<line x1="245" y1="246" x2="161.561" y2="162.561" class="spoke" />
|
||||
<circle cx="161.561" cy="162.561" r="4.5" class="bullet" data-index="10" data-angle="160" />
|
||||
<line x1="245" y1="246" x2="199.843" y2="136.982" class="spoke" />
|
||||
<circle cx="199.843" cy="136.982" r="4.5" class="bullet" data-index="11" data-angle="176" />
|
||||
<line x1="245" y1="246" x2="245.000" y2="128.000" class="spoke" />
|
||||
<circle cx="245.000" cy="128.000" r="4.5" class="bullet" data-index="12" data-angle="192" />
|
||||
<line x1="245" y1="246" x2="290.157" y2="136.982" class="spoke" />
|
||||
<circle cx="290.157" cy="136.982" r="4.5" class="bullet" data-index="13" data-angle="208" />
|
||||
<line x1="245" y1="246" x2="328.439" y2="162.561" class="spoke" />
|
||||
<circle cx="328.439" cy="162.561" r="4.5" class="bullet" data-index="14" data-angle="224" />
|
||||
<line x1="245" y1="246" x2="354.018" y2="200.843" class="spoke" />
|
||||
<circle cx="354.018" cy="200.843" r="4.5" class="bullet" data-index="15" data-angle="240" />
|
||||
<circle cx="245" cy="246" r="7" fill="#20252b" />
|
||||
<rect x="215" y="261" width="60" height="26" fill="#ffffff" />
|
||||
<text x="245" y="280" text-anchor="middle" class="note">Origin</text>
|
||||
</g>
|
||||
<g id="aimed-ring" data-count="16" data-aim="40">
|
||||
<circle cx="730" cy="246" r="118" fill="none" stroke="#e0e5ea" stroke-dasharray="3 5" />
|
||||
<line x1="730" y1="246" x2="795.557" y2="344.113" stroke="#294f82" stroke-width="2.5" />
|
||||
<circle cx="795.557" cy="344.113" r="6" class="first" data-index="0" data-angle="40" />
|
||||
<line x1="730" y1="246" x2="753.021" y2="361.733" class="spoke" />
|
||||
<circle cx="753.021" cy="361.733" r="4.5" class="bullet" data-index="1" data-angle="56" />
|
||||
<line x1="730" y1="246" x2="706.979" y2="361.733" class="spoke" />
|
||||
<circle cx="706.979" cy="361.733" r="4.5" class="bullet" data-index="2" data-angle="72" />
|
||||
<line x1="730" y1="246" x2="664.443" y2="344.113" class="spoke" />
|
||||
<circle cx="664.443" cy="344.113" r="4.5" class="bullet" data-index="3" data-angle="88" />
|
||||
<line x1="730" y1="246" x2="631.887" y2="311.557" class="spoke" />
|
||||
<circle cx="631.887" cy="311.557" r="4.5" class="bullet" data-index="4" data-angle="104" />
|
||||
<line x1="730" y1="246" x2="614.267" y2="269.021" class="spoke" />
|
||||
<circle cx="614.267" cy="269.021" r="4.5" class="bullet" data-index="5" data-angle="120" />
|
||||
<line x1="730" y1="246" x2="614.267" y2="222.979" class="spoke" />
|
||||
<circle cx="614.267" cy="222.979" r="4.5" class="bullet" data-index="6" data-angle="136" />
|
||||
<line x1="730" y1="246" x2="631.887" y2="180.443" class="spoke" />
|
||||
<circle cx="631.887" cy="180.443" r="4.5" class="bullet" data-index="7" data-angle="152" />
|
||||
<line x1="730" y1="246" x2="664.443" y2="147.887" class="spoke" />
|
||||
<circle cx="664.443" cy="147.887" r="4.5" class="bullet" data-index="8" data-angle="168" />
|
||||
<line x1="730" y1="246" x2="706.979" y2="130.267" class="spoke" />
|
||||
<circle cx="706.979" cy="130.267" r="4.5" class="bullet" data-index="9" data-angle="184" />
|
||||
<line x1="730" y1="246" x2="753.021" y2="130.267" class="spoke" />
|
||||
<circle cx="753.021" cy="130.267" r="4.5" class="bullet" data-index="10" data-angle="200" />
|
||||
<line x1="730" y1="246" x2="795.557" y2="147.887" class="spoke" />
|
||||
<circle cx="795.557" cy="147.887" r="4.5" class="bullet" data-index="11" data-angle="216" />
|
||||
<line x1="730" y1="246" x2="828.113" y2="180.443" class="spoke" />
|
||||
<circle cx="828.113" cy="180.443" r="4.5" class="bullet" data-index="12" data-angle="232" />
|
||||
<line x1="730" y1="246" x2="845.733" y2="222.979" class="spoke" />
|
||||
<circle cx="845.733" cy="222.979" r="4.5" class="bullet" data-index="13" data-angle="248" />
|
||||
<line x1="730" y1="246" x2="845.733" y2="269.021" class="spoke" />
|
||||
<circle cx="845.733" cy="269.021" r="4.5" class="bullet" data-index="14" data-angle="8" />
|
||||
<line x1="730" y1="246" x2="828.113" y2="311.557" class="spoke" />
|
||||
<circle cx="828.113" cy="311.557" r="4.5" class="bullet" data-index="15" data-angle="24" />
|
||||
<circle cx="730" cy="246" r="7" fill="#20252b" />
|
||||
<rect x="700" y="261" width="60" height="26" fill="#ffffff" />
|
||||
<text x="730" y="280" text-anchor="middle" class="note">Origin</text>
|
||||
<line x1="800.557" y1="351.597" x2="829.447" y2="394.833" stroke="#294f82" stroke-width="1.8" stroke-dasharray="4 4" marker-end="url(#arrow)" />
|
||||
<path d="M 832.225 391.990 l 7 7 l -7 7 l -7 -7 z" fill="#294f82" />
|
||||
<text x="848.225" y="405.990" class="note accent">Player</text>
|
||||
</g>
|
||||
<text x="42" y="413" class="mono">0, 16, 32, …, 240</text>
|
||||
<text x="542" y="413" class="mono">40, 56, 72, …, 24</text>
|
||||
<rect x="24" y="451" width="952" height="47" rx="4" fill="#edf2f8" />
|
||||
<text x="500" y="481" text-anchor="middle" class="note accent">Same spacing: 256 ÷ 16 = 16 angle units = 22.5°</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.9 KiB |
@@ -841,6 +841,20 @@ pre code {
|
||||
.notion-bridge-flow {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
.th04-flow {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
.th04-overview {
|
||||
margin-bottom: 3.2rem;
|
||||
}
|
||||
.th04-ring-figure img {
|
||||
min-width: 680px;
|
||||
}
|
||||
.th04-preview img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
.notion-channel {
|
||||
color: var(--accent);
|
||||
background: #edf2f8;
|
||||
@@ -994,7 +1008,8 @@ pre code {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.flow-steps,
|
||||
.notion-bridge-flow {
|
||||
.notion-bridge-flow,
|
||||
.th04-flow {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
@@ -232,6 +232,38 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container feature-case">
|
||||
<div>
|
||||
<p class="eyebrow">Case study · PC-98 DOS</p>
|
||||
<h2>TH04's aimed bullet rings</h2>
|
||||
<p>
|
||||
Inspect a 16-bit DOS function with REA. Follow its angle
|
||||
calculation from original instructions to readable C++, then see
|
||||
how adding the player's direction turns a ring of bullets.
|
||||
</p>
|
||||
<a class="text-link" href="showcase/th04/"
|
||||
>See the bullet calculation</a
|
||||
>
|
||||
</div>
|
||||
<figure class="workflow-figure case-preview th04-preview">
|
||||
<p class="figure-title">Fixed and aimed rings</p>
|
||||
<img
|
||||
src="assets/figures/th04-bullet-ring.svg"
|
||||
width="1000"
|
||||
height="520"
|
||||
alt="TH04's fixed and aimed 16-bullet rings side by side. The first bullet is highlighted in blue; adding the player direction rotates every bullet while preserving the spacing."
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
<figcaption>
|
||||
Adding the player's direction rotates every bullet by the same
|
||||
angle.
|
||||
</figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container start-row">
|
||||
<div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>Case studies — REA</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Follow REA investigations through code and figures: recover a native calculation in DX-Ball and trace Notion's Electron clipboard bridge."
|
||||
content="Follow REA investigations through code and figures: DX-Ball's sound pan, Notion's Electron clipboard and TH04's aimed bullet rings."
|
||||
/>
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
<link rel="icon" href="../assets/favicon.svg" type="image/svg+xml" />
|
||||
@@ -76,6 +76,24 @@
|
||||
<a class="text-link" href="notion/">Read the Notion case study</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="guide-entry">
|
||||
<p class="eyebrow">PC-98 DOS · Reconstruction</p>
|
||||
<div>
|
||||
<h2>Understanding TH04's bullet patterns</h2>
|
||||
<p>
|
||||
Inspect the original 16-bit angle helper with REA. Match its
|
||||
multiply, divide and coordinate operations to readable C++, then
|
||||
see how they produce a ring aimed at the player.
|
||||
</p>
|
||||
<div class="guide-route">
|
||||
<span>Original DOS code</span> <b aria-hidden="true">→</b>
|
||||
<span>REA instructions</span> <b aria-hidden="true">→</b>
|
||||
<span>Angle calculation</span> <b aria-hidden="true">→</b>
|
||||
<span>Bullet ring</span>
|
||||
</div>
|
||||
<a class="text-link" href="th04/">Read the TH04 case study</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<section class="article-section">
|
||||
<h2>Try a smaller example first.</h2>
|
||||
|
||||
@@ -0,0 +1,637 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>TH04 bullet patterns — REA</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Inspect TH04's original 16-bit DOS code with REA. Follow the assembly and recovered C++ to see how a ring of bullets is spaced and aimed at the player."
|
||||
/>
|
||||
<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="../">Showcases</a>
|
||||
<a class="nav-start" href="../../get-started/">Get started</a>
|
||||
<a href="../../guides/">Guides</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> / <a href="../">Showcases</a> / TH04
|
||||
</p>
|
||||
<p class="eyebrow">Case study · Touhou 4: Lotus Land Story</p>
|
||||
<h1>Reconstructing TH04's<br />bullet patterns.</h1>
|
||||
<p class="lede">
|
||||
A ring of bullets starts with a short angle calculation. Use REA to
|
||||
inspect the original DOS function, then follow its instructions into
|
||||
readable C++.
|
||||
</p>
|
||||
<p class="page-meta">PC-98 · 16-bit DOS · C++ and assembly</p>
|
||||
<a class="text-link" href="https://github.com/N0zoM1z0/th04"
|
||||
>View the TH04 reconstruction</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<figure class="workflow-figure th04-overview">
|
||||
<p class="figure-title">From original instructions to checked source</p>
|
||||
<ol class="flow-steps th04-flow">
|
||||
<li>
|
||||
<span class="flow-label">01 · Original game</span
|
||||
><strong class="flow-node">MAIN.EXE</strong
|
||||
><span class="flow-note"
|
||||
>The PC-98 executable and a reviewed bullet helper.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<span class="flow-label">02 · Inspect with REA</span
|
||||
><strong class="flow-node">Instructions + references</strong
|
||||
><span class="flow-note"
|
||||
>Check the loaded image, read the arithmetic and anchor it to file
|
||||
bytes.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<span class="flow-label">03 · Read the C++</span
|
||||
><strong class="flow-node">Space → aim → rotate</strong
|
||||
><span class="flow-note"
|
||||
>Connect each operation to the maintained reconstruction.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<span class="flow-label">04 · Check the source</span
|
||||
><strong class="flow-node">2,139 matching bytes</strong
|
||||
><span class="flow-note"
|
||||
>Recorded compiler checks cover the containing bullet-add
|
||||
code.</span
|
||||
>
|
||||
</li>
|
||||
</ol>
|
||||
<figcaption>
|
||||
REA returns the original code and its analysis evidence. The TH04
|
||||
project supplies the maintained source and compiler checks.
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
<div class="article-layout">
|
||||
<nav class="contents" aria-label="On this page">
|
||||
<p>In this case study</p>
|
||||
<ul>
|
||||
<li><a href="#ring">The bullet ring</a></li>
|
||||
<li><a href="#rea">What REA returns</a></li>
|
||||
<li><a href="#source">Assembly to C++</a></li>
|
||||
<li><a href="#checking">Checking the source</a></li>
|
||||
<li><a href="#project">The full project</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<article class="article" aria-label="TH04 bullet-pattern case study">
|
||||
<section class="article-section" id="ring">
|
||||
<h2>How a ring aims at the player</h2>
|
||||
<p>
|
||||
Elly's attack requests an aimed ring with an initial count of 16.
|
||||
One helper calculates the direction of each bullet. The same ring
|
||||
can face a fixed direction or turn toward the player.
|
||||
</p>
|
||||
<div class="agent-terminal">
|
||||
<div class="terminal-header">
|
||||
<span class="terminal-title"
|
||||
><span class="terminal-dots" aria-hidden="true"
|
||||
><i></i><i></i><i></i></span
|
||||
>Your coding agent</span
|
||||
>
|
||||
<button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="th04-prompt"
|
||||
aria-label="Copy TH04 example prompt"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<p class="terminal-prompt">
|
||||
<span class="prompt-symbol" aria-hidden="true">›</span
|
||||
><span id="th04-prompt"
|
||||
>Use REA to find how TH04 creates a ring of bullets and aims
|
||||
it at the player. Explain the calculation and show the
|
||||
code.</span
|
||||
><span class="terminal-cursor" aria-hidden="true"></span>
|
||||
</p>
|
||||
</div>
|
||||
<p class="caption">
|
||||
An example prompt, with the original executable and reconstruction
|
||||
checkout available locally.
|
||||
</p>
|
||||
<p>
|
||||
TH04 stores a full clockwise turn in 256 angle units. For 16
|
||||
bullets, each index adds 16 units: <code>0, 16, 32, …, 240</code>.
|
||||
Adding the player's direction rotates those positions together.
|
||||
</p>
|
||||
<figure class="explanatory-figure th04-ring-figure">
|
||||
<div
|
||||
class="figure-viewport"
|
||||
tabindex="0"
|
||||
role="region"
|
||||
aria-label="TH04 fixed and aimed bullet rings; scroll horizontally on smaller screens"
|
||||
>
|
||||
<img
|
||||
src="../../assets/figures/th04-bullet-ring.svg"
|
||||
width="1000"
|
||||
height="520"
|
||||
alt="Two diagrams of a 16-bullet ring. The fixed ring starts at angle zero. Adding a player direction of 40 rotates every direction by the same amount; the highlighted first bullet points toward the player. Both keep a spacing of 16 angle units, or 22.5 degrees."
|
||||
decoding="async"
|
||||
/>
|
||||
</div>
|
||||
<figcaption>
|
||||
An illustration of the recovered angle math for count 16, player
|
||||
direction 40 and template rotation 0.
|
||||
<a href="../../assets/figures/th04-bullet-ring.svg"
|
||||
>Open figure</a
|
||||
>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<h3 class="small-heading">
|
||||
The firing template in the recovered source
|
||||
</h3>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Elly's ring attack · source excerpt</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="th04-template"
|
||||
aria-label="Copy TH04 firing template"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="th04-template">bullet_template.angle = 0;
|
||||
bullet_template.group = BG_RING_AIMED;
|
||||
bullet_template.count = 16;
|
||||
bullet_template_tune();</code></pre>
|
||||
</div>
|
||||
<p class="caption">
|
||||
These lines select the pattern before difficulty and performance
|
||||
tuning.
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26"
|
||||
>Read the attack's source</a
|
||||
>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="rea">
|
||||
<h2>What REA returns</h2>
|
||||
<p>
|
||||
The project already has a reviewed boundary for
|
||||
<code>bullet_velocity_and_angle_set()</code>. Inspecting that
|
||||
original function through REA returns its instructions, pseudocode
|
||||
and references together. Here are three parts of the result that
|
||||
explain the pattern.
|
||||
</p>
|
||||
<ol class="rea-queries">
|
||||
<li>
|
||||
<h4>Check the DOS image before reading its code</h4>
|
||||
<div class="rea-query-pair">
|
||||
<div class="code-block">
|
||||
<div class="code-header"><span>Agent → REA</span></div>
|
||||
<pre><code>open_binary
|
||||
{"path": "MAIN.EXE"}
|
||||
|
||||
inspect_native_load_image
|
||||
{}</code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA → agent · selected fields</span>
|
||||
</div>
|
||||
<pre><code>status: "verified"
|
||||
format: "dos-mz"
|
||||
load_segment: 4096
|
||||
header_bytes: 6144
|
||||
module_bytes: 150114</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
The check ties the loaded code and relocation records to the
|
||||
supplied executable. The path above is shortened for display.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<h4>Read the ring's multiply and divide</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": "0x2cfc8"}</code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA → agent · instruction excerpt</span>
|
||||
</div>
|
||||
<pre><code>0x2d0eb: MOV AX, SI
|
||||
0x2d0ed: SHL AX, 0x8
|
||||
0x2d0f0: MOV DL, byte ptr [0x53af]
|
||||
0x2d0f9: IDIV BX</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
<code>SI</code> holds the bullet index. The shift multiplies
|
||||
it by 256, then the division uses the count read from
|
||||
<code>DS:53AF</code>. The maintained source names that field
|
||||
<code>bullet_template.count</code>. The complete sequence
|
||||
appears below.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<h4>Find where the pattern turns toward the player</h4>
|
||||
<div class="rea-query-pair">
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Same function result · aim excerpt</span>
|
||||
</div>
|
||||
<pre><code>0x2d190: SUB AX, word ptr [0x53a6]
|
||||
0x2d198: SUB AX, word ptr [0x53a4]
|
||||
0x2d19d: CALLF 0x1000:1da8
|
||||
0x2d1a2: ADD word ptr [BP + -0x2], AX</code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Corresponding maintained C++</span>
|
||||
</div>
|
||||
<pre><code>group_angle_offset += iatan2(
|
||||
player_pos.cur.y - bullet_template.origin.y,
|
||||
player_pos.cur.x - bullet_template.origin.x
|
||||
);</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
The instruction operands expose two coordinate differences and
|
||||
a direction helper. Its return value is added to the relative
|
||||
ring angle. Source names make those addresses readable; REA
|
||||
lets the agent check the original operations behind them.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="source">
|
||||
<h2>From assembly to readable C++</h2>
|
||||
<p>
|
||||
Select a step to match the original instructions with the angle
|
||||
calculation. This summary follows the aimed-ring path; the full
|
||||
source also handles spreads, stacks and random patterns.
|
||||
</p>
|
||||
<div class="step-comparison" data-step-comparison>
|
||||
<div
|
||||
class="step-selector"
|
||||
role="group"
|
||||
aria-label="Follow the TH04 aimed-ring calculation"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="1"
|
||||
aria-pressed="true"
|
||||
aria-controls="ring-assembly ring-source ring-step-detail"
|
||||
>
|
||||
<span>01</span> Index
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="2"
|
||||
aria-pressed="false"
|
||||
aria-controls="ring-assembly ring-source ring-step-detail"
|
||||
>
|
||||
<span>02</span> Space
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="3"
|
||||
aria-pressed="false"
|
||||
aria-controls="ring-assembly ring-source ring-step-detail"
|
||||
>
|
||||
<span>03</span> Aim
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="4"
|
||||
aria-pressed="false"
|
||||
aria-controls="ring-assembly ring-source ring-step-detail"
|
||||
>
|
||||
<span>04</span> Rotate
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
data-select-step="5"
|
||||
aria-pressed="false"
|
||||
aria-controls="ring-assembly ring-source ring-step-detail"
|
||||
>
|
||||
<span>05</span> Store
|
||||
</button>
|
||||
</div>
|
||||
<div class="code-comparison">
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>REA · original 16-bit instructions</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="ring-assembly"
|
||||
aria-label="Copy TH04 assembly excerpt"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="ring-assembly"><span class="code-step is-active" data-step="1">0x2cfcf: MOV SI, word ptr [BP + 0x4]
|
||||
0x2d0eb: MOV AX, SI</span>
|
||||
<span class="code-step" data-step="2">0x2d0ed: SHL AX, 0x8
|
||||
0x2d0f0: MOV DL, byte ptr [0x53af]
|
||||
0x2d0f4: MOV DH, 0x0
|
||||
0x2d0f6: PUSH DX
|
||||
0x2d0f7: CWD
|
||||
0x2d0f8: POP BX
|
||||
0x2d0f9: IDIV BX
|
||||
0x2d0fb: MOV word ptr [BP + -0x2], AX</span>
|
||||
<span class="code-step" data-step="3">0x2d18d: MOV AX, [0x4650]
|
||||
0x2d190: SUB AX, word ptr [0x53a6]
|
||||
0x2d194: PUSH AX
|
||||
0x2d195: MOV AX, [0x464e]
|
||||
0x2d198: SUB AX, word ptr [0x53a4]
|
||||
0x2d19c: PUSH AX
|
||||
0x2d19d: CALLF 0x1000:1da8
|
||||
0x2d1a2: ADD word ptr [BP + -0x2], AX</span>
|
||||
<span class="code-step" data-step="4">0x2d1b9: MOV AL, byte ptr [BP + -0x2]
|
||||
0x2d1bc: ADD AL, byte ptr [0x53ad]</span>
|
||||
<span class="code-step" data-step="5">0x2d1c0: MOV [0xbcc8], AL</span></code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Readable C++ · aimed-ring summary</span
|
||||
><button
|
||||
class="copy-button"
|
||||
type="button"
|
||||
data-copy="ring-source"
|
||||
aria-label="Copy readable aimed-ring calculation"
|
||||
>
|
||||
Copy
|
||||
</button>
|
||||
</div>
|
||||
<pre><code id="ring-source">unsigned char aimed_ring_angle(
|
||||
<span class="is-active" data-step="1">int index</span>, int count,
|
||||
int player_direction,
|
||||
unsigned char rotation)
|
||||
{
|
||||
<span class="code-step is-active" data-step="1"> int angle = index;</span>
|
||||
<span class="code-step" data-step="2"> angle = (angle * 256) / count;</span>
|
||||
<span class="code-step" data-step="3"> angle += player_direction;</span>
|
||||
<span class="code-step" data-step="4"> angle += rotation;</span>
|
||||
<span class="code-step" data-step="5"> return (unsigned char)angle;</span>
|
||||
}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="step-detail"
|
||||
id="ring-step-detail"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
>
|
||||
<p data-step-note="1">
|
||||
<strong>01 · Read the bullet index.</strong> The stack
|
||||
argument is loaded into <code>SI</code>. In a 16-bullet ring,
|
||||
this member index runs from 0 through 15.
|
||||
</p>
|
||||
<p data-step-note="2" hidden>
|
||||
<strong>02 · Space the directions around a full turn.</strong>
|
||||
<code>SHL AX,8</code> multiplies by 256. The count is
|
||||
zero-extended into a word, then <code>IDIV</code> divides the
|
||||
product by that count. For count 16, each index advances 16
|
||||
angle units.
|
||||
</p>
|
||||
<p data-step-note="3" hidden>
|
||||
<strong>03 · Add the player direction.</strong> The two
|
||||
subtractions form player-minus-origin coordinates. The
|
||||
direction helper returns an angle in <code>AX</code>; adding
|
||||
it turns the whole ring toward the player.
|
||||
</p>
|
||||
<p data-step-note="4" hidden>
|
||||
<strong>04 · Add the pattern's rotation.</strong>
|
||||
<code>ADD AL,[0x53ad]</code> adds the template angle. Elly's
|
||||
initial template sets it to zero; other patterns can use the
|
||||
same helper with a rotation.
|
||||
</p>
|
||||
<p data-step-note="5" hidden>
|
||||
<strong>05 · Keep the final angle in one byte.</strong> The
|
||||
store writes <code>AL</code> to the spawn-angle field. Values
|
||||
wrap after 255, just as the unsigned-byte cast does. The
|
||||
surrounding source also converts this angle and speed into
|
||||
velocity.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="caption">
|
||||
The assembly selects the aimed-ring branch, aim calculation and
|
||||
final store. The C++ above is a readable summary. Compiler checks
|
||||
below apply to the maintained source in the linked project.
|
||||
</p>
|
||||
<details class="evidence-details">
|
||||
<summary>Read the maintained ring and aim source</summary>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Ring macro · TH04 branch, excerpt</span>
|
||||
</div>
|
||||
<pre><code>angle_offset = (i * BULLET_ANGLE_FULL_TURN) / count;
|
||||
if (i >= (count - 1)) {
|
||||
group_complete = true;
|
||||
}
|
||||
goto aim_or_no_aim;</code></pre>
|
||||
</div>
|
||||
<div class="code-block">
|
||||
<div class="code-header">
|
||||
<span>Angle and velocity · source excerpt</span>
|
||||
</div>
|
||||
<pre><code>aim:
|
||||
group_angle_offset += iatan2(
|
||||
(player_pos.cur.y - bullet_template.origin.y),
|
||||
(player_pos.cur.x - bullet_template.origin.x)
|
||||
);
|
||||
|
||||
no_aim:
|
||||
vector2_near(
|
||||
bullet_template.velocity,
|
||||
(group_angle_offset + bullet_template.angle),
|
||||
speed
|
||||
);
|
||||
bullet_spawn_angle = (group_angle_offset + bullet_template.angle);</code></pre>
|
||||
</div>
|
||||
<p class="caption">
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add_impl.hpp#L4"
|
||||
>Ring macro</a
|
||||
>
|
||||
·
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add.cpp#L422"
|
||||
>Aim and velocity source</a
|
||||
>
|
||||
·
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6"
|
||||
>Angle representation</a
|
||||
>
|
||||
</p>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="checking">
|
||||
<h2>Checking the maintained source</h2>
|
||||
<p>
|
||||
The TH04 project checks this compiler-sensitive C++ with its
|
||||
pinned Turbo C++ 4.0J toolchain. Recorded checks cover the
|
||||
complete bullet-add source owner containing this helper.
|
||||
</p>
|
||||
<div class="verification">
|
||||
<div>
|
||||
<h3>2,139 matching bytes</h3>
|
||||
<p>
|
||||
The rebuilt code matches the complete original target extent.
|
||||
The comparison also checks the MAP contribution and
|
||||
overlapping relocation.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Two clean builds</h3>
|
||||
<p>
|
||||
Two isolated compiler runs produce the same matching result.
|
||||
The recorded input hashes match the maintained bullet source
|
||||
shown here.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="caption">
|
||||
Recorded on 3 October 2026.
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation"
|
||||
>Read the compiler checks</a
|
||||
>.
|
||||
</p>
|
||||
<details class="evidence-details">
|
||||
<summary>Target identity and analysis scope</summary>
|
||||
<div class="evidence-table-wrap">
|
||||
<table class="evidence-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Original target</th>
|
||||
<td><code>MAIN.EXE</code>, 156,258 bytes, DOS MZ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Helper entry</th>
|
||||
<td><code>0x2cfc8</code> in REA's loaded image</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Original file offset</th>
|
||||
<td>
|
||||
<code>0x1e7c8</code>, returned by
|
||||
<code>address_to_file_offset</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Recorded code inspection</th>
|
||||
<td>REA 4.1.0 · 7 October 2026</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>
|
||||
REA verified the static DOS load image at load segment
|
||||
<code>0x1000</code>. Its addresses describe that analysis image.
|
||||
The function result reports 503 body bytes in two ranges across
|
||||
a 517-byte span; the selected instructions above lie in those
|
||||
reported ranges.
|
||||
</p>
|
||||
<p>
|
||||
The source names and compiler checks come from TH04 checkpoint
|
||||
<code>0d72e980</code>. Earlier reconstruction observations used
|
||||
the project's own analysis scripts; this page adds a fresh REA
|
||||
inspection of the same original target. The supplied game's
|
||||
identity is pinned by its repository manifest, with independent
|
||||
pristine-dump provenance still open.
|
||||
</p>
|
||||
<p>
|
||||
The figure illustrates the angle calculation. Full-game
|
||||
controls, timing and PC-98 hardware behavior have separate
|
||||
runtime checks in the reconstruction project.
|
||||
</p>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<section class="article-section" id="project">
|
||||
<h2>The full TH04 reconstruction</h2>
|
||||
<p>
|
||||
The project builds the game's four DOS products from maintained
|
||||
C++ and assembly. Beyond bullet generation, the source covers
|
||||
stages, bosses, rendering, input, menus, endings and score
|
||||
handling.
|
||||
</p>
|
||||
<p>
|
||||
<a class="text-link" href="https://github.com/N0zoM1z0/th04"
|
||||
>Explore the TH04 repository</a
|
||||
>
|
||||
</p>
|
||||
<ul class="reading-list">
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add.cpp#L292"
|
||||
>Bullet-generation source</a
|
||||
><span
|
||||
>The complete helper, other pattern types and template
|
||||
tuning.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/DOS_BUILD.md"
|
||||
>DOS build and run guide</a
|
||||
><span
|
||||
>Build the source and test it in the project's PC-98 emulator
|
||||
workflow.</span
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/RE_HANDOFF.md"
|
||||
>Current project state</a
|
||||
><span>DOS verification and the separate native x64 port.</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>
|
||||
Reference in new issue
Block a user