The PokéCommunity Forums  

Go Back   The PokéCommunity Forums > Fan Games > Binary ROM Hacking
Reload this Page Help Thread ASM & Disassembly

Notices
For all updates, view the main page.

Binary ROM Hacking Need a helping hand or just want to talk about binary ROM hacks? Get comments and answers to any ROM Hacking-related problems, questions or thoughts you have here.

Ad Content
Closed Thread
 
Thread Tools
  #201   Link to this post, but load the entire thread.  
Old March 5th, 2015 (7:05 AM).
jiangzhengwenjzw's Avatar
jiangzhengwenjzw jiangzhengwenjzw is offline
now working on katam
 
Join Date: Sep 2012
Gender: Male
Posts: 175
Quote:
Originally Posted by FBI agent View Post
All of them are available in thumb mode unless stated otherwise (divARM for example is ARM obviously, and the ones marked as NDS aren't GBA)
Actually that's not what happens in the ldmia still. It's like a looped ldr. The word sequence at the RAM offset (in r0) is being stored in the registers in the Rlist, ldr != str.

I was just suspicious that you were curious about things, while not understanding the basics. If you've read tutorials, then you can dismiss my random suspicions :P
I'm still wrong? But I could only get those from your words...
You say
Quote:
The word sequence at the RAM offset (in r0) is being stored in the registers in the Rlist, ldr != str.
I think that's the same as my understanding...
  #202   Link to this post, but load the entire thread.  
Old March 5th, 2015 (8:46 AM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by jiangzhengwenjzw View Post
I'm still wrong? But I could only get those from your words...
You say


I think that's the same as my understanding...
Code:
........
ldr r0, ramoffset
........
ldmia r0!, {r2-r6}
........

.align 2
ramoffset:
.word 0x02000000
Is conceptually the same as:

Code:
main:
	mov r1, #0x0

loop:
	ldr r0, .ramoffset
	add r0, r0, r1
	ldr r(Next), [r0] @so the register we're storing into is basically taken as "next register in the list"
	add r1, r1, #0x1
	cmp r1, #Number of registers in Rlist
	ble loop

.align 2
ramoffset:
.word 0x02000000
We're writing to the registers in Rlist, not to the RAM offset. Hence my saying,
Quote:
The word sequence at the RAM offset (in r0) is being stored in the registers in the Rlist, ldr != str.
__________________
...
  #203   Link to this post, but load the entire thread.  
Old March 5th, 2015 (5:01 PM).
jiangzhengwenjzw's Avatar
jiangzhengwenjzw jiangzhengwenjzw is offline
now working on katam
 
Join Date: Sep 2012
Gender: Male
Posts: 175
Quote:
Originally Posted by FBI agent View Post
Code:
........
ldr r0, ramoffset
........
ldmia r0!, {r2-r6}
........

.align 2
ramoffset:
.word 0x02000000
Is conceptually the same as:

Code:
main:
	mov r1, #0x0

loop:
	ldr r0, .ramoffset
	add r0, r0, r1
	ldr r(Next), [r0] @so the register we're storing into is basically taken as "next register in the list"
	add r1, r1, #0x1
	cmp r1, #Number of registers in Rlist
	ble loop

.align 2
ramoffset:
.word 0x02000000
We're writing to the registers in Rlist, not to the RAM offset. Hence my saying,
Yes, Actually I think I knew that the words at the RAM address were written into the registers in the Rlist in sequence.
I think I have the same meaning as yours. Maybe I didn't convey what I wanted to say clearly...
Thank you for your reply. :P
  #204   Link to this post, but load the entire thread.  
Old March 9th, 2015 (12:36 AM).
daniilS's Avatar
daniilS daniilS is offline
busy trying to do stuff not done yet
 
Join Date: Aug 2013
Age: 23
Gender: Male
Posts: 409
Quote:
Originally Posted by Lone Knight View Post
OK I want to use sound in my ASM routine. I settled the register to appropriate values and called the fanfare routine
Sound did play. But the game froze. Can anyone help me?
Please show us your routine, we can't really say much without looking at it.
__________________
  #205   Link to this post, but load the entire thread.  
Old March 21st, 2015 (2:51 PM).
Chaotix Chaotix is offline
Love to test
 
Join Date: Feb 2007
Nature: Adamant
Posts: 59
I'm trying to get the EVs for Trainers hack detailed in http://www.pokecommunity.com/showthread.php?t=307117 to work for Fire Red.

The code I am working with is:

Spoiler:
#EV spread table format
#Each spread is 16 bytes
#0x0 = Nature
#0x4 = IVs (from 0-31, not 0-255, used for all IVs)
# (if you want hidden powers, recall the ai can't handle -- bp moves)
#0x5 = HP EVs
#0x6 = Atk EVs
#0x7 = Def EVs
#0x8 = Speed EVs
#0x9 = SAtk EVs
#0xA = SDef EVs
#0xB = Pokeball
#0xC = Ability
#last four bytes are filler

.align 2
.thumb
.thumb_func

.org 0x115f6
mov r0, r1
mov r6, r0
b 0x11604

.org 0x1162c
ldr r0, .Method_Addr
bx r0

.Method_Addr: .word 0x08F90001

.org 0x3dc70
b 0x3dcd0


.org 0xF90000

LoadItem:
add r5, #0x6
add r0, r4, #0x0
mov r1, #0xc
add r2, r5, #0x0
bl Insert_Element

LoadHPEV:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0x5
mov r1, #0x1A
mov r0, r4
bl Insert_Element

LoadAtkEV:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0x6
mov r1, #0x1B
mov r0, r4
bl Insert_Element

LoadDefEV:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0x7
mov r1, #0x1C
mov r0, r4
bl Insert_Element

LoadSpeedEV:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0x8
mov r1, #0x1D
mov r0, r4
bl Insert_Element

LoadSAtkEV:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0x9
mov r1, #0x1E
mov r0, r4
bl Insert_Element

LoadSDefEV:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0xA
mov r1, #0x1F
mov r0, r4
bl Insert_Element

LoadBall:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0xB
mov r1, #0x26
mov r0, r4
bl Insert_Element

LoadAbility:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
add r2, #0xC
mov r1, #0x2E
mov r0, r4
bl Insert_Element

StartNatureLoop:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
ldrb r5, [r2, #0x0]
cmp r5, #0x0
beq LoadIVs
ldr r0, [r4, #0x0]
ldr r1, [r4, #0x4]
eor r1, r0, r1
str r1, [r4, #0x4]

NatureLoop:
ldr r0, [r4, #0x0]
add r0, r0, #0x18
str r0, [r4, #0x0]
mov r1, #0x19
bl Mod
cmp r0, r5
bne NatureLoop

EndNatureLoop:
ldr r0, [r4, #0x0]
ldr r1, [r4, #0x4]
eor r1, r0, r1
str r1, [r4, #0x4]

LoadIVs:
lsl r0, r6, #0x4
ldr r2, .EV_Table
add r2, r0
ldrb r6, [r2, #0x4]
push {r6}

StartIVLoop:
mov r5, #0x27

IVLoop:
mov r0, r4
mov r1, r5
mov r2, sp
bl Insert_Element
add r5, r5, #0x1
cmp r5, #0x2D
bne IVLoop

End:
pop {r6}
bl Recalculate_Stats
ldr r1, .Return_Addr
bx r1

Insert_Element:
ldr r3, .Insert_Addr
bx r3

Recalculate_Stats:
mov r0, r4
ldr r1, .Recalc_Addr
bx r1

Mod:
ldr r3, .Mod_Addr
bx r3

.align 2
.Return_Addr: .word 0x08011639
.EV_Table: .word 0x08F00000
.Insert_Addr: .word 0x0804037d
.Recalc_Addr: .word 0x0803e47d
.Mod_Addr: .word 0x081e4685


After compiling the bin file, there are supposedly three areas in the rom I need to replace with bytes from the bin file. Those locations being at 0x115f6, 0x3dc70, and 0xF90000. I am having problems determining how much I am supposed to replace at 0x115f6 and 0x3dc70.

Starting offset 0x115f0 in the bin file the bytes are:

Spoiler:
000115f0 00 00 00 00 00 00 08 1c 06 1c 03 e0 00 00 00 00 ...........à....
00011600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00011610 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00011620 00 00 00 00 00 00 00 00 00 00 00 00 00 48 00 47 .............H.G
00011630 01 00 f9 08 00 00 00 00 00 00 00 00 00 00 00 00 ..ù.............


and at offset 0x3dc70 the bytes in the bin file are:

Spoiler:
0003dc70 2e e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .à..............
0003dc80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0003dc90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0003dca0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................


With all the 0's I don't know where to stop replacing bytes in the rom.

For consistency, the bytes at 0xF90000 in the bin are:

Spoiler:
00f90000 06 35 20 1c 0c 21 2a 1c 00 f0 69 f8 30 01 38 4a .5 ..!*..ðiø0.8J
00f90010 12 18 05 32 1a 21 20 1c 00 f0 61 f8 30 01 34 4a ...2.! ..ðaø0.4J
00f90020 12 18 06 32 1b 21 20 1c 00 f0 59 f8 30 01 30 4a ...2.! ..ðYø0.0J
00f90030 12 18 07 32 1c 21 20 1c 00 f0 51 f8 30 01 2c 4a ...2.! ..ðQø0.,J
00f90040 12 18 08 32 1d 21 20 1c 00 f0 49 f8 30 01 28 4a ...2.! ..ðIø0.(J
00f90050 12 18 09 32 1e 21 20 1c 00 f0 41 f8 30 01 24 4a ...2.! ..ðAø0.$J
00f90060 12 18 0a 32 1f 21 20 1c 00 f0 39 f8 30 01 20 4a ...2.! ..ð9ø0. J
00f90070 12 18 0b 32 26 21 20 1c 00 f0 31 f8 30 01 1c 4a ...2&! ..ð1ø0..J
00f90080 12 18 0c 32 2e 21 20 1c 00 f0 29 f8 30 01 18 4a ...2.! ..ð)ø0..J
00f90090 12 18 15 78 00 2d 0f d0 20 68 61 68 41 40 61 60 ...x.-.Ð [email protected]`
00f900a0 20 68 18 30 20 60 19 21 00 f0 1e f8 a8 42 f7 d1 h.0 `.!.ð.ø¨B÷Ñ
00f900b0 20 68 61 68 41 40 61 60 30 01 0d 4a 12 18 16 79 [email protected]`0..J...y
00f900c0 40 b4 27 25 20 1c 29 1c 6a 46 00 f0 08 f8 01 35 @´'% .).jF.ð.ø.5
00f900d0 2d 2d f7 d1 40 bc 00 f0 04 f8 04 49 08 47 05 4b --÷Ñ@¼.ð.ø.I.G.K
00f900e0 18 47 20 1c 04 49 08 47 04 4b 18 47 39 16 01 08 .G ..I.G.K.G9...
00f900f0 00 00 f0 08 7d 03 04 08 7d e4 03 08 85 46 1e 08 ..ð.}...}ä...F..


but I'm fairly sure I inserted those correctly at 0xF90000 in the rom.

If anyone can help me out I would appreciate it greatly. As I have it right now when I begin a trainer battle with Custom moves and Custom items it restarts and goes back to the title screen.

I also have applied JPAN's hacked engine, would that cause problems with this?
  #206   Link to this post, but load the entire thread.  
Old March 22nd, 2015 (9:41 AM).
Mystery Man's Avatar
Mystery Man Mystery Man is offline
Don't be like me!
 
Join Date: Dec 2011
Age: 27
Nature: Quirky
Posts: 205
@Chaotix
If I remember correctly, you do not do anything with the sea of 00s the bin file gives you. Firstly, look at the ASM code. Locate all of the offsets that are not at the end of the ASM code (i.e. 0x115f6). That should tell you the starting point of what to copy from the bin file and replace in your ROM. So for the first offset, go to 0x115f6 in the bin file, copy all of the bytes before the vast sea of zeros (in this particular one, "08 1c 06 1c 03 e0"), and go to the exact location in your ROM (0x115f6) and replace whatever bytes are there with the ones you copied from the bin file.

As far as compatability with JPAN's hacked engine, I remember having issues with the set trainer level specials. That's all I know as I used the hack applier tool and have only selected a few hacks.
  #207   Link to this post, but load the entire thread.  
Old March 23rd, 2015 (7:21 AM).
Chaotix Chaotix is offline
Love to test
 
Join Date: Feb 2007
Nature: Adamant
Posts: 59
Quote:
Originally Posted by Mystery Man View Post
@Chaotix
If I remember correctly, you do not do anything with the sea of 00s the bin file gives you. Firstly, look at the ASM code. Locate all of the offsets that are not at the end of the ASM code (i.e. 0x115f6). That should tell you the starting point of what to copy from the bin file and replace in your ROM. So for the first offset, go to 0x115f6 in the bin file, copy all of the bytes before the vast sea of zeros (in this particular one, "08 1c 06 1c 03 e0"), and go to the exact location in your ROM (0x115f6) and replace whatever bytes are there with the ones you copied from the bin file.

As far as compatability with JPAN's hacked engine, I remember having issues with the set trainer level specials. That's all I know as I used the hack applier tool and have only selected a few hacks.
Thanks for replying.

I just tried your suggestion and unfortunately its a similar problem. When battles against trainers with custom moves and items start now the game freezes and the screen stays black.

Something just doesn't seem right about the values I'm getting in the bin to replace at 0x3dc70, to me; just two bytes, that's all?
  #208   Link to this post, but load the entire thread.  
Old March 23rd, 2015 (7:27 AM).
Red John's Avatar
Red John Red John is offline
Progressing Assembly hacker
 
Join Date: May 2014
Location: Where ever there is peace and darkness
Gender: Male
Nature: Lonely
Posts: 137
How to execute a script in Thumb?
__________________
  #209   Link to this post, but load the entire thread.  
Old March 23rd, 2015 (7:37 AM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by Lone Knight View Post
How to execute a script in Thumb?
You need to call the script executor function. It's at 08069AE4 and takes one paramater, the script pointer, in r0. There are some limitations involved however, so be careful.
__________________
...
  #210   Link to this post, but load the entire thread.  
Old March 23rd, 2015 (3:12 PM).
Mystery Man's Avatar
Mystery Man Mystery Man is offline
Don't be like me!
 
Join Date: Dec 2011
Age: 27
Nature: Quirky
Posts: 205
Quote:
Originally Posted by Chaotix View Post
Thanks for replying.

I just tried your suggestion and unfortunately its a similar problem. When battles against trainers with custom moves and items start now the game freezes and the screen stays black.

Something just doesn't seem right about the values I'm getting in the bin to replace at 0x3dc70, to me; just two bytes, that's all?
It might be the set trainer level specials now that I remember correctly. I would try reverting the bytes that the set trainer level special hack changes to those of an unhacked Firered, as it interferes with the EV hack. Here is what fixed it for me: go to 0x011624. The bytes there should be "00 48 00 47 ?? ?? ?? 08". Overwrite that with Firered's original coding, which is: "20 1C 33 1C 2C F0 14 FA". It should work now (that, or there might be another thing I forgot.)

Yes, it is only two bytes. In ASM code, this is all that is being done:
Spoiler:

Code:
.org 0x3dc70
b 0x3dcd0
  #211   Link to this post, but load the entire thread.  
Old March 23rd, 2015 (6:59 PM).
Red John's Avatar
Red John Red John is offline
Progressing Assembly hacker
 
Join Date: May 2014
Location: Where ever there is peace and darkness
Gender: Male
Nature: Lonely
Posts: 137
Quote:
Originally Posted by FBI agent View Post
You need to call the script executor function. It's at 08069AE4 and takes one paramater, the script pointer, in r0. There are some limitations involved however, so be careful.
Are you sure? I know that place has something to do with script, but I saw it using the r5 for something. And also what are the limitations to be precise?
__________________
  #212   Link to this post, but load the entire thread.  
Old March 24th, 2015 (5:30 AM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by Lone Knight View Post
Are you sure? I know that place has something to do with script, but I saw it using the r5 for something. And also what are the limitations to be precise?
There are recursion limitations. Also, it doesn't use r5 for parameters, the actual routine even pushes r5.
__________________
...
  #213   Link to this post, but load the entire thread.  
Old March 24th, 2015 (11:53 AM).
Red John's Avatar
Red John Red John is offline
Progressing Assembly hacker
 
Join Date: May 2014
Location: Where ever there is peace and darkness
Gender: Male
Nature: Lonely
Posts: 137
Quote:
Originally Posted by FBI agent View Post
There are recursion limitations. Also, it doesn't use r5 for parameters, the actual routine even pushes r5.
Its not working. Here is the script and code
Spoiler:

Main script
Code:
#org 0x72001
callasm 0x730001
Routine at 730000
Code:
main:
push {r0-r1,lr}
ldr r0, =0x8720000
ldr r1, =0x8069ae5
bx r1
Script at 720000
Code:
#org 0x720000
msgbox @msg 0x2
#org @msg
= Tis a test.
__________________
  #214   Link to this post, but load the entire thread.  
Old March 24th, 2015 (12:15 PM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by Lone Knight View Post
Its not working. Here is the script and code
Spoiler:

Main script
Code:
#org 0x72001
callasm 0x730001
Routine at 730000
Code:
main:
push {r0-r1,lr}
ldr r0, =0x8720000
ldr r1, =0x8069ae5
bx r1
Script at 720000
Code:
#org 0x720000
msgbox @msg 0x2
#org @msg
= Tis a test.
Uhh, you've got issues with your script AND your routine. I'll address the routine issues here.

Code:
.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r3, lr}
	ldr r0, =(0x8720000)
	ldr r1, =(0x8069AE4 +1)
	bl linker
	pop {r0-r3, pc}
	
linker:
	bx r1
	
.align 2
In your routine, you pushed the registers, but haven't popped them. This creates misaligned pushes and pops. That being said, because we have to use bx to reach the function (in this case), we need to use the "bl linker" tactic of branching in order to write to the link register so you CAN pop. That's the error with your routine.

For your scripts, I notice you're not using dynamic offsets, which is fine if you know what you're doing. However, 72000 is not free space (for your first script). I suggest just using dynamic offsets all the time, unless you're editing something specific. On top of that, you're missing a few other commands like "end" in your scripts. Read up on a few scripting tutorials and such for more on that stuff.
__________________
...
  #215   Link to this post, but load the entire thread.  
Old March 24th, 2015 (1:16 PM).
daniilS's Avatar
daniilS daniilS is offline
busy trying to do stuff not done yet
 
Join Date: Aug 2013
Age: 23
Gender: Male
Posts: 409
I think the actual reason it isn't working is because you need 08 before the callasm offset.
__________________
  #216   Link to this post, but load the entire thread.  
Old March 25th, 2015 (3:41 AM).
jiangzhengwenjzw's Avatar
jiangzhengwenjzw jiangzhengwenjzw is offline
now working on katam
 
Join Date: Sep 2012
Gender: Male
Posts: 175
Quote:
Originally Posted by FBI agent View Post
There are recursion limitations. Also, it doesn't use r5 for parameters, the actual routine even pushes r5.
Hello, I've read your ""Hooking" from existing routines" tutorial, but I have a small problem.
When setting the bx to the new program, the value of R2 was changed. Though it will be changed again by r0 (in the program at 08008DA4) after that in this case, but I think there maybe another case which do not refresh value of r2 after the program so it's not safe to use R2 to load other values.
So can you tell me the reason to not use push {r2} & pop {r2}?
  #217   Link to this post, but load the entire thread.  
Old March 25th, 2015 (5:56 AM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by daniilS View Post
I think the actual reason it isn't working is because you need 08 before the callasm offset.
No you don't, XSE and PKSV both add the 08 prefix during compile time if it's not already there. Noob scripter daniilS, pls :P

Quote:
Originally Posted by jiangzhengwenjzw View Post
Hello, I've read your ""Hooking" from existing routines" tutorial, but I have a small problem.
When setting the bx to the new program, the value of R2 was changed. Though it will be changed again by r0 (in the program at 08008DA4) after that in this case, but I think there maybe another case which do not refresh value of r2 after the program so it's not safe to use R2 to load other values.
So can you tell me the reason to not use push {r2} & pop {r2}?
Hi, by ASM standards r0-r3 are assumed by functions to be safe to be parameters. In the case the function doesn't require 4 parameters, it still assumes that these registers are safe to used. You'll notice that all functions will push any register equal or higher than r4. You avoid these kinds of scenarios by either pushing the low registers then modifying them accordingly, or by writing their values into higher registers before function calling so that they can be easily restored.

Ex:
Code:
.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r3, lr}
	
	@r0 is the address for the first pokemon in the party
	ldr r0, =(0x2024284)

	@we save r0 by setting r4 to it.
	mov r4, r0

	@call decrypter func to return species
	mov r1, #0xB
	ldr r3, =(0x803FBE8 +1)
	bl linker

	@put the return of decrypter (species ID) into r1
	mov r1, r0

	@restore first pokemon, then do whatever to that address
	@adding 0x64 is ofcourse getting the next 'Mon
	mov r0, r4
	add r0, r0, #0x64
	....
	....
	pop {r0-r3, pc}
	
linker:
	bx r3
	
.align 2
Here we utilize the fact that functions will push all registers higher or equal to r4 which they use. So if we write into r4 something which we want to save that was previously in r0, then the function (if it uses r4) will push r4 (but not r0-r3), thus saving the values in r4. I.e it will not consume what's in r4, but there's no guarantee that r0-r3 is saved.

Here's an example using the pushing method
Code:
.text
.align 2
.thumb
.thumb_func

main:
	@suppose we're hooking from a function
	@at this point, say r0 has the OTID. But we want to
	@call a function which requires r0 to be 0x5 to work
	ldr r0, =(OTID)
	push {r0}
	mov r0, #0x5
	
	@assuming r1 is not a required paramater
	ldr r1, =(0x8Function +1)
	bl linker

	@functions return values are kept in r0, if not void
	mov r1, r0
	pop {r0}

	@now r0 is back to being the OTID.	
	
linker:
	bx r1
	
.align 2
I prefer the writing to bigger sized registers method. However, it's likely, especially when you're hooking, that these registers contain data which shouldn't be overwritten. In such cases, you will need to push said registers.
__________________
...
  #218   Link to this post, but load the entire thread.  
Old March 25th, 2015 (7:06 AM).
jiangzhengwenjzw's Avatar
jiangzhengwenjzw jiangzhengwenjzw is offline
now working on katam
 
Join Date: Sep 2012
Gender: Male
Posts: 175
Quote:
Originally Posted by FBI agent View Post
No you don't, XSE and PKSV both add the 08 prefix during compile time if it's not already there. Noob scripter daniilS, pls :P



Hi, by ASM standards r0-r3 are assumed by functions to be safe to be parameters. In the case the function doesn't require 4 parameters, it still assumes that these registers are safe to used. You'll notice that all functions will push any register equal or higher than r4. You avoid these kinds of scenarios by either pushing the low registers then modifying them accordingly, or by writing their values into higher registers before function calling so that they can be easily restored.

Ex:
Code:
.text
.align 2
.thumb
.thumb_func

main:
	push {r0-r3, lr}
	
	@r0 is the address for the first pokemon in the party
	ldr r0, =(0x2024284)

	@we save r0 by setting r4 to it.
	mov r4, r0

	@call decrypter func to return species
	mov r1, #0xB
	ldr r3, =(0x803FBE8 +1)
	bl linker

	@put the return of decrypter (species ID) into r1
	mov r1, r0

	@restore first pokemon, then do whatever to that address
	@adding 0x64 is ofcourse getting the next 'Mon
	mov r0, r4
	add r0, r0, #0x64
	....
	....
	pop {r0-r3, pc}
	
linker:
	bx r3
	
.align 2
Here we utilize the fact that functions will push all registers higher or equal to r4 which they use. So if we write into r4 something which we want to save that was previously in r0, then the function (if it uses r4) will push r4 (but not r0-r3), thus saving the values in r4. I.e it will not consume what's in r4, but there's no guarantee that r0-r3 is saved.

Here's an example using the pushing method
Code:
.text
.align 2
.thumb
.thumb_func

main:
	@suppose we're hooking from a function
	@at this point, say r0 has the OTID. But we want to
	@call a function which requires r0 to be 0x5 to work
	ldr r0, =(OTID)
	push {r0}
	mov r0, #0x5
	
	@assuming r1 is not a required paramater
	ldr r1, =(0x8Function +1)
	bl linker

	@functions return values are kept in r0, if not void
	mov r1, r0
	pop {r0}

	@now r0 is back to being the OTID.	
	
linker:
	bx r1
	
.align 2
I prefer the writing to bigger sized registers method. However, it's likely, especially when you're hooking, that these registers contain data which shouldn't be overwritten. In such cases, you will need to push said registers.
Sorry as I do not really understand your meanings. TAT

First, below is what I get from your words.
I think in your reply you showed two ways of restoring data in low registers:
1. Storing it into registers higher than r3 and then restoring it through that rX because when X is higher than 3 it's always pushed if used.
2.Using push and pop command to keep the value of a register.

But you have said "but there's no guarantee that r0-r3 is saved".
In your tutorial ""Hooking" from existing routines" you use r2 to make a branch (ldr r2, =(0x8[where we plan to insert our snipplet] +1)) so that the value of r2 is changed to the pointer of the new program. My meaning is that if the modified program "0809A8BC" is called before another function which use R2 as a parameter, then why won't it cause problems?

Maybe the question is kinda silly, but I really want to know it.
  #219   Link to this post, but load the entire thread.  
Old March 25th, 2015 (7:35 AM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by jiangzhengwenjzw View Post
Sorry as I do not really understand your meanings. TAT

First, below is what I get from your words.
I think in your reply you showed two ways of restoring data in low registers:
1. Storing it into registers higher than r3 and then restoring it through that rX because when X is higher than 3 it's always pushed if used.
2.Using push and pop command to keep the value of a register.

But you have said "but there's no guarantee that r0-r3 is saved".
In your tutorial ""Hooking" from existing routines" you use r2 to make a branch (ldr r2, =(0x8[where we plan to insert our snipplet] +1)) so that the value of r2 is changed to the pointer of the new program. My meaning is that if the modified program "0809A8BC" is called before another function which use R2 as a parameter, then why won't it cause problems?

Maybe the question is kinda silly, but I really want to know it.
I see now. You're confused as to why we can use r2 as the bx register for our jump when it's not safe to use in general. Allow me to explain.

Lets first take a look at the routine at 0809A8BC.

Spoiler:

Code:
ROM:0809A8BC @ =============== S U B R O U T I N E =======================================
ROM:0809A8BC
ROM:0809A8BC
ROM:0809A8BC item_by_id:                            
ROM:0809A8BC                                         
ROM:0809A8BC                 PUSH    {LR}
ROM:0809A8BE                 LSL    R0, R0, #0x10
ROM:0809A8C0                 LSR    R0, R0, #0x10
ROM:0809A8C2                 BL      itemid_sanitize
ROM:0809A8C6                 LSL    R0, R0, #0x10
ROM:0809A8C8                 LSR    R0, R0, #0x10
ROM:0809A8CA                 MOV    R1, #sizeof(item)
ROM:0809A8CC                 MUL    R0, R1
ROM:0809A8CE                 LDR     R1, =item_undefined
ROM:0809A8D0                 ADD    R0, R0, R1
ROM:0809A8D2                 POP     {R1}


...
...
ROM:0809A8A4 itemid_sanitize:                        @ CODE XREF: item_by_id+6p
ROM:0809A8A4                                         
ROM:0809A8A4                 PUSH    {LR}
ROM:0809A8A6                 LSL    R0, R0, #0x10
ROM:0809A8A8                 LSR    R1, R0, #0x10
ROM:0809A8AA                 MOV    R0, #0x176
ROM:0809A8AE                 CMP     R1, R0
ROM:0809A8B0                 BHI     loc_809A8B6
ROM:0809A8B2                 MOV    R0, R1
ROM:0809A8B4                 B       loc_809A8B8
ROM:0809A8B6 @ ---------------------------------------------------------------------------
ROM:0809A8B6
ROM:0809A8B6 loc_809A8B6:                           
ROM:0809A8B6                 MOV    R0, #0
ROM:0809A8B8
ROM:0809A8B8 loc_809A8B8:                            
ROM:0809A8B8                 POP     {R1}
ROM:0809A8BA                 BX      R1
ROM:0809A8BA @ End of function itemid_sanitize
ROM:0809A8BA
ROM:0809A8BC

As you can see, the whole function doesn't use r2. However, this is just something that happened in this specific case. We can tell by just looking at the above routines that this function doesn't use r2 as a parameter AND that r2 isn't used for any of the calculations. However, there can be routines which don't take r2 as a parameter but use it for calculation inside the routine.

In general, if the registers aren't specifically used as parameters, you can use them to call the function. If they're not parameters, the only way for them to be used inside the routine is for calculations. For example, lets look at the other routine you were talking about.

Code:
ROM:08008DA4 gf_strcat:                              
ROM:08008DA4                                         
ROM:08008DA4                 PUSH    {LR}
ROM:08008DA6                 MOV    R2, R0
ROM:08008DA8                 B       loc_8008DAC
ROM:08008DAA @ ---------------------------------------------------------------------------
ROM:08008DAA
ROM:08008DAA loc_8008DAA:                            
ROM:08008DAA                 ADD    R2, #1
ROM:08008DAC
ROM:08008DAC loc_8008DAC:                           
ROM:08008DAC                 LDRB    R0, [R2]
ROM:08008DAE                 CMP     R0, #0xFF
ROM:08008DB0                 BNE     loc_8008DAA
ROM:08008DB2                 MOV    R0, R2          @ dst
ROM:08008DB4                 BL      strcpy_xFF_terminated
ROM:08008DB8                 POP     {R1}
ROM:08008DBA                 BX      R1
Clearly here, r2 cannot be a Parameter because it's overwritten by r0 in the first OP code after the push statement. In fact, if r2 or r1 isn't a parameter, but it used in calculations, the routine must first make measures to "clean" or set them. This is because the function doesn't know from where it may be getting called from. In this case r2 is overwritten with r0, so the old value of r2 is irrelevant to the function. Notice that because r2 is overwritten, the function which calls this one had it's old value of r2 changed. This is what I mean by "we cannot guarantee registers r0-r3 aren't overwritten".

To take away from this, basically if a register isn't used specifically as a parameter for the function, and is a low register, then it's safe to use as a caller register.
__________________
...
  #220   Link to this post, but load the entire thread.  
Old March 25th, 2015 (7:37 AM).
Chaotix Chaotix is offline
Love to test
 
Join Date: Feb 2007
Nature: Adamant
Posts: 59
Quote:
Originally Posted by Mystery Man View Post
It might be the set trainer level specials now that I remember correctly. I would try reverting the bytes that the set trainer level special hack changes to those of an unhacked Firered, as it interferes with the EV hack. Here is what fixed it for me: go to 0x011624. The bytes there should be "00 48 00 47 ?? ?? ?? 08". Overwrite that with Firered's original coding, which is: "20 1C 33 1C 2C F0 14 FA". It should work now (that, or there might be another thing I forgot.)

Yes, it is only two bytes. In ASM code, this is all that is being done:
Spoiler:

Code:
.org 0x3dc70
b 0x3dcd0
Thanks for the help, I really appreciate it.

Changing the bytes you listed have seemingly allowed it to work; at least the pokeball they use to send out pokemon has changed so I know that much is working.

I wasn't intending on using JPAN's trainer level hack for what I'm currently working on anyway, so that is fine.
  #221   Link to this post, but load the entire thread.  
Old March 25th, 2015 (7:57 AM).
jiangzhengwenjzw's Avatar
jiangzhengwenjzw jiangzhengwenjzw is offline
now working on katam
 
Join Date: Sep 2012
Gender: Male
Posts: 175
Quote:
Originally Posted by FBI agent View Post
I see now. You're confused as to why we can use r2 as the bx register for our jump when it's not safe to use in general. Allow me to explain.

Lets first take a look at the routine at 0809A8BC.

Spoiler:

Code:
ROM:0809A8BC @ =============== S U B R O U T I N E =======================================
ROM:0809A8BC
ROM:0809A8BC
ROM:0809A8BC item_by_id:                            
ROM:0809A8BC                                         
ROM:0809A8BC                 PUSH    {LR}
ROM:0809A8BE                 LSL    R0, R0, #0x10
ROM:0809A8C0                 LSR    R0, R0, #0x10
ROM:0809A8C2                 BL      itemid_sanitize
ROM:0809A8C6                 LSL    R0, R0, #0x10
ROM:0809A8C8                 LSR    R0, R0, #0x10
ROM:0809A8CA                 MOV    R1, #sizeof(item)
ROM:0809A8CC                 MUL    R0, R1
ROM:0809A8CE                 LDR     R1, =item_undefined
ROM:0809A8D0                 ADD    R0, R0, R1
ROM:0809A8D2                 POP     {R1}


...
...
ROM:0809A8A4 itemid_sanitize:                        @ CODE XREF: item_by_id+6p
ROM:0809A8A4                                         
ROM:0809A8A4                 PUSH    {LR}
ROM:0809A8A6                 LSL    R0, R0, #0x10
ROM:0809A8A8                 LSR    R1, R0, #0x10
ROM:0809A8AA                 MOV    R0, #0x176
ROM:0809A8AE                 CMP     R1, R0
ROM:0809A8B0                 BHI     loc_809A8B6
ROM:0809A8B2                 MOV    R0, R1
ROM:0809A8B4                 B       loc_809A8B8
ROM:0809A8B6 @ ---------------------------------------------------------------------------
ROM:0809A8B6
ROM:0809A8B6 loc_809A8B6:                           
ROM:0809A8B6                 MOV    R0, #0
ROM:0809A8B8
ROM:0809A8B8 loc_809A8B8:                            
ROM:0809A8B8                 POP     {R1}
ROM:0809A8BA                 BX      R1
ROM:0809A8BA @ End of function itemid_sanitize
ROM:0809A8BA
ROM:0809A8BC

As you can see, the whole function doesn't use r2. However, this is just something that happened in this specific case. We can tell by just looking at the above routines that this function doesn't use r2 as a parameter AND that r2 isn't used for any of the calculations. However, there can be routines which don't take r2 as a parameter but use it for calculation inside the routine.

In general, if the registers aren't specifically used as parameters, you can use them to call the function. If they're not parameters, the only way for them to be used inside the routine is for calculations. For example, lets look at the other routine you were talking about.

Code:
ROM:08008DA4 gf_strcat:                              
ROM:08008DA4                                         
ROM:08008DA4                 PUSH    {LR}
ROM:08008DA6                 MOV    R2, R0
ROM:08008DA8                 B       loc_8008DAC
ROM:08008DAA @ ---------------------------------------------------------------------------
ROM:08008DAA
ROM:08008DAA loc_8008DAA:                            
ROM:08008DAA                 ADD    R2, #1
ROM:08008DAC
ROM:08008DAC loc_8008DAC:                           
ROM:08008DAC                 LDRB    R0, [R2]
ROM:08008DAE                 CMP     R0, #0xFF
ROM:08008DB0                 BNE     loc_8008DAA
ROM:08008DB2                 MOV    R0, R2          @ dst
ROM:08008DB4                 BL      strcpy_xFF_terminated
ROM:08008DB8                 POP     {R1}
ROM:08008DBA                 BX      R1
Clearly here, r2 cannot be a Parameter because it's overwritten by r0 in the first OP code after the push statement. In fact, if r2 or r1 isn't a parameter, but it used in calculations, the routine must first make measures to "clean" or set them. This is because the function doesn't know from where it may be getting called from. In this case r2 is overwritten with r0, so the old value of r2 is irrelevant to the function. Notice that because r2 is overwritten, the function which calls this one had it's old value of r2 changed. This is what I mean by "we cannot guarantee registers r0-r3 aren't overwritten".

To take away from this, basically if a register isn't used specifically as a parameter for the function, and is a low register, then it's safe to use as a caller register.
I got what you meant in the above reply now, but I think there's still a specific case which cause problem. (Not the case in the tutorial as the tutorial do not cause such problem) To show it more clearly, I will make an example:

Firstly, the routine at 0809A8BC was called (which is already modified) so that r2 was changed.

Then an unknown routine is called, which use R2 as a parameter.

For pseudo code:

.......(instructions, which turns r2 into 0x1 for example)
bl 0809A8BC(r2 is changed into a pointer as the routine is modified)
bl 08XXXXXX(take r2 as a parameter to output something)
.......(Not related codes)

As you can see, I think it may cause problem... I think what you said is the case when the function at 08XXXXXX doesn't take r2 as a parameter, as in the tutorial. Or did I ignore something in your words? Thank you very much.
  #222   Link to this post, but load the entire thread.  
Old March 25th, 2015 (8:25 AM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by jiangzhengwenjzw View Post
I got what you meant in the above reply now, but I think there's still a specific case which cause problem. (Not the case in the tutorial as the tutorial do not cause such problem) To show it more clearly, I will make an example:

Firstly, the routine at 0809A8BC was called (which is already modified) so that r2 was changed.

Then an unknown routine is called, which use R2 as a parameter.

For pseudo code:

.......(instructions, which turns r2 into 0x1 for example)
bl 0809A8BC(r2 is changed into a pointer as the routine is modified)
bl 08XXXXXX(take r2 as a parameter to output something)
.......(Not related codes)

As you can see, I think it may cause problem... I think what you said is the case when the function at 08XXXXXX doesn't take r2 as a parameter, as in the tutorial. Or did I ignore something in your words? Thank you very much.
In this case the routine would need to set the paramaters again before the second "bl", or the first routine would have to restore said parameter (which it probably won't).

Remember that functions are expected to modify or use registers r0-r3. So if one function is called, then we need to assume r0-r3 holds some sort of return value OR the values are messed up. So the second function, by definition, mustn't have any parameters at all, OR the parameters for it are the return value from the first function. For example, picture this:

bl getPokemonName @maybe sets r0 to a RAM offset with the Pokemon's name
bl checkIfMagikarp @maybe checks if r0's RAM location says Magikarp

(or the parameters are stored via SP, which is a little more complicated and I will probably explain in my next tutorial or something, just forget I said this bracketed comment for now :P ).
__________________
...
  #223   Link to this post, but load the entire thread.  
Old March 25th, 2015 (4:52 PM).
jiangzhengwenjzw's Avatar
jiangzhengwenjzw jiangzhengwenjzw is offline
now working on katam
 
Join Date: Sep 2012
Gender: Male
Posts: 175
Quote:
Originally Posted by FBI agent View Post
In this case the routine would need to set the paramaters again before the second "bl", or the first routine would have to restore said parameter (which it probably won't).

Remember that functions are expected to modify or use registers r0-r3. So if one function is called, then we need to assume r0-r3 holds some sort of return value OR the values are messed up. So the second function, by definition, mustn't have any parameters at all, OR the parameters for it are the return value from the first function. For example, picture this:

bl getPokemonName @maybe sets r0 to a RAM offset with the Pokemon's name
bl checkIfMagikarp @maybe checks if r0's RAM location says Magikarp

(or the parameters are stored via SP, which is a little more complicated and I will probably explain in my next tutorial or something, just forget I said this bracketed comment for now :P ).
Okay, I think this time I know your meaning! Thank you very much for your replies!

But I've found another problem:
The function runs well when use "bufferitem" command in script, but in the bag it is messed up with the next line. After some debugging, I've found that the problem is caused because the string of the text of the next item (or "cancel") overwrite the RAM offset where the 15th,16th... character of the first item are stored.
  #224   Link to this post, but load the entire thread.  
Old March 25th, 2015 (6:47 PM).
Blah's Avatar
Blah Blah is offline
Free supporter
 
Join Date: Jan 2013
Location: Unknown Island
Gender: Male
Posts: 1,924
Quote:
Originally Posted by jiangzhengwenjzw View Post
Okay, I think this time I know your meaning! Thank you very much for your replies!

But I've found another problem:
The function runs well when use "bufferitem" command in script, but in the bag it is messed up with the next line. After some debugging, I've found that the problem is caused because the string of the text of the next item (or "cancel") overwrite the RAM offset where the 15th,16th... character of the first item are stored.
Do you have the RAM offsets for these? It could be either an insufficient malloc or possibly the buffer is too small. Dependently the fix is a little different for each time. It's also important to note, that after a few char expansions that the graphical space for the name will overflow.
__________________
...
  #225   Link to this post, but load the entire thread.  
Old March 25th, 2015 (8:39 PM).
jiangzhengwenjzw's Avatar
jiangzhengwenjzw jiangzhengwenjzw is offline
now working on katam
 
Join Date: Sep 2012
Gender: Male
Posts: 175
Quote:
Originally Posted by FBI agent View Post
Do you have the RAM offsets for these? It could be either an insufficient malloc or possibly the buffer is too small. Dependently the fix is a little different for each time. It's also important to note, that after a few char expansions that the graphical space for the name will overflow.
It seems that the function at "08008D84" is always called to transfer the string data of item in the ROM to a RAM offset.
Therefore, the RAM offset of the first item should be at "020041F1". You will see that firstly the string of the expanded is written correctly to that offset, but after some time the offset after the 14th byte of the string is overwritten by the next item string (or cancel). If you create a breakpoint on write to this offset, you will find the function at "08008D84" is called again.

This is a screenshot of this. (I modified "burn heal" into "THEITEMNAMEISNEW")
Closed Thread

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

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 9:23 AM.