# CD32 Native-Akiko — Fast-Push Release

Experimental MiSTer Minimig-AGA fork that implements native CD32 Akiko CD-DMA
instead of the IDEFix97 / CD32-Emulator workaround. Boots Cannon Fodder
(1993, Virgin) end-to-end on real MiSTer hardware via a single MGL launcher,
**with full NVRAM save persistence** AND **a 2.4× faster sector-push path**
between MiSTer userspace and the akiko sector buffer.

## What's new vs. the saves release

The previous `CD32-native-saves` build pushed each 2352-byte raw CD sector to
the FPGA via UIO_DMA_WRITE on the akiko 0xF500 sub-channel. That path
round-trips an SSPI_ACK per byte, costing ~2.3 ms per sector — the dominant
slice of CF's MGL boot latency (583 ms over 256 sectors before the BIOS could
see its first usable data).

This build replaces that path with the framework's canonical UIO_SECTOR_RD
pipeline, the same one all stock cores use for SD/CD bulk reads:

- **New RTL slot 1 in `hps_io` (VDNUM=2)** wired to a dedicated
  `hps_sec_dma_*` port group on `akiko.v`. Userspace sends
  `UIO_SECTOR_RD | (1<<8)` followed by 2352 raw bytes via
  `fpga_spi_fast_block_write_8`; `hps_io`'s `b_wr<<1` cascade pulses
  `sd_buff_wr` per byte at SPI clock and auto-increments `sd_buff_addr`.
  No per-byte ACK round-trip.
- **Sector buffer write port collapsed to a single muxed write** so Quartus
  keeps the 2352-byte array in M10K (a naive two-writer implementation
  blew the fitter to 100% ALM at 41,910 / 41,910). After the fix the
  design fits at 52% ALM with -0.662 ns setup slack — measurably better
  than the saves-release baseline (-2.461 ns).
- **Default-on**, with `AKIKO_SLOW_PUSH=1` in the MiSTer env as an escape
  hatch back to the legacy slow path if a future regression needs A/B
  diagnosis without a rebuild.

Hardware A/B (Cannon Fodder cold-start MGL launch, CHD on USB SSD,
2026-05-07):

| Metric | Saves release | Fast-push release | Δ |
|---|---|---|---|
| push (256 sectors) | 583 ms | 244 ms | **2.4× faster** |
| per-sector push | 2.28 ms | 0.95 ms | matches `fpga_spi_fast_block_write_8` ~400 ns/byte |
| first sec_req timing | t=17.9s | t=12.0s | 5.9 s earlier |
| PLAY DATA arms | 43 | 22 | half — no BIOS retry storm |
| t=35s intro frame | poppy title screen | "Sensible Software" credits | ≈ one full intro screen further |

NVRAM save persistence, OSD-open-edge save trigger, per-game `cd32-<hash>.nvr`
files, mediachange recovery — all unchanged from the saves release.

Both cfg/mgl filenames still carry the `MVP` suffix for continuity with
existing installs.

## Files

| File | Path on MiSTer | Purpose |
|---|---|---|
| `MiSTer` | `/media/fat/MiSTer` | Patched Main_MiSTer userspace (Akiko bridge + canonical SD-block NVR + UIO_SECTOR_RD fast push by default) |
| `Minimig.rbf` | `/media/fat/_Test/Minimig.rbf` | Patched Minimig-AGA core (NATIVE_CD32=1, hps_io VDNUM=2 BLKSZ=3, akiko sector slot 1) |
| `CannonFodder-CD32MVP.cfg` | `/media/fat/config/CannonFodder-CD32MVP.cfg` | CF launch config (binds CHD) |
| `CannonFodder-CD32MVP.mgl` | `/media/fat/_Computer/CannonFodder-CD32MVP.mgl` | CF launcher entry |
| `CD32-NoCD-MVP.cfg` | `/media/fat/config/CD32-NoCD-MVP.cfg` | No-CD test config (kickstart only) |
| `CD32-NoCD-MVP.mgl` | `/media/fat/_Computer/CD32-NoCD-MVP.mgl` | No-CD test launcher |

## Building the CD32 ROM (1MB combined)

The CD32 needs a 1MB ROM image consisting of the standard Amiga Kickstart 3.1
(512KB) followed by the CD32 extended ROM (512KB). It is normally distributed
as two separate 512KB files which must be concatenated into a single 1MB file.

File names vary by source but commonly look like `kick40060.CD32` (the 512KB
Kickstart) and `kick40060.E` (the 512KB extended ROM). Other common names
include `391330-01.U6A` + `391330-01.U6B` halves, etc. Make sure you know
which two files you have. **Order matters: Kickstart first, extended ROM
second.**

**Windows (cmd.exe):**

```
copy /b kick40060.CD32 + kick40060.E cd32.rom
```

**Windows (PowerShell):**

```powershell
[System.IO.File]::WriteAllBytes('cd32.rom', [System.IO.File]::ReadAllBytes('kick40060.CD32') + [System.IO.File]::ReadAllBytes('kick40060.E'))
```

**Linux / macOS (bash/zsh):**

```bash
cat kick40060.CD32 kick40060.E > cd32.rom
```

After concatenation, verify the size is exactly 1048576 bytes (1MB):

- Linux / macOS: `wc -c cd32.rom`
- Windows PowerShell: `(Get-Item cd32.rom).Length`

The native-Akiko core takes natural-byte-order ROMs (no byte-swap).

Place the resulting `cd32.rom` somewhere on the SD card or USB and update
the kickstart path in the `.cfg` file (offset 0x00C as a NUL-terminated
relative path) to point to it.

## Prerequisites

- MiSTer SD card with a CD32 Kickstart ROM at the path encoded in the
  bundled .cfg files (currently `/media/usb0/Games/Amiga/roms/Caldor/cd32_swapped.rom`).
- Cannon Fodder CHD at:
  `/media/usb0/Games/Amiga/CHD/Cannon Fodder (1993)(Virgin)[Amiga-CD32].chd`

Adjust paths in the `.cfg` files if your layout differs (kickstart at offset
0x00C as a NUL-terminated relative path; CHD path at offset 0x418).

## Install

1. Back up your existing `/media/fat/MiSTer` and any `/media/fat/Minimig*.rbf`.
2. Copy `MiSTer` to `/media/fat/MiSTer`, `chmod +x` it.
3. Copy `Minimig.rbf` to `/media/fat/_Test/Minimig.rbf` (or replace the
   production `Minimig_<date>.rbf` if you want it to be the default).
4. Copy the two `.cfg` files to `/media/fat/config/`.
5. Copy the two `.mgl` files to `/media/fat/_Computer/`.
6. Reboot MiSTer (`killall MiSTer` works; no supervisor on this device).

The fast push path is on by default. To revert to the slow path for
diagnostic A/B comparison without rebuilding, restart MiSTer with
`AKIKO_SLOW_PUSH=1` in its environment.

## Test

- **Boot CF**: from MiSTer menu, navigate to Computer → CannonFodder-CD32MVP.
  Cannon Fodder should boot to the HEROES selection menu. Intro graphics
  visibly progress further within the first 35 seconds than on the saves
  release.
- **Verify the fast path is on**: after launch, check
  `cat /tmp/akiko_dbg.log` for a `sec_req timing N=256` line. Push average
  should be ≈ 950 µs/sector. If you see ≈ 2300 µs/sector you're on the
  slow path (check the env).
- **Save in-game**: complete a mission or use CF's save dialog. The akiko
  log will show `[akiko] NVR dirty observed at t=...`.
- **Commit on OSD-open**: open the OSD any time after a save. The log
  will show `[akiko] NVR flush: OSD opened with dirty pending` followed
  immediately by `[akiko] NVR saved 1024 bytes to /media/fat/saves/Minimig/cd32-<hash>.nvr`.
- **Reload across reset**: power-cycle or reset MiSTer. On next boot of
  the same CHD, the NVR slot mounts and `[akiko] NVR loaded 1024 bytes
  from .../cd32-<hash>.nvr (verify OK)` confirms the byte-for-byte load.
  CF's save slot should appear in its load menu.

## Save layout

- One file per CHD: `/media/fat/saves/Minimig/cd32-<16hex>.nvr` (1024 bytes,
  byte-format compatible with WinUAE's `cd32.nvr`).
- The 16-hex suffix is the FNV-1a-64 hash of the CHD basename, so renaming
  a CHD will start a fresh save slot. Keep the basename stable.
- Saves are byte-format compatible with WinUAE: copy a
  `cd32-<hash>.nvr` over WinUAE's `cd32.nvr` and CF will load the save in
  WinUAE, and vice versa.

## What's also fixed (carried from earlier releases)

- **Boot-with-no-CD-then-mount works** (Phase 33-E, 2026-05-07). Launching
  the no-CD MGL and then mounting a CHD via OSD reaches the cold-boot
  auto-init path via a deferred `minimig_reset()`. Hot-swaps during
  gameplay still go through the WinUAE-style mediachange push.
- **TOC max points 16 → 32** (2026-05-06). High-track CDDA discs (e.g.
  Fire & Ice with 23 tracks) no longer hang post-scan-TOC.
- **Negative-LBA PBX feed** now skip-pushes like WinUAE instead of pushing
  zeros, eliminating a BIOS-retry storm during pre-gap PLAY DATA.

## Known issues

- emu PLL setup slack is -0.662 ns. Better than the saves release's
  -2.461 ns; real-hardware tests pass.
- chd_read latency variability has been observed (10s vs 2 min mission
  loads on the same content). Suspected USB-SATA bridge link power
  management on some SSD enclosures, not a fast-push issue. Tracked
  separately.
