Estudo de caso · Touhou 4: História da Lotus Land

Reconstrução de TH04
padrões de bala.

Um anel de balas começa com um cálculo de ângulo curto. Use REA para inspecionar a função DOS original e, em seguida, siga suas instruções em C++legível.

PC-98 · 16-bit DOS * C++ e montagem

Ver a reconstrução TH04

Das instruções originais à fonte verificada

  1. 01 * jogo OriginalPrincipal.EXEO executável PC-98 e seu auxiliar de ângulo de bala.
  2. 02 * inspeccionar com REA Instruções + referênciasVerifique o código dos carregado e leia o cálculo do ângulo do executável.
  3. 03 * leia o c++Espaço * objectivo * rotaçãoLigar cada operação à reconstrução mantida.
  4. 04 * verificar a fonte2.139 bytes correspondentesAs verificações do compilador gravadas cobrem o código de geração de marcadores que contém este auxiliar.
REA retorna o código original e sua evidência de análise. O projeto TH04 fornece as verificações de origem e compilador mantidas.

Como um anel visa o jogador

O ataque de Elly solicita um anel apontado Com uma contagem inicial de 16. Um auxiliar calcula a direção de cada bala. O mesmo anel pode estar voltado para uma direção fixa ou virar em direção ao jogador.

O seu agente de codificação

Use REA para descobrir como TH04 cria um anel de balas e o aponta para o jogador. Explique o cálculo e mostre o código.

Um exemplo de prompt, com o executável original e o checkout de reconstrução disponíveis localmente.

TH04 armazena uma volta completa no sentido horário em 256 unidades do ângulo. Para 16 marcadores, cada índice adiciona 16 unidades: 0, 16, 32, …, 240. Adicionar a direção do jogador gira essas posições juntas.

Dois diagramas de um anel de 16 balas. O anel fixo começa no ângulo zero. Adicionar uma direção de Jogador de 40 gira todas as direções na mesma quantidade; o primeiro marcador destacado aponta para o jogador. Ambos mantêm um espaçamento de 16 unidades de ângulo, ou 22,5 graus.
Uma ilustração da matemática do ângulo recuperado para a contagem 16, direção do jogador 40 e rotação do Modelo 0. Figura aberta

O modelo de disparo na fonte recuperada

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

Essas linhas selecionam o padrão antes da dificuldade e do ajuste de desempenho. Leia a fonte do ataque.

O que REA retorna

Nós inspecionamos bullet_velocity_and_angle_set(), a função que define a velocidade e o ângulo de cada bala. REA retorna suas instruções, pseudocódigo e referências. Três partes desse resultado explicam o padrão.

  1. Verifique a imagem do DOS antes de ler seu código

    Agente REA
    open_binary
    {"path": "MAIN.EXE"}
    
    inspect_native_load_image
    {}
    REA extraterritorial * campos seleccionados
    status: "verified"
    format: "dos-mz"
    load_segment: 4096
    header_bytes: 6144
    module_bytes: 150114

    A verificação vincula o código carregado e os registros de realocação ao executável fornecido. O caminho acima é encurtado para exibição.

  2. Leia o anel multiplicar e dividir

    Agente REA · analyze_function
    {"procedure": "0x2cfc8"}
    REA7 agente * excerto de instruções
    0x2d0eb: MOV AX, SI
    0x2d0ed: SHL AX, 0x8
    0x2d0f0: MOV DL, byte ptr [0x53af]
    0x2d0f9: IDIV BX

    SI mantém o índice de marcadores. O deslocamento o multiplica por 256, então a divisão usa a contagem lida de DS:53AF. Os nomes de origem mantidos nesse campo bullet_template.count. A sequência completa é apresentada abaixo.

  3. Encontre onde o padrão gira em direção ao jogador

    Resultado da mesma função * trecho aim
    0x2d190: SUB AX, word ptr [0x53a6]
    0x2d198: SUB AX, word ptr [0x53a4]
    0x2d19d: CALLF 0x1000:1da8
    0x2d1a2: ADD word ptr [BP + -0x2], AX
    C++mantido correspondente
    group_angle_offset += iatan2(
      player_pos.cur.y - bullet_template.origin.y,
      player_pos.cur.x - bullet_template.origin.x
    );

    Os operandos de instrução expõem duas diferenças de coordenadas e um auxiliar de direção. O seu valor de retorno é adicionado ao ângulo relativo do anel. Os nomes de origem tornam esses endereços legíveis; REA permite que o agente verifique as operações originais por trás deles.

Da montagem ao C++legível

Selecione uma etapa para corresponder às instruções originais com o cálculo do ângulo. Este resumo segue a trajectória do anel visado; a fonte completa também lida com spreads, stacks e padrões aleatórios.

REA * instruções originais de 16 bits
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++ legível · resumo do anel direcionado
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 * leia o índice do marcador. O argumento stack é carregado em SI. Num anel de 16 marcadores, este índice de membros vai de 0 a 15.

O conjunto selecciona a ramificação do anel de mira, o cálculo da mira e o armazenamento final. O C++ acima é um resumo legível. As verificações do compilador abaixo se aplicam à fonte mantida no projeto vinculado.

Leia o anel mantido e aim fonte
Macro do anel * ramificação TH04, excerto
angle_offset = (i * BULLET_ANGLE_FULL_TURN) / count;
if (i >= (count - 1)) {
    group_complete = true;
}
goto aim_or_no_aim;
Ângulo e velocidade * excerto da fonte
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);

Anel macro · Alvo e fonte de velocidade · Representação do ângulo

Verificação da fonte mantida

As verificações registadas do projecto TH04 compilam o código de geração de marcadores, incluindo este auxiliar, com a sua cadeia de ferramentas Turbo C++ 4.0 j fixada.

2.139 bytes correspondentes

O código compilado de geração de marcadores corresponde a uma seção de 2.139 bytes do executável original.

Duas construções limpas

Duas compilações separadas produzem os mesmos bytes correspondentes. Os hashes de entrada gravados correspondem à fonte mantida mostrada aqui.

Gravado em 3 de outubro de 2026. Leia as verificações do compilador.

Identidade-alvo e âmbito de análise
Alvo Original MAIN.EXE, 156.258 bytes, dos MZ
Entrada auxiliar 0x2cfc8 na imagem carregada de REA
Deslocamento do ficheiro Original 0x1e7c8, devolvido por address_to_file_offset
Inspecção do Código registado REA 4.1.0 * 7 de outubro de 2026

As verificações do compilador cobrem a seção completa do código de adição de marcadores, incluindo este auxiliar. Eles também comparam a contribuição do mapa e a deslocalização sobreposta.

REA verificou a imagem estática de Carga Dos no segmento de carga 0x1000. Os seus endereços descrevem essa imagem de análise. O resultado da função reporta 503 bytes de corpo em dois intervalos num intervalo de 517 bytes; as instruções seleccionadas acima situam-se nesses intervalos comunicados.

Os nomes de origem e as verificações do compilador vêm do ponto de verificação TH04 0d72e980. As observações de reconstrução anteriores utilizaram os próprios scripts de análise do projecto; esta página inclui uma nova inspecção REA do mesmo alvo original. A identidade do jogo fornecido é fixada por seu manifesto de repositório, com proveniência independente de despejo intocado ainda aberta.

A figura ilustra o cálculo do ângulo. Os controlos completos do jogo, a temporização e o comportamento do hardware PC-98 têm verificações de tempo de execução separadas no projecto de reconstrução.

A reconstrução completa do TH04

O projeto constrói os quatro produtos DOS do jogo a partir de C++ e assembly mantidos. Além da geração de marcadores, a fonte abrange estágios, chefes, renderização, entrada, menus, finais e manipulação de pontuação.

Explore o repositório TH04

Top