Decomp & Disassembly Guides and resources to help you develop your decompilation or disassembly-based hack can be found here.

Ad Content
Thread Tools
  #1   Link to this post, but load the entire thread.  
Old October 7th, 2018 (1:07 PM). Edited January 24th, 2019 by Avara.
phvse's Avatar
phvse phvse is offline
programmer who likes pokemon
    Join Date: Oct 2018
    Gender: Male
    Posts: 6
    Pokeruby is a decompilation of Pokemon Ruby & Sapphire.
    ProjectRevoTPP is absolutely certain that this will be the next wave of hacking Pokemon games, so I decided to give it a shot and slap a new type in.

    Was it easier than hacking the binary ROM? Well, that depends on your preference. If you can't or refuse to read source code, you might enjoy repointing tables. Personally, I've been doing both for a while, but I think editing the source code is a lot easier.

    In this tutorial, I will be adding a Fairy type, include the type image & effectiveness chart.
    Here is the result:

    Step 0: Setup Pokeruby
    You can follow Revo's tutorial here.
    I am using commit 09b8f4c09e69a2359cdf5e4497b97aca3746b8b1 (future commits will most likely be the same unless some things are renamed).

    Step 1: Add the new Type Constant
    All types have an ID associated with them. We need to put the ID of our new type in two places.

    In constants/
    	// ...
    	.set TYPE_ICE,      0x0f
    	.set TYPE_DRAGON,   0x10
    	.set TYPE_DARK,     0x11
    	.set TYPE_FAIRY,    0x12
    In include/pokemon.h:
    // ...
    #define TYPE_ICE      0x0f
    #define TYPE_DRAGON   0x10
    #define TYPE_DARK     0x11
    #define TYPE_FAIRY    0x12
    Step 2: Adding the Type Name
    Next we need to add the name of the type so it shows up properly in the battle screen.

    In data/text/
    	// ...
    	.string "ICE$", 7
    	.string "DRAGON$", 7
    	.string "DARK$", 7
    	.string "FAIRY$", 7
    Step 3: Adding the Type Effectiveness
    Next, we're going to add the effectiveness for our type. This isn't needed, but I doubt you want your type to not do anything special.

    The type effectiveness table is in the format
    where EFFECTIVENESS is one of
    * 0: no effect
    * 5: not very effective
    * 20: super effective

    From what I know, you can use any number here, but these numbers are the standard ones that will display the proper messages.

    In data/
    (this is formatted as a git diff)
     	.byte TYPE_FIGHTING,     TYPE_ROCK, 20
     	.byte TYPE_FIGHTING,     TYPE_DARK, 20
     	.byte TYPE_FIGHTING,    TYPE_STEEL, 20
    +	.byte TYPE_FIGHTING,    TYPE_FAIRY,  5
     	.byte   TYPE_POISON,    TYPE_GRASS, 20
     	.byte   TYPE_POISON,   TYPE_POISON,  5
     	.byte   TYPE_POISON,   TYPE_GROUND,  5
     	.byte   TYPE_POISON,     TYPE_ROCK,  5
     	.byte   TYPE_POISON,    TYPE_GHOST,  5
     	.byte   TYPE_POISON,    TYPE_STEEL,  0
    +	.byte   TYPE_POISON,    TYPE_FAIRY, 20
     	.byte   TYPE_GROUND,     TYPE_FIRE, 20
     	.byte   TYPE_GROUND, TYPE_ELECTRIC, 20
     	.byte   TYPE_GROUND,    TYPE_GRASS,  5
    @@ -88,6 +90,7 @@ gTypeEffectiveness:: @ 81F9720
     	.byte      TYPE_BUG,    TYPE_GHOST,  5
     	.byte      TYPE_BUG,     TYPE_DARK, 20
     	.byte      TYPE_BUG,    TYPE_STEEL,  5
    +	.byte      TYPE_BUG,    TYPE_FAIRY,  5
     	.byte     TYPE_ROCK,     TYPE_FIRE, 20
     	.byte     TYPE_ROCK,      TYPE_ICE, 20
     	.byte     TYPE_ROCK, TYPE_FIGHTING,  5
    @@ -102,17 +105,26 @@ gTypeEffectiveness:: @ 81F9720
     	.byte    TYPE_GHOST,    TYPE_GHOST, 20
     	.byte   TYPE_DRAGON,   TYPE_DRAGON, 20
     	.byte   TYPE_DRAGON,    TYPE_STEEL,  5
    +	.byte   TYPE_DRAGON,    TYPE_FAIRY,  0
     	.byte     TYPE_DARK, TYPE_FIGHTING,  5
     	.byte     TYPE_DARK,  TYPE_PSYCHIC, 20
     	.byte     TYPE_DARK,    TYPE_GHOST, 20
     	.byte     TYPE_DARK,     TYPE_DARK,  5
     	.byte     TYPE_DARK,    TYPE_STEEL,  5
    +	.byte     TYPE_DARK,    TYPE_FAIRY,  5
     	.byte    TYPE_STEEL,     TYPE_FIRE,  5
     	.byte    TYPE_STEEL,    TYPE_WATER,  5
     	.byte    TYPE_STEEL, TYPE_ELECTRIC,  5
     	.byte    TYPE_STEEL,      TYPE_ICE, 20
     	.byte    TYPE_STEEL,     TYPE_ROCK, 20
     	.byte    TYPE_STEEL,    TYPE_STEEL,  5
    +	.byte    TYPE_STEEL,    TYPE_FAIRY, 20
    +	.byte    TYPE_FAIRY,     TYPE_DARK, 20
    +	.byte    TYPE_FAIRY,   TYPE_DRAGON, 20
    +	.byte    TYPE_FAIRY, TYPE_FIGHTING, 20
    +	.byte    TYPE_FAIRY,     TYPE_FIRE,  5
    +	.byte    TYPE_FAIRY,   TYPE_POISON,  5
    +	.byte    TYPE_FAIRY,    TYPE_STEEL,  5
     	.byte          0xFE,          0xFE,  0
     	.byte   TYPE_NORMAL,    TYPE_GHOST,  0
     	.byte TYPE_FIGHTING,    TYPE_GHOST,  0
    Step 4: The Type Image
    Images are super simple to add to the decompilation.

    Here's my fairy.png:

    I'm using the same palette as the Flying type image. I haven't tried to add a new palette yet.

    To build this new image, we need to add it to the Makefile responsible for building the graphics.

    types := normal fight flying poison ground rock bug ghost steel mystery fire water grass electric psychic ice dragon dark fairy
    This will build, but if you check in game you'll see the wrong palette!
    To fix this, we need to change what palette is loaded for our type image.
    The code that maps types to image palettes is in src/pokemon_summary_screen.c:
    static const u8 sUnknown_PaletteNums[] = { 0xD, 0xD, 0xE, 0xE, 0xD, 0xD, 0xF, 0xE, 0xD, 0xF, 0xD, 0xE, 0xF, 0xD, 0xE, 0xE, 0xF, 0xD, 0xD, 0xE, 0xE, 0xF, 0xD };
    Currently this variable doesn't have a nice name, but essentially it contains a list of palette indexes. The list is indexed by Type IDs.

    TYPE_NORMAL = 0x00 => 0xD
    TYPE_FIGHTING = 0x01 => 0xD
    TYPE_FLYING = 0x02 => 0xE
    We want the palette for the Flying type image, so we want to grab the third number (index of 0x2) from the list, which is 0xE.

    Next, we want to add a new number into the list. Our Fairy type has the ID of 0x12, so we want to add a number at index 18 (the 19th number).

    This is what the change should look like:
    static const u8 sUnknown_PaletteNums[] = { 0xD, 0xD, 0xE, 0xE, 0xD, 0xD, 0xF, 0xE, 0xD, 0xF, 0xD, 0xE, 0xF, 0xD, 0xE, 0xE, 0xF, 0xD, 0xD, 0xE, 0xE, 0xF, 0xD };
    static const u8 sUnknown_PaletteNums[] = { 0xD, 0xD, 0xE, 0xE, 0xD, 0xD, 0xF, 0xE, 0xD, 0xF, 0xD, 0xE, 0xF, 0xD, 0xE, 0xE, 0xF, 0xD, /*FAIRY:*/0xE, 0xD, 0xE, 0xE, 0xF, 0xD };
    And that's it! You can try out your new type by changing an existing Pokemon or move.
    I changed Tackle to the TYPE_FAIRY and got the result I put above!
    If you want a summary of the changes as a git commit, you can view them here.
    Hacks you should watch: Pokemon Suri - Pokemon Orange - Pokemon Cosmos
    Reply With Quote
      #2   Link to this post, but load the entire thread.  
    Old October 13th, 2018 (8:34 AM). Edited October 13th, 2018 by Lunos.
    Lunos's Avatar
    Lunos Lunos is offline
    Random Uruguayan User
      Join Date: Oct 2008
      Location: Montevideo (Uruguay)
      Gender: Male
      Nature: Lonely
      Posts: 1,821
      First of all, I have to say you did an amazing work here dude. The tutorial is easy to understand and the changes are well explained.

      With that being said, are you sure these are all the changes to get a fully working Fairy type?
      In some sort of united effort between Wahackforo, me and some other people in some other place, we also tried to add the Fairy type to Pokeruby almost 2 months ago, and along all the changes you're showing here, we also had to do some other changes that are not being shown in this thread, changes in pokemon_summary_screen.c and changes in the pokedex.c file too.
      Click here to read the full post that I wrote in Wahack with all the changes.

      With that being said, although the Fairy type itself does work correctly, our implementation showed some issues In-Game:
      -The poké ball sprites in the lower left corner of the Pokémon Summary Screen get buggy after the 10th one.
      -The Normal and Fighting types sprites can get buggy too.
      -Searching for a Fairy type pokémon with the pokédex gives you a lot of irrelevant results. (In this short video, only Jigglypuff should be showing up when searching a Normal-Fairy pokémon, for example.)

      Could you confirm if they happen on your end, just in case? I'm curious.
      I suppose they could have been fixed automagically with recent commits done to the main Pokeruby repo though, so there's that.
      Reply With Quote

      Quick Reply

      Join the conversation!

      Create an account to post a reply in this thread, participate in other discussions, and more!

      Create a PokéCommunity Account
      Ad Content
      Thread Tools

      Posting Rules
      You may not post new threads
      You may not post replies
      You may not post attachments
      You may not edit your posts

      BB code is On
      Smilies are On
      [IMG] code is On
      HTML code is Off

      Forum Jump

      All times are GMT -8. The time now is 1:24 PM.