’Cause all games were better on the GBC

You are not logged in.

#1 2012-08-10 09:43:50

Registered: 2012-06-14
Post 39/140

Disassemble of Curse

Here's a small gift from me to those who wonder how move effect ASM looks like. I was struggling to find out where is this located and when I did, I was so relieved. So here is Curse ASM located in 0D:8776:

ld de, $CB2A
ld bc, $CBAA
ld a, $FFE6
and a
jr z, $06 ->
ld de, $D10D
ld bc, $CBB2

This is pretty straightforward. First, player's pokemon type is loaded to de and stage of attack is loaded into bc. Then register a loaded from $FFE6 tells us if this is player's turn (0), or enemy's turn(1). If it's computer turn, then enemy pokemon's type and stage of attack is loaded in de and bc in place of player's ones. The jr z, $6 command jumps exactly here:

-> ld a, (de)
cp $08
jr z, $39 ->
inc de
ld a, (de)
cp $08
jr z, $33 ->

This is pretty easy to understand aswell, de is loaded into a and compared with $08. What does it mean? Remember when I wrote the type was loaded into de? This checks if the pokemon's primary type is Ghost ($08). If it is, perform a $39 jump, if it's not, increment de and load it into a again so we can check secondary type for Ghost. The bytes for Ghost type are located in 0x3769a and 0x376a0, if someone would want to change them. If pokemon didn't have Ghost type, then no jump is executed and we continue reading:

ld a, (bc)
cp $0D
jr c, $06 ->
inc bc
ld a, (bc)
cp $0D
jr nc, $5B ->

This part of code at first loads stage of pokemon's attack from bc to a. What is a stage of stat? Stage shows us how many times a stat has been increased/decreased. Primarily, it is $07. If enemy casts Growl on us, it's decreased to $06. Amnesia would raise stage by $02. The maximum is $0D, meaning we can improve a stat only 6 levels from the start (or three times with "went way up" moves). Let's return to code - bc is loaded into a so it's compared with $0D. If it's less than $0D, flag C is set and we jump $06 bytes ahead. If it's not, it means attack is maxed. bc is incremented so it points to defense and everything else is repeated. If flag C wasn't set, it means defense is maxed and we perform a huge jump of $5B bytes. No, we don't, we continue on reading ;) You might wonder, Curse also decreases Speed, why isn't it checked? I guess it was made so your own pokemon doesn't cast a move just to reduce its own speed without improving attack or defense. If speed is minimum and attack/defense are not, then speed can't be decreases anymore but attack/defense are still improved.
Where are we now? We know our Pokemon isn't Ghost type and we know it hasn't maxed either (or both) Attack and Defense. This means we go to the part where real action begins:

-> ld a, $01
ld $CB67, a
call $7ECC
ld a, $02
call $6651
call $514E
call $6508
call $664C
call $514E
call $62D0
call $64D7
call $664C
call $62D4
jp $64D7

Looks amazing, doesn't it? I'm having hard time understanding that too. So I will write a simple overall explanation of each call.
I think the loading $01 into $CB67 is responsible for making the next call play non-ghost Curse animation. If $CB67 isn't $01, then Ghost animation will be played.
The call $7ECC calls 0D:CC7E -> 0x37ECC. This plays the either animation of Curse depending on content of $CB67.
ld a, $02 tells which stat will be lowered. $00 is attack, $01 is defense, $02 is speed, and so on.
call $6651 is responsible for decreasing this stat. It doesn't involve "Pokemon's X fell" message though.
call $514E - I'm pretty sure it determines which Pokemon is going to receive stat boosts. When I removed this call for testing purposes, the Enemy Pokemon was the one who received Attack and Defense boost.
call $6508 writes the "Pokemon's Speed fell" message.
call $664C - I have no idea what it does.
call $514E was described while ago. Why is it being used again after call $664C?
call $62D0 - increases Pokemon's Attack one stage.
call $64D7 - writes the "Pokemon's X went up" message. X is dependant on which stat was boosted while ago.
call $664C - No idea what it does.
call $62D4 - increases Defense one stage.
jp $64D7 - writes the text about Defense being increased. This is a jump, not a call, so the whole non-ghost Curse part ends here.

Remember the type checks? This is the part where the "Ghost type" jump goes:

->call $7E75
jr nz, $28 ->
call $747C
jr nz, $23 ->
ld a, $05
call $3C0B
bit 1, (hl)
jr nz, $1A ->
set 1, (hl)
ld hl, $4C47
call $7F3E
ld hl, $4BE7
call $7F3E
call $3BB9
ld hl, $5FF2
jp, $3CD6

This is the Ghost-part Curse ASM. There must be scripts responsible for checking if it's player/opponent turn, reducing HP by 1/2, checking if the target was Cursed before, doing the Curse, writing the text responses. Without trying to read this, I already see which instruction might be responsible for what action (the call $7ECC was used in non-ghost Curse aswell). I'll try to read this later.

->call $7F42
jp, $7452

I guess this is the "But it failed" part of ghost-Curse.

-> ld b, $08
call $65AE
call $7F42
ld hl, $5C27
jp, $3CD6

This must be "Pokemon's Ability cannot go any higher" for non-ghost Curse part. This is also the end of Curse ASM.

I hope that my post will help those who always wanted to understand how moves work and might start doing even their own, original moves. Implementing moves from next gen was my dream since I started my hack. I hope you are one step closer to your goal too.


#2 2012-08-10 11:29:51

Registered: 2010-10-16
Post 1,021/2,348

Re: Disassemble of Curse

This is a good tutorial for those who want to hack the move data and for learning assembly after knowing the basics.
Didn't really read it through but some of it and it looks like you know what you're talking about.

Great job!


#3 2012-08-29 19:28:35

New member
Registered: 2012-08-29
Post 1/5

Re: Disassemble of Curse

Great find. Could you perhaps describe your process for how you found where the move data was located?


#4 2012-09-09 08:46:15

Registered: 2012-06-14
Post 49/140

Re: Disassemble of Curse

I didn't see your post before, Fireburn. Here's how I found it:

I searched for Reflect text saying "Pokemon's Defense rose", then searched for a pointer to it. This pointer was located in Reflect ASM. Now I had to find beginning of Reflect ASM and find a pointer to that offset. That led me to a pointer table of move effects. After lots of experimenting with the pointers, that led me to Curse ASM (0D:8776) - I wanted to copy it and add a new attack which increases both Defense stats. I can't check now where it is, but write 8776 into search you will find a pointer table in bank D or F, as I remember. I think bank F has the pointers, bank D has the moves ASM.

The whole finding of pointer table has allowed me also to change duration of Sandstorm, you can do everything. There are type checks, with that you can even add Cacnea and Cacturne and edit Sandstorm ASM so it doesn't damage these 2 Pokemon numbers. I will (in some future) try to make completely new moves.

Last edited by Akwa (2012-09-09 09:10:23)


Board footer

Powered by FluxBB