#pragma once

#include "ghidra.h"

#define COLLISION_FLAGS_LEFT 0x1
#define COLLISION_FLAGS_RIGHT 0x2
#define COLLISION_FLAGS_FLOOR 0x4
#define COLLISION_FLAGS_CEIL 0x8
#define IO_PCBVER_FLAG_INTERNATIONAL 0x80
#define STRING_END 0xff
#define IO_Z80BUS_LOCK 0x100
#define IO_Z80BUS_UNLOCK 0x0
#define IO_Z80RES_FREEZE 0x0
#define IO_Z80RES_THAW 0x100
#define VDP_REG_MODE_SET_3_PER_LINE_H_SCROLL 0x8b03
// FIXME
// #define COMPRESSION_LZ77_HUFFMAN 0x2000000
// FIXME
// #define COMPRESSION_NONE 0x1000000

typedef unsigned int dword;
typedef long long longlong;
typedef unsigned long long qword;
typedef unsigned char uchar;
typedef unsigned long long ulonglong;
typedef unsigned long long undefined5;
typedef unsigned long long undefined6;
typedef unsigned long long undefined8;
typedef unsigned short ushort;
typedef unsigned short wchar16;
typedef unsigned short word;
#define unkbyte9 unsigned long long
#define unkbyte10 unsigned long long
#define unkbyte11 unsigned long long
#define unkbyte12 unsigned long long
#define unkbyte13 unsigned long long
#define unkbyte14 unsigned long long
#define unkbyte15 unsigned long long
#define unkbyte16 unsigned long long

#define unkuint9 unsigned long long
#define unkuint10 unsigned long long
#define unkuint11 unsigned long long
#define unkuint12 unsigned long long
#define unkuint13 unsigned long long
#define unkuint14 unsigned long long
#define unkuint15 unsigned long long
#define unkuint16 unsigned long long

#define unkint9 long long
#define unkint10 long long
#define unkint11 long long
#define unkint12 long long
#define unkint13 long long
#define unkint14 long long
#define unkint15 long long
#define unkint16 long long

#define unkfloat1 float
#define unkfloat2 float
#define unkfloat3 float
#define unkfloat5 double
#define unkfloat6 double
#define unkfloat7 double
#define unkfloat9 long double
#define unkfloat11 long double
#define unkfloat12 long double
#define unkfloat13 long double
#define unkfloat14 long double
#define unkfloat15 long double
#define unkfloat16 long double

#define BADSPACEBASE void
#define code void

typedef struct int8_vec2_t int8_vec2_t, *Pint8_vec2_t;

struct int8_vec2_t {
  int8_t x;
  int8_t y;
};

typedef struct tile_1bpp_row_t tile_1bpp_row_t, *Ptile_1bpp_row_t;

typedef uchar uint8_t;

struct tile_1bpp_row_t {
  uint8_t a : 1;
  uint8_t b : 1;
  uint8_t c : 1;
  uint8_t d : 1;
  uint8_t e : 1;
  uint8_t f : 1;
  uint8_t g : 1;
  uint8_t h : 1;
};

typedef struct compressed_data_ref_t compressed_data_ref_t,
    *Pcompressed_data_ref_t;

typedef enum compression_t {
  COMPRESSION_00 = 0,
  COMPRESSION_NONE = 1,
  COMPRESSION_01_LZ77_HUFFMAN = 2,
  COMPRESSION_INVALID = 255,
} compression_t;

struct compressed_data_ref_t {
  enum compression_t encoding;
  pointer24 address;
};

typedef struct glyph_info_4_t glyph_info_4_t, *Pglyph_info_4_t;

typedef struct glyph_flag_t glyph_flag_t, *Pglyph_flag_t;

typedef struct tile_1bpp_t tile_1bpp_t, *Ptile_1bpp_t;

struct glyph_flag_t { // Encodes how to parse the following glyph data.
  bool narrow : 1;    // Whether the glyph only has two tiles rather than four
  bool g : 1;
  bool f : 1;
  bool e : 1;
  bool d : 1;
  bool checksum : 1;
  bool rle : 1; // Whether the tiles are run-length encoded
  bool a : 1;
};

struct tile_1bpp_t {
  struct tile_1bpp_row_t a;
  struct tile_1bpp_row_t b;
  struct tile_1bpp_row_t c;
  struct tile_1bpp_row_t d;
  struct tile_1bpp_row_t e;
  struct tile_1bpp_row_t f;
  struct tile_1bpp_row_t g;
  struct tile_1bpp_row_t h;
};

struct glyph_info_4_t {
  struct glyph_flag_t flag;
  struct tile_1bpp_t tiles[4];
};

typedef uint16_t vdp_color_t;

typedef struct script_state_bit_t script_state_bit_t, *Pscript_state_bit_t;

struct script_state_bit_t { // Represents a specific bit in a specific byte.
  uint16_t index : 13;
  uint8_t bit : 3;
};

typedef struct comp_unkown_t comp_unkown_t, *Pcomp_unkown_t;

struct comp_unkown_t {
  word unk1;
  word unk2;
};

typedef enum vdp_reg_t {
  VDP_REG_MODE_SET_1 = 32768,
  VDP_REG_MODE_SET_1_COLOR_USE_ALL_BITS = 32772,
  VDP_REG_MODE_SET_1_COLOR_HBLANK_INTERRUPT_AND_USE_ALL_BITS = 32788,
  VDP_REG_MODE_SET_2 = 33028,
  VDP_REG_SCROLL_A_ADDR_0000 = 33280,
  VDP_REG_SCROLL_A_ADDR_C000 = 33328,
  VDP_REG_WINDOW_ADDR_0000 = 33536,
  VDP_REG_WINDOW_ADDR_D000 = 33588,
  VDP_REG_SCROLL_B_ADDR_0000 = 33792,
  VDP_REG_SCROLL_B_ADDR_E000 = 33799,
  VDP_REG_SPRITES_TABLE_ADDR_0000 = 34048,
  VDP_REG_SPRITES_TABLE_ADDR_DC00 = 34158,
  VDP_REG_SPRITES_TABLE_ADDR_DE00 = 34159,
  VDP_REG_BACKGROUND_COLOR = 34560,
  VDP_REG_HBLANK_INTERRUPT_RATE = 35328,
  VDP_REG_MODE_SET_3 = 35584,
  VDP_REG_MODE_SET_4 = 35840,
  VDP_REG_MODE_SET_4_H40_AND_SHADOW = 35969,
  VDP_REG_HSCROLL_TABLE_ADDR_0000 = 36096,
  VDP_REG_HSCROLL_TABLE_ADDR_D800 = 36150,
  VDP_REG_MODE_AUTO_INCREMENT_00 = 36608,
  VDP_REG_MODE_AUTO_INCREMENT_02 = 36610,
  VDP_REG_SCROLL_SIZE = 36864,
  VDP_REG_SCROLL_SIZE_H64_CELL = 36865,
  VDP_REG_WIN_H_POS = 37120,
  VDP_REG_WIN_V_POS = 37376,
  VDP_REG_MODE_DMA_COUNTER_LOW = 37632,
  VDP_REG_MODE_DMA_COUNTER_HIGH = 37888,
  VDP_REG_MODE_DMA_SOURCE_ADDR_LOW = 38144,
  VDP_REG_MODE_DMA_SOURCE_ADDR_MID = 38400,
  VDP_REG_MODE_DMA_SOURCE_ADDR_HIGH = 38656,
  VDP_REG_MODE_DMA_SOURCE_VRAM_FILL = 38784,
} vdp_reg_t;

typedef struct palette_effect_state_t palette_effect_state_t,
    *Ppalette_effect_state_t;

typedef enum palette_effect_state_type_t {
  PALETTE_EFFECT_STATE_DISABLED = 0,
  PALETTE_EFFECT_STATE_ENABLED = 255,
} palette_effect_state_type_t;

struct palette_effect_state_t {
  enum palette_effect_state_type_t state;
  byte duration;
  byte remaining;
  byte unknown; // Maybe unused
};

typedef struct tile_4bpp_t tile_4bpp_t, *Ptile_4bpp_t;

typedef struct tile_4bpp_row_t tile_4bpp_row_t, *Ptile_4bpp_row_t;

struct tile_4bpp_row_t {
  uint8_t a : 4;
  uint8_t b : 4;
  uint8_t c : 4;
  uint8_t d : 4;
  uint8_t e : 4;
  uint8_t f : 4;
  uint8_t g : 4;
  uint8_t h : 4;
};

struct tile_4bpp_t {
  struct tile_4bpp_row_t a;
  struct tile_4bpp_row_t b;
  struct tile_4bpp_row_t c;
  struct tile_4bpp_row_t d;
  struct tile_4bpp_row_t e;
  struct tile_4bpp_row_t f;
  struct tile_4bpp_row_t g;
  struct tile_4bpp_row_t h;
};

typedef struct sized_string_t sized_string_t, *Psized_string_t;

struct sized_string_t {
  uint16_t length;
  char string[1];
};

typedef struct glyph_tile_t glyph_tile_t, *Pglyph_tile_t;

struct glyph_tile_t {
  struct tile_1bpp_t tiles[2]; // 1bpp, 1 byte per row top to bottom, 1 bit per
                               // column left to right.
};

typedef struct int16_vec2_t int16_vec2_t, *Pint16_vec2_t;

struct int16_vec2_t {
  int16_t x;
  int16_t y;
};

typedef byte angle_t;

typedef vdp_color_t vdp_palette_t[16];

// FIXME
// typedef struct struct struct, *Pstruct;

// FIXME
// struct struct {
//     undefined field0_0x0;
//     long field1_0x1;
// };

typedef enum hud_icon_life_drop_anim_tick_t {
  hud_icon_life_drop_anim_tick_00 = 0,
} hud_icon_life_drop_anim_tick_t;

typedef enum vdp_mem_t {
  VDP_MEM_VIDEO_RAM = 1,
  VDP_MEM_COLOR_RAM = 3,
  VDP_MEM_VSCROLL_RAM = 5,
} vdp_mem_t;

typedef struct entity_state_mixed_a_t entity_state_mixed_a_t,
    *Pentity_state_mixed_a_t;

typedef enum entity_state_a_t {
  ENTITY_STATE_A_08 = 8,
  ENTITY_STATE_A_H_FLIP = 16,
} entity_state_a_t;

typedef enum entity_state_1_b_t {
  ECS_STATE_1_B_WALKING_OR_DOWNSTAB = 2,
  ECS_STATE_1_B_JUMPING_OR_UNSHIELDING = 4,
  ECS_STATE_1_B_FALLING = 6,
  ECS_STATE_1_B_ATTACKING_MID_AIR = 8,
  ECS_STATE_1_B_ATTACKING_GROUNDED = 10,
  ECS_STATE_1_B_TALKING_OR_ENTERING_BACK_DOOR = 14,
  ECS_STATE_1_B_ENTERING_FRONT_DOOR = 34,
} entity_state_1_b_t;

struct entity_state_mixed_a_t {
  enum entity_state_a_t field0_0x0;
  enum entity_state_1_b_t field1_0x1;
};

typedef struct signed_rgb_t signed_rgb_t, *Psigned_rgb_t;

struct signed_rgb_t { // Values can be in the range [-0xf, 0xf]
  int8_t r;
  int8_t g;
  int8_t b;
  int8_t unused;
};

typedef struct GameHeader GameHeader, *PGameHeader;

struct GameHeader {
  char ConsoleName[16];
  char ReleaseDate[16];
  char DomesticName[48];
  char InternationalName[48];
  char Version[14];
  word Checksum;
  char IoSupport[16];
  pointer RomStart;
  pointer RomEnd;
  pointer RamStart;
  pointer RamEnd;
  char field11_0xb0[4];
  pointer SramStart;
  pointer field13_0xb8;
  char Notes[68];
};

typedef struct fixed_w_vec2_t fixed_w_vec2_t, *Pfixed_w_vec2_t;

typedef union fixed_w_t fixed_w_t, *Pfixed_w_t;

typedef struct fixed_11_t fixed_11_t, *Pfixed_11_t;

struct fixed_11_t {
  int8_t i;
  int8_t f;
};

union fixed_w_t {
  short raw;
  struct fixed_11_t fixed;
};

struct fixed_w_vec2_t {
  union fixed_w_t x;
  union fixed_w_t y;
};

typedef char *script_t;

typedef enum palette_id_offset_t { // Only multiples of 4 are valid.
  PALETTE_ID_OFFSET_0 = 0,
  PALETTE_ID_OFFSET_1 = 4,
  PALETTE_ID_OFFSET_2 = 8,
  PALETTE_ID_OFFSET_3 = 12,
} palette_id_offset_t;

typedef enum palette_id_flag_t {
  PALETTE_ID_FLAG_NONE = 0,
  PALETTE_ID_FLAG_0 = 1,
  PALETTE_ID_FLAG_1 = 2,
  PALETTE_ID_FLAG_2 = 4,
  PALETTE_ID_FLAG_3 = 8,
  PALETTE_ID_FLAG_ALL = 15,
} palette_id_flag_t;

typedef uint16_t entity_id_w_t;

typedef enum hud_icon_life_drop_anim_unknown_1_t {
  hud_icon_life_drop_anim_unknown_1_00 = 0,
} hud_icon_life_drop_anim_unknown_1_t;

typedef struct component_mixed_1_t component_mixed_1_t, *Pcomponent_mixed_1_t;

struct component_mixed_1_t { // Used in function #27fc8
  word unknown_3;
  word x;
  word y;
  word state_1_d;
  enum entity_state_a_t state_a;
  enum entity_state_1_b_t state_1_b;
};

typedef struct sized_string_20_t sized_string_20_t, *Psized_string_20_t;

struct sized_string_20_t {
  word length;
  char string[32];
};

typedef struct glyph_info_2_t glyph_info_2_t, *Pglyph_info_2_t;

struct glyph_info_2_t {
  struct glyph_flag_t flag;
  struct tile_1bpp_t tiles[2];
};

typedef struct palette_fade_t palette_fade_t, *Ppalette_fade_t;

struct palette_fade_t {
  bool ongoing; // Seemingly can be 0, 1 or ff (needs checking)
  byte type;
  byte frames_n; // Apply the effect every n frames
  byte frames_i; // Remaining frames before applying the effect
};

typedef struct palette_effect_t palette_effect_t, *Ppalette_effect_t;

typedef enum palette_effect_type_t {
  PALETTE_EFFECT_TYPE_COLOR = 0,
  PALETTE_EFFECT_TYPE_SET_DURATION = 1,
  PALETTE_EFFECT_TYPE_STOP = 2,
  PALETTE_EFFECT_TYPE_SET_START = 3,
  PALETTE_EFFECT_TYPE_RESTART = 4,
} palette_effect_type_t;

struct palette_effect_t { // For the "set" type, the second byte is the
                          // duration.
  enum palette_effect_type_t type : 3;
  uint8_t index : 4;
  uint8_t b : 3;
  uint8_t g : 3;
  uint8_t r : 3;
};

typedef struct palette_iter_t palette_iter_t, *Ppalette_iter_t;

struct palette_iter_t {
  byte start;  // The first color index
  byte length; // The number of colors from the start index
  byte unknown2;
  byte unknown3;
};

typedef enum comp_state_t {
  COMP_STATE_STAND = 0,
  COMP_STATE_WALK = 2,
  COMP_STATE_JUMP = 4,
  COMP_STATE_FALL = 6,
  COMP_STATE_ATTACK = 8,
  COMP_STATE_ATTACK_MID_AIR = 10,
  COMP_STATE_ROPE_HOLD = 12,
  COMP_STATE_ROPE_SWITCH_SIDE = 14,
  COMP_STATE_ROPE_CLIMB_UP_START = 16,
  COMP_STATE_ROPE_CLIMP_DOWN_START = 18,
  COMP_STATE_ROPE_CLIMB_UP = 22,
  COMP_STATE_ROPE_CLIMB_DOWN = 24,
  COMP_STATE_SHIELD = 28,
  COMP_STATE_ROPE_JUMP = 32,
  COMP_STATE_THROW_PEPELOGOO = 46,
  COMP_STATE_THROW_PEPELOGOO_MID_AIR = 48,
  COMP_STATE_JUMP_FROM_PEPELOGOO = 54,
} comp_state_t;

typedef struct sized_string_8_t sized_string_8_t, *Psized_string_8_t;

struct sized_string_8_t {
  word length;
  char string[8];
};

typedef union fixed_t fixed_t, *Pfixed_t;

typedef struct fixed_22 fixed_22, *Pfixed_22;

struct fixed_22 {
  int16_t i;
  int16_t f;
};

union fixed_t {
  long raw;
  struct fixed_22 fixed;
};

typedef struct comp_func_offset_t comp_func_offset_t, *Pcomp_func_offset_t;

struct comp_func_offset_t {
  byte unk1;
  byte func_offset_from_15ede;
  byte unk3;
  byte unk4;
};

typedef enum script_mode_t {
  SCRIPT_MODE_00 = 0,
  SCRIPT_MODE_02 = 2,
  SCRIPT_MODE_04 = 4,
  SCRIPT_MODE_NEW_LINE = 6,
  SCRIPT_MODE_08 = 8,
  SCRIPT_MODE_0A = 10,
  SCRIPT_MODE_PROMPT = 12,
  SCRIPT_MODE_INCANT_SPELL = 14,
  SCRIPT_MODE_QUIZZ = 16,
  SCRIPT_MODE_SAVE = 255,
} script_mode_t;

typedef struct script_ctx_t script_ctx_t, *Pscript_ctx_t;

typedef enum script_ctx_flag_t {
  SCRIPT_CTX_FLAG_NONE = 0,
  SCRIPT_CTX_FLAG_01 = 1,
  SCRIPT_CTX_FLAG_02 = 2,
  SCRIPT_CTX_FLAG_DISABLE_SPEED_UP = 4,
  SCRIPT_CTX_FLAG_DAKUTEN = 8,
  SCRIPT_CTX_FLAG_HANDAKUTEN = 16,
  SCRIPT_CTX_FLAG_DAKUTEN_HANDAKUTEN = 24,
  SCRIPT_CTX_FLAG_40 = 64,
  SCRIPT_CTX_FLAG_80 = 128,
  SCRIPT_CTX_FLAG_A0 = 160,
  SCRIPT_CTX_FLAG_A1 = 161,
  SCRIPT_CTX_FLAG_C0 = 192,
  SCRIPT_CTX_FLAG_C1 = 193,
  SCRIPT_CTX_FLAG_E0 = 224,
  SCRIPT_CTX_FLAG_NOT_HANDAKUTEN = 239,
  SCRIPT_CTX_FLAG_NOT_DAKUTEN = 247,
} script_ctx_flag_t;

typedef union union2_t union2_t, *Punion2_t;

union union2_t {
  word w;
  byte b[2];
};

struct script_ctx_t {
  enum script_ctx_flag_t flags;
  enum script_mode_t mode;
  undefined2 bf_03_and_bf_06_arg_fed_to_vdp_data;
  script_t script;
  uint16_t b;
  undefined1 d;
  undefined1 e;
  union union2_t f;
  undefined1 h;
  uint8_t bf_09_arg;
  uint16_t i;
  union union2_t k;
  uint16_t bf_05_and_13_arg_vram_address_related;
  uint16_t bf_05_arg2_vram_address_related;
  undefined1 m;
  uint8_t script_stack_offset;
  uint8_t prompt_related;
  undefined1 p;
  undefined1 q;
  undefined1 r;
  undefined2 t;
  char *script_stack;
};

typedef union union4_t union4_t, *Punion4_t;

union union4_t {
  long l;
  word w[2];
  byte b[4];
};

typedef enum hud_icon_gold_anim_unknown_1_t {
  hud_icon_gold_anim_unknown_1_00 = 0,
} hud_icon_gold_anim_unknown_1_t;

typedef struct comp_collision_t comp_collision_t, *Pcomp_collision_t;

struct comp_collision_t {
  byte set_by_anim_command_fb;
  byte unk2;
  struct int8_vec2_t collision;
};

typedef enum gamepad_t {
  GAMEPAD_NONE = 0,
  GAMEPAD_UP = 1,
  GAMEPAD_DOWN = 2,
  GAMEPAD_DPAD_Y = 3,
  GAMEPAD_LEFT = 4,
  GAMEPAD_RIGHT = 8,
  GAMEPAD_DPAD_X = 12,
  GAMEPAD_DPAD_ANY = 15,
  GAMEPAD_B = 16,
  GAMEPAD_C = 32,
  GAMEPAD_A = 64,
  GAMEPAD_ACCEPT = 96,
  GAMEPAD_START = 128,
  GAMEPAD_CANCEL = 144,
  GAMEPAD_BUTTON_ANY = 240,
} gamepad_t;

typedef struct struct_int_char struct_int_char, *Pstruct_int_char;

struct struct_int_char {
  int i;
  char c;
};

typedef struct vdp_draw_pos_t vdp_draw_pos_t, *Pvdp_draw_pos_t;

struct
    vdp_draw_pos_t { // The position of the electron beam on the screen, cf.
                     // https://segaretro.org/Sega_Mega_Drive/VDP_general_usage#H.2FV_counter
  uint8_t y;
  uint8_t x;
};

typedef struct comp_anim_t comp_anim_t, *Pcomp_anim_t;

struct comp_anim_t {
  byte unk1;
  byte unk2;
  byte frame; // The frame or tile index of the entity's animation
  byte unk4;
};

typedef struct register_d8_a6_t register_d8_a6_t, *Pregister_d8_a6_t;

typedef int register_t;

struct register_d8_a6_t {
  register_t d[8];
  register_t a[6];
};

typedef enum sound_id_t {
  SOUND_ID_OVERTURE = 0, // Main menu theme,
  SOUND_ID_OVER_THE_CLOUDS = 1,
  SOUND_ID_ARABESQUE_COURT_IN_DREAM = 2,
  SOUND_ID_MAIN_THEME = 3,
  SOUND_ID_STREAM_SANCTUARY = 4,
  SOUND_ID_BIRTH_OF_PEPELOGOO = 5,
  SOUND_ID_LAMP_DE_GODJARRE = 6,
  SOUND_ID_LONG_DISTANCE = 7,
  SOUND_ID_LABYRINTH_ON_THE_SKY = 8,
  SOUND_ID_KOOL_DUDE = 9,
  SOUND_ID_PREMONITION = 10,
  SOUND_ID_KINGDOM_OF_RADAPAGNA = 11,
  SOUND_ID_TRY_THE_TRIAL = 12,
  SOUND_ID_VOLCANIC_CAVE = 13,
  SOUND_ID_HEART_OF_ICEGRAVE = 14,
  SOUND_ID_HEAD_BANGER = 15,
  SOUND_ID_MALEVOLENT_DEITY = 16,
  SOUND_ID_FINALE_PART_1 = 17,
  SOUND_ID_A_CRADLE_SONG_OF_PEPELOGOO = 18,
  SOUND_ID_TALES_FROM_MONSTER_WORLD = 19,
  SOUND_ID_JINGLE_1 = 20,
  SOUND_ID_FINALE_PART_2 = 21,
  SOUND_ID_ASCENSION_TO_HEAVEN = 22, // Asha died,
  SOUND_ID_CONQUERS_THE_DUNGEON = 23,
  SOUND_ID_JUMP = 24,
  SOUND_ID_ATTACK = 25, // Also used for the shield at a different pitch,
  SOUND_ID_ROPE_RIDE = 26,
  SOUND_ID_ROPE_FALL = 27,
  SOUND_ID_SLAPPED = 28,
  SOUND_ID_DAMAGE_1 = 29, // Asha hurt,
  SOUND_ID_DAMAGE_2 = 30, // Enemy hurt,
  SOUND_ID_FALL = 31,
  SOUND_ID_LANDING = 32,
  SOUND_ID_SLASH = 33,
  SOUND_ID_CATHEDRAL = 34,
  SOUND_ID_FADE_INTO_DARKSIDE = 35,
  SOUND_ID_REBIRTH = 36,
  SOUND_ID_DOOR = 37,         // Going through a door,
  SOUND_ID_SCN_CHG = 38,      // Scene change,
  SOUND_ID_PEPE_VOICE_1 = 39, // Pepelogoo called,
  SOUND_ID_PEPE_VOICE_2 = 40,
  SOUND_ID_ITEM_EXIST = 41, // Item dropped,
  SOUND_ID_ITEM_GET = 42,   // Item collected,
  SOUND_ID_LIFE = 43,       // Life replenished,
  SOUND_ID_RES_KEY = 44,    // Menu item selected,
  SOUND_ID_RES_BTTN = 45,   // Menu item activated,
  SOUND_ID_JUNGLE_5 = 46,
  SOUND_ID_SPLASH = 47,
  SOUND_ID_EN_DEAD = 48,
  SOUND_ID_SLIP = 49,
  SOUND_ID_TRUE = 50,
  SOUND_ID_FALSE = 51,
  SOUND_ID_COUNT = 52,
  SOUND_ID_SAVE = 53,
  SOUND_ID_LOAD = 54,
  SOUND_ID_FLOW = 55,
  SOUND_ID_DEFENCE = 56,
  SOUND_ID_PEPE_VOICE_3 = 57,
  SOUND_ID_BOX_OPEN = 58,
  SOUND_ID_TREE = 59,
  SOUND_ID_EGG_FALL = 60, // Also Asha Bounces,
  SOUND_ID_EGG_CRACK = 61,
  SOUND_ID_EGG_HATCH = 62,
  SOUND_ID_CRYS_FLASH = 63, // Elixir drop,
  SOUND_ID_TOW_APPEAR = 64,
  SOUND_ID_WARP = 65,
  SOUND_ID_BOMB_USE = 66,
  SOUND_ID_TOW_STOP = 67,
  SOUND_ID_UTSUSEMI = 68,
  SOUND_ID_SCOOP_UP = 69,
  SOUND_ID_EXT_BUCKET = 70,
  SOUND_ID_EXT_BREATH = 71,
  SOUND_ID_PEPE_ENTER = 72,
  SOUND_ID_CARPET = 73,
  SOUND_ID_CRITIC = 74,
  SOUND_ID_EAT_A_NUT = 75,
  SOUND_ID_DEATH_CRY = 76,
  SOUND_ID_DEATH_OF_PEPELOGOO = 77,
  SOUND_ID_SPIRITS = 78,
  SOUND_ID_GET_MEAT = 79,
  SOUND_ID_FX_OFF = 80,
  SOUND_ID_SONG_OFF = 81,
  SOUND_ID_FINALE_3 = 82,
  SOUND_ID_LAST = 83,
  SOUND_ID_F9 = 249,
  SOUND_ID_FA = 250,
  SOUND_ID_PAUSE = 252,
  SOUND_ID_RESUME = 253,
  SOUND_ID_FE = 254,
  SOUND_ID_FF = 255, // Possibly related to Game Over
} sound_id_t;

typedef struct palette_color_iter_t palette_color_iter_t,
    *Ppalette_color_iter_t;

struct palette_color_iter_t {
  int16_t start;
  uint16_t length;
};

typedef enum component_state_b_t {
  COMPONENT_STATE_B_ACTIVE = 1,
  COMPONENT_STATE_B_C0 = 192,
} component_state_b_t;

typedef struct unk1_t unk1_t, *Punk1_t;

struct unk1_t {
  byte a;
  word b;
  byte c;
  byte d;
  byte e;
  byte f;
  byte g;
  word h;
  byte j;
  byte k;
  byte l;
  byte m;
  byte n;
  byte o;
  byte p;
};

typedef struct text_load_glyph_tiles_result_t text_load_glyph_tiles_result_t,
    *Ptext_load_glyph_tiles_result_t;

struct text_load_glyph_tiles_result_t {
  struct glyph_flag_t flags;
  struct tile_1bpp_row_t *tiles_in;
  struct tile_1bpp_row_t *tiles_out;
};

typedef enum palette_fade_type_t {
  PALETTE_FADE_NONE = 0,
  PALETTE_FADE_1 = 1,
  PALETTE_FADE_BLACK_EASE_IN = 2,  // 0x00 to -0x10,
  PALETTE_FADE_BLACK_EASE_OUT = 3, // -0xf1 to 0x01,
  PALETTE_FADE_WHITE_EASE_IN = 4,  // 0x00 to 0x10,
  PALETTE_FADE_WHITE_EASE_OUT = 5, // 0x0f to 0x00
} palette_fade_type_t;

typedef enum anim_item_t { // Values from #01 to #ef are added to the current
                           // animation tick.
  ANIM_RESET_TICK = 0,
  ANIM_INVALID_COMMAND_F0 = 240,
  ANIM_INVALID_COMMAND_F1 = 241,
  ANIM_INVALID_COMMAND_F2 = 242,
  ANIM_INVALID_COMMAND_F3 = 243,
  ANIM_INVALID_COMMAND_F4 = 244,
  ANIM_COMMAND_F5 = 245,
  ANIM_COMMAND_F6 = 246,
  ANIM_COMMAND_F7 = 247,
  ANIM_COMMAND_F8 = 248,
  ANIM_COMMAND_F9 = 249,
  ANIM_COMMAND_FA = 250,
  ANIM_COMMAND_FB = 251,
  ANIM_COMMAND_FC = 252,
  ANIM_COMMAND_FD = 253,
  ANIM_COMMAND_FE = 254,
  ANIM_COMMAND_FF = 255,
} anim_item_t;

typedef struct sized_string_1a_t sized_string_1a_t, *Psized_string_1a_t;

struct sized_string_1a_t {
  uint16_t length;
  char string[26];
};

typedef struct sound_id_word_t sound_id_word_t, *Psound_id_word_t;

struct sound_id_word_t {
  byte unused;
  enum sound_id_t as_word;
};

typedef struct undefined12 undefined12, *Pundefined12;

struct undefined12 {
  undefined4 a;
  undefined4 b;
  undefined4 c;
};

typedef enum hud_icon_gold_anim_unknown_3_t {
  hud_icon_gold_anim_unknown_3_00 = 0,
} hud_icon_gold_anim_unknown_3_t;

typedef enum palette_fade_type_long_t {
  PALETTE_FADE_LONG_NONE = 0,
  PALETTE_FADE_LONG_1 = 1,
  PALETTE_FADE_LONG_BLACK_EASE_IN = 2,  // 0x00 to -0x10,
  PALETTE_FADE_LONG_BLACK_EASE_OUT = 3, // -0xf1 to 0x01,
  PALETTE_FADE_LONG_WHITE_EASE_IN = 4,  // 0x00 to 0x10,
  PALETTE_FADE_LONG_WHITE_EASE_OUT = 5, // 0x0f to 0x00
} palette_fade_type_long_t;

typedef struct sized_string_a_t sized_string_a_t, *Psized_string_a_t;

struct sized_string_a_t {
  word length;
  char string[10];
};

typedef enum entity_id_t { // Only multiples of 4 are valid.
  ENTITY_ID_ASHA = 0,
  ENTITY_ID_PEPELOGOO = 4,
  ENTITY_ID_08 = 8,
  ENTITY_ID_0C = 12,
  ENTITY_ID_F4 = 244,
  ENTITY_ID_F8 = 248,
  ENTITY_ID_FC = 252,
} entity_id_t;

typedef struct value_dst_t value_dst_t, *Pvalue_dst_t;

struct value_dst_t {
  long value;
  undefined *dst;
};

typedef enum item_t {
  ITEM_ASHA_SWORD = 0,
  ITEM_PLAIN_SHIELD = 8,
  ITEM_TRAVELER_ARMOR = 16,
  ITEM_HEALING_MEDICINE = 28,
  ITEM_MAGIC_LAMP = 29,
  ITEM_NONE = 255,
} item_t;

typedef struct ulong_ushort ulong_ushort, *Pulong_ushort;

struct ulong_ushort {
  ulong a;
  ushort b;
};

typedef struct compression_related_a_t compression_related_a_t,
    *Pcompression_related_a_t;

struct compression_related_a_t {
  uint8_t *a0_src;
  uint8_t *a1_dst;
  uint8_t d0b_src_value;
  uint16_t d1w_unused_bits;
  uint16_t d7w;
};

typedef enum entity_state_1_a_t {
  ECS_STATE_1_A_NORMAL = 128,
  ECS_STATE_1_A_GOING_THROUGH_DOORS = 192,
} entity_state_1_a_t;

typedef enum vdp_ctrl_read_t {
  VDP_CTRL_READ_NONE = 0,
  VDP_CTRL_READ_PAL = 1,
  VDP_CTRL_READ_DMA_BUSY = 2,
  VDP_CTRL_READ_IN_H_BLANK = 4,
  VDP_CTRL_READ_IN_V_BLANK = 8,
  VDP_CTRL_READ_ODD_FRAME = 16,
  VDP_CTRL_READ_SPRITE_COLLISION = 32,
  VDP_CTRL_READ_SPRITE_OVERFLOW = 64,
  VDP_CTRL_READ_V_INTERRUPT_HAPPENED = 128,
  VDP_CTRL_READ_FIFO_FULL = 256,
  VDP_CTRL_READ_FIFO_EMPTY = 512,
} vdp_ctrl_read_t;

typedef struct sprite_4_t sprite_4_t, *Psprite_4_t;

struct sprite_4_t { // Fifth byte of a sprite, cf.
                    // https://segaretro.org/Sega_Mega_Drive/Sprites
  bool priority : 1;
  uint8_t palette_line : 2;
  bool v_flip : 1;
  bool h_flip : 1;
};

typedef struct script_name_id_t script_name_id_t, *Pscript_name_id_t;

struct script_name_id_t {
  char type;
  char index;
};

typedef struct sprite_t sprite_t, *Psprite_t;

struct sprite_t {
  uint16_t position_y : 10;
  uint8_t size_x : 2;
  uint8_t size_y : 2;
  uint8_t link : 7;
  bool priority : 1;
  uint8_t palette_id : 2;
  uint8_t flip_y : 1;
  uint8_t flip_x : 1;
  uint16_t tile_id : 11;
  uint16_t position_x : 9;
};

typedef union sound_id_word_union_t sound_id_word_union_t,
    *Psound_id_word_union_t;

union sound_id_word_union_t {
  word as_word;
  enum sound_id_t as_byte;
};

typedef enum palette_id_flag_w_t {
  PALETTE_ID_FLAG_W_NONE = 0,
  PALETTE_ID_FLAG_W_0 = 1,
  PALETTE_ID_FLAG_W_1 = 2,
  PALETTE_ID_FLAG_W_2 = 4,
  PALETTE_ID_FLAG_W_3 = 8,
  PALETTE_ID_FLAG_W_ALL = 15,
} palette_id_flag_w_t;

typedef enum palette_effect_value_t {
  PALETTE_EFFECT_VALUE_SET_DURATION = 4095, // Set if [0x1000,0x1fff],
  PALETTE_EFFECT_VALUE_STOP = 8191,         // Stop if [0x2000,0x2fff],
  PALETTE_EFFECT_VALUE_SET_START = 12288,   // Store if [0x3000,0x3fff],
  PALETTE_EFFECT_VALUE_RESTART = 16384,     // Load If >= 0x4000
} palette_effect_value_t;

typedef struct struct2_t struct2_t, *Pstruct2_t;

struct struct2_t {
  byte a;
  byte b;
};

typedef enum hud_icon_gold_anim_unknown_2_t {
  hud_icon_gold_anim_unknown_2_00 = 0,
} hud_icon_gold_anim_unknown_2_t;

typedef enum vdp_ctrl_read_lower_byte_t { // The lower half of vdp_ctrl_read_t
  VDP_CTRL_READ_LOWER_BYTE_NONE = 0,
  VDP_CTRL_READ_LOWER_BYTE_PAL = 1,
  VDP_CTRL_READ_LOWER_BYTE_DMA_BUSY = 2,
  VDP_CTRL_READ_LOWER_BYTE_IN_H_BLANK = 4,
  VDP_CTRL_READ_LOWER_BYTE_IN_V_BLANK = 8,
  VDP_CTRL_READ_LOWER_BYTE_ODD_FRAME = 16,
  VDP_CTRL_READ_LOWER_BYTE_SPRITE_COLLISION = 32,
  VDP_CTRL_READ_LOWER_BYTE_SPRITE_OVERFLOW = 64,
  VDP_CTRL_READ_LOWER_BYTE_V_INTERRUPT_HAPPENED = 128,
} vdp_ctrl_read_lower_byte_t;

typedef struct VectorsTable VectorsTable, *PVectorsTable;

struct VectorsTable {
  pointer SSP;
  pointer Reset;
  pointer BusErr;
  pointer AdrErr;
  pointer InvOpCode;
  pointer DivBy0;
  pointer Check;
  string *field7_0x1c;
  pointer GPF;
  pointer Trace;
  pointer Reserv0;
  pointer Reserv1;
  pointer Reserv2;
  pointer Reserv3;
  pointer Reserv4;
  pointer BadInt;
  pointer Reserv10;
  pointer Reserv11;
  pointer Reserv12;
  pointer Reserv13;
  pointer Reserv14;
  pointer Reserv15;
  pointer Reserv16;
  pointer Reserv17;
  pointer BadIRQ;
  pointer IRQ1;
  pointer EXT;
  pointer IRQ3;
  pointer HBLANK;
  pointer IRQ5;
  pointer VBLANK;
  pointer IRQ7;
  pointer Trap0;
  pointer Trap1;
  pointer Trap2;
  pointer Trap3;
  pointer Trap4;
  pointer Trap5;
  pointer Trap6;
  pointer Trap7;
  pointer Trap8;
  pointer Trap9;
  pointer Trap10;
  pointer Trap11;
  pointer Trap12;
  pointer Trap13;
  pointer Trap14;
  pointer Trap15;
  pointer Reserv30;
  pointer Reserv31;
  pointer Reserv32;
  pointer Reserv33;
  pointer Reserv34;
  pointer Reserv35;
  pointer Reserv36;
  pointer Reserv37;
  pointer Reserv38;
  pointer Reserv39;
  pointer Reserv3A;
  pointer Reserv3B;
  pointer Reserv3C;
  pointer Reserv3D;
  pointer Reserv3E;
  pointer Reserv3F;
};

typedef enum vdp_ctrl_read_upper_byte_t {
  VDP_CTRL_READ_UPPER_BYTE_NONE = 0,
  VDP_CTRL_READ_UPPER_BYTE_FIFO_FULL = 1,
  VDP_CTRL_READ_UPPER_BYTE_FIFO_EMPTY = 2,
} vdp_ctrl_read_upper_byte_t;
