Skip to content

Zenkai Example Scripts

Johnathon edited this page Jun 1, 2026 · 5 revisions

How to Read Scripts

Every script is a flat stream of bytes. To decode it, read the first byte and look it up in the Main Dispatch Table — this tells you what kind of node you're dealing with. Each node type then consumes however many following bytes it needs, and execution moves to the next node.

The two most important things to know before reading any script:

  • Numbers are ZigZag encoded. A value like 0x81, 0x70 is not two separate bytes — it is a single multi-byte integer. The high bit of each byte signals whether another byte follows. Once assembled, the raw value is zigzag-decoded: even values become positive, odd values become negative. So 2 is 1, 6 becomes 3, 0x81 0x70 is 120, 0x81 0x50 is 104.
  • Opcodes are looked up separately. When a Step node is encountered, the next byte is an index into the Opcode Table, not the dispatch table. 0x02, 0x23 means "Step, then execute opcode index 35 (0-based)" — which resolves to LoadMapWithEntities.

Arguments are passed via a stack. Nodes like PushByte and PushMultiVarint push values onto it. Opcodes then pop what they need from the top, so arguments are pushed before the opcode that consumes them.

Intro Sequence Script #1

ROM Address: 0x083B827B

Raw bytes: 0x1D, 5, 2, 6, 2, 0x81, 0x70, 0x81, 0x50, 2, 0x23, 0, 0xB4, 2, 0x45, 0, 0xF0, 2, 0x28, 2, 0x2D, 0, 0x17, 2, 0x31, 0x11, 0, 0, 0

A world transition sequence. Pushes the destination map arguments onto the stack, loads the map with entities, waits a specific number of frames, fades out, swaps the sprite palette, and starts a music track.

Decode

Bytes Node Resolves To Notes
0x1D, 5, 2, 6, 2, 0x81 0x70, 0x81 0x50, 2 PushMultiVarint(5) [1, 3, 120, 104, 1] Pushes 5 zigzag-encoded varints — world 1, area 3, spawn X 120, spawn Y 104, variation 1
0x02, 0x23 Step(0x23) LoadMapWithEntities Pops all 5 stack values — loads world 1 area 3 at position 120, 104 with variation 1
0x00, 0xB4 PushByte 180 Raw byte, no encoding
0x02, 0x45 Step(0x45) WaitFrames Pops 180 — waits 180 frames before continuing
0x00, 0xF0 PushByte 240 Raw byte, no encoding
0x02, 0x28 Step(0x28) FadeOut Pops 240 — fades out over 240 frames
0x02, 0x2D Step(0x2D) UploadSpritePalette No args. Copies sprite palette to VRAM via DMA
0x00, 0x17 PushByte 23 Raw byte, no encoding
0x02, 0x31 Step(0x31) PlayMusic Pops 23 — starts music track 23
0x11, 0, 0, 0 Terminator Standard script end marker

Intro Sequence Script #2

ROM Address: 0x083B831B

Raw bytes: 0, 2, 2, 0x18, 0, 0x78, 2, 0x2A, 0x1D, 2, 6, 0xC, 2, 0x62, 0, 3, 2, 0x46, 0x1D, 5, 2, 2, 2, 0x83, 0x10, 0x8A, 0x30, 2, 0x27, 0, 0x78, 2, 0x2B, 0x11, 0, 0, 0

A level up transition sequence. Disables a display layer, fades to white, sets the specified character to level 6, then warps to zone 1 area 1.

Decode

Bytes Node Resolves To Notes
0x00, 0x02 PushByte 2 Raw byte, no encoding
0x02, 0x18 Step(0x18) DisableLayer Pops 2 — disables display layer 2
0x00, 0x78 PushByte 120 Raw byte, no encoding
0x02, 0x2A Step(0x2A) FadeToWhite Pops 120 — fades to white over 120 frames
0x1D, 2, 6, 0x0C PushMultiVarint(2) [3, 6] Pushes 2 zigzag-encoded varints — char index 3, level 6
0x02, 0x62 Step(0x62) SetCharacterLevel Pops 3 (char index), 6 (level)
0x00, 0x03 PushByte 3 Raw byte, no encoding
0x02, 0x46 Step(0x46) SetActiveCharacter Pops 3 — sets character 3 as active
0x1D, 5, 2, 2, 2, 0x83 0x10, 0x8A 0x30, 2 PushMultiVarint(5) [1, 1, 1, 200, 664] Pushes 5 zigzag-encoded varints — zone 1, area 1, variation 1, spawn X 200, spawn Y 664
0x02, 0x27 Step(0x27) WarpToMapNoEntities Pops all 5 stack values — warps to zone 1 area 1 at position 200, 664 with variation 1
0x00, 0x78 PushByte 120 Raw byte, no encoding
0x02, 0x2B Step(0x2B) sub_8009B94 Pops 120 — unknown, likely a fade or wait
0x11, 0, 0, 0 Terminator Standard script end marker

Clone this wiki locally