3.9 KiB
3.9 KiB
| applyTo |
|---|
| ** |
Crusader Ghidra Workflow
- Active target is the raw full-EXE Ghidra program
CRUSADER-RAW.EXEunless explicitly stated otherwise. - Use Ghidra MCP tools for analysis, decompilation, renaming, comments, and xref work.
- Keep analysis batches small: prefer 1-5 functions, labels, or comments at a time.
- Avoid speculative renames. Prefer names that are supported by one of these:
- verified raw mapping from standalone segment work
- direct string evidence
- clear call/field behavior in decompiler or disassembly
- xref relationships to already-named functions
- When porting names from standalone segment extracts into
CRUSADER-RAW.EXE, use only verified base mappings.
Verified Raw Mapping Rules
seg001raw base =0x6E570seg021raw base =0x87170- Porting formula:
raw_full_exe_flat = verified_segment_base + standalone_segment_relative_offset seg001andseg021both contain a keyboard handler; keep the seg001 name asseg001_input_keyboard_handlerto avoid collision.
Working Method
- Prefer a single decompile call first.
- If the decompiler collapses to thunk-heavy output, use one disassembly lookup to confirm the wrapper or parameter setup.
- When
decompile_functionoutput is too large (>~50KB), the result is written to a temp JSON file thatread_filereturns as empty{}. Usedisassemble_functioninstead — it returns inline assembly directly and is fully navigable for large functions. - Add a short decompiler comment when a rename is mapped from verified notes so the provenance stays visible in Ghidra.
- Keep
crusader_decompilation_notes.mdupdated after each verified batch. - Record raw-import addresses alongside original segment-relative offsets when porting names.
- Always use
rename_function_by_address—rename_function(by name) fails with "must have required property 'old_name'" and is broken. Use"function_address": "000c:XXXX"format.
Current Verified Raw-Import Ports
0006:e5d0=cursor_update_hoverfrom seg0010x00600008:7377=entity_count_by_type_afrom seg0210x02070007:28ce=shot_entity_allocfrom seg0010x435e0007:2a19=shot_entity_freefrom seg0010x44a90007:2bc9=projectile_init_vectorfrom seg0010x46590007:3001=entity_fire_weaponfrom seg0010x4a910007:3088=fire_weapon_from_cursorfrom seg0010x4b180007:30e8=projectile_check_hitfrom seg0010x4b780007:319e=projectile_step_updatefrom seg0010x4c2e0007:3298=projectile_trace_rayfrom seg0010x4d280007:371d=projectile_update_tickfrom seg0010x51ad0007:4009=projectile_apply_hitfrom seg0010x5a99
Named 000e: Functions (direct analysis — not segment-ported)
Parser Cluster (000e:34xx–38xx)
000e:345e=record_table_init000e:34cc=record_table_destroy000e:35c6=record_table_release_buffer000e:35ef=record_table_next_slot000e:3639=record_table_parse_buffer000e:3798=record_parser_read_line000e:38f8=record_parser_find_marker
RIFF/Animation Cluster (000e:03xx–2xxx)
000e:2a28=riff_find_chunk_by_type(RIFF LIST/RIFF walker; FourCC match at chunk+8)000e:2104=animation_start(finds "movi" chunk, inits timing ring buffer, kicks advance)000e:12f4=animation_advance_frame(fixed-point 0x1000 timer stepper, ring buffer update)000e:103f=animation_tick(guard wrapper — checks +0xd4 != -1, calls advance_frame)000e:06f7=anim_load_audio_frame(checks "01wb" chunk tag 0x62773130, copies audio into ring buffer)
Constructor/Assert Helpers (000e:22xx–29xx)
000e:223d=assert_alive_sentinel(expects +0xd4 == -1; traps on mismatch)000e:2777=animation_ctor_variant_a(alloc + init flags + chained init/assert/finalize)000e:2860=animation_ctor_variant_b(variant A with extra +0x109 init)000e:2969=animation_ctor_variant_c(default static flag profile +0x4c=0xd)