Skeetendo

’Cause all games were better on the GBC

You are not logged in.

#1 2014-09-10 14:47:32

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 207/450
Website

Fixing four catch rate minor bugs

There are four minor bugs related to the catch rate of certain types of pokeballs in pokemon gold/silver/crystal. The fourth is not stricly a bug but does feel quite odd.

The first one is that paralysis, burn and posion were intended to increase the catch rate by 5, but instead have no effect. I could explain it myself but I don't think I would explain it better than this, so I'll just leave the link here...

The second one is that love ball increases the catch rate against pokemon of the same gender instead of different gender. Here is the code:

Function_0xed12: ; ed12
    ld a, [TempEnemyMonSpecies]
    ld c, a
    ld a, [TempBattleMonSpecies]
    cp c
    ret nz

    push bc
    ld a, [TempBattleMonSpecies]
    ld [CurPartySpecies], a
    xor a
    ld [MonType], a
    ld a, [CurBattleMon]
    ld [CurPartyMon], a
    callba GetGender
    jr c, .asm_ed66

    ld d, 0
    jr nz, .asm_ed39
    inc d
.asm_ed39

    push de ; female: d=1 ; male d=0
    ld a, [TempEnemyMonSpecies]
    ld [CurPartySpecies], a
    ld a, WILDMON
    ld [MonType], a
    callba GetGender
    jr c, .asm_ed65

    ld d, 0
    jr nz, .asm_ed52
    inc d
.asm_ed52

    ld a, d ; female a=1 ; male a=0
    pop de
    cp d
    pop bc
    ret nz ; return if different genders

    sla b
    jr c, .asm_ed62
    sla b
    jr c, .asm_ed62
    sla b
    ret nc
.asm_ed62
    ld b, $ff
    ret

So basically we first compare the species and then the gender of both pokemon in battle, and if both match, the catch rate is multiplied by 8 (three left shifts). If the species match we then save our pokemon's gender into d, load into a the enemy's gender, and finally compare both. But we want to return only if the genders match, instead of if they differ, so that we increase the catch rate in the second case. The fix to this bug is simple, we just have to change the ret nz instruction before the three sla b to a ret z instruction that does exactly the opposite.

The third bug is straightforward. We want moon ball to increase the catch rate (x4) against pokemon that evolve with moon stone and not against pokemon that evolve with... burn heal!

Function_0xecdd: ; ecdd

GLOBAL EvosAttacks
GLOBAL EvosAttacksPointers

    push bc
    ld a, [TempEnemyMonSpecies]
    dec a
    ld c, a
    ld b, 0
    ld hl, EvosAttacksPointers
    add hl, bc
    add hl, bc
    ld a, BANK(EvosAttacksPointers)
    call GetFarHalfword
    pop bc

    push bc
    ld a, BANK(EvosAttacks)
    call GetFarByte
    cp EVOLVE_ITEM
    pop bc
    ret nz

    inc hl
    inc hl
    inc hl

; It appears that Moon Stone's constant from Pokémon Red is used.
; No Pokémon evolve with Burn Heal, so
; Moon Balls always have a catch rate of 1x.
    push bc
    ld a, BANK(EvosAttacks)
    call GetFarByte
    cp BURN_HEAL
    pop bc
    ret nz

    sla b
    jr c, .max
    sla b
    jr nc, .done
.max
    ld b, $ff
.done
    ret
; ed12

So we'd just change the cp BURN HEAL to cp MOON STONE, whose constant is 08 (Burn heal's constant is 0A).


And finally the last one is mostly something that doesn't feel too right (at least to me). Fast ball is supposed to increase catch rate against pokemon that may flee, but it only works against the first three pokemon in the fleeing pokemon table, which are magnemite, grimer and tangela. Ironically, these are some of the slowest pokemon!

Function_0xed68: ; ed68
    ld a, [TempEnemyMonSpecies]
    ld c, a
    ld hl, FleeMons
    ld d, 3

.loop
    ld a, BANK(FleeMons)
    call GetFarByte

    inc hl
    cp -1
    jr z, .next
    cp c
    jr nz, .next
    sla b
    jr c, .max

    sla b
    ret nc

.max
    ld b, $ff
    ret

.next
    dec d
    jr nz, .loop
    ret
; ed8c

So what does this do? We take the first entry from the fleeing pokemons and see if the pokemon there matches with the species of the wild pokemon. If it doesn't check the next entry and so on until register d reaches 0. Since d is initially 3 only three entries are checked. But there are a total of 23 (24 in g/s) fleeing Pokemon separated in three tables!

SometimesFleeMons: ; 3c59a ; 10%
    db MAGNEMITE
    db GRIMER
    db TANGELA
    db MR__MIME
    db EEVEE
    db PORYGON
    db DRATINI
    db DRAGONAIR
    db TOGETIC
    db UMBREON
    db UNOWN
    db SNUBBULL
    db HERACROSS
    db -1

OftenFleeMons: ; 3c5a8 ; 50%
    db CUBONE
    db ARTICUNO
    db ZAPDOS
    db MOLTRES
    db QUAGSIRE
    db DELIBIRD
    db PHANPY
    db TEDDIURSA
    db -1

AlwaysFleeMons: ; 3c5b1 ; %100
    db RAIKOU
    db ENTEI
;    db SUICUNE
    db -1
; 3c5b4

The tables are separated by 0xFF and d is decremented with FF too, so to cover all fleeing pokemon we need to check a total of 25 or 0x19 (26 or 0x1A in g/s) entries. So the solution is simple; we just have to change the ld d, 3 instruction to ld d,19 (ld d,1A in g/s).

Last edited by Crystal_ (2014-09-10 14:49:15)

Offline

#2 2014-09-14 10:24:43

Pokemon_Master
Member
From: Eastern Kingdom of Mikado
Registered: 2013-05-18
Post 912/951
Website

Re: Fixing four catch rate minor bugs

That's interesting !
@Crystal_ i think you made a little mistake.
There's no Pokémon that evolves with Burn Heal,but with a Fire Stone.

Offline

#3 2014-09-14 10:41:53

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 208/450
Website

Re: Fixing four catch rate minor bugs

There's no Pokémon that evolves with Burn Heal,but with a Fire Stone.

That's what the bug is about. Moon Ball was accidentally made to increase catch rate against pokemon that evolve with burn heal, but as you said no pokemon evolves with burn heal.

Offline

#4 2014-09-14 14:03:28

Mateo
Member
From: The Sims 4
Registered: 2009-11-25
Post 2,898/3,578

Re: Fixing four catch rate minor bugs

This is a really nice find, thanks for pointing this out and clarifying it for people. I'll be applying these fixes to Pokémon Christmas as well.

Offline

#5 2014-09-14 18:28:04

comet
Member
Registered: 2012-04-09
Post 478/679

Re: Fixing four catch rate minor bugs

Crystal_ wrote:

The tables are separated by 0xFF and d is decremented with FF too, so to cover all fleeing pokemon we need to check a total of 25 or 0x19 (26 or 0x1A in g/s) entries. So the solution is simple; we just have to change the ld d, 3 instruction to ld d,19 (ld d,1A in g/s).

That would work, but the bug was just a typo.

.loop
    ld a, BANK(FleeMons)
    call GetFarByte
    inc hl

    cp -1
    jr z, .next
    cp c
    jr nz, .next

    sla b
    ...

should actually be

.loop
    ld a, BANK(FleeMons)
    call GetFarByte
    inc hl

    cp -1
    jr z, .next
    cp c
    jr nz, .loop

    sla b
    ...

Then you wouldn't need to fix the length each time you changed the FleeMons tables.

Offline

#6 2015-03-07 22:17:15

Urnighter
Member
Registered: 2015-01-17
Post 34/123

Re: Fixing four catch rate minor bugs

Basic Question:

In the link you provided it says

ld b, a
        ld a, [WildPokemonStatus]
        and SLP|FRZ
        ld c, 10
        jr nz, .done
        and a
        ld c, 5
        jr nz, .done
        ld c, 0
.done

But the pokecrystal disassembly says...

ld b, a
ld a, [EnemyMonStatus]
and 1 << FRZ | SLP
ld c, 10
jr nz, .addstatus
and a
ld c, 5
jr nz, .addstatus
ld c, 0

As you can see they are slightly different.

If I just replace it with what the link suggests to replace it with will it still work?

Last edited by Urnighter (2015-03-07 22:18:08)

Offline

#7 2015-03-08 00:23:09

comet
Member
Registered: 2012-04-09
Post 537/679

Re: Fixing four catch rate minor bugs

Use 1 << FRZ.

FRZ describes which bit from 0-7 it is. Example: "bit FRZ, a".

When using instructions that operate on a byte, like "and", you can shift a 1 into the right place to make a mask (1 << FRZ).

The exception is SLP, which is already a mask (it's the number of turns until you wake up).

Last edited by comet (2015-03-08 00:33:16)

Offline

#8 2015-03-08 01:09:39

Urnighter
Member
Registered: 2015-01-17
Post 38/123

Re: Fixing four catch rate minor bugs

The link suggests to replace it with

ld b, a
        ld a, [WildPokemonStatus]
        and a
        ld c, 0
        jr z, .done
        and SLP|FRZ
        ld c, 10
        jr nz, .done
        ld c, 5

And you're saying I should replace it with

ld b, a
        ld a, [WildPokemonStatus]
        and a
        ld c, 0
        jr z, .done
        and 1 << FRZ | SLP
        ld c, 10
        jr nz, .done
        ld c, 5

Correct? What should I do about [EnemyMonStatus] vs. [WildPokemonStatus]

Offline

#9 2015-03-08 10:09:35

Crystal_
Member
From: Spain
Registered: 2012-09-16
Post 253/450
Website

Re: Fixing four catch rate minor bugs

Keep the dissasembly's label. When iimarckus made that post that ram address probably wasn't labeled in the dissasembly yet so he used his own name for it. EnemyMon extends to both wild and (the current) trainer pokemon. WildPokemonStatus doesn't exist, so if you use it you will get an error when trying to build pokecrystal.

Last edited by Crystal_ (2015-03-08 10:10:53)

Offline

Board footer

Powered by FluxBB