mk1_trainer.zip ( cheat offsets ) ( Mobygames )
For the DOS floppy patched UltraTech release ( mk.exe should be dated 1/3/94, some *.GRA files should be dated 12/30/93 )
The trainer is a win32 program, designed to manipulate the process memory of a DOS emulator that is running MK1.
( The DosBox Emulator must be using core=normal )
Don't select Goro or TSUNG for a human player.
Don't select a match before starting your first round.
Don't select a 'Test Your Might' match.
Once you've reached the 'Test Your Might' stage, you can lock the match and do an infinte number of breaks.
If running the trainer without admin privileges you may see a messagebox about not having the SE_DEBUG_NAME token. AFAIK the token is not needed but if things don't work then try running it as admin :-)
The "Pit Fall Always" cheat is probably the most interesting hack in this trainer. One of the fight environments is a narrow bridge over a pit of spikes. Normally an uppercut knocks a fighter off the bridge only during the finishing period. This hack allows an uppercut to knock a victim off the bridge at any time. The first fighter to land an uppercut instantly wins the current round, by way of impalement. I spent quite a lot of time squeezing this patch into the available space.
// orginal: F605CE5B1D00FF751A803DBC5B1D00037511E87BA8FFFF750AE8F1A8FFFF83F8027451 // patched: B8BC5B1D00803803751981480B01010100B818631B003B3874020464041CC60000EB51
// original: if uppercut occurs code F605CE5B1D00FF test byte [001D5BCE],FF // check if fatalities disabled 751A jne 0017A218 ($+1a) // jump out if disabled 803DBC5B1D0003 cmp byte [001D5BBC],03 // check if map == 'the pit' 7511 jne 0017A218 ($+11) // jump out if not 'the pit' E87BA8FFFF call 00174A87 ($-5785) // set jump flag if the victim is dead 750A jne 0017A218 ($+a) // jump out if victim is not dead E8F1A8FFFF call 00174B04 ($-570f) // returns the winning player's number of rounds won... 83F802 cmp eax,0002 // check if rounds won == 2 7451 je 0017A269 ($+51) // jump if someone is going to be knocked into the pit
// patched: if uppercut occurs code B8BC5B1D00 mov eax,001D5BBC // load pointer to current map id 803803 cmp byte ptr [eax],03 // check for map "the pit" 7519 jne ($+19) // jump out if map is not "the pit" 81480B01010100 or dword ptr [eax+B],00010101 // set no finishing period, finishing period over, and round over flags B818631B00 mov eax,001B6318 // ptr to id for player1 3B38 cmp edi,[eax] // edi is the id for the victim 7402 je ($+2) // jump over next instruction if player1 is the victim 0464 add eax,64 // load up player2 (eax + 64) 041C add eax,1C // get player->health (eax + 1C) C60000 mov byte ptr [eax],00 // kill that player EB51 jmp ($+51) // goto "yes someone is falling into the pit" code
Wait, that's not going to work! What if there was a relocation? What if the user closed then re-opened the game or trainer at some point? I didn't want to do a round of fix-ups on the patch bytes, so back to the drawing board assembler. In the end not everything would fit. I had to patch the IsVictimDead function to return a pointer to the victim's hit points in the EBX register, after a check that the original value returned in EBX was not used anywhere.
// Original: IsVictimDead function ( edi is the victim Id ) A134631D00 mov eax,[001D6334] // health P1 8B1D38631D00 mov ebx,[001D6338] // damage not yet dec from health P1 3B3D18631D00 cmp edi,[001D6318] // check if victim is player1 740B je 00194AA5 ($+B) A198631D00 mov eax,[001D6398] // p2 health 8B1D9C631D00 mov ebx,[001D639C] // p2 damage 2BC3 sub eax,ebx // subtract dmg from hp 7902 jns 00194AAB ($+2) 33C0 xor eax,eax // dead C3 ret // return hp remaining & zero flag set if dead // Patched: IsVictimDead function ( edi is the victim Id ) // changed function so ebx points to the victims health upon return... BBxxxxxxxx mov ebx,xxxxxxxx // don't touch, ptr to P1 health 3B7BE4 cmp edi,dword ptr [ebx-1C] // check if P1 is the victim 7403 je $+3 83C364 add ebx,64 // ptr to p2 health 8B03 mov eax,dword ptr [ebx] 2B4304 sub eax,dword ptr [ebx+4] // subtract dmg from hp 7902 jns $+2 31C0 xor eax,eax // dead C3 retn // return hp remaining & zero flag set if dead
The pit fall check became:
// enabled 90 nop B8 xxxxxxxx mov eax, xxxxxxxx // don't touch the [fatality setting] address F600FF test byte ptr ds:[eax],FF // check if fatalities disabled 7518 jne 0017A218 ($+18) // jump out if disabled 8078EE03 cmp byte ptr ds:[eax-12],03 // check for map "the pit" 7512 jne 0017A218 ($+12) // jump out if map is not "the pit" 8148F901010100 or dword ptr [eax-7],00010101 // set no finishing period, finishing period over, and round over flags E8 75A8FFFF call 00174A87 // returns pointer to victim health in ebx C60300 mov byte ptr ds:[ebx],0 // kill the victim 90 nop EB51 jmp ($+51) // jump if someone is going to be knocked into the pit // disabled 90 nop B8 xxxxxxxx mov eax, xxxxxxxx F600FF test byte ptr ds:[eax],FF // check if fatalities disabled 7518 jne 0017A218 ($+18) // jump out if disabled 8078EE03 cmp byte ptr ds:[eax-12],03 // check for map "the pit" 7512 jne 0017A218 ($+12) // jump out if map is not "the pit" 90 nop E87BA8FFFF call 00174A87 ($-5785) // set jump flag if the victim is dead 750A jne 0017A218 ($+A) // jump out if victim is not dead E8F1A8FFFF call 00174B04 ($-570F) // returns the winning player's number of rounds won... 83F802 cmp eax,0002 // check if rounds won == 2 7451 je 0017A269 ($+51) // jump if someone is going to be knocked into the pit