Recapitulando do artigo anterior, descobrimos que a função localizada no endereço 0x4f1c é responsável pela leitura dos comandos do jogador, seja via teclado ou via joystick. Também descobirmos que esta função recebe um parâmetro contido no registrador A.
Agora precisamos rastrear os trechos do jogo que chamam e função 0x4f1c e ver o que acontece quando os valores 7 e 3 são retornados, o que corresponde aos comandos de 'esquerda' e 'direita' respectivamente.
Analisando a primeira chamada, a partir de 0x4cc3 temos que quando a chamada a 0x4f1c retorna 3, o endereço 0x4f03 é chamado
O que encontramos nesta chamada é um bom indício de que estamos perto, pois ambas as chamadas limitam o valor da variável contida em 0xd010. Para a direita o valor é limitado a 100 (0x64 em hexadecimal). Se o valor for menor do que 100 então o conteúdo da posição de memória em 0xd010 é incrementado. Já para a esquerda o valor é limitado a 10 (0x0A).
Em ambos os casos, caso a posição em oxd010 seja alterada a função salta para 0x4ddc. Vamos ver o que tem lá:
- A posição em 0xd012 é incrementada com módulo 2. Isso talvez sirva para comandar o sprite do personagem conforme ele se movimenta, mas por enquanto não importa.
Vamos voltar um pouco e retomar a pista do endereço de memória 0xd010 e ver onde este endereço é usado e como é usado:
Bom, este endereço é utilizado em 18 lugares! São dezesseis lugares a mais para pesquisar (dois nós já vimos). Isso fica para o próximo artigo.
O objetivo é rastrear as referências a esta chamada. Queremos saber se a leitura do Joystick é feita no meio do loop do jogo, ou se é chamada a partir dele. Devemos seguir o código para trás e para a frente até chegar a um bloco estanque. No caso temos todo o bloco compreendido entre os endereços 0x4f1c e 0x4f5e.
Precisamos analisar esta função e ver o que ela recebe de entrada e o que retorna de saída. As primeiras instruções mostram que se o registrador A for igual a 0xFF na entrada, a função desvia para 0x4f48.
Analisando a primeira parte da função (chamada com A!=255), vemos que a matriz de teclado também é lida (função SNSMAT - 0141h) pesquisando-se as teclas 'C' (row 3 bit 0) e 'Z' (row 5 bit 7)
Caso nenhuma destas teclas esteja pressionada, a rotina lê o Joystick 2. Caso o joystick 2 esteja em repouso, ou na posição 1 (cima) ou na posição 5 (baixo) a função retorna. Por outro lado, se o joystick estiver nas posições 2,3,4 (direita e diagonais) a função retorna o valor '3' (direita). Analogamente, se a posição for superior a 5 (6,7,8 - esquerda e diagonais) a função retorna o valor '7' (esquerda).
Os valores 3 e 7 correspondem às posições direita e esquerda, respectivamente que são os mesmos que a função GTSTK retorna quando o joystick é acionado para a esquerda ou a direita.
Já o outro trecho de código lê o teclado e o joystick 1 e também retorna 3 ou 7 caso um destes dois dispositivos esteja nas posições direita/diagonais-direita ou esquerda/diagonais-esquerda.
Este trecho inteiro é candidato a local para se instalar os patches, mas agora é preciso descobrir como o jogo transforma o resultado dos controles direcionais em coordenadas da personagem, que é o tema do próximo artigo.
O MSX só tem duas vias para comandos do usuário: O Teclado e as Portas de Joystick. Sendo assim todos os jogos necessariamente têm que acessar estas vias. Para isso o jogo pode usar as rotinas da BIOS (recomendado) ou ler diretamente as portas de I/O. Para cada jogo precisamos descobrir o método ou os métodos utilizados.
A primeira rotina a ser procurada é a GTPDL (00DEH). Se o jogo a utiliza nosso trabalho está concluído. Mas infelizmente para o Penguin Wars ainda não foi dessa vez.
Estes endereços serão o ponto de partida para a pesquisa das funções que guardam a posição da personagem na tela.
Existem várias ferramentas para desassemblar código de Z80, mas eu gosto de usar o DZ80. O jogo que eu escolhi para adaptar foi o Penguin Wars. A ROM de MSX deste jogo tem 32Kbytes e as configurações para o disassembly ficam como na figura abaixo:
Se tudo estiver certo, a listagem em assembly gerada deve começar no endereço 0x4000 e os dois primeiros caracteres devem ser 0x41 e 0x42
Apesar do padrão MSX estabelecer um padrão para Paddles e tanto a BIOS quanto o BASIC terem suporte a eles, nenhum jogo que eu tenha notícia os utiliza. O único jogo que utiliza Paddles é o Arkanoid, porém este utiliza um padrão próprio, em vez de usar o padrão nativo.
Pois bem, a mecânica de jogo de alguns títulos utiliza somente movimentos laterais e são ótimos candidatos a adaptações para uso de Paddles. Um exemplo é o Galaga.
Lá pelos idos de 1990 eu construí um Paddle para o MSX seguindo as especificações do Livro Vermelho do MSX. Na falta de jogos que o utilizassem eu consegui desassemblar justamente o Galaga de forma a convertê-lo para o uso de Paddles. Naquela época eu ainda usava fitas cassete e tinha que me utilizar de programas que eu mesmo escrevia de forma a poder fazer a adaptação. Como todo o processo era muito trabalhoso eu nunca me aventurei a converter nenhum outro jogo. Hoje em dia com emuladores, desassembladores, etc esta tarefa é um pouco mais facilitada mas mesmo assim não é trivial, uma vez que cada jogo, mesmo da mesma desenvolvedora, funciona de maneira diferente na hora de ler as interfaces com o usuário (teclado, joysticks).
- Inclusão das chamadas de leitura do paddle em substituição às funções de tratamento de teclado e mouse.