1 hour ago, rje said:
Here's something I've wanted at least three times now: a "BASIC blitter" or something, that can print strings stored in banked RAM.
I'm doing this a lot:
for x = a to a+15 :n$=n$+chr$(peek(x)) :next x
My inner garbage collector dies a little every time I do this. Maybe I can set the accumulator from BASIC and then call CHROUT in that loop? e.g.
for x = a to a+15 :poke 780, peek(x) :sys $FFD2 :next x
OKAY, I'VE ANSWERED MY OWN QUESTION: yes, it works.
It's still clunky, but at least it doesn't offend my inner gc.
There is already a feature request on the ROM Github page.
While there's been some discussion about the actual implementation, the basic idea has definitely been put forward to the team. Short version, is I proposed PEEK and POKE for all of the basic data types, along with a BANK statement to make it simpler to access banked memory with all of the BASIC memory commands.
So let's skip to how to do it NOW....
Cheat and hack the variable table. The VARTAB variable lives at $03E2 on the CX16. (Look at the "basic.sym" file included with the emulator.)
Start by creating a string that you don't intend to use. I'll use B$ in my example.
Looking at $3E2, we see the table is actually at $0811
so lets look at $0811, we get:
42 80 - B$ (B is ASCII 42, and 80 is the internal flag for $).
04 - the string is 4 bytes long
09 08 - data is stored at $0809 in memory. Let's confirm this:
There it is! ABCD
and this is actually pretty smart... if we examine memory from the start of our program ($801), we see that $809 is actually the location of the string literal itself. Check it out:
So the interpreter actually just pointed the string pointer
directly inside the program. So we can hack this by pointing to a different place in memory and reading our string from there. Let's write the numerals 1-8 to $400
Now modify the variable table
By changing the address to $00 04, we point the start of the string to $400
And by changing the 04 to 08, we can make the string 8 bytes long.
This results in:
It's a little more complex to put this into BASIC, but we can do it:
This program writes all of the PETSCII characters to the $400 space, then changes B$ to point to the @ sign. It makes B$ 32 bytes long, so we should see the whole alphabet, plus a few extra characters:
Note the test for B$ on line 30. The variable table sets bit 7 of the
second letter high on a string variable. So B$ is actually "B" followed by $80.
Line 40 advances to the next variable in the table, and contains a sanity check to make sure we don't read past the end of BASIC memory.
Finally, line 50 errors out if we made a mistake.
So using that technique, you should be able to point to any place in memory, including banked RAM. Just be careful to always set your bank register to the right location before trying to print or read B$.