Jump in Midair

nolberto82
Hacking these kinds of codes can be simple or very hard. You need to know assembly for that particular system.

Example : Super Mario Bros - FDS
Emulator used : FCEUX

This game is very easy because it has a value in memory. The address 0x1D in RAM changes
from 0 to 1 when jumping. I put a breakpoint on read on 0x1D. Click run until the debugger snaps here:

00:9458:A5 1D     LDA $001D = #$00
00:945A:C9 03     CMP #$03
00:945C:D0 23     BNE $9481               branch if Mario is not climbing

After the branch:
00:9481:AD 0E 07  LDA $070E = #$00  
00:9484:D0 0A     BNE $9490                
00:9486:A5 0A     LDA $000A = #$80   this address holds the A button value
00:9488:29 80     AND #$80               
00:948A:F0 04     BEQ $9490                if A is pressed continue
00:948C:25 0D     AND $000D = #$00
00:948E:F0 03     BEQ $9493                
00:9490:4C 24 95  JMP $9524
00:9493:A5 1D     LDA $001D = #$00   
00:9495:F0 11     BEQ $94A8                this is the part that we want to change.

I changed that part to a BPL or 0x10. It makes the game think that he is still on the ground
thus you can jump again. Every game use different routines for jumping. Some games have a routine for the initial jump and the other for ascending and descending. It helps to find the controller address. I'll show another example later. 

__________________________________

Example : Megaman 7 - SNES
Emulator used : Geiger's SNES9X Debugger ep9r8

This game has various values at 0x7E0C02. But the two that matter are 6 for ascending and 8 for descending. I put a breakpoint on read at 0x7E0C02. The debugger should snap here:


Code:

Jumping
$C1/10CC A6 02       LDX $02    [$00:0C02]   A:0080 X:0000 Y:0000 P:eNvMXdiZc
$C1/10CE FC D7 10    JSR ($10D7,x)[$C1:12A1] A:0080 X:0006 Y:0000 P:envMXdizc

Falling
$C1/10CC A6 02       LDX $02    [$00:0C02]   A:0080 X:0000 Y:0000 P:eNvMXdiZc
$C1/10CE FC D7 10    JSR ($10D7,x)[$C1:131C] A:0080 X:0008 Y:0000 P:envMXdizc

This kind of code you'll encounter in many games. The X register determines where to jump.
A problem arises if you try to change C1:131C to C1:12A1. Megaman will just continue jumping
and not come back down. So I try to see if there was something I could replace.

I searched for the controller address. I found it at 0x7E0C41. So I put a breakpoint on read. Until it snapped here:

Code:

$C1/119A A5 41       LDA $41    [$00:0C41]   A:FC00 X:007E Y:0005 P:eNvMXdizC
$C1/119C 89 08       BIT #$08                A:FC00 X:007E Y:0005 P:envMXdiZC
$C1/119E F0 19       BEQ $19    [$11B9]      A:FC00 X:007E Y:0005 P:envMXdiZC

This one caught my eye. Because this is checking to see if the player is pressing up,
it seems to be unused. I changed that from:

Code:

$C1/119A A5 41       LDA $41    [$00:0C41]   A:390A X:0086 Y:0014 P:envMXdizC
$C1/119C 89 08       BIT #$08                A:3908 X:0086 Y:0014 P:envMXdizC
$C1/119E F0 19       BEQ $19    [$11B9]      A:3908 X:0086 Y:0014 P:envMXdizC
$C1/11A0 C2 20       REP #$20                A:3908 X:0086 Y:0014 P:envMXdizC
$C1/11A2 A5 05       LDA $05    [$00:0C05]   A:3908 X:0086 Y:0014 P:envmXdizC
$C1/11A4 8D 00 00    STA $0000  [$80:0000]   A:0939 X:0086 Y:0014 P:envmXdizC

to this:

Code:

$C1/119A A5 45       LDA $45    [$00:0C45]   A:B20A X:0094 Y:0054 P:envMXdizC
$C1/119C 89 80       BIT #$80                A:B280 X:0094 Y:0054 P:eNvMXdizC       
$C1/119E F0 19       BEQ $19    [$11B9]      A:B280 X:0094 Y:0054 P:eNvMXdizC    if B was pressed last frame continue else branch
$C1/11A0 C2 20       REP #$20                A:B280 X:0094 Y:0054 P:eNvMXdizC      reset A
$C1/11A2 A9 06 00    LDA #$0006              A:B280 X:0094 Y:0054 P:eNvmXdizC   if you remember from before 6 means jumping
$C1/11A5 85 02       STA $02    [$00:0C02]   A:0006 X:0094 Y:0054 P:envmXdizC stores the 6 and makes him jump in midair

I only had to do this for Megaman 6 and 7 since I couldn't find an easier way. There might be an easier way. In the next one I'll show another trick. 

___________________________________

This next method I've used frequently. Which is to make a jump to the jumping subroutine.

Example : Donkey Kong Country 2 - SNES
Emulator used : Geiger's SNES9X Debugger ep9r8

This games jumping works in a similar manner as Megaman 7. It has 2 pointers one fot the initial jump and the next one for ascending and descending. For some games changing the pointer to the ascending/descending routine works but not for this game. So we have to get creative. What I did was to find the controller address which was at 7E0983. I put a breakpoint at this address. The debugger snaps here:

Code:

$B8/B90A AD 83 09    LDA $0983  [$B8:0983]   A:0000 X:0DE2 Y:16B2 P:envmxdIZCH
$B8/B90D 99 02 00    STA $0002,y[$B8:16B4]   A:0000 X:0DE2 Y:16B2 P:envmxdIZCH

This is not what we are looking for because it's storing the value from 0x983 to 0x16B4. Press run
while pressing B and we land here:

Code:

$B8/C50D AD 83 09    LDA $0983  [$B8:0983]   A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C510 29 00 80    AND #$8000              A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C513 F0 07       BEQ $07    [$C51C]      A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C515 A4 66       LDY $66    [$00:0066]   A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C517 A5 2A       LDA $2A    [$00:002A]   A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C519 99 22 00    STA $0022,y[$B8:16D4]   A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C51C 60          RTS                     A:0002 X:0002 Y:16B2 P:envmxdIzc

This is checking to see if you press B while jumping. The value that gets store at 0x16D4 increases everytime you press B. It may be the value that keeps you from jumping more than once. So what I did was to JSR to B8/C472. It will look like this:

Code:

$B8/C50D AD 83 09    LDA $0983  [$B8:0983]   A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C510 29 00 80    AND #$8000              A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C513 F0 07       BEQ $07    [$C51C]      A:0002 X:0002 Y:16B2 P:envmxdIzc
$B8/C515 20 72 C4    JSR $C472  [$B8:C472]   A:8000 X:0002 Y:16B2 P:eNvmxdIzc
$B8/C518 60          RTS                     A:0000 X:0DE2 Y:1D0F P:envmxdIZc

Code:

$B8/C472 A6 64       LDX $64    [$00:0064]   A:451C X:0DE2 Y:16B2 P:envmxdIzc
$B8/C474 AD 83 09    LDA $0983  [$B8:0983]   A:451C X:0DE2 Y:16B2 P:envmxdIzc
$B8/C477 29 00 80    AND #$8000              A:451C X:0DE2 Y:16B2 P:envmxdIzc
$B8/C47A F0 09       BEQ $09    [$C485]      A:451C X:0DE2 Y:16B2 P:envmxdIzc

Here it's checking to see if you have pressed B. If that is the case it'll rerun the initial jump routine everytime you press B. Having a value in memory that checks if you're jumping is not always useful.
Knowing the controller address and the players Y velocity can come in handy as in this case. I'll post another one later. 

_________________________________________

Example : Castlevania - NES
Emulator used : FCEUX

One to five lines of code is the best case scenario. Castlevania for the NES is one of those games that I had to do more than 5 lines. Every game is different so you need different approaches. After trying so
many things with this game I decided I needed to make a jump to the jumping routine. The problem
was finding a hook that wouldn't break the game. I searched and found address 0x514 in RAM. The value there is 1 for the being on the ground, 0 he's in the air. I placed a breakpoint on read on it and pressed A. I checked every break changing branches until I found one that wasn't causing problems. This one:

Code:

06:94CA:AD 14 05  LDA $0514 = #$01 | This is the hook since it doesn't break the game.
06:94CD:F0 0A     BEQ $94D9

The other value to find was the Y velocity or moon jump address. Which I found at 0x4DC. Placed a breakpoint on write and pressed A. This is what I got:

Code:

06:9401:A5 F5     LDA $00F5 = #$80 | This is where we are jumping to.
06:9403:29 80     AND #$80
06:9405:F0 35     BEQ $943C
06:9407:20 98 99  JSR $9998
06:940A:90 4C     BCC $9458
06:940C:AD 8D 9B  LDA $9B8D = #$90
06:940F:8D DC 04  STA $04DC = #$00 
06:9412:AD 8E 9B  LDA $9B8E = #$9B | This is where the debugger snaps.
06:9415:8D F8 04  STA $04F8 = #$00
06:9418:A9 00     LDA #$00
06:941A:8D 14 05  STA $0514 = #$00
06:941D:8D 43 01  STA $0143 = #$03
06:9420:EE 6C 04  INC $046C = #$00
06:9423:8D 88 04  STA $0488 = #$00
06:9426:8D 4C 05  STA $054C = #$00

Okay so I changed 0x94CA to:

Code:

06:94CA:20 01 94  JSR $9401

Game Genie codes for that change:

Code:

AXKOZKSZ
PEKOLGGP
KOKOGGIA

In a perfect world that should have been it. But just with that change it was causing graphic glitches and freezes. So I had to change something within the jumping routine.

Code:

06:9401:A5 F5     LDA $00F5 = #$80 
06:9403:29 80     AND #$80
06:9405:F0 35     BEQ $943C
06:9407:20 98 99  JSR $9998
06:940A:90 4C     BCC $9458
06:940C:AD 8D 9B  LDA $9B8D = #$90
06:940F:8D DC 04  STA $04DC = #$00 
06:9412:AD 8E 9B  LDA $9B8E = #$9B 
06:9415:8D F8 04  STA $04F8 = #$00
06:9418:A9 00     LDA #$00
06:941A:8D 14 05  STA $0514 = #$00
06:941D:8D 43 01  STA $0143 = #$03 | I changed this one. 
06:9420:EE 6C 04  INC $046C = #$00 | And this one. This the opcode that was causing the problem.
06:9423:8D 88 04  STA $0488 = #$00
06:9426:8D 4C 05  STA $054C = #$00

Since we're jumping to 0x9401 every time he's in the air. It's going to increase 0x46C which is the player's actions. A 1 at this address means he's jumping. So I changed it to:

Code:

06:9401:A5 F5     LDA $00F5 = #$00
06:9403:29 80     AND #$80
06:9405:F0 35     BEQ $943C
06:9407:20 98 99  JSR $9998
06:940A:90 4C     BCC $9458
06:940C:AD 8D 9B  LDA $9B8D = #$90
06:940F:8D DC 04  STA $04DC = #$00
06:9412:AD 8E 9B  LDA $9B8E = #$9B
06:9415:8D F8 04  STA $04F8 = #$00
06:9418:A9 00     LDA #$00
06:941A:8D 14 05  STA $0514 = #$00
06:941D:A9 01     LDA #$01
06:941F:8D 6C 04  STA $046C = #$00 | Instead of increasing this address it stores 1 everytime getting rid of the glitches and freezes.
06:9422:4A        LSR
06:9423:8D 88 04  STA $0488 = #$00
06:9426:8D 4C 05  STA $054C = #$00

As you can see the green text is what was changed. Those changes will turn to these Game Genie codes:

Code:

OZOOIKSE
PAOOTGLG
SAOOYGPE
GTXPAKVV
GAXPPKGT
ZGXPZGGE

0x143 has to do how he'll be landing. On one knee or on his feet. So I replaced it. I put a breakpoint
on read and I got this:

Code:

06:977A:60        RTS
...
06:978D:AD 43 01  LDA $0143 = #$0A | This is where the debugger snaps.
06:9790:C9 08     CMP #$08
06:9792:90 E6     BCC $977A

If the carry flag is clear it branches to an RTS. So I changed 0x9792 to 0x60 or RTS. The reason I did
this is so he doesn't land on one knee every time he lands. The Game Genie code is:

Code:

AVOPZYEP

And finally to prevent him from dying when jumping out of the screen. I found the vertical position at 0x3F. Put a breakpoint on read on on it. This is what I got:

Code:

06:9482:A5 3F     LDA $003F = #$B0
06:9484:38        SEC
06:9485:E9 E0     SBC #$E0
06:9487:C9 10     CMP #$10
06:9489:B0 03     BCS $948E
06:948B:4C E5 A1  JMP $A1E5 
06:948E:20 79 94  JSR $9479

Changed that to:

Code:

06:9482:A5 3F     LDA $003F = #$B0
06:9484:38        SEC
06:9485:E9 E0     SBC #$E0
06:9487:C9 10     CMP #$10
06:9489:B0 03     BCS $948E
06:948B:4C E5 A1  JMP $948E
06:948E:20 79 94  JSR $9479

Last two lines:
Code:

VEEOGGSV
KOEOIGOZ

This code was a pain to make. Well that's it for this one.