Como foram programados os jogos baseados em cartuchos? [fechadas]


44

Estou pensando em como o SNES, N64, Atari ... até o DS hoje, suponho.

Os jogos SNES não costumavam ocupar mais de 4 MB de espaço, e os jogos N64 geralmente possuíam 32 a 64 MB de dados.

Hoje em dia, você mal consegue compilar um "olá mundo!" programa sem a compilação resultante gerando 1,21 gigabytes !! De dados. (Brincadeiras à parte, os arquivos hoje ocupam muito espaço em comparação com algumas das tecnologias da época).

Então como eles fizeram?

  • Em que eles programaram esses jogos? ASM? A coisa toda no ASM ?!
  • Como os gráficos foram criados? Que tecnologia eles tinham para criar folhas de sprite e, em alguns casos (como o N64), modelos 3D?
  • Como eles se encaixam em tantos níveis, personagens, missões e itens nesses cartuchos? Quero dizer, Super Mario World no SNES tem cerca de 1 MB e tem 96 saídas! Ocarina of Time, Banjo-Kazooie, DK64 e alguns outros jogos ocupam menos de 64 MB e tinham mundos enormes, toneladas de conteúdo e modelos 3D!

Desculpe se minhas perguntas parecem um pouco exageradas, estou surpreso que muitos títulos excelentes tenham conseguido se encaixar em um espaço de armazenamento tão pequeno.

É fascinante para mim, porque mesmo os arquivos e jogos mais pequenos e triviais conseguem ocupar pelo menos alguns MB, imaginando que níveis enormes como os do GoldenEye 007 conseguiram quase nenhum dado são alucinantes.


1
Além disso, em relação à duplicação, sei que as pessoas apontarão: estou mais interessado em como os dados reais foram colocados nos jogos e em como foram criados níveis enormes, mantendo um tamanho pequeno de arquivo - não tanto no processo de desenvolvimento e nas ferramentas utilizadas.
Corey


1
O NES (consulte Metroid Source no MDB) e o SNES (o código fonte de alguns jogos aleatórios de terceiros estão disponíveis na web) usavam o ASM, N64 (a tela de depuração do Zelda: MM exibe o nome do arquivo nas informações da falha) usado C.
Ivo Wetzel

A programação de jogos era muito expansiva nos dias de 8 bits. Por exemplo, fazer Pacman custar uma fortuna quando poderia ser feito hoje de forma bastante barata. As razões são que as restrições de hardware eram mais limitantes do que são hoje em mil vezes (ou mais). Isso significava que você tinha que confiar no código do assembler para esses jogos de 8 bits. A razão pela qual os jogos hoje são tão grandes não é que eles precisam ser. É principalmente que eles podem ser. Você pode ler sobre a lei de Wirth.
wolfdawn

Sim, jogos de 8 bits costumavam ser escritos em Assembly. Os jogos de SMS foram feitos com um Z80 em mente, isso é bem conhecido. Ao escrever no Assembly, você ainda pode criar bibliotecas úteis. Não vejo como manter o código compacto seja relevante para o desenvolvimento de jogos atualmente. Parece alguém perguntando como alimentar e cuidar de cavalos em um fórum de carros modernos. Se você escrever instruções binárias nativas, em uma máquina com uma finalidade, é claro que você pode e provavelmente manterá o código compacto. Quão inchado pode ser quando você precisa que seu código seja executado em alguns megahertz. :) #
13911 wolfdawn #

Respostas:


25

São os recursos de arte e áudio que ocupam espaço; a escolha da linguagem de programação era mais para tirar o máximo proveito do hardware.

Usando o N64 como exemplo, a maioria dos jogos de terceiros era de 8, 12 ou 16Mb. Os jogos de 32 e 64Mb eram principalmente da Nintendo, pois era muito caro transportar carrinhos tão grandes para todo mundo. Isso parece minúsculo, mas também os recursos artísticos e a saída visual final. Você deve se lembrar que a maioria dos jogos N64 renderizados em 320x240 não são os 1280x760 ou mais hoje. Com uma resolução de saída tão pequena, as texturas e sprites eram muito menores do que são hoje.

Por causa do pequeno cache de textura no N64, a maioria das texturas tinha 32x64 pixels com uma paleta de 4/8 bits (também conhecida como 16/256 cores). Detalhes de cores extras costumavam ser feitos misturando texturas e cores de vértices. Os jogos de banjo são um bom exemplo disso.

Hoje, um único rock em um jogo de motor Unreal terá vários 512x512x24bpp ou mesmo 32bpp. Além disso, em vez de apenas uma textura difusa, agora você tem mapas normais, máscaras especulares, máscaras de reflexão, mapas de cubo de reflexão e muito mais. Portanto, um objeto que costumava ter 4Kb de texturas agora é coberto em vários MB de dados.

Jogos antigos também têm uma quantidade enorme de reutilização de arte. Os arbustos em Super Mario Bros. são os mesmos sprites que as nuvens, as colinas são as mesmas que os cogumelos. Caracteres diferentes são apenas versões com cores alteradas dos mesmos recursos artísticos. Tudo isso teve mais uso de cada textura ou sprite que estava no carrinho.

O áudio é outra grande diferença para os jogos modernos. Quase tudo nos velhos tempos era feito com faixas seqüenciadas. Agora, ambas as faixas de música, efeitos de voz e som são armazenados em vários formatos de áudio compactados. Embora certamente menores que os dados não compactados, eles ainda são significativamente maiores que seus equivalentes sequenciados.


8
Ah, os mario arbustos / árvores incestam com uma explicação lógica! Excelente.
Kzqai 9/10/10

10
Vale ressaltar que os carros eram geralmente dimensionados em mega bits , não em mega bytes . Esses carrinhos de 64Mb tinham apenas 8MB.
traço-tom-bang

3
A saída não era 320 x 240 no N64. Os detalhes estão incorretos. A maioria dos jogos provavelmente estava usando 256 × 224. Veja aqui
wolfdawn 14/03

13

Quanto ao NES (e SNES também principalmente), aqui está uma visão geral básica. Eu não escrevi nenhum jogo NES, mas escrevi um emulador NES (Graybox) e fiz uma boa quantidade de engenharia de revisão de carros antigos.

Quanto à linguagem de programação: sim, era tudo montagem. Programar o NES significava trabalhar diretamente com interrupções de hardware, portas DMA, comutação de bancos etc. Felizmente, programar o 6502 (ou melhor, o 2A03) é bastante fácil [1]:

  • Existem poucos registros: A, X e Y principalmente, sendo os dois últimos utilizáveis ​​apenas para indexação e iteração
  • o conjunto de instruções é pequeno e principalmente direto
  • pouca memória: a RAM principal é de 2 KB, com uma extensão opcional de 8 KB suportada por bateria. Desses 2 KB, 256 bytes são reservados para a pilha e a página 0 (os primeiros 256 bytes) foi onde você deseja armazenar seus ponteiros e valores mais usados ​​devido a alguns modos de endereçamento especiais

Essas três coisas juntas criam um ambiente fácil de memorizar enquanto você trabalha com ele. Sim, você mesmo gerencia toda a memória, mas isso significava essencialmente que você cria um mapa completo de onde tudo vai adiante e esse mapa não é muito grande, porque você só precisa se preocupar com 2K, para que possa traçar isso em um pedaço de papel gráfico. Você precisava planejar um pouco mais e atribuir variáveis ​​e constantes estaticamente aos locais de RAM e ROM (no cartucho).

Fica um pouco mais complicado quando os dados do seu cartucho ultrapassam os limites endereçáveis ​​da CPU. São 64 KB, dos quais os 32 KB inferiores são definidos em pedra e mapeados para todos os tipos de portas de hardware e RAM. É aqui que a troca de banco entra em ação, o que significa mapear uma seção da ROM para (parte do) espaço de endereço de 32 KB mais alto.

Isso pode ser usado da maneira que o programador desejar, mas um exemplo de uso pode estar em um jogo com 3 níveis, com todos os dados de nível, metadados e código de cada nível, amontoados em áreas de 8KB de memória separadas no cartucho. O nível pode ter retornos de chamada para, por exemplo, inicialização, atualização por quadro, etc. "Carregando" o nível significaria mapear esse pedaço de 8 KB de memória em, por exemplo, 0xC000. Em seguida, você pode especificar que a rotina init esteja sempre em 0xC000, a rotina de atualização de quadros esteja em 0xC200 e os dados de nível iniciem em 0xC800. O código principal do jogo, alojado em outro pedaço de memória, controla as alterações de nível simplesmente trocando o pedaço direito e saltando para os endereços absolutos 0xC000 e 0xC200 nos horários apropriados.

Dados gráficos errados: os dados dos blocos do NES são mapas de 2 bits e 8x8 pixels. Para o segundo plano, eles são combinados com uma camada de 2 bits e 1/4 de resolução. Esses valores de 4 bits foram então indexados em uma paleta de 16 entradas, e acredito que 53 cores exclusivas efetivas estejam disponíveis. Os sprites também usaram os dados de pixel de 2 bits e cada sprite especificou seu próprio índice de grupo de 2 bits, formando novamente um índice pal de 4 bits. A imagem BG na tela é uma matriz de 32x30 de números de índice de bloco.

Essencialmente, com uma tonelada de repetição e índices em índices, você pode manter os dados muito pequenos. Os dados de nível geralmente eram armazenados como barras verticais de índices de bloco e, como essas barras verticais também eram reutilizadas, elas também eram indexadas e armazenadas apenas uma vez no cartucho. Técnicas simples de compactação de dados funcionam de maneira semelhante. Isso permitiu que o Mario 1 tivesse 32 KB de dados (com espaço de sobra) e 8 KB de dados de bitmap.

Quanto aos ambientes de desenvolvimento, vi algumas fotos em que as pessoas trabalhavam em computadores antigos comprovadamente conectados a gravadores EEPROM para o trabalho. A depuração assistida por ferramentas não era realmente uma possibilidade até depois da idade do SNES [2]. Esta é a principal razão pela qual muitos jogos antigos possuem bugs "óbvios" e por que coisas como Gameshark podem fazer o que fazem; a saúde do jogador sempre estaria no local X da memória, para que você possa forçar 100 a qualquer momento.

Se você achar essas coisas interessantes, encorajo você a consultar, por exemplo, http://wiki.nesdev.com/w/index.php/Nesdev_Wiki. Existem muitos cursos de programação para o NES também online.

Espero que essa visão simplificada tenha dado algumas dicas sobre o desenvolvimento de jogos da era dos anos 80.

[1] Relativamente falando. Também sou tendencioso quando escrevi o Graybox em cerca de 85% do conjunto PowerPC. [2] Veja a elaboração do artigo FF6: http://www.edge-online.com/features/the-making-of-final-fantasy-vi/


3

Existem muitos subtópicos em quase todas as perguntas que você está fazendo. A otimização é um campo enorme por si só e há muitas coisas para explorar.

Se você está interessado nesse tipo de otimização, uma das coisas que você pode explorar é a demonstração . O demosceno e algumas de suas culturas artísticas relacionadas há muito tempo mantêm um sentimento de admiração ao tentar criar arte complexa para computadores que ocupa o mínimo de espaço possível. Muitos deles terão informações sobre como eles fizeram alguns ou todos os seus "truques".

Freqüentemente há uma mistura artística de bom senso, embora haja "truques" e "hacks" específicos para um jogo ou gênero. Freqüentemente, há um pouco de "sorte" envolvida, e uma equipe que conhece os limites para os quais trabalha (talvez discorde continuamente com esses limites ao longo do processo), conhece suas vantagens e desvantagens e está disposta a fazer parte do comércio necessário -offs e sacrifícios para atingir seus limites.

Aqui estão algumas das coisas que posso pensar que podem ajudar uma equipe a obter um jogo para tamanhos menores:

  • Reutilize o que você pode: reutilizar os mesmos sprites e as variações que você pode facilmente fazer a partir de uma única imagem de sprite (como reflexos, rotações, mudanças de paleta) economizarão espaço. O mesmo vale para código, música e quase tudo o mais em um jogo.
  • Comprima o que puder: existem vários esquemas de compactação por aí e saber quais usar pode ser uma enorme economia de espaço. Às vezes, mesmo os esquemas de compactação simples, como a codificação de execução, podem fazer uma diferença surpreendente. Não apenas isso, mas existem esquemas de compactação (e formatos alternativos que não são exatamente compactação) para tipos de arquivos individuais, geralmente com compensações de qualidade. Por exemplo, arquivos de áudio wave / CD podem ser compactados, com alguma perda marginal de informações, em arquivos MP3. Além disso, formatos de arquivo como MIDI e MOD baseado em sampler são formatos alternativos que ocupam muito menos espaço, mas codificam a música de maneira totalmente diferente e exigem habilidades diferentes para fazê-las soar bem.
  • Perca o que você não precisa: você pode fazer isso mais barato? Por exemplo, você ainda pode transmitir a "personalidade" de um personagem em menos pixels (ou polígonos)? O posicionamento dos blocos precisa ser exatamente definido por um designer ou eles podem ser gerados aleatoriamente no código do seu programa?
  • O código geralmente é mais barato: embora você tenha feito uma piada sobre quanto espaço um código compila normalmente leva agora idéias (e há razões pelas quais essa 'plataforma' aumentou ao longo dos anos e maneiras de reduzi-lo quando você absolutamente precisa), mas, geralmente, se você puder executar algo de forma algorítmica / processual / no código facilmente, essa abordagem também será mais fácil de ajustar e reutilizar para outros recursos semelhantes, mas diferentes. Os fractais são um exemplo particularmente fácil de ver: você pode ter uma imagem de um fractal complexo que ocupa muito espaço em comparação com a fórmula matemática que o gera. Além disso, a fórmula matemática pode ter parâmetros que podem gerar imagens semelhantes, mas às vezes surpreendentemente diferentes.

De qualquer forma, para um conjunto tão grande e carregado de perguntas, espero que alguns dos tópicos acima sejam bons pontos de partida para você aprender mais.


Além disso, use tecnologia que use menos espaço.
Speeder

3
(desculpe, digite o problema novamente ... existe uma maneira de desativá-lo? Eu odeio isso toda vez que pressiono digitar o comentário enviado).
Speeder

Outro entra: / De qualquer forma, use tecnologia que use menos espaço, como mapas procedurais (Noctis tem uma galáxia inteira com vários milhões de sistemas solares, com planetas que você pode pousar e ver vida, árvores, ruínas, edifícios ... em menos de 3MB ), música de módulo (música em formatos como .mod, .xm, .it ...), texturas procedurais (consulte werkkzeug, mapzone e alguns outros softwares), efeitos sonoros procedimentais (quase todos os efeitos sonoros são possíveis em matemática) equações ou manipulação de ondas sonoras básicas) e assim por diante.
speeder

@speeder é fácil clicar em 'editar' ou 'delete' em comentários acidentais ...
traço-tom-bang

Re: "Comprimir o que puder", no hardware antigo que você normalmente comprimiria para o que o hardware pudesse suportar. Você nunca comprimiria áudio para MP3, porque o hardware de áudio não o tratava nativamente e não gostaria de perder tempo descompactando-o na CPU quando pudesse apenas transmiti-lo diretamente da mídia para o hardware de áudio. O MIDI foi ótimo, porque todo mundo tinha (e tem) um sintetizador de ondas a bordo; basta carregar suas amostras e pronto.
Dash-tom-bang

0

Uma coisa é que não tenho certeza se ele ainda está na era pós-N64, mas o SNES e o N64 frequentemente reutilizam texturas em outros objetos 3D, o que geralmente economiza espaço considerável e arte pré-renderizada, pois os fundos geralmente são falsos. Outro truque era criar uma névoa de fundo na borda que seria usada.

O San Francisco Rush N64 sempre teve um pouco de neblina, embora as configurações pudessem mudar a densidade onde o fliperama do San Francisco Rush não possuía e você podia ver a ponte Golden Gate na pista 1 em comparação com a versão N64.

Além disso, os jogos frequentemente reutilizam músicas como Zelda Ocarina of Time reutilizam muito as músicas, o que eu acho irritante, pois poderia ter sido feito um trabalho melhor, como a forma como o Banjo Kazooie / DK64 costumava ter temas dentro dos temas!

Zelda Ocarina, na época, poderia ter o Hyrule Overworld e, em seguida, uma versão subaquática do tema, se você for subaquático ou fizer com que os instrumentos no Shop Theme reflitam a área externa onde flautas e violinos seriam usados ​​para a loja da floresta Kokiri e buzinas e trompetes para a loja Hyrule Castle Town e bateria na vila Goron.etc

Nos módulos 3D do PC são compilados em bibliotecas para acessá-los rapidamente usando um programa para descompactá-lo, mas não tenho certeza se esse é o caso da Nintendo, que é baseada em ROM. PCs são RAM como entrar em uma sala bagunçada em que as coisas nem sempre ficam onde deveriam e as informações podem ser substituídas a ponto de o computador nem sequer iniciar!

Os consoles de jogos são ROM, onde tudo é armazenado em um espaço alocado; assim, toda vez que você liga o jogo, ele procura os arquivos nesse espaço alocado com garantia de que ele permanecerá lá.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.