Puyo Puyo Tsu/Memory Structures
Memory structures are the definition of how data is packed and stored by the game engine, along with the meanings of the various fields. This page also lists conventions, definitions or default values.
Board representation
The board is an array of bytes, two of which depict a single position, since the game stores every sprite ID twice at the same spot.
Puyo representation
The game picks puyos according to color codes, which are converted into sprite numbers to be displayed on the screen. Thus, in structures handling the board, the display of the few upcoming pairs, the currently falling piece, the codes are sprite identifiers, stored on 1 byte as such:
- 0x80: red
- 0x90: yellow
- 0xA0: green 1
- 0xB0: green 2
- 0xC0: purple
- 0xD0: blue
- 0xE0: ojama
- 0xF0: block
Each sprite code has variations: the first digit stands for the color, while the second digit is the sprite variation (where they look at, how they are linked to their neighbors...).
While picking pairs, in the memory areas containing the randomized pair pool and the next three pairs, the game handles color codes according to this list:
- 0x00: red
- 0x01: yellow
- 0x02: green 1
- 0x03: green 2
- 0x04: purple
- 0x05: blue
- 0x06: ojama
- 0x07: block
Note: there are 2 colors codes acting as green, but they are not compatible. The game does not link those puyos together, and treats them as different colors.
Player status structure
This structure is related to the player status in the current battle, and keeps the state of the current player: score, turn, groups to be cleared, nuisance to be received, current checkpoint in the game algorithm (main logic callback, i.e. "pair is falling", "resolving chain", "summing score"...).
Field offset | Field size | Description |
---|---|---|
0x00 | 2 bytes | pool tag, 0xF7C0 (player status) |
0x02 | 4 bytes | ROM pointer value (callback pointer) |
0x06 | 3 bytes | yet unknown |
0x09 | 1 byte | current chain length |
0x0A | 4 bytes | score |
0x0E | 4 bytes | score for current chaining step |
0x12 | 2 bytes | score multiplier for current chaining step (10 * puyos cleared * variable factor, capped to 65535) |
0x14 | 2 bytes | pending ojama count after opponent is done chaining (to fall on the structure's player) |
0x16 | 8 bytes | yet unknown |
0x1E | 2 bytes | score multiplier for current chaining step (chain power + color bonus + group bonus, capped to 999) |
0x20 | 4 bytes | yet unknown |
0x24 | 2 bytes | callback pass counter (countdown: 0=call only once before advancing) |
0x26 | 2 bytes | number of puyo groups to be cleared (for group bonus) |
0x28 | 2 bytes | yet unknown |
0x2A | 1 byte | player ID (0: P1, 1: P2) |
0x2B | 3 bytes | yet unknown |
0x2E | 4 bytes | pointer to next player status structure |
0x32 | 4 bytes | pointer to the upcoming pair pool buffer |
0x36 | 2 bytes | yet unknown |
0x38 | 2 bytes | pending ojama count while opponent is chaining (to fall on the structure's player) |
0x3A | 6 bytes | yet unknown |
Falling Puyo structure
This structure is related to the Falling Pair Spawning Process
Field offset | Field size | Description |
---|---|---|
0x00 | 2 bytes | pool tag, 0xF7C0 (player status) or 0xF780 (falling puyo) |
0x02 | 4 bytes | ROM pointer value (apparently a function callback pointer) |
0x06 | 1 byte | yet unknown |
0x07 | 1 byte | bitfield of the current status: bit #0: blocked under the main puyo |
0x08 | 1 byte | puyo color |
0x09 | 1 byte | counter before next RNG iteration: initial value made hard to memorize (64 hardcoded values + randomized values), and various hardcoded steps |
0x0A | 2 bytes | absolute-pixel reference x coordinate (beam-x) |
0x0C | 2 bytes | unconfirmed, supposed to be: beam-x coordinate 32-bit extension |
0x0E | 2 bytes | absolute-pixel reference y coordinate (beam-y) |
0x10 | 2 bytes | beam-y coordinate 32-bit extension, value extended for calculation of gravity acceleration |
0x12 | 4 bytes | yet unknown |
0x16 | 4 bytes | current fall height due to gravity (terminal velocity capped at 0x80000, 8 pixels/tick, half a cell) |
0x1A | 2 bytes | puyo x-pos (col) |
0x1C | 2 bytes | puyo y-pos (row) |
0x1E | 2 bytes | during fall: x-axis pixel shift to reflect D-pad action on the next frame after pair lockout: gravity acceleration (defaults to 0x3000/tick2) |
0x20 | 2 bytes | offset comparable to a video frame counter, which defines how far a puyo has fallen through the cell it's currently on |
0x22 | 1 byte | yet unknown |
0x23 | 1 byte | rotation counter (for double tap) |
0x24 | 2 bytes | callback pass counter (countdown: 0=call only once before advancing) |
0x26 | 2 bytes | counter of mid-height crossings, to prevent the pair from being pushed "upwards" more than 8 times |
0x28 | 2 bytes | grace period counter while blocked, before control lockout (defaults to 32) |
0x2A | 1 byte | player id (0: P1, 1: P2) |
0x2B | 1 byte | rotation id (0: top, 1: right, 2: bottom, 3: left) |
0x2C | 2 bytes | yet unknown |
0x2E | 4 bytes | pointer to parent structure "main" puyo only: pointer to player status |
0x32 | 4 bytes | ROM pointer value (apparently sprite buffer pointer) |
0x36 | 4 bytes | "main" puyo only: pointer to next structure in linked list |
0x36 | 1 byte | "slave" puyo only: current rotation offset (used for animation steps) |
0x37 | 1 byte | "slave" puyo only: target rotation offset |
0x38 | 2 bytes | "slave" puyo only: rotation animation step (defaults to 8) |
0x3A | 6 bytes | yet unknown |
Here's a screenshot showing the game's memory location involved with those structures:
Gamepad Status
Gamepad status is stored at 0xFFF070 for pad 1 and 0xFFF076 for pad 2:
Field offset | Field size | Description |
---|---|---|
0x00 | 1 byte | Pad key status: bitfield representing gamepad state for the current frame. Bits are affected as follows: SACBRLDU. |
0x01 | 1 byte | Pad new keys: bitfield (SACBRLDU) of buttons newly pressed on the current frame only. If any button was being held down by the player from a previous frame, they don't show up here. |
0x02 | 1 byte | Pad active keys: bitfield (SACBRLDU) of buttons the game considers active for the current frame, accounting for the input repeat mechanism. |
0x03 | 1 byte | Initial button input timer. Default values:
|
0x04 | 1 byte | Subsequent button input timer. Default values:
|
0x05 | 1 byte | Yet unknown |
This structure is discussed on the following page: Puyo Puyo Tsu/Gamepad Input