
Como você sabe, nesta série de jogos em cada taberna, o jogador só pode contratar um novo Herói por semana. Mas…
Descrição do bug: Se não houve recrutamento na taberna externa, então, a partir do 8º dia, você pode comprar dois heróis em dois dias.
O arquivo desmontado heroes4.exe do último complemento oficial "Winds of War" é usado para o trabalho. O procedimento de operação da taverna foi descoberto pela equipe anteriormente e está localizado no endereço 4705E0. De todo o algoritmo de seu trabalho, estou interessado no local em que se determina se é possível contratar um Herói na taberna no momento, ou se é necessário esperar. No jogo, isso é manifestado pela saída da mensagem correspondente:

Do ponto de vista programático, esta é uma nova janela que é criada no jogo usando a função NewWindowCreate (720C80) (as funções reconhecidas no desmontador recebem seus próprios nomes). Existem várias chamadas para esta função no procedimento da taverna, e o primeiro desafiante é uma chamada para o endereço 470823. Com a ajuda do depurador, certifico-me de que, de fato, esta chamada cria a caixa de diálogo desejada. O código que controla esta chamada para NewWindowCreate está localizado acima em 470645:
00470638 call HeroesPricesInTavern_Lost
0047063D mov al, [ebp+48h] // 0 – ; 1 – ( 7 ).
00470640 add esp, 8
00470643 test al, al
00470645 jz loc_470866 // , 470823
Eu compro na taverna do Herói, em seguida, defino o "ponto de interrupção" para escrever para o celular endereçado a [ebp + 48h], após o qual aguardo 7 dias no jogo. Quando a taverna é "esvaziada", o depurador aparece no endereço 470DFF. Vamos ver o código ao redor:
00470DF0 TavernCountDays proc near
00470DF0 mov dl, [ecx+48h] // ECX+48h – :
DL=0 – ;
DL=1 – ( 7 )
00470DF3 xor eax, eax
00470DF5 cmp dl, al
00470DF7 jz short loc_470E06
00470DF9 cmp dword ptr [ecx+4Ch], 7 // [ECX+4Ch] - . 7 – .
00470DFD jl short loc_470E06
00470DFF mov [ecx+48h], al // (AL=0)
00470E02 mov [ecx+4Ch], eax //
00470E05 retn
00470E06
00470E06 loc_470E06:
00470E06
00470E06 inc dword ptr [ecx+4Ch] //
00470E09 retn
00470E09 TavernCountDays endp
Este procedimento rápido é usado para verificar o número de dias que a taberna está fechada para aluguel. Observe que ele é chamado para todas as tabernas do mapa todos os dias de jogo. O que está causando o bug? Por alguma razão, o programa continua a contar o número de dias durante os quais não houve contratação de Herói na taberna e após a semana em que a taberna foi fechada (consulte o contador em 470E06). Como resultado, temos a seguinte imagem. Deixe o primeiro recrutamento do Herói ocorrer apenas no oitavo dia de jogo. Na entrada do procedimento, o valor do sinalizador de disponibilidade da taverna em [ecx + 48h] será "1" (a taverna está fechada), e o valor do contador de dias em [ecx + 4Ch] será "8". Porém, após a comparação em 470DF9, o controle receberá um código em 470DFF, que reabrirá a taverna de aluguel! Isso zera o contador de dias.e após a contratação do segundo Herói, o algoritmo já funcionará, conforme pretendiam os autores. Mas depois de duas semanas no jogo, todo o ciclo se repetirá.
A maneira mais fácil de consertar o bug é pular a contagem dos dias. Deixe o contador funcionar apenas quando a taberna estiver fechada (o que é mais lógico) e, no resto do tempo, defina-o para zero. Isso é obtido de forma muito simples - alterando a transição no endereço 00470DF7 para o final da função:
00470DF5 cmp dl, al
00470DF7 jz short loc_470E09
Agora tudo o que resta é corrigir o código existente. Para fazer isso, olhe para o original

e modificado

opções.
Como você pode ver, o resultado desejado pode ser alcançado substituindo 0D por 10 no endereço 470DF8. Um clássico do gênero: consertar um bug substituindo apenas um byte!