mirror of
https://github.com/morluto/rea
synced 2026-10-27 14:42:18 -04:00
b27e1a74c9
Resolve eight nested README links from their owning directory. Preserve the shared README/website inventory contract by registering Malayalam with an explicitly untranslated catalog and the existing visible, noindex English fallback. Regenerate the shared website navigation and catalog references. Existing parsed translations remain unchanged. Validation: docs check, full website check (401 HTML pages, 27790 local references, 19 tests), all 19 generated Malayalam fallback pages, and two source reviews. No Malayalam website translation or browser layout claim. Fixes #4821
812 lines
38 KiB
HTML
812 lines
38 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>TH04 Reverse Engineering: DOS 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."
|
||
/>
|
||
<!-- website:sharing:start -->
|
||
<!-- prettier-ignore -->
|
||
<link rel="canonical" href="https://rea.tools/showcase/th04/" />
|
||
<!-- website:languages:start -->
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="en" href="https://rea.tools/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="zh-CN" href="https://rea.tools/zh-CN/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="zh-TW" href="https://rea.tools/zh-TW/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ja" href="https://rea.tools/ja/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ko" href="https://rea.tools/ko/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="tr" href="https://rea.tools/tr/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ru" href="https://rea.tools/ru/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="vi" href="https://rea.tools/vi/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="th" href="https://rea.tools/th/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="de" href="https://rea.tools/de/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="es" href="https://rea.tools/es/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="fr" href="https://rea.tools/fr/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="uk" href="https://rea.tools/uk/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="pl" href="https://rea.tools/pl/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="pt-BR" href="https://rea.tools/pt-BR/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ar" href="https://rea.tools/ar/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="fa" href="https://rea.tools/fa/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="id" href="https://rea.tools/id/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="it" href="https://rea.tools/it/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="el" href="https://rea.tools/el/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="ml" href="https://rea.tools/ml/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<link rel="alternate" hreflang="x-default" href="https://rea.tools/showcase/th04/" />
|
||
<!-- website:languages:end -->
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:type" content="website" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:site_name" content="REA" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:title" content="TH04 Reverse Engineering: DOS Bullet Patterns — REA" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og: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." />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:url" content="https://rea.tools/showcase/th04/" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image" content="https://rea.tools/assets/social-card.png" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image:type" content="image/png" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image:width" content="1200" />
|
||
<!-- prettier-ignore -->
|
||
<meta property="og:image:height" content="630" />
|
||
<!-- prettier-ignore -->
|
||
<meta
|
||
property="og:image:alt"
|
||
content="REA — Find out how software works. Reverse engineering with your coding agent."
|
||
/>
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter:card" content="summary_large_image" />
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter:title" content="TH04 Reverse Engineering: DOS Bullet Patterns — REA" />
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter: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." />
|
||
<!-- prettier-ignore -->
|
||
<meta name="twitter:image" content="https://rea.tools/assets/social-card.png" />
|
||
<!-- prettier-ignore -->
|
||
<meta
|
||
name="twitter:image:alt"
|
||
content="REA — Find out how software works. Reverse engineering with your coding agent."
|
||
/>
|
||
<!-- website:sharing:end -->
|
||
<!-- website:theme:start -->
|
||
<meta name="theme-color" content="#ffffff" />
|
||
<!-- Apply the saved theme before styles load, to avoid a flash on navigation. -->
|
||
<script src="../../assets/theme.js"></script>
|
||
<!-- website:theme:end -->
|
||
<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 id="top">
|
||
<a class="skip-link" href="#main">Skip to content</a>
|
||
<!-- website:header:start -->
|
||
<!-- prettier-ignore -->
|
||
<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" data-i18n-skip>Reverse Engineer Anything</span></a
|
||
>
|
||
<nav class="navigation" aria-label="Main navigation">
|
||
<a href="../../get-started/" class="nav-start">Get started</a>
|
||
<a href="../../showcase/" aria-current="page">Showcases</a>
|
||
<a href="../../blog/">Blog</a>
|
||
<a href="../../guides/">Guides</a>
|
||
<a href="../../faq/">FAQ</a>
|
||
<a href="../../contributors/">Contributors</a>
|
||
</nav>
|
||
<div class="header-social">
|
||
<details class="language-picker" data-i18n-skip><summary><span aria-hidden="true">文 / A</span> <span>English</span></summary><nav aria-label="English"><a href="../../showcase/th04/" lang="en" dir="ltr" data-language="en" aria-current="true">English</a><a href="../../zh-CN/showcase/th04/" lang="zh-CN" dir="ltr" data-language="zh-CN">简体中文</a><a href="../../zh-TW/showcase/th04/" lang="zh-TW" dir="ltr" data-language="zh-TW">繁體中文</a><a href="../../ja/showcase/th04/" lang="ja" dir="ltr" data-language="ja">日本語</a><a href="../../ko/showcase/th04/" lang="ko" dir="ltr" data-language="ko">한국어</a><a href="../../tr/showcase/th04/" lang="tr" dir="ltr" data-language="tr">Türkçe</a><a href="../../ru/showcase/th04/" lang="ru" dir="ltr" data-language="ru">Русский</a><a href="../../vi/showcase/th04/" lang="vi" dir="ltr" data-language="vi">Tiếng Việt</a><a href="../../th/showcase/th04/" lang="th" dir="ltr" data-language="th">ไทย</a><a href="../../de/showcase/th04/" lang="de" dir="ltr" data-language="de">Deutsch</a><a href="../../es/showcase/th04/" lang="es" dir="ltr" data-language="es">Español</a><a href="../../fr/showcase/th04/" lang="fr" dir="ltr" data-language="fr">Français</a><a href="../../uk/showcase/th04/" lang="uk" dir="ltr" data-language="uk">Українська</a><a href="../../pl/showcase/th04/" lang="pl" dir="ltr" data-language="pl">Polski</a><a href="../../pt-BR/showcase/th04/" lang="pt-BR" dir="ltr" data-language="pt-BR">Português (Brasil)</a><a href="../../ar/showcase/th04/" lang="ar" dir="rtl" data-language="ar">العربية</a><a href="../../fa/showcase/th04/" lang="fa" dir="rtl" data-language="fa">فارسی</a><a href="../../id/showcase/th04/" lang="id" dir="ltr" data-language="id">Bahasa Indonesia</a><a href="../../it/showcase/th04/" lang="it" dir="ltr" data-language="it">Italiano</a><a href="../../el/showcase/th04/" lang="el" dir="ltr" data-language="el">Ελληνικά</a><a href="../../ml/showcase/th04/" lang="ml" dir="ltr" data-language="ml">മലയാളം</a></nav></details>
|
||
<button class="theme-toggle" type="button" data-theme-toggle hidden>
|
||
<svg class="theme-moon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
|
||
<path d="M20.9 13a9 9 0 0 1-9.9-9.9A9 9 0 1 0 20.9 13Z" />
|
||
</svg>
|
||
<svg class="theme-sun" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true" focusable="false">
|
||
<circle cx="12" cy="12" r="4" />
|
||
<path d="M12 2v2m0 16v2M2 12h2m16 0h2M4.93 4.93l1.42 1.42m11.3 11.3 1.42 1.42M4.93 19.07l1.42-1.42m11.3-11.3 1.42-1.42" />
|
||
</svg>
|
||
</button>
|
||
<a
|
||
class="nav-github"
|
||
href="https://github.com/morluto/rea"
|
||
aria-label="REA on GitHub"
|
||
title="REA on GitHub"
|
||
>
|
||
<svg
|
||
width="22"
|
||
height="22"
|
||
viewBox="0 0 16 16"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path
|
||
fill="currentColor"
|
||
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82a7.65 7.65 0 0 1 2-.27c.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"
|
||
/>
|
||
</svg>
|
||
<span class="nav-github-count" hidden aria-hidden="true"></span>
|
||
</a>
|
||
<a
|
||
class="nav-discord"
|
||
href="https://discord.gg/GkcryMnJDM"
|
||
aria-label="Join REA on Discord"
|
||
title="Join REA on Discord"
|
||
>
|
||
<svg
|
||
width="22"
|
||
height="22"
|
||
viewBox="0 0 24 24"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path
|
||
fill="currentColor"
|
||
d="M20.317 4.3698a19.7913 19.7913 0 0 0-4.8851-1.5152.0741.0741 0 0 0-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 0 0-.0785-.037 19.7363 19.7363 0 0 0-4.8852 1.515.0699.0699 0 0 0-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 0 0 .0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 0 0 .0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 0 0-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 0 1-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 0 1 .0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 0 1 .0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 0 1-.0066.1276 12.2986 12.2986 0 0 1-1.873.8914.0766.0766 0 0 0-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 0 0 .0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 0 0 .0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 0 0-.0312-.0286ZM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189Zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"
|
||
/>
|
||
</svg>
|
||
</a>
|
||
<a
|
||
class="nav-x"
|
||
href="https://x.com/reatools"
|
||
aria-label="Follow REA on X"
|
||
title="Follow REA on X"
|
||
>
|
||
<svg
|
||
width="18"
|
||
height="18"
|
||
viewBox="0 0 24 24"
|
||
aria-hidden="true"
|
||
focusable="false"
|
||
>
|
||
<path
|
||
fill="currentColor"
|
||
d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"
|
||
/>
|
||
</svg>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
<!-- website:header:end -->
|
||
<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 its bullet-angle helper.</span
|
||
>
|
||
</li>
|
||
<li>
|
||
<span class="flow-label">02 · Inspect with REA</span
|
||
><strong class="flow-node">Instructions + references</strong
|
||
><span class="flow-note"
|
||
>Verify the loaded DOS code and read the angle calculation from
|
||
the executable.</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 bullet-generation code that
|
||
contains this helper.</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>
|
||
We inspect <code>bullet_velocity_and_angle_set()</code>, the
|
||
function that sets each bullet's velocity and angle. REA returns
|
||
its instructions, pseudocode and references. Three parts of that
|
||
result 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's recorded checks compile the bullet-generation
|
||
code, including this helper, with its pinned Turbo C++ 4.0J
|
||
toolchain.
|
||
</p>
|
||
<div class="verification">
|
||
<div>
|
||
<h3>2,139 matching bytes</h3>
|
||
<p>
|
||
The compiled bullet-generation code matches a 2,139-byte
|
||
section of the original executable.
|
||
</p>
|
||
</div>
|
||
<div>
|
||
<h3>Two clean builds</h3>
|
||
<p>
|
||
Two separate builds produce the same matching bytes. The
|
||
recorded input hashes match the maintained 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>
|
||
Compiler checks cover the complete bullet-add code section,
|
||
including this helper. They also compare its MAP contribution
|
||
and overlapping relocation.
|
||
</p>
|
||
<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>
|
||
<!-- website:footer:start -->
|
||
<!-- prettier-ignore -->
|
||
<footer class="site-footer">
|
||
<div class="container footer-inner">
|
||
<p>REA · Reverse Engineer Anything</p>
|
||
<div class="footer-links">
|
||
<a href="../../contributors/">Contributors</a
|
||
><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">Join the community</a
|
||
><a href="https://x.com/reatools">Follow us on X</a>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
<p class="sr-only" id="copy-status" role="status" aria-live="polite"></p>
|
||
<a class="back-to-top" href="#top" aria-label="Back to top">
|
||
<span aria-hidden="true">↑</span> Top
|
||
</a>
|
||
<!-- website:footer:end -->
|
||
</body>
|
||
</html>
|