NetHack minor release checklist items - savefiles

Make some progress on a couple of next minor release checklist
items, hopefully without introducing too many new bugs. This
is just the initial commit, and work continues.

Checklist items:

Savefiles compatible between Windows versions, whether 64-bit
or 32-bit in little-endian field format.

Selection of file formats:
 historical (structlevel saves),
 lendian (little-endian, fieldlevel saves),
 and just for proof-of-concept, ascii fieldlevel saves
 (the ascii is huge! 10x bigger than little-endian).

For the fieldlevel save, all complex data structures recursively
get broken down until until it is one of the simple types that
can't be broken down any further, and that gets when it gets
written to the output file.

New files needed for this build:

hand-coded:
include/sfprocs.h
src/sfbase.c      - really a dispatcher to one of the
                    output/input format routines.
src/sflendian.c   - little-endian output writer/reader.
src/sfascii.c     - ascii text output writer/reader.

auto-coded (generated):
include/sfproto.h
src/sfdata.c

This is just one approach. I'm sure there are countless others
and they have different pros and cons.

For producing the auto-coded files a utility called
universal-ctags, that is actively maintained and evolving,
was used to do all the heavy-lifting of parsing the
NetHack C sources to tabulate the data fields, and store
them in an intermediate file called util/nethack.tags
(not required for building NetHack if you already have a
generated include/sfproto.h and src/sfdata.c)

util/readtags (also not required for building NetHack
itself) will decipher the nethack.tags file and produce
the functions that can deal with the NetHack struct data
fields.

You can obtain the source for universal-ctags by cloning it
from here:
https://github.com/universal-ctags/ctags.git

The combination universal-ctags + util/readtags has been
tried and tested under both Windows and Linux, so it is
not tied to a particular platform.

Note: util/readtags will work only with universal-ctags
output, so other ctags are unlikely to work as-is.
Universal-ctags can be build from source very easily
under Linux, or under Windows using visual studio.
This commit is contained in:
nhmall
2019-06-23 00:11:46 -04:00
parent c9e8ae6323
commit 7054e06e42
45 changed files with 14114 additions and 1280 deletions
+33 -9
View File
@@ -6,6 +6,8 @@
#include "hack.h"
#include "artifact.h"
#include "artilist.h"
#include "sfproto.h"
/*
* Note: both artilist[] and artiexist[] have a dummy element #0,
@@ -76,20 +78,42 @@ init_artifacts()
}
void
save_artifacts(fd)
int fd;
save_artifacts(nhfp)
NHFILE *nhfp;
{
bwrite(fd, (genericptr_t) g.artiexist, sizeof g.artiexist);
bwrite(fd, (genericptr_t) g.artidisco, sizeof g.artidisco);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) g.artiexist, sizeof g.artiexist);
bwrite(nhfp->fd, (genericptr_t) g.artidisco, sizeof g.artidisco);
}
if (nhfp->fieldlevel) {
int i;
for (i = 0; i < (1 + NROFARTIFACTS + 1); ++i)
sfo_boolean(nhfp, &g.artiexist[i], "artifacts", "g.artiexist", 1);
for (i = 0; i < NROFARTIFACTS; ++i)
sfo_xchar(nhfp, &g.artidisco[i], "artifacts", "g.artidisco", 1);
}
}
void
restore_artifacts(fd)
int fd;
restore_artifacts(nhfp)
NHFILE *nhfp;
{
mread(fd, (genericptr_t) g.artiexist, sizeof g.artiexist);
mread(fd, (genericptr_t) g.artidisco, sizeof g.artidisco);
hack_artifacts(); /* redo non-saved special cases */
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) g.artiexist, sizeof g.artiexist);
mread(nhfp->fd, (genericptr_t) g.artidisco, sizeof g.artidisco);
}
if (nhfp->fieldlevel) {
int i;
for (i = 0; i < (1 + NROFARTIFACTS + 1); ++i)
sfi_boolean(nhfp, &g.artiexist[i], "artifacts", "g.artiexist", 1);
for (i = 0; i < NROFARTIFACTS; ++i)
sfi_xchar(nhfp, &g.artidisco[i], "artifacts", "g.artidisco", 1);
}
hack_artifacts(); /* redo non-saved special cases */
}
const char *
+68 -32
View File
@@ -5,6 +5,8 @@
#include "hack.h"
#include "lev.h"
#include "sfproto.h"
#ifdef MFLOPPY
extern long bytes_counted;
@@ -338,7 +340,7 @@ int how;
time_t when;
struct obj *corpse;
{
int fd, x, y;
int x, y;
struct trap *ttmp;
struct monst *mtmp;
struct permonst *mptr;
@@ -346,13 +348,14 @@ struct obj *corpse;
struct cemetery *newbones;
char c, *bonesid;
char whynot[BUFSZ];
NHFILE *nhfp;
/* caller has already checked `can_make_bones()' */
clear_bypasses();
fd = open_bonesfile(&u.uz, &bonesid);
if (fd >= 0) {
(void) nhclose(fd);
nhfp = open_bonesfile(&u.uz, &bonesid);
if (nhfp) {
close_nhfile(nhfp);
if (wizard) {
if (yn("Bones file already exists. Replace it?") == 'y') {
if (delete_bonesfile(&u.uz))
@@ -500,8 +503,8 @@ struct obj *corpse;
if (wizard)
g.level.flags.wizard_bones = 1;
fd = create_bonesfile(&u.uz, &bonesid, whynot);
if (fd < 0) {
nhfp = create_bonesfile(&u.uz, &bonesid, whynot);
if (!nhfp) {
if (wizard)
pline1(whynot);
/* bones file creation problems are silent to the player.
@@ -514,7 +517,10 @@ struct obj *corpse;
#ifdef MFLOPPY /* check whether there is room */
if (iflags.checkspace) {
savelev(fd, ledger_no(&u.uz), COUNT_SAVE);
int savemode = nhfp->mode;
nhfp->mode = COUNTING;
savelev(nhfp, ledger_no(&u.uz));
/* savelev() initializes bytes_counted to 0, so it must come
* first here even though it does not in the real save. the
* resulting extra bflush() at the end of savelev() may increase
@@ -525,31 +531,47 @@ struct obj *corpse;
* this code would have to know the size of the version
* information itself.
*/
store_version(fd);
store_savefileinfo(fd);
bwrite(fd, (genericptr_t) &c, sizeof c);
bwrite(fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nnn */
savefruitchn(fd, COUNT_SAVE);
bflush(fd);
store_version(nhfp);
store_savefileinfo(nhfp);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &c, sizeof c);
bwrite(nhfp->fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nnn */
}
if (nhfp->fieldlevel) {
sfo_char(nhfp, &c, "bones", "bones_count", 1);
sfo_char(nhfp, bonesid, "bones", "bonesid", (int) c);
}
savefruitchn(nhfp);
if (nhfp->structlevel)
bflush(nhfp->fd);
if (bytes_counted > freediskspace(bones)) { /* not enough room */
if (wizard)
pline("Insufficient space to create bones file.");
(void) nhclose(fd);
close_nhfile(nhfp);
cancel_bonesfile();
return;
}
co_false(); /* make sure stuff before savelev() gets written */
nhfp->mode = savemode;
}
#endif /* MFLOPPY */
store_version(fd);
store_savefileinfo(fd);
bwrite(fd, (genericptr_t) &c, sizeof c);
bwrite(fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nnn */
savefruitchn(fd, WRITE_SAVE | FREE_SAVE);
nhfp->mode = WRITING | FREEING;
store_version(nhfp);
store_savefileinfo(nhfp);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &c, sizeof c);
bwrite(nhfp->fd, (genericptr_t) bonesid, (unsigned) c); /* DD.nnn */
savefruitchn(nhfp);
}
if (nhfp->fieldlevel) {
sfo_char(nhfp, &c, "bones", "bones_count", 1);
sfo_char(nhfp, bonesid, "bones", "bonesid", (int) c); /* DD.nnn */
savefruitchn(nhfp);
}
update_mlstmv(); /* update monsters for eventual restoration */
savelev(fd, ledger_no(&u.uz), WRITE_SAVE | FREE_SAVE);
bclose(fd);
savelev(nhfp, ledger_no(&u.uz));
close_nhfile(nhfp);
commit_bonesfile(&u.uz);
compress_bonesfile();
}
@@ -557,8 +579,8 @@ struct obj *corpse;
int
getbones()
{
register int fd;
register int ok;
int ok, i;
NHFILE *nhfp = (NHFILE *) 0;
char c, *bonesid, oldbonesid[40]; /* was [10]; more should be safer */
if (discover) /* save bones files for real games */
@@ -572,11 +594,18 @@ getbones()
return 0;
if (no_bones_level(&u.uz))
return 0;
fd = open_bonesfile(&u.uz, &bonesid);
if (fd < 0)
return 0;
if (validate(fd, g.bones) != 0) {
nhfp = open_bonesfile(&u.uz, &bonesid);
if (!nhfp)
return 0;
if (nhfp && nhfp->structlevel && nhfp->fd < 0)
return 0;
if (nhfp && nhfp->fieldlevel) {
if (nhfp->style.deflt && !nhfp->fpdef)
return 0;
}
if (validate(nhfp, g.bones) != 0) {
if (!wizard)
pline("Discarding unuseable bones; no need to panic...");
ok = FALSE;
@@ -584,13 +613,20 @@ getbones()
ok = TRUE;
if (wizard) {
if (yn("Get bones?") == 'n') {
(void) nhclose(fd);
close_nhfile(nhfp);
compress_bonesfile();
return 0;
}
}
mread(fd, (genericptr_t) &c, sizeof c); /* length incl. '\0' */
mread(fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &c, sizeof c); /* length incl. '\0' */
mread(nhfp->fd, (genericptr_t) oldbonesid, (unsigned) c); /* DD.nnn */
}
if (nhfp->fieldlevel) {
sfi_char(nhfp, &c, "bones", "bones_count", 1); /* length incl. '\0' */
for (i = 0; i < (int) c; ++i)
sfi_char(nhfp, &oldbonesid[i], "bones", "bonesid", 1);
}
if (strcmp(bonesid, oldbonesid) != 0
/* from 3.3.0 through 3.6.0, bones in the quest branch stored
a bogus bonesid in the file; 3.6.1 fixed that, but for
@@ -612,7 +648,7 @@ getbones()
} else {
register struct monst *mtmp;
getlev(fd, 0, 0, TRUE);
getlev(nhfp, 0, 0, TRUE);
/* Note that getlev() now keeps tabs on unique
* monsters such as demon lords, and tracks the
@@ -638,7 +674,7 @@ getbones()
resetobjs(g.level.buriedobjlist, TRUE);
}
}
(void) nhclose(fd);
close_nhfile(nhfp);
sanitize_engravings();
u.uroleplay.numbones++;
+5 -1
View File
@@ -789,6 +789,8 @@ wiz_identify(VOID_ARGS)
STATIC_PTR int
wiz_makemap(VOID_ARGS)
{
NHFILE tmpnhfp;
if (wizard) {
struct monst *mtmp;
boolean was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz);
@@ -835,7 +837,9 @@ wiz_makemap(VOID_ARGS)
keepdogs(TRUE); /* (pets-only; normally we'd be using 'FALSE' here) */
/* discard current level; "saving" is used to release dynamic data */
savelev(-1, ledger_no(&u.uz), FREE_SAVE);
zero_nhfile(&tmpnhfp); /* also sets fd to -1 as desired */
tmpnhfp.mode = FREEING;
savelev(&tmpnhfp, ledger_no(&u.uz));
/* create a new level; various things like bestowing a guardian
angel on Astral or setting off alarm on Ft.Ludios are handled
by goto_level(do.c) so won't occur for replacement levels */
+51 -30
View File
@@ -15,7 +15,7 @@ STATIC_DCL void FDECL(dosinkring, (struct obj *));
STATIC_PTR int FDECL(drop, (struct obj *));
STATIC_PTR int NDECL(wipeoff);
STATIC_DCL int FDECL(menu_drop, (int));
STATIC_DCL int NDECL(currentlevel_rewrite);
STATIC_DCL NHFILE *NDECL(currentlevel_rewrite);
STATIC_DCL void NDECL(final_level);
/* static boolean FDECL(badspot, (XCHAR_P,XCHAR_P)); */
@@ -1114,18 +1114,21 @@ doup()
}
/* check that we can write out the current level */
STATIC_OVL int
STATIC_OVL NHFILE *
currentlevel_rewrite()
{
register int fd;
NHFILE *nhfp;
char whynot[BUFSZ];
#ifdef MFLOPPY
int savemode;
#endif
/* since level change might be a bit slow, flush any buffered screen
* output (like "you fall through a trap door") */
mark_synch();
fd = create_levelfile(ledger_no(&u.uz), whynot);
if (fd < 0) {
nhfp = create_levelfile(ledger_no(&u.uz), whynot);
if (!nhfp) {
/*
* This is not quite impossible: e.g., we may have
* exceeded our quota. If that is the case then we
@@ -1134,35 +1137,39 @@ currentlevel_rewrite()
* writable.
*/
pline1(whynot);
return -1;
return (NHFILE *) 0;
}
#ifdef MFLOPPY
if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
(void) nhclose(fd);
savemode = nhfp->mode;
nhfp->mode = COUNTING;
if (!savelev(nhfp, ledger_no(&u.uz))) {
close_nhfile(nhfp);
delete_levelfile(ledger_no(&u.uz));
pline("NetHack is out of disk space for making levels!");
You("can save, quit, or continue playing.");
return -1;
}
nhfp->mode = savemode;
#endif
return fd;
return nhfp;
}
#ifdef INSURANCE
void
save_currentstate()
{
int fd;
NHFILE *nhfp;
if (flags.ins_chkpt) {
/* write out just-attained level, with pets and everything */
fd = currentlevel_rewrite();
if (fd < 0)
nhfp = currentlevel_rewrite();
if (!nhfp)
return;
bufon(fd);
savelev(fd, ledger_no(&u.uz), WRITE_SAVE);
bclose(fd);
bufon(nhfp->fd);
nhfp->mode = WRITING;
savelev(nhfp,ledger_no(&u.uz));
close_nhfile(nhfp);
}
/* write out non-level state */
@@ -1226,7 +1233,8 @@ goto_level(newlevel, at_stairs, falling, portal)
d_level *newlevel;
boolean at_stairs, falling, portal;
{
int fd, l_idx;
int l_idx, save_mode;
NHFILE *nhfp;
xchar new_ledger;
boolean cant_go_back, great_effort,
up = (depth(newlevel) < depth(&u.uz)),
@@ -1307,8 +1315,8 @@ boolean at_stairs, falling, portal;
if (u.utrap && u.utraptype == TT_BURIEDBALL)
buried_ball_to_punishment(); /* (before we save/leave old level) */
fd = currentlevel_rewrite();
if (fd < 0)
nhfp = currentlevel_rewrite();
if (!nhfp)
return;
/* discard context which applies to the level we're leaving;
@@ -1354,10 +1362,12 @@ boolean at_stairs, falling, portal;
cant_go_back = (newdungeon && In_endgame(newlevel));
if (!cant_go_back) {
update_mlstmv(); /* current monsters are becoming inactive */
bufon(fd); /* use buffered output */
bufon(nhfp->fd); /* use buffered output */
}
savelev(fd, ledger_no(&u.uz),
cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
save_mode = nhfp->mode;
nhfp->mode = cant_go_back ? FREEING : (WRITING | FREEING);
savelev(nhfp, ledger_no(&u.uz));
nhfp->mode = save_mode;
/* air bubbles and clouds are saved in game-state rather than with the
level they're used on; in normal play, you can't leave and return
to any endgame level--bubbles aren't needed once you move to the
@@ -1366,9 +1376,15 @@ boolean at_stairs, falling, portal;
aren't saved with the level and restored upon return (new ones are
created instead), we need to discard them to avoid a memory leak;
so bubbles are now discarded as we leave the level they're used on */
if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz))
save_waterlevel(-1, FREE_SAVE);
bclose(fd);
if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz)) {
NHFILE tmpnhfp;
zero_nhfile(&tmpnhfp);
tmpnhfp.fd = -1;
tmpnhfp.mode = FREEING;
save_waterlevel(&tmpnhfp);
}
close_nhfile(nhfp);
if (cant_go_back) {
/* discard unreachable levels; keep #0 */
for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
@@ -1418,21 +1434,26 @@ boolean at_stairs, falling, portal;
new = TRUE; /* made the level */
} else {
/* returning to previously visited level; reload it */
fd = open_levelfile(new_ledger, whynot);
if (tricked_fileremoved(fd, whynot)) {
nhfp = open_levelfile(new_ledger, whynot);
if (tricked_fileremoved(nhfp, whynot)) {
/* we'll reach here if running in wizard mode */
error("Cannot continue this game.");
}
reseed_random(rn2);
reseed_random(rn2_on_display_rng);
minit(); /* ZEROCOMP */
getlev(fd, g.hackpid, new_ledger, FALSE);
getlev(nhfp, g.hackpid, new_ledger, FALSE);
/* when in wizard mode, it is possible to leave from and return to
any level in the endgame; above, we discarded bubble/cloud info
when leaving Plane of Water or Air so recreate some now */
if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz))
restore_waterlevel(-1);
(void) nhclose(fd);
if (Is_waterlevel(&u.uz) || Is_airlevel(&u.uz)) {
NHFILE tmpnhfp;
zero_nhfile(&tmpnhfp);
tmpnhfp.fd = -1;
restore_waterlevel(&tmpnhfp);
}
close_nhfile(nhfp);
oinit(); /* reassign level dependent obj probabilities */
}
reglyph_darkroom();
+173 -64
View File
@@ -7,6 +7,8 @@
#include "dgn_file.h"
#include "dlb.h"
#include "lev.h"
#include "sfproto.h"
#define DUNGEON_FILE "dungeon"
@@ -56,8 +58,9 @@ STATIC_DCL const char *FDECL(br_string, (int));
STATIC_DCL char FDECL(chr_u_on_lvl, (d_level *));
STATIC_DCL void FDECL(print_branch, (winid, int, int, int, BOOLEAN_P,
struct lchoice *));
STATIC_DCL mapseen *FDECL(load_mapseen, (int));
STATIC_DCL void FDECL(save_mapseen, (int, mapseen *));
/* SAVE2018 */
STATIC_DCL mapseen *FDECL(load_mapseen, (NHFILE *));
STATIC_DCL void FDECL(save_mapseen, (NHFILE *, mapseen *));
STATIC_DCL mapseen *FDECL(find_mapseen, (d_level *));
STATIC_DCL mapseen *FDECL(find_mapseen_by_str, (const char *));
STATIC_DCL void FDECL(print_mapseen, (winid, mapseen *, int, int, BOOLEAN_P));
@@ -129,41 +132,68 @@ dumpit()
/* Save the dungeon structures. */
void
save_dungeon(fd, perform_write, free_data)
int fd;
save_dungeon(nhfp, perform_write, free_data)
NHFILE *nhfp;
boolean perform_write, free_data;
{
int i, count;
branch *curr, *next;
mapseen *curr_ms, *next_ms;
int count;
if (perform_write) {
bwrite(fd, (genericptr_t) &g.n_dgns, sizeof g.n_dgns);
bwrite(fd, (genericptr_t) g.dungeons,
sizeof(dungeon) * (unsigned) g.n_dgns);
bwrite(fd, (genericptr_t) &g.dungeon_topology, sizeof g.dungeon_topology);
bwrite(fd, (genericptr_t) g.tune, sizeof tune);
if(nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &g.n_dgns, sizeof g.n_dgns);
bwrite(nhfp->fd, (genericptr_t) g.dungeons,
sizeof(dungeon) * (unsigned) g.n_dgns);
bwrite(nhfp->fd, (genericptr_t) &g.dungeon_topology, sizeof g.dungeon_topology);
bwrite(nhfp->fd, (genericptr_t) g.tune, sizeof tune);
}
if (nhfp->fieldlevel) {
sfo_int(nhfp, &g.n_dgns, "dungeon", "dungeon_count", 1);
for (i = 0; i < g.n_dgns; ++i)
sfo_dungeon(nhfp, &g.dungeons[i], "dungeon", "dungeon", 1);
sfo_dgn_topology(nhfp, &g.dungeon_topology, "dungeon", "g.dungeon_topology", 1);
for (i = 0; i < sizeof tune; ++i)
sfo_char(nhfp, &g.tune[i], "dungeon", "tune", 1);
}
for (count = 0, curr = g.branches; curr; curr = curr->next)
count++;
bwrite(fd, (genericptr_t) &count, sizeof(count));
for (curr = g.branches; curr; curr = curr->next)
bwrite(fd, (genericptr_t) curr, sizeof(branch));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &count, sizeof(count));
if (nhfp->fieldlevel)
sfo_int(nhfp, &count, "dungeon", "branch_count", 1);
for (curr = g.branches; curr; curr = curr->next) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) curr, sizeof(branch));
if (nhfp->fieldlevel)
sfo_branch(nhfp, curr, "dungeon", "branch", 1);
}
count = maxledgerno();
bwrite(fd, (genericptr_t) &count, sizeof count);
bwrite(fd, (genericptr_t) g.level_info,
(unsigned) count * sizeof(struct linfo));
bwrite(fd, (genericptr_t) &g.inv_pos, sizeof g.inv_pos);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &count, sizeof count);
bwrite(nhfp->fd, (genericptr_t) g.level_info,
(unsigned) count * sizeof(struct linfo));
bwrite(nhfp->fd, (genericptr_t) &g.inv_pos, sizeof g.inv_pos);
}
if (nhfp->fieldlevel) {
sfo_int(nhfp, &count, "dungeon", "level_info_count", 1);
for (i = 0; i < count; ++i)
sfo_linfo(nhfp, &g.level_info[i], "dungeon", "g.level_info", 1);
sfo_nhcoord(nhfp, &g.inv_pos, "dungeon", "g.inv_pos", 1);
}
for (count = 0, curr_ms = g.mapseenchn; curr_ms;
curr_ms = curr_ms->next)
count++;
bwrite(fd, (genericptr_t) &count, sizeof(count));
for (curr_ms = g.mapseenchn; curr_ms; curr_ms = curr_ms->next)
save_mapseen(fd, curr_ms);
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &count, sizeof(count));
if (nhfp->fieldlevel)
sfo_int(nhfp, &count, "dungeon", "mapseen_count", 1);
for (curr_ms = g.mapseenchn; curr_ms; curr_ms = curr_ms->next) {
save_mapseen(nhfp, curr_ms);
}
}
if (free_data) {
@@ -177,7 +207,7 @@ boolean perform_write, free_data;
if (curr_ms->custom)
free((genericptr_t) curr_ms->custom);
if (curr_ms->final_resting_place)
savecemetery(fd, FREE_SAVE, &curr_ms->final_resting_place);
savecemetery(nhfp, &curr_ms->final_resting_place);
free((genericptr_t) curr_ms);
}
g.mapseenchn = 0;
@@ -186,24 +216,40 @@ boolean perform_write, free_data;
/* Restore the dungeon structures. */
void
restore_dungeon(fd)
int fd;
restore_dungeon(nhfp)
NHFILE *nhfp;
{
branch *curr, *last;
int count, i;
mapseen *curr_ms, *last_ms;
mread(fd, (genericptr_t) &g.n_dgns, sizeof(g.n_dgns));
mread(fd, (genericptr_t) g.dungeons, sizeof(dungeon) * (unsigned) g.n_dgns);
mread(fd, (genericptr_t) &g.dungeon_topology, sizeof g.dungeon_topology);
mread(fd, (genericptr_t) g.tune, sizeof tune);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &g.n_dgns, sizeof(g.n_dgns));
mread(nhfp->fd, (genericptr_t) g.dungeons, sizeof(dungeon) * (unsigned) g.n_dgns);
mread(nhfp->fd, (genericptr_t) &g.dungeon_topology, sizeof g.dungeon_topology);
mread(nhfp->fd, (genericptr_t) g.tune, sizeof tune);
}
if (nhfp->fieldlevel) {
sfi_int(nhfp, &g.n_dgns, "dungeon", "dungeon_count", 1);
for (i = 0; i < g.n_dgns; ++i)
sfi_dungeon(nhfp, &g.dungeons[i], "dungeon", "dungeon", 1);
sfi_dgn_topology(nhfp, &g.dungeon_topology, "dungeon", "g.dungeon_topology", 1);
for (i = 0; i < sizeof tune; ++i)
sfi_char(nhfp, &g.tune[i], "dungeon", "tune", 1);
}
last = g.branches = (branch *) 0;
mread(fd, (genericptr_t) &count, sizeof(count));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &count, sizeof(count));
if (nhfp->fieldlevel)
sfi_int(nhfp, &count, "dungeon", "branch_count", 1);
for (i = 0; i < count; i++) {
curr = (branch *) alloc(sizeof(branch));
mread(fd, (genericptr_t) curr, sizeof(branch));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) curr, sizeof(branch));
if (nhfp->fieldlevel)
sfi_branch(nhfp, curr, "dungeon", "branch", 1);
curr->next = (branch *) 0;
if (last)
last->next = curr;
@@ -212,18 +258,33 @@ int fd;
last = curr;
}
mread(fd, (genericptr_t) &count, sizeof(count));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &count, sizeof(count));
if (nhfp->fieldlevel)
sfi_int(nhfp, &count, "dungeon", "level_info_count", 1);
if (count >= MAXLINFO)
panic("level information count larger (%d) than allocated size",
count);
mread(fd, (genericptr_t) g.level_info,
(unsigned) count * sizeof(struct linfo));
mread(fd, (genericptr_t) &g.inv_pos, sizeof g.inv_pos);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) g.level_info,
(unsigned) count * sizeof(struct linfo));
if (nhfp->fieldlevel)
for (i = 0; i < count; ++i)
sfi_linfo(nhfp, &g.level_info[i], "dungeon", "g.level_info", 1);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &g.inv_pos, sizeof g.inv_pos);
mread(nhfp->fd, (genericptr_t) &count, sizeof(count));
}
if (nhfp->fieldlevel) {
sfi_nhcoord(nhfp, &g.inv_pos, "dungeon", "inv_pos", 1);
sfi_int(nhfp, &count, "dungeon", "mapseen_count", 1);
}
mread(fd, (genericptr_t) &count, sizeof(count));
last_ms = (mapseen *) 0;
for (i = 0; i < count; i++) {
curr_ms = load_mapseen(fd);
curr_ms = load_mapseen(nhfp);
curr_ms->next = (mapseen *) 0;
if (last_ms)
last_ms->next = curr_ms;
@@ -752,7 +813,7 @@ init_dungeons()
*/
if (iflags.window_inited)
clear_nhwindow(WIN_MAP);
if (!check_version(&vers_info, DUNGEON_FILE, TRUE))
if (!check_version(&vers_info, DUNGEON_FILE, TRUE, UTD_CHECKSIZES))
panic("Dungeon description not valid.");
/*
@@ -2187,58 +2248,106 @@ int ledger_num;
}
STATIC_OVL void
save_mapseen(fd, mptr)
int fd;
save_mapseen(nhfp, mptr)
NHFILE *nhfp;
mapseen *mptr;
{
branch *curr;
int brindx;
int i, brindx;
for (brindx = 0, curr = g.branches; curr; curr = curr->next, ++brindx)
if (curr == mptr->br)
break;
bwrite(fd, (genericptr_t) &brindx, sizeof brindx);
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &brindx, sizeof brindx);
if (nhfp->fieldlevel)
sfo_int(nhfp, &brindx, "mapseen", "branch_index", 1);
bwrite(fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
bwrite(fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
bwrite(fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
bwrite(fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
if (mptr->custom_lth)
bwrite(fd, (genericptr_t) mptr->custom, mptr->custom_lth);
bwrite(fd, (genericptr_t) mptr->msrooms, sizeof mptr->msrooms);
savecemetery(fd, WRITE_SAVE, &mptr->final_resting_place);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &mptr->lev, sizeof mptr->lev);
bwrite(nhfp->fd, (genericptr_t) &mptr->feat, sizeof mptr->feat);
bwrite(nhfp->fd, (genericptr_t) &mptr->flags, sizeof mptr->flags);
bwrite(nhfp->fd, (genericptr_t) &mptr->custom_lth, sizeof mptr->custom_lth);
}
if (nhfp->fieldlevel) {
sfo_d_level(nhfp, &mptr->lev, "mapseen", "d_level", 1);
sfo_mapseen_feat(nhfp, &mptr->feat, "mapseen", "feat", 1);
sfo_mapseen_flags(nhfp, &mptr->flags, "mapseen", "flags", 1);
sfo_unsigned(nhfp, &mptr->custom_lth, "mapseen", "custom_lth", 1);
}
if (mptr->custom_lth) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) mptr->custom, mptr->custom_lth);
}
if (nhfp->fieldlevel) {
for (i = 0; i < (int) mptr->custom_lth; ++i)
sfo_char(nhfp, &mptr->custom[i], "mapseen", "custom", 1);
}
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &mptr->msrooms, sizeof mptr->msrooms);
}
if (nhfp->fieldlevel) {
for (i = 0; i < ((MAXNROFROOMS + 1) * 2); ++i)
sfo_mapseen_rooms(nhfp, &mptr->msrooms[i], "mapseen", "msrooms", 1);
}
savecemetery(nhfp, &mptr->final_resting_place);
}
STATIC_OVL mapseen *
load_mapseen(fd)
int fd;
load_mapseen(nhfp)
NHFILE *nhfp;
{
int branchnum, brindx;
int i, branchnum, brindx;
mapseen *load;
branch *curr;
load = (mapseen *) alloc(sizeof *load);
mread(fd, (genericptr_t) &branchnum, sizeof branchnum);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &branchnum, sizeof branchnum);
if (nhfp->fieldlevel)
sfi_int(nhfp, &branchnum, "mapseen", "branch_index", 1);
for (brindx = 0, curr = g.branches; curr; curr = curr->next, ++brindx)
if (brindx == branchnum)
break;
load->br = curr;
mread(fd, (genericptr_t) &load->lev, sizeof load->lev);
mread(fd, (genericptr_t) &load->feat, sizeof load->feat);
mread(fd, (genericptr_t) &load->flags, sizeof load->flags);
mread(fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &load->lev, sizeof load->lev);
mread(nhfp->fd, (genericptr_t) &load->feat, sizeof load->feat);
mread(nhfp->fd, (genericptr_t) &load->flags, sizeof load->flags);
mread(nhfp->fd, (genericptr_t) &load->custom_lth, sizeof load->custom_lth);
}
if (nhfp->fieldlevel) {
sfi_d_level(nhfp, &load->lev, "mapseen", "d_level", 1);
sfi_mapseen_feat(nhfp, &load->feat, "mapseen", "feat", 1);
sfi_mapseen_flags(nhfp, &load->flags, "mapseen", "flags", 1);
sfi_unsigned(nhfp, &load->custom_lth, "mapseen", "custom_lth", 1);
}
if (load->custom_lth) {
/* length doesn't include terminator (which isn't saved & restored) */
load->custom = (char *) alloc(load->custom_lth + 1);
mread(fd, (genericptr_t) load->custom, load->custom_lth);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) load->custom, load->custom_lth);
}
if (nhfp->fieldlevel) {
for (i = 0; i < (int) load->custom_lth; ++i)
sfi_char(nhfp, &load->custom[i], "mapseen", "custom", 1);
}
load->custom[load->custom_lth] = '\0';
} else
load->custom = 0;
mread(fd, (genericptr_t) load->msrooms, sizeof load->msrooms);
restcemetery(fd, &load->final_resting_place);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &load->msrooms, sizeof load->msrooms);
}
if (nhfp->fieldlevel) {
for (i = 0; i < ((MAXNROFROOMS + 1) * 2); ++i)
sfi_mapseen_rooms(nhfp, &load->msrooms[i], "mapseen", "msrooms", 1);
}
restcemetery(nhfp, &load->final_resting_place);
return load;
}
+16 -9
View File
@@ -15,6 +15,8 @@
#include <limits.h>
#endif
#include "dlb.h"
#include "sfproto.h"
/* add b to long a, convert wraparound to max value */
#define nowrap_add(a, b) (a = ((a + b) < 0 ? LONG_MAX : (a + b)))
@@ -2131,18 +2133,20 @@ struct kinfo *kptr;
}
void
save_killers(fd, mode)
int fd;
int mode;
save_killers(nhfp)
NHFILE *nhfp;
{
struct kinfo *kptr;
if (perform_bwrite(mode)) {
if (perform_bwrite(nhfp)) {
for (kptr = &g.killer; kptr != (struct kinfo *) 0; kptr = kptr->next) {
bwrite(fd, (genericptr_t) kptr, sizeof (struct kinfo));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t)kptr, sizeof(struct kinfo));
if (nhfp->fieldlevel)
sfo_kinfo(nhfp, kptr, "killers", "kinfo", 1);
}
}
if (release_data(mode)) {
if (release_data(nhfp)) {
while (g.killer.next) {
kptr = g.killer.next->next;
free((genericptr_t) g.killer.next);
@@ -2152,13 +2156,16 @@ int mode;
}
void
restore_killers(fd)
int fd;
restore_killers(nhfp)
NHFILE *nhfp;
{
struct kinfo *kptr;
for (kptr = &g.killer; kptr != (struct kinfo *) 0; kptr = kptr->next) {
mread(fd, (genericptr_t) kptr, sizeof (struct kinfo));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t)kptr, sizeof(struct kinfo));
if (nhfp->fieldlevel)
sfi_kinfo(nhfp, kptr, "killers", "kinfo", 1);
if (kptr->next) {
kptr->next = (struct kinfo *) alloc(sizeof (struct kinfo));
}
+40 -17
View File
@@ -5,6 +5,8 @@
#include "hack.h"
#include "lev.h"
#include "sfproto.h"
STATIC_VAR NEARDATA struct engr *head_engr;
STATIC_DCL const char *NDECL(blengr);
@@ -1173,48 +1175,69 @@ sanitize_engravings()
}
void
save_engravings(fd, mode)
int fd, mode;
save_engravings(nhfp)
NHFILE *nhfp;
{
struct engr *ep, *ep2;
unsigned no_more_engr = 0;
for (ep = head_engr; ep; ep = ep2) {
ep2 = ep->nxt_engr;
if (ep->engr_lth && ep->engr_txt[0] && perform_bwrite(mode)) {
bwrite(fd, (genericptr_t) &ep->engr_lth, sizeof ep->engr_lth);
bwrite(fd, (genericptr_t) ep, sizeof (struct engr) + ep->engr_lth);
if (ep->engr_lth && ep->engr_txt[0] && perform_bwrite(nhfp)) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth));
bwrite(nhfp->fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth);
}
if (nhfp->fieldlevel) {
sfo_unsigned(nhfp, &(ep->engr_lth), "engravings", "engr_lth", 1);
sfo_engr(nhfp, ep, "engravings", "engr", 1);
sfo_str(nhfp, ep->engr_txt, "engravings", "engr_txt", ep->engr_lth);
}
}
if (release_data(mode))
if (release_data(nhfp))
dealloc_engr(ep);
}
if (perform_bwrite(mode))
bwrite(fd, (genericptr_t) &no_more_engr, sizeof no_more_engr);
if (release_data(mode))
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t)&no_more_engr, sizeof no_more_engr);
if (nhfp->fieldlevel)
sfo_unsigned(nhfp, &no_more_engr, "engravings", "engr_lth", 1);
}
if (release_data(nhfp))
head_engr = 0;
}
void
rest_engravings(fd)
int fd;
rest_engravings(nhfp)
NHFILE *nhfp;
{
struct engr *ep;
unsigned lth;
head_engr = 0;
while (1) {
mread(fd, (genericptr_t) &lth, sizeof lth);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &lth, sizeof(unsigned));
if (nhfp->fieldlevel)
sfi_unsigned(nhfp, &lth, "engravings", "engr_lth", 1);
if (lth == 0)
return;
ep = newengr(lth);
mread(fd, (genericptr_t) ep, sizeof (struct engr) + lth);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) ep, sizeof(struct engr) + lth);
}
if (nhfp->fieldlevel) {
sfi_engr(nhfp, ep, "engravings", "engr", 1);
ep->engr_txt = (char *) (ep + 1);
sfi_str(nhfp, ep->engr_txt, "engravings", "engr_txt", lth);
}
ep->nxt_engr = head_engr;
head_engr = ep;
ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */
/* Mark as finished for bones levels -- no problem for
ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */
/* mark as finished for bones levels -- no problem for
* normal levels as the player must have finished engraving
* to be able to move again.
*/
* to be able to move again */
ep->engr_time = g.moves;
}
}
+538 -148
View File
File diff suppressed because it is too large Load Diff
+58 -25
View File
@@ -4,6 +4,8 @@
#include "hack.h"
#include "lev.h" /* for checking save modes */
#include "sfproto.h"
/*
* Mobile light sources.
@@ -42,25 +44,27 @@
#define LSF_SHOW 0x1 /* display the light source */
#define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */
STATIC_DCL void FDECL(write_ls, (int, light_source *));
STATIC_DCL int FDECL(maybe_write_ls, (int, int, BOOLEAN_P));
/* SAVE2018 */
STATIC_DCL void FDECL(write_ls, (NHFILE *, light_source *));
STATIC_DCL int FDECL(maybe_write_ls, (NHFILE *, int, BOOLEAN_P));
/* imported from vision.c, for small circles */
extern char circle_data[];
extern char circle_start[];
/* Create a new light source. */
void
new_light_source(x, y, range, type, id)
xchar x, y;
int range, type;
anything *id;
xchar x, y;
int range, type;
anything *id;
{
light_source *ls;
if (range > MAX_RADIUS || range < 1) {
impossible("new_light_source: illegal range %d", range);
return;
impossible("new_light_source: illegal range %d", range);
return;
}
ls = (light_source *) alloc(sizeof *ls);
@@ -311,22 +315,28 @@ unsigned fmflags;
/* Save all light sources of the given range. */
void
save_light_sources(fd, mode, range)
int fd, mode, range;
save_light_sources(nhfp, range)
NHFILE *nhfp;
int range;
{
int count, actual, is_global;
light_source **prev, *curr;
if (perform_bwrite(mode)) {
count = maybe_write_ls(fd, range, FALSE);
bwrite(fd, (genericptr_t) &count, sizeof count);
actual = maybe_write_ls(fd, range, TRUE);
if (perform_bwrite(nhfp)) {
count = maybe_write_ls(nhfp, range, FALSE);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &count, sizeof count);
}
if (nhfp->fieldlevel) {
sfo_int(nhfp, &count, "lightsources", "lightsource_count", 1);
}
actual = maybe_write_ls(nhfp, range, TRUE);
if (actual != count)
panic("counted %d light sources, wrote %d! [range=%d]", count,
actual, range);
}
if (release_data(mode)) {
if (release_data(nhfp)) {
for (prev = &g.light_base; (curr = *prev) != 0;) {
if (!curr->id.a_monst) {
impossible("save_light_sources: no id! [range=%d]", range);
@@ -361,18 +371,24 @@ int fd, mode, range;
* pointers.
*/
void
restore_light_sources(fd)
int fd;
restore_light_sources(nhfp)
NHFILE *nhfp;
{
int count;
light_source *ls;
/* restore elements */
mread(fd, (genericptr_t) &count, sizeof count);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &count, sizeof count);
if (nhfp->fieldlevel)
sfi_int(nhfp, &count, "lightsources", "lightsource_count", 1);
while (count-- > 0) {
ls = (light_source *) alloc(sizeof(light_source));
mread(fd, (genericptr_t) ls, sizeof(light_source));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) ls, sizeof(light_source));
if (nhfp->fieldlevel)
sfi_ls_t(nhfp, ls, "lightsources", "lightsource", 1);
ls->next = g.light_base;
g.light_base = ls;
}
@@ -430,14 +446,17 @@ boolean ghostly;
}
}
/* SAVE2018 */
/*
* Part of the light source save routine. Count up the number of light
* sources that would be written. If write_it is true, actually write
* the light source out.
*/
STATIC_OVL int
maybe_write_ls(fd, range, write_it)
int fd, range;
maybe_write_ls(nhfp, range, write_it)
NHFILE *nhfp;
int range;
boolean write_it;
{
int count = 0, is_global;
@@ -465,7 +484,7 @@ boolean write_it;
if (is_global ^ (range == RANGE_LEVEL)) {
count++;
if (write_it)
write_ls(fd, ls);
write_ls(nhfp, ls);
}
}
@@ -499,11 +518,19 @@ light_sources_sanity_check()
}
}
/* Write a light source structure to disk. */
/* SAVE2018 */
#if 0
STATIC_OVL void
write_ls(fd, ls)
int fd;
light_source *ls;
#endif /* 0 */
/* Write a light source structure to disk. */
STATIC_OVL void
write_ls(nhfp, ls)
NHFILE *nhfp;
light_source *ls;
{
anything arg_save;
struct obj *otmp;
@@ -511,7 +538,10 @@ light_source *ls;
if (ls->type == LS_OBJECT || ls->type == LS_MONSTER) {
if (ls->flags & LSF_NEEDS_FIXUP) {
bwrite(fd, (genericptr_t) ls, sizeof(light_source));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) ls, sizeof(light_source));
if (nhfp->fieldlevel)
sfo_ls_t(nhfp, ls, "lightsources", "lightsource", 1);
} else {
/* replace object pointer with id for write, then put back */
arg_save = ls->id;
@@ -531,7 +561,10 @@ light_source *ls;
ls->id.a_uint);
}
ls->flags |= LSF_NEEDS_FIXUP;
bwrite(fd, (genericptr_t) ls, sizeof(light_source));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) ls, sizeof(light_source));
if (nhfp->fieldlevel)
sfo_ls_t(nhfp, ls, "lightsources", "lightsource", 1);
ls->id = arg_save;
ls->flags &= ~LSF_NEEDS_FIXUP;
}
+56 -29
View File
@@ -6,6 +6,8 @@
#include "hack.h"
#include "sp_lev.h"
#include "lev.h" /* save & restore info */
#include "sfproto.h"
STATIC_DCL int FDECL(iswall, (int, int));
STATIC_DCL int FDECL(iswall_or_stone, (int, int));
@@ -1558,33 +1560,46 @@ water_friction()
}
void
save_waterlevel(fd, mode)
int fd, mode;
save_waterlevel(nhfp)
NHFILE *nhfp;
{
struct bubble *b;
if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz))
return;
if (perform_bwrite(mode)) {
if (perform_bwrite(nhfp)) {
int n = 0;
for (b = g.bbubbles; b; b = b->next)
++n;
bwrite(fd, (genericptr_t) &n, sizeof n);
bwrite(fd, (genericptr_t) &g.xmin, sizeof g.xmin);
bwrite(fd, (genericptr_t) &g.ymin, sizeof g.ymin);
bwrite(fd, (genericptr_t) &g.xmax, sizeof g.xmax);
bwrite(fd, (genericptr_t) &g.ymax, sizeof g.ymax);
for (b = g.bbubbles; b; b = b->next)
bwrite(fd, (genericptr_t) b, sizeof *b);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &n, sizeof(int));
bwrite(nhfp->fd, (genericptr_t) &g.xmin, sizeof(int));
bwrite(nhfp->fd, (genericptr_t) &g.ymin, sizeof(int));
bwrite(nhfp->fd, (genericptr_t) &g.xmax, sizeof(int));
bwrite(nhfp->fd, (genericptr_t) &g.ymax, sizeof(int));
}
if (nhfp->fieldlevel) {
sfo_int(nhfp, &n, "waterlevel", "bubble_count", 1);
sfo_int(nhfp, &g.xmin, "waterlevel", "g.xmin", 1);
sfo_int(nhfp, &g.ymin, "waterlevel", "g.ymin", 1);
sfo_int(nhfp, &g.xmax, "waterlevel", "g.xmax", 1);
sfo_int(nhfp, &g.ymax, "waterlevel", "g.ymax", 1);
}
for (b = g.bbubbles; b; b = b->next) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) b, sizeof(struct bubble));
if (nhfp->fieldlevel)
sfo_bubble(nhfp, b, "waterlevel", "bubble", 1);
}
}
if (release_data(mode))
if (release_data(nhfp))
unsetup_waterlevel();
}
void
restore_waterlevel(fd)
int fd;
restore_waterlevel(nhfp)
NHFILE *nhfp;
{
struct bubble *b = (struct bubble *) 0, *btmp;
int i, n;
@@ -1592,7 +1607,7 @@ int fd;
if (!Is_waterlevel(&u.uz) && !Is_airlevel(&u.uz))
return;
if (fd == -1) { /* special handling for restore in goto_level() */
if (nhfp->fd == -1) { /* special handling for restore in goto_level() */
if (!wizard)
impossible("restore_waterlevel: returning to %s?",
Is_waterlevel(&u.uz) ? "Water" : "Air");
@@ -1601,23 +1616,35 @@ int fd;
}
set_wportal();
mread(fd, (genericptr_t) &n, sizeof n);
mread(fd, (genericptr_t) &g.xmin, sizeof g.xmin);
mread(fd, (genericptr_t) &g.ymin, sizeof g.ymin);
mread(fd, (genericptr_t) &g.xmax, sizeof g.xmax);
mread(fd, (genericptr_t) &g.ymax, sizeof g.ymax);
if (nhfp->structlevel) {
mread(nhfp->fd,(genericptr_t)&n,sizeof(int));
mread(nhfp->fd,(genericptr_t)&g.xmin,sizeof(int));
mread(nhfp->fd,(genericptr_t)&g.ymin,sizeof(int));
mread(nhfp->fd,(genericptr_t)&g.xmax,sizeof(int));
mread(nhfp->fd,(genericptr_t)&g.ymax,sizeof(int));
}
if (nhfp->fieldlevel) {
sfi_int(nhfp, &n, "waterlevel", "bubble_count", 1);
sfi_int(nhfp, &g.xmin, "waterlevel", "g.xmin", 1);
sfi_int(nhfp, &g.ymin, "waterlevel", "g.ymin", 1);
sfi_int(nhfp, &g.xmax, "waterlevel", "g.xmax", 1);
sfi_int(nhfp, &g.ymax, "waterlevel", "g.ymax", 1);
}
for (i = 0; i < n; i++) {
btmp = b;
b = (struct bubble *) alloc(sizeof *b);
mread(fd, (genericptr_t) b, sizeof *b);
if (g.bbubbles) {
btmp->next = b;
b->prev = btmp;
} else {
g.bbubbles = b;
b->prev = (struct bubble *) 0;
}
mv_bubble(b, 0, 0, TRUE);
b = (struct bubble *) alloc(sizeof(struct bubble));
if (nhfp->structlevel)
mread(nhfp->fd,(genericptr_t) b, sizeof(struct bubble));
if (nhfp->fieldlevel)
sfi_bubble(nhfp, b, "waterlevel", "bubble", 1);
if (g.bbubbles) {
btmp->next = b;
b->prev = btmp;
} else {
g.bbubbles = b;
b->prev = (struct bubble *) 0;
}
mv_bubble(b, 0, 0, TRUE);
}
g.ebubbles = b;
b->next = (struct bubble *) 0;
+39 -19
View File
@@ -16,6 +16,8 @@
*/
#include "hack.h"
#include "sfproto.h"
STATIC_DCL boolean FDECL(isbig, (struct mkroom *));
STATIC_DCL struct mkroom *FDECL(pick_room, (BOOLEAN_P));
@@ -24,8 +26,11 @@ STATIC_DCL void NDECL(mktemple);
STATIC_DCL coord *FDECL(shrine_pos, (int));
STATIC_DCL struct permonst *NDECL(morguemon);
STATIC_DCL struct permonst *NDECL(squadmon);
STATIC_DCL void FDECL(save_room, (int, struct mkroom *));
STATIC_DCL void FDECL(rest_room, (int, struct mkroom *));
/* SAVE2018 */
/* STATIC_DCL void FDECL(save_room, (int,struct mkroom *)); */
/* STATIC_DCL void FDECL(rest_room, (int,struct mkroom *)); */
STATIC_DCL void FDECL(save_room, (NHFILE *, struct mkroom *));
STATIC_DCL void FDECL(rest_room, (NHFILE *, struct mkroom *));
#define sq(x) ((x) * (x))
@@ -796,8 +801,8 @@ gotone:
* (if any).
*/
STATIC_OVL void
save_room(fd, r)
int fd;
save_room(nhfp, r)
NHFILE *nhfp;
struct mkroom *r;
{
short i;
@@ -807,37 +812,48 @@ struct mkroom *r;
* of writing the whole structure. That is I should not write
* the g.subrooms pointers, but who cares ?
*/
bwrite(fd, (genericptr_t) r, sizeof (struct mkroom));
for (i = 0; i < r->nsubrooms; i++)
save_room(fd, r->sbrooms[i]);
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) r, sizeof (struct mkroom));
if (nhfp->fieldlevel)
sfo_mkroom(nhfp, r, "room", "mkroom", 1);
for (i = 0; i < r->nsubrooms; i++) {
save_room(nhfp, r->sbrooms[i]);
}
}
/*
* save_rooms : Save all the rooms on disk!
*/
void
save_rooms(fd)
int fd;
save_rooms(nhfp)
NHFILE *nhfp;
{
short i;
/* First, write the number of rooms */
bwrite(fd, (genericptr_t) &g.nroom, sizeof(g.nroom));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &g.nroom, sizeof(g.nroom));
if (nhfp->fieldlevel)
sfo_int(nhfp, &g.nroom, "room", "g.nroom", 1);
for (i = 0; i < g.nroom; i++)
save_room(fd, &g.rooms[i]);
save_room(nhfp, &g.rooms[i]);
}
STATIC_OVL void
rest_room(fd, r)
int fd;
rest_room(nhfp, r)
NHFILE *nhfp;
struct mkroom *r;
{
short i;
mread(fd, (genericptr_t) r, sizeof(struct mkroom));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) r, sizeof(struct mkroom));
if (nhfp->fieldlevel)
sfi_mkroom(nhfp, r, "room", "mkroom", 1);
for (i = 0; i < r->nsubrooms; i++) {
r->sbrooms[i] = &g.subrooms[g.nsubroom];
rest_room(fd, &g.subrooms[g.nsubroom]);
rest_room(nhfp, &g.subrooms[g.nsubroom]);
g.subrooms[g.nsubroom++].resident = (struct monst *) 0;
}
}
@@ -847,15 +863,19 @@ struct mkroom *r;
* the disk.
*/
void
rest_rooms(fd)
int fd;
rest_rooms(nhfp)
NHFILE *nhfp;
{
short i;
mread(fd, (genericptr_t) &g.nroom, sizeof(g.nroom));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.nroom, sizeof(g.nroom));
if (nhfp->fieldlevel)
sfi_int(nhfp, &g.nroom, "room", "g.nroom", 1);
g.nsubroom = 0;
for (i = 0; i < g.nroom; i++) {
rest_room(fd, &g.rooms[i]);
rest_room(nhfp, &g.rooms[i]);
g.rooms[i].resident = (struct monst *) 0;
}
g.rooms[g.nroom].hx = -1; /* restore ending flags */
+65 -22
View File
@@ -5,6 +5,8 @@
#include "hack.h"
#include "lev.h" /* save & restore info */
#include "sfproto.h"
STATIC_DCL void FDECL(setgemprobs, (d_level *));
STATIC_DCL void FDECL(shuffle, (int, int, BOOLEAN_P));
@@ -286,29 +288,46 @@ oinit()
}
void
savenames(fd, mode)
int fd, mode;
savenames(nhfp)
NHFILE *nhfp;
{
register int i;
int i, j;
unsigned int len;
if (perform_bwrite(mode)) {
bwrite(fd, (genericptr_t) g.bases, sizeof g.bases);
bwrite(fd, (genericptr_t) g.disco, sizeof g.disco);
bwrite(fd, (genericptr_t) objects,
sizeof(struct objclass) * NUM_OBJECTS);
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t)g.bases, sizeof g.bases);
bwrite(nhfp->fd, (genericptr_t)g.disco, sizeof g.disco);
bwrite(nhfp->fd, (genericptr_t)objects,
sizeof(struct objclass) * NUM_OBJECTS);
}
if (nhfp->fieldlevel) {
for (i = 0; i < MAXOCLASSES; ++i)
sfo_int(nhfp, &g.bases[i], "names", "g.bases", 1);
for (i = 0; i < NUM_OBJECTS; ++i)
sfo_short(nhfp, &g.disco[i], "names", "g.disco", 1);
for (i = 0; i < NUM_OBJECTS; ++i)
sfo_objclass(nhfp, &objects[i], "names", "objclass", 1);
}
}
/* as long as we use only one version of Hack we
need not save oc_name and oc_descr, but we must save
oc_uname for all objects */
for (i = 0; i < NUM_OBJECTS; i++)
if (objects[i].oc_uname) {
if (perform_bwrite(mode)) {
if (perform_bwrite(nhfp)) {
len = strlen(objects[i].oc_uname) + 1;
bwrite(fd, (genericptr_t) &len, sizeof len);
bwrite(fd, (genericptr_t) objects[i].oc_uname, len);
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t)&len, sizeof len);
bwrite(nhfp->fd, (genericptr_t)objects[i].oc_uname, len);
}
if (nhfp->fieldlevel) {
sfo_unsigned(nhfp, &len, "names", "len", 1);
for (j = 0; (unsigned) j < len; ++j)
sfo_char(nhfp, &objects[i].oc_uname[j], "names", "oc_uname", 1);
}
}
if (release_data(mode)) {
if (release_data(nhfp)) {
free((genericptr_t) objects[i].oc_uname);
objects[i].oc_uname = 0;
}
@@ -316,21 +335,45 @@ int fd, mode;
}
void
restnames(fd)
register int fd;
restnames(nhfp)
NHFILE *nhfp;
{
register int i;
int i, j;
unsigned int len;
mread(fd, (genericptr_t)g.bases, sizeof g.bases);
mread(fd, (genericptr_t) g.disco, sizeof g.disco);
mread(fd, (genericptr_t) objects, sizeof(struct objclass) * NUM_OBJECTS);
for (i = 0; i < NUM_OBJECTS; i++)
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) g.bases, sizeof g.bases);
mread(nhfp->fd, (genericptr_t) g.disco, sizeof g.disco);
mread(nhfp->fd, (genericptr_t) objects,
sizeof(struct objclass) * NUM_OBJECTS);
}
if (nhfp->fieldlevel) {
for (i = 0; i < MAXOCLASSES; ++i)
sfi_int(nhfp, &g.bases[i], "names", "g.bases", 1);
for (i = 0; i < NUM_OBJECTS; ++i)
sfi_short(nhfp, &g.disco[i], "names", "g.disco", 1);
for (i = 0; i < NUM_OBJECTS; ++i)
sfi_objclass(nhfp, &objects[i], "names", "objclass", 1);
}
for (i = 0; i < NUM_OBJECTS; i++) {
if (objects[i].oc_uname) {
mread(fd, (genericptr_t) &len, sizeof len);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &len, sizeof len);
}
if (nhfp->fieldlevel) {
sfi_unsigned(nhfp, &len, "names", "len", 1);
}
objects[i].oc_uname = (char *) alloc(len);
mread(fd, (genericptr_t) objects[i].oc_uname, len);
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t)objects[i].oc_uname, len);
}
if (nhfp->fieldlevel) {
for (j = 0; (unsigned) j < len; ++j)
sfi_char(nhfp, &objects[i].oc_uname[j],
"names", "oc_uname", 1);
}
}
}
#ifdef USE_TILES
shuffle_tiles();
#endif
+4
View File
@@ -18,6 +18,7 @@ NEARDATA struct instance_flags iflags; /* provide linkage */
#include "tcap.h"
#include <ctype.h>
#endif
#include "sfprocs.h"
#define BACKWARD_COMPAT
@@ -698,6 +699,9 @@ initoptions_init()
if (boolopt[i].addr)
*(boolopt[i].addr) = boolopt[i].initvalue;
}
/* initialize the function pointers for fieldlevel saves */
sf_init();
#if defined(COMPRESS) || defined(ZLIB_COMP)
set_savepref("externalcomp");
set_restpref("externalcomp");
+227 -88
View File
@@ -4,6 +4,8 @@
#include "hack.h"
#include "lev.h"
#include "sfproto.h"
/*
* This should really go into the level structure, but
@@ -613,64 +615,126 @@ xchar x, y;
* save_regions :
*/
void
save_regions(fd, mode)
int fd;
int mode;
save_regions(nhfp)
NHFILE *nhfp;
{
int i, j;
unsigned n;
if (!perform_bwrite(mode))
if (!perform_bwrite(nhfp))
goto skip_lots;
bwrite(fd, (genericptr_t) &g.moves, sizeof(g.moves)); /* timestamp */
bwrite(fd, (genericptr_t) &g.n_regions, sizeof(g.n_regions));
for (i = 0; i < g.n_regions; i++) {
bwrite(fd, (genericptr_t) &g.regions[i]->bounding_box, sizeof(NhRect));
bwrite(fd, (genericptr_t) &g.regions[i]->nrects, sizeof(short));
for (j = 0; j < g.regions[i]->nrects; j++)
bwrite(fd, (genericptr_t) &g.regions[i]->rects[j], sizeof(NhRect));
bwrite(fd, (genericptr_t) &g.regions[i]->attach_2_u, sizeof(boolean));
n = 0;
bwrite(fd, (genericptr_t) &g.regions[i]->attach_2_m, sizeof(unsigned));
n = g.regions[i]->enter_msg != (const char *) 0
? strlen(g.regions[i]->enter_msg)
: 0;
bwrite(fd, (genericptr_t) &n, sizeof n);
if (n > 0)
bwrite(fd, (genericptr_t) g.regions[i]->enter_msg, n);
n = g.regions[i]->leave_msg != (const char *) 0
? strlen(g.regions[i]->leave_msg)
: 0;
bwrite(fd, (genericptr_t) &n, sizeof n);
if (n > 0)
bwrite(fd, (genericptr_t) g.regions[i]->leave_msg, n);
bwrite(fd, (genericptr_t) &g.regions[i]->ttl, sizeof(long));
bwrite(fd, (genericptr_t) &g.regions[i]->expire_f, sizeof(short));
bwrite(fd, (genericptr_t) &g.regions[i]->can_enter_f, sizeof(short));
bwrite(fd, (genericptr_t) &g.regions[i]->enter_f, sizeof(short));
bwrite(fd, (genericptr_t) &g.regions[i]->can_leave_f, sizeof(short));
bwrite(fd, (genericptr_t) &g.regions[i]->leave_f, sizeof(short));
bwrite(fd, (genericptr_t) &g.regions[i]->inside_f, sizeof(short));
bwrite(fd, (genericptr_t) &g.regions[i]->player_flags,
sizeof(unsigned int));
bwrite(fd, (genericptr_t) &g.regions[i]->n_monst, sizeof(short));
for (j = 0; j < g.regions[i]->n_monst; j++)
bwrite(fd, (genericptr_t) &g.regions[i]->monsters[j],
sizeof(unsigned));
bwrite(fd, (genericptr_t) &g.regions[i]->visible, sizeof(boolean));
bwrite(fd, (genericptr_t) &g.regions[i]->glyph, sizeof(int));
bwrite(fd, (genericptr_t) &g.regions[i]->arg, sizeof(anything));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &g.moves, sizeof (g.moves)); /* timestamp */
bwrite(nhfp->fd, (genericptr_t) &g.n_regions, sizeof (g.n_regions));
}
if (nhfp->fieldlevel) {
sfo_long(nhfp, &g.moves, "regions", "tmstamp", 1);
sfo_int(nhfp, &g.n_regions, "regions", "region_count", 1);
}
for (i = 0; i < g.n_regions; i++) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->bounding_box, sizeof (NhRect));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->nrects, sizeof (short));
}
if (nhfp->fieldlevel) {
sfo_nhrect(nhfp, &g.regions[i]->bounding_box, "g.regions", "bounding_box", 1);
sfo_short(nhfp, &g.regions[i]->nrects, "g.regions", "nrects", 1);
}
for (j = 0; j < g.regions[i]->nrects; j++) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->rects[j], sizeof (NhRect));
if (nhfp->fieldlevel)
sfo_nhrect(nhfp, &g.regions[i]->rects[j], "g.regions", "rect", 1);
}
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->attach_2_u, sizeof (boolean));
if (nhfp->fieldlevel)
sfo_boolean(nhfp, &g.regions[i]->attach_2_u, "g.regions", "attach_2_u", 1);
n = 0;
skip_lots:
if (release_data(mode))
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->attach_2_m, sizeof (unsigned));
if (nhfp->fieldlevel)
sfo_unsigned(nhfp, &g.regions[i]->attach_2_m, "g.regions", "attach_2_m", 1);
n = g.regions[i]->enter_msg != (const char *)0 ?
strlen(g.regions[i]->enter_msg) : 0;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &n, sizeof n);
if (nhfp->fieldlevel)
sfo_unsigned(nhfp, &n, "g.regions", "enter_msg_length", 1);
if (n > 0) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) g.regions[i]->enter_msg, n);
if (nhfp->fieldlevel)
sfo_char(nhfp, g.regions[i]->enter_msg, "g.regions", "enter_msg", 1);
}
n = g.regions[i]->leave_msg != (const char *)0 ?
strlen(g.regions[i]->leave_msg) : 0;
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &n, sizeof n);
if (nhfp->fieldlevel)
sfo_unsigned(nhfp, &n, "g.regions", "leave_msg_length", 1);
if (n > 0) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) g.regions[i]->leave_msg, n);
}
if (nhfp->fieldlevel) {
for (j = 0; j < (int) n; ++j)
sfo_char(nhfp, &g.regions[i]->leave_msg[j], "g.regions", "leave_msg", 1);
}
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->ttl, sizeof (long));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->expire_f, sizeof (short));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->can_enter_f, sizeof (short));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->enter_f, sizeof (short));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->can_leave_f, sizeof (short));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->leave_f, sizeof (short));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->inside_f, sizeof (short));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->player_flags, sizeof (unsigned int));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->n_monst, sizeof (short));
}
if (nhfp->fieldlevel) {
sfo_long(nhfp, &g.regions[i]->ttl, "g.regions", "ttl", 1);
sfo_short(nhfp, &g.regions[i]->expire_f, "g.regions", "expire_f", 1);
sfo_short(nhfp, &g.regions[i]->can_enter_f, "g.regions", "can_enter_f", 1);
sfo_short(nhfp, &g.regions[i]->enter_f, "g.regions", "enter_f", 1);
sfo_short(nhfp, &g.regions[i]->can_leave_f, "g.regions", "can_leave_f", 1);
sfo_short(nhfp, &g.regions[i]->leave_f, "g.regions", "leave_f", 1);
sfo_short(nhfp, &g.regions[i]->inside_f, "g.regions", "inside_f", 1);
sfo_unsigned(nhfp, &g.regions[i]->player_flags, "g.regions", "player_flags", 1);
sfo_short(nhfp, &g.regions[i]->n_monst, "g.regions", "monster_count", 1);
}
for (j = 0; j < g.regions[i]->n_monst; j++) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->monsters[j],
sizeof (unsigned));
if (nhfp->fieldlevel)
sfo_unsigned(nhfp, &g.regions[i]->monsters[j], "g.regions", "monster", 1);
}
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->visible, sizeof (boolean));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->glyph, sizeof (int));
bwrite(nhfp->fd, (genericptr_t) &g.regions[i]->arg, sizeof (anything));
}
if (nhfp->fieldlevel) {
sfo_boolean(nhfp, &g.regions[i]->visible, "g.regions", "visible", 1);
sfo_int(nhfp, &g.regions[i]->glyph, "g.regions", "glyph", 1);
sfo_any(nhfp, &g.regions[i]->arg, "g.regions", "arg", 1);
}
}
skip_lots:
if (release_data(nhfp))
clear_regions();
}
void
rest_regions(fd, ghostly)
int fd;
rest_regions(nhfp, ghostly)
NHFILE *nhfp;
boolean ghostly; /* If a bones file restore */
{
int i, j;
@@ -678,77 +742,152 @@ boolean ghostly; /* If a bones file restore */
long tmstamp;
char *msg_buf;
clear_regions(); /* Just for security */
mread(fd, (genericptr_t) &tmstamp, sizeof(tmstamp));
clear_regions(); /* Just for security */
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &tmstamp, sizeof (tmstamp));
if (nhfp->fieldlevel)
sfi_long(nhfp, &tmstamp, "regions", "tmstamp", 1);
if (ghostly)
tmstamp = 0;
else
tmstamp = (g.moves - tmstamp);
mread(fd, (genericptr_t) &g.n_regions, sizeof(g.n_regions));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.n_regions, sizeof (g.n_regions));
if (nhfp->fieldlevel)
sfi_int(nhfp, &g.n_regions, "regions", "region_count", 1);
g.max_regions = g.n_regions;
if (g.n_regions > 0)
g.regions = (NhRegion **) alloc(sizeof(NhRegion *) * g.n_regions);
g.regions = (NhRegion **) alloc(sizeof (NhRegion *) * g.n_regions);
for (i = 0; i < g.n_regions; i++) {
g.regions[i] = (NhRegion *) alloc(sizeof(NhRegion));
mread(fd, (genericptr_t) &g.regions[i]->bounding_box, sizeof(NhRect));
mread(fd, (genericptr_t) &g.regions[i]->nrects, sizeof(short));
g.regions[i] = (NhRegion *) alloc(sizeof (NhRegion));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &g.regions[i]->bounding_box, sizeof (NhRect));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->nrects, sizeof (short));
}
if (nhfp->fieldlevel) {
sfi_nhrect(nhfp, &g.regions[i]->bounding_box, "g.regions", "bounding box", 1);
sfi_short(nhfp, &g.regions[i]->nrects, "g.regions", "nrects", 1);
}
if (g.regions[i]->nrects > 0)
g.regions[i]->rects =
(NhRect *) alloc(sizeof(NhRect) * g.regions[i]->nrects);
for (j = 0; j < g.regions[i]->nrects; j++)
mread(fd, (genericptr_t) &g.regions[i]->rects[j], sizeof(NhRect));
mread(fd, (genericptr_t) &g.regions[i]->attach_2_u, sizeof(boolean));
mread(fd, (genericptr_t) &g.regions[i]->attach_2_m, sizeof(unsigned));
g.regions[i]->rects = (NhRect *)
alloc(sizeof (NhRect) * g.regions[i]->nrects);
for (j = 0; j < g.regions[i]->nrects; j++) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.regions[i]->rects[j], sizeof (NhRect));
if (nhfp->fieldlevel)
sfi_nhrect(nhfp, &g.regions[i]->rects[j], "g.regions", "rect", 1);
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &g.regions[i]->attach_2_u, sizeof (boolean));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->attach_2_m, sizeof (unsigned));
}
if (nhfp->fieldlevel) {
sfi_boolean(nhfp, &g.regions[i]->attach_2_u, "g.regions", "attach_2_u", 1);
sfi_unsigned(nhfp, &g.regions[i]->attach_2_m, "g.regions", "attach_2_m", 1);
}
mread(fd, (genericptr_t) &n, sizeof n);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &n, sizeof n);
if (nhfp->fieldlevel)
sfi_unsigned(nhfp, &n, "g.regions", "enter_msg_length", 1);
if (n > 0) {
msg_buf = (char *) alloc(n + 1);
mread(fd, (genericptr_t) msg_buf, n);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) msg_buf, n);
}
if (nhfp->fieldlevel) {
for (j = 0; (unsigned) j < n; ++j)
sfi_char(nhfp, &msg_buf[j], "g.regions", "enter_msg", 1);
}
msg_buf[n] = '\0';
g.regions[i]->enter_msg = (const char *) msg_buf;
} else
g.regions[i]->enter_msg = (const char *) 0;
g.regions[i]->enter_msg = (const char *)0;
mread(fd, (genericptr_t) &n, sizeof n);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &n, sizeof n);
if (nhfp->fieldlevel)
sfi_unsigned(nhfp, &n, "g.regions", "leave_msg_length", 1);
if (n > 0) {
msg_buf = (char *) alloc(n + 1);
mread(fd, (genericptr_t) msg_buf, n);
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) msg_buf, n);
}
if (nhfp->fieldlevel) {
for (j = 0; (unsigned) j < n; ++j)
sfi_char(nhfp, &msg_buf[j], "g.regions", "leave_msg", 1);
}
msg_buf[n] = '\0';
g.regions[i]->leave_msg = (const char *) msg_buf;
g.regions[i]->leave_msg = (const char *) msg_buf;
} else
g.regions[i]->leave_msg = (const char *) 0;
g.regions[i]->leave_msg = (const char *)0;
mread(fd, (genericptr_t) &g.regions[i]->ttl, sizeof(long));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.regions[i]->ttl, sizeof (long));
if (nhfp->fieldlevel)
sfi_long(nhfp, &g.regions[i]->ttl, "g.regions", "ttl", 1);
/* check for expired region */
if (g.regions[i]->ttl >= 0L)
g.regions[i]->ttl =
(g.regions[i]->ttl > tmstamp) ? g.regions[i]->ttl - tmstamp : 0L;
mread(fd, (genericptr_t) &g.regions[i]->expire_f, sizeof(short));
mread(fd, (genericptr_t) &g.regions[i]->can_enter_f, sizeof(short));
mread(fd, (genericptr_t) &g.regions[i]->enter_f, sizeof(short));
mread(fd, (genericptr_t) &g.regions[i]->can_leave_f, sizeof(short));
mread(fd, (genericptr_t) &g.regions[i]->leave_f, sizeof(short));
mread(fd, (genericptr_t) &g.regions[i]->inside_f, sizeof(short));
mread(fd, (genericptr_t) &g.regions[i]->player_flags,
sizeof(unsigned int));
if (ghostly) { /* settings pertained to old player */
(g.regions[i]->ttl > tmstamp) ? g.regions[i]->ttl - tmstamp : 0L;
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &g.regions[i]->expire_f,
sizeof (short));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->can_enter_f,
sizeof (short));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->enter_f,
sizeof (short));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->can_leave_f,
sizeof (short));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->leave_f,
sizeof (short));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->inside_f,
sizeof (short));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->player_flags,
sizeof (unsigned int));
}
if (nhfp->fieldlevel) {
sfi_short(nhfp, &g.regions[i]->expire_f, "g.regions", "expire_f", 1);
sfi_short(nhfp, &g.regions[i]->can_enter_f, "g.regions", "can_enter_f", 1);
sfi_short(nhfp, &g.regions[i]->enter_f, "g.regions", "enter_f", 1);
sfi_short(nhfp, &g.regions[i]->can_leave_f, "g.regions", "can_leave_f", 1);
sfi_short(nhfp, &g.regions[i]->leave_f, "g.regions", "leave_f", 1);
sfi_short(nhfp, &g.regions[i]->inside_f, "g.regions", "inside_f", 1);
sfi_unsigned(nhfp, &g.regions[i]->player_flags, "g.regions", "player_flags", 1);
}
if (ghostly) { /* settings pertained to old player */
clear_hero_inside(g.regions[i]);
clear_heros_fault(g.regions[i]);
}
mread(fd, (genericptr_t) &g.regions[i]->n_monst, sizeof(short));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.regions[i]->n_monst, sizeof (short));
if (nhfp->fieldlevel)
sfi_short(nhfp, &g.regions[i]->n_monst, "g.regions", "monster_count", 1);
if (g.regions[i]->n_monst > 0)
g.regions[i]->monsters =
(unsigned *) alloc(sizeof(unsigned) * g.regions[i]->n_monst);
(unsigned *) alloc(sizeof (unsigned) * g.regions[i]->n_monst);
else
g.regions[i]->monsters = (unsigned int *) 0;
g.regions[i]->monsters = (unsigned int *)0;
g.regions[i]->max_monst = g.regions[i]->n_monst;
for (j = 0; j < g.regions[i]->n_monst; j++)
mread(fd, (genericptr_t) &g.regions[i]->monsters[j],
sizeof(unsigned));
mread(fd, (genericptr_t) &g.regions[i]->visible, sizeof(boolean));
mread(fd, (genericptr_t) &g.regions[i]->glyph, sizeof(int));
mread(fd, (genericptr_t) &g.regions[i]->arg, sizeof(anything));
for (j = 0; j < g.regions[i]->n_monst; j++) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.regions[i]->monsters[j],
sizeof (unsigned));
if (nhfp->fieldlevel)
sfi_unsigned(nhfp, &g.regions[i]->monsters[j], "g.regions", "monster", 1);
}
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &g.regions[i]->visible, sizeof (boolean));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->glyph, sizeof (int));
mread(nhfp->fd, (genericptr_t) &g.regions[i]->arg, sizeof (anything));
}
if (nhfp->fieldlevel) {
sfi_boolean(nhfp, &g.regions[i]->visible, "g.regions", "visible", 1);
sfi_int(nhfp, &g.regions[i]->glyph, "g.regions", "glyph", 1);
sfi_any(nhfp, &g.regions[i]->arg, "g.regions", "arg", 1);
}
}
/* remove expired regions, do not trigger the expire_f callback (yet!);
also update monster lists if this data is coming from a bones file */
+649 -309
View File
File diff suppressed because it is too large Load Diff
+36 -11
View File
@@ -6,6 +6,8 @@
#include "hack.h"
#include "lev.h"
#include "dlb.h"
#include "sfproto.h"
/* [note: this comment is fairly old, but still accurate for 3.1]
* Rumors have been entirely rewritten to speed up the access. This is
@@ -383,15 +385,27 @@ dlb *fp;
}
void
save_oracles(fd, mode)
int fd, mode;
save_oracles(nhfp)
NHFILE *nhfp;
{
if (perform_bwrite(mode)) {
bwrite(fd, (genericptr_t) &g.oracle_cnt, sizeof g.oracle_cnt);
if (g.oracle_cnt)
bwrite(fd, (genericptr_t) g.oracle_loc, g.oracle_cnt * sizeof(long));
int i;
if (perform_bwrite(nhfp)) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &g.oracle_cnt, sizeof g.oracle_cnt);
if (nhfp->fieldlevel)
sfo_unsigned(nhfp, &g.oracle_cnt, "oracles", "g.oracle_cnt", 1);
if (g.oracle_cnt) {
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t)g.oracle_loc, g.oracle_cnt * sizeof (long));
}
if (nhfp->fieldlevel) {
for (i = 0; (unsigned) i < g.oracle_cnt; ++i)
sfo_ulong(nhfp, &g.oracle_loc[i], "oracles", "oracle loc", 1);
}
}
}
if (release_data(mode)) {
if (release_data(nhfp)) {
if (g.oracle_cnt) {
free((genericptr_t) g.oracle_loc);
g.oracle_loc = 0, g.oracle_cnt = 0, g.oracle_flg = 0;
@@ -400,13 +414,24 @@ int fd, mode;
}
void
restore_oracles(fd)
int fd;
restore_oracles(nhfp)
NHFILE *nhfp;
{
mread(fd, (genericptr_t) &g.oracle_cnt, sizeof g.oracle_cnt);
int i;
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.oracle_cnt, sizeof g.oracle_cnt);
if (nhfp->fieldlevel)
sfi_unsigned(nhfp, &g.oracle_cnt, "oracles", "g.oracle_cnt", 1);
if (g.oracle_cnt) {
g.oracle_loc = (unsigned long *) alloc(g.oracle_cnt * sizeof(long));
mread(fd, (genericptr_t) g.oracle_loc, g.oracle_cnt * sizeof(long));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) g.oracle_loc, g.oracle_cnt * sizeof (long));
}
if (nhfp->fieldlevel) {
for (i = 0; (unsigned) i < g.oracle_cnt; ++i)
sfi_ulong(nhfp, &g.oracle_loc[i], "oracles", "g.oracle_loc", 1);
}
g.oracle_flg = 1; /* no need to call init_oracles() */
}
}
+616 -294
View File
File diff suppressed because it is too large Load Diff
+1112
View File
File diff suppressed because it is too large Load Diff
+640
View File
@@ -0,0 +1,640 @@
/* NetHack 3.6 sf_base.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */
/* Copyright (c) Michael Allison, 2019. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "integer.h"
#include "sfprocs.h"
struct sf_procs sfoprocs[4], sfiprocs[4],
zerosfoprocs = {0}, zerosfiprocs = {0};
void FDECL(sfi_log, (NHFILE *, const char *, const char *, const char *, int));
/*
*----------------------------------------------------------------------------
* initialize the function pointers. These are called from initoptions_init().
*----------------------------------------------------------------------------
*/
void
sf_init()
{
sfoprocs[invalid] = zerosfoprocs;
sfiprocs[invalid] = zerosfiprocs;
sfoprocs[historical] = zerosfoprocs;
sfiprocs[historical] = zerosfiprocs;
sfoprocs[lendian] = lendian_sfo_procs;
sfiprocs[lendian] = lendian_sfi_procs;
sfoprocs[ascii] = ascii_sfo_procs;
sfiprocs[ascii] = ascii_sfi_procs;
}
/*
*----------------------------------------
* routines called from engine core and
* from functions in generated sfdata.c
*----------------------------------------
*/
void
sfo_any(nhfp, d_any, myparent, myname, cnt)
NHFILE *nhfp;
union any *d_any;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_any)(nhfp, d_any, myparent, myname, cnt);
}
void
sfo_aligntyp(nhfp, d_aligntyp, myparent, myname, cnt)
NHFILE *nhfp;
aligntyp *d_aligntyp;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_aligntyp)(nhfp, d_aligntyp, myparent, myname, cnt);
}
void
sfo_bitfield(nhfp, d_bitfield, myparent, myname, cnt)
NHFILE *nhfp;
uint8_t *d_bitfield;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_bitfield)(nhfp, d_bitfield, myparent, myname, cnt);
}
void
sfo_boolean(nhfp, d_boolean, myparent, myname, cnt)
NHFILE *nhfp;
boolean *d_boolean;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_boolean)(nhfp, d_boolean, myparent, myname, cnt);
}
void
sfo_char(nhfp, d_char, myparent, myname, cnt)
NHFILE *nhfp;
char *d_char;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_char)(nhfp, d_char, myparent, myname, cnt);
}
void
sfo_genericptr(nhfp, d_genericptr, myparent, myname, cnt)
NHFILE *nhfp;
genericptr_t d_genericptr;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_genericptr)(nhfp, d_genericptr, myparent, myname, cnt);
}
void
sfo_int(nhfp, d_int, myparent, myname, cnt)
NHFILE *nhfp;
int *d_int;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_int)(nhfp, d_int, myparent, myname, cnt);
}
void
sfo_long(nhfp, d_long, myparent, myname, cnt)
NHFILE *nhfp;
long *d_long;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_long)(nhfp, d_long, myparent, myname, cnt);
}
void
sfo_schar(nhfp, d_schar, myparent, myname, cnt)
NHFILE *nhfp;
schar *d_schar;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_schar)(nhfp, d_schar, myparent, myname, cnt);
}
void
sfo_short(nhfp, d_short, myparent, myname, cnt)
NHFILE *nhfp;
short *d_short;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_short)(nhfp, d_short, myparent, myname, cnt);
}
void
sfo_size_t(nhfp, d_size_t, myparent, myname, cnt)
NHFILE *nhfp;
size_t *d_size_t;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_size_t)(nhfp, d_size_t, myparent, myname, cnt);
}
void
sfo_time_t(nhfp, d_time_t, myparent, myname, cnt)
NHFILE *nhfp;
time_t *d_time_t;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_time_t)(nhfp, d_time_t, myparent, myname, cnt);
}
void
sfo_unsigned(nhfp, d_unsigned, myparent, myname, cnt)
NHFILE *nhfp;
unsigned *d_unsigned;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_unsigned)(nhfp, d_unsigned, myparent, myname, cnt);
}
void
sfo_uchar(nhfp, d_uchar, myparent, myname, cnt)
NHFILE *nhfp;
unsigned char *d_uchar;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_uchar)(nhfp, d_uchar, myparent, myname, cnt);
}
void
sfo_uint(nhfp, d_uint, myparent, myname, cnt)
NHFILE *nhfp;
unsigned int *d_uint;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_uint)(nhfp, d_uint, myparent, myname, cnt);
}
void
sfo_ulong(nhfp, d_ulong, myparent, myname, cnt)
NHFILE *nhfp;
unsigned long *d_ulong;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_ulong)(nhfp, d_ulong, myparent, myname, cnt);
}
void
sfo_ushort(nhfp, d_ushort, myparent, myname, cnt)
NHFILE *nhfp;
unsigned short *d_ushort;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_ushort)(nhfp, d_ushort, myparent, myname, cnt);
}
void
sfo_xchar(nhfp, d_xchar, myparent, myname, cnt)
NHFILE *nhfp;
xchar *d_xchar;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_xchar)(nhfp, d_xchar, myparent, myname, cnt);
}
void
sfo_str(nhfp, d_str, myparent, myname, cnt)
NHFILE *nhfp;
char *d_str;
const char *myparent;
const char *myname;
int cnt;
{
(*sfoprocs[nhfp->fnidx].fn.sf_str)(nhfp, d_str, myparent, myname, cnt);
}
void
sfo_addinfo(nhfp, parent, action, myname, index)
NHFILE *nhfp;
const char *parent, *action, *myname;
int index;
{
(*sfoprocs[nhfp->fnidx].fn.sf_addinfo)(nhfp, parent, action, myname, index);
}
/*
*----------------------------------------------------------------------------
* routines called from core and from functions in generated sfi_data.c
*----------------------------------------------------------------------------
*/
void
sfi_any(nhfp, d_any, myparent, myname, cnt)
NHFILE *nhfp;
union any *d_any;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "any";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_any)(nhfp, d_any, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%ld)\n", d_any->a_long);
#endif
}
void
sfi_aligntyp(nhfp, d_aligntyp, myparent, myname, cnt)
NHFILE *nhfp;
aligntyp *d_aligntyp;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "aligntyp";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_aligntyp)(nhfp, d_aligntyp, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%d)\n", *d_aligntyp);
#endif
}
void
sfi_bitfield(nhfp, d_bitfield, myparent, myname, cnt)
NHFILE *nhfp;
uint8_t *d_bitfield;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "bitfield";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_bitfield)(nhfp, d_bitfield, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%hd)\n", *d_bitfield);
#endif
}
void
sfi_boolean(nhfp, d_boolean, myparent, myname, cnt)
NHFILE *nhfp;
boolean *d_boolean;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "boolean";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_boolean)(nhfp, d_boolean, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%s)\n", (*d_boolean) ? "true" : "false");
#endif
}
void
sfi_char(nhfp, d_char, myparent, myname, cnt)
NHFILE *nhfp;
char *d_char;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "char";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_char)(nhfp, d_char, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%s)\n", d_char ? d_char : "");
#endif
}
void
sfi_genericptr(nhfp, d_genericptr, myparent, myname, cnt)
NHFILE *nhfp;
genericptr_t d_genericptr;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "genericptr";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_genericptr)(nhfp, d_genericptr, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%s)\n", (d_genericptr) ? "set" : "null");
#endif
}
void
sfi_int(nhfp, d_int, myparent, myname, cnt)
NHFILE *nhfp;
int *d_int;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "int";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_int)(nhfp, d_int, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%d)\n", *d_int);
#endif
}
void
sfi_long(nhfp, d_long, myparent, myname, cnt)
NHFILE *nhfp;
long *d_long;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "long";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_long)(nhfp, d_long, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%ld)\n", *d_long);
#endif
}
void
sfi_schar(nhfp, d_schar, myparent, myname, cnt)
NHFILE *nhfp;
schar *d_schar;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "schar";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_schar)(nhfp, d_schar, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%hd)\n", (short) *d_schar);
#endif
}
void
sfi_short(nhfp, d_short, myparent, myname, cnt)
NHFILE *nhfp;
short *d_short;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "short";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_short)(nhfp, d_short, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%hd)\n", *d_short);
#endif
}
void
sfi_size_t(nhfp, d_size_t, myparent, myname, cnt)
NHFILE *nhfp;
size_t *d_size_t;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "size_t";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_size_t)(nhfp, d_size_t, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%lu)\n", (unsigned long) *d_size_t);
#endif
}
void
sfi_time_t(nhfp, d_time_t, myparent, myname, cnt)
NHFILE *nhfp;
time_t *d_time_t;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "time_t";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_time_t)(nhfp, d_time_t, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%s)\n", yyyymmddhhmmss(*d_time_t));
#endif
}
void
sfi_unsigned(nhfp, d_unsigned, myparent, myname, cnt)
NHFILE *nhfp;
unsigned *d_unsigned;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "unsigned";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_unsigned)(nhfp, d_unsigned, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%u)\n", *d_unsigned);
#endif
}
void
sfi_uchar(nhfp, d_uchar, myparent, myname, cnt)
NHFILE *nhfp;
unsigned char *d_uchar;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "uchar";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_uchar)(nhfp, d_uchar, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%hu)\n", (unsigned short) *d_uchar);
#endif
}
void
sfi_uint(nhfp, d_uint, myparent, myname, cnt)
NHFILE *nhfp;
unsigned int *d_uint;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "uint";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_uint)(nhfp, d_uint, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%u)\n", *d_uint);
#endif
}
void
sfi_ulong(nhfp, d_ulong, myparent, myname, cnt)
NHFILE *nhfp;
unsigned long *d_ulong;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "ulong";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_ulong)(nhfp, d_ulong, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%lu)\n", *d_ulong);
#endif
}
void
sfi_ushort(nhfp, d_ushort, myparent, myname, cnt)
NHFILE *nhfp;
unsigned short *d_ushort;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "ushort";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_ushort)(nhfp, d_ushort, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%hu)\n", *d_ushort);
#endif
}
void
sfi_xchar(nhfp, d_xchar, myparent, myname, cnt)
NHFILE *nhfp;
xchar *d_xchar;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "xchar";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_xchar)(nhfp, d_xchar, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(%hd)\n", (short) *d_xchar);
#endif
}
void
sfi_str(nhfp, d_str, myparent, myname, cnt)
NHFILE *nhfp;
char *d_str;
const char *myparent;
const char *myname;
int cnt;
{
const char *parent = "str";
sfi_log(nhfp, myparent, myname, parent, cnt);
(*sfiprocs[nhfp->fnidx].fn.sf_str)(nhfp, d_str, myparent, myname, cnt);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
fprintf(nhfp->fpdebug, "(\"%s\")\n", d_str);
#endif
}
void
sfi_addinfo(nhfp, myparent, action, myname, index)
NHFILE *nhfp;
const char *myparent, *action, *myname;
int index;
{
if (nhfp) {
if (nhfp->fplog)
(void) fprintf(nhfp->fplog, "# %s %s %s %d\n", myparent, action, myname, index);
#ifdef DO_DEBUG
if (nhfp->fpdebug)
(void) fprintf(nhfp->fpdebug, "# %s %s %s %d\n", myparent, action, myname, index);
#endif
}
(*sfiprocs[nhfp->fnidx].fn.sf_addinfo)(nhfp, myparent, action, myname, index);
}
void
sfi_log(nhfp, t1, t2, t3, cnt)
NHFILE *nhfp;
const char *t1, *t2, *t3;
int cnt;
{
#ifdef DO_DEBUG
#ifdef SAVEFILE_DEBUGGING
if (nhfp) {
if (nhfp->fplog)
(void) fprintf(nhfp->fplog, "%s %s %s cnt=%d\n", t1, t2, t3, cnt);
if (nhfp->fpdebug)
(void) fprintf(nhfp->fpdebug, "%s %s %s cnt=%d ", t1, t2, t3, cnt);
}
#endif
#endif
}
+5776
View File
File diff suppressed because it is too large Load Diff
+1313
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -6032,7 +6032,7 @@ const char *name;
if (!fd)
return FALSE;
Fread((genericptr_t) &vers_info, sizeof vers_info, 1, fd);
if (!check_version(&vers_info, name, TRUE)) {
if (!check_version(&vers_info, name, TRUE, UTD_CHECKSIZES)) {
(void) dlb_fclose(fd);
goto give_up;
}
+73 -38
View File
@@ -5,6 +5,8 @@
#include "hack.h"
#include "lev.h" /* for checking save modes */
#include "sfproto.h"
STATIC_DCL void NDECL(stoned_dialogue);
STATIC_DCL void NDECL(vomiting_dialogue);
@@ -1631,13 +1633,13 @@ do_storms()
* Call timers that have timed out.
*
* Save/Restore:
* void save_timers(int fd, int mode, int range)
* void save_timers(NHFILE *, int range)
* Save all timers of range 'range'. Range is either global
* or local. Global timers follow game play, local timers
* are saved with a level. Object and monster timers are
* saved using their respective id's instead of pointers.
*
* void restore_timers(int fd, int range, boolean ghostly, long adjust)
* void restore_timers(NHFILE *, int range, boolean ghostly, long adjust)
* Restore timers of range 'range'. If from a ghost pile,
* adjust the timeout by 'adjust'. The object and monster
* ids are not restored until later.
@@ -1665,10 +1667,10 @@ STATIC_DCL void FDECL(print_queue, (winid, timer_element *));
STATIC_DCL void FDECL(insert_timer, (timer_element *));
STATIC_DCL timer_element *FDECL(remove_timer,
(timer_element **, SHORT_P, ANY_P *));
STATIC_DCL void FDECL(write_timer, (int, timer_element *));
STATIC_DCL void FDECL(write_timer, (NHFILE *, timer_element *));
STATIC_DCL boolean FDECL(mon_is_local, (struct monst *));
STATIC_DCL boolean FDECL(timer_is_local, (timer_element *));
STATIC_DCL int FDECL(maybe_write_timer, (int, int, BOOLEAN_P));
STATIC_DCL int FDECL(maybe_write_timer, (NHFILE *, int, BOOLEAN_P));
/* If defined, then include names when printing out the timer queue */
#define VERBOSE_TIMER
@@ -2110,8 +2112,8 @@ anything *arg;
}
STATIC_OVL void
write_timer(fd, timer)
int fd;
write_timer(nhfp, timer)
NHFILE *nhfp;
timer_element *timer;
{
anything arg_save;
@@ -2121,34 +2123,49 @@ timer_element *timer;
case TIMER_GLOBAL:
case TIMER_LEVEL:
/* assume no pointers in arg */
bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) timer, sizeof(timer_element));
if (nhfp->fieldlevel)
sfo_fe(nhfp, timer, "timers", "timer", 1);
break;
case TIMER_OBJECT:
if (timer->needs_fixup)
bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
else {
if (timer->needs_fixup) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t)timer, sizeof(timer_element));
if (nhfp->fieldlevel)
sfo_fe(nhfp, timer, "timers", "timer", 1);
} else {
/* replace object pointer with id */
arg_save.a_obj = timer->arg.a_obj;
timer->arg = cg.zeroany;
timer->arg.a_uint = (arg_save.a_obj)->o_id;
timer->needs_fixup = 1;
bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t)timer, sizeof(timer_element));
if (nhfp->fieldlevel)
sfo_fe(nhfp, timer, "timers", "timer", 1);
timer->arg.a_obj = arg_save.a_obj;
timer->needs_fixup = 0;
}
break;
case TIMER_MONSTER:
if (timer->needs_fixup)
bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
else {
if (timer->needs_fixup) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t)timer, sizeof(timer_element));
if (nhfp->fieldlevel)
sfo_fe(nhfp, timer, "timers", "timer", 1);
} else {
/* replace monster pointer with id */
arg_save.a_monst = timer->arg.a_monst;
timer->arg = cg.zeroany;
timer->arg.a_uint = (arg_save.a_monst)->m_id;
timer->needs_fixup = 1;
bwrite(fd, (genericptr_t) timer, sizeof(timer_element));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t)timer, sizeof(timer_element));
if (nhfp->fieldlevel)
sfo_fe(nhfp, timer, "timers", "timer", 1);
timer->arg.a_monst = arg_save.a_monst;
timer->needs_fixup = 0;
}
@@ -2231,8 +2248,9 @@ timer_element *timer;
* be written. If write_it is true, actually write the timer.
*/
STATIC_OVL int
maybe_write_timer(fd, range, write_it)
int fd, range;
maybe_write_timer(nhfp, range, write_it)
NHFILE *nhfp;
int range;
boolean write_it;
{
int count = 0;
@@ -2244,17 +2262,14 @@ boolean write_it;
if (!timer_is_local(curr)) {
count++;
if (write_it)
write_timer(fd, curr);
if (write_it) write_timer(nhfp, curr);
}
} else {
/* local timers */
if (timer_is_local(curr)) {
count++;
if (write_it)
write_timer(fd, curr);
if (write_it) write_timer(nhfp, curr);
}
}
}
@@ -2262,6 +2277,7 @@ boolean write_it;
return count;
}
/*
* Save part of the timer list. The parameter 'range' specifies either
* global or level timers to save. The timer ID is saved with the global
@@ -2276,22 +2292,29 @@ boolean write_it;
* + timeouts that stay with the level (obj & monst)
*/
void
save_timers(fd, mode, range)
int fd, mode, range;
save_timers(nhfp, range)
NHFILE *nhfp;
int range;
{
timer_element *curr, *prev, *next_timer = 0;
int count;
if (perform_bwrite(mode)) {
if (range == RANGE_GLOBAL)
bwrite(fd, (genericptr_t) &g.timer_id, sizeof(g.timer_id));
count = maybe_write_timer(fd, range, FALSE);
bwrite(fd, (genericptr_t) &count, sizeof count);
(void) maybe_write_timer(fd, range, TRUE);
if (perform_bwrite(nhfp)) {
if (range == RANGE_GLOBAL) {
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &g.timer_id, sizeof(g.timer_id));
if (nhfp->fieldlevel)
sfo_ulong(nhfp, &g.timer_id, "timers", "g.timer_id", 1);
}
count = maybe_write_timer(nhfp, range, FALSE);
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &count, sizeof count);
if (nhfp->fieldlevel)
sfo_int(nhfp, &count, "timers", "timer_count", 1);
(void) maybe_write_timer(nhfp, range, TRUE);
}
if (release_data(mode)) {
if (release_data(nhfp)) {
for (prev = 0, curr = g.timer_base; curr; curr = next_timer) {
next_timer = curr->next; /* in case curr is removed */
@@ -2314,22 +2337,34 @@ int fd, mode, range;
* monster pointers.
*/
void
restore_timers(fd, range, ghostly, adjust)
int fd, range;
restore_timers(nhfp, range, ghostly, adjust)
NHFILE *nhfp;
int range;
boolean ghostly; /* restoring from a ghost level */
long adjust; /* how much to adjust timeout */
{
int count;
timer_element *curr;
if (range == RANGE_GLOBAL)
mread(fd, (genericptr_t) &g.timer_id, sizeof g.timer_id);
if (range == RANGE_GLOBAL) {
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &g.timer_id, sizeof g.timer_id);
if (nhfp->fieldlevel)
sfi_ulong(nhfp, &g.timer_id, "timers", "g.timer_id", 1);
}
/* restore elements */
mread(fd, (genericptr_t) &count, sizeof count);
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &count, sizeof count);
if (nhfp->fieldlevel)
sfi_int(nhfp, &count, "timers", "timer_count", 1);
while (count-- > 0) {
curr = (timer_element *) alloc(sizeof(timer_element));
mread(fd, (genericptr_t) curr, sizeof(timer_element));
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) curr, sizeof(timer_element));
if (nhfp->fieldlevel)
sfi_fe(nhfp, curr, "timers", "timer", 1);
if (ghostly)
curr->timeout += adjust;
insert_timer(curr);
+60 -23
View File
@@ -6,6 +6,10 @@
#include "hack.h"
#include "dlb.h"
#include "date.h"
#include "lev.h"
#include "sfproto.h"
/*
* All the references to the contents of patchlevel.h have been moved
* into makedefs....
@@ -250,10 +254,11 @@ long filetime;
#endif
boolean
check_version(version_data, filename, complain)
check_version(version_data, filename, complain, utdflags)
struct version_info *version_data;
const char *filename;
boolean complain;
unsigned long utdflags;
{
if (
#ifdef VERSION_COMPATIBILITY
@@ -273,9 +278,12 @@ boolean complain;
(version_data->feature_set & ~IGNORED_FEATURES)
!= (VERSION_FEATURES & ~IGNORED_FEATURES)
#endif
|| version_data->entity_count != VERSION_SANITY1
|| version_data->struct_sizes1 != VERSION_SANITY2
|| version_data->struct_sizes2 != VERSION_SANITY3) {
|| ((utdflags & UTD_SKIP_SANITY1) == 0
&& version_data->entity_count != VERSION_SANITY1)
|| ((utdflags & UTD_CHECKSIZES) &&
(version_data->struct_sizes1 != VERSION_SANITY2))
|| ((utdflags & UTD_CHECKSIZES) &&
(version_data->struct_sizes2 != VERSION_SANITY3))) {
if (complain)
pline("Configuration incompatibility for file \"%s\".", filename);
return FALSE;
@@ -286,24 +294,47 @@ boolean complain;
/* this used to be based on file date and somewhat OS-dependant,
but now examines the initial part of the file's contents */
boolean
uptodate(fd, name)
int fd;
uptodate(nhfp, name, utdflags)
NHFILE *nhfp;
const char *name;
unsigned long utdflags;
{
int rlen;
int rlen, cmc = 0, filecmc = 0;
struct version_info vers_info;
boolean verbose = name ? TRUE : FALSE;
char indicator;
rlen = read(fd, (genericptr_t) &vers_info, sizeof vers_info);
minit(); /* ZEROCOMP */
if (rlen == 0) {
if (verbose) {
pline("File \"%s\" is empty?", name);
wait_synch();
}
return FALSE;
if (nhfp->structlevel) {
rlen = read(nhfp->fd, (genericptr_t) &indicator, sizeof indicator);
rlen = read(nhfp->fd, (genericptr_t) &filecmc, sizeof filecmc);
if (rlen == 0)
return FALSE;
}
if (!check_version(&vers_info, name, verbose)) {
if (nhfp->fieldlevel) {
sfi_char(nhfp, &indicator, "indicate", "format", 1);
sfi_int(nhfp, &filecmc, "validate", "critical_members_count", 1);
cmc = critical_members_count();
}
if (cmc != filecmc)
return FALSE;
if (nhfp->fieldlevel && (nhfp->fnidx > historical)) {
sfi_version_info(nhfp, &vers_info, "version", "version_info", 1);
} else {
int rlen;
rlen = read(nhfp->fd, (genericptr_t) &vers_info, sizeof vers_info);
minit(); /* ZEROCOMP */
if (rlen == 0) {
if (verbose) {
pline("File \"%s\" is empty?", name);
wait_synch();
}
return FALSE;
}
}
if (!check_version(&vers_info, name, verbose, utdflags)) {
if (verbose)
wait_synch();
return FALSE;
@@ -312,19 +343,25 @@ const char *name;
}
void
store_version(fd)
int fd;
store_version(nhfp)
NHFILE *nhfp;
{
static const struct version_info version_data = {
VERSION_NUMBER, VERSION_FEATURES,
VERSION_SANITY1, VERSION_SANITY2, VERSION_SANITY3
};
bufoff(fd);
/* bwrite() before bufon() uses plain write() */
bwrite(fd, (genericptr_t) &version_data,
(unsigned) (sizeof version_data));
bufon(fd);
if (nhfp->structlevel) {
bufoff(nhfp->fd);
/* bwrite() before bufon() uses plain write() */
bwrite(nhfp->fd,(genericptr_t) &version_data,
(unsigned) (sizeof version_data));
bufon(nhfp->fd);
}
if (nhfp->fieldlevel) {
sfo_version_info(nhfp, (struct version_info *) &version_data,
"version", "version_info", 1);
}
return;
}
+48 -16
View File
@@ -5,6 +5,8 @@
#include "hack.h"
#include "lev.h"
#include "sfproto.h"
#define newseg() (struct wseg *) alloc(sizeof (struct wseg))
#define dealloc_seg(wseg) free((genericptr_t) (wseg))
@@ -477,31 +479,46 @@ boolean use_detection_glyph;
* of segments, including the dummy. Called from save.c.
*/
void
save_worm(fd, mode)
int fd, mode;
save_worm(nhfp)
NHFILE *nhfp;
{
int i;
int count;
struct wseg *curr, *temp;
if (perform_bwrite(mode)) {
if (perform_bwrite(nhfp)) {
for (i = 1; i < MAX_NUM_WORMS; i++) {
for (count = 0, curr = wtails[i]; curr; curr = curr->nseg)
count++;
/* Save number of segments */
bwrite(fd, (genericptr_t) &count, sizeof(int));
if (nhfp->structlevel)
bwrite(nhfp->fd, (genericptr_t) &count, sizeof(int));
if (nhfp->fieldlevel)
sfo_int(nhfp, &count, "worm", "segment_count", 1);
/* Save segment locations of the monster. */
if (count) {
for (curr = wtails[i]; curr; curr = curr->nseg) {
bwrite(fd, (genericptr_t) & (curr->wx), sizeof(xchar));
bwrite(fd, (genericptr_t) & (curr->wy), sizeof(xchar));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) &(curr->wx), sizeof(xchar));
bwrite(nhfp->fd, (genericptr_t) &(curr->wy), sizeof(xchar));
}
if (nhfp->fieldlevel) {
sfo_xchar(nhfp, &(curr->wx), "worm", "wx", 1);
sfo_xchar(nhfp, &(curr->wy), "worm", "wy", 1);
}
}
}
}
bwrite(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
if (nhfp->structlevel) {
bwrite(nhfp->fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
}
if (nhfp->fieldlevel) {
for (i = 0; i < MAX_NUM_WORMS; ++i)
sfo_long(nhfp, &wgrowtime[i], "worm", "wgrowtime", 1);
}
}
if (release_data(mode)) {
if (release_data(nhfp)) {
/* Free the segments only. savemonchn() will take care of the
* monsters. */
for (i = 1; i < MAX_NUM_WORMS; i++) {
@@ -518,29 +535,38 @@ int fd, mode;
}
}
/* SAVE2018 */
/*
* rest_worm()
*
* Restore the worm information from the save file. Called from restore.c
*/
void
rest_worm(fd)
int fd;
rest_worm(nhfp)
NHFILE *nhfp;
{
int i, j, count;
struct wseg *curr, *temp;
for (i = 1; i < MAX_NUM_WORMS; i++) {
mread(fd, (genericptr_t) &count, sizeof(int));
if (!count)
continue; /* none */
if (nhfp->structlevel)
mread(nhfp->fd, (genericptr_t) &count, sizeof(int));
if (nhfp->fieldlevel)
sfi_int(nhfp, &count, "worm", "segment_count", 1);
/* Get the segments. */
for (curr = (struct wseg *) 0, j = 0; j < count; j++) {
temp = newseg();
temp->nseg = (struct wseg *) 0;
mread(fd, (genericptr_t) & (temp->wx), sizeof(xchar));
mread(fd, (genericptr_t) & (temp->wy), sizeof(xchar));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) &(temp->wx), sizeof(xchar));
mread(nhfp->fd, (genericptr_t) &(temp->wy), sizeof(xchar));
}
if (nhfp->fieldlevel) {
sfi_xchar(nhfp, &(temp->wx), "worm", "wx", 1);
sfi_xchar(nhfp, &(temp->wy), "worm", "wy", 1);
}
if (curr)
curr->nseg = temp;
else
@@ -549,7 +575,13 @@ int fd;
}
wheads[i] = curr;
}
mread(fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
if (nhfp->structlevel) {
mread(nhfp->fd, (genericptr_t) wgrowtime, sizeof(wgrowtime));
}
if (nhfp->fieldlevel) {
for (i = 0; i < MAX_NUM_WORMS; ++i)
sfi_long(nhfp, &wgrowtime[i], "worm", "wgrowtime", 1);
}
}
/*