Na reconversão do Megalomania, eu tinha prometido contar sobre as incompatibilidades deste demo no TK90X. Nesta postagem estou cumprindo a promessa.
Parte 1
Já na 1ª parte o demo trava na tela abaixo, esperando entrada pelo teclado.
Este é o sintoma de uma incompatibilidade já conhecida na porta 254, que espera um valor que nunca será fornecido pelo TK90X e alguns modelos de ZX Spectrum ou clones. A listagem assembly do trecho da leitura do teclado é:
A leitura da porta 254 deveria ser tratada bit a bit, não feita uma comparação com o byte inteiro. Felizmente como a rotina não é otimizada, há espaço de sobra para ser modificada:
loop
Já na 1ª parte o demo trava na tela abaixo, esperando entrada pelo teclado.
Este é o sintoma de uma incompatibilidade já conhecida na porta 254, que espera um valor que nunca será fornecido pelo TK90X e alguns modelos de ZX Spectrum ou clones. A listagem assembly do trecho da leitura do teclado é:
58216 LD BC,#F7FE ;Seleciona fileira das teclas 1-5.
58221 IN A,(C) ;Leitura da porta 254.
CP #BF ;Se nenhuma tecla for pressionada
JR Z,58221 ;
(%10111111),
volta para o laço.
LD (65502),A ;Guarda valor em variável do programa.
CP #BE ;Tecla 1 (%10111110).
JR NZ,58238
LD B,1
JR 58268
58238 CP #BD ;Tecla 2 (%10111101).
JR NZ,58246
LD B,2
JR 58268
58246 CP #BB ;Tecla 3 (%10111011).
JR NZ,58254
LD B,3
JR 58268
58254 CP #B7 ;Tecla 4 (%10110111).
JR NZ,58262
LD B,4
JR 58268
58262 CP #AF ;Tecla 5 (%10101111).
JR NZ,58221
58266 LD B,5
58268 LD HL,22711
A leitura da porta 254 deveria ser tratada bit a bit, não feita uma comparação com o byte inteiro. Felizmente como a rotina não é otimizada, há espaço de sobra para ser modificada:
58221 IN A,(C)
58223 OR %11100000
58225 CP %11111111
58227 JR Z,58221
58229 RES 6,A
58231 LD (65502),A
58234 LD B,1
58236 RRA
58237 JR NC,skip1
58239 INC B
58240 RRA
58241 JR NC,skip1
58243 INC B
58244 RRA
58245 JR NC,skip1
58247 INC B
58248 RRA
58249 JR NC,skip1
58251 INC B
58252 RRA
58253 JR C,loop
skip1
58255 JP 58268
Com o remendo (patch) acima, o demo roda sem problemas no TK90X.
Parte 3
Logo depois de iniciar esta parte, o computador fica paralisado.
Examinando com a Multiface 1, encontrou-se a pilha do Z80 em SP=#7516, que aponta para o endereço 51952. O disassembly deste trecho é:
51949 EI
51950 NOP
51951 HALT
51952 DI
Vi que IFF2=0, isto é, aparentemente ocorre um HALT com interrupções desabilitadas, o que explicaria o travamento do computador.
Logo após retornar da M1, o programa destrava e continua funcionando por um tempo. Porém novamente acaba travando após certo tempo. Este fato reforça a hipótese de um HALT com interrupções desabilitadas, pois o NMI da M1 aparentemente faz com que o Z80 saia do estado de HALT.
Segundo Sean Young, em "The Undocumented Z80 Documented" (disponível em www.z80.info), a instrução logo a seguir de EI não aceitará interrupções. Portanto do jeito que está, não se aceita requisição de interrupção entre 51949 e 51950, porém é perfeitamente possível haver uma requisição entre 51950 e 51951.
Se houver uma requisição de interrupção antes de HALT, as interrupções são desabilitadas e executa-se a rotina em 65535, que simplesmente é RET. O problema está no retorno da rotina de interrupção, que deixa a interrupção desabilitada; ao encontrar HALT, o Z80 fica paralisado para sempre. O correto era: 1) a rotina de interrupção deve ativar as interrupções antes do retorno; ou 2) colocar a instrução EI imediatamente antes de HALT.
O motivo do bug só se manifestar no TK90X não está claro. Uma possibilidade é que, por ser de 60Hz a frequência do sinal INT do Z80, diferente de 50 Hz do ZX Spectrum, acaba fazendo com que em algum momento ocorra a infeliz coincidência da interrupção ser executada entre 51950 e 51951. Talvez do modo que o programa está escrito, com o sinal INT à 50 Hz não há possibilidade de ocorrer tal coincidência. Qualquer hora preciso testar no TK90X chaveado para 50 Hz.
O diagnóstico não é fácil, mas a solução é bastante simples. Basta subsitituir a instrução em 51950 de NOP para EI, para impedir que uma interrupção seja aceita entre 51950 a 51951. Para isso basta fazer POKE 51950,251 (251 é opcode de EI). Este é o único programa com problema com 60 Hz que encontrei uma solução que não seja o chaveamento na ULA.
Nenhum comentário:
Postar um comentário
Seu comentário é bem vindo, mas peço que use este espaço adequadamente.