Artigos
GBA em Assembly — 1. Como o hardware funciona
Comece do zero: entenda CPU, ROM, RAM e o mapa de memória do Game Boy Advance antes de escrever as primeiras instruções.
Você aperta uma tecla, um personagem anda e a tela muda. Em um jogo feito para navegador, uma biblioteca pode esconder quase todo o caminho entre essas três coisas. No Game Boy Advance, vamos enxergar esse caminho: a CPU lê os botões, calcula uma posição, grava números na memória de vídeo e o circuito de vídeo transforma esses números em imagem.
Esta série parte de noções de variáveis, condições e laços. Você não precisa conhecer eletrônica, Assembly ou arquitetura de computadores. Vamos aprender cada conceito com um exemplo pequeno e chegar a um minijogo de levar um quadrado até um alvo. Essa base prepara a leitura do artigo principal de Tower Defense.
Durante a leitura, use a referência de instruções e sintaxe. Ela reúne os comandos, as condições e as diretivas em um artigo de consulta; os capítulos também apontam diretamente para as seções usadas em cada exemplo.
Como acompanhar este curso
Você só precisa reconhecer uma variável, uma condição if e um laço. Vamos apresentar o vocabulário de hardware e Assembly conforme ele aparecer. Não é necessário conhecer eletrônica ou ter desenvolvido para consoles.
- Leia os capítulos 1 e 2 com um caderno. Os blocos curtos de código são exercícios para acompanhar valores; ainda não é necessário instalar ou executar nada.
- No capítulo 3, instale as ferramentas, prepare três arquivos e construa sua primeira ROM. Aqui, ROM é o arquivo do jogo aberto em um emulador, programa que imita o console no seu computador.
- Nos capítulos 4 a 8, abra o arquivo
.scompleto do capítulo, construa e confira o resultado descrito antes de editar. Cada arquivo é um programa independente. As rotinas citadas explicam partes desse arquivo; não são arquivos para substituí-lo. - Faça uma pequena mudança, salve, reconstrua e compare o resultado com a previsão. Guarde uma cópia do último código que funcionou para poder desfazer a alteração.
- Use o capítulo 9 para conferir sua compreensão antes de começar o Tower Defense. A referência de instruções serve para consultar um comando quando ele aparecer; você não precisa decorá-la antes.
O caminho obrigatório termina no ponto de conferência de cada capítulo. As experiências extras são opcionais. Se uma conferência falhar, resolva antes de acrescentar o próximo conceito: os exemplos seguintes se apoiam na explicação que você acabou de usar.
Qual Game Boy estamos programando?
O alvo é o Game Boy Advance, ou GBA, o mesmo do tutorial de Tower Defense deste site. O Game Boy clássico e o Game Boy Color usam outra CPU e outro conjunto de instruções. Um programa ARM deste curso não funciona neles. A compatibilidade do GBA com jogos antigos não torna os dois ambientes de programação iguais.
No GBA, nossa CPU é a ARM7TDMI. Vamos usar seu conjunto de instruções ARM de 32 bits. Ela também oferece Thumb, com instruções menores, mas misturar os dois agora acrescentaria uma dificuldade desnecessária. “Assembly” é o nome de uma família de linguagens próximas das instruções das CPUs; não existe um Assembly universal.
O percurso de um programa
Uma CPU executa instruções representadas por números. Uma instrução pode somar dois valores; outra pode ler um endereço de memória; outra pode mudar o ponto da execução. O texto add r1, r1, #1 é uma forma legível de pedir uma dessas operações. Um programa chamado assembler traduz esse texto para a representação que a CPU executa.
O nosso arquivo .gba será uma imagem de ROM: uma sequência de bytes organizada como o conteúdo de um cartucho. No console, a inicialização passa pelo programa interno de boot antes de entrar no cartucho. No emulador, esse processo pode ser reproduzido ou parcialmente substituído. Por isso, abrir uma ROM no emulador é uma verificação útil, mas não comprova funcionamento em um console físico.
Depois da entrada no nosso código, não há um navegador chamando uma função de atualização. Somos responsáveis por preparar a memória que usamos e por escrever o laço que mantém o jogo funcionando.
CPU, ROM e RAM têm trabalhos diferentes
Pense em uma receita, uma bancada e nas pequenas anotações que você mantém enquanto cozinha. A ROM se parece com a receita: contém instruções e dados que o nosso programa vai consultar. A RAM se parece com a bancada: guarda o estado que muda durante a partida. Os registradores da CPU se parecem com as anotações que você está usando naquele instante.
A analogia tem limites. Os registradores são espaços de armazenamento dentro da CPU; a RAM fica em outras regiões do sistema. Para calcular algo com uma variável da RAM, normalmente precisamos carregá-la em um registrador, operar e gravar o resultado de volta.
| Peça | Papel neste jogo | Exemplo |
|---|---|---|
| CPU | Executar instruções | Somar um à posição do inimigo |
| ROM do cartucho | Conservar código e constantes | Rotina que calcula dano |
| RAM de trabalho | Guardar o estado da partida | Vida da base e saldo de moedas |
| Memória de vídeo, VRAM | Guardar dados gráficos | Cores dos pixels no modo escolhido |
| Registradores de entrada e saída | Expor controles do hardware | Ler botões ou selecionar um modo de vídeo |
| Circuito de vídeo | Produzir a imagem a partir da configuração e dos dados | Exibir o tabuleiro |
O hardware não sabe o que é uma torre, uma moeda ou uma vitória. Esses significados pertencem ao nosso programa.
O caminho entre o código e a tela
Leia as setas como o caminho dos dados nos nossos exemplos. A seta dupla da RAM indica leitura e escrita: a CPU consulta a posição do jogador, calcula uma nova posição e a guarda de volta. A ROM fornece instruções e constantes; não é onde salvamos o estado que muda durante a partida.
Os botões chegam ao programa por KEYINPUT. Para mostrar o resultado de uma ação, a CPU escreve as cores na VRAM. Ela também escolhe como o vídeo deve interpretar esses dados por meio de DISPCNT. O circuito de vídeo usa a configuração e os dados gráficos para produzir a imagem da tela.
O desenho é um mapa conceitual desse uso do hardware, não um esquema dos fios e barramentos do console. Outros acessos são possíveis, e a forma de organizar os dados gráficos muda conforme o modo de vídeo. A seguir vamos colocar endereços nas peças que o programa acessa.
Endereços são a ponte entre Assembly e hardware
Para a CPU, várias dessas peças podem ser acessadas por endereços. Um endereço identifica um lugar no mapa de memória. Não significa necessariamente uma célula de RAM: certas faixas correspondem a controles do hardware.
| Endereço inicial | Região | Como vamos usá-la |
|---|---|---|
0x02000000 | EWRAM, 256 KiB de RAM de trabalho | Variáveis da partida |
0x03000000 | IWRAM, 32 KiB de RAM interna | Pilha de chamadas |
0x04000000 | Registradores de entrada e saída, ou I/O | Vídeo e botões |
0x05000000 | Memória de paletas | Fica para uma evolução dos gráficos |
0x06000000 | VRAM, 96 KiB | Imagem do nosso exemplo |
0x07000000 | OAM, atributos de objetos gráficos | Fica para a introdução a sprites |
0x08000000 | Primeira região de acesso à ROM do cartucho | Código e constantes |
0x indica um número escrito em hexadecimal. Vamos aprender essa notação no próximo capítulo. Por enquanto, trate os números da tabela como endereços de uma rua: mudar de endereço pode significar falar com outra peça.
Este é um recorte do mapa. Existem outras regiões, espelhamentos e restrições de acesso. Não vamos supor que qualquer endereço possa ser lido ou escrito livremente.
Dois sentidos para a palavra registrador
Para consultar a notação do exemplo, veja registradores da CPU e LDR, STR e a diferença entre endereço e conteúdo na referência.
Essa distinção evita muita confusão. r0 é um registrador da CPU: pode guardar temporariamente um número ou um endereço. DISPCNT é um registrador de controle do vídeo, acessado pelo endereço 0x04000000: seus bits configuram o circuito de vídeo.
Neste trecho, ainda apenas para leitura, estamos preparando uma configuração:
ldr r0, =0x04000000
ldr r1, =0x0403
strh r1, [r0]
A primeira linha coloca o endereço de DISPCNT em r0. A segunda coloca o valor desejado em r1. A terceira escreve 16 bits desse valor no endereço guardado em r0. O circuito de vídeo interpreta esses bits como uma configuração. Não chamamos uma função de desenho: realizamos uma escrita em um endereço com significado para o hardware.
Em outro endereço, a mesma instrução strh poderia escrever uma cor ou alterar uma variável. A instrução descreve a operação; o endereço determina com qual parte do sistema ela interage.
O que vamos construir, em ordem
| Capítulo | Pergunta que vamos responder | Experiência ou resultado |
|---|---|---|
| 1. Este artigo | Como o programa alcança o hardware? | Identificar CPU, memória e I/O |
| 2. Bits, registradores e memória | O que uma instrução realmente modifica? | Acompanhar valores passo a passo |
| 3. Ambiente e primeira ROM | Como o texto vira um cartucho executável? | Tela vermelha com um pixel branco |
| 4. Pixels e cenário | Como coordenadas viram endereços na VRAM? | Retângulo verde sobre fundo preto |
| 5. Tempo e VBlank | Como acompanhar o ritmo da tela? | Uma atualização por quadro |
| 6. Ler os botões | Como o hardware representa um botão? | Quadrado que muda de cor ao apertar A |
| 7. Mover um quadrado | Como unir entrada, posição e imagem? | Quadrado controlado pelo direcional |
| 8. Primeiro minijogo | Como pequenas regras formam um jogo? | Alcançar um alvo, vencer e reiniciar |
| 9. Depuração e próximos passos | Como descobrir por que algo falhou? | Inspecionar uma ROM e planejar melhorias |
Os dois primeiros capítulos são de fundamentos. Do terceiro em diante, vamos executar os exemplos. O pacote de apoio contém seis programas independentes: primeira tela, retângulo, pisca, botões, movimento e minijogo. Cada arquivo .s é completo e usa apenas o linker script e a ferramenta de cabeçalho incluídos. Você pode escrever os trechos estudados e comparar com o arquivo pronto, sem depender de funções escondidas.
O código do Tower Defense vem da versão v0.3.0 do projeto Gateblade e recebeu apoio de IA. Os seis exemplos desta série foram preparados separadamente para ensinar um conceito por vez. Os testes se concentram em emulação; não foi realizado teste em GBA físico.
Antes de continuar
Tente responder: quem decide que o inimigo perdeu vida? Quem guarda esse valor entre duas atualizações? Quem transforma as cores gravadas em uma imagem?
As respostas são, respectivamente, nosso código executado pela CPU, a RAM e o circuito de vídeo. Se você consegue separar esses três trabalhos, já tem o modelo necessário para começar.
Para consultar o mapa e as características da máquina, use Tonc: hardware do GBA. A introdução do Tonc a Assembly ARM será uma referência complementar ao longo da série.
Próximo: bits, registradores e memória, sem pular as primeiras instruções.