When life gives you lemons ...
Tags: linux, gamedev, tooling, compression
Published: 2023-12-31 14:21:13

Recently, I found myself reminiscing about games that really stuck with me. One of those titles is _Theme Hospital_. Luckily, there are people with enough love for these [good old games](https://www.gog.com/), as to make them available to be run on modern operating systems. Although _GOG_ usually has most bases covered, _Theme Hospital_ appears to be an exception. A [GNU/Linux](https://en.wikipedia.org/wiki/GNU/Linux_naming_controversy) version is unfortunately not available, which prompted me to investigate the available ports and see if there may be a way to get them running on my machine anyhow. It turns out the _MacOS_ package has everything we would need for just such an endeavor. After downloading the most recent [PAK](https://www.fileextensiongeek.com/pak/) file (at the time of this writing theme_hospital_enUS_1_0_3_33062.pkg), we need a way to extract its contents. The container is compressed using [XAR](https://docs.fileformat.com/compression/xar/), so options are limited. Luckily, [7z](https://www.7-zip.org/) does support this format.

Let's setup a temporary place for the archive contents and change the directory via
`mkdir -p /tmp/theme-hospital-pak && cd /tmp/theme-hospital-pak`. Now we can extract the contents via `7z x ${HOME}/theme_hospital_enUS_1_0_3_33062.pkg`, which tells _7 zip_ to place the contents into the directory we are currently executing this command from. The result should look something like:
```bash
-rw-rw-r-- 1 goggy  780 Oct 21 13:26  Distribution
drwx------ 1 goggy    0 Jan  1  1970  package.pkg/
drwx------ 1 goggy    0 Jan  1  1970  Resources/
-rw-rw-r-- 1 goggy  14K Oct 21 13:26 '[TOC].xml'
```

Now if we look into `package.pkg/` we find two files:
```bash
package.pkg
├── PackageInfo
└── Scripts
```
The file Scripts is another archive compressed via [gzip](https://www.gzip.org/). So let's decompress via `cat package.pkg/Scripts | gzip -dc > unzipped`. The newly created file unzipped is another archive. It can be processed by [cpio](https://www.gnu.org/software/cpio/). Let's prepare a directory `mkdir /tmp/theme-hospital-pak/raw` and extract the raw contents into it via `cat unzipped | cpio -i -D raw`, after which it will tell us how many blocks it restored. Something like: `399282 blocks`

Looking into raw, we find a directory called `payload`. In it, we can spot the actual game data, an embedded [DOSBox](https://www.dosbox.com/) version, as well as scripts to start the game. Since this is a _MacOS_ package, we cannot use this version of _DOSBox_ and need a local installation for whichever _GNU/Linux_ flavor you are running. If we wish to start a single-player session, we'd need to make use of the core _DOSBox_ config file, and the single player specific config file.

First, we need to change the execution environment to be the same directory as the game directory. In this case, `cd /tmp/theme-hospital-pak/raw/payload/Contents/Resources`. Assuming the local _DOSBox_ installation is available in `$PATH`, we may now call `dosbox -conf game/dosboxTH.conf -conf game/dosboxTH_single.conf`.

Since I thought this process might as well be documented in code, I came up with a tool called _goggy_. It allows you to do this process with the aforementioned classic `Theme Hospital` and any other game packaged in a similar way. Check out the source code at [https://github.com/BlurryRoots/ws-goggy](https://github.com/BlurryRoots/ws-goggy) and have a great time looking after [those patients in need of assistance](https://retrogamer.biz/wp-content/uploads/2015/10/Theme-Hospital-manual.pdf).