Skip to content

Commit 69bf8a9

Browse files
committed
docs: unify compatibility policy handbooks
1 parent da64be0 commit 69bf8a9

7 files changed

Lines changed: 147 additions & 21 deletions

File tree

AI/ARCHITECTURE.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,27 @@ For an early-stage repo, a simplified equivalent is acceptable as long as these
114114
- When CGB arrives, prefer one standard CGB model before attempting fine-grained CGB hardware revision support.
115115
- Architecture should allow the same core to run in DMG-family mode or CGB mode without duplicating subsystem implementations.
116116

117+
## Compatibility-policy architecture
118+
119+
- Compatibility policy is a loader/config contract around the T-cycle core, not a second hardware model.
120+
- The project should expose a typed execution-mode concept such as `ExecutionMode::{Strict, Permissive, Experimental}` rather than scattered booleans.
121+
- The project should expose one central `CompatibilityPolicy`-style structure, or an equally explicit equivalent, that at least carries:
122+
- `execution_mode`
123+
- `validation_policy`
124+
- `heuristic_policy`
125+
- `override_policy`
126+
- `diagnostic_policy`
127+
- One central decision point should translate typed cartridge classification, the active compatibility policy, and explicit manual overrides into a final load decision.
128+
- That decision point must not reparse cartridge headers differently per frontend, per mode, or per call site.
129+
- For already supported hardware, switching execution mode must not change T-cycle-visible hardware truth such as timing, arbitration, memory mapping, IRQ behavior, or mapper semantics.
130+
- Mode changes are allowed to affect admission, validation severity, heuristic enablement, manual overrides, diagnostics, and access to explicitly experimental implementations.
131+
- Any temporary exception where a mode changes supported-hardware runtime behavior should be documented as technical debt rather than normalized as ordinary behavior.
132+
- `Strict` is the oracle and CI mode for official accuracy claims.
133+
- `Permissive` is the intended tolerant interactive mode for ordinary users once frontends expose mode selection.
134+
- `Experimental` is for research, bring-up, and partial hardware paths; it must not be treated as evidence for official accuracy claims.
135+
- Save states, replays, and official test artifacts must record the execution mode and active overrides that produced them.
136+
- Restoring or replaying under a different execution mode should fail by default unless a later explicit developer-only conversion workflow is designed on top of the recorded metadata.
137+
117138
## Suggested subsystem boundaries
118139

119140
- CPU: instruction flow, register state, decode/execution state, fine-grained fetch/read/write/internal steps, IME state, interrupt acceptance/dispatch, HALT/STOP semantics, and micro-operation visibility for timing-sensitive hardware interactions
@@ -142,6 +163,7 @@ to immediately materialize as a separate directory.
142163
- system base types
143164
- enums for hardware variants and shared configuration
144165
- structural core configuration
166+
- shared compatibility-policy types such as execution mode and override metadata
145167
- architectural extension points for future variants such as CGB
146168

147169
### `scheduler/`
@@ -266,8 +288,9 @@ to immediately materialize as a separate directory.
266288
- typed cartridge-header parsing over `0x0100-0x014F`
267289
- decoded cartridge capability model including cartridge type, ROM size, RAM size, CGB flag, and SGB flag
268290
- explicit capability metadata for battery-backed RAM, RTC, and rumble derived from the validated header type
269-
- central cartridge factory and validation policy
291+
- central cartridge factory, compatibility-policy consumption, and validation policy
270292
- typed loader result that separates supported cartridge construction from structured special / unsupported classification, preserving raw `0x0147`, detected name, category, and reason
293+
- one central load-decision path that combines cartridge classification, compatibility policy, and explicit overrides into admit / warn / reject results
271294
- concrete cartridge devices such as `NoMbcCartridge`, `Mbc1Cartridge`, `Mbc2Cartridge`, `Mbc3Cartridge`, and `Mbc5Cartridge`
272295
- No MBC family support, including the `0x00`, `0x08`, and `0x09` header variants
273296
- MBC implementations
@@ -313,6 +336,7 @@ to immediately materialize as a separate directory.
313336
- Storage backends such as disk or in-memory adapters should own serialization format, versioning, file naming, path mapping, timestamps, and atomic replacement policy, not cartridge semantics.
314337
- Frontend and tooling layers may decide when to flush, such as on close, on explicit manual save, or via optional auto-flush, but they should do so through the persistence backend rather than through bus hooks or cartridge-local file I/O.
315338
- Cartridge persistence and emulator save states must remain separate systems. Cartridge persistence stores only cartridge-owned hardware state; emulator save states may snapshot the whole machine.
339+
- Emulator save states and replays should also preserve the execution mode and active compatibility overrides that were in effect when they were created.
316340
- Tests and tools must be able to use an in-memory persistence backend so cartridge persistence can be validated without host file I/O.
317341

318342
## Module mapping notes

AI/ROADMAP.md

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,11 @@ They do not move full joypad, serial, audio, or timing-complete PPU implementati
383383
Acceptance criteria: the bus can read `0x0000-0x7FFF` and `0xA000-0xBFFF` without knowing the active MBC, ROM-space writes route to cartridge commands, and header bytes remain visible through ordinary ROM bank `0` reads.
384384
3. Add the cartridge factory.
385385
Acceptance criteria: the loader selects `NoMbc`, `Mbc1`, `Mbc2`, `Mbc3`, `Mbc5`, or a structured special / unsupported classification from `0x0147`, and unsupported types preserve raw `0x0147`, detected name, category, and reason for diagnostics.
386-
4. Close validation and diagnostics policy.
387-
Acceptance criteria: ROM-size and RAM-size metadata are checked explicitly, size mismatches produce useful warnings or errors, special ROM-size codes are not ignored silently, documented-but-unsupported cartridge types fail in a controlled way without mapper fallback, and the project exposes a configurable strict-versus-permissive policy with heuristics disabled by default in strict mode.
386+
4. Define the typed compatibility-policy model.
387+
Scope: one real `ExecutionMode::{Strict, Permissive, Experimental}` type plus a central `CompatibilityPolicy`-style structure carrying validation, heuristic, override, and diagnostic policy.
388+
Acceptance criteria: execution modes are not represented as scattered booleans, one shared policy object exists for loader, tooling, and frontends, and the T-cycle core does not need to read ad hoc global compatibility flags.
389+
5. Close validation and diagnostics policy.
390+
Acceptance criteria: ROM-size and RAM-size metadata are checked explicitly, size mismatches produce useful warnings or errors, special ROM-size codes are not ignored silently, documented-but-unsupported cartridge types fail in a controlled way without mapper fallback, and the project exposes a central strict / permissive / experimental policy with heuristics disabled by default in strict and permissive modes.
388391

389392
##### No MBC milestone
390393

@@ -397,10 +400,25 @@ They do not move full joypad, serial, audio, or timing-complete PPU implementati
397400
4. Add optional external RAM.
398401
Acceptance criteria: `0xA000-0xBFFF` is either explicit "RAM absent" behavior or one linear `8 KiB` RAM window; there is no RAM enable, no RAM banking, no RTC, and battery only changes persistence policy.
399402
5. Harden validation and diagnostics.
400-
Acceptance criteria: No MBC expects `32 KiB` ROM and at most `8 KiB` RAM, inconsistent headers report declared type, declared ROM size, declared RAM size, and actual file size, `0x08` and `0x09` may warn as rare but are not rejected solely for rarity, and strict/permissive/test modes remain configurable.
403+
Acceptance criteria: No MBC expects `32 KiB` ROM and at most `8 KiB` RAM, inconsistent headers report declared type, declared ROM size, declared RAM size, and actual file size, `0x08` and `0x09` may warn as rare but are not rejected solely for rarity, and strict / permissive / experimental mode handling stays centralized.
401404
6. Close integration coverage.
402405
Acceptance criteria: skip-boot and post-`FF50` mapping tests use No MBC as the first closed cartridge baseline in this phase; once Phase 2 real-boot execution exists, the first real-boot cartridge coverage also lands on No MBC before any MBC-dependent validation.
403406

407+
#### Compatibility-policy sequencing across cartridge bring-up
408+
409+
1. Model the policy types.
410+
Scope: `ExecutionMode::{Strict, Permissive, Experimental}` plus a central `CompatibilityPolicy` or equivalent.
411+
Acceptance criteria: execution modes are real types rather than loose booleans, and loader, tooling, and frontends consume one shared compatibility-policy shape.
412+
2. Centralize the category-by-mode decision table.
413+
Scope: resolve `Supported`, `PlannedVariant`, `DocumentedButUnsupported`, `ExperimentalHeuristic`, `AccessorySpecialCase`, and `UnknownCode` through one shared matrix driven by typed cartridge classification.
414+
Acceptance criteria: load / warn / reject behavior is decided centrally, the loader does not duplicate per-mode classification logic, and `Strict`, `Permissive`, and `Experimental` keep supported-hardware runtime semantics identical.
415+
3. Close diagnostics and manual overrides.
416+
Scope: explicit rejection and warning reasons, visible heuristic and partial-path diagnostics, and manual overrides for model, mapper, mode, and validation policy.
417+
Acceptance criteria: loader messages report raw `0x0147`, detected name, category, current mode, and precise reason; overrides are visible in logs and tooling; and no silent mapper invention remains.
418+
4. Integrate execution mode into save states, replays, CI, and tooling.
419+
Scope: persist execution-mode metadata, reject mismatched-mode restore by default, keep CI and oracle comparison on `Strict`, and segregate `Experimental` artifacts.
420+
Acceptance criteria: save states and replay logs record the originating mode and active overrides, strict-mode CI remains the official closure path, and experimental runs cannot be mistaken for oracle evidence.
421+
404422
---
405423

406424
### Phase 2 — CPU and real temporal control
@@ -1198,15 +1216,15 @@ Close the DMG core with a formal validation matrix, strong differential and dete
11981216
Scope: instruction / micro-op / short-window T-cycle tracing, breakpoints and watchpoints on `PC`, memory, MMIO, and cartridge-bank state, plus fast inspection of CPU, scheduler, bus owner, PPU mode / dot / `LY`, DMA, timer, APU, and cartridge / MBC state.
11991217
Acceptance criteria: a blocking divergence can be localized without a long blind rerun, and the project has practical viewers or equivalent dumps for PPU, cartridge / MBC, APU, and IRQ state.
12001218
5. Lock determinism, replay, save/load determinism, soak, and regression retention.
1201-
Scope: same-ROM replay with identical input stream and injected time source, mid-run save/load equivalence, longer-running soak cases, and a permanent regression path for every important hardening bug.
1202-
Acceptance criteria: repeated runs converge exactly under the same inputs and injected time source, save/load continuation matches uninterrupted execution, soak coverage includes at least one real game plus long-running synthetic coverage, and fixed hardening bugs leave behind permanent regression assets.
1219+
Scope: same-ROM replay with identical execution mode, explicit overrides, input stream, and injected time source, mid-run save/load equivalence, longer-running soak cases, and a permanent regression path for every important hardening bug.
1220+
Acceptance criteria: repeated runs converge exactly under the same recorded mode, overrides, inputs, and injected time source; save/load continuation matches uninterrupted execution; mismatched-mode restore is rejected by default; soak coverage includes at least one real game plus long-running synthetic coverage; and fixed hardening bugs leave behind permanent regression assets.
12031221

12041222
#### Done criteria
12051223

12061224
- core unit and short integration suites for the blocking DMG areas are green
12071225
- the minimum external closure suites are green
12081226
- differential comparison either shows no unexplained divergence in the covered scenarios or records the remaining arbitrations explicitly
1209-
- deterministic replay and save/load determinism are green
1227+
- deterministic replay and save/load determinism are green under `Strict`, with execution-mode metadata recorded in the relevant artifacts
12101228
- no severe open correctness bugs remain in `NoMbc`, `Mbc1`, `Mbc2`, `Mbc3`, or `Mbc5`
12111229
- the project has an explicit DMG closure checklist instead of relying on a general compatibility impression
12121230

AI/TESTING.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ Every subsystem change should aim to leave behind one of these:
6161
- When SameBoy and Gambatte agree and this project differs, treat the discrepancy as a project bug by default until evidence shows otherwise.
6262
- When the oracles disagree, mark the case as requiring arbitration rather than silently accepting one side as correct.
6363

64+
## Execution-mode validation policy
65+
66+
- `Strict` is the only mode that counts as the project's oracle path for CI, differential comparison, DMG closure, and official accuracy claims.
67+
- `Permissive` is for tolerant interactive use and loader-validation coverage around odd but still unambiguous supported cartridges; it must not change the runtime semantics of admitted supported hardware.
68+
- `Experimental` is for research and bring-up; its results must stay segregated from official closure metrics, oracle comparisons, and compatibility claims.
69+
- Mode-sensitive loader tests should cover the documented category matrix for `Supported`, `PlannedVariant`, `DocumentedButUnsupported`, `ExperimentalHeuristic`, `AccessorySpecialCase`, and `UnknownCode`.
70+
- When a test exercises heuristics, partial implementations, or manual overrides, the captured artifacts should say so explicitly rather than looking like ordinary strict-mode evidence.
71+
- Differential comparison against SameBoy or Gambatte should always run under `Strict`, not under `Permissive` or `Experimental`.
72+
6473
## Validation tooling requirements
6574

6675
- Hardening-ready validation requires trace logging at instruction level, micro-op level, and short T-cycle windows.
@@ -219,13 +228,15 @@ When a change affects observable timing or ordering:
219228

220229
## Determinism policy
221230

222-
- Core execution should be deterministic for the same inputs and model configuration.
231+
- Core execution should be deterministic for the same inputs, model configuration, execution mode, and explicit override set.
223232
- Tests should prefer reproducible stepping and explicit expected state over fuzzy assertions.
224233
- Instrumentation should not change hardware-visible behavior.
225234
- Battery-backed RTC persistence tests must use an injected or otherwise explicit time source rather than the host wall clock.
226235
- Determinism coverage should include replay from the same ROM plus input stream, save/load determinism, and at least some longer-running soak cases.
227-
- "Same ROM + same input stream + same injected time source => same result" is the intended project contract.
228-
- Save/load determinism should prove that saving, restoring, and continuing produces the same result as uninterrupted execution.
236+
- "Same ROM + same execution mode + same explicit overrides + same input stream + same injected time source => same result" is the intended project contract.
237+
- Save/load determinism should prove that saving, restoring, and continuing produces the same result as uninterrupted execution under the same recorded execution mode.
238+
- Save states and replay logs should record the execution mode and active overrides that produced them.
239+
- Restoring or replaying under a different execution mode should be rejected by default; if a later explicit developer conversion path is added, tests should cover that path separately and mark it as non-oracle.
229240
- Soak coverage should include at least one real game, one longer-running test ROM, and one or two cases with APU activity plus banked cartridges.
230241

231242
## Regression policy
@@ -235,7 +246,7 @@ When a change affects observable timing or ordering:
235246
- Use a ROM-based reproduction case when the bug is systemic or easiest to demonstrate through an external suite.
236247
- Use a stored differential case when the bug was discovered by comparison against SameBoy, Gambatte, or another explicit oracle.
237248
- Keep regression organization by subsystem or hardware area so repeated failures do not disappear into one catch-all bucket.
238-
- Differential regressions should preserve enough reproduction context to rerun them quickly, including the ROM, input stream, injected seed or time source when relevant, first divergence point, and an optional snapshot when that reduces debug time.
249+
- Differential regressions should preserve enough reproduction context to rerun them quickly, including the ROM, execution mode, active overrides, input stream, injected seed or time source when relevant, first divergence point, and an optional snapshot when that reduces debug time.
239250

240251
## Severity and DMG closure policy
241252

@@ -248,7 +259,8 @@ When a change affects observable timing or ordering:
248259

249260
## CI stratification policy
250261

251-
- The regular CI path should always run critical unit tests, critical short integration tests, a stable subset of external ROMs, and save/load determinism coverage.
262+
- The regular CI path should always run critical unit tests, critical short integration tests, a stable subset of external ROMs, and save/load determinism coverage under `Strict`.
263+
- Experimental suites may exist in nightly or manual jobs, but they must publish artifacts separately and must not gate or dilute the official strict-mode closure signal.
252264
- Longer differential runs, soak tests, and broader external ROM inventories may live in nightly or manual suites, but they must remain documented and runnable.
253265
- Failure artifacts should include enough information to debug without rerunning blindly, such as logs, optional snapshots, framebuffer output when relevant, and a diff against the reference output when one exists.
254266

AI/hardware/BOOT-ROM.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Real boot should start CPU execution at `0x0000` with the internal boot ROM mapp
101101
- `SkipBoot` must distinguish between values that are fixed by model, values derived from the cartridge header, and values that are genuinely unreliable after power-up.
102102
- WRAM and HRAM should not be treated as fixed zero-filled memory in the direct post-boot snapshot.
103103
- Cartridge RAM, whether external or mapper-local to the cartridge controller, should not be assumed clean on first power-up when a direct post-boot path is used.
104-
- A direct-boot path should use an explicit policy for uninitialized memory and unreliable registers, such as seeded pseudo-random data, a documented pattern, or a debug-oriented strict mode.
104+
- A direct-boot path should use an explicit policy for uninitialized memory and unreliable registers, such as seeded pseudo-random data, a documented pattern, or a debug-oriented deterministic startup policy.
105105
- That uninitialized-state policy must not overwrite values that are deterministic in the documented post-boot snapshot.
106106

107107
## Post-boot visible map baseline

0 commit comments

Comments
 (0)