Base do port#
O trabalho começou com o estudo de conteúdo da Definitive Edition para Android. Isso gerou uma biblioteca de recursos e uma prévia 3D. Para chegar a uma experiência clássica jogável, adotamos depois a base aberta reVC Web / wasm-revc, compilada para WebAssembly, usando dados da edição PC clássica.
Jogo clássico e prévia 3D. O jogo do menu usa a engine clássica e arquivos nativos. A prévia da Definitive Edition usa modelos convertidos para Three.js. Cada rota tem formatos e otimizações próprios; os ganhos de uma não descrevem automaticamente a outra.
A comunidade já havia construído partes essenciais: a engine reVC, sua adaptação Web e um runtime de streaming. Nosso trabalho reaproveita essas bases e documenta a integração, as correções de I/O e áudio, a restauração de recursos, os perfis de carregamento, a instrumentação e a entrega no site.
Este é um estudo de um experimento em evolução. Há trechos de jogo e sistemas verificados; campanha inteira e equivalência audiovisual completa continuam abertas.
Engine, navegador e arquivos#
A engine executa a lógica clássica. O navegador fornece renderização, áudio, entrada e acesso à rede. A adaptação conecta a leitura nativa de arquivos a esse ambiente.
- Página e comandos
- HTML e CSS apresentam o jogo. JavaScript inicia a engine após Jogar e conecta a interface ao navegador.
- Engine em WebAssembly
- O código C/C++ compilado executa os sistemas nativos. Este build usa WebGL2 e áudio OpenAL.
- Arquivos por demanda
- O FS virtual conserva caminhos e tamanhos. O streamer resolve as leituras em blocos, cache e rede.
WebAssembly é o formato de execução do código compilado. Compilar a engine é uma parte do port. Fazer seus caminhos de áudio, arquivos, memória e atualização cooperarem com o navegador exige adaptação adicional. O Emscripten distingue arquivos embutidos e pré-carregados; escolher um pacote de dados não implementa sozinho o streaming conforme o uso. Referência de empacotamento.
| Formato | Papel | Decisão deste port |
|---|---|---|
| DFF | Modelos e geometria. | Conservar a leitura nativa. |
| TXD | Dicionários de texturas. | Preservar materiais e ligação às malhas. |
| IMG | Arquivo que reúne recursos. | Buscar intervalos sem exigir o corpo inteiro. |
| SCM | Programa de missões e scripts. | Executar pela engine clássica. |
| Áudio e tabelas | Falas, música, efeitos e metadados. | Antecipar só o necessário e conservar as amostras. |
A engine pede bytes como antes; a camada Web decide como obtê-los. Essa fronteira precisa respeitar quando a engine pode esperar e quando exige uma leitura concluída.
Processo de desenvolvimento#
O projeto foi conduzido por Alan Nicolas, com assistência de IA para pesquisar fontes, ler código, implementar adaptações, investigar falhas e produzir verificações. A direção foi refinada ao jogar e revisar as entregas: primeiro a biblioteca, depois uma execução Web, os problemas de textura, desempenho, banda, controles e acesso pelo celular. Os pedidos de Alan definiram as prioridades e o acabamento que precisava ser preservado.
O port usa as bases comunitárias reVC, wasm-revc e wasm.com.br. As revisões e os créditos estão em Fontes e créditos.
Workflow de desenvolvimento
O trabalho foi dividido em rodadas, com fonte identificada, tarefa delimitada, alteração de código e verificação. Código, decisões e resultados foram registrados para a sessão seguinte.
- Definir o trecho a executar
Separar os marcos: menu, partida, movimento com controles livres, rua, interior e retorno ao jogo. Na biblioteca, contar as coleções e abrir os recursos no consumidor correspondente. O plano registra a cobertura de cada trecho.
- Identificar a versão e as dependências
Registrar edição, revisão de código e hashes. A fonte inicial é a Definitive Edition Android 1.90.0; a execução clássica usa dados PC e reVC Web. Essas bases têm formatos e sistemas distintos.
- Pesquisar a alteração
Ler o código e a documentação do sistema afetado. Na compressão, verificar como a engine pede bytes, quais offsets espera e quando a leitura precisa terminar.
- Relacionar recursos aos sistemas que os usam
Mapear modelos, texturas, animações, áudio, mapas e scripts. Rastrear o recurso desde o registro e o setor do arquivo até o carregador, o material e a instância desenhada.
- Integrar a engine
Montar o sistema de arquivos, chegar ao menu e liberar o jogador. Observar posição, quadros, pausa e leituras. O visualizador de modelos fica separado da campanha para não alterar os slots usados pelos scripts.
- Reproduzir o defeito
Guardar revisão, cenário, entrada e resultado. Isolar a falha em I/O, áudio, cache, material, toque ou hospedagem. Cada defeito devolvido por Alan recebe uma verificação nomeada.
- Preservar os dados afetados
Definir o que deve permanecer igual: bytes, PCM, pixels, glifos, escala, física e resolução. Filas conservam ordem e cancelamento; canais pendentes conservam a identidade do som.
- Medir carregamento e desempenho
Separar página, clique, menu, jogador livre e exploração. Registrar arquivos, bytes e quadros com cache frio e quente. Comparações de desempenho usam a mesma arte, percurso e pares intercalados.
- Conferir comportamento e aparência
Rodar o validador principal e os cenários afetados. Comparar poses e animações no mesmo instante. Para coleções, conferir o conjunto declarado e distinguir carga técnica de inspeção visual.
- Registrar a rodada
Versionar código, fontes, decisões, falhas e próximo passo. Tarefas auxiliares têm objetivo e área delimitados. As 149 sessões auxiliares identificadas na auditoria ocorreram ao longo do projeto, sem indicar execução simultânea.
- Publicar o build
Comparar o manifesto de produção com o publicado e enviar os arquivos alterados. Conferir hashes, MIME, Range, cache, isolamento e versão na hospedagem. Atualizações de texto e estilo mantêm o site disponível durante o envio dos metadados.
- Conferir a URL entregue
Abrir o site publicado e repetir o fluxo afetado. Registrar falhas e lacunas para a próxima rodada, como áudio ausente, material sem textura ou comando de toque perdido entre quadros.
Quais IAs participaram
- GPT-6.1 Sol
gpt-6.1-sol - Pesquisa, leitura da engine, implementação, diagnóstico, testes e documentação no Codex.Identificador encontrado nos registros de turnos do projeto.
- GPT-6 Astra
gpt-6-astra - Participação no trabalho técnico conduzido pelo Codex.Identificador encontrado nos registros. O histórico acumulado não permite separar com precisão os tokens entre Sol e Astra.
- Claude Opus 5.5
claude-opus-5-5 - Interface de abertura, menus e ajustes da bancada de modelos.A conversa do menu registra alterações nesses arquivos e 230 respostas únicas com uso contabilizado.
- Gemini 4 Argon
Antigravity - Compressão e otimização dos objetos 3D, streaming e carregamento por demanda para os primeiros minutos. A etapa 3D está em Compressão dos objetos 3D.Nome do modelo informado por Alan Nicolas. Os tokens foram conferidos nos recortes locais; os registros de uso não trazem o identificador exato do modelo.
Alan definiu as prioridades e revisou as entregas. C/C++, Emscripten, JavaScript, Python e navegadores automatizados foram usados para compilar, integrar e verificar as alterações. Os menus feitos no Claude foram mantidos durante as otimizações de carregamento.
O total reúne os registros identificados de Codex, Claude e os recortes do Antigravity descritos abaixo. Cada origem conserva seu corte e sua forma de contar cache.
Tokens registrados
Os registros locais de Codex, Claude e dos recortes do Antigravity somam 7.349.836.566 tokens, incluindo leituras de contexto em cache. O levantamento cobre os recortes identificados; outras máquinas, conversas e atividade posterior podem ficar de fora.
Corte do Codex: 21/10/2026 às 01:24:05, horário de Brasília, ou 04:24:05 UTC. Última resposta do Claude contabilizada: 20/10/2026 às 22:01:32, horário de Brasília. O recorte do Antigravity termina em 21/10/2026 às 02:19:24, horário de Brasília. Atividade posterior a cada corte fica fora deste retrato.
| Componente | Codex · conjunto Vice City | Claude · conversa do menu | Gemini · recortes Antigravity |
|---|---|---|---|
| Entrada total | 7.186.744.106 | 43.060.419 | 91.487.426 |
| Leitura de entrada em cache | 7.084.412.032 | 42.583.793 | 88.104.036 |
| Entrada fora de leitura de cache | 102.332.074 | 492 de entrada comum + 476.134 de criação de cache | 3.383.390 |
| Saída registrada | 28.034.996 | 157.637 | 351.982 |
| Total por origem | 7.214.779.102 | 43.218.056 | 91.839.408 |
Leituras de cache. Em uma execução longa, o contexto e os resultados de ferramentas voltam em muitas requisições. A mesma informação pode ser lida repetidamente e aparecer como entrada reutilizada. Neste agregado, cerca de 98,17% do total corresponde a leituras de cache. Isso não significa bilhões de tokens de código novo, nem mede o tamanho do jogo.
Descontadas somente as leituras de cache, restam 134.736.705 tokens no agregado: entrada fora dessas leituras, criação de cache do Claude e saída das três origens. A parcela restante também pode conter contexto repetido e não equivale a uma cobrança. Cada fornecedor usa sua própria tokenização, portanto a soma é uma contagem administrativa dos registros, não uma medida universal de texto.
Recortes do Gemini no Antigravity
A otimização de ativos 3D e de carregamento soma 597 chamadas, 3.600.971 tokens fora de leitura de cache e 90.834.850 no total bruto. Dez chamadas posteriores para apurar o consumo levam o retrato ampliado a 607 chamadas e 91.839.408 tokens brutos. O agregado do projeto usa esse retrato ampliado.
| Etapa | Chamadas | Fora de leitura de cache | Leitura de cache | Total bruto |
|---|---|---|---|---|
| Ativos 3D | 222 | 1.270.843 | 30.825.892 | 32.096.735 |
| Streaming e demanda inicial | 375 | 2.330.128 | 56.407.987 | 58.738.115 |
| Contagem do consumo do GTA | 10 | 134.401 | 870.157 | 1.004.558 |
Foram somados os eventos únicos dos passos 0 a 509 da frente 3D, 500 a 1356 da frente de carregamento e 1357 a 1377 da apuração. O total de 607 chamadas enviado por Alan confere até o passo 1377. Estender a seleção até 1385 inclui mais três chamadas de contagem. Os trechos sobre Casa 49 e Hades II ficaram fora.
Comparação da janela de otimização
Alan também forneceu um recorte do Codex para a otimização: 407.778.300 tokens na conversa principal e 35.730.409 em oito sessões de revisão automática, totalizando 443.508.709. Somado ao retrato ampliado do Gemini, esse comparativo registra 535.348.117 tokens brutos: 14.176.049 fora de leituras de cache e 521.172.068 em cache.
Esse comparativo é o recorte informado por Alan. Não foi adicionado ao agregado do projeto: a conversa principal se sobrepõe à contagem anterior, e a seleção das oito revisões ainda não foi conciliada por identificador. Usar um início anterior ao primeiro contador observado também muda o delta da janela.
Método de contagem
- Codex: 150 sessões identificadas do projeto: uma conversa principal e 149 sessões auxiliares/de revisão. Há uso em 149; uma não tem contador disponível e fica fora da soma. Cada identificador entra uma vez. Da conversa longa, usamos o último contador acumulado, sem somar os eventos acumulados entre si nem adicionar páginas históricas novamente.
- Continuidade da evidência: 23 sessões têm leitura atual do arquivo canônico; 126 reaproveitam sua medição histórica selada de 16/10, identificador por identificador. Os contadores disponíveis coincidem com o retrato do banco local. Arquivos históricos indisponíveis não foram reconstruídos por estimativa.
- Claude: 230 respostas únicas. Os 224 registros repetidos do fluxo de respostas foram descartados. Para o mesmo identificador, a entrada precisa coincidir e conserva-se a maior saída observada. Detalhes internos de cache e iterações não são somados de novo.
- Antigravity: somar entrada, leitura de cache e saída dos eventos selecionados, uma vez por passo. A saída registrada já inclui o consumo informado pelo exportador; não acrescentar raciocínio novamente. O nome Gemini 4 Argon vem do relato de Alan, pois estes registros não trazem o identificador do modelo.
- Escopo: o estudo relacionado sobre Gotham e conversas que misturam outros jogos ficam fora do total principal. Revisões efêmeras sem uso salvo, atividade inacessível ou em outras máquinas e possíveis sessões não identificadas não podem ser certificadas.
Os campos dos fornecedores têm significados diferentes. No Codex, a leitura de cache já faz parte da entrada e o raciocínio registrado já faz parte da saída; somá-los novamente inflaria o total. No Claude, a entrada total desta auditoria soma entrada comum, criação de cache e leitura de cache. As fórmulas seguem as documentações de contabilidade da OpenAI e de cache da Anthropic.
Codex = entrada total + saída
Claude = entrada comum + criação de cache + leitura de cache + saída
Antigravity = entrada sem cache + leitura de cache + saída
Agregado = Codex + Claude + Antigravity
Não adicionar novamente os subconjuntos:
cache do Codex, raciocínio ou detalhes internos de cache.
Custo financeiro não apurado. O levantamento não foi conciliado com uma fatura. Plano, modelo, cache e ferramentas podem ter regras de cobrança distintas; o total de tokens, sozinho, não determina o custo.
Baixar os números e a metodologia em JSON. O arquivo público contém agregados, contagens e hashes dos recibos de auditoria. O arquivo não contém transcrições, prompts, identificadores de conversas ou credenciais.
Cronologia
As datas abaixo registram as mudanças de escopo e as etapas do projeto.
7 a 14/10 · Biblioteca e investigação da Definitive Edition
O ponto de partida foi catalogar o pacote Android, recursos e sistemas. As revisões de personagens, veículos e armas mostraram que extrair um arquivo não garante uma prévia útil: materiais, variantes, rigs e nomes também precisam ser resolvidos. A biblioteca permitiu inspecionar conteúdo; reconstruir toda a engine dessa edição continuou sendo um problema maior.
15 a 19/10 · Uma base clássica para o experimento jogável
Alan autorizou usar qualquer Vice City neste experimento. A rota passou a integrar o clássico PC com reVC Web, reaproveitando uma engine existente. O foco mudou para a execução nativa no navegador, arquivos por demanda, texturas, áudio, interiores e trechos da campanha. Esse reaproveitamento preserva sistemas já implementados e exige registrar exatamente a base usada.
20/10 · Desempenho, banda e a página de entrada
A investigação de FPS e I/O avançou junto com a compressão sem perdas. A pergunta “por que o menu baixa tanto?” revelou leitura antecipada de áudio e trabalho de engine antes da escolha de jogar. O menu criado no Claude foi preservado; imagens/fontes foram otimizadas sem cortar sua arte. O relatório de carregamento virou material público e um processo para outros ports.
20 a 21/10 · Controle e adaptação ao toque
O controle físico passou a ter orientação e detecção na entrada, usando a Gamepad API e o caminho SDL existente. A adaptação móvel estudou os widgets Android e criou um controle lógico para analógico, câmera e botões por contexto. A revisão para iPhone/tablet revelou problemas de área visível, toque curto e dependência de rede do Worker no WebKit.
21/10 · Assinatura, créditos e registros do processo
O estudo público passou a reunir assinatura, divisão de trabalho, workflow, auditoria de tokens e correções registradas durante o port.
Correções no WebKit e nos controles de toque
No WebKit, a partida parava em uma falta de dados. Mensagens entre página e Worker passavam, mas as respostas de rede do Worker só concluíam quando a página liberava execução. A espera da página impedia a conclusão da operação da qual ela dependia.
A solução atual usa leitura Range síncrona de bytes originais somente nas faltas de cache desse navegador, com checagem de status, intervalo, tamanho e SHA dos blocos mapeados. Preparação assíncrona e LRU continuam; Chromium mantém o caminho de Worker e compressão. Uma falta de cache nessa rota pode bloquear o quadro e transferir mais bytes crus.
Nos testes de toque rápido, o botão visual respondia, mas a engine podia ler o controle apenas depois de o dedo já ter soltado. O pulso de botão passou a conservar somente o restante de 100 ms para atravessar a leitura por quadro. Cancelamento, perda de foco, rotação e mudança de contexto continuam limpando a entrada imediatamente.
Etapas de carregamento#
Separamos a visita à página, o menu nativo, o jogador livre e a exploração. Cada etapa pede um conjunto de arquivos.
| Momento | O que precisa existir | Referência deste caso |
|---|---|---|
| Apresentar a página | Interface, fontes e arte integral. | Cerca de 1,03 MB de corpos na medição histórica; nenhum recurso da engine antes de Jogar. |
| Abrir o menu nativo | Engine, dados iniciais, tabelas e sons imediatos. | 36,58 → 17,10 MB no ensaio comparativo após o clique. |
| Liberar o jogador | Trecho de mundo, personagem, colisões e dependências. | Controles livres e movimento nativo; custo depende da rota. |
| Continuar a partida | Outras áreas, missões, idiomas e áudio. | Leituras por demanda, sem temporizador para baixar tudo. |
Medições históricas de outubro de 2026 em ambiente local. MB = 1.000.000 bytes; MiB = 1.048.576 bytes. Corpo de resposta, transferência efetiva e banda faturada são medidas distintas. Os percentuais têm bases diferentes e não se somam.
Inicialização somente após Jogar
O pequeno ponto de entrada passou a importar o carregador somente na escolha de Jogar. Antes disso, não há Worker clássico, manifesto de instalação nem WASM em preparação. Revisamos também imports indiretos: outro módulo pode disparar a engine mesmo quando o botão parece leve.
A arte foi preservada. Doze imagens passaram para WebP sem perdas, incluindo transparência; três fontes passaram para WOFF2 com os glifos completos. Os 15 arquivos caíram de 1.988.974 para 1.014.742 bytes. Comparar os dados decodificados e a tela composta são provas diferentes: filtros e bordas transparentes podem produzir arredondamentos no render.
Dados dos primeiros cinco minutos#
A base clássica contém 1.445 entradas / 1.534.714.792 bytes. Antes, ser um arquivo pequeno era motivo para baixá-lo na abertura: 1.423 arquivos e mais de 121 MB, mesmo quando muitos não seriam usados.
Instrumentamos leituras reais durante menu, nova partida, introdução e um cenário curto. O perfil prepara 117 dados / 11.942.098 bytes. Outros 1.306 pequenos ficam montados no FS virtual; os 22 grandes já usavam blocos. Suplementos de textura e tabelas necessárias continuam preparados.
Arquivo montado e dados residentes. O caminho do arquivo pode existir para a engine antes de seu corpo estar na memória. O perfil inicial prevê o que antecipar; não decide quais arquivos o jogador pode usar.
Num ensaio de cinco minutos, nove dos 1.306 arquivos pequenos adiados foram pedidos e 1.297 ficaram intocados. Esse resultado pertence ao cenário e à revisão medidos. Outro idioma, save avançado ou rota pode pedir outros recursos no primeiro minuto.
A contraprova é solicitar conteúdo fora do perfil e confrontar seus bytes com a origem. Fizemos isso com áudio futuro, outro idioma e colisão de outra região. A previsão pode estar incompleta; a disponibilidade precisa sobreviver a isso.
Carregamento após o perfil inicial
Continuar seguindo as leituras do jogo. Não há um alarme que baixa o acervo inteiro. Antecipar depende de sinais de necessidade e de limites de rede e memória.
Cidade por blocos#
O arquivo gta3.img reúne muitos recursos. A engine pede intervalos de bytes. HTTP Range permite solicitar uma faixa e receber 206 Partial Content, com tamanho e posição indicados no cabeçalho. Referência de Range.
A compressão precisava conservar esse acesso. Dividimos o arquivo em 1.250 blocos lógicos de 256 KiB, comprimidos independentemente. Um índice relaciona a posição original ao intervalo comprimido em três pacotes de até 64 MiB.
- Offset original
- A engine pede bytes. O índice localiza os blocos correspondentes.
- Range comprimido
- O Worker restaura o bloco recebido e confere tamanho e SHA256.
- Bytes originais
- O bloco entra no cache e a engine conserva seus offsets e formatos.
O arquivo completo passou de 327.487.488 para 182.687.465 bytes no transporte, redução de 44,22%. A engine continua enxergando os mesmos 327.487.488 bytes. Não há corte de geometria, textura ou regra nativa nessa transformação.
Esse percentual descreve o arquivo inteiro. No cenário de partida medido em três pares, a redução média do conjunto de corpos baixados foi de 22,83%. Uma sessão pede parte do arquivo e também baixa outros dados.
Acesso aleatório e blocos independentes
Uma compressão contínua pode exigir decodificar trechos anteriores para alcançar o ponto desejado. Blocos independentes permitem restaurar uma faixa isolada. O ganho precisa compensar índice, cabeçalhos, buscas e descompressão.
Também produzimos variantes Brotli e gzip do JS/WASM, conferidas contra os binários originais. A negociação foi verificada localmente; ter um arquivo .br no disco não certifica que a hospedagem pública o escolhe.
Leitura assíncrona e renderização#
A engine já possuía um protocolo de leitura com estados de espera. Porém, a adaptação Web terminava a leitura dentro da chamada inicial. Quando os bytes estavam frios na rede, a renderização esperava junto.
Adaptamos o caminho: a leitura enfileira; a consulta de estado verifica a residência; só então a engine copia os bytes para o buffer nativo. Enquanto o pedido adiável está pendente, o loop pode apresentar outros quadros.
Esquema conceitual da leitura:
pedirLeitura(intervalo) → enfileirar
consultarEstado() → pendente: próximo quadro
pronto: copiar bytes residentes
erro: tratar falha de leitura
sincronizarObrigatorio() → concluir antes do parser
Leituras obrigatoriamente síncronas continuam concluídas antes de o consumidor avançar. Retornar sucesso com um buffer incompleto seria corrupção. Flush, cancelamento, troca de canal e destruição do mundo também precisam estar corretos: um callback não pode escrever num ponteiro liberado.
Worker e sincronização
Ele busca, restaura e confere blocos. A ponte legada usa memória compartilhada e isolamento entre origens. Mas uma função que espera em Atomics na thread principal ainda pode bloquear a aba. O ganho depende dos pontos em que o consumidor realmente permite esperar até o próximo quadro.
O agendador reaproveita operações em andamento e limita a oito buscas assíncronas pendentes. Não cria outro pedido do mesmo bloco a cada quadro. A preparação inicial tem um limite separado de quatro downloads.
Com 150 ms de atraso artificial nos blocos, três pares mediram 49,909 → 59,876 FPS. Em rede local normal: 59,456 → 59,862 FPS. O ganho sob atraso pertence a essa condição.
Áudio sob demanda#
O áudio escondia dois problemas. A engine abria falas e músicas para descobrir suas durações. O consumidor de efeitos também lia seu banco inteiro, embora poucos sinais fossem necessários na abertura.
Tabela de duração do áudio
A própria engine suportava uma tabela de duração. Geramos e conferimos a tabela com a base exata: 1.224 durações / 4.896 bytes. A abertura consulta metadados sem abrir cada voz só para medi-la. Isso permitiu adiar 1.200 MP3/WAV pequenos / 96.888.249 bytes, conservando os arquivos originais.
Leitura por amostra no banco SFX
O banco SFX precisava de uma adaptação nativa. O canal agora aguarda seus bytes antes de copiar e enviar PCM ao áudio. Parar ou limpar cancela a reprodução pendente; a espera conserva a identidade e o tempo de vida do som que ainda interessa.
Os 11 sinais originais de abertura e navegação são preparados antes do menu: três blocos / 786.432 bytes, em vez de antecipar 21.233.664 bytes. Os demais efeitos chegam conforme o uso.
Adiar com qualidade exige prever o instante de tocar. Os sinais curtos aguardam os bytes sem perder a identidade do canal. Preparar sons imediatos e conservar os canais foi parte da solução. Um primeiro efeito ainda frio pode depender da rede; isso não autoriza prender a renderização.
Outra correção retirou uma espera ocupada entre canais estéreo que dependia de o navegador receber o controle de volta. O caminho Web retorna ao loop e tenta novamente depois.
Limites de quadros e medição de FPS#
Um limite nativo de 30 Hz convivia com a espera do navegador e outro bloqueio no caminho Web. A composição dessas esperas perdia oportunidades de apresentação. Investigamos o loop real, mantendo a qualidade da cena.
O caminho Web passou a seguir requestAnimationFrame, com alvo 60 quando o limitador está ligado. O prazo usa relógio monotônico e evita despejar todos os quadros vencidos após um atraso. O comportamento não Web foi preservado.
| Condição | Antes | Depois |
|---|---|---|
| Mesma rua, arte final, 1280 × 720, Metal / Apple M3 Ultra, três pares intercalados. | 24,1619 FPS | 59,9530 FPS |
O contador avança na apresentação nativa. Contar RAF, iterações de lógica ou tempo de download responderia a outra pergunta. Mesmo esse contador não mede diretamente o tempo de GPU ou a varredura física do monitor.
Esse resultado não promete 60 FPS em celular. Tampouco demonstra toda a física e a campanha sob outra frequência. Mudanças de cadência exigem verificar timers, animação e simulação.
Compressão dos objetos 3D#
O Gemini 4 Argon participou da compressão e otimização dos objetos 3D, conforme informado por Alan Nicolas. Na prévia Three.js, os recursos convertidos usam GLB e texturas separadas. O conjunto contém 428 modelos e 465 registros de textura. Seu tamanho ativo único passou de 427.886.280 para 101.351.068 bytes, redução de 76,31%.
- Geometria compartilhada. Conservar accessors entre materiais e usar índices de 16 bits somente quando todos os valores cabem, preservando a topologia.
- Meshopt. Comprimir buffers e quantizar apenas direções de normais/tangentes, com decodificação independente. Posições, UVs, pesos e animações conservam seus valores verificados.
- Texturas por papel. Cor e dados lineares têm critérios próprios, com resolução preservada. Se a qualidade ou o tamanho não favorece a conversão, fica o original.
- Reutilização e descarte. Reaproveitar operações, modelos e texturas. Descartar resultados tardios de uma cena abandonada e conservar o necessário para restauração gráfica.
Fechar um ImageBitmap logo após o upload parecia liberar memória mais cedo, mas impedia reconstruir a textura depois da perda de contexto. A liberação precisa respeitar o ciclo de vida inteiro.
A redução é do conjunto da prévia, não do download inicial nem dos DFF/TXD/IMG da campanha clássica. Preservação perceptual e direções aproximadas não significam igualdade binária de todos os recursos.
Cache, memória e banda#
O navegador pode reaproveitar o que ainda estiver no cache. Isso depende da identidade, dos cabeçalhos, do espaço e das decisões do navegador. Nova versão, cache apagado, navegação privada ou descarte podem gerar transferências. Não há promessa de armazenamento offline permanente.
| Camada | O que guarda | Limite |
|---|---|---|
| HTTP | Respostas reutilizáveis entre visitas. | Assets com hash recebem cache longo; páginas e índices revalidam. Retenção não é garantida. |
| Streamer | Blocos residentes durante a sessão. | LRU de 400 MiB neste port. Não é a RAM total nem um teto adequado a todo aparelho. |
| Engine / GPU | Modelos, texturas, áudio e estruturas prontas. | Tamanho comprimido não determina a memória após decodificar. |
Corrigimos a contabilidade: uma view de 256 KiB podia manter vivo um buffer maior, apesar de contabilizar só o trecho. Guardar um bloco com armazenamento próprio pode economizar RAM mesmo exigindo uma cópia deliberada.
Uma estimativa de banda precisa separar os públicos:
banda ≈ visitas × bytes da apresentação
+ inícios de partida × bytes adicionais até jogar
+ conteúdo extra efetivamente solicitado
− reaproveitamento observado no cache
Use medições compatíveis. Cabeçalhos e transporte acrescentam custo, e a contagem do provedor pode ser outra. A revisita histórica registrou 18.314 bytes de transferência reportada num mesmo contexto; isso não garante o custo após perda de cache.
Na URL pública, conferir MIME, isolamento, Range, build e cache. no-cache exige revalidação; não significa necessariamente baixar todo o corpo novamente. Referência de cache HTTP.
Testes e limitações#
- Fixar o objeto. Identificar engine, dados, cena, configuração e build; confrontar o servido com o medido.
- Separar integridade e aparência. Hash prova bytes. A tela em movimento nas mesmas condições revela materiais, rig, transparência e timing.
- Observar o consumidor. Exigir movimento nativo com controle livre, PCM correto e retorno de pausa. Uma API sem erro pode não produzir nada útil na tela.
- Provocar falhas úteis. Testar bloco incompleto, índice divergente, atraso, cancelamento, original de reserva e restauração gráfica.
- Medir pares. Em performance, três pares intercalados com a arte final. Uma rodada mistura rede, cache e aquecimento.
- Contar o conjunto. Conferir 428 modelos ou 1.224 durações prova esses conjuntos, não todo recurso ou comportamento.
A rodada passou 248 verificações primárias e 18 específicas com controle virtual contra a engine real: movimento, câmera, zona morta, menus, pausa, desconexão, reconexão e teclado. O esquema original usa A/✕ para confirmar, Y/△ para voltar em submenus e Start para pausar/retomar.
Permanece aberto: campanha completa, fidelidade audiovisual integral, desempenho em aparelhos físicos e controle Bluetooth físico. Testes virtuais e celular emulado não substituem essas provas. Os números são dos cenários identificados.
Controles físicos e adaptação móvel
O controle Bluetooth/USB usa o mapeamento padrão que o navegador expõe à Gamepad API, chegando ao SDL2 já compilado na engine. A página detecta e orienta; conectar um controle não inicia o download do jogo. Os testes incluem dois analógicos, pausa, desconexão, reconexão e teclado preservado, com controle virtual. A conexão Bluetooth física ainda precisa ser confrontada em aparelhos reais.
Para toque, a pesquisa consultou os widgets da versão Android identificada e adaptou suas funções ao controle clássico. O analógico esquerdo move ou esterça; a área de olhar controla a câmera; os botões mudam em menus, cenas, a pé e em veículo. Cada dedo conserva sua identidade. Soltar um gesto não solta os outros, e perda de foco/cancelamento limpa o estado. A interface acompanha a área visível, as bordas seguras, rotação e janela dividida.
Na revisão anterior a esta edição, o validador principal passou 251 de 251 testes. A matriz de layout passou 176 de 176 casos: 22 tamanhos × quatro contextos × Chromium/WebKit. Houve ainda 66 verificações de toque no Chromium e 15 no WebKit com a engine, incluindo menus, áudio, pausa e disparo por toque rápido. Esses números descrevem a revisão 7934b4489bd7c60b147398c1fe804b085ca6b1d2, não um ensaio novo executado pelo leitor.
Os tamanhos e áreas seguras foram emulados. WebKit no Mac não certifica Safari/iOS no aparelho; a arma do ensaio foi obtida por um cheat nativo declarado no perfil de teste. Aquisição normal, desempenho físico móvel, todos os controles e campanha completa não estão certificados por esses resultados. A rota síncrona de compatibilidade pode bloquear durante uma falta de rede.
Aplicação em outros jogos#
Este roteiro reúne as etapas usadas aqui. Os parâmetros e a economia de bytes precisam ser medidos em cada jogo.
- Fixe a versão e meça a abertura atual.
Registre hashes, cena, fluxo e referência visual. Separe visita, menu, primeiro controle e sessão curta.
- Separe apresentação e engine.
Revise imports, preload e construtores. Prove que a simples visita não prepara uma instalação ainda não iniciada.
- Descubra leituras que só procuram metadados.
Instrumente arquivos e APIs de assets. Procure duração, dimensões, cabeçalhos e dependências; produza índices vinculados à revisão.
- Separe disponibilidade e residência.
Monte o conteúdo completo e antecipe o conjunto observado. Depois peça outro idioma, save avançado ou área fora da previsão.
- Respeite o tempo da engine.
Use pendente/pronto/erro onde isso fizer sentido. Mantenha leitura obrigatória concluída. Revise flush, cancelamento, teardown e ponteiros.
- Comprima o que será transferido.
Para acesso aleatório, avalie blocos independentes. Para JS/WASM, representações HTTP. Em malhas/texturas, preserve atributos usados e compare o resultado.
- Limite antecipação, concorrência e retenção.
Guarde operações em andamento. Conte memória realmente retida. Evite download geral por tempo decorrido.
- Feche consumidores especiais.
Áudio, shaders, cenas e vídeo podem ler seus pacotes inteiros. Um FS virtual não elimina sozinho esse comportamento interno.
- Confira o servidor na URL pública.
Verifique MIME, encoding quando usado, Range, isolamento necessário, cache e identidade entregue.
- Compare resultado e qualidade.
Repita com cache frio e revisita, mesma arte e condições. Observe em movimento e teste o aparelho alvo antes de prometer seus números.
Adaptação por arquitetura
| Port | Investigar primeiro | Não assumir |
|---|---|---|
| C/C++ → WASM | Fronteira de I/O, metadados e bloqueios. | Pacotes de preload não implementam streaming por uso. |
| Emulador / disco virtual | Separação runtime/dados e acesso por blocos. | Uma camada externa não elimina a exigência interna do arquivo completo. |
| Three.js / GLB | Dependências, geometria compartilhada e texturas por papel. | Arquivo menor não demonstra menor VRAM ou menos draw calls. |
| Unity Web com projeto | Empacotamento, catálogos, dependências, descarte e headers. | O patch nativo deste caso não se aplica diretamente à Unity. |
Comece por um cenário pequeno, repetível e comparável. Prove a integração antes de reconverter o acervo inteiro.
Referência das 28 técnicas#
Abra um item para revisar o mecanismo e o cuidado ao reaplicá-lo. Use os identificadores O01 a O28 para citar uma técnica deste estudo.
O01Engine somente após Jogar
Importação dinâmica, uma única inicialização e falha visível. Antes da escolha, não preparar Worker, WASM ou instalação. Revisar imports indiretos.
O02Imagens de interface sem perdas
WebP lossless com RGBA, transparência e dimensões preservados. Conferir dados decodificados e composição final; arquivo e captura são provas distintas.
O03Fontes completas em WOFF2
Conservar glifos, contornos, métricas e kerning. Comprimir o contêiner não exige cortar caracteres ou idiomas.
O04Preparação com concorrência limitada
Quatro downloads iniciais, barreira de falha e cancelamento dos irmãos. Conferir posse do buffer antes de entregá-lo sem cópia adicional ao FS.
O05Arquivos grandes montados por blocos
Reaproveitar o FS virtual para 22 grandes. Conservar caminhos, tamanhos e offsets. Montar não significa baixar o corpo inteiro.
O06Perfil inicial de leituras reais
Antecipar 117 dados; adiar 1.306 pequenos. A previsão é vinculada à revisão e não exclui os recursos restantes.
O07Durações pré-calculadas
Tabela nativa exata de 1.224 durações / 4.896 bytes evita abrir todas as falas para medir metadados. Falhas de integridade ficam visíveis.
O08Áudio pequeno por demanda
1.200 MP3/WAV abaixo de 4 MiB usam o streamer sem transcodificação. Consumidores de leitura integral precisam de investigação própria.
O09Blocos e antecipação conforme o acesso
Blocos de 256 KiB e antecipação legada de 1, 8 ou 32 blocos conforme a sequência. Esses valores são parâmetros do caso, não um ótimo universal.
O10Worker e ponte compartilhada prontos
Preparar o Worker antes de depender dele. SharedArrayBuffer exige isolamento. A engine inteira não foi movida para um Worker.
O11Leitura nativa realmente pendente
Enfileirar e copiar só bytes residentes. Manter Sync, flush, troca de canal e teardown corretos; sucesso exige dados disponíveis.
O12Reutilizar pedidos em andamento
Guardar a operação por arquivo/bloco, além do resultado. Limitar background e evitar clonar o índice inteiro em cada pedido.
O13LRU e memória realmente retida
Teto de 400 MiB neste cache, com descarte de blocos antigos e armazenamento próprio. Uma view pequena pode reter um backing buffer enorme.
O14Compressão independente da cidade
1.250 blocos gzip em três pacotes, com índice, tamanho e hash. 327.487.488 → 182.687.465 bytes, restaurando o conteúdo nativo.
O15Brotli e gzip para a engine
Conferir restauração e negociar com MIME e Vary corretos. Preservar a representação de Range. Negociação local não certifica a pública.
O16Identidade por conteúdo e cache
Nomes com hash permitem cache longo de corpos estáveis. Páginas e índices mutáveis revalidam; identidade nova não pode apontar para corpo incompatível.
O17Integridade, prazos e original de reserva
Conferir tamanho e hash, coordenar prazos e recuperar pela origem quando necessário. Cancelamento impede efeitos tardios.
O18Banco SFX no consumidor nativo
Conservar alocação e estado, lendo PCM por amostra. Canais pendentes mantêm identidade; Stop, Reset e limpeza cancelam o interesse perdido.
O19Preparar sons imediatos
Onze sinais precisam estar residentes antes da primeira pausa. Três blocos / 786.432 bytes preparados, mantendo o restante por demanda.
O20Cadência Web e quadros reais
Investigar limitadores duplicados, seguir RAF e medir a apresentação nativa. Mudanças de cadência exigem verificar a simulação.
O21Devolver controle para o áudio avançar
Evitar espera ocupada por uma condição dependente da próxima tarefa do navegador. Retornar ao loop quando canais estéreo desencontram.
O22Payload sem dados que não são desenhadosPrévia 3D
O consumidor da prévia não usa os atributos de diagnóstico já omitidos na conversão. Demonstrar o não uso; o nome do campo não autoriza apagá-lo em outro jogo.
O23Geometria compartilhada e índices adequadosPrévia 3D
Converter accessors únicos; índices de 16 bits só quando todos cabem. Preservar topologia e LODs existentes, sem corte automático de triângulos.
O24Meshopt e quantização limitadaPrévia 3D
Comprimir buffers e aproximar só direções conforme a régua. Decodificar e conferir os demais atributos; aproximação não é igualdade bit a bit.
O25Texturas por papel e qualidade medidaPrévia 3D
Preservar resolução, distinguir cor de dados lineares e manter PNG quando qualidade ou tamanho não favorecem conversão. Medir e observar.
O26Coleções por uso e recursos compartilhadosPrévia 3D
Reutilizar índices, promessas, modelos e materiais. Clonar transformações não exige duplicar geometria nem prova redução de draw calls.
O27Descarte e restauração gráficaPrévia 3D
Definir dono e duração. Descartar resultados tardios e manter ImageBitmap até o descarte para restaurar texturas após perda de contexto.
O28Publicação como parte do funcionamento
Conferir status, MIME, Range, cache, isolamento e build na URL real. Enviar diferenças economiza publicação, medida distinta da banda dos jogadores.
Glossário#
- Engine
- Sistemas que executam mundo, lógica, desenho, áudio e outros comportamentos do jogo.
- WebAssembly / WASM
- Formato de código compilado executável no navegador, integrado às APIs do ambiente.
- FS virtual
- Arquivos apresentados à engine mesmo quando seus dados vêm de memória ou rede.
- Streaming
- Trazer conteúdo conforme a necessidade, aqui inclusive por intervalos de bytes.
- Residente
- Dado disponível numa camada de memória para consumo. Um arquivo comprimido ainda pode precisar de preparo.
- Worker
- Contexto separado usado para buscar, restaurar e conferir dados.
- Cache frio / quente
- Dados ausentes ou presentes na camada de cache observada.
- LRU
- Remover primeiro os itens usados há mais tempo quando o cache ultrapassa seu limite.
- SHA256
- Resumo do conteúdo usado para confrontar identidade e integridade dos bytes.
- RAM / VRAM
- Memória do sistema e associada à GPU; o download não mede nenhuma diretamente.
- PCM
- Amostras de áudio usadas no caminho de reprodução.
- Build
- Conjunto produzido para executar e publicar, identificado por commit e manifesto.
Fontes e créditos#
As medidas vêm dos manifestos e dos testes registrados do projeto. Cada comparação conserva a revisão e o cenário em que foi feita. O roteiro para outros jogos reúne procedimentos derivados deste port.
- wasm-revc / reVC Web: base comunitária. Revisão estudada:
acde392e0ba582156fcf516dbaeb73b73adebb3e, com adaptações locais. Este build usa WebGL2; versões atuais da origem podem ter outros caminhos. - wasm.com.br: base de streaming, revisão
4f050344abea8c2735a9db9269644d1ff2ab130f. Reaproveitada e corrigida neste experimento. - Emscripten: Packaging Files: empacotamento, preload e observação de uso.
- MDN: Range requests: intervalos e respostas parciais.
- MDN: HTTP caching e transferSize: cache e interpretação de transferência.
- MDN: Gamepad API: exposição e leitura de controles.
- Dados públicos da auditoria de processo: agregados, cobertura, modelos e hashes dos recibos; corte de 21/10/2026.
- Identidade publicada: commit e build atualmente servidos. As medições históricas não são um benchmark automático dessa versão.
Referência da publicação do relatório de carregamento: build ff25461b8a718a73ae26dfe4d0b8d85c68eec2653ff33c6fd23fef0ef36b85d5, com cenários comparativos de revisões anteriores identificados no texto. Controle: commit c19fd1db097dbc2c807c34031fc342a509377219. Uma regressão nativa mais ampla permaneceu parcial; testes primários ou específicos não a substituem.
Créditos: Rockstar Games pelo jogo original; comunidades reVC, wasm-revc e wasm.com.br pelas bases; Emscripten, librw, SDL, OpenAL, Three.js e ferramentas de compressão pelos componentes. Este material documenta a integração e suas medições.