Saturday, January 30, 2016

RC2016/01 Wrap-Up

Here we are at the end of RC2016/01, and what have we got? Well in my case I have a port of Xmas Rush for the TRS-80 MC-10 -- very exciting stuff! At the end of my last post on the topic, there was still some timer stuff to handle and some "odds and ends". So, let's see how that went...


Pause To Experiment

Early on I had thought that precision timing might not really be necessary, that perhaps the video glitches would be spread so thin that it would hardly be noticeable. Later, someone else made a similar suggestion. So I conducted an experiment that changed the game's time base to just a bit more than the time required for a single frame of video. This did have the predicted effect of spreading the video glitches around so as to make them less objectionable, but they were still both noticeable and constantly recurring. While I did not pursue any algorithmic changes to the drawing routines that might have made this even less objectionable, the experiment cemented my belief that stable timing synchronized with the video hardware remained a worthwhile pursuit.


Help From Afar!

I implemented the timing synchronization by enlisting help from the user to position a marker off-screen. This marker represented the time the video hardware was not actively drawing the screen, and moving it off-screen equated to synchronizing the program to do its animation while the hardware was not actively drawing. This solution is quite effective, and I don't think it is objectionable for the user to do this once when starting the game.

The timing I am seeing here at home is the roughly 60Hz timing of NTSC video. Of course, in much of the world the video standards are timed for 50 Hz vertical refresh rates. By adding a user choice between 50Hz and 60Hz and a corresponding variable used for timer setting, I was able to accommodate that situation. However, I don't have an MC-10 that uses PAL video or one of the French MC-10 clones, the Matra Alice. Luckily I was able to reach out for testing help on the Yahoo MC-10 group. There I found confirmation that my 50Hz timer synchronization was working too.

One Last Bug...

Along with that testing came a report that in some cases the snowmen would overlap and disappear! Worse, even in this vanished state they could still capture the player, causing him to lose...what was going on?

The moving objects in Xmas Rush are drawn using an XOR operation against the existing screen data.  The primary reason for this is to highlight the case when a snowman captures the player, but a side effect is that when two snowmen exactly overlap then they cancel each other out on the screen and seemingly disappear. In order to counteract that I have a series of tests in the snowmen movement routines that were intended to prevent an exact overlap. However, those test were clearly not working...

The original 6809 code for the snowman position tests used a CMPD instruction to do a 16-bit comparison against the D register (i.e. the A register and B register together). The 6803 lacks such an instruction, so in the conversion process I compared 8-bits against A and the other 8-bits against B. This changed the flow just enough that I confused myself, and I ended-up checking each snowman's position against the position of only one other snowman, allowing overlaps to occur with the other two! Once I found that problem it was easy to correct, and now snowmen should generally be unable to eclipse one another.

That's A Wrap

So anyway, that's about it for Xmas Rush on the MC-10. I'll get the MC-10 binaries added to the Xmas Rush web page and then I'll call it a month. I am really happy to have finally taken the time to learn more about the MC-10 and to put it to a decent use, and I hope you have enjoyed monitoring my progress along the way. I will probably have Xmas Rush on display at the 25th annual "Last" Chicago CoCoFEST! this April, if you want to stop and give it a go.

Until next time, I hope you will find your own excuse to get out your retro computing gear and make it do something fun, useful, or otherwise enjoyable. And as always, I hope you will stay tuned!

Saturday, January 23, 2016

Checking My List

Another week down and roughly one more left to go in the Retrochallenge RC2016/01 event. I got off to a bit of a slow start this month, but since then things have progressed well. It looks like things are shaping-up nicely for my port of Xmas Rush to the TRS-80 MC-10!


Time Is On My Side

One of my main concerns with this port has been the lack of a vertical sync signal available to the CPU on the MC-10. A direct port of the drawing algorithms from the CoCo version of Xmas Rush resulted in objects sometimes disappearing completely within certain vertical ranges of the screen. I considered altering the basic drawing algorithms in hopes of minimizing the screen problems, but that really seemed like a "band aid" solution at best.

The MC-10's Motorola 6803 CPU does have a hardware timer circuit, so precision timing is possible. The problem remains as to where (actually when) to anchor the timer settings. Since we know how long the screen is actively drawing and how long each frame lasts, we can derive the anchor point by interacting with the user. The timer is used to divide the screen into two periods, representing the active and inactive drawing times. A visual indicator is used to indicate the temporal position of the inactive period, and the user is asked to provide input that is used to relocate the inactive period until it's visual indicator is not visible. Once that temporal anchor is established, all that is required is to never miss a frame timer expiration... :-)


Watch Your Step

Xmas Rush uses a bitwise map to represent the scrubby trees that comprise the playfield terrain. At game time, that map is also used to generate a data structure used to detect potential collisions between that terrain and the player and snowmen. Converting the original 6809 code to 6803 code was a bit tricky, since the 6809 code made use of the extra index register available on that CPU. The conversion made a lot more use of the stack, reminding me of a Towers of Hanoi game gone terribly wrong... Anyway, I eventually managed to sort that out and objects were suitably constrained from moving across the tree-filled terrain.

With the player now moving about, it seemed like a good time to introduce the pitter-patter sound used during player motion. The CoCo version used the horizontal sync signal for timing square wave generation, but the MC-10 is as equally unhelpful for horizontal sync as it is for vertical sync. I had hoped that I could do some tricky hardware timer manipulations to use the timer both for the vertial sync emulation and for sound timing, but I couldn't seem to master that feat. Instead, the sound timing is based around cycle-counted loops representing horizontal sync periods. This proved to be satisfactory for all of the sound generation in Xmas Rush.

BTW, the pitter-patter sound is not a normal tone. Each up-down transition of the square wave is governed by the output of a linear feedback shift register (LFSR) used to generate pseudo-random data. In a very real sense, the pitter-patter sound is more of a noise than an actual tone.


Win Or Lose

It is important to be able to tell when the moving objects collide. This causes the player to lose when he collides with one of the snowmen, and it is a prerequisite for a win that the player must seize the evergreen tree. Xmas Rush does not have any special data structure for detecting sprite collisions. With so few sprites, it was easiest just to check each sprite position to see if it overlaps with the player.

A set of flags is used within the game code to indicate which snowmen are active and whether or not the evergreen tree has been seized by the player. These flags are used in the drawing routines to control what is drawn in a given frame. The "seized" flag is also used in coordination with the player's position to detect a "win" condition.


The last, big missing piece was the movement of the snowmen. Since the game loop erases and redraws every sprite during every frame, movement is nearly trivial -- just change the draw location and the object moves! Each of the four snowmen has its own movement strategy and a corresponding routine to implement that strategy. I won't divulge them here, but each strategy is fairly simple, and the snowmen can be manipulated into trapping themselves behind parts of the terrain as they pursue their personal strategy.

Anyway, with moving snowmen the game is largely complete. All that remains is integration of the timer calibration code into the main program, and a few odds and ends. This week should see a successful end to this project...I hope you will stay tuned!

Friday, January 15, 2016

RC2016/01 Half-time Update

Wow, half-way through January already! After a slow start, I now have my Xmas Rush port to the MC-10 well underway. I recorded a few more progress reports throughout the past week -- let's review!


Graphics Mode

The Christmas tree on the title screen is drawn in a "semi-graphics" mode in which the low-resolution graphical glyphs are really just special characters, no different from numerals, punctuation, and letters of the alphabet. These are handy for a number of things, but they are generally not as flexible as the "high-resolution" graphics used for the main part of the game. Fortunately, switching to graphics mode is fairly simple to do.

The 6847 Video Display Generator (VDG) is configured through a collection of logic signals applied to its external pins. These can be wired a number of different ways, and even on the MC-10 some of the configuration pins are actually driven directly by the incoming video data. The rest are connected to a small register on the MC-10 motherboard. That register can be changed by writing to any address between $9000 and $bfff, although $bfff is the conventional address to use. Writing an appropriate bit pattern to this address is all that is required to change the graphics mode.


Coordinate Translation

With graphics mode engaged, we need some way to specify where graphics are displayed on the screen. For simplicity's sake, I designed Xmas Rush to use a simple 32x32 grid for placing objects on the screen. This alignment naturally matches the number of horizontal bytes for each line, avoiding the need for any mask-and-shift operations when writing data to the screen. The X- and Y-coordinate for each object is stored in a two-bye pair that can be easily manipulated using the double-accumulator operations (e.g. LDD, STD, etc) available on the 6803.

There is a bit of math involved in translating a set of coordinates on the 32x32 grid into an address for accessing the framebuffer. Of course, I already had 6809 code to do this on the CoCo. Blindly translating that to 6803 code for the MC-10 quickly provided satisfactory results.



Timing Again

From there, I quickly conquered the task of drawing the playfield. Xmas Rush uses a bitmap to describe the placement of all the bare trees that make-up the playfield. Translating the relevant 6809 code from the CoCo to 6803 code for the MC-10 again proved an easy task, allowing me to begin work on the fundamentals of constructing the game loop.

The CoCo version of Xmas Rush uses a graphics animation technique known as "double buffering". At any give time one buffer is displayed while the other is redrawn for the next frame of animation. Periodically a vertical sync event occurs.  At that time the program changes which buffer is actually displayed, and work shifts to clearing and redrawing the previous buffer. This technique prevents ever displaying a partially drawn frame, and it provides a natural source of "real time" information for pacing the game.


The MC-10 provides no means for the CPU to observe when a vertical sync event happens, but it does provide an internal timing source that can be used for game pacing. My initial attempt to use this timing source as a substitute for the vertical sync event was disappointing, because I was resetting the timer based upon its current value (a moving target) rather than as an offset from the previous setting. A little fix stabilized the timing so at least the game can be paced correctly.

The current timing technique is still prone to showing some weird video effects, depending on the exact timing between the game and what the VDG is doing. I think that a manual, user-driven timing synchronization is possible. Alternatively, maybe just some random resets will be acceptable -- this would be similar to the "reset until this is blue" that was so common on CoCo games that used NTSC "artifact" colors.

In any case, there is still some work to be done adding player movement, snowman AI, and other missing game bits.  This is a good start, but it needs a good finish. Do you want to see how it ends-up? Then you will just have to stay tuned...

Sunday, January 10, 2016

MC-10 Familiarization

Programming retro computers is not rocket science. After all, it wasn't that long ago that teenagers and grade-schoolers regularly produced commercial-quality programs on these very machines! Nevertheless, a new machine always has some new idiosyncrasies and a few tricks to learn to make them useful. The MC-10 is no exception, and much of my time spent with that machine in the past week has been devoted to learning a few such tips and tricks...


Time Well Spent

I like to make use of "real time" sources to control events in my games. Hand-coded loops and cycle counting can be an effective soure of "real time" information, but they are fragile. Small changes in the game code can produce large timing differences than can be difficult to predict and painful to recode again and again. On the CoCo, I often use the vertical and horizontal sync signals as reliable sources of timing information. Unfortunately, the MC-10 makes no provision for accessing either sync source.

Fortunately, the Motorola 6803 CPU in the MC-10 has a little "secret" -- an internal timer! The timer functionality is based on counting elapsed CPU clock pulses, which amounts to a source of "real time" information. Using this timer I was able to replace the hand-coded timing loop in my screen flashing example program, unlocking the ability to accurately time game events.


Key Exercises

Moving along from timing, it should be obvious that a game needs some form of input to indicate what the player wants to do in the game. A joystick would seem like an obvious choice, but the MC-10 has no joystick ports. It does, however, have a keyboard. The MC-10 keyboard employs a reasonably standard switch matrix that the CPU controls by outputing a value at one location and reading back a value from another location. This is similar to how the keyboard is read on the CoCo and on any number of other systems.

Conversely, a game needs some form of output. Graphics are obvious, but a little audio can be a big plus. The MC-10 has no sound chip, and it does not even have the CoCo's DAC. However, it does have a 1-bit digital output for producing audio, similar to the Apple II or the ZX Spectrum. Producing audio on the MC-10 is reasonably simple, particularly with control of the timer. There is even a ROM call available for producing simple tones. One might be surprised at how much is possible with 1-bit audio, but simple tones will be more than enough for porting Xmas Rush.


Practice Porting

So with a few exercises under my belt, it is time to start porting. Since the MC-10 has the same Motorola 6847 video chip as the CoCo and can support all of the video modes used by Xmas Rush, there is practically no need to generate new graphic data for anything. I started by reproducing the "intro" and "tally" screens using the same data used in the CoCo version. I did change some of the text to reflect the use of the MC-10 keyboard rather than the (non-existent) joystick port. Incidentally, the Christmas tree graphic was produced using Simon Jonassen's web-based sgedit utility -- very handy!

Well, that is my little recap of this week's progress. I am pleased with my results so far! The biggest challenge has been figuring-out how to port 6809 code to it's poorer cousin, the 6803. Most of the Xmas Rush graphics data should remain intact, and most algorithms will be virtually the same (albeit written for the register-poor 6803). The biggest problem I forsee right now will be dealing with the single, fixed video buffer on the MC-10. I don't think that problem will be too tough, but there could be problems.  If you want to see how that goes, then you will just have to stay tuned!

Tuesday, January 5, 2016

A Little Prodding Helps!

More than half-way through the first week of RC2016/01, and not surprisingly I am barely getting started. Slow Retrochallenge starts seem to have become a habit for me! Hopefully this competition will at least end better for me than the last one did...


Desktop MC-10

The biggest reason for my sluggish Retrochallenge start is that I was still finishing-up some stuff I started during my extended end-of-the-year break in December. I generally use this yearly ritual to enjoy some retro projects and similar work, and this time was no exception. Along with a few soldering projects and other fun, I used a big portion of my time to straighten-up some of the disaster that is my office/bonus-room/man-cave. This time I even managed to clear-off the top of my desk and to reduce the biggest pile of junk to a somewhat smaller, mostly orderly pile of boxes!

One of the soldering projects from my December break involved installing a composite video output circuit to my MC-10. (These are available from Ed Snider, and are highly recommended to other MC-10 owners!) The newly composite-capable MC-10 pairs nicely with an 8 inch Night Owl LCD monitor on my newly cleaned-off desk. In fact, I have it situated in such a way that the "cassette" interface cable easily reaches my development laptop, allowing me to load code on the MC-10 by simply playing a WAV file on my laptop.

Wake-Up Calls

We are far enough into the Retrochallenge event that I had started to get "how's it going?" inquiries from a few friends. This includes inquiries from CoCo (and MC-10) "demo coder" Simon Jonassen, fellow Retrochallenge competitor Brett Gordon, and even my old Linux colleague Alan Cox. In particular, the latter inquiry proved to be enough to get me moving.

I had no idea that Alan had been working on a project to enable playing the old Scott Adams adventure games on the MC-10. Anyway, Alan suggested using a slightly modernized version of the old Motorola freeware assembler which is maintained for Unix-like systems. He also pointed me at a tool he had written for making cassette images for loading machine code. I had solutions for these problems, but apparently Alan's code (and his interest in my project) was enough to get me off the couch -- thanks, Alan!

In Motion

Back in March of 2014, there was a thread on the MC-10 Yahoo group about getting an ASCII-based animation running on the MC-10 and other 6847-based machines. I had participated in this effort, and had some MC-10 assembly code as my result. As part of getting started with this project, I got that code out and running on the MC-10 on my desk. I also ported the code I had from my earlier Micro Chroma 68 build I did as a Retrochallenge project. I now feel "in the groove" for writing some new code for the MC-10.


Originally, I had envisioned porting a monitor program for loading code over the serial port. However, the rebuild/reload/run cycle with my current arrangement seems fairly quick and is convenient enough to make me question the need for that porting effort. Also, the MC-10 emulator support on Linux is better than I had realized, including both MAME/MESS support and a surprisingly good Javascript-based emulator at mc-10.com.  The latter even includes the ability to load cassette images from local storage directly into emulator memory -- fast and easy! So, I may just live with what I have and save the serial-port stuff for another day...maybe...

Anyway, I suppose this post marks that I am officially underway with the RC2016/01 competition.  If you want to see where I end-up, then I guess you will just have to stay tuned...