I´ve noticed that some game had a weird way of storing statistics: Little Endian!
e.g. 1000 isn´t represented like this -> 000003E8
but like this -> E80300000
http://en.wikipedia.org/wiki/Endianness
I can set a BP write on it to figure who´s updating that amount.
Is there some expected assembly way of converting little endian to big endian or even a direct way of adding/subing to/from it? Would be amazing to know.
I´m basically interested in hacking the amount of points that are gained. I can´t quite do it the "usual" way (+ xxxx etc.), obviously (since it completely messes with the amount instead).
Very weird. The PPC can be "switched" into little endian mode with a bit in the Machine State Register (MSR), so it's possible the game is actually running the CPU in little endian mode.
Some part of the game has to be adding etc to the value. See if you can find it. There may be a function whose purpose is to add a little endian number to a big endian number, or there may be a function that takes an argument and returns the opposite endian. Poke around the top few levels of the call stack to see if anything stands out.
The game seems to store each byte individually. r0 is modified by 8030E96C: 7C600378 or r0,r3,r0 which came from r1 + 9.
Regs:
[spoiler] CR:48202888 XER:20000000 CTR:800692A8 DSIS:02400000
DAR:93491F6C SRR0:8030E970 SRR1:0000B032 LR:8030E958
r0:0000004C r1:8024A318 r2:80241D00 r3:00000040
r4:8024A321 r5:00000013 r6:8024A300 r7:8024A2F0
r8:8024A2F4 r9:8024A2F8 r10:0011C26C r11:8024A368
r12:800692A8 r13:802409C0 r14:0000000C r15:8017E590
r16:802D5000 r17:808788B4 r18:93491F6C r19:00000000
r20:00000000 r21:808788B4 r22:00000008 r23:00000001
r24:00000004 r25:80718FF0 r26:93491F64 r27:80710000
r28:80880000 r29:808787A8 r30:00000000 r31:00000001[/spoiler]
Function:[spoiler]8030E7E8: 9421FFB0 stwu r1,-80(r1)
8030E7EC: 7C0802A6 mflr r0
8030E7F0: 90010054 stw r0,84(r1)
8030E7F4: 39610050 addi r11,r1,80
8030E7F8: 4BD5044D bl 0x8005ec44
8030E7FC: 7C731B78 mr r19,r3
8030E800: 3F208072 lis r25,-32654
8030E804: 3B398FF0 subi r25,r25,28688
8030E808: 3C808088 lis r4,-32632
8030E80C: 386487A8 subi r3,r4,30808
8030E810: 800487A8 lwz r0,-30808(r4)
8030E814: 5400103A rlwinm r0,r0,2,0,29
8030E818: 7C630214 add r3,r3,r0
8030E81C: 80030044 lwz r0,68(r3)
8030E820: 54030FFE rlwinm r3,r0,1,31,31
8030E824: 540007FE rlwinm r0,r0,0,31,31
8030E828: 7C001A78 xor r0,r0,r3
8030E82C: 7C030050 sub r0,r0,r3
8030E830: 2C000001 cmpwi r0,1
8030E834: 41820018 beq- 0x8030e84c
8030E838: 4BFFFF69 bl 0x8030e7a0
8030E83C: 38600001 li r3,1
8030E840: 38990230 addi r4,r25,560
8030E844: 4CC63182 crclr 6,6
8030E848: 48177819 bl 0x80486060
8030E84C: 48172539 bl 0x80480d84
8030E850: 2C030000 cmpwi r3,0
8030E854: 41820180 beq- 0x8030e9d4
8030E858: 7E639B78 mr r3,r19
8030E85C: 48046255 bl 0x80354ab0
8030E860: 482B2F3D bl 0x805c179c
8030E864: 7C7A1B78 mr r26,r3
8030E868: 2C030000 cmpwi r3,0
8030E86C: 41820168 beq- 0x8030e9d4
8030E870: 3AE00001 li r23,1
8030E874: 3B000004 li r24,4
8030E878: 3BE00001 li r31,1
8030E87C: 3BC00000 li r30,0
8030E880: 3F608071 lis r27,-32655
8030E884: 3F808088 lis r28,-32632
8030E888: 3BBC87A8 subi r29,r28,30808
8030E88C: 48000128 b 0x8030e9b4
8030E890: 7C170000 cmpw r23,r0
8030E894: 40800010 bge- 0x8030e8a4
8030E898: 80630064 lwz r3,100(r3)
8030E89C: 7C63C02E lwzx r3,r3,r24
8030E8A0: 48000008 b 0x8030e8a8
8030E8A4: 387B5A54 addi r3,r27,23124
8030E8A8: 4BD5D70D bl 0x8006bfb4
8030E8AC: 7C761B78 mr r22,r3
8030E8B0: 28031FFC cmplwi r3,8188
8030E8B4: 4180001C blt- 0x8030e8d0
8030E8B8: 4BFFFEE9 bl 0x8030e7a0
8030E8BC: 38600001 li r3,1
8030E8C0: 38990278 addi r4,r25,632
8030E8C4: 7EC5B378 mr r5,r22
8030E8C8: 4CC63182 crclr 6,6
8030E8CC: 48177795 bl 0x80486060
8030E8D0: 801C87A8 lwz r0,-30808(r28)
8030E8D4: 5400103A rlwinm r0,r0,2,0,29
8030E8D8: 7C9D0214 add r4,r29,r0
8030E8DC: 38770001 addi r3,r23,1
8030E8E0: 80040044 lwz r0,68(r4)
8030E8E4: 7C030000 cmpw r3,r0
8030E8E8: 40800014 bge- 0x8030e8fc
8030E8EC: 80040064 lwz r0,100(r4)
8030E8F0: 7C60C214 add r3,r0,r24
8030E8F4: 82A30004 lwz r21,4(r3)
8030E8F8: 48000008 b 0x8030e900
8030E8FC: 3ABB5A54 addi r21,r27,23124
8030E900: 3A800000 li r20,0
8030E904: 7E5AB214 add r18,r26,r22
8030E908: 48000094 b 0x8030e99c
8030E90C: 7C630774 extsb r3,r3
8030E910: 2C03005A cmpwi r3,90
8030E914: 40820010 bne- 0x8030e924
8030E918: 9BD20000 stb r30,0(r18)
8030E91C: 3A940001 addi r20,r20,1
8030E920: 48000074 b 0x8030e994
8030E924: 2C03004F cmpwi r3,79
8030E928: 40820010 bne- 0x8030e938
8030E92C: 9BF20000 stb r31,0(r18)
8030E930: 3A940001 addi r20,r20,1
8030E934: 48000060 b 0x8030e994
8030E938: 38810008 addi r4,r1,8
8030E93C: 4BFFFE69 bl 0x8030e7a4
8030E940: 2C030000 cmpwi r3,0
8030E944: 41820038 beq- 0x8030e97c
8030E948: 88110001 lbz r0,1(r17)
8030E94C: 7C030774 extsb r3,r0
8030E950: 38810009 addi r4,r1,9
8030E954: 4BFFFE51 bl 0x8030e7a4
8030E958: 2C030000 cmpwi r3,0
8030E95C: 41820020 beq- 0x8030e97c
8030E960: 88010008 lbz r0,8(r1)
8030E964: 54032036 rlwinm r3,r0,4,0,27
8030E968: 88010009 lbz r0,9(r1)
8030E96C: 7C600378 or r0,r3,r0
8030E970: 98120000 stb r0,0(r18) # break
8030E974: 3A940002 addi r20,r20,2
8030E978: 4800001C b 0x8030e994
8030E97C: 4BFFFE25 bl 0x8030e7a0
8030E980: 38600001 li r3,1
8030E984: 389902C4 addi r4,r25,708
8030E988: 7EA5AB78 mr r5,r21
8030E98C: 4CC63182 crclr 6,6
8030E990: 481776D1 bl 0x80486060
8030E994: 3AD60001 addi r22,r22,1
8030E998: 3A520001 addi r18,r18,1
8030E99C: 7E35A214 add r17,r21,r20
8030E9A0: 7C75A0AE lbzx r3,r21,r20
8030E9A4: 7C600775 extsb. r0,r3
8030E9A8: 4082FF64 bne+ 0x8030e90c
8030E9AC: 3B180008 addi r24,r24,8
8030E9B0: 3AF70002 addi r23,r23,2
8030E9B4: 801C87A8 lwz r0,-30808(r28)
8030E9B8: 5400103A rlwinm r0,r0,2,0,29
8030E9BC: 7C7D0214 add r3,r29,r0
8030E9C0: 80030044 lwz r0,68(r3)
8030E9C4: 7C170000 cmpw r23,r0
8030E9C8: 4180FEC8 blt+ 0x8030e890
8030E9CC: 7E639B78 mr r3,r19
8030E9D0: 482B2EB9 bl 0x805c1888
8030E9D4: 39610050 addi r11,r1,80
8030E9D8: 4BD502B9 bl 0x8005ec90
8030E9DC: 80010054 lwz r0,84(r1)
8030E9E0: 7C0803A6 mtlr r0
8030E9E4: 38210050 addi r1,r1,80
8030E9E8: 4E800020 blr [/spoiler]
Bump.
Here´s some ridiculous way I came up with on how to convert little endian <-> big endian ;D ;D ;D
lis r12, 0xXXXX
lis r10, 0xQQQQ
lbz r11, 0xYYYY (r12)
stb r11, 0xWWWW + 3 (r10)
lbz r11, 0xYYYY + 1 (r12)
stb r11, 0xWWWW + 2 (r10)
lbz r11, 0xYYYY + 2 (r12)
stb r11, 0xWWWW + 1 (r10)
lbz r11, 0xYYYY + 3 (r12)
stb r11, 0xWWWW (r10)
lwz r11, 0xWWWW (r10)
We read each byte manually and store them back inversed to some random RAM location. Finally, we load the full 32bit word into r11.
Caution! We need to convert back before writing to our address.
Any better ideas than that? :)
I think this is right
~11 lines, pseudo asm, needs 3 registers (counting the one that has the 32bit value to be byte reversed) and no storage:
if register a = 01020304
c = a<<16 # (shift left 16 bits) // c = 0304
a = a>>16 # (shift right 16 bits -- make sure left zeros) // a = 0102
b = a<<8
b = b AND 0x0000FF00 //might not be needed if there's specific asm for special shifting
a = a>>8
a = b OR a # a = 0201
b = c<<8
c = c>>8
c = b OR c # c = 0403
c = c<<16
a = c OR a # a = 04030201
Doesn´t look like an ideal solution either, but thank you for this, James. :o
lwbrx, stwbrx
Gah! I knew there was an instruction but I could not find it. lol Thanks megazig
Quote from: James0x57 on November 26, 2012, 09:11:22 PM
b = b AND 0x0000FF00 //might not be needed if there's specific asm for special shifting
I believe what you were looking for was rlwimi (Rotate Left Word Immediate then Mask Insert). It allows you to rotate a register, and then generate a bit mask (like rlwinm style bit mask (http://wiird.l0nk.org/forum/index.php/topic,2844.0.html), see that thread where brkirch goes into detail), and then insert the masked bits directly into the destination register. Quite a complex instruction, but it can be very handy. http://pds.twi.tudelft.nl/vakken/in101/labcourse/instruction-set/rlwimi.html
rlwimi would allow you to mask and insert each byte at the appropriate area with just four instructions. Assuming r12 has the word of interest and r11 is where you want it (and I *think* this will work, but rlwimi is confusing so I may have misunderstood the docs, and some of the numbers may need tweaked)
rlwimi r11, r12, 24, 0, 7 # rotate r12 to the left 24 bits (byte 3 rotated to byte 0), then mask off bits 0-7 (byte 0), and overwrite byte 0 of r12
rlwimi r11, r12, 8, 8, 15 # rotate r12 to the left 8 bits (byte 2 rotated to byte 1), mask off bits 8-15 (byte 1), overwrite byte 1 of r12
rlwimi r11, r12, 24, 16, 23 # r12 to the left 24 bits (= rotate right by 8 bits), mask off byte 2, overwrite byte 2 of r12
rlwimi r11, r12, 8, 24, 31 # r12 to the left 8 bits (= rotate right 24 bits), mask off byte 3, overwrite byte 3 of r12
However, megazig is right, lwbrx (Load Word Byte-Reversed indeXed) is the way to go. Kudos for remembering that instruction! However, I thought the rlwimi instruction might be enlightening too.
EDIT:
hmm....can we do this in three instructions?
rlwimi r11, r12, 24, 0, 23
rlwimi r11, r12, 8, 8, 15
rlwimi r11, r12, 8, 24, 31
I just used "megazig´s" instructions
Quote from: megazig on November 26, 2012, 10:53:25 PM
lwbrx, stwbrx
and yeah, confirmed working! ^_^