PowerPC For Dummies - Examples And Guides
 
If any of this is wrong, or if you're still confused about something...
check the main page, or contact me on discord "JimmyK#2848
The Basics

Gonna start this off with some easy to assemble codes in Gecko Code format.


Ram Write
04XXXXXX YYYYYYYY

This will force the game to replace the value at an address.

Replace the X values with the address you want to replace a value in.
Replace the Y values with the value you want to put in said address


Example

04000004 00000001

This will force the game to always make address 0x80000004 have the value of "0x1"

Instruction Replace
C2XXXXXX 00000001
YYYYYYYY 00000000

This will replace an assembly instruction. For the sake of simplicity, I will not go into detail about the different types of instructions. Those are explained in further detail below.

The X values specify the address you want to execute the instruction at.
The Y values specify the instruction that will be executed at said address.


Now for the assembly tutorials.


 

Load An Address into a Register
lis r0, 0x8000
ori r0, r0, 0xFFFF


This will load address 0x8000FFFF into register 0

You might be thinking "why not just use li for the bottom half of the register?"
 
"li" can only load values up to 0x7FFF into a register, whereas "ori" can load values up to 0xFFFF

This type of code requires 2 registers.

  # Assume that you want to replace the value at the address 0x8000FFFF
  # First, you need to load it into a register.
  # Let's load it into Register 0 as an example.

  lis       r0, 0x8000
  ori       r0, r0, 0xFFFF

  # Register 0 now holds the address 0x8000FFFF

  # Next, you need to load the value you want to replace at the address      you loaded into register 0

  # Assume that the value you want to replace at 0x8000FFFF is "0x5" 

  li r1, 0x5

 # Register 0 now holds the address 0x8000FFFF

 # Finally, you have to store the value into the address

 # This instruction below basically tells the code "Whatever value is in     register 1 will be stored into the address held in register 0"

  stw r1, 0x0(r0)


The value at address 0x8000FFFF is now "0x5"

Specify an Operation in MEM2
42000000 90000000

This sets the code base to 90XXXXXX
 
A 04 ram write code type will now affect any address starting with 0x90
A 05 ram write type code will now effect any address starting with 0x91
Specify an Operation in MEM3
42000000 92000000

This sets the code base to 92XXXXXX
 
A 04 ram write code type will now affect any address starting with 0x92
A 05 ram write type code will now effect any address starting with 0x93
Branches
Branch
When your code reaches this instruction, it will jump to wherever you specify.

EXAMPLE:

li r0, 1
b function2

function2:
li r0, 2

# After the execution of the li instruction, the code will execute the "b" instruction, this will cause the code to jump to "function2" and start executing every instruction in that function


 This is equivalent to a "goto" statement.

Branch And Link
This is basically an instruction that tells your code to execute a specific function and then return to where it originally branched from.

This instruction type requires the mflr and mtlr instruction types, I haven't been able to simplify the explanation for how those 2 instruction work yet.

Example will be added as soon as I can simplify this.

Branch To Link Register
This instruction causes your code to branch to whatever address is held in the Link Register.
 
Example will be added as soon as I can simplify the process.
 
Advanced Operations
Specify the amount of times you want something to happen in a code
There are 2 parts to this. Specifying the amount, and the code itself.

# The value of "X" in the li instruction is the amount of times your code will loop

li r0, 4
mtctr r0

# Register 0 now countains the amount of times the code will loop, which in this case is "4"

# Now for the actual code.

function:
addi r1, r1, 0x1
bdnz function

b loop_has_stopped

 

# The instruction "bdnz" subtracts 1 from the Count Register (The value in Register 0) each time it's ran, when the value in the Count Register is 0, the loop stops.
 
# In this context, the code above will add "1" to the value in register 1, This will happen 4 times, After the 4th time, the count register will have the value "0" and the loop will stop. The code will then branch to the next function named "loop_has_stopped"
 
Load The CPU Clock into a Register
This is a trick that most, if not all randomization codes use. I don't know if there is any other way to make one besides using a game's rng seed though.
 
I'm mostly just listing the mftbl (Move From Time Base Low) instruction here because it isn't doccumented anywhere, at least to my knowledge.
 
# Let's move the CPU Clock into a register.
 
mftbl r0
 
# r0 now contains the CPU Clock
# That's all for the instruction. I can't give a randomization example just yet, it involves many different variables.
 
 
 
Create a Stack Frame

To put it simply, if you don't make one of these, the game you're making a code for will crash if you try and replace a value in Registers 0 - 4.

It's going to take a while for me to be able to simplfy the whole process of it.

So for now, here is kiwi515's explanation of it
 

# Update r1 (By subtracting 0x80, we now effectively "own" 0x80 bytes)
stwu sp, -0x80 (sp)

# Backup r3 through r31 into this new area
stmw r3, 0x8 (sp)

# Do whatever with the registers here

# Restore the backups to r3 through r31
lmw r3, 0x8 (sp)

# Update r1 (By adding 0x80, we effectively "give back" the memory that we once owned)
addi sp, sp, 0x80 

 
 
AND, OR, XOR

Oh man, It was an absolute mindfuck trying to understand how these worked. I had to do a ton of testing.

I'm 90% sure this is wrong, but these are the results I got while testing these instructions in dolphin. 

These instructions work in a very oddly specific way.

 

AND
AND means "If both values are true (equal), the result is true".

AND takes the values from Register B and C and compares them, the result of the operation is put in Register A

EXAMPLE:

# Assume that Register 0 and Register 1 both hold the value "3"

and r2, r0, r1
cmpwi r2, 3
beq
function2

# This code will compare the values of Registers 0 and 1 to see if they are both equal to 3, in this case they are, so the code jumps to "function2"

  • If both the values are the same, the resulting value is the same as the intial value
     
  • If one value is different than the other, the resulting value is
    0 (false)

 

OR
OR means "If at least one value is true (equal), the result is true.

OR takes the values from Register B and C and compares them, the result of the operation is put in Register A

EXAMPLE:

# Assume that Register 0 holds the value "2" and Register 1 holds the value "3"

or r2, r0, r1
cmpwi r2, 3

beq function2
cmpwi r2, 5
beq function2

# You might be wondering why the resulting register is being checked for the value "5".

# If only one of the values is "true", the resulting value is made up of both values added together, which in this case would be "5"

# The code checks to see if either 1 value was "true" (if r2 = 0x5),
or if both of them were (if r2 = 0x3). If one of those conditions are met, the code jumps to 
"function2"
 

  • If both the values are the same, the resulting value is the intial value
     
  • If 1 value is different, the resulting value is the sum of both values added together

 

XOR
XOR means "Only one value can be true, otherwise the result is false".

XOR takes the values from Register B and C and compares them, the result of the operation is put in Register A

EXAMPLE:

# Assume that Register 0 holds the value "2" and Register 1 holds the value "3"

xor r2, r0, r1
cmpwi r2, 5
beq 
function2

# Assume that you want your code to jump to "function2" if only 1 of the values in Register 0 and Register 1 is "true"

# I can't think of a good way to explain this.....

# Basically, the xor instruction adds both values from both registers together if one of them is different from the other.



# Let's assume that in this context, you wanted to check to see if Register 0 or Register 1 held the value "2", as the code above shows.

# Register 0 holds the value "2", and Register 1 holds the value "3"

# The resulting value is "5", and the operation result was "true"

# Do you know why the result was true?

#Because "2" was one of the values that was needed to make the result value.

 

That's the best way I can possibly explain it.

 
  • If both the values are the same, the resulting value is 0 (false)
     
  • If 1 value is different, the resulting value is the sum of both values added together

 

 

 

 

 

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
The Basics
Ram WriteInstruction Replace
Load An Address into a RegisterReplace a Value at an AddressSpecify an Operation in MEM2Specify an Operation in MEM3
Branches
BranchBranch And LinkBranch To Link Register
Advanced Operations
Specify the amount of times you
want something to happen in
a code
Load The CPU Clock into a 
Register
Create a Stack FrameAND, OR, XORTBDTBDTBDTBD
TBD
TBDTBDTBDTBDTBDTBDTBDTBDTBDTBDTBDTBD
TBD
TBDTBDTBDTBDTBDTBDTBDTBD
TBD
TBDTBDTBDTBDTBDTBDTBDTBDTBDTBDTBDTBD
Original Description - Hex
Codetypes in depth
A hex digit actually represents 4 bits, and you need to look at the underlying bits to understand why the code types are defined the way they are. Normally, we refer to a 32 1018 -bit RAM write as an "04 code type", but this is actually a misnomer. It misleadingly implies that the 8 bits belonging to the two hex digits "04" are the code type, when the actual code type only has 7 bits! The 8th bit belongs to the address, which creates the "05" code type. People also think that the address is only comprised of 24 bits (the other 6 hex digits), when the address is actually 25 bits (the other 6 hex digits + the last bit of the second digit).

A picture may help; Here's the binary breakdown of the first 
word
 of a code.

Hex Digit  |
         First         
  |
        Second         
|
        Third     
|
   Fourth ...

Bit#       |
   0   1   2   
|
   3   
|
   4   5   6   
|
   7   
|
   8   9  10  11  
|
   12     ...

is         |
   Code Type   
|
 ba/po 
|
 Code Sub Type 
|
  address ..............................