Commit Graph

4 Commits

Author SHA1 Message Date
nhmall
a654d08c3b save/restore changes - part 3
This is the third of a series of savefile-related changes.

    This adds early-days experimental support for a completely optional
    'sfctool' utility (savefile conversion tool), to be able to export
    a savefile's contents into a more portable format. There are likely
    to be bugs at this stage. In this initial first-attempt, the export
    format is a very simple ascii output.

    NetHack can be built entirely, without also building this tool.
    NetHack has no dependencies on the tool.

    Attempts were made to minimize duplication of existing NetHack code.
    To achieve that, unfortunately, #ifdef SFCTOOL and #ifndef SFCTOOL
    had to be sprinkled around through some of the existing NetHack
    source code, so that it could be re-used for building the utility.

    The process for building the sfctool typically recompiles the source
    files with #define SFCTOOL and a distinct object file with SF- is
    produced.

sfctool notes:

    Universal ctags is used and required to produce the sfctool utility.

    Some targets were added to the Unix and Windows Makefiles to
    facilitate the build process.

         make sfctool

    That should build a copy in util.

    Note: At present, the Unix Makefiles do not copy sfctool over to the
          NetHack playground during 'make install' or 'make update'.
          Until that gets resolved by someone, The tool will
          have to be manually copied there by the builder/admin if
          desired.
          cp util/sfctool ~/nh/install/games/lib/nethackdir/sfctool

    Also, a separate Visual Studio sfctool.sln solution was written and
    placed in sys/windows/vs. That has has only very limited testing.

    Usage:

      i)  To convert an existing savefile to an exportascii format
          that co-resides with the savefile:

          sfctool -c savefile

          That *must* be executed on the same platform / architecture /
          data model that produced the save file in the first place.

     ii)  To unconvert an existing exportascii format export file to a
          historical format savefile that can then be used by NetHack:

          sfctool -u savefile

          That must be executed on the same target platform / architecture /
          data model that was used to build the NetHack that will
          utilize the save file that results.

     A Windows example:

          sfctool -c Fred.NetHack-saved-game

          That should result in creation of Fred.NetHack-saved-game.exportascii
          from existing savefile:
              %USERPROFILE%\AppData\Local\NetHack\3.7\Fred.NetHack-saved-game

     A Unix example:

          sfctool -c 1000wizard

          That should result in creation of 1000wizard.exportascii.gz
          from existing savefile in the playground save directory:
              1000wizard.gz

  Current Mechanics:
     1. Makefile recipe, or script uses universal ctags to produce
        util/sf.tags.

     2. util/sftags is built and executed to read util/sf.tags and
        generate: include/sfproto.h and src/sfdata.c.

     3. util/sfctool is built from the following:
        generated file compiled with -DSFCTOOL:
                    src/sfdata.c       -> sfdata.o
        existing files compiled with -DSFCTOOL:
                    util/sfctool.c     -> sfctool.o
                    util/sfexpasc.c    -> sfexpasc.o
                    src/alloc.c        -> sf-alloc.o
                    src/monst.c        -> sf-monst.o
                    src/objects.c      -> sf-objects.o
                    src/sfbase.c       -> sfbase.o
                    src/sfstruct.c     -> sfstruct.o
                    src/nhlua.c        -> sf-nhlua.o
                    util/panic.c       -> panic.o
                    src/date.c         -> sf-date.o
                    src/decl.c         -> sf-decl.o
                    src/artifact.c     -> sf-artifact.o
                    src/dungeon.c      -> sf-dungeon.o
                    src/end.c          -> sf-end.o
                    src/engrave.c      -> sf-engrave.o
                    src/cfgfiles.c     -> sf-cfgfiles.o
                    src/files.c        -> sf-files.o
                    src/light.c        -> sf-light.o
                    src/mdlib.c        -> sf-mdlib.o
                    src/mkmaze.c       -> sf-mkmaze.o
                    src/mkroom.c       -> sf-mkroom.o
                    src/o_init.c       -> sf-o_init.o
                    src/region.c       -> sf-region.o
                    src/restore.c      -> sf-restore.o
                    src/rumors.c       -> sf-rumors.o
                    src/sys.c          -> sf-sys.o
                    src/timeout.c      -> sf-timeout.o
                    src/track.c        -> sf-track.o
                    src/version.c      -> sf-version.o
                    src/worm.c         -> sf-worm.o
                    src/strutil.c      -> strutil.o
2025-05-25 20:38:17 -04:00
nhmall
f4a6da2e52 save/restore changes - part 2
This is the second of a series of changes related to save/restore.

    No EDITLEVEL bump has been included, because although the code
    is changed extensively by this, the content of the savefiles have
    not been changed.

    Push the use of the structlevel bwrite() and mread() function use
    out of the core and into sfstruct.c. This is groundwork for upcoming
    changes.

    In the core, replace the bwrite() and mread() calls with the
    use of type-specific savefile output (Sfo) and savefile
    input (Sfi) macros.  The macros are defined in a new header file
    savefile.h, which also contains the prototypes for the sfo_* and
    sfi_* functions that the macros ultimately expand to. The functions
    themselves are in src/sfbase.c.

    On C99, each Sfo or Sfi macro expansion refers directly to the
    corresponding  type-specific sfo_* or sfi_* function.

    If C23 or later is is use, the majority (all but 3 types) of the
    macros refer to a single _Generic output routine sfo(nhfp, dt, tag),
    and a single _Generic input routine sfi(nhfp, dt, tag), which handles
    the dispatch of the type-specific underlying functions. This was
    somewhat experimental, but turned out to be practical because the
    compiler would gripe if the type for a variable was not included in
    the _Generic when passed as an argument, so it could be fixed.

    This alters the savefile verication process by having a common set
    return values for the related functions such as uptodate(),
    check_version(), etc. The new return values return more information
    about savefile incompatibilities, beyond failure/sucess. The
    additional information will be useful for an upcoming addition.
    The expanded return values are:
     SF_UPTODATE                     (0) everything matched and looks good
     SF_OUTDATED                     (1) savefile is outdated
     SF_CRITICAL_BYTE_COUNT_MISMATCH (2) critical size count mismatch
     SF_DM_IL32LLP64_ON_ILP32LL64    (3) Windows x64 savefile on x86
     SF_DM_I32LP64_ON_ILP32LL64      (4) Unix 64 savefile on x86
     SF_DM_ILP32LL64_ON_I32LP64      (5) x86 savefile on Unix 64
     SF_DM_ILP32LL64_ON_IL32LLP64    (6) x86 savefile on Windows x64
     SF_DM_I32LP64_ON_IL32LLP64      (7) Unix 64 savefile on Windows x64
     SF_DM_IL32LLP64_ON_I32LP64      (8) Windows x64 savefile on Unix 64
     SF_DM_MISMATCH                  (9) some other mismatch
    The callers in the core have been adjusted to deal with the expanded
    return values.

    Other miscellaneous inclusions:

       - go.oracle_loc -> svo.oracle_loc.
       - add a bit (1UL << 30) to  called SFCTOOL_BIT as groundwork
         for changes to follow.
2025-05-25 15:03:13 -04:00
nhmall
bc8c1f8f56 remove field-level savefile code 2019-12-08 07:27:01 -05:00
nhmall
7054e06e42 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.
2019-06-23 00:11:46 -04:00