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:

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…

What about this “check if control character”
LA32F CMPA #SPACE
BCS LA35D
Seems like a great place to add things like this, unless all codes <32 are already taken? (I haven’t read the next part yet).
Tangent 1:
Technically the VIC 20 (and all other Commodore 8-bits) really only had two modes, either upper lower case + some graphic characters, or upper case + more graphics characters. However thanks to the char rom being right after the built in RAM in a VIC 20 as seen fro the VIC chip you could set the character pointer so the first 128 characters points to RAM and the upper 128 characters points to ROM, resulting in those pointing to what was intended as the first 128 characters, thus the RVS ON = non reversed ROM characters, while RVS OFF gave RAM characters.
Tangent 2:
Most typical asynchronous terminals and afaik all their successors (like the console in Linux, Windows, OS X or whatnot) have control codes for moving the cursor and whatnot, but those tend to be more complicated ANSI escape sequences. But I assume you already know this.`s
Tangent 3:
It’s a bit bad that the blog software seems to embed some sort of session cookie like thing in the HTML code, that expires after a while, and if that thing is expired any attempts to post a comment results in the comment being thrown away, not even offering a way to retry. I managed to salvage most of what I wrote above by opening the dev tool thing in Firefox and check what Firefox sent each time I tried reloading the POST that resulted in an error message. Would be nice if the blog software would at least return to the “enter comment” state when this error happens, with the comment and name/mail already filled in. Or maybe I ought to install the firefox add-on that makes background opened tabs not actually load until they are activated. I tried searching for a way to invalidate the cache for a specific non-current tab, but that seems really hard. Seems like a not great idea to clear all Firefox cache just to ensure that the tabs I keep open with the next few parts of this series will be forced to reload (and thus not result in expired things) when I find time to read them. Really it would be great if Feedbro didn’t automatically mark everything as read as soon as I’ve seen the list of feed things, but that might be too much to ask in today’s society where everything apparently is supposed to be a “flow” that just fades away when you look away :)
Don’t get me started on WordPress. I bet it’s better if you pay $$$$ and host it on the WordPress site, directly, but it has been quite problematic for me over the years on the dozens of sites I use it on for other projects.
I’ll check that ROM code out. I need to do a few more parts to this. New information and all…