Page 1 of 1

Function Screen() to get a character code from screen

Posted: Sat Sep 28, 2024 11:49 pm
by mobluse
If Commander X16 BASIC had the function SCREEN(ROW, COL) that exists in GWBASIC and QBASIC then one could easily make e.g. trackers that use the BASIC editor without using machine code. Example that uses machine code:
Making 8-bit Music From Scratch at the Commodore 64 BASIC Prompt

SCREEN() function in GWBASIC: http://www.antonis.de/qbebooks/gwbasman/screenf.html
SCREEN() function in QBasic: https://www.qbasic.net/en/reference/qb1 ... SCREEN.htm
You can use some form of PEEK() from screen memory, but that is more complicated than using a SCREEN() function. You still need to use machine code to get multitasking, i.e. being able to edit the music while it plays. You can use Stop-key (Ctrl+C or Ctrl+Break or Ctrl+ScrollLock) and CONT (continue) instead of multitasking.

I wrote this in GW-BASIC that is compatible with Linus Ã…kesson's tracker, but it has only one channel:

Code: Select all

10 GOTO 90 'TRACKER INSPIRED BY LTFKRYO'S FOR C64 EDITOR IN BASIC&MC.
20 N0=ASC("@") 'CODE IS PURE GWBASIC. BREAK EARLY USING CTRL+SCRLK!
30 FOR I=8 TO 79
40 N=SCREEN(7,I):C=SCREEN(4,I)
50 N$=CHR$(N):C$=CHR$(C):LOCATE 4,I:COLOR 15:PRINT C$;
60 IF N$<>" " AND N$<>":" THEN PLAY "N"+STR$(N-N0) ELSE PLAY "N0"
70 LOCATE 4,I:COLOR 7:PRINT C$;
80 NEXT:GOTO 30
90 COLOR 7:CLS:PRINT "RUN 20":PRINT TAB(8)"GWTRAKR":LIST 91- 'ONLY ONE CHANNEL
91 REM
92 REM +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---
93 REM :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :
94 REM :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :   :
95 REM AEFH:AEFH AEFH E:A E:C EECA AE H:HF EFH E A C  A    :   :   :   :QSU:ZX
96 REM
97 REM   B D   G I K   N P   S U W   Z
98 REM  A C E F H J L M O Q R T V X Y
You have to use RUN 80 to get the tracker music on the screen and then RUN to play it. The source code is also on https://github.com/mobluse/x16-psg-musi ... WTRAKR.BAS . On X16 it could have more sound channels.

Re: Function Screen() to get a character code from screen

Posted: Sun Sep 29, 2024 12:46 am
by desertfish
There is such a function though... TDATA

https://github.com/X16Community/x16-doc ... C.md#tdata

Re: Function Screen() to get a character code from screen

Posted: Sun Sep 29, 2024 1:29 pm
by mobluse
Thanks! I now tested TDATA(X, Y), and compared to SCREEN(r, c) it has some disadvantages:
  • Arguments are in reverse order compared to LOCATE r, c.
  • Arguments are 0 based, but in LOCATE they are 1 based.
  • It doesn't return PETSCII, but some private code that can be converted to PETSCII in a subroutine using some IF statements.
  • It is not compatible with SCREEN(r, c) in GWBASIC and QBasic which makes programs less portable.
Here is my Commander X16 BASIC V2 test program that shows the difference between PETSCII code and TDATA code for different intervals of 32 printable characters. Note that the last character in PETSCII, 255, doesn't have the same difference as the others in that interval. Maybe this is a bug in the ROM?
Try It Now!

Code: Select all

10 SCREEN 2
20 FOR I=1 TO 3
30 GOSUB 200
40 NEXT
50 FOR I=5 TO 7
60 GOSUB 200
70 NEXT
99 END
200 CLS:LOCATE 1, 39: PRINT I;
210 S=32*I
220 FOR J=S TO S+32-1
230 C$=CHR$(J)
240 LOCATE 1, J-S+1: PRINT C$;
250 C=ASC(C$)
260 T=TDATA(J-S, Y)
270 LOCATE J-S+3, 1: PRINT C$, C, T, C-T
280 NEXT
285 INPUT A$
290 RETURN
I noticed that if I do ?CHR$(15) before I run the program, i.e. switch to ISO-mode, then the difference is always zero, which is good. I would prefer if the function SCREEN(), compatible with the statement LOCATE, was added and that it also worked in PETSCII mode, but I can manage without it.

Re: Function Screen() to get a character code from screen

Posted: Wed Oct 09, 2024 6:04 am
by voidstar
re: keyboard-codes vs display-codes. That's a "historical" aspect of CBM machines - the keyboard grid was electrically different than the video mechanism for showing fonts (and to keep cost down, the keyboards were very simple). And that unfortunately meant the (then) ~1MHz CPU was wasting cycles converting between the two conventions. And many systems of that era had that same issue, since ASCII wasn't universally adopted (and to be fair, in pre-internet days broadcasting standards wasn't so easy; plus keep in mind the "A" in ASCII means American as opposed to Universal).

And unfortunately, a lot of new-to-this-system developers have to grind through understanding all this - the tech refs are very good, but this is an aspect that isn't really documented very well (but it's not all that complicated once you get it - and then you discover ISO mode, and just use that all the time :) ). Display Codes are essentially an index into the font table VERA 0:$F000, F for font!! :P ). When you do PRINT "ABC", the BASIC parser has to translate each of "ABC" into corresponding font indexes - which takes time. That's why TILE can be faster (except of course you have to call TILE 3x times to write "ABC", so its utility just depends on what you're doing). One has a lot of control over font, but not so much control over the keyboard scan codes (which for the X16, I think for the SMC and PS/2 integration, those scan codes are essentially an old IBM "set2" standard - which the System ROM adapters those codes over into classic CBM codes and/or key-modifier flags).


X16 BASIC is sort of like Extended Color BASIC for the Color Computer - in terms of having a lot of system-specific keywords to help speed things up or take advantage of hardware it had. But I view that as just the nature of BASIC: it has a few staple commands like LIST, RUN, IF, FOR, PRINT - commands beyond just depend on how you want to use the system.