Files
psxrecomp/PRINCIPLES.md
T
Matthew Stanley 7c40d33db3 Phase 1 complete: recompiler proven correct on SCPH1001.BIN
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>
2026-04-11 21:26:04 -07:00

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:

  1. The exact point of divergence
  2. The exact state difference
  3. 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:

  1. STOP
  2. Identify target
  3. 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:

  1. Root cause identified
  2. Divergence explained
  3. Fix addresses cause
  4. 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.