Category Archives: Sub-Etha Software

Dissecting my MiniBanners program – part 1

See Also: part 1 (with more parts to come).

This series of blog posts will discuss my CoCo program, MiniBanners. It will discuss the things that changed between versions, and dissect the code to explore how it worked. The code referenced in this blog post can be found in my new SubEthaSoftware repository on GitHub:

https://github.com/allenhuffman/SubEthaSoftware/tree/main

Part 1 – Origin and versions

MiniBanners is a banner printing program I wrote and sold through Sub-Etha Software. It made its debut at the 1990 Atlanta CoCoFest. It was written in BASIC and ran on a Color Computer 3 using the 40 column text screen. It “required” a CoCo 3 only because I was making use of CoCo 3 fonts that could be LOADM’d and used on the graphics screens with the HPRINT command.

Unlike most (all?) commercial banner programs of the era, MiniBanners did not require a graphics printer. It would work on small printers like the Radio Shack TP-10 (32 columns) or wider ones (132 columns). It would use any ASCII character to make the banners with. Some printers had a black graphics block they could print (Tandy printers, TP-10, etc.), so it could use that. For non-dot matrix printers, it could use an ASCII “X” or “#” or whatever character the user wanted. This let it print to basically any printer – dot matrix, thermal and even daisy wheel. (Remember those?)

Another feature was the ability to print multi-line banners. You could specify the height of each line and either print a one-line banner using the full 80 column width of a printer, or make it four lines with each line of text being 20 characters tall.

I would even switch printer ribbons and print “multi color” banners, but that was not anything that the program directly helped with. Here is a photo of some of the banners we used at a CoCoFest (except for the top one; I think that was done on an Apple 2 using PrintShop or whatever they had back then).

While our initial lineup of programs were all for Disk BASIC (RS-DOS as we called it back then), so many people at the CoCoFest told us “I’d buy it if it ran under OS-9” that it was soon ported over to BASIC09 as an OS-9 program. If I can find versions of that code, I’ll include it in this series in a later installment.

It all began as a one (or two) liner…

I recall finding a free BASIC banner printing program that had an awful font. I wanted to modify it to make the letters it printed look better. I decided to use the font data that was part of the CoCo 3 ROM. This data starts in memory at &HF09D. Here is a snippet from the disassembly:

* SPECIAL CHARACTERS AND NUMBERS
SF09D FCB $00,$00,$00,$00,$00,$00 BLANK
FCB $00,$00
FCB $10,$10,$10,$10,$10,$00 !
FCB $10,$00
FCB $28,$28,$28,$00,$00,$00 "
FCB $00,$00
FCB $28,$28,$7C,$28,$7C,$28 #
FCB $28,$00
FCB $10,$3C,$50,$38,$14,$78 $
FCB $10,$00

Rather than rebuild the DATA in the program I was playing with, I decided to just write my own. I quickly had a simple program that would input a line and then print out a banner using this font data. If I recall, I had the whole program fitting in one or two lines.

I had planned to submit it to Rainbow magazine for their “one/two liner” thing they printed in each issue, but I do not recall actually doing that.

It was this simple program inspired me to create a larger program with more features (such as multi-line banners). MiniBanners became Sub-Etha Software’s third product (after ShadowBBS and MultiBasic, both written by cofounder Terry Todd).

It pretended to be in assembly…

I knew most folks would not buy a program written in BASIC. Ads of the time would exlaim “100% machine language.” Because of this, I decided to disguise that MiniBanners was in BASIC by turning it into a “.BIN” file you had to LOADM and EXEC to run, rather than LOAD and RUN to run like a BASIC program.

In case anyone got suspicious and took a disk editor to my .BIN program, I also “scrambled” the contents so they would not look obviously like a BASIC program. You wouldn’t be able to see the standard patterns for line numbers, strings, etc.

I did this by using a short assembly language routine I called SCRAM.ASM. It would take the BASIC program in memory, then “scramble” it by inverting the bits in each byte using the COM op code. That data was then added to an assembly loader routine that would descramble it and set it up to run like a normal BASIC. The end result was you would LOADM”MINIBAN.BIN”:EXEC and have a program running as if it were a machine language program.

In a later installment, I plan to explore that assembly code and try to re-learn how it worked.

For now, let’s discuss the different versions of the RS-DOS BASIC version of MiniBanners.

Version 0.0 – 9/20/1990

According to comments in the code, work began on MiniBanners on September 20, 1990. The goal was to have it ready for the first Atlanta CoCoFest which would be held about two weeks later on the weekend of October 6-7, 1990. The whole program was created in about ten days, including writing the code and manual, and having the manual printed and getting master disks copied (with serial numbers) and labeled for sale at the Fest.

Since this program only came to exist after we had submitted our booth information for the CoCoFest show guide, our entry there has no mention of MiniBanners:

Our entry in the 1990 Atlanta CoCoFest show guide.

Version 1.0 – 10/1990

This was the initial release version sold at that CoCoFest. It ran only on a 40 column screen.

Version 1.1 – 10/1990

This version added support for 80 columns with a new menu option of “W” to toggle between 40 and 80.

It also made specifying the baud rate easier. The user could now just type in 600, 1200, etc. and it would be calculated. In version 1.0, you had to know the POKE value for the desired baud rate. Examples offered in v1.0 were 180 for 600 baud, 88 for 1200 baud, and 41 for 2400 baud. In 1.1, you could just enter 1200 or 2400 and a routine would figure out the POKE value.

I have no idea where I got this from, but I know I didn’t come up with it ;-)

875 REM * Baud Rate Routine
880 POKE150,INT(.2175+5.7825*2^(5-(LOG(BD/600)/LOG(2)))-4.5):RETURN

It also appears the “instant showing screen” trick was not used in version 1.0, as I find routines in 1.1 that set the text palette to the background color. Then, in the GOSUB routine that does input, it sets it back to white. Clever.

50 REM * Main Menu
55 PALETTE8,BG:CLS:PRINTTAB(TB+9)"/) MiniBanners! "VR$" (\":ATTR1,1:PRINT:ATTR0,0:LOCATE0,22:ATTR1,1:PRINT:ATTR0,0:PRINTTAB(TB+13)"Enter Function";
60 LOCATETB+11,6:PRINT"[1] Print a Banner":PRINT:PRINTTAB(TB+11)"[2] Select Font ("FT$")":PRINT:PRINTTAB(TB+11)"[3] Configuration"
65 LOCATETB+11,17:PRINT"[W] Toggle 40/80":LOCATETB+11,19:PRINT"[X] Exit to Basic"
70 LOCATETB+15,3:PRINT"[D]rive:"DR:DRIVEDR
75 GOSUB1055:A=INSTR("123DWX",A$):IFA=0THENSOUND200,1:GOTO75
...
1050 REM * Inkey$
1055 PALETTE8,FG
1060 A$=INKEY$:IFA$=""THEN1060ELSESOUND1,1:LT=ASC(A$):IFLT>96THENA$=CHR$(LT-32)
1065 RETURN

There are also some new POKEs added when setting up the screen:

PALETTE1,FG:PALETTE9,BG:POKE63395,9:POKE63468,9:POKE63503,0:POKE63567,0:POKE63644,0:POKE63771,0

Let’s see if we can figure out what they do. Consulting Super Color BASIC Unravelled should help, or the source code listing at the toolshed repository on GitHub:

https://github.com/n6il/toolshed/blob/master/cocoroms/coco3.asm

First, let’s convert those decimal values into HEX so we can find them in the assembly listing.

POKE63395,9 - F7A3
POKE63468,9 - F7EC
POKE63503,0 - F80F
POKE63567,0 - F84F
POKE63644,0 - F89C
POKE63771,0 - F91B

At the time I was writing MiniBanners, my Sub-Etha Software co-founder, Terry, was deep into patching BASIC for his MultiBasic product. He had picked up copies of the Unravelled series and would tell me neat POKEs to try. I expect he provided me with these POKEs because, at the time, I had no idea how the BASIC ROMs worked beyond using a few documented ROM calls in small assembly routines I wrote.

POKE63395,9 – F7A3 takes me to this bit in the source code:

SF79F	LDA	>H.CRSATT	GET THE CURSOR ATTRIBUTES RAM IMAGE
ORA #$40 FORCE THE UNDERLINE ATTRIBUTE

I expect this location is changing the #$40 from an underline to a 9. The original code was setting bits. $40 would be 01000000. 9 would be 00001001. Since these deal with the cursor attributes, I guess we need to figure out what those 8 bits do. The Unravelled book explains this on page 8:

Bit 7 BLINK 1=Character blinks
Bit 6 UNDLN 1=Character is underlined
Bit 5 FGND2 Foreground Color (MSB)
Bit 4 FGND1 Foreground Color
Bit 3 FGND0 Foreground Color (LSB)
Bit 2 BGND2 Background Color (MSB)
Bit 1 BGND1 Background Color
Bit 0 BGND0 Background Color (LSB)
Figure 4 - Attribute byte

The original code was setting bit 6, the underline bit. That make the BASIC cursor be an underline. But the new code is setting bits 0 and 3 which are setting the foreground color to 100 (4) and background to 100 (4). Or maybe that is reversed (since I see MSB/LSB) and they are both being set to 1. Maybe someone can explain it, but I think this is just setting it to a solid color block.

POKE63468,9 – F7EC looks to be the same attribute, but this time involved when printing a backspace.

* DO A HI-RES BACKSPACE HERE
SF7E2 PSHS B,A
LDA #SPACE SPACE CHARACTER
LDB >H.CRSATT GET THE ATTRIBUTES RAM IMAGE
STD ,X SAVE A SPACE ON THE SCREEN AT THE OLD CURSOR POSITION
ORB #$40 FORCE THE UNDERLINE ATTRIBUTE

POKE63503,0 – F80F is also related to the cursor attribute:

SF807	PSHS	B,A
LDA #$20 GET THE CURSOR CHARACTER
LDB >H.CRSATT GET THE CURSOR ATTRIBUTES RAM IMAGE
ORB #$40 FORCE THE UNDERLINE ATTRIBUTE

POKE63567,0 – F84F is just a bit further down, same thing:

	LDB	>H.CRSATT	ACCB ALREADY CONTAINS THIS VALUE
ORB #$40 FORCE THE UNDERLINE ATTRIBUTE

POKE63644,0 – F89C is likely this, again:

	LDB	>H.CRSATT	GET THE CURSOR ATTRIBUTES RAM IMAGE
ORB #$40 FORCE THE UNDERLINE ATTRIBUTE

POKE63771,0 – F91B is this a bit further down:

	LDA	>H.CRSATT	GET THE CURSOR ATTRIBUTES RAM IMAGE
ORA #$40 FORCE UNDERLINE ATTRIBUTE

I therefore conclude that these POKEs are just changing the cursor from an underline (which screams “I am a BASIC program!”) to a solid block. Running these POKEs on a CoCo 3 emulator confirms. Thanks, Terry!

I find a POKE 282,0 added, which is done before calling a line input routine. That address is:

CASFLG RMB 1 UPPER CASE/LOWER CASE FLAG: $FF=UPPER, 0=LOWER

It appears to change the input to lowercase before the user types in the line to be printed. I suppose this saved the user from having to SHIFT-0 before entering their message.

Another line was added, which checks to see if the printer is ready. If the printer is ready, it just goes on and prints. If it is not, it displays the “Ready Printer or Press [X]” message. Nice.

156 IF(PEEK(&HFF22)AND1)>0THENLOCATETB+6,23:ATTR1,1,B:PRINT" Ready Printer or Press [X]";:ATTR0,0:GOSUB1055:IFA$="X"THEN55ELSE156

There is an error handling routine which got updated with the wording changed from “eliminate” to “exterminate” for some reason. Maybe I thought “exterminate” was more clever for a bug?

735 LOCATETB+6,4:PRINT"[ Error"ERNO"reported at"ERLIN"]":PRINT:PRINTTAB(TB)" Honestly, I thought I had it bug-free!":PRINT:PRINTTAB(TB)"   If this was something other than a":PRINTTAB(TB)"   Disk Full or I/O Error, please let"
736 PRINTTAB(TB)" us know so we may exterminate it."

I also find a few bug fixes. MiniBanners ran in the “double speed” mode using POKE 65497,0. This would mess up disk I/O unless you switched back to low speed with POKE 65496,0 before doing it. I found I had added the slow/fast POKEs in some places that had been missing it, such as this line which loaded a font:

765 A$=FT$:EX$="FNT":GOSUB840:IFA=0THENRETURNELSEPOKE65496,0:LOADMA$+"."+EX$:POKE65497,0

It also looks like I added a “are you sure” confirmation when you exited the program:

95 LOCATETB+5,23:PRINT"Exit Banners? [Y]es or [N]o :";:GOSUB1055:IFA$<>"Y"THEN55

There may have been some other things I missed, but those were the main ones that I noticed.

Version 1.2 – 4/11/1991

This update had the note “fix reset when exiting” but I find nothing in the code that changed from 1.1 other than the version (“1.2”) and the year (“1991”). I may be missing the actual fixed version, and now I wonder what the problem was when exiting. The exit code looks like:

95 LOCATETB+5,23:PRINT"Exit Banners? [Y]es or [N]o :";:GOSUB1055:IFA$<>"Y"THEN55
96 CLS:PRINTTAB(TB+4)"Thank You for using MiniBanners!":ATTR1,1:PRINT:ATTR0,0:PRINT
97 POKE65496,0:POKE150,18:POKE282,255:POKE63395,64:POKE63468,64:POKE63503,64:POKE63567,64:POKE63644,64:POKE63771,64:NEW

It has the “are you sure” confirmation added in 1.1, then I see it POKEs back to slow speed, POKEs to reset the printer baud rate, and POKEs to restore the cursor before erasing the program using NEW. I expect somewhere in the program I did something else that I forgot to restore, and that is what 1.2 was supposed to address. Maybe I will find another copy of this file somewhere in my archives. If so, I’ll update this post at that time.

Looking at this now, I probably should have just reset the machine, or added something to erase the program from memory. After existing this way, someone could have done two POKEs to change the end location of BASIC in memory and recovered the program and had the source code ;-)

Up next … dissecting the code.

Until then…