Sunday, October 23, 2011

Two milestones reached

Yesterday I was chatting with Md5 about the recent progress in Blue Force, and I thought to myself that I should make a blog posting. Looking back, it seems it was June when I made the previously posting. I hadn't realised that it was that long.

As those of who frequent the IRC channel or forums would be aware, Ringworld was completed, and will be part of the upcoming official 1.4 release. We'd already had a successful testing period, with several bugs identified and fixed. It'll be nice to see another game I've worked on added to the trunk and become officially supported.

Now, onto more recent developments. As of yesterday, Strangerke and I have reached two more milestones in the progress of the TsAGE engine.

The first is that I completed the first complete play-through of Blue Force. This had been a gradual process over the last few weeks, as we identified game stopping bugs and fixed them. The save format also changed several times during this period, as we implemented the final few game scenes, and added missing game state variables. Yes, clone2727, the game is completable. So nyaaa. :)

The next step will be for us to start playing the game again from the beginning, comparing it against the original and looking for any minor graphics glitches or problems that we missed. We will also ensure that none of the fixes done for the later game scenes had any adverse effect on the earlier scenes. This includes a variety of minor issues that we identified during the first play through, but were deemed too minor to immediately worry about.

One of the more amusing glitches I came across was a scene in day 2 of Blue Force where a police inspection is done. This particular scene seems to use animation sprites different from anywhere else in both Blue Force and Ringworld. Likely some as yet un-handled flag or sprite offset - the result being that all the officers get drawn with their bodies on top of their head. Picture if you will headless officers walking around balancing on their own heads. :)


The second milestone is the commit of the beginnings of the ‘Return to Ringworld’ game - the third and final 2-D TsAGE adventure. I’d previously spent some time on the side starting to look at a disassembly of the game, and identifying all the common engine functions against my disassemblies of Ringworld and Blue Force, and got to the point where all the core functionality had been identified. I started on adding the game classes about a week ago, and have got to the point where I can at least display the first in-game scene.

I had been holding off on committing this to trunk until after the branch, since it affects a lot of the files, but now the 1.4 branch has been done. It also invalidates the current Blue Force savegame format (but not RIngworld) - since both of them share mostly the same UI code, it made sense to encapsulate it in a common base class. Given that Blue Force isn't official yet, it was easier to break the existing savegame format for it as part of this, then to try and maintain the savegames intact. So it was good that I’ve now completed the first play through of Blue Force, and can start from the beginning of the game again.


I have a tendency, for games I plan to work on disassembling, not to play them through using the original executables. That way I can have the fun of gradually playing through the game as I implement the code for it in ScummVM, and get the enjoyment from playing it for the first time in code that I’ve written. It also serves as an inducement to work hard, so I can see what happens in the game. I’m eager to see what happens to Quinn, Miranda, and Seeker in their second foray to the Ringworld.

Once we've cleaned up the Blue Force code-base a bit more, then work on Return to Ringworld will begin in earnest. Hopefully there won't be too many core engine changes, and work can proceed on it as rapidly as was done for Blue Force.

On a final note, for those of you wondering about Rex Nebular, I did start to return to looking at it, but I've been away from working on it in earnest for too long. There are still parts of the game not yet dis-assembled, and I'd need time to complete that and re-familiarise with the existing code. So it really needs some time when I'm not actively working on some other game. I'll have to see how I do when the TsAGE games are complete.

Tuesday, June 21, 2011

Let there be sound

The TsAGE engine for Ringworld now has sound playing! I'd be hard to pressed to express just how happy I was when I ran ScummVM and finally had correct sound playing back. I was like, Oh My God! it's finally working. After all the time spent re-implementing all the sound code from the original, and then spending nearly as much time slowly tracing through the execution of the original versus ScummVM to try and figuring out the cause of differences, it was a relief to finally have it working.

As such, the Ringworld game is that much closer to being complete. There are still a few areas left to look into, and polish up, such as:
* Sound fading isn't yet working correctly
* I need to hook the sound manager into the savegame format, and ensure playing sounds are persisted
* There are certain suspect areas in the sound manager's main _sfRethinkVoiceTypes method to review; at least one variable is being assigned to at one point and not currently being used, so I need to double check if that's really the case.
* The sound manager could use an overall clean-up.

It won't be too much longer until it's ready for public testing. Soon Larry Niven fans will be able to explore the Ringworld, and search for a way to defeat the bloodthirsty Kzins.

So what's coming next? Well, I've promised myself some time to work on Rex Nebular again, which I've somewhat neglected in my zest to have Ringworld completed. Strangerke is also enthusiastic about working on the other games that used the TsAGE engine, so I'll probably be spending some time on the game Blue Ice to determine what changes have been made to the engine, and provide a basis for being able to re-implement the game scene logic similar to what was done for Ringworld. Finally, I may offer to help out somewhat on the other games the team has received original source for. Gotta keep busy after all. :)

Monday, June 13, 2011

TsAGE sound support progressing

Work on the TsAGE sound has been progressing. I had originally hoped that the raw format used by the game would be a standard Adlib raw format that I could feed into one of the existing Adlib Sound FX classes. I tried to pass the data to the player class in the Cruise engine, which I had previously worked on, but unfortunately, whilst it didn't crash, it didn't play anything. And I'm not familiar enough with sound formats to have been able to diagnose why.

As such, I've spent some time powering through implementing all the relevant sound code directly from the demo executable. With the symbols identified, I at least had a heads up for the original engine names for a lot of the methods. Plus, we were able to garner some additional information from a demo version of the game Protostar. Whilst it's not an adventure game, the sound code has a lot in common with Ringworld; and not only did it have method names, it also had a lot of field information for the classes and structures. As with the Ringworld demo, it didn't have it for all the classes, but I was at least able to name fields in the sound classes and the sound manager.

From this basis I've now implemented what I think are all the relevant methods of the demo for both the Adlib sound driver and the sound manager classes - I'm currently using the OPL functionality with OPLWriteReg in place of direct port access. The resulting code I've completed doesn't actually play anything back yet, though. Making a log of the underlying writes to the Adlib port versus my ScummVM code, the results are different, so there's obviously some incorrectly implemented code.

My current major suspect is a method called _sfRethinkVoiceTypes - it's a enormously big method with over 500 lines, responsible for updating the voice channels based on queued sounds. It's one big mess, with a large pre-processing, post-processing, and main processing areas. I'll have to slowly trace through the execution both in ScummVM and the demo in the DOSBox Debugger to identify the problem. Hopefully once I've identified the differences, I'll finally hear some sound output.

Fingers crossed. :)

Sunday, April 24, 2011

Most wonderful Ringworld demo

Hopefully everyone had a happy Easter weekend; or for those of other religions, were able to enjoy a long weekend wherever you are. :)

It's been a little over a week since the TsAGE engine hit the trunk, and a big thanks go out to everyone who's helped out with commits - fixing compilation problems, and cleaning up the code. Special thanks again go to Strangerke, who has been busy working his way through the Ringworld game to fix bugs and make the game completable. I too have spent most of my time fixing some of the outstanding bugs, as well as newly identified bugs in the core engine.

On another topic, we've had a stroke of exceptional luck. I had been starting to get bogged down in all the various classes related to sound handling, and I wasn't looking forward to trying to figure out what it all did. But then Strangerke discovered that one of the two available Ringworld demos actually had embedded symbol information for most of the variables and methods of the demo!

Since the full game engine isn't anticipated to be much different from that used in the demo, it likewise means we've suddenly got a huge jump forward in understanding the remaining sound-related parts of the engine. Fuzzie was able to extract the information into a text file listing, and I wrote a quick and dirty script in IDA's IDC language to load the symbol information into a new IDB file for the demo executable.

This isn't quite as good as getting the full original source for the game, but it's still a major find. The biggest limitation of the symbol information is that such symbol tables don't include information for fields within structures. So, for example, the 'ASound' class has 282h bytes of information, but the instance of the class only has the symbol for the first byte, not all of the bytes. Therefore, I'll still need to spend a reasonable amount of time figuring out the contents of the various methods. But at least with the method names known, I can more easily figure out what each method actually does.

In the space of under two days, I've already implemented support for the two Ringworld demos. Luckily, the demos use a single script sequence rather than direct code, which made it very easy to add support for. All that still needs to be implemented for the demo are a few custom dialogs, and ensuring none of the full game functionality, like Saving and Restoring, is enabled for it.

Implementing support for the demo also identified a key difference between the two versions of the demo - the second demo was similar to the CD version, in that they changed the format of how the data for priority regions and walkable areas was stored. Having a disassembly of the demo with symbols made it easier to identify the relevant areas of code, and figure out the differences.

In addition to polishing up support for the demo, I'll likely making a branch to work on the sound classes separately. We currently have some hard-coded logic in the existing engine to properly signal actions that any played sound has immediately ended, so I don't want to interface with that whilst working on a proper implementation of the sound system.

So things are definitely rapidly moving forward. :)

Wednesday, April 13, 2011

TsAGE has now hit the trunk

Hi all,

I'd been meaning to write a new blog post for a while, but progress was progressing so quickly, that I never quite got around to it. Now, though, work has progressed far enough that the tSage engine has now been merged into trunk. Huzzah! :)

Many thanks go to Strangerke, who joined me in implementing all the various game scenes of the Ringworld game. Together, we've implemented all the game logic.

The following is the state of the game:
* All the game scenes for the floppy version of the game are implemented, although some still need some bug-fixing, so the game isn't completable.
* Sound isn't supported yet, and still needs to be reverse engineered in the original game.

So we have the following goals for the near future:
* We'll be working on fixing the remaining scene bugs, and ensuring the game runs smoothly from start to finish.
* Implementing the sound code.
* I also want to implement support for the original game's cheating/debug functionality.
* Add support for the CD version of the game, which has some minor differences.
* And add support for the demo version, if possible.

All in all, it's a celebration for another engine being added to the ScummVM universe. :)

Sunday, December 19, 2010

tSage engine proceeding quickly

Hi all,

I've really been making some great strides forward with my implementation of the tSage engine. I offer the two screenshots below. One is from the first game scene when run in DOSBox, the other under ScummVM:







Hard to tell them apart, isn't it? :). The one on the left is from DOSBox, and the one on the right is ScummVM. All the initial hotspots in the first game room are now set up, are being drawn on the screen, and have correct look descriptions. The only exception is a minor graphic glitch with the doorway - the current drawing code doesn't yet support clipping objects based on priority calculations, so the top of the doorway isn't correctly clipped off.

One of the next major steps from here is to delve further into the movement classes and code. Whilst the player is now drawn on-screen, I don't yet have any code responsible for moving the player, such as when you manually walk somewhere, or when the computer moves the player to a set location, such as when you use the door beam.

From what little I've looked into the movement code so far, the game maintains a set of classes responsible for moving objects within the scene. For the player specifically, there's a lot of code that seems to make use of special 'walk regions', which indicate where on the screen the user can walk. The movement code is tied into this, and uses them to determine both where the player can move to, and for pathfinding to move the player to the given destination.

Given the pace I've been having recently in other areas of the engine, I don't anticipate that it will take too long. Hopefully, soon I'll be able to move the player about on the screen. Then I can start delving into implementing all the logic involved in the first cut-scene, where the Kzin comes to the door and speaks with the player. It's so much more fun working on an engine when you can almost day-by-day make visible progress in it's implementation.

PS: I've been making such rapid progress with tSage, I've been somewhat neglecting work on the MADS engine. I hope any fans of Rex Nebular will be patient with me.. I will get back to work on it eventually. :)

Sunday, November 21, 2010

Update on the game engines

Hi all,

It's been a while since my last blog posting, so I figure it was time to wax poetic on what I'm currently up to.

I've spent some considerable time working on the Broken Sword 2.5 engine with Sev. As has happened previously, what I originally intended as something else to work on alongside Rex Nebular, quickly overshadowed it, and I ended up spending most of my recent holiday just working on it. It's now available in the public SVN, and is running fairly well, so I'm going to leave any remaining work to any other interested parties, and have returned to work on my other engines.

-----

Rex Nebular is coming along nicely. As I've mentioned in the past, I've been creating a custom script engine, based on the Tinsel script interpreter, to handle interpretation of game scripts. I've then created a custom script program that iterates over specified functions in the Rex Nebular disassembly, and converts them to a script text file. I then have a simple script compiler I've developed that compiles the scripts, and creates a new 'mads.dat' file.

As of right now, I've only converted the scripts associated with the first game room. The scripts associated with scene entry and 'scene tick/step' are working properly, so Rex is now waking up and standing entirely based on script execution, rather than the hard coded behaviour I previously had. I consider this a big step, since it validates the entire process of converting original executable instructions to script code, and final execution works properly.

The next step is to implement some remaining missing pieces of the action dispatch code so that Rex can actually do actions, rather than just walking about. Right now, I'm aiming for right-click Look actions to work properly. Then it should only be minor further changes to have other actions work as well. Soon Rex will be able to do all the various things in the first room. And I'm looking forward to the day when Rex will finally be able to take his first steps into a bigger world and finally leave the cockpit.. :)

----

Another game engine I'm currently working on is the tSage engine, which is used by the Ringworld game. Previously, the fact that it was so Object Oriented annoyed me, because it made it harder to understand the game flow since some classes, such as the event manager, had four descendant classes, making it difficult to understand what each class in the hierarchy did. Now, though, I'm actually starting to see some benefit from it.

The classes related to handling the game state are very clean. For example, there is a generic 'Scene' class, from which each game scene dervices a specific implementation class. So, there is a 'Scene30' class for the first scene in the game, and it has fields for the various hotspots and objects within the scene. Speaking of hotspots, there too is a hierarchy, with a base 'SavedObject' (used for object persistence), which subclasses to a 'SceneHotspot' (used for basic hotspots), which subclasses to a SceneObject (which is an object in the scene that is drawn into it, rather than being part of the background). From there, a SceneObject is sub-classed to the NPC class - this is where the encapsulation really helps, since all logic related to drawing NPC's is already handled by the SceneObject class, so didn't need to be disassembled multiple times for different kinds of things in the scene. The NPC class only has to implement the additional logic for moving character around the scene.

In fact, the NPC class also further sub-classes to the 'Player' class, which has extra logic to handle allowing the player to interact within the game. A lot of the logic for handling the player is thus already handled by the NPC class, so the Player class only has to add on the extra logic for allowing direct player control.

Because of this OO model, all the game logic is implemented by deriving new custom classes from these base classes, and then adding them into a particular scene. So, for example, the first scene in the game has the player having to ring a doorbell by 'using' a motion sensing beam. This beam is implemented as a 'SceneObject' derived custom class, which overrides the 'action' method to either provide a description on-screen for the 'Look' action, and start the 'kzin answering the door' sequence in response to a 'Use'.

I'm still undecided about whether I'll re-implement the game by manually converting all the game logic to C++ code, or try to create a process, as with Rex Nebular, to convert the game executable routines into equivalent scripts that could be interpreted. The OO nature of the game engine would make it trickier to convert to scripts. I'm planning to at least, eventually, converting the logic for the first scene to full C++, and see how it looks.