O que há de Novo?
  • Anunciando os planos GOLD no Fórum Outer Space
    Visitante, agora você pode ajudar o Fórum Outer Space e receber alguns recursos exclusivos, incluindo navegação sem anúncios e dois temas exclusivos. Veja os detalhes aqui.

Os jogos mais avançados do Nintendo 64 [+Doom 1 e 2 do PC no Ultra 64][+DINOSAUR PLANET vazou página 42]

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303
192031

Patch de correções para o Dinossaur Planet

dinopatch v2.4 dead dino edition

https://www.dropbox.com/s/ugtwdybv8ag20lm/dinopatch_v2.4.xdelta

novo nesta compilação:

  • o menu principal do jogo foi restaurado! e com ele, o menu de opções está finalmente acessível pelos meios normais! as mesmas opções que funcionavam anteriormente no dinomod também funcionarão via dinopatch a partir desta compilação (widescreen, posição, áudio, exibição)
  • o klanadack agora pode ser derrotado! o jogo vai jogar a cena da vitória, premiar a pedra mágica e transportá-lo de volta para a cidade murada como (principalmente) pretendido
  • derrotar galadon não o joga mais no vazio e premiar corretamente a pedra mágica
  • a música da fase um do galadon foi corrigida, junto com muitas outras trilhas em minas darkice
  • a cutscene de introdução do galadon foi melhorada, o gelo agora quebra corretamente e a pedra mágica é animada
  • a correção de coleta de item foi retrabalhada para mitigar problemas de estabilidade para algumas pessoas
  • alguns ícones de inventário de pedra mágica foram corrigidos, incluindo o ícone de pedra mágica klanadack (anteriormente um CRF gema da sala de energia)
  • lightfoot enjaulado em cape claw não usa mais o modelo do lightfoot chefe
  • as configurações pertencentes ao menu de opções são carregadas na inicialização para evitar a necessidade de entrar no menu de opções cada vez que o jogo é iniciado
dinomod v2.4 "one hour video edition "

https://www.dropbox.com/s/xjiwmr21c6uvxq5/dinomod_v2.4.xdelta

novo nesta compilação:
  • todos os itens acima do dinopatch v2.4, mais ...
  • o jingle de retirada de item antigo, conforme ouvido no vídeo de 1 hora, agora pode ser ativado opcionalmente! esta configuração é armazenada no savegame.
  • o templo earthwalker (o antigo mapa da cidade murada) foi adicionado de volta ao jogo e pode ser explorado através dos menus warp! nota: isso não substitui a cidade murada e existe separadamente
  • os menus "iniciar jogo" agora permitem que você especifique a configuração do mapa a ser usada, quando aplicável. em alguns casos, eles podem configurar o nível de forma diferente (veja abaixo)
  • um truque para combustível de snowbike CRF / GP infinito foi adicionado - use isso com o acima (iniciar o jogo -> planícies douradas -> configuração do mapa 6) para gerar uma moto de neve e freeride pelo deserto até o conteúdo do seu coração!
  • uma opção de depuração adicional foi adicionada para imprimir os endereços / coordenadas do jogador / auxiliar,
  • os santuários krazoa nos menus warp foram renomeados (esperançosamente com precisão)
  • o truque do feitiço do portal foi corrigido (não consigo ler)
  • o teste de som agora traduz o ID do som para um ID SFX.bin ou MPEG.bin
  • moveu alguns alternadores em um submenu "configurações", e removeu o inicializador do menu de opções, já que o menu principal do jogo agora oferece esta funcionalidade
 


Sulu

Supra-sumo
Mensagens
1.014
Reações
130
Pontos
154
Visualizar anexo 192031

Patch de correções para o Dinossaur Planet

dinopatch v2.4 dead dino edition

https://www.dropbox.com/s/ugtwdybv8ag20lm/dinopatch_v2.4.xdelta

novo nesta compilação:

  • o menu principal do jogo foi restaurado! e com ele, o menu de opções está finalmente acessível pelos meios normais! as mesmas opções que funcionavam anteriormente no dinomod também funcionarão via dinopatch a partir desta compilação (widescreen, posição, áudio, exibição)
  • o klanadack agora pode ser derrotado! o jogo vai jogar a cena da vitória, premiar a pedra mágica e transportá-lo de volta para a cidade murada como (principalmente) pretendido
  • derrotar galadon não o joga mais no vazio e premiar corretamente a pedra mágica
  • a música da fase um do galadon foi corrigida, junto com muitas outras trilhas em minas darkice
  • a cutscene de introdução do galadon foi melhorada, o gelo agora quebra corretamente e a pedra mágica é animada
  • a correção de coleta de item foi retrabalhada para mitigar problemas de estabilidade para algumas pessoas
  • alguns ícones de inventário de pedra mágica foram corrigidos, incluindo o ícone de pedra mágica klanadack (anteriormente um CRF gema da sala de energia)
  • lightfoot enjaulado em cape claw não usa mais o modelo do lightfoot chefe
  • as configurações pertencentes ao menu de opções são carregadas na inicialização para evitar a necessidade de entrar no menu de opções cada vez que o jogo é iniciado
dinomod v2.4 "one hour video edition "

https://www.dropbox.com/s/xjiwmr21c6uvxq5/dinomod_v2.4.xdelta

novo nesta compilação:
  • todos os itens acima do dinopatch v2.4, mais ...
  • o jingle de retirada de item antigo, conforme ouvido no vídeo de 1 hora, agora pode ser ativado opcionalmente! esta configuração é armazenada no savegame.
  • o templo earthwalker (o antigo mapa da cidade murada) foi adicionado de volta ao jogo e pode ser explorado através dos menus warp! nota: isso não substitui a cidade murada e existe separadamente
  • os menus "iniciar jogo" agora permitem que você especifique a configuração do mapa a ser usada, quando aplicável. em alguns casos, eles podem configurar o nível de forma diferente (veja abaixo)
  • um truque para combustível de snowbike CRF / GP infinito foi adicionado - use isso com o acima (iniciar o jogo -> planícies douradas -> configuração do mapa 6) para gerar uma moto de neve e freeride pelo deserto até o conteúdo do seu coração!
  • uma opção de depuração adicional foi adicionada para imprimir os endereços / coordenadas do jogador / auxiliar,
  • os santuários krazoa nos menus warp foram renomeados (esperançosamente com precisão)
  • o truque do feitiço do portal foi corrigido (não consigo ler)
  • o teste de som agora traduz o ID do som para um ID SFX.bin ou MPEG.bin
  • moveu alguns alternadores em um submenu "configurações", e removeu o inicializador do menu de opções, já que o menu principal do jogo agora oferece esta funcionalidade
Ótima notícia!

Não estou acompanhando o trabalho da cena no jogo.

Há chance de ele ficar jogável do começo ao fim algum dia?
 

Warrior Of Light

Bam-bam-bam
Mensagens
998
Reações
3.283
Pontos
283


Eu não sou de ficar fazendo “resposta” a vídeos ou coisas do tipo, mas esse cara fez um vídeo cheio de desinformação a respeito do Nintendo 64, além disso, fica debochando de quem discorda, onde o mesmo tira print de comentários e posta na comunidade do YouTube para que a fã base dele debochem também, e não é a primeira vez que isso acontece.

Sobre o vídeo, o que ele fala está em vermelho e a resposta em negrito logo abaixo.

“A Rare propôs então fazer um jogo de luta pro Arcade e a Nintendo aceitou na hora, o resultado dessa proposta é um game que você já deve conhecer, o Killer Instinct, e na abertura desse game a gente vê bem grandão escrito Ultra 64 e aí que começa a grande mentira da Nintendo, antes de se chamar Nintendo 64 o console de 64 Bits tinha o nome provisório de Ultra 64, o Killer Instinct era um espetáculo audiovisual e ao colocar o Ultra 64 na abertura do game a Nintendo queria convencer o mundo de que ali dentro teria a mesma tecnologia que os consumidores receberiam em casa no futuro console, só que vimos que isso foi pura conversa fiada, uma mentira daquelas de que se o Pinóquio tivesse contado o nariz de madeira dele daria volta ao mundo.”

Aqui dá pra ver que ele não sabe as especificações técnicas do Arcade Ultra 64 da Rare e nem do Nintendo 64 (ele se baseou somente na PCB e no preço e tirou conclusões precipitadas de que o N64 era muito inferior ao Arcade).

“Killer Instinct é um jogo de 94 e em 94 o Nintendo 64 simplesmente não existia ainda, o novo videogame da Nintendo era um projeto ultra secreto que naquele ponto era um esboço de um protótipo, mas a Nintendo não poderia perder a chance de criar um hype monstruoso pro seu futuro console com aquele videogame e eu sei o que você agora está se perguntando o quê que tinha dentro do hardware da máquina de Killer Instinct se não era de fato o Ultra 64.”

O Nintendo tinha uma arquitetura muito superior ao Arcade Ultra 64, tirando o tamanho de memória dedicada para o jogo, que no caso do Arcade tinha 9 chips de ROM (para o código e som do jogo) que neste caso não eram grandes coisas, mas contava com um HD enorme para armazenar a parte gráfica (FMVs e Sprites), contra 1 cartucho com muito menos memória disponível para o jogo, impossibilitando completamente o uso de FMVs (que possuem tamanhos enormes) e Sprites na mesma qualidade (onde eram usadas texturas pequenas de baixa resolução devido ao pouco espaço da ROM), pelo menos até o momento.



“O hardware do arcade custava mais de 5 mil dólares e era uma versão simplificada e modificada de uma estação gráfica da Silicon Graphics que usava o processador r4600 rodando a 100MHz e um processador de som, a DCS 2150 e ainda contava com memória interna em abundância e ainda usava um HD para carregamento rápido de arquivos de vídeo, os que que eu estou falando os vídeos dos cenários do game que eram vídeos tocados pra frente e pra traz em tempo real de acordo com a posição de jogador na tela”

Mas é claro que o Arcade custava isso, somente o gabinete enorme de madeira totalmente personalizado era uma fortuna, tirando que dentro dele tinha um monitor, moldura, sistema de fichas, alto falantes, fonte, tampas de ventilação, interruptor liga/desliga e outros componentes (mais a PCB obviamente).

Por isso não faz sentido pegar o preço do Arcade Ultra 64 para compará-lo ao preço do Nintendo 64 como justificativa de ele ser tecnicamente superior em Hardware por causa da diferença de valores.

Nem quando ele falou sobre “a memória em abundância” ele acertou, pois os chips de ROM eram 512KB para o código (Boot-ROM) e 8 pentes de 512KB dedicados para o som do jogo (Sound-ROMs), totalizando 4.5MB.


A única coisa que ele acertou aqui foi quando ele menciona as informações sobre o HD e os vídeos usados nos cenários. Mas deixou de falar uma informação muito importante, o tamanho do HD, que era de 131MB (89.5MB usados) para o Killer Instinct e 420.8MB (125MB usados) para o Killer Instinct 2.

Isso foi CRUCIAL para a diferença gráfica entre a versão do Arcade para o Nintendo 64, que contava com uma ROM de apenas 12MB para tudo, um cartucho desse tamanho jamais comportaria aquelas FMVs (que eram enormes) e replicar os mesmos sprites, como mencionado anteriormente, a saber o cartucho de Killer Instinct Gold tinha quase 11 vezes menos memória para dedicar ao jogo se comparado ao Killer Instinct 2.

“Eu não sei se você já viu uma placa de Nintendo 64, mas na tela tem as duas lado a lado, a esquerda tem a placa do Nintendo 64 e a direita tem a placa do Killer Instinct, placas completamente diferentes, com componentes diferentes e sem nenhuma compatibilidade entre elas, definitivamente não tinha o Ultra 64 dentro do gabinete de Killer Instinct, mentira da Nintendo, mentira da Nintendo.”

Aqui ele está certo sobre falar a respeito dos componentes diferentes, mas ele deveria ter mencionado que as CPUs eram da mesma família, inclusive a do Nintendo 64 era uma versão pareada com a usada no Arcade Ultra 64, além do RCP (RSP para ser mais específico) ter sido baseado na CPU R4000 (mas com uma unidade vetorial), que também foi uma CPU usada no SGI Indy.


“Mas essa foi uma mentirinha light, pois hardwares passam por revisões, dois anos separam o hardware do Nintendo 64 do Ultra 64 do Arcade, literalmente ficariam diferentes de qualquer forma pelo simples fato da evolução da tecnologia, mas essa mentirinha iria se transformar numa mentirona daquelas bem cabeludas.”

Sim, hardwares passam por revisões e a tecnologia evoluiu, esse é o motivo pelo qual o hardware do Nintendo 64 ter ficado superior ao Arcade Ultra 64.

“O processador do hardware do Killer Instinct, o R4600 era o mesmo processador de uma estação gráfica da Silicon chamada Indy, o Indy custava cerca de 40 mil dólares na sua época e não era uma estação High-End bilonga das galáxias, mas era o que a Rare tinha para trabalhar.”

O processador era o mesmo, mas o restante dos componentes eram muito inferiores, nem GPU para gráficos poligonais tinha (que por si já era um downgrade enorme), além de ter muito menos memória RAM, ou seja, o Arcade do Killer Instinct era muito inferior se comparado ao PC SGI Indy.

Por esse motivo mais uma vez não faz sentido citar o preço como justificativa, outra coisa, o valor que ele disse também está errado, não eram 40 mil dólares, os PCs SGI Indy custavam 5 mil dólares em sua versão mais simples, enquanto em sua versão mais avançada custava 23,700 dólares.


O Nintendo 64 por sua vez não usou o Indy como uma máquina de desenvolvimento, ele usou uma outra estação gráfica chamada Onyx e dependendo da configuração e do tempo de uso custava entre 100 mil e 250 mil dólares em 95, a Onyx era considerada como um Super Computador que calculava modelos tridimensionais de terrenos, tinha até usos militares e era coisa fina, a Onyx era uma máquina tão poderosa que conseguia rodar máquinas virtuais e por isso foi escolhida como ferramenta para desenvolvimento do N64, ele rodava dentro do Onyx de uma forma emulada o que permitia fazer todos os tipos de estudo e modificações antes da construção do hardware propriamente dito.”

O fato do Nintendo 64 não ter usado o Indy como estação de desenvolvimento era porque o Indy era fraco demais pra desenvolver jogos para o hardware do Nintendo 64, as ferramentas de modelagem 3D eram muito pesadas, somente os super computadores da SGI para dar conta do recado, tanto que os programadores do GoldenEye relataram justamente isso, o que somente colabora com o fato do hardware do Nintendo 64 estar muito a frente do Arcade Ultra 64, que como dito anteriormente sequer tem uma GPU para gráficos poligonais, o que exige uma máquina mais fraca para desenvolver um jogo como Killer Instinct (kits de desenvolvimento mais leves voltados para gráficos bidimensionais), pois o mesmo só tem FMV e Sprites. Mas nada de polígonos, iluminação, filtros, correções gráficas e vários efeitos como no Nintendo 64.

Outra coisa, ele falou sobre o SGI Onyx rodar o Nintendo 64 de forma emulada, o que não é verdade, os caras da Rare durante o desenvolvimento de GoldenEye disseram que para renderizar os gráficos poligonais o Nintendo 64 era muito mais rápido que o SGI Onyx, um cenário do jogo era renderizado em 2 FPS no Onyx, mesmo sem inimigos, objetos e sem a arma do Bond. Desde quando o SGI Onyx conseguiria emular o Nintendo 64, sendo que ele era até mais lento que o mesmo para renderizar gráficos em 3D. O SGI Onyx poderia ser ótimo em em muitas outras coisas, mas não em renderizar gráficos poligonais em tempo real.


>> I mentioned we didn't have an N64 or anything like one. The closest we had was an SGI Onyx or two. Thankfully, as it turned out, the N64 could render triangles much faster than the SGI Onyx. This was shocking as the list price of the Onyx was $250K dollars, and the N64 launched for about 1000th of this price. That's progress. And it totally saved us, as several of the backgrounds rendered at about 2Hz (2 fps) on the Onyx, without even drawing enemies, objects, or Bond's gun. My attitude was always, well, if it runs at all on the Onyx, we can probably get it to run at about 30Hz on the final hardware. <<<
Todas as tech demos por exemplo, eram scriptadas, nenhuma rodava com aqueles gráficos em tempo real, tudo era pré-renderizado. Talvez esse seja o motivo do pessoal da Rare não ter ficado impressionado com as tech demos.


>> The team decided to take Bond ‘off the rails’, though knowing exactly what the N64 was capable of required a good deal of faith. Its development system used high-end Silicon Graphics machines, a pleasure to work with, if prone to overheating, whilst the specifications of Nintendo’s forthcoming console were yet to be finalised. “I vaguely remember being disappointed seeing the tech demos running on the first development consoles,” admits Mark. “But once our own artists got going onto the project, they managed to make the graphics look good! <<<

Se você pegar as tech demos de fato, não tem nada de outro mundo, como exemplo vou pegar a mais famosa.



Esse tubarão nadando e o avião sobrevoando no deserto mostrados no vídeo são fracos em geometria e texturização, e também só estão rodando de forma fluída porque não estão sendo processados em tempo real, mas rodando por script.

Vou colocar aqui 2 exemplos do Nintendo 64 fazendo fases semelhantes a essas 2 tech demos, mas com geometria mais complexa, texturas melhores e rodando em tempo real.

Banjo Tooie



Donkey Kong 64



Aero Fighters Assault



Star Wars: Rogue Squadron



Se quiser conferir como a tech demo do tubarão roda em tempo real tem a demonstração, o desempenho é doloroso, dá pra ver os wireframes também.




“Você acredita em mágica? Eu te pergunto isso porque a gente sabe que o Nintendo 64 chegou em 96 custando apenas 200 dólares, e se o hardware do Ultra 64 o Arcade custava alguns milhares de dólares os engenheiros da Nintendo tiveram que fazer alguma feitiçaria interdimencional nível doutor estranho para chegar nesse valor de 200 dólares para o consumidor, se não teve feitiço teve muita engenhosidade, inteligência e um corte de custos tão violento que impactou diretamente na capacidade do que o Nintendo 64 seria capaz de fazer, isso é normal, é assim que cortes de orçamento funcionam, trocam presunto por apresuntado e a vida segue, dona Nintendo sabia muito bem o que que estava rolando, ela sabia que o corte de custos sacrificou capacidade técnica, só que ela escolheu não revelar essa informação ao público, ela convenientemente escolheu fingir que continuava tudo como antes conforme o nome Ultra 64 do Arcade indicava na abertura do Killer Instinct.”

Só que no caso eles trocaram apresuntado por presunto, e ao invés de fazer um hardware mais fraco que o Arcade Ultra 64 a Nintendo entregou algo muito melhor.

Arcade Ultra 64 - Killer Instinct 1/2

CPU: R4600 @100MHz (mas opera somente em 50MHz pelo barramento)

>> The R4600 had 16 KB two-way set associative caches for instructions and data. It supported an L2 cache, but has no on-die hardware to control it, requiring external logic, whether it be a custom application specific integrated circuit (ASIC) or chipset, to the cache. The SysAD bus is 64 bits wide and can operate at clock rates up to 50 MHz for a peak bandwidth of 400 MB/s. The R4600's external interface did not support multiprocessing<<<
Taxa de transferência: 400 MB/s
Cachê: 16kb (instruções) / 16kb (dados)
Barramento: 64 Bits
MFLOPS: 44 (R4600 em 133 MHz)
GPU/PPU: Gráficos 2D
Cores: 32.768
Resolução: 320x224
HD: 130 MB em KI / 420 MB em KI2 (FMV’s e Sprites)
ROM: 4.5MB (9 pentes de 512 KB para código e som)
Memória RAM: 4 MB DRAM (4 pentes de 1 MB)
Tempo de resposta: 60-80ns (quanto maior o número de nano-segundos mais demorado)

SPU: ADSP 2105 @10MHz (DCS Sound System)
Sample Rate: 32 KHz
Canais de som: 4 canais em 16 Bits Mono





Arcade Ultra 64 (Cruis’n USA)

Processador: TMS32031 @50 MHZ
Barramento: 32 Bits
GPU: V-Unity VLSI
Resolução: 512x400
Polígonos/quads: 54 mil em 30 FPS com correção de perspectiva apenas
ROM: 14MB
SPU: ADSP 2105 @10MHz (DCS Sound System)
Sample Rate: 32 KHz
Canais de som: 4 canais em 16 Bits Mono



198401

Esse mesmo arcade do Cruis’n USA (Ultra 64) era chamado de Midway V-Unity e seu último upgrade foi no Arcade do War Gods (protótipo de Mortal Kombat 4), sendo a versão mais avançada dentre todos os Arcades “Ultra 64”. Pois além de possuir a GPU V-Unity VLSI eles também melhoraram o chip sonoro, que agora possui uma versão mais avançada do DCS Sound System, o ADSP 2115 que roda em 16MHz e conta com dois DACs controlados por DMA, com saída em Stereo, além de contar com um HD de 400 MB.



Ironicamente War Gods roda muito melhor no Nintendo 64, assim como o sucessor de Cruis’n USA, o Cruis’n World, que além de ser tecnicamente mais avançado que seu antecessor também roda melhor no Nintendo 64 (mais à frente os dados a respeito de ambos os jogos).

Trechos de reviews do Wars Gods

>> War Gods was originally an arcade game, and despite the hype surrounding its initial release it never quite lived up to what fans of the genre were expecting. Midway, aware of this fact, recalled parts of the development team in hopes of improving upon the game for the Nintendo 64 port and for the most part it was successful.

Two major flaws plagued the arcade version: Horribly bad AI (Artificial intelligence) and choppy gameplay. The Nintendo 64 version improves on both, but certainly doesn't conquer either feat. While the AI in the N64 port is arguably better, it seems oddly unbalanced and often discouraging. For example, even on the easiest level of challenge the opponents are often cheap, effortlessly throwing everything they've got at you. We appreciate a balanced match as much as the next guy, but when your character can be killed off in a few seconds flat it's hard to keep up a healthy degree of optimism. <<<
>> While both the Nintendo 64 and PlayStation versions benefit from these improvements, only the N64 game boasts the supercharged, antialiased visuals we've come to expect from the system. Projectile attacks-although they're still 2-D-looking bitmaps-no longer look as pixelated as they did in the arcade and PlayStation versions. And the arenas look especially spectacular. Hie war gods themselves appear fairly faithful to the arcade original's motion-captured combatants, except for the occasional few frames of choppy animation (noticeable when one warrior throws another). <<<
Reviews de Cruis’n World


198408

198409

Nintendo 64

Processador: VR4300 @93.75 MHz
Taxa de transferência: 250 MB/s entre a CPU e RCP (não tem DMA e quem acessa a memória diretamente e transfere os dados é o RCP)
Cachê: 16KB (instruções) / 8KB (dados)
Barramento: 32 Bits
MIPS: 125
MFLOPS: 93
GPU: RCP (RSP+RDP) @62.5 MHz
Taxa de transferência: 1GB/s / mas provavelmente 500 MB/s (se considerar a velocidade do clock)
Barramento: 128 Bits
Cores: 32.768 simultâneas
Resolução: 320x240 / 640x480 (480i)
Polígonos por segundo: 100 mil com todos os filtros e correções gráficas (Fast 3D)

600 mil sem nenhum filtro ou correções gráficas (Turbo 3D)

300 mil sem Z-Buffer e com AA (dependendo do micro-código)

198410

Memória RAM: 4MB / 8MB (com expansão) RDRAM (RAMBUS)
Tempo de resposta: 50-70ns
Taxa de transferência: 500 MB/s

Processador e chip sonoro: N/A (feito por software) com suporte a ADPCM, MIDI, MP3, Tracker
Sample Rate: 44/48 KHz
Canais de som: 100 canais PCM em 16 Bits Stereo com cada canal usando 1% da CPU (Driver de som inicial) com 16/24 canais usados na prática.

Driver de som MusyX (Factor 5): 20/32 canais em 16 bits Stereo com áudio Redbook (som de CD), Músicas dinâmicas (MIDI) ou outros formatos sonoros com suporte a Dolby Surround Sound e com número de vozes limitados apenas pelo hardware, entre vários outros recursos, usando 0.7/0.9% da CPU e 0.7/0.8% do RSP por voz ativa dentro de uma configuração ideal.



ROM de Killer Instinct Gold: 12MB

ROM de Cruis’n USA: 8MB

Para deixar registrado vou deixar aqui as especificações de um PC mediano da SGI (nem vou colocar outras versões mais obsoletas como o Indigo 2 “cru” ou o Indigo 2 XL).

Indigo 2 XZ

CPU: R4000 @100MHz
Taxa de transferência: 400 MB/s (CPU e memória) e 267 MB/s (I/O)
Cachê: L1 (16 KB) e L2 (expansão para 1MB)
Barramento: 64 Bits
Memória RAM: 8 MB (expansão para 384 MB)
MIPS: 85
MFLOPS: 16
GPU: 2 GE7 Geomety Engine (sua versão mais recente utiliza 4 GE7 Geometry Engine)
MFLOPS: 64 com 2 GPUs e 128 com 4 GPUs (32 MFLOPS cada GPU)
Rasterizador: REX3 @50 MHz
Cores: 24 Bits por pixel (16.7 milhões de cores)
Resolução: 1280x1024 (Super XGA)

Polígonos por segundo: 250 mil sem textura (Flat Shaded), sem Z-Buffer e com pintura de malhas (Mesh Colors)


“Nos Estados Unidos tem um evento tradicional chamado Consumer Electronics Show (CES), é uma feira enorme daquelas que as empresas mostram as suas novidades para o mercado, na edição de 94 ainda a Nintendo fez demonstrações de dois jogos supostamente do Ultra 64, mas fez isso a portas fechadas só para um público selecionado, um desses jogos advinha, era o Killer Instinct e o outro era o Cruis’n USA, um jogo de corrida, quem viu os jogos aquele dia saiu do estante da Nintendo impressionado com que o Ultra 64 era capaz de fazer, só que o detalhe é que tudo isso era fake news, a Nintendo teve a cara de pau de mostrar os jogos do Arcade rodando no hardware do Ultra 64 que sequer existia ainda, uma mentira de proporções épicas, a Nintendo tentando enganar todo mundo, tentando fazer pose de que tinha algo pronto em mãos que na verdade não tinha, lembra daquela situação de alguém de aluga uma Ferrari e posta foto nas redes sociais só pra pagar de rico e fazer pose, mas o que levaria a Nintendo a agir dessa forma, porque obviamente as pessoas iriam sacar a mentira eventualmente, eu só consigo pensar que foi uma tentativa de manter o interesse das pessoas no seu futuro projeto no memento que ela já não tinha nada para mostrar, já que estava super atrasada em relação aos concorrentes, especialmente ao PlayStation da Sony, a Nintendo se viu acuada em posição de desvantagem no mercado, ela não sabia exatamente o que fazer e acredito que ela fez isso confiando que poderia entregar o que foi prometido, apesar da grande mentira momentânea e talvez ela conseguisse escapar sem ser pega se o projeto não estivesse demorado tanto pra ficar pronto e se no lançamento do Nintendo 64 Killer Instinct e Cruis’n USA estivessem presentes e fossem iguais ao que estivesse sido demonstrado naquela CES, só que nada disso aconteceu, em junho de 96 no Japão os games de lançamento foram Super Mario 64, Pilotwings e Saikyō Habu Shōgi, em setembro de 96 nos Estados Unidos apenas Super Mario 64 e Pilotwings 64, estranho né? Se Killer Instinct estavam prontos desde 94 porque não estariam presentes logo no primeiro dia do console no mercado, no entanto o Nintendo 64 recebeu o Killer Instinct, o Killer Instinct Gold em novembro de 96 e o Cruis’n USA no mês seguinte e nenhuma dessas versões desses jogos é igual as versões dos Arcades e bla bla bla.”

Só que ela entregou o prometido e foi além, como mostrado nas especificações técnicas de cada Arcade Ultra 64 e do Nintendo 64.

Killer
Instinct é um jogo 2D no Arcade, que conta com 129.5 MB de memória para os gráficos, sons e código, comparado ao Nintendo 64 que por sua vez tinha uma ROM de 12 MB pro Killer Instinct Gold, ou seja, quase 11 vezes menos de memória pro jogo (como dito anteriormente), pra fazer igual tinha que ter uma ROM bem maior pra comportar todas as FMVs e Sprites (usando texturas maiores de 64x64 ou 64x128) para ficar na mesma qualidade. Cruis’n USA a mesma coisa, no Arcade o jogo conta com uma ROM de 14 MB contra 8 MB no Nintendo 64, contando com quase 2 vezes mais memória disponível pro jogo. Mas o que mais prejudicou a versão de Nintendo 64 foram as censuras (que estão sendo completamente removidas por alguns hackers), se quiser os Patchs pra deixar a versão o mais fiel possível ao Arcade.


No caso de Killer Instinct 2 bastava uma ROM do mesmo tamanho do Arcade para os FMVs, e usando micro-código o resultado seria MUITO melhor. A saber, existem 2 micro códigos específicos para gráficos 2D, e 1 deles é o S2DEX que foi usado em Yoshi Story, infelizmente Killer Instinct Gold não usou de nenhum desses micro-códigos para gráficos 2D. Então é muito fácil olhar para uma tela comparativa sem saber os detalhes técnicos a fundo e sair tirando conclusões sem embasamento, desse jeito fica muito fácil comparar jogos.


Mas é bom mostrar na prática (além de mostrar no papel) que o Nintendo 64 rodou jogos dos mesmos Arcades “Ultra 64” com qualidade superior, como em War Gods e em Cruis’n World (continuação de Cruis’n USA).

Na verdade esses jogos são tecnicamente muito simples para os padrões do Nintendo 64, tanto War Gods como Cruis’n World não exigem muita coisa, bastou capricharem mais nos portes para superarem suas versões de Arcade “Ultra 64” sem grandes esforços, pois sequer usaram micro-código e ainda possuem ROMs minúsculas, War Gods até HD de 401.4 MB possui (55.8 MB usados).


Ou basta comparar com jogos avançados do Nintendo 64 de ambos os gêneros (corrida e luta) para ver a diferença estratosférica, como no caso de Mace: The Dark Age, que se parece com jogo de outra geração se comparado ao War Gods, o mesmo vale pro World Driver Championship e Stunt Racer 64 se comparados ao Cruis’n World, até mesmo se comparados ao Cruis’n Exótica, chega a ser até covardia fazer esse tipo de comparativo.







Não tenho nada contra esse YouTuber, mas o cara não se dá ao trabalho de fazer uma pesquisa aprofundada para falar sobre o assunto, e o vídeo tem 110 mil visualizações, enchendo a cabeça de muitos com vento, e o pior é que ainda acha que está passando informações corretas, complicado.
 
Ultima Edição:

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303
Eu sinceramente não sei o que acontece com esses youtubers, aproveitam a popularidade do canal para soltar matérias equivocadas no calor da emoção , não sei se é para causar polemica ou sei lá , os ultimos meses eu tenho visto muitos videos nesses estilo ai, inclusive sobre o porte do Resident Evil 2 também que disseram que foi facil como zipar em modo ultra com winrar kkk

Muito bem colocado o time do Goldeneye fez o jogo sem saber se o hardware do N64 ia dar conta, as proprias estações não conseguiam rodar o jogo com a fisica e tudo mais realmente, eles deram graças quando o N64 chegou para eles, só tiveram que reduzir as texturas mesmo.

Olha agora que essa informação esta ai revelada, vendo uma materia aqui escrita por uns dos funcionário da Silicon Graphics mostra como os engenheiros conseguiram a proeza de reduzir os chip em tamanho menor mantendo os recursos e entregando um clock maior no final, então no final, entregaram mais do que prometeram realmente, segue na integra a materia traduzida eu marquei as partes mais importantes


PROJECT REALITY

23 de agosto de 1993. A indústria de eletrônicos de consumo sintonizou-se quando a SGI e a Nintendo anunciaram uma parceria para construir a máquina de jogos mais poderosa do mundo. Falando para uma multidão de analistas, mídia de notícias e especialistas da indústria, Jim Clark delineou um projeto ambicioso, Project Reality, que revolucionaria a indústria de eletrônicos de consumo. Sem ser de subavaliação, Clark declarou que o Project Reality aproveitaria o “poder computacional combinado de centenas de PCs” por menos de $ 250. Os especialistas estavam convencidos de que a potência da SGI / Nintendo poderia entregá-lo. Então, aparentemente, estavam os analistas - as ações da 3DO caíram US $ 4 naquele dia em negociações pesadas - e crianças ao redor do mundo, levadas ao frenesi pelos relatos brilhantes na mídia, começaram a fazer lobby com seus pais por seus presentes de Natal de 95. Por todas as indicações, O Project Reality seria um tremendo sucesso. Restava apenas uma pequena tarefa - construí-la. Preparar. Definir…

O plano exigia que a SGI desenvolvesse dois chips que seriam o coração do sistema: o R4300i e o Reality Coprocessor (RCP). O R4300i, a CPU MIPS RISC de baixo custo e baixo consumo de energia, lidaria com a interação com o jogador e administraria as tarefas de controle do jogo. O RCP, o mecanismo de processamento de mídia, lidaria com todas as tarefas gráficas de alto desempenho e síntese musical. A equipe do R4300i já estava instalada no MIPS e composta por engenheiros experientes. No entanto, a equipe do Project Reality, que projetaria o RCP e escreveria o software, teve que ser construída do zero.
“Só contratar superestrelas” era a ordem de Wei. O pessoal estava indo mais devagar do que o esperado e isso era uma tarefa difícil. Surpreendentemente, o recrutamento interno foi difícil. Muitas pessoas dentro da SGI suspeitaram do hype em torno do projeto. “Gráficos de calibre Onyx e síntese musical em uma caixa de US $ 250? Você está louco ”, vieram os protestos. “Pode ser, mas é isso que vamos fazer”, foi a resposta da equipe. A maior parte da equipe inicial do Project Reality, com exceção de alguns veteranos exaustos, veio de fora da SGI.
Com poucas pessoas a bordo, os membros da equipe do Project Reality desempenharam muitas funções no outono e inverno de 93. Logic designers tornaram-se administradores de sistema, o pessoal de software escreveu verilog e Gudrun, ostensivamente o Admin, escreveu microcódigo. Mas, um por um, atraídos pela perspectiva de projetar um sistema que enviaria milhões de unidades por ano (a Nintendo já vendeu 100 milhões de unidades até agora), os principais designers de hardware e software se inscreveram. Quando o inverno se transformou em primavera, a equipe atingiu a massa crítica e tudo começou a se encaixar. O plano do produto se cristalizou e o primeiro marco ficou claro: RCP Tapeout 1.0.


O caminho para a primeira fita para fora

RCP Tape Out 1.0 não deveria ser uma saída de fita normal. Não apenas o projeto RCP de 2,4 milhões de transistores deveria ser concluído, mas o microcódigo de áudio e gráfico deveria ser escrito, simulado e testado com o verilog. Em outras palavras, virtualmente todo o sistema deveria ser desenvolvido para garantir que o chip funcionasse conforme necessário.
O verão de 94 viu alguns sucessos significativos, já que as madrugadas e o trabalho árduo começaram a dar frutos. O primeiro ponto amostrado do polígono sombreado suave foi gerado pelo simulador RCP C. O microcódigo de conversão da taxa de amostragem de áudio foi concluído. O design do chip estava bem encaminhado. As coisas pareciam estar indo bem. Seja o produto da visão inspirada ou as corridas de hambúrguer habenero, a equipe teve o "fogo na barriga".
Naquele verão também ocorreu o primeiro lançamento do ambiente de emulação Project Reality. Como o sistema real não estaria disponível até a primavera de 95, a equipe projetou um software que rodava em um Onyx com um Reality Engine que permitia à Nintendo e desenvolvedores importantes como Rare e DMA começarem a trabalhar em seus jogos.
Foi só em outubro de 94, com os prazos finais da fita se aproximando, que as dúvidas que os projetistas do RCP vinham guardando para si próprios chegaram à superfície; o chip era muito grande! Para cumprir as metas de custo, o RCP tinha que ser menor do que um tamanho específico e, embora os projetistas estivessem levando as ferramentas de design ao limite, parecia que o RCP iria perder sua área-alvo por um longo tiro.

Em 10 de outubro, uma reunião crítica foi convocada para discutir as opções. Cortar a unidade do vetor pela metade? Isso destruiria o desempenho. Cortar a memória cache? Isso prejudicaria o microcódigo gráfico que já estava usando cada bit de memória de instrução disponível. Ore para que os projetistas consigam, de alguma forma, enganar as ferramentas, fazendo com que façam o que até mesmo os fornecedores de ferramentas acreditavam que não poderiam fazer? Com o primeiro teste de fita programado para daqui a pouco mais de um mês, as alterações no design do chip seriam impossíveis de implementar, muito menos testar, a tempo. A terceira opção era a única viável; vá em frente e confie nos designers para encontrar uma maneira.
Enquanto os projetistas do chip RCP estavam ocupados reduzindo a área e completando a planta baixa do nível superior, a equipe de software trabalhava arduamente na ingrata tarefa de verificar o chip (não normalmente uma tarefa de software) para se certificar de que não haveria falhas. Afinal, o RCP seria enviado em dezenas de milhões de sistemas.

No final de 1994, o tempo estava se esgotando. Para enviar sistemas para o Natal de 95, tanto o RCP quanto o R4300i precisaram ser retirados com fita adesiva muito em breve. Felizmente, a equipe do R4300i cumpriu o cronograma e concluiu sua fita no início de dezembro. A equipe RCP não teve tanta sorte. Com o feriado se aproximando, a equipe RCP estava trabalhando quase sem parar para terminar o design do chip para que a NEC pudesse começar a fabricar os protótipos que seriam integrados aos sistemas de desenvolvimento. Pessoas com planos de folga na semana de Natal os cancelaram. Alguns dos principais membros da equipe chegaram no dia de Natal. Todos perceberam que as apostas eram altas.
No final de janeiro de 95, a equipe estava exausta. Trabalhar à noite e fins de semana longe da família e amigos estava começando a cobrar seu preço. A tensão da fita adesiva aumentava a cada dia que passava. Finalmente, em 24 de fevereiro de 1995, a gravação foi concluída. E isso significava ...


FESTA!

E que festa! Depois do brinde e do discurso obrigatório da gerência, dois engenheiros sumariamente batizaram o diretor com a banheira de água gelada, começando o que poderia muito bem ser a celebração interna mais úmida da história da SGI. Por alguma feliz coincidência, uma das salas de conferência próximas continha um monte de balões, que foram rapidamente colocados em serviço para a mãe de todas as lutas de balões de água. Depois de encharcar completamente os membros da equipe e não alguns espectadores inocentes, a equipe decidiu compartilhar a celebração com outras pessoas. Embalando tubos de balões de água, a equipe invadiu o prédio 10, onde em um clarão de glória, emboscou um desavisado Wei Yen.

Levantar a questão

Com o design do chip a caminho da fábrica, muitos dos designers de chips finalmente tiraram uma folga. Enquanto isso, a equipe de software estava ocupada se preparando para a introdução do sistema. Com o silício funcional da equipe do R4300i em mãos, os engenheiros de software do sistema operacional colocaram parte do kernel em funcionamento. Tudo estava pronto para a chegada dos chips RCP.
Os chips RCP estavam programados para voltar na terceira semana de abril e a Nintendo queria mostrar os sistemas de demonstração três semanas depois no show da E3. Ia ser apertado. Apertado, mas não impossível. Na verdade, funcionou como um relógio:
  • Terça-feira, 18 de abril: Os chips RCP não testados chegaram ao aeroporto de São Francisco vindos da NEC. Naquela noite, ele estava funcionando - e passando - em alguns testes preliminares do sistema.
  • Quarta-feira, 19 de abril: o acesso RDRAM foi obtido e o buffer de quadros foi exibido na TV.
  • Quinta-feira, 20 de abril: O primeiro triângulo foi processado pelo RCP Display Processor.
  • Sexta-feira, 21 de abril: O processador de sinais RCP passou nos testes.
  • Sábado, 22 de abril: O primeiro miniaplicativo animado de triângulo saltitante foi executado no sistema.
  • Domingo, 23 de abril: O primeiro aplicativo completo estava instalado e funcionando menos de uma semana depois que o primeiro silício pousou nos Estados Unidos.
Durante as duas semanas seguintes, a equipe do Project Reality trabalhou quase o tempo todo com engenheiros da Paradigm Simulation para polir o jogo Cobra da Paradigm, que a Nintendo demonstrou aos principais desenvolvedores e distribuidores em uma suíte de sussurros no show da E3 em 10 de maio.
Pouco antes do show, no entanto, a Nintendo lançou uma bomba - isso atrasaria o lançamento do Nintendo 64 até abril de 96. De acordo com o comunicado à imprensa, a Nintendo queria dar aos desenvolvedores mais tempo para desenvolver seus jogos. Apesar de tudo, a equipe continuou: com o primeiro lançamento de software no hardware real agendado para o início de junho, e a segunda fita lançada agendada para meados de julho, não havia tempo a perder.

Fora do laboratório

Quase antes de a poeira da E3 baixar, os sistemas de desenvolvimento foram retirados do laboratório e colocados nas mãos dos desenvolvedores que aguardavam. Graças ao emulador Reality Engine, muitos dos jogos já estavam em produção, mas não há nada como rodar jogos no hardware real para ajustar os sons, imagens e jogabilidade. Com os sistemas de desenvolvimento em mãos, os desenvolvedores podem iniciar esse processo.
Enquanto isso, a equipe de chips estava lutando na batalha da área. No verão de 95, a equipe R4300i juntou-se formalmente à equipe Project Reality com o objetivo de ajudar a reduzir o RCP a um tamanho que melhor correspondesse às metas de custo da Nintendo. Armado com técnicas completas de design customizado e um saco de truques para forçar as ferramentas de design físico a serem submetidas, este grupo trabalhou lado a lado com a equipe de design RCP original para reduzir o tamanho do chip sem comprometer qualquer funcionalidade. Com um pouco de design personalizado aqui, muita otimização de design e magia de ferramentas ali, a equipe foi capaz de atingir a meta de tamanho da matriz. A frequência do clock foi aumentada para o máximo possível para a placa do sistema também!


Tornando isso real

O outono de 95 viu o Nintendo 64 amadurecer do protótipo ao sistema real, conforme a equipe de software otimizou, adicionou recursos, corrigiu bugs e trouxe novos desenvolvedores de jogos à velocidade. O outono de 95 também viu o país começar a ganhar vida fora da SGI.
A máquina de marketing despertou enquanto a Nintendo se preparava para uma apresentação pública em novembro no Japão em seu show Shoshinkai. Embora o Nintendo 64 não fosse lançado até abril, Shoshinkai foi um show importante para a Nintendo. Os principais distribuidores tomariam suas decisões de compra com base no que ouviram e viram lá.
Enquanto o mundo experimentava o poder do Nintendo 64, a equipe SGI experimentava o que significa enviar um produto de consumo. Em novembro e dezembro de 95, a equipe atendeu ao milhão e um detalhes que precisavam ser resolvidos para a produção em massa: vetores de teste de chip, testes de linha de produção, correlação de rendimento de processo, testes de regressão. Não é um trabalho muito glamoroso, de forma alguma, mas um trabalho crucial.
Em 1 de fevereiro de 1996, a Nintendo anunciou o segundo e último atraso. Citando a falta de peças como o principal motivo, a Nintendo declarou que o sistema seria lançado oficialmente em 23 de junho no Japão e em 30 de setembro na América do Norte. Mas seria revelado no show E3 em maio, no Centro de Convenções de Los Angeles.
Nos dois meses seguintes, a equipe SGI trabalhou nos detalhes finais da produção em massa enquanto os desenvolvedores davam os toques finais em seus jogos e os enviavam para a Nintendo para teste de estresse. Finalmente, na primeira parte de maio, tudo estava pronto para o show.

E3: Nossa!

A E3 era tudo o que se esperava e muito mais. A revelação oficial ocorreu em uma coletiva de imprensa na quarta-feira, 15 de maio. “Acabou, acabou tããão”, babou um membro da imprensa assistindo à demonstração ao vivo de jogos reais no monitor de tela grande. O pessoal da GamerX estava ainda mais entusiasmado:
“Hoje é um dia lindo, principalmente porque acabei de deixar um briefing para a mídia da Nintendo, onde dois veteranos da Nintendo of America lançaram sua maravilha de 64 bits, o Nintendo-64. Tenho que admitir - esse bebê fuma. Com o hardware da Silicon Graphics, sem redução de velocidade do CD-ROM (o N-64, como foi apelidado, usará cartuchos, não CD-ROMs), e vários jogos que parecem ser de primeira qualidade, Sony e Sega tinham melhor cuidado com suas costas. Mal posso esperar para ter alguma experiência prática com jogos como Super Mario 64, que parece absolutamente incrível. E, a julgar pela reação da multidão reunida, ninguém mais pode.
“Deixe-me sem palavras ... Parabéns à SGI e sua implementação de console doce para a Nintendo. Super Mario 64 no Nintendo-64 é uma alegria de se ver, e além de criar uma plataforma que faz o PC parecer um Atari, a SGI trouxe uma nova vida ao processador MIPS sob o capô. Mostra como a localização pode fazer toda a diferença. De repente, o MIPS é mainstream e quente - e não estamos falando de problemas de dissipação de calor, também. ”
Até a mainstream Time Magazine juntou-se à festa. Em um artigo de duas páginas sobre o Nintendo 64 na edição de 20 de maio, Michael Krantz da Time diz
“O que importa é que o Nintendo 64 movido a chip da Silicon Graphics coloca a ação de jogo mais rápida e suave já alcançável via joystick a serviço de um movimento igualmente virtuoso.”
Os participantes da convenção não ficaram menos entusiasmados. Em todos os lugares que você ligava no piso da convenção, as pessoas comentavam sobre a qualidade e a velocidade do Nintendo 64. A espera nas dezenas de consoles do Nintendo 64 foi de meia hora, enquanto jogadores frenéticos faziam fila para experimentar os novos títulos como Super Mario 64, WaveRace 64, PilotWings 64, Star Wars: Shadows of the Empire, Cruis'n USA, Mortal Kombat e Killer Instinct.
E como a equipe se sentiu? Para a maioria dos membros da equipe, o show da E3 foi uma soma: o total emocional de quase três anos de muito trabalho, de amizades, de trabalho em equipe e de crescimento pessoal. E embora ninguém tenha falado sobre isso, cada um provavelmente sentiu - enquanto estavam diante do produto acabado que iria transmitir a soma de suas idéias para o mundo - o sentimento particular de orgulho que, se tivesse palavras, teria dito "Isso é o que eu posso fazer."

fonte:
 


Sony-AMD

Bam-bam-bam
Mensagens
9.296
Reações
9.446
Pontos
338
O canal do Ed é legalzinho, ele é um bom comunicador, só que ele fala para uma audiência (que assim como ele) segue o senso comum, então lá tudo de senso comum será reafirmado, então cartucho é ruim, cartucho é erro etc luta contra as verdades estabelecidas (que na verdade são mentiras estabelecidas) é difícil pois o youtuber seria rapidamente detonado por outros canais e pelos inscritos.
 

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303
Environment Mapping


Em 1996 somente os computadores da Silicon Graphics eram capazes desse recurso que foi mantido também no Nintendo 64

198886

O mapeamento de ambiente (EM) é outro recurso de hardware que não está disponível no Saturn ou no PSX.
Em jogos como Mario, Zelda e Turok é usado com grande efeito, por exemplo. em SM64 EM é usado para fazer Mario parecer um homem de metal tipo T1000 e também para as poças de água metálica. Em Zelda, EM é usado para modelar a armadura reflexiva de cavaleiros e também objetos como espadas, etc. Turok usa EM para as extremidades de estojos de espingarda que têm uma bela aparência dourada, os powerups de saúde rotativos, as peças-chave de nível 8 e em outro lugar. Outros jogos também usam EM, por exemplo. Goldeneye usa para fazer algumas das armas bem metálicas (Magnum, Golden Gun) e para janelas reflexivas, etc.



198888


A imagem acima aqui mostra uma cena do Goldeneye que tem uma sala inteira cheia de telas reflexivas (o nível 'Complexo'); nesta imagem, uma parte da parede cinza tem uma tela reflexiva de cada lado. Mas esta parte específica da sala mostra algo interessante: à medida que nos aproximamos das telas, a tela da direita lentamente se torna transparente, mas a tela da esquerda não fica transparente. Enquanto essa mudança na transparência está acontecendo, ambas as telas continuam refletindo da maneira usual.

198889





Assim, efeitos como EM e transparência podem ser combinados para produzir efeitos mais complexos, permitindo modelar outros materiais, como vidro fumê, espelhos unidirecionais, lagos de água calmos, etc. e de maneiras que podem depender de cada um. distância do objeto visualizado; ou seja, neste caso, a transparência da tela do lado direito só é visível quando se está perto da tela.

Imagine um exemplo mais complexo: um balão inflado, padronizado, transparente, de plástico: o material terá transparência, uma textura para o padrão, um efeito reflexivo porque é feito de plástico (ou pode-se usar apenas iluminação especular), e provavelmente também será sombreado devido a quaisquer fontes de luz presentes - uma grande combinação de efeitos. É claro que combinar efeitos dessa forma exigirá maior computação, portanto, um designer de jogos deve decidir sobre uma compensação entre o realismo visual e a velocidade do jogo. Na prática, a ação em alguns jogos pode estar se movendo tão rápido que não vale a pena usar muitos efeitos especiais, pois o jogador não os notará.

Outro ponto sobre Goldeneye: no nível 'Biblioteca', há uma área onde muitas pequenas salas de 'escritório' têm janelas transparentes, mas as janelas também são parcialmente refletivas. Ao contrário das imagens acima, no entanto, as janelas da área de escritório são dominadas por sua transparência e não por sua refletividade. Isso mostra que um designer pode determinar em que grau os vários efeitos especiais decidirão a aparência final, como eles se combinam e a que distâncias os diferentes efeitos serão proeminentes. É importante notar que é possível ver através de mais de uma janela para uma parede distante, mas ambas as janelas ainda mostram sua refletividade. Do ponto de vista do jogo, também é interessante que o jogo modele adequadamente a presença de várias janelas:e uma marca de bala na parede oposta, tudo corretamente alinhado.


Existem dois tipos de mapeamento de ambiente:

  1. Um objeto é feito para refletir seus arredores, com base na cena textural real em que o objeto está colocado. Este método envolve operações bastante complexas.

  2. Um objeto é feito para refletir uma imagem arbitrária colocando matematicamente o objeto dentro de um cubo ou esfera onde a superfície interna do cubo / esfera é coberta com a imagem a ser refletida. Os cálculos são mais simples neste caso.
Pelo que eu sei, a segunda técnica é frequentemente usada em jogos N64 (por exemplo, nível 8 chave em Turok ), embora eu tenha certeza de ter visto o primeiro método usado também (por exemplo, a sala de espelhos em Mario, embora talvez isso seja feito por outros meios - não posso ter certeza).
A imagem de exemplo mostrada no topo desta página usa a segunda técnica: ela mostra um objeto em forma de espiral refletindo uma fotografia de uma cena de restaurante. Clique na imagem para baixar uma versão muito maior. Abaixo está um exemplo final muito mais claro: quatro visualizações diferentes do chassi do computador SGI O2, refletindo a cena de um restaurante / bar.

198890
 
Ultima Edição:

Ghr

Supra-sumo
Mensagens
802
Reações
1.384
Pontos
183
Offroad Challenge é outro jogo da Midway que poderia estar nessas comparações entre Arcade e Nintendo 64.
O jogo não é grande coisa, mas a versão do Nintendo 64 ficou bem fiel, foi reduzido apenas as texturas dos cenários.
Ta ai um jogo simples que eu gosto demais.
Mesmo eu possuindo um ed64 plus, fiz questão de adquirir o cartucho do offroad Challenge, apesar de ter gráficos fracos e distorcer um pouco igual o play1, acho um jogo super divertido

 

Luke 64

Ser evoluído
Mensagens
187
Reações
130
Pontos
43
Eu sinceramente não sei o que acontece com esses youtubers, aproveitam a popularidade do canal para soltar matérias equivocadas no calor da emoção , não sei se é para causar polemica ou sei lá , os ultimos meses eu tenho visto muitos videos nesses estilo ai, inclusive sobre o porte do Resident Evil 2 também que disseram que foi facil como zipar em modo ultra com winrar kkk

Muito bem colocado o time do Goldeneye fez o jogo sem saber se o hardware do N64 ia dar conta, as proprias estações não conseguiam rodar o jogo com a fisica e tudo mais realmente, eles deram graças quando o N64 chegou para eles, só tiveram que reduzir as texturas mesmo.

Olha agora que essa informação esta ai revelada, vendo uma materia aqui escrita por uns dos funcionário da Silicon Graphics mostra como os engenheiros conseguiram a proeza de reduzir os chip em tamanho menor mantendo os recursos e entregando um clock maior no final, então no final, entregaram mais do que prometeram realmente, segue na integra a materia traduzida eu marquei as partes mais importantes


PROJECT REALITY

23 de agosto de 1993. A indústria de eletrônicos de consumo sintonizou-se quando a SGI e a Nintendo anunciaram uma parceria para construir a máquina de jogos mais poderosa do mundo. Falando para uma multidão de analistas, mídia de notícias e especialistas da indústria, Jim Clark delineou um projeto ambicioso, Project Reality, que revolucionaria a indústria de eletrônicos de consumo. Sem ser de subavaliação, Clark declarou que o Project Reality aproveitaria o “poder computacional combinado de centenas de PCs” por menos de $ 250. Os especialistas estavam convencidos de que a potência da SGI / Nintendo poderia entregá-lo. Então, aparentemente, estavam os analistas - as ações da 3DO caíram US $ 4 naquele dia em negociações pesadas - e crianças ao redor do mundo, levadas ao frenesi pelos relatos brilhantes na mídia, começaram a fazer lobby com seus pais por seus presentes de Natal de 95. Por todas as indicações, O Project Reality seria um tremendo sucesso. Restava apenas uma pequena tarefa - construí-la. Preparar. Definir…

O plano exigia que a SGI desenvolvesse dois chips que seriam o coração do sistema: o R4300i e o Reality Coprocessor (RCP). O R4300i, a CPU MIPS RISC de baixo custo e baixo consumo de energia, lidaria com a interação com o jogador e administraria as tarefas de controle do jogo. O RCP, o mecanismo de processamento de mídia, lidaria com todas as tarefas gráficas de alto desempenho e síntese musical. A equipe do R4300i já estava instalada no MIPS e composta por engenheiros experientes. No entanto, a equipe do Project Reality, que projetaria o RCP e escreveria o software, teve que ser construída do zero.
“Só contratar superestrelas” era a ordem de Wei. O pessoal estava indo mais devagar do que o esperado e isso era uma tarefa difícil. Surpreendentemente, o recrutamento interno foi difícil. Muitas pessoas dentro da SGI suspeitaram do hype em torno do projeto. “Gráficos de calibre Onyx e síntese musical em uma caixa de US $ 250? Você está louco ”, vieram os protestos. “Pode ser, mas é isso que vamos fazer”, foi a resposta da equipe. A maior parte da equipe inicial do Project Reality, com exceção de alguns veteranos exaustos, veio de fora da SGI.
Com poucas pessoas a bordo, os membros da equipe do Project Reality desempenharam muitas funções no outono e inverno de 93. Logic designers tornaram-se administradores de sistema, o pessoal de software escreveu verilog e Gudrun, ostensivamente o Admin, escreveu microcódigo. Mas, um por um, atraídos pela perspectiva de projetar um sistema que enviaria milhões de unidades por ano (a Nintendo já vendeu 100 milhões de unidades até agora), os principais designers de hardware e software se inscreveram. Quando o inverno se transformou em primavera, a equipe atingiu a massa crítica e tudo começou a se encaixar. O plano do produto se cristalizou e o primeiro marco ficou claro: RCP Tapeout 1.0.


O caminho para a primeira fita para fora

RCP Tape Out 1.0 não deveria ser uma saída de fita normal. Não apenas o projeto RCP de 2,4 milhões de transistores deveria ser concluído, mas o microcódigo de áudio e gráfico deveria ser escrito, simulado e testado com o verilog. Em outras palavras, virtualmente todo o sistema deveria ser desenvolvido para garantir que o chip funcionasse conforme necessário.
O verão de 94 viu alguns sucessos significativos, já que as madrugadas e o trabalho árduo começaram a dar frutos. O primeiro ponto amostrado do polígono sombreado suave foi gerado pelo simulador RCP C. O microcódigo de conversão da taxa de amostragem de áudio foi concluído. O design do chip estava bem encaminhado. As coisas pareciam estar indo bem. Seja o produto da visão inspirada ou as corridas de hambúrguer habenero, a equipe teve o "fogo na barriga".
Naquele verão também ocorreu o primeiro lançamento do ambiente de emulação Project Reality. Como o sistema real não estaria disponível até a primavera de 95, a equipe projetou um software que rodava em um Onyx com um Reality Engine que permitia à Nintendo e desenvolvedores importantes como Rare e DMA começarem a trabalhar em seus jogos.
Foi só em outubro de 94, com os prazos finais da fita se aproximando, que as dúvidas que os projetistas do RCP vinham guardando para si próprios chegaram à superfície; o chip era muito grande! Para cumprir as metas de custo, o RCP tinha que ser menor do que um tamanho específico e, embora os projetistas estivessem levando as ferramentas de design ao limite, parecia que o RCP iria perder sua área-alvo por um longo tiro.

Em 10 de outubro, uma reunião crítica foi convocada para discutir as opções. Cortar a unidade do vetor pela metade? Isso destruiria o desempenho. Cortar a memória cache? Isso prejudicaria o microcódigo gráfico que já estava usando cada bit de memória de instrução disponível. Ore para que os projetistas consigam, de alguma forma, enganar as ferramentas, fazendo com que façam o que até mesmo os fornecedores de ferramentas acreditavam que não poderiam fazer? Com o primeiro teste de fita programado para daqui a pouco mais de um mês, as alterações no design do chip seriam impossíveis de implementar, muito menos testar, a tempo. A terceira opção era a única viável; vá em frente e confie nos designers para encontrar uma maneira.
Enquanto os projetistas do chip RCP estavam ocupados reduzindo a área e completando a planta baixa do nível superior, a equipe de software trabalhava arduamente na ingrata tarefa de verificar o chip (não normalmente uma tarefa de software) para se certificar de que não haveria falhas. Afinal, o RCP seria enviado em dezenas de milhões de sistemas.

No final de 1994, o tempo estava se esgotando. Para enviar sistemas para o Natal de 95, tanto o RCP quanto o R4300i precisaram ser retirados com fita adesiva muito em breve. Felizmente, a equipe do R4300i cumpriu o cronograma e concluiu sua fita no início de dezembro. A equipe RCP não teve tanta sorte. Com o feriado se aproximando, a equipe RCP estava trabalhando quase sem parar para terminar o design do chip para que a NEC pudesse começar a fabricar os protótipos que seriam integrados aos sistemas de desenvolvimento. Pessoas com planos de folga na semana de Natal os cancelaram. Alguns dos principais membros da equipe chegaram no dia de Natal. Todos perceberam que as apostas eram altas.
No final de janeiro de 95, a equipe estava exausta. Trabalhar à noite e fins de semana longe da família e amigos estava começando a cobrar seu preço. A tensão da fita adesiva aumentava a cada dia que passava. Finalmente, em 24 de fevereiro de 1995, a gravação foi concluída. E isso significava ...


FESTA!

E que festa! Depois do brinde e do discurso obrigatório da gerência, dois engenheiros sumariamente batizaram o diretor com a banheira de água gelada, começando o que poderia muito bem ser a celebração interna mais úmida da história da SGI. Por alguma feliz coincidência, uma das salas de conferência próximas continha um monte de balões, que foram rapidamente colocados em serviço para a mãe de todas as lutas de balões de água. Depois de encharcar completamente os membros da equipe e não alguns espectadores inocentes, a equipe decidiu compartilhar a celebração com outras pessoas. Embalando tubos de balões de água, a equipe invadiu o prédio 10, onde em um clarão de glória, emboscou um desavisado Wei Yen.

Levantar a questão

Com o design do chip a caminho da fábrica, muitos dos designers de chips finalmente tiraram uma folga. Enquanto isso, a equipe de software estava ocupada se preparando para a introdução do sistema. Com o silício funcional da equipe do R4300i em mãos, os engenheiros de software do sistema operacional colocaram parte do kernel em funcionamento. Tudo estava pronto para a chegada dos chips RCP.
Os chips RCP estavam programados para voltar na terceira semana de abril e a Nintendo queria mostrar os sistemas de demonstração três semanas depois no show da E3. Ia ser apertado. Apertado, mas não impossível. Na verdade, funcionou como um relógio:
  • Terça-feira, 18 de abril: Os chips RCP não testados chegaram ao aeroporto de São Francisco vindos da NEC. Naquela noite, ele estava funcionando - e passando - em alguns testes preliminares do sistema.
  • Quarta-feira, 19 de abril: o acesso RDRAM foi obtido e o buffer de quadros foi exibido na TV.
  • Quinta-feira, 20 de abril: O primeiro triângulo foi processado pelo RCP Display Processor.
  • Sexta-feira, 21 de abril: O processador de sinais RCP passou nos testes.
  • Sábado, 22 de abril: O primeiro miniaplicativo animado de triângulo saltitante foi executado no sistema.
  • Domingo, 23 de abril: O primeiro aplicativo completo estava instalado e funcionando menos de uma semana depois que o primeiro silício pousou nos Estados Unidos.
Durante as duas semanas seguintes, a equipe do Project Reality trabalhou quase o tempo todo com engenheiros da Paradigm Simulation para polir o jogo Cobra da Paradigm, que a Nintendo demonstrou aos principais desenvolvedores e distribuidores em uma suíte de sussurros no show da E3 em 10 de maio.
Pouco antes do show, no entanto, a Nintendo lançou uma bomba - isso atrasaria o lançamento do Nintendo 64 até abril de 96. De acordo com o comunicado à imprensa, a Nintendo queria dar aos desenvolvedores mais tempo para desenvolver seus jogos. Apesar de tudo, a equipe continuou: com o primeiro lançamento de software no hardware real agendado para o início de junho, e a segunda fita lançada agendada para meados de julho, não havia tempo a perder.

Fora do laboratório

Quase antes de a poeira da E3 baixar, os sistemas de desenvolvimento foram retirados do laboratório e colocados nas mãos dos desenvolvedores que aguardavam. Graças ao emulador Reality Engine, muitos dos jogos já estavam em produção, mas não há nada como rodar jogos no hardware real para ajustar os sons, imagens e jogabilidade. Com os sistemas de desenvolvimento em mãos, os desenvolvedores podem iniciar esse processo.
Enquanto isso, a equipe de chips estava lutando na batalha da área. No verão de 95, a equipe R4300i juntou-se formalmente à equipe Project Reality com o objetivo de ajudar a reduzir o RCP a um tamanho que melhor correspondesse às metas de custo da Nintendo. Armado com técnicas completas de design customizado e um saco de truques para forçar as ferramentas de design físico a serem submetidas, este grupo trabalhou lado a lado com a equipe de design RCP original para reduzir o tamanho do chip sem comprometer qualquer funcionalidade. Com um pouco de design personalizado aqui, muita otimização de design e magia de ferramentas ali, a equipe foi capaz de atingir a meta de tamanho da matriz. A frequência do clock foi aumentada para o máximo possível para a placa do sistema também!


Tornando isso real

O outono de 95 viu o Nintendo 64 amadurecer do protótipo ao sistema real, conforme a equipe de software otimizou, adicionou recursos, corrigiu bugs e trouxe novos desenvolvedores de jogos à velocidade. O outono de 95 também viu o país começar a ganhar vida fora da SGI.
A máquina de marketing despertou enquanto a Nintendo se preparava para uma apresentação pública em novembro no Japão em seu show Shoshinkai. Embora o Nintendo 64 não fosse lançado até abril, Shoshinkai foi um show importante para a Nintendo. Os principais distribuidores tomariam suas decisões de compra com base no que ouviram e viram lá.
Enquanto o mundo experimentava o poder do Nintendo 64, a equipe SGI experimentava o que significa enviar um produto de consumo. Em novembro e dezembro de 95, a equipe atendeu ao milhão e um detalhes que precisavam ser resolvidos para a produção em massa: vetores de teste de chip, testes de linha de produção, correlação de rendimento de processo, testes de regressão. Não é um trabalho muito glamoroso, de forma alguma, mas um trabalho crucial.
Em 1 de fevereiro de 1996, a Nintendo anunciou o segundo e último atraso. Citando a falta de peças como o principal motivo, a Nintendo declarou que o sistema seria lançado oficialmente em 23 de junho no Japão e em 30 de setembro na América do Norte. Mas seria revelado no show E3 em maio, no Centro de Convenções de Los Angeles.
Nos dois meses seguintes, a equipe SGI trabalhou nos detalhes finais da produção em massa enquanto os desenvolvedores davam os toques finais em seus jogos e os enviavam para a Nintendo para teste de estresse. Finalmente, na primeira parte de maio, tudo estava pronto para o show.

E3: Nossa!

A E3 era tudo o que se esperava e muito mais. A revelação oficial ocorreu em uma coletiva de imprensa na quarta-feira, 15 de maio. “Acabou, acabou tããão”, babou um membro da imprensa assistindo à demonstração ao vivo de jogos reais no monitor de tela grande. O pessoal da GamerX estava ainda mais entusiasmado:
“Hoje é um dia lindo, principalmente porque acabei de deixar um briefing para a mídia da Nintendo, onde dois veteranos da Nintendo of America lançaram sua maravilha de 64 bits, o Nintendo-64. Tenho que admitir - esse bebê fuma. Com o hardware da Silicon Graphics, sem redução de velocidade do CD-ROM (o N-64, como foi apelidado, usará cartuchos, não CD-ROMs), e vários jogos que parecem ser de primeira qualidade, Sony e Sega tinham melhor cuidado com suas costas. Mal posso esperar para ter alguma experiência prática com jogos como Super Mario 64, que parece absolutamente incrível. E, a julgar pela reação da multidão reunida, ninguém mais pode.
“Deixe-me sem palavras ... Parabéns à SGI e sua implementação de console doce para a Nintendo. Super Mario 64 no Nintendo-64 é uma alegria de se ver, e além de criar uma plataforma que faz o PC parecer um Atari, a SGI trouxe uma nova vida ao processador MIPS sob o capô. Mostra como a localização pode fazer toda a diferença. De repente, o MIPS é mainstream e quente - e não estamos falando de problemas de dissipação de calor, também. ”
Até a mainstream Time Magazine juntou-se à festa. Em um artigo de duas páginas sobre o Nintendo 64 na edição de 20 de maio, Michael Krantz da Time diz
“O que importa é que o Nintendo 64 movido a chip da Silicon Graphics coloca a ação de jogo mais rápida e suave já alcançável via joystick a serviço de um movimento igualmente virtuoso.”
Os participantes da convenção não ficaram menos entusiasmados. Em todos os lugares que você ligava no piso da convenção, as pessoas comentavam sobre a qualidade e a velocidade do Nintendo 64. A espera nas dezenas de consoles do Nintendo 64 foi de meia hora, enquanto jogadores frenéticos faziam fila para experimentar os novos títulos como Super Mario 64, WaveRace 64, PilotWings 64, Star Wars: Shadows of the Empire, Cruis'n USA, Mortal Kombat e Killer Instinct.
E como a equipe se sentiu? Para a maioria dos membros da equipe, o show da E3 foi uma soma: o total emocional de quase três anos de muito trabalho, de amizades, de trabalho em equipe e de crescimento pessoal. E embora ninguém tenha falado sobre isso, cada um provavelmente sentiu - enquanto estavam diante do produto acabado que iria transmitir a soma de suas idéias para o mundo - o sentimento particular de orgulho que, se tivesse palavras, teria dito "Isso é o que eu posso fazer."

fonte:
Eu tinha visto esse video e fiquei revoltado com o tanto de desinformação e sensacionalismo, esse cara tem um birra enorme com o N64, no canal dele é cheio de hate gratuito com o N64, sua resposta é excelente e poderia comentar nas redes sociais dele pra ver se ele tem coragem de argumentar contra esses fatos.
 

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303
@Luke 64 Eu não tenho redes sociais e não curto , se quiser pode copiar minha postagem aqui e postar lá

aqui um video comparativo sobre outro game de arcade o California Speed


graficamente é bem simples também

@Ghr

teve o Monster Truck Madness que foi um porte de jogo de PC

 

Luke 64

Ser evoluído
Mensagens
187
Reações
130
Pontos
43
@Luke 64 Eu não tenho redes sociais e não curto , se quiser pode copiar minha postagem aqui e postar lá

aqui um video comparativo sobre outro game de arcade o California Speed


graficamente é bem simples também

@Ghr

teve o Monster Truck Madness que foi um porte de jogo de PC

Eu to afastado das redes sociais no momento, essa polarização toda dos últimos anos me fez perder a vontade de ficar nas redes
 

Ghr

Supra-sumo
Mensagens
802
Reações
1.384
Pontos
183
@Luke 64 Eu não tenho redes sociais e não curto , se quiser pode copiar minha postagem aqui e postar lá

aqui um video comparativo sobre outro game de arcade o California Speed


graficamente é bem simples também

@Ghr

teve o Monster Truck Madness que foi um porte de jogo de PC

Esse monster eu não consigo jogar ele, essa jogabilidade sabão me da agonia kk
 

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303
O PORTE IMPOSSÍVEL , O MILAGRE DE INDIANA JONES AND THE INFERNAL MACHINE NO N64

PARTE 01

199417


O Porte de RE2 ficou muito famoso pela proeza de compressão de video e audio da Angel Studios, mas o estúdio alemão Factor 5 conseguiu uma proeza também no console, uma tarefa se não mais impossível ainda que RE2 não pelo audio ou que o jogo tenha tido FMVs mas sim pelo jogo ter sido portado do PC, ter uma enorme quantidade de texturas e um minímo de processamento e memoria muito , muito mais alto do que as especificações do Nintendo 64, o jogo também era 2 discos e pior ainda o espaço disponivel para a Factor 5 foi a metade do cartucho do RE2

199431

Olhando as configurações minimas vemos que o jogo requer o dobro de processamento em relação ao N64
32mb de RAM fora 4mb de memoria somente de vídeo dedicado com suporte ao directx 6.1 ,e essa versão da epoca ocupava mais de 800mb no hd , 700 animações diferentes para cada personagem, mais de 50 minutos de audio, estamos vendo um jogo aqui que seria mais viavel ser portado direto para a sexta geração de consoles , ao contrario de RE2 que o consumo de memoria era menor pois o PS1 possuia menos memoria que o N64. Agora vamos tentar entender como a Factor 5 conseguiu recodificar esse jogo no N64 adicionando mais conteudos e até detalhes nos gráficos bem como melhorias no gameplay e som Surround como era de costume


  • Baseado em Indiana Jones e a Infernal Machine para PC
  • Chicoteie, salte, escale, rasteje e nade em incríveis ambientes 3D
  • Sobreviva ao desafio de criaturas famintas, robôs hostis, monstros estranhos, metade do Exército Vermelho e muito mais (incluindo ¿oh não ¿cobras!)
  • Descubra 17 capítulos de uma história emocionante e cheia de ação
  • Viaje pelo mundo para locais exóticos, das ruínas da Babilônia aos labirintos dos reis núbios
  • Todas as armas de que você precisa, incluindo pistolas automáticas, metralhadoras, granadas, cargas de mochila, bazucas e, é claro, o confiável chicote e revólver de Indy
  • Motor completamente recodificado pela LucasArts e Factor 5 para desempenho máximo no N64
  • Suporte para pacote de expansão de 4 MB ¿o jogo é executado em modo de alta resolução
  • Novo sistema de controle corrige o movimento desajeitado e desajeitado da versão para PC
  • Novos efeitos de iluminação, efeitos de partículas e transparências de água adicionam ainda mais realismo a um título já realista.
  • Muita fala no jogo e som surround brilhante usando as técnicas de compressão de marca registrada do Factor 5.
Uma equipe de apenas 8 pessoas, 19 meses de produção

199480

A grande força era o cartucho N64. Usamos o cartucho quase como a RAM normal e transmitimos todos os níveis de dados, texturas, animações, música, som e até mesmo código de programa enquanto o jogo está rodando. Com o tamanho final dos níveis e a quantidade de texturas, a RAM do N64 nunca teria sido nem remotamente suficiente para caber em qualquer nível individual. Portanto, a tecnologia do cartucho realmente salvou o dia.

Limitações da taxa de preenchimento do N64 foram contornadas . Implementado modo Hi-Res no Rogue por causa de sua aparência nítida, mas a taxa de quadros era questionável. Assim, ao ligar os motores de Indy e Naboo, o objetivo principal era obter uma alta taxa de quadros em Hi-Res. Isso significava não usar o Z-Buffer, porque ele sozinho usa um pouco da taxa de preenchimento do N64.
Todos os truques possíveis em termos de uso ideal do cache de textura 4K para cada textura. Os programadores descobriram os formatos de textura mais estranhos para obter a resolução máxima de cada textura. Uma ferramenta elaborada analisa cada textura original e tenta encontrar o melhor formato de textura para ela no N64. A ferramenta também permite manipular e escolher esses formatos de textura manualmente, algo que tivemos que fazer em muitos casos.


Introdução


A tarefa de portar Indiana Jones e a Infernal Machine do PC para o N64 provou ser bastante desafiadora. O Nintendo 64 conseguia lidar com a quantidade de polígonos muito bem, mas o uso de memória era um grande problema porque os desenvolvedores do PC original não precisaram se preocupar com isso. Enquanto uma quantidade de memória típica de PC pode ser de 128 MB, o N64 precisava rodar o jogo com apenas 4 MB - e isso também deve conter o código, buffers de quadro, texturas e listas de exibição. Você pode aproveitar as vantagens do N64 Expansion Pak para fornecer maior resolução e melhor desempenho, mas apenas se estiver presente.


Olhando apenas para esses números, parece que esse tipo de desafio está fadado ao fracasso desde o início. No entanto, quando o projeto começou, o jogo original para PC era muito menor em termos de textura e uso do modelo. Como todos sabemos, os projetos tendem a crescer durante a última fase de produção porque todos querem que o jogo seja o melhor possível. Certamente, um jogo de aventura como Indy forneceu oportunidades suficientes para crescimento.

Descobrimos que estávamos procurando por cada mil bytes que poderíamos liberar no final. Vários métodos diferentes foram usados para torná-lo adequado. Este artigo apresenta um resumo dos métodos mais importantes necessários para lidar com as restrições de memória, muitos dos quais são aplicáveis e benéficos para outros projetos. Reduzir o uso de memória também ajuda a aumentar o desempenho porque os dados são mais provavelmente locais e, portanto, mais prováveis de serem encontrados em um dos caches de dados da CPU.

Pode-se argumentar que os desenvolvedores hoje não precisam mais se concentrar em problemas de restrição de memória por causa de novos sistemas como o Sony Playstation 2 e o Nintendo Gamecube. No entanto, embora seus recursos de renderização tenham melhorado continuamente, seus subsistemas de memória não mudaram muito. Isso sugere que a organização da memória e o uso eficiente da memória são agora um problema ainda mais urgente.



Cenário

A abordagem usada para portar Indy para o N64 compartilha muitas semelhanças com um caminho de dados que é usado na produção de um título original do zero. Normalmente, os dados de arte e nível são exportados para o formato de dados específico do mecanismo de jogo usando uma combinação de ferramentas de exportação. Esses, por sua vez, são ligados, criando um recurso binário que é carregado no destino. Para reduzir o tamanho do recurso binário, ficamos com duas opções: reescrever a ferramenta de exportação configurando-a para gerar estruturas menores e mais otimizadas ou usar a inicialização do jogo para PC existente e a parte de inicialização para carregar o recurso binário.

Escolhemos a segunda abordagem, porque oferecia o benefício de uma inicialização rápida, visto que todos os dados de carregamento e inicialização do código já estavam no lugar. Tudo o que precisávamos fazer era pegar o jogo e remover o loop de renderização dele. A partir daqui, poderíamos pegar todas as estruturas de dados do jogo, reescrevê-las e otimizá-las de maneira fácil (Figura 1). Nós nos familiarizamos com a estrutura interna do jogo no processo. Chamamos esse executável abusado de munger. Nós o estendemos para otimizar e reescrever todas as estruturas de dados. Também fornecia mais verificações de consistência, que eram necessárias para garantir que nossas alterações nas estruturas de dados não prejudicassem os dados convertendo valores de 32 bits em oito bits.


199420

Esta abordagem tem muitas semelhanças entre um caminho de dados original porque é usado para um título original e, portanto, os métodos usados e as lições aprendidas ao portar Indy se aplicam aos títulos originais. Também é importante levar em consideração os requisitos de gerenciamento e armazenamento de dados, uma vez que a quantidade de dados de arte (por exemplo, geometria, texturas, dados de animação, etc.) está aumentando com o lançamento dos sistemas de próxima geração

Métodos Usados

Os métodos usados são categorizados em três classes. O restante do artigo discute os métodos em mais detalhes e oferece algumas dicas práticas, que podem ser úteis para aqueles que estão enfrentando problemas de memória semelhantes.

  • Reescrevendo e otimizando estruturas de dados: diminuir o tamanho das estruturas de dados parece um processo tedioso e errôneo; bem feito, isso pode ser uma maneira fácil de reduzir o tamanho dos dados.
  • Cache de recursos no destino: embora uma grande quantidade de dados possa ser armazenada em cache (isso funciona surpreendentemente bem), diferentes tipos de dados requerem diferentes abordagens de cache. Os esquemas de cache usados são descritos e classificados.
  • Usando um Kernel de Memória Virtual para reduzir o tamanho do código: um dos benefícios da programação do console é que você tem controle total sobre o hardware de destino. A implementação de um kernel de memória virtual parece exagero no início, no entanto, não apenas fornece memória preciosa, mas também ajuda no desenvolvimento e na depuração. Em geral, um kernel de memória virtual apresenta um meio de interceptar o acesso ilegal à memória.
Método A: Reescrevendo e Otimizando Estruturas de Dados

Um problema básico no início do projeto era que os dados do PC estavam todos em little-endian, enquanto o N64 (e GCN) usa big-endian. Embora seja possível alterar o endianess da CPU MIPS4300i, seria necessário um novo sistema operacional, o que não era viável na época. Uma vez que os dados tiveram que ser trocados de acordo com o tamanho da palavra dos dados (ou seja, você troca um valor de 32 bits de uma maneira diferente do que troca um valor de 16 bits e você não troca um byte), o munger precisava saber o layout das estruturas de dados. Isso foi necessário porque é fácil escrever um array. Os vetores de ponto flutuante são um ótimo exemplo. Você sabe que um vetor consiste em três valores de ponto flutuante consecutivos, cada um com 32 bits. A partir disso, você pode derivar um pequeno trecho de código, que trocaria "


Esse problema é ainda mais desafiador se você precisar escrever estruturas complexas, que contêm subestruturas e subuniões. Você teria que escrever um pequeno pedaço de código para cada definição de tipo no jogo, o que seria quase impossível de manter porque uma discrepância entre a definição de tipo e o pequeno pedaço de código faria com que os dados fossem escritos incorretamente. Olhando para um jogo em grande escala, percebemos rapidamente que essa abordagem não era possível; simplesmente havia muitos tipos de dados envolvidos e muitos deles estavam sujeitos a mudanças constantes porque nosso objetivo era reduzir seu tamanho. Portanto, precisávamos de um mecanismo que pudesse determinar automaticamente como converter o endianess de estruturas de dados arbitrárias, independentemente de conterem uniões e subestruturas.

A solução parece um pouco assustadora no início, mas provou ser bastante útil. Durante a inicialização do munger, ele analisa uma parte de seu próprio código-fonte para determinar o layout de memória de todas as estruturas de dados que estão prestes a ser convertidas de big para little-endian. Com Indy , isso teria sido muito difícil se permitíssemos a sintaxe C completa para estruturas de dados, incluindo arquivos e expansão de macro. Havia, no entanto, uma solução fácil que permitiu manter a análise realmente simples ao criar todas as estruturas C:

  • Definição de um conjunto simples de macros do pré-processador C (Figura 2), que são fáceis de reconhecer por um scanner de linha única, mas se expandem para a sintaxe C válida.
  • Usando um retorno de chamada durante o tempo de execução para especificar qual parte de uma união escrever, fornecendo um ponteiro (void *) para o objeto atual em questão.
  • Manter todas as estruturas de dados a serem convertidas, juntas em um arquivo.
Fazendo isso, podemos modificar as estruturas de dados sem nos preocupar com quaisquer problemas de conversão. Também é um método viável para garantir o alinhamento adequado nos tipos de dados, pois é possível verificar todos os elementos de uma estrutura quanto à sua posição dentro dela. Seria necessário verificar se o compilador C não introduz preenchimento automático que é invisível para o munger. Isso pode ser feito usando algumas instruções #pragma específicas do compilador.

199440

O exemplo acima se assemelha ao código C legal, que pode ser executado em qualquer compilador. Observe que nas definições da estrutura, cada linha ENTRY consiste em quatro elementos. Os dois últimos elementos são para uso do compilador e são substituídos pela macro #define ENTRY. O Munger do lado oposto examina o arquivo linha por linha e detecta as três palavras-chave BEGIN_STRUCT, ENTRY e END após remover o espaço em branco. Em seguida, analisa os primeiros dois elementos da linha ENTRY. O primeiro número fornece as informações de quantidade, enquanto o segundo campo declara o tipo de dados. O segundo campo não pode conter todos os tipos C. Ele só pode conter tipos C conhecidos pelo Munger, como UBYTE, UWORD, ULONG, float, enum e POINTER. Você também pode especificar tipos complexos, que já são conhecidos pelo Munger,

Usando mais algumas macros, subuniões e subestruturas podem ser especificadas. O Munger também reúne uma lista nomeada de todos os elementos e tipos envolvidos, portanto, é possível nomear elementos de estrutura durante o tempo de execução. Isso é útil quando é necessário decidir qual parte de um sindicato precisa ser escrita. Usando uniões, podemos interpretar um pedaço de memória de maneiras diferentes, o que afetará a troca de bytes durante a escrita. No entanto, cada objeto que está usando sindicatos deve codificar parte desse sindicato que está sendo usado. O uso de um retorno de chamada, que fornece o nome da estrutura / união em questão e um ponteiro para ela, permite que o Munger examine um objeto e retorne o nome correto da união para ser gravado no disco (Figura 3).

199442

Como você pode economizar memória com isso?

Por que, você pode perguntar, é necessário ter uma discussão tão prolixa sobre como escrever estruturas de dados, quando tudo o que estamos tentando fazer é reduzir seu tamanho? A resposta é direta. Seu objetivo principal é reduzir o tamanho das estruturas de dados. Sendo assim, é óbvio que as próprias definições da estrutura de dados estão em constante mudança durante o processo de desenvolvimento. Lidar automaticamente com essas mudanças ajuda muito. No entanto, e se você alterar uma estrutura a ponto de exigir grandes mudanças no código do Munger, que, como lembramos, é baseado no código do jogo real? Por exemplo, se você alterar todos os pontos mundiais para um número inteiro de vetores de 16 bits em vez de flutuantes, você terminará com uma quantidade inacreditável de erros do compilador. Mesmo que esteja compilando, é muito duvidoso que o executável ainda funcione.

Portanto, apresentamos dois conjuntos de estruturas de dados. Deixe o conjunto original (conjunto A) como estava no jogo original para PC e no Munger. Também introduzimos um novo conjunto de estruturas de dados, que é, no início, idêntico ao conjunto A. Este conjunto (conjunto B) é reconhecido pelo munger como o conjunto que deve ser convertido em big endian e as definições dos dados as estruturas são lidas durante o tempo de execução, conforme descrito acima. As estruturas de dados no conjunto B são provavelmente menores do que as originais, usando técnicas diferentes, que são descritas mais tarde. Uma função de transferência também é necessária, que copia os dados do conjunto A para o conjunto B. Durante esta etapa de cópia, várias coisas podem ser feitas nos dados para remover a redundância e compactá-los. A máquina de destino (o N64 em nosso caso) só conhece os dados no conjunto B. Portanto, ele '

A otimização do conjunto B de estruturas de dados usa alguns princípios, que são resumidos aqui:

  • Use tipos mais curtos do mesmo tipo (ou seja, use WORD em vez de LONG, use BYTE em vez de SHORT)
  • Combine vários campos de bits, enumerações em um
  • Use números inteiros curtos em vez de valores de ponto flutuante
  • Remova e otimize o preenchimento dentro da estrutura
  • Remova os componentes não utilizados
Obviamente, muitos desses métodos são perigosos porque os valores podem exceder as capacidades de seus tipos de dados. Além disso, usando números inteiros curtos para valores de ponto flutuante, podemos perder a precisão necessária. No entanto, se usarmos uma função de transferência para copiar os dados, é possível proteger contra todas essas armadilhas (na verdade, é loucura não fazer isso). Ao copiar um longo para um curto, simplesmente adicione uma instrução if e salve se o longo for <-32768 || > 32767. A mesma técnica pode ser usada para todos os outros problemas.

Mais técnicas

Além de alterar as próprias estruturas de dados, há várias outras técnicas que podem produzir quantidades consideráveis de memória.

  • Encontre elementos exclusivos em grandes matrizes e use índices para acessá-los. Por exemplo, em vez de armazenar centenas de vetores de ponto flutuante, que estão todos apontando na mesma direção, apenas armazene um vetor e use um índice curto que procura o normal correto. Essa abordagem é viável para muitos dados, como normais, vértices e cores.
  • Remova os dados redundantes herdados. Por exemplo, em um mecanismo de portal, sempre existem dois portais, onde um é o espelho exato do outro. Em Indy , foi possível cortar exatamente a metade das estruturas do portal, introduzindo uma broca "é-espelho". O código precisou ser alterado para inverter o normal do portal. Isso ganhou muita memória, pois a estrutura do portal era de tamanho considerável.
  • Um mecanismo às vezes abusa das estruturas de dados. Tipos complexos são usados para representar tipos simples. O melhor exemplo em Indy foi o uso de uma estrutura de "coisa" para representar pontos no mundo 3D. O desperdício foi de cerca de 500 bytes para cada instância, o que totalizou quase 100k em um nível típico. A razão para essa má decisão de design no PC era que simplesmente não importava e os designers de níveis podiam usar as ferramentas de posicionamento de "coisas" no editor de níveis para especificar as posições. No entanto, foram necessárias algumas investigações e alterações no código do jogo, mas o esforço valeu a pena.
  • Use campos de bits em vez de matrizes de booleanos. Às vezes, os booleanos são definidos como valores de 32 bits para contornar algumas armadilhas C típicas. No entanto, mesmo quando eles já são caracteres não assinados, você pode reduzir o tamanho para 1/8. Isso foi usado em Indy para reduzir o tamanho das informações de visibilidade potencial (PVS).
  • Dê uma olhada na representação binária de objetos de dados. Algum esquema de compactação simples pode ser aplicado, especialmente quando os dados não são usados com freqüência. Pode ser benéfico usar um pequeno cache para ocultar os custos de descompressão (veja abaixo).
  • Livre-se da precisão não utilizada e / ou desnecessária onde for viável. O sistema de animação de Indy no PC usava três flutuações de dados translacionais e três flutuações de dados rotacionais por quadro-chave. Ele também armazenou outros três flutuadores de informação delta translacional, uma vez que armazenou três flutuadores adicionais de informação delta rotacional mais um flutuante para o índice de tempo do quadro-chave (quadro #). Ao usar informações de rotação absoluta, os seis flutuadores para a informação delta podem ser removidos e, em vez de usar flutuadores para os seis valores restantes, usamos valores de 16 bits com sinal (na verdade, apenas 13 bits foram usados, os 3 * 3 bits restantes foram usados para codificar o número do quadro). Portanto, o tamanho de um quadro-chave foi reduzido de 7 * 4 = 28 bytes para 3 * 2 = 6 bytes.
No entanto, é preciso ter cuidado ao remover a precisão. Em Indy , também convertemos vértices mundiais e normais mundiais de valores flutuantes para valores de 16 bits com sinal. O que aconteceu é que os ventiladores de triângulo ficaram esburacados e o sistema de colisão falhou porque assumiu polígonos convexos. Ao mover os vértices (ou seja, encaixá-los na grade inteira), essa propriedade foi perdida junto com a colisão para lidar com polígonos côncavos. Não há necessidade de mencionar que fizemos isso em Indy .

  • Encontre linhas correspondentes em enormes matrizes multidimensionais e armazene índices em referências. Observe que isso só funciona com dados somente leitura, uma vez que a modificação de um elemento pode afetar muitos elementos lógicos (Figura 4). Usar este método para compactar as tabelas de descrição de animação (qual animação tocar, para qual movimento, com qual velocidade, etc) ganhou quase 100k em Indy quando havia muita animação em um nível.
  • Combine vários elementos de uma estrutura em uma união se eles forem mutuamente exclusivos. Essa técnica é mais do tipo 'último recurso' porque não se pode determinar rapidamente se alguns elementos de uma estrutura são realmente mutuamente exclusivos. Além disso, requer muitas mudanças de código para acessar os sindicatos corretamente.
  • 'Terceirizar' subestruturas enormes se raramente forem usadas. Um bom exemplo disso são as estruturas de 'superfície' em Indy porque elas continham uma quantidade bastante grande de informações sobre propriedades de superfície, como animação e iluminação, que eram usadas apenas para superfícies de 'efeitos especiais'. Por sua própria natureza, havia menos de um por cento daqueles em um nível típico. Remova as informações de "fx especial" e armazene-as em um novo tipo de dados, como tSurfaceFX, e atribua um identificador (pode ser apenas um valor de oito bits). Durante o tempo de execução, aloque um novo tSurfaceFX assim que o mecanismo animar uma superfície.
199443
Cache de recursos no destino

O armazenamento de objetos é baseado nas observações feitas durante qualquer ponto do jogo; você não precisa de todos os recursos de uma vez. Existem muitos tipos diferentes de recursos que você deve considerar armazenar em cache. Muitos recursos parecem difíceis de lidar ou não vale a pena armazenar em cache, uma vez que você assume que um cache não seria benéfico. Quando estávamos criando Indy , as seguintes lições foram aprendidas:


  • É difícil prever o desempenho de um cache. Geralmente, ele sempre tende a funcionar melhor do que o esperado, o que é obviamente uma coisa muito boa.
  • Ao escrever um cache, torne-o geral. Não crie um cache, que lida com as texturas do mundo, é melhor criar um, que lida com todas as texturas.
Quando se trata de selecionar quais recursos armazenar em cache, você pode querer considerar tudo, dependendo de quão desesperado você está. Para dar uma impressão do que é viável, aqui está uma lista de coisas que foram armazenadas em cache com sucesso em Indy no N64.

Texturas
Isso provou ser muito benéfico porque você raramente vê todas as texturas de uma vez em um ambiente interno típico. As texturas são freqüentemente compactadas usando um método LZ.

199879
Mesmo a distancia as texturas ficam bem nitidas na versão do N64



Listas de exibição para geometria de mundo / objeto

As listas de exibição são um grande problema de memória no N64. Eles contêm informações binárias usadas pelo hardware de renderização para desenhar primitivas e são consideravelmente maiores do que a própria geometria. Por esse motivo, a geometria do mundo (dividida em setores) e os objetos são convertidos de sua representação geométrica para exibir listas quando se tornam visíveis. Eles são eliminados se não forem processados por um período de tempo específico.




Potencialmente Informações de Visibilidade (PVS)

Para acelerar a renderização, uma tabela pvs é usada para facilitar o cálculo da visibilidade. No entanto, ele contém um campo de bits para cada setor mundial, que é do tamanho "# setores mundiais". Um bit definido neste campo de bits significa que há uma linha de visão entre um par de setores. O renderizador só precisa das informações de visibilidade para o setor em que a câmera está atualmente. Isso significa que o conjunto de PVs raramente muda (ou seja, se o jogador estiver correndo rápido, a cada cinco segundos). Mesmo se estiver mudando, é provável que a câmera volte para um setor visitado anteriormente (ou seja, o jogador está correndo em círculos). Portanto, um cache com apenas dez entradas ajuda muito. Como adicionar um novo conjunto de PVs ao cache é um evento raro, os dados são baixados da ROM e descompactados usando um método RLL.


Dados de animação

Em um jogo baseado em personagem de terceira pessoa, há muitas trilhas de animação que podem ser aplicadas aos personagens. Para cada ator, existem mais de 700 animações diferentes. Claro, alguns deles são usados apenas uma vez no jogo completo (ou seja, para cenas especiais). Seria um crime mantê-los todos na memória ao mesmo tempo. Felizmente, o sistema de animação usado no jogo original para PC fornecia funções para iniciar e parar uma trilha. Esses dois pontos tornaram fácil ancorar as funções de bloqueio e desbloqueio do cache.

Código de script

O mecanismo de script do jogo usava um código de bytes que foi interpretado para executar ações de script. Esses scripts eram específicos para uma determinada situação e nível. Portanto, armazená-los em cache foi uma ideia simples. Além disso, muitos scripts usavam um esquema básico de execução: após se inicializarem, eles esperavam que alguma condição específica ocorresse. Durante esse tempo, nenhum script é executado, então o código não precisa ficar parado.

Dados de colisão para geometria de mundo / objeto

Por sua própria natureza, as colisões ocorrem localmente. Os dados envolvidos consistem em normais e vértices. Se um objeto não está se movendo, o motor não realiza nenhuma verificação de colisão, portanto, seus normais e vértices não são necessários. Lembre-se de que, com a arquitetura N64, uma cópia desses 'pausas' nas listas de exibição para renderização. Infelizmente, não é possível acessar as listas de exibição para buscar vértices e normais porque o formato é binário, o que é extremamente complicado de acessar.

Modelos de objetos
Durante o jogo, muitos objetos são criados dinamicamente. Os objetos são criados a partir de um modelo que descreve as propriedades do novo objeto. Os modelos, portanto, não são constantemente necessários, com um cache de apenas oito sendo suficiente.

Benefícios do armazenamento em cache

O cache é usado para reduzir o uso de memória para um determinado conjunto de objetos. Isso é arquivado mantendo apenas uma quantidade fixa de objetos na memória. Quando precisar de espaço para um novo, você descobrirá qual deles não será usado por um tempo e o removerá, ao fazer isso você criará espaço para o novo objeto. Claro que o lixo ocorrerá quando você tornar o cache muito pequeno. Trashing é um termo usado para descrever uma linha de cache que é constantemente recarregada com diferentes objetos. Isso é ruim para o desempenho geral porque você está constantemente carregando e baixando do armazenamento em massa.

No entanto, há uma visão diferente sobre isso também. Sem o cache, você simplesmente precisa de uma quantidade específica de memória; não há nada para mexer. Quando você armazena um recurso em cache, existe a possibilidade de contrabalançar o desempenho em relação ao uso da memória. Talvez você esteja correndo tão apertado que fique feliz em oferecer um pouco de desempenho em troca de alguma memória tão necessária.

Com o cache, o uso de memória durante o tempo de execução pode ser corrigido. Ao criar objetos dinâmicos usando um cache, você pode impor um limite superior (é claro, deve estar tudo bem para descartar objetos antigos e recriá-los mais tarde). É uma idéia muito boa ter consertado as pegadas de memória nos consoles. No entanto, você deve fornecer modos de 'pânico' para alguns caches. Por exemplo, quando você usa um cache para renderizar a geometria e o cache está cheio, evitando, assim, que você limpe um elemento do cache (uma vez que todos eles estão visíveis), o renderizador lida com isso não renderizando o objeto. Caso contrário, você deve preencher a tela com sabedoria.

Outro benefício dos caches é que eles podem ocultar custos de acesso caros (na verdade, é para isso que servem os caches nas CPUs). Quando seus dados de origem de baixa entropia estão compactando bem, mas a descompactação está consumindo um pouco de tempo, é aconselhável colocar os objetos descompactados em um cache. Portanto, da próxima vez que forem solicitados, basta retornar um ponteiro para o objeto. Normalmente, um pequeno é suficiente para esse tipo de cache.

Esquemas de Cache

Existem basicamente duas abordagens diferentes para integrar um cache com seu cliente. Pode-se usar um Lock e desbloquear; protocolo. Sempre que o motor decidir usar um objeto por um período de tempo prolongado, ele deve usar Lock ; com o cache primeiro. O cache, por sua vez, faz o que for necessário para fornecer esse recurso (ou seja, baixando e / ou descompactando). O objeto então reside no cache até que o cliente decida que não é mais necessário e emita uma chamada de desbloqueio. O cache reconhece isso e pode reutilizar a linha do cache para outros objetos. Obviamente, seria aconselhável manter as informações no cache, mesmo que ele não esteja mais bloqueado. As informações podem ser solicitadas novamente em breve e, desde que o cache não fique sem espaço. A desvantagem de usar este esquema é que é possível que o cache fique sem espaço, porque todas as linhas do cache são preenchidas com objetos. Uma vez que o Lock (); call retorna um ponteiro para o cliente, e o cliente pode usá-lo contanto que o ponteiro não tenha sido desbloqueado, não há como liberar uma linha de cache. Portanto, o cliente deve ser capaz de lidar com a condição "não".

A segunda abordagem para fazer a interface do cache com seu cliente é usar um Touch ; chamar o cache sempre que um objeto estiver prestes a ser usado. A ideia é que o ponteiro do objeto, retornado pelo Touch ; chamada, só é válida até o próximo toque; ligar. Considerando a condição completa, a pior coisa que pode acontecer é ter o cache sendo constantemente recarregado e descartado. Isso causaria um desempenho ruim, mas pelo menos não há nenhuma condição especial com a qual se preocupar. Este é definitivamente o caminho a seguir se o cache for grande o suficiente e pode-se garantir que não haverá lixo. No entanto, sempre que um objeto é usado, deve haver um Touch ; chamada feita. Considere o Lock; e desbloquear ; interface para reduzir a quantidade de sobrecarga se isso acontecer com frequência.

O método de escolha é baseado em uma série de circunstâncias diferentes, incluindo custo de fornecimento de recursos (tempo de download, tempo de descompactação), estrutura de software existente e a frequência de duração dos objetos em cache que estão sendo usados.

Cache de exemplo

O arquivo de cabeçalho de exemplo abaixo (cf. fig. 5) mostra as definições estruturais para o cache de vértices de Indy . Este cache contém informações de vértices para propósitos de colisão com a geometria do mundo. É invocado sempre que ocorre uma colisão em um setor específico do mundo. Falando mais precisamente, ele contém uma matriz de valores de 16 bits sem sinal, que são índices na (um, grande) array de vértices mundiais. Os índices não ficam na memória o tempo todo, pois são usados apenas para fins de colisão.

A definição do cache consiste em três funções e uma definição de tipo. A estrutura contém um bit de alocação para cada uma das linhas de cache NUM_LINES (aqui: 128). Observe o uso das macros do pré-processador. Teria sido possível alterar o tamanho do cache dinamicamente durante o tempo de execução, no entanto, não há necessidade real disso, considerando que a definição de tamanho usando uma macro torna o código mais rápido para escrever. Além disso, o cache contém um mapeamento de uma linha de cache para um setor. Isso pode ser usado para encontrar rapidamente qual setor está armazenado em cache em uma linha de cache específica. Em contraste, há também um mapeamento de um determinado setor para uma linha de cache. Isso é usado quando o cache é solicitado a fornecer informações sobre um setor específico. Isso significa que o objeto não é armazenado em cache se o mapeamento não for inicializado (ou seja, 0xff). Se houver uma linha de cache atribuída, a posição dos dados é pesquisada usando o mapeamento CacheLine2Base com o endereço base do cache * Data. Uma vez que a quantidade de índices de vértice pode variar de setor para setor, a quantidade é codificada em CacheLine2Size também. O bloco de dados do cache é gerenciado usando um serviço freelist, que é encapsulado no membro tFreeList. Ele fornece alocação e desalocação básicas para a * área de dados. O cache rastreia a linha de cache mais antiga usando outro serviço. Este serviço tLRU (última utilização) fornece meios para manter uma lista ordenada por idade de acesso. Cada vez que o cache é acessado usando GetSectorPoints ; função, o LRU do cache é atualizado. Sempre que é hora de limpar uma entrada, o serviço LRU fornece a linha de cache mais antiga. É uma boa ideia implementar serviços separados, como tFreeList e tLRU,

199446

O cache também contém um contador para controlar a quantidade de bytes baixados da ROM por motivos de depuração e criação de perfil. Pode-se notar também que embora o número de linhas de cache seja definido durante o tempo de compilação, o tamanho real do cache (ou seja, a quantidade de índices que ele pode conter com esse número fixo de linhas de cache) é dinamicamente ajustável usando o Initialize; ligar. A quantidade de memória alocada para * Dados é alterada de acordo.
Detalhes de Implementação

Pode-se observar uma série de características para caches específicos com requisitos específicos, por meio da implementação de muitos caches diferentes. Algumas características têm um grande impacto no design de um cache.


Como o cache lida com a condição de "cheio"?
Existem diferentes abordagens para a condição "plena". Obviamente, o cache deve ter o tamanho adequado para que essa condição desagradável ocorra com pouca frequência. Você pode evitar isso executando as seguintes etapas:

  1. Descarte uma linha de cache aleatória. É claro que essa não é a maneira ideal de lidar com a situação; no entanto, é fácil de implementar. Isso é exatamente o que a unidade de gerenciamento de memória das CPUs MIPS faz, quando precisa buscar um novo descritor de página (veja abaixo).
  2. Descarte a linha de cache mais antiga. Isso só é útil quando há uma linha de cache desbloqueada (que é a mais antiga). Usando o Bloqueio (); e desbloquear (); protocolo nem sempre é o melhor método porque todas as linhas de cache podem estar bloqueadas no momento.
  3. Às vezes, é impossível descartar qualquer linha de cache (retornar NULL). Isso pode acontecer em um cache de textura, onde todas as linhas de cache contêm texturas bloqueadas porque o motor afirma que todas elas são visíveis. Em Indy , o renderizador desenhou um retângulo preenchido usando a cor ambiente do setor.
Qual é a frequência de acesso do cache?

Os caches variam em sua frequência de acesso. Às vezes, um objeto é solicitado apenas uma vez durante a inicialização do nível (ou seja, um objeto de script de inicialização) e nunca mais tocado. Às vezes, um objeto é usado com frequência durante um período de tempo prolongado em um nível específico, mas não é usado em nenhum outro lugar do jogo. Finalmente, alguns objetos (como os dados de animação dos personagens principais) são usados em todo o jogo de forma constante.

Também existe a frequência de acesso durante um único loop de renderização. O objeto é solicitado do cache para cada quadro ou é solicitado (bloqueado) apenas uma vez e então usado até ser liberado (desbloqueado) novamente? Os caches, que têm uma frequência de acesso baixa, se qualificam para dados de origem compactados porque a descompactação não ocorre com muita frequência (é claro, os dados também devem ser adequados para compactação).

Como o cache lida com a fragmentação?

Observe que a fragmentação da memória e a coleta de lixo são apenas um problema para caches que suportam objetos de dados de tamanhos diferentes. A fragmentação não é um problema porque não ocorre se todos os objetos tiverem o mesmo tamanho. Sempre vale a pena tentar evitar a fragmentação, embora nem sempre seja possível.

Se for necessário lidar com a fragmentação, é provável que esteja interessado em evitar buracos na memória cache alocada. Essas falhas podem levar à condição de cheio, mesmo se o cache estiver meio vazio, porque não há um único bloco de memória que seja grande o suficiente para conter um objeto solicitado. Em Indy , a coleta de lixo era necessária para o cache de textura. Muitas texturas pequenas compartilhavam o cache com algumas texturas grandes. As pequenas texturas (se não coletadas) se espalhariam uniformemente no cache, efetivamente bagunçando todo o cache, de forma que nenhuma textura grande pudesse ser baixada.

Felizmente, um cache de textura é especialmente adequado para coleta de lixo porque o único cliente que mantém um ponteiro para uma textura é o renderizador. Portanto, você só tem um cliente informando sobre as texturas movidas. A movimentação é necessária para preencher os buracos que vão surgindo durante o uso do cache. A abordagem é bastante simples. Procure no cache, começando no final, uma textura que caiba em um buraco. Ao fazer isso, o espaço no final do cache é liberado, enquanto as lacunas no início do cache são preenchidas. Para fazer isso de forma eficiente, pesquise uma correspondência para cada ou (como foi feito em Indy) têm um segundo encadeamento usando o tempo de CPU não utilizado de outra forma para navegar pelo cache e limpá-lo. Usar um segundo encadeamento reforça o uso de semáforos para garantir a sincronização adequada entre os encadeamentos, mas isso está fora do assunto e pertence ao adorável campo da programação paralela.

Como determinar o objeto mais antigo em um cache?

Esse problema está estreitamente ligado ao protocolo de acesso básico usado com um cache porque a única entrada disponível para resolver esse problema é o tempo de um Lock ou Touch ; chamada, desde que nenhuma informação de envelhecimento seja gravada no objeto em cache durante o uso.

  1. Encontre o objeto mais antigo usando um algoritmo LRU (usado recentemente). Esses algoritmos criam uma lista classificada de objetos em cache. Sempre que um objeto é usado, ele é movido para o topo da lista. Quando um objeto é usado pela primeira vez, ele é adicionado à lista, caso contrário, ele apenas é movido de sua posição anterior. Observe que isso pode produzir resultados incorretos para Lock ; e desbloquear ; protocolo, já que você toma o tempo de travamento como base e não o último tempo de uso. Esse problema não ocorre quando você usa o Touch ; protocolo, porque você tem uma base correta.
  2. Outra opção é usar carimbos de idade. Sempre que você usa um objeto, você atualiza um carimbo de idade embutido em um objeto. O número do quadro atual é um bom valor. Quando você precisar limpar uma linha de cache, pesquise todos os objetos em cache (o que só é recomendado, quando você tem um cache pequeno) para determinar o mais antigo.
Observe que a estampagem pode ser feita durante Touch ; liga ou mesmo com o Lock; e desbloquear ; esquema. Nesse caso, você precisará gravar o carimbo de idade em um campo designado do objeto em cache toda vez que for usado.

Dicas para executar caches

Depois que o cache estiver em execução, você deve reservar um tempo e criar um perfil dele. Tenha uma ideia da quantidade de dados que passam e determine por que eles são solicitados. Descubra mais sobre os padrões de acesso. Essas informações podem ser usadas para redimensionar o cache (sim, pode ser muito grande). Em quase todos os caches, existem dois recursos que determinam a condição "cheia". O cache pode ficar sem espaço de armazenamento. Nesse caso, a memória alocada para ele precisa ser aumentada. Por outro lado, o cache pode ficar sem linhas de cache livres. Não fará sentido, neste caso, aumentar o tamanho do armazenamento, se o cache não tiver meios para reter as informações para gerenciar o espaço extra. Além disso, se você descobrir que o espaço de armazenamento do seu cache é muito grande e você reduzi-lo, também pode acabar usando menos linhas de cache. Ao criar o perfil dos caches, esteja ciente das situações reais de jogo. O estresse colocado em um cache de textura é muito diferente quando você usa uma câmera de depuração veloz em vez das câmeras de jogo reais.

Para caches complexos, use muitos, muitos asserts ; para ajudá-lo a verificar a consistência de seu novo cache. Às vezes, alguma programação errada pode fazer você acreditar que está tudo bem até um ponto no final do jogo; como quando seu cache começa a retornar ponteiros para dados, que não pertencem ao objeto correto.

Por último, implemente serviços LRU e FREELIST separados porque você precisará deles novamente. Alguém poderia argumentar que um módulo de cache abstrato seria de algum benefício, mas pelo menos em Indy , cada cache tinha suas próprias características e casos especiais minúsculos, o que impedia essa abordagem.

Usando um Kernel de Memória Virtual

A etapa final que demos no Indy estava implementando um kernel de memória virtual para código e dados somente leitura. Esta decisão foi tomada porque o código para uma versão de lançamento chegou muito perto da marca de um megabyte. Comparado com o total de quatro megabytes que o N64 não expandido tem a oferecer, isso era simplesmente demais. Estritamente falando, um kernel de memória virtual representa apenas outro método de armazenamento em cache. É claro que se explora as possibilidades do processador devido ao uso de tabelas de mapeamento de página e da unidade de gerenciamento de memória. Outra coisa boa sobre o uso de kernel é que não há necessidade de dividir o código em várias seções de sobreposição, o que era comum na primeira geração de jogos N64. A sobreposição é uma técnica perigosa para reduzir o tamanho do código. O vinculador coloca módulos mutuamente exclusivos no mesmo espaço de endereço físico. Isto'

Claro, você cometerá erros com esse esquema (simplesmente porque existe o potencial para cometer erros), e ele não dá resultados muito bons. No entanto, como um kernel de memória virtual manterá apenas as páginas de código na memória, que estão realmente sendo usadas, você terá o benefício de sobrepor o código gratuitamente. Muitos módulos também se dividem em duas seções: uma para inicialização e outra para atualizar objetos. Após a inicialização do mecanismo, um kernel de memória virtual descarta o código de inicialização automagicamente, com base no tamanho da página virtual selecionada.

199447


Um kernel também pode fornecer e ajudá-lo a depurar seu programa. É possível detectar acessos de gravação ao código e dados somente leitura. Além disso, o uso de um espaço de endereço virtual exclusivo distingue ainda mais os dados dos endereços. Recursos de memória mapeada também podem ser implementados, no entanto, isso não foi feito em Indy .

Um kernel de memória virtual consiste em dois componentes principais (cf. fig. 6). Uma tabela de página descreve qual página virtual é mapeada para qual página física na memória, se é que está mapeada. Há uma entrada na tabela de páginas para todas as páginas virtuais conhecidas. Uma página geralmente é um bloco de 4096 bytes. A CPU tem um TLB de 32 entradas (cache de tradução à parte) no chip. Este TLB mapeia até 32 páginas virtuais para suas contrapartes físicas. Você deve configurar um mapeamento global (isto é, espaço de endereço completo) para cobrir acessos válidos de leitura / gravação à memória. No entanto, as 31 entradas restantes podem ser usadas para mapear páginas de código de 4 K. Claro, esses 31 mapeamentos não são suficientes. Portanto, a CPU emite um IRQ de recarga sempre que um mapeamento é desconhecido para o cache TLB. Uma rotina de montagem muito curta busca as informações de mapeamento corretas da tabela de página externa e as carrega em uma entrada TLB aleatória. Esta estratégia aleatória não é a melhor, mas também não é a pior e é fácil de implementar. Na verdade, a CPU MIPS fornece até mesmo um comando de montagem LoadToRandomTLBEntry.

No entanto, quando a CPU encontra uma página virtual não mapeada (ou seja, marcada como inválida), ela emite um IRQ de página inválida. Neste ponto, o software kernel precisa determinar qual página limpar da memória física (usando um algoritmo LRU muito, muito rápido, é claro), invalidar os bits válidos dessa página, baixar a nova página de código da ROM e marcar a página solicitada como sendo válido após a atualização da entrada TLB responsável por aquela página. s também não é o pior e é fácil de implementar. Na verdade, a CPU MIPS fornece até mesmo um comando de montagem LoadToRandomTLBEntry. No entanto, quando a CPU encontra uma página virtual não mapeada (ou seja, marcada como inválida), ela emite um IRQ de página inválida. Neste ponto, o software do kernel precisa determinar qual página limpar da memória física (usando um algoritmo LRU muito, muito rápido, é claro), invalidar os bits válidos dessa página, baixar a nova página de código da ROM e marcar a página solicitada como sendo válido após a atualização da entrada TLB responsável por aquela página. s também não é o pior e é fácil de implementar.

Todo esse processo pode parecer assustador, mas, na verdade, não é muito difícil de implementar. O software do kernel tem, no geral, cerca de 1000 linhas de instruções de montagem MIPS. É preciso cavar fundo no manual do processador, mas vale a pena o esforço. Claro, tentamos rodar Indy com apenas 64k de código, que funcionou bem, mas muito lento. No final, Indy usou ~ 400k de memória física de código, liberando cerca de 550k.


Conclusão


Para resumir este artigo:

  • Mesmo que alguns métodos ganhem uma quantidade considerável de memória, nenhum método sozinho ganha o que você precisa.
  • A combinação de métodos faz a diferença. É claro que se deseja lidar com os grandes pedaços primeiro.
  • Organizar seus dados com considerações de espaço em mente desde o início é melhor do que realizar uma programação de emergência no final.
  • O cache funciona melhor do que o esperado, especialmente quando você armazena recursos em cache em pontos centrais (ou seja, lidando com texturas em apenas um lugar).
  • O armazenamento em cache também ajuda a manter os dados locais e, portanto, aumenta o desempenho. Quanto menos dados a CPU tiver que lidar, melhor.
  • Não tenha medo de fazer um trabalho de baixo nível. Pelo menos em consoles você ainda pode fazer isso!
  • Mesmo com a próxima geração de consoles, os problemas apresentados aqui ainda são válidos (se não mais importantes), e com o ARAM do Gamecube, há algo para fazer o download…
To be continued...
 
Ultima Edição:

Cristiano Sword

Bam-bam-bam
Mensagens
1.162
Reações
4.564
Pontos
303
O PORTE IMPOSSÍVEL , O MILAGRE DE INDIANA JONES AND THE INFERNAL MACHINE NO N64

PARTE 01

Visualizar anexo 199417


O Porte de RE2 ficou muito famoso pela proeza de compressão de video e audio da Angel Studios, mas o estúdio alemão Factor 5 conseguiu uma proeza também no console, uma tarefa se não mais impossível ainda que RE2 não pelo audio ou que o jogo tenha tido FMVs mas sim pelo jogo ter sido portado do PC, ter uma enorme quantidade de texturas e um minímo de processamento e memoria muito , muito mais alto do que as especificações do Nintendo 64, o jogo também era 2 discos e pior ainda o espaço disponivel para a Factor 5 foi a metade do cartucho do RE2

Visualizar anexo 199431

Olhando as configurações minimas vemos que o jogo requer o dobro de processamento em relação ao N64
32mb de RAM fora 4mb de memoria somente de vídeo dedicado com suporte ao directx 6.1 ,e essa versão da epoca ocupava mais de 800mb no hd , 700 animações diferentes para cada personagem, mais de 50 minutos de audio, estamos vendo um jogo aqui que seria mais viavel ser portado direto para a sexta geração de consoles , ao contrario de RE2 que o consumo de memoria era menor pois o PS1 possuia menos memoria que o N64. Agora vamos tentar entender como a Factor 5 conseguiu recodificar esse jogo no N64 adicionando mais conteudos e até detalhes nos gráficos bem como melhorias no gameplay e som Surround como era de costume


  • Baseado em Indiana Jones e a Infernal Machine para PC
  • Chicoteie, salte, escale, rasteje e nade em incríveis ambientes 3D
  • Sobreviva ao desafio de criaturas famintas, robôs hostis, monstros estranhos, metade do Exército Vermelho e muito mais (incluindo ¿oh não ¿cobras!)
  • Descubra 17 capítulos de uma história emocionante e cheia de ação
  • Viaje pelo mundo para locais exóticos, das ruínas da Babilônia aos labirintos dos reis núbios
  • Todas as armas de que você precisa, incluindo pistolas automáticas, metralhadoras, granadas, cargas de mochila, bazucas e, é claro, o confiável chicote e revólver de Indy
  • Motor completamente recodificado pela LucasArts e Factor 5 para desempenho máximo no N64
  • Suporte para pacote de expansão de 4 MB ¿o jogo é executado em modo de alta resolução
  • Novo sistema de controle corrige o movimento desajeitado e desajeitado da versão para PC
  • Novos efeitos de iluminação, efeitos de partículas e transparências de água adicionam ainda mais realismo a um título já realista.
  • Muita fala no jogo e som surround brilhante usando as técnicas de compressão de marca registrada do Factor 5.
Uma equipe de apenas 8 pessoas, 19 meses de produção

Visualizar anexo 199480

A grande força era o cartucho N64. Usamos o cartucho quase como a RAM normal e transmitimos todos os níveis de dados, texturas, animações, música, som e até mesmo código de programa enquanto o jogo está rodando. Com o tamanho final dos níveis e a quantidade de texturas, a RAM do N64 nunca teria sido nem remotamente suficiente para caber em qualquer nível individual. Portanto, a tecnologia do cartucho realmente salvou o dia.

Limitações da taxa de preenchimento do N64 foram contornadas . Implementado modo Hi-Res no Rogue por causa de sua aparência nítida, mas a taxa de quadros era questionável. Assim, ao ligar os motores de Indy e Naboo, o objetivo principal era obter uma alta taxa de quadros em Hi-Res. Isso significava não usar o Z-Buffer, porque ele sozinho usa um pouco da taxa de preenchimento do N64.
Todos os truques possíveis em termos de uso ideal do cache de textura 4K para cada textura. Os programadores descobriram os formatos de textura mais estranhos para obter a resolução máxima de cada textura. Uma ferramenta elaborada analisa cada textura original e tenta encontrar o melhor formato de textura para ela no N64. A ferramenta também permite manipular e escolher esses formatos de textura manualmente, algo que tivemos que fazer em muitos casos.


Introdução


A tarefa de portar Indiana Jones e a Infernal Machine do PC para o N64 provou ser bastante desafiadora. O Nintendo 64 conseguia lidar com a quantidade de polígonos muito bem, mas o uso de memória era um grande problema porque os desenvolvedores do PC original não precisaram se preocupar com isso. Enquanto uma quantidade de memória típica de PC pode ser de 128 MB, o N64 precisava rodar o jogo com apenas 4 MB - e isso também deve conter o código, buffers de quadro, texturas e listas de exibição. Você pode aproveitar as vantagens do N64 Expansion Pak para fornecer maior resolução e melhor desempenho, mas apenas se estiver presente.


Olhando apenas para esses números, parece que esse tipo de desafio está fadado ao fracasso desde o início. No entanto, quando o projeto começou, o jogo original para PC era muito menor em termos de textura e uso do modelo. Como todos sabemos, os projetos tendem a crescer durante a última fase de produção porque todos querem que o jogo seja o melhor possível. Certamente, um jogo de aventura como Indy forneceu oportunidades suficientes para crescimento.

Descobrimos que estávamos procurando por cada mil bytes que poderíamos liberar no final. Vários métodos diferentes foram usados para torná-lo adequado. Este artigo apresenta um resumo dos métodos mais importantes necessários para lidar com as restrições de memória, muitos dos quais são aplicáveis e benéficos para outros projetos. Reduzir o uso de memória também ajuda a aumentar o desempenho porque os dados são mais provavelmente locais e, portanto, mais prováveis de serem encontrados em um dos caches de dados da CPU.

Pode-se argumentar que os desenvolvedores hoje não precisam mais se concentrar em problemas de restrição de memória por causa de novos sistemas como o Sony Playstation 2 e o Nintendo Gamecube. No entanto, embora seus recursos de renderização tenham melhorado continuamente, seus subsistemas de memória não mudaram muito. Isso sugere que a organização da memória e o uso eficiente da memória são agora um problema ainda mais urgente.



Cenário

A abordagem usada para portar Indy para o N64 compartilha muitas semelhanças com um caminho de dados que é usado na produção de um título original do zero. Normalmente, os dados de arte e nível são exportados para o formato de dados específico do mecanismo de jogo usando uma combinação de ferramentas de exportação. Esses, por sua vez, são ligados, criando um recurso binário que é carregado no destino. Para reduzir o tamanho do recurso binário, ficamos com duas opções: reescrever a ferramenta de exportação configurando-a para gerar estruturas menores e mais otimizadas ou usar a inicialização do jogo para PC existente e a parte de inicialização para carregar o recurso binário.

Escolhemos a segunda abordagem, porque oferecia o benefício de uma inicialização rápida, visto que todos os dados de carregamento e inicialização do código já estavam no lugar. Tudo o que precisávamos fazer era pegar o jogo e remover o loop de renderização dele. A partir daqui, poderíamos pegar todas as estruturas de dados do jogo, reescrevê-las e otimizá-las de maneira fácil (Figura 1). Nós nos familiarizamos com a estrutura interna do jogo no processo. Chamamos esse executável abusado de munger. Nós o estendemos para otimizar e reescrever todas as estruturas de dados. Também fornecia mais verificações de consistência, que eram necessárias para garantir que nossas alterações nas estruturas de dados não prejudicassem os dados convertendo valores de 32 bits em oito bits.



Esta abordagem tem muitas semelhanças entre um caminho de dados original porque é usado para um título original e, portanto, os métodos usados e as lições aprendidas ao portar Indy se aplicam aos títulos originais. Também é importante levar em consideração os requisitos de gerenciamento e armazenamento de dados, uma vez que a quantidade de dados de arte (por exemplo, geometria, texturas, dados de animação, etc.) está aumentando com o lançamento dos sistemas de próxima geração

Métodos Usados

Os métodos usados são categorizados em três classes. O restante do artigo discute os métodos em mais detalhes e oferece algumas dicas práticas, que podem ser úteis para aqueles que estão enfrentando problemas de memória semelhantes.

  • Reescrevendo e otimizando estruturas de dados: diminuir o tamanho das estruturas de dados parece um processo tedioso e errôneo; bem feito, isso pode ser uma maneira fácil de reduzir o tamanho dos dados.
  • Cache de recursos no destino: embora uma grande quantidade de dados possa ser armazenada em cache (isso funciona surpreendentemente bem), diferentes tipos de dados requerem diferentes abordagens de cache. Os esquemas de cache usados são descritos e classificados.
  • Usando um Kernel de Memória Virtual para reduzir o tamanho do código: um dos benefícios da programação do console é que você tem controle total sobre o hardware de destino. A implementação de um kernel de memória virtual parece exagero no início, no entanto, não apenas fornece memória preciosa, mas também ajuda no desenvolvimento e na depuração. Em geral, um kernel de memória virtual apresenta um meio de interceptar o acesso ilegal à memória.
Método A: Reescrevendo e Otimizando Estruturas de Dados

Um problema básico no início do projeto era que os dados do PC estavam todos em little-endian, enquanto o N64 (e GCN) usa big-endian. Embora seja possível alterar o endianess da CPU MIPS4300i, seria necessário um novo sistema operacional, o que não era viável na época. Uma vez que os dados tiveram que ser trocados de acordo com o tamanho da palavra dos dados (ou seja, você troca um valor de 32 bits de uma maneira diferente do que troca um valor de 16 bits e você não troca um byte), o munger precisava saber o layout das estruturas de dados. Isso foi necessário porque é fácil escrever um array. Os vetores de ponto flutuante são um ótimo exemplo. Você sabe que um vetor consiste em três valores de ponto flutuante consecutivos, cada um com 32 bits. A partir disso, você pode derivar um pequeno trecho de código, que trocaria "


Esse problema é ainda mais desafiador se você precisar escrever estruturas complexas, que contêm subestruturas e subuniões. Você teria que escrever um pequeno pedaço de código para cada definição de tipo no jogo, o que seria quase impossível de manter porque uma discrepância entre a definição de tipo e o pequeno pedaço de código faria com que os dados fossem escritos incorretamente. Olhando para um jogo em grande escala, percebemos rapidamente que essa abordagem não era possível; simplesmente havia muitos tipos de dados envolvidos e muitos deles estavam sujeitos a mudanças constantes porque nosso objetivo era reduzir seu tamanho. Portanto, precisávamos de um mecanismo que pudesse determinar automaticamente como converter o endianess de estruturas de dados arbitrárias, independentemente de conterem uniões e subestruturas.

A solução parece um pouco assustadora no início, mas provou ser bastante útil. Durante a inicialização do munger, ele analisa uma parte de seu próprio código-fonte para determinar o layout de memória de todas as estruturas de dados que estão prestes a ser convertidas de big para little-endian. Com Indy , isso teria sido muito difícil se permitíssemos a sintaxe C completa para estruturas de dados, incluindo arquivos e expansão de macro. Havia, no entanto, uma solução fácil que permitiu manter a análise realmente simples ao criar todas as estruturas C:

  • Definição de um conjunto simples de macros do pré-processador C (Figura 2), que são fáceis de reconhecer por um scanner de linha única, mas se expandem para a sintaxe C válida.
  • Usando um retorno de chamada durante o tempo de execução para especificar qual parte de uma união escrever, fornecendo um ponteiro (void *) para o objeto atual em questão.
  • Manter todas as estruturas de dados a serem convertidas, juntas em um arquivo.
Fazendo isso, podemos modificar as estruturas de dados sem nos preocupar com quaisquer problemas de conversão. Também é um método viável para garantir o alinhamento adequado nos tipos de dados, pois é possível verificar todos os elementos de uma estrutura quanto à sua posição dentro dela. Seria necessário verificar se o compilador C não introduz preenchimento automático que é invisível para o munger. Isso pode ser feito usando algumas instruções #pragma específicas do compilador.

Visualizar anexo 199440

O exemplo acima se assemelha ao código C legal, que pode ser executado em qualquer compilador. Observe que nas definições da estrutura, cada linha ENTRY consiste em quatro elementos. Os dois últimos elementos são para uso do compilador e são substituídos pela macro #define ENTRY. O Munger do lado oposto examina o arquivo linha por linha e detecta as três palavras-chave BEGIN_STRUCT, ENTRY e END após remover o espaço em branco. Em seguida, analisa os primeiros dois elementos da linha ENTRY. O primeiro número fornece as informações de quantidade, enquanto o segundo campo declara o tipo de dados. O segundo campo não pode conter todos os tipos C. Ele só pode conter tipos C conhecidos pelo Munger, como UBYTE, UWORD, ULONG, float, enum e POINTER. Você também pode especificar tipos complexos, que já são conhecidos pelo Munger,

Usando mais algumas macros, subuniões e subestruturas podem ser especificadas. O Munger também reúne uma lista nomeada de todos os elementos e tipos envolvidos, portanto, é possível nomear elementos de estrutura durante o tempo de execução. Isso é útil quando é necessário decidir qual parte de um sindicato precisa ser escrita. Usando uniões, podemos interpretar um pedaço de memória de maneiras diferentes, o que afetará a troca de bytes durante a escrita. No entanto, cada objeto que está usando sindicatos deve codificar parte desse sindicato que está sendo usado. O uso de um retorno de chamada, que fornece o nome da estrutura / união em questão e um ponteiro para ela, permite que o Munger examine um objeto e retorne o nome correto da união para ser gravado no disco (Figura 3).

Visualizar anexo 199442

Como você pode economizar memória com isso?

Por que, você pode perguntar, é necessário ter uma discussão tão prolixa sobre como escrever estruturas de dados, quando tudo o que estamos tentando fazer é reduzir seu tamanho? A resposta é direta. Seu objetivo principal é reduzir o tamanho das estruturas de dados. Sendo assim, é óbvio que as próprias definições da estrutura de dados estão em constante mudança durante o processo de desenvolvimento. Lidar automaticamente com essas mudanças ajuda muito. No entanto, e se você alterar uma estrutura a ponto de exigir grandes mudanças no código do Munger, que, como lembramos, é baseado no código do jogo real? Por exemplo, se você alterar todos os pontos mundiais para um número inteiro de vetores de 16 bits em vez de flutuantes, você terminará com uma quantidade inacreditável de erros do compilador. Mesmo que esteja compilando, é muito duvidoso que o executável ainda funcione.

Portanto, apresentamos dois conjuntos de estruturas de dados. Deixe o conjunto original (conjunto A) como estava no jogo original para PC e no Munger. Também introduzimos um novo conjunto de estruturas de dados, que é, no início, idêntico ao conjunto A. Este conjunto (conjunto B) é reconhecido pelo munger como o conjunto que deve ser convertido em big endian e as definições dos dados as estruturas são lidas durante o tempo de execução, conforme descrito acima. As estruturas de dados no conjunto B são provavelmente menores do que as originais, usando técnicas diferentes, que são descritas mais tarde. Uma função de transferência também é necessária, que copia os dados do conjunto A para o conjunto B. Durante esta etapa de cópia, várias coisas podem ser feitas nos dados para remover a redundância e compactá-los. A máquina de destino (o N64 em nosso caso) só conhece os dados no conjunto B. Portanto, ele '

A otimização do conjunto B de estruturas de dados usa alguns princípios, que são resumidos aqui:

  • Use tipos mais curtos do mesmo tipo (ou seja, use WORD em vez de LONG, use BYTE em vez de SHORT)
  • Combine vários campos de bits, enumerações em um
  • Use números inteiros curtos em vez de valores de ponto flutuante
  • Remova e otimize o preenchimento dentro da estrutura
  • Remova os componentes não utilizados
Obviamente, muitos desses métodos são perigosos porque os valores podem exceder as capacidades de seus tipos de dados. Além disso, usando números inteiros curtos para valores de ponto flutuante, podemos perder a precisão necessária. No entanto, se usarmos uma função de transferência para copiar os dados, é possível proteger contra todas essas armadilhas (na verdade, é loucura não fazer isso). Ao copiar um longo para um curto, simplesmente adicione uma instrução if e salve se o longo for <-32768 || > 32767. A mesma técnica pode ser usada para todos os outros problemas.

Mais técnicas

Além de alterar as próprias estruturas de dados, há várias outras técnicas que podem produzir quantidades consideráveis de memória.

  • Encontre elementos exclusivos em grandes matrizes e use índices para acessá-los. Por exemplo, em vez de armazenar centenas de vetores de ponto flutuante, que estão todos apontando na mesma direção, apenas armazene um vetor e use um índice curto que procura o normal correto. Essa abordagem é viável para muitos dados, como normais, vértices e cores.
  • Remova os dados redundantes herdados. Por exemplo, em um mecanismo de portal, sempre existem dois portais, onde um é o espelho exato do outro. Em Indy , foi possível cortar exatamente a metade das estruturas do portal, introduzindo uma broca "é-espelho". O código precisou ser alterado para inverter o normal do portal. Isso ganhou muita memória, pois a estrutura do portal era de tamanho considerável.
  • Um mecanismo às vezes abusa das estruturas de dados. Tipos complexos são usados para representar tipos simples. O melhor exemplo em Indy foi o uso de uma estrutura de "coisa" para representar pontos no mundo 3D. O desperdício foi de cerca de 500 bytes para cada instância, o que totalizou quase 100k em um nível típico. A razão para essa má decisão de design no PC era que simplesmente não importava e os designers de níveis podiam usar as ferramentas de posicionamento de "coisas" no editor de níveis para especificar as posições. No entanto, foram necessárias algumas investigações e alterações no código do jogo, mas o esforço valeu a pena.
  • Use campos de bits em vez de matrizes de booleanos. Às vezes, os booleanos são definidos como valores de 32 bits para contornar algumas armadilhas C típicas. No entanto, mesmo quando eles já são caracteres não assinados, você pode reduzir o tamanho para 1/8. Isso foi usado em Indy para reduzir o tamanho das informações de visibilidade potencial (PVS).
  • Dê uma olhada na representação binária de objetos de dados. Algum esquema de compactação simples pode ser aplicado, especialmente quando os dados não são usados com freqüência. Pode ser benéfico usar um pequeno cache para ocultar os custos de descompressão (veja abaixo).
  • Livre-se da precisão não utilizada e / ou desnecessária onde for viável. O sistema de animação de Indy no PC usava três flutuações de dados translacionais e três flutuações de dados rotacionais por quadro-chave. Ele também armazenou outros três flutuadores de informação delta translacional, uma vez que armazenou três flutuadores adicionais de informação delta rotacional mais um flutuante para o índice de tempo do quadro-chave (quadro #). Ao usar informações de rotação absoluta, os seis flutuadores para a informação delta podem ser removidos e, em vez de usar flutuadores para os seis valores restantes, usamos valores de 16 bits com sinal (na verdade, apenas 13 bits foram usados, os 3 * 3 bits restantes foram usados para codificar o número do quadro). Portanto, o tamanho de um quadro-chave foi reduzido de 7 * 4 = 28 bytes para 3 * 2 = 6 bytes.
No entanto, é preciso ter cuidado ao remover a precisão. Em Indy , também convertemos vértices mundiais e normais mundiais de valores flutuantes para valores de 16 bits com sinal. O que aconteceu é que os ventiladores de triângulo ficaram esburacados e o sistema de colisão falhou porque assumiu polígonos convexos. Ao mover os vértices (ou seja, encaixá-los na grade inteira), essa propriedade foi perdida junto com a colisão para lidar com polígonos côncavos. Não há necessidade de mencionar que fizemos isso em Indy .

  • Encontre linhas correspondentes em enormes matrizes multidimensionais e armazene índices em referências. Observe que isso só funciona com dados somente leitura, uma vez que a modificação de um elemento pode afetar muitos elementos lógicos (Figura 4). Usar este método para compactar as tabelas de descrição de animação (qual animação tocar, para qual movimento, com qual velocidade, etc) ganhou quase 100k em Indy quando havia muita animação em um nível.
  • Combine vários elementos de uma estrutura em uma união se eles forem mutuamente exclusivos. Essa técnica é mais do tipo 'último recurso' porque não se pode determinar rapidamente se alguns elementos de uma estrutura são realmente mutuamente exclusivos. Além disso, requer muitas mudanças de código para acessar os sindicatos corretamente.
  • 'Terceirizar' subestruturas enormes se raramente forem usadas. Um bom exemplo disso são as estruturas de 'superfície' em Indy porque elas continham uma quantidade bastante grande de informações sobre propriedades de superfície, como animação e iluminação, que eram usadas apenas para superfícies de 'efeitos especiais'. Por sua própria natureza, havia menos de um por cento daqueles em um nível típico. Remova as informações de "fx especial" e armazene-as em um novo tipo de dados, como tSurfaceFX, e atribua um identificador (pode ser apenas um valor de oito bits). Durante o tempo de execução, aloque um novo tSurfaceFX assim que o mecanismo animar uma superfície.
Visualizar anexo 199443
Cache de recursos no destino

O armazenamento de objetos é baseado nas observações feitas durante qualquer ponto do jogo; você não precisa de todos os recursos de uma vez. Existem muitos tipos diferentes de recursos que você deve considerar armazenar em cache. Muitos recursos parecem difíceis de lidar ou não vale a pena armazenar em cache, uma vez que você assume que um cache não seria benéfico. Quando estávamos criando Indy , as seguintes lições foram aprendidas:


  • É difícil prever o desempenho de um cache. Geralmente, ele sempre tende a funcionar melhor do que o esperado, o que é obviamente uma coisa muito boa.
  • Ao escrever um cache, torne-o geral. Não crie um cache, que lida com as texturas do mundo, é melhor criar um, que lida com todas as texturas.
Quando se trata de selecionar quais recursos armazenar em cache, você pode querer considerar tudo, dependendo de quão desesperado você está. Para dar uma impressão do que é viável, aqui está uma lista de coisas que foram armazenadas em cache com sucesso em Indy no N64.

Texturas
Isso provou ser muito benéfico porque você raramente vê todas as texturas de uma vez em um ambiente interno típico. As texturas são freqüentemente compactadas usando um método LZ.

Listas de exibição para geometria de mundo / objeto
As listas de exibição são um grande problema de memória no N64. Eles contêm informações binárias usadas pelo hardware de renderização para desenhar primitivas e são consideravelmente maiores do que a própria geometria. Por esse motivo, a geometria do mundo (dividida em setores) e os objetos são convertidos de sua representação geométrica para exibir listas quando se tornam visíveis. Eles são eliminados se não forem processados por um período de tempo específico.

Potencialmente Informações de Visibilidade (PVS)

Para acelerar a renderização, uma tabela pvs é usada para facilitar o cálculo da visibilidade. No entanto, ele contém um campo de bits para cada setor mundial, que é do tamanho "# setores mundiais". Um bit definido neste campo de bits significa que há uma linha de visão entre um par de setores. O renderizador só precisa das informações de visibilidade para o setor em que a câmera está atualmente. Isso significa que o conjunto de PVs raramente muda (ou seja, se o jogador estiver correndo rápido, a cada cinco segundos). Mesmo se estiver mudando, é provável que a câmera volte para um setor visitado anteriormente (ou seja, o jogador está correndo em círculos). Portanto, um cache com apenas dez entradas ajuda muito. Como adicionar um novo conjunto de PVs ao cache é um evento raro, os dados são baixados da ROM e descompactados usando um método RLL.


Dados de animação

Em um jogo baseado em personagem de terceira pessoa, há muitas trilhas de animação que podem ser aplicadas aos personagens. Para cada ator, existem mais de 700 animações diferentes. Claro, alguns deles são usados apenas uma vez no jogo completo (ou seja, para cenas especiais). Seria um crime mantê-los todos na memória ao mesmo tempo. Felizmente, o sistema de animação usado no jogo original para PC fornecia funções para iniciar e parar uma trilha. Esses dois pontos tornaram fácil ancorar as funções de bloqueio e desbloqueio do cache.

Código de script

O mecanismo de script do jogo usava um código de bytes que foi interpretado para executar ações de script. Esses scripts eram específicos para uma determinada situação e nível. Portanto, armazená-los em cache foi uma ideia simples. Além disso, muitos scripts usavam um esquema básico de execução: após se inicializarem, eles esperavam que alguma condição específica ocorresse. Durante esse tempo, nenhum script é executado, então o código não precisa ficar parado.

Dados de colisão para geometria de mundo / objeto

Por sua própria natureza, as colisões ocorrem localmente. Os dados envolvidos consistem em normais e vértices. Se um objeto não está se movendo, o motor não realiza nenhuma verificação de colisão, portanto, seus normais e vértices não são necessários. Lembre-se de que, com a arquitetura N64, uma cópia desses 'pausas' nas listas de exibição para renderização. Infelizmente, não é possível acessar as listas de exibição para buscar vértices e normais porque o formato é binário, o que é extremamente complicado de acessar.

Modelos de objetos
Durante o jogo, muitos objetos são criados dinamicamente. Os objetos são criados a partir de um modelo que descreve as propriedades do novo objeto. Os modelos, portanto, não são constantemente necessários, com um cache de apenas oito sendo suficiente.

Benefícios do armazenamento em cache

O cache é usado para reduzir o uso de memória para um determinado conjunto de objetos. Isso é arquivado mantendo apenas uma quantidade fixa de objetos na memória. Quando precisar de espaço para um novo, você descobrirá qual deles não será usado por um tempo e o removerá, ao fazer isso você criará espaço para o novo objeto. Claro que o lixo ocorrerá quando você tornar o cache muito pequeno. Trashing é um termo usado para descrever uma linha de cache que é constantemente recarregada com diferentes objetos. Isso é ruim para o desempenho geral porque você está constantemente carregando e baixando do armazenamento em massa.

No entanto, há uma visão diferente sobre isso também. Sem o cache, você simplesmente precisa de uma quantidade específica de memória; não há nada para mexer. Quando você armazena um recurso em cache, existe a possibilidade de contrabalançar o desempenho em relação ao uso da memória. Talvez você esteja correndo tão apertado que fique feliz em oferecer um pouco de desempenho em troca de alguma memória tão necessária.

Com o cache, o uso de memória durante o tempo de execução pode ser corrigido. Ao criar objetos dinâmicos usando um cache, você pode impor um limite superior (é claro, deve estar tudo bem para descartar objetos antigos e recriá-los mais tarde). É uma idéia muito boa ter consertado as pegadas de memória nos consoles. No entanto, você deve fornecer modos de 'pânico' para alguns caches. Por exemplo, quando você usa um cache para renderizar a geometria e o cache está cheio, evitando, assim, que você limpe um elemento do cache (uma vez que todos eles estão visíveis), o renderizador lida com isso não renderizando o objeto. Caso contrário, você deve preencher a tela com sabedoria.

Outro benefício dos caches é que eles podem ocultar custos de acesso caros (na verdade, é para isso que servem os caches nas CPUs). Quando seus dados de origem de baixa entropia estão compactando bem, mas a descompactação está consumindo um pouco de tempo, é aconselhável colocar os objetos descompactados em um cache. Portanto, da próxima vez que forem solicitados, basta retornar um ponteiro para o objeto. Normalmente, um pequeno é suficiente para esse tipo de cache.

Esquemas de Cache

Existem basicamente duas abordagens diferentes para integrar um cache com seu cliente. Pode-se usar um Lock (); e desbloquear (); protocolo. Sempre que o motor decidir usar um objeto por um período de tempo prolongado, ele deve usar Lock (); com o cache primeiro. O cache, por sua vez, faz o que for necessário para fornecer esse recurso (ou seja, baixando e / ou descompactando). O objeto então reside no cache até que o cliente decida que não é mais necessário e emita uma chamada de desbloqueio. O cache reconhece isso e pode reutilizar a linha do cache para outros objetos. Obviamente, seria aconselhável manter as informações no cache, mesmo que ele não esteja mais bloqueado. As informações podem ser solicitadas novamente em breve e, desde que o cache não fique sem espaço. A desvantagem de usar este esquema é que é possível que o cache fique sem espaço, porque todas as linhas do cache são preenchidas com objetos. Uma vez que o Lock (); call retorna um ponteiro para o cliente, e o cliente pode usá-lo contanto que o ponteiro não tenha sido desbloqueado, não há como liberar uma linha de cache. Portanto, o cliente deve ser capaz de lidar com a condição "não".

A segunda abordagem para fazer a interface do cache com seu cliente é usar um Touch (); chamar o cache sempre que um objeto estiver prestes a ser usado. A ideia é que o ponteiro do objeto, retornado pelo Touch (); chamada, só é válida até o próximo toque (); ligar. Considerando a condição completa, a pior coisa que pode acontecer é ter o cache sendo constantemente recarregado e descartado. Isso causaria um desempenho ruim, mas pelo menos não há nenhuma condição especial com a qual se preocupar. Este é definitivamente o caminho a seguir se o cache for grande o suficiente e pode-se garantir que não haverá lixo. No entanto, sempre que um objeto é usado, deve haver um Touch (); chamada feita. Considere o Lock (); e desbloquear (); interface para reduzir a quantidade de sobrecarga se isso acontecer com frequência.

O método de escolha é baseado em uma série de circunstâncias diferentes, incluindo custo de fornecimento de recursos (tempo de download, tempo de descompactação), estrutura de software existente e a frequência de duração dos objetos em cache que estão sendo usados.

Cache de exemplo

O arquivo de cabeçalho de exemplo abaixo (cf. fig. 5) mostra as definições estruturais para o cache de vértices de Indy . Este cache contém informações de vértices para propósitos de colisão com a geometria do mundo. É invocado sempre que ocorre uma colisão em um setor específico do mundo. Falando mais precisamente, ele contém uma matriz de valores de 16 bits sem sinal, que são índices na (um, grande) array de vértices mundiais. Os índices não ficam na memória o tempo todo, pois são usados apenas para fins de colisão.

A definição do cache consiste em três funções e uma definição de tipo. A estrutura contém um bit de alocação para cada uma das linhas de cache NUM_LINES (aqui: 128). Observe o uso das macros do pré-processador. Teria sido possível alterar o tamanho do cache dinamicamente durante o tempo de execução, no entanto, não há necessidade real disso, considerando que a definição de tamanho usando uma macro torna o código mais rápido para escrever. Além disso, o cache contém um mapeamento de uma linha de cache para um setor. Isso pode ser usado para encontrar rapidamente qual setor está armazenado em cache em uma linha de cache específica. Em contraste, há também um mapeamento de um determinado setor para uma linha de cache. Isso é usado quando o cache é solicitado a fornecer informações sobre um setor específico. Isso significa que o objeto não é armazenado em cache se o mapeamento não for inicializado (ou seja, 0xff). Se houver uma linha de cache atribuída, a posição dos dados é pesquisada usando o mapeamento CacheLine2Base [] com o endereço base do cache * Data. Uma vez que a quantidade de índices de vértice pode variar de setor para setor, a quantidade é codificada em CacheLine2Size [] também. O bloco de dados do cache é gerenciado usando um serviço freelist, que é encapsulado no membro tFreeList. Ele fornece alocação e desalocação básicas para a * área de dados. O cache rastreia a linha de cache mais antiga usando outro serviço. Este serviço tLRU (última utilização) fornece meios para manter uma lista ordenada por idade de acesso. Cada vez que o cache é acessado usando GetSectorPoints (); função, o LRU do cache é atualizado. Sempre que é hora de limpar uma entrada, o serviço LRU fornece a linha de cache mais antiga. É uma boa ideia implementar serviços separados, como tFreeList e tLRU,

Visualizar anexo 199446

O cache também contém um contador para controlar a quantidade de bytes baixados da ROM por motivos de depuração e criação de perfil. Pode-se notar também que embora o número de linhas de cache seja definido durante o tempo de compilação, o tamanho real do cache (ou seja, a quantidade de índices que ele pode conter com esse número fixo de linhas de cache) é dinamicamente ajustável usando o Initialize ( ); ligar. A quantidade de memória alocada para * Dados é alterada de acordo.
Detalhes de Implementação

Pode-se observar uma série de características para caches específicos com requisitos específicos, por meio da implementação de muitos caches diferentes. Algumas características têm um grande impacto no design de um cache.


Como o cache lida com a condição de "cheio"?
Existem diferentes abordagens para a condição "plena". Obviamente, o cache deve ter o tamanho adequado para que essa condição desagradável ocorra com pouca frequência. Você pode evitar isso executando as seguintes etapas:

  1. Descarte uma linha de cache aleatória. É claro que essa não é a maneira ideal de lidar com a situação; no entanto, é fácil de implementar. Isso é exatamente o que a unidade de gerenciamento de memória das CPUs MIPS faz, quando precisa buscar um novo descritor de página (veja abaixo).
  2. Descarte a linha de cache mais antiga. Isso só é útil quando há uma linha de cache desbloqueada (que é a mais antiga). Usando o Bloqueio (); e desbloquear (); protocolo nem sempre é o melhor método porque todas as linhas de cache podem estar bloqueadas no momento.
  3. Às vezes, é impossível descartar qualquer linha de cache (retornar NULL). Isso pode acontecer em um cache de textura, onde todas as linhas de cache contêm texturas bloqueadas porque o motor afirma que todas elas são visíveis. Em Indy , o renderizador desenhou um retângulo preenchido usando a cor ambiente do setor.
Qual é a frequência de acesso do cache?

Os caches variam em sua frequência de acesso. Às vezes, um objeto é solicitado apenas uma vez durante a inicialização do nível (ou seja, um objeto de script de inicialização) e nunca mais tocado. Às vezes, um objeto é usado com frequência durante um período de tempo prolongado em um nível específico, mas não é usado em nenhum outro lugar do jogo. Finalmente, alguns objetos (como os dados de animação dos personagens principais) são usados em todo o jogo de forma constante.

Também existe a frequência de acesso durante um único loop de renderização. O objeto é solicitado do cache para cada quadro ou é solicitado (bloqueado) apenas uma vez e então usado até ser liberado (desbloqueado) novamente? Os caches, que têm uma frequência de acesso baixa, se qualificam para dados de origem compactados porque a descompactação não ocorre com muita frequência (é claro, os dados também devem ser adequados para compactação).

Como o cache lida com a fragmentação?

Observe que a fragmentação da memória e a coleta de lixo são apenas um problema para caches que suportam objetos de dados de tamanhos diferentes. A fragmentação não é um problema porque não ocorre se todos os objetos tiverem o mesmo tamanho. Sempre vale a pena tentar evitar a fragmentação, embora nem sempre seja possível.

Se for necessário lidar com a fragmentação, é provável que esteja interessado em evitar buracos na memória cache alocada. Essas falhas podem levar à condição de cheio, mesmo se o cache estiver meio vazio, porque não há um único bloco de memória que seja grande o suficiente para conter um objeto solicitado. Em Indy , a coleta de lixo era necessária para o cache de textura. Muitas texturas pequenas compartilhavam o cache com algumas texturas grandes. As pequenas texturas (se não coletadas) se espalhariam uniformemente no cache, efetivamente bagunçando todo o cache, de forma que nenhuma textura grande pudesse ser baixada.

Felizmente, um cache de textura é especialmente adequado para coleta de lixo porque o único cliente que mantém um ponteiro para uma textura é o renderizador. Portanto, você só tem um cliente informando sobre as texturas movidas. A movimentação é necessária para preencher os buracos que vão surgindo durante o uso do cache. A abordagem é bastante simples. Procure no cache, começando no final, uma textura que caiba em um buraco. Ao fazer isso, o espaço no final do cache é liberado, enquanto as lacunas no início do cache são preenchidas. Para fazer isso de forma eficiente, pesquise uma correspondência para cada ou (como foi feito em Indy) têm um segundo encadeamento usando o tempo de CPU não utilizado de outra forma para navegar pelo cache e limpá-lo. Usar um segundo encadeamento reforça o uso de semáforos para garantir a sincronização adequada entre os encadeamentos, mas isso está fora do assunto e pertence ao adorável campo da programação paralela.

Como determinar o objeto mais antigo em um cache?

Esse problema está estreitamente ligado ao protocolo de acesso básico usado com um cache porque a única entrada disponível para resolver esse problema é o tempo de um Lock () ou Touch (); chamada, desde que nenhuma informação de envelhecimento seja gravada no objeto em cache durante o uso.

  1. Encontre o objeto mais antigo usando um algoritmo LRU (usado recentemente). Esses algoritmos criam uma lista classificada de objetos em cache. Sempre que um objeto é usado, ele é movido para o topo da lista. Quando um objeto é usado pela primeira vez, ele é adicionado à lista, caso contrário, ele apenas é movido de sua posição anterior. Observe que isso pode produzir resultados incorretos para Lock (); e desbloquear (); protocolo, já que você toma o tempo de travamento como base e não o último tempo de uso. Esse problema não ocorre quando você usa o Touch (); protocolo, porque você tem uma base correta.
  2. Outra opção é usar carimbos de idade. Sempre que você usa um objeto, você atualiza um carimbo de idade embutido em um objeto. O número do quadro atual é um bom valor. Quando você precisar limpar uma linha de cache, pesquise todos os objetos em cache (o que só é recomendado, quando você tem um cache pequeno) para determinar o mais antigo.
Observe que a estampagem pode ser feita durante Touch (); liga ou mesmo com o Lock (); e desbloquear (); esquema. Nesse caso, você precisará gravar o carimbo de idade em um campo designado do objeto em cache toda vez que for usado.

Dicas para executar caches

Depois que o cache estiver em execução, você deve reservar um tempo e criar um perfil dele. Tenha uma ideia da quantidade de dados que passam e determine por que eles são solicitados. Descubra mais sobre os padrões de acesso. Essas informações podem ser usadas para redimensionar o cache (sim, pode ser muito grande). Em quase todos os caches, existem dois recursos que determinam a condição "cheia". O cache pode ficar sem espaço de armazenamento. Nesse caso, a memória alocada para ele precisa ser aumentada. Por outro lado, o cache pode ficar sem linhas de cache livres. Não fará sentido, neste caso, aumentar o tamanho do armazenamento, se o cache não tiver meios para reter as informações para gerenciar o espaço extra. Além disso, se você descobrir que o espaço de armazenamento do seu cache é muito grande e você reduzi-lo, também pode acabar usando menos linhas de cache. Ao criar o perfil dos caches, esteja ciente das situações reais de jogo. O estresse colocado em um cache de textura é muito diferente quando você usa uma câmera de depuração veloz em vez das câmeras de jogo reais.

Para caches complexos, use muitos, muitos asserts (); para ajudá-lo a verificar a consistência de seu novo cache. Às vezes, alguma programação errada pode fazer você acreditar que está tudo bem até um ponto no final do jogo; como quando seu cache começa a retornar ponteiros para dados, que não pertencem ao objeto correto.

Por último, implemente serviços LRU e FREELIST separados porque você precisará deles novamente. Alguém poderia argumentar que um módulo de cache abstrato seria de algum benefício, mas pelo menos em Indy , cada cache tinha suas próprias características e casos especiais minúsculos, o que impedia essa abordagem.

Usando um Kernel de Memória Virtual

A etapa final que demos na Indyestava implementando um kernel de memória virtual para código e dados somente leitura. Esta decisão foi tomada porque o código para uma versão de lançamento chegou muito perto da marca de um megabyte. Comparado com o total de quatro megabytes que o N64 não expandido tem a oferecer, isso era simplesmente demais. Estritamente falando, um kernel de memória virtual representa apenas outro método de armazenamento em cache. É claro que se explora as possibilidades do processador devido ao uso de tabelas de mapeamento de página e da unidade de gerenciamento de memória. Outra coisa boa sobre o uso de kernel é que não há necessidade de dividir o código em várias seções de sobreposição, o que era comum na primeira geração de jogos N64. A sobreposição é uma técnica perigosa para reduzir o tamanho do código. O vinculador coloca módulos mutuamente exclusivos no mesmo espaço de endereço físico. Isto'

Claro, você cometerá erros com esse esquema (simplesmente porque existe o potencial para cometer erros), e ele não dá resultados muito bons. No entanto, como um kernel de memória virtual manterá apenas as páginas de código na memória, que estão realmente sendo usadas, você terá o benefício de sobrepor o código gratuitamente. Muitos módulos também se dividem em duas seções: uma para inicialização e outra para atualizar objetos. Após a inicialização do mecanismo, um kernel de memória virtual descarta o código de inicialização automagicamente, com base no tamanho da página virtual selecionada.

Visualizar anexo 199447


Um kernel também pode fornecer e ajudá-lo a depurar seu programa. É possível detectar acessos de gravação ao código e dados somente leitura. Além disso, o uso de um espaço de endereço virtual exclusivo distingue ainda mais os dados dos endereços. Recursos de memória mapeada também podem ser implementados, no entanto, isso não foi feito em Indy .

Um kernel de memória virtual consiste em dois componentes principais (cf. fig. 6). Uma tabela de página descreve qual página virtual é mapeada para qual página física na memória, se é que está mapeada. Há uma entrada na tabela de páginas para todas as páginas virtuais conhecidas. Uma página geralmente é um bloco de 4096 bytes. A CPU tem um TLB de 32 entradas (cache de tradução à parte) no chip. Este TLB mapeia até 32 páginas virtuais para suas contrapartes físicas. Você deve configurar um mapeamento global (isto é, espaço de endereço completo) para cobrir acessos válidos de leitura / gravação à memória. No entanto, as 31 entradas restantes podem ser usadas para mapear páginas de código de 4 K. Claro, esses 31 mapeamentos não são suficientes. Portanto, a CPU emite um IRQ de recarga sempre que um mapeamento é desconhecido para o cache TLB. Uma rotina de montagem muito curta busca as informações de mapeamento corretas da tabela de página externa e as carrega em uma entrada TLB aleatória. Esta estratégia aleatória não é a melhor, mas também não é a pior e é fácil de implementar. Na verdade, a CPU MIPS fornece até mesmo um comando de montagem LoadToRandomTLBEntry.

No entanto, quando a CPU encontra uma página virtual não mapeada (ou seja, marcada como inválida), ela emite um IRQ de página inválida. Neste ponto, o software kernel precisa determinar qual página limpar da memória física (usando um algoritmo LRU muito, muito rápido, é claro), invalidar os bits válidos dessa página, baixar a nova página de código da ROM e marcar a página solicitada como sendo válido após a atualização da entrada TLB responsável por aquela página. s também não é o pior e é fácil de implementar. Na verdade, a CPU MIPS fornece até mesmo um comando de montagem LoadToRandomTLBEntry. No entanto, quando a CPU encontra uma página virtual não mapeada (ou seja, marcada como inválida), ela emite um IRQ de página inválida. Neste ponto, o software do kernel precisa determinar qual página limpar da memória física (usando um algoritmo LRU muito, muito rápido, é claro), invalidar os bits válidos dessa página, baixar a nova página de código da ROM e marcar a página solicitada como sendo válido após a atualização da entrada TLB responsável por aquela página. s também não é o pior e é fácil de implementar.

Todo esse processo pode parecer assustador, mas, na verdade, não é muito difícil de implementar. O software do kernel tem, no geral, cerca de 1000 linhas de instruções de montagem MIPS. É preciso cavar fundo no manual do processador, mas vale a pena o esforço. Claro, tentamos rodar Indy com apenas 64k de código, que funcionou bem, mas muito lento. No final, Indy usou ~ 400k de memória física de código, liberando cerca de 550k.


Conclusão

Para resumir este artigo:

  • Mesmo que alguns métodos ganhem uma quantidade considerável de memória, nenhum método sozinho ganha o que você precisa.
  • A combinação de métodos faz a diferença. É claro que se deseja lidar com os grandes pedaços primeiro.
  • Organizar seus dados com considerações de espaço em mente desde o início é melhor do que realizar uma programação de emergência no final.
  • O cache funciona melhor do que o esperado, especialmente quando você armazena recursos em cache em pontos centrais (ou seja, lidando com texturas em apenas um lugar).
  • O armazenamento em cache também ajuda a manter os dados locais e, portanto, aumenta o desempenho. Quanto menos dados a CPU tiver que lidar, melhor.
  • Não tenha medo de fazer um trabalho de baixo nível. Pelo menos em consoles você ainda pode fazer isso!
  • Mesmo com a próxima geração de consoles, os problemas apresentados aqui ainda são válidos (se não mais importantes), e com o ARAM do Gamecube, há algo para fazer o download…
To be continued...
Carai mano! Que artigo bem escrito! Deu até vontade de imprimir pra ler com cheiro de papel xD
Foi vc que escreveu? Acho incrivel como levaram a otimizacao de baixo nivel dos jogos 2D de 8 e 16 bits pro 32bits.
Ansioso pelo próximo post^^
 

Freturn

Bam-bam-bam
Mensagens
1.083
Reações
4.025
Pontos
278
apaga ai e posta aqui

vlw man, postei lá.
 

Retroviews

Supra-sumo
Mensagens
876
Reações
1.835
Pontos
169
Desenterraram um trailer perdido de Mother 3 do Nintendo 64, exibido na Spaceworld de 1997. Infelizmente sem som.



Curioso como não é muito diferente da versão de GBA. Os personagens e cenários são fáceis de se reconhecer. Na torcida para esse jogo ter a mesma sorte do Dinosaur Planet e aparecer algum dia, mesmo sabendo que não chegaram a terminar.
 

Ghr

Supra-sumo
Mensagens
802
Reações
1.384
Pontos
183
Desenterraram um trailer perdido de Mother 3 do Nintendo 64, exibido na Spaceworld de 1997. Infelizmente sem som.



Curioso como não é muito diferente da versão de GBA. Os personagens e cenários são fáceis de se reconhecer. Na torcida para esse jogo ter a mesma sorte do Dinosaur Planet e aparecer algum dia, mesmo sabendo que não chegaram a terminar.
Esse com certeza tem sido um dos mais esperados pela comunidade pra vazar, sempre vejo citação dele
 

Fabio Alexandre

Supra-sumo
Mensagens
817
Reações
1.346
Pontos
183
California Speed merecia uma versão no Dreamcast, que conseguiria fazer um Arcade Perfect.
Mas a versão N64 não ficou ruim, achei aceitável, conseguiram colocar todo o conteúdo no cartucho.
.
Não removeram nenhuma pista, considerando que o cartuchinho não deve ter nem 1/10 do espaço da versão Arcade.
Só deveriam ter colocado a opção de usar o Expansion Pack, pra aumentar a Resolução e o Draw Distance.
 

Ghr

Supra-sumo
Mensagens
802
Reações
1.384
Pontos
183
California Speed merecia uma versão no Dreamcast, que conseguiria fazer um Arcade Perfect.
Mas a versão N64 não ficou ruim, achei aceitável, conseguiram colocar todo o conteúdo no cartucho.
.
Não removeram nenhuma pista, considerando que o cartuchinho não deve ter nem 1/10 do espaço da versão Arcade.
Só deveriam ter colocado a opção de usar o Expansion Pack, pra aumentar a Resolução e o Draw Distance.
O jogo em si foi um bom port, apesar das censuras bestas que a Nintendo colocava, a parte do shopping por exemplo, não tem as pessoas pra atropelar kk
 

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303
O PORTE IMPOSSÍVEL , O MILAGRE DE INDIANA JONES AND THE INFERNAL MACHINE NO N64
(PARTE 2)


203914



Pode-se dizer que o desenvolvedor Core Design simplesmente transformou os filmes de Indiana Jones em um jogo e substituiu Harrison Ford por Lara Croft quando criou Tomb Raider.Ironicamente, também se poderia argumentar que no ano passado a LucasArts retribuiu o favor ao lançar o Indiana Jones e a Infernal Machine para PC oficialmente licenciados - um jogo que lembrava tanto a aparência de Tomb Raider que era inegável. Infelizmente para os jogadores de PC, embora o produto fornecesse um enredo forte e mundos habilmente projetados e repletos de quebra-cabeças dignos do nome do Dr. Jones, ele também sofria consideravelmente com as mesmas deficiências do de Croft; em particular, um sistema de controle terrivelmente desorganizado e uma boa quantidade de código cheio de bugs para inicializar.

"Aproxime-se do presente. LucasArts se juntou ao desenvolvedor Factor 5 para trazer The Infernal Machine para os proprietários de Nintendo 64 - só que desta vez sem as falhas inerentes à versão para PC. Para seu crédito, a empresa foi amplamente bem-sucedida. Indy 64 não sacrifica nada da versão para PC, exceto por muitas de suas frustrações. Parece tão bom, senão melhor, e graças a um esquema de controle totalmente redesenhado, parece como deveria para começar - mais intuitivo, mais estreito, mais rápido e totalmente mais equilibrado. Todos os quebra-cabeças e design de nível superior do título para PC, entretanto, permanecem perfeitamente intactos."


Jogabilidade


Você jogou Tomb Raider. Imagine que Lara Croft não fosse tão voluptuosa. Agora imagine que ela usasse um chapéu e carregasse um chicote. Bem-vindo a Indiana Jones e a Máquina Infernal. O design por trás do jogo não é original, mas traz alguns novos elementos para o gênero de ação e aventura repleto de quebra-cabeças e há variedade suficiente para manter os jogadores felizes por um longo tempo.
Indy viaja por mais de 17 níveis diferentes resolvendo quebra-cabeças, eliminando inimigos e coletando artefatos inestimáveis. Ele pode usar uma variedade de armas e dispositivos - tudo, desde uma arma padrão e facão a uma espingarda, mais leve e, sim, até mágica. Ao longo do caminho, nosso herói também terá que descer rios de barco em uma jangada, atravessar desertos em um jipe, pular, escalar, nadar, rastejar, chicotear, balançar e deslizar até a vitória. A seleção é louvável. Na versão para PC do jogo, tarefas simples, como usar armas, eram uma tarefa árdua, pois tudo estava confinado a diferentes teclas. Para o "porte" N64, a LucasArts e a Factor 5 tomaram conhecimento de The Legend of Zelda: Ocarina of Timeesquema de item do botão C de e copiei-o. Não há nenhuma vergonha, realmente - ele arrasou e funciona tão brilhantemente no mundo de Indy. Utilizando-o, selecionar um item é tão simples quanto apertar um dos três botões C. Por exemplo: C-esquerdo puxa o chicote do Dr. Jones enquanto C-direito tira sua arma e C-desce o isqueiro. Enquanto isso, C-up é usado para um modo de visualização livre no qual os jogadores podem simplesmente olhar ao redor em seu ambiente - útil quando um está preso.
Outra grande inovação em relação ao esquema de controle da versão para PC é a inclusão de um recurso adicional que se tornou popular com o título Zelda de Miyamoto: o z-trigger lock-on. Quando a arma de Indy é sacada, os jogadores podem travar em um inimigo com o botão R, momento em que Dr. Jones pode simplesmente bombardear seu inimigo e continuar a atirar com um ângulo de câmera fixo. Funciona esplendidamente - assim como funcionou para Link em suas batalhas. É uma adição aparentemente simples que, na verdade, ajuda muito a tornar a sensação da aventura mais intuitiva, dando ao jogador mais confiança em sua habilidade.

Mas nem tudo está bem na nova aventura de Indiana. Certas deficiências da versão para PC ainda são evidentes no N64. O controle, embora melhorado muito, ainda é estranho. Indy é como Lara Croft em seus movimentos - lento. Ele não é um acrobata capaz de pular de uma saliência em outra, deslizando em encostas e mergulhando com perfeita precisão através de uma janela em um abismo. Em vez disso, ele deve ser virado, cuidadosamente posicionado e, então, ter permissão para ir em frente, mas mesmo assim não há garantia de que os jogadores irão derrotar com sucesso qualquer objetivo de manipulação que eles esperavam. Como Tomb Raider, um certo grau de paciência é necessário para jogar com Indy, e se você nunca gostou dos movimentos de Lara, também não vai gostar dos do Dr. Jones. Além disso, existem problemas ocasionais com a detecção de colisão. Indiana ricocheteou em uma saliência que tínhamos a intenção de que ele agarrasse antes e, da mesma forma, ele foi pego em uma pedra durante o rafting ou preso em uma parede durante a exploração, não nos deixando escolha a não ser reiniciar. Esses exemplos são raros, mas dignos de nota.

Os layouts dos níveis são quase idênticos aos encontrados na versão para PC; mundos enormes e temáticos com quebra-cabeças enormes e extensos que desencadeiam novos quebra-cabeças, que por sua vez desbloqueiam novos quebra-cabeças. Indy deve lutar contra tigres, atropelar hienas com seu jipe, evitar pedras que estouram jangadas nas corredeiras, pular lava fervente, quebrar paredes com magia, atirar em soldados russos mortos, andar em carrinhos de minas e evitar ser envenenado por répteis e insetos nojentos. Ele deve viajar do topo de montanhas nevadas a desertos empoeirados, através de pirâmides subterrâneas, em florestas e em abismos escuros e subaquáticos que parecem continuar indo e vindo. Os jogadores não ficarão absolutamente entediados com a complexidade ou variedade que o jogo apresenta, e isso ajuda muito a aumentar o valor do replay. Outro reforço de replay, talvez mais importante, vem na forma do tesouro que Indy coleta.

Artefatos inestimáveis estão escondidos em todos os níveis do jogo e conforme o Dr. J os coleta, seu QI sobe. Depois que ele atinge um certo QI, um segredo muito, muito impressionante é desvendado. É definitivamente algo para o jogador mestre almejar e a boa notícia é que os jogadores podem voltar aos níveis já vencidos a qualquer momento para procurar e salvar tesouros.

Gráficos


Indiana Jones e a Máquina Infernal é um dos títulos mais bonitos que já enfeitaram um cartucho do Nintendo 64. LucasArts e Factor 5 na verdade melhoraram o visual de muitas maneiras em relação ao original para PC. Pense em mundos gigantescos e intrincadamente detalhados com trabalho de textura nítida e magnificamente ambiente que o fará se perguntar se é realmente um produto N64 e efeitos de iluminação que são tão impressionantes. Adicione um sistema de efeitos de partículas energéticos - algo que faltava no jogo para PC - que permite que pedras caiam das texturas conforme Indy sobe, ou chamas que lançam faíscas quando se dobram com o vento. Junte tudo com uma enorme arquitetura 3D e uma incrível quantidade de variação de nível para nível. Agora, para o kicker - tudo é executado no modo de alta resolução de 640x480, já que os jogadores possuem um pacote de expansão de 4 MB.
Na verdade, as únicas desvantagens reais para os gráficos são o sistema de animação e, ocasionalmente, a taxa de quadros. Indy anda, rasteja e sobe como se tivesse algo incrivelmente doloroso acampado em sua traseira - assim como na versão para PC. É o único aspecto do esforço de 64 bits que gostaríamos que tivesse sido abordado. A taxa de quadros, por sua vez, pode cair em grandes ambientes externos com vários inimigos na tela ao mesmo tempo, mas como a aventura é frequentemente confinada a áreas internas e não é configurada de uma forma que convoque dezenas de inimigos ao mesmo tempo, é raro que o a fluidez diminui para um grau perceptível.


As diferenças gráficas entre o N64 e o PC são muito menos dramáticas do que você pode imaginar. Capturamos nosso Indiana Jones e a Infernal Time Machine (PC) em um PIII de 600 MHz com um Riva TNT2 Ultra. Para ser justo, rodamos o PC com resolução de 640x480, já que a versão N64 funciona com a mesma resolução. A principal diferença que você verá imediatamente é a profundidade da cor nas texturas. O N64 é famoso por fazer cores muito suaves às vezes, se não forem o vermelho, o azul ou o amarelo primários. Assim, os desfiladeiros castanho-avermelhados acabaram por ser muito mais castanhos. Quando você realmente joga o jogo não é perceptível no N64 porque você não tem nada com que se comparar, mas sentimos a necessidade de mencionar isso porque as imagens contrastam mais nesta área. Além disso, sentimos que as texturas do N64 são absolutamente incríveis e chegam bem perto das usadas na versão para PC. Na verdade, o uso de texturas de Indy no N64 é um dos melhores que já vimos. Não necessariamente em termos de design de textura, mas certamente em termos de nitidez. Isso pode ser visto nas fotos.
Abaixo apresentamos algumas fotos para sua própria comparação


203922



Uma viagem aos mistérios do N64 RCP


203923

O microcódigo gráfico da obra-prima por trás da versão para Nintendo 64 de Indiana Jones e a Máquina Infernal e Star Wars Episódio I: Batalha por Naboo


Introdução


A Factor 5 costumava ser um dos melhores estúdios de desenvolvimento de jogos no final dos anos 90 / início dos anos 2000. Seus programadores, vindos do cenário de hackers e demos alemães, eram muito talentosos e, graças a uma colaboração com a Nintendo e a LucasArts, foram capazes de fornecer impressionantes conquistas gráficas no N64 e no GameCube.

Após o sucesso de Star Wars: Rogue Squadron em 1998, Factor 5 começou a trabalhar dois novos jogos, Indiana Jones and the Infernal Machine e Star Wars Episódio I: Battle para Naboo, com a intenção de apertar o Nintendo 64 ao seu melhor. Para isso, a Factor 5 decidiu desenvolver um “novo” microcódigo gráfico (e otimizar seu microcódigo de áudio chamado Musyx).

No final da vida comercial do N64, ambos os jogos foram lançados, tarde demais para atrair o favor da crítica e de um público já focado na próxima geração de consoles, o que significa que as conquistas técnicas injetadas nesses jogos foram infelizmente despercebido.

GlideN64, como seu predecessor Glide64, foi desenvolvido principalmente como um plugin de emulação de alto nível (HLE). Um microcódigo é uma biblioteca de comandos macro de alto nível (alto nível em comparação com os códigos operacionais do processador). A maneira LLE é executar esses comandos como o hardware real faria, instrução por instrução. O HLE implementa o que os comandos dessa biblioteca executam o mais rápido possível, sem executar o código do comando real.

Conforme explicado por Sergey em seu blog há alguns anos poucos jogos não puderam ser emulados graficamente no HLE como a documentação necessária para fazer isso estava indisponível. Ainda assim, alguns anos atrás, Sergey e eu começamos a fazer engenharia reversa e implementar microcódigos gráficos alfandegários.

Quando começamos nossa jornada para decifrar aquele usado por Indiana Jones e a Máquina Infernal e Star Wars Episódio I: Batalha por Naboo, ficamos impressionados com o quão bem escrito e otimizado ele foi e embora não possamos entender sua complexidade em detalhes, acreditamos que suas proezas merecem ser documentadas para a posteridade.

Observe que para entender a documentação abaixo, você deve estar familiarizado com a programação gráfica (OpenGL), hardware N64 e o microcódigo Fast3D. (
Ao contrário do que poderia ser sugerido pelo Factor5, o microcódigo gráfico de Indiana Jones e Battle de Naboo eraNÃO desenvolvido do zero. Ele foi obviamente desenvolvido com o código-fonte do microcódigo F3DEX fornecido pela Nintendo em seu SDK, que é apenas uma versão otimizada do microcódigo Fast3D usado por Super Mario 64. É claro que a maioria dos comandos gráficos foram reescritos junto com muitas adições importantes ( o tamanho do microcódigo é cerca de duas vezes maior que os outros), mas seu núcleo é bastante semelhante ao do primeiro jogo do console.

O que resta principalmente é a maneira de transformar os vértices de entrada em uma estrutura de dados de saída específica armazenada em um buffer dentro da Memória de Dados (DMEM) do RSP (Processador de Sinal de Realidade). Essas estruturas podem ser selecionadas por um comando de triângulo, formatadas em um comando de triângulo de baixo nível e então usadas pelo Reality Display Processor (RDP). O código usado a este respeito é comparável ao código usado no microcódigo F3DEX onde não há correspondência com o código de outros tipos de microcódigo (Turbo3D, ZSort) para fazer tal operação.

Outra evidência a este respeito é que o cabeçalho do comando (ou seja, 0xBC para o comando MoveWord, 0xBF para o comando de triângulo TRI1, etc.) são iguais ao microcódigo F3DEX.

Como uma consequência interessante, isso significa que, na verdade, nenhum dos microcódigos N64 foi escrito do zero por desenvolvedores terceirizados, mas apenas pela SGI ou pela Nintendo. No entanto, é verdade que apenas cerca de 20% do código está de alguma forma relacionado ao F3DEX, o que significa que este último foi usado como um ambiente viável para desenvolver os novos comandos repletos de recursos exclusivos.

I / Poucos recursos pendentes em comparação com o microcódigo F3DEX

A. O endereço DMEM é integrado diretamente ao comando gráfico


DMEM é uma pequena memória de 4kb que o microcódigo RSP usa para armazenar os dados recuperados da RDRAM. Os dados são usados pelo RSP para fazer os cálculos de acordo com a especificação de um comando.

No microcódigo F3DEX, o endereço DMEM não faz parte do comando em si, mas é um índice. O endereço DMEM real usado por este índice é armazenado no próprio DMEM na inicialização do microcódigo, oculto para os usuários finais. Neste microcódigo Indy / Naboo, o endereço DMEM é definido diretamente no comando. Este recurso exclusivo ajuda a economizar espaço no DMEM para outras finalidades.

Vamos dar um exemplo simples: o
comando 0xBC é um comando MoveWord, que simplesmente armazena palavras de 32 bits no DMEM. Como você deve estar ciente, as palavras movidas serão usadas posteriormente por outros comandos como parâmetros.

0xBC00014C
0x00000715

0xBC é o cabeçalho do comando, 0x14C é o endereço DMEM e 0x00000715 é a palavra armazenada neste endereço. Para comparação, em F3DEX:

0xBC000406
0x002D4CD0

0x06 é um mero sinalizador que é usado pelo microcódigo para localizar no DMEM um endereço DMEM base. Esse sinalizador pode variar dependendo do tipo de palavra a ser armazenada (ou seja, um endereço RDRAM de segmento). 0x0004 é adicionado a este endereço DMEM básico. Em nosso exemplo, o endereço DMEM básico é 0x160 + 0x004 = 0x164. Portanto, a palavra 0x002D4CD0 será armazenada no endereço DMEM 0x164.

B. O modo de geometria é um mero registro RSP

No microcódigo F3DEX, o modo Geometria é armazenado no DMEM e cada vez que ele precisa ser verificado ou alterado, ele deve ser carregado em um registro RSP, alterado e depois armazenado de volta. No microcódigo Indy / Naboo, há simplesmente um registro RSP inteiro dedicado ao modo de geometria. Isso significa que você tem um registro a menos, mas é uma maneira fácil de gerenciar o modo de geometria e também economizar um pouco de espaço no DMEM.

C. Brincando com listas de exibição

No microcódigo Indy / Naboo, a forma como as listas de exibição são gerenciadas é relativamente diferente do F3DEX.
  1. Execução de várias listas de exibição no mesmo nível hierárquico
No F3DEX original, as listas de exibição são relativamente diretas, de forma que são, como no OpenGL, gerenciadas hierarquicamente. Primeiro, você chama uma nova lista de exibição e, em seguida, uma lista de exibição aninhada, que também pode chamar uma lista de exibição aninhada.
Quanto a Star Wars: Rogue Squadron, um mecanismo inteligente foi desenvolvido para “pular” de uma lista de exibição para outra lista de exibição. No início de cada lista de exibição, em vez de ter o primeiro comando imediato a ser executado, você simplesmente tem um endereço RDRAM que pode ser chamado no final da lista de exibição pelo comando imediato 0xB5. Nesse caso, uma lista de exibição será recuperada do endereço RDRAM especificado. Esta lista de exibição carregada também contém um endereço RDRAM em seu início. Portanto, em vez de aninhar as listas de exibição, você passa de uma lista de exibição para outra no mesmo nível de hierarquia.
  1. Execução de uma lista de exibição sob condição
Esse mecanismo é incrível. O comando MoveWord (0xBC00058C) pode fornecer um endereço RDRAM. Ao executar alguns comandos imediatos que podem levar ao desenho de alguns gráficos (retângulos texturizados, triângulos), ANTES de serem realmente desenhados, uma lista de exibição aninhada é recuperada e executada a partir de tal endereço RDRAM. É o caso do comando RDP imediato 0xE4 / 0xE5, para triângulos não rejeitados, para partículas. Tal mecanismo vincula o desenho real de uma primitiva RDP a uma lista de exibição que define os parâmetros de tal desenho (ou seja, modo de combinação, outros modos, imagem de textura, bloco, etc.). E tal mecanismo ocorre SOMENTE quando o primitivo está para ser desenhado. Portanto, por exemplo, se um triângulo estiver fora da janela de visualização e, portanto, rejeitado, esta lista de exibição para a configuração do pipeline de pixel não será executada. Desta forma, o N64 RDP é usado apenas quando necessário!

D. Segmentação de memória inteligente

No F3DEX, o código gerencia a segmentação da memória através do uso do comando MoveWord. Com este método, o número de segmentos é limitado a 16 e requer o armazenamento das palavras no DMEM. No microcódigo Indy / Naboo, a segmentação da memória é gerenciada de forma diferente e de alguma forma como o mecanismo de “salto”, já explicado para a lista de exibição. No primeiro comando imediato 0x02 fornece um endereço RDRAM. Este é o endereço RDRAM do primeiro segmento. A primeira palavra neste endereço RDRAM é o endereço RDRAM do segmento seguinte. O tamanho de cada segmento é limitado a 0x100 bytes e quando um comando imediato solicita dados além do segmento, os dados restantes são recuperados do segmento seguinte, onde novamente a primeira palavra fornece o endereço RDRAM do segmento seguinte.

E. Estrutura de comando intrincada

No F3DEX, o tamanho do comando é fixado em duas meras palavras de 32 bits com a mesma finalidade exata. Em Indy / Naboo, o tamanho de um comando pode ser muito maior. Por exemplo, o maior comando imediato do microcódigo, que é usado para gerar os polígonos do terreno a partir de um mapa de altura, é composto por 16 palavras de 32 bits !!!!

0x05000000
0x217A800F
0x045ED4E3
0x00000000
0x000001E4
0xD642FE9B
0x00000000
0x00000000
0x00000000
0x00000000
0xFF000000
0xFF000000
0x00000000
0x00000000
0x00000000
0xEF5B0017

O mesmo comando imediato pode ter seu tamanho variando de acordo com uma bandeira dentro de tal comando. Por exemplo, o comando TRI 0xB4 para polígonos texturizados é maior do que para polígonos sombreados
.
TEXTURED TRIANGLES

0xB400 06 00
0x06000628
0x0C000408
0x06500678
0x07DD062C
0x07DD062C
0x0787062C
0x07DD062C

SHADED TRIANGLES

0xB400 04 00
0x06000628
0x0C000408
0x06500678

A bandeira do comando também pode alterar seu comportamento. Por exemplo, o comando TRI 0xB4 com sinalizador 0x06 é usado para triângulos texturizados com texturas regulares, mas o sinalizador 0x0E ativa a geração de coordenadas de textura para texturas reflexivas.

0xB400 0E 00
0x099809C0
0xACA0A4A8
0x09700948
0x7F0000B8
0x7F0000C0
0x7F0000B0
0x7F0000A8

Às vezes, o mesmo comando pode ter uma finalidade completamente diferente. Por exemplo, o comando 0x05 pode ser usado para gerar retângulos de textura, gerar partículas, gerar terreno a partir de um mapa de altura, gerar vértices específicos. Exceto para gerar gráficos, não há nada em comum entre esses comandos imediatos, na verdade.

II / Lista dos comandos com explicação de alto nível

Mesmo se pudéssemos decifrar o microcódigo, isso não significa que todos os parâmetros desses comandos foram totalmente apreendidos. Alguns, é claro, são bastante óbvios, mas alguns são usados em comandos muito grandes e complexos e, portanto, confusos.

Comando 0x01

O principal objetivo desse comando imediato é recuperar dados da RDRAM e, potencialmente, usar esses dados para computar novos dados.
A estrutura do comando é a seguinte:

0x01ODDDLL
0xBBAAAAAA

0x01 Cabeçalho do comando
O Opção do comando: para o mesmo DDD, a opção pode levar a outra parte do código
DDD Endereço DMEM onde os dados serão armazenados. TAMBÉM o código irá verificar e dependendo disso, irá rotear o código para uma porção específica do código, que irá então rotear novamente por O.
LL número de bytes a serem recuperados da memória
BB é um mero byte que pode ser usado de acordo para a rota que o comando tomará após ter recuperado os dados (ou seja, para o número de luzes)
AAAAAA Quando diferente de zero, os dados são recuperados desta memória RDRAM, quando há apenas 0x000000, os dados são recuperados de um segmento.

Portanto, o mesmo comando 0x01 pode ser usado para vários cenários, como:

Quando O é 0, o comando é como o comando F3DEX MoveMem, o que significa que ele simplesmente recupera dados de RDRAM e os armazena em DMEM.

Quando O é 1, o comando é como o comando F3DEX VTX, o que significa que os vértices são recuperados da RDRAM para o DMEM, transformados e armazenados em um buffer.

Quando O é 2, cálculos de iluminação são realizados. O comando recupera dados de RDRAM e calcula cores para vértices. As cores são armazenadas em um buffer de onde os comandos de triângulo as recuperam posteriormente. O sistema de iluminação é muito complexo, com muitas opções.

Quando O é 3, o comando define o número de luz e potencialmente recupera a estrutura de luz.

Quando O for 5, o comando recupera os vértices da RDRAM de forma específica para o DMEM, transforma-os e armazena-os em um buffer. Essa opção diz respeito a gráficos 2D onde triângulos são usados.

Comando 0x02

Ele define o endereço RDRAM do primeiro segmento utilizável pelo comando 0x01. Como já explicado, o endereço RDRAM do próximo segmento é a 1ª palavra do endereço RDRAM do segmento anterior.

Comando 0x05

Este comando gera primitivas de várias maneiras (de um mero retângulo de textura a partículas a triângulos usados para campo, etc.). O último byte da segunda palavra determina o modo do comando.

0x18 (2 palavras)

0x05XXXXXX
0xXXXXXX18

Este subcomando transforma os vértices selecionados pela matriz Modelview (0x010E403F) e os armazena em um buffer de vértice.

0x27 (6 palavras)

0x05XXXXXX
0xXXXXXX27

O subcomando gera vértices e alguns sinalizadores usados por outro subcomando 0x05.

0x24 (10 palavras)

0x05XXXXXX
0xXXXXXX24

O subcomando gera partículas (na verdade, pequenos retângulos de textura) a partir dos vértices / sinalizadores obtidos pelo subcomando 0x05 anterior.

0x15 (8 palavras)

0x05XXXXXX
0xXXXXXX15

O subcomando gera um mero retângulo de textura usando um vértice como centro de tal retângulo. É usado principalmente para explosões.

0x4F (2 palavras)

0x05XXXXXX
0xXXXXXX4F
Esse subcomando é uma mera sinalização usada pelo subcomando 0x0F para alterná-lo entre sua versão curta (4 palavras e a versão longa (16 palavras)

0x0F (4 ou 16 palavras)

0x05XXXXXX
0xXXXXXX0F

Tal sub -comando é usado para definir parâmetros para o subcomando 0x09 e 0x0C. Há uma versão curta e outra longa, ativada pelo subcomando acima.
0x09 e 0x0C (6 palavras)

0x05XXXXXX
0xXXXXXX0C

0x05XXXXXX
0xXXXXXX09

Ambos os subcomandos geram os triângulos para o solo no Episódio I de Star Wars: Batalha por Naboo (até 32 por subcomandos). Parece ser gerado a partir de um mapa de altura colorido.
Como você entende, o comando 0x05 é um conjunto de 8 subcomandos!

Comando 0x06

Este comando é igual ao comando gSPDisplayList em F3DEX.

Comando 0x07

Este comando é igual ao comando gSPBranchList em F3DEX.

Comando 0xB4 (4 ou 8 palavras)

É semelhante ao comando TRI2 em F3DEX, exceto que as coordenadas e índices de textura no buffer de cores fornecidos como parâmetros do comando.

Comando 0xB5

Este comando dispara um “salto” para outra lista de exibição previamente definida como a primeira palavra da lista de exibição atual.

Comando 0xB6

Este comando é igual ao comando gSPClearCeometryMode em F3DEX.

Comando 0xB7

Este comando é igual ao comando gsSPSetGeometryMode em F3DEX.

Comando 0xB8

Este comando termina uma lista de exibição.

Comando 0xB9

Este comando é semelhante ao comando gSPSetOtherMode em F3DEX (metade inferior)

Comando 0xBA

Este comando é semelhante ao comando gSPSetOtherMode em F3DEX (metade superior)

Comando 0xBB

Este comando é semelhante ao comando gSPTexture em F3DEX.

Comando 0xBC

Este comando é semelhante ao comando Moveword em F3DEX.

Comando 0xBD

Usado apenas na Batalha de Naboo. Ele define os OtherModes para os triângulos usados pelos comandos que geram o solo.

Comando 0xBE

Usado apenas na Batalha de Naboo. Ele define os OtherModes (junto com o comando imediato 0xBD) e as coordenadas de textura para cada triângulo que gera o solo. Em conjunto com os parâmetros definidos pelos subcomandos 0x05 -0x09 e 0x0C, ele também pode gerar esses triângulos (até 32 deles).

Comando 0xBF (4 ou 8 palavras)

É semelhante ao comando TRI1 em F3DEX, exceto que as coordenadas e índices de textura no buffer de cores fornecidos como parâmetros do comando.

Conclusão:

Com um microcódigo tão avançado, é claro que poucos jogos N64 podem competir graficamente com Indiana Jones e Star Wars Episódio I: Batalha por Naboo.
Como as imagens falam mais alto do que as palavras, aqui estão alguns exemplos impressionantes do excelente exploit gráfico.

A iluminação é absolutamente esplêndida em Indiana Jones e na Máquina Infernal.

Por exemplo, no início do nível chamado Vulcão, 12 fontes de luzes são usadas ao mesmo tempo !!



Em outro nível chamado Templo de Palawan, luzes pontuais esplêndidas são exibidas.



As partículas são usadas em muitos lugares sem qualquer desaceleração em Indiana Jones e na Máquina Infernal e no Episódio I de Guerra nas Estrelas: Batalha por Naboo. Um exemplo, entre muitos, seria a neve.




O terreno no Episódio I de Star Wars: Batalha por Naboo é enorme e sem neblina.



Alguns efeitos de grandes explosões são frequentemente mostrados no Episódio I de Star Wars: Batalha por Naboo.



Efeitos esplêndidos de mapeamento de reflexão às vezes são usados.



Como você pode ver, os dois jogos são simplesmente incríveis para um Nintendo 64. Tendo em mente que os jogos também usam o microcódigo de áudio Musyx, o console provavelmente mostrou com eles o melhor que pode oferecer. Também prova que programadores qualificados podem superar as limitações de uma máquina muito além das expectativas !!!

Veredito
Indiana Jones e a Máquina Infernal é o Tomb Raider que os proprietários do Nintendo 64 nunca tiveram. É uma aventura de ação e quebra-cabeça complexa, às vezes absolutamente difícil, com belos visuais e um enredo divertido. Felizmente, o título também foi muito melhorado em relação ao seu predecessor para PC. LucasArts e Factor 5 retrabalharam muito o esquema de controle para que ele seja muito mais intuitivo e adequado para jogos de console. Além disso, os visuais foram aprimorados de forma semelhante para permitir uma melhor iluminação e efeitos de partículas, sem mencionar um grau espetacular de detalhes de textura para um carrinho de 64 bits

203926
 
Ultima Edição:

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303

Falkner

Bam-bam-bam
Mensagens
3.879
Reações
4.720
Pontos
303
Para ficar bom em tv moderna fullhd ou com resolução mais alta, creio que seja necessário um upscaler bom, pois nesse caso do rgb a resolução continuará baixa, mas deve ficar menos pior que no composto.
estava fazendo as contas aqui e ia ficar na faixa dos R$ 800,00 um gbs control(ou ossc)+cabo scart+mod rgb :kcaro:kcaro
 

Jefferson Praxedes

Bam-bam-bam
Mensagens
1.473
Reações
5.105
Pontos
303
As TVs mais modernas vai ter um trabalho para lidar com resoluções de 480i para baixo , fica tudo estivado, mesmo em componente vai ficar bem lavada a imagem . Como o @*ka falou melhor caminho é um OSSC , podes pegar do Aliexpress mesmo ! A hora que a minha de tubo de pau eu vou pegar um também !
 
Topo Fundo