Saving Jagex’s Vertigo
Originally posted on 2019-04-19.
This week I was aiming to work on the actual code base of FPL and adding a new feature - a Save manager to backup and restore files. As I mentioned last time, the application is built on Electron, using Typescript and leveraging the use of React to deliver component-based modules.
Setting up FPL was very pleasant - it was primarily built by obelisk, the main mechanic on the Flashpoint team. I will keep mentioning the fact that I am an abused Windows developer until the end of time - FPL was primarily made for Windows so the development environment was much more favourable.
Some issues that arose:
- The games didn’t show up anywhere. This was fixed by going into configs and pointing at a consumer installation of Flashpoint (Ultimate or Infinity)
- The images and playlists didn’t show up.
Had to change
config.json
to this:
"imageFolderPath": "Images",
"jsonFolderPath": "Data",
"logoFolderPath": "Logos",
"playlistFolderPath": "Playlists"
- Redirector didn’t show up
Fixed by copying
services.json
into the consumer Flashpoint’sData
folder
Side Tracking from the Save Manager
The internal documentation is still a Work in Progress. So, a lot of inferring and questioning needed to be done.
As I was resolving build issues, I would take a break and resume doing some curation. I haven’t mentioned all my curations (since Pebble’s Quarry, I’ve also resurrected Postopia adventure and was working with an FPL colleague to restore more of them). I also tried to resurrect Waffle boy’s mountain adventure, famously lost in our community. I managed to partially recreate the missing XML (that loads the separate Flash SWFs properly) to play the first level, but beyond that I couldn’t resolve it.
So, I decided to curate an old Java applet game from freearcade.com that I used to play back in the day. It was a game called Vertigo, from 1999, made by Andrew Gower of RuneScape fame. I mistakenly assumed that it would be as easy as the few that I did after my first one.
Issue:
Get Vertigo to work on Flashpoint since it no longer works on the browser.
Problems (If you want the solution, scroll down):
- Going the traditional route of setting up the files ended with no Flashpoint redirector complaints. I needed something to error out so I would understand the problem, so I directly went to the JDK and used appletviewer.exe directly with my embedded html and class file. That threw me this error:
java.lang.ClassFormatError: Name index 0 in LocalVariableTable has bad constant type in class file vertigo
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at sun.applet.AppletClassLoader.findClass(AppletClassLoader.java:217)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.applet.AppletClassLoader.loadClass(AppletClassLoader.java:152)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.applet.AppletClassLoader.loadCode(AppletClassLoader.java:626)
at sun.applet.AppletPanel.createApplet(AppletPanel.java:799)
at sun.applet.AppletPanel.runLoader(AppletPanel.java:728)
at sun.applet.AppletPanel.run(AppletPanel.java:378)
at java.lang.Thread.run(Thread.java:748)
Here’s where my detour started - everything I read online mentioned that it was incompatibility between an older version of Java versus a newer one. Using this command in Bash, I can get the major version (which tells the user which JDK version was used to compile the file):
$ od --format=d1 vertigo.class -j 7 -N 1
0000007 45 0000010
The middle number (45) indicated the version. Here’s a table of JDK versions and their respective major versions:
Java Version | Major Version |
---|---|
1.1 | 45 |
1.2 | 46 |
1.3 | 47 |
1.4 | 48 |
5 | 49 |
6 | 50 |
7 | 51 |
8 | 52 |
9 | 53 |
10 | 54 |
11 | 55 |
Clearly this game was made with one of the earliest possible JDKs - 1.1.
- My approach went like this (which was incorrect) - Download JDK 1.1.X version from the Oracle archives.
- Turns out the original JDK was a 16-bit program so installation was blocked by this error:
Unsupported 16-Bit Application
.
That’s when I learned the Win10 x64 architecture completely dropped 16 bit support (another indication of how old programs lose support after some time). So: - Spun up a Windows 7 x32 virtual machine
- Installed it successfully there
- Sent the extracted files back to my host
- Modified the startJava.bat located in Flashpoint to point at the new, ancient JDK and ran the game
- Finally I was able to get useful asset GET requests through the redirector! I collected the files that way.
- An issue with bad class file format showed up - apparently the wrapper.class was made with major version 48 instead of 45, so I re-hunted for the files via Wayback
- Finally, after all of that hard work, this was the result:
It was throwing an array out of bounds and pulling in the wrong assets.
- The only lead I had there was after using javap to decompile the class files, there were errors with the encoding, and it gave me nonsense unicode
- At this point I was giving up - learning ancient encoding to translate the code into something that made sense was, the first cardinal sin of troubleshooters, going way too complicated for a solution
Solution:
- Gave up and asked the Java experts on the Flashpoint discord
- nosamu pointed me to Strawrat, a skilled Java expert who had reverse engineered Java applets before
- Within ten minutes, the problem that had been plaguing me for days had been resolved
Instead, Strawrat started at that very first problem all the way back at the beginning -
java.lang.ClassFormatError: Name index 0 in LocalVariableTable has bad constant type in class file vertigo
Here’s how they did it:
- Use a Java .class file editor - Dirty Joe This one in particular doesn’t crash with really old Java class files
- Open the Vertigo asset classes in the program
- Hit the Methods tab, it will show a list of methods in that class. The first one should be selected.
- In the panel on the right that says Attributes, click on Code. That should open up a new window that has a bunch of stuff (Max Stack, Attributes, Exceptions, etc)
- Right click on LocalVariableTable and select Delete Attribute
- The close that window and save the class file
Here’s a demonstration:
Apparently LocalVariableTable
in the class file was broken and needed to be deleted - it’s considered optional, similar to LineNumberTable
.
This answer was so beyond my expertise that I knew I would have never figured it out on my own.
I’m very greatful to the FPL community for their expertise and wizard-like reverse-engineering.
You can see the game in FPL 6.0 or download Vertigo here!