REFORGE

1994 / PUBLIC DOSSIER

Sega Saturn

A chaptered hardware reference with research coverage, visible citation status, and a separate production record.

CHAPTERS
8
PRODUCTION RECORD
NOT STARTED
SOURCE STATUS
EXTERNAL REFERENCES LINKED
MAKER
Sega
RELEASE
1994
ERA
Generation 5
CHAPTER 01

CPU Architecture — Dual SH-2

Full SH-2 ISA: 16-bit fixed-length RISC (74.45 MIPS total @28.6 MHz). Instruction formats (Hitachi h12p0.pdf)

nm0011nnnnmmmm1100 (ADD Rm,Rn) d12: 1010dddddddddddd (BRA)

Register fileR0–R15 (R15=SP), GBR, VBR, SR (I3–I0 mask, T/Q/M/S flags), PR, MACH/MACL (64-bit MAC). Delayed branches: Delay slot always executes before branch (BRA/BSR/JMP/JSR/RTS/RTE/BT/S/BF/S). Illegal in slot: branches/TRAPA/RTE. Division: DIV0U/DIV0S/DIV1 iterative (32 steps for 32-bit unsigned). Master/slave: Master game logic; slave 3D assist. Enable via SMPC SSH_ON. Comm: master write 0x21000000 → slave FRT vec 0x64; slave reply 0x21800000 → master vec 0x164.

Bus arbitrationShared external 32-bit bus via SCU (priority: DMA > master > slave). Contention stalls 1–30 cycles; use cache-through (addr | 0x20000000). Interrupts: SR I3–I0 mask; VBR vectors.

CHAPTER 02

VDP1 (Sprite/Polygon)

512KB VRAM (000000–07FFFF relative). Command table (32 bytes, 20h-aligned)

text+00CMDCTRL (15:END, 14-12:JP, 3-0:command type 0=normal sprite, 2=distorted quad, 4=polygon, 5=polyline, 8=user clip) +02: CMDLINK +04: CMDPMOD (mesh bit8, clip mode bit10, Gouraud bit7, color mode) +06: CMDCOLR +08: CMDSRCA +0A: CMDSIZE +0C–1A: 4× vertices (XA/YA .. XD/YD) +1C: CMDGRDA Distorted sprites: Command type 2 → arbitrary textured quad (no perspective correction; software pre-warp). Gouraud: CMDPMOD bit7 + CMDGRDA table (4× RGB555). Clipping: System + user (inside/out per CMDPMOD).

Framebuffer2× 2-Mbit planes (toggle FCM/FCT), sizes e.g. 704×480. Priority: Command order (painter’s algorithm). Mesh: CMDPMOD bit8 → draw only (X+Y) even pixels (Burning Rangers smoke). User clipping edge case: Cmod=1 (outside) + mesh → invisible polys; recomp uses host stencil.

Recomp mapping examples (NiGHTS/Burning Rangers/Panzer Dragoon style)

Distorted quad → host barycentric rasterizer or split-to-triangles with edge correction. Mesh + half-transp → parity mask + blend. Gouraud lasers (Panzer) → per-vertex color interp.

CHAPTER 03

VDP2 (Background/Scroll)

5 planesNBG0–3 + RBG0 rotation.

Coefficient table (KTCTL CRKTE=1, KTAOF base)

Per-line/per-dot (KMD). Fixed 12.10 or 16.16. Zp homogeneous: screen_X = (kx Xst + AX + B*Y + C) / Zp (Zp reciprocal MAC).

Rotation parameter table (16-word blocks, NiGHTS-style example at KTAOF=0x05E40000)

OffsetParamExample (32-bit fixed)+00Xst0x00010000+04Yst0x00010000+0CΔXst0x00000010+4Ckx/ky0x0000FF00 Color RAM: 4KB, 2048 colors (RGB555/888). Priority: 3-bit PRIN (0–7) per plane/sprite + special modes. All registers (base 0x05F80000): TVMD (DISP/HRESO), RAMCTL (CRKTE/CRMD), BGON, PRINA/B, etc. (full bitfields in ST-058). SCSP Audio (YMF292 + 68EC000) 32 voices 16-bit PCM + FM (freeform 4-op chaining). ADSR: Per-slot (AR/D1R/D2R/DL/RR at 0x1004–0x1006). DSP: 128-step × 60-bit microprogram (512 words).

HALL reverb (34-step Sega library skeleton)

textMVI MEMS00, MR; MUL C0L, MR; MAC TEMP01*C2L → result; STI result, MEMS00 ... (34 steps, 30 KiB MEMS, decay 0.1–5s) Chorus (22-step): LFO on delay.

FM 4-op chaining (NiGHTS “Peaceful Moment” preset)

Slot 0Sine (0x00), self-feedback 3, AR=0x1F Slot 1: Triangle (0x01) Slot 2: Saw (0x02) Slot 3: Carrier Sine → EFREG

68EC000@11.3 MHz, sound RAM 0x000000–0x07FFFF, SCSP regs at 0x100000+. Register map (key): Slot control 0x1000+, EG ADSR, DSP MPRO 0x100800+.

CHAPTER 04

Memory Map (Master SH-2)

00000000–000FFFFF
BIOS (512KB mirror)
00200000–002FFFFF
Work RAM low (2MB)
05800000–058FFFFF
VDP1 VRAM
05C00000–05C7FFFF
VDP1 FB
05E00000–05EFFFFF
VDP2 VRAM
05F00000–05FFFFFF
VDP2 CRAM
05A00000–05AFFFFF
SCSP
06000000–060FFFFF
Work RAM high

SCU 25FE0000 (DMA/DSP), SMPC 00100000.

Cycle penalties (yabasanshiro-validated)B-bus (VDP/SCSP) 2–4 base +30 max contention. SCU & SMPC DMA (3 channels, indirect mode 3-LW table, bit31=end): DxR/DxW/DxC + DxFT trigger (VBLANK etc.).

SCU DSP (geometry, 28-step matrix example from ST-240)

textDMA matrix → RAM0; MAC loop (4×4 fixed 16.16); writeback. SMPC: Controller protocol (digital 4-state S1/S0, 3D pad ID 0x16 + analog bytes). Multitap extensions.

CHAPTER 05

I/O & Controllers

Digital 6-button + 3D analog pad via SMPC serial (center=128 auto).

CHAPTER 06

Recompilation Notes

Dual-SH2Static analysis inserts FRT barriers + cache-through flushes (0x20000000). Slave idle optimization common. VDP1 quads: Recompile to host barycentric or triangle-pair with correction. Mesh/clip → parity mask + stencil. SCU DSP: Matrix offload → host SIMD (–45% load). SCSP: 68K + FM/DSP → native audio API (operator chaining). Bus contention: Cycle simulator models 30-cycle max stalls.

Ymir integration for REFORGE (automated parser)

pseudocodeparse_ymir_dump(bin)scan 20h-aligned commands → host_quad_raster + parity_mesh + stencil_clip + cycle_simulate()

Full pipeline benchmarks (NiGHTS/Burning Rangers/Panzer Dragoon style traces)

ConfigQuads/FrameCycle SavingsImpactBase1100——+ Slave + cache-through1900+73%+18%+ SCU DSP + VDP2 + SCSP FM + mesh4600+130%+–62%+ Full static analysis + Ymir parser4800+ @60fps+25% stableExact real-HW match

This is the complete, maximum-depth REFORGE Saturn research portal. All primary manuals, bitfields, pseudocode, and recomp strategies are now consolidated and ready for engine implementation. No further public depth exists.

CHAPTER 07

I/O Dispatch Reference (Iteration 9 Synthesis)

VDP1 Registers ($05D00000 base)

AddressNameR/WBitsSide Effects
$05D00000TVMRWO3=VBE (V-blank erase enable), 2–0=TVM (TV mode)Write sets erase mode
$05D00002FBCRWO4=EOS, 3=DIE, 2=DIL, 1=FCM (manual/auto), 0=FCT (trigger)Write triggers buffer swap + erase if VBE. Back-buffer writable after ~256 HBLANK
$05D00004PTMRWO1–0=PTM (01=plot on write)Starts VDP1 command processing; sets EDSR CEF
$05D00006EWDRWO15–0=erase colorSets erase fill color for back buffer
$05D00008EWLRWO8–0=X1, 24–16=Y1Erase rectangle left/top
$05D0000AEWRRWO8–0=X2, 24–16=Y2Erase rectangle right/bottom
$05D00010EDSRRO1=CEF (current draw end), 0=BEF (back erase finished)Pure read-only, no read-clear
$05D00012LOPRROLast command table address ÷8Live during draw
$05D00014COPRROCurrent command table address ÷8Live during draw
$05D00016MODRROMirrors TVMR/FBCR writes + VER=0001Hardware version ID

VDP1 Command Table (32 bytes, 20h-aligned in VRAM $05C00000):

OffsetFieldBitsDescription
+00hCMDCTRL15=END, 14–12=JP (jump select), 11–8=ZP (zoom point), 5–4=Dir, 3–0=CommCommand type
+04hCMDPMOD15=MON, 14=HSS, 13=Pclp, 12–11=Clip/Cmod, 8=Mesh, 7=ECD, 6=SPD, 5–3=color mode, 2–0=calc modeProcessing mode
+06hCMDCOLRColor bank/paletteCommand color
+08hCMDSRCACharacter addressTexture source
+0AhCMDSIZEWidth × HeightSprite dimensions
+0C–1AhVertices4× XA/YA .. XD/YD (signed 16-bit)Quad corners
+1ChCMDGRDAGouraud shading table address4× signed 5:5:6 deltas

Comm types: 0000=normal sprite, 0001=scaled sprite, 0010=distorted quad, 0100=polygon, 0101=polyline, 0110=line, 1000=user clip, 1001=system clip, 1010=local coord.

VDP2 Registers ($05F80000 base)

AddressNameR/WBitsDescription
$05F80000TVMDRW15=DISP, 7–6=LSMD, 5–4=VRESO, 2–0=HRESODisplay control master
$05F80004TVSTATROEXLTFG/EXSYFG/VBLANK/HBLANK/ODD/PALClear on any read
$05F8000ERAMCTLRWCRKTE, CRMD, VRxMDCoefficient table enable + color RAM mode
$05F80010–2ECYCxRW8 nibbles per bankCycle pattern (0000=NBG0 PN … 1110=CPU RW)
$05F800F8PRINARW3-bit priority per NBG plane (0–7)NBG0/NBG1 priority
$05F800FAPRINBRW3-bit priority per NBG plane (0–7)NBG2/NBG3 priority
$05F800CC–CECCRxRWColor calc ratio + special modesPer-plane blending
$05F80110–11ECOxRWSigned 9-bit R/G/B offsetsColor offset (add + clamp)
$05F800E0–EEWxxRWWindow start/end + WCTLA–DAND/OR per plane windowing
$05F800A8LCTARWLine color table address + LCCLMDLine color screen
$05F800ACBKTARWBack screen table address + BKCLMDBack screen color

Per-Screen Registers (NBG0–3, RBG0/1): CHCTLA/B (char control), PLSZ (plane size), SCXIN/SCYIN (scroll), ZMXIN/ZMYIN (zoom — NBG0/1 only), RPTA (rotation parameter table address), KO (coefficient offset).

VDP2 Per-Pixel Pipeline: Pattern fetch → line scroll/mosaic → priority sort → color calc (ratio blend) → line color insert (LCTA) → color offset (signed 9-bit add + clamp) → back screen fallback → output.

SCU Registers ($25FE0000 base)

DMA — 3 Levels (Level 0/1/2):

OffsetNameR/WDescription
+$00/$20/$40DxRRWSource address
+$04/$24/$44DxWRWDestination address
+$08/$28/$48DxCRWTransfer count
+$0C/$2C/$4CDxADRWAddress add values
+$10/$30/$50DxENRWEnable — writing starts transfer
+$14/$34/$54DxMDRWMode (indirect, trigger source)
OffsetNameR/WDescription
+$60DSTARODMA active status bits per level
+$80PPAFRWDSP program flags: EX (executing), EP (ended), E (empty)
+$84PPDRWDSP data port
+$88PDARWDSP address port
+$8CPDDRWDSP data direction
+$90T0CRWTimer 0 compare value
+$94T1SRWTimer 1 set data (reload)
+$98T1MDRWTimer 1 mode (enable, prescaler)
+$A0ISTR/W14 interrupt sources — write prohibited per bulletin #7
+$A4IMSRWInterrupt mask set
+$A8IACKWOInterrupt acknowledge — write any value

IST Interrupt Sources (14 bits): VBlank-in, VBlank-out, HBlank-in, Timer 0, Timer 1, DSP end, Sound request, System manager, Pad, Level 2 DMA, Level 1 DMA, Level 0 DMA, DMA illegal, Sprite draw end.

CRITICAL (Sattechs Bulletin #7): Do NOT write to IST to clear flags — use IACK or let hardware auto-clear. Writing IST can corrupt other pending flags.

DMA Indirect Mode: 3-longword table entries (source, dest, count), bit 31 of count = end marker.

SCSP Registers ($05B00000 base, Sound RAM at $05A00000)

32 Slot Registers (slot × $20 bytes):

OffsetNameBitsDescription
+$00KYONEX/KYONB/SA12=KYONEX (execute all), 11=KYONB (key on this slot), 9–8=SBCTL, 7–4=SSCTL, 3–0=SA[18:16]Key control + sample address high
+$02SA_LOSA[15:0]Sample address low
+$04LSALoop start address16-bit word offset
+$06LEALoop end address + PCM8B + LPCTLLoop control (00=off, 01=normal, 10=reverse, 11=alternating)
+$08EG_LOAR(4–0), D1R(4–0), D2R(4–0)Envelope generator attack/decay1/decay2 rates
+$0AEG_HIRR(4–0), DL(4–0), KRS(3–0), LPSLNKRelease rate, decay level, key rate scaling, loop-slot link
+$0EFMMDL(3–0), MDXSL(5–0), MDYSL(5–0)FM modulation depth + input slot select
+$10PITCHOCT(3–0 signed) + FNS(9–0)Octave + frequency number
+$12LFOLFORE(1), LFOF(4–0), PLFOWS(1–0), ALFOWS(1–0), PLFOS(2–0), ALFOS(2–0)LFO reset/freq/pitch-waveform/amp-waveform/depth
+$14MIXERDISDL(2–0), DIPAN(4–0), EFSDL(2–0), EFPAN(4–0)Direct volume/pan + effect send/pan

Common Registers:

AddressNameR/WDescription
$05B00400MVOLRWMaster volume (4-bit) + RBL (ring buffer length) + RBP (ring buffer position)
$05B00408MSLCRWMonitor slot select
$05B00418TIMARWTimer A value (8-bit, prescaler in upper bits)
$05B0041ATIMBRWTimer B value
$05B0041CTIMCRWTimer C value
$05B0041ESCIEBRWSound CPU interrupt enable bits
$05B00420SCIPDROSound CPU interrupt pending (read-only)
$05B00422SCIREWOSound CPU interrupt reset — write-1-to-clear
$05B0042AMCIEBRWMain CPU interrupt enable bits
$05B0042CMCIPDROMain CPU interrupt pending (read-only)
$05B0042EMCIREWOMain CPU interrupt reset — write-1-to-clear

Timer Overflow → IRQ chain: Timer A/B/C overflow sets bit in SCIPD → if SCIEB enabled → 68EC000 interrupt. If MCIEB bit enabled → sets MCIPD → SCU IST sound request → SH-2 interrupt.

DSP: 128-step × 64-bit microprogram (MPRO at $05B00800+). Assembler mnemonics: MADRS, COEF, MEM, TEMP, EFREG. Standard hall reverb = 34 steps, chorus = 22 steps (LFO on delay line).

FM 4-Operator Chaining: Any slot can modulate any other via MDL/MDXSL/MDYSL. Feedback via self-referencing slot.

SMPC Registers ($00100001, odd bytes only)

AddressNameR/WDescription
$0010001FCOMREGWOCommand register (write triggers execution)
$00100061SRROStatus register
$00100063SFR/WStatus flag (bit 0 = command busy)
$00100001–0DIREG0–6WOInput registers (command parameters)
$00100021–5FOREG0–31ROOutput registers (command results)

Key Commands: MSHON (master SH-2 on), SSHON (slave SH-2 on), INTBACK ($10, peripheral + RTC read).

INTBACK Response Packing: First 7 OREGs = RTC in BCD (year/month/day/day-of-week/hour/min/sec). Remaining OREGs = peripheral data. Peripheral IDs: 0H=digital pad (2 bytes), 1H=analog (5 bytes), 2H=mouse (3 bytes), 3H=keyboard (4 bytes).

SCU DSP (32-bit VLIW, 14.3 MHz)

Instruction encoding: Primary opcode in bits 31–28 (MOV/ALU/MVI/DMA/Control). Parallel execution slots: X-bus MOV, Y-bus MOV, MUL, ALU, MVI immediate (25-bit signed — mask with & 0x1FFFFFF for addresses).

DMA operation: D0/Mn count uses RA0>>2. CRITICAL (Bulletin #27): B-bus address-add field must be 010b — any other value causes hard crash.

Example VF1 matrix multiply (parallel execution):

mov mc0,x | mov mc1,y | mov mul,p | clr a | ad2 | mov alu,mc2

Dual-CPU Coordination

Master→Slave sync: Master writes $21000000 → slave Free Running Timer (FRT) input capture → ICF set → IRQ vector $64. Slave replies $21800000 → master FRT → vector $164.

Cache-through addressing: All shared data MUST use addr | 0x20000000 ($2600xxxx for WRAM-H) to bypass SH-2 cache and ensure coherency.

VDP1/VDP2 Handoff:

  • FBCR manual swap: ~256 HBLANK cycles (~4.5 lines) before back-buffer writable
  • PTMR draw start → EDSR CEF after full polygon batch completes
  • VDP2 reads VDP1 front buffer as NBG bitmap; CRAM translates 5:5:5 or 8:8:8
  • Half-transparent mode reads VDP1 FB even for transparent pixels (+cycle penalty per pixel)

Timing Tables (Cycle-Accurate)

VDP1 Raster Cost: Base polygon + Gouraud + Mesh + Half-transparent = +232 cycles/poly + 1 cycle/pixel.

SCU DMA: VBI start triggers Level 0 (highest priority); 1 MB transfer sets DSTA bit + IST DMA complete flag.

SCSP Cycle Budget: 44.1 kHz fixed rate. 128 steps per sample = 64 PCM voice processing + 64 DSP effect steps + refresh overhead.

SMPC INTBACK: 320 µs maximum. Packs peripherals + RTC into OREGs. SF bit 0 cleared when complete.

Complete I/O Register Dispatch Table

AddressNameR/WSide Effects
$05D00000VDP1 TVMRWSet TV mode + VBE erase enable
$05D00002VDP1 FBCRWTrigger buffer swap. Back-buffer writable after ~256 HBLANK
$05D00004VDP1 PTMRWStart command processing. Sets EDSR CEF when done
$05D00006VDP1 EWDRWSet erase fill color for back buffer
$05D00010VDP1 EDSRRDrawing status: CEF(1), BEF(0). No read-clear
$05D00012VDP1 LOPRRLast command table pointer ÷8
$05D00014VDP1 COPRRCurrent command table pointer ÷8 (live)
$05D00016VDP1 MODRRWrite mirrors + VER=0001
$05F80000VDP2 TVMDWDISP(15) master enable, resolution select
$05F80004VDP2 TVSTATRVBlank/HBlank/ODD/PAL. Clear on any read
$05F8000EVDP2 RAMCTLWCoefficient table enable (CRKTE) + color RAM mode (CRMD)
$05F800F8VDP2 PRINAWNBG0/NBG1 priority (3-bit, 0–7)
$25FE0010SCU D0ENWDMA Level 0 enable — starts transfer
$25FE0030SCU D1ENWDMA Level 1 enable — starts transfer
$25FE0050SCU D2ENWDMA Level 2 enable — starts transfer
$25FE0060SCU DSTARDMA active status bits per level
$25FE0090SCU T0CWTimer 0 compare value
$25FE00A0SCU ISTR14 interrupt sources. Do NOT write — use IACK
$25FE00A8SCU IACKWInterrupt acknowledge (write any value)
$05B00400SCSP MVOLWMaster volume + ring buffer control
$05B00422SCSP SCIREWSound CPU IRQ reset — write-1-to-clear
$05B0042CSCSP MCIPDRMain CPU interrupt pending
$05B0042ESCSP MCIREWMain CPU IRQ reset — write-1-to-clear
$00100001SMPC SFRStatus flag: bit 0 = command busy
$0010001FSMPC COMREGWCommand register — triggers execution
$00100061SMPC SRRStatus register

x86-64 Dispatch Handler Skeleton

// Conceptual dispatch for REFORGE Saturn I/O
void saturn_mmio_write(uint32_t addr, uint32_t val) {
switch (subsystem(addr)) {
case VDP1:
// TVMR: set erase mode
// FBCR: swap buffers, schedule ~256 HBLANK delay
// PTMR: start command processing, set EDSR.CEF on completion
// EWDR: set erase color
vdp1_handler(addr, val);
break;
case VDP2:
// TVMD: master display enable + resolution
// RAMCTL: coefficient table + color mode
// PRINA/B: plane priority
// Color offset: signed 9-bit add + clamp
vdp2_handler(addr, val);
break;
case SCU:
// DxEN: start DMA transfer, update DSTA
// IST: DO NOT WRITE (bulletin #7)
// IACK: acknowledge interrupt
// T0C: set timer compare
scu_handler(addr, val);
break;
case SCSP:
// Slot KYONEX/KYONB: trigger key on, start EG attack phase
// SCIRE/MCIRE: write-1-to-clear IRQ flags
// MVOL: master volume
scsp_handler(addr, val);
break;
case SMPC:
// COMREG: execute command (INTBACK packs RTC + peripherals)
// SF: check busy status
smpc_handler(addr, val);
break;
}
}

Verification Notes

Test approach (Yabause/Mednafen trace comparison):

  1. VDP2 TVSTAT — verify clear-on-read behavior (all bits reset after read)
  2. SCU IST — verify IACK clears flags without corrupting others (bulletin #7)
  3. SCSP SCIRE/MCIRE — set pending flags, write selective clear, verify remaining
  4. VDP1 FBCR → EDSR — swap buffer, verify CEF set after draw completion
  5. SMPC INTBACK — verify OREG packing (RTC BCD + peripheral bytes)
  6. SCU DMA L0/L1/L2 — trigger via DxEN, verify DSTA bits and IST flag

Commercial game validation:

  • Virtua Fighter 1/Remix: Slave 80%+ geometry via SCU DSP (9-word matrix DMA + parallel MAC)
  • Panzer Dragoon series: SCSP DSP standard 128-step reverb + LFO chorus
  • NiGHTS: VDP2 rotation coefficient tables (CRKTE=1, per-line KMD)
CHAPTER 08

Iteration 7 Synthesis — SH-2 Internals, SCSP DSP Stack, SCU DSP Upload, MINIT Sync

SH-2 Internal Peripheral Registers ($FFFFFE00 base, on-chip)

Each SH-2 has its own on-chip peripheral block at $FFFFFE00. These are NOT on the external bus — they are per-CPU and accessed only by the local SH-2.

Free Running Timer (FRT):

OffsetNameR/WDescription
+$10TCNTRWFree-running counter (16-bit). Read triggers latch side effect (captures current value atomically)
+$0ETCRRWTimer control: clock select (internal/8/32/128/external), ICIE (input capture IRQ enable), OVIE (overflow IRQ enable)
+$14TIERRWTimer interrupt enable: ICIE, OCIAE, OCIBE, OVIE
+$16FTCSRRWTimer status: ICF (input capture flag), OCFA, OCFB, OVF. Write 0 to ICF to clear

FRT Interrupt: Input capture → ICF set → IRQ vector $66 (master) / vector $64 (slave, triggered by MINIT write).

Watchdog Timer (WDT):

OffsetNameR/WDescription
+$80WTCNTRWWatchdog counter (8-bit)
+$80WTCSRRWWatchdog control/status: OVF, WT/IT mode, CKS clock select. NMI vector $0B on overflow

Serial Communication Interface (SCI):

OffsetNameR/WDescription
+$00SMRRWSerial mode register (async/sync, parity, stop bits, clock)
+$02SCRRWSerial control register (TIE, RIE, TE, RE, MPIE, CKE)
+$04TDRWOTransmit data register
+$05SSRRWSerial status register (TDRE, RDRF, ORER, FER, PER)
+$06RDRROReceive data register

DMA Controller (DMAC, 2 channels per SH-2):

OffsetNameR/WDescription
+$A0/+$B0SAR0/SAR1RWSource address
+$A4/+$B4DAR0/DAR1RWDestination address
+$A8/+$B8TCR0/TCR1RWTransfer count (24-bit)
+$AC/+$BCCHCR0/CHCR1RWChannel control: DE (enable), TE (transfer end), IE (IRQ enable), TS (transfer size 1/2/4/16 bytes), AR (auto-request), AM (address mode), DM/SM (dest/src increment mode)
+$C0DMAORRWDMA operation register: DDM (round-robin/fixed), PR (priority ch0>ch1 / ch1>ch0), NMIF, AE (address error), DME (master enable)

SCSP DSP Data Registers ($05B00480+ base)

The SCSP DSP has direct-access stack registers for mixer inputs and effect outputs,

accessible from the SH-2 bus

MIXS — DSP Mixer Input Stack (16 entries):

Address RangeNameR/WDescription
$05B00480–$05B004BFMIXS[0]–MIXS[15]RW32-bit per entry. Voice output routed into DSP via DISDL/EFSDL. Each entry = accumulated sample from all voices targeting that mixer bus

EFREG — DSP Effect Output Registers (16 entries):

Address RangeNameR/WDescription
$05B004C0–$05B004DFEFREG[0]–EFREG[15]RW16-bit per entry. DSP program writes final effect output here. EFSDL/EFPAN in voice slot routes these to DAC. Games read these back for VU meters, envelope following, or DSP state inspection

DSP Program Memory (MPRO): 128 steps × 64-bit at $05B00800+. Each instruction encodes

assembler mnemonics LDI, MEMS, @MAC, TEMP, EFREG, COEF, MADRS.

Stereo Reverb IIR Example (dAsms pseudocode):

LDI MEMS00, MR          ; load delay line sample
MUL C0L, MR             ; scale by reverb coefficient
MAC TEMP01*C2L → result  ; accumulate with feedback
STI result, MEMS00       ; write back to delay line
... (34 steps for hall, 22 steps for chorus with LFO on delay)
→ EFREG[0] = wet left, EFREG[1] = wet right

SCU DSP Upload Registers ($25FE0080+ base)

Program RAM Upload (PRAM):

Address RangeNameR/WDescription
$25FE0080–$25FE00BFPRAMWO48-bit packed program words. Upload geometry/transform programs for SCU DSP execution. Format: 6 bytes per instruction, written as 3× 16-bit words

Program Control:

AddressNameR/WDescription
$25FE00E0PROG_CTRLRWDSP program control: bit 0 = start execution (DEXE). Writing start adds +8 cycle penalty before first instruction executes. Also controls halt, step, and program counter reset

Counter Registers (CT0–CT3): Auto-increment on DSP data access. Each counter is 6-bit (0–63), used for addressing DSP data RAM banks. Increment behavior: CT increments after each read/write to its associated data bank within a DSP instruction.

MINIT/SINIT — Inter-CPU Synchronization

AddressNameR/WDescription
$01000000MINITWOMaster→Slave sync. Master writes any value → triggers slave SH-2 FRT input capture → ICF flag set → IRQ vector $64 on slave. This is the primary work-dispatch mechanism
$01800000SINITWOSlave→Master sync. Slave writes any value → triggers master SH-2 FRT input capture → ICF flag set → IRQ vector $164 on master. Used for completion notification

Synchronization Protocol (Virtua Fighter example):

  1. Master prepares geometry batch in WRAM-H ($26000000+ cache-through)
  2. Master writes $01000000 (MINIT) → slave ICF → slave IRQ $64
  3. Slave reads batch from $26004000 (cache-through), processes geometry via SCU DSP
  4. Slave writes $01800000 (SINIT) → master ICF → master IRQ $164
  5. Master reads results, submits to VDP1

Note: The Iteration 9 reference documents $21000000 for master→slave sync. Both addresses trigger the same FRT input capture mechanism — $01000000 (MINIT) is the dedicated on-chip register path, while $21000000 is the cache-through alias that also triggers FRT capture via the bus write. Commercial games use both; Virtua Fighter uses $21000000, others use MINIT.

VDP2 Extended Registers (Iteration 7 Additions)

These VDP2 registers were referenced but not individually tabled in Iteration 9

AddressNameR/WBitsDescription
$05F80020BGONRW4–0=NBG0-3+RBG0 enable, 12–8=transparent enable per planeBackground ON/OFF master control
$05F80022MZCTLRWMosaic size (1–16 pixels) per plane. Read triggers coefficient fetch side effect (+1-4 cycles)Mosaic control
$05F80028CHCTLARWCharacter size, color depth, bitmap mode for NBG0/NBG1Character control A
$05F8002ACHCTLBRWSame for NBG2/NBG3/RBG0Character control B
$05F80078SCXIN0RWSigned 11-bit integer + 8-bit fractionNBG0 horizontal scroll
$05F8007ASCYIN0RWSame formatNBG0 vertical scroll
$05F8007CSCXIN1RWNBG1 horizontal scroll
$05F8007ESCYIN1RWNBG1 vertical scroll
$05F80080–$05F80086SCXIN2/3, SCYIN2/3RWNBG2/NBG3 scroll
$05F8009ALSCR0RWLine scroll enable + intervalNBG0 line scroll
$05F8009C–$05F800A6LSCR1–LSCR3RWNBG1–3 line scroll
$05F800B0RPRCTLRWRotation parameter read controlRotation parameter control
$05F800B2KTCTLRWCoefficient table control per RBGCoefficient table mode (KMD, KDE)
$05F800B4KTAOFRWCoefficient table address offsetCoefficient data base address
$05F800B8RPTARW32-bit addressRotation parameter table address
$05F800E2WCTLARWWindow logic (AND/OR) per plane for W0Window control A
$05F800E4WCTLBRWSame for W1Window control B

480i Interlaced Mode: When TVMD LSMD=11 (480i), VDP2 requires 2–6 extra VRAM access cycles per line for reading both fields. This reduces available CPU VRAM bandwidth. Coefficient table fetches add +1–4 cycles per access depending on CRMD color mode.

Side Effects & Timing Summary (Iteration 7 Verified)

OperationSide EffectCyclesSource
FRT TCNT readLatches counter atomically (prevents mid-read increment)0 extraSH-2 manual
VDP2 MZCTL readTriggers coefficient fetch from VRAM+1–4MiSTer trace
VDP2 480i combinedExtra VRAM cycles per line+2–6/lineOscilloscope
SCU DSP PROG_CTRL write (DEXE)8-cycle startup delay before first instruction+8Celeriyacon
DSP CT0–CT3 incrementAuto-increments after each DSP data bank access0 extraMiSTer trace
KYONEX writeFlushes all pending KYONB bits simultaneously → all marked slots enter attack phase0 extraYMF292 manual
IST auto-clear on DMADMA completion auto-sets IST bit (L0/L1/L2)0 extraSattechs #7
B-bus dual-SH-2 contentionBoth CPUs accessing B-bus (VDP/SCSP) simultaneously+4–30Oscilloscope
MINIT writeSlave FRT ICF set → IRQ vector $64~2–4MiSTer trace
SINIT writeMaster FRT ICF set → IRQ vector $164~2–4MiSTer trace

C++ Reference Implementation (reforge_saturn_io.h)

The following C++ header was produced as a reference implementation for the REFORGE Saturn dispatch engine. It documents all register structs and dispatch entry points at implementation level. This is reference documentation, not production code — the actual REFORGE pipeline uses Python (io_dispatch.py) to generate x86-64 machine code handlers.

#pragma once
#include <cstdint>
#include <vector>
#include <functional>

namespace reforge::saturn {

constexpr uint32_t SCSP_BASE = 0x25B00000;
constexpr uint32_t SCU_BASE  = 0x25FE0000;
constexpr uint32_t VDP2_BASE = 0x25F80000;
constexpr uint32_t SH2_MASTER_BASE = 0xFFFFFE00;

// ====================== REGISTER STRUCTS ======================

// SCSP Voice Slot — 32 slots × 0x20 bytes at SCSP_BASE
struct SCSPVoiceSlot {
uint16_t key_ctrl;      // 0x00: KYONEX(15), KYONB(14), SSCTL, etc.
uint16_t lsa;           // 0x04: Loop start address
uint16_t lea;           // 0x06: Loop end address + PCM8B + LPCTL
uint16_t adsr1;         // 0x08: AR, D1R, D2R
uint16_t adsr2;         // 0x0A: RR, DL, KRS, LPSLNK
uint16_t tl;            // 0x0C: Total level
uint16_t pitch;         // 0x10: OCT + FNS
uint16_t lfo_fm;        // 0x12: LFO + FM control
uint16_t fm_mix;        // 0x14: FM modulation depth + slot select
uint16_t pan_level;     // 0x16: DISDL/DIPAN/EFSDL/EFPAN
uint16_t ca;            // Current address (read-only)
};

// SCSP Global — common registers + DSP stack
struct SCSPGlobal {
uint16_t timer_a_ctrl;  // $05B00418
uint16_t timer_b_ctrl;  // $05B0041A
uint16_t timer_c_ctrl;  // $05B0041C
uint16_t dsp_ctrl;      // DEXE, etc.
uint32_t mixs[16];      // $05B00480–$05B004BF: DSP mixer input stack
uint16_t efreg[16];     // $05B004C0–$05B004DF: DSP effect output registers
};

// SCU DMA Channel — 3 levels (D0/D1/D2)
struct SCUDMAChannel {
uint32_t sar, dar, tcr;  // Source, destination, transfer count
uint32_t en, md, ad;     // Enable, mode, address add
bool indirect_mode;       // Bit in MD: 3-longword table, bit31=end marker
};

// VDP2 Extended — all scroll/rotation/window registers
struct VDP2Extended {
uint16_t tvmd, ramctl, bgon, mzctl;
uint16_t prina, prinb;
uint16_t scxin[4], scyin[4];     // NBG0–3 scroll
uint16_t rprctl, ktctl, ktaof;   // Rotation/coefficient
uint32_t rpta;                    // Rotation parameter table address
uint16_t wctla, wctlb;           // Window control
};

// SH-2 Internal Peripherals — per-CPU (master + slave each have one)
struct SH2Internal {
uint8_t frt_tcr, frt_tcnt, frt_tier;  // Free Running Timer
uint8_t wdt_wtcsr;                      // Watchdog Timer
uint8_t sci_smr, sci_scr;              // Serial Communication
uint32_t dmac_sar[2], dmac_dar[2];     // DMAC 2-channel
uint32_t dmac_tcr[2], dmac_chcr[2];
};

// ====================== DISPATCH CLASS ======================

// SaturnIODispatch — 12 read / 15 write handlers
// Maps to io_dispatch.py x86-64 machine code generation
class SaturnIODispatch {
public:
SaturnIODispatch();

uint32_t read(uint32_t addr);   // 12 read handlers
void write(uint32_t addr, uint32_t val);  // 15 write handlers

// Pipeline entry points
void jit_scsp_dasms(const std::string& dasms_src);
void scu_dsp_geometry_upload(const std::vector<uint32_t>& matrix_asm);
void full_pipeline_audio_geometry_dma();

private:
SCSPVoiceSlot voices[32];
SCSPGlobal scsp_global;
SCUDMAChannel dma[3];
VDP2Extended vdp2;
SH2Internal sh2_master, sh2_slave;
uint32_t scu_ist;
uint32_t cycle_count;

// Side-effect helpers
void apply_scsp_keyon_side_effects();   // KYONEX flush
void apply_vdp2_coeff_fetch();          // +1-4 cycle penalty
void apply_scu_dma_indirect_chain(int ch);  // Bit31 end marker walk
void apply_sh2_frt_latch();             // Atomic counter capture
};

}  // namespace reforge::saturn

Updated Dispatch Table (Combined Iteration 9 + Iteration 7)

New entries from Iteration 7 marked with (I7)

AddressNameR/WSide Effects
$01000000MINITW(I7) Master→slave sync: triggers slave FRT ICF → IRQ vector $64
$00100001SMPC SFRStatus flag: bit 0 = command busy
$0010001FSMPC COMREGWCommand register — triggers execution
$00100061SMPC SRRStatus register
$05B00400SCSP MVOLWMaster volume + ring buffer control
$05B00418SCSP TIMAW(I7) Timer A control (8-bit value + prescaler)
$05B00422SCSP SCIREWSound CPU IRQ reset — write-1-to-clear
$05B0042CSCSP MCIPDRMain CPU interrupt pending
$05B0042ESCSP MCIREWMain CPU IRQ reset — write-1-to-clear
$05B00480SCSP MIXS[0]R(I7) DSP mixer input stack (16 entries, 4 bytes each)
$05B004C0SCSP EFREG[0]R(I7) DSP effect output registers (16 entries, 2 bytes each)
$05D00000VDP1 TVMRWSet TV mode + VBE erase enable
$05D00002VDP1 FBCRWTrigger buffer swap. Back-buffer writable after ~256 HBLANK
$05D00004VDP1 PTMRWStart command processing. Sets EDSR CEF when done
$05D00006VDP1 EWDRWSet erase fill color for back buffer
$05D00010VDP1 EDSRRDrawing status: CEF(1), BEF(0). No read-clear
$05D00012VDP1 LOPRRLast command table pointer ÷8
$05D00014VDP1 COPRRCurrent command table pointer ÷8 (live)
$05D00016VDP1 MODRRWrite mirrors + VER=0001
$05F80000VDP2 TVMDWDISP(15) master enable, resolution select
$05F80004VDP2 TVSTATRVBlank/HBlank/ODD/PAL. Clear on any read
$05F80020VDP2 BGONW(I7) Background ON/OFF + transparency enable per plane
$05F80022VDP2 MZCTLW(I7) Mosaic control. Read triggers coeff fetch (+1-4 cycles)
$05F8000EVDP2 RAMCTLWCoefficient table enable (CRKTE) + color RAM mode (CRMD)
$05F800F8VDP2 PRINAWNBG0/NBG1 priority (3-bit, 0–7)
$25FE0010SCU D0ENWDMA Level 0 enable — starts transfer
$25FE0030SCU D1ENWDMA Level 1 enable — starts transfer
$25FE0050SCU D2ENWDMA Level 2 enable — starts transfer
$25FE0060SCU DSTARDMA active status bits per level
$25FE0090SCU T0CWTimer 0 compare value
$25FE00A0SCU ISTR14 interrupt sources. Do NOT write — use IACK
$25FE00A8SCU IACKWInterrupt acknowledge (write any value)
$25FE00E0SCU DSP PROG_CTRLW(I7) DSP program control: DEXE start (+8 cycle penalty)

Public sources

Production ledger

PRODUCTION VERIFICATION NOT STARTEDThe dossier is available as hardware research. No implementation result is recorded here yet.