Which interpreters comply with ZMS 1.1 regarding prompt parameter of @save/@restore opcodes?

Are there any interpreters for Z-Machine that obey the Standard 1.1 directive that a prompt parameter for the @save and @restore opcodes can be given to suppress prompting the user for a filename? The relevant text is:

***[1.1] As of Standard 1.1 an additional optional parameter, prompt, is allowed on
Version 5 extended save/restore. This allows a game author to tell the interpreter whether it
should ask for confirmation of the provided file name (prompt is 1), or just silently
save/restore using the provided filename (prompt is 0). If the parameter is not provided,
whether to prompt or not is a matter for the interpreter - this might be globally user-
configurable. Infocom’s interpreters do prompt for filenames, many modern ones do not.

The version of Frotz in gargoyle the I7 IDE for Linux (I think Frotz 2.50) reports 1.1 compliance but seems to ignore the prompt parameter of the opcode. A filename prompt is produce regardless of whether prompt is 0 or 1. (EDIT: It looks like I was mixing up my interpreters before.)

I know that WinFrotz obeys the prompt parameter, but I’m not aware of any other interpreters that do. EDIT: Per the efforts of DavidG and cas (see below), support for this feature has now been added to both Frotz and Bocfel (used by Gargoyle).

1 Like

I never got around to implementing any of the additional operands on @save in ZVM, but no one ever asked about them either. And it does claim to be a 1.1 interpreter…

1 Like

What test program were you using?

Here’s a short example program.

Constant Story "save/restore prompt parameter";
Constant Headline "^(a ZMS 1.1 compliance test)^";

Include "Parser";
Include "VerbLib";
Include "Grammar";

Array hopcount --> 1;

Array savename string "hopcount.aux";

Class Room
    has light;

Room Start "Starting Point"
    with    description
                "An uninteresting room.",
            before [;
                Jump: print_ret "Hop count = ", ++(hopcount-->0), ".";
                WaveHands: SilentSave();
                Wait: SilentRestore();
            ];

[ SilentSave result ;
    @save hopcount 2 savename 0 -> result;
];

[ SilentRestore result ;
    @restore hopcount 2 savename 0 -> result;
];

[ Initialise ;

    location = Start;

    print ">JUMP   --   increase counter^";
    print ">WAVE   --   save counter (silently, in theory)^";
    print ">WAIT   --   restore counter (silently, in theory)^";

];
2 Likes

Thanks. I’ll go over this tomorrow and see what’s going on in the current Frotz code.

I filed an issue on this at https://gitlab.com/DavidGriffith/frotz/-/issues/258, fixed the oversight, and closed out that issue.

Thank you @otistdog for bringing this to my attention.

3 Likes

Thank you! That makes two major interpreters that support this aspect of the ZMS 1.1 standard.

Any chance of Bocfel (which is the Z-Machine interpreter actually used by Gargoyle) being updated to support this feature? The version of Gargoyle released in 2019 seems to use Bocfel 1.0.1, which also ignores the prompt parameter for these opcodes. There are some newer versions available, but I don’t see anything in the change notes (Downloads - Bocfel) that seems relevant to this. Is that maintained by @cas?

Maybe… I’ve intentionally kept this unimplemented because I’m wary of allowing arbitrary files to be written by a game. Unfortunately, due to the fact that Glk doesn’t allow filename suggestions, that means that if a game is trying to save a specific file, unprompted, the user will be shown a dialog with some name supplied by the Glk implementation (e.g. Untitled.glksave). This isn’t exactly user friendly.

I’d probably be comfortable adding unprompted save files which are confined to their own per-game directory. At least then the game can’t do anything but overwrite its own files, which is perfectly valid.

How many games are there out in the wild which use these extended save/restore features? I know SameGame does for high scores, but I’m not aware of any others.

1 Like

I think it’s something of a chicken-and-egg problem. There’s not much point in using a feature that’s not supported by the most popular interpreters. There are several Glulx games that use silent file writes and reads, I believe.

I know effectively nothing about Glk, but I’m looking at the specification. I think section 6 (Glk: A Portable Interface Standard for IF) is the governing portion, and it seems to explicitly support this kind of activity:

A fileref does not have to refer to a file which actually exists. You can create a fileref for a nonexistent file, and then open it in write mode to create a new file.

and:

When a fileref is created non-interactively (glk_fileref_create_by_name, glk_fileref_create_temp) the default rules always apply.

and in Section 6.1, regarding glk_fileref_create_by_name():

This creates a reference to a file with a specific name. The file will be in a fixed location relevant to your program, and visible to the player. [This usually means “in the same directory as your program.”]

Is that not the function that could be used to write a file with a name specified by the author instead of the player?

For sure, and I’m not using that as an excuse to not implement silent reads/writes; just a general interest in how common it is. In fact, I’ve just finished up an implementation for Bocfel, and I ought to be able to backport it to the 1.4 branch and get it into the next Gargoyle release.

Glk can open arbitrary (-ish) files, yes; but the issue I was referring to is the fact that Glk cannot display a prompt with a suggested filename (per the 1.1 requirement). Any suggested filename is entirely up to the Glk implementation.

A possible solution is a Gargoyle extension which allows a suggested filename. I don’t really want to extend Gargoyle too far past standard Glk, but it might be worth doing.

2 Likes

I was preoccupied with V6 EGA graphics conversions and didn’t ponder this as deeply as I should have. Your concerns are spot on. I’m not sure I’ll want to keep this in Frotz. If I leave it in, I want to restrict the filename to <gamename>.aux. Without restrictions, this is asking for trouble.

Regarding that type of concern, section 6.1 of the Glk specification goes on to say:

Earlier versions of the Glk spec specified that the library may have to extend, truncate, or change your name argument in order to produce a legal native filename. This remains true. However, since Glk was originally proposed, the world has largely reached concensus about what a filename looks like. Therefore, it is worth including some recommended library behavior here. Libraries that share this behavior will more easily be able to exchange files, which may be valuable both to authors (distributing data files for games) and for players (moving data between different computers or different applications).

The library should take the given filename argument, and delete any characters illegal for a filename. This will include all of the following characters (and more, if the OS requires it): slash, backslash, angle brackets (less-than and greater-than), colon, double-quote, pipe (vertical bar), question-mark, asterisk. The library should also truncate the argument at the first period (delete the first period and any following characters). If the result is the empty string, change it to the string “null”.

It should then append an appropriate suffix, depending on the usage: “.glkdata” for fileusage_Data, “.glksave” for fileusage_SavedGame, “.txt” for fileusage_Transcript and fileusage_InputRecord.

Perhaps those are useful guidelines that would help to create consistency across interpreters. I would suggest leaving period characters as an option, so that an author can invent an ID for their work and ask for files with names like “data1.storyid”, which could translate to a file data1.storyid.aux.

Thank you very much! That’s terrific news. Three major Z-Machine interpreters, now.