Improve the Pokemon picture system - pret/pokered GitHub Wiki

We will need to include our image files in gfx/pics.asm. However, with this method they can be stored in any bank so long as each pokemon's front and back sprite stay together in the same bank. We will create a new section called Pics 7 for our new pokemon.

...
ChannelerPic::     INCBIN "gfx/trainers/channeler.pic"
AgathaPic::        INCBIN "gfx/trainers/agatha.pic"
LancePic::         INCBIN "gfx/trainers/lance.pic"
+
+SECTION "Pics 7", ROMX
+
+CrobatPicFront::  INCBIN "gfx/pokemon/front/crobat.pic"
+CrobatPicBack::   INCBIN "gfx/pokemon/back/crobatb.pic"

This method does assume that the pics for fossil kabutops, fossil aerodactyl, and ghost are all included in the same back, so we will move them to Pics 7 as well.

...
BeedrillPicBack::     INCBIN "gfx/pokemon/back/beedrillb.pic"

-FossilKabutopsPic::   INCBIN "gfx/pokemon/front/fossilkabutops.pic"


SECTION "Pics 4", ROMX
...

...
CharizardPicBack::     INCBIN "gfx/pokemon/back/charizardb.pic"
-FossilAerodactylPic::  INCBIN "gfx/pokemon/front/fossilaerodactyl.pic"
-GhostPic::             INCBIN "gfx/battle/ghost.pic"
OddishPicFront::       INCBIN "gfx/pokemon/front/oddish.pic"
...

...
SECTION "Pics 7", ROMX

CrobatPicFront::  INCBIN "gfx/pokemon/front/crobat.pic"
CrobatPicBack::   INCBIN "gfx/pokemon/back/crobatb.pic"

+FossilKabutopsPic::   INCBIN "gfx/pokemon/front/fossilkabutops.pic"
+FossilAerodactylPic::  INCBIN "gfx/pokemon/front/fossilaerodactyl.pic"
+GhostPic::             INCBIN "gfx/battle/ghost.pic"

Next we must change UncompressMonSprite in home/pics.asm to work with this new method.

UncompressMonSprite::
	ld bc, wMonHeader
	add hl, bc
	ld a, [hli]
	ld [wSpriteInputPtr], a    ; fetch sprite input pointer
	ld a, [hl]
	ld [wSpriteInputPtr+1], a
-; define (by index number) the bank that a pokemon's image is in
-; index = MEW:             bank $1
-; index = FOSSIL_KABUTOPS: bank $B
-;       index < $1F:       bank $9 ("Pics 1")
-; $1F ≤ index < $4A:       bank $A ("Pics 2")
-; $4A ≤ index < $74:       bank $B ("Pics 3")
-; $74 ≤ index < $99:       bank $C ("Pics 4")
-; $99 ≤ index:             bank $D ("Pics 5")
	ld a, [wcf91]
-	ld b, a
-	cp MEW
-	ld a, BANK(MewPicFront)
-	jr z, .GotBank
-	ld a, b
	cp FOSSIL_KABUTOPS
+	jr z, .RecallBank
+	cp FOSSIL_AERODACTYL
+	jr z, .RecallBank
+	cp MON_GHOST
+	jr z, .RecallBank
+	ld a, [wMonHPicBank]
+	jr .GotBank
+.RecallBank
	ld a, BANK(FossilKabutopsPic)
-	jr z, .GotBank
-	ld a, b
-	cp TANGELA + 1
-	ld a, BANK("Pics 1")
-	jr c, .GotBank
-	ld a, b
-	cp MOLTRES + 1
-	ld a, BANK("Pics 2")
-	jr c, .GotBank
-	ld a, b
-	cp BEEDRILL + 2
-	ld a, BANK("Pics 3")
-	jr c, .GotBank
-	ld a, b
-	cp STARMIE + 1
-	ld a, BANK("Pics 4")
-	jr c, .GotBank
-	ld a, BANK("Pics 5")
-
.GotBank
	jp UncompressSpriteData
...

In case that's hard to read, here's what the function should look like when you're done:

UncompressMonSprite::
	ld bc, wMonHeader
	add hl, bc
	ld a, [hli]
	ld [wSpriteInputPtr], a    ; fetch sprite input pointer
	ld a, [hl]
	ld [wSpriteInputPtr+1], a
	ld a, [wcf91] ; XXX name for this ram location
	cp FOSSIL_KABUTOPS
	jr z, .RecallBank
	cp FOSSIL_AERODACTYL
	jr z, .RecallBank
	cp MON_GHOST
	jr z, .RecallBank
	ld a, [wMonHPicBank]
	jr .GotBank
.RecallBank
	ld a, BANK(FossilKabutopsPic)
.GotBank
	jp UncompressSpriteData
...

We will now need to add wMonHPicBank into ram/wram.asm just before the end of the mon header.

...
wMonHeader::
; In the ROM base stats data structure, this is the dex number, but it is
; overwritten with the internal index number after the header is copied to WRAM.
wMonHIndex:: db
wMonHBaseStats::
wMonHBaseHP:: db
wMonHBaseAttack:: db
wMonHBaseDefense:: db
wMonHBaseSpeed:: db
wMonHBaseSpecial:: db
wMonHTypes::
wMonHType1:: db
wMonHType2:: db
wMonHCatchRate:: db
wMonHBaseEXP:: db
wMonHSpriteDim:: db
wMonHFrontSprite:: dw
wMonHBackSprite:: dw
wMonHMoves:: ds NUM_MOVES
wMonHGrowthRate:: db
wMonHLearnset:: flag_array NUM_TMS + NUM_HMS
-	ds 1
+wMonHPicBank:: db
wMonHeaderEnd::
...

Finally, we need to update each pokemon's base stat data with the bank of their picture. You could do this by individually changing each file, but don't. We can easily do this automatically by using sed. Simply run the following code in your terminal (note for Cygwin users: by default, paste is set to shift+ins instead of the ctrl+v you may be used to):

for f in data/pokemon/base_stats/*.asm; do
    cat $f \
    | tr '\n' '\v' \
    | sed -E 's/dw (\w+), (\w+)(.+)(..)db [%01]+ ; padding/dw \1, \2\3\4db BANK(\1)\4assert BANK(\1) == BANK(\2)/g' \
    | tr '\v' '\n' \
    > $f.tmp;
    mv -f $f.tmp $f;
done

and all your base stat files should now be properly updated.

   db DEX_CROBAT ; pokedex id

   db  85,  90,  80,  130,  80
   ;   hp  atk  def  spd  spc

   db POISON, FLYING ; type
   db 90 ; catch rate
   db 241 ; base exp

   INCBIN "gfx/pokemon/front/crobat.pic", 0, 1 ; sprite dimensions
   dw CrobatPicFront, CrobatPicBack

   db LEECH_LIFE, SCREECH, BITE, SCREECH ; level 1 learnset
   db GROWTH_MEDIUM_FAST ; growth rate

   ; tm/hm learnset
   tmhm RAZOR_WIND,   WHIRLWIND,    TOXIC,        TAKE_DOWN,    DOUBLE_EDGE,  \
        HYPER_BEAM,   RAGE,         MEGA_DRAIN,   MIMIC,        DOUBLE_TEAM,  \
        BIDE,         SWIFT,        REST,         SUBSTITUTE,   FLY
   ; end

-	db 0 ; padding
+	db BANK(CrobatPicFront)
+	assert BANK(CrobatPicFront) == BANK(CrobatPicBack)