|
| 1 | +# Jaguar CD BIOS Jump Table Calling Convention |
| 2 | + |
| 3 | +Reverse-engineered from the retail CD BIOS ROM (`[BIOS] Atari Jaguar CD (World).j64`), |
| 4 | +cross-referenced against the developer BIOS, CDBYPASS ROMs, and MiSTer FPGA implementation. |
| 5 | + |
| 6 | +## Jump Table Layout |
| 7 | + |
| 8 | +The BIOS copies an 18-entry branch table from ROM `$8084A6` to RAM `$3000`. |
| 9 | +Each entry is 6 bytes: `BRA.W <offset>` + `NOP`. |
| 10 | + |
| 11 | +| Entry | Address | Name | Parameters | |
| 12 | +|-------|---------|--------------------|------------------------------------| |
| 13 | +| 0 | $3000 | CD_setup_audio_isr | A0 = GPU RAM base. Copies $E0 bytes of ISR. Sets [$3072]=0. | |
| 14 | +| 1 | $3006 | CD_wait_response | Polls BUTCH bit 13, reads DS_DATA response into D1. | |
| 15 | +| 2 | $300C | CD_wait_response2 | Same as entry 1. | |
| 16 | +| 3 | $3012 | CD_i2s_enable | D0: 0=disable, 1=enable Jerry+FIFO. | |
| 17 | +| 4 | $3018 | CD_spin_up | D1=session, D0=wait flag. DSA cmd $18nn. | |
| 18 | +| 5 | $301E | CD_stop_drive | D0=wait flag. DSA cmd $0200. | |
| 19 | +| 6 | $3024 | CD_set_volume_mute | D0=wait. DSA cmd $5100. | |
| 20 | +| 7 | $302A | CD_set_volume_max | D0=wait. DSA cmd $51FF. | |
| 21 | +| 8 | $3030 | CD_pause | D0=wait. DSA cmd $0400. | |
| 22 | +| 9 | $3036 | CD_unpause | D0=wait. DSA cmd $0500. | |
| 23 | +| 10 | $303C | **CD_read** | See below. | |
| 24 | +| 11 | $3042 | CD_fifo_disable | Clear bit 2 of I2CNTRL. | |
| 25 | +| 12 | $3048 | CD_hw_reset | DSA cmd $7001. Reset BUTCH/DSCNTRL/I2CNTRL. | |
| 26 | +| 13 | $304E | **CD_poll** | See below. | |
| 27 | +| 14 | $3054 | CD_set_dac_mode | D0=0-2. DSA cmd $70nn. | |
| 28 | +| 15 | $305A | CD_read_toc | A0 = buffer ($384 bytes). DSA cmds $03nn/$14nn. | |
| 29 | +| 16 | $3060 | CD_setup_cdrom_isr | A0 = GPU RAM base. Copies $150 bytes. Sets [$3072]=$FF. | |
| 30 | +| 17 | $3066 | CD_setup_data_isr | A0 = GPU RAM base. Copies $D4 bytes. Sets [$3072]=1. | |
| 31 | + |
| 32 | +## CD_read ($303C) — Full Specification |
| 33 | + |
| 34 | +### Inputs |
| 35 | + |
| 36 | +| Register | Meaning | |
| 37 | +|----------|---------| |
| 38 | +| D0.L | Packed MSF seek position: `(min << 16) \| (sec << 8) \| frm`. Values are binary (NOT BCD). **Bit 31**: if set, skip hardware init, just re-seek (GPU data area already configured by prior call). | |
| 39 | +| D1.L | Sync sentinel for CD-ROM mode ISR. Stored to GPU data area [+16]. In audio mode ISR, ignored. CDBYPASS passes `$41545249` ("ATRI") for boot stub reads. Games may pass DDL markers. | |
| 40 | +| D2.L | Speed/mode parameter. Only used in CD-ROM mode ([$3072] bit 7 set). | |
| 41 | +| A0 | Destination buffer in Jaguar RAM. Internally decremented by 4 (GPU ISR pre-increments before store). | |
| 42 | +| A1 | End address (destination + byte count). Stored to GPU data area [+4]. | |
| 43 | + |
| 44 | +### Behavior (bit 31 clear — full init, used by games) |
| 45 | + |
| 46 | +1. Disable BUTCH IRQs, disable FIFO |
| 47 | +2. Store `A0 → GPU_DATA[+0]` (dest), `A1 → GPU_DATA[+4]` (end), `0 → GPU_DATA[+8]` (progress) |
| 48 | +3. Drain FIFO, re-enable BUTCH with IRQ |
| 49 | +4. Extract MSF from D0: min = `(D0 >> 16) & 0xFF`, sec = `(D0 >> 8) & 0xFF`, frm = `D0 & 0xFF` |
| 50 | +5. Send DSA seek commands: `$10MM`, `$11SS`, `$12FF` to DS_DATA ($DFFF0A) |
| 51 | + |
| 52 | +### Behavior (bit 31 set — re-seek, used by BIOS internally) |
| 53 | + |
| 54 | +Skip steps 1-3, only send DSA seek commands (step 4-5). |
| 55 | + |
| 56 | +### Transfer Mechanism |
| 57 | + |
| 58 | +Data arrives asynchronously via the GPU ISR: |
| 59 | +- Audio mode ISR ($3000 setup): transfers all incoming I2S data directly to RAM |
| 60 | +- **CD-ROM mode ISR ($3060 setup): scans incoming I2S data for the D1 sync sentinel, then starts transferring from that point** |
| 61 | +- Data ISR ($3066 setup): variant of audio mode |
| 62 | + |
| 63 | +The ISR writes data to the destination buffer and advances the write pointer. |
| 64 | +Transfer completes when the write pointer reaches the end address (A1). |
| 65 | + |
| 66 | +### Sync Sentinel Scanning (CD-ROM mode) |
| 67 | + |
| 68 | +In CD-ROM mode, the GPU ISR does NOT transfer data immediately. |
| 69 | +It scans each incoming I2S word for the 32-bit pattern stored in D1. |
| 70 | +When the pattern is found, the ISR begins the actual data transfer. |
| 71 | + |
| 72 | +This is how the BIOS locates specific data on disc: |
| 73 | +- The boot stub seeks to near the session-2 start |
| 74 | +- The I2S stream contains all sectors from that point forward (crossing track boundaries) |
| 75 | +- The ISR scans through potentially hundreds of sectors of boot stub / padding data |
| 76 | +- When it finds the DDL marker matching D1, it starts copying game data to RAM |
| 77 | + |
| 78 | +### BIOS Internal Completion |
| 79 | + |
| 80 | +The BIOS does NOT use CD_poll. It polls DSP RAM flag at `[$F1B4C8]` — the GPU ISR |
| 81 | +writes `$FFFFFFFF` there when the transfer completes, and the BIOS loops until negative. |
| 82 | + |
| 83 | +## CD_poll ($304E) |
| 84 | + |
| 85 | +### Inputs |
| 86 | +None. |
| 87 | + |
| 88 | +### Outputs |
| 89 | + |
| 90 | +| Register | Meaning | |
| 91 | +|----------|---------| |
| 92 | +| A0 | Current RAM write position (GPU ISR advances this as data arrives) | |
| 93 | +| A1 | Bytes transferred so far (from GPU data area [+8]) | |
| 94 | + |
| 95 | +Boot stubs typically save the end address in A6 before calling CD_read, then poll: |
| 96 | +``` |
| 97 | +.poll: JSR ($304E).w |
| 98 | + CMPA.L A6, A0 ; current position >= end? |
| 99 | + BLT .poll |
| 100 | +``` |
| 101 | + |
| 102 | +## CDBYPASS Boot Sequence (Reference) |
| 103 | + |
| 104 | +1. `JSR $3048` — hardware reset |
| 105 | +2. `JSR $3006` — CD_init (D0=2, audio mode) |
| 106 | +3. `JSR $305A` — read TOC to $2C00 |
| 107 | +4. TOC scan: find session marker (byte[4]==1), take next entry's MSF |
| 108 | +5. MSF adjustment: subtract 6 frames (pregap offset) |
| 109 | +6. `JSR $3060` — set up **CD-ROM mode ISR** (A0=$F030A4) |
| 110 | +7. First `JSR $303C` — CD_read 4096 bytes, D1="ATRI", to $6010 |
| 111 | +8. Scan loaded data for "TRI " header, extract load address + length |
| 112 | +9. Second `JSR $303C` — CD_read (length) bytes of game data |
| 113 | +10. Copy to final load address, `JMP` to it |
| 114 | + |
| 115 | +## Sector Data Format |
| 116 | + |
| 117 | +Jaguar CD data tracks are typed as AUDIO in CUE sheets. Each sector is 2352 bytes |
| 118 | +of raw data (no Mode 1 sync/header/ECC structure). The I2S bus transfers all 2352 bytes. |
| 119 | + |
| 120 | +The I2S transfer swaps bytes within 16-bit words. The GPU ISR un-swaps before writing |
| 121 | +to RAM. Data on disc (in BIN files) is stored pre-swapped. |
| 122 | + |
| 123 | +MiSTer FPGA note: the ring buffer stores 2048 bytes per sector, but this is an |
| 124 | +implementation detail of the HPS interface, not a reflection of the Jaguar hardware. |
0 commit comments