Prefácio
Bom dia, falaremos sobre o mecanismo de jogo de raios-X, ou melhor, sobre o garfo de oxigênio para raios-X Em dezembro de 2016, o projeto de oxigênio para raios-X foi publicado. Então eu a desenvolvi sozinha e não sonhei com o que se tornou no momento.
Em março, surgiu a idéia: "Por que não transferir tudo para x64?" Como você entende, é sobre essa idéia, ou melhor, sobre sua implementação, que será discutida.
Montagem do projeto
O primeiro passo foi portar o código para colocar tudo sob a plataforma x64. Depois de configurar os projetos, encontrei o primeiro problema ... Não, não as funções do Ptr, mas o assembler insere ...
__forceinline void fsincos( const float angle , float &sine , float &cosine ) { __asm { fld DWORD PTR [angle] fsincos mov eax , DWORD PTR [cosine] fstp DWORD PTR [eax] mov eax , DWORD PTR [sine] fstp DWORD PTR [eax] } }
A beleza desse código era a otimização, mas o MSBuilder em x64 não o suportava e ainda não o suporta. A maior parte desse código pode ser substituída por análogos std; havia lugares que poderiam ser facilmente alterados para Intrínsecos , por exemplo, como:
__asm pause;
Pode ser substituído com segurança por:
_mm_pause();
Também no mecanismo, às vezes havia análogos de funções no código nativo (louvado seja o sistema CPUID). Mas havia lugares dos quais você só precisava se livrar. Por exemplo, as instruções da MMX caíram no esquecimento. Felizmente, eles não foram chamados a lugar algum, mas simplesmente compilados e permanecendo ociosos.
Operabilidade
Depois de todas as edições na montagem, a próxima etapa começou: Como começar tudo isso?
O primeiro traidor foi LuaJIT . Infelizmente, o LuaJIT começou a funcionar bem (bem, quase ...) no x64 apenas com a versão 2.0.5. E esses eram pequenos problemas com a alocação de memória de pequenos dígitos. Mas, então, eu não sabia e a primeira coisa que vi foi o LuaJIT e enrolei a baunilha Lua 5.1. Sim, isso resolveu o problema, mas a velocidade ... Lembre-se, lamentamos. Mais tarde, no fórum, fui informado de que você pode tentar usar o LuaJIT 2.0.4. E sim, ajudou, eu comecei o jogo e fui capaz de ir para o menu principal!
Mas ... a felicidade durou pouco ... Olá para estruturar compensações, tipos de dados e xrCDB. O jogo não carregou o nível, os materiais voaram nos objetos e o motor não gostou muito. Depois de alguns dias, fiquei completamente desesperada e decidi pedir ajuda a um programador mais experiente, sob o apelido de Giperion. Não contei com a participação dele no projeto, meu sonho era apenas um conselho. Mas, dessa maneira, consegui um desenvolvedor experiente no projeto. A partir desse momento, uma equipe se formou.
O próximo problema foi OPCODE e tipos de dados. Eu tive que traduzir todas as udwords (int sem assinatura) para uqwords (sem assinatura por muito tempo). Somente para entender isso, tive que passar cerca de 4 horas no depurador.
Mas isso foi apenas parte do problema. Foi a vez dos materiais. O que temos:
union { u32 dummy;
Esse código no x32 foi salvo pelo #pragma pack(4)
mágico #pragma pack(4)
, mas no x64, por algum motivo, ele não foi salvo. Chegou a vez do alinhamento, por meio de uma depuração, descobrimos que em alguns casos os dados na estrutura eram válidos, mas em outros não. Refazemos a estrutura e tornamos o conversor validador. A estrutura tem o seguinte formato:
union { size_t dummy; struct { size_t material:14;
E o validador era assim:
... if (rebuildTrisRequired) { TRI_DEPRECATED* realT = reinterpret_cast<TRI_DEPRECATED*> (T); for (int triIter = 0; triIter < tris_count; ++triIter) { TRI_DEPRECATED& oldTri = realT[triIter]; TRI& newTri = tris[triIter]; newTri = oldTri; } } else { std::memcpy(tris, T, tris_count * sizeof(TRI)); } ...
Assim, parte das chamadas teve que ser alterada devido ao sinalizador rebuildTrisRequired, mas o jogo foi iniciado.
Mas, com o tempo, surgiu o problema com as partículas:
real_ptr = malloc( sizeof( Particle ) * ( max_particles + 1 ) ); particles = (Particle*)((DWORD)real_ptr + (64 - ((DWORD)real_ptr & 63)));
Este código não causou problemas com as partículas originais. Eles eram muito simples e se encaixavam silenciosamente na memória alocada para eles. Mas, com detalhes mais complexos e coloridos, feitos por modmakers, surgiram desvios da memória. x64 e trava na memória, como assim ?! O código foi refeito, as partidas desapareceram:
particles = alloc<Particle>(max_particles);
Problemas de jogo
O primeiro problema foi, novamente, LuaJIT

Os dados do usuário para capas inteligentes voaram. Este problema foi corrigido quase o último. Apenas transferindo as edições do LuaJIT 2.0.5 lançado.
Próximo problema: Física e cálculo de carros alegóricos. control87
e _controlfp
para calcular o infinity
em x64 foram bloqueados ... Houve um grande problema com a queda de itens, uma vez que três deles caíram corretamente. Às vezes eles voavam para o espaço, às vezes sob terrane. O problema estava em apenas uma variável, à qual foi dado o valor infinito. A situação foi corrigida pelo FLT_MAX, o mesmo para todas as plataformas.
surface.mu = dInfinty
O último problema foi a velocidade das partículas. Preste atenção ao seguinte código:
DWORD angle = 0xFFFFFFFF; ... if (angle != *((DWORD*)&m.rot.x)) { angle = *((DWORD*)&m.rot.x); fsincos(angle, sina, cosa); }
Tudo parece estar em ordem. Mas, 0xFFFFFFFF em x64 tem um significado diferente ao converter para um tipo de ponto flutuante. O fato é que fsincos tem uma contraparte dupla e x64 prefere dados duplos. E esse valor em dobro importa muito mais. Converter para flutuar salvou a situação.
DWORD angle = 0xFFFFFFFF; ... if (angle != *((DWORD*)&m.rot.x)) { angle = *((DWORD*)&m.rot.x);
Conclusão
Concluindo, quero dizer apenas uma coisa: a porta em x64 trouxe muitos conhecimentos novos que serão úteis no futuro. Eu falei sobre muitos problemas de portabilidade. E então tudo dependerá de você, se você decidir fazer isso em qualquer projeto OpenSource.
Obrigado pela leitura!