Skip to content
CJ Kucera edited this page Jun 4, 2024 · 35 revisions

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 and offer some more in-depth documentation about the various bits of data, but the editor templates are likely to be a bit more complete and well-proofread.

Unknowns/TODO

  • Waveform puzzle

Header Info

The first u32 of the file is a version field – was 2 at one point during prerelease, 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 user. 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). Sample code to “fix” the checksum on a file on-disk can be found here: https://gist.github.com/apocalyptech/8f8815c06bde9cd46d5170e1548c1e66

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.

Slot Data

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.

General Info

  • 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: 0x108 - u32?

Times Saved: 0x1A8 - u16?

Health: 0x1B4 - u8

  • Note: Presumably this is only “regular” health

Timing (for Stopwatch / Speedrunning) - u32

  • These are measured in “ticks.” The game runs at 60Hz, so the unit is not milliseconds. Don’t try to just plug it into a usual date-handling library without accounting for that first!
  • 0x1BC - Elapsed time in-game. The game does not actually report this anywhere to the user, that I’m aware of
  • 1x1C0 - Elapsed time including paused time. This is what’s reported to the user and checked for speedrun figurines, etc.

Times Died: 0x1E4 - u16

  • The skulls in the B.B. Wand / Souvenir Cup / Smiley Code / Skull room dynamically change depending on this value; don’t need to look for those separately.

Spawn Point:

  • Turns out these are coordinates, not save-point indexes! Two u32s, describing the X and Y room to spawn in. You can set these to rooms which don’t have telephones and you’ll spawn in there. 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.
  • X coord: 0x1D4
  • Y coord: 0x1D8

Map Data

Cranks

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.

Chest Bitfields

I suspect (but don’t know for sure yet) that all chests are near this point in the data, in a single large bitfield. 0 means the chest has not been opened yet, 1 means you’ve looted its contents. Note that merely setting a chest to open does not give you whatever was in that chest.

0x126

  • 0x04 - Stamp Chest (in Egg Room)

0x127

  • 0x20 - Map Chest

0x12A

  • 0x01 - Clover Egg Chest

0x12C

  • 0x10 - Fanny Pack Chest

Squirrel-Frightening Bitfields

I suspect (but don’t know for sure yet) that all squirrels are near this point in the data, in a single large bitfield. 0 means the squirrel is happily eating a nut, 1 means you scared it away. (Note: I assume that these go to 1 when you steal a nut, too. Have not tested that, though!)

0x19C

  • 0x20: The first squirrel you see in the game

Ghost-Frightening Bitfields

I suspect (but don’t know for sure yet) that all ghosts are near this point in the data, in a single large bitfield. 0 means the ghost is ready to give you a fright, 1 means you scared it away. (Note: I do not yet know how this interacts with lighting candles.) These values should get set back to 0 if you die, though once again I don’t know how that interacts with candles.

0x1E7

  • 0x01 - The ghost “blocking” the way to the map pickup and exit to the larger map, at the beginning.
  • 0x04 - The ghost you’re intended to frighten off first, after picking up fireworks for the first time.

Unlockable Doors and Moveable Walls

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

Button-Door Bitfields

First: the door buttons. I suspect (but don’t know for sure) that all door buttons are near this point in the data, in a single large bitfield. 0 means the button has not been pushed, 1 means the button has been pushed. The lights on the doorway are tied to this as well. Marking all necessary buttons as pushed technically does not open the door, but as soon as you enter a room with all pushed-down buttons, the door will open anyway, so it’s not really that important

0x148

  • 0x80: The first button you come across if heading to pick up firecrackers for the first time

0x149

  • 0x01: The second button (across the water)
  • 0x04: The final button (after going underneath)

Now, the doors themselves. Again, I suspect (but don’t know for sure) that all doors are near this point in the data, in a single large bitfield. 0 means the door is closed, 1 means the door is open. You can set a door to open without having any of the buttons pressed down. (I’m not sure exactly what happens if you then press one of the buttons, though.)

0x137

  • 0x04: The door opened by the buttons described above, in front of the intended first-time firecracker pickups

There’s a second class of doors in the game which aren’t opened by buttons but by other means (such as keys). The one that I’ve investigated so far is just the Fanny Pack door (which AFAIK does not require a key), but this is definitely a bitfield:

0x1EC

  • 0x04: Fanny Pack door

Fruit Bitfields

So far all I’ve looked at is the first couple “regular” fruits. Again, I suspect (but don’t know for sure) that all fruits are near this point in the data, in a single large bitfield. 0 means the fruit is still available, 1 means the fruit has been consumed. These bitfields should all get reset to 0 when you die.

Known locations (I did not try to enumerate the specific fruits at all, yet):

  • 0x178

Firecracker Bitfields

Again, I suspect (but don’t know for sure) that all firecracker plants are near this point in the data, in a single large bitfield. 0 means the firecracker is still available, 1 means that it’s been harvested. These bitfields should all get reset to 0 when you die.

Known locations (these are all in that first intended firecracker-pickup area):

  • 0x178
  • 0x179
  • 0x17A

Character/Collectibles Data

Equipment Unlocks

Currently-selected Equipment: 0x1EA

  • This is not a bitfield; it’s actually just a numeric ID. I have yet to enumerate which IDs go with which bits of equipment, but the two I know of are:
    • 0x01 - Firecrackers
    • 0x05 - Disc
  • 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.

Firecracker Count: 0x1B3 - u8

  • Note: You do need to actually unlock firecrackers below (and set the currently-selected equipment above, if this is a fresh save) – merely adding firecrackers will not let you use them if you haven’t unlocked them yet.

Equipment Unlock Bitfield: 0x1DC - u16

  • 0x02: Firecrackers
  • 0x04: Whistle
  • 0x08: Lantern
  • 0x10: Top
  • 0x20: Disc (Note: if you give this to yourself without also setting the as-yet-not-figured-out Mock Disc statuses, you’ll find yourself with a persistent friend following you around.)
  • 0x40: B. Wand
  • 0x80: Yoyo
  • 0x100: Slink
  • 0x200: Remote
  • 0x400: Ball
  • 0x800: Wheel
  • 0x1000: UV Light

(TODO: Have not yet looked into how the B.B. Wand is unlocked)

Other Inventory Unlock Bitfields

Not sure if it makes sense to group this separately from the “equippable” items, but these are items which show up in your inventory but which you don’t directly use (except in specific locations, like keys).

0x1DE

  • 0x02: S Medal
  • 0x08: House Key (I think, could have that switched with Office)
  • 0x10: Office Key (I think, could have that switched with House)
  • 0x20: Unused Key (literally not used in the game at all)
  • 0x40: E Medal
  • 0x80: Fanny Pack

Map Unlock Bitfield

This bitfield controls what aspects of the map you’ve got unlocked.

0x1ED

  • 0x02 - The map itself
  • 0x04 - Stamp
  • 0x08 - Pencil

Egg Bitfields

I suspect (but don’t know for sure yet) that all eggs are near this point in the data, in a single large bitfield. Presumably that’d mean a big ol’ bitfield of 8 bytes. 0 means you don’t have the egg yet, 1 means you’ve got it. Setting these flags does not do anything to the chests they come from, but it doesn’t appear to harm anything if you give yourself an egg, and then go collect it from the “proper” chest later.

Known locations:

  • 0x18E - includes the Clover egg, and seven others which sit next to it in the Egg Room

Minimap

“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 starts at 0x3EC and runs up until 0xD22C (non-inclusive).

Immediately after the “main” minimap data area is a single (presumably unused) byte, and then another chunk of 52,800 bytes which describe the “pencil” data which can be drawn by the user. It’s in the same format as the main minimap data. That starts at 0xD22D and runs up until 0x1A06D (non-inclusive).

Stamps are stored earlier in the game data, starting at 0x225. The first bit of data is a u8 describing how many stamps have been placed. Next is a u16 which stores the stamp icon that’s currently selected by the user. The values are:

  • 0: Chest
  • 1: Heart
  • 2: Skull
  • 3: Diamond-or-whatever
  • 4: Spiral
  • 5: Flame
  • 6: Diamond “grid”
  • 7: Question Mark

(a u16 is a bit overkill for that, but it’s what the game seems to use).

Then after that are 64 slots for stamp descriptions. The game will compact them into a consecutive list as stamps are deleted, so you 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:

  1. u16 - x coordinate (in minimap pixels)
  2. u16 - y coordinate (in minimap pixels)
  3. u16 - icon, using the same values as above

The stamp data should end at byte 0x3A7 (so 0x3A8 would be the next-free byte for other data).

Game Options

ANIMAL SICK has pretty thoroughly figured that section out – we’ll paste that in here once we get permission for that. The options start just after the last save slot, at 0x75048.

Clone this wiki locally