Nghiên cứu điển hình * Touhou 4: Lotus Land Story

XÂY DỰNG LẠI TH04 ' s
mẫu đạn.

Một vòng đạn bắt đầu bằng một phép tính góc ngắn. SỬ DỤNG REA để kiểm tra chức năng dos ban đầu, sau đó làm theo hướng dẫn của NÓ vào C++có thể đọc được.

PC-98 * 16-bit DOS * c++ và lắp ráp

Xem TÁI THIẾT TH04

Từ hướng dẫn ban đầu để kiểm tra nguồn

  1. 01 * Trò Chơi GốcCHÍNH.EXETỆP THỰC thi PC-98 và trình trợ giúp góc đạn của NÓ.
  2. 02 * Kiểm tra VỚI REA Hướng dẫn + tài liệu tham khảoXác minh mã DOS đã tải và đọc phép tính góc từ tệp thực thi.
  3. 03 * Đọc C CKhông gian → mục tiêu → xoayKết nối từng hoạt động với việc tái thiết được duy trì.
  4. 04 * Kiểm tra nguồn2,139 byte phù hợpKiểm tra trình biên dịch đã ghi bao gồm mã tạo đạn có chứa trình trợ giúp này.
REA trả về mã gốc và bằng chứng phân tích của nó. DỰ án TH04 cung cấp các kiểm tra nguồn và trình biên dịch được duy trì.

Làm thế nào một chiếc nhẫn nhắm vào người chơi

Cuộc tấn công của Elly yêu cầu một chiếc nhẫn nhắm với số lượng ban đầu là 16. Một người trợ giúp tính toán hướng của mỗi viên đạn. Cùng một vòng có thể đối mặt với một hướng cố định hoặc quay về phía người chơi.

Agent mã hóa của bạn

SỬ DỤNG REA để tìm CÁCH TH04 tạo ra một vòng đạn và nhắm vào người chơi. Giải thích tính toán và hiển thị mã.

Một lời nhắc ví dụ, với thanh toán thực thi và tái thiết ban đầu có sẵn tại địa phương.

TH04 lưu trữ một lượt theo chiều kim đồng hồ đầy đủ trong 256 đơn vị góc. Đối với 16 viên đạn, mỗi chỉ số thêm 16 đơn vị: 0, 16, 32, …, 240. Thêm hướng của người chơi xoay các vị trí đó lại với nhau.

Hai sơ đồ của một vòng 16 viên đạn. Vòng cố định bắt đầu ở góc không. Thêm một hướng chơi của 40 xoay mỗi hướng bằng cùng một số tiền; các điểm đạn đầu tiên được đánh dấu về phía người chơi. Cả hai đều giữ khoảng cách 16 đơn vị góc hoặc 22,5 độ.
Một minh họa của toán học góc phục hồi cho đếm 16, hướng máy nghe nhạc 40 và mẫu xoay 0. Hình mở

Mẫu bắn trong nguồn được phục hồi

Elly ' s ring attack * đoạn trích nguồn
bullet_template.angle = 0;
bullet_template.group = BG_RING_AIMED;
bullet_template.count = 16;
bullet_template_tune();

Những dòng này chọn mẫu trước khi điều chỉnh độ khó và hiệu suất. Đọc nguồn của cuộc tấn công.

REA trả về gì

Chúng tôi kiểm tra bullet_velocity_and_angle_set(), chức năng đặt vận tốc và góc của mỗi viên đạn. REA trả về hướng dẫn, mã giả và tài liệu tham khảo. Ba phần của kết quả đó giải thích mô hình.

  1. Kiểm tra hình ẢNH DOS trước khi đọc mã của nó

    Agent → REA
    open_binary
    {"path": "MAIN.EXE"}
    
    inspect_native_load_image
    {}
    REA → agent * các trường được chọn
    status: "verified"
    format: "dos-mz"
    load_segment: 4096
    header_bytes: 6144
    module_bytes: 150114

    Việc kiểm tra liên kết mã đã tải và các bản ghi di dời đến tệp thực thi được cung cấp. Đường dẫn trên được rút ngắn để hiển thị.

  2. Đọc nhân và chia của chiếc nhẫn

    Agent → REA · analyze_function
    {"procedure": "0x2cfc8"}
    REA → agent · trích đoạn hướng dẫn
    0x2d0eb: MOV AX, SI
    0x2d0ed: SHL AX, 0x8
    0x2d0f0: MOV DL, byte ptr [0x53af]
    0x2d0f9: IDIV BX

    SI giữ chỉ số đạn. Sự thay đổi nhân nó với 256, sau đó phép chia sử dụng số đếm đọc từ DS:53AF. Tên nguồn duy trì trường đó bullet_template.count. Trình tự hoàn chỉnh xuất hiện bên dưới.

  3. Tìm nơi mẫu quay về phía người chơi

    Kết quả chức năng tương tự * aim trích đoạn
    0x2d190: SUB AX, word ptr [0x53a6]
    0x2d198: SUB AX, word ptr [0x53a4]
    0x2d19d: CALLF 0x1000:1da8
    0x2d1a2: ADD word ptr [BP + -0x2], AX
    Tương Ứng Duy Trì C C
    group_angle_offset += iatan2(
      player_pos.cur.y - bullet_template.origin.y,
      player_pos.cur.x - bullet_template.origin.x
    );

    Các toán hạng hướng dẫn phơi bày hai sự khác biệt tọa độ và một trợ giúp hướng. Giá trị trả về của nó được thêm vào góc vòng tương đối. Tên nguồn làm cho các địa chỉ đó có thể đọc được; REA cho phép tác nhân kiểm tra các hoạt động ban đầu đằng sau chúng.

Từ lắp Ráp Đến có Thể đọc Được c C

Chọn một bước để khớp các hướng dẫn ban đầu với phép tính góc. Bản tóm tắt này theo đường dẫn vòng nhắm; nguồn đầy đủ cũng xử lý chênh lệch, ngăn xếp và các mẫu ngẫu nhiên.

REA * hướng dẫn 16-bit gốc
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ó thể đọc Được C++ * tóm tắt vòng nhắm
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 * Đọc chỉ số đạn. Đối số ngăn xếp được tải vào SI. Trong vòng 16 viên đạn, chỉ số thành viên này chạy từ 0 đến 15.

Việc lắp ráp chọn nhánh vòng nhắm, tính toán mục tiêu và cửa hàng cuối cùng. C++ ở trên là một bản tóm tắt có thể đọc được. Kiểm tra trình biên dịch bên dưới áp dụng cho nguồn được duy trì trong dự án được liên kết.

Đọc vòng duy trì và mục tiêu nguồn
Vòng macro * chi NHÁNH TH04, đoạn trích
angle_offset = (i * BULLET_ANGLE_FULL_TURN) / count;
if (i >= (count - 1)) {
    group_complete = true;
}
goto aim_or_no_aim;
Góc và vận tốc * trích đoạn nguồn
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);

Vòng macro · Mục tiêu và vận tốc nguồn · Biểu diễn góc

Kiểm tra nguồn duy trì

CÁC kiểm tra được ghi LẠI CỦA DỰ án TH04 biên dịch mã tạo đạn, bao gồm cả trình trợ giúp này, với chuỗi công cụ Turbo C 4 4.0 J được ghim.

2,139 byte phù hợp

Mã tạo đạn được biên dịch khớp với phần 2.139 byte của tệp thực thi ban đầu.

Hai tòa nhà sạch sẽ

Hai bản dựng riêng biệt tạo ra cùng một byte phù hợp. Các băm đầu vào được ghi lại khớp với nguồn được duy trì được hiển thị ở đây.

Thu âm vào ngày 3 tháng 10 năm 2026. Đọc kiểm tra trình biên dịch.

Phạm vi phân tích và nhận dạng mục tiêu
Mục tiêu ban đầu MAIN.EXE, 156,258 byte, DOS MZ
Mục trợ giúp 0x2cfc8 TRONG HÌNH ẢNH ĐƯỢC tải CỦA REA
Tập tin ban đầu bù đắp 0x1e7c8, trả lại bởi address_to_file_offset
Kiểm tra mã được ghi lại REA 4.1.0 * 7 tháng mười 2026

Kiểm tra trình biên dịch bao gồm phần bullet-add code hoàn chỉnh, bao gồm cả trình trợ giúp này. Họ cũng so sánh ĐÓNG góp BẢN đồ của nó và di dời chồng chéo.

REA đã xác minh hình ảnh tải DOS tĩnh ở phân đoạn tải 0x1000. Địa chỉ của nó mô tả hình ảnh phân tích đó. Kết quả hàm báo cáo 503 byte cơ thể trong hai phạm vi trong khoảng 517 byte; các hướng dẫn được chọn ở trên nằm trong các phạm vi được báo cáo đó.

Tên nguồn và kiểm tra trình biên dịch đến từ TRẠM KIỂM SOÁT TH04 0d72e980. Các quan sát tái thiết trước đó đã sử dụng các kịch bản phân tích riêng của dự án; trang này thêm một kiểm tra REA mới của cùng một mục tiêu ban đầu. Danh tính của trò chơi được cung cấp được ghim bởi biểu hiện kho lưu trữ của nó, với nguồn gốc tự đổ nguyên sơ độc lập vẫn còn mở.

Hình minh họa tính toán góc. Điều khiển đầy đủ trò chơi, thời gian VÀ HÀNH vi PHẦN CỨNG PC-98 có kiểm tra thời gian chạy riêng biệt trong dự án tái thiết.

VIỆC TÁI THIẾT TH04 đầy đủ

Dự án xây dựng bốn sản phẩm dos của trò chơi từ C++ và lắp ráp được duy trì. Ngoài bullet generation, nguồn bao gồm các giai đoạn, ông chủ, kết xuất, đầu vào, menu, kết thúc và xử lý điểm.

Khám PHÁ KHO LƯU TRỮ TH04

Hàng đầu