An Odd World; Oddworld Stranger's Wrath Prototype
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!
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.
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.
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.)
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.
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.
The second one here is test_ajb.geo
which looks like a collection of shapes.
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.
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.
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
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.
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.
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.
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).
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).
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).
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!