Arquitetura do PlayStation 2

Uma análise prática por Rodrigo Copetti

Traduzido por Lucas Akira Morishita

Se você usa ferramentas de acessibilidade ou navegadores antigos, mude para a edição ‘clássica’.




Imagens de suporte

Modelo

Image
O PlayStation 2 original.
Lançado em 04/03/2000 no Japão, 26/10/2000 nos EUA e em 24/11/2000 na Europa

Placa-mãe

Image
Placa-mãe
Mostrando a revisão 'GH-001' do modelo SCPH-10000 somente lançado no Japão.
Graças às doações recebidas, consegui comprar este modelo e tirar uma boa foto que me permite identificar a maior parte dos chips.
Eu presumo que o chip no canto inferior direito é a BIOS ROM de 4 MB
Image
Placa-mãe com partes importantes rotuladas

Diagrama

Image
Diagrama de arquitetura principal
O design original (implementado na revisão 'SCPH-10000').
Cada barramento de dados está rotulado com sua largura e velocidade.
Essa arquitetura passou por várias revisões, mais detalhes abaixo

Uma breve introdução

O PlayStation 2 não foi um dos consoles mais potentes de sua geração, porém conseguiu alcançar um nível de popularidade impensável para outras empresas.

Esta máquina não é nem perto de ser simples como o primeiro PlayStation foi, mas veremos o motivo dela não ter sofrido o mesmo destino de consoles complexos passados.


CPU

No coração deste console encontramos um potente conjunto encapsulado chamado Emotion Engine ou ‘EE’ desenvolvido pela Sony e rodando a ~294,91 MHz [1]. Este chipset contém múltiplos componentes, um deles sendo a CPU principal. O restante dos componentes está à disposição da CPU para acelerar algumas tarefas.

O líder

O núcleo principal é uma CPU compatível com MIPS R5900 com vários aperfeiçoamentos. Este é o primeiro chip que começa a executar instruções quando o console é ligado. O processador fornece os seguintes recursos:

O núcleo é complementado com uma unidade de ponto flutuante dedicada (identificada como ‘COP1’) que acelera operações com números de ponto flutuante de 32 bits (também conhecidos como floats em C). É um bloco peculiar visto que ele não obedece ao padrão IEEE 754, mais evidente com sua falta de infinity (computado como 0 no lugar) [2].

Uma escolha de memória reconhecida

Próximo ao Emotion Engine estão dois blocos de 16 MB de RAM, dando um total de 32 MB de memória principal. O tipo de memória usado é RDRAM (déjà vu!) que é acessado por um barramento de 16 bits.

Image
Design da memória do Emotion Engine. Você consegue adivinhar onde o congestionamento vai surgir.

À primeira vista, isso pode parecer um pouco decepcionante, considerando que o barramento interno do Emotion Engine tem uma largura de até 128 bits. Porém, os chips de RAM foram estrategicamente posicionados seguindo a arquitetura dual-channel, que consiste em conectar ambos os chips usando dois barramentos independentes de 16 bits (um barramento por chip) para melhorar a vazão de dados. A configuração resultante fornece uma vazão teórica de 3,2 GB/sec, portanto pode ter certeza que latência de memória não é um problema neste console!

Em um canto do Emotion Engine há um poderoso Controlador DMA ou ‘DMAC’ que transfere dados entre a memória principal e o Scratchpad (memória de rascunho); ou entre a memória principal e qualquer componente dentro do EE.

Transferências de dados são feitas em lotes de 128 bits, mas aqui fica a parte interessante: a cada oito lotes, o barramento principal é temporariamente desbloqueado. Isso deixa uma pequena janela de tempo para realizar outras transferências DMA em paralelo (até dez) ou deixar a CPU usar o barramento principal. Esse modus operandi é chamado slice mode e é um dos vários modos disponíveis nesta unidade DMA. Tenha em mente que enquanto o slice mode reduz paradas no barramento principal, ele o faz ao custo de desacelerar a transferência geral do DMA.

Prevenindo contratempos passados

Quer queiramos ou não, com a quantidade de tráfego ocorrendo dentro do Emotion Engine, esse design vai eventualmente sofrer as consequências da arquitetura de memória unificada ou ‘UMA’ (Unified Memory Architecture). Isto é: múltiplos componentes independentes tentando acessar a memória principal ao mesmo tempo, causando congestionamento. Bem, para corrigir esses problemas, a Sony aliviou o uso constante de memória com os seguintes métodos:

Isso soa muito conveniente em aplicações que podem se beneficiar da cache, mas e em certas tarefas, como a manipulação de Display Lists, que não devem usar a cache de forma alguma? Por sorte, a CPU fornece um modo de acesso alternativo chamado UnCached, que usa apenas o Write Back Buffer. Portanto, ciclos não serão desperdiçados corrigindo a cache (resultados de cache misses).

Além disso, o modo UnCached accelerated também está disponível. Este adiciona um buffer para acelerar a leitura de endereços contínuos na memória.

Outras partes interessantes

Dentro do mesmo encapsulamento do Emotion Engine, há ainda um outro processador chamado Unidade de Processamento de Imagem ou ‘IPU’ (Image Processing Unit), desta vez feito para descompressão de imagens. Como sucessor do MDEC, a IPU pode ser útil quando um jogo precisa decodificar um filme MPEG2 sem travar a CPU principal.

De forma resumida, o jogo envia fluxos de imagens comprimidas para a IPU (com sorte utilizando DMA) os quais são então decodificados em um formato que a GPU pode exibir. O sistema operacional do PS2 também depende da IPU para fornecer reprodução de DVDs.

Finalmente, a IPU também opera em texturas de alta resolução comprimidas, o que economiza uso de CPU e reduz grandes transferências.


Co-CPUs

Já faz dois anos desde que os rivais apresentaram suas mais recentes ofertas ao mercado. Se você leu o artigo anterior e acabou de começar a ler este aqui, eu presumo que você ainda está esperando ‘a coisa’ que faz o PS2 ser tão poderoso quanto parecia na época. Agora, deixe-me introduzir um conjunto de componentes muito importantes que a Sony colocou no Emotion Engine, as Unidades de Processamento Vetorial ou ‘VPU’ (Vector Processing Units).

Arquitetura

Uma Unidade de Processamento Vetorial é um pequeno processador independente projetado para operar vetores, e em particular, vetores com quatro floats. Esses processadores são tão rápidos que eles gastam apenas um ciclo por operação, o que pode ser extremamente conveniente para o processamento de geometria. Apesar disso, eles apresentam um comportamento não padronizado similar à FPU da CPU.

VPUs são feitos dos seguintes componentes:

Funcionalidade

Para começar a funcionar, a Unidade Vetorial precisa de um ‘pontapé inicial’. Para isso, a CPU principal fica encarregada de fornecer o microcódigo.

duas VPUs dentro do Emotion Engine, mas elas são organizadas de forma diferente, dando lugar a diferentes usos e otimizações.

Unidade de Processamento Vetorial 0

Image
Arquitetura da VPU0.

A primeira VPU, a VPU0, está posicionada entre a CPU e a outra unidade vetorial (VPU1). Ela possui um papel ‘auxiliar’ para a CPU principal.

A VPU0 possui dois modos de operação:

  • Micromode: Esse é o ‘modo tradicional’. A VPU vai executar de forma independente ‘microinstruções’ de um microprograma guardado na micromemória.
  • Macromode. A VPU0 se torna o ‘COP2’ da CPU principal e executa ‘macroinstruções’, recebidas da CPU principal por um barramento dedicado de 128 bits.
    • Macroinstruções têm a mesma funcionalidade das microinstruções, porém utilizam opcodes diferentes. No entanto, a unidade de execução da VPU não fica mais dividida (o que significa que ela só pode executar uma instrução por vez).
    • Apesar desse modo não utilizar completamente todos os componentes da VPU0, ele ainda acelera as operações vetoriais da CPU. Além disso, em termos de simplicidade, um coprocessador é mais fácil de programar que uma unidade independente (algo que os programadores de PC vão achar útil).

O mapa de memória da VPU0 também tem acesso a alguns registradores e flags da outra VPU, presumivelmente para verificar seu estado ou ler rapidamente os resultados de algumas operações feitas pela outra VPU.

Unidade de Processamento Vetorial 1

Image
Arquitetura da VPU1.

A segunda VPU, a VPU1, é uma versão melhorada da VPU0 com o quádruplo de micromemória e memória VU. Além disso, essa unidade inclui um componente adicional chamado Unidade de Função Elementar ou ‘EFU’ (Elementary Function Unit) que acelera a execução de funções exponenciais e trigonométricas.

A VPU1 está localizada entre a VPU0 e a Interface Gráfica (o ‘portão’ para a GPU), então ela possui barramentos adicionais que fornecem geometria para a GPU o mais rápido possível e sem utilizar o barramento principal.

No entanto, devido à sua localização, a VPU1 apenas opera em micromode.

É óbvio que essa VPU foi projetada para operações trigonométricas, e ela pode ser usada como um pré-processador para a GPU. Logo, ela é geralmente responsável pelo fornecimento dos famosos Display Lists.

Mundos infinitos

Uma abordagem útil que pode ser explorada com essas unidades é a geração procedural. Em outras palavras, ao invés de construir uma cena utilizando geometria definida por código, deixe que as VPUs a gerem utilizando algoritmos. Neste caso, a VPU calcula funções matemáticas para produzir a geometria que é então interpretada pela GPU (i.e. triângulos, linhas, quadriláteros, etc.) e, finalmente, usada para desenhar a cena.

Comparado com o uso de dados explícitos, o conteúdo procedural é ideal para tarefas paralelizadas, libera largura de banda, e é dinâmico (programadores podem definir parâmetros para obter resultados diferentes) [3]. Muitas áreas podem se beneficiar fortemente desta técnica:

Por outro lado, o conteúdo procedural pode ter problemas com animações e, se o algoritmo é muito complexo, a VPU pode não gerar a geometria no tempo exigido.

Em resumo, geração procedural não é uma técnica nova, mas graças às VPUs, essa técnica abre portas para maiores otimizações e gráficos mais sofisticados. Contudo, não é uma técnica simples de implementar e a equipe de P&D da Sony publicou vários artigos descrevendo diferentes abordagens para utilizá-la em seu console.

Você define o fluxo de trabalho

Com essas novas adições, programadores agora possuem muita flexibilidade para desenvolver seus motores gráficos. Para ajudar nesta tarefa, a Sony gastou recursos adicionais para elaborar e documentar modelos eficientes de pipeline. Os exemplos a seguir são pipelines gráficas otimizadas para diferentes tipos de cargas de trabalho [4]:

Image
Design do pipeline paralelo.
Image
Design do pipeline serial.

No primeiro exemplo, o design Paralelo, a CPU é combinada com a VPU0 em macromode para produzir geometria em paralelo com a VPU1. O conjunto CPU/VPU0 faz uso total do scratchpad e da cache para evitar usar o barramento principal, que a VPU1 depende para buscar dados da memória principal. No final, ambos os grupos de renderização simultaneamente enviam seus respectivos Display Lists à GPU.

O segundo exemplo, o design Serial, propõe uma abordagem diferente onde o grupo CPU/VPU0 trabalha como um preprocessador para a VPU1. A primeira etapa irá buscar e processar toda a geometria que a VPU1 vai posteriormente transformar em uma Display List.

Esses foram, até agora, exemplos do ponto de vista teórico, porém para explicar uma implementação mais ‘prática’, eu vou referenciar um vídeo publicado por Jon Burton que fala sobre o desenvolvimento de um de seus jogos de PS2 [5].

Image
Crash Bandicoot: The Wrath of Cortex (2001). Partículas formam o fogo da vela e a luz que vem das janelas de vidro.

O antigo diretor da Travellers Tales explicou como seu time obteve um sistema de partículas totalmente encapsulado dentro da VPU1. Em poucas palavras, a VPU1 focou em ler uma base de dados previamente preenchida em sua memória VU, e a base de dados foi usada para calcular as coordenadas de partículas a todo instante sem depender de nenhum outro componente. O resultado da operação poderia ser transformado em Display Lists e enviado imediatamente.

Com essa abordagem, a CPU ficou significativamente descarregada, permitindo-lhe realizar outras tarefas como IA e física.

Há vários outros exemplos por aí, mas resumindo as coisas: cabe agora ao programador encontrar a configuração mais otimizada, e isso é um ponto positivo.


Gráficos

Considerando todo o trabalho feito pelo Emotion Engine, falta alguma coisa? Na verdade, o último passo: a visualização dos gráficos!

Image
Final Fantasy X (2001).

Existe um simples porém rápido chip especializado nisso: O Sintetizador Gráfico ou ‘GS’ (Graphics Synthesizer) rodando a ~147,46 MHz. Ele contém 4 MB de DDRAM embutido para realizar todo o processamento internamente. Assim, eliminando a necessidade de acesso à memória principal. A RAM embutida é conectada utilizando diferentes barramentos dependendo do tipo de dado exigido.

O GS possui menos recursos que outros sistemas gráficos analisados anteriormente neste site. No entanto, é muito rápido no que se propõe a fazer.

Arquitetura e design

Essa GPU só faz rasterização e isso inclui… Gerar pixels, mapear texturas, aplicar iluminação e alguns outros efeitos. Isso significa que não há transformações de vértices (estas são feitas pelas VPUs). Além disso, trata-se de um pipeline de função fixa, então não há modificações sofisticadas nem shaders, estamos restritos a um modelo de sombreamento fixo (ex: Gouraud).

Image
Design do pipeline do Graphics Synthesizer

Parece bem simples né? Bem, vamos nos aprofundar mais e ver o que acontece em cada estágio.

Pré-processamento

Image
Estágio pré-processamento.

O Emotion Engine inicia o Sintetizador Gráfico preenchendo sua DRAM com os materiais exigidos (Bitmaps de texturas e Lookup tables de cores, sendo o último também chamado ‘CLUT’), atribuindo valores nos registradores do ‘GS’ para configurá-lo e, finalmente, emitindo os comandos de desenho (Display Lists) que vão instruir o GS a desenhar primitivas (pontos, linhas, triângulos, sprites, etc.) em lugares específicos da tela.

Adicionalmente, o GS irá pré-processar alguns valores que serão necessários para cálculos futuros. Um desses números em especial é o valor do Algoritmo Diferencial Digital, que será usado para interpolações durante o processo de desenho.

Rasterização

Image
Estágio de rasterização.

Usando os valores calculados anteriormente, o renderizador gera pixels a partir das primitivas. Essa unidade pode gerar 8 pixels (com texturas) ou 16 pixels (sem texturas) simultaneamente, e para cada pixel as seguintes propriedades são calculadas:

  • RGBA: correspondente ao gradiente de vermelho (Red), verde (Green), azul (Blue) e Alfa (transparência).
  • Z-value: usado para testes de profundidade em estágios seguintes.
  • Fog: opcional, usado para simular névoa no ambiente.
  • Propriedade de texturas: contém o endereço de DRAM da textura dentre outras propriedades (coordenadas, nível de detalhe, filtro, etc.) que serão usadas no estágio seguinte.

Também são feitos testes de corte (Scissoring Tests) que descartam polígonos fora do quadro (baseado nos seus valores X/Y), e algumas propriedades de pixel são encaminhadas a um estágio de ‘teste de pixel’ para verificações adicionais. A Iluminação é também fornecida ao selecionar uma das duas opções disponíveis, Gouraud e Flat.

O pacote é então entregue ao motor de ‘mapeamento de texturas’, mas cada propriedade é operada por um ‘submotor’ especializado, o que permite o processamento de diferentes propriedades em paralelo.

Texturização

Image
Estágio de mapeamento de texturas

Esse estágio é movido por uma grande Unidade de Pixel que pode computar até 16 pixels de uma vez, e é aqui que as texturas serão mapeadas nos polígonos (que agora são pixels). Ademais, os efeitos de névoa e anti-aliasing são aplicados aqui.

Mapeamentos de textura são obtidos da DRAM em uma área definida como buffer de textura, embora isso seja interligada com uma área separada chamada buffer de paginação de texturas, que parece servir como um mecanismo de cache de texturas. CLUTs também são mapeados utilizando este sistema de paginação. Ambos os elementos são retirados com o uso de um barramento de 512 bits.

A unidade de pixel executa uma correção de perspectiva para mapear texturas nas primitivas (uma grande melhoria considerando a abordagem anterior de mapeamento afim). Adicionalmente, ela também fornece filtragem bilinear e trilinear, o último sendo usado junto com texturas MIP mapeadas.

Testes

Image
Estágio de teste de pixels

Aqui certos pixels serão descartados se eles não atenderem a vários requisitos. Dito isso, os seguintes testes são realizados:

  • Teste de Alfa: compara o valor de alfa (transparência) de um pixel com o valor ‘padrão’. O motivo disso é que em alguns casos o valor de alfa precisa estar dentro de um determinado intervalo ou maior/menor que um valor arbitrário.
  • Teste de Alfa do destino: verifica o valor de alfa do pixel novamente antes de desenhá-lo no frame buffer.
  • Teste de Profundidade: compara o valor de Z do pixel com o valor de Z correspondente ao Z-buffer. Isso evita o processamento de pixels que ficariam ocultados atrás de outros pixels.

Pós-Processamento

Image
Estágio pós-processamento

O último estágio pode aplicar alguns efeitos sobre nossos novos pixels usando o frame buffer anterior localizado na DRAM local:

  • Alpha Blending: Mescla cores do buffer atual com o anterior na memória.
  • Dithering: Altos valores RGBA precisam ser cortados, então o dithering pode ser aplicado para suavizar a perda de precisão.
  • Colour Clamping: Após aplicar operações como o Alpha Blending, o novo valor RGB pode exceder o intervalo válido (0-255), então o clamping determina um valor dentro do intervalo.
  • Formatação: Converte o frame buffer final gerado no pipeline em um formato que pode ser guardado em memória.

Finalmente, o novo frame buffer, junto com o Z-buffer atualizado, são escritos na memória usando um barramento de 1024 bits.

Ainda mais pós-processamento

Existe um componente dedicado dentro do GS chamado Controlador CRT Programável ou ‘PCRTC’ (Programmable CRT Controller) que envia o frame buffer na memória para a saída de vídeo, para você poder ver o frame na TV. Mas isso não é tudo: ele também contém um bloco especial chamado Merge Circuit que permite o Alpha Blend de dois frame buffers separados (útil se os jogos querem reusar o frame anterior para formar o novo). O frame resultante pode ser enviado pelo sinal de vídeo e/ou escrito de volta à memória.

Modelos melhores

Com tudo o que foi dito, isso certamente trouxe designs melhores para atualizar personagens já famosos. Dê uma olhada neste ‘Antes & Depois’:

WireframeSuperfícieTexturizado
3D model
Crash Bandicoot (1996) para o PS1.
732 triângulos.
WireframeSuperfícieTexturizado
3D model
Crash Bandicoot: The Wrath of Cortex (2001).
2226 triângulos.

Aqui estão personagens de novas séries de jogos. Estes foram modelados com altos níveis de detalhe desde o início:

WireframeSuperfícieTexturizado
3D model
Kingdom Hearts (2002).
2744 triângulos.
WireframeSuperfícieTexturizado
3D model
Dragon Quest VIII (2004).
2700 triângulos.

Vale a pena mencionar que jogos como Dragon Quest implementaram um modelo de iluminação personalizado chamado Cel Shading (um termo que eu já mencionei antes), porém, nos meus artigos anteriores eu expliquei que a GPU era a principal responsável por isso. No caso do PS2, os cálculos de cores exigidos são presumivelmente feitos pelo Emotion Engine, dado que o GS não é tão flexível quanto outras GPUs.

Saída de Vídeo

Como dito anteriormente, o PCRTC envia o frame buffer pelo sinal de vídeo. A interface pode transmitir vídeo utilizando uma ampla gama de formatos (para funcionar com TVs de qualquer região geográfica) [6]:

Image
Lado direito do console [7], visto de trás. Exibindo a porta A/C, porta de áudio digital e saída Multi AV.

Há muitos modos para escolher, porém, tudo se resume ao formato adotado durante o início dos anos 2000, o que diminui as opções para PAL e NTSC. Além disso, embora o padrão PAL tenha fornecido uma resolução maior que o NTSC, algumas versões europeias de jogos NTSC recorreram ao letterboxing para mascarar as linhas horizontais não utilizadas e diminuíram a taxa de atualização da imagem do jogo para encaixar no limite de 50 Hz (Eu os chamo de ‘más adaptações’!).

A porta da saída de vídeo (Multi A/V) é muito conveniente. Ela carrega os sinais RGB, Componente, S-Video e Composto. Logo, todos os sinais importantes estão disponíveis sem a necessidade de adaptadores proprietários ou modificações internas.


Áudio

O novo chip de áudio é uma atualização incremental da antiga SPU chamada… SPU2! Melhorias incluem a adição de 2 MB de memória interna e 48 canais disponíveis (duas vezes mais que a quantidade original).

A SPU2 é feita de dois processadores de som em seu interior, referidos como CORE0 e CORE1, e roda a ~36,86 MHz. Cada um processa 24 canais.

Curiosamente, esses ainda são dois processadores independentes e para os configurar, você precisa alterar seus registradores. No entanto, a Sony avisou os desenvolvedores que os dois conjuntos de registradores devem ser configurados com 1/48000 segundo de intervalo. Se você se apressar demais, o comportamento da SPU2 pode se tornar imprevisível!

A SPU2 herda os mesmos efeitos disponíveis na SPU original. A memória fornecida é usada como uma ‘área de trabalho’: você pode guardar dados brutos de formas de ondas e alocar espaço extra para processá-los e aplicar efeitos sobre eles.

Finalmente, o chip pode mixar todos os canais para fornecer saída estéreo. Agora, aqui fica a parte interessante: a SPU2 pode se alimentar da amostra estéreo mixada como uma nova entrada, e isso permite que o EE a acesse (para mixá-la com ainda mais áudio, por exemplo), ou permite continuar com a adição de mais efeitos (como reverberação, eco e atraso).

Kingdom Hearts II (2005). Sem reverberação.
Kingdom Hearts II (2005). Com reverberação.

Saída de áudio

O sinal de áudio é transmitido através de dois meios:


E/S

A E/S do PS2 não é complicada, mas várias revisões deste console mudaram completamente várias interfaces internas e externas.

Para começar, existe um processador dedicado que arbitra a comunicação entre os diferentes componentes, e essa CPU não é nenhuma outra além do núcleo original baseado no MIPS R3000 encontrado no PlayStation 1. Desta vez, ela é chamada IOP e roda a 37,5 MHz usando um barramento de 32 bits [8].

A IOP comunica com o Emotion Engine usando uma interface de E/S especializada chamada System Interface ou ‘SIF’, e ambos usam suas respectivas unidades de DMA para transferir dados entre si. A IOP também contém sua própria memória utilizada como um buffer.

A IOP dá acesso às portas frontais, ao controlador de DVD, à SPU2, à BIOS ROM e ao slot de placas de PC.

Compatibilidade herdada

Ao incluir a CPU original, podemos suspeitar que a compatibilidade de PS1 eventualmente aconteceria de alguma forma. Convenientemente, ocorre que a IOP inclui o resto dos componentes que formam o subsistema da CPU do PS1. No mais, este núcleo pode diminuir sua frequência para rodar na velocidade do PS1. Infelizmente, a SPU2 mudou demais para o PS1 e, devido a isso, o Emotion Engine é ‘reprogramado’ para emular a antiga SPU.

Em revisões posteriores deste console, a IOP foi substituída por um PowerPC 401 ‘Deckard’ e 4 MB de SDRAM (2 MB a mais que antes), mantendo a retrocompatibilidade, porém através de software.

Interfaces disponíveis

Este console manteve as portas frontais anteriores incluídas no PlayStation original, e também apresentou algumas interfaces ‘experimentais’ que pareciam muito promissoras no início.

Image
Frente do PS2 mostrando portas comuns incluindo controles e Memory Cards, mais os novos USBs e o i.Link [9].

A adição mais popular: duas portas USB 1.1. Amplamente adotada por acessórios de outras fabricantes, essas portas foram mantidas em todas as revisões futuras do console.

E quanto às ‘experimentais’? Para começar, havia inicialmente uma porta i.Link frontal (também conhecida como IEEE 1394, ou ‘FireWire’ no mundo da Apple). Essa porta foi utilizada para conectar dois PS2s para possibilitar partidas multijogador local, porém foi removida após a terceira revisão (presumivelmente foi trocada pela ‘placa de rede Network Adaptor’, mais detalhes abaixo).

Na parte de trás do console também havia um slot para placas de PC, e você podia comprar uma ‘placa Network Adaptor’ da Sony que fornecia duas portas extras. Uma para conectar um cabo Ethernet, e outra para conectar uma ‘Unidade de Disco Rígido’ (Hard Disk Drive Unit) externa e proprietária, também vendida pela Sony. Ter um disco rígido permitiu que jogos guardassem dados temporários (ou instalá-los permanentemente) para obter tempos de carregamento mais rápidos. No entanto, apenas alguns poucos jogos usaram esse recurso.

Image
Parte traseira do PS2 mostrando o compartimento do disco rígido (tampa removida) [10].
Image
Network adaptor (adaptador de rede) visto de frente [11]. Este modelo em particular fornece portas modem e Ethernet.
Image
Network adaptor visto de trás [12], com um disco rígido inserido.
Image
Parte traseira do modelo slim com a porta Ethernet fixa visível.

Em revisões posteriores, a porta PCMCIA foi substituída por um Compartimento de Expansão (Expansion Bay) onde um disco rígido de 3,5 polegadas poderia ser instalado dentro do console. Você precisava comprar antes um Network adaptor que não apenas fornecia as portas de modem e/ou Ethernet (dependendo do modelo), mas também incluía as conexões necessárias para um disco rígido ATA-66. Revisões ‘Slim’ removeram completamente essa funcionalidade, mas deixaram uma porta Ethernet permanentemente instalada na parte de trás do console. Além disso, a nova revisão adicionou uma nova ‘porta’ frontal, o sensor infravermelho.

O transceptor Ethernet fornecido suporta taxas de transferência de até 100 Mbps (12,5 MB/s). Porém, a taxa observada é notoriamente menor (diminui para até 2 MB/s em alguns casos). A explicação para isso é relativamente simples: para conseguir uma comunicação de rede utilizável, é necessário implementar todas as camadas do padrão ‘Modelo OSI’, e o transceptor é apenas uma peça do quebra-cabeça. O resto é geralmente delegado à IOP (logo, feito em software), mas o desempenho limitado da IOP [13] resulta em gargalos.

Acessórios interativos

A nova versão do controle deles, o DualShock 2, é uma versão ligeiramente melhorada do DualShock.

Image
Controle DualShock 2 [14].
Image
Memory Card oficial (modelo de 8 MB) [15].

Durante os dias do PlayStation original, múltiplas revisões do controle original foram lançadas com diferentes funcionalidades (o que também trouxe fragmentação ao mercado). Agora, em benefício aos desenvolvedores, havia um único controle que unificava todas as propriedades anteriores.

Comparado com o DualShock, a nova versão possui uma pequena mudança de design, incluía duas alavancas analógicas e dois motores de vibração para uma entrada e feedback com maior riqueza, respectivamente.

Próximo ao slot de controle está o slot de Memory Card que é compatível com os cartões do PS1 e do PS2. Os novos cartões de memória incorporaram circuitos extras para fins de segurança chamados MagicGate, que permite que os jogos bloqueiem transferências de dados entre diferentes Memory Cards.


Sistema Operacional

Há um chip ROM de 4 MB instalado na placa-mãe que armazena uma grande quantidade de código usado para carregar um menu de shell que os usuários podem interagir, mas ele também fornece chamadas de sistema para simplificar o acesso de E/S [16], nos quais os jogos dependem.

Image
Animação de splash após ligar o console.
Image
Logo do PS2 visível após um jogo válido de PS2 ser inserido.

Durante a inicialização, a CPU irá executar instruções na ROM que irão:

  1. Inicializar o hardware.
  2. Carregar um Kernel na RAM, que lidará com chamadas de sistema e também fornecer suporte a multi-threading (cooperativo e baseado em prioridades).
  3. Iniciar o processador IOP e enviar-lhe módulos; estes permitirão que a IOP lide com o hardware deste console. No final, a IOP será colocada em um estado de ‘aguardando comandos’.
    • O uso de módulos permite que a Sony lance novas revisões de hardware do PS2 sem mudar a IOP, reduzindo os custos de produção.
  4. Carregar a ‘’OSDSYS’, o programa que mostra a animação de splash e o menu do shell.

Shell interativo

A funcionalidade do shell do PS2 está praticamente à mesma altura dos outros consoles da 6ª geração.

Image
Menu inicial. Aparece quando não há disco inserido.
Image
Navegador do Memory Card.
Image
Navegador de jogos salvos. Ele aparece após selecionar um Memory Card.
Image
Editor de jogos salvos, exibido após selecionar um jogo salvo.
Image
Configurações do Sistema.

O shell apresenta algumas seções práticas que permitem a realização de operações do dia-a-dia, como a manipulação de jogos salvos no Memory Card. Ele também fornece algumas opções excepcionais, como alterar o modo de vídeo atual.


Jogos

É sem precedentes o nível de popularidade que este sistema alcançou durante a primeira década dos anos 2000, e no final do seu tempo de vida (2013, depois de 13 anos!) o catálogo de jogos continha 1850 títulos [17].

Image
Mr Moskeeto (2001). Toda vez que alguém discute sobre a abundância de jogos de PS2, eu me lembro desse jogo.

O que aconteceu aqui é realmente impressionante. O PS2 não possui uma arquitetura ‘amigável para programadores’ (da perspectiva de um programador de PC), porém com essa quantidade de jogos desenvolvidos, eu também me pergunto se havia mais fatores envolvidos (como ‘facilidades de licenciamento’, baixos custos de distribuição, formato compacto, etc.).

Ecossistema de desenvolvimento

A Sony forneceu o hardware e o software para ajudar no desenvolvimento de jogos.

No lado do software, havia o PlayStation 2 SDK que incluía [18]:

No lado do hardware, a Sony forneceu hardware dedicado aos estúdios para executar e realizar debug de jogos internamente. Os kits de desenvolvimento (devkits) iniciais eram um conjunto de placas expostas empilhadas que replicavam o hardware ainda não lançado do PS2. Os kits posteriores (chamados Development Tool), possuíam uma aparência mais apresentável, E/S aprimorada e combinavam um workstation (rodando RedHat 5.2) com o hardware do PS2 para compilar e instalar o jogo dentro do mesmo kit [19].

A combinação do Devkit, do SDK oficial e do CodeWarrior (um IDE famoso) era uma das configurações mais populares.

Mídia

O leitor de discos consegue ler tanto DVDs e CDs, então os jogos poderiam ser distribuídos usando um dos dois formatos, mas por razões óbvias você encontrará a maioria dos títulos no formato DVD.

Image
Kingdom Hearts II (2005). Embalagem de jogo e disco comuns no varejo.

DVDs podem guardar até 4,7 GB de dados no caso do DVD-5 (o ‘subformato’ mais comum) ou até 8,5 GB no caso do DVD-9 (versão dual-layer, menos comum) [20]. Na verdade, há um terceiro formato, o DVD-10, que é de dupla face, mas nenhum jogo o utilizou.

Devido ao tipo de mídia usada, não apenas jogos poderiam ser rodados, mas filmes também. Agora, um decodificador é necessário para que o formato de um filme DVD possa ser lido, e para isso, o PS2 inicialmente incluiu as partes necessárias para tal instaladas no Memory Card (este é, afinal, um meio de armazenamento como qualquer outro), porém modelos posteriores do console vieram com o software de DVD pré-instalado na ROM da BIOS.

Em termos de velocidade, CD-ROMs são lidos em velocidade 24x (logo a 3,6 MB/s) e DVD-ROMs são lidos em velocidade 4x (5,28 MB/s) [21].

Serviços de rede

Como você pôde observar, os recursos de rede desses consoles não foram padronizados até revisões posteriores, que chegaram quatro anos após o lançamento da primeira versão. Da mesma forma, os estúdios de jogos estavam encarregados de prover a infraestrutura necessária se eles decidirem fornecer serviços online (como partidas multijogador). Anos mais tarde, a Sony implantou o Sistema de Autentificação de Rede Dinâmica ou ‘DNAS’ (Dynamic Network Authentication System), e isso não era um servidor online, mas um sistema de autentificação para impedir que jogos pirateados conectassem online.

Um tipo de jogo incomum

Além de todos esses jogos com seus gráficos sofisticados, a Sony lançou uma distribuição Linux baseada no ‘Kondara’ (que por sua vez é baseada no Red Hat 6) disponível em dois DVDs (o primeiro disco chamado ‘Runtime Environment’ e o segundo chamado ‘Software Packages’) junto com um adaptador VGA, teclado e mouse USB, e alguns manuais de desenvolvedor. Esse pacote era conhecido como Kit Linux e você podia executar o SO iniciando o primeiro DVD e então prosseguir da mesma forma que em qualquer ambiente Linux old school. Você obviamente precisava de um disco rígido instalado no console para instalar a distribuição Linux. Uma vez instalada, o primeiro DVD sempre era necessário para inicializar o SO.

O Kit Linux incluía compiladores tendo como alvo o EE (gcc 2.95.2 com glibc 2.2.2) e assemblers para as unidades vetoriais, junto com um sistema gráfico de janelas (XFree86 3.3.6) ‘acelerado’ no Sintetizador Gráfico [22]. De modo geral, isso parece um ambiente interessante. De fato, um dos artigos de pesquisa que eu li para escrever este artigo foi feito com essa configuração.


Anti-Pirataria e Homebrew

Há bastante coisa para falar aqui, então vamos começar com o leitor de DVD.

Proteção contra cópia

Essa seção foi particularmente preocupante para os estúdios de jogos, visto que este console usava um formato de disco acessível para guardar os jogos e havia um grande risco de pirataria.

Image
Essa tela de erro pode aparecer se o leitor está com defeito… ou se uma cópia pirata foi inserida.

Quando o SO carrega um jogo, ele o faz enviando comandos específicos para o leitor de DVD. Os comandos especificamente usados para ler o conteúdo de um jogo comportavam-se de forma muito diferente dos comandos padrões de DVD (i.e. para ler um filme em DVD). Acontece que os jogos autorizados contêm um ‘arquivo de mapeamento’ fora de alcance na seção interna do disco que indexa o sistema de arquivos por nome, posição e tamanho. Quando o DVD é solicitado a ler um disco de jogo, ele sempre vai navegar pelo disco usando um arquivo de mapeamento, o que significa que uma cópia pirata de um jogo, que não poderia incluir o arquivo de mapeamento, será impossível de ser lida. Isso foi complementado por um sistema de bloqueio de região que impedia que jogos importados funcionassem em um console de região diferente.

Vulnerabilidades descobertas

Tendo explorado as partes mais críticas deste console, vamos dar uma olhada em vários métodos descobertos que poderiam contornar os mecanismos de proteção.

Modchips

Como qualquer outro console de sua geração (e da geração passada) que usava um sistema baseado em disco, era uma questão de tempo até que outras empresas realizassem engenharia reversa do subsistema de DVD. O objetivo aqui era encontrar uma vulnerabilidade (exploit) útil que poderia forçar o leitor a navegar pelos arquivos do sistema sem a necessidade de um arquivo de mapeamento fora de alcance.

Isso eventualmente aconteceu na forma de modchips, o que também contornou as restrições de bloqueio de região.

Trapaças

Junto com os modchips, que exigiam habilidades de solda para instalar, discos não autorizados porém ‘legítimos’ surgiram no mercado. Estes permitiam contornar a proteção de região e o uso de trapaças no jogo por meio de pequenas alterações no SO. Além disso, ‘discos de trapaça’ tinham a vantagem de não precisar modificar o console. Suponho que o melhor exemplo a ser mencionado é o CodeBreaker.

Disc swapping (troca de discos)

No meio dos últimos avanços, surgiu mais um truque. Desta vez, explorando a forma como o leitor lida com setores defeituosos. Swap Magic parece como um outro disco ‘legítimo’, mas o ‘jogo’ presente nele diz ao DVD para ler um executável inexistente localizado deliberadamente em um setor defeituoso, o que interrompe o leitor por completo [23]. Essa janela de oportunidade permitiu que usuários trocassem o disco por um não-legítimo. Então o Swap Magic, ainda carregado em memória, inicializa o executável principal do novo disco, carregando um jogo de verdade no final do processo. Tudo isso é feito enquanto o leitor de CD/DVD ainda acredita que um disco legítimo foi inserido.

Isso não requer necessariamente uma alteração no console. Porém, dependendo do modelo, a carcaça externa do PS2 terá que ser manipulada para bloquear os sensores de remoção de mídia do leitor. Em alguns casos, colocar algodão em alguns lugares será o suficiente.

Overflow do PS1

O PS2 guarda um arquivo de base de dados chamado TITLE.DB no Memory Card que contém informações usadas para otimizar a emulação de jogos de PS1 [24]. Quando um jogos de PS1 é inserido, o SO busca o arquivo de base de dados e carrega o arquivo inteiro em memória em um endereço fixo (strike um). O analisador de informações é implementado utilizando o strncpy(), uma função em C que copia strings (cadeia de caracteres) de um lugar para outro.

Para pessoas familiarizadas com C, vocês provavelmente já adivinharam onde eu vou chegar com isso. O fato é que strncpy() não sabe o quão longo é uma string, então a menos que ela seja finalizada (colocando \0 no final da cadeia) o processo de cópia vai continuar ‘para sempre’ (com resultados imprevisíveis!). Felizmente, essa função contém um parâmetro opcional que especifica o número máximo de bytes a serem copiados, protegendo a cópia de buffer overflows. Por mais ridículo que possa parecer, a Sony não usou esse parâmetro, embora cada entrada da base de dados tenha um tamanho fixo de 256 bytes (strike dois).

Após uma inspeção mais detalhada da RAM, ocorre que TITLE.DB é copiado próximo de um registrador salvo, o $ra, que indica o endereço de retorno após a função atual em execução finalizar (strike três), o que levou à vulnerabilidade conhecida como The independence exploit: faça um TITLE.DB com uma string comprida, inclua um executável dentro dele e faça a string de forma que o $ra seja sobrescrito para apontar para o executável. Se você conseguir enviar este arquivo para seu Memory Card (através de outro exploit ou um adaptador USB no PC) você conseguiu um Homebrew launcher simplificado.

Após o lançamento das revisões slim, a vulnerabilidade foi corrigida (me pergunto como). Curiosamente, este caso não foi o último descuido grave que expôs código desleixado.

Um desbloqueio de software semi-permanente

Há algum tempo, foi descoberto que a BIOS deste console pode ser atualizado usando o Memory Card, e que essa função nunca foi usada na prática, mas também não foi removida (pelo menos durante boa parte do período de vida do console). Com isso, hackers perceberam que se eles encontrassem um jeito de instalar softwares específicos no Memory Card, então a BIOS sempre iria carregá-los durante a inicialização. Essa descoberta levou ao Free MCBoot, um programa apresentado ao console como ‘dados de atualização’ que substitui o shell original com um que pode executar Homebrew.

Tenha em mente que essas alterações não são permanentes, um Memory Card com o ‘Free MCBoot’ instalado deve ser inserido antes da inicialização do console. Além disso, este software precisa ser instalado de alguma forma, então um outro exploit (ex: disc swapping) é necessário para inicializar o instalador.

Mais truques de disco

No mesmo ano após o lançamento do Free MCBoot, um outro truque foi descoberto: Disfarçar jogos como se fossem filmes em DVD, permitindo efetivamente que cópias não autorizadas de jogos possam ser lidos sem a necessidade de um modchip.

Isso apenas exigia a alteração da imagem do jogo com a adição de metadados e partições somente usadas por filmes em DVD. Então, quando a cópia gravada é inserida no console, o leitor não irá rejeitá-lo, mas o jogo também não será executado. Porém, com a ajuda de um programa Homebrew chamado ESR, o jogo consegue ser inicializado.


Isso é tudo pessoal

Parabéns e obrigado por chegar ao fim do artigo! Para ser honesto, havia tanta coisa para falar que eu me perguntei se os leitores iriam eventualmente se cansar de conteúdos relacionados ao PlayStation depois de terminar isso.

De qualquer forma, e falando sério, eu espero que você tenha descoberto novas coisas após ler este artigo e se você tem qualquer comentário, não hesite em falar comigo.

Até a próxima!
Rodrigo


Contribuir

Este artigo faz parte da série Arquitetura dos Consoles. Se você o achou interessante, por favor, considere fazer uma doação. A sua contribuição será usada para financiar a compra de ferramentas e recursos que me ajudarão a melhorar a qualidade dos artigos existentes e dos que estão por vir.

Donate with PayPal
Become a Patreon

Você também pode comprar a edição eBook em inglês. Eu trato os lucros como doações.

Image

Uma lista de ferramentas desejáveis e as mais recentes aquisições para este artigo são mantidas aqui:

### Interesting hardware to get (ordered by priority)

- Hard drive/Network card for the SCPH-10000.
- PS2 SCPH-3x00x model to check out Homebrew using the hard drive.

### Acquired tools used

- PS2 SCPH-10000 (£60) to do a proper motherboard analysis.
- Old PS2 Slim grey (£40?) from back then.

Como alternativa, você pode ajudar sugerindo alterações e/ou adicionando traduções.


Copyright and permissions

This work is licensed under a Creative Commons Attribution 4.0 International License. You may use it for your work at no cost, even for commercial purposes. But you have to respect the license and reference the article properly. Please take a look at the following guidelines and permissions:

Article information and referencing

For any referencing style, you can use the following information:

For instance, to use with BibTeX:

@misc{copetti-ps2,
    url = {https://www.copetti.org/writings/consoles/playstation-2/},
    title = {PlayStation 2 Architecture - A Practical Analysis},
    author = {Rodrigo Copetti},
    year = {2020}
}

or a IEEE style citation:

[1]R. Copetti, "PlayStation 2 Architecture - A Practical Analysis", Copetti.org, 2020. [Online]. Available: https://www.copetti.org/writings/consoles/playstation-2/. [Accessed: day- month- year].
Special use in multimedia (Youtube, Twitch, etc)

I only ask that you at least state the author’s name, the title of the article and the URL of the article, using any style of choice.

You don’t have to include all the information in the same place if it’s not feasible. For instance, if you use the article’s imagery in a Youtube video, you may state either the author’s name or URL of the article at the bottom of the image, and then include the complete reference in the video description. In other words, for any resource used from this website, let your viewers know where it originates from.

This is a very nice example because the channel shows this website directly and their viewers know where to find it. In fact, I was so impressed with their content and commentary that I gave them an interview 🙂.

Appreciated additions

If this article has significantly contributed to your work, I would appreciate it if you could dedicate an acknowledgement section, just like I do with the people and communities that helped me.

This is of course optional and beyond the requirements of the CC license, but I think it’s a nice detail that makes us, the random authors on the net, feel part of something bigger.

Third-party publishing

If you are interested in publishing this article on a third-party website, please get in touch.

If you have translated an article and wish to publish it on a third-party website, I tend to be open about it, but please contact me first.


Fontes / Continuar lendo

Anti-pirataria

Processador

Jogos

Geral

Gráficos

E/S

Sistema Operacional

Fotografia


Rodrigo Copetti

Rodrigo Copetti

Espero que você tenha gostado deste artigo! Se você quer saber mais sobre o autor toque aqui e se você gostaria de apoiá-lo toque aqui ao em vez disso

rsslinkedintwittergithub facebookreddit