Standard BASIC does more than just number crunching and string manipulation. You can call up Z80 machine language programs with the USR function. You can put values into certain parts of memory with the POKE statement and look at memory with the PEEK function.
You saw in Chapter 9 how to do some graphics and simple animation with PRINT statements. POKEs can do the same faster and without that annoying cursor flashing all over the place. Part of the Sorcerer's memory is screen RAM. (RAM is Random Access Memory, what the user can get at.) The video driver (part of the Sorcerer's hardware) constantly scans screen RAM and puts whatever it sees into the appropriate corresponding position on the screen. For instance, location F080 hex (-3968 decimal) is the left uppermost position of the screen. Whatever character the Sorcerer sees in this memory location (represented by the character's ASCII number), it puts in the upper left-hand corner of the screen.
Example:
POKE -3968,65
prints a capital A in the upper left of your screen.
POKE -2112,63
prints a question mark in the lower left of your screen.
65 is the ASCII number of the capital A and 63 is the ASCII number of the question mark. You find these in Table 3 in Appendix G. You can also use the ASC function to POKE characters into screen locations. These two statements are the equivalent of the preceding two:
POKE -3968,ASC("A")
and
POKE -2112,ASC("?")
Screen locations are given in Table 2 in this chapter, The upperleft screen position is -3968 decimal. Since each screen line is 64 characters wide, each line starts 64 numbers higher.
You know about standard keyboard graphic characters which you can type directly on the screen, as well as call up with the CHR$ function. Each character consists of an 8 x 8 dot matrix. (Certain of the dots are "on" and appear white on the screen-, the dots which are "off" do not appear on the screen.)
The Sorcerer's graphic resolution is 512 x 240, that is, there are 512 horizontal positions and 240 vertical positions for dots to appear on the screen. To print a character on the screen, the Sorcerer selects an 8 x 8 square of these positions and puts dots in just the places needed to form the character.
Since each character occupies an 8 x 8 space, and the screen is 512 x 240, it follows that you can get 64 characters on a line, and 30 lines on the screen. The total number of characters on the screen at any time (including blank spaces) is 1920 (64 x 30).
Now the question is who gets to say what's on the screen? Using the SHIFT key and the GRAPHIC key together with the rest of the keyboard you have access to 256 different characters. Look on pages 20 and 21 of A GUIDED TOUR OF PERSONAL COMPUTING for pictures of all the characters you get. (You can leave the SHIFT LOCK key up and get the lower case characters: you can depress the SHIFT LOCK and get the upper case alphabet. You can use the the same way you do on a typewriter to get the characters "on top of" the numbers and some of the symbols. You can use the GRAPHIC key to get the standard graphic characters, the ones defined by the Sorcerer. And you can use both the GRAPHIC key and the key to get some more characters.) Well, it's only fair you be able to define as many characters as the Sorcerer, so we have a compromise. 128 fixed characters (Standard ASCII) and 128 programmable. The compromise is this:
Since the keyboard needed to be labeled and most of the people in the world relate to typewriters, the Sorcerer selected for its own use the upper and lower case alphanumeric character set plus enough symbols to make up the complete Standard ASCII set; you can't change the first 128 characters (ASCII codes 0 to 127).
The Sorcerer has left completely undefined 64 of the characters; they print on the screen as "garbage" until you define their appearance. Since there was room on the keyboard tops, the Monitor arbitrarily assigned useful symbols to the first 64 of the 128 characters (ASCII codes 128 to 191 ) reserved for graphics; you can change those if you want. You, too, have control of 128 characters (ASCII codes 128 to 255) and if you don't like the Sorcerer's selection, you may change them, even into another language; after all, they don't have to be graphic symbols.
You can program your Sorcerer to use special graphic characters that you design yourself. If you want to store or print information in Russian, Arabic. Hebrew or Greek, your Sorcerer can use those alphabets; if you just want to use a graphic symbol that is not in the standard keyboard graphic set, you can do that too.
There are two ways of defining your own characters.
Each character of the group referred to as user-defined graphics (those with ASCII numbers 192 to 255) is stored in eight successive memory addresses in the memory block FE00 to FFFF (hexadecimal). These are the characters that you print on the screen by typing a key while holding down both the GRAPHIC key and the SHIFT key. For example, the first of these characters (ASCII 192, the one "under" the 1 key on the main keyboard), uses FE00 TO FE07. So first you have to figure, out which eight addresses go with the key in which you want to store your new character. (See Figures 1 and 2.)
Your character will be represented as an 8 x 8 array of dots and blanks, so get out a pencil and paper and work out the representation. Quarter-inch grid graph paper is useful here. Each eight-place row of this array will fit in one of the eight addresses of your character's key; the top line goes into the first address, the next line goes into the second, and so on.
Example:
One way to represent the Greek letter omega is:
Now take each line of your array, and change it into a two-character code in this way: First split the eight-place line in two. Then convert each of these two four-place lines into hexadecimal code with the following table:
The eight lines of our letter omega are:
What you have just done is to consider each eight-place line of your character as an eight-digit binary number (white dots are 1s and blanks are 0s), and rewrite that number in hexadecimal notation. So you now have a two-digit hexadecimal number for each of the eight lines of your new character; you must now get these numbers into the right memory locations that belong to your character's key.
Get into the Power-On Monitor by giving the command BYE (leave the ROM PAC in place). Then give the Monitor command EN XXXX (where XXXX is the first memory address of the desired key). For example, the first address of the 1 key on the main keyboard is FE00, so the proper command for that key is EN FE00. The Sorcerer responds with the address you gave it, followed by a colon.
Example:
You type: EN FE00
Sorcerer replies: FE00:_
Type in the two-digit hexadecimal code of your character's first line, and continue through eight lines. After you have entered all eight lines of your character into memory, type a slash (/) and hit RETURN. It looks like this for the omega:
FE00: 38 44 82 82 44 28 EE 00 /
If you don't enter the slash, and hit RETURN, the Sorcerer gives you the address of the first memory location for the next key on the keyboard. You may continue entering bytes (each two-digit hexadecimal code is eight bits or one byte) for further characters that you wish to define.
The new character you defined is now stored in the Sorcerer. Just press GRAPHIC and SHIFT and your character's key, and your new graphic appears on the screen.
Your special graphic characters normally live in memory addresses FE00 to FFFF. Addresses FC00 to FDFF contain the standard graphic characters; these are the characters you get using the GRAPHIC key, but not the SHIFT. You can put your own characters into these addresses if you wish; the procedure is the same as above. The Sorcerer still responds to the one-key BASIC command for your character's key (see Appendix E).
Get back into Standard BASIC with the Monitor command PP. In early versions of Standard BASIC, when you use the CLEAR key or PRINT CHR$(12) to clear the screen all of the standard graphics characters that you have defined (those with ASCII numbers 128 to 191) revert to those originally defined by the Sorcerer. The top 64 (those with ASCII numbers 192 to 255) remain the same as you defined them. For this reason, unless you need more than 64 characters, you should use the top 64 (those starting at FE00 hex). When you turn off the Sorcerer's power, or hit RESET, all your user-defined characters are lost. To save them for future use, pass to the Power-On Monitor and save the contents of the characters memory addresses on cassette, using the Monitor command SA. You can load the characters back into memory from the tape using the Monitor command LO.
Example:
SA CHARS FE00 FFFF
saves the set of characters with ASCII numbers 192 to 255 that you have defined on tape unit #1 under the name of CHARS. (If you don't specify the tape unit, your characters are saved automatically on unit #1.)
LO CHARS
loads the set of characters that you called CHARS from tape unit #1 into the Sorcerer's memory. (As before, if you don't specify the unit number, it defaults to #1.)
Another way to do this is to define them as part of a program subroutine using decimal code and POKEs.
Just as you can POKE characters into the screen, you can POKE the codes for those characters into the part of RAM where the characters live. You can see from Figure 2 that address FE00 hex is equivalent to -512 decimal.
Here is a program that converts hexadecimal addresses to decimal. Notice that memory addresses above 32768 decimal (8000 hex) are expressed as negative numbers by subtracting 65536 from them. (These are required for POKE and PEEK, see Appendix B.)
10 REM PROGRAM TO CONVERT HEXADECIMAL ADDRESSES TO DECIMAL
20 K=0
30 INPUT "HEXADECIMAL NUMBER";A$
40 IF LEN(A$)>0 AND LEN(A$)<5 THEN 60
50 PRINT "WRONG NUMBER OF DIGITS":GOTO 20
60 FOR X=1 TO LEN(A$)
70 A(X)=0
80 B$=MID$(A$,X,1)
90 A(X)=ASC(B$)
100 IF (A(X)>47 AND A(X)<58) OR (A(X)>64 AND A(X)<71) THEN 120
110 PRINT A$;" IS NOT A HEXADECIMAL NUMBER":GOTO 20
120 IF A(X)>57 THEN A(X)=A(X)-7
130 A(X)=A(X)-48:REM CHANGE ASCII CODE INTO CORRECT DECIMAL
140 K=K*16+A(X):REM MULTIPLY TOTAL BY 16 AND ADD NEXT DIGIT
150 NEXT X
160 IF K>32768 THEN K=K-65536
170 PRINT
180 PRINT A$;" hex = ";K;"decimal"
190 PRINT
200 INPUT "TRY AGAIN (Y/N)";C$
210 IF LEFT$(C$,1)="N" THEN END
220 PRINT
230 GOTO 20
Change each of the eight two-digit hex codes that define the character into a decimal number. (It will always be a number from 0 to 255. Two digit hex codes run from 00 to FF. FF hex is 255 decimal.)
Example:
10 FOR X=0 TO 7
20 READ Y
30 POKE -512+X,Y
40 NEXT X
50 DATA
Now try pressing the GRAPHIC key and the SHIFT key together with the 1 see what you get.
Here is the Greek alphabet (upper case)
10 PRINT CHR$(12)
20 PRINT:PRINT:PRINT
30 REM THIS SECTION LOADS THE CHARACTERS INTO USER GRAPHICS
40 FOR X=-128 TO -41
50 READ Y
60 POKE X,Y
70 NEXT X
80 PRINT "HERE ARE THOSE LETTERS THAT DIFFER FROM OURS:"
90 PRINT:PRINT
100 FOR Z=240 TO 250
110 PRINT CHR$(Z);" ";
120 NEXT Z
130 PRINT:PRINT:PRINT:PRINT
140 PRINT "HERE IS THE ENTIRE GREEK ALPHABET:"
150 PRINT:PRINT
160 FOR W=1 TO 24
170 READ V
180 PRINT CHR$(V);" ";
190 NEXT W
200 DATA 124, 68, 64, 64, 64, 64, 64, 0:REM GAMMA
210 DATA 16, 16, 40, 40, 68, 68, 254, 0:REM DELTA
220 DATA 56, 68, 130, 186, 130, 68, 56, 0:REM THETA
230 DATA 16, 16, 40, 40, 68, 68, 198, 0:REM LAMBDA
240 DATA 254, 0, 0, 56, 0, 0, 245, 0:REM XI
250 DATA 254, 68, 68, 68, 68, 68, 68, 0:REM PI
260 DATA 252, 66, 32, 16, 32, 66, 252, 0:REM SIGMA
270 DATA 68, 170, 146, 16, 16, 16, 16, 0:REM UPSILON
280 DATA 16, 124, 146, 146, 124, 16, 16, 0:REM PHI
290 DATA 16, 146, 146, 84, 56, 16, 16, 0:REM PSI
300 DATA 56, 68, 130, 130, 68, 40, 238, 0:REM OMEGA
310 REM THESE ARE THE ASCII NUMBERS OF OUR GREEK ALPHABET
320 DATA 65, 66, 240, 241, 69, 90, 72, 242, 73, 75, 243, 77, 78, 244
330 DATA 79, 245, 80, 246, 84, 247, 248, 88, 249, 250, 251
The function USR allows a BASIC program to call a machine language subroutine. One format for the call is:
LET <variable>=USR(X)
Although the USR function calls a machine language subroutine, BASIC treats it as a function, so it must have an argument (the number within the parentheses). Any number in the range -32768 to 32767 will do. The <variable> may change when the USR function is called, so you must use a variable that occurs nowhere else in the program.
Since USR is a function, it may be used in other ways, such as IF USR(3) =..., etc. At 1BF hex is a four-byte floating point representation of the USR function's argument. The machine language subroutine has the option of changing this value because it will be used as the function value on return. For more on this, see the SOFTWARE MANUAL.
Of course, to use the USR function you must know Z80 assembly language,
When Standard BASIC first takes control of the Sorcerer, it writes the machine code C3 (hexadecimal) into memory address 0103 hex (259 decimal). This is the first byte of a three-byte jump instruction. The other two bytes, addresses 0104 and 0105 hex (260 and 261 decimal), contain the address to which to jump. Using the POKE command, you load the starting address of your machine language subroutine into 0104 and 0105 hex before calling the USR function. The low-order byte comes first and the high-order byte second.
(Any hexadecimal address, XXYY, consists of two bytes, XX and YY. XX is called the high-order byte and YY the low-order byte. Each byte is a two-digit hexadecimal number in the range 00 to FF, so any address from 0000 to FFFF may be represented by four hex digits. The Sorcerer's CPU can handle all addresses from 0000 hex to FFFF hex/65535 decimal.) For example, to load address 0080 use the 80 byte first and the 00 byte second. Remember that you must use decimal notation with the POKE command.
You have to be careful where you POKE data during execution of a BASIC program, or you may kill your program or BASIC's work area, and you'll have to hit RESET and start again). There are certain safe areas into which you can POKE or where you can locate a machine language subroutine that you call with the USR function, The area from 80 to FF hexadecimal (128 to 255 decimal) is one of the safe areas, there are others. If, for instance, you tried to POKE into the area starting at 100 hex, you might very well run into your program.
Standard BASIC has its own stack, separate from the Monitor stack. So long as your USR routine maintains stack integrity, a Z80 return instruction (RET) returns control to BASIC.
Here is a program that loads a machine language routine into the safe area with POKE commands and then executes that routine with the USR function. The program first examines the contents of the area with the PEEK function, and then confirms that the machine language subroutine has been loaded. This program displays the entire 256-character ASCII set in the center of your screen, one at a time.
10 PRINT CHR$(12)
20 FOR X=128 TO 151:PRINT PEEK(X);:NEXT
30 PRINT
40 FOR X=1 TO 24:READ A:POKE X+127,A:NEXT
50 FOR X=128 TO 151:PRINT PEEK(X);:NEXT
60 REM LOAD STARTING ADDRESS OF USR ROUTINE
61 REM (0080 HEX, WHOSE TWO BYTES ARE 00 AND 80 HEX, OR
62 REM 0 AND 128 DECIMAL) INTO ADDRESSES 104 AND 105 HEX
63 REM (260 AND 261 DECIMAL)
70 POKE 260,128:REM POKE LOW-ORDER BYTE INTO FIRST ADDRESS
80 POKE 261,0:REM POKE HIGH ORDER BYTE INTO SECOND ADDRESS
90 Z=USR(0)
100 PRINT:PRINT "DONE"
110 DATA 33, 31, 244, 175, 119, 205, 140, 0, 60
120 DATA 32, 249, 201, 71, 17, 0, 0, 19, 122, 254
130 DATA 31
140 DATA 32, 250, 120, 201
Notes:
Line Comment
10 This instruction clears the screen by printing
an ASCII form-feed (CTRL L). This does
the same thing as the CLEAR key.
20 Prints the contents (in decimal numbers) of
addresses 0080 hex to 0097 hex (128 to 151)
decimal).
40 Reads the 24 machine language instructions
(note that they must be expressed in decimal
form) from the data statements and loads them
into addresses 0080 to 0097 hex.
50 Same as 20. Confirms that the code has loaded.
70, 80 Puts 0080 hex (128 decimal; the location to
jump to) into addresses 0104 and 0105 hex (260
and 261 decimal). The low-order byte (80 hex =
128 decimal) goes first, and then the high-order
byte (00 hex = 0 decimal).
90 Calls the USR function with a variable not used
elsewhere in the program, and a "dummy" argument
of 0. This executes the machine language program.
100 Control is returned to BASIC after the machine
language routine.
110-140 The machine language instructions (in decimal).
130 This instruction governs the time delay. To slow
down the appearance of the characters on the screen,
increase this number (to a maximum of 255); to speed
up, decrease.
Here are the Z80 machine-language and assembly-language versions of the routine:
Addr Code Instruction
(hex) (hex) Op code Operand
0080 ORG 0080H ;start at loc 80 hex
0080 21 1F F4 LD HL,0F41FH ;screen address F41F
0083 ;(15th row, 32d col)
0083 AF XOR A ;start character at 0
0084 77 LOOP: LD (HL),A ;put char on screen
0085 CD 8C 00 CALL DELAY ;wait
0088 3C INC A ;next char
0089 20 F9 JR NZ,LOOP-$ ;continue 256 chars
008B C9 RET ;done,return
008C 47 DELAY: LD B,A ;save A
008D 11 00 00 LD DE,0000H ;init delay value
0090 13 DELAY1: INC DE ;waste time
0091 7A LD A,D
0092 FE 1F CP 1FH ;are we done?
0094 20 FA JR NZ,DELAY1-$ ;no,wait some more
0096 78 LD A,B ;yes,restore A
0097 C9 RET ;return to "LOOP" ;caller
Decimal equivalents are added here, so you can see where the POKE instructions came from:
Addr Addr Code Code Instruction
(hex) (dec) (hex) (dec) Op Code Operand
0080 ORG 0080H
0080 128 21 1F F4 33 31 244 LD HL,0F41FH
0083 131 AF 175 XOR A
0084 132 77 119 LOOP LD (HL),A
0085 133 CD 8C 00 205 140 0 CALL DELAY
0088 136 3C 60 INC A
0089 137 20 F9 32 249 JR NZ,LOOP-$
008B 139 C9 201 RET
008C 140 47 71 DELAY LD B,A
008D 141 11 00 00 17 0 0 LD DE,0000H
0090 144 13 19 DELAY1 INC DE
0091 145 7A 122 LD A,D
0092 146 FE 1F 254 31 CP 1FH
0094 148 20 FA 32 250 JR NZ,DELAY1-$
0096 150 78 120 LD A,B
0097 151 C9 201 RET
You will find more information about the USR function in the Sorcerer Software Manual (DP 5008) and the Sorcerer Technical Manual (DP5003).
You may also use POKE statements to define your own special characters, and to place characters on the screen in various positions. Instead of going into the monitor and using the EN statement, use POKE statements. To put a character on the screen, place the ASCII number of that character into the corresponding screen position address. Screen RAM lives in addresses F080 to F7FF hex (equivalent to -3968 to -2049 decimal). The four corners of the screen are F080, F0BF, F7C0 and F7FF hex (equivalent to -3968, -3905, -2112 and -2049 decimal). Here is a program that prints random dots all over the screen, in all possible positions. Each character resides in an 8 x 8 rnatrix, each defined by eight addresses. The program first creates 64 characters, each with one dot randomly placed in one of the 64 possible positions, and then places each character in a random position on the screen. The process repeats continuously. To stop the program, type CTRL C.
10 F0R Z=-3968 TO -2049:POKE Z,32:NEXT
20 FOR Y=0 TO 63
30 FOR X=1 TO 8
40 POKE Y*8+X-513,0
50 NEXT X
60 POKE INT(RND(1)*8)-513+8*Y,2^(INT(RND(1)*8))
70 POKE INT(RND(1)*1920)-3968,192+Y
80 NEXT Y
90 G0TO 20
Notes:
Line Comment
10 POKE Z,32 is equivalent to POKE Z,ASC(" ").
You could clear the screen with the CLEAR key
or the statement, PRINT CHR$(12). Both of those
have, in early versions of Standard BASIC, the
drawback of losing the values of any user-defined
characters that replace those defined by the Sorcerer
(that is, those with ASCII numbers 128 to 191 ). Both
also leave the cursor on the screen. This routine leaves
a completely clear screen. (You could erase the screen
from the bottom to top by substituting FOR Z=-2049 TO -3968 STEP -1.)
ASCII 32 is the space. You could fill the screen with any
other character by Substituting its ASCII number for 32.
20 For each of the 64 top ASCII characters (those
from ASCII 192 to 255).
30-50 Creates a blank character.
60 Puts one dot somewhere randomly in the grid. The
addresses for these characters begin at -512
decimal. The number defining one dot is represented
(in decimal) by a power of 2. (The decimal equivalents
of the information in Table 1.)
70 Randomly places the character somewhere in one of the
1920 screen locations (starting at -3968 decimal).
90 After characters 192 to 255 are all printed, the entire
process is repeated.
Have you ever wondered how things move in video games? It's not done by the kind of animation used in films. A character (or blocks of characters for large images) prints on the screen and shifts over a position while a blank is printed on its previous position. If you know the addresses of all the positions on the screen, you can POKE characters anywhere on the screen.
Here are three "bouncing ball" programs. They are rough, but they will give you the general idea of what happens in video games. The third version attempts to move the ball more smoothly by making transition images. You can combine them to have the ball go more directions than one in one program.
BALL 1
10 PRINT CHR$(12)
20 POKE -3904,32:REM REMOVES CURSOR FROM SCREEN
30 FOR X=-3072 TO -3009
40 POKE X,132:REM SORCERER PREDEFINED BALL CHARACTER
45 REM (ASCII CODE 84H; GRAPHIC: 5)
50 POKE X-1,32
60 NEXT
70 FOR X=-3009 TO -3072 STEP -1
80 POKE X,132
90 POKE X+1,32
100 NEXT
110 GOTO 30
BALL 2
10 PRINT CHR$(12)
20 POKE -3904,32
30 FOR X=-2112 TO -3939 STEP -63
40 POKE X,132
50 POKE X+126,32
60 WAIT 254,16:REM SEE APPENDIX B
70 POKE X+63,32
80 POKE X,32
90 NEXT
100 FOR X=-3939 TO -2112 STEP 63
110 POKE X,13
120 POKE X-126,32
130 WAIT 254,16
140 POKE X-63,32
150 POKE X,32
160 NEXT
170 GOTO 30
BALL 3
10 PRINT CHR$(12)
20 POKE -3904,32
30 GOSUB 210
40 FOR X=-3072 TO -3010
50 POKE X,132
60 POKE X,193
70 POKE X+1,192
80 POKE X-1,32
90 POKE X+1,132
100 POKE X,32
110 NEXT
120 FOR X=-3009 TO -3071 STEP -1
130 POKE X,132
140 POKE X,192
150 POKE X-1,193
160 POKE X+1,32
170 POKE X-1,132
180 POKE X,32
190 NEXT
200 GOTO 40
205 REM DEFINES TRANSITION CHARACTERS
210 FOR X=0 TO 15
220 READ A
230 POKE -512+X,A:REM CHARACTERS 192 AND 193
240 NEXT X
250 DATA 0,192,224,240,240,224,192,0,0,3,7,15,15,7,3,0
260 RETURN
TABLE 2: FIRST ADDRESSES IN EACH LINE OF VIDEO
LINE # FIRST ADDRESS FIRST ADDRESS
IN HEX IN DECIMAL*
1 F080 -3968
2 F0C0 -3904
3 F100 -3840
4 F140 -3776
5 F180 -3712
6 FC00 -3648
7 F200 -3584
8 F240 -3520
9 F280 -3456
10 F2C0 -3392
11 F300 -3328
12 F340 -3264
13 F380 -3200
14 F3C0 -3136
15 F400 -3072
16 F440 -3008
17 F480 -2944
18 F4C0 -2880
19 F500 -2816
20 F540 -2752
21 F580 -2688
22 F5C0 -2624
23 F600 -2560
24 F640 -2496
25 F680 -2432
26 F6C0 -2368
27 F700 -2304
28 F740 -2240
29 F780 -2176
30 F7C0 -2112
*These are not the decimal equivalents of the hex numbers (F038=61568 and F0C0=61632, for instance), but the decimal POKE/PEEK addresses.
You have seen how to poke characters into different places on the screen. You may wish to move the cursor various directions, to print at different places, or to format your output. You can use PRINT statements to move the cursor. What you print are the control characters, some of those in the ASCII range 0 to 31.
Press the CTRL key and the HOME key on the numeric keyboard and watch what happens. Now hit the RETURN several times and then type ten letter As to move the cursor somewhere in the middle of the screen. Type CTRL W, CTRL A, CTRL S, CTRL Z and watch what happens to the cursor. (You don't hit after each of these.) Try CTRL Q. Notice that the same thing happens as with CTRL HOME. Try the CTRL key with the up arrow on the numeric keyboard. It does the same as CTRL W. The CTRL key with the right-arrow, left-arrow and down arrow does the same as CTRL S, CTRL A, and CTRL Z.
NOTE
The SHIFT key gives the same results when used with the arrows and the HOME key on the numeric pad as the CTRL key.
While we're talking about control functions, notice that CTRL U does the same thing as the @ key, and that CTRL H works the same as SHIFT RUB .
You may use these as part of PRINT statements, but whenever you LIST the program, these CTRL functions "do their thing." You must surround them with quotes, just as you must to print any other literal.
You type this:
10 PRINT "XCTRL XX"
This is how it appears on the screen:
X"
10 PRINT "X
That is also what you get whenever you LIST. If you try to enter this:
10 PRINT CLEAR
pressing the key, not typing the word "CLEAR"
what you have on the screen disappears. When you LIST, you never see that statement, nor do you see any longer those preceding it.
You can get around this by using CHR$.
Examples:
PRINT CHR$(1); moves the cursor one
position to the left.
PRINT CHR$(8); moves the cursor one
position to the left
and erases the character
at the cursor position.
PRINT CHR$(19); moves the cursor one
position to the right.
PRINT CHR$(23); moves the cursor one
position up.
PRINT CHR$(10); move the cursor one
and PRINT CHR$(26); position down.
PRINT CHR$(12); erases the screen.
PRINT CHR$(13); returns the cursor to
the start of the line.
Here is a demonstration of how to start printing at the bottom of the screen and work up:
10 PRINT CHR$(12)
20 FOR X=1 TO 15:PRINT CHR$(26):NEXT
30 FOR Z=1 TO 15
40 PRINT "XXXX"CHR$(23);
50 PRINT CHR$(13);
60 PRINT "OOOO"CHR$(23);
70 PRINT CHR$(13);
80 NEXT Z
90 PRINT
100 GOTO 10