Gargoyle on Haiku

Gargoyle is a player for interactive fiction (text adventure) games, such as Zork. I recently switched its UI to Qt, which resulted in Haiku support, for free, since Qt is available on Haiku.

It builds and runs just fine on Haiku, but I don’t know how to be friendly to Haiku packaging. For other non-Unix platforms (Windows and macOS), the build system puts all the binaries/libraries in a single place that platform-specific scripts pick up and use, and if that’s something that works on Haiku, I’d be happy to accommodate that. windows.sh and gargoyle_osx.sh are the scripts that do this.

If anybody is interested/willing to improve Haiku support, please come on by and take a look. There should be few to no code changes needed, just adjustments to the build to create a proper hierarchy for Haiku packaging.

If you’re interested in building to test, you’ll need a few (development) packages installed: freetype, libjpeg, zlib, libpng, libsndfile, mpg123, libopenmpt, fontconfig, and qt5

There are two sound backends, SDL and Qt. The SDL backend doesn’t work with Gargoyle on Haiku due to, I believe, conflicts between Qt and SDL over who owns the BApplication, so I wrote a Qt-based backend as a replacement. When configuring CMake, you have to select it:

cmake -DSOUND=QT …
11 Likes

is there a Qt release already?

Grabbed the sources and checking out a build atm :slight_smile:

EDIT build failed (log at Ubuntu Pastebin will stay up there for a month)
EDIT2 this is on 32bit haiku with gcc11

is there a Qt release already?

Sorry, should have been more clear about this. No, Qt support is only in master. A new release should be coming out in the near future, and that’s the impetus for getting proper Haiku support.

Grabbed the sources and checking out a build atm 

EDIT build failed (log at Ubuntu Pastebin 3 will stay up there for a month)
EDIT2 this is on 32bit haiku with gcc11

Thanks for testing! I’ve been using x86_64 Haiku, where this problem isn’t present. I just installed an x86 version and was able to reproduce this easily. I just pushed a fix for it to master. I can successfully build all of Gargoyle on x86 Haiku now.

It crashed at startup, but that may well be a result of my lack of understanding of Haiku’s packages, given that I had some clashing libraries (x86 and non-x86 versions); after a reboot the bootloader can’t find anything, so I’ll reinstall and try to be more careful, but at least you ought to be able to compile it now, if not run it.

2 Likes

Hello there, I’ve made a WIP package file for this software, I have a couple of questions though. : )

Does this have an Icon? Usually we take Icons of other OSes and remake them in the Haiku icon style for ports.

What is up with the stuff it tries to put into libexec? Haiku does not have this directory, and i don’t understand what it does on linux either, is this just executables the main executable wants to find? Could they be put into the data directory instead?
EDIT: after updating to the proper cmake args in the recipe it no longer does this, hopefully it works regardless

Where does the application look for config? it seems on linux this is some .rc file in $HOME, In haiku we have a proper API to locate these directories instead (The Haiku Book: FindDirectory.h File Reference), I had looked at the code, but i don’t really understand it to patch it.

Where are some scripts or files I can use to test this engine?

And here, my WIP recipe to play around with:

SUMMARY="An interactive fiction player"
DESCRIPTION="Gargoyle is an IF player that supports all the major interactive fiction formats.

Most interactive fiction is distributed as portable game files. These portable game files come in many formats. In the past, you used to have to download a separate player (interpreter) for each format of IF you wanted to play."
HOMEPAGE="https://github.com/garglk/garglk/"
rev="bbfc7a89db80a95e6c801a75612e1cf35c1392c4"
COPYRIGHT="2009 Tor Andersson"
LICENSE="GNU GPL v2"
REVISION="1"
SOURCE_URI="https://github.com/garglk/garglk/archive/${rev}.tar.gz"
SOURCE_DIR="garglk-${rev}"
CHECKSUM_SHA256="38108fe975a09afcc59932542ae3ac56db86d981870fe82d23b9473347e57f3e"


ARCHITECTURES="all !x86_gcc2"
SECONDARY_ARCHITECTURES="x86"

PROVIDES="
	garglk
	app:garglk
	cmd:gargoyle
	"
REQUIRES="
	haiku$secondaryArchSuffix
	lib:libfreetype$secondaryArchSuffix
	lib:libjpeg$secondaryArchSuffix
	lib:libmpg123$secondaryArchSuffix
	lib:libpng16$secondaryArchSuffix
	lib:libz$secondaryArchSuffix
	lib:libsndfile$secondaryArchSuffix
	lib:libopenmpt$secondaryArchSuffix
	lib:libfontconfig$secondaryArchSuffix
	lib:libQt5Core$secondaryArchSuffix >= 5.15.2
	"

BUILD_REQUIRES="
	haiku${secondaryArchSuffix}_devel
	devel:libfreetype$secondaryArchSuffix
	devel:libjpeg$secondaryArchSuffix
	devel:libmpg123$secondaryArchSuffix
	devel:libpng16$secondaryArchSuffix
	devel:libz$secondaryArchSuffix
	devel:libz$secondaryArchSuffix
	devel:libsndfile$secondaryArchSuffix
	devel:libopenmpt$secondaryArchSuffix
	devel:libfontconfig$secondaryArchSuffix
	devel:libQt5Core$secondaryArchSuffix
	"
BUILD_PREREQUIRES="
	cmd:cmake$secondaryArchSuffix
	cmd:gcc$secondaryArchSuffix
	cmd:ninja$secondaryArchSuffix
	cmd:pkg_config$secondaryArchSuffix
	"

BUILD()
{
	cmake -Bbuild $cmakeDirArgs -DSOUND=QT -GNinja
	ninja -Cbuild
}

INSTALL()
{
	ninja -Cbuild install

	# remove not relevant files
	rm -rf $dataDir/{mime, icons, applications}

	#local MAJOR="`echo "$portVersion" | cut -d. -f1`"
	#local MIDDLE="`echo "$portVersion" | cut -d. -f2`"
	#local MINOR="0"
	#sed \
	#	-e "s|@MAJOR@|$MAJOR|" \
	#	-e "s|@MIDDLE@|$MIDDLE|" \
	#	-e "s|@MINOR@|$MINOR|" \
	#	$portDir/additional-files/garglk.rdef.in > garglk.rdef

	#addResourcesToBinaries garglk.rdef $binDir/garglk
}

This is odd, any idea what could have happened or how to reproduce it?

Confirmed. Built successfully on Haiku R1B3 x86.

This is odd, any idea what could have happened or how to reproduce it?

Well, you see… I removed some non-x86 packages (because I had conflicts between the same libraries in /boot/system/lib/x86 and /boot/system/lib), and that solved a few conflicts, and then I tried removing another package (can’t remember which, and I couldn’t remember which I’d installed vs which were preinstalled) which cascaded into removing a whole bunch of, I assume, necessary system libraries. I figured worst-case I’d reinstall.

Basically, I suspect I did a rough equivalent of “rm -rf /”. 99% chance it’s a stupid user error. :slight_smile:

1 Like

You can just reboot into an earlier state and the make that persistent, no need to reinstall

1 Like

Hello there, I’ve made a WIP package file for this software, I have a couple of questions though. : )

Thank you for doing this!

Does this have an Icon? Usually we take Icons of other OSes and remake them in the Haiku icon style for ports.

Yes, the icon is in garglk/gargoyle-house.png.

What is up with the stuff it tries to put into libexec? Haiku does not have this directory, and i don’t understand what it does on linux either, is this just executables the main executable wants to find? Could they be put into the data directory instead?
EDIT: after updating to the proper cmake args in the recipe it no longer does this, hopefully it works regardless

Gargoyle is slightly odd here, in how it works. Briefly, there are a bunch of different “interpreters”, or game players, for various types of game (Infocom games, Magnetic Scrolls games, etc). Gargoyle provides an implementation of a common I/O interface called Glk, which was designed for these kinds of games. All the interpreters use Glk for their I/O, so ultimately all those files in libexec are the individual interpreters, each one linked to libgarglk, which provides the Glk implementation. These are the actual programs which run the games.

Finally, there is a launcher, which is the “gargoyle” binary. This is the main entry point, and all it does is determine which interpreter to run for a specific file, and calls it. Finding the interpreters is one of the few areas where some platform-specific code might be needed. On macOS, for example, the interpreters are all packaged into the disk image bundle, and it knows to look there. On Windows, the interpreters are installed alongside the gargoyle.exe, and it knows to look for interpreters in the same directory as gargoyle.exe. On Unix, $PREFIX/libexec/gargoyle is built in as the directory to use.

The relevant code is in garglk/launchqt.cpp, in main. If it’s needed, I can add code specifically for Haiku to search for interpreters.

Where does the application look for config? it seems on linux this is some .rc file in $HOME, In haiku we have a proper API to locate these directories instead (The Haiku Book: FindDirectory.h File Reference), I had looked at the code, but i don’t really understand it to patch it.

Configuration with Gargoyle is messy for various reasons (some historical). On Unix platforms it uses $XDG_CONFIG_HOME to determine the config file location. I noticed that Haiku sets this environment variable, so I assumed it was safe to use it, which means that for now it looks in $XDG_CONFIG_HOME/garglk.ini, which on my system expands to /boot/home/config/settings.

I’m guessing that that’s just a hack to support Unix code which doesn’t know any better. And in fact, I’m aware of find_directory(B_USER_SETTINGS_DIRECTORY, ..), given that I used it in one of the interpreters bundled with Gargoyle; somehow it just slipped my mind that it existed! I’ll add Haiku-specific code to look up the config file.

So ultimately, if it sounds right, the config file will be in <B_USER_SETTINGS_DIRECTORY>/Gargoyle; but if there’s a better naming convention, do let me know, and I’ll conform to it.

Where are some scripts or files I can use to test this engine?

The IFDB is the best place to find all sorts of games that will work with Gargoyle.

For a specific one (so you don’t have to waste time searching), you can give Anchorhead a go. You can either run it with the gargoyle launcher (to see if it’s got paths to interpreters set up properly), or run it directly with the “bocfel” interpreter, which is used for .z8 games.

And here, my WIP recipe to play around with:

Thank you! I’ll start familiarizing myself with Haiku recipes.

1 Like

You can just reboot into an earlier state and the make that persistent, no need to reinstall

Looks like I’ll be learning how to use Haiku at the same time I’m figuring out developing on it. Thanks!

2 Likes

It’s fine to use this for ported software, there is still a bug that the xdg vars are not set when launched via the gui, this will probably only be really fixed in beta4(it works in the noghtlies now), but in general those xdg vars are available for compat (I only read an issue that said it was a hardcoded fotfile location in home, which is why i asked)
find_directory is nifty if you want something more specific than what xdg vars can procide : )

this recipe is for haikuports/haikuporter, I’ll try to put it on my git today so you could clone it directly

One thing comes to mind that might sense for haiku too, mime sniffer rules for the archive files, aswell as associated mimetypes, this way archives should be able to be forwarded to the main executable directly (or even to the interpreters directly, keeping the launcher for a GUI way to “open a game”)

One thing comes to mind that might sense for haiku too, mime sniffer rules for the archive files, aswell as associated mimetypes, this way archives should be able to be forwarded to the main executable directly (or even to the interpreters directly, keeping the launcher for a GUI way to “open a game”)

There’s been some work in this direction, although not a whole lot. The Gargoyle repository contains an interactive-fiction.xml file which includes MIME types and magic (where feasible) for the various types. This is specific to the freedesktop.org Shared MIME-info Database so I suppose isn’t directly useful for Haiku, but it could be adapted, at least, as a starting point. Some of the MIME types have been seen in the wild, but I think I probably had to invent a couple of them (it’s been years since I put this together).

I’ve been wanting, for a long time, to include file type detection to the launcher to avoid having to use extensions. Some formats aren’t really able to be detected reliably, but many of them are. I’ve written code to do detection before, so it’s more a matter of figuring out how to incorporate it properly into Gargoyle. It’s not completely straight-forward, given some idiosyncrasies in how Gargoyle operates, but it’s definitely a nut I want to crack.

Alright, I’ve got a pull request here: Properly look up config file location on Haiku by cspiegel · Pull Request #562 · garglk/garglk · GitHub

If there’s anything I’m doing wrong vis-à-vis Haiku in this patch, please let me know.

B_USER_SETTINGS_DIRECTORY should be B_USER_PREFERENCES_DIRECTORY
(settings is ~/config/ and preferences is ~/config/settings, a bit confusing unfortunately)
(point 6 for windows sais gargoye instead of gargoyle for the executable name, is that intentional?)

Running the interpreter directly with the provided game seems to work nicely, I did not test much however, running with my package script for the main executable fails however.
screenshot143

I tried to make an icon, it’s not finished.

Some of the MIME types have been seen in the wild, but I think I probably had to invent a couple of them (it’s been years since I put this together).

I’ll take a look, perhaps it is adaptable, we have something similar to linuxes magic sniffer (and also a database of file extensions, but this seems completely broken, haiku does not like this really)

The file manager would usually sniff the mimetype of files before asking to start them (by an executable that declares support for this mimetype), In your main loader you could likely check the mimetype directly if set also (though Haiku will likely misindify all of the archives currently as they are not yet sniffed for i think)

Edit: if we don’t have this already, a tool to convert the freedesktop MIME infot one to our variant would be nice, it looks to include directly convertible info

Maybe I’ve got something odd going on locally, but when I use B_USER_SETTINGS_DIRECTORY, I get “/boot/home/config/settings”, and for B_USER_PREFERENCES_DIRECTORY I get “/boot/home/config/preferences”.

“gargoye” is indeed a typo, thanks for that.

Running the interpreter directly with the provided game seems to work nicely, I did not test much however, running with my package script for the main executable fails however.

I’ve got the recipe running and I see what’s happening. In CMake, the interpreter directory is set using GNUInstallDirs on Unix platforms, and CMake considers Haiku to be Unix. So it does this:

set(INTERPRETER_INSTALL_DIR "${CMAKE_INSTALL_LIBEXECDIR}/gargoyle")

The interpreters use this variable to install themselves, and Gargoyle uses it to hard-code the path to the interpreters. So, whatever the value is set to ought to work, however weird a location it might be. But there’s a big difference with GNUInstallDirs on Haiku vs Unix: on Unix systems, CMAKE_INSTALL_LIBEXECDIR is a relative path, relative to CMAKE_INSTALL_PREFIX. So it’s just the bare string “libexec”. On Haiku, it’s the full path. This is allowed by CMake but since I’d never seen it before, I didn’t even think about it.

I’ve just pushed a fix for this to master. With that fix in, launching via “gargoyle” is now working for me.

I made a couple small changes to the recipe:

  1. My CMake complained about CMAKE_BUILD_TYPE not being set, so I just added -DCMAKE_BUILD_TYPE=Release
  2. Gargoyle can be told not to install the freedesktop.org mime/icons/applications files by adding this when calling cmake: -DWITH_FREEDESKTOP=OFF. This should get rid of the need to manually remove those files.

I tried to make an icon, it’s not finished.

This is great, thank you!

The file manager would usually sniff the mimetype of files before asking to start them (by an executable that declares support for this mimetype), In your main loader you could likely check the mimetype directly if set also (though Haiku will likely misindify all of the archives currently as they are not yet sniffed for i think)

If I understand right, the suggestion is to look up the interpreter via MIME type rather than extension? For a system like Haiku where MIME types are king that makes a lot of sense. I can’t find an API call to determine a file’s MIME type; but it’s entirely possible I’m fundamentally misunderstanding how this works on Haiku.

If that’s the suggestion, I see no problem in probing for MIME type and using that, if it’s one of the recognized types, falling back to extensions if necessary. This would probably be a Haiku-only thing to start with, but it’s probably the right way to go for the future.

I’ll note that I do see that Qt has a QMimeDatabase/QMimeType classes for this, but from a cursory examination of the source it seems to only use the freedesktop.org-style database, not making use of Haiku’s own MIME database, making it less useful for Haiku.

1 Like

I’ve looked at the source, and it agrees with you. The B_USER_PREFERENCES_DIRECTORY variable is used nowhere in tha Haiku sourcetree, but the B_USER_SETTINGS_DIRECTORY is used (And I’ve also mixed this up with B_USER_CONFIG_DIRECTORY above, ehh)

So, it seems B_USER_SETTINGS_DIRECTORY is indeed the correct one, sorry for that.

I’ve started a mailing list thread about this, maybe I can improve the documentation to prevent this for the future (or figure out why there seem to be two vars that do the same thing but return different directories)

In Haiku MIME types are stored as extended (typed) atributes on the file itself, you can play around with this with the listattr, copyattr, rmattr, catattr commands on the commandline.

As an example:

~ listattr -l image.png                                                                             
File: image.png
        Type       Size  Name                                Contents
-------------------------------------------------------------------------------
 MIME String        10  "BEOS:TYPE"                         image/png
      Int-32         4  "Media:Width"                       1326
      Int-32         4  "Media:Height"                      266

18 bytes total in attributes.
~ 

For this image the BEOS:TYPE atribute has a type of MIME string and the value of image/png.

In essence, there seem to be two ways to start a game with gargoyle. (I’ll exclude “running the interpreter directly”, it doesn’t need any heuristics)

  1. Run the “main” app and pick a file
  2. Double click an archive in the file manager

For the case 1. we can’t be sure that the file was ever sniffed and got a MIMEtype, or a valid one, it’s possible this was just downloaded from the web and the web server said “I know this, it’s an octet byte stream”, not very usefull for us in that case.

For this case I would: Probe the mimetype, and if it is one you know trust the value, and if not fall back to your own detection.

(It might also be possible to ask the MIME sniffer directly to probe the file, but I am not sure what api that is, or if it is public, I think this is what you asked above, but other than “tracker calls it” I don’t know where it is)

For the case 2. We know reasonably well the file manager has been openend and the MIME type was sniffer, in this case we can go a much easier route of: declaring for each interpreter the specific MIME types they support, the OS would then bypass the launcher app and directly call the interpreters.
One problem with this aproach is that Haiku does store file extensions for mime type info currently, but never parses them, so If we want to go this route we would need high quality content based sniffer rules.

For this case It would also be nice to provide an Icon for these files so users can quickly determine from a glance that it indeed is recognized as an archive that is “for gargoyle”

If it were possible to directly ask Haiku’s MIME sniffer, that’d be ideal, since then Gargoyle would always agree with Haiku; but if that’s not exposed, manually doing probing using Qt’s MIME handling is fine, with a caveat: Qt expects there to be a freedesktop.org-style MIME database available. Qt looks in “standard” directories for these, and although Haiku doesn’t use such XML files, Qt does know one location to look on Haiku: /boot/system/data/mime/packages. I’m still learning Haiku’s method of package management (this sort of virtual filesystem overlay based on the hpkg files is really slick), so I’m not sure if it’s possible to include the XML file in that directory on install. If so, that should be workable, although I can’t run a quick test since that directory isn’t writable by “normal” processes.

At any rate I’m working on including MIME detection to test how that works. I’ll probably only enable it on Haiku for the next release, given that it’d be a change in behavior to some degree on other platforms, but it’ll probably wind up being a standard option in the future. It’s about 80% of what I wanted out of file type probing, and that might be enough.

For the case 2. We know reasonably well the file manager has been openend and the MIME type was sniffer, in this case we can go a much easier route of: declaring for each interpreter the specific MIME types they support, the OS would then bypass the launcher app and directly call the interpreters.
One problem with this aproach is that Haiku does store file extensions for mime type info currently, but never parses them, so If we want to go this route we would need high quality content based sniffer rules.

A few points:

  1. Gargoyle allows the user to select which interpreter they want to use based on the filename of the game being launched. In general this is useless because for the most part there is one interpreter per game type, but there are two interpreters for Glulx files and it’s theoretically possible somebody might want to override one for a particular game.
  2. There’s one supported file type (called Blorb) which can’t be sniffed using a declarative approach, but must be parsed as an IFF file to determine the MIME type.
  3. Some game types are just not sniffable at all.

So in general I like the idea of assigning MIME type support to individual interpreters. In 99% of cases, the Gargoyle launcher is just acting how the desktop launcher would anyway, so why not cut out the middleman?

Point 1 above is a slight argument against, but realistically it’s only needed for a very small subset of games which require a specific interpreter. Since you can manually launch that interpreter anyway, it’s probably not worth the extra step of the launcher, at least on Haiku.

Point 2 may be moot, given that I don’t know how Haiku sniffs MIME types. Blorb files are basically archives which contain a game plus resources. Blorb files are IFF files, and need to be parsed as such to determine which game type is stored. This isn’t hard, but if the MIME sniffer is declarative, it won’t be able to handle these. Worst case, though, Blorb files can be sent to the launcher, which understands Blorbs.

Point 3: there are some game types which are just not identifiable. There’s no magic number, nothing to identify them. These either need to be identified by extension, or the user would have to manually enter a MIME type for them.

I think it’s worth trying, on Haiku, the approach of giving interpreters their own MIME types. The launcher would still be necessary for the types which can’t be sniffed, but otherwise, things can be launched directly. I’m still going to have to mull over some of the possible side effects of this, but it’s definitely something to try.

For this case It would also be nice to provide an Icon for these files so users can quickly determine from a glance that it indeed is recognized as an archive that is “for gargoyle”

Gargoyle comes with a file-type icon in garglk/gargoyle-docu2.png, but it’s nowhere near the style of Haiku, so would need reworking (or just something new entirely).

2 Likes