segunda-feira, 9 de dezembro de 2019

ULA - floating bus no ZX Spectrum 48K

No Spectrum, além do efeito da contenção de memória aquando de acessos simultâneos à RAM dos primeiros 16KB e da ULA, existe também um fenómeno conhecido como floating bus

Na realidade, este é um fenómeno que afecta o resultado da leitura de portas "não conectadas", i.e. de portas ímpares que não tenham hardware associado, já que as portas pares activam a ULA.

Foi discutido que o data BUS por defeito se encontra(va) em $FF no ZX Spectrum. Na realidade, dado a ULA e o Z80 partilharem BUS de endereço e dados, o que acontece é que se for feita uma leitura de uma porta ímpar não conectada  durante o período em que a ULA está a aceder a um byte da área de pixels ou atributos, o valor desse byte será devolvido na leitura da porta. Noutras alturas, é devolvido o valor $FF.

Este comportamento pode ser (ab)usado para monitorar a ULA e é abusado em jogos. (Arkanoid, Sidewize, Cobra, Short Circuit, Aquaplane, Darkstar). O floating bus, pode ser e é diferente em clones, desde a sua não existência, ou timings diferentes. (Timex 2048 / 2068 / modelos 128K / Scorpion /...). Aliás, o comportamento conhecido como floating bus não está presente nos issue 1 e 2 do ZX Spectrum 16K / 48K.

Existe também o floatspy da RAMSOFT, que é um diagnóstico interessante para avaliar se a ULA / primeiros 16 kb da RAM estão bem de saúde, ou se um emulador cumpre os requisitos de emular um ZX Spectrum 48K.

Além de outros efeito, um possível uso útil de monitorizar o floating bus, é esperar que o Spectrum acabe de varrer pelo menos o border superior, ou até a zona de atributos toda, para se ter a certeza que se pode manipular o ecrã sem haver flicker e / ou contenção de RAM.

Sabemos também que o primeiro byte de atributos, é lido 14347T depois do Z80 ter recebido um sinal de INTR da ULA.

Como exemplo de timings:

Valor128K T48K T
Primeira linha de pixels
(0x4000)1436814347
(0x5800)1436914348
(0x4001)1437014349
(0x5801)1437114350
IDLE ($FF)1437214351
IDLE ($FF)1437314352
IDLE ($FF)1437414353
IDLE ($FF)1437514354
(0x4002)1437614355
(0x5802)1437714356
.........
Segunda linha de pixels
(0x4100)1459614571
(0x5800)1459714572
.........

 Note-se a ordem de cada linha:
- Primeira coluna de 8 pixels ($4000/16384)
- Atributo correspondente
- Segunda coluna de 8 pixels
- Atributo correspondente
- Bus em descanso
- Data BUS em descanso;
- Data BUS em descanso;
- Data BUS em descanso;
- Segunda coluna de 8 pixels
....

 Salienta-se mais uma vez, que o varrimento de linhas é feito pela ordem que as linhas são visíveis no ecrã. (para ter melhor ideia, veja no floating_bus.c abaixo, o array de inteiros screen_line em que começa em cada uma das 192 linhas do  ecrã  do ZX Spectrum o varrimento de pixels (e acaba o varrimento do border esquerdo).

Na verdade, o estudo e análise deste efeito colateral do varrimento de ecrã, é uma das melhores formas de entender o efeito dos timings do varrimento de ecrã, mencionados em ULA - varrimento de ecrã do ZX Spectrum

ASM de rotina a usar floating bus para colocar linha de border 
TAP

Output esperado do floatspy num 48K (neste caso no QtSpecem)


Ver:

The floating bus on the 48K and 128K

The floating bus

The “Sidewize Test”: ZX Spectrum floating bus shenanigans

The Definitive Programmer’s Guide to Using the Floating Bus Trick on the ZX Spectrum

teste de floating BUS - floatspy.tap

floating_bus.c : implementação do efeito de floating bus no QtSpecem

Sem comentários:

Publicar um comentário