PHO - Pokémon Hackers Online
Go Back   PHO - Pokémon Hackers Online > Discussion Board > Archive

Notices

Archive Old threads that serve no purpose are here.

 
 
Thread Tools Display Modes
Old 7th September 2011, 12:42 PM   #1
Jambo51
Glory To Arstotzka
Ex-Staff
 
Jambo51's Avatar
 
Join Date: May 2012
Location: Scotland
Posts: 85
Jambo51
Default Jambo51's ASM Resource Center

Hey there, I'm relatively new to this forum, but i've been kicking about on PC for a while and have built up a considerable list of useful ASM routines, mostly for FireRed (US) 1.0. I wanted to share these routines with other hackers, but always got the impression that the people (mods) over at PC didn't like me very much because I sided with Gamer2020 in his war of words with them.

Anyway, I decided to put this post up.

Stuff Needed:
Basic Hex Editing Knowledge
A Brain
A THUMB compiler - HackMew's is the best i've found so far
A Hex Editor - I use Hex Workshop

If you use these, you should credit me. If I credit anyone else in here, you should credit them too.

Each piece of ASM will be presented like this:
CODE - The actual ASM code
INSERTION LOCATION - Where to put the link to the new routine, and what hex bytes you will need to do it.
EXPLANATION - A short explanation of what the code does.

Without further ado, I present to you the ASM itself:

Trainer Encounter Music Hack:
Spoiler:

The code:
Code:
.text
.align 2
.thumb
.thumb_func
.global exclaimhack

main:
ldr r1, table
cmp r0, #0x14 /*This is the number of encounter music track you want
to have. If you use a value above this, it loads slot 3 of the table as a
failsafe*/
ble back
mov r0, #0x3
back: lsl r0, r0, #0x1
add r1, r0, r1
ldrh r0, [r1, #0x0]
ldr r1, place
bx r1
.align
place: .word 0x080806BB
table: .word 0xFFFFFFFF
Where to insert: In a hex editor, navigate to 0x80650, and overwrite the data there with this: 00 49 08 47 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: All this does is reads the "music" byte which accompanies every trainer battle, and reads a newly created table. This table should have a half word for each entry. Which represent which music slot will be played for that music byte. Create your table wherever you like, then change the table: .word 0xFFFFFFFF to be a pointer to this new table.

Build the table like so:
Spoiler:
1D01 1D01 1C01 1C01 (etc)

putting in as many entries as you want.


Legendary Battle Music Hack:
Spoiler:

The Code:
Code:
.text
.align 2
.thumb
.thumb_func
.global battlemusichackleg
main: push {r2,r3}
ldr r0, tableloc
there: ldrh r2, [r0, #0x0]
cmp r1, r2
beq loadmusic
ldr r3, end
cmp r2, r3
beq loadnormal
add r0, #0x4
b there
loadnormal: mov r1, #0xAA
lsl r1, r1, #0x1
add r1, #0x1
return: pop {r2,r3}
ldr r0, goback
bx r0
loadmusic: ldrh r1, [r0, #0x2]
b return
.align
end: .word 0x0000FEFE
goback: .word 0x0807FA3F
tableloc: .word 0xFFFFFFFF
Where to Insert: Navigate to 0x7F9F4 and change the bytes to 01 1C 00 00 00 48 00 47 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: This routine reads what Pokémon species you are fighting, and searches a created table for that species. When it finds that species, it loads the associated music slot to modify what battle music you hear. If it doesn't find a matching species, it loads music slot 0x155 as standard.

The table should be set out as such:
Let's say you wanted Mewtwo to have slot 0x154, Mew to have slot 0x12B and Ho-oh to have slot 0x153. The table would be laid out like so:
9600 5401 9700 2B01 FA00 5301 FEFE 0000
In otherwords, you repeat this pattern until you want the table to end, which is were you put the "killing" half word. The number the routine looks for to mark the end of the table.

[Pokémon ID - Half word - in little endian (reverse hex)] [Music slot to load - Half word - little endian mode]

This table will only affect legendary battles which are run through special 0x138!


Naming the Rival from the Overworld:
Spoiler:

The Code:
Code:
.text
.align 2
.thumb
.thumb_func
.global rivalnamingingame
main:
push {r0-r4,lr}
ldr r0, place
str r0, [sp, #0x4]
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
mov r0, #0x4
mov r2, #0x0
mov r3, #0x0
bl place2
ldr r1, ramlocation
ldr r1, [r1, #0x0]
ldr r0, standard
add r1, r1, r0
ldrb r0, [r1, #0x0]
cmp r0, #0xFF
beq failsafe
cmp r0, #0x0
beq failsafe
return: pop {r0-r4}
pop {pc}
place2: ldr r4, actualroutine
bx r4
failsafe: ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
strb r2, [r1, #0x0]
cmp r2, #0xFF
beq return
add r0, #0x1
add r1, #0x1
b loop
.align
place: .word 0x080568E1
ramlocation: .word 0x03005008
standard: .word 0x00003A4C
actualroutine: .word 0x0809D955
rivalname: .word 0x08FFFFFF
Where to insert: Anywhere! This routine is called from a script in the game, and as such, doesn't need to be carefully linked into existing routines. All you need to do is remember the rule of THUMB, add 1 to the offset when calling it!

Explanation: It's what it says on the tin, it lets you name your rival from the in game overworld, allowing for Silver like naming, or indeed, any other possibility you can come up with. The rivalname: .word 0x08FFFFFF is for if the player leaves the name box blank. It will fill it with a standard name instead. This standard name is up to you to create. Simply compile a name with XSE, and point that pointer to it.

You also need to put this routine in the game, or else it won't be able to load past the intro without naming the rival. All it does is temporarily write a holding name to the rival buffer so that the game doesn't crash.

Code:
.text
.align 2
.thumb
.thumb_func
.global rivalnamingskip
main:
ldr r1, [r6, #0x0]
ldr r0, number
mov r8, r0
add r1, r8
push {r1}
ldr r0, rivalname
loop: ldrb r2, [r0, #0x0]
cmp r2, #0xFF
beq end
strb r2, [r1, #0x0]
add r0, #0x1
add r1, #0x1
b loop
end: strb r2, [r1, #0x0]
pop {r1}
mov r0, sp
ldr r3, return
bx r3
.align
number: .word 0x00003A4C
rivalname: .word 0x08FFFFFF
return: .word 0x08054A75
Where to insert: Navigate to 0x54A6A, and change the following bytes to this:
01 49 08 47 00 00 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: It simply writes a placeholder name into the [rival] buffer so the game doesn't crash. Obviously, you shouldn't be using the [rival] buffer until the player has named the rival, so it shouldn't be a problem.

To make this work, navigate to 0x130690, and change the pointer there to 0x1307D1.


Making Pre-Battle Mugshots available to all trainers:
Spoiler:

The Code:
Code:
.text
.align 2
.thumb
.thumb_func
.global mugshothackone
main:
cmp r0, #0x87
beq there
cmp r0, #0x88
beq there
ldr r4, ramoffset
ldrh r4, [r4, #0x0]
lsl r5, r4, #0x2
add r5, r4, r5
lsl r4, r5, #0x3
ldr r5, place
ldr r5, [r5, #0x0]
add r0, r4, r5
ldrb r0, [r0, #0x3]
there: add r4, r0, #0x0
add r5, r1, #0x0
add r6, r2, #0x0
mov r9, r3
ldr r7, [sp, #0x34]
ldr r0, return
bx r0
.align
place: .word 0x08044028
ramoffset: .word 0x020386AE
return: .word 0x0808386D
Where to insert: Navigate to 0x83862, and replace the existing code with this:
01 4C 20 47 00 00 XX XX XX 08.
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: This routine reads a what sprite the trainer you're about to battle has, and passes that index to the original routine, which then loads the appropriate sprite from there.

You will also need the following routine. This routine reads the trainerbattle script for a byte which tells it whether it should or should not load a mugshot.

The Code:
Code:
.text
.align 2
.thumb
.thumb_func
.global mugshothacktwo
main:
ldrb r5, [r4, #0x3]
lsl r5, r5, #0x18
lsr r5, r5, #0x18
cmp r5, #0x0
beq normalchecks
mov r1, #0x5A
ldr r5, returnone
bx r5
normalchecks: cmp r1, #0x57
bne later
add r1, r2, #0x0
mov r0, #0xCD
ldr r5, returntwo
bx r5
later: ldr r5, returnone
bx r5
.align
returntwo: .word 0x0807FFA5
returnone: .word 0x08080009
Where to insert: Navigate to 0x7FF90, and replace the existing code with this:
00 4A 10 47 XX XX XX 08
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: This code simply reads the trainerbattle script to judge whether or not it should load a mugshot. If the byte loaded is NOT 0, it will load a mugshot.

And the final piece of code, which allows us to control the background pallet of the mugshot, follows:

The Code:
Code:
.text
.align 2
.thumb
.thumb_func
.global mugshotpallethack
main:
ldr r1, ramoffset
ldrh r1, [r1, #0x0]
lsl r0, r1, #0x2
add r0, r0, r1
lsl r1, r0, #0x3
ldr r0, trainertable
ldr r0, [r0, #0x0]
add r1, r0, r1
ldrb r1, [r1, #0x1]
cmp r1, #0x5A
beq oldway
cmp r1, #0x57
beq oldway
ldr r1, ramoffset
ldrb r1, [r1, #0x3]
sub r1, #0x1
lsl r1, r1, #0x2
ldr r0, table2
add r1, r1, r0
ldr r0, [r1, #0x0]
b back
oldway: ldr r1, table
mov r2, r8
mov r3, #0x26
ldrh r0, [r2, r3]
lsl r0, r0, #0x2
add r0, r0, r1
ldr r0, [r0, #0x0]
back: ldr r1, return
bx r1
.align
ramoffset: .word 0x020386AE
trainertable: .word 0x08044028
table: .word 0x083FA740
table2: .word 0x08FFFFFF
return: .word 0x080D28D5
Where to insert: Navigate to 0xD28C6, and replace the existing code with this:
01 49 08 47 00 00 XX XX XX 08
Where the XX's stand for the pointer to the new routine plus 1.

Explanation: This routine reads the byte given by the trainerbattle script to determine which background pallet to load for the mugshot. The table2: .word 0x08FFFFFF is the location of a new table which contains pointers to the new pallets you can create for the mugshots. For an understanding of how these work, open 0x3FA6A0 in APE. This will show you how the pallets are constructed. You do NOT have to create 1 pallet for male and 1 for female, as the game actually works out which is needed, and sticks the relevant colours onto the end of the pallet you create. You also need to navigate to 0x801F5 and change the byte to 0x78.

How to use: Once the routines are present and correct, all you need to do to use the mugshots is write your trainerbattle like so:

trainerbattle [type] [id] [pallet id - byte AND 0x0 - byte] [messages...]
eg.: trainerbattle 0x1 0x123 0x100 @challenge @lose @after (for Pallet 1)
trainerbattle 0x0 0x124 0x200 @challenge @lose (for Pallet 2)

Please note, the battle type makes no difference to the mugshots. It will work with any battle type.


Fixing the player not facing trainers:
Spoiler:

You need to call this routine from the edited script given at the end of this part.

The Code:
Code:
.text
.align 2
.thumb
.thumb_func
.global trainerface
main:
push {r0-r3,lr}
ldr r0, storeloc
ldrb r0, [r0, #0x0]
mov r1, #0x24
mul r0, r1
ldr r1, playerloc
add r0, r0, r1
ldrh r2, [r0, #0x10]
ldrh r3, [r1, #0x10]
cmp r2, r3
beq alternative
sub r2, r2, r3
cmp r2, #0x1
beq right
mov r0, #0x2
b end
right: mov r0, #0x3
b end
alternative: ldrh r2, [r0, #0x12]
ldrh r3, [r1, #0x12]
sub r2, r2, r3
cmp r2, #0x1
beq up
mov r0, #0x1
b end
up: mov r0, #0x0
end: ldr r1, lastresult
strh r0, [r1, #0x0]
pop {r0-r3,pc}
.align
storeloc: .word 0x03005074
playerloc: .word 0x02036E38
lastresult: .word 0x020370D0
Where to insert: Call from the script which follows.

Explanation: This simply reads the player's location against the trainer you're battling's location, and returns an assigned value which controls which way the player will look.

The Script:
Code:
#dynamic 0x800000
#org @main
callasm 0x8XXXXXX
compare LASTRESULT 0x0
if 0x1 call @down
compare LASTRESULT 0x1
if 0x1 call @up
compare LASTRESULT 0x2
if 0x1 call @left
compare LASTRESULT 0x3
if 0x1 call @right
goto 0x81A4FC7
#org @down
applymovement 0xFF   @Lookdown
waitmovement 0xFF
return
#org @up
applymovement 0xFF   @Lookup
waitmovement 0xFF
return
#org @left
applymovement 0xFF   @Lookleft
waitmovement 0xFF
return
#org @right
applymovement 0xFF   @Lookright
waitmovement 0xFF
return
#org   @Lookdown
#raw 0x0
#raw 0xFE
#org   @Lookup
#raw 0x1
#raw 0xFE
#org   @Lookleft
#raw 0x2
#raw 0xFE
#org   @Lookright
#raw 0x3
#raw 0xFE
Where to insert: Compile this script wherever you like and note down it's location.
You must also change the pointer of the callasm to the location of the SECOND routine plus one. Then, navigate to 0x1A4EBD and 0x1A4F15, and change the pointers there to point to your new script.

Explanation: The actual script which makes the player turn and face opponents. You don't need to call it or anything, it's all done automatically in the background now.


These should all be completely bug free for the time being., but if anyone spots any bugs, hit me up and I'll try to get them fixed ASAP.
__________________
I have nothing interesting to add

Last edited by Jambo51; 25th October 2013 at 07:43 PM.
Jambo51 is offline  
Likes daniilS, Full Metal ★ liked this post
Sponsored Links
Old 25th October 2013, 12:45 PM   #2
Linkandzelda
RHO つぃちょう
Webmaster
 
Linkandzelda's Avatar
 
Join Date: Apr 2012
Location: United Kingdom
Posts: 286
Linkandzelda Linkandzelda Linkandzelda
Default

Just restored this document from the depths of hell, bumping because nobody ever saw it before due to the old date.
__________________





Linkandzelda is offline  
Likes daniilS liked this post
Old 25th October 2013, 02:37 PM   #3
Pia Carrot
Orange Developer
Administrator
 
Pia Carrot's Avatar
 
Join Date: Aug 2010
Location: Valencia Island
Age: 22
Posts: 811
Pia Carrot Pia Carrot Pia Carrot Pia Carrot Pia Carrot
Default

:O This existed around the time I wasn't around due to family issues, and I think PCF was shortly after this so no wonder it died.

Interesting resource though, even if it is 2 years old now.
Pia Carrot is offline  
Old 25th October 2013, 02:41 PM   #4
Linkandzelda
RHO つぃちょう
Webmaster
 
Linkandzelda's Avatar
 
Join Date: Apr 2012
Location: United Kingdom
Posts: 286
Linkandzelda Linkandzelda Linkandzelda
Default

Quote:
Originally Posted by Pia Carrot View Post
:O This existed around the time I wasn't around due to family issues, and I think PCF was shortly after this so no wonder it died.

Interesting resource though, even if it is 2 years old now.
This particular thread was never posted on PHO so that's why nobody saw it, I got it from the TPW archives
__________________





Linkandzelda is offline  
Old 28th October 2013, 10:01 AM   #5
mewthree9000
Junior Trainer
 
mewthree9000's Avatar
 
Join Date: May 2010
Location: U.S.A.
Age: 27
Posts: 70
mewthree9000 mewthree9000
Default

Jambo, for the love of god, make more tutorials!
__________________
-Mewthree9000
We all fight a war within ourselves, a war of greatness, a war to become the best.
LIVE THE REVOLUTION, PHO!
Gotta Hack'em All!!




My current projects:
-Pokemon ChaosBlack[v2]
-!!Elite FireRed ROM Base!!
mewthree9000 is offline  
Likes Jambo51 liked this post
 

Tags
asm, center, jambo51, resource, [Document]

Thread Tools
Display Modes

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. The time now is 01:59 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, vBulletin Solutions, Inc. User Alert System provided by Advanced User Tagging (Lite) - vBulletin Mods & Addons Copyright © 2018 DragonByte Technologies Ltd.
Feedback Buttons provided by Advanced Post Thanks / Like (Lite) - vBulletin Mods & Addons Copyright © 2018 DragonByte Technologies Ltd.
Pokémon characters and images belong to Pokémon USA, Inc. and Nintendo.
Pokémon Hackers Online (PHO) is in no way affiliated with or endorsed by Nintendo LLC, Creatures, GAMEFREAK inc,
The Pokémon Company, Pokémon USA, Inc., The Pokémon Company International, or Wizards of the Coast.
All forum/site content (unless noted otherwise) and site designs are © 2006-2013 Pokémon Hackers Online (PHO).
Green Charizard Christos TreeckoLv100

"Black 2" by ARTPOP. Kyurem artwork by XOUS.

no new posts