Codificando a tela de animação “woosh” no Amiga
(dansalva.to)- Magicore Anomala implementa CG em tela cheia e transições no estilo animação com os recursos gráficos e sonoros do Amiga, lançado em 1985, mas dentro do motor do jogo é preciso resolver ao mesmo tempo o layout da RAM, a divisão da tela e as limitações dos sprites
- Em uma configuração comum do Amiga 500, há apenas 512 KB de Chip RAM disponíveis para gráficos e som, então os 48 KB descompactados de uma CG 320x240 com 32 cores pesam bastante
- A CG é reduzida para cerca de 8 KB com compressão ZX0, fica na RAM de expansão e é descompactada para a Chip RAM pouco antes de ser exibida, reutilizando os 48.000 bytes da memória de tela já existente
- O efeito de transição é criado com o copper, que altera registradores de hardware em scanlines específicas e desliga e religa o DMA de bitplanes, enquanto a CPU ajusta os valores da copperlist a cada frame conforme a largura do split
- As motion lines do fundo precisam contornar dependências de cor, reutilização e bitplane dos sprites do Amiga, e os mecanismos centrais são attached sprites, bits de controle falsos, manutenção de 1 bitplane e ajuste de
BPLMOD1
O problema de RAM para colocar uma CG em tela cheia no Amiga 500
- A plataforma-alvo de Magicore Anomala é um Amiga 500 típico, com 512 KB de Chip RAM e 512 KB de RAM de expansão
- A memória que o chipset do Amiga pode usar para saída gráfica e sonora é apenas a Chip RAM
- A RAM de expansão só pode ser acessada pela CPU, então é difícil usá-la diretamente para gráficos e som
- A graphic de personagem em tela cheia (CG) é uma imagem bitmap 320x240 com 32 cores e ocupa 48 KB sem compressão
- Considerando assets compartilhados, dados de fase e alocação de memória de tela, 48 KB é um overhead grande
- O suporte adicionado recentemente para compressão de assets usa o formato de compressão ZX0
- A CG comprimida cai para cerca de 8 KB
- Ao carregar os assets da fase, a CG comprimida é colocada na RAM de expansão
- Pouco antes da exibição, ela é descompactada para a Chip RAM
Como evitar reservar mais 48 KB de Chip RAM
- Em vez de procurar 48 KB livres de Chip RAM só para a CG, parte da memória de tela existente é reutilizada
- Imagem de fundo da sala
- Camada de tela para renderizar objetos perigosos
- Área da tela da caixa de texto
- Essas três regiões de memória são contíguas na RAM, e o tamanho combinado é de 48.000 bytes, exatamente o tamanho da CG
- A imagem de fundo da sala pode ser restaurada depois que a CG termina de ser exibida, então não há problema em sobrescrevê-la
- A descompressão da CG leva cerca de 500 ms, mas isso é inserido no fluxo da cutscene para não parecer um carregamento
- O vídeo de proof-of-concept da gameplay de Magicore Anomala pode ser visto no YouTube
Efeito de divisão de tela e uso do copper
- No começo foi considerada uma transição vertical em wipe, mas para ficar bonita ela precisaria de um gradiente com ajuste da paleta de cores em cada scanline
- Foi considerado difícil definir todas as 32 cores em um único blank horizontal usando apenas o copper
- Como não havia interesse em lidar com “racing the beam”, foi escolhido o efeito de divisão de tela
- O efeito de divisão de tela parece mais impressionante para o público em geral, e o copper do Amiga funciona praticamente como se tivesse sido feito para esse tipo de efeito
- Um caso semelhante embutido no Amiga Workbench pode ser visto neste vídeo
- A implementação usa duas funções do Amiga em conjunto
- O copper executa sua própria lista de instruções em paralelo com a CPU e pode alterar registradores de hardware em linhas específicas da tela
- Os ponteiros de tela podem ser definidos em registradores de hardware para mudar a memória de tela para qualquer posição dentro da Chip RAM
Parando o DMA de bitplanes e retomando o desenho depois
- Por exemplo, se a memória principal da tela começa em
0x20000, normalmente o copper define esse endereço nos registradores de DMA de bitplanes- Quando os bitplanes são ativados, o DMA lê essa região de memória em sequência e a desenha na tela
- Se cada linha horizontal ocupa
0x100bytes, definir o ponteiro de tela como0x20800faz a tela parecer rolada 8 linhas para cima- Isso acontece porque o ponto inicial da tela foi deslocado 8 linhas para baixo na memória
- A metade superior do split é rolada para cima dessa forma
- No ponto do split, o copper desliga o DMA de bitplanes e muda a cor de fundo para vermelho
- Os registradores de hardware ligados aos bitplanes praticamente congelam nesse momento
- Ao chegar à parte inferior do split, a cor de fundo é restaurada e o DMA de bitplanes é ligado novamente
- A tela volta a ser desenhada a partir da posição em que havia parado, mas a posição real de exibição já está mais abaixo
- A cada frame, a CPU ajusta
vs_TCopTopevs_TCopBottomde acordo com a largura atual do split- O ajuste do ponteiro de tela para o split superior também é feito, mas não está incluído no exemplo de código
Contornos com sprites para as motion lines do “woosh”
- As motion lines do fundo animado são desenhadas com sprites
- Como os sprites são desenhados independentemente da memória de tela e podem se mover, eles são adequados para esse uso
- Ainda assim, os sprites do Amiga têm muitas limitações e são complicados de lidar
-
Restrições de cor
- Os sprites compartilham bitplanes e paleta de cores, então é preciso usar o mínimo possível de cores
- As motion lines usam apenas 3 cores, deixando 28 cores para a CG e 1 cor para o fundo
- No Amiga, o intervalo de cores da paleta usado varia conforme cada par de sprites
- Os dois primeiros sprites usam as cores 16-19
- Os dois sprites seguintes usam as cores 20-23
- Ao fazer attach de dois sprites, eles passam a funcionar como um único sprite com paleta de 16 cores e podem usar as cores 16-31
- As motion lines usam 4 attached sprites e, nos gráficos, usam apenas as cores 29-31
-
Usando o mesmo gráfico de sprite em várias posições
- Os 4 primeiros bytes do gráfico do sprite são bits de controle que definem posição e altura
- Essa estrutura vira um problema quando se quer desenhar o mesmo gráfico em várias posições
- Tentou-se definir diretamente os bits de controle do sprite por registradores de hardware, mas não foi possível fazer com que aparecessem na tela
- O DMA de sprites do Amiga, assim como o DMA de bitplanes, segue o ponteiro dos dados do sprite e desenha na tela
- A solução foi criar 8 sprites falsos de 4 bytes
- Esses sprites falsos contêm apenas bits de controle
- Todos os ponteiros de sprite são primeiro definidos para os sprites falsos
- Por volta da linha 19, o sprite DMA lê os ponteiros e carrega os bits de controle
- Depois disso, todos os ponteiros são trocados para o gráfico real da “motion line”
- Com isso, o DMA fica carregado para desenhar sprites em posições diferentes enquanto usa o mesmo gráfico, e essa troca é feita na copperlist
O problema de os sprites sumirem quando os bitplanes são desligados
- Antes de a CG chegar ao topo da tela, há um espaço vazio entre a parte superior da tela e o ponto inicial da CG
- Se os bitplanes ficarem ligados nesse momento, lixo visual será desenhado na tela
- Nessa área, é preciso desligar os bitplanes para que o DMA não leia dados inválidos
- O problema é que, ao desligar os bitplanes, os sprites também deixam de ser desenhados
- As motion lines acabam aparecendo apenas dentro dos limites da CG
- A solução é não desligar completamente os bitplanes: mantém-se apenas 1 ativo e o ponteiro da tela é definido para dados vazios
- Algo é desenhado na tela, mas na prática nada fica visível
- Não é necessário preparar uma tela vazia inteira
- Considerando pixels de 1 bit, uma linha de 320 pixels tem 320 bits, ou 40 bytes
- Ao definir
BPLMOD1como-40, depois de cada linha o ponteiro volta 40 bytes e repete o desenho dos mesmos 40 bytes - Basta deixar zerados os primeiros 40 bytes da safety margin da tela
Resultado e pequenas tarefas que ainda restam
- No início havia dúvida se valeria a pena colocar esse tipo de CG no jogo por causa da exigência de RAM, mas depois de implementar a compressão de dados ficou claro que o overhead é bastante razoável
- Isso permitiu adicionar mais ornamentação visual ao Magicore
- Ainda restam pequenas tarefas não abordadas
- Por exemplo, evitar que a parte de baixo de uma motion line de 100 px desapareça de repente depois que ela sai pelo topo da tela
- Esse efeito não usa o blitter em nenhum momento
- Um texto sobre blitter está em Getting clever with the Amiga blitter
- O Amiga continua sendo uma plataforma capaz de impressionar as pessoas com sua exibição de gráficos coloridos hoje, assim como impressionava no fim dos anos 1980
1 comentários
Comentários do Hacker News
Entendo exatamente o que quer dizer “Racing the beam”. Antigamente, a gente mudava a cor do feixe no início e no fim de uma rotina sincronizada com vsync para calcular quantas scanlines de tempo de CPU podíamos usar por frame
Lembro que o endereço usado para isso era $dff180. Era a paleta de cores 0, então sempre aparecia também nas bordas da tela fora da área do bitmap
Aprendi esse truque todo no boca a boca, sem internet, e nem sabia que hoje ainda havia gente tentando extrair mais daquele chipset
A demoscene hoje ficou absurdamente boa desde mais ou menos 2017, e há produções de que gosto rodando em um Amiga 500 básico com apenas memória no trapdoor
https://www.youtube.com/watch?v=2jciCr8zEhw
https://www.youtube.com/watch?v=iD9xk3SDSYc
https://www.youtube.com/watch?v=pYtleuGV7ok
https://www.youtube.com/watch?v=E0OzX7plbeY
https://www.youtube.com/watch?v=rIV4AhfugIs
Tenho muita curiosidade sobre que tipo de gente consegue arranjar tempo para criar jogos no Amiga. Imagino que os mais jovens não se interessem por computadores tão antigos, e que quem cresceu usando isso esteja ocupado com família e trabalho
Mesmo que não estejam ocupados, há tantos projetos igualmente divertidos e capazes de manter uma pegada moderna. Ainda assim, é muito legal
Hoje trabalho em tempo integral como desenvolvedor indie de jogos. Fazer um jogo para Amiga era quase um sonho de vida, e agora acho que tenho as habilidades para realizá-lo
Quero mostrar que, usando as ferramentas atuais e o conhecimento amplamente disponível, é possível dar nova vida a um hardware clássico querido com uma experiência de jogo baseada em princípios modernos de design
Se você relaciona tudo na vida à carreira, a vida inteira vira trabalho
É parecido com perguntar por que praticar pintura a óleo se existe Photoshop, ou por que restaurar carros antigos se existe Tesla
A modificação de troca de região é bem complexa, porque é preciso alternar entre dois VIC-II e dois osciladores. Também tenho um MSX2; não usei muito, mas ele tem muito charme
Arranjar tempo para realmente escrever código para essas máquinas é difícil, mas, como na maioria dos hobbies de quem trabalha, é uma questão de dedicar noites e fins de semana quando a inspiração aparece
Retrocomputação é um hobby excelente, fascinante e gratificante. Minha maior queixa, porém, nem é o tempo, mas o preço e a dificuldade de conseguir peças
É uma pena ver que, no mercado de computadores, parece haver cada vez mais gente tentando vender caro qualquer coisa que receba o rótulo de “antigo” ou “vintage”
Sobre o pessoal mais velho, é difícil falar por eles, mas parece que alguns dos que ainda fazem demos para Commodore 64 têm uma vontade forte de se reconectar com a infância
Há obras que quase contam isso diretamente, como a demo relativamente recente “Mojo”, da Bonzai e da Pretzel Logic. Tentar fazer uma narrativa “séria” em uma produção da demoscene é meio constrangedor, mas ainda assim é caloroso e simpático
É um hobby que consome muito tempo, mas, se você realmente quer arranjar tempo, acaba encontrando um jeito
[1]: https://csdb.dk/release/?id=232966, https://www.youtube.com/watch?v=HXi3oJ9huiI
[1] https://retro.moe/2024/02/04/bluepad32-v4-0/
[2] https://www.youtube.com/watch?v=Nj5fZlt_834
https://www.udemy.com/course/programming-games-for-the-atari...
Achei que trabalhar de casa me daria mais tempo livre, mas não foi bem assim. Ainda assim, um dia preciso continuar mexendo nisso
Sempre me perguntei como seriam jogos no estilo dos consoles japoneses no Amiga, e se o Amiga realmente não tinha desempenho suficiente ou se o design da maioria dos jogos simplesmente não era do meu gosto
Bonk foi muito bem portado pela Factor 5, mas eles eram praticamente magos
A parte que diz “um Amiga 500 comum tem 512 KB de Chip RAM e 512 KB de RAM de expansão” é um pouco imprecisa. O A500 básico tinha apenas 512 KB de Chip RAM
Muitos usuários adicionavam a expansão de RAM A501, acrescentando 512 KB de Fast RAM que o hardware gráfico não podia acessar diretamente
Embora fosse chamada de Fast RAM, por causa da arquitetura da expansão ela era mais lenta que a Fast RAM de verdade
A maioria dos donos de A500 tinha a expansão de 512 KB no trapdoor. Muitos softwares, incluindo jogos como Monkey Island, não rodavam sem 1 MB de RAM no total
Hoje há muitas expansões baratas de trapdoor baseadas em projetos de hardware aberto, oferecendo 1,5 MB de Slow RAM, 512 KB de Chip RAM para chegar a 1 MB total, e até RTC
Há algo incrivelmente atraente em programar dentro dessas limitações
Que bom ver o IE. É legal vê-lo explorando o Amiga
Tenho a impressão de que muita gente brincou com um Amiga diferente do que eu tive. Havia, sem dúvida, jogos com visual bonito, mas o Nintendo NES também tinha, e não olho para nenhum dos dois com tanta ternura
Ainda assim, é muito legal mostrar como uma animação dessas foi feita
O Amiga era realmente um sistema com tudo dentro. Tinha uma CPU avançada de 32 bits, aceleração gráfica, áudio excelente e literalmente 256 vezes mais RAM que o NES
Nem o SNES chegou perto; só na época do Sega Saturn vi uma máquina superar o Amiga
https://www.youtube.com/watch?v=4SB20aFHc08