No Amiga, o que acontece quando escrevo para $DFC5A0 por engano?
Estou consertando um jogo (TV Sports Basketball) que tenta gravar em dados de áudio (usando o intervalo $DFF0A0
para $DFF0D0
), mas por algum motivo (programação ruim), o índice às vezes (nem sempre) é falso
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
se D0
for maior que 3, a gravação (A0,D0.W)
está fora dos limites. No meu caso, ele escreve para $DFC5A0
, porque após o deslocamento D0
é $D500
. Também depende da localização da memória da expansão de memória (usar apenas a memória do chip não aciona o bug).
Eu sei que o sistema de endereçamento do Amiga tem máscaras para registradores personalizados e CIAs, e talvez ele realmente escreva para o endereço correto (duvido com $D50
um valor base para o índice do canal...), mas se eu corrigir o problema por removendo a gravação quando o índice está fora do intervalo, talvez o som não funcione, enquanto funciona com esse endereço falso.
Por exemplo, se eu escrever algo para $DFC09A
ele, na verdade, tem efeito sobre $DFF09A
(INTENA, mais fácil de verificar com este registro específico que possui uma contraparte somente leitura), mas se eu escrever $DFC59A
, não tem efeito sobre o INTENA.
Não quero deixar esse endereço falso como está, porque ele viola o layout da memória. Existe uma fórmula para mascarar esse endereço e voltar ao $DFF0A0 - $DFF0D0
intervalo?
Respostas
nota: estou respondendo minha própria pergunta depois de mais pesquisa e experimentação.
A $DFF000
base é o endereço base de registro de chip personalizado recomendado pela Commodore .
Mas muitos outros endereços básicos funcionam. Algumas linhas de endereço selecionam a base de chip personalizada e outras são ignoradas.
A área de endereço do chip personalizado é DF0000-DFFFFF
para que qualquer base $DFx000
funcione.
Isso se confirma fazendo alguns testes no emulador WinUAE, que é muito fiel a esses aspectos, e que tem a interessante capacidade de poder ler o que está escrito no registrador usando seu depurador interno.
Então, se eu escrever $12345678
, $DFC0A0
por exemplo, $12345678
aparecerá $DFF0A0
ao ler registros personalizados (usando o emulador): $DFC000
é tão bom quanto $DFF000
um endereço de base de chip personalizado e alguns jogos (por exemplo Curse of Ra) usam endereços de base personalizados alternativos (Curse of Ra usa $DFE000
), talvez para confundir os hackers, ou apenas para ser original.
Agora, quando escrevo um valor de 32 bits para $DFC5A0
(exemplo da vida real), o endereço é convertido em registros personalizados $1A0
e $1A2
que são os registros de cores 16 e 17 ( $5A0
é mascarado para $1A0
, existem apenas registros personalizados de $ 100 de 16 bits, qualquer bit superior é ignorado ), portanto, nesse caso, o registro de áudio não é gravado, mas os registros de cor são gravados, então realmente há um bug na rotina de som.
Agora, por que não tem um efeito visual? Porque escrever em registros de cores geralmente não tem efeito: a maioria das listas de cobre sobrescreve aquelas a cada início do feixe, a cada 20ms em PAL. Pode ser perceptível para a cor de fundo (o fundo piscaria brevemente), mas para as cores do primeiro plano seria pouco visível ou mesmo invisível.
Então agora só tenho que decidir se não executo nenhuma ação nesse caso (como no jogo original) ou se mascaro o valor para selecionar um canal de áudio válido e ver se ele altera o som e talvez corrija um bug de longo prazo no o jogo.