"There is no future in time travel."
YOUR SECOND GFA BASIC 3.XX MANUAL
- or -
HOW I LEARNED TO STOP WORRYING AND LOVE GFA-BASIC
PART 10
CHAPTER NINE - SCREEN OUTPUT
by Han Kempen
CLS
It's not necessary to use CLS as one of the first commands in an
interpreted program, because the interpreter executes a CLS
automatically. But it's not a bad idea to use CLS anyway, just in
case you decide to compile your program later.
PRINT
It is very important to know if PRINT will be used on the so-
called TOS-screen (no windows opened), or in a window. TOS
emulates the VT52-terminal of Digital Equipment, so if you PRINT
on the TOS-screen, the VT52-codes will be interpreted as
commands. But in a window these codes are printed as characters!
Actually I prefer to use the TOS-screen, but if you're thinking
(and programming) big you should avoid the TOS-screen and stick
to windows. Do your thing inside a window, so other
programs/accessories will not be affected. A 'CLS' on the TOS-
screen might not be a good idea after all.
In both High and Medium resolution you can PRINT 25 lines of 80
characters, but in Low resolution it's 25 lines of 40 characters
only.
Normally you can't PRINT a character at position (80,25) in High
or Medium resolution, or at (40,25) in Low resolution. Try the
following:
PRINT AT(80,25);"X";
and you will see that a linefeed is executed automatically, in
spite of the semicolon after "X". On the TOS-screen you can put a
character at this position by using the VT52-command 'wrap off':
PRINT AT(80,25);"*wX"; ! * = <Esc> (use Alternate-method)
After 'Esc w' the linefeed is suppressed. If you PRINT a string
that doesn't fit on the current line, the remaining characters
are either printed on the next line ('Esc v', the default in the
interpreter, not in a compiled program), or discarded ('Esc w').
After 'Esc w' all characters up to the first CHR$(10) or CHR$(13)
are discarded, except the very last character which is always
printed at column 80 (in High or Medium resolution).
It's impossible to PRINT characters with ASCII-code 0-31 on the
TOS-screen. However, you can print any character with:
OUT 5,code ! if necessary, use LOCATE first
After opening a window (OPENW x) the command DEFTEXT will change
size and colour of PRINTed text as well! One advantage is that
you can now PRINT in different colours on the screen.
On the TOS-screen, all PRINTed text has the same colour. The
colour is determined by VDI colour-index 1 and is also used for
the Alert-box and the Fileselector. The background on the screen
is determined by VDI colour-index 0. This colour is used by the
CLS-command. Read the paragraph 'SETCOLOR and VSETCOLOR' in
chapter 20 for more information about the use of colours.
It is possible to PRINT in different colours on the TOS-screen
by using the VT52-code 'Esc b'. The background of PRINTed text
can be changed with VT52-code 'Esc c'. Use the following to
experiment:
PRINT CHR$(27);"b";CHR$(color);" Watch the letter-colour "
PRINT CHR$(27);"c";CHR$(color);" Watch the background-colour "
Use the SETCOLOR-table from the paragraph 'SETCOLOR and
VSETCOLOR' or be prepared to become very frustrated. And
remember, the VT52-codes have to be PRINTed to become effective.
Note the spaces at beginning and end of the string to emphasize
the text-colour against the background-colour.
In order to catch the eye of the user in High resolution you can
PRINT reverse on the TOS-screen:
PRINT "this is *p IMPORTANT *q" ! * = <Esc>
Enter the Escape-character in the usual way (Alternate-method).
Note again the extra space both before and after the word that
should stand out. Of course you could also use CHR$(27):
PRINT "this is ";CHR$(27);"p IMPORTANT ";CHR$(27);"q"
More difficult to read in the editor, but easier to Llist.
If you use a comma with PRINT, the cursor will jump to the next
tabulator-stop. Tab-stops are at position 1, 17, 33, 49 and 65.
Try the following to see what I mean (in High or Medium
resolution):
PRINT "1","17","33","49","65","1","17"
If you use the comma after the last tab-stop, a linefeed is
executed and the cursor jumps to the first tab-stop on the next
line.
The easiest way to use double quotes is by using double double
quotes (read this twice to make sure you understand it):
PRINT "double quotes printed the ""easy"" way"
In a DATA-line a single double quote suffices:
READ t$
PRINT t$
DATA "look Ma, "double quotes" again"
By the way, in a DATA-line you can't use a comma after a double
quote and you have to use double quotes if there are trailing
spaces:
DATA "after "double quotes" , always insert a space before
the comma"
DATA You don't need double quotes here at all.
DATA "With trailing space-characters you do need double
quotes "
LOCATE
The syntax of PRINT AT and LOCATE is now less confusing:
PRINT AT(column,line)
LOCATE column,line
In older versions of GFA-Basic it was 'LOCATE line,column'.
Check this if you run an old program and text is PRINTed on the
wrong place.
PRINT USING
I keep forgetting that it's not possible to use a dash in the
format-string of PRINT USING:
PRINT USING "VDI-index ##",i ! looks innocent enough
The dash is seen as the negative sign, but the error-message
you'll get is usually not very helpful. Precede the dash with an
underscore:
PRINT USING "VDI_-index ##",i ! should work now
PRINT TAB
Don't use PRINT TAB with a position greater than 255. Try the
following in High or Medium resolution:
FOR i=0 TO 30
PRINT TAB(i*20);i;
NEXT i
Because TAB uses one byte for the position, you get strange
results if the position is greater than 255. One way to solve
this problem is:
PRINT TAB(MOD(i*20,80));i; ! do use semicolons
You can combine TAB with PRINT AT and with PRINT USING:
PRINT AT(1,1);"1";TAB(40);"40"
PRINT TAB(40);USING "##",40
Setscreen (XBIOS 5)
With XBIOS 5 (Setscreen) it is possible to change the resolution
from Low to Medium and from Medium to Low. Unfortunately, GEM
ignores the switch, so GEM-commands (e.g. ALERT, TEXT, MOUSE) do
not work properly! But you could change from Low to Medium
resolution to show text on the TOS-screen with PRINT (and VT52-
commands). Most users will be grateful for the improved
readability of the text:
~XBIOS(5,L:-1,L:-1,1) ! switch from Low to Medium
(...) ! print text in Medium resolution
~XBIOS(5,L:-1,L:-1,0) ! and go back to Low
If you change the resolution, the VT52-emulator is automatically
initialised. You'll probably have to adjust the palette before
you can read the text without sun-glasses. Don't forget to save
and restore the old palette.
XBIOS 5 is very useful if you would like to draw on a screen
before showing it to the user. Drawing on an "invisible" screen
is indeed possible, because the operating system uses two
screens: the physical screen (visible on your monitor) and the
logical screen (usually, but not necessarily, the same as the
physical screen). All graphical (GEM-)com-mands, including the
TEXT-command, are always sent to the logical screen. But TOS will
send the first PRINT-command to the physical screen, unless
you've opened a window. That's a bug. Just send one PRINT and all
the following PRINT-commands are properly sent to the logical
screen. If the address of logical and physical screen is not the
same, you have your invisible screen. The address of the logical
screen must be a multiple of 256. You could use the invisible
screen for fluid animations:
DIM screen.2|(32255) ! reserve space for
screen.2
screen.2%=VARPTR(screen.2|(0))
screen.2%=AND(ADD(screen.2%,255),&HFFFFFF00) ! multiple of
256
screen.1%=XBIOS(2) ! physical screen
~XBIOS(5,L:screen.2%,L:-1,-1) ! invisible screen.2 is
now active
(...) ! draw on invisible
screen
SWAP screen.1%,screen.2%
VSYNC ! avoid flash
~XBIOS(5,L:screen.2%,L:screen.1%,-1) ! swap the screens
(...)
~XBIOS(5,L:XBIOS(2),L:XBIOS(2),-1) ! restore original
setting
On some ST-computers XBIOS 5 does not function properly after
installation of a RAM-disk. In that case you could change the
address of the logical screen by using the system-variable
screenpt (at &H45E):
VSYNC
SLPOKE &H45E,adr% ! system-variable screenpt
XBIOS 5 is suitable for screen-swapping on a 'regular' ST, but
will probably not work if you have installed a graphics
extension-board. In that case you should also avoid: XBIOS 2
(Physbase), 3 (Logbase), 4 (Getrez), 6 (Setpalette), 7 (Setcolor)
and 33 (Setscreen).
Animation
In the previous paragraph you could read that XBIOS 5 is
suitable for animations. There are several ways to implement an
animation, here are some ideas. The basic idea is the following:
- create object and mask
- perform first animation
- start animation-loop
1. Create a GET-string of the object that will be animated.
Sometimes the object is called a sprite, although a 'proper'
sprite is limited to 16x16 pixels (see paragraph 'SPRITE' in
chapter 20). Here we'll use the more flexible GET-string.
All pixels that do not belong to the object must have the
background colour (VDI colour-index 0). The pixels of the
object itself may have any colour(s), except 0. If the
object itself is static (the static object moves around the
screen), you'll need only one object-string, e.g.:
CLS
DEFFILL 1,1
PCIRCLE d/2,d/2,d/2 ! d = diameter of circle
GET 0,0,d,d,object$ ! black disk on white
background
If the object itself should be animated, you'll need
different object-strings for each 'frame' of the object-
animation.
2. Create a mask of the object. This is necessary because if
you simply put the object on the screen, the background will
be destroyed. The mask is needed to stamp a 'hole' in the
background that has the exact form of the object (in our
case a disk). All pixels in the mask that correspond with
the object should have the background-colour (VDI colour-
index 0). All pixels that do not correspond with the object
(in our case everything outside the disk) should have VDI
colour-index 1 (that's SETCOLOR-index 3 in Medium and 15 in
Low resolution). In our case we need:
CLS
BOUNDARY 0
DEFFILL 1,1
PBOX 0,0,d,d ! black square
DEFFILL 0,1
PCIRCLE d/2,d/2,d/2 ! stamp out white disk
GET 0,0,d,d,mask$ ! white disk on black
background
A PUT-action with object$ in the proper PUT-mode could also
be used to create the mask.
3. Prepare an invisible logical screen (as described in the
paragraph 'Setscreen') and fill with an interesting
background.
4. Determine the coordinates (x1,y1) where the object will
appear and save the background under the object:
GET x1,y1,x1+d,y1+d,back$
This is not necessary if the background is scrolling. In
that case you would first draw a completely new background
before you continue with step 5.
5. Put the mask on the invisible screen:
PUT x1,y1,mask$,1 ! mode 1
The mask has stamped out a 'hole' for the object.
6. Put the object on the invisible screen:
PUT x1,y1,object$,7 ! mode 7
All pixels outside the object (our disk) retain their
original colour.
7. Swap screens to show the result. Swapping screens with XBIOS
5 (including a VSYNC to prevent blinking) is faster than
BMOVEing the complete logical screen to the physical screen.
On the other hand, the animation-loop is simpler if you use
BMOVE (see step 8). Test both methods to determine which is
the fastest in your situation.
8. Restore the invisible screen. After swapping the two screens
the current invisible screen is the screen that a moment ago
was visible on the monitor. Unless you are going to restore
the entire background (only necessary if the background
scrolls), you'll have to restore the previous animation-
screen:
PUT x0,y0,previous.back$
Of course there is no previous animation-screen after the
first animation (step 4 to 7). You could check this in the
animation-loop, but it's easier to perform the first
animation outside the animation-loop. If you used BMOVE in
step 7 you restore the invisible logical screen (the current
animation-screen) with:
PUT x1,y1,back$
Then you would repeat the animation-loop by going to step 4.
9. Store the current coordinates of the object on the
animation-screen (now visible on the monitor) and the
background on that screen:
x0=x1
y0=y1
SWAP previous.back$,back$
10. Repeat the animation-loop: go to step 4.
Take care not to PUT anything outside the screenborders. You'll
have to check yourself because CLIP has no effect on PUT.
For a scrolling background you could restrict yourself to one
screen: what scrolls off on one side reappears on the opposite
side. A horizontal scroll-effect could be implemented with
GET/PUT or with RC_COPY. Vertical scrolls with BMOVE are faster
than horizontal scrolls (early games on the ST featured vertical
scrolling only). Another idea would be to create a long vertical
strip of several screens in MALLOCated memory and to move the
appropriate background to the invisible screen (step 4) with
BMOVE.
Font
TOS has three built-in systemfonts. The default PRINT-font for
High resolution is the 8x16 font (equals DEFTEXT ,,,13 for TEXT),
while the 8x8 font (equals DEFTEXT ,,,6) is used in Medium and
Low resolution. You can switch between these two fonts:
a$=MKI$(&HA000)+MKI$(&H2009)+MKI$(&H4E75)
adr%=VARPTR(a$)
adr%=C:adr%() ! address of font-table
{INTIN}={adr%+8} ! pointer to 8x16 systemfont
VDISYS 5,2,0,102 ! install 8x16 font as systemfont
'
a$=MKI$(&HA000)+MKI$(&H2009)+MKI$(&H4E75)
adr%=VARPTR(a$)
adr%=C:adr%() ! address of font-table
{INTIN}={adr%+4} ! pointer to 8x8 systemfont
VDISYS 5,2,0,102 ! install 8x8 font as systemfont
The third font (6x6) is used for icons, but for some reason can
not become the current systemfont. The VDI-function seems to work
only with fonts containing characters of width 8 pixels. The
function (VDI 5, Escape 102) is not officially documented by
Atari (?).
You can replace the systemfont by a font that has been created
with 'Fontkit' or 'Fontkit Plus' by Jeremy Hughes (e.g. a 4114
byte A1_xxxxx.FON file for High resolution):
' load an 8x16 A1_xxxxx.FON file (4114 bytes) here
INLINE new.font%,4114
'
adr%=L~A-22 ! V_FNT_AD
normal.font%={adr%} ! remember current
systemfont
SLPOKE adr%,new.font% ! install new font
(...) ! PRINT with new font
SLPOKE L~A-22,normal.font% ! restore original
systemfont
A font-table for a High resolution 8x16 font occupies exactly
4096 bytes (16 bytes/character, 256 characters). A FONTKIT-font
usually has a name attached at the end, that's why I reserve 4114
bytes. TOS ignores the name completely, it's only used by the
accessory FONSEL.ACC or FSWITCH4.ACC. You can load any 4096-byte
8x16 font in the INLINE-line, you don't even have to change 4114
into 4096. Although you lose 18 bytes if you don't.
The new systemfont is only used by PRINT, not by TEXT. After
installing GDOS you can load a new font for TEXT with
VST_LOAD_FONTS, but it's also possible to install a new font
without using GDOS:
' load two 8x16 fonts (A1_BAULI.FON and A1_MED.FON) here:
INLINE a1_bauli%,4184
INLINE a1_med%,4184
'
n.fonts=2 ! 2 fonts
DIM newfont.adr%(PRED(n.fonts)),newheader.adr%(PRED(n.fonts))
newfont.adr%(0)=a1_bauli% ! font no. 2
newfont.adr%(1)=a1_med% ! font no. 3
header.adr%={L~A-906} ! address of systemfont-
header
font.adr%={header.adr%+76} ! address of systemfont
FOR i=0 TO PRED(n.fonts)
newheader.adr%(i)=newfont.adr%(i)+4096 ! put header
behind font
{header.adr%+84}=newheader.adr%(i) ! address of next
header
BMOVE header.adr%,newheader.adr%(i),88 ! copy old header
WORD{newheader.adr%(i)}=i+2 ! font-number
{newheader.adr%(i)+76}=newfont.adr%(i) ! font-address
WORD{newheader.adr%(i)+66}=12 ! bit 0 in flag
header.adr%=newheader.adr%(i) ! address of font-
header
NEXT i
{header.adr%+84}=0 ! there is no next
header
After installing the two fonts, you can activate them with
DEFTEXT:
DEFTEXT ,,,,2 ! font no. 2 active (A1_BAULI)
DEFTEXT ,,,,3 ! font no. 3 active (A1_MED)
DEFTEXT ,,,,1 ! original systemfont (no. 1) active
again
Don't do this if GDOS is installed. In that case you should
install a new GEM-font the proper way with VST_LOAD_FONTS. Such
GEM-fonts have a header with all kinds of data about the font.
FONTKIT-fonts and regular 4096-byte fonts don't have a header.
That's why we had to create a header for the new fonts in the
above listing. In this case we simply copied the header of the
systemfont and made a few changes.
Procedures (CHAPTER.09)
Center CNTR_TXT
Center a text on the screen:
@center(5,40,text$) ! start at line 5; 40 characters
wide
Line longer than 40 characters are printed on the next line(s).
Char_print_at CHAR_PRINT
Print any character (also with ASCII-code 1-31) on the screen:
@char_print_at(1,10,16) ! PRINT digital '0' at (1,10)
Fastprint_init and Fastprint FASTPRNT
With an assembly-routine text is printed about four times faster
than with PRINT:
@fastprint_init
@fastprint(10,5,"Very fast") ! same as PRINT AT(10,5);
"Very fast"
This Procedure can only be used on the TOS-screen in High
resolution.
Flash_text FLASHTXT
Flash a text a few times:
@flash_text(TRUE,"attention",5) ! flash 5 times with
bell-sound
If the flag is FALSE the bell is not used.
Lin_max LIN_MAX
Change number of PRINT-lines on TOS-screen:
@lin_max(24) ! line 1-24 available, line 25
'protected'
Print_colors PRNTCLRS
Change background- and foreground(PRINT)-colours:
@print_colors("777","000",ink$,paper$) ! white letters on
black
Screen2_init, Screen2_swap and Screen2_restore SCREEN2
Install second screen as invisible logical screen (mainly for
animations):
@screen2_init(FALSE,phys%,log%) ! activate invisible
screen
(...) ! draw on invisible
logical screen
@screen2_swap(FALSE,phys%,log%) ! swap physical and
logical screen
(...)
@screen2_restore ! restore original
screens
If the flag is TRUE, the logical screen is copied to the
physical screen.
Scroll_print SCRL_PRT
Scroll text in box with (jerky) PRINT-command:
@scroll_print("Scroll this text",5,10,8)
The text is scrolled at position (5,10) in a rectangle with a
width of 8 characters.
Scroll_text SCRL_TXT
Scroll text in box with (fluid) TEXT-command:
@scroll_text("Scroll this text",50,100,80)
The text is scrolled in a rectangle at coordinates (50,100) with
a width of 80 pixels.
Sound_print SOUNDPRT
A scale is played while a (short) text is PRINTed:
@sound_print("Listen while this is PRINTed")
Systemfont_8x16 and Systemfont_8x8 SYSTFONT
Activate 8x16 or 8x8 systemfont for PRINT:
@systemfont_8x16
@systemfont_8x8
Systemfont_new FONT_NEW
Change the systemfont for PRINTing on the TOS-screen in High
resolution:
' Load font A1_DIGT.FON in INLINE-line:
INLINE a1_digt%,4114
@systemfont_new(TRUE) ! install new systemfont
(...) ! do some PRINTing
@systemfont_new(FALSE) ! restore original systemfont
Textfont_init TEXTFONT
Install one or more fonts for use with TEXT:
' Load font A1_DIGT.FON in INLINE-line:
INLINE a1_digt%,4114
@textfont_init
You'll have to enter the correct number of new fonts and the
INLINE-addresses of the fonts in the Procedure yourself.
Vert_print VERT_PRT
PRINT a string vertically:
@vert_print(10,1,"Vertical") ! at position (10,1)
Wrap WRAP
Switch 'Wrap' on or off:
@wrap(TRUE) ! Wrap on
Not very useful, except for PRINTing at position (80,25) after
switching 'Wrap' off.
Wrap_word WRAPWORD
This Procedure wraps long text-lines, but is far superior to the
Procedure Wrap as it wraps only whole words (after a space or a
hyphen):
@wrap_word(10,10,40,text$) ! start at (10,10), 40
characters wide
Of course you can also use the entire screen:
@wrap_word(1,line,80,text$) ! useful in text-editor
Functions (CHAPTER.09)
All Functions must be PRINTed. Use a semicolon to prevent an
unwanted linefeed.
Center$ [Standard Function] CENTER
Returns a text centered:
PRINT @center$("This will be centered"); ! end with
semicolon
This is a Standard Function (see paragraph 'The Standard' in
chapter 'INTRODUCTION').
Clr_line$ (VT52) \VT52\CLR_LINE
Clears a line completely:
PRINT @clr_line$(10); ! clear line 10
This Function uses VT52-commands, so it can only be used on the
TOS-screen.
Clr_lines_from$ (VT52) \VT52\CLR_LIFR
Clears all lines to last line of screen:
PRINT @clr_lines_from$(10); ! clear line 10 - 25
Clr_lines_to$ (VT52) \VT52\CLR_LITO
Clears all lines above (and inluding) the given one:
PRINT @clr_lines_to$(10); ! clear line 1 - 10
Clr_rest_line$ (VT52) \VT52\CL_RLINE
Clear rest of current line from cursor-position:
LOCATE 10,5
PRINT @clr_rest_line$; ! clear 10 - 80 on line 5
Clr_rest_screen$ (VT52) \VT52\CL_RSCRN
Clear screen from current cursor-position:
PRINT @clr_rest_screen$;
Flush_right$ FLUSH_RI
Print text flushed right:
PRINT @flush_right$("Flush me to the right");
Print_colors$ (VT52) \VT52\PRTCOLRS
Use ink&- and paper&-colour for printing text:
PRINT @print_colors$(" Red ink on green paper ",red,green);
Of course the variables red& and green& must be defined. In my
programs they are Standard Globals anyway, but that might not be
your cup of tea. You can use VDI colour-indices because the
Function converts these to SETCOLOR-indices through the Standard-
array setcolor&().
Print_ink$ (VT52) [Standard Function] \VT52\PRINTINK
Change the ink-colour for PRINTing:
PRINT @print_ink$(red);
PRINT "These letters are now red"
Print_paper$ (VT52) [Standard Function] \VT52\PRINTPAP
Change the paper-colour (background) for PRINTing:
PRINT @print_paper$(green);
PRINT " This background is now green "
Rev$ (VT52) [Standard Function] \VT52\REV
Return characters reversed for printing on High resolution
screen:
PRINT @rev$(" This is reverse ");
Disclaimer
The text of the articles is identical to the originals like they appeared
in old ST NEWS issues. Please take into consideration that the author(s)
was (were) a lot younger and less responsible back then. So bad jokes,
bad English, youthful arrogance, insults, bravura, over-crediting and
tastelessness should be taken with at least a grain of salt. Any contact
and/or payment information, as well as deadlines/release dates of any
kind should be regarded as outdated. Due to the fact that these pages are
not actually contained in an Atari executable here, references to scroll
texts, featured demo screens and hidden articles may also be irrelevant.