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

◆ BUFFER_BLOCK_INCREMENT

#define BUFFER_BLOCK_INCREMENT   1024

Referenced by sf_put().

◆ BUFFER_INITIAL_SIZE

#define BUFFER_INITIAL_SIZE   1024

Referenced by try_save().

◆ RECONSTRUCT_U32B

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

◆ SAVE_U32B

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

◆ SAVEFILE_HEAD_SIZE

#define SAVEFILE_HEAD_SIZE   28

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

◆ find_loader()

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

◆ get_desc()

static int get_desc ( void  )
static

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

◆ next_blockheader()

static errr next_blockheader ( ang_file f,
struct blockheader b 
)
static

◆ 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(), NULL, 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  )
static

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

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

◆ sf_put()

static void sf_put ( byte  v)
static

◆ skip_block()

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

◆ 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 
)
static

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)
static

◆ 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
static

◆ buffer_check

u32b buffer_check
static

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

◆ buffer_pos

u32b buffer_pos
static

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

◆ buffer_size

u32b buffer_size
static

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.

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

◆ loaders

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 },
{ "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:1622
int rd_history(void)
Definition: load.c:1571
int rd_player(void)
Read the player information.
Definition: load.c:603
int rd_options(void)
Read options.
Definition: load.c:387
int rd_chunks(void)
Read the chunk list.
Definition: load.c:1507
int rd_player_spells(void)
Read the player spells.
Definition: load.c:1015
int rd_stores(void)
Read the stores - wrapper functions.
Definition: load.c:1174
int rd_randomizer(void)
Read RNG state.
Definition: load.c:351
int rd_object_memory(void)
Definition: load.c:500
int rd_monsters(void)
Read the monster list - wrapper functions.
Definition: load.c:1471
int rd_monster_memory(void)
Read monster memory.
Definition: load.c:456
int rd_objects(void)
Read the objects - wrapper functions.
Definition: load.c:1458
int rd_misc(void)
Definition: load.c:884
int rd_player_hp(void)
Definition: load.c:992
int rd_dungeon(void)
Definition: load.c:1404
int rd_ignore(void)
Read ignore and autoinscription submenu for all known objects.
Definition: load.c:779
int rd_quests(void)
Definition: load.c:575
int rd_messages(void)
Read the saved messages.
Definition: load.c:427
int rd_traps(void)
Read the traps - wrapper functions.
Definition: load.c:1495
int rd_gear(void)
Read the player gear - wrapper functions.
Definition: load.c:1093
int rd_artifacts(void)
Definition: load.c:962

Savefile loading functions.

◆ name

char name[16]

◆ save

void(* save) (void)

◆ savefile_desc

char savefile_desc[120]
static

◆ savefile_magic

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

Magic bits at beginning of savefile.

Referenced by check_header(), and savefile_save().

◆ savefile_name

const byte savefile_name[4] = "VNLA"
static

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:1026
void wr_randomizer(void)
Write RNG state.
Definition: save.c:272
void wr_ignore(void)
Definition: save.c:497
void wr_stores(void)
Definition: save.c:722
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:964
void wr_player(void)
Definition: save.c:401
void wr_objects(void)
Definition: save.c:958
void wr_traps(void)
Definition: save.c:970
void wr_chunks(void)
Definition: save.c:979
void wr_gear(void)
Definition: save.c:715
void wr_dungeon(void)
Definition: save.c:937
void wr_misc(void)
Definition: save.c:588
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:652
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().

◆ version

u32b version