The “round timer” patch that was really editing rand() % 60
An early Tekken 4 (PS2) cheat targeted what looked like the round timer. The code was a division by 60 whose remainder, not quotient, was kept: a random 0 to 59 frame countdown per fighter. The disassembler of the time hid the instructions that gave it away. Three other early patches were wrong too. None of them ever ran, for an unrelated reason.
The first cheats written for Tekken 4 included an infinite round timer. It patched code at 0x1B0F5C, 0x1B1024 and 0x1B1164 that appeared to set a per-fighter countdown from a division by 60, which looks a lot like frames to seconds. It wasn’t the round timer.
What the code does
jal 0x2A2538 # rand()div v0, 60 # lo = v0 / 60, hi = v0 % 60mfhi a0 # a0 = remainder, not quotientsh a0, 722(s0) # fighter +0x2D2 = rand() % 60On MIPS, div puts the quotient in the lo register and the remainder in hi. mfhi reads the remainder. So the code stores rand() % 60 at fighter +0x2D2: a random countdown of 0 to 59 frames, decremented elsewhere (0x1B1000) and re-rolled when it goes negative. It’s some per-fighter timing jitter, not the clock on screen.
Why it was missed
The disassembler in use at the time didn’t decode div or mfhi. It printed them as raw .word values, and the remainder was read as a quotient. The project’s tooling and rules changed as a result:
- The disassembler now decodes these instructions. A
.wordin the middle of a code sequence is treated as a decoding failure, to be resolved before drawing any conclusion. - Every generated patch is run back through the disassembler before it’s used.
- No patch ships from a constant scan alone. The surrounding code must be disassembled and read.
The real round timer, found later by searching memory against the on-screen clock, is a 32-bit count of frames remaining at 0x00356064. It’s verified in game: patched, it holds at the same value while the play clock advances.
Three more wrong patches
The same review found that every early patch was wrong in some way:
- “Faster movement” at
0x1B052C. It changed a 1.0 that isn’t a speed. It’s the w of a homogeneous vector(dx, 0, dz, 1.0)passed to a direction calculation, so changing it would skew directions, not speed anything up. - “Extend the attract-mode timer” at
0x1FC684. It changed the reload value of a countdown in a menu animation’s state machine. Nothing tied it to the demo mode, so it was dropped. - Widescreen. The project’s own copy of the patch lacked the 16:9 aspect setting, and would have squeezed widescreen geometry into a 4:3 picture. It was replaced with PCSX2’s own patch.
Why none of it mattered
None of these patches ever ran. PCSX2 2.x applies a cheat only if it’s named in the game’s own settings file, and that file didn’t exist. Savestates from that period show every patched address still holding the original instruction. That was its own lesson (see Testing a PS2 game with no one at the controller): check that the change is actually in memory before reading anything into the result.