Executando verificação de segurança...
20

Recriando um jogo de Game Boy Advance a partir dos sons de crash

Antes de começar essa publicação, eu preciso que você escute isso aqui. O som desse vídeo é o som de quando ocorre um travamento (crash) no Game Boy Advance (um console de 2001). Mas você sabe por que o crash tem um som assim no GBA?

Um canal no YouTube chamado TheZZAZZGlitch tem vários vídeos de curiosidades em consoles e jogos antigos, e um deles, chamado Interesting observations #4, no minuto 6:01, explica como funciona esse som (e é importante entender isso para o resto desta publicação fazer sentido).

O som de crash ocorre apenas quando o travamento ocorre quando a interrupção do VCount é desativada por uma falha na execução. Não achei um link para deixar de referência sobre esse VCount interrupt, mas no vídeo ele continua com um exemplo.

Os dados de áudio são transmitidos de um pequeno buffer na RAM a uma taxa constante, usando um mecanismo chamado DMA. Ele faz isso automaticamente, sem que o processador precise trabalhar. Então, cada vez que o fim do buffer é atingido, uma interrupção é disparada para atualizar esses dados e redefinir o ponteiro DMA.

Ponteiro voltando ao início do som ao chegar na interrupção.

Se, por algum motivo, a interrupção não estiver presente, o ponteiro DMA nunca será reiniciado, e os dados nunca serão atualizados. O DMA automático simplesmente seguirá em frente e continuará funcionando, alimentando os conteúdos de todo o espaço de endereço para os alto-falantes como dados sonoros para tocar.

Som não interrompido, então executa sons não esperados.

O buffer de som está localizado na RAM, que tem apenas 32 KB, espelhado em um pedaço de 16 MB de espaço de endereço. Portanto, o mesmo som de falha será repetido 512 vezes.

Se você esperar por 512 loops (ou cerca de 17 minutos), a RAM para de fazer o loop e o ponteiro DMA alcança a MMIO (memory mapped I/O). Essa área faz um loop a cada 1 KB, resultando em um som mais áspero (ouça no vídeo).

Essa parte do vídeo termina com o questionamento:

Podemos ouvir esses sons e recuperar o conteúdo da RAM a partir deles? Talvez possamos realizar o dump da ROM ouvindo o som de travamento e decodificá-lo?

Realizando o dump da ROM de um jogo do GBA ouvindo seu som de crash

O vídeo mostrando o processo e a investigação está aqui: Dumping the ROM of a GBA game by crashing it.

O primeiro passo era verificar se o conteúdo da ROM era realmente despejado no áudio de crash. Depois de 1h50, o autor do vídeo conseguiu confirmar isso ao ouvir as amostras de instrumentos do jogo (que estão na ROM) em sequência.

Depois disso, era a hora da programação. Foram dois dias corrigindo alguns bugs e então ele conseguiu gerar o arquivo necessário para testar. O código foi compartilhado aqui, com o nome gbacrashsound_dumper.zip, no arquivo a.py.

Mas, ao importar o arquivo no emulador, o jogo crashou. Então, ele viu que tinham alguns espaços vazios (com bytes 0x00) na ROM, e criou um segundo código para tratar isso: b.py.

Seções com bytes 0x00 no áudio.

O resultado foi um dump 99.76% preciso, mas ainda sem conseguir executar no emulador. Ele decidiu gerar mais dumps. Foram três gravações longas, e ao mesclá-las considerando o como certo os bytes em comum "na maioria" dos arquivos, conseguiu alcançar a precisão de 99.979% do dump. O boot funcionou, mas ainda não estava correto:

O jogo iniciou com algumas manchas pretas, e crashou.

Realizou mais três gravações, e com 7 dumps diferentes, conseguiu alcançar a precisão de 100%.

O jogo iniciando corretamente.

Após ter esse sucesso no emulador, ele pegou um Nintendo DS e um cartucho do Pokémon Emerald para realizar o teste do crash. O cartucho era uma réplica (pirata), então não dava para ter certeza se o comportamento seria o mesmo do emulador.

Eu não havia entendido porquê ele pegou um Nintendo DS se estava falando sobre um jogo de GBA, mas pesquisei e vi que é possível rodar um jogo de GBA em um Nintendo DS, e o formato do cartucho que ele inseriu no Nintendo DS realmente era de um cartucho GBA.

Ele precisou fazer algumas adaptações para capturar o som de forma limpa, fez mais cinco gravações e atingiu apenas 85% de precisão, com a maior parte das diferenças no final do arquivo. A suspeita era de que esse cartucho réplica preenchia a ROM com 0x00 ao invés de 0xFF:

Final do arquivo com as diferenças.

O autor precisou de mais 45 gravações e conseguiu 99.9837%. Apesar disso, o jogo iniciou corretamente. Então, ele decidiu realizar uma engenharia reversa para entender as diferenças.

Ele descobriu que o cartucho réplica não tem um chip flash dedicado para armazenar o progresso. Em vez disso, a ROM em si é armazenada em um chip flash gravável, junto com os dados salvos. Como não é possível executar a partir do flash enquanto grava nele, há algumas modificações que copiam o código para a RAM e pulam para lá.

Mas, isso já é outra história. A conclusão (que eu tirei) do vídeo é que, dado arquivos de crashs o suficiente, é possível sim reconstruir a ROM de um jogo de GBA, mas não é um processo tão simples. Foi uma pesquisa interessante.

Carregando publicação patrocinada...
1