Como funcionam os patches nos jogos?

37

Às vezes, os jogos de console e PC têm patches para corrigir erros que os desenvolvedores perderam / não tiveram tempo de corrigir.

Minha pergunta é como isso funciona?

Às vezes, os arquivos de patch têm alguns megabytes de tamanho. Não entendo como um arquivo pequeno pode alterar um programa cumprido.

MulletDevil
fonte
Deseja alterar os jogos compilados que você criou usando um pequeno patch?
wolfdawn
Não, só estou interessado na teoria por trás disso. Meus jogos são pequenos o suficiente para apenas recompilar-los e distribuir todo o jogo novamente :)
MulletDevil
4
Esta é uma pergunta interessante. Não se baseia em um problema que você está enfrentando no design do jogo. Também existem muitas maneiras de lidar com patches da maneira mais ingênua, substituindo todos os arquivos que foram modificados para os mais complexos, obtendo instruções para alterar itens específicos nos arquivos existentes. Não tenho certeza se esta pergunta é adequada para este site.
wolfdawn
3
Alguns megabytes não são "pequenos". Suponha que tenhamos um arquivo de três megabytes, com seis megabytes de código executável, compactado. Suponha que as instruções tenham, em média, seis bytes, portanto, são cerca de um milhão de instruções. (Vamos ignorar dados estáticos, como literais de seqüência de caracteres e outros enfeites.) Se uma linha de C corresponde a cerca de dez instruções da máquina, são 100.000 linhas de código. Isso parece suficiente para o mecanismo principal de um jogo. A maior parte do tamanho da instalação será composta por mapas de textura, telas, sequências de vídeo.
2
alguns megabytes podem ser pequenos, tudo depende do conteúdo e da porcentagem da base de código total. Se, por exemplo, um mapa de nível 3D inteiro precisar ser substituído por causa dos formatos de arquivo escolhidos, etc., incluindo todas as texturas e outros, alguns megabytes podem ser muito pequenos.
jwenting

Respostas:

30

Existem várias maneiras de fazer isso, o mais simples seria XOR os dois arquivos e compactá-los (GZIP ou mais). A teoria por trás disso é que, esperançosamente, você pode obter uma grande sequência de zeros (longas seqüências dos mesmos valores são compactadas bem).

Você pode levar esse conceito adiante e tentar encontrar áreas dos dois arquivos em que os dados são idênticos e omitir completamente.

Por fim, você pode usar a estrutura de cada tipo de arquivo para sua vantagem. Por exemplo, em um EXE, você pode empacotar cada método individualmente (somente os que foram alterados) e reconstituir você mesmo o EXE durante o aplicativo de patch; lembre-se, no entanto, de que isso é muito provável no reino do exagero e pode não valer o esforço (o ganho em um bdiff simples pode não justificar a complexidade extra que pode ocorrer na natureza). Como outro exemplo, você pode usar arquivos diff para scripts.

No entanto, a maioria dos sistemas de patches na natureza segue o caminho mais simples: eles apenas empacotam arquivos que foram alterados - eles não tentam apenas empacotar as alterações nesses arquivos (provavelmente por um bom motivo, a maioria dos conteúdos do jogo já está compactada e criando patches contra altos entropia ou dados compactados não funcionarão ).

Jonathan Dickinson
fonte
O que você quer dizer com empacotar cada método em um exe individualmente. Isso é prático?
wolfdawn
@ArthurWulfWhite yes. Para uma casa independente, provavelmente não vale o tempo, pois levaria uma quantidade extrema de tempo e esforço (você precisa essencialmente escrever seu próprio vinculador) - como uma empresa que lida exclusivamente com 'tecnologia de correção', valeria a pena o esforço. Tudo depende do tamanho do código executável - dei uma olhada rápida no Sacred 2 e ele tinha 26 MB (8 MB para o EXE principal). Um diff binário pode ser capaz de se aproximar dele - ainda é uma idéia que vale a pena divulgar (sei que os CABs conseguem uma boa compactação nos EXEs porque tiram vantagem da estrutura).
Jonathan Dickinson
Isso é muito interessante. Suponho que com a largura de banda seja o que é hoje, minimizar o tamanho do patch do jogo não é um problema importante. Marcar com +1 uma resposta interessante e bem pensada.
wolfdawn
Não é possível aplicar métodos individuais na maioria dos jogos. O compilador pode ter uma saída bastante drasticamente diferente, mesmo com alterações simples de código. As decisões de alinhamento automático podem mudar, o layout da tabela de símbolos pode mudar etc. As alterações de código também costumam mudar a estrutura interna da API. As otimizações já desfocam a linha entre os limites das funções em comparação com o que você vê no seu editor de código. Os sistemas de DRM também turvam muito a água. Os sistemas de correção usam substituição por atacado ou diferenças binárias e as comprimem. Qualquer coisa como você sugere é simplesmente muito frágil para ser transportada no mundo real.
Sean Middleditch
2
@SeanMiddleditch Vou fazer isso apenas para provar que é possível :).
Jonathan Dickinson
15

O código executável de um jogo nem sempre reside apenas no executável, geralmente é dividido em várias bibliotecas dinâmicas (por exemplo, os mecanismos de jogo, gráficos e som), o executável real e, possivelmente, muitos scripts para diversos fins.

Um patch pode corrigir problemas em qualquer uma dessas partes sem justificar a alteração em todas elas.

Uma abordagem diferente da substituição de todos os arquivos alterados poderia ser simplesmente fazer uma comparação binária neles e apenas empacotar as diferenças reais a serem redistribuídas.

(Obviamente, isso funcionará apenas em arquivos que você pode garantir que não serão alterados pelo usuário.)


fonte
2
Você poderia mencionar isso como um exemplo: daemonology.net/bsdiff
wolfdawn
2
Boa resposta prática. 1
wolfdawn 14/10
2

Normalmente eles usam um sistema diff binário de terceiros para distribuir patches nos dados do jogo. Os executáveis ​​geralmente são pequenos o suficiente para serem totalmente distribuídos trivialmente.

A maioria dos jogos modernos possui centenas de megas de dados (principalmente texturas, modelos, dados de níveis, etc.). Isso requer patch com bastante frequência. Até onde eu sei, os editores normalmente têm uma maneira proprietária padrão de fazer isso.

Escusado será dizer que existem exemplos de código aberto. Algumas distribuições Linux (Fedora?) Usam diffs binários para seus patches. Você pode investigar isso e ler o código fonte ou a documentação.

MarkR
fonte
-1

Moderno diffAlgoritmos podem encontrar com eficiência sequências de bytes comuns entre dois binários. Não surpreendentemente, se você pensar sobre isso. A compactação de arquivos também encontra seqüências de bytes idênticas.

Depois de ter a lista de sequências de bytes idênticas, você só precisa enviar as compensações antigas e novas, o comprimento e, claro, qualquer coisa completamente nova. No lado do recebimento, é então uma montagem direta. Copie os bits que você precisa manter do arquivo antigo, preencha os novos bits.

A criação do patch fica ainda mais fácil se o seu vinculador puder cuspir um arquivo MAP que lista os deslocamentos de todas as funções no arquivo.

MSalters
fonte