Mario Kart Wii Gecko Codes, Cheats, & Hacks
C0 Codetypes - Printable Version

+- Mario Kart Wii Gecko Codes, Cheats, & Hacks (
+-- Forum: Guides/Tutorials/How-To's (
+--- Forum: Power PC Assembly (
+--- Thread: C0 Codetypes (/showthread.php?tid=1156)

C0 Codetypes - Vega - 07-05-2019

C0 Codetypes

Thank you to Star for teaching me some details on the C0 Codes.

Fyi: This information is for the original release of the Gecko OS code handler which is used in many applications (such as USB Loader GX). Other code handlers (like the one for Dolphin) are different so the information here may not be accurate for those other code handlers.

Chapter 1. What Are C0 Codes?

C0 Codes are called Execute ASM Codes. They are a bit different than 'C2/Insert ASM' Codes. The instructions of a C0 code are executed every time the Gecko Code Handler gets executed. The Gecko Code Handler gets executed whenever it's designated hooktype (that you chose in your Cheat/Ocarina settings of your Disc/ISO HBC loader app) gets executed. Every hooktype executes every frame (60 times per second). So in conclusion, your C0 Code executes every frame of the game.

For example, if your Hooktype for your Cheat/Ocarina settings is OSSleepThread, every time the OSSleepThread function is executed, the C0 Code will be executed as well. To understand more about Hooktypes, read this thread HERE.

For each C0 code you have in your GCT/Cheat-Manager, the Gecko Code Handler will create a subroutine for it, every C0 code you have gets executed via the following instructions of the Code Handler

mtlr r15 #Place address of current C0 code into r15
blrl #Execute C0 code and return back to Code Handler

Register safety differs in C0 Codes compared to how it is for C2 Codes, which will be covered in Chapter 3. C0 Codes have no base address, and can be region-free or even wii-game-universal (this all depends on the exact code itself ofc).

Chapter 2: How to Compile C0 Codes

Every C0 code must end in a blr instruction. This is needed so your can have code return back to the Code Handler once it has finished. Some compilers have a C0 option while others do not.

Compiling with PyiiASMH:
There is NO NEED to include the final blr instruction to your source. Just select the 'C0' option before compiling. That's it.

Compiling with WiiRDGUI:
You MUST include the final blr instruction in your source. Use an address of '80000000' when compiling. Once your code has been compiled change the 'C2' byte of the code (the very 1st byte that represents an Insert ASM code), and change it to 'C0'. if WiiRDGUI had to add a nop to your code (60000000), then remove the final compiled line of your code (60000000 00000000), and subtract one from the value of the line-amount-designator byte (this is the upper most far right byte of the compiled code that tells the Code Handler how many lines of compiled code is underneath).

Compiling with CodeWrite:
You MUST include the final blr instruction in your source. Leave the Insertion Address blank! Follow the same procedure in adjusting the compiled code that was explained for the WiiRDGUI compiler if a nop was auto added to your code.

Chapter 3: Register Safety

Certain registers and condition fields are already taken up by the Code Handler so we want to make sure we don't edit those specific values

r0 = Safe
r1 = Not Safe (Can push/pop stack like any other ASM code if needed)
r2 = Not Safe ofc...
r3 = Safe
r4 = Not Safe
r5 = Safe
r6 thru r8 = Not Safe
r9 thru r12 = Safe
r13 thru r31 = Not Safe
All Condition Fields = Safe (CR backed up by code handler, CR's get set with new values with new instructions after C0 subroutine)
CTR = Safe (CTR backed up by code handler, CTR gets set with new value with new instructions after C0 subroutine)
LR = Not Safe ofc...
f0 & f1 = Follow Standard Safety Protocol
f2 & f3 = Safe (backed up by code handler)
f4 thru f31 = Follow Standard Safety Protocol

As noted above, you can push/pop the stack for more registers if needed. As usual, try using the least amount of stack space possible. Only allocate what you need.

Chapter 4: Make C0 Code Only Execute Once

If desired, here is a list of instructions to add to your Source to enable a C0 Code to only execute once. Make sure these instructions come before all other instructions of your Source.

lis rX, 0x4E80
ori rX, rX, 0x0020
stw rX, 0 (r15)

rX = Any of the safe registers.

Since r15 points to the first instruction of your C0 code, we simply overwrite that instruction with a 'blr', thus causing that particular C0 code to not ever execute again.

Chapter 5: Button Activation/De-Activation

You cannot use gecko codetype 16-bit if statements (i.e. 2834/2833XXXX YYYYZZZZ) to make your C0 code(s) be activated and/or deactivated via a button value(s). You must write all of the button activation/deactivation in your source.

Here is an example template you can use for assistance, this isn't a 'plug and play' for use with every C0 code, you will need to make the proper adjustments for this to work in your specific C0 code ~~

lis rX, 0x803x #8033 for NTSC-K MKWii, 0x8034 for all other MKW regions, adjust this accordingly if used for a different Wii game. This instruction is setting the upper 16 bits of the memory address where your button values reside in memory.
lhz rX, 0xXXXX (rX) #XXXX is the lower 16 bits of the memory address (the XXXX in 2833/2834XXXX for MKW). If 0xZZZZ exceeds 0x7FFF, use the sign-extension trick (increase the lis instruction value by 0x0001, then pre-pend the 0xZZZZ value with 0xFFFF (0xFFFFZZZZ).
andi. rX, rX, 0xZZZZ #ZZZZ is the button activator(s) you want to check for
beq+ do_not_execute

#instructions here for when code gets executed (button(s) is pressed


IMPORTANT NOTE if writing this for GCN: Since standard wired GCNs have this stupid 0x0080 value that's always present, you will need to use the ZZZZ values that are for the Wavebird (wireless GCN). You could get around this by writing extra source, but I simply wanted to provide you the template that contains the least amount of instructions.

Chapter 6: Warning about Function Calls

Certain function calls will not work on C0 codes when ran on the Dolphin Emulator. This is not a fault of the code or C0 codetype, but it's the Dolphin Emulator forcing the Gecko Code Handler to execute in the middle of your C0 code. It appears that if a C0 code takes too long to execute, regardless of whether or not it contains function calls, Dolphin will invoke its own 'master interrupt'. This 'master interrupt' will cause your C0 code to quit executing and force the emulated CPU to jump to the start of the Gecko Code Handler.

Nothing can disable this 'Master Interrupt'. Not even disabling interrupts on the Machine State Register.

If you have function calls in a C0 code, be sure to test them many times on Dolphin. Game-specific function calls seem to work fine but larger Wii-based function calls that take much longer to execute (like file editing) will not work. A solution is to drop the C0 codetype and rewrite your code using standard C2 with an address that executes every frame.

You may discover that C0 codes with large function call(s) will botch your game on real Wii hardware. This is because of normal interrupts by Starlet or some other piece of hardware. You need to disable interrupts in the Machine State Register before your function call(s), then restore interrupts afterwards.

Here's a snippet of source disabling interrupts of the Machine State Register, place this at the start of your code~
mfmsr rX #rX must be a register that its value will be preserved throughout your code (until we need to restore interrupts)!!!; Copy value of MSR to rX
rlwinm rY, rX, 0, 17, 15 #Flip 'Allow Interrrupts' bit Low
mtmsr rY #rY's value can now be scrapped AFTER this instruction has executed; rY's value is copied to the MSR

And here's a snippet of source to restore interrupts, place this at the end of your code~
andi. rX, rX, 0x8000 #Check if 'Allow Interrupts' bit was already low before it was flipped low from earlier, we no longer need rX's preserved value
mfmsr rX  #We cannot simply reuse our old MSR value btw, your function calls may have modified other bits in the MSR
beq- disable_ints #Check if interrupts were already disabled beforehand. If so, ensure that they stay disabled

#Flip on 'Allow Interrupts' bit
ori rX, rX, 0x8000
b update_msr

rlwinm rX, rX, 0, 17, 15

mtmsr rX

Chapter 7: Stepping Thru C0 Codes (Debugging)

Stepping thru C0 Codes may require a bit more work compared to C2 Codes. Especially if you have multiple C0 codes. You will need to decide if you are OK with allowing the emulation to run a bit, or if you want to absolutely make sure you have all your debugging tools + Breakpoints set before the C0 code gets executed by the first initial execution of the Code Handler. This all depends on your C0 code you are debugging and what instructions are in the code. There's no way I can know personally which method applies to you and your code.

If you have a C0 code that's intended to execute all its instructions on its first initial execution, you may want to have everything prepared before the Code handler gets its first time execution. If you have a C0 Code that only executes on something like a button activator, then it would be okay to allow the game to run while setting up everything as long as said button activator isn't pressed.

How to debug a C0 code:
1. If you have multiple C0 codes on your Cheat-Manager, be sure the specific one you want to debug is the FIRST/TOP one.
2. At this point you need to decide if you are fine with allowing the emulation run a bit or you need everything setup immediately. If you are fine with the emulation running, skip ahead to Step 5
3. Before you boot the game, at the top of your Dolphin, click on Options.
4. A drop down menu should appear. Click on the box next to "Boot Game to Pause". Be sure the box is checkmarked/filled.
5. Boot your game! If you chose to allow the emulation to run, you can now Pause it.
6. In Code view go to 0x80001F9C. You should see a 'blrl' instruction. It may not be at that exact address, but still should be nearby. See picture below. If you did the boot-to-pause option, you will nto see any instructions as the Code Handler hasn't been injected yet, proceed to Step 7.

[Image: C001.png]

7. Set an Instruction BP on that address that contains the blrl instruction. Like in this picture below (notice the Grey Dot next to the address indicating a BP has been activated). However if you did the boot-to-pause option, set an Instruction BP on 0x800018A8 instead, run the emulation, the BP will hit. Now you can scroll down to 0x80001F9C and set an Instruction BP there.

[Image: C002.png]

8. Resume emulation, the emulation will pause once your BP has been hit. At this point the blrl instruction in Code View should be highlighted in green, like the picture below...

[Image: C003.png]

9. Now Step just ONE time. You are now at the first instruction of your C0 code. Smile Now you can start debugging the C0 code, congratz.

Anybody who created/helped-on the Gecko Code Handler
dcx2 (for his comments about this topic on the old WiiRD forums)

RE: C0 Codetypes - _tZ - 03-12-2021

the trick in chapter 5 does not update the code cache (this is not good)
should probably be
/* overwrite first instruction with blr */
lis rX, 0x4E80
ori rX, rX, 0x0020
stw rX, 0x0(r15)
/* update cache */
dcbf 0, r15
icbi 0, r15

RE: C0 Codetypes - Vega - 03-12-2021

In my experience I never needed to instantly update the cache. Though it wouldn't hurt.

According to the Broadway manual, the cache needs to be updated like this if you are modifying executable instructions

dcbst 0, rX
icbi 0, rX

RE: C0 Codetypes - lovops - 03-13-2021

I want to learn about Hooking.

RE: C0 Codetypes - Vega - 03-14-2021

There isn't much to learn.

I went ahead and updated the thread that explains Hooktypes if that helps.

RE: C0 Codetypes - lovops - 03-16-2021

(03-14-2021, 04:57 PM)Vega Wrote: There isn't much to learn.

I went ahead and updated the thread that explains Hooktypes if that helps.

Where can I find a thread that mentions hoking?

RE: C0 Codetypes - Vega - 03-17-2021

A link is provided in Chapter 1.