Learn to decompile GameCube assembly into byte-matching C.
The Curriculum
Read the asm · write the C · the compiler grades it byte-for-byte.
0 / 264 matched
functions reconstructed
0
in progress
0
XP
Recruit
[](https://decomp-academy.dev/lesson/foundations-welcome "Your First Match")[](https://decomp-academy.dev/lesson/foundations-identity "Arguments Live in Registers Too")[](https://decomp-academy.dev/lesson/foundations-add "Adding Two Registers")[](https://decomp-academy.dev/lesson/foundations-subtract "Subtraction Reverses Its Operands")[](https://decomp-academy.dev/lesson/foundations-immediate "Immediates: Math With Constants")[](https://decomp-academy.dev/lesson/foundations-negate "Negation and the Zero Register")[](https://decomp-academy.dev/lesson/arithmetic-add-sub "An Add Then a Subtract")[](https://decomp-academy.dev/lesson/arithmetic-two-adds "Two Adds, Reassociated")[](https://decomp-academy.dev/lesson/arithmetic-sub-add "A Subtract Then an Add")[](https://decomp-academy.dev/lesson/arithmetic-add-sub-add "A Three-Instruction Chain")[](https://decomp-academy.dev/lesson/arithmetic-mul "Multiplying Two Registers")[](https://decomp-academy.dev/lesson/arithmetic-mul-const-pow2 "Multiply by a Power of Two")[](https://decomp-academy.dev/lesson/arithmetic-mul-const "Multiply by a Small Constant")[](https://decomp-academy.dev/lesson/arithmetic-affine "An Affine Expression")[](https://decomp-academy.dev/lesson/arithmetic-div-pow2-unsigned "Unsigned Divide by a Power of Two")[](https://decomp-academy.dev/lesson/arithmetic-div-pow2-signed "Signed Divide by a Power of Two")[](https://decomp-academy.dev/lesson/arithmetic-div-var "Real Division")[](https://decomp-academy.dev/lesson/arithmetic-mod "Modulo Has No Instruction")[](https://decomp-academy.dev/lesson/arithmetic-mul-add "Multiply Then Add")[](https://decomp-academy.dev/lesson/arithmetic-add-mul "Precedence Changes the Order")[](https://decomp-academy.dev/lesson/arithmetic-two-products "Two Products, Subtracted")[](https://decomp-academy.dev/lesson/arithmetic-mul-add-sub "A Three-Instruction Mixed Chain")[](https://decomp-academy.dev/lesson/arithmetic-scale-sum "When a Multiply Is a Shift")[](https://decomp-academy.dev/lesson/arithmetic-scale-chain "A Shift Inside a Mixed Chain")[](https://decomp-academy.dev/lesson/arithmetic-div-add "Divide Then Add")[](https://decomp-academy.dev/lesson/arithmetic-shrink-sum "When a Divide Is a Shift")[](https://decomp-academy.dev/lesson/arithmetic-shrink-chain "A Shift-Divide in a Chain")[](https://decomp-academy.dev/lesson/arithmetic-div-sub-mul "Divide and Multiply, Then Subtract")[](https://decomp-academy.dev/lesson/arithmetic-mul-add-div "Multiply and Divide Combined")[](https://decomp-academy.dev/lesson/arithmetic-all-four-ops "All Four Arithmetic Operators")[](https://decomp-academy.dev/lesson/bitwise-and-mask "Masking Bits With AND")[](https://decomp-academy.dev/lesson/bitwise-or "Combining Bits With OR")[](https://decomp-academy.dev/lesson/bitwise-xor "Flipping Bits With XOR")[](https://decomp-academy.dev/lesson/bitwise-set-flag "Setting a Single Flag Bit")[](https://decomp-academy.dev/lesson/bitwise-clear-flag "Clearing a Bit: The rlwinm Surprise")[](https://decomp-academy.dev/lesson/bitwise-test-bit "Testing Whether a Bit Is Set")[](https://decomp-academy.dev/lesson/bitwise-shift-left "Shifting Left by a Constant")[](https://decomp-academy.dev/lesson/bitwise-shift-right-unsigned "Logical Right Shift (Unsigned)")[](https://decomp-academy.dev/lesson/bitwise-shift-right-signed "Arithmetic Right Shift (Signed)")[](https://decomp-academy.dev/lesson/bitwise-shift-variable "Shifting by a Variable Amount")[](https://decomp-academy.dev/lesson/bitwise-extract-field "Extracting a Bitfield in One rlwinm")[](https://decomp-academy.dev/lesson/bitwise-shift-or-pack "Packing Two Values with a Shift and OR")[](https://decomp-academy.dev/lesson/bitwise-merge-fields "Merging Two Fields: rlwinm + rlwimi")[](https://decomp-academy.dev/lesson/bitwise-xor-chain "Chaining XOR Across Three Values")[](https://decomp-academy.dev/lesson/bitwise-bit-select "Bit Select (Mux): AND, ANDC, OR")[](https://decomp-academy.dev/lesson/bitwise-pack-three "Capstone: Pack Three Values into One Word")[](https://decomp-academy.dev/lesson/control-eq-bool "Returning a Comparison as a Bool")[](https://decomp-academy.dev/lesson/control-ne-bool "Not-Equal Is Its Own Idiom")[](https://decomp-academy.dev/lesson/control-if-else "If / Else: The Compare Feeds a Branch")[](https://decomp-academy.dev/lesson/control-sign-masks "Two's Complement, srawi, and andc by Hand")[](https://decomp-academy.dev/lesson/control-clamp-low "Clamping to Zero, Branchlessly")[](https://decomp-academy.dev/lesson/control-cmp-signed "Signed Compare: cmpw")[](https://decomp-academy.dev/lesson/control-cmp-unsigned "Unsigned Compare: cmplw")[](https://decomp-academy.dev/lesson/control-cmp-immediate "Comparing Against a Constant: cmpwi vs cmplwi")[](https://decomp-academy.dev/lesson/control-guard "The Guard Clause / Early Return")[](https://decomp-academy.dev/lesson/control-ternary-max "Ternary Max")[](https://decomp-academy.dev/lesson/control-ternary-min "Ternary Min")[](https://decomp-academy.dev/lesson/control-short-circuit "Short-Circuit && and ||")[](https://decomp-academy.dev/lesson/control-switch "Switch: The Compare Chain")[](https://decomp-academy.dev/lesson/control-clamp-range "Clamping Between Two Bounds")[](https://decomp-academy.dev/lesson/control-nested-ladder "The if / else-if Ladder")[](https://decomp-academy.dev/lesson/control-range-and "A Range Test with &&")[](https://decomp-academy.dev/lesson/control-reject-or "Rejecting Out-of-Range with ||")[](https://decomp-academy.dev/lesson/control-guard-or "A Multi-Condition Guard")[](https://decomp-academy.dev/lesson/control-capstone-clamp-step "Capstone: A Guarded, Clamped Update")[](https://decomp-academy.dev/lesson/loops-for-sum "The Anatomy of a Counted Loop")[](https://decomp-academy.dev/lesson/loops-while-equivalence "While Is the Same Loop")[](https://decomp-academy.dev/lesson/loops-do-while "Do-While: The Tightest Loop")[](https://decomp-academy.dev/lesson/loops-countdown "Counting Down Is Cheaper")[](https://decomp-academy.dev/lesson/loops-array-sum "Walking an Array by Index")[](https://decomp-academy.dev/lesson/loops-array-max "Finding the Maximum")[](https://decomp-academy.dev/lesson/loops-strlen "Walking a Pointer to a Sentinel")[](https://decomp-academy.dev/lesson/loops-break "Breaking Out Early")[](https://decomp-academy.dev/lesson/loops-anatomy-model "A Mental Model: The Five Parts of a Loop")[](https://decomp-academy.dev/lesson/loops-strength-reduction "Strength-Reduced Induction")[](https://decomp-academy.dev/lesson/loops-weighted-sum "A Loop With More Work Inside")[](https://decomp-academy.dev/lesson/loops-nested "Nested Loops")[](https://decomp-academy.dev/lesson/loops-grid-sum "Nesting Over a 2-D Array")[](https://decomp-academy.dev/lesson/loops-triangular "When the Inner Bound Follows the Outer")[](https://decomp-academy.dev/lesson/loops-inversions "Capstone: Counting Pairs in a Grid Scan")[](https://decomp-academy.dev/lesson/types-load-u8 "Loading a Byte")[](https://decomp-academy.dev/lesson/types-load-u16 "Loading a Halfword")[](https://decomp-academy.dev/lesson/types-load-signed "Signed Loads Sign-Extend")[](https://decomp-academy.dev/lesson/types-store-byte "Storing a Byte Truncates")[](https://decomp-academy.dev/lesson/types-store-half "Storing a Halfword")[](https://decomp-academy.dev/lesson/types-u8-not-char "u8, Not char (The Spurious extsb)")[](https://decomp-academy.dev/lesson/types-widen-zero-vs-sign "Widening: Zero vs Sign Extend")[](https://decomp-academy.dev/lesson/types-truncate-mask "Truncating With a Mask")[](https://decomp-academy.dev/lesson/types-explicit-cast "Casts That Sign-Extend")[](https://decomp-academy.dev/lesson/types-cast-between-signed "Casting Between Signed Widths")[](https://decomp-academy.dev/lesson/types-compare-width "The Compare Opcode Follows the Type")[](https://decomp-academy.dev/lesson/types-counter-increment "Bumping a Byte Counter")[](https://decomp-academy.dev/lesson/types-rmw-scale "Read, Scale, Truncate")[](https://decomp-academy.dev/lesson/types-rmw-half "A Signed Halfword Read-Modify-Write")[](https://decomp-academy.dev/lesson/types-mix-widths "Combining Two Widths")[](https://decomp-academy.dev/lesson/types-mix-signs "Mixed Signedness in One Expression")[](https://decomp-academy.dev/lesson/types-capstone "Capstone: Widths and Signs in One Function")[](https://decomp-academy.dev/lesson/pointers-deref "Dereferencing a Pointer")[](https://decomp-academy.dev/lesson/pointers-store "Storing Through a Pointer")[](https://decomp-academy.dev/lesson/pointers-index-const "A Constant Index Becomes a Displacement")[](https://decomp-academy.dev/lesson/pointers-store-index-const "Writing at a Constant Index")[](https://decomp-academy.dev/lesson/pointers-arith "Pointer Arithmetic Is Scaled")[](https://decomp-academy.dev/lesson/pointers-index-var "A Variable Index Needs Scaling Then Indexing")[](https://decomp-academy.dev/lesson/pointers-u8-array "Byte Arrays Need No Shift")[](https://decomp-academy.dev/lesson/pointers-u16-array "Halfword Arrays Shift by One")[](https://decomp-academy.dev/lesson/pointers-strlen "Walking a String")[](https://decomp-academy.dev/lesson/pointers-compare "Comparing Two Pointers")[](https://decomp-academy.dev/lesson/pointers-null-check "Guarding Against NULL")[](https://decomp-academy.dev/lesson/pointers-swap "Swapping Through Pointers")[](https://decomp-academy.dev/lesson/pointers-sum-two "Reading Two Elements and Combining Them")[](https://decomp-academy.dev/lesson/pointers-weighted-elements "Scaling One Element Before Combining")[](https://decomp-academy.dev/lesson/pointers-deref-then-compute "Dereference, Then Compute With an Argument")[](https://decomp-academy.dev/lesson/pointers-computed-offset "Indexing Neighbors From a Computed Offset")[](https://decomp-academy.dev/lesson/pointers-two-arrays "Combining Two Arrays at the Same Index")[](https://decomp-academy.dev/lesson/pointers-capstone "Capstone: Several Dereferences in One Expression")[](https://decomp-academy.dev/lesson/structs-read-field "Reading a Struct Field")[](https://decomp-academy.dev/lesson/structs-write-field "Writing a Struct Field")[](https://decomp-academy.dev/lesson/structs-narrow-read "Narrow Fields: Byte and Halfword Loads")[](https://decomp-academy.dev/lesson/structs-narrow-write "Storing a Byte Field")[](https://decomp-academy.dev/lesson/structs-padding "Alignment Padding Shifts an Offset")[](https://decomp-academy.dev/lesson/structs-sum-fields "Combining Two Fields")[](https://decomp-academy.dev/lesson/structs-combine-fields "Computing Across Three Fields")[](https://decomp-academy.dev/lesson/structs-nested "Nested Structs Flatten to One Offset")[](https://decomp-academy.dev/lesson/structs-struct-of-structs "Combining Fields Across Nested Structs")[](https://decomp-academy.dev/lesson/structs-array-index "Arrays of Structs: Scaling the Index")[](https://decomp-academy.dev/lesson/structs-array-field "An Array Inside a Struct")[](https://decomp-academy.dev/lesson/structs-union "Unions Overlay the Same Bytes")[](https://decomp-academy.dev/lesson/structs-bitfield-set "A Single-Bit Flag: li; rlwimi")[](https://decomp-academy.dev/lesson/structs-bitfield-multi "Multi-Bit Bitfield Writes")[](https://decomp-academy.dev/lesson/structs-bitfield-read "Reading a Bitfield: rlwinm Extract")[](https://decomp-academy.dev/lesson/structs-linked-list "Walking a Linked List")[](https://decomp-academy.dev/lesson/structs-function-pointer "Calling Through a Function Pointer")[](https://decomp-academy.dev/lesson/structs-copy-whole "Copying a Whole Struct")[](https://decomp-academy.dev/lesson/structs-copy-aligned "Eight-Byte Alignment Copies Through Float Registers")[](https://decomp-academy.dev/lesson/structs-copy-large "Big Structs Copy in a Loop")[](https://decomp-academy.dev/lesson/structs-copy-chain "Combining a Copy With a Field Update")[](https://decomp-academy.dev/lesson/structs-capstone "Capstone: Reading a Whole Struct")[](https://decomp-academy.dev/lesson/floats-add "Floats Live in a Different Register File")[](https://decomp-academy.dev/lesson/floats-mul "Single-Precision Multiply")[](https://decomp-academy.dev/lesson/floats-sub "Subtraction Keeps Its Order")[](https://decomp-academy.dev/lesson/floats-div "Floating-Point Division Is Real")[](https://decomp-academy.dev/lesson/floats-div-const-reciprocal "Dividing by a Constant Becomes a Multiply")[](https://decomp-academy.dev/lesson/floats-double-add "Doubles Drop the 's'")[](https://decomp-academy.dev/lesson/floats-frsp-highlight "★ The Spurious frsp: f32 vs double Helpers")[](https://decomp-academy.dev/lesson/floats-literal "Loading a Float Constant from the SDA")[](https://decomp-academy.dev/lesson/floats-fmadds-highlight "★ Fused Multiply-Add")[](https://decomp-academy.dev/lesson/floats-int-to-float "Integer to Float: The Magic-Number Trick")[](https://decomp-academy.dev/lesson/floats-float-to-int "Float to Int: fctiwz and the Store/Load Dance")[](https://decomp-academy.dev/lesson/floats-compare-branch "Comparing Floats: fcmpo Feeding a Branch")[](https://decomp-academy.dev/lesson/floats-abs-neg "Absolute Value and Negation")[](https://decomp-academy.dev/lesson/floats-two-adds "Chaining Two Float Adds")[](https://decomp-academy.dev/lesson/floats-add-then-subtract "Mixing Add and Subtract in One Chain")[](https://decomp-academy.dev/lesson/floats-weighted-sum "A Weighted Sum Folds Into One fmadds")[](https://decomp-academy.dev/lesson/floats-lerp "The Lerp Idiom — fsubs Feeding fmadds")[](https://decomp-academy.dev/lesson/floats-dot-product-2d "Two Products Summed — the 2D Dot Product")[](https://decomp-academy.dev/lesson/floats-dot-product-3d "Accumulating Three Products — the 3D Dot Product")[](https://decomp-academy.dev/lesson/floats-max-via-compare "Picking the Larger: fcmpo + Conditional fmr")[](https://decomp-academy.dev/lesson/floats-two-sided-clamp "Clamping Between Two Constants")[](https://decomp-academy.dev/lesson/floats-f32-f64-mixing "Mixing f32 and f64 — Double Math, then frsp")[](https://decomp-academy.dev/lesson/floats-capstone-approach "★ Capstone: A Float Step With a Clamp")[](https://decomp-academy.dev/lesson/finale-scale-then-clamp "Scale, Then Clamp")[](https://decomp-academy.dev/lesson/finale-real-global-carry-chain "A 64-bit Global Accumulator")[](https://decomp-academy.dev/lesson/finale-masked-guarded-sum "A Masked, Guarded Accumulator")[](https://decomp-academy.dev/lesson/finale-real-framed-global-clamp "Call, Read a Global, Clamp")[](https://decomp-academy.dev/lesson/finale-build-a-bitmask "Building a Bitmask in a Loop")[](https://decomp-academy.dev/lesson/finale-real-scheduled-global-fmadds "Globals, Literals, and the Scheduler")[](https://decomp-academy.dev/lesson/finale-struct-field-sum-clamp "Sum a Struct Field, Then Clamp")[](https://decomp-academy.dev/lesson/finale-real-jumptable-volatile-dispatch "★ A Jump-Table of Volatile Reads")[](https://decomp-academy.dev/lesson/finale-guarded-float-accumulate "A Guarded Float Accumulator")[](https://decomp-academy.dev/lesson/finale-real-downcast-clamp-finale "★ 64-bit Globals, Downcast, Clamp")[](https://decomp-academy.dev/lesson/abi-arg-registers "The Integer Argument Registers")[](https://decomp-academy.dev/lesson/abi-fifth-arg "Reaching the Fifth Argument")[](https://decomp-academy.dev/lesson/abi-float-args "Floats Use Their Own Registers")[](https://decomp-academy.dev/lesson/abi-leaf-function "A Leaf Has No Stack Frame")[](https://decomp-academy.dev/lesson/abi-stack-frame "The Stack Frame and the Link Register")[](https://decomp-academy.dev/lesson/abi-arg-marshalling "Marshalling Arguments for a Call")[](https://decomp-academy.dev/lesson/abi-saved-registers "Surviving a Call: Saved Registers")[](https://decomp-academy.dev/lesson/abi-declaration-order "Declaration Order Colors the Registers")[](https://decomp-academy.dev/lesson/abi-tail-call "Returning a Called Result Directly")[](https://decomp-academy.dev/lesson/abi-stack-args "When Arguments Spill to the Stack")[](https://decomp-academy.dev/lesson/abi-keep-and-call "Chaining: Keep a Value, Marshal the Rest")[](https://decomp-academy.dev/lesson/abi-pipe-through "Chaining: Pipe One Call's Result Into the Next")[](https://decomp-academy.dev/lesson/abi-two-survivors-call "Chaining: Two Survivors Feeding a Final Call")[](https://decomp-academy.dev/lesson/abi-finale "Chaining: The Whole ABI in One Function")[](https://decomp-academy.dev/lesson/globals-read-int "Reading a Global Through the Small Data Area")[](https://decomp-academy.dev/lesson/globals-write-int "Writing a Global")[](https://decomp-academy.dev/lesson/globals-narrow-type "The Opcode Follows the Type")[](https://decomp-academy.dev/lesson/globals-read-float "A Global Float and the Second Small Data Area")[](https://decomp-academy.dev/lesson/globals-float-literal "Float Literals Become Pooled Constants")[](https://decomp-academy.dev/lesson/globals-address-of "Taking an Address: SDA li vs. the @ha/@l Pair")[](https://decomp-academy.dev/lesson/globals-array-index "Indexing a Global Array")[](https://decomp-academy.dev/lesson/globals-read-compute-write "Read Two Globals, Compute, Write Back")[](https://decomp-academy.dev/lesson/globals-float-global-literal "A Float Global Times a Pooled Literal")[](https://decomp-academy.dev/lesson/globals-scale-narrow-store "Read Wide, Store Narrow")[](https://decomp-academy.dev/lesson/globals-array-store "Writing Into a Global Array")[](https://decomp-academy.dev/lesson/globals-array-index-narrow "Index an Array, Narrow the Result")[](https://decomp-academy.dev/lesson/globals-array-rmw-scalar "Read-Modify-Write an Array Element")[](https://decomp-academy.dev/lesson/globals-float-array-literal-scalar "★ A Float Array Element, Scaled Into a Global")[](https://decomp-academy.dev/lesson/globals-capstone "★ Capstone: A Lighting-Update Function")[](https://decomp-academy.dev/lesson/optimization-o4p "What -O4,p Actually Does")[](https://decomp-academy.dev/lesson/optimization-scheduling "Instruction Scheduling: Hiding Latency")[](https://decomp-academy.dev/lesson/optimization-peephole-merge "The Peephole Optimizer: Dot-Form Merging")[](https://decomp-academy.dev/lesson/optimization-peephole-off "#pragma peephole off: Unfusing the Merge")[](https://decomp-academy.dev/lesson/optimization-scheduling-off "#pragma scheduling off: Freezing the Order")[](https://decomp-academy.dev/lesson/optimization-fp-scheduling "Scheduling Floating-Point Work")[](https://decomp-academy.dev/lesson/optimization-fp-contract "fp_contract: Fused Multiply-Add")[](https://decomp-academy.dev/lesson/optimization-strength-reduction "Strength Reduction in a Loop")[](https://decomp-academy.dev/lesson/optimization-cse "Common-Subexpression Elimination")[](https://decomp-academy.dev/lesson/optimization-cse-strength "Chaining: CSE Feeds Strength Reduction")[](https://decomp-academy.dev/lesson/optimization-schedule-peephole "Chaining: Scheduling Plus a Dot-Merge")[](https://decomp-academy.dev/lesson/optimization-fp-dot-chain "Chaining: FP Scheduling and fp_contract at Arity Three")[](https://decomp-academy.dev/lesson/optimization-fp-cse-contract "Chaining: A Reused Product Inside a Fused Multiply-Add")[](https://decomp-academy.dev/lesson/optimization-capstone "Capstone: Scheduling Meets fp_contract")[](https://decomp-academy.dev/lesson/advanced-switch-jumptable "Switch: The Jump Table")[](https://decomp-academy.dev/lesson/advanced-switch-decision "Table or Chain? The Density Rule")[](https://decomp-academy.dev/lesson/advanced-psq-callee-save "Paired-Single FPR Saves in the Prologue")[](https://decomp-academy.dev/lesson/advanced-psq-asm-exception "Where Inline asm{} Earns Its Place: psq_l / psq_st")[](https://decomp-academy.dev/lesson/advanced-enum-sizing "Enums Are int-Sized: Recovery Is Naming")[](https://decomp-academy.dev/lesson/advanced-volatile-cse "Volatile Defeats CSE: Two Reads, Two Loads")[](https://decomp-academy.dev/lesson/advanced-volatile-hwreg "Volatile Hardware Registers")[](https://decomp-academy.dev/lesson/advanced-enum-jumptable "Chain: An Enum Switched Through the Table")[](https://decomp-academy.dev/lesson/advanced-hwreg-switch "Chain: Switch on a Hardware Register")[](https://decomp-academy.dev/lesson/advanced-enum-volatile-guard "Chain: Enum Guard, Then a Volatile Sum")[](https://decomp-academy.dev/lesson/advanced-state-machine "Capstone: A Volatile-Guarded Enum State Machine")[](https://decomp-academy.dev/lesson/advanced-psq-switch-combine "Capstone II: Saved Floats Dispatched Through a Switch")[](https://decomp-academy.dev/lesson/int64-register-pairing "Two Registers Make a long long")[](https://decomp-academy.dev/lesson/int64-add "Adding 64-bit Integers (addc / adde)")[](https://decomp-academy.dev/lesson/int64-sub "Subtracting 64-bit Integers (subfc / subfe)")[](https://decomp-academy.dev/lesson/int64-register-alignment "The Odd-Register Alignment Rule")[](https://decomp-academy.dev/lesson/int64-downcast "The Downcast Fingerprint")[](https://decomp-academy.dev/lesson/int64-multiply "Multiplying 64-bit Integers")[](https://decomp-academy.dev/lesson/int64-divide "Division Calls an Intrinsic")[](https://decomp-academy.dev/lesson/int64-shift "Shifts Call an Intrinsic Too")[](https://decomp-academy.dev/lesson/int64-bitwise "Bitwise Ops Are Just Two Halves")[](https://decomp-academy.dev/lesson/int64-compare "Comparing 64-bit Integers")[](https://decomp-academy.dev/lesson/int64-carry-then-borrow "Chaining: Carry Into a Borrow")[](https://decomp-academy.dev/lesson/int64-bitwise-then-add "Chaining: A Bitwise Pair Feeds a Carry Chain")[](https://decomp-academy.dev/lesson/int64-downcast-chain "Chaining: A Downcast Prunes the Chain")[](https://decomp-academy.dev/lesson/int64-sum-then-compare "Chaining: A Sum Feeds a 64-bit Compare")[](https://decomp-academy.dev/lesson/int64-three-stage-fuse "Chaining: Carry, Borrow, and Mask in One Body")[](https://decomp-academy.dev/lesson/finale-scale-then-clamp "Scale, Then Clamp")[](https://decomp-academy.dev/lesson/finale-real-global-carry-chain "A 64-bit Global Accumulator")[](https://decomp-academy.dev/lesson/finale-masked-guarded-sum "A Masked, Guarded Accumulator")[](https://decomp-academy.dev/lesson/finale-real-framed-global-clamp "Call, Read a Global, Clamp")[](https://decomp-academy.dev/lesson/finale-build-a-bitmask "Building a Bitmask in a Loop")[](https://decomp-academy.dev/lesson/finale-real-scheduled-global-fmadds "Globals, Literals, and the Scheduler")[](https://decomp-academy.dev/lesson/finale-struct-field-sum-clamp "Sum a Struct Field, Then Clamp")[](https://decomp-academy.dev/lesson/finale-real-jumptable-volatile-dispatch "★ A Jump-Table of Volatile Reads")[](https://decomp-academy.dev/lesson/finale-guarded-float-accumulate "A Guarded Float Accumulator")[](https://decomp-academy.dev/lesson/finale-real-downcast-clamp-finale "★ 64-bit Globals, Downcast, Clamp")[](https://decomp-academy.dev/lesson/mastery-spellstone-setstate "A Real Setter: State, a Float Nudge, and a Boolean Return")[](https://decomp-academy.dev/lesson/mastery-fueltank-apply "Copying a Position With a Bias")[](https://decomp-academy.dev/lesson/mastery-fueltank-tick "A Flag Toggle Behind a Helper Call")[](https://decomp-academy.dev/lesson/mastery-clamp-health "Clamping a Float Into Range")[](https://decomp-academy.dev/lesson/mastery-cloudrace-oncomplete "A Loop Over an Event Array")[](https://decomp-academy.dev/lesson/mastery-asteroid-orbit "Orbital Math: fmadds, fdivs, and Saved Float Registers")[](https://decomp-academy.dev/lesson/mastery-race-advance "A Phase State Machine")[](https://decomp-academy.dev/lesson/mastery-spellstone-step "A Per-Frame Update: Rotation, a Flag, and a Branch")[](https://decomp-academy.dev/lesson/mastery-tank-hitdetect "Guarded Hit Detection: NULL Chains and a Type Check")[](https://decomp-academy.dev/lesson/mastery-mine-reset "The Capstone: A Full Reset-to-Idle")[](https://decomp-academy.dev/lesson/mastery-tumbler-integratespin "peephole off: When You Must Write the (s16) Cast Yourself")[](https://decomp-academy.dev/lesson/mastery-voxmap-choosedir "Two Running Sums, Woven by Hand: Steering the ,p Scheduler")[](https://decomp-academy.dev/lesson/mastery-targetblock-scorehit "Param Inversion: Who Gets the Saved Register")[](https://decomp-academy.dev/lesson/mastery-blend-accumulate "Declaration Order Is Register Order: Coloring Saved Regs by Hand")
Solved Attempted Not started Concept (reading) Difficulty 1–5
I
Warm-up
Learn to read the machine
0/6
1
Foundations Continue here
What decompilation is, PowerPC registers, and reading MWCC output.
\~30m0/6
Your First MatchResumeArguments Live in Registers TooAdding Two RegistersSubtraction Reverses Its OperandsImmediates: Math With ConstantsNegation and the Zero Register
II
Core idioms
Every shape C compiles into
0/164
2
Integer Arithmetic
Add, subtract, multiply, divide, immediates and the bit-twiddling idioms.
\~164m0/24
An Add Then a SubtractTwo Adds, ReassociatedA Subtract Then an AddA Three-Instruction ChainMultiplying Two RegistersMultiply by a Power of TwoMultiply by a Small ConstantAn Affine ExpressionUnsigned Divide by a Power of TwoSigned Divide by a Power of TwoReal DivisionModulo Has No InstructionMultiply Then AddPrecedence Changes the OrderTwo Products, SubtractedA Three-Instruction Mixed ChainWhen a Multiply Is a ShiftA Shift Inside a Mixed ChainDivide Then AddWhen a Divide Is a ShiftA Shift-Divide in a ChainDivide and Multiply, Then SubtractMultiply and Divide CombinedAll Four Arithmetic Operators
3
Bitwise & Shifts
AND/OR/XOR, masks, shifts, and the rlwinm family MWCC loves.
\~122m0/16
Masking Bits With ANDCombining Bits With ORFlipping Bits With XORSetting a Single Flag BitClearing a Bit: The rlwinm SurpriseTesting Whether a Bit Is SetShifting Left by a ConstantLogical Right Shift (Unsigned)Arithmetic Right Shift (Signed)Shifting by a Variable AmountExtracting a Bitfield in One rlwinmPacking Two Values with a Shift and ORMerging Two Fields: rlwinm + rlwimiChaining XOR Across Three ValuesBit Select (Mux): AND, ANDC, ORCapstone: Pack Three Values into One Word
4
Control Flow
if/else, ternaries, switch, and the all-important signed-vs-unsigned compare.
\~151m0/19
Returning a Comparison as a BoolNot-Equal Is Its Own IdiomIf / Else: The Compare Feeds a BranchTwo's Complement, srawi, and andc by HandConceptClamping to Zero, BranchlesslySigned Compare: cmpwUnsigned Compare: cmplwComparing Against a Constant: cmpwi vs cmplwiThe Guard Clause / Early ReturnTernary MaxTernary MinShort-Circuit && and ||Switch: The Compare ChainClamping Between Two BoundsThe if / else-if LadderA Range Test with &&Rejecting Out-of-Range with ||A Multi-Condition GuardCapstone: A Guarded, Clamped Update
5
Loops
for, while, do-while, induction variables and counted loops.
\~125m0/15
The Anatomy of a Counted LoopWhile Is the Same LoopDo-While: The Tightest LoopCounting Down Is CheaperWalking an Array by IndexFinding the MaximumWalking a Pointer to a SentinelBreaking Out EarlyA Mental Model: The Five Parts of a LoopConceptStrength-Reduced InductionA Loop With More Work InsideNested LoopsNesting Over a 2-D ArrayWhen the Inner Bound Follows the OuterCapstone: Counting Pairs in a Grid Scan
6
Types & Width
u8/s8/u16/s16 loads, sign vs zero extension, and width-driven matching, building up to mixed-width and mixed-sign expressions.
\~141m0/17
Loading a ByteLoading a HalfwordSigned Loads Sign-ExtendStoring a Byte TruncatesStoring a Halfwordu8, Not char (The Spurious extsb)Widening: Zero vs Sign ExtendTruncating With a MaskCasts That Sign-ExtendCasting Between Signed WidthsThe Compare Opcode Follows the TypeBumping a Byte CounterRead, Scale, TruncateA Signed Halfword Read-Modify-WriteCombining Two WidthsMixed Signedness in One ExpressionCapstone: Widths and Signs in One Function
7
Pointers & Memory
Loads and stores, addressing modes, pointer arithmetic and arrays.
\~148m0/18
Dereferencing a PointerStoring Through a PointerA Constant Index Becomes a DisplacementWriting at a Constant IndexPointer Arithmetic Is ScaledA Variable Index Needs Scaling Then IndexingByte Arrays Need No ShiftHalfword Arrays Shift by OneWalking a StringComparing Two PointersGuarding Against NULLSwapping Through PointersReading Two Elements and Combining ThemScaling One Element Before CombiningDereference, Then Compute With an ArgumentIndexing Neighbors From a Computed OffsetCombining Two Arrays at the Same IndexCapstone: Several Dereferences in One Expression
8
Structs, Unions & Bitfields
From single fields up to combining several across nested structs, member arrays, unions, and bitfields.
\~168m0/22
Reading a Struct FieldWriting a Struct FieldNarrow Fields: Byte and Halfword LoadsStoring a Byte FieldAlignment Padding Shifts an OffsetCombining Two FieldsComputing Across Three FieldsNested Structs Flatten to One OffsetCombining Fields Across Nested StructsArrays of Structs: Scaling the IndexAn Array Inside a StructUnions Overlay the Same BytesA Single-Bit Flag: li; rlwimiMulti-Bit Bitfield WritesReading a Bitfield: rlwinm ExtractWalking a Linked ListCalling Through a Function PointerCopying a Whole StructEight-Byte Alignment Copies Through Float RegistersBig Structs Copy in a LoopCombining a Copy With a Field UpdateCapstone: Reading a Whole Struct
9
Floating Point
f32 vs f64, frsp, fused multiply-add, and float comparisons.
\~183m0/23
Floats Live in a Different Register FileSingle-Precision MultiplySubtraction Keeps Its OrderFloating-Point Division Is RealDividing by a Constant Becomes a MultiplyDoubles Drop the 's'★ The Spurious frsp: f32 vs double HelpersLoading a Float Constant from the SDA★ Fused Multiply-AddInteger to Float: The Magic-Number TrickFloat to Int: fctiwz and the Store/Load DanceComparing Floats: fcmpo Feeding a BranchAbsolute Value and NegationChaining Two Float AddsMixing Add and Subtract in One ChainA Weighted Sum Folds Into One fmaddsThe Lerp Idiom — fsubs Feeding fmaddsTwo Products Summed — the 2D Dot ProductAccumulating Three Products — the 3D Dot ProductPicking the Larger: fcmpo + Conditional fmrClamping Between Two ConstantsMixing f32 and f64 — Double Math, then frsp★ Capstone: A Float Step With a Clamp
10
Putting It Together
Whole functions that combine arithmetic, bits, control, loops, types, pointers and structs into one realistic body.
\~98m0/10
Scale, Then ClampA 64-bit Global AccumulatorA Masked, Guarded AccumulatorCall, Read a Global, ClampBuilding a Bitmask in a LoopGlobals, Literals, and the SchedulerSum a Struct Field, Then Clamp★ A Jump-Table of Volatile ReadsA Guarded Float Accumulator★ 64-bit Globals, Downcast, Clamp
III
The real ABI
Frames, globals, optimizer, 64-bit
0/80
11
Functions & the ABI
Arg registers, saved registers, stack frames and declaration-order coloring.
\~118m0/14
The Integer Argument RegistersReaching the Fifth ArgumentFloats Use Their Own RegistersA Leaf Has No Stack FrameThe Stack Frame and the Link RegisterMarshalling Arguments for a CallSurviving a Call: Saved RegistersDeclaration Order Colors the RegistersReturning a Called Result DirectlyWhen Arguments Spill to the StackChaining: Keep a Value, Marshal the RestChaining: Pipe One Call's Result Into the NextChaining: Two Survivors Feeding a Final CallChaining: The Whole ABI in One Function
12
Globals, the SDA & Pools
r13/r2 small-data addressing, @sda21/@ha/@l relocations, and rodata pools.
\~145m0/15
Reading a Global Through the Small Data AreaWriting a GlobalThe Opcode Follows the TypeA Global Float and the Second Small Data AreaFloat Literals Become Pooled ConstantsTaking an Address: SDA li vs. the @ha/@l PairIndexing a Global ArrayRead Two Globals, Compute, Write BackA Float Global Times a Pooled LiteralRead Wide, Store NarrowWriting Into a Global ArrayIndex an Array, Narrow the ResultRead-Modify-Write an Array Element★ A Float Array Element, Scaled Into a Global★ Capstone: A Lighting-Update Function
13
Optimization & Scheduling
\-O4,p, peephole, instruction scheduling, and the pragmas that bend them.
\~142m0/14
What -O4,p Actually DoesInstruction Scheduling: Hiding LatencyThe Peephole Optimizer: Dot-Form Merging#pragma peephole off: Unfusing the Merge#pragma scheduling off: Freezing the OrderScheduling Floating-Point Workfp\_contract: Fused Multiply-AddStrength Reduction in a LoopCommon-Subexpression EliminationChaining: CSE Feeds Strength ReductionChaining: Scheduling Plus a Dot-MergeChaining: FP Scheduling and fp\_contract at Arity ThreeChaining: A Reused Product Inside a Fused Multiply-AddCapstone: Scheduling Meets fp\_contract
14
Advanced Idioms
Paired-singles, switch jump tables, enums, and volatile — the master's toolkit.
\~128m0/12
Switch: The Jump TableTable or Chain? The Density RulePaired-Single FPR Saves in the PrologueWhere Inline asm{} Earns Its Place: psq\_l / psq\_stEnums Are int-Sized: Recovery Is NamingVolatile Defeats CSE: Two Reads, Two LoadsVolatile Hardware RegistersChain: An Enum Switched Through the TableChain: Switch on a Hardware RegisterChain: Enum Guard, Then a Volatile SumCapstone: A Volatile-Guarded Enum State MachineCapstone II: Saved Floats Dispatched Through a Switch
15
64-bit Integers
long long across two registers — carry chains, ABI pairing, downcast fingerprints, and intrinsics.
\~125m0/15
Two Registers Make a long longConceptAdding 64-bit Integers (addc / adde)Subtracting 64-bit Integers (subfc / subfe)The Odd-Register Alignment RuleThe Downcast FingerprintMultiplying 64-bit IntegersDivision Calls an IntrinsicShifts Call an Intrinsic TooBitwise Ops Are Just Two HalvesComparing 64-bit IntegersChaining: Carry Into a BorrowChaining: A Bitwise Pair Feeds a Carry ChainChaining: A Downcast Prunes the ChainChaining: A Sum Feeds a 64-bit CompareChaining: Carry, Borrow, and Mask in One Body
16
The Whole ABI at Once
Whole realistic function bodies that fuse frames, globals, the optimizer, and 64-bit work — every chapter of the tier converging in one symbol.
\~98m0/10
Scale, Then ClampA 64-bit Global AccumulatorA Masked, Guarded AccumulatorCall, Read a Global, ClampBuilding a Bitmask in a LoopGlobals, Literals, and the SchedulerSum a Struct Field, Then Clamp★ A Jump-Table of Volatile ReadsA Guarded Float Accumulator★ 64-bit Globals, Downcast, Clamp
IV
Proving ground
Real Star Fox Adventures functions, start to finish
0/14
17
Real-World Mastery
Authentic Star Fox Adventures functions, from warm-ups to full capstones.
\~162m0/14
A Real Setter: State, a Float Nudge, and a Boolean ReturnCopying a Position With a BiasA Flag Toggle Behind a Helper CallClamping a Float Into RangeA Loop Over an Event ArrayOrbital Math: fmadds, fdivs, and Saved Float RegistersA Phase State MachineA Per-Frame Update: Rotation, a Flag, and a BranchGuarded Hit Detection: NULL Chains and a Type CheckThe Capstone: A Full Reset-to-Idlepeephole off: When You Must Write the (s16) Cast YourselfTwo Running Sums, Woven by Hand: Steering the ,p SchedulerParam Inversion: Who Gets the Saved RegisterDeclaration Order Is Register Order: Coloring Saved Regs by Hand
