ECL format


typedef struct {
    uint32_t sub_count;
    uint32_t main_offset;
    uint32_t padding[2]; // Always 0.
    uint32_t subs_offsets[sub_count];
} thecl06_header_t;


Starting at 0x10.
They describe the appearance and comportment of a certain type of enemy

Ends with frame_num = 0xffffffff and opcode = 0xffff, for a size of 0xc (the minimum) and default masks.

Parameters are dependants of the opcode.

typedef struct {
    uint32_t frame_num;
    uint16_t opcode;
    uint16_t size; // Never less than 0xc.
    uint16_t rank_mask; // the first byte is always 0xff, and the second the mask of the ranks to which the instruction applies, 1 for easy, 8 for lunatic.
    uint16_t param_mask; // Unused in EoSD, always 255. It is used in other Touhou games to indicate whether an argument is an "address" or not, though.
    unsigned char params[size-0xc];
} thecl06_sub_t;


Each instruction contains its size (which is always greater than 8, or else the game crashs). The only values encountered in the game are 0x1c, 0x10 and 8, but values of 0x38 work (skip the next instruction).
The frame_num must greater than or equal to the previous, or the instruction will be skipped.
The parsing ends when frame_num is 0xffff.

typedef struct {
    uint16_t frame_num;
    uint16_t unused1;
    uint16_t unused2;
    uint16_t size;
    uint8_t arguments[size-8];
} thecl_main_instr_t;

Most present instruction, that pops an enemy.

typedef struct {
    uint16_t time;
    uint16_t sub; // Sub function to use.
    uint16_t type;
    uint16_t size; // Really the size of the instruction. NOT ignored by the game.
    float x;
    float y;
    float z; // Unused, always 0.
    int16_t life; // From 0 to 0x7fff; lower than 0 is equal to 1.
    int16_t object_dropped; // Between -2 and 2.
			    // 0 to 6: corresponding bonus
			    // -1: random
			    // other: nothing
    uint32_t die_score;
} thecl_enemy_t;

Unknown, used only at the end of each stage.

typedef struct {
    uint16_t time;
    uint16_t sub; // always 0.
    uint16_t type; // always 0xa.
    uint16_t size;
    float unused1; // always 0.
    float unused2; // always 0.
} thecl_other1_t;

Unknown, used only at the end of each stage. Always in group of 1, 2 or 3, with a sequence of (9), (8, 9) or (0xc, 8, 9).

typedef struct {
    uint16_t time;
    uint16_t sub; // always 0.
    uint16_t type;
    uint16_t size;
} thecl_other2_t;


Used in the game are: 0, 2, 4, 6 for the enemies (0x1c-long), 0xa for the 0x10-long instruction, and 8, 9 and 0xc for the 8-long one. Type might be quite a misnomer since those are pretty much flags.

  1. normal enemy
  2. normal enemy
  3. mirrored enemy
  4. mirrored enemy
  5. normal enemy (random placement)
  6. normal enemy (random placement)
  7. mirrored enemy (random placement)
  8. mirrored enemy (random placement)
  9. starts the msg (which?)
  10. nothing?
  11. crash!?
  12. nothing?
  13. nothing?
  14. etc.