Hacking the Color BASIC PRINT command – part 1

Over in the CoCo Facebook group, Erico Patricio Monteiro asked an interesting question:

“Would it be possible to PRINT a transparent character?”

– Erico Patricio Monteiro

His idea was for putting stuff on the CoCo’s text screen without wiping out the background. He used an example of PRINT”OOOOX” where “O” represented the transparent character. The way I see it, if you had the first line printed like this:

PRINT @0,"ABCDEFG";

…and you had such a transparent character and did this:

PRINT @0,"OOOXOOO";

…your top line would then look like this:

ABCXEFG

This reminded me of how my Commodore VIC-20 had cursor movement characters you could embed in a PRINT statement. Once you typed the quote, you could now embed typeable escape codes to change colors, clear the screen, home the cursor, insert or delete characters, or just move the cursor up, down, left or right. This made VIC-20 program listings require a graphical printer to represent those characters. Here is something from the VIC-20 manual:

This is many pages into the manual, after it had explained how you can embed things like color changes or reverse video. The program listings in the VIC-20 manual had graphical characters in them, and you had to learn what to type to recreate them:

Program listings for the VIC looked weird ;-)

At some point, Commodore BASIC listings were represented with text strings instead of the graphical characters, making a modern listing look like this:

25 print"{home}{down}{right}{black}abc{down}{left*3}def{down}{left*3}ghi{down}{left*3}jkl"

Then you just had to know what key was “black” or “left” (three times, as the “left*3” indicates).

But I digress…

Since there was no PRINT@ or LOCATE on the VIC-20, any time you wanted to print something in a particular spot on the screen you had to print the HOME (move cursor to top left of the screen) character then use a bunch of cursor controls to move to where you wanted to print.

This was … not optimal. And thus, most BASIC VIC-20 programs would print their information (lives left, etc.) on the top of the screen since it was shorter code just to home and print there:

VIC-20 Sky-Ape-Er, screen 3.

My Sky-Ape-Er VIC-20 game had a timer, and I got it in that top corner like this:

105 print"{home}{blue}{reverse on}{right}time:";t:t=t+1

You will notice the above snipped says “reverse on” and has “time” in lowercase, but on my screenshot it is uppercase without being reversed. That is due to the character sets of the VIC-20 where some modes were upper and lower, some were upper with reverse, and other combinations. For the mode I was in, reverse was getting the uppercase characters (and uppercase characters typed with SHIFT would be the graphical characters for those keys).

“But that’s really not important to this story…”

If you look at the Color BASIC Unraveled book you can find the Console Out routine (PUTCHR) on page 84. I did not want to type it all in here, but I did find this GitHub repository by tomctomc that has this already in a text file:

coco_roms/bas.asm at master · tomctomc/coco_roms

From the “bas.asm”, here is the code in question:

; CONSOLE OUT
PUTCHR          JSR         >RVEC3          ; HOOK INTO RAM
                PSHS        B               ; SAVE ACCB
                LDB         DEVNUM          ; GET DEVICE NUMBER
                INCB                        ;  SET FLAGS
                PULS        B               ; RESTORE ACCB
                BMI         LA2BF           ; SEND TO LINE PRINTER
                BNE         LA30A           ; SEND TO SCREEN

                ...snip...

; PUT A CHARACTER ON THE SCREEN
LA30A           PSHS        X,B,A           ; SAVE REGISTERS
                LDX         CURPOS          ; POINT X TO CURRENT CHARACTER POSITION
LA30E           CMPA        #BS             ; IS IT BACKSPACE?
                BNE         LA31D           ; NO
                CMPX        #VIDRAM         ; AT TOP OF SCREEN?
                BEQ         LA35D           ; YES - DO NOT ALLOW BACKSPACE
                LDA         #$60            ; BLANK
                STA         ,-X             ; PUT IN PREVIOUS POSITION
                BRA         LA344           ; SAVE NEW CURPOS
LA31D           CMPA        #CR             ; ENTER KEY?
                BNE         LA32F           ; BRANCH IF NOT
                LDX         CURPOS          ; GET CURRENT CHAR POSITION
LA323           LDA         #$60            ; BLANK
                STA         ,X+             ; PUT IT ON SCREEN
                TFR         X,D
                BITB        #$1F            ; TEST FOR BEGINNING OF NEW LINE
                BNE         LA323           ; PUT OUT BLANKS TILL NEW LINE
                BRA         LA344           ; CHECK FOR SCROLLING
LA32F           CMPA        #SPACE
                BCS         LA35D           ; BRANCH IF CONTROL CHARACTER
                TSTA                        ;  SET FLAGS
                BMI         LA342           ; IT IS GRAPHIC CHARACTER
                CMPA        #$40
                BCS         LA340           ; BRANCH IF NUMBER OR SPECIAL CHARACTER
                CMPA        #$60            ; UPPER/LOWER CASE?
                BCS         LA342           ; BRANCH IF UPPER CASE ALPHA
                ANDA        #$DF            ; CLEAR BIT 5, FORCE ASCII LOWER CASE TO BE UPPER CASE
LA340           EORA        #$40            ; INVERT BIT 6, CHANGE UPPER CASE TO LOWER & VICE VERSA
LA342           STA         ,X+             ; STORE CHARACTER TO SCREEN
LA344           STX         CURPOS          ; SAVE CURRENT CHAR POSITION
                CMPX        #VIDRAM+511     ; END OF SCREEN BUFFER?
                BLS         LA35D           ; RETURN IF NO NEED TO SCROLL

You can see at LA30A the code begins checking for things like backspace and enter. Eventually at LA342 it puts the character on the screen an increments X which is the current screen location. It then has code (not shown) that detects being at the bottom of the screen and scrolling up a line if needed.

To patch this CHROUT routine to support a “transparent” character, I think we’d just have to intercept the code at LA342 and decide if it should put a character on the screen (STA ,X+) or just increment X (LEAX 1,X or something) without putting anything there.

And that would be a real simply patch. A CoCo 1/2 with 64K could run the program that copies the ROM into RAM then switches over, then this could code easily be patched.

And while we were there, maybe it could be extended to support cursor movements as well, replicating how the VIC-20 output works.

But I am getting ahead of myself…

To be continued…

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.