Phase 1a (boot slice): 30 instructions at 0xBFC00000, compiles clean. Phase 1b (instruction coverage): 54 opcodes implemented in strict_translator, 44,629 walker-reachable instructions covered, 0 missing. Phase 1c (function discovery): 76 functions from 2 seeds, 2,988 instructions, 199 call edges, 27 indirect jumps. All validated through StrictTranslator. Phase 1d (indirect control flow): 27 sites classified — 21 A0/B0/C0 dispatch stubs, 4 computed calls, 2 computed tail calls. Ghidra cross-referenced with 0 disagreements. Phase 1e (relocation): ROM-to-RAM copy at FUN_bfc00420 proven with both Ghidra (static) and DuckStation (runtime). 69 address aliases, 68/69 function entries match byte-for-byte in RAM. Normalization rule documented. Includes PRINCIPLES.md and DEBUG.md adapted from recomp-template. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.1 KiB
PRINCIPLES.md
Global Debugging & Reverse Engineering Principles
This document is the SINGLE source of truth for all rules. All other files reference this. Nothing overrides this.
1. CORE PHILOSOPHY
We do not guess. We do not explore blindly. We do not fix symptoms.
We identify:
- The exact point of divergence
- The exact state difference
- The exact instruction or function responsible
Then we fix that — and only that.
2. STATE OVER THEORY
If two systems behave differently, then their state differs.
All debugging reduces to:
- Capturing state
- Comparing state
- Finding the first difference
Do not theorize causes without state evidence.
3. FIRST DIVERGENCE (CRITICAL)
Never debug the final symptom.
Always find:
The FIRST moment where expected != actual
If you are not identifying the first divergence, you are doing it wrong.
4. TEMPORAL DEBUGGING
Bugs are about WHEN, not WHAT.
Reason in time:
- What happened before this?
- What changed?
5. WRITE VS READ BUGS
Determine the class:
Write-time:
- Wrong data written
Read-time:
- Correct data, wrong usage
Do not mix these.
6. TRACE THE WRITER
When state differs, find:
- WHO wrote it
- WHEN it was written
- WHY it differs
7. FIX THE SOURCE
Invalid:
- Clamping
- Skipping logic
- Hardcoding values
Valid:
- Fixing the producing logic
- Fixing execution order
- Reproducing missing state
8. MINIMAL FIXES
The correct fix:
- Smallest possible change
- Matches original system behavior
9. STRUCTURED DATA ONLY
Use:
- Ring buffers
- State snapshots
- Structured JSON artifacts
Avoid:
- printf spam
- unstructured logs
- log files of any kind
10. BUILD TOOLS, NOT GUESSWORK
If you cannot answer something: -> build a tool to answer it
11. NEVER DEBUG BLIND
If you say:
- "maybe"
- "likely"
You are missing data.
Stop and gather it.
12. STUBS (ABSOLUTE RULE)
NO STUBS — EVER
If execution reaches unknown code:
- STOP
- Identify target
- Fix discovery/codegen
Never simulate behavior.
13. FUNCTION DISCOVERY
A dispatch miss is a graph failure.
Fix:
- function finder
- codegen
Never patch output.
14. SUCCESS DEFINITION
A bug is fixed only when:
- Root cause identified
- Divergence explained
- Fix addresses cause
- Behavior matches reference
15. DISTRUST TOOLING
At the start of every session, validate that tools are doing what you think they're doing. Run a known-good query, check the output by hand, verify file paths resolve where you expect.
Never trust:
- That a previous session's tool still works the same way
- That generated output matches what you asked for
- That a grep/awk pipeline found all matches
When you build a new tool or instrument, verify its FIRST output manually before relying on it for analysis.
16. ORACLES
Truth comes from two sources:
- Ghidra for what the code is supposed to do (static analysis)
- DuckStation for what real PS1 hardware does at runtime (dynamic oracle)
Use both, never just one. Don't guess. Don't say "probably". If you cannot answer a question from Ghidra or DuckStation, the answer is "I don't know yet" — not a confident guess.