Broken ScottFree with broken TI-99/4A format support!

This is an experiment to try adding support for the TI-99/4A Scott Adams games to ScottFree. It doesn’t actually work, but still gets further than expected.

I made a repository here with the GlkTerm source included, a makefile and an Xcode project. I have only tried building on my M1 Mac. It is a cut-down version of the Spatterlight ScottFree interpreter, using the GlkTerm library, with all support for graphics and the ZX Spectrum and C-64 versions removed. Fragments of the Bunyon interpreter are also sprinkled here and there. I’m afraid it is not in a very clean or readable state.

The relevant code is in the file load_TI99_4a.c, in particular the function ReadTI99Action().

Some games, like Adventureland and the other first four SACA games seems to work pretty well, while others, such as The Count and Savage Island, break at the first move. I haven’t tested any of them extensively, though. It reads games in the .fiad format only. (It also still plays TRS-80 format games, but that’s not what we are testing here.)

The main problem is that the action format is different, and that the TI-99/4A format allows more conditions and commands per action than the TRS-80 format that ScottFree uses natively. I’ve tried working around this by simply cutting up the too-long actions into several shorter ones and inserting extra continue commands to glue them together. This is a gross hack and it isn’t surprising that it doesn’t work perfectly, but many of the more severe problems seem to have other causes. I wonder if the differences in the TI-99/4A continue command (TRY) are to blame.

I don’t really expect to get much further with this. I’m posting it here in the hope that somebody will find it interesting, and perhaps even be able to explain why and where it breaks. Any ideas for alternative approaches are welcome.

6 Likes

I’ll be sure to read this in great detail. I’ve gotten started writing a terp for the TI-99/4A files at least once, so this is super interesting to me at least. :slight_smile:

In my case, I abandoned the effort due to a combination of not finding good documentation and not being able to figure out everything on my own, and it just being too much work, considering the end result. I seem to remember the actions being very different, removing some annoying old constraints while adding new ones.

Don’t get me wrong. I’d like to get further since it’s a slightly more capable engine than the original TRS-80 heritage one, and also investigate if there’s a connection to the later “v2” data files that later QuestProbe games use. (They may be completely unconnected, of course, but Scott Adams seems to have been pretty enamoured with his games on the TI-99.)

1 Like

I don’t know if this is relevant, but I made a Scottkit game, and when playing it using Scottkit player, I noticed 2 things:

  1. The command gameover still has one extra turn before really ending the game. It maybe my fault, but it seems that the game still takes user input before ending the game, even though there’s no more processing of said input.

  2. The random value seems to be called once per turn, rather than once per command. So, occur 10% and occur 50% either occurs both at the same time, or only 50%. I’d think that they should computed independently.

This is the behavior I noticed from ScottKit. I haven’t tested it with ScottFree.

1 Like

Just as an example of what is broken, here is beginning of The Count in this build:

Welcome to ADVENTURE: 5 'THE COUNT'. Dedicated to Alvin Files.
I see I was put to bed. I've overslept & it's after noon!
I've a hunch I've been robbed!
I see I was put to bed. I've overslept & it's after noon!
A bell rings somewhere: 'DING-DONG'.

Tell me what to do ? 

Note the repeated message. Also, the game will start in darkness. Here is the correct behaviour, from Bunyon:

Welcome to ADVENTURE: 5 'THE COUNT'. Dedicated to Alvin Files. I see I was put
to bed. I've overslept & it's after noon!
What shall I do? 

Looking at the actions (decompiled with Bunyon), there are a lot of statements like this:

try
    {
        goto rm_001;
        off flag_15;
        msg_002;        # "I see I was put to bed. I've overslept & it's after noon!";
        drop itm_000;        # Sheets
    }

That are not meant to fire on the first turn, but do anyway.

I suspect that it isn’t completely on-topic exactly, but those are interesting points.

That sounds wrong, but maybe there’s a sort of “do you wish to play again Y/N” input expected there. I need to do a bit of investigation to be sure.

That sounds even more wrong. The original BASIC source code generates a new random value every time a new action is evaluated at least:
380 IF NV(0) = 0 THEN F = 0 : IF RND(100) <= N THEN 400 ELSE NEXT X : GOTO 990

1 Like

To me, this sounds like the flags are initialized differently in the TI-99 engine. That’s one of the things I was very uncertain about when I made my attempt.

That was my first thought too. But it seems that most of the flags that are checked are set by earlier actions, so my hunch is that either the order in which the actions are checked is wrong, some opcodes are broken in translation, or that the TI-99 engine has a special mechanism to stop actions from being considered. As I mentioned, I still don’t quite understand what the parameter of the TRY command does.

I really should improve the debug tracing output of both Bunyon and ScottFree so that the differences can be seen more clearly.

My old notes weren’t a great help unfortunately. What I did, was to compare the binary data of the TI-99/4A version of Ghost Town with the TRS-80 version. I couldn’t get Bunyon working properly for me, or I would have sprinkled the source code with printf() statements until i understood it.

I found this script useful when building Bunyon. Or is that perhaps what you used?

It seems to work well for me, even if I was confused at first by the fact that the command line switches and file path had to be in the opposite order from what the documentation said.

1 Like

I completely missed that. It works great when I try it now. Nice!

I notice the save game command has a colon. Fixing that seems to fix the randomness error.

The game_over error, however, is still there. It only happens on occur but not on action so maybe @MikeTaylor should know? I’m on scottkit -p mode.

Just letting you know that I fixed a couple of opcodes, and many games run a lot better. Still very buggy, though.

EDIT: One more fix. I’m almost starting to believe that this can be done by adjusting exactly when and where the too-large actions are split.

EDIT 2: I think I’m getting close. This is ready for testing now.

Very nice! It looks like you’ve made a lot of progress, judging from the commit history.

I’m looking forward to writing some documentation on this whole thing once the last of the question marks are gone.

I made some more fixes and added support for disk image format and homebrew games.

I think the homebrew games expect the inventory to always show in the upper window, as they have no INVENTORY command. Also, it would be nice if ScottFree showed the startup screen text, like Bunyon does.

EDIT: I’m giving up again! Turns out the TRY mechanism is a lot more intricate than I had hoped, which breaks homebrew games like the Colossal Cave port. I have no idea how to implement it using the current approach.

I guess I could just add Bunyon to Spatterlight instead, but then Stu George would first have to release it under a GPL-compatible license.

It seems I did have an idea of how to implement the TRY mechanism after all, and now it works. Title screens and upper-window inventory also work.

2 Likes

I made this into a pull request for Gargoyle. Among other things this means that binary builds of Gargoyle with this ScottFree fork can be downloaded from Gargoyle’s Github Actions page. Now you can try this out without having to build it yourself.