O que há de Novo?
Fórum Outer Space - O maior fórum de games do Brasil

Registre uma conta gratuita hoje para se tornar um membro! Uma vez conectado, você poderá participar neste site adicionando seus próprios tópicos e postagens, além de se conectar com outros membros por meio de sua própria caixa de entrada privada!

  • 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]

Warrior Of Light

Bam-bam-bam
Mensagens
1.213
Reações
4.520
Pontos
453
TUTORIAL: COMPILANDO E UTILIZANDO O LIBDRAGON NO WINDOWS

Bem, vamos com algo novo, as roms geradas não vão funcionar na maioria dos emuladores (aqueles que só olham para libultra), vai funcionar em emuladores de baixo nível como MESS ou CEN64 e no Hardware original.

Em primeiro lugar, eu não encontrei um único tutorial que explique bem os passos, sempre acontece algo que não permite a compilação.

Isso foi testado no Windows 7 x64 e no Windows XP x86.

DOWNLOAD
Eu criei um ariquivo rar com um conjunto de recursos necessários:

- O libdragon vem com um makefile fixo, pois falha na compilação do mksprite, há um exemplo que montei que aparecerá no final do thread, para poder para colocar uma imagem na tela sem muitas dificuldades.

- Vem a versão x86 do cygwin (recomendado), o ambiente de trabalho que iremos utilizar.

- O Notepad ++ (versão portátil) vem com editor de texto, é necessário usar um editor que respeite a quebra de linha de um código, NÃO use Windows, ou Wordpad ou qualquer coisa do gênero.

Ele pode ser baixado aqui

INSTALAR CYGWIN
Descompacte N64kit.rar em uma pasta, dentro encontraremos "setup-x86.exe", execute-o.

Passos:

1) Escolhemos C: \ cygwin como caminho, sem complicações.

2) Conexão direta, os pacotes serão baixados automaticamente da internet (cygwin.netbet.org foi bastante rápido para mim)

3) Passo muito importante, escolhemos quais pacotes são instalados com o cygwin, encontraremos algo semelhante a este menu:



No motor de busca no canto superior esquerdo procuramos os seguintes pacotes, exibimos menus, marcamos como aparecem na imagem, queremos apenas os binários, não o "src":

gcc-core
gcc-g++
libmpc-devel
libpng-devel
wget
texinfo
make

* São cerca de 400MB de download, antes de instalar vai avisar que falta o libusb, aceitamos e pronto.

4) Deixamos a instalação criar um ícone na área de trabalho.

5) Copiamos a pasta libdragon que vem em N64kit.rar em " C: \ cygwin \ usr \ local "

COMPILAR AMBIENTE
1) Executamos o terminal Cygwin, o novo ícone na área de trabalho como administrador (clique direito), durante todo o tutorial NUNCA vamos sair do terminal, minimizar no máximo, nunca fechar.

2) Iremos obter uma janela semelhante ao console de comando msdos, o que vamos fazer é mover para a pasta que copiamos do libdragon, criar uma pasta temporária e copiar o arquivo de construção, com os seguintes comandos, pressione enter em cada um:

cd ..
cd ..
cd usr
cd local
cd libdragon
cd temp
./build

O último é o importante, em um computador razoavelmente rápido você pode passar 2 horas compilando , nós deixamos fazer isso.

Incluí no zip os arquivos que o build procura nos repositórios: binutils-2.25, gcc-5.1.0, newlib-2.2.0, para agilizar o processo.

3) Ao terminar, o cursor sairá novamente e poderemos escrever, verificamos se há algum texto de erro na tela, caso não haja, continuamos, escrevemos:

cd ..
export N64_INST=/usr/local
make
make install
make tools
make tools-install

* Com isso já teremos compilado o libdragon e todas as suas ferramentas, verificamos que não há erros, se em qualquer caso falharmos em algum dos passos devemos sempre ir para usr / local / libdragon para compilar algum dos passos anteriores .

COMPILANDO O LIBMIKMOD
Eu adicionei a biblioteca libmikmod pronta para compilar na pasta libdragon / temp, é inútil instalar a que vem com o cygwin porque é personalizada, tive que corrigir o makefile claro, vamos ao terminal e escrever:

cd temp
cd libmikmod
make
make install
cd ..
cd ..

Com isso, podemos compilar exemplos que carregam música, voltamos à raiz do libdragon.

EXEMPLO DE COMPILAÇÃO
1) Agora o seguinte é ir para a pasta de exemplos e compilar alguns, escrevemos:

cd examples
cd bmb
cd filesystem
$N64_INST/bin/mksprite 32 conker.png conker.sprite


Isso pega uma imagem PNG e a transforma em um sprite N64 compatível, para nos localizarmos na pasta, podemos acessá-la através do Windows Explorer em:

C: \ cygwin \ usr \ local \ libdragon \ examples \ bmb \ filesystem

Podemos alterar a imagem por qualquer outra em formato PNG se preferirmos, se tudo correr bem, terá sido criado conker.sprite na pasta.

2) Agora o seguinte é para compilar o exemplo, escrevemos:

cd ..
make

E ... depois de tanta história, ele terá compilado alguma coisa?



Se o fizemos corretamente, na pasta (C: \ cygwin \ usr \ local \ libdragon \ examples \ bmb \) aparecerão os seguintes arquivos, o que nos interessa é bmb.v64, copiamos para o SD de Everdrive 64 e é isso.



NOTAS
- Se quisermos mexer no código é o arquivo bmb.c, abrimos com o Notepad ++ (N64kit.rar)

- Os arquivos bmb.bin, bmb.elf, bmb.o, bmb.v64, spritemap. dfs são criados com o make, podemos excluí-los, se atualizarmos qualquer sprite na pasta do sistema de arquivos é OBRIGATÓRIO excluir spritemap.dfs ou não será atualizado quando compilado, esses arquivos são armazenados em cache para acelerar a compilação.

- É de vital importância lembrar:

export N64_INST = / usr / local

Teremos que escrever antes de compilar um exemplo se tivermos fechado o terminal.

- Cada vez que fecharmos o terminal teremos que voltar para o caminho (usr / local / libdragon)

cd ..
cd ..
cd usr
cd local
cd libdragon
cd examples

É essencial aprender a navegar pelos arquivos com o terminal, se quisermos ver o que a pasta atual contém, escrevemos "dir" no terminal

- Neste link há uma descrição de todas as funções da libdragon.

RESULTADOS
O teste de bmb é simplesmente uma imagem que pode ser movida pela tela usando o joystick analógico, o código que implementei para obter o fps é muito experimental, é baseado na teoria de que o ciclo do código é um quadro renderizado e que o relógio do sistema é independente, pode não ser exato, mas tudo parece indicar que o libdragon por padrão funciona a 30fps e você tem que modificar algum valor para alterá-lo.



Você pode usar sprites por hardware ou por software (que a cpu faz de tudo), obviamente por software é MUITO lento, se fizermos por software não tem limite de tamanho, você pode tirar uma imagem de 1MB e o N64 fará o que tem pode representá-lo, se usarmos sprites de hardware estamos limitados a 4KB do TMEM.

Nesse outro exemplo usei o modo 640x480x32bits , o máximo que o console dá, carreguei uma imagem de Link de 640x480 e 32bits de quase 1MB (do total 8MB com expansão), o desempenho é ... 3fps, como é de se esperar, acho que para modos de software o ideal seria usar 320x240 e 16bits.



LIMPEZA
Assim que tudo funcionar corretamente, podemos excluir a pasta temporária de C: \ cygwin \ usr \ local \ libdragon, não precisaremos mais dela e ela ocupa mais de 2 GB.

Vamos continuar experimentando para vermos se consigimos fazer alguma tech demo legal ou algo assim.
Sorrir


178263
 
Ultima Edição:

Jefferson Praxedes

Bam-bam-bam
Mensagens
2.051
Reações
7.547
Pontos
453
Aqui um game pouco conhecido , inclusive um porte vindo do PS1 o jogo ROBOTRON 64

6810_front.jpg


A parte técnica aqui não chega ser a respeito dos graficos em si, até porque o jogo tem uma premissa bem simples porem comparado a versão do PS1 o jogo teve um bom salto na qualidade geral .

"Todas as texturas e polígonos são muito mais bonitos do que a versão anterior", afirma Morrison. "Os gráficos são substancialmente melhores, os mapas de textura e as cores vão ficar melhores; há muito mais uso do sombreamento Gourard, fatos de iluminação mais interessantes. Essencialmente, todos os efeitos gráficos do N64 serão usados." Outra coisa que tornará os gráficos fortes é que a taxa de quadros também é consistente com 30 quadros por segundo, acrescentou Weising.

O que mais me chamou a atenção é a quantidade de inimigos em tela com frame rate estável, sim este é um dos poucos games que tem frame rate cravado sem slowdown, o qual segundo o dev não conseguiu atingir no PS1.

Tom Ketola

Trabalhei com jogos naquela época, especificamente em jogos para Playstation 1 e Nintendo 64. Durante esse tempo, trabalhei em vários títulos, mas vou entrar na história de um especificamente (que acabou nos dois sistemas). Fui o engenheiro principal do Robotron X para o PlayStation original e trabalhei como engenheiro sênior na versão N64 do mesmo jogo, Robotron 64. Nenhum desses jogos saiu da maneira que eu acho que qualquer um de nós gostaria , mas olhando para trás, serve como um bom exemplo para sua pergunta.


giphy.gif


Todos nós que trabalhamos na equipe éramos fãs do Robotron original. Gostamos do jogo por sua alta energia e desafio extremo. Embora uma sequência já tenha sido feita antes (Smash TV), que foi um sucesso por si só, muitos de nós sentimos que ela perdeu a energia e "nervosismo" do original. Também pensamos que Robotron, com seu conteúdo gerado por algoritmos, seria um candidato ideal para os recursos limitados disponíveis no PS1.

O PS1 tinha um limite de renderização de polígono de aproximadamente 3000-4000 triângulos por frame a 30fps e 1500-2000 por frame a 60fps. Em nossos cálculos, pensamos que poderíamos projetar inimigos com menos de 100 triângulos cada, e com isso esperávamos conseguir inimigos suficientes na tela para recriar o robotron original, em toda a sua glória de 8 bits, mas em 3D. Os únicos recursos artísticos necessários seriam os próprios personagens, então sentimos que poderíamos encaixar na memória do sistema (menos de 2 MB) e, portanto, transmitir a música do jogo a partir do disco.

giphy.gif


Assinamos um contrato e eu era o único engenheiro na versão Playstation (e o único com um kit de desenvolvimento). Tive cerca de 11 meses para concluir o projeto do início ao fim, mas esperávamos ter uma vantagem, já que outro engenheiro começou a trabalhar na parte do jogo usando um motor de renderização para PC, e meu trabalho seria pegar o código do jogo e colocá-lo em execução no PS1. Quando recebi meu kit de desenvolvimento, acredito que já tínhamos usado alguns desses 11 meses, mas o jogo era relativamente jogável no PC e parecia estar se dando bem, mas eu tinha um longo caminho a percorrer para conseguir em execução no dispositivo.

O primeiro problema que encontramos é que o acesso à memória no PS é * muito * lento. O jogo, mesmo sem nenhum gráfico rodando, rodou a menos de 30 fps devido ao uso extensivo de ponto flutuante. Meu primeiro trabalho foi converter todo o código existente para código inteiro, o que desencadeou todo um conjunto de problemas diferentes em torno de fazer as coisas escalarem corretamente e fazer as coisas se moverem da maneira que queríamos (particularmente em torno de colisões). Depois de rodar o jogo a uma velocidade decente, tive que começar a trabalhar na renderização do código. Mesmo que nosso código de transformação e renderização fosse bastante rápido, havia muita coisa na tela, e o pobre dispositivo simplesmente não conseguia acompanhar. Isso significa que tivemos que começar a mudar os elementos do próprio design para tentar permanecer dentro dos limites.

Nosso objetivo principal era reduzir o número de triângulos que estávamos desenhando e reduzimos nossos gráficos ao mínimo possível. Usamos principalmente triângulos com sombreado gouraud, mas sem textura para maximizar nossa renderização, e reduzimos o número de triângulos. Nossa contagem média de triângulos por inimigo era de cerca de 80 polígonos, então estávamos bem abaixo do limite que estabelecemos para nós mesmos. Isso ainda não era suficiente para compensar a sobrecarga do próprio código do jogo em execução e, portanto, para reduzir o orçamento, tivemos que acelerá-lo.

Infelizmente, a essa altura, estávamos atrasados no cronograma e todos trabalhávamos mais de 10 horas por dia em nosso cronograma comprimido para tentar terminar o jogo. Eu ainda era o único com um kit de desenvolvimento de Playstation, mas não tinha escrito o código do jogo em si, então as mudanças eram relativamente lentas. Nossos tempos de compilação foram em torno de 20 minutos, e isso não contou a sobrecarga de fazer as próprias alterações, nem para jogar até o ponto que queríamos testar. A primeira mudança que foi feita foi fazer com que os inimigos "deformassem" no nível conforme você os matasse, para que o jogo processasse menos inimigos. Nossa esperança era que pudéssemos encontrar outras maneiras de melhorar a velocidade e poder retirar essas mudanças, porque mudou fundamentalmente a forma como o jogo em si é jogado.

Por volta dessa época, foi a mesma época em que adicionamos nosso streaming de música. Infelizmente, isso teve o efeito colateral de usar uma parte significativa de nossa preciosa largura de banda de memória e teve um efeito em nossa velocidade de renderização. Agora não estávamos apenas acima do orçamento em nossa CPU, mas também em nosso processador gráfico. Para corrigir esse problema (e manter o jogo jogável), aumentamos o zoom da câmera para reduzir o número de inimigos desenhados. Isso também mudou fundamentalmente a maneira como o jogo era jogado, e nos obrigou a remover o modo "clássico" que havíamos colocado no jogo, com uma câmera totalmente suspensa da mesma perspectiva do original.

Nenhum de nós estava feliz com as mudanças, mas estávamos cumprindo os prazos de Natal e, após quase um ano de trabalho 7 dias por semana, o produto foi enviado. Em retrospecto, estou muito infeliz com o resultado do produto, mas fiquei aliviado por poder enviá-lo. Embora tenhamos cometido uma série de erros durante a produção que teriam melhorado o produto, em retrospectiva, acho que éramos muito ambiciosos com hardware relativamente novo e desconhecido e um cronograma apertado e, portanto, nosso projeto pode ter sido condenado desde o início. Esperávamos corrigir esses erros com a segunda versão do jogo, Robotron 64, que estava para ser lançado no Nintendo 64.

No segundo título, eu não era mais o único engenheiro (nem o líder, devido ao cronograma, ao tempo e ao excesso de trabalho no primeiro projeto). A versão do Nintendo 64 tinha algumas vantagens sobre a primeira. A grande vantagem que tinha era começar com uma base de código existente cujos pontos fracos e fortes já eram conhecidos. O Nintendo 64 também tinha memória muito * muito * rápida (para a época), sem tempos de carregamento (estando em um cartucho, você pode endereçar a memória diretamente). Ele também tinha um orçamento de renderização maior, mas como a arte já havia sido criada para uma plataforma inferior, ele tinha todos os tipos de orçamento de renderização extra para utilizar. Finalmente, ele não conseguia transmitir música, o que exigia corrigir um reprodutor de música rastreado, mas também não consumia uma grande parte da largura de banda da memória. Este projeto foi concluído em um período de tempo semelhante ao original (acredito um pouco menos, mas posso estar errado), mas foi um projeto relativamente lógico, sem o mesmo tipo de horas malucas. Também acabou sendo um jogo muito melhor por causa disso.


giphy.gif


Achei bem interessante o comentário do desenvolvedor, muitas vezes não adianta voce ter um disco com bastante espaço para fazer jogos sem limitações , esse tipo de jogo caiu como uma luva na arquitetura de cartucho do N64

 

Falkner

Ei mãe, 500 pontos!
Mensagens
7.628
Reações
10.607
Pontos
753
Console complicado esse n64.
Recentemente adquirir um, junto com uma tv de tubo (famosa sony wega 21" que tanto falam) e everdrive do aliexpress
Gastei uma graninha, tudo isso pra descobrir que a imagem fica b*sta no cabo composto.
Tá virando muito gasto pra pouca diversão.
Estou tentando vender essa TV para pegar uma com s-video ou de 14"




 

Warrior Of Light

Bam-bam-bam
Mensagens
1.213
Reações
4.520
Pontos
453
Console complicado esse n64.
Recentemente adquirir um, junto com uma tv de tubo (famosa sony wega 21" que tanto falam) e everdrive do aliexpress
Gastei uma graninha, tudo isso pra descobrir que a imagem fica b*sta no cabo composto.
Tá virando muito gasto pra pouca diversão.
Estou tentando vender essa TV para pegar uma com s-video ou de 14"




Faz o mod RGB (pague algum tecnico se estiver com medo de estragar o aparelho) e compra um cabo SCART, voce vai jogar na excelencia. Muito melhor do que cabo S-Video e cabo Composto é porcaria mesmo (fuja disso o máximo que puder). Tu vai gastar mais grana, mas compensa cada centavo investido.

178292


 
Ultima Edição:

Jefferson Praxedes

Bam-bam-bam
Mensagens
2.051
Reações
7.547
Pontos
453
Console complicado esse n64.
Recentemente adquirir um, junto com uma tv de tubo (famosa sony wega 21" que tanto falam) e everdrive do aliexpress
Gastei uma graninha, tudo isso pra descobrir que a imagem fica b*sta no cabo composto.
Tá virando muito gasto pra pouca diversão.
Estou tentando vender essa TV para pegar uma com s-video ou de 14"

pois é cara voce não tá aproveitando nem o console nem a TV com cabo de video composto, essas wegas são muito cobiçadas , faz o que eu te falei lá no outro topico
compra o cabo RBG pra Componente, mas antes tem que instalar o mod que reabilita a saida RGB do console
eu tenho uma wega de 29 olha como fica :

d8zljjj.jpg


Epv7duZ.jpg


o mesmo cabo tu aproveita no super nintendo sem mod nenhum

ldxsozx.jpg
 

*ka

Mil pontos, LOL!
Mensagens
11.773
Reações
11.462
Pontos
1.344
Console complicado esse n64.
Recentemente adquirir um, junto com uma tv de tubo (famosa sony wega 21" que tanto falam) e everdrive do aliexpress
Gastei uma graninha, tudo isso pra descobrir que a imagem fica b*sta no cabo composto.
Tá virando muito gasto pra pouca diversão.
Estou tentando vender essa TV para pegar uma com s-video ou de 14"





Eu não acho que a imagem fica ruim com cabo de vídeo composto. Esse teu console não está convertido para PAL-M? Se for modelo americano convertido para PAL-M não fica legal.

O que eu acho engraçado de hoje em dia é que pessoal que usar console velho e tv velha, mas não aceita a qualidade de imagem que se tinha na época a inventa gambiarras para tentar melhorar a imagem. Eu que quem quer uma qualidade superior a da época tem que partir para emuladores, sai muito mais barato e roda bem a maior parte dos jogos e em uma tela maior, pois telas de lcd ou oled normalmente são maiores que uma crt.
 


Warrior Of Light

Bam-bam-bam
Mensagens
1.213
Reações
4.520
Pontos
453
Eu não acho que a imagem fica ruim com cabo de vídeo composto. Esse teu console não está convertido para PAL-M? Se for modelo americano convertido para PAL-M não fica legal.

O que eu acho engraçado de hoje em dia é que pessoal que usar console velho e tv velha, mas não aceita a qualidade de imagem que se tinha na época a inventa gambiarras para tentar melhorar a imagem. Eu que quem quer uma qualidade superior a da época tem que partir para emuladores, sai muito mais barato e roda bem a maior parte dos jogos e em uma tela maior, pois telas de lcd ou oled normalmente são maiores que uma crt.
Tem que olhar se o cabo Composto dele é Chinês tbm, sacrifica ainda mais a qualidade. Outra opção para ele é justamente essa que voce falou, recorrer aos emuladores.
 

Falkner

Ei mãe, 500 pontos!
Mensagens
7.628
Reações
10.607
Pontos
753
Faz o mod RGB (pague algum tecnico se estiver com medo de estragar o aparelho) e compra um cabo SCART, voce vai jogar na excelencia. Muito melhor do que cabo S-Video e cabo Composto é porcaria mesmo (fuja disso o máximo que puder). Tu vai gastar mais grana, mas compensa cada centavo investido.

Visualizar anexo 178292



pois é cara voce não tá aproveitando nem o console nem a TV com cabo de video composto, essas wegas são muito cobiçadas , faz o que eu te falei lá no outro topico
compra o cabo RBG pra Componente, mas antes tem que instalar o mod que reabilita a saida RGB do console
eu tenho uma wega de 29 olha como fica :

d8zljjj.jpg


Epv7duZ.jpg


o mesmo cabo tu aproveita no super nintendo sem mod nenhum

ldxsozx.jpg
Eu não acho que a imagem fica ruim com cabo de vídeo composto. Esse teu console não está convertido para PAL-M? Se for modelo americano convertido para PAL-M não fica legal.

O que eu acho engraçado de hoje em dia é que pessoal que usar console velho e tv velha, mas não aceita a qualidade de imagem que se tinha na época a inventa gambiarras para tentar melhorar a imagem. Eu que quem quer uma qualidade superior a da época tem que partir para emuladores, sai muito mais barato e roda bem a maior parte dos jogos e em uma tela maior, pois telas de lcd ou oled normalmente são maiores que uma crt.
Tem que olhar se o cabo Composto dele é Chinês tbm, sacrifica ainda mais a qualidade. Outra opção para ele é justamente essa que voce falou, recorrer aos emuladores.

Agradeço as respostas mas fazendo as contas aqui, realizar o mod pra mim é um tanto quanto inviável, pois terei que gastar com muita coisa, visto que não tenho nada (ferramenta de solda, chave pra abrir o console, etc).

Meu console é PAL-M, e estou usando cabo composto paralelo, então creio que seja o pior cenário possível. Não precisa ser aquela imagem perfeita, mas do jeito que está é bem ruim, sinceramente, pois não dá pra enxergar nada direito.

O que estou propenso a fazer é vender essa minha TV e pegar uma de 21" com S-VIDEO. Encontrei essa daqui no marketplace:

178323

E comprar um cabo simples desses que tem no ML/Aliexpress:

178324

De acordo com esse vídeo aqui o resultado é muito bom:




Eu tenho PC bom com retroarch configurado, mas peguei o console mais pela nostalgia, e tbm pq emular nintendo 64 é um saco.
 

Fabio Alexandre

Bam-bam-bam
Mensagens
1.299
Reações
2.141
Pontos
453
Sim...... S-Video é uma grande evolução perto do Cabo Composto, usei durante anos o S-Video no Nintendo 64 até fazer o Mod RGB e usar componente. Aconselho também a trocar o Nintendo 64 por um Americano NTSC ou levar pra um técnico trocar a transcodificação pra NTSC, que tem resolução superior.
 

Falkner

Ei mãe, 500 pontos!
Mensagens
7.628
Reações
10.607
Pontos
753
Antes de pensar em fazer qualquer m**** é melhor abrir o console e verificar o chip, correto? Achei meio caro a chave pra abrir...

Vi também que tem umas 3 versões do modchip
 

Falkner

Ei mãe, 500 pontos!
Mensagens
7.628
Reações
10.607
Pontos
753
Pergunta noob, onde eu encaixo esse cabo scart? :klol nunca vi essa entrada antes
 

Warrior Of Light

Bam-bam-bam
Mensagens
1.213
Reações
4.520
Pontos
453
Pergunta noob, onde eu encaixo esse cabo scart? :klol nunca vi essa entrada antes
Você encaixaria num conversor como este.

179592

Mas no seu caso é um pouco diferente, já que você comprou essa TV pra jogar, depois de fazer o Mod você compra o cabo de RGB para Componente e vai poder aproveitar sua Sony Wega e jogar numa imagem infinitamente melhor.


Existe outra opção pra jogar muito melhor ainda no Hardware original, mas nem vou falar pois é uma facada no bolso. Se quiser resultados melhores do que isso só no emulador mesmo (visando custo e benéfico).
 
Ultima Edição:

Sword of Light

Habitué da casa
Mensagens
48
Reações
85
Pontos
58
Se não fosse pela internet eu nunca diria que o Goldeneye rodava a 20 fps. Na verdade ele tinha aquele turbo mode que deixava o jogo rápido igual ao Quake.

 

Cristiano Sword

Bam-bam-bam
Mensagens
2.296
Reações
10.701
Pontos
453
TUTORIAL: COMPILANDO E UTILIZANDO O LIBDRAGON NO WINDOWS

Bem, vamos com algo novo, as roms geradas não vão funcionar na maioria dos emuladores (aqueles que só olham para libultra), vai funcionar em emuladores de baixo nível como MESS ou CEN64 e no Hardware original.

Em primeiro lugar, eu não encontrei um único tutorial que explique bem os passos, sempre acontece algo que não permite a compilação.

Isso foi testado no Windows 7 x64 e no Windows XP x86.

DOWNLOAD
Eu criei um ariquivo rar com um conjunto de recursos necessários:

- O libdragon vem com um makefile fixo, pois falha na compilação do mksprite, há um exemplo que montei que aparecerá no final do thread, para poder para colocar uma imagem na tela sem muitas dificuldades.

- Vem a versão x86 do cygwin (recomendado), o ambiente de trabalho que iremos utilizar.

- O Notepad ++ (versão portátil) vem com editor de texto, é necessário usar um editor que respeite a quebra de linha de um código, NÃO use Windows, ou Wordpad ou qualquer coisa do gênero.

Ele pode ser baixado aqui

INSTALAR CYGWIN
Descompacte N64kit.rar em uma pasta, dentro encontraremos "setup-x86.exe", execute-o.

Passos:

1) Escolhemos C: \ cygwin como caminho, sem complicações.

2) Conexão direta, os pacotes serão baixados automaticamente da internet (cygwin.netbet.org foi bastante rápido para mim)

3) Passo muito importante, escolhemos quais pacotes são instalados com o cygwin, encontraremos algo semelhante a este menu:



No motor de busca no canto superior esquerdo procuramos os seguintes pacotes, exibimos menus, marcamos como aparecem na imagem, queremos apenas os binários, não o "src":

gcc-core
gcc-g++
libmpc-devel
libpng-devel
wget
texinfo
make

* São cerca de 400MB de download, antes de instalar vai avisar que falta o libusb, aceitamos e pronto.

4) Deixamos a instalação criar um ícone na área de trabalho.

5) Copiamos a pasta libdragon que vem em N64kit.rar em " C: \ cygwin \ usr \ local "

COMPILAR AMBIENTE
1) Executamos o terminal Cygwin, o novo ícone na área de trabalho como administrador (clique direito), durante todo o tutorial NUNCA vamos sair do terminal, minimizar no máximo, nunca fechar.

2) Iremos obter uma janela semelhante ao console de comando msdos, o que vamos fazer é mover para a pasta que copiamos do libdragon, criar uma pasta temporária e copiar o arquivo de construção, com os seguintes comandos, pressione enter em cada um:

cd ..
cd ..
cd usr
cd local
cd libdragon
cd temp
./build

O último é o importante, em um computador razoavelmente rápido você pode passar 2 horas compilando , nós deixamos fazer isso.

Incluí no zip os arquivos que o build procura nos repositórios: binutils-2.25, gcc-5.1.0, newlib-2.2.0, para agilizar o processo.

3) Ao terminar, o cursor sairá novamente e poderemos escrever, verificamos se há algum texto de erro na tela, caso não haja, continuamos, escrevemos:

cd ..
export N64_INST=/usr/local
make
make install
make tools
make tools-install

* Com isso já teremos compilado o libdragon e todas as suas ferramentas, verificamos que não há erros, se em qualquer caso falharmos em algum dos passos devemos sempre ir para usr / local / libdragon para compilar algum dos passos anteriores .

COMPILANDO O LIBMIKMOD
Eu adicionei a biblioteca libmikmod pronta para compilar na pasta libdragon / temp, é inútil instalar a que vem com o cygwin porque é personalizada, tive que corrigir o makefile claro, vamos ao terminal e escrever:

cd temp
cd libmikmod
make
make install
cd ..
cd ..

Com isso, podemos compilar exemplos que carregam música, voltamos à raiz do libdragon.

EXEMPLO DE COMPILAÇÃO
1) Agora o seguinte é ir para a pasta de exemplos e compilar alguns, escrevemos:

cd examples
cd bmb
cd filesystem
$N64_INST/bin/mksprite 32 conker.png conker.sprite


Isso pega uma imagem PNG e a transforma em um sprite N64 compatível, para nos localizarmos na pasta, podemos acessá-la através do Windows Explorer em:

C: \ cygwin \ usr \ local \ libdragon \ examples \ bmb \ filesystem

Podemos alterar a imagem por qualquer outra em formato PNG se preferirmos, se tudo correr bem, terá sido criado conker.sprite na pasta.

2) Agora o seguinte é para compilar o exemplo, escrevemos:

cd ..
make

E ... depois de tanta história, ele terá compilado alguma coisa?



Se o fizemos corretamente, na pasta (C: \ cygwin \ usr \ local \ libdragon \ examples \ bmb \) aparecerão os seguintes arquivos, o que nos interessa é bmb.v64, copiamos para o SD de Everdrive 64 e é isso.



NOTAS
- Se quisermos mexer no código é o arquivo bmb.c, abrimos com o Notepad ++ (N64kit.rar)

- Os arquivos bmb.bin, bmb.elf, bmb.o, bmb.v64, spritemap. dfs são criados com o make, podemos excluí-los, se atualizarmos qualquer sprite na pasta do sistema de arquivos é OBRIGATÓRIO excluir spritemap.dfs ou não será atualizado quando compilado, esses arquivos são armazenados em cache para acelerar a compilação.

- É de vital importância lembrar:

export N64_INST = / usr / local

Teremos que escrever antes de compilar um exemplo se tivermos fechado o terminal.

- Cada vez que fecharmos o terminal teremos que voltar para o caminho (usr / local / libdragon)

cd ..
cd ..
cd usr
cd local
cd libdragon
cd examples

É essencial aprender a navegar pelos arquivos com o terminal, se quisermos ver o que a pasta atual contém, escrevemos "dir" no terminal

- Neste link há uma descrição de todas as funções da libdragon.

RESULTADOS
O teste de bmb é simplesmente uma imagem que pode ser movida pela tela usando o joystick analógico, o código que implementei para obter o fps é muito experimental, é baseado na teoria de que o ciclo do código é um quadro renderizado e que o relógio do sistema é independente, pode não ser exato, mas tudo parece indicar que o libdragon por padrão funciona a 30fps e você tem que modificar algum valor para alterá-lo.



Você pode usar sprites por hardware ou por software (que a cpu faz de tudo), obviamente por software é MUITO lento, se fizermos por software não tem limite de tamanho, você pode tirar uma imagem de 1MB e o N64 fará o que tem pode representá-lo, se usarmos sprites de hardware estamos limitados a 4KB do TMEM.

Nesse outro exemplo usei o modo 640x480x32bits , o máximo que o console dá, carreguei uma imagem de Link de 640x480 e 32bits de quase 1MB (do total 8MB com expansão), o desempenho é ... 3fps, como é de se esperar, acho que para modos de software o ideal seria usar 320x240 e 16bits.



LIMPEZA
Assim que tudo funcionar corretamente, podemos excluir a pasta temporária de C: \ cygwin \ usr \ local \ libdragon, não precisaremos mais dela e ela ocupa mais de 2 GB.

Vamos continuar experimentando para vermos se consigimos fazer alguma tech demo legal ou algo assim.
Sorrir


Muito Top seu post!
merecia um topico só pra esses testes :)

Agora uma coisa que fiquei intrigado, como e pq uma makelib gerada pelo GCC demora 2 horas pra compilar? (No caso a libdragon)

Tem alguma coisa errada ou diferente nesse makelib? não é possivel demorar tanto assim.
Nem uma makelib de Dreamcast ou até mesmo PS2 demora tanto pra compilar.
 

Warrior Of Light

Bam-bam-bam
Mensagens
1.213
Reações
4.520
Pontos
453
Muito Top seu post!
merecia um topico só pra esses testes :)

Agora uma coisa que fiquei intrigado, como e pq uma makelib gerada pelo GCC demora 2 horas pra compilar? (No caso a libdragon)

Tem alguma coisa errada ou diferente nesse makelib? não é possivel demorar tanto assim.
Nem uma makelib de Dreamcast ou até mesmo PS2 demora tanto pra compilar.
Essa makelib é lenta para compilar arquivos grandes e consome muita memória, a grande expressão no código coloca uma grande carga no alocador de registradores, além dos gargalos de tempo de compilação que são causados por algoritmos ruins, esse tipo de código mostra um péssimo comportamento de tempo de compilação e tornam o compilador muito lento. Se tem alguma optimização que reduz o tempo de compilação e o tamanho do arquivo eu não estou ciente, mas essa makelib ainda está muito precária e eu sou apenas um "curioso."

Os caras que realmente estão em outra dimensão são o Itália64/Conker64, Krom e Jnmartin84.
 
Ultima Edição:

Warrior Of Light

Bam-bam-bam
Mensagens
1.213
Reações
4.520
Pontos
453
Turok 3 (N4TKER09 Prototype)

Existem diferentes builds do Turok 3, o jogo foi lançado 3 meses depois, o fato é que o estado do beta é surpreendente e tudo o que eles fizeram em apenas 3 meses, nessa versão temos o modo de Debug dentro do jogo, onde podemos colocar o personagem em terceira pessoa (entre outras coisas como desativar o FOG, sombras, arma, etc), isso é algo INSANO, pois se trata daquele mesmo modelo de alta geometria das cut-cenes, porém, em ambiente real de jogo.

Esse é o menu de Debug.

180713

Este é o modelo da personagem in-game.

180714

Também nos permite ver a taxa de quadros para obter detalhes interessantes (embora a versão final pareça ser um pouco melhor, mas você pode sair desativando várias opções no menu de depuração), onde em baixa resolução roda em 30 fps com quedas para 20/15 fps na maioria das vezes. Desabilitar outros recursos pode melhorar o desempenho. Mas o modelo de alta geometria em tela não afeta o desempenho.

180716

Não existem outros modelos de personagens in-game com geometria maior do que isso, eu realmente fiquei impressionado. Todos os personagens possuem cerca de 3.000 polígonos e mais de 9.000 vértices, tem muito jogo da próxima geração que tem bem menos do que isso.

180718



Turok 2 (Kiosk Demo)


Esta é outra build só que do jogo anterior, onde optimizaram o jogo para rodar com melhor desempenho, o que eu pude perceber é que na optimização conseguiram descartar alguns polígonos que antes estavam sendo processados a toa, apenas consumindo parte do processamento (visto que a maioria dos motores gráficos no N64 não descartavam o que não era visto na tela). Onde em algumas partes o jogo roda em 60 fps, enquanto em outras em 30 fps com algumas quedas (e ficam alternando entre isso).




Porém, existem bugs e outras falhas, o projeto não teve continuação (assim como a build do Turok 3 de N4TKER09 postada anteriormente), o que teria sido desses jogos se tivessem mais tempo de desenvolvimento? Bom, pelo que foi mostrado é fácil concluir que o frame-rate e geometria seriam ainda melhores, optimização é tudo.


Stunt Racer 64

Esse jogo utiliza o mesmo micro-códido do WDC, o Z-SORT e consegue impressionar ainda mais que o próprio WDC, pois o micro-código está mais optimizado, o primeiro feito mais impressionante são os cenários em volta, que são muito animados (diferente de outros jogos onde tudo era estático), muitas coisas em volta estão se movendo por todos os lados, e o segundo feito é a iluminação/sombreamento dinâmico que escurece ou altera a cor do carro quando ele passa por uma fonte de luz ou algum local escuro, além disso, as fontes de luz nesse jogo têm várias tonalidades diferentes, então você notará a lataria do carro sendo tonificada por várias cores diferentes, a troca de paletas nos carros é constante (além de outros reflexos como o próprio cenário sendo espelhado na lataria), deixei marcado essa parte no vídeo.




Como a mesma engine do WDC foi usada, aqui você notará vários feitos técnicos avançados, pois o jogo roda em 30 fps cravados mesmo com 4 players simultâneos, com enorme draw distance, texturas muito boas, e claro, alta geometria dos carros e cenários, carros fazendo várias acrobacias no ar com extrema fluídez, iluminação e sombreamento dinâmico, reflexos variados e avançados, 6 carros em tela, vários itens espalhados na pista (como moedas) e conforme você corre por elas, você notará animais incríveis e gigantescos, enormes edifícios saltitantes e palhaços psicodélicos - todos animados para que seus sentidos de jogo fiquem bem despertados, é uma corrida maluca onde você viaja num universo imaginário de uma criança, com carros antigos correndo em pistas futurísticas e fazendo loucas manobras, o jogo também possui suporte a alta resolução (em letterbox), deixando tudo bem nítido e fazendo uso do Expansion Pak para desfrutar de tudo o que esse jogo oferece.

A Boss Game Studios mostrou mais uma vez como extrair potencial do Nintendo 64, se te perguntarem qual é o jogo de corrida mais impressionante da época, não tenha dúvidas, Stunt Race 64 se destaca por tudo que ele pode oferecer, alta geometria, efeitos avançados, cenários animados, várias acrobacias, draw distance, iluminação/sombreamento, texturas, alta resolução e jogabilidade muito fluída, tudo em um único jogo. Não é apenas um feito técnico ou outro que impressiona, mas vários deles reunidos no mesmo pacote.

 
Ultima Edição:

Jefferson Praxedes

Bam-bam-bam
Mensagens
2.051
Reações
7.547
Pontos
453
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

Ei mãe, 500 pontos!
Mensagens
1.018
Reações
141
Pontos
804
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
1.213
Reações
4.520
Pontos
453



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
2.051
Reações
7.547
Pontos
453
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:
 

Sega&AMD

Ei mãe, 500 pontos!
Mensagens
13.706
Reações
13.740
Pontos
803
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
2.051
Reações
7.547
Pontos
453
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:

Gustavo Reis

Bam-bam-bam
Mensagens
1.262
Reações
2.377
Pontos
453
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
134
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.
 

Luke 64

Ser evoluído
Mensagens
187
Reações
134
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
 

Gustavo Reis

Bam-bam-bam
Mensagens
1.262
Reações
2.377
Pontos
453
@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
2.051
Reações
7.547
Pontos
453
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

53646122-b3927380-3c3a-11e9-9753-076891265654.png


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.

vPYUhrW.jpg



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
2.296
Reações
10.701
Pontos
453
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^^
 
Topo Fundo