/ Resurrecting Waffle Boy's Mountain Adventure
Created 2019-05-13 Modified 2019-05-13

3010 Words

Resurrecting Waffle Boy’s Mountain Adventure

Originally posted on 2019-05-13.

If you just want to know how to play the game or you just want the files, skip to the bottom of this post to the section "Wrap up".

It’s been more than a month since I’ve joined the Flashpoint team and it’s been consistently interesting.

By the way, if you’re a developer and have old files from Postopia or other early websites that haven’t been archived, please reach out to the project! A lot of the Shockwave games on Postopia have not been archived, and a lot of loader XMLs have been lost.

Stubbornness is a trait that has served me well in the past. But it also has served me poorly, pouring hours and energy into something that is better attempted later. And of course, that means I gravitate towards stubborn games that aren’t working.

For those who don’t know, Waffle Boy’s Mountain Adventure was a rather famous web game. You can find its successor, Waffle Boy’s Jungle Adventure, accessible even to this day. Originally made by Smashing Ideas for Kraft and hosted on Postopia.com, the game was an impressive platformer, boasting various movements like climbing vines and riding motorbikes, boats and helicopters (that slowly ran out of gas). It also pops up then and again on Reddit for a nostalgic reminiscing.

The game had way more content than its successor, 4 levels to 3, along with animated intros, a special level transition room with minigames and apparently a final encounter. What sucked was that even though the majority of game content was archived in Wayback, it was missing the most important part - the XML.

The way Flash tends to work with many different SWF objects (at least on Postopia) is by using an external XML to load the assets in the expected order. Problem is that waffleboy.xml (not shell.xml listed in the Lost Media Wiki page), the loader for the game, was never archived by Wayback. So basically, there’s all this saved content and no way to play it.

If you hunt around, you’ll find all references to Mountain Adventure overshadowed by its successor. Even games that claim to be the Mountain version, end up pulling the Jungle version. No other site (as far as I know) had mirrored or ever hosted the game separately without calling Postopia for the files. Google fu-ing places like Reddit yielded no useful files or information. According to LMW, they had reached out to the developer only to find that they didn’t have the files. Many people have tried to resurrect the game but even those that got the farthest reached only the strange debug area.

Of course, rather than being rational and leaving it up to some random good Samaritan to pass along the missing file, I decided this was the best task for a newbie curator like me to tackle.


So following the typical Flashpoint game testing outline, I recreated the folders needed with the assets. Not going to get too much into the specifics of curation with this post (I have written about it before), but the necessary things to know is that Flashpoint uses a modified Apache server so that if a game requests for assets off of its original site, it’s redirected into the folders on your hard drive (it’s up to you to use the 404 errors to hunt for missing assets).

  1. First thing was to find the page where the game was hosted, hunt for the game source url and used the full, giant URL off of the embed on the site:
http://www.Postopia.com/games/vr_loader/vr_base.swf?vrloader=/games/vr_loader/vr_loader.swf&filelist=/games/wbmountadv/waffleboy.xml&filepath=/games/wbmountadv/swf/&vrinfo=/games/wbmountadv/vr_info.xml&urlaction=http://www.Postopia.com/common/gaming/game_action.aspx&game=/games/wbmountadv/waffleboy.swf&width=500&height=320&bgcolor=0xffffff&viewonly=false&urlobject=/common/gaming/game_submit.aspx&urlemail=/common/games/Game_Ecard

This gives the redirector server all the necessary extra calls (with Shockwave, we must define the parameters using a script that one of our hackers made - since we don’t have that for Flash, we need the calls made in the URL).

  1. First things the web server tries to HTTP GET in terms of assets was vr_base.swf (which if you ignore all the parameters within that url, you will see that before the first ? that it’s asking for that swf file) and vr_loader.swf. Thankfully these were all archived, and it seems that these files were used as generic code for launching the games on the site.
  2. The first issue that happened was a missing vr_info.xml. This is a generic file that is uniquely modified for various games on Postopia for the purposes of earning either extra lives or post token rewards (tokens used to be provided in the cereal boxes). This wasn’t archived, so that bit of information on how the site used to define tokens for the game has been lost. Fortunately, it’s not a necessary piece of code, and I was able to make a dummy file for it
  3. There was also a common file used for sending HTTP POST requests to - I’m still unsure of the purpose of this, but it was archived and even if it wasn’t, potentially a dummy file could have been substituted.
  4. Then it asked for waffleboy.swf. From reading through the decompiled code (we’ll get to that later), I concluded that this was fail safe, that if the game errored out, it would display a blue background. This was archived so it was easy to place into the folders.

Now onto the really difficult issue:

According to LMW, the shell.xml was missing. They were correct; however, it’s referred to as waffleboy.xml in the URL parameters. This was the important file that was not saved, meaning that I did not know what files were necessary and what was being loaded - this was the most important file for recreating the game, and it was missing.

Here is what a typical file loader XML looks like on the site - note the specific naming of assets and extra modules:

Dream XML

Another example, except this one is completely different, indicating what version of Flash to fall back on. Most files look the previous ones, but this is just to demonstrate how unique these files can get:

Sky

In general, Postopia did not save a lot of these loader XMLs, so I had very little content to go off on how to recreate this XML. To find the necessary game files for Mountain Adventure, I had LMW to thank for this list:

File Availability Extra notes
./swf/game.swf Found
./swf/gateway.swf Found
./swf/intro.swf Found
./waffleboy.swf Found
./vr_loader/vr_base.swf Found Base for vr_loader
./vr_loader/vr_loader.swf Found Postoken reward check
./wbmountadv/shell.xml Lost File list
./vr_info.xml Lost Postoken reward info

Table source

If I use one of their links, I get a list of all the assets saved for wbmountadv, the folder used to house the different SWFs for loading.

We can see in the table above that we have three swfs - game.swf (which is the main game code), gateway.swf (which is the unique transition area between levels and has minigames), and intro.swf (the intro to the game). So somehow, we need to load these SWFs in their proper order.

The process in recreating the XML was extremely long. It took me days and it for sure is not the same as it was. I just want to state that it took a giant amount of time with a lot of trial. I won’t be covering all the failed XML recreations, only those that I feel were vital for understanding the structure of how Postopia dealt with these games.


First things first, there was a common structure to the XMLs. There was a root node (funnily enough, I only have experience with JSON, but this was a great adventure in learning XML structure), module node and a loader node.

<root >
	<module type="object" required="1" baseLevel="2500">
		<comm src="module/comm.swf" />
		<hockeyGame src="module/hockeyGame.swf" />
		<display src="octoDisplay.swf" />
	</module>
	
	<loader baseLevel="400" required="1">
		<loader name="loader0" src="introLoader.swf" />
		<loader src="loaderInGame.swf" />
	</loader>
	
	<content baseLevel="100">
		<content name="stage0" title="Octo Hockey Assets" required="1" src="octostage0.swf" />
		<content name="winGame" title="Game End" src="winGame.swf" />
		<content name="keys" title="Game End" src="unlockDoor.swf" />
		<content name="nickkeys" title="Game End" src="nickKeys.swf" />
		<content name="octoVault" title="Octo Vault" src="scenes/octovault.swf" />
		<content name="octoCastle" title="Octo Castle" src="scenes/octocastle.swf" />
		<content name="octoGarden" title="Octo Garden" src="scenes/octogarden.swf" />
		<content name="octoVillage" title="Octo Village" src="scenes/octoVillage.swf" />
	</content>
</root>

The above is the XML for Octo Hockey (seems to be another lost game). The specific values for root, module (like type="object”, baseLevel="2500”), loader (baseLevel="400”), and content (baseLevel="100”) were the same in every single loader XML I could find on the site. So, I assumed I can start building waffleboy.xml using those values.

Modules appear to be external links to shared objects within Postopia under a conveniently named folder called modules…. All of them, save for one, were not saved. Which spells bad news for the other games on the site that depend on them. Thankfully some of them were saved under random SWF folders on the site but it will take some digging and luck to restore those games.

Sadly, I had no idea of what modules were used. As you can see in the example above, some are specific to games (like hockeyGame.swf, octoDisplay.swf) and some were generics (like comm.swf). Almost every XML had comm.swf (which was archived) and I decided to use that as temporary stand in as a module.

The loader I assumed to be the intro.swf (since the above hints that the loader is specific to the game) and in the content, I copied over the content and used a generic name with a required tag.

And it started playing the intro! At least until I realized the skip button was broken and the game refused to play after it. Switching places with the Loader, I placed the game.swf there.

And it was working yet again! Except that it wasn’t any proper level. Turns out, that if the XML is not loading the files correctly, it defaults to this weird debug room (that you can exit through the door by pressing up). It leads to a second checkpoint in the first level (which is basically just half of a level).

Fittingly, he looks quite smug at this point: Waffleboy debug

So, at this point, I had no idea whether the intro was the loader or not. So in comes JPEXS Free Flash Decompiler.

Perhaps looking at the code would give me clues of what comes first.


Here’s where we delve into me code reading ActionScript - an archaic form of EcmaScript that is becoming obsolete.

The way the game sets its external XML parameters is through something called setContent. (How did I find out? I ctrl-shift-F4-ed the names intro, gateway, game, anything that could show me when the XML gets set). setContent doesn’t seem to be defined anywhere in the API references, so I can only conclude that it may be a user made function for writing to an XML loader - however this O’Reilly reference to XML.nodeValue seems to show the structure that this user made function may be following.

Also, this ActionScript code may potentially be older than AS3, the “modern” iteration of AS.

Quick notes from decompiling and reading the code:

  • Waffleboy.swf doesn’t set any XML - it appears to read from it. There’s a clue for potential content tags that are supposed to be set with this code in frame 1:
    if(this == _level0)
    

    level0 can either be a reference to game.swf (that has may lay out the levels like 0,1,2,3,4 where 0-3 are the actual game levels and 4 is the debug section) OR it could be an unarchived, missing asset. These names are very important for the XML. For example, it could be used in a content node like

     <content name="level0" src="neededasset.swf" />
    

    The name value is very important for the SWFs to be able to write and read from the XML file. It can also be used I believe for module structures, for example:

     <module>
         <level0 src="neededasset.swf" />
     </module>
    

    Where the name is the actual tag name.

  • Comm.swf (the temporary module I grabbed) seems to be a generic structure for showing debug logs for the games on the site.
  • Intro.swf sets something called
    Movie.content.setContent("Level1");
    

    Which, if you investigate other swfs is how they set their swfs in the XML. This again, like Waffleboy.swf could either be a reference to the main game object or a missing asset.

  • Gateway.swf, the transition level, calls these pieces of code:
      Movie.content.setContent("Game");
    

    Which is clearly a reference to the main game object because when you exit the transition level, it returns to the main game and increments the level.


Let’s talk about Game.swf separately.

  1. It calls both intro and gateway, which lead me to think that it was supposed to be the loader - with intro and gateway either being the content or the modules.

    Movie.Content.setContent("intro");
    Movie.content.setContent("Gateway");
    
  2. There are very likely 2 SWFs that are completely lost. This code appears:

     Movie.content.setContent("Level4Anim");
     Movie.content.setContent("GameEndAnim");
    

    As a younger me playing the game, I never reached level 4. There are also no available playthroughs on YouTube. But I think it’s safe to assume that there was an animation for entering the 4th level and an animation for passing the entire game.

  3. It seems as if Comm.swf is needed as a module. The code refers to an object called Comm for sending game data to.

    comm.sendScore(GameData.score); 
    

    However, for some reason, if I put it into the XML, it fails to properly use it. But without having any module, Flashpoint never loads the game at all. Only if I put into the XML and set the path incorrectly does the XML load any of the SWF pieces.

  4. I thought I had my breakthrough with this piece of code before the intro set content:

    if(Key.isDown(16) && Key.isDown(17)){
            if(Key.isDown(49)){
                GameData.level = 1;
            }
            if(Key.isDown(50)){
                GameData.level = 2;
            }
            if(Key.isDown(51)){
                GameData.level = 3;
            }
            if(Key.isDown(52)){
                GameData.level = 4;
            }
    

    Which, in the context of the code, means that by holding down CTRL+SHIFT+ A KEYBOARD NUMBER corresponding to the game level, you could switch to different game modes. This didn’t work - it would freeze the game.

So, at this point, I was getting fed up with playing the debug level and trying to get the game to transition to Gateway or go from Intro to the game. I was only able to get to a point where I could skip the intro and go to Gateway, only to have it repeat that process once again before making it to the game. It wasn’t transitioning properly between levels. And the game level and score weren’t showing up, which I suspect is extremely important for getting the gateway transition to work.

I was pretty much done.


Right about then was when I stumbled upon this code within frame 30 of the SWF:

    switch(GameData.level)
    {
    case 1:
        StartLevel(1,"Woods_Section1","Start");
        break;
    case 2:
        StartLevel(2,"Caves_Section1","Start");
        break;
    case 3:
        StartLevel(3,"Crystals_Section1","Start");
        break;
    case 4:
        StartLevel(4,"Lair_Section1","Start");
        break;
    default:
        GameSettingDebug = true;
        _global.PostVRTips = false;
        _global.PostBonusRooms = true;
        _global.PostExtraLives = false;
        if(Key.isDown(49))
        {
            StartLevel(1,"Woods_Section1","Checkpoint2");
            break;
        }
        if(Key.isDown(50))
        {
            StartLevel(2,"Caves_Section1","Start");
            break;
        }
        if(Key.isDown(51))
        {
            StartLevel(3,"Crystals_Section1","Start");
            break;
        }
        if(Key.isDown(52))
        {
            StartLevel(4,"Lair_Section1","Start");
            break;
        }
        StartLevel(3,"Bonus_Room_1","StartDoor");
        break;
    }

So I’ve been mentioning there was a debug room, and I had no idea how to escape from it. And the above code was the key. For some reason (that I have still not resolved but I suspect it’s due to the XML loading incorrectly), GameData.Level was not being set properly for the game go to the actual levels. So it defaulted to that debug mode.

So in hindsight, I could’ve just kept that code. That Key.isDown parameter threw me off - apparently if I hold down the corresponding key BEFORE the game launches, it throws me into the correct level without the debug mode. I was trying to do so when the game was already loaded, and like the CTRL+SHIFT+Keyboard number, it wasn’t working.

But in any case, I went about modifying the actual code using Flasm, the best way I found to modify the content of the object. JPEXS can edit P-Code, but I found that it didn’t save properly. I deleted the debug settings along with the extra lives and such, and placed StartLevel(3,"Woods_Section1","Start); instead of the Bonus_Room_1 function.

Here’s what my XML ended up looking like:

<root _width="600" _height="370">
    <module type="object" required="1" baseLevel="2500">
        <comm src="swf/comm.swf"/>
    </module>
    <loader baseLevel="400" required="1">
        <loader src="game.swf"/>
    </loader>
</root> 

That Comm, as I mentioned before, is linked incorrectly on purpose to force the game to load as a loader. If you want level 2, you hold down 2 on your keyboard once you launch it in FPL and so on.


Although I’m disappointed in being unable to 100% perfectly recreate the game, I’m happy that these lost levels can still be played. (Although there is Dark Souls’ style death where if you die you must restart).

As an open source programmer, it’s sometimes hard to see and explain the work that we do. Rarely do we get to do something so compelling that non-programmers can understand the gravity of the work that we’ve done. That’s why I enjoy this community, there’s lots of variety, interesting challenges, a compelling reason to do it (saving items of historical importance) and I can say that I worked on saving a game that mattered to someone.

Oh, and it’s nice to know that I managed to pick up better experience of XML and delved deeper into the subtleties of decompilation, flexing my code reading skills and understanding of ActionScript.

Wrap up

We accidentally missed Waffle Boy’s Mountain Adventure for our 6.0 release due to the overwhelming amount of game uploads! If you cannot wait for 6.1 and you have Flashpoint, you can download Waffle boy here.

Again, in order to play the levels - download Flashpoint launcher , higher than version 6.0. Find Mountain Adventure in the list, download it. BEFORE pressing play, hold down the corresponding level number on your keyboard - 2 for level 2, 4 for level 4, etc. There are only 4 levels. Then hit play. These files are made to be used for Flashpoint specifically, but you may be able to use it elsewhere.

And if someone wants to heavily modify the ActionScript so the intro and gateway work, join our Discord! (And thanks for lasting all the way to the end of this post!)