Cheat Code

From Custom Mario Kart
Jump to: navigation, search

In Wii and GameCube modding, the words Cheat Code normally refers to GCT (Gecko Code Type) code. GCT code takes the form of a series of variable length instructions which are run every frame during game play.

Format and Behaviour

GCT codes take the form of a series of variable length instructions which are run every frame during game play by a Gecko interpreter. Each instruction is a multiple of 64 bits so the codes are usually presented in hexadecimal with 64 bits per line divided evenly into two columns. This must be converted directly to the equivalent binary representation to form the .gct file used by most interpreters. For example:

048a5b30 00000000

To use a GCT, the loader patches the program (game) to add a 'hook'. This amounts to inserting a branch from the game's Assembly Code to the GCT interpreter which resides in an unused area of RAM, typically address 0x80002800 on Wii. Commonly the branch leaves the game's VISetNextFrameBuffer method at the blr (return) instruction, which is called a "VI Hook". This therefore causes the interpreter to run once per frame. The interpreter then locates the GCT code and executes each instruction in it sequentially. Most instructions are 64 bits but some are longer. Some instructions affect the control flow of the interpreter, for example only executing the next instruction if a condition is met. When the interpreter reaches the exit instruction, it returns to the game by executing the blr instruction that was replaced.

Registers

Addresses in GCT codes are relative to either ba or po which are two registers maintained by the interpreter. ba means Base Address and is always reset to address 0x80000000 at the start of the GCT code. This is the logical address at the start of RAM meaning that barelative codes typically correspond to absolute logical addresses. Codes are expected to reset ba to 0x80000000 if they modify it. po means Pointer and is also reset to 0x80000000 at the start of the GCT code. po is not typically reset when modified so codes should not rely on it having any particular value.

Instructions

The format of instructions is an 7 bit opcode, followed by arguments. Some of the common instructions are described here. For more complete documentation see geckocodes.org. Opcodes are commonly presented shifted left by 1 bit as this is similar to how they appear in the hexadecimal code, making them easier to recognize.

04 / 05 - 32 bit Write

Opcode 04 / 04 signifies a 32 bit write. This is commonly used for setting values. 04XXXXXX YYYYYYYY instructs the interpreter to write the 32 bit value YYYYYYYY at address ba + X & 0x1FFFFFF where X and Y are placeholders for hexadecimal constants. Note that the constant X includes the bottom bit of the first byte.

C0 - Execute ASM

Opcode C0 causes the interpreter to execute the ASM contained in this instruction which must end with a blr. C0000000 NNNNNNNN causes the interpreter to branch to the start of this instruction's payload. This instruction is variable length and the constant NNNNNNNN counts how many 64 bit values follow this instruction. These values are ignored by the interpreter but are executed as ASM due to the branch. The last ASM instruction of the payload must be a blr instruction to return to the interpreter. Therefore the last 64 bits of the payload are typically either 4e800020 00000000 or XXXXXXXX 4e800020.

C2 / C3 - Insert ASM

Opcode C2 / C3 causes the interpreter to patch a branch from the game's ASM to the ASM contained in this instruction and puts branch back after the instructions have executed. C2XXXXXX NNNNNNNN causes the interpreter to write a branch at address ba + X & 0x1FFFFFF to the start of this instruction's payload. This instruction is variable length and the constant NNNNNNNN counts how many 64 bit values follow this instruction. These values are ignored by the interpreter but are executed as ASM due to the branch. The last 32 bits are overwritten by the interpreter with the return branch back to the original instruction after the inserted branch and is usually 00000000 or 60000000 (nop)

F0 - End of Code

Opcode F0 signifies the end of codes, and causes the interpreter to return to the game. The remaining 57 bits should all be 0. Ordinary codes should not contain this instruction, it is typically inserted automatically by the GCT file creator after all codes the user is combining.

Criticism

GCT code has been criticized for being intentionally hard to read and understand, possibly to make it hard to reverse engineer and therefore encourage the purchase of magazines containing cheat codes. It lacks a high level representation, with most programmers writing the GCT code directly in hexadecimal. In practise most GCT code creators therefore only use a tiny fraction of its instructions, preferring to work in ASM. The timing of the code running is also ambiguous which can make writing precise codes hard. On the other hand, GCT code is very convenient quick to experiment with. It is also well standardized and there are many loaders which allow GCT patching of games, where few offer direct ASM manipulation. Another criticism is the maximum length; most interpreters have a hidden maximum input size after which they corrupt game instructions and generally crash. This makes GCT codes unsuitable for large modding projects or complex codes. This size restriction is not necessarily the same between all loaders causing portability issues.

Tools

The following tools deal with GCT codes.

  • Wiimm's SZS Tools can patch main.dol to include a GCT file directly. They are able to manage large cheat codes (up to 900K; limited by free BSS space) by moving them at the end of the heap. However, the heap size is reduced by the cheat code size.