GSoC 2018 Wrapup (and final mission details)

Google Summer of Code officially ended last Monday, August 6th. My project was to reimplement Star Trek: 25th Anniversary in ScummVM.

The project involved reimplementation of all of the hardcoded game logic, since it doesn’t have a scripting language. In my original proposal, I conservatively estimated that I would finish only the first 4 away missions, of 7 in total. In fact, I managed to finish all 7 (though it took a few days past the official end time).

That doesn’t mean it’s done though; the away missions are only half of the game, albeit the larger and more interesting half. There also remains the pseudo-3D space combat element, which I dabbled with, but am still nowhere near done with. I’m hoping to be able to finish that by the time summer’s over, though I can’t make any guarantees on that.

So: the end result is that, right now, you can play all 7 away missions in Star Trek: 25th Anniversary in ScummVM. However, without the bridge sections or space combat, players will be missing the context of why you’re on the away mission in the first place.

Here is a more comprehensive list of what remains to be done in the long-term:

  • Space combat, segments taking place on the bridge (finish implementing 25th anniversary)
  • Support for non-DOS versions (mac, amiga) and other languages (french, german)
  • Support for Judgment Rites (probably not happening too soon unfortunately)

Get the code

See my commits here.

To compile ScummVM with the star trek engine, run:

./configure --enable-engine=startrek
make

Then, you will need to provide ScummVM with the original DOS game data files, and copy the “voc” folder from the CD into the same folder. (If you don’t do this there will be no voice acting and missing audio.)

The final mission

Continue reading for the regular postmortem on the mission I just finished working on. Spoiler alert.

In this mission, the USS Republic, which you fought in a mock battle at the very beginning of the game, gets demolished by a mysterious assailant.

There are reports of softlocks in this mission. One is that after you lower the shields, the Elasi immediately beam over before you can shoot them, rendering the mission unbeatable. I haven’t verified this, but I can see why it would happen based on reading the code; the timer that’s supposed to make them beam over before you raise the shields, also applies after you lower the shields! So, if you lower the shields much more quickly than the developers expected, that counter may reach 0 and cause the elasi to beam over.

There’s another reported softlock, though, that doesn’t seem to be a real softlock. For some background, in the auxiliary control room, you’re supposed to either “use” or “look at” a specific part of a console in order to see that the torpedo loading mechanism is jammed. This triggers an event flag necessary to complete the mission. A GameFAQs guide claims that under certain circumstances, it becomes impossible to do this, which is only half-true.

Once you power up the shields, it becomes impossible to power up the weapons until later on. The result is that you cannot “use” the weapon system to trigger this event flag; however, you can still “look” at it to do so.

It’s all rather confusing – and it doesn’t help that you need to click on a very specific part of the console for any of this to work – but I haven’t found a softlock here. Though if I’m mistaken I’ll gladly fix any further softlocks.

Interestingly though, in the hallway that links the two turbolifts together, using Spock on the debris at the end of the hall, when the support beam is in place, would crash the game, because code execution actually derails into executing data. Those kind of mistakes can happen when writing raw assembly…

Anyway, that’s the most interesting stuff I’ve found in the final mission. I may make more infrequent blog posts as I work on the rest of the game, though don’t expect the almost-weekly updates I’ve been providing up until now.

GSoC Week 10: Nuclear moon bases

Last week I worked on mission 6, “That Old Devil Moon”. It features some interesting lore of two ancient civilizations that annihilated each other through the use of nuclear weaponry. What a totally, uh, alien and unthinkable prospect, haha…

This mission features the most obscure puzzle in the game, which involves converting “sacred numbers” from base 10 to base 3 to crack passcodes! While I personally can handle a bit of base conversion, the even bigger sin is that the hint required to open the door is missable! If you fail to look up every remotely relevant entry in the ship’s computer before beaming down, you’ll have no way of even knowing what numbers you’re even supposed to convert! I definitely had to look up a walkthrough here.

Incidentally, while implementing the text input boxes, I found a way to crash the game. Simply fill up the box, then repeatedly press the “end” key, enter a character, press “end” again, etc. Soon the text buffer overflows into something that’s probably important and the game crashes. This works because the “end” button is the only one that doesn’t check if the length of the string exceeds the maximum text size. Naturally this is fixed in scummvm.

In addition, this mission, too, has some ways to get an infinite score, by repeatedly scanning or using the computers in the final room. Using McCoy’s tricorder on the air in this room also works. That’s all in the way of bugs that I’ve found, though.

GSoC officially ends next week. I’ve opened up my pull request to the main branch, though the engine is still incomplete, so I can continue working on it in-tree; in addition to working on the final mission this week, I have some feedback to take care of before the pull request gets accepted.

GSoC Week 9: Space, and glitchy planet rendering

This past week has been spent on space; trying to make heads or tails of the game’s “pseudo-3d” engine. And, while it hasn’t been entirely unsuccessful, progress on this front has been relatively slow.

I started by getting the background starfield working. It involved some trigonometric functions and matrix multiplication. Nothing too insane, once I figured out what I was looking at. To complicate matters, the game has at least 3 fixed-point decimal formats, including a format specifically for numbers between -1 and 1, in addition to using the processor’s floating-point hardware on occasion.

Encouraged by this early progress, the next step was to make more elements of the game’s intro visible, starting with the red planet the Enterprise flies past. However, when I finally reached the function which draws space objects to the screen, the function graph showed me this would be no picnic.

Each box is a block of code, some too small to see.

Despite my best efforts, I was unable to quite get this working properly. I discovered today that I didn’t even have an accurate view of the function, because part of the code is overwritten from elsewhere before it gets called! Perhaps because of this incompleteness, I was only able to get a sliver of the image to appear in a glitchy way.

I’ll figure this out, eventually. But I alotted myself a week to work on this before moving on to other things, so I’ll come back to this later. It’s time to start focusing on code cleanup so this can be merged into scummvm, as well as finishing up the away missions. Then, I’ll come back to finish space combat and everything between missions.

GSoC Week 8: Set phasers to stun. …Then kill.

Last week was mostly focused on finishing up the second part of the “Feathered Serpent” mission, in which Quetzalcoatl is put on trial by the klingons for spreading messages of peace. Kirk agrees to go through a set of trials to prove his honor or something so that Quetzalcoatl can go free.

Kirk offering a fine defense.

Mission oddities

Last week, I mentioned various ways to get an infinite score in this mission. Well, there are even more, easier ways to do so in the second half, including:

  • Repeatedly scanning a door lock with Spock.
  • Repeatedly scanning an energy life-form with Spock.
  • Repeatedly carving out part of a room with a phaser.

All of the above are in a single room. This room also interestingly allows you to cancel a death if you react fast enough.

In addition, this mission has two endings (three if you just give up defending Quetzalcoatl entirely). The “main” win method is to discover a weird alien room, which is probably what most people did.

The secondary method is very obscure, and I suspect most people don’t know about it. If you don’t discover the alien room, you instead must pass a Klingon automaton blocking you.

Since the solution is so obscure, I’ll just tell you. Using the stun phaser doesn’t work; after two shots, it kills the crew. Using the kill phaser doesn’t work, either; it kills the crew after only one shot.

So, what’s do be done? Use the stun phaser, THEN the kill phaser. That will give it just enough energy to overload before it can take out the crew. …Naturally…

On my casual playthrough, I completely gave up on passing the automaton, since I already knew about the other method of completing the mission. This is an “inferior” way to beat the mission, anyway, but it’s interesting that it’s locked behind such an obscure solution.

What’s next

For now, I’m taking a break from the repetitive mission logic to take a look at the pseudo-3D and ship combat stuff. I really have no idea how long this will take, but I felt I needed to look at something fresh and different. Regardless, my primary mission is to get the away missions working and I only have 3 weeks left (officially), so I’ll return to that if time doesn’t allow me to finish the starship stuff. Due to the belatedness of this post, there’ll be another later this week.

GSoC Week 7: What does Quetzalcoatl need with a starship?

This week, in addition to finishing up the Harry Mudd mission, I’ve done the first half of mission 5, “Feathered Serpent”. This is the only mission to be divided into two “away mission” segments, with another ship segment between the two.

In classic Star Trek style, we encounter the Aztec god Quetzalcoatl (Quetzecoatl?) attempting to bring enlightenment to the Klingons. Lt. Buchert must have jinxed us when he mentioned the absence of any angry gods last mission.

The first half of the mission consists of eight rooms, which is technically a record so far, but some rooms are little more than scenic pathways. It’s also very linear compared to other missions. There’s only one case where you might have a reason to backtrack at all, and often you’re prevented from going back to previous rooms entirely.

This mission has some rather pretty screens.

Mission oddities

There is a case where you can scan Lt. Stragey (the redshirt) while he’s dead, and someone who is… clearly not McCoy, say “He’s dead, Jim”. Was DeForest Kelley sick that day? Well, he says the same line in other places, so I substituted one of those in.

There are at least two ways to get an infinitely high score in this mission. The first way is to repeatedly try to grab a snake in the second room. Whether you succeed or not, you get a point each time. (Normally the snake retreats into a hole before you can grab it.)

The second way is to repeatedly solve one of the puzzles. I don’t really want to give away any solutions, but there’s a particular action you can do repeatedly on the lake screen. The first time, it wards off a monster, but after that it serves no purpose, despite continuing to give you points.

Unfortunately, based on my limited testing, it looks like your score does cap at 100% in the final report.

Unused stuff & version differences

The devs seemed to have a good sense of humor; in particular, the original floppy version was snarkier in places. If you use a knife on yourself, it says “You won’t break your contract to the network that easily!”

That line was changed later; this particular piece of text changed between the original floppy release, the mac release, and the voiced release. Supporting all 3 will surely be a nightmare.

Also, it turns out that the redshirts are named after the devs, which somehow makes the redshirt deaths seem even funnier.

A personal favourite of mine.

I’ve also encountered the string “***Game Over, Man!***” in the game files multiple times, at least back in the first mission; perhaps it was used before they implemented the “game over” menu properly. Today, I even found a voiced version which seems to be unused, done with all the professionalism of any other line. I wasn’t a fan at first, but this narrator voice is growing on me.

Anyway, there are just two and a half missions to go now. I think I could manage to finish this within GSoC, starship sections and all. I doubt I’ll have enough time to finish Judgment Rites, but perhaps I can get a decent chunk done if space combat doesn’t turn out to be too insane to implement.

GSoC Week 6: Harcourt Fenton Mudd, have you been drinking again?

Mission 4: “Love’s Labor Jeopardized”, is an odd one. You don’t really need to do very much to complete the mission; most of the challenge comes from getting the maximum number of points possible by discovering as much as you can about an alien ship.

There is only one way to die, which involves waiting for 25 minutes with plenty of warnings, and there aren’t even any redshirt deaths! Lt. Buchert must be the luckiest security officer in the crew.

Though, he has to deal with Harry Mudd, so I guess he breaks even. Honestly, the best part about this mission is talking to the crewmembers and getting their reactions to Mudd.

Mission oddities

This mission follows familiar patterns; there are pieces of unused audio, despite clearly having places to fit in. For instance, there was an instance where McCoy and the redshirt had the same line, but the redshirt played McCoy’s voice clip when his textbox came up. That was easily fixed, since his voice clip still exists in the game data.

I also encountered invalid actions, which was a first. For example, there was an action defined for “using a viewscreen on Kirk”. Obviously, that’s supposed to go the other way.

What’s great is that, if the text exists, it’s voice-acted. They were thorough with that, even if the text was unused for one reason or another.

Aside from that, there is one very, very, very obvious bug in this mission. Basically, Mudd goes completely insane after inhaling some alien aromas, and you’re supposed to help him out. (Or you can leave him as-is.)

However, you can just go straight back to the first room, and he’ll still be there, cheerfully bantering with the crew as if nothing happened. Then you can go back to the previous room, and he’s insane again.

I’m still finishing up the mission, but I’ll be sure this gets fixed in ScummVM.

A detour into Mac OS 8

Earlier this week, I took a quick break from mission logic to take a look at the Mac port. Since I was convinced at that point that the mission logic was hand-written assembly, I wanted to see what they did with the different processor architectures.

I spent two days trying to read from almost-dead floppy disks, searching for obscure unmaintained programs to read from a file’s so called “resource fork” (a feature of the mac filesystem), figuring out how to use Mac OS 8, and looking for an appropriate emulator to run it. (The program is called Sheepsaver, it’s pretty swell.)

This was what my Monday evening looked like.

And, what did I find when I finally dumped the files? x86 assembly in the mission logic. Now, I haven’t done any serious reverse-engineering on the main executable file, but since the Macs of that day ran on 68k processors, it’s quite obvious that emulation was going on.

The Amiga was apparently based on the 68k processor as well, so, perhaps this is related to the complaints of sluggishness in the Amiga port that I’ve heard about. That being said, mission logic would take only a very small fraction of the total execution time, so perhaps there are other reasons for the sluggishness. Or perhaps even parts of the engine code are emulated as well. That’s just speculation, though.

A fun side-note: I was running Mac OS 8 when installing this version, which ran on PowerPCs. So, my x86 computer was emulating a PowerPC for MacOS, emulating a 68k for Star Trek, emulating an x86 for the mission logic. Ahh, the circle of life is beautiful.

PS

I was mentioned on Github’s blog in a feature on ScummVM! It’s great to know that people are paying attention. It motivates me to make these posts as interesting as possible.

GSoC Week 5: Star Trek Teaches Chemistry: How to Make Laughing Gas

Mission 3: Love’s Labor Jeopardized. It’s about 90% finished.

The mission starts with a rather ear-grating computer voice. Thank god they got Majel Barrett for the sequel.

That said, this is a neat mission. You’re given information about various chemical compounds that may be useful in the mission, then you need to figure out which ones are important and mix up some ingredients to cure a virus that’s running loose through the station.

Or you can just, you know, inhale some laughing gas instead.

Mission bugs

Last week, I promised there would be bugs in this mission. There’s nothing mission-breaking that I’ve found, though, mostly text stuff.

The most eggregious is a weird textbox I encountered in my casual playthrough. As far as I know, you’ll always encounter this if you take long enough during the mission.

I also encountered this following bug while writing this blog post. This is part of the 10% of the mission I haven’t rewritten yet, though, so I can’t explain what it’s about.

Aside from that, there are a couple of cases where voice acting doesn’t play when it should. And, if you look at Dr. Marcus when she’s tied up, it plays the wrong file entirely; only narrating the first half of the textbox. There was an unused audio file that narrated the entire textbox, so I replaced it with that.

The one thing that might be considered a bug in the mission mechanics, is the way you can give water to the Romulans. Apparently you can get a point in your mission score for doing that. But, sometimes, if they’re unconscious, nothing happens. You lose the water, you don’t get any points, and not even a textbox is shown. It’s honestly kind of odd. I’m still debating what to do about that; for now I’ve made it so you can’t give water to them while they’re unconscious.

Other oddities

There are a number of cases where a single line is read multiple times by the actors, simply because the same textbox is shown in multiple different rooms. For example, if you scan the air with the medical tricorder, McCoy says the exact same line, but with a different voice clip depending on the room. I can just imagine the cast complaining about why they have to record the same voice clip three times.

Anyway, this mission should be completable in ScummVM within the next day or two. Next week will feature the return of Harry Mudd in one of this game’s weirder missions.

GSoC Week 4: Dammit Jim, I’m a doctor, not a QA tester!

Star Trek’s second mission, “Hijacked”, is finished. It’s very short, only consisting of 4 rooms. Despite this, the devs didn’t fail to insert a number of bugs into the mission, most of them in the final room.

Let’s start simple: if you talk to McCoy at a specific time, he has no text.

However, there is an audio file which fits perfectly for this situation. So, I whipped up some corresponding text to go along with it, and inserted it appropriately. Honestly, how could I let DeForest Kelley’s wonderfully snarky voice acting go to waste?

It’s not the only voice clip that’s unused, either. There are a surprising number of cases where they clearly intended for some dialogue to be said, but there’s problems in the implementation causing it to not occur; for example, when you try to shoot the Masada crewman, he’s supposed to say something, but due to a bug(?), he didn’t in the original.

There’s also an oversight with the mission scoring system. You’re supposed to combine some inventory items together to progress through the mission, but you only get points for this if you do it in a specific room! This is the consequence of each room having entirely separate codebases; the code needed to be copied for each room, and clearly, they must have forgotten that the code was duplicated when they made some changes to it.

Lastly, the final room is pretty buggy. Don’t read any further if you want to avoid spoilers.

So, there are three ways to end the mission; either you shoot the Elasi, they surrender, or they attempt to deorbit the ship. But… these aren’t mutually exclusive. In fact, all three can happen, and the devs clearly didn’t think this through properly.

Consider scenario #1: You shoot the Elasi. This aggros them, and they immediately kill your redshirt, followed by Kirk. However, you can still talk to the Elasi if you’re fast enough. If you convince them to surrender… they don’t actually surrender, despite saying so, they just keep killing you. If they deorbit the ship, you can call Sulu, stabilize the orbit, and beam out, WHILE THEY’RE STILL SHOOTING YOU.

Scenario #2: You talk to the Elasi, and you choose the worst option, causing them to both deorbit the ship and start shooting you. This one’s funny, because there’s no way to finish the mission in a way that makes sense. You can do one of two things:

Scenario #2a: Shoot the Elasi. This is sensible since you only have a few seconds before they kill you. After this, the mission is “successful”, even though you never save the Masada from deorbiting. I guess the security team that beams over dies when the ship goes down…

Scenario #2b: Call Sulu to prevent the ship from deorbiting. This results in the same issue as scenario #1.

It’s a mess. I’ve tried to fix things as best I can, by requiring that if the ship is being deorbited, shooting the elasi doesn’t end the mission, and vice-versa; saving the ship from deorbiting doesn’t end the mission if the Elasi are still a threat. Also, if the Elasi say they surrender, they actually do surrender now.

There are many more minor bugs, such as the Elasi guards freezing up if you shoot one of them at a specific time; but I’d be here all day if I listed them all. I’ve put down “BUGFIX” tags in the source code whenever something like this comes up. I’ve no doubt I’ll encounter more while working on the next mission.

GSoC Week 3: R̶e̶b̶e̶l̶ Elasi Scum

The main task of this last week was to implement saving. This had a surprising amount of nuance to it, since I need to provide ScummVM with various metadata, including a thumbnail of the savefile, the savegame description, etc… fortunately it wasn’t too difficult to use other engines as templates on how to accomplish this. I’m quite glad I found out about ScummVM’s built-in serializer before starting on this, as it reduces the amount of redundant code by a lot (saving and loading is done with the same code).

The main issue I encountered, was a portability concern. I can’t simply memcpy a data structure to save it, since there are no guarantees about struct packing, or endianness, etc… so, I need to specify each individual variable that goes into the savefile. This is a huge pain to do, since each individual room has its own set of variables, and I’m still figuring out what they are. I’ve mostly held off on saving room-specific variables for now. Hopefully I’ll find a better solution, but obviously I must eventually solve this for saves to work properly.

In the meantime, the next mission is coming along, in which Kirk faces off against the Elasi – some kind of “rebel alliance”, except, they’re the bad guys.

GSoC Week 2: Everyone Gets Vaporized

My work this week has been the repetitive and somewhat tedious task of rewriting the code for Mission 1. It did take a while, but hardly the entire month my original schedule called for! My original schedule didn’t anticipate that I would finish the entire game within GSoC, but at this rate, it seems quite possible.

Anyway, this week’s work speaks for itself: the first mission is fully playable in ScummVM. There are just a handful of animation errors and default interactions missing (ie. using a tricorder on something when no “action” is defined for that).

Something I struggled with this week was text handling, keeping in mind that I’ll eventually want to port the French and German versions to scummvm as well. Before, that would have been extremely difficult due to the way I was hardcoding text into the code, so I switched to a system where each piece of text is referenced by a constant integer value; this will make it easy to support other languages later. And, as it turns out, almost every piece of text already has a unique “name” in the form of the corresponding audio filename, so this system was actually pretty easy to implement.

Instead of going straight to mission 2 next, I’ll be taking a break from mission-specific logic by looking into the saving system next. It’s sorely needed to make testing easier.