1 pontos por GN⁺ 2023-10-09 | 1 comentários | Compartilhar no WhatsApp
  • 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 make no Mac/Linux; a build em Python foi testada apenas na versão 3.x, e o Windows inclui make.exe
    • No Windows, a build é feita com make.bat; no Mac/Linux, com make; a saída padrão é elite-pal.NES na pasta 5-compiled-rom-images
    • É possível gerar elite-ntsc.NES com variant=ntsc
  • 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.py compara 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
  • 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

 
GN⁺ 2023-10-09
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.asm há 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.

    • Provavelmente sua memória misturou as coisas. Nenhuma revisão do NES lançada ao público teve timer de hardware.
      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.
    • Ouvi uma história parecida de Andrew Davie, da BEAM Software (Melbourne House). Ele desenvolveu Super Glove Ball e disse que, como a Nintendo quase não fornecia documentação útil, eles tiveram que usar vários hacks em partes como o cálculo da taxa de quadros.
      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.

    • Gostei muito de Elite Dangerous. Parei de jogar depois que o suporte a consoles foi encerrado, mas, apesar da repetição e do conteúdo raso, sinto falta do tempo pilotando naves com amigos.
      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.
    • Joguei Elite: Dangerous por bastante tempo desde o beta aberto. É um jogo lindo, e o design de som é fantástico.
      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/

    • Ian Bell e o site dele certamente merecem ser mencionados. É lá que se encontra o código-fonte original da versão para BBC Micro, e esses discos originais servem de base para todo o meu trabalho de anotação de Elite, incluindo o projeto de NES
      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 citação original é esta: “Tecnicamente, minhas maiores conquistas publicadas foram colocar ‘Elite’ da fita cassete do BBC, incluindo a tela, em 32K de RAM, e a conversão de ‘Elite’ para o Nintendo Entertainment System, usando uma tela mapeada por caracteres e um único controle de NES. O NES é minha conversão publicada favorita, e, até conseguirmos fazê-la, ela não era considerada tecnicamente possível.”
      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
    • Mas removeram o comércio de escravos e drogas :)
    • Arch Elite é claramente o ápice
    • A versão recente feita por fãs para Oric Atmos também é bem boa: https://www.youtube.com/watch?v=kC1cJGLGlxo
  • Gosto do fato de haver esse shim de troca de banco no início de cada banco
    SEI / INC $C006 / JMP BEGIN
    A explicação entra em detalhes dizendo que isso é feito para economizar espaço, mas, aos meus olhos, o único motivo para o JMP ser necessário é o pipeline de instruções, e parece que um simples NOP bastaria para fazer o flush
    Então minha otimização de 2 bytes seria: SEI / INC $FFFD ; usa o C0 dentro do vetor de instrução / NOP

    • Dizer que “o único motivo para o JMP ser 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 7
      Como 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

    • Na época em que se usava 6502, não era tudo mantido na cabeça; ficava guardado em pilhas de papel contínuo para impressora matricial, alimentado por trator. Normalmente também havia um monte de anotações e correções feitas a lápis
    • Fiz um pouco de desenvolvimento embarcado para máquinas de 8 bits nos tempos modernos, e tenho um respeito sincero pelos engenheiros que faziam isso nos anos 80
      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/...
    • Nós éramos melhores naquela época. Falando sério, qualquer projeto de algum porte quase inevitavelmente exigia escrever ou imprimir muito código em papel. Era preciso muito papel mesmo
    • Este código é extremamente bem organizado e bem documentado. Não sei qual era o nível de documentação do código original, mas imagino que os impressos tivessem muitas anotações manuscritas
      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
    • Do ponto de vista de um engenheiro moderno, não entendo muito bem por que seria preciso manter isso na cabeça
  • É 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

    • Isso aconteceu porque Braben foi complicado em relação a questões de copyright. Bell, por outro lado, era um cara legal e disponibilizou a maior parte do que escreveu diretamente
    • A história por trás dessa liberação remonta a décadas atrás
      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