Caso di studio · Touhou 4: Lotus Land Story

Ricostruzione di TH04
modelli di proiettile.

Un anello di proiettili inizia con un calcolo dell'angolo corto. Utilizzare REA per ispezionare la funzione DOS originale, quindi seguire le sue istruzioni in C++leggibile.

PC-98 * DOS a 16 bit * C++ e assemblaggio

Visualizza la ricostruzione TH04

Dalle istruzioni originali alla fonte controllata

  1. 01 * Gioco originalePRINCIPALE.EXEL'eseguibile PC-98 e il suo helper bullet-angle.
  2. 02 * Ispezionare con REA Istruzioni + riferimentiVerificare il codice DOS caricato e leggere il calcolo dell'angolo dall'eseguibile.
  3. 03 * Leggere il C++Spazio → obiettivo → ruotaCollegare ogni operazione alla ricostruzione mantenuta.
  4. 04 * Controllare la fonte2,139 byte corrispondentiI controlli del compilatore registrati coprono il codice di generazione bullet che contiene questo helper.
REA restituisce il codice originale e le sue prove di analisi. Il progetto TH04 fornisce i controlli di origine e compilatore mantenuti.

Come un anello mira al giocatore

L'attacco di Elly richiede un anello mirato con un conteggio iniziale di 16. Un aiutante calcola la direzione di ogni proiettile. Lo stesso anello può affrontare una direzione fissa o girare verso il giocatore.

Il tuo agente di codifica

Usa REA per scoprire come TH04 crea un anello di proiettili e lo mira al giocatore. Spiega il calcolo e mostra il codice.

Un prompt di esempio, con l'eseguibile originale e il checkout di ricostruzione disponibili localmente.

TH04 memorizza una rotazione completa in senso orario in 256 unità angolari. Per 16 punti, ogni indice aggiunge 16 unità: 0, 16, 32, …, 240. Aggiungendo la direzione del giocatore ruota insieme quelle posizioni.

Due diagrammi di un anello a 16 proiettili. L'anello fisso inizia dall'angolo zero. L'aggiunta di una direzione del giocatore di 40 ruota ogni direzione dello stesso importo; il primo punto evidenziato punta verso il giocatore. Entrambi mantengono una spaziatura di 16 unità angolari o 22,5 gradi.
Un'illustrazione della matematica dell'angolo recuperato per il conteggio 16, la direzione del giocatore 40 e la rotazione del modello 0. Apri figura

Il modello di cottura nella fonte recuperata

Elly's ring attack * fonte estratto
bullet_template.angle = 0;
bullet_template.group = BG_RING_AIMED;
bullet_template.count = 16;
bullet_template_tune();

Queste linee selezionano il modello prima della difficoltà e della messa a punto delle prestazioni. Leggi la fonte dell'attacco.

Cosa restituisce REA

Controlliamo bullet_velocity_and_angle_set(), la funzione che imposta la velocità e l'angolo di ogni proiettile. REA restituisce le sue istruzioni, pseudocodice e riferimenti. Tre parti di questo risultato spiegano il modello.

  1. Controllare l'immagine DOS prima di leggere il suo codice

    Agente → REA
    open_binary
    {"path": "MAIN.EXE"}
    
    inspect_native_load_image
    {}
    REA → agente * campi selezionati
    status: "verified"
    format: "dos-mz"
    load_segment: 4096
    header_bytes: 6144
    module_bytes: 150114

    Il controllo lega il codice caricato e i record di rilocazione all'eseguibile fornito. Il percorso sopra è abbreviato per la visualizzazione.

  2. Leggi l'anello moltiplica e dividi

    Agente → REA · analyze_function
    {"procedure": "0x2cfc8"}
    REA → agente * estratto di istruzioni
    0x2d0eb: MOV AX, SI
    0x2d0ed: SHL AX, 0x8
    0x2d0f0: MOV DL, byte ptr [0x53af]
    0x2d0f9: IDIV BX

    SI contiene l'indice proiettile. Lo spostamento lo moltiplica per 256, quindi la divisione utilizza il conteggio letto da DS:53AF. I nomi di origine mantenuti quel campo bullet_template.count. La sequenza completa appare sotto.

  3. Trova dove il modello gira verso il giocatore

    Stesso risultato di funzione * estratto aim
    0x2d190: SUB AX, word ptr [0x53a6]
    0x2d198: SUB AX, word ptr [0x53a4]
    0x2d19d: CALLF 0x1000:1da8
    0x2d1a2: ADD word ptr [BP + -0x2], AX
    Corrispondente mantenuto C++
    group_angle_offset += iatan2(
      player_pos.cur.y - bullet_template.origin.y,
      player_pos.cur.x - bullet_template.origin.x
    );

    Gli operandi di istruzione espongono due differenze di coordinate e un assistente di direzione. Il suo valore di ritorno viene aggiunto all'angolo dell'anello relativo. I nomi di origine rendono leggibili quegli indirizzi; REA consente all'agente di controllare le operazioni originali dietro di loro.

Dall'assembly al C++leggibile

Selezionare un passaggio che corrisponda alle istruzioni originali con il calcolo dell'angolo. Questo riepilogo segue il percorso dell'anello mirato; la fonte completa gestisce anche spread, stack e modelli casuali.

REA * istruzioni originali a 16 bit
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
C++ leggibile * riepilogo dell'anello mirato
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 * Leggere l'indice proiettile. L'argomento stack viene caricato in SI. In un anello a 16 proiettili, questo indice membro va da 0 a 15.

L'assemblaggio seleziona il ramo dell'anello di mira, il calcolo dell'obiettivo e l'archivio finale. Il C++ sopra è un riassunto leggibile. I controlli del compilatore riportati di seguito si applicano all'origine mantenuta nel progetto collegato.

Leggi l'anello mantenuto e la fonte aim
Macro anello * Ramo TH04, estratto
angle_offset = (i * BULLET_ANGLE_FULL_TURN) / count;
if (i >= (count - 1)) {
    group_complete = true;
}
goto aim_or_no_aim;
Angolo e velocità * fonte estratto
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);

Anello macro · Sorgente di mira e velocità · Rappresentazione angolare

Verifica della fonte mantenuta

I controlli registrati del progetto TH04 compilano il codice di generazione bullet, incluso questo helper, con la sua toolchain Turbo C++ 4.0 J bloccata.

2,139 byte corrispondenti

Il codice di generazione bullet compilato corrisponde a una sezione di 2.139 byte dell'eseguibile originale.

Due build pulite

Due build separate producono gli stessi byte corrispondenti. Gli hash di input registrati corrispondono alla sorgente mantenuta mostrata qui.

Registrato il 3 ottobre 2026. Leggi i controlli del compilatore.

Identità target e ambito di analisi
Obiettivo originale MAIN.EXE, 156,258 byte, DOS MZ
Helper entry 0x2cfc8 nell ' immagine caricata di REA
Offset file originale 0x1e7c8, restituito da address_to_file_offset
Ispezione del codice registrato REA 4.1.0 * 7 Ottobre 2026

I controlli del compilatore coprono la sezione completa del codice bullet-add, incluso questo helper. Confrontano anche il suo contributo alla MAPPA e il trasferimento sovrapposto.

REA verificato l'immagine di carico statico DOS al segmento di carico 0x1000. I suoi indirizzi descrivono quell'immagine di analisi. Il risultato della funzione riporta 503 byte del corpo in due intervalli su un intervallo di 517 byte; le istruzioni selezionate sopra si trovano in quegli intervalli riportati.

I nomi dei sorgenti e i controlli del compilatore provengono dal checkpoint TH04 0d72e980. Le precedenti osservazioni di ricostruzione utilizzavano gli script di analisi del progetto; questa pagina aggiunge una nuova ispezione REA dello stesso obiettivo originale. L'identità del gioco in dotazione è bloccata dal suo repository manifest, con la provenienza indipendente di pristine-dump ancora aperta.

La figura illustra il calcolo dell'angolo. I controlli di gioco completi, i tempi e il comportamento hardware PC-98 hanno controlli di runtime separati nel progetto di ricostruzione.

La ricostruzione completa TH04

Il progetto costruisce quattro prodotti DOS del gioco da mantenuto C++ e assembly. Oltre alla generazione di proiettili, la fonte copre fasi, boss, rendering, input, menu, finali e gestione dei punteggi.

Esplora il repository TH04

Cima