New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updated ScottFree #627
Updated ScottFree #627
Conversation
An improved ScottFree would be great! It's barely been touched since I ported it to Glk something like 8 years ago, and I think was pretty dormant before that. A few notes here:
However, if you decide to stick with POSIX, you'll be able to remove I did find a segfault with Pyramid of Doom (adv08.dat): (gdb) bt
#0 __strlen_avx2 () at ../sysdeps/x86_64/multiarch/strlen-avx2.S:74
#1 0x00007ffff79e22b1 in __vfprintf_internal (s=s@entry=0x7fffffffb8a0, format=0x40f360 "Location of item %d: %d, \"%s\"\n", ap=0x7fffffffd9d8, mode_flags=0)
at vfprintf-internal.c:1517
#2 0x00007ffff79e2ad6 in buffered_vfprintf (s=0x7ffff7b656a0 <_IO_2_1_stderr_>, format=format@entry=0x40f360 "Location of item %d: %d, \"%s\"\n",
args=args@entry=0x7fffffffd9d8, mode_flags=mode_flags@entry=0) at vfprintf-internal.c:2261
#3 0x00007ffff79e1cd4 in __vfprintf_internal (s=<optimized out>, format=0x40f360 "Location of item %d: %d, \"%s\"\n", ap=ap@entry=0x7fffffffd9d8,
mode_flags=mode_flags@entry=0) at vfprintf-internal.c:1236
#4 0x00007ffff79cdee9 in __fprintf (stream=<optimized out>, format=<optimized out>) at fprintf.c:32
#5 0x0000000000405940 in LoadDatabase (f=0x444e30, loud=1) at /home/chris/github/garglk/terps/scott/scott.c:540
#6 0x00000000004097e0 in detect_game (file_name=0x7fffffffe150 "/home/chris/Programming/scottfree/games/adv08.dat")
at /home/chris/github/garglk/terps/scott/detectgame.c:143
#7 0x0000000000408d23 in glk_main () at /home/chris/github/garglk/terps/scott/scott.c:2015
#8 0x000000000040e239 in main (argc=2, argv=0x7fffffffdd18) at /home/chris/github/garglk/garglk/main.c:50
(gdb) frame 5
#5 0x0000000000405940 in LoadDatabase (f=0x444e30, loud=1) at /home/chris/github/garglk/terps/scott/scott.c:540
540 fprintf(stderr, "Location of item %d: %d, \"%s\"\n", ct, ip->Location, Rooms[ip->Location].Text);
(gdb) print ip->Location
$3 = 255 '\377'
(gdb) print Rooms[ip->Location]
$4 = {Text = 0x371 <error: Cannot access memory at address 0x371>, Exits = {-120, 92, 0, 0, -26838, 27077}, Image = 61 '='} I know nothing about the Scott Adams format, but to a naive eye it looks like 255 is a sentinel value? |
Let's see if MinGW complains.
Try to stay C99 for now. Also rewrite LoadTitleScreen() slightly.
Thanks for taking a look! I was afraid that there would be embarrassing bugs left, but that one was pretty bad. Not only was the "print lots and lots of debug info" switch on, every game that starts with the player carrying something would crash. Should be fixed now. It sounds like we will eventually have to switch to POSIX for convenience, but let's try to stay C99 for now. I added lots of header includes trying to make MinGW happy, but |
Also change to safe usage of them.
This was probably never needed.
Just to make them more symmetrical.
terps/scott/gameinfo.c
Outdated
|
||
/* This is supposed to be the original ScottFree system | ||
messages in second person, as far as possible */ | ||
char *sysdict[MAX_SYSMESS] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably this would be better as const char *
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I know I'm being annoying here, but there are lots of places that ought to be const throughout the code. Anything which is just string literals should be stored in const char*
, and when those changes are made, warnings will radiate out to various other functions/variables, but it's simple enough to fix as you find them.
The Glk API, unfortunately, takes some char *
values when it should take const char *
, so casts will be required there, but throughout ScottFree things ought to be const except where they're modified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely not annoying! Thanks the review. I hope I got all of them.
terps/scott/layouttext.c
Outdated
|
||
int diff = 0; | ||
|
||
while (diff < columns && !isspace(buf[pos])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is always one of my least-favorite review issues, because it seems so ridiculous, but when passing a char
to the ctype
functions, you need to cast it to unsigned char
. Why? Because the C standard says so, that's why...
But it's really to accommodate systems which use macros plus lookup tables to speed up these functions. Solaris used to do this, and to my recollection NetBSD did as well. I'm not sure any modern systems still do, but they're allowed to. On Solaris, isspace
used to look like this:
#define isspace(c) ((__ctype + 1)[c] & _S)
And __ctype
is an array mapping unsigned char
to a set of bits indicating which properties each character has. The + 1
is because EOF (-1 on Solaris and probably ever other existing system) has to be handled as well. So isspace(x)
will index directly into the array, and if you have a signed char
type, and the value is negative, you'll index backward into something that's totally unrelated.
So, long story short, all ctype
functions are required to take “an int
, the value of which shall be representable as an unsigned char
or shall equal the macro EOF
.” That's backwards compatibility for you.
terps/scott/load_TI99_4a.c
Outdated
} | ||
|
||
struct Keyword { | ||
char *name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recommend making this a const char *.
|
||
int offset; | ||
|
||
#pragma mark rooms |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When warnings are enabled with gcc (which they're not, for some reason, but should be: I must have just forgotten to add it), these pragmas cause warnings. They ought to be wrapped in tests to see if the compiler is clang.
terps/scott/scott.c
Outdated
//#ifdef __GNUC__ | ||
//__attribute__((__format__(__printf__, 2, 3))) | ||
//#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be removed
And add casts where needed.
Unfortunately this commit contains quite a number of changes all over the code. It completely overhauls the way we read TI-99/4A format actions and also tries to clean up other parts of the action code by removing magic numbers and renaming variables.
This got lost by when I added the TI994A_STYLE flag.
Broke this when merging the FlushRoomDescription() functions.
This never worked as indended.
@angstsmurf Do you feel this is in a pretty good state for a full review again? I'm happy to look it over and bring it in to Gargoyle if you're fine with its current state. |
terps/scott/TI99_4a_terp.c
Outdated
ActionResultType PerformTI99Line(uint8_t *action_line) | ||
{ | ||
if (action_line == NULL) | ||
return 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this returns an enum, it ought to use the enum names (ACT_FAILURE here, preusmably).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
terps/scott/TI99_4a_terp.c
Outdated
#include "scott.h" | ||
#include "TI99_4a_terp.h" | ||
|
||
ActionResultType PerformTI99Line(uint8_t *action_line) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be static
since it's only used in this file.
In addition, it looks like action_line
can be const
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And done.
Use enum name ACT_FAILURE as return value Make function static and its parameter const
The Clang static analyzer pointed this out.
I don't think there is a lot left to be done here except testing games, unless you have more comments. I suppose I could add some kind of script reading mechanism to make testing easier. Also, the Mysterious Adventures (and perhaps others) need the PREHISTORIC_LAMP setting that destroys the lamp when it runs out, and there is no way to set this in Gargoyle. This problem exists in the current ScottFree in master as well. Perhaps I could just calculate checksums and autodetect these games. |
Such as #RESTORE and #SCRIPT, to avoid conflicts with original game commands, like RESTORE and RESTART being understood as REST, a synonym of WAIT.
This detects the "extracted" dat versions of Brian Howarth's 11 Mysterious Adventures and switches on the SCOTTLIGHT and PREHISTORIC_LAMP options for them, for correct lamp behaviour. SCOTTLIGHT gives more precise warnings every five turns when the lamp is nearing depletion ("Light runs out in 5 turns.") PREHISTORIC_LAMP will remove the lamp from play when it runs out. If this is not set, as is the case when running these games with the ScottFree version currently in master, you end up with two lamps in your inventory, one lit and one unlit. This is not properly tested yet but seems to work.
Type #SCRIPT LOAD to load command script file
Now the lamp should work correctly in the Mysterious Adventures. I also implemented a way to read command scripts, (#SCRIPT LOAD) and have played through The Golden Baton, Arrow of Death part 1, Ten Little Indians, Waxworks, Secret Mission, Voodoo Castle, Strange Odyssey, Mystery Fun House, Ghost Town and The Golden Voyage to completion. I'd say this is ready to go, but more testing wouldn't hurt. |
This homebrew game does things in a slightly broken way, so TAKE ALL will pick up the wrong object.
Could break in rare cases. Also make the function static.
Also removes some unused code.
Sorry for the long delay, but I'd say it's high time to get this in! A couple considerations:
|
The current ScottFree code in Spatterlight is very different from this. The major part of it is support for the ZX Spectrum and Commodore 64 cassette versions released by Adventure International UK, with graphics and animations, none of which is included here. The point of this pull request was to start small with a subset that was easier to review, leaving out all the more hacky and controversial stuff, such as the 6502 emulator used to decompress the Commodore 64 versions, and then cleaning up and adding the rest later. By the way, someone just ported the complete Spatterlight ScottFree interpreter, 6502 emulator, German grammar and all, to C++ and the ScummVM framework. It might even make more sense to port that to Gargoyle instead, as some cruft was removed in the porting process, but that would require a bit of work. None of this precludes making a separate repository out of this pull request, of course.
Well, yes and no. The parser works a bit differently, but if you enter the exact same commands the output should be identical. |
Ok, I see.
I've looked at ScummVM's Glk implementation before, and they really hack up the interpreters to fit into their model. To port it over we'd need a compatibility layer, at least providing the common routines they use ( Offhand I think it'd be easier to get the Spatterlight code extracted and usable everywhere, but I'll try to find some time to see just how difficult it'd be to use the ScummVM code with a shim layer. For now, I'm not against a separate "in between" version as represented by this pull request.
I do think this is the right approach: I'd prefer for Gargoyle to not be the "official" source for any interpreters. At the moment the Scott Adams interpreter is from https://github.com/cspiegel/scottfree-glk, so it has an official-esque upstream, although it's just my straight port of the original ScottFree to Glk. I'm slowly trying to decouple Gargoyle from the interpreters so that it's easier to see Gargoyle's modifications, and to upgrade interpreters when necessary. A new upstream Scott Adams interpreter would make things a lot cleaner, and I'd rather keep my scottfree-glk repo just the original 1.14 ported to Glk, with no embellishments. If you'd prefer I can create a repository under the garglk organization to hold this version of the interpreter, and features from Spatterlight can slowly be added to it, then upstreamed here. If you're in favor of that I can do the work of shifting this branch over as the initial commit there.
OK, that's reasonable enough to not need two interpreters. |
I'm closing this now. It's too out of sync with the Spatterlight version. I made a fork here with all the three Scott Adams-related interpreters (ScottFree, TaylorMade and Plus) running in Gargoyle: https://github.com/angstsmurf/garglk/tree/saga Seems to work fine apart from locking up on certain animations. And I don't know how to get the AppImage workflow to build. |
I don't know if there is any interest in this, but I think that with a bit of polish, this could eventually become a nice update to the ScottFree interpreter.
It is a cut-down version of the Spatterlight ScottFree fork, which removes all support for German grammar, graphics, and ZX Spectrum and Commodore 64 versions, although there are traces of them left in the code. The TI-99/4A format support is still in there, but not very well tested.
New features:
EDIT: Now also supports IT (refers to the last noun) and TAKE ALL BUT X AND Y