; Front-end for the ADPCM transport (ROADMAP P6a), for the rig. ; ; It plays ONE buffer of nibbles the host pushed into RAM and reports what the ; channel did. What is being measured is not this code -- it is the CHIP: which ; delta formula, which nibble of a byte first, where the accumulator clamps, and ; what it starts at. tools/bench/verify_adpcm_chip.py reads all four out of ; MAME's own -wavwrite capture. ; ; THE ONE THING THIS FILE HAS TO GET RIGHT is the order of the two starts. The ; chip resets its accumulator, its step index AND its nibble select when it is ; told to PLAY, and it begins consuming immediately out of whatever its data ; register holds. So the channel goes first and the CPU waits for MTC to move ; -- proof that a byte has actually been taken -- before the PLAY. The stream ; still has a prologue of unknown length, because the gap between PLAY and the ; NEXT #DRQ3 is not ours to set; the prologue is 16 zero nibbles for exactly ; that reason and the verifier reads its length off the capture. include "src/player/geom.i" AD_FLAG = $18600 ; u32 0 idle, 1 armed, 2 playing, $FF done, $EE error AD_BUF = $18604 ; u32 where the nibble bytes are AD_LEN = $18608 ; u32 how many bytes AD_MTC0 = $1860C ; u32 MTC at the instant PLAY was written AD_CSRF = $18610 ; u32 CSR at completion AD_CERF = $18614 ; u32 CER with it AD_MTCF = $18618 ; u32 MTC with it AD_MARF = $1861C ; u32 MAR with it -- where the channel stopped AD_SPIN = $18620 ; u32 trips round the wait loop AD_STAT = $18624 ; u32 the chip's own status byte while playing AD_PATIENCE = 60000000 AD_SETTLE = 60000 ; ~100 ms at 10 MHz, 18 clocks a trip ; the wait is bounded like every other org $10000 start: bsr ad_setup ; ---- SETTLE, and it is not superstition. The 8 MHz ADPCM clock is ; CT1 in the YM2151's port register, and this machine delivers that ; write to the ADPCM chip on the SOUND system's own schedule rather ; than at the instant of the store -- so a transfer started in the same ; breath as ad_setup plays its first ~17 ms at the PREVIOUS clock. The ; symptom is exact: the capture's first 130-odd samples come out in ; identical PAIRS, because the chip is clocking half as fast as the ; capture, and every model then fails to fit a stream that changed rate ; part way through. ~100 ms of nothing costs the gate nothing and a ; player sets its clock once at boot. move.l #AD_SETTLE,d0 .settle:subq.l #1,d0 bne.s .settle movea.l AD_BUF.l,a1 move.l AD_LEN.l,d1 bsr ad_arm move.l #1,AD_FLAG.l ; ---- wait for the channel to actually take byte 0. Not a delay loop: ; the condition is MTC having moved, which is the channel's own account. move.l #AD_PATIENCE,d3 .first: move.w A3_MTC,d0 andi.l #$FFFF,d0 cmp.l AD_LEN.l,d0 bne.s .go subq.l #1,d3 bne.s .first bra bad .go: move.l d0,AD_MTC0.l bsr ad_play move.l #2,AD_FLAG.l moveq #0,d0 move.b AD_CTRLR,d0 ; bit 7 clear = the chip says it is playing move.l d0,AD_STAT.l clr.l AD_SPIN.l move.l #AD_PATIENCE,d3 .wait: addq.l #1,AD_SPIN.l move.b A3_CSR,d4 btst #4,d4 ; ERR -- CER says which bne.s bad btst #7,d4 ; COC bne.s .fin subq.l #1,d3 bne.s .wait bra.s bad .fin: bsr report ; The chip is left PLAYING deliberately: it goes on replaying the last ; byte it was given, which the verifier ignores. Stopping here would ; put a silence in the capture at a point the host would then have to ; find, and the capture already has a length it knows. move.l #$FF,AD_FLAG.l hold: bra.s hold bad: bsr report move.l #$EE,AD_FLAG.l bra.s hold report: moveq #0,d0 move.b A3_CSR,d0 move.l d0,AD_CSRF.l moveq #0,d0 move.b A3_CER,d0 move.l d0,AD_CERF.l move.w A3_MTC,d0 andi.l #$FFFF,d0 move.l d0,AD_MTCF.l move.l A3_MAR,d0 move.l d0,AD_MARF.l rts include "src/player/adpcm.i"