GSoC Week 1: Kirk is incompetent

It’s been a week and change since GSoC started. When we left off, I’d just finished implementing pathfinding. In the week since then, I’ve been busy implementing the action system, which is central to any adventure game.

The action menu and inventory

First thing’s first: we need to be able to select our actions.

This game’s interface is… questionable. You click on a body part to select your action, ie. clicking on the mouth selects the “speak” action. It may look cool and all, but the selection areas are just a bit too small. I also really dislike how the game is constantly warping the mouse around – I never have any idea where it will be after closing a menu… but alas, my job is to recreate the game faithfully, not to change the things I deem clunky.

The inventory was the next logical target. By this point, I had also figured out hotspot detection; I started to get a good grasp on how the game handles interaction between objects.

Inventory items were also a good test subject for implementing the “look” action.

Room-specific code

With the interaction system just about figured out at this point, it was time to look at room-specific code. This is what makes the missions tick; each room has a series of “event hooks” that may run when the room is first entered, when a certain amount of time passes, or when you try to vandalize a sign with a phaser.

Rewriting this will easily be the most time-consuming part of the project, and I suspect that future progress updates won’t be much more than “I finished rewriting these rooms, check it out”.

That being said, I finished rewriting the first room, check it out.

(Source: https://www.youtube.com/watch?v=sJpijZ1ukuI)

If all goes well, maybe the first mission will be completable by next week’s blog post. Here’s hoping.

GSoC Week 0: Implementing the basics in Star Trek

Google Summer of Code officially started yesterday; but, since I got started a bit early, I already have a week’s worth of things to talk about. If I want to support both Star Trek: 25th Anniversary and Star Trek: Judgment Rites, I need to get moving!

Audio and the Options Menu

Since the engine could already display textboxes, the options menu seemed like a juicy next target. In fact, I barely needed to do anything to make it display; the buttons were loaded in exactly the same way as other textboxes.

This provided a nice segue into audio code; it showed me which variables corresponded to “music enabled” and “sfx enabled”. MIDI music already worked thanks to the efforts of clone2727 from years back. I added support for midi sound effects, which turned out to just be separate tracks on the same midi file as the music.

But there’s more than just MIDI – the game features voice acting from the original Star Trek cast. Their lines, plus some other audio, are stored in .voc files on the CD. To work with ScummVM, they need to be copied from the CD to the hard drive with the rest of the game’s data.

I figured it would be easy. ScummVM has a built-in VOC decoder. What could possibly go wrong?

Well, I was greeted by thisSWEET JESUS THAT IS LOUD. (I always use headphones, by the way.) However, it’s definitely the red alert sound.

OK, so after a quick look at the decoder function’s flags, I passed Audio::FLAG_UNSIGNED to the decoder. That’s much better.

Beam me down, Scotty

With audio working, animations were next on my list. As it turned out, the transporter room was perfect for testing this; the entire sequence is just 5 objects being animated.

Did you notice that every crewman is McCoy? That’s because the other 3 officers have their animations based on McCoy’s. They just apply an xor over the face and recolor the uniforms.

After fixing that (and discovering that the timer runs at 18.206 Hz, the rate of the DOS clock), the animations looked perfect, aside from layering.

Scaling

Sprite scaling would be needed before tackling away missions. Star Trek optimized this heavily; they wrote a function which constructed another function in RAM! This resulting function was just an unrolled loop which copies a row of unscaled pixels to a row of scaled pixels. This is DOS, so there’s no interpolation here.

I obviously don’t need to do anything as fancy as dynamically constructing a function in ScummVM. There’s no way I could do that portably, anyway. Fortunately, my computer is probably a hundred times faster than what Star Trek was developed on, so I’m not too worried.

Weirdest transporter accident I’ve ever seen…

Away Missions

With animations done, it was time for me to do movement and pathfinding.

Pathfinding is a simple system where each room has a set of waypoints. Given a source and a destination, the game locates the waypoints closest to each. Kirk then moves to the source waypoint, moves along a set path to the destination waypoint, and then moves from there to the exact destination you clicked on. This sometimes causes Kirk to walk back-and-forth when he’s starting a walk, since he might need to move backwards to reach a waypoint. I’m not sure if other adventure games do this, but it does make movement in this game feel somewhat finicky.

Anyway, just today I figured out how warps work – some of them, anyway. Each room has a set of polygons where warps occur if Kirk walks into them. However, apparently the doors in the first room of the first mission are more complicated. It seems that, since a sound effect goes with them, they need to call some room-specific code to handle that.

The game is suddenly starting to feel alive. Not only can I control Kirk, but the crewmen follow behind him when moving between screens, or do their idle animation when waiting around. It’s a small thing, but it’s rather refreshing after looking at static screens for so long.

Other stuff

I found an interesting error message:

Jay didn't think about pmcheck.

Jay is probably Jayesh Patel, who is credited as one of the programmers. I don’t really know what that error message means, but at least I’ll know who to blame if I ever see it. 🙂

Anyway, next on my list of things is to work on the action menu and inventory menu. And, very soon, I’ll need to start looking into how room-specific logic works. Again, this is all done with x86 code and not a scripting language, so it will need to be tackled on a room-by-room basis.

Google Summer of Code 2018: Boldly going where one team has gone before

This summer, I’ve been accepted into Google Summer of Code to work on the ScummVM project. My task: to reverse-engineer Star Trek: 25th Anniversary and rewrite the game’s code in C++ as part of ScummVM’s framework.

Why did I apply to ScummVM? Well, to me, it sounded a lot more interesting than traditional coding projects; I get a kick out of picking apart a game’s code (as I’ve been doing with Oracle of Ages for the last 3 years), so this should be an enjoyable summer for me.

I’m not quite starting from scratch – an engine with some basic file handling and image display was started by clone2727 several years ago – but the vast majority of the work remains to be done. I got started on this while working on my proposal, and implemented the sprite and text systems in the ScummVM engine (see below).

The task of rewriting the game is complicated by the fact that the game appears to have a great deal of hardcoded logic; unlike more “sophisticated” engines which have their own scripting languages, everything here appears to be done with x86 assembly. On one hand, I’ll need to rewrite all of this logic, which is a lot of work. On the other hand, all of the game’s logic will be documented when it’s done, so bugfixes will be easier to implement after the fact.

I’ll be posting weekly updates here as I proceed, at least once the “coding phase” starts (May 14th). My work can be found in this repository.

Big thanks to Google and to the ScummVM team for selecting me.