From a99944fb09c765bb8006ad65233f67a58db05348 Mon Sep 17 00:00:00 2001 From: nhmall Date: Thu, 29 May 2025 09:59:29 -0400 Subject: [PATCH] improve sfctool messages --- include/hacklib.h | 4 +- src/hacklib.c | 19 +++-- src/mdlib.c | 4 +- src/version.c | 5 +- sys/windows/vs/sfctool.sln | 10 +++ sys/windows/vs/sfctool/sfctool.vcxproj | 2 +- util/sfctool.c | 110 ++++++++++++++++++++----- 7 files changed, 117 insertions(+), 37 deletions(-) diff --git a/include/hacklib.h b/include/hacklib.h index 96b6bdf39..18630e1b1 100644 --- a/include/hacklib.h +++ b/include/hacklib.h @@ -79,8 +79,8 @@ extern unsigned Strlen_(const char *, const char *, int) NONNULLPTRS; #endif extern int unicodeval_to_utf8str(int, uint8 *, size_t); extern boolean copy_bytes(int, int); -extern const char *datamodel(void); -extern const char *what_datamodel_is_this(int, int, int, int, int); +extern const char *datamodel(int); +extern const char *what_datamodel_is_this(int, int, int, int, int, int); #endif /* HACKLIB_H */ diff --git a/src/hacklib.c b/src/hacklib.c index fd8f20c91..209982751 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -957,20 +957,21 @@ copy_bytes(int ifd, int ofd) struct datamodel_information { int sz[MAX_D]; const char *datamodel; + const char *dmplatform; }; static struct datamodel_information dm[] = { { { (int) sizeof(short), (int) sizeof(int), (int) sizeof(long), (int) sizeof(long long), (int) sizeof(genericptr_t) }, - "" }, - { { 2, 4, 4, 8, 4 }, "ILP32LL64" }, /* Windows, Unix x86 */ - { { 2, 4, 4, 8, 8 }, "IL32LLP64" }, /* Windows x64 */ - { { 2, 4, 8, 8, 8 }, "I32LP64" }, /* Unix 64-bit */ - { { 2, 8, 8, 8, 8 }, "ILP64" }, /* HAL, SPARC64 */ + "", "" }, + { { 2, 4, 4, 8, 4 }, "ILP32LL64", "x86 32-bit" }, /* Windows or Unix */ + { { 2, 4, 4, 8, 8 }, "IL32LLP64", "Windows x64 64-bit" }, + { { 2, 4, 8, 8, 8 }, "I32LP64", "Unix 64-bit"}, + { { 2, 8, 8, 8, 8 }, "ILP64", "Unix ILP64"}, /* HAL, SPARC64 */ }; const char * -datamodel(void) +datamodel(int retidx) { int i, j, matchcount; static const char *unknown = "Unknown"; @@ -982,13 +983,13 @@ datamodel(void) ++matchcount; } if (matchcount == MAX_D) - return dm[i].datamodel; + return (retidx == 0) ? dm[i].datamodel : dm[i].dmplatform; } return unknown; } const char * -what_datamodel_is_this(int szshort, int szint, int szlong, int szll, +what_datamodel_is_this(int retidx, int szshort, int szint, int szlong, int szll, int szptr) { int i; @@ -998,7 +999,7 @@ what_datamodel_is_this(int szshort, int szint, int szlong, int szll, if (szshort == dm[i].sz[0] && szint == dm[i].sz[1] && szlong == dm[i].sz[2] && szll == dm[i].sz[3] && szptr == dm[i].sz[4]) - return dm[i].datamodel; + return (retidx == 0) ? dm[i].datamodel : dm[i].dmplatform; } return unknown; } diff --git a/src/mdlib.c b/src/mdlib.c index 701b39901..fb4155dab 100644 --- a/src/mdlib.c +++ b/src/mdlib.c @@ -56,7 +56,7 @@ static boolean date_via_env = FALSE; extern unsigned long md_ignored_features(void); -extern const char *datamodel(void); +extern const char *datamodel(int); char *version_id_string(char *, size_t, const char *) NONNULL NONNULLPTRS; char *bannerc_string(char *, size_t, const char *) NONNULL NONNULLPTRS; int case_insensitive_comp(const char *, const char *) NONNULLPTRS; @@ -696,7 +696,7 @@ build_options(void) STOREOPTTEXT(optbuf); optbuf[0] = '\0'; length = COLNO + 1; /* force 1st item onto new line */ - Strcat(strcpy(buf, datamodel()), " data model,"); + Strcat(strcpy(buf, datamodel(0)), " data model,"); opt_out_words(buf, &length); for (i = 0; i < SIZE(build_opts); i++) { #if !defined(MAKEDEFS_C) && defined(FOR_RUNTIME) diff --git a/src/version.c b/src/version.c index 04987929c..99c36efdf 100644 --- a/src/version.c +++ b/src/version.c @@ -778,9 +778,10 @@ compare_critical_bytes(NHFILE *nhfp, int *idx_1st_mismatch, unsigned long utdfla } for (i = 1; i < cnt; ++i) { if (cscbuf[i] != critical_sizes[i].ucsize) { - const char *dm = datamodel(), *dmfile; + const char *dm = datamodel(0), *dmfile; - dmfile = what_datamodel_is_this(cscbuf[1], /* short */ + dmfile = what_datamodel_is_this(0, + cscbuf[1], /* short */ cscbuf[2], /* int */ cscbuf[3], /* long */ cscbuf[4], /* long long */ diff --git a/sys/windows/vs/sfctool.sln b/sys/windows/vs/sfctool.sln index c997bd45f..06ef30f69 100644 --- a/sys/windows/vs/sfctool.sln +++ b/sys/windows/vs/sfctool.sln @@ -16,6 +16,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sftags", "sftags\sftags.vcx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fetchctags", "fetchctags\fetchctags.vcxproj", "{AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hacklib", "hacklib\hacklib.vcxproj", "{096FD6BB-256A-4E68-9B09-2ACA7C606FF3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -48,6 +50,14 @@ Global {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Release|x64.Build.0 = Release|x64 {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Release|x86.ActiveCfg = Release|Win32 {AAE63AD3-8185-4E19-B6A3-13F4CB891AAD}.Release|x86.Build.0 = Release|Win32 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Debug|x64.ActiveCfg = Debug|x64 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Debug|x64.Build.0 = Debug|x64 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Debug|x86.ActiveCfg = Debug|Win32 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Debug|x86.Build.0 = Debug|Win32 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Release|x64.ActiveCfg = Release|x64 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Release|x64.Build.0 = Release|x64 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Release|x86.ActiveCfg = Release|Win32 + {096FD6BB-256A-4E68-9B09-2ACA7C606FF3}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sys/windows/vs/sfctool/sfctool.vcxproj b/sys/windows/vs/sfctool/sfctool.vcxproj index e63a0c61d..7a64f39c9 100644 --- a/sys/windows/vs/sfctool/sfctool.vcxproj +++ b/sys/windows/vs/sfctool/sfctool.vcxproj @@ -194,4 +194,4 @@ - + \ No newline at end of file diff --git a/util/sfctool.c b/util/sfctool.c index cc3f9e464..c79be9254 100644 --- a/util/sfctool.c +++ b/util/sfctool.c @@ -77,6 +77,8 @@ static NHFILE *create_dstfile(char *, enum saveformats); static const char *style_to_text(enum saveformats style); static void read_sysconf(void); static int length_without_val(const char *user_string, int len); +static void usage(int argc, char **argv); +static const char *briefname(const char *fnam); void zero_nhfile(NHFILE *); NHFILE *new_nhfile(void); @@ -158,18 +160,19 @@ static char srclogfilenm[BUFSZ], dstlogfilenm[BUFSZ]; *********/ int -main(int argc UNUSED, char *argv[]) +main(int argc, char *argv[]) { int arg; char folderbuf[5000]; const char *suffix = (convertstyle == exportascii) ? ".exportascii" : ""; - boolean add_folder = TRUE; -#ifdef WIN32 - size_t sz; -#endif + boolean add_folder = TRUE, add_extension = FALSE; - if (argc < 3) - exit(EXIT_FAILURE); +#ifdef WIN32 + const char *default_extension = ".NetHack-saved-game"; + size_t sz; +#else + const char *default_extension = ""; +#endif runtime_info_init(); /* mdlib.c */ #ifdef UNIX @@ -188,13 +191,26 @@ main(int argc UNUSED, char *argv[]) exit(EXIT_FAILURE); sz = strlen(folderbuf); (void) snprintf(eos(folderbuf), sizeof folderbuf - sz, - "\\AppData\\Local\\NetHack\\3.7\\"); - //initoptions_init(); // This allows OPTIONS in syscf on Windows. + "\\AppData\\Local\\NetHack\\3.7\\"); + // initoptions_init(); // This allows OPTIONS in syscf on Windows. set_default_prefix_locations(argv[0]); #endif read_sysconf(); + thisdatamodel = datamodel(0); + if (argc < 3 && !(argc == 2 && !strcmp(argv[1], "-d"))) { + usage(argc, argv); + exit(EXIT_FAILURE); + } for (arg = 1; arg < argc; ++arg) { + if (arg == 1 && !strcmp(argv[arg], "-d")) { + fprintf( + stdout, + "\nThe historical savefile datamodel supported by this utility is %s (%s).\n", + thisdatamodel, datamodel(1)); + exit(EXIT_SUCCESS); + } + if (arg == 1 && !strcmp(argv[arg], "-u")) { explicit_option = TRUE; chosen_unconvert = TRUE; @@ -209,6 +225,7 @@ main(int argc UNUSED, char *argv[]) chosen_unconvert = FALSE; continue; } + if (arg == 2) { size_t ln = strlen(argv[arg]); boolean addseparator = FALSE; @@ -223,13 +240,23 @@ main(int argc UNUSED, char *argv[]) } else { add_folder = FALSE; } +#ifdef WIN32 + /* On Windows we allow specifying the savefile name without the extention + * in the arguments */ + if (strstr(argv[arg], default_extension) == 0) + add_extension = TRUE; +#endif if (explicit_option) { if (add_folder) ln += strlen(folderbuf); + if (add_extension) + ln += strlen(default_extension); unconverted_filename = (char *) alloc((int) ln + 1); - Snprintf(unconverted_filename, ln + 1, "%s%s%s", + Snprintf(unconverted_filename, ln + 1, "%s%s%s%s", add_folder ? folderbuf : "", - addseparator ? "/" : "", argv[arg]); + addseparator ? "/" : "", + argv[arg], + add_extension ? default_extension : ""); ln += strlen(suffix); converted_filename = (char *) alloc((int) ln + 1); Snprintf(converted_filename, ln + 1, "%s%s", @@ -246,7 +273,7 @@ main(int argc UNUSED, char *argv[]) !converted_filename ? "" : "un"); exit(EXIT_FAILURE); /* need both filenames */ } - thisdatamodel = datamodel(); + my_sf_init(); if (chosen_unconvert) { process_savefile(converted_filename, convertstyle, @@ -274,16 +301,27 @@ process_savefile(const char *srcfnam, enum saveformats srcstyle, extern struct version_info vers_info; extern uchar cscbuf[]; /* nh_uncompress(fq_save); */ + const char *dmfile; if ((nhfp[srcidx] = open_srcfile(srcfnam, srcstyle)) == 0) return 0; sfstatus = validate(nhfp[srcidx], srcfnam, FALSE); + dmfile = what_datamodel_is_this(0, + cscbuf[1], /* short */ + cscbuf[2], /* int */ + cscbuf[3], /* long */ + cscbuf[4], /* long long */ + cscbuf[5]); /* ptr */ if (sfstatus > SF_UPTODATE && ((sfstatus <= SF_CRITICAL_BYTE_COUNT_MISMATCH) || !unconvert)) { fprintf(stderr, - "This savefile is not compatible with %sutility.\n%s\n", - !unconvert ? "the datamodel of this particular " : "this ", - srcfnam); + "The %s savefile %s%s%s not compatible with this %s%sutility.\n", + briefname(srcfnam), + dmfile ? "is a " : "", + dmfile ? dmfile : "", + dmfile ? " savefile, thus" : " is", + thisdatamodel ? thisdatamodel : "", + thisdatamodel ? " " : ""); return 0; } if (sfstatus >= SF_DM_IL32LLP64_ON_ILP32LL64) { @@ -303,12 +341,16 @@ process_savefile(const char *srcfnam, enum saveformats srcstyle, nhfp[srcidx]->nhfpconvert = nhfp[CONVERTED]; } if (unconvert) - fprintf(stdout, "\n\nunconverting %s to %s %s\n", - style_to_text(srcstyle), style_to_text(cvtstyle), - thisdatamodel); + fprintf(stdout, "\n\nunconverting %s to %s savefile called %s.\n", + briefname((const char *) converted_filename), + dmfile, + briefname((const char *) unconverted_filename)); else - fprintf(stdout, "\n\nconverting %s %s to %s\n", - style_to_text(srcstyle), thisdatamodel, style_to_text(cvtstyle)); + fprintf(stdout, "\n\nconverting %s %s format %s to %s format\n", + style_to_text(srcstyle), + thisdatamodel, + briefname((const char *) unconverted_filename), + style_to_text(cvtstyle)); rewind_nhfile(nhfp[srcidx]); #ifdef SAVEFILE_DEBUGGING @@ -564,6 +606,17 @@ create_dstfile(char *fnam, enum saveformats mystyle) return nhfp; } +static const char * +briefname(const char *fnam) +{ + const char *bn = fnam, *sep = (const char *) 0; + + if ((sep = strrchr(fnam, '/')) || (sep = strrchr(fnam, '\\')) + || (sep = strrchr(fnam, ':'))) + bn = sep + 1; + return bn; +} + static const char * style_to_text(enum saveformats style) { @@ -1279,7 +1332,7 @@ free_oname(struct obj *obj) } } -#ifdef WIN32 +#ifdef WIN32 void win32_abort(void) { @@ -1320,4 +1373,19 @@ match_optname(const char *user_string, const char *optn_name, int min_length, && !strncmpi(optn_name, user_string, len)); } +staticfn void +usage(int argc, char **argv) +{ + char *cp = argv[0], *sep = (char *) 0; + + if ((sep = strrchr(cp, '/')) || (sep = strrchr(cp, '\\')) + || (sep = strrchr(cp, ':'))) + cp = sep + 1; + fprintf(stderr, + "\nTo convert a savefile to export format:\n %s %s %s\n", cp, + "-c", "savefile"); + fprintf(stderr, + "\nTo unconvert an exported savefile back into a savefile:\n %s %s %s\n", cp, + "-u", "savefile"); +} /* sfctool.c */