Então eu resolvi criar um jogo para MSX

Sempre achei que desenvolver um jogo deve ser o ápice da capacidade de um programador e a maneira mais forte de provar a habilidade de uma pessoa e, como não tenho experiência em desenvolvimento, qualquer coisa relacionada ao assunto sempre parece magia arcana e invocação espiritual esteve envolvido no processo. Mas recentemente eu decidi colocar minha falta de confidencia de lado e tentar desenvolver algo pra maquinas MSX desde o zero.

Minha tentativa inicial foi usar a biblioteca Fusion-C, então fui atrás do livro oficial e tentei algumas linhas de código e pude compilar e executar o programa no OpenMSX depois de algumas noites trabalhando nos problemas do ambiente.

Excelente conteúdo, mas muito técnico

Como sugerido por um amigo do Brasil, eu estava tentando fazer algo que pudesse se parecer com os Portões Laser do Atari, e usando o TinySprite do Jannone eu poderia replicar alguns dos sprites do jogo como a nave principal e alguns inimigos, mas devido à minha falta de habilidade e conhecimento das entranhas do MSX, os resultados não foram tão bons na época, como podemos ver abaixo.

Na época, percebi que copiar e colar trechos de exemplos não me ajudaria em nada a melhorar os resultados do meu código, e minha falta de conhecimento sobre a arquitetura estava me impedindo de seguir em frente.

Deixei tudo de lado por algum tempo e mudei para outros projetos, mas no segundo semestre de 2021 a necessidade de aprender e criar algo me atingiu novamente, então fui atrás de alguns outros livros como “Aprenda programa de montagem multiplataforma com ChibiAkumas” e o “livro de dados técnicos do MSX” para detalhes adicionais sobre a plataforma, e eu finalmente mergulhei de cabeça no trabalho incrível e assustador de MSX Assembly

Como eu comecei?

Lendo os livros e páginas da web, percebi que, em geral, é recomendável iniciar o caminho de aprendizagem entendendo os seguintes assuntos básicos:

  1. Como o processador Z80 funciona
  2. Cálculos em binário e hexadecimal
  3. A arquitetura completa do MSX
  4. A arquitetura e os registradores do VDP TMS9918
  5. Invocando seres antigos e convocando espíritos

Como um bom tipo estranho de pessoa, simplesmente decidi ir direto ao código assembly, sabendo que precisaria buscar mais informações sobre assuntos básicos quando necessário, avançando com o conhecimento apenas o suficiente para fazer algo funcionar. Esta é uma ação arriscada, mas não tenho medo de arranhar tudo e começar do zero novamente se ficar preso, e nenhum dano poderia acontecer com isso, exceto perder meu tempo disponível no processo. Para ser honesto, esse método não é o mais recomendado e pode ser muito frustrante, mas avançar qualquer etapa parece uma grande conquista.

É incrível o número de recursos disponíveis hoje para desenvolver para a plataforma MSX se você pesquisar um pouco na rede, desde programar diretamente no hardware original até emuladores baseados na Web com rápida compilação ASM. Tentei algumas das opções disponíveis, mas no final decidi começar meu caminho de aprendizagem usando o site MSXPen ,uma vez que fornece um processo muito simples de executar o programa ASM sem a necessidade de mover arquivos ou executar emuladores em minha máquina local.

Explicar é a melhor maneira de aprender

Indo direto ao assunto, quero explicar as coisas que aprendi da maneira mais simplificada, o que me ajudará a absorver melhor as informações e também ajudar qualquer pessoa interessada em descobrir como programar em Assembly para o MSX, e eventualmente ter algo para mostrar no final deste caminho.

Em meus artigos, usarei o MSXPen como a ferramenta principal para as atividades, mas, eventualmente, posso incluir outras ferramentas. Meu objetivo é explicar e fornecer recursos a qualquer pessoa para replicar minhas ações sem muito aborrecimento.

O site MSXPen vem com um simples código de "Olá Mundo?" , então meu primeiro passo foi comentar em todas as linhas para entender como o programa funciona:

; chamada de bios para imprimir um caractere na tela CHPUT: equ 0x00a2 ; o endereço do nosso programa org 0xD000 start: ld hl, mensagem mainLoop: ld a, (hl) cp 0 ret z call CHPUT inc hl jr mainLoop mensagem: db "Hello world!",0 ; use o rótulo "start" como o ponto de entrada end start

O programa começa definindo uma constante para a chamada CHPUT para uma função do BIOS, que é responsável por escrever caracteres na tela baseada em texto. Para um iniciante, é de alguma forma difícil entender completamente o que está acontecendo aqui, mas imagine que isso é como contratar uma pessoa para escrever cartas em uma placa em seu lugar, então você não precisa se preocupar em misturar tintas ou saber qual é o melhor pincel ou lápis a usar, basta informar ao profissional qual carta você deseja imprimir e eles cuidam do resto. Voltarei em um artigo posterior explicando o que o endereço hexadecimal 0x00a2 significa e como trabalhar com outras chamadas de BIOS, mas por enquanto, é tudo o que precisamos saber.

O org informa ao sistema onde alocar o programa na memória. A definição de slots e espaço de memória MSX é realmente interessante e importante de entender, mas agora nós só queremos ver a mensagem na tela, configurando a origem do código para 0xD000 funciona perfeitamente e é tudo o que precisamos.

O compilador MSXPen envolve o código com as declarações começar: e fim início , então é bom mantê-lo assim por enquanto. Vemos que o primeiro comando real é ld hl, mensagem, o que basicamente significa “Carregar no registro HL a variável message”, mas isso não significa que todo o conteúdo da variável será carregado no registro e veremos em breve como a montagem funciona em torno disso.

Em seguida temos a seção mainLoop: ,e há um bom motivo para criá-lo lá. As seções que definimos no código não acabaram no programa final, mas são usadas como um ponteiro para o compilador para que ele saiba onde na memória o programa pode precisar pular eventualmente. O primeiro comando em mainLoop é ld a, (hl), que significa "carregar no registro A a posição da memória apontada por HL“, Que é exatamente o primeiro caractere da variável mensagem. Mas por que não carregar mensagem em UMA de uma vez? Simplesmente, o sistema precisará passar por todos os caracteres da variável, uma vez que não pode carregar todos os dados em A (um registrador de 8 bits) e chamar CHPUT pra imprimir ele na tela

O cp 0 compara o conteúdo do registro A com zero e levanta um sinalizador especial denominado Z se verdadeiro. É assim que crio uma instrução semelhante a IF no código do assembly, transferindo a execução do código para outra posição quando necessário. Então a instrução ret z significa “retornar à parte do programa que chamou essa rotina e, se não houver, retornar ao BASIC”. Então podemos descobrir que quando o registrador HL apontar para o valor 0, a rotina terminará e o programa terminará, retornando o controle do sistema para BASIC, DOS ou o que quer que estivesse rodando antes de o programa ser executado.

O comando seguinte é chamar CHPUT, que invoca a rotina do BIOS armazenada na posição 0x00a2 da ROM principal responsável por imprimir as coisas no display. Esta é a definição dessa rotina encontrada no site grauw.nl .

CHPUT Endereço: #00A2 Função: Exibe um caractere Entrada: A - Código ASCII do caractere a ser exibido

A função basicamente obtém o valor do registrador A e o imprime na tela. O local onde será impresso não é uma preocupação para esta rotina, então o caractere será exibido na posição atual dos cursos e então moverá o cursor para a próxima coluna ou linha na tela. Simplesmente assim.

Agora temos algumas ações importantes na próxima linha de código: inc hl. Isso aumentará o valor de HL, o que significa que agora o registro aponta para o segundo caractere da string definida pela variável de mensagem. É assim que o código passa por todos os caracteres definidos pela declaração BD e chama CHPUT para todos eles até que 0 seja carregado em HL, o que faz com que o comando PC 0 levantar a flag Z e retornar a execução de volta ao BASIC ou onde quer que o programa tenha sido executado.

Então, finalmente temos o jr mainLoop, que constantemente retornará a execução do código de volta à posição de memória definida pelo rótulo mainLoop até que algo mais interrompa o loop, neste caso a dupla CP 0 / RET Z .

O final do código contém a seção de mensagem com o DB (Define Byte) com a mensagem "Olá Mundo!" seguida pelo valor 0 que termina o loop quando PC 0 é encontrado.

Tudo isso é muito confuso? Pode ser um pouco, mas mexendo no código Hello world, podemos aprender o básico da montagem do MSX e fazer algumas coisas malucas, como remover as instruções PC 0 e RET Z apenas para ver o sistema MSX enlouquecer, imprimindo lixo e bipando como um louco até que todo o sistema trave. É muito divertido, você deveria tentar!

Isso é tudo, pessoal!

Vou parar por aqui por agora e voltar com mais códigos explicados nos próximos artigos, mas agradecerei todas as sugestões e recomendações para os próximos. Obrigado e bom aprendizado!

Sempre achei que desenvolver um jogo deveria ser o ápice da capacidade de um programador e a maneira mais forte de provar a habilidade de uma pessoa e como não tenho experiência em desenvolvimento, qualquer coisa relacionada ao assunto sempre me pareceu alguma magia arcana e a invocação espiritual. esteve envolvido no processo. Mas recentemente…

2 Comentários

  1. Excelente artigo! Percebi que os comandos \ne outras\ou, típicos de linguagens, dentro dos caracteres da mensagem, podem escrever textos mais longos também. Muito legal.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

pt_BRPortuguês do Brasil