20. GRAPHICS Resolutions The ST(E) can use three resolutions: High, Medium or Low. Here is an overview: High Medium Low width (pixels) 640 640 320 x-coordinate 0-639 0-639 0-319 height (pixels) 400 200 200 y-coordinate 0-399 0-199 0-199 bit-planes 1 2 4 colours 2 4 16 colour-index 0-1 0-3 0-15 scanline (bytes) 80 160 160 scanlines 400 200 200 The number of bit-planes tells you how many bits are used to determine the colour of one pixel. With one bit you can have colour-index &X0 or &X1, i.e. two colours (black and white). With two bits you have four colours: &X00, &X01, &X10 and &X11. And with four bits 16 colours. The colour-index points to a table of colour-registers ('palette'), so the actual colour of a pixel is determined by the colour-index and the palette. To make the life of programmers more exciting, there are two different colour-index tables (see next paragraph). The current number of bit-planes can be determined in two ways: bit.planes&=INT{L~A} ! uses Line-A bit.planes&=LOG(WORK_OUT(13))/LOG(2) ! alternative WORK_OUT(13) holds the number of colours that can be used on the screen. For High resolution it's easy to understand how the colour-index of a pixel is coded in RAM. Screen-RAM starts at memory-address XBIOS(2) (Physbase) for the physical screen and at XBIOS(3) (Logbase) for the logical screen. In the default situation physical and logical screen start at the same address. The 'screen-unit' is one word (16 bits). The first pixel of the screen at (0,0) is stored in bit 15 of the first unit of screen-RAM, the second pixel (1,0) in bit 14, etc. Bit 15 of the second unit determines the colour-index of (16,0), etc. For Medium resolution the screen-unit is two consecutive words (32 bits). The colour-index is stored in two bits of course, but the bits lie 16 bits apart. The first pixel of the screen (0,0) is stored in bit 31 and bit 15 of the first unit. The second pixel (1,0) in bit 30 and 14, etc. Bit 31 and 15 of the second unit determine the colour-index of (16,0), etc. You guessed right, for Low resolution the screen-unit has to be four consecutive words (64 bits). The bits 63/47/31/15 of the first unit determine the colour-index of (0,0) and bits 62/46/30/14 of (1,0). Bits 63/47/31/15 of the second unit determine the colour-index of (16,0), etc. A horizontal line from left to right on the monitor is called a scanline. The number of scanlines is therefore equal to the height of the screen in pixels. The length of a scanline in screen-RAM is determined by the width of the screen in pixels and the number of bit-planes. In High resolution we have 640 pixels and with 1 bit for one pixel that's 80 bytes. In Medium resolution we also have 640 pixels, but with 2 bits for one pixel, or 160 bytes. And in Low resolution there are 320 pixels with 4 bits for one pixel, so we get 160 bytes too. INT{L~A+2} also gives the scanline-width. Perhaps you find all this a bit complicated. Don't worry, you only need to understand about scanlines and bit-planes if you're going to use BMOVE or the Line-A BITBLT-command. In the paragraph 'Setscreen (XBIOS 5)' in chapter 9, I already pointed out that resolution switching is possible, but generally should be avoided. In two cases a resolution switch seems useful: (1) to show a Low-resolution picture from a program running in Medium and (2) to show text in Medium resolution from a program running in Low. If you switched from Low to Medium resolution, graphic commands are restricted to 'Low' coordinates, i.e. the left part of the Medium screen. But you can RC_COPY from the left half to the right half, so it is possible to draw on the full Medium screen after all. SETCOLOR and VSETCOLOR There are several ways to determine the colour that will be used by certain commands: COLOR colour ! colour used by most graphic commands DEFFILL colour ! colour used by (POLY)FILL, PBOX, PCIRCLE, PELLIPSE DEFMARK colour ! colour used by POLYMARK DEFTEXT colour ! colour used by TEXT With the commands COLOR, DEFFILL, DEFMARK and DEFTEXT you choose the colour with a VDI colour-index (0-3 in Medium resolution, 0-15 in Low resolution). You can change the colour that's assigned to a VDI colour- index with SETCOLOR, but unfortunately SETCOLOR uses a different table: VDI colour-index : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SETCOLOR (Low rez) : 0 15 1 2 4 6 3 5 7 8 9 10 12 14 11 13 SETCOLOR (Med rez) : 0 3 1 2 From this table it follows you would have to use SETCOLOR-index 2 to change VDI colour-index 3: SETCOLOR 2,r,g,b COLOR 3 ! use colour &Hrgb for graphics This is not a bug, but a consequence of two different colour-tables that are used by GEM and GEMDOS. By the way, all Line-A commands use the SETCOLOR-table (hardware registers)! At first sight VSETCOLOR looks like an ideal solution to this problem: VSETCOLOR index,r,g,b COLOR index ! use colour &Hrgb for graphics This index is the VDI colour-index, so you would use 'VSETCOLOR 2,r,g,b' in order to change VDI colour-index 2. Sounds quite logical, doesn't it? Unfortunately VSETCOLOR has its own peculiarities, as you can read in the next paragraph ('VSETCOLOR-bug'). In High resolution you can invert the screen-colours with: VSETCOLOR 0,0 ! reverse High-screen (black background) VSETCOLOR 1,0 ! normal High-screen (black letters) An inverted screen is perhaps slightly less suitable for text, but graphics look superb. In Medium resolution text definitely looks better on a reverse screen: VSETCOLOR 0,0,0,0 ! black background VSETCOLOR 1,7,7,7 ! white letters Yellow letters on a black background also look nice in Medium resolution. VDI colour-index 0 (also SETCOLOR-index 0) determines the colour of the background. This index also determines the colour of the border on your colour monitor. This means you can change the border-colour, although you can't draw or PRINT on the border of your colour monitor. VSETCOLOR 0,r,g,b ! change colour of background The colour of all PRINTed text on the TOS-screen is determined by VDI colour-index 1, unless you use the 'Esc b' command (read the paragraph 'PRINT' in chapter 9 again if your long-term memory is too short): VSETCOLOR 1,r,g,b ! change colour of all PRINTed text The SETCOLOR-index of the the PRINT-colour (VDI colour-index 1) is easy to remember, because all bits have to be 1. Therefore we have SETCOLOR-index &X1 (decimal 1) in High resolution, &X11 (decimal 3) in Medium and &X1111 (decimal 15) in Low. VSETCOLOR-bug If you like, you can use the hexadecimal 3-nibble mix-value with VSETCOLOR instead of the three separate values: VSETCOLOR index,&Hrgb ! hexadecimal mix-value VSETCOLOR index,r,g,b ! three separate values But you won't like it at all, because the hexadecimal mix-value is corrupted by GFA-Basic: the r- and b-nibble are swapped. You could correct this yourself, but I can't recommend this: VSETCOLOR index,&Hbgr ! becomes &Hrgb (correct the GFA-bug) GFA-Basic 3.5 (for the STE) has another surprise if you use VSETCOLOR on a regular ST (not an STE). The value of the three colour-bytes is halved: VSETCOLOR 0,7,6,4 ! &H764 on a STE, but becomes &H332 on an ST Perhaps this is not a bug after all. On an STE you can use values 0-15 for each colour-nibble (16*16*16 = 4096 colours possible), while the ST allows values 0-7 (for 8*8*8 = 512 different colours). But it makes life rather difficult if you write a program that's supposed to run on any ST/STE with any GFA-Basic version (3.0x or 3.5). I don't even want to think about the TT. Perhaps it's better to return to the despised SETCOLOR-command in spite of the confusing colour-table. SETCOLOR works fine on my ST, and the hexadecimal mix-value also behaves properly: SETCOLOR 0,7,6,4 ! stays &H764 on my ST (what happens on an STE?) SETCOLOR 0,&H764 ! stays &H764 also (no unwanted nibble-swapping) Palette Before changing colours, you should always save the current palette. And do restore the old palette before the user exits the program. I really hate programs that return to a pink or yellow desktop. You can store the palette either in an integer array or in a string. In both cases you need XBIOS 7 (Setcolor): DIM palet%(15) FOR i=0 TO 15 palet%(i)=XBIOS(7,i,-1) ! array-method NEXT i ' FOR i=0 TO 15 palet$=palet$+MKI$(XBIOS(7,i,-1)) ! string-method NEXT i The string-method is compatible with Degas. Restore (or install) a palette with XBIOS 7 for the array-method or with XBIOS 6 (Setpalette) for the string-method: FOR i=0 TO 15 ~XBIOS(7,i,palet%(i)) ! array-method NEXT i ' ~XBIOS(6,L:V:palet$) ! string-method You can examine the rgb-value of a certain colour-index with: rgb$=RIGHT$(HEX$(XBIOS(7,index,-1)),3) ! use SETCOLOR-index! DEFMARK The point as mark-symbol (No. 1) cannot be enlarged. Other mark-symbols can be enlarged, but all lines in the symbol retain a width of one pixel. The size of a symbol must be a multiple of 11 plus 6: 0, 17, 28, 39, 50. For a value in between, the prior allowed size is chosen. Perhaps there is some magic hidden in the allowed sizes, or am I missing something? DEFFILL If you haven't defined your own Fill-pattern, the Atari-symbol will be used after DEFFILL 1,4,x. The desktop Fill-pattern is DEFFILL 1,2,4. The Fill-pattern string can consist of 16, 32 or 64 words (MKI$-format). Word 1 to 16 is needed for bitplane 0 (High resolution), word 17 to 32 for bitplane 1 (Medium resolution) and word 33 to 64 for the bitplanes 2 and 3 (Low resolution). In all resolutions, the pattern occupies a rectangle of 16x16 pixels on the screen. The same 16x16 rectangle is also used for the mouse-cursor and sprites. You can always use a Fill-pattern in a lower resolution, e.g. a High-pattern in Medium or Low resolution, but not the other way around. There's gold in them thar Fills. You could surprise the user with a bomb-pattern: RESTORE bomb.fill FOR i=1 TO 16 READ pat$ pat%=VAL("&X"+pat$) fill$=fill$+MKI$(pat%) NEXT i bomb.fill: DATA 0000011000000000 DATA 0010100100000000 DATA 0000000010000000 DATA 0100100001000000 DATA 0001000111110000 DATA 0000000111110000 DATA 0000011111111100 DATA 0000111111111110 DATA 0000110111111110 DATA 0001111111111111 DATA 0001111111101111 DATA 0000111111101110 DATA 0000111111011110 DATA 0000011111111100 DATA 0000001111111000 DATA 0000000011100000 Be careful, a screen filled with this pattern might provoke a heart- attack. If it does, you should blame the DEFFILL, not me. Many Fill-patterns are available as files. You can use these with something like this: bytes=32 ! 32 bytes for High resolution ' *** load Fill-pattern (32 bytes for High resolution) here INLINE fill1%,32 pattern$=STRING$(bytes,0) ! room for Fill-pattern BMOVE fill1%,V:pattern$,bytes ! copy Fill-pattern DEFFILL ,pattern$ ! activate Fill-pattern FILLing a screen with a pattern takes some time, especially in High resolution. If you have to fill an area with an irregular border, you'll have to use the slow FILL-command, but in rectangular areas you should use the fast PBOX- or ARECT-command: DEFFILL colour,fill$ ! activate Fill-pattern BOUNDARY 0 ! no borders PBOX 0,0,639,399 ! for High resolution screen ' ACLIP 1,0,0,639,399 ARECT 0,0,639,399,1,0,fill%,15 ! alternative Line-A command ACLIP 0,0,0,639,399 The Line-A method can be used in High resolution only, the PBOX-method works in any resolution. DEFLINE After 'DEFLINE ,n' all horizontal lines have a width of n pixels (n should be odd), except in Medium resolution. I have trouble counting the pixels in Medium resolution. I think the width of horizontal lines is: n : 1 3 5 7 9 width : 1 1 3 3 5 etc. Is this documented anywhere? If n is larger than 1, all vertical lines are n+2 pixels wide! You define your own Line-patterns by using a negative 16-bit value (from -&X1 to -&X1111111111111111). Each set bit corresponds with a pixel in the Line-pattern (High resolution). The highest bit (15) corresponds with the leftmost pixel of the pattern. Don't get confused if the editor changes the negative binary number you entered as a pattern. The editor uses a special notation for negative binary numbers. GFA-Basic represents integer numbers as binary strings of 32 bits. The most significant bit (31) determines the sign of the integer. If this bit is 0, the remaining 31 bits represent an "ordinary" positive number. But if the most significant bit is 1, the remainder is a negative number in 'two's complement' notation. I won't try to explain that. In any case, the next time you type -&X111 and a friend is watching you, don't blink your eyes, but casually remark "of course the editor converts this into two's complement notation". After 'DEFLINE ,,2,2' you'll discover that the rounded end of the line extends beyond the coordinates of the actual line. The rounded end is created by drawing a filled circle with the centre at the end of the line. No bug, just something to remember. DEFTEXT You change the size of TEXT-letters with: DEFTEXT ,,,size Increasing the size-variable does not always result in larger letters: size 3 barely readable in High resolution 4 6x6 systemfont (icon-text) 6 8x8 systemfont 7-12 progressive magnifications of 8x8 systemfont 13 8x16 systemfont 14-26 progressive magnifications of 8x16 systemfont 27-32 always size 26 Text with size=13 has almost the same height as with size=10, but the letters are much narrower. Letters with size 11 and 12 are actually larger than letters with size 13. Due to a VDI-bug sizes larger than 26 are converted to 26. In some publications you can read about 'shadowed text' (style = 32), but unfortunately our GEM doesn't know this style. You can even find the mask for shadowed text with WORD{L~A+92}, but it's 0. For small letters you get a shadow-like effect this way: DEFTEXT 1,16,angle,13 TEXT x,y,text$ GRAPHMODE 2 DEFTEXT ,17 TEXT x,y,text$ For larger letters (size > 20) you get a 3D-effect with this method. I never succeeded in finding the current text-style (useful in Procedure: restore original style later) with VDISYS 38 (vqt_attributes). Either a bug in GEM or my mistake. I don't want to know, because the easy way is: txt.style=WORD{L~A+90} With DEFTEXT you can set the height of TEXT-letters (in pixels). A letter occupies more space though, determined by the letter-box: letter-height letter-box system-font DEFTEXT ,,,4 4 6 x 6 icon DEFTEXT ,,,6 6 8 x 8 Medium & Low rez DEFTEXT ,,,13 13 8 x 16 High resolution The letter-height is the distance from Descent-Line to Ascent-Line, but the Bottom-Line and Top-Line lie at least one pixel lower/higher. The height of the letter-box is the distance from Bottom-Line to Top-Line. Most letters rest on the Base-Line, but letters with a descender (g,j,p, etc.) rest on the Descent-Line. The top of lowercase letters like a or c touches the Half-Line. If you are still with me, from top to bottom we have the following lines (the letters 'I' and 'p' are shown in the example, but the scale is wrong): Top-Line ------------------- - Ascent-Line ---*****----------- - | * | | Half-Line -----*------****--- | | * * * |letter- |letter-box Base-Line ---*****----****--- |height |height * | | Descent-Line ------------*------ - | Bottom-Line ------------------- - Drop me a line if you don't understand this. DEFTEXT won't affect the text-style used by ALERT and FILESELECT. If you really would like to be able to change that text-style, you need VDISYS 106 (vst_effects): CONTRL(1)=0 CONTRL(3)=1 CONTRL(6)=1 INTIN(0)=style VDISYS 106 Outlined letters (style-bit 4 set) are broader than other letters, so you'll probably have to adjust the Alert-box width by adding some (dummy) spaces. If you PRINT text in a window, GFA actually uses the TEXT-command. This means that DEFTEXT has the same effect on PRINT as on TEXT. On the TOS- screen (not in a window) PRINT is not influenced by DEFTEXT (see paragraph 'PRINT' in chapter 9). GRAPHMODE Imagine you're about to show the letter 'T' on the screen with TEXT. I'll assume the background-colour is white and the text-colour is black. TEXT grabs the letter 'T' from the current font-table in the form of a white rectangle (letter-box) with a black 'T' in it. What will happen when TEXT puts the rectangle on the screen depends on GRAPHMODE and the background: GRAPHMODE 1 (Replace-mode) The background is completely ignored. The letter-box is put on the screen, covering anything under the box, so you'll allways see a black 'T' on a white rectangle. GRAPHMODE 2 (Transparent-mode) Only the black pixels in the letter-box are put on the screen. On a white background the result will be the same as with GRAPHMODE 1. But on a black background you won't be able to see the black 'T'. GRAPHMODE 3 (Xor-mode) The letter-box is 'Xorred' with the background. Each pixel of the letter-box is compared with the corresponding pixel of the background. If both are the same, the result is a white pixel. If they are different, the result is a black pixel. This means you can always read the letter, whatever the background. But the main advantage of the Xor-mode is that you get the original background back if you 'Xor' the same rectangle twice on the same spot. This mode is therefore useful if you will be moving the 'T' around on the screen. GRAPHMODE 4 (Reverse Transparent-mode) First the letter-box is reversed, so we get a white 'T' on a black rectangle. Then GRAPHMODE 2 is used to put the reversed letter-box on the screen. If you draw a rectangle with BOX in GRAPHMODE 3 (Xor-mode), the pixel in the left upper corner is not drawn. Actually this pixel is drawn twice, and in GRAPHMODE 3 this means the pixel disappears. Use PLOT to draw this pixel: GRAPHMODE 3 BOX x1,y1,x2,y2 ! draw the rectangle PLOT x1,y1 ! and fill the gap With PBOX in GRAPHMODE 3 you'll also get trouble in the same corner. Avoid this by using the command 'BOUNDARY 0' first: GRAPHMODE 3 BOUNDARY 0 ! no borders PBOX 50,50,100,100 ! draw the rectangle As mentioned before, GRAPHMODE 3 is especially useful if you make a temporary drawing. Draw the same picture a second time to restore the original screen. In the following example this method is used to draw a line: x=50 ! start line at (50,50) y=50 GRAPHMODE 3 DEFMOUSE 0 SHOWM MOUSE x1,y1,k REPEAT ! main loop LINE x,y,x1,y1 ! draw line REPEAT MOUSE x2,y2,k UNTIL x2<>x1 OR y2<>y1 OR k>0 ! mouse moved LINE x,y,x1,y1 ! erase line x1=x2 y1=y2 UNTIL k>0 ! mouse-click: we're ready GRAPHMODE 1 LINE x,y,x2,y2 ! this is the final line You could also use the 'GRAPHMODE 3'-method for animation, but the XBIOS 5 (Setscreen) method is more suitable (see the paragraph 'Animation', page 9-5). Don't try to draw in GRAPHMODE 3 with a linewidth greater than 1 pixel. GEM will surprise you with some modern art if you can't resist the temptation. If you want to confirm a particular choice of the user, you can invert the relevant part of the screen: GRAPHMODE 3 DEFFILL color,1 ! contrasting colour (usually black) BOUNDARY 0 PBOX x1,y1,x2,y2 Do this once more to restore the original screen. You can 'grey out' an unavailable option on the screen with: GRAPHMODE 3 DEFFILL color,2,2 ! same colour as used in box BOUNDARY 0 PBOX x1,y1,x2,y2 Do this once more to restore the original screen. The entire (High resolution) screen can be dimmed with: SGET dimmer.screen$ GRAPHMODE 4 DEFFILL 1,2,4 BOUNDARY 0 PBOX 0,0,639,399 This could be useful if the user has to wait during some time-consuming operation (like file-loading). Restore the screen with: SPUT dimmer.screen$ After using GRAPHMODE you should always return to the default situation with 'GRAPHMODE 1'. PLOT and DRAW You can use both 'PLOT x,y' and 'DRAW x,y' to set a point on the screen. The size of the point can be changed: DEFLINE ,size,2,2 ! change size of points But the shapes you'll see don't look like points anymore, due to the same problem as described in the paragraph 'DEFLINE'. Use PCIRCLE for proper fat points. PLOT-bug PLOT doesn't work after 'DEFLINE ,size' if size > 1 (GFA-bug?). PCIRCLE-bug With CLIP on, a PCIRCLE touching the upper screen-border is not filled properly in High resolution: CLIP 0,0,640,400 ! default with interpreter anyway PCIRCLE 0,0,50 I don't know if we should blame GFA or GEM for not filling the two top- lines in the circle. With FILL you can correct this bug, in this case by following the PCIRCLE-command with: DEFFILL 1,1 FILL 0,0 ! now the circle is properly filled CURVE With the command CURVE you can draw a Bezier-curve: CURVE x1,y1,x2,y2,x3,y3,x4,y4 The Bezier-curve starts at (x1,y1) and ends at (x4,y4). The other two points act like little magnets. You can also use this command to draw a 'normal' curve between two points by letting the points (x3,y3) and (x4,y4) coincide. Try the following to see what I mean: GRAPHMODE 3 MOUSE x2,y2,k REPEAT CURVE 10,100,x2,y2,110,100,110,100 ! draw curve REPEAT MOUSE x,y,k UNTIL x<>x2 OR y<>y2 CURVE 10,100,x2,y2,110,100,110,100 ! erase curve x2=x y2=y UNTIL k<>0 ! exit after mouse-click TEXT The coordinates used with TEXT determine the start of the Base-Line of the text (see paragraph 'DEFTEXT'). The descenders of letters like 'g', 'j', and 'p' lie below the Base-Line. This is especially important, not to say frustrating, if you use TEXT with an angle of 90, 180 or 270 degrees. The text rotates anticlockwise around the TEXT-coordinates! You can use TEXT to print "digital" numbers (ASCII-code 16-25): number$="24379" FOR i=1 TO LEN(number$) dig$=dig$+CHR$(BCLR(ASC(MID$(number$,i,1)),5)) NEXT i TEXT x,y,dig$ SPRITE You could design and save sprites in vitro with one of the many Sprite- editors that are available. But it's also easy to create a sprite in vivo in your GFA-program: RESTORE pattern.sprite1 READ x,y,mode,msk.color,spr.color FOR i=1 TO 16 READ msk$ msk%=VAL("&X"+msk$) msk.pat$=msk.pat$+MKI$(msk%) NEXT i FOR i=1 TO 16 READ spr$ spr%=VAL("&X"+spr$) spr.pat$=spr.pat$+MKI$(spr%) NEXT i FOR i=1 TO 16 pat$=pat$+MID$(msk.pat$,i*2-1,2)+MID$(spr.pat$,i*2-1,2) NEXT i s$=MKI$(x)+MKI$(y)+MKI$(mode)+MKI$(msk.color) s$=s$+MKI$(spr.color)+pat$ ' pattern.sprite1: ' *** x,y,mode(0=normal;-1=XOR),mask-colour,sprite-colour DATA 0,0,0,0,1 ' *** mask-pattern (1 = pixel on , 0 = pixel off) DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 ' *** sprite-pattern DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 DATA 0000000000000000 If you copy this sprite you won't impress anybody. Switch to Overwrite- mode in the GFA-editor and draw a nice sprite-pattern by typing '1' for every pixel that should be visible. The mask should be an exact copy of the sprite-pattern if you need a transparant sprite. Making the mask one pixel wider than the sprite usually is a good idea. Leave the mask empty (all '0') and the sprite will disappear behind objects on the screen. Fill the mask with '1' and the 16x16 sprite will always remain visible. Switch mask- and sprite-colour in the first DATA-line to create a "reverse" sprite. Or use any SETCOLOR-index (!) that is available in the current resolution. In XOR-mode (same as GRAPHMODE 3, see page 20-9) the sprite is always visible whatever the background is. If you put a sprite on the screen, the background (16x16 pixels) is temporarily saved. GFA automatically removes the old sprite if you use new coordinates for your sprite: DO (...) VSYNC ! prevent blinking SPRITE s$,x,y ! old sprite automatically removed (...) LOOP Using more than one sprite simultaneously, it is essential you remove old sprites in reverse order yourself. This is necessary because a sprite could overlap another sprite. Removing the top sprite first ensures that the original background will reappear after removing the last old sprite, e.g.: DO (...) SPRITE s2$ ! remove old sprites in reverse order... SPRITE s1$ VSYNC ! prevent blinking SPRITE s1$,x1,y1 ! draw new sprites... SPRITE s2$,x2,y2 (...) LOOP VQT_EXTENT The function VQT_EXTENT can be used if you would like to draw a rectangle around a text-string: ~VQT_EXTENT(txt$,x1,y1,x2,y2,x3,y3,x4,y4) The coordinates of the four corners depend on the angle of the text (0, 90, 180 or 270 degrees) and of course on the size of the text. The point (x1,y1) is the lower left corner of the imaginary rectangle around the text and the other points are arranged anticlockwise around the text- string. Because the text rotates around the TEXT-coordinates (start of the Base-Line), it will take some trial and error to determine the correct position of the rectangle if the angle is not 0 degrees. In the following table you'll find the "true" origin of the rectangle, the width and the height of the rectangle, and also the actual position of the lower left corner of the text-block (x1,y1): angle position (x1,y1) origin width height 0 lower left x1,y1 x2 y4 900 lower right x4,y4 x1 y3 1800 upper right x3,y3 x4 y2 2700 upper left x2,y2 x3 x4 The coordinates of the origin are (0,0), so with an angle of 0 degrees both x1 and y1 are 0. The rectangle rests on the x-axis, while the left side coincides with the y-axis. This is a "mathematical" y-axis, not a "screen" y-axis. This means you go upwards for positive y-values. For an angle of 0 degrees the coordinates will be: (x4,y4). .(x3,y3) . TEXTBLOCK . (x1,y1) (x2,y2) If you understand the table, you should be surprised by the height 'x4' instead of 'y1' at an angle of 270 degrees. I think I discovered a bug in GEM here. Correct GEM by changing the following variables if an angle of 270 degrees is used: y1=x4 SWAP x4,y4 Now, the height is 'y1' as you suspected. Clever, aren't we? I have not been able to confirm my discovery. None of my reference-books mention the bug. Perhaps it's not a bug, but my imagination. And then there is a terrible GFA-bug as well: in a compiled program all coordinates are 0. Sigh. If you use the alternative VQT_EXTENT-command you'll find the coordinates both in interpreted and in compiled programs: ~VQT_EXTENT(txt$) x1=PTSOUT(0) y1=PTSOUT(1) x2=PTSOUT(2) (...) y4=PTSOUT(7) Line-A The Line-A commands are faster than the corresponding VDI-commands in GFA- Basic. Commands such as PSET, PTST and HLINE are two to three times faster than the corresponding VDI-commands PLOT, POINT and LINE. The difference should be even greater after loading GDOS. The syntax of Line-A commands is more complicated, but that's no problem for us GFA-experts. Line-A commands use the SETCOLOR-index, not the VDI colour-index (see paragraph 'SETCOLOR and VSETCOLOR' in this chapter). Because GFA uses Line-A commands for sprites, you need a SETCOLOR-index for sprites as well (see paragraph 'SPRITE') Of course it's completely legal to use Line-A commands. Atari has sworn an oath that you always will be able to use Line-A commands. Until the world ends, or they change their mind. Atari now recommends to avoid all the hardware-specific TOS-routines, including Line-A commands. Remember their other promise, that the BIOS system-variables (&H400 - &H4FF) are cast in concrete? Let us pray they don't dump these variables in a lake. Amen. HLINE An additional advantage of the commands HLINE, ARECT and APOLY, apart from the gain in speed, is that you don't have to change the DEFFILL-parameters in the main program. For solid horizontal lines, use: pattern&=-1 adr%=V:pattern& HLINE x1,y,x2,color,mode,adr%,0 You can't use &X1111111111111111 (16 bits) for the pattern, because bit 15 of a word-variable is a flag for a negative number. Yes, that's why the largest positive word is 2^15 - 1 (32767). The solution to this little problem is to assign -1 to the word-variable. You have my word, now all 16 bits are 1. Use BIN$ if you don't believe me. That's an insult, I gave you my 16 bits, didn't I? For very complicated patterns you could use a word-array: DIM pattern&(i) adr%=V:pattern&(0) (...) ! put fill-pattern in pattern&(0) to pattern&(i) HLINE x1,y,x2,color,mode,adr%,i ACHAR and ATEXT It's difficult to combine the Line-A commands ACHAR and ATEXT with TEXT. The coordinates used with ACHAR and ATEXT determine the position of the left upper corner of the (first) letter-box. That's the Top-Line, not the Base-Line (see paragraph 'DEFTEXT'). With TEXT you can use GRAPHMODE, but you can't select a graphic mode for ACHAR and ATEXT. You can't use the text-style underlined (8) with ACHAR and ATEXT. Probably a GFA-bug. SGET and SPUT A regular ST-screen (32,000 bytes in High, Medium or Low resolution) fits in a string, but larger screens can not be handled. SGET and SPUT are useless if the screen is larger because a string can't contain more than 32767 bytes. TT-programmers have to MALLOCate their own solution to this problem. GET and PUT You can save any rectangular part of the screen as a file: GET x1,y1,x2,y2,pic$ ! a GET-picture BSAVE file$,V:pic$,LEN(pic$) ! use the extension PUT in the filename Later, you could put the saved GET-picture back on the screen with: OPEN "I",#1,file$ LET bytes%=LOF(#1) ! how many bytes needed? CLOSE #1 picture$=SPACE$(bytes%) ! reserve some space, BLOAD file$,V:picture$ ! load the GET-picture PUT x,y,picture$ ! careful: insensitive to CLIP-settings Loading/saving several GET-pictures not only takes time, but it also wastes a lot of valuable space on your disk. Each file occupies at least 1 K, e.g. 10 small GET-rectangles occupy 10 K! If you create an array of the GET-pictures you can save the entire array in one file. Loading a file is very boring for the user, so you should avoid it if possible. You can avoid the loading of a GET-picture, but you have to do some extra work. Don't start complaining, because that's what you're paid for as a programmer. Transfer the GET-picture to an INLINE-line in your program. If you then BMOVE the picture to a string you can PUT the picture anywhere on the screen. I'll assume you have a GET-picture in a file with a length of 2000 bytes. After loading the file in an INLINE-line you can use the following method: INLINE picture%,2000 picture$=SPACE$(2000) ! create string for picture BMOVE picture%,V:picture$,2000 ! put picture in string PUT x,y,picture$ ! show the picture A disadvantage of this method is that the picture is stored twice in memory: in the INLINE-line and in the string. Why not assign a string- variable to the picture in the INLINE-line? Sounds easy, but it isn't. I'll assume you have the same 2000-byte picture as a file. Add 10 to this length for the descriptor (6 bytes) and backtrailer (4 bytes) of the string we are going to create. Load the picture and run this: INLINE picture%,2010 BMOVE picture%,picture%+6,2000 !# make room for descriptor ' Alternative method if the picture is available as GET-string pic$: BMOVE V:pic$,picture%+6,2000 !# move picture from GET-string LONG{picture%}=picture%+6 !# address of string WORD{picture%+4}=LEN(pic$) !# string-length LONG{picture%+LEN(pic$)+6}=picture% !# backtrailer picture$="" ! create string-variable ABSOLUTE picture$,picture% ! assign GET-picture to string After this operation you can delete all lines marked with '#'. The GET- picture is now immediately available in the program: PUT x,y,picture$ A GET-string starts with two words for the x- and y-coordinate of the lower right corner (relative to the upper left corner at 0,0) and one word for the number of bitplanes. The number of bitplanes is determined by the resolution: 1 for High, 2 for Medium and 4 for Low. The three-word header of a GET-string is contructed as follows: header$=MKI$(x)+MKI$(y)+MKI$(bitplanes) These three words are followed by the actual picture as a list of words. As the picture-width is not necessarily a multiple of 16, any bits beyond the right border will be ignored by the PUT-command. These bits are not 0, there's random garbage beyond the border. If you need a 'clean' GET-string for some special purpose you could proceed as follows: GET x1,y1,x2,y2,pic$ ! create GET-string pic$=STRING$(LEN(pic$),0) ! clear the string GET x1,y1,x2,y2,pic$ ! 'clean' GET-string Here is the connection between GRAPHMODE and PUT-mode: GRAPHMODE PUT-mode 1 (Replace) 3 (default) 2 (Transparent) 7 3 (Xor) 6 4 (Reverse Transparent) 13 In the paragraph 'GRAPHMODE' you have found a method to invert a rectangular part of the screen with PBOX. Here is an alternative method with GET/PUT: GET x1,y1,x2,y2,block$ PUT x1,y1,block$,12 ! invert block (...) PUT x1,y1,block$,12 ! normal again I have encountered a few programs in GFA-Basic 2.0 where PUT was used just outside the screen (I know: bad, bad, bad). In GFA-Basic 3.0 the program didn't work. The same occurred in a program where a picture was BLOADed a few bytes before the screen-RAM. I don't understand why GFA- Basic 3.0 doesn't accept this, as there is some unused space there (read the paragraph 'RAM', page 4-1), but I've learned to correct this when I convert a program from GFA-Basic 2.0 to version 3.0. Degas-Pictures I declare Degas as the standard picture-format for GFA-Basic. A Degas picture-file contains not only the actual picture (same format as SGET- picture), but also the colour-palette of the picture and the resolution. The original Degas-files have a length of 32034 bytes: 1 word - resolution 16 words - palette 16000 words - picture data You can check the resolution-word for the correct resolution (0 = Low, 1 = Medium, 2 = High), but you can also look at the extension of the filename (PI1/PI2/PI3 for Low/Medium/High). In the second Degas-version (Degas Elite), 16 words for colour-animation can be added after the picture data. Files with colour-animation have a length of 32066 bytes, but Degas Elite files without colour-animation are exactly the same as the original files. A Degas Elite picture can (and really should!) be saved in a compressed format. The extensions PC1/PC2/PC3 are used for Low/Medium/High resolution. Also, the highest bit of the resolution-word is set as a flag for a compressed picture. With the proper unpack-routines you can show a compressed Degas-picture reasonably fast on the screen. If you have created a picture for one specific GFA-program, you should put it in an INLINE-line. The GFA-program will become larger, but the picture is immediately available in the program and you can't lose the separate Degas-file. You shouldn't throw the Degas-file away, just in case you accidentally corrupt the INLINE-line. Assuming there is no colour- animation, you could proceed as follows. Load the uncompressed Degas- picture in an INLINE-line. Before you show the Degas-picture you change the palette (don't forget to save the current palette first) and then you BMOVE the picture to the monitor: INLINE degas%,32034 ~XBIOS(6,L:degas%+2) ! change palette BMOVE degas%+34,XBIOS(2),32000 ! show picture on physical screen Other Picture-Formats Although I declared Degas as the standard picture-format for GFA-Basic, there are many other formats. GEM bitmap (.IMG), Neochrome (.NEO), Tiny (.TN?) and Deluxe Paint(.IFF) are some widely used picture-formats. Don't try to load all these formats in your GFA-programs, but use a (Public Domain) program to convert these pictures to Degas. Try to find conversion-programs such as IFFCNV or PicSwitch. The GEM bitmap format is a serious candidate for a standard format, but only for High resolution as there is no standard method to include the palette in the IMG-file. BMOVE and RC_COPY BMOVE can be used to move blocks of memory (e.g. complete number-arrays, as described in the paragraph 'BMOVE' in chapter 4). It is the first choice if you are going to move a screen-wide block of the physical or the logical screen (one or more scanlines). In the paragraph 'Resolutions' you could already find the length of a scanline in the three resolutions: scanline High resolution 80 bytes Medium resolution 160 bytes Low resolution 160 bytes If the screen-block is narrower than the screen-width you have to use the slower RC_COPY-command. And you can always use GET/PUT if you don't mind the slower speed compared to BMOVE and RC_COPY. With GET/PUT you are restricted to the logical screen, but with BMOVE and RC_COPY you can use physical screen, logical screen and/or a screen-buffer. In the following example the three methods are used to move the first 16 scanlines of the logical screen (High resolution) 16 scanlines down. The original scanlines remain unaltered, so this actually is a copy-method: GET 0,0,639,15,block$ ! upper 16 scanlines of logical screen PUT 0,16,block$,3 ! place block 16 scanlines down ' RC_COPY XBIOS(3),0,0,640,16 TO XBIOS(3),0,16,3 ! faster ' BMOVE XBIOS(3),XBIOS(3)+16*80,16*80 ! fastest With a narrower block you can't use BMOVE: GET 0,0,99,15,block$ ! block is 100 pixels wide PUT 0,16,block$,3 ' RC_COPY XBIOS(3),0,0,100,16 TO XBIOS(3),0,16,3 ! fastest VSYNC The VSYNC-command is useful if you want to prevent irritating blinking during animation. Always VSYNC before drawing a new picture in an animation sequence (including SPRITE-animation). The program is slowed down of course, because it waits for a vertical blank interrupt before starting to draw. But it looks much nicer. BITBLT BITBLT is supposed to be suitable for experienced professionals only. Actually there are two BITBLT-commands available: one uses VDI and the other Line-A. The VDI BITBLT-command needs three integer-arrays with a lot of parame ters. Twenty-one parameters sounds frightening, but 14 parameters are more or less fixed, so you only have to think about 7 parameters. That's 4 parameters for the source-rectangle (x1,y1,x2,y2), 2 parameters for the destination-rectangle (x1,y1) and 1 parameter for the copy-mode (same as PUT-mode). Sounds easy now, doesn't it? Unfortunately this also means you can use BITBLT for exactly the same operations as BMOVE and RC_COPY. All the extra parameter-handling makes BITBLT even slower than BMOVE and RC_COPY. You might as well forget the VDI BITBLT-command completely. I don't understand why GFA calls this a VDI-command, but you already forgot about this command, so I won't bother you with that. The Line-A BITBLT-command is a different cup of tea. Here you need 22 parameters (preferably in one integer-array), but this is reduced to about 9 parameters that really matter. This time the command offers more possibilities than BMOVE or RC_COPY, but you have to understand everything about scanlines and byte-offsets first. If you do, you can use elements 10 and 16 of the integer-array to do clever things. And you can use elements 18-21 to create complicated fill-patterns. I'll leave that to the professionals. Both BITBLT-commands are insensitive to any (A)CLIPping and are quite happy to blit bits everywhere in memory. So be careful and expect your program to crash any time you test your thoroughly debugged program. ACLIP Line-A commands are 'CLIP-sensitive', although they are not supposed to be. Just in case you forgot you used some CLIP-command somewhere else, you should always use an appropriate ACLIP-command before a Line-A command. The following Line-A commands are not influenced by ACLIP though: ALINE, HLINE, PSET, PTST and BITBLT. Blitter The Blitter-TOS (1987) allows you to switch the Blitter on/off from GFA- Basic with the function XBIOS 64 (Blitmode). Procedures (CHAPTER.20) Bitblt_a_screen_init (page 20-22) \BITBLT_A\SCR_INIT Bitblt_a BITBLT_A Copy a rectangle to the physical screen: @bitblt_a_screen_init(source.screen%) @bitblt_a(100,100,150,150,0,0,3,80,80) ! for High resolution In this case the box (100,100,150,150) from the source-screen (usually an invisible second screen) is copied to position (0,0) on the physical screen, using PUT-mode 3. For both source and destination the 80 byte length of one scanline is used (for Medium or Low resolution you need 160 bytes). Special effects are possible by changing these offsets. Procedure Bitblt_a uses the Line-A BITBLT-command. Bitblt_get_init (page 20-22) \BITBLT\GET_INIT Bitblt_screen_init SCR_INIT Bitblt BITBLT Copy a rectangle to the physical screen: @bitblt_screen_init(source.screen%) @bitblt(100,100,150,150,0,0,3) This has the same effect as the previous example, but it's faster. Procedure Bitblt uses the VDI(?) BITBLT-command. It's also possible to manipulate (a part of) a GET-string: @bitblt_get_init(block$,destination.screen%,x2,y2) @bitblt(50,50,x2,y2,0,0,3) Here the rectangle (50,50,x2,y2) is copied from the GET-string to (0,0) on the destination-screen. The GET-rectangle itself has the coordinates (0,0,x2,y2). Bitblt_ \BITBLT\SCROLL\ back_reverse,curtain,iris,merge_all BACK_REV CURTAIN IRIS MERG_ALL merge_leftright,merge_topdown MERG_LR MERG_TD put_modes,random,roll_down PUT_MODE RANDOM ROLLDOWN roll_downup,roll_right,roll_rightleft ROLLDNUP ROLL_R ROLL_RL shrink,sliders,spiral4,vertical_blind SHRINK SLIDERS SPIRAL4 V_BLIND These are all scroll-Procedures that have to be used with Procedures Bitblt_screen_init and Bitblt: @bitblt_screen_init(invisible.screen%) ' Put a picture on the invisible (logical) screen @bitblt_back_reverse ! uses Procedure Bitblt Blend BLEND Fade-over picture to the screen (several effects possible): ' Picture at address pic% @blend(pic%,effect,delay) ! delay determines speed Best results in High resolution. Blitter (page 20-22) BLITTER Switch Blitter on or off (with Blitter-TOS only): @blitter(TRUE) ! switch Blitter on Box_dimmer (page 20-11) BOX_DIM Dim a box (e.g. to tell the user that an option is unavailable): @box_dimmer(100,100,200,150) ! box greyed out ' Do something @box_dimmer(100,100,200,150) ! normal again Box_reverse (page 20-11) BOX_REV Invert box (e.g. to tell user that an option has been selected): @box_reverse(100,100,200,150) ! box inverted ' Do something @box_reverse(100,100,200,150) ! normal again Busy BUSY Fill the entire High resolution screen with bees and tell the user that we're very busy right now: @busy Color_cycle and Cycle_every COLRCYCL Cycle colours from VDI colour-index c1 to c2 every ticks (1/200 s): @color_cycle(c1,c2,200,TRUE) ! cycle every second ' Do something else @color_cycle(c1,c2,200,FALSE) ! switch colour-cycling off Colors_dim COLORDIM Dim colours with VDI colour-index c1 to c2: @colors_dim(c1,c2) Cube CUBE Draw a cube in High or Low resolution: @cube(x,y,width,color,fill) Degas_inline_med_low (page 20-2,20-20) \DEGAS\INL_LOW Show a Degas-picture (stored in an INLINE-line) in Low resolution from a program running in Medium resolution: @degas_inline_med_low(picture1%,0) ! waits for key or click @degas_inline_med_low(picture2%,5) ! wait 5 seconds Degas_inline_show (page 20-20) \DEGAS\INL_SHOW Show a Degas-picture that is stored in an INLINE-line: @degas_inline_show(picture%) A better idea than loading an uncompressed Degas-picture. Degas_load (page 20-20) \DEGAS\LOAD Load a Degas-picture and the palette in strings: @degas_load(file$,picture$,palet$,ok!) IF ok! ' Degas-picture now available as SPUT-string picture$ ELSE ' Something went wrong ENDIF The Procedure loads both uncompressed and compressed Degas-pictures. Colour-animation data are ignored. Degas_load_show (page 20-20) \DEGAS\LOADSHOW Same as Degas_load, but now the Degas-picture is shown immediately on the physical screen: @degas_load_show(file$,ok!) IF NOT ok! ' Something went wrong ENDIF Degas_save (page 20-20) \DEGAS\SAVE The logical screen is saved as an uncompressed Degas-picture: @degas_save(file$,ok!) Fill_border \FILL\FILLBORD Fill an area within a coloured boundary: @fill_border(100,100,red) ! stop FILLing at red boundary Fill_1_high_init and Fill_high_creation (page 20-5) \FILL\FILL_HI Create a Fill-pattern for High resolution: @fill_1_high_init(pattern$) ! create Fill-pattern DEFFILL ,pattern$ ! activate pattern FILL 10,10 ! use pattern Fill_1_low_init and Fill_low_creation (page 20-5) \FILL\FILL_LOW Create a Fill-pattern for Low resolution. Fill_1_med_init and Fill_med_creation (page 20-5) \FILL\FILL_MED Create a Fill-pattern for Medium resolution. Fill_init (page 20-6) \FILL\FILLINIT Load a Fill-pattern from an INLINE-line in a string: @fill_init(adr%,pattern$) Gem_image_load_show (page 20-20) \PICTURE\IMG_SHOW Show a GEM bitmap picture (*.IMG) on the screen: @gem_image_load_show(file$,ok!) ! High resolution only Line LINE Let user draw a line on the screen and return the coordinates: @line(x1,y1,x2,y2) Magnify MAGNIFY Put a magnified rectangular part of the TOS-screen somewhere else on the screen: @magnify(0,0,10,10,100,0,8) ! 8 times magnified at (100,0) Message MESSAGE Show a centered message in reverse on the TOS-screen: @message(" This is a message ",25,TRUE) ! on line 25 ' Do something @message("",25,FALSE) ! restore screen Message_any_key MESS_KEY Show message "Press any key or mouse-button..." in reverse on bottom line of TOS-screen and wait: @message_any_key Message_time MESS_TIM Show message in reverse on bottom line of TOS-screen and wait: @message_time("Read this",5) ! show for 5 seconds Mirror MIRROR Return mirror-image of a GET-string: @mirror(source$,0,mirror$) ! vertical (1=horizontal) Neochrome_load_show (page 20-20) \PICTURE\NEO_SHOW Show a Neochrome-picture on the monitor: @neochrome_load_show(file$,ok!) IF NOT ok! ' Something went wrong ENDIF Palet (page 20-2, 20-4) \PALET\PALET Show current palette in a rectangle ('spectrum'): @palet(100,100,10,10) In this case the left upper corner of the rectangle is at (100,100) and both height and width of each colour-box is 10 pixels. Palet_low (page 20-2) \PALET\PALETLOW Install a new Low-palette: @palet_low ! palette stored in DATA-lines Palet_medium (page 20-2) \PALET\PALETMED Install a new Medium-palette: @palet_medium ! palette stored in DATA-lines Palet_save_int and Palet_change_int (page 20-4) \PALET\PAL_INT Save current palette in an integer-array and restore the saved palette later: @palet_save_int(palet%()) ! save palette ' Do something @palet_change_int(palet%()) ! restore palette Palet_save_str and Palet_change_str (page 20-4) \PALET\PAL_STR Save current palette in a (Degas-compatible) string and restore the saved palette later: @palet_save_str(palet$) ! save palette ' Do something @palet_change_str(palet$) ! restore palette Palet_string (page 20-5) \PALET\PALSTRNG Create a palette-string from DATA-lines: RESTORE this.palet @palet_string(palet$) ! make palette-string @palet_change_str(palet$) ! activate the palette Picture_init PICTURE Prepare a picture on an invisible logical screen and return the picture as a GET-string: RESTORE picture.data @picture_init(picture$) ! uses Screen2_init & _restore PUT 50,50,picture$ picture.data: DATA BOX,0,0,80,80 DATA LINE 0,0,80,80 DATA END This Procedure recognizes the following commands: DEFLINE, DEFTEXT, LINE, DRAW, BOX, RBOX, TEXT and END (=last command) Point POINT Let user pick a point on the screen with the mouse: @point("Click on point",x,y) Rectangle \RECTNGLE\RECTNGLE User cuts GET-rectangle from TOS-screen: @rectangle(part$,x,y) ! left upper corner at (x,y) CLS PUT 0,0,part$ Rectangle_array_load (page 20-18) \RECTNGLE\REC_AR_L Load an array of GET-rectangles from disk: @rectangle_array_load(file$,ok!,picture$()) IF ok! PUT 10,10,picture$(0) PUT 10,100,picture$(1) ENDIF Rectangle_array_save (page 20-18) \RECTNGLE\REC_AR_S Save an array of GET-rectangles on disk: @rectangle_array_save(file$,picture$()) Rectangle_flash (page 20-19) \RECTNGLE\REC_FLSH Flash a rectangle several times (especially suitable for text-boxes): @rectangle_flash(50,50,200,150,5) ! flash 5 times Rectangle_load (page 20-18) \RECTNGLE\REC_LOAD Load a GET-rectangle from disk: @rectangle_load(file$,ok!,clip$) IF ok!=TRUE PUT 50,50,clip$ ENDIF Rectangle_save (page 20-18) \RECTNGLE\REC_SAVE Save a GET-rectangle on disk: @rectangle_save(file$,picture$) Rectangle_shadow \RECTNGLE\REC_SHDW Draw a rectangle with a shadow (3D-effect): @rectangle_shadow(30,30,100,100) Res_low_medium and Res_medium_low (page 20-2,9-4) RESLOMED Switch temporarily from Low to Medium resolution, e.g. to show text: @res_low_medium("000","770","700","007",palet$) PRINT "This is a medium screen, shown from a program running in Low!" PRINT "In this example we use yellow letters on a black screen." ~INP(2) @res_medium_low(palet$) ! back to Low (restore palette too) Screen_cls_down (page 20-21) \SCRN_CLS\DOWN Clear screen by scrolling the screen downwards: @screen_cls_down(2,black) ! steps of 2 scanlines; make black Screen_cls_luxaflex \SCRN_CLS\LUXAFLEX Clear the screen with a luxaflex-effect: @screen_cls_luxaflex Screen_cls_scroll \SCRN_CLS\SCROLL Clear the screen with an upwards scrolling rectangle in the current foreground-colour (usually black): @screen_cls_scroll Screen_cls_shrink \SCRN_CLS\SHRINK Clear the screen with a shrinking rectangle in the foreground-colour (usually black): @screen_cls_shrink Screen_cls_up (page 20-21) \SCRN_CLS\UP As Screen_cls_down, but screen scrolls upwards. Screen_convert \SCREEN\SCRNCONV Convert picture on logical screen (from wrong resolution) to current resolution (especially suitable to show a Medium or Low picture in High): ' Load Medium picture in logical screen @screen_convert(1) ! convert picture to High Screen_dimmer (page 20-11) \SCREEN\SCRN_DIM Dim entire screen, e.g. to indicate that some time-consuming action is going on): @screen_dimmer(black,TRUE) ! use black colour ' Do something @screen_dimmer(black,FALSE) ! restore screen Screen_fill (page 20-6) \SCREEN\SCRN_FIL Fill High screen with a Fill-pattern: @screen_fill(adr%) Screen_invert (page 20-3) \SCREEN\SCRN_INV Invert entire High screen: @screen_invert(TRUE) ! invert screen ' Do something @screen_invert(FALSE) ! restore screen Screen_shrink \SCREEN\SCRSHRNK Shrink screen, e.g. to be able to show small copies of several pictures together on one screen: @screen_shrink(2,physbase%,physbase%,pic$) ! quarter size Scroll_init (page 20-21) \SCROLL\SCR_INIT Scroll_cover,drop,luxaflex,middle COVER DROP LUXAFLEX MIDDLE middlepush,random,rolldown,slider MIDPUSH RANDOM ROLLDOWN SLIDER spiral,strips,uncover,up,venetian SPIRAL STRIPS UNCOVER UP VENETIAN Scroll second screen on physical screen: @scroll_init ! activate invisible second screen ' Put something nice on the invisible logical screen @scroll_cover ! scroll down, covering current monitor-picture Scroll_text_down (page 20-21) SCRLTXTD Scroll text-lines one line down on the TOS-screen: @scroll_text_down(1,5) ! scroll line 1 - 5 one line down This is much faster than rePRINTing lines 1 - 5 again one line down. Scroll_text_up (page 20-21) SCRLTXTU Scroll text-lines one line up on the TOS-screen: @scroll_text_up(2,8) ! scroll line 2 - 8 one line up Spectrum_load_show (page 20-20) \PICTURE\SPECSHOW Put a Spectrum 512 picture on the screen: @spectrum_load_show(file$,ok!) ! press a key to continue Not all (old) ST's are able to show 512 colours. Sprite_init_1 and Sprite_creation (page 20-13) SPRITE Create a sprite from DATA-lines: @sprite_init_1(sprite1$) Text_3d (page 20-8) \TEXT\TEXT_3D Create 3D-letters with TEXT: @text_3d(10,10,"3D",black,26,0) ! size 26, angle 0 Text_at \TEXT\TEXT_AT Same effect as PRINT AT(column,line), but uses TEXT: @text_at(1,5,"Printed with TEXT at column 1, line 5") You can use this Procedure to mix PRINTed text with TEXT-effects such as bold, underlined, italics, etc. Text_box \TEXT\TEXT_BOX Put a text in a box: @text_box(column,line,3,black,black,"Text in a box") The start-position of the box is determined by column and line. In this case the line-width of the box is 3 (if width is 0, a double line is drawn) and black is used both for the box and the text. Text_box_center \TEXT\TEXT_CEN Put a text in a centered box: @text_box_center(3,black,black,"Text in a centered box") Same as Procedure Text_box, but now the box appears in the middle of the screen. Text_box_invert \TEXT\TXET_BOX Put inverted text (standard size) in a box: @text_box_invert(x1,y1,x2,y2," Inverted text in a box ") By the way, the filename is indeed TXET_BOX (inverted TEXT, get it?) Text_extent (page 20-15) \TEXT\TEXT_EXT Return width and height of a TEXT-string: TEXT 50,50,"Measure this text" @text_extent("Measure this text",width,height) You can now draw a rectangle around the text, although that's not easy. Text_parameters (page 20-8) \TEXT\TEXT_PAR Return current DEFTEXT-parameters: @text_parameters(colour,attributes,angle,height) Text_shadow (page 20-8) \TEXT\TEXT_SHD Create large letters (size 26) with shadow-effect: @text_shadow(50,100," S H A D O W S ") Textstyle_alert (page 20-9) \TEXT\TEXTSTYL Change text-style for ALERT (and FILESELECT): @textstyle_alert(1) ALERT 1,"A bold Alert-box",1,"OK",k Tiny_load_show (page 20-20) \PICTURE\TINYSHOW Show a Tiny picture on the monitor: @tiny_load_show(file$,ok!) Too slow! Functions (CHAPTER.20) Digital$ (page 20-13) DIGITAL Return a number with 'LCD'-digits: TEXT 50,100,@digital$("128") Rgb_value$ (page 20-5) RGB_VAL Return RGB-string of a VDI colour-index: PRINT "Background-colour is: &H";@rgb_value$(0) PRINT "PRINT-colour is: &H";@rgb_value$(1)