LBSOS KRNLI/O ERRORFILE 'SOS.KERNEL' NOT FOUNDINVALID KERNEL FILExةw,@  4  J  ȱ⩤i8#) ) 8LeARTICLE20v' '*ARTICLE.203Nm7,BOUNCE.PRIOR b,BOUNCE.SCRUB 'BUG.BOX H*FINAL.FIRE 9+MOVE.SINGLE %DISKNAME.DAT#l0k5!+*HELLO.TEXTl;O*MENU.MAKER K;+READCRT.INV!t+REQUEST.INV !+%SEG.T jKŸ/ (STANDARD8!tIII.BSB.07IC.05u' %APPLE8!+ARTICLE2043ARTICLE2144,ARTICLES.PT1PT1  2)BGRAF.INV($!L+,DOWNLOAD.INVm#im#iЛ#Lȱ  6L憦  Lsmm l y` @8(Je稽 ʈ[.NEW.MOVE.THREE p)NEW.SCRUB U *READ.SCRUB ,SCREW.AROUND *+ZOOM.SINGLE .  shape%(7,15),tshape%(7,31)&".d1/bgraf.inv",".d1/request.inv"#1,".grafix""Shape file name: ";file$file$=""300 1000:error"Error number "error" in file '"file$"'.":253j=015:i=03:tshape%(i,j+8)=shape%(i,j)::#, 0 0, 0Qij=015:" ";1100+5*ij;" data ";:jk=03:2010;shape%(jk,ij);:jk::ij 6#,"," ","  0, 0V 0, 0[ 0, 1984` 1984, 2080e 2080, 4752j 4752, 4112o 4112, 5008t 5008, 2080y 2080, 1984~ 1984, 2336 2976, 2720 1344, 4752 0, 0 00,0),%f%,%r%,%z%,%s%,%s%)moveto(%k,%m)1drawimage(@tshape%(0,0),%f%,%r%,%z%,%s%,%t%)ka$:a$)<>27105,release:release:release6:@J i=015 j=01shape%(j,i)ji$L 0, 0Q r(%13):fillport Agrafixondf%=4:s%=16:t%=32:z%=0 ik=0100nj=k/5+2)*53+88sl=k/10)*30+58xm=k/10)*70+85}r%=s%*(r%=z%)moveto(%k+28,%j)1drawimage(@tshape%(0,0),%f%,%r%,%z%,%s%,%t%)moveto(%k+14,%l)0drawimage(@shape%( shape%(1,15),tshape%(1,31)".d1/bgraf.inv"#1,".grafix" 10003j=015:i=01:tshape%(i,j+8)=shape%(i,j)::#initgrafix(grafixmode(%3,%1)-pencolor(%4)2fillcolor(%7):fillport 7viewport(%40,%100,%15,%130)<fillcoloret%<>256error=2:: Shape definition is invalid Berror=0:: Shape loaded : Shape loaded elease:release:release@:J œ1030array$="shape%":#3,file$ftype=3)1ftype=1#3;filtyp,ch,cw,sl:filtyp=11070:#3:ftype=0file$ error=1: Not a shape file $0.#3,1:filread(%3,@array$,%256,@ret%)::#388*(r%=t%)moveto(%k+28,%j)1drawimage(@tshape%(0,0),%s%,%r%,%z%,%s%,%t%)moveto(%k+14,%l)0drawimage(@shape%(0,0),%s%,%r%,%z%,%s%,%s%)moveto(%k,%m)1drawimage(@tshape%(0,0),%s%,%r%,%z%,%s%,%t%)ka$:a$)<>27105,:6r initgrafix(grafixmode(%3,%1)-pencolor(%4)2fillcolor(%7):fillport 7viewport(%40,%100,%15,%130)<fillcolor(%13):fillport Agrafixonds%=16:t%=32:z%=0 ik=0100nj=k/5+2)*53+88sl=k/10)*30+58xm=k/10)*70+85}r%=t%+s% shape%(1,15),tshape%(1,31)".d1/bgraf.inv"#1,".grafix" 10003j=015:i=01:tshape%(i,j+8)=shape%(i,j)::#initgrafix(grafixmode(%3,%1)-pencolor(%4)2fillcolor(%7):fillport 7viewport(%40,%100,%15,%130)<fillcolo,release:release:release6:@JXsetctab(%7,%2,%7)bsetctab(%2,%7,%7)lsetctab(%14,%2,%13)vsetctab(%15,%7,%13)setctab(%14,%13,%13)setctab(%14,%7,%7)setctab(%15,%13,%13)setctab(%15,%2,%2) i=0(%7):fillcolor(%15)0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)&x1n-x2n)>12y1n-y2n)>10150moveto(%x1n,%y1n)!pencolor(%2):fillcolor(%14)0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)#s1x=x1n:s1y=y1n:s2x=x2n:s2y=y2n120y1m:122.|x2n=s2x+x2m:x2n<37x2n>89x2m=-x2m:124/~y2n=s2y+y2m:y2n<27y2n>134y2m=-y2m:126r%=s%*(r%=z%)moveto(%x1n,%y1n)!pencolor(%2):fillcolor(%14)0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)moveto(%x2n,%y2n)!pencolorA600 FgrafixonPfillcolor(%14)df%=4:s%=16:t%=32:z%=0(is1x=1)*40)+40:s1y=1)*115)+15(ns2x=1)*40)+40:s2y=1)*115)+15sx1m=3:y1m=3:x2m=3:y2m=3.xx1n=s1x+x1m:x1n<37x1n>89x1m=-x1m:120/zy1n=s1y+y1m:y1n<27y1n>134y1m=- shape%(1,15),tshape%(1,31)".d1/bgraf.inv"#1,".grafix" 10003j=015:i=01:tshape%(i,j+8)=shape%(i,j)::#initgrafix(grafixmode(%3,%1)2fillcolor(%5):fillport 7viewport(%40,%100,%15,%130)<fillcolor(%13):fillport 4752j 4752, 4112o 4112, 5008t 5008, 2080y 2080, 1984~ 1984, 2336 2976, 2720 1344, 4752 0, 0 0, 0 0, 0, 0x1n:s1y=y1n:s2x=x2n:s2y=y2n120,release:release:release6:@J i=015 j=01shape%(j,i)ji$L 0, 0Q 0, 0V 0, 0[ 0, 1984` 1984, 2080e 2080,|x2n=s2x+x2m:x2n<37x2n>89x2m=-x2m:124/~y2n=s2y+y2m:y2n<27y2n>134y2m=-y2m:126r%=s%*(r%=z%)moveto(%x1n,%y1n)0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)moveto(%x2n,%y2n)0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)#s1x=r(%13):fillport Agrafixondf%=4:s%=16:t%=32:z%=0(is1x=1)*40)+40:s1y=1)*115)+15(ns2x=1)*40)+40:s2y=1)*115)+15sx1m=1:y1m=1:x2m=1:y2m=1.xx1n=s1x+x1m:x1n<37x1n>89x1m=-x1m:120/zy1n=s1y+y1m:y1n<27y1n>134y1m=-y1m:122.15 j=01shape%(j,i)ji$L 0, 0Q 0, 0V 0, 0[ 0, 1984` 1984, 2080e 2080, 4752j 4752, 4112o 4112, 5008t 5008, 2080y 2080, 1984~ 1984, 2336 2976, 2720 1344, 4752 0, 0 0, 0 0, 0, 0 shape%(1,15),tshape%(1,31)".d1/bgraf.inv"#1,".grafix" 1000initgrafix#grafixmode(%3,%1)(fillcolor(%5):fillport1-moveto(%45,%145):pencolor(%0):#1;"Bug Box"2viewport(%40,%99,%15,%130)7fillcolor(%13):fillport<%,%white%)&Bsetctab(%yellow%,%white%,%white%)L%)Lnge%)&setctab(%dgreen%,%green%,%green%)&setctab(%dgreen%,%white%,%white%)'setctab(%brown%,%orange%,%orange%)%setctab(%brown%,%green%,%green%)%$setctab(%brown%,%white%,%white%)$.setctab(%grey%,%green%,%green%)$8setctab(%grey%,%whitecolor$(k)=f$k n=0139 dr$=draw$ k=06color$(k)=f$7458n>=horz(k,0)n<=horz(k,1)dr$,7*k+2,1)=color$(k)dr$,7*k+4,1)=n)k d$(n)=dr$n $setctab(%dgreen%,%blue%,%blue%)(setctab(%dgreen%,%orange%,%oradraw$=p$+p$+p$+p$+p$+p$+p$ 30,47,65,75,95,115,191 1 0,139,20,95,0,139,50,139,0,139,0,75,0,139  -1,6,-1,9,-1,12,-1 1k=06:vert(k):draw$,7*k+6,1)=vert(k)):"k=06:horz(k,0),horz(k,1): k=06+z:z>=0color$(k)=z)::moverel(%3,%0):x=xloc#x<0x>139moverel(%-3,%0):3linerel(%0,%184):moverel(%0,%-184):#1;d$(x);/moverel(%-3,%-184):pencolor(%vector(pen)):release:release:release:'p$=19)+f$+24)+" "+0)+" "+0)!j()450,455,460,465,470,500#1;q$;:moverel(%-7,%0) 425#1;b$;:moverel(%-4,%0)::#1;b$;:moverel(%-10,%0):2pen=(pen<>4)*(pen)+1:pencolor(%vector(pen)):<pen=(pen<>1)*(pen-1)+4*(pen=1):pencolor(%vector(pen)):en map grafixonfillcolor(%f)" paint the screen ),i=0139:moveto(%i,%0):#1;d$(i);:viewport(%0,%139,%0,%192)0pen=1:moveto(%0,%7):pencolor(%vector(pen))#1;q$;:moverel(%-7,%0) 425!420: insert timewaster here=34):b$=" ":j(21)=1:j(8)=2:j(10)=3:j(11)=4:j(32)=5:j(27)=6grafixmode(%3,%1)initgrafix#1000: set color priorities ""Background color number: ";f f$=f)5:=12:=20:"Setting up the screen, please wait""700: initialize scred#1,".grafix"/nd$(139),color$(6),vert(6),horz(6,1),j(255)x".d1/bgraf.inv"3purple%=3:blue%=6:orange%=9:green%=12:white%=15*dgreen%=4:brown%=8:grey%=10:yellow%=13Hvector(1)=yellow%:vector(2)=grey%:vector(3)=brown%:vector(4)=dgreen%Bq$viewport(%60,%80,%62,%82)Afillcolor(%4):fillportF600: set prioritiesKviewport(%40,%99,%15,%130) Pgrafixondf%=4:s%=16:t%=32:z%=0(is1x=1)*40)+40:s1y=1)*115)+15(ns2x=1)*40)+40:s2y=1)*115)+15sx1m=3:y1m=3:x2m=3:y2m=3!"#)+h$,3,2)))ji5 7215,32545, 838,15360, 0, 0, 0, 05 14430,32322, 1548,30720, 0, 256, 1, 05 28732,31748, 3096,28672, 1, 769, 2, 2565 24696,30728, 6192,24576, 258, 1794, 4, 7685  164915);0Xtext40$;bw$]21);"9"; b::l i=06head1$(i)="":head2$(i)="" j=03a%:h$=a%)7head1$(i)=head1$(i)+h$,1,2)))+h$,3,2)))j j=03a%:h$=a%)7head2$(i)=head2$(i)+h$,1,2))t$(i))name$:*i=17:control(%17,@ctre$(i))name$:110 Process keystrokes =27500 20021);"="22);14);:(nam$=q$+"/profile/basic/standard"+q$.getfont(@nam$,@array$):loadfont(@array$) &$&'(initionsZ800: load the print line!d900: set up control stringsn600: set up screen xline$; 200*i=17:control(%17,@ctrb$(i))name$:x=030:i=174ctrlist$(i),2,1)=x):ctrlist$(i),11,1)=x+1)#control(%17,@ctrlis, a%(511),ctrlist$(7),head1$(6),head2$(6))".d1/download.inv",".d1/request.inv")q$=34):array$="a%":name$=".console"(fg$=19):bg$=20)2mblue$=6):white$=15)<bw$=fg$+mblue$+bg$+white$Ftext40$=16)+1)#P700: get the head def1344, 4752 0, 0 0, 0 0, 0, 0,i)ji$L 0, 0Q 0, 0V 0, 0[ 0, 1984` 1984, 2080e 2080, 4752j 4752, 4112o 4112, 5008t 5008, 2080y 2080, 1984~ 1984, 2336 2976, 2720 vsetctab(%15,%7,%13)setctab(%14,%13,%13)setctab(%14,%7,%7)setctab(%15,%13,%13)setctab(%15,%2,%2)setctab(%2,%4,%4)setctab(%7,%4,%4)setctab(%14,%4,%4)setctab(%15,%4,%4) i=015 j=01shape%(j0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)#s1x=x1n:s1y=y1n:s2x=x2n:s2y=y2n125=27300=13:40 250,6release:release:release@:JXsetctab(%7,%2,%7)bsetctab(%2,%7,%7)lsetctab(%14,%2,%13)lcolor(%14)0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)moveto(%x2n,%y2n)!pencolor(%7):fillcolor(%15)0drawimage(@shape%(0,0),%f%,%r%,%z%,%s%,%s%)&x1n-x2n)>10y1n-y2n)>10200moveto(%x1n,%y1n)!pencolor(%2):fillcolor(%14) x250.}x1n=s1x+x1m:x1n<37x1n>89x1m=-x1m:125/y1n=s1y+y1m:y1n<27y1n>134y1m=-y1m:130.x2n=s2x+x2m:x2n<37x2n>89x2m=-x2m:135/y2n=s2y+y2m:y2n<27y2n>134y2m=-y2m:140r%=s%*(r%=z%)moveto(%x1n,%y1n)!pencolor(%2):fil6,28688,12384,16384, 773, 3844, 8, 17925  96,24608,24640, 0, 1803, 7944, 17, 38405 64,16448,16384, 0, 3607,16144, 291, 7680 line$="" *i=0314line$=line$+128+i)>i Hcr0$=0);Rctrl$=1)+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$ \i=031fctrl$,2,1)=i)pcontrol(%17,@ctrl$)name$zi i=162ctrlist$(i)=2)+0)+head1$(i)+1)+head2$(i) ctrb$(i)=1)+0)+head2$(i)!ctre$(i)=1)+31)+head1$(i)i2ctrlist$(7)=2)+0)+head2$(2);14);:(nam$=q$+"/profile/basic/standard"+q$.getfont(@nam$,@array$):loadfont(@array$) &15);0Xtext40$;bw$]21);"9"; b::l i=06head1$(i)="":head2$(i)="" j=03a%:h$=a%)7head1$(i)=head1$(-/01he head definitionsZ800: load the print lined900: create zoom$ n600: set up screen xline$; 200,i=1231:control(%17,@zoom$(i))name$:160 Process keystrokes =27500 20021);"="27 a%(511),ctrlist$(7),head1$(6),head2$(6),zoom$(231))".d1/download.inv",".d1/request.inv")q$=34):array$="a%":name$=".console"(fg$=19):bg$=20)2mblue$=6):white$=15)<bw$=fg$+mblue$+bg$+white$Ftext40$=16)+1)#P700: get tGApple 1.1R READC 15:i=01:zshape%(i,j+8)=mshape%(i,j)::  0,0  0,0  0,0  0,1984 1984,2080 2080,4752 4752,4112 4112,5008 5008,2080 2080,1984 1984,2336 2976,2720  1344,4752  0,0  0,0  0,0ԕgrafixmode(%3,%2):grafixongrafixmode(%3,%1)moveto(%k+28,%j)1drawimage(@zshape%(0,0),%f%,%r%,%z%,%s%,%t%) grafixonka$:a$)<>27105,release:release:release6:@J&j=015:i=01:mshape%(i,j)::4j=0)+r(%4)Cfillcolor(%7):fillport Dviewport(%40,%100,%15,%130)Efillcolor(%13):fillportFgrafixmode(%3,%1) Kgrafixon Nviewport(%40,%100,%15,%130)ds%=16:t%=32:z%=0:f%=4 ik=0100nj=k/5+2)*53+88si=11000:}r%=s%*(r%=z%) ~ mshape%(1,15),zshape%(1,31)".d1/bgraf.inv"#1,".grafix" 1000#initgrafix(grafixmode(%3,%1)-pencolor(%4)2fillcolor(%7):fillport 7viewport(%40,%100,%15,%130)<fillcolor(%13):fillportAgrafixmode(%3,%2)Bpencolo0)+1)+head1$(0) ctrb$(7)=1)+0)+head1$(0)!ctre$(7)=1)+31)+head2$(0)31)+head2$(0)i)+h$,1,2)))+h$,3,2)))j j=03a%:h$=a%)7head2$(i)=head2$(i)+h$,1,2)))+h$,3,2)))ji" 7215,32545,838,15360,0,0,0,0& 14430,32322,1548,30720,0,256,1,0( 28732,31748,3096,28672,1,769,2,256+ 24696,30728,6192,24576,258,1794,4,768-  16496,28688,12384,16384,773,3844,8,1792(  96,24608,24640,0,1803,7944,17,3840* 64,16448,16384,0,3607,16144,291,7680 line$="" *i=0314line$=line$+128+i)>i Hcr0$=0);Rctrl$=1)+cr0$+cr0$mount of similarity in structure with other programs in that treatise. The trick last time to moving lots of bug heads smoothly was to print alternating sets of character 128 and character 129 across the screen and then download definitions of each chare question that somewhat naturally came up was "How can I move just one head across the screen?". Curiously enough, its a little harder, enough so that its worth showing a program to accomplish it. If you read last month's article, you'll notice a fair ar download" capability of the .console driver to create smooth animation by rapid switching of character definitions. We proved how powerful the technique was by smoothly scrolling hundreds of little bug heads from one side of the screen to the other. Thracter graphic animation, and then plunge headlong into the Apple /// bit-mapped display, most notably the 140X192 sixteen color mode. A Last Issue from Last Time As you may remember, one of the major events from last time was the use of the "character "News and Views" this month. We've got a lot of material to go over, and after several months at this, it will be assumed that you are pretty familiar with the concepts. This issue will cover one last technique (oh, no! not the Last Technique!) for chadeas in this series utilize the unique hardware and operating system capabilities of the ///, rather than just those of Business Basic, you can adapt most of the material whether you are working in Pascal, COBOL, FORTRAN or Assembler. That's about it fo/. Pascal in particular can make SOS calls and communicate to drivers through its own set of proceedures, similar to the Business Basic invokables. In fact, the Pascal equivalent of BGRAF is called PGRAF (clever, those Apple programmers!). Since the i2456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~h's article continues the never-ending (it seems that way) saga of graphics capabilities on the Apple ///. It's only fair to point out (as several of you have already) that many of the techniques shown in this series are useful from any language on the // T H E T H I R D B A S I C by Taylor Pohlman Exploring Business Basic, Part 20 Greetings, BASIC buffs! This montzoom$(z)=ctre$(z-224):tre$(z-224):2)+0)+head2$(0)+1)+head1$(0) ctrb$(7)=1)+0)+head1$(0)!ctre$(7)=1)+31)+head2$(0)z=17:zoom$(z)=ctrb$(z):x=030:i=174ctrlist$(i),2,1)=x):ctrlist$(i),11,1)=x+1) zoom$(7*(x+1)+i)=ctrlist$(i):'z=225231:+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$ \i=031fctrl$,2,1)=i)pcontrol(%17,@ctrl$)name$zi i=162ctrlist$(i)=2)+0)+head1$(i)+1)+head2$(i) ctrb$(i)=1)+0)+head2$(i)!ctre$(i)=1)+31)+head1$(i)i2ctrlist$(7)=acter which showed the head making a step-by-step transition from one character cell to the other. Since a character cell is seven dots wide, it takes eight steps to go from completely in one cell to completely in the next one. By reversing the process for every other cell, the illusion of smooth motion is created. To create the character cell definitions, we used the font and shape editor which was described in the February issue (part 17). However, in case you missed that issue, or couldn't summon thethe characters from 128 to 159 which are the displayable versions of character definitions 0 to 31. We could have used more characters, but it is necessary to skip character number 32 (space) or risk redefining every space character on the screen. As lon(0) 850 ctrl$=CHR$(1)+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$+cr0$ 860 FOR i=0 TO 31 870 SUB$(ctrl$,2,1)=CHR$(i) 880 PERFORM control(%17,@ctrl$)name$ 890 NEXT i 895 RETURN Notice in lines 810-830 that line$ is built containing all pear in an actual font definition). Next comes the routine to create a print string for the screen, and to redefine all the characters in it to blanks: 800 line$="" 810 FOR i=0 TO 31 820 line$=line$+CHR$(128+i) 830 NEXT i 840 cr0$=CHR$e routine above is identical to one discussed last time, so you're on your own. If you want to use a font editor to create the heads, just load up the 'head$' arrays in the same sequence as found in the DATA statements (which are arranged as they would ap, 2, 256 776 DATA 24696,30728, 6192,24576, 258, 1794, 4, 768 778 DATA 16496,28688,12384,16384, 773, 3844, 8, 1792 780 DATA 96,24608,24640, 0, 1803, 7944, 17, 3840 782 DATA 64,16448,16384, 0, 3607,16144, 291, 7680 Th(MID$(h$,1,2)))+CHR$(TEN(MID$(h$,3,2))) 755 NEXT j 760 NEXT i 765 RETURN 770 DATA 7215,32545, 838,15360, 0, 0, 0, 0 772 DATA 14430,32322, 1548,30720, 0, 256, 1, 0 774 DATA 28732,31748, 3096,28672, 1, 769:head2$(i)="" 720 FOR j=0 TO 3 725 READ a%:h$=HEX$(a%) 730 head1$(i)=head1$(i)+CHR$(TEN(MID$(h$,1,2)))+CHR$(TEN(MID$(h$,3,2))) 735 NEXT j 740 FOR j=0 TO 3 745 READ a%:h$=HEX$(a%) 750 head2$(i)=head2$(i)+CHR$(TEN GOSUB 800:REM load the print line 100 GOSUB 900:REM set up control strings 110 GOSUB 600:REM set up screen The first routine loads the head definitions, in this case from DATA statements: 700 RESTORE 710 FOR i=0 TO 6 715 head1$(i)=""ming and going. The other lines above establish constants which will be used later. Now, to initialize the data and get ready to scroll, we will use several routines, which will be discussed in turn: 80 GOSUB 700:REM get the head definitions 90 white$ 70 text40$=CHR$(16)+CHR$(1) Line 10 defines various arrays to be used in the program. 'Ctrlist$' contains the character redefinitions for downloading to the character generator, and the two 'head$' arrays contain definitions of the bug head, coproblem: 10 DIM a%(511),ctrlist$(7),head1$(6),head2$(6) 20 INVOKE"/basic/download.inv","/basic/request.inv" 30 q$=CHR$(34):array$="a%":name$=".console" 40 fg$=CHR$(19):bg$=CHR$(20) 50 mblue$=CHR$(6):white$=CHR$(15) 60 bw$=fg$+mblue$+bg$+ank. The program can then redefine the characters, one at a time, and give the appearance of motion across the screen, as each successive character is given the head definition. The following program illustrates one way to use this approach to solve the head across the screen is a little trickier than flipping one character definition to the next. The simplest solution is to print a string of characters across the screen, each one a different character number, but initially all defined to appear as a bl strength to type the whole thing in, the following program uses data statements to define the bug head transitions. Feel free to edit your own head definitions and substitute the approriate routine if you want. As was mentioned above, moving a single g as we just redefine control characters (0-31), we won't disturb anything important. Of course, with some thought, you can build 'line$' to any reasonable length. Next comes the routine which defines the character download strings, defining the successive versions of the characters: 900 FOR i=1 TO 6 905 ctrlist$(i)=CHR$(2)+CHR$(0)+head1$(i)+CHR$(1)+head2$(i) 910 ctrb$(i)=CHR$(1)+CHR$(0)+head2$(i) 915 ctre$(i)=CHR$(1)+CHR$(31)+head1$(i) 920 NEXT i 925 ctrlist$(7)=CHR$(2)+CHR$(or tables. By pre-storing the results of the various string substitutions in a large string array, the whole sequence can be rewritten as a simple loop. We will declare a string array 'zoom$' to accomplish this, with the following changes to the program e the routines at line 160 and line 185 are much faster than the main routine in lines 165-180. Although the routine can be speeded up somewhat, more drastic measures are required to make it substantially faster. The tradeoff, as usual, is memory space f0th character position, only to reappear again on the left of the screen. One thing is noticable, however. If you watch closely, the head appears to zip onto and off the screen much faster than it chugs across the main part of the screen. This is becausam$,@array$):PERFORM loadfont(@array$) 550 PRINT CHR$(15); 560 END Well, that's it. When you run this program, the little creature's head should appear on the left side of the screen, move smoothly to the right, and disappear somewhere around the 3p and exit routine at line 500, to wit: 200 OFF KBD 210 IF KBD=27 THEN 500 220 ON KBD GOTO 200 230 RETURN 500 PRINT CHR$(21);"=" 510 PRINT CHR$(22);CHR$(14); 520 TEXT:HOME 530 nam$=q$+"/basic/standard"+q$ 540 PERFORM getfont(@n_r_d___D_e_v_i_c_e___D_r_i_v_e_r_s___M_a_n_u_a_l on .Console control functions, and the 'Request.inv' documentation on the Basic disk. All that remains now of our program is the keyboard service routine at line 200 and the cleanuNotice that the same 'ctrlist$' definition is used each time, with the appropriate character numbers plugged in line 170. If you are unsure as to how the 'PERFORM control' statement works, review last month's article, the section in the _S_t_a_n_d_anto the first character position. Line 165-180 then set up a major loop to proceed through the characters in 'line$' (remember that they are now printed on the screen), taking each through the seven phase redefinition necessary for the smooth scrolling. rints the character string on the screen, and line 150 sets up an ON KBD jump to exit from the scrolling. Scrolling begins in line 160 by successively redefining the first character in the string through the seven phases required to bring the head fully i PERFORM control(%17,@ctrlist$(i))name$ 180 NEXT:NEXT 185 FOR i=1 TO 7:PERFORM control(%17,@ctre$(i))name$:NEXT 190 GOTO 160 We stated earlier that the animation would occur by successively redefining our string of characters. Line 120 preen to white. Now the fun begins: 120 PRINT line$; 150 ON KBD GOTO 200 160 FOR i=1 TO 7:PERFORM control(%17,@ctrb$(i))name$:NEXT 165 FOR x=0 TO 30:FOR i=1 TO 7 170 SUB$(ctrlist$(i),2,1)=CHR$(x):SUB$(ctrlist$(i),11,1)=CHR$(x+1) 175 screen setup routine: 600 PRINT text40$;bw$ 605 PRINT CHR$(21);"9"; 610 HOME:PRINT:PRINT 620 RETURN This just turns on the forty column mode, sets the color to blue on a white background, turns off character wrap (line 605), and clears the sce screen, there are two special arrays, 'ctrb$' and 'ctre'. 'Ctrb$' is the head definition as it appears onto the screen in the leftmost character position, while 'ctre$' is the definition of the rightmost character, as it disappears. Lastly comes the 0)+head2$(0)+CHR$(1)+head1$(0) 930 ctrb$(7)=CHR$(1)+CHR$(0)+head1$(0) 935 ctre$(7)=CHR$(1)+CHR$(31)+head2$(0) 940 RETURN Note that in addition to the 'ctrlist$' definitions above, which define the transitions of the characters in the middle of thabove: 10 DIM a%(511),ctrlist$(7),head1$(6),head2$(6),zoom$(231) 160 FOR i=1 TO 231:PERFORM control(%17,@zoom$(i))name$:NEXT 165 GOTO 160 940 FOR z=1 TO 7:zoom$(z)=ctrb$(z):NEXT 945 FOR x=0 TO 30:FOR i=1 TO 7 950 SUB$(ctrlist$(i),2,1)=CHR$(x):SUB$(ctrlist$(i),11,1)=CHR$(x+1) 955 zoom$(7*(x+1)+i)=ctrlist$(i) 960 NEXT:NEXT 965 FOR z=225 TO 231:zoom$(z)=ctre$(z-224):NEXT 970 RETURN Notice that we have added code in lines 940-970 to put the various string values inhe Apple /// graphics driver is exploited very little by programmers, but will be the subject of much of the rest of this article. One comment is important before we proceed, however. If you don't have a color monitor, there is no need for dispair. The ixel position at a time. As the string runs off the left side of the screen, the priority established in the color table insures that neither the fill or pen color will disturb the color 9 bars at the edge of the screen. This very powerful feature of t complete description of this process can be found in the Device Drivers manual and in the Business Basic manual (Volume 2), but running the program is the best way to see how this works. The loop in lines 80-90 makes the print string run backwards, one p the result will remain color 9. Lines 50-65 use the window capability to set up two orange (color 9) borders. Without the changes to the default color table, anything printed in the first or last column of the screen would destroy the borders. A fairlye, we set the primary colors to be 4 and 13, the fillcolor and pencolor respectively, in lines 35 and 40, and fill the screen with color 4 (dark green) . The color table definition in line 45 says that anytime color 4 or color 13 are printed over color 9,M moveto(%j,%180):PRINT#1;m$ 90 NEXT j 95 GET a$:IF ASC(a$)<>27 THEN 80 100 PERFORM release:PERFORM release:PERFORM release 105 CLOSE:INVOKE 110 TEXT 115 END Setting your Priorities In the little demonstration of color priorities abovcolor(%9) 55 PERFORM viewport(%0,%6,%0,%191):PERFORM fillport 60 PERFORM viewport(%133,%139,%0,%191):PERFORM fillport 65 PERFORM fillcolor(%4) 70 PERFORM viewport(%0,%139,%0,%191) 75 PERFORM grafixon 80 FOR j=7 TO-77 STEP-1 85 PERFOR m$=" ** **** ** **** *** * **** ** *****" 25 PERFORM initgrafix 30 PERFORM grafixmode(%3,%1) 35 PERFORM pencolor(%13) 40 PERFORM fillcolor(%4):PERFORM fillport 45 PERFORM setctab(%4,%9,%9):PERFORM setctab(%13,%9,%9) 50 PERFORM fillure 'setctab' is used to change single color entries in the table in a much easier manner than the .grafix driver permits directly. Type in the following program, and we'll begin our exploration: 10 INVOKE"/basic/bgraf.inv" 15 OPEN#1,".grafix" 20 s driver, the setting of priorities in the 'color table'. Remember that all communication to and from the actual bit-map is via the .grafix driver, and the Bgraf.inv routine is used to make the functions of the driver easier to perform. The Bgraf proceedding out bits of data from certain areas of memory and translating them to dots (pixels) on the display screen. As a reminder, let's look at the program we concluded with last time, which gives a hint as to an important capability of the Apple /// graphiche preceeding retrospective into character graphics was important to clear up some issues, the real purpose of this article was to get heavily involved in the graphics modes of the Apple ///, called a "bit-mapped" display, since the image is created by reaexample, by splitting up the string and printing it in various places on the screen, you can cause the head to move around, disappear from one spot, only to re-appear somewhere else. Have fun! Can't Tell One Pixel from Another Without a Bit Map While tto the 'zoom$' array, and therefore line 160 now performs the entire sequence, much faster than before (you can now delete lines 170-190). The difference in speed should be really noticeable. The uses of this basic idea are practically unlimited. For Apple /// automatically translates color output into sixteen shades of gray (or green) on your monochrome display, and the color values in the following examples were arrived at to make sure that they would look OK without color. So, get a good grip on your 'BGRAF.INV' module, 'cause here we go! Becoming a Fan of Hi-res Graphics The program below illustrates the abilities of the color priority table on a much grander scale, and even suggests how the capability can be used to give the illusion of depth t bars on the screen, after first turning on the screen and clearing to the background color you have just chosen: 220 PERFORM grafixon 230 PERFORM fillcolor(%a):PERFORM fillport 300 PERFORM viewport(%20,%30,%40,%170) 310 PERFORM fillcolor(%blaackground color for the screen. You should choose this carefully, since the color table will affect the results of certain choices. Colors 7, 11 and 14 should give good results. Next, we'll use the viewport, fillport combinations to create various color to worry about it. Oh, well, enough praise for .grafix. To continue: 200 INPUT"Background color number: ";a$ 210 a=VAL(a$):IF a$="" OR a<0 OR a>15 THEN 510 To further see the effect of the color table, the program allows you to set the overall bkgrounds! Checking on every spot on the screen to see what color is already there would be incredibly time-consuming. Since the color table is built into the .grafix driver, using it causes the check to be done at assembly language speeds, without having orange, but has no effect on green and white. Yellow effects everything but white. These statements are easy to understand, and could be programmed in simple background situations, but imagine what it would be like to draw lines or shapes on complex bacawn. As you can see, dark green won't affect anything but the background, since drawing dark green over blue, orange, green or white will have no effect. Brown, however, will draw over blue, but loses to orange, green and white. Grey draws over blue andRFORM setctab(%grey%,%green%,%green%) 1080 PERFORM setctab(%grey%,%white%,%white%) 1090 PERFORM setctab(%yellow%,%white%,%white%) 1100 RETURN In the case above, we are using the color table to establish priorities for the 'vector' colors to be dr20 PERFORM setctab(%dgreen%,%green%,%green%) 1030 PERFORM setctab(%dgreen%,%white%,%white%) 1040 PERFORM setctab(%brown%,%orange%,%orange%) 1050 PERFORM setctab(%brown%,%green%,%green%) 1060 PERFORM setctab(%brown%,%white%,%white%) 1070 PEwill be used for the rest of this article. After initializing the graphics screen, we set up the changes to the color table in a routine at line 1000: 1000 PERFORM setctab(%dgreen%,%blue%,%blue%) 1010 PERFORM setctab(%dgreen%,%orange%,%orange%) 100 GOSUB 1000 The program opens with the usual initalization, and defines a number of variables as color constants in lines 120-140. Line 150 sets the graphics mode to three, the 140X192 color screen. This is the unrestricted sixteen color mode, which /basic/bgraf.inv" 120 black%=0:blue%=6:orange%=9:green%=12:white%=15 130 dgreen%=4:brown%=8:grey%=10:yellow%=13 140 vector(1)=dgreen%:vector(2)=brown%:vector(3)=grey%:vector(4)=yellow% 150 PERFORM grafixmode(%3,%1) 160 PERFORM initgrafix 17dition, the default is what you would expect, that is, the color you plot with is the color you get on the screen. Without further ado, let's look at the program: 50 REM 7, 11 and 14 are best background colors 100 OPEN#1,".grafix" 110 INVOKE" a misnomer, actually, since the entrys in the table can produce any color as a result of plotting one color over another. Its just as easy to specify that plotting dark green over orange will produce white as to say that orange will be unaffected. In ado an image on the screen. As explained in the Basic manual section on 'SETCTAB', every pixel to be plotted on the screen is first passed through the color table, and converted, if necessary, before being actually drawn. The word "priority" is somewhat ofck%):PERFORM fillport 320 PERFORM viewport(%35,%40,%30,%160) 330 PERFORM fillcolor(%blue%):PERFORM fillport 340 PERFORM viewport(%52,%65,%40,%170) 350 PERFORM fillcolor(%orange%):PERFORM fillport 360 PERFORM viewport(%77,%92,%35,%175) 370 PERFORM fillcolor(%green%):PERFORM fillport 380 PERFORM viewport(%110,%120,%20,%170) 390 PERFORM fillcolor(%white%):PERFORM fillport Note that normally you would set up the screen, and then turn on the display (i.e. move statement 220 to after 390)A 2080,1984 2050 DATA 1984,2336 2055 DATA 2976,2720 2060 DATA 1344,4752 2065 DATA 0, 0 2070 DATA 0, 0 2075 DATA 0, 0 Lines 1000-1020 read the contents of the data statements into the mshape% array, thereby 1020 RETURN 2000 DATA 0, 0 2005 DATA 0, 0 2010 DATA 0, 0 2015 DATA 0,1984 2020 DATA 1984,2080 2025 DATA 2080,4752 2030 DATA 4752,4112 2035 DATA 4112,5008 2040 DATA 5008,2080 2045 DATtion, along with movement. The x% and y% arrays will be covered in a minute. After invoking the 'bgraf.inv' module, we gosub to line 1000 for the shape definition, like so: 1000 RESTORE 1010 FOR j=0 TO 15:FOR i=0 TO 1:READ mshape%(i,j):NEXT:NEXT grafix" 20 GOSUB 1000 Mshape% in line 5 is the array which will contain the creature's shape definition, in two parts. The first part (column) will show the tenacles extended, the second column defines the tenacles retracted. This allows simple anima-res screen. The program below defines the creature, and lets us move him (ugly creatures are always male) around on the screen. We begin with the usual declarations: 5 DIM mshape%(1,15),x%(255),y%(255) 10 INVOKE"/basic/bgraf.inv" 15 OPEN#1,".eature, somewhat larger than his character graphics ancestors, which was originally created using the Shape Editor from the February issue. We will use this new kind of "bug" (which really resembles a squid), to begin our discussion of animation on the hiatures from space, right? So let's bring on the bugs! Actually, it is useful to look at a combining of the techniques which we have already discussed with the new capabilities of the bit-mapped graphics display. The following program introduces a new cr You might try setting different result colors, for example, setting some to the background color, and observing the effects. The Bugs are Back Although the program listed above is interesting, even dramatic in its own way, you're paying to see the creERFORM release:PERFORM release 530 INVOKE:CLOSE 540 END Running the program above with various background colors and various settings of the color table will allow you to experiment with the SETCTAB proceedure enough to get to know its capabilities.source. Because of the color priorities established, the effect is quite dramatic, since the rays appear to go behind some objects, and in front of others. Pressing Escape in line 500 terminates the program, like so: 510 TEXT 520 PERFORM release:P sets the viewport to the whole screen, and then uses a double loop to draw lines from the point x=0,y=96 (middle of the left side of the screen) to various points on the right hand side. The effect is somewhat like a fan, or rays projected from a single OR j=1 TO 10 430 horiz=(i-1)*45+j*4 440 PERFORM moveto(%140,%horiz) 450 PERFORM pencolor(%vector(i)) 460 PERFORM lineto(%0,%96) 470 NEXT j 480 NEXT i 500 GET a$:IF ASC(a$)<>27 THEN TEXT:GOTO 255 The routine abovetatements is identical except for parameters, but this way you get a feel for exactly what's going on. Next, we draw vectors over our landscape, and observe the color table effects: 400 PERFORM viewport(%0,%139,%0,%192) 410 FOR i=1 TO 4 420 F. In this case, its worth looking at how the color bars are set up, especially if you use different background colors than those suggested. The lines above could be replaced by some data statements and a loop for more compactness, since each set of two sdefining the two versions of our creature. Hang on to these data statements, they will be used in several other programs later on in this article, and they are really too dull to repeat. Next comes the screen setup: 25 PERFORM initgrafix 30 PERFORM grafixmode(%3,%1) 35 PERFORM fillcolor(%4):PERFORM pencolor(%13) 40 PERFORM fillport 45 PERFORM viewport(%0,%139,%0,%191) 50 PERFORM grafixon The lines above clear the screen to dark green and set the pen color to yellow. Note that we againline 61 corresponds to the character '7', which is in the upper left-hand corner of the keypad. Both x% and y% are affected, x% being decremented (indicating movement to the left) and y% being incremented (indicating movement up). This combination create3 x%(52)=-3:x%(54)=3:y%(56)=3:y%(50)=-3 The lines above set up additional definitions of possible X and Y movements. Close examination of your ASCII chart will show that the codes correspond to numbers on the numeric pad of the Apple ///. ASCII 55 in y the program above. You should have some fun watching the creature swim around the screen at your command. For a little more excitement, try adding the following: 61 x%(55)=-3:y%(55)=3:x%(49)=-3:y%(49)=-3 62 x%(57)=3:y%(57)=3:x%(51)=3:y%(51)=-3 6he new location. If the character typed is an Escape (27), then cleanup and termination is done: 100 TEXT 105 PERFORM release:PERFORM release:PERFORM release 110 CLOSE:INVOKE 115 END If you type nothing else in from this article, at least trre 'off' (0's) are drawn in the current fillcolor. Lines 85 and 90 get keystrokes and modify the values of 'i' and 'j' according to the contents of that character location in the 'x%' and 'y%' arrays and then jump back to 70 to redisplay the creature at traw from that point, and the number of rows to draw. This is sufficient information to define any arbitrary rectangular block of bits in any given array. Any bits in the array that are 'on' (that is, 1's) are drawn in the current pencolor, and any that ato specify a source array, the number of bytes in a given row of the array (needed to find the offset for row 2, etc.), the number of bits to skip in the row before drawing, the number of rows to skip in a column before drawing, the number of row bits to dscussion of 'drawimage', but fundamentally, the parameters look like this: PERFORM drawimage(@array,%Num.Row.Bytes,%X.skip,%Y.skip,%Dr.width,%Dr.height) This definition parallels, of course, the DrawBlock capability of the .Grafix driver, and allows you ernate between 0 and 16, which will be our bit index into the mshape% array. The 'drawimage' proceedure (from 'bgraf.inv') is then used to put the appropriate bit pattern on the screen, at the current pen location. See your Basic manual for a specific di@mshape%(0,0),%f%,%r%,%z%,%s%,%s%) 85 GET a$:a=ASC(a$) 90 IF a<>27 THEN i=i+x%(a):j=j+y%(a):GOTO 70 The lines above constitute the main loop of the program. After moving to the position established by the initial values of i and j, r% is set to altechniques are wasteful of space, but increase speed. We'll see an even more interesting application of this technique in just a minute. For now, on with the program: 70 PERFORM moveto(%i,%j) 75 IF r%=0 THEN r%=16:ELSE r%=0 80 PERFORM drawimage(n. That makes it obvious that we will be using values in the x% and y% arrays to indicate the amount and direction of movement depending on which cursor key is pressed (left and down being negative movements, respectively). As we have seen before, such t. A quick check of your keyboard chart should tell you that ASCII 8 is the left arrow key, 21 is the right arrow key, 11 is the up arrow and 10 is the down arrow. Left and right correspond to movement in the X direction, and up and down in the Y directio use the 140X192 color mode. After this setup we initialize some general variables: 55 f%=4:s%=16:z%=0 60 x%(8)=-3:x%(21)=3:y%(11)=3:y%(10)=-3 65 i=70:j=90 Of note above is line 60, which establishes some entries into the large x% and y% arrayss diagonal motion. Quick comparisons with the rest of the characters will show the remaining relationships. Add these lines and run the program again. You'll find that you can control the creature completely from the pad! Note also that changing the constant value will change the amount of movement in any direction. Onward, Ever Diagonally Here's hoping that the program above has whetted you appetite for more creature features. The next program will combine creature movement with the windowing techne% is used where possible. Note also that the X positions are offset from each other, with the boundaries of the window responsible for "clipping" the images until they are within the display area. Running this program will produce images of bouncing cre 130-155 then move to each unique location, draw the appropriate creature image, and go on. Note that the incremental movement of the first and third shape is great enough that we need to use the zshape% version. Since zshape% takes longer to draw, mshapRFORM moveto(%k,%m) 155 PERFORM drawimage(@zshape%(0,0),%f%,%r%,%z%,%s%,%t%) 160 NEXT k 200 GET a$:IF ASC(a$)<>27 THEN 105 The effect of the statements in lines 110-120 is to create different y values for each of three creature images. Lines58 120 m=SIN(k/10)*70+85 125 r%=s%*(r%=z%) 130 PERFORM moveto(%k+28,%j) 135 PERFORM drawimage(@zshape%(0,0),%f%,%r%,%z%,%s%,%t%) 140 PERFORM moveto(%k+14,%l) 145 PERFORM drawimage(@mshape%(0,0),%f%,%r%,%z%,%s%,%s%) 150 PE to 32767), the only visible effects will occur in the 40,130 to 100,15 window. Next, we get to the draw section, which is quite a bit more elaborate: 100 s%=16:t%=32:z%=0:f%=4 105 FOR k=0 TO 100 110 j=COS(k/5+2)*53+88 115 l=SIN(k/10)*30+PERFORM fillport 55 PERFORM viewport(%40,%100,%15,%130) 60 PERFORM fillcolor(%13):PERFORM fillport 65 PERFORM grafixon Note above that although the graphics routines will let us draw anywhere on the screen (and anywhere off the screen from -32768nough for the tricks we are about to pull. Next, we initalize and declare a viewport, in which the visible part of our operations will occur: 35 PERFORM initgrafix 40 PERFORM grafixmode(%3,%1) 45 PERFORM pencolor(%4) 50 PERFORM fillcolor(%7):se the same data statements from the last program, and, once the mshape% array is defined, we load the middle of the zshape% array with it. The offset in the rows between mshape% and zshape% gives eight extra blank rows at the top and bottom of zshape%, eay. This array is initalized in the routine at 1000, as follows: 1000 RESTORE 1010 FOR j=0 TO 15:FOR i=0 TO 1:READ mshape%(i,j):NEXT:NEXT 1020 FOR j=0 TO 15:FOR i=0 TO 1:zshape%(i,j+8)=mshape%(i,j):NEXT:NEXT 1030 RETURN Please note that we u on the screen, we will do the following: 10 DIM mshape%(1,15),zshape%(1,31) 15 INVOKE"/basic/bgraf.inv" 20 OPEN#1,".grafix" 25 GOSUB 1000 The difference above is that we introduce the zshape% array, with twice as many rows as our mshape% arrm are completely zero. Some analysis of the row values will prove that the same is true about zero bits on the left and right sides of the columns. To allow our next program some freedom as to how much displacement an image can have without leaving trashthree pixels in any direction, when we move five at a time, some old bits are left on the screen without being cleaned up by the next occurance of drawimage. A quick glance at the data statements will show that only three rows on top and three on the bottotry: 60 x%(8)=5:x%(21)=-5:y%(11)=5:y%(10)=-5 Now use the cursor keys. Makes a mess, right? Right. What happens is that while the previous drawblock image had enough fillcolor bits (zero value bits) surrounding the image to blank out any movement of iques of the graphics driver to create interesting motions of several creatures at once. First, however, some fooling around should be encouraged. Try changing the displacement constants in the previous program to values higher than three. For example, atures, zipping through a box-like window on the screen. Like most programs, this one has a cleanup section: 300 PERFORM release:PERFORM release:PERFORM release 310 CLOSE:INVOKE 320 TEXT 330 END There, have fun with that one! By the way, if you want to edit your own creatures for the previous program, on any to follow, you can use the February Shape Editor, and make the following changes to the program above: 10 DIM shape%(7,15),mshape%(1,15),zshape%(1,31) 15 INVOKE"/basic/bgraf.inv"s cross. Lines 620-655 insure that the background (fill) colors will always translate to yellow (13), the background color of the box in which our creatures will live (and bounce). Study this carefully, until you are sure as to what is going on. Finallyblue creature will use a fillcolor of aqua (14) and the light blue one will use fillcolor white (15). As you can see from lines 600-610, the dark blue creature will always appear to pass behind (be covered up by) the light blue creature, should their pathsetctab(%7,%4,%4) 670 PERFORM setctab(%14,%4,%4) 675 PERFORM setctab(%15,%4,%4) 690 RETURN As the routine above might tend to indicate, we will employ two creatures in this demonstration, one dark blue (color 2) and one light blue (7). The dark 20 PERFORM setctab(%14,%2,%13) 630 PERFORM setctab(%15,%7,%13) 640 PERFORM setctab(%14,%13,%13) 645 PERFORM setctab(%14,%7,%7) 650 PERFORM setctab(%15,%13,%13) 655 PERFORM setctab(%15,%2,%2) 660 PERFORM setctab(%2,%4,%4) 665 PERFORM a window of yellow created by lines 50-55. Then a dark green square is drawn in the middle of the box by lines 60-65, and we go the the routine at 600 to set up our color table scheme: 600 PERFORM setctab(%7,%2,%7) 610 PERFORM setctab(%2,%7,%7) 65,%130) 55 PERFORM fillcolor(%13):PERFORM fillport 60 PERFORM viewport(%60,%80,%62,%82) 65 PERFORM fillcolor(%4):PERFORM fillport 70 GOSUB 600:REM set color table After clearing the screen to gray in line 40, We print the title "Bug Box" above 1020 RETURN Now on to setting up the screen: 30 PERFORM initgrafix 35 PERFORM grafixmode(%3,%1) 40 PERFORM fillcolor(%5):PERFORM fillport 45 PERFORM moveto(%45,%145):PERFORM pencolor(%0):PRINT#1;"Bug Box" 50 PERFORM viewport(%40,%99,%10 OPEN#1,".grafix" 25 GOSUB 1000 The lines above are the usual warmup. The routine at 1000 is the usual, and uses the data statements from the previous programs, to wit: 1000 RESTORE 1010 FOR i=0 TO 15:FOR j=0 TO 1:READ mshape%(j,i):NEXT:NEXT e square blocks "balls") bouncing off the walls of a video room, not unlike the old "Pong" game. Since we have already shown how to endow our creations with X and Y movements, this should be easy: 10 DIM mshape%(1,15) 15 INVOKE"/basic/bgraf.inv" 2apes to move through some rather elaborate paths. The program below puts together everything we have covered so far, and borrows from an idea in the old _A_p_p_l_e_s_o_f_t___T_u_t_o_r_i_a_l manual, that of objects (the called the littl1000 to 1090 above can be used as a general purpose shape load routine. Note the addition of the 'Request.inv' invokable to do the reading of the shape file. Wrapping It All Up and Bouncing It Off a Wall The program above proves that you can get the sh0 error=1:REM Not a shape file 1060 RETURN 1070 READ#3,1:PERFORM filread(%3,@array$,%256,@ret%):OFF ERR:CLOSE#3 1080 IF ret%<>256 THEN error=2:RETURN:REM Shape definition is invalid 1090 error=0:RETURN:REM Shape loaded The routine from =0 TO 1:zshape%(i,j+8)=mshape%(i,j):NEXT:NEXT 1000 ON ERR GOTO 1030 1010 array$="shape%":OPEN#3,file$ 1020 ftype=TYP(3) 1030 IF ftype=1 THEN READ#3;filtyp,ch,cw,sl:IF filtyp=1 THEN 1070 1040 OFF ERR:CLOSE#3:IF ftype=0 THEN DELETE file$ 105,"/basic/request.inv" 22 INPUT"Shape file name: ";file$ 24 IF file$="" THEN 300 28 IF error THEN PRINT"Error number "error" in file '"file$"'.":GOTO 22 30 FOR j=0 TO 15:FOR i=0 TO 1:mshape%(i,j)=shape%(i,j):NEXT:NEXT 32 FOR j=0 TO 15:FOR i, lines 660-675 insure that any movement in the area of the dark green (4) box will be hidden, that is, appear to go behind that object, since all colors drawn onto color 4 will result in color 4 on the screen. Now that our colors are set, on with the show: 75 PERFORM viewport(%40,%99,%15,%130) 80 PERFORM grafixon 100 f%=4:s%=16:t%=32:z%=0 105 s1x=INT(RND(1)*40)+40:s1y=INT(RND(1)*115)+15 110 s2x=INT(RND(1)*40)+40:s2y=INT(RND(1)*115)+15 115 x1m=3:y1m=3:x2m=3:y2m=3 120 ON KBD GOTO 250 CLOSE:INVOKE 330 END Does the usual cleanup. A Cheerful Farewell This month's article should give you lots to work on. As you might imagine, the color table presents all sorts of possibilities that this missive could only hint at. Next time we'lllor table affects the creatures when they cross over, but the random values put them on paths that don't cross. You just press RETURN and start over with a new scenario. Finally: 300 TEXT 310 PERFORM release:PERFORM release:PERFORM release 320 HEN POP:GOTO 40 265 ON KBD GOTO 250 270 RETURN This ON KBD routine allows termination (with Escape (27)) and if RETURN is pressed, the program starts all over with new random locations for the creatures. This is useful if you want to see how the coChanging the values of x1m, x2m, y1m and y2m will effect the type, length and angle of bounce. Experiment and see what you like (random numbers are fun too!) A little more and we're finished: 250 OFF KBD 255 IF KBD=27 THEN 300 260 IF KBD=13 Thout these lines to see what happens. In either circumstance, line 200 sets the current positions of the creatures to the positions just used, and starts over. The effect is that of the two beasts bouncing off the four walls in quite a regular fashion. part of the its image, which subsequent repositioning of the creatures cannot recreate. Lines 180-195 check for this possiblity and redraw creature number one, to fill in any missing parts before the next erase at the top of the loop. Try the program witthe colors and draw the image. Lines 165-175 do the same for the second creature. Now comes something interesting. Creature number two has priority over creature number one, if they are in the same space. Therefore drawing over number one will destroy (0,0),%f%,%r%,%z%,%s%,%s%) 200 s1x=x1n:s1y=y1n:s2x=x2n:s2y=y2n 205 GOTO 125 Notice again that we use r% to calculate the offset into the mshape% array to animate our creature. Lines 150-160 move to the calculated position of our first creature, set ):PERFORM fillcolor(%15) 175 PERFORM drawimage(@mshape%(0,0),%f%,%r%,%z%,%s%,%s%) 180 IF ABS(x1n-x2n)>10 OR ABS(y1n-y2n)>10 THEN 200 185 PERFORM moveto(%x1n,%y1n) 190 PERFORM pencolor(%2):PERFORM fillcolor(%14) 195 PERFORM drawimage(@mshape%he positions calculated above: 145 r%=s%*(r%=z%) 150 PERFORM moveto(%x1n,%y1n) 155 PERFORM pencolor(%2):PERFORM fillcolor(%14) 160 PERFORM drawimage(@mshape%(0,0),%f%,%r%,%z%,%s%,%s%) 165 PERFORM moveto(%x2n,%y2n) 170 PERFORM pencolor(%7e within the ranges of the window. Note that the pen position is always the upper lefthand corner of the drawblock image, which explains the differences in the values from the viewport statement above. Now we get into the actual draw routines, based on t x2n=s2x+x2m:IF x2n<37 OR x2n>89 THEN x2m=-x2m:GOTO 135 140 y2n=s2y+y2m:IF y2n<27 OR y2n>134 THEN y2m=-y2m:GOTO 140 The lines above add the X and Y increments (or decrements, if negative) to their respective values, and check to see if the results ar 250 to get us out of the program. We now start the loop which will bounce our creatures off the walls of their tiny domain: 125 x1n=s1x+x1m:IF x1n<37 OR x1n>89 THEN x1m=-x1m:GOTO 125 130 y1n=s1y+y1m:IF y1n<27 OR y1n>134 THEN y1m=-y1m:GOTO 130 135 The lines above establish a viewport for operations, and set up the initial random X and Y locations for our two creatures (lines 105-110). Line 115 sets the increment of movement in each direction for each creature, and 120 establishes an ON KBD jump to wrap up our discussion of graphics and get on to more interesting doings with the Apple ///. Until then... "mshape%(1,15),x%(255),y%(255) ".d1/bgraf.inv"#1,".grafix" 1000initgrafixgrafixmode(%3,%1)!#fillcolor(%4):pencolor(%13) (fillport-viewport(%0,%139,%0,%191) 2grafixon7f%=4:s%=16:z%=0(<x%(8)=-3:x%(21)=3:y%(11)=3 should be able to easily order it for you from Apple. The second announcement is a great one for those of you who read this article wistfully, because you have an Apple ][ and keep wondering what all the fuss is about concerning the Apple ///, or becaund character drivers and the SOS manual contains a diskette with a program called "EXER-SOS", designed to help debug drivers and other routines by providing a full interface to operating system and driver 'calls'. If your local dealer doesn't stock it, hevorite machine really works. If anybody you know thinks SOS isn't the best single user operating system around, show him a copy! In addition to great explanations of the inner workings, the Device Drivers manual contains listings of sample disk (block) aegin are appropriate. First, the long awaited SOS Reference Manual and Device Drivers Writer's Guide came off the presses in April and should have reached the far corners of the earth by now. They are an incredible wealth of information about how your fa T H E T H I R D B A S I C by Taylor Pohlman Exploring Business Basic - Part 21 Two quick announcements before we bARTICLE21v' '*ARTICLE.21J080  2080,1984  1984,2336  2976,2720   1344,4752  0,0  0,0  0,0 0,0 <>27i=i+x%(a):j=j+y%(a):70direlease:release:releasen:s&j=015:i=01:mshape%(i,j)::  0,0  0,0  0,0  0,1984  1984,2080  2080,4752  4752,4112  4112,5008  5008,2:y%(10)=-3*=x%(55)=-3:y%(55)=3:x%(49)=-3:y%(49)=-3(>x%(57)=3:y%(57)=3:x%(51)=3:y%(51)=-3)?x%(52)=-3:x%(54)=3:y%(56)=3:y%(50)=-3 Ai=70:j=90Fmoveto(%i,%j)Kr%=0r%=16:r%=01Pdrawimage(@mshape%(0,0),%f%,%r%,%z%,%s%,%s%)Ua$:a=a$)#Zase you need another Apple /// for your business, etc. Apple dropped the price of a 256K Apple /// in April to $2695! That's a full $1600 less than this time last year, and represents (in this humble Apple /// owner's opinion), the best bargain in personal computers anywhere. So much for the commercial. And Now, Back to our Regularly Scheduled Program As was mentioned last time, this article is the last in a series exploring the text and bit map modes of graphics on the Apple ///. We've covered a grea,e columns of numbers, they are really important. For ordinary text, however, monospacing is not only less natural and attractive, it wastes space as well. In fact, several word processors for the Apple ][ use the 280X192 graphics mode to create "proporti much room as an "M" or "X", yet in standard computer output they do, in order that all columns will automatically line up properly, and that editing can be simplified. Such constant spacing techniques are called "Monospacing", and for certain things, likrtionally" spaced, that is each character is arranged to be the minimum distance from the ajoining character, not evenly spaced as in normal computer printouts and screen displays. It's easy to see that the characters "i" and "l" don't take up nearly asay, but the fact that the characters are pleasingly arranged on the screen, more like text is found in a magazine or book than that found on a computer terminal. The fundamental difference in the display modes is that all text on the Lisa screen is "propoBy now many of you have probably looked at a photograph, if not an actual demo, of Apple's new Lisa system. One of the things which immediately strikes people is how pleasing the display looks. When you analyze it, it's not only the high-resolution displng possibilities, among which is the ability to really dress up the appearance of text on the screen. It is on this intriging capability that our final (for a while) discussion of the BGRAF invokable module will rest. Beauty in "Proportion" to its Cost isodes, we've been dealing with DrawImage's shape drawing ability, to populate our screen with creatures of various shapes which crawled their way into our hearts. The marriage of the DrawImage flexibility with a text character set presents some interestising the BGRAF module, it is possible to assign a new character set to be used by DrawBlock. It is also possible to use the DrawImage function of the module to draw any shape (including text characters) onto the graphics screen. For the last couple of epce that the printing of text characters on the graphics screen is handled by the DrawBlock function of the driver, writing out the bit patterns of each character from the currently defined character set (normally the set used by the .CONSOLE driver). By u but what does that have to do with the graphics invokable in Business Basic? If you carefully read the sections in your Basic manual on the BGRAF invokable module, and the section in the Standard Device Drivers manual on the .GRAFIX driver, you'll notie time may be a bit confused by the last sentence in the paragraph above. "I know how to do text on the graphics screen", you say, "just OPEN the .GRAFIX driver and print characters to it like any other driver!". Right as rain, as they say in California,s it even more reasonable that the last in the graphics series (at least for now) covers a combination of the two worlds, text on the bit-mapped graphics display. Farewell, Faithful BGRAF.INV Those of you who have been following these articles for somt deal in the last three months, from simple character set and shape definitions, through character set animation effects (including a game!!!!) and finally to color bit-mapped graphics with it's own brand of animation. That's a lot of territory, and makeonal" character sets. These programs allow up to 70 characters across a screen which can accomidate only 40 monospaced characters! We will learn in this article that the higher resolution of the Apple /// allows us to get over _o_n_e___h_u_n_d_16 4060 FOR i=0 TO 255:a$=HEX$(i):flip(i)=v16*lookup(TEN(MID$(a$,4,1))) +lookup(TEN(MID$(a$,3,1))):NEXT The section from lines 4000 to 4060 above is identical to routines in previous programs. It creates the 'flip' array, which is simply a loolay from that point. Let's look at the initialization section, where this will become more clear: 4000 REM initialize 4025 DATA 0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15 4045 FOR i=0 TO 15:READ lookup(i):NEXT 4055 v256=256:v512=512:v128=128:v16=cessary to define for each character cell just how much of the character in it we want to display. In this program that is accomplished by defining the starting pixel row within the character cell to start the display, and the number of pixel rows to dispacter associated with the element number and the names should be a clue as to what that information is. The characters in a normal character set are stored in blocks one byte wide in the 'char' array, but since we want to do proportional spacing, it is nean operate on. 'Lookup' and 'flip' are used to accomplish this transformation quickly. Which brings us to the 'cstart' and 'clen' arrays. Their size of 128 elements each should be a clue that each element contains information about the respective chart we'll go with for now. 'Cset' contains the actual image of a system font file, as read in by the "download.inv" invokable module. We'll look at a conversion routine which transforms fonts in the system format into character set definitions that BGRAF cused for defining flash in inverse text mode (7X8 displayable). Those of you who read the documentation will notice that a .BGRAF character set can actually contain 256 character definitions, but the standard system fonts are limited to 128, so that's whamiliar. 'Char' contain the character set of our choice and it is defined as being 128 bytes wide by 8 rows high, enough to contain the 128 ASCII character definitions in a standard font, which is 8X8 pixels per character, with the right-most pixel column ait" 25 GOSUB 4000 The first section sets up our arrays and goes to the subroutine at 4000 to load up tables and do other initialization. For those of you who have been following this series, the arrays 'char', 'cset', 'lookup' and 'flip' should be far own non-standard sizes. There's plenty to cover, so let's go... 10 DIM char%(63,7),cset%(511),lookup(15),flip(255),cstart%(127),clen%(127) 15 HOME:PRINT"High Resolution Screen Character Editor":PRINT 20 PRINT"Initializing variables, please w the .GRAFIX driver you can have individual characters which are much larger than the normal 7X8 character cell definition. The program deals with normal size character fonts, but we'll discuss easy modifications which are possible if you want to use you as overstrikes and erasures. The best feature of the program, however, is that it contains lots of routines you can use to create your own hi-res displays, both with the currently available fonts, and any of your own design. Remember that with BGRAF andks like a high resolution screen editor for text. The editor program permits you to place porportional or mono-spaced text anywhere on the screen, use multiple fonts on the same screen, and use the graphics driver "transfer mode" feature to do such thingsr_e_d___c_h_a_r_a_c_t_e_r_s across the screen, with no sacrifice in readability! Beauty on a Budget This month's program allows you to play with the concepts of proportional spacing and text font appearance from within a program which workup table of all the possible combinations of the value of a byte of data (256 in all) with their values if the bits in the byte were exactly reversed, that is, flipped over. This table is required by the routine which transforms a character set from system font format to .GRAFIX format. Apple cleverly made these two formats the exact reverse of each other. Next comes more initialization of variables: 4070 name$="Font":array$="cset%":size%=1024 4085 ctrl$=CHR$(8)+CHR$(21)+CHR$(11)+CHR$(10)+CHR$(130 =Q:WW=0A=:A=21A=9&oldprefix$=40A=31410: Control C "aborts" program to Basic(:A=13770: Return Selects a file *DA=27:50: Escape to change disks7FA=324000: back out one directory level -IA=(81+UCA)A=(IC 0":150A$="TEXT 0":150A$="CAT 0":150A$="FONT 0":150A$="FOTO 0":150A$(L),"BLOCKS")510*=27:=19:"FREE MEMORY AVAILABLE: ";=7:=20:"80C";A$(L);$:=5:THPOS=4:I=1:IBOTM=J-1:620Q=:=26:=21:160 +Q Quits."r12);::"80C";a$;:+w#9,"DISKNAME.DAT":#9;DISKNAME$:#9|d$=DISKNAME$$=23:=0::"80C";d$;::12)201M=3:=14:"This /// SIG Disk is \^ 19";Р,2)", Washington Apple `, Ltd."=4:B$(1)="":B$(2)=""A$="BAS6,B) THEN 240 #1, d$="":=10:"80C";d$ ž#1300I=0"I=I+1:#1;A$(I):290,#1 6L=I-1@j=1:same=0 J:SEG=0 Tœ2030^CT<1CT=1:CT>13000Zha$="{,|,~,}; selects; to new disk; J/2)=4:=+1:ۙ=44B$(J);:J=J+1I:1,180,22:2,280,21:2,2380,23:8A$(1000),B$(1000),C%(511),C$(20),name$(20):=10:=0UCA=128:LCA=UCA+32CT=15 IF PREFIX$= PREFIX$+MID$(B$(I),1OLUME NAME (/DISKNAME) OR DEVICE NAME (.Dx)"P12);::"80C";a$;:Zb$="CHANGING DISKS"$d=23:=0::"80C";b$;::12).n=12:=20:"MAKE A NEW MENU FOR DISK: ";N$xN$)<2110=N$ :210 I=1L(A$(I),A$))200B$(/ WAP /// SIG MENU.MAKER PROGRAM (v. 6.1) =".D1"210: Coldstart (320: Warmstart &*X=11000: TEXT SLOW-DOWN LOOP ,X.1 CHANGE DISK SUBROUTINE23œ202:2200<RFa$=" YOU MAY SELECT YOUR DISK BY V6 4210 DATA 1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6 4215 DATA 1,6,1,6,3,2,2,3,1,5,2,5,2,5,1,6 4220 DATA 1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6 4225 DATA 1,6,2,4,1,6,1,6,1,6,1,6,1,6,1,6 4230 DATA 1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6 4235 DATA 1,6,1,6,1,6,2,5,cter spacing. These are values you would want to change if you used other, non standard character sets. Next comes a big table which will be a challenge to type in: 4200 DATA 3,4,3,2,2,4,1,6,1,6,1,6,1,6,3,2 4205 DATA 1,4,3,4,1,6,1,6,2,3,2,5,3,2,1, arrow, down arrow, carriage return and escape. Line 4090 sets some initial constraints for the area which may be edited, and sets the initial position of the cursor to 0,191 (chorz and cvert). Line 4100 sets the default for horizontal and vertical chara(1)="Proportional" Several variables are worthy of note above. First, in line 4085 a string is built of command characters which will be used later for fast lookup by the editor command routine. In order, the characters are back arrow, forward arrow, up)+CHR$(27) 4090 left=0:right=559:top=191:bot=18:cvert=191:chorz=0:delay=1:noset=1 4100 hspace=7:vspace=8:reverse=0 4110 bell$=CHR$(7):eras$(0)="Replace":eras$(1)="Overlay":eras$(2)="Invert " 4120 eras$(3)="Erase ":prop$(0)="Monospace ":prop$81+LCA):::: RebootN=THPOS:B$(I);XA<8A>11540bA-7640,660,690,720l:=THPOS:B$(I);v:520: 500THPOS=4:I/2=I/2)I=I-1I=IBOTM THPOS=44:I/2<>I/2)I=I+1I2=-1:I=I-2:IBOTM<30THPOS=44I=IBOTM/2)*2:=+IBOTM/2)-1:0=+IBOTM/2-.5):I=IBOTM:I/2=I/2)I=I-1 œ2120B=B$(I),16)," ")-1 B$(I),"BASIC 0")850B$(I),"TEXT 0")890  MENU.MAKER TEXT MODULESEG=0"MENU.MAKER"890&*X=11000: TEXT SLOW-DOWN LOOP ,X.1,180,22:2,280,21:2,2380,23:z:A$="LISTING "+B$(I),16,B)$=01:=0::"80C";A$;::12)>=23:=0::"GA3/1.01:7SY CONTROL  RETURN Notice that there are eight sets of two values on each line and 12 lines, for a total of 96 sets of values, one for each of the "displayable" characters in a font definition. To save trouble and improve performance, we have not bothered to make1,6,2,5,1,6,1,6 4240 DATA 2,4,1,6,1,6,1,6,1,6,1,6,1,6,1,6 4245 DATA 1,6,2,4,1,5,1,6,2,4,1,6,1,6,1,6 4250 DATA 1,6,1,6,1,6,1,6,1,6,1,6,1,6,1,6 4255 DATA 1,6,1,6,1,6,1,6,2,3,1,6,1,6,0,7 4300 FOR i=32 TO 127:READ cstart%(i),clen%(i):NEXT 450012405l=ơ):: Routine to back up one directory level.a$=С,l-1) s=a$)a$=a$,s-1)a$,1)="/"5060:s=s-1 5030=a$240( MENU.MAKER 6.10 * Thanks to C.M.Davidson for his help!NOT FOUND.)"X=11000:X:::210Z a$="{,|,~,}; selects; back 1 level; G$:::320H: Error Routine 202:U=11:"79C";"BAD PATH ERROR (NO DISK IN DISK DRIVE OR DESIRED FILE ,2))=0"12";џ,6);:ٟ;$П,2))=>12" PM-":" AM-" 1830WW=1530 =26:=21 1600 &:WW=1:0 :SEG=1;".D1/S EG.F" SEG=1".D1/SEG.G"diskname$=3802  CATCH PASCAL TEXT FILES "JUNE":1750M$="JULY":1750M$="AUGUST":1750M$="SEPTEMBER":1750M$="OCTOBER":1750M$="NOVEMBER":1750M$="DECEMBER":1750826);"-";M$;" ";Ѡ,2));", ";"19";Р,2);" ";/П,2))=>13П,2))-12;џ,6);:1780$~240:=24:=0:"@ ..... "DATE.TIME.LINE" ....JM=Ҡ,4,2))BTM1630,1640,1650,1660,1670,1680,1690,1700,1710,1720,1730,1740^M$="JANUARY":1750hM$="FEBRUARY":1750rM$="MARCH":1750|M$="APRIL":1750M$="MAY":1750M$=B$(I),"CAT 0")1140*B$(I),"FONT 0")18504B$(I),"FOTO 0")1930>B$(I),"PASTXT 0")2070H540R\A$="RUNNING "+B$(I),16,B)f"79C";A$;:=0pB$(I),16,B) z::SEG=1".D1/SEG.T"t=+B$(I),16,B) yCT=CT+179C";"PRESS ANY KEY TO HALT LISTING"::202 1020#2,B$(I),16,B)ž#242:::1160Z=1#2;A$:"78A";A$Z=Z+1:Z>1842:::Z=1980*:=23:=0::"79C";"CONTINUE...?":1C$:C$<>"Y"C$<>"y"C$<>"N"C$<>"n"10L `L5hzh{ Qghhh5h66 HHH566 qyhhhpx{HzH`~GA3/1.01:7SY GETFONT FILWRITE FILWRITEGETRFNM RTRFNM ERROR ^ROR DOARRAY OARRAY  ERROR ?BUFPNT NT DEVINFO DEVINFO MOVESTR FILREAD FILREAD BUF :4 GETRFNM BUFPNT OJNT ERROR ROR DOARRAY e=TPARMSERROR uROR BUFPNT BMOVESTR REQNUM UUM BLDSTRN DSTRN BUF pia RETURN RETADR  GETPARMSFREQNUM BUF "CONTROL CONTROL RETURN RETADR GETPARMS TPARMSERROR ROR STATUS STATUS BLDSTRN ,BUF |F GETPARMSca` hhh5h66HH :5HHH) @  hhh g5ȱg6ȱg@ ɀL g eegghI8e556l6m `  hUhVh8 ㅊ eh֭VHUHk`HFB>;:9853/&" NL64Ch5h6h3lh4m 0/L6H5H`g8640'%76,V^dKA;6hWhXhhhQlhRm e Nb YMH YhLSꈭTXHWH`gca` hhh5h66HH :5HHH) @  hhh g5ȱg6ȱg@ ɀL g eegghI8e556l6m `  hUhVh8 ㅊ eh֭VHUHk`HFBhhHHHH l5m6m6  ЙW5X6X6 ` 5`MD32KA;6hWhXhhhQlhRm e Nb YMH YhLSꈭTXHWH`g##6 >?Bi{Ci|) |=! "LL{@?>8(O\ F9 >{i 5|i6) 6|8 L5{ hhhh0 hWhXXhhh5h66HH :~5~HHH|})   |}) @  hhh g5ȱg6ȱg@ ɀLDg eegghI8e556l6m`  lmL}\ZYc&h:h; (+65;H:H`,.CONSOLEg<:/.-+*(% CX`6>6|~fnl6vf~><~~<`lnf~||f6|<~f|~fnl`<6vfff<<<<<````ff<f66f<<<<<<>~ZZZ>~fff<~f~<>~fv6|~fnl``<~f>><fff~|fff<ZZZ~|f<|>8p`xx``xx>8888866$$~$~$>> >B%$R! *,88888"6">~~`p8>"""> > >>> > >""> >> >>>">> >">">>"> ~~ < <~b0pppppppp"AAAAAA>>6>>***~" "w"w>>$$>>>00@@ !~6>6AAAAAAREADC READC  #.-2hhhhHH`$.CONSOLE24320/JGETFONT GETFONT DOARRAY2QLOADFONT LOADFONTDOARRAY2ARRAY2 Y.333>> >333>!?&>33> 3333 00000633 ++++666666633>33> 6>06>; ++++>3 3333>$? ?pp8 )((8*,;((*,((+)((9/(p((>3  =9 :9 .(+( 8#8# %3(8 ((,+)(%.4$)?((,(103  7  3  5  presented in lines 4200 to 4255 will define the slim new format for all the characters in the font we will be using. Note that this definition is for the "Standard" font. Several other fonts come with the Business Basic disk, such as "Roman", "Apple", ett column which would read "1,6" in our "starting pixel, character width" format. In the case of the lower case "i", the formula is "2,4" since we are to skip the first two pixel columns and then only use four to draw the character. In any case the table | | X | | X | | X X | |X X | | XXX | |XXX | |_______| |______| |_______| |____| Notice that the new "A" is obtained by simply shaving off the firs | X X | |X X | | XX | |XX | | XXXXX | |XXXXX | | X | | X | | X X | |X X | | X | | X | | X X | |X X Normal "i" (7) New "i" (4) _________ ________ _________ ______ | X | | X | | X | | X | | X X | | X X | | | | | s the ability to write 93 characters across the screen and then, depending on the number of "i's" and "l's" and other skinny characters that get used, the actual total may be much higher. An example would help: Normal "A" (7 wide) New "A" (6 Wide) pixel at the end. This does mean, however, that we save at least one pixel per character, which for 80 characters across on a normal screen is 80 pixels, or the equivalent of an extra 13 characters from that technique alone! Six wide monospacing thus buyse the next 6 pixels". This is because a large number of characters in the standard set are five pixels wide, and we need one pixel for spacing. For consistancy, we always steal the extra pixel from the leading edge of the character, leaving the spacing the control character definitions displayable, so the characters from 32 ('space') through 127 ('DLE') are the only ones defined. Notice that most characters seem to follow the pattern '1,6' meaning "start one pixel over in the character definition and u <"<"""<< <"""<"><$""< """"  "" 6***""""""""""<""< :< $"""2,"""""**6"""""< >>8  80,>!"*:<"">""""""""""""">>><2"<""">""" ""  ">"6**"""""&*2""""""""""""*,"" "" ">""""""""""""""**6"""""""> >>> >00000>">>< (&20 *, **>> "2*&" " >>  ">> "8""> """"""< >> "c. These fonts contain characters which are designed a little differently than the standard font characters, so you should construct a different table for those characters. Well, having beaten initialization to death, let's get on with the show: 30 INVOKE"/basic/bgraf.inv","/basic/request.inv","/basic/download.inv" 35 OPEN#1,".grafix" 50 INPUT"Use Normal or Inverse screen (N or I)? ";a$ 55 IF a$="" THEN GOTO 1050 60 a$=MID$(a$,1,1):op=INSTR("NnIi",a$) 65 IF NOT op THEN 50:ELSE op=INT((ohe message area. If 'warn' mode is on, then the message is written from horizontal positions 413 to 559, between rows 0 and 8 on the screen, the lower righthand corner. If 'warn' is zero, then the message is written between positions 5 and 411. These tey to write messages to the user on the bottom of the screen. Line 3100 above first sets transfer option 0, called "replace", which will overwrite any message currently in the message area. Then subroutine 3500 is called to clear the appropriate part of t0 IF NOT warn THEN GOSUB 3500:ELSE:warn=0 3135 RETURN 3500 PERFORM viewport(%5+408*warn,%411+148*warn,%0,%8):PERFORM fillport 3510 PERFORM viewport(%0,%559,%0,%191) 3520 RETURN The subroutines above give the program a general purpose abilitption and the spacing mode: 3100 PERFORM xfroption(%0) 3105 GOSUB 3500 3110 PERFORM moveto(%7+412*warn,%7):PRINT#1;message$; 3120 IF NOT warn THEN FOR i=1 TO 750*delay:NEXT 3125 PERFORM xfroption(%( NOT( NOT erase))*(erasenum-2+erase)) 313urrent fill color and then create a message area in the bottom ten lines of the screen. If 'reverse' is on (more on that later), then the operation is finished. Otherwise, the subroutine at line 3100 is called to write the current state of the transfer o PERFORM moveto(%0,%9):PERFORM linerel(%559,%0) 3630 PERFORM moveto(%412,%9):PERFORM linerel(%0,%-9) 3640 IF reverse THEN RETURN 3650 warn=1:message$=eras$(erase)+" "+prop$(prop):GOSUB 3100 3660 RETURN Lines 3600-3630 clear the screen to the caracters onto the screen, and 'prop' which defines whether proportional or monospaced character writing will be performed. Then the subroutine at line 3600 is called to set up the screen: 3600 PERFORM viewport(%0,%559,%0,%191):PERFORM fillport 3620 120 erase=0:prop=1 130 GOSUB 3600 In line 105 the program sets mode 2, the 560X192 mode, and 110 uses the previously defined fill and pencolor variables. Line 120 sets the initial values for 'erase' which defines the transfer option used to write che found later in this article. Next comes more initialization: 100 PERFORM initgrafix 105 PERFORM grafixmode(%2,%1) 110 PERFORM fillcolor(%fill):PERFORM pencolor(%pen) 115 HOME:PRINT:PRINT"Initializing the graphics screen, please wait." n't interfere with the text which will be on the screen. If the pencolor is 0 (black) then transfer option 2, "invert", is used. If the pencolor is 15 (white) then option 6 is used, "inverse invert". More detail on how these transfer options work will bg on the value of 'op'. An IF statement would work just as easily, but practice in logical value calculations can't hurt. The variable 'erasenum' in line 75 is used to define what transfer option is appropriate to use to draw the cursor so that it doesmode (just the opposite). Notice the use of the INSTR statement and the calculations in lines 60 and 65 to check for mismatches and then set 'op' to 0 or 1 for normal or inverse. Line 70 then sets 'fill' and 'pen' to either 0 and 15 or 15 and 0, dependinphics driver is opened, allowing us a path to print text commands on the graphics screen and perform other functions. Line 50 through 75 then request whether the screen is to be displayed in normal mode (white characters on a black background) or inverse p+1)/2)-1 70 fill=op*15:pen=( NOT op)*15 75 erasenum=2+4*op Because we'll be dealing with fonts as well as the .GRAFIX driver, we invoke the three modules listed in line 30, all of which are found on the Business Basic master diskette. Then the grachniques can be used to establish several message "windows" if necessary, each using the same routines. Line 3110 then moves to the appropriate place on the screen and writes the message in 'message$'. Messages in the "warning" window remain until changed by another message, but if the regular message window is used, the program pauses briefly (line 3120) and then sets the transfer mode back to its original state and calls line 3500 to clear the window. Back Home from the Subroutines Now that the progry$) 1445 OFF ERR:GOSUB 2000 1450 message$=name$+" loaded.":GOSUB 3100:GOSUB 2100 1455 RETURN The routine above first sets up an ON ERRor jump to line 1460 and then tries to use the 'getfont' proceedure from the "download.inv" module to load a fon screen. Now that we have a general way to get input, and to check for certain control characters like ESCape, we continue our look at the font request routine: 1435 ON ERR GOTO 1460 1440 font$=CHR$(34)+line$+CHR$(34):PERFORM getfont(@font$,@arraA value of 2 for 'fin' indicates that ESCape has been pressed, and a "control-X" erases the input line, just as it does in Basic, except that the prompt is redisplayed. In all, this is a useful routine which could be easily adapted for use anywhere on thecharacter from the end of 'line$', and then loops back to get the next character. Lines 3030-3040 handle special character exits from the routine. A carriage return exits with 'fin' set to 0 if there are characters in line$, or 1 if the string is null. processing, including back arrow erasing, is handled in lines 3030-3065. Backing up is a matter of moving the cursor location back one space, printing a blank, and then moving back to accept the new character. In addition, line 3060 removes the previous is made in line 3020 to be sure that the input doesn't overflow past 40 characters and thus into the next message window. If everything's ok, the character is added to 'line$', and the routine loops back up to get the next character. Control characterT erase))*(erasenum-2+erase)) 3075 RETURN The routine above is very similar to others in this column which accept input while on the high-resolution screen. It supports typing in characters, and erasing input with the back-arrow. In addition, a check=24 THEN PRINT bell$;:GOTO 3005 3045 IF a<>8 THEN 3015 3050 IF LEN(line$)=0 THEN 3015 3055 PERFORM moverel(%-7,%0):PRINT#1;" ";:PERFORM moverel(%-7,%0) 3060 line$=MID$(line$,1,LEN(line$)-1) 3065 GOTO 3015 3070 PERFORM xfroption(%( NOT( NO3015 GET a$:a=ASC(a$):IF a<32 THEN 3030 3020 IF LEN(line$)<40 THEN PRINT#1;a$;:line$=line$+a$:ELSE:PRINT bell$; 3025 GOTO 3015 3030 IF a=13 THEN fin=(LEN(line$)=0):GOSUB 3500:GOTO 3070 3035 IF a=27 THEN fin=2:GOSUB 3500:GOTO 3070 3040 IF ack look at the input routine is appropriate now (are you beginning to feel like the Apple /// itself, plunging deep into subroutines again?): 3000 PERFORM xfroption(%0) 3005 GOSUB 3500:PERFORM moveto(%7,%7):PRINT#1;prompt$; 3010 line$="":fin=0 n a minute). The variable 'fin' in line 1425 is used to indicate a non-standard exit from input, such as pressing "escape" or a carriage return at the beginning of the input. In any case, the font name, if any, is returned in the variable 'line$'. A qui 1400 prompt$=name$+" pathname: " 1425 GOSUB 3000:IF fin THEN RETURN The font subroutine above first prompts for the pathname of the font file, by using the variable prompt$ and the high-resolution input routine at line 3000 (more on that routine iND noset THEN 1000 170 GOSUB 3500 After putting an identifying message on the bottom of the screen, the section above uses the subroutine at line 1400 to load the character font which will be used to write on the screen. That routine starts like this:am has set up the screen and the default modes are established, we turn on the screen and start using the program: 150 PERFORM grafixon 155 message$="High Resolution Screen Editor":GOSUB 3100 160 GOSUB 1400 165 IF fin=2 THEN 1000:ELSE IF fin At from the file specified in 'line$'. If anything goes wrong, for example, the file specified is not a font file, then a jump is made to the error routine: 1460 ON ERR GOTO 1490 1465 OPEN#3,line$ 1470 PERFORM filread(%3,@array$,%size%,@ret%) 1475 OFF ERR:CLOSE#3 1480 IF ret%=size% THEN GOSUB 2000:GOTO 1450 1485 message$=name$+" in "+line$+" is invalid.":GOSUB 3100:GOTO 1400 1490 message$="Not a "+name$+" file.":GOSUB 3100 1495 OFF ERR:IF TYP(3)=0 THEN CLOSE#3:DELETE line$:ELSE:CLOS where the character will be written: 200 PERFORM xfroption(%erasenum) 205 PERFORM moveto(%chorz,%cvert) 210 PERFORM drawimage(@char%(0,0),%v128,%995,%0,%1,%vspace) 215 GET a$ 220 PERFORM drawimage(@char%(0,0),%v128,%995,%0,%1,%vspace) Fir, with a font definition loaded in the 'char%' array. That brings us to the interesting stuff, actually putting some of these characters onto the screen using the proportional spacing tables. Our first step is to put a "cursor" on the screen, to indicateld allow quick switching of fonts without the complicated preparation routines. Now for Something Completely Useful Those of you who have been following along with our nested subroutine calls above will now realize that we are back to the main routine invokable. Note also that you could speed up this process considerably by pre-storing a font definition in a file as a character set array in the 'char%' format. That would require modification of the subroutine at 1400 which reads in the array, but wouows represent rows of bits, and columns represent character definitions, two per integer value. More information on this format can be found in previous articles in this series, and in the Business Basic manual, volume 2, under the discussion of the BGRAF+1)=TEN(MID$(a$,3,2)+MID$(b$,3,2)) 2125 NEXT:NEXT 2140 message$="Font format transferred":GOSUB 3100:GOSUB 3500 2150 noset=0 2160 RETURN Note above that we are unpacking 'cset%' into a simple row, column format in the array 'char%, where r00 message$="Transferring Font format to Character set format":GOSUB 3100 2105 FOR k=16 TO 63:j=8*k-1 2110 FOR i=0 TO 7 STEP 2:j=j+1:a$=HEX$(cset%(j)):b$=HEX$(cset%(j+4)) 2115 char%(k,i)=TEN(MID$(a$,1,2)+MID$(b$,1,2)) 2120 char%(k,iand their corresponding reversed values. The routine is compacted on one line for maximum performance. Now that the font is flipped, it is necessary to expand it from the single dimensioned array 'cset%' to a form more readily usable by "Drawimage": 21n seen in previous episodes, since the standard system font definitions used by text mode are exactly the reverse (on a character basis) from those of the high-resolution DRAWBLOCK fonts. Line 2010 uses the 'flip' array to define all possible byte values the routine abyss): 2000 message$="Preparing the character font.":GOSUB 3100 2010 FOR k=0 TO 511:b$=HEX$(cset%(k)):cset%(k)=TEN(HEX$(v256* flip(TEN(MID$(b$,1,2)))+flip(TEN(MID$(b$,3,2))))):NEXT 2020 RETURN The routine above has also beel goes back to the beginning to ask for the filename again. In the hopeful event that the filename is correct and the program can read a font from it, a subroutine at line 2000 is called to prepare the font for use by the program (deeper, ever deeper intoead from but contained wrong information, or line 1490 if there was trouble opening or reading the file. The TYP function in line 1495 serves to check if the file is blank because the original OPEN caused it to be created. If so, it is deleted and controticle, or some other means to get a font definition into a file without being able to change the file type to "FONT". If something goes wrong this time, then the appropriate error message is displayed, either in line 1485 if the file could be opened and rE#3 1500 GOTO 1400 The routine at 1460 attempts to open the file as a Basic file, and use the 'filread' proceedure from "request.inv" to read a font definition array. This might be the case if you used the Character and Shape Editor from a previous arst we set the transfer option for "invert". This allows the cursor to overwrite information on the screen by turning black to white, and white to black. Line 205 positions the cursor to the current horizontal and vertical value, and line 210 writes the cursor on the screen using the "drawimage" routine. This statement draws a vertical bar of bits from the 'char%' array which is one pixel wide and 8 pixels ('vspace') high starting at bit location 995 in the character set. It happens that 995 is the locatjump is made to line 400 to do processing of commands. If not, a check is made for "open-apple" in line 275, and if so, the skip flag is set to zero, indicating that cursor positioning is to be done in one pixel increments. The character typed is then ch1)-1:IF bot<=vmove THEN cvert=vmove 375 GOTO 200 380 chorz=0 385 IF bot<=cvert-vspace THEN PRINT#1;CHR$(10);:cvert=cvert-vspace 390 GOTO 200 First a check is made in line 270 to see if the character typed was an "ESCape". If so, an immediate ace-1)-1:IF left<=hmove THEN chorz=hmove 345 GOTO 200 350 hmove=chorz+skp*(hspace-1)+1:IF right>=hmove THEN chorz=hmove 355 GOTO 200 360 vmove=cvert+skp*(vspace-1)+1:IF top>=vmove THEN cvert=vmove 365 GOTO 200 370 vmove=cvert-skp*(vspace-nd other special characters are handled by the routine at line 270: 270 IF key=27 THEN 400 275 IF key>127 THEN skp=0:key=key-128 280 kvl=INSTR(ctrl$,CHR$(key)) 285 ON kvl GOTO 340,350,360,370,380,160 290 GOTO 200 340 hmove=chorz-skp*(hsped by 'right'. If everything is ok then the character is written by line 250 and the current horizontal position is updated. Then a loop back to the beginning is done to redisplay the cursor and start the process over. As was mentioned before, control aer of the character. It's always the character code times eight for monospace, with the additional value 'cstart%' if proportional. Once the correct values are computed, a check is made to see if the result will go past the right edge of the window definepending on whether proportional or monospace mode is being used. 'Hspace' indicates how wide is the character to be written; 7 for monospace or the value in 'clen%' if proportional. 'Xskip' is the offset in the 'char%' array at which to start the transfracter. A check is made to see if the character is a control character or if "open-Apple" was pressed along with the character (key>127). If not, then the character is a printing one which is to be put on the screen. Line 240 sets 'hspace' and 'xskip' d 250 PERFORM drawimage(@char%(0,0),%v128,%xskip,%0,%hspace,%vspace) 255 chorz=chorz+hspace 260 GOTO 200 Notice that first we put the screen back into whatever transfer mode was selected, and then set 'key' equal to the ASCII value of the typed charoption(%( NOT( NOT erase))*(erasenum-2+erase)) 230 key=ASC(a$):skp=1:IF key<32 OR key>127 THEN 270 240 IF prop THEN hspace=clen%(key):xskip=key*8+cstart%(key): ELSE:hspace=7:xskip=key*8 245 IF rightG$:::".D1/MENU.MAKER",320R",220(204::"79A";""; 2D=1:F=1 <#4;a$ FD=D+1 P#5;a$ZD=60#5;12)dD=60D=1nF=F+1::d$;::Y=1100:Y x13402  CATCH PASCAL TEXT FILES 202 :F*=08:"78C";"SORRY BUT MENU.MAKER CAN'T R".D1/MENU.MAKER",220 d$="" A$="PRINTING "+B$(I),16,B)=01:=0::"80C";A$;:#3,B$(I),16,B)Z=1#3;b$:"78A";b$Z=Z+1:Z=18:1290 1260 #4,B$(I),16,B)#5,".PRINTER"+ž#4#5;12):::".D1/MENU.MAKE30C$="N"C$="n"1160;:=23:=0::"79C";"PRESS ANY KEY TO HALT LISTING": $1020.202 8::Z=1B::=23:=0::"79C";"WOULD YOU LIKE A PRINTED COPY?":1C$:C$<>"Y"C$<>"y"C$<>"N"C$<>"n"1170*C$="N"C$="n"Side One of disks 3BSB-03/04 for more information. We are pleased to bring you these excellent series of articles and their accompanying programs. We hope you enjoy them!! 00052 ARTICLE.6 6 TEXT 00060 ARTICLE.7 7 TEXT 00052 ARTICLE.8 8 TEXT 00043 ARTICLE.9 9 TEXT 00067 ARTICLE.10 10 TEXT 00068 ARTICLE.11 11 TEXT 00064 ARTICLE.12 13 TEXT 00033 ARTICLE.13 14 TEXT 00023 ARTICLE.14 15 TEXT 00054 ARTICLE.15 16 TEXT 00054 ARTICLE.16 17 TEXT 00057 ARTICLE.17 18 TEXT 00070 ARTICLE.18 20 TEXT 00064 ARTICLE.19 21 TEXT 00069 ARTICLE.20 22 TEXT COMMAND.TEST 8 BASIC 00008 04/08/88 22:17 12/05/87 13:24 3557 CREATE.TRASH 10 BASIC 00003 05/22/82 21:31 12/05/87 13:33 983 CREATE.TRASH 11 BASIC 00003 06/22/82 20:32 12/05/87 13:36 983 CREATEJUNKFILE 16 BASIC The Third Basic by Taylor Pohlman 6 TEXT 00001 FORMAT.DUMP 5 BASIC 00001 FREE.FIRE 19 BASIC 00006 FREE.FIRE 21 BASIC 00006 page - 3 T.MOVE 21 BASIC 00004 FILL.PIC 8 FOTO 00033 FINAL.B.SORT 16 BASIC 00005 FINAL.FIRE 22 BASIC 00006 FINAL.PROP.EDIT 24 BASIC 00011 FONTLOAD.SUB 19 BASIC 00001 FONTLOAD.SUB 21 BASIC 00001 FOR.NEXT.OUT 00010 EDIT.SHAPE 18 BASIC 00025 EDIT.SHAPE 21 BASIC 00025 EDITOR 8 BASIC 00009 ELLIPSE 7 BASIC 00001 EXTENDED.ADD 6 BASIC 00004 FAST.B.SORT 16 BASIC 00005 FAST.CIRCLE 7 BASIC 00001 FAS 6 TEXT 00001 DIRECTORYDUMP 6 TEXT 00006 DUMP.DATA 5 TEXT 00005 DUMP.DIR 6 BASIC 00001 DUMP.OUT 5 TEXT 00013 DUMP.STATUS 10 BASIC 00004 DUMP.USING.GET 5 BASIC 00001 EDIT.FONT 8 BASICPARTS.PROG 3 BASIC 00007 DATABASE.PROG 9 BASIC 00013 DB.BTREE 17 BASIC 00019 DECODE 10 BASIC 00003 DECODE.DUMP 10 BASIC 00004 DEMO.MOVE.FONT 25 BASIC 00005 DEMO.PRIORITY 19 BASIC 00005 DIR.DUMP.OUT 00003 CIRCLE.PROG 7 BASIC 00003 CIRCLE.SCALE 7 BASIC 00001 CIRCLE.SUB 7 BASIC 00001 COMMAND.TEST 8 BASIC 00008 CREATE.TRASH 10 BASIC 00003 CREATE.TRASH 11 BASIC 00003 CREATEJUNKFILE 16 BASIC 00001 DATA.19 BASIC 00008 BUILD.FILE.1 26 BASIC 00006 BUILD.INV.BYTES 8 BASIC 00001 CHANGES.PROG 4 BASIC 00003 CHAR.ARROW 18 DATA 00007 CIRCLE 7 BASIC 00001 CIRCLE.ASPECT 7 BASIC 00001 CIRCLE.FINAL 7 BASIC page - 2 File Name Ref# Type Blks BUG.FONT 18 FONT 00003 BUG.FONT 19 FONT 00003 BUG.FONT 21 FONT 00003 BUG.FONT.1 18 FONT 00003 BUG.FONT.1 19 FONT 00003 BUG.MANIA B 22 BASIC 00004 BUBBLE.SORT 15 BASIC 00001 BUBBLE.SORT 16 BASIC 00001 BUBL.PNTR.SORT 15 BASIC 00001 BUBL.PNTR.SORT 16 BASIC 00001 BUG.BOX 22 BASIC 00005 00078 ARTICLE.21 23 TEXT 00074 ARTICLE.22 25 TEXT 00049 ARTICLE.23 26 TEXT 00040 B.SORT.2D 16 BASIC 00001 BINARY.SORT 16 BASIC 00005 BINARY.SORT 17 BASIC 00005 BOUNCE.PRIOR 22 BASIC 00005 BOUNCE.SCRU00001 10/03/82 01:01 12/05/87 14:01 217 DATA.PARTS.PROG 3 BASIC 00007 10/13/81 23:08 10/18/87 23:06 2718 DATABASE.PROG 9 BASIC 00013 03/22/82 23:39 12/05/87 12:56 5803 DB.BTREE 17 BASIC 00019 11/01/82 12:50 12/05/87 14:12 8996 DECODE 10 BASIC 00003 04/08/88 22:43 12/05/87 13:35 1021 DECODE.DUMP 10 BASIC 00004 04/08/88 22:40 12/05/87 13:33 1073 DEMO.MOVE.FONT 25 BASIC 00005 07/13/88 22:33 12/05/87 17:42 1812 DEMO.PRIORITY h   HH`420.-&#  Phhhhhhhhhh  HH`DB@><:86421.+*)'jhhhhhhhh    X XLJFE>987410/-   `+(%" Bhhh h h h hh hhhhhh  HH`ZXVTRPNLJHFDB@<;85431hhh    `OLIHEDCB?<;8541.+*x  `"hhhhhhhh    HH`XVTRPN.GRAFIX jj# \\JHFD=;9210-,+*)!   v Q )``.`5`=`C`E` `BGRAF (C) APPLE 1980j @@@@ @``` kLK``9(89:9g:h:h L89:mm95:6:6hg gh h 99 O S   L `ee m`iɂ`0`hIhJh\h] wh]h^ w\\ ]] ]L ]L\A \A JHIH`i8\i]i\`\]`K`M %b&*L+ 16>:)    kL GA3/1.01/LINr GRAFIXMO P.USING.GET 5 BASIC 00001 11/15/81 07:19 10/18/87 23:10 128 EDIT.FONT 8 BASIC 00010 04/08/88 22:25 12/05/87 13:24 4162 EDIT.SHAPE 18 BASIC 00025 07/14/88 22:41 12/05/87 14:10 11794 EDIT.SHAPE 21 BASIC 00025:42 10/18/87 23:10 1562 DUMP.DIR 6 BASIC 00001 12/29/81 15:51 12/05/87 08:21 252 DUMP.OUT 5 TEXT 00013 11/15/81 11:12 10/18/87 23:10 6078 DUMP.STATUS 10 BASIC 00004 04/08/88 22:40 12/05/87 13:33 1094 DUM 19 BASIC 00005 07/14/88 22:05 12/13/87 20:22 1610 DIR.DUMP.OUT 6 TEXT 00001 12/30/81 00:59 12/05/87 08:22 427 DIRECTORYDUMP 6 TEXT 00006 12/29/81 15:11 12/05/87 08:24 2422 DUMP.DATA 5 TEXT 00005 11/15/81 16 HH`)r` @A>~|zxvtslgbWTSRPMED=hhhh   HH`420.-&#  Phhhh   HH`420.-&#  P  `"hhhhhh  HH`420.,*)&#"! Rhhhhhh  B B HH`yyP`GBRETADDR tpINITCHK ITCHK PENCOLOR PENCOLOR RANGECHKNGECHKWBUFLEN UFLEN SOSWRITESWRITERWBUF |x FILLCOLO FILLCOLO TRETADDR  SETCTAB SETCTAB  INITCHK ITCHK RANGECHKHKWBUFLEN UFLEN SOSWRITESWRITERWBUF  'SOSWRITESWRITERWBUF  RETADDR PLINITCHK sITCHK VIEWPORT VIEWPORTWBUFLEN }UFLEN SOSWRITESWRITERWBUF  xplhd`\XUFLEN SOSWRITESWRITERWBUF ~zvrRETADDR $ INITCHK ITCHK XFROPTIO XFROPTIORANGECHKNGECHKWBUFLEN UFLEN #ITCHK WBUFLEN DUFLEN SOSWRITEGSWRITERWBUF ?:72-(SYSFONT SYSFONT RETADDR njDRAWIMAG DRAWIMAGINITCHK ITCHK WBUFLEN RETADDR INITCHK ITCHK RANGECHKECHKWBUFLEN UFLEN SOSWRITESWRITERWBUF  NEWFONT NEWFONT INITCHK =+SOSWRITE@.!RWBUF  83& INITCHK uITCHK GRAFIXON GRAFIXONWBUFLEN UFLEN SOSWRITESWRITERWBUF zBUF GPGSREQDLGRAFIXMO GRAFIXMORBUFLEN 9RANGECHKwWBUFLEN ASOSWRITERWBUF \SOSREAD GBASADR TSOSSMARK$INITCHK ITCHK INITGRAF INITGRAFWBUFLEN RETADDR ISOSDSTATGSCB kSOSOPEN INITCHK READPARM5CREFNUM DWBUFADR ?BMOVCHK RBUFADR 7WRITEPAR=SREFNUM FRREFNUM 6WREFNUM >INITFLG KSOSCLOSEhhhhhh HHHH`&$<D^Z FpHx  )) y xHHHJJiH 詏 鮀 `}wqnkjba_\[ZYXWVURQ$hhhhhh HH H)HHH`20+*)Hhhhhhh HHHH`&$< 詏 )x `a^]NMJGF>=<10/.+* )) y xHHHJJiH 詏 鮀hhhh  HH`420.,*)&#"! Rhhhhhh    HH`DB@><:983.+('&$h J)` `!0 nljhfdcbQNMLJFEDCBA<;6hhhhhh  HH`420.,*)&#"! Rhhhhhh    HH`DB@><:983.+('&$hhhRETADDR INITCHK ITCHK RANGECHKNGECHKWBUFLEN UFLEN SOSWRITESWRITERWBUF  INITCHK ITCHK FILLPORT FILLPORT WBUFLEN !UFLEN SOSWRITE$SWRITERWBUF BUF RETADDR ieB>INITCHK UITCHK MOVETO MOVETO  WBUFLEN _UFLEN SOSWRITEbSWRITE 07/14/88 22:58 12/13/87 19:49 11986 EDITOR 8 BASIC 00009 04/08/88 22:16 12/05/87 13:23 3595 ELLIPSE 7 BASIC 00001 01/01/00 00:59 12/05/87 13:13 240 EXTENDED.ADD 6 BASIC 00004 12/30/81 00:50 12/05/87 08:21YLOC  SDSTATGSCB  INITCHK  ITCHK XLOC XLOC RETADDR     SOSDSTAT SDSTATGSCB   INITCHK  ITCHK YLOC  ASADR SOSSMARK SSMARKRETADDR  z v INITCHK  ITCHK XYCOLOR XYCOLOR RWBUF  F SOSREAD  SREAD RETADDR  SOSDSTATGPGSREQD GSREQDSOSCLOSE SCLOSEGRAFIXMO AFIXMOGLOAD GLOAD RBUFLEN  N RWBUF    SOSREAD  EAD GBASADR GBASADR ( ASADR SOSDSTAT~ SDSTATGSCB  INITCHK { ITCHK CREFNUM  EFNUM RBUFADR  ADR SREFNUM  EFNUM RREFNUM  M WBUFADR   ADR GSAVE GSAVE WREFNUM F  M GPGSREQD5 GSREQDSOSCLOSE> SCLOSEWBUFLEN 8  LEN SOSWRITE; SWRITERWBUF C F INITCHK  ITCHK BMOVCHK  OVCHK INITFLG  ITFLG RWBUF  F SOSDSTAT" SDSTATGSCB % CB INITCHK  ITCHK CREFNUM  EFNUM  T P SOSDSTATj SDSTATGSCB LINEREL LINEREL INITCHK g ITCHK WBUFLEN  UFLEN SOSWRITE SWRITERWBUF } d ` \ X RELEASE RELEASE  RETADDR % ! INITCHK  ITCHK LINETO LINETO WBUFLEN  UFLEN SOSWRITE SWRITERWBUF     CALCABS x q ABS RETADDR CALCABS  ABS RETADDR  SOSDSTAT SDSTATGSCB INITCHK  ITCHK DOTREL DOTREL WBUFLEN  UFLEN SOSWRITE SWRITERWBUF SWRITERWBUF  RETADDR c _ < 8 INITCHK O ITCHK WBUFLEN Y UFLEN SOSWRITE\ SWRITERWBUF T L H D @ DOTAT DOTAT RWBUF ZRNJFCALCABS BRETADDR SOSDSTATSDSTATGSCB  MOVEREL MOVEREL INITCHK ITCHK WBUFLEN UFLEN SOSWRITE 1491 FAST.B.SORT 16 BASIC 00005 10/22/82 16:32 12/05/87 14:01 1695 FAST.CIRCLE 7 BASIC 00001 01/01/00 01:26 12/05/87 13:13 385 FAST.MOVE 21 BASIC 00004 07/15/88 22:48 12/13/87 19:54 1435 FILL.PIC 8