WiiRd forum

Wii & Gamecube Hacking => Wii Game hacking help => Topic started by: Deathwolf on February 27, 2011, 06:47:17 PM

Title: .long instruction as string with C2/C0
Post by: Deathwolf on February 27, 2011, 06:47:17 PM
Is it possible to use a .long/.word instruction with C2/C0 as string?
Example:

lis r12,0x8012
ori r12,r12,0x3456
-------------------
.long 0x00000063

Which instruction is for activating the .long?

Thanks for any help
Title: Re: .long instruction as string with C2/C0
Post by: smoere on February 28, 2011, 02:34:56 AM
i don't think i get your question, as the asm you posted, if it's meant to be consecutive, doesn't make sense to me at all (would look like a wrong disasembly, meaning the dissasembler interpreted data for instructions, thus falsely creating the first two lines).

<edit>hopefully clarifying edit: even though i managed to wake up enough braincells to understand your example, i'm still stumped with your "activating the .long", as even after i've reread your post for about 20 minutes i just can't figure out what you mean by activating .data. so could you please rephrase what you want to accomplish? </edit>
Title: Re: .long instruction as string with C2/C0
Post by: dcx2 on February 28, 2011, 03:50:06 AM
You can use .long etc.  However, if the CPU executes your data, it will freeze.
Title: Re: .long instruction as string with C2/C0
Post by: Nutmeg on February 28, 2011, 04:46:23 AM
^in simpler terms.

.long is NOT ASM.  It is used to "specify" how large the data is.
Title: Re: .long instruction as string with C2/C0
Post by: dcx2 on February 28, 2011, 05:47:21 AM
Not how large data is.  It inserts a raw value directly in line with the ASM.  You could do

.long 60000000

And when you compile it, you'll see a nop, because the value 60000000 interpreted as ASM is nop.  It just inserts a raw value.  The confusion arises because data is not normally in line with ASM.  Attempting to execute a data value will almost always freeze the Wii with an illegal opcode exception, unless the data value itself is valid ASM.

You would never, ever mix data and ASM...unless you're using the bl trick to have a small data area inside your ASM code.  For instance, my Super Mario Galaxy 2 teleportation/levitation code uses the bl trick, and you'll see that I use .word in my code.  But my code makes sure the .word's will never be executed as ASM.
Title: Re: .long instruction as string with C2/C0
Post by: Deathwolf on February 28, 2011, 11:50:56 AM
so no string instruction for ASM? I saw 4A001000 but it doesn't work.
Title: Re: .long instruction as string with C2/C0
Post by: smoere on February 28, 2011, 01:57:08 PM
4A001000 XXXXXXXX just sets po=gr0 + XXXXXXXX.

and am i right to assume, that you just want to write 32bit to memory?

if so i think i can see the source of your confusion:

in assembler one has to jump through hoops (ok, not realy, but as i began with "da azm shit yo", i had that impression) to do it, (as PPC-ASM uses fixed length 32bit instructions, ("lis rD, XXXX" for example is just a shorthand expression for "addis rD,0,0xXXXX", wich uses 6 bits for the opcode (what to do) and 10 bits for the operands (where to do it), leaving just 16 bits of "payload") so it can't be simple.

well, it just turns out it is, as it doesn't matter what kind of content you want to write, as the bits in the ram have no type associated (labels like .long, .word, .text, .data etc are just used to improve readability (okok, and they are also instructions for the assembler, which turns the ASM to machine code)) they just get interpreted according to their context, meaning if the CPU thinks "the next 32bit are an instruction, because the ones before were too or i got directed here by a branch instruction" it tries to execute it, or handles it as data in case some instruction had the adress in a register to load it or write to it.

sooooo, lets return from my little tangent and try to answer what i think is your question: to write 32 bits to memory, just use a 04 type code, for example:

to write the value 0xDEADBEEF to adress 0x8016D360 use 0416D360 DEADBEEF
to write the value 0xC0FEBABE to adress 0x812AC04C use 052AC04C C0FEBABE
to write to a memory location outside the 0x800000 range you have to set ba or po accordingly, but please remember to terminate (aka reset them) afterwards using a E0000000 80008000 code
Title: Re: .long instruction as string with C2/C0
Post by: Deathwolf on February 28, 2011, 02:08:16 PM
Thanks for your answer, but I was asking for a String code in ASM.
Now I think that's not possible.
Title: Re: .long instruction as string with C2/C0
Post by: smoere on February 28, 2011, 02:56:40 PM
string code as in
QuoteString Write (Patch Code)
06______ YYYYYYYY
d1d2d3d4 d5d6....

Writes each byte (d1, d2, d3, ...) consecutively, starting at address ba +______ YYYYYYYY is the number of bytes to write

To use po instead of ba, change the codetype from 06 to 16. For values of ______ >= 0x01000000, add one to the codetype.
?

of course you can write those in assembler on your own, but i just don't see why you would want to do so, as long as it isn't meant to be a training exercise. :)

anyway: load the values you want to write into consecutive registers (for example using the lis + ori method from your example), then use  stmw, stswi or stswx to write them to memory.

oh, and get yourself a copy of 6xx_pem.pdf (https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2) it will come in handy ;)
Title: Re: .long instruction as string with C2/C0
Post by: Deathwolf on February 28, 2011, 03:09:39 PM
Quote from: smoere on February 28, 2011, 02:56:40 PM
string code as in
QuoteString Write (Patch Code)
06______ YYYYYYYY
d1d2d3d4 d5d6....

Writes each byte (d1, d2, d3, ...) consecutively, starting at address ba +______ YYYYYYYY is the number of bytes to write

To use po instead of ba, change the codetype from 06 to 16. For values of ______ >= 0x01000000, add one to the codetype.
?

of course you can write those in assembler on your own, but i just don't see why you would want to do so, as long as it isn't meant to be a training exercise. :)

anyway: load the values you want to write into consecutive registers (for example using the lis + ori method from your example), then use  stmw, stswi or stswx to write them to memory.

oh, and get yourself a copy of 6xx_pem.pdf (https://www-01.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2) it will come in handy ;)

thanks but this should work too or?

example a serial code:
lis r12,0xFFFF
ori r12,r12,0xFFFF
stw r12,0(31)
stw r12,4(31)
stw r12,8(31)
stw r12,12(31)
stw r12,16(31)
stw r12,20(31)

C2000000 00000005
3D80FFFF 618CFFFF
919F0000 919F0004
919F0008 919F000C
919F0010 919F0014
60000000 00000000

String:
lis r0,0x8012
ori r0,r0,0x2340
lis r3,0xFFFF
ori r3,r3,0xFFFF
stw r3,0(r0)
lis r5,0x8012
ori r5,r5,0x2344
lis r9,0x4200
ori r9,r9,0x6666
stw r9,0(r5)
lis r10,0x8012
ori r10,r10,0x2348
lis r11,0x16FD
ori r11,r11,0xCCF7
stw r11,0(r10)
lis r12,0x8012
ori r12,r12,0x234C
lis r14,0x3F80
ori r14,r14,0x0020
stw r14,0(r12)


C0000000 0000000B
3C008012 60002340
3C60FFFF 6063FFFF
90600000 3CA08012
60A52344 3D204200
61296666 91250000
3D408012 614A2348
3D6016FD 616BCCF7
916A0000 3D808012
618C234C 3DC03F80
61CE0020 91CC0000
4E800020 00000000
Title: Re: .long instruction as string with C2/C0
Post by: ukuneko on February 28, 2011, 03:38:59 PM
Sample. How do you like it?


040039FC 00000063  <------set String value 00000063
C0000000 00000008
9421FFB0 BDC10008
3DC08000 61CE3A00
3DE08000 61EF3B00
820EFFFC 920E0000
39CE0004 7C0E7800
41820008 4BFFFFF0
B9C10008 38210050
4E800020 00000000

stwu r1,-80(r1)
stmw r14,8(r1)
lis r14,-32768
ori r14,r14,14848  <------set start String Address = 0x80003A00
lis r15,-32768
ori r15,r15,15104  <------set End String Address = 0x80003B00
lwz r16,-4(r14)    <------Load String value = 00000063
stw r16,0(r14)   <------Write a 00000063
addi r14,r14,4   <-------Go Next Address  b 0x0004
cmpw r14,r15   <------  check End String Address
beq- 0x08
b 0xFFFFFFF0  <------RTN   stw r16,0(r14)  b 0x -10
lmw r14,8(r1)       
addi r1,r1,80
blr
Title: Re: .long instruction as string with C2/C0
Post by: Deathwolf on February 28, 2011, 03:44:11 PM
Quote from: ukuneko on February 28, 2011, 03:38:59 PM
Sample. How do you like it?


040039FC 00000063  <------set String value 00000063
C0000000 00000008
9421FFB0 BDC10008
3DC08000 61CE3A00
3DE08000 61EF3B00
820EFFFC 920E0000
39CE0004 7C0E7800
41820008 4BFFFFF0
B9C10008 38210050
4E800020 00000000

stwu r1,-80(r1)
stmw r14,8(r1)
lis r14,-32768
ori r14,r14,14848  <------set start String Address = 0x80003A00
lis r15,-32768
ori r15,r15,15104  <------set End String Address = 0x80003B00
lwz r16,-4(r14)    <------Load String value = 00000063
stw r16,0(r14)   <------Write a 00000063
addi r14,r14,4   <-------Go Next Address  b 0x0004
cmpw r14,r15   <------  check End String Address
beq- 0x08
b 0xFFFFFFF0  <------RTN   stw r16,0(r14)  b 0x -10
lmw r14,8(r1)       
addi r1,r1,80
blr


That looks really nice but sounds for me like a "serial code".
Btw you are able to use a stack frame with C0?

ok here just a example using all registers: String 80122340- 80122374

stwu r1,-80(r1)
stmw r14,8(r1)
lis r0,0x8012
ori r0,r0,0x2340
lis r3,0xFFFF
ori r3,r3,0xFFFF
stw r3,0(r0)
lwz r3,0(r0)
lis r5,0x8012
ori r5,r5,0x2344
lis r9,0x4200
ori r9,r9,0x6666
stw r9,0(r5)
lwz r9,0(r5)
lis r10,0x8012
ori r10,r10,0x2348
lis r11,0x16FD
ori r11,r11,0xCCF7
stw r11,0(r10)
lwz r11,0(r10)
lis r12,0x8012
ori r12,r12,0x234C
lis r14,0x3F80
ori r14,r14,0x0020
stw r14,0(r12)
lwz r14,0(r12)
lis r15,0x8012
ori r15,r15,0x2350
lis r16,0x3ED0
ori r16,r16,0x0000
stw r16,0(r15)
lwz r16,0(r15)
lis r17,0x8012
ori r17,r17,0x2354
lis r18,0x3800
ori r18,r18,0x0645
stw r18,0(r17)
lwz r18,0(r17)
lis r19,0x8012
ori r19,r19,0x235C
lis r20,0x6000
ori r20,r20,0x0000
stw r20,0(r19)
lwz r20,0(r19)
lis r21,0x8012
ori r21,r21,0x2360
lis r22,0xEC02
ori r22,r22,0x20C3
stw r22,0(r21)
lwz r22,0(r21)
lis r23,0x8012
ori r23,r23,0x2364
lis r24,0xFC34
ori r24,r24,0x5928
stw r24,0(r23)
lwz r24,0(r23)
lis r25,0x8012
ori r25,r25,0x236C
lis r26,0x6C0E
ori r26,r26,0xDDDC
stw r26,0(r25)
lwz r26,0(r25)
lis r27,0x8012
ori r27,r27,0x2370
lis r28,0x4DCE
ori r28,r28,0x8830
stw r28,0(r27)
lwz r28,0(r27)
lis r29,0x8012
ori r29,r29,0x2374
lis r30,0x0183
ori r30,r30,0x1337
stw r30,0(r29)
lwz r30,0(r29)
lmw r14,8(r1)       
addi r1,r1,80

C0000000 00000027
9421FFB0 BDC10008
3C008012 60002340
3C60FFFF 6063FFFF
90600000 80600000
3CA08012 60A52344
3D204200 61296666
91250000 81250000
3D408012 614A2348
3D6016FD 616BCCF7
916A0000 816A0000
3D808012 618C234C
3DC03F80 61CE0020
91CC0000 81CC0000
3DE08012 61EF2350
3E003ED0 62100000
920F0000 820F0000
3E208012 62312354
3E403800 62520645
92510000 82510000
3E608012 6273235C
3E806000 62940000
92930000 82930000
3EA08012 62B52360
3EC0EC02 62D620C3
92D50000 82D50000
3EE08012 62F72364
3F00FC34 63185928
93170000 83170000
3F208012 6339236C
3F406C0E 635ADDDC
93590000 83590000
3F608012 637B2370
3F804DCE 639C8830
939B0000 839B0000
3FA08012 63BD2374
3FC00183 63DE1337
93DD0000 83DD0000
B9C10008 38210050
4E800020 00000000
Title: Re: .long instruction as string with C2/C0
Post by: ukuneko on February 28, 2011, 04:28:47 PM
hahaha
0h! I've been misunderstood .  :D
Title: Re: .long instruction as string with C2/C0
Post by: smoere on February 28, 2011, 05:04:54 PM
@Deathwolf: so all you want to do is write 13 consecutive 32bit words, that do not have some kind of reusable pattern, to memory?
then why not let the codehandler the work for you and use

06122340 00000034
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF 00000000

which would be shorter, easyier to read and less error prone? (and yes, i'm aware you don't want to use DEADBEEF, i just didn't wan't to copy out your data ;))

at least in my opinion you should only write such monsters on your own when there is some kind of pattern you can use to generate the string on runtime

<edit> oh, and even if you'd need the values in the registers again, you dont need to reload them, stw doesn't wipe them </edit>
Title: Re: .long instruction as string with C2/C0
Post by: Deathwolf on February 28, 2011, 05:14:57 PM
Quote from: smoere on February 28, 2011, 05:04:54 PM
@Deathwolf: so all you want to do is write 13 consecutive 32bit words, that do not have some kind of reusable pattern, to memory?
then why not let the codehandler the work for you and use

06122340 00000034
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF 00000000

which would be shorter, easyier to read and less error prone? (and yes, i'm aware you don't want to use DEADBEEF, i just didn't wan't to copy out your data ;))

at least in my opinion you should only write such monsters on your own when there is some kind of pattern you can use to generate the string on runtime



yea you are right.


06122340 00000034
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF 00000000

4A000000 80122340
16000000 00000034
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF 00000000
E0000000 80008000

etc. But I was asking to use something like that with C0 or C2.
lis and ori are like the codetypes 00,02 and 04 but I never saw a instruction for string in ASM.
Anyway, MAYBE there is a way to grab a address from C0 oder C2 like this:

lis r12,0x8012     # load into address 80122340
ori r12,r12,0x2340
Then grab this address and activate 06/16
16000000 00000034
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF DEADBEEF
DEADBEEF 00000000
E0000000 80008000


Title: Re: .long instruction as string with C2/C0
Post by: smoere on February 28, 2011, 05:30:23 PM
would you care to elaborate on why you need to do this from within the game code?
Title: Re: .long instruction as string with C2/C0
Post by: Deathwolf on February 28, 2011, 05:40:03 PM
Ok if you have the codetype 48, why are you using ASM? 48 works fine too!
If you have codetype 04, why are you using 00,02,04,06? Because it's a smaller code? lol

I don't see the real reason to do this.
Title: Re: .long instruction as string with C2/C0
Post by: Y.S. on March 01, 2011, 02:34:16 AM
QuoteString:
lis r0,0x8012
ori r0,r0,0x2340
lis r3,0xFFFF
ori r3,r3,0xFFFF
stw r3,0(r0)

lis r5,0x8012
ori r5,r5,0x2344
lis r9,0x4200
ori r9,r9,0x6666
stw r9,0(r5)

lis r10,0x8012
ori r10,r10,0x2348
lis r11,0x16FD
ori r11,r11,0xCCF7
stw r11,0(r10)

lis r12,0x8012
ori r12,r12,0x234C
lis r14,0x3F80
ori r14,r14,0x0020
stw r14,0(r12)

Writing a string of data using ASM can be done like this;
[spoiler].set base,0x80122340

.set data,3
.set address,4
.set offset,5

.set counter,12
.set anchor,12

stwu   r1,-0x80(r1)
stmw   r2,8(r1)
mflr   r2

li   counter,(_DataEnd - _DataStart)/4
mtctr   counter

bl   _DataEnd
_DataStart:
.long 0xFFFFFFFF
.long 0x42006666
.long 0x16FDCCF7
.long 0x3F800020
_DataEnd:

mflr   anchor
lis   address,base@h
ori   address,address,base@l
li   offset,0

_Loop:
lwzx   data,anchor,offset
stwx   data,address,offset
addi   offset,offset,4
bdnz+   _Loop

mtlr   r2
lmw   r2,8(r1)
addi   r1,r1,0x80[/spoiler]
Title: Re: .long instruction as string with C2/C0
Post by: dcx2 on March 01, 2011, 04:00:11 AM
Y.S.

I don't think you can use r2 to cache the LR.  r2 is a reserved register that points to a read-only data area for things like constants and globals.

Also, you can replace the lwzx/stwx with lwzu/stwu.  This would allow you to optimize away the li offset and addi offset, but you need to un-offset the anchor so the lwzu points to the right place.  Fortunately, we can un-offset the base during compilation.  It will also execute slightly faster.

This requires your data to be word aligned.  If you want byte alignment, you'd have to rewrite it with lbzu/stbu instead.  If you know your data is double-word aligned, you can switch to psq_lu and psq_stu for a somewhat pointless increase in speed.

Also, to prove a point about using these commands to insert data into your code, I switched it up a bit.  Now, it loads a variety of data types; one word, four bytes, the float 1.0 and a float approximation of pi.  The assembler will automatically convert all those values to hex.

[spoiler].set base,0x80122340 - 4

.set LR_save_reg,14
.set data,15
.set address,16
.set offset,17

.set counter,18
.set anchor,18


stwu r1,-80(r1)
stmw r14,8(r1)
mflr   LR_save_reg

li   counter,(_DataEnd - _DataStart)/4
mtctr   counter

bl   _DataEnd
_DataStart:
.long 0xFFFFFFFF
.byte 16, 99, 127, 255
.float 1.0
.float 3.14159

_DataEnd:

mflr   anchor
subi anchor, anchor, 4
lis   address,base@h
ori   address,address,base@l

_Loop:
lwzu   data,4(anchor)
stwu   data,4(address)
bdnz+   _Loop

mtlr   LR_save_reg
lmw   r14,8(r1)
addi   r1,r1,80[/spoiler]

Note the compiled form

[spoiler]C0000000 0000000B
9421FFB0 BDC10008
7DC802A6 3A400004
7E4903A6 48000015
FFFFFFFF 10637FFF
3F800000 40490FD0

7E4802A6 3A52FFFC
3E008012 6210233C
85F20004 95F00004
4200FFF8 7DC803A6
B9C10008 38210050
4E800020 00000000[/spoiler]

Bolded is the string data.  Compare this to

06122340 00000010
FFFFFFFF 10637FFF
3F800000 40490FD0


EDIT typo
Title: Re: .long instruction as string with C2/C0
Post by: Y.S. on March 01, 2011, 07:03:39 AM
I assumed that r2 can be used as long as it is pushed on the stack (haven't actually tested yet). Thanks for pointing that out.

And about the optimization, I think your idea of using lwzu/stwu in a loop is a more elegant way to copy a block of data, but what I don't understand is the registers' assignment; Are there any guidelines to follow when you choose which register(s) to use in the code?
In other words, why did you choose r14~r18? 

Title: Re: .long instruction as string with C2/C0
Post by: dcx2 on March 01, 2011, 01:41:34 PM
We typically recommend pushing everything from r14 up onto the stack.  r14-r31 are all non-volatile registers that are safe to use when their contents are backed up on the stack.  At that point, you can use any of the registers, so I just started with r14 and worked my way up each time I needed a new register.'

A C0 code's guidelines are different because it runs in the context of the code handler.

For C2 codes, I made a post recommending guidelines for choosing registers.  Most of the time, you don't need to create a stack frame for a C2 code if you pick your hook right.

http://wiird.l0nk.org/forum/index.php/topic,6555.0.html
Title: Re: .long instruction as string with C2/C0
Post by: Deathwolf on March 01, 2011, 06:03:49 PM
Thank you guys, that is what I'm looking for but I never used these instructions.
Could you explain this a little more please?