Thursday, February 20, 2014

Explosive decompression

Looking back, despite my earlier promises of posting more regularly, it seems I've been a bit tardy in posting updates, and quite a bit has happened. So lets get up to date with what's been happening with me. Firstly, we finally got some proper bug reports for Return to Ringworld, and have been working to fix them. Well, moreso Strangerke than me, so thanks go to him for his work in fixing bugs when he has the time.  As of right now, the card mini-game still isn't fully functional, but at least the main game is that much more polished now than it was.

Secondly, as of Monday, I finally merged the next game I was working on, Voyeur, into the project's master branch. This is a weird little game that Strangerke put me onto, because the original DOS executable had debug information embedded in it, which made it somewhat easier to implement. Still a lot of work to understand the contents of methods, reimplement them, and get the game in a stable state. But it made a nice change of pace from all the TsAGE work, where we had to disassemble everything from scratch. As of right now, the Voyeur engine only supports the DOS version. Apart from DOS, there were also CDi and Macintosh versions released. The Mac version at least may be supported at some point in the future, although there is some extra complexities we'd have to worry about due to the Mac-specific data in it, such as rasterized fonts that the PC version doesn't have. Adding support for it might make a nice future mini-project for a Mac enthusiast.

So what's next? Apart from further bugfixes for both Return to Ringworld and Voyeur, I'm already onto my next project.. once again tackling the white elephant of Nex Nebular, for the 3rd time. This time, though, things will hopefully be different. Using my experience with disassembling the TsAGE sound system, I tackled the sound system first, which was the major previous remaining stumbling block. And as of last Sunday, I finally got it working! That's right, my new embryonic MADS engine was able to play back the explosive decompression sound you get when you fail the copy protection check. It was a wonderful feeling, after spending a week reverse engineering and then implementing the code, then having spent an afternoon trying to debug my code and compare bytes being written to the ScummVM FM_OPL driver against the port writes in the original running under DosBox, to finally get everything right, and hear the sound coming out of my speakers.

 It turns out that despite some funky assembly tricks in the player that I had to work around, the player itself is actually a fairly compact, simple implementation. I'm no sound expert (as my frequent prior complaints make clear :) ), but I understood enough to give the various methods in my code halfway decent names, and name at least some of the fields. Hopefully a further analysis, now that I have cleaner C++ code, will help me better understand what's going on, and give the rest of the fields more proper names.

Now that the issue of sound support is taken care of, how am I going to proceed from here? I have a lot of code back from the earlier combined m4 engine which had code from both Rex Nebular and Orion Burger. Part of the trouble with the earlier attempts, I think, was that we were overcomplicating matters. As such, I'll only gradually put in code as I need it, and not worry so much about M4. That'll help me keep the focus more on getting Rex Nebular to work. Not that I'm going to just chuck out all M4 code from the engine. I've already started work on making the core classes, such as the previously named 'M4Surface' class, having a cleaner structure more suited for multiple games. For example, it'll now have it's own class factory, which will abstract having a base MSurface class that will have different descendants that implement the various game specific load/display logic. That seems cleaner than littering the code with "if isM4()" checks, and having methods like "rexLoadBackground". As far as a caller is concerned, they'll just initialise a surface, and the factory will take care of giving them the right kind for their game.

With a cleaner separation of game logic into descendent classes, I'll be able to, for example, keep in place special cases we'd already figured out for Riddle of Master Lu, and make it that much easier to implement support for it later. So that should keep a certain team member who shall remain nameless happy.  :)

At the moment, I'm currently aiming for getting all the initial engine setup sorted out, and playing back the animation sequence for when you get the copy protection answer wrong. As I mentioned above, this will involve pulling some code from the old project to save time, but I'm also already doing a fair amount of refactoring and cleanup, such as changing char *'s to Common::String, using Common::Point's, properly commenting the code, and so on. Given the amount of previous work done on the old M4 engine and the mostly complete disassembly I had of Rex Nebular, we can hopefully expect rapid progress in functionality, and eventually enjoy Rex's escapdes as he quests for the vase he's been sent to find.