Angband
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
 

Macros

#define BUFFER_INITIAL_SIZE   1024
 
#define BUFFER_BLOCK_INCREMENT   1024
 
#define SAVEFILE_HEAD_SIZE   28
 
#define SAVE_U32B(v)
 
#define RECONSTRUCT_U32B(from)
 

Typedefs

typedef int(* loader_t )(void)
 

Functions

void note (const char *message)
 

Utility

More...
 
static void sf_put (byte v)
 

Base put/get

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

Accessor functions

More...
 
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

More...
 
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

More...
 
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...
 

Variables

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 andi@.nosp@m.takk.nosp@m.aria..nosp@m.org

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

#define BUFFER_BLOCK_INCREMENT   1024

Referenced by sf_put().

#define BUFFER_INITIAL_SIZE   1024

Referenced by try_save().

#define RECONSTRUCT_U32B (   from)
Value:
((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)
Value:
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().

#define SAVEFILE_HEAD_SIZE   28

Referenced by next_blockheader(), and try_save().

Typedef Documentation

typedef int(* loader_t)(void)

Function Documentation

static bool check_header ( ang_file f)
static


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().

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

Find the right loader for this block, return it.

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

Referenced by try_load().

static int get_desc ( void  )
static

References rd_string(), and savefile_desc.

Referenced by savefile_get_description().

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

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().

static errr next_blockheader ( ang_file f,
struct blockheader b 
)
static
void note ( const char *  message)
void pad_bytes ( int  n)

References wr_byte().

void rd_byte ( byte ip)
void rd_s16b ( s16b ip)
void rd_s32b ( s32b ip)

References rd_u32b().

Referenced by rd_dungeon_aux(), rd_history(), rd_misc(), and rd_player().

void rd_string ( char *  str,
int  max 
)
void rd_u16b ( u16b ip)
void rd_u32b ( u32b ip)
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(), NULL, savefile_desc, skip_block(), and streq.

Referenced by list_saves().

bool savefile_load ( const char *  path,
bool  cheat_death 
)
bool savefile_save ( const char *  path)
static byte sf_get ( void  )
static

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

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

static void sf_put ( byte  v)
static
static void skip_block ( ang_file f,
struct blockheader b 
)
static

Skip a block.

References file_skip(), and blockheader::size.

Referenced by savefile_get_description().

void strip_bytes ( int  n)

References rd_byte().

Referenced by rd_ignore(), and rd_player().

static bool try_load ( ang_file f,
const struct blockinfo local_loaders 
)
static

Try to load a savefile.

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

Referenced by savefile_load().

static bool try_save ( ang_file file)
static
void wr_byte ( byte  v)
void wr_s16b ( s16b  v)
void wr_s32b ( s32b  v)

References wr_u32b().

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

void wr_string ( const char *  str)
void wr_u16b ( u16b  v)
void wr_u32b ( u32b  v)

Variable Documentation

byte* buffer
static
u32b buffer_check
static

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

u32b buffer_pos
static

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

u32b buffer_size
static

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

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.

TODO:

  • 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().

const struct blockinfo loaders[]
static
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 },
{ "artifacts", rd_artifacts, 1 },
{ "player", rd_player, 1 },
{ "ignore", rd_ignore, 1 },
{ "misc", rd_misc, 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't need loading anymore.
Definition: load.c:1578
int rd_history(void)
Definition: load.c:1523
int rd_player(void)
Read the player information.
Definition: load.c:630
int rd_options(void)
Read options.
Definition: load.c:384
int rd_chunks(void)
Read the chunk list.
Definition: load.c:1488
int rd_player_spells(void)
Read the player spells.
Definition: load.c:1010
int rd_stores(void)
Read the stores - wrapper functions.
Definition: load.c:1174
int rd_randomizer(void)
Read RNG state.
Definition: load.c:348
int rd_object_memory(void)
Definition: load.c:497
int rd_monsters(void)
Read the monster list - wrapper functions.
Definition: load.c:1448
int rd_monster_memory(void)
Read monster memory.
Definition: load.c:453
int rd_objects(void)
Read the objects - wrapper functions.
Definition: load.c:1431
int rd_misc(void)
Definition: load.c:909
int rd_player_hp(void)
Definition: load.c:987
int rd_dungeon(void)
Definition: load.c:1379
int rd_ignore(void)
Read ignore and autoinscription submenu for all known objects.
Definition: load.c:804
int rd_quests(void)
Definition: load.c:572
int rd_messages(void)
Read the saved messages.
Definition: load.c:424
int rd_traps(void)
Read the traps - wrapper functions.
Definition: load.c:1472
int rd_gear(void)
Read the player gear - wrapper functions.
Definition: load.c:1091
int rd_artifacts(void)
Definition: load.c:597

Savefile loading functions.

char name[16]
void(* save)(void)
char savefile_desc[120]
static
const byte savefile_magic[4] = { 83, 97, 118, 101 }
static

Magic bits at beginning of savefile.

Referenced by check_header(), and savefile_save().

const byte savefile_name[4] = "VNLA"
static

Referenced by check_header(), and savefile_save().

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 },
{ "artifacts", wr_artifacts, 1 },
{ "player", wr_player, 1 },
{ "ignore", wr_ignore, 1 },
{ "misc", wr_misc, 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:994
void wr_randomizer(void)
Write RNG state.
Definition: save.c:272
void wr_ignore(void)
Definition: save.c:515
void wr_stores(void)
Definition: save.c:725
void wr_description(void)
Write a description of the character.
Definition: save.c:47
void wr_messages(void)
Definition: save.c:323
void wr_player_hp(void)
Definition: save.c:670
void wr_monsters(void)
Definition: save.c:945
void wr_player(void)
Definition: save.c:419
void wr_objects(void)
Definition: save.c:936
void wr_traps(void)
Definition: save.c:954
void wr_chunks(void)
Definition: save.c:966
void wr_gear(void)
Definition: save.c:715
void wr_dungeon(void)
Definition: save.c:915
void wr_misc(void)
Definition: save.c:606
void wr_monster_memory(void)
Definition: save.c:340
void wr_player_spells(void)
Definition: save.c:680
void wr_quests(void)
Definition: save.c:388
void wr_artifacts(void)
Definition: save.c:401
void wr_object_memory(void)
Definition: save.c:360
void wr_options(void)
Write the "options".
Definition: save.c:300

Savefile saving functions.

Referenced by try_save().

u32b version

Referenced by try_save().