I'm fixing a game (TV Sports Basketball) that tries to write in audio data (using the range $DFF0A0 to $DFF0D0) but for some reason (bad programming), the index is sometimes (not always) bogus

MOVEA.L #$00DFF0A0,A0        ;004e78: 207c00dff0a0  load custom address in A0
MOVE.W  $0008(A5),D0         ;004e80: 302d0008      audio channel 0-3
LSL.W   #4,D0                ;004e84: e948          shifting (mul by 16)
MOVE.L  -$346E(A4),(A0,D0.W) ;004e86: 21accb920000  write to register

if D0 is greater than 3, then the write to (A0,D0.W) is way out of bounds. In my case it writes to $DFC5A0, because after shifting D0 is $D500. It also depends on the memory location of the memory expansion (using only chip memory doesn't trigger the bug).

I know that the Amiga addressing system has masks for custom registers and CIAs, and maybe it will actually write to the correct address (I doubt it with $D50 as a base value for the channel index...), but if I fix the issue by removing the write when the index is out of range, maybe that the sound won't work, whereas it works with that bogus address.

For instance, if I write somethig to $DFC09A it actually has an effect on $DFF09A (INTENA, easier to check with this particular register which has a read-only counterpart) but if I write to $DFC59A it has no effect on INTENA.

I don't want to leave that bogus address as is, because it violates the memory layout. Is there a formula to mask this address and get back in the $DFF0A0 - $DFF0D0 range ?

  • What is your program doing with the low 4 bits of DMACON? Maybe you can safely ignore audio channels that aren't even used? – Brian H Aug 18 at 15:33
  • DMACON audio is enabled at the time of the wrong access. – Jean-François Fabre Aug 18 at 17:35

note: I'm answering my own question after more research and experimentation.

The $DFF000 base is the custom chip register base address recommended by Commodore.

But many other base addresses work. Some address lines select the custom chip base, and some are ignored.

The custom chip address area is DF0000-DFFFFF so any base like $DFx000 works.

This is confirmed by doing some tests on WinUAE emulator, which is very faithful of those aspects, and which has the interesting ability of being able to read what's written in the register using its internal debugger.

So if I write $12345678 in $DFC0A0 for instance, $12345678 will appear in $DFF0A0 when reading custom registers (using the emulator): $DFC000 is as good as $DFF000 as a custom chip base address, and some games (for instance Curse of Ra) use alternate custom base addresses (Curse of Ra uses $DFE000), maybe to confuse hackers, or just to be original.

Now when I write a 32-bit value to $DFC5A0 (real-life example), the address translates to custom registers $1A0 and $1A2 which are color registers 16 and 17 ($5A0 is masked to $1A0, there are only $100 16 bit custom registers, any higher bit is ignored), so in that case, the audio register isn't written, color registers are written instead, so there's really a bug in the sound routine.

Now why doesn't it have an effect of the visuals? Because writing to color registers has usually no effect: most copperlists overwrite those at each start of the beam, every 20ms in PAL. It can be noticeable for the background color (background would briefly flash) but for foreground colors it would be barely visible or even invisible.

So now I just have to decide if I perform no action in that case (like the original game) or if I mask the value to select a valid audio channel and see if it changes the sound, and maybe correct a long-term bug in the game.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.