Imagens de suporte
Uma breve introdução
À primeira vista, o NES parece ser só mais um computador 6502, com uma carcaça sofisticada e um controle.
E apesar disso ser tecnicamente verdade, deixe-me mostrar o porquê da CPU não ser a parte principal desse sistema.
Modelos e variantes
A Nintendo distribuiu vários modelos diferentes do mesmo console através do globo [1], e mesmo que todos tenham a mesma arquitetura, muitos têm visuais extremamente diferentes e alguns podem incluir acessórios embutidos. Então, para manter as coisas simples neste artigo, vou me concentrar nas duas revisões mais populares:
- O Family Computer (conhecido como Famicom) foi a primeira encarnação, lançado somente no Japão. Esse design parecido com um brinquedo possui dois controles não removídeis (dos quais o segundo controle conta com um microfone integrado), uma porta para a pistola (light gun, chamada de Zapper), saída de vídeo RF (utilizando sinal NTSC-J) e pinos extras na entrada para cartuchos, a fim de expandir as capacidades de aúdio. Esse modelo foi a base para clones populares no Brasil, como o Dynavision, Phantom System e PolyStation.
- O Nintendo Entertainment System (conhecido como NES ou informalmente Nintendinho) foi uma versão repaginada para o público da América do Norte, Europa e Oceania; com uma aparência bastante similar à de um aparelho VHS. Do ponto de vista técnico, os controles agora são removíveis (sem microfone) e o vídeo foi aprimorado com mais opções de saída (componente RCA), embora a expansão de áudio tenha sido substituída por um subsistema antipirataria. Por fim, a parte inferior do aparelho carrega uma “porta de expansão” que nunca foi utilizada, junto com pinos de cartucho extras que se comunicam com aquela porta [2].
Como o autor cresceu com o nome “NES”, esse termo será usado para se referir ao console em geral, mas trocarei para o nome “Famicom” quando me referir a capacidades únicas só encontradas na variante japonesa e seus clones.
CPU
A CPU do NES é um Ricoh 2A03 [3], que por sua vez é baseado na popular CPU 8 bits MOS Technology 6502 e roda com um clock de 1.79 MHz ( ou 1.66 MHz em sistemas PAL).
Um pouco de contexto
O mercado de CPUs no final dos anos 70 e início dos anos 80 era bastante diversificado. Se uma empresa quisesse construir um microcomputador com preços acessíveis, as seguintes opções estavam disponíveis:
- O Intel 8080: uma CPU popular em destaque no Altair, o primeiro computador “pessoal” (PC). Tem um barramento de dados de 8 bits e um barramento de endereçamento de 16 bits.
- O Zilog Z80: uma atualização “não oficial” do 8080, aprimorada com mais instruções, registradores e componentes internos. Foi vendido por um preço menor e ainda podia rodar programas escritos para o 8080 [4]. A Amstrad e a Sinclair (entre outros) escolheram esta CPU.
- O Motorola 6800: outra CPU de 8 bits projetada pela Motorola, contém um conjunto de instruções completamente diferente. Muitos kits DIY de computador, sintetizadores e computadores tudo-em-um incluíam o 6800.
Como se essas opções não fossem o suficiente, outra empresa chamada MOS apareceu no mercado e ofereceu uma versão reformulada do 6800: o 6502. Apesar de ser incompatível com código escrito para os outros, o novo chip era muito, mas muito mais barato de produzir [5] [6], e era só questão de tempo até as fabricantes de computadores mais famosas (Commodore, Apple, Atari, Acorn, entre outras) escolherem o 6502 para comandar suas máquinas.
De volta ao Japão, a Nintendo precisava de algo barato, porém familiar para desenvolverem, então eles escolheram o 6502. A Ricoh, sua fornecedora de CPUs, produziu com sucesso uma CPU compatível com o 6502.
O enigma de licenciamento da Ricoh
Como a Ricoh conseguiu clonar o 6502 não é claro até hoje. Se esperaria que a MOS tivesse licenciado o projeto do chip para Ricoh, mas há muitas contradições nisso:
- Ambas as versões da Ricoh e da MOS apresentam o mesmo layout, mas a versão da Ricoh contém barramentos cortados (desabilitando certas funções) [7]. Vou entrar em mais detalhes depois.
- Nenhum documento que afirme explicitamente que a MOS licenciou o 6502 para a Ricoh foi encontrado até agora.
- Um artigo publicado em 2008 no site Nikkei Trendy afirma que a Ricoh conseguiu a licença com a Rockwell, uma fabricante de chips autorizada [8]. Embora seja discutível se uma propriedade intelectual teria sido repassada de segunda mão a terceiros com aprovação da MOS.
- Essa não seria a primeira vez que a Nintendo conseguiu contornar direitos de propriedade intelectual, já que o caso Ikegami Tsushinki v. Nintendo no Japão determinou que a Nintendo não possuia direitos autorais sob o código da versão original de Donkey Kong [9].
Funções removidas
O Ricoh 2A03 omite o modo BCD (Binary-Coded Decimal), originalmente incluso no 6502 [10]. O modo codifica cada dígito decimal de um número como um binário de 4 bits separado. O 6502 usa “palavras” de 8 bits, o que significa que cada palavra armazena dois dígitos decimais.
Como um exemplo para os curiosos, o número decimal 42
é representado como:
0010 1010
em binário.0100 0010
em BCD.
Poderíamos continuar falando sobre o assunto, mas para resumir: BCD é útil para aplicativos que exigem tratamento de cada casa decimal separadamente (por exemplo, um relógio digital). No entanto, isso exige mais armazenamento, pois cada palavra de 8 bits só consegue representar até o número decimal 99
, enquanto o binário tradicional consegue até o 255
.
De qualquer forma, a Ricoh deliberadamente omitiu o modo BCD de seu chip cortando as linhas de controle que o ativam. Presumivelmente, isso foi feito para evitar o pagamento de royalties para a MOS, já que o BCD foi patenteado por eles (e a legislação que permite direitos autorais sobre os layouts de circuitos integrados nos Estados Unidos só seria promulgada em 1984 [11]).
Memória
Ambos os Ricoh 2A03 e MOS 6502 possuem um barramento de dados de 8 bits e um ** barramento de endereçamento de 16 bits, que lhes permite acessar até 64 KB de memória**. Então, como a Nintendo preencheu esse espaço de memória?
Por um lado, a placa-mãe contém um chip fornecendo 2 KB de RAM Estática (SRAM) [12]. A Nintendo chama esta área de “Work Ram” (WRAM) e ela pode ser usada para armazenar:
- Variáveis para controlar o estado do jogo e/ou para buscar informações.
- A “pilha” (stack), que salva temporariamente os valores de registradores enquanto a CPU está executando sub-rotinas.
- Uma “área de buffer” para que a CPU possa copiar grandes quantidades de dados entre dois locais.
Por outro lado, os componentes do sistema são mapeados na memória [13], o que significa que eles são acessados usando endereços de memória, assim, eles ocupam parte do espaço de endereçamento da CPU. O espaço de memória da CPU é preenchido com endereços apontando para o cartucho do jogo, WRAM, a PPU, a APU e dois controles (não se preocupe com cada componente, eles são explicados ao longo desse artigo).
Cartucho/dados do jogo
Caso não saiba, jogos do NES são distribuídos na forma de cartuchos e os barramentos do cartucho se conectam diretamente à CPU.
A Nintendo conectou as linhas do cartucho de uma forma que apenas 49120 Bytes (~ 49,97 KB) dos dados do cartucho podem ser acessados [14]. Agora, o que quero dizer com “dados do cartucho”? Bem, qualquer chip conectado a esses barramentos, por exemplo:
- Uma ROM de Programa onde o programa do jogo é armazenado. Isso não inclui os dados de gráficos, como você verá mais tarde na seção “Gráficos”. Naturalmente, e ao contrário dos outros chips, este é obrigatório.
- Chips de RAM para estender a WRAM.
- Um Chip de RAM com uma bateria de lítio para armazenar o progresso do jogo.
O fato de existirem diferentes combinações se deve ao fato que a CPU não se importa com o tipo de componente que está sendo lido, ela só vê os endereços de memória. Então, cabe ao desenvolvedor de jogos escolher (ou criar) um layout viável para adequar seu jogo.
Por exemplo, no “Super Mario Bros.” da Nintendo foi usado um layout chamado NES-NROM-256 que consistia em 32 KB de ROM de programa e 8 KB de “Character ROM” para gráficos (veremos mais sobre isso na seção “Gráficos”) [16]. O layout NES-NROM-256 também estava preparado para suportar até 3 KB de WRAM extra, embora o jogo não faça uso disso.
Indo além das capacidades existentes
Uma das grandes limitações dos barramentos de endereço de 16 bits (que afetam os consoles de terceira e quarta geração) é o seu espaço de endereço compacto. Hoje em dia, computadores de 32 bits podem endereçar até 4 GB de memória (e máquinas de 64 bits desfrutam generosamente de até 16 exabytes), portanto isso já não é mais motivo de preocupação. Porém, naquele tempo o NES só tinha um espaço de endereçamento de 64 KB, além de que boa parte dele era consumida por hardware mapeado em memória (algo que os competidores evitaram).
Então, quer dizer que os desenvolvedores de jogos só podiam desenvolver jogos de até 49,97 KB? Não mesmo! Se a história nos ensinou alguma coisa, é que há sempre uma solução inteligente para um problema desafiador; e este problema foi resolvido com um Mapper (Mapeador).
Um mapper é um chip extra incluído no cartucho que fica entre os chips de memória e as linhas de endereçamento do console. Seu principal trabalho é aumentar o espaço de endereçamento para que os desenvolvedores possam usufruir de chips com maior capacidade de armazenamento. Isso é feito pela troca de banco: Endereços de memória são agrupados em bancos, e o mapper fornece interruptores (controlados através de endereços de memória) para alternar entre os bancos. Apesar disso, a CPU ainda vê a mesma quantidade de memória, então é o jogo que foi programado com a presença de um mapper que fica responsável pela troca de banco. Devido ao seu custo-benefício, os mappers foram amplamente utilizados nas tecnologias dos anos 80 até o início dos anos 90.
Voltando ao NES, um exemplo famoso é o “Super Mario Bros. 3” que foi distribuído com o mapper “MMC3” (feito pela Nintendo) em seu cartucho. Para fins de comparação, o chip MMC3 fornecia até 512 KB de espaço para a ROM de programa, até 256 KB para a Character Memory e até 8 KB de WRAM adicionais [18]. Agora fica claro por que “Super Mario Bros. 3” difere significativamente de qualidade em comparação com o primeiro lançamento da série.
Em resumo, embora este console possa parecer limitado ao examinar suas características internas, a Nintendo se certificou de que ele pudesse se adaptar à medida que a tecnologia evoluía. Por outro lado, ao mesmo tempo que esta técnica ajudou a manter os custos do console baixos, ela também transferiu parte do custo para o cartucho do jogo. Portanto, a qualidade do jogo e os custos com cartuchos eram duas preocupações para os desenvolvedores de jogos ponderarem.
Gráficos
Os gráficos são gerados por um chip proprietário chamado Picture Processing Unit (PPU). Esse é um dos chips que dão ao NES uma identidade. Em outras palavras, qualquer um pode pegar uma CPU 6502 na loja de hardware, então por que o NES é diferente de, digamos, de um Apple 2 ou de um Commodore 64? Bem, o que distingue o NES de outras máquinas são os chips em volta da CPU: A PPU e a APU. Esses dois constituem, respectivamente, as capacidades gráficas e de áudio exclusivas do NES.
Dito isso, a PPU renderiza gráficos 2D chamados de sprites e backgrounds (planos de fundo), enviando o resultado para o sinal de vídeo.
Organizando o conteúdo
Para renderizar algo na tela, a PPU precisa saber quais gráficos deve desenhar, onde na tela colocá-los; e como desenhá-los (ex: qual paleta usar).
Para responder a estas perguntas, a PPU foi pré-programada com um mapa de memória diferente que procura os seguintes tipos de dados:
- Dados gráficos são lidos do cartucho do jogo, que contém um chip dedicado chamado Character Memory armazenando os desenhos em 2D (chamados tiles, ou ladrilhos), organizados em uma estrutura de dados chamada Pattern Table (Tabela de Padrões). A Character Memory pode vir na forma de “Read Only Memory” (ROM) ou “Random Access Memory” (RAM), dependendo se o jogo é composto por um conjunto imutável de gráficos ou se a CPU deve intervir, respectivamente.
- A PPU endereça até 8 KB de Character Memory, organizada em dois grupos de 4 KB cada.
- Metadados dizendo à PPU “onde” e “como” desenhar gráficos são encontrados em outras áreas:
- Uma SRAM separada de 2 KB fica localizada na placa-mãe, dedicada aos dados relacionados aos gráficos. A Nintendo chama este espaço Video RAM (VRAM) e armazena duas estruturas de dados chamadas Nametables (Tabela de Nomes).
- A PPU incorpora 256 B de DRAM para armazenar a Object Attribute Memory (Memória de Atributo de Objeto, ou OAM).
- Por último, a PPU também possui 4 B de memória para definir as paletas de cores.
Não se preocupe com a nova terminologia, o significado dessas estruturas de dados é discutido passo a passo nos parágrafos a seguir.
Construindo o quadro
Tal como com seus contemporâneos, este chip é projetado para o comportamento de uma tela CRT, popularmente conhecida como “TV de tubo”. Não existe um frame buffer: a PPU irá renderizar ao mesmo tempo que o feixe de elétrons da CRT varre a tela, construindo a imagem em tempo real.
A PPU desenha quadros com uma dimensão fixa de 256x240 píxeis [19]. Infelizmente, devido às discrepâncias entre os padrões de vídeo analógico ao redor do mundo, a imagem terá uma aparência diferente dependendo da região do aparelho (NTSC ou PAL) pelo qual é exibido. Resumindo, as televisões NTSC vão cortar as bordas superiores e inferiores para acomodar a faixa de overscan (apenas ~224 linhas de varredura são visíveis), essas bordas são consideradas “zonas de perigo” pelos desenvolvedores na hora de decidir onde colocar elementos no jogo. Por outro lado, as telas PAL não cortarão as bordas, mas mostrarão barras pretas extras para preencher o sinal mais alto (PAL usa 288 linhas de varredura).
Por trás dos panos, o quadro que a saí da PPU é composto por duas camadas diferentes. Para fins de demonstração, vamos usar Super Mario Bros. para mostrar como isso funciona:
Tiles
Para começar, a PPU usa tiles como um ingrediente básico para produzir sprites e backgrounds.
O NES define tiles como mapas básicos de 8x8 píxeis, estes são armazenados na Character memory (localizada no cartucho do jogo) e organizados em uma grande estrutura de dados chamada Tabela de Padrões [20]. Cada tile ocupa 16 B e a Tabela de Padrões contém 256 tiles [21]. Como a PPU acessa até 8 KB de Character memory, ela pode acessar até duas Tabelas de Padrões.
Dentro de um tile, cada um dos seus pixeis é codificado usando um valor de 2 bits, que faz referência a uma das quatro cores de uma paleta. Os programadores podem definir até oito paletas (quatro para o background e as outras quatro para sprites). As cores referenciadas em cada paleta apontam para uma “paleta mestra” composta de 64 cores [22], representando todas as cores que o console consegue produzir. As paletas são feitas de quatro cores, embora uma seja reservada para transparência
.
Para começar a desenhar algo na tela, os jogos preenchem um conjunto de tabelas com referências a tiles na Character memory. Cada tabela é responsável por uma camada (sprite ou background) do quadro. Então, a PPU lê destas tabelas e constrói as linhas de varredura que serão projetadas pelo canhão CRT.
Agora vou explicar como cada camada/tabela funciona e como elas diferem em termos de funcionalidade.
Camada Background
A camada de background é um mapa de 512x480 píxeis contendo tiles estáticos [23]. Você pode se lembrar que o quadro visível é muito menor, então o jogo decide qual parte da camada é selecionada para exibição. Jogos também podem mover a área visível durante o jogo; é assim que se chega ao efeito de rolagem.
Para economizar memória, grupos de quatro tiles são combinados em mapas de 16x16 pixeis chamados de blocos, nos quais todos os tiles compartilham uma paleta de cores.
As tabelas de nomes (armazenadas na VRAM) especificam quais tiles exibir na camada de background. A PPU procura por quatro tabelas de nomes de tamanho 1024 bytes, onde cada uma correspondendo a um quadrante da camada. No entanto, só 2 KB de VRAM está disponível! Como consequência, apenas duas tabelas de nomes podem ser armazenadas sem o uso de hardware adicional no cartucho. Apesar de ainda ser necessário endereçar as duas tabelas de nomes restantes em algum lugar, a maioria dos jogos apenas as aponta para onde as primeiras duas estão localizadas (o que é conhecido como espelhamento).
Embora essa arquitetura possa parecer falha à primeira vista, ela foi projetada para manter os custos baixos enquanto oferecer uma expansibilidade simples: se os jogos precisassem de um background mais amplo, mais VRAM poderia ser incluída no cartucho.
Os últimos bytes de cada tabela de nomes armazenam uma tabela de atributos de 64 bytes que especifica qual paleta de cores é atribuída a cada bloco [24].
Camada de sprites
Sprites são tiles que podem se mover pela tela. Eles também podem se sobrepor uns aos outros ou aparecer atrás do background. A imagem visível será decidida com base em seu valor de prioridade (é o mesmo conceito de “camadas” utilizados em software tradicionais de design gráfico).
A tabela de Object Attribute Memory (OAM) especifica quais tiles serão usados como sprites [25]. Além do índice do tile, cada entrada contém uma posição (x,y) e vários atributos (paleta de cores, prioridade e flags de espelhamento). Esta tabela é armazenada em uma DRAM de 256 bytes encontrada no chip PPU.
A tabela OAM pode ser preenchida pela CPU. Contudo, isso pode ser bastante lento na prática (e corre o risco de corromper o quadro se não for feito no momento certo). Como consequência, a PPU contém um pequeno componente chamado Direct Memory Access ou DMA, que pode ser programado (alterando os registrados da PPU) para buscar a tabela na WRAM. Com o DMA, é garantido que a tabela será carregada a tempo para o próximo quadro ser desenhado, mas é importante lembrar que a CPU será interrompida durante a transferência!
A PPU é limitada a oito sprites por linha de varredura e até 64 por quadro. O limite de linha de varredura pode ser excedido graças às habilidades de multiplexação da PPU. Em outras palavras, a PPU irá alternar automaticamente os sprites entre as varreduras; contudo, eles aparecerão piscando na tela.
Divisão de background
Antes de prosseguirmos, há algo que eu ainda não disse. Se você jogar Super Mario Bros, irá perceber que quando o Mario se move, a cena rola sem problemas. No entanto, você também observará que a área superior (onde fica as estatísticas) permanece estática, mesmo que ambas as partes façam parte da mesma camada de background! Então, o que acontece aqui? Bem, o jogo está alternando os valores de rolagem no meio do quadro para mostrar o mundo e as estatísticas (que residem numa parte fixa do background) simultaneamente. O NES não oferece esse recurso nativamente, mas o jogo deduz os tempos observando o estado da PPU (manifestado através de seu registro de status [26]).
Para conseguir isso, os jogos utilizam uma técnica chamada Sprite 0 Hit. Em Super Mario Bros, a PPU é instruída a renderizar um sprite fictício atrás da moeda, que é o primeiro sprite desenhado no quadro. Após a PPU desenhar este sprite, ela atualiza seu registro de status com uma flag que denota que o primeiro sprite (conhecido como sprite 0) foi desenhado. Enquanto isso, o jogo está constantemente verificando no meio do quadro se o status do sprite 0 foi marcado (ou seja, hit), se isso acontecer, o jogo passa a atualizar a propriedade de rolagem da tabela de background para movê-la para onde o Mario está.
Em geral, o Sprite 0 Hit é um procedimento muito delicado, pois é fácil errar nos tempos (a flag sprite 0 não é apagada depois de verificada, o que leva a positivos “duplicados” [27]). Além disso, como essa rotina se repete indefinidamente, pode ser bastante dispendiosa (em ciclos da CPU) para executar. Por outro lado, posteriormente, os mappers assumiram essa função com o uso de interrupções automáticas que são acionadas sempre que uma linha de varredura arbitrária é atingida [28] (uma técnica muito mais eficiente), o que melhorou significativamente as capacidades visuais de Super Mario Bros 3, por exemplo.
Resultado
Depois que o quadro é finalizado, é hora de passar para o próximo!
No entanto, a CPU não pode modificar nenhuma tabela que esteja sendo usada atualmente pela PPU, caso contrário, podem aparecer artefatos na tela. Então, quando todas as linhas de varredura são concluídas, a PPU aciona a interrupção Vertical Blank (V-Blank) na CPU. Isso notifica o jogo de que ele pode começar a atualizar as tabelas sem rasgar a imagem exibida atualmente. Nesse momento, o feixe do CRT está apontando abaixo da área visível da tela, na área de borda inferior (overscan).
Apenas alguns registros da PPU podem ser atualizados foram da janela V-Blank [29], o que explica a capacidade de rolar a camada de background no meio do quadro.
Segredos e limitações
Se você está pensando que o sistema de buffer de quadros com memória alocada para armazenar o quadro completo teria sido preferível: os cursos de RAM eram muito altos e o objetivo do console era ser acessível. Deixe-me agora mostrar por que esse projeto se mostrou muito eficiente e flexível.
Multi-rolagem
Alguns jogos exigem que o personagem principal se mova verticalmente - assim, a tabela de nomes será configurada com espelhamento horizontal. Outros jogos precisam que o personagem se mova para a esquerda e para a direita, então eles usam o espelhamento vertical.
Qualquer um dos modos de espelhamentos permite que a PPU atualize os tiles de background sem que o usuário perceba: há bastante espaço para rolar enquanto novos tiles estão sendo renderizados a uma certa distância.
E se o personagem quiser se mover diagonalmente? A PPU pode rolar em qualquer direção, mas sem VRAM extra, as bordas são forçadas a compartilhar a mesma paleta de cores (lembre-se de que os tiles são agrupados em blocos).
É por isso que alguns jogos, como Super Mario Bros. 3, mostram gráficos estranhos na borda direita da tela enquanto Mario se move (o jogo é configurado para rolagem vertical) [30]. É possível que os desenvolvedores precisassem minimizar o custo de hardware por cartucho (já que este jogo já tem um poderoso mapper instalado).
Como uma correção interessante, a PPU permite que os desenvolvedores apliquem uma máscara vertical sobre os tiles, ocultando efetivamente parte da área com defeito.
Troca de Tile
Outra especialidade de Super Mario Bros. 3 é a quantidade de gráficos que ele pode exibir.
Este jogo exibe mais tiles de background do que é estritamente permitido. Então, como ele faz isso? Se tirarmos duas capturas de tela em momentos diferentes enquanto a exibição é gerada, é possível observar que o quadro final é realmente composto de dois quadros diferentes.
Esta é outra magia do mapper MMC3. Ele não só foi usado para acessar espaço extra na ROM de Programa, também foi usado para estende o espaço do Character ROM conectando dois chips de Character ROM diferentes. Ao verificar qual parte da tela a PPU está solicitando, o mapper redireciona para um chip ou outro — permitindo assim mais tiles únicos na tela do que era originalmente suportado [31].
Comportamento curioso
Ao longo da minha pesquisa, encontrei muitos artigos interessantes que explicam comportamentos incomuns da PPU, então pensei em mencionar alguns aqui:
- Ao contrário do VDP do Master System, que gera cores RGB que são posteriormente codificadas em sinais NTSC/PAL para transmissão, a PPU do NES faz tudo de uma vez [32]. Portanto, não há uma conexão um-a-um entre as cores da paleta mestra da PPU e o espaço de cores RGB padrão (amplamente adotado pela tecnologia atual). Isso deixa algum espaço para interpretação e, como consequência, vários emuladores exibirão uma paleta diferente.
- As discrepâncias entre paletas RGB são mais evidentes com o kit DIY de Tim Worthington, que adiciona saída de sinal RGB ao NES, pois ele também implementa uma interruptor que escolhe entre três paletas pré-definidas [33].
- A paleta mestra contém uma cor “amaldiçoada” (
$0D
) que pode bagunçar o sinal de TV NTSC [34]. Bem, o que acontece é que a TV confunde o sinal ao exibir essa cor com o sinal de supressão, então pode ocorrer cintilação. - A PPU depende da DRAM para armazenar sua Object Attribute Memory (OAM). A DRAM exige atualizações constantes para evitar a perda de dados (ao contrário do SRAM), entretanto a PPU não atualiza o DRAM quando não está renderizando o quadro [35]. Isso se manifesta durante a sincronização vertical. Por esse motivo, é recomendado não atualizar a OAM fora da sincronização vertical, pois o período de não-atualização que ocorre durante o V-blank pode corromper parte da tabela.
- A variante da PPU para sistemas PAL não são afetadas por isso, pois atualiza durante a V-Blank (que dura mais nos sistemas PAL).
Áudio
Um componente dedicado chamado Audio Processing Unit (Unidade de Processamento de Áudio, ou APU) fornece esse serviço [36]. A Ricoh a embutiu dentro do chip da CPU, presumivelmente para evitar a clonagem não autorizada tanto da CPU quanto da APU.
Funcionalidade
Este circuito de áudio é comumente referido como um Programmable Sound Generator (Gerador de Som Programável, ou PSG), o que implica vagamente que ele pode produzir apenas um conjunto predefinido de formas de onda, e nesse caso é em grande parte verdade. A APU sequencia dados de áudio em cinco canais de áudio — cada um reservado para uma forma de onda ou sinal específico. Cada canal contém diferentes propriedades que alteram o tom da forma de onda, o som, o volume e/ou duração. Eles são continuamente mixados e enviados através do sinal de saída de áudio.
A funcionalidade da APU é exposta através dos endereços de memória, a CPU lê os dados relacionados à música encontrados na ROM de programa e programa a APU de acordo.
Indo além, o modelo Famicom em particular fornece pinos de cartucho que enviam o sinal de áudio mixado para o cartucho, assim o cartucho pode mixar o som com canais extras (que exigem chips adicionais) [37].
Vamos agora analisar os cinco canais fornecidos pela APU [38]:
Pulso
Os primeiros dois canais produzem ondas de pulso [39]. Quando ouvidas, apresentam um som de beep muito distinto que é principalmente usado para melodias ou efeitos sonoros. O sequenciador respectivo pode gerar três tipos de ondas de pulso, feitas variando a duração do pulso (também conhecido como duty cycle, ou razão cíclica). Os circuitos também estão conectados a uma unidade de sweep (permitindo modular o tom) e a um gerador de envelope para alterar o volume ao longo do tempo (também conhecido como decaimento).
A maioria dos jogos usa um canal de pulso para a melodia e outro para o acompanhamento. Você pode notar que frequentemente quando um jogo precisa reproduzir um efeito sonoro, o canal de acompanhamento é alterado para reproduzir o efeito e depois retorna ao acompanhamento. Isso evita interromper a melodia durante o jogo.
Acredito ser justo dizer que as ondas de pulso são um dos emblemas desta geração de consoles. Presumo que sua adoção foi feita puramente por motivos de custo-benefício: uma CPU (limitada) pode processar apenas uma certa quantidade de dados por vez, e as ondas de pulso são ideais no sentido de que não exigem muitos parâmetros para tocar melodias simples (o que, por sua vez, libera ciclos da CPU para outras operações).
Triângulo
Uma das especialidades da APU, quando comparada à concorrência, é a capacidade de produzir ondas triangulares. Estas são frequentemente usadas como uma linha de baixo para a melodia. Além disso, modificando drasticamente o seu tom, é possível utilizá-las também para percussão.
A APU tem um canal reservado para este tipo de onda. Nos bastidores, um sequenciador dedicado leva 32 ciclos para gerar um sinal triangular [40], esta limitação faz com que a forma de onda resultante tenha a forma de uma escada.
Por outro lado, o respectivo circuito não fornece controle de volume. De qualquer forma, alguns jogos encontraram outras formas, mexendo com o controle de volume do mixer.
Ruído
O conceito de “ruído” é atribuído a uma série de formas de onda que não seguem um padrão ou ordem. Por sua vez, nossos ouvidos o interpretam como estática branca. Dito isto, a APU aloca um canal que pode reproduzir diferentes tipos de ruído.
Nos bastidores, o gerador de ruído se baseia no gerador de envelope (similar ao canal de pulso), sendo aleatoriamente silenciado por uma porta OR [41]. A condição para o silenciamento depende do valor de um registrador de deslocamento de 15 bits conectado ao circuito de retroalimentação. Isso faz com que a saída do circuito gere um sinal com padrões pseudo-imprevisíveis, e portanto ruído.
Em termos de controle, 4 bits alteram o período do gerador de envelope e um bit altera o “modo” do registrador de deslocamento. Isso deixa disponíveis 32 predefinições de ruídos. Metade (16) dessas predefinições produzem estática limpa e a outra metade, estática robótica.
Em geral, os jogos usam o canal de ruído para percussão ou efeitos ambientais.
Amostra
Amostras são pedaços gravados de música que podem ser reproduzidos. Como você pode ver, as amostras não se limitam a uma única forma de onda, mas consomem muito mais espaço.
A APU possui um canal dedicado a amostras. Nesse canal, as amostras são limitadas a uma resolução de 7 bits (codificadas com valores de 0
a 127
) e uma taxa de amostragem de ~15,74 kHz [42]. Para programar esse canal, os jogos podem transmitir valores de 7 bits (o que consome muitos ciclos e espaço de armazenamento) ou usar modulação delta para codificar apenas a variação entre a próxima amostra e a anterior.
A implementação da modulação delta na APU só recebe valores de 1 bit, o que significa que os jogos só podem informar se a amostra aumenta ou diminui 1
a cada vez que o contador é acionado. Assim, em detrimento da fidelidade, a modulação delta pode poupar os jogos de ter que transmitir valores contínuos para a APU.
Como a programação desse canal requer mais espaço e ciclos de CPU, os jogos normalmente armazenam pequenas amostras (como sons de bateria) que podem ser reproduzidas repetidamente. De qualquer forma, ao longo da vida útil do NES, inúmeros desenvolvedores criaram usos inteligentes para esse canal.
Segredos e limitações
Enquanto a APU não era comparável à qualidade do vinil, cassete ou CD, os programadores encontraram maneiras de expandir sua capacidade, principalmente graças à arquitetura modular do NES.
Canais extras
Lembra que o Famicom fornecia pinos de cartucho exclusivos disponíveis para expansão de som? Bem, jogos como Castlevania 3 aproveitaram isso e incluíram um chip extra chamado Konami VRC6, que adicionou duas ondas de pulso extras e uma onda de dente de serra à mistura.
Dê uma olhada nos dois exemplos que mostram a diferença entre a versão japonesa e a americana do jogo (esta última roda na variante do NES, que não forneceu recursos de expansão de som).
Tremolo
Em vez de aumentar o custo dos cartuchos, alguns jogos priorizaram a criatividade em vez da tecnologia para adicionar mais canais.
Neste exemplo, Final Fantasy III teve a ideia de usar efeitos de tremolo para dar a sensação de canais extras.
Uma observação mais refinada
Agora que você teve uma visão do que a APU é capaz, deixe-me mostrar um método alternativo para observar como o seu som se comporta. Isso não apenas complementará o que já foi falado sobre a APU, como também fornecerá uma análise mais objetiva, especialmente porque não depende mais dos seus ouvidos.
Antes de tudo, vamos começar com uma breve introdução à teoria do som.
Graças aos princípios da Análise de Fourier, podemos decompor todo o som que ouvimos em uma soma de ondas senoidais de diferentes frequências e amplitudes [43]. A onda senoidal mais grave (na frequência mais baixa) é chamada de fundamental e as demais são chamadas de sobretons. Se você adicionar a onda fundamental e seus sobretons, você recupera o som original. Dito isso, com os sons que têm um tom reconhecível, você notará que a maioria (se não todos) os sobretons têm frequências que são múltiplos da frequência fundamental. Assim, esses sobretons são chamados de harmônicos [44].
Harmônicos se tornarão um tópico recorrente nesta seção, pois formas de onda como pulsos, triângulos e dentes de serra seguem uma fórmula que dita os harmônicos que elas contêm. Caso contrário, essas formas de onda podem se desviar de sua forma “perfeita”.
Introdução aos espectrogramas
Como as ondas senoidais são agora o ingrediente-chave que pode compor qualquer som, podemos analisar os sons que ouvimos pelas suas ondas senoidais. Agora, para qualquer tipo de análise de dados, nada é mais conveniente do que plotar um gráfico para organizar grandes quantidades de informação. Bem, em caso de análise sonora, temos os Espectogramas. Eles codificam todas as informações de uma amostra de áudio em um único gráfico. O eixo X denota o tempo (em segundos), o eixo Y denota as frequências (em Hz) das ondas senoidais produzidas durante esse tempo e o eixo Z (brilho da cor de cada ponto) denota a potência/sonoridade (em decibéis) de cada frequência.
Como você pode observar neste exemplo, cada linha horizontal (também conhecida como sequência de pontos) corresponde a uma onda senoidal (a mais baixa é a fundamental, enquanto as demais são os harmônicos) e o brilho indica a amplitude. Com isso em mente, podemos extrair as seguintes informações:
- Com o tempo, as linhas horizontais tendem a se deslocar drasticamente. Isso é a mudança de tom do canal de pulso.
- O início de cada nota é alto (os pontos são brilhantes) seguido de um rápido declínio. Isso é o controle de envelope da APU em ação.
- Além disso, no final do período de decaimento, aparece uma linha vertical brilhante. É bastante breve, então não é facilmente audível, mas, em todo caso, é ruído (um som curto de estalo) e eu suspeito que seja uma deficiência da APU.
- Segurar uma nota por mais de 0,25 segundos faz surgir vibrato (flutuações contínuas no eixo Y). Não tenho certeza se isso é intencional (usando a função de varredura) ou um efeito adverso da APU.
Observe como a maioria dessas observações não são facilmente derivadas apenas ouvindo um simples áudio, por esta razão, esta seção foi escrita.
Plotando a APU
Para estudar a APU do NES, compilei cinco espectogramas, cada um correspondente a um canal de APU utilizando os exemplos anteriores. Ao lado deles, você verá minha tentativa de desvendar o que os dados estão exibindo.
Antes de começar, devo admitir que para obter dados sem imprecisões (como ruídos extras), tive que fazer algumas concessões. As gravações foram obtidas usando um programa do Windows chamado “towave”, que usa síntese de banda limitada para resolver um problema fundamental com a emulação de chips de áudio baseados em PSG. Basicamente, pulsos, triângulos e dentes de serra são feitos de harmônicos infinitos. No entanto, isso não se mistura bem com placas de som modernas que são limitadas as amostras de 44,1 kHz. Portanto, uma técnica chamada “síntese de banda limitada” é usada para escolher os harmônicos corretos na limitação da placa de som. No geral, essa técnica fornece um equilíbrio viável entre desempenho, precisão e prevenção de aliasing (frequências falsas). Contudo, os dados podem não ser 100% idênticos ao seu equivalente analógico (que também introduziria outros problemas, como ruído do equipamento de gravação), mas acredito que estejam em um grau aceitável e, o mais importante, cumpre sua tarefa para esta seção do artigo.
Dito isso, vamos para a análise.
Pulso
A teoria diz que um tom de pulso contém apenas harmônicos ímpares. Em outras palavras, a fundamental é combinada com seu terceiro harmônico, quinto e assim por diante. Além disso, cada harmônico diminui sua amplitude quanto mais afastado estiver da fundamental. A fórmula da amplitude é amplitude = 1 ÷ número harmônico
[45].
Portanto, observe como o brilho de cada harmônico no espectrograma diminui à medida que ele sobre no eixo Y. Contudo, as ondas de pulso da APU também parecem exibir o efeito de vibrato mencionado anteriormente, que aumenta a cada número harmônico. Além disso, áreas do espectrograma que deveriam estar vazias de qualquer som contêm sobretons abafados (possivelmente resultado de ruído e outras imperfeições).
Triângulo
Uma onda triangular é também composta por harmônicos ímpares, mas com uma diminuição mais rápida de sua amplitude (onde a amplitude = 1 ÷ harmonic number²
[46]).
No entanto, isso não é o que aparece aqui, a forma de escada da onda triangular, que a APU produz, leva a harmônicos extras e aumento das amplitudes.
Ruído
Naturalmente, o ruído não segue as regras dos harmônicos e pode preencher aleatoriamente todo o espaço de frequência, portanto, a falta de um tom facilmente reconhecível.
No entanto, seguindo a linha do tempo, é possível diferenciar os diferentes pré-configurações de ruído que a APU fornece, cada um exibindo um conjunto distinto de sobretons.
Amostra
Diferente dos canais anteriores, o canal de amostra reproduz apenas a gravação de baixa resolução que o desenvolvedor alimenta na APU. Considerando que o exemplo tocava uma bateria, não consigo identificar nenhuma característica identificável no espectrograma (além das semelhanças com o ruído branco).
Dente de serra
Como bônus, vamos dar uma olhada no canal de dente de serra (sawtooth) da expansão VRC6. Para começar, uma onda de dente de serra perfeita é composta por todos os harmônicos, cada um exibindo amplitudes decrescentes (onde a amplitude = 1 ÷ harmonic number
[47]).
Isso é bastante exigente para equipamentos digitais e naturalmente inacessível para um cartucho de jogo (talvez nem precise de tanta perfeição!). Similar as ondas de triângulo da APU, o VRC6 sequencia as ondas de dente de serra em 7 ciclos (e assim produz efeitos de escada semelhantes).
Consequentemente, o respectivo espectrograma é bastante confuso, as técnicas de aproximação do VRC6 preenchem a onda com harmônicos extras em diversos lugares.
Conclusão
Bem, parece que as formas de onda sintéticas do NES não são moldadas como a teoria dita. Isso significa que a APU tem falhas? Não! A maneira que a APU foi projetada acabou concedendo ao console sons únicos e identificáveis — e essas propriedades, intencionais ou não, fizeram com que os espectrogramas exibissem resultados incomuns.
Como observação adicional, a geometria perfeita pode ser agradável aos nossos olhos, mas curiosamente, nossos ouvidos não são particularmente adeptos de formas de onda com bordas perfeitas! (você começa a ouvir estalos).
Olhando adiante, a análise de som usando espectrogramas será útil em outros artigos, seja para uma análise simples ou para fazer comparações com outros sistemas. Observe que esses gráficos não são a ferramenta definitiva, especialmente com amostras de som que foram misturadas com muitos canais/instrumentos (dificultando muito sua decomposição). Mas acredito que eles fornecem um bom ponto de partida para qualquer tido de estudo objetivo.
Jogos
Os jogos do NES foram escritos principalmente em linguagem de montagem 6502 e residem na ROM de Programa, enquanto os gráficos do jogo (tiles) são armazenados na Character memory.
Além disso, os jogos eram vendidos (ou alugados) em lojas de varejo sob a aprovação da Nintendo.
A mídia alternativa
Mesmo que tenha sido lançado apenas no Japão, eu pensei que essa seria uma boa oportunidade para apresentar um complemento curto, mas peculiar, que, assim como os mappers, trouxe mais capacidades para este console. Este periférico era chamado de Famicom Disk System (FDS) e foi lançado em 1986 (~3 anos após o Famicom). Ele tinha a forma de um leitor de disquetes externo e vinha com um cartucho de formato estranho chamado “adaptador de RAM”.
O Famicom Disk System adicionou os seguintes serviços ao Famicom:
- Uma nova mídia de distribuição para jogos chamada Famicom Disk [48]. Baseado no “Quick Disk” da Mitsumi, ele fornece ~64 KB de dados por lado e é regravável.
- Um canal de áudio extra que usa síntese de tabela de onda [49].
Como o disquete é uma mídia única (diferente dos cartuchos que podem ter vários chips), todos os dados do jogo precisam ser comprimidos dentro dele, embora seja mantido organizado com o uso de um sistema de arquivos proprietário.
No entanto, o Famicom/NES exige rigorosamente que a memória de Programa e de Personagens seja segregada para funcionar, então esse é o trabalho que “adaptador de RAM” tem que resolver. Este componente abriga 32 KB de RAM de Programa e 8 KB de RAM de Personagem para armazenar em buffer os dados do jogo lidos do disquete, e ao fazê-lo, permite que o console leia dele como se fosse um jogo em cartucho.
Para operar a unidade, o adaptador de RAM incorpora uma ROM adicional de 8 KB para armazenar um BIOS [50]. Este programa realiza as seguintes tarefas:
- Carrega uma animação de abertura.
- Inicializa o jogo a partir do disquete. Nos bastidores, o BIOS contém rotinas para copiar o conteúdo do disquete para o respectivo chip de memória, possibilitando que o console possa lê-lo.
- Fornece bibliotecas de entrada e saídas para os jogos, permitindo, por exemplo, percorrer o sistema de arquivo do disco.
Durante aquela época, a Nintendo instalou alguns “quiosques” em lojas de varejo para que os usuários pudessem levar seus disquetes e regravá-los com um novo jogo a um preço reduzido.
Infelizmente, após alguns anos de vida útil, o Famicom Disk System foi descontinuado e os jogos subsequentes voltaram ao formato de cartucho. Por outro lado, surgiram novos mappers disponíveis com capacidades semelhantes (ou melhores) em comparação às funções do FDS.
Anti-pirataria e Trava de região
A Nintendo foi capaz de bloquear a publicação não autorizada graças à inclusão de um chip de bloqueio proprietário chamado Checking Integrated Circuit (CIC) [51]. Ele está localizado no console e está conectado ao sinal de reinicialização (portanto, não pode ser facilmente removido).
Este chip executa o 10NES, um programa interno que verifica a existência de outro chip de bloqueio no cartucho do jogo. Se essa verificação falhar, o console é enviado para um ciclo de reinicialização infinito.
Ambos os chips de bloqueio estão em constante comunicação durante o tempo que o console está ligado. Este sistema pode ser vencido cortando um dos pinos do bloqueio do console, o que deixa o chip em estado ocioso. Alternativamente, enviando um sinal de -5V pode congelá-lo.
O CIC existe como resultado do medo causado pelo colapso dos videogames em 1983. O então presidente da Nintendo, Hiroshi Yamauchi, decidiu que, para impor jogos de boa qualidade, eles seriam responsáveis por aprovar cada um deles [52].
Perceba que o modelo japonês do console, o Famicom, foi lançado antes do colapso de 1983. É por isso que nem os cartuchos, nem o console incluem circuitos CIC [53], em vez disso, os pinos são usados para expansão de som opcional.