sábado, 15 de março de 2025

Criar o Manager de Futebol 2025 para ZX Spectrum (parte 2)

Depois de termos deixado a parte 1 do diário de Manager de Futebol 2025 (ver aqui), deixamos agora a segunda parte. O jogo foi desenvolvido por Mário Armão Ferreira, autor da excelente página PCManias (ver aqui).

Criar o Manager de Futebol 2025 para ZX Spectrum (parte 2)

Após ler um bocadinho sobre a arquitectura do Spectrum vejo que os 64 KB restantes não são acessíveis de uma vez como os primeiros. E que dado eles estarem em quatro bancos de 16KB de RAM, teria de aceder a cada um deles de forma individual. E pesquisando um pouco de informação sobre como lhes aceder, atiro-me de cabeça a explorá-los.

Aqui, poderia ter feito como o comum dos mortais. Parava o jogo, estudava a coisa, e voltava quando a percebesse completamente. Mas não só eu não sou assim, como muito sinceramente, não tenho grande pachorra para leituras. Assim, preferi entrar à bruta, batendo com a cabeça e aprendendo com os erros. É minha convicção que o aprendido desta forma acaba por ser mais duradouro que o que se aprende meramente lendo.

Daí que me “atirei” aos bancos, usando código meu. E comparo o que me sucedeu aqui com uma cena do Filme Indiana Jones e a Ultima Cruzada.

Nesse filme, já na parte final, Indiana tem que salvar a vida do seu Pai, e para isso tem de resolver uma série de puzzles que lhe podem custar a vida. Um dele chama-se “A Palavra de Deus”, e consiste num chão coberto de letras onde apenas calcando as letras certas se é possível passar. Indiana conclui que Deus em Hebraico se escreve Jehovah, pelo que muito convicto avança…

J… E o chão desaba sob os seus pés quase o matando, pois na realidade, em Hebraico, Jahovah escreve-se Yehõwã.

Ora é impossível deixar de fazer a comparação disto com o que aconteceu comigo: Ok, há quatro bancos, vamos abrir o primeiro.

1… E o que me apercebo é que, uma vez o banco aberto, 25% do meu código do jogo… desapareceu.
Porque aconteceu isto? Porque na realidade há um bom motivo para que o Basic, em modo 128KB, apenas dê acesso a 64 KB máximo de RAM. E o motivo é que o Z80 apenas consegue endereçar no máximo essa RAM. O que implica que, aceder a mais 16 KB, requer largar um dos bancos em uso, para aceder ao outro.

Por outras palavras, não era com as rotinas que estava a usar que conseguiria chegar lá!

A solução que encontrei passou por reservar um pedaço de RAM dos 64 KB iniciais, que abdico de endereçar, e com ela abrir uma “janela” para os outros bancos, por onde se transfere os dados. E após muito bater com a cabeça, lá consegui com PEEKS e POKES metidos num ciclo FOR NEXT transferir dados para um dos bancos.

Oh maravilha… tudo funcionava… Ou não?

Na realidade… funcionava! Mas a velocidade de transferência de dados era miserável. Por exemplo, para encher o equivalente à memória vídeo, que são 6 912 bytes, o ciclo tinha de ir de 1 a 6 912 para ler os bytes todos. Experimentem fazer um ciclo com esta dimensão, mesmo sem fazerem nada no seu interior, e vejam o que tem de penar para que ele acabe.

E foi aqui que o assembler entrou. Dado que a transferência usando Basic, era lenta, mas mesmo muito, muito lenta, recorri ao assembler, centenas de vezes mais rápido. Apenas como exemplo, em Basic, passar o conteúdo da RAM vídeo de um lado para o outro, demorava mais de 4 minutos. Em assembler, apenas alguns milisegundos.

Tinha resolvido o meu problema. Estava a aceder a mais RAM. E nesse sentido até fui ao meu blogue, a PCMANIAS.COM, colocar num comentário onde tinha dado a conhecer que estava quase a desistir do jogo, o texto: “Yippee-Kai-Yai Motherfucker, consegui!”.

Mas será que tinha mesmo conseguido?

A realidade é que tudo funcionava… e com a RAM adicional, o grafismo podia ser melhorado, e a memória base livre da parte que o definia. Libertaria RAM base, e conseguiria melhores gráficos. Que maravilha!

Assim, conseguindo meter e tirar dados do banco adicional 1… passo ao banco adicional 2…
E tudo funcionava. Excepto que quando mandava retornar os dados do banco 1, o que obtinha era o conteúdo do banco 2 … Que raio se passava?

O que vim a descobrir, é que uma vez aberto o acesso a um banco, a mudança para outro não fecha o acesso ao inicialmente aberto. Conclusão, dado que o estava a trabalhar com endereços lógicos, e não os físicos, que desconheço quais pertencem a que banco, ao mandar os dados para o segundo banco, os dados no primeiro nos mesmos endereços lógicos, eram sobrepostos.

Deixem-me explicar melhor isto:

Cada bloco de RAM tem 16 KB, o que significa que cada um deles tem um total de 16 384 Bytes com endereços do 0000h ao 3FFFh (hexadecimal para 0 e 16 383).

Os primeiros 64 KB de RAM são apresentados como um todo, endereçados com endereços físicos do byte 0 ao 65 535 (0000h a FFFFh), sendo que os restantes bancos terão endereços físicos que acrescem a este valor um total de 16 384 bytes cada um. 

Ou seja, se os bancos fossem usados sequencialmente, do 0 ao 7, o banco 0,1,2 e 3 estariam a uso no Basic e devidamente endereçados, e o banco 4 começaria no endereço 65 536 e iria até ao 81 919, e por aí foram até perfazermos os 128 Kb.

A questão é que, no tempo que disponibilizei a isso não consegui encontrar dados concretos sobre qual a ordem dos bancos, quais os usados, e quais os endereços de RAM de cada um. E nesse sentido fui por tentativa e erro. Assim acedia a bancos livres, mas sem saber quais os endereços físicos que eles possuíam.

A solução foi usar endereços lógicos. Basicamente isso implica tratar os bancos todos por igual, e em vez de dizer qual o endereço exato na RAM total, refiro o endereço dentro do banco em uso que vai do byte 0 ao Byte 14 383.

Ora com dois bancos abertos, ao mandar dados para os primeiros 7 KB do Bloco, o que acontecia é que ele mandava para ambos a mesma coisa, escrevendo por cima do que já tinha mandado para o primeiro bloco. Ou seja, ambos os blocos ficavam a uso, mas ambos continuam a mesma coisa.

É um pouco como em vez de dizerem ao carteiro para entregar na Avenida Marechal Gomes da Costa nº 146, abrindo a cidade Lisboa, mudando depois para o Porto, e pedindo igualmente para entregar na Avenida Marechal Gomes da Costa, nº 146, o que, pelo não fecho de Lisboa, originaria uma duplicação da entrega em ambas as Avenidas (se tal fosse possível).

OMG! E Agora! Como resolvo esta situação! Preciso de fechar o acesso ao primeiro banco, antes de aceder ao segundo.

Recorri a fóruns de programação para ajuda, mas não conhecendo verdadeiramente nenhum bem ativo e dedicado ao Spectrum, não obtive grande ajuda.

Aliás, as respostas que obtinha eram desanimadoras, e do género: “Ao usares os bancos extras dessa forma, meteste-te num caminho que poucos que usaram o Spectrum conseguiam trilhar”.
Desanimei… 

No meio destes comentários, alguém me referiu: “Usa a RAMDISK”. Não dei importância ao que me foi dito, pois não sabia o que isso era, e pensei tratar-se de algum software de terceiros. Optei por usar apenas 16 KB extra, metendo apenas o grafismo do campo, agora bem mais detalhado do que antes, nesta memória. Basicamente leria o conteúdo das imagens directamente para a RAM vídeo, não usando assim memória extra nos 64 KB base.

E assim, disto:


Passei a isto:


Ao não ter de desenhar o campo, tornei o processo mais rápido, libertando o código de uma boa quantidade de PLOTs e DRAWs. O resultado era bem mais convincente. E dado que usava a mesma linha de código para desenhar o campo nas duas direcções, isso obrigava ao uso de variáveis e cálculos de valor absoluto, de forma a tornar positivos resultados negativos. Estava ali uma boa quantidade de código massudo que libertei desta forma.

Mas quando coloco a imagem, criada no Photoshop, na RAM do Spectrum, e executo as animações das jogadas sobre ela… OMG. Que salgalhada de cores!

O motivo era simples. O Spectrum trabalha com duas cores em cada bloco de 8x8, o INK, e o PAPER. Eu tive o cuidado ao criar a imagem de em cada bloco de 8x8 apenas usar duas cores, e usar a paleta de cores do Spectrum. Mas não pude definir, qual da duas cores era o PAPER, e qual era o INK. E o resultado era que isso estava à sorte, criando uma salgalhada de alterações de cores.

Basicamente tive de rever a imagem, recorrendo ao software ZX PAINTBRUSH, percebendo as zonas do ecrã que estavam bem, e copiando os atributos para todo o resto do ecrã, pixel a pixel. Pff… Foi uma trabalheira.

A questão era… mesmo assim a memória estava curta. Faltava muito, muito pouco, mas dado que estava a reservar RAM para a transferência de dados para a RAM Superior, e para a música, precisava de um pouquinho mais de RAM, ou iria ter de sacrificar algumas das novidades. E ainda tinha o problema do Beta Testing, que poderia encontrar bugs que requeressem várias linhas de código para correcção, ou mesmo a criação de subrotinas para prever casos não pensados (como aconteceu).
Tinha de aceder ao resto da RAM. Afinal estava lá tão perto.

Revendo os comentários de ajuda, bati novamente com o que me dizia “Usa a RAMDISK”. E fui pesquisar por ela!

O que encontrei… era a solução de todos os meus problemas.

Continua na parte 3...

Sem comentários:

Enviar um comentário