NES Elite - código-fonte documentado de Elite para NES
(github.com/markmoxon)- Código-fonte de Elite para NES, de Ian Bell e David Braben, com documentação em todas as linhas e explicações na maior parte delas, reconstruído manualmente a partir do disassembly do binário original do jogo
- É possível gerar uma imagem ROM iNES que compila um jogo totalmente funcional a partir do código-fonte em computadores modernos e pode ser carregada em um NES real ou em emuladores
- As variantes com suporte são a variante PAL da Imagineer e a variante NTSC do site pessoal de Ian Bell; a build padrão é a variante PAL
- As formas de explorar o código-fonte incluem visualizá-lo em um formato legível por humanos em elite.bbcelite.com ou abrir o código comentado em uma IDE; o conteúdo do site e dos arquivos-fonte é o mesmo
- Os requisitos de build são BeebAsm, Python e
makeno Mac/Linux; a build em Python foi testada apenas na versão 3.x, e o Windows incluimake.exe- No Windows, a build é feita com
make.bat; no Mac/Linux, commake; a saída padrão éelite-pal.NESna pasta5-compiled-rom-images - É possível gerar
elite-ntsc.NEScomvariant=ntsc
- No Windows, a build é feita com
- As opções de build controlam seleção de variante, uso de um commander de teste próximo do máximo, omissão da correspondência com o binário original, desativação da verificação crc32 e outros ajustes
- Um exemplo representativo é
make variant=ntsc commander=max match=no verify=no crc32.pycompara lado a lado os checksums e os tamanhos de arquivo dos arquivos gerados e dos arquivos de referência extraídos do código-fonte original
- Um exemplo representativo é
- As variantes PAL e NTSC diferem em aspectos como contagem de ciclos do NMI handler, o heading Imagineer/Nintendo na tela inicial, o tempo de espera do auto-play da demo de combate, o algoritmo de checksum do slot de save, o número de versão interno, a mensagem de copyright oculta, o texto de rolagem e constantes de coordenada y
- A variante NTSC não funciona em hardware NTSC real; trata-se de uma emulação NTSC com timing de NMI alterado para se adequar ao modo NTSC de alguns emuladores
- Não há arquivo de licença; aplica-se a lei de direitos autorais padrão, permitindo apenas leitura e fork, sem autorização para reprodução, distribuição ou criação de obras derivadas
1 comentários
Comentários do Hacker News
Há muito tempo, quando eu trabalhava na Frontier, ouvi de David Braben uma anedota interessante sobre NES Elite. Pelo que me lembrava, no início eles rastreavam o tempo real usando o timer de hardware do NES, para que a física avançasse de forma constante mesmo que a taxa de quadros variasse.
Ouvi dizer que, nos testes de pré-lançamento da Nintendo, algumas das primeiras unidades do NES foram reprovadas porque esse timer não funcionava direito, então Bell/Braben fizeram o jogo manter suas próprias estimativas de quantos ciclos de clock cada função havia usado naquele quadro e, no fim do quadro, somá-las para estimar o tempo decorrido.
Mas, olhando o código-fonte no GitHub, parece que eu me lembrava errado ou não entendi direito o que Braben disse. Em
elite-source-bank-7.asmhá um comentário dizendo “atualiza o timer NMI que podemos usar em vez de um timer de hardware, que o NES não oferece”, e parece que eles implementaram uma espécie de relógio de tempo real contando interrupções não mascaráveis.O die das primeiras CPUs do NES tinha vestígios de um timer de intervalo programável com bug e desativado: https://www.nesdev.org/wiki/RP2A03_Programmable_Interval_Tim...
Em revisões posteriores ele foi completamente removido, e é possível que só fosse habilitado em coisas como kits de desenvolvimento. Se o jogo dependesse de um recurso que não funcionava nos aparelhos de consumidor, faria sentido ser rejeitado nos testes da Nintendo.
Mesmo que os consoles lançados tivessem um timer de intervalo programável, ele provavelmente só seria útil para medições subframe, como efeitos de raster precisos. Para medir tempo real, a contagem de NMI faz muito mais sentido. A NMI ocorre no início de cada quadro de vídeo, é muito constante a 60,0988 Hz, e mesmo que a engine do jogo fique lenta e a taxa de quadros varie, o processamento da CPU não consegue afetar o timing do sinal de vídeo.
Como observação, o hardware de áudio também pode gerar interrupções de timer, e muitos chips de expansão têm contadores de scanline para sincronização de renderização. Não faltam formas de medir tempo no NES.
Quando tentaram obter a aprovação da Nintendo para um jogo, ouvi que ele não funcionava em uma versão específica do NES americano ou fazia o sistema superaquecer. O cronograma de lançamento estava apertado, então ele teve que voar até a sede da Nintendo para resolver, e lembro que essa versão específica tinha menos de 100 unidades em circulação.
Mais tarde encontrei anotações de um livro não publicado, e na verdade era um pouco diferente. Os testes de jogos não se limitavam à jogabilidade; era preciso testar em todas as variantes de console NES em que ele pudesse rodar. Andrew Davie, da Beam Software, relembrou que “The Three Stooges” causou problema no NES usado para testes no escritório da Nintendo em Washington, e por isso ele foi até lá pessoalmente.
Ele disse que, para o jogo ser aprovado, havia “umas 23 variações de máquina”, incluindo combinações de diferentes fabricantes de chips, e que, por falta de documentação oficial, ele fez os dados de sprites serem escritos diretamente a cada 2 segundos, em vez de gravá-los na RAM como a recomendação oficial, o que fazia o NES esquentar demais e causava piscadas de sprites durante todo o jogo. Depois da correção, o lançamento foi aprovado, e ele ouviu dizer que a combinação problemática de NES existia em apenas cerca de 5 unidades em todos os EUA, então foi removida da linha de testes da Nintendo.
Comecei recentemente a jogar a continuação, Elite: Dangerous, e, embora não seja isenta de problemas, é uma experiência bem impressionante.
Foi estranhamente emocionante ver elementos de jogo que vêm desde a versão de 1984. Ver as naves — e especialmente a estação Coriolis —, que naquela época eram exibidas em gráficos vetoriais em uma tela mapeada em 16K de memória de ponta para a época, transformadas em renderização 3D completa em 4K/60 fps me atingiu emocionalmente mais do que eu esperava.
Finalmente ver o interior detalhado de uma Coriolis, com outdoors, plantas e equipamentos de acoplagem, honestamente quase me deixou com os olhos marejados. Mesmo com as dificuldades atuais, este jogo é um legado precioso, e espero que continue existindo de alguma forma.
Acoplar manualmente uma nave ouvindo Blue Danube sempre foi uma experiência relaxante.
Fico me perguntando por que simuladores e jogos espaciais sempre acabam tendo tantos problemas. Elite Dangerous parece não ir a lugar nenhum, Star Citizen parece um beta eterno, e KSP2 também foi decepcionante.
Pensamentos que escrevi 9 anos atrás: https://hypertexthero.com/elite-dangerous-education/
A expansão Odyssey também é divertida, e espero que um dia adicionem caminhadas espaciais em EVA e missões em gravidade zero.
Há também Elite - The New Kind, uma versão em C quase fiel ao original: https://github.com/fesh0r/newkind
Feita por Christian Pinder: https://www.christianpinder.com/games/
A homepage de Elite do Ian Bell também vale a visita, com várias versões originais: http://www.ianbellelite.com/
O núcleo da versão de NES de 1991, ou seja, cerca de 30% da ROM de 128K, é essencialmente a versão de 1986 para BBC Master, que por sua vez é uma evolução da versão original de 1984 para BBC Micro. As versões para Commodore 64 e Apple II também vêm dessa mesma linhagem, e o desenvolvimento foi feito no BBC Micro
A maior parte do código dos bancos 0, 1 e 2 foi trazida diretamente da versão original para BBC, com mais algumas partes no banco 7. Novas rotinas de gráficos, som e controles foram colocadas na frente, mas o coração pulsante ainda é a versão Beeb
Ian Bell, autor de Elite, disse que a versão para NES era sua versão 8-bit de Elite favorita
No geral, disse que sua favorita era a conversão para o Archimedes de 32 bits
A entrevista completa está em http://www.elitehomepage.org/archive/b5081501.htm
Interpreto isso como ele dizendo que sua versão favorita é a edição em cassete para BBC Micro, e sua conversão favorita é a versão para NES. Mas talvez eu esteja interpretando com otimismo por ser fanboy do BBC
Gosto do fato de haver esse shim de troca de banco no início de cada banco
SEI/INC $C006/JMP BEGINA explicação entra em detalhes dizendo que isso é feito para economizar espaço, mas, aos meus olhos, o único motivo para o
JMPser necessário é o pipeline de instruções, e parece que um simplesNOPbastaria para fazer o flushEntão minha otimização de 2 bytes seria:
SEI/INC $FFFD ; usa o C0 dentro do vetor de instrução/NOPJMPser necessário é o pipeline de instruções” também está correto, mas também faz sentido para uma pessoa. A execução começa no banco 7, então ele está saltando para o banco 7Como observação paralela, no Game Boy o ponto de entrada fica no banco fixo, ROM0, então pelo menos nos MBCs comuns esse problema nem existe
Como comparação, há o código-fonte de Oolite, um clone open source de Elite escrito em Objective-C: https://github.com/OoliteProject/oolite
https://oolite.space
https://news.ycombinator.com/item?id=7894145
Joguei isso no C64 quando tinha 8 anos. Trinta anos depois, ainda não entendo este código
Só o banco 0 tem 18.305 linhas de assembly; nem consigo imaginar como mantinham isso tudo na cabeça
Mesmo com ferramentas de ponta, acompanhar o código devia exigir uma organização e uma disciplina enormes. Pesquisei assemblers do início dos anos 80 para Hitachi 6303[0]/Motorola 6800[1], e é impressionante o que as pessoas conseguiram fazer com essas limitações de ferramentas
Por exemplo, os dois assemblers abaixo só permitiam rótulos de até 6 caracteres, e não havia rótulos locais exclusivos para dentro de sub-rotinas. No meu trabalho, eu limitei os rótulos a 40 caracteres por legibilidade, e ainda assim era assim
Ainda assim, a relativa simplicidade dessas arquiteturas é realmente revigorante em comparação com trabalho embarcado em sistemas modernos. Conseguir manter o estado geral do sistema mais ou menos na cabeça é claramente uma vantagem
0: http://www.bitsavers.org/components/hitachi/_dataBooks/U24_H...
1: http://www.bitsavers.org/components/motorola/6800/exorciser/...
No geral, programação em assembly não é tão diferente de linguagens de alto nível. Você organiza o código em funções, blocos e assim por diante. Escrever uma parede gigantesca de código com saltos todos entrelaçados é pedir para arrumar um problema sério
É uma pena que não seja software livre. Se eu fosse o criador de Elite, teria liberado todos os ports do jogo sob uma licença livre
De qualquer forma, hoje dá para jogar Oolite em um netbook barato e se divertir tanto quanto, ou até mais, graças à enorme lista de add-ons
O lado de Braben estava desenvolvendo Elite 4/Elite: Dangerous, então parece que não queria enfraquecer o copyright
Todo código-fonte deveria ser documentado nesse nível