Years ago, I used to play a game for the Nintendo Entertainment System called Star Voyager. The basic premise is simple: you're a pilot of a space fighter, and you need to defeat an armada of aliens who are bent on destroying you and your space station, simply because they are mean.
I wasn't very good at it, but there was a lot to it that kept me coming back to play it again over the years. You could dock at space stations and repair and refuel your spaceship. You could land on the eight planets that actually orbit the center of the galaxy. One of these eight contains an upgraded engine, and one contains upgraded weapons -- both of which feel like necessities when fighting enemies that are very difficult. The euphoric feeling of destroying an alien mothership aside, there were other things to it: the exploration, unknown secrets, nagging questions such as, "How do you escape from a black hole? Can you even do it?" made me keep coming back to try something new. (And yes, apparently you can -- but that isn't what we're discussing today!)
The game itself is notoriously difficult. Even with Game Genie cheats, and your shields up, your ship takes damage from the aliens fairly easily, especially if you have the tendency to fly in predictable patterns. Many people have given up on the game as a relic that was too difficult in the 90's without the manual and without something that gives you a significant edge.
RESET Subroutine
Well, today I think I found the ultimate advantage. While digging into the game with a debugger running, I came across an interesting and noteworthy phenomenon in the code: the game was purposely leaving three bytes uninitialized during a reset -- $07FD-$07FF. Not only that, but two of these values were being read uninitialized and compared against "magic numbers."
This made me think the game was purposely testing memory to distinguish between a "warm reset" where a player would press the Reset button, and a "cold reset" where a player would turn the console on fresh. As it turns out, not only was this going on, but the game was tracking the amount of resets and storing that number in $07FD.
But why?
Conditions for the Dev Secret
The game considers the first time you power on the system with the game as reset one. It was looking specifically for reset number six. If it was in fact the sixth reset, then it would perform an AND against two values in zero page. If the result of that wasn't zero, then it would initialize another value in zero page to zero.
It actually sounds convoluted if you don't know what the values are that are being compared. It took me a little bit of time to figure out what exactly the variables being AND'ed represented. Once I did, however, it became abundantly clear what the game was looking for.
One of these variables was the 2nd player's controller input. Interesting. Another was an entry within a table of possible input values corresponding to A, B, Select, Start, Up, Down, Left, and Right. Also interesting.
The game was checking to see if the following conditions were met:
- You had reset the console 5 times since the time you originally turned it on with the game loaded.
- You were holding Select on Player Two's controller when the game was loading you into the cockpit.
If these conditions were met, then address $9E, which I dubbed MysteryValue, would be set to zero. If these conditions were not met, then MysteryValue would have its previously-set value of nine.
Trying It Out
Instead of hooking up a second controller, I instead used the debugger to make the above conditions true, right when they needed to be.
And nothing seemed to happen.
I checked the map, and I didn't notice anything different.
I exited the map. A little bit of patience, and soon I got a transmission. The game began to inform me that I had, in fact, already won, despite all of the enemies still being visible on the map.
MysteryValue seems to be how many enemies you have left to destroy before victory. By meeting these conditions, we short-circuited the need to destroy them. A better name for the variable might be EnemiesRemaining.
Why is this here?
In my humble opinion, I think this was a trick way for the devs to test the part of the game after you won. All they had to do was load the game, press reset 5 times, hold down Select on the 2nd controller, and then dock with the space station right next to them. Easy testing.
Duplicate with Game Genie Code
We can write our own Game Genie code to set this variable to 0. (If you want to try to write your own codes, there are web sites that can do the bitwise math for you.) Let's look at the relevant section of code where the game initializes $9E (EnemiesRemaining) to nine during a normal run.
Through the Game Genie, we can change one byte per code. The value of nine is written at address $D546: STX EnemiesRemaining. The problem is that the value of nine is achieved by first performing a LDX #$0A at $D53F and then a DEX at $D545.
This means there's no easy way to load my own value into X. Decrementing X and storing the result is very efficiently performed in three bytes while a LDX opcode would take two bytes just to load an immediate value, and the required STX would take another two.
At the moment when X is being decremented, Y is 0. We can swap STX with STY with a single byte change. Let's try it.
STX with zero page addressing has a value of $86. STY with the same addressing has a value of $84. The Game Genie code to swap out $86 and put $84 in its place at address $D546 is KAKITIVA.
Sure enough, success!
Just start the game, wait for the message congratulating you for winning, and then dock with the station. Enjoy the credits!
Too Easy Now!
Well, yes, fighting no one can be too easy. What shall we do? We can change the condition so that you must fight at least one enemy mothership and her fleet before victory is achieved.
I attempted this by converting the extra DEX to INY. This, coupled with our previous Game Genie code, succeeded in increasing Y to 1, and then storing it into EnemiesRequired. Unfortunately, changing Y seemed to have other side effects. Despite killing all of the enemies entirely across the galaxy, the game wouldn't end.
We need to change EnemiesRequired ($9E) within a span of 3 bytes, without altering registers. Instead, we can have Game Genie overwrite STX EnemiesRequired with INC EnemiesRequired, and leave the previous DEX alone. Since EnemiesRequired is initialized to zero at the reset routine, an increment is guaranteed to bump it up to one.
This approach worked for me, and I achieved victory after destroying one enemy. The Game Genie code is VTKITIVA.
Conclusion
- The developers of Star Voyager included a hidden way of accessing the winning screen.
- Load the game normally.
- Reset the NES five times.
- On the last restart, you need to hold down Select on Controller Two until you're fully loaded in the cockpit.
- Wait for the victory message, and then dock with the space station.
- You can trigger the same win condition with Game Genie code KAKITIVA. There is no need to reset the console nor to use any input on Controller Two.
- With Game Genie code VTKITIVA, you can trigger the win condition after you defeat one enemy mothership and her fighters.







Top comments (0)