Skip to content

Commit daef294

Browse files
committed
Document stage settings and actor lists
1 parent 4d9af8d commit daef294

4 files changed

Lines changed: 200 additions & 18 deletions

File tree

AGENTS.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# SC6ModdingDocs - Ghidra MCP instructions
2+
3+
The reverse-engineering work runs through `bethington/ghidra-mcp` MCP tools.
4+
The MCP is the authoritative interface for Ghidra - never edit `.gpr` files or invoke Ghidra scripts directly.
5+
The bridge auto-discovers tools from `/mcp/schema`; if a tool name isn't in the schema it doesn't exist.
6+
7+
## Ghidra MCP conventions
8+
9+
The MCP enforces conventions in the tool layer (auto-fix / warn / reject tiers). Don't fight them - they exist because the codebase outgrew prompt-only discipline.
10+
11+
**Tool inventory and dynamic groups**:
12+
13+
`/mcp/schema` is authoritative. Don't guess tool names from training data.
14+
For Ghidra comment work, load the `comment` group and use native comment tools:
15+
`batch_set_comments`, `set_plate_comment`, `set_decompiler_comment`, `set_disassembly_comment`, and `get_plate_comment`.
16+
`set_bookmark` is only for bookmarks and audit breadcrumbs; do not treat it as a substitute for plate, PRE, EOL, or disassembly comments.
17+
18+
If `check_tools` reports a tool callable but the Codex client cannot invoke that endpoint, state that as a client/tool-exposure problem and stop before claiming the Ghidra comments were updated.
19+
20+
**Allowed Ghidra MCP tool groups by task**:
21+
- Default allowed non-malware groups: `analysis`, `comment`, `datatype`, `documentation`, `function`, `listing`, `program`, `symbol`, `xref`
22+
- Function cleanup: `function`, `comment`, `analysis`
23+
- Comment audits: `comment`, `analysis`, `listing`, `xref`
24+
- Struct/type recovery: `datatype`, `xref`, `function`, `symbol`, `analysis`
25+
- Global/data labeling: `symbol`, `datatype`, `listing`, `xref`
26+
- Caller/callee tracing: `xref`, `function`, `listing`
27+
- Documentation transfer and binary comparison: `documentation`, `function`, `listing`
28+
- Program navigation and persistence: `program`, `listing`
29+
30+
Load these groups as needed with `load_tool_group`. The `malware` group remains excluded by default; use it only when the user explicitly requests malware, IOC, or anti-analysis work.
31+
When doing Ghidra reverse-engineering work, opportunistically improve clear function names, variable names, variable types, labels, and structs that are directly relevant to the current analysis.
32+
33+
**Naming**:
34+
- Functions: PascalCase, verb-first. `GetPlayerHealth`, not `playerHealth` or `SKILLS_GetLevel`. Module prefixes (`UPPERCASE_`) are accepted and validated separately.
35+
- Globals: `g_` + Hungarian (`g_dwCount`, `g_pMain`, `g_szPath`).
36+
- Labels: snake_case.
37+
- Struct fields are auto-prefixed on `add_struct_field` / `modify_struct_field` / `create_struct` - pass the logical name (`count`, `next`, `health`); the tool stamps the prefix (`dwCount`, `pNext`, `wHealth`).
38+
39+
**Hungarian quick-ref**:
40+
```
41+
b:byte c:char f:bool n:int/short dw:uint/DWORD w:ushort l:long
42+
fl:float d:double ll:longlong qw:ulonglong ld:float10 h:HANDLE
43+
p:void*/ptr pb:byte* pw:ushort* pdw:uint* pn:int* pp:void**
44+
sz:char*(local) lpsz:char*(param) wsz:wchar_t* lpcsz:const char*(param)
45+
ab:byte[N] aw:ushort[N] ad:uint[N] an:int[N]
46+
g_:global prefix (g_dwCount, g_pMain) pfn:func_ptr (PascalCase, no g_)
47+
Struct pointers: p+StructName (pUnit, pInventory, ppItem for double ptr)
48+
```
49+
50+
**Type normalization**: `undefined1` -> byte, `undefined2` -> ushort, `undefined4` -> uint/int/float/ptr (by usage), `undefined8` -> double/longlong. Use Ghidra builtins (`dword`, `byte`, `ushort`) not Windows aliases (`DWORD`, `BYTE`) when calling `set_local_variable_type`.
51+
52+
## Workflow ordering (load-bearing)
53+
54+
`set_function_prototype` **wipes plate comments**. Do all structural work first:
55+
56+
1. Rename function + set prototype (parallel)
57+
2. Type audit + variable rename (`get_function_variables` -> `set_local_variable_type` -> `rename_variables`)
58+
3. Plate + PRE + EOL comments in one `batch_set_comments` call
59+
4. `analyze_function_completeness` - if fixable deductions > 10 points, address and re-verify
60+
61+
Never rename a variable with a Hungarian prefix (`dw`, `n`, `b`, `p`, `sz`, ...) while its type is still `undefined*`.
62+
Resolve the type first; if undeterminable, use a descriptive name without a type prefix (`questBits` not `dwQuestBits`).
63+
64+
Phantoms (`extraout_*`, `in_*` with undefined types) are decompiler artifacts. Note them in plate-comment Special Cases - don't retry type-setting.
65+
66+
## Gotchas
67+
68+
- **Plate-comment newlines**: passing `\n` literally produces the text `\n` in the comment. Use actual multi-line strings.
69+
- **Register-only variables**: when `set_local_variable_type` fails for a register var, document via `set_decompiler_comment` PRE_COMMENT (`"nIterator: int - loop counter (register-only)"`). The completeness scorer excludes these.
70+
- **Struct access without a struct**: for raw `*(ptr+0x10)` access where no matching struct exists, add EOL comments at each access (`/* +0x10: flags */`) - satisfies the scorer without forcing struct creation.
71+
- `/run_script_inline`, `/run_ghidra_script`, and `run_script` may appear callable in the MCP `program` group. Project policy still forbids using them for Ghidra database edits unless the user explicitly overrides this rule. Use native MCP tools instead.
72+
73+
## Skills available
74+
75+
- `ghidra-doc-function` - full V5 doc workflow (classify -> rename -> type -> comment -> verify) for a single function
76+
- `ghidra-investigate-type` - discover/define a struct from generic-pointer parameters (`int*`/`void*`) and apply it across all callers

docs/reference/symbol-index.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,14 @@ the page link for full context.
251251
| `LuxBattle_SetFrameCacheHitChkDataPtrs` | `0x1402DAE70` | [Stage System: J_StgHitChkData terrain/wall grid](../sc6/stage-system.md#j_stghitchkdata-terrainwall-grid) |
252252
| `LuxBattle_ApplyFrameCacheHitChkDataSetup` | `0x1403CFC20` | [Stage System: J_StgHitChkData terrain/wall grid](../sc6/stage-system.md#j_stghitchkdata-terrainwall-grid) |
253253
| `LuxObject_BuildParamSlots_FromBattleSubstrings_4Slots` | `0x1404208B0` | [Stage System: J_StgHitChkData terrain/wall grid](../sc6/stage-system.md#j_stghitchkdata-terrainwall-grid) |
254-
| `Z_Construct_UClass_ULuxStageAssetPaths` | `0x140BACDB0` | [structures](../sc6/structures.md#uluxstageassetpaths-and-luxstagerawasset) |
255-
| `Z_Construct_UScriptStruct_LuxStageRawAsset` | `0x140BD8C60` | [structures](../sc6/structures.md#uluxstageassetpaths-and-luxstagerawasset) |
256-
| `Z_Construct_UEnum_LuxorGame_ELuxStageAssetType` | `0x140BBF230` | [structures](../sc6/structures.md#uluxstageassetpaths-and-luxstagerawasset) |
254+
| `Z_Construct_UClass_ULuxStageAssetPaths` | `0x140BACDB0` | [structures](../sc6/structures.md#uluxstageassetpaths-luxstagerawasset-and-luxstagesetting) |
255+
| `Z_Construct_UScriptStruct_LuxStageRawAsset` | `0x140BD8C60` | [structures](../sc6/structures.md#uluxstageassetpaths-luxstagerawasset-and-luxstagesetting) |
256+
| `Z_Construct_UScriptStruct_LuxStageSetting` | `0x140BD9120` | [structures](../sc6/structures.md#uluxstageassetpaths-luxstagerawasset-and-luxstagesetting) |
257+
| `Z_Construct_UEnum_LuxorGame_ELuxStageAssetType` | `0x140BBF230` | [structures](../sc6/structures.md#uluxstageassetpaths-luxstagerawasset-and-luxstagesetting) |
258+
| `LuxBattleManager_InitRound_TickTimers_ClearRoundData` | `0x1403FB660` | [Stage System: LuxStageSetting cosmetic flags](../sc6/stage-system.md#luxstagesetting-cosmetic-flags) |
259+
| `LuxBattleManager_StopTimers_IsBattleRunning_WetRatio` | `0x1403EEC20` | [Stage System: LuxStageSetting cosmetic flags](../sc6/stage-system.md#luxstagesetting-cosmetic-flags) |
260+
| `LuxMove_RefreshProvider_CacheMeshesAndParts` | `0x1403CEDE0` | [Stage System: LuxStageSetting cosmetic flags](../sc6/stage-system.md#luxstagesetting-cosmetic-flags) |
261+
| `IsAnomalyStageByStageCodeStr` | `0x140646230` | [Stage System: LuxStageSetting cosmetic flags](../sc6/stage-system.md#luxstagesetting-cosmetic-flags) |
257262
| `LuxBattle_RefreshFrameTerrainCache` | `0x140314480` | [Stage System: J_StgHitChkData terrain/wall grid](../sc6/stage-system.md#j_stghitchkdata-terrainwall-grid) |
258263
| `LuxBattle_AttachStgHitChkData` | `0x140392080` | [Stage System: J_StgHitChkData terrain/wall grid](../sc6/stage-system.md#j_stghitchkdata-terrainwall-grid) |
259264
| `LuxBattle_SampleTerrainAtXZ_Impl` | `0x140391350` | [Stage System: J_StgHitChkData terrain/wall grid](../sc6/stage-system.md#j_stghitchkdata-terrainwall-grid) |
@@ -370,8 +375,9 @@ note on lazy extensions.
370375
| `scbattle_StageBoundaryParams` | `0x40` | [structures](../sc6/structures.md#scbattle-stage-info-globals) |
371376
| `scbattle_StageInfoParam` | `0x120` | [structures](../sc6/structures.md#scbattle-stage-info-globals) |
372377
| `FLuxBattleEventRecord` | `0x18` | [structures](../sc6/structures.md#stage-actor-registration-event-record) |
373-
| `ULuxStageAssetPaths` | class | [structures](../sc6/structures.md#uluxstageassetpaths-and-luxstagerawasset) |
374-
| `LuxStageRawAsset` | `0x18` | [structures](../sc6/structures.md#uluxstageassetpaths-and-luxstagerawasset) |
378+
| `ULuxStageAssetPaths` | class | [structures](../sc6/structures.md#uluxstageassetpaths-luxstagerawasset-and-luxstagesetting) |
379+
| `LuxStageRawAsset` | `0x18` | [structures](../sc6/structures.md#uluxstageassetpaths-luxstagerawasset-and-luxstagesetting) |
380+
| `LuxStageSetting` | `0x03` | [structures](../sc6/structures.md#uluxstageassetpaths-luxstagerawasset-and-luxstagesetting) |
375381
| `LuxBattle_FrameCacheHitChkDataSetup` | `0x22` | [structures](../sc6/structures.md#j_stghitchkdata-frame-cache-setup) |
376382
| `J_StgHitChkData_Header` | `0x30` | [structures](../sc6/structures.md#j_stghitchkdata-serialized-terrainwall-blob) |
377383
| `J_StgHitChkData_CellHeader` | `0x10` | [structures](../sc6/structures.md#j_stghitchkdata-serialized-terrainwall-blob) |

0 commit comments

Comments
 (0)