# Strat VM opcodes (groove.exe, "Argonaut Strategy Language") Machine-readable tables (the source of the editor's names and help): `src/main/resources/com/eliasmueller/llamamod/format/strat/ops.tsv` (opcodes) and `props.tsv` (strat properties). Language/syntax: `notes/strat-language.md`. Disassembler/assembler: `format.strat`. ## Summary * **434 opcodes** (0x000–0x1b1; 0x00–0x44 "short" with a signed 16-bit argument in the high half of the word, 0x45+ "long" with inline operand words). All of them have a name and a one-line semantics from reading every handler (headless Ghidra decompile of the two handler tables 0x5796bc / 0x578ff4, plus the helpers they call). * Confidence: **353 high, 79 medium, 2 low**. Of the **222 opcodes the 34 level WADs use**: 177 high, 44 medium, 1 low; high-confidence opcodes cover **97.3 %** of the 556314 instructions in the levels. * **Low-confidence review (2026-11-07)**: all 34 former low opcodes re-read (handler table entry checked against the exe, Ghidra decompile of handler + callees, `objdump` of the exe where Ghidra's C was incomplete – e.g. it drops the bone index of 0xc7 and every reader of +0x114), and cross-checked with their uses in the WADs. Findings: 0x107 setAnimSpeed is the per-frame animation step (sub-frame accumulator +0x116, 1.0 = one frame per game frame); 0x2f freezes a strat while it is off-camera (with the camera pass's +0xEC 0x8000); 0x28 is read by the camera scripts to look at the strat registered with 0x113; 0x14a is a no-op (FUN_004268c0 only acts for 0); 0x9c's value is dead; 0x18a/0x18b set the pending particle settings consumed by the next spawnParticle; 0x1a9's top value is the rain texture and the others are wind x, amount, wind z; all no-op/drop stubs verified. Still low: 0x34 and 0xf2 (no reader of their flag bits found); see the table for the new descriptions. * **Renamed opcodes (aliases)**: placeholder names whose meaning the review established got clear names – 0x2f `flagEC10000` → `freezeOffCamera`, 0x31 `flagEC2` → `touchable`, 0x33 `flagEC100` → `noFloorPhysics`, 0x14a `hudReset2` → `hudResetNoop`. The old names stay valid mnemonics (resource `op-aliases.tsv`, `OpTable.alias`), so stored sources still assemble; listings and the compiler use the new names. Names of flags without a known reader (0x32, 0x34, 0x141–0x144, 0x14b) keep their address-style names. * **252 opcodes matched to Argonaut names** (column *ref*: Croc 2 PSX demo jump table / Croc 1 handler names), by handler behaviour and table position. 99 slots are no-ops, error stubs or pop-only stubs (dropped Croc features). * Strat properties (short ops 0x07/0x40 own, 0x1c/0x37 player, …): **194 ids** named (`props.tsv`), getter FUN_00550e60 and setter FUN_005509f0 share the numbering; ids without a setter are read-only (a write would go to address 0). ## Spawning and collision (engine facts, found by the arena, 2026-11-07) * `spawn` (0xe0, FUN_0054bfc0) takes the same fields as a MAP strat record: params = MAP parameter count, vars = local variables, slots, typeFlags = MAP type flags (collision setup), `extra` = words of the collision-bone area. * `spawn` copies the spawner's matrix/translation block (+0x20…), not its `x/y/z` properties: after `self.x = …` the child still appears at the old place. Set the position, **yield**, then spawn. * A MAP-placed type that uses `collisionOn` needs collision type flags in its MAP record (0x28000 like Coin); with typeFlags 0 the game crashes (page fault in the heap allocator FUN_0041ae20). ## Sources * groove.exe handler tables, decompiled with Ghidra 12.2 (headless, all 0x1b2 + 0x45 entries and their callees). Usage counts: our disassembler over all 34 level WADs. * Knowledge only (no code copied – Stratigise is GPL-2.0): the opcode name lists of [Stratigise](https://github.com/Argonaut-PS1-Reverse/Stratigise) (fork: [knot126/Stratigise](https://github.com/knot126/Stratigise)) – especially `doc/Croc2/Croc 2 psx demo strat_jump_table.txt` (319 handler names of the Croc 2 PSX demo) and `doc/Croc1/Opcodes.md` – and the Croc 1 decompilation [Xeeynamo/croc](https://github.com/Xeeynamo/croc) (`src/croc/3038.c`, `st*` handler names). Croc 1 uses a different, expression-tree encoding; Croc 2 is the direct ancestor: our long opcodes are the Croc 2 table index + 0x3b at the start (0x0a stNumber = our 0x45 push, 0x0e stAdd = 0x49 add), the offset shrinks stepwise where Croc 2 entries were dropped and grows where Groove added opcodes (0x50 shl, 0x51 shr, 0x52 animToFrame, 0x9b stream play, most of 0x140+: particles, trails, tint, update order, level end). ## Conventions * Stack: `PUSH` = FUN_0054bbd0, `POP` = FUN_0054bc00 (strat+0x104 = stack pointer). Binary ops pop **b** (top) then **a** and push `a op b`. Comparisons push raw 0/1. * Numbers are 20.12 fixed point (0x1000 = 1.0); `mul` = a·b>>12, `div` = (a<<8)/b<<4. * Angles: a full turn is **0x1000000** (4096.0 in 20.12, i.e. 4096 sin-table units << 12); getters mask angles to 24 bits. The language writes them as `90deg`. * Variables: strat+0xF4 array; the first n are the MAP parameters of the instance. Event handlers (0x0c): 16-byte slots at strat+0xF8; entry {type, param, rel}; type 4 = touched / collision (pickups), 0x40 = timer, 0x80/0x100 = player distance. * Special strats: player 0x6D9E1C (set by 0xb5 isPlayer), camera 0x6D9E28, camera targets 0x6D9E30/34, boss 0x6D9E24, dialog strat 0x6D9E2C, "parent" = strat+0xC (the spawner). Short-op families: push value / push address / pop for own vars (0x04/0x08/0x41), own props (0x07/0x0b/0x40), parent vars (0x18/0x19/0x3e) and props (0x1a/0x1b/0x3f), player (0x1c/0x1d/0x37), camera (0x1e/0x1f/0x38), target (0x20/0x21/0x39), target2 (0x24/0x25/0x3a), boss (0x26/0x27/0x3d), dialog (0x28/0x29/0x3b), globals 0x06/0x0a/0x43 (array 0x6D9E8C; the exe never indexes it – meanings only from script use). * Calls: 0x11 `call` pushes the return address (0x10 is the same with a yield, unused); `return` (0xb3) pops it. Yield = flag 2 in strat+0xE8 ends the strat's frame. ## Opcodes ops = operands (inline words for long ops, the 16-bit argument for short ops); pops/pushes (? = variable); uses = instructions in the 34 level WADs; conf = confidence. | op | name | operands | pops | pushes | uses | conf | ref | semantics | |---|---|---|---|---|---|---|---|---| | 0x00 | `nop_0x00` | - | 0 | 0 | | high | stCommandError | No-op (shared empty handler 00426500); unused in levels. 426500 | | 0x01 | `hide` | imm | 0 | 0 | 294 | medium | stHide | arg!=0 sets, arg==0 clears flag 0x1000000 in +0xE8; renderer and shadow pass skip strats with this bit, so it hides the strat. 54fa50 | | 0x02 | `skipArgs` | count | 0 | 0 | 1523 | medium | - | Inline block: count word, then count push instructions (0x44 one word, 0x45/0xea two words) that are skipped without executing; data block read by 0x0c event descriptors (same use count as 0x0c). 553850 | | 0x03 | `print` | count | 0 | 0 | 26 | medium | stPrint | Debug print with output stripped: skips count inline push instructions like 0x02 and advances debug text line y DAT_006d9db8 by 12 (reset to 0x20/0x48 each frame). 5537f0 | | 0x04 | `pushVar` | var | 0 | 1 | 50710 | high | stLocal | Pushes own variable n (+0xF4 array). 553710 | | 0x05 | `pushCodeWord` | rel | 0 | 1 | 438 | high | - | Pushes the 32-bit word at pc+arg*4 (inline data in the code stream, pc = next instruction). 5537b0 | | 0x06 | `pushGlobal` | global | 0 | 1 | 27756 | high | stGlobal | Pushes global n (0x6D9E8C[n]). 5536b0 | | 0x07 | `pushProp` | prop | 0 | 1 | 38636 | high | stAlienVar | Pushes own property n via FUN_00550E60(self,self,n). 552ab0 | | 0x08 | `pushVarAddr` | var | 0 | 1 | 2074 | high | stLocalAddress | Pushes address of own variable n (for 0x47/0x48/0x4d). 5536f0 | | 0x09 | `pushCodeAddr` | rel | 0 | 1 | 28 | high | - | Pushes address pc+arg*4 (address of inline code-stream data word). 553790 | | 0x0a | `pushGlobalAddr` | global | 0 | 1 | 1087 | high | stGlobalAddress | Pushes address of global n. 553690 | | 0x0b | `pushPropAddr` | prop | 0 | 1 | 248 | high | stAlienVarAddress | Pushes address of own property n (FUN_005509F0(self,self,n)). 552ad0 | | 0x0c | `onEvent` | rel,imm | 0 | 0 | 1523 | high | - | Installs event handler slot (2nd word) in table +0xF8 (16-byte slots): descriptor at word pc+1+off holds type, param, rel code address of the handler; type 0x40 = timer (param converted to frames), types 0x80/0x100 enable player-distance tracking (+0xEC bit 0x4000). 54fc40 | | 0x0d | `clearEvent` | imm | 0 | 0 | 35 | high | - | Clears event handler slot arg (type word := 0). 54dbe0 | | 0x0e | `disableEvent` | imm | 0 | 0 | | high | - | Disables event handler slot arg (sets bit 31 of its type word). 54dc20 | | 0x0f | `enableEvent` | imm | 0 | 0 | | high | - | Re-enables event handler slot arg (clears bit 31 of its type word). 54dc00 | | 0x10 | `callYield` | rel | 0 | 1 | | high | stJsr | Pushes return address (next pc), jumps to next+arg*4 and yields (+0xE8 bit 2); unused in levels. 553d40 | | 0x11 | `call` | rel | 0 | 1 | 8471 | high | stJsrImm | Pushes return address (next pc) and jumps to next+arg*4 without yielding; the call form actually used by the compiler. 553d10 | | 0x12 | `jzYield` | rel | 1 | 0 | 3012 | high | stBeq | Pops cond; if 0 jumps to next+arg*4; always yields this frame. 553e10 | | 0x13 | `jnzYield` | rel | 1 | 0 | 202 | high | stBne | Pops cond; if !=0 jumps to next+arg*4; always yields this frame. 553eb0 | | 0x14 | `jz` | rel | 1 | 0 | 32026 | high | stBeqImm | Pops cond; if 0 jumps to next+arg*4. 553e50 | | 0x15 | `jnz` | rel | 1 | 0 | | high | stBneImm | Pops cond; if !=0 jumps to next+arg*4; unused. 553e80 | | 0x16 | `jmp` | rel | 0 | 0 | 15125 | high | stJumpImm | Jumps to next+arg*4. 553d80 | | 0x17 | `switch` | rel | 1 | 0 | 597 | high | stIndex_Jump | Pops value; table at next+arg*4+4: count, then entries (case value as 0x44 short or 0x45 imm, then rel offset); on match jumps to next+offset*4, otherwise falls through. 550060 | | 0x18 | `pushParentVar` | var | 0 | 1 | 711 | high | stExt_Local | Pushes variable n of the linked strat at +0xC (parent/creator). 553750 | | 0x19 | `pushParentVarAddr` | var | 0 | 1 | 135 | high | stExt_LocalAddress | Pushes address of variable n of the +0xC strat. 553770 | | 0x1a | `pushParentProp` | prop | 0 | 1 | 1362 | high | stExt_AlienVar | Pushes property n of the +0xC strat. 552af0 | | 0x1b | `pushParentPropAddr` | prop | 0 | 1 | | high | stExt_AlienVarAddress | Pushes address of property n of the +0xC strat; unused. 553730 | | 0x1c | `pushPlayerProp` | playerProp | 0 | 1 | 4320 | high | stPlayer_AlienVar | Pushes property n of the player strat (DAT_006D9E1C, set by 0xb5), 0 if none. 552d20 | | 0x1d | `pushPlayerPropAddr` | playerProp | 0 | 1 | | high | stPlayer_AlienVarAddress | Pushes address of player property n (0 if no player); unused. 552d50 | | 0x1e | `pushCameraProp` | prop | 0 | 1 | 855 | high | stCamera_AlienVar | Pushes property n of the camera strat (DAT_006D9E28, set by 0xc8), 0 if none. 552b60 | | 0x1f | `pushCameraPropAddr` | prop | 0 | 1 | | high | stCamera_AlienVarAddress | Pushes address of camera property n (0 if none); unused. 552b90 | | 0x20 | `pushTargetProp` | prop | 0 | 1 | 1484 | medium | stTarget_AlienVar | Pushes property n of the camera target strat (DAT_006D9E30, set by 0xc9 from the player character strats), 0 if none. 552c40 | | 0x21 | `pushTargetPropAddr` | prop | 0 | 1 | | medium | stTarget_AlienVarAddress | Pushes address of target property n (0 if none); unused. 552c70 | | 0x22 | `error_0x22` | - | 0 | 0 | | high | stCollide_AlienVar | Prints "stCollide_AlienVar" not-implemented error; unused. 54d200 | | 0x23 | `error_0x23` | - | 0 | 0 | | high | stCollide_AlienVarAddress | Prints "stCollide_AlienVarAddress" not-implemented error; unused. 54d220 | | 0x24 | `pushTarget2Prop` | prop | 0 | 1 | | medium | stTarget_AlienVar | Pushes property n of the second target strat (DAT_006D9E34, set by 0xca), 0 if none; unused. 552bd0 | | 0x25 | `pushTarget2PropAddr` | prop | 0 | 1 | | medium | stTarget_AlienVarAddress | Pushes address of target2 property n (0 if none); unused. 552c00 | | 0x26 | `pushBossProp` | prop | 0 | 1 | | high | stBoss_AlienVar | Pushes property n of the boss strat DAT_006D9E24 (set by 0xef isBoss) via the getter FUN_00550E60; no null check; unused in the levels. 552b10 | | 0x27 | `pushBossPropAddr` | prop | 0 | 1 | | high | stBoss_AlienVarAddress | Pushes the address of property n of the boss strat DAT_006D9E24 (setter FUN_005509F0 returns the address); no null check; unused. 552b30 | | 0x28 | `pushDialogProp` | prop | 0 | 1 | 1678 | high | stDialog_AlienVar | Pushes property n of the strat registered by 0x113 (DAT_006D9E2C: the NPC/puzzle/door that a cut-scene is about), 0 if none. WAD use: Camera and CutSceneCameraDirectional read its x/y/z/rotY to look at it (1585 of 1678 uses). 552cb0 | | 0x29 | `pushDialogPropAddr` | prop | 0 | 1 | | high | stDialog_AlienVarAddress | Pushes the address of property n of the DAT_006D9E2C strat (0 if none); unused. 552ce0 | | 0x2a | `shadow` | imm | 0 | 0 | 887 | medium | stShadow | arg!=0 sets, 0 clears +0xE8 bit 0x20 (shadow on; shadow pass requires it plus size from 0x59 and texture from 0x5a). 54e8e0 | | 0x2b | `jmpYield` | rel | 0 | 0 | 2958 | high | - | Jumps to next+arg*4 and yields this frame (loop back-edge / wait one frame). 553da0 | | 0x2c | `nop_0x2c` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x2d | `nop_0x2d` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x2e | `nop_0x2e` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x2f | `freezeOffCamera` (was `flagEC10000`) | imm | 0 | 0 | 1888 | medium | - | arg!=0 sets, 0 clears +0xEC bit 0x10000 = "freeze when off-camera": the camera pass (FUN_00436190) sets +0xEC 0x8000 when the strat is outside the camera range; with both bits set the frame loop (0x54c603) and the strat-vs-strat collision loop (0x54cc1a) skip it. Used by ~1350 strats (pickups, triggers, enemies). 54f720 | | 0x30 | `trackPlayer` | imm | 0 | 0 | | medium | - | If no player yet: re-executes itself next frame (pc-=4, yield); else arg sets/clears +0xEC bit 0x4000 = update distance to player each frame (+0x148). 54fa80 | | 0x31 | `touchable` (was `flagEC2`) | imm | 0 | 0 | 410 | medium | - | arg sets/clears +0xEC bit 2 = "others can stand on / touch me": in the strat collision loop (0x54cc96) a strat touching a strat with this bit gets +0xE8 0x400000 (and 0x800000 when it moves) = properties 32/33; also readable as property 0x1f. Set by Llama, Coin, Jar, EnemyCoin, RubyIdol. 54e090 | | 0x32 | `flagE8_80000000` | imm | 0 | 0 | | medium | - | arg sets/clears +0xE8 bit 31; no reader of the bit found in the exe (scan of all +0xE8 flag tests); unused in the levels. 54dd90 | | 0x33 | `noFloorPhysics` (was `flagEC100`) | imm | 0 | 0 | 60 | medium | - | arg sets/clears +0xEC bit 0x100; the collision response (0x4044f7) skips the floor/slope handling when it is set. Used by LlamaSpit, DropObject, RollerCoaster, KuscoTurtle (objects that move by script, not by floor physics). 54dd30 | | 0x34 | `flagEC200000` | imm | 0 | 0 | 50 | low | - | arg sets/clears +0xEC bit 0x200000; no direct test of the bit found in the exe (all +0xEC flag tests scanned). Used by Llama, RiverCroc, RiverLog, Rock, river NPCs (river/canoe level objects). 54dd60 | | 0x35 | `nop_0x35` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x36 | `nop_0x36` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x37 | `popPlayerProp` | playerProp | 1 | 0 | 1131 | high | - | Pops value and stores it into player property n (discarded if no player). 553920 | | 0x38 | `popCameraProp` | prop | 1 | 0 | 564 | high | - | Pops value into camera strat property n (discarded if none). 553950 | | 0x39 | `popTargetProp` | prop | 1 | 0 | 186 | medium | - | Pops value into camera target (DAT_006D9E30) property n (discarded if none). 553980 | | 0x3a | `popTarget2Prop` | prop | 1 | 0 | | medium | - | Pops value into DAT_006D9E34 strat property n (discarded if none); unused. 5539b0 | | 0x3b | `popDialogProp` | prop | 1 | 0 | | high | - | Pops a value into property n of the DAT_006D9E2C strat (discarded if none); unused. 5539e0 | | 0x3c | `error_0x3c` | - | 0 | 0 | | high | - | Prints "stCollide_AlienVar_Equals" not-implemented error; unused. 54d240 | | 0x3d | `popBossProp` | prop | 1 | 0 | | high | - | Pops a value into property n of the boss strat DAT_006D9E24 (no null check); unused. 553a10 | | 0x3e | `popParentVar` | var | 1 | 0 | 204 | high | - | Pops value into variable n of the +0xC strat. 553a40 | | 0x3f | `popParentProp` | prop | 1 | 0 | | high | - | Pops value into property n of the +0xC strat; unused. 553a60 | | 0x40 | `popProp` | prop | 1 | 0 | 15730 | high | - | Pops value into own property n (via FUN_005509F0 address). 553a90 | | 0x41 | `popVar` | var | 1 | 0 | 30379 | high | - | Pops value into own variable n. 553ac0 | | 0x42 | `popCodeWord` | rel | 1 | 0 | 372 | high | - | Pops value into the code-stream word at pc+arg*4 (self-modifying inline data, pairs with 0x05). 553ae0 | | 0x43 | `popGlobal` | global | 1 | 0 | 20214 | high | - | Pops value into global n. 553b00 | | 0x44 | `pushShort` | imm | 0 | 1 | 82749 | high | stNumber | Pushes the sign-extended 16-bit arg (raw, not shifted to 20.12). 553610 | | 0x45 | `push` | imm | 0 | 1 | 25870 | high | stNumber | Pushes inline 32-bit word (handler shared with 0xd7). 5535f0 | | 0x46 | `neg` | - | 1 | 1 | 923 | high | stUMinus | Pops a, pushes -a. 5508b0 | | 0x47 | `inc` | - | 1 | 0 | 1648 | high | stIncrease | Pops address, adds 1.0 (0x1000) to the word there. 553890 | | 0x48 | `dec` | - | 1 | 0 | 1924 | high | stDecrease | Pops address, subtracts 1.0 (0x1000) from the word there. 5538b0 | | 0x49 | `add` | - | 2 | 1 | 15901 | high | stAdd | Pops b, a; pushes a+b. 5538d0 | | 0x4a | `sub` | - | 2 | 1 | 10042 | high | stSub | Pops b, a; pushes a-b. 552d90 | | 0x4b | `mul` | - | 2 | 1 | 11877 | high | stMul | Pops b, a; pushes fixed-point a*b>>12. 552dc0 | | 0x4c | `div` | - | 2 | 1 | 468 | high | stDiv | Pops b, a; pushes fixed-point (a<<8)/b<<4. 552e00 | | 0x4d | `store` | - | 2 | 0 | | high | stEquals | Pops value, then address; stores value at address; unused (compiler uses pop ops). 553900 | | 0x4e | `eq` | - | 2 | 1 | 10075 | high | stCompare | Pops b, a; pushes a==b (0/1, raw). 553be0 | | 0x4f | `lt` | - | 2 | 1 | 5556 | high | stLessThan | Pops b, a; pushes a553bb0 | | 0x50 | `shl` | - | 2 | 1 | 1162 | high | stShiftLeft | Pops b, a; pushes a << (b>>12) (b fixed shift count). 54fb70 | | 0x51 | `shr` | - | 2 | 1 | 2496 | high | stShiftRight | Pops b, a; pushes a >> (b>>12) arithmetic (also stashes a in 0x6DA2D8). 54fba0 | | 0x52 | `animToFrame` | - | 1 | 0 | 91 | medium | - | Pops frame (fixed); steps current anim frame +0x110 forward (wrapping) until it reaches frame (clamped to last frame of anim +0x14), applying each frame to the model. 54fad0 | | 0x53 | `gt` | - | 2 | 1 | 3662 | high | stGreaterThan | Pops b, a; pushes a>b. 553b20 | | 0x54 | `setModel` | - | 1 | 0 | 1439 | high | stSetModel | Pops model address; sets +0x10 and updates +0xEC bit 0x20 / +0xE8 bit 0x80 from model header fields. 553c10 | | 0x55 | `scale` | - | 1 | 0 | 376 | high | stScale | Pops scale (fixed); sets x/y/z scale +0x60/+0x64/+0x68. 54ffe0 | | 0x56 | `scaleX` | - | 1 | 0 | 102 | high | stScaleX | Pops scale (fixed) into +0x60. 550000 | | 0x57 | `scaleY` | - | 1 | 0 | 242 | high | stScaleY | Pops scale (fixed) into +0x64. 550020 | | 0x58 | `scaleZ` | - | 1 | 0 | 24 | high | stScalez | Pops scale (fixed) into +0x68. 550040 | | 0x59 | `shadowSize` | - | 1 | 0 | 548 | high | stShadowSize | Pops shadow size (fixed) into +0x12C (shadow drawn only if >=0x80). 54e840 | | 0x5a | `shadowTexture` | - | 1 | 0 | 548 | medium | stShadowType | Pops shadow texture index (TEXT texture) into +0x128 (short). 54e860 | | 0x5b | `error_0x5b` | - | 0 | 0 | | high | stFlash | Prints "stFlash" not-implemented error; unused. 54d260 | | 0x5c | `error_0x5c` | - | 0 | 0 | | high | stTrans | Prints "stTrans" not-implemented error; unused. 54d280 | | 0x5d | `moveUp` | - | 1 | 0 | 50 | high | stMoveUp | Pops dist (fixed); moves strat by local (0,+d,0) via FUN_005501D0. 550910 | | 0x5e | `moveDown` | - | 1 | 0 | 29 | high | stMoveDown | Pops dist; moves by local (0,-d,0). 550960 | | 0x5f | `moveForward` | - | 1 | 0 | 95 | high | stMoveForward | Pops dist; moves by local (0,0,+d) along its facing. 550590 | | 0x60 | `moveBackward` | - | 1 | 0 | 12 | high | stMoveBackward | Pops dist; moves by local (0,0,-d). 5505c0 | | 0x61 | `moveLeft` | - | 1 | 0 | 20 | high | stMoveLeft | Pops dist; moves by local (+d,0,0). 550720 | | 0x62 | `moveRight` | - | 1 | 0 | 4 | high | stMoveRight | Pops dist; moves by local (-d,0,0). 550750 | | 0x63 | `turnRight` | - | 1 | 0 | 380 | high | stTurnRight | Pops angle; yaw +0x24 -= angle (24-bit wrap; 4096.0 = full turn). 553c90 | | 0x64 | `turnLeft` | - | 1 | 0 | 775 | high | stTurnLeft | Pops angle; yaw +0x24 += angle. 553cb0 | | 0x65 | `tiltLeft` | - | 1 | 0 | 4 | high | stTiltLeft | Pops angle; roll +0x28 -= angle. 54e9e0 | | 0x66 | `tiltRight` | - | 1 | 0 | 6 | high | stTiltRight | Pops angle; roll +0x28 += angle. 54ea00 | | 0x67 | `tiltForward` | - | 1 | 0 | 26 | high | stTiltForward | Pops angle; pitch +0x20 += angle. 553cd0 | | 0x68 | `tiltBackward` | - | 1 | 0 | | high | stTiltBackward | Pops angle; pitch +0x20 -= angle; unused. 553cf0 | | 0x69 | `turnToPlayerX` | - | 1 | 0 | | high | stTurnToPlayerX | Pops max step (angle); turns pitch +0x20 toward the player by at most step; unused. 54ef50 | | 0x6a | `turnToPlayerY` | - | 1 | 0 | 345 | high | stTurnToPlayerY | Pops max step (angle); turns yaw +0x24 toward the player by at most step. 54f0d0 | | 0x6b | `turnToPlayerXY` | - | 1 | 0 | 1 | high | stTurnToPlayerXY | Pops max step (angle); turns yaw and pitch toward the player. 54eff0 | | 0x6c | `turnToX` | - | 4 | 0 | 2 | high | stTurnToX | Pops step, z, y, x; turns pitch toward point (x,y,z) by at most step. 54eb10 | | 0x6d | `turnToY` | - | 4 | 0 | 209 | high | stTurnToY | Pops step, z, y, x; turns yaw toward point (x,y,z) by at most step. 54ebc0 | | 0x6e | `turnToXY` | - | 4 | 0 | 28 | high | stTurnToXY | Pops step, z, y, x; turns yaw and pitch toward point (x,y,z). 54ec60 | | 0x6f | `wobble` | - | 1 | 0 | | medium | stWobble | Pops and discards one value (unimplemented; shared pop handler); unused. 554fb0 | | 0x70 | `resetPos` | - | 0 | 0 | 613 | high | stReSetPos | Restores 8 words (angles+position, +0x20..+0x3C) from the saved copy at +0xA0. 54fa10 | | 0x71 | `savePos` | - | 0 | 0 | 566 | high | stSetPos | Saves 8 words (+0x20..+0x3C angles+position) to +0xA0 for 0x70. 54f9f0 | | 0x72 | `nop_0x72` | - | 0 | 0 | | medium | stJump | No-op (shared empty handler); unused. 426500 | | 0x73 | `wpFirst` | - | 0 | 0 | 833 | high | stWPFirst | Current waypoint +0x120 := first waypoint +0x118. 54ea60 | | 0x74 | `wpLast` | - | 0 | 0 | 83 | high | stWPLast | Current waypoint +0x120 := last waypoint +0x11C. 54f240 | | 0x75 | `wpNext` | - | 0 | 0 | 1129 | high | stWPNext | Current waypoint := its next link; wraps to first. 54f260 | | 0x76 | `wpPrev` | - | 0 | 0 | 177 | high | stWPPrev | Current waypoint := its prev link; wraps to last. 54f550 | | 0x77 | `error_0x77` | - | 0 | 0 | | high | stWPDel | Prints "stWpdel" not-implemented error; unused. 54d2a0 | | 0x78 | `error_0x78` | - | 0 | 0 | | high | stWPNew | Prints "stWpnew" not-implemented error; unused. 54d2c0 | | 0x79 | `wpNearest` | - | 0 | 0 | | high | stWPNearest | Sets current waypoint to the one nearest the strat position; unused. 54f3f0 | | 0x7a | `wpFurthest` | - | 0 | 0 | | high | stWPFurthest | Sets current waypoint to the one furthest from the strat (excluding last); unused. 54f500 | | 0x7b | `wpTurnToX` | - | 1 | 0 | 12 | high | stWPTurnToX | Pops max step (angle); turns pitch toward the current waypoint (pos at wp+0x18). 54ee40 | | 0x7c | `wpTurnToY` | - | 1 | 0 | 230 | high | stWPTurnToY | Pops max step (angle); turns yaw toward the current waypoint (if any). 54eed0 | | 0x7d | `wpTurnToXY` | - | 1 | 0 | 25 | high | stWPTurnToXY | Pops max step (angle); turns yaw and pitch toward the current waypoint. 54ed60 | | 0x7e | `animPlay` | - | 1 | 0 | 3847 | high | stAnimPlay | Pops anim address; sets +0x14, frame +0x110 := 0, sets +0xE8 bit 8 (playing) and applies frame 0 to the model. 550160 | | 0x7f | `animStop` | - | 0 | 0 | 458 | high | stAnimStop | Clears +0xE8 bit 8 (anim playing). 54f7c0 | | 0x80 | `animClear` | - | 0 | 0 | | medium | stAnimClear | Clears the current anim pointer (+0x14) and flag 0x8 in +0xE8 (no anim playing). 54f7d0 | | 0x81 | `animSetSpeed` | - | 0 | 0 | | high | stAnimSetSpeed | Unimplemented on PC: only logs "stAnimsetspeed" via the debug print; no stack effect. 54d2e0 | | 0x82 | `collisionType` | - | 1 | 0 | 179 | high | stCollisionType | pops type (raw int); clears bits 0x42C of +0xEC then sets 1->0x8, 2->0x400, 3->0x20, 4->none, other->0x4 (collision shape/type flags). 54fd60 | | 0x83 | `collRadius` | - | 1 | 0 | 821 | high | stCollRadius | pops radius; stores its low 16 bits raw into collision radius short +0xD2. 54e910 | | 0x84 | `collHeight` | - | 0 | 0 | | high | stCollHeight | Unimplemented: logs "stCollheight" only. 54d300 | | 0x85 | `collExtent` | - | 1 | 0 | | medium | stCollextent | pops extent; stores its low 16 bits raw into short +0xC4. 54e930 | | 0x86 | `collView` | - | 0 | 0 | | high | stCollView | Unimplemented: logs "stCollview" only. 54d320 | | 0x87 | `nop_0x87` | - | 0 | 0 | | high | stCollPoints | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Slot of Croc2 stCollPoints. 426500 | | 0x88 | `nop_0x88` | - | 0 | 0 | | high | stCollSetPoint | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Slot of Croc2 stCollSetPoint. 426500 | | 0x89 | `createTrigger` | - | 0 | 0 | 45 | medium | stCreateTrigger | Sets flag 0x40 in +0xE8 (strat becomes a trigger/touchable, used by pickups like Health, Carrot). 54e4c0 | | 0x8a | `killTrigger` | - | 0 | 0 | | medium | stKillTrigger | Clears flags 0x40 and 0x4000000 in +0xE8 (undoes createTrigger). 54e4b0 | | 0x8b | `wait` | - | 1 | 0 | 1671 | high | stWait | pops frames (fixed, >>12) into wait counter short +0xFE and sets flag 0x2 in +0xE8 (strat sleeps until the counter runs out). 54fb40 | | 0x8c | `hold` | - | 0 | 0 | 110 | medium | stHold | Sets flags 0x12 (0x2 wait + 0x10 stopped) in +0xE8: suspends the strat indefinitely until released. 54fce0 | | 0x8d | `release` | - | 0 | 0 | | high | stRelease | Unimplemented: logs "stRelease" only. 54d340 | | 0x8e | `remove` | - | 0 | 0 | 985 | high | stRemove | Sets flags 0x6 in +0xE8 (yield + kill); same handler as 0xb4 end. 5535e0 | | 0x8f | `nop_0x8f` | - | 0 | 0 | | high | stMapRemove | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Slot of Croc2 stMapRemove. 426500 | | 0x90 | `mapAdd` | - | 0 | 0 | | high | stMapAdd | Unimplemented: logs "stMapadd" only. 54d360 | | 0x91 | `mapReplace` | - | 0 | 0 | | high | stMapReplace | Unimplemented: logs "stMapreplace" only. 54d380 | | 0x92 | `activated` | - | 0 | 0 | | medium | stActivated | Sets bit 0x8 in byte +0x44 of the strat's map-instance record (+0xF0): marks the map object as activated (persistent state). 54db40 | | 0x93 | `collected` | - | 0 | 0 | | medium | stCollected | Sets bit 0x4 in byte +0x44 of the map-instance record (+0xF0): marks the map object as collected so it does not respawn. 54db50 | | 0x94 | `spawnLegacy` | count,imm,imm,flags,imm | ? | 0 | | medium | stSpawn | pops code address of the new strat, then argCount (first inline word) argument values (popped inside FUN_0054bfc0); spawns a child strat at this strat's position (+0x20 block); inline words 3-5 are spawn parameters/flags (word 3 tested for 0x40000/0x80000/0x8000 collision-info allocation). Unused in shipped levels. 5531d0 | | 0x95 | `spawnFrom` | count,imm,imm,flags,imm,imm | ? | 0 | | medium | stSpawnFrom | Like spawn (pops code address + args) but with an extra inline block giving a local offset (x/y/z) that is rotated by the strat's matrix (+0x70..) and added to its translation (+0x94..): spawn at an offset relative to this strat. Unused. 5533f0 | | 0x96 | `link` | - | 0 | 0 | | high | stLink | Unimplemented: logs "stLink" only. 54d3a0 | | 0x97 | `unlink` | - | 0 | 0 | | high | stUnlink | Unimplemented: logs "stUnlink" only. 54d3c0 | | 0x98 | `soundShift` | - | 2 | 0 | 2 | medium | stSoundShift | pops pitch (fixed, >>12), then sound channel; changes pitch of a playing sound channel owned by this strat (FUN_00546400). 54e0c0 | | 0x99 | `soundStop` | - | 1 | 0 | 209 | high | stSoundStop | pops sound channel; stops that channel if owned by this strat, or (channel <0/invalid) all sounds of this strat. 54e1c0 | | 0x9a | `musicPlay` | - | 1 | 0 | 108 | high | stCdPlay | pops music track index (fixed, >>12); if different from the current track (0x586430) starts that ASF music stream (FUN_00546b70). 54d4c0 | | 0x9b | `streamPlay` | - | 0 | 0 | | high | - | Unimplemented: logs "stStreamPlay" only. 54d3e0 | | 0x9c | `speechSetPos` | - | 1 | 0 | 31 | high | - | Pops a value into global 0x6DA2B8 (written only, never read: no effect) and moves the speech/voice channel (DAT_006D94A0, started by "#" texts) to this strat's position (+0x30..0x38), so the voice plays from the speaker. 54d530 | | 0x9d | `discard_0x9d` | - | 1 | 0 | 28 | high | stMidiVolume | Pops a value (>>12) and passes it to the empty function 0x426500: a pure drop on PC. Croc2 slot midiVolume/cdFade. 54d4f0 | | 0x9e | `speechStop` | - | 0 | 0 | 141 | high | stMidiStop | Stops the current speech/voice stream (handle 0x6D94B4) if one is playing and resets the handle to -1. 54d510 | | 0x9f | `streamQueue` | - | 0 | 0 | | high | stMidiQueue | Unimplemented: logs "stStreamQueue" only. 54d400 | | 0xa0 | `isLight` | - | 0 | 0 | | high | stIsLight | Unimplemented: logs "stIsLight" only. 54d420 | | 0xa1 | `lightCol` | - | 0 | 0 | | high | stLightCol | Unimplemented: logs "stLightCol" only. 54d440 | | 0xa2 | `lightFade` | - | 0 | 0 | | high | stLightFade | Unimplemented: logs "stLightFade" only. 54d460 | | 0xa3 | `lightAtten` | - | 0 | 0 | | high | stLightAtten | Unimplemented: logs "stLightAtten" only. 54d480 | | 0xa4 | `lightType` | - | 0 | 0 | | high | stLightType | Unimplemented: logs "stLightType" only. 54d4a0 | | 0xa5 | `collisionOn` | flags | 0 | 0 | 1591 | high | stCollisionOn | ORs the inline flag word into +0xE8; if any of 0x34000 is set also sets 0x4000 in +0xEC. 54fcf0 | | 0xa6 | `collisionOff` | flags | 0 | 0 | 1134 | high | stCollisionOff | Clears the inline flag word's bits in +0xE8. 54fd40 | | 0xa7 | `collisionOffAll` | - | 0 | 0 | | high | stCollisionOffAll | Clears all collision flag bits 0x7E000 in +0xE8. 54fd30 | | 0xa8 | `soundPlayEx` | - | 3 | 0 | 5 | high | stSoundPlay | pops pitch (fixed), volume (fixed), sound id; in game states 3/4 plays the sound on this strat and sets its volume and pitch (no channel returned). 54e3a0 | | 0xa9 | `soundPlay4_0xa9` | - | 4 | 0 | | medium | stSoundPlay | pops 4 values and discards them (stubbed sound-play variant). 54e400 | | 0xaa | `soundPlayAssEx` | - | 3 | 1 | | high | stSoundPlayAss | pops pitch, volume, sound id; plays it like 0xa8 and pushes the channel (raw int), or -1 if not in game state 3/4. 54e320 | | 0xab | `soundPlayAss4_0xab` | - | 4 | 0 | | medium | stSoundPlayAss | pops 4 values and discards them (same stub as 0xa9; pushes nothing). 54e400 | | 0xac | `int` | - | 1 | 1 | 1508 | high | stInt | pops x; pushes x & 0xFFFFF000 (fixed-point floor/truncate to integer). 5501b0 | | 0xad | `sin` | - | 1 | 1 | 2994 | high | stSin | pops angle (fixed, 4096 table units = full turn); pushes sin from table 0x574318 (20.12). 54e790 | | 0xae | `cos` | - | 1 | 1 | 3149 | high | stCos | pops angle; pushes cos (table 0x574318 offset by quarter turn 0x400). 54e810 | | 0xaf | `not` | - | 1 | 1 | 4952 | high | stNot | pops x; pushes 1 if x==0 else 0. 54fc20 | | 0xb0 | `pop` | - | 1 | 0 | | high | stPop | Drops the top stack value (stack pointer +0x104 -= 4). 553dd0 | | 0xb1 | `stkCmp` | imm | 0 | 1 | | high | stStkCmp | Reads one inline word imm (pc += 4), peeks the top stack entry (no pop), dereferences it as an int pointer and pushes imm − *top. Unused in the levels. 553de0 | | 0xb2 | `address` | addr | 0 | 1 | 7890 | high | stAddress | Patches itself into 0x45 (push immediate) after resolving the operand to an absolute address (negative = import table 0x6DA324, else + STPC base 0x6D9DBC) and pushes it (code/model/anim address). 553630 | | 0xb3 | `return` | - | 1 | 0 | 4974 | high | stReturn | pops code address and jumps there (pc = popped). 5537d0 | | 0xb4 | `end` | - | 0 | 0 | 2006 | high | stEndStrat | Sets flags 0x6 in +0xE8 (yield + kill): ends the strat. Same handler as 0x8e. 5535e0 | | 0xb5 | `isPlayer` | - | 0 | 0 | 62 | high | stIsPlayer | Registers this strat as the player (global 0x6D9E1C = strat) and sets flag 0x800 in +0xE8. 550140 | | 0xb6 | `and` | - | 2 | 1 | 3004 | high | stAnd | pops b, a; pushes 1 if both are non-zero else 0 (logical and). 552e60 | | 0xb7 | `or` | - | 2 | 1 | 5411 | high | stOr | pops b, a; pushes a \| b (bitwise, used as logical or). 552ea0 | | 0xb8 | `bitwiseAnd` | - | 2 | 1 | 6814 | high | stBitwiseAnd | pops b, a; pushes a & b. 552e30 | | 0xb9 | `discard_0xb9` | - | 1 | 0 | | medium | - | Shared stub 0x554fb0: pops one value and discards it. Unused (Croc2 ext-var slots). 554fb0 | | 0xba | `discard_0xba` | - | 1 | 0 | | medium | - | Shared stub 0x554fb0: pops one value and discards it. Unused. 554fb0 | | 0xbb | `nop_0xbb` | - | 0 | 0 | | high | - | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. 426500 | | 0xbc | `notEqual` | - | 2 | 1 | 2576 | high | stNotEqual | pops b, a; pushes 1 if a != b else 0. 54fbd0 | | 0xbd | `greaterEqual` | - | 2 | 1 | 1169 | high | stGreaterEqual | pops b, a; pushes 1 if a >= b else 0. 553b80 | | 0xbe | `lessEqual` | - | 2 | 1 | 2129 | high | stLessEqual | pops b, a; pushes 1 if a <= b else 0. 553b50 | | 0xbf | `rnd` | - | 1 | 1 | 4990 | high | stRnd | pops n; pushes random value (two rand() halves) modulo n, 0 if n==0; result is in the same units as n (fixed in, fixed out). 54f960 | | 0xc0 | `loseHeart` | - | 0 | 0 | 219 | high | stLoseHeart | In game state 3, unless player invulnerable (0x584710 bit 0): health 0x584E70 -= 1.0, or if already 0 sets 0x584638 = 2 (player dies); refreshes HUD (FUN_004268c0(1)). 54f5c0 | | 0xc1 | `nop_0xc1` | - | 0 | 0 | | high | stResettoCheckPoint | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Croc2 slot stResettoCheckPoint. 426500 | | 0xc2 | `forceCollision` | - | 0 | 0 | 1619 | medium | stForceCollision | Runs world collision for this strat (FUN_00403020 with level geometry): updates floor/ceiling/wall info in the collision block +0xC0 (ground height, surface type). 54e9c0 | | 0xc3 | `turnFromPlayerY` | - | 1 | 0 | | medium | stTurnFromPlayerY | pops max turn step (angle, 0x1000000 = full turn); turns yaw +0x24 toward the direction from the player (0x6D9E1C) to this strat, i.e. away from the player, by at most step. 54f1c0 | | 0xc4 | `rumble` | - | 2 | 0 | 93 | high | stRumble | Shared stub 0x555090: pops two values and discards them (PSX pad rumble is not implemented on PC). 555090 | | 0xc5 | `suspendIfTooFar` | - | 1 | 0 | 232 | high | stSuspendIfTooFar | Shared stub 0x554fb0: pops one value (distance) and discards it – no effect on PC (op 0x2f gives the off-camera freeze instead). 554fb0 | | 0xc6 | `collisionBone` | - | 2 | 0 | 90 | medium | stCollisionBone | pops value (short), then bone id (fixed, >>12); sets/adds entry {id, value} in the bone table at +0xC8 (count +0xC6). 54e6c0 | | 0xc7 | `useBone` | - | 1 | 0 | 345 | high | stUseBone | Pops bone n (>>12); if the strat has an animated model (+0x14) it takes bone n of the current animation frame (+0x110; anim+0x1C frame table, 64 bytes per bone, offset +0x30..0x38 = bone position), rotates it by the strat's rotation matrix and adds the position: world point in +0xD8/+0xDC/+0xE0 = properties boneX/Y/Z. (The Ghidra C output drops the bone index; read from the assembly.) Used to spawn effects at hands/mouths. 54e4d0 | | 0xc8 | `isCamera` | - | 0 | 0 | 34 | high | stIsCamera | Registers this strat as the camera (global 0x6D9E28) and sets flag 0x8000000 in +0xE8. 5500f0 | | 0xc9 | `lookAtMe` | - | 0 | 0 | 86 | high | stLookatme | Sets camera look-at target global 0x6D9E30 = this strat. 5500e0 | | 0xca | `lookAtMe2` | - | 0 | 0 | | medium | stLookatme | Sets secondary look-at global 0x6D9E34 = this strat. Unused. 5500d0 | | 0xcb | `pushCamera` | - | 0 | 0 | | high | stPushCamera | Pushes current camera (0x6D9E28) and look-at (0x6D9E30) pair onto the camera stack 0x6D9DCC (index 0x6D9E40). 54dbb0 | | 0xcc | `popCamera` | - | 0 | 0 | | high | stPopCamera | If the camera stack is not empty, restores camera and look-at from it and increments camera-change counter 0x6D9D34. 54db00 | | 0xcd | `nop_0xcd` | - | 0 | 0 | | high | stResetCamerapos | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Croc2 slot stResetCamerapos. 426500 | | 0xce | `gainHeart` | - | 0 | 0 | 94 | high | stGainHeart | Health 0x584E70 += 1.0 if below max 0x584E6C; refreshes HUD (FUN_004268c0(1)). 54f650 | | 0xcf | `nop_0xcf` | - | 0 | 0 | | high | stGainHeartPot | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Croc2 slot stGainHeartPot. 426500 | | 0xd0 | `addInv` | imm | 0 | 0 | | medium | stAddInv | Adds inline item to inventory via FUN_00426860(item,1,1,0,0), which is a stub returning 0 on PC (no effect). 54da00 | | 0xd1 | `nop_0xd1` | - | 0 | 0 | | high | stGainCrystal | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Croc2 slot stGainCrystal. 426500 | | 0xd2 | `discard_0xd2` | - | 1 | 0 | | high | stCutscene | Shared stub 0x554fb0: pops one value and discards it. Unused (Croc2 slot stCutscene). 554fb0 | | 0xd3 | `inventory` | imm | 0 | 1 | | medium | stInventory | Queries inline item via stub FUN_00426860 and pushes result<<12 (always 0 on PC). 54d9d0 | | 0xd4 | `debugName` | imm,count | 0 | 0 | 1804 | high | stDebugname | Strat name: skips the first inline word, reads the byte length of the following name string, sets the name pointer (+0x18) to that string and jumps past it. 553ef0 | | 0xd5 | `soundPlay` | - | 1 | 0 | 1835 | high | stSoundPlay | pops sound id; plays it on this strat (FUN_00546170); outside game states 3/4 first sets game state 0x5846E4 = 5. 54e230 | | 0xd6 | `soundPlayAss` | - | 1 | 1 | 288 | high | stSoundPlayass | pops sound id; in game states 3/4 plays it and pushes the channel (raw int), else pushes -1. 54e1e0 | | 0xd7 | `soundAddress` | sound | 0 | 1 | 2996 | high | stSoundAddress | Pushes the inline sound id (same handler as 0x45 push immediate). 5535f0 | | 0xd8 | `nop_0xd8` | - | 0 | 0 | | high | stOnground | Shared empty handler 0x426500 (verified in the handler table); unused in the levels. Croc2 slot stOnground/stObjectFallslow. 426500 | | 0xd9 | `collisionOffset` | - | 3 | 0 | 403 | high | stCollisionOffset | pops z, y, x; stores low 16 bits into shorts +0xD0, +0xCE, +0xCC (collision centre offset). 54e050 | | 0xda | `abs` | - | 1 | 1 | 1847 | high | stAbs | pops x; pushes \|x\|. 5508d0 | | 0xdb | `pickup` | imm | 0 | 0 | | medium | stPickup | inline flag: nonzero sets bit 0x200 in +0xEC, zero clears it (strat can be picked up/carried). 54dd00 | | 0xdc | `min` | - | 2 | 1 | 1546 | high | stMin | pops b, a; pushes the smaller (signed). 54dc80 | | 0xdd | `max` | - | 2 | 1 | 768 | high | stMax | pops b, a; pushes the larger (signed). 54dc40 | | 0xde | `spawnParticle` | - | 6 | 0 | 1935 | medium | stSpawnparticle | pops param (texture or colour, type-dependent), vz, vy, vx (velocity, fixed), scale (fixed, 0x1000 = default), particle type (raw int); emits a particle at this strat's position (FUN_00428ea0). 552ed0 | | 0xdf | `sgn` | - | 1 | 1 | | high | stSgn | pops x; pushes 1.0 (0x1000), -1.0 or 0 by sign. 54e7c0 | | 0xe0 | `spawn` | count,count,imm,flags,imm | ? | 0 | 1788 | medium | stSpawn | Spawns a child strat via FUN_0054bfc0: pops code address of the new strat (top), then pops operand1 (param count) values from the parent stack as the child's MAP parameters; operand2 = local variable count of the child, operand4 = spawn flags (ORed with own +0x138; bits 0x40000/0x80000/0x8000 select model/collision setup), operands 3/5 extra sizes/flags; child copies parent orientation/position block (+0x20) and waypoint fields; fails silently (params still popped) if strat pool full 553230 | | 0xe1 | `nop_0xe1` | - | 0 | 0 | | high | stDontLookatme? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0xe2 | `nop_0xe2` | - | 0 | 0 | | high | stRunat? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0xe3 | `moveForwardQ` | - | 1 | 0 | 854 | high | stMoveForwardq | pops distance (fixed); x(+0x30) += d*sin(yaw), z(+0x38) += d*cos(yaw), yaw = +0x24 (4096 units per turn, table 0x574318) 550690 | | 0xe4 | `moveBackwardQ` | - | 1 | 0 | 436 | high | stMoveBackwardq | pops distance (fixed); moves the strat backwards along its yaw (x -= d*sin, z -= d*cos) 550600 | | 0xe5 | `playSoundVol` | - | 2 | 0 | 1631 | high | stSoundPlay | pops volume (fixed, >>12), sound id; if game state DAT_005846e4 is 3 or 4 plays the sound for this strat (FUN_00546170) and sets the channel volume (+0x6a, FUN_00546360) 54e2d0 | | 0xe6 | `playSoundChannel` | - | 2 | 1 | 47 | high | stSoundPlayass | pops volume (fixed), sound id; if game state DAT_005846e4==3 plays the sound with that volume and pushes the channel index (raw int, not fixed), else pushes -1 54e270 | | 0xe7 | `setWP` | - | 0 | 0 | 213 | high | stSetWP | saves the current waypoint: +0x124 = +0x120 54ea20 | | 0xe8 | `resetWP` | - | 0 | 0 | 193 | high | stResetWP | restores the saved waypoint: +0x120 = +0x124 54ea40 | | 0xe9 | `soundVolume` | - | 2 | 0 | 7 | high | stSoundVolume | pops volume (fixed), sound channel; sets the channel volume (+0x6a) if the channel belongs to this strat (FUN_00546360) 54e190 | | 0xea | `nop_0xea` | - | 0 | 0 | | high | stString? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0xeb | `setBossHearts` | - | 1 | 0 | | high | stSetbossHearts | pops count (fixed); sets boss heart max DAT_00584f0c and current DAT_00584f10 to count 54f580 | | 0xec | `loseBossHeart` | - | 0 | 0 | | high | stLosebossHeart | decrements boss hearts DAT_00584f10 (not below 0) and refreshes the HUD (FUN_004268c0(1)) 54f5a0 | | 0xed | `soundShiftRelative` | - | 2 | 0 | 57 | medium | stSoundShiftrelative | pops shift/pitch (fixed, >>12), sound channel; sets channel +0x70 and updates a playing voice (FUN_00546460) if the channel belongs to this strat 54e0f0 | | 0xee | `smin` | - | 2 | 1 | 42 | high | stSmin | pops limit (top), value; pushes value with its magnitude clamped to limit, keeping the sign (sign(v)*min(\|v\|,limit)) 54dcc0 | | 0xef | `isBoss` | - | 0 | 0 | | high | stIsboss | registers this strat as the boss: DAT_006d9e24 = self 550130 | | 0xf0 | `topSay` | text | 0 | 0 | 1308 | high | stTopsay | shows dialog text (inline text index) in the top text box: sets DAT_006d9858=1 and formats via FUN_0040d4c0 40d480 | | 0xf1 | `getParentPos` | - | 0 | 0 | 48 | high | stGetparentpos | copies parent's (+0xC) orientation+position block (+0x20..+0x3C, 8 words) into this strat 54e030 | | 0xf2 | `setDrawMode` | - | 1 | 0 | | low | - | Pops mode (raw int): 1 sets +0xEC 0x80000, 2 sets 0x100000, anything else clears both; no reader of these two bits found in the exe; unused in the levels. 54fe40 | | 0xf3 | `afterBoss` | - | 0 | 0 | | high | stAfterboss | if no boss (DAT_006d9e24) rewinds pc and yields (waits); else relinks this strat in the process list right after the boss 553290 | | 0xf4 | `afterPlayer` | - | 0 | 0 | 144 | high | stAfterPlayer | if no player (DAT_006d9e1c) rewinds pc and yields (waits); else relinks this strat in the process list right after the player 553380 | | 0xf5 | `beforePlayer` | - | 0 | 0 | 22 | high | stBeforePlayer | if no player rewinds pc and yields (waits); else relinks this strat in the process list right before the player 553300 | | 0xf6 | `nop_0xf6` | - | 0 | 0 | | high | stBeforeboss?/stNohang? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0xf7 | `pushZero` | - | 0 | 1 | | high | stZero | pushes 0 (same handler as 0x1a7); unused 54e880 | | 0xf8 | `nop_0xf8` | - | 0 | 0 | | high | stTophead? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0xf9 | `popDiscard_0xf9` | - | 1 | 0 | | high | stTopdialog? | pops and discards one value (stub FUN_00554fb0, shared with 0x6f etc.); unused 554fb0 | | 0xfa | `bottomSay` | text | 0 | 0 | 891 | high | stBottomsay | shows dialog text (inline text index) in the bottom text box: sets DAT_006d94e8=2 and formats via FUN_0040d4c0 40d8d0 | | 0xfb | `nop_0xfb` | - | 0 | 0 | | high | stBottomhead? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0xfc | `popDiscard_0xfc` | - | 1 | 0 | | high | stBottomdialog? | pops and discards one value (stub FUN_00554fb0); unused 554fb0 | | 0xfd | `getPlayerPos` | - | 0 | 0 | 193 | high | stGetPlayerpos | if a player exists copies its orientation+position block (+0x20..+0x3C) into this strat 54dde0 | | 0xfe | `getWPPos` | - | 0 | 0 | 406 | high | stGetWPpos | sets rotation x/y/z (+0x20..+0x28) from the current waypoint's (+0x120) ints <<12 and position (+0x30..+0x3C) from waypoint +0x18..+0x24 54dfe0 | | 0xff | `getBossPos` | - | 0 | 0 | | high | stGetbosspos | copies the boss's (DAT_006d9e24) orientation+position block (+0x20..+0x3C) into this strat (no null check); unused 54ddc0 | | 0x100 | `getDoorPos` | - | 0 | 0 | 31 | medium | stGetdoorpos | finds the level door record (DAT_00584648+0x24) in this strat's x/z cell nearest in y; if found sets current door DAT_00584644, places the strat at the door position/yaw (FUN_0054de00) and, unless door flag 2, moves it forward by the door's distance (+0x38) 54df30 | | 0x101 | `fadeOut` | - | 1 | 0 | 181 | medium | stFadeout | pops speed selector (fixed, 1/2/3/other) and starts a screen fade-out (FUN_00415390 mode 1/5/0xb/3); sets DAT_00584638=6 unless it is 7 or 10 54d910 | | 0x102 | `fadeIn` | - | 1 | 0 | 150 | medium | stFadein | pops speed selector (fixed, 1/3/other) and starts a screen fade-in (FUN_00415390 mode 2/10/4); DAT_00584638=0 54d8a0 | | 0x103 | `moveUpQ` | - | 1 | 0 | 1018 | high | stMoveUpq | pops distance (fixed); y(+0x34) += d 5508f0 | | 0x104 | `moveDownQ` | - | 1 | 0 | 314 | high | stMoveDownq | pops distance (fixed); y(+0x34) -= d 550940 | | 0x105 | `forcePlayerDist` | - | 0 | 0 | | high | stForcePlayerdist | recomputes the cached squared player distance +0x148 (coords >>6) and clears +0x1C; 0x200000 if no player; unused 54e950 | | 0x106 | `nop_0x106` | - | 0 | 0 | | high | stShadeType? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x107 | `setAnimSpeed` | - | 1 | 0 | 645 | high | stSetanimSpeed? | Pops the animation speed (20.12, 1.0 = one animation frame per game frame) into halfword +0x114; while animating (+0xE8 bit 8) the frame loop adds it to the sub-frame counter +0x116 and advances the frame (+0x110) each time it passes 1.0 (0x54c630). WAD use: 1.0, 0.25, 1.5 and computed values. 54d880 | | 0x108 | `nop_0x108` | - | 0 | 0 | | high | stCheckleveldoor? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x109 | `nop_0x109` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x10a | `nop_0x10a` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x10b | `nop_0x10b` | - | 0 | 0 | | high | stGainjigsaw? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x10c | `nop_0x10c` | - | 0 | 0 | | high | stGaingoldengobbo? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x10d | `gainSecret` | - | 0 | 0 | 26 | high | stGainCrystal? | increments the collected-secrets counter DAT_00584e64 (copied to the HUD/stats at level reset); used only by strat Secret 54f710 | | 0x10e | `nop_0x10e` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x10f | `nop_0x10f` | - | 0 | 0 | 1 | high | stCheckPoint? | no-op handler FUN_00426500 (does nothing, no inline operands); used once (LlamaChase) 426500 | | 0x110 | `setMainCameraFlag` | - | 0 | 0 | 23 | medium | stIsmainCamera? | sets flag 0x8000000 in own flags +0xE8 (same flag the camera-register opcode FUN_005500f0 sets, without registering DAT_006d9e28); used by CameraCollisionInFront 550120 | | 0x111 | `nop_0x111` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x112 | `nop_0x112` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x113 | `isDialog` | - | 0 | 0 | 157 | high | stIsdialog | registers this strat as the dialog partner: DAT_006d9e2c = self 550110 | | 0x114 | `distance` | - | 3 | 1 | 20 | high | stDistance | pops z (top), y, x; pushes the 3D distance from the strat's position (+0x30) to (x,y,z) (FUN_00404bb0, float sqrt -> int) 54f840 | | 0x115 | `showLevelStartInfo` | imm | 0 | 0 | 60 | medium | - | inline word: low byte stored in DAT_006da294 (level start info / title card index), logs 'show level start info %d' 54e8b0 | | 0x116 | `topCloseDialog` | - | 0 | 0 | 32 | high | stTopclosedialog | closes the top dialog text box: DAT_006d9858 = 0 40d900 | | 0x117 | `bottomCloseDialog` | - | 0 | 0 | 4 | high | stBottomclosedialog | closes the bottom dialog text box: DAT_006d94e8 = 0 40d910 | | 0x118 | `nop_0x118` | - | 0 | 0 | | high | stNextinventory? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x119 | `nop_0x119` | - | 0 | 0 | | high | stPrevinventory? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x11a | `otherPiece` | - | 0 | 0 | 266 | medium | stOtherpiece | finds the switchable map piece at the strat's grid cell (FUN_00553f10, table DAT_00584648+0x50) and sets it to its alternate state (*piece[5] = piece[4]), swapping its texture/collision table entries if DAT_006da330 bit 0x10000000 553f70 | | 0x11b | `normalPiece` | - | 0 | 0 | 264 | medium | stNormalpiece | same as otherPiece but restores the piece's normal state (*piece[5] = piece[3]) 554090 | | 0x11c | `delInv` | imm | 0 | 0 | | medium | stDelinv | inline word (inventory item id) passed to FUN_00426860(item,1,-1,0,0), which is a stub returning 0 in this build: effectively no-op; unused 54da20 | | 0x11d | `nop_0x11d` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x11e | `nop_0x11e` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x11f | `nop_0x11f` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x120 | `nop_0x120` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x121 | `nop_0x121` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x122 | `nop_0x122` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x123 | `nop_0x123` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x124 | `nop_0x124` | - | 0 | 0 | | high | - | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x125 | `moveLeftQ` | - | 1 | 0 | 131 | high | stMoveLeftq | pops distance (fixed); strafes: x += d*cos(yaw), z += d*sin(yaw-half turn) (= -d*sin) 550790 | | 0x126 | `moveRightQ` | - | 1 | 0 | 299 | high | stMoveRightq | pops distance (fixed); strafes opposite to moveLeft (x -= d*cos(yaw), z += d*sin(yaw)) 550820 | | 0x127 | `bitwiseNot` | - | 1 | 1 | 1 | high | stBitwisenot | pops v; pushes ~v 54fc00 | | 0x128 | `bordersOn` | - | 0 | 0 | 157 | high | stBorderson | enables cinematic letterbox borders: DAT_005fd090 = 1 54dac0 | | 0x129 | `bordersOff` | - | 0 | 0 | 176 | high | stBordersoff | disables letterbox borders: DAT_005fd090 = 0 54dad0 | | 0x12a | `soundAdsr` | - | 5 | 0 | | high | stSoundadsr | pops and discards 5 values (stubbed); unused 54e120 | | 0x12b | `soundAdsrRelative` | - | 3 | 0 | 74 | medium | stSoundadsrrelative | pops a (top), b (fixed), sound channel; if the channel belongs to this strat sets channel +0x34 = b>>12, +0x38 = a>>12 (FUN_005463b0, envelope/range params) 54e150 | | 0x12c | `nop_0x12c` | - | 0 | 0 | | high | stRotatepiece? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x12d | `setAmbient` | - | 3 | 0 | 273 | high | stSet_ambient | pops b, g, r (fixed, >>12, top = b) into bytes +0x135/+0x134/+0x133 and enables the own ambient light colour (+0x136 = 1) 54fea0 | | 0x12e | `resetAmbient` | - | 0 | 0 | | high | stReset_ambient | disables the own ambient colour: +0x136 = 0; unused 54fee0 | | 0x12f | `invActive` | - | 0 | 0 | | high | stInvactive | calls inventory stub FUN_00426860(0,1,0,1,0) (returns 0, no effect in this build); unused 54da60 | | 0x130 | `invInactive` | - | 0 | 0 | | high | stInvinactive | calls inventory stub FUN_00426860(0,1,0,1,1) (no effect); unused 54da40 | | 0x131 | `sampleStatus` | - | 1 | 1 | | high | stSamplestatus | pops sound id; pushes (fixed) the channel index on which this strat is playing that sound, or -1.0 if not playing (FUN_005461e0); unused 54e480 | | 0x132 | `nop_0x132` | - | 0 | 0 | | high | stResettoCheckPointnlh? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x133 | `resetDoor` | - | 0 | 0 | 31 | high | stResetdoor | restores the stored door (DAT_006da28c -> DAT_00584644) and, if a player exists, places the player at that door (FUN_0054de00) and restores its saved orientation/position block from DAT_006d9e48 54def0 | | 0x134 | `storeDoor` | - | 0 | 0 | 62 | high | stStoredoor | stores the current door (DAT_00584644 -> DAT_006da28c) and the player's orientation/position block (+0x20..+0x3C) into DAT_006d9e48 54dec0 | | 0x135 | `cameraModified` | - | 0 | 0 | | medium | stCamera_modified | if a camera strat (DAT_006d9e28) exists copies this strat's orientation/position block into it and its position into globals DAT_006d9d20..2c; unused 54d830 | | 0x136 | `pushPlayer` | - | 0 | 0 | | high | stPushPlayer | saves the current player pointer DAT_006d9e1c into DAT_006d9e20 (logs an error if no player); unused 54db60 | | 0x137 | `popPlayer` | - | 0 | 0 | | high | stPopPlayer | restores the player pointer (DAT_006d9e1c and DAT_006d9e30) from DAT_006d9e20 and clears it; unused 54db90 | | 0x138 | `resetToStart` | - | 0 | 0 | | high | stReSetPostrn | restores position +0x30..+0x38 from the saved (start) position +0xB0..+0xB8; unused 54fa30 | | 0x139 | `gainItem` | - | 0 | 0 | | high | stGainitem | increments item counter DAT_005fd09c up to the maximum DAT_005fd0a4; unused 54f680 | | 0x13a | `setItem` | - | 1 | 0 | | high | stSetitem | pops maximum (fixed); DAT_005fd0a4 = max, counter DAT_005fd09c = 0, enables item counter display (DAT_005fd0a0 = 1); unused 54f6a0 | | 0x13b | `setTimer` | - | 1 | 0 | | high | stSettimer | pops time (fixed, >>12) into DAT_005fd0ac and enables the timer (DAT_005fd0a8 = 1); unused 54f6d0 | | 0x13c | `timerOff` | - | 0 | 0 | | high | stTimeroff | disables the timer: DAT_005fd0a8 = 0; unused 54f6f0 | | 0x13d | `distanceNoY` | - | 2 | 1 | 170 | high | stDistancenoy | pops z (top), x; pushes the horizontal (x/z) distance from the strat's position to (x,z) (FUN_00404c50) 54f890 | | 0x13e | `nop_0x13e` | - | 0 | 0 | | high | stSwim? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x13f | `nop_0x13f` | - | 0 | 0 | | high | stLoseCrystal? | no-op handler FUN_00426500 (does nothing, no inline operands); unused 426500 | | 0x140 | `nop_0x140` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x141 | `setDebugFlag5849a0On` | - | 0 | 0 | | medium | - | Writes short 1 to global 0x5849A0; that global is never read anywhere in groove.exe (dead PSX leftover). 54dab0 | | 0x142 | `setDebugFlag5849a0Off` | - | 0 | 0 | | medium | - | Writes short 0xFFFF to global 0x5849A0 (never read; dead leftover). 54daa0 | | 0x143 | `clearFlag5fd0b8` | - | 0 | 0 | | medium | - | Sets global 0x5FD0B8 = 0; global is never read elsewhere (dead leftover). 54da80 | | 0x144 | `setFlag5fd0b8` | - | 0 | 0 | | medium | - | Sets global 0x5FD0B8 = 1; global is never read elsewhere (dead leftover). 54da90 | | 0x145 | `nop_0x145` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x146 | `nop_0x146` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x147 | `nop_0x147` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x148 | `gotoLevel4_1` | - | 0 | 0 | | medium | - | Hardcoded level change: next level (0x584EB4/EB8/EBC/EC0) = 4/1/1/0, previous level (0x585008..14) = 4/1/4/0, game state 0x584638 = 7 (load level). 54e430 | | 0x149 | `nop_0x149` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x14a | `hudResetNoop` (was `hudReset2`) | - | 0 | 0 | | high | - | Calls FUN_004268c0(2), which returns at once for any argument other than 0 (verified in the assembly): a no-op. Unused. 54f700 | | 0x14b | `setGlobal5fd086` | imm | 0 | 0 | | medium | - | Stores the low 16 bits of the inline word in global 0x5FD086 (never read elsewhere; dead leftover). 54e890 | | 0x14c | `removeCollPoint` | - | 1 | 0 | 49 | medium | stSetCollPoint (inverse) | pops id (fixed, >>12); removes the collision point with that id from the strat's collision point list (+0xC8 array of 4-byte entries, count +0xC6). Counterpart of 0xc6 (add/set collision point). 54e720 | | 0x14d | `setFlagEC_400000` | flags | 0 | 0 | | high | - | Inline word: nonzero sets, zero clears bit 0x400000 of strat flags2 (+0xEC); the bit selects which height constant own property 0xF2 returns. 54f780 | | 0x14e | `atan2` | - | 2 | 1 | 457 | high | - | pops b (top), a; pushes angle atan2(a, b) as (0..0xFFF)<<12, i.e. full turn = 0x1000000 (4096.0); used with a=dx, b=dz like yaw-to-target. 54f7f0 | | 0x14f | `nop_0x14f` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x150 | `nop_0x150` | - | 0 | 0 | 1 | high | - | Empty handler FUN_00426500 (shared no-op); does nothing (used once in HelpGirlSkip). 426500 | | 0x151 | `nop_0x151` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x152 | `nop_0x152` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x153 | `findNearestLight` | - | 3 | 1 | 1 | medium | - | pops z (top), y, x; searches the level light table (0x586598, 0x1C-byte entries, count 0x5865D0) for the nearest light of type 2 (point light) to (x,y,z) and pushes its pointer (0 if none). 554280 | | 0x154 | `setLightIntensity` | - | 2 | 0 | 3 | medium | - | pops intensity (fixed; top), light pointer (from 0x153); stores intensity in light+0x18, rebuilds the light (FUN_0042c4a0) and re-flags/relights the map polygons within its radius (0 = off, 0x1000 = full). 554310 | | 0x155 | `nop_0x155` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x156 | `nop_0x156` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x157 | `nop_0x157` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x158 | `nop_0x158` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x159 | `nop_0x159` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x15a | `setPosToPlayer` | - | 0 | 0 | 27 | high | - | Copies the player's position x/y/z (+0x30..+0x38) and +0x3C into the strat (player strat = 0x6D9E1C). 554480 | | 0x15b | `setPosToPlayerXZ` | - | 0 | 0 | | high | - | Copies the player's x and z (+0x30, +0x38) into the strat; y unchanged. 5544b0 | | 0x15c | `setShadowHeight` | - | 1 | 0 | 1 | medium | - | Pops v into +0x14C, the water/floor height limit used by the shadow pass (FUN_00555140: -0x1000 = use the camera-cell floor height DAT_00586424, prop camFloorHeight); the shadow is skipped when the floor under the strat lies below it. One use (SinkingStatuePad). 5544d0 | | 0x15d | `packRgb` | - | 3 | 1 | 98 | high | - | pops c (top), b, a (fixed 0..255); pushes (c<<16)\|(b<<8)\|a as a raw packed colour int (push order r,g,b gives 0x00BBGGRR). 5544f0 | | 0x15e | `trailCreate` | - | 2 | 1 | 6 | medium | - | pops vertB (top), vertA (fixed vertex indices of the strat's model/anim frame); allocates a free trail/ribbon slot (0x5FD180, 0x42C bytes each) owned by this strat and pushes its handle (0 if none free). 554530 | | 0x15f | `trailAddPoint` | - | 3 | 0 | 6 | medium | - | pops colourB (top), colourA, trail handle; transforms the two trail vertices of the current anim frame into world space and appends them to the trail history (20 points) with the given colours; no-op if handle 0. 5545c0 | | 0x160 | `trailFree` | - | 1 | 0 | 6 | high | - | pops trail handle; releases it (clears owner +0x414) if nonzero. 554950 | | 0x161 | `setPauseState` | - | 1 | 0 | | medium | - | pops v (fixed); sets global pause state 0x584640 = v>>12 (0 = not paused, 1 = paused, 2 = pausing disabled). 554970 | | 0x162 | `setFlagE8_1000` | flags | 0 | 0 | | high | - | Inline word: nonzero sets, zero clears bit 0x1000 of strat flags (+0xE8). 54fdd0 | | 0x163 | `setCollOffset` | - | 3 | 0 | 189 | medium | - | pops z (top), y, x; stores them as 16-bit shorts into the strat's collision descriptor (+0xC0) at +0x32/+0x34/+0x36 = collision sphere centre offset. 54fe00 | | 0x164 | `angleDiff` | - | 2 | 1 | 1507 | high | - | pops b (top), a (angles, full turn 0x1000000); pushes (a-b) wrapped to the signed half-turn range (-0x800000..0x7FF000). 554990 | | 0x165 | `collideAsPlayer` | - | 0 | 0 | 27 | medium | - | Sets flag 0x800 on self (excludes self), temporarily makes self the player (0x6D9E1C) and runs the player-vs-strat collision pass FUN_004051d0, then restores the player; lets projectiles (LlamaSpit) hit strats like the player does. 554bc0 | | 0x166 | `setGlobalTint` | - | 3 | 0 | | high | - | pops b (top), g, r (fixed, clamped 0..255); sets the global strat tint 0x6D9E14..16 and enables it, and applies it to every strat that has no own tint yet (+0x133..+0x136). 554bf0 | | 0x167 | `screenOverlay` | flags | 0 | 0 | 18 | high | - | Inline word: nonzero enables the full-screen colour overlay (0x583740 = 1, colour reset to 0), zero disables it. 54d970 | | 0x168 | `setScreenOverlayColour` | - | 4 | 0 | 18 | medium | - | pops d (top), c, b, a (fixed 0..255, >>12); sets the full-screen overlay colour to a<<24 \| d<<16 \| b<<8 \| c (a = alpha; d,b,c land in the R,G,B byte positions of the D3D colour). 54d990 | | 0x169 | `nop_0x169` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x16a | `turnTowardStratY` | - | 2 | 0 | | high | stTurnTowardY | pops maxStep (top, angle), target strat pointer; turns own yaw (+0x24) toward the target's position by at most maxStep (full turn 0x1000000). 554cd0 | | 0x16b | `pushSelf` | - | 0 | 1 | | high | - | Pushes the pointer of the executing strat (this). 554cc0 | | 0x16c | `nop_0x16c` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x16d | `nop_0x16d` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x16e | `lerp` | - | 3 | 1 | 2167 | high | - | pops t (top), b, a; pushes b + (a-b)*t (fixed): t=0 gives b, t=1.0 gives a. 5549c0 | | 0x16f | `clamp` | - | 3 | 1 | 459 | high | - | pops hi (top), x, lo; pushes max(lo, min(x, hi)) (push order lo, x, hi). 554a10 | | 0x170 | `distSqToPos` | - | 3 | 1 | 166 | high | - | pops z (top), y, x; pushes squared 3D distance from own position, computed on coordinates >>6 (dx>>6)^2+(dy>>6)^2+(dz>>6)^2. 54f8d0 | | 0x171 | `distSqToPosXZ` | - | 2 | 1 | 394 | high | - | pops z (top), x; pushes squared horizontal distance from own position, (dx>>6)^2+(dz>>6)^2. 54f920 | | 0x172 | `approach` | - | 3 | 1 | 365 | high | - | pops step (top), target, value; pushes value moved toward target by step without overshooting. 554a70 | | 0x173 | `distSqXZ` | - | 4 | 1 | 28 | high | - | pops z2 (top), x2, z1, x1; pushes (x2-x1)^2 + (z2-z1)^2 in fixed point. 554ad0 | | 0x174 | `turnTowardAngleY` | - | 2 | 0 | 466 | high | stTurnTowardY | pops maxStep (top), targetYaw; turns own yaw (+0x24) toward targetYaw by at most maxStep, wrapping (full turn 0x1000000). 54f150 | | 0x175 | `setFlagEC_80` | flags | 0 | 0 | | high | - | Inline word: nonzero sets, zero clears bit 0x80 of strat flags2 (+0xEC). 54f750 | | 0x176 | `inRectXZ` | - | 6 | 1 | 7 | high | - | pops maxZ (top), maxX, minZ, minX, z, x; pushes integer 1 (not 0x1000) if minX<=x<=maxX and minZ<=z<=maxZ, else 0. 554b40 | | 0x177 | `waypointStep` | - | 1 | 0 | 402 | high | stNextWaypoint/stPrevWaypoint | pops n (fixed); moves current waypoint (+0x120) n steps forward via next links (wraps to first +0x118) or -n steps back via prev links (wraps to last +0x11C). 54f290 | | 0x178 | `inWaypointBoxXZ` | - | 2 | 1 | 319 | high | - | pops z (top), x; pushes integer 1 if (x,z) lies inside the axis-aligned XZ box spanned by the current waypoint and the next one (wrapping to first), else 0. 54f2f0 | | 0x179 | `nearestWaypoint` | - | 0 | 0 | | high | stNearestWaypointNext | Sets current waypoint (+0x120) to the waypoint of the list (+0x118) nearest (XZ) to the strat. 54f430 | | 0x17a | `nearestWaypointToPlayer` | - | 0 | 0 | | high | - | Sets current waypoint to the waypoint nearest (XZ) to the player. 54f470 | | 0x17b | `nearestOtherWaypoint` | - | 0 | 0 | | high | - | Sets current waypoint to the waypoint nearest (XZ) to the strat, excluding the current one. 54f4b0 | | 0x17c | `nop_0x17c` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x17d | `nop_0x17d` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x17e | `nop_0x17e` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x17f | `nop_0x17f` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x180 | `addTint` | - | 3 | 0 | | high | - | pops b (top), g, r (fixed deltas); adds them to the strat's tint (own +0x133..135, or the level ambient at 0x584644+0x4C if none), clamps 0..255, stores and enables own tint (+0x136). 54fef0 | | 0x181 | `setAnimFrame` | - | 1 | 0 | | high | - | pops frame (fixed); if an anim is set (+0x14) sets current frame +0x110 (out of range/negative -> 0), clears +0x114 and sets flag 8 (anim changed). 554d50 | | 0x182 | `nop_0x182` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x183 | `showSaveSlotInfo` | - | 1 | 0 | 1 | medium | - | pops slot (fixed 1..3); draws the save-game slot info text ('Gespeichertes Spiel n', chapter, etc.) for the main menu (FUN_0040db90). 554da0 | | 0x184 | `pushTintR` | - | 0 | 1 | | high | - | Pushes own tint red byte (+0x133) as fixed. 554dc0 | | 0x185 | `pushTintG` | - | 0 | 1 | | high | - | Pushes own tint green byte (+0x134) as fixed. 554de0 | | 0x186 | `pushTintB` | - | 0 | 1 | | high | - | Pushes own tint blue byte (+0x135) as fixed. 554e00 | | 0x187 | `emitterInit` | - | 7 | 0 | 113 | medium | stSpawnparticle | pops colour/texture (top, raw), z, y, x (vector/offset), type (fixed 1..0x2B preset, or >=0x1000 type flags), size/speed (fixed, 0x1000 default), slot (0..2, >=3 = extra slot +0x153); (re)initialises the strat's particle emitter in that slot (records at 0x5FE230, 0x34 bytes; texture/colour stored per type). 552f40 | | 0x188 | `emitParticles` | - | 3 | 0 | | medium | - | pops yStep (top, fixed), count, slot; emits count particles from the slot's emitter at own position with random XZ velocity, each raised by yStep. 552fb0 | | 0x189 | `randSigned` | - | 1 | 1 | 922 | high | - | pops n; pushes a random value in (-n, n) ((rand32 - rand32) % n, same fixed scale as n). 54f9a0 | | 0x18a | `emitterSetParams` | - | 5 | 0 | 113 | medium | - | Pops e (top), d, c, b, slot (>>12): pending particle settings of this strat (slot 0–2 → record index at strat+0x150+slot, ≥3 → +0x153, record allocated on demand in the 0x34-byte table 0x5FE23C): b = size scale (1.0 = default), c>>12 = extra lifetime in frames, e≠0: +0x246 = e (drift), +0x23C = d; e==0: +0x25C = (d>>12)*32-32 (sprite size). spawnParticle consumes and resets the +0x153 record; same as spawnParticle type 0x19. 5530b0 | | 0x18b | `emitterSetColour` | - | 5 | 0 | 9 | medium | - | Pops colour (top, raw packed, see 0x15d), b, g, r, slot: pending particle colour for the next particle(s) of this strat (record as 0x18a; same as spawnParticle type 0x1e): +0x250 = colour; r without fraction = alpha r>>12 (7 bits), else r,g,b>>12 = per-channel fade, +0x243 = 0x80; alpha 0 = 0xFF/lifetime. 553100 | | 0x18c | `emitParticlesStill` | - | 3 | 0 | 50 | medium | - | pops yStep (top, raw fixed), count, slot; emits count particles from the slot's emitter at own position without velocity, stacked by yStep. 552ff0 | | 0x18d | `stubPop2_0x18d` | - | 2 | 0 | | high | - | Stub FUN_00555090: pops and discards 2 values (feature removed in PC port). 555090 | | 0x18e | `stubPop2_0x18e` | - | 2 | 0 | | high | - | Stub FUN_00555090: pops and discards 2 values (feature removed in PC port). 555090 | | 0x18f | `clampToWaypointBox` | - | 0 | 0 | 155 | high | - | Clamps own x/z (+0x30/+0x38) into the XZ box spanned by the current waypoint and the next one. 54f390 | | 0x190 | `processBeforeCamera` | - | 0 | 0 | 107 | high | - | If no camera strat (0x6D9E28) yet: re-executes next frame (pc-=4, yield). Else unlinks self from the strat list (0x6D9E38) and reinserts it directly before the camera so it updates before the camera. 554e60 | | 0x191 | `processBeforeCamera2` | - | 0 | 0 | 84 | high | - | Same as 0x190 (waits for camera, then moves self just before the camera in the update list); functionally identical alias. 554f30 | | 0x192 | `endLevel` | - | 3 | 0 | 91 | medium | stEndlevel | pops sub (top), level, world (fixed); saves current level as previous, sets next level, sets 'all coins collected'/completion flags, updates furthest-progress 0x585018, state 0x584638 = 10 and starts the fade-out (world=level=sub=7 means return to the level map). 54d620 | | 0x193 | `stubPop1Push0_0x193` | - | 1 | 1 | | high | - | Stub FUN_005550b0: pops 1 value and pushes 0. 5550b0 | | 0x194 | `stubPop1Push0_0x194` | - | 1 | 1 | | high | - | Stub FUN_005550b0: pops 1 value and pushes 0. 5550b0 | | 0x195 | `stubPop2_0x195` | - | 2 | 0 | | high | - | Stub FUN_00555090: pops and discards 2 values (feature removed in PC port). 555090 | | 0x196 | `stubPop2_0x196` | - | 2 | 0 | | high | - | Stub FUN_00555090: pops and discards 2 values (feature removed in PC port). 555090 | | 0x197 | `nop_0x197` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x198 | `nop_0x198` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x199 | `nop_0x199` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x19a | `nop_0x19a` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x19b | `nop_0x19b` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x19c | `nop_0x19c` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x19d | `sqrt` | - | 1 | 1 | 67 | high | - | pops v (fixed); pushes fixed sqrt(v) (fsqrt of v/4096, rescaled). 54f610 | | 0x19e | `nop_0x19e` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x19f | `nop_0x19f` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x1a0 | `setWaypointParam1` | - | 1 | 0 | 167 | high | - | pops v; sets current waypoint +0x08 = (v>>12)&0xFFF (readable as own property 9). 54ea80 | | 0x1a1 | `setWaypointParam2` | - | 1 | 0 | 245 | high | - | pops v; sets current waypoint +0x0C = (v>>12)&0xFFF (readable as own property 10). 54eab0 | | 0x1a2 | `setWaypointParam3` | - | 1 | 0 | | high | - | pops v; sets current waypoint +0x10 = (v>>12)&0xFFF (readable as own property 11). 54eae0 | | 0x1a3 | `stubPop1_0x1a3` | - | 1 | 0 | | high | - | Stub FUN_00554fb0: pops and discards 1 value. 554fb0 | | 0x1a4 | `stubPop1_0x1a4` | - | 1 | 0 | | high | - | Stub FUN_00554fb0: pops and discards 1 value. 554fb0 | | 0x1a5 | `nop_0x1a5` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x1a6 | `emitterKill` | - | 1 | 0 | | high | - | pops slot (fixed); frees the strat's particle emitter in that slot (+0x150+slot = 0xFF) and resets the record. 553150 | | 0x1a7 | `stubPush0_0x1a7` | - | 0 | 1 | | high | - | Stub FUN_0054e880: pushes 0. 54e880 | | 0x1a8 | `processFirst` | - | 0 | 0 | 1 | high | - | Moves self to the head of the strat update list (0x6D9E38) if not already there. 554e20 | | 0x1a9 | `setRain` | - | 4 | 0 | 4 | medium | - | Weather: pops texture (top, raw tex index → 0x6D9BE8, read by the rain renderer), windZ (>>12 → 0x578EF4), c (>>12 → 0x6D9BF4, only used for the off test), windX (>>12 → 0x578EF0); each raindrop restarts with velocity (windX, -256, windZ) per frame. windX, c, windZ all 0 = rain off (drops cleared, 0x6D9BE4 = 0), else on. Rain type: setRain(v0, v1, v2, tex:768) with params 16.0, 0, 16.0. 554fc0 | | 0x1aa | `stubPop1Push0_0x1aa` | - | 1 | 1 | | high | - | Stub FUN_005550b0: pops 1 value and pushes 0. 5550b0 | | 0x1ab | `stubPop2_0x1ab` | - | 2 | 0 | | high | - | Stub FUN_00555090: pops and discards 2 values (feature removed in PC port). 555090 | | 0x1ac | `stubPop1Push0_0x1ac` | - | 1 | 1 | | high | - | Stub FUN_005550b0: pops 1 value and pushes 0. 5550b0 | | 0x1ad | `stubPop2Push0_0x1ad` | - | 2 | 1 | | high | - | Stub FUN_005550d0: pops 2 values and pushes 0. 5550d0 | | 0x1ae | `stubPop3_0x1ae` | - | 3 | 0 | | high | - | Stub FUN_005550f0: pops and discards 3 values. 5550f0 | | 0x1af | `setWeatherRender` | - | 1 | 0 | | medium | - | pops mode (fixed): 0 installs the normal rain/weather update+render callbacks (0x5FF034/38), 1 installs no-op callbacks and clears 0x6D94D0 (weather off). 555040 | | 0x1b0 | `emitParticlesVel` | - | 6 | 0 | 159 | medium | - | pops vz (top), vy, vx (velocity), yStep, count, slot (last three fixed >>12); emits count particles from the slot's emitter at own position with the given velocity, stacked by yStep. 553030 | | 0x1b1 | `nop_0x1b1` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | ## Properties (`pushProp`/`popProp` id; same ids for player/parent/camera/… variants) | id | name | get | set | conf | semantics | |---|---|---|---|---|---| | 0 | `zero_0` | yes | no | high | Always pushes 0 (unused id; also 0x13, 0x15, 0x47, 0x75, 0x76, 0x77, 0x98, 0x9e, 0xc1, 0xd8, 0xed, 0xee, 0x102 push 0). | | 1 | `unk_1` | yes | no | low | DAT_006d94d0 << 12 (int global, cleared in FUN_00426... init; meaning unknown). | | 3 | `wpEndFlags` | yes | no | high | Current waypoint (+0x120) link bits: bit0 = no previous node (node[0]==0, first), bit1 = no next node (node[1]==0, last). Raw int. | | 4 | `wpParam` | yes | yes | medium | Current waypoint field +0x28 (raw 32-bit, per-node parameter). | | 5 | `distToWp` | yes | no | high | 3D distance from strat position (+0x30) to current waypoint position (wp+0x18), 20.12 (FUN_00404bb0, sqrt). | | 6 | `wpX` | yes | yes | high | Current waypoint x (wp+0x18), 20.12. | | 7 | `wpY` | yes | yes | high | Current waypoint y (wp+0x1C), 20.12. | | 8 | `wpZ` | yes | yes | high | Current waypoint z (wp+0x20), 20.12. | | 9 | `wpRotX` | yes | no | medium | Current waypoint int field +0x08 << 12 (node rotation x in 4096 table units, per notes). | | 10 | `wpRotY` | yes | no | medium | Current waypoint int field +0x0C << 12 (node yaw in 4096 table units; e.g. checkpoint respawn yaw). | | 11 | `wpRotZ` | yes | no | low | Current waypoint int field +0x10 << 12 (third node angle/param). | | 12 | `playerDistToWp` | yes | no | high | 3D distance from the player (0x6D9E1C) to this strat's current waypoint, 20.12; 100.0 (0x64000) if no player. | | 13 | `angleToWp` | yes | no | high | Yaw from the strat to its current waypoint: atan2(dx,dz) (FUN_00404d60), 24-bit angle (0x1000000 = full turn, 4096 table units <<12). | | 14 | `animFrame` | yes | no | high | Current anim frame +0x110 << 12. | | 15 | `animPlaying` | yes | no | high | Flag +0xE8 bit 3 (0x8, anim playing) as 0/1. | | 16 | `floorHeight` | yes | yes | high | Floor height under the strat, collision record (+0xC0)+0x00, 20.12 (0xFFFF0000 = no floor). Get returns 0 if no record. | | 17 | `floorMaterial` | yes | no | high | Floor surface/material id, short at (+0xC0)+0x04, << 12 (0xFFFF = none; 16 = level door trigger). 0 if no record. | | 18 | `ceilingMaterial` | yes | no | medium | Short at (+0xC0)+0x30 << 12: material of the surface above (set together with ceiling height +0x28 in the collision code, 0xFFFF none). | | 19 | `zero_19` | yes | no | high | Always 0. | | 20 | `slideAngle` | yes | no | low | Short at (+0xC0)+0x2C << 12: direction (atan2 of old->new pos) written when the strat is pushed back off an edge/wall; 4096 units. | | 21 | `zero_21` | yes | no | high | Always 0 (both branches push 0). | | 22 | `collisionRadius` | yes | yes | high | Collision radius, short at +0xD2 (raw, not shifted). Set writes a full 32-bit word at +0xD2 (also clobbers the short at +0xD4). | | 29 | `isActivated` | yes | no | high | Map-instance record (+0xF0) byte +0x44 bit 0x8 (persistent "activated" state, set by op 0x92). Returns 8 or 0. No null check. | | 30 | `isCollected` | yes | no | high | Map-instance record (+0xF0) byte +0x44 bit 0x4 (persistent "collected", set by op 0x93). Returns 4 or 0. No null check. | | 31 | `onGround` | yes | no | medium | Flag +0xEC & 0x2 (standing on a floor; slope/platform code FUN_004054c0 requires it). Returns 2 or 0. | | 32 | `flagE8_400000` | yes | no | low | Flag +0xE8 bit 22 (0x400000) as 0/1. | | 33 | `flagE8_800000` | yes | no | low | Flag +0xE8 bit 23 (0x800000) as 0/1. | | 34 | `x` | yes | yes | high | Position x +0x30, 20.12. | | 35 | `y` | yes | yes | high | Position y +0x34, 20.12. | | 36 | `z` | yes | yes | high | Position z +0x38, 20.12. | | 37 | `rotX` | yes | yes | high | Rotation x (pitch) +0x20; get masks to 24 bits (0x1000000 = full turn), set stores raw. | | 38 | `rotY` | yes | yes | high | Rotation y (yaw) +0x24; 24-bit angle, 0x1000000 = full turn. | | 39 | `rotZ` | yes | yes | high | Rotation z (roll) +0x28; 24-bit angle. | | 41 | `angleToPlayer` | yes | no | high | Yaw from this strat to the player: atan2(px-x, pz-z) (FUN_00404d60(player+0x30, self+0x30)), 24-bit angle; 0 if no player. (Notes called 41 "distance to player" - code is an angle.) | | 42 | `padHeld` | yes | no | high | Joypad buttons currently held, DAT_005FCF20 (bit mask: 0x10 up, 0x40 down, 0x80 left?, 0x20 right?, 0x1/0x8/0x400.. buttons; 0x10000-0x80000 = direction relative to player yaw). | | 43 | `padReleased` | yes | no | high | Buttons released this frame, DAT_005FCF34 (= old & ~new). | | 44 | `padPressed` | yes | no | high | Buttons newly pressed this frame, DAT_005FCF30 (= new & ~old). | | 45 | `distToPlayer` | yes | no | high | 3D distance to the player, cached in +0x1C (computed lazily as sqrt of +0x148, the squared distance updated per frame), 20.12. | | 47 | `scale` | yes | no | high | Scale y +0x64 (used as the uniform scale value), 20.12; see op 0x55. | | 48 | `scaleX` | yes | no | high | Scale x +0x60, 20.12. | | 49 | `scaleY` | yes | no | high | Scale y +0x64, 20.12. | | 50 | `scaleZ` | yes | no | high | Scale z +0x68, 20.12. | | 51 | `stratCount` | yes | no | medium | Number of strats in use DAT_006D9DC8 << 12. | | 52 | `stratCapacity` | yes | no | medium | Level header (DAT_00584648)+0x08 << 12 (max strat count of the level; compared against stratCount on spawn). | | 53 | `distToWpXZ` | yes | no | high | Horizontal (x/z) distance from strat to current waypoint, 20.12 (FUN_00404c50). | | 54 | `boneX` | yes | no | medium | +0xD8: x of the bone/attachment point computed by op 0xc7 (useBone), 20.12 world. | | 55 | `boneY` | yes | no | medium | +0xDC bone point y. | | 56 | `boneZ` | yes | no | medium | +0xE0 bone point z. | | 57 | `playerPtr` | yes | no | high | Pointer to the player strat (DAT_006D9E1C); 0 if none (usable as "player exists"). | | 58 | `camLookAtX` | yes | yes | medium | Camera look-at point x DAT_006D9D80, 20.12 (default 0; cut-scene cameras write it). | | 59 | `camLookAtY` | yes | yes | medium | Camera look-at point y DAT_006D9D84 (default 1.0). | | 60 | `camLookAtZ` | yes | yes | medium | Camera look-at point z DAT_006D9D88. | | 61 | `tribe` | yes | no | high | Current level tribe DAT_00584EB4 << 12 (level id part 1, %d_%d_%d file names). | | 62 | `world` | yes | no | high | Current level world DAT_00584EB8 << 12. | | 63 | `chapter` | yes | no | high | Current level chapter DAT_00584EBC << 12. | | 64 | `map` | yes | no | high | Current map/sub-level DAT_00584EC0 << 12. | | 65 | `hasCamTarget` | yes | no | medium | -1 if a camera target strat (DAT_006D9E30, op 0xc9) is set, else 0. | | 66 | `hasCamTarget2` | yes | no | medium | -1 if the second camera target (DAT_006D9E34, op 0xca) is set, else 0. | | 67 | `padType` | yes | no | low | DAT_005FCF18 << 12: 3 = digital pad, 2 = direction/analog input active this frame. | | 68 | `camDistToTarget` | yes | no | high | 3D distance camera strat (0x6D9E28) -> camera target (0x6D9E30), 20.12; 0 if no camera. | | 69 | `camDistToTarget2` | yes | no | high | 3D distance camera -> second target (0x6D9E34), 20.12; 0 if no camera. | | 70 | `camTargetYawDiff` | yes | no | high | Signed yaw difference target.rotY - camera.rotY (wrapped to +-0x800000, FUN_0054dae0). No null checks. | | 72 | `camDistToTargetXZ` | yes | no | high | Horizontal distance camera -> target (FUN_00404cc0), 20.12. No null check. | | 73 | `camDistToTarget2XZ` | yes | no | high | Horizontal distance camera -> second target, 20.12. No null check. | | 75 | `stickX` | yes | no | high | Analog/digital stick x DAT_005FCF1C (-0x2000..0x1FC0, i.e. about +-2.0 fixed). | | 76 | `stickY` | yes | no | high | Stick y DAT_005FCF2C (same range). | | 77 | `stickMagnitude` | yes | no | high | Stick deflection DAT_005FCEFC, raw int 0..0xB5 (thresholds: 42 deadzone, 84 direction bits, see ids 94-97/130-131). | | 78 | `stickAngle` | yes | no | high | Stick direction DAT_005FCF4E (short, 4096 units) << 12. | | 79 | `stickAngleWorld` | yes | no | high | (stick angle + camera yaw DAT_005FCF00) << 12, masked to 24 bits: stick direction in world yaw. | | 80 | `stick2X` | yes | no | low | DAT_005FCF28, never written by the exe (second stick set, always 0). | | 81 | `stick2Y` | yes | no | low | DAT_005FCF24, never written (always 0). | | 82 | `stick2Magnitude` | yes | no | low | DAT_005FCEF8, never written (always 0). | | 83 | `stick2Angle` | yes | no | low | Short DAT_005FCF4C << 12, never written. | | 84 | `stick2AngleWorld` | yes | no | low | (camera yaw + DAT_005FCF4C) << 12 masked 24 bits. | | 85 | `slopeForward` | yes | no | medium | Floor normal rotated into the strat's yaw frame, forward component DAT_0057DDA8 (FUN_004054c0; 0 unless onGround), 20.12. | | 86 | `slopeSide` | yes | no | medium | Floor normal, sideways component in the strat's frame DAT_0057DD90, 20.12. | | 87 | `slopeAngle` | yes | no | medium | Downhill direction relative to the strat's yaw DAT_0057DD94 (0..0xFFF) << 12. | | 88 | `padAux` | yes | no | low | DAT_005FCF58 (extra input bits, cleared when >1 pads). | | 90 | `padAuxPressed` | yes | no | low | DAT_005FCF60 = new & ~old of padAux. | | 91 | `unk_5b` | yes | no | low | DAT_00584F10 << 12 (game state global, unknown). | | 92 | `health` | yes | no | medium | Player health DAT_00584E70 (fixed, starts at 5.0, HUD shows it; reset to 5.0 on respawn). Same value as id 189 (settable there). | | 93 | `unk_5d` | yes | no | low | DAT_0058464C (raw, game-state pointer/flag). | | 94 | `stickWalkThreshold` | yes | no | medium | Constant 84 (0x54, raw int): stick magnitude above which direction bits are generated. | | 95 | `stickRunThreshold` | yes | no | medium | Constant 123 (0x7B, raw int). | | 96 | `stickWalkThreshold2` | yes | no | medium | Constant 84 (duplicate of 94). | | 97 | `stickRunThreshold2` | yes | no | medium | Constant 123 (duplicate of 95). | | 98 | `hasWaypoints` | yes | no | high | 1.0 if the EXECUTING strat (not the queried one) has a first waypoint (+0x118), else 0. For 0x1c (player prop) this still checks the caller. | | 99 | `distToBoss` | yes | no | high | 3D distance from the boss strat (DAT_006D9E24, op 0xef) to this strat, 20.12; 100.0 if none. | | 100 | `distToBossXZ` | yes | no | high | Horizontal distance boss -> this strat, 20.12; 100.0 if none. | | 101 | `zoneX` | yes | no | low | Map zone/cell record containing the strat (FUN_0054d560, same x/z grid cell, nearest y) field +0x0C, integer part (& 0xFFFFF000); -1.0 if none. | | 102 | `zoneY` | yes | no | low | Zone record field +0x10 integer part; -1.0 if none. | | 103 | `zoneZ` | yes | no | low | Zone record field +0x14 integer part; -1.0 if none. | | 104 | `distToWpSq` | yes | no | high | Squared 3D distance to current waypoint ((d>>6)^2 summed, i.e. 20.12 of world units squared). Same as 194. | | 105 | `distToWpSqXZ` | yes | no | high | Squared horizontal distance to current waypoint. | | 106 | `flag83730Clear` | yes | no | low | 1.0 if DAT_00583730 == 0 (FUN_00414fb0), else 0. | | 107 | `distToPlayerXZ` | yes | no | high | Horizontal distance player -> this strat, 20.12; 100.0 if no player. | | 108 | `saveByte5219` | yes | no | low | DAT_00585219 << 12 (per-save-slot byte, reset to 0 on new game). | | 110 | `queueAEmpty` | yes | no | low | 1.0 if DAT_006D9858 < 1 (message/stream queue A empty), else 0. | | 111 | `queueBEmpty` | yes | no | low | 1.0 if DAT_006D94E8 < 1 (queue B empty; also blocks HUD counters), else 0. | | 120 | `camFloorHeight` | yes | yes | medium | Get: floor height of the map cell under the camera DAT_00586424 (-16.0 if outside the map). Set: writes the OVERRIDE DAT_0058641C (non-zero replaces the computed value). Get and set use different variables. | | 121 | `camX` | yes | yes | high | Camera position x DAT_006D9D20 (copied from the camera strat each frame), 20.12. | | 122 | `camY` | yes | yes | high | Camera position y DAT_006D9D24. | | 123 | `camZ` | yes | yes | high | Camera position z DAT_006D9D28. | | 124 | `flagEC_1000000` | yes | no | low | Flag +0xEC bit 24 as 0/1. | | 125 | `flagEC_2000000` | yes | no | low | Flag +0xEC bit 25 as 0/1. | | 126 | `hitDepth` | yes | no | medium | Short +0xD4 (raw): penetration depth of the last player-vs-strat sphere hit (FUN_004051d0), 0xFFFF none. | | 127 | `hitAngle` | yes | no | medium | Short +0xD6 << 12: direction of the last sphere hit (4096 units; player gets the opposite of the strat). | | 128 | `unk_80` | yes | no | low | DAT_00585004 << 12 (unknown game global). | | 129 | `zoneFlags` | yes | no | low | Zone record (FUN_0054d560) +0x20 & 0xC00, << 12; -1.0 if none. | | 130 | `stickDeadzone` | yes | no | medium | Constant 42 (0x2A, raw int). | | 131 | `stickDeadzone2` | yes | no | medium | Constant 42 (duplicate). | | 132 | `oldX` | yes | yes | medium | Previous-frame position x +0x50, 20.12 (collision code restores it on edge push-back). | | 133 | `oldY` | yes | yes | medium | Previous position y +0x54. | | 134 | `oldZ` | yes | yes | medium | Previous position z +0x58. | | 135 | `unk_6da2c0` | yes | no | low | DAT_006DA2C0, no other reference (always 0). | | 136 | `unk_6da2c4` | yes | no | low | DAT_006DA2C4, no other reference (always 0). | | 137 | `queuesEmpty` | yes | no | low | 1.0 if both queue A and queue B are empty (ids 110 and 111), else 0. | | 138 | `alpha` | yes | yes | medium | Transparency +0x10C (renderer: < 0x1000 = translucent, 1.0 = opaque), 20.12. | | 139 | `oldRotX` | yes | yes | medium | Previous rotation x +0x40 (24-bit masked on get). | | 140 | `oldRotY` | yes | yes | medium | Previous yaw +0x44 (compared with +0x24 by the collision code). | | 141 | `oldRotZ` | yes | yes | medium | Previous rotation z +0x48. | | 142 | `optionFlag80000` | yes | no | low | DAT_006DA330 & 0x80000 (global option/debug flag word). | | 143 | `camScale` | yes | yes | low | DAT_006D9D30, camera value initialised to 1.0 (zoom/fov factor?). | | 144 | `levelHeaderC` | yes | no | low | Level header (DAT_00584648)+0x0C ushort << 12. | | 145 | `slopeSteepness` | yes | no | medium | 1.0 - floor normal y (DAT_0057DDA4) << 12: 0 on flat ground (FUN_004054c0). | | 147 | `levelTableByte` | yes | no | low | Byte table 0x585024[map + (world + tribe*10)*4] << 12 (FUN_0041af40(tribe, world, map)); bss, never written by the game (always 0) – but world-9 coin counters of TestLevel chapters 22–31 land in its tribe-1 part (see testlevel-chapters.md). | | 149 | `flagEC_1` | yes | no | low | Flag +0xEC & 0x1. | | 150 | `flagEC_8000000` | yes | no | low | Flag +0xEC & 0x8000000. | | 151 | `cheat5` | yes | no | medium | Cheat toggle bits DAT_00584710 & 0x20 (button-sequence cheats, FUN_0041a0xx). | | 153 | `frameCounter` | yes | no | high | Strat-update frame counter DAT_006D9E10 (+1.0 per frame). | | 154 | `hitSphere` | yes | no | medium | Byte +0x130 << 12: index of the collision sphere hit by the player (FUN_004051d0). | | 155 | `unk_6d9d38` | yes | no | low | DAT_006D9D38, no other reference. | | 156 | `unk_6d9cf0` | yes | no | low | DAT_006D9CF0, no other reference. | | 157 | `isFloorCollisionSolid` | yes | no | low | 1 (raw) if +0xEC has both 0x8000 and 0x10000 set, else 0. | | 159 | `scratch6d9e68` | yes | yes | low | DAT_006D9E68 (only accessed by strats). | | 160 | `saveEnabled` | yes | yes | low | DAT_006D9E74 (1.0 enables the save-game prompt, reset to 0 on level start). | | 161 | `hudValueA` | yes | yes | low | DAT_006DA300 (HUD element value, shown via >>12, reset per level). | | 162 | `hudValueB` | yes | yes | low | DAT_006DA2F8 (HUD element value, reset per level). | | 163 | `audioMode` | yes | yes | low | DAT_006DA2FC: 3.0/4.0/5.0 from the sound output menu (Stereo/Quatro/Surround); also written (slot+1) by save code. | | 164 | `instanceData0` | yes | yes | low | Map-instance record (+0xF0)+0x28 -> word 0. Set returns NULL (crash) unless record+0x24 != 0. Get pushes nothing if no record. | | 165 | `instanceData1` | yes | yes | low | Map-instance record (+0xF0)+0x28 -> word 1. | | 166 | `floorCollisionOn` | yes | no | medium | Flag +0xEC & 0x8000 (floor collision, ops 0xa5/0xa6). | | 169 | `lives` | yes | yes | low | DAT_00584E6C (fixed, starts at 5.0, saved per slot) - lives or max health. | | 171 | `saveProgressA` | yes | no | low | DAT_00585008 << 12: last played tribe (KSV +0x3E, set by endLevel). | | 172 | `progressWorld` | yes | no | low | DAT_0058500C << 12: last played world (KSV +0x3F, set by endLevel; 8 = finale). | | 173 | `progressChapter` | yes | no | low | DAT_00585010 << 12: last played chapter (KSV +0x40; 6 with world 8 = last level). | | 174 | `saveProgressB` | yes | no | low | DAT_00585014 << 12: last played map (KSV +0x41). | | 175 | `unk_6da308` | yes | no | low | DAT_006DA308, no other reference. | | 178 | `cheat4` | yes | no | medium | DAT_00584710 & 0x10 (cheat toggle). | | 179 | `hudFlags` | yes | yes | medium | DAT_006DA2E0 HUD element enable mask (default 0x3F000; 0x2000 timer, 0x8000/0x10000/0x20000/0x40000 counters). | | 181 | `gameState1d74` | yes | yes | low | DAT_00581D74 (game/menu state, checked == 0 for normal play). | | 182 | `camFlag800000` | yes | no | low | Camera strat +0xEC & 0x800000 (0 if no camera). | | 183 | `slopeNormalX` | yes | no | medium | Floor normal x DAT_0057DD9C (world, 20.12; FUN_004054c0). | | 184 | `slopeNormalZ` | yes | no | medium | Floor normal z DAT_0057DDA0. | | 185 | `wpParam2` | yes | yes | medium | Current waypoint field +0x2C (raw); 0 / NULL if no waypoint. | | 186 | `hitRadius` | yes | yes | medium | +0x13C: player interaction radius (player collides when squared player distance +0x148 <= r*r), 20.12. | | 187 | `hitDamage` | yes | yes | medium | +0x140: damage dealt on contact (copied into the other strat's +0x144). | | 188 | `damageTaken` | yes | no | medium | +0x144: damage received from the last contact (player cleared to 0 each frame). | | 189 | `health2` | yes | yes | medium | DAT_00584E70 = health (same as 92, settable). | | 190 | `levelRecord` | yes | yes | medium | Coin counter of the current level: u32 DAT_00584F1C[chapter + world*6] (coins << 12; HUD and tally show it, zeroed on level start, KSV keeps worlds 0–8 as u16). World 9 has no row: TestLevel chapter c hits 0x584FF4 + 4c (chapter 9 = furthest progress 0x585018) – only chapters 1 and 32–49 are free (testlevel-chapters.md). | | 191 | `counterC` | yes | yes | low | DAT_00584FFC: persistent HUD counter (icon 0x150), saved. | | 192 | `counterA` | yes | yes | low | DAT_00584FF4: persistent HUD counter (icon 0x184, displayed up to 999) - probably coins. | | 201 | `distToPlayerSq` | yes | no | high | +0x148: cached squared distance to the player ((d>>6)^2 sum), updated each frame when tracking (op 0x30). | | 202 | `distToPlayerSqXZ` | yes | no | high | Squared horizontal distance player -> strat (FUN_00404c90); 100.0 if no player. | | 203 | `soundVecX` | yes | yes | low | DAT_006DA2CC; on the next set of 203/204 the magnitude sqrt(x^2+y^2)*4 is passed to FUN_00546140 (sound/volume parameter). | | 204 | `soundVecY` | yes | yes | low | DAT_006DA2D0, see 203. | | 210 | `collisionHeight` | yes | yes | medium | Collision record (+0xC0)+0x18: strat height/size used for ceiling tests (ceiling hit if ceiling <= y + this), 20.12. Get 0 if no record. | | 211 | `mapFloorHeight` | yes | no | low | (+0xC0)+0x1C: floor height from the landscape test (FUN_004036d0), 0xFFFF0000 none. No null check. | | 212 | `mapFloorMaterial` | yes | no | low | Short (+0xC0)+0x24 << 12: material of that floor (0xFFFF none). | | 213 | `objFloorHeight` | yes | no | low | (+0xC0)+0x20: floor height from the strat-object test (FUN_00403ad0, skipped with +0xE8 bit 0x400). | | 214 | `objFloorMaterial` | yes | no | low | Short (+0xC0)+0x26 << 12: material of the object floor. | | 215 | `wallMaterial` | yes | no | low | Short (+0xC0)+0x3A << 12 (material of the wall/side surface hit, set with object/face +0x3C/+0x3E). | | 217 | `collisionField38` | yes | yes | low | Short (+0xC0)+0x38 raw on get; set writes 32 bits at +0x38 (also clobbers +0x3A). | | 218 | `hudDigit` | yes | yes | low | DAT_006DA290: HUD single-digit counter (shown as '0'+value>>12). | | 226 | `animFrameCount` | yes | no | high | Anim header (+0x14)+0x08 << 12 (number of frames). No null check. | | 227 | `angleToCamLookAt` | yes | no | medium | Yaw from the strat to the camera look-at point (DAT_006D9D80), 24-bit angle. | | 228 | `skyParamA` | yes | yes | low | DAT_0057D830 (render global, sky/background). | | 229 | `skyParamB` | yes | yes | low | DAT_0057D83C. | | 230 | `skyParamC` | yes | yes | low | DAT_0057D840. | | 231 | `skyRotation` | yes | yes | low | DAT_0057D834: rotation added to a background model's yaw (>>12 & 0xFFF). | | 232 | `hudTimer` | yes | yes | low | DAT_006DA304: HUD timer/counter value (>>12 displayed, element bit 0x2000). | | 233 | `animPtr` | yes | no | high | Current anim address +0x14 (0 = none). | | 234 | `cheat1` | yes | no | medium | DAT_00584710 & 0x2 (cheat toggle). | | 236 | `hudRefresh` | yes | yes | low | DAT_006DA2DC (forces HUD counter redraw when non-zero). | | 239 | `unk_57ddb0` | yes | no | low | DAT_0057DDB0, no other reference. | | 240 | `unk_57ddb4` | yes | no | low | DAT_0057DDB4, no other reference. | | 241 | `unk_57ddb8` | yes | no | low | DAT_0057DDB8, no other reference. | | 242 | `drawDistance` | yes | no | low | 1000.0 unless +0xEC bit 0x10000; else (bit 0x400000 ? DAT_0058658C : DAT_00586590) + 0.5 (view/clip distance globals). | | 243 | `ceilingHeight` | yes | no | medium | (+0xC0)+0x28: height of the surface above (1000.0 default when ceiling test enabled by +0xE8 0x200000). No null check. | | 244 | `zoneParam` | yes | no | low | DAT_006DA298: short +0x38 of the zone record the strat entered (op FUN_0054df30, used as conveyor/offset). | | 249 | `wpPtr` | yes | yes | high | Current waypoint pointer +0x120 (set allows jumping to a stored node). | | 250 | `counterB` | yes | yes | low | DAT_00584E60: HUD counter (icon 0x11C), reset when entering a different level. | | 253 | `musicBusy` | yes | no | low | 1 (raw) if FUN_00546600(DAT_006D94B4,0) == 2 (stream/voice state), else 0. | | 265 | `musicTrack` | yes | no | medium | Current music track DAT_00586430 << 12 (level header +0x58, 0x23/0x27 for special modes). |