Skip to content
104 changes: 104 additions & 0 deletions .agents/skills/openshc-attempt-bytecode-matching-dll/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Attempt Bytecode Matching DLL

Iteratively improve bytecode matching between a reimplementation and the original binary using the workflow:

**Locate → Setup → Build → Compare → Analyze → Modify → Repeat**

At each iteration, perform the next phase only if the previous one succeeded.

## Workflow

### Locate
- Use the **find-function-implementation** skill to locate the target `.cpp` file.

### Setup
- Ask whether to enable source compilation for the located function.
- Mention that it is assumed the function is already active if declined.
- If yes, invoke **enable-local-function-dev** for the located function.

### Build
Run:

```powershell
.\build --wrap-quiet RelWithDebInfo OpenSHC.dll > $null 2>&1
```

If the build fails:
- Stop the workflow.
- Offer to rerun with verbose output:

```powershell
.\build RelWithDebInfo OpenSHC.dll
```

### Compare
Extract the hexadecimal address from the function comment:

```cpp
// FUNCTION: STRONGHOLDCRUSADER 0x...
```

Run:

```powershell
$env:PYTHONIOENCODING="utf-8"; reccmp/dll/run --wrap-quiet reccmp-reccmp --target STRONGHOLDCRUSADER --verbose <address> 2>$null
```

If the comparison fails or produces no output:
- Stop the workflow.
- Offer to rerun with stderr enabled for diagnosis, noting that the output may be large.

### Analyze
Compare **structure**, not exact bytes.

Treat the following as expected differences:
- proxied function calls
- global resolver addresses

Instead, compare:
- control flow
- call placement
- global access patterns
- local variable ordering
- stack usage
- casts and type conversions

### Modify
Attempt structural improvements without changing program behavior.

Typical changes include:
- reordering local variables
- reordering statements
- introducing or removing temporary variables
- moving casts
- expanding or simplifying expressions
- restructuring control flow

### Repeat
Return to the **Build** phase.

After each iteration:
- report whether the match improved
- explain likely causes of remaining mismatches
- ask whether another iteration should be attempted

If 3–4 consecutive iterations show no improvement, recommend stopping.

### Optional: Enable Struct Implementations
If many diffs appear to be caused by global resolver usage, offer to enable struct implementations.
Note that this will only remove diffs caused by `<offset>` <-> `<StructResolver::Instance>` mismatches if the structure fits.
It will **not** improve structural differences.

If accepted:
1. Find every included `OpenSHC/Globals/...` header used by the function.
2. In each included header, locate its `MACRO_STRUCT_RESOLVER(...)` definition.
3. Change the second macro argument from `false` to `true`.
4. Return to the **Build** phase.
5. Report whether the match improved.

## Principles

- Preserve program behavior at all times.
- Prefer structural changes over logic changes.
- Function calls will always and global accesses will often appear as differences because they are proxied or resolved; compare only their structural placement.
- The user decides whether to continue after every iteration.
179 changes: 179 additions & 0 deletions .agents/skills/openshc-clean-decomp-body/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# Clean Decomp Body

Transforms decompiled C++ function implementations into the project's macro/global style while preserving the original logic.

## Workflow

### Input

Request the function implementation file using **Find Function Implementation**.

Transform the file directly. Do not create a separate replacement snippet unless requested.

### Abort Conditions

Do not transform if:
- The body is empty or contains no meaningful code.
- The code already matches cleaned style:
- Uses `MACRO_CALL` / `MACRO_CALL_MEMBER`.
- Uses `::instance` / `::ptr` for global access.
- Uses `_Func` namespaces inside function macros.
- Already uses correct namespaces and imports.

Report that no transformation is required.

---

## Rules

Preserve:
- Control flow.
- Local variables.
- Conditions.
- Returns.
- Statement order.
- Switch structure.
- Original logic.

Do not:
- Refactor.
- Simplify.
- Remove code.
- Reorder code.

Never invent:
- namespaces
- globals
- singleton names
- imports

If a required transformation cannot be resolved from the implementation or project context, ask for clarification instead of guessing.
Leave all code not covered by these transformation rules unchanged.

---

## Transformation Process

Apply transformations in this order:

### 1. Determine Context

Identify:
- Current class if member function.
- Existing imports.
- Function and class namespaces.
- Required function/global dependencies.

Use this information for all following transformations.

---

### 2. Member Field Access

Member field access might appear through a global in the code, since many are singletons.

Determine from the function signature whether the implementation is a member function: `<class>::<function>(<params>)`

If so, identify the singleton/global representing the current class. For example: `DAT_<class>`

Transform to `this` access:

`DAT_<class>.field` → `this->field`

If the required global cannot be identified, ask for clarification instead of guessing.

---

### 3. Global Access

Convert globals for field access:

`SEC_RNG.currentNumber1` → `SEC_RNG::instance.currentNumber1`

Only use pointer in cases of function calls or pointer assigns:

`&DAT_Global` → `DAT_Global::ptr`

Keep global namespaces.

---

### 4. Function Calls

Replace direct calls:

`Namespace::Function(args)` → `MACRO_CALL(Namespace_Func::Function)(args)`

Replace member calls using:

- the "this" pointer if the current function is a member function of the same class:
`Namespace::Class::Function(&ClassObject, args)` or `Namespace::Class::Function(ClassObject, args)` → `MACRO_CALL_MEMBER(Namespace::Class_Func::Function, this)(args)`

- global objects otherwise:
`Namespace::Class::Function(&Global, args)` or `Namespace::Class::Function(Global, args)` → `MACRO_CALL_MEMBER(Namespace::Class_Func::Function, Global::ptr)(args)`

Rules:
- Keep normal namespaces for classes and functions.
- Only add `_Func` inside macro function references.
- Use the resolved namespace to determine the required `.func.hpp` import.
- Apply transformations recursively, including nested function calls.

---

### 5. Namespace Resolution

Ensure classes, functions, and types use their correct namespaces after transformation.

Rules:
- Macro function references use the `_Func` namespace: `SFX::SFXState_Func::PlaySpeechSFX`
- Types and globals keep their normal namespaces.

Use namespace information to identify required imports.

---

### 6. Imports

Add only required dependency imports.

Rules:
- The current file's relative `.func.hpp` import already exists. Do not add or modify it.
- Add `.func.hpp` imports for called functions/classes.
- Add global `.hpp` imports for accessed globals. Not for the transformed class global.
- Global imports always use `OpenSHC/Globals/<Name>.hpp`.
- All new imports must use the full project path.
- Do not add unused imports.
- Preserve existing include grouping.
- Do not duplicate existing imports.

Example:

```cpp
#include "OpenSHC/Audio/SFX/SFXState.func.hpp"

#include "OpenSHC/Globals/DAT_SFXState.hpp"
```

---

## File Structure

Keep the existing file structure.

Preserve:
- Existing namespace layout.
- Function address comments: `// FUNCTION: STRONGHOLDCRUSADER 0xXXXXXXXX`

---

## Output

Apply the transformation directly to the function implementation file.

The CLI response should only contain a short summary:
- Functions converted to `MACRO_CALL` / `MACRO_CALL_MEMBER`.
- Globals converted to `::instance`, `::ptr`, or `this`.
- Imports added.
- Namespace/type adjustments made.

Do not output the full transformed file unless explicitly requested.
66 changes: 66 additions & 0 deletions .agents/skills/openshc-enable-local-function-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Enable Local Function Development

Configure `cmake/openshc-sources.txt.local` with selected `.cpp` implementations.

## Input

Request a list of functions.

Accepted formats:

- Function: `wipeAICMemory`
- Class/function: `AICState::wipeAICMemory`
- Path: `src/OpenSHC/AI/AICState/wipeAICMemory.cpp`
- Address: `0x004C6D30`

Mixed formats are allowed.

---

## Resolve Inputs

Resolve each input using **Find Function Implementation**.

Rules:

- Deduplicate resolved paths while preserving input order.
- If any input fails to resolve, abort.
- Do not modify files on failure.
- Report the failing input and reason.

---

## Update Configuration

Manage:

`cmake/openshc-sources.txt.local`

Create it if missing.

Rewrite the file contents with the resolved paths. Do not append.

Rules:
- Paths are relative to project root
- Use `/` separators
- Preserve order
- End with newline

Never modify:

`cmake/openshc-sources.txt`

---

## Completion

Output:

```text
Configured <count> files for local development

Files:
<path>
<path>
...
```
Loading