tEXPZCPR3ASMEZCPR3 HEX+jEZCPR55 COM`sSYS ENV H)SYS FCPUSYS IOP" SYS RCP\SYSENV ASMWSYSFCP ASMsSYSFCP LIB.eSYSRCP ASMSYSRCP LIB.{<V40BIOS HEX+ABV40BIOS MAClu~Z3BASE LIB@Z3HDR LIBDZCPR3 HEX_+sjZCPR55 COMe`̇ COPYRIGHT (C) 1978, DIGITAL RESEARCH (  !"# $%&'o&)))))))a{__> ̓> ̓͊~̓#ÚO****!*$*'! ">2!4:(wNͯ>2:)!4f!^!*FNͷyj*DMͿ2: K!͚u b͊<2:\_/:)j*"*\<œ!w͕b2|\ ¢! DMͿ\ô!͕b!͕u AmA2Aͦ͊!͚u b͊2!>͚!͕u bA6mA2Aͦ!͕u b͊!6!>͚>ͦ͊!P͕SYSGEN VER 1.4SOURCE DRIVE NAME (OR RETURN TO SKIP)SOURCE ON , THEN TYPE RETURNDESTINATION DRIVE NAME (OR RETURN TO REBOOT)DESTINATION ON , THEN TYPE RETURNPERMANENT ERROR, TYPE RETURN TO IGNOREFUNCTION COMPLETEINVALID DRIVE NAME (USE A, B, C, OR D)NO SOURCE FILE ON DISKSOURCE FILE INCOMPLETE1!t͚:] Éz8O!B N#N ¾SP.* |} !9":q!"ͦ!q:_  !p+q.*   !q*&!p+q*2!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q*!1! !{ { ! 8COMSAVEJUMP]1y2ͳ͆y2ċ͸!12<2!"6'į2~;(1͌*~w# ·((~; #"":ʩ!Zʛ!~(#(>eWʛ!ZʘÐ/: :G(>2*"!"^2=!~(6#gÿ=\N  !͝>2"~(#"\Nl2(2>2:2K~2: /2(#Q( :>ѯ2~2> . # :K~!8 (#= >y* >?#?y#!4#~A8 @G:Kx:=x8=2>#~ ~ ( 8##~ ͺG:KxH:?x82Ků=#( #(  = ʹtG:Kx˜:?x82KG:Kx¯:=x82>ů~ :K(g PW?>  #~#͘6 þ #~# (+;ɯ > ï:dNo Fil> 6> _>(6\/m~#6  _2<\>_ ͱ!Ƕ2a{_/:A6:Ƿ( 8 >1606::6#~ 6!~!8 ͝>2":K(>}>>6 !~#͘6ַ  ~!8=_.:,<>¯Ʌo$~#!d~+ H(6!]~y(#8Wy888 88Oy0 0?7!] ~ (-H()08 80#OzW{_W{_}~2> ~2K=> :<=͋>ó:K! F#~(" # ~#fo###گ=͑>.6~#6 !͘~=`O> ͚Oͤo&!l\͝ -͙(+)z(͂\] \͞< ͖ ?(g AFN Erro\*͢dErase!]ͅ>?6'YͭO3: $:*:K2:>ŷ(=2͸^!/"!~(#p^"n͂>2ů2!~ :< ~:#~#2K/ 2=ͥ(ͣ(͐!>8!͂[ = >͋>ódFul=!>8!`9 = >i>ÑBFulC = >̓>ë\Ful=mșȥȫȱ"C{2!"E9"1A˯22!ty)K!G_^#V*Cʐ~ԃEԜԥԫ ,&-AGMS˛!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6 O͐  :˷E B 2>: ˷b# : ˷y! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #H: ! ˾ Hù H H $O͐: 2 *CN# x: 2 p&x~+é7ɯ2 H! >w_: ! ˾5ͤNkͱ¦ͱxʊ#Nx: ˷! ˖2 ͤ! 5™#wO~x½p Hy<< ַʑ :!qMD#2E>! ^#V w#P:BO|^#V#"##"##"##"!O*!O*|!6ʝ6>֯*w#w*w#w'û*ַ! J*""!N#F*^#V*~#foyx*{_zW+*yx#*DM*s#r*s#ryOxG*0MD!!N:շ EG>O: \̷S̀*C :շqn& ^#V>O^"*}:*)=":O:աo"*C *C!ͮ~2~2ͦ:զ2ͮ:̯O:Ձw:w |g}o*կ# ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:Յo$*C~i6iw**{#zr+s{ozg**͕** ;,w͜͸Ͳ!!N#F$**O!~#:A˾#~$=2Ek͌::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | sϖ-|N-# S:2E!~Яw>T D^6k-äPYy 5*{zBK5ڋ>*Cw~#+w#w+ɯ2E22i^ *C :շ~w~͔͔# #  w ~>2!E5T*C!"C"C!w# F! w͌xͯ2͢*C ~<wʃG:ՠ!զʎì 4~ʶ¬:<ʶ$ʶïZͻ̯x>2>2ͻ:!վZѯ2:E˷ẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C :շ:ddslO s#r:E˷͊:==»y==»*Ww#*"͸*:G#š"͸:!վw4!iw:Z!E~=26̯2*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!B˾w!>2*C~=2u:B2~2wE:A*C˶w>"!""կ2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*դW}_*"}o|g":շʑ*C6:շʑw:2E**E}DQ>26Ýâÿõçâ 1>>O|(A,!ط $ >( K<ͤ:O!6 BIOS: Boot Error2@2A22>2!"2!"~O0͢#_^#V#sV1iH{VM#!P5#5 > k#5 :YKiͳ*L*H|gzW>k66>kɞמ$؞cD؞גs( (?  !"# $%&' !"# $%&':AĬٯ2@:72;OG ڷ2B!y27yo&))))@C8y2?CF n&>2E>y2E2D2B:?<2:!@~6(7!; #:AĬ;!7:Cٯ2A:?o&)))))))*F:D >2A͔͔͆͆:E:B2Aͬ:B:  ڷ2B ڷ2B !;N#V##^!!!!!!>2BsN1x(((*(`Sz{N`Sz`Sz`)i (i ͆!p#q#{/w#z/w>2͔͆: ͔> ki8>k> k> k!/!*!:%!!:!:!!:>ɽۍްڠ'~ާܒ޵޶ކި~޽ލ޽ލޒޒ:>ɯ2(!5*F "x:/2xi( ::P(>2iO(0>k>k>(2PPPPG(yx _Ax Gx>>2R:Y>83!ր= =ɇ!_~#:(<2*w "͵#}!: ­yʧ:(Ϳ: 5y 58 0!P܇ɋܵܿ`:!́ !"J"L"H|g6 #*H#"H*J,}P :<2.| B$"J> k>2Q͋} *HP"H:<2:K 2KB<2Ke"H>2J*J}} :=2.O%-"J*H+"H:K=2K:=2*H"H*H|gyw͋:(:*LṔ*LP"L!u:K*LP@0 p`P@0>2 : (F((Q:S4y 0@2U>2 y P0-2T*T"Je*J&"HyY(=(~(5(6(2 ɯ2S>2 2S:/2hhۯ2 yK(k(_E(.D(.e:JO >PǴL:KO>OṔ 2 ɯ2 ͍(X͍XY͛(yXYͽ(@Ͷ(Oͽ@A(y@Ͷ((y@:(AAA2(@ A(@ : Ay@1!XY6|/G}/O! !- !@!K6!=6!?6!P>dh>k>28!"9>w`>BAAYY>NY>Y2>NA>A@@XX>2eH>k>k>kV>2ͤ!H"P!6#!>2O 55K ZCPR3 (Z80 Operating System) BIOS Version 4.0x14 [8702.08] WARNING!!! Unreleased BIOS. Z3ENV@  KPPB:`B:B:XRSH VAR Superbrain  =%+ %+ T)($ ADPIP STAT XDIR DIR A: DIR B: A:B:S *** disk not ready *** *** disk write protected *** *** record not found *** *** crc error *** *** lost data ***STARTUP ** lost data ***STARTUP COPYRIGHT (C) 1978, DIGITAL RESEARCH (  !"# $%&'o&)))))))a{__> ̓> ̓͊~̓#ÚO****!*$*'! ">2!4:(wNͯ>2:)!4f!^!*FNͷyj*DMͿ2: K!͚u b͊<2:\_/:)j*"*\<œ!w͕b2|\ ¢! DMͿ\ô!͕b!͕u AmA2Aͦ͊!͚u b͊2!>͚!͕u bA6mA2Aͦ!͕u b͊!6!>͚>ͦ͊!P͕SYSGEN VER 1.4SOURCE DRIVE NAME (OR RETURN TO SKIP)SOURCE ON , THEN TYPE RETURNDESTINATION DRIVE NAME (OR RETURN TO REBOOT)DESTINATION ON , THEN TYPE RETURNPERMANENT ERROR, TYPE RETURN TO IGNOREFUNCTION COMPLETEINVALID DRIVE NAME (USE A, B, C, OR D)NO SOURCE FILE ON DISKSOURCE FILE INCOMPLETE1!t͚:] Éz8O!B N#N ¾SP.* |} !9":q!"ͦ!q:_  !p+q.*   !q*&!p+q*2!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q*!1! !{ { ! 8COMSAVEJUMPI1y2~ͫ~y2yăͰw!12<2!"6į2~;(1x*~w# ·((~; #"":ʩ!Hʇ!~(#(>QEʇ!Hʄ|': :G(>2*"!"^2=!~(.#_ÿ=\N  !͋>2"~(#"\Nl2(2,2:~29~2: /2(#Q( :,ѯ2~2> . # :9~!8 (#= >g* >?#?g#!4#~A8 @G:Kx:=x8=2,#~ ~ ( 8##~ ͨG:KxH:?x829ů=#( #(  = ʹtG:Kx˜:?x829G:Kx¯:=x82,ů~ _ PW?>  #~#͆6 þ #~# (+;ɯ > ï:~\No Fil> .> _>(.\'e~#.  _2<\>_ ͩ!yǶ2a{_':yA.:~Ƿ( 8 >1.0.:y:.#~ .!~!8 ͋>2>>. !~#͆6ַ  ~!8=_.:,<>¯Ʌo$~#!d~+ H(6!]~g(#8Wy888 88Oy0 0?7!] ~ (-H()08 80#OzW{_W{_}~2, ~29+> :y<=̓>ë:K! F#~(  # ~#fo###ܯ=}>..~#. !͆~=`O> ͆=͒o&!l\͋͑(+)z(z\U \͖< ͂w ?(_ AFN Erro\͚\Erase!]q>?.Yͥ=3: $::92~:,ŷ(=2yͰ^!Ͱ'"!~(#pww^"Zz>2ů2!~ :y< ~:y8!zS = >̓>ë\Ful=̓((n!>8!`9 = >i>ÑBFulC = >̓>ë\Ful=mșȥȫȱ"C{2!"E9"1A˯22!ty)K!G_^#V*Cʐ~ԃEԜԥԫ ,&-AGMS˛!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6 O͐  :˷E B 2>: ˷b# : ˷y! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #H: ! ˾ Hù H H $O͐: 2 *CN# x: 2 p&x~+é7ɯ2 H! >w_: ! ˾5ͤNkͱ¦ͱxʊ#Nx: ˷! ˖2 ͤ! 5™#wO~x½p Hy<< ַʑ :!qMD#2E>! ^#V w#P:BO|^#V#"##"##"##"!O*!O*|!6ʝ6>֯*w#w*w#w'û*ַ! J*""!N#F*^#V*~#foyx*{_zW+*yx#*DM*s#r*s#ryOxG*0MD!!N:շ EG>O: \̷S̀*C :շqn& ^#V>O^"*}:*)=":O:աo"*C *C!ͮ~2~2ͦ:զ2ͮ:̯O:Ձw:w |g}o*կ# ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:Յo$*C~i6iw**{#zr+s{ozg**͕** ;,w͜͸Ͳ!!N#F$**O!~#:A˾#~$=2Ek͌::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | sϖ-|N-# S:2E!~Яw>T D^6k-äPYy 5*{zBK5ڋ>*Cw~#+w#w+ɯ2E22i^ *C :շ~w~͔͔# #  w ~>2!E5T*C!"C"C!w# F! w͌xͯ2͢*C ~<wʃG:ՠ!զʎì 4~ʶ¬:<ʶ$ʶïZͻ̯x>2>2ͻ:!վZѯ2:E˷ẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C :շ:ddslO s#r:E˷͊:==»y==»*Ww#*"͸*:G#š"͸:!վw4!iw:Z!E~=26̯2*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!B˾w!>2*C~=2u:B2~2wE:A*C˶w>"!""կ2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*դW}_*"}o|g":շʑ*C6:շʑw:2E**E}DQ>26Ýâÿõçâ 1>>O|(A,!ط $ >( K=ͤ:O!6 BIOS: Boot Error2A2B22>2!"2!"~O0͢#_^#V#sW1iH{WM#!Q5#5 > k#5 :YKiͳ*M*I|gzW>k66>kɞמ$؞cD؞גs( (?  !"# $%&' !"# $%&':BĬٯ2A:822F>y2F2E2C:@<2;!A~6(8!< #:BĬ2B͔͔͆͆:F:C2Bͬ:C:  ڷ2C ڷ2C !2CsO1x(((*(`Sz{O`Sz`Sz`)i (i ͆!p#q#{/w#z/w>2͔͆: ͔> ki8>k> k> k!/!*!:%!!:!:!!:>ɽۍްڠ'~ާܒ޵޶ކި~޽ލ޽ލޒޒ:>ɯ2(!5*F "x:/2xi( ::Q(>2iO(0>k>k>(2QPPPG(yx _Ax Gx>>2S:Y>83!ր= =ɇ!_~#:(<2*w "͵#}!: ­yʧ:(Ϳ:5y 58 0!P܇ɋܵܿ`:!́ !"K"M"I|g6 #*I#"I*K,}P :<2.| B$"K> k>2R͋} *IP"I:<2:L 2LB<2Le"I>2K*K}} :=2.O%-"K*I+"I:L=2L:=2*I"I*I|gyw͋:(:*MṔ*MP"M!u:L*MP@0 p`P@0>2 : (F((Q:T4y 0@2V>2 y P0-2U*U"Ke*K&"IyY(=(~(5(6(2 ɯ2T>2 2T:/2hhۯ2 yK(k(_E(.D(.e:KO >PǴL:LO>OṔ 2ɯ2͍(X͍XY͛(yXYͽ(@Ͷ(Oͽ@A(y@Ͷ((y@:(AAA2(@ A(@ : Ay@1!YZ6|/G}/O! !. !@!K6!=6!?6!P>dh>k>28!"9>w`>BAAYY>NY>Y2>NA>A@@XX>2eH>k>k>kV>2ͤ!I"P!6#!>2O 55K ZCPR3 (Z80 Operating System) BIOS Version 4.0x13 [8702.08] WARNING!!! Unreleased BIOS. Z3ENV@  KPPB:`B:B:XRSH VAR Superbrain *=%+ %+ T)($ ADPIP STAT XDIR DIR A: DIR B: A:B:S *** disk not ready *** *** disk write protected *** *** record not found *** *** crc error *** *** lost data ***STARTUP ** lost data ***STARTUP ;* Z3BASE ;**************************************************************** ;* * ;* Z3BASE.LIB -- BASE ADDRESSES FOR ZCPR3 SYSTEM ON INTERTEC * ;* WITH A 55K SYSTEM. * ;* * ;* THESE ADDRESSES ARE USED BY THE FOLLOWING SYSTEM * ;* SEGMENTS: * ;* * ;* SEGMENT FUNCTION * ;* ------- -------- * ;* BOOT BOOT SYSTEM FROM FLOPPY DISK * ;* BDOSZ CUSTOMIZED BDOS * ;* CBIOSZ CUSTOMIZED BIOS * ;* ZCPR3 ZCPR3 COMMAND PROCESSOR * ;* *.ENV ALL ENVIRONMENT DESCRIPTORS * ;* *.FCP ALL FLOW COMMAND PACKAGES * ;* *.IOP ALL INPUT/OUTPUT PACKAGES * ;* *.NDR ALL NAMED DIRECTORY DEFINITION FILES * ;* *.RCP ALL RESIDENT COMMAND PACKAGES * ;* * ;* * ;* MEMORY MAP OF SYSTEM: * ;* * ;* ADDRESS RANGE SIZE FUNCTION * ;* ------------- ------- -------- * ;* 0 - FF 256 B STANDARD CP/M BUFFERS EXCEPT * ;* 40 - 4A 11 B FOR ZCPR3 EXTERNAL PATH * ;* 4B 1 B WHEEL BYTE * ;* 100 - BFFF ~48 K TPA * ;* C000 - C805 2 K ZCPR3 COMMAND PROCESSOR * ;* C806 - D5FF 3.5K BDOSZ * ;* D600 - E3FF 3.5K CBIOSZ WITH BUFFERS * ;* E400 - EBFF 2 K RESIDENT COMMAND PACKAGE * ;* EC00 - F1FF 1.5K INPUT/OUTPUT PACKAGE * ;* F200 - F3FF 0.5K FLOW COMMAND PACKAGE * ;* F400 - F4FF 256 B MEMORY-BASED NAMED DIRECTORY * ;* F500 - F57F 128 B ZCPR3 SHELL STACK * ;* F580 - F5CF 80 B ZCPR3 MESSAGE BUFFERS * ;* BYTE 0: ERROR FLAG (Z/NZ) * ;* BYTE 1: IF (8 LEVELS) * ;* BYTE 2: IF ACTIVE (8 LEVELS) * ;* BYTE 3: Z3 CMD STATUS * ;* 00B - NORMAL * ;* 01B - SHELL * ;* 10B - ERROR * ;* BYTES 4&5: ERROR ADDRESS IF 10B * ;* BYTE 6: PROGRAM ERROR CODE * ;* BYTE 7: ZEX MESSAGE BYTE * ;* 00B - NORMAL * ;* 01B - Z3 PROMPT * ;* 10B - SUSPEND INTERCEPT * ;* BYTE 8: ZEX RUNNING FLAG (0=NO) * ;* BYTES 9-10: ADDRESS OF NEXT * ;* CHAR FOR ZEX TO RETURN * ;* BYTES 11-12: ADDRESS OF FIRST * ;* CHAR IN ZEX MEMORY- * ;* BASED FILE BUFFER * ;* BYTE 13: SH CONTROL BYTE * ;* BIT 0: ENABLE SHCMT * ;* BIT 1: ENABLE SHECHO * ;* BIT 7: ENABLE SHELL * ;* ENTRY WAIT * ;* BYTES 14-15: SHELL SCRATCH * ;* BYTES 10H-2FH: ERROR CMD * ;* BYTES 30H-39H: REGISTERS * ;* BYTES 3AH-3FH: RESERVED * ;* BYTES 40H-4FH: USER-DEFINED * ;* F5D0 - F5FF 48 B ZCPR3 EXTERNAL FCB * ;* F600 - F6FF 256 B ENVIRONMENT DESCRIPTORS * ;* BYTES 00H-7FH: Z3 PARAMETERS * ;* BYTES 80H-FFH: Z3 TERMINAL CAP * ;* F700 - F7CF 208 B MULTIPLE COMMAND LINE BUFFER * ;* F7D0 - F7FF 48 B ZCPR3 EXTERNAL STACK * ;* F800 - FFFF 2 K SCREEN BUFFER * ;* * ;**************************************************************** ;* ;* ZCPR3 BASE EQUATES ;* FALSE EQU 0 TRUE EQU NOT FALSE ; ; 1. VERSION NUMBERS, MEMORY SIZE, AND CP/M BASE ADDRESS ; ; THE FOLLOWING EQUATES DEFINE THE VERSION NUMBERS OF THE ZCPR3 ; COMMAND PROCESSOR AND THE CBIOSZ. THEY ALSO EXPLICITLY STATE THE SIZE ; OF THE TPA FOR INCLUSION IN THE CBIOSZ HEADER PRINTED AT COLD BOOT. ; Z3REV EQU 30 ; ZCPR3 REV NUMBER MSIZE EQU 55 ; 55K ZCPR system ; ; BASE - BASE ADDRESS OF USER'S CP/M SYSTEM (NORMALLY 0 FOR DR VERSION) ; THIS EQUATE ALLOWS EASY MODIFICATION BY NON-STANDARD CP/M (EG,H89) ; BASE EQU 0 ; ; 2. PROCESSOR SELECTION ; ; THE FOLLOWING EQUATE SELECTS THE USE OF THE 8080/8085 MICRO OR ; THE Z80 MICRO FOR THE TARGET FOR ZCPR3. NOTE THAT SELECTING THE ; 8080/8085 SHOULD BE DONE ONLY IF YOU HAVE AN 8080 OR 8085. IF YOU HAVE ; A Z80, BY ALL MEANS SELECT THIS ONE SINCE THE CODE IS MUCH SMALLER AND ; YOU CAN CRAM MORE FEATURES INTO THE SYSTEM AS A RESULT. ; IF THE PROCESSOR IS AN 8080 OR 8085, SET THIS EQUATE TO TRUE. ; IF THE PROCESSOR IS A Z80, SET IT TO FALSE. ; I8080 EQU FALSE ; ; 3. EXTERNAL PATH ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS OF THE ZCPR3 EXTERNAL ; PATH AND THE NUMBER OF TWO-BYTE ELEMENTS CONTAINED IN THIS PATH (MAXIMUM). ; IF THERE IS NO ZCPR3 EXTERNAL PATH, BOTH OF THESE VALUES SHOULD BE SET TO 0. ; EXPATH EQU 40H ; EXTERNAL PATH EXPATHS EQU 5 ; 5 2-BYTE PATH ELEMENTS ; (PATH SIZE = EXPATHS*2 + 1) ; ; 4. WHEEL BYTE ; ; THE FOLLOWING EQUATE DEFINES THE ADDRESS OF THE ZCPR3 WHEEL BYTE. ; IF THERE IS NO ZCPR3 WHEEL BYTE, THIS VALUE SHOULD BE SET TO 0. ; Z3WHL EQU 4BH ; WHEEL BYTE ADDRESS ; ; 5. CCP LOCATION ; ; THE FOLLOWING EQUATE DEFINES THE ADDRESS OF THE ZCPR3 COMMAND ; PROCESSOR. THIS ADDRESS MUST BE SUPPLIED. ; CCP EQU 0C000H ; ZCPR3 COMMAND PROCESSOR ; ; 6. RCP LOCATION ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS OF THE ZCPR3 RESIDENT ; COMMAND PACKAGE AND ITS SIZE IN 128-BYTE BLOCKS. IF THERE IS NO ; ZCPR3 RESIDENT COMMAND PACKAGE, BOTH OF THESE VALUES SHOULD BE 0. ; RCP EQU 0E400H ; RESIDENT COMMAND PACKAGE RCPS EQU 16 ; 16 128-BYTE BLOCKS (2K BYTES) ; ; 7. IOP LOCATION ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS OF THE ZCPR3 INPUT/OUTPUT ; PACKAGE AND ITS SIZE IN 128-BYTE BLOCKS. IF THERE IS NO ZCPR3 INPUT/OUTPUT ; PACKAGE, BOTH OF THESE VALUES SHOULD BE 0. ; IOP EQU 0EC00H ; REDIRECTABLE I/O PACKAGE IOPS EQU 12 ; 12 128-BYTE BLOCKS (1.5K BYTES) ; ; 8. FCP LOCATION ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS OF THE ZCPR3 FLOW COMMAND ; PACKAGE AND ITS SIZE IN 128-BYTE BLOCKS. IF THERE IS NO ZCPR3 FLOW COMMAND ; PACKAGE, BOTH OF THESE VALUES SHOULD BE 0. ; FCP EQU 0F200H ; FLOW COMMAND PACKAGE FCPS EQU 4 ; 4 128-BYTE BLOCKS (0.5K BYTES) ; ; 9. ENV LOCATION ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS OF THE ZCPR3 ENVIRONMENT ; DESCRIPTOR AND ITS SIZE IN 128-BYTE BLOCKS. IF THERE IS NO ZCPR3 ENVIRONMENT ; DESCRIPTOR, BOTH OF THESE VALUES SHOULD BE 0. ; Z3ENV EQU 0F600H ; ENVIRONMENT DESCRIPTORS Z3ENVS EQU 2 ; SIZE OF ENVIRONMENT DESCRIPTOR IN 128-BYTE BLOCKS ; ; 10. SHELL STACK ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS OF THE ZCPR3 SHELL STACK, ; THE NUMBER OF ENTRIES PERMITTED IN THE ZCPR3 SHELL STACK, AND THE SIZE ; OF EACH ENTRY IN THE SHELL STACK IN TERMS OF BYTES. IF THERE IS NO ZCPR3 ; SHELL STACK, ALL THREE VALUES SHOULD BE 0. ; SHSTK EQU 0F500H ; ZCPR3 SHELL STACK SHSTKS EQU 4 ; NUMBER OF SHSIZE-BYTE SHELL STACK ENTRIES SHSIZE EQU 32 ; SIZE OF A SHELL STACK ENTRY ; (STACK SIZE = SHSTKS * SHSIZE) ; ; 11. ZCPR3 MESSAGES ; ; THE FOLLOWING EQUATE DEFINES THE ADDRESS OF THE ZCPR3 MESSAGE BUFFER. ; THIS BUFFER IS ALWAYS 80 BYTES LONG. IF THERE IS NO ZCPR3 MESSAGE BUFFER, ; THIS ADDRESS SHOULD BE 0. ; Z3MSG EQU 0F580H ; ZCPR3 MESSAGE BUFFER ; ; 12. EXTERNAL FCB ; ; THE FOLLOWING EQUATE DEFINES THE ADDRESS OF THE ZCPR3 EXTERNAL FCB. ; THIS BUFFER IS ALWAYS 36 BYTES LONG. IF THERE IS NO ZCPR3 EXTERNAL FCB, ; THIS ADDRESS SHOULD BE 0. ; EXTFCB EQU 0F5D0H ; ZCPR3 EXTERNAL FCB ; ; 13. NAMED DIRECTORY BUFFER ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS AND SIZE (IN TERMS OF 18-BYTE ; ENTRIES) OF THE ZCPR3 NAMED DIRECTORY BUFFER. IF THERE IS NO SUCH BUFFER, ; BOTH OF THESE VALUES SHOULD BE 0. ; Z3NDIR EQU 0F400H ; ZCPR3 NAMED DIRECTORY AREA Z3NDIRS EQU 14 ; 14 18-BYTE NAMED DIRECTORY ELEMENTS PERMITTED ; (NDIR SIZE = Z3NDIRS*18 + 1 FOR TRAILING 0) ; ; 14. COMMAND LINE ; ; THE FOLLOWING EQUATES DEFINE THE ADDRESS AND SIZE (IN TERMS OF BYTES) ; OF THE ZCPR3 COMMAND LINE BUFFER (FORMERLY CALLED THE MULTIPLE COMMAND LINE ; BUFFER UNDER ZCPR2). IF THERE IS NO SUCH BUFFER, BOTH OF THESE VALUES SHOULD ; BE 0. ; Z3CL EQU 0F700H ; ZCPR3 COMMAND LINE BUFFER Z3CLS EQU 200 ; SIZE OF COMMAND LINE BUFFER ; ; 15. EXTERNAL STACK ; ; THE FOLLOWING EQUATE DEFINES THE ADDRESS OF THE ZCPR3 EXTERNAL STACK. ; THIS STACK IS ALWAYS 48 BYTES IN SIZE. IF THERE IS NO SUCH STACK, THIS ; VALUE SHOULD BE 0. ; EXTSTK EQU 0F7D0H ; ZCPR3 EXTERNAL STACK ; ; 16. USER EQUATES ; ; THE FOLLOWING EQUATES ARE AVAILABLE FOR THE IMPLEMENTER'S TARGET ; SYSTEM. THESE ARE IMPLEMENTATION-DEFINED. ; ;* ;* END OF ZCPR3 BASE EQUATES ;* ORG 100H ENV: JMP 0 ; Leading JMP ENV1: ; ZCPR3 enviornment descriptor ... DB 'Z3ENV' ; . Environment ID DB 1 ; . Class 1 environment (external) DW EXPATH ; . External path (PATH) DB EXPATHS ; DW RCP ; . Resident command package (RCP) DB RCPS ; DW IOP ; . Input/output package (IOP) DB IOPS ; DW FCP ; . Flow command package (FCP) DB FCPS ; DW Z3NDIR ; . Named directories (NDR) DB Z3NDIRS ; DW Z3CL ; . Command line (CL) DB Z3CLS ; DW Z3ENV ; . Environment (ENV) DB Z3ENVS ; DW SHSTK ; . Shell stack (SH) DB SHSTKS ; DB SHSIZE ; DW Z3MSG ; . Message buffer (MSG) DW EXTFCB ; . External FCB (FCB) DW EXTSTK ; . External stack (STK) DB 0 ; . Quiet flag (1=quiet, 0=not quiet) DW Z3WHL ; . Wheel byte (WHL) DB 4 ; . Processor speed (Mhz) DB 'P'-'@' ; . Max disk letter DB 31 ; . Max user number DB 1 ; . 1=ok to accept DU:, 0=not ok DB 0 ; . CRT selection DB 0 ; . Printer selection DB 80 ; . CRT 0: Width DB 24 ; # of lines DB 22 ; # of text lines DB 132 ; . CRT 1: Width DB 24 ; # of lines DB 22 ; # of text lines DB 80 ; . PRT 0: Width DB 66 ; # of lines DB 58 ; # of text lines DB 1 ; FF flag (1=can form feed) DB 96 ; . PRT 1: Width DB 66 ; # of lines DB 58 ; # of text lines DB 1 ; FF flag (1=can form feed) DB 132 ; . PRT 2: Width DB 66 ; # of lines DB 58 ; # of text lines DB 1 ; FF flag (1=can form feed) DB 132 ; . PRT 3: Width DB 88 ; # of lines DB 82 ; # of text lines DB 1 ; FF flag (1=can form feed) DB 'SH ' ; . Shell variable filename DB 'VAR' ; . Shell variable filetype DB ' ' ; . File 1 DB ' ' ; DB ' ' ; . File 2 DB ' ' ; DB ' ' ; . File 3 DB ' ' ; DB ' ' ; . File 4 DB ' ' ; DS 128-($-ENV) ; Make ENV 128 bytes long ENV2: ; Terminal capabilities data DB 'ADM-3A ' ; . Name of terminal (ADM 3A) DB ' ' ; . DB 'K'-'@' ; . Cursor up DB 'J'-'@' ; . Cursor down DB 'L'-'@' ; . Cursor right DB 'H'-'@' ; . Cursor left DB 10 ; . Clear screen delay DB 00 ; . Cursor motion delay DB 00 ; . Clear to EOL delay DB 'Z'-'@',0 ; . (CL) Clear screen string DB 1BH,'=%+ %+ ',0 ; . (CM) Cursor motion string DB 'E'-'@',0 ; . (CE) Clear to EOL string DB 'Q'-'@',0 ; . (SO) Start hilite string DB 'T'-'@',0 ; . (SE) End hilite string DB 'T'-'@',0 ; . (TI) Terminal init string DB 'Z'-'@',0 ; . (TE) Terminal de-init string DB 0 ; ENVEND: ; End of environment and TCAP descriptors CMDSET: DW Z3CL+4 ; Point to first chr in cmd line buf DB Z3CLS ; Command line buffer size PATH: ; Initial path description DB '$',0 ; . Current drive, user 0 DB 1,11 ; . Drive A:, user 11 DB 1,15 ; . Drive A:, user 15 DB 1,0 ; . Drive A:, user 0 DB 1,1 ; . Drive A:, user 1 DB 0 ; (end of path) ; Z3HDR - Minimum Configuration ; Offset: 4100H ************************************************************************* * * * Z C P R 3 -- Z80-Based Command Processor Replacement, Version 3.0 * * * * Copyright (c) 1984 by Richard Conn * * Copyright Pending, US Government * * All Rights Reserved * * * * ZCPR3 was written by Richard Conn, who assumes no responsibility * * or liability for its use. ZCPR3 is released to the CP/M user * * community for non-commercial use only. * * * * All registered users of CP/M are encouraged to freely copy and use * * ZCPR3 and its associated utilities on their registered systems for * * non-commercial purposes. * * * * Any commercial use of ZCPR3 is prohibited unless approved by the * * author, Richard Conn, or his authorized agent, Echelon, Inc, in * * writing. * * * * This is the RELEASE VERSION of ZCPR3. * * * ************************************************************************* ; ; Module: Z3HDR ; Author: Richard Conn ; Module Used By: ZCPR3 Version 3.x ; Note: Z3HDR contains the key customization equates for ZCPR3. These ; equates allow the user to select various ZCPR3 options and do an ; extensive amount of tailoring of ZCPR3 to the user's desires. ; ; ; 1. BASIC SYSTEM DEFINITIONS ; ; The following equates may be used to customize this CPR for the user's ; system and integration technique. The following equate are provided: ; ; REL - TRUE if integration is to be done via MOVCPM ; - FALSE if integration is to be done via DDT and SYSGEN ; ; CPRLOC - Base Page Address of CPR; this value can be obtained by running ; the CCPLOC program on your system, and if REL is FALSE, this ; value is supplied through the Z3BASE.LIB CCP equate ; REL EQU FALSE ; IF REL CPRLOC EQU 0 ELSE CPRLOC EQU CCP ;VALUE PROVIDED IN Z3BASE.LIB ENDIF ; ; 2. DEFAULT FILE TYPES ; ; The following macros define the file types of the command object files ; (COM files under CP/M 2.2) to be loaded when a non-resident ZCPR3 command ; is given and of the indirect command files (SUB files under CP/M 2.2) to ; be used to extract commands from when the indirect command facility is ; invoked. ; COMTYP MACRO DB 'COM' ENDM SUBTYP MACRO DB 'SUB' ENDM ; ; 3. SUBMIT FILE PROCESSING ; ; The following flag enables the ability of ZCPR3 to process ; SUBMIT files (command files of the form $$$.SUB). If SUBON is TRUE, then ; ZCPR3 will process such files like CP/M's CCP normally does; if SUBON is ; FALSE, ZCPR3 will not process such files (ignore them). In such a case, ; only indirect command file facilities like ZEX will work. Much code is ; saved inside of the ZCPR3 Command Processor if SUBON is set to FALSE, ; but this rather useful facility is lost. ; SUBON EQU FALSE ; ; 4. COMMAND PREFIX ; ; The following flag allows ZCPR3 to accept commands of the form ; "du:command params" or "dir:command params". If DRVPREFIX is TRUE, ; this form is accepted; if FALSE, this form is not accepted. ; DRVPREFIX equ TRUE ; ; 5. COMMAND ATTRIBUTES ; ; The following equate allows the user to select the attributes of the ; COM files which are selected for execution. The ZCPR3 Command Processor ; can be made to execute only COM files with the System attribute set, with ; the Directory (non-System) attribute set, or with either attribute set. ; The following values are defined for this equate: ; ; COMATT Files Selected ; 0 System ; 80H Directory ; 1 Both System and Directory ; COMATT equ 01H ; ; 6. ZCPR3 RESIDENT COMMAND ACTIVATION AND WHEEL FACILITY ; ; The following equates enable various ZCPR3-resident commands. ; The user may invoke these as desired, but should keep in mind the size ; of the resulting ZCPR3 and make sure it does not exceed the required ; limits. ; DIRON equ FALSE ;DIR COMMAND LTON equ FALSE ;LIST, TYPE COMMANDS GOON equ FALSE ;GO COMMAND ERAON equ FALSE ;ERA COMMAND SAVEON equ TRUE ;SAVE COMMAND RENON equ FALSE ;REN COMMAND GETON equ FALSE ;GET COMMAND JUMPON equ TRUE ;JUMP COMMAND NOTEON equ FALSE ;NOTE COMMAND ; ; The Wheel equate table enables the WHEEL facility of ZCPR3. With this ; facility, a WHEEL BYTE, which exists somewhere in memory, is examined ; before a set of installer-selected commands are executed. ; If this byte is not zero, then the command proceeds. If it is zero, ; then the command is not allowed to proceed and is exited with an error ; message. ; ; The following set of equates make each of the indicated commands ; selectable to respond to the Wheel Byte or not. For instance, if ; WERA=TRUE, then it responds to the Wheel Byte; if WERA=FALSE, it does not. ; IF Z3WHL NE 0 ;IF A WHEEL BYTE ADDRESS IS DEFINED WERA equ FALSE ;Make ERA a Wheel-Oriented Command WREN equ FALSE ; " REN " " " " WLT equ FALSE ; " L/T " " " " (LIST/TYPE) WGO equ FALSE ; " GO " " " " WSAVE equ TRUE ; " SAVE " " " " WGET equ FALSE ; " GET " " " " WJUMP equ TRUE ; " JUMP " " " " WDU equ FALSE ; " DU: " " " " (DU/DIR Change) WHEEL equ WERA OR WREN OR WLT OR WGO OR WSAVE OR WGET OR WJUMP OR WDU ENDIF ;Z3WHL ; ; 7. ZCPR3 RESIDENT COMMAND TABLE ; ; This table consists of the names of the various ZCPR3-resident ; commands and their addresses. The NCHARS equate defines how many ; characters long each name may be, and all table entries must be exactly ; the indicated number of characters (trailing spaces are used to fill ; out shorter names). ; ; Each table entry is structured as follows: ; ; DB 'CMND' ;Name of Command (NCHARS long) ; DB CMNDADR ;Address of Command within ZCPR3 ; ; The installer should only change the names of the commands as ; desired and should not, as a rule, touch the address definition since ; this is fixed within the body of ZCPR3. ; NCHARS EQU 4 ;NUMBER OF CHARS/COMMAND CTABLE MACRO ; IF DIRON DB 'DIR ' DW DIR ;DIRECTORY DISPLAY COMMAND ENDIF ; IF LTON DB 'LIST' DW LIST ;LIST FILE ON PRINTER COMMAND DB 'TYPE' DW TYPE ;TYPE FILE ON CONSOLE COMMAND ENDIF ; IF GOON DB 'GO ' DW GO ;EXECUTE CURRENT TPA COMMAND ENDIF ; IF ERAON DB 'ERA ' DW ERA ;ERASE FILES COMMAND ENDIF ; IF SAVEON DB 'SAVE' DW SAVE ;SAVE TPA COMMAND ENDIF ; IF RENON DB 'REN ' DW REN ;RENAME FILES COMMAND ENDIF ; IF GETON DB 'GET ' DW GET ;LOAD FILE INTO TPA COMMAND ENDIF ; IF JUMPON DB 'JUMP' DW JUMP ;JUMP TO ANY MEMORY LOCATION COMMAND ENDIF ; IF NOTEON DB 'NOTE' DW NOTE ;NOTE - NULL COMMAND (NOP) ENDIF ; ENDM ; ; 8. CONTROLS ON ZCPR3 RESIDENT COMMANDS ; ; The following sets of equates provide special controls and ; parameters on various ZCPR3-resident commands. ; ; ; The following equates set the width of the spacing between the ; file names for the DIR command and the character used to separate file ; names from one another on the same line. ; ; Assuming that FENCE is set to the character '|', If WIDE is TRUE, ; then the output will look like: ; ; filename.typ__|__filename.typ ... ; ; while if WIDE is FALSE, the output will look like: ; ; filename.typ_|_filename.typ ... ; ; (underscore represents a space) ; WIDE EQU TRUE FENCE EQU '|' ; ; The following equates define two flags which are used in ; conjunction with the DIR command on the command line. SYSFLG is ; the character used to indicate to DIR that all files, both System ; and Non-System, are to be displayed. SOFLG is the character used ; to indicate to DIR that only the System files are to be displayed. ; By default, DIR displays non-System files. ; ; For example, if SYSFLG is set to 'A' and SOFLG is set to ; 'S', then: ; DIR *.COM A ; ; displays all COM files with both System and non-System attributes ; while: ; DIR *.COM S ; ; displays only COM files with the System attribute. Naturally: ; ; DIR *.COM ; ; displays only COM files with the non-System attribute. ; SYSFLG EQU 'A' SOFLG EQU 'S' ; ; The following equate causes ERA to confirm the files to be erased ; before it goes ahead and erases them. If ERAOK is TRUE, then the user ; will be prompted each time; if it is FALSE, then the user will not be ; prompted. ; ERAOK equ FALSE ; ; If ERAOK is TRUE, the following equate adds a Verify option to the ; ERA command which causes the user to be prompted only if the Verify ; option letter, defined by ERDFLG, is given after the file name. If ; ERAV is TRUE, then the user will be asked to verify only when ERDFLG ; is contained in the command line; if ERAV is FALSE, the user will always ; be asked to verify. ; ; For example, if ERAOK is TRUE, ERAV is TRUE, and ERDFLG is 'V', ; then the command: ; ERA *.* V ; will result in the file names being displayed and the user being asked ; for verification. If the V option were not given, the user would not ; be asked for verification. ; ERAV equ FALSE ERDFLG equ 'V' ; ; The following equates set the paging parameters for the TYPE ; command. ; ; PGDFLT determines if TYPE pages by default. If PGDFLT is TRUE, ; then: ; TYPE FILE.TXT ; ; will be paged. If PGDFLT is FALSE, the above command will not be paged. ; ; PGDFLG defines the option character in the TYPE command line which ; is used to toggle the default set by PGDFLT. Assuming that PGDFLG is set ; to 'P', then: ; TYPE FILE.TXT P ; ; will page the file listing if PGDFLT is FALSE and not page it if PGDFLT is ; TRUE. ; PGDFLT EQU TRUE PGDFLG EQU 'P' ; ; The following equate defines the number of lines on the user's CRT ; screen for use by the TYPE command when it is paging. This value is usually ; 24. ; NLINES EQU 24 ; ; The following equate defines the option letter used with the ; SAVE command to indicate that the associated number is 128-byte sectors ; as opposed to 256-byte pages. For example, if SECTFLG is set to 'S', then: ; ; SAVE 25 FILE.BIN S ; ; save 25 128-byte sectors starting at location 100H into the file named ; FILE.BIN. IF the S option was not present, SAVE would have saved 25 ; 256-byte blocks starting at location 100H into the file named FILE.BIN. ; SECTFLG EQU 'S' ; ; 9. PATH DEFINITION ; ; The following equate specifies the address of the PATH to be followed ; for the PATH command-search if the PATH is to be initialized by the BIOS ; and set by the user via a PATH.COM program. The value of PATH should ; be the address of the PATH data area in memory. If the internal PATH ; provided by ZCPR3 is to be used, then PATHBASE should be equated to 0, ; which selects the PATH located just after the MEMLOAD routine. If the ; external PATH is to be used, then PATHBASE should be set to the address ; of the external path. ; ; A PATH is a series of byte-pairs, terminated by a binary 0. The first ; byte of each pair is the disk number (1-16 for disks A-P), and the second ; byte of each pair is the user number (0-31). The special character '$' ; indicates the current user or current disk. For example, the path ; from current disk/current user to current disk/user 0 to disk A/user 0 ; is selected by the following sequence: ; ; DB '$$' ;current disk/user ; DB '$',0 ;current disk/user 0 ; DB 1,0 ;disk A/user 0 ; DB 0 ;end of path ; IF EXPATH NE 0 ;External Path Selected ; ; This equate defines the base address of the external path ; PATH equ EXPATH ;External ZCPR3 PATH at CBIOS Buffer Area ELSE ;Internal Path Selected ; ; The following macro defines the n-element internal path ; IPATH MACRO db 'A'-'@','$' ;Disk A, Current User db 'A'-'@',0 ;Disk A, User 0 db 0 ;End of Path -- MUST be here ENDM ; ENDIF ; ; The following flag enables ZCPR3 to perform an optimized path ; search when it is searching along a path for a file. If this equate ; is TRUE, ZCPR3 will build a path in memory of absolute entries (A1, B7, etc) ; from the symbolic path (one containing '$') which is the path it would ; otherwise use. This new path would contain no duplicate path elements, ; where a symbolic path analysis may. For example, if the path is: ; ; db 'A'-'@','$' ;disk A, current user ; db 'A'-'@',15 ;disk A, user 15 ; db 0 ; ; then if the user is logged into A15, setting the below equate to TRUE ; would allow ZCPR3 to build the path: ; ; db 'A'-'@',15 ;only one entry ; db 0 ; ; in the analysis of this symbolic path, while with this equate FALSE, ; ZCPR3 may log into A15 as many as three times (once for the default ; and twice more for the symbolic path) in looking for a file which is ; not found before it gives up. Using this minimum path facility costs ; some code in ZCPR3, but it speeds up processing noticably in some cases. ; ; Enable this equate if MINIMUM PATH SEARCH is to be employed. ; MINPATH EQU TRUE ; ; In searching for a file along a path, ZCPR3 can be commanded ; to always look in the current logged-in directory before beginning ; the path search. This equate controls this feature. If SCANCUR ; is set to TRUE, the current directory need never be referenced in ; a symbolic path expression (DB '$','$') since SCANCUR insures that ; the current directory is scanned. ; ; Enable this equate if the current DU is always to be scanned. ; SCANCUR EQU TRUE ; ; 10. DU AND DIR CONTROLS ; ; ; The following equate enables the appearance of the current disk/user ; in the ZCPR3 prompt. If set to FALSE, the prompt appears as '>' (assuming ; > is the current value of CPRMPT). If set to TRUE, the prompt appears ; as 'd>' or 'dn>'. (see INCLNDR below) ; INCLDU equ TRUE ; ; The following equate allows ZCPR3 to accept the DU: prefix or ; login form for input. Set this to TRUE if DU: prefix is to be allowed. ; ; Setting this equate to TRUE allows the following forms: ; ; A>B1: ; A>TYPE B4:FILE.TXT ; A>B: ; A>1: ; ACCPTDU EQU TRUE ; ; This equate enables ZCPR3 to process DIR: forms internally ; through the memory-based named directory buffer. This equate and ; the NDBASE address should be TRUE (non-zero) in order to enable ; ZCPR3 to process named directories. ; ; If NDINCP is TRUE, the following forms are allowed: ; ; A>ROOT: ; A>TYPE TEXT:FILE.TXT ; ; if the other associated equates (below) are set correctly. ; NDINCP EQU TRUE ; ; The following equate will cause the name of the current directory ; to be displayed as part of the prompt along with the DU form if enabled. ; (see INCLDU above) ; ; For example, if INCLNDR is TRUE, the prompt would look like: ; ; B7:TEXT> -- if INCLDU is also TRUE ; TEXT> -- if INCLDU is FALSE ; INCLNDR EQU TRUE ; ; The following equate allows ZCPR3 to accept the DIR: prefix or ; login form for input. Set this to TRUE if DIR: prefix is to be allowed. ; ; Setting this equate to TRUE allows the following forms: ; ; A>ROOT: ; A>TYPE TEXT:FILE.TXT ; ACCPTND EQU TRUE ; ; The following equate determines the hierarchy of DU:/DIR: evaluation. ; Set this to TRUE if DU: is to be tested for before DIR: or set this to ; FALSE if DIR: is to be tested for before DU:. If this is FALSE, named ; directories like C: (standing for C work area - NOT disk C) are permitted. ; ; Assuming that a directory for C programs, named 'C', and a root ; directory, named 'ROOT', exist, then if DUFIRST is set to FALSE: ; ; A>C: -- logs the user into the directory named 'C' ; A>ROOT: -- logs the user into the directory named 'ROOT' ; ; while if DUFIRST is set to TRUE: ; ; A>C: -- logs the user into disk C: (dir C can't be accessed) ; A>ROOT: -- logs the user into the directory named 'ROOT' ; DUFIRST EQU FALSE ; ; Enable password check on named directory references. If a named ; directory is referenced and has a password associated with it, ZCPR3 ; will ask the user for this password and approve the reference only ; if he gives a valid response. One and only one try is permitted. ; Setting this equate to TRUE will enable the password check facility. ; PWCHECK EQU TRUE ; ; 11. COMMAND LINE BUFFER CONTROL ; ; The MULTCMD equate enables the feature of having more than ; one command on the same line, separated by a separation char ; which is defined by the CMDSEP equate. If this feature is ; enabled, the command line buffer and buffer pointers are ; moved outside of ZCPR3 at the indicated address of Z3CL. ; ; MULTCMD indicates if the ability to have more than one command ; on a line is to be enabled, and CMDSEP is the character used to separate ; these commands. For example, if CMDSEP is ';' and MULTCMD is TRUE, then ; commands like this are possible: ; ; ERA *.BAK;DIR ; IF Z3CL NE 0 MULTCMD equ TRUE ELSE MULTCMD equ FALSE ENDIF CMDSEP equ ';' ; ; 12. CMDRUN -- ZCPR3 EXTENDED COMMAND PROCESSING FACILITY ; ; This equate enables the ZCPR3 CMDRUN facility. If CMDRUN is TRUE, then ; another stage of command processing is invoked should ZCPR3 fail to find ; a COM file when the user gives a command. This stage involves invoking ; the COM file specified by CMDFCB and giving it the current command line ; as an argument. In this way, if, say, M80 PROG2 fails as a command, ; a new command like LRUNZ M80 PROG2, SUB M80 PROG2, or ZEX M80 PROG2 may ; be processed. If the new command fails, an appropriate error message is ; given. ; ; The ROOTONLY option causes ZCPR3 to only look at the Root (bottom of ; path) for the Extended Command Processor if it is set to TRUE. If it ; is set to FALSE, the path is searched for the Extended Command Processor. ; The tradeoff here is that ROOTONLY = TRUE is less flexible but somewhat ; faster than ROOTONLY = FALSE. ; CMDRUN equ FALSE ; Enable the Facility if CMDRUN ROOTONLY equ TRUE ; TRUE if look at Root Only for Extended ; Command Processor, FALSE if look along ; path CMDFCB MACRO db 0 db 'CMDRUN ' ;Name of Program db 'COM' ;File Type ENDM endif ;CMDRUN ; ; 13. FLOW COMMAND FACILITY ; ; This equate enables ZCPR3 to respond to IF processing. ; ZCPR3 simply flushes commands if a FALSE IF is currently engaged. ; FCPs must be enabled for IFON to work correctly. ; IFON EQU TRUE ; ; 14. MISCELLANEOUS EQUATES ; MAXUSR EQU 31 ;MAXIMUM USER NUMBER ACCESSABLE MAXDISK EQU 4 ;MAXIMUM NUMBER OF DISKS ACCESSABLE SUPRES EQU TRUE ;SUPRESSES USER # REPORT FOR USER 0 SPRMPT EQU '$' ;CPR PROMPT INDICATING SUBMIT COMMAND CPRMPT EQU '>' ;CPR PROMPT INDICATING USER COMMAND WPRMPT EQU '}' ;CPR PROMPT INDICATING WHEEL COMMAND NUMBASE EQU 'H' ;CHAR USED TO SWITCH FROM DEFAULT NUMBER BASE CURIND EQU '$' ;SYMBOL FOR CURRENT DISK OR USER COMMENT EQU ';' ;LINES BEGINNING WITH THIS CHAR ARE COMMENTS ; ; END OF ZCPR3 CUSTOMIZATION SECTION ; ;August 5, 1986 Version for Ampro Little Board RCPID EQU 'L' ;----------------------------------------------------------------------------- ; W H E E L E Q U A T E S WCP equ TRUE ;Make CP a Wheel-Oriented Command WDIR equ FALSE ; " DIR " " " " WERA equ TRUE ; " ERA " " " " WLIST equ TRUE ; " LIST " " " " WPEEK equ TRUE ; " PEEK " " " " WPOKE equ TRUE ; " POKE " " " " WPROT equ TRUE ; " PROT " " " " WREG equ TRUE ; " REG " " " " WREN equ TRUE ; " REN " " " " WTYPE equ FALSE ; " TYPE " " " " WHEEL set WCP OR WDIR OR WERA OR WLIST OR WPEEK OR WPOKE WHEEL set WHEEL OR WPROT OR WREG OR WREN OR WTYPE ;----------------------------------------------------------------------------- ; C O M M A N D E Q U A T E S CMDLEN EQU 4 ;length of command names HELPCMD MACRO ;help command name DB 'H ' ENDM ;------------------------------ CLEAR SCREEN CLSON EQU TRUE CLSCMD MACRO ;name for clear screen command DB 'CLS ' ENDM CLSTCAP EQU TRUE ;use TCAP for clear-screen string ;if CLSTCAP is false, the string below must be provided and ;it must end with a character with the high bit set CLSSTR MACRO DB 'L'-'@'+80H ;control-L to clear screen ENDM ;------------------------------ COPY COMMAND CPON EQU TRUE CPCMD MACRO ;name for copy command IF WCP DB 'C'+80h DB 'P ' ELSE DB 'CP ' ENDIF ENDM CPBLOCKS EQU 128 ;USE 16K FOR BUFFERING OF COPY COPYTOP EQU TRUE ;USE TOP OF TPA AS COPY BUFFER ;------------------------------ COPY COMMAND DIRON EQU TRUE DIRCMD MACRO ;name for directory command IF WDIR DB 'L'+80h DB 'S ' ELSE DB 'LS ' ENDIF ENDM SYSFLG EQU 'A' SOFLG EQU 'S' SORTNT EQU TRUE WIDE EQU TRUE FENCE EQU '|' ;------------------------------ ECHO COMMAND ECHOON EQU FALSE ECHOCMD MACRO ;name for echo command DB 'ECHO' ENDM ECHOLST EQU FALSE ;------------------------------ ERASE COMMAND ERAON EQU FALSE ERACMD MACRO ;name for erase command IF WERA DB 'E'+80h DB 'RA ' ELSE DB 'ERA ' ENDIF ENDM ;------------------------------ LIST AND TYPE COMMANDS LTON EQU TRUE TYPECMD MACRO ;name for type command IF WTYPE DB 'T'+80 DB 'YPE' ELSE DB 'TYPE' ENDIF ENDM LISTON EQU TRUE LISTCMD MACRO ;name for list command IF WLIST DB 'P'+80h DB 'RT ' ELSE DB 'PRT ' ENDIF ENDM PGDFLT EQU TRUE PGDFLG EQU 'P' NLINES EQU 24 ;------------------------------ NOTE COMMAND NOTEON EQU FALSE NOTECMD MACRO ;name for note command DB 'NOTE' ENDM ;------------------------------ PEEK COMMAND PEEKON EQU TRUE PEEKCMD MACRO ;name for peek command IF WPEEK DB 'P'+80h DB ' ' ELSE DB 'P ' ENDIF ENDM ;------------------------------ POKE COMMAND POKEON EQU TRUE POKECMD MACRO ;name for poke command IF WPOKE DB 'P'+80h DB 'OKE' ELSE DB 'POKE' ENDIF ENDM ;------------------------------ PROTECT COMMAND PROTON EQU FALSE PROTCMD MACRO ;name for protect command IF WPROT DB 'P'+80h DB 'ROT' ELSE DB 'PROT' ENDIF ENDM ;------------------------------ REGISTER COMMAND REGON EQU FALSE REGCMD MACRO ;name for register command IF WREG DB 'R'+80h DB 'EG ' ELSE DB 'REG ' ENDIF ENDM ;------------------------------ RENAME COMMAND RENON EQU TRUE RENCMD MACRO ;name for rename command IF WREN DB 'R'+80h DB 'EN ' ELSE DB 'REN ' ENDIF ENDM ;------------------------------ DISK RESET COMMAND RESON EQU TRUE ;reset disk system RESETCMD MACRO ;name for disk reset command DB 'R ' ENDM RESMSG EQU TRUE ;print disk reset message ;------------------------------ ERROR TESTING COMMAND TSTON EQU FALSE ;include program error testing TESTCMD MACRO ;name for error testing command DB 'TST ' ENDM TESTM80 EQU TRUE TESTF80 EQU FALSE TESTZAS EQU TRUE ;------------------------------ WHEEL COMMANDS WHLON EQU FALSE WHLCMD MACRO ;name for wheel setting command DB 'WHL ' ENDM WHLQCMD MACRO ;name for wheel query command DB 'WHLQ' ENDM WHLQUIET EQU TRUE ;don't report wheel state with WHL cmd WPASS MACRO DB 'SYSTEM ' ENDM ;----------------------------- ENABLE AND DISABLE COMMANDS ; ; X. ENA COMMAND ; TRANSIENT COUNTERPART: WHEEL ; ; The following equate determines if the ENA and DIS commands are made ; available. Setting this equate to TRUE enables them. ; ; The ENA and DIS commands are used to turn the Wheel byte on and off ; respectively. ENAble will turn on priveledges (if the correct password is ; entered) and DISable will turn it off. The state of the wheel byte is ; continously available by observing the ZCPR prompt. ; ; The syntax is: ; ; ENA -- make user non-priveleged ; PW? password -- password is not echoed. ; or: ; ENA password -- make user priveleged ; DIS -- make user non privledged ; EDON EQU TRUE ; ; The following equate defines the password to be used by the WHL and ENA ; commands. It must always be 8 bytes long (trailing spaces allowed) and ; must be upper-case. ; ENACMD MACRO DB 'ENA ' ; Enable Wheel ENDM DISCMD MACRO DB 'D'+80H db 'IS ' ; Disable Wheel ENDM WCRYPT EQU 0AAh WPASS MACRO DB 'T'-WCRYPT DB 'O'-WCRYPT DB 'O'-WCRYPT DB 'L'-WCRYPT DB 'S'-WCRYPT DB 'R'-WCRYPT DB 'U'-WCRYPT DB 'N'-WCRYPT ENDM  ************************************************************************* * * * Z C P R 3 -- Z80-Based Command Processor Replacement, Version 3.0 * * * * Copyright (c) 1984 by Richard Conn * * Copyright US Government * * All Rights Reserved * * * * ZCPR3 was written by Richard Conn, who assumes no responsibility * * or liability for its use. ZCPR3 is released to the CP/M user * * community for non-commercial use only. * * * * All registered users of CP/M are encouraged to freely copy and use * * ZCPR3 and its associated utilities on their registered systems for * * non-commercial purposes. * * * * Any commercial use of ZCPR3 is prohibited unless approved by the * * author, Richard Conn, or his authorized agent, Echelon, Inc, in * * writing. * * * * This is the RELEASE VERSION of ZCPR3. Dated: 21 Apr 84 * * * ************************************************************************* ; ; ZCPR3 -- CP/M Z80 Command Processor Replacement (ZCPR) Version 3.0 ; ; ZCPR3 is based upon ZCPR2 ; ;******** Structure Notes ******** ; ; ZCPR3 is divided into a number of major sections. The following ; is an outline of these sections and the names of the major routines ; located therein. ; ; Section Function/Routines ; ------- ----------------- ; ; -- Opening Comments, Equates, and Macro Definitions ; ; 0 JMP Table into ZCPR3 ; ENTRY ; ; 1 Buffers ; 1. Input Command Line and Default Command ; 2. File Type of COM File ; 3. SUBMIT File Control Block ; 4. Command File Control Block ; 5. Line Count Buffer ; 6. Resident Command Table ; ; 2 CPR Starting Modules ; CPR1 CPR RESTRT RS0 RS1 ; RS2 PARSER SCANNER DUSCAN DIRSCAN ; PASSCK SKSP TSTEOL INITFCB IFCB ; FILL PRNNF ; ; 3 Utilities ; CONIN CRLF CONOUT LCOUT LSTOUT ; PAGER READF READ BDOSB NOTE ; PRINTC PRINT PRIN1 GETDRV DEFDMA ; DMASET RESET BDOSJP LOGIN OPENF ; OPEN GRBDOS CLOSE SEARF SEAR1 ; SEARN SUBKIL DELETE GETUSR SETUSR ; ; 4 CPR Utilities ; SETUD UCASE PROMPT READBUF BREAK ; SDELM ADDAH LDIR NUMBER NUMERR ; HEXNUM FCBLOG SLOGIN WHLCHK CMDSER ; ; 5 CPR-Resident Commands and Functions ; 5A DIR DIRPR PRFN DIRPTR GETSBIT ; 5B ERA ; 5C LIST ; 5D TYPE ; 5E SAVE AMBCHK EXTEST ; 5F REN ; 5G JUMP ; 5H GO ; 5I COMDIR COM CALLPROG ; 5J GET MLOAD DLOGIN PRNLE PATH ; MPATH STACK PWLIN ; ; ; The following MACLIB statements load all the user-selected equates ; which are used to customize ZCPR3 for the user's working environment. ; MACLIB Z3BASE MACLIB Z3HDR ; CTRLC EQU 03H TAB EQU 09H LF EQU 0AH CR EQU 0DH ; WBOOT EQU BASE+0000H ;CP/M WARM BOOT ADDRESS UDFLAG EQU BASE+0004H ;USER NUM IN HIGH NYBBLE, DISK IN LOW BDOS EQU BASE+0005H ;BDOS FUNCTION CALL ENTRY PT TFCB EQU BASE+005CH ;DEFAULT FCB BUFFER TFCB2 EQU TFCB+16 ;2ND FCB TBUFF EQU BASE+0080H ;DEFAULT DISK I/O BUFFER TPA EQU BASE+0100H ;BASE OF TPA BIOS EQU CCP+0800H+0E00H ;BIOS Location ; $-MACRO ;FIRST TURN OFF THE EXPANSIONS ; ; MACROS TO PROVIDE Z80 EXTENSIONS ; MACROS INCLUDE: ; ; JR - JUMP RELATIVE ; JRC - JUMP RELATIVE IF CARRY ; JRNC - JUMP RELATIVE IF NO CARRY ; JRZ - JUMP RELATIVE IF ZERO ; JRNZ - JUMP RELATIVE IF NO ZERO ; DJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO ; PUTRG - SAVE REGISTERS ; GETRG - RESTORE REGISTERS ; ; @GENDD MACRO USED FOR CHECKING AND GENERATING ; 8-BIT JUMP RELATIVE DISPLACEMENTS ; @GENDD MACRO ?DD ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS IF (?DD GT 7FH) AND (?DD LT 0FF80H) DB 100H,?DD ;Displacement Range Error ELSE DB ?DD ENDIF ;;RANGE ERROR ENDM ; ; ; Z80 MACRO EXTENSIONS ; JR MACRO ?N ;;JUMP RELATIVE IF I8080 ;;8080/8085 JMP ?N ELSE ;;Z80 DB 18H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM ; JRC MACRO ?N ;;JUMP RELATIVE ON CARRY IF I8080 ;;8080/8085 JC ?N ELSE ;;Z80 DB 38H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM ; JRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY IF I8080 ;;8080/8085 JNC ?N ELSE ;;Z80 DB 30H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM ; JRZ MACRO ?N ;;JUMP RELATIVE ON ZERO IF I8080 ;;8080/8085 JZ ?N ELSE ;;Z80 DB 28H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM ; JRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO IF I8080 ;;8080/8085 JNZ ?N ELSE ;;Z80 DB 20H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM ; DJNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO IF I8080 ;;8080/8085 DCR B JNZ ?N ELSE ;;Z80 DB 10H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM ; PUTRG MACRO PUSH H ;;SAVE REGISTERS IN ORDER PUSH D PUSH B ENDM ; GETRG MACRO POP B ;;RESTORE REGISTERS IN ORDER POP D POP H ENDM ; ; END OF Z80 MACRO EXTENSIONS ; ; ;**** Section 0 **** ; ORG CPRLOC ; ; ENTRY POINTS INTO ZCPR3 ; ; IF MULTCMD (MULTIPLE COMMANDS ON ONE LINE) is FALSE: ; If ZCPR3 is entered at location CPRLOC (at the JMP to CPR), then ; the default command in CMDLIN will be processed. If ZCPR3 is entered ; at location CPRLOC+3 (at the JMP to CPR1), then the default command in ; CMDLIN will NOT be processed. ; NOTE: Entry into ZCPR3 at CPRLOC is permitted, but in order for this ; to work, CMDLIN MUST be initialized to contain the command line (ending in 0) ; and the C register MUST contain a valid User/Disk Flag ; (the most significant nybble contains the User Number and the least ; significant nybble contains the Disk Number). ; ; IF MULTCMD is TRUE: ; Entry at CPR or CPR1 has the same effect. Multiple command processing ; will still continue. ; ; If MULTCMD is FALSE, a user program need only load the buffer ; CMDLIN with the desired command line, terminated by a zero, in order to ; have this command line executed. If MULTCMD is TRUE, a user program must ; load this buffer as before, but he must also set the NXTCHR pointer to ; point to the first character of the command line. ; ; NOTE: ***** (BIG STAR) ***** Programs such as SYNONYM3 will fail if ; multiple commands are enabled, but this feature is so very useful that I ; feel it is worth the sacrifice. Some ZCPR3 utilities, like ALIAS and MENU, ; require multiple commands, and this feature also permits simple chaining ; of programs to be possible under the ZCPR3 environment. ; ; Enjoy using ZCPR3! ; Richard Conn ; ENTRY: JMP CPR ; Process potential default command JMP CPR1 ; Do NOT process potential default command ; ;**** Section 1 **** ; BUFFERS ET AL ; ; **** 1. INPUT COMMAND LINE AND DEFAULT COMMAND ; IF MULTCMD ;MULTIPLE COMMANDS ALLOWED? ; ; For Multiple Commands, the command line buffer (CMDLIN) is located external ; to ZCPR3 so that it is not overlayed during Warm Boots; the same is true ; for NXTCHR, the 2nd key buffer. BUFSIZ and CHRCNT are not important and ; are provided so the BDOS READLN function can load CMDLIN directly and ; a user program can see how much space is available in CMDLIN for its text. ; NXTCHR EQU Z3CL ;NXTCHR STORED EXTERNALLY (2 bytes) BUFSIZ EQU NXTCHR+2 ;BUFSIZ STORED EXTERNALLY (1 byte) CHRCNT EQU BUFSIZ+1 ;CHRCNT STORED EXTERNALLY (1 byte) CMDLIN EQU CHRCNT+1 ;CMDLIN STORED EXTERNALLY (long) BUFLEN EQU Z3CLS ;LENGTH OF BUFFER ; ELSE ; ; If no multiple commands are permitted, these buffers are left internal ; to ZCPR3 so that the original CCP command line facility (as used by ; programs like SYNONYM3) can be left intact. ; BUFLEN EQU 80 ;MAXIMUM BUFFER LENGTH BUFSIZ: DB BUFLEN ;MAXIMUM BUFFER LENGTH CHRCNT: DB 0 ;NUMBER OF VALID CHARS IN COMMAND LINE CMDLIN: DB ' ' ;DEFAULT (COLD BOOT) COMMAND DB 0 ;COMMAND STRING TERMINATOR DS BUFLEN-($-CMDLIN)+1 ;TOTAL IS 'BUFLEN' BYTES ; NXTCHR: DW CMDLIN ;POINTER TO COMMAND INPUT BUFFER ; ENDIF ;MULTCMD ; ; ; **** 2. FILE TYPE FOR COMMAND ; COMMSG: COMTYP ;USE MACRO FROM Z3HDR.LIB ; IF SUBON ;IF SUBMIT FACILITY ENABLED ... ; ; **** 3. SUBMIT FILE CONTROL BLOCK ; SUBFCB: DB 1 ;DISK NAME SET TO DEFAULT TO DRIVE A: DB '$$$' ;FILE NAME DB ' ' SUBTYP ;USE MACRO FROM Z3HDR.LIB DB 0 ;EXTENT NUMBER DB 0 ;S1 SUBFS2: DS 1 ;S2 SUBFRC: DS 1 ;RECORD COUNT DS 16 ;DISK GROUP MAP SUBFCR: DS 1 ;CURRENT RECORD NUMBER ; ENDIF ;SUBON ; ; **** 4. COMMAND FILE CONTROL BLOCK ; IF EXTFCB NE 0 ;MAY BE PLACED EXTERNAL TO ZCPR3 ; FCBDN EQU EXTFCB ;DISK NAME FCBFN EQU FCBDN+1 ;FILE NAME FCBFT EQU FCBFN+8 ;FILE TYPE FCBDM EQU FCBFT+7 ;DISK GROUP MAP FCBCR EQU FCBDM+16 ;CURRENT RECORD NUMBER ; ELSE ;OR INTERNAL TO ZCPR3 ; FCBDN: DS 1 ;DISK NAME FCBFN: DS 8 ;FILE NAME FCBFT: DS 3 ;FILE TYPE DS 1 ;EXTENT NUMBER DS 2 ;S1 AND S2 DS 1 ;RECORD COUNT FCBDM: DS 16 ;DISK GROUP MAP FCBCR: DS 1 ;CURRENT RECORD NUMBER ; ENDIF ;EXTFCB ; ; ; **** 5. LINE COUNT BUFFER ; IF LTON PAGCNT: DB NLINES-2 ;LINES LEFT ON PAGE ENDIF ;LTON ; ; **** 6. RESIDENT COMMAND TABLE ; EACH TABLE ENTRY IS STRUCTURED AS FOLLOWS: ; DB 'NAME' ;NCHARS LONG ; DW ADDRESS ;ADDRESS OF COMMAND ; CMDTBL: DB NCHARS ;SIZE OF TEXT IN COMMAND TABLE CTABLE ;DEFINE COMMAND TABLE VIA MACRO IN Z3HDR FILE DB 0 ;END OF TABLE ; ; ;**** Section 2 **** ; ZCPR3 STARTING POINTS ; ; START ZCPR3 AND DON'T PROCESS DEFAULT COMMAND STORED IF MULTIPLE COMMANDS ; ARE NOT ALLOWED ; CPR1: ; IF NOT MULTCMD ;IF MULTIPLE COMMANDS NOT ALLOWED ; XRA A ;SET END OF COMMAND LINE SO NO DEFAULT COMMAND STA CMDLIN ;FIRST CHAR OF BUFFER ; ENDIF ;NOT MULTCMD ; ; START ZCPR3 AND POSSIBLY PROCESS DEFAULT COMMAND ; ; NOTE ON MODIFICATION BY Ron Fowler: BDOS RETURNS 0FFH IN ; ACCUMULATOR WHENEVER IT LOGS IN A DIRECTORY, IF ANY ; FILE NAME CONTAINS A '$' IN IT. THIS IS NOW USED AS ; A CLUE TO DETERMINE WHETHER OR NOT TO DO A SEARCH ; FOR SUBMIT FILE, IN ORDER TO ELIMINATE WASTEFUL SEARCHES. ; CPR: LXI SP,STACK ;RESET STACK ; IF NOT MULTCMD ;ONLY ONE COMMAND PERMITTED LXI H,CMDLIN ;SET PTR TO BEGINNING OF COMMAND LINE SHLD NXTCHR ENDIF ;NOT MULTCMD ; PUSH B MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4) RAR ;EXTRACT USER NUMBER RAR RAR RAR ANI 0FH STA CURUSR ;SET USER CALL SETUSR ;SET USER NUMBER CALL RESET ;RESET DISK SYSTEM ; IF SUBON ;IF SUBMIT FACILITY ENABLED ; STA RNGSUB ;SAVE SUBMIT CLUE FROM DRIVE A: ; ENDIF ;SUBON ; POP B MOV A,C ;C=USER/DISK NUMBER (SEE LOC 4) ANI 0FH ;EXTRACT CURRENT DISK DRIVE STA CURDR ;SET IT CNZ LOGIN ;LOG IN DEFAULT DISK IF NOT ALREADY LOGGED IN CALL SETUD ;SET USER/DISK FLAG CALL DEFDMA ;SET DEFAULT DMA ADDRESS ; IF SUBON ;CHECK FOR $$$.SUB IF SUBMIT FACILITY IS ON ; LXI D,SUBFCB ;CHECK FOR $$$.SUB ON CURRENT DISK RNGSUB EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS THE RNGSUB FLAG ORA A ;SET FLAGS ON CLUE CNZ SEAR1 STA RNGSUB ;SET FLAG (0=NO $$$.SUB) ; ENDIF ;SUBON ; JR RS1 ;CHECK COMMAND LINE FOR CONTENT ; ; PROMPT USER AND INPUT COMMAND LINE FROM HIM ; RESTRT: LXI SP,STACK ;RESET STACK ; ; READ INPUT LINE FROM USER OR $$$.SUB ; RS0: ; IF Z3MSG NE 0 XRA A ;SET NO OUTPUT MESSAGE STA Z3MSG+3 ;ZCPR3 COMMAND STATUS INR A ;SET ZCPR3 INPUT PROMPT STA Z3MSG+7 ;ZEX MESSAGE BYTE ENDIF ;Z3MSG NE 0 ; LXI H,CMDLIN ;SET POINTER TO FIRST CHAR IN COMMAND LINE SHLD NXTCHR ;POINTER TO NEXT CHARACTER TO PROCESS MVI M,0 ;ZERO OUT COMMAND LINE IN CASE OF WARM BOOT PUSH H ;SAVE PTR CALL READBUF ;INPUT COMMAND LINE FROM USER (OR $$$.SUB) ; IF Z3MSG NE 0 XRA A ;NORMAL PROCESSING RESUMED STA Z3MSG+7 ;ZEX MESSAGE BYTE ENDIF ; POP H ;GET PTR MOV A,M ;CHECK FOR COMMENT LINE CPI COMMENT ;BEGINS WITH COMMENT CHAR? JRZ RS0 ;INPUT ANOTHER LINE IF SO ; ; PROCESS INPUT LINE; NXTCHR PTS TO FIRST LETTER OF COMMAND ; RS1: LXI SP,STACK ;RESET STACK ; ; RETURN TO CURRENT DIRECTORY AND POINT TO NEXT CHAR IN COMMAND LINE ; CALL DLOGIN ;RETURN TO CURRENT DIRECTORY LHLD NXTCHR ;PT TO FIRST CHAR OF NEXT COMMAND PUSH H ;SAVE PTR ; ; CAPITALIZE COMMAND LINE ; CAPBUF: MOV A,M ;CAPITALIZE COMMAND CHAR CALL UCASE MOV M,A INX H ;PT TO NEXT CHAR ORA A ;EOL? JRNZ CAPBUF POP H ;GET PTR TO FIRST CHAR IN LINE ; ; SET POINTER FOR MULTIPLE COMMAND LINE PROCESSING TO FIRST CHAR OF NEW CMND ; RS2: CALL SKSP ;SKIP OVER SPACES ORA A ;END OF LINE? JRZ RESTRT CPI CTRLC ;ABORT CHAR? JRZ RESTRT ; IF MULTCMD ;MULTIPLE COMMANDS ALLOWED? MOV A,M ;GET FIRST CHAR OF COMMAND CPI CMDSEP ;IS IT A COMMAND SEPARATOR? JRNZ RS3 INX H ;SKIP IT IF IT IS JR RS2 ENDIF ;MULTCMD ; RS3: SHLD NXTCHR ;SET PTR TO FIRST CHAR OF NEW COMMAND LINE SHLD CURCMD ;SAVE PTR TO COMMAND LINE FOR ERROR RETURN ; ; PARSE COMMAND LINE PTED TO BY HL ; CALL PARSER ;PARSE ENTIRE COMMAND LINE ; ; CHECK FOR SHELL INVOCATION AND RUN IT IF SO ; IF Z3MSG NE 0 LDA Z3MSG+3 ;GET COMMAND STATUS CPI 1 ;SHELL? JZ RS4 ENDIF ;Z3MSG NE 0 ; ; IF IFON AND FCP AVAILABLE, TRY TO RUN FROM FCP ; IF IFON AND (FCP NE 0) LXI H,FCP+5 ;PT TO COMMAND TABLE CALL CMDSCAN ;SCAN TABLE JZ CALLP ;RUN IF FOUND (NO LEADING CRLF) ENDIF ;IFON AND (FCP NE 0) ; ; IF IFON, THEN CHECK FOR RUNNING IF AND FLUSH COMMAND LINE IF ENABLED ; IF IFON LXI H,Z3MSG+1 ;PT TO IF BYTE MOV A,M ;GET IT ORA A ;SEE IF ANY IF JRZ RS4 ;CONTINUE IF NOT INX H ;PT TO IF ACTIVE BYTE ANA M ;SEE IF CURRENT IF IS ACTIVE JRZ RS1 ;SKIP IF NOT ENDIF ;IFON RS4: ; ; IF DIR: PREFIX, HANDLE AS COM FILE ; COLON EQU $+1 ;FLAG FOR IN-THE-CODE MODIFICATION MVI A,0 ;COMMAND OF THE FORM 'DIR:COMMAND'? ORA A ;0=NO JNZ COMDIR ;PROCESS AS COM FILE IF DIR: FORM ; ; CHECK FOR RESIDENT COMMAND ; CALL CMDSER ;SCAN FOR CPR-RESIDENT COMMAND JZ CALLP ;RUN CPR-RESIDENT COMMAND WITH NO LEADING CRLF ; ; CHECK FOR RESIDENT COMMAND PACKAGE ; IF RCP NE 0 LXI H,RCP+5 ;PT TO RCP COMMAND TABLE CALL CMDSCAN ;CHECK FOR RCP JZ CALLPROG ENDIF ; ; PROCESS AS COM FILE ; JMP COM ;PROCESS COM FILE ; ; ERROR PROCESSOR ; ERROR: ; IF SUBON ;IF SUBMIT FACILITY IS ON ; CALL SUBKIL ;TERMINATE ACTIVE $$$.SUB IF ANY ; ENDIF ;SUBON ; CALL CRLF ;NEW LINE ; IF Z3MSG NE 0 ;MESSAGES ENABLED? ; LDA Z3MSG+3 ;WAS ERROR CAUSED BY NO SHELL? ANI 1 ;BIT 0 SAYS ZCPR3 TRIED TO RUN A SHELL JRNZ ERRSH ;ABORT SHELL LDA Z3MSG ;GET ERROR HANDLER MESSAGE MOV B,A ;... IN B ORA A ;FLUSH AND RESUME? JRZ ERR0 MVI A,2 ;SET ERROR FLAG STA Z3MSG+3 ;IN SHELL STATUS BUFFER LHLD CURCMD ;PT TO BEGINNING OF ERROR SHLD Z3MSG+4 ;SAVE IN MESSAGE LXI H,Z3MSG+10H ;PT TO COMMAND LINE SHLD NXTCHR ;NEXT CHARACTER TO EXECUTE JMP RS1 ;RUN CONTENTS OF BUFFER ; ; CLEAR SHELL STACK AND RESTART COMMAND PROCESSING ; ERRSH: ; IF SHSTK NE 0 ;IF SHELL STACK AVAILABLE XRA A ;CLEAR SHELL STACK STA SHSTK ENDIF ; JMP RESTRT ;RESTART PROCESSING ERR0: ; ENDIF ;Z3MSG NE 0 ; CURCMD EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION LXI H,0 ;PT TO BEGINNING OF COMMAND LINE ERR1: MOV A,M ;GET CHAR ORA A ;END OF LINE? JRZ ERR2 CALL CONOUT ;PRINT COMMAND CHAR INX H ;PT TO NEXT CHAR JR ERR1 ;CONTINUE ERR2: CALL PRINT ;PRINT '?' DB '?'+80H ERR3: JMP RESTRT ;RESTART CPR ; ; PARSE COMMAND LINE PTED TO BY HL ; RETURN WITH NZ IF ERROR IN COMMAND NAME ; PARSER: ; ; INITIALIZE THE COMMAND AND TOKEN FCBS ; LXI D,FCBDN ;PT TO COMMAND FCB CALL INITFCB ;INIT IT LXI D,TFCB ;PT TO TOKEN FCB CALL INITFCB ;INIT IT ; ; EXTRACT COMMAND NAME ; LXI D,FCBDN ;PLACE COMMAND NAME INTO COMMAND FCB CALL SCANNER ;EXTRACT COMMAND NAME JRNZ ERROR ;ERROR RETURN ; ; CHECK FOR ERROR IN COMMAND NAME (FILE TYPE GIVEN) ; LXI D,FCBFT ;PT TO FILE TYPE LDAX D ;GET FIRST CHAR OF FILE TYPE CPI ' ' ;MUST BE BLANK, OR ERROR JRNZ ERROR ;ERROR RETURN ; ; SET TYPE OF COMMAND ; PUSH H ;SAVE PTR TO NEXT BYTE LXI H,COMMSG ;PLACE DEFAULT FILE TYPE (COM) INTO FCB MVI B,3 ;3 BYTES CALL LDIR POP H ;GET PTR TO NEXT BYTE ; ; SET DIR: PREFIX FLAG ; MYCOLON EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;PREVIOUS TOKEN CONTAINED A COLON? STA COLON ; ; SAVE POINTER TO COMMAND TAIL FOR LATER COPY INTO TBUFF AND FIND END OF ; COMMAND LINE; THIS IS ALSO THE ENTRY POINT FOR CMDRUN FACILITY TO ; PARSE THE ENTIRE COMMAND LINE AS A TAIL ; PARSET: SHLD TAILSV ;SAVE PTR TO COMMAND TAIL PUSH H ;SAVE PTR CTAIL: MOV A,M ;GET CHAR CALL TSTEOL ;AT EOL? JRZ CTAIL1 INX H ;PT TO NEXT JR CTAIL CTAIL1: SHLD NXTCHR ;SAVE PTR TO NEXT LINE POP H ;GET PTR TO COMMAND TAIL ; ; EXTRACT FIRST TOKEN ; CALL SKSP ;SKIP OVER SPACES RZ ;DONE IF EOL OR END OF COMMAND LXI D,TFCB ;STORE FIRST TOKEN IN TFCB CALL SCANNER ;EXTRACT TOKEN ; ; EXTRACT SECOND TOKEN ; CALL SKSP ;SKIP OVER SPACES RZ ;DONE IF EOL OR END OF COMMAND LXI D,TFCB+16 ;PT TO 2ND FCB AND FALL THRU TO SCANNER ; ; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCB PTED TO BY DE ; FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP) ; ON INPUT, HL PTS TO NEXT CHAR AND DE PTS TO FCB ; ON OUTPUT, HL PTS TO DELIMITER AFTER TOKEN AND ZERO FLAG IS RESET ; IF '?' IS IN TOKEN ; ; ENTRY POINTS: ; SCANNER - LOAD TOKEN INTO FCB PTED TO BY DE ; SCANNER: XRA A ;A=0 STAX D ;SET DEFAULT DRIVE STA MYCOLON ;SET NO COLON STA TEMPDR ;SET TEMPORARY DRIVE NUMBER TO DEFAULT STA QMCNT ;ZERO QUESTION MARK COUNTER LDA CURUSR ;GET CURRENT USER STA TEMPUSR ;SET TEMPUSR PUSH D ;SAVE PTR TO FIRST BYTE OF FCB MVI B,8 ;8 CHARS MAX CALL SCANF ;PLACE FIRST TOKEN INTO FILE NAME FIELD POP D ;GET PTR TO FIRST BYTE OF FCB MOV A,M ;GET TERMINATING CHAR STA ENDCHAR ;SET ENDING CHAR CPI ':' ;COLON? JRNZ SCAN1 ;NO, WE HAVE A FILE NAME STA MYCOLON ;SET COLON INX H ;PT TO CHAR AFTER COLON ; ; SCAN TOKEN FOR DIR: FORM, WHICH MEANS WE HAVE A USER/DISK SPECIFICATION ; HL PTS TO CHAR AFTER COLON ; IF (Z3NDIR NE 0) AND NDINCP ;NAMED DIRS AVAILABLE ; IF DUFIRST ;DU: BEFORE DIR: ; ; CHECK FOR DU: FORM ; IF ACCPTDU ;PERMIT DU: FORM PUSH D ;SAVE PTR TO FCB DN PUSH H ;SAVE PTR TO NEXT CHAR IN LINE CALL DUSCAN ;CHECK FOR DU: FORM POP H ;GET PTR TO NEXT CHAR POP D ;GET PTR TO FCB JRZ SUD1 ;GOT IT ENDIF ;ACCPTDU ; ; CHECK FOR DIR: FORM ; IF ACCPTND ;PERMIT DIR: FORM PUSH D ;SAVE PTR TO FCB PUSH H ;SAVE PTR TO NEXT CHAR CALL DIRSCAN ;CHECK FOR DIR: FORM POP H ;GET PTR TO NEXT CHAR POP D ;GET PTR TO FCB JRNZ SCAN1 ;ERROR IN PREFIX ENDIF ;ACCPTND SUD1: ; ELSE ;DIR: BEFORE DU: ; ; CHECK FOR DIR: FORM ; IF ACCPTND ;PERMIT DIR: FORM PUSH D ;SAVE PTR TO FCB PUSH H ;SAVE PTR TO NEXT CHAR CALL DIRSCAN ;CHECK FOR DIR: FORM POP H ;GET PTR TO NEXT CHAR POP D ;GET PTR TO FCB JRZ SUD1 ;GOT IT ENDIF ;ACCPTND ; ; CHECK FOR DU: FORM ; IF ACCPTDU ;PERMIT DU: FORM PUSH D ;SAVE PTR TO FCB DN PUSH H ;SAVE PTR TO NEXT CHAR IN LINE CALL DUSCAN ;CHECK FOR DU: FORM POP H ;GET PTR TO NEXT CHAR POP D ;GET PTR TO FCB JRNZ SCAN1 ;ERROR IN PREFIX ENDIF ;ACCPTDU SUD1: ; ENDIF ;DUFIRST ; ELSE ;DU ONLY ; ; CHECK FOR DU: FORM ; IF ACCPTDU ;ALLOW DU: FORM PUSH D ;SAVE PTR TO FCB DN PUSH H ;SAVE PTR TO NEXT CHAR IN LINE CALL DUSCAN ;CHECK FOR DU: FORM POP H ;GET PTR TO NEXT CHAR POP D ;GET PTR TO FCB JRNZ SCAN1 ;ERROR IN PREFIX ENDIF ;ACCPTDU ; ENDIF ;(Z3NDIR NE 0) AND NDINCP ; ; SET DRIVE REFERENCED ; LDA TEMPDR ;SET DRIVE STAX D ;... IN FCB ; ; REINIT FCB PTED TO BY DE ; PUSH D ;SAVE PTR INX D ;PT TO FN FIELD CALL IFCB ;ONLY PARTIAL INIT (17 BYTES TOTAL) POP D ; ; EXTRACT FILENAME FIELD ; XRA A STA QMCNT ;ZERO QUESTION MARK COUNTER PUSH D ;SAVE PTR TO FIRST BYTE OF FCB MVI B,8 ;8 CHARS MAX CALL SCANF ;STORE FILE NAME POP D ;GET PTR TO FIRST BYTE OF FCB MOV A,M ;GET OFFENDING CHAR STA ENDCHAR ;SET ENDING CHAR ; ; SKIP TO FILE TYPE FIELD ; HL PTS TO NEXT CHAR, DE PTS TO DN FIELD OF FCB ; SCAN1: ENDCHAR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;GET ENDING CHAR XCHG LXI B,8 ;PT TO BEFORE FILE TYPE FIELD OF FCB DAD B XCHG ; ; EXTRACT FILETYPE FIELD ; MVI B,3 ;PREPARE TO EXTRACT FILE TYPE CPI '.' ;IF '.', WE HAVE A TYPE JRNZ SCAN2 INX H ;PT TO CHAR AFTER '.' PUSH D CALL SCANF ;GET FCB FILE TYPE POP D SCAN2: ; ; SET USER NUMBER REFERENCED ; HL PTS TO NEXT CHAR, DE PTS TO BEFORE FCB FT ; XCHG LXI B,5 ;PT TO S1 FIELD DAD B XCHG LDA TEMPUSR ;STORE USER NUMBER HERE STAX D ; ; SKIP TO SPACE, CHAR AFTER =, OR EOL ; HL PTS TO NEXT CHAR IN LINE ; SCAN3: MOV A,M ;GET NEXT CHAR CPI ' '+1 ;DONE IF LESS THAN SPACE JRC SCAN4 CALL TSTEOL ;EOL? JRZ SCAN4 INX H ;PT TO NEXT CPI '=' ;EQUATE? JRNZ SCAN3 SCAN4: ; ; SET ZERO FLAG TO INDICATE PRESENCE OF '?' IN DIR:FILENAME.TYP ; QMCNT EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;NUMBER OF QUESTION MARKS ORA A ;SET ZERO FLAG RET ; ; SCANF -- SCAN TOKEN PTED TO BY HL FOR A MAX OF B BYTES; PLACE IT INTO ; FILE NAME FIELD PTED TO BY DE; EXPAND AND INTERPRET WILD CARDS OF ; '*' AND '?'; ON EXIT, DE PTS TO TERMINATING DELIMITER ; SCANF: CALL SDELM ;DONE IF DELIMITER ENCOUNTERED RZ INX D ;PT TO NEXT BYTE IN FCB CPI '*' ;IS (DE) A WILD CARD? JRNZ SCANF1 ;CONTINUE IF NOT MVI A,'?' ;PLACE '?' IN FCB AND DON'T ADVANCE HL IF SO STAX D CALL SCQ ;SCANNER COUNT QUESTION MARKS JR SCANF2 SCANF1: STAX D ;STORE FILENAME CHAR IN FCB INX H ;PT TO NEXT CHAR IN COMMAND LINE CPI '?' ;CHECK FOR QUESTION MARK (WILD) CZ SCQ ;SCANNER COUNT QUESTION MARKS SCANF2: DJNZ SCANF ;DECREMENT CHAR COUNT UNTIL 8 ELAPSED SCANF3: CALL SDELM ;8 CHARS OR MORE - SKIP UNTIL DELIMITER RZ ;ZERO FLAG SET IF DELIMITER FOUND INX H ;PT TO NEXT CHAR IN COMMAND LINE JR SCANF3 ; ; INCREMENT QUESTION MARK COUNT FOR SCANNER ; THIS ROUTINE INCREMENTS THE COUNT OF THE NUMBER OF QUESTION MARKS IN ; THE CURRENT FCB ENTRY ; SCQ: PUSH H ;SAVE HL LXI H,QMCNT ;GET COUNT INR M ;INCREMENT POP H ;GET HL RET ; ; SCAN FOR AND EXTRACT DISK/USER INFO ASSUMING DU: FORM ; ON ENTRY, DE PTS TO FIRST BYTE OF FCB CONTAINING POSSIBLE DU FORM ; ON EXIT, ZERO FLAG SET MEAN OK AND TEMPDR AND TEMPUSR SET ; IF ACCPTDU ;ALLOW DU: FORM DUSCAN: XCHG ;PTR IN HL INX H ;PT TO FIRST BYTE OF FN MOV A,M ;GET FIRST CHAR CPI 'A' ;CONVERT POSSIBLE DRIVE SPEC TO NUMBER JRC DUS1 ;IF LESS THAN 'A', MUST BE DIGIT ; ; SET DISK NUMBER (A=1) ; SUI 'A'-1 ;CONVERT DRIVE NUMBER TO 1-16 ; ; BYE PATCH ADDED HERE ; IF WHEEL mov b,a ; SAVE THE A REG. lda Z3WHL ; CHECK IF WE'RE A WHEEL ora a mov a,b ; RESTORE THE A REG. jnz SKPMAX ELSE mov b,a ; PUT IT IN REG B ENDIF lda 003Dh ; GET MAX DRIVE dcr b ; OFFSET BY ONE TO AGREE cmp b ; WITHIN RANGE? inr b ; SET IT BACK TO WHAT IT WAS mov a,b ; RESTORE DRIVE NUMBER TO A jrc DUSE1 ;INVALID DISK NUMBER ; ; END OF BYE PATCH ; ;** CPI MAXDISK+1 ;WITHIN RANGE? ;** JRNC DUSE1 ;INVALID DISK NUMBER SKPMAX: STA TEMPDR ;SET TEMPORARY DRIVE NUMBER INX H ;PT TO NEXT CHAR MOV A,M ;SEE IF IT IS A SPACE CPI ' ' RZ CALL DIGCK ;CHECK FOR DIGIT RC ; ; SET USER NUMBER ; DUS1: PUSH H ;SAVE PTR TO DIGITS MVI B,2 ;UP TO 2 DIGITS DUS1A: MOV A,M ;CHECK FOR DIGIT OR SPACE CPI ' ' ;IF SPACE, THEN NO DIGIT JRZ DUS2 CALL DIGCK ;CHECK FOR DIGIT JRC DUSE INX H DJNZ DUS1A ;COUNT DOWN MOV A,M ;3RD CHAR CPI ' ' ;MUST BE SPACE JRNZ DUSE DUS2: POP H CALL NUM0A ;GET NUMBER ; ; BYE PATCH ADDED HERE ; IF WHEEL mov b,a ; SAVE OUR A REG. lda Z3WHL ; CHECK IF WE'RE A WHEEL ora a mov a,b ; RESTORE THE A REG. jnz SKPWHL2 ELSE mov b,a ; PUT IT IN REG B ENDIF lda 003Fh ; GET MAX USER NUMBER sui 1 ; CORRECT OFFSET cmp b ; IS IT WITHIN RANGE? mov a,b ; RESTORE USER NUMBER IN A jrc DUSE1 ; UNALLOWED USER NUMBER ; ; END OF BYE PATCH ; ;** CPI MAXUSR+1 ;WITHIN LIMIT? ;** JRNC DUSE1 SKPWHL2: STA TEMPUSR ;SAVE USER NUMBER XRA A ;SET OK RET DUSE: POP H ;CLEAR STACK DUSE1: XRA A DCR A RET ; ENDIF ;ACCPTDU ; IF (Z3NDIR NE 0) AND NDINCP AND ACCPTND ; ; SCAN FOR DIR FORM ; ON ENTRY, DE PTS TO FCB CONTAINING NAME TO CHECK FOR ; ON EXIT, IF FOUND, Z AND TEMPUSR AND TEMPDR SET ; DIRSCAN: XCHG ;PTR IN HL INX H ;PT TO FN LXI D,Z3NDIR ;PT TO FIRST ENTRY IN MEMORY-BASED DIR DIRS1: LDAX D ;GET NEXT CHAR ORA A ;ZERO IF END OF DIR JRZ DIRSERR INX D ;PT TO DIR NAME INX D PUSH H ;SAVE PTR TO FILE NAME PUSH D ;SAVE PTR TO DIR ENTRY MVI B,8 ;MATCH? DIRS2: LDAX D ;GET BYTE CMP M ;COMPARE JRNZ DIRS3 INX H ;PT TO NEXT INX D DJNZ DIRS2 ;COUNT DOWN DIRS3: POP D ;RESTORE REGS POP H JRZ DIRS4 XCHG ;ADVANCE TO NEXT ENTRY LXI B,16 ;8 BYTES FOR NAME + 8 BYTES FOR PASSWORD DAD B XCHG JR DIRS1 ; ; NO DIR match ; DIRSERR: XRA A ;RETURN NZ DCR A RET ; ; DIR match ; DIRS4: ; IF PWCHECK PUSH D ;SAVE PTR TO DE LXI B,8 ;PT TO PW XCHG ;HL PTS TO ENTRY DAD B CALL PASSCK ;CHECK FOR PW POP D ;GET PTR JNZ DIRSERR ENDIF ;PWCHECK ; DCX D ;PT TO USER LDAX D ;GET USER ; ; BYE PATCH ADDED HERE ; IF WHEEL mov b,a ; SAVE THE A REG. lda Z3WHL ; CHECK IF WE'RE A WHEEL ora a mov a,b ; RESTORE THE A REG. jnz SKPMAX3 ELSE mov b,a ; PUT IT IN REG B ENDIF lda 003Fh ; GET MAX USER AREA sui 1 ; OFFSET BY ONE TO AGREE cmp b ; WITHIN RANGE? mov a,b ; RESTORE DRIVE NUMBER TO A jrc dirserr ;INVALID DISK NUMBER ; ; END OF BYE PATCH ; SKPMAX3: STA TEMPUSR DCX D ;PT TO DISK LDAX D ;GET IT ; ; BYE PATCH ADDED HERE ; IF WHEEL mov b,a ; SAVE THE A REG. lda Z3WHL ; CHECK IF WE'RE A WHEEL ora a mov a,b ; RESTORE THE A REG. jnz SKPMAX4 ELSE mov b,a ; PUT IT IN REG B ENDIF lda 003Dh ; GET MAX DRIVE dcr b ; OFFSET BY ONE TO AGREE cmp b ; WITHIN RANGE? inr b ; SET IT BACK TO WHAT IT WAS mov a,b ; RESTORE DRIVE NUMBER TO A jrc dirserr ;INVALID DISK NUMBER ; ; END OF BYE PATCH ; SKPMAX4: STA TEMPDR ;A=1 XRA A ;SET Z RET ; ENDIF ;(Z3NDIR NE 0) AND NDINCP AND ACCPTND ; IF PWCHECK ; ; CHECK FOR PASSWORD PTED TO BY HL ; RETURN WITH ZERO FLAG SET IF MATCH ; PASSCK: MOV A,M ;CHECK FOR NO PW CPI ' ' RZ IF Z3WHL ; DO WE HAVE WHEEL LDA Z3WHL ; LOAD A FROM WHEEL BYTE ORA A ; SEE IF IT IS NON ZERO JRZ PASSCK2 ; IF IT IS THEN CHECK PASSWORD XRA A ; ELSE CLEAR A (FORCE MATCH) RET ; RETURN WITH 0 SET ENDIF ; WHEEL AND PASSWORD CHECK PASSCK2: PUSH H ;SAVE PTR CALL PRINT DB CR,LF,'PW?',' '+80H LXI D,PWLIN MVI A,9 ;SET CHAR COUNT STAX D MVI C,10 ;BDOS READLN PUSH D CALL BDOS POP H ;GET PTR TO BUFFER INX H ;PT TO CHAR COUNT MOV A,M ;GET CHAR COUNT INX H ;PT TO FIRST CHAR PUSH H ;SAVE PTR CALL ADDAH ;HL PTS TO AFTER LAST CHAR MVI M,' ' ;PLACE SPACE POP D ;PT TO USER INPUT POP H ;PT TO PASSWORD MVI B,8 ;8 CHARS MAX PWCK: LDAX D ;GET NEXT CHAR CALL UCASE ;CAPITALIZE USER INPUT CMP M ;COMPARE FOR MATCH RNZ ;NO MATCH CPI ' ' ;DONE? RZ INX H ;PT TO NEXT INX D DJNZ PWCK XRA A ;SET ZERO FLAG RET ; ENDIF ;PWCHECK ; ; SKIP OVER SPACES PTED TO BY HL ; ON RETURN, ZERO FLAG SET MEANS WE HIT EOL OR CMDSEP ; SKSP: MOV A,M ;GET NEXT CHAR INX H ;PT TO NEXT CPI ' ' ;SPACE? JRZ SKSP DCX H ;PT TO NON-SPACE ; ; CHECK TO SEE IF CHAR IN A IS EOL OR CMDSEP ; TSTEOL: ORA A ;EOL? ; IF MULTCMD ;MULTIPLE COMMANDS SUPPORTED? RZ ;RETURN WITH FLAG CPI CMDSEP ;COMMAND SEPARATOR? ENDIF ;MULTCMD ; RET ; ; INIT FCB PTED TO BY DE ; INITFCB: XRA A STAX D ;SET DEFAULT DISK (DN BYTE IS 0) INX D ;PT TO FILE NAME FIELD CALL IFCB ;FILL 1ST PART OF FCB; FALL THRU TO IFCB TO RUN AGAIN ; ; FILL FN, FT, EX, S1, S2, RC, AND FOLLOWING CR (OR DN) FIELDS ; IFCB: MVI B,11 ;STORE 11 SPACES MVI A,' ' CALL FILL XRA A STAX D ;SET EX TO ZERO INX D LDA CURUSR STAX D ;SET S1 TO CURRENT USER INX D MVI B,3 ;STORE 3 ZEROES XRA A ;FALL THRU TO FILL ; ; FILL MEMORY POINTED TO BY DE WITH CHAR IN A FOR B BYTES ; FILL: STAX D ;FILL WITH BYTE IN A INX D ;PT TO NEXT DJNZ FILL RET ; ; No File Error Message ; PRNNF: CALL PRINTC ;NO FILE MESSAGE DB 'No Fil','e'+80H RET ; ;**** Section 3 **** ; I/O UTILITIES ; ; OUTPUT CHAR IN REG A TO CONSOLE AND DON'T CHANGE BC ; CONIN: MVI C,1 ;INPUT CHAR CALL BDOS ;GET INPUT CHAR WITH ^S PROCESSING AND ECHO JMP UCASE ;CAPITALIZE ; ; OUTPUT ; CRLF: MVI A,CR CALL CONOUT MVI A,LF ;FALL THRU TO CONOUT ; CONOUT: PUTRG ;SAVE REGS MVI C,2 OUTPUT: MOV E,A CALL BDOS GETRG ;GET REGS RET ; LCOUT: PUSH PSW ;OUTPUT CHAR TO CON: OR LST: DEP ON PRFLG PRFLG EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS THE PRINT FLAG ORA A ;0=TYPE JRZ LC1 POP PSW ;GET CHAR ; ; OUTPUT CHAR IN REG A TO LIST DEVICE ; LSTOUT: PUTRG ;SAVE REGISTERS MVI C,5 JR OUTPUT LC1: POP PSW ;GET CHAR PUSH PSW CALL CONOUT ;OUTPUT TO CON: POP PSW ; IF LTON CPI LF ;CHECK FOR PAGING RNZ ; ; PAGING ROUTINES ; PAGER COUNTS DOWN LINES AND PAUSES FOR INPUT (DIRECT) IF COUNT EXPIRES ; PAGSET SETS LINES/PAGE COUNT ; PAGER: PUSH H LXI H,PAGCNT ;COUNT DOWN DCR M JRNZ PAGER1 ;JUMP IF NOT END OF PAGE MVI M,NLINES-2 ;REFILL COUNTER ; PGFLG EQU $+1 ;POINTER TO IN-THE-CODE BUFFER PGFLG MVI A,0 ;0 MAY BE CHANGED BY PGFLG EQUATE CPI PGDFLG ;PAGE DEFAULT OVERRIDE OPTION WANTED? ; IF PGDFLT ;IF PAGING IS DEFAULT JRZ PAGER1 ; PGDFLG MEANS NO PAGING ELSE ;IF PAGING NOT DEFAULT JRNZ PAGER1 ; PGDFLG MEANS PLEASE PAGINATE ; ENDIF ;PGDFLG ; PUSH B ;SAVE REG CALL BIOS+9 ;BIOS CONSOLE INPUT ROUTINE POP B ;GET REG CPI 'C'-'@' ;^C JZ RS1 ;RESTART CPR PAGER1: POP H ;RESTORE HL ENDIF ;LTON ; RET ;RETURN FOR LC1 IF NOT LTON ; ; READ FILE BLOCK FUNCTION ; READF: LXI D,TFCB ;FALL THRU TO READ READ: MVI C,14H ;FALL THRU TO BDOSB ; ; CALL BDOS AND SAVE BC ; BDOSB: PUSH B CALL BDOS POP B ORA A ; ; THIS RETURN IS FOR BDOSB AND FOR THE NULL FUNCTION CALLED NOTE ; NOTE: RET ; ; PRINT STRING (ENDING IN CHAR WITH MSB SET) PTED TO BY RET ADR ; START WITH ; PRINTC: CALL CRLF ;NEW LINE ; PRINT: XTHL ;GET PTR TO STRING CALL PRIN1 ;PRINT STRING XTHL ;RESTORE HL AND RET ADR RET ; ; PRINT STRING (ENDING IN 0 OR BYTE WITH MSB SET) PTED TO BY HL ; PRIN1: MOV A,M ;GET NEXT BYTE INX H ;PT TO NEXT BYTE ORA A ;END OF STRING? RZ ;STRING TERMINATED BY BINARY 0 PUSH PSW ;SAVE FLAGS ANI 7FH ;MASK OUT MSB CALL CONOUT ;PRINT CHAR POP PSW ;GET FLAGS RM ;STRING TERMINATED BY MSB SET JR PRIN1 ; ; BDOS FUNCTION ROUTINES ; ; ; RETURN NUMBER OF CURRENT DISK IN A ; GETDRV: MVI C,19H JR BDOSJP ; ; SET 80H AS DMA ADDRESS ; DEFDMA: LXI D,TBUFF ;80H=TBUFF DMASET: MVI C,1AH JR BDOSJP ; RESET: MVI C,0DH BDOSJP: JMP BDOS ; LOGIN: MOV E,A MVI C,0EH JR BDOSJP ;SAVE SOME CODE SPACE ; OPENF: XRA A STA FCBCR LXI D,FCBDN ;FALL THRU TO OPEN ; OPEN: MVI C,0FH ;FALL THRU TO GRBDOS ; GRBDOS: CALL BDOS INR A ;SET ZERO FLAG FOR ERROR RETURN RET ; CLOSE: MVI C,10H JR GRBDOS ; SEARF: LXI D,TFCB ;SPECIFY FCB SEAR1: MVI C,11H JR GRBDOS ; SEARN: MVI C,12H JR GRBDOS ; ; CHECK FOR SUBMIT FILE IN EXECUTION AND ABORT IT IF SO ; IF SUBON ;ENABLE ONLY IF SUBMIT FACILITY IS ENABLED ; SUBKIL: LXI H,RNGSUB ;CHECK FOR SUBMIT FILE IN EXECUTION MOV A,M ORA A ;0=NO RZ MVI M,0 ;ABORT SUBMIT FILE LXI D,SUBFCB ;DELETE $$$.SUB ; ENDIF ;SUBON ; DELETE: MVI C,13H JR BDOSJP ;SAVE MORE SPACE ; ; GET/SET USER NUMBER ; GETUSR: MVI A,0FFH ;GET CURRENT USER NUMBER SETUSR: MOV E,A ;USER NUMBER IN E MVI C,20H ;SET USER NUMBER TO VALUE IN E (GET IF E=FFH) JR BDOSJP ;MORE SPACE SAVING ; ; END OF BDOS FUNCTIONS ; ; ;**** Section 4 **** ; ZCPR3 UTILITIES ; ; SET USER/DISK FLAG TO CURRENT USER AND DEFAULT DISK ; SETUD: CALL GETUSR ;GET NUMBER OF CURRENT USER ANI 0FH ;MASK SURE 4 BITS ADD A ;PLACE IT IN HIGH NYBBLE ADD A ADD A ADD A LXI H,CURDR ;MASK IN CURRENT DRIVE NUMBER (LOW NYBBLE) ORA M ;MASK IN STA UDFLAG ;SET USER/DISK NUMBER RET ; ; CONVERT CHAR IN A TO UPPER CASE ; UCASE: ANI 7FH ;MASK OUT MSB CPI 61H ;LOWER-CASE A RC CPI 7BH ;GREATER THAN LOWER-CASE Z? RNC ANI 5FH ;CAPITALIZE RET ; ; PRINT DU (DIR) PROMPT ; PROMPT: ; ; PRINT PROMPT (DU>) ; CALL CRLF ;PRINT PROMPT ; IF INCLDU ;IF DRIVE IN PROMPT LDA CURDR ;CURRENT DRIVE IS PART OF PROMPT ADI 'A' ;CONVERT TO ASCII A-P CALL CONOUT LDA CURUSR ;GET USER NUMBER ; IF SUPRES ;IF SUPPRESSING USR # REPORT FOR USR 0 ORA A JRZ PRMPT2 ENDIF ;SUPRES ; CPI 10 ;USER < 10? JRC PRMPT1 SUI 10 ;SUBTRACT 10 FROM IT PUSH PSW ;SAVE IT MVI A,'1' ;OUTPUT 10'S DIGIT CALL CONOUT POP PSW PRMPT1: ADI '0' ;OUTPUT 1'S DIGIT (CONVERT TO ASCII) CALL CONOUT PRMPT2: ENDIF ;INCLDU ; ; PRINT NDIR ENTRY IF ANY ; IF INCLNDR AND (Z3NDIR NE 0) ; LDA CURDR ;GET CURRENT DU IN BC INR A MOV B,A LDA CURUSR MOV C,A LXI H,Z3NDIR ;SCAN DIRECTORY FOR MATCH ; ; MAIN LOOP FOR SCANNING NDR FOR DU IN BC ; PRMPT3: MOV A,M ;END OF NDR? ORA A RZ INX H ;PT TO USER CMP B ;COMPARE DISK JRNZ PRMPT5 MOV A,M ;COMPARE USER CMP C JRNZ PRMPT5 ; ; MATCH OF DU ; IF INCLDU ;SEPARATE DU AND NDR WITH COLON MVI A,':' ;PRINT SEPARATOR CALL CONOUT ENDIF ;INCLDU ; MVI B,8 ;8 CHARS MAX PRMPT4: INX H ;PT TO NEXT CHAR MOV A,M ;GET NEXT CHAR CPI ' ' ;DONE IF SPACE RZ CALL CONOUT ;PRINT CHAR DJNZ PRMPT4 ;COUNT DOWN RET ; ; ADVANCE TO NEXT DU ; PRMPT5: LXI D,16+1 ;SKIP USER (1 BYTE) AND NAME/PW (16 BYTES) DAD D JR PRMPT3 ;CONTINUE SCAN ; ENDIF ;INCLNDR AND (Z3NDIR NE 0) ; RET ; ; INPUT NEXT COMMAND TO CPR ; This routine determines if a SUBMIT file is being processed ; and extracts the command line from it if so or from the user's console ; READBUF: ; IF SUBON ;IF SUBMIT FACILITY IS ENABLED, CHECK FOR IT ; LDA RNGSUB ;SUBMIT FILE CURRENTLY IN EXECUTION? ORA A ;0=NO JRZ RB1 ;GET LINE FROM CONSOLE IF NOT LXI D,SUBFCB ;OPEN $$$.SUB PUSH D ;SAVE DE CALL OPEN POP D ;RESTORE DE JRZ RB1 ;ERASE $$$.SUB IF END OF FILE AND GET CMND LDA SUBFRC ;GET VALUE OF LAST RECORD IN FILE DCR A ;PT TO NEXT TO LAST RECORD STA SUBFCR ;SAVE NEW VALUE OF LAST RECORD IN $$$.SUB CALL READ ;DE=SUBFCB JRNZ RB1 ;ABORT $$$.SUB IF ERROR IN READING LAST REC LXI D,CHRCNT ;COPY LAST RECORD (NEXT SUBMIT CMND) TO CHRCNT LXI H,TBUFF ; FROM TBUFF MVI B,BUFLEN ;NUMBER OF BYTES CALL LDIR LXI H,SUBFS2 ;PT TO S2 OF $$$.SUB FCB MVI M,0 ;SET S2 TO ZERO INX H ;PT TO RECORD COUNT DCR M ;DECREMENT RECORD COUNT OF $$$.SUB LXI D,SUBFCB ;CLOSE $$$.SUB CALL CLOSE JRZ RB1 ;ABORT $$$.SUB IF ERROR CALL PROMPT ;PRINT PROMPT MVI A,SPRMPT ;PRINT SUBMIT PROMPT TRAILER CALL CONOUT LXI H,CMDLIN ;PRINT COMMAND LINE FROM $$$.SUB CALL PRIN1 CALL BREAK ;CHECK FOR ABORT (ANY CHAR) RNZ ;IF NO ^C, RETURN TO CALLER AND RUN CALL SUBKIL ;KILL $$$.SUB IF ABORT JMP RESTRT ;RESTART CPR ; ; INPUT COMMAND LINE FROM USER CONSOLE ; RB1: CALL SUBKIL ;ERASE $$$.SUB IF PRESENT ; ENDIF ;SUBON ; ; IF SHELL STACKS ARE IMPLEMENTED, CHECK FOR CONTENT AT THIS TIME ; IF SHSTK NE 0 ; LXI H,SHSTK ;PT TO STACK MOV A,M ;CHECK FIRST BYTE CPI ' '+1 ;SEE IF ANY ENTRY JRC RB2 ;GET USER INPUT IF NONE ; ENDIF ;SHSTK NE 0 ; IF (SHSTK NE 0) OR (Z3MSG NE 0) ; RUNBUF: LXI D,CMDLIN ;PT TO FIRST CHAR OF COMMAND LINE MVI B,SHSIZE ;COPY SHELL LINE INTO COMMAND LINE BUFFER CALL LDIR ;DO COPY XCHG ;HL PTS TO END OF LINE MVI A,1 ;SAY SHELL WAS INVOKED STA Z3MSG+3 ;Z3 OUTPUT MESSAGE JR RB3 ;STORE ENDING ZERO AND EXIT RB2: ; ENDIF ;(SHSTK NE 0) OR (Z3MSG NE 0) ; CALL PROMPT ;PRINT PROMPT IF Z3WHL LDA Z3WHL ; CHECK STATUS OF WHEEL BYTE ORA A ; SET Z FLAG JRZ RB2A ; IF 0 THEN IGNORE THIS MVI A,WPRMPT ; ELSE LOAD WHEEL PROMPT JR RB2B ; AND CONTINUE ENDIF ; Z3WHL RB2A: MVI A,CPRMPT ;PRINT PROMPT TRAILER RB2B: CALL CONOUT MVI C,0AH ;READ COMMAND LINE FROM USER LXI D,BUFSIZ ;PT TO BUFFER SIZE BYTE OF COMMAND LINE CALL BDOS ; ; STORE ZERO AT END OF COMMAND LINE ; LXI H,CHRCNT ;PT TO CHAR COUNT MOV A,M ;GET CHAR COUNT INX H ;PT TO FIRST CHAR OF COMMAND LINE CALL ADDAH ;PT TO AFTER LAST CHAR OF COMMAND LINE RB3: MVI M,0 ;STORE ENDING ZERO RET ; ; CHECK FOR ANY CHAR FROM USER CONSOLE; RET W/ZERO SET IF NONE ; BREAK: PUTRG ;SAVE REGISTERS CALL BIOS+6 ;CONSOLE STATUS CHECK ORA A ;SET FLAGS CNZ BIOS+9 ;GET INPUT CHAR WITH ^S PROCESSING CPI 'S'-'@' ;PAUSE IF ^S CZ BIOS+9 ;GET NEXT CHAR GETRG ;RESTORE REGISTERS CPI 'C'-'@' ;CHECK FOR ABORT RET ; ; CHECK TO SEE IF HL PTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET ; SDELM: MOV A,M ;GET NEXT CHAR FROM LINE CPI ' '+1 ;DELIM IF <= JRC ZERO CPI '=' ;'='=DELIMITER RZ CPI 5FH ;UNDERSCORE=DELIMITER RZ CPI '.' ;'.'=DELIMITER RZ CPI ':' ;':'=DELIMITER RZ CPI ',' ;','=DELIMITER RZ ; IF CMDSEP NE ';' CPI ';' ;';'=DELIMITER RZ ENDIF ; CPI '<' ;'<'=DELIMITER RZ CPI '>' ;'>'=DELIMITER RZ JMP TSTEOL ;CHECK FOR EOL ZERO: XRA A ;SET ZERO FLAG RET ; ; ADD A TO HL (HL=HL+A) ; ADDAH: ADD L MOV L,A RNC INR H RET ; ; COPY FROM HL TO DE FOR B BYTES ; LDIR: MOV A,M ;GET BYTE STAX D ;PUT BYTE INX H ;PT TO NEXT INX D DJNZ LDIR RET ; ; EXTRACT DECIMAL NUMBER FROM COMMAND LINE ; RETURN WITH VALUE IN REG A; ALL REGISTERS MAY BE AFFECTED ; NUMBER: LXI H,TFCB+8 ;PT TO END OF TOKEN FOR CONVERSION MVI B,8 ;8 CHARS MAX ; ; CHECK FOR SUFFIX FOR HEXADECIMAL NUMBER ; NUMS: MOV A,M ;GET CHARS FROM END, SEARCHING FOR SUFFIX DCX H ;BACK UP CPI ' ' ;SPACE? JRNZ NUMS1 ;CHECK FOR SUFFIX DJNZ NUMS ;COUNT DOWN JR NUM0 ;BY DEFAULT, PROCESS NUMS1: CPI NUMBASE ;CHECK AGAINST BASE SWITCH FLAG JRZ HEXNUM ; ; PROCESS DECIMAL NUMBER ; NUM0: LXI H,TFCB+1 ;PT TO BEGINNING OF TOKEN NUM0A: LXI B,1100H ;C=ACCUMULATED VALUE, B=CHAR COUNT ; (C=0, B=11) NUM1: MOV A,M ;GET CHAR CALL SDELM ;DONE IF DELIMITER JRZ NUM2 INX H ;PT TO NEXT CHAR CALL DIGCK ;CHECK FOR DIGIT IN A JRC NUMERR MOV D,A ;DIGIT IN D MOV A,C ;NEW VALUE = OLD VALUE * 10 RLC ;*2 JRC NUMERR RLC ;*4 JRC NUMERR ADD C ;*5 JRC NUMERR RLC ;*10 JRC NUMERR ADD D ;NEW VALUE = OLD VALUE * 10 + DIGIT JRC NUMERR ;CHECK FOR RANGE ERROR MOV C,A ;SET NEW VALUE DJNZ NUM1 ;COUNT DOWN ; ; RETURN FROM NUMBER ; NUM2: MOV A,C ;GET ACCUMULATED VALUE RET ; ; NUMBER ERROR ROUTINE FOR SPACE CONSERVATION ; NUMERR: JMP ERROR ;USE ERROR ROUTINE - THIS IS RELATIVE PT ; ; CHECK TO SEE IF A IS A DIGIT ; IF SO, RETURN ITS VALUE ; IF NOT, RETURN WITH CARRY SET ; DIGCK: SUI '0' ;DIGIT? RC ;ERROR CPI 10 ;RANGE? JRNC DIGCK1 CMC ;FLIP CARRY RET DIGCK1: STC ;SET CARRY RET ; ; EXTRACT HEXADECIMAL NUMBER FROM COMMAND LINE ; RETURN WITH VALUE IN REG A; ALL REGISTERS MAY BE AFFECTED ; HEXNUM: LXI H,TFCB+1 ;PT TO TOKEN FOR CONVERSION LXI D,0 ;DE=ACCUMULATED VALUE MVI B,11 ;B=CHAR COUNT HNUM1: MOV A,M ;GET CHAR CPI ' ' ;DONE? JRZ HNUM3 ;RETURN IF SO CPI NUMBASE ;DONE IF NUMBASE SUFFIX JRZ HNUM3 SUI '0' ;CONVERT TO BINARY JRC NUMERR ;RETURN AND DONE IF ERROR CPI 10 ;0-9? JRC HNUM2 SUI 7 ;A-F? CPI 10H ;ERROR? JRNC NUMERR HNUM2: INX H ;PT TO NEXT CHAR MOV C,A ;DIGIT IN C MOV A,D ;GET ACCUMULATED VALUE RLC ;EXCHANGE NYBBLES RLC RLC RLC ANI 0F0H ;MASK OUT LOW NYBBLE MOV D,A MOV A,E ;SWITCH LOW-ORDER NYBBLES RLC RLC RLC RLC MOV E,A ;HIGH NYBBLE OF E=NEW HIGH OF E, ; LOW NYBBLE OF E=NEW LOW OF D ANI 0FH ;GET NEW LOW OF D ORA D ;MASK IN HIGH OF D MOV D,A ;NEW HIGH BYTE IN D MOV A,E ANI 0F0H ;MASK OUT LOW OF E ORA C ;MASK IN NEW LOW MOV E,A ;NEW LOW BYTE IN E DJNZ HNUM1 ;COUNT DOWN ; ; RETURN FROM HEXNUM ; HNUM3: XCHG ;RETURNED VALUE IN HL MOV A,L ;LOW-ORDER BYTE IN A RET ; ; LOG INTO DU CONTAINED IN FCB PTED TO BY DE ; FCBLOG: PUSH D ;SAVE PTR TO FCB XCHG MOV A,M ;GET DRIVE STA TEMPDR ;SET TEMP DRIVE LXI B,13 ;PT TO S1 FIELD DAD B MOV A,M ;GET USER STA TEMPUSR ;SET TEMP USER CALL SLOGIN ;LOG IN POP D ;GET PTR TO FCB RET ; ; CHECK FOR SPECIFIED DRIVE AND LOG IT IN ; SLOGIN: TEMPDR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;2ND BYTE (IMMEDIATE ARG) IS TEMPDR ORA A ;0=CURRENT DRIVE JRNZ SLOG1 LDA CURDR ;LOG IN CURRENT DRIVE INR A ;ADD 1 FOR NEXT DCR SLOG1: DCR A ;ADJUST FOR PROPER DISK NUMBER (A=0) CALL LOGIN ;LOG IN NEW DRIVE TEMPUSR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;2ND BYTE IS USER TO BE SELECTED JMP SETUSR ;LOG IN NEW USER ; ; ROUTINE TO CHECK FOR A WHEEL BYTE AS NON-ZERO ; IF WHEEL BYTE IS ZERO, THEN ABORT (POP STACK AND RETURN) ; ; IF WHEEL ;WHEEL FACILITY? WHLCHK: LDA Z3WHL ;GET WHEEL BYTE ORA A ;ZERO? RNZ ;OK IF NOT JMP ERROR ;PROCESS AS ERROR ENDIF ;WHEEL ; ; ; CMDTBL (COMMAND TABLE) SCANNER ; ON RETURN, HL CONTAINS ADDRESS OF COMMAND IF CPR-RESIDENT ; ON RETURN, ZERO FLAG SET MEANS CPR-RESIDENT COMMAND ; CMDSER: LXI H,CMDTBL ;PT TO COMMAND TABLE ; ; ENTRY POINT TO PERMIT RCP TABLE TO BE SCANNED ; CMDSCAN: MOV B,M ;GET SIZE OF COMMAND TEXT INX H ;PT TO FIRST COMMAND CMS1: MOV A,M ;CHECK FOR END OF TABLE ORA A JRZ CMS5 LXI D,FCBFN ;PT TO STORED COMMAND NAME PUSH B ;SAVE SIZE OF COMMAND TEXT CMS2: LDAX D ;COMPARE AGAINST TABLE ENTRY ;*** ; Changed to ignore the MSB of the byte in memory ; --Chuck ;*** ; CMP M xra m ; check for a match ani 7fh ; and turn off bit 7 (I know, 2 more bytes) JRNZ CMS3 ;NO MATCH INX D ;PT TO NEXT CHAR INX H DJNZ CMS2 ;COUNT DOWN LDAX D ;NEXT CHAR IN INPUT COMMAND MUST BE CPI ' ' JRNZ CMS4 POP B ;CLEAR STACK MOV A,M ;GET ADDRESS FROM TABLE INTO HL INX H MOV H,M MOV L,A ;HL CONTAINS ADDRESS XRA A ;ZERO FLAG SET FOR COMMAND FOUND RET ;COMMAND IS RESIDENT (ZERO FLAG SET) CMS3: INX H ;SKIP TO NEXT COMMAND TABLE ENTRY DJNZ CMS3 CMS4: POP B ;GET SIZE OF COMMAND TEXT INX H ;SKIP ADDRESS INX H JR CMS1 CMS5: XRA A ;SET NZ DCR A ;COMMAND NOT FOUND IF NZ RET ; ;**** Section 5 **** ; CPR-Resident Commands ; ; ;Section 5A ;Command: DIR ;Function: To display a directory of the files on disk ;Forms: ; DIR Displays the DIR files ; DIR S Displays the SYS files ; DIR A Display both DIR and SYS files ;Notes: ; The flag SYSFLG defines the letter used to display both DIR and ; SYS files (A in the above Forms section) ; The flag SOFLG defines the letter used to display only the SYS ; files (S in the above Forms section) ; The flag WIDE determines if the file names are spaced further ; apart (WIDE=TRUE) for 80-col screens ; The flag FENCE defines the character used to separate the file ; names ; IF DIRON ;DIR ENABLED ; DIR: LXI D,TFCB ;PT TO TARGET FCB PUSH D ;SAVE PTR INX D ;PT TO FILE NAME LDAX D ;GET FIRST CHAR CPI ' ' ;IF , MAKE ALL WILD JRNZ DIR1 MVI B,11 ;11 BYTES MVI A,'?' ;WILD CALL FILL DIR1: POP D ;GET PTR TO FCB LXI D,TFCB ;PT TO TARGET FCB CALL FCBLOG ;LOG IN TEMP DISK/USER LDA TFCB2+1 ;LOOK AT NEXT INPUT CHAR MVI B,80H ;PREPARE FOR DIR-ONLY SELECTION CPI ' ' JRZ DIRPR ;THERE IS NO FLAG, SO DIR ONLY MVI B,1 ;SET FOR BOTH DIR AND SYS FILES CPI SYSFLG ;SYSTEM AND DIR FLAG SPECIFIER? JRZ DIRPR ;GOT SYSTEM SPECIFIER CPI SOFLG ;SYS ONLY? JRNZ DIRPR DCR B ;B=0 FOR SYS FILES ONLY ;DROP INTO DIRPR TO PRINT DIRECTORY ; THEN RESTART CPR ; ENDIF ;DIRON ; ; DIRECTORY PRINT ROUTINE; ON ENTRY, B REG IS SET AS FOLLOWS: ; 0 FOR ONLY SYSTEM FILES, 80H FOR ONLY DIR FILES, 1 FOR BOTH ; IF DIRON OR ERAON ; DIRPR: MOV A,B ;GET FLAG STA SYSTST ;SET SYSTEM TEST FLAG MVI E,0 ;SET COLUMN COUNTER TO ZERO PUSH D ;SAVE COLUMN COUNTER (E) CALL SEARF ;SEARCH FOR SPECIFIED FILE (FIRST OCCURRENCE) JRNZ DIR3 CALL PRNNF ;PRINT NO FILE MSG; REG A NOT CHANGED XRA A ;SET ZERO FLAG IN CASE CALLED BY ERA POP D ;RESTORE DE RET ; ; ENTRY SELECTION LOOP; ON ENTRY, A=OFFSET FROM SEARF OR SEARN ; DIR3: CALL GETSBIT ;GET AND TEST FOR TYPE OF FILES JRZ DIR6 POP D ;GET ENTRY COUNT (= COUNTER) MOV A,E ;GET ENTRY COUNTER INR E ;INCREMENT ENTRY COUNTER PUSH D ;SAVE IT ANI 03H ;OUTPUT IF 4 ENTRIES PRINTED IN LINE JRNZ DIR4 CALL CRLF ;NEW LINE JR DIR5 DIR4: CALL PRINT ; IF WIDE ; DB ' ' ;2 SPACES DB FENCE ;THEN FENCE CHAR DB ' ',' '+80H ;THEN 2 MORE SPACES ; ELSE ; DB ' ' ;SPACE DB FENCE ;THEN FENCE CHAR DB ' '+80H ;THEN SPACE ; ENDIF ;WIDE ; DIR5: ; MVI B,01H ;PT TO 1ST BYTE OF FILE NAME ; MOV A,B ;A=OFFSET MVI A,1 ;PT TO 1ST BYTE OF FILE NAME CALL DIRPTR ;HL NOW PTS TO 1ST BYTE OF FILE NAME CALL PRFN ;PRINT FILE NAME DIR6: CALL BREAK ;CHECK FOR ABORT JRZ DIR7 CALL SEARN ;SEARCH FOR NEXT FILE JRNZ DIR3 ;CONTINUE IF FILE FOUND DIR7: POP D ;RESTORE STACK MVI A,0FFH ;SET NZ FLAG ORA A RET ; ENDIF ;DIRON OR ERAON ; ; PRINT FILE NAME PTED TO BY HL ; PRFN: MVI B,8 ;8 CHARS CALL PRFN1 MVI A,'.' ;DOT CALL CONOUT MVI B,3 ;3 CHARS PRFN1: MOV A,M ; GET CHAR INX H ; PT TO NEXT CALL CONOUT ; PRINT CHAR DCR B ; COUNT DOWN JRNZ PRFN1 RET ; ; PT TO DIRECTORY ENTRY IN TBUFF WHOSE OFFSET IS SPECIFIED BY A AND C ; DIRPTR: LXI H,TBUFF ;PT TO TEMP BUFFER ADD C ;PT TO 1ST BYTE OF DIR ENTRY CALL ADDAH ;PT TO DESIRED BYTE IN DIR ENTRY MOV A,M ;GET DESIRED BYTE RET ; ; AFTER A SEARCH, RETURN NZ SET IF DESIRED TYPE OF FILE FOUND, Z IF NOT ; THIS ALGORITHM LOOKS AT THE SYSTEM BIT OF THE LOCATED FILE; THIS ; BIT IS SET TO 1 IF THE FILE IS A SYSTEM FILE AND 0 IF NOT A SYSTEM ; FILE. THE FOLLOWING EXCLUSIVE OR MASKS ARE APPLIED TO RETURN Z OR NZ ; AS REQUIRED BY THE CALLING PROGRAM: ; ; SYSTEM BYTE: X 0 0 0 0 0 0 0 (AFTER 80H MASK, X=1 IF SYS, 0 IF DIR) ; ; SYS-ONLY : 0 0 0 0 0 0 0 0 (XOR 0 = 0 if X=0, = 80H if X=1) ; DIR-ONLY : 1 0 0 0 0 0 0 0 (XOR 80H = 80h if X=0, = 0 if X=1) ; BOTH : 0 0 0 0 0 0 0 1 (XOR 1 = 81H or 1H, NZ in both cases) ; GETSBIT: DCR A ;ADJUST TO RETURNED VALUE RRC ;CONVERT NUMBER TO OFFSET INTO TBUFF RRC RRC ANI 60H MOV C,A ;OFFSET INTO TBUFF IN C (C=OFFSET TO ENTRY) MVI A,10 ;ADD 10 TO PT TO SYSTEM FILE ATTRIBUTE BIT CALL DIRPTR ;A=SYSTEM BYTE ANI 80H ;LOOK AT ONLY SYSTEM BIT SYSTST EQU $+1 ;IN-THE-CODE VARIABLE XRI 0 ; IF SYSTST=0, SYS ONLY; IF SYSTST=80H, DIR ; ONLY; IF SYSTST=1, BOTH SYS AND DIR RET ;NZ IF OK, Z IF NOT OK ; ;Section 5B ;Command: ERA ;Function: Erase files ;Forms: ; ERA Erase Specified files and print their names ; ERA V Erase Specified files and print their names, but ask ; for verification before Erase is done ;Notes: ; Several Key Flags affect this command: ; ERAV - If TRUE, the V option is enabled, and the character ; which turns it on (the V) is defined by ERDFLG ; ERAOK - If TRUE, the OK? prompt is enabled ; If ERAOK is FALSE, the verification feature is disabled regardless ; of what value ERAV has ; If ERAOK is TRUE, then: ; If ERAV is TRUE, verification is requested only if the V ; flag (actual letter defined by ERDFLG) is in the ; command line ; If ERAV is FALSE, verification is always requested, and a ; V flag in the command line will cause an error ; message to be printed (V?) after the ERA is completed ; IF ERAON ;ERA ENABLED? ; ERA: ; IF WERA ;WHEEL FACILITY ENABLED? CALL WHLCHK ;CHECK FOR IT ENDIF ;WERA ; IF ERAV AND ERAOK ;V FLAG AND OK? ENABLED? LDA TFCB2+1 ;GET ERAFLG IF IT'S THERE STA ERAFLG ;SAVE IT AS A FLAG ENDIF ;ERAV ; LXI D,TFCB ;PT TO TARGET FCB CALL FCBLOG ;LOG INTO DU IN FCB MVI B,1 ;DISPLAY ALL MATCHING FILES CALL DIRPR ;PRINT DIRECTORY OF ERASED FILES RZ ;ABORT IF NO FILES ; IF ERAOK ;PRINT PROMPT ; IF ERAV ;TEST VERIFY FLAG ; ERAFLG EQU $+1 ;ADDRESS OF FLAG MVI A,0 ;2ND BYTE IS FLAG CPI ERDFLG ;IS IT A VERIFY OPTION? JRNZ ERA2 ;SKIP PROMPT IF IT IS NOT ; ENDIF ;ERAV ; CALL PRINTC DB 'OK to Erase','?'+80H CALL CONIN ;GET REPLY CPI 'Y' ;YES? RNZ ;ABORT IF NOT ; ENDIF ;ERAOK ; ERA2: LXI D,TFCB ;DELETE FILE SPECIFIED JMP DELETE ;DELETE FILE AND REENTER CCP ; ENDIF ;ERAON ; ;Section 5C ;Command: LIST ;Function: Print out specified file on the LST: Device ;Forms: ; LIST Print file (NO Paging) ;Notes: ; The flags which apply to TYPE do not take effect with LIST ; IF LTON ;LIST AND TYPE ENABLED? ; LIST: MVI A,0FFH ;TURN ON PRINTER FLAG JR TYPE0 ; ;Section 5D ;Command: TYPE ;Function: Print out specified file on the CON: Device ;Forms: ; TYPE Print file ; TYPE P Print file with paging flag ;Notes: ; The flag PGDFLG defines the letter which toggles the paging ; facility (P in the forms section above) ; The flag PGDFLT determines if TYPE is to page by default ; (PGDFLT=TRUE if TYPE pages by default); combined with ; PGDFLG, the following events occur -- ; If PGDFLT = TRUE, PGDFLG turns OFF paging ; If PGDFLT = FALSE, PGDFLG turns ON paging ; TYPE: XRA A ;TURN OFF PRINTER FLAG ; ; ENTRY POINT FOR CPR LIST FUNCTION (LIST) ; TYPE0: STA PRFLG ;SET FLAG ; IF WLT ;WHEEL ON? CALL WHLCHK ;CHECK WHEEL BYTE ENDIF ;WLT ; LDA TFCB2+1 ;GET PGDFLG IF IT'S THERE STA PGFLG ;SAVE IT AS A FLAG LXI D,TFCB ;PT TO TARGET FILE FCB CALL AMBCHK ;CHECK FOR QUESTION MARKS IN TFCB RZ ;ERROR IF ANY QUESTION MARKS CALL FCBLOG ;LOG INTO DU IN FCB LXI D,TFCB ;PT TO SELECT FILE CALL OPEN ;OPEN SELECTED FILE JZ PRNNF ;ABORT IF ERROR CALL CRLF ;NEW LINE MVI A,NLINES-1 ;SET LINE COUNT STA PAGCNT LXI B,080H ;SET CHAR POSITION AND TAB COUNT ; (B=0=TAB, C=080H=CHAR POSITION) ; ; MAIN LOOP FOR LOADING NEXT BLOCK ; TYPE2: MOV A,C ;GET CHAR COUNT CPI 80H JRC TYPE3 PUSH H ;READ NEXT BLOCK PUSH B CALL READF POP B POP H RNZ ;ERROR? MVI C,0 ;SET CHAR COUNT LXI H,TBUFF ;PT TO FIRST CHAR ; ; MAIN LOOP FOR PRINTING CHARS IN TBUFF ; TYPE3: MOV A,M ;GET NEXT CHAR ANI 7FH ;MASK OUT MSB CPI 1AH ;END OF FILE (^Z)? RZ ;RESTART CPR IF SO ; ; OUTPUT CHAR TO CON: OR LST: DEVICE WITH TABULATION ; CPI CR ;RESET TAB COUNT? JRZ TYPE4 CPI LF ;RESET TAB COUNT? JRZ TYPE4 CPI TAB ;TAB? JRZ TYPE5 ; ; OUTPUT CHAR AND INCREMENT CHAR COUNT ; CALL LCOUT ;OUTPUT CHAR INR B ;INCREMENT TAB COUNT JR TYPE6 ; ; OUTPUT OR AND RESET TAB COUNT ; TYPE4: CALL LCOUT ;OUTPUT OR MVI B,0 ;RESET TAB COUNTER JR TYPE6 ; ; TABULATE ; TYPE5: MVI A,' ' ; CALL LCOUT INR B ;INCR POS COUNT MOV A,B ANI 7 JRNZ TYPE5 ; ; CONTINUE PROCESSING ; TYPE6: INR C ;INCREMENT CHAR COUNT INX H ;PT TO NEXT CHAR CALL BREAK ;CHECK FOR ABORT RZ ;RESTART IF SO JR TYPE2 ; ENDIF ;LTON ; ;Section 5E ;Command: SAVE ;Function: To save the contents of the TPA onto disk as a file ;Forms: ; SAVE ; Save specified number of pages (start at 100H) ; from TPA into specified file; is in DEC ; SAVE S ; Like SAVE above, but numeric argument specifies ; number of sectors rather than pages ;Notes: ; The MULTCMD flag (Multiple Commands Allowed) expands the code slightly, ; but is required to support multiple commands with SAVE ; The SECTFLG defines the letter which indicates a sector count ; (S in the Forms section above) ; IF SAVEON ;SAVE ENABLED? ; SAVE: ; IF WSAVE ;WHEEL FACILITY? CALL WHLCHK ;CHECK FOR WHEEL BYTE ENDIF ;WSAVE ; CALL NUMBER ;EXTRACT NUMBER FROM COMMAND LINE MOV L,A ;HL=PAGE COUNT MVI H,0 PUSH H ;SAVE PAGE COUNT LXI H,TFCB2 ;COPY 2ND FCB INTO POSITION OF FIRST LXI D,TFCB PUSH D ;SAVE PTR TO FCB MVI B,14 ;14 BYTES CALL LDIR POP D ;GET PTR TO FCB CALL AMBCHK ;CHECK FOR AMBIGUOUS POP H RZ ;ABORT IF SO PUSH H CALL EXTEST ;TEST FOR EXISTENCE OF FILE AND ABORT IF SO MVI C,16H ;BDOS MAKE FILE CALL GRBDOS POP H ;GET PAGE COUNT JRZ SAVE3 ;ERROR? LXI D,TPA-128 ;PT TO START OF SAVE AREA (TPA) DAD H ;DOUBLE 256-BYTE BLOCK COUNT FOR SECTOR COUNT XCHG ;DE IS COUNT, HL IS NEXT BLOCK - 128 BYTES SAVE1: MOV A,D ;DONE WITH SAVE? ORA E ;DE=0 IF SO JRZ SAVE2 DCX D ;COUNT DOWN ON SECTORS PUSH D ;SAVE PTR TO BLOCK TO SAVE LXI D,128 ;128 BYTES PER SECTOR DAD D ;PT TO NEXT SECTOR PUSH H ;SAVE ON STACK XCHG ;DE IS ADDRESS CALL DMASET ;SET DMA ADDRESS FOR WRITE (ADDRESS IN DE) LXI D,TFCB ;WRITE SECTOR MVI C,15H ;BDOS WRITE SECTOR CALL BDOSB ;SAVE BC POP H ;GET PTR TO NEXT SECTOR IN HL POP D ;GET SECTOR COUNT IN DE JRNZ SAVE3 ;WRITE ERROR? JR SAVE1 ;CONTINUE SAVE2: LXI D,TFCB ;CLOSE SAVED FILE CALL CLOSE INR A ;ERROR? JRNZ SAVE4 SAVE3: CALL PRNLE ;PRINT 'NO SPACE' ERROR SAVE4: JMP DEFDMA ;SET DMA TO 0080 AND RESTART CPR ; ENDIF ;SAVEON ; IF LTON OR SAVEON OR RENON ;FOR LIST/TYPE, SAVE, AND REN FCTS ; ; TEST FCB PTED TO BY DE TO SEE IF ANY ? CHARS IN IT ; RETURN WITH Z IF SO, NZ IF NOT; DON'T AFFECT DE ; AMBCHK: PUSH D INX D ;PT TO FIRST CHAR MVI B,11 ;11 CHARS AMB1: LDAX D ;GET CHAR CPI '?' ;ERROR? JRZ AMB2 INX D ;PT TO NEXT DJNZ AMB1 DCR B ;SET NZ POP D ;RESTORE PTR RET AMB2: CALL PRINT DB CR,LF,'AFN Erro','r'+80H XRA A ;SET ZERO FLAG POP D ;RESTORE PTR RET ; ENDIF ;LTON OR SAVEON ; ; Test File in FCB for existence, ask user to delete if so, and abort if he ; choses not to ; IF SAVEON OR RENON ;FOR SAVE AND REN FUNCTIONS ; EXTEST: LXI D,TFCB ;PT TO FCB PUSH D ;SAVE PTR CALL FCBLOG ;LOG INTO DU CALL SEARF ;LOOK FOR SPECIFIED FILE POP D ;GET PTR TO FCB RZ ;OK IF NOT FOUND PUSH D ;SAVE PTR TO FCB CALL PRINTC DB 'Erase',' '+80H LXI H,TFCB+1 ;PT TO FILE NAME FIELD CALL PRFN ;PRINT IT MVI A,'?' ;PRINT QUESTION CALL CONOUT CALL CONIN ;GET RESPONSE POP D ;GET PTR TO FCB CPI 'Y' ;KEY ON YES JNZ ERR3 ;RESTART AS ERROR IF NO PUSH D ;SAVE PTR TO FCB CALL DELETE ;DELETE FILE POP D ;GET PTR TO FCB RET ; ENDIF ;SAVEON OR RENON ; ;Section 5F ;Command: REN ;Function: To change the name of an existing file ;Forms: ; REN = Perform function ; IF RENON ;REN ENABLED? ; REN: ; IF WREN ;WHEEL FACILITY? CALL WHLCHK ;CHECK FOR WHEEL BYTE ENDIF ;WREN ; LXI D,TFCB ;CHECK FOR AMBIGUITY IN FIRST FILE NAME CALL AMBCHK RZ LXI D,TFCB2 ;CHECK FOR AMBIGUITY IN SECOND FILE NAME CALL AMBCHK RZ CALL EXTEST ;TEST FOR FILE EXISTENCE AND RETURN ; IF FILE DOESN'T EXIST; ABORT IF IT DOES MVI B,16 ;EXCHANGE NEW AND OLD FILE NAMES LXI H,TFCB ;PT TO NEW LXI D,TFCB2 ;PT TO OLD REN0: LDAX D ;GET OLD MOV C,A MOV A,M ;GET NEW STAX D ;PUT NEW MOV M,C ;PUT OLD INX H ;ADVANCE INX D DJNZ REN0 ; ; PERFORM RENAME FUNCTION ; LXI D,TFCB ;RENAME FILE XRA A STAX D ;SET CURRENT DISK MVI C,17H ;BDOS RENAME FCT CALL GRBDOS RNZ JMP PRNNF ;PRINT NO FILE MSG ; ENDIF ;RENON ; ;Section 5G ;Command: JUMP ;Function: To Call the program (subroutine) at the specified address ; without loading from disk ;Forms: ; JUMP Call at ; is in HEX ; IF JUMPON ;JUMP ENABLED? ; JUMP: ; IF WJUMP ;WHEEL FACILITY? CALL WHLCHK ;CHECK FOR WHEEL BYTE ENDIF ;WJUMP ; CALL HEXNUM ;GET LOAD ADDRESS IN HL JR CALLPROG ;PERFORM CALL ; ENDIF ;JUMPON ; ;Section 5H ;Command: GO ;Function: To Call the program in the TPA without loading ; loading from disk. Same as JUMP 100H, but much ; more convenient, especially when used with ; parameters for programs like STAT. Also can be ; allowed on remote-access systems with no problems. ; ;Form: ; GO ; IF GOON ;GO ENABLED? ; GO: ; IF WGO ;WHEEL FACILITY? CALL WHLCHK ;CHECK FOR WHEEL BYTE ENDIF ;WGO ; LXI H,TPA ;Always to TPA JR CALLPROG ;Perform call ; ENDIF ;GOON ; ;Section 5I ;Command: COM file processing ;Function: To load the specified COM file from disk and execute it ;Forms: ;Notes: ; COM files are processed as follows -- ; 1. File name buffers are initialized and a preliminary ; error check is done ; 2. MLOAD is used to search for the file along the Path ; and load it into the TPA ; 3. CALLPROG is used to set up the buffers to be used by ; the transient (FCB at 5CH, FCB at 6CH, BUFF at 80H) ; and run the program ; The flag MULTCMD comes into play frequently here; it mainly serves ; to save space if MULTCMD is FALSE and enables Multiple ; Commands on the same line if MULTCMD is TRUE ; COMDIR: IF DRVPREFIX ; LDA FCBFN ;ANY COMMAND? CPI ' ' ;' ' MEANS COMMAND WAS 'DIR:' TO SWITCH JRNZ COM ;NOT , SO MUST BE TRANSIENT OR ERROR ; ; ENTRY POINT TO SELECT USER/DISK VIA DIR: PREFIX ; IF WDU ;WHEEL FACILITY? CALL WHLCHK ;CHECK FOR WHEEL BYTE ENDIF ;WDU ; LDA FCBDN+13 ;GET SELECTED USER CPI 16 ;OUT OF RANGE? JNC ERROR LXI D,FCBDN ;PT TO FCB CALL FCBLOG ;LOG INTO DU LDA TEMPUSR ;GET TEMPORARY USER STA CURUSR ;SET CURRENT USER (MAKE PERMANENT) LDA TEMPDR ;GET SELECTED DISK ORA A ;IF 0 (DEFAULT), NO CHANGE JRZ COMDR DCR A ;ADJUST FOR LOGIN STA CURDR ;SET CURRENT DRIVE COMDR: CALL SETUD ;SET UD BYTE JMP RS1 ;RESUME COMMAND LINE PROCESSING ; ENDIF ;DRVPREFIX ; ; PROCESS COMMAND ; COM: ; IF CMDRUN ;COMMAND RUN FACILITY AVAILABLE? MVI A,0FFH ;USE IT IF AVAILABLE (MLOAD INPUT) ENDIF ;CMDRUN ; ; ; SET EXECUTION AND LOAD ADDRESS ; LXI H,TPA ;TRANSIENT PROGRAM AREA PUSH H ;SAVE TPA ADDRESS FOR EXECUTION CALL MLOAD ;LOAD MEMORY WITH FILE SPECIFIED IN CMD LINE POP H ;GET EXECUTION ADDRESS; FALL THRU TO CALLPROG ; ; CALLPROG IS THE ENTRY POINT FOR THE EXECUTION OF THE LOADED ; PROGRAM; ON ENTRY TO THIS ROUTINE, HL MUST CONTAIN THE EXECUTION ; ADDRESS OF THE PROGRAM (SUBROUTINE) TO EXECUTE ; CALLPROG: CALL CRLF ;LEADING NEW LINE CALLP: SHLD EXECADR ;PERFORM IN-LINE CODE MODIFICATION ; ; COPY COMMAND TAIL INTO TBUFF ; TAILSV EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION LXI H,0 ;ADDRESS OF FIRST CHAR OF COMMAND TAIL LXI D,TBUFF ;PT TO TBUFF PUSH D ;SAVE PTR MVI B,0 ;SET COUNTER INX D ;PT TO FIRST CHAR TAIL: MOV A,M ;GET CHAR CALL TSTEOL ;CHECK FOR EOL JRZ TAIL1 STAX D ;PUT CHAR INX H ;PT TO NEXT INX D INR B ;INCREMENT COUNT JR TAIL TAIL1: XRA A ;STORE ENDING ZERO STAX D POP H ;GET PTR MOV M,B ;SAVE COUNT ; ; RUN LOADED TRANSIENT PROGRAM ; CALL DEFDMA ;SET DMA TO 0080 ; ; EXECUTION (CALL) OF PROGRAM (SUBROUTINE) OCCURS HERE ; EXECADR EQU $+1 ;CHANGE ADDRESS FOR IN-LINE CODE MODIFICATION CALL TPA ;CALL TRANSIENT ; ; RETURN FROM EXECUTION ; CALL DEFDMA ;SET DMA TO 0080, IN CASE PROG CHANGED IT JMP RS1 ;RESTART CPR AND CONTINUE COMMAND PROCESSING ; ;Section 5J ;Command: GET ;Function: To load the specified file from disk to the specified address ;Forms: ; GET Load the specified file at the specified page; ; is in HEX ; IF GETON ;GET ENABLED? ; GET: ; IF WGET ;WHEEL ON? CALL WHLCHK ;CHECK WHEEL BYTE ENDIF ;WGET ; LXI H,TFCB2 ;COPY TFCB2 TO FCBDN FOR LOAD LXI D,FCBDN MVI B,14 ;14 BYTES (INCLUDES DU) CALL LDIR CALL HEXNUM ;GET LOAD ADDRESS IN HL ; ; FALL THRU TO MLOAD ; IF CMDRUN ;COMMAND RUN FACILITY AVAILABLE? XRA A ;NO CMDRUN IF FACILITY IS THERE (MLOAD INPUT) ENDIF ;CMDRUN ; ENDIF ;GETON ; ; MEMORY LOAD SUBROUTINE ; ; LOAD MEMORY WITH THE FILE WHOSE NAME IS SPECIFIED IN THE COMMAND LINE ; ON INPUT, HL CONTAINS STARTING ADDRESS TO LOAD ; ; EXIT POINTS ARE A RETURN AND LOG IN CURRENT USER/DISK IF NO ERROR, ; A JMP TO ERROR IF COM FILE NOT FOUND OR A MESSAGE AND ABORT IF MEMORY FULL ; MLOAD: ; IF CMDRUN ;CMDRUN FACILITY? STA CRFLAG ;SAVE FLAG ENDIF ;CMDRUN ; SHLD LOADADR ;SET LOAD ADDRESS XCHG ;LOAD ADDRESS IN DE CALL DMASET ;SET DMA ADDRESS ; ; MLA is a reentry point for a non-standard CP/M Modification ; The PATH command-search is implemented by this routine ; MLA: ; ; Set attributes of COM files which match search ; MVI A,COMATT ;CUSTOMIZER-SPECIFIED ATTRIBUTES STA SYSTST ;SET FLAG ; ; Analyze current path, generating a minimal, optimal absolute ; path equivalent in the buffer MPATH ; IF MINPATH ;IF MINIMUM PATH SEARCH EMPLOYED XRA A STA MPATH ;SET EMPTY PATH ; IF DRVPREFIX ;PAY ATTENTION TO DU:COM PREFIX? ; ; Convert DU in FCBDN into absolute expression in MPATH ; LXI D,MPATH ;BUILD MPATH BUFFER LXI H,FCBDN ;HL PTS TO FCB, DE PTS TO MPATH MOV A,M ;GET DRIVE ORA A ;SELECT CURRENT JRNZ MLAMPD LDA CURDR ;SET CURRENT DRIVE INR A ;ADJUST FOR PATH MLAMPD: STAX D ;SET DRIVE INX D ;PT TO USER LXI B,13 ;PT TO USER DAD B MOV A,M ;GET USER STAX D ;SAVE USER INX D ;PT TO NEXT XRA A ;A=0 STAX D ;STORE ENDING 0 IN MPATH ENDIF ;DRVPREFIX ; IF SCANCUR ;SCAN CURRENT DU AT ALL TIMES? LDA CURDR ;GET CURRENT DRIVE INR A ;ADD 1 FOR A=1 MOV B,A LDA CURUSR ;GET CURRENT USER MOV C,A ;BC=DU LXI H,PATH ;PT TO FIRST PATH ELEMENT JR MPATHBC ;PLACE ENTRY INTO MPATH ENDIF ;SCANCUR ; ; Convert symbolic path at PATH into absolute path at MPATH ; LXI H,PATH ;PT TO SYMBOLIC PATH MPATH1: MOV A,M ;CHECK FOR END OF SYMBOLIC PATH ORA A ;0=END OF PATH JRZ MPATH7 ; ; Place absolute form for current path element in BC ; ANI 7FH ;MASK OUT SYSTEM BIT CPI CURIND ;CHECK FOR CURRENT DRIVE JRNZ MPATH2 LDA CURDR ;GET CURRENT DRIVE INR A ;ADJUST FOR A=1 MPATH2: MOV B,A ;DRIVE IN B (1=A) INX H ;PT TO USER MOV A,M ;GET USER INX H ;PT TO NEXT ELEMENT ANI 7FH ;MASK OUT SYSTEM BIT CPI CURIND ;CHECK FOR CURRENT USER JRNZ MPATH3 LDA CURUSR ;GET CURRENT USER MPATH3: MOV C,A ;SET USER IN C ; ; Scan MPATH for DU element in BC ; MPATHBC: PUSH H ;SAVE PTR TO NEXT PATH ELEMENT LXI H,MPATH ;PT TO MINIMUM PATH MPATH4: MOV A,M ;CHECK FOR END OF PATH ORA A JRZ MPATH6 INX H ;PT TO USER CMP B ;CHECK FOR DISK MATCH JRNZ MPATH5 MOV A,M ;GET USER CMP C ;CHECK FOR USER MATCH JRNZ MPATH5 POP H ;MATCH, SO BC IS DUPLICATE JR MPATH1 ;CONTINUE MPATH5: INX H ;PT TO NEXT ELEMENT JR MPATH4 ; ; No match, so BC is a unique DU and store it in path ; MPATH6: MOV M,B ;STORE DRIVE INX H MOV M,C ;STORE USER INX H MVI M,0 ;STORE ENDING 0 POP H ;PT TO NEXT ENTRY JR MPATH1 ;CONTINUE ; ; MPATH now contains the minimal path ; MPATH7: ; ENDIF ;MINPATH ; ; Non-MINPATH Processing: ; If DRVPREFIX or SCANCUR are TRUE, look in DU in FCBDN ; IF (NOT MINPATH) AND (DRVPREFIX OR SCANCUR) LXI D,FCBDN ;LOOK FOR FILE CALL FCBLOG ;LOG INTO FCB CALL SEAR1 JNZ MLA4 ENDIF ;(NOT MINPATH) AND (DRVPREFIX OR SCANCUR) ; ; Select current disk at all times ; XRA A STA FCBDN ;SET CURRENT DISK MLARUN: ; ; The following selects the path to be followed; if the Minimal Path is ; available, it is followed; else, the Symbolic Path is followed ; IF MINPATH ;IF MINIMAL PATH USED LXI H,MPATH ;PT TO MINIMAL PATH ELSE ;NOT MINPATH LXI H,PATH ;PT TO SYMBOLIC PATH ENDIF ;MINPATH ; ; This is the main path search loop; HL pts to the next path element ; MLA0: MOV A,M ;GET DRIVE ORA A ;0=DONE=COMMAND NOT FOUND ; IF NOT CMDRUN ;ERROR ABORT IF NO COMMAND RUN FACILITY JZ ERROR ;PATH EXHAUSTED ; ELSE ;CONTINUE PROCESSING FOR COMMAND RUN ; ; CMDRUN Facility ; JRNZ NOCRUN ;NOT READY FOR CMD RUN YET CRFLAG EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;CHECK CRFLAG ORA A ;0=NO JZ ERROR ;PROCESS AS ERROR IF CMD RUN EXHAUSTED ; IF ROOTONLY ;ONLY LOOK FOR EXT COMMAND PROCESSOR AT ROOT PUSH H ;SAVE PTR TO PATH END ENDIF ;ROOTONLY ; XRA A ;DO NOT REENTER THIS CODE STA CRFLAG ;SET ZERO FOR NO ENTRY LXI H,CFCB ;SET CFCB AS COMMAND LXI D,FCBDN ;... BY COPYING IT INTO FCBDN MVI B,12 ;ONLY 12 BYTES REQUIRED CALL LDIR LHLD CURCMD ;GET PTR TO CURRENT COMMAND LINE CALL PARSET ;PARSE AS COMMAND TAIL ; IF ROOTONLY ;LOOK FOR EXT COMMAND PROCESSOR AT ROOT ONLY? JR MLA3RT ;PROCESS FROM PATH END ELSE ;FOLLOW PATH LOOKING FOR EXT COMMAND PROCESSOR ; JR MLARUN ;NOW TRY THE RUN FROM THE PATH ; ENDIF ;ROOTONLY ; CFCB: CMDFCB ;FCB DEFINING INITIAL COMMAND NOCRUN: ENDIF ;CMDRUN ; ; LOOK FOR COMMAND IN DIRECTORY PTED TO BY HL; DRIVE IN A ; IF NOT MINPATH CPI CURIND ;CURRENT DRIVE SPECIFIED? JRNZ MLA1 ;SKIP DEFAULT DRIVE SELECTION IF SO LDA CURDR ;GET CURRENT DRIVE INR A ;SET A=1 ENDIF ;NOT MINPATH ; MLA1: STA TEMPDR ;SELECT DIFFERENT DRIVE IF NOT CURRENT INX H ;PT TO USER NUMBER MOV A,M ;GET USER NUMBER INX H ;PT TO NEXT ENTRY IN PATH PUSH H ;SAVE PTR ; IF NOT MINPATH ANI 7FH ;MASK OUT SYSTEM BIT CPI CURIND ;CURRENT USER SPECIFIED? JRNZ MLA2 ;DO NOT SELECT CURRENT USER IF SO LDA CURUSR ;GET CURRENT USER NUMBER MLA2: ENDIF ;NOT MINPATH ; STA TEMPUSR ;SET TEMPORARY USER NUMBER CMA ;FLIP BITS SO SYSTEM BIT IS 0 IF SYS-ONLY ANI 80H ;MASK FOR ONLY NOT OF SYSTEM BIT TO SHOW JRNZ MLA3 ;DON'T SET FLAG IF ORIGINALLY SYSTEM BIT=0 STA SYSTST ;TEST FLAG IS 0 FOR SYS-ONLY, 1 FOR BOTH MLA3: CALL SLOGIN ;LOG IN PATH-SPECIFIED USER/DISK MLA3RT: LXI D,FCBDN ;PT TO FCB CALL SEAR1 ;LOOK FOR FILE POP H ;GET PTR TO NEXT PATH ENTRY JRZ MLA0 ;CONTINUE PATH SEARCH IF SEARCH FAILED ;LOAD IF SEARCH SUCCEEDED ; ; FILE FOUND -- PERFORM SYSTEM TEST AND PROCEED IF APPROVED ; MLA4: PUSH H ;SAVE PTR CALL GETSBIT ;CHECK SYSTEM BIT POP H ;GET PTR JRZ MLA0 ;CONTINUE IF NO MATCH CALL OPENF ;OPEN FILE FOR INPUT LOADADR EQU $+1 ;MEMORY LOAD ADDRESS (IN-LINE CODE MOD) LXI H,TPA ;SET START ADDRESS OF MEMORY LOAD MLA5: MVI A,ENTRY/256-1 ;GET HIGH-ORDER ADR OF JUST BELOW CPR CMP H ;ARE WE GOING TO OVERWRITE THE CPR? JRC PRNLE ;ERROR IF SO PUSH H ;SAVE ADDRESS OF NEXT SECTOR XCHG ;... IN DE CALL DMASET ;SET DMA ADDRESS FOR LOAD LXI D,FCBDN ;READ NEXT SECTOR CALL READ POP H ;GET ADDRESS OF NEXT SECTOR JRNZ MLA6 ;READ ERROR OR EOF? LXI D,128 ;MOVE 128 BYTES PER SECTOR DAD D ;PT TO NEXT SECTOR IN HL JR MLA5 ; MLA6: DCR A ;LOAD COMPLETE JRNZ PRNLE ;MEMORY FULL IF NZ ; ; RETURN TO CURRENT DIRECTORY ; DLOGIN: CURDR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;PREP TO LOG IN CURRENT DRIVE CALL LOGIN ;LOGIN CURRENT DRIVE CURUSR EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;PREP TO LOG IN CURRENT USER NUMBER JMP SETUSR ;LOG IN NEW USER ; ; LOAD ERROR ; PRNLE: CALL PRINTC DB 'Ful','l'+80H JMP RESTRT ;RESTART ZCPR ;***** ; ; DEFAULT PATH USED FOR PATH COMMAND-SEARCH ; IF EXPATH EQ 0 ;USE THIS PATH? ; PATH: IPATH ;PATH DEFINED IN Z3HDR.LIB ; ENDIF ;INTPATH ; ;***** ; ; INTERNAL MINIMUM PATH ; IF MINPATH MPATH: DS EXPATHS+3 ;SIZE OF PATH, MAX ; (+2 FOR DU:COM PREFIX, +1 FOR ENDING 0) ENDIF ;MINPATH ;***** IF EXTSTK NE 0 ;EXTERNAL STACK STACK EQU EXTSTK+48 ;SET TOP-OF-STACK ADDRESS ELSE ; ; STACK AREA ; DS 48 ;STACK AREA STACK EQU $ ;TOP OF STACK ; ENDIF ;INTSTACK ; IF PWCHECK PWLIN EQU STACK-48 ;PLACE LINE AT BOTTOM OF STACK ENDIF ;PWCHECK ; ; The following will cause an error message to appear if ; the size of ZCPR3 is over 2K bytes. ; IF ($ GT CPRLOC+800H) ZCPR3ER EQU NOVALUE ;ZCPR3 IS LARGER THAN 2K BYTES ENDIF END  ; PROGRAM: SYSRCP.ASM ; AUTHOR: RICHARD CONN ; VERSION: 1.0 ; DATE: 3 FEB 84 ; PREVIOUS VERSIONS: NONE ; VERSION EQU 13 ; 08/05/86 Mark Dapoz ; Version 1.3L. Added code from experimental RCP for additional ; features. See documentation in EXPRCP.ASM for details. ; 09/06/85 Jay Sage ; Version 1.3. Modified peek command to work with last page of ; memory by changing the code for detecting the end of the specified ; memory range to handle overflow past FFFF. I added a new equate in ; the code below (PEEKCHK). If PEEKCHK is TRUE, then a peek command ; display will never go past address FFFF to 0000. This feature costs ; five extra bytes, so some people may want to disable it. The command ; "P 100 100" will now work and display one line of bytes. Corrected ; error in @GENDD macro and renamed macros for ZAS compatibility. ; Changed name of symbols I and J to II and JJ because the symbol I ; conflicts with the I register of the Z80. A bug in ZAS V2.0 prevents ; it from assembling the file to a correct hex file (later versions will, ; one hopes, correct this problem). ZAS V1.4 can be used if the files ; in the MACLIB statements below are changed to include the file type ; LIB explicitly. ; 07/21/85 Jay Sage ; Version 1.2. Added TST command to test the program error flag. ; Also made CLS command optionally use TCAP for clear screen sequence. ; 04/28/85 Jay Sage ; Added WHLQUIET equate to make WHL command not report wheel status ; changes as an added measure of security, especially during alias operations ; that set the wheel byte temporarily. An RCPM user might, on seeing the ; 'whl byte on' message, try to interrupt program execution. ; 02/22/85 Jay Sage ; Corrected omission of wheel check based on WREG equate in SYSRCP.LIB. ; 02/14/85 Jay Sage ; Modified CP command to use the top of the TPA for buffering so ; that the GO command will still work in most cases after CP is ; finished. The equate COPYTOP determines whether the new or the ; old code will be generated. ; 02/13/85 Jay Sage ; Added code for an R (disk reset) and a CLS (clear screen) function. ; ; SYSRCP is a resident command processor for ZCPR3. As with ; all resident command processors, SYSRCP performs the following functions: ; ; 1. Assuming that the EXTFCB contains the name of the ; command, SYSRCP looks to see if the first character ; of the file name field in the EXTFCB is a question ; mark; if so, it returns with the Zero Flag Set and ; HL pointing to the internal routine which prints ; its list of commands ; 2. The resident command list in SYSRCP is scanned for ; the entry contained in the file name field of ; EXTFCB; if found, SYSRCP returns with the Zero Flag ; Set and HL pointing to the internal routine which ; implements the function; if not found, SYSRCP returns ; with the Zero Flag Reset (NZ) ; ; ; Global Library which Defines Addresses for SYSRCP ; MACLIB Z3BASE ; USE BASE ADDRESSES MACLIB SYSRCP ; USE SYSRCP HEADER PEEKCHK EQU TRUE ; SET TRUE TO INCLUDE CODE TO ;PREVENT OVERFLOW PAST FFFF WITH PEEK ;COMMAND (COSTS 5 BYTES OF CODE) CTRLC EQU 'C'-'@' TAB EQU 09H LF EQU 0AH FF EQU 0CH CR EQU 0DH CTRLX EQU 'X'-'@' CTRLZ EQU 'Z'-'@' ; WBOOT EQU BASE+0000H ;CP/M WARM BOOT ADDRESS UDFLAG EQU BASE+0004H ;USER NUM IN HIGH NYBBLE, DISK IN LOW BDOS EQU BASE+0005H ;BDOS FUNCTION CALL ENTRY PT TFCB EQU BASE+005CH ;DEFAULT FCB BUFFER FCB1 EQU TFCB ;1st and 2nd FCBs FCB2 EQU TFCB+16 TBUFF EQU BASE+0080H ;DEFAULT DISK I/O BUFFER TPA EQU BASE+0100H ;BASE OF TPA DIRBUF EQU BASE+4000H ;DIR BUFFER (MANY ENTRIES PERMITTED) PAGCNT EQU DIRBUF-100H ;PAGE COUNT BUFFER OLDFCB EQU PAGCNT+1 ;OLD FCB BUFFER ;CPBLOCKS EQU 64 ;BUF SIZE - MOVED TO SYSRCP.LIB ; ; MACROS TO PROVIDE Z80 EXTENSIONS ; MACROS INCLUDE: ; ; DJNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO ; BR - JUMP RELATIVE ; BRC - JUMP RELATIVE IF CARRY ; BRNC - JUMP RELATIVE IF NO CARRY ; BRZ - JUMP RELATIVE IF ZERO ; BRNZ - JUMP RELATIVE IF NO ZERO ; DBNZ - DECREMENT B AND JUMP RELATIVE IF NO ZERO ; ; @GENDD MACRO USED FOR CHECKING AND GENERATING ; 8-BIT JUMP RELATIVE DISPLACEMENTS ; @GENDD MACRO ?DD ;;USED FOR CHECKING RANGE OF 8-BIT DISPLACEMENTS IF (?DD GT 7FH) AND (?DD LT 0FF80H) DB 100H ;Displacement Range Error on Jump Relative ELSE DB ?DD ENDIF ;;RANGE ERROR ENDM ; ; ; Z80 MACRO EXTENSIONS ; BR MACRO ?N ;;JUMP RELATIVE IF I8080 ;;8080/8085 JMP ?N ELSE ;;Z80 DB 18H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM BRC MACRO ?N ;;JUMP RELATIVE ON CARRY IF I8080 ;;8080/8085 JC ?N ELSE ;;Z80 DB 38H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM BRNC MACRO ?N ;;JUMP RELATIVE ON NO CARRY IF I8080 ;;8080/8085 JNC ?N ELSE ;;Z80 DB 30H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM BRZ MACRO ?N ;;JUMP RELATIVE ON ZERO IF I8080 ;;8080/8085 JZ ?N ELSE ;;Z80 DB 28H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM BRNZ MACRO ?N ;;JUMP RELATIVE ON NO ZERO IF I8080 ;;8080/8085 JNZ ?N ELSE ;;Z80 DB 20H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM DBNZ MACRO ?N ;;DECREMENT B AND JUMP RELATIVE ON NO ZERO IF I8080 ;;8080/8085 DCR B JNZ ?N ELSE ;;Z80 DB 10H @GENDD ?N-$-1 ENDIF ;;I8080 ENDM ; ; SYSTEM Entry Point ; org rcp ; passed for Z3BASE db 'Z3RCP' ; Flag for Package Loader ; ; **** Command Table for RCP **** ; This table is RCP-dependent! ; ; The command name table is structured as follows: ; ; ctable: ; DB 'CMNDNAME' ; Table Record Structure is ; DW cmndaddress ; 8 Chars for Name and 2 Bytes for Adr ; ... ; DB 0 ; End of Table ; cnsize equ CMDLEN ; NUMBER OF CHARS IN COMMAND NAME db cnsize ; size of text entries ctab: HELPCMD ;macro to provide name of help command ; db 'H ' ; Help for RCP dw clist ctab1: IF CLSON CLSCMD ;macro to provide name of clear screen command ; db 'CLS ' ; Clear Screen dw cls ENDIF ;CLSON IF CPON CPCMD ;macro to provide name of copy command ; db 'CP ' ; Copy dw copy ENDIF ;CPON IF DIRON DIRCMD ;macro to provide name of directory command ; db 'DIR ' ; Directory dw dir ENDIF ;DIRON IF ECHOON ECHOCMD ;macro to provide name of echo command ; db 'ECHO' ; Echo dw echo ENDIF IF ERAON ERACMD ;macro to provide name of erase command ; db 'ERA ' ; Erase dw era ENDIF ;ERAON IF LTON AND LISTON LISTCMD ;macro to provide name of list command ; db 'LIST' ; List dw list ENDIF ;LTON AND LISTON IF NOTEON NOTECMD ;macro to provide name of note command ; db 'NOTE' ; Note-Comment-NOP Command dw note ENDIF IF PEEKON PEEKCMD ;macro to provide name of peek command ; db 'P ' ; Peek into Memory dw peek ENDIF ;PEEKON IF POKEON POKECMD ;macro to provide name of poke command ; db 'POKE' ; Poke Values into Memory dw poke ENDIF ;POKEON IF PROTON PROTCMD ;macro to provide name of protect command ; db 'PROT' ; Protection Codes dw att ENDIF ;PROTON IF RESON RESETCMD ;macro to provide name of disk reset command ; db 'R ' dw reset ENDIF ;RESON IF REGON REGCMD ;macro to provide name of register command ; db 'REG ' ; Register Command dw register ENDIF ;RSETON IF RENON RENCMD ;macro to provide name of rename command ; db 'REN ' ; Rename dw ren ENDIF ;RENON IF TSTON TESTCMD ;macro to provide name of error testing command ; db 'TST ' ; Type dw testerr ENDIF ;LTON IF LTON TYPECMD ;macro to provide name of type command ; db 'TYPE' ; Type dw type ENDIF ;LTON IF WHLON WHLCMD ;macro to provide name of wheel setting command ; db 'WHL ' ; Wheel dw whl WHLQCMD ;macro to provide name of wheel query command ; db 'WHLQ' ; Wheel Query dw whlmsg ENDIF ;WHLON ; IF EDON ENACMD ;macro to provide name of enable command ; db 'ENA ' ; Enable Wheel dw ena DISCMD ;macro to provide name of disable command ; DB 'D'+80H ; db 'IS ' ; Disable Wheel dw dis ENDIF ;EDON ; db 0 ; ; BANNER NAME OF RCP ; rcp$name: db 'SYS ' db (version/10)+'0','.',(version mod 10)+'0' db RCPID db 0 ; ; Command List Routine ; clist: lxi h,rcp$name ; print RCP Name call print1 lxi h,ctab1 ; print table entries mvi c,1 ; set count for new line clist1: mov a,m ; done? ora a rz lxi d,entryname ; copy command name into message buffer mvi b,cnsize ; number of chars clist2: mov a,m ; copy stax d inx h ; pt to next inx d dcr b jnz clist2 inx h ; skip to next entry inx h push h ; save ptr ; *** ; Changed this routine so that routines that could not be run with out wheel ; were not shown. Had to change SCANNER in ZCPR3.ASM too! ; *** if z3whl lda z3whl ; get the wheel byte ora a ; check it brnz clshow ; if on always show the command lda entryname ; get first character ani 80h ; isolate the high order bit brnz clskip ; if a wheel command (B7 <> 0) Don't Show it endif ; z3whl (adds 21 bytes) clshow: lda entryname ; turn off that high order bit ani 7fh ; so print doesn't get confused sta entryname ; store it back dcr c ; moved this code from up above brnz clshow1 ; if not 0 yet no crlf needed call crlf ; print a crlf mvi c,4 ; re intialize it clshow1: lxi h,entrymsg ; print message call print1 clskip: pop h ; get ptr jmp clist1 ; ; Console Output Routine ; conout: push h ; save regs push d push b push psw ani 7fh ; mask MSB mov e,a ; char in E mvi c,2 ; output call bdos pop psw ; get regs pop b pop d pop h ; ; This simple return doubles for the NOTE Command (NOP) and CONOUT Exit ; NOTE Command: NOTE any text ; NOTE: ret ; ; Print String (terminated in 0 or MSB Set) at Return Address ; print: xthl ; get address call print1 xthl ; put address ret ; ; Print String (terminated in 0 or MSB Set) pted to by HL ; print1: mov a,m ; done? inx h ; pt to next ora a ; 0 terminator rz call conout ; print char rm ; MSB terminator jmp print1 ; ; CLIST Messages ; entrymsg: db ' ' ; command name prefix entryname: ds cnsize ; command name db 0 ; terminator ; ; **** RCP Routines **** ; All code from here on is RCP-dependent! ; ; ;Section 4A ;Command: CLS ;Function: To clear the CRT screen ;Restrictions: The setting of the CLSTCAP equate determines whether this ; command uses the TCAP information or not. If not, it uses the ; clear-screen string passed in macro CLSSTR. That string should ; end with the high bit set. ; IF CLSON CLS: IF CLSTCAP ;if using TCAP for clear screen string LXI H,Z3ENV+80H ;point to beginning of TCAP MOV A,M ;see if blank CPI ' '+1 BRNC CLS1 ;if not, go to clear screen code CALL PRINT ;if blank, then give error message DB ' NO TCA','P'+80H RET CLS1: LXI H,Z3ENV+97H ;point to beginning of clear screen string CLS2: MOV A,M ;get character ORA A ;test for end of string RZ CALL CONOUT ;send character to console INX H ;point to next character BR CLS2 ELSE ;NOT USING TCAP CALL PRINT CLSSTR ;string from SYSRCP.LIB RET ENDIF ;CLSTCAP ENDIF ;CLSON ; ;Section 4B ;Command: RESET ;Function: To reset the disk system to force relogging in of disks ;Comments: ZRDOS does not require a disk system reset when disks are ; changed, but directory programs will not show the correct ; size if this is not done. ; IF RESON RESET: MVI C,13 ;disk reset BDOS function IF RESMSG CALL BDOS ;reset disk system CALL PRINT ;report action DB 'rese','t'+80h RET ELSE ;NOT RESMSG JMP BDOS ;call BDOS and return ENDIF ;RESMSG ENDIF ;RESON ;Section 4C ;Command: TST ;Function: To set the message buffer program error flag based on ; error count reported by ZAS, M80, or L80 ;Forms: TST PN where PN is first letter of ZAS, M80, or L80 IF TSTON ; Equates for addresses where error counts are kept by the programs to be tested ; M80/F80, Version 3.44 m80f equ 03cedh ;addr of word with fatal error count (M80) m80w equ 03cefh ;addr of word with warning error count (M80) f80f equ 001c1h ;addr of word with fatal error count (F80) f80w equ 002adh ;addr of word with warning error count (F80) ; ZAS Version 2.0 zasf equ 010aah ;addr of word with fatal error count (ZAS) testerr: if z3msg eq 0 ;if no message buffer, give error message *** ERROR *** this code cannot be used unless the ZCPR3 message buffer is implemented else ;generate code ;check for name of program to test lda fcb1+1 ;get first character in command tail if testm80 lxi h,m80f ;preset for M80 test counts lxi d,m80w cpi 'M' brz testcount endif ;testm80 if testf80 lxi h,f80f lxi d,f80w cpi 'F' brz testcount endif ;testf80 if testzas lxi h,zasf mov d,h ;use zasf twice (shorter code) mov e,l ;since ZAS has only one count cpi 'Z' brz testcount endif ;testzas ;if no match, give error message call print badtailmsg: db 'bad nam' db 'e' or 80h testcount: mov a,m ;test first error count word inx h ora m xchg ;test second word ora m inx h ora m lxi h,z3msg+6 ;point to program error flag mvi m,0 ;clear it rz ;if counts were zero, we are done mvi m,0ffh ;else set the error flag ret endif ;z3msg ENDIF ;TSTON ; ;Section 5A ;Command: DIR ;Function: To display a directory of the files on disk ;Forms: ; DIR Displays the DIR files ; DIR S Displays the SYS files ; DIR A Display both DIR and SYS files ;Notes: ; The flag SYSFLG defines the letter used to display both DIR and ; SYS files (A in the above Forms section) ; The flag SOFLG defines the letter used to display only the SYS ; files (S in the above Forms section) ; The flag WIDE determines if the file names are spaced further ; apart (WIDE=TRUE) for 80-col screens ; The flag FENCE defines the character used to separate the file ; names ; IF DIRON DIR: ; ; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED ; IF WDIR CALL WHLTST ENDIF ;WHEEL APPROVAL ; CALL RETSAVE ;SAVE RET ADDRESS AND SET STACK LXI H,FCB1+1 ;MAKE FCB WILD (ALL '?') IF NO FILENAME.TYP MOV A,M ;GET FIRST CHAR OF FILENAME.TYP CPI ' ' ;IF , ALL WILD CZ FILLQ LDA FCB2+1 ;GET FIRST CHAR OF 2ND FILE NAME MVI B,80H ;PREPARE FOR DIR-ONLY SELECTION CPI ' ' ;ANY FLAG? BRZ DIRPR ;THERE IS NO FLAG, SO DIR ONLY MVI B,1 ;SET FOR BOTH DIR AND SYS FILES CPI SYSFLG ;SYSTEM AND DIR FLAG SPECIFIER? BRZ DIRPR ;GOT SYSTEM SPECIFIER CPI SOFLG ;SYS ONLY? BRNZ DIRPR DCR B ;B=0 FOR SYS FILES ONLY ; ENDIF ;DIRON ; ; DIRECTORY PRINT ROUTINE; ON ENTRY, B REG IS SET AS FOLLOWS: ; 0 FOR ONLY SYSTEM FILES, 80H FOR ONLY DIR FILES, 1 FOR BOTH ; IF DIRON OR ERAON OR LTON OR PROTON OR CPON OR RENON DIRPR: MOV A,B ;GET SYSTST FLAG CALL GETDIR ;LOAD AND SORT DIRECTORY JZ PRFNF ;PRINT NO FILE MESSAGE MVI E,4 ;COUNT DOWN TO 0 ; ; ENTRY PRINT LOOP; ON ENTRY, HL PTS TO FILES SELECTED (TERMINATED BY 0) ; AND E IS ENTRY COUNTER ; DIR3: MOV A,M ;CHECK FOR DONE ORA A JZ EXIT ;EXIT IF DONE MOV A,E ;GET ENTRY COUNTER ORA A ;OUTPUT IF 4 ENTRIES PRINTED IN LINE CZ DIRCRLF ;NEW LINE MOV A,E ;GET ENTRY COUNT CPI 4 ;FIRST ENTRY? BRZ DIR4 CALL PRINT ; IF WIDE ; DB ' ' ;2 SPACES DB FENCE ;THEN FENCE CHAR DB ' '+80H ;THEN 1 MORE SPACE ; ELSE ; DB ' ' ;SPACE DB FENCE+80H ;THEN FENCE CHAR ; ENDIF ;WIDE ; DIR4: CALL PRFN ;PRINT FILE NAME CALL BREAK ;CHECK FOR ABORT DCR E ;DECREMENT ENTRY COUNTER BR DIR3 ; ; CRLF FOR DIR ROUTINE ; DIRCRLF: PUSH PSW ;DON'T AFFECT PSW CALL CRLF ;NEW LINE POP PSW MVI E,4 ;RESET ENTRY COUNTER RET ; ; AFTER A SEARCH, RETURN NZ SET IF DESIRED TYPE OF FILE FOUND, Z IF NOT ; THIS ALGORITHM LOOKS AT THE SYSTEM BIT OF THE LOCATED FILE; THIS ; BIT IS SET TO 1 IF THE FILE IS A SYSTEM FILE AND 0 IF NOT A SYSTEM ; FILE. THE FOLLOWING EXCLUSIVE OR MASKS ARE APPLIED TO RETURN Z OR NZ ; AS REQUIRED BY THE CALLING PROGRAM: ; ; SYSTEM BYTE: X 0 0 0 0 0 0 0 (AFTER 80H MASK, X=1 IF SYS, 0 IF DIR) ; ; SYS-ONLY : 0 0 0 0 0 0 0 0 (XOR 0 = 0 if X=0, = 80H if X=1) ; DIR-ONLY : 1 0 0 0 0 0 0 0 (XOR 80H = 80h if X=0, = 0 if X=1) ; BOTH : 0 0 0 0 0 0 0 1 (XOR 1 = 81H or 1H, NZ in both cases) ; GETSBIT: DCR A ;ADJUST TO RETURNED VALUE RRC ;CONVERT NUMBER TO OFFSET INTO TBUFF RRC RRC ANI 60H MOV C,A ;OFFSET INTO TBUFF IN C (C=OFFSET TO ENTRY) LXI D,TBUFF ;PT TO BUFFER MOV A,E ;BASE ADDRESS IN A ADD C ;ADD IN ENTRY OFFSET MOV E,A ;RESULT IN E PUSH D ;SAVE PTR IN DE ADI 10 ;ADD OFFSET OF 10 TO PT TO SYSTEM BYTE MOV E,A ;SET ADDRESS LDAX D ;GET BYTE POP D ;GET PTR IN DE ANI 80H ;LOOK AT ONLY SYSTEM BIT SYSTST EQU $+1 ;IN-THE-CODE VARIABLE XRI 0 ; IF SYSTST=0, SYS ONLY; IF SYSTST=80H, DIR ; ONLY; IF SYSTST=1, BOTH SYS AND DIR RET ;NZ IF OK, Z IF NOT OK ; ; FILL FCB @HL WITH '?' ; FILLQ: MVI B,11 ;NUMBER OF CHARS IN FN & FT MVI A,'?' ;STORE '?' FILLP: MOV M,A ;STORE BYTE INX H ;PT TO NEXT DBNZ FILLP ;COUNT DOWN RET ; ; LOAD DIRECTORY AND SORT IT ; ON INPUT, A=SYSTST FLAG (0=SYS, 1=DIR, 80H=BOTH) ; DIRECTORY IS LOADED INTO DIRBUF ; RETURN WITH ZERO SET IF NO MATCH AND HL PTS TO 1ST ENTRY IF MATCH ; GETDIR: STA SYSTST ; SET SYSTEM TEST FLAG CALL LOGUSR ; LOG INTO USER AREA OF FCB1 LXI H,DIRBUF ; PT TO DIR BUFFER MVI M,0 ; SET EMPTY LXI B,0 ; SET COUNTER CALL SEARF ; LOOK FOR MATCH RZ ; RETURN IF NOT FOUND ; ; STEP 1: LOAD DIRECTORY ; GD1: PUSH B ; SAVE COUNTER CALL GETSBIT ; CHECK FOR SYSTEM OK POP B BRZ GD2 ; NOT OK, SO SKIP PUSH B ; SAVE COUNTER INX D ; PT TO FILE NAME XCHG ; HL PTS TO FILE NAME, DE PTS TO BUFFER MVI B,11 ; COPY 11 BYTES CALL LDIR ; DO COPY XCHG ; HL PTS TO NEXT BUFFER LOCATION POP B ; GET COUNTER INX B ; INCREMENT COUNTER GD2: CALL SEARN ; LOOK FOR NEXT BRNZ GD1 MVI M,0 ; STORE ENDING 0 LXI H,DIRBUF ; PT TO DIR BUFFER MOV A,M ; CHECK FOR EMPTY ORA A RZ ; ; STEP 2: SORT DIRECTORY ; PUSH H ; SAVE PTR TO DIRBUF FOR RETURN CALL DIRALPHA ; SORT POP H XRA A ; SET NZ FLAG FOR OK DCR A RET ; ; DIRALPHA -- ALPHABETIZES DIRECTORY IN DIRBUF; BC CONTAINS ; THE NUMBER OF FILES IN THE DIRECTORY ; DIRALPHA: MOV A,B ; ANY FILES? ORA C RZ MOV H,B ; HL=BC=FILE COUNT MOV L,C SHLD N ; SET "N" ; ; SHELL SORT -- ; THIS SORT ROUTINE IS ADAPTED FROM "SOFTWARE TOOLS" ; BY KERNIGAN AND PLAUGHER, PAGE 106. COPYRIGHT, 1976, ADDISON-WESLEY. ; ON ENTRY, BC=NUMBER OF ENTRIES ; N EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION LXI H,0 ; NUMBER OF ITEMS TO SORT SHLD GAP ; SET INITIAL GAP TO N FOR FIRST DIVISION BY 2 ; FOR (GAP = N/2; GAP > 0; GAP = GAP/2) SRTL0: ORA A ; CLEAR CARRY GAP EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION LXI H,0 ; GET PREVIOUS GAP MOV A,H ; ROTATE RIGHT TO DIVIDE BY 2 RAR MOV H,A MOV A,L RAR MOV L,A ; TEST FOR ZERO ORA H RZ ; DONE WITH SORT IF GAP = 0 SHLD GAP ; SET VALUE OF GAP SHLD II ; SET II=GAP FOR FOLLOWING LOOP ; FOR (II = GAP + 1; II <= N; II = II + 1) SRTL1: II EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION LXI H,0 ; ADD 1 TO II INX H SHLD II ; TEST FOR II <= N XCHG ; II IS IN DE LHLD N ; GET N MOV A,L ; COMPARE BY SUBTRACTION SUB E MOV A,H SBB D ; CARRY SET MEANS II > N BRC SRTL0 ; DON'T DO FOR LOOP IF II > N LHLD II ; SET JJ = II INITIALLY FOR FIRST SUBTRACTION OF GAP SHLD JJ ; FOR (JJ = II - GAP; JJ > 0; JJ = JJ - GAP) SRTL2: LHLD GAP ; GET GAP XCHG ; ... IN DE JJ EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION LXI H,0 ; GET JJ MOV A,L ; COMPUTE JJ - GAP SUB E MOV L,A MOV A,H SBB D MOV H,A SHLD JJ ; JJ = JJ - GAP BRC SRTL1 ; IF CARRY FROM SUBTRACTIONS, JJ < 0 AND ABORT MOV A,H ; JJ=0? ORA L BRZ SRTL1 ; IF ZERO, JJ=0 AND ABORT ; SET JG = JJ + GAP XCHG ; JJ IN DE LHLD GAP ; GET GAP DAD D ; JJ + GAP SHLD JG ; JG = JJ + GAP ; IF (V(JJ) <= V(JG)) CALL ICOMPARE ; J IN DE, JG IN HL ; ... THEN BREAK BRC SRTL1 ; ... ELSE EXCHANGE LHLD JJ ; SWAP JJ, JG XCHG JG EQU $+1 ; POINTER FOR IN-THE-CODE MODIFICATION LXI H,0 CALL ISWAP ; JJ IN DE, JG IN HL ; END OF INNER-MOST FOR LOOP BR SRTL2 ; ; SWAP (Exchange) the elements whose indexes are in HL and DE ; ISWAP: CALL IPOS ; COMPUTE POSITION FROM INDEX XCHG CALL IPOS ; COMPUTE 2ND ELEMENT POSITION FROM INDEX MVI B,11 ; 11 BYTES TO FLIP ISWAP1: LDAX D ; GET BYTES MOV C,M MOV M,A ; PUT BYTES MOV A,C STAX D INX H ; PT TO NEXT INX D DBNZ ISWAP1 RET ; ; ICOMPARE compares the entry pointed to by the pointer pointed to by HL ; with that pointed to by DE (1st level indirect addressing); on entry, ; HL and DE contain the numbers of the elements to compare (1, 2, ...); ; on exit, Carry Set means ((DE)) < ((HL)), Zero Set means ((HL)) = ((DE)), ; and Non-Zero and No-Carry means ((DE)) > ((HL)) ; ICOMPARE: CALL IPOS ; GET POSITION OF FIRST ELEMENT XCHG CALL IPOS ; GET POSITION OF 2ND ELEMENT XCHG ; ; COMPARE DIR ENTRY PTED TO BY HL WITH THAT PTED TO BY DE; ; NO NET EFFECT ON HL, DE; RET W/CARRY SET MEANS DE Erase Specified files and print their names ; ERA I Erase Specified files and print their names, but ask ; for verification before Erase is done ; IF ERAON ERA: ; ; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED ; IF WERA CALL WHLTST ENDIF ;WHEEL APPROVAL ; CALL RETSAVE LDA FCB2+1 ;GET ERAFLG IF IT'S THERE STA ERAFLG ;SAVE IT AS A FLAG MVI A,1 ;DIR FILES ONLY CALL GETDIR ;LOAD DIRECTORY OF FILES JZ PRFNF ;ABORT IF NO FILES ; ; MAIN ERASE LOOP ; ERA1: PUSH H ;SAVE PTR TO FILE CALL PRFN ;PRINT ITS NAME SHLD NXTFILE ;SAVE PTR TO NEXT FILE POP H ;GET PTR TO THIS FILE CALL ROTEST ;TEST FILE PTED TO BY HL FOR R/O BRNZ ERA3 ERAFLG EQU $+1 ;ADDRESS OF FLAG MVI A,0 ;2ND BYTE IS FLAG CPI 'I' ;IS IT AN INSPECT OPTION? BRNZ ERA2 ;SKIP PROMPT IF IT IS NOT CALL ERAQ ;ERASE? BRNZ ERA3 ;SKIP IF NOT ERA2: LXI D,FCB1+1 ;COPY INTO FCB1 MVI B,11 ;11 BYTES CALL LDIR CALL INITFCB1 ;INIT FCB MVI C,19 ;DELETE FILE CALL BDOS ERA3: LHLD NXTFILE ;HL PTS TO NEXT FILE MOV A,M ;GET CHAR ORA A ;DONE? JZ EXIT CALL CRLF ;NEW LINE BR ERA1 ; ENDIF ;ERAON ; ;Section 5C ;Command: LIST ;Function: Print out specified file on the LST: Device ;Forms: ; LIST Print file (NO Paging) ;Notes: ; The flags which apply to TYPE do not take effect with LIST ; IF LTON LIST: ; ; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED ; IF WLIST CALL WHLTST ENDIF ;WHEEL APPROVAL ; CALL RETSAVE MVI A,0FFH ;TURN ON PRINTER FLAG BR TYPE0 ; ;Section 5D ;Command: TYPE ;Function: Print out specified file on the CON: Device ;Forms: ; TYPE Print file ; TYPE P Print file with paging flag ;Notes: ; The flag PGDFLG defines the letter which toggles the paging ; facility (P in the forms section above) ; The flag PGDFLT determines if TYPE is to page by default ; (PGDFLT=TRUE if TYPE pages by default); combined with ; PGDFLG, the following events occur -- ; If PGDFLT = TRUE, PGDFLG turns OFF paging ; If PGDFLT = FALSE, PGDFLG turns ON paging ; TYPE: ; ; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED ; IF WTYPE CALL WHLTST ENDIF ;WHEEL APPROVAL ; CALL RETSAVE XRA A ;TURN OFF PRINTER FLAG ; ; ENTRY POINT FOR CPR LIST FUNCTION (LIST) ; TYPE0: STA PRFLG ;SET FLAG LDA FCB2+1 ;GET PAGE FLAG STA PGFLG ;SAVE IT AS A FLAG MVI A,1 ;SELECT DIR FILES CALL GETDIR ;ALLOW AMBIGUOUS FILES JZ PRFNF ;NO FILES SHLD NXTFILE ;SET PTR TO NEXT FILE BR TYPEX2 TYPEX: LHLD NXTFILE ;GET PTR TO NEXT FILE MOV A,M ;ANY FILES? ORA A JZ EXIT LDA PRFLG ;CHECK FOR LIST OUTPUT ORA A ;0=TYPE BRZ TYPEX1 MVI A,CR ;BOL ON PRINTER CALL LCOUT MVI A,FF ;FORM FEED THE PRINTER CALL LCOUT BR TYPEX2 TYPEX1: CALL PAGEBREAK ;PAGE BREAK MESSAGE TYPEX2: LXI D,FCB1+1 ;COPY INTO FCB1 MVI B,11 ;11 BYTES CALL LDIR SHLD NXTFILE ;SET PTR TO NEXT FILE CALL INITFCB1 ;INIT FCB1 MVI C,15 ;OPEN FILE CALL BDOS INR A ;SET ERROR FLAG JZ PRFNF ;ABORT IF ERROR MVI A,NLINES-2 ;SET LINE COUNT STA PAGCNT MVI A,CR ;NEW LINE CALL LCOUT MVI A,LF CALL LCOUT LXI B,080H ;SET CHAR POSITION AND TAB COUNT ; (B=0=TAB, C=080H=CHAR POSITION) ; ; MAIN LOOP FOR LOADING NEXT BLOCK ; TYPE2: MOV A,C ;GET CHAR COUNT CPI 80H BRC TYPE3 PUSH H ;READ NEXT BLOCK PUSH B LXI D,FCB1 ;PT TO FCB MVI C,20 ;READ RECORD CALL BDOS ORA A ;SET FLAGS POP B POP H BRNZ TYPE7 ;END OF FILE? MVI C,0 ;SET CHAR COUNT LXI H,TBUFF ;PT TO FIRST CHAR ; ; MAIN LOOP FOR PRINTING CHARS IN TBUFF ; TYPE3: MOV A,M ;GET NEXT CHAR ANI 7FH ;MASK OUT MSB CPI 1AH ;END OF FILE (^Z)? BRZ TYPE7 ;NEXT FILE IF SO ; ; OUTPUT CHAR TO CON: OR LST: DEVICE WITH TABULATION ; CPI CR ;RESET TAB COUNT? BRZ TYPE4 CPI LF ;RESET TAB COUNT? BRZ TYPE4 CPI TAB ;TAB? BRZ TYPE5 ; ; OUTPUT CHAR AND INCREMENT CHAR COUNT ; CALL LCOUT ;OUTPUT CHAR JZ TYPEX ;SKIP INR B ;INCREMENT TAB COUNT BR TYPE6 ; ; OUTPUT OR AND RESET TAB COUNT ; TYPE4: CALL LCOUT ;OUTPUT OR JZ TYPEX ;SKIP MVI B,0 ;RESET TAB COUNTER BR TYPE6 ; ; TABULATE ; TYPE5: MVI A,' ' ; CALL LCOUT JZ TYPEX ;SKIP INR B ;INCR POS COUNT MOV A,B ANI 7 BRNZ TYPE5 ; ; CONTINUE PROCESSING ; TYPE6: INR C ;INCREMENT CHAR COUNT INX H ;PT TO NEXT CHAR CALL BREAK ;CHECK FOR ABORT JZ TYPEX ;SKIP BR TYPE2 TYPE7: LXI D,FCB1 ;CLOSE FILE MVI C,16 ;BDOS FUNCTION CALL BDOS JMP TYPEX ; ; SEND OUTPUT TO LST: OR CON:, AS PER THE FLAG ; RETURN WITH Z IF ABORT ; LCOUT: PUSH H ;SAVE REGS PUSH D PUSH B MOV E,A ;CHAR IN E MVI C,2 ;OUTPUT TO CON: PRFLG EQU $+1 ;POINTER FOR IN-THE-CODE MODIFICATION MVI A,0 ;2ND BYTE IS THE PRINT FLAG ORA A ;0=TYPE BRZ LC1 MVI C,5 ;OUTPUT TO LST: LC1: PUSH D ;SAVE CHAR CALL BDOS ;OUTPUT CHAR IN E POP D ;GET CHAR MOV A,E CPI LF BRNZ LC2 LDA PRFLG ;OUTPUT TO LST:? ORA A ;NZ = YES BRNZ LC2 ; ; CHECK FOR PAGING ; LXI H,PAGCNT ;COUNT DOWN DCR M BRNZ LC2 ;JUMP IF NOT END OF PAUSE MVI M,NLINES-2 ;REFILL COUNTER PGFLG EQU $+1 ;POINTER TO IN-THE-CODE BUFFER MVI A,0 ;2ND BYTE IS THE PAGING FLAG CPI PGDFLG ;PAGE DEFAULT OVERRIDE OPTION WANTED? ; IF PGDFLT ;IF PAGING IS DEFAULT ; BRZ LC2 ;PGDFLG MEANS NO PAGING ; ELSE ; BRNZ LC2 ;PGDFLG MEANS PAGE ; ENDIF ;PGDFLT ; CALL PAGEBREAK ;PRINT PAGE BREAK MESSAGE BR LC3 ;Z TO SKIP LC2: XRA A ;SET OK DCR A ;NZ=OK LC3: POP B ;RESTORE REGS POP D POP H RET ; ; PRINT PAGE BREAK MESSAGE AND GET USER INPUT ; ABORT IF ^C, RZ IF ^X ; PAGEBREAK: PUSH H ;SAVE HL CALL PRINT DB cr,lf,' Typing',' '+80H LXI H,FCB1+1 ;PRINT FILE NAME CALL PRFN CALL DASH ;PRINT DASH CALL CONIN ;GET INPUT POP H ;RESTORE HL PUSH PSW CALL CRLF ;NEW LINE POP PSW CPI CTRLC ;^C JZ EXIT CPI CTRLX ;SKIP? RET ; ENDIF ;LTON ; ;Section 5E ;Command: REN ;Function: To change the name of an existing file ;Forms: ; REN = Perform function ; IF RENON REN: ; ; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED ; IF WREN CALL WHLTST ENDIF ;WHEEL APPROVAL ; CALL RETSAVE ; ; ; STEP 1: CHECK FOR FILE 2 BEING AMBIGUOUS ; LXI H,FCB2+1 ;CAN'T BE AMBIGUOUS CALL AMBCHK1 ; ; STEP 2: LOG INTO USER AREA ; CALL LOGUSR ;LOG INTO USER AREA OF FCB1 ; ; STEP 3: SEE IF NEW FILE ALREADY EXISTS ; EXTEST PERFORMS A NUMBER OF CHECKS: ; 1) AMBIGUITY ; 2) R/O ; 3) IF FILE EXISTS AND NOT R/O, PERMISSION TO DELETE ; CALL EXTEST JZ EXIT ;R/O OR NO PERMISSION ; ; STEP 4: EXCHANGE FILE NAME FIELDS FOR RENAME ; LXI H,FCB1 ;EXCHANGE NAMES ONLY PUSH H ;SAVE PTR INX H LXI D,FCB2+1 MVI B,11 ;11 BYTES REN1: LDAX D ;GET OLD MOV C,A MOV A,M STAX D ;PUT NEW MOV M,C INX H ;PT TO NEXT INX D DBNZ REN1 ; ; STEP 5: SEE IF OLD FILE IS R/O ; CALL SEARF ;LOOK FOR FILE JZ PRFNF CALL GETSBIT ;GET PTR TO ENTRY IN TBUFF XCHG ;HL PTS TO ENTRY INX H ;PT TO FN CALL ROTEST ;SEE IF FILE IS R/O JNZ EXIT ; ; STEP 6: RENAME THE FILE ; POP D ;GET PTR TO FCB MVI C,23 ;RENAME CALL BDOS INR A ;SET ZERO FLAG IF ERROR JZ PRFNF ;PRINT NO SOURCE FILE MESSAGE JMP EXIT ; ENDIF ;RENON ; ;Section 5F ;Command: PROT ;Function: To set the attributes of a file (R/O and SYS) ; ;Form: ; PROT afn RSI ;If either R or S are omitted, the file is made R/W or DIR, resp; ;R and S may be in any order. If I is present, Inspection is enabled. ; IF PROTON ATT: ; ; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED ; IF WPROT CALL WHLTST ENDIF ;WHEEL APPROVAL ; CALL RETSAVE XRA A ;SET NO INSPECT STA INSPECT LXI H,0 ;SET R/O AND SYS ATTRIBUTES OFF LXI D,FCB2+1 ;PT TO ATTRIBUTES MVI B,3 ;3 CHARS MAX ATT1: LDAX D ;GET CHAR INX D ;PT TO NEXT CPI 'I' ;INSPECT? BRZ ATTI CPI 'R' ;SET R/O? BRZ ATTR CPI 'S' ;SET SYS? BRZ ATTS ATT2: DBNZ ATT1 BR ATT3 ATTI: STA INSPECT ;SET FLAG BR ATT2 ATTR: MVI H,80H ;SET R/O BIT BR ATT2 ATTS: MVI L,80H ;SET SYS BIT BR ATT2 ATT3: SHLD FATT ;SAVE FILE ATTRIBUTES MVI A,1 ;SELECT DIR AND SYS FILES CALL GETDIR ;LOAD DIRECTORY JZ PRFNF ;NO FILE ERROR SHLD NXTFILE ;PT TO NEXT FILE BR ATT5 ATT4: LHLD NXTFILE ;PT TO NEXT FILE MOV A,M ;END OF LIST? ORA A JZ EXIT CALL CRLF ;NEW LINE ATT5: PUSH H ;SAVE PTR TO CURRENT FILE CALL PRFN ;PRINT ITS NAME SHLD NXTFILE ;SAVE PTR TO NEXT FILE CALL PRINT DB ' Set to R','/'+80H LHLD FATT ;GET ATTRIBUTES MVI C,'W' ;ASSUME R/W MOV A,H ;GET R/O BIT ORA A BRZ ATT6 MVI C,'O' ;SET R/O ATT6: MOV A,C ;GET CHAR CALL CONOUT MOV A,L ;GET SYS FLAG ORA A ;SET FLAG BRZ ATT7 CALL PRINT DB ' and SY','S'+80H ATT7: INSPECT EQU $+1 ;PTR FOR IN-THE-CODE MODIFICATION MVI A,0 ;GET INSPECT FLAG ORA A ;Z=NO POP H ;GET PTR TO CURRENT FILE BRZ ATT8 CALL ERAQ1 ;ASK FOR Y/N BRNZ ATT4 ;ADVANCE TO NEXT FILE IF NOT Y ATT8: LXI D,FCB1+1 ;COPY INTO FCB1 MVI B,11 ;11 BYTES CALL LDIR FATT EQU $+1 ;PTR FOR IN-THE-CODE MODIFICATION LXI H,0 ;GET ATTRIBUTES DCX D ;PT TO SYS BYTE DCX D MOV A,L ;GET SYS FLAG CALL ATTSET ;SET ATTRIBUTE CORRECTLY DCX D ;PT TO R/O BYTE MOV A,H ;GET R/O FLAG CALL ATTSET LXI D,FCB1 ;PT TO FCB MVI C,30 ;SET ATTRIBUTES CALL BDOS BR ATT4 ATTSET: ORA A ;0=CLEAR ATTRIBUTE BRZ ATTST1 LDAX D ;GET BYTE ORI 80H ;SET ATTRIBUTE STAX D RET ATTST1: LDAX D ;GET BYTE ANI 7FH ;CLEAR ATTRIBUTE STAX D RET ; ENDIF ;PROTON ; ;Section 5G ;Command: CP ;Function: To copy a file from one place to another ; ;Form: ; CP new=old ; IF CPON IF COPYTOP ; IF USING TOP OF TPA AS COPY BUFFER CBUFF DS 2 ; SPACE TO SAVE ADDRESS OF COPY BUFFER ENDIF ;COPYTOP COPY: ; ; CHECK FOR WHEEL APPROVAL IF OPTION ENABLED ; IF WCP CALL WHLTST ENDIF ;WHEEL APPROVAL ; CALL RETSAVE ; ; STEP 0: IF NEW IS BLANK, MAKE IT THE SAME NAME AND TYPE AS OLD ; LXI D,FCB1+1 ;PT TO NEW FILE NAME LDAX D ;GET FIRST CHAR CPI ' ' ;NO NAME? BRNZ COPY0 LXI H,FCB2+1 ;MAKE SAME AS OLD MVI B,11 ;11 BYTES CALL LDIR ; ; STEP 1: SEE IF NEW=OLD AND ABORT IF SO ; COPY0: LXI H,FCB1 ;PT TO NEXT LXI D,FCB2 ;PT TO OLD PUSH H ;SAVE PTRS PUSH D INX H ;PT TO FILE NAME INX D MVI B,13 ;COMPARE 13 BYTES COPY1: LDAX D ;GET OLD CMP M ;COMPARE TO NEW BRNZ COPY2 INX H ;PT TO NEXT INX D DBNZ COPY1 MVI C,25 ;GET CURRENT DISK CALL BDOS INR A ;MAKE 1..P MOV B,A ;CURRENT DISK IN B POP D ;GET PTR TO DN POP H LDAX D ;GET DISK MOV C,A ;... IN C ORA A ;CURRENT? BRNZ COPY1A MOV C,B ;MAKE C CURRENT COPY1A: MOV A,M ;GET DISK ORA A ;CURRENT? BRNZ COPY1B MOV A,B ;MAKE A CURRENT COPY1B: CMP C ;SAME DISK ALSO? BRNZ COPY3 ;CONTINUE WITH OPERATION BR CPERR COPY2: POP D ;GET PTRS POP H ; ; STEP 2: SET USER NUMBERS ; COPY3: LDA FCB1+13 ;GET NEW USER STA USRNEW LDA FCB2+13 ;GET OLD USER STA USROLD ; ; STEP 3: SEE IF OLD FILE EXISTS ; LXI H,OLDFCB ;COPY OLD INTO 2ND FCB PUSH H ;SAVE PTR TO 2ND FCB XCHG MVI B,14 ;14 BYTES CALL LDIR CALL LOGOLD ;LOG IN USER NUMBER OF OLD FCB POP H ;GET PTR TO 2ND FCB CALL INITFCB2 ;INIT FCB MVI C,17 ;LOOK FOR FILE CALL BDOS INR A ;CHECK FOR ERROR JZ PRFNF ;FILE NOT FOUND ; ; STEP 4: SEE IF NEW EXISTS ; CALL LOGNEW ;LOG INTO NEW'S USER AREA CALL EXTEST ;TEST JZ EXIT ;ERROR EXIT ; ; STEP 5: CREATE NEW ; LXI D,FCB1 ;PT TO FCB MVI C,22 ;MAKE FILE CALL BDOS INR A ;ERROR? BRNZ COPY4 ; ; COPY ERROR ; CPERR: CALL PRINT DB ' Copy','?'+80H JMP EXIT ; ; STEP 6: OPEN OLD ; COPY4: CALL LOGOLD ;GET USER LXI H,OLDFCB ;PT TO FCB CALL INITFCB2 ;INIT FCB MVI C,15 ;OPEN FILE CALL BDOS ; ; STEP 7: COPY OLD TO NEW WITH BUFFERING ; COPY5: CALL LOGOLD ;GET USER MVI B,0 ;SET COUNTER ; LXI H,TPA ;SET NEXT ADDRESS TO COPY INTO ; NEW CODE TO USE TOP OF TPA AS COPY BUFFER IF COPYTOP LHLD BDOS+1 ;GET BOTTOM OF BDOS LXI D,-(CPBLOCKS*128 + 806H) ;SAVE CCP AND BUFFER SPACE DAD D ;ADDR OF BOTTOM OF COPY BUFFER SHLD CBUFF ELSE ;NOT COPYTOP LXI H,TPA ENDIF ;COPYTOP ; END OF NEW CODE BLOCK COPY5A: PUSH H ;SAVE ADDRESS AND COUNTER PUSH B LXI D,OLDFCB ;READ BLOCK FROM FILE MVI C,20 CALL BDOS POP B ;GET COUNTER AND ADDRESS POP D ORA A ;OK? BRNZ COPY5B PUSH B ;SAVE COUNTER LXI H,TBUFF ;COPY FROM BUFFER MVI B,128 ;128 BYTES CALL LDIR XCHG ;HL PTS TO NEXT POP B ;GET COUNTER INR B ;INCREMENT IT MOV A,B ;DONE? CPI CPBLOCKS ;DONE IF CPBLOCKS LOADED BRNZ COPY5A COPY5B: MOV A,B ;GET COUNT ORA A BRZ COPY6 ;DONE IF NOTHING LOADED PUSH B ;SAVE COUNT CALL LOGNEW ;GET USER ; LXI H,TPA ;PT TO TPA IF COPYTOP ; LHLD CBUFF ; ELSE ;NOT COPYTOP ; LXI H,TPA ; ENDIF ;COPYTOP ; COPY5C: LXI D,TBUFF ;COPY INTO TBUFF MVI B,128 ;128 BYTES CALL LDIR PUSH H ;SAVE PTR TO NEXT LXI D,FCB1 ;PT TO FCB MVI C,21 ;WRITE BLOCK CALL BDOS ORA A BRNZ CPERR ;COPY ERROR POP H ;GET PTR TO NEXT BLOCK POP B ;GET COUNT DCR B ;COUNT DOWN BRZ COPY5 ;GET NEXT PUSH ISKSP: DEFS 2 ;HOLDS OLD SP FOR DISK DELAY: DEFS 1 ;TIMEOUT FOR KEY DELAY BELL: DEFS 1 ;TIMEOUT FOR BELL(MUST FOLLOW DELAY) BREAK: DEFS 1 ;COUNTER FOR TIMEOUT(MUST FOLLOW BELL) ESCTYP: DEFS 1 ;FF=T 00=Y;X ESCY: DEFS 1 ;Y VALUE OF CURSOR POS ESCX: DEFS 1 ;X VALUE INTSP: DEFS 2 ;OLD SP FOR INTERUPT ; LAST_SG EQU $ ; Mark the last avail. byte IF ZCPR3 ; RESERVE EQU 0F600H ; (0F600H if ZCPR3) ELSE RESERVE EQU 0F800H ; (0F800H if no ZCPR3) ENDIF ; IF $ GE (BIOS+0E00h) ; BIOS is only 3.5K SIZE: TOOBIG ; print end address :-) IF1 .PRINTX * Warning: BIOS is too big * ENDIF ENDIF IF $ GE QUE .PRINTX * BIOS running into buffers!!! * BIOS ERROR ENDIF ; * * * * * * * * ; ; Show the available free space and the number of sectors needed ; to hold a SYSGEN image of CP/M with this BIOS: ; ; * * * * * * * * FREEMEM EQU RESERVE - LAST_SG ; Free memory left SGSIZE EQU (LAST_SG-CCP+127)/128 ; Sysgen size ; Number of sectors -- Must be 50H or less! END BIOS Z3FCPIF ELSEdFI VXIF JEMEREXNUWH;IFA~#~(.!w!~(w !~G#(( ~/Ox/G~w_> ]' };}:m ( *)~(GGl<(l<(2 :(:l <=_:y_ !~(#ȯ=!~F#  #~#fo= !~(($# +~w RIGHT ONE CHARACTER DB 'E'-64,0,0,0,0,0,0,0 ;UP UP ONE LINE DB 'X'-64,0,0,0,0,0,0,0 ;DOWN DOWN ONE LINE DB 'Q'-64,'A',0,0,0,0,0,0 ;ENTER FIND/REPLACE STRING DB 'Q'-64,'D',0,0,0,0,0,0 ;, GOTO RIGHT MARGIN DB 'F'-64,0,0,0,0,0,0,0 ;- RIGHT ONE WORD DB 'C'-64,0,0,0,0,0,0,0 ;. UP ONE PAGE DB 'PIP ',0,0,0,0 ;0 PIP DB 'STAT ',0,0,0 ;1 STAT DB 'XDIR ',0,0,0 ;2 XDIR DB 'R'-64,0,0,0,0,0,0,0 ;3 DOWN ONE PAGE DB 'DIR A:',0DH,0 ;4 DIR A: DB 'DIR B:',0DH,0 ;5 DIR B: DB 'A'-64,0,0,0,0,0,0,0 ;6 LEFT ONE WORD DB 'A:',0,0,0,0,0,0 ;7 A: DB 'B:',0,0,0,0,0,0 ;8 B: DB 'Q'-64,'S',0,0,0,0,0,0 ;9 GOTO LEFT MARGIN ; MSG1: DB CR,LF,'*** disk not ready ***',80h MSG2: DB CR,LF,'*** disk write protected ***',80h MSG3: DB CR,LF,'*** record not found ***',80h MSG4: DB CR,LF,'*** crc error ***',80h MSG5: DB CR,LF,'*** lost data ***',80h IF ZCPR3 ; ; AutoStart command ; ; This value is set by the CONFIG program, and is used as the ; initial command to ZCPR3. This command is ignored in the CP/M ; CCP. ; ; The format of this region is: ; ; Command length -- 1 byte ; Command text -- 8 bytes (max) ; Trailing zero -- 1 byte ; ; ; ORG BIOS+062H AUTOCMD: DB 8,'STARTUP ',0 ; Cmd length + cmd + 0 terminator ENDIF ; ; ; UNINITIALIZED VARIABLES ; ; DISK ; SEKDSK: DS 1 ;seek disk number SEKTRK: DS 2 ;seek track number SEKHST: DS 1 ;seek shr secshf ; HSTDSK: DS 1 ;host disk number HSTTRK: DS 2 ;host track number HSTSEC: DS 1 ;host sector number ; SEKSEC: DS 1 ;seek sector number HSTACT: DS 1 ;host active flag HSTWRT: DS 1 ;host written flag ; ERFLAG: DS 1 ;error reporting RSFLAG: DS 1 ;read sector flag READOP: DS 1 ;1 if read operation WRTYPE: DS 1 ;write operation type DMAADR: DS 2 ;last dma address ; ; SCREEN AND KEYBOARD ; ; The next four labels (6 bytes) must stay in this order ; so that external access is possible. ; CURSOR: DEFS 2 ;PRESENT CURSOR LOCATION CURCL: DEFS 1 ;CURSOR COL CURLN: DEFS 1 ;CURSOR LINE TOPLN: DEFS 2 ;RAM ADDRESS FOR TOP OF SCREEN D************** ;* * ;* COLD BOOT ENTRY * ;* * ;******************************************************** ; CBOOT: IF FALSE DI LD A,(FREQ) ;PROGRAM THE CRT OUT (PPIA),A LD A,0C3H ;JMP LD (0038H),A ;RST 38H USED FOR SCREEN LD HL,INTERUPT LD (0039H),HL LD HL,BAUD ;PROGRAM REST OF PORTS LD A,(HL) OUT (BDGEN),A LD A,042H OUT (AUXST),A OUT (AUXST),A OUT (MNSTAT),A OUT (MNSTAT),A INC HL LD A,(HL) ;MAIN PORT MODE OUT (MNSTAT),A INC HL LD A,(HL) ;MAIN PORT COMMAND OUT (MNSTAT),A INC HL LD A,(HL) ;AUXILARY PORT MODE OUT (AUXST),A INC HL LD A,(HL) ;AUXILARY PORT COMMAND OUT (AUXST),A IN A,(AUXDAT) ;PRIME PORTS? IN A,(AUXDAT) IN A,(MNDAT) IN A,(MNDAT) CALL ERASCR ;ERASE THE SCREEN CALL TOPSCR ;START SCREEN DISPLAY OUT (INTRST),A LD A,2 OUT (PPICW),A ;TURN ON VIDEO IM 001H ;SET MODE EI ld hl,cursor ;pick up the address ld (50h),hl ;save it page zero RET ENDIF LD SP,STACK DI IF ZCPR3 ; Init ZCPR3 stuff if present LD HL,LAST_SG ; Set up HL and DE to clear memory LD DE,LAST_SG+1 ; from the end of boot to FFFFh LD (HL),0 LD A,H CPL LD B,A LD A,L CPL LD C,A LDIR ZBOOT: LD BC,3 ; Set up the ZCPR3 command line LD HL,CMDSET ; . pointers LD DE,Z3CL ; LDIR ; LD BC,10 ; Move the automatic command to LD HL,AUTOCMD ; . the ZCPR3 command line LD DE,Z3CL+3 ; LDIR ; LD BC,11 ; Move the initial path descriptor LD HL,PATH ; . to the proper location LD DE,EXPATH ; LDIR ; LD HL,Z3WHL ; Turn the wheel byte off LD (HL),00H ; LD HL,3DH ; Set maxdrive to drive D LD (HL),03H ; LD HL,3FH ; Set maxuser to 15 LD (HL),0FH ; LD HL,ENV ; Move environment and TCAP to the LD DE,Z3ENV ; . proper location LD BC,ENVEND-ENV+1 ; . LDIR ; ENDIF ; ZCPR3 init ; LD A,(DE) ;PROGRAM THE CRT ; INC DE LD A,64h OUT (PPIA),A LD A,0eh OUT (6bh),a LD A,0C3H ;JMP LD (RSTADD),A ;RST 38H USED FOR SCREEN LD HL,INTERUPT LD (RSTADD+1),HL ; LD A,(DE) LD A,77h OUT (BDGEN),A LD A,042H OUT (AUXST),A OUT (AUXST),A OUT (MNSTAT),A OUT (MNSTAT),A INC DE ; LD A,(DE) ;MAIN PORT MODE LD A,4eh OUT (MNSTAT),A INC DE ; LD A,(DE) ;MAIN PORT COMMAND LD A,17h OUT (MNSTAT),A LD (MNCMD),A INC DE ; LD A,(DE) ;AUXILARY PORT MODE LD A,4eh OUT (AUXST),A INC DE ; LD A,(DE) ;AUXILARY PORT COMMAND LD A,17h OUT (AUXST),A IN A,(AUXDAT) ;PRIME PORTS? IN A,(AUXDAT) IN A,(MNDAT) IN A,(MNDAT) INC DE ; LD A,(DE) LD A,00h LD (HDSHAK),A ;HANDSHAKE FLAG CALL ERASCR ;ERASE THE SCREEN CALL TOPSCR ;START SCREEN DISPLAY OUT (INTRST),A LD A,2 OUT (PPICW),A ;TURN ON VIDEO LD A,00EH ;RESET NEW KEY FLAG OUT (PPICW),A LD A,00FH OUT (PPICW),A IM 001H ;SET MODE EI LD A,95H LD (IOBYTE),A CALL SETFLG LD HL,CURSOR ;save address pointer LD (SCRNPTRS),HL LD B,QLEN ; fill the keyboard buffer LD HL,QUE QFILL: LD (HL),8 INC HL DJNZ QFILL LD HL,LOGMSG ;signon message CALL MSGOUT LD A,0 ; make A default drive LD (DFLDRV),A LD C,A JP CCP ; go to CP/M LOGMSG: DB CR,LF,MSIZE/10 +'0',MSIZE MOD 10 +'0','K ' IF ZCPR3 DB 'ZCPR3 ' ELSE DB 'CP/M vers 2.2 ' ENDIF DB '(Z80 Operating System)',CR,LF DB 'BIOS Version ',VERS/10+'0','.' DB VERS MOD 10+'0' IF INTERNAL ; Display internal revision # DB 'x',INT$REV/10+'0',INT$REV MOD 10 + '0' DB ' [',THIS$YEAR/10+'0',THIS$YEAR MOD 10 + '0' DB THIS$MONTH/10+'0',THIS$MONTH MOD 10 + '0','.' DB THIS$DAY/10+'0',THIS$DAY MOD 10 + '0',']',CR,LF DB 'WARNING!!! Unreleased BIOS.' ENDIF DEFB CR,LF,80H ; ;******************************************************** ;* * ;* STORAGE LOCATIONS * ;* * ;******************************************************** ; IF ZCPR3 ; Include ZCPR3 definitions? ENV: JP 0 ; Leading JMP ENV1: ; ZCPR3 enviornment descriptor ... DB 'Z3ENV' ; . Environment ID DB 1 ; . Class 1 environment (external) DW EXPATH ; . External path (PATH) DB EXPATHS ; DW RCP ; . Resident command package (RCP) DB RCPS ; DW IOP ; . Input/output package (IOP) DB IOPS ; DW FCP ; . Flow command package (FCP) DB FCPS ; DW Z3NDIR ; . Named directories (NDR) DB Z3NDIRS ; DW Z3CL ; . Command line (CL) DB Z3CLS ; DW Z3ENV ; . Environment (ENV) DB Z3ENVS ; DW SHSTK ; . Shell stack (SH) DB SHSTKS ; DB SHSIZE ; DW Z3MSG ; . Message buffer (MSG) DW EXTFCB ; . External FCB (FCB) DW EXTSTK ; . External stack (STK) DB 0 ; . Quiet flag (1=quiet, 0=not quiet) DW Z3WHL ; . Wheel byte (WHL) DB 4 ; . Processor: LD HL,LINPTRS ;LOOK UP ADDRESS OF LINE LD A,(CURLN) RLCA CALL LOOKUP EX DE,HL LD HL,(TOPLN) ;OFFSET FROM TOP OF SCREEN ADD HL,DE RET ; ; LINPTRS: DEFW 000H,050H,0A0H,0F0H,140H,190H DEFW 1E0H,230H,280H,2D0H,320H,370H DEFW 3C0H,410H,460H,4B0H,500H,550H DEFW 5A0H,5F0H,640H,690H,6E0H,730H,780H ; ;******************************************************** ;* * ;* ESCAPE HANDLERS * ;* * ;******************************************************** ; ; ESC1: LD A,001H LD (ESCAPE),A RET ; ESC2: LD A,(ESCAPE) CP 001H JR Z,ESC3 CP 002H JR Z,ESCYX CP 003H JR Z,ESCYY JR ESCCAN ; ESCYX: LD A,(ESCTYP) OR A JP NZ,ESCT2 LD A,C SUB ' ' JP M,ESCCAN CP LPF JR NC,ESCCAN LD (ESCX),A LD A,003H LD (ESCAPE),A RET ; ESCYY: LD A,C SUB ' ' JP M,ESCCAN CP 050H JR NC,ESCCAN LD (ESCY),A LD HL,(ESCY) LD (CURCL),HL CALL SCRLL2 EX DE,HL LD HL,(CURCL) LD H,000H ADD HL,DE LD (CURSOR),HL JR ESCCAN ; ESC3: LD A,C CP 'Y' JR Z,ESCYV CP '=' JR Z,ESCYV CP '~' JR Z,ESCT CP '5' JR Z,ESC5 CP '6' JR Z,ESC6 ESCCAN: XOR A LD (ESCAPE),A RET ESCYV: XOR A LD (ESCTYP),A ESCY2: LD A,002H LD (ESCAPE),A RET ; ESCT: LD (ESCTYP),A JR ESCY2 ; ESC5: LD A,(APLFLG) CPL ;REVERSE FLAG LD (APLFLG),A JR ESCCAN ; ESC6: IN A,(PPIA) ;TOGGLE REVERSE VIDEO XOR 128 OUT (PPIA),A JR ESCCAN ; ESCT2: XOR A ;ESC~N DELETED JAN/81 LD (ESCAPE),A LD A,C CP 'K' JR Z,ESCTK CP 'k' JR Z,ESCTLK AND 05FH CP 'E' JR Z,ESCTE CP 'D' JR Z,ESCTD RET ; ESCTK: CALL SCRLL2 LD A,(CURCL) LD B,00H LD C,A ADD HL,BC LD A,050H SUB C LD B,A CALL FILL RET ; ESCTLK: CALL ESCTK LD A,(CURLN) CP LPF - 1 RET Z LD C,A LD A,LPF - 1 SUB C LD C,A ERLP2: LD B,50H CALL FILL DEC C JR NZ,ERLP2 RET ; ESCTE: LD (TRANSP),A RET ; ESCTD: XOR A LD (TRANSP),A RET ; ;******************************************************** ;* * ;* PORT SERVICING ROUTINES * ;* * ;******************************************************** ; ; ; MAIN PORT SERIAL DATA IN ; MANIN: CALL MANIST ;ANYTHING THERE? JR Z,MANIN ;NO KEEP TRYING IN A,(MNDAT) RET ; MANTRY: CALL MANIST ;ANYTHING THERE? RET Z ;NO IN A,(MNDAT) ;YES - GET IT RET ; MANIST: IN A,(MNSTAT) ;CHECK PORT AND 02H ;CHAR READY? RET ; ; MAIN PORT SERIAL DATA OUT ; MANOUT: CALL MANOST ;GET STATUS JR Z,MANOUT ;NO LD A,C ;GET CHARACTER OUT (MNDAT),A RET ; MANOST: IN A,(MNSTAT) ;GET STATUS AND 01H ;TRANSMITTER EMPTY? RET ;LEAVE WITH RESULT ; ; ; AUX PORT SERIAL DATA IN ; AUXIN: CALL AUXIST ;ANYTHING THERE? JR Z,AUXIN IN A,(AUXDAT) RET ; AUXINE: CALL AUXTRY ;ANYTHING THERE? JR Z,AUXINE ;NO - KEEP TRYING PUSH AF ;YES, SAVE IT LD C,A ;LOAD C CALL AUXOT1 ;ECHO IT POP AF ;RESTORE CHAR AND 7FH ;STRIP PARITY RET ; AUXTRY: CALL AUXIST ;ANYTHING THERE? RET Z ;NO IN A,(AUXDAT) ;YES - GET IT RET ; AUXIST: IN A,(AUXST) ;GET AUX PORT STATUS AND 02H ;CHARACTER READY? RET ; ; AUX PORT SERIAL OUT--CTS WHEN HDSHAK NON ZERO ; AUXOUT: CALL AUXOST ;GET STATUS JR Z,AUXOUT ;NOT READY LD A,C OUT (AUXDAT),A RET ; AUXOTE: CALL AUXOT1 ;SEND CHAR AWAIT: CALL AUXTRY ;WAIT FOR ECHO JR Z,AWAIT RET ; AUXOT1: CALL AUXST2 ;GET AUX PORT TX STATUS JR Z,AUXOT1 ;WAIT UNTIL BUFFER EMPTY LD A,C ;READY - LOAD CHAR OUT (AUXDAT),A ;SEND IT RET ; AUXOST: LD A,(HDSHAK) OR A JR Z,AUXST2 IN A,(AUXST) ;GET HANDSHAKE STATUS AND 80H RET Z AUXST2: IN A,(AUXST) ;GET TRANSMITTER STATUS AND 01H RET ; ; A printer handler for XON/XOFF protocol using the aux port ; XPRTOT: IN A,(AUXST) ;get printer status LD (PRTST),A ;save it AND 02h ;any input char? JR Z,XPRINT ;no IN A,(AUXDAT) ;yes - get it AND 7fh ;strip parity CP X$OFF ;is printer requesting a break? JR NZ,XPRINT ;no ; XPRTWT: IN A,(AUXST) ;wait for an x$on AND 02h JR Z,XPRTWT IN A,(AUXDAT) AND 7fh CP X$ON JR NZ,XPRTWT ; XPRINT: LD A,(PRTST) ;get status back XWTOUT: AND 01h ;TX buffer empty? JR NZ,XPRCHR IN A,(AUXST) ;check again JR XWTOUT ; XPRCHR: LD A,C ;now get char OUT (AUXDAT),a ;and send it RET ; PRTST: DS 1 ; X$OFF EQU 11h ;XOFF X$ON EQU 13h ;XON ; TTYOUT EQU AUXOUT TTYIN EQU AUXIN TTYOST EQU AUXOST TTYIST EQU AUXIST ; ;****************************************** (MNSTAT),A LD A,80H RET ; KEYPROC: CP 80H ;KEYPAD? JR C,QUEKEY ;NO THEN ENTER LD HL,GOTIT PUSH HL SUB 80H CP 4 ;CURSOR KEYS? RET C DEC A CP 4 ;CURSOR DOWN? RET Z SUB 7 CP 5 ;ENTER? RET Z SUB 30 CP 9 ; , - . RET C DEC A CP 20 ;NUMBERS RET C POP HL ;NOT FROM KEY PAD RET ; GOTIT: ADD A,A ADD A,A ADD A,A ;MULTIPLY BY 8 LD HL,KEYBUF ;ADD BASE LD E,A LD D,0 ADD HL,DE GOTLP: LD A,(HL) ;MOVE 8 CHARACTERS OR A ;OR STOP AT NULL RET Z PUSH HL CALL QUEKEY ;ADD THE CHAR TO QUE POP HL INC HL DJNZ GOTLP RET ; QUEKEY: AND 7FH ;ADD THE KEY TO THE QUE PUSH AF LD A,(QCOUNT) ;INCREMENT THE COUNT CP QLEN JR Z,QUEFULL ;NO MORE ROOM INC A LD (QCOUNT),A POP AF LD HL,(QEND) LD (HL),A ;SAVE IT CALL QPTR ;MODULO INCREMENT LD (QEND),HL RET ; QUEFULL: POP AF ;RING BELL CALL CNTRLG RET ; QPTR: INC HL ;POINT TO NEXT LOC PUSH HL ;SAVE PTR LD A,L CP (QUE+QLEN) AND 0FFH ;ARE WE THERE? POP HL ;RESTORE ORIGINAL PTR RET NZ ;NO LD HL,QUE ;YES- POINT TO BEGINING RET ; QUEIT: ;QUES STRING -> DE EX DE,HL CALL GOTLP EX DE,HL RET ; ;******************************************************** ;* * ;* SCREEN HANDLER * ;* * ;******************************************************** ; ; SCREEN: CRTOUT: LD A,(ESCAPE) OR A ;ESCAPE SEEN? JP NZ,ESC2 LD A,C CP 01BH ;ESCAPE? JP Z,ESC1 LD A,(PRTSW) ;control-\ set? OR A JR Z,NEXT1 ;no - move on PUSH BC ;save C CALL LIST ;send char to list device POP BC ;restore C and carry on NEXT1: LD A,(TRANSP) ;TRANSPARENT MODE? OR A JP NZ,PRINT LD A,C CP 20H JP NC,PRINT ; ;******************************************************** ;* * ;* CONTROL CODE HANDLERS FOLLOW * ;* * ;******************************************************** ; ; CNTRL: ; CP 1 ; JR Z,CNTRLA SUB 6 JR C,NOCNTR CP TBLMAX JR NC,NOCNTR LD HL,CNTTBL ADD A,A CALL LOOKUP JP (HL) NOCNTR: RET ; CNTTBL: DEFW CNTRLF,CNTRLG,CNTRLH,CNTRLI,CNTRLJ,CNTRLK DEFW CNTRLL,CNTRLM ; TBLMAX EQU ($-CNTTBL)/2 ; CNTRLL: LD A,(PAGFLG) ;CHEK FOR PAGE MODE OR A RET NZ ERASCR: DI LD HL,0F800H LD C,8 LD B,0 ERLP: CALL FILL DEC C JR NZ,ERLP LD HL,0000H LD (CURCL),HL LD (TOPLN),HL LD (CURSOR),HL EI RET ; FILL: LD A,H OR 0F8H LD H,A LD (HL),' ' INC HL DJNZ FILL RET ; ;CNTRLA: REMOVED FOR LINKMT ; LD A,(PAGFLG) ;CHECK FOR PAGE MODE ; OR A ; RET NZ ; LD HL,0000H ;HOME CURSOR ; LD (CURCL),HL ; LD HL,(TOPLN) ; LD (CURSOR),HL ; RET ; CNTRLF: LD HL,(CURSOR) INC HL LD (CURSOR),HL LD HL,(CURCL) INC L LD A,L CP 050H JR NZ,SAMELN LD A,(LINCNT) ;INC RELATIVE LINE INC A LD (LINCNT),A LD L,000H LD A,H CP LPF - 1 JR NZ,NXTLN1 PUSH HL CALL SCRLL1 POP HL JR SAMELN NXTLN1: INC H SAMELN: LD (CURCL),HL RET ; CNTRLG: LD A,00DH ;BELL OUT (PPICW),A LD A,BELTIM LD (BELL),A RET ; CNTRLI: CALL CNTRLF ;TAB LD A,L AND 007H JR NZ,CNTRLI RET ; CNTRLJ: LD HL,(CURSOR) ;LINEFEED LD DE,0050H ADD HL,DE LD (CURSOR),HL LD A,(LINCNT) ;INC RELATIVE LINE INC A LD (LINCNT),A LD A,(CURLN) CP LPF - 1 JR NZ,NEXTLN LD (CURLN),A CALL SCRLL1 RET ; NEXTLN: INC A LD (CURLN),A RET ; CNTRLM: CALL SCRLL2 LD (CURSOR),HL LD A,000H LD (CURCL),A RET ; CNTRLH: LD HL,(CURCL) LD A,L OR H RET Z LD A,L OR A JR NZ,SMLN LD A,(LINCNT) ;DEC RELATIVE LINE DEC A LD (LINCNT),A LD L,04FH DEC H JR NXTLN SMLN: DEC L NXTLN: LD (CURCL),HL LD HL,(CURSOR) DEC HL LD (CURSOR),HL RET ; CNTRLK: LD A,(CURLN) ;UP LINEFEED OR A RET Z DEC A LD (CURLN),A LD A,(LINCNT) DEC A LD (LINCNT),A LD HL,(CURSOR) LD DE,0FFB0H ADD HL,DE LD (CURSOR),HL RET ; ;******************************************************** ;* * ;* VISIBLE PRINTING ROUTINE * ;* * ;******************************************************** ; ; PRINT: LD HL,(CURSOR) LD A,H OR 0F8H LD H,A LD A,C ;get the character LD (HL),A ;PRINT THE CHAR. CALL CNTRLF ;ADVANCE THE CURSOR RET ; SCRLL1: LD A,(PAGFLG) OR A JR Z,SCRL12 LD A,(LINCNT) CP LPF CALL Z,CONIN SCRL12: DI ;MOVE TOP LINE DOWN ONE LD HL,(TOPLN) LD B,80 CALL FILL LD HL,(TOPLN) LD DE,80 ADD HL,DE LD (TOPLN),HL EI RET ; SCRLL2: PUSH HL ;READ A SECTOR INTO SECOND RAM CALL SENDPARMS CALL WTRES POP HL CALL GETFLAGS JR DISKOUT ; FUNC5: CALL SENDPARMS ;FORMAT THE SECTOR WITHOUT CHECKING LD B,08CH STALL: PUSH HL POP HL DJNZ STALL XOR A JP DISKOUT ; ; WTRES: IN A,(PPIB) ;WAIT FOR DONE FLAG AND 020H JR Z,WTRES WTRES2: IN A,(PPIB) AND 020H JR NZ,WTRES2 RET ; SENDPARMS: CALL BUSOPEN ;GET CPUS TALKING LD HL,8802H LD (HL),B ;SAVE COMMAND INC HL LD (HL),C ;DISK NUMBER INC HL LD A,E CPL LD (HL),A ;SECTOR NUMBER INC HL LD A,D CPL LD (HL),A ;TRACK NUMBER LD A,0FFH LD (8807H),A CALL BUSCLOSE RET ; GETFLAGS: CALL BUSOPEN ;GET RESULTS LD A,(8A0BH) PUSH AF CALL BUSCLOSE POP AF RET ; BUSOPEN: LD A,00AH ;SET UP COMM. BETWEEN CPU OUT (PPICW),A ;BUS SWITCHING WAITACK: IN A,(PPIB) RLA JR C,WAITACK LD A,008H OUT (PPICW),A RET ; BUSCLOSE: LD A,009H ;BUS BACK TO NORMAL OUT (PPICW),A LD A,00BH OUT (PPICW),A RET ; ;******************************************************** ;* * ;* IO BYTE DISPATCH ROUTINES * ;* * ;******************************************************** ; ; CONST: LD HL,CSTBLE JR CONIN1 ; CONOUT: LD HL,COTBLE JR CONIN1 ; READER: LD HL,RTBLE RDRST2: LD A,(IOBYTE) READR1: RRA JR SELDEV ; RDRST: LD HL,RSTBLE JR RDRST2 ; PUNCH: LD HL,PTBLE LD A,(IOBYTE) PNCH1: RRA RRA JR READR1 ; LIST: LD HL,LTBLE LIST2: LD A,(IOBYTE) RRA RRA JR PNCH1 ; LISTST: LD HL,LSTBLE JR LIST2 ; CONIN: LD HL,CITBLE ;CONIN AT TYPE AHEAD CONIN1: LD A,(IOBYTE) RLA ; SELDEV: AND 6H ;OFFSET INTO TABLE CALL LOOKUP JP (HL) ;DISPATCH THE ROUTINE ; READY: LD A,0FFH OR A RET ; ; ; DISPATCH ADDRESSES ; ; CONSOLE STATUS ; CSTBLE: CSTTY: DEFW TTYIST CSCRT: DEFW KEYST CSBAT: DEFW MANIST CSUC1: DEFW RDRST ; ; CONSOLE INPUT ; CITBLE: CITTY: DEFW TTYIN ;ROUTED TO AUXIN CICRT: DEFW KEYBRD CIBAT: DEFW MANIN CIUC1: DEFW READER ; ; CONSOLE OUTPUT ; COTBLE: COTTY: DEFW TTYOUT ;ROUTED TO AUXOUT COCRT: DEFW SCREEN COBAT: DEFW MANOUT COUC1: DEFW PUNCH ; ; LIST OUTPUT ; LTBLE: LOTTY: DEFW XPRTOT ;XON/XOFF driver - aux port LOCRT: DEFW SCREEN LOLPT: DEFW AUXOUT ;aux port - DTR protocol LOUL1: DEFW AUXOTE ;WAIT FOR ECHO THEN AUX PORT OUT ; ; LIST STATUS TABLE ; LSTBLE: LSTTY: DEFW AUXOST LSCRT: DEFW READY LSLPT: DEFW AUXOST LSUL1: DEFW AUXOST ; ; READER INPUT ; RTBLE: RITTY: DEFW AUXTRY ;AUX PORT IN - RETURN ANYWAY RIPTR: DEFW MANTRY ;MAIN PORT IN - RETURN ANYWAY RIUR1: DEFW AUXINE ;AUX PORT IN - ECHO CHAR RIUR2: DEFW MANIN ;MAIN PORT IN - WAIT FOR CHAR ; ; READER STATUS ; RSTBLE: RSTTY: DEFW AUXIST RSPTR: DEFW MANIST RSUR1: DEFW AUXIST RSUR2: DEFW MANIST ; ; PUNCH OUTPUT ; PTBLE: POTTY: DEFW AUXOUT ;AUX PORT OUT POPTP: DEFW MANOUT ;MAIN PORT OUT POUP1: DEFW AUXOTE ;AUX PORT OUT AND WAIT FOR ECHO POUP2: DEFW MANOUT ;MAIN PORT OUT ; ;******************************************************** ;* * ;* KEYBOARD HANDLERS * ;* * ;******************************************************** ; KEYST: LD A,(QCOUNT) ;RETURN STATUS OF THE QUE OR A RET Z LD A,0FFH RET ; KEYBRD: XOR A LD (LINCNT),A CALL KEYST ;MAKE SURE QUE NOT EMPTY JR Z,KEYBRD LD HL,QCOUNT ;DECREMENT THE COUNT DEC (HL) LD HL,(QFRONT) ;GET THE CHAR LD B,(HL) CALL QPTR ;MODULO N THE PTR LD (QFRONT),HL LD A,B CP FS ;control-\? RET NZ ;no LD A,(PRTSW) ;yes - get flag CPL ;reverse it LD (PRTSW),A ;resave it LD A,B ;restore the character RET ; HKEYST: IN A,(PPIB) ;GET STATUS AND 03H ;REPEAT OR NEW KEY JR Z,NOKEY AND 01H ;NEW KEY? JR NZ,KEY LD A,(LASTST) OR A RET Z LD A,(DELAY) ;KEY CLOCK OR A JR Z,KEY XOR A RET ; KEY: LD A,0FFH OR A NOKEY: LD (LASTST),A RET ; ; HKEYBRD: IN A,(PPIB) ;GET THE KEY LD C,A AND 001H ;IS IT A NEW KEY JR Z,REPEAT ;NO LD A,00EH ;RESET NEW KEY FLAG OUT (PPICW),A LD A,00FH OUT (PPICW),A LD A,KEYDLY ;SETUP DELAY BEFORE REPEAT GETKEY: LD (DELAY),A IN A,(KBCHAR) IN A,(KBCHAR) IN A,(KBCHAR) LD B,A CP 080H ;FILTER OUT BREAK JR Z,KEY80 LD A,C ;STATUS AND 010H ;CAPS LOCK? LD A,B JR NZ,GOTKEY AND 5FH SUB 041H ;CONVERT LOWERCASE JP M,GOTKEY SUB 01AH JP P,GOTKEY LD A,B XOR 20H ;CONVERT LD B,A GOTKEY: LD A,B RET ; REPEAT: LD A,RPTTIM ;SETUP TIME FOR REAPEAT AGAIN JR GETKEY ; KEY80: LD A,BRKTIM ;BREAK LD (BREAK),A LD A,(MNCMD) OR 008H OUTR READ AND WRITE FOLLOWS * ;* * ;***************************************************** RWOPER: ; ENTER HERE TO PERFORM THE READ/WRITE LD (READOP),A XOR A ;ZERO TO ACCUM LD (ERFLAG),A ;NO ERRORS (YET) LD A,(SEKSEC) ;COMPUTE HOST SECTOR OR A ;CARRY = 0 RRA ;SHIFT RIGHT RRA AND 0FH INC A LD (SEKHST),A ;HOST PHYSICAL SECTOR TO SEEK ; ; ACTIVE HOST SECTOR? ; LD HL,HSTACT ;HOST ACTIVE FLAG LD A,(HL) LD (HL),1 ;ALWAYS BECOMES 1 OR A ;WAS IT ALREADY? JR Z,FILHST ;FILL HOST IF NOT ; ; HOST BUFFER ACTIVE, SAME AS SEEK BUFFER? LD B,4 LD DE,SEKDSK LD HL,HSTDSK ;SAME DISK? CMPLOP: LD A,(DE) CP (HL) ;SEKDSK = HSTDSK? JR NZ,NOMATCH INC HL INC DE DJNZ CMPLOP JR MATCH ; NOMATCH: ; PROPER DISK, BUT NOT CORRECT SECTOR LD A,(HSTWRT) ;HOST WRITTEN? OR A CALL NZ,WRITEHST ;CLEAR HOST BUFF ; FILHST: ; MAY HAVE TO FILL THE HOST BUFFER LD DE,HSTDSK LD HL,SEKDSK LD BC,4 LDIR LD A,(RSFLAG) ;NEED TO READ? OR A CALL NZ,READHST ;YES, IF 1 XOR A ;0 TO ACCUM LD (HSTWRT),A ;NO PENDING WRITE ; MATCH: ; COPY DATA TO OR FROM BUFFER LD A,(SEKSEC) ;MASK BUFFER NUMBER AND SECMSK ;LEAST SIGNIF BITS LD L,A ;READY TO SHIFT LD H,0 ;DOUBLE COUNT ADD HL,HL ;SHIFT LEFT 7 ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ; HL HAS RELATIVE HOST BUFFER ADDRESS LD DE,HARDBUF ADD HL,DE ;hl = host address EX DE,HL ;now in DE LD HL,(DMAADR) ;get/put CP/M data LD BC,128 ;length of move LD A,(READOP) ;which way? OR A JR NZ,RWMOVE ;skip if read ; ; write operation, mark and switch direction LD A,1 LD (HSTWRT),A ;hstwrt = 1 PUSH DE LD DE,HSTBUF PUSH DE PUSH BC LDIR POP BC POP HL POP DE CALL BUSOPEN LDIR CALL BUSCLOSE JR RWMV1 ; RWMOVE: EX DE,HL PUSH DE LD DE,HSTBUF PUSH DE PUSH BC CALL BUSOPEN LDIR CALL BUSCLOSE POP BC POP HL POP DE LDIR ; ; data has been moved to/from host buffer RWMV1: LD A,(WRTYPE) ;WRITE TYPE CP WRDIR ;TO DIRECTORY? LD A,(ERFLAG) ;IN CASE OF ERRORS RET NZ ;NO FURTHER PROCESSING OR A ;ERRORS? RET NZ ;SKIP IF SO XOR A ;0 TO ACCUM LD (HSTWRT),A ;BUFFER WRITTEN CALL WRITEHST LD A,(ERFLAG) RET ; ;***************************************************** ;* * ;* WRITEHST PERFORMS THE PHYSICAL WRITE TO * ;* THE HOST DISK, READHST READS THE PHYSICAL * ;* DISK. * ;* * ;***************************************************** WRITEHST: ; HSTDSK = HOST DISK #, HSTTRK = HOST TRACK #, ; HSTSEC = HOST SECT #. WRITE "HSTSIZ" BYTES ; FROM HSTBUF AND RETURN ERROR FLAG IN ERFLAG. ; RETURN ERFLAG NON-ZERO IF ERROR ; ; CALL PARM ;GET DISK PARAMETERS LD B,2 ;WRITE COMMAND LD A,(RAW) ;GET READ-AFTER-WRITE INDICATOR OR A ;RAW? JR NZ,WRIT1 ;YES LD B,6 ;NO WRIT1: CALL DISK OR A ;ERROR STATUS RETURNED IN A LD (ERFLAG),A RET Z JR ERROUT ;GO TO ERROR HANDLER ; READHST: ; HSTDSK = HOST DISK #, HSTTRK = HOST TRACK #, ; HSTSEC = HOST SECT #. READ "HSTSIZ" BYTES ; INTO HSTBUF AND RETURN ERROR FLAG IN ERFLAG. ; ; CALL PARM ;GET DISK PARAMETERS LD B,1 ;DISK READ COMMAND CALL DISK OR A LD (ERFLAG),A RET Z JR ERROUT ; ; ; ROUTINE TO GET DISK PARAMETERS ; PARM: LD HL,HSTDSK LD C,(HL) ;GET LOGICAL DISK NUMBER INC HL LD D,(HL) ;GET TRACK NO. INC HL INC HL LD E,(HL) ;GET SECTOR NO. LD HL,HSTBUF RET ; ;******************************************************** ;* * ;* ERROR HANDLER * ;* * ;******************************************************** ; ; ERROUT: LD HL,MSG1 RLA ;DISK NOT READY? CALL C,MSGOUT LD HL,MSG2 RLA ;DISK WRITE PROTECTED? CALL C,MSGOUT LD HL,MSG3 RLA RLA ;CAN'T FIND RECORD? CALL C,MSGOUT LD HL,MSG4 RLA ;CRC ERROR? CALL C,MSGOUT LD HL,MSG5 RLA ;LOST DATA? CALL C,MSGOUT LD A,01 LD (ERFLAG),A RET ; ;******************************************************** ;* * ;* DISK INTERFACE TO SECOND CPU * ;* * ;******************************************************** ; ; DISK: LD (DISKSP),SP ;SAVE STACK POINTER LD SP,STACK3 ;SET UP NEW ONE ABOVE RAM SWITCH LD A,B ;GET COMMAND OR A ;0,4 = RESTORE JR Z,RESTORE CP 004H JR Z,RESTORE CP 005H ;5 = FORMAT JR Z,FUNC5 CP 001H ;1 = READ JR Z,DREAD CALL SENDPARMS ;ALL ELSE IS WRITE CALL WTRES CALL GETFLAGS DISKOUT: LD SP,(DISKSP) ;RESTORE STACK RET ; RESTORE: CALL SENDPARMS ;FUNCTION 5 RESET THE DISK CALL WTRES CALL GETFLAGS JR DISKOUT ; DREAD OUT (PPICW),A LD (HL),CRSOR ;CRSOR IS THE ADDRESS, HL THE DATA EX DE,HL LD (HL),TOPSEL ;AND ALSO TOP OF SCREEN LD A,000H ;BACK TO NORMAL OUT (PPICW),A RET ; ;******************************************************** ;* * ;* DISK HANDLERS * ;* * ;******************************************************** ; ; ; DEFINITION FOR DISK A (512 BYTES/SECTOR, 64 DIRECTORY ENTRIES) ; DPBASE: ; DPE0: DEFW XLT0,0000H DEFW 0000H,0000H DEFW DIRBUF,DPB1 DEFW CSV0,ALV0 ; ; DEFINITION FOR DISK B (512 BYTES/SECTOR, 64 DIRECTORY ENTRIES) ; DPE1: DEFW XLT0,0000H DEFW 0000H,0000H DEFW DIRBUF,DPB1 DEFW CSV1,ALV1 ; ; DEFINITION FOR DISK C (512 BYTES/SECTOR, 128 DIRECTORY ENTRIES) ; DPE2: DEFW XLT0,0000H DEFW 0000H,0000H DEFW DIRBUF,DPB0 DEFW CSV2,ALV2 ; ; DEFINITION FOR DISK D (512 BYTES/SECTOR, 128 DIRECTORY ENTRIES) ; DPE3: DEFW XLT0,0000H DEFW 0000H,0000H DEFW DIRBUF,DPB0 DEFW CSV3,ALV3 ; DPB0: DEFW 40 ;CPM sectors per track DEFB 4 ;BSH DEFB 15 ;BLM DEFB 1 ;EXM DEFW DSM ;DSM - total storage in 2K blocks DEFW 127 ;DRM = max dir entries - 1 DEFB 0C0H ;AL0 DEFB 0 ;AL1 DEFW 32 ;CKS = size of dir check vector DEFW 2 ;OFF = no of reserved system tracks ; DPB1: DEFW 40 ;CPM sectors per track DEFB 4 ;BSH DEFB 15 ;BLM DEFB 1 ;EXM DEFW DSM ;DSM - total storage in 2K blocks DEFW 63 ;DRM = max dir entries - 1 DEFB 80H ;AL0 DEFB 0 ;AL1 DEFW 16 ;CKS = size of dir check vector DEFW 2 ;OFF = no of reserved system tracks ; XLT0: DEFB 0,1,2,3 DEFB 8,9,10,11 DEFB 16,17,18,19 DEFB 24,25,26,27 DEFB 32,33,34,35 DEFB 4,5,6,7 DEFB 12,13,14,15 DEFB 20,21,22,23 DEFB 28,29,30,31 DEFB 36,37,38,39 ; ; ; ALV0: DEFS 31 CSV0: DEFS 32 ALV1: DEFS 31 CSV1: DEFS 32 ALV2: DEFS 31 CSV2: DEFS 16 ALV3: DEFS 31 CSV3: DEFS 16 ; ; ; ;***************************************************** ;* * ;* CP/M to host disk constants * ;* * ;***************************************************** ; BLKSIZ EQU 2048 ;CP/M allocation size HSTSIZ EQU 512 ;host disk sector size HSTSPT EQU 10 ;host disk sectors/trk HSTBLK EQU HSTSIZ/128 ;CP/M sects/host buff CPMSPT EQU HSTBLK * HSTSPT ;CP/M sectors/track SECMSK EQU HSTBLK-1 ;sector mask DSKMASK EQU 1 ;logical to physical disk mask ; ;***************************************************** ;* * ;* BDOS constants on entry to write * ;* * ;***************************************************** ; WRDIR EQU 1 ;write to directory WRUAL EQU 2 ;write to unallocated ; ; ; home the selected disk ; HOME: LD A,(HSTWRT) ;CHECK FOR PENDING WRITE OR A CALL NZ,WRITEHST ;CLEAR BUFFER XOR A LD (HSTACT),A ;CLEAR HOST ACTIVE FLAG LD A,(SEKDSK) ;GET DISK NO. LD (HSTDSK),A LD C,A ;GET DISK NO. XOR A ;RESTORE COMMAND LD B,A CALL DISK OR A LD (ERFLAG),A ;ERROR STATUS RET Z JP ERROUT ;GO TO ERROR ROUTINE ; ; SELECT A DISK ; SELDSK: LD HL,0000 ;ERROR RETURN CODE LD A,C ;SELECTED DISK NUMBER AND DSKMASK ;CONVERT TO PROPER PHYSICAL DISK NUMBER LD (SEKDSK),A ;SEEK DISK NUMBER LD A,C ;RELOAD SELECTED DISK NUMBER CP MAXDSK ;MAX NO. OF DISKS RET NC LD L,A ;DISK NUMBER TO HL LD H,0 ADD HL,HL ;MULTIPLY BY 16 ADD HL,HL ADD HL,HL ADD HL,HL LD DE,DPBASE ;BASE OF PARM BLOCK ADD HL,DE ;HL=.DPB(CURDSK) RET ; ; SET TRACK GIVEN BY BC ; SETTRK: LD (SEKTRK),BC ;TRACK TO SEEK RET ; ; SET SECTOR GIVEN BY C ; SETSEC: LD A,C LD (SEKSEC),A ;SECTOR TO SEEK RET ; ; SET DMA ADDRESS GIVEN BY BC ; SETDMA: LD (DMAADR),BC RET ; ; TRANSLATE SECTOR NUMBER IN BC ; SECTRAN: EX DE,HL ;HL=.TRANS ADD HL,BC ;HL=.TRANS(SECTOR) LD L,(HL) LD H,0 RET ; ;***************************************************** ;* * ;* THE READ ENTRY POINT TAKES THE PLACE OF * ;* THE PREVIOUS BIOS DEFINTION FOR READ. * ;* * ;***************************************************** ; READ: LD A,WRUAL LD (WRTYPE),A ;TREAT AS UNALLOC LD A,0FFH ;READ JR RWOPER ;TO PERFORM THE READ ; ;***************************************************** ;* * ;* THE WRITE ENTRY POINT TAKES THE PLACE OF * ;* THE PREVIOUS BIOS DEFINTION FOR WRITE. * ;* * ;***************************************************** ; WRITE: LD A,C ;WRITE TYPE IN C LD (WRTYPE),A XOR A ; ; ;***************************************************** ;* * ;* COMMON CODE FON PORT DATA MNSTAT EQU 59H ;MAIN PORT STATUS BDGEN EQU 60H ;BAUD RATE GENERATOR PPIA EQU 68H ;8255 PORT A PPIB EQU 69H ;8255 PORT B PPIC EQU 6AH ;8255 PORT C PPICW EQU 6BH ;8255 CONTROL PORT TOPSEL EQU 2H ;CRTC TOP OF PAGE REGISTER ROWSTR EQU 01H ;CRTC ROW START REGISTER CRSOR EQU 03H ;CRTC CURSOR REGISTER BELTIM EQU 15 ;BELL TIME LOOP KEYDLY EQU 40 ;KEY DELAY BEFORE REPEAT RPTTIM EQU 3 ;KEY REPEAT TIME LOOP BRKTIM EQU 15 ;250 MILLISEC BREAK TIME FOR COMM PORT LPF EQU 24 ;NO. OF ROWS ON CRT PROMLD EQU 0C003H ;ROUTINE TO ACCESS DISK DURING BOOT RSTADD EQU 38H DFLDRV EQU 4 SCRNPTRS EQU 50H BTVECT EQU 0 BDOSVT EQU 5 ; FS EQU 1CH ;CONTROL-\ .Z80 ASEG ; ; BEGINNING OF RETAINED BIOS ; ORG BIOS ; ;******************************************************** ;* * ;* BIOS JUMP TABLE * ;* * ;******************************************************** ; ; JP CBOOT WBOOTE: JP WBOOT JP CONST JP CONIN JP CONOUT JP LIST JP PUNCH JP READER JP HOME JP SELDSK JP SETTRK JP SETSEC JP SETDMA JP READ JP WRITE JP LISTST JP SECTRAN JP DISK ; ; ;******************************************************** ;* * ;* WARM BOOT ROUTINE * ;* * ;******************************************************** ; WBOOT: LD SP,STACK ; Set stack to below default DMA LD A,DFLDRV ; Boot from default drive LD a,0 LD C,A ; . LD E,0 ; Set autoselect bit CALL SELDSK ; Select the system disk LD A,H ; Check for a select error OR L ; . JR Z,WBERR ; Select error -- try again LD BC,0 ; Start reading from track 0 CALL SETTRK ; . LD B,NSECTS ; Set the # of sectors to read LD C,1 ; Start from sector 1 of track 0 LD HL,CCP ; Where we want the data to go WBLOOP: PUSH BC ; Save sector count PUSH HL ; and DMA address CALL SETSEC ; Set the sector to read next POP BC ; Get the DMA address PUSH BC ; Save it back CALL SETDMA ; Set the current DMA CALL READ ; Read the sector OR A ; Check for errors JR NZ,WBERR ; Disp msg & try again on error POP HL ; Get DMA address POP BC ; Get count & current sector LD DE,128 ; Update DMA address ADD HL,DE ; . INC C ; Bump sector count LD A,CPMSPT ; Get sectors/track for this disk CP C ; Are we at the end of track yet? JR NZ,NXTSEC ; No, just get the next sector PUSH BC ; Yes, save count & current sector LD BC,(HSTTRK) ; Bump current track INC BC ; . CALL SETTRK ; . POP BC ; Restore count LD C,0 ; Reset sector to 0 NXTSEC: DJNZ WBLOOP ;Falls through to GOCPM GOCPM: ; Setup CP/M vectors and jump to CP/M CALL SETFLG LD A,(DFLDRV) ;get default drive LD C,A JP CCP ; go to CP/M ; WBERR: ; Warm boot error message LD HL,WB_MSG ;wboot error message CALL MSGOUT JP WBOOT ; WB_MSG: DB CR,LF,'BIOS: Boot Error',80h ; SETFLG: XOR A LD (HSTACT),A ;RESET ACTIVE FLAGS LD (HSTWRT),A LD (APLFLG),A LD (PRTSW),a LD A,0C3H ;JMP INSTRUCTION LD (BTVECT),A LD HL,WBOOTE LD (BTVECT+1),HL LD (BDOSVT),A LD HL,3C06H+BIAS LD (BDOSVT+1),HL RET ; MSGOUT: PUSH AF MSGOU1: LD A,(HL) ;SEND HL STRING TO CONSOLE LD C,A ;ENDING IN 80H CP 80H JR NC,MSGGONE PUSH HL CALL CONOUT POP HL INC HL JR MSGOU1 ; MSGGONE: POP AF RET ; LOOKUP: LD D,0 ;HL = BASE ON ENTRY LD E,A ;A = OFFSET ADD HL,DE ; ON EXIT HL CONTAINS WORD LD E,(HL) ; DE CONTAINS LOCATION OF NEXT INC HL LD D,(HL) INC HL EX DE,HL RET ; ; ;******************************************************** ;* * ;* INTERRUPT HANDLER * ;* * ;******************************************************** ; ; INTERUPT: LD (INTSP),SP ;SAVE STACK POINTER LD SP,STACK1 ;AND SET UP NEW ONE PUSH HL ;SAVE REGISTERS PUSH DE PUSH BC PUSH AF IN A,(PPIB) ;GET TYPE OF INTERUPT AND 004H ;IS IT VERT SYNC CALL NZ,TOPSCR ;YES IN A,(INTRST) ;RESET INTERUPT LATCH POP AF ;RESTORE REGISTERS POP BC POP DE POP HL LD SP,(INTSP) ;RESTORE STACK EI RETI ; TOPSCR: CALL SENDPTRS ;SEND NEW PTRS TO CRT CONTRL LD HL,DELAY ;DECREMENT COUTNERS DEC (HL) INC HL DEC (HL) JR NZ,BELLSTIL LD A,00CH ;TURN OFF BELL OUT (PPICW),A BELLSTIL: INC HL ;BREAK DEC (HL) JR NZ,TYPEAH LD A,(MNCMD) ;TURN OFF BREAK OUT (MNSTAT),A TYPEAH: CALL HKEYST ;A KEY WAITING? RET Z ;NO CALL HKEYBRD ;GET IT CALL KEYPROC RET ; ; SENDPTRS: LD HL,(TOPLN) ;TELL THE CRT WHERE TO FIND INFO EX DE,HL ;PREPARE THE REGISTERS LD HL,(CURSOR) LD A,H ;SCREEN STARTS AT F800H AND 00FH LD H,A LD A,D AND 00FH LD D,A LD A,001H ;SWITCH DATA AND ADDRESS BUSSESLES. ; ; 4 Oct 82 - location 50 is initialised as a pointer to ; the screen management parameter table. This ; permits utilities needing to access screen ; memory to find this essential information. ; This same pointer has also been placed in ; the WATSTAR versions of this BIOS for uniformity. ; ; 8 Nov 82 - modified to support the alternate character ; set for the enhanced design machines. This ; required removing the old APL support. ; Control-\ (control-P mimic) added for MBASIC. ; ; 14 Jan 83 - keyboard, and escape handlers modified to be ; uniform with *WATSTAR BIOS. ; ; 17 Jan 83 - expansion of BIOS to handle 128 directory entry ; disks in addition to 64 directory entry disks. ; Drives A and B have a directory size of 128, and ; drives C and D have a directory size of 64. ; ; 15 Dec 86 - Switched definitions for drives A-C and B-D ; - Converted for M80 assembler ; -MD ; ; 16 Jan 87 - Warm start loader modified for standard CP/M disk ; layout ; -MD ; ; 08 Feb 87 - Modified for use with ZCPR3 ; -MD ; ; ; THIS BIOS CONTAINS THE FOLLOWING MODULES ; ; 1) BOOT LOADER ; -LOADS BIOS AND INITIALIZES THE SYSTEM ; - removed, no longer needed, performed by disk boot (md). ; ; 2) BIOS INTERFACE AND WARM BOOT MODULE ; -CONTAINS JMPS FROM CPM AND SYSTEM BOOT ROUTINES ; ; 3) INTERUPT MODULE ; -MANAGES SYSTEM INTERUPTS FOR I/O ; ; 4) DISK MODULE ; -MANAGES ALL DISK OPERATIONS ; ; 5) IOBYTE DISPATCH MODULE ; -CONTROLS ALL NON DISK I/O ; ; 6) KEYBOARD CONTROL MODULE ; -MANAGES INPUT FROM THE KEYBOARD ; ; 7) SCREEN CONTROL MODULE ; -MANAGES OUTPUT TO THE CRT SCREEN ; ; 8) PORT CONTROL MODULE ; -MANAGES INPUT AND OUTPUT FROM BOTH PORTS ; ; ;* BOOT DISK LAYOUT ;**************************************************************** ;* * * ;* Sec. Track 0 * Sec. Track 1 * ;* |-------------| * |-------------| * ;* 1 | BOOT | * | | * ;* |-------------| * 1-5 | BDOS | * ;* | | * | | * ;* | | * |-------------| * ;* 2-17 | CCP | * | | * ;* | | * | | * ;* | | * | | * ;* |-------------| * | | * ;* | | * 6-35 | BIOS | * ;* | | * | | * ;* | | * | | * ;* 13-40| BDOS | * | | * ;* | | * | | * ;* | | * |-------------| * ;* | | * 36-40 |/////////////| * ;* |-------------| * |-------------| * ;* * * ;**************************************************************** ; ; ;******************************************************** ;* * ;* SYSTEM EQUATES FOR EXTERNAL VARIABLES * ;* * ;******************************************************** ; IF1 ; Assemble messages .PRINTX *Pass 1* ENDIF IF2 .PRINTX *Pass 2* ENDIF FALSE EQU 0 TRUE EQU NOT FALSE CR EQU 0DH LF EQU 0AH ZCPR3 EQU TRUE ; Running ZCPR? IF ZCPR3 MACLIB Z3BASE.LIB ; MSIZE defined in Z3BASE.LIB ELSE MSIZE EQU 55 ; Actual CP/M size ENDIF BIAS EQU (MSIZE-20)*1024 ; BIAS BDOS EQU BIAS+3C00H ; BDOS address CCP EQU BIAS+3400H ; CCP address BIOS EQU CCP+1600H ; BIOS address NSECTS EQU (BIOS-CCP)/128 ; Size of CCP+BDOS in sectors IF1 ; Assembly messages IF ZCPR3 .PRINTX *Assembling ZCPR3 BIOS* ELSE .PRINTX *Assembling CP/M BIOS* ENDIF ENDIF VERS EQU 40 ; Current version THIS$MONTH EQU 02 ; Today's month THIS$DAY EQU 08 ; day THIS$YEAR EQU 87 ; year INTERNAL EQU TRUE INT$REV EQU 14 ; Internal revision number ; ; DSM parameter for drive DPH ; 51H(81) = 35 tracks, 5EH(94) = 40 tracks (single sided) ; A9H(169) = 70 tracks, C2H(194) = 80 tracks (double sided) ; DSM EQU 0A9H ; ; KEY DISK PARAMETERS ; MAXDSK EQU 4 ;NUMBER OF LOGICAL DISK DRIVES PHYDSK EQU 2 ;PHYSICAL NUMBER OF DISK DRIVES ; ; QLEN EQU 16 ;TYPE AHEAD QUE SIZE IOBYTE EQU 3H ; ; STORAGE UP TOP ; HARDBUF EQU 08008H ;ADDRESS OF SECOND RAM SET HSTBUF EQU BIOS+0E00H-80H ;DISK DEBLOCKING BUFFER (END OF BIOS) DIRBUF EQU HSTBUF-80H ;DIRECTORY BUFFER STACK EQU DIRBUF ;TOP OF STACK STACK1 EQU STACK-20H ;STACK DURING INTERRUPT STACK3 EQU STACK1-18H ;STACK DURING DISK I/O ; ; LOCATIONS FIXED BY CONFIGUR ; QUE EQU STACK3-QLEN-18H ;TYPE AHEAD QUE BAUD EQU QUE - 8 ;BAUD RATE MNMOD EQU BAUD + 1 ;MAIN PORT MODE MNCMD EQU BAUD + 2 ;MAIN PORT COMMAND AUXMOD EQU BAUD + 3 ;AUXIL PORT MODE AUXCMD EQU BAUD + 4 ;AUXIL PORT COMMAND FREQ EQU BAUD + 5 ;50/60 HZ HDSHAK EQU BAUD + 6 ;DATA SET READY ON/OFF RAW EQU BAUD + 7 ;READ AFTER WRITE ON/OFF ; ; TABLE OF EQUATES--I/O DEVICES ; AUXDAT EQU 40H ;AUX PORT DATA AUXST EQU 41H ;AUX PORT STATUS INTRST EQU 48H ;RESET INTERRUPT LATCH KBCHAR EQU 50H ;KEYBOARD CHARACTER MNDAT EQU 58H ;MAI8 :10DC0200E1C9F1CDB5DCC923E57DFEB0E1C021A0BB :10DC1200E2C9EBCDDEDBEBC93A0CE1B7C2ADDD798F :10DC2200FE1BCAA7DD3A12E1B72805C5CDBFDAC18E :10DC32003A0DE1B7C235DD79FE20D235DDD60638A0 :10DC42000CFE0830082150DC87CDD7D6E9C98BDC21 :10DC5200B5DCF8DCBFDCC8DC1ADD60DCECDC3A11D8 :10DC6200E1B7C0F32100F80E080600CD81DC0D20DB :10DC7200FA210000224AE2224CE22248E2FBC97C5D :10DC8200F6F86736202310F7C92A48E2232248E231 :10DC92002A4AE22C7DFE5020163A18E13C3218E165 :10DCA2002E007CFE172007E5CD42DDE1180124227B :10DCB2004AE2C93E0DD36B3E0F3251E2C9CD8BDC35 :10DCC2007DE60720F8C92A48E2115000192248E2ED :10DCD2003A18E13C3218E13A4BE2FE172007324B88 :10DCE200E2CD42DDC93C324BE2C9CD65DD2248E2DC :10DCF2003E00324AE2C92A4AE27DB4C87DB7200C0E :10DD02003A18E13D3218E12E4F2518012D224AE240 :10DD12002A48E22B2248E2C93A4BE2B7C83D324BCD :10DD2200E23A18E13D3218E12A48E211B0FF192225 :10DD320048E2C92A48E27CF6F8677977CD8BDCC9DC :10DD42003A11E1B728083A18E1FE18CCCEDAF32AE4 :10DD52004CE20650CD81DC2A4CE211500019224CD3 :10DD6200E2FBC92175DD3A4BE207CDD7D6EB2A4C4F :10DD7200E219C900005000A000F00040019001E04B :10DD82000130028002D00220037003C0031004603D :10DD920004B00400055005A005F00540069006E019 :10DDA20006300780073E01320CE1C93A0CE1FE0160 :10DDB2002846FE022806FE03281C18513A53E2B7F1 :10DDC200C234DE79D620FA0FDEFE1830403255E238 :10DDD2003E03320CE1C979D620FA0FDEFE50302D17 :10DDE2003254E22A54E2224AE2CD65DDEB2A4AE2CB :10DDF2002600192248E2181579FE592815FE3D28F9 :10DE020011FE7E2817FE352818FE36281DAF320C6B :10DE1200E1C9AF3253E23E02320CE1C93253E21899 :10DE2200F53A10E12F3210E118E3DB68EE80D36897 :10DE320018DBAF320CE179FE4B280FFE6B281DE692 :10DE42005FFE45282EFE44282EC9CD65DD3A4AE202 :10DE520006004F093E509147CD81DCC9CD4CDE3AD8 :10DE62004BE2FE17C84F3E17914F0650CD81DC0D95 :10DE720020F8C9320DE1C9AF320DE1C9CD8DDE28DE :10DE8200FBDB58C9CD8DDEC8DB58C9DB59E602C9B8 :10DE9200CD9BDE28FB79D358C9DB59E601C9CDBD3C :10DEA200DE28FBDB40C9CDB6DE28FBF54FCDD4DE44 :10DEB200F1E67FC9CDBDDEC8DB40C9DB41E602C960 :10DEC200CDDDDE28FB79D340C9CDD4DECDB6DE2848 :10DED200FBC9CDE8DE28FB79D340C93A9EE2B728D8 :10DEE20005DB41E680C8DB41E601C9DB41321BDFCD :10DEF200E6022816DB40E67FFE11200EDB41E60239 :10DF020028FADB40E67FFE1320F23A1BDFE601200F :09DF120004DB4118F879D340C981 :10DF1C003100E3F32158E21159E236007C2F477DA2 :10DF2C002F4FEDB001030021FEE01100F7EDB00121 :10DF3C000A00212DE21103F7EDB0010B002101E1E4 :10DF4C00114000EDB0214B003600213D003603217D :10DF5C003F00360F2150E01100F601AF00EDB03E4E :10DF6C0064D3683E0ED36B3EC332380021E1D62217 :10DF7C0039003E77D3603E42D341D341D359D35974 :10DF8C00133E4ED359133E17D359329AE2133E4ED9 :10DF9C00D341133E17D341DB40DB40DB58DB581336 :10DFAC003E00329EE2CD65DCCD00D7D3483E02D395 :10DFBC006B3E0ED36B3E0FD36BED56FB3E9532038F :10DFCC0000CDA4D62148E2225000061021A0E23652 :10DFDC00082310FB21EFDFCDC6D63E003204004FE4 :10DFEC00C300C00D0A35354B205A435052332028FC :10DFFC005A3830204F7065726174696E672053799E :10E00C007374656D290D0A42494F5320566572731E :10E01C00696F6E20342E30783134205B38373032D3 :10E02C002E30385D0D0A5741524E494E4721212161 :10E03C0020556E72656C65617365642042494F535F :10E04C002E0D0A80C300005A33454E560140000580 :10E05C0000E41000EC0C00F20400F40E00F7C80011 :10E06C00F60200F5042080F5D0F5D0F7004B000443 :10E07C00101F01000050181684181650423A016007 :10E08C00423A0184423A01845852015348202020DC :10E09C0020202056415220202020202020202020EB :10E0AC002020202020202020202020202020202064 :10E0BC002020202020202020202020202020202054 :10E0CC00202000005375706572627261696E2020A9 :10E0DC00202020200B0A06080000000C001B3D2508 :10E0EC002B20252B20001B54001B29001B28000073 :10E0FC00000004F7C82400010B010F01000101000E :10E10C0000000000000000A0E2A0E21000010700E7 :10E11C0000000000000013000000000000000400DC :10E12C0000000000000005000000000000001800C6 :10E13C00000000000000114100000000000011442C :10E14C0000000000000006000000000000000300BA :10E15C000000000000005049502000000000535403 :10E16C004154200000005844495220000000120085 :10E17C0000000000000044495220413A0D0044497F :10E18C005220423A0D000100000000000000413A0C :10E19C00000000000000423A000000000000115393 :10E1AC000000000000000D0A2A2A2A206469736B03 :10E1BC00206E6F74207265616479202A2A2A800D82 :10E1CC000A2A2A2A206469736B2077726974652085 :10E1DC0070726F746563746564202A2A2A800D0A34 :10E1EC002A2A2A207265636F7264206E6F7420660F :10E1FC006F756E64202A2A2A800D0A2A2A2A206327 :10E20C007263206572726F72202A2A2A800D0A2A84 :10E21C002A2A206C6F73742064617461202A2A2A64 :0BE22C0080085354415254555020000C :00D600002A 32248E231 :10DC92002A4AE22C7DFE5020163A18E13C3218E165 :10DCA2002E007CFE172007E5CD42DDE1180124227B :10DCB2004AE2C TITLE Preliminary Intertec ZCPR Bios 4.0 - (MD) 08 Feb 87 ; ; CUSTOM BIOS REWORKED IN ZILOG MNEMONICS ; ; V40BIOS.MAC ; ; THIS IS BIOS DESIGN 2 DEVELOPED BY GEORGE WALKER. ; IT IS BASED UPON THE ORIGINAL SUPERBRAIN PROGRAMS AND ; IS A STANDALONE MODULE, THAT IS IT CONTAINS ALL THE ; PROGRAMS NEEDED TO DRIVE THE SUPERBRAIN SYSTEM, INCLUDING ; THE DISK, PORT, SCREEN AND INTERRUPT SERVICING WHICH ; ARE TRANSPARENT IN THE STANDARD SUPERBRAIN BIOS SINCE ; THEY ARE EMBEDDED IN THE CUSTOM SYSGEN MODUZ3ENV@  KPPB:`B:B:XRSH VAR ADM-3A  =%+ %+ $ 5VzÔÜáñLTP^Z3IOP!>!xT##Fy0=ɯ<#q!##F#VxpyO:2! w'^wNe#DeeTTY Epson MX80 Printer (No LF's)TTY8 TTY with 8th Sig BitEPSON EPSON MX80 PrinterCRT ADM-3A CRTCRTNEC CRT Input and CRT/EPSON Printer OutputCRTTY CRT Input and CRT/TTY Printer OutputCRTMOD CRT and Modem in ParallelCRTREM CRT Input and CRT/Remote OutputCRTMOD2 CRT Input and CRT/Modem OutputREMOTE Remote ComputerMODEM Hayes Smartmodem 1200CLOCK DC Hayes Chronograph# ####-*6>-\\fReFeqL*###! >22h2i#"""ۄJۄD(ۀ(yӀ--ÀییF(ۈL(yӈ>>>ӌی>qʀyیی͎(ۈͰ͔(yӈ͎͚͚>>ӌی;(>>>2: y2y F#FR\- O-ͤ-:hyä:iyä> >ͤ2hͤ2i:10D60000C31CDFC336D6C39DDAC3CEDAC3A2DAC3E6 :10D61000BFDAC3B5DAC3A7DAC3A2D8C3C1D8C3DAA5 :10D62000D8C3DFD8C3E4D8C3EFD8C3F8D8C3C9DAA6 :10D63000C3E9D8C309DA3100E33E043E004F1E00BF :10D64000CDC1D87CB52841010000CDDAD8062C0E1A :10D65000012100C0C5E5CDDFD8C1C5CDE4D8CDEFEF :10D66000D8B72024E1C1118000190C3E28B9200C44 :10D67000C5ED4B3CE203CDDAD8C10E0010D6CDA4E7 :10D68000D63A04004FC300C02191D6CDC6D6C336CA :10D69000D60D0A42494F533A20426F6F74204572AB :10D6A000726F7280AF3240E23241E23210E13212E8 :10D6B000E13EC33200002103D622010032050021E1 :10D6C00006C8220600C9F57E4FFE803008E5CDA2CF :10D6D000DAE12318F2F1C916005F195E235623EB35 :10D6E000C9ED7356E231E0E2E5D5C5F5DB69E60444 :10D6F000C400D7DB48F1C1D1E1ED7B56E2FBED4D33 :10D70000CD23D72150E235233520043E0CD36B23A3 :10D710003520053A9AE2D359CD4BDBC8CD69DBCD34 :10D72000B3DBC92A4CE2EB2A48E27CE60F677AE6D3 :10D730000F573E01D36B3603EB36023E00D36BC965 :10D740009ED700000000000000E38FD7E5D7C6D7C2 :10D750009ED700000000000000E38FD724D805D832 :10D760009ED700000000000000E380D763D844D8B3 :10D770009ED700000000000000E380D792D873D845 :10D780002800040F01A9007F00C00020000200282B :10D7900000040F01A9003F008000100002000001FA :10D7A000020308090A0B1011121318191A1B202161 :10D7B0002223040506070C0D0E0F141516171C1D49 :06D7C0001E1F2425262790 :10D8A2003A41E2B7C4ACD9AF3240E23A37E2323B56 :10D8B200E24FAF47CD09DAB73242E2C8C3DFD9211E :10D8C200000079E6013237E279FE04D06F260029A2 :10D8D2002929291140D719C9ED4338E2C979323FC4 :10D8E200E2C9ED4346E2C9EB096E2600C93E0232A7 :10D8F20045E23EFF1805793245E2AF3244E2AF32EB :10D9020042E23A3FE2B71F1FE60F3C323AE22140C1 :10D91200E27E3601B7281906041137E2213BE21AEA :10D92200BE2006231310F8181D3A41E2B7C4ACD941 :10D93200113BE22137E2010400EDB03A43E2B7C401 :10D94200C3D9AF3241E23A3FE2E6036F260029290A :10D95200292929292911088019EB2A46E201800088 :10D962003A44E2B7201A3E013241E2D51180E3D5B2 :10D97200C5EDB0C1E1D1CD86DAEDB0CD94DA18149F :10D98200EBD51180E3D5C5CD86DAEDB0CD94DAC101 :10D99200E1D1EDB03A45E2FE013A42E2C0B7C0AF92 :10D9A2003241E2CDACD93A42E2C9CDD2D906023AED :10D9B2009FE2B720020606CD09DAB73242E2C81862 :10D9C2001CCDD2D90601CD09DAB73242E2C8180D10 :10D9D200213BE24E235623235E2180E3C921B2E19B :10D9E20017DCC6D621CBE117DCC6D621EAE1171730 :10D9F200DCC6D62105E217DCC6D62119E217DCC641 :10DA0200D63E013242E2C9ED734EE231C8E278B746 :10DA1200281AFE042816FE05282AFE012819CD60C0 :10DA2200DACD53DACD7ADAED7B4EE2C9CD60DACDCA :10DA320053DACD7ADA18F0E5CD60DACD53DAE1CDFA :10DA42007ADA18E3CD60DA068CE5E110FCAFC3297F :10DA5200DADB69E62028FADB69E62020FAC9CD86FE :10DA6200DA210288702371237B2F77237A2F773E66 :10DA7200FF320788CD94DAC9CD86DA3A0B8AF5CD22 :10DA820094DAF1C93E0AD36BDB691738FB3E08D33F :10DA92006BC93E09D36B3E0BD36BC921DFDA182F5A :10DAA20021EFDA182A2107DB3A03001F1825210F7C :10DAB200DB18F52117DB3A03001F1F18EE21F7DAF6 :10DAC2003A03001F1F18F221FFDA18F421E7DA3AAD :10DAD200030017E606CDD7D6E93EFFB7C9BDDE1F64 :10DAE200DB8DDEB0DAA0DE27DB7EDEA7DAC2DE1A4D :10DAF200DC92DEB5DAEDDE1ADCC2DECBDEDDDEDBA9 :10DB0200DADDDEDDDEB6DE86DEA8DE7EDEBDDE8DC1 :10DB1200DEBDDE8DDEC2DE92DECBDE92DE3A17E1C4 :10DB2200B7C83EFFC9AF3218E1CD1FDB28F7211776 :10DB3200E1352A15E146CD09DC2215E178FE1CC04B :10DB42003A12E12F3212E178C9DB69E6032814E6C2 :10DB520001200D3A0EE1B7C83A50E2B72802AFC928 :10DB62003EFFB7320EE1C9DB694FE60128303E0EB7 :10DB7200D36B3E0FD36B3E283250E2DB50DB50DBDF :10DB82005047FE80281C79E610782010E65FD641C7 :10DB9200FA9EDBD61AF29EDB78EE204778C93E0366 :10DBA20018D63E0F3252E23A9AE2F608D3593E8034 :10DBB200C9FE80383321D4DBE5D680FE04D83DFE91 :10DBC20004C8D607FE05C8D61EFE09D83DFE14D8E5 :10DBD200E1C9878787211AE15F1600197EB7C8E578 :10DBE200CDEADBE12310F5C9E67FF53A17E1FE1035 :10DBF20028103C3217E1F12A13E177CD09DC22131routine address in HL if match and NZ flag ; ; IF NOT COMIF condtest: lxi h,condtab ;pt to table condt1: mov a,m ;end of table? ora a rz ldax d ;get char mov b,m ;get other char in B inx h ;pt to next inx d cmp b ;compare entries brnz condt2 ldax d ;get 2nd char cmp m ;compare brnz condt2 inx h ;pt to address mov a,m ;get address in HL inx h mov h,m mov l,a ;HL = address xra a ;set NZ for OK dcr a ret condt2: lxi b,3 ;pt to next entry dad b ; ... 1 byte for text + 2 bytes for address dcx d ;pt to 1st char of condition br condt1 ; ; ENDIF ;NOT COMIF ; ; Turn on next IF level ; B register is 0 if level is inactive, 0FFH is level is active ; Return with Z flag set if OK ; ifset: lxi h,z3msg+1 ;get IF flag mov a,m ora a ;if no if at all, start 1st one brz ifset1 cpi 80h ;check for overflow (8 IFs max) brz iferr inx h ;pt to active IF byte ana m ;check to see if current IF is TRUE brnz ifset0 ;if TRUE, proceed mvi b,0 ;set False IF ifset0: dcx h ;pt to IF level mov a,m ;get it rlc ;advance to next level ani 0feh ;only 1 bit on mov m,a ;set IF byte br ifset2 ifset1: inr a ;A=1 mov m,a ;set 1st IF inx h ;clear active IF byte mvi m,0 dcx h ifset2: mov d,a ;get IF byte ana b ;set interested bit mov b,a inx h ;pt to active flag mov a,d ;complement IF byte cma mov d,a mov a,m ;get active byte ana d ;mask in only uninterested bits ora b ;mask in complement of interested bit mov m,a ;save result call ifstat ;print status xra a ;return with Z ret iferr: call print ;beep to indicate overflow db bell+80H xra a ;set NZ dcr a ret ;**************************************************************** ;* * ;* IF.COM Processing * ;* * ;**************************************************************** ; ; If IF.COM to be processed, goto ROOT (base of path) and load it ; IF COMIF runcomif: IF PATHROOT ; ; Get Current Disk and User in BC ; lda udflag ;get UD push psw ;save UD flag ani 0fh ;get disk sta cdisk ;set current disk mov b,a ;B=disk (A=0) pop psw ;get UD flag rlc ;get user in low 4 bits rlc rlc rlc ani 0fh ;get user sta cuser ;set current user mov c,a ;... in C ; ; Pt to Start of Path ; lxi h,expath ;pt to path ; ; Check for End of Path ; fndroot: mov a,m ;check for done ora a ;end of path? brz froot2 ; ; Process Next Path Element ; cpi '$' ;current disk? brnz froot0 lda cdisk ;get current disk inr a ;+1 for following -1 froot0: dcr a ;set A=0 mov b,a ;set disk inx h ;pt to user mov a,m ;get user cpi '$' ;current user? brnz froot1 lda cuser ;get current user froot1: mov c,a ;set user inx h ;pt to next br fndroot ; ; Done with Search - BC Contains ROOT DU ; ENDIF ;PATHROOT IF NOT PATHROOT ; ; Save default drive and user values ; lda udflag ;get UD push psw ;save UD flag ani 0fh ;get disk sta cdisk ;set current disk pop psw ;get UD flag rlc ;get user in low 4 bits rlc rlc rlc ani 0fh ;get user sta cuser ;set current user ; ; Set BC to drive/user in which to find IF.COM ; lxi b,100h*(ifdrv-'A') + ifusr ENDIF ;NOT PATHROOT froot2: ; ; Log Into ROOT ; call logbc ;log into root DU ; ; Set Address of Next Load and Set DMA for OPEN ; lxi h,100h ;pt to TPA shld nxtload ;set address for next load xchg ;DE=100H so don't wipe out buffers mvi c,26 ;set DMA call bdos ; ; Try to Open File IF.COM ; lxi d,extfcb ;pt to FCB mvi c,15 ;open file call bdos inr a ;check for found jz ifnotfnd ; ; Load File IF.COM ; ifload: ; ; Set Load Address ; lhld nxtload ;get address of next load push h ;save it lxi d,80h ;pt to following dad d shld nxtload pop d ;get load address mvi c,26 ;set DMA call bdos ; ; Read in Block (Sector) and Loop Back if Not Done ; lxi d,extfcb ;read file mvi c,20 push d ;save ptr in case of failure (done) call bdos pop d ora a ;OK? brz ifload ; ; Done - Close File ; mvi c,16 ;close file call bdos ; ; Reset Environment (DMA and DU) and Run IF.COM ; call reset ;reset DMA and directory jmp tpa ;run IF.COM ; ; Reset DMA Address and Current Disk (in CDISK) and User (in CUSER) ; reset: lxi d,80h ;reset DMA address mvi c,26 call bdos lda cdisk ;return home mov b,a lda cuser mov c,a ; ; Log Into DU in BC ; logbc: mov e,b ;set disk push b mvi c,14 ;select disk call bdos pop b mov e,c ;set user mvi c,32 ;select user jmp bdos ; ; IF.COM not found - Process as IF F ; ifnotfnd: call reset ;return home jmp ifcf ; ; Buffers for COMIF ; nxtload: ds 2 ;address of next block (sector) to load cuser: ds 1 ;current user cdisk: ds 1 ;current disk (A=0) ; ENDIF ;COMIF ; ; ; Test for Size Error ; if ($ GT (FCP + FCPS*128)) sizerr equ novalue ;FCP is too large for buffer endif end ndition match brnz runcond ;if found, process condition IF COMIF jmp runcomif ;if function not found in table, use IF.COM ENDIF ;COMIF call print ;beep to indicate error db bell+80H jmp ifstat ;no condition, display current condition ; ; Process register - register value is in A ; IF IFOREG runreg: push psw ;save value call getnum ;extract value in FCB2 as a number pop psw ;get value cmp b ;compare against extracted value brz ifctrue ;TRUE if match br ifcfalse ;FALSE if non-match ENDIF ;IFOREG ; ; Process conditional test - address of conditional routine is in HL ; runcond: pchl ;"call" routine pted to by HL ; ; ; Condition: NULL (2nd file name) ; IF IFONULL ifcnull: lda fcb2+1 ;get first char of 2nd file name cpi ' ' ;space = null brz ifctrue br ifcfalse ENDIF ;IFONULL ; ; Condition: TCAP ; IF IFOTCAP ifctcap: lda z3env+80H ;get first char of Z3 TCAP Entry cpi ' '+1 ;space or less = none brc ifcfalse br ifctrue ENDIF ;IFOTCAP ; ; Condition: WHEEL ; IF IFOWHEEL ifcwheel: lhld z3env+29h ;get address of wheel byte mov a,m ;get byte ora a ;test for true brz ifcfalse ;FALSE if 0 br ifctrue ENDIF ;IFOWHEEL ; ; Condition: TRUE ; IFCTRUE enables an active IF ; Condition: FALSE ; IFCFALSE enables an inactive IF ; ifctrue: ; IF IFONEG call negtest ;test for negate brz ifcf ENDIF ;IFONEG ; ifct: mvi b,0ffh ;active jmp ifset ifcfalse: ; IF IFONEG call negtest ;test for negate brz ifct ENDIF ;IFONEG ; ifcf: mvi b,0 ;inactive jmp ifset ; ; Condition: INPUT (from user) ; IF IFOINPUT ifcinput: lxi h,z3msg+7 ;pt to ZEX message byte mvi m,10b ;suspend ZEX input push h ;save ptr to ZEX message byte IF NOT NOISE call nl ENDIF ;NOT NOISE call prif call print db 'True?',' '+80H mvi c,1 ;input from console call bdos pop h ;get ptr to ZEX message byte mvi m,0 ;return ZEX to normal processing cpi ' ' ;yes? brz ifctrue ani 5fh ;mask and capitalize user input cpi 'T' ;true? brz ifctrue cpi 'Y' ;yes? brz ifctrue cpi CR ;yes? brz ifctrue br ifcfalse ENDIF ;IFOINPUT ; ; Condition: EXIST filename.typ ; IF IFOEXIST ifcex: call tlog ;log into DU lxi d,fcb2 ;pt to fcb mvi c,17 ;search for first call bdos inr a ;set zero if error brz ifcfalse ;return FALSE br ifctrue ;return TRUE ENDIF ;IFOEXIST ; ; Condition: EMPTY filename.typ ; IF IFOEMPTY ifcempty: call tlog ;log into FCB2's DU lxi d,fcb2 ;pt to fcb2 mvi c,15 ;open file push d ;save fcb ptr call bdos pop d inr a ;not found? brz ifctrue mvi c,20 ;try to read a record xra a ; set cr value to zero sta fcb2+32 ; to attempt to read first record call bdos ora a ;0=OK brnz ifctrue ;NZ if no read br ifcfalse ENDIF ;IFOEMPTY ; ; Condition: ERROR ; IF IFOERROR ifcerror: lda z3msg+6 ;get error byte ora a ;0=FALSE (no error registered) brz ifcfalse br ifctrue ENDIF ;IFOERROR ; ; **** Support Routines **** ; ; ; Convert chars in FCB2 into a number in B ; IF IFOREG getnum: mvi b,0 ;set number lxi h,fcb2+1 ;pt to first char getn1: mov a,m ;get char inx h ;pt to next sui '0' ;convert to binary rc ;done if error cpi 10 ;range? rnc ;done if out of range mov c,a ;value in C mov a,b ;A=old value add a ;*2 add a ;*4 add b ;*5 add a ;*10 add c ;add in new digit value mov b,a ;result in B br getn1 ;continue processing ENDIF ;IFOREG ; ; Log into DU in FCB2 ; IF IFOEXIST OR IFOEMPTY tlog: lda fcb2 ;get disk ora a ;current? brnz tlog1 mvi c,25 ;get disk call bdos inr a ;increment for following decrement tlog1: dcr a ;A=0 mov e,a ;disk in E mvi c,14 call bdos lda fcb2+13 ;pt to user mov e,a mvi c,32 ;set user jmp bdos ; ENDIF ;IFOEXIST OR IFOEMPTY ; ; Test of Negate Flag = negchar ; IF IFONEG negtest: negflag equ $+1 ;pointer for in-the-code modification mvi a,0 ;2nd byte is filled in cpi negchar ;test for No ret ENDIF ;IFONEG ; ; Test FCB1 against a single digit (0-9) ; Return with register value in A and NZ if so ; IF IFOREG regtest: ldax d ;get digit sui '0' brc zret ;Z flag for no digit cpi 10 ;range? brnc zret ;Z flag for no digit lxi h,z3msg+30H ;pt to registers add l ;pt to register mov l,a mov a,h ;add in H aci 0 mov h,a xra a ;set NZ dcr a mov a,m ;get register value ret zret: xra a ;set Z ret ENDIF ;IFOREG ; ; Test to see if a current IF is running and if it is FALSE ; If so, return with Zero Flag Set (Z) ; If not, return with Zero Flag Clear (NZ) ; Affect only HL and PSW ; iftest: lxi h,z3msg+1 ;get IF flag mov a,m ;test for active IF ora a brz ifok ;no active IF inx h ;pt to active flag ana m ;check active flag rz ;return Z since IF running and FALSE ifok: xra a ;return NZ for OK dcr a ret ; ; Test FCB1 against condition table (must have 2-char entries) ; Return with ifstart db 'ELSE' dw ifelse db 'FI ' dw ifend db 'XIF ' dw ifexit db 0 ; ; Condition Table ; condtab: ; IF IFOTRUE db 'T ' ;TRUE dw ifctrue db 'F ' ;FALSE dw ifcfalse ENDIF ; IF IFOEMPTY db 'EM' ;file empty dw ifcempty ENDIF ; IF IFOERROR db 'ER' ;error message dw ifcerror ENDIF ; IF IFOEXIST db 'EX' ;file exists dw ifcex ENDIF ; IF IFOINPUT db 'IN' ;user input dw ifcinput ENDIF ; IF IFONULL db 'NU' dw ifcnull ENDIF ; IF IFOTCAP ;Z3 TCAP available db 'TC' dw ifctcap ENDIF ; IF IFOWHEEL ;Wheel Byte db 'WH' dw ifcwheel ENDIF ; db 0 ; ; Print " IF" ; prif: call print db 'IF',' '+80H ret ; ; Print String (terminated in 0 or MSB Set) at Return Address ; print: IF NOISE mvi a,' ' ;print leading space call conout ENDIF ;NOISE xthl ; get address call print1 xthl ; put address ret ; ; Print String (terminated by MSB Set) pted to by HL ; print1: mov a,m ; done? inx h ; pt to next call conout ; print char ora a ; set MSB flag (M) rm ; MSB terminator br print1 ; ; **** FCP Routines **** ; All code from here on is FCP-dependent! ; ; ; FCP Command: XIF ; XIF terminates all IFs, restoring a basic TRUE state ; ifexit: IF NOISE call nl ;print new line ENDIF ;NOISE call iftest ;see if current IF is running and FALSE brz ifstat ;abort with status message if so lxi h,z3msg+1 ;pt to IF flag xra a ;A=0 mov m,a ;zero IF flag br ifendmsg ;print message ; ; FCP Command: FI ; FI decrements to the previous IF ; ; Algorithm: ; Rotate Current IF Bit (1st IF Message) Right 1 Bit Position ; ifend: IF NOISE call nl ;print new line ENDIF ;NOISE lxi h,z3msg+1 ;pt to IF flag mov a,m ;get it ora a ;no IF active? brz ifnderr ifendmsg: IF NOISE push psw ;save A call print db 'T','o'+80H ;prefix to status display pop psw ;get A ENDIF ;NOISE rrc ;move right 1 bit ani 7fh ;mask msb 0 mov m,a