Last week on the CoCo discord assembly channel Simon Jonassen posted some code to draw and animate 128 pixels that drew a radar or fan blade type animation on the CoCo 3 screen using some very optimized 6809 assembly code. I was intrigued by his code and the idea of how he was drawing and erasing the pixels. I came up with another way of doing it. He suggested the only way to know if it will work is by actually doing it. “The proof is in the pudding.” I needed a little break from Robotron anyways… While chatting a little about this with Simon he mentioned how cool it would be to use this effect to draw a 3D face. I’m an old 3D modelling guy who’s been modelling on computers since I got my Amiga 500 back in the late 80’s so once Simon suggested this all kinds of ideas popped into my head. All I needed was a way to get the 3D point info from 3D objects and do a little math with the numbers so they show up with some depth on the CoCo 3 screen and animate them.
I used blender’s animation tool and took a 3D object (in this case the Death Star) and did a 360 degree animation over 55 frames. I was able to write a tiny script to capture the output of the rotated object for each frame and export each frame to a file. I then wrote a program to get the vertices from each file and convert them into some data the CoCo 3 can display.
I start by preprocessing the data (which Simon also does with his program) by copying the background image of each pixel to be drawn on screen into a data table which holds the original value of the pixel from the previous frame along with the location to be drawn and also generate the new pixel for the current frame to draw. The table entries end up in a format that can be quickly pulled off the user stack as:
PULU A,B,X,Y where A is the original (background) value of the previous frame. B is the value of the new pixel to be drawn on the current frame. X is the screen address of the pixel from the previous dot and Y is the screen address of the pixel for the current frame. All that’s needed is to STA ,X and the old pixel from the previous frame is erased and a STB ,Y to draw the new pixel for the current frame. Here’s the small main loop of code that does the magic restore a pixel and draw a new one in 27 CPU cycles:
LDU #$C000 * Position U at the start of the block ! PULU D,X,Y * A = byte to use to put back previous frame to normal @ X * B = new coloured Dot to use on the current frame @ Y STA ,X * Erase old coloured pixel from previous frame on screen STB ,Y * Display new pixel CMPU #$C000+NumberOfPoints*6-18 * Have we gone through all the pixels? BNE < * Keep looping until we've done them all
I threw together a little demo video to show the code in action. See the video here:
Pulling the data off the user stack let’s the CoCo 3 erase 727 pixels and draw another 727 pixels each frame and I’d say just under 60% CPU time per 60 hz frame. The blue colour at the top and sides of the frame is CPU timing info. It’s another cool thing I learned from Simon this week. Apparently this technique has been used since the 80’s but it’s new to me.
The way it works is you set the colour of the border to anything you like, in my example video I used blue for the border. Right at the start of your drawing routine you set the border colour and as soon as your drawing routine is done you turn off the border colour. What you get is the colour down the screen. The further down it goes the more time it took to draw your screen.
Just before you start drawing to the screen you use this code:
LDA #%00001111 * xxRGBrgb - light blue colour STA $FF9A * Setup Border Colour (Speed check)
At the end of your screen drawing code you use this code:
CLRA STA $FF9A * Clear Border colour (Speed Check)
I think this is a pretty cool trick. Thanks Simon for sharing your code and ideas with the CoCo community to help push this retro computer to new limits.