Wait, you're trying to test Psystrike's battle effect in the OW with a signpost script? Really?
This should be put in a battlescript which is then attached to an attack. Then used in a battle. Wow.
I know, it is to test the swap. It will work in a script and in a battle script, no ?
So it is "callasm 0xOffset +1", thank you.
You don't seem to understand..
It's a code for a move. There is no battle scene on the overworld. You can't just "callasm 0xmovescript" and make psystrike happen on the overworld. It doesn't make sense lol
I've moved this entire discussion to the ASM & Disassembly Help Thread because it is in no way an ASM Resource. :D
Actually, I don't understand how to insert a script in a battlescript.
Yes of course, i know how to create a battlescript.Do you have battle script pro?
You can use that to compile battle scripts.
I would like to know, if it's possible, the offset of two routines :
- First, the one which creates an OW on the map when we come on this map ;
- And also, the one which check if there is an OW next to the player before walking.
Can someone help me ? Thanks ^^
.text
.align 2
.thumb
.thumb_func
.global swap
main:
push {r0-r3, lr}
ldr r0, .CDEFA1
ldrb r1, [r0]
ldr r2, .CSPEDEFA1
ldrb r3, [r2]
strb r1, [r2]
strb r3, [r0]
ldr r0, .CDEFA2
ldrb r1, [r0]
ldr r2, .CSPEDEFA2
ldrb r3, [r2]
strb r1, [r2]
strb r3, [r0]
ldr r0, .CDEFE1
ldrb r1, [r0]
ldr r2, .CSPEDEFE1
ldrb r3, [r2]
strb r1, [r2]
strb r3, [r0]
ldr r0, .CDEFE2
ldrb r1, [r0]
ldr r2, .CSPEDEFE2
ldrb r3, [r2]
strb r1, [r2]
strb r3, [r0]
pop {r0-r3, pc}
.align 2
.CDEFA1:
.word 0x0202409E
.CSPEDEFA1:
.word 0x020240A1
.CDEFA2:
.word 0x202414E
.CSPEDEFA2:
.word 0x02024151
.CDEFE1:
.word 0x020240F6
.CSPEDEFE1:
.word 0x020240F9
.CDEFE2:
.word 0x020241A6
.CSPEDEFE2:
.word 0x020241A9
.text
.align 2
.thumb
.thumb_func
.global swap
main:
push {r0-r3, lr}
ldr r0, .DEFA1
ldrh r1, [r0]
ldr r2, .SPEDEFA1
ldrh r3, [r2]
strh r1, [r2]
strh r3, [r0]
ldr r0, .DEFA2
ldrh r1, [r0]
ldr r2, .SPEDEFA2
ldrh r3, [r2]
strh r1, [r2]
strh r3, [r0]
ldr r0, .DEFE1
ldrh r1, [r0]
ldr r2, .SPEDEFE1
ldrh r3, [r2]
strh r1, [r2]
strh r3, [r0]
ldr r0, .DEFE2
ldrh r1, [r0]
ldr r2, .SPEDEFE2
ldrh r3, [r2]
strh r1, [r2]
strh r3, [r0]
pop {r0-r3, pc}
.align 2
.DEFA1:
.word 0x02024548
.SPEDEFA1:
.word 0x0202454E
.DEFA2:
.word 0x020245AC
.SPEDEFA2:
.word 0x020245B2
.DEFE1:
.word 0x020247A0
.SPEDEFE1:
.word 0x020247A6
.DEFE2:
.word 0x02024804
.SPEDEFE2:
.word 0x0202480A
Hello,
I don't understand why this doesn't work :
Spoiler:
Code:.text .align 2 .thumb .thumb_func .global swap main: push {r0-r3, lr} ldr r0, .CDEFA1 ldrb r1, [r0] ldr r2, .CSPEDEFA1 ldrb r3, [r2] strb r1, [r2] strb r3, [r0] ldr r0, .CDEFA2 ldrb r1, [r0] ldr r2, .CSPEDEFA2 ldrb r3, [r2] strb r1, [r2] strb r3, [r0] ldr r0, .CDEFE1 ldrb r1, [r0] ldr r2, .CSPEDEFE1 ldrb r3, [r2] strb r1, [r2] strb r3, [r0] ldr r0, .CDEFE2 ldrb r1, [r0] ldr r2, .CSPEDEFE2 ldrb r3, [r2] strb r1, [r2] strb r3, [r0] pop {r0-r3, pc} .align 2 .CDEFA1: .word 0x0202409E .CSPEDEFA1: .word 0x020240A1 .CDEFA2: .word 0x202414E .CSPEDEFA2: .word 0x02024151 .CDEFE1: .word 0x020240F6 .CSPEDEFE1: .word 0x020240F9 .CDEFE2: .word 0x020241A6 .CSPEDEFE2: .word 0x020241A9
Whereas this works :
Spoiler:
Code:.text .align 2 .thumb .thumb_func .global swap main: push {r0-r3, lr} ldr r0, .DEFA1 ldrh r1, [r0] ldr r2, .SPEDEFA1 ldrh r3, [r2] strh r1, [r2] strh r3, [r0] ldr r0, .DEFA2 ldrh r1, [r0] ldr r2, .SPEDEFA2 ldrh r3, [r2] strh r1, [r2] strh r3, [r0] ldr r0, .DEFE1 ldrh r1, [r0] ldr r2, .SPEDEFE1 ldrh r3, [r2] strh r1, [r2] strh r3, [r0] ldr r0, .DEFE2 ldrh r1, [r0] ldr r2, .SPEDEFE2 ldrh r3, [r2] strh r1, [r2] strh r3, [r0] pop {r0-r3, pc} .align 2 .DEFA1: .word 0x02024548 .SPEDEFA1: .word 0x0202454E .DEFA2: .word 0x020245AC .SPEDEFA2: .word 0x020245B2 .DEFE1: .word 0x020247A0 .SPEDEFE1: .word 0x020247A6 .DEFE2: .word 0x02024804 .SPEDEFE2: .word 0x0202480A
With the first routine I want to switch some bytes and with the second i switch some "double bytes".
Hi, it looks like it would do the same. I don't know which base you're using, but the offsets of the symbols from routine #1 don't match the offsets of the symbols in routine #2. Other than that, swapping a byte instead of a half word shouldn't be a problem (actually the halfword one has more limitations than the byte swapping, but that's besides the point).
Hi, unfortunately I don't know where the overworld is created. Though I do know that there's a collision check which occurs when the player tries to use surf or waterfall.
This sub routine is at 0x805C8B0. More specifically, the check to see if an NPC is blocking the way is done at 0x80636AC, it's used for stuff like ledge hopping and stuff too.
[U][B]Value of r0[/B][/U] | [U][B]Obstacle[/B][/U]
0 | Nothing
2 | Solid block (buildings, trees...)
3 | Walking : water / Surfing : ground
4 | NPC
Thanks a lot ;)
I found something : the result given by the routine at 0x80636AC is stored in r0.
Code:[U][B]Value of r0[/B][/U] | [U][B]Obstacle[/B][/U] 0 | Nothing 2 | Solid block (buildings, trees...) 3 | Walking : water / Surfing : ground 4 | NPC
NOOB HERE! o/
If this (from Shiny Quagsire's tutorial) saves a byte to a variable...
Spoiler:.align 2
.thumb
main:
push {r0-r1,lr}
ldr r0, pokemon_data
ldrb r0, [r0]
lsl r0, #0x5
lsr r0, #0x5
ldr r1, var
strh r0, [r1]
pop {r0-r1,pc}
.align 2
pokemon_data:
.word 0x02024284 + 0x50
var:
.word 0x020270B6 + (0x800D * 2)
Then would switching "ldr r0, pokemon_data" to "ldr r0, var" (ldr r1, var too) then store whatever the value of 0x800D in the data? Or is life not that simple : <.
push {r0-r1, lr}
mov r0, #0xValue
ldr r1, .var
strh r0, [r1]
pop {r0-r1, pc}
You'll notice that he saves the value in r0 into the address in r1 (the variable).
So all you need to do is this:
push {r0-r1, lr}
mov r0, #0xValue @changes r0 to 0xValue?
ldr r1, .var @loads variable value to r1
strh r0, [r1] @stores r0's value to the var
pop {r0-r1, pc}
.align 2
.thumb
main:
push {r0-r1,lr}
ldrb r0, move_data ----> 8250cb8 is [I]cut[/I]'s data. Just because. +0x1 as it's the second byte that decides the power?
ldrb r0, [r0]
add r0, #0x5 ----> Addings 0x5 to previous power
ldr r1, var ----> Load 0x800D
strh r0, [r1] ----> Put new power in 0x800D (to see if anything has happened).
pop {r0-r1,pc}
.align 2
move_data:
.word 0x08250CB8 + 0x1
var:
.word 0x020270B6 + (0x800D * 2)
Code:push {r0-r1, lr} mov r0, #0xValue @changes r0 to 0xValue? ldr r1, .var @loads variable value to r1 strh r0, [r1] @stores r0's value to the var pop {r0-r1, pc}
All this lingo still confuses me XD.
Sorry I'm not sure what you mean :<. Your code doesn't have any locations other than the var, so how can it set a byte to the value of the var? It might have just been I wasn't clear in my last post >< haha.
Also in regards to your tutorial (and our VMs) how do you know when you need to 'hook' and things?
Latest attempt of a routine.Think I must have oversimplified something? I get nothing ><. It runs but obviously not doing what I'd like it to XD. Vague comments about what I think ought to be happenin on the side :').
Spoiler:Code:.align 2 .thumb main: push {r0-r1,lr} ldrb r0, move_data ----> 8250cb8 is [I]cut[/I]'s data. Just because. +0x1 as it's the second byte that decides the power? ldrb r0, [r0] add r0, #0x5 ----> Addings 0x5 to previous power ldr r1, var ----> Load 0x800D strh r0, [r1] ----> Put new power in 0x800D (to see if anything has happened). pop {r0-r1,pc} .align 2 move_data: .word 0x08250CB8 + 0x1 var: .word 0x020270B6 + (0x800D * 2)
It now tells me 55 - which is correct! :o 50+5 power. How can I then extend this routine to replace the 50 (0x32) in the ROM with 55 (0x37)?
IM SO SORRY FOR ALL THE NOTIFICATIONS ;-; /thousanth edit
OK, so when you do "ldr r0, move_data" you don't load it as a byte. move_data is a symbol which represents a pointer (in this case 0x8250CB8 + 1). We want a byte at that pointer so we do:
ldr r0, move_data @load the actual pointer
ldrb r0, [r0] @load a byte from the value of the pointer
If you did ldrb r0, move_data, it would just take move_data as a hex value and load the first byte of it, rather than the first byte of the value it's pointing to (power).
The rest of this is right. Also you seem to be confusing yourself with the names on the bottom. They're just definitions. It's the same thing to do ldr r0, move_data as it is to do ldr r0, =(0x8250CB8 +1).
Addressing your questions about what I've said last time, 0xValue is just a name I came up with. It's supposed to be some arbitrary, valid, constant. Replace it with 0xA or 0x50 or whatever your favorite hex value is.
mov r0, #0x50 @Sets r0 to be 0x50
ldr r1, =(0x20370D0) @loads address of Lastresult into r1. I.e pointer to the value in 0x800D (last result)
strh r0, [r1] @stores 2 bytes of whatever is in r0 into the address/location specified by r1. In this case stores 0x50 in the last result
I hope you see what we're doing with the pointers/symbols/storing now. With that out of the way I can address hooking.
Spoiler:I'm going to explain assuming you already know what a hook is. You basically know that a hook is required when you're reworking or adding additional features to existing game code. In this case you're changing the damage of a move's power based on badges. Thus you're added a feature to existing game code. If you were to just paste your code over the existing code at that region, then obviously you would be overwriting some other important code. This is why we place a hook.
Sometimes it's possible that the game code lends itself to be easily reworked and thus you just overwrite some existing bytes to do that (an example would be my "catch trainer's pokemon" thing). In these cases you don't need hooks (though it's kind of rare in comparison).
I should warn you, to hook successfully into some routines are harder than others. You need to analyze the code at said routine and note to yourself which registers are free, which registers contain information you need after you hook and of course which register you will use for the hook. In complex functions you often don't have a lot of resources, so you need to draw conclusions based on what the analyzed code is like.
Worst case scenario is usually that there's no registers you can use for the hook at the place you want to hook from. If that's the case you just hook early enough to a point where there are registers available and just derive their values and do your code from where you wanted to hook. OK, that last part doesn't make sense unless you've experienced what I'm talking about :P
This last paragraph isn't that important anyways, just me rambling, lol.