On August 21, 1994 I began writing a space invaders game for the Radio Shack TRS-80 Color Computer. The game was written in 6809 assembly language, and ran under the Microware OS-9 operating sytem as opposed to the ROM-based Disk Extended Color BASIC.
It did not initially start out as an OS-9 game. It started out as a NitrOS9 game. NitrOS9 was (and still is) a greatly optimized and enhanced version of the stock OS-9 for the Color Computer. It was initially a set of patches that took advantage of the hidden features of the Hitatchi 6309 chip. Many of us did CPU swaps in our CoCo 3s specifically to be able to run this faster version of OS-9. Years later, NitrOS-9 was backported to run on a stock 6809 and the project continues today with the Ease of Use edition where it comes ready to run and bundled with all kinds of utilities, applications, and games. (I think my game is even on there.)
http://www.lcurtisboyle.com/nitros9/nitros9.html
But I digress.
The reason I chose to write a game was after learning about a new system call that NitrOS9 added. It allowed mapping in graphics screen memory so a program could directly access it — just like from BASIC. With that in mind, I wrote a simple demo that had a peace-sign space ship that could move left and right and fire (multishots!), as well as a scrolling star background.
I believe my game demo source might have been published in The International OS-9 Underground magazine at some point.
As soon as I figure out how to make WordPress allow uploading a .asm source file, I’ll share it here.
But I digress. Again.
Invaders09 Secrets
Version 1.00 was completed on September 24, 1994. It was first sold at the 1994 Atlanta CoCoFest. I don’t remember how many copies the game sold over its lifetime, but I do know it was not enough to retire on. :)
On December 26, 1994, version 1.01 was released. This contained code by Robert Gault that allowed the game to work on machines with more than 512K memory. (Robert was also responsible for code that allowed the game to work on stock OS-9, as well.)
A big update happened on January 29, 1995, when the game was upgraded from a 4-color screen to glorious 16 colors.
1.03 was completed on February 4, 1995 and included bug fixes.
Almost twenty years later, to the day, I did a 1.04 update. The title screen text removed my old P.O. Box from Texas, and replaced it with an e-mail address. I also added the “secret” command line option to the help screen, so it would no longer be secret. There had also been a bug that caused the fonts to sometimes fail to load, which I found and fixed. There were also some bad bits in the graphics I had never noticed (but could see clearly on a modern monitor) which were corrected.
Something old. Something new?
I pulled up this source code today and was looking at it to see what all I’d have to do to convert it to run under Disk Extended Color BASIC. I’d have to learn about keyboard and joystick reading in assembly, as well as how to map in graphics screens. I’d also have to take care of the blips and boops, and create my own graphical text engine for displaying game and title screen messages.
I don’t know how to do any of that, yet.
But I did discover something I have no recollection of… The game contains its own font data, which it loads when the game first runs. (Note to self: Better check and make sure the game cleans that font up and deallocates it when the game exits.)
The font data is a series of fcb byte entries like these:
* 91 [ fcb 126, 64, 64, 96, 96, 96, 126, 0 * 92 \ fcb 64,64,32,24,12,6,6,0 * 93 ] fcb 126, 2, 2, 6, 6, 6, 126, 0 * 94 up arrow fcb 24,52,98,0,0,0,0,0 * 95 _ fcb 0, 0, 0, 0, 0, 0, 0, 255 * 96 ` fcb 96, 48, 0, 0, 0, 0, 0, 0 * 97 a fcb 0, 0, 62, 2, 126, 98, 126, 0
The fonts are 8×8 pixels in size, so each entry has 8 bytes to represent the character.
At the top of the font data was a comment that caught my attention:
* hidden stuff in the font! :)
Hidden stuff? What did I hide? It appears there was repeating data in the first 32 font characters before the SPACE at 32:
font fcb $05,$00,$08,$00,$08,$04,$00 <- GPBufLoad Stuff fcb 0,87,81,119,20,23,0,0 * hidden stuff in the font! :) fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 fcb 0,87,81,119,20,23,0,0 * 32 (space) fcb 0, 0, 0, 0, 0, 0, 0, 0
I was curious what that was, so I searched to see if I could find an only bitmap font editor. Sure enough, someone has one for doing Commodore fonts:
I went there, and was able to recreate this “hidden stuff” in the font:
I had hidden a teeny tiny “42” in the font character set… Something no one would ever see, and that I had forgotten about.
Sub-Etha Software had other hidden 42s in other programs we distributed. I bet I’ve forgotten about some of them, as well…
But wait, there’s more … BASIC!
I took the code I wrote to display VIC-20 font data on a CoCo and updated it a bit, with this font data.
You can adjust the WD variable in line 10 based on what PMODE you want to see it in. Change that to 32 and PMODE 4 and you get it in the size it would be on a CoCo 32-column screen. Use 16 and that will work with PMODE 0 or PMODE 2. (PMODE 1 and 3 are color modes and just look weird since they take the 8 bits and turn them in to four 2-bit color pixels).
Enjoy…
0 REM INVADERS09 CHARSET 10 WD=16 '16=PMODE 0/2, 32=4 20 PMODE 0,1:PCLS:SCREEN 1,1 30 L=1536+2048:C=0 40 FOR R=0 TO 7:READ D:IF D=-1 THEN 999 50 POKE L+(WD*R),D:NEXT 60 L=L+1:C=C+1:IF C>=WD THEN C=0:L=L+(WD*8) 70 GOTO 40 999 GOTO 999 1000 ' hidden stuff in the font! :) 1010 DATA 0,87,81,119,20,23,0,0 1020 DATA 0,87,81,119,20,23,0,0 1030 DATA 0,87,81,119,20,23,0,0 1040 DATA 0,87,81,119,20,23,0,0 1050 DATA 0,87,81,119,20,23,0,0 1060 DATA 0,87,81,119,20,23,0,0 1070 DATA 0,87,81,119,20,23,0,0 1080 DATA 0,87,81,119,20,23,0,0 1090 DATA 0,87,81,119,20,23,0,0 1100 DATA 0,87,81,119,20,23,0,0 1110 DATA 0,87,81,119,20,23,0,0 1120 DATA 0,87,81,119,20,23,0,0 1130 DATA 0,87,81,119,20,23,0,0 1140 DATA 0,87,81,119,20,23,0,0 1150 DATA 0,87,81,119,20,23,0,0 1160 DATA 0,87,81,119,20,23,0,0 1170 DATA 0,87,81,119,20,23,0,0 1180 DATA 0,87,81,119,20,23,0,0 1190 DATA 0,87,81,119,20,23,0,0 1200 DATA 0,87,81,119,20,23,0,0 1210 DATA 0,87,81,119,20,23,0,0 1220 DATA 0,87,81,119,20,23,0,0 1230 DATA 0,87,81,119,20,23,0,0 1240 DATA 0,87,81,119,20,23,0,0 1250 DATA 0,87,81,119,20,23,0,0 1260 DATA 0,87,81,119,20,23,0,0 1270 DATA 0,87,81,119,20,23,0,0 1280 DATA 0,87,81,119,20,23,0,0 1290 DATA 0,87,81,119,20,23,0,0 1300 DATA 0,87,81,119,20,23,0,0 1310 DATA 0,87,81,119,20,23,0,0 1320 DATA 0,87,81,119,20,23,0,0 1330 ' 32 (space) 1340 DATA 0, 0, 0, 0, 0, 0, 0, 0 1350 DATA 16, 16, 24, 24, 24, 0, 24, 0 1360 DATA 102, 102, 204, 0, 0, 0, 0, 0 1370 DATA 68, 68, 255, 68, 255, 102, 102, 0 1380 DATA 24, 126, 64, 126, 6, 126, 24, 0 1390 DATA 98, 68, 8, 16, 49, 99, 0, 0 1400 DATA 62, 32, 34, 127, 98, 98, 126, 0 1410 DATA 56, 56, 24, 48, 0, 0, 0, 0 1420 DATA 12, 24, 48, 48, 56, 28, 12, 0 1430 DATA 48, 56, 28, 12, 12, 24, 48, 0 1440 DATA 0, 24, 36, 90, 36, 24, 0, 0 1450 DATA 0, 24, 24, 124, 16, 16, 0, 0 1460 DATA 0, 0, 0, 0, 0, 48, 48, 96 1470 DATA 0, 0, 0, 126, 0, 0, 0, 0 1480 DATA 0, 0, 0, 0, 0, 48, 48, 0 1490 ' 47 / 1500 DATA 2, 2, 4, 24, 48, 96, 96, 0 1510 DATA 126, 66, 66, 70, 70, 70, 126, 0 1520 DATA 8, 8, 8, 24, 24, 24, 24, 0 1530 DATA 126, 66, 2, 126, 96, 98, 126, 0 1540 DATA 124, 68, 4, 62, 6, 70, 126, 0 1550 DATA 124, 68, 68, 68, 126, 12, 12, 0 1560 DATA 126, 64, 64, 126, 6, 70, 126, 0 1570 DATA 126, 66, 64, 126, 70, 70, 126, 0 1580 DATA 62, 2, 2, 6, 6, 6, 6, 0 1590 DATA 60, 36, 36, 126, 70, 70, 126, 0 1600 DATA 126, 66, 66, 126, 6, 6, 6, 0 1610 DATA 0, 24, 24, 0, 24, 24, 0, 0 1620 DATA 0, 24, 24, 0, 24, 24, 48, 0 1630 DATA 6, 12, 24, 48, 28, 14, 7, 0 1640 DATA 0, 0, 126, 0, 126, 0, 0, 0 1650 DATA 112, 56, 28, 6, 12, 24, 48, 0 1660 DATA 126, 6, 6, 126, 96, 0, 96, 0 1670 ' 64 1680 DATA 60, 66, 74, 78, 76, 64, 62, 0 1690 DATA 60, 36, 36, 126, 98, 98, 98, 0 1700 DATA 124, 68, 68, 126, 98, 98, 126, 0 1710 DATA 126, 66, 64, 96, 96, 98, 126, 0 1720 DATA 124, 66, 66, 98, 98, 98, 124, 0 1730 DATA 126, 64, 64, 124, 96, 96, 126, 0 1740 DATA 126, 64, 64, 124, 96, 96, 96, 0 1750 DATA 126, 66, 64, 102, 98, 98, 126, 0 1760 DATA 66, 66, 66, 126, 98, 98, 98, 0 1770 DATA 16, 16, 16, 24, 24, 24, 24, 0 1780 DATA 4, 4, 4, 6, 6, 70, 126, 0 1790 DATA 68, 68, 68, 126, 98, 98, 98, 0 1800 DATA 64, 64, 64, 96, 96, 96, 124, 0 1810 DATA 127, 73, 73, 109, 109, 109, 109, 0 1820 DATA 126, 66, 66, 98, 98, 98, 98, 0 1830 DATA 126, 66, 66, 98, 98, 98, 126, 0 1840 DATA 126, 66, 66, 126, 96, 96, 96, 0 1850 DATA 126, 66, 66, 66, 66, 78, 126, 0 1860 DATA 124, 68, 68, 126, 98, 98, 98, 0 1870 DATA 126, 66, 64, 126, 6, 70, 126, 0 1880 DATA 126, 16, 16, 24, 24, 24, 24, 0 1890 DATA 66, 66, 66, 98, 98, 98, 126, 0 1900 DATA 98, 98, 98, 102, 36, 36, 60, 0 1910 DATA 74, 74, 74, 106, 106, 106, 126, 0 1920 DATA 66, 66, 66, 60, 98, 98, 98, 0 1930 DATA 66, 66, 66, 126, 24, 24, 24, 0 1940 DATA 126, 66, 6, 24, 96, 98, 126, 0 1950 ' 91 [ 1960 DATA 126, 64, 64, 96, 96, 96, 126, 0 1970 ' 92 \ 1980 DATA 64,64,32,24,12,6,6,0 1990 ' 93 ] 2000 DATA 126, 2, 2, 6, 6, 6, 126, 0 2010 ' 94 up arrow 2020 DATA 24,52,98,0,0,0,0,0 2030 ' 95 _ 2040 DATA 0, 0, 0, 0, 0, 0, 0, 255 2050 ' 96 ` 2060 DATA 96, 48, 0, 0, 0, 0, 0, 0 2070 ' 97 a 2080 DATA 0, 0, 62, 2, 126, 98, 126, 0 2090 DATA 64, 64, 126, 70, 70, 70, 126, 0 2100 DATA 0, 0, 126, 66, 96, 98, 126, 0 2110 DATA 2, 2, 126, 66, 70, 70, 126, 0 2120 DATA 0, 0, 124, 68, 124, 98, 126, 0 2130 DATA 62, 34, 32, 120, 48, 48, 48, 0 2140 DATA 0, 0, 126, 66, 98, 126, 2, 62 2150 DATA 64, 64, 126, 66, 98, 98, 98, 0 2160 DATA 16, 0, 16, 16, 24, 24, 24, 0 2170 DATA 0, 2, 0, 2, 2, 2, 98, 126 2180 DATA 96, 96, 100, 68, 126, 70, 70, 0 2190 DATA 16, 16, 16, 16, 24, 24, 24, 0 2200 DATA 0, 0, 98, 126, 74, 106, 106, 0 2210 DATA 0, 0, 126, 66, 98, 98, 98, 0 2220 DATA 0, 0, 126, 66, 98, 98, 126, 0 2230 DATA 0, 0, 126, 66, 66, 126, 96, 96 2240 DATA 0, 0, 126, 66, 78, 126, 2, 2 2250 DATA 0, 0, 124, 96, 96, 96, 96, 0 2260 DATA 0, 0, 126, 64, 126, 6, 126, 0 2270 DATA 16, 16, 126, 16, 24, 24, 24, 0 2280 DATA 0, 0, 66, 66, 98, 98, 126, 0 2290 DATA 0, 0, 98, 98, 98, 36, 24, 0 2300 DATA 0, 0, 66, 74, 106, 126, 36, 0 2310 DATA 0, 0, 98, 126, 24, 126, 98, 0 2320 DATA 0, 0, 98, 98, 98, 36, 24, 112 2330 DATA 0, 0, 126, 108, 24, 50, 126, 0 2340 DATA 14, 24, 24, 112, 24, 24, 14, 0 2350 DATA 24, 24, 24, 0, 24, 24, 24, 0 2360 DATA 112, 24, 24, 14, 24, 24, 112, 0 2370 DATA 50, 126, 76, 0, 0, 0, 0, 0 2380 DATA 102, 51, 153, 204, 102, 51, 153, 204 2390 DATA 102, 51, 153, 204, 102, 51, 153, 204 2400 DATA -1
Until next time…
If you load it as a regular font, then you should be able to DISPLAY it in another graphics window while the game is running in OS-9/NitrOS9 (thus being able to view it even if you do kill the font when exiting the game).
Interesting. Font buffer is global, yes?