|A port of Canabalt, the popular one-button jump'n'run, was an interesting diversion|
But Prince of Persia was still at the back of my mind, mostly because it's such a great project and I got so far already. I still intended to finish it some day, but I didn't have the energy and most of all, I couldn't see the light at the end of the tunnel. I had no plan how to continue.
I wanted to release Canabalt in March of 2011, but as it turned out, I had to wait a long time for somebody to do the music for the game. In April I still hadn't received it, so I kinda became bored with waiting and my thoughts wandered off.
Before long I found myself thinking about Prince of Persia again. I had the idea to look into C64 cartridge technology to decide if that would be a feasible route to go. I only had a very minimal idea of how some of the advanced cartridges with bank-switching logic (the ones used by Ocean and System 3) worked in detail. I started investigating and in my head I began to rearrange the memory layout of my existing code base.
Which things can I move into the cartridge ROM? Which things have to stay in RAM? Where's the best place to put graphics data? How much work would it be to rewrite my existing REU-based code to get this up and running?
I was quite aware that those cartridges offered a unique possibility. Not only would I be able to move all the big animation data into ROM, but I could also have code there and run it from ROM. This meant it would be possible to free up even more RAM, which is something I needed to fit in all the parts that I hadn't touched yet. Guards and fighting logic, among other things.
But most of all I was hoping that it would allow me to fit two full frame buffers into memory, to get rid of all the ugly redrawing glitches.
So off I went, tearing my old code apart and rearranging it. I initially planned to use an Ocean cartridge but quickly found some inconsistencies in VICE's emulation of that type of cartridge, which meant that my code worked in VICE but didn't work on real hardware. I decided to continue working within VICE and got it up and running in a few days, after which I made a little video capture to show off the double-buffered drawing code.
Now I was finally able to add new features. I added Steve's player sprites and did the status display on the bottom. Things started to become easy again.
Getting annoyed by Ocean cartridge limitations I decided to switch to EasyFlash. It was a clean, well documented standard, with excellent support in VICE. I was amazed by enthusi's conversions of Maniac Mansion and Zak McKracken and I liked the fact that the cartridge could be flashed using just a C64, eliminating the need for dodgy Windows software. Also the prize was affordable, so I ordered a pre-built cartridge and it arrived at the beginning of May. I was very excited that I could finally play the cartridge-based build on real hardware so I made a little movie.
I still had a good chunk of work ahead of me. The most pressing issue now was to get the guards in, and to do a serious amount of performance optimizations.
To help with the first I was lucky that Steve had already released his conversions of those animation frames. So I now had to figure out which part of the code was dealing with the second character.
The basic idea of the game engine is that most of it can deal with either the Prince or a guard. The routines use the CharData structures, so the same animation code is used to animate them both. That gave me a hint that I should have almost all of the code already in place.
I had to do a bit of cleaning up and structure it more like the original. The low-level functions for executing the sequence and looking up frame definitions were shared. The code calling those was split up into two parts: updateKidAnimation and updateShadAnimation.
The first of the two loads KidData into CharData and ShadData into OppData using loadKidAndShad. It then runs the input control code (updateControlAndCheckForDeath), parses the sequence table (animChar), applies acceleration and velocity to the character, then updates the position. Afterwards it does collision detection and resolution.
The other function, updateShadAnimation uses loadShadAndKid to load ShadData into CharData and KidData into OppData, but otherwise does many of the same things. It obviously doesn't run the input code but instead it checks the type of opponent and then runs updateOpponent which handles hard-wired behaviors of mouse, skeleton and shadow man and generic sword fighting movement for guards (updateNormalGuardImpl). It then goes through much of the same code as updateKidAnimation to animate the character and update its position.
Since the guards only have a small subset of animation frames compared to the Prince, they also only have a smaller frame def list. To deal with this, readFrameDef calls a routine which I called overrideFrameDefListForCharacter. It checks CharID and then reads from the alternative frame def list via indexIntoGuardFrameDefList.
After updateCharacters is done with dealing with the Kid and the Shad separately it handles common code needed for fighting (checkIfStabbingOrBlocking, checkIfCharacterIsHit, checkIfStabbingOpponent) before updating the strength of both characters. Now all the state variables of the characters are final and the game is ready to update the screen.
Having made many mistakes in reverse engineering all of this code at first, I was quite happy to finally see a second animated character on the screen. Initially the fighting code didn't quite work, but that also came together after a few days. I had reached the point now where I had to move some of the code to ROM, and the guard AI logic was the prime candidate for that. So I still had room to grow the game.
|The skeleton is just a normal guard that can't be killed|
Within a month of rebooting the project, I had made a lot of progress and was confident that I could finish this game. But because I was unsure about the remaining parts I still expected it to take another year. The requirements for cutscenes and title screen scared me a bit. I had no idea how much work that would be. Also I had no music or sound effects, no final background graphics and performance was still abysmal. The latter now became a real problem. I had to tackle that one first. But I was just about to leave for vacation to Barcelona. Would that be a problem or a blessing? Find out in the next part.