In April, in the Hidden Palace Discord server, a user with the handle ‘Sgabbit’ asked about the Oddworld Stranger’s Wrath prototype that had been shown on the YouTube channel PtoPOnline. Unfortunately, many years later, it still wasn’t publicly available.

Aiming to change that, we decided to make an offer to the individual behind the channel, and after acquiring some better capture equipment and sending our Xbox off to have more RAM soldered onto the motherboard, here we are today!

Stranger is ready gif

If you’re just interested in downloading the prototype, then click here to skip to the end, otherwise read on!

Verifying the Date

Usually, before we get too deep in examining anything, we’ll try and verify when it’s actually from. When we checked the file timestamps on the Xbox XBEs in this prototype, we were a little puzzled as they did not align with when this particular build was supposedly thrown together. Odd. Pun not intended.

Screenshot showing how they appear in the folder

After using a tool to further inspect the other accompanying executables alongside the Xbox XBEs, it appears this prototype is probably from around the 22nd of May 2004 - that’s at least the time the builds were actually compiled, it seems.

Screenshot showing timestamp provided in the PE executable

Because the timestamps for executable files were wrong, it casts a little bit of doubt over whether any other timestamps in this build are necessarily correct, but unfortunately, we’ve not got much else we can use to date them. Generally, we’re dubious of any timestamp going as far back as 2000 or earlier as it appears to be the general pattern.

To add a little bit to the confusion, when you start the prototype up, there’s a brief splash screen that appears to display ‘JANUARY 2004’ on the bottom right. (Ignore the blue box on the top left, that’s being displayed by our HD upscaler.)

Screenshot of splash screen

We figure there was probably some other build produced at that time, either produced for preview purposes or some internal milestone (we don’t know), and that splash screen was simply not replaced before this build. It may suggest that the build we have here is a little less formal than whatever was created back then.

Glorious PDBs!

As you probably noticed from the screenshot earlier, this prototype also includes the PDBs. If you’re unfamiliar with these, they’re essentially debug symbols that contain heaps of useful information! In summary, this is going to be a massive help to anyone reverse engineering both this prototype and the final game.

One of the things I personally also love about PDBs, besides the fact that they’re an abundant source of information, is that they usually include references to the original files used in the source tree during compilation, so from that we can get a rough idea of how the project was set up at the time it was compiled. You can see the results of that here.

Screenshot of the source tree repo

You’ll likely note the root “exoddus” directory that Oddworld Inhabitants (OWI) used for the project, we’ll get to that shortly.

Stranger’s Engine

Going into this, we actually knew next to nothing about Stranger’s Wrath, especially when it came to the technology behind the game, so this has been quite educational. As it turns out, Stranger’s Wrath uses OWI’s own proprietary game engine, which is unlike the Oddworld Munch’s Oddysee title released prior, which instead used NetImmerse/Gamebryo (we actually confirmed this independently ourselves too, as we’re always a little wary when no citation is provided).

To my knowledge, there’s no formal name provided for the engine that Stranger’s Wrath used, but we’ll refer to it as “Stranger’s engine”, which is a term Lorne Lanning, a founder of OWI, used himself.

The capabilities of the engine were quite respectable for their time, with support for pixel shaders, shadow maps (only from characters), level streaming, SWF-based UI system, a C-like scripting language, a skeletal animation system utilizing Granny 3D, lightmaps, and more. Fancy! Additionally, as clear from nosing at the PDB, the game was written in C++ which isn’t too surprising for the time.

Like many others, OWI used a few third-party libraries to aid the development of the engine.

  • Flex + Bison; these are very likely used to aid in the implementation of the scripting language.
  • STLport; from the terrible days when compilers didn’t provide very good standard library implementations for C++, and developers usually just rolled their own. This library is still available but unsurprisingly appears to have fallen out of use.
  • Granny 3D; mentioned earlier, this is used to provide the skeletal animation system. Quite a common library for the time which has fallen out of use in recent years.

But for the most part, excluding the Xbox SDK and other trivial libraries they might’ve used, that appears to be it and otherwise everything else is home-grown. I was especially impressed by their decision to write their own SWF player to use for the UI, which appears to have been quite ahead of the curve, as other engines later into the decade would adopt Scaleform to support flash-based interfaces rather than rolling their own solution.

It’s actually a bit of a shame as it’s the only title OWI ended up releasing to use this technology, despite plans to use it in their follow-up ill-fated title, The Brutal Ballad of Fangus Klot.

“[…] We wanted to take Stranger’s engine and basically re-skin something more hardcore […]”
Source

Fortunately, while described as an “Xbox-exclusive engine” during an interview, Just Add Water Ltd. eventually gave the engine a bit of love and brought Stranger’s Wrath to Sony’s PlayStation 3 in 2011, eventually followed by a myriad of other platforms.

Some quick reversing…

And that leads onto a little bit of poking and prodding at some formats here. This section is a bit shorter than planned, but we’re sure the community is going to be quick to fill in the rest.

From comparing the final game to this build, it became apparent there were a number of additional folders that the final game didn’t include, such as the following.

  • data/fonts
  • data/geometry
  • data/levels
  • data/prefs
  • data/scripts
  • data/shaders
  • data/ui

I’d suspected that the prototype did not actually pull data from some of these locations, given their absence from the final game, and as it appeared a bulk of the data was packed into SMB files just as they also are in the final game (they’re a kind of package file, we’ll talk about them shortly).

We ended up confirming this is probably the case when we tried to run the prototype with the levels and geometry locations removed.

It’s quite likely most of these folders were left-overs from the packaging process used to produce the SMB packages under the data/bundles and data/global locations. Though, oddly enough there should also be a left-over directory for textures too, which appears to be missing, so that might get removed during some other stage of the process.

SMB/GEO Format

Let’s get the big one out the way first, I guess. ‘SMB’ here stands for Shared Memory Block, and the files are essentially a collection of separate data blobs. You could basically consider it a type of package/container file.

From the standpoint of reverse-engineering, the format is terrible to reverse because there doesn’t appear to be any mechanism for knowing up-front how large a given struct/class is going to be (meaning we can’t cleanly skip the ones we don’t want or don’t have reversed), but fortunately using the available PDBs, it was pretty easy to deduce elements of the format.

struct OIStringBuffer
{
	int32_t size;
	char    buffer[ size ];
};

/**
 * There is an older version of the format that uses
 * 0x600ddea1 as it's magic instead and does not have
 * a version number (engine interprets it as version '0')
 */

struct SMBHeader
{
	uint32_t magic;// 0x3a4b5c6d
	if ( magic == 0x3a4b5c6d )
	{
		int32_t version;// 5
	}
	struct OIStringBuffer fileName;
	int32_t               fileOffset;
	int32_t               headerStreamEnd;

	int32_t numContiguousBytes;
	int32_t numSystemBytes;
	if ( magic == 0x3a4b5c6d )
	{
		// if old format, both the below are the same as above
		int32_t contiguousSizeUnpadded;
		int32_t systemSizeUnpadded;

		if ( version >= 3 )
		{
			int32_t numResources;
		}
		if ( version >= 4 )
		{
			int32_t ioMode;
		}
	}

	uint32_t endHeaderMagic;// 0xbeef1234
};

struct SMBHeader header;

As you can see, there are various checks for different versions of the format indicating that the format was expanded on overtime, and the team were obviously keen to retain backwards compatibility. I was a little curious if the final game (or at least the HD PC version) could load any of the SMBs from the prototype, but sadly had little success with shuffling various files around—there are many reasons why this probably didn’t work.

Oh, and this format gets used for models too, which use a geo extension instead of smb.

I’d made a slightly further effort before deciding it was a bit more than I wanted to focus my time on at the moment. Below you can find the main MaterialDef structure outlined, but this is then used as part of the many other subclasses such as MaterialDef_Transparent, MaterialDef_SimpleTextured, MaterialDef_NormalMapped, and so on and so on.

struct MaterialDef
{
	int32_t version;
	if ( version < 19 )
	{
		uint32_t flags;
	}
	else
	{
		uint32_t flags[ 6 ];
	}

	float    glareStartFade;
	float    glareEndFade;
	float    reflectionStrength;
	float    mipmapLodBias;
	uint32_t glareColor;

	float lmTexelSize;
	float lmCreaseAngleDegrees;
	float lmNormalHardness;
};

struct MaterialDef_NormalMapped
{
	int32_t            version;
	struct MaterialDef materialDef;
    // i gave up here...
};

The MaterialDef_* classes are just one collection of many other classes that are serialised as part of the SMB, as you also have the actual geometry classes such as IndexedRenderableVB, PBIndexedRenderableVB and many others for all the various different sets of data that get serialised.

Something I’ll perhaps return to eventually, though I’m fairly sure the community will likely leap at this sooner and faster than I will.

TAG Format

There are seemingly two types of TAG files here, some are in a binary form and others just plaintext. A subset of the latter format can be seen below.

There are multiple types of tags here, which together appear to make up everything that’s featured in the given level.

// TagFile (version: 0, comment lines: 5)
//  ** EDITS TO THIS FILE ARE NOT PRESERVED **.  Change the .mb file instead
// 
// Tags Exporter, version 0.93
//  -       File Exported as: d:/Exoddus/Build/Game/data/levels/Region_01/transition_01_1.tag
// 

<WorldGeometry>
	begin
		m_tagName: ""
		m_tagZone: -1
		m_isInProxyZone: false
		m_tagTransform: 1 [3F800000] 0 [00000000] 0 [00000000] 0 [00000000] 1 [3F800000] 0 [00000000] 0 [00000000] 0 [00000000] 1 [3F800000] 0 [00000000] 0 [00000000] 0 [00000000] 1 [3F800000] 
		m_illuminationColor: 1 [3F800000] 1 [3F800000] 1 [3F800000] 1 [3F800000] 
		m_snapToGround: false
		m_groupName: ""
		m_startsInPurgatory: false
		m_castLightmapShadows: true
		m_scriptFile: ""
		m_scriptArgs: ""
		m_scriptEmb: ""
		m_pathToken: ""
		m_levelPrefs: block
		begin
[...]

My guess is that the plaintext files get converted into the binary format at some stage for speed (or the plaintext files are just an older version), given the binary variations of the format seem to contain the same data within them anyway and would be more optimal to parse.

Checking out a couple models

There don’t seem to be that many ‘test’ models left hanging around, though I can’t speak for the rest of the models available (it would take someone with a bit more knowledge on Stranger’s Wrath than us to identify what is of interest).

There were two test models amongst the files that I was particularly interested to take a look at; test_ajb.geo and test_dummy.geo. Given the annoying complexity of parsing the file format right now I instead opted to brute-force it by just identifying the given tag and then pulling the vertex coordinates directory, though unfortunately neither of these appear to be quite as interesting as I had originally hoped.

This first one seen below is the test_dummy.geo mesh, which is hard to recognise.

img_2.png

The second one here is test_ajb.geo which looks like a collection of shapes.

img_3.png

There are a few other test models and other leftovers amongst the files, but they didn’t sound particularly interesting to me, so I didn’t get round to taking a look at them. And no, as far as I could tell, there don’t appear to be any particularly interesting characters or cut enemies as far as I could see, but I’m hopefully wrong!

It would be great to see the community whip up a model viewer which probably wouldn’t be too difficult at all with the information available in the PDBs, and such a thing could be used to more easily identify the models and any differences.

“Exoddus”

When poking around various files, we stumbled upon references to “Exoddus”, which appears to be the internal location that Stranger’s Wrath project was developed under, at least.

Reference to Exoddus screenshot

But why “Exoddus”? Given our own lack of knowledge on the Oddworld franchise at the time, Abe’s Exoddus sprung to mind, which didn’t make any sense given that was a 2D game developed with an incredibly different engine, quite a significant amount of time before Stranger’s Wrath. It was doubtful Stranger’s Wrath was built upon the engine used for Abe’s Exoddus.

As we soon learned, there was intended to be a follow-up to Munch’s Oddysee dubbed “Munch’s Exoddus”, which didn’t see a release in the end. Initially, the only piece of information we could find was on the Oddworld Wiki - no citations though (the administrator has since added a notice on the front page underlining the situation with dubious content on the site). We tried a few other fan sites, such as this, this, and stumbled upon this video, but again, no citations. There was a reference here but again, it’s just a passing reference of the title.

I made it the fuck up video

All we wanted to determine was 1) was Munch’s Exoddus actually a title in development at some point, or just a rumor, and 2) did Stranger’s Wrath have any relationship with it?

Grinding my teeth into paste at this point, I eventually jumped onto the Oddworld Discord and asked for help, and fortunately, the community there pointed us in the right direction and introduced us to the fantastic site, Magog On The March, and there it was…

Stranger’s Wrath was Munch’s Exoddus, and actually there is a build somewhere, on Xbox, which has Stranger and Munch hopping round the world. And it’s like OK, this is a bit weird now.
Source

Given that then, it seems reasonable to conclude that the Exoddus directory then that Stranger’s Wrath was seemingly located under during its development was a result of it being originally intended as the follow-up to Munch’s Oddysee before it evolved into the game we know it as today.

Taking a Listen

Stranger giving a listen gif

We thought it’d be interesting to see if any sounds here were different from what ended up shipping in the final game. Originally I was going to write our own tool for doing this, and then realised tools already existed after wasting about a day on it. Me smart. Brain big. Smack rock.

On Windows, WinMerge is usually a great tool for this sort of thing, as it lets you quickly compare multiple directories for instance, so we can point it on one side to the prototype and on the other, the retail release (if you’re a Linux user, like us, Meld seems to be alright too, but I’ve not used it quite as much).

Initially, it looked pretty promising.

Very promising screenshot

Unfortunately, as it turns out, the XWB files in the retail release don’t seem to retain the unique names for each of the audio tracks within, making quick comparisons tricky without spending a lot of time on it. It means some of these might actually be exactly the same, but the difference is just the lack of names.

To add to the pain, the number of banks stored in some of these files has changed between the final release and the prototype, so some new sounds have been added and some old sounds have been removed, and it’s difficult to quickly determine what’s what because of the lack of names in the release.

You could probably diff the audio_master.h file between the release and prototype to determine what new banks have been added (or removed) to aid in the process of plundering the XWB files, but we didn’t have time to do this ourselves.

That said, it at least looks like some of the music tracks in the prototype are higher quality than those in the final release, which may be the case for some sound effects too.

Higher quality screenshot

Playing the Prototype

So we’re not sure many people are going to be able to run this right now. As it stands, we weren’t able to successfully get this running under Cxbx-Reloaded or Xemu. In the end we resorted to good ol’ hardware instead, but obviously not everyone has access to a modded Xbox with more RAM or an Xbox development kit, so we decided to record as much footage of the prototype as possible for others to analyse.

If you can run this, you’ll need to move one of the Xbox executables (the ‘xbe’ files) into the same directory as the ‘data’ folder.

Originally the plan was to split these videos up based on the bounty, but that didn’t quite work out due to issues with video editing software, so you’re getting these videos pretty much untouched… So, forewarning; I absolutely suck at playing this game, so apologies for that.

There are so many differences here, mind that I’m not going to point out every single one but rather those that stood out to me the most.

For instance, as you can see upon starting a new game (1:11), there is nothing prior to the moment you start playing. We drop in at the first town immediately! No introduction cutscene, either. As a matter of fact, you’ll notice that the tutorials originally featured at the start of the final game in their own unique area (see here) are instead integrated with the rest of the general flow here.

As we move through the tunnel towards our goal (3:56), we meet two characters talking over the body of another character which then introduces us to the capture mechanic. This is all completely absent from the final game.

Screenshot

These two characters are in the same area in the final game but are simply wondering around instead.

Following this, we see how the bridge gets destroyed and are subsequently introduced to jumping to reach the area on the other side. When the player approaches this area in the final game, the bridge is already destroyed.

It’s curious why OWI decided to change this approach towards teaching the player the mechanics, as what they’ve done here certainly felt more natural. Instead, the tutorial introduced in the final game is, in my opinion, significantly more intrusive (as a matter of fact, I believe the Nintendo Switch release of the game introduced an option to skip the entire tutorial section).

Another curious change is at the Water Facility, which appears to feature a separate area for the boss fight, which is found at the top of the tower (34:20).

Water tower boss area screenshot

And again, much to our surprise, a cutscene plays out here introducing us to our bounty not featured in the final game.

You likely noticed a few other differences in our approach to the Water Facility. Moreover, at the facility itself, such as along the top of the building, there are additional barriers, making it much harder to hit the enemies on the roof (30:55).

Barriers at the top of the roof screenshot

Or that the door leading into the inner room of the building is wooden instead (31:13), allowing the player to break it (which makes sense given that in the final game this was likely changed to accommodate the change in location for the boss fight).

Wooden door screenshot

As stated earlier, there are just so many differences throughout this build it would be probably impossible for us to easily list them all, which is all the more reason why it’s going to be great to see this build out there for others to explore.

If there’s a desire to see more footage, let us know!

Download

And this is probably what most of you have been after; grab it here.

If you want to support what we do, we’re not accepting donations at this time, but any and all feedback is appreciated; feel free to join our Discord or leave a comment letting us know what you think!