Branch Compiling Error

Started by Bully@Wiiplaza, October 18, 2012, 01:18:10 PM

Previous topic - Next topic

Bully@Wiiplaza

In the disassembly, branches indicate directly to which address they could/would jump by showing the 8-digited address. In ASMWiiRd or PyiiASMH we have to type the offset between those addresses instead of the destination address. It therefore doesn´t allow the branch instructions to be copied over from the disassembly.

Why is it this way?
My Wii hacking site...
http://bullywiihacks.com/

My youtube account with a lot of hacking videos...
http://www.youtube.com/user/BullyWiiPlaza

~Bully

megazig

because the branch isn't really a jump to an address. it's a jump to an offset relative to the current instruction.
disassemblers cheat for you and show the address instead of showing the offset just to be nice. anything where you don't have a defined address for an instruction either needs an offset for the branch or you have to use another technique like mtctr or setting lr and blr.

Bully@Wiiplaza

Thanks. It´s basically just a disassembly feature to have it more convient for viewing, that´s it.
My Wii hacking site...
http://bullywiihacks.com/

My youtube account with a lot of hacking videos...
http://www.youtube.com/user/BullyWiiPlaza

~Bully

dcx2

In this thread over here, I showed that when porting ASM hacks, you can include branches with addresses.

[spoiler=NTSC]800B82F8:  D01D0068   stfs   f0,104(r29)
800B82FC:  48000018   b   0x800b8314
800B8300:  C042BD9C   lfs   f2,-16996(r2)
800B8304:  C03E0000   lfs   f1,0(r30)
800B8308:  C01D0068   lfs   f0,104(r29)
800B830C:  EC02007C   fnmsubs   f0,f2,f1,f0
800B8310:  D01D0068   stfs   f0,104(r29)
800B8314:  881D0058   lbz   r0,88(r29)
800B8318:  2C000000   cmpwi   r0,0
800B831C:  41820024   beq-   0x800b8340
800B8320:  C03D0050   lfs   f1,80(r29)
800B8324:  C002BD88   lfs   f0,-17016(r2)
800B8328:  FC010040   fcmpo   cr0,f1,f0
800B832C:  4081007C   ble-   0x800b83a8[/spoiler]

[spoiler=PAL]8017DDB8:  D01D0068   stfs   f0,104(r29)
8017DDBC:  48000018   b   0x8017ddd4
8017DDC0:  C042FE44   lfs   f2,-444(r2)
8017DDC4:  C03E0000   lfs   f1,0(r30)
8017DDC8:  C01D0068   lfs   f0,104(r29)
8017DDCC:  EC02007C   fnmsubs   f0,f2,f1,f0
8017DDD0:  D01D0068   stfs   f0,104(r29)
8017DDD4:  881D0058   lbz   r0,88(r29)
8017DDD8:  2C000000   cmpwi   r0,0
8017DDDC:  41820024   beq-   0x8017de00
8017DDE0:  C03D0050   lfs   f1,80(r29)
8017DDE4:  C002FE30   lfs   f0,-464(r2)
8017DDE8:  FC010040   fcmpo   cr0,f1,f0
8017DDEC:  4081007C   ble-   0x8017de68
[/spoiler]

Things to note: everything is identical except for a few places that are offset of r2 (in red).  r2 and r13 are both dangerous for this reason, so do not include them in a signature analysis.

Note the underlined branch is the same exact hex value in both versions - 0x41820024 - even though the actual destination address is different (NTSC: 0x800b8340 PAL: 0x8017de00).  See how the lower half-word of the instruction's hex is 0x24?  They are both branching over 0x24 bytes from the current address.

Bully@Wiiplaza

Yes, the branches may refer to a different address, but the offset is the same. Therefore the value aswell. I´m wondering how to properly detect instructions that you marked in red (the "dangerous" ones). Is it because of r2 being dangerous all the time or something? Is there any other register to beware of other than r13? In most cases instructions will have the same offset even if it´s large. I can´t quite find a general rule...
My Wii hacking site...
http://bullywiihacks.com/

My youtube account with a lot of hacking videos...
http://www.youtube.com/user/BullyWiiPlaza

~Bully

dcx2

Off topic but...

Yes, r2 and r13 are always dangerous for porting.  r2 is the read-only anchor.  It typically holds constants, like the magic float needed for int -> float conversions.  r13 would be used for global variables that can be written to, like some sort of global flag.  I tend to see r2 more than r13.

The reason these are dangerous is because the compiler is free to rearrange the order of the data pointed at by the anchors.  The compiler might choose one offset for PAL, but then the phase of the moon changes or some other random nonsense when NTSC is compiled so the compiler chooses a different offset for NTSC.

"Local" branches don't have this problem, there's usually the same number of instructions between the branch itself and its destination (although this is not always true, sometimes PAL/JPN is different because of Unicode and stuff).

bl, however, is almost always dangerous.  bl jumps from one function to another, and the compiler is free to use the phase of the moon to determine where to place these functions.

The last thing to watch out for are when the game lis/ori's on its own.  For example, Tales of Symphonia has a rather large table that lists all the experience needed for each level.  This table would take up too much space in the anchor areas, so the game doesn't use r2 or r13.  Rather, it literally lis/ori's the address of the table, just like we lis/ori our addresses.  These static addresses also depend on the phase of the moon during compilation, so they will differ between regions.  The lis and ori themselves may be separated by one or more instructions as well.