This tutorial is for how to add a new TM. As an example, we'll add TM51 Aeroblast. ## Contents 1. [Define constants with `add_tm`](#1-define-constants-with-add_tm) 2. [Define standard item data](#2-define-standard-item-data) 3. [Update the TM/HM move table](#3-update-the-tmhm-move-table) 4. [Add the TM to base learnsets](#4-add-the-tm-to-base-learnsets) 5. [Adding up to 120 new TMs](#5-adding-up-to-120-new-tms) ## 1. Define constants with `add_tm` Edit [constants/item_constants.asm](../blob/master/constants/item_constants.asm): ```diff add_tm: MACRO if !DEF(TM01) TM01 = const_value enum_start 1 endc define _\@_1, "TM_\1" const _\@_1 enum \1_TMNUM ENDM ; see data/moves/tmhm_moves.asm for moves add_tm DYNAMICPUNCH ; bf ... add_tm NIGHTMARE ; f2 + add_tm AEROBLAST NUM_TMS = const_value - TM01 - 2 ; discount ITEM_C3 and ITEM_DC ``` The `add_tm` macro will simultaneously define the next item constant `TM_AEROBLAST` and the `TMNUM` constant `AEROBLAST_TMNUM` (equal to 51). The item constant is used for `giveitem` scripts, in Mart inventories, etc. The `TMNUM` constant is not used directly, but gets referred to by the `tmhm` learnsets in Pokémon base data. (We'll get to that later.) ## 2. Define standard item data First of all, unlike [regular items](Add-different-kinds-of-new-items), we don't need to edit [data/items/descriptions.asm](../blob/master/data/items/descriptions.asm) or [data/items/item_effects.asm](../blob/master/data/items/item_effects.asm). The `ItemDescriptions` table already has dummy "?" descriptions for all the items from TM01 and up; and the `ItemEffects` table ends right before TM01 (since TMs and HMs don't use those effects anyway). Edit [data/items/names.asm](../blob/master/data/items/names.asm): ```diff db "TM50@" + db "TM51@" db "HM01@" ... db "HM07@" db "TERU-SAMA@" - db "TERU-SAMA@" db "TERU-SAMA@" db "TERU-SAMA@" db "TERU-SAMA@" db "TERU-SAMA@" db "?@" ``` Edit [data/items/attributes.asm](../blob/master/data/items/attributes.asm): ```diff ; TM50 item_attribute 2000, HELD_NONE, 0, CANT_SELECT, TM_HM, ITEMMENU_PARTY, ITEMMENU_NOUSE +; TM51 + item_attribute 2000, HELD_NONE, 0, CANT_SELECT, TM_HM, ITEMMENU_PARTY, ITEMMENU_NOUSE ; HM01 item_attribute 0, HELD_NONE, 0, CANT_SELECT | CANT_TOSS, TM_HM, ITEMMENU_PARTY, ITEMMENU_NOUSE ... ; HM07 item_attribute 0, HELD_NONE, 0, CANT_SELECT | CANT_TOSS, TM_HM, ITEMMENU_PARTY, ITEMMENU_NOUSE ; ITEM_FA item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE -; $fb - item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE ; $fc item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE ; $fd item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE ; $fe item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE ; $ff item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE ; $00 item_attribute $9999, HELD_NONE, 0, NO_LIMITS, ITEM, ITEMMENU_NOUSE, ITEMMENU_NOUSE ``` Notice how the `ItemNames` and `ItemAttributes` both already had the maximum 256 entries, so we had to remove dummy entries to add the TM51 ones. And there aren't many dummy entries; 251 items are defined, from $00 to $FA. If you want a lot of new TMs, you'll have to remove some unused items. There are 26 unused ITEM_XX constants, counting `ITEM_C3` and `ITEM_DC`, which interrupt the sequence of TMs and need [a bit of special handling](../blob/master/docs/design_flaws.md#item_c3-and-item_dc-break-up-the-continuous-sequence-of-tm-items) to remove. ## 3. Update the TM/HM move table Edit [data/moves/tmhm_moves.asm](../blob/master/data/moves/tmhm_moves.asm): ```diff TMHMMoves: ; entries correspond to *_TMNUM enums (see constants/item_constants.asm) ; TMs db DYNAMICPUNCH ... db NIGHTMARE + db AEROBLAST ``` This associates the `AEROBLAST_TMNUM` TM/HM constant with the `AEROBLAST` move constant. ## 4. Add the TM to base learnsets So far we've created a TM51 item and assigned it a move, but nothing can learn it. Edit the `tmhm` entries in [data/pokemon/base_stats/](../blob/master/data/pokemon/base_stats/): - [lugia.asm](../blob/master/data/pokemon/base_stats/lugia.asm): `..., NIGHTMARE, FLY, ...` → `..., NIGHTMARE, AEROBLAST, FLY, ...` - [mew.asm](../blob/master/data/pokemon/base_stats/mew.asm): `..., NIGHTMARE, CUT, ...` → `..., NIGHTMARE, AEROBLAST, CUT, ...` The learnable moves have to be in the same order as the `add_tm` lines, since that's what they're referencing: the `tmhm` macro turns `NIGHTMARE` into `NIGHTMARE_TMNUM`, `CUT` into `CUT_TMNUM`, etc, and then processes them to efficiently store learnsets. (We'll get to the details of how it works next.) Anyway, that's all: ![Screenshot](screenshots/tm51-aeroblast.png) ## 5. Adding up to 120 new TMs There are 50 TMs, 7 HMs, and 3 tutor moves; they each have an associated `*_TMNUM` constant, from 1 to 60. Adding TM51 Aeroblast brings the total to 61. If you end up with more than 64 learnable moves, you'll have to start updating the `tmhm` macro in [data/pokemon/base_stats.asm](../blob/master/data/pokemon/base_stats.asm). Here's the macro as-is: ``` tmhm: MACRO ; used in data/pokemon/base_stats/*.asm tms1 = 0 ; TM01-TM24 (24) tms2 = 0 ; TM25-TM48 (24) tms3 = 0 ; TM49-TM50 + HM01-HM07 + MT01-MT03 (12/24) rept _NARG if DEF(\1_TMNUM) if \1_TMNUM < 24 + 1 tms1 = tms1 | (1 << ((\1_TMNUM) - 1)) elif \1_TMNUM < 48 + 1 tms2 = tms2 | (1 << ((\1_TMNUM) - 1 - 24)) else tms3 = tms3 | (1 << ((\1_TMNUM) - 1 - 48)) endc else fail "\1 is not a TM, HM, or move tutor move" endc shift endr rept 3 ; TM01-TM24 (24/24) db tms1 & $ff tms1 = tms1 >> 8 endr rept 3 ; TM25-TM48 (24/24) db tms2 & $ff tms2 = tms2 >> 8 endr rept 2 ; TM49-TM50 + HM01-HM07 + MT01-MT03 (12/16) db tms3 & $ff tms3 = tms3 >> 8 endr ENDM ``` Basically it defines three variables `tms1`, `tms2`, and `tms3`, each of which can hold up to three bytes (that's 24 bits), and sets their bits according to which moves were listed; then it outputs those variables one byte at a time with `db` statements. Three variables with 24 bits each are sufficient for 72 learnable moves, but only eight `db`s are output, so beyond 64 moves we already have to update `tmhm`. Here's how to output a ninth byte, allowing up to 72 learnable moves: ```diff rept 3 ; TM01-TM24 (24/24) db tms1 & $ff tms1 = tms1 >> 8 endr rept 3 ; TM25-TM48 (24/24) db tms2 & $ff tms2 = tms2 >> 8 endr -rept 2 ; TM49-TM50 + HM01-HM07 + MT01-MT03 (12/16) +rept 3 ; TM49-TM72 (24/24) db tms3 & $ff tms3 = tms3 >> 8 endr ``` Here's how to add a tenth byte (which also needs a fourth variable), allowing up to 80 learnable moves: ```diff tmhm: MACRO ; used in data/pokemon/base_stats/*.asm tms1 = 0 ; TM01-TM24 (24) tms2 = 0 ; TM25-TM48 (24) tms3 = 0 ; TM49-TM50 + HM01-HM07 + MT01-MT03 (12/24) +tms4 = 0 ; TM73-TM80 (8/24) rept _NARG if DEF(\1_TMNUM) if \1_TMNUM < 24 + 1 tms1 = tms1 | (1 << ((\1_TMNUM) - 1)) elif \1_TMNUM < 48 + 1 tms2 = tms2 | (1 << ((\1_TMNUM) - 1 - 24)) - else + elif \1_TMNUM < 72 + 1 tms3 = tms3 | (1 << ((\1_TMNUM) - 1 - 48)) + else +tms4 = tms3 | (1 << ((\1_TMNUM) - 1 - 72)) endc else fail "\1 is not a TM, HM, or move tutor move" endc shift endr rept 3 ; TM01-TM24 (24/24) db tms1 & $ff tms1 = tms1 >> 8 endr rept 3 ; TM25-TM48 (24/24) db tms2 & $ff tms2 = tms2 >> 8 endr -rept 2 ; TM49-TM50 + HM01-HM07 + MT01-MT03 (12/16) +rept 3 ; TM49-TM72 (24/24) db tms3 & $ff tms3 = tms3 >> 8 endr +rept 1 ; TM73-TM80 (8/24) + db tms4 & $ff +tms4 = tms4 >> 8 +endr ENDM ``` You can probably continue the pattern from here. The fourth variable `tms4` will let you output 10, 11, or 12 bytes; then if you need more than 96 learnable moves, you can add a fifth variable and output 13, 14, or 15 bytes for up to 120 learnable moves; and so on. Actually, as soon as you add that tenth byte, the base data will become too large to fit in a ROM bank. You'll get an error when you run `make`: ``` error: Section 'bank14' is too big (max size = 0x4000 bytes). ``` One way to fix this is to remove the six unknown/padding bytes from all the base data. First edit all the base data files, removing these three lines from each: - `db 100 ; unknown 1` - `db 5 ; unknown 2` - `db 0, 0, 0, 0 ; padding` Then edit [wram.asm](../blob/master/wram.asm): ```diff ; corresponds to the data/pokemon/base_stats/*.asm contents wCurBaseData:: ; d236 wBaseDexNo:: db ; d236 wBaseStats:: ; d237 wBaseHP:: db ; d237 wBaseAttack:: db ; d238 wBaseDefense:: db ; d239 wBaseSpeed:: db ; d23a wBaseSpecialAttack:: db ; d23b wBaseSpecialDefense:: db ; d23c wBaseType:: ; d23d wBaseType1:: db ; d23d wBaseType2:: db ; d23e wBaseCatchRate:: db ; d23f wBaseExp:: db ; d240 wBaseItems:: ; d241 wBaseItem1:: db ; d241 wBaseItem2:: db ; d242 wBaseGender:: db ; d243 -wBaseUnknown1:: db ; d244 wBaseEggSteps:: db ; d245 -wBaseUnknown2:: db ; d246 wBasePicSize:: db ; d247 -wBasePadding:: ds 4 ; d248 wBaseGrowthRate:: db ; d24c wBaseEggGroups:: db ; d24d wBaseTMHM:: flag_array NUM_TM_HM_TUTOR ; d24e wCurBaseDataEnd:: ``` That gives you enough free space for seven extra base data bytes per Pokémon. Plus the eight that are already used for learnable moves, that's up to 15 `tmhm` bytes, which would allow 120 learnable moves: easily enough for the 100 TMs of Gen 7, plus HMs and tutors. If you somehow need *even more* than that, you can figure out how to save more bytes by packing the base data more compactly.