Data Structures | Macros | Typedefs | Functions | Variables
savefile.c File Reference

Savefile loading and saving main routines. More...

#include <errno.h>
#include "angband.h"
#include "game-world.h"
#include "init.h"
#include "savefile.h"

Data Structures

struct  blockheader
struct  blockinfo


#define BUFFER_INITIAL_SIZE   1024
#define SAVE_U32B(v)
#define RECONSTRUCT_U32B(from)


typedef int(* loader_t) (void)


void note (const char *message)


static void sf_put (byte v)

Base put/get

static byte sf_get (void)
void wr_byte (byte v)

Accessor functions

void wr_u16b (u16b v)
void wr_s16b (s16b v)
void wr_u32b (u32b v)
void wr_s32b (s32b v)
void wr_string (const char *str)
void rd_byte (byte *ip)
void rd_u16b (u16b *ip)
void rd_s16b (s16b *ip)
void rd_u32b (u32b *ip)
void rd_s32b (s32b *ip)
void rd_string (char *str, int max)
void strip_bytes (int n)
void pad_bytes (int n)
static bool try_save (ang_file *file)

Savefile saving functions

bool savefile_save (const char *path)
 Attempt to save the player in a savefile. More...
static bool check_header (ang_file *f)

Savefile loading functions

static errr next_blockheader (ang_file *f, struct blockheader *b)
 Get the next block header from the savefile. More...
static loader_t find_loader (struct blockheader *b, const struct blockinfo *local_loaders)
 Find the right loader for this block, return it. More...
static bool load_block (ang_file *f, struct blockheader *b, loader_t loader)
 Load a given block with the given loader. More...
static void skip_block (ang_file *f, struct blockheader *b)
 Skip a block. More...
static bool try_load (ang_file *f, const struct blockinfo *local_loaders)
 Try to load a savefile. More...
static int get_desc (void)
const char * savefile_get_description (const char *path)
 Try to get the 'description' block from a savefile. More...
bool savefile_load (const char *path, bool cheat_death)
 Load a savefile. More...


bool character_saved
 The savefile code. More...
static const byte savefile_magic [4] = { 83, 97, 118, 101 }
 Magic bits at beginning of savefile. More...
static const byte savefile_name [4] = "VNLA"
struct {
   char   name [16]
   void(*   save )(void)
   u32b   version
savers []
 Savefile saving functions. More...
static const struct blockinfo loaders []
 Savefile loading functions. More...
static bytebuffer
static u32b buffer_size
static u32b buffer_pos
static u32b buffer_check
static char savefile_desc [120]

Detailed Description

Savefile loading and saving main routines.

Copyright (c) 2009 Andi Sidwell

This work is free software; you can redistribute it and/or modify it under the terms of either:

a) the GNU General Public License as published by the Free Software Foundation, version 2, or

b) the "Angband licence": This software may be copied and distributed for educational, research, and not for profit purposes provided that this copyright and statement are included in all such copies. Other copyrights may also apply.

Macro Definition Documentation



Referenced by sf_put().


#define BUFFER_INITIAL_SIZE   1024

Referenced by try_save().


#define RECONSTRUCT_U32B (   from)
((u32b) savefile_head[from]) | \
((u32b) savefile_head[from+1] << 8) | \
((u32b) savefile_head[from+2] << 16) | \
((u32b) savefile_head[from+3] << 24);
uint32_t u32b
Definition: h-basic.h:172

Referenced by next_blockheader().


#define SAVE_U32B (   v)
savefile_head[pos++] = (v & 0xFF); \
savefile_head[pos++] = ((v >> 8) & 0xFF); \
savefile_head[pos++] = ((v >> 16) & 0xFF); \
savefile_head[pos++] = ((v >> 24) & 0xFF);

Referenced by try_save().



Referenced by next_blockheader(), and try_save().

Typedef Documentation

◆ loader_t

typedef int(* loader_t) (void)

Function Documentation

◆ check_header()

static bool check_header ( ang_file f)

Savefile loading functions

Check the savefile header file clearly inicates that it's a savefile

References file_read(), savefile_magic, and savefile_name.

Referenced by savefile_get_description(), and try_load().

◆ find_loader()

static loader_t find_loader ( struct blockheader b,
const struct blockinfo local_loaders 

Find the right loader for this block, return it.

References i, blockinfo::loader, blockheader::name, blockinfo::name, streq, blockheader::version, and blockinfo::version.

Referenced by try_load().

◆ get_desc()

static int get_desc ( void  )

References rd_string(), and savefile_desc.

Referenced by savefile_get_description().

◆ load_block()

static bool load_block ( ang_file f,
struct blockheader b,
loader_t  loader 

Load a given block with the given loader.

References buffer, buffer_check, buffer_pos, buffer_size, file_read(), mem_alloc(), mem_free(), and blockheader::size.

Referenced by savefile_get_description(), and try_load().

◆ next_blockheader()

static errr next_blockheader ( ang_file f,
struct blockheader b 

◆ note()

void note ( const char *  message)

◆ pad_bytes()

void pad_bytes ( int  n)

References wr_byte().

◆ rd_byte()

void rd_byte ( byte ip)

◆ rd_s16b()

void rd_s16b ( s16b ip)

◆ rd_s32b()

void rd_s32b ( s32b ip)

◆ rd_string()

void rd_string ( char *  str,
int  max 

◆ rd_u16b()

void rd_u16b ( u16b ip)

◆ rd_u32b()

void rd_u32b ( u32b ip)

◆ savefile_get_description()

const char* savefile_get_description ( const char *  path)

Try to get the 'description' block from a savefile.

Try to get a description for this savefile.

Fail gracefully.

References check_header(), file_close(), file_open(), FTYPE_TEXT, get_desc(), load_block(), MODE_READ, my_strcpy(), blockheader::name, next_blockheader(), savefile_desc, skip_block(), and streq.

Referenced by list_saves().

◆ savefile_load()

bool savefile_load ( const char *  path,
bool  cheat_death 

◆ savefile_save()

bool savefile_save ( const char *  path)

◆ sf_get()

static byte sf_get ( void  )

References buffer, buffer_check, buffer_pos, buffer_size, and quit().

Referenced by rd_byte(), rd_u16b(), and rd_u32b().

◆ sf_put()

static void sf_put ( byte  v)

◆ skip_block()

static void skip_block ( ang_file f,
struct blockheader b 

Skip a block.

References file_skip(), and blockheader::size.

Referenced by savefile_get_description().

◆ strip_bytes()

void strip_bytes ( int  n)

References rd_byte().

Referenced by rd_ignore(), and rd_player().

◆ try_load()

static bool try_load ( ang_file f,
const struct blockinfo local_loaders 

Try to load a savefile.

References check_header(), find_loader(), format(), load_block(), blockheader::name, next_blockheader(), and note().

Referenced by savefile_load().

◆ try_save()

static bool try_save ( ang_file file)

◆ wr_byte()

void wr_byte ( byte  v)

◆ wr_s16b()

void wr_s16b ( s16b  v)

◆ wr_s32b()

void wr_s32b ( s32b  v)

References wr_u32b().

Referenced by wr_chunks(), wr_dungeon_aux(), wr_history(), and wr_misc().

◆ wr_string()

void wr_string ( const char *  str)

◆ wr_u16b()

void wr_u16b ( u16b  v)

◆ wr_u32b()

void wr_u32b ( u32b  v)

Variable Documentation

◆ buffer

byte* buffer

◆ buffer_check

u32b buffer_check

Referenced by load_block(), sf_get(), sf_put(), and try_save().

◆ buffer_pos

u32b buffer_pos

Referenced by load_block(), sf_get(), sf_put(), and try_save().

◆ buffer_size

u32b buffer_size

Referenced by load_block(), sf_get(), sf_put(), and try_save().

◆ character_saved

bool character_saved

The savefile code.

Savefile API

Savefiles since ~3.1 have used a block-based system. Each savefile consists of an 8-byte header, the first four bytes of which mark this as a savefile, the second four bytes provide a variant ID.

After that, each block has the format:

  • 16-byte string giving the type of block
  • 4-byte block version
  • 4-byte block size
  • 4-byte block checksum ... data ... padding so that block is a multiple of 4 bytes

The savefile deosn't contain the version number of that game that saved it; versioning is left at the individual block level. The current code keeps a list of savefile blocks to save in savers[] below, along with their current versions.

For each block type and version, there is a loading function to load that type/version combination. For example, there may be a loader for v1 and v2 of the RNG block; these must be different functions. It has been done this way since it allows easier maintenance; after each release, you need simply remove old loaders and you will not have to disentangle lots of code with "if (version > 3)" and its like everywhere.

Savefile loading and saving is done by keeping the current block in memory, which is accessed using the wr_* and rd_* functions. This is then written out, whole, to disk, with the appropriate header.

So, if you want to make a savefile compat-breaking change, then there are a few things you should do:

  • increment the version in 'savers' below
  • add a loading function that accepts the new version (in addition to the previous loading function) to 'loaders'
  • and watch the magic happen.


  • wr_ and rd_ should be passed a buffer to work with, rather than using the rd_ and wr_ functions with a universal buffer
  • Global "we've just saved" variable

Referenced by handle_signal_abort(), handle_signal_simple(), inkey_ex(), and savefile_save().

◆ loaders

const struct blockinfo loaders[]
Initial value:
= {
{ "description", rd_null, 1 },
{ "rng", rd_randomizer, 1 },
{ "options", rd_options, 1 },
{ "messages", rd_messages, 1 },
{ "monster memory", rd_monster_memory, 1 },
{ "object memory", rd_object_memory, 1 },
{ "quests", rd_quests, 1 },
{ "player", rd_player, 1 },
{ "ignore", rd_ignore, 1 },
{ "misc", rd_misc, 1 },
{ "artifacts", rd_artifacts, 1 },
{ "player hp", rd_player_hp, 1 },
{ "player spells", rd_player_spells, 1 },
{ "gear", rd_gear, 1 },
{ "stores", rd_stores, 1 },
{ "dungeon", rd_dungeon, 1 },
{ "objects", rd_objects, 1 },
{ "monsters", rd_monsters, 1 },
{ "traps", rd_traps, 1 },
{ "chunks", rd_chunks, 1 },
{ "history", rd_history, 1 },
int rd_null(void)
For blocks that don&#39;t need loading anymore.
Definition: load.c:1676
int rd_history(void)
Definition: load.c:1625
int rd_player(void)
Read the player information.
Definition: load.c:633
int rd_options(void)
Read options.
Definition: load.c:413
int rd_chunks(void)
Read the chunk list.
Definition: load.c:1561
int rd_player_spells(void)
Read the player spells.
Definition: load.c:1060
int rd_stores(void)
Read the stores - wrapper functions.
Definition: load.c:1219
int rd_randomizer(void)
Read RNG state.
Definition: load.c:377
int rd_object_memory(void)
Definition: load.c:530
int rd_monsters(void)
Read the monster list - wrapper functions.
Definition: load.c:1525
int rd_monster_memory(void)
Read monster memory.
Definition: load.c:482
int rd_objects(void)
Read the objects - wrapper functions.
Definition: load.c:1512
int rd_misc(void)
Definition: load.c:928
int rd_player_hp(void)
Definition: load.c:1037
int rd_dungeon(void)
Definition: load.c:1458
int rd_ignore(void)
Read ignore and autoinscription submenu for all known objects.
Definition: load.c:823
int rd_quests(void)
Definition: load.c:605
int rd_messages(void)
Read the saved messages.
Definition: load.c:453
int rd_traps(void)
Read the traps - wrapper functions.
Definition: load.c:1549
int rd_gear(void)
Read the player gear - wrapper functions.
Definition: load.c:1138
int rd_artifacts(void)
Definition: load.c:1007

Savefile loading functions.

◆ name

char name[16]

◆ save

void(* save) (void)

◆ savefile_desc

char savefile_desc[120]

◆ savefile_magic

const byte savefile_magic[4] = { 83, 97, 118, 101 }

Magic bits at beginning of savefile.

Referenced by check_header(), and savefile_save().

◆ savefile_name

const byte savefile_name[4] = "VNLA"

Referenced by check_header(), and savefile_save().

◆ savers

const { ... } savers[]
Initial value:
= {
{ "description", wr_description, 1 },
{ "rng", wr_randomizer, 1 },
{ "options", wr_options, 1 },
{ "messages", wr_messages, 1 },
{ "monster memory", wr_monster_memory, 1 },
{ "object memory", wr_object_memory, 1 },
{ "quests", wr_quests, 1 },
{ "player", wr_player, 1 },
{ "ignore", wr_ignore, 1 },
{ "misc", wr_misc, 1 },
{ "artifacts", wr_artifacts, 1 },
{ "player hp", wr_player_hp, 1 },
{ "player spells", wr_player_spells, 1 },
{ "gear", wr_gear, 1 },
{ "stores", wr_stores, 1 },
{ "dungeon", wr_dungeon, 1 },
{ "objects", wr_objects, 1 },
{ "monsters", wr_monsters, 1 },
{ "traps", wr_traps, 1 },
{ "chunks", wr_chunks, 1 },
{ "history", wr_history, 1 },
void wr_history(void)
Definition: save.c:1039
void wr_randomizer(void)
Write RNG state.
Definition: save.c:285
void wr_ignore(void)
Definition: save.c:510
void wr_stores(void)
Definition: save.c:735
void wr_description(void)
Write a description of the character.
Definition: save.c:48
void wr_messages(void)
Definition: save.c:336
void wr_player_hp(void)
Definition: save.c:683
void wr_monsters(void)
Definition: save.c:977
void wr_player(void)
Definition: save.c:415
void wr_objects(void)
Definition: save.c:971
void wr_traps(void)
Definition: save.c:983
void wr_chunks(void)
Definition: save.c:992
void wr_gear(void)
Definition: save.c:728
void wr_dungeon(void)
Definition: save.c:950
void wr_misc(void)
Definition: save.c:601
void wr_monster_memory(void)
Definition: save.c:353
void wr_player_spells(void)
Definition: save.c:693
void wr_quests(void)
Definition: save.c:402
void wr_artifacts(void)
Definition: save.c:665
void wr_object_memory(void)
Definition: save.c:374
void wr_options(void)
Write the "options".
Definition: save.c:313

Savefile saving functions.

Referenced by try_save().

◆ version

u32b version