• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Forum moderator applications are now open! Click here for details.
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

Development: More TMs/HMs

ZodiacDaGreat

Working on a Mobile System
429
Posts
17
Years
Let's try to implement the way the 4th generation games have more than 50 TMs. Please post your findings here :D On Ruby version, I provide this two routines (Commented roughly so may have mistakes lol - a bit lazy today)

Code:
@ Routine 1 - TM data [AXVE]
@ -----------------------------------------------
0806f7b8  b500 push {lr}
0806f7ba  0400 lsl r0, r0, #0x10
0806f7bc  0c02 lsr r2, r0, #0x10
0806f7be  2100 mov r1, #0x0
0806f7c0  4b04 ldr r3, [$0806f7d4] (=$08376504) @ Pointer to TM data
0806f7c2  1c08 add r0, r1, #0x0
0806f7c4  3032 add r0, #0x32 @ 0x32 = 50 (50 TMs)
0806f7c6  0040 lsl r0, r0, #0x01 @ r0 = 0x64
0806f7c8  18c0 add r0, r0, r3 @ r0 becomes pointer to HM data
0806f7ca  8800 ldrh r0, [r0, #0x0]
0806f7cc  4290 cmp r0, r2
0806f7ce  d103 bne $0806f7d8
0806f7d0  2001 mov r0, #0x1
0806f7d2  e007 b $0806f7e4

0806f7d4  6504 str r4, [r0, #0x50] @ Pointer bytes
0806f7d6  0837 lsr r7, r6, #0x00

0806f7d8  1c48 add r0, r1, #0x1
0806f7da  0600 lsl r0, r0, #0x18
0806f7dc  0e01 lsr r1, r0, #0x18
0806f7de  2907 cmp r1, #0x7
0806f7e0  d9ef bls $0806f7c2
0806f7e2  2000 mov r0, #0x0
0806f7e4  bc02 pop {r1}
0806f7e6  4708 bx r1

@ Routine 2 - TM/HM Routine [AXVE]
@ -----------------------------------------------
080c9e90  b510 push {r4,lr}
080c9e92  0600 lsl r0, r0, #0x18
080c9e94  0e04 lsr r4, r0, #0x18
080c9e96  2000 mov r0, #0x0
080c9e98  210d mov r1, #0xd
080c9e9a  220d mov r2, #0xd
080c9e9c  2314 mov r3, #0x14
080c9e9e  f7a7 bl $08071e84 @ Message Box function?
080c9ea2  4806 ldr r0, [$080c9ebc] (=$0203855e) @ Contains TM/HM data
080c9ea4  8801 ldrh r1, [r0, #0x0] @ Loads TM/HM index number
080c9ea6  20a9 mov r0, #0xa9
080c9ea8  0040 lsl r0, r0, #0x01 @ r0 = 0x152 (TM 50 Index Number)*
080c9eaa  4281 cmp r1, r0
080c9eac  d90c bls $080c9ec8 @ if less or equal call TM branch

HM Branch
080c9eae  4904 ldr r1, [$080c9ec0] (=$0840ea16) @ Pointer to HM Message
080c9eb0  4a04 ldr r2, [$080c9ec4] (=$080c9ee5)
080c9eb2  1c20 add r0, r4, #0x0
080c9eb4  2301 mov r3, #0x1
080c9eb6  f02f bl $080f90b8
080c9eba  e00b b $080c9ed4
080c9ebc  855e strh r6, [r3, #0x2a]
080c9ebe  0203 lsl r3, r0, #0x08
080c9ec0  ea16 [ ??? ]
080c9ec2  0840 lsr r0, r0, #0x01
080c9ec4  9ee5 ldr r6, [sp, #0x394]
080c9ec6  080c lsr r4, r1, #0x00

TM Branch
080c9ec8  4904 ldr r1, [$080c9edc] (=$0840ea06) @ Pointer to TM Message
080c9eca  4a05 ldr r2, [$080c9ee0] (=$080c9ee5)
080c9ecc  1c20 add r0, r4, #0x0
080c9ece  2301 mov r3, #0x1
080c9ed0  f02f bl $080f90b8
080c9ed4  bc10 pop {r4}
080c9ed6  bc01 pop {r0}
080c9ed8  4700 bx r0

The first routine is the one that calls the TM/HM move data (The moves that it contain) The second routine is the Field Usage routine for TMs/HMs in the Item Structure - all TMs/HMs use this to calculate which TM/HM is which.

Basically what I've done so far
j8jink.png
nwyg74.png
epkt47.png

70w9he.png


I tried to create more TMs - as you can see in the Item editor image but they turned out to be HMs in the game what's more, its seems like only the first 8 HMs can be used to teach the moves while the other two when used will show that the Pokemon aren't able to learn it like in the image above. To sum it up, the two TMs I made became HMs and the two old HMs got shifted down and cannot be used.

So, I think there are more routines that limit the TM/HM amount and so on. Any thoughts or discoveries? Hehe, I'm a bit lazy this time XD
 

Gamer2020

Accept no Imitations!
1,062
Posts
15
Years
If I remember correctly there is a place in the ROM where you have to edit which Pokemon learn what TM/HM.
It's similar to the move tutors but longer.
Perhaps that is why the Pokemon won't learn the other moves.
 

ZodiacDaGreat

Working on a Mobile System
429
Posts
17
Years
Gamer2020 said:
If I remember correctly there is a place in the ROM where you have to edit which Pokemon learn what TM/HM.
It's similar to the move tutors but longer.
Perhaps that is why the Pokemon won't learn the other moves.
If you read what I typed and see the images, you'll know that most of the HMs are compatible with the Pokemon in the party. So, what you said is out of the question.
 
47
Posts
15
Years
  • Seen Apr 25, 2011
Well, simple logic dictates that something must be declaring the number of TM/HMs. They seem to be stored in the same list, judging by the bleed over. Even so, the combined number doesn't add up to the maximum number of variables (forgive me for stating the obvious, I'm building a foundation for my hypothesis). It would seem from your test that there are two missing factors. One must define the highest numbered object that is a "TM", this being why anything beyond that value is automatically classed as a "HM". I think it likely that the other missing factor must relate to which badge is needed for which HM move to be taught in some way. Since you can only have eight badges, any "extra" HM would have no "badge check" to activate it. I don't know if that helps, and it's only a theory until tested, but it might give you an idea of what to be looking for.
 

Gamer2020

Accept no Imitations!
1,062
Posts
15
Years
If you read what I typed and see the images, you'll know that most of the HMs are compatible with the Pokemon in the party. So, what you said is out of the question.
"its seems like only the first 8 HMs can be used to teach the moves while the other two when used will show that the Pokemon aren't able to learn it like in"

Maybe I misread.
But still, the area would have to be edited still? To include the new TMs/HMs.
 

ZodiacDaGreat

Working on a Mobile System
429
Posts
17
Years
Prof. Briar said:
Well, simple logic dictates that something must be declaring the number of TM/HMs. They seem to be stored in the same list, judging by the bleed over. Even so, the combined number doesn't add up to the maximum number of variables (forgive me for stating the obvious, I'm building a foundation for my hypothesis). It would seem from your test that there are two missing factors. One must define the highest numbered object that is a "TM", this being why anything beyond that value is automatically classed as a "HM". I think it likely that the other missing factor must relate to which badge is needed for which HM move to be taught in some way. Since you can only have eight badges, any "extra" HM would have no "badge check" to activate it. I don't know if that helps, and it's only a theory until tested, but it might give you an idea of what to be looking for.
Exactly. That's the missing routines.
 
5,256
Posts
16
Years
No reason to reply to years old thread. You will not get anything here

Actually, the thread revival rule does not apply here so he is well within his right to post here, as even if the OP isn't here, it's possible that other users may wish to help out. In future just report posts you feel are breaking the rules please.
 
200
Posts
10
Years
  • Age 30
  • Seen Jun 19, 2022
I have managed to _sort of_ do something like this; make a fake TM that isn't a TM (it's in misc items). If the goal is just to have more items that teach moves, this does that?

I used the Hacked Engine, and a simple normal item script that teaches you a move. My version has some problems (it teaches only the first pokemon in your party in the first slot a move), since I don't know the special to bring up the party screen and save that slot chosen to a var yet, if that even exists :(
It does not get used up when you use it. I consider that a bonus but people could easily add a deleteitem.
Also, any pokemon can learn, but that can be fixed simply by using special 12b to check pokemon type (by default that special just checks if grass, but there's a hacked version out there by FBI agent I think?), so you could get an item that teaches a move to, say, any water pokemon! You could also, if you just wanted only a few pokemon to learn it specifically, check for them instead.
I tried to use special DC to choose the slot, but it didn't seem to work, so I just use it to let you see the poke after.

here's my example, I hope this is useful (I'm kinda a newbie to hacking):
Code:
#dynamic 0x801250
#org @mymove
lock
bufferfirstpokemon 0x2
bufferattack 0x0 0x1
msgbox @teachmove 0x5
compare LASTRESULT 0x1
if 0x0 goto @end
setvar 0x8004 0x0 
special 0x6
setvar 0x8006 0x1 '= attack number
setvar 0x8005 0x0 ' = attack slot,
special 0x17 'change poke move
special 0xdc 
special 0x6
release
end
#org @end
release
end

#org @teachmove
= Teach [buffer3] [buffer1]?
You don't have to do any table repointing with this method, any hard stuff, just inset in some free space somewhere and change the use-item script pointer for one item. Just remember it goes in Misc. Items not TMs. Any, it seems really pretty nifty and cool- teach a move to a pokemon of a specific type! Although I have yet to actually try that type-specific part (it would be something like special2 0xvar tehtypespecial, compare var, if blah, I think?). It just always seemed a little weird to me there were, say, water type moves all water types couldn't learn.

I know this is kind of a sucky solution, since it isn't a 'real' TM, but I hope it helps someone and I'd like to see it in hacks.

EDIT: okay, I did some testing, here's a version that checks if the pokemon is the right type or not. Much more useful than the first given.
Also, I found it doesn't seem to like new hacked on moves past the originals. But still has potential.
Example:
Code:
#dynamic 0x801300
#org @mymove
lock
bufferfirstpokemon 0x2
bufferattack 0x0 0x0AC ' flame wheel
setvar 0x8000 0xA 'fire type.
special2 0x4001 0x12B 'the special, you will have to put in the patched version
compare 0x4001 0x1 'check the slot
if 0x0 goto @can
msgbox @donthave 0x2
release
end

#org @can
msgbox 0x8801286 MSG_YESNO '"Teach [buffer3] [buffer1] in 1st\n..."
msgbox @teachmove 0x5
compare LASTRESULT 0x1
if 0x0 goto @end
setvar 0x8004 0x0 
setvar 0x8005 0x0
special 0x6
setvar 0x8006 0x0AC '= attack number
special 0x17 'change poke move
special 0x6
special 0xdc '0x8005 = attack slot
release
end

#org @teachmove
= Teach [buffer3] [buffer1] in 1st slot? 

#org @donthave
= Your [buffer3] can't learn\n[buffer1], switch a diff. [PK][MN] to\l1st slot.
 
Last edited:

Blah

Free supporter
1,924
Posts
11
Years
I have managed to _sort of_ do something like this; make a fake TM that isn't a TM (it's in misc items). If the goal is just to have more items that teach moves, this does that?

I used the Hacked Engine, and a simple normal item script that teaches you a move. My version has some problems (it teaches only the first pokemon in your party in the first slot a move), since I don't know the special to bring up the party screen and save that slot chosen to a var yet, if that even exists :(
It does not get used up when you use it. I consider that a bonus but people could easily add a deleteitem.
Also, any pokemon can learn, but that can be fixed simply by using special 12b to check pokemon type (by default that special just checks if grass, but there's a hacked version out there by FBI agent I think?), so you could get an item that teaches a move to, say, any water pokemon! You could also, if you just wanted only a few pokemon to learn it specifically, check for them instead.
I tried to use special DC to choose the slot, but it didn't seem to work, so I just use it to let you see the poke after.

here's my example, I hope this is useful (I'm kinda a newbie to hacking):
Code:
#dynamic 0x801250
#org @mymove
lock
bufferfirstpokemon 0x2
bufferattack 0x0 0x1
msgbox @teachmove 0x5
compare LASTRESULT 0x1
if 0x0 goto @end
setvar 0x8004 0x0 
special 0x6
setvar 0x8006 0x1 '= attack number
setvar 0x8005 0x0 ' = attack slot,
special 0x17 'change poke move
special 0xdc 
special 0x6
release
end
#org @end
release
end

#org @teachmove
= Teach [buffer3] [buffer1]?
You don't have to do any table repointing with this method, any hard stuff, just inset in some free space somewhere and change the use-item script pointer for one item. Just remember it goes in Misc. Items not TMs. Any, it seems really pretty nifty and cool- teach a move to a pokemon of a specific type! Although I have yet to actually try that type-specific part (it would be something like special2 0xvar tehtypespecial, compare var, if blah, I think?). It just always seemed a little weird to me there were, say, water type moves all water types couldn't learn.

I know this is kind of a sucky solution, since it isn't a 'real' TM, but I hope it helps someone and I'd like to see it in hacks.

EDIT: okay, I did some testing, here's a version that checks if the pokemon is the right type or not. Much more useful than the first given.
Also, I found it doesn't seem to like new hacked on moves past the originals. But still has potential.
Example:
Code:
#dynamic 0x801300
#org @mymove
lock
bufferfirstpokemon 0x2
bufferattack 0x0 0x0AC ' flame wheel
setvar 0x8000 0xA 'fire type.
special2 0x4001 0x12B 'the special, you will have to put in the patched version
compare 0x4001 0x1 'check the slot
if 0x0 goto @can
msgbox @donthave 0x2
release
end

#org @can
msgbox 0x8801286 MSG_YESNO '"Teach [buffer3] [buffer1] in 1st\n..."
msgbox @teachmove 0x5
compare LASTRESULT 0x1
if 0x0 goto @end
setvar 0x8004 0x0 
setvar 0x8005 0x0
special 0x6
setvar 0x8006 0x0AC '= attack number
special 0x17 'change poke move
special 0x6
special 0xdc '0x8005 = attack slot
release
end

#org @teachmove
= Teach [buffer3] [buffer1] in 1st slot? 

#org @donthave
= Your [buffer3] can't learn\n[buffer1], switch a diff. [PK][MN] to\l1st slot.

This is the concept I would go with for "Expanding TMs". Just make another item that goes into the TMs pocket. Great thinking there longlostsoldier. You can change which pocket the item will appear in by modifying the pocket byte which is 0x1A.
As for the code, I would try to search for the TM use routine, and use it as a skeleton for a modified version of it for the new item.
 
200
Posts
10
Years
  • Age 30
  • Seen Jun 19, 2022
This is the concept I would go with for "Expanding TMs". Just make another item that goes into the TMs pocket. Great thinking there longlostsoldier. You can change which pocket the item will appear in by modifying the pocket byte which is 0x1A.
As for the code, I would try to search for the TM use routine, and use it as a skeleton for a modified version of it for the new item.

^_^ Yeah, I attempted to put it in TMs, but that caused the script not to work correctly, as it seemed to automatically interpret it as just another TM (Spit Up, in fact, which is odd). I probably should have mentioned that.

Alright, I found another version which doesn't use JPAN's hack, although it only allows for 16 more moves: one can use the Move Tutor special, which, well, acts a lot more like a normal tm as it automatically lets you choose a pokemon and a slot to teach it to.

Special 18D, just setflag 0x8005 to 0-F first to use in a script.

This also seems to cooperate with newer gen moves added to the engine (I used MrDollSteak for testing), so what one could do is add 16 new gen moves, put them in move tutor slots, and then simply use the other version of this to re-add the old move tutor moves and make them available. A pain in the butt, but, it does give 16+ more moves, which is pretty nifty. We've got some actual progress on adding new moves and new move tutoring items!

Edit: Oh yeah, I should mention, to alter the move tutor moves, the moves are two bytes each, starting from 0x459B60, from 0500 (mega punch?) to A400. 16 move tutor moves.
Using MrDollSteaks Decap and Fairy Type patch, I replaced several of them and tested out with these, 'altho I haven't actually tested each one it seems to work fine. One would still have to go in and manually change what pokemon can learn which move of course. Since the hexes for newer moves (especially in two byte form) don't seem to be listed anywhere, I thought I'd give them so other people could quick test too.

dark pulse 6f 01
rock climb 88 01
roost 8b 01
shadow claw 8d 01
xscissor 90 01
venoshock a6 01
dragon tail bc 01
giga impact! 78 01
flash cannon c1 01
dazzle d2 01
77 01 force palm
 
Last edited:

Blah

Free supporter
1,924
Posts
11
Years
^_^ Yeah, I attempted to put it in TMs, but that caused the script not to work correctly, as it seemed to automatically interpret it as just another TM (Spit Up, in fact, which is odd). I probably should have mentioned that.

Alright, I found another version which doesn't use JPAN's hack, although it only allows for 16 more moves: one can use the Move Tutor special, which, well, acts a lot more like a normal tm as it automatically lets you choose a pokemon and a slot to teach it to.

Special 18D, just setflag 0x8005 to 0-F first to use in a script.

This also seems to cooperate with newer gen moves added to the engine (I used MrDollSteak for testing), so what one could do is add 16 new gen moves, put them in move tutor slots, and then simply use the other version of this to re-add the old move tutor moves and make them available. A pain in the butt, but, it does give 16+ more moves, which is pretty nifty. We've got some actual progress on adding new moves and new move tutoring items!

Edit: Oh yeah, I should mention, to alter the move tutor moves, the moves are two bytes each, starting from 0x459B60, from 0500 (mega punch?) to A400. 16 move tutor moves.
Using MrDollSteaks Decap and Fairy Type patch, I replaced several of them and tested out with these, 'altho I haven't actually tested each one it seems to work fine. One would still have to go in and manually change what pokemon can learn which move of course. Since the hexes for newer moves (especially in two byte form) don't seem to be listed anywhere, I thought I'd give them so other people could quick test too.

dark pulse 6f 01
rock climb 88 01
roost 8b 01
shadow claw 8d 01
xscissor 90 01
venoshock a6 01
dragon tail bc 01
giga impact! 78 01
flash cannon c1 01
dazzle d2 01
77 01 force palm

Very good find. Actually you'll be pleased to know that I looked at the routine for special 0x18D and to my surprise there aren't ANY limiters. Literally none!
The code does a few things to get into the Pokemon selection menu, and checking if the Pokemon can learn the move or not. However, the pointer to the table is loaded directly into R0. Meaning if you can change that pointer you can have theoretically as many move tutor moves as you want!

The pointer to this is at: 0x120BE4

Well that solves the problem of expanding TMs. Good thinking Longlostsoldier!
 

MrDollSteak

Formerly known as 11bayerf1
858
Posts
15
Years
Very good find. Actually you'll be pleased to know that I looked at the routine for special 0x18D and to my surprise there aren't ANY limiters. Literally none!
The code does a few things to get into the Pokemon selection menu, and checking if the Pokemon can learn the move or not. However, the pointer to the table is loaded directly into R0. Meaning if you can change that pointer you can have theoretically as many move tutor moves as you want!

The pointer to this is at: 0x120BE4

Well that solves the problem of expanding TMs. Good thinking Longlostsoldier!

Well actually the problem with Move Tutor moves is that the Move Tutor Compatability is stored in a Bitmap, that means that you can only use 15 moves, so there's no need for a limiter as such. To make more moves you need to rewrite the compatibility table to work from a full word as opposed to a halfword.

I think it'd be more valuable to get more TMs by putting them in the bag. Also I think the reason it is so difficult to expand TMs is partially due to the TM compatability. That'll be why the extra two moves get pushed to the end and don't work, because they're now out of the array of the compatibility.
 

Blah

Free supporter
1,924
Posts
11
Years
Well actually the problem with Move Tutor moves is that the Move Tutor Compatability is stored in a Bitmap, that means that you can only use 15 moves, so there's no need for a limiter as such. To make more moves you need to rewrite the compatibility table to work from a full word as opposed to a halfword.

I think it'd be more valuable to get more TMs by putting them in the bag. Also I think the reason it is so difficult to expand TMs is partially due to the TM compatability. That'll be why the extra two moves get pushed to the end and don't work, because they're now out of the array of the compatibility.

You seem to be right about compatibility. I just tested on something outside and it failed to learn a compatible move. I fear that actual TM move learning is centered around this concept as well.
While you are allowed to have a large amount of moves, anything not supported is considered incompatible.

The only feasible way would be to extend the bit field to a larger size per Pokemon. Which is not something I'm interested in doing anymore :P
 
3,830
Posts
14
Years
  • Age 26
  • OH
  • Seen Feb 26, 2024
So I was toying around with trying to make new TMs and looking through the tables for TMs and I have successfully made 2 learnable TMs. (Though they have the problem with graphically being loaded as an HM, and being deletable like a TM.)

With the way the game is currently setup, we are able to have up to 64 compatible TM/HMs with the way the compatibility table is setup. The max amount of compatible moves for an individual poke is FF FF FF FF FF FF FF FF.

If all TM/HMs in game are learn-able (Mew) , the value for the table is FF FF FF FF FF FF FF 03. This value will result in 58 compatible moves (the same amount of TM/HM). Every individual F is the equivalent of 4 consecutive moves (i.e. 1-4 is 0F and 1-8 is FF).

This may be well known knowledge already, but I decided to post this any way in hopes that extending the amount of TMs becomes better documented information.

This is because each compatibility entry within the table is 64 bits (8 bytes), with the first 58 bits being used to check for TM/HM compatibility. Each bit determines whether a certain TM works, 0 being not allowed and 1 being allowed (it's a bitmap).

So for TM01, bit 0 determines whether it is learnable, and for HM01, bit 50 determines its compatibility, and so on.

This means that with the data alone, there is theoretically space right now to add 8 more TMs to the table without needing to rewrite how the game reads from the table too much.
 
22
Posts
9
Years
  • Age 27
  • Seen Oct 18, 2021
I understand the workings. However, the TM Bag will not allow more than 58 TM/HMs.

Insert this asm at any place.
.text
.align 2
.thumb
.thumb_func
.global tm_slots_hack

main:
ldr r0, ram
str r0, [r1, #0x18]
mov r0, #0x6C
strb r0, [r1, #0x1c]
ldr r0, return
bx r0

.align
ram: .word 0x0203c000
return: .word 0x08099e74+1

Then goto 99E6A, insert
01 48 00 47 00 00 FF FF FF 08
FF FF FF 08 is the pointer of the asm location+1

You should also apply Jpan's saveblock hack to keep those data saved.
This enable you to have 108 TM&HM in the bag.

Edit: The previous save file will not work if apply this.
 
Last edited:
22
Posts
9
Years
  • Age 27
  • Seen Oct 18, 2021
[S-HIGHLIGHT]Notes: BUG found, so use this at your own risk.[/S-HIGHLIGHT]
Also this is for Fire Red
1.First you need to create new TM, but once you create one, you need to follow it with another one until all are added.
If you don't want to overlap the previous item, item extension should be consider.

To remove the limiter for item extension
Spoiler:


Then repoint the item data(3DB028) and image & palette pointer(3D4294) like what you did in pokemon expansion.

2.After that repoint the TM/HM table at 45A80C, it should be 0x74 bytes long.
Then add whatever move you want to have for new TM.

3.Fix the TM move index routine
Spoiler:

125A78: 00 49 08 47 FF FF FF 08, FF FF FF 08 = first asm location+1
tm_table is what you repoint at step 2.

4.Fix the No.# things
Spoiler:


131D5A: 01 48 00 47 00 00 FF FF FF 08, FF FF FF 08 = second asm location+1

5.Fix the compatibility
Spoiler:


43C40: 00 48 00 47 FF FF FF 08, FF FF FF 08 = third asm location+1
table refer to your pokemon TM/HM compatibility table


Format:
It works exactly the same as vanilla fire red, but two more line added, so it supports up to 128 TM/HM.
Now each entry cost you 16 bytes, so the old compatibility table is dead.

Spoiler:



Every works fine but the animation when you forget move to learn new TM(thought it is pointless) will kill the game.
Also the sequence for the new TMs is not right.
 
Last edited:
15
Posts
9
Years
  • Age 28
  • Seen Nov 20, 2016
Is there any way to disable the animation on the overworld for learning TMs?
Also what do you mean by "Also the sequence for the new TMs is not right."?
 
Back
Top