9. SCREEN OUTPUT 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"; ! * = (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 (page 20-2) 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" ! * = 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 (see page 2-6). 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', page 9-4) 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 (page 9-4) 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 (page 9-2) CHARPRNT 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 (page 9-2) PRNTCLRS Change background- and foreground(PRINT)-colours: @print_colors("777","000",ink$,paper$) ! white letters on black Screen2_init, Screen2_swap and Screen2_restore (page 9-4) 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 (page 9-7) SYSTFONT Activate 8x16 or 8x8 systemfont for PRINT: @systemfont_8x16 @systemfont_8x8 Systemfont_new (page 9-7) 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 (page 9-8) 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 (page 9-1) 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', page 22). 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$ (page 9-2) (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$ (page 9-2) (VT52) [Standard Function] \VT52\PRINTINK Change the ink-colour for PRINTing: PRINT @print_ink$(red); PRINT "These letters are now red" Print_paper$ (page 9-2) (VT52) [Standard Function] \VT52\PRINTPAP Change the paper-colour (background) for PRINTing: PRINT @print_paper$(green); PRINT " This background is now green " Rev$ (page 9-2) (VT52) [Standard Function] \VT52\REV Return characters reversed for printing on High resolution screen: PRINT @rev$(" This is reverse ");