IMD 1.16: 29/05/2007 12:45:47 FOGCPM.048 --FOGCPM048BUFEXEC COMBUFEXEC DOCBUFEXECRCOM' BUFEXECRDOC EXAUTO ASM GRAFTESTBAS VIDEO BAS#ZEROMAKRCOMm !"#$ZEROMAKRDOC %&ZEROMAKRBAS'(NULL COM)NULL ASM!*+,-.OTHELLO BAS/0123456789:;<=>OTHELLO BAS%?@ABC-06-00 86 FREE30 DOCDEFGKEYBD COMHIKEYBD DOC5JKLMNOPFNKEYS COMQRFNKEYS DOC1STUVWXYKEYS COMZKEYS DOC[\]^KEYS MAC_`abSAVKEY COMcSETKEY COMdSET-SAVEDOC efSAVKEY ASM&ghijkSETKEY ASMlmnoEXROM11 COMpEXROM11 DOCqPEEK COM rsPEEK DOCtuvPEEK ASMwxyPEEKBDOSASMXz{|}~EXTONE1 COMEXTONE1 ASMRSXSEED MACTEXECSCRNCOMESNAPSHOTCOMSNAPSHOTASMEXECESAYTXT_-CPM048 DOC(This is the disk name. êÎTc#CPMOCC Executive,CC,PA,PL CompuServe CP/M (R) Executive Version 2.3++ **** Osborne Executive I **** Copyright (C) 1980, 1981 CompuServe Incorporated $1 2*!"!"22(  ͳ*#0 >fͺf21 2:>PͺI! ~ #DͺA ʜB ʜC ʜDʜHʠJʷKTʗYjʜmlO>fy>f>=f> f> f>f>Tf> f>f>Rf> f>f>=fͺfͺfL'Gogw# K>.!>/ A>02 Z!\F#~:I#>K+6~.Y#6:\q_:2:D ʻ > W> WYʶyl>2U!~#͒:B>͒*>. 2U: ~>. ͺ.>2!͹;w#%x2 x2>!U*2_W2|2 2|>2 : ¨_<2 !w: G_<2 !:B~~. Z *> #\W:_~ P.P#`I 6> I>. : <:e>02 ͺʅh>/ hC{2!2 ʡw#ÕK½: O: x2:>/ h>. h!2": <:>02 *F#>{: {~ %:~%%>{~@{#>{{ @>{{@{%ͳhzH E>{CW./#Hͳʮ#®ͳʢʬz•’ ʺ#ͺ2ͺzW{_z % CSEXEC - Initializing file transfer $ % CSEXEC - Beginning Download $ % CSEXEC - Beginning Upload $ ? CSEXEC - Aborting file transfer $ % CSEXEC - That file already exists on your disk. Do you wish to replace it (Y or N) ? $ ? CSEXEC - Diskette is full! $ ? CSEXEC - That file is not on your diskette! $ ? CSEXEC - Your diskette is full! $>  ͯ> d >W>jWͯ>W>kW> > > >D > > > > : :B >^W@WBUFEXEC.COM is a modem program designed to download files from CompuServe. It uses a special protocol that is detected by CompuServe's computer. To use the EXEC to download software (eg, from the CPM-SIG {special interest group}), you can find the file you want by BROwsing an XA (database), telling CompuServe you want to Download it. CompuServe's computer will then detect that you have a compatable program, then ask for the file name you want to store the program ON YOUR COMPUTER. Answer with standard CP/M naming protocol (d:filname.typ). The CompuServe computer will do the rest. Randy Cassingham CompuServe [72246,172] CP/M naming protocol (d:filname.typ). The CompuServe computer will do the rest. Randy Cassingham CompuServe [7224  kOEXECOM î#CPMOCC Executive,CC,PA,PL CompuServe CP/M (R) Executive Version 2.3++ **** Osborne Executive I **** using OEXECOM Resident System Extension Copyright (C) 1980, 1981 CompuServe Incorporated $1 2 *!"i!"o2 2 ( < : 2 < = : = : = hA*  3tʄ}ʊ b>332 1 2 3: >ʪIS! ~3 #ÞA B C DHJKTY:jm3l3O>yb>>=> > 3>>T> >>R$> 3>>=3L G o g w#fK >.{>/ 3A3>02 ʹ! \F#~:£#>å+͐~.³#͐:\_: 2 : DXr w > ͱ> ͱYy_w>2 ͯ2! ~#&: B?>wẅ́>. 2 3U_ >. ._>2 ! w#x2 *zx2 *>!.̈́2 3_ͱwK2|2 wQ2|>2 : wW_<2 !w: 'wG_<2 !: BG~B~B5ZVZ  ẅ́> }\ͱ: _~ ʪ.ʪ#`ڣ > ã>. : <:ڿ>02 h_>/ C{2 ! 2 w#K : O: x2 : >/ _>. ! 2 " : <:?>02 * F#>: ?~? : ~ww>~@#W>{ Қ>{@% h_z¢ Ÿ>Ýͱ./B}â } z }/2 9?zW{_z % CSEXEC - Initializing file transfer $ % CSEXEC - Beginning Download $ % CSEXEC - Beginning Upload $ ? CSEXEC - Aborting file transfer $ % CSEXEC - That file already exists on your disk. Do you wish to replace it (Y or N) ? $ ? CSEXEC - Diskette is full! $ ? CSEXEC - That file is not on your diskette! $ ? CSEXEC - Your diskette is full! $< : : Gx2 < : : (  % : B  % >^ͱ@ͱ: : <  H Can't locate the communications RSX - can't continue $OEXECOM   d e f tOEXECOM ] =oe f3dy< sr1r#~H#^#V#^#VS?!#H¤S= >2W[=O:Aye!~###^#VI[?!!!!RuV^rsrsV^rsrsw w w w [?Z[?>W[?l‚GOxڂ[?Ê[?>W[?!ʤ!».ʻ͇[?y[?>W[?!!.[?OQ[? [?>W[?!"!2.2[?:[?>W[?!T!d.d[?l[?>W[?!ʆ!ªV^rsrsw w [?ò[?>W[?!!V^rsrsw w [?[?>W[?>W:A%ͥ[?22A0[?>0W>2A2[?W{r {r>4>t>!ʈ!N ! D!#!#!#y!#! 7 Y`@0   O!.YQ ͅMO!.zQͅM!!.ʣ >( M!.ʾ >(M> > M>>M> >0 M>>0MůN yx .( ͇yN y姯^ V z(nf R 7znfq#ut4 4 ^VR nfutnfN#ut~ 5 5 ^VR nfutyOdC++++  ++++  + + + K K K K k I$D@"A D "H D D"$@"B$@$@"ID"D!DB HHH$$A I D"B@I $I**tnfN#ut~ 5 5 ^VR nfutyOdC++++ Different version of BUFEXEC. Not sure exactly what is different (what do you want for free?) BUFEXECR$$$; Osborne Executive Auto-Start Program ; ; By ; ; Guy Gamble 05/03/84 ; ; ------------------------------------------------------------- ; EXAUTO.ASM -- is intended to replace the original auto start ; program that came with the Osborne Executive. ; I wrote this very short program because I felt ; EXECST.COM program took to much time by displaying ; the Osborne Logo, etc. also EXAUTO uses only 1k ; of disk space. ; ------------------------------------------------------------- ; ; Customization instructions: ; ; 1. Insert the filename for the program you want to ; auto run into location NEWPRG: see below. ; If you want to execute a program other than a ; .COM file you will have to add the file extent. ; ; Examples: ; 'WS' ;for the filename WS.COM ; 'DATE.INT' ;for the filename DATE.INT (CBASIC) ; |||| ; ------ ; extent ; ; ; 2. Use MAC.COM and HEXCOM.COM to compile EXAUTO.ASM ; ; (Remainder of step 2 added by Jim Switz, FOG, 6 Feb 85) ; Here's How: ; a) Place this file, MAC.COM and HEXCOM.COM on one ; disk, with 20 or 30 K of space remaining (just ; to be safe). Then type the following (assuming ; you are using the A drive): ; ; b) A>MAC EXAUTO $PZ SZ ; ....some stuff appears.... ; A>HEXCOM EXAUTO ; ....more stuff appears.... ; ; 3. The compiled EXAUTO.COM now has to be renamed to ; EXECST.COM because this is the name that is used ; in the operating system. You must also change the ; attribute of the file to SYS. ; ; Example: ; REN EXECST.COM=EXAUTO.COM ; SET EXECST.COM[SYS] ; ; 4. This will now automatically run whatever program ; you inserted at the NEWPRG: location below. ; ; I hope I explained everything so people with little ; programing experience are able to implement this ; useful program. If you need any help leave questions ; either on the CPM SIG, EMAIL on Compuserve or FOG. ; ; Guy Gamble 74375,257 ; ; --------------------------------------------------------------- ; ;Program Listing ; WBOOT: EQU 0000H BDOS: EQU 0005H DMA: EQU 0080H ;Default DMA address CHAIN: EQU 47 ;CPM Plus CHAIN to program ; ; ORG 0100H ;Beginning of TPA ; LXI H,CMDLN ;Start of new command line MOV A,M ;Check first byte of CMDLN ORA A JNZ MOVE ;If file found on default drive ; move info to default DMA ; MVI C,0 ;File not found so reset system JMP BDOS ;.... ; ; Routine to move new command line into the default DMA for ; processing by the CPM Plus BDOS command 47 (Chain to program) ; MOVE: MOV C,M MVI B,0 LXI H,NEWPRG LXI D,DMA ; DB 0EDH,0B0H ;Z80 LDIR instruction tranfers ; the new command line to DMA ; MVI C,CHAIN ;CPM Plus (Chain to program) JMP BDOS ;.... ; CMDLN: EQU $ ;length of filename for program ; DB LENGTH ; ;.... ; ; ********************************************************************** ; ; FILENAME.EXT ;Insert filename.ext for program ; 12345678.123 ; you wish to auto run ; ; .COM files do not need the .EXT ; ' . ' ; put an apostrophe at the beginning ; ; and the end of program name. NEWPRG: DB 'WS' ; ; ********************************************************************** ; CMDEND: EQU $ ; ;.... ; ; Don't change the following necessary data ; DB 0 ;Mandatory filename termiator ; DB ' ' ;Pad with 12 spaces ; LENGTH: EQU CMDEND-CMDLN ;Calculate new filename length +1 ; END  termiator ; line into the default DMA for ; processing by the CPM Plus BDOS command 47 (Chain to program) ; MOVE: MOV C,M MVI B,0 LXI H,NEWPRG LXI D,DMA ; DB 0EDH,0B0H ;Z80 LDIR instruction tranfers ; the new command line to DMA ; MVI C,CHAIN ;CPM Plus (Chain to program) JMP BDOS ;.... ; CMDLN: EQU $ ;length of filename for program ; DB LENGTH ; ;.... ; ; 10 REM************************************************************************* 20 REM* THIS IS A TEST PROGRAM WRITTEN TO DOCUMENT THE SCREEN GRAPHICS BUGS * 30 REM* UNDER MBASIC ON THE OSBORNE EXECUTIVE I AS OF 18 DEC 1983. THIS * 40 REM* PROGRAM ILLUSTRATES THE FACT THAT CHARACTER STRINGS 9 AND 27 ARE NOT * 50 REM* INTERPRETED AT ALL, AND ARE SIMPLY IGNORED. HOWEVER, RUNNING THE * 60 REM* PROGRAM MAKES OBVIOUS THE FACT THAT THE GRAPHICS CHARACTERS REPEAT, * 70 REM* AND THAT SUBSTITUTING CHARACTER STRING 137 FOR 9 AND 155 FOR 27 (ONLY * 80 REM* WHEN USED AS AS A GRAPHICS CHARACTER, NOT AN `ESCAPE') WILL SOLVE THE * 90 REM* PROBLEM. THIS IS THE FIX USED TO PATCH `OTHELLO.BAS', FOR INSTANCE. * 95 REM* JIM SWITZ * 96 REM* FOG EXECUTIVE LIBRARIAN * 97 REM************************************************************************* 120 PRINT 130 PRINT 140 FOR I = 0 TO 255 150 PRINT CHR$(27)+"g"; 160 PRINT I;CHR$(I); 170 NEXT I 180 PRINT CHR$(27)+"G" 190 END  130 PRINT 140 FOR I = 0 TO 255 150 PRINENT THE SCREEN GRAPHICS BUGS * 30 REM* UNDER MBASIC ON THE OSBORNE EXECUTIVE I AS OF 18 DEC 1983. THIS * 40 REM* PROGRAM ILLUSTRATES THE FACT THAT CHARACTER STRINGS 9 AND 27 ARE NOT * 50 REM* INTERPRETED AT ALL, AND ARE SIMPLY IGNORED. HOWEVER, RUNNING THE * 60 REM* PROGRAM MAKES OBVIOUS THE FACT THAT THE GRAPHICS CHARACTERS REPEAT, * 70 REM* AND THAT SUBSTITUTING CHARACTER STRING 137 FOR 9 AND 155 FOR 27 (ONLY * 80 REM* WHEN USED AS AS A GRAPHICS CHARACTER, NOT AN `ESCAPE') WILL SOLVE THE * 90 REM* PROBLEM. THIS IS THE FIX USED TO PATCH `OTHELLO.BAS', FOR INSTANCE. * 95 REM* JIM SWITZ * 96 REM* FOG EXECUTIVE LIBRARIAN * 97 REM************************************************************************* 120 PRINT 130 PRINT 140 FOR I = 0 TO 255 150 PRIN10 REM *************************************************** 20 REM ***** ***** 30 REM ***** VIDEO ATTRIBUTES - OSBORNE EXEC ***** 40 REM ***** ***** 50 REM ***** FEBRUARY 1984 - H. M. HAWKINS ***** 60 REM ***** ***** 70 REM *************************************************** 80 REM 90 PRINT CHR$(&H1A): REM CLEARS SCREEN 100 PRINT:PRINT:PRINT:PRINT:PRINT 110 PRINT TAB(28)," MENU SELECTIONS" 120 PRINT 130 PRINT TAB(28) " 0. WINDOWING " 140 PRINT TAB(28) " 1. BLINKING CURSOR " 150 PRINT TAB(28) " 2. STEADY BLOCK CURSOR" 160 PRINT TAB(28) " 3. BLINK UNDERLINE CURSOR " 170 PRINT TAB(28) " 4. STEADY UNDERLINE CURSOR " 180 PRINT TAB(28) " 5. INVERSE VIDEO ON " 190 PRINT TAB(28) " 6. INVERSE VIDEO OFF" 200 PRINT TAB(28) " 7. REVERSE VIDEO" 210 PRINT TAB(28) " 8. NORMAL VIDEO" 220 PRINT TAB(28) " 9. DEFINE BACKGROUND. 230 PRINT 240 PRINT TAB(28),"ENTER SELECTION"; 250 A$=INKEY$:IF A$="" THEN GOTO 250 260 IF A$="0" THEN 290 270 ON VAL(A$) GOTO 490,510,530,550,570,590,610,630,650 280 GOTO 90 290 PRINT CHR$(26):PRINT TAB(28)"WINDOW FEATURE" 300 PRINT:PRINT:PRINT TAB(20)"THE SCREEN CONTAINS 80 COLUMNS AND 24 ROWS." 310 PRINT TAB(20)"YOU MAY DEFINE A WINDOW BY SELECTING THE" 320 PRINT TAB(20)"BEGINNING AND ENDING OF THE COLUMN & ROW" 330 PRINT TAB(20)"BY ANSWERING THE PROMPTS WHICH FOLLOW." 340 PRINT TAB(20)"THE WINDOW YOU DEFINE WILL SCROLL ON THE SCREEN" 350 PRINT TAB(20)"WHILE THE REST OF THE DISPLAY WILL BE FROZEN." 360 PRINT TAB(20)"FOR EXAMPLE, A SMALL WINDOW IN THE MIDDLE OF THE" 370 PRINT TAB(20)"SCREEN, 4 BY 12 SPACES, CAN BE DEFINED BY USING" 380 PRINT TAB(20)"THE SEQUENCE 8-30-12-42. TO RESTORE THE FULL" 390 PRINT TAB(20)"SCREEN, ENTER THE SEQUENCE 24-80-24-80." 400 PRINT TAB(20)"REMEMBER TO PRESS 0 (ZERO) TO SELECT THE" 410 PRINT TAB(20)"MENU SELECTION - THEN ENTER THE NUMBER SEQUENCE." 420 PRINT:INPUT"ENTER BEGINNING ROW (1 TO 24) THEN PRESS ";BR 430 PRINT:INPUT"ENTER BEGINNING COLUMN (1 TO 80) PRESS ";BC 440 PRINT:INPUT"ENTER ENDING ROW (1 TO 24) PRESS ";ER 450 PRINT:INPUT"ENTER ENDING COLUMN (1 TO 80) PRESS ";EC 460 PRINT CHR$(27)+"z"+"5"+CHR$(BR+32)+CHR$(BC+32)+CHR$(ER+32)+CHR$(EC+32) 470 PRINT CHR$(27)+"s"+"5" 480 GOTO 90 490 PRINT CHR$(27)+"."+"1" 500 GOTO 90 510 PRINT CHR$(27)+"."+"2" 520 GOTO 90 530 PRINT CHR$(27)+"."+"3" 540 GOTO 90 550 PRINT CHR$(27)+"."+"4" 560 GOTO 90 570 PRINT CHR$(27)+"j" 580 GOTO 90 590 PRINT CHR$(27)+"k" 600 GOTO 90 610 PRINT CHR$(27)+"b" 620 GOTO 90 630 PRINT CHR$(27)+"d" 640 GOTO 90 650 PRINT CHR$(&H1A):PRINT:PRINT:PRINT:PRINT 660 PRINT TAB(10) " THE FOLLOWING MENU WILL ALLOW YOU TO CHANGE THE" 670 PRINT TAB(10) " BACKGROUND VIDEO. SIMPLY SELECT THE CHARACTER" 680 PRINT TAB(10) " YOU DESIRE WHEN THE PROMPT IS OFFERED." 690 PRINT 700 PRINT TAB(12) "0 = NORMAL 9 = DIM UNDERLINE" 710 PRINT TAB(12) "1 = DIM : = BLINK UNDERLINE" 720 PRINT TAB(12) "2 = BLINK ; = DIM UNDERLINE BLINK" 730 PRINT TAB(12) "3 = DIM BLINK < = UNDERLINE REVERSE" 740 PRINT TAB(12) "4 = REVERSE = = UNDERLINE REVERSE DIM" 750 PRINT TAB(12) "5 = REVERSE DIM > = UNDERLINE REVERSE BLINK" 760 PRINT TAB(12) "6 = REVERSE BLINK ? = UNDERLINE REV. DIM BLINK" 770 PRINT TAB(12) "7 = REVERSE DIM BLINK" 780 PRINT TAB(12) "8 = UNDERLINE X = RETURN TO MAIN MENU" 790 PRINT:PRINT 800 PRINT "SELECT NUMBER OR CHARACTER FROM ABOVE MENU"; 810 M$=INKEY$ 820 IF M$="" THEN GOTO 810 830 IF M$="0" THEN 1010 ELSE 840 840 IF M$="1" THEN 1010 ELSE 850 850 IF M$="2" THEN 1010 ELSE 860 860 IF M$="3" THEN 1010 ELSE 870 870 IF M$="4" THEN 1010 ELSE 880 880 IF M$="5" THEN 1010 ELSE 890 890 IF M$="6" THEN 1010 ELSE 900 900 IF M$="7" THEN 1010 ELSE 910 910 IF M$="8" THEN 1010 ELSE 920 920 IF M$="9" THEN 1010 ELSE 930 930 IF M$="X" THEN 90 ELSE 940 940 IF M$="=" THEN 1010 ELSE 950 950 IF M$=";" THEN 1010 ELSE 960 960 IF M$=":" THEN 1010 ELSE 970 970 IF M$="<" THEN 1010 ELSE 980 980 IF M$=">" THEN 1010 ELSE 990 990 IF M$="?" THEN 1010 ELSE 1000 1000 GOTO 650 1010 PRINT CHR$(27)+"x"+M$ 1020 GOTO 650 980 IF M$=">" THEN 1010 ELSE 990 990 IF M$="?" THEN 1010 ELSE 1000 1000 GOTO 650 1010 PR(12) "6 = REVERSE BLINK ? = UNDERLINE REV. DIM BLINK" 770 PRINT TAB(12) "7 = REVERSE DIM BLINK" 780 PRINT TAB(12) "8 = UNDERLINE X = RETURN TO MAIN MENU" 790 PRINT:PRINT 800 PRINT "SELECT NUMBER OR CHARACTER FROM ABOVE MENU"; 810 M$=INKEY$ 820 IF M$="" THEN GOTO 810 830 IF M$="0" THEN 1010 ELSE 840 840 IF M$="1" THEN 1010 ELSE 850 850 IF M$="2" THEN 1010 ELSE 860 860 IF M$="3" THEN 1010 ELSE 870 870 IF M$="4" THEN 1010 ELSE 880 880 IF M$="5" THEN 1010 ELSE 890 890 IF M$="6" THEN 1010 ELSE 900 900 IF M$="7" THEN 1010 ELSE 910 910 IF M$="8" THEN 1010 ELSE 920 920 IF M$="9" THEN 1010 ELSE 930 930 $!8ÐUW$!(!j(8 !(!k(8 !(l!l!l!l!Jl!Jl!rl!'l!l!l!(l!Jl!<! H!gH! l!Jl!Jl! l!l!Jl!H! z !ͣ !8!ͩ%! %!7!!Jl!Jl!uH!l͟MÕͷMͧsQ!(l!(l!Jl!Jl!m%!Jl!Jl!9H!6 z !ͣ !2ͧ!.ͧ|g}o|%(1y5Y91< Do you wish to name another disk (Y/N) pB:*.*2x ZERO FILE CREATED ON DRIVE B - NAME: RB:-1 Enter the name of the new ZERO file: 2 Directory of the B: drive.D# This program will then confirm the listing by calling up the,j INSERT the disk to be named in the B Drive D any combination of seven letters or numbers for a file name.G the dash (-) in the first position of the file. You may enterH* in the FOG Program `CATALOG'. This program automatically insertsEu This program is designed to create a zero length file for use* CP/M 3.0( V1.55 Osborne EXECUTIVE Zero ProgramMz[[[[ BASLIB #100288 5.1 - OWNED BY MICROSOFT, 1979 <ÚÚ*DM*"T*##"R`>22*^#V"##^#V"!Z"W6#6P>2^>2]>2\͔͗ _|"~͟*"*}|I$"6# xJ$* ">:!9"$*6*0x!6#}x|x6!*6#z‹*4|ʬ> 6#s#r#=¡>2>2!>2 2#"&!"1ͳG͜ STO M *1.. . .........7*?|:<Q*:|QP *0 s#r*0 {w#6"=*$*:>2<M ͜Error -!~~Input Past En?Bad Record Numbe@Bad File NamCToo Many FileUnprintable Erro!9N#F**~#~ҁ ~+ʇ ~#~ځ +^#V###_ ###_ |ʓ ~#fo! ͜ Internal Error - No Line Number **~#/ ͜ at lineP M > <    < 0͎+  }_|W!% Q,~#fo>͜ at address|!}!M > ͎+> Î+!9"*: G(!(####~#’(F#N#~#fo~#fo(B¥(##~>O%6#p#6 ####y̓B&+w~!)͑B~L+>_*:J)R,G'R,>r'*͒#))%*`i)9^#V!~̰&y,*#~#fo##A:)R,x>r'N#"v !9"q "s y2u */|ʜ *G!s "?A~#*x E,~s .   "x   !*f-*d-*b-*`- o*d- *f-*d-*x E,! ~#"x ,s ä ~s !"?~,"9 #"~M M # < s "S #"x x"h h +~ ] y ͜?Redo from Start *q 7! *v :u Oã *s +~+    +w ++~#fo"s !u 5*q ~2 #~#^#V͎++-ͥ)W uVW ̀VW ͋VW KVW usW ̀sW ͋sW ÁW u&W ̀&W ͋&W &d-Ö`-Ö"d-ßH~# —x2:RM <͍~*#ü~ *#>2:RMF#~#fox̍ ~#*->"*G:Vxʢ+*W+~ *>,*W*W#^ ̰ʪ+=ڪ͢+z{{_ô!Z"W!"/2R!U~6#w~!Na i& G~##++*0:5Î+W ͹YY--~#~#foV,>Ä>Ä>Ä>Ä>Ä>^#V#^#V#ú+>î>î>î>î>î>!+#,^#V#W [3ý^#,W ~##++ĭ>V,+V+^++r+sW ~#^#V|W !9>+͉*W{ *P|}*W_@++*V"Vs#r+E*P#~_#~W a r+s##6"T###!V~#foDd,4<*R"P*T}o|g6@#s#r#6"T**"V}w>#w##d,o++6+6Xa7~͎+#=͢~͎+#â~#N#F#^#V=2PY! N#F!^#VL3 '*d-}/o|/g#"d-|.<5!f-~wɯ2g-'͌1.*d-.<5'l1>>~#3!j-Q>!j-`-2X# W!j-/!j-8~->>z>|}+!.ͨ5+6!f->/12_-!3!.!j-.~_#~W#~O6^3![35ɇ<o&.<5*d-*f-"d-`i"f-!d-^#V#N#F#!\46x{6!h-6͵5wg>=76<:Gw#<7Q!j-8d-'`-'/*d-||<'*d-K!EaÎ:f-2f-:g- :g-¯ô|/g}/o! :g-"d->2aj L}+>2`h~&B-%+%+ .ʲe7Ea lOLOqOQ`:z>z~%ʿ#!dzD‘ 8 {‘_{_•'!' ‘%#oÑ#Ñ !' ='DGt"`-`i"b-#~+-0OxG#~ª`xEy ҕ>2|ҕÕ"`-`i"b-#W:)--͙60 +~0<. n'>"w#6+_6-/</ a:#p#w#6!#zڌ͑zmX{̂=mʤp#6!#:~ ʩ*ʩ+ -+$0# ++wê6%ړ g+6%/>_xm̈́}ĬÑ_yIK{_xgm̈́xmyͰOmGOƒ*=mPÚѯʙ/7yOzWO/< ͬ/>N>Np#=!`->?ͬ/{_#zW#yO++0ͳ#p#">^>ͬN#F#*d-/}o|gq"d-p#=^ͬw1_cƤ~@zZrN vH Tʚ;@B''d #~:   0?<=:47-++ OSHS+_hH#ʔna M!̀~}0?)))صoÀM!ͦڤ}0? ڼ? ))))صoæa{ o':g-:f-ÿ:22a a 6@2.6!`6=y=7= 7=6E= 7!6=:.6!?6ܤ=!`6:96u=i66> =k=ܤ=:66Š=:36Š=:462665@??*/6##:76226G6 ~¾==w# ´= #ô= w#W }%|)y)!$ ~ #~ `iͲ" >O #~goPY!$ ůw"ʑ)&!ѯÂ)<ʗ)!" ^#Vr+sW }%}%s! PYi!!`!`i>!!$ ~!"͖&W }%|)!#‘!! ~+ngW }%|)! n&*/~v)ʋ(DM$~ 4N#V p!zw w+s#r#6#6DM! {zV:" w<8"<ʗ)!! {w:f)O"Ͳ"!! ~ !& p" p"m)~# s"*/~ʹ(% ~ʝ"+~#5O ~+~ʩ"ͯ""7>*/T]" N#F+q#p###6 ""=">w+w!%}"7?*/$ 6#67~ʔ)#^#fk_,#N#~:0#++@ʔ)y@ڔ)Ҕ)  ##~.Z#m#7F##G#2 -z ʔ)ڔ)> m#a#> †#a#W #  <ʋ)!  > V,#: ! š) <…) * ~y)#N#F++- O$I$Ry)* |$!" }_%-$͖&{%ˆ)z# &"/# > V,66"~y$<ʗ)Î$<Ž$‹)m$!"w#w#w#w~ʪ$ͯ"& p# °$% _W #  <ʋ)W ! 6# ͡%!%W #2 ! ͝%! ͝%  ʋ)O!  ~#*yp%~ m%>.* Z%:Z W:[ډ%> *** J%~*6?# ¡%" >25!("6:3<23*1" !%"1" W #*C|%##n?!%.:!* |)<|)=_!C~#fo"&##{8&++&*CA&"Cq#p#s#4#5++###DM !E~#fot&+V+^##* {zF&BK^#V+"E! DMÆ&* DMs#r# 6# x‰& !CT]~#fo|)x¡&y¡&~#~+*E"Es#rC* |&! s#r#w&2&W :&)'"&)'2&W :&*'"&*'2&}%y)! ^#V:&L'*&{)+s#r! w#w! ~#fo!g)|'ú'BK>!)ҏ')#Ð'))Ҟ' ҝ'#=…'}_}la)ښ)ҵ'#xš)"&! "&!& "&!}o|gg)'bk:&*(g)'G(DM*&*&~("&PYF(}o|g*&#"&'G(DM*&*&~("&PY(2f)*&! ~#fog)s#rm(:f)z(!z(!# !~# x(DM(ʎ)(! w!% V6 ʴ(zw(ʎ)(! ~!(! ^#V! s#rDM((g)}%|))y)`i"/!)"8D)"a !>W |,>)-:5|)*6!"8{͹f$%b)![)*8M)|}!"/>6>4>?>=>:>7>5>2>3>@>C>a o&!"/!z "x ͻ): )͜?)p**:*>\2*))*+)~**+****!z 2***O):*'*>\*2*yʑ**7 ʸ* ʑ* K*)Ñ**)i*)*> *>)s*>#)Œ*6*!z ** *x<>ʜ*yq#* *> **ʩ* **: *wdM Î+>^*@**~ *> **#**W +#~+<+=ܢ+ y+|+ "+4+~# *~=€+*W!Z"W*"W> *> *> > **+ G++~#fo+##+>+~+~?~,+# ,+ ,&)))^#V#!d-3,3,w#w#w#w##~ D, D,Ʌo$ɧGw#Z,{zJDM!>)کI)ґI کI=ƒI|I JʺI6HͩF6HExG6HÄF|JJDM!>I I7>{_zW}o|g=I×I|G J|GOoygG*J|XHiFIg{oH J! ~w! ~G+NFrJ/<#Fwx+ bJF+N9F!G>6#r-͡1q-ʭ-6Oʲ-!7!f-y#ª-+-6?7͕.6l1-͕.c1x.!j-͡17.:g-6:q-//1I02_-:`-͖06x/F+N+=µ.!j-.!`->q#p#=.!`-.",.ͯ.͛.*,͡1ʰ6:g-ʰ6!p-N#Fʹ41q+/G]0[1x / /Ö0!f-71#/j0 TeB׳]h!I.k ͕.6l1r/͕.c1!j-.!g-q#~++w+q/6DNn"~`35zr1{r1h!I͡16yO2p-/͡16:g-x.//11626!h-6͵5g>=7|ԑ5>1ak6V24V266d26l2ͽ54245|6@2!V2Q2ͽ52b4s2>O!g-~+>w6QY656:g-Ҫ2hڢ2ͽ54Ɓʪ2͟53!203Jf4QY6666|Yt&wz^Pc|u~r162>2g-!203ͽ5og<5a3 }}{(qnz ͽ56b403b4ͽ5~#6=x_46a3;3N5^366:g-6q3/<͟56ͨ5g=7!d-3~_#~W#~OҐ6#46.S7Ð6G~_#~W#~O܋55N5366>Oa3N53656ȯGʹ4"M-y2O-Fo͖5͟5!D*d-:f-O4g-46(484g.*M-:O-Oz484g.*d-:f-4x<=O4{_zWxG)yOHGÐ6N5_4666ʹ4y+F+F+Fw`h|ʬ4gyҐ4:d-O|g}oxG-|„4}45ElaO~4!g-~Gx4ƀʯ6wͨ5w+ɷ6ð66x{6!h-6͵5wg4z4 >=7|Ԣ6{>2g-5/$7 #77>{_zW}o|g=7|g}oL7CZQ?7 o-yOzW{_xGO7d-*f-DM^#V#N#F#xy7:g-:f!d-3~_#~W#~OҐ6#46.S7Ð6G~_#~W#~O܋55N5366>Oa3N53656ȯGʹ4"M-y2O-Fo͖5͟5!D*d-:f-O4g-46(484g.*M-:O-Oz484g.*d-:f-4x<=O4{_zWxG)yOHGÐ6N5_4666ʹ4y+F+F+Fw`h|ʬ4gyҐ4:d-O|g}oxG-|„4}45ElaO~4!g-~Gx4ƀʯ6wͨ5w+ɷ6ð66x{6!h-6͵5wg4z4 >=7|Ԣ6{ ZEROMAKR.DOC CREATED: 3/17/84 by DAVID WHORF FOG # 251 C/O ALNITAK COMPUTING COMPANY 1326 GREENWICH STREET SAN FRANCISCO, CA. 94109 ZEROMAKR.BA i progra designe t facilitat th creatio o zer-lengt fil fo us wit th FO `CATALOG program CP/͠ 3. doe no hav th abilit t creat zero-lengt indexin fil wit "SAV 0 function Thi progra create suc fil withou th nee o PIPin a existin indexin fil fro anothe disk Th DASȠ tha i necessar i th firs positio o th fil name i automaticall inserte wit thi program Yo ma therefor ente an combinatio o letter an number u t tota o SEVEN Fil Typ designatio i optional. Thi progra shoul b ru o th Drive Th disk t b name shoul b place i th Drive Afte eac ne name dis ha bee created th director o th Driv i displaye i orde t confir th ne label. Yo ma continu t labe additiona disk b answerin "Y t th promp afte th director display. Th creatio o th zer fil i accomplishe b openin rando fil an the closin i withou makin an entries Th progra i quit simpl a th listin shows Ther i timin loo i lin 30 whic yo ma wis t alte o eliminate. I hope you enjoy using ZEROMAKR.BAS - DAVID WHORF  indexin fil fro anothe disk Th DASȠ tha i necessar i th firs positio o th fil name i automaticall inserte wit thi program Yo ma therefor ente an combinatio o letter an number u t tota o SEVEN Fil Typ designatio i optional. Thi progra shoul b ru o th Drive Th disk t b name shoul b place i th Drive Afte eac ne name dis ha bee created th director o th Driv i displaye i orde t confir th ne l10 REM ****************************** 20 REM *** ZEROMAKR.BAS ****** 30 REM ****************************** 40 REM A METHOD FOR CREATING A ZERO FILE ON THE EXECUTIVE 50 REM BY USING THE OPEN STATEMENT FOR A RANDOM FILE IN MBASIC 60 REM THIS IS IN LIEU OF THE `SAVE 0' FUNCTION USED BY THE OSBORNE 1 70 REM Created by David Whorf 03/12/84 FOG#251 75 SI$=CHR$(27)+CHR$(106):EI$=CHR$(27)+CHR$(107) 80 PRINT CHR$(26) 90 PRINT " Osborne EXECUTIVE Zero Program" 100 PRINT " V1.5" 102 PRINT " CP/M 3.0" 105 PRINT:PRINT 110 PRINT " This program is designed to create a zero length file for use" 120 PRINT " in the FOG Program `CATALOG'. This program automatically inserts" 130 PRINT " the dash (-) in the first position of the file. You may enter" 140 PRINT " any combination of seven letters or numbers for a file name." 150 GOTO 170 160 PRINT CHR$(26) 170 PRINT 180 PRINT TAB(18)SI$ " INSERT the disk to be named in the B Drive ";EI$ 190 PRINT 200 PRINT:PRINT " This program will then confirm the listing by calling up the" 210 PRINT " Directory of the B: drive." 220 PRINT 230 PRINT " Enter the name of the new ZERO file: ";:INPUT;"",Z$ 250 Z$="B:-"+Z$ 260 OPEN "R",1,Z$,12 270 CLOSE 280 PRINT:PRINT 290 PRINT " ZERO FILE CREATED ON DRIVE B - NAME: ";Z$ 300 FOR I=1 TO 2000:NEXT I:PRINT CHR$(7) 310 PRINT CHR$(26) 320 PRINT:PRINT 330 FILES "B:*.*" 340 PRINT 350 PRINT:PRINT " Do you wish to name another disk (Y/N) ";:INPUT;"",Y$ 360 IF Y$<>"Y" AND Y$<>"y" THEN END ELSE GOTO 160 370 END  " Do you wish to name another disk (Y/N) ";:INPUT;"",Y$ 360 IF Y$<>"Yautomatically inserts" 130 PRINT " the dash (-) in the first position of the file. You may enter" 140 PRINT " any combination of seven letters or numbers for a file name." 150 GOTO 170 160 PRINT CHR$(26) 170 PRINT 180 PRINT TAB(18)SI$6 NULL FILE UTILITY v1.0 - for CPM PLUS - 03/19/84 This writes a NULL file to drive B: :v2y1l6 Type Q to QUIT or Press RETURN to continue OQ  6 TRY AGAIN !! d6 INSERT DISK in drive B: ENTER FILENAME.EXT :dpy͉<´͒<͛6 ä~F#~7#_   _ yo%\\\!yz&6d͛6 +++ FILE ALREADY EXISTS +++ ä6 +++ NO DIRECTORY SPACE +++ ä 6 {\ ;NULL v1.0 - CP/M Plus Utility - For writing a 0 byte file to disk ; ; COPYRIGHTED 1984 BY GUY GAMBLE ; ; This utility takes the place of the A>SAVE 0 filename.ext of CPM 2.2 ; and before. The main reason I wrote this was to make it easy to write ; a directory entry of type -.123 so the popular MCAT program can be ; used with C/PM Plus operating system. The program is self explanatory ; so I did not write a DOC file. ; ; The only thing you might need to know is that drive B: is the default ; drive that the program writes to. So you don't need to specify any ; drive when you name the file. ; ; This program is donated to Public Domain and I hope people will im- ; prove on it. It is not intended for commercial distribution. If you ; make modifications please update and resubmit to the Public Domain ; either here or any other RCPM BBS. ; - Guy Gamble ; ;======================================================================= ; ; System Equates under CP/M Plus ; BASE: EQU 0 FCB: EQU BASE+5CH BDOS: EQU BASE+5 PRINT: EQU 9 CONIN: EQU 1 CONOUT: EQU 2 RESETD: EQU 13 ;Disk system reset both drives SDSKR: EQU 37 ;Single disk reset SELDK: EQU 14 PFCB: EQU 152 ;CPM Plus only PARSE FCB RCONBF: EQU 10 MAKEF: EQU 22 OPEN: EQU 15 CLOSE: EQU 16 ; ; ; EQU for ASCII characters ; CR: EQU 0DH LF: EQU 0AH CLS: EQU 1AH ;Clear screen ; ; ; ORG BASE+100H ; ; ; Sign on messege ; CALL ILPRT DB CLS,LF,' NULL FILE UTILITY v1.0 - for CPM PLUS - 03/19/84' DB CR,LF,LF DB ' This writes a NULL file to drive B:',CR,LF,LF,0 ; START: LDA BUFLEN ;Maximum input buffer length (12 char) STA INBUF ;initialize 0 byte of the input buffer ; ;for BDOS function 10 ; ; LXI SP,STACK ;local stack XRA A CALL ILPRT DB ' Type Q to QUIT or',CR,LF,LF DB ' Press RETURN to continue ',0 CALL CRTIN CPI 'Q' JZ QUIT CPI CR JZ MSG CALL ILPRT DB CLS,LF,LF,' TRY AGAIN !!',CR,LF,LF,0 JMP START ; ; ; MSG: CALL ILPRT DB CLS,LF,LF,' INSERT DISK in drive B:',CR,LF,LF DB ' ENTER FILENAME.EXT',CR,LF,LF DB ' :',0 CALL INPUT CALL MOVFN ;move name from inbuf to FCB ; ;BDOS function 152 under CPM Plus only CALL RESDSK CALL OFILE INR A JNZ ERR1 CALL MFILE INR A JZ ERR2 CALL CFILE CALL ILPRT DB CLS,LF,LF,0 JMP INIT ; ; ILPRT: XTHL ;inline print routine ; ; ILPLP: MOV A,M PUSH H CALL CRTOUT POP H INX H MOV A,M ORA A JNZ ILPLP INX H XTHL RET ; ; CRTOUT: PUSH PSW MVI C,CONOUT MOV E,A CALL BDOS POP PSW RET ; ; CRTIN: MVI C,CONIN CALL BDOS ANI 07FH CPI ' ' RZ CPI 'C'-40H JZ QUIT CPI ' ' RC ANI 05FH RET ; ; ; INPUT: MVI C,RCONBF ;BDOS function 10 LXI D,INBUF ;input buffer address CALL BDOS CALL CRLF RET ; ; MOVFN: MVI C,PFCB ;move filename.ext from input ; ;buffer to FCB. BDOS 152 CPM Plus only LXI D,PFILE CALL BDOS RET ; ; RESDSK: MVI C,SDSKR ;reset drive B: only LXI D,0002 CALL BDOS ; MVI C,SELDK ;select drive B: MVI  E,01 CALL BDOS RET ; ; OFILE: MVI C,OPEN ;check to see if file exists LXI D,FCB CALL BDOS RET ; ; MFILE: MVI C,MAKEF ;write file to disk LXI D,FCB CALL BDOS RET ; ; CFILE: MVI C,CLOSE LXI D,FCB CALL BDOS RET ; ; INIT: LXI H,INBUF ;initialization of input buffer LXI D,INBUF+1 LXI B,0026H MVI M,0 ;fill with 0's DB 0EDH,0B0H ;Z80 LDIR command JMP START ;start over again ; ; ERR1: CALL CFILE CALL ILPRT DB CLS,LF,LF,' +++ FILE ALREADY EXISTS +++',CR,LF,LF,0 JMP INIT ; ; ERR2: CALL ILPRT DB CLS,LF,LF,' +++ NO DIRECTORY SPACE +++',CR,LF,LF,0 JMP INIT ; ; QUIT: CALL CRLF MVI C,RESETD ;reset both drives before returning ; ;to CPM CALL BDOS JMP BASE ; ; CRLF: CALL ILPRT DB CR,LF,0 RET ; ; DS 80 ;local stack STACK: DB 0,0,0 ; ; PFILE: DW INBUF+2 ;BDOS function 152 DW FCB ;move filename.ext from inbuf+2 DB 0,0,0 ;to FCB address ; ; BUFLEN: DB 0CH,0,0 ;maximum number of char allowed ; ;to be input -filename.ext ; ;currently set for 12 chars INBUF: DB 0,0 DS 26H ; ; END MAKEF ;write file to disk LXI D,FCB CALL BDOS RET ; ; CFILE: MVI C,CLOSE LXI D,FCB CALL BDOS RET ; ; INIT: LXI H,INBUF ;initialization of input buffer LXI D,INBUF+1 LXI B,0026H MVI M,0 ;fill with 0's DB 0EDH,0B0H ;Z80 LDIR command JMP START ;start over again ; ; ERR1: CALL CFILE CALL ILPRT DB CLS,LF,LF,' +++ FILE ALREADY EXISTS +++',CR,LF,LF,0 JMP INIT ; ; ERR2: CALL ILPRT DB CLS,LF,LF,' +++ NO DIRECTORY SPACE +++',CR,LF,LF,0 JMP INIT ; ; QUIT: CALL CRLF MVI C,RESETD ;reset both drives before returning ; ;to CPM CALL BDOS JMP BASE ; ; CRLF: CALL ILPRT DB CR,LF,0 RET ; ; DS 80 ;local stack STACK: DB 0,0,0 ; ; PFILE: DW INBUF+2 ;BDOS function 152 DW FCB ;move filename.ext from inbuf+2 DB 0,0,0 ;to FCB address ; ; BUFLEN: DB 0CH,0,0 ;maximum number of char allowed ; ;to be input -filename.ext 100 DEFINT A-Z 110 DIM B(9,9),BR(8,8) 'B IS THE BOARD 120 DIM BSAVE(9,9) 'USED FOR SAVING THE BOARD 130 DIM BRM(8,8) 'MODIFIED BOARD RATINGS 140 M = 3 150 DIM IB(M),JB(M),RB(M) 'FOR M BEST MOVES 160 STRTEND = 50 170 SEARCH = 0 180 REM BR IS THE RATING OF THE BOARD POSITIONS 190 DIM IDIR(8),JDIR(8) 200 DIM XDIR(8),YDIR(8) 210 DIM CHNG(8),TOT(2) 220 REM TWO PLAYERS ARE -1 AND 1 230 REM PLAYER 1 IS BLACK (SMALL SQUARE) 240 REM PLAYER -1 IS WHITE (LARGE SQUARE) 250 REM BLACK (1) GOES FIRST 260 GOSUB 970 'INITIALIZE THE DIRECTIONS 270 REM 280 REM ****************************************** 290 REM START NEW GAME 300 GOSUB 3420 'LOAD THE BOARD RATINGS 310 SEARCH = 0 320 GOSUB 4100 'PRINT INTRO MESSAGES AND SET OZ 330 GOSUB 840 'INITIALIZE THE BOARD 340 GOSUB 1110 'PRINT THE BOARD TEMPLATE 350 GOSUB 1400 'PRINT THE INITIAL FOUR PIECES 360 MOVENUM = 4 : PLYR = 1 370 GOSUB 2900 'PRINT PLAYER AND TOTALS 380 EXM = 1 'ASSUME THERE IS A LEGAL MOVE 390 IF(PLYR<>OZ) THEN GOSUB 1490 'MOVE THE CURSOR FOR MOVE 400 IF(PLYR=OZ AND MOVENUM=STRTEND)THEN GOSUB 4780 420 IF(EXM=0) THEN GOTO 550 430 GOSUB 2170 'CHECK IF MOVE IS LEGAL AND SET CHANGES 440 IF(LEGAL=0) THEN GOSUB 2460 : GOTO 390 450 REM GOSUB PRINTS ILLEGAL MOVE MESSAGE 460 GOSUB 2590 'PERFORM THE MOVE (FLIP PIECES) 470 IF(MOVENUM=STRTEND-1) THEN GOSUB 3190 530 REM CHECK IF PLAYER HAS A LEGAL MOVE 540 IF(EXM=1) THEN GOTO 370 550 REM ONE PLAYER HAS NO LEGAL MOVE 560 GOSUB 3330 'PRINT NO LEGAL MOVE MESSAGE 570 PLYR = PLYR*(-1) 580 GOSUB 3190 'CHECK IF SECOND PLAYER HAS A MOVE 590 IF(EXM=0) THEN GOSUB 3330 : GOTO 610 600 GOTO 370 610 REM END OF GAME 620 REM ****************************************** 630 REM 640 PLYR = 0 : GOSUB 2900 'PRINT FINAL TOTALS 650 XPOS = 65 : YPOS = 49 : GOSUB 4040 660 PRINT"END OF THE GAME"; 670 YPOS = YPOS + 2 : GOSUB 4040 680 IF(TOT(0)=TOT(2))THEN PRINT"IT WAS A TIE"; 690 IF(OZ=-1 AND TOT(0)>TOT(2))THEN PRINT"YOU LOST"; 700 IF(OZ=1 AND TOT(0)TOT(2))THEN PRINT"YOU WON!"; 730 YPOS = YPOS + 1 : GOSUB 4040 740 IF(LEN(INKEY$)<>0) THEN GOTO 740 750 PRINT"HIT Q TO QUIT"; 760 YPOS = YPOS + 1 : GOSUB 4040 770 PRINT"OR ANY OTHER KEY"; 780 YPOS = YPOS + 1 : GOSUB 4040 790 PRINT"FOR ANOTHER GAME "; 800 A$ = INKEY$ : IF(LEN(A$)=0) THEN GOTO 800 810 IF(A$="Q" OR A$="q") THEN STOP ELSE GOTO 290 820 REM END OF THE PROGRAM 830 REM ------------------------------------------- 840 REM INITIALIZE THE BOARD 850 REM MATRIX B(8,8) CONTAINS THE BOARD 860 FOR I = 0 TO 9 870 FOR J = 0 TO 9 880 B(I,J) = 0 890 NEXT J 900 NEXT I 910 B(4,4) = -1 : B(5,5) = -1 920 B(4,5) = 1 : B(5,4) = 1 930 TOT(0) = 2 : TOT(2) = 2 940 RETURN 950 REM END OF INITIALI ZING THE BOARD 960 REM ------------------------------------------- 970 REM INITIALIZE THE DIRECTIONS 980 REM THE DIRECTIONS ARE AS FOLLOWS: 990 REM 1-8 ARE E,W,S,N,SE,NW,NE,SW, RESPECTIVELY 1000 IDIR(1)=1 : IDIR(2)=-1 : IDIR(3)=0 : IDIR(4)=0 1010 IDIR(5)=1 : IDIR(6)=-1 : IDIR(7)=1 : IDIR(8)=-1 1020 JDIR(1)=0 : JDIR(2)=0 : JDIR(3)=1 : JDIR(4)=-1 1030 JDIR(5)=1 : JDIR(6)=-1 : JDIR(7)=-1 : JDIR(8)=1 1040 XDIR(1)=4 : XDIR(2)=-4 : XDIR(3)=0 : XDIR(4)=0 1050 XDIR(5)=4 : XDIR(6)=-4 : XDIR(7)=4 : XDIR(8)=-4 1060 YDIR(1)=0 : YDIR(2)=0 : YDIR(3)=3 : YDIR(4)=-3 1070 YDIR(5)=3 : YDIR(6)=-3 : YDIR(7)=-3 : YDIR(8)=3 1080 RETURN 1090 REM END OF INITIALIZING THE DIRECTIONS 1100 REM ------------------------------------------- 1110 REM PRINT THE BLANK BOARD TEMPLATE 1120 PRINT CHR$(&H1A); 1130 FOR I% = 1 TO 8 1140 FOR J% = 1 TO 2 1150 FOR K% = 1 TO 7 1160 PRINT CHR$(&HC); 1170 PRINT CHR$(&HC); 1180 PRINT CHR$(&HC); 1190 PRINT CHR$(27)+"g"; 1200 PRINT CHR$(11); 1210 PRINT CHR$(27)+"G"; 1220 NEXT K% 1230 PRINT 1240 NEXT J% 1250 IF(I%=8)THEN GOTO 1360 1260 FOR K% = 1 TO 7 1270 PRINT CHR$(27)+"g"; 1271 REM *** NOTE *** LINES 1280,1290,1300 AND 1320 HAVE BEEN MODIFIED TO 1272 REM CAUSE THE GRAPHICS OUTPUT TO APPEAR CORRECTLY ON THE OSBORNE 1273 REM EXECUTIVE I. THE PROBLEM EXISTS AS OF 18 DEC 83, AND IS DESCRIBED 1274 REM IN THE FILE `GRAFTEST.BAS', WHICH MAY BE LISTED/RUN FOR DETAILS. 1275 REM THE MODIFICATION IS AS FOLLOWS; ALL GRAPHICS PAIRS: 1276 REM CHR$(27)+CHR$(27) 1277 REM HAVE BEEN CHANGED TO: 1278 REM CHR$(27)+CHR$(155) 1279 REM .................... JIM SWITZ, FOG EXECUTIVE LIBRARIAN (18 DEC 83) 1280 PRINT CHR$(27)+CHR$(155); 1290 PRINT CHR$(27)+CHR$(155); 1300 PRINT CHR$(27)+CHR$(155); 1310 PRINT CHR$(12); 1320 IF(K%=7)THEN PRINT CHR$(27)+CHR$(155);:PRINT CHR$(27)+CHR$(155);:PRINT CHR$(27)+CHR$(155); 1330 PRINT CHR$(27)+"G"; 1340 NEXT K% 1350 PRINT 1360 NEXT I% 1370 RETURN 1380 REM END OF PRINTING THE BOARD TEMPLATE 1390 REM ------------------------------------------- 1400 REM PRINT THE INITIAL FOUR PIECES 1410 PIECE = -1 : X = 45 : Y = 42 1420 GOSUB 1800 'DRAW THE FIRST PIECE 1430 X = 49 : Y = 45 : GOSUB 1800 1440 PIECE = 1 : X = 49 : Y = 42 : GOSUB 1800 1450 X = 45 : Y = 45 : GOSUB 1800 1460 RETURN 1470 REM END OF PRINTING THE INITIAL FOUR PIECES 1480 REM ------------------------------------------- 1490 REM MOVE THE CURSOR 1500 X = 33 : Y = 33 : I = 1 : J = 1 1510 PRINT CHR$(27)+"="+CHR$(Y)+CHR$(X); 1520 IF(LEN(INKEY$)<>0) THEN GOTO 1520 1530 A$ = INKEY$ : IF(LEN(A$)=0)THEN GOTO 1530 1540 IF(A$=CHR$(13)) THEN GOTO 1770 1550 IF(A$="L") THEN GOSUB 5570 'LEGAL MOVE? 1560 IF(A$="L" AND EXM=0) THEN GOTO 1770 1570 IF(A$="L" AND EXM=1) THEN GOTO 1530 1580 XDEL = 0 : YDEL = 0 1590 IF(A$="4") THEN XDEL = -4 1600 IF(A$="6") THEN XDEL = 4 1610 IF(A$="8") THEN YDEL = -3 1620 IF(A$="2") THEN YDEL = 3 1630 IF(A$="3") THEN XDEL = 4 : YDEL = 3 1640 IF(A$="9") THEN XDEL = 4 : YDEL = -3 1650 IF(A$="7") THEN XDEL =-4 : YDEL = -3 1660 IF(A$="1") THEN XDEL =-4 : YDEL = 3 1670 IF(XDEL=0 AND YDEL=0) THEN GOTO 1530 1680 XNEW = X + XDEL : YNEW = Y + YDEL 1690 REM DON'T MOVE CURSOR OFF THE BOARD 1700 IF(XNEW<32 OR XNEW >62) THEN GOTO 1530 1710 IF(YNEW<32 OR YNEW >54) THEN GOTO 1530 1720 X = XNEW : Y = YNEW 1730 I = I + SGN(XDEL) : J = J + SGN(YDEL) 1740 PRINT 1750 PRINT CHR$(27)+"="+CHR$(Y)+CHR$(X); 1760 GOTO 1530 1770 RETURN 1780 REM END OF MOVING THE CURSOR 1790 REM ----------------------------------------- 1800 REM DRAW A PIECE 1810 REM (X,Y) IS THE POSITION; PIECE = 1, -1 1820 XOLD = X : YOLD = Y 1830 X = X - 1 : Y = Y - 1 1840 PRINT CHR$(&H1E); 1850 PRINT CHR$(27)+"="+CHR$(Y)+CHR$(X); 1860 IF(PIECE=-1)THEN GOTO 2020 1870 REM PIECE = 1 1880 PRINT" "; 1890 PRINT CHR$(27)+"g"; 1900 PRINT CHR$(24); 1910 PRINT CHR$(27)+"G"; 1920 PRINT" "; 1930 Y = Y + 1 1940 PRINT 1950 PRINT CHR$(27)+"="+CHR$(Y)+CHR$(X); 1960 PRINT" "; 1970 PRINT CHR$(27)+"g"; 1980 PRINT CHR$(23); 1990 PRINT CHR$(27)+"G"; 2000 PRINT" "; 2010 GOTO 2120 2020 REM PIECE = -1 2030 PRINT CHR$(27)+"g"; 2040 PRINT CHR$(22); : PRINT CHR$(23); 2050 PRINT CHR$(22); : PRINT CHR$(27)+"G"; 2060 Y = Y + 1 2070 PRINT 2080 PRINT CHR$(27)+"="+CHR$(Y)+CHR$(X); 2090 PRINT CHR$(27)+"g"; 2100 PRINT CHR$(22); : PRINT CHR$(24); 2110 PRINT CHR$(22); : PRINT CHR$(27)+"G"; 2120 REM 2130 X = XOLD : Y = YOLD 2140 RETURN 2150 REM END OF DRAWING THE PIECE 2160 REM ------------------------------------------ 2170 REM CHECK IF MOVE I,J IS LEGAL 2180 REM LEGAL = 0 IF ILLEGAL, 1 IF LEGAL 2190 REM CHNG CONTAINS THE # OF CHANGES IN DIR I 2200 REM SCHNG IS THE TOTAL NUMBER OF CHANGES 2210 REM SCHNG DOES NOT COUNT THE MOVE ITSELF 2220 SCHNG = 0 2230 LEGAL = 0 2240 IF(I=0 OR I=9) THEN STOP 2250 IF(J=0 OR J=9) THEN STOP 2260 IF(B(I,J)<>0) THEN GOTO 2430 2270 REM CHECK THE EIGHT DIRECTIONS 2280 FOR IND = 1 TO 8 'IND IS THE CURRENT DIRECTION 2290 CHNG(IND) = 0 2300 IDEL = IDIR(IND) : JDEL = JDIR(IND) 2310 INEW = I + IDEL : JNEW = J + JDEL 2320 IF(PLYR<> -1* B(INEW,JNEW))THEN GOTO 2390 2330 FOR JND1 = 1 TO 8 2340 INEW = INEW + IDEL : JNEW = JNEW + JDEL 2350 CHNG(IND) = CHNG(IND) + 1 2360 IF(B(INEW,JNEW)=0)THEN CHNG(IND)=0:GOTO 2390 2370 IF(B(INEW,JNEW)=PLYR)THEN GOTO 2390 2380 NEXT JND1 2390 REM DONE CURRENT DIRECTION 2400 SCHNG = SCHNG + CHNG(IND) 2410 NEXT IND 2420 IF(SCHNG > 0) THEN LEGAL = 1 2430 RETURN 2440 REM END OF LEGAL MOVE SUBROUTINE 2450 REM ----------------------------------------- 2460 REM PRINT NOT LEGAL MOVE MESSAGE 2470 XPOS = 64 : YPOS = 50 : GOSUB 4040 2480 PRINT"SORRY, THAT IS NOT"; 2490 YPOS = YPOS + 1 : GOSUB 4040 2500 PRINT" A LEGAL MOVE"; 2510 FOR TIME = 1 TO 400 : DUM = 4.3*8.7 : NEXT TIME 2520 YPOS = YPOS - 1 : GOSUB 4040 2530 PRINT" "; 2540 YPOS = YPOS + 1 : GOSUB 4040 2550 PRINT" "; 2560 RETURN 2570 REM END OF PRINTING NOT LEGAL MESSAGE 2580 REM ------------------------------------------ 2590 REM PERFORM THE MOVE (FLIP PIECES) 2600 PIECE = PLYR 2610 B(I,J) = PLYR 2620 JSUB = PLYR + 1 2630 IF(SEARCH=0) THEN TOT(JSUB) = TOT(JSUB) + 1 2640 IF(JSUB=2) THEN KSUB=0 ELSE KSUB=2 2650 IF(SEARCH=0) THEN GOSUB 1800 'DRAW THE PIECE 2660 IF(SEARCH=1) THEN GOTO 2690 2670 FOR TIME = 1 TO 100 : DUM=2.3*8.9 : NEXT TIME 2680 IF(SEARCH=0) THEN GOSUB 1800 'DRAW THE PIECE AGAIN 2690 REM NOW FLIP THE REMAINING PIECES 2700 FOR IND = 1 TO 8 2710 IF(CHNG(IND)=0) THEN GOTO 2860 2720 IDEL = IDIR(IND) : JDEL = JDIR(IND) 2730 XDEL = XDIR(IND) : YDEL = YDIR(IND) 2740 ISAVE = I : JSAVE = J 2750 XSAVE = X : YSAVE = Y 2760 FOR JND = 1 TO CHNG(IND) 2770 I = I + IDEL : J = J + JDEL 2780 X = X + XDEL : Y = Y + YDEL 2790 IF(SEARCH=0)THEN GOSUB 1800 'DRAW THE PIECE 2800 B(I,J) = PLYR 2810  IF(SEARCH=0)THEN TOT(JSUB) = TOT(JSUB) + 1 2820 IF(SEARCH=0)THEN TOT(KSUB) = TOT(KSUB) - 1 2830 NEXT JND 2840 X = XSAVE : Y = YSAVE 2850 I = ISAVE : J = JSAVE 2860 NEXT IND 2870 RETURN 2880 REM END OF PERFORM THE MOVE 2890 REM ------------------------------------------ 2900 REM PRINT PLAYER'S TOTAL AND WHOSE TURN IT IS 2910 XPOS = 74 : YPOS = 35 : GOSUB 4040 2920 PRINT"TOTAL" 2930 YPOS = YPOS + 1 : GOSUB 4040 2940 PRINT"PIECES" 2950 PIECE = 1 2960 XPOS = 65 : YPOS = 38 : GOSUB 4040 2970 PRINT" PLAYER "; TOT(2); 2980 YPOS = YPOS + 1 : GOSUB 4040 2990 PRINT" "; 3000 X = 68 : Y = 41 3010 GOSUB 1800 3020 IF(PLYR=1 AND PLYR<>OZ) THEN PRINT"<- YOUR MOVE"; 3030 IF(PLYR=1 AND PLYR=OZ) THEN PRINT"<- MY MOVE"; 3040 IF(PLYR<>1) THEN PRINT" "; 3050 XPOS = 65 : YPOS = 44 : GOSUB 4040 3060 PRINT" PLAYER "; TOT(0); 3070 YPOS = YPOS + 1 : GOSUB 4040 3080 PRINT" "; 3090 X = 68 : Y = 47 3100 PIECE = -1 3110 GOSUB 1800 3120 IF(PLYR=-1 AND PLYR<>OZ) THEN PRINT"<- YOUR MOVE"; 3130 IF(PLYR=-1 AND PLYR=OZ) THEN PRINT"<- MY MOVE"; 3140 IF(PLYR<>-1) THEN PRINT" "; 3150 PRINT 3160 RETURN 3170 REM END OF PRINTING PLAYER'S TOTALS 3180 REM ----------------------------------------- 3190 REM CHECK IF PLAYER HAS ANY LEGAL MOVE 3200 REM EXM = 1 IF THERE EXISTS A LEGAL MOVE 3210 REM EXM = 0 IF PLAYER HAS NO LEGAL MOVES 3220 EXM = 0 3230 FOR I = 1 TO 8 3240 FOR J = 1 TO 8 3250 GOSUB 2170 3260 IF(LEGAL=1) THEN GOTO 3290 3270 NEXT J 3280 NEXT I 3290 IF(LEGAL=1) THEN EXM = 1 3300 RETURN 3310 REM END OF CHECKING IF PLAYER HAS LEGAL MOVE 3320 REM ----------------------------------------- 3330 REM PRINT NO LEGAL MOVE MESSAGE 3340 IF(PLYR=1) THEN XPOS=66 : YPOS = 39 3350 IF(PLYR=-1)THEN XPOS=66 : YPOS = 45 3360 GOSUB 4040 3370 PRINT"NO LEGAL MOVE"; 3380 FOR TIME = 1 TO 450 : DUM=2.3*3.4 : NEXT TIME 3390 RETURN 3400 REM END OF NO LEGAL MOVE MESSAGE 3410 REM ----------------------------------------- 3420 REM LOAD THE BOARD RATINGS 3430 FOR I = 1 TO 8 3440 FOR J = 1 TO 8 3450 BR(I,J) = 0 3460 GOSUB 3660 'COMPUTE NRM=NORM(I,J) 3470 IF(NRM=2) THEN BR(I,J) = -2 3480 IF(NRM=3) THEN BR(I,J) = 3 3490 NEXT J 3500 NEXT I 3510 BR(1,2)=2 : BR(2,1)=2 : BR(1,7)=2 : BR(7,1)=2 3520 BR(2,8)=2 : BR(8,2)=2 : BR(7,8)=2 : BR(8,7)=2 3530 BR(2,2) = -4 : BR(2,7) = -4 3540 BR(7,2) = -4 : BR(7,7) = -4 3550 BR(1,1) = 6 : BR(1,8) = 6 3560 BR(8,1) = 6 : BR(8,8) = 6 3570 BR(3,3)=1 : BR(3,6)=1 : BR(6,3)=1 : BR(6,6)=1 3580 FOR I = 1 TO 8 3590 FOR J = 1 TO 8 3600 BRM(I,J) = BR(I,J) 3610 NEXT J 3620 NEXT I 3630 RETURN 3640 REM END OF LOAD BR SUBROUTINE 3650 REM ----------------------------------------- 3660 REM COMPUTE NORM(I,J), THE DISTANCE FROM CENTER 3670 REM STORE THE NORM IN NRM 3680 IF(I>4) THEN INRM = I - 5 3690 IF(I<=4) THEN INRM = 4 - I 3700 IF(J>4) THEN JNRM = J - 5 3710 IF(J<=4) THEN JNRM = 4 - J 3720 IF(INRM>JNRM)THEN NRM=INRM ELSE NRM=JNRM 3730 RETURN 3740 REM END OF COMPUTE NORM(I,J) ROUTINE 3750 REM ----------------------------------------- 3760 REM DETERMINE OZ'S MOVE 3770 IBEST = 0 : JBEST = 0 3780 RBEST! = -30000 3790 IF(SEARCH=0) THEN XPOS = 66 : YPOS = 50 : GOSUB 4040 3800 IF(SEARCH=0) THEN PRINT"I'M THINKING"; 3810 IF(SEARCH=0) THEN YPOS = YPOS + 1 : GOSUB 4040 3820 FOR I = 1 TO 8 3830 IF(SEARCH=0) THEN PRINT"X"; 3840 FOR J = 1 TO 8 3850 GOSUB 2170 'CHECK IF MOVE IS LEGAL 3860 IF(LEGAL=0) THEN GOTO 3900 3870 IF(MOVENUM>STRTEND) THEN FAC!=0 ELSE FAC!=1 3880 RATING! = SCHNG + BRM(I,J)*FAC! 3890 IF(RATING!>RBEST!)THEN IBEST=I:JBEST=J:RBEST!=RATING! 3900 NEXT J 3910 NEXT I 3920 I = IBEST : J = JBEST 3930 IF(SEARCH=1) THEN GOTO 4010 3940 REM ERASE I'M THINKING MESSAGE 3950 X = 29 + 4*I : Y = 30 + 3*J 3960 YPOS = YPOS - 1 : GOSUB 4040 3970 PRINT" "; 3980 YPOS = YPOS + 1 : GOSUB 4040 3990 PRINT" "; 4000 IF(IBEST=0 OR JBEST=0) THEN EXM=0 4010 RETURN 4020 REM END OF DETERMINE OZ'S MOVE 4030 REM ----------------------------------------- 4040 REM REPOSITION CURSOR AT (XPOS,YPOS) 4050 PRINT 4060 PRINT CHR$(27)+"="+CHR$(YPOS)+CHR$(XPOS); 4070 RETURN 4080 REM END OF REPOSITIONING THE CURSOR 4090 REM ----------------------------------------- 4100 REM PRINT INTRO MESSAGES AND SET OZ 4110 REM OZ <> 0 IF OZZIE PLAYS 4120 REM OZ = 0 IF OZZIE DOES NOT PLAY 4130 PRINT CHR$(&H1A); 4140 XPOS = 42 : YPOS = 33 : GOSUB 4040 4150 PRINT"OSBORNE OTHELLO" 4160 PRINT" by Mark Broadie"; 4170 XPOS = 32 : YPOS = 36: GOSUB 4040 4180 PRINT" CURSOR MOVEMENT IS CONTROLLED" 4190 PRINT" BY THE NUMBER KEYS:" 4200 PRINT 4210 PRINT" 8" 4220 PRINT" 7 ^ 9" 4230 PRINT" \|/ " 4240 PRINT" 4<--- --->6" 4250 PRINT" /|\ " 4260 PRINT" 1 | 3 " 4270 PRINT"  2" 4280 PRINT 4290 PRINT" MOVE THE CURSOR WITH NUMBER KEYS" 4300 PRINT" AND THEN HIT RETURN TO ENTER MOVE." 4310 PRINT" IF YOU THINK THAT YOU DO NOT HAVE" 4320 PRINT" A LEGAL MOVE HIT 'L'. " 4330 PRINT" NOTE: ALPHA LOCK SHOULD BE ON." 4340 PRINT 4350 IF(LEN(INKEY$)<>0) THEN GOTO 4350 4360 PRINT" DO YOU WANT OZZIE TO PLAY (Y OR N)? "; 4370 A$ = INKEY$ : IF(LEN(A$)=0) THEN GOTO 4370 4380 IF(A$<>"Y" AND A$<>"N") THEN GOTO 4370 4390 PRINT A$ 4400 IF(A$="N") THEN OZ = 0 : GOTO 4490 4410 REM A$ = "Y" 4420 PRINT 4430 IF(LEN(INKEY$)<>0) THEN GOTO 4430 4440 PRINT" DO YOU WANT TO GO FIRST (Y OR N)? "; 4450 A$ = INKEY$ : IF(LEN(A$)=0) THEN GOTO 4450 4460 IF(A$<>"Y" AND A$<>"N") THEN GOTO 4450 4470 PRINT A$ 4480 IF(A$="N") THEN OZ = 1 ELSE OZ = -1 4490 RETURN 4500 END OF PRINT INSTRUCTIONS 4510 REM ----------------------------------------- 4520 REM MODIFY BRM 4530 IF(PLYR=OZ OR OZ=0) THEN GOTO 4740 4540 GOSUB 3660 'COMPUTE NRM = NORM(I,J) 4550 IF(NRM<2) THEN GOTO 4740 4560 REM NRM = 3 4570 IF(I=1 AND J=1) THEN BRM(2,2)=0 : GOTO 4740 4580 IF(I=1 AND J=8) THEN BRM(2,7)=0 : GOTO 4740 4590 IF(I=8 AND J=1) THEN BRM(7,2)=0 : GOTO 4740 4600 IF(I=8 AND J=8) THEN BRM(7,7)=0 : GOTO 4740 4610 IF(J=1 OR J=8) THEN GOTO 4680 4620 IF(B(I,J+1)<>0 OR B(I,J+2)<>0)THEN GOTO 4740 4630 IF(B(I,J-1)<>0 OR B(I,J-2)<>0)THEN GOTO 4740 4640 BRM(I,J+1)=-3 : BRM(I,J-1)=-3 4650 IF(J=2) THEN BRM(I,1)=6 4660 IF(J=7) THEN BRM(I,8)=6 4670 GOTO 4740 4680 REM 4690 IF(B(I+1,J)<>0 OR B(I+2,J)<>0)THEN GOTO 4740 4700 IF(B(I-1,J)<>0 OR B(I-2,J)<>0)THEN GOTO 4740 4710 BRM(I+1,J)=-3 : BRM(I-1,J)=-3 4720 IF(I=2) THEN BRM(1,J)=6 4730 IF(I=7) THEN BRM(8,J)=6 4740 REM RETURN POINT 4750 RETURN 4760 REM END OF MODIFYING BRM 4770 REM ----------------------------------------- 4780 REM DETERMINE OZ'S MOVE IN THE ENDGAME 4790 REM DETERMINE BEST M MOVES 4800 SEARCH = 1 4810 XPOS = 66 : YPOS = 50 : GOSUB 4040 4820 PRINT"I'M THINKING"; 4830 YPOS = YPOS + 1 : GOSUB 4040 4840 FOR IND = 1 TO M 4850 IB(IND)=0 : JB(IND)=0 : RB(IND)=-30000 4860 NEXT IND 4870 FOR I = 1 TO 8 4880 IF(I=4)THEN PRINT"X"; 4890 IF(I=8)THEN PRINT"X"; 4900 FOR J = 1 TO 8 4910 GOSUB 2170 'IS MOVE LEGAL 4920 IF(LEGAL=0) THEN GOTO 5050 4930 FOR K = 1 TO M 4940 IF(SCHNG < RB(K)) THEN GOTO 5040 4950 IT=IB(K):JT=JB(K):RT=RB(K) 4960 IB(K)=I:JB(K)=J:RB(K)=SCHNG 4970 IF(K=M) THEN GOTO 5050 4980 FOR L = K+1 TO M 4990 TMP=IB(L):IB(L)=IT:IT=TMP 5000 TMP=JB(L):JB(L)=JT:JT=TMP 5010 TMP=RB(L):RB(L)=RT:RT=TMP 5020 NEXT L 5030 K = M 5040 NEXT K 5050 NEXT J 5060 NEXT I 5070 REM COPY B INTO BSAVE, PLYR INTO PSAVE 5080 GOSUB 5390 : PSAVE = PLYR 5090 FOR IIND = 1 TO M 5100 IF(IB(IIND)=0) THEN GOTO 5210 5110 I = IB(IIND) : J = JB(IIND) 5120 GOSUB 2170 'LEGAL MOVE AND SET CHNG 5130 GOSUB 2590 'PERFORM MOVE ON B 5140 PLYR = PLYR*(-1) 5150 PRINT"XX"; 5160 GOSUB 3760 'DETERMINE BEST RESPONSE 5170 IF(I=0)THEN RB(IIND)=RB(IIND)+5000:ELSE RB(IIND)=RB(IIND)-RBEST! 5180 'THERE MAY BE NO LEGAL RESPONSE 5190 PLYR = PLYR*(-1) 5200 GOSUB 5480 'COPY BSAVE INTO B 5210 NEXT IIND 5220 REM DETERMINE BEST MOVE OF THE THREE 5230 TMP=-30000 5240 FOR IIND = 1 TO M 5250 IF(RB(IIND)>TMP)THEN INDB=IIND:TMP=RB(IIND) 5260 NEXT IIND 5270 SEARCH = 0 5280 PLYR = PSAVE : GOSUB 5480 5290 I = IB(INDB) : J = JB(INDB) 5300 X = 29 + 4*I : Y = 30 + 3*J 5310 REM ERASE I'M THINKING MESSAGE 5320 XPOS = 66 : YPOS = 50 : GOSUB 4040 5330 PRINT" "; 5340 YPOS = YPOS + 1 : GOSUB 4040 5350 PRINT" "; 5360 RETURN 5370 REM END OF DETERMINE OZ'S MOVE IN ENDGAME 5380 REM ----------------------------------------- 5390 REM COPY B INTO BSAVE 5400 FOR ROW = 0 TO 9 5410 FOR COL = 0 TO 9 5420 BSAVE(ROW,COL) = B(ROW,COL) 5430 NEXT COL 5440 NEXT ROW 5450 RETURN 5460 REM END OF COPY B INTO BSAVE 5470 REM ----------------------------------------- 5480 REM COPY BSAVE INTO B 5490 FOR ROW = 0 TO 9 5500 FOR COL = 0 TO 9 5510 B(ROW,COL) = BSAVE(ROW,COL) 5520 NEXT COL 5530 NEXT ROW 5540 RETURN 5550 REM END OF COPY BSAVE INTO B 5560 REM ----------------------------------------- 5570 REM CHECK IF PLAYER HAS LEGAL MOVE 5580 REM CALLED FROM MOVE CURSOR ROUTINE 5590 REM FIRST PRINT MESSAGE 5600 XPOS = 65 : YPOS = 50 : GOSUB 4040 5610 PRINT"CHECKING FOR A"; 5620 YPOS = YPOS + 1 : GOSUB 4040 5630 PRINT"LEGAL MOVE ..."; 5640 GOSUB 3190 5650 REM ERASE MESSAGE 5660 YPOS = 50 : GOSUB 4040 5670 PRINT" "; 5680 YPOS = 51 : GOSUB 4040 5690 PRINT" "; 5700 REM IF NO MOVE (EXM=0) THEN RETURN 5710 IF(EXM=0) THEN GOTO 5900 5720 REM IF THERE IS A MOVE (EXM=1) SET CURSOR 5730 REM AND PRINT MESSAGE 5740 YPOS = 50 : GOSUB 4040 5750 PRINT"THERE IS AT LEAST"; 5760 YPOS = 51 : GOSUB 4040 5770 PRINT"ONE LEGAL MOVE -"; 5780 YPOS = 52 : GOSUB 4040 5790 PRINT"SEE CURSOR"; 5800 X = 29 + 4*I : Y = 30 + 3*J : PRINT 5810 PRINT CHR$(27)+"="+CHR$(Y)+CHR$(X); 5820 FOR TIME = 1 TO 550 : DUM=4.3*2.2 : NEXT TIME 5830 YPOS = 50 : GOSUB 4040 5840 PRINT" "; 5850 YPOS = 51 : GOSUB 4040 5860 PRINT" "; 5870 YPOS = 52 : GOSUB 4040 5880 PRINT" "; : PRINT 5890 PRINT CHR$(27)+"="+CHR$(Y)+CHR$(X); 5900 RETURN 5910 REM END OF CHECK FOR LEGAL MOVE 5920 REM ----------------------------------------- )+"="+CHR$(Y)+CHR$(X); 5900 RETURN 5910 REM END OF CHECK FOR LEGAL MOVE 59 ERASE MESSAGE 5660 YPOS = 50 : GOSUB 4040 5670 PRINT" "; 5680 YPOS = 51 : GOSUB 4040 5690 PRINT" "; 5700 REM IF NO MOVE (EXM=0) THEN RETURN 5710 IF(EXM=0) THEN GOTO 5900 5720 REM IF THERE IS A MOVE (EXM=1) SET CURSOR 5730 REM AND PRINT MESSAGE 5740 YPOS = 50 : GOSUB 4040 5750 PRINT"THERE IS AT LEAST"; 5760 YPOS = 51 : GOSUB 4040 5770 PRINT"O Free disk space in CP/M 3.0 by Kenji Nakadegawa 2/15/84 While reading the february issue of the Foghorn I noticed a plea for help with the problem of determining free space on disk drives under CP/M 3.0. I just finished converting a version of XDIR.COM to run under both 2.2 and 3.0 so I'll tell you what I found out. Many "extended" directory programs use something called the allocation vector to determine the used and free space on a disk. The allocation vector is effectively a map of the used and free blocks on the disk. Reading through my CP/M 3.0 documentation I found that banked 3.0 systems ( any system with more than 64K ram e.g. OsExec1 ) often keep the allocation vector in bank 0 which cannot be accessed by transient programs. That is why you get strange answers for space remaining when using programs like XDIR and SWEEP. Fortunately there is a new BDOS function number 46 that returns free space on a specified drive. Here is an example of 8080 assembly code which shows a good way to get the free space of a drive under CP/M 3.0. I took this code straight from the source listing of SUPER DIRECTORY PROGRAM v7.2 10/16/83 by Bruce R. Ratoff. I hope he doesn't mind. Bear in mind that all symbolic labels in this example were set by equates or ds statements elsewhere in the program. For example in the CALL CPM statement, CPM is a subroutine which calls bdos (location 05h) after saving all registers and VERFLAG is a memory location specified by a ds statement at the end of the program. ; EXCERPT 1, ( This bdos call gets the version # for later conditional actions. ) ; MVI C,12 ;get and save the cp/m version # CALL BDOS MOV A,L STA VERFLG ;( The current cp/m version number is stored CPI 20H here. See your documentation. ) ; ; a carry flag set after the cpi 20h means you have cp/m 1.4 ; EXCERPT 2, ( The routine FREE20 gets the free space on the drive by the old method. ) ; FREE: LDA VERFLG ;check version # CPI 30H ;3.0? JC FREE20 ;use old method if not LDA FCB ;get drive # ( The drive number is stored as A-P = 1-16 in this program. CP/M wants the drive number as 0-15. ) DCR A MOV E,A ;use new compute free space bdos call MVI C,46 CALL CPM ( The number of free sectors is returned as a 3 byte binary number in the first three bytes of the current DMA buffer which is in this case the default buffer at 80h. The format is lsb in 80h, midsb in 81h, and msb in 82h. Since the number represents 128 byte sectors and we want it in 'K' we have to divide it by 8 which in binary is 3 shift rights. ) MVI C,3 ;answer is a 24-bit integer ; FRE3L1: LXI H,BASE+82H ;answer is in 1st 3 bytes of dma adr MVI B,3 ;convert it from sectors to k ORA A ;by dividing by 8 ; FRE3L2: MOV A,M RAR MOV M,A DCX H DCR B JNZ FRE3L2 ;loop for 3 bytes DCR C JNZ FRE3L1 ;shift 3 times LHLD BASE+80H ;now get result in k SHLD SAVFRE ;store it ( We now have the free space on the drive stored at location SAVFRE in binary or hex. You can use the hex word to 4 decimal digit output routine which I assume you already have somewhere else in the program to output this number to the console or whatever. ) END he number of free sectors is returned as a 3 byte binary number in the first three bytes of the current DMA buffer which is in this case the default buffer at 80h. The format is lsb in 80h, midsb in 81h, and msb in 82h. Since the number represents 128 byte sectors and we want it in 'K' we have to divide it by 8 which in binary is 3 shift rights. ) MVI C,3 ;answer is a 24-bit integer ; FRE3L1: LXI H,BASE+82H ;answer is in 1st 3 bytes of dma adr MVI B,3 ;convert it from sectors to k ORA A ;by dividing by 8 ; FRE3L2: MOV A,M RAR MOV M,A DCX H DCR B JNZ FRE3L2 ;loop for 3 bytes DCR C JNZ FRE3L1 ;shift 3 times LHLD BASE+80H ;now get result in k SHLD SAVFRE ;store it ( We now have the free space on the drive s1 UKEYBD 2.0 (06/86) - Osborne Executive !I -<2:l !m~ 6?#!e~ ̽!u~ ̽!l UReading...:]? \T@;@;A;\d:\CC!@!  @@I!\ # 8:]?(:?U Edit keyboard? (Y/N): MasN! H@I!H@!H @I!@6 IUf= 6KEYBD Keyboard Definition Utility=!;v2.0 (c)1986 E.Meyer="6---------------------------------U=# Y=&,Keyboard to edit: (1) Normal (2) Shift (3) Control='?(4) Caps-lock (5) Control-shift=*4Select (1-5), or RET to save to :? URAM,: :@O>:O!~ (͐>.O͐U: Mu 188>O! @@( ! DM= "`i U=# Y=%=????????? Keyboard: !U HU !> OHU=.6Key: )(^RET exits)(=.;Mj!@(>O7R*"U=.@Value: )(chr,RET or H,H)(=.GM20sM2 (s!$*w:>O!H @I6  IUeU Saving...:?ʦ wd@e@eAeòd:CC!D! @ D@!":!Dò! @ @IU 6K#6B#6DU)~#U(!884($(((( (2 (> (2(>?>v >^><>>OU UES USP UTB UCR !@7R*~0s4> O22> 8>2>/!"> %!"> "> >2> > >2>22Uò=v͔́͊ͥͮ͞:=v~(A8_00_>OÓ#_A0:OO>_㯆#OUa{_A[  0 >^O@O> Oɯ~#O '[12345678qwertyuiasdfghjkzxcvbnm,0 .po9-/;\l=abcdefghijklmnopqrstuvwxyz0123456789[/\-=';,.  Normal Shift ControlCaps-lockCtl-ShiftUòUòUòUò>> KEYBD.DOC --------- Instructions for KEYBD v2.0 (c) E.Meyer 6/86 KEYBD is a utility for the Osborne Executive computer, which allows you to redefine the entire keyboard. This powerful feature of the Exec is not supported by any of the standard software; but together with the ability to redefine characters on the video display (using the Osborne CHARGEN utility), it makes the Exec extraordinarily versatile in coping with foreign languages and odd programming languages, as well as varying personal tastes. (You can create a European or Dvorak layout; or just "customize" little features for favorite programs, like using SHIFTED arrow keys for BIG moves in WordStar.) Any key on the Exec keyboard can be redefined to produce any ASCII code from 00-7F hex (actually 00-FF, but there are restrictions). KEYBD lets you create your own definitions, stores them on disk, and loads them into RAM. KEYBD is only 2k in size; its KBD disk files are 1k each. Basically, KEYBD takes two arguments: a source and a destination. If the source is a disk and the destination is RAM, it will simply load the keyboard map into memory. Otherwise, you will have the opportunity to edit (modify) the keyboard before the transfer is made. SYNTAX: A>KEYBD source [dest] ("[]" = optional) "source" may be: (1) a drive alone, such as "A:", for system tracks (keyboard loaded automatically on cold boots) (2) a disk file, "D:FILENAME", created with KEYBD (the file TYP will default to ".KBD") (3) an asterisk "*", to indicate RAM Similarly for "dest", although if it is "*" you may omit it. (NOTE: Omitting "dest" is recommended only at the CCP A> prompt. When running KEYBD from within other software, this may not work properly, so you should specify "*". WordStar's "R" command, for example, does not always initialize the FCBs if they are left blank.) EXAMPLES LOADING INTO MEMORY: A>keybd a: [*] Takes the keyboard from the A: system tracks, and installs it in RAM. A>keybd dvorak [*] Takes the keyboard from file A:DVORAK.KBD and loads it into RAM. keybd b:eurostd * From WordStar's "R" command, takes keyboard from B:EUROSTD.KBD, loads it into RAM. (Note the "*".) MODIFYING: A>keybd * [*] Edits keyboard in RAM then stores it back. A>keybd my my Edits keyboard A:MY.KBD and stores it back. MOVING AROUND: A>keybd my b: Writes keyboard from A:MY.KBD to B: system tracks. Asks first whether you want to edit. A>keybd a: b: Writes keyboard from A: system tracks to B: system tracks. Asks whether you want to edit. EDITING THE KEYBOARD When you are not just loading a keyboard from disk into RAM, KEYBD asks you whether you want to edit it before saving to the destination. (If the source and dest are the same, it will go directly into editing.) If you answer "Y" (for Yes), you will go into edit mode. You will be asked WHICH keyboard you want to edit. The five keyboards are: normal, shift, control, caps-lock, control-shift. That is, each of the 53 different keys (the numeric keypad keys are NOT distinct) on the keyboard can produce up to five different codes, depending on whether the SHIFT is depressed, etc. The keyboard you choose will then display on the screen in two rows, one for the alphabet and one for the other 27 keys. The NAMES of the keys ("a", "1", etc) will display in dim video. Note the 8 abbreviated names at the end of the list: SPace, EScape, TaB, CarriageReturn, and the four arrow keys represented by " ^ > v < ". The VALUES of these keys, the ASCII codes they will produce, are displayed below each name. If the value is a printable character, it will display as such; if it is a control code (below 20 hex) it will display with a caret, such as "^G"; otherwise, it will show as two hex digits (eg "8B"). Values 00-7F hex are standard ASCII codes. The codes 80-FF hex can also be used; several of these have special meaning for the Exec BIOS: 80-89 are the Function Keys 0-9 (normally produced by ctl-0..9) 8A-8D are the Arrow keys (up, right, down, left) FE toggles the alternate character set (normally ctl-TAB) FF means the key is undefined When editing, the prompts will guide you first to press the KEY you wish to redefine (keep SHIFT, CTL, and CAPS LOCK off), then to enter its new VALUE: either by typing that character, then pressing RETURN, or by entering two hex digits. The new value should then display. Typing control-RET at the "Key" prompt will get you back to the first menu, from which you can edit another keyboard, or save and exit. If you don't wish to continue, and don't want to save anything, typing ^C (control-C) will ABORT the program at this point. TECHNICAL NOTES You want to be careful with KEYBD: don't try to load something into RAM if you're not sure it's a valid keyboard. All your keys will wind up producing random garbage; there is no remedy aside from the RESET button. Things can get confusing if you are trying to run KEYBD after already having redefined your keyboard. Note that KEYBD installs its own default Normal keyboard (1) while editing, which guarantees that you can type the original key NAMEs for assigning keys. However, if you use CTL-, SHIFT, or CAPS LOCK, you are using the currently defined keyboard, which may be quite different in layout. If you want to assign a VALUE that is not currently available on a key, you can use the hex entry mode. ERROR MESSAGES One of the command line arguments is missing or invalid. The source file specified doesn't exist. An error occurred while reading/writing a disk file. An error occurred while reading/writing system tracks. You typed ^C. HISTORY Version 2.0 of KEYBD adds the ability to use RAM as a source, deletes the dangerous "blank" source feature, and makes cosmetic improvements. The other features, and the ".KBD" file format, remain as in version 1.0. ----- Eric Meyer, 427 N. Washington, Bloomington IN 47401 ----- d the ".KBD" fiyou can type the original key NAMEs for assigning keys. However, if you use CTL-, SHIFT, or CAPS LOCK, you are using the currently defined keyboard, which may be quite different in layout. If you want to assign a VALUE that is not currently available on a key, you can use the hex entry mode. ERROR MESSAGES One of the comm1FNKEYS 2.1 (06/86) - Osborne Executive !H -2:l !m~ 6?#!e~ ̓!u~ ̓!l Reading...:]? \<,@ͻ!\ѷO:\!@!U!MAH;xa!\ # 4:]?(:? Edit keys? (Y/N): N!D6 H6 HfFNKEYS Function/Arrow Key Utility v2.1 (c)1986 E.Meyer ---------------------------------  Select <0-L>, ESC to clear, or RET to save to :? RAM-: :<@>:!~ (>.: sʟ 2ͬڗ2 T)(^ESC quits, ^RET saves, <- corrects)( ͂>MA !   !D6  H6 Heͼ> Saving...:?x I 8>2>/!"> %!"> "> >2> > >2>22=͑ͥͯ͜͹:͑=="RY!MA>͜2, F#q --------(;`iU bytes free)--------- )(!H()(-( w#>8+~ >!Hw7T!MA:(N #= ~(^6#DM!MCBDM;:H(+8O(#yw#O!LCT]BBDMN#!H!MA>y^OxG#= | }d8 d8 d>0 8 >006F#6N#6K0::_!~0 ?0! (# 7yURDL 0@)>^(>_㯆#~#a{_ Ä Ä Ä Ä Ä ͼÄ>> 8>2>/!"> %!"> "> >2> > >2>22=͑ͥͯ͜͹ FNKEYS.DOC ---------- Instructions for FNKEYS v2.1 (c) E.Meyer 6/86 FNKEYS is a utility for the Osborne Executive computer, designed to make it easier to change function and arrow key definitions. The Osborne SETUP utility allows you to do this, but configurations have to be saved to the system tracks of a disk, and you need to reset and reboot to change them in memory! FNKEYS allows you to quickly change key definitions, and to save them to small (1k) disk files. You can keep several of these on a disk, and load one quickly into RAM whenever needed. Basically, FNKEYS takes two arguments: a source and a destination. If the source is a disk and the destination is RAM, it will simply load the key definitions into memory. Otherwise, you will have the opportunity to edit (modify) the definitions before the transfer is made. SYNTAX: A>FNKEYS source [dest] ("[]" = optional) "source" may be: (1) a drive alone, such as "A:", for system tracks (that is, where SETUP puts the key definitions-- FNKEYS will only accept A: or B: here) (2) a disk file, "D:FILENAME", created with FNKEYS (the file TYP will default to ".FNK") (3) an asterisk "*", to indicate RAM Similarly for "dest", although if it is "*" you may omit it. (NOTE: Omitting "dest" is recommended only at the CCP A> prompt. When running FNKEYS from within other software, this may not work properly, so you should specify "*". WordStar's "R" command, for example, does not always initialize the FCBs if they are left blank.) EXAMPLES LOADING INTO MEMORY: A>fnkeys a: [*] Takes the function/arrow key definitions from the A: system tracks, and installs them in RAM. A>fnkeys cpm [*] Takes the definitions from file A:CPM.FNK and loads them into RAM. fnkeys b:ws * From WordStar's "R" command, takes definitions from B:WS.FNK, loads them into RAM. (Note the "*".) MODIFYING: A>fnkeys * [*] Edits definitions in RAM then stores them back. A>fnkeys my my Edits definitions in A:MY.FNK then stores them back. MOVING AROUND: A>fnkeys my b: Takes definitions from file A:MY.FNK, writes them to B: system tracks. Asks if you want to edit first. A>fnkeys a: b: Takes definitions from A: system tracks, writes them onto B: system tracks. Asks if you want to edit. EDITING KEY DEFINITIONS When you are not just loading definitions from disk into RAM, FNKEYS asks you whether you want to edit them before saving to the destination. (If the source and dest are the same, it will go directly into editing without even asking.) On entering Edit mode, you will see the definitions: <0>dir a:^M <1>dir b:^M ... ^J ^H The numbers 0-9 denote the ten function keys; the arrow keys are denoted U,R,D,L for Up, Right, Down, Left. Any control codes will display as shown above ("^M" for control-M, or RET; etc). You will be told how many bytes are still free for key definitions. To change a definition, select either "0"-"9" or "U"-"L", and then enter the new string. Any control codes typed (including backspace and RET) will be entered into the key definition. A string can be up to 255 characters in length (it can wrap around onto the next line). You can correct errors with the Left Arrow key. Type control-ESC to quit without changing the definition. When finished, type control-RET; if the new string doesn't exceed the bytes available, it will be saved. At the prompt, you can also type ESC to clear all function keys at once; or RET, to save the definitions. If you want to quit without saving you can type ^C; nothing will have been affected. Function keys do not operate while in FNKEYS. COMPATIBILITY WITH SETUP FNKEYS is completely compatible with the Osborne SETUP program, with the following exception. SETUP allows only a total of 242 bytes of key definitions. FNKEYS will allow twice as much (498 bytes). As long as you see more than "256 bytes free" in FNKEYS, you are staying within the limits of SETUP. If you go beyond this point, you may find that configurations created with FNKEYS cannot subsequently be edited correctly with SETUP. I don't know why SETUP limits function keys to a 256 byte block, when there appear to be 512 bytes available. Possibly Osborne was thinking of implementing two independent sets of keys. But I have experienced no difficulty in using all 512 bytes (aside from problems with SETUP.COM). INVALID DATA If you load a file that wasn't created with FNKEYS, or try to read the system tracks of a disk that has no valid key definitions, you will most likely get a DATA ERROR; there is still a small chance that random garbage could be read in and accepted, so be careful. ERROR MESSAGES One of the command line arguments is missing or invalid. The source file specified doesn't exist. An error occurred while reading/writing a disk file. An error occurred while reading/writing system tracks. The source doesn't look like valid key definitions. You typed ^C. HISTORY Version 2.0 of FNKEYS (6/86) added the ability to display and edit the function keys, if desired. Otherwise it maintained the same features, and the same ".FNK" file format, as the previous version 1.1. Version 2.1 has several small fixes, including ability to backspace, an improved display, and data checking.  ------ Eric Meyer, 427 N. Washington, Bloomington IN 47401 ------ ackspace, an improved display, and data checking. there is still a small chance that random garbage could be read in and accepted, so be careful. ERROR MESSAGES One of the command line arguments is missing or invalid. The source file specified doesn't exist. An error occurred while reading/writing a disk file. An error occurred while reading/writing system tracks. The source doesn't look like valid key definitions. You typed ^C. HISTORY Version 2.0 of FNKEYS (6/86) added the ability to display and edit the function keys, if desired. Otherwise it maintained the same features, and the same ".FNK" file format, as the previous version 1.1. Version 2.1 has several small fixes, including ability to backspace, an improved display, and data checking. !``1o-2`!U!UQ:`>2 ` UQ! 0-(_|``> ``$(&G 8&``> ``> ``_0`` ( >^``@N`><``>C``>R``>>>2 ASSIGNED KEYS ARE; $ZEROMAKRCOMm !"#$ZEROMAKRDOC %&ZEROMAKRBAS'(NULL COM)NULL ASM!*+,-.OTHELLO BAS/0123456789:;<=>OTHELLO BAS%?@ABCFREE30 DOCDEFGKEYBD COMHIKEYBD DOC5JKLMNOPFNKEYS COMQRFNKEYS DOC1STUVWXYKEYS $$$KEYS.CO͠ print th SETUP.CO assigne key t th scree an t printer fo th Osborn Executive Thi fil i ver shor a i doe no hav man operation t do th hardes i ban switc t ban wher th assignmen key ar stored Th firs addres o th key start a 2155 continuin unti th ke dat i finished. I th Executiv guid volum 'Masterin th Osborn Executive'i state th maximu characterpossibl ar 24 thi mean th las addres POSSIBL o an ke assignmen i a 2247H, th progra move th whol are (2K THIS VERSION), using an LDIR t ban startin a 5155H fo processin an printing A exampl ke assignmen sequenc fro ban i shown in the hex dump below; 2150 FF OD FF FF FF(OC)57 53 0D 20 0A 48 30 20 4E 20 ......WS. .H0 N 2160 42 3A(0C)57 53 0D 20 0A 48 30 20 44 20 42 3A(08) B:.WS. .H0 D B:. 2170 11 43 20 0F 52 37 36 0D(0C)45 52 41 20 42 3A 2A .C .R76..ERA B:* 2180 2E 42 41 4B 0D(0A)0B 56 20 0B 48 20 11 56 20 19 .BAK...V .H .V . 2190 (09)4C 49 42 20 54 4C 3D 42 3A(05)2E 4D 41 43 0D .LIB TL=B:..MAC. 21A0 (05)58 44 49 52 0D(08)58 44 49 52 20 42 3A 0D(04) .XDIR..XDIR B:.. 21B0 11 44 0D 19<01>05<01>04<01>18<01>13 00 00 00 00 .D.............. 21C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ Thos he character i roun bracket ( abov sho th begining o eac string givin tota characte coun i he fo eac string Afte th 1 assignment󠴠othe assignmentar show whic th Executiv use fo othe reasons (unknow b m anyway) marke i shar bracket <> Notic tha th en o ke assignmenstrinusea0D contro characte an no fulCR/L sequence thi mus b adde b th Executiv whe operatin th assignment --------------------------------------------------------------------------- Furthe note o th sourc cod ar i KEYS.MAC not tha an specia printe switche ca b include i th cod bu i woul hav t b re- assemble b you Becaus o th LDI loade a th beginin o th file afte assembly th key routin wil hav t b move bac dow t 010E froit6000/60B?H addressUs SID.CO t d i loading the file as; A>SID B:KEYS.COM and with the 'M'=move switch; #M6000 60BFH 010E an sav th (read t b sprung fil ont dis agai wit th 'W'=writ switch in SID.COM; #WB:KEYS.COM 0100 01FFH --------------------------------------------------------------------------- To run the program from A or B disk follow this example; A>KEYS The whole 10 keys will be printed like this; ASSIGNED KEYS ARE; 0 WS ^JH0 N B: 1 WS ^JH0 D B: 2 ^QC ^OR76 3 ERA B:*.BAK 4 ^KV ^KH ^QV ^Y 5 LIB TL=B: 6 .MAC 7 XDIR 8 XDIR B: 9 ^QD^Y To the the printer also if plugged in. Programed by; D.AMOS. 68a FINDLAY AVENUE. ROSEVILLE, N.S.W. AUSTRALIA. 2069. A member of a software development group for better assembly files. y th key routin wil hav t b move bac dow t 010E froit6000/60B?H addressUs SID.CO t d i loading the file as; A>SID B:KEYS.COM and with the 'M'=move switch; #M6000 60BFH 010E an sav th (read t b sprung fil ont dis agai wit th 'W'=writ switch in SID.COM; #WB:KEYS.COM 0100 01FFH --------------------------------------------------------------------------- To run the program from A or B disk follow this example; A>KEYS The whole 10 keys will be printed like this; ASSIGNED KEYS ARE; 0 WS ^JH0 N B: 1 WS ^JH0 D B: 2 ^QC ^OR76 3 ERA B:*.BAK 4 ^KV ^KH ^QV ^Y 5 LIB TL=B: 6 .MAC 7 XDIR 8 XDIR B: 9 ^QD^Y To the the printer also if plugged in. Programed by; D.AMOS. 68a FINDLAY AVENUE. ROSEVILLE, N.S.W. AUSTRALIA. ;TO VIEW AND PRINT THE SETUP KEYS FOR AN OSBORNE EXECUTIVE. ; ;FOR MAC80 USERS THE CSEG OFFSET IS -103H. KEYS EQU 6000H-103H ; ;1ST PAGE ADDRESSES. BDOS EQU 05H ; ;CONTROL CHARACTERS. CR EQU 0DH LF EQU 0AH NUL EQU 00H ; .Z80 ;MAC 80 Z80 SWITCH. ASEG ;MAC 80 RELOCATABLE SWITCH ;ASSEMBLED AT 0100H. ORG 0100H ; ;AN LDIR ROUTINE LOADS THE FILE AT 6000H, BEYOND THE BANK 8 OVERWRITE. WHEN ;BANK 8 IS SWITCHED ON LOWER MEMORY INCLUDING THE 1ST PAGE IS OVERWRITTEN. LOADUP: LD HL,010EH ;START ADDRESS TO LOAD BYTES FROM. LD DE,6000H ;DESTINATION ADDRESS FOR KEYS.COM BYTES. LD BC,0100H ;COVERING THE BYTES OF KEYS.COM LDIR JP 6000H ;AFTER LOADING JUMP TO THE BEGINING. ; CSEG ;MAC 80 RELOCATABLE SWITCH. ;TO BE ASSEMBLED AT 6000H. ORG KEYS ; START: LD SP,6FFFH ;PUT THE STACK AT 6FFFH. CALL 0F92DH ;INITIALISE THE PRINTER. OR A JP Z,NUL ;JUMP TO CP/M COLD START IF NOT WORKING. ; ;THIS IS A SECTION ALLOWING PRINTER SWITCHES, THESE ARE FOR THE ITOH 8510 ;AND SET CONDENSED AND REDUCE THE SPACE BETWEEN LINES. ANY SWITCHES CAN ;BE SET FOR YOUR PRINTER, IF NEEDED! ; LD C,1BH ; CALL 0F90FH ; LD C,42H ; CALL 0F90FH ; LD C,1BH ; CALL 0F90FH ; LD C,51H ; CALL 0F90FH ; ;THE BANK 8 SWITCH, AS IN THE EXECUTIVE REFERENCE MANUAL (SYSTEM SPEC). IN A,(00H) LD (TEMP),A ;SAVE THE ORIGINAL VALUE TO TEMP. OR 80H ;OR IN THE BANK 8 BIT. OUT (00H),A ;RESTORE IT TO PORT 00H. ; ;LDIR THE KEY AREA TO MAIN MEMORY @5155H ON. LD HL,2155H ;1ST ADDRESS OF THE ASSIGNMENTS IN BANK 8. LD DE,5155H ;MOVE ASSIGNMENTS TO THE USER TPA. LD BC,07FFH ;THIS VERSION MOVES 2K OF KEY ASSIGNMENTS! LDIR ; ;SWITCH BACK OUT OF BANK 8. LD A,(TEMP) ;RELOAD ORIGINAL VALUE TO A. OUT (00H),A ;RESTORE IT TO PORT 00H. ; ;CHANGE THE SCREEN JUMP TO A CALL, TO INCLUDE THE PRINTER ALSO. LD A,0CDH LD (0F90CH),A LD DE,KEYST LD C,09H CALL BDOS ;PRINT THE 'ASSIGNED KEYS ARE' STRING. ; LD DE,5155H ;H='0' AND L=11. LD HL,300BH LENGTH: DEC L JR Z,NDALL LD A,H CALL CHAR ;PRINT THE KEY NUMBER FROM H. LD A,20H CALL CHAR ;PRINT A SPACE. INC H LD A,(DE) ;LOAD THE COUNT INTO A REG. OR A ;TAST IF ZERO= NO KEY ASSIGNMENT HERE! JR Z,EMTYN ;IF NONE HERE. LD B,A ;FOR DJNZ. ; A1TO9: INC DE LD A,(DE) ;ASSIGNMENT CHARACTER TO A REG. CP 20H ;FOR LESS THAN A SPACE=^CHAR. JR C,CONCHAR CONTIN: CALL CHAR DJNZ A1TO9 ;END LINE. NDLINE: LD A,0DH CALL CHAR LD A,0AH CALL CHAR INC DE JR LENGTH ; ;BDOS2 PRINT A CHARACTER. CHAR: PUSH HL PUSH DE PUSH BC LD C,02H LD E,A CALL BDOS POP BC POP DE POP HL RET ; ;IF THE ASSIGNMENT KEY IS EMPTY ADD 30H TO A AND PRINT IT. EMTYN: ADD A,30H CALL CHAR JR NDLINE ; CONCHAR:PUSH AF CP 0DH ;IS IT CR? JR Z,CONCR ;YES CONTROL/CARRIAGE RETURN. LD A,5EH ;PRINT A CARET '^'. CALL CHAR ;PRINT IT. POP AF OR A ADD A,40H ;ADD 40H TO TAKE THE CHAR TO A TO Z RANGE. CONTIN0:JP CONTIN ; ;ROUTINE FOR DISPLAY OF CR. CONCR: LD A,'<' CALL CHAR LD A,'C' CALL CHAR LD A,'R' CALL CHAR LD A,'>' JR CONTIN0 ; ;END OF ALL KEYS, WHEN B=ZERO. NDALL: LD A,0C3H ;RESTORE THE SCREEN JUMP. LD (0F90CH),A JP NUL ;JUMP TO CP/M COLD START. ; KEYST: DB 'ASSIGNED KEYS ARE;',CR,LF,'$' ; TEMP: DB NUL ;USED FOR THE BANK DEFAULT. ; END  A REG. CP 20H ;FOR LESS THAN A SPACE=^CHAR. JR C,CONCHAR CONTIN: CALL CHAR DJNZ A1TO9 ;END LINE. NDLINE: LD A,0DH CALL CHAR LD A,0AH CALL CHAR INC DE JR LENGTH ; ;BDOS2 PRINT A CHARACTER. CHAR: PUSH HL PUSH DE PUSH BC LD C,02H LD E,A CALL BDOS POP BC POP DE POP HL RET ; ;IF THE ASSIGNMENT KEY IS EMPTY ADD 30H TO A AND PRINT IT. EMTYN: ADD A,30H CALL CHAR JR NDLINE ; CONCHAR:PUSH AF CP 0DH ;IS IT CR? JR Z,CONCR ;YES CONTROL/CARRIAGE RETURN. LD A,5EH ;PRINT A CARET '^'. CALL CHAR ;PRINT IT. POP AF OR A ADD A,40H ;ADD 40H TO TAKE THE CHAR TO A TO Z RANGE. CONTIN0:JP CONTIN ; ;ROUTINE FOR DISPLAY OF CR. CONCR: LD A,'<' CALL CHAR LD A,'C' CALL CHAR LD A,'R' CALL CHAR LD A,'>' 1`m_  *ɀ\\>2h\\\\~#!PP:]AҮ!k\$!:2~~!!]f!te.<=OB!\l!uE7.P`WN` Write keys in file of type KEY and name? :$ File exists. Backup or Overwrite (B/O)? :$ KEYBAK >!U!P>KEYS COMZKEYS DOC[\]^KEYS MAC_`abSAVKEY $$$1`D_  \1ɀ\\!P:]Aw!:2~~(!e<’bP>5P KEY file name is? :$ No file by that name$ KEY>!PU!>KEYBD COMHIKEYBD DOC5JKLMNOPFNKEYS COMQRFNKEYS DOC1STUVWXYKEYS COMZKEYS DOC[\]^KEYS MAC_`abSAVKEY COMcSETKEY $$$.. Disk documention FROM: Gordon Wilk 6707 Springpark Ave Los Angeles CA 90056 (213) 645-6419 SETKEY SAVKEY These were written as a simple way to switch the definitions of the arrow keys and the control key settings of the numeric pad. Copy the file SAVKEY.COM to the disk on which you keep SETUP.COM Use SETUP to configure the arrow and function keys, save them in the normal manner, then re-boot the disk to get the definitions in the standard memory locations. Run SAVKEY giving it (either in the command line or in answer to its question) an appropriate file name to which it will add the Type ".KEY" ( use WS.KEY and CPM.KEY for example). Copy the file SETKEY along with the "KEY" type files you created to your other disks. Now you can switch between key settings by running SETKEY. The file to set from can either be provided in the command line (i.e SETKEY WS will set the keys to Wordstar configuration) or in answer to the question the program will ask if there is no file in the command line. Since each file will be only 1k, a number of them can be kept on a disk at little cost. reSAVKEY These were written as a simple way to switch the definitions of the arrow keys and the control key settings of the numeric pad. Copy the file SAVKEY.COM to the disk on which you keep SETUP.COM Use SETUP to configure the arrow and function keys, save them in the normal manner, then re-boot the disk to get the definitions in the standard memory locations. Run SAVKEY giving it (either in the command line or in answer to its question) an appropriate file name to which it will add the Type ".KEY" ( use WS.KEY and CPM.KEY for example). Copy the file SETKEY along with the "KEY" type files you created to your other disks. Now you can switch between key settings by running SETKEY. The file to set from can either be provided in the command line (i.e SETKEY WS will set the keys to Wordstar configuration) or in answer to the question the program will ask if there;SAVKEY: Saves key assignments from memory to disk ; ; Usage: SAVKEY ; Fileref is optional and should omit .TYP as the ;filetype is automatically set to .KEY ; If Fileref is not entered, program will ask for ;the drive and filename ; ; Saves the arrow and function key settings ; in memory to a file with the name specified ; by the user and filetype .KEY ; ; (C) Gordon Wilk ; 6706 Springpark Av ; Los Angeles CA 90056 ; ; ;------ EQUATES ------------------------- ; BOOT EQU 00 ;warmboot BDOS EQU 05 ;BDOS call CR EQU 0DH ;carraige return LF EQU 0Ah ;line feed FCB EQU 05CH ;adr of default fcb fcbDR EQU FCB fcbNAME EQU FCB+1 fcbTYPE EQU FCB+9 fcbEX EQU FCB+0CH fcbCR EQU FCB+20H NEWDR EQU FCB+10H ;For rename NEWNAME EQU FCB+11H NEWTYPE EQU FCB+19H DBUFF EQU 080H ;adr of default dma TBL8 EQU 2155H ;key table in bank 8 ;To move char set also use ; TBL8 EQU 2015h NEWORG EQU 5000H LRL EQU 128 ;Logical record length ;To move char set also use ; LRL EQU 256 STAK EQU 6000H UCAS EQU 05FH ;AND with char ; ;------MACROS---------------------------- ; PRINT MACRO MSG ;;Print string @ MSG LXI D,MSG CALL PSTR ENDM ; LDIR MACRO DB 0EDH,0B0H ;z80 LDIR ENDM ; DJNZ MACRO TO DB 10H,TO-$-1 ENDM ; ONE EQU 01H SEVEN EQU 41H EIGHT EQU 81H BANK MACRO NUMBER ;;Enable bank # MVI A,NUMBER OUT 0 ENDM ; BLKMOVE MACRO FROM,TO,LENGTH ;;Block move LXI H,FROM LXI D,TO LXI B,LENGTH DB 0EDH,0B0H ;z80 LDIR ENDM ; REPLY MACRO BUFFER,LENGTH LDA LENGTH STA BUFFER LXI D,BUFFER CALL GETS ENDM ; BUFFER MACRO BUFADR LXI D,BUFADR CALL SETBUFF ENDM ; ;-------PROLOG--------------------------------------- ; ORG 100H LXI SP,STAK JMP START ; ;---------------------------------------------------- ; ; SUBROUTINES ; GETC MVI C,01 ;get char into A CALL BDOS cpi 03 ;Abort JZ boot ANI 05FH ;Uppercase RET ; GETS MVI C,0AH ;get string into CALL BDOS ;adr pointed to by DE RET ; PSTR MVI C,09 ;display string pointed CALL BDOS ;to by DE RET ; PARSE LXI D,PFCB ;Parse string DBuff MVI C,98H ; to FCB filespec CALL BDOS RET PFCB DW DBUFF DW FCB ; OPEN LXI D,FCB ;Open existing file MVI C,15 ; named at fcb1 CALL BDOS RET ; MAKEF MVI A,0 ;Extent 0 STA fcbEX LXI D,FCB MVI C,22 ;Create file CALL BDOS ; from FCB RET ; RENAME LXI D,FCB MVI C,23 ;Rename file CALL BDOS ; in FCB RET ; CLOSE MVI C,16 ;Close file LXI D,FCB ; @ FCB CALL BDOS RET ; WRITE LXI D,FCB ;;Write sector in MVI C,21 ;; in buffer CALL BDOS ;; to file in fcb1 RET ; SETBUFF MVI C,26 ;;Set File buffer CALL BDOS ;; to (DE) RET ; ;Changes string pointed to by HL to upper case ;->HL=string adr B=string length ;<-HL=string end+1 B=0 Uses AF ; UPCASE MOV A,M ANI 05FH INX H DJNZ UPCASE RET ; ; ;==========MAINLINE============================= ; ; Relocate the block move above the bank 8 screen and ; execute it to move the key codes up to KEYtbl1 also ; above the bank 8 screen, ; START BLKMOVE RSEG1,NEWORG,RSEG2-RSEG1 CALL NEWORG ;Move and do relocateble code ; ; Check command tail for fileref ; LDA FCB+1 CPI 'A' JNC ISFILE ;Fileref in tail ; ; No fileref in tail - so get the drive and file ; in which to write the the key table ; NOFILE PRINT MSG1 ;Save in file ? BLKMOVE DFCB,FCB,36 BLKMOVE BLANK,DBUFF,14 REPLY DBUFF-2,14 CALL PARSE ; ; Assure filename is in upper case ; LXI H,FCBNAME MVI B,08 CALL UPCASE ; ; If the named file does not exist create it. If it ;exists, overwrite or make backup copy - then open ; ISFILE BLKMOVE KTYPE,FCBTYPE,3 ; Type = .KEY CALL OPEN ;Open file INR A ;FF -> 0 JZ ISFIL$3 ;No file: create ISFIL$2 PRINT MSG2 ;BACKUP OR OVERWRITE CALL GETC CPI 'O' JZ MVTBL ;GO overwrite CPI 'B' JNZ ISFIL$2 BLKMOVE FCB,NEWDR,16 ;rename to .BAK BLKMOVE BAKTYP,NEWTYPE,3 CALL RENAME ISFIL$3 CALL MAKEF CALL OPEN ; ; Write the keytable in the file, close file ;and quit. ; MVTBL BUFFER NEWORG+TBL1-RSEG1; Points to keytable CALL WRITE ; Write from keytable ;To save char set also add: ; buffer neworg+tbl1-rseg1+128 ; call write CALL CLOSE JMP BOOT ; MSG1 DB CR,LF,'Write keys in file of type KEY and name? :$' MSG2 DB CR,LF,'File exists. Backup or Overwrite (B/O)? :$' DFCB DB 0,' ' KTYPE DB 'KEY' DW 0,0,0,0,0,0,0,0,0,0,0,0 BAKTYP DB 'BAK' BLANK DB ' ' ; ;Relocatable segment. This moves the tables from bank 8 ; to tbl1 in bank 1; ; RSEG1 BANK eight BLKMOVE TBL8,NEWORG+TBL1-RSEG1,LRL BANK one RET RSEG2 NOP TBL1 DS 128 ;To move char set also use ; TBL1 DS 256 TOP DB 0 END 100H 2 ;BACKUP OR OVERWRITE CALL GETC CPI 'O' JZ MVTBL ;GO overwrite CPI 'B' JNZ ISFIL$2 BLKMOVE FCB,NEWDR,16 ;rename to .BAK BLKMOVE BAKTYP,NEWTYPE,3 CALL RENAME ISFIL$3 CALL MAKEF CALL OPEN ; ; Write the keytable in the file, close file;SETKEY: Sets keycodes to those in a disk file ; ; Usage: SETKEY ; Filename is optional. If used should include ;drive (if not default) but not .TYP which will ;be KEY. If no filename used, the program will ;ask for one. ; ; Sets the arrow and functions keys in effect ; to those found in the file whose name is ; specified and of type .KEY The new key ; key setting take effect immediately. ; ; (C) Gordon Wilk ; 6706 Springpark AV ; Los Angeles CA 90056 ; ;------ EQUATES ------------------------- ; BOOT EQU 00 ;warmboot BDOS EQU 05 ;BDOS call CR EQU 0DH ;carraige return LF EQU 0Ah ;line feed FCB EQU 05CH ;adr of default fcb fcbDR EQU FCB fcbNAME EQU FCB+1 fcbTYPE EQU FCB+9 fcbEX EQU FCB+0CH fcbCR EQU FCB+20H NEWDR EQU FCB+10H ;For rename NEWNAME EQU FCB+11H NEWTYPE EQU FCB+19H DBUFF EQU 080H ;adr of default dma TBL8 EQU 2155H ;key table in bank 8 NEWORG EQU 5000H LRL EQU 128 ;Logical record length ;To set char set also use ;LRL EQU 256 STAK EQU 6000H ; ;------MACROS---------------------------- ; PRINT MACRO MSG ;;Print string @ MSG LXI D,MSG CALL PSTR ENDM ; LDIR MACRO DB 0EDH,0B0H ;z80 LDIR ENDM ; ONE EQU 01H EIGHT EQU 81H BANK MACRO NUMBER ;Enable bank # MVI A,NUMBER OUT 0 ENDM ; BLKMOVE MACRO FROM,TO,LENGTH ;;Block move LXI H,FROM LXI D,TO LXI B,LENGTH DB 0EDH,0B0H ;;z80 LDIR ENDM ; REPLY MACRO BUFFER,LENGTH LDA LENGTH STA BUFFER LXI D,BUFFER CALL GETS ENDM ; BUFFER MACRO BUFADR ;Sets buffer address LXI D,BUFADR ; to BUFADR CALL SETBUFF ENDM ; ;-------PROLOG--------------------------------------- ; ORG 100H LXI SP,STAK JMP START ; ;---------------------------------------------------- ; ; SUBROUTINES ; GETC MVI C,01 ;get char into A CALL BDOS cpi 03 ;Abort JZ boot ANI 05FH ;Uppercase RET ; GETS MVI C,0AH ;get string into CALL BDOS ;adr pointed to by DE RET ; PSTR MVI C,09 ;display string pointed CALL BDOS ;to by DE RET ; OPEN LXI D,FCB ;Open existing file MVI C,15 ; named at fcb1 CALL BDOS RET ; PARSE LXI D,PFCB ;Parse filename in DBuff MVI C,152 ; to filespex in FCB CALL BDOS RET PFCB DW DBUFF DW FCB ; READ LXI D,FCB ;;Read sector to MVI C,20 ;; buffer CALL BDOS RET ; SETBUFF MVI C,26 ;;Set File buffer CALL BDOS ;; to (DE) RET ; ; ;==========MAINLINE============================= ; ;Move relocatable segment up above bank 8 ; START BLKMOVE RSEG1,NEWORG,RSEG2-RSEG1 ; ;Check command tail for filespec ; If filespec given go check validity and open ; LDA FCB+1 CPI 'A' JNC ISFILE ; ; If no filename given, ask name ; BLKMOVE BLANK,DBUFF,15 ASKF PRINT MSG1 ;FILENAME? REPLY DBUFF-2,14 CALL PARSE ; ; If the named file does not exist ask again. If it ;exists, open it. ; ISFILE BLKMOVE KTYPE,FCBtype,26 CALL OPEN ;Open file INR A ;FF -> 0 JNZ MVTBL ;If there PRINT MSG2 ;If not JMP ASKF ;say so and ask again ; ; Read the keytable in the file into TBL1 ; MVTBL BUFFER NEWORG+TBL1-RSEG1; Points to keytable ; To set char set also add ; mvi e,2 ;set multisector ; mvi c,44 ;count = 2 ; call bdos CALL READ ;Read into TBL1 JMP NEWORG ;To relocated segment ; MSG1 DB CR,LF,'KEY file name is? :$' MSG2 DB CR,LF,'No file by that name$',CR,LF BLANK DB ' ',0 KTYPE DB 'KEY' DS 22 ; ;Relocatable segment ;Moves the table from bank 1 to bank 8 ; RSEG1 BANK EIGHT BLKMOVE NEWORG+TBL1-RSEG1,TBL8,LRL BANK ONE JMP BOOT RSEG2 NOP TBL1 DS 128 ;Key table in bank 1 ;To set char set also use ;TBL1 DS 256 TOP DB 0 END 100H iven, ask name ; BLKMOVE BLANK,DBUFF,15 ASKF PRINT MSG1 ;FILENAME? REPLY DBUFF-2,14 CALL PARSE ; ; If the named file does not exist ask again. If it ;exists, open it. ; ISFILE BLKMOVE KTYPE,FCBtype,26 CALL OPEN ;Open file INR A ;FF -> 0 JNZ MVTBL ;If there PRINT MSG2 ;If not JMP ASKF ;say so and ask again ; ; Read the keytable in the file into TBL1!@h@1h@>!h@ >,@h@\\\\BUFEXECRDOC EXAUTO ASM GRAFTESTBAS VIDEO BAS#ZEROMAKRCOMm !"#$ZEROMAKRDOC %&ZEROMAKRBAS'(NULL COM)NULL ASM!*+,-.OTHELLO BAS/0123456789:;<=>OTHELLO BAS%?@ABCFREE30 DOCDEFGKEYBD COMHIKEYBD DOC5JKLMNOPFNKEYS COMQRFNKEYS DOC1STUVWXYKEYS COMZKEYS DOC[\]^KEYS MAC_`abSAVKEY COMcSETKEY COMdSET/SAV DOC efSAVKEY ASM&ghijkSETKEY ASMlmnoEXROM11 $$$EXROM11.COM reads the ROM from bank 8. Invoke with A> EXROM11 [d:filename.typ] the memory from bank 8 will be stored there. XROM11.COM reads the ROM from bank 8. Invoke with A> EXROM11 [d:filename.typ] the memory from bank 8 will be stored there. ZEROMAKRCOMm !"#$ZEROMAKRDOC %&ZEROMAKRBAS'(NULL COM)NULL ASM!*+,-.OTHELLO BAS/0123456789:;<=>OTHELLO BAS%?@ABCFREE30 DOCDEFGKEYBD COMHIKEYBD DOC5JKLMNOPFNKEYS COMQRFNKEYS DOC1STUVWXYKEYS COMZKEYS DOC[\]^KEYS MAC_`abSAVKEY COMcSETKEY COMdSET/SAV DOC efSAVKEY ASM&ghijkSETKEY ASMlmnoEXROM11 COMpEXROM11 $$$PEEKBDOS!]~- #!!~ Gu<~# P1>282QACLGW >Q2 Command Line Syntax Error ${PEEKBDOSAPEEKBDOSy<!~# 6>͂$"!9"1> o> o*KE: z^{^E)yʟV ot> o!KV‡K!~^ "!K^:E  _Q2**#~:#^#V#"!#:  !6*~#fo#~2+~Q>A4C4y2 >2K~#oK^> ogƐ'@'_:O Ʌo$opnficlsfird sewr sesetdmsrch srch renamerase!rd ra"wr racreatexs1s2rcnr Ret:D$! $@BB$H$$H  H A !]~- #!!~ Gu<~# P1>282QACLGW >Q2 Command Line Syntax Error ${PEEKBDOSAPEEKBDOSy<!~# 6>͂$"!9"1> o> o*KE: z^{^E)yʟV ot> o!KV‡K!~^ "!K^:E  _Q2**#~:#^#V#"!#:  !6*~#fo#~2+~Q>A4C4y2 >2K~#oK^> ogƐ'@'_:O Ʌo$opnficlsfird sewr sesetdmsrch srch renamerase!rd ra"wr racreatexs1s2rcnr Ret: This file contains brief documentation for PEEK, a CPM+ utility that appeared in the Feb, 1984 issue of Microsystems. Please re- fer to the article for more information. --Ron Fowler title 'BDOS-PEEK RSX for CP/M 3.0' *************************** * PEEKBDOS.ASM * * Version 1.0 * * Copyright (c) 1983 * * by * * Ron Fowler * *************************** This program is an RSX running under CP/M 3.0 (only). It's purpose is to trace file-related BDOS calls, and display information regarding each call on the AUX device. It must be combined with the companion module, "PEEK.ASM" using GENCOM, as described in the CP/M+ programmer's guide. PEEK's output device defaults to the system console, and can be changed by doing "peek a" (aux), "peek l" (list), or "peek c" (console). Note that "peek p" sets the pause flag, causing the trace to pause after the call to bdos. Note also that a "*" is printed at the pause; the program then waits for input. Any character other than "Q" will simply cause a return to the caller. A "Q" resets the pause flag, and the program then displays without pausing. "PEEK Q" removes the RSX from memory. I find this very useful for debugging programs. Typically, I keep a term- attached to my AUX device (well, actually, it's a separate computer, run- ning a modem program across a serial link, but that's another story...) -- this RSX outputs to the AUX device to keep the output from the program from getting mixed up with the output from this RSX. Hence, I get a full "snapshot" of file operations made by the program under test. Note that this RSX uses one level of caller's stack. Also, if you modify this code, be VERY careful with the registers; I save only what is absol- utely necessary, in order to conserve memory. Ron Fowler Fort Atkinson, WI 08/22/83 UPDATE INFORMATION: -- if you update this program, please pass along a copy to Fort Fone File Folder (FFFF) RCP/M, Fort Atkinson, WI: (414) 563-9932 (no ringback). Please update the version number in both modules (PEEK.ASM also). updates (in reverse order to minimize reading time): 1.0 originally written by Ron Fowler 08/22/83 ------------------------------------------------------------ ng(well, actually, it's a separate computer, run- ning a modem program across a serial link, but that's another story...) -- this RSX outputs to the AUX device to keep the output from the program from getting mixed up with the output from this RSX. Hence, I get a full "snapshot" of file operations made by the program under test. Note that this RSX uses one level of caller's stack. Also, if you modify this code, be VERY careful with the registers; I save only what is absol- utely necessary, in order to conserve memory. Ron Fowler Fort Atkinson, WI 08/22/83 UPDATE INFORMATION: -- if you upd title 'PEEK.ASM: tpa module for PEEK RSX' ; ; ; copyright (C) 1983 : Ron Fowler, Fort Atkinson, WI ; ; This is the TPA module for the PEEK rsx; it must be combined with ; PEEKBDOS using the GENCOM utility, as described in the CPM+ Pro- ; grammer's Guide. Syntax and usage information is contained in the ; companion module, PEEKBDOS.ASM. ; ; equates ; bdos equ 5 ;system entry point printf equ 9 ;print console buffer funct # rsxf equ 60 ;"CALL RSX" system call ; dfcb1 equ 5ch ;default file control block 1 dfcb2 equ 6ch ;default file control block 2 tpa equ 100h ;transient program area ; cr equ 13 ;carriage-return code lf equ 10 ;linefeed code ; ; by the time we get running, the CPM+ loader has already loaded ; and activated the rsp (or it may already be in memory from a ; previous load). So all we have to do is parse any arguments from ; the command line, and pass them on to the rsx using function 60. ; lxi h,dfcb1+1 ;get pointer to command line arg mov a,m ;get optional "-" (for unix people) cpi '-' jnz nodash ;jump if not there inx h ;yep, advance past it nodash: call parse ;parse first argument call parse ;parse possible second argument mov a,m ;shouldn't be a third cpi ' ' ;(ie, 3rd position should be blank) jnz synerr ;if bad, jump sendit: lxi d,rsxpb ;send to rsp mvi c,rsxf call bdos jmp 0 ;all done, warm-boot ; ; parse an argument ; parse: mov a,m ;fetch argument inx h ;advance pointer cpi ' ' ;allow nulls rz cpi 'P' ;pause-flag? jnz npars ;jump if not mvi a,1 ;pause-flag sta args+1 ;where it goes ret npars: call valid ;validate sta args ret ; valid: cpi 'Q' ;quit... rz cpi 'A' ;out to aux rz cpi 'C' ;out to con rz cpi 'L' ;out to list jnz synerr ;what then? ret ; ; syntax error ; synerr: lxi d,synems ;oops, bomb out mvi c,printf ;print string function # call bdos mvi a,'Q' ;insure removal of rsx sta args jmp sendit ;go send, exit ; synems: db cr,lf,'Command Line Syntax Error',cr,lf,'$' ; ; rsx parameter block ; rsxpb: db 127 ;function # (we ignore) db 2 ;2 parameters dw myname ;parm1 = rsx name dw args ;parm2 = command line arguments ; ; name of rsx ; myname: db 'PEEKBDOS' ;name of RSX we're calling args: db 'A',0ffh ;output-device, pause-flag ; end  ; ; parse an argument ; parse: mov a,m ;fetch argument inx h ;advance pointer cpi ' ' ;allow nulls rz cpi 'P' ;pause-flag? jnz npars ;jump if not mvi a,1 ;pause-flag sta args+1 ;where it goes ret npars: call valid ;validate sta args ret ; valid: cpi 'Q' ;quit... rz cpi 'A' ;out to aux rz cpi 'C' ;out to con rz cpi 'L' ;out to list jnz synerr ;what then? ret ; ; syntax error ; synerr: lxi d,synems ;oops, bomb out mvi c,printf ;print string function # call bdos mvi a,'Q' ;insure removal of rsx sta args jmp sendit ;go send, exit ; synems: db cr,lf,'Command Line ; This file contains the source code for PEEK, a CPM+ utility ; that appeared in the Feb, 1984 issue of Microsystems. Please re- ; fer to the article for more information (the source files contain ; some information on the use of PEEK). --Ron Fowler ; ; title 'BDOS-PEEK RSX for CP/M 3.0' ; ; ; *************************** ; * PEEKBDOS.ASM * ; * Version 1.0 * ; * Copyright (c) 1983 * ; * by * ; * Ron Fowler * ; *************************** ; ; This program is an RSX running under CP/M 3.0 (only). It's purpose is ; to trace file-related BDOS calls, and display information regarding each ; call on the AUX device. It must be combined with the companion module, ; "PEEK.ASM" using GENCOM, as described in the CP/M+ programmer's guide. ; ; PEEK's output device defaults to the system console, and can be changed ; by doing "peek a" (aux), "peek l" (list), or "peek c" (console). Note ; that "peek p"  sets the pause flag, causing the trace to pause after the ; call to bdos. Note also that a "*" is printed at the pause; the program ; then waits for input. Any character other than "Q" will simply cause a ; return to the caller. A "Q" resets the pause flag, and the program then ; displays without pausing. ; ; "PEEK Q" removes the RSX from memory. ; ; I find this very useful for debugging programs. Typically, I keep a term- ; attached to my AUX device (well, actually, it's a separate computer, run- ; ning a modem program across a serial link, but that's another story...) -- ; this RSX outputs to the AUX device to keep the output from the program ; from getting mixed up with the output from this RSX. Hence, I get a full ; "snapshot" of file operations made by the program under test. ; ; Note that this RSX uses one level of caller's stack. Also, if you modify ; this code, be VERY careful with the registers; I save only what is absol- ; utely necessary, in order to conserve memory. ; ; Ron Fowler ; Fort Atkinson, WI ; 08/22/83 ; ; UPDATE INFORMATION: ; ; -- if you update this program, please pass along a copy to Fort Fone File ; Folder (FFFF) RCP/M, Fort Atkinson, WI: (414) 563-9932 (no ringback). ; Please update the version number in both modules (PEEK.ASM also). ; ; updates (in reverse order to minimize reading time): ; ; 1.0 originally written by Ron Fowler 08/22/83 ; ;------------------------------------------------------------ ; ; CP/M equates ; conotf equ 2 ;output character to console auxotf equ 4 ;aux output lstotf equ 5 ;list output diriof equ 6 ;direct console i/o printf equ 9 ;print string function openf equ 15 ;open file closf equ 16 ;close file srchf equ 17 ;search for file 1st occurance srchn equ 18 ;search for file next occurance erasf equ 19 ;erase file readf equ 20 ;read sequential writf equ 21 ;write sequential creat equ 22 ;create file renmf equ 23 ;rename file sdmaf equ 26 ;set transfer address rdran equ 33 ;read random wrran equ 34 ;write random ; ; character equates ; cr equ 13 ;carriage-return code lf equ 10 ;linefeed code ; ; ; ; RSX prefix ; db 0,0,0,0,0,0 ;space for CPM3 to insert serial # jmp begin ;jump to entry point next: db jmp ;jump instruction op-code dw 0 ;next RSX or loader dw 0 ;previous RSX or 0 rmvflg: db 0 ;removes RSX when non-0 db 0 ;flag for non-banked only myname: db 'PEEKBDOS' ;our name db 0 ;loader flag db 0,0 ;reserved ; ; This is the BDOS call intercept. Here we determine if the ; call is one of those we process. If not, we simply pass ; control on to the next module. ; begin: mov a,c ;get function code cpi 60 ;for RSX's only? jz rsxfnc ;go if so lxi h,fnctbl ;nope, test for one of ours scan: mov a,m ;get first/next table opcode inx h ora a ;end-of-table? jz next ;then quit now cmp c ;ours? jz trap ;go trap if so mvi a,6 ;nope, calculate next table entry call addha jmp scan ;continue ; ; Here when we've determined that we must display the system call. ; First save caller's stackpointer and load a local stack. ; trap: shld tblptr ;save pointer to function string lxi h,0 ;get user's sp dad sp shld spsave lxi sp,stack ;load local stack ; ; begin the trace: do newline, then print the function string ; mvi a,cr ;carriage call type mvi a,lf call type lhld tblptr ;get string pointer call prathl ;print it call ilprnt ;colon, open paren db ': ' db '('+80h ; ; print fcb address (or dma address) ; mov a,d ;get parameter hi call hexout mov a,e ;then lo call hexout call ilprnt ;closing paren db ')',' '+80h mov a,c ;get function code cpi sdmaf ;set-dma? jz exit ;then done ; ; Not setdma function. Print out the FCB information ; push d ;save fcb pointer ldax d ;get drive code inx d call hexsp ;print hex byte, space ; ; Print the file name ; mvi b,11 ;eleven characters fnprnt: ldax d ;get first/next char inx d ;advance fcb pointer call type ;print it dcr b ;all 11 jnz fnprnt mvi a,' ' ;separate filename call type ; ; print ex,s1,s2,rc ; mvi b,4 ;four of these lxi h,idbase ;ascii id's for each field idloop: call prathl ;print id ldax d ;get field inx d ;advance fcb pointer call hexsp ;print in hex, space dcr b ;all 4 jnz idloop ; ; print the nr field ; call prathl ;last id string lxi h,16 ;offset to nr field dad d mov a,m ;fetch it call hexout ;print it pop d ;restore fcb pointer ; ; here after fcb info printed. Allow the call to pass upward, ; then print the returned value. ; exit: call next ;give call to bdos shld hlsave ;save returned registers push d push b push psw ;save returned value lxi h,rtnmsg ;print "Ret: " call prathl pop psw ;restore, resave returned a push psw call hexout ;print it in hex lda pause ;do a pause? ora a jz nopaus ;jump if not call ilprnt ;yep, print prompt db ' ','*'+80h mvi c,diriof ;get a character mvi e,0FDH ;don't come back 'till we have one call next ani 5fh ;convert char to upper case cpi 'Q' ;quit-pause? jnz nopaus ;no xra a ;yes sta pause nopaus: pop psw ;restore 'em all pop b pop d lhld spsave ;restore stackpointer sphl lhld hlsave ret ;back to caller ; ; Handler for function 60: call RSX. Here we insure that the ; call is for us. The RSX parameter block passed in DE must ; contain two parameters, the first of which is a pointer to ; our name (near absolute insurance that there won't be any ; confusion). The second parameter is a pointer to a request ; code (one of: "Q", quit, "C", console, "L", list, "A", aux). ; rsxfnc: push d ;save user de xchg ;rsx pb pointer to hl inx h ;ignore function code mov a,m ;get # parameters cpi 2 ;two? jnz pass ;quit if not inx h ;skip # of parameters mov e,m ;fetch parameter #1 inx h mov d,m inx h ;hl points to 2nd parm shld spsave ;save that pointer lxi h,myname ;check for our name mvi b,8 ;8 characters ckname: ldax d ;compare first/next character inx d cmp m ;compare with our name inx h jnz pass ;if fails, pass to next rsx dcr b ;all 8 jnz ckname ; ; rsx request is for us, get rsx pointer, load 2nd parameter ; pop d ;recall passed parameter ; ; call next rsx's -- we may be an accidently loaded rsx (which ; will happen when the tpa module is used only for communication ; with us). PEEK always returns 0, CP/M returns 0FFH. So... ; unless we get an ff back, there are more of us in memory, and we ; are only a clone, and must commit suicide (does this sound ; like science fiction to you too??) ; call next ;are we real? cpi 0ffh ;a=0ffh? jz wereal ;jump if so lxi h,rmvflg ;sad... mvi m,0ffh ret ; wereal: lhld spsave ;get rsx pointer mov a,m ;fetch next parameter inx h mov h,m ;into hl mov l,a ;hl points to request inx h ;point to pause flag mov a,m ;fetch it cpi 0ffh ;null? (don't alter pauseflag) jz pntreq ;jump if so sta pause ;no, stuff it pntreq: dcx h ;point to request mov a,m ;fetch request ; ; a now has the function request character passed from the tpa ; cpi 'Q' ;quit? jz quit cpi 'A' ;output to aux? mvi c,auxotf ;prep function code jz setout cpi 'C' ;output to console? mvi c,conotf ;prep code jz setout mvi c,lstotf ;process of elimination (list) setout: mov a,c ;get new output device code sta curdev ;stuff it xra a ;return a=0 ret ; ; here when call 60 is not for us ; pass: pop d ;clear stack jmp next ;to next rsx ; ; here to quit ; quit: mvi a,0ffh ;flag loader to remove us sta rmvflg xra a ;we still return 0 ret ; ; *************** ; * subroutines * ; *************** ; ; print in-line message terminated by char w/bit7=1 ; ilprnt: xthl ;msg pointer to hl call prathl ;print it xthl ret ; ; print string pointed to by hl, until char w/bit7=1 ; prathl: mov a,m ;fetch first/next char inx h ;advance pointer call type ;print it ani 80h ;terminator? jz prathl ;continue if not ret ; ; output a in hex, followed by space ; hexsp: call hexout ;print it mvi a,' ' jmp type ; ; output a as 2 hex digits ; hexout: push psw ;save it rrc ;hi nybble into lo rrc rrc rrc call nybble ;print it pop psw ;now restore, fall into lo nybble: ani 0fh ;zap any garbage in hi nybble adi 90h ;this little beauty... daa ;...is from the old (and maybe aci 40h ;...still existing) Intel library daa ;fall into type ; ; type char in a on console via current output device. ; type: push psw ;save all push h push d push b ani 7fh ;allow no parity bits to pass mov e,a ;align character lda curdev ;get device function code mov c,a call next ;output the character pop b ;clean up pop d pop h pop psw ret ; ; add a to hl ; addha: add l mov l,a rnc inr h ret ; ; Table of locally-processed system function calls. Format is function ; code followed by id string. Note that more functions may be added to ; this table, but if they are not fcb-related functions, you'll have to ; modify the TRAP routine to process the new data types. ; fnctbl: db openf,'opnfi','l'+80H db closf,'clsfi','l'+80H db readf,'rd se','q'+80H db writf,'wr se','q'+80H db sdmaf,'setdm','a'+80H db srchf,'srch ','1'+80H db srchn,'srch ','n'+80H db renmf,'renam','e'+80H db erasf,'erase',' '+80H db rdran,'rd ra','n'+80H db wrran,'wr ra','n'+80H db creat,'creat','e'+80H ; db 0 ; ; table of fcb id strings ; idbase: db 'ex','='+80h db 's1','='+80h db 's2','='+80h db 'rc','='+80h db 'nr','='+80h ; rtnmsg: db ' Ret:',' '+80h ; ; data area ; curdev: db auxotf ;system-call # for output pause: db 0 ;non-0 = pause after bdos calls tblptr: dw 0 ;saved pointer into fnctbl hlsave: dw 0 ;save for hl spsave: dw 0 ;stackpointer save ds 24 ;12-level stack stack: ; ; end inter into fnctbl hlsave: dw 0 ;save for hl spsave: dw 0 ;stackpointer save ds 24 ;12-le1 !"*#"|7|.}}.*:"txg|g*t2m:*tmI*t|+m;EXTONE.ASM (version 1.0) 8/12/83 ;A Utility for the Osborne Executive I George Peace ; Midlothian, Virginia ; CompuServe 71555,1501 ;Demonstration of the NOISE subroutine for controlling the speaker ;on the Executive I ;An interesting side-effect of this program is that occasionally the ;drive the program was loaded from remains selected. bug/missed interrupt? org 100h lxi sp,stack jmp start tlow equ 5 ;duration for low tones tmed equ 25 ;duration for medium tones thigh equ 125 ;duration for high tones timer: dw 0000h temp: db 1 start: lxi h,0 ;initialize tone control to zero shld timer ;and plant seed for the loop loop1: lhld timer ;retrieve last tone control value inx h ;increment tone control value shld timer ;save for next loop ;limit the demonstration to 200h different tones mov a,h ;get high order byte of counter cpi 02h ;have 200h repeats yet? jz done ;yes - all done ;shorten the tone duration when the lower tones begin mvi b,tlow ;set tone duration for lows mov a,h ;get high order byte of tone value cpi 01h ;have 100h repeats yet? jz loop2 ;leave duration at default for lows mov a,l ;get low order byte of tone value mvi b,thigh ;set long duration for highs cpi 80h ;have 0080h repeats yet? jc loop2 ;not yet - no change mvi b,tmed ;set shorter tone duration for mediums loop2: lhld timer ;get tone control value call noise ;make noise (HL=tone,B=duration) jmp loop1 ;...then change the tone a bit done: jmp 0 ;do warm boot ;--- beginning of NOISE subroutine ---------------------------------- ;Subroutine to make noise on the Osborne Executive I (George Peace 8/12/83) ;This subroutine allows "standardized" control of the speaker from within ;a program. ; input: HL = tone control value (use low numbers produce high tones) ; B = tone duration ; exit: all registers/flags unchanged ;note that both input parameters must be non-zero (at least 1) to operate noise: push psw ;save environment push b shld noisav ;save tone control value mov a,b ;get tone duration ora a ;if zero, jz noise2 ;... exit as if never called mov a,h ;get tone control ora l ;if zero, jz noise2 ;... exit as if never called noise1: lhld noisav ;retrieve tone control value in 02h ;get original port control value sta temp ori 00001000b ;set speaker bit on out 02h call noisew ;measure length of time to leave noise on lda temp ;get original port control byte out 02h ;and restore to its original state lhld noisav ;restore tone control value call noisew ;leave noise off same length as on dcr b ;decrement tone duration counter jnz noise1 ;loop until done noise2: lhld noisav ;restore environment pop b pop psw ret noisew: mov a,h ;count ora l ; down dcx h ; to jnz noisew ; zero ret noisav: ds 2 ;save area for caller's HL ;--- end of NOISE subroutine ---------------------------------------- ds 20h stack: ds 2 end  .Z80 ;using M80.COM ;??????? version 1.0 by George F Peace ; P. O. Box 481 ; Midlothian, Virginia 23113 ; CompuServe 71555,1501 ; ;This is a Resident System Extension (RSX) intended to run under CP/M Plus. ; ;****** This is a "seed" RSX to be used to build addional RSX's. ****** ;****** Only the generic support functions are provided. ****** ;****** Model your own subfunctions after the ones provided. ****** ; ;The RSX is called via BDOS function 60 (in register C) with register pair DE ;pointing to the RSX parameter block. The parameter block has the following ;format: ; ; RSXPB: DB subfnc ;the subfunction number (0-127) for this RSX ; DB 2 ;exactly two parameters follow ; DW rsxnam ;pointer to the name of the RSX being called ; ; (must be exactly 8 bytes) ; DW arglst ;pointer to the arguments for the subfunction ; ; (may vary in length depending on subfunction) ; ;------ RSX Prefix Structure ------ ; serial: defb 0,0,0,0,0,0 ;room to insert serial number start: jp ftest ;beginning of program next: defb 0C3H ;jump instruction op-code defw 0 ;next module in line (or BDOS) prev: defw 0 ;previous module remov: defb 0FFh ;remove flag initially set nonbnk: defb 0 ;>0 to load only in non-banked CP/M rsxnam: defb '????????' ;the name of this RSX loader: defb 0 ;loader flag defb 0,0 ;reserved ;------ BDOS function 60 sub-functions used by this RSX ------ ; rsxtest equ 100 ;test for RSX in memory rsxinit equ 101 ;RSX initialize function code rsxterm equ 102 ;RSX terminate function code rsxdebug equ 103 ;debug control ;------ RSX-specific Constants used to support this RSX ------ ; nparam equ 2 ;number of parameters required in caller's ; RSX parameter block ;------ Define the RSX subfunction lookup table format ------ ; tabent macro m1,m2 ;TABENT subfunction,address defb m1 ;RSX subfunction number defw m2 ;RSX routine address endm ;------ RSX subfunction lookup table ------ ; ftable: tabent rsxtest,rsxtst ;Test for RSX in memory tabent rsxinit,rsxint ;RSX initialize tabent rsxterm,rsxtrm ;RSX terminate and deactivate tabent rsxdebug,rsxdbg ;set/clear debug mode defb 0FFh ;end of table ;------ Miscellaneous data/constants ------ ; debug equ 0 ;debug code generation control rsxpb: defw 0 ;caller's RSX parameter block address spsave: defw 0 ;pointer storage iniflg: defb notinit ;if not reset, all operations rejected init equ 00 ; initialized notinit equ 0FFh ; not initialized ;------ Stack storage ------ ; defs 48 locstk: ;internal stack stksav: defw 0 ;caller's stack pointer CR EQU 0DH ;carriage return LF EQU 0AH ;line feed ;------ Macro Definitions ------ ; ; DDMSG ; ddmsg macro ?msg ;display a string on the console local pastsb local pstcal if debug jr pastsb msgout: push af ld a,(debflg) cp 00 jr z,pstcal push bc push hl push ix push iy ld c,9 call next pop iy pop ix pop hl pop bc pstcal: pop af ret pastsb: endif ;debug ddmsg macro ??msg local tymsg local pastm if debug push de ld de,tymsg call msgout pop de jr pastm tymsg: defb '&??msg',cr,lf,'$' pastm: endif ;debug endm if debug ddmsg endif ;debug endm ;------------------------------------ ;------ Entry point to the RSX ------ ;------------------------------------ ; ftest: ld a,c ;get BDOS function cp 60 ;could this one be for us? jp nz,next ;nope - ignore this function ddmsg < > ddmsg ;This is the RSX-specific BDOS call. First, we'll make sure that the call ;is actually for this RSX by testing the name of the RSX passed as the first ;parameter. ld (stksav),sp ;save caller's stack pointer ld sp,locstk ;load stack pointer with our stack address push bc ;save caller's environment (except AF) push de push hl push ix push iy push de ;save caller's DE ex de,hl ;get caller's parameter block address in HL inc hl ;move past function code ld a,(hl) ;get number of parameters passed cp nparam ;exactly right number of parameters? jp nz,bypass ;if not, pass the caller on to the next RSX ddmsg inc hl ;move pointer past number of parameters ld e,(hl) ;get first parameter address inc hl ld d,(hl) inc hl ;HL points to second parameter push de ;save first parameter address ld e,(hl) ;get second parameter address inc hl ld d,(hl) ld (spsave),de ;save address of actual caller parameters pop de ;restore first parameter address ld hl,rsxnam ;get location of the RSX name field ld b,8 ;set loop counter to 8 (characters) ckname: ld a,(de) ;get next character of caller's parameter inc de ;update pointer to caller's parameter cp (hl) ;compare to this RSX's name inc hl ;update pointer to my RSX name jp nz,bypass ;no match - not for us dec b ;decrement loop counter jr nz,ckname ;go back for more if not done ;Ok, the name matches so this must be the right RSX. ddmsg pop de ;recall passed parameter ld (rsxpb),de ;save caller's RSX parameter block address ;But wait ... what if there is already another copy of this RSX in memory? ;We'll check ... ;Call the next RSX or BDOS to see if this is the only copy of the RSX ;currently in memory with our name. ddmsg call next ;check if this the only one copy in memory ddmsg cp 0FFh ;did the call reach BDOS? jr z,realthing ;yes - this RSX is unique ddmsg ld a,0FFh ;no - this RSX duplicates one already resident ld (remov),a ;mark this RSX to be unloaded jp done ;and return to caller realthing: ddmsg ;Ok, this is it. All the external validity checks are complete. Now make sure ;the RSX has been properly initialized. If not, only an initialize operation ;is allowed. ;Get the RSX subfunction from the first byte of the caller's parameter block ld de,(rsxpb) ;retrieve original parameter pointer ld a,(de) ;get RSX function number from parameter block ld c,a ;save RSX function ;Check the initialize indicator ld a,(iniflg) ;get the initialize flag cp init ;is the RSX initialized? jr z,allfok ;yes - all functions are ok ld a,c ;retrieve the function code cp rsxinit ;is it an initialize request? jp nz,erfun ;nope, treat the request as if it is undefined ddmsg allfok: ld hl,ftable ;get function table address flook: ld a,(hl) ;pick up function value inc hl ;increment pointer to routine address cp 0FFh ;reached end of table yet? jp z,erfun ;yes - bad function passed cp c ;is this our function? jr z,fmatch ;yes - go jump to our function inc hl ;increment HL past inc hl ; address field jr flook ; and try again fmatch: ddmsg ld e,(hl) ;get address of routine inc hl ;in register pair DE ld d,(hl) ex de,hl ;set up HL for the jump ld de,done ;get routine return address push de ;put it on the stack for RET instruction jp (hl) ;and jump to the requested routine erfun: ddmsg jp bypas1 ;no match - continue with next RSX ;----------------------------------- ;------ RSX control functions ------ ;----------------------------------- ;------ Provide an indication that the RSX is in memory and available ------ ; ; ARGLST: DB nn ;dummy parameter ; DB nn ;status 1 of the request (0CCh=ok, other=error) ; DB nn ;status 2 of the request (0CCh=ok, other=error) ; ;(both bytes must be equal) ; rsxtst: ld de,(spsave) ;retrieve second parameter address ld a,0CCh ;get a special status code inc de ;increment to first status byte ld (de),a ;and update the caller's status byte inc de ;increment to second status byte ld (de),a ;and update the c aller's status byte ret ;complete - return to caller ;------ Initialize the RSX environment for subsequent calls ------ ; ; This routine establishes the environment for all other calls to the RSX. ; The operation is completed only if the RSX is not in an initialized state. ; If the RSX is already initialized, the function is bypassed and an error ; status is passed back to the caller. ; ; ARGLST: DB nn ;dummy parameter ; DB nn ;status of the request (0=ok, other=error) ; rsxint: ld a,(iniflg) ;get the initialize indicator cp notinit ;is this a clean copy? jr nz,rsxin2 ;no - can't reinitialize, must use RESET ld de,(spsave) ;retrieve second parameter address inc de ;increment to status byte xor a ;get a zero ld (remov),a ;mark the RSX resident ld (de),a ;set status normal ld (iniflg),a ;and mark this RSX as open for business jr rsxin9 ;complete - exit rsxin2: ld de,(spsave) ;retrieve second parameter address inc de ;increment to status byte ld a,0FFh ;get an error code ld (de),a ;and let caller know we failed jr rsxin9 ;complete - exit rsxin9: ret ;all done - return to caller ;------ Disengage this RSX ------ ; ; ARGLST: DB nn ;dummy parameter ; DB nn ;status of the request (0=ok, other=error) ; rsxtrm: ld a,0FFh ld (iniflg),a ;reset the init flag to prevent further access ld (remov),a ;flag to drop this RSX on next warm boot ld de,(spsave) ;retrieve second parameter address inc de ;increment to status byte xor a ;get a zero ld (de),a ;set status normal ret ;finished with RSX function, return ;------ Set/Reset Debug Mode ------ ; ; ARGLST: DB nn ;00=no debug non-zero=debug on ; debflg: db 0 ;global debug flag (default = off) rsxdbg: ld de,(spsave) ;retrieve second parameter address ld a,(de) ;get argument ld (debflg),a ;update debug flag ret ;operation complete ;------ Bypass this RSX and pass control on to the next one ------ ; bypass: pop de ;restore stack condition bypas1: pop iy ;restore caller's environment pop ix pop hl pop de pop bc ddmsg ld sp,(stksav) ;restore caller's stack pointer jp next ;move on to next RSX ;------ Processing is complete - return to caller ------ ; done: xor a ;indicate to caller that we were here pop iy pop ix pop hl pop de pop bc ddmsg ld sp,(stksav) ;restore caller's stack pointer ret ;return to caller end 28!"9!!>2 0&+!0 [ (!ePWA8Q0G: x@!\w# (   L). )!h6# (*(.(!8}(*(Ww#>?> w#a{ |e}nƐ'@'ý7||}>"C ""*B"[R*"^#V#^#V#N#FO/o&9O/o&9!9(> (G!9 w#EMw}8"RB0 >RRR!+k = R!+k = !+k = !+k = !#k = !+k = T]KB!z> S>))0 = |  DMgo>jB0 7?= H<͡z5)<z {0Gɯgo|| }||/g}/o#}o&K[xAJSJDM!b"!6J"DM'oodo o} $yWj _}8(8J`9{T]=o`9y $͙ >" 8# }>(́ x }} ˸T}ٕ(0D= ,= (  0% , 7 R ?(88 x  - 8˸x   ͠ ,-xG} }م 9 .>#n0  = - nx  ,-(-˸G,- }ٕ? 9.>R 88 ?= u+-(> 08  8R ?x  , 78ƀ8ƀ8ox٨!دoGOW_gɷɷ|لg{ً_zيWyىOxوG|ٔg{ٛ_zٚWyٙOx٘Gxٸyٹzٺ{ٻ|ټx٨u xx( ?}ٽR }ց <( 7 = |٤g{٣_z٢Wy١Ox٠G 8͉ }x>"8}ƀ/ƀó ͙ - }0- ,}l˸k 8 ́ # x(͙ -k 8 -k 8, }l8;*!# ! >8# # 8---͙ ,,,-xGg?+2n*8t z~,->"x"$}.́  ,͙ ́ ! >,.-͙ o&0%͔,# ͙ }g }؉}颋.:}8c~I$I~L*.ٷx˸́ }0G,\<}͔,-(- ! >0 $# o8 Á >"m.`1pF,t6|!wS<.z}[|%FXc~ur1}ٯx(<˸k 8́ !~Jk 0ͺO!Z>k 8 =  ͙ # ͙ ́ ͺ͙ 0 - OT0 j oD,:j !I}袋.}8c~I$I~L!>8# # ͙ # = Ù nf^VNF!DLT\I!!53!r1!!> x #-= o˸x(-͙ }(x>8( , `i!>"| | >)=|(DMbo˸y88yx(0 8> x(>-q{(ay(oe z(>.q (o =e{>Eq>+|(|Dg>-q|/ 0:p# ~# +>0w#,-  60# ˸}րogM͇| .( = ~> x0w#xG% % ZJDM% = _~65(+~hìx-Sx9?+{Η@}|  gZJDM0 ,7}o˸ #yO!@9i&  #w#/w#w#!9! E9!!9~(+FM!"9!(#>2*u"|>":( E *6#w*6#6 !\$!u[ (W( #:~CONTRMKBDLSTAUXUSR>2ͭ*#~ u*:> >w###6Õ  #6++p>2Su:*6###ww#w$w#w: ͳ##N#F*B>w#w#[s#rò>2u*6 #-Nw#Fwq#p#6#w#w#w͞* :( Q: *^ F* < >26"~^*-w#ww#Ͳ^"~ <@*u!\  >2*|>! * \$\<(!: [1Á\!(f"́> 2:!"F( #~#6$>!"N>!~8>O6*"w (=(&("( :( 8y(~#ͽ7+ (6*#~́*#~ *~(h#"b=  8ͽ ̶J= B== ͯ}8= ͵}/l !*###~-_~(46*>2>*##w:>*##~*#~(E͋ ( ( ( ͕!] ( ( ((w#(͕́̕6!]~-#8~>7́ Õ͕>O*{͍̈́s #r*{/͍ d͋ ͕ (( #w(͕́̕q*#~ʶ (͕́ ͕ Õ*##~6[O*#~(08ʦ=ʦ==ʩ=ʬò+###~-_q46`>*:4^q}Q*|(|( 6-#Sy[R8 (G> QC~Q#*ͳyC!' !+TRUEFALSEy!9^#~#(G~Q#> Q> Q "F!(#R0ͳ*4#4>R *4 #4(Ͳ>>2*V(/˖:(#~+ x y!t( =( X:(R*:(###~-_-K< =>:("^"*^˞*V˖0 SѷR8A* N#F#s#r 0})jS\*###w* N#FB ^r+s>!T]>)j)0 0= R!#*^#V#N#F#^#V>">!2DM"~ʲx(L* :O(o:" C}=( ?*-N#Fp+qq#p! * F+N+++V+^Bq#p>>>SѷR* s#r$ s#r*"[R0s#r>"[^#VS!9[R8[R>O"w2x2!"" ͵*>2"!"""!\u*: ͭ!~6go(\R*s#r_2x( s x(T]DMR0 -a%Ù}Wo*!~6o&͠|ͣ}^C" User break1: I/O Run-time error e, PC=[R"` Program aborted*1!`!>#ͅ!"!ͱ@ @ Osborne Executive Screen CommandOO@ @ Rinaldo F. Prisco (315) 343-5343OO@ @ 1 = normal backgroundO@ @ 2 = dim backgroundO@ @ 3 = blinking backgroundO@ @ 4 = dim blinking backgroundO@ @ 5 = reverse backgroundO@ @ 6 = reverse dim backgroundO@ @ 7 = reverse blinking backgroundO@ @$ 8 = reverse dim blinking backgroundO@ @ 9 = underline backgroundO@ @10 = underline dim backgroundO@ @"11 = underline blinking backgroundO@ @&12 = underline dim blinking backgroundO@ @!13 = underline reverse backgroundO@ @%14 = underline reverse dim backgroundO@ @*15 = underline reverse blinking backgroundO@ @.16 = underline reverse dim blinking backgroundO@ @17 = quit programOOO*!$E;#!ͱ!=ͱ!! ͱ!! ͱ@ @Screen Selection: !ͭ*!$E8#!ͱ!xͱ*!/ͱ!ͱ!ͱ@ }"r @Screen Selection: !ͭ*!$Everse dim backgroundO@ @ 7 = reverse blinking backgroundO@ @$ 8 = reverse dim blinking backgroundO@ @ 9 = underline backgroundO@ @10 = underline dim backgroundO@ @"11 = underline blinking backgroundO@ @&12 = underline d1>A! >!P^@# 40 @>; SNAP A screen dump routine ; ;------ EQUATES ------------------------- ; ; BDOS LOCATIONS BOOT EQU 00 ;warmboot BDOS EQU 05 ;BDOS call ; ; PROGRAM CONSTANTS CR EQU 0Dh ;carraige return SCRN1 EQU 0A000H ;put the screen here in bank 1 SCRN8 EQU 0C000H ;the screen is here in bank 8 SCRNSIZ EQU 0CBFH-SCRN8 ;screen length SCRNWID EQU 80 ; 80 column wide screen SCRNLN EQU 24 ; 24 lines per screen ; ;---------------MACROS---------------------- ; ; ;;Bank switching macro ONE EQU 01H SEVEN EQU 41H EIGHT EQU 81H BANK MACRO NUMBER ;;Enable bank # MVI A,NUMBER OUT 0 ENDM ; BLKMOVE MACRO FROM,TO,LENGTH ;;Block move LXI H,FROM LXI D,TO LXI B,LENGTH DB 0EDH,0B0H ;z80 LDIR ENDM ;------------------------------------------------ ; MAIN ;------------------------------------------------ ORG 100H LXI SP,STAK ; BANK SEVEN ;enable screen BLKMOVE SCRN8,SCRN1,SCRNSIZ ;Move screen to bank 1 BANK ONE ;Back to bank one MVI B,SCRNLN ;B=lines LXI H,SCRN1 ;HL=adr of byte to print ;Loop for each line LINLOOP MVI C,SCRNWID ;C=columns ;Loop for each column COLOOP MOV E,M ;put char in E CALL LCHAR ;PRINT IT INX H ;next column DCR C ;decrment col count SUB A ; CMP C ; is it zero yet? JNZ COLOOP ;NO, not at end of line DCR B ;EOL - decrement line count CMP B ; is it zero yet? JZ EXIT ;YES - done LXI D,128-80 ;NO, skip over line extensions DAD D JMP LINLOOP ;Go do next line EXIT MVI E,CR ;End with CR CALL LCHAR CALL BOOT ; and out ; LCHAR PUSH B ;Save BC and HL PUSH H MVI C,05 ;List out CALL BDOS POP H ;restore POP B RET ; DS 64 ;Stack STAK DW 0 END ------- ; MAIN ;------------------------------------------------ ORG 100H LXI SP,STAK ; BANK SEVEN ;enable screen BLKMOVE SCRN8,SCRN1,SCRNSIZ ;Move screen to bank 1 BANK ONE ;Back to bank one MVI B,SCRNLN ;B=lines LXI H,SCRN1 ;HL=adr of# OF EXECUTIVE SCREEN DUMPS AND CLOCKS ------------------------------------ By Gordon Wilk An article in a recent issue of Foghorn showed how to print the screen of the OS-1. The screen in the Executive is also memory mapped and can be sent to the printer; however it is harder to do so since the screen is hidden away in bank seven of the memory. Since page 438 of the Executive Reference Manual tells how to switch banks, my first thought was to switch bank 7 in ( it only occupies locations C000-CFFF hex, well above where my program would load) and use CP/M3's BDOS function 112 (List Block) to print the screen. This did not work and my efforts may be informative to others. Function 112, List Block, would not have worked in any event since the internal screen is 128 columns wide of which only the first 80 are used. Unlike the OS-1 horizontal scrolling is entirely in software and the "invisible" columns are never used; actually they are filled with "U"s for some reason. Only the first 80 columns ever contain usable information. A more serious flaw in my plan was due to the fact that the Osborne BIOS does not play according to the rules when it switches banks, as it does on virtually every call. The bank switching method on page 438 of the Executive Reference Guide tells how to restore the banks to the state existing before the switch. The BIOS does not do this. Apparently it assumes that all calls originate from a user program in bank one and just restores bank one. Thus if one executes a BDOS call while bank 1 and 7 are active, the call will return with only bank one active. The first rule becomes: You cannot make BDOS calls while bank 7 or 8 is switched in! This also means that SID (and DDT) cannot be used while to trace programs during a bank switch (SID and DDT use BDOS calls to print information to the screen). This discovery led me to the plan of switching bank 7 in, moving the entire screen from C000-CFFF to A000-AFFF which lies in bank one even when bank 8 is switched in and then printing the moved screen image a line at a time. Here is the program that does it: ; SNAP A screen dump routine ; ;------ EQUATES ------------------------- ; ; BDOS LOCATIONS BOOT EQU 00 ;warmboot BDOS EQU 05 ;BDOS call ; ; PROGRAM CONSTANTS CR EQU 0Dh ;carraige return SCRN1 EQU 0A000H ;put the screen here in bank 1 SCRN8 EQU 0C000H ;the screen is here in bank 8 SCRNSIZ EQU 0CBFH-SCRN8 ;screen length SCRNWID EQU 80 ; 80 column wide screen SCRNLN EQU 24 ; 24 lines per screen ; ;---------------MACROS---------------------- ; ; ;;Bank switching macro ONE EQU 01H SEVEN EQU 41H EIGHT EQU 81H BANK MACRO NUMBER ;;Enable bank # MVI A,NUMBER OUT 0 ENDM ; BLKMOVE MACRO FROM,TO,LENGTH ;;Block move LXI H,FROM LXI D,TO LXI B,LENGTH DB 0EDH,0B0H ;z80 LDIR ENDM ;------------------------------------------------ ; MAIN ;----------------------------------------------- ORG 100H ;OMIT THESE TWO LINES FOR A SUBROUTINE LXI SP,STAK ; BANK SEVEN ;enable screen BLKMOVE SCRN8,SCRN1,SCRNSIZ ;Move screen to bank 1 BANK ONE ;Back to bank one MVI B,SCRNLN ;B=lines LXI H,SCRN1 ;HL=adr of byte to print ;Loop for each line LINLOOP MVI C,SCRNWID ;C=columns ;Loop for each column COLOOP MOV E,M ;put char in E CALL LCHAR ;PRINT IT INX H ;next column DCR C ;decrment col count SUB A ; CMP C ; is it zero yet? JNZ COLOOP ;NO, not at end of line DCR B ;EOL - decrement line count CMP B ; is it zero yet? JZ EXIT ;YES - done LXI D,128-80 ;NO, skip over line extensions DAD D JMP LINLOOP ;Go do next line EXIT MVI E,CR ;End with CR CALL LCHAR CALL BOOT ; and out *change to RET for a sub ; LCHAR PUSH B ;Save BC and HL PUSH H MVI C,05 ;List out CALL BDOS POP H ;restore POP B RET ; DS 64 ;Stack STAK DW 0 END The program is written to be assembled with the MAC macro assembler delivered with CP/M3 and makes use of the macro facilities to increase readability. The program begins after the "MAIN" heading. The two BANK macro invocations expand into the code needed to switch banks. The BLKMOVE macro provides a call using the Z80 LDIR opcode (here written as a DB) which performs the block move. The remainder of the code just prints out the first 80 characters of each 128 character line for the 24 lines of the screen. This code could have been written to run faster, but its execution is limited by the speed of the printer and there is no need for tight code. To use this program, type it with WordStar in the "N" mode into$ a file named "SNAPSHOT.ASM". Then assem- ble it with the cammand MAC SNAPSHOT. This will produce a .HEX file ( as well as .SYM and .PRN files) which must be converted to a .COM file with the command HEXCOM SNAPSHOT. After all this, turn your printer on, get something worthwhile on the screen and type SNAPSHOT . Once the program is running correctly, I suggest converting it into a subroutine which can be included in another program and called from within that program. As a subroutine the "A> SNAPSHOT " line need not appear in the printout. The conversion can be done by changing one line and omitting two others as shown in the listing. Another fine article in FOGHORN located the Executive's clock and showed how to access it. The clock referrred to in the article stored the date and time in hours, minutes and seconds, which is fine if all one wants is to read the time of day. On the other hand, if you want to time the running of a program and its subroutines, seconds are much too coarse a measure. C/80 and other languages include a profiler to do this; such profilers need a clock which counts sixtieths or smaller fractions of a second. There is such a clock in the Exec, but, you guessed it, it's not in bank one. The clock, two bytes that tick in milliseconds (approximately), is at location 23E8 hex in bank 8. Getting at it is an even harder job than getting at the screen. While the bank 7 only overlays high memory from C000 hex upward, bank 8 overlays the first 4k bytes of bank one. Any program trying to read or write in bank 8 must originate at a location higher than 4000 hex. While an independent program could easily be written to do this (using the ORG directive in MAC), what is needed for a program timer is a subroutine and there is no easy way of guaranteeing where a subroutine will link to a program written in a higher level language. The solution is to make use of CP/M+'s unique RSX feature. An RSX (Resident System Extension) is a program automatically loaded in high memory, just below the BDOS common memory which can then be called and used like a BDOS call. Writing an RSX is not actually hard, it just has more steps than needed with an ordinary program; once written an RSX can be used by programs written in any language allowing BDOS calls -- this includes Pascal and C amongst others. Here is the program. Type it with WordStar in "N" mode as a file called "TIME.ASM": ; TIME RSX ; Reads or sets the internal clock (tick) ; Usage: ; Assemble, HEXCOM and GENCOM this file to a NULL COM file ; Before using, load it by calling TIME ; ; In calling program ; To set clock to 00 call BDOS with DE = 0 ; To read clock call BDOS function 60 with DE > 0 ; ; RSX HEADER ; SERIAL DB 0,0,0,0,0,0 ;filled in by loader START JMP MAIN ;jump to start of program NEXT DB 0C3H ;JMP DW 0 ;filled in by loader PREV DW 0 ;ditto REM DB 0FFh ;Dump after one use ;This should be 0 if it is not to be ;deleted after on use NON DB 0 ;Always load NAM DB 'TIME ' ;Must be exactly 8 chars LOD DB 0,0,0 ;filled in by loader ; MAIN: MOV A,C ;Is this func 60 CPI 60 ; if not JNZ NEXT ; pass the call to next routine or BDOS MVI A,81H ;Switch Bank 8 in OUT 0 SUB A ;Does E = 0 ? CMP E ; JZ ZERO ; If so, go reset clock ; If not, LHLD 23E8H ;load clock bits JMP ONE ZERO LXI H,0 ;Store 00 in clock bytes SHLD 23E8H ONE MVI A,01 ;Switch back to Bank 1 OUT 0 MOV D,H ;DE=HL MOV E,L RET ;with clock in DE and HL END ; The equates labeled "RSX HEADER" is information needed by the loader to know this as an RSX and properly load it. The program just reads the clock bytes and returns with them in both the DE and HL registers. This routine actually violates the official conventions for RSX calls, but no harm is done as long as this is the calling program does not call any other RSX's via funtion 60. The official convention is that when function 60 is called the DE register should contain the address of a parameter block containing the addresses of the parameters. Since there is only one para- meter passed and returned, I passed them directly through the DE register; the return was duplicated in the HL register for the convenience of C/80 which expects parameters to be returned in HL. The following steps are needed to prepare the program: Assemble it with RMAC: RMAC TIME Link it as a Page Relocatable Program: LINK TIME [OP] Rename it an RSX: REN TIME.RSX=TIME.PRL Create a null program to load it: GENCOM TIM%E [NULL] Load it: TIME The program will now be loaded and remain in memory throughout the running of the next program executed. At the end of that program the RSX will automatically be erased. Now you need a program that will make the BDOS call and print out the clock so you can test the program. Unfortunately BASIC cannot make a BDOS call, though it could call an assembly language USR routine that did. For clarity, here is a simple C/80 program to make the call and print the results: #include "PRINTF.C" main() { static unsigned tick; while(1) /* Do forever */ { tick = clock(); /* Read the clock */ printf("\n\t%u",tick); /* Print it */ } } clock() { #asm LXI D,1 ; read clock MVI C,60 ; BDOS function 60 CALL 5 ; Call BDOS #endasm return; } This will continuously print the tick count until you stop it with a ^S ^C. In BASIC the "clock" function would have to written and assembled as a separate assembler program and then called by the USR function. In JRT Pascal, the call could be made direclty but the register data structure makes the program more complicated. Timer or profiler routines read the clock at entry to a routine then again at exit and subtract the two counts. The difference is the time spent in the routine. The times are cumulated for each call to the function and then printed on exit from the program. The CPROF.C program provided with C/80 is such a routine which can be easily modified to use this RSX by substituting BDOS calls for the references to TICCNT in the source code. When used as such a timer, this RSX has an accuracy of +/- 256 ticks. lls for the references to TICCNT in the so C,60 ; BDOS function 60 CALL 5 ; Call BDOS #endasm return; } Th This is the release date of the disk. KEYBD DOC JFNKEYS COM QFNKEYS DOC SKEYS COM ZKEYS DOC [ KEYS MAC _ SAVKEY COM cSETKEY COM dSET-SAVEDOC eSAVKEY ASM gSETKEY ASM lEXROM11 COM pEXROM11 DOC qPEEK COM rZEROMAKR.BAS EC 95 1792 14 NULL .COM CE 30 640 5 NULL .ASM 28 53 4224 33 OTHELLO .BAS 80 F8 21120 165 FREE30 .DOC AC 6B 3328 26 KEYBD .COM 15 01 2048 16 KEYBD .DOC EB B7 6784 53 FNKEYS .COM 1F 98 1792 14 FNKEYS .DOC 35 4F 6272 49 KEYS .COM 16 22 256 2 KEYS .DOC 33 F3 3200 25 KEYS .MAC FE E9 3328 26 SAVKEY  Fog Library Disk FOG-CPM.048 Copyright (1986) by Fog International Computer Users Group to the extent not copyrighted by the original author for the exclusive use and enjoyment of its members. Any reproduction or distribution for profit or personal gain is strictly forbidden. For information, contact FOG, P. O. Box 3474, Daly City, CA. 94015-0474. as part of the description of a file indicates that the program is distributed on a "try first, pay if you like it" basis. If you find the program(s) meet your need, please refer to the author's documentation for information on becoming a registered user. Only by registering and paying for the programs you like and use will the authors of such programs continue development. Often, more complete documentation, additional modules, and new releases are available only to registered users. Osborne Executive specific programs. Source is included for many of the programs so that they can be modified for other CPM+ computers. Filename Description -06-00 .86 This is the release date of the disk. -CPM048 .DOC This is the description of the disk contents. BUFEXEC .COM B562 2K [BUFEXEC 1 of 4] Two versions of a modem program written to support CompuServe protocol. BUFEXEC .DOC 3590 1K [BUFEXEC 2 of 4] BUFEXECR.COM 8480 5K [BUFEXEC 3 of 4] BUFEXECR.DOC DC13 1K [BUFEXEC 4 of 4] EXAUTO .ASM 46A3 4K ASseMbler source code for a replacement of the Osborne Executive EXECST program. GRAFTEST.BAS 46B0 2K Short demo to show screen graphics on the Executive VIDEO .BAS 40CF 5K MBasic menu-driven program which demonstrates the Osborne Executive video attributes. ZEROMAKR.COM 6EA8 14K [Zeromaker 1 of 3] Create a 0K file for use with catalog programs, etc. Inserts the dash (-) character automatically. MBasic source included. ZEROMAKR.DOC 5318& 2K [Zeromaker 2 of 3] ZEROMAKR.BAS EC95 2K [Zeromaker 3 of 3] NULL .COM CE30 1K [Null 1 of 2] Create a 0K file for use with catalog programs, etc. ASseMbler source code included. NULL .ASM 2853 5K [Null 2 of 2] OTHELLO .BAS 80F8 21K Mbasic game using Executive screen graphics. FREE30 .DOC AC6B 4K Discussion on how to implement correct disk space remaining on the Osborne Executive. KEYBD .COM 1501 2K ver. 2.0 [Keyboard 1 of 2] Redefinition program for the Osborne Executive. KEYBD .DOC EBB7 7K ver. 2.0 [Keyboard 2 of 2] FNKEYS .COM 1F98 2K ver. 2.1 [FunctionKeys 1 of 2] Allows Osborne Executive user to change function and arrow keys. Extends standard 256 bytes to 512 bytes available. FNKEYS .DOC 354F 7K ver. 2.1 [FunctionKeys 2 of 2] KEYS .COM 1622 1K [Keys 1 of 3] Prints Osborne Executive key definitions to screen or printer MAC source is included. KEYS .DOC 33F3 4K [Keys 2 of 3] KEYS .MAC FEE9 4K [Keys 3 of 3] SET-SAV .DOC 265B 2K [Set and Save Keys 1 of 5] Set arrow and function key settings and then save to a disk file. This allows you to easily switch between applications. ASseMbler source code is included. SETKEY .COM 44BB 1K [Set and Save Keys 2 of 5] SAVKEY .COM 4278 1K [Set and Save Keys 3 of 5] SETKEY .ASM 15C5 4K [Set and Save Keys 4 of 5] SAVKEY .ASM 82B3 5K [Set and Save Keys 5 of 5] EXROM11 .COM B949 1K ver. 1.1 [Executive ROM 1 of 2] Reads the Osborne Executive ROM from Bank 8 to a disk file. EXROM11 .DOC BAA8 1K ver. 1.1 [Executive ROM 2 of 2] PEEK .COM 6428 2K [PEEK 1 of 4] A programming debugging tool to display file related BDOS  accesses in CPM+. ASseMbler source code is included. PEEK .DOC 9B52 3K [PEEK 2 of 4] PEEK .ASM F1E4 3K [PEEK 3 of 4] PEEKBDOS.ASM DBF4 11K [PEEK 4 of 4] EXTONE1 .COM 7FDC 1K ver. 1.0 [Executive Tones 1 of 2] Demonstrates the noise generator of the Osborne Executive. ASseMbler source code is included. EXTONE1 .ASM 929E 3K ver. 1.0 [Executive Tones 2 of 2] RSXSEED .MAC CE15 11K Outline to allow you to build your own RSX for the Osborne Executive. EXECSCRN.COM DC3C 9K Menu-driven program to set screen attributes on the Osborne Executive. SNAPSHOT.COM 529B 1K [Snapshot 1 of 3] Screen dump routine for the Osborne Executive (see also PRTSCRN on FOG-CPM.038). ASseMbler source is included. SNAPSHOT.ASM 7CB4 2K [Snapshot 2 of 3] EXECESAY.TXT B663 12K [Snapshot 3 of 3]  [Set and Save Keys 2 of 5] SAVKEY'