TADS 2 savefiles being saved as datafiles

So I’ve had a bug report that Parchment couldn’t restore TADS 2 files, and the cause is that the save command results in a data file being saved, but the restore command specifies a save file. Gargoyle 2023.1 also has this issue, although Gargoyle 2019.1 did not. One example file which has this issue is Babel.

The cause seems to be because the TADS 2 askfile function didn’t always have a filetype argument, as the docs explain:

On some systems, the open-file dialogue will filter the files it displays so that the player only sees files of the particular type being requested. The file_type_code parameter lets you specify the type of file you’re interested in, so that the dialogue can use the appropriate filtering on systems that support this. The file_type_code can be one of the following values, defined in adv.t:

FILE_TYPE_GAME - a game data file (.gam)
FILE_TYPE_SAVE - a saved game (.sav)
FILE_TYPE_LOG - a transcript (log) file
FILE_TYPE_DATA - general data file (used for fopen())
FILE_TYPE_CMD - command input file
FILE_TYPE_TEXT - text file
FILE_TYPE_BIN - binary data file
FILE_TYPE_UNKNOWN - unknown file type

If you leave out the type code arguments in a call to askfile(), the function will behave as it did with previous versions of TADS. This means that your prompt string must contain the word “save” or “write” in order to show a “save file” dialogue rather than an “open file” dialogue on those systems that differentiate between these dialogue types.

The fact that it used to work in Gargoyle gives me hope we can fix it again, but I have no idea where to look for a solution. Anyone have any ideas?

2 Likes

I have tried all the interpreters I have with UU1, here is a report:

Gargoyle 2023.1: Needs appending .glksave extension to the save filename. Then you can restore them.

Parchment (iplayif.com, 4/28/23): Same as Gargoyle.

Spatterlight (v1.0): Saves with .glkdata extension by default, also supports restoring from .glkdata.

Lectrote (v1.4.3): Saves with .glkdata extension by default, but won’t list .glkdata while restoring. It is expecting .glksave. Also it doesn’t allow changing the extension while saving.

Edit: Added version info for software for future reference.

3 Likes

Could you try it with Gargoyle 2019.1.1 to confirm that it did used to work?

I couldn’t try 2019.1.1, no Mojave build in releases. But I have tried 2019.1.

It saves with .sav extension just like 2022.1 and 2023.1 but unlike them it also supports restoring from .sav files. 2022.1 and 2023.1 require .glksave extension.

The main thing we want is that, without manually specifying or changing the file extension, you can save and restore a savefile in the same interpreter.

Only Gargoyle 2019.1 and Spatterlight do that at the moment. All others need to be tweaked by their respective developers.

In Gargoyle, this was exposed when I synced with the latest CheapGlk, which follows the recommendations in §6.1 of the Glk spec:

The library should take the given filename argument, and delete any characters illegal for a filename.… The library should also truncate the argument at the first period … then append an appropriate suffix, depending on the usage: “.glkdata” for fileusage_Data, “.glksave” for fileusage_SavedGame, “.txt” for fileusage_Transcript and fileusage_InputRecord.

This mixes with what I think is a bug in TADS. Look here. This is a general purpose “open file dialog” function.

The interpreter uses the prompt supplied (by the game, through the TADS standard library) to figure out what to show the user. If the prompt contains “save”, for example, it assumes it’s saving, not restoring. Specifically in this code, file_type is what’s important: this maps to Glk’s file usage (e.g. fileusage_SavedGame). Line 1005 starts by assuming a save file. But then look at the loop on line 1026: if none of the “restore game” strings match, then file_type is set to OSFTUNK, which maps to fileusage_Data. Buy why must the prompt be “restore game” for the file type to be a save? When a save game dialog is used, then, the file type becomes OSFTUNK.

So the result is that fileusage_Data is passed for save games (but not restore). On Gargoyle 2019 (on Windows, at least), this uses a filter of *.*, and doesn’t add any extension. But TADS, it looks like, adds .sav, if the file has no extension. On restore, Gargoyle 2019 uses *.sav, which just so happens to line up with what TADS uses. It’s incidentally correct.

What happens on 2023.1 is that *.glkdata is used for saves now, because TADS said it’s a datafile (due to the presumed bug noted above). But TADS gets it right on restore, meaning the file filter is *.glksave, which doesn’t show the original save file.

I think the fix needs to be in bif.c. The prompts, in Babel at least, look like this:

  • “File to save game in”
  • “File to restore game from”

So the logic should probably wind up something like this:

  • If “save” or “write” is in the prompt, this is OS_AFP_SAVE, otherwise OS_AFP_OPEN [this logic currently exists]
  • If “save game” or “restore game” is in the prompt, this is OSFTSAVE, otherwise OSFTUNK [this is new, replacing the loop on 1026]
2 Likes

I looked at that function yesterday but couldn’t work out what was wrong, so thanks for pointing it out: line 1028 is just completely wrong! It would erase all the good work that the first loop did identifying the save prompt.

Do you think you could put a PR together with what you’re proposing at the end?

Sure thing! I’ll likely have something ready this weekend.

1 Like

Does anyone know if there any non-English TADS 2 games that would be affected? IFDB only has 344 TADS 2 games in total, so if there are it would surely be a very small number, meaning we could consider adding the vocab for their languages.

This TADS search has no results, but that doesn’t mean the data is correct…

IF Archive only has a Russian translation of the library, so possibly the only non-English TADS 2 game ever made was Andrey Grankin’s translation of Ditch Day Drifter.

Thanks to @cas’s fix, Parchment can now save/restore TADS 2 games. I’m sure the fix will find its way into the other interpreters in time.

3 Likes

Although this fixes saving/restoring in-game, restoring after dying (i.e. at the Please enter RESTORE, RESTART, QUIT, or UNDO: > prompt) now shows an empty window even if you’ve saved previously. It seems to be looking for data files instead of save files.

Of course, you can just restart at the prompt and then restore in-game, but I thought I’d mention it anyway.

Ah, yes I can see why. If a game is using the standard library’s die function, then the prompt is “File to restore”, which won’t be caught by Cas’s new logic.

I’m assuming an earlier version of std.t had the same prompt text but without the FILE_TYPE_SAVE argument…

I think we have a fix, but I haven’t tested it myself. Do you know of a game where dying is relatively quick and easy? :laughing:

1 Like

You can die fairly quickly in UU1 with the following command sequence:

get lamp. x master. g. g. get key. n. ne. unlock grate with it. open it. d. light lamp. s. sw. break glass
1 Like

Sorry it took so long, but the fix for restoring after game over has finally been merged into Emglken and Parchment.

1 Like