-
Notifications
You must be signed in to change notification settings - Fork 0
Format Description
AnimalWell.sav
is a monolithic file containing "global" state info
(figurines, etc), individual save slots, and game options all wrapped up into
one. It has a fixed size of 479,360 bytes (at least at time of writing), so any
given bit of information can be hardcoded with an index, if you're looking to
look something up.
Note that the best source of information about the save file are the hex editor patterns out in the main area of the github repo. The most-canonical version is likely to be the 010 Editor Template, but the ImHex Pattern should be good as well.
This document will strive to be reasonably complete, though, and and offer some more in-depth documentation about the various bits of data. Some information in here might be useful for someone looking to develop a tool to alter the data.
The first u32 of the file is a version field – was 2 at one point during pre-release, and as of writing is 9. Probably worth checking this if you're writing any tools.
The next u32 (at 0x04
) holds the achievements that have been earned. It's
not known if merely setting these values in the save will cause the
achievements to be applied to your Steam account. The bitfield is structured
like so:
-
0x000001
- (unused? Marked as "Platinum" on the 010 Template) -
0x000002
- EXPLORER (Find the map) -
0x000004
- SECRET EGG (Find a secret egg) -
0x000008
- EGG ENJOYER (Find 8 secret eggs) -
0x000010
- EGG HOBBYIST (Find 16 secret eggs) -
0x000020
- EGG LORD (Find 32 secret eggs) -
0x000040
- EGG WELL (Find all secret eggs) -
0x000080
- SECRET RABBIT (Find a secret rabbit) -
0x000100
- CHAMELEON (Find the V. flame) -
0x000200
- GHOST (Find the P. flame) -
0x000400
- SEAHORSE (Find the B. flame) -
0x000800
- OSTRICH (Find the G. flame) -
0x001000
- CANDLE BRIGHT (Light all candles) -
0x002000
- MANTICORE (Release the Manticore) -
0x004000
- SNEAK (Sneak up on a squirrel) -
0x008000
- GOOD ENDING (Get crushed by a chinchilla) -
0x010000
- BACK AND FORTH FOREVER (Find a new way to get around) -
0x020000
- BUBBLE ECSTASY (Pop 1000 bubbles) -
0x040000
- TRAVEL FLUTE (Find another way to get around) -
0x080000
- WALK THE DOG (Find a different way to get around) -
0x100000
- EXIT (Leave the well)
The next u32 (at 0x08
) is the "Frame Seed." This is a counter which starts
when the game is booted and ends when the last flame disappears in the intro,
and is presumably used in various RNG seeds throughout the game. Probably the
most noticeable effect is that this value determines which Bunny Mural segment
will be shown to the player. That will be the Frame Seed modulo 50. So,
changing this value 50 times should let you see all segments in a singleplayer
session.
The next u8 (at 0xC
) is the last-active save slot (0, 1, or 2), used by the
main menu "continue" option.
The next u8 (at 0xD
) is an XOR-based checksum of the entire file. If the
checksum doesn't match, the game will spawn a Manticore friend to help you play
with your internal organs more efficiently. Fortunately it's simple to compute:
simply start with 0, and walk through the file XORing each byte into the
previous result (making sure to skip any existing checksum byte in the file).
Code examples for fixing the checksum:
- Standalone Python script to fix the checksum
- 010 Editor Hash Calculation
- ImHex Hash Calculation
- animalwellsave calculation
The next u8 (at 0xE
) is used during the game runtime, to indicate whether an
invalid hash was seen. It's not actually used from the savefile.
The next u32 (at 0x10
) is a bitfield containing global unlocks, including the
various figurines in the game:
-
0x000001
- Stopwatch -
0x000002
- Pedometer -
0x000004
- Pink Phone -
0x000008
- Souvenir Cup -
0x000010
- Origami Figurines -
0x000020
- Rabbit Figurine (Two Rabbits) -
0x000040
- Owl Figurine -
0x000080
- Cat Figurine -
0x000100
- Fish Figurine -
0x000200
- Donkey Figurine -
0x000400
- "DecoRabbit" Figurine -
0x000800
- mama cha -
0x001000
- Giraffe Figurine -
0x002000
- Incense Burner -
0x004000
- Peacock Figurine -
0x008000
- Otter Figurine -
0x010000
- Duck Figurine -
0x020000
- (unused) -
0x040000
- "PedometerWChest" (not sure what this one means) -
0x080000
- (unused)
The rest of the header is either unknown or padding.
Each save slot has a static offset in the file, and each slot is structured identically. The offsets are:
-
0x00018
- Slot 1 -
0x27028
- Slot 2 -
0x4E038
- Slot 3
Each slot is exactly 159,760 bytes. The game options start immediately after, at 0x75048
.
NOTE: When I mention any file indexes from here on out in the "Slot Data" section, they'll be relative to the save slot. So if I say something's at 0x108
, that means that for slot 1 it lives at 0x120
, for slot 2 it lives at 0x27130
, etc.
- Load Screen timestamp:
0x0
from the slot start- Two bytes for the year, and then one each for month, day, hour, minute, and second.
- Step Count: u32 at
0x108
from the slot start - Total Firecrackers Picked Up: u16 at
0x1A2
from the slot start - Total Bubbles Popped: u16 at
0x1A4
from the slot start - Times saved: u16 at
0x1A8
from the slot start - Keys in inventory: u8 at
0x1B1
from the slot start - Matches in inventory: u8 at
0x1B2
from the slot start - Firecrackers in inventory: u8 at
0x1B3
from the slot start- Note that merely adding firecrackers to your inventory will not allow you to use firecrackers as an item; you will need to unlock them via the Equipment bitfield as well.
- Hits Taken: u16 at
0x1E2
from the slot start - Total Deaths: u16 at
0x1E4
from the slot start- The skulls in the B.B. Wand / Souvenir Cup / Pink Phone / Smiley Code / Skull room dynamically change depending on this value
- Berries Eaten While Full: u16 at
0x26FFA
from the slot start- Resets when hit, or when the player eats a blue berry
- Nuts Stolen from Squirrels: u8 at
0x1AE
from the slot start. This is related to one of the unicode-message hints.
Health (number of hearts) is stored as a u8 at 0x1B4
from the slot start.
Any health above the player's current "base" health will show up as temporary
blue hearts.
Gold hearts can be acquired from the Groundhog if the system
clock is set to Groundhog Day (February 2), and the number of gold hearts is
stored as a u8 at 0x1B5
from the slot start.
The game also keeps track of the last year in which a gold heart was
redeemed from the groundhog. This value is stored as a u16 at 0x1B6
from the slot start.
Time in the game is measured in "ticks," and stored as a u32. The game runs at 60fps, so the unit is not milliseconds. Don't try to just plug it into a usual date-handling library without accounting for that first!
There are technically two fields for time spent in game. The first is stored
at 0x1BC
from the start of the slot, and describes only the in-game tick
count, discounting any paused time. This doesn't seem to be used for
anything obvious to the player. The second value, at 0x1C0
from the
start of the save slot, also includes time spent in pause menus, and this is
what the game uses for the speedrunning figurines, and what gets shown on
the "load game" screen.
The player's spawnpoint is stored as a pair of u32 values, at 0x1D4
from the
start of the slot, with the X value first, and Y value second. Note that
the upper-left room on the map is coordinate (2, 4). If there is a phone in
the room specified, the player will spawn next to the phone -- otherwise,
they will spawn in the most upper-left corner available. (Note that technically
the player will spawn at "Tile ID 16," for folks who have been diving into
map editing. That tile tends to be placed next to the phone, but it can
technically be moved around anywhere, or even added to other rooms with the
proper tools, though that's outside the remit of the save format.)
Spawning outside the map boundaries just gives you a featureless black screen and an inability to do anything but access the Esc pause menu, alas.
Crank data is stored at 0x8
from the slot start, as a list of 23 u16 values.
The min/max values haven't yet been catalogued, but you can see the hex editor
templates for the specific room mappings for all 23. The puzzle-specific cranks
are listed here, though:
- Indexes 7 and 8 are for the water reservoir puzzle at (7, 11)
- One "solved" state for these would be 464, 64624
- Indexes 13, 14, and 15 are for the water reservoir puzzle at (4, 15)
- One "solved" state for these would be 63840, 1584, 32
- Indexes 16 and 17 are for the seahorse boss reservoir puzzle at (2, 17)
- This one doesn't have a fully-solved state since solving the puzzle requires moving them around to make use of the seahorse
- Indexes 19, 20, and 21 are for the levers at the sine wave puzzle at (15, 17)
- One "solved" state for these would be 40, 168, 140
Chest-opening status is encoded as a 128-bit value starting at 0x120
from
the start of the slot. These have not been fully mapped yet, but known
room coordinates can be seen in the hex editor templates. It looks like
only the first 102 bits are used in this field.
There's also a separate bitfield to store the chest status for chests found
in Layer 1 (which is Collector's Edition Temple). There's only the one
chest (which holds the Two Rabbits Figurine), but it's a single byte at
0x1AF
from the start of the slot.
There are five categories of openable doors/walls in the game:
- "Regular" doors which are opened via button presses, water reservoir puzzles, or other environmental puzzles.
- "Unlockable" doors which are opened using the "generic" keys you can store in your inventory.
- Moveable walls which are stored in the same kind of structure as the Unlockable Doors
- Egg Chamber Doors
- Other "special" doors like the House, Office, and Closet doors, whose states are actually controlled via "quest" flags, rather than a dedicated door structure.
The first category of doors are the ones opened by puzzles, be they buttons,
water reservoirs, or other such things. These are stored in a 128-bit
bitfield starting at 0x130
from the start of the slot data. These haven't
been entirely mapped out yet, but you can get many room mappings from the
hex editor patterns. It looks like only the first 94 bits are used in this
field.
Note that the door state is completely independent from the button/puzzle states. You can toggle the doors to be open without having any of the buttons pressed down, and the doors will stay open.
Unlockable Doors (of the sort which are unlocked via "generic" inventory keys)
and moveable walls are stored using very similar data structures in the game,
which the hex editor patterns call TileID
. Each TileID
structure consists
of:
- Room Y coordinate: u8
- Room X coordinate: u8
- Tile Y coordinate: u8
- Tile X coordinate: u8 (but only the bottom six bits)
- Map Layer: The top two bits of the Tile X coordinate
Note that the data stores the Y coordinates first, instead of X.
In practice, all known instances of TileID
structures in the game have used
map layer 0, but the engine does check for those top two bits, specifically
looking for layer 1.
Additionally, the game stores the "next index" for the array, used by the engine to know where to write the next bit of data, but this index is stored rather far away from the arrays themselves, and uses a different byte width between the Doors and Walls arrays.
Unlockable Doors are stored starting at 0x88
from the slot start, and the
"next index" is stored as a u16 at 0x1AA
from the slot start. There
are 16 TileID entries available. There are only six "valid" lockable door
entries in the game, which are listed here with coordinates in the more-normal
x, y
order, rather than the y, x
order they are stored in:
- Room (7, 4), Tile (9, 5), Layer 0
- Room (15, 8), Tile (38, 6), Layer 0
- Room (16, 10), Tile (4, 5), Layer 0
- Room (14, 13), Tile (6, 16), Layer 0
- Room (14, 15), Tile (27, 6), Layer 0
- Room (14, 15), Tile (32, 6), Layer 0
Moveable Walls are stored starting at 0xC8
from the slot start, and the
"next index" is stored as a u8 at 0x1B8
from the slot start. There are
16 TileID entries available. Interestingly, there are technically 17
moveable walls in the game (three of which are only available via cheating),
and the game's bounds checks for this data structure are not good.
Triggering the 17th wall opening will cause the engine to repeatedly
increment the "next index" and write the new value over a large chunk of
savegame data. As of 2024-06-04, that has not yet been fixed.
The 14 "valid" moveable wall entries are:
- Room (2, 5), Tile (2, 1), Layer 0
- Room (15, 5), Tile (6, 3), Layer 0
- Room (6, 6), Tile (16, 14), Layer 0
- Room (7, 6), Tile (16, 1), Layer 0
- Room (7, 6), Tile (5, 14), Layer 0
- Room (13, 7), Tile (29, 1), Layer 0
- Room (10, 8), Tile (16, 17), Layer 0
- Room (2, 9), Tile (1, 6), Layer 0
- Room (9, 10), Tile (39, 6), Layer 0
- Room (8, 11), Tile (33, 19), Layer 0
- Room (13, 11), Tile (39, 17), Layer 0
- Room (6, 13), Tile (36, 7), Layer 0
- Room (2, 19), Tile (9, 7), Layer 0
- Room (2, 19), Tile (31, 7), Layer 0
The 3 "illegal" entries which could potentially fill up the array and cause an overflow if not removed, are:
- Room (12, 4), Tile (29, 4), Layer 0
- Room (3, 7), Tile (5, 3), Layer 0
- Room (13, 13), Tile (11, 8), Layer 0
The four doors in the egg chamber get their own 8-bit field at 0x1B9
from the start of the slot data. These doors will automatically open
when you have the requisite number of eggs, but they can also be set
to open via this bitfield. The first four bits control the doors,
in order -- the other four are unused (as far as we know).
There are four colors of buttons in the game which are stored in the save data:
- Yellow buttons stay pressed down when pressed once
- Purple buttons will pop back up without constant pressure (until all buttons in the relevant puzzle have been pushed down at the same time, at which time they'll stay down)
- Green buttons control fans, instead of doors
- Pink buttons control moveable walls, instead of doors
The button states are technically independent of the doors/walls that they're associated with, but if you set the correct buttons to be pressed down, the associated door will open up automatically when you next enter the room (even the ones controlled by purple buttons). Not all of these have been exhaustively mapped, but you can get room mappings for many by looking at the hex editor patterns.
These are all stored in bitfields, and grouped by their colors.
- Yellow buttons are a 192-bit field starting at
0x140
from the start of the slot, and seem to use 134 of those bits.- Additionally, a separate bitfield to store the state of yellow buttons
in Layer 2 (Space / Bunny Island) can be found as a single byte at
0x1B0
from the start of the slot. There's only the four teleporation torus buttons which get stored there.
- Additionally, a separate bitfield to store the state of yellow buttons
in Layer 2 (Space / Bunny Island) can be found as a single byte at
- Purple buttons are a 64-bit field starting at
0x160
from the start of the slot, and seem to use 27 of those bits. - Green buttons are a 64-bit field starting at
0x168
from the start of the slot, and seem to use just 7 of those bits. - Pink buttons are a 16-bit field starting at
0x1AC
from the start of the slot, and ten of those are used by the game. See the section on moveable walls for some caveats about hitting all of these, since the moveable-wall section can overflow and corrupt saves!-
0x001
- Illegal Bunny 1 -
0x002
- Spike Bunny -
0x004
- Floor is Lava Bunny -
0x008
- Illegal Bunny 2 -
0x010
- Map Number Bunny -
0x020
- Elevator Dog Wheel -
0x040
- Chinchilla Bunny -
0x080
- Bulb Bunny -
0x100
- Illegal Bunny 3 -
0x200
- Lower Portal Nexus
-
The fill levels for the water reservoir puzzles are stored at 0x10C
from the
slot start as an array of 16 u8 values. The values are 0 when empty and 80
(decimal) when filled.
Even though there is room for 16 of them, there are only five in the game, stored in this order:
- Room (7, 11)
- Room (5, 15)
- Three in Room (2,17) *(ordered left to right)
Fruit only respawns in the game when your character dies, so the savegame
keeps track of exactly which fruit has been picked. This is done via a
128-bit field starting at 0x170
from the start of the slot data. Fruits
are stored in the xy room order => yx tile order. Be aware that they are
filed under xy_id room coordinates in the template. 115 of the bits are
in use, covering all in-game fruit: 80 pink, 31 blue, 4 large blue fruit.
Some fruit names are missing from the template at the time of writing but
they have all been identified.
Like fruit, firecrackers only respawn in the game when your character
dies, so the savegame keeps track of those, too. This is done via a
64-bit field starting at 0x180
from the start of the slot data. These
have not been fully mapped, but you can get many room mappings from the
hex editor patterns. All 64 bits are used.
The candles which the player has lit are stored in a u16 bitfield at
0x1E0
from the start of the slot. See the hex editor template for
room mappings. The first 9 bits of the field are used for the 9
candles in the game.
Detonators and the explosive charges they set off are technically stored in two separate bitfields in the game data. Setting them to enabled will result in the appropriate wall-destroying effect in game, but clearing out the fields will not recover destroyed walls; that would have to be done via the destruction map, instead.
The explosive statuses are stored in a 32-bit field starting at 0x190
from the start of the slot data. Only 10 bits are actually used in
there. See the hex editor patterns for room mappings.
The detonator statuses are stored in a 32-bit field starting at 0x194
from the start of the slot data. Only 9 bits are actually used in
there. See the hex editor patterns for room mappings.
Frightened ghosts will respawn on player death (unless a candle has
been lit in their room), and this is stored in a u16 bitfield at
0x1E6
from the start of the slot. 11 of the bits are used.
- Ghost at Room (08,06)
- Ghost at Room (04,07)
- Ghost at Room (06,07)
- Ghost at Room (06,09)
- Ghost at Room (15,09) (top)
- Ghost at Room (15,09) (left)
- Ghost at Room (15,09) (right)
- Ghost at Room (05,13)
- Ghost at Room (10,13)
- Ghost at Room (16,13)
- Ghost at Room (07,14)
Frightened-squirrel state is stored as a 16-bit field at 0x19C
from
the start of the slot data. See the hex editor pattern for specific
room mappings. Only 13 of the bits are actually used.
The 16-bit bitfield which controls which cat cages are open, and whether
the Wheel cage is open (in Mother Lynx's lair) is at 0x19E
from the
start of the slot data. There are only six bits actually used in
the field:
-
0x01
: Caged Cat 1 at Room (16,18) -
0x02
: Caged Cat 2 at Room (16,18) -
0x04
: Caged Cat 3 at Room (16,18) -
0x08
: Caged Cat 1 at Room (14,19) -
0x10
: Caged Cat 2 at Room (14,19) -
0x20
: Wheel Cage
The state of the game's elevators and moving platforms is stored via
a variety of structures. First, at 0x3A8
from the start of the slot
data, there are 8 pairs of four-byte floats:
- First, the elevator position
- Second, the elevator speed
(The specifics of what the specific values mean hasn't really been documented.)
Then, at 0x3E8
from the start of the slot, there's a u8 bitfield to
determine the currently-selected direction of the variable-direction
elevators. The known values:
-
0x01
- Blue Rat (0 down, 1 up) -
0x02
- Red Rat (0 right, 1 left) -
0x04
- Ostrich (0 right, 1 left) -
0x08
- Dog (0 down, 1 up)
Then, finally, at 0x3E9
from the slot start, there's another u8
bitfield which defines which elevators are inactive. A 0
in
this field indicates that the elevator is moving as per usual,
and a 1
indicates that it's been stopped. These have not really
been mapped out much yet, but the known values are:
-
0x001
- Elevator1 -
0x002
- Elevator2 -
0x004
- Wheel Ostrich Elevator (gets disabled when the Wheel Ostrich is freed) -
0x008
- Elevator4 -
0x010
- Elevator5 (Disabled from game start) -
0x020
- Elevator6 (Disabled from game start) -
0x040
- Elevator7 (Disabled from game start) -
0x080
- Elevator8
The ones disabled from the game start are likely to be the ones which only move when using the Wheel equipment.
The state of the destructible harmful environmental hazards like stalactites, stalagmites, and icicles, are stored in a few different areas.
First, "big" stalactite state is stored starting at 0x26F77
from
the start of the slot, and consists of 16 u8 values which should
be one of the following values:
- 0: Default
- 1: Cracked Once
- 2: Cracked Twice
- 3: On the Floor
- 4: On the Floor, Cracked Once
- 5: On the Floor, Cracked Twice
- 6: Broken
See the hex editor pattern for specific room mappings for these.
Next, starting at 0x26F98
from the start of the slot, is a series
of 8 u64 bitfields (or a single 512-byte bitfield, if you like)
describing small stalactites/stalagmites that have been destroyed.
The hex editor patterns have room mappings for all of those.
Finally, starting at 0x26FD8
from the start of the slot, there
is a series of 4 u64 bitfields (or a single 256-byte bitfield, if
you like) describing icicles that have been destroyed. At time
of writing, these haven't been mapped into rooms at all yet, but
check the hex editor patterns in case that's changed.
The unlocked equipment avilable to the player is stored as a u16 bitfield
at 0x1DC
from the start of the slot data. The available masks are:
-
0x02
: Firecrackers -
0x04
: Animal Flute -
0x08
: Lantern -
0x10
: Top -
0x20
: Disc (Note: if you give this to yourself without also setting the relevant quest statuses, you can find yourself with ghost dog hunting you down) -
0x40
: B. Wand -
0x80
: Yoyo -
0x100
: Slink -
0x200
: Remote -
0x400
: Ball -
0x800
: Wheel -
0x1000
: UV Light
If you're editing equipment into a character which did not have equipment already (such as a fresh save), make sure to also alter the "selected equipment" field below! It can be difficult to get equipment selected unless the value is set right away.
The currently-selected equipment is stored as a u8 at 0x1EA
from the
start of the save slot. Valid values are:
-
0x0
: None -
0x1
: Firecracker -
0x2
: Animal Flute -
0x3
: Lantern -
0x4
: Top -
0x5
: Disc -
0x6
: B. Wand -
0x7
: Yoyo -
0x8
: Slink -
0x9
: Remote -
0xA
: Ball -
0xB
: Wheel -
0xC
: UV Light
If you unlock any equipment via save editing but leave this field at 0x00
(such as if you're editing a brand-new slot before it's picked up any
equipment), equipment-swapping will be in a semi-non-working state. Next/Prev
equipment buttons won't work, and if you only have a single equipment item, you
can't enable it via the inventory screen, either. If you have more than one
equipment item in your inventory, you can select one of them from the
inventory screen, at which point all the equipment keys should work as
intended. Bottom line, if you're enabling equipment with save editing, just be
sure to make sure this field is set to one of the items you've added to the
save.
Other items which show up in your inventory are stored in a u8 bitfield at
0x1DE
from the start of the slot. This includes a few items which are
no longer used in the game. Valid values are:
-
0x01
: Mock Disc -
0x02
: S. Medal -
0x04
: Cake (from the alpha, unused) -
0x08
: House Key -
0x10
: Office Key -
0x20
: Closet Key (from the alpha, unused) -
0x40
: E. Medal -
0x80
: F. Pack
The eggs you acquire are stored in a 64-bit field starting at 0x188
from
the start of the slot data, and all 64 bits are used. The bitfield is set
up like so:
-
0x0000000000000001
: Reference Egg -
0x0000000000000002
: Brown Egg -
0x0000000000000004
: Raw Egg -
0x0000000000000008
: Pickled Egg -
0x0000000000000010
: Big Egg -
0x0000000000000020
: Swan Egg -
0x0000000000000040
: Forbidden Egg -
0x0000000000000080
: Shadow Egg -
0x0000000000000100
: Vanity Egg -
0x0000000000000200
: Egg as a Service -
0x0000000000000400
: Depraved Egg -
0x0000000000000800
: Chaos Egg -
0x0000000000001000
: Upside Down Egg -
0x0000000000002000
: Evil Egg -
0x0000000000004000
: Sweet Egg -
0x0000000000008000
: Chocolate Egg -
0x0000000000010000
: Value Egg -
0x0000000000020000
: Plant Egg -
0x0000000000040000
: Red Egg -
0x0000000000080000
: Orange Egg -
0x0000000000100000
: Sour Egg -
0x0000000000200000
: Post Modern Egg -
0x0000000000400000
: Universal Basic Egg -
0x0000000000800000
: Laissez-Faire Egg -
0x0000000001000000
: Zen Egg -
0x0000000002000000
: Future Egg -
0x0000000004000000
: Friendship Egg -
0x0000000008000000
: Truth Egg -
0x0000000010000000
: Transcendental Egg -
0x0000000020000000
: Ancient Egg -
0x0000000040000000
: Magic Egg -
0x0000000080000000
: Mystic Egg -
0x0000000100000000
: Holiday Egg -
0x0000000200000000
: Rain Egg -
0x0000000400000000
: Razzle Egg -
0x0000000800000000
: Dazzle Egg -
0x0000001000000000
: Virtual Egg -
0x0000002000000000
: Normal Egg -
0x0000004000000000
: Great Egg -
0x0000008000000000
: Gorgeous Egg -
0x0000010000000000
: Planet Egg -
0x0000020000000000
: Moon Egg -
0x0000040000000000
: Galaxy Egg -
0x0000080000000000
: Sunset Egg -
0x0000100000000000
: Goodnight Egg -
0x0000200000000000
: Dream Egg -
0x0000400000000000
: Travel Egg -
0x0000800000000000
: Promise Egg -
0x0001000000000000
: Ice Egg -
0x0002000000000000
: Fire Egg -
0x0004000000000000
: Bubble Egg -
0x0008000000000000
: Desert Egg -
0x0010000000000000
: Clover Egg -
0x0020000000000000
: Brick Egg -
0x0040000000000000
: Neon Egg -
0x0080000000000000
: Iridescent Egg -
0x0100000000000000
: Rust Egg -
0x0200000000000000
: Scarlet Egg -
0x0400000000000000
: Sapphire Egg -
0x0800000000000000
: Ruby Egg -
0x1000000000000000
: Jade Egg -
0x2000000000000000
: Obsidian Egg -
0x4000000000000000
: Crystal Egg -
0x8000000000000000
: Golden Egg
The bunnies that you've collected are stored in a 32-bit field starting
at 0x198
from the start of the slot. Technically all 32 bits are
used, but unlocking any of the "illegal" bunnies will make BDTP impossible
to solve and prevent you from executing it entirely, "since the BDTP
path is xored with your bunny flags" to see if you're on the right path.
(Explanation by: @Randomiser on Discord)
The valid bunny bitmasks are:
-
0x00000001
: Tutorial Bunny (#4) -
0x00000004
: Origami Bunny (#17) -
0x00000008
: Crow Bunny (#10) -
0x00000010
: Ghost Bunny (#9) -
0x00000040
: Fish Mural Bunny (#8) -
0x00000080
: Map Numbers Bunny (#5) -
0x00000100
: TV Bunny (#16) -
0x00000200
: UV Bunny (#7) -
0x00000400
: Bulb Bunny (#13) -
0x00000800
: Chinchilla Bunny (#2) -
0x00008000
: Bunny Mural Bunny (#1) -
0x00400000
: Duck Bunny (#11) -
0x02000000
: Ghost Dog Bunny (#18) -
0x10000000
: Dream Bunny (#12) -
0x40000000
: Floor Is Lava Bunny (#14) -
0x80000000
: Spike Room Bunny (#20)
The "illegal" bunny bitmasks are:
-
0x00000002
: Illegal 1 -
0x00000020
: Illegal 2 -
0x00001000
: Illegal 3 -
0x00002000
: Illegal 4 -
0x00004000
: Illegal 5 -
0x00010000
: Illegal 6 -
0x00020000
: Illegal 7 -
0x00040000
: Illegal 8 -
0x00080000
: Illegal 9 -
0x00100000
: Illegal 10 -
0x00200000
: Illegal 11 -
0x00800000
: Illegal 12 -
0x01000000
: Illegal 13 -
0x04000000
: Illegal 14 -
0x08000000
: Illegal 15 -
0x20000000
: Illegal 16
There's no "quests" in the game per se; perhaps "progression" is a better term. Regardless, there are a couple of bitfields to store that information.
The main bitfield which is involved with quests/progression is a u32 bitfield
starting at 0x1EC
past the slot start. There are a fair number of unknown
fields in here which are probably not actually used by the game. This also
includes some door states for the office area, etc.
-
0x00000001
: House Open -
0x00000002
: Office Open -
0x00000004
: Closet Open -
0x00000008
: (unknown) -
0x00000010
: (unknown) -
0x00000020
: (unknown) -
0x00000040
: (unknown) -
0x00000080
: (unknown) -
0x00000100
: Global Switch State (0 is right, 1 is left) -
0x00000200
: Map Unlocked -
0x00000400
: Stamps Unlocked -
0x00000800
: Pencil Unlocked -
0x00001000
: Defeated Chameleon -
0x00002000
: Cheater's Ring -
0x00004000
: Eaten by Chameleon -
0x00008000
: Inserted S. Medal -
0x00010000
: Inserted E. Medal -
0x00020000
: Wings / Flying Unlocked -
0x00040000
: Woke Up (start of game) -
0x00080000
: B.B. Wand Upgrade -
0x00100000
: Egg 65 -
0x00200000
: All Candles Lit (opens door under candle grid) -
0x00400000
: Teleport Torus Active -
0x00800000
: Manticore Egg Placed -
0x01000000
: Defeated Bat -
0x02000000
: Freed Ostrich -
0x04000000
: Defeated Ostrich -
0x08000000
: Fighting Eel -
0x10000000
: Defeated Eel -
0x20000000
: No Disc in Dog Shrine (the one that unlocks P. Flame) -
0x40000000
: No Disc in Dog Head Statue (where the Disc is acquired) -
0x80000000
: (unknown)
Note that the "Defeated Ostrich" mask (0x4000000
) controls both the
ground-based ostrich guarding the Yoyo area, and the wheel ostrich guarding
the G. Flame. If attempting to clear out the Defeated/Freed Ostrich
flags, be sure to un-press at least one of the relevant buttons, otherwise
the Wheel Ostrich will automatically free itself again when you next enter
the room. Also note that freeing the Wheel Ostrich will stop its relevant
elevator, so that data might need cleaning up.
Also note that in a vanilla game, both the "Freed Ostrich" and "Defeated Ostrich" flags will be set after the encounter. For the Eel encounter, though, the "Fighting Eel" flag will be cleared out once "Defeated Eel" is set.
The couple of quest states relating to the Disc / Mock Disc are of particular interest, because the game state can vary quite a bit depending on the state of those two flags, the presence of the Disc in your Equipment, and the presence of the Mock Disc in your inventory. Setting things improperly can lead to the player being chased by the ghost dog. A full sheet describing all possible combinations and their effect on the game can be found on Google Drive. A condensed version which only includes "valid" game states is shown below:
Has Mock Disc | Has Disc | No-Statue | No-Shrine | State |
---|---|---|---|---|
N | N | N | N | Start of Game |
Y | N | Y | Y | Picked up Mock Disc |
N | Y | N | Y | Swapped Mock Disc |
N | Y | Y | N | Moved Mock Disc to Shrine |
N | N | Y | N | Replaced Disc with M. Disc in Shrine |
There are some other combinations which are valid at runtime but which are never ordinarily found in savefiles, since the player can't save the game while the ghost dog is active. Other combinations simply can't be achieved without save/memory editing. See the sheet for full details.
So, if you're developing a tool which can give the player the Disc or Mock Disc, make sure to provide some avenue to set the quest states properly too!
Setting the Defeated Chameleon flag (0x1000
) will also remove the
chameleon at (14, 9) and the chameleon statue at (14, 10), in addition
to the main boss at (13, 5). Likewise, clearing the flag will cause
all three to reappear.
There's a separate u16 bitfield at 0x21C
from the slot start which defines
some other quest-like parameters. These are mostly related to very early
game, but they also have a flag for having the house key drop, after the
first set of credits. The known possible flags:
-
0x01
- Game Started -
0x02
- (unknown) -
0x04
- Ready To Hatch -
0x08
- Show HP Bar -
0x10
- Drop House Key
Both the Blue and Red Manticore states are tracked in a pair of u8 values.
The Blue Manticore is at 0x1F0
from the slot start, and the Red
Manticore is at 0x1F1
from the slot start. Valid values appear to be one
of these three:
- 0: Default/Unknown
- 1: In Overworld (will attack the player)
- 2: In Space (will be peaceful)
It's a bit difficult to know whether this should got in the map area, the player status area, or the quest/progression area. Anyway, here it is for now.
The Kangaroo will drop three K. Shards which together are used to unlock the K. Medal Circular Recess. The save format will store the exact location of any dropped shards which have yet to be picked up, and will retain that information in the structure after the player has picked up and/or placed the shards. The combined state of all three of these structures will determine when the K. Medal door opens.
Each of the three encounters has the same structure:
- A float (four byte) defining the in-room X position of the dropped bag
- A float (four byte) defining the in-room Y position of the dropped bag
- A u8 defining the room X coordinate in which the bag's found
- A u8 defining the room Y coordinate in which the bag's found
- A u8 defining the shard state. This will be one of four values:
- 0: Not Present
- 1: Dropped by Kangaroo
- 2: Picked Up
- 3: Inserted
- A u8 "Encounter ID." This will be a value from 0 to 4, and the IDs
correspond to specific room values (so the room coordinates will
always match up to the same IDs).
- 0: Room (6, 6) (one potential valid in-room position: 38, 104)
- 1: Room (9, 11) (one potential valid in-room position: 156, 136)
- 2: Room (12, 11) (one potential valid in-room position: 16, 144)
- 3: Room (9, 13) (one potential valid in-room position: 147, 144)
- 4: Room (16, 16) (one potential valid in-room position: 154, 128)
The three encounters start at 0x1F4
past the slot start.
After the final encounter, there are two more bits of data. First,
a u8 defining the next encounter where the Kangaroo will show up (at
0x218
past the start of the slot data). The ID will match the
Encounter IDs enumerated above. Then, at 0x219
past the slot start,
another u8 will define the current Kangaroo state, which should be
one of these values:
- 0: Idle
- 1: Running Away
- 2: Attacking
In my own testing, I found those statuses to be somewhat difficult to predict apart from "Attacking" (though perhaps I was just making some silly mistakes), so to ensure that the Kangaroo shows up immediately at a particular location, set its status to Attacking.
Flame states are stored as four u8 values, starting at 0x21E
from
the slot start. The valid values appear to be:
- 0: Sealed (the default state)
- 1: Cracked
- 2: Cracked More
- 3: Glass Broken
- 4: Flame Collected (in player inventory)
- 5: Flame Placed
The order of u8 values is:
- B. Flame
- P. Flame
- V. Flame
- G. Flame
There are two bitfields which respectively define which portals have
been "seen" (and will therefore open up when the player next plays
the flute at the control area), and which portals are already open.
These are u8 bitfields, and the "seen" field is at 0x223
past the
start of the slot, and the "active" field is at 0x224
past the
start of the slot. The masks are:
-
0x01
- (unused)- Does not control the Eel/Bonefish portal; that is done via a Quest flag instead.
-
0x02
- Frog -
0x04
- Fish -
0x08
- Bear -
0x10
- Dog -
0x20
- Bird -
0x40
- Squirrel -
0x80
- Hippo
(As mentioned far above in the header section, note that the section of the mural shown to the player depends on the Frame Seed)
There are a few bits of information stored about the Bunny Mural. First,
a pair of u8 values at 0x3EA
and 0x3EB
from the start of the slot
data which describe the currently-selected X/Y position of the mural,
when using the controls to alter it.
Then, the actual mural data is much later in the file, starting at
0x26EAF
past the slot start. The mural is 40x20 in resolution.
The data is essentially arranged like an image, which each pixel
taking two bits of data to describe (which results in four possible
colors per pixel). Since four pixels can fit inside a byte, a
40-pixel row will fit into 10 bytes. At 20 rows, that means the
mural data takes up 200 bytes total.
There is a u16 bitfield starting at 0x26FF8
from the start of the slot
which seems to mimic some of the data from the "global" unlocks section (ie:
figurines, stopwatch, pedometer, etc). It's not fully understood how this
one works at time of writing, or if it even has an effect.
Stamps are stored starting at 0x225
from the slot start. The first u8 there
describes how many stamps have been placed. Immediately after is a u16
which stores the stamp icon that's currently selected by the player. The values
are:
- 0: Chest
- 1: Heart
- 2: Skull
- 3: Diamond-or-whatever
- 4: Spiral
- 5: Flame
- 6: Diamond "grid"
- 7: Question Mark
Then after that are 64 slots for stamp descriptions. The game will compact them into a consecutive list as stamps are deleted, so editors don't need to check for "null" stamps or anything; just read in however many the save says are there. The format of each stamp is:
- u16 - X coordinate (in minimap pixels)
- u16 - Y coordinate (in minimap pixels)
- u16 - Icon, using the same values as above
When the player deletes a stamp in the game, the engine will copy the last stamp into the deleted index and then decrement the index, so deletions will only re-order the last stamp in the list.
"Basic" minimap data is stored as a single bit for each "pixel" of the minimap. The game engine fills in the colors as-appropriate, and will update the map depending on the actual game state (if walls have been demolished, etc).
Each minimap room is 40x22 pixels, so that's five bytes for a single row across a room, and 110 bytes total for the room. Even though the playable game area is 16x16 rooms, the minimap (and the actual map, technically), is 20x24, with the 16x16 playable area centered in there. There are four empty rows of rooms on the top+bottom, and two columns of empty rooms on the sides. So, that yields 52,800 bytes of info for the minimap as a whole.
Structurally, it's stored sort of like an image; one big row at a time. So the
entire first row comes first (for all rooms at the "top"), then the next row
down, etc. The minimap data starts at 0x3EC
.
The minimap pencil layer is structure identically to the "revealed" minimap
data, and it starts at 0xD22D
from the start of the slot data. Note that
there is a single unused byte inbetween the main "revealed" data and the
pencil data.
The game also keeps track of which tiles have been destroyed (whether via the
top, Manticore lasers, detonators, or whatever) in another identical format
to the minimap. This starts at 0x1A06E
from the start of the slot data.
Like with the Pencil layer, note that there's an empty byte inbetween the
Pencil data and the destruction layer.
The game options start at the very end of the file, at position 0x75048
.
First up, at that address, is a u16 bitfield with the following known
values:
-
0x0001
- Scanlines -
0x0002
- Fullscreen -
0x0004
- Show Time -
0x0008
- Show Steps -
0x0010
- Vibration -
0x0020
- Forced Save Mode -
0x0040
- Reduce Flashing -
0x0080
- Override Controller Style -
0x0200
- Swap Confirm/Cancel -
0x0400
- Ignore BG Input -
0x0800
- Gamepad Speaker Off (possibly reverted?)
Then at pos 0x7504A
is a u8 value which defines the language used:
- 0: English
- 1: Spanish
- 2: French
- 3: Italian
- 4: German
- 5: Chinese
- 6: Korean
- 7: Japanese
- 8: Portuguese
- 9: Ukrainian
- 10: Russian
Next, starting at 0x7504B
are five u8 values which are best left alone.
The first is a possible demo mode toggle, which crashes the game, the
second seems to always be 1
, and the other three are unknown.
After that, at 0x75050
and 0x75054
are float values to define the
volume for SFX and Music, respectively.
Next, the controller style is a u8 at 0x75058
and should be one of these
values:
- 0: PS5
- 1: XBox
- 2: Nintendo
- 3: Keyboard
Finally, the u8 at 0x75059
describes the current graphics setting:
- 0: Good
- 1: Better
- 2: Best
The remainder of the header appears to just be null-byte padding.