Skip to content

Commit 2e14f71

Browse files
committed
docs: align hardware handbooks and roadmap
1 parent c0fe707 commit 2e14f71

10 files changed

Lines changed: 165 additions & 12 deletions

File tree

AI/ARCHITECTURE.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,15 @@ to immediately materialize as a separate directory.
222222

223223
### `dma/`
224224

225+
- shared DMA controller and active-transfer state
225226
- DMG OAM DMA
227+
- transfer lifecycle such as `Idle`, `Starting`, `Active`, `Completed`, and future `Cancelled`
226228
- transfer timing over the shared scheduler timeline
229+
- per-transfer timing policy, block granularity, and advance-condition modeling
230+
- publication of CPU-impact and memory-region-impact state for bus and PPU consumption
231+
- DMA-owned validation and normalization of source and destination contracts
227232
- integration with bus arbitration
228-
- architectural preparation for future transfer mechanisms outside current DMG scope
233+
- architectural preparation for future GDMA and HDMA without scheduler redesign
229234

230235
### `timer/`
231236

@@ -326,6 +331,7 @@ to immediately materialize as a separate directory.
326331
- The boot subsystem owns firmware assets, model-aware boot configuration, and boot-ROM enable/disable state.
327332
- The boot subsystem also owns the source-of-truth startup snapshot for direct-boot entry, while the target subsystems still own the live semantics of their registers once execution begins.
328333
- The DMA subsystem owns transfer state and transfer requests over time.
334+
- The DMA subsystem also owns transfer-kind-specific validation, lifecycle, progress, CPU-impact policy, and region-impact publication; the bus and PPU should consume that common state instead of reverse-engineering DMA behavior from MMIO register details.
329335
- The PPU owns LCD mode state and the rules that determine when VRAM/OAM are accessible.
330336
- The PPU also owns the live Mode `2` OAM-row state and the DMG-family OAM corruption formulas, while the bus routes relevant access attempts and the CPU exposes the micro-events needed to classify IDU-driven triggers.
331337
- The interrupt controller owns `IF`/`IE` register state and pending-request bookkeeping, while the CPU owns `IME`, `halted`, `stopped`, and the final decision to accept and service an interrupt.

AI/ROADMAP.md

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ coherent without refactoring.
162162
Acceptance criteria: CPU and DMA use the same arbitration route, decode/ownership and access-policy layers stay distinct, and DMG OAM DMA correctly leaves CPU with HRAM only.
163163
3. **IRQ aggregation layer** (`Phase 2`)
164164
Goal: separate source request, `IF` visibility, and CPU acceptance.
165-
Acceptance criteria: PPU, timer, serial, and joypad only request; the CPU accepts by `IME/IE/IF` and fixed priority; timer keeps its delayed one-M-cycle request timing.
165+
Acceptance criteria: PPU, timer, serial, and joypad only request; the CPU accepts by `IME/IE/IF` and fixed priority; timer keeps its delayed `4`-T-cycle (`1` M-cycle) request timing.
166166
4. **Cycle logging** (`Phase 0`, expanded later)
167167
Goal: make the actual ordering visible per T-cycle.
168168
Acceptance criteria: traces can expose phase, bus owner, CPU micro-op, PPU mode, DMA activity, timer or serial events, and `IF/IE/IME`.
@@ -488,7 +488,7 @@ Build a truly temporal CPU core, where observable behavior emerges from internal
488488

489489
#### Goal
490490

491-
Integrate OAM DMA as a real transfer mechanism inside the system architecture, coordinated with the scheduler and bus.
491+
Integrate DMG OAM DMA as a real transfer mechanism inside the system architecture through a reusable DMA-controller foundation, coordinated with the scheduler and bus and already prepared for future CGB transfer families without implementing them yet.
492492

493493
#### Modules involved
494494

@@ -500,19 +500,41 @@ Integrate OAM DMA as a real transfer mechanism inside the system architecture, c
500500

501501
#### Deliverables
502502

503+
- common `DmaController`-style infrastructure with explicit active-transfer state
503504
- writing to the DMA register triggers the transfer
504-
- real temporal copy progression
505+
- OAM DMA as the first concrete transfer kind inside that common infrastructure
506+
- real temporal copy progression on the shared T-cycle timeline
505507
- integration with bus arbitration
508+
- separation between transfer progression and DMA-published arbitration state
509+
- explicit lifecycle and status visibility for active transfers
506510
- observability of DMA start, progress, and completion
507511
- scheduler-visible DMA state that bus arbitration can use on the same T-cycle
512+
- transfer fields that already leave room for block or windowed progression without wiring CGB MMIO yet
508513

509514
#### Done criteria
510515

511516
- the transfer is not implemented as an instantaneous memory copy
517+
- OAM DMA is implemented as an instance of the common DMA transfer infrastructure rather than a one-off path outside it
512518
- arbitration correctly reflects DMA effects on concurrent accesses
513519
- CPU-versus-DMA precedence is decided centrally through bus arbitration instead of CPU-local blocking logic
520+
- DMG OAM DMA still leaves the CPU with HRAM access only while active
521+
- DMA lifecycle and active-state visibility are explicit and traceable
522+
- the infrastructure can already represent future block or windowed transfers without requiring a later scheduler redesign, even though GDMA and HDMA remain out of scope here
514523
- the system can trace DMA over time
515524

525+
#### Recommended sequencing inside Phase 3
526+
527+
1. Extract OAM DMA into the common controller.
528+
Acceptance criteria: OAM DMA no longer lives on an ad hoc path, visible DMG behavior does not regress, CPU still remains HRAM-only during active OAM DMA, and the PPU still sees the same OAM-conflict state.
529+
2. Separate transfer mechanics from arbitration policy.
530+
Acceptance criteria: the bus consults one common DMA constraint API, the DMA subsystem does not reimplement bus decode, and the PPU can react to common OAM or VRAM impact state rather than to transfer-specific register knowledge.
531+
3. Add common lifecycle and status visibility.
532+
Acceptance criteria: OAM DMA uses `Idle -> Starting -> Active -> Completed`, the common API can already represent future cancellation, and code can query active-versus-finished state without depending on one specific origin register.
533+
4. Prepare block or windowed progression hooks.
534+
Acceptance criteria: fields such as `block_size` and `advance_condition` exist in the controller contract, including room for future `0x10`-byte HDMA-style blocks, they are not yet wired to real HDMA registers, and Phase 3 does not need another scheduler redesign when CGB transfer work starts.
535+
5. Lock the infrastructure with focused tests.
536+
Acceptance criteria: tests cover OAM DMA on the new controller, published bus constraints, lifecycle visibility, completion, and at least one simulated `0x10`-byte block-style transfer shape that is not yet mapped to real CGB MMIO.
537+
516538
#### Risks if delayed too much
517539

518540
- the need to rewrite the bus
@@ -793,13 +815,14 @@ Complete basic system peripherals on top of an already consolidated bus, schedul
793815

794816
---
795817

796-
### Phase 6 — Banked cartridges and persistence
818+
### Phase 6 — Banked cartridges, special cartridges, and persistence
797819

798820
25. **MBC1**
799821
26. **MBC2**
800822
27. **MBC3**
801823
28. **MBC5**
802-
29. **Banked external RAM, battery, RTC, persistence**
824+
29. **Special cartridges and unsupported policy**
825+
30. **Banked external RAM, battery, RTC, persistence**
803826

804827
#### Goal
805828

@@ -1221,7 +1244,7 @@ Suggested entry style:
12211244

12221245
- None currently.
12231246

1224-
### Phase 6 — Banked cartridges and persistence
1247+
### Phase 6 — Banked cartridges, special cartridges, and persistence
12251248

12261249
- None currently.
12271250

AI/TIMING-AND-ACCURACY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ When implementing timing:
7979
- For the CPU specifically, opcode fetch, immediate fetch, stack transfer, indirect memory access, conditional timing splits, and internal no-bus steps should all remain expressible as ordered events on that timeline.
8080
- Long-running hardware activity started by a register write, such as OAM DMA, should become explicit in-flight state on the shared timeline rather than a one-shot side effect.
8181
- When a subsystem progresses in repeated temporal slices, such as one DMA byte every four dots on DMG OAM DMA, that phase relationship should remain visible in code and tests.
82+
- The timing model must support both fixed-duration burst transfers and windowed or block transfers that only advance in eligible windows such as HBlank, while keeping both on the same shared T-cycle timeline.
83+
- A transfer's CPU or bus impact and its data-copy action should be expressible separately per T-cycle, because arbitration may be visible on cycles where no byte commits and future block DMA may stall only for selected windows.
84+
- Future transfer advance may depend on other live machine state such as PPU HBlank visibility or CPU `HALT` state; keep that dependency explicit in the transfer model rather than hiding it in bus code.
8285
- Edge-driven subsystems such as the timer should derive visible events from clocked internal state transitions, not from coarse accumulated-period shortcuts.
8386
- CPU interrupt acceptance, delayed `EI`, `HALT` wake-up, and `HALT` bug behavior should be expressed as ordered events on that same shared timeline rather than as opaque instruction-level shortcuts.
8487
- For the PPU specifically, dot-by-dot progression is the intended interpretation of the shared T-cycle timeline.

AI/hardware/BUS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Address alone is not enough: the bus must also consider the current temporal har
2121
- distinguish requester-specific access semantics when CPU, DMA, or other actors do not obey the same rules
2222
- coordinate dynamic mapping between boot ROM, cartridge ROM, and later model-specific extensions
2323
- consume subsystem-owned state such as PPU mode, DMA progress, and boot-ROM enable state when deciding the observable result of an access
24+
- consume DMA-published constraint state from the common transfer controller rather than re-deriving live DMA policy from MMIO register values or ad hoc per-kind branches
2425
- delegate all cartridge-owned accesses through one stable cartridge-device contract instead of embedding per-MBC logic in the bus
2526

2627
## Registers / MMIO
@@ -173,6 +174,8 @@ Address alone is not enough: the bus must also consider the current temporal har
173174
- After nominal ownership is known, the owning region or device may still block or modify the access according to live policy, such as VRAM in Mode `3`, OAM in Mode `2/3`, `FEA0-FEFF`, disabled cartridge RAM, or cartridge-selected RTC behavior.
174175
- CPU, DMA, and any future transfer engine must all use this one central arbitration path; no caller-specific fast path may bypass decode or access policy.
175176
- On the shared scheduler timeline, the arbitration decision for a T-cycle should see the already-updated current-cycle DMA and PPU state before the CPU micro-operation issues its access for that same T-cycle.
177+
- The bus should consult DMA-owned published constraints such as CPU impact, region impact, and current-cycle transfer activity instead of peeking at `FF46` or future `HDMA1-5` register state directly.
178+
- DMA policy questions such as "HRAM-only", "fully stalled until done", or "stalled only during a block" belong to the DMA subsystem; the bus should only apply the resulting requester-visible constraints.
176179

177180
## Model-aware MMIO baseline
178181

@@ -202,6 +205,7 @@ Address alone is not enough: the bus must also consider the current temporal har
202205
- OAM access blocking during PPU Mode 2 must be represented as observable bus behavior, not as a render-only detail.
203206
- During PPU Mode 3, both OAM and VRAM access restrictions must be represented as observable bus behavior.
204207
- During DMG OAM DMA, CPU accesses should retain normal HRAM behavior while non-HRAM CPU accesses observe DMA-blocked semantics instead of normal memory-region behavior.
208+
- DMA-visible blocking and DMA data movement should remain separable on the T-cycle timeline; a transfer may affect CPU-visible access policy on a cycle even if no byte commit occurs on that same cycle.
205209
- With LCD disabled, access rules should return to the hardware state expected for LCD-off behavior.
206210
- LCD-off accessibility should remove ordinary PPU mode locks, but it must not erase independent blocking rules coming from DMA or any later bus actor.
207211
- The same PPU-disabled state that makes `STAT.mode` read as `0` should also be the state the bus uses to release ordinary VRAM/OAM mode restrictions.
@@ -279,6 +283,7 @@ Priority order:
279283
- A bus context or equivalent state bundle is a good fit for carrying model, PPU mode, LCD enable, DMA activity, boot ROM mapping, and later CGB-specific selectors.
280284
- A caller-aware access split or equivalent internal distinction between CPU-initiated and DMA-initiated accesses is recommended when the observable rules differ.
281285
- Let subsystems define the state that causes restrictions or remapping, but keep the final blocked-access or routing decision in bus-facing handlers.
286+
- A DMA-facing query such as `bus_constraints()` plus a separate transfer-commit path is a good fit for keeping arbitration policy separate from byte-copy mechanics.
282287
- Prefer a centralized MMIO descriptor table or equivalent routed register map over scattered `match` blocks that each know only part of a register's semantics.
283288
- Let subsystem-owned handlers compose readback from live state, latched state, and forced bits; do not teach the bus to fake those register internals.
284289
- Do not special-case CPU opcode fetch, operand fetch, or stack accesses outside the common bus contract; they should use the same routed access path as any other CPU-visible memory transaction.

AI/hardware/CGB.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ Priority order:
9999
- CPU `STOP` should already be represented separately from `HALT`, because future CGB speed-switch behavior should attach to an existing explicit control state rather than force a later CPU-state redesign.
100100
- The boot subsystem and bus should already treat boot-ROM mapping as model-aware routing state so future CGB split boot-ROM windows can extend the same abstraction while preserving cartridge-header visibility around `0x0100-0x014F`.
101101
- The DMG OAM DMA implementation should already live inside a reusable DMA subsystem contract so future CGB OAM DMA timing differences, GDMA, and HDMA can extend the same infrastructure.
102+
- When CGB DMA work starts, model GDMA as a full-burst transfer and HDMA as a windowed block transfer inside that shared DMA controller, with CPU-impact and advance-condition policy published to the scheduler and bus rather than re-encoded in CGB-only bus branches.
102103
- The DMG timer implementation should already be expressed in terms of an internal counter plus derived edge logic so future CGB clocking changes can extend the same model rather than replace it.
103104
- The DMG APU implementation should already derive `DIV-APU` / frame-sequencer timing from the shared divider timeline so future CGB double-speed audio timing can extend the same ownership split rather than introducing a second audio clock model.
104105
- The DMG-family OAM corruption bug should stay behind an explicit model gate so future CGB, AGB, AGS, and GBP support can keep the documented non-bugged behavior.

AI/hardware/CPU.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The source of truth should not be "execute opcode, mutate registers, then report
3636
- The CPU should only accept maskable interrupts at defined points in the instruction-flow pipeline, effectively at instruction boundaries or an equivalent explicitly modeled acceptance point.
3737
- When an interrupt is accepted, the CPU should clear `IME`, clear the selected bit in `IF`, push `PC`, and jump to the matching vector as part of one explicit service sequence.
3838
- The CPU should make that accept-or-not decision only after current-cycle MMIO side effects and interrupt aggregation are already visible; interrupt producers do not bypass that CPU-owned decision point.
39-
- Once accepted, interrupt servicing must consume the documented DMG `5` M-cycles through the same ordered CPU execution model used for normal stack and control-flow work.
39+
- Once accepted, interrupt servicing must consume the documented DMG `20` T-cycles (`5` M-cycles) through the same ordered CPU execution model used for normal stack and control-flow work.
4040

4141
## IME, HALT, and STOP baseline
4242

@@ -135,7 +135,7 @@ Priority order:
135135
- tests for correct push of `PC`, clearing of `IF`, and `IME -> 0` on interrupt service
136136
- tests for `EI ; NOP`, `EI ; DI`, `DI ; EI ; NOP`, and pending-IRQ visibility around delayed `EI`
137137
- tests for `HALT` wake-up with `IME = 1`, `IME = 0`, and `IME = 0` plus already-pending interrupt
138-
- tests that interrupt acceptance starts a real `5` M-cycle service sequence instead of an immediate vector jump
138+
- tests that interrupt acceptance starts a real `20` T-cycle (`5` M-cycle) service sequence instead of an immediate vector jump
139139
- tests for `STOP` wake-up driven through the relevant hardware source path rather than by directly poking CPU state
140140
- tests for `RETI` re-enabling interrupts and allowing later pending requests to be serviced
141141
- tests that `inc rr` / `dec rr` with `BC`, `DE`, or `HL` in `FE00-FEFF` expose the IDU event needed by the OAM-corruption path

0 commit comments

Comments
 (0)