From f52b27513024eba344e26ddece9759184313e691 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 10 Jan 2026 13:52:53 -0700 Subject: [PATCH] Add initial Kaitai formats to document LEGO Island file formats (#1712) * Add initial Kaitai formats * Update README with installation and command examples Added installation instructions for Kaitai Struct Visualizer and updated ksdump command examples. * Update README.md * Update link to Kaitai Struct documentation * Update installation link for Kaitai Struct Visualizer --- docs/README.md | 55 +++++++++++++++++ docs/history.ksy | 125 +++++++++++++++++++++++++++++++++++++++ docs/players.ksy | 48 +++++++++++++++ docs/samples/History.gsi | Bin 0 -> 184 bytes docs/samples/Players.gsi | Bin 0 -> 44 bytes 5 files changed, 228 insertions(+) create mode 100644 docs/README.md create mode 100644 docs/history.ksy create mode 100644 docs/players.ksy create mode 100755 docs/samples/History.gsi create mode 100755 docs/samples/Players.gsi diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..297f7ce3 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,55 @@ +# LEGO Island File Format Documentation + +This folder contains documentation for LEGO Island's custom binary file formats using [Kaitai Struct](https://kaitai.io/), a declarative language for describing binary data structures. + +## What is Kaitai Struct? + +Kaitai Struct allows you to define binary formats in a YAML-based `.ksy` file, which can then be: +- Compiled into parser libraries for [many programming languages](https://kaitai.io/#quick-start) (C++, Python, JavaScript, etc.) +- Visualized interactively using the [Kaitai Struct Visualizer](https://github.com/kaitai-io/kaitai_struct_visualizer) +- Dumped to human-readable formats using `ksdump` + +image + +## Documented Formats + +| File | Extension | Description | +|------|-----------|-------------| +| [`players.ksy`](/docs/players.ksy) | `.gsi` | Player profile save data (usernames) | +| [`history.ksy`](/docs/history.ksy) | `.gsi` | Score history and high scores | + +## Using the Tools + +### Installation + +See the [Kaitai Struct Visualizer installation instructions](https://github.com/kaitai-io/kaitai_struct_visualizer?tab=readme-ov-file#downloading-and-installing) for setup details. + +### Kaitai Struct Visualizer (ksv) + +The [Kaitai Struct Visualizer](https://github.com/kaitai-io/kaitai_struct_visualizer) (`ksv`) provides an interactive terminal UI for exploring binary files. + +```bash +# View a Players.gsi file +ksv samples/Players.gsi players.ksy + +# View a History.gsi file +ksv samples/History.gsi history.ksy +``` + +### Kaitai Struct Dump (ksdump) + +`ksdump` outputs the parsed structure as JSON or YAML for scripting and inspection. + +```bash +# Dump Players.gsi to JSON +ksdump --format json samples/Players.gsi players.ksy + +# Dump History.gsi to YAML +ksdump --format yaml samples/History.gsi history.ksy +``` + +## Sample Files + +The [`samples/`](/docs/samples/) directory contains example save files for testing: +- `Players.gsi` - Sample player profile data +- `History.gsi` - Sample score history data diff --git a/docs/history.ksy b/docs/history.ksy new file mode 100644 index 00000000..f60bb2af --- /dev/null +++ b/docs/history.ksy @@ -0,0 +1,125 @@ +meta: + id: history + title: Score History Save File + application: LEGO Island + file-extension: gsi + license: CC0-1.0 + endian: le +doc: | + Score history save data for LEGO Island (1997). Stores up to 20 player + score entries, tracking high scores across all missions and characters. + + The file is located at `/History.gsi` where save_path is + typically the game's installation directory. + +seq: + - id: next_player_id + type: s2 + doc: | + The next player ID to be assigned when a new player profile is created. + Increments each time a new player is added, ensuring unique IDs. + - id: count + type: s2 + doc: Number of score entries in the history (0-20 max). + - id: entries + type: score_entry + repeat: expr + repeat-expr: count + doc: Array of score history entries, sorted by total score descending. + +types: + score_entry: + doc: | + A single score history entry containing a player's high scores across + all minigames and characters. Total serialized size is 45 bytes + (2 for index + 43 for score_item data). + seq: + - id: index + type: s2 + doc: Array index of this entry (0 to count-1). Stored redundantly in file. + - id: total_score + type: s2 + doc: Sum of all individual high scores across all missions and actors. + - id: scores + type: mission_scores + doc: High scores organized by mission type, each containing scores per actor. + - id: name + type: username + doc: The player's username associated with these scores. + - id: player_id + type: s2 + doc: Unique player identifier matching the player's profile. + + mission_scores: + doc: | + High scores for all 5 missions. Each mission contains scores for all + 5 playable actors. + seq: + - id: car_race + type: actor_scores + doc: Car Race mission high scores. + - id: jetski_race + type: actor_scores + doc: Jetski Race mission high scores. + - id: pizza_delivery + type: actor_scores + doc: Pizza Delivery mission high scores. + - id: tow_track + type: actor_scores + doc: Tow Track mission high scores. + - id: ambulance + type: actor_scores + doc: Ambulance mission high scores. + + actor_scores: + doc: | + High scores for a single mission across all 5 playable actors. + seq: + - id: pepper + type: u1 + enum: score_color + doc: High score for Pepper. + - id: mama + type: u1 + enum: score_color + doc: High score for Mama. + - id: papa + type: u1 + enum: score_color + doc: High score for Papa. + - id: nick + type: u1 + enum: score_color + doc: High score for Nick. + - id: laura + type: u1 + enum: score_color + doc: High score for Laura. + + username: + doc: | + A player username consisting of up to 7 letters. Each letter is stored + as a signed 16-bit index. The struct is always 14 bytes (0x0e). + seq: + - id: letters + type: s2 + repeat: expr + repeat-expr: 7 + doc: | + Letter indices for the username characters: + - 0-25: Standard alphabet (0=A, 1=B, ..., 25=Z) + - 29: International ä, å, or ñ (language-dependent) + - 30: International ö or æ (language-dependent) + - 31: International ß or ø (language-dependent) + - 32: International ü + - -1 (0xFFFF): Empty/unused position + + Unused positions are filled with -1. A name shorter than 7 + characters will have trailing -1 values. + +enums: + score_color: + 0: grey + 1: yellow + 2: blue + 3: red diff --git a/docs/players.ksy b/docs/players.ksy new file mode 100644 index 00000000..84136ed2 --- /dev/null +++ b/docs/players.ksy @@ -0,0 +1,48 @@ +meta: + id: players + title: Players Save File + application: LEGO Island + file-extension: gsi + license: CC0-1.0 + endian: le +doc: | + Player profile save data for LEGO Island (1997). Stores up to 9 player + profiles, each identified by a 7-character username. Usernames are stored + as letter indices rather than ASCII characters. + + The file is located at `/Players.gsi` where save_path is + typically the game's installation directory. + +seq: + - id: count + type: s2 + doc: | + Number of saved player profiles. The game supports a maximum of 9 + players; when a 10th player is added, the oldest profile is deleted. + - id: entries + type: username + repeat: expr + repeat-expr: count + doc: Array of player username entries, ordered by most recently played. + +types: + username: + doc: | + A player username consisting of up to 7 letters. Each letter is stored + as a signed 16-bit index. The struct is always 14 bytes (0x0e). + seq: + - id: letters + type: s2 + repeat: expr + repeat-expr: 7 + doc: | + Letter indices for the username characters: + - 0-25: Standard alphabet (0=A, 1=B, ..., 25=Z) + - 29: International ä, å, or ñ (language-dependent) + - 30: International ö or æ (language-dependent) + - 31: International ß or ø (language-dependent) + - 32: International ü + - -1 (0xFFFF): Empty/unused position + + Unused positions are filled with -1. A name shorter than 7 + characters will have trailing -1 values. diff --git a/docs/samples/History.gsi b/docs/samples/History.gsi new file mode 100755 index 0000000000000000000000000000000000000000..f253055f399b34cf63954bdf1a0d998cf5d8ae18 GIT binary patch literal 184 zcmaKmOAf#w2n9zm?XH_9z5h-10ktMB%8PslqS1guPiCKsGMuTK>M|%vy+CX%_+-lA WLj8l$_?8|n9NuoNtDenIWULH9zzVYf literal 0 HcmV?d00001 diff --git a/docs/samples/Players.gsi b/docs/samples/Players.gsi new file mode 100755 index 0000000000000000000000000000000000000000..21c08e1d044b16a14b2be41ebd4771d38f3f1a3e GIT binary patch literal 44 gcmZQ(U`Bxq3``8dKq$t*$MF9@jK|I($iTt?04lozrvLx| literal 0 HcmV?d00001