Skip to content

Game structs

Typed views of game structs in guest RAM.

Generated by the engine build; do not edit.

Layouts come from the decompilation, which builds a byte-identical PSX binary; the PSYQ types the game embeds come first, under a PSX_ prefix (PSX_MATRIX, PSX_RECT, PSX_DRAWENV, ...) so a translation unit may also include <windows.h>, which defines RECT. Pointer fields are uint32_t guest vaddrs; resolve them with api->guest(). The _Static_asserts at the end pin every size and member offset to the MIPS layout, so a layout change fails the mod's compile.

Source links open the definition in the decompilation at commit 4e7b7f06e5, the checkout this SDK was generated from.

ActiveSound

Source: include/spu.h:13-31
Size: 0x1c

Field Offset
m_Moby 0x0
m_StereoVolume 0x4
m_Pitch 0x8
unk_0xC 0xc
m_SoundId 0xd
m_Flags 0xe
m_Volume 0x10
m_PitchIncrease 0x14
m_SoundRefPtr 0x18
typedef struct ActiveSound {
  uint32_t m_Moby; /**< Guest pointer: `Moby *`. */

  PSX_SpuVolume m_StereoVolume; // Transformed m_Volume to stereo based on the
                            // position of the Moby

  uint32_t m_Pitch;

  uint8_t unk_0xC;
  uint8_t m_SoundId;
  uint16_t m_Flags;

  PSX_SpuVolume m_Volume;

  int m_PitchIncrease;

  uint32_t m_SoundRefPtr; /**< Guest pointer: `uint8_t *`. */ // Pointer to a flag that is set when the sound is
                         // done playing
} ActiveSound;

AnimationFrame

Source: include/moby.h:167-185
Size: 0x8

Field Offset
m 0x0
m.m_Props 0x0
m.m_Props.m_VertexOffset 0x0 bits 0-20
m.m_Props.m_CollisionModel 0x0 bits 21-23
m.m_Props.m_FrameSound 0x0 bits 24-31
m.m_Data 0x0
m_VertexColorOffset 0x4
m_Shadow 0x6
m_ShortOffset 0x7
typedef struct AnimationFrame {
  // Vertex offset:    00000000000111111111111111111111
  // Collision model:  00000000111000000000000000000000
  // Frame sound:      11111111000000000000000000000000
  union {

    // Not sure if this will match, but there's only one way to find out
    struct {
      uint32_t m_VertexOffset : 21;
      uint32_t m_CollisionModel : 3;
      uint32_t m_FrameSound : 8;
    } m_Props;
    uint32_t m_Data;
  } m;

  uint16_t m_VertexColorOffset;
  uint8_t m_Shadow;
  uint8_t m_ShortOffset;
} AnimationFrame;

AnimationHeader

Source: include/moby.h:196-220
Size: 0x2c

Field Offset
m_NumFrames 0x0
m_NumColors 0x2
m_IsSpyroAnimation 0x4
m_Scale 0x5
m_ShortEncodeShift 0x6
m_Radius 0x7
m_VertCountHigh 0x8
m_VertCountLow 0x9
m_Padding2 0xa
m_DepthScale 0xb
m_ProgressPerTick 0xc
m_Padding3 0xd
m_Padding4 0xe
m_AnimationVertices 0x10
m_Faces 0x14
m_Colors 0x18
m_LpFaces 0x1c
m_LpColors 0x20
m_Frames 0x24
typedef struct AnimationHeader {
  short m_NumFrames;
  uint16_t m_NumColors;

  uint8_t m_IsSpyroAnimation; // If 1, the other values of the int are unused
  uint8_t m_Scale;
  uint8_t m_ShortEncodeShift;
  uint8_t m_Radius;

  uint8_t m_VertCountHigh;
  uint8_t m_VertCountLow;
  uint8_t m_Padding2;
  uint8_t m_DepthScale;
  uint8_t m_ProgressPerTick;
  uint8_t m_Padding3;
  uint16_t m_Padding4;

  uint32_t m_AnimationVertices; /**< Guest pointer: `void *`. */ // Used when m_IsSpyroAnimation is set, otherwise
                             // matches m_faces
  uint32_t m_Faces; /**< Guest pointer: `void *`. */
  uint32_t m_Colors; /**< Guest pointer: `void *`. */
  uint32_t m_LpFaces; /**< Guest pointer: `void *`. */
  uint32_t m_LpColors; /**< Guest pointer: `void *`. */
  AnimationFrame m_Frames[1]; // To the size of frameCount
} AnimationHeader;

AnimationState

Source: include/moby.h:10-39
Size: 0x7

Field Offset
m_Animation 0x0
m_NextAnimation 0x1
m_Frame 0x2
m_NextFrame 0x3
m_FrameProgress 0x4
m_PerFrameProgress 0x5
m_AnimationFlags 0x6
typedef struct AnimationState {
  /** @brief Which animation is currently playing. */
  uint8_t m_Animation;

  /** @brief Which animation you're interpolating to. */
  uint8_t m_NextAnimation;

  /** @brief The current frame. */
  uint8_t m_Frame;

  /** @brief The next frame which you're interpolating to. */
  uint8_t m_NextFrame;

  /** @brief The progress of the current frame used for interpolation. */
  uint8_t m_FrameProgress;

  /** @brief The amount of progress to make per frame. */
  uint8_t m_PerFrameProgress;

  /** @brief Flags that are set by the animation system. */
  uint8_t m_AnimationFlags;
} AnimationState;

Camera

Source: include/camera.h:34-67
Size: 0x110

Field Offset
m_ProjectionMatrix 0x0
m_ViewMatrix 0x14
m_Position 0x28
m_DestinationPosition 0x34
unk_0x40 0x40
m_Rotation 0x4c
unk_0x52 0x52
m_OcclusionGroup 0x54
m_State 0x58
unk_0x5C 0x5c
m_LastSimulation 0x60
m_Sphere 0x78
m_Simulation 0x90
unk_0xA8 0xa8
unk_0xC0 0xc0
unk_0xC4 0xc4
m_SpyroOffCenterFrames 0xc8
unk_0xCC 0xcc
m_Focus 0xd0
m_FocusRotation 0xd4
m_SphericalPreset 0xd8
unk_0xDC 0xdc
unk_0xE0 0xe0
unk_0xE4 0xe4
unk_0xE8 0xe8
unk_0xEC 0xec
m_OnMovingPlatform 0xf0
unk_0xF4 0xf4
unk_0xF8 0xf8
unk_0xFC 0xfc
unk_0x100 0x100
unk_0x10C 0x10c
typedef struct Camera {
  SHORTMATRIX m_ProjectionMatrix; // Scaled for the aspect ratio
  SHORTMATRIX m_ViewMatrix; // Represents the camera's position and orientation
  Vector3D m_Position;      // Camera's position
  Vector3D m_DestinationPosition;
  int unk_0x40[3];       // Probably padding
  Vector3D16 m_Rotation; // Camera's rotation
  short unk_0x52;        // Padding
  int m_OcclusionGroup;  // Occlusion group
  uint32_t m_State;         // Camera state
  int unk_0x5C;          // Padding
  SphericalCoordsOffset m_LastSimulation;
  SphericalCoordsOffset m_Sphere;
  SphericalCoordsOffset m_Simulation;
  SphericalCoordsOffset unk_0xA8;
  int unk_0xC0; // Related to states
  int unk_0xC4; // Accumulator/counter used in camera smoothing/collision
  int m_SpyroOffCenterFrames;
  int unk_0xCC; // Flag: set to 1 when camera forced to destination
  uint32_t m_Focus; /**< Guest pointer: `Vector3D *`. */
  int m_FocusRotation;
  uint32_t m_SphericalPreset; /**< Guest pointer: `SphericalCoordsOffset *`. */
  int unk_0xDC;
  int unk_0xE0;
  int unk_0xE4;
  int unk_0xE8; // Result of func_80033F08: whether azimuth changed
  uint32_t unk_0xEC; /**< Guest pointer: `LevelFlyInParameters *`. */
  int m_OnMovingPlatform;
  int unk_0xF4;
  int unk_0xF8;
  int unk_0xFC;
  Vector3D unk_0x100;
  int unk_0x10C;
} Camera;

CdMusic

Source: include/music.h:11-23
Size: 0x224

Field Offset
m_CurrentTrack 0x0
m_Flags 0x4
m_MusicTable 0x8
m_MusicTable[0].start 0x8
m_MusicTable[0].end 0xc
m_TrackPosition 0x208
m_SyncData 0x20c
m_PostCDCommand 0x214
m_Flags2 0x218
m_EasterEggTicks 0x21c
m_Aud 0x220
typedef struct CdMusic {
  int m_CurrentTrack;
  int m_Flags;
  struct {
    int start, end;
  } m_MusicTable[64]; // 64 entries, but only 48 are used
  int m_TrackPosition;
  char m_SyncData[8];
  int m_PostCDCommand;
  int m_Flags2;
  int m_EasterEggTicks;
  PSX_CdlATV m_Aud; // Stereo mixing
} CdMusic;

CdState

Source: include/cd.h:14-24
Size: 0x2c

Field Offset
m_WadSector 0x0
m_Size 0x4
m_ReadLoc 0x8
m_OutBuf 0xc
m_FileInfo 0x10
m_IsReading 0x28
typedef struct CdState {
  int m_WadSector;
  int m_Size;
  PSX_CdlLOC m_ReadLoc;
  uint32_t m_OutBuf; /**< Guest pointer: `void *`. */

  // Unused in Final, used in Prototypes and Demos (see CDGetFileSector)
  PSX_CdlFILE m_FileInfo;

  volatile int m_IsReading;
} CdState;

CheckpointData

Source: include/checkpoint.h:6-30
Size: 0x68

Field Offset
m_StoodOnCheckpoint 0x0
m_DragonCount 0x4
m_GemCount 0x8
m_unusedCount 0xc
m_KilledMobysSaved 0x10
m_KilledMobys 0x30
m_StartingPosition 0x50
m_StartingRotation 0x5c
m_Unused1 0x60
m_Unused2 0x64
typedef struct CheckpointData {
  /** @brief Set to 1 if the player has stood on any checkpoint. */
  int m_StoodOnCheckpoint;

  // SKELETON: Written, but never read
  // That unused count is never used, so it's probably a remnant
  // of something that was removed
  int m_DragonCount;
  int m_GemCount;
  int m_unusedCount;

  // The difference between saved and not saved
  // is that when you die, the unsaved ones still spawn.
  // Saved when you stand on a checkpoint
  uint32_t m_KilledMobysSaved[8];
  uint32_t m_KilledMobys[8];

  // When you start the level, it's the level's starting position,
  // when you stand on a checkpoint, the checkpoint's position is written here
  Vector3D m_StartingPosition;
  int m_StartingRotation; // Only the Z axis is used, int for some reason

  int m_Unused1; // Never written to, only read to copy into m_Unused2
  int m_Unused2; // Only written to, never read from
} CheckpointData;

Color

Source: include/common.h:116-118
Size: 0x4

Field Offset
r 0x0
g 0x1
b 0x2
s 0x3
typedef struct Color {
  uint8_t r, g, b, s;
} Color;

ColorInt

Source: include/common.h:120-122
Size: 0xc

Field Offset
r 0x0
g 0x4
b 0x8
typedef struct ColorInt {
  int r, g, b;
} ColorInt;

CutsceneCameraData

Source: include/cutscene.h:9-12
Size: 0x18

Field Offset
m_Position 0x0
m_Rotation 0xc
typedef struct CutsceneCameraData {
  Vector3D m_Position;
  Vector3D m_Rotation; // Yeah, Vector3D..
} CutsceneCameraData;

CutsceneLayout

Source: include/cutscene.h:20-27
Size: 0x18

Field Offset
m_CurrentTick 0x0
m_0x04 0x4
m_Duration 0x8
m_MobyCount 0xc
m_CameraData 0x10
m_MobyData 0x14
typedef struct CutsceneLayout {
  int m_CurrentTick;
  int m_0x04;
  int m_Duration;
  int m_MobyCount;
  uint32_t m_CameraData; /**< Guest pointer: `CutsceneCameraData *`. */
  uint32_t m_MobyData[1]; /**< Guest pointer: `CutsceneMobyData *`. */ // Variable length array, size m_MobyCount
} CutsceneLayout;

CutsceneMobyData

Source: include/cutscene.h:14-18
Size: 0x4

Field Offset
m_PackedPos 0x0
typedef struct CutsceneMobyData {
  // Packed position data for a moby at a specific frame
  // 10:10:10 format (top 2 bits unused), where every value was divided by 256
  int m_PackedPos[1];
} CutsceneMobyData;

Cyclorama

Source: include/cyclorama.h:9-15
Size: 0x14

Field Offset
m_SectorCount 0x0
m_Sectors 0x4
m_OcclusionGroupsCount 0x8
m_OcclusionGroups 0xc
m_BackgroundColor 0x10
typedef struct Cyclorama {
  int m_SectorCount;
  uint32_t m_Sectors; /**< Guest pointer: `void *`. */ // TODO: Type
  int m_OcclusionGroupsCount;
  uint32_t m_OcclusionGroups; /**< Guest pointer: `void *`. */ // TODO: Type
  Color m_BackgroundColor;
} Cyclorama;

DB

Source: include/graphics.h:14-27
Size: 0x84

Field Offset
m_DrawEnv 0x0
m_DispEnv 0x5c
m_PolyBuf 0x70
m_WorldOT 0x74
m_HudOT 0x78
m_Unused1 0x7c
m_Unused2 0x80
typedef struct DB {
  // The GPU contexts
  PSX_DRAWENV m_DrawEnv;
  PSX_DISPENV m_DispEnv;

  // Pointer to the
  uint32_t m_PolyBuf; /**< Guest pointer: `void *`. */

  uint32_t m_WorldOT; /**< Guest pointer: `void *`. */
  uint32_t m_HudOT; /**< Guest pointer: `void *`. */

  int m_Unused1; // Might be unused OTs or pointers
  int m_Unused2; // No XREFs
} DB;

DrawStateSonyBuf

Source: include/sony_image.h:12-20
Size: 0x1c00

Field Offset
m_Moby 0x0
unk_0x900 0x900
unk_0x1600 0x1600
unk_0x1604 0x1604
unk_0x161C 0x161c
unk_0x1622 0x1622
unk_0x1628 0x1628
typedef struct DrawStateSonyBuf {
  uint32_t m_Moby[0x240]; /**< Guest pointer: `Moby *`. */     // 0x900
  uint8_t unk_0x900[0xD00]; //??
  int unk_0x1600;
  uint8_t unk_0x1604[24];
  Vector3D16 unk_0x161C;
  Vector3D16 unk_0x1622;
  uint8_t unk_0x1628[0x5D8];
} DrawStateSonyBuf;

Environment

Source: include/environment.h:60-73
Size: 0x30

Field Offset
m_SectorPointer 0x0
m_SectorCount 0x4
m_OcclusionGroups 0x8
m_OcclusionGroupCount 0xc
m_SurfaceData 0x10
m_SurfaceCount 0x14
m_LQTexturePointer 0x18
m_HQTexturePointer 0x1c
m_TextureCount 0x20
m_LodDistance 0x24
m_CullingDistance 0x28
m_TerrainCollision 0x2c
typedef struct Environment {
  uint32_t m_SectorPointer; /**< Guest pointer: `void *`. */ // TODO: Type
  int m_SectorCount;
  uint32_t m_OcclusionGroups; /**< Guest pointer: `void *`. */ // TODO: Type
  int m_OcclusionGroupCount;
  uint32_t m_SurfaceData; /**< Guest pointer: `SpecialSurface **`. */
  int m_SurfaceCount;
  uint32_t m_LQTexturePointer; /**< Guest pointer: `void *`. */ // TODO: Type
  uint32_t m_HQTexturePointer; /**< Guest pointer: `void *`. */ // TODO: Type
  int m_TextureCount;
  int m_LodDistance;
  int m_CullingDistance;
  uint32_t m_TerrainCollision; /**< Guest pointer: `TerrainCollision *`. */
} Environment;

EnvironmentAnimations

Source: include/environment.h:25-56
Size: 0x48

Field Offset
m_TextureAnimationCount 0x0
m_TextureAnimations 0x4
m_ScrollingTextureCount 0x8
m_ScrollingTextures 0xc
m_LowPolyAnimationCount 0x10
m_LowPolyAnimations 0x14
m_LowColorAnimationCount 0x18
m_LowColorAnimations 0x1c
m_HighPolyAnimationCount 0x20
m_HighPolyAnimations 0x24
m_HighColorAnimationCount 0x28
m_HighColorAnimations 0x2c
section7Count 0x30
section7 0x34
section8Count 0x38
section8 0x3c
m_CollisionAnimationCount 0x40
m_CollisionAnimations 0x44
typedef struct EnvironmentAnimations {
  // Animated textures are textures that take on the UVs of another texture
  // For example, Supercharge ramps
  int m_TextureAnimationCount;
  uint32_t m_TextureAnimations; /**< Guest pointer: `void *`. */

  // Scrolling textures are textures who's UVs scroll by a certain amount every
  // frame For example, waterfalls
  int m_ScrollingTextureCount;
  uint32_t m_ScrollingTextures; /**< Guest pointer: `void *`. */

  // These are animations on the environment geometry, like the moving platforms
  // Or torch-lit floors and walls
  int m_LowPolyAnimationCount;
  uint32_t m_LowPolyAnimations; /**< Guest pointer: `void *`. */
  int m_LowColorAnimationCount;
  uint32_t m_LowColorAnimations; /**< Guest pointer: `void *`. */
  int m_HighPolyAnimationCount;
  uint32_t m_HighPolyAnimations; /**< Guest pointer: `void *`. */
  int m_HighColorAnimationCount;
  uint32_t m_HighColorAnimations; /**< Guest pointer: `void *`. */

  // These are unused, they aren't referenced anywhere in the code
  int section7Count;
  uint32_t section7; /**< Guest pointer: `void *`. */
  int section8Count;
  uint32_t section8; /**< Guest pointer: `void *`. */

  // These are animations on the environment's collision, similar to above
  int m_CollisionAnimationCount;
  uint32_t m_CollisionAnimations; /**< Guest pointer: `void *`. */
} EnvironmentAnimations;

Gamepad

Source: include/gamepad.h:52-82
Size: 0xa4

Field Offset
m_Down 0x0
m_Released 0x4
m_Held 0x8
m_Type 0xc
m_LeftStickMoved 0x10
m_Sticks 0x14
m_NoButtonsDown 0x18
m_NoMovementButtonPressed 0x1c
m_CaliStickCenter 0x20
m_CaliStickMin 0x24
m_CaliStickMax 0x28
m_CaliStickUpperMin 0x2c
m_CaliStickLowerMin 0x30
m_CaliUpperSensitivity 0x34
m_CaliLowerSensitivity 0x3c
m_BufferedInputs 0x44
m_BufferedInputs[0].m_Type 0x44
m_BufferedInputs[0].m_Held 0x48
m_BufferedInputs[0].m_Down 0x4c
m_BufferedInputs[0].m_Released 0x50
m_BufferedInputs[0].m_LeftStickMoved 0x54
m_BufferedInputs[0].m_Sticks 0x58
typedef struct Gamepad {
  int m_Down;     // Buttons pressed this frame
  int m_Released; // Buttons released this frame
  int m_Held;     // Buttons that are currently held

  int m_Type; // CONTROLLER_TYPE_*

  int m_LeftStickMoved;   // Has the left stick moved?
  GamepadSticks m_Sticks; // Stick data

  int m_NoButtonsDown;           // No buttons are pressed
  int m_NoMovementButtonPressed; // No movement buttons are pressed

  // Stick calibration values (This is all really weird stuff)
  uint8_t m_CaliStickCenter[4];
  uint8_t m_CaliStickMin[4];
  uint8_t m_CaliStickMax[4];
  uint8_t m_CaliStickUpperMin[4];
  uint8_t m_CaliStickLowerMin[4];
  uint16_t m_CaliUpperSensitivity[4];
  uint16_t m_CaliLowerSensitivity[4];

  struct {
    int m_Type;             // CONTROLLER_TYPE_*
    int m_Held;             // Buttons held during this frame
    int m_Down;             // Buttons pressed during this frame
    int m_Released;         // Buttons released during this frame
    int m_LeftStickMoved;   // Has the left stick moved during this frame?
    GamepadSticks m_Sticks; // Stick data during this frame
  } m_BufferedInputs[4];    // Buffered inputs
} Gamepad;

GamepadSticks

Source: include/gamepad.h:45-50
Size: 0x4

Field Offset
m_RightX 0x0
m_RightY 0x1
m_LeftX 0x2
m_LeftY 0x3
typedef struct GamepadSticks {
  uint8_t m_RightX;
  uint8_t m_RightY;
  uint8_t m_LeftX;
  uint8_t m_LeftY;
} GamepadSticks;

Glow

Source: include/graphics.h:66-74
Size: 0x24

Field Offset
unk_0x00 0x0
unk_0x04 0x4
MobyPos 0x8
GlowColor 0xc
unk_0x010 0x10
PosOffset 0x14
unk_0x20 0x20
typedef struct Glow {
  int unk_0x00;
  uint32_t unk_0x04; /**< Guest pointer: `int*`. */
  uint32_t MobyPos; /**< Guest pointer: `Vector3D*`. */
  Color GlowColor;
  int unk_0x010;
  Vector3D PosOffset;
  int unk_0x20;
} Glow;

LevelFlyInParameters

Source: include/camera.h:8-15
Size: 0x38

Field Offset
m_SpyroPosition 0x0
m_SpyroRotation 0xc
m_CameraPosition 0x18
m_CameraRotation 0x24
unk_0x30 0x30
unk_0x34 0x34
typedef struct LevelFlyInParameters {
  Vector3D m_SpyroPosition;
  Vector3D m_SpyroRotation;
  Vector3D m_CameraPosition;
  Vector3D m_CameraRotation;
  int unk_0x30; // Usually 1
  int unk_0x34; // Usually 0x2000
} LevelFlyInParameters;

LevelHeader

Source: include/wad.h:40-52
Size: 0x1d0

Field Offset
m_VramSramOffset 0x0
m_VramSramSize 0x4
m_DataOffset 0x8
m_DataSize 0xc
m_ModelDataOffset 0x10
m_ModelDataSize 0x14
m_SceneOffset 0x18
m_SceneSize 0x1c
m_Dragons 0x20
m_ModelOffsets 0x50
m_ModelIndices 0x150
typedef struct LevelHeader {
  int m_VramSramOffset;
  int m_VramSramSize;
  int m_DataOffset;
  int m_DataSize;
  int m_ModelDataOffset;
  int m_ModelDataSize;
  int m_SceneOffset;
  int m_SceneSize;
  OffsetLength m_Dragons[6];
  int m_ModelOffsets[64];
  short m_ModelIndices[64];
} LevelHeader;

MemCardSaveFile

Source: include/save_file.h:49-52
Size: 0x1400

Field Offset
m_Header 0x0
m_Saves 0x200
typedef struct MemCardSaveFile {
  SaveFileHeader m_Header;
  SaveFile m_Saves[3];
} MemCardSaveFile;

Moby

Source: include/moby.h:42-164
Size: 0x58

Field Offset
m_Props 0x0
m_CollisionChainNext 0x4
m_CollisionGroup 0x8
m_Position 0xc
m_DamageFlags 0x18
m_ShadowDistance 0x1c
m_RotationMatrix 0x20
m_CollisionRegion 0x34
m_Class 0x36
m_FloorDistance 0x38
m_DroppedFlag 0x3a
m_CollisionRange 0x3b
m_AnimationState 0x3c
m_Pod 0x43
m_Rotation 0x44
m_DepthOffset 0x47
m_State 0x48
m_Substate 0x49
m_SectorIndex 0x4a
m_Renderer 0x4b
m_Renderer.flags 0x4b
m_Renderer.flags.m_Distance 0x4b bits 0-6
m_Renderer.flags.m_ShinyRenderer 0x4b bit 7
m_Renderer.raw 0x4b
m_SpecularMetalColor 0x4c
m_SpecularMetalType 0x4f
m_RenderRadius 0x50
m_WasDrawn 0x51
m_UpdateDistance 0x52
m_DropMoby 0x53
m_SoundChannel 0x54
m_SoundDistance 0x55
m_MobyIndex 0x56
m_ScaleOverride 0x57
typedef struct Moby {
  /** @brief Specifies the properties of the moby, which is class specific. */
  uint32_t m_Props; /**< Guest pointer: `void *`. */

  /** @brief The next moby in the collision chain that this Moby is a part of. */
  uint32_t m_CollisionChainNext; /**< Guest pointer: `struct Moby *`. */

  /** @brief This Moby's active collision group (Which is part of it's model). */
  uint32_t m_CollisionGroup; /**< Guest pointer: `void *`. */

  /** @brief The Moby's position. */
  Vector3D m_Position;

  /** @brief The damage that has been applied to the Moby. */
  int m_DamageFlags; // TODO: Enum?

  /** @brief The distance of the shadow from the Moby, equal to the floor. */
  int m_ShadowDistance;

  /** @brief The Moby's rotation matrix. */
  SHORTMATRIX m_RotationMatrix;

  /** @brief The collision region that the Moby is in. */
  short m_CollisionRegion;

  /** @brief The Moby's class, which specifies which kind of Moby it is. */
  short m_Class;

  /** @brief The distance of the moby to the floor. */
  short m_FloorDistance;

  /** @brief Flag used to determine if the Moby has already dropped it's drop. */
  uint8_t m_DroppedFlag;

  /** @brief The range of the Moby's current collision. */
  uint8_t m_CollisionRange;

  /** @brief The Moby's current animation state. */
  AnimationState m_AnimationState;

  /** @brief The Pod that this Moby is a part of. */
  uint8_t m_Pod;

  /** @brief The Moby's rotation. */
  Vector3D8 m_Rotation;

  /** @brief Offsets the sorting depth of the entire Moby. */
  char m_DepthOffset;

  /** @brief The Moby's current state, often used in Moby code. */
  uint8_t m_State;

  /** @brief The Moby's substate, less often used in Moby code. */
  uint8_t m_Substate;

  /** @brief Sector the Moby is located in, for culling purposes. */
  uint8_t m_SectorIndex;

  union {
    struct {
      /** @brief Stores the render distance of the Moby. */
      uint8_t m_Distance : 7;

      /** @brief And the renderer to be used. */
      uint8_t m_ShinyRenderer : 1;
    } flags;
    uint8_t raw;
  } m_Renderer;

  // We have to define it like this, we can't use
  // a bitfield because there's no 24 bit integer
  // type and the compiler aligns it to the
  // integer size used

  // Used for the specular color, which is 6 bits per channel (each value is
  // divided by 2)

  // For metal it's straight forward, 8 bits per channel

  uint8_t m_SpecularMetalColor[3];

  // Stores the type when shinyRenderer is enabled
  // If Shiny renderer: 0 = Specular 1/2 = metal (2 being rotated)
  // If shaded: color index
  uint8_t m_SpecularMetalType;

  /** @brief Radius of the Moby for clipping purposes (>> 2). */
  uint8_t m_RenderRadius;

  // Stores whether the Moby got drawn last frame
  // If it has, the Moby receives more grace during culling
  // Also often used in Moby code, often enemies will not attack when they
  // are off-screen
  uint8_t m_WasDrawn;

  /** @brief The distance at which Mobys get updated (/1024). */
  // Mobys often initialize this to 0xFF
  uint8_t m_UpdateDistance;

  /** @brief Moby class dropped by this Moby. */
  uint8_t m_DropMoby;

  /** @brief Sound channel the moby is occuping. */
  uint8_t m_SoundChannel;

  /** @brief Distance the last sound played was at. */
  uint8_t m_SoundDistance;

  // If dynamically allocated, this contains the index of the Moby that spawned
  // us used for keeping track of which index of the gem bitmask needs to be set
  // Ignored if the moby is not dynamically allocated
  uint8_t m_MobyIndex;

  // Used for resizing the Moby model dynamically, if set to 0 the regular size
  // is used
  uint8_t m_ScaleOverride;
} Moby;

Moby17Props

Source: include/moby.h:415-418
Size: 0x10

Field Offset
unk_0x00 0x0
unk_0x0C 0xc
typedef struct Moby17Props {
  Vector3D unk_0x00;
  int unk_0x0C;
} Moby17Props;

MobyButterflyProps

Source: include/moby.h:379-387
Size: 0x18

Field Offset
unk_0x00 0x0
unk_0x04 0x4
unk_0x10 0x10
unk_0x11 0x11
unk_0x12 0x12
unk_0x13 0x13
unk_0x14 0x14
typedef struct MobyButterflyProps {
  int unk_0x00;
  Vector3D unk_0x04;
  char unk_0x10;
  char unk_0x11;
  char unk_0x12;
  char unk_0x13;
  short unk_0x14;
} MobyButterflyProps;

MobyCollectableProps

Source: include/moby.h:442-452
Size: 0x18

Field Offset
m_InitPos 0x0
m_CollisionIndex 0xc
m_SpawnState 0xe
m_Ticks 0xf
m_RotX 0x10
m_RotY 0x11
m_RotZ 0x12
m_RotationTicks 0x13
m_SparkleHandle 0x14
typedef struct MobyCollectableProps {
  Vector3D m_InitPos;
  short m_CollisionIndex;
  uint8_t m_SpawnState;
  uint8_t m_Ticks;
  uint8_t m_RotX;
  uint8_t m_RotY;
  uint8_t m_RotZ;
  uint8_t m_RotationTicks;
  uint8_t m_SparkleHandle;
} MobyCollectableProps;

MobyDragonFragmentProps

Source: include/moby.h:433-440
Size: 0x14

Field Offset
trajectory 0x0
initZ 0xc
unk_0x10 0x10
unk_0x11 0x11
unk_0x12 0x12
m_Lifetime 0x13
typedef struct MobyDragonFragmentProps {
  Vector3D trajectory;
  int initZ;
  char unk_0x10;
  char unk_0x11;
  char unk_0x12;
  char m_Lifetime;
} MobyDragonFragmentProps;

MobyFlightTrainProps

Source: include/moby.h:364-369
Size: 0x18

Field Offset
m_Path 0x0
unk_0x4 0x4
unk_0x8 0x8
unk_0x14 0x14
typedef struct MobyFlightTrainProps {
  uint32_t m_Path; /**< Guest pointer: `PathData *`. */
  int unk_0x4;
  Vector3D unk_0x8;
  int unk_0x14;
} MobyFlightTrainProps;

MobyFragmentProps

Source: include/moby.h:420-431
Size: 0x14

Field Offset
unk_0x00 0x0
unk_0x02 0x2
unk_0x04 0x4
unk_0x06 0x6
unk_0x08 0x8
unk_0x0A 0xa
unk_0x0C 0xc
unk_0x10 0x10
typedef struct MobyFragmentProps {
  short unk_0x00;
  short unk_0x02;
  short unk_0x04;

  short unk_0x06;
  short unk_0x08;
  short unk_0x0A;

  int unk_0x0C;
  int unk_0x10;
} MobyFragmentProps;

MobyLetterProps

Source: include/moby.h:389-393
Size: 0x8

Field Offset
m_Parent 0x0
m_Len 0x4
m_Index 0x6
typedef struct MobyLetterProps {
  uint32_t m_Parent; /**< Guest pointer: `Moby *`. */
  short m_Len;
  short m_Index;
} MobyLetterProps;

MobyNumberProps

Source: include/moby.h:406-412
Size: 0x14

Field Offset
unk_0x0 0x0
unk_0x4 0x4
unk_0x8 0x8
typedef struct MobyNumberProps {
  int unk_0x0;
  // not sure what to call this, for input pGemValue=25 this is either "20" or
  // "5"
  int unk_0x4;
  Vector3D unk_0x8;
} MobyNumberProps;

MobyPortalPathProps

Source: include/moby.h:371-377
Size: 0x1c

Field Offset
m_Path 0x0
unk_0x4 0x4
m_Sidedness 0x10
unk_0x14 0x14
unk_0x18 0x18
typedef struct MobyPortalPathProps {
  uint32_t m_Path; /**< Guest pointer: `PathData *`. */
  Vector3D unk_0x4;
  int m_Sidedness;
  int unk_0x14;
  int unk_0x18; // Some kinda link? not sure
} MobyPortalPathProps;

MobyShadow

Source: include/moby.h:473-476
Size: 0xc

Field Offset
shadow 0x0
shadow_list 0x8
typedef struct MobyShadow {
  Tiledef shadow;
  uint32_t shadow_list; /**< Guest pointer: `int *`. */ // shadow queue?
} MobyShadow;

MobySparxProps

Source: include/moby.h:395-402
Size: 0x14

Field Offset
unk_0x00 0x0
unk_0x04 0x4
unk_0x06 0x6
unk_0x08 0x8
glow 0xc
unk_0x10 0x10
typedef struct MobySparxProps {
  int unk_0x00;
  short unk_0x04;
  short unk_0x06;
  short unk_0x08;
  uint32_t glow; /**< Guest pointer: `Glow *`. */
  int unk_0x10;
} MobySparxProps;

Model

Source: include/moby.h:222-229
Size: 0x3c

Field Offset
m_NumAnimations 0x0
m_Sounds 0x4
m_CollisionModels 0x14
m_Data 0x34
m_Animations 0x38
typedef struct Model {
  int m_NumAnimations; // >= 0 == Model
  uint8_t m_Sounds[16];
  uint32_t m_CollisionModels[8]; /**< Guest pointer: `void *`. */
  uint32_t m_Data; /**< Guest pointer: `void *`. */ // offset from this to the data, used to offset pointers inside
                // animations
  uint32_t m_Animations[1]; /**< Guest pointer: `AnimationHeader *`. */
} Model;

OffsetLength

Source: include/wad.h:4-7
Size: 0x8

Field Offset
m_Offset 0x0
m_Length 0x4
typedef struct OffsetLength {
  int m_Offset;
  int m_Length;
} OffsetLength;

PadBuffer

Source: include/gamepad.h:84-90
Size: 0x20

Field Offset
status 0x0
size_type 0x1
inputs 0x2
sticks 0x4
padding 0x8
typedef struct PadBuffer {
  uint8_t status;        // Current status of the controller, 0 means connected
  uint8_t size_type;     // HW_TYPE_*
  uint8_t inputs[2];     // Button states
  GamepadSticks sticks; // Stick data
  uint8_t padding[24];   // Padding, some controllers provide more data
} PadBuffer;

Particle

Source: include/renderers.h:34-42
Size: 0x20

Field Offset
m_Class 0x0
m_Type 0x1
m_Life 0x2
m_03 0x3
m_Data 0x4
typedef struct Particle {
  uint8_t m_Class; // Particle class, determines behavior
  uint8_t m_Type;  // TODO: Document
  uint8_t m_Life;  // Remaining life in ticks
  uint8_t m_03;

  // Depends on the type, and class
  uint8_t m_Data[28];
} Particle;

ParticleTexture

Source: include/renderers.h:14-30
Size: 0x8

Field Offset
uv0 0x0
uv0.s 0x0
uv0.s.u0 0x0
uv0.s.v0 0x1
uv0.s.clut 0x2
uv0.all 0x0
uv2 0x4
uv2.s 0x4
uv2.s.u2 0x4
uv2.s.v2 0x5
uv2.s.tpage 0x6
uv2.all 0x4
typedef struct ParticleTexture {
  union {
    struct {
      uint8_t u0, v0;
      uint16_t clut;
    } s;
    int all;
  } uv0;

  union {
    struct {
      uint8_t u2, v2;
      uint16_t tpage;
    } s;
    int all;
  } uv2;
} ParticleTexture;

PathData

Source: include/moby.h:352-361
Size: 0x18

Field Offset
m_NodeCount 0x0
m_CurrentNode 0x1
unk_0x2 0x2
m_Reversed 0x6
m_Nodes 0x8
m_Nodes[0].m_Position 0x8
m_Nodes[0].unk_0xC 0x14
typedef struct PathData {
  uint8_t m_NodeCount;
  uint8_t m_CurrentNode;
  char unk_0x2[4];  // No clue, padding? Usually 0
  short m_Reversed; // Path traversal: -1 = normal, 1 = reversed
  struct {
    Vector3D m_Position;
    int unk_0xC; // Padding I assume
  } m_Nodes[1];
} PathData;

Portal

Source: include/cyclorama.h:36-49
Size: 0x38

Field Offset
m_Skybox 0x0
m_PointCount 0x4
unk_0x8 0x8
m_WorldSector 0x14
m_PathMoby 0x18
m_LevelId 0x1c
m_Center 0x20
m_Points 0x2c
typedef struct Portal {
  uint32_t m_Skybox; /**< Guest pointer: `PortalDataSky *`. */ // This one is difficult to type,
                           // because it refers to the last (missing) point
                           // in the cyclorama points array, which is being used
                           // as strange storage

  int m_PointCount;
  Vector3D unk_0x8;
  int m_WorldSector;
  int m_PathMoby;
  int m_LevelId;
  Vector3D m_Center;
  Vector3D m_Points[1]; // To the length (m_PointCount - 1)
} Portal;

PortalDataSky

Source: include/cyclorama.h:24-34
Size: 0x24

Field Offset
copySectorCount 0x0
copySectors 0x4
zero 0x8
zero2 0xc
copyBgColor 0x10
componentSize 0x14
m_BackgroundColor 0x18
m_SectorCount 0x1c
m_Sectors 0x20
typedef struct PortalDataSky {
  int copySectorCount;
  uint32_t copySectors; /**< Guest pointer: `void *`. */
  int zero;
  int zero2;
  int copyBgColor;
  int componentSize;
  Color m_BackgroundColor;
  uint32_t m_SectorCount;
  uint32_t m_Sectors[1]; /**< Guest pointer: `void *`. */
} PortalDataSky;

RescuedDragonMobyProps

Source: include/moby.h:454-469
Size: 0x58

Field Offset
m_CameraPosition 0x0
m_CameraRotation 0xc
m_CutsceneId 0x18
m_Rotation 0x1c
m_DragonPadLink 0x20
m_OldDialogueId 0x24
m_Angle 0x28
m_IsUnskipable 0x34
m_NameIndex 0x38
m_CutsceneAudioPitch 0x3c
m_CutsceneTicks 0x40
m_ShakeTimer 0x44
m_AngleStorage 0x48
m_PosZStorage 0x54
typedef struct RescuedDragonMobyProps {
  Vector3D m_CameraPosition;
  Vector3D m_CameraRotation;
  int m_CutsceneId; // The ID of the cutscene to play when this Moby is
  int m_Rotation;
  int m_DragonPadLink;
  int m_OldDialogueId; // The ID of the *text* dialogue, used in prototypes
  Vector3D m_Angle;
  int m_IsUnskipable;       // Whether the cutscene can't be skipped
  int m_NameIndex;          // The index of the name in the dragon name table
  int m_CutsceneAudioPitch; // The pitch of the cutscene audio (for sample rate)
  int m_CutsceneTicks;      // The number of ticks the cutscene lasts
  int m_ShakeTimer;
  Vector3D m_AngleStorage; // Used in moby code
  int m_PosZStorage;       // Used in moby code
} RescuedDragonMobyProps;

SaveFile

Source: include/save_file.h:12-37
Size: 0x600

Field Offset
m_LevelId 0x0
m_SoundVolume 0x1
m_MusicVolume 0x2
m_ControllerVibrationEnabled 0x3
m_CameraSpeed 0x4
m_AudioMono 0x8
m_UnusedByte1 0x9
m_UnusedByte2 0xa
m_ExtraLifeCount 0xb
unk_0x0C 0xc
m_Flight 0x10
m_LevelsVisited 0x40
m_LevelsCompleted 0x64
m_CollectedDragons 0x88
m_CollectedGems 0xac
m_CollectedEggs 0xf4
m_UnlockedHomeworlds 0x106
m_GemCollectionMask 0x10c
m_Checksum 0x58c
pad 0x590
typedef struct SaveFile {
  uint8_t m_LevelId;
  uint8_t m_SoundVolume;
  uint8_t m_MusicVolume;
  uint8_t m_ControllerVibrationEnabled;
  int m_CameraSpeed;
  uint8_t m_AudioMono;
  uint8_t m_UnusedByte1;
  uint8_t m_UnusedByte2;
  uint8_t m_ExtraLifeCount;
  int unk_0x0C;

  SaveFlight m_Flight;

  uint8_t m_LevelsVisited[TOTAL_LEVEL_COUNT];
  uint8_t m_LevelsCompleted[TOTAL_LEVEL_COUNT];
  uint8_t m_CollectedDragons[TOTAL_LEVEL_COUNT];
  short m_CollectedGems[TOTAL_LEVEL_COUNT];
  // Only the first three homeworlds have eggs
  uint8_t m_CollectedEggs[LEVEL_PER_HOMEWORLD * 3];
  uint8_t m_UnlockedHomeworlds[HOMEWORLD_COUNT];
  // In memory, this is padded to 1200, but in the save file it's 1152
  uint8_t m_GemCollectionMask[TOTAL_LEVEL_COUNT * 32];
  int m_Checksum;
  char pad[0x70];
} SaveFile;

SaveFileHeader

Source: include/save_file.h:39-47
Size: 0x200

Field Offset
m_Magic 0x0
m_IconDisplayFlag 0x2
m_BlockNum 0x3
m_Title 0x4
reserved 0x44
m_Clut 0x60
m_Icon 0x80
typedef struct SaveFileHeader {
  char m_Magic[2];
  uint8_t m_IconDisplayFlag;
  uint8_t m_BlockNum;
  uint8_t m_Title[0x40];
  char reserved[0x1C];
  uint16_t m_Clut[0x10];
  uint8_t m_Icon[0x80][3];
} SaveFileHeader;

SaveFlight

Source: include/save_file.h:7-10
Size: 0x30

Field Offset
m_CourseRecords 0x0
m_FlightCollected 0x14
typedef struct SaveFlight {
  int m_CourseRecords[5];
  uint8_t m_FlightCollected[5][5];
} SaveFlight;

SHORTMATRIX

Source: include/matrix.h:6-9
Size: 0x14

Field Offset
m 0x0
_pad 0x12
typedef struct SHORTMATRIX {
  short m[3][3]; /**< 3x3 rotation matrix. */
  short _pad;    /**< padding. */
} SHORTMATRIX;

SimpleModel

Source: include/moby.h:237-242
Size: 0x10

Field Offset
m_NumAnimations 0x0
m_Verts 0x4
m_Colors 0x8
m_Faces 0xc
typedef struct SimpleModel {
  int m_NumAnimations; // < 0 == SimpleModel (always -1 in reality)
  uint32_t m_Verts; /**< Guest pointer: `void *`. */
  uint32_t m_Colors; /**< Guest pointer: `void *`. */
  uint32_t m_Faces; /**< Guest pointer: `void *`. */
} SimpleModel;

SoundDefinition

Source: include/spu.h:33-45
Size: 0x14

Field Offset
m_Addr 0x0
m_LoopAddr 0x4
unk_0x8 0x8
m_Pitch 0xa
m_PitchVariance 0xc
m_PitchMultiplier 0xe
m_VarianceType 0x10
typedef struct SoundDefinition {
  uint32_t m_Addr;
  uint32_t m_LoopAddr; // Saved but completely unnecessary
  short unk_0x8;     // Named unusedVolume in my notes
  uint16_t m_Pitch;
  uint16_t m_PitchVariance;
  uint16_t m_PitchMultiplier;

  // 0: Positive and negative pitch variance
  // 1: Only positive pitch variance
  // 2: Only negative pitch variance
  int m_VarianceType;
} SoundDefinition;

SoundTable

Source: include/sound_table.h:6-266
Size: 0x100

Field Offset
gemPickup 0x0
sound_0x1 0x1
sound_0x2 0x2
sound_0x3 0x3
spyroCharge 0x4
superCharge 0x5
waterfall 0x6
birdSong1 0x7
birdSong2 0x8
birdSong3 0x9
birdChirp1 0xa
birdChirp2 0xb
birdChirp3 0xc
crow1 0xd
crow2 0xe
seagull1 0xf
seagull2 0x10
sound_0x11 0x11
fountainLoop 0x12
owl1 0x13
owl2 0x14
owl3 0x15
grasshopper1 0x16
grasshopper2 0x17
grasshopper3 0x18
grasshopper4 0x19
exitVortex 0x1a
spyroStars 0x1b
sound_0x1c 0x1c
waterSplash 0x1d
spyroWalk 0x1e
electricShock 0x1f
spyroUnsquish 0x20
flightPling 0x21
flightTimeAdded 0x22
flightCollected 0x23
flightCompleted 0x24
flightLowPlong 0x25
mobyPoof 0x26
sound_0x27 0x27
spyroFlame 0x28
beastSound1 0x29
beastSound2 0x2a
beastSound3 0x2b
menuSound 0x2c
menuCursor 0x2d
menuConfirm 0x2e
pickupDing 0x2f
rescueingSound 0x30
dragonBreak 0x31
dragonRumbleBreaking 0x32
dragonFlash 0x33
dragonCounter 0x34
dragonCounterBam 0x35
whirlwind 0x36
titlescreenMove 0x37
inventorySwoosh 0x38
sound_0x39 0x39
splort 0x3a
flipImpact 0x3b
gnastyDoorOpening 0x3c
sound_0x3d 0x3d
sound_0x3e 0x3e
sound_0x3f 0x3f
sound_0x40 0x40
sound_0x41 0x41
sound_0x42 0x42
sound_0x43 0x43
sound_0x44 0x44
sound_0x45 0x45
sound_0x46 0x46
sound_0x47 0x47
sound_0x48 0x48
sound_0x49 0x49
sound_0x4a 0x4a
sound_0x4b 0x4b
sound_0x4c 0x4c
sound_0x4d 0x4d
sound_0x4e 0x4e
sound_0x4f 0x4f
sound_0x50 0x50
sound_0x51 0x51
sound_0x52 0x52
sound_0x53 0x53
sound_0x54 0x54
sound_0x55 0x55
sound_0x56 0x56
sound_0x57 0x57
sound_0x58 0x58
sound_0x59 0x59
sound_0x5a 0x5a
sound_0x5b 0x5b
sound_0x5c 0x5c
sound_0x5d 0x5d
sound_0x5e 0x5e
sound_0x5f 0x5f
sound_0x60 0x60
sound_0x61 0x61
sound_0x62 0x62
sound_0x63 0x63
sound_0x64 0x64
sound_0x65 0x65
sound_0x66 0x66
sound_0x67 0x67
sound_0x68 0x68
sound_0x69 0x69
sound_0x6a 0x6a
sound_0x6b 0x6b
sound_0x6c 0x6c
sound_0x6d 0x6d
sound_0x6e 0x6e
sound_0x6f 0x6f
sound_0x70 0x70
sound_0x71 0x71
sound_0x72 0x72
sound_0x73 0x73
sound_0x74 0x74
sound_0x75 0x75
sound_0x76 0x76
sound_0x77 0x77
sound_0x78 0x78
sound_0x79 0x79
sound_0x7a 0x7a
sound_0x7b 0x7b
sound_0x7c 0x7c
sound_0x7d 0x7d
sound_0x7e 0x7e
sound_0x7f 0x7f
sound_0x80 0x80
sound_0x81 0x81
sound_0x82 0x82
sound_0x83 0x83
sound_0x84 0x84
sound_0x85 0x85
sound_0x86 0x86
sound_0x87 0x87
sound_0x88 0x88
sound_0x89 0x89
sound_0x8a 0x8a
sound_0x8b 0x8b
sound_0x8c 0x8c
sound_0x8d 0x8d
sound_0x8e 0x8e
sound_0x8f 0x8f
sound_0x90 0x90
sound_0x91 0x91
sound_0x92 0x92
sound_0x93 0x93
sound_0x94 0x94
sound_0x95 0x95
sound_0x96 0x96
sound_0x97 0x97
sound_0x98 0x98
sound_0x99 0x99
sound_0x9a 0x9a
sound_0x9b 0x9b
sound_0x9c 0x9c
sound_0x9d 0x9d
sound_0x9e 0x9e
sound_0x9f 0x9f
sound_0xa0 0xa0
sound_0xa1 0xa1
sound_0xa2 0xa2
sound_0xa3 0xa3
sound_0xa4 0xa4
sound_0xa5 0xa5
sound_0xa6 0xa6
sound_0xa7 0xa7
sound_0xa8 0xa8
sound_0xa9 0xa9
sound_0xaa 0xaa
sound_0xab 0xab
sound_0xac 0xac
sound_0xad 0xad
sound_0xae 0xae
sound_0xaf 0xaf
sound_0xb0 0xb0
sound_0xb1 0xb1
sound_0xb2 0xb2
sound_0xb3 0xb3
sound_0xb4 0xb4
sound_0xb5 0xb5
sound_0xb6 0xb6
sound_0xb7 0xb7
sound_0xb8 0xb8
sound_0xb9 0xb9
sound_0xba 0xba
sound_0xbb 0xbb
sound_0xbc 0xbc
sound_0xbd 0xbd
sound_0xbe 0xbe
sound_0xbf 0xbf
sound_0xc0 0xc0
sound_0xc1 0xc1
sound_0xc2 0xc2
sound_0xc3 0xc3
sound_0xc4 0xc4
sound_0xc5 0xc5
sound_0xc6 0xc6
sound_0xc7 0xc7
sound_0xc8 0xc8
sound_0xc9 0xc9
sound_0xca 0xca
sound_0xcb 0xcb
sound_0xcc 0xcc
sound_0xcd 0xcd
sound_0xce 0xce
sound_0xcf 0xcf
sound_0xd0 0xd0
sound_0xd1 0xd1
sound_0xd2 0xd2
sound_0xd3 0xd3
sound_0xd4 0xd4
sound_0xd5 0xd5
sound_0xd6 0xd6
sound_0xd7 0xd7
sound_0xd8 0xd8
sound_0xd9 0xd9
sound_0xda 0xda
sound_0xdb 0xdb
sound_0xdc 0xdc
sound_0xdd 0xdd
sound_0xde 0xde
sound_0xdf 0xdf
sound_0xe0 0xe0
sound_0xe1 0xe1
sound_0xe2 0xe2
sound_0xe3 0xe3
sound_0xe4 0xe4
sound_0xe5 0xe5
sound_0xe6 0xe6
sound_0xe7 0xe7
sound_0xe8 0xe8
sound_0xe9 0xe9
sound_0xea 0xea
sound_0xeb 0xeb
sound_0xec 0xec
sound_0xed 0xed
sound_0xee 0xee
sound_0xef 0xef
sound_0xf0 0xf0
sound_0xf1 0xf1
sound_0xf2 0xf2
sound_0xf3 0xf3
sound_0xf4 0xf4
sound_0xf5 0xf5
sound_0xf6 0xf6
sound_0xf7 0xf7
sound_0xf8 0xf8
sound_0xf9 0xf9
sound_0xfa 0xfa
sound_0xfb 0xfb
sound_0xfc 0xfc
sound_0xfd 0xfd
sound_0xfe 0xfe
sound_0xff 0xff
typedef struct SoundTable {
  uint8_t gemPickup;
  uint8_t sound_0x1; // Low quality walk sound
  uint8_t sound_0x2; // Weird blub blub sound
  uint8_t sound_0x3; // Simple chest breaking sound (Misty Bog; Metalhead;
                    // Twilight Harbor)
  uint8_t spyroCharge;
  uint8_t superCharge;
  uint8_t waterfall;
  uint8_t birdSong1;
  uint8_t birdSong2;
  uint8_t birdSong3;
  uint8_t birdChirp1;
  uint8_t birdChirp2;
  uint8_t birdChirp3;
  uint8_t crow1;
  uint8_t crow2;
  uint8_t seagull1;
  uint8_t seagull2;
  uint8_t sound_0x11; // Something metal breaking? (Misty Bog; Metalhead;
                     // Twilight Harbour)
  uint8_t fountainLoop;
  uint8_t owl1;
  uint8_t owl2;
  uint8_t owl3;
  uint8_t grasshopper1;
  uint8_t grasshopper2;
  uint8_t grasshopper3;
  uint8_t grasshopper4;
  uint8_t exitVortex;
  uint8_t spyroStars;
  uint8_t sound_0x1c; // Something exploding (Peace Keepers; Cliff town)
  uint8_t waterSplash;
  uint8_t spyroWalk;
  uint8_t electricShock;
  uint8_t spyroUnsquish;
  uint8_t flightPling;
  uint8_t flightTimeAdded;
  uint8_t flightCollected;
  uint8_t flightCompleted;
  uint8_t flightLowPlong;
  uint8_t mobyPoof;
  uint8_t sound_0x27; // Unused
  uint8_t spyroFlame;
  uint8_t beastSound1;
  uint8_t beastSound2;
  uint8_t beastSound3;
  uint8_t menuSound;
  uint8_t menuCursor;
  uint8_t menuConfirm;
  uint8_t pickupDing;
  uint8_t rescueingSound;
  uint8_t dragonBreak;
  uint8_t dragonRumbleBreaking;
  uint8_t dragonFlash;
  uint8_t dragonCounter;
  uint8_t dragonCounterBam;
  uint8_t whirlwind;
  uint8_t titlescreenMove;
  uint8_t inventorySwoosh;
  uint8_t sound_0x39; // Weird windy sound; loops (Sunny Flight; Gnasty's Loot)
  uint8_t splort;
  uint8_t flipImpact;
  uint8_t gnastyDoorOpening; // (Gnasty Gnorc; Gnasty's Loot)
  uint8_t sound_0x3d;        // Unused
  uint8_t sound_0x3e;        // Unused
  uint8_t sound_0x3f;        // Unused
  uint8_t sound_0x40;        // Unused
  uint8_t sound_0x41;        // Moving terrain sound
  uint8_t sound_0x42;        // Unused
  uint8_t sound_0x43;        // Everything past this is unused
  uint8_t sound_0x44;
  uint8_t sound_0x45;
  uint8_t sound_0x46;
  uint8_t sound_0x47;
  uint8_t sound_0x48;
  uint8_t sound_0x49;
  uint8_t sound_0x4a;
  uint8_t sound_0x4b;
  uint8_t sound_0x4c;
  uint8_t sound_0x4d;
  uint8_t sound_0x4e;
  uint8_t sound_0x4f;
  uint8_t sound_0x50;
  uint8_t sound_0x51;
  uint8_t sound_0x52;
  uint8_t sound_0x53;
  uint8_t sound_0x54;
  uint8_t sound_0x55;
  uint8_t sound_0x56;
  uint8_t sound_0x57;
  uint8_t sound_0x58;
  uint8_t sound_0x59;
  uint8_t sound_0x5a;
  uint8_t sound_0x5b;
  uint8_t sound_0x5c;
  uint8_t sound_0x5d;
  uint8_t sound_0x5e;
  uint8_t sound_0x5f;
  uint8_t sound_0x60;
  uint8_t sound_0x61;
  uint8_t sound_0x62;
  uint8_t sound_0x63;
  uint8_t sound_0x64;
  uint8_t sound_0x65;
  uint8_t sound_0x66;
  uint8_t sound_0x67;
  uint8_t sound_0x68;
  uint8_t sound_0x69;
  uint8_t sound_0x6a;
  uint8_t sound_0x6b;
  uint8_t sound_0x6c;
  uint8_t sound_0x6d;
  uint8_t sound_0x6e;
  uint8_t sound_0x6f;
  uint8_t sound_0x70;
  uint8_t sound_0x71;
  uint8_t sound_0x72;
  uint8_t sound_0x73;
  uint8_t sound_0x74;
  uint8_t sound_0x75;
  uint8_t sound_0x76;
  uint8_t sound_0x77;
  uint8_t sound_0x78;
  uint8_t sound_0x79;
  uint8_t sound_0x7a;
  uint8_t sound_0x7b;
  uint8_t sound_0x7c;
  uint8_t sound_0x7d;
  uint8_t sound_0x7e;
  uint8_t sound_0x7f;
  uint8_t sound_0x80;
  uint8_t sound_0x81;
  uint8_t sound_0x82;
  uint8_t sound_0x83;
  uint8_t sound_0x84;
  uint8_t sound_0x85;
  uint8_t sound_0x86;
  uint8_t sound_0x87;
  uint8_t sound_0x88;
  uint8_t sound_0x89;
  uint8_t sound_0x8a;
  uint8_t sound_0x8b;
  uint8_t sound_0x8c;
  uint8_t sound_0x8d;
  uint8_t sound_0x8e;
  uint8_t sound_0x8f;
  uint8_t sound_0x90;
  uint8_t sound_0x91;
  uint8_t sound_0x92;
  uint8_t sound_0x93;
  uint8_t sound_0x94;
  uint8_t sound_0x95;
  uint8_t sound_0x96;
  uint8_t sound_0x97;
  uint8_t sound_0x98;
  uint8_t sound_0x99;
  uint8_t sound_0x9a;
  uint8_t sound_0x9b;
  uint8_t sound_0x9c;
  uint8_t sound_0x9d;
  uint8_t sound_0x9e;
  uint8_t sound_0x9f;
  uint8_t sound_0xa0;
  uint8_t sound_0xa1;
  uint8_t sound_0xa2;
  uint8_t sound_0xa3;
  uint8_t sound_0xa4;
  uint8_t sound_0xa5;
  uint8_t sound_0xa6;
  uint8_t sound_0xa7;
  uint8_t sound_0xa8;
  uint8_t sound_0xa9;
  uint8_t sound_0xaa;
  uint8_t sound_0xab;
  uint8_t sound_0xac;
  uint8_t sound_0xad;
  uint8_t sound_0xae;
  uint8_t sound_0xaf;
  uint8_t sound_0xb0;
  uint8_t sound_0xb1;
  uint8_t sound_0xb2;
  uint8_t sound_0xb3;
  uint8_t sound_0xb4;
  uint8_t sound_0xb5;
  uint8_t sound_0xb6;
  uint8_t sound_0xb7;
  uint8_t sound_0xb8;
  uint8_t sound_0xb9;
  uint8_t sound_0xba;
  uint8_t sound_0xbb;
  uint8_t sound_0xbc;
  uint8_t sound_0xbd;
  uint8_t sound_0xbe;
  uint8_t sound_0xbf;
  uint8_t sound_0xc0;
  uint8_t sound_0xc1;
  uint8_t sound_0xc2;
  uint8_t sound_0xc3;
  uint8_t sound_0xc4;
  uint8_t sound_0xc5;
  uint8_t sound_0xc6;
  uint8_t sound_0xc7;
  uint8_t sound_0xc8;
  uint8_t sound_0xc9;
  uint8_t sound_0xca;
  uint8_t sound_0xcb;
  uint8_t sound_0xcc;
  uint8_t sound_0xcd;
  uint8_t sound_0xce;
  uint8_t sound_0xcf;
  uint8_t sound_0xd0;
  uint8_t sound_0xd1;
  uint8_t sound_0xd2;
  uint8_t sound_0xd3;
  uint8_t sound_0xd4;
  uint8_t sound_0xd5;
  uint8_t sound_0xd6;
  uint8_t sound_0xd7;
  uint8_t sound_0xd8;
  uint8_t sound_0xd9;
  uint8_t sound_0xda;
  uint8_t sound_0xdb;
  uint8_t sound_0xdc;
  uint8_t sound_0xdd;
  uint8_t sound_0xde;
  uint8_t sound_0xdf;
  uint8_t sound_0xe0;
  uint8_t sound_0xe1;
  uint8_t sound_0xe2;
  uint8_t sound_0xe3;
  uint8_t sound_0xe4;
  uint8_t sound_0xe5;
  uint8_t sound_0xe6;
  uint8_t sound_0xe7;
  uint8_t sound_0xe8;
  uint8_t sound_0xe9;
  uint8_t sound_0xea;
  uint8_t sound_0xeb;
  uint8_t sound_0xec;
  uint8_t sound_0xed;
  uint8_t sound_0xee;
  uint8_t sound_0xef;
  uint8_t sound_0xf0;
  uint8_t sound_0xf1;
  uint8_t sound_0xf2;
  uint8_t sound_0xf3;
  uint8_t sound_0xf4;
  uint8_t sound_0xf5;
  uint8_t sound_0xf6;
  uint8_t sound_0xf7;
  uint8_t sound_0xf8;
  uint8_t sound_0xf9;
  uint8_t sound_0xfa;
  uint8_t sound_0xfb;
  uint8_t sound_0xfc;
  uint8_t sound_0xfd;
  uint8_t sound_0xfe;
  uint8_t sound_0xff;
} SoundTable;

Sparkle

Source: include/renderers.h:79-90
Size: 0x18

Field Offset
m_Position 0x0
m_Life 0xc
m_Speed 0xd
m_0x0E 0xe
m_0x0F 0xf
m_Color 0x10
m_Fade 0x14
m_Size 0x15
typedef struct Sparkle {
  Vector3D m_Position;

  uint8_t m_Life;  // Remaining life in ticks
  uint8_t m_Speed; // Speed
  uint8_t m_0x0E;  // Not sure, variation
  uint8_t m_0x0F;  // Not sure

  Color m_Color;
  uint8_t m_Fade;
  uint8_t m_Size;
} Sparkle;

SpecialSurface

Source: include/environment.h:6-9
Size: 0xc

Field Offset
m_Type 0x0
m_Param1 0x4
m_Param2 0x8
typedef struct SpecialSurface {
  uint8_t m_Type;
  int m_Param1, m_Param2;
} SpecialSurface;

SpecularAndMetal

Source: include/specular_and_metal.h:7-20
Size: 0x30

Field Offset
m_specularLightDirection 0x0
m_specularLightDirectionMoby 0xc
m_metalmatrix 0x18
m_specularTime 0x2c
typedef struct SpecularAndMetal {
  /** @brief The direction of the light that shines on specular surfaces. */
  Vector3D m_specularLightDirection;

  /** @brief The direction of the light that shines on specular surfaces (For. */
  Vector3D m_specularLightDirectionMoby;

  /** @brief The matrix used to rotate the vertex normals of metal surfaces. */
  SHORTMATRIX m_metalmatrix;

  /** @brief The timer used to animate the specular light on menus. */
  int m_specularTime;
} SpecularAndMetal;

SphericalCoordinates

Source: include/vector.h:18-20
Size: 0xc

Field Offset
azimuth 0x0
elevation 0x4
radius 0x8
typedef struct SphericalCoordinates {
  int azimuth, elevation, radius;
} SphericalCoordinates;

SphericalCoordsOffset

Source: include/camera.h:23-26
Size: 0x18

Field Offset
m_Coords 0x0
m_Offset 0xc
typedef struct SphericalCoordsOffset {
  SphericalCoordinates m_Coords;
  SphericalCoordinates m_Offset;
} SphericalCoordsOffset;

Spyro

Source: include/spyro.h:64-265
Size: 0x2a4

Field Offset
m_Position 0x0
m_bodyRotation 0xc
m_headRotation 0xf
m_tailRotation 0x12
unk_0x15 0x15
m_bodyAnimation 0x18
m_nextBodyAnimation 0x19
m_headAnimation 0x1a
m_nextHeadAnimation 0x1b
m_tailAnimation 0x1c
m_nextTailAnimation 0x1d
m_bodyAnimationFrame 0x1e
m_nextBodyAnimationFrame 0x1f
m_headAnimationFrame 0x20
m_nextHeadAnimationFrame 0x21
m_tailAnimationFrame 0x22
m_nextTailAnimationFrame 0x23
m_bodyFrameProgress 0x24
m_headFrameProgress 0x25
m_tailFrameProgress 0x26
m_sortingDepth 0x27
m_colorFilter 0x28
m_colorFilter.m_red 0x28
m_colorFilter.m_green 0x29
m_colorFilter.m_blue 0x2a
m_colorFilter.m_interpolation 0x2b
m_DamageFlags 0x2c
m_FloorDistance 0x30
m_RotationMatrix 0x34
m_bodyTransitionType 0x54
m_bodyAnimationSpeed 0x58
m_lastAnimationState 0x5c
unk_0x60 0x60
m_headAnimationSpeed 0x64
unk_0x68 0x68
unk_0x6C 0x6c
m_tailAnimationSpeed 0x70
unk_0x74 0x74
m_State 0x78
m_walkingState 0x7c
m_idleTimer 0x80
unk_0x84 0x84
m_touchingMoby 0x88
m_previousPosition 0x8c
m_floorIdleTime 0x98
m_airTime 0x9c
m_surfaceBelowSpyro 0xa0
m_floorPositonOnSlope 0xa4
m_slopeAngle 0xb0
m_againstWall 0xb4
m_wallAgainstSpyro 0xb8
m_onEdge 0xc4
m_Physics 0xc8
m_onSlope 0x150
m_isGliding 0x154
m_highestFlightPoint 0x158
unk_0x15c 0x15c
m_invulverabilityTimer 0x160
m_health 0x164
m_drowningOffset 0x168
m_touchingSurface 0x16c
m_SurfaceProximityState 0x170
m_damagingFloorIndex 0x174
m_damagingFloorFlags 0x178
unk_0x17c 0x17c
m_KnockbackDirection 0x188
unk_0x194 0x194
unk_0x198 0x198
unk_0x19c 0x19c
unk_0x1a0 0x1a0
m_HeadLookTarget 0x1a4
unk_0x1b0 0x1b0
unk_0x1b4 0x1b4
unk_0x1b8 0x1b8
unk_0x1bc 0x1bc
unk_0x1c0 0x1c0
unk_0x1c4 0x1c4
m_headRotationMatrix 0x1c8
m_seperateTailAnimation 0x1e8
m_flameableFrames 0x1ec
m_noGamepadUpdateFrames 0x1f0
m_ControlFlags 0x1f4
m_portalEndPos 0x1f8
m_portalAngle 0x204
unk_0x207 0x207
unk_0x208 0x208
unk_0x214 0x214
m_fallingState 0x218
unk_0x21c 0x21c
unk_0x220 0x220
m_mobyInUseBySpyro 0x224
unk_0x228 0x228
unk_0x240 0x240
unk_0x244 0x244
unk_0x248 0x248
m_flyingAbility 0x24c
m_doingSupercharge 0x250
unk_0x254 0x254
m_RotXAccumulator 0x258
m_RotYAccumulator 0x25c
unk_0x260 0x260
unk_0x264 0x264
unk_0x268 0x268
unk_0x26c 0x26c
unk_0x270 0x270
m_CollisionTriangleIndex 0x274
m_collisionTriangleUnpacked 0x278
m_collisionTriangleUnpacked.points 0x278
m_floorFlagsPointer 0x29c
m_damageSoundChannel 0x2a0
m_chargeSoundChannel 0x2a1
unk_0x2a2 0x2a2
typedef struct Spyro {
  Vector3D m_Position;

  /** @brief The rotation of the body. */
  Vector3D8 m_bodyRotation;

  /** @brief The rotation of the head. */
  Vector3D8 m_headRotation;

  /** @brief The rotation of the tail. */
  Vector3D8 m_tailRotation;

  Vector3D8 unk_0x15; // No idea, no XREFs

  /** @brief The animation the body is playing. */
  uint8_t m_bodyAnimation;

  /** @brief The next animation the body will play, used for interpolation. */
  uint8_t m_nextBodyAnimation;

  /** @brief The animation the head is playing. */
  uint8_t m_headAnimation;

  /** @brief The next animation the head will play, used for interpolation. */
  uint8_t m_nextHeadAnimation;

  /** @brief The animation the tail is playing. */
  uint8_t m_tailAnimation;

  /** @brief The next animation the tail will play, used for interpolation. */
  uint8_t m_nextTailAnimation;

  /** @brief The current frame of the body. */
  uint8_t m_bodyAnimationFrame;

  /** @brief The next frame of the body, used for interpolation. */
  uint8_t m_nextBodyAnimationFrame;

  /** @brief The current frame of the head. */
  uint8_t m_headAnimationFrame;

  /** @brief The next frame of the head, used for interpolation. */
  uint8_t m_nextHeadAnimationFrame;

  /** @brief The current frame of the tail. */
  uint8_t m_tailAnimationFrame;

  /** @brief The next frame of the tail, used for interpolation. */
  uint8_t m_nextTailAnimationFrame;

  // The progress of the current frame used for interpolation,
  // 0 - 4096 (0.0 - 1.0)

  /** @brief The progress of the body frame. */
  uint8_t m_bodyFrameProgress;

  /** @brief The progress of the head frame. */
  uint8_t m_headFrameProgress;

  /** @brief The progress of the tail frame. */
  uint8_t m_tailFrameProgress;

  /** @brief Subtracted from Spyro's Z depth, unsigned though (usually 4). */
  uint8_t m_sortingDepth;

  /** @brief Interpolated with vertex colours, used by Fairy Kiss effect. */
  struct {
    uint8_t m_red;
    uint8_t m_green;
    uint8_t m_blue;
    uint8_t m_interpolation; // 0 - 255 (0.0 - 1.0)
  } m_colorFilter;

  /** @brief The damage that's been applied to Spyro, similar to Mobys. */
  uint32_t m_DamageFlags; // TODO: enum / defines

  /** @brief The distance to the floor. */
  int m_FloorDistance;

  /** @brief Spyro's rotation matrix. */
  PSX_MATRIX m_RotationMatrix;

  /** @brief Current body animation transition type (0=normal, 1-8=various. */
  int m_bodyTransitionType;

  int m_bodyAnimationSpeed;

  /** @brief Previous animation state, used as "from" in transition lookup table. */
  int m_lastAnimationState;
  int unk_0x60;
  int m_headAnimationSpeed;
  int unk_0x68;
  int unk_0x6C;
  int m_tailAnimationSpeed;
  int unk_0x74;
  int m_State; // TODO: enum / defines
  int m_walkingState;
  int m_idleTimer;
  int unk_0x84;
  int m_touchingMoby;
  Vector3D m_previousPosition; // 0x8c - Position before movement update
  int m_floorIdleTime;         // 0x98
  int m_airTime;               // 0x9c
  int m_surfaceBelowSpyro;
  Vector3D m_floorPositonOnSlope;
  int m_slopeAngle;
  int m_againstWall;
  Vector3D m_wallAgainstSpyro;
  int m_onEdge;
  SpyroPhysics m_Physics;
  int m_onSlope;
  int m_isGliding;
  int m_highestFlightPoint;
  int unk_0x15c;
  int m_invulverabilityTimer;
  int m_health;
  int m_drowningOffset;
  int m_touchingSurface;
  /**
   * Tracks proximity state to special surfaces when Spyro is above but not
   * directly on them.
   *
   * - Reset to 0 each frame in UpdateSpyroPhysicsAndSurfaces before surface
   * checks
   * - Set to 1 by ApplySpecialSurfaceEffects when Spyro is above a type-0
   * damage floor (more than 512 units above) but not close enough for direct
   * contact
   * - Checked by physics (func_80043FE4) to modify behavior when hovering
   *   above special surfaces
   */
  int m_SurfaceProximityState;
  int m_damagingFloorIndex;
  uint32_t m_damagingFloorFlags; /**< Guest pointer: `int *`. */
  Vector3D unk_0x17c;
  Vector3D m_KnockbackDirection; // Direction vector applied to acceleration on
                                 // knockback
  int unk_0x194;                 // Used to force spyro to flame in cutscenes
  int unk_0x198;
  int unk_0x19c;
  int unk_0x1a0;
  Vector3D
      m_HeadLookTarget; // Target angles for head look-at (set by
                        // SetSpyroHeadLookTarget, consumed by func_80049880)
  int unk_0x1b0;
  int unk_0x1b4;
  int unk_0x1b8;
  int unk_0x1bc;
  int unk_0x1c0;
  int unk_0x1c4;
  PSX_MATRIX
  m_headRotationMatrix; // 0x1c8 - Combined body+head rotation for rendering
  int m_seperateTailAnimation; // Whether the tail is animated seperately from
                               // the body, otherwise it copies the body
  int m_flameableFrames; // How many frames have we been able to flame? Not used
                         // for anything, isn't reset either, useless
  int m_noGamepadUpdateFrames; // How many frames the gamepad can't be updated
                               // for
  /**
   * Bitfield of ControlFlags that modify Spyro's behavior during scripted
   * sequences, cutscenes, and special traversal states.
   * Cleared to 0 when exiting cutscene/scripted playback.
   * @see ControlFlags
   */
  int m_ControlFlags;
  Vector3D m_portalEndPos; // Not 100% sure
  Vector3D8 m_portalAngle; // The angle of the portal
  uint8_t unk_0x207;        // Padding
  Vector3D unk_0x208;
  int unk_0x214;
  int m_fallingState; // Not sure
  uint32_t unk_0x21c; /**< Guest pointer: `Vector3D *`. */
  int unk_0x220;

  // Used for the cannon, and whirlwinds, camera related
  uint32_t m_mobyInUseBySpyro; /**< Guest pointer: `Moby *`. */
  uint8_t unk_0x228[24]; // Fuck knows, no XREFs, considering the rest of this
                        // section it's probably moby related though
  uint32_t unk_0x240; /**< Guest pointer: `PathData *`. */
  int unk_0x244;       // Path moby related
  int unk_0x248;       // Path moby related
  int m_flyingAbility; // Used in flying levels and gnasty's loot
  int m_doingSupercharge;
  int unk_0x254;
  int m_RotXAccumulator; // Spring-damper accumulator for smooth RotX
                         // transitions
  int m_RotYAccumulator; // Spring-damper accumulator for smooth RotY
                         // transitions
  int unk_0x260;         // No XREFS
  int unk_0x264;
  int unk_0x268;
  int unk_0x26c; // No XREFS
  int unk_0x270; // No XREFS
  int m_CollisionTriangleIndex;
  struct {
    Vector3D points[3];
  } m_collisionTriangleUnpacked;
  uint32_t m_floorFlagsPointer; /**< Guest pointer: `int *`. */
  uint8_t m_damageSoundChannel;
  uint8_t m_chargeSoundChannel;
  short unk_0x2a2; // Probably padding
} Spyro;

SpyroAnimationFrame

Source: include/moby.h:187-194
Size: 0x4

Field Offset
m 0x0
m.m_Data 0x0
typedef struct SpyroAnimationFrame {
  union {
    // TODO: Document the Spyro model format
    // struct {
    // } m_Props;
    uint32_t m_Data;
  } m;
} SpyroAnimationFrame;

SpyroFlame

Source: include/spyro.h:287-367
Size: 0x138

Field Offset
m_Position 0x0
m_Rotation 0xc
pad1 0xf
m_FlameTexture 0x10
m_SuperFlameTexture 0x18
unk_20 0x20
unk_24 0x24
unk_28 0x28
unk_2c 0x2c
unk_30 0x30
unk_34 0x34
unk_38 0x38
unk_3c 0x3c
unk_40 0x40
unk_44 0x44
unk_48 0x48
unk_4c 0x4c
unk_50 0x50
unk_54 0x54
unk_58 0x58
unk_5c 0x5c
unk_60 0x60
unk_64 0x64
unk_68 0x68
unk_6c 0x6c
unk_70 0x70
unk_74 0x74
unk_78 0x78
unk_7c 0x7c
unk_80 0x80
unk_84 0x84
unk_88 0x88
unk_8c 0x8c
unk_90 0x90
unk_94 0x94
m_IsFlameActive 0x98
unk_99 0x99
unk_9c 0x9c
m_FairyKissTimer 0xa0
unk_a4 0xa4
unk_a8 0xa8
unk_ac 0xac
unk_b0 0xb0
unk_b4 0xb4
unk_b8 0xb8
unk_bc 0xbc
unk_c0 0xc0
unk_c4 0xc4
unk_c8 0xc8
unk_cc 0xcc
unk_d0 0xd0
unk_d4 0xd4
unk_d8 0xd8
unk_dc 0xdc
unk_e0 0xe0
unk_e4 0xe4
unk_e8 0xe8
unk_ec 0xec
unk_f0 0xf0
unk_f4 0xf4
unk_f8 0xf8
unk_fc 0xfc
unk_100 0x100
unk_104 0x104
unk_108 0x108
unk_10c 0x10c
unk_110 0x110
unk_114 0x114
unk_118 0x118
unk_11c 0x11c
unk_120 0x120
unk_124 0x124
unk_128 0x128
unk_12c 0x12c
unk_130 0x130
unk_134 0x134
typedef struct SpyroFlame {
  Vector3D m_Position;
  Vector3D8 m_Rotation;
  uint8_t pad1;
  Tiledef m_FlameTexture;
  Tiledef m_SuperFlameTexture;
  int unk_20;
  int unk_24;
  int unk_28;
  int unk_2c;
  int unk_30;
  int unk_34;
  int unk_38;
  int unk_3c;
  int unk_40;
  int unk_44;
  int unk_48;
  int unk_4c;
  int unk_50;
  int unk_54;
  int unk_58;
  int unk_5c;
  int unk_60;
  int unk_64;
  int unk_68;
  int unk_6c;
  int unk_70;
  int unk_74;
  int unk_78;
  int unk_7c;
  int unk_80;
  int unk_84;
  int unk_88;
  int unk_8c;
  int unk_90;
  int unk_94;

  /** @brief Flame breath active flag. 1 = active, 0 = inactive */
  uint8_t m_IsFlameActive;

  uint8_t unk_99[3];
  int unk_9c;
  int m_FairyKissTimer;
  int unk_a4;
  int unk_a8;
  int unk_ac;
  int unk_b0;
  int unk_b4;
  int unk_b8;
  int unk_bc;
  int unk_c0;
  int unk_c4;
  int unk_c8;
  int unk_cc;
  int unk_d0;
  int unk_d4;
  int unk_d8;
  int unk_dc;
  int unk_e0;
  int unk_e4;
  int unk_e8;
  int unk_ec;
  int unk_f0;
  int unk_f4;
  int unk_f8;
  int unk_fc;
  int unk_100;
  int unk_104;
  int unk_108;
  int unk_10c;
  int unk_110;
  int unk_114;
  int unk_118;
  int unk_11c;
  int unk_120;
  int unk_124;
  int unk_128;
  int unk_12c;
  int unk_130;
  int unk_134;
} SpyroFlame;

SpyroPhysics

Source: include/spyro.h:45-62
Size: 0x88

Field Offset
m_TargetSpeedAngle 0x0
m_SlopeGravityZ 0x10
unk_0xdc 0x14
unk_0xe8 0x20
m_Acceleration 0x2c
m_Velocity 0x38
m_TrueVelocity 0x44
m_SpeedAngle 0x50
m_TrueSpeed 0x60
m_CollisionMovement 0x64
unk_0x138 0x70
unk_0x13c 0x74
unk_0x140 0x78
unk_0x144 0x7c
m_TurnMomentum 0x80
m_gravity 0x84
typedef struct SpyroPhysics {
 // Needed to match atleast one place
  SpyroSpeedAngle m_TargetSpeedAngle;
  int m_SlopeGravityZ; // Set by ApplySlopeGravity but never read (unused)
  Vector3D unk_0xdc;
  Vector3D unk_0xe8; // Probably some kind of momentum, not sure
  Vector3D m_Acceleration;
  Vector3D m_Velocity;
  Vector3D m_TrueVelocity; // After collision, how much of the velocity is left
  SpyroSpeedAngle m_SpeedAngle;
  int m_TrueSpeed;              // The size of m_TrueVelocity
  Vector3D m_CollisionMovement; // How much the triangle under spyro moved
  int unk_0x138;
  int unk_0x13c;
  int unk_0x140;
  int unk_0x144;
  int m_TurnMomentum; // -6 (hard left) to +6 (hard right)
  int m_gravity;
} SpyroPhysics;

SpyroShadow

Source: include/spyro.h:371-380
Size: 0x28

Field Offset
unk_00 0x0
unk_04 0x4
unk_08 0x8
unk_0c 0xc
m_Position 0x10
unk_1c 0x1c
unk_20 0x20
m_IsSpyroOverWater 0x24
typedef struct SpyroShadow {
  int unk_00;
  int unk_04;
  int unk_08;
  int unk_0c;
  Vector3D m_Position;
  int unk_1c;
  int unk_20;
  int m_IsSpyroOverWater;
} SpyroShadow;

SpyroSpeedAngle

Source: include/spyro.h:40-43
Size: 0x10

Field Offset
m_Speed 0x0
m_RotZ 0x4
m_RotY 0x8
m_RotX 0xc
typedef struct SpyroSpeedAngle {
  int m_Speed;
  int m_RotZ, m_RotY, m_RotX;
} SpyroSpeedAngle;

TerrainCollision

Source: include/environment.h:11-19
Size: 0x1c

Field Offset
m_TriangleCount 0x0
m_FlagCount 0x4
m_BlockTree 0x8
m_Blocks 0xc
m_Triangles 0x10
m_TriangleOcclusionAssignment 0x14
m_Flags 0x18
typedef struct TerrainCollision {
  int m_TriangleCount;
  int m_FlagCount;
  uint32_t m_BlockTree; /**< Guest pointer: `uint16_t *`. */
  uint32_t m_Blocks; /**< Guest pointer: `uint16_t *`. */
  uint32_t m_Triangles; /**< Guest pointer: `void *`. */
  uint32_t m_TriangleOcclusionAssignment; /**< Guest pointer: `uint8_t *`. */
  uint32_t m_Flags; /**< Guest pointer: `uint8_t *`. */
} TerrainCollision;

Tiledef

Source: include/common.h:124-139
Size: 0x8

Field Offset
uv0 0x0
uv0.s 0x0
uv0.s.u0 0x0
uv0.s.v0 0x1
uv0.s.clut 0x2
uv0.all 0x0
uv1 0x4
uv1.s 0x4
uv1.s.u1 0x4
uv1.s.v1 0x5
uv1.s.tpage 0x6
uv1.all 0x4
typedef struct Tiledef {
  union {
    struct {
      uint8_t u0, v0;
      uint16_t clut;
    } s;
    int all;
  } uv0;
  union {
    struct {
      uint8_t u1, v1;
      uint16_t tpage;
    } s;
    int all;
  } uv1;
} Tiledef;

TracerPoint

Source: include/graphics.h:56-60
Size: 0x1c

Field Offset
WorldPos 0x0
ScreenPos 0xc
Age 0x18
typedef struct TracerPoint {
  Vector3D WorldPos;
  Vector3D ScreenPos;
  int Age;
} TracerPoint;

TransGem

Source: include/loaders.h:15-26
Size: 0x10

Field Offset
xOffset 0x0
yOffset 0x2
targetX 0x4
targetY 0x6
_08 0x8
age 0x9
rot 0xa
_0D 0xd
_0E 0xe
_0F 0xf
typedef struct TransGem {
  short xOffset;
  short yOffset;
  short targetX;
  short targetY;
  uint8_t _08;
  uint8_t age;
  Vector3D8 rot;
  uint8_t _0D;
  uint8_t _0E;
  uint8_t _0F;
} TransGem;

Vector3D

Source: include/vector.h:6-8
Size: 0xc

Field Offset
x 0x0
y 0x4
z 0x8
typedef struct Vector3D {
  int x, y, z;
} Vector3D;

Vector3D16

Source: include/vector.h:14-16
Size: 0x6

Field Offset
x 0x0
y 0x2
z 0x4
typedef struct Vector3D16 {
  short x, y, z;
} Vector3D16;

Vector3D8

Source: include/vector.h:10-12
Size: 0x3

Field Offset
x 0x0
y 0x1
z 0x2
typedef struct Vector3D8 {
  uint8_t x, y, z;
} Vector3D8;

WadDragonHeader

Source: include/dragon.h:7-13
Size: 0x24

Field Offset
unk_0x0 0x0
m_SpuData 0x4
m_DragonModel 0xc
m_SpyroModel 0x14
m_CameraData 0x1c
typedef struct WadDragonHeader {
  int unk_0x0; // Unknown, always 0
  OffsetLength m_SpuData;
  OffsetLength m_DragonModel;
  OffsetLength m_SpyroModel;
  OffsetLength m_CameraData;
} WadDragonHeader;

PSYQ types

Types from the PlayStation SDK that the game structs embed. Their layouts are pinned like every other struct; PSX_RECT and PSX_MATRIX complete the forward declarations the wrappers header makes. The PSX_ prefix is what lets a mod include <windows.h>, which defines a RECT of its own.

PSX_MATRIX

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x20

Field Offset
m 0x0
t 0x14
typedef struct PSX_MATRIX {
  short m[3][3]; /**< 3x3 rotation matrix. */
  int32_t t[3];     /**< Transfer vector. */
} PSX_MATRIX;

PSX_RECT

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x8

Field Offset
x 0x0
y 0x2
w 0x4
h 0x6
typedef struct PSX_RECT {
  short x, y; /**< Offset point on VRAM. */
  short w, h; /**< Width and height. */
} PSX_RECT;

PSX_DR_ENV

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x40

Field Offset
tag 0x0
code 0x4
typedef struct PSX_DR_ENV {
  uint32_t tag;
  uint32_t code[15];
} PSX_DR_ENV;

PSX_DRAWENV

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x5c

Field Offset
clip 0x0
ofs 0x8
tw 0xc
tpage 0x14
dtd 0x16
dfe 0x17
isbg 0x18
r0 0x19
g0 0x1a
b0 0x1b
dr_env 0x1c
typedef struct PSX_DRAWENV {
  PSX_RECT clip;         /**< Clip area. */
  short ofs[2];      /**< Drawing offset. */
  PSX_RECT tw;           /**< Texture window. */
  uint16_t tpage;     /**< Texture page. */
  uint8_t dtd;        /**< Dither flag (0:off, 1:on). */
  uint8_t dfe;        /**< Draw on the display area (0:off, 1:on). */
  uint8_t isbg;       /**< Auto-clear enable. */
  uint8_t r0, g0, b0; /**< Initial background colour. */
  PSX_DR_ENV dr_env;     /**< Packed drawing environment. */
} PSX_DRAWENV;

PSX_DISPENV

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x14

Field Offset
disp 0x0
screen 0x8
isinter 0x10
isrgb24 0x11
pad0 0x12
pad1 0x13
typedef struct PSX_DISPENV {
  PSX_RECT disp;         /**< Display area. */
  PSX_RECT screen;       /**< Display start point. */
  uint8_t isinter;    /**< Interlace 0:off, 1:on. */
  uint8_t isrgb24;    /**< RGB24 mode. */
  uint8_t pad0, pad1;
} PSX_DISPENV;

PSX_SpuVolume

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x4

Field Offset
left 0x0
right 0x2
typedef struct PSX_SpuVolume {
  short left;  /**< Lch. */
  short right; /**< Rch. */
} PSX_SpuVolume;

PSX_SpuExtAttr

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0xc

Field Offset
volume 0x0
reverb 0x4
mix 0x8
typedef struct PSX_SpuExtAttr {
  PSX_SpuVolume volume;
  int reverb;
  int mix;
} PSX_SpuExtAttr;

PSX_SpuCommonAttr

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x28

Field Offset
mask 0x0
mvol 0x4
mvolmode 0x8
mvolx 0xc
cd 0x10
ext 0x1c
typedef struct PSX_SpuCommonAttr {
  uint32_t mask;
  PSX_SpuVolume mvol;
  PSX_SpuVolume mvolmode;
  PSX_SpuVolume mvolx;
  PSX_SpuExtAttr cd;
  PSX_SpuExtAttr ext;
} PSX_SpuCommonAttr;

PSX_CdlLOC

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x4

Field Offset
minute 0x0
second 0x1
sector 0x2
track 0x3
typedef struct PSX_CdlLOC {
  uint8_t minute; /**< Minute (BCD). */
  uint8_t second; /**< Second (BCD). */
  uint8_t sector; /**< Sector (BCD). */
  uint8_t track;
} PSX_CdlLOC;

PSX_CdlATV

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x4

Field Offset
val0 0x0
val1 0x1
val2 0x2
val3 0x3
typedef struct PSX_CdlATV {
  uint8_t val0; /**< Volume CD(L) -> SPU(L). */
  uint8_t val1; /**< Volume CD(L) -> SPU(R). */
  uint8_t val2; /**< Volume CD(R) -> SPU(L). */
  uint8_t val3; /**< Volume CD(R) -> SPU(R). */
} PSX_CdlATV;

PSX_CdlFILE

Source: PSYQ SDK (tools/psyq_types.py)
Size: 0x18

Field Offset
pos 0x0
size 0x4
name 0x8
typedef struct PSX_CdlFILE {
  PSX_CdlLOC pos;    /**< File location. */
  uint32_t size;    /**< File size. */
  char name[16]; /**< File name. */
} PSX_CdlFILE;