Hey guys,
I was wondering if it´s possible to spy out enemys data using a breakpoint in the game!
I´ll take PBR as an example:
Let´s set a breakpoint on the health adress, if an enemy gets hit, r0 shows the enemys remaining HP (hit points).
Normally, you only see the HP bar for enemys, but you can only see the exact amount of HP on your own Pokemon.
Luckily, I found an adress, which can rewrite the display HP of your Pokemon, so I can load the enemys HP there and can see it on my screen ;D
My ASM code should take the value from r0 (ONLY if an enemy got hit! I already found the player counter register, it´s r5)
and write it to adress 80xxxxxx as it´s value. If I need to get the breakpoint which can write to this specific adress instead of a RAM write, let me know!
Breakpoint Write on Health (This breakpoint was taken from the player, if it´s an enemy, r5 shows 0000001)
[spoiler]CR:44000000 XER:00000000 CTR:803CB5B4 DSIS:00000000
DAR:00000000 SRR0:803CB64C SRR1:0000B032 LR:803CB5F4
r0:00000148 r1:80F650E8 r2:80648600 r3:0000014C
r4:92481660 r5:00000000 r6:FFFFFFFC r7:FFFFFFFC
r8:00000000 r9:00000004 r10:00000004 r11:80F650E8
r12:803CB5B4 r13:806452C0 r14:00000008 r15:00000002
r16:00000000 r17:00000004 r18:00000000 r19:00000004
r20:0000F100 r21:00000010 r22:00000003 r23:00010000
r24:918E83A0 r25:00000000 r26:8048CDB4 r27:9247F240
r28:00000004 r29:918E83B4 r30:9247F240 r31:92481660
f0:00000000 f1:3F000000 f2:00000000 f3:00000000
f4:00000000 f5:00000000 f6:00000000 f7:00000000
f8:00000000 f9:00000000 f10:00000000 f11:3F800000
f12:00000000 f13:00000000 f14:00000000 f15:00000000
f16:00000000 f17:00000000 f18:00000000 f19:00000000
f20:00000000 f21:00000000 f22:00000000 f23:00000000
f24:00000000 f25:00000000 f26:00000000 f27:00000000
f28:00000000 f29:00000000 f30:00000000 f31:00000000
803CB5B4: 9421FFF0 stwu r1,-16(r1)
803CB5B8: 7C0802A6 mflr r0
803CB5BC: 90010014 stw r0,20(r1)
803CB5C0: 93E1000C stw r31,12(r1)
803CB5C4: 7C9F2378 mr r31,r4
803CB5C8: 93C10008 stw r30,8(r1)
803CB5CC: 7C7E1B78 mr r30,r3
803CB5D0: 7FE3FB78 mr r3,r31
803CB5D4: 80A400B4 lwz r5,180(r4)
803CB5D8: 38050001 addi r0,r5,1
803CB5DC: 900400B4 stw r0,180(r4)
803CB5E0: 4800B88D bl 0x803d6e6c
803CB5E4: 7C651B78 mr r5,r3
803CB5E8: 7FC3F378 mr r3,r30
803CB5EC: 7FE4FB78 mr r4,r31
803CB5F0: 4800CA4D bl 0x803d803c
803CB5F4: 1D0300C0 mulli r8,r3,192
803CB5F8: 80FF215C lwz r7,8540(r31)
803CB5FC: 7C651B78 mr r5,r3
803CB600: 7C9F4214 add r4,r31,r8
803CB604: 80C42D8C lwz r6,11660(r4)
803CB608: 7C073215 add. r0,r7,r6
803CB60C: 41810010 bgt- 0x803cb61c
803CB610: 7C0600D0 neg r0,r6
803CB614: 901F2148 stw r0,8520(r31)
803CB618: 48000008 b 0x803cb620
803CB61C: 90FF2148 stw r7,8520(r31)
803CB620: 80DF2148 lwz r6,8520(r31)
803CB624: 2C060000 cmpwi r6,0
803CB628: 40800018 bge- 0x803cb640
803CB62C: 5460103A rlwinm r0,r3,2,0,29
803CB630: 7C7F0214 add r3,r31,r0
803CB634: 80030164 lwz r0,356(r3)
803CB638: 7C060050 sub r0,r0,r6
803CB63C: 90030164 stw r0,356(r3)
803CB640: 80642D8C lwz r3,11660(r4)
803CB644: 801F215C lwz r0,8540(r31)
803CB648: 7C030215 add. r0,r3,r0
803CB64C: 90042D8C stw r0,11660(r4) --> was going to be executed
803CB650: 40800010 bge- 0x803cb660
803CB654: 38000000 li r0,0
803CB658: 90042D8C stw r0,11660(r4)
803CB65C: 48000018 b 0x803cb674
803CB660: 7C7F4214 add r3,r31,r8
803CB664: 80632D90 lwz r3,11664(r3)
803CB668: 7C001840 cmplw r0,r3
803CB66C: 40810008 ble- 0x803cb674
803CB670: 90642D8C stw r3,11660(r4)
803CB674: 7FC3F378 mr r3,r30
803CB678: 7FE4FB78 mr r4,r31
803CB67C: 4BFF1CF9 bl 0x803bd374
803CB680: 83E1000C lwz r31,12(r1)
803CB684: 38600000 li r3,0
803CB688: 83C10008 lwz r30,8(r1)
803CB68C: 80010014 lwz r0,20(r1)
803CB690: 7C0803A6 mtlr r0
803CB694: 38210010 addi r1,r1,16
803CB698: 4E800020 blr
[/spoiler]
Adress, which let´s you edit your own display HP amount (doesn´t affect them at all):
02478554 0000XXXX
8)
First, what kind of breakpoint is this? I assume that it is "write." If that's the case, it should only break when the enemy is hit, so I think it should just be as easy as this:
Hook: 803CB64C
lis r16,0x8000
stw r0,0x1500(r16)
stw r0,11660(r4)
lis r16,0x0000
nop
---------------------
-That stores enemy HP to 80001500. Is that what you wanted? I'm kind of confused about where you want the HP value stored...
Nutmeg; you shouldn't assume 0 = safe. It does not. The value in r16 could change; it's part of the non-volatile registers, so you shouldn't mess with it. The short answer is to use r12 for anything that you ever want to do. The long answer is here (http://wiird.l0nk.org/forum/index.php/topic,6555.0.html)
Also, because Data Access Register DAR = 0, this must be from an execute breakpoint.
---
Bully; do you see the . after add.? That means it sets the Condition Register CR. Specifically, you get a free "cmpwi rD, 0". CR is used to determine whether or not conditional branches (like the bge after your hook line) will be taken or not. If you do some cmpwi to make sure you only target enemies, you will screw up the CR and the bge will do funny things.
To fix this problem, put the cmpwi r0,0 at the end of your ASM. This makes sure the CR holds the right value before the branch back to game code.
---
EDIT:
Here's an example of the window where the CR is not safe (in red). You either need to push/pop CR, or reproduce the comparison that is supposed to be there.
803CB640: 80642D8C lwz r3,11660(r4)
803CB644: 801F215C lwz r0,8540(r31)
803CB648: 7C030215 add. r0,r3,r0
803CB64C: 90042D8C stw r0,11660(r4) --> was going to be executed
803CB650: 40800010 bge- 0x803cb660
803CB654: 38000000 li r0,0
803CB658: 90042D8C stw r0,11660(r4)
Shouldn't it should be safe to use r16 because of the way I load 0000 back to the register?
Wait... When the breakpoint hits, the value might not always be 0? Uhg, I'm confused...
It's difficult to explain exactly. The link I provided in my previous post ("the long answer is here") goes into great detail.
The short version is that just because r16 is 0 now doesn't mean it will be 0 later. In particular, registers above r13 are bad to touch unless you push/pop them on/off the stack. r12 is always safe, even though it will never be 0.
but I still don´t know, how it´s possible to store the value of r0 (if an enemy got hit)
to a specific adress as value :-[
You said that if I use a cmpwi, the bge will do funny things...
You need a cmpwi r5 to make sure you are only affecting enemies, right? The problem is that this cmpwi r5 will adversely affect the CR. However, you can reproduce the correct CR by doing a cmpwi that sets the CR exactly like the add. operation. The . at the end of any instruction means that it sets the CR by cmpwi rD, 0.