---
title: 'TH04 inżynieria odwrotna: wzory pocisków dos-REA'
url: https://rea.tools/pl/showcase/th04/
---

[Spis treści](https://rea.tools/pl/) / [Gabloty](https://rea.tools/pl/showcase/) / TH04

Studium przypadku \* Touhou 4: Lotus Land Story

# Rekonstrukcja TH04 wzory pocisków.

Pierścień pocisków zaczyna się od obliczenia krótkiego kąta. Użyj REA, aby sprawdzić oryginalną funkcję DOS, a następnie postępuj zgodnie z jej instrukcjami w czytelnym C++.

PC-98 \* 16-bitowy DOS · C++ i montaż

[Zobacz rekonstrukcję TH04](https://github.com/N0zoM1z0/th04)

Od oryginalnych instrukcji do sprawdzonego źródła

1. 01 \* oryginalna gra

   **Główny.EXE**

   Plik wykonywalny PC-98 i jego pomocnik kąta pocisku.
2. 02 \* sprawdź za pomocą REA

   **Instrukcje + referencje**

   Sprawdź załadowany kod DOS i odczytaj obliczenie kąta z pliku wykonywalnego.
3. 03 \* przeczytaj C++

   **Przestrzeń → cel → obróć**

   Połącz każdą operację z utrzymaną rekonstrukcją.
4. 04 \* Sprawdź źródło

   **2139 pasujących bajtów**

   Zarejestrowane kontrole kompilatora obejmują kod generowania punktorów, który zawiera ten Pomocnik.

REA zwraca oryginalny kod i jego dowody analizy. Projekt TH04 zapewnia utrzymywane kontrole źródła i kompilatora.

## Jak pierścień celuje w gracza

Atak Elly wymaga wycelowanego pierścienia z początkową liczbą 16. Jeden Pomocnik oblicza kierunek każdego pocisku. Ten sam pierścień może być skierowany w ustalonym kierunku lub skręcić w kierunku gracza.

Twój agent kodowania

Użyj REA, aby dowiedzieć się, jak TH04 tworzy pierścień pocisków i celuje w gracza. Wyjaśnij obliczenia i pokaż kod.

Przykładowy monit z oryginalnym plikiem wykonywalnym i kasą rekonstrukcji dostępną lokalnie.

TH04 przechowuje pełny obrót zgodnie z ruchem wskazówek zegara w jednostkach kąta 256. Dla 16 pocisków każdy indeks dodaje 16 jednostek: `0, 16, 32, …, 240`. Dodanie kierunku gracza obraca te pozycje razem.

![Dwa schematy pierścienia z 16 kulami. Stały pierścień zaczyna się pod kątem zerowym. Dodanie kierunku gracza 40 obraca się w każdym kierunku o tę samą wartość; podświetlona pierwsza wypunktowanie wskazuje na gracza. Oba zachowują odstęp 16 jednostek kąta lub 22,5 stopnia.](https://rea.tools/assets/localized/pl/figures/th04-bullet-ring.svg)

Ilustracja odzyskanej matematyki kąta dla liczby 16, kierunku gracza 40 i obrotu szablonu 0. [Otwórz rysunek](https://rea.tools/assets/localized/pl/figures/th04-bullet-ring.svg)

### Szablon wypalania w odzyskanym źródle

Atak pierścienia Elly \* fragment źródłowy

```
bullet_template.angle = 0;
bullet_template.group = BG_RING_AIMED;
bullet_template.count = 16;
bullet_template_tune();
```

Linie te wybierają wzór przed trudnością i strojeniem wydajności. [Przeczytaj źródło ataku](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/boss/elly_phase_ring16.cpp#L26).

## Co zwraca REA

Sprawdzamy `bullet_velocity_and_angle_set()`, funkcja, która ustawia prędkość i kąt każdego pocisku. REA zwraca instrukcje, pseudokod i odwołania. Trzy części tego wyniku wyjaśniają wzór.

1. #### Sprawdź obraz DOS przed przeczytaniem jego kodu

   Agent → REA

   ```
   open_binary
   {"path": "MAIN.EXE"}

   inspect_native_load_image
   {}
   ```

   REA → agent \* wybrane pola

   ```
   status: "verified"
   format: "dos-mz"
   load_segment: 4096
   header_bytes: 6144
   module_bytes: 150114
   ```

   Sprawdzenie wiąże załadowany kod i rekordy relokacji z dostarczonym plikiem wykonywalnym. Ścieżka powyżej jest skrócona do wyświetlania.
2. #### Przeczytaj mnożenie i dzielenie pierścienia

   Agent → REA · `analyze_function`

   ```
   {"procedure": "0x2cfc8"}
   ```

   REA → agent \* fragment instrukcji

   ```
   0x2d0eb: MOV AX, SI
   0x2d0ed: SHL AX, 0x8
   0x2d0f0: MOV DL, byte ptr [0x53af]
   0x2d0f9: IDIV BX
   ```

   `SI` posiada indeks punktora. Przesunięcie mnoży go przez 256, a następnie podział wykorzystuje liczbę odczytaną z `DS:53AF`. Utrzymane nazwy źródłowe tego pola `bullet_template.count`. Pełna sekwencja pojawia się poniżej.
3. #### Znajdź, gdzie wzór obraca się w kierunku gracza

   Ta sama funkcja wynik \* aim fragment

   ```
   0x2d190: SUB AX, word ptr [0x53a6]
   0x2d198: SUB AX, word ptr [0x53a4]
   0x2d19d: CALLF 0x1000:1da8
   0x2d1a2: ADD word ptr [BP + -0x2], AX
   ```

   Odpowiadający utrzymywany C++

   ```
   group_angle_offset += iatan2(
     player_pos.cur.y - bullet_template.origin.y,
     player_pos.cur.x - bullet_template.origin.x
   );
   ```

   Operandy instrukcji ujawniają dwie różnice współrzędnych i pomocnika kierunku. Jego wartość zwracana jest dodawana do względnego kąta pierścienia. Nazwy źródeł sprawiają, że adresy te są czytelne; REA pozwala agentowi sprawdzić oryginalne operacje za nimi.

## Od zestawu do czytelnego C++

Wybierz krok, aby dopasować oryginalne instrukcje do obliczenia kąta. To podsumowanie podąża ścieżką ukierunkowanego pierścienia; pełne źródło obsługuje również spready, stosy i losowe wzory.

REA \* oryginalne 16-bitowe instrukcje

```
0x2cfcf: MOV SI, word ptr [BP + 0x4]
0x2d0eb: MOV AX, SI
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
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
0x2d1b9: MOV AL, byte ptr [BP + -0x2]
0x2d1bc: ADD AL, byte ptr [0x53ad]
0x2d1c0: MOV [0xbcc8], AL
```

Czytelne podsumowanie C++ · aimed-ring

```
unsigned char aimed_ring_angle(
    int index, int count,
    int player_direction,
    unsigned char rotation)
{
    int angle = index;
    angle = (angle * 256) / count;
    angle += player_direction;
    angle += rotation;
    return (unsigned char)angle;
}
```

**01 \* przeczytaj indeks punktora.** Argument stosu jest ładowany do `SI`. W pierścieniu z 16 pociskami ten indeks członków biegnie od 0 do 15.

**02 \* Rozmieść Kierunki wokół pełnego obrotu.** `SHL AX,8` mnoży się przez 256. Liczba jest zerowa-rozszerzona na słowo, a następnie `IDIV` dzieli produkt przez tę liczbę. W przypadku liczby 16 każdy indeks przesuwa się o 16 jednostek kąta.

**03 \* Dodaj kierunek gracza.** Dwa odejmowania tworzą współrzędne player-minus-origin. Pomocnik kierunku zwraca kąt w `AX`; dodanie go obraca cały pierścień w kierunku gracza.

**04 \* Dodaj obrót wzoru.** `ADD AL,[0x53ad]` dodaje kąt szablonu. Początkowy szablon Elly ustawia go na zero; inne wzory mogą używać tego samego pomocnika z obrotem.

**05 \* Zachowaj ostateczny kąt w jednym bajcie.** Sklep pisze `AL` do pola kąta odrodzenia. Wartości zawijają się po 255, tak jak robi to odlewanie bez znaku. Otaczające źródło również przekształca ten kąt i prędkość w prędkość.

Zespół wybiera gałąź pierścienia celowanego, obliczenie celu i końcowy magazyn. Powyższy C++ jest czytelnym podsumowaniem. Poniższe kontrole kompilatora dotyczą utrzymywanego źródła w połączonym projekcie.

Przeczytaj utrzymane źródło pierścienia i celu

Pierścień makro \* TH04 oddział, fragment

```
angle_offset = (i * BULLET_ANGLE_FULL_TURN) / count;
if (i >= (count - 1)) {
    group_complete = true;
}
goto aim_or_no_aim;
```

Kąt i prędkość \* fragment źródła

```
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);
```

[Makro pierścienia](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add_impl.hpp#L4) · [Cel i źródło prędkości](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add.cpp#L422) · [Reprezentacja kąta](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/types.hpp#L6)

## Sprawdzanie utrzymywanego źródła

Zarejestrowane kontrole projektu TH04 kompilują kod generowania pocisków, w tym ten pomocnik, z przypiętym łańcuchem narzędzi Turbo C++ 4.0 J.

### 2139 pasujących bajtów

Skompilowany kod generowania punktorów pasuje do 2139-bajtowej sekcji oryginalnego pliku wykonywalnego.

### Dwie czyste Kompilacje

Dwie oddzielne Kompilacje dają te same pasujące bajty. Zapisane skróty wejściowe odpowiadają wyświetlonemu tutaj utrzymywanemu źródłu.

Zarejestrowany 3 października 2026 roku. [Przeczytaj kontrole kompilatora](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/reconstruction/product/TH04_SEMANTIC_BULLET_GENERATION_V1236.md#validation).

Tożsamość celu i zakres analizy

|  |  |
| --- | --- |
| Oryginalny cel | `MAIN.EXE`, 156 258 bajtów, DOS MZ |
| Wpis pomocnika | `0x2cfc8` w załadowanym obrazie REA |
| Oryginalny plik offset | `0x1e7c8`, zwrócony przez `address_to_file_offset` |
| Rejestrowana Kontrola kodu | REA 4.1.0 \* 7 października 2026 |

Kontrole kompilatora obejmują pełną sekcję bullet-add code, w tym tego pomocnika. Porównują również wkład Mapy i nakładające się relokacje.

REA zweryfikował statyczny obraz obciążenia DOS w segmencie obciążenia `0x1000`. Jego adresy opisują ten obraz analizy. Wynik funkcji zgłasza 503 bajty treści w dwóch zakresach w zakresie 517 bajtów; wybrane instrukcje powyżej znajdują się w tych zgłaszanych zakresach.

Nazwy źródeł i kontrole kompilatora pochodzą z punktu kontrolnego TH04 `0d72e980`. Wcześniejsze obserwacje rekonstrukcji wykorzystywały własne skrypty analityczne projektu; ta strona dodaje nową inspekcję REA tego samego oryginalnego celu. Tożsamość dostarczonej gry jest przypięta przez manifest repozytorium, a niezależne pochodzenie nieskazitelnego zrzutu jest nadal otwarte.

Rysunek ilustruje obliczenie kąta. Sterowanie pełną grą, czas i zachowanie sprzętowe PC-98 mają oddzielne kontrole środowiska wykonawczego w projekcie rekonstrukcji.

## Pełna rekonstrukcja TH04

Projekt buduje cztery produkty dos gry z utrzymanego C++ i assembly. Poza generowaniem pocisków, źródło obejmuje etapy, bossów, renderowanie, wprowadzanie, menu, zakończenia i obsługę punktów.

[Poznaj repozytorium TH04](https://github.com/N0zoM1z0/th04)

- [Źródło generowania pocisków](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/src/main/bullet/add.cpp#L292)Kompletny Pomocnik, inne typy wzorów i strojenie szablonów.
- [Dos build and run guide](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/DOS_BUILD.md)Zbuduj źródło i przetestuj je w przepływie pracy emulatora PC-98 projektu.
- [Aktualny stan projektu](https://github.com/N0zoM1z0/th04/blob/0d72e9801a5c14c10384efcbb6734ceccb74ee63/docs/RE_HANDOFF.md)Weryfikacja DOS i oddzielny natywny port x64.
