terça-feira, 18 de julho de 2017

Depois de 11 anos, finalmente saiu a tradução completa do Hikaru no Go GBA!

A história é assim: em 2006 eu estava loucamente viciado em Go e ficava jogando no trem e no ônibus. Mas só tinham duas opções de Go portátil naquela época, um port do gnugo para Palm que era bem fraquinho, e o Hikaru no Go de Game Boy Advance que era mais forte e mais divertido.

Mas esse Hikago do GBA só tinha em japonês, como eu já tinha experiência em tradução de jogos resolvi fazer eu mesmo. Infelizmente, o japonês do jogo estava acima do meu nível, então eu publiquei na web tudo que eu tinha feito e deixei uma mensagem pedindo ajuda caso alguém tivesse interesse e habilidade.

Pois bem, em março desse ano um chinês me mandou um email falando que podia continuar a tradução. Eu dei as dicas, expliquei como funcionava o meu script de tradução, e ele se virou sozinho daí em diante. Ontem ele me mandou o resultado, todos os textos do jogo estão traduzidos agora! 

Agora faltam só os gráficos (tem uns kanjis desenhados como gráficos), e reprogramar alguns trechos do código (tipo a tela onde você insere seu nome, atualmente só dá para colocar kana).

Para quem quiser jogo, aqui está o ips para aplicar na rom original: 

http://www.ricbit.com/mundobizarro/hikago-2017-07-18.zip

E eu coloquei no github os scripts de tradução:

https://github.com/ricbit/hikago

(E fiquei impressionado como eu era diferente na época, hoje em dia nunca que eu ia usar java e xml para fazer script de tradução. Mas até que foi bom porque o chinês entende de java e conseguiu mudar sozinho um monte de partes do script.)


quinta-feira, 6 de julho de 2017

No episódio de hoje de "great minds think alike":
Um dos caras que eu recomendo seguir no twitter é o John Carmack (o programador original do Doom). Apesar de ser zilionário por causa do jogo, ele ainda é programador, porque é a coisa que ele mais gosta de fazer. E ele manja pra caramba de programação, então quando passa uma dica é bom parar pra ouvir, porque ele sabe do que está falando.
Dia desses ele twittou um artigo antigo sobre "implementações paralelas". Quem é, ou já foi, da área de jogos, certamente teve que otimizar código até o caroço; e normalmente o ciclo de desenvolvimento é algo do tipo: otimiza, testa, se ficou mais rápido git commit, goto 1.
Isso é legal, mas não é muito honesto. Você pode acabar fazendo uma otimização que desfaz um ganho que você teve alguns ciclos para trás e nem vai perceber. O Carmack, no artigo, menciona que o mais correto é manter todas as implementações em paralelo: você faz copy-and-paste no código, otimiza, e mantém as duas versões funcionando para ter comparação honesta.
Aí eu pensei: ahá! Foi exatamente o que eu fiz com o meu descompressor de gzip em Rust!
No meu caso, eu estava começando Rust do zero e simplesmente não sabia qual era o jeito mais rápido de otimizar. Então eu fiz várias implementações em paralelo, e eu troco na linha de comando qual implementação eu quero usar. Assim eu acho a combinação de implementações que dá o melhor ganho global!
Eu tenho quatro pedaços que posso trocar: um pedaço que "lê os bytes do disco" (entre aspas porque uma das implementações não lê nada, faz um mmap). Outro pedaço é o que converte bytes em bits, outro pedaço é o buffer de 32kb usado para manter a janela do LZ, e o último pedaço é que o escreve no disco de várias maneiras diferentes.
Os resultados não foram intuitivos at all pra mim. Eu achei que o mmap ia bombar, mas nem foi (provavelmente porque é melhor manter um buffer menor no L1 que sujar o cache com um pedação continuo de memória). Escrever no disco em uma thread separada foi ruim também (o overhead de comunicação entre as threads matava o ganho). Um buffer circular de 32kb não é necessariamente melhor que manter o arquivo todo em memória, depende de qual módulo está escrevendo no disco, e assim por diante.
Recomendo a técnica para todos que estão otimizando!
Aqui o meu codigo do rgzip:
https://github.com/ricbit/rgzip