Advertiser Content

Resource FBI's HM type-check hack

Started by Uncommon December 2nd, 2015 7:28 PM
  • 16831 views
  • 70 replies

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
Announcements

7/23/18
  • Bugs section added to OP (there's only 1 tiny one, I promise!)


Previous updates

Spoiler:
1/1/17:

Spoiler:
Happy New Year PC! I have a few bits of news to share about this project:.
  • Version 1.1 released! mbcn10ww discovered and solved a bug with this hack. In Version 1.0, for all HMs except Flash, although checking for types was functionally correct, the animation and text always showed the first Pokémon in your party, not necessarily the one with the correct type. mbcn10ww came up with a simple fix, which I verified and applied to all HMs in Version 1.1, with help from FBI. The Downloads section of this post has been updated.
  • I've added the source ASM for Fly into the Advanced section (originally I only had the compiled version there), so you can mess around with it if you want.
  • Also, mbcn10ww has made his own fork of this hack. In addition to the aforementioned bug fix, his version also moves the hack out to offset 0x990000 to increase compatibility with hacks in progress and adds the ability to use more than one type per HM move (which is really cool!). Check out the thread here.
  • I will continue to keep this thread maintained because I feel this base version is simpler and I can personally vouch for its stability, but feel free to check out mbcn10ww's version, too. I will still love you no matter which version you use <3
  • The Advanced section of this post is still being updated to reflect the changes to Version 1.1, I'll try to have that finished in the next couple days and will post an announcement when done. All the other sections are already updated.


1/7/17:

Spoiler:
  • The Advanced and Compatibility sections of the OP have been updated
  • This whole post is now up-to-date for Version 1.1







Uncommon's FBI HM system patch

Hi everyone! This is my first public contribution to the world of ROM hacking. What I’ve got for you today is a patch for FireRed (English 1.0 BPRE) that changes the behavior of HMs in the overworld. This is heavily based on FBI’s research on HM checks. All the credit for that research goes to FBI (along with knizz and touched), and I’ll be referring to his thread throughout this post.

What is this?

What this patch does is change all the HM overworld use checks. Instead of needing certain badges and moves to use HM moves in the overworld, you need to have certain types in your party. The needed type is easily changeable, but the types I've chosen to start with are:

Surf - Water
Waterfall - Water
Cut - Grass
Rock Smash - Fighting
Strength - Fighting
Flash - Fire
Fly - Flying
As described in FBI’s post, the original inspiration was to match the show, in which Trainers can effectively Surf with any Water-type Pokemon, Fly with (almost) any Flying-type, etc. This also eliminates the need to carry around an HM slave, or overwrite good moves for useless ones like Flash.

How does it work?

I've hijacked the internal script for each HM and redirected it to a new script that checks the new condition - whether or not you have a Pokemon of the appropriate type in your party - and, if so, activates the HM’s overworld effect. This check is accomplished with FBI’s modified version of special 0x12b, also explained in his post. I’ve tested all the scripts thoroughly and I’m confident their text and sequence of events match their vanilla FR counterparts (if applicable). If you want to get a deeper understanding of how this works, read FBI’s thread on changing the HM checks, and check out the script posted in the Advanced Usage section.

Usage

After patching, all of these are passive and don’t require any editing to start using them right away, except for Flash. To apply the Flash hack, you need to add it as a level script to each Flash-able map in A-Map. Its offset is 0x760024. I recommend following diego’s level script tutorial (starting at step 5, because the script is already done). For the flag variable in A-Map, use 4000. As FBI explained to me, this is a temporary variable that’s reset whenever the map reloads, meaning it’ll be ready to activate again each time you enter the map.

In the game

With the exception of now needing a type instead of a move and a badge, Surf, Waterfall, Cut, Rock Smash, and Strength work exactly how they normally do - press A to interact with an obstacle and follow the prompts.



If you have a Pokemon of the correct type (Fire by default), Flash will activate as soon as you enter a map with the level script applied.



To activate Fly, a new option has been added to the START menu: MAP. It shows you the town map, and if you have a Flying-type, lets you choose a location to Fly to. The MAP option shows up when you activate the POKEMON menu option (ie, when you get your first Pokemon).



Advanced Usage (optional)

Spoiler:
Enable/disable flags
Spoiler:


Each new HM script has two flag checks that allow you to enable/disable the HM with events in the game. First, there's a flag that controls whether or not the new HM check system itself is active. If this flag is cleared, the HMs will behave exactly as they do in vanilla FR. However, if you set the flag, they'll use the new system of checks instead. The flag I’ve used is 0x828, the flag for having the Pokemon option in the Start menu, which means as soon as you have any Pokemon, the new checks will be active. But you can change which flag controls this by editing the two reverse hex bytes at 0x760690, or by decompiling the script at 0x760414, editing the flag number, and recompiling (without changing the offset). If you change it to, say, flag 0x201 (so bytes 01 02 at 0x760690), the new checks would be disabled until you set flag 0x201 in a script.

Also, each script checks a second, individual flag beforehand, so you can make them dependent on badges as well if you want. I've set the flag for each one again to 0x828 so they’re immediately active by default, but like the overall enable/disable flag above, this is easily changeable. If you want to use a different flag, simply go to each offset specified below and overwrite the existing two bytes with the reverse hex of the flag you want to check instead:

Surf - 0x7602D8
Waterfall - 0x76038D
Cut - 0x7600DF
Rock Smash - 0x76016D
Strength - 0x7601FD
Flash - 0x760044
Fly - 0x7606F4


Changing types
Spoiler:


Also, you can easily change which types are required for each HM. Navigate the the offsets specified below for each type and change the byte to the value of the type you want:

Surf - 0x7602E3
Waterfall - 0x760398
Cut - 0x7600EA
Rock Smash - 0x760178
Strength - 0x760211
Flash - 0x760050
Fly - 0x7606BE
Values for each type (from FBI’s thread about his modified special 0x12b):

Spoiler:
Normal 0x0
Fighting 0x1
Flying 0x2
Poison 0x3
Ground 0x4
Rock 0x5
Bug 0x6
Ghost 0x7
Steel 0x8
??? (egg) 0x9
Fire 0xA
Water 0xB
Grass 0xC
Electric 0xD
Psychic 0xE
Ice 0xF
Dragon 0x10
Dark 0x11


New scripts

Spoiler:
You could also make these changes by decompiling and editing the new scripts, which are at the offsets below:

Surf - 0x7602C7
Waterfall - 0x76037C
Cut - 0x7600CD
Rock Smash - 0x76015B
Strength - 0x7601EB
Flash - 0x760024
Fly - 0x7606A0, but this one's ASM, so no easy decompiling.
The Fly check is done in ASM, here is the source code (commented):

.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r1, lr}
	
	ldr r1, =(0x8760690) @location of master enable flag
	ldrh r0, [r1]
	ldr r1, =(0x806E6D0 +1) @flag check routine
	bl CALLER
	cmp r0, #0x0 @if the master flag is not set
	beq NORMALMAP @open normal map

	ldr r0, =(0x828) @set the individual (badge) flag number
	ldr r1, =(0x806E6D0 +1) @flag check routine
	bl CALLER
	cmp r0, #0x0 @if the flag is not set
	beq NORMALMAP @open normal map

	ldr r0, .VAR @set paramaters for special
	mov r1, #0x2 @type to check; #0x2 is Flying
	strb r1, [r0]
	ldr r1, =(0x80CA804 +1) @look for flying type
	bl CALLER
	cmp r0, #0x6 @check if there is a flying type
	
	bge NORMALMAP @if no flying open normal map

	ldr r1, .SLOT @bug fix for showing wrong Pokemon
	strb r0, [r1] @write slot number of flying type to .SLOT

	ldr r1, =(0x80C4EF8 +1) @open Fly map
	bl CALLER
	b END

NORMALMAP:
	ldr r1, =(0x80A1CC0 +1)
	bl CALLER
	b END

CALLER:
	bx r1

END:
	pop {r0-r1,pc}
	

.align 2
.VAR:
	.word 0x020270B8 + (0x8000 * 2)
.SLOT:
	.word 0x0203B0A9

These scripts are mostly independent, but they all reference one script for the overall enable/disable flag check, and also one script for a sort of initialization/check that the game does for each HM. I don’t think it’s necessary but I decided to leave it in just in case.


Decap

Spoiler:
All the texts used are decap-agnostic because they dynamically load the names of Pokemon and attacks, except for the Fly menu change. Those are capitalized by default so that this patch can be applied to vanilla FR with no editing, but decapped versions of those texts are already included as well. To use them, navigate to the two offsets below and make these changes:

Spoiler:
At 0x3A735C, paste-write:

2C 06 76
At 0x3A73A0, paste-write:

34 06 76
These will point the name and description for the menu text to the decapped versions instead.







Compatibility

Now, you’ll notice I have used free space for these new scripts (from 760000-760704), which means this patch MIGHT NOT be compatible with hacks in progress. Since most people start at 800000, there’s a good chance it IS compatible (for instance, this patch is 100% compatible with MrDollsteak's Attack and Decap Rombase!) but it’s not guaranteed. If you really want to add this to a hack in progress, below are instructions for doing so.

Spoiler:
Tools required:
XSE ( v1.1.1 - older versions may not work)
A hex editor (I recommend HxD)
Advance Map (only needed for Flash)

There a a lot of steps. Gives you an idea of how long it took to develop this.

First, you’ll need to insert FBI’s modified special 0x12b. Here are instructions for doing so (quoted from FBI’s thread):
Put into some free space (even ending):
06 4A 12 78 88 79 90 42 02 D0 C8 79 90 42 03 D1 28 1C 70 BC 02 BC 08 47 01 48 00 47 B8 70 03 02 59 A8 0C 08
Keep track of the offset you inserted this in.

Now go to 0xCA840, and insert:
00 48 00 47
Finally, for the next four bytes, you must do some reverse hex. Take the offset you inserted in, and prefix it with 08. Then insert the reverse hex version of the whole thing plus 1.
So if I inserted at 7266B0, then
7266B0 = 087266B0
087266B + 1 = 087266B1
087266B1 = B1 66 72 08 (you insert this after 00 48 00 47).

Finally we want to return 6, if there isn't a Pokemon in the party of the type we specified. Go to 0xCA862 and change 00 to 06. That's it!
Next, open up your ROM in XSE, copy and paste the script below into the XSE window, and compile. I’ve used dynamic offsets for all the new scripts, so this will NOT overwrite anything you’ve already done. The static offsets you see in the scripts are those for existing HM scripts, calls to scripts that end, release, etc., and the appropriate text strings. A fun note: because these scripts call existing text strings and dynamically pull the names of attacks, they’re decap-agnostic! You’ll note I have the dynamic start offset set to 0x760000; feel free to change that if you want. Note down the offset it gives you for @Flash, and for @flagcheck. You’ll need to apply the Flash hack manually - see Usage above - and you’ll need the @flagcheck offset to apply the Fly hack.

Looooong script:
Spoiler:
#dynamic 0x760000


'---------------
#org @flash
lock
setvar 0x4000 0x1     'set this to the flag variable in A-Map (can be 4000-4010 - temps)
checkflag 0x806	      'flash active flag - do not change
if 0x1 goto 0x1A7AE0

call @init            'initialization check, from original
call @flagcheck       'check if new check system is enabled 
if 0x0 goto 0x1A7AE0  'if not, release and end

checkflag 0x828	      'set this to the new badge you want (828 is the pkmn menu)
if 0x0 goto 0x1A7AE0  'if not set, release and end

lockall
setvar 0x8000 0xA     'set this to the type you want (A is Fire)
special2 0x4001 0x12B 'these lines are the new check
compare 0x4001 0x6
if 0x4 goto 0x1A7AE0

bufferpartypokemon 0x0 0x4001 
bufferattack 0x1 0x94
msgbox @question MSG_YESNO '"[buffer1] can light up the\ndarkne..."
compare LASTRESULT 0x0
if 0x1 goto 0x1A7AE0
msgbox 0x81BDFD7 MSG_KEEPOPEN '"[buffer1] used [buffer2]!"
setanimation 0x0 0x4001 
doanimation 0x28
waitstate
lighten 0x0
darken 0x0
setflag 0x806

releaseall
end

'---------
' Strings
'---------
#org @question 
= [buffer1] can light up the darkness\nwith [buffer2]. Use [buffer2]?






'---------------
#org 0x1BDF13
goto @newcut

'---------------
#org @newcut

call @init            'initialization check, from original
call @flagcheck       'check if new check system is enabled 
if 0x0 goto @originalcut

lockall
checkflag 0x828	      'set this to the new badge you want (828 is the pkmn menu)
if 0x0 goto 0x81BDF87

setvar 0x8000 0xC     'set this to the type you want (C is Grass)
special2 0x4001 0x12B
compare 0x4001 0x6
if 0x4 goto 0x81BDF87
'setvar 0x4001 LASTRESULT 

goto @cutaction

'---------------
#org @originalcut

checkflag 0x821
if 0x0 goto 0x81BDF87
checkattack 0xF
compare LASTRESULT 0x6
if 0x1 goto 0x81BDF87

goto @cutaction

'---------------
#org @cutaction

setanimation 0x0 0x4001
bufferpartypokemon 0x0 0x4001
bufferattack 0x1 0xF
msgbox 0x81BDF94 MSG_YESNO '"This tree looks like it can be Cut..."
compare LASTRESULT 0x0
if 0x1 goto 0x81BDF91
msgbox 0x81BDFD7 MSG_KEEPOPEN '"[buffer1] used [buffer2]!"
closeonkeypress
doanimation 0x2
waitstate
goto 0x81BDF76









'---------------
#org 0x1BE00C
goto @newrocksmash

'---------------
#org @newrocksmash

call @init            'initialization check, from original
call @flagcheck       'check if new check system is enabled 
if 0x0 goto @originalrocksmash

lockall
checkflag 0x828	      'set this to the new badge you want (828 is the pkmn menu)
if 0x0 goto 0x81BE091

setvar 0x8000 0x1     'set this to the type you want (1 is Fighting)
special2 0x4001 0x12B
compare 0x4001 0x6
if 0x4 goto 0x81BE091
'setvar 0x4001 LASTRESULT 
lockall

goto @rocksmashaction

'---------------
#org @originalrocksmash
lockall
checkflag 0x825
if 0x0 goto 0x81BE091
checkattack 0xF9
compare LASTRESULT 0x6
if 0x1 goto 0x81BE091

goto @rocksmashaction


'---------------
#org @rocksmashaction

setanimation 0x0 0x4001
bufferpartypokemon 0x0 0x4001
bufferattack 0x1 0xF9
msgbox 0x81BE09D MSG_YESNO '"This rock appears to be breakable...."
compare LASTRESULT 0x0
if 0x1 goto 0x81BE09A
msgbox 0x81BDFD7 MSG_KEEPOPEN '"[buffer1] used [buffer2]!"
closeonkeypress
doanimation 0x25
waitstate
goto 0x81BE06F







'---------------
#org 0x1BE11D
goto @newstrength

'---------------
#org @newstrength

call @init            'initialization check, from original
call @flagcheck       'check if new check system is enabled 
if 0x0 goto @originalstrength

lockall
checkflag 0x828       'set this to the new badge you want (828 is the pkmn menu)
if 0x0 goto 0x81BE185
checkflag 0x805       'strength active flag - do not change
if 0x1 goto 0x81BE18E

setvar 0x8000 0x1     'set this to the type you want (1 is Fighting)
special2 0x4001 0x12B
compare 0x4001 0x6
if 0x4 goto 0x81BE185
'setvar 0x4001 LASTRESULT 

goto @strengthaction


'---------------
#org @originalstrength

lockall
checkflag 0x823
if 0x0 goto 0x81BE185
checkflag 0x805
if 0x1 goto 0x81BE18E
checkattack 0x46
compare LASTRESULT 0x6
if 0x1 goto 0x81BE185

goto @strengthaction


'---------------
#org @strengthaction
bufferattack 0x1 0x46
setanimation 0x0 0x4001
msgbox 0x81BE19A MSG_YESNO '"It's a big boulder, but a Pokémon\..."
compare LASTRESULT 0x0
if 0x1 goto 0x81BE197
closeonkeypress
doanimation 0x28
waitstate
setflag 0x805
msgbox @strengthtext MSG_NORMAL '"[buffer1] used [buffer2]!\p[buffer..."
end


'---------
' Strings
'---------
#org @strengthtext
= [buffer1] used [buffer2]!\p[buffer1]'s [buffer2] made it\npossible to move boulders around!









'---------------
#org 0x1A6AC8
goto @newsurf

'---------------
#org @newsurf

call @init            'initialization check, from original
call @flagcheck       'check if new check system is enabled 
if 0x0 goto @originalsurf

checkflag 0x828       'set this to the new badge you want (828 is the pkmn menu)
if 0x0 goto @nosurf

setvar 0x8000 0xB     'set this to the type you want (B is Water)
special2 0x4001 0x12B
compare 0x4001 0x6
if 0x4 goto @nosurf
'setvar 0x4001 LASTRESULT 

goto @surfaction

'---------------
#org @originalsurf

checkflag 0x824
if 0x0 goto 0x1A6B0C
checkattack 0x39
compare LASTRESULT 0x6
if 0x1 goto 0x81A6B0C

goto @surfaction

'---------------
#org @surfaction

setanimation 0x0 0x4001
bufferpartypokemon 0x0 0x4001
lockall
bufferattack 0x1 0x39
msgbox 0x81A556E MSG_YESNO '"The water is dyed a deep blue[.]\n..."
compare LASTRESULT 0x0
if 0x1 goto 0x81A6B0B
msgbox 0x81BDFD7 MSG_KEEPOPEN '"[buffer1] used [buffer2]!"
doanimation 0x9
releaseall
end

'---------------
#org @nosurf
msgbox @nosurftext MSG_SIGN
releaseall
end

'---------
' Strings
'---------
#org @nosurftext
= The water is dyed a deep blue[.]







'---------------
#org 0x1BE2B7
goto @newwaterfall

'---------------
#org @newwaterfall

call @init            'initialization check, from original
call @flagcheck       'check if new check system is enabled 
if 0x0 goto @originalwaterfall

checkflag 0x828       'set this to the new badge you want (828 is the pkmn menu)
if 0x0 goto 0x81BE300 'specific to waterfall

setvar 0x8000 0xB     'set this to the type you want (B is Water)
special2 0x4001 0x12B
compare 0x4001 0x6
if 0x4 goto 0x81BE300 'specific to waterfall
'setvar 0x4001 LASTRESULT 

goto @waterfallaction


'---------------
#org @originalwaterfall

checkflag 0x826
if 0x0 goto 0x1A6B0C
lockall
checkattack 0x7F
compare LASTRESULT 0x6
if 0x1 goto 0x81BE300

goto @waterfallaction

'---------------
#org @waterfallaction

setanimation 0x0 0x4001
bufferpartypokemon 0x0 0x4001
lockall
bufferattack 0x1 0x7F
msgbox 0x81BE33F MSG_YESNO '"It's a large waterfall.\nWould you..."
compare LASTRESULT 0x0
if 0x1 goto 0x81BE308
msgbox 0x81BDFD7 MSG_KEEPOPEN '"[buffer1] used [buffer2]!"
doanimation 0x2B
goto 0x81BE308










'---------------
#org @init
special 0x187         'some error check that the game does for each HM
compare LASTRESULT 0x2
if 0x1 goto 0x81A7AE0
return

'---------------
#org @flagcheck
setvar 0x4001 0x0     'initialize variable - fixes a silly bug
setvar LASTRESULT 0x0 'initialize variable - fixes a silly bug
checkflag 0x828       'set this to the new flag to enable/disable the new checks
return


Next, make the following edits in your hex editor:

At 0x6D588, replace 0C D1 with 00 00 (this allows Surf to look outside its own check)
At 0x6D566, replace 03 D1 with 00 00 (this allows Waterfall to look outside its own check)
At 0x6D59C, replace 24 08 with 28 08 (bypasses game’s Surf badge check)
At 0x6D5D0, replace 26 08 with 28 08 (bypasses game’s Waterfall badge check)

Don’t worry about bypassing the badge checks - my script has a badge check you can use if you want. We just need to bypasses this one to start the new check process.

Then, to apply the Fly hack, make these changes:

Spoiler:
At free space ending in a multiple of 4, paste-write:

03 B5 12 49 08 88 12 49 00 F0 1A F8 00 28 13 D0 10 48 0F 49 00 F0 14 F8 00 28 0D D0 09 48 02 21 01 70 0D 49 00 F0 0C F8 06 28 05 DA 06 49 08 70 0A 49 00 F0 05 F8 04 E0 09 49 00 F0 01 F8 00 E0 08 47 03 BD B8 70 03 02 A9 B0 03 02 XX XX XX 08 D1 E6 06 08 28 08 00 00 05 A8 0C 08 F9 4E 0C 08 C1 1C 0A 08
where XX XX XX is a (reversed) pointer to [the offset of @flagcheck from the XSE script +0xB (hex)]. This is the offset where the actual number for the flag to check is written.

Note down the offset where you paste. This the Fly routine.

At 0x3A7344, paste-write:

7D 62 41 08 11 F4 06 08 66 5A 41 08 4D F4 06 08 85 62 41 08 81 F4 06 08 30 A4 71 08 51 A4 71 08 8E 62 41 08 B5 F4 06 08 96 62 41 08 FD F4 06 08 91 62 41 08 E9 F4 06 08 9D 62 41 08 41 F5 06 08 A2 62 41 08 55 F5 06 08 00 01 01 0A 04 0F 08 00 76 9F 41 08 BB 9F 41 08 01 A0 41 08 34 A4 71 08 49 A0 41 08 B7 A0 41 08 6F A0 41 08 11 A1 41 08 49 A0 41 08 F8 01 00 00 00 02 0F 1A 04 0F 98 01 FF 00 00 00 00 00 00 00 00 01 01 0E 09 0D 08 00 01 02 03 00 01 04 05 00 01 06 07 00 00 00 00 00 00 00 B0 BB 00 B0 BB AA 00 AB BA AA 00 AB 99 BB B0 BB 99 BA B0 AA AB BA B0 AA AB BB 00 00 00 00 00 00 00 00 0B 00 00 00 0B 00 00 00 BB B0 0B 00 AA AB BA 00 AA 99 AA 0B BB 99 BB 0B 00 BB B4 BB 00 44 44 4F 40 FD 4F F4 40 DF 4F 44 00 44 44 FD 00 FF D4 DF 00 00 F4 FD 00 00 40 44 AA BA AA 0B AB BA AA 0B B4 4B BB 00 F4 44 F4 0F 4F 44 44 FF 4F FF DF F4 F4 F4 FD 04 FF 4F 44 00 00 00 00 00 00 00 B0 0B 00 BB AB BA B0 AA AB BA B0 9A B9 BB BB 9B A9 BB AB BA AA AB AB BA BA AB 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0B BB 00 00 BA AA 0B 00 9A A9 BA 00 B0 4B BB BB 00 44 44 AB 40 FD 4F BF 40 DF 4F 44 00 44 44 FD 00 FF D4 DF 00
This is the Start menu change.

At free space, paste-write:

C7 BB CA FF 00 FF
This is the Map name text. If you want it decapped, paste-write this instead:

C7 D5 E4 FF 00 FF
At free space, paste-write:

BD DC D9 D7 DF 00 ED E3 E9 E6 00 E4 E6 D9 E7 D9 E2 E8 00 E0 E3 D7 D5 E8 DD E3 E2 00 D5 E2 D8 00 D8 D9 D7 DD D8 D9 FE EB DC D9 E6 D9 00 E8 E3 00 C0 C6 D3 B8 00 DD DA 00 ED E3 E9 00 DC D5 EA D9 00 D5 00 C0 C6 D3 C3 C8 C1 AE CE D3 CA BF AD FF 00 FF
This is the Map description text. If you want it decapped, paste-write this instead:

BD DC D9 D7 DF 00 ED E3 E9 E6 00 E4 E6 D9 E7 D9 E2 E8 00 E0 E3 D7 D5 E8 DD E3 E2 00 D5 E2 D8 00 D8 D9 D7 DD D8 D9 FE EB DC D9 E6 D9 00 E8 E3 00 C0 E0 ED B8 00 DD DA 00 ED E3 E9 00 DC D5 EA D9 00 D5 00 C0 E0 ED DD E2 DB AE E8 ED E4 D9 AD FF 00 FF
At 0x3A7360 write in a pointer to the offset of the fly routine + 1.

At 0x3A735C, write in a pointer to the offset of the "name" text.

At 0x3A73A0, write in a pointer to the offset of the "description" text.

At free space ending in a multiple of 4, paste-write:

30 B4 0C 1C 13 48 14 49 00 F0 22 F8 00 06 00 0E 01 28 1A D1 01 20 11 49 00 F0 1A F8 02 20 0F 49 00 F0 16 F8 03 20 0D 49 00 F0 12 F8 04 20 0B 49 00 F0 0E F8 05 20 09 49 00 F0 0A F8 06 20 07 49 00 F0 06 F8 30 BC 01 BC 00 47 30 BC 04 48 00 47 08 47 C0 46 28 08 00 00 D1 E6 06 08 95 ED 06 08 DB ED 06 08
This is a bug fix for the menu.

At 0x6EDC6, write in 01 48 00 47 00 00 followed by a pointer to offset of the bug fix + 1.

At 0x6EDD0, paste-write:

01 28 02 D1 01 20 FF F7 DD FF 02 20 FF F7 DA FF 04 20 FF F7 D7 FF 05 20 FF F7 D4 FF 06 20 FF F7 D1 FF 06 20 00 00 00 00 01 BC 00 47 29 08 00 00
This is a change to the order that the START menu options load.

All the ASM was written by FBI, except for a slight edit to the Fly routine done by me (to add in flag checks). For more info and the actual ASM, check out FBI’s thread on changing the HM checks.



Bugs

Spoiler:

  • When using HM moves in the overworld, the animation and text always show the first Pokémon in your party, not necessarily the one with the correct type FIXED in Version 1.1 thanks to mbcn10ww and FBI
  • In the Safari Zone, the option to RETIRE from the START menu is gone. This is because this hack changes the START menu and the Safari Zone uses a different version of the START menu that I never bothered to check while building it. The issue is documented here. Since it's not game-breaking in any way (the only ill effect is that you lose the option to immediately "retire" from the Start menu and have to use up your steps instead), I don't plan on addressing it, but I have posted the relevant information in the linked thread in case you want to take a crack at it.


Credits

I intend to use this in my upcoming hack, and now you can, too! With permission from FBI, this patch is for public use. Feel free to use it as long as you credit the following people:

FBI - for the research and ASM development, plus help with fixing a bug with Fly
knizz - for helping in FBI’s research on Fly
touched - for helping create FBI’s modified special 0x12b
mbcn10ww - for discovering and fixing a bug with the wrong Pokemon being displayed
Uncommon - for writing the scripts, testing, and creating this patch

Downloads

and finally... the patch!

Version 1.1 - .zip file that includes both the full patch and a patch to upgrade from version 1.0 to 1.1, plus instructions in the ReadMe

Changelog

Spoiler:
12/2/15 - Version 1.0 released
1/1/17 - Version 1.1 released (fixes a bug where the animation and text always show the first Pokémon in your party, not necessarily the one with the correct type - credit to mbcn10ww and FBI)
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

PokemonBen

Kanto Champion

Male
England
Seen December 15th, 2015
Posted December 7th, 2015
60 posts
4 Years
This is brilliant. Now I can have an easier time making gym leaders and make my hack go the way I want it to. Question: can we disable some of them? For example maybe I want people to need a gym badge to use surf, but I want to keep all the others. Sorry if you have explained but I am my phone.

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
This is brilliant. Now I can have an easier time making gym leaders and make my hack go the way I want it to. Question: can we disable some of them? For example maybe I want people to need a gym badge to use surf, but I want to keep all the others. Sorry if you have explained but I am my phone.
Thanks! There isn't (yet) a way to disable the type-check system for a single HM, but it's easy to add in a Gym badge requirement for any HM (on top of the type requirement) - check the Advanced Usage section, under Enable/Disable Flags. Let me know if that accomplishes what you want. If not, I could add that ability in, or help you do it.

It's pretty cool.
Quick question: can other Pokémon types still learn HMs and be able to use it?
Good question. Not directly by interacting with an obstacle, but you can still use them from the Pokemon menu. Maybe I should disable those...
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

ThomasWinwood

Male
Seen 2 Days Ago
Posted 2 Days Ago
86 posts
5.9 Years
In-battle there's nothing special about "an HM move". What Uncommon just said was nothing in this thread prevents you from activating HM moves like Flash by teaching a Pokémon Flash and then using it from the Pokémon menu.
The rival in Red and Blue is called Green. Gary is some character from a lame cartoon.

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
So we can't use Surf in battle? Or do you just mean we can't manually activate Flash?
In-battle there's nothing special about "an HM move". What Uncommon just said was nothing in this thread prevents you from activating HM moves like Flash by teaching a Pokémon Flash and then using it from the Pokémon menu.
ThomasWinwood is exactly correct. There have been no changes to the HM moves themselves, only to the conditions that allow you to use their effects in the overworld.
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

Bobsomeness

Pure Bobsomeness

Male
Pallet Town
Seen November 28th, 2018
Posted April 28th, 2017
218 posts
4.5 Years
This is amazing! I'm using it for my hack (credit will be given, of course).
This signature has been disabled.
Too tall
Please review and fix the issues by reading the signature rules.

You must edit it to meet the limits set by the rules before you may remove the [sig-reason] code from your signature. Removing this tag will re-enable it.

Do not remove the tag until you fix the issues in your signature. You may be infracted for removing this tag if you do not fix the specified issues. Do not use this tag for decoration purposes.

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
What do you mean by disable?
I mean eliminating the ability to use HMs from the Pokemon menu, so you can only activate them from interacting with obstacles in the overworld (and the special "MAP" option for Fly). I'm sure I saw a thread explaining how to do this, but now I can't seem to find it... For now I'll just leave it as-is, so you can continue to use HMs from the Pokemon menu if you have a Pokemon who knows the move, in addition to the new overworld type checks.
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
Is it really compatible with Mr Dollstreak's base?
As of the time of writing (December '15), it was 100% compatible. I've been pretty much inactive since February, though, so I don't know if Dollsteak's had any updates that break compatibility. I've listed all the free offsets I used in the thread, so you can compare to Dollsteak's thread and check for any overlaps.
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
How easy would it be to change the routine to check for whether or not a pokémon can learn the given HM move, rather than typing?
I thought about doing this too, and I actually think it's probably a better idea. In theory, it should be pretty easy. All you'd have to do is edit my scripts and change the lines where I used FBI's special 0x12b to check types to instead check the move table. I just never got familiar enough with the move table do it.
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

Age 21
Male
Seen 3 Hours Ago
Posted March 23rd, 2019
545 posts
7.1 Years
How easy would it be to change the routine to check for whether or not a pokémon can learn the given HM move, rather than typing?
I thought about doing this too, and I actually think it's probably a better idea. In theory, it should be pretty easy. All you'd have to do is edit my scripts and change the lines where I used FBI's special 0x12b to check types to instead check the move table. I just never got familiar enough with the move table do it.
I think this is what you're looking for. http://www.pokecommunity.com/showpost.php?p=8927083&postcount=726
Male
Seen January 18th, 2017
Posted January 18th, 2017
110 posts
5.1 Years
Bug Fix:



The code to do this is simple, first compile this into free space:
Spoiler:


Code:
.text .align 2 .thumb .thumb_func main: push {r4-r5} mov r4, r1 @save r1 contents ldr r0, = 0x828 ldr r1, = (0x806E6D0 +1) @checkflag bl linkerOne lsl r0, r0, #0x18 lsr r0, r0, #0x18 cmp r0, #0x1 bne end mov r0, #0x1 @load rest of menu manually ldr r1, = (0x806ED94 +1) bl linkerOne mov r0, #0x2 ldr r1, = (0x806ED94 +1) bl linkerOne mov r0, #0x3 ldr r1, = (0x806ED94 +1) bl linkerOne mov r0, #0x4 ldr r1, = (0x806ED94 +1) bl linkerOne mov r0, #0x5 ldr r1, = (0x806ED94 +1) bl linkerOne mov r0, #0x6 ldr r1, = (0x806ED94 +1) bl linkerOne pop {r4-r5} pop {r0} @put separately for readability bx r0 end: pop {r4-r5} ldr r0, =(0x806EDDA +1) @if no party bx r0 linkerOne: bx r1 .align 2





Now go to 0x6EDC6 and overwrite the bytes there with:
01 48 00 47 00 00
The next 4 bytes after these 6 is the pointer to the above assembled code + 1 in reverse hex.
What the above does is creates a branch from the initial flagcheck into our routine.

Finally we need to modify the order that the other menus come up pre-map availablity.
Go to 0x6EDD0 and ctrl+b this:
Code:
01 28 02 D1 01 20 FF F7 DD FF 02 20 FF F7 DA FF 04 20 FF F7 D7 FF 05 20 FF F7 D4 FF 06 20 FF F7 D1 FF 06 20 00 00 00 00 01 BC 00 47 29 08 00 00

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
http://www.pokecommunity.com/showpost.php?p=8505791&postcount=14

The finally, the soft reset, in menu
...what?

Not really sure what you're getting at here. I'm well aware of the post you linked, I used FBI's work to make this.

Please explain what bug you are seeing in the hack. If there is a bug, I'd like to confirm the fix, but I don't understand what you're trying to fix here.
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

Male
Seen January 18th, 2017
Posted January 18th, 2017
110 posts
5.1 Years
...what?

Not really sure what you're getting at here. I'm well aware of the post you linked, I used FBI's work to make this.

Please explain what bug you are seeing in the hack. If there is a bug, I'd like to confirm the fix, but I don't understand what you're trying to fix here.
When you open the menu is Restarts

When you start a game and open the menu restarts, you send that page is for you to check and mend the error, If you want good haha xD , alone Help wanted .

Uncommon

Oozma Kappa

Johto
Seen 4 Hours Ago
Posted 1 Week Ago
191 posts
4.4 Years
When you open the menu is Restarts

When you start a game and open the menu restarts, you send that page is for you to check and mend the error, If you want good haha xD , alone Help wanted .
Definitely not a bug. If the game restarts when you open the menu, it means the hack has been applied wrong. This is usually a symptom of incorrectly pointing to an ASM routine.

Did you use the patch I provided, or did you apply things on your own? Please download the patch, patch it to a clean ROM and try again.
My work: HM type-check system hack (FireRed) | Turbo Test patch (FireRed)

Advertiser Content