diff options
author | Chatot4444 <94812895+Chatot4444@users.noreply.github.com> | 2022-01-23 16:18:18 -0500 |
---|---|---|
committer | Chatot4444 <94812895+Chatot4444@users.noreply.github.com> | 2022-01-23 16:18:18 -0500 |
commit | 4a19e80e343202cfa81a186328723dfbc7918167 (patch) | |
tree | d2ca8d218acba762d2dc26c145c54bc214ebd8eb | |
parent | cd7e491d7018403739e97ec550c953f5968c98cc (diff) |
added new method for pokemon pics
-rw-r--r-- | Adding-a-New-Pokemon.md | 213 |
1 files changed, 210 insertions, 3 deletions
diff --git a/Adding-a-New-Pokemon.md b/Adding-a-New-Pokemon.md index 4eedd59..fd166d5 100644 --- a/Adding-a-New-Pokemon.md +++ b/Adding-a-New-Pokemon.md @@ -5,7 +5,8 @@ This tutorial will cover how to add a new pokemon to the game. Before we begin, - [Pokemon base data and moves](#2-pokemon-base-data-and-moves) - [Miscellaneous data](#3-miscellaneous-data) - [Pokedex Entry](#4-pokedex-entry) -- [Pokemon Pics](#5-pokemon-pics) +- [Pokemon Pics-Method 1](#5-pokemon-pics-method-1) +- [Pokemon Pics-Method 2](#6-pokemon-pics-method-2) ## 1. Define Pokemon constants @@ -291,9 +292,11 @@ Finally, we add the pokedex entry text in [data/pokemon/dex_text.asm](../blob/ma ... ``` -## 5. Pokemon Pics +## 5. Pokemon Pics-Method 1 -For our last step, we will add the front and back sprites of our new pokemon. The front picture will need to be a png file with only four colors and a size of either 40x40, 48x48, or 56x56 pixels. The back picture is a 32x32 file, however the image itself is 28x28 pixels, with the bottom and rightmost four rows left blank. This is because the 28x28 image will be scaled up by 2 to fill the 56x56 space, but the dimensions of the file must be a multiple of 8. The files will be placed in gfx/pokemon/front and gfx/pokemon/back, respectively. We then include those files in [gfx/pics.asm](../blob/master/gfx/pics.asm). Where we place them depends on what method we use to load the pokemon pictures. For this method, we must follow the index order. +There are two different methods for how to handle the pokemon sprites. The first method uses the system already in place in the original game, but it can be a bit tedious and uses up a relatively large amount of valuable space in the Home bank. The second method is much more flexible and easy to use. This is the method I would generally recommend. However, it does make use of the unused padding byte in the pokemon base stat data, so if you had planned on using that for something else (such as pokemon gender ratios if you plan on porting the gen 2 pokemon gender mechanics) you'll have to use the first method. + +Regardless of which method is used, we will need the front and back sprites of our new pokemon. The front picture will need to be a png file with only four colors and a size of either 40x40, 48x48, or 56x56 pixels. The back picture is a 32x32 file, however the image itself is 28x28 pixels, with the bottom and rightmost four rows left blank. This is because the 28x28 image will be scaled up by 2 to fill the 56x56 space, but the dimensions of the file must be a multiple of 8. The files will be placed in gfx/pokemon/front and gfx/pokemon/back, respectively. We then include those files in [gfx/pics.asm](../blob/master/gfx/pics.asm). Where we place them depends on what method we use to load the pokemon pictures. For this first method, we must follow the index order. ```diff ... @@ -307,6 +310,7 @@ OnixPicFront:: INCBIN "gfx/pokemon/front/onix.pic" OnixPicBack:: INCBIN "gfx/pokemon/back/onixb.pic" ... ``` + Because these banks are very full, we will likely have to shift some pokemon down into the next bank. Make sure that as you are doing this they remain in index order. ```diff @@ -354,4 +358,207 @@ If you recieve an error saying that a pic section grew too big or that sections Again, these specific changes may not be what your code needs to look like. Just make sure the pokemon you are comparing against is the last pokemon in their bank. +## 6. Pokemon Pics-Method 2 + +Just like the first method, we will need to include our image files in [gfx/pics.asm](../blob/master/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. + +```diff +... +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. + +```diff +... +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](../blob/master/home/pics.asm) to work with this new method. + +```diff +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 (wram.asm)[../blob/master/wram.asm] just before the end of the mon header. + +```diff +... +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](https://www.gnu.org/software/sed/manual/sed.html). 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. + + ```diff + 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) +``` + And with that, we have added a new pokemon! |