Thursday, 24 October 2024

"Stellar Odyssey" by Nick Marentes (1982)-- A Conversion Odyssey

I was watching The Coco Nation live stream stream show the other day, when somehow the conversation got on to Nick Marentes' first game "Stellar Odyssey" I was intrigued to hear that the game was mostly BASIC. I think Nick mentioned that it was a hard game to get running on emulators because it was designed in the form of three tape files. The first was a loader program that poked M/L language routines into memory. The the main program was then loaded and run.  Finally a save game file was loaded to get you off and running, either from the initial starting point, or some other point that had been saved while playing. This system was used to save memory on the limited 16K of space of the early TRS-80 model 1 computer. Nick noted that it was unlikely people would bother to give the game a spin these days because of these complexities.  I think Curtis suggested that it might be nice if someone could convert it to Coco.

I immediately typed into the chat to volunteer, since this is precisely the kind of program I love to convert. The program sounded intriguing. From the description Nick provided and subsequent investigation, I learned that the game uniquely combines elements of the text adventure genre, the RPG genre, rogue-likes, graphic adventures, and arcade animation. I searched online to see if I could find a copy on one of the TRS-80 sites I know, but I realized it wasn't listed in any of the usual places. So I asked in the chat if Nick would share his source code.  He generously agreed, so I sent him and email and he responded with the three files.

My first challenge was to try and load the files into my Model 1 emulator. For some reason this would not work. In the course of trying to figure out why, two things happened.  I somehow ruined my Model 1 ROM that I was using with the emulator, so that it stopped working. The second thing was I re-discovered forgotten knowledge I had once had about the different speeds that cassette files could be saved and loaded with on the TRS-80.  I think Nick's files were probably saved using the low speed setting and that I needed to type "L" at the Cass? prompt that TRS-80 Model 1s with Extended BASIC start up with.  But by this point, this knowledge didn't matter because my emulator was fried, and I had to go looking for either a new ROM or a new emulator. 

I came across an interesting online TRS-80 emulator that had some nice file handling utilities built in.  Using it I was at least able to view the files and extract the ASCII text of the main BASIC program file. Once I had that working I could begin examining the code. I couldn't run the whole program though because the emulator would only allow one file at a time to be drag and dropped on it. So I couldn't load Nick's loader program, and then have it load the main program, and then the game file to start the game. But not being able to run the program was not my chief worry. By just examining the code of the main program I was starting to suspect that the loader program might not just contain M/L routines to handle sound generation (as I had hoped), but that might also handle drawing the walls of the maze-like ship that you explore. I could tell that the USR calls spread throughout the main program were mostly of a type USR(0) to USR(255), which appeared from the BASIC routines to be doing something roughly equivalent to SOUND command-like stuff. Swapping the USRs for many such instances created the typical kinds of effects I also use in games using SOUND, so part of the mystery of the M/L USR calls was solved.

But there were some calls with values other than 0-255 (they appeared to be memory addresses). These were usually preceded by or connected with POKE commands to specific areas of memory. Some of the USR (0-255) type calls also had POKEs connected with them, but I guessed that these were simply fiddling with the pitch or length of the sounds being produced for certain sound effects.  But the ones relating to memory addresses were, I guessed, communicating info about rooms, so that a specific one could be rendered. There were a lot of rooms (86), and I began to despair that I would be able to port the game.

Then Canadian Thanksgiving happend and my software engineer son Charlie came home from Halifax.  With his help I was able to view the bits of integer DATA from the loader program. I was able to guess by the length of that data that each room was composed by 5 single bytes, with the bits of each byte being used to render the 7 horizontal spaces of the 5 rows of each room. Then my son was able to craft an elegant algorithm in BASIC (with his old man's help with the archaic language) that would render the byte numbers into a stream of zeros and ones to print 3X2 blue blocks or black semi-graphic spaces to create the rooms on screen. Then we just had to extract the data from the loader program and put it into my slowly evolving Micro Color BASIC version of Nick's main program.

At this point we descended into Unicode Hell. I asked Charlie to create a Javascript routine to take the bytes from the loader program turn them into characters and break them into the 5 character strings for each room. First, the Javascript compiler wouldn't recognize some of the bytes generated from the code as ASCII because it insisted on translating some (sometimes all) of them from UTF-8 to two byte UTF-16 codes.  It was a monumental struggle informing ourselves and navigating these processes that occur behind the scenes in the Windows environment. So many landmines tripped over. Just switching between Notepad (Charlie's preferred editor) and Wordpad (mine), caused what felt like endless confusion. There was much hair pulling and debate about what was going on, but we finally figured it out and got what appeared to be a clean stream of 5 byte strings to render each of the 86 rooms. I say "appeared" because we seemed to have a few extra bytes. Two to be exact.

Then we descended into Micro Color BASIC text handling Hell. The BASIC Interpreter in the MC-10 and the Coco doesn't like dealing with characters below 32. And even some characters above that range have problems.  ASCII 32, for example, is always being hot swapped for a light green character 96 in the printable character set.  Others can't be typed in from the keyboard and are annihilated by the interpreter when they are "quick-typed" in.  Some of the graphic characters above 128, cannot be displayed in Windows editors and "disappear" when working with them. This meant we couldn't just easily create plain text strings to economically store the room DATA. But by translating that DATA into raw list of integers, and then rendering those as rooms, we at least were able to create a utility (ROOMS) to examine the maze. Most rooms looked okay, especially early in the list. But some of the later rooms looked messed up and didn't link up with other rooms properly. Those "two extra bytes" were clearly affecting things at certain points. But the real problem was that using raw numbers in DATA statements would require too much memory to work with Nick's main program. It was fine for a utility to just examine the map, but not for the game. We had to translate the data into CHR$ commands for some of the problematic bytes concatenated with strings of regular characters. Once again my son's Javascript (with another slight foray in Unicode Hell) was able to automate the process.

Then my son went home, and left me to figure out the extra two byte problem. This simply required using the evolving ROOM utility to explore the map and make guesses where the list of bytes had become misaligned by the rogue bytes. In the end there were not just two extra bytes, but also a few incorrect bytes.  As I said, the space character does not play nicely in the way the Color BASIC Interpreter handles it. So there were two rooms that I had to find close binary approximations to ASCII code 32. I think room 48 was one of these.  In the end I was able to get all the rooms of the maze to properly connect up as I believe they did in Nick's original.

In the course of working on the rooms, and in examining and working on the main game code, I was able to begin to create a solution map of the evolving MC-10 version of the game.  I slowly was figuring out the puzzles and the clues (variables used in the save data were a great help here). I was creating lower res Colour equivalents (64X32) for Nick's higher res (128X48) semi-graphic characters and animations. I like to think that in making conversions from TRS-80 to MC-10 there is an acceptable trade off between added colour versus lost resolution. But I don't know if Nick would agree.  But I think I've done the best that I can in rendering the game elements in a MC6847 environment. But I wish some folks would take the game for a spin, and offer constructive criticism to help improve it if necessary.

The process of translating the screen took more trial and error than I normally have to do for TRS-80 to MC-10 conversions, because the lower resolution of the MC-10 (32 versus 48 in the vertical) forced the title block at the top to have to be 3 lines, instead of two, to properly render readable letters of the game title. This meant everything on screen was pushed down by 1 row.  So instead of just taking all PRINT@s and dividing them by 2, I actually had to calculate the location of each PRINT@ and screen POKE and PEEK command. This would have been necessary eventually anyway, because I soon realized the game would just barely fit into the 20K of memory of an expanded MC-10. In other words, no simply using a divide by 2 kludge. Of course, in the emulator I could just turn on extra memory until I could get the program properly "slimmed down."

As I played the game I began to suspect that Nick's expectation of player expertise and persistence may have been set just a bit too high. As a programmer, I have sometimes come to have overly high expectation of players. You live with a program so intimately as a coder that you know all its nuances and secrets. This can incline you to make a game more and more challenging so that it can maintain a challenge for you.  As I played the game it appeared to me that the aliens, who begin to attack you above room 14 (there are two other main levels/areas of the map-- see above), come so often and with such intensity that I couldn't actually get through the map to the end without saving the game at the end of every screen to preserve my health and life. I had to resort to programmer tricks so I could test features, such as breaking out of the game, modifying the room number variable, entering "CONT" and zapping myself immediately somewhere I wanted to go.

So, I added difficulty level selection at the start of the game and nerfed the RNDs used for combat elements of the game. I have now played though on level 1, but if you choose level 3, you will be playing on an unadulterated Marentes level of play. The final win screen now also reports which level you are playing at. I also added to the clue provided by Nick (he has at least one clue for every puzzle) for solving the final puzzle. It makes it a little more apparent what you must do.  Otherwise you will likely have to die several times and restore from a saved game before you can figure out the final puzzle. Finding that clue is pretty tough and it will still require some careful interpretation. I also added a clue to another puzzle, to help you find a needed object a little more easily. I really would like some folks to try playing the game on the tougher levels (and without my map above) and to hear some feedback about whether I have nerfed the game too much.

The old clue.

I also changed the game save and load features. The original requires you to load a game at the start of each launch of the program. The standard "gamefile" just stores the ordinary starting details. Then you could just save new files, to start at different points in your progression through the game and load those instead. I chose to hard code the starting details and begin the game with those every time.  Then, if you want to save or load you simply choose "Q" to go to a file menu for these actions.  You can also restart the game from that menu, hence the "Q" for "quit" key choice.  You have to hold the Q down slightly to launch this menu, as it uses a different method (PEEKing the keyboard roll-over table)  rather than INKEY$ used for commands entry. This is a good thing, because it helps prevents triggering of the menu if you just brush the key. I also changed a few other keys. I switched the "V" key command (Verbs) to what I feel is a more standard "H" for help screen command. Since the normal MC-10 right arrow "S" key is used for the "Sprint" command, I used the < > keys (i.e. the comma and period) for TURN LEFT and TURN right commands. The other commands should be the same as the original and are listed by the "H" command. I should note that on Nick's web page it mentions one of the commands being "Attack" conceivably using the "A" key, but the command I found in his sources code was "F" for Fire.

I hope that I can take this completed program and convert it to Coco BASIC, but realistically, I don't think this will happen until Christmas. Once again, I had Charlie try to create a Javascript program to consistently convert all the raw semigraphic-4 characters embedded in strings into CHR$ and STRING$ commands as appropriate. But once again we descended into Unicode Hell, with some characters just not being sensed or sensed correctly. It is simply too daunting a task to think of doing this manually. But once we figure the graphic character conversion issue out, then I can simply manually translate the lines which the Color computer requires spaces to be inserted before command keywords, that the MC-10 interpreter doesn't have trouble with:

FORA=B_TOC_STEP

IFA_ORB_THEN

IFA_ANDB_THEN

I will also have to switch the CLOAD*array commands and CSAVE*array commands to Coco equivalent disk load and save routines. I had to convert Nick's routine, which saves 16 numeric items, and then a single string containing hashed information about items carried and/or the rooms in which they are currently located.  I convert that string into a bunch of integers, which I simply add to the numeric array values that I load and save using the special CLOAD* and CSAVE* command of the MC-10 (it's really convenient). I must say, the hashing routines created by Nick are amazing examples of memory saving technique, especially when one considers he was only in high school at the time. The whole program, in fact is a master class of memory parsimonious BASIC programming. And it's still elegant and readable to boot. My hat goes off to Nick. He's a national treasure of the Coco nation.

I think Nick might have had some M/L special effects as part of the final Win Game scene, which I have converted to flashing the screen to the alternate yellow/red character screen colours of the MC6847. But having never got the original game running, the special effects in the game are just my best guesses.

The Internet Archive is currently down from a cyber attack, but when it is back up and running, Maybe I'll put the Coco version of the game up there, unless Nick wants to pull the distribution in-house. But in the mean time, for testing purposes, the MC-10 version can be played for the next little while at my Gamejolt page:

https://gamejolt.com/games/jgmc-10games/339292

Just hit the big green "Play" button then select the "Text Adventures Requiring Save/Load" menu option.  Use the "Cassette" menu of the online emulator to select STLODSSY and type RUN and hit Enter in the main emulator screen. You should also be able to save and load the GAMEFILE, using the the buttons under the main screen.  Comments welcome.

ADDENDUM:

Nick contacted me, and helped me figure out the nuances of Discord so that we could have a chat about his game. He had some suggestions for how to make the screen more aesthetically pleasing and clearer. I've started to implement his suggestions, which really streamline things nicely. Nick thought the big title could go and be replaced by a simpler text title, but I'm kind of attached to his swoopy graphic title.  But I did centre it a bit better.

I've made some headway on the Coco conversion too! Should be out in the next couple of weeks.


Coco version finally completed! Here is the game playing on VCC


Edits up (Nov 8, 2024). Tweaked room descriptions. Added "You are" back to the beginning of the descriptions. And altered the hint I embedded in one of the room descriptions to help in locating a needed item.