Import Kaitai Struct files into utils/kaitai/

Originally maintained at https://github.com/principia-game/kaitai
This commit is contained in:
ROllerozxa 2026-06-02 16:52:24 +02:00
commit a9408d30ca
6 changed files with 428 additions and 0 deletions

View file

@ -15,3 +15,6 @@ Most of these programs rely on source files from the main Principia codebase and
- `lvledit`: Edit metadata of Principia level files
- `package-creator`: Create a Principia package file from JSON data
- `progress-get`: Get leaderboard score for a given level from a data.bin file
## Kaitai Struct files
The `kaitai` directory contains Kaitai Struct files that describe some of Principia's file formats.

6
utils/kaitai/README.md Normal file
View file

@ -0,0 +1,6 @@
# Principia Kaitai files
This directory contains [Kaitai Struct](https://kaitai.io/) files that describe some of Principia's file formats.
In addition to being able to load them into the [Kaitai IDE](https://ide.kaitai.io/) to inspect files, Kaitai Struct files can be used to generate parsers in various programming languages.
Do note that these files were largely written through reverse engineering efforts prior to the game's open source release, so naming conventions may be inconsistent with how things are named in the actual codebase.

55
utils/kaitai/featuredlist.ksy Executable file
View file

@ -0,0 +1,55 @@
meta:
id: featuredlist
endian: le
seq:
- id: featured_level_count
type: u4
- id: featured_levels
type: featured_level
repeat: expr
repeat-expr: featured_level_count
- id: contest_stuff
type: u4
doc: Intended for telling the count of contests to show in the create dialog, but this is unused and mostly not usable, just keep it at zero.
- id: gettingstarted_list_count
type: u4
- id: gettingstarted_list
type: gettingstarted
repeat: expr
repeat-expr: gettingstarted_list_count
types:
featured_level:
seq:
- id: id
type: u4
- id: name_size
type: u4
- id: name
type: str
size: name_size
encoding: UTF-8
- id: author_size
type: u4
- id: author
type: str
size: author_size
encoding: UTF-8
- id: jpegstream_size
type: u4
- id: jpegstream
size: jpegstream_size
gettingstarted:
seq:
- id: name_size
type: u4
- id: name
type: str
size: name_size
encoding: UTF-8
- id: link_size
type: u4
- id: link
type: str
size: link_size
encoding: UTF-8

223
utils/kaitai/plvl.ksy Executable file
View file

@ -0,0 +1,223 @@
meta:
id: plvl
file-extension: plvl
endian: le
seq:
- id: version
type: u1
- id: type
type: u1
enum: level_type
- id: community_id
type: u4
- id: autosave_id
type: u4
if: version >= 28
- id: revision
type: u4
- id: parent_id
type: u4
doc: Level ID of parent level (for derivatives)
- id: name_size
type: u1
- id: descr_size
type: u2
- id: allow_derivatives
type: u1
- id: visibility
type: u1
if: version >= 3
- id: parent_revision
type: u4
if: version >= 7
- id: pause_on_finish
type: u1
if: version >= 7
- id: show_score
type: u1
if: version >= 7
- id: bg
type: u1
- id: bg_color
type: u4
doc: Assumedly RGBA, needs testing though
if: version >= 28
- id: size_x
type: u2
- id: size_y
type: u2
- id: size_x_2
type: u2
if: version >= 12
- id: size_y_2
type: u2
if: version >= 12
- id: velocity_iterations
type: u1
- id: position_iterations
type: u1
- id: final_score
type: u4
- id: sandbox_cam_x
type: f4
- id: sandbox_cam_y
type: f4
- id: sandbox_cam_zoom
type: f4
- id: gravity_x
type: f4
if: version >= 3
- id: gravity_y
type: f4
if: version >= 3
- id: bounds_x1
type: f4
if: version >= 13
- id: bounds_y1
type: f4
if: version >= 13
- id: bounds_x2
type: f4
if: version >= 13
- id: bounds_y2
type: f4
if: version >= 13
- id: flags
type: u8
if: version >= 9
doc: TODO
- id: prismatic_tolerance
type: f4
if: version >= 26
- id: pivot_tolerance
type: f4
if: version >= 26
- id: seed
type: u8
if: version >= 28
- id: adventure_id
type: u4
if: version >= 28
- id: linear_damping
type: f4
if: version >= 28
- id: angular_damping
type: f4
if: version >= 28
- id: joint_friction
type: f4
if: version >= 28
- id: body_absorb_time
type: f4
if: version >= 28
- id: respawn_cooldown
type: f4
if: version >= 28
- id: compression_buf_size
type: u8
if: version >= 28
- id: name
type: str
size: name_size
encoding: UTF-8
- id: level_thumbnail
size: 128*128
if: version >= 6
doc: >
A 128x128 8-bit grayscale bitmap, which is a screenshot of the level where it last was saved.
It is used for package thumbnails.
- id: descr
type: str
size: descr_size
encoding: UTF-8
- id: group_count_pre28
type: u2
if: version < 28
- id: entity_count_pre28
type: u2
if: version < 28
- id: connection_count_pre28
type: u2
if: version < 28
- id: cable_count_pre28
type: u2
if: version < 28
- id: group_count
type: u4
if: version >= 28
- id: entity_count
type: u4
if: version >= 28
- id: connection_count
type: u4
if: version >= 28
- id: cable_count
type: u4
if: version >= 28
- id: chunk_count
type: u4
if: version >= 28
- id: state_size
type: u4
if: version >= 28
- id: gencount
type: u4
if: version >= 28
- id: level_buffer
size-eos: true
doc: >
zlib compressed level buffer data.
In earlier level versions (TODO: what versions?), the level buffer is uncompressed.
enums:
level_version:
0: any
1: version_beta_1
2: version_beta_2
3: version_beta_3
4: version_beta_4
5: version_beta_5
6: version_beta_6
7: version_beta_7
8: version_beta_8
9: version_beta_9
10: version_beta_10
11: version_beta_11
12: version_beta_12
13: version_beta_13
14: version_beta_14
15: version_1_0
16: version_1_1_6
17: version_1_1_7
18: version_1_2
19: version_1_2_1
20: version_1_2_2
21: version_1_2_3
22: version_1_2_4
23: version_1_3_0_1
24: version_1_3_0_2
25: version_1_3_0_3
26: version_1_4
27: version_1_4_0_2
28: version_1_5
29: version_1_5_1
level_type:
0: puzzle
1: adventure
2: custom

109
utils/kaitai/pobj.ksy Executable file
View file

@ -0,0 +1,109 @@
meta:
id: pobj
file-extension: pobj
endian: le
seq:
- id: version
type: u1
- id: type
type: u1
enum: level_type
- id: name_size
type: u1
- id: bounds_x1
type: f4
if: version >= 13
- id: bounds_y1
type: f4
if: version >= 13
- id: bounds_x2
type: f4
if: version >= 13
- id: bounds_y2
type: f4
if: version >= 13
- id: name
type: str
size: name_size
encoding: UTF-8
- id: group_count_pre28
type: u2
if: version < 28
- id: entity_count_pre28
type: u2
if: version < 28
- id: connection_count_pre28
type: u2
if: version < 28
- id: cable_count_pre28
type: u2
if: version < 28
- id: group_count
type: u4
if: version >= 28
- id: entity_count
type: u4
if: version >= 28
- id: connection_count
type: u4
if: version >= 28
- id: cable_count
type: u4
if: version >= 28
- id: chunk_count
type: u4
if: version >= 28
- id: state_size
type: u4
if: version >= 28
- id: gencount
type: u4
if: version >= 28
- id: level_buffer
size-eos: true
doc: >
zlib compressed level buffer data.
In earlier level versions (TODO: what versions?), the level buffer is uncompressed.
enums:
level_version:
0: any
1: version_beta_1
2: version_beta_2
3: version_beta_3
4: version_beta_4
5: version_beta_5
6: version_beta_6
7: version_beta_7
8: version_beta_8
9: version_beta_9
10: version_beta_10
11: version_beta_11
12: version_beta_12
13: version_beta_13
14: version_beta_14
15: version_1_0
16: version_1_1_6
17: version_1_1_7
18: version_1_2
19: version_1_2_1
20: version_1_2_2
21: version_1_2_3
22: version_1_2_4
23: version_1_3_0_1
24: version_1_3_0_2
25: version_1_3_0_3
26: version_1_4
27: version_1_4_0_2
28: version_1_5
29: version_1_5_1
level_type:
0: puzzle
1: adventure
2: custom
100: partial

32
utils/kaitai/ppkg.ksy Executable file
View file

@ -0,0 +1,32 @@
meta:
id: ppkg
file-extension: ppkg
endian: le
seq:
- id: version
type: u1
- id: community_id
type: u4
if: version >= 2
- id: name
type: str
size: 0xFF
encoding: UTF-8
- id: levels_unlocked
type: u1
doc: The amount of incomplete levels that are available at a time. Default is 2.
if: version >= 3
- id: first_is_menu
type: u1
doc: When 1, Principia automatically plays the first level in the package. On level completion, you go back to this first level. Can be used for a custom level selection level.
if: version >= 1
- id: return_on_finish
type: u1
doc: Return to level select on level finish
if: version >= 1
- id: levels
type: u1
- id: level_id
type: u4
repeat: expr
repeat-expr: levels