Age of Empires I, similar to Age of Empires II, allows multiple game speeds up to x16, but in this version there is a limit implemented to stop the game speed at x2. The limit is a basic if that checks if (compare and jump in assembly) the game speed is at x2 and stops the incrementing there. I managed to identify the problematic code and replaced it with nothing, allowing the game to increment the game speed using it's own code. This fix was written using Cheat Engine and it's available as a cheat table as well as a trainer (executable file independent of Cheat Engine).

Source code used in trainer creation from assembly to lua.

Posted by on

I started by finding the troublesome code

{
// ORIGINAL CODE - INJECTION POINT: AoEDE_s.exe+216983
AoEDE_s.exe+21696F: 80 B8 86 0A 00 00 00     - cmp byte ptr [rax+00000A86],00
AoEDE_s.exe+216976: 0F 84 31 01 00 00          - je AoEDE_s.exe+216AAD
AoEDE_s.exe+21697C: 80 B8 A7 0A 00 00 00     - cmp byte ptr [rax+00000AA7],00
// ---------- INJECTING HERE ----------
AoEDE_s.exe+216983: 0F 84 24 01 00 00          - je AoEDE_s.exe+216AAD
// ---------- DONE INJECTING  ----------
AoEDE_s.exe+216989: 0F 2E 05 10 A8 93 00     - ucomiss xmm0,[AoEDE_s.exe+B511A0]
}

and used Cheat Engine code injection

define(address,"AoEDE_s.exe"+216983)
define(bytes,0F 84 24 01 00 00)

[ENABLE]
assert(address,bytes)
address:
  nop
  nop
  nop
  nop
  nop
  nop

[DISABLE]
address:
  db bytes

then I converted it to LUA

{$lua}
if syntaxcheck then return end

[ENABLE]
address = AOBScan("0F 84 24 01 00 00 0F 2E 05 10 A8 93 00")[0]
registerSymbol("speedAddress",address)
writeBytes(address, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90)

[DISABLE]
writeBytes(address, 0x0F, 0x84, 0x24, 0x01, 0x00, 0x00)
unregisterSymbol("speedAddress")

from which I made a trainer (encoded strings must be on one line - 200 word limit)

function AoEForm_UnlockClick(sender)
  decodeFunction("
c-oWpDNPJ!ketlRCB=/U!NS2(5ypT38s!d+42)bqE11h63=$eb92guM7#LI/7#P[PI52
Q9Ff[0,I5Ic[m9^ZBFsL^+FtRl]GPnWRjRzPR4gxXbK{H5gAZ]TWgFvj{z](x$(.ZiQz]}
K3l2VjfT,G7Z:/gJqoS4U:Zs4Y1VWMDUqF]XCU_.{7ZVE:O3I=VMh6W0b77CWeKtW
-cGg/hHQqwbwOHzx1D_3[bb69wb3sO@49HHiNmltK0q(iiWq!tTLfNEi6zy/(iJ{?]
")()
end

function AoEForm_LockClick(sender)
  decodeFunction("
c-oWpDNPJ!ketlRCB=/U!NS2(5ypT38s!d+4D3J#7nsYz3nbVW92ndj92goK7#I#7U_
=WmWMpu3WMpV.WMnu9#3}L9ENllH85_jyKx^?eh6V.spgtDv?{kU:RHw=4*M6Hn#F
Uhx*Z$]ceyB}tEii?)jKK)Fz,A(3SejRqnx0u*l3Em8nVXcK!?@r!keZs{2r-P20UH1SMw{s%
")()
end

createHotkey(AoEForm_UnlockClick, VK_MULTIPLY)
createHotkey(AoEForm_LockClick, VK_DIVIDE)
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: