IMD 1.17: 2/06/2011 15:32:49 super bios for super six sbc dsdd  >o:~W!{> " OC > S>O:31!2|}N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!'}#"* (,*#"+))[R#}! !!Ax͎qput+[[R8 utx7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !;NFx(ENF C$7?KnfB8C[0MD!' {:m!;!NFnfB#>,(0W}_nfRut;RDM!A76! [36:G6!w0 ͖!2͖ !͗>O3F#Nů  SYS: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file *+":*+"/:*+"^:*+":!":"5:"d:":!":"7:"f:"::8*9:8=o&))8  ^#V!q;p+q!r;6>!r;2*r;&;) p;3>L ~ÒÃG3x(OxAG:xG~ > 2v:nO y~ 8 q!*z~(ͭ8͏ͷ:q2t>2>2yKc> 2v> :yG /_~(!` *k:t{  _!c(  :v= L{((ZZ:nhZ:thZ:xhZZ>2v ~  ( w:q2rF8 <2ty2x:qW:j*mKoB(7:rGz?"|*m"o:qG2rxG![k2jG!> z{2n2xw<2q*k!` "kͱ"k: (8 ~Zd>w(>>w~Can't recognize density of disk in$Read$Write$Seek$ error on track $ sector $ side $ drive $ $!\6͂ !!y;6͂6 :y;- !Ͱ ͭ :s;:| :\:y;HZ !:]A<2\O>n !*y;&\ 6 ì !y;6:s;.¨ ͭ͂ڨ :y; ڟ !Ͱ ͭÌ ! :y;<2y;O!\ :s;w:s;0O> :s;02s;> :s;AO> :s;A 2s;>>!"z; :s;<:s;]:s; HҀ :s;S¸ !96ͭ} :s;P !96 "9} :s;D !96 "9} :s;L "8} :s;M 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>"FORMAT MACSUBMIT COM CPMO SYSP FORMAT MACSBCBOOT MACLDRBDOS MAC^MODEM COM;FORMAT COM FMTHD MACd !"#$%&SUPRBIOSMAC'(bcdRAMDISK MAC)*CPM SYSN+,-./RAMDISK PRNL01234RAMDISK REL5MAID5046PAS6789:;<=MAID5046PAS>?@ABCDETRK0 LDRMNLODRBIOSMACOPQRSTUVLODRBIOSMACWXYZ[\]^LODRBIOSMAC_`FMTHD COMaNEWSIZE DOCeCPMINSTADOC fREADFRSTDOCghSBCHBOOTMACijMODEM DOC`klmnopLOADER DOCqrUSER DOCstHDBADMPRCOM uHDBADMPRMAC`vwxyz{INTRFACEDOC,|}~FORMAT DOCTRK0506 LDRTRK02020LDRHDUPDATEDOCTRK02040LDRMOVCPM COMLPIP COM:XSUB COM ED COM4 ASM COM@DDT COM&LOAD COMSTAT COM)SYSGEN COMDUMP COMLDRGEN COMSUPRBIOSMACSUPRBIOSMACSUPRBIOSMACSUPRBIOSMACMAID5046PASFGHIJKLMAID5046PASMAID5046PASkM5046 ASMM5046 ASMM5046 ASMM5046 ASMM5046 ASMM5046 ASMM5046 ASMM5046 ASM .Z80 ;FORMAT VERSION 3.0 ; ; ;FORMAT PROGRAM FOR THE WD1791 FDISK CONTROLLER ; FALSE EQU 0 TRUE EQU NOT FALSE CR EQU 0DH LF EQU 0AH ; BDOS EQU 5 ;BDOS ENTRY POINT WBOOT EQU 0 ;WARM BOOT RETURN ; ; ;DISK DRIVE TYPE MINI EQU FALSE ;SET TO TRUE FOR 5.25 IN. DISKS FORTY8 EQU TRUE ;SET TO TRUE FOR 48TPI DRIVES ; ; ;DENSITY AND SIDE INDICATORS/CODES INFORMATION ; DD EQU 1 ;DOUBLE DENSITY FLAG SD EQU 0 ;SINGLE DENSITY FLAG SS EQU 0 ;SINGLE SIDED FLAG DS EQU 1 ;DOUBLE SIDED FLAG DDDS EQU 0E7H ;DOUBLE DENS DOUBLE SIDED CODE DDSS EQU 0E6H ;DOUBLE DENS SINGLE SIDED CODE SDSS EQU 0E5H ;SINGLE DENSITY SINGLE SIDED CODE DATA EQU 0E5H ;VALUE TO FILL SECTORS WITH RPT EQU 099H ;REPEAT INDICATOR ENDRPT EQU 066H ;END OF REPEAT INDICATOR ENDTRK EQU 0AAH ;END OF TRAK MARKER IDAM EQU 0FEH ; ID ADDRESS MARK IF FORTY8 MINITRKS EQU 40 ;48TPI MINI MAX TRACKS ELSE MINITRKS EQU 77 ;96TPI MINI MAX TRACKS ENDIF EINCHTRKS EQU 77 ;8 INCH DIVE MAX TRACKS MINISECS EQU 4 ;MINI SECTORS DDSECӠ EQU 8 ;8 INCH DOUBLE DENSITY SECTORS SDSECS EQU 26 ;8 INCH SINGLE DENSITY SECTORS ; ;DISK COMMANDS SEEK EQU 019H ;SEEK WTRAK EQU 0F4H ;WRITE TRACK RESTORE EQU 01H ;RESTORE SECTRD0 EQU 082H ;READ SECTOR SIDE ZERO SECTRD1 EQU 08AH ;READ SECTOR SIDE ONE ; CMD EQU 0CH ;COMMAND REGISTER TRACK EQU CMD + 1 ;TRACK REGISTER SECT EQU CMD + 2 ;SECTOR REGISTER DAL EQU CMD + 3 ;DATA PORT ; WAIT EQU 014H ;STATUS/SELECT REGISTER ; ; CSEG ; START: LD SP,START ;INITIALIZE STACK POINTER LD DE,MSG1 CALL PRNT ;PRINT START MESSAGE ; ;OBTAIN DISK DRIVE NUMBER ; RESTART: LL: LD DE,MSG4 CALL PRNT CALL CHARIN ;GET DRIVE TO BE USED SUB '0' JR C,LL CP 4 JR NC,LL LD (DRIVENO),A ;SAVE DRIVE NUMBER ; ;OBTAIN DENSITY INFORMATION ; IF MINI LD A,DD LD (DENS),A ;SET DOUBLE DENSITY FOR MINI ; ELSE LER: LD DE,MSG5 CALL PRNT CALL CHARIN ;ASK USER DENSITY INFO CP 'D' JR Z,DOUBLE CP 'S' JR NZ,LER ;ERROR LD A,SD ;SET SINGLE DENSITY JR SDDDCNTL ; DOUBLE: LD A,DD SDDDCNTL: LD (DENS),A ;SET DOUBLE DENSITY ENDIF ; LD A,(DENS) CP SD JR NZ,CHEKSIDE ;GET SIDE (DOUBLE/SINGLE) INFO LD A,SS JR SIDECNTL ;SET SINGLE SIDED CHEKSIDE: LD DE,MSG6 CALL PRNT CALL CHARIN ;ASK USER IF SINGLE OR DOUBLE SIDED CP 'S' JR NZ,CHEKDS LD A,SS JR SIDECNTL ;SET SINGLE SIDED CHEKDS: CP 'D' JR NZ,CHEKSIDE LD A,DS SIDECNTL: LD (SIDED),A ; ERR: LD DE,MSG7 CALL PRNT ;SEE IF SYS TRAKS ONLY CALL CHARIN CP 'N' JR Z,CONTINUE CP 'Y' JR NZ,ERR LD A,(DENS) CP SD JR NZ,ONETRK ;SET MAX TRAKS TO ONE FOR DOUBLE DENS LD A,2 ;SET TO TWO FOR SINGLE DENSITY ONETRK: LD (MAXTRKS),A JR CONT1 ;INDICATE SYSTEM TRACKS ONLY ; CONTINUE: XOR A CONT1: LD (SYSFLAG),A ; ;SEE IF VERIFY SHOULD BE SUPRESSED LLL: LD DE,MSG77 CALL PRNT CALL CHARIN CP 'N' JR Z,DNTSUPRES CP 'Y' JR NZ,LLL LD A,1 JR LL1 DNTSUPRES: XOR A LL1: LD (SPFLAG),A REDO: ;SET UP OPERATIONAL PARAMETERS ; IF MINI LD A,(SIDED) CP SS JR Z,NDSIDED LD A,DDDS ;DOUBLE SIDED CODE INFORMATION JR FWD NDSIDED: LD A,DDSS ;SINGLE SIDED CODE INFORMATION FWD: LD (DENSCODE),A LD A,(SYSFLAG) OR A JR NZ,DONTCHG LD A,MINITRKS LD (MAXTRKS),A DONTCHG: LD A,MINISECS LD (MAXSECS),A LD IX,DDCONTROL ;LOAD IX WITH DOUBLE DENSITY CONTROL BLOCK ADDRES LD (IXTRK1ON),IX ;SAVE IX POINTER LD IY,MINISEQ LD (IYTRK1ON),IY ;SAVE IY POINTER LD IY,MINISEQ0 ;SET IY TO POINT TO TRACK 0 FORMAT ELSE LD A,(SYSFLAG) ;CHECK SYSTEM TRACKS ONLY INDICATOR OR A JR NZ,DONTCHNG LD A,EINCHTRKS LD (MAXTRKS),A DONTCHNG: LD A,(DENS) CP SD ;CHECK SINGLE DENSITY JR Z,NDD LD IX,DDCONTROL LD (IXTRK1ON),IX LD IY,DDSEQ LD (IYTRK1ON),IY LD A,(SIDED) CP SS JR Z,NDSIDED LD A,DDDS ;DOUBLE DENSITY DOUBLE SIDED CODE INFO JR FWD1 NDSIDED: LD A,DDSS ;DOUBLE DENSITY SINGLE SIDED CODE INFO FWD1: LD (DENSCODE),A ; ;SET CONTROL PARMETER TO SINGLE DENSITY,EVEN IF WORKING WITH DOUBLE DENSITY ;SINCE TRACK ZERO IS ALWAYS FORMATTED SINGLE DENSITY LD IX,SDCONTROL ;SET SINGLE DENSITY CONTROL LD IY,SDSEQ JR HERE NDD: LD A,SDSS ;SINGLE DENSITY SINGLE SIDED DENS CODE LD (DENSCODE),A LD IX,SDCONTROL LD (IXTRK1ON),IX ;SET CONTROL TO SINGLE FOR ALL TRACKS LD IY,SDSEQ LD (IYTRK1ON),IY ;SET SECTOR SEQUENCE ALSO TO SINGLE HERE: LD A,SDSECS ;SINGLE DENSITY SECTORS LD (MAXSECS),A ENDIF ; ;SAVE IX AND IY REGISTERS FOR TRACK ZERO DOUBLE SIDED RETRIEVE LD (IX0SAVE),IX ;SAVE IX LD (IY0SAVE),IY ;SAVE IY ;PROMPT USER BY ASKING TO TYPE A RETURN TO BEGIN FORMATTING LD DE,MSG8 CALL PRNT LD A,(DRIVENO) ADD A,030H CALL CHAROUT ;PRINT DRIVE NUMBER LD DE,MSG9 CALL PRNT LD C,1 CALL BDOS CP CR JP NZ,WBOOT ;GO BACK TO CPM CALL CHAROUT LD A,LF CALL CHAROUT ; ;RESET HEAD AND DISK DRIVE STATUS REGISTERS CALL RESUMESCREEN XOR A LD D,A ;START WITH TRACK ZERO LD (SIDE),A ;SIDE ZERO CALL SELSIDE ;SELECT SIDE LD A,RESTORE CALL PERFORM ; ;MAIN PROGRAM LOOP BASICALLY STARTS HERE L11: PUSH IX PUSH IY PUSH DE LD DE,MSG147 CALL PRNT POP DE LD A,D PUSH DE CALL HEXOUT POP DE POP IY POP IX L12: LD HL,BUFFER ;BUFFER TO SET UP DATA L1: LD A,(IX) ;GET CONTROL CP RPT ;IS IT REPEAT? JR NZ,NRPT INC IX CALL REPEAT ;PERFORM REPEAT IF SO JR L1 NRPT: CP ENDTRK ;IS END OF CONTROL FOR THIS TRACK ? JR Z,WRITE CALL PUT ;SET UP BUFFER ACCORDINGLY JR L1 ; WRITE: LD HL,BUFFER ;SET HL TO BUILT BUFFER DI ;DISABLE INTERRUPTS CALL WRTRAK ;WRITE THIS TRACK EI ;REENABLE INTERRUPTS IN A,(CMD) ;CHECK FOR ERROR LD (STATUS),A OR A JP NZ,WRERROR ;PROCEES WRITE ERROR LD A,(SPFLAG) ;SEE IF READ SHOULD BE SUPRESSED OR A JR NZ,DONTVRFY CALL RDTRK ;VERIFY BY READING DONTVRFY: LD A,(SIDED) CP SS JR Z,NOTDSIDED LD A,(SIDE) OR A JR Z,CHNGSIDE ;CHANGE SIDE TO ONE AND WRITE OTHER SIDE XOR A LD (SIDE),A ;OTHERWISE RESET SIDE BACK TO ZERO CALL SELSIDE ;SELECT SIDE ZERO SKIPTONEXT: NOTDSIDED: PUSH DE ;SAVE REG LD C,11 ;CHECK CONSOLE STATUS CALL BDOS OR A ;CHAR AVAIL. POP DE ;RESTORE DE JR Z,SKP ;SKIP IF NOT PUSH DE ;SAVE REG LD C,1 ;GET CHAR CALL BDOS CP 3 ;IS IT A ^C POP DE ;RESTORE DE JP Z,ABORT ;IF SO ASK IF EXIT SKP: INC D ;INCREMENT TRACK COUNTER LD B,D LD A,(MAXTRKS) CP B JR Z,COMPLETE ;IF MAX TRACK REACHED THEN DONE IF NOT MINI ; ;SEE IF CONTROL PARAMETERS HAVE TO BE SWITCHED FROM SINGLE TO DOUBLE ; LD A,D CP 1 ;SEE IF TRACK ONE JR NZ,NOTTRK1 LD A,(DENS) CP DD ;SEE IF DOUBLE DENSITY JR NZ,NOTDD LD A,DDSECS ;SET MAX DOUBLE DENSITY SECTORS LD (MAXSECS),A CALL SELSIDE ;SELECT DOUBLE DENSITY NOTDD: NOTTRK1: ENDIF ; ;PREPARE FOR NEXT TRACK LD A,D OUT (DAL),A ;SET DATA REGISTER TO PROPER TRK LD A,SEEK ;SEEK TO NEXT TRACK CALL PERFORM LD IX,(IXTRK1ON) ;GET IX POINTER LD IY,(IYTRK1ON) ;GET IY POINTER JP L11 CHNGSIDE: LD A,1 ;SIDE ONE LD (SIDE),A CALL SELSIDE ;SELECT SIDE ONE LD A,D OR A ;TEST FOR TRACK ZERO JR NZ,NOTZ LD IX,(IX0SAVE) ;RETRIEVE TRACK ZERO IX LD IY,(IY0SAVE) ;RETRIEVE TRACK ZERO IY JP L12 ;FORMAT SIDE ONE NOTZ: LD IX,(IXTRK1ON) ;RESET IX LD IY,(IYTRK1ON) ;RESET IY JP L12 ;FORMAT SIDE ONE ; ABORT: LD DE,ABTMSG ;PRINT ABORTED MESSAGE CALL PRNT JR L2 ; COMPLETE: LD DE,MSG10 CAL PRNT ;END OF OPERATION MESSAGE L2: LD DE,MSG11 CALL PRNT CALL CHARIN OR A JP Z,WBOOT CP 'C' JR NZ,L2 XOR A LD (DENDNE),A ;CLEAR DENSITY WRITE FLAG L5: LD DE,MSG12 CAL PRN ;SEE IF THE SAME PARAMS ARE TO BE USED CALL CHARIN OR A JP Z,REDO CP 'N' JR NZ,L5 JP RESTART ; ;REPEAT SUBROUTINE BUILDS THE BUFFER FOR THE NUMBER OF SECTORS SPECIFIED ; ; REPEAT: LD A,(MAXSECS) ;MAX SECTORS LD C,A LD (IXSAVE),IX ;SAVE IX L6: LD E,(IY) ;SECTOR NUMBER IN E REGISTER INC IY LOOP1: LD A,(IX) CP ENDRPT ;IS IT END OF REPEAT JR Z,ENDR CALL PUT ;BUILD BUFFER JR LOOP1 ENDR: INC IX DEC C RET Z LD IX,(IXSAVE) JR L6 ; ;THE PUT SUBROUTINE TAKES COMMAND FROM CONTROL BUFFER AND BUILDS ACCORDINGLY ; PUT: LD B,(IX) ;REPEAT COUNT INC IX LD A,(IX) ;DATA VALUE INC IX CP IDAM ;IS IT ID ADDRESS MARK JR NZ,NOTIDAM LD (HL),A ;PUT DATA INC HL LD (HL),D ;PUT TRACK INC HL LD A,(SIDE) ;SIDE LD (HL),A INC HL LD (HL),E ;SECTOR INC HL RET ; NOTIDAM: LOOP: LD (HL),A INC HL DEC B JR NZ,LOOP CP DATA ;SEE IF DATA VALUE RET NZ LD A,(SIDE) ADD A,E ;GET SECTOR NUMBER DEC A OR D ;TRACK PUSH BC LD B,A LD A,(DENDNE) ;WRITTEN DENSITY CODE ALREADY OR B POP BC RET NZ ;IF TRACK 0 SECT ONE THEN SET DENS CODE LD A,(DENSCODE) ;GET DENS CODE DEC HL ;POINT TO THE LAST BYTE OF DATA LD (HL),A ;PUT DENS CODE INC HL LD (DENDNE),A ;SAY DONE ONCE RET ; ; CHARIN SUBROUTINE INPUTS ONE CHARACTER FROM CONSOLE IN A REGISTER CHARIN: XOR A LD (IBUFF+2),A LD C,10 LD DE,IBUFF LD A,80 LD (DE),A CALL BDOS LD A,(IBUFF+2) CP 'a' JP C,LOWER CP 'z'+1 JP NC,LOWER AND 05FH LOWER: RET ; CHAROUT: LD C,2 LD E,A CALL BDOS RET ; PRNT: LD C,9 CALL BDOS RET ; RESUMESCREEN: PUSH DE LD A,(SPFLAG) OR A JR NZ,SPSCREEN LD DE,MSG13 CALL PRNT LD DE,MSG14 CALL PRNT LD DE,MSG147 CALL PRNT JR KK SPSCREEN: LD DE,MSG148 CALL PRNT LD DE,MSG147 CALL PRNT KK: POP DE LD A,D PUSH DE CALL HEXOUT POP DE RET ; MSGP: DB CR,LF,LF,'DISK ERROR: $' ; PERFORM: DI OUT (CMD),A IN A,(WAIT) EI IN A,(CMD) ;GET STATUS OR A ;NEEDS TO BE VALIDATED RET ;ERROR PUSH AF LD DE,MSGP CALL PRNT POP AF CALL DETERMERR JP WBOOT ;BACK TO CPM ; WRTRAK: LD A,WTRAK LD C,DAL OUT (CMD),A L3: IN A,(WAIT) OR A RET P ; OUTI JR L3 ; ;READ VRIFY ROUTINE ; RDTRK: LD (IYSAVE),IY ;SAVE IY FOR A POSSIBLE RETRY LD A,(MAXSECS) ;SAVE MAX SECS LD (READSECS),A NEXTSECTOR: XOR A ;RESET RET copyright(c) 1977, digital research $Error On Line $SUBNo 'SUB' File Present$Disk Write Error$Command Buffer Overflow$Command Too Long$Parameter Error$Invalid Control Character$Directory Full$Cannot Close, Read/Only?$!9"!͇͊!p+q* ͊!p+q*͍2!p+q*͍2!p+q*͊!p+q*͍!p+q*͍!p+q*͍2!s+p+q+p+q:=2ʦ** w*#"*#"!p+q(+*DM*p*& 6:ep\:=ͧ!t6>!t%\= >!t6:t<2t=O! ~2u b:<2O>9b!60+~9b!60+4:uat:u_2u:uMʉSͧ!v6!"v!|6:|Ҁ!x6 2}:} Hk:} h:}$6 2}$*}M3:}02}O> ͧ3!z6ͭ:}"!}5́ͭ́3*yM"h:}^a a2}O>Vͧ^:}>*z& ~ !z4í!{q*v#"v͙dͧ*vv :{w:x<2xO>}|ͧ-!6]:ͧz2~e:~2O! 6*~& 6$>!~_z*~& w!~5Bx:yͧ*v+"vv ~_{ozg001 $$$$ SUB ͊!p+q*͍2!p+q*͍2!p+q*͊!p+q*͍!p+q*͍!p+q*͍2!s+p+q+p+q:=2ʦ** w*#"*#"!p+q(+*DM*p*& 6:ep\:=ͧ!t6>!t%\= >!t6:t<2t=O! ~2u b:<2O>9b!60+~9b!60+4:uat:u_2u:uMʉSͧ!v6!"v!|6:|Ҁ!x6 2}:} Hk:} h:}$6 2}$*}M3:}02}O> ͧ3!z6ͭ:}"!}5́ͭ́3*yM"h:}^a a2}O>Vͧ^:}>*z& ~ !z4í!{q*v#"v͙dͧ*vv :{w:x<2xO>}|ͧW Extended Submit Vers 2.0Xsub Already Present$Requires CP/M Version 2.0 or later$:y*###ƒ# yk   җ 4!~=ŐW!xʵ ~#èbx {~#o}où.xsubb!np+q*m2_!pp+q*o ]xsub*"-!/"*"+!""1 M*!"́!"* (xsub active)$|*y ʥ*"*7***x*́͋<͛ :%*=26͋!7^#6 #6 #6$ 8*7~O #w# !6:6=2% ͋*-"*$$$ SUBq:(=2(N *$*& w*$#"$*&#"&' !"N*M^7 !)6:!)ھ *N*DM͆ 2*ʭ :*ʗ ͯ *N"P*6:2)÷ *N"N!) $@BA$! A "!$"" :2!q: " *M n :c4 *M n :2!c:Q !c:2: !:cw>!n !5 Y : { !6!q:!lwҙ  â :0O !q:O| :O| !6:]2l:o'2o:n'2n:m'2m*mMͣ *nMͣ *oMͣ :]:   *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z!/H:_2:!q:A/>Z!/H8: 2::=O>m:W!Q} Hmd>9>!6:2*M!E ^#V͎ڗO **~2*#"m2m͖ 2m!6m!6m!6 m2mͯ m!62m!62m!62m!62m'2:2:TҒ:2!6*ME:2::Ҳ:<22ý: 2:} >ͯ :i:2:d*M:[  COPYRIGHT (C) 1979, DIGITAL RESEARCH DISK OR DIRECTORY FULL$FILE EXISTS, ERASE IT$NEW FILE$** FILE IS READ/ONLY **$"SYSTEM" FILE NOT ACCESSIBLE$BAK$$$BAK$$$-(Y/N)?$NO MEMORY$BREAK "$" AT $1mM"m +!8s~1m!f6 *M  *!M 1m! 6!6! 6: 2Ebͽ!e:d\::eH2 H҆ͽ:e2!:d2e:!2dû :!I¬!: :H2 ҮX:h2iҐ:!ʍ:!:!H:!H,!"! 6#~ F)ͷX:! X):i!h)9 e:!:h2jO>F L>!":i!jHҼ*"+M ~ ʼͲ!f6!h6!"! 6F!f6:h2k!iҠ:i2k:j2h:k!hҶ9 æ:h2j!!6:j2he:! >"Ͳ*"M ~2!O :! *+"!!6e*!M͛ /$^L:!@OL:! 2͑e:b:! L:h<2hb:! b:hO>!hw:! pX:! …!!6  LÊ!!6ûô:!ʛ͑:! ҩ OҸû:!R†!6G>!!!6 :2.t -? >!!6!6s, !6:xB!6OU2!SB!G6:҃!6:G҃*G& ~2!:G<2G_ Qқ=e  b:!-®! 6:!#¿͇;J:!:!!6Lv:!:Jv: *#"͎! 6:!B)! >w!"&*o"(R :!C:eR :!DKeX :!K\ͷX :!Lj^ :!Pš͎҇! 6F×͢җ:Ç :!T¨F :!U¾: 2 :!V͎"$DMͩ/ *oDMͩ : 2 :! (::H%^bF : ͎H :!Ay! 6*""&*o"(R͎an͢na! 6R :!F”͢ґ Ä :!J $:2$͢ :=2:<2!*& ~2!ü*""I*M*o/!:""&! 6R*I""ë :!M:H| ! 6>F ͛e: <2 O! Hqy d F : 2! 6*#s#r :!N ͢ *o/ Ҧ Ͷn! 6!"&R! 6o$ Î Ç :!S0 $͢- :2"+s#r!:* *& ~2!:<2 :!W> v :!X³ Z͎\ Ee ð :7/҃ E!76e ͕ :xƒ - ͷ*&"K(Kڰ *KM N͔*K"KҌ :!Z ͎  ͢ : :!  'v!gq:f *g&!lq:l $ !h4:l 1 !h6*lM :hB     !h55!mq:m :hO>H2ny} !m6 !o6:n!oښ *mM !o4‚ !pq:p ڪ >:p :p H:p H!qq*qM͛  ^W :q@2q*qMW   !sp+q*r !up+q *tDM !wp+q*v !zp+q*y2x!|p+q*{2x!~p+q*}2x!p+q*!p+q*!p+q*!p+q*2x!p+q*!6   >>! q* &!p+q*:7 e !p+q*DM  =? ) !p+q.*DMF -L *9"`!"b!h6!j6!|6.!=\ -x !e:dʥ *eM \R :xʥ @ *dM \, :x \͕ :x - V :e _ :f w : =e !e:d*eM =e : =e =͕ !]6:x>- !"!76!6!6!66*dM  *dM !6:8!*`*;DM \u 2xʻ>!xҨ- *`*;6:82*`"`:<2w!"`9`h*`*;~2*`#"`:*eM !b+!s{!f!6:!b*b*^DM =ͅ N- *b"b:<2)f!"b!q9bڀ*b*^:w*b#"b!q:6ڶZͅ ʱ- !66*6& :w:6<26!J6*b}:J<2Jm=? :x- : ;*dM .=\ -=ͨ ;: *eM =ͨ .M= -C!q:Y*M !q:a/>z!/H!q*MaҎ:_:!q:ҥ*My:!p+q!'"!6>**ͪ{2**ͪ"*! ͪ":!!\X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<ԯ2 Շ!۶2:2a{_:۷ʖ:۷>Ľʖ:=2–!B!6#5ʖ:۷Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ "ַ"͌#>?͌͘ =_.:;<> Oօo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USERg!yO#< Ty#O 3ׯ21y_͸2y2ͽ:Է˜1͘A͌>>͌92^ :۷¥.!_~#fow]٭ڎڥ!v"!çREAD ERRORçNO FILE^:۷ ! ~ 3#0 Wx x ր ւ G ~ # 3x~#B!Y~ɯ2:۷=!۾ý:۷=!۾:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ ٯw4!Y~ʆ͌†t=ʆf ^ T ٯ2o&)|+!<ͧÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Yڸpsp2mÆÆf ͧÆFILE EXISTS _: É: :۷ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~2ۯ2\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: !۶ Â$$$ SUBgܙܥܫܱ"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͌x2͢*C ~<wʃG:!ʎì 4~ʶ¬:<ʶ$ʶïZͻx>2>2ͻ:!Z2:E߷ẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C ::ddslO s#r:E߷͊:==»y==»*Ww#*"͸*:G#š"͸:!w4!iw:Z!E~=262*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>2a×âÐÙëül.oÀgÅÛtU G+ G+ Ď((T ^hp!p:!x:!:!x:????!p:??!x:!:'_^#V([!{<2~(y*|>>/s1H*|<(2\!w͙h(p(y>> >/͏(y>>1͝2.|'^#VS*3!1NFx(BoNF Cg7?KnfB8C[tMD̀ͅ >2!"2*5":O*3!vy2l!=8"j~(##^#V( (!Sw CCnz( Ni`Chɯ2>2;͵:ɯ22y2ͩ͝͵;͵: >2:̝::z2m:[hg:}2q:[hg:{2p:!h_>p!a"r:[hgSt:~[q2v:l![n*y:p!j:q!jͩ*t[y͝![vF:–ͩͩ͝ :2!j[*::~!p#=[!>w( KQ (͚( K| (ͥ:'''!!Kxy:K!!:˗!X[~ ~w(:!w(x(~9:KY(<>0Ͱ> :G!a::G!a:( ((:<22Cɯ2*j~*~!H[l~2y< P# kz͜:yw*j~@(8#~2y>=9!y:y_>=?͘:!yI :y! g( !so(!%_( W(s#rI:y_ ag( o(ys#r:y!:g( !o(!R_(  W(*js#r!:yw:y͵> =G͵x> _  w !a> k_ (!a> _ !> _ > _:yg(! O ! O(! _z((!:lA%͐(> >2~#$% O͙!H6#!X[lw*j##^#V*j^#V>= ɧ:=#={z͑{M Warm Boot Error - Reset System$ Bios Err on $: Drive Not Ready$: Write Protected Disk$ 3w+ Ô2"{3q3(:> :<.33PX 2|2>:f3)0R3>::cR{?@/ _ `     "?/c4> \^4U :U H0ʄ4H=;: y4ɯ;:͞:!*#@*?!!44͍ 4:@¾C02@*?r:5H=͈:3 4*@*@*?"?"@"@ bkë4:?2@+5ů2@@ :@ʊ5-? M? @ ?  +,ĝ5) <ĝw+:> G6G5͌2 D6>R? ? @, `     \4>Ô5^4*%@>2@3H0ʱ6 ʶ1;ʫ1'ʡ6"ʡ6>1Ç6G͕0 ʶ1ʛ6â6"%@;:͞:!*#@* @*?!!64>2@" @͍ 7:@6x 7* @##~#7+4r:47H=r:1:3 7* @1>2>2!>~ '#F ###^#V!~!~p= !1 !; !`|G^>>>:??C!  00G>0O Super Bios v. 2.3 K CP/M 2.2 installed $D`DÇ6U ĝ*@18:@<2@= 2=xx2=*=T9"=:=2=@ !!@Ns#Frͦ9ͯ9q#p*@^#V+*@##^#V+*!@}9ͯ9"!@9*@ "@*)@͍ I;*?%:?͍ I;*@T9ͦ9*%@{_{:s#r#>w#wͯ9%:s#r*:"#@*#@ͦ9s#r{_*%@{̺9*@w{W:a:"%@{_ͯ9zʺ9*@}‚:}o~r:{ʗ:a:{_ͯ9{ȯw#w*@s#r͔9*#@ͦ9q#p*%@{:*@"%@~{_ͦ9{_{:a:*@*?:?;*)@%T9o zo W{_*@*@T9BK*s#r͔9*#@ͦ9q#p*%@{w# øa*$wxw# Ó'~#fo&'q#p:B(* ͅ ~'M(:J2A(*;" 2 U6+:A(wAMz(2A(7(:B((*;" :A(2B(*;r#s+:A(i(*;͢(" 2A(2B(!* p# P(!HN#*~# ^(Ar#s *){ʅ({ƀ_҅(zʞ()Å(ͣ) *)!.*ʹ)!.*V#^(((!((ʹ)(z(!.*ʹ)(ͣ)z{7.RY INDICATOR LD (RTRY),A RETRY: LD A,(IY) ;IY POINTS TO SECTOR UNDER VERIFICATION OUT (SECT),A ;LOAD SECTOR REGISTER LD A,(SIDE) OR A JR Z,SIDE0 ;LOAD WITH CONTROL CODE FOR SIDE ZERO LD A,SECTRD1 ;LOAD WITH CONTROL CODE FOR SIDE ONE JR STARTRD SIDE0: LD A,SECTRD0 STARTRD: DI ;NO OUTSIDE BOTHERING OUT (CMD),A ;REQUEST READ SECTOR NEXTBYTE: IN A,(WAIT) ;WAIT FOR OPERATTION COMPLETE AND 080H JR Z,DONESECT ;DONE WITH THIS SECTOR ; IN A,(DAL) ;INPUT DATA BYTE JR NEXTBYTE ;GET NEXT BYTE ; DONESECT: EI ;CAN NOW BE BOTHERED AGAIN IN A,(CMD) ;GET STATUS LD (STATUS),A ;SAVE AWAY OR A ;ERROR? JR NZ,FAILED ;PROCESS ERROR CASE LD A,(READSECS) DEC A ;SECTOR COUNTER JR Z,DONETRK LD (READSECS),A INC IY ;POINT TO NEXT SECTOR ID JR NEXTSECTOR ;VERIFY NEXT SECTOR ; DONETRK: LD A,(RTRY) ;SEE IF ANY RETRIES PERFORMED OR A RET Z ;RETURN OF NORMAL CASE CALL RESUMESCREEN RET ;RETURN ; ;PROCESS ERROR ACCORDINGLY ; FAILED: LD A,(RTRY) ;INCREMENT RETRY INC A LD (RTRY),A CP 10 JR C,RETRY ; ;10 RETRIES FAILED, REPORT FATAL ERROR ; PUSH DE ;SAVE IT LD DE,MSG19 CALL PRNT LD A,(STATUS) CAL DETERMERR ;PRINT APPROPRIATE ERROR USERINTERFACE: LD DE,MSG155 CALL PRNT LD A,(SIDE) CALL OUT LD DE,MSG16 CALL PRNT POP DE LD A,D ;TRACK PUSH DE CALL HEXOUT ;PRINT TRACK NUMBER LD DE,MSG17 CALL PRNT LD A,(IY) ;SECTOR CALL HEXOUT ;PRINT SECTOR NUMBER LD DE,MSG18 CALL PRNT LD A,(STATUS) ;GET STATUS CALL HEXOUT ;PRINT STATUS ; ;ASK USER FOR HELP TO DECIDE WHAT TO DO NEXT ; ERRIN: LD DE,MSG20 CALL PRNT CALL CHARIN OR A JP Z,ABORT ;EXIT OPTION CP 'S' ;SKIP? JP Z,SKIP CP 'R' ;RETRY? JR NZ,ERRIN ;RETRY WRITE AND THEN READ VERIFY AGAIN POP DE CALL RESUMESCREEN ;RESTORE SCREEN XOR A LD (SIDE),A ;SET SIDE TO ZERO CALL SELSIDE ;SELECT SIDE,DENSTY LD IY,(IYSAVE) ;RESTORE IY JP WRITE ;WRITE THIS TRACK OVER ;SKIP TO NEXT TRACK SKIP: POP DE CALL RESUMESCREEN XOR A LD (SIDE),A ;RESET SIDE TO ZERO CALL SELSIDE ;AND SELECT IT JP SKIPTONEXT ; ; SELSIDE: LD A,(SIDE) ;GET SIDE NUMBER RLC A RLC A LD B,A LD A,(DRIVENO) OR B IF MINI OR 08 ;SELECT DOUBLE DENSITY ; ELSE LD B,A LD A,D OR A JR Z,TRK0 LD A,(DENS) CP DD JR NZ,NODD LD A,08 ;SELECT DOUBLE DENSITY JR SESIDE NODD: TRK0 XOR A ;SELECT SINGLE DENSITY SESIDE: ADD A,B ENDIF OUT (WAIT),A ;TELL FDC RET ; ;DISK WRITE ERROR ; ERRMSG: DB CR,LF,'WRITE ERROR: $' ; WRERROR: LD (IYSAVE),IY PUSH DE PUSH AF LD DE,ERRMSG CALL PRNT POP AF CALL DETERMERR JP USERINTERFACE ; DETERMERR: PUSH DE L B,A AND 80H JR Z,D1 LD DE,MSG25 CALL PRNT ;DRIVE NOT READY JR EXITD D1: LD A,B AND 40H JR Z,D2 LD DE,MSG26 CALL PRNT ;WRITE PROTECT JR EXITD D2: LD A,B AND 20H JR Z,D3 LD DE,MSG27 CALL PRNT ;WRITE FAULT JR EXITD D3: LD A,B AND 10H JR Z,D4 LD DE,MSG28 CALL PRNT ;RECORD NOT FOUND JR EXITD D4: LD A,B AND 8 JR Z,D5 LD DE,MSG29 CALL PRNT ;CRC ERROR JR EXITD D5: LD A,B AND 4 JR Z,D6 LD DE,MSG30 CALL PRNT JR EXITD D6: LD A,B AND 2 JR Z,D7 LD DE,MSG31 ;DATA REQUEST CALL PRNT D7: EXITD: POP DE RET ; HEXOUT: PUSH AF SRL A SRL A SRL A SRL A CALL OUT POP AF OUT: AND 0FH ADD A,90H DAA ADC A,40H DAA CALL CHAROUT RET ; SPFLAG: DB 0 READSECS: DB 0 RTRY: DB 0 IYSAVE: DW 0 IXSAVE: DW 0 IXTRK1ON: DW 0 IYTRK1ON: DW 0 IX0SAVE: DW 0 IY0SAVE: DW 0 MAXTRKS: DB 0 MAXSECS: DB 0 STATUS: DB 0 SYSFLAG: DB 0 SIDE: DB 0 SIDED: DB 0 DENS: DB 0 DENDNE: DB 0 DENSCODE: DB 0E5H DRIVENO: DB 0 ; ; ; ;MESSAGES MSG: DB CR,LF,'FORMATTING',CR,LF,'$' MSG1: DB CR,LF,LF,' SBC Z80 SUPER QUAD DOUBLE' IF NOT MINI DB ' / SINGLE' ENDIF DB CR,LF,' DENSITY FORMAT PROGRAM vs 3.0' IF MINI DB CR,LF,' FOR ' IF FORTY8 DB '48' ELSE DB '96' ENDIF DB 'TPI MINI FLOPPY DISK DRIVES' ENDIF DB '$' MSG4: DB CR,LF,LF,'Enter Disk Drive To Be Formatted (0,1,2,3) ? $' MSG5: DB CR,LF,'Enter Density, Single or Double (S,D) ? $' MSG6: DB CR,LF,'Format Single or Double Sided (S,D) ? $' MSG7: DB CR,LF,'Format System Tracks only ? (Y,N) ? $' MSG77: DB CR,LF,'Supress Format Verification ? (Y,N) ? $' MSG8: DB CR,LF,'Insert Diskett Into Drive $' MSG9: DB ' And Press The Return Key $' MSG10: DB CR,LF,'Formatting Complete$' MSG11: DB CR,LF,'Option (CR to Exit, C to Continue) ? $' MSG12: DB CR,LF,'Option (CR for Same Parameters, N for New Parameters) ? $' MSG13: DB CR,LF,LF,' FORMATTING & VERIFYING$' MSG14: DB CR,LF, ' TRACK',LF,'$' MSG147: DB CR, ' $' MSG148: DB CR,LF,LF,' FORMATTING TRACK',LF,'$' MSG155: DB CR,LF,'SIDE= $' MSG16: DB ', TRACK= $' MSG17: DB ', SECTOR= $' MSG18: DB ', STATUS= $' MSG19: DB CR,LF,LF,'FATAL READ VERIFY ERROR DETECTED: $' MSG20: DB CR,LF,LF,'OPTION (CR to Exit, S to Skip, R to Retry) ? $' ; MSG25: DB 'DRIVE NOT READY$' MSG26: DB 'DISK IS WRITE PROTECTED$' MSG27: DB 'WRITE FAULT$' MSG28: DB 'RECORD NOT FOUND$' MSG29: DB 'CRC ERROR$' MSG30: DB 'LOST DATA$' MSG31: DB 'DATA REQUEST$' ABTMSG: DB CR,LF,'FORMATTING ABORTED$' ; ;CONTROL STRUCTURES SECTION ; ;MINI FLOPPY WRITE SECTOR SEQUENCE CONTROL MINISEQ0: DB 1,2,3,4 MINISEQ: DB 1,3,2,4 ;FOR WRITE DB 1,2,3,4 ; ;8 INCH FLOPPY WRITE SECTOR SEQUENCE CONTROL ;(SINGLE DENSITY) SDSEQ: DB 1,2,3,4,5,6,7,8,9,10,11,12,13 DB 14,15,16,17,18,19,20,21,22,23,24,25,26 ;FOR READ DB 1,3,5,7,9,11,13,15,17,19,21,23,25,2,4,6 DB 8,10,12,14,16,18,20,22,24,26 ; (DOUBLE DENSITY) DDSEQ: DB 1,4,7,2,5,8,3,6 ;FOR WRITE DB 1,7,5,3,4,2,8,6 ;FOR READ ; ;SINGLE DENSITY DISKETT FORMATTING CONTROL SDCONTROL: DB 40,0FFH ;PRE INDEX DB 6,00 DB 1,0FCH ;INDEX MARK DB 26,0FFH ;GAP1 POST INDEX DB RPT ;PROGRAM DESIGNED BEGINNING OF ;A REPEAT FUNCTION DB 6,00 ;SECTOR START ZEROS DB 1,0FEH ;ID ADDRESS MARK ;MISSING THREE BYTES ARE FILLED AT RUN TIME DB 1,00 ;SECTOR LENGTH DB 1,0F7H ;CRC'S DB 11,0FFH ;POST CRC DB 6,00 ;POST CRC DB 1,0FBH ;DATA ADDRESS MARK DB 128,0E5H ;DATA FIELD DB 1,0F7H ;CRC'S DB 27,0FFH ;POST CRC DB ENDRPT ;END OF REPEAT FUNCTION DB 200,0FFH ;END OF TRACK GAP4 DB 200,0FFH ; DB 200,0FFH ; DB 168,0FFH ; DB ENDTRK ; ; ;DOUBLE DENSITY DISKETT FORMATTING CONTROL ; ; ***** MOST OF THE COMMENTS USED ABOVE APPLY HERE AS WELL ***** ; DDCONTROL: DB 80,04EH DB 12,00 DB 3,0F6H DB 1,0FCH DB 50,04EH DB RPT DB 12,00 DB 3,0F5H DB 1,0FEH ; MISSING BYTES ARE FILLED AT RUN TIME DB 1,03 DB 1,0F7H DB 22,04EH DB 12,00 DB 3,0F5H DB 1,0FBH DB 128,0E5H DB 128,0E5H DB 0,0E5H ;0 COUNT = 256 DB 0,0E5H DB 0,0E5H DB 1,0F7H DB 66,04EH DB ENDRPT DB 200,04EH DB 200,04EH DB ENDTRK ; IBUFF: DS 80 ; BUFFER: DB 0 END START  .z80 ; ; ;COLD BOOT LOADER FOR CP/M 2.2 ; FOR THE Z80 SBC ;LAST UPDATE 5/15/82 ; false equ 0 ;logical equates true equ not false MINI EQU false ;set to true for mini trk0dd equ true ;true = track 00 double density dsd equ true ;true = double sided for double density use ; RTYN EQU 10 ; disk io retries SEEKRT EQU 1 ; rate 0=3ms, 1=6ms, 2=10ms, 3=20ms CDISK EQU 4 ; last disk selected by the ccp BELL EQU 07 ; ding MAXDSK EQU 1 ; largest disk number MONIT EQU 0F033H ; monitor boot error entry point LOADER EQU 100H CMDSTATUS EQU 100H-4 SECTORS EQU 100H-2 ; CMD EQU 0CH ; fdc command & fdc status register TK EQU CMD+1 ; fdc track register SECMD EQU CMD+2 ; fdc sector register DAL EQU CMD+3 ; fdc data port WAIT EQU 014H ; hardware wait for fdc intrq + drq ; & drive select - restore latch ; ; BUFF EQU 80H ; default dma buffer ; ; BOOT: LD A,01101111B ;enable memory, turn prom and power on jump off OUT (16H),A LD A,(NSECTS) ;get sectors to load LD D,A LD HL,80H ;start loading at 80h LD E,1 ;start with sector 1 RBLK1: LD BC,DAL ; no status checks and data port into C LD A,E ; get sector OUT (SECMD),A ; set sector LD A,088H ; get operation OUT (CMD),A NOP READLOOP: IN A,(WAIT) ; wait for drq or intrq OR A ; was it intrq ? JP P,IODONE ; if so leave INI ; otherwise get data JR READLOOP ; and go do more IODONE: IN A,(CMD) ;get status LD C,A LD (CMDSTATUS),BC ;and save it AND 9CH ;any errors JR NZ,BOOTERROR ;leave if so DEC D ; one less block to get JP Z,LOADER ; if zero must be done INC E ; otherwise increment sector LD A,26+1 CP E ;past end of track JR NZ,RBLK1 ;if not go read more BOOTERROR: PUSH AF ;Save errors for monitor reporting LD (SECTORS),DE ;save error sector LD A,01001111B ;turn prom on OUT (16H),A JP MONIT ;and go back to monitor ORG 07EH NSECTS: IF trk0dd DB 4 ;if track o double density get 4 1024b sectors ELSE DB 24 ; else get 24 ENDIF dens: if trk0dd if dsd db 0e7h ;double density double sided flag else db 0e6h ;double density single sided flag endif else DB 0E5H ;density flag patched by sysgen endif END  otherwise get data JR READLOOP ; and go do more IODONE: IN A,(CMD) ;get status LD C,A LD (CMDSTATUS),BC ;and save it AND 9CH ;any errors JR NZ,BOOTERROR ;leave if so DEC D ; one less block to get JP Z,LOADER ; if zero must be done INC E ; otherwise increment sector LD A,26+1 CP E ;past end of track JR NZ,RBLK1 ;if not go read more BOOTERROR: PUSH AF ;Save errors for monitor reporting LD (SECTORS),DE ;save error sector LD A,01001111B ;turn prom on OUT (16H),A JP MONIT ;and go back to monitor ORG 07EH NSECTS: IF trk0dd DB 4 ;if track o double densit; ; Program to investigate CP/M directory structures on the disk ; ; Warning! assumes first sector number is 0!!!! ; Will only work for drives with capacity of 64K sectors or less ; (=8 megabytes) bdossecs equ 44 ;sectors to read on warm boot .z80 buffer equ 2000h monit equ 0f033h ;return to monitor for error memory equ 16h ;to enable monitor PROM false equ 0 true equ not false devlp equ false ;true for devlopment loader to ask what to load nmbch equ 2 ;number of choices to choose from nmbcpm equ 1 ;number of cp/m choices turbo equ false ;true if for turbodos loader ; loader bios access bios equ 500h conin equ bios+09h conout equ bios+0ch seldsk equ bios+1bh settrk equ bios+1eh setsec equ bios+21h setdma equ bios+24h read equ bios+27h sectran equ bios+30h page start: ld SP,100h ;use default buffer for stack if devlp ques: ld HL,signon ;send which boot mess. call pstrng xor a call conin ;get response push psw ;save input ld C,A ;display it call conout pop psw ;get input back sub '0' ;make number cp nmbch ;make sure valid jr nc,ques ;if not ask again ld (typeld),A ;save type of load ld HL,cpmf ;get address of start of file names ld DE,namlng ;get length of name entry floop: dec a ;add in length jp m,fdone ;skip out if no more to add in add HL,DE ;else add in lingth of entry jr floop ; and go back for more else if turbo ld HL,turbof ;load turbodos loader file name adderss ld A,1 ;force load type ld (typeld),A else ld HL,cpmf ;load cp/m file name xor A ;force load type ld (typeld),A endif endif fdone: ;HL points to beg. of name to load ld DE,filefcb+1 ;destination to move to ld BC,8 ;amount to move ldir ;now move file to load ld C,0 ld E,0 ;make seldsk know this is the first call call seldsk ld A,H or L ld DE,badsel jp z,error ;bad select-HL=0000 ;HL=DPH address ld C,(HL) ;XLT table, low order byte inc HL ld B,(HL) ld A,B or C ;A=0 if no sector translation ld (trans),A ld (XLT),BC ld DE,7 add HL,DE ;(HL)=DIRBUF address - might as well use it ;for our workspace ld C,(HL) inc HL ld B,(HL) ld (dirbuf),BC push HL call setdma ;use the dirbuf for operations pop HL inc HL ;(HL)=DPB address ld E,(HL) inc HL ld D,(HL) page ex DE,HL ;HL=DPB address ld E,(HL) inc HL ld D,(HL) ;(HL)=sectors per track ld (SPT),DE ;highest sector number before next track inc HL ld A,(HL) ;Block shift factor ld (BSH),A inc HL ld A,(HL) ld (BLM),A ;block mask inc A ld (blksec),A ;sectors per block inc HL inc HL inc HL ld A,(HL) ;A=msb of DSM or total block count of drive ld (blkmsb),A inc HL ld E,(HL) inc HL ld D,(HL) inc DE ;make = max dirs. not -1 ld (maxdir),DE ld DE,5 add HL,DE ;(HL)=track offset ld C,(HL) inc HL ld B,(HL) ld (trkoff),BC ld (curtrk),BC call settrk ;directory starts at first non-system track page  ; Current status of program: ; The disk on which the system file resides has been selected ; and the head has been stepped to the first directory track ; Note that the directory will always start at sector 1 of ; the first non-system track, and will occupy consecutive ; sectors through the end of the directory. The total number ; of sectors occupied is (maxdir)/4, but they may be on more ; than one track. ; nextsec: ;read next directory sector into the DIRBUF ld HL,(SPT) ld BC,(cursec) sbc HL,BC jr nc,trksame ;haven't gone to next track yet ld BC,(curtrk) inc BC ld (curtrk),BC call settrk ;step disk ld BC,0 ;first sector, new track trksame: push BC ;logical sector ld A,(trans) or A jr z,notran ;do we need to do sector translation? ld DE,(XLT) ;translate table call sectran push HL pop BC notran: call setsec call read or A ld DE,permerr jp nz,error ;physical error pop HL ;sector just read inc HL ld (cursec),HL ; ; The next sector of the directory (4 entries) is now in the DIRBUF ; Now see if we can find the file ; ld HL,(dirbuf) ld DE,32d ld B,4 nextdir: push HL push DE push BC call match ;match directory entry with FCB pop BC pop DE pop HL jr z,found ;file found add HL,DE djnz nextdir ; ; we've search this sector-no match. Was it the last? ; ld HL,(absec) inc HL ld (absec),HL dec HL ;HL=sectors read so far add HL,HL add HL,HL ;sectors x 4 = directory entries ld DE,(maxdir) sbc HL,DE ld DE,nofile jp z,error jr nextsec page ; ; Match: match takes as a parameter HL pointing to a directory ; entry. Match returns the zero flag set if the file matches. ; match: ex DE,HL ;use DE to point to directory ld HL,Filefcb ;first character in filename to search ld BC,0c0dh ;11 characters to match nextch: ld A,(DE) ;next character in directory entry inc DE and 7fh ;mask file attribute bits cpi ret nz ;no match, return djnz nextch ret page ; ; Now we have the correct directory entry, with HL pointing to ; the the start of the FCB ; Next we expand the block allocation data into a table of items: ; ; dw track, dw first sector, dw last sector found: ld DE,15d add HL,DE ;(HL)=records in this extent ld DE,filefcb+15d ;DE=block allocation area in filefcb ld BC,17d ldir ;move to file fcb ld IY,filefcb+16 ;pointer to next block ld IX,boottbl ;pointer to current table entry call getblk ;returns block # in DE newtbl: push DE call mktrk ;returns track in BC, 1st sector in HL ld (IX),C ld (IX+1),B ;store track ld (IX+2),L ;first sector ld (IX+3),H dec HL ;set up for add mrebks1: ld DE,(blksec) add HL,DE ;HL=last sector of block ld DE,(spt) dec DE ;sectors numbered 0-(spt-1) sbc HL,DE jr c,skp jr nz,newtrk ;block overflows to next track skp: add HL,DE ;add sectors per track back in ld (IX+4),L ;save last sector ld (IX+5),H nxtblk: call getblk ;get next block # pop HL ;last block scf ccf sbc HL,DE inc HL ;HL=0 if new block adjacent to last ld A,H or L jr z,moreblks ld BC,6 add IX,BC ;set pointer to next track item jr newtbl newtrk: ld (IX+4),E ;spt-1 last sector on track ld (IX+5),D ld BC,6 add IX,BC ;pointer to next track dec HL ld (IX+4),L ;last sector of this block ld (IX+5),H xor A ld (IX+3),A ;start sector zero ld (IX+2),A ld C,(IX-6) ld B,(IX-5) ;last track inc BC ld (IX),C ld (IX+1),B jr nxtblk page moreblks: push DE ;save new block # ld L,(IX+4) ;last sector so far ld H,(IX+5) jr mrebks1 ;go do rest of overflow check ; getblk returns the block # (IY) in DE and moves IY to the next ; also, exits loop if block # = 0 getblk: ld E,(IY) ld A,(blkmsb) or A jr z,onebyte inc IY ld A,(IY) onebyte: ld D,A inc IY or E ;block # = 0? ret nz pop DE ;lose return in loop jr tbldone ; mktrk gets block # in DE, returns track in BC, 1st sector in HL mktrk: ex DE,HL ld A,(bsh) ld B,A shftblk: add HL,HL djnz shftblk ;HL=absolute sector number ld DE,(spt) scf ccf ld BC,(trkoff) dec BC mortrk: sbc HL,DE inc BC jr nc,mortrk add HL,DE ;restore sector relative in track ret page ; ; table now contains the track/sector map for all the blocks in ; the directory. Now read the table into memory. ; tbldone: ld HL,buffer ;start of CCP-starting DMA ld IY,boottbl-6 ;point to boot table nxttrk: push HL ;current DMA ;read sectors of next track ld DE,6 ;update track pointer add IY,DE ld C,(IY) ld B,(IY+1) ;BC=track ld A,B or C jr z,bootdone ;last track done call settrk ld C,(IY+2) ;get next sector to read ld B,(IY+3) dec BC ;pre decrement it ld (nextsc),BC ;save it nxtsec: pop BC ;DMA push BC call setdma scf ;clear carry flag ccf ld BC,(nextsc) ;get next sector to read inc BC ;update it ld L,(IY+4) ;get last sector ld H,(IY+5) sbc HL,BC ;any more on this track pop HL ;fix stack jr c,nxttrk ;done with last sector ld (nextsc),BC ;save next sector ld DE,128 add HL,DE ;update DMA push HL ld DE,(xlt) call sectran ld C,L ld B,H call setsec call read or A ld DE,permerr jr nz,error ;physical read error jr nxtsec page ; ; the .SYS file is now in memory starting at (buffer) ; bootdone: ld A,(typeld) ;load of cp/m or something else cp nmbcpm jp nc,trboot ;if not cp/m leave ; ; we must go through it and remove all the BIOS sectors ; to make it a table of CCP and BDOS sectors only for wboot ; ld IX,boottbl-6 ld HL,0 ;count of sectors in table so far nxtitem: push HL ;save count of sectors so far ld DE,6 add IX,DE ld C,(IX+2) ;get first sector this track ld B,(IX+3) ld L,(IX+4) ;get last sector this track ld H,(IX+5) sbc HL,BC inc HL ;sectors in this track pop DE add HL,DE ;total sectors so far ld A,bdossecs ;number of sectors for wboot cp L jr z,movtbl ;this track ends exactly at the BIOS jr nc,nxtitem ;keep reading table ;this is the item we must cut down ;B=first sector, C=last sector, E=C-B+1 ;A=bdossecs, L=sectors through end of track ld D,A ld A,L sub D ;A=sectors to remove ld E,A ld D,0 ld L,(IX+4) ld H,(IX+5) sbc HL,DE ld (IX+4),L ;must contain at least one sector in track ld (IX+5),H page ; ; table has now been modified for CP/M wboot use ; IX+5 is end of last table entry movtbl: push IX pop HL ld DE,boottbl-6 sbc HL,DE ;HL=length to move ld B,H ld C,L ld HL,boottbl ld DE,buffer+1637h ;boottbl in buffer-after jump table ldir ;move table ;boottbl filled in, now move image to execution ;area ld HL,buffer ld DE,(buffer+1633h) ;ccp start ld C,0 ld A,(filefcb+15) ;128 byte records allocated rrca rr C ;carry=> odd number of records and 7fh ld B,A ldir ;transfer jp buffer+1600h ;coldboot jump page ; ; turbodos loader stuff ; trboot: ld HL,80h ;first need to clear default buffer ld DE,81h xor A ld (HL),A ld BC,30h ldir ; jp buffer ;now go to loader page ;-------------------------------------------- ; ; error message routine ; error: ex DE,HL ;put message address in HL call pstrng ;send message ld HL,errmsg ;send error message call pstrng ld B,11d ;send file name ld HL,filefcb call pstr2 ld A,4fh ;turn prom back on out (memory),A jp monit ;go back to monitor pstrng: ld B,(HL) pstr2: inc HL ;HL=first character, B=count push HL ld C,(HL) push BC xor A call conout pop BC pop HL djnz pstr2 ret ; ;storage ; filefcb: db 0 ;user number db ' ' ;file name filled in at beg. of code db 'SYS' ;extension ds 20 ;dummy rest of dir entry BSH: ds 1 ;block shift factor = log2(records/block) BLM: ds 1 ;block mask = records/block-1 blkmsb: ds 1 ;non-zero is >255 blocks on drive ;=msb of DSM in DPB blksec: ds 2 ;sectors per block (BLM+1) dirbuf: ds 2 ;address of DIRBUF trans: ds 1 ;0 if no sector translation XLT: ds 2 ;translate table address SPT: ds 2 ;sector per track count maxdir: ds 2 ;number of directory entries on disk trkoff: ds 2 ;track offset curtrk: ds 2 ;current track cursec: ds 2 absec: ds 2 ;absolute sector typeld: ds 1 ;load type 0=cp/m, 1=turbodos nextsc: ds 2 ;temp storage for next sector to read ; ;messages ; signon: db badsel-$ db 0dh,0ah,'Which .SYS file to load',0dh,0ah db '0 = ' cpmf: db 'CPM ',0DH,0AH db '1 = ' turbof: db 'OSLOAD ',0DH,0AH db '? ' namlng equ turbof-cpmf ;length of name entry in above table badsel: db 6,'Select' permerr: db 4,'Read' nofile: db 14,'File not found' errmsg: db 14,' error: file ' boottbl: ds 60 end !9"1s MODEM TRANSFER PROGRAM as of 05/14/82 FOR SUPER QUAD Z80 SBC by ADVANCED MICRO DIGITAL $ >2/2:X˜>2c:G cMʉ>2:ETTS}RD c::] >2/2A!">2h`sG:>2x^c VS^:`:/2`>2`[:ʙw#" Ž>:[:=̠>22 !:w#[:w#[>  x6#}l&)>o55+|!͏!\ i!3͏!l͏ͥ:, ʘ0 ++FILE DOES NOT EXIST++ 0TYPE "R" TO RETURN TO MODEM TYPE "A" TO RE-ENTER NAME: s}[NAcRʊØ;f0 ++FILE TRANSFER COMPLETED++ Ê0 ++FILE TRANSFER UNSUCCESSFUL++ Ê0 ++ TRANSFER CANCELLED ++ 6# 6 #”6#0 ENTER FILE NAME TO BE TRANSFERRED - C/R TO QUIT: *͜N*!333!~"hs##[shTsc[T[T:£>2:(Sͯҫ>B2>a=:] 4͐ͥP͐#2͎ : ö>a =2:>2l>B2=:] 4) ͩ Q:N:N0FILE OPEN, READY TO RECEIVE :>Y>Ca:y0CRC in effect Ñ0Checksum in effect ͒ ڣ͈͡ Ñ͹͈ =:0AWAITING NAME NAK P͸>a!5*\ i">a7 !]~a:~[8#>a:NQe>ua:X0CHECKSUM ERROR P͸>a>a!\͑:ʑ0AWAITING FILE NAME Aڑͣʡ7!]:0TIME OUT RECEIVING FILENAME ?w:~[>a#}é:Nya?!\͑:60CHECKSUM ERROR A6ä>a͋7>2(2ͮ!F^" !\7ͻ ڕ:fp*\ i"!4p!5d!F^":A>@2!6!+N!, 6 !+F# ~ # ~ "+# ~ :<2# ~ 12 SBC Z80 SUPER QUAD DOUBLE / SINGLE $ d DENSITY FORMAT PROGRAM vs 2.0$= >2à Enter Density, Single or Double (S,D) :$t D´ûS¹>N2 Enter Disk Drive to be Formatted (A,B,C,D) :$ >2AڹҹO2< Format System Tracks only ? (Y,N) :$ NUY22:²>2Ó Format Single or Double Sided (S,D) :$h SʲDU>2>2 Insert diskette into drive $ :A_: and press the Return key $   $ :> W2!>(6#>6#r#:w#s#6#6#> 6#>{=•:•+:w#6#>{S> ¨!!>  :z:l> :Gzl72:>2:G:!"!P>N:5zB;zB{ N*^{#"ʡ>6#r#:w#s#6#6#>N >6#>6#>NP%>N £!!>  ::=>22zMl> :lw# < Disk Formatting Error Disk drive Status : $  `RƐ'@'_IʋÀ Drive not ready$n l@lî Disk is write protected$ l:2 >P:AڹҹO2< Format System Tracks only ? (Y,N) :$ NUY22:²>2Ó Format Single or Double Sided (S,D) :$h SʲDU>2>2 Insert diskette into drive $ :A_: and press the Return key $   $ :> W2!>(6#>6#r#:w#s#6#6#> 6#>{=•:•+:w#6#>{S> ¨!!>  :z:l> :Gzl72:>2:G:!"!P>N:5zB;zB{ N*^{#"ʡ>6#r#:w#s#6#6#>N >6#>6#>NP%>N £!!>  ::=>22zMl> :lw# TITLE ADVANCED DIGITAL HDC1001 HARD DISK FORMATTER OCT 27 1982 09:30 ;********************************************************* ;** ** ;** ADVANCED DIGITAL HDC1001 HARD DISK CONTROLLER ** ;** ** ;** HARD DISK FORMATTER ** ;** ** ;** This program will format an HDC1001 device. ** ;** It requires a hardware discription vector ** ;** for the selected device. It formats the ** ;** drive in 512 byte sectors for ADVANCED ** ;** DIGITAL SUPER QUAD'S Super Bios. ** ;** ** ;** Written by ** ;** ** ;** Greg Lindberg ** ;** ** ;********************************************************* .z80 PAGE ;*** EQUATES *** ;SYSTEM EQUATES BDOS EQU 5 ;BDOS entry point TFCB EQU 5CH ;Temporary FCB CR EQU 0DH ;Carriage return LF EQU 0AH ;Line feed BS equ 08H ;Back space ; PRTSTR EQU 9 ; Print string CONIN EQU 1 ; Console input CONOUT EQU 2 ; Console output RDBUF EQU 10 ; Read console buffer CONST EQU 11 ; Console status ;Port offsets for the HDC1001 HDBASE EQU 0E0H ; HDC1001 BASE I/O PORT DATA EQU HDBASE+0 ; Data register ERROR EQU HDBASE+1 ; Error register SECNT EQU HDBASE+2 ; Sector count SECNO EQU HDBASE+3 ; Sector number CYLLO EQU HDBASE+4 ; Cylinder low CYLHI EQU HDBASE+5 ; Cylinder high SDH EQU HDBASE+6 ; Size/Drive/Head COMND EQU HDBASE+7 ; Command register STATUS EQU COMND ; Status register ;Some HDC1001 commands CREAD EQU 20H ; Read sector CWRITE EQU 30H ; Write sector CFORM EQU 50H ; Format track PAGE ; ;*** Main program *** ; START: ld DE,signon ;send signon message ld C,prtstr call bdos strt1: ld DE,inbuf ;Get response to disk type ld C,rdbuf call bdos LD A,(NUMCHR) ;How many chars returned cp 0 jr z,bad ;no chars cp 3 ;to many chars jr C,good ;if not skip bad: ld DE,inval ld C,prtstr call bdos ld DE,menu ;ask again ld C,prtstr call bdos jr strt1 good: LD DE,INTTBL ;set up registers LD HL,0 DECLP: PUSH AF ;Save char count LD A,(DE) ;get char INC DE CP '0' JP C,BAD ;Char less than a '0' CP '9'+1 JP NC,BAD ;Char greater than a '9' SUB '0' ;make = 0-9 LD B,H ;mult present value * 10 LD C,L ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,BC ;*5 ADD HL,HL ;*10 ADD A,L ;add in new value LD L,A JP NZ,DIGNC INC H DIGNC: pop AF dec A ;done yet JP NZ,DECLP ;if not go back for more add HL,HL ;now make ref into table of drive parameters add HL,HL ;*4 ld DE,dskprms add HL,DE ld DE,secs ;now move parms to use locs ld BC,4 ldir drvin: ld DE,drvmsg ;get which physical drive to format ld C,prtstr call bdos ld C,conin ;get response call bdos sub '0' ;make = 0-3 cp 4 ;valid response jr c,goodr ;yes ld DE,inval ; otherwise bad response ld C,prtstr call bdos jr drvin ;try again goodr: ld (unit),A ;save drive ; ;Make sure the guy out there really wants to do this ; ld DE,q1 ; Ask if really want to do this ld C,prtstr call bdos LD A,(UNIT) CALL OUTCHR ld DE,q2 ld C,prtstr call bdos ld C,conin ; Get response call bdos CP CR ; Carriage return JP Z,DOIT ABORT: ld DE,abtmsg ld C,prtstr call bdos jp resel ;Calculate interleave table ;But first clear the table to all FF's DOIT: ld DE,formsg ; Say formatting ld C,prtstr call bdos LD B,64 ; Make table 64 long LD HL,INTTBL ; Index interleave table SETLP: LD (HL),-1 INC HL DEC B JP NZ,SETLP ;Generate 16 bit interleave LD HL,(INTERB) ; Get interleave byte LD H,0 ; and turn it into a word LD (INTER),HL ;Next, calculate interleave table upper limit LD A,(SECS) ; Get number of sectors LD B,A ; Save for later LD E,A ; Offset off base of int table LD D,0 LD HL,INTTBL ADD HL,DE LD A,L ; Negate (2s complement) CPL LD L,A LD A,H CPL LD H,A ; This is our upper limit INC HL LD (LIMIT),HL ;Now, negative sector count LD A,B ; Get sectors per track (SECS) CPL ; And twos complement LD L,A  LD H,-1 INC HL LD (NSECS),HL ;Calculate interleave table LD B,0 ; Clear sector number LD DE,INTTBL ; Index interleave table CHECK: LD HL,(LIMIT) ; Make sure limits not exceeded ADD HL,DE JP NC,WITHIN ; We are within limits LD HL,(NSECS) ; Otherwise subtract SECS ADD HL,DE XCHECK: EX DE,HL JP CHECK ; And check limits again WITHIN: LD A,(DE) ; This place taken? AND A JP M,GOTIT ; If not, we can use it INC DE ; Else, check next one JP CHECK GOTIT: LD A,B ; Store sector number LD (DE),A LD HL,(INTER) ; Increment pointer by ADD HL,DE ; interleave INC B ; Increment sector count LD A,(SECS) ; Have we done enough? CP B JP NZ,XCHECK ;Do a dummy read to insure that the head has beed restored LD A,CREAD OUT (COMND),A RSWAIT: IN A,(status) AND A JP M,RSWAIT ;Figure all the needed format paramters ; SDH mask LD A,20H ; Get 512 mask LD B,A ; Save for a moment jr noecc ;skip for now LD A,80H ; OR in ECC bit OR B LD B,A ; Save for a while NOECC: LD A,(UNIT) ; Get drive number RLCA ; Rotate drive into position RLCA RLCA OR B ; OR in sector size LD (UNIT),A ; Save size/drive mask ;Get cylinder and head and format LD HL,(CYLS) ; Get last cylinder push HL ; Save it HEADLP: call cylprt ;print new cylinder LD A,(HEADS) ; Get last head LD D,A FORLP: push DE push BC ld A,D ; Output head that we are on call outchr ld E,bs ld C,conout call bdos pop BC pop DE LD A,(SECS) ; Get sector count OUT (SECNT),A pop HL push HL LD A,L OUT (CYLLO),A ; Cylinder low LD A,H OUT (CYLHI),A ; Cylinder high LD A,(UNIT) ; Get size/drive mask OR D ; Or in heads OUT (SDH),A LD A,CFORM ; Issue format command OUT (COMND),A LD HL,INTTBL ; Index interleave table LD B,0 ; Get transfer size 0 = 256 ld A,DATA ld C,A XOR A ; Get bad block bits DATALP: OUT (C),A OUTI JR NZ,DATALP ; Continue till sector full FWAIT: IN A,(STATUS) ; Wait for format AND A  JP M,FWAIT RRA ; Any errors? JP C,HERROR ; If so, call it quits call xitck ; want to exit DEC D ; Bump head counter JP P,FORLP ; Have we passed head 0? pop HL DEC HL ld A,H ; Have we passed cyl 0? and A push HL JP P,HEADLP pop HL ; ;Now verify that all records that we formatted can be read. ; ld DE,vermsg ; Say verifying ld C,prtstr call bdos LD HL,(CYLS) ; Get last cylinder LD A,(HEADS) ; Get last head LD E,A LD A,(SECS) ; get last sector DEC A LD D,A RHEAD: call cylprt ;print new cylinder LD C,E ; Reload head RSECS: push HL push DE push BC ld A,C ; Output head that we are on call outchr ld E,bs ld C,conout call bdos pop BC pop DE pop HL LD B,D ; Reload sector READIT: ld A,B OUT (SECNO),A ; Get sector LD A,L OUT (CYLLO),A ; Get cylinder low LD A,H OUT (CYLHI),A ; Get cylinder high L A,(UNIT Ge Size/Drive OR C ; OR in head OUT (SDH),A LD A,CREAD ; Issue read command OUT (COMND),A  RWAIT: IN A,(STATUS) ; Wait for it to be read AND A JP M,RWAIT RRA ; Check for errors JP NC,NOERR ; Jump if no error, ; ;This routine gives the user a detailed error report ; push HL ; Save important registers push DE push BC ld DE,errst ; Send error message ld C,prtstr call bdos IN A,(ERROR) ;error CALL HEXOUT ld DE,errhd ;head ld C,prtstr call bdos IN A,(SDH) AND 7 CALL OUTCHR ; Print single digit ld DE,errcyl ld C,prtstr call bdos IN A,(CYLHI) ; Report CYLHI first CALL HEXOUT IN A,(CYLLO) ; then CYLLO CALL HEXOUT ld DE,errsec ld C,prtstr call bdos IN A,(SECNO) CALL HEXOUT ld DE,vermsg1 ld C,prtstr call bdos call cylprt pop BC ; Restore registers pop DE pop HL ;The read sector routine continues here NOERR: call xitck DEC B ; Bump sector number JP P,READIT DEC C ; Bump head number JP P,RSECS DEC HL ; Bump cylinder number LD A,H ; Make sure it's not minus AND A JP P,RHEAD ld DE,dnemsg ; Say done ld c,prtstr call bdos JP RESEL ; Reselect original drive ;This subroutine checks for premature exit request xitck: push HL ; save regs push DE push BC ld C,const ;get console status call bdos AND A jr z,skp ;skip if no char ld C,conin call bdos cp 3 ; is it a ^C jp z,ABORT ;if so restart sys skp: pop BC pop DE pop HL ret ;This subroutine prints the contents of A in hex HEXOUT: PUSH AF RRCA ; Get upper digit RRCA RRCA RRCA CALL OUTCHR ; Print upper digit POP AF OUTCHR: AND 0FH ; Mask four bits ADD A,90H DAA ADC A,40H DAA LD E,A ld C,conout ; Write it to console call bdos RET cylprt: push DE push BC push HL ; Save regs to print out cyl ld DE,bsmsg ;back up ld C,prtstr call bdos pop HL ;get cyl push HL ld A,H ;print high cyl call hexout pop HL push HL ld A,L ;print low cyl call hexout ld DE,HDmsg ;print head msg ld C,prtstr call bdos pop HL ;restore regs pop BC pop DE ret HERROR: ld DE,urcmsg ld C,prtstr call bdos ;Re-select formerly current drive RESEL: JP 0 ;WARM START ; ; Disk parameters ; dskprms: st503: db 16 ;sectors dw 152 ;cylinders-1 db 1 ;heads-1 st506: db 16 ;sectors dw 152 ;cylinders-1 db 3 ;heads-1 tm601s: db 16 ;sectors dw 152 ;cylinders-1 db 1 ;heads-1 tm602s: db 16 ;sectors dw 152 ;cylinders-1 db 3 ;heads-1 tm603s: db 16 ;sectors dw 152 ;cylinders-1 db 5 ;heads-1 tm603se: db 16 ;sectors dw 229 ;cylinders-1 db 5 ;heads-1 tm501: db 16 ;sectors dw 305 ;cylinders-1 db 1 ;heads-1 tm502: db 16 ;sectors dw 305 ;cylinders-1 db 3 ;heads-1 tm503: db 16 ;sectors dw 305 ;cylinders-1 db 5 ;heads-1 sa602: db 16 ;sectors dw 159 ;cylinders-1 db 1 ;heads-1 sa604: db 16 ;sectors dw 159 ;cylinders-1 db 3 ;heads-1 sa606: db 16 ;sectors dw 159 ;cylinders-1 db 5 ;heads-1 sa1002: db 16 ;sectors dw 255 ;cylinders-1 db 1 ;heads-1 sa1004: db 16 ;sectors dw 255 ;cylinders-1 db 3 ;heads-1 q2010: db 16 ;sectors dw 511 ;cylinders-1 db 1 ;heads-1 q2020: db 16 ;sectors dw 511 ;cylinders-1 db 3 ;heads-1 q2030: db 16 ;sectors dw 511 ;cylinders-1 db 5 ;heads-1 q2040: db 16 ;sectors dw 511 ;cylinders-1 db 7 ;heads-1 m2010: db 16 ;sectors dw 479 ;cylinders-1 db 1 ;heads-1 m2020: db 16 ;sectors dw 479 ;cylinders-1 db 3 ;heads-1 ; ; Messages ; signon: db 'ADVANCED DIGITAL CORPORATION',CR,LF db 'HDC1001 Hard Disk Controller Formatter',CR,LF,LF db 'Select disk type from following menu',CR,LF menu: db '*** Hard Disk selection choices ***',CR,LF db '0 = ST503 ; Seagate Technology ST503',CR,LF db '1 = ST506',CR,LF db '2 = TM601S ; Tandon Magnetics TM601S',CR,LF db '3 = TM602S',CR,LF db '4 = TM603S',CR,LF db '5 = TM603SE',CR,LF db '6 = TM501 ; Tandon Magnetics TM501',CR,LF db '7 = TM502',CR,LF db '8 = TM503',CR,LF db '9 = SA602 ; Shugart Associates SA602',CR,LF db '10 = SA604',CR,LF db '11 = SA606',CR,LF db '12 = SA1002 ; Shugart Associates SA1002',CR,LF db '13 = SA1004',CR,LF db '14 = Q2010 ; Quantum Q2010',CR,LF db '15 = Q2020',CR,LF db '16 = Q2030',CR,LF db '17 = Q2040',CR,LF db '18 = M4010 ; MiniScribe 4010',CR,LF db '19 = M4020',CR,LF db '? $' inval: db CR,LF,'Invalid input try again.',CR,LF,'$' drvmsg: db CR,LF,'Which physical hard disk do you want to format. (0-3)? $' q1: db CR,LF,'This operation will destroy all data on drive $' q2: db '.',CR,LF,'Hit return to continue or ^C to abort.$' formsg: db LF,'Formatting. CYLINDER ' HDMSG: DB ' HEAD $' BSMSG: db bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,'$' vermsg1: db LF vermsg: db CR,'Verifying. CYLINDER HEAD $' errst: db CR,LF,'HDC1001 Error $' errhd: db ' on Head $' errcyl: db ', Cylinder $' errsec: db ', Sector $' dnemsg: db CR,LF,'Format completed.$' urcmsg: db 'Sorry, unrecoverable error during format.$' abtmsg: db CR,LF,'Operation aborted.$' ; ;Variables ; UNIT: DS 1 ; Physical device unit INTERB: DB 8 ; Current interleave SECS: DS 1 ; Sectors per track CYLS: DS 2 ; Cylinders per drive HEADS: DS 1 ; Heads per drive INTER: DS 2 ; 16 bit interleave NSECS: DS 2 ; 16 bit negative SECS LIMIT: DS 2 ; Upper memory limit of table inbuf: db 64 ; Line input buffer numchr: ds 1 ; Number of characters returned INTTBL: DS 64 ; Interleave table END n to continue or ^C to abort.$' formsg: db LF,'Formatting. CYLINDER ' HDMSG: DB ' HEAD $' BSMSG: db bs,bs,bs,bs,bs,bs,bs,bs,bs,bs,'$' vermsg1: db LF vermsg: db CR,'Verifying. CYLINDER HEAD $' errst: db CR,LF,'HDC1001 Error $' errhd: db ' on Head $' errcyl: db ', Cylinder $' errsec: db ', Sector $' dnemsg: db CR,LF,'Format completed.$' urcmsg: db 'Sorry, unrecoverable error during format.$' abtmsg: db CR,LF,'Operation aborted.$' ; ;Variables ; UNIT: DS 1 ; Physical device unit  TITLE ADVANCED DIGITAL SUPERBIOS FOR SUPER QUAD Dec 18 1982 14:30 ;***************************************************************** ;** ** ;** ADVANCED DIGITAL SUPER QUAD Z80 SBC ** ;** ** ;** SUPER BIOS ** ;** ** ;** This bios contains drivers for: ** ;** ** ;** Floppy disk ** ;** Hard disk ** ;** Two serial ports ** ;** Parallel port ** ;** ** ;** Console input and output can be polled or ** ;** interrupt driven. Seperatly sellected. ** ;** ** ;** Warm boot can be from disk or from prom. ** ;** ** ;** ** ;** Written by: ** ;** ** ;** Scott Carter ** ;** Greg Lindberg ** ;** ** ;***************************************************************** SUBTTL Customization Equates page 60 .z80 true equ 0ffffh false equ 0 mini equ false ;true for minifloppy BIOS special equ false ;true for 8"-5" special board m48tpi equ true ;true for 48tpi mini drives m96tpi equ false ;true for 96tpi mini drives nmbfpy equ 4 ;number of floppy disk drives fpyfrst defl true ;true if floppies are first logical drives ;only valid if hard disk installed prmboot equ true ;true for warmboot from prom (use only with warm boot prom) intrin equ true ;true for interrupt console input (Type ahead) introut equ false ;true for interrupt console output (Buffered console output) parprnt equ true ;true for parallel printer, false for serial printer ;------------------------------------------------------------------------ ; This is the seek rate constant!! seekrt, below, is an offset! seekrate equ 0 ;6ms for 8", 12ms for 5" ;seek rate 0=3ms, 1=6ms, 2=10ms, 3=15ms ;these times double for minifloppies ;*** Hard Disk selection choices *** ST503 EQU 1 ; Seagate Technology ST503 ST506 EQU 2 TM601S EQU 3 ; Tandon Magnetics TM601S TM602S EQU 4 TM603S EQU 5 TM603SE EQU 6 TM501 EQU 7 ; Tandon Magnetics TM501 TM502 EQU 8 TM503 EQU 9 SA602 EQU 10 ; Shugart Associates SA602 SA604 EQU 11 SA606 EQU 12 SA1002 EQU 13 ; Shugart Associates SA1002 SA1004 EQU 14 Q2010 EQU 15 ; Quantum Q2010 Q2020 EQU 16 Q2030 EQU 17 Q2040 EQU 18 M4010 EQU 19 ; MiniScribe 4010 M4020 EQU 20 ;*** HDC1001 Physical drives *** hd0 equ M4020 ; Set to type of drive or false if not used hd1 equ false ; all drives must have same interface type hd2 equ false ; i.e. all SA1000 type or all ST506 type hd3 equ false SUBTTL SYMBOLIC EQUATES page if intrin or introut ints equ true else ints equ false endif ; board hardware equates cmd equ 0ch ;fdc command register trk equ cmd+1 ;track register sec equ cmd+2 ;sector register data equ cmd+3 ;data register wait equ 14h ;INTRQ and DRQ synch port (see manual) pioad equ 4 ;PIO channel A data pioac equ 6 ; " " " control piobd equ 5 ; " " B data piobc equ 7 ; " " " control memry equ 16h ;memory control port ; ; sector deblocking equates ; hstcnt equ 8 ;number of sectors in buffer hstshft equ 3 ;shift factor for # of sectors in buffer if mini ddpspt equ 4 ;double density physical sectors per track if m48tpi tracks equ 39 ;minifloppies else tracks equ 76 ;96tpi drives endif else ddpspt equ 8 ;eight inch tracks equ 76 endif dpblen equ 15 ;length of a DPB ; ; floppy disk hardware parameter offsets ; ****** these are offsets into table do not change ****** ; density equ 0 ;0=single, 1=single side double D, 2= 2S2D seekrt equ 1 ;THIS IS OFFSET INTO TABLE, VALUE IN TABLE CAN BE ;seek rate 0=3ms, 1=6ms, 2=10ms, 3=15ms ;these times double for minifloppies pspt equ 2 ;physical sectors per track (one side) drvtrk equ 3 ;track a floppy is at parmlen equ 4 ;length of the parameter block ; ; miscellaneous equates ; iobyte equ 3 ;used to select various consoles and printers cdisk equ 4 ;default disk user number bdos equ 5 retries equ 10 ;retry count for disk operations inbfsz equ 32 ;size of input buffer;--------------------------------------------------------------------------- ; ; SUPERBIOS implementation example - Memory disk ; ;-------------------------------------------------------------------------- nbanks equ 4 ;number of 16K banks available memory equ 16h ;SBC memory control port bnkslct equ 40h ;bank select for memory disk rambase equ 4000h ;bank address - 4000h recommended dirbuf equ 0F900h ;for standard system secbuf equ 0F980h ;use floppy deblocking buffer for two-stage transfer .z80 ; org at 0 code relative, control location at link time jp ramhome jp ramsel jp rsettrk jp rsetsec jp rsetdma jp ramread jp ramwrite ret nop nop ;no flush needed db 'RAMDISK ' ;module name for display in more advanced loader ramhome: ld C,0 rsettrk: ld A,C ld (ramtrk),A ret rsetsec: ld A,C ld (ramsec),A ret rsetdma: ld (ramdma),BC ret ramsel: ld HL,ramdph ret page 60 ; Disk tables for memory disk - see CP/M 2 Alteration Guide for details ramdph: dw 0,0,0,0 ;no sector translate dw dirbuf ;use dirbuf in floppy module dw ramdpb dw 0 ;no directory check dw ramalv ;allocation vector ramdpb: dw 128 ;128 sectors per track - each 16K bank is a one ;track db 3 ;BSH - use 1K blocks if <257K memory db 7 ;BLM db 0 ;EXM dw 16*banks-1 ;if using 1K blocks dw 63 ;64 directories should be enough db 0c0h ;two directory blocks db 0 dw 0 ;no directory check dw 0 ;no system tracks ramalv: 2*nbanks-1 ;for 1K blocks ramtrk: ds 1 ramsec: ds 1 ramdma: ds 2 page ;------------------------------------------------------------------------- ; ; The only actual i/o involved is blockmoves between the memory bank ; and the user's DMA area. If the DMA area is masked by the bank ; address, we must transfer through a secondary buffer. ; ;------------------------------------------------------------------------- ramread: ld C,0 ;read/write flag jr ramio ramwrite: ld C,0ffh ramio: ld HL,(ramdma) ld B,H ld A,11000000b and B ;get two high order bits of address dec A ;if bank addressed at 4000h jr nz,onetran ;DMA address is masked by memory bank ld A,C or A jr z,dblread ;must do write through secondary buffer ld DE,secbuf ld BC,128 ldir ;move from DMA to secondary buffer ld HL,secbuf ;make onetran think this is DMA address ld C,A ;read/write flag jr onetran dblread: ld HL,secbuf call onetran ;read from bank to secondary buffer ld DE,(ramdma) ld HL,secbuf ld BC,128 ldir ;move from secondary buffer to user DMA ret ;A set to 0 in onetran page onetran: call bankon ;turn on memory bank ld A,(ramsec) srl A ld DE,rambase rr E ;put low order bit of A (odd number of sectors) add A,D ;in E and base + sectors/2 in D ld D,A ld A,C ;readwrite flag ld BC,128 or A jr nz,dowrite ;write operation ex DE,HL ;set to read to user DMA dowrite: ldir call bankoff ;restore SBC memory xor A ret ;return with no errors bankon:  ;turn on 16K bank at 4000h ;can use A,B,DE ld A,00101101b ;turn off 4000h bank on SBC out (memory),A ld A,(ramtrk) ;each track is one 16K bank dec A ld B,A ld A,1 jr z,setbnk ;bank 0 shift: add A,A djnz shift ;A now has one bit set at position (ramtrk) setbnk: out (bnkslct),A ;for boards with one bit per bank ret bankoff: xor A out (bnkslct),A ;turn of memory board ld A,00101111b ;turn on 4000h bank of SBC memory ret end \X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<د2 ه!߶2:2a{_:߷ʖ:߷>Ľʖ:=2–!B!6#5ʖ:߷Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ "ڷ"͌#>?͌͘ =_.:;<> Oڅo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USERg!yO#< Ty#O 3ۯ21y_͸2y2ͽ:ط˜1͘A͌>>͌92^ :߷¥.!_~#fow]ݭގޥ!v"!çREAD ERRORçNO FILE^:߷ ! ~ 3#0 Wx x ڀ ڂ G ~ # 3x~#B!Y~ɯ2:߷=!߾ý:߷=!߾:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ ݯw4!Y~ʆ͌†t=ʆf ^ T ݯ2o&)|+!<ͧÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Y޸psp2mÆÆf ͧÆFILE EXISTS _: É: :߷ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~2߯2\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: !߶ Â$$$ SUBg"C{2!"E9"1A22!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~+é72 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͌x2͢*C ~<wʃG:!ʎì 4~ʶ¬:<ʶ$ʶïZͻx>2>2ͻ:!Z2:Eẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C ::ddslO s#r:E͊:==»y==»*Ww#*"͸*:G#š"͸:!w4!iw:Z!E~=262*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 "ã:!Bw!>2*C~=2u:B2~2wE:A*Cw>"!""2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*W}_*"}o|g":ʑ*C6:ʑw:2E**E}DQ>2×âÐÙëül.oÀgÅÛtU G+ G+ Ď((T ^hp!p:!x:!:!x:????!p:??!x:!:'_^#V([!{<2~(y*|>>/s1H*|<(2\!w͙h(p(y>> >/͏(y>>1͝2.|'^#VS*3!1NFx(BoNF Cg7?KnfB8C[tMD̀ͅ >2!"2*5":O*3!vy2l!=8"j~(##^#V( (!Sw CCnz( Ni`Chɯ2>2;͵:ɯ22y2ͩ͝͵;͵: >2:̝::z2m:[hg:}2q:[hg:{2p:!h_>p!"r:[hgSt:~[q2v:l![n*y:p!j:q!jͩ*t[y͝!Y[vF:–ͩͩ͝ :2!j[*::~!Yp#=[!Y>w( KQ (͚( K| (ͥ:'''!!Kxy:K!!:˗!X[~ ~w(:!w(x(~9:KY(<>0Ͱ> :G!::G!:( ((:<22Cɯ2*j~*~!H[l~2y< P# kz͜:yw*j~@(8#~2y>=9!y:y_>=?͘:!yI :y! g( !so(!Y_( W(s#rI:y_ ag( o(Ys#r:y!:g( !o(!Y_(  W(*js#r!:yw:y͵> =G͵x> _  w !> k_ (!> _ !> _ > _:yg(! O ! O(! _z((!:lA%͐(> >2~#$% O͙!H6#!X[lw*j##^#V*j^#V>= ɧ:=#={z͑{M Warm Boot Error - Reset System$ Bios Err on $: Drive Not Ready$: Write Protected Disk$ 3w+ Ô2"{3q3(:> :<.33PX 2|2>:f3)0R3>::ca{?@/ _ `     "?/c4> \^4U :U H0ʄ4H=;: y4ɯ;:͞:!*#@*?!!44͍ 4:@¾aC02@*?r:5H=͈:3 4*@*@*?"?"@"@ bkë4:?2@+5ů2@@ :@ʊ5a-? M? @ ?  +,ĝ5) <ĝw+:> G6G5͌2 D6>a9% 5 =6:@6G6 ;,76<36>76G67676 w+5:@G66+.0xĝ" @&i"?m6\4>Ô5^4*%@>2@3H0ʱ6 ʶ1;ʫ1'ʡ6"ʡ6>1Ç6G͕0 ʶ1ʛ6â61>2>2!>~ '#F ###^#V!~!~p= ! ! !`|G^>>>:??rC!  00G>0O Super Bios v. 2.3 K CP/M 2.2 installed $D`DO~ʥ7 #Ù7!ɷ #"?~(w/"@i2 ,7w+2@2@ 2=xx2=*=T9"=:=2=@ !!@Ns#Frͦ9ͯ9q#p*@^#V+*@##^#V+*!@}9ͯ9"!@9*@ "@*)@͍ I;*?%:?͍ I;*@T9ͦ9*%@{_{:s#r#>w#wͯ9%:s#r*:"#@*#@ͦ9s#r{_*%@{̺9*@w{W:a:"%@{_ͯ9zʺ9*@}‚:}o~r:{ʗ:a:{_ͯ9{ȯw#w*@s#r{_*%@{̺9*@w{'* "'&'m&'͓'(8(8(8!C N#F#^#V#~#fo|} +x~+ -xw# 8*vxw# Ó'~#fo&'q#p:B(* ͅ ~'M(:J2A(*;" 2 U6+:A(wAMz2@2@ 0) THEN BEGIN C := C - 1 END ELSE BEGIN IF CH = CHR(13) THEN BEGIN IF CARR = 'C' THEN BEGIN D[C] := CHR(13); C := C + 1 END; FOR C := C TO LENGTH DO D[C] := ' '; EXIT END ELSE BEGIN IF C <= LENGTH THEN BEGIN D[C] := CH; C := C + 1 END ELSE BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - LINE OVER FLOW - '); WRITELN; WRITE(' PLEASE REPHRASE INPUT, DO NOT EXCEED ',LENGTH); WRITELN(' CHARACTERS '); WRITELN;  WRITE(' ? '); C := 1 END END END UNTIL CH = CHR(13); EXIT END; (* KYBRD *) PROCEDURE CRT(VAR D : CREG; LENGTH : INTEGER); VAR C :INTEGER; BEGIN C := 1; REPEAT IF C > LENGTH THEN EXIT; IF D[C] = CHR(13) THEN EXIT; WRITE(D[C]); C := C + 1 UNTIL FALSE END; (* CRT *) PROCEDURE OCTALPAD(VAR DATAR : REAL; MIN : REAL; MAX : REAL); CONST BASE = 8; POSLEN = 15; VAR CH : CHAR; C : INTEGER; SCRATCH : INTEGER; PLACEVAL : ARRAY [1..POSLEN] OF REAL; SUMS : ARRAY [1..POSLEN] OF REAL; STORE : ARRAY [0..POSLEN] OF REAL; TDATA : REAL; X : REAL; BEGIN X := 1.0; FOR C := 1 TO POSLEN DO BEGIN PLACEVAL[C] := X; X := X * BASE; END; C := 1; DATAR := 0.0; TDATA := 0.0; SCRATCH := 0; WRITE(' (OCTAL): '); REPEAT READ(CH); CASE CH OF '0' : TDATA := 0.0; '1' : TDATA := 1.0; '2' : TDATA := 2.0; '3' : TDATA := 3.0; '4' : TDATA := 4.0; '5' : TDATA := 5.0; '6' : TDATA := 6.0; '7' : TDATA := 7.0; ELSE BEGIN IF (CH = CHR(08)) AND (C > 1) THEN BEGIN C := C - 2; FOR SCRATCH := 0 TO POSLEN DO STORE[SCRATCH] := STORE[SCRATCH + 1]; FOR SCRATCH := 0 TO POSLEN DO STORE[SCRATCH] := STORE[SCRATCH + 1]; TDATA := STORE[0] END ELSE BEGIN IF (CH = CHR(08)) AND (C <= 1) THEN BEGIN WRITE(' '); C := 0 END ELSE BEGIN IF CH = CHR(13) THEN BEGIN IF TDATA >= MIN THEN BEGIN DATAR := TDATA; EXIT END; WRITELN;  WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITELN(' PLEASE RE-ENTER - MINIMUM VALUE = ',MIN,' '); WRITELN; WRITE(' (OCTAL): '); TDATA := MIN; C := 0 END ELSE BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITE(' PLEASE RE-ENTER - MIN. VALUE = ',MIN); WRITELN(', MAX. VALUE = ',MAX,' '); WRITELN; WRITE(' (OCTAL): '); TDATA := MIN; C := 0 END END END END END; (* CASE *) IF C < POSLEN THEN BEGIN STORE[0] := TDATA; TDATA := 0.0; FOR SCRATCH := POSLEN DOWNTO 1 DO STORE[SCRATCH] := STORE[SCRATCH - 1]; FOR SCRATCH := 1 TO C DO SUMS[SCRATCH] := STORE[SCRATCH] * PLACEVAL[SCRATCH] END ELSE BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - THATS TO MANY NUMBERS - '); WRITELN; WRITE(' PLEASE REPHRASE INPUT, DO NOT EXCEED ',POSLEN -1); WRITELN(' CHARACTERS '); WRITELN; WRITE(' (OCTAL): '); TDATA := MIN; C := 0 END; FOR SCRATCH := 1 TO C DO TDATA := TDATA + SUMS[SCRATCH]; IF TDATA > MAX THEN BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITELN(' PLEASE RE-ENTER - MAXIMUM VALUE = ',MAX,' '); WRITELN; WRITE(' (OCTAL): '); TDATA := MIN; C := 0 END; C := C + 1 UNTIL FALSE (* FOREVER LOOP *) END; (* OCTAL KEYPAD *) PROCEDURE HEXPAD(VAR DATAR : REAL; MIN : REAL; MAX : REAL); CONST BASE = 16; POSLEN = 10; VAR CH : CHAR; C : INTEGER; SCRATCH : INTEGER; PLACEVAL : ARRAY [1..POSLEN] OF REAL; SUMS : ARRAY [1..POSLEN] OF REAL; STORE : ARRAY [0..POSLEN] OF REAL; TDATA : REAL; X : REAL; BEGIN X := 1.0; FOR C := 1 TO POSLEN DO BEGIN PLACEVAL[C] := X; X := X * BASE; END; C := 1; DATAR := 0.0; TDATA := 0.0; SCRATCH := 0; WRITE(' (HEX): '); REPEAT READ(CH); CASE CH OF '0' : TDATA := 0.0; '1' : TDATA := 1.0; '2' : TDATA := 2.0; '3' : TDATA := 3.0; '4' : TDATA := 4.0; '5' : TDATA := 5.0; '6' : TDATA := 6.0; '7' : TDATA := 7.0; '8' : TDATA := 8.0; '9' : TDATA := 9.0; 'A' : TDATA := 10.0; 'B' : TDATA := 11.0; 'C' : TDATA := 12.0; 'D' : TDATA := 13.0; 'E' : TDATA := 14.0;  'F' : TDATA := 15.0; ELSE BEGIN IF (CH = CHR(08)) AND (C > 1) THEN BEGIN C := C - 2; FOR SCRATCH := 0 TO POSLEN DO STORE[SCRATCH] := STORE[SCRATCH + 1]; FOR SCRATCH := 0 TO POSLEN DO STORE[SCRATCH] := STORE[SCRATCH + 1]; TDATA := STORE[0] END ELSE BEGIN IF (CH = CHR(08)) AND (C <= 1) THEN BEGIN WRITE(' '); C := 0 END ELSE BEGIN IF CH = CHR(13) THEN BEGIN IF TDATA >= MIN THEN BEGIN DATAR := TDATA; EXIT END; WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITELN('PLEASE RE-ENTER - MINIMUM VALUE = ',MIN,' '); WRITELN; WRITE(' (HEX): '); TDATA := MIN; C := 0 END ELSE BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITE(' PLEASE RE-ENTER - MIN. VALUE = ',MIN); WRITELN(', MAX. VALUE = ',MAX,' '); WRITELN; WRITE(' (HEX): '); TDATA := MIN; C := 0 END END END END END; (* CASE *) IF C < POSLEN THEN BEGIN STORE[0] := TDATA; TDATA := 0.0; FOR SCRATCH := POSLEN DOWNTO 1 DO STORE[SCRATCH] := STORE[SCRATCH -1]; FOR SCRATCH := 1 TO C DO SUMS[SCRATCH] := STORE[SCRATCH] * PLACEVAL[SCRATCH] END ELSE BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - THATS TO MANY NUMBERS - '); WRITELN; WRITE(' PLEASE REPHRASE INPUT, DO NOT EXCEED ',POSLEN -1); WRITELN(' CHARACTERS '); WRITELN; WRITE(' (HEX): '); TDATA := MIN; C := 0 END; FOR SCRATCH := 1 TO C DO TDATA := TDATA + SUMS[SCRATCH]; IF TDATA > MAX THEN BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITELN(' PLEASE RE-ENTER - MAXIMUM VALUE = ',MAX,' '); WRITELN; WRITE(' (HEX): '); TDATA := MIN; C := 0 END; C := C + 1 UNTIL FALSE (* FOREVER LOOP *) END; (* HEX KEYPAD *) PROCEDURE DECPAD(VAR DATAR : REAL; MIN : REAL; MAX : REAL); CONST BASE = 10; POSLEN = 12; VAR CH : CHAR; C : INTEGER; SCRATCH : INTEGER; PLACEVAL : ARRAY [1..POSLEN] OF REAL; SUMS : ARRAY [1..POSLEN] OF REAL; STORE : ARRAY [0..POSLEN] OF REAL; TDATA : REAL; X : REAL; BEGIN X := 1.0; FOR C := 1 TO POSLEN DO BEGIN PLACEVAL[C] := X; X := X * BASE; END; C := 1; DATAR := 0.0; TDATA := 0.0; SCRATCH := 0; WRITE(' (DEC): '); REPEAT READ(CH); CASE CH OF '0' : TDATA := 0.0; '1' : TDATA := 1.0; '2' : TDATA := 2.0; '3' : TDATA := 3.0; '4' : TDATA := 4.0; '5' : TDATA := 5.0; '6' : TDATA := 6.0; '7' : TDATA := 7.0; '8' : TDATA := 8.0; '9' : TDATA := 9.0; ELSE BEGIN IF (CH = CHR(08)) AND (C > 1) THEN BEGIN C := C - 2; FOR SCRATCH := 0 TO POSLEN DO STORE[SCRATCH] := STORE[SCRATCH + 1]; FOR SCRATCH := 0 TO POSLEN DO   STORE[SCRATCH] := STORE[SCRATCH + 1]; TDATA := STORE[0] END ELSE BEGIN IF (CH = CHR(08)) AND (C <= 1) THEN BEGIN WRITE(' '); C := 0 END ELSE BEGIN IF CH = CHR(13) THEN BEGIN IF TDATA >= MIN THEN BEGIN DATAR := TDATA; EXIT END; WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITELN(' PLEASE RE-ENTER - MINIMUM VALUE = ',MIN,' '); WRITELN; WRITE(' (DEC): '); TDATA := MIN; C := 0 END ELSE BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITE(' PLEASE RE-ENTER - MIN. VALUE = ',MIN); WRITELN(', MAX. VALUE = ',MAX,' '); WRITELN; WRITE(' (DEC): '); TDATA := MIN; C := 0 END END END END END; (* CASE *) IF C < POSLEN THEN BEGIN STORE[0] := TDATA; TDATA := 0.0; FOR SCRATCH := POSLEN DOWNTO 1 DO STORE[SCRATCH] := STORE[SCRATCH - 1]; FOR SCRATCH := 1 TO C DO SUMS[SCRATCH] := STORE[SCRATCH] * PLACEVAL[SCRATCH] END ELSE BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - THATS TO MANY NUMBERS - '); WRITELN; WRITE(' PLEASE REPHRASE INPUT, DO NOT EXCEED ',POSLEN -1); WRITELN(' CHARACTERS '); WRITELN; WRITE(' (DEC): '); TDATA := MIN; C := 0 END; FOR SCRATCH := 1 TO C DO TDATA := TDATA + SUMS[SCRATCH]; IF TDATA > MAX THEN BEGIN WRITELN; WRITELN; WRITELN; WRITELN(' OOPS - VALUE OUT OF RANGE - '); WRITELN; WRITELN(' PLEASE RE-ENTER - MAXIMUM VALUE = ',MAX,' '); WRITELN; WRITE(' (DEC): '); TDATA := MIN; C := 0 END; C := C + 1 UNTIL FALSE (* FOREVER LOOP *) END; (* DECIMAL KEYPAD *) PROCEDURE SELBASE(VAR BASEX : CHAR); BEGIN WRITELN('SELECT BASE '); WRITELN('1) - DECIMAL '); WRITELN('2) - HEX '); WRITELN('3) - OCTAL '); READ(BASEX); WRITELN; CASE BASEX OF '1' : BASEX := 'D'; '2' : BASEX := 'H'; '3' : BASEX := 'O'; ELSE BASEX := 'H' END (* CASE *) END; (* SELECT BASE *) PROCEDURE CLEARSCREEN; BEGIN WRITE(CHR(12)); WRITE(CHR(27)); WRITE(CHR(43)); END; (* CLEAR SCREEN *) PROCEDURE AMPERIFHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * AMPERIF - MAID-III * * * '); WRITELN; WRITELN; WRITELN; END; (* AMPERIF HEADING *) PROCEDURE INIT1(VAR XXW : WDTEMPLATE;VAR XB : BOOLEAN); VAR X : INTEGER; BEGIN FOR X := 1 TO 5 DO XXW[X] := $0000; XB := FALSE END; (* INIT 1 *) PROCEDURE INITUSER(VAR NAME : IREG); VAR X : CHAR; BEGIN CLEARSCREEN; WRITELN; WRITE('HI, NAME PLEASE? '); KYBRD(NAME,20,'C'); AMPERIFHEADING; IF NAME[1] = CHR(13) THEN BEGIN NAME[1] := 'I'; NAME[2] := 'M'; NAME[3] := 'P'; NAME[4] := 'A'; NAME[5] := 'T'; NAME[6] := 'I'; NAME[7] := 'E'; NAME[8] := 'N'; NAME[9] := 'T'; NAME[10] := CHR(13) END; CRT(NAME,20); WRITELN(','); WRITELN; WRITELN; WRITELN(' TYPE CTRL - H :TO BACK SPACE. '); WRITELN(' TYPE CTRL - S :TO STOP SCROLL (XOFF). '); WRITELN(' TYPE CTRL - Q :TO START SCROLL (XON). '); WRITE(' TYPE RETURN TO CONTINUE. '); READ(X) END; (* INITUSER *) PROCEDURE EFHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - EF WORD * * * '); WRITELN; WRITELN; WRITELN END; (* EFW HEADING *) PROCEDURE AFHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - AF WORD * * * '); WRITELN; WRITELN; WRITELN END; (* AFW HEADING *) PROCEDURE STHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - STATUS WORD * * * '); WRITELN; WRITELN; WRITELN END; (* STATUS WORD HEADING *) PROCEDURE OUTBUFFHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - OUTPUT BUFFER * * * '); WRITELN; WRITELN; WRITELN; END; (* OUTPUT BUFFER HEADING *) PROCEDURE INBUFFHEADING;  BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - INPUT BUFFER * * * '); WRITELN; WRITELN; WRITELN; END; (* INPUT BUFFER HEADING *) PROCEDURE DDFHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - DUMP DATA FILE * * * '); WRITELN; WRITELN; WRITELN END; (* DUMP DATA FILE HEADING *) PROCEDURE INSTRHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - INSTRUCTIONS * * * '); WRITELN; WRITELN; WRITELN END; (* INSTRUCTION HEADING *) PROCEDURE MAKHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - MAKE PACKET * * * '); WRITELN; WRITELN END; (* MAKE PACKET *) PROCEDURE DMPHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - DUMP PACKET FILE * * * '); WRITELN; WRITELN; WRITELN END; (* DUMP PACKET FILE *) PROCEDURE CMPHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - COMPARE DATA FILES * * * '); WRITELN; WRITELN; WRITELN END; (* COMPARE DATA FILES *) PROCEDURE EXECHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - EXECUTE PACKET FILE * * * '); WRITELN; WRITELN; WRITELN END; (* EXECUTE PACKET *) PROCEDURE TERMHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - TERMINAL TALK * * * '); WRITELN; WRITELN; WRITELN END; (* TERMINAL TALK *) PROCEDURE PHTERMHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - PHONE ON TERMINATION * * *'); WRITELN; WRITELN; WRITELN END; (* PHONE ON TERMINATION *) PROCEDURE DIRHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - FILES DIRECTORY * * * '); WRITELN; WRITELN; WRITELN END; (* DIRECTORY HEADING *) PROCEDURE DELHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - DELETE FILE * * * '); WRITELN; WRITELN; WRITELN END; (* DELETE FILE HEADING *) PROCEDURE MANUALHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - MANUAL/OVER-RIDE * * * '); WRITELN; WRITELN; WRITELN END; (* MANUAL/OVERRIDE HEADING *) PROCEDURE POSTHEADING; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITE(' * * * MAID-III - POST EXECUTION ANALYSIS'); WRITELN(' * * * '); WRITELN; WRITELN; WRITELN END; (* POST ANALYSIS HEADING *) PROCEDURE SETUPCOMM(C:CHAR); VAR CMD : CHAR; TALK : CHAR; CMDSTR : ARRAY [1..27] OF CHAR; XM : INTEGER; BEGIN IF C = 'C' THEN BEGIN WRITELN('EXAMPLE - "ATDT 1-(XXX) XXX-XXXX" '); WRITE('ENTER MODEM COMMAND STRING: '); KYBRD(CMDSTR,26,'C'); WRITE('ENTER SPEED (ORIGINATE - A=300, B=1200, RET=LAST): '); READ(CMD);   CASE CMD OF 'A','a' : BEGIN INLINE("MVI A / $40 / "OUT / $C1 / "MVI A / $CF / "OUT / $C1 / "MVI A / $27 / "OUT / $C1) END; 'B','b' : BEGIN INLINE("MVI A / $40 / "OUT / $C1 / "MVI A / $CE / "OUT / $C1 / "MVI A / $27 / "OUT / $C1) END END; (* CASE *) WRITELN; WRITE('SEND COMMAND STRING NOW (Y/N): '); READ(CMD); WRITELN; END; IF CMD = 'Y' THEN C := 'D'; IF CMD = 'y' THEN C := 'D'; IF C = 'D' THEN BEGIN XM := 0; REPEAT XM := XM + 1; TALK := CMDSTR[XM]; INLINE( [LBL] ); INLINE("IN / $C1 / "ANI / $01 / "JZ / LBL / "LDA / TALK /  "OUT / $C0); WRITE(TALK); UNTIL TALK = CHR(13) END END; (* SET UP USART AND SMART MODEM *) PROCEDURE DATANIBBLES(VAR XDN : WDTEMPLATE;BASEREQ : CHAR); VAR DNR : REAL; DNI : INTEGER; NI : INTEGER; MAXVAL : REAL; TEMPREGI : ARRAY[1..9] OF INTEGER; BEGIN WRITELN; FOR NI := 1 TO 9 DO BEGIN IF NI = 9 THEN MAXVAL := 15.0 ELSE MAXVAL := 15.0; WRITE('NIBBLE ',NI); IF BASEREQ = 'D' THEN DECPAD(DNR,0.0,MAXVAL); IF BASEREQ = 'H' THEN HEXPAD(DNR,0.0,MAXVAL); IF BASEREQ = 'O' THEN OCTALPAD(DNR,0.0,MAXVAL); REALINT8B(DNR,DNI,1); TEMPREGI[NI] := DNI; WRITELN END; XDN[1] := (TEMPREGI[2] * 16) + TEMPREGI[1]; XDN[2] := (TEMPREGI[4] * 16) + TEMPREGI[3]; XDN[3] := (TEMPREGI[6] * 16) + TEMPREGI[5]; XDN[4] := (TEMPREGI[8] * 16) + TEMPREGI[7]; XDN[5] := TEMPREGI[9] END; (* LOAD BITS 35 - 0 (NIBBLE FORMAT) *) PROCEDURE DATABYTES(VAR XDB : WDTEMPLATE;BASEREQ : CHAR); VAR DBR : REAL; DBI : INTEGER; BI : INTEGER; MAXVAL : REAL; BEGIN WRITELN; FOR BI := 1 TO 5 DO BEGIN IF BI = 5 THEN MAXVAL := 15.0 ELSE MAXVAL := 255.0; WRITE('BYTE ',BI); IF BASEREQ = 'D' THEN DECPAD(DBR,0.0,MAXVAL); IF BASEREQ = 'H' THEN HEXPAD(DBR,0.0,MAXVAL); IF BASEREQ = 'O' THEN OCTALPAD(DBR,0.0,MAXVAL); REALINT8B(DBR,DBI,1); XDB[BI] := DBI; WRITELN END END; (* LOAD BITS 35 - 0 (BYTE FORMAT) *) PROCEDURE DATAWORD(VAR XDW : WDTEMPLATE;MINV,MAXV : REAL;BREQ : CHAR; BYTES : INTEGER); CONST ZERO = $0000; ZMSK70 = $0000; ZMSK158 = $0000; ZMSK2316 = $0000; ZMSK3124 = $0000; ZMSK3932 = $0000; ZMSK3936 = $000F; VAR DWR : REAL; DWI : INTEGER; BYT : INTEGER; BEGIN IF BREQ = 'D' THEN DECPAD(DWR,MINV,MAXV); IF BREQ = 'H' THEN HEXPAD(DWR,MINV,MAXV); IF BREQ = 'O' THEN OCTALPAD(DWR,MINV,MAXV); FOR BYT := 1 TO BYTES DO BEGIN REALINT8B(DWR,DWI,BYT); XDW[BYT] := DWI; END; WRITELN END; (* LOAD BITS 35 - 0 (DATA WORD) *) PROCEDURE MAKEBUFFER(VAR XWDA:WDTEMPLATE;VAR XFERLR:REAL; VAR PRGCMD,DATMOD:INTEGER;VAR BUFRPT,WRDRPT:BOOLEAN;VAR PRGCNT:A2B); VAR BUFFREPEATMAX : REAL; BUFFRPTCNT : REAL; ACTMBCT : REAL; OPTMBCT : REAL; REMBCT : REAL; DATRPTCNT : REAL; X : INTEGER; COMMR : REAL; COMM : INTEGER; DATAFORMT : CHAR; BASEREQ : CHAR; C : CHAR; BEGIN DATRPTCNT := 0.0; BUFFREPEATMAX := 0.0; BUFFRPTCNT := 0.0; ACTMBCT := 0.0; OPTMBCT := 0.0; REMBCT := XFERLR; BUFRPT := FALSE; WRDRPT := FALSE; PRGCMD := $06; DATMOD := $FE; (* OPEN/CREATE - FILE *) M5046(PRGCMD); REPEAT IF OPTMBCT < 65536.0 THEN BEGIN OUTBUFFHEADING; WRITE('REMAINING BUFFER SPACE = ',REMBCT,'(DEC) '); WRITELN(' DATA TRANSFER LENGTH = ',XFERLR,'(DEC) '); WRITELN; SELBASE(BASEREQ); WRITELN('SELECT DATA FORMAT'); WRITELN('1) - WORD '); WRITELN('2) - BYTE '); WRITELN('3) - NIBBLE '); READ(DATAFORMT); WRITELN; WRITE('DATA WORD'); CASE DATAFORMT OF '1' : DATAWORD(XWDA,0.0,68719476735.0,BASEREQ,5); '2' : DATABYTES(XWDA,BASEREQ); '3' : DATANIBBLES(XWDA,BASEREQ) ELSE DATAWORD(XWDA,0.0,68719476735.0,BASEREQ,5) END; (* CASE *) OPTMBCT := OPTMBCT + 1.0; ACTMBCT := ACTMBCT + 1.0; REMBCT := XFERLR - ACTMBCT; IF ACTMBCT < XFERLR THEN BEGIN OUTBUFFHEADING; WRITE('REMAINING BUFFER SPACE = ',REMBCT,'(DEC) '); WRITELN(' DATA TRANSFER LENGTH = ',XFERLR,'(DEC) '); WRITELN; WRITE('DATA WORD REPEAT COUNT'); DECPAD(DATRPTCNT,0.0,REMBCT); ACTMBCT := ACTMBCT + DATRPTCNT; REMBCT := XFERLR - ACTMBCT; IF DATRPTCNT > 0.0 THEN BEGIN WRITELN; WRITELN(' - MODIFY DATA THROUGH REPEAT COUNT - '); WRITELN; WRITELN('1) - NO OPERATION '); WRITELN('2) - INCREMENT '); WRITELN('3) - DECREMENT '); WRITELN('4) - SHIFT RIGHT '); WRITELN('5) - SHIFT LEFT '); WRITELN('6) - RANDOM '); WRITELN('7) - COMPLIMENT '); WRITELN; WRITE(' - enter number'); DECPAD(COMMR,1.0,7.0); COMM := TRUNC(COMMR); WRITELN; CASE COMM OF 1 : BEGIN DATMOD := $01; IF DATRPTCNT = XFERLR - 1 THEN BEGIN WRDRPT := TRUE; BUFRPT := TRUE END END; 2 : BEGIN DATMOD := $02  END; 3 : BEGIN DATMOD := $03 END; 4 : BEGIN DATMOD := $04 END; 5 : BEGIN DATMOD := $05 END; 6 : BEGIN DATMOD := $06 END; 7 : BEGIN DATMOD := $07 END END (* CASE *) END ELSE BEGIN DATMOD := $01 END; REALINT8B(DATRPTCNT,X,1); PRGCNT[1] := X; REALINT8B(DATRPTCNT,X,2); PRGCNT[2] := X; M5046(PRGCMD); DATRPTCNT := 0.0 END; IF XFERLR > ACTMBCT THEN IF ACTMBCT <= RECSIZ / 5 THEN BEGIN OUTBUFFHEADING; WRITE('REMAINING BUFFER SPACE = ',REMBCT,'(DEC) '); WRITELN(' DATA TRANSFER LENGTH = ',XFERLR,'(DEC) '); WRITELN; WRITE('REPEAT BUFFER THROUGH TRANSFER LENGTH (Y/N) '); READ(C); IF C = 'Y' THEN BEGIN BUFRPT := TRUE; ACTMBCT := XFERLR END; REMBCT := XFERLR - ACTMBCT END END ELSE WRITELN('OUT OF BUFFER SPACE '); UNTIL ACTMBCT = XFERLR; DATMOD := $FF; (* CLOSE FILE AND REWRITE CONTROL RECORD *) M5046(PRGCMD) END; (* MAKE BUFFER *) PROCEDURE DSKUNIT(VAR BYTE4 : INTEGER); CONST ZMSK2824 = $00E0; VAR DSKUNTR : REAL; DSKUNTI : INTEGER; BEGIN WRITE('DISK UNIT ADDRESS'); DECPAD(DSKUNTR,0.0,31.0); DSKUNTI := TRUNC(DSKUNTR); BYTE4 := BYTE4 AND ZMSK2824; BYTE4 := BYTE4 OR DSKUNTI; WRITELN END; (* LOAD BITS 28 - 24 (DSK) *) PROCEDURE ZERO172(VAR XWRD : WDTEMPLATE); CONST ZERO = $0000; ZMSK72 = $0003; ZMSK158 = $0000; ZMSK1716 = $00FC; BEGIN XWRD[1] :=  XWRD[1] AND ZMSK72; XWRD[1] := XWRD[1] OR ZERO; XWRD[2] := XWRD[2] AND ZMSK158; XWRD[2] := XWRD[2] OR ZERO; XWRD[3] := XWRD[3] AND ZMSK1716; XWRD[3] := XWRD[3] OR ZERO END; (* ZERO BITS 17 - 2 *) PROCEDURE ZERO3429(VAR XWRD : WDTEMPLATE); CONST ZERO = $0000; ZMSK3129 = $001F; ZMSK3432 = $00F8; BEGIN XWRD[4] := XWRD[4] AND ZMSK3129; XWRD[4] := XWRD[4] OR ZERO; XWRD[5] := XWRD[5] AND ZMSK3432; XWRD[5] := XWRD[5] OR ZERO END; (* ZERO BITS 34 - 29 *) PROCEDURE SET35(VAR BYTE5 : INTEGER); CONST BIT35 = $0008; ZMSK35 = $00F7; BEGIN BYTE5 := BYTE5 AND ZMSK35; BYTE5 := BYTE5 OR BIT35 END; (* SET BIT 35 (EF) *) PROCEDUR BACKFACTOR(VAR BYTE1 : INTEGER); CONST ZMSK10 = $00FC; VAR BACFACI : INTEGER; BACFACR : REAL; BEGIN WRITE('BACKING FACTOR'); DECPAD(BACFACR,0.0,3.0); BACFACI := TRUNC(BACFACR); BYTE1 := BYTE1 AND ZMSK10; BYTE1 := BYTE1 OR BACFACI; WRITELN END; (* LOAD BITS 1 - 0 (BF) *) PROCEDURE ZERO170(VAR XWRD : WDTEMPLATE); CONST ZERO = $0000; ZMSK70 = $0000; ZMSK158 = $0000; ZMSK1716 = $00FC; BEGIN XWRD[1] := XWRD[1] AND ZMSK70; XWRD[1] := XWRD[1] OR ZERO; XWRD[2] := XWRD[2] AND ZMSK158; XWRD[2] := XWRD[2] OR ZERO; XWRD[3] := XWRD[3] AND ZMSK1716; XWRD[3] := XWRD[3] OR ZERO END; (* ZERO BITS 17 - 0 *) PROCEDURE ZERO178(VAR XWRD : WDTEMPLATE); CONST ZERO = $0000; ZMSK158 = $0000; ZMSK1716 = $00FC; BEGIN XWRD[2] := XWRD[2] AND ZMSK158; XWRD[2] := XWRD[2] OR ZERO; XWRD[3] := XWRD[3] AND ZMSK1716; XWRD[3] := XWRD[3] OR ZERO END; (* ZERO BITS 17 - 8 *) PROCEDURE ZERO1716(VAR BYTE3 : INTEGER); CONST ZERO = $0000; ZMSK1716 = 00FC; BEGIN BYTE3 := BYTE3 AND ZMSK1716; BYTE3 := BYTE3 OR ZERO END; (* ZERO BITS 17 - 16 *) PROCEDURE WRDPREPLEN(VAR BYTE1 : INTEGER); CONST ZMSK70= $0000; VAR WPREPLR : REAL; WPREPLI : INTEGER; BEGIN WRITE('WORD PREP LENGTH'); DECPAD(WPREPLR,112.0,112.0); WPREPLI := TRUNC(WPREPLR); BYTE1 := BYTE1 AND ZMSK70; BYTE1 := BYTE1 OR WPREPLI; WRITELN END; (* LOAD BITS 7 - 0 (WRDPREPLEN) *) PROCEDURE WRDXFERLEN(VAR XWRD : WDTEMPLATE;VAR WDXFERLR : REAL); CONST ZMSK70 = $0000; ZMSK158 = $0000; VAR WDXFERLI : INTEGER; BEGIN WRITE('WORD TRANSFER LENGTH'); DECPAD(WDXFERLR,1.0,65535.0); REALINT8B(WDXFERLR,WDXFERLI,1); XWRD[1] := XWRD[1] AND ZMSK70; XWRD[1] := XWRD[1] OR WDXFERLI; REALINT8B(WDXFERLR,WDXFERLI,2); XWRD[2] := XWRD[2] AND ZMSK158; XWRD[2] := XWRD[2] OR WDXFERLI; WRITELN END; (* LOAD BITS 15 - 0 (XFERLEN) *) PROCEDURE BYTERECLEN(VAR XWRD : WDTEMPLATE); CONST ZMSK70 = 0000; ZMSK158 = 0000; VAR BYTRECLR : REAL; BYTRECLI : INTEGER; BEGIN WRITE('BYTE RECORD LENGTH'); DECPAD(BYTRECLR,504.0,504.0); REALINT8B(BYTRECLR,BYTRECLI,1); XWRD[1] := XWRD[1] AND ZMSK70; XWRD[1] := XWRD[1] OR BYTRECLI; REALINT8B(BYTRECLR,BYTRECLI,2); XWRD[2] := XWRD[2] AND ZMSK158; XWRD[2] := XWRD[2] OR BYTRECLI; WRITELN END; (* LOAD BITS 15 - 0 (BYTE REC LENGTH) *) PROCEDURE WRDVERLEN(VAR XWRD : WDTEMPLATE); CONST ZMSK70 = $0000; ZMSK158 = $0000; VAR WVERLR : REAL; WVERLI : INTEGER; BEGIN WRITE('WORD VERIFY LENGTH'); DECPAD(WVERLR,0.0,65535.0); REALINT8B(WVERLR,WVERLI,1); XWRD[1] := XWRD[1] AND ZMSK70; XWRD[1] := XWRD[1] OR WVERLI; REALINT8B(WVERLR,WVERLI,2); XWRD[2] := XWRD[2] AND ZMSK158; XWRD[2] := XWRD[2] OR WVERLI; WRITELN END; (* LOAD BIT 15 - 0 (WRD VERIFY LEN) *) PROCEDURE RELWRDADD(VAR XWRD : WDTEMPLATE); CONST ZMSK70 = $0000; ZMSK158 = $0000; ZMSK2316 = $0000; ZMSK2624 = $00F8; VAR RWADDR : REAL; RWADDI : INTEGER; BEGIN WRITE('RELATIVE WORD ADDRESS'); DECPAD(RWADDR,0.0,134217727.0); REALINT8B(RWADDR,RWADDI,1); XWRD[1] := XWRD[1] AND ZMSK70; XWRD[1] := XWRD[1] OR RWADDI; REALINT8B(RWADDR,RWADDI,2); XWRD[2] := XWRD[2] AND ZMSK158; XWRD[2] := XWRD[2] OR RWADDI; REALINT8B(RWADDR,RWADDI,3); XWRD[3] := XWRD[3] AND ZMSK2316; XWRD[3] := XWRD[3] OR RWADDI; REALINT8B(RWADDR,RWADDI,4); XWRD[4] := XWRD[4] AND ZMSK2624; XWRD[4] := XWRD[4] OR RWADDI; WRITELN END; (* LOAD BITS 26 - 0 (REL WRD ADD) *) PROCEDURE ZERO3427(VAR XWRD : WDTEMPLATE); CONST ZERO = $0000; ZMSK3127 = $0007; ZMSK3432 = $00F8; BEGIN XWRD[4] := XWRD[4] AND ZMSK3127; XWRD[4] := XWRD[4] OR ZERO; XWRD[5] := XWRD[5] AND ZMSK3432; XWRD[5] := XWRD[5] OR ZERO END; (* ZERO BITS 34 -27 *) PROCEDURE ZERO70(VAR BYTE1 : INTEGER); CONST ZERO = $0000; ZMSK70 = $0000; BEGIN BYTE1 := BYTE1 AND ZMSK70; BYTE1 := BYTE1 OR ZERO END; (* ZERO BITS 7 - 0 *) PROCEDURE ZERO1713(VAR XWRD : WDTEMPLATE); CONST ZERO = $0000; ZMSK1513 = $001F; ZMSK1716 = $00FC; BEGIN XWRD[2] := XWRD[2] AND ZMSK1513; XWRD[2] := XWRD[2] OR ZERO; XWRD[3] := XWRD[3] AND ZMSK1716; XWRD[3] := XWRD[3] OR ZERO END; (* ZERO BITS 17 - 13 *) PROCEDURE ZERO3428(VAR XWRD : WDTEMPLATE); CONST ZERO = $0000; ZMSK3128 = $000F; ZMSK3432 = $00F8; BEGIN XWRD[4] := XWRD[4] AND ZMSK3128; XWRD[4] := XWRD[4] OR ZERO; XWRD[5] := XWRD[5] AND ZMSK3432; XWRD[5] := XWRD[5] OR ZERO END; (* ZERO BITS 34 - 28 *) PROCEDURE HEADADD(VAR BYTE2 : INTEGER); CONST ZMSK128 = $00E0; VAR HEADR : REAL; HEADI : INTEGER; BEGIN WRITE('HEAD ADDRESS'); DECPAD(HEADR,0.0,31.0); HEADI := TRUNC(HEADR); BYTE2 := BYTE2 AND ZMSK128; BYTE2 := BYTE2 OR HEADI; WRITELN END; (* LOAD BITS 12 - 8 (HD) *) PROCEDURE RESET35(VAR BYTE5 : INTEGER); CONST BIT35 = $0000; ZMSK35 = 00F7; BEGIN BYTE5 := BYTE5 AND ZMSK35; BYTE5 := BYTE5 OR BIT35 END; (* RESET BIT35 *) PROCEDURE SECTORADD(VAR BYTE1 : INTEGER); CONST ZMSK70 = $0000; VAR SECTORR : REAL; SECTORI : INTEGER; BEGIN WRITE('SECTOR ADDRESS'); DECPAD(SECTORR,0.0,255.0); SECTORI := TRUNC(SECTORR); BYTE1 := BYTE1 AND ZMSK70; BYTE1 := BYTE1 OR SECTORI; WRITELN END; (* LOAD BITS 7 - 0 (SECTOR) *) PROCEDURE RECORDT(VAR BYTE1 : INTEGER); CONST ZMSK70 = $0000; VAR RECR : REAL; RECI : INTEGER; BEGIN WRITE('RECORD'); DECPAD(RECR,0.0,255.0); RECI := TRUNC(RECR); BYTE1 := BYTE1 AND ZMSK70; BYTE1 := BYTE1 OR RECI; WRITELN END; (* LOAD BITS 7 - 0 (RECORD) *) PROCEDURE CYLADD(VAR XWRD : WDTEMPLATE); CONST ZMSK2318 = $0003; ZMSK2724 = $00F0; VAR CYLR : REAL; CYLI : INTEGER; BEGIN WRITE('CYLINDER ADDRESS'); DECPAD(CYLR,0.0,1023.0); REALINT8B(CYLR,CYLI,1); XWRD[3] := XWRD[3] AND ZMSK2318; XWRD[3] := XWRD[3] OR CYLI; REALINT8B(CYLR,CYLI,2); XWRD[4] := XWRD[4] AND ZMSK2724; XWRD[4] := XWRD[4] OR CYLI; WRITELN END; (* LOAD BITS 27 - 18 (CYL ADD) *) PROCEDURE ZERO10(VAR BYTE1 : INTEGER); CONST ZERO = $0000; ZMSK10 = $00FC; BEGIN BYTE1 := BYTE1 AND ZMSK10; BYTE1 := BYTE1 OR ZERO END; (* ZERO BITS 1 - 0 *) PROCEDURE MENULANG5046(VAR EFW,AFW,ODW,IDW,STW:WDTEMPLATE; VAR EF,AF,OD,ID,ST:BOOLEAN); CONST SECPOSRELSK = $AC; TRKPOSRELSK = $2C; SEEK = $1C; SEEKASETSEC = $9C; RECALIBRATE = $4C; NOOPERATION = $0C; WRTHMADDROS = $D4; PREPTRACK = $04; PREPCYL = $84; WRITEDATA = $34; WRTDATAPADZ = $24; READIPL = $00; READFULLTRK = $58; READHMADDSP = $D8; READCOUNT = $48; SPCNTARDDAT = $98; READDATA = $38; RDDATASPEC = $F8; READVERIFY = $28; READLABEL = $C8; SENSEIO = $10; RDARESBUFLG = $90; READCONFG = $D0; RDBUFFREC = $50; ZMSK2318 = $0003; VAR CMD : CHAR; BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - 5046 COMMANDS * * * '); WRITELN; WRITELN; WRITELN; WRITELN('1) - CONTROL COMMANDS '); WRITELN('2) - WRITE COMMANDS '); WRITELN('3) - READ COMMANDS '); WRITELN('4) - SENSE COMMANDS '); WRITELN; WRITE(' - enter number: '); READ(CMD); WRITELN; CASE CMD OF '1' : BEGIN CLEARSCREEN; WRITELN;   WRITELN; WRITELN; WRITE(' * * * MAID-III - 5046 CONTROL COMMANDS * * * '); WRITELN; WRITELN; WRITELN; WRITELN; WRITELN('1) - SECTOR POSITION RELATIVE SEEK '); WRITELN('2) - TRACK POSITION RELATIVE SEEK '); WRITELN('3) - SEEK '); WRITELN('4) - SEEK AND SET SECTOR '); WRITELN('5) - RECALIBRATE '); WRITELN('6) - NO OPERATION '); WRITELN; WRITE(' - enter number: '); READ(CMD); WRITELN; CASE CMD OF '1' : BEGIN EFHEADING; WRITELN('SECTOR POSITION RELATIVE SEEK '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR SECPOSRELSK; DSKUNIT(EFW[4]); BACKFACTOR(EFW[1]);  SET35(EFW[5]); ZERO172(EFW); ZERO3429(EFW); AFHEADING; RESET35(AFW[5]); ZERO3427(AFW); RELWRDADD(AFW); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '2' : BEGIN EFHEADING; WRITELN('TRACK POSITION RELATIVE SEEK '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR TRKPOSRELSK; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO172(EFW); ZERO10(EFW[1]); AFHEADING; RESET35(AFW[5]); ZE>o:~W!{> " OC > S>O:31!2|}N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!'}#"* (,*#"+))[R#}! !!Ax͎qput+[[R8 utx7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !;NFx(ENF C$7?KnfB8C[0MD!' {:m!;!NFnfB#>,(0W}_nfRut;RDM!A76! [36:G6!w0 ͖!2͖ !͗>O3F#Nů  SYS: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file *+":*+"/:*+"^:*+":!":"5:"d:":!":"7:"f:"::8*9:8=o&))8  ^#V!q;p+q!r;6>!r;2*r;&;) p;3>L ~ÒÃG3x(OxAG:RG~ > 2P:HO y~ 8 q!*T~(ͭ8͏ͷ:K2N>2>2SKc> 2P> :SG /_~(!: *E:N{  _!c(  :P= L{(({ZZ:HhZ:NhZ:RhZZ>2P ~ ( w:K2LF8 <2Ny2R:KW:D*GKIB(7:LGz?"V*G"I:KG2LxG![E2DG!> z:(8 XZd>w(>>w~Can't recognize density of disk in$Read$Write$Seek$ error on track $ sector $ side $ drive $ $!\6͂ !!y;6͂6 :y;- !Ͱ ͭ :s;:| :\:y;HZ !:]A<2\O>n !*y;&\ 6 ì !y;6:s;.¨ ͭ͂ڨ :y; ڟ !Ͱ ͭÌ ! :y;<2y;O!\ :s;w:s;0O> :s;02s;> :s;AO> :s;A 2s;>>!"z;͆ :s;<:s;]:s; HҀ :s;S¸ !96ͭ} :s;P !96 "9} :s;D !96 "9} :s;L "8} :s;M q!*T~(ͭ8͏ͷ:K2N>2>2SKc> 2P> :SG /_~(!: *E:N{  _!c(  :P= L{(({ZZ:HhZ:NhZ:RhZZ>2P ~ ( w:K2LF8 <2Ny2R:KW:D*GKIB(7:LGz?"V*G"I:KG2LxG![E2DG!> z:(8 XZd>w(>>w~Can't recognize density of disk in$Read$ TITLE ADVANCED DIGITAL LOADER BIOS FOR SUPER QUAD Oct 15 1982 08:00 ;***************************************************************** ;** ** ;** ADVANCED DIGITAL SUPER QUAD Z80 SBC ** ;** ** ;** LOADER BIOS ** ;** ** ;** This bios contains drivers for: ** ;** ** ;** Floppy disk or ** ;** Hard disk ** ;** Serial input & output ** ;** ** ;** Written by: ** ;** ** ;** Scott Carter ** ;** Greg Lindberg ** ;** ** ;***************************************************************** SUBTTL Customization Equates page 60 .z80 true equ 0ffffh false equ 0 mini equ false ;true for minifloppy BIOS special equ false ;true for 8"-5" special board m48tpi equ false ;true for 48tpi mini drives m96tpi equ false ;true for 96tpi mini drives nmbfpy equ 2 ;number of floppy disk drives ;------------------------------------------------------------------------ ; This is the seek rate constant!! seekrt, below, is an offset! seekrate equ 0 ;6ms for 8", 12ms for 5" ;seek rate 0=3ms, 1=6ms, 2=10ms, 3=15ms ;these times double for minifloppies ;*** Hard Disk selection choices *** ST503 EQU 1 ; Seagate Technology ST503 ST506 EQU 2 TM601S EQU 3 ; Tandon Magnetics TM601S TM602S EQU 4 TM603S EQU 5 TM603SE EQU 6 TM501 EQU 7 ; Tandon Magnetics TM501 TM502 EQU 8 TM503 EQU 9 SA602 EQU 10 ; Shugart Associates SA602 SA604 EQU 11 SA606 EQU 12 SA1002 EQU 13 ; Shugart Associates SA1002 SA1004 EQU 14 Q2010 EQU 15 ; Quantum Q2010 Q2020 EQU 16 Q2030 EQU 17 Q2040 EQU 18 M4010 EQU 19 ; MiniScribe 4010 M4020 EQU 20 ;*** HDC1001 Physical drives *** hd0 equ m4020 ; Set to type of drive or false if not used SUBTTL SYMBOLIC EQUATES page ; board hardware equates cmd equ 0ch ;fdc command register trk equ cmd+1 ;track register sec equ cmd+2 ;sector register data equ cmd+3 ;data register wait equ 14h ;INTRQ and DRQ synch port (see manual) memry equ 16h ;memor y control port ; ; sector deblocking equates ; hstcnt equ 8 ;number of sectors in buffer hstshft equ 3 ;shift factor for # of sectors in buffer if mini ddpspt equ 4 ;double density physical sectors per track if m48tpi tracks equ 39 ;minifloppies else tracks equ 76 ;96tpi drives endif else ddpspt equ 8 ;eight inch tracks equ 76 endif dpblen equ 15 ;length of a DPB ; ; floppy disk hardware parameter offsets ; density equ 0 ;0=single, 1=single side double D, 2= 2S2D seekrt equ 1 ;THIS IS OFFSET INTO TABLE, VALUE IN TABLE CAN BE ;seek rate 0=3ms, 1=6ms, 2=10ms, 3=15ms ;these times double for minifloppies pspt equ 2 ;physical sectors per track (one side) drvtrk equ 3 ;track a floppy is at parmlen equ 4 ;length of the parameter block ; ; miscellaneous equates ; iobyte equ 3 ;used to select various consoles and printers cdisk equ 4 ;default disk user number retries equ 10 ;retry count for disk operations inbfsz equ 32 ;size of input buffer for interrupt input must be power of 2 outbfsz equ 64 ;size of output buffer for interrupt output must be power of 2 SUBTTL Hard disk equates page ;*** HDC1001 Disk equates *** HOFF EQU 1 ; Number of reserved tracks for loader TST MACRO DN ;physical hard disk defined IF HD&DN x defl 1 else x defl 0 endif endm hddsks defl 0 ;number of physical hard disk drives hdldrvs defl 0 ;number of logical hard disk drives hdtst macro tst %hddsks ;test for physical drives iff x exitm endif .lall hddsks defl hddsks+1 .xall endm ;end hdtst hdtst ;calculate number of physical hard disks if hddsks ;set flag for hard disks hard equ true else hard equ false endif .sfcond if hard ;put this stuff in only if needed .lfcond ;*** Port equates for HDC1001 *** HDCBASE EQU 0E0H ; Base of HDC1001 HDCDATA EQU HDCBASE ; Data port WPC EQU HDCBASE+1 ; Write precomp port HDCERR EQU WPC ; Error port SECNT EQU HDCBASE+2 ; Sector count SECNO EQU HDCBASE+3 ; Sector number CYLLO EQU HDCBASE+4 ; Cylinder low CYLHI EQU HDCBASE+5 ; Cylinder high SDH EQU HDCBASE+6 ; Size/Drive/Head COMND EQU HDCBASE+7 ; Command register STATUS EQU COMND ; Status register ;*** Command equates for HDC1001 *** CREST EQU 10H ; Restore command CSEEK EQU 70H ; Seek command CREAD EQU 20H ; Read sector command CWRITE EQU 30H ; Write command CFORM EQU 50H ; Format track inter equ 8 ;hard disk sector interleave factor secs equ 16 ;Physical sectors per track per head hstsiz equ 512 ;size of a hard disk physical sector hdstcnt equ hstsiz/128 ;cp/m sectors per physical sector blksiz equ 4096 ;cp/m block size cpmspt equ hdstcnt*secs ;cp/m sectors per track per head cpmscbk equ blksiz/128 ;cp/m sectors per cp/m block ; dpbg macro dn,secs,bls,blm,ext,dks,dir,al0,al1,cks,off,phys .lall dpb&dn: dw secs ;sec per track db bls ;block shift db blm ;block mask db ext ;extnt mask dw dks ;disk size-1 dw dir ;directory max db al0 ;alloc0 db al1 ;alloc1 dw cks ;check size dw off ;offset db phys ;physical disk drive .xall endm hdscg macro dn,mxcl,mxhd,stprt .lall hdesc&dn: db hdcbase ;base i/o port address db dn ;physical unit no. db inter ;hardware interleave db secs ;sectors per track dw mxcl ;last cylinder db mxhd ;last head db hstsiz/128 ;sector size/128 db stprt ;step rate .xall endm dsktyp macro dn,typ .lall .sfcond if typ eq ST503 hpb&dn macro no dw -1,hdesc&dn als&no defl 004Ch ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,607,511,240,0,0,1,%dn hdscg %dn,152,1,3 endm hddr&dn defl 1 endif if typ eq ST506 hpb&dn macro no dw -1,hdesc&dn als&no defl 0098h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1215,511,240,0,0,1,%dn hdscg %dn,152,3,3 endm hddr&dn defl 1 endif if typ eq TM601S hpb&dn macro no dw -1,hdesc&dn als&no defl 004Ch ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,607,511,240,0,0,1,%dn hdsc %dn,152,1,3 endm hddr&dn defl 1 endif if typ eq TM602S hpb&dn macro no dw -1,hdesc&dn als&no defl 0098h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1215,511,240,0,0,1,%dn hdsc %dn,152,3,3 endm hddr&dn defl 1 endif if typ eq TM603S hpb&dn macro no dw -1,hdesc&dn als&no defl 00E4h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1823,1023,255,0,0,1,%dn hdscg %dn,152,5,3 endm hddr&dn defl 1 endif if typ eq TM603SE hdpb603E0&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,229,5,3 endm hdpb603E1&dn macro no als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,699,511,240,0,0,172,%dn endm hpb&dn macro no local x x defl no hdpb603E0&dn %x x defl x+1 hdpb603E1&dn %x endm hddr&dn defl 2 endif if typ eq TM501 hpb&dn macro no dw -1,hdesc&dn als&no defl 0099h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1219,511,240,0,0,1,%dn hdscg %dn,305,1,3 endm hddr&dn defl 1 endif if typ eq TM502 hdpb5020&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,305,3,3 endm hdpb5021&dn macro no als&no defl 0031H ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,391,511,240,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb5020&dn %x x defl x+1 hdpb5021&dn %x endm hddr&dn defl 2 endif if typ eq TM503 hdpb5030&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,305,5,3 endm hdpb5031&dn macro no als&no defl 00CAH ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1611,1023,255,0,0,172,%dn endm hpb&dn macro no local x x defl no hdpb5030&dn %x x defl x+1 hdpb5031&dn %x endm hddr&dn defl 2 endif if typ eq SA602 hpb&dn macro no dw -1,hdesc&dn als&no defl 0050h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,635,511,240,0,0,1,%dn hdscg %dn,159,1,3 endm hddr&dn defl 1 endif if typ eq SA604 hpb&dn macro no dw -1,hdesc&dn als&no defl 009Fh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1271,511,240,0,0,1,%dn hdsc %dn,159,3,3 endm hddr&dn defl 1 endif if typ eq SA606 hpb&dn macro no dw -1,hdesc&dn als&no defl 00EFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1907,1023,255,0,0,1,%dn hdscg %dn,159,5,3 endm hddr&dn defl 1 endif if typ eq SA1002 hpb&dn macro no dw -1,hdesc&dn als&no defl 0080h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1019,511,240,0,0,1,%dn hdscg %dn,255,1,0 endm hddr&dn defl 1 endif if typ eq SA1004 hpb&dn macro no dw -1,hdesc&dn als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2039,1023,255,0,0,1,%dn hdscg %dn,255,3,0 endm hddr&dn defl 1 endif if typ eq Q2010 hpb&d macr no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,2043,1023,255,0,0,1,%dn hdscg %dn,511,1,0 endm hddr&dn defl 1 endif if typ eq Q2020 hdpb20&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,3 1,1,2047,1023,255,0,0,1,%dn hdscg %dn,511,3,0 endm hdpb21&dn macro no als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2039,1023,255,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb20&dn %x x defl x+1 hdpb21&dn %x endm hddr&dn defl 2 endif if typ eq Q2030 hdpb30&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,511,5,0 endm hdpb31&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,172,%dn endm hdpb32&dn macro no als&no defl 00FEh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2031,1023,255,0,0,343,%dn endm hpb&dn macro no local x x defl no hdpb30&dn %x x defl x+1 hdpb31&dn %x x defl x+1 hdpb32&dn %x endm hddr&dn defl 3 endif if typ eq Q2040 hdpb40&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,511,7,0 endm hdpb41&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,255,0,0,129,%dn endm hdpb42&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,255,0,0,257,%dn endm hdpb43&dn macro no als&no defl 00FEh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2031,1023,255,0,0,385,%dn endm hdpb4021&dn macro no als&no defl 00DFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1783,1023,255,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb40&dn %x x defl x+1 hdpb41&dn %x x defl x+1 hdpb42&dn %x x defl x+1 hdpb43&dn %x endm hddr&dn defl 4 endif if typ eq M4010 hpb&dn macro no dw -1,hdesc&dn als&no defl 00F0h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1915,1023,255,0,0,1,%dn hdscg %dn,479,1,0 endm hddr&dn defl 1 endif if typ eq M4020 hdpb4020&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,480,3,0 endm hdpb4021&dn macro no als&no defl 00DFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1783,1023,255,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb4020&dn %x x defl x+1 hdpb4021&dn %x endm hddr&dn defl 2 endif hdldrvs defl hdldrvs+hddr&dn .lfcond .xall endm x defl 0 rept hddsks dsktyp %x,hd%x ;define hard disk parameters x defl x+1 endm ; ; dskhdr macro dn ; define a single disk header list .lall hdph&dn: dw 0000h,0000h ;translate table dw 0000h,0000h ;scratch area dw dirbuf,dpb&dn ;dir buff,parm block dw 0000h,0000h ;check, alloc vectors .xall endm ; hddisks macro nd ; define nd disks ndisks defl nd ;for later reference dpbase equ $ ;base of disk parameter blocks ; generate the nd elements dsknxt defl nmbfpy rept nd dskhdr %dsknxt dsknxt defl dsknxt+1 endm endm ; lgdrvs defl 0 ; hdpbs macro dn,lgno hpb&dn lgno lgdrvs defl hddr&dn endm ; hddpbs macro times ;define hard disk parameter blocks local x,y x defl 0 y defl nmbfpy rept times hdpbs %x,%y ;define dpb's for this hd drive endm x defl x+1 ;bump counters y defl y+lgdrvs endm ; ddb macro data,comm ; define a db statement db data comm endm ; ddw macro data,comm ; define a dw statement dw data comm endm ; defds macro lab,space lab: ds space endm ; lds macro lb,dn,val size defl val&dn defds lb&dn,%size endm ; ; logdsk defl nmbfpy endif ;hard disk definitions .lfcond fdskhdr macro dn .lall fdph&dn: dw trans,0,0,0 dw dirbuf,fdpbase dw 0000h,0000h .xall endm fdisks macro x defl 0 rept nmbfpy fdskhdr %x x defl x+1 endm endm dwdsk macro drvr,lgdsk dw drvr+lgdsk endm DSKTBL MACRO ;DEFINES DISK ASSIGNMENT TABLE x defl 0 .lall drvtbl equ $+1 .xall if fpyfrst dw fpy rept nmbfpy-1 dwdsk fpy,%x x defl x+1 endm ;rept y defl 0 rept hdldrvs dwdsk hdc,%x iff y ;if first time thru x defl 0 ;reset x for hard disk logical drives starting at 0 y defl y+1 else x defl x+1 endif endm ;rept else ;fpyfrst dw hdc rept hdldrvs-1 dwdsk hdc,%x x defl x+1 endm ;rept y defl 0 rept nmbfpy dwdsk fpy,%x iff y ;if first time thru x defl 0 ;reset x for hard disk logical drives starting at 0 y defl y+1 else x defl x+1 endif endm ;rept endif ddb %x,<;last logical drive> rept 16-nmbfpy-hdldrvs dw 0 endm ;rept endm ;dsktbl SUBTTL BIOS ENTRY AND PUBLIC TABLES page ; ; BIOS jump table start:: ret ;no cold boot dw 0 ret ;no warm boot dw 0 jp pserin jp serin jp serout ret ;no list dw 0 ret ;no punch dw 0 ret ;no reader dw 0 jp home jp seldsk jp settrk jp setsec jp setdma jp read ret ;no write dw 0 ret ;no list status dw 0 jp sectran SUBTTL Console drivers page ; ; Console drivers ; All have entry A=driver number, other parameters per CP/M ; A=0 serial port 0; A=1 serial port 1 pserin:: ;poll serial in-return A=0ff if char ready, else 0 add A,A inc A ;A=command port ld C,A in A,(C) and 1 ret z ;no character waiting ld A,0ffh ret serin:: ld B,A call pserin ld A,B jr z,serin ;loop until character received add A,A ld C,A in A,(C) and 7fh ;mask high order bit ret serout:: ld B,C ;character to output add A,A inc A ld C,A serst:: in A,(C) and 4 jr z,serst dec C out (C),B ret ; miscellaneous character i/o routines pmsg:: ;equivalent to BDOS function 9 (print) ld A,(DE) cp '$' ret z ld C,A inc DE push DE xor A call serout pop DE jr pmsg phex:: ;print A in hex push AF rra rra rra rra call hex1 pop AF hex1:: and 0fh add A,90h daa adc A,40h daa ld C,A xor A jp serout ; ; setdma:: ld (iodma),BC ;shared among all drivers ret ; ; Sectran input:: Logical sector in BC, translate table in DE ; no translation if DE=0 ; ; Returns physical sector in HL ; Note:: only used in single density sectran:: ld A,D or E ld L,C ld H,B ret z ;no sector translation ex DE,HL add HL,BC ld L,(HL) ld H,0 ret SUBTTL Floppy disk driver module page ; ; Floppy disk drive driver module ; .sfcond iff hard ;if not hard disk .lfcond dskparm:: ;disk hardware parameter block ;one block for each drive rept nmbfpy if (mini and not special) db 1 ;single sided double density  else db 0 ;density - 0=single D; 1=1 side, Double D; 2= 2S 2D endif db seekrate ;seek rate - 0=3ms, 1=6ms, 2=10ms, 3=15ms if (mini and not special) db ddpspt else db 26 ;physical sectors per track - 26 in SD, ddpspt in DD endif db 0 ;track drive currently set at endm page ; ; CP/M disk tables fDPHbase:: fdisks ; defind disk parameter headers for floppys page ; ; DPB's for the three formats of disk:: ; ; 8" Single sided, single density ; 5" Single sided, double density ; 5" Double sided, double density ; fdpbase:: sssddpb:: ;single density (1K block) dw 26 ;sectors per track db 3 ;block shift (log2[block size/128]) db 7 ;block mask ([block size/128]-1) db 0 ;extent mask dw 242 ;highest block on disk (numbered from 0) dw 63 ;directory entries-1 db 0c0h ;alloc0 -first two bits for two blocks for Dir db 0 ;alloc1 dw 16 ;checked directories dw 2 ;track offset (system tracks) page ssdddpb:: ;single sided double density dw 8*ddpsp t ;128 byte sectors per track db 4 db 0fh db 0 dw (tracks*ddpspt/2)-1 ;each of 76 tracks has ddpspt/2 2K blocks if mini dw 63 db 80h else dw 127 db 0c0h endif db 0 dw 32 dw 1 dsdddpb:: ;double sided double density dw 16*ddpspt ;one track consists of both sides db 4 db 0fh db 0 dw (tracks*ddpspt)-1 ;each of 76 tracks has ddpspt 2K blocks if mini dw 127 db 0c0h else dw 255 db 0f0h endif db 0 dw 32 dw 1 page trans:: ;single density translate table db 1,7,13,19,25,5,11,17,23,3,9,15,21 ;sectors 1-13 db 2,8,14,20,26,6,12,18,24,4,10,16,22 ;secotrs 14-16 home:: ld C,0 settrk:: ld A,C ld (iotrk),A ret setsec:: ld A,C ld (iosec),A ret page ; ; Fseldsk selects the physical floppy in A (0-3) ; B=0 if last disk selected was a different floppy ; C=logical disk the floppy corresponds to seldsk:: ld D,0 ;physcial floppy ld E,C ;save logical disk call getden ;will set density byte if successful or A jr nz,fbadsel ;couldn't get density ;all physical operations OK here ld (hwptr),IX ;store for later use ld A,(IX+density) inc A ;make 1-3 ld B,A ld HL,fdpbase-dpblen ld DE,dpblen fgetdpb:: add HL,DE djnz fgetdpb ;HL=DPB address ld C,L ld B,H ld HL,fdphbase ld A,(IX+density) or A jr z,setran ;single density,set translate vector xor A ld (HL),A inc HL ld (HL),A jr putdpb setran:: ld DE,trans ;single density translate table ld (HL),E inc HL ld (HL),D putdpb:: ld DE,9 ;offset of DPB in DPH add HL,DE ld (HL),C inc HL ld (HL),B dec HL dec HL sbc HL,DE ;restore DPH (carry reset by or A) ret fbadsel::ld HL,0 ret ;return error page ; ; Seldrv selects the drive , head from (head) ; (bit 0 set for head1), and density from (IX+density) ; it assembles the correct byte and outputs to wait ; and updates the track register with the most recent information seldrv:: ld A,(IX+density) or A jr z,setdens ld A,00001000b ;set double density bit ld B,A ld A,(head) rlca rlca ;move head bit to bit 2 or B setdens:: ld B,A out (wait),A ld A,(IX+drvtrk) ;get track from parameter table ;this may be first physical i/o out (trk),A ret page ; ; Seek attempts to step the R/W head to the track in (iotrk) ; seek:: ld A,retries ld (retryc),A seek2:: ld A,(iotrk) ld C,A ;track stays in C in A,(trk) sub C ret z ;already there ld A,C out (data),A ld A,(IX+seekrt) ;seek rate mask or 1ch ;seek with verify di out (cmd),A in A,(wait) ei rla jr c,seekerr ;no INTRQ from FDC in A,(cmd) and 10011001b ;seek error, CRC error, or incomplete jr nz,seekerr ;seek successful ld (IX+drvtrk),C ret seekerr:: ld E,1ch ;seek command call diskerror jr seek2 page ; ; Read reads the sector from the selected disk ; In double density, the sector may already be in the host buffer ; read:: ld IX,(hwptr) ;restore parameter pointer ld A,(IX+density) ;density byte or A jr z,rdsngl ;singl density call inbuf jr c,rddbl ;sector not in buffer ; sector is in buffer movrd:: call mkbufad ;HL=start of sector in buffer ldir ret ;transfer done rddbl:: call sidesec call readprep or A ret nz jr movrd rdsngl:: ld A,(iosec) ld (psec),A ;physical sector same as CP/M sector ;in single density readprep:: ld A,0A2h ;second byte of INI instruction ld (iotran+1),A ;patch rdwrite routine ld A,08ch ;sector read command ld (oper),A page strtsel:: call seldrv ;physically select drive and head call seek ;step to correct track ; ; diskio actually reads or writes the necessary sector ; it assumes that the head has already settled on the correct track ; (and that the head has been selected on the correct side!) ; and that the bytes in rdwrite for R/W and sector size have been filled diskio:: ld A,retries ld (retryc),A iotry:: ld A,0d0h ;force interrupt no conditions out (cmd),A ld A,(oper) ld B,A ld C,data ;prepare for indirect I/O instruction ex (SP),HL ;waste some time ex (SP),HL ex (SP),HL ex (SP),HL di ;no interrupts from here to end of transfer in A,(cmd) and 20h ;bit 5=head loaded rrca rrca rrca ;move bit 5 to bit 2 cpl and B ; the purpose of these manipulations has been ; to set bit 2 of the FDC command if the head ; isn't settled. Bit 2 will give a 15 ms delay ld E,A ld A,(IX+density) or A ld D,1 ;one sector i/o transfer for single denisty jr z,dmasingl ;use the CP/M DMA buffer in single density ld HL,hstbuf ;use host buffer for double density operations ld D,hstcnt ;number of 128 byte units to transfer jr strtio dmasingl:: ld HL,(iodma) strtio:: ld A,(psec) out (sec),A ;set physical sector ld A,E out (cmd),A ;start read/write operation call rdwrite ;do the actual i/o in A,(cmd) ei ;now ok to interrupt-status is saved ld E,A ;save status or B ;B returned from rdwrite is lost bytes count ret z ;if status OK and no lost bytes call diskerror call seek or A jr z,iotry ;if nonzero then hopeless seek error ret ; ; rdwrite does the actual transfer to/from the FDC ; HL set to DMA address on entry, D=number of 128 byte units to transfer ; transfer direction has been set by poking INI or OUTI instruction rdwrite:: ld B,128 ;bytes in one CP/M sector loop:: in A,(wait) or A ret p ;no more DRQ iotran:: ini ;start with read ;the second byte of this instruction is patched to ;be either INI or OUTI depending on need jr nz,loop dec D jr nz,rdwrite jr loop ;sector done, wait for INTRQ from fdc page ; ; disk error will eventually have all kinds of nice messages ; diskerror:: ld A,(retryc) dec A jr nz,restore ;more retries to attempt ld A,E cp 1ch ;was it a seek error? jr z,pseekerr cp 0ach ;writing? jr z,pwriterr ld DE,rderr jr perrtyp pwriterr:: ld DE,wrterr jr perrtyp pseekerr:: ld DE,skerr perrtyp:: call pmsg ld DE,trkerr  call pmsg ld A,(iotrk) call phex ld DE,secerr call pmsg ld A,(psec) call phex ld DE,siderr call pmsg ld A,(head) call phex pdrv:: ld DE,drverr call pmsg ld DE,crlf call pmsg ld A,255 ret page ; ; Restore is called from a disk operation with A=retries left ; restore:: ld (retryc),A in A,(cmd) and 00010000b ;bit 4=record not found ret z ;try again if record was found but ;read/written with error resto1:: ;restore to track 0 and seek again ld A,(IX+seekrt) ;get seek rate mask or 00001100b ;head load, restore, verify track 0 out (cmd),A tk0wait:: in A,(cmd) and 00000100b ;at track 0 jr z,tk0wait xor A out (trk),A ;back at track 0 ld (IX+drvtrk),A ;update track table ret page ; ; sidesec is the read/write preparation for double density ; sidesec computes the correct physical sector and side ; sidesec:: ld A,(iosec) and not(hstcnt-1) ;computer first CP/M sector in block ld (blksec),A sideflsh:: ;called to set up for a flush rept hstshft rrca endm ;A=physical sector number, but it may ;be on the second side ld B,(IX+pspt) cp B ld C,0 jr c,side0 sub B inc C side0:: inc A ld (psec),A ;physical sector on one side ld A,C ld (head),A ;set head control byte ret page ; ; inbuf returns carry flag set if sector not in buffer ; also returns (iosec) in D ; if sector is in buffer, returns offset (0 - hstcnt-1) in A ; inbuf:: ld A,(iosec) ld D,A ld A,(bufvalid) ;0 if contains valid data, else 255 rra ret c inbuf2:: ld HL,(iodrvtrk) ;check for 2nd sector ;of unallocated block ld BC,(blkdrvtrk) sbc HL,BC ;same drive and track jr z,rttrk scf ret ;not a match rttrk:: ld A,(blksec) ld B,A ld A,D sub B ret C ;sector lower # than buffer cp hstcnt ;carry set if in buffer ccf ret ; stores drive, track, sector of contents of buffer for use by flush ; also saves hardware pointer and sets buffer valid flag ; returns HL=start  of sector in buffer, DE=DMA address, BC=128, A=0 mkbufad:: ld (blkptr),IX ld HL,(iodrvtrk) ld (blkdrvtrk),HL ld A,(iosec) ld B,A and not(hstcnt-1) ld (blksec),A ld A,B and hstcnt-1 ld B,A ;B=relative sector in buffer inc B ld HL,hstbuf-128 ld DE,128 shft2:: add HL,DE djnz shft2 ld BC,128 ;make ready for sector LDIR ld DE,(iodma) xor A ld (bufvalid),A ret page ; ; returns IX=start of DHPB (disk hardware parameter block) for ; the drive in A (0-3) ; uses B,DE also, returns D=0 getparm:: ld B,A inc B ld IX,dskparm-parmlen ;hardware parameter block ld DE,parmlen shft1:: add IX,DE djnz shft1 ret page ; ; Getden attempts to find the density of the disk in drive (D) ; by trying to read the current track address in both densities ; If the attempt is successful, Getden will update the ; dens, pspt, and drvtrk fields of the paramter table ; If E (logical disk) is zero, then getden assumes the density hasn't ; changed (if it has, then we can't do a warm boot-table is wrong getden:: ld A,0d0h ;reset FDC out (cmd),A ld A,D and 7fh call getparm ld A,(7fh) ;code byte for disk type OR A jr z,codeok ;some SD disks have old loaders here sub 0e5h ;code for a normal single density disk cp 3 jr c,codeok ld DE,badcode ;not our code byte call pmsg call pdrv ld A,255 ret codeok:: ld (IX+density),A or A jr z,snglspt ld A,ddpspt ;physical sectors on one side of DD jr putpspt snglspt:: ld A,26d ;single density physical sectors putpspt:: ld (IX+pspt),A xor A ret ;no errors logdin::call getparm ld A,(IX+density) jr codeok ; drive can't change density else ;iff hard SUBTTL Hard disk drivers page .lfcond ; ; Hard disk drive driver module ; ; ; CP/M Hard disk tables ; hDPHbase:: hddisks hdldrvs ;set up disk parameter headers ; ; DPB's for HARD DISKS ; ; hdpbase equ $+4 hddpbs hddsks ;set up disk parameter blocks page home:: ld BC,0 ;force track 0 settrk:: ld (hdiotrk),BC ;save track number ret setsec:: ld (hdiosec),BC ;save sector number ret ; ; Hseldsk selects the hard disk seldsk:: ld HL,hdphbase ;add in base address ret ; and go ; ; Seldrv selects the drive from (curhdsk), head from (hhead) ; it assembles the correct byte and outputs it ; and updates the track register with the most recent information hseldrv:: ld A,(hhead) ;get head or 20h ;set sector size to 512 bytes out (sdh),a ;send to controller ret page ; ; Seek sets head to the track in (hdiotrk) ; and sector to (hpsec), sector count to one ; hseek:: ld a,(hdiotrk) ;send low order byte of track out (cyllo),a ld a,(hdiotrk+1) ;send high byte out (cylhi),a ld A,(hpsec) ;send physical sector out (secno),A ld A,1 ;set sector count out (secnt),A ret page ; ; Read reads the sector from the selected disk ; it handles any necessary buffering ; read:: call hinbuf ;is it in the buffer jr c,hrd ;sector not in buffer  ; sector is in buffer hmvrd:: call hmkbfad ;HL=start of sector in buffer ldir ret ;transfer done hrd:: call hsidselc call hrdprep or A ret nz jr hmvrd ; ; read preperation ; hrdprep:: call hseldrv ;physically select drive and head call hseek ;step to correct track ; ; this actually reads the necessary sector ; it assumes that the head has already settled on the correct track ; (and that the proper head has been selected) ld HL,hstbuf ;point to buffer ld BC,hdcdata ;count and port di ;protect transfer ld A,cread ;send read command out (comnd),A hrdw:: in A,(status) ;done yet and A jp m,hrdw ;if not wait inir ;256 bytes twice inir ei in A,(status) and 1 ;any errors ret z ;return if not ; page ; ; hard disk error message processor ; ; This routine gives the user a detailed error report ; herrors:: push AF ;save error indication ld DE,herrst CALL pmsg ; First the error code IN A,(HDCERR) CALL phex ld DE,errhd CALL pmsg ; then the head IN A,(SDH) push AF ;save drive no AND 7 CALL hex1 ; Print single digit ld DE,errcyl CALL pmsg ; the cylinder IN A,(CYLHI) ; Report CYLHI first CALL phex IN A,(CYLLO) ; then CYLLO CALL phex ld DE,errsec CALL pmsg ; and finally the sector IN A,(SECNO) CALL phex ld DE,errdr ;send drive mess call pmsg pop AF rlca ;get drive rlca rlca and 3 call hex1 ld A,crest ;restore drive out (comnd),A herrlp:: in A,(status) rlca jr c,herrlp ;wait until done po AF RET page ; ; hsidselc is the read/write preparation for hard disk ; hsidselc computes the correct physical sector and side ; hsidselc:: ld HL,(hdiosec) ld E,L ;save L ld A,L and not(31) ;compute first cp/m sector in buffer ld L,A ld (hblksec),HL ;save it ld L,E ;restore sector to HL hflsdsc:: ;called to set up for a flush or a ;clear carry ld C,-1 ;set up head count ld DE,secs*4 ;set up number cpm sectors per head sdsclp: inc C ;increment head count sbc HL,DE ;subtract out one heads worth of sectors jp p,sdsclp ;if not negitive do more add HL,DE ;restore sector number to HL ld A,L srl A ;find physical sector srl A ld (hpsec),A ld A,C ld (hhead),A ;set head control byte ret page ; ; hinbuf returns carry flag set if sector not in buffer ; if sector is in buffer, returns offset (0 - hdstcnt-1) in A ; hinbuf:: ld A,(bufvalid) ;0 if contains valid data, else 255 rra ret c hinbuf2:: ld A,(hiodrvtrk) ;check for right drive ld B,A ld A,(hblkdrvtrk) sub B jr z,rthdd ;skip if right drive scf ret ;wrong drive return with carry set rthdd:: ld HL,(hiodrvtrk+1) ;check for right track ld BC,(hblkdrvtrk+1) sbc HL,BC ;same drive and track scf ret nz ;not a match ld DE,(hblksec) ld HL,(hdiosec) ld A,D ;high bytes = cp H scf ;set failure flag ret nz ;exit if not equal ccf ;clear carry sbc HL,DE ret C ;sector lower # than buffer ld A,L cp hdstcnt ;carry set if in buffer ccf ret ; ; stores drive, track, sector of contents of buffer for use by flush ; also sets buffer valid flag ; returns HL=start of sector in buffer, DE=DMA address, BC=128, A=0 ; hmkbfad:: ld A,(hiodrvtrk) ld (hblkdrvtrk),a ld HL,(hiodrvtrk+1) ld (hblkdrvtrk+1),HL ld HL,(hdiosec) ld B,L ld A,L and not(hdstcnt-1) ld L,A ld (hblksec),HL ld A,B and hdstcnt-1 ld B,A ;B=relative sector in buffer inc B ld HL,hstbuf-128 ld DE,128 hshft2:: add HL,DE djnz hshft2 ld BC,128 ;make ready for sector LDIR ld DE,(iodma) xor A ld (bufvalid),A ret endif SUBTTL Floppy disk storage page ; ; Floppy disk driver storage ; bufvalid:: db 0ffh ;buffer contains valid data for (blksec) ;0 = valid data iodma:: ds 2 ;dma storage .sfcond iff hard ;if not hard .lfcond iodrvtrk:: curfpy:: db 0 ;current selected physical floppy drive iotrk:: ds 1 ;current track for current disk blkdrvtrk:: ds 2 ;drive and track for deblocking buffer iosec:: ds 1 ;current logical sector for DD, physical for SD blksec:: ds 1 ;first logical sector in current host blk2sec:: ds 1 ;8th CP/M sector in an unallocated 2K block psec:: ds 1 ;current physical sector wrtpend:: db 0 ;write pending from buffer retryc:: db 0 ;number of retries left newfpy:: db 0 ;new floppy to be selected head:: db 0 ;head control = 0 or 1 oper:: db 0 ;operation (read/write) to be performed next hwptr:: dw dskparm ;storage for pointer to current hw parameters blkptr:: dw dskparm ;pointer to paramters for block drive SUBTTL Hard disk storage page ; ; Hard disk driver storage ; else .lfcond hiodrvtrk:: curhdsk:: db 0 ;current selected physical hard disk drive hdiotrk:: ds 2 ;current track for current disk hblkdrvtrk:: ds 3 ;drive and track for deblocking buffer hdiosec:: ds 2 ;current logical sector hblksec:: dw 0 ;first logical sector in host buffer hunalsec:: dw  0 ;first logical sector in current host unallocated block unalcv:: db 0 ;unallocated block vector hpsec:: ds 1 ;current physical sector hwrtpnd:: db 0 ;write pending from buffer hhead:: db 0 ;head control endif SUBTTL Error messages page .sfcond iff hard .lfcond ; ; Floppy error messages ; badcode:: db 'Can''t recognize density of disk in$' rderr:: db 'Read$' wrterr:: db 'Write$' skerr:: db 'Seek$' trkerr:: db ' error on track $' secerr:: db ' sector $' siderr:: db ' side $' drverr:: db ' drive $' crlf:: db 0dh,0ah,'$' page ; ; Hard disk error messages ; else .lfcond herrst:: DB 0dH,0ah,'HD1001 Error $' errhd:: DB ' on Head $' errcyl:: DB ', Cylinder $' errsec:: DB ', Sector $' errdr:: db ', Drive $' endif SUBTTL Disk buffers and Cold Boot code page ; ; disk buffers ; These are not part of the floppy driver module as such and ; should be shared by all disk modules as much as possible dirbuf:: hstbuf equ dirbuf+128 ;sector deblocking buffer ; ; lastadd equ $ SUBTTL SYMBOLS end  q :r(8 C s!0:0DM)) )oN$=3))g 08  2e8 :eYi  ʬP Ó @!s6#¹*f&"k:gG_!s}/o|/g#"ox/o&#"ms*o*mx*k:g> > G>G:e2e*hh:jWzY:g}|:e>P!s>Oy nڋ79+|2 *h:j_:g=WhKyYBx}|:e>  P Y PP P h7 +| Ó ( ʡYƐ'@'_ |P}P & 1ADVANCED DIGITAL CORPORATION HDC1001 Hard Disk Controller Formatter Select disk type from following menu *** Hard Disk selection choices *** 0 = ST503 ; Seagate Technology ST503 1 = ST506 2 = TM601S ; Tandon Magnetics TM601S 3 = TM602S 4 = TM603S 5 = TM603SE 6 = TM501  ; Tandon Magnetics TM501 7 = SA602 ; Shugart Associates SA602 8 = SA604 9 = SA606 10 = SA1002 ; Shugart Associates SA1002 11 = SA1004 12 = Q2010 ; Quantum Q2010 13 = Q2020 14 = Q2030 15 = Q2040 ? $ Invalid input try again. $ Which physical hard disk do you want to format. (0-3)? $ This operation will destroy all data on drive $. Hit return to continue or ^C to abort.$ Formatting. CYLINDER HEAD $$ Verifying. CYLINDER HEAD $ HDC1001 Error $ on Head $, Cylinder $, Sector $ Format completed.$Sorry, unrecoverable error during format.$ Operation aborted.$@ Disk Controller Formatter Select disk type from following menu *** Hard Disk selection choices *** 0 = ST503 ; Seagate Technology ST503 1 = ST506 2 = TM601S ; Tandon Magnetics TM601S 3 = TM602S 4 = TM603S 5 = TM603SE 6 = TM501  for interrupt input must be power of 2 outbfsz equ 64 ;size of output buffer for interrupt output must be power of 2 public savnum,biosiz,mxld64k,kld64k,syssiz,ldofst,allfpy,lastadd SUBTTL Hard disk equates page ;*** HDC1001 Disk equates *** HOFF EQU 1 ; Number of reserved tracks for loader TST MACRO DN ;physical hard disk defined IF HD&DN x defl 1 else x defl 0 endif endm hddsks defl 0 ;number of physical hard disk drives hdldrvs defl 0 ;number of logical hard disk drives hdtst macro rept 4 tst %hddsks ;test all four physical drives iff x exitm endif .lall hddsks defl hddsks+1 .xall endm ;end rept endm ;end hdtst hdtst ;calculate number of physical hard disks if hddsks ;set flag for hard disks hard equ true else hard equ false fpyfrst defl true ;force floppies first if no hard disks endif ; ddb macro data,comm ; define a db statement db data comm endm ; ddw macro data,comm ; define a dw statement dw data comm endm ; defds macro lab,space lab: ds space endm ; lds macro lb,dn,val size defl val&dn defds lb&dn,%size endm .sfcond if hard ;put this stuff in only if needed .lfcond ;*** Port equates for HDC1001 *** HDCBASE EQU 0E0H ; Base of HDC1001 HDCDATA EQU HDCBASE ; Data port WPC EQU HDCBASE+1 ; Write precomp port HDCERR EQU WPC ; Error port SECNT EQU HDCBASE+2 ; Sector count SECNO EQU HDCBASE+3 ; Sector number CYLLO EQU HDCBASE+4 ; Cylinder low CYLHI EQU HDCBASE+5 ; Cylinder high SDH EQU HDCBASE+6 ; Size/Drive/Head COMND EQU HDCBASE+7 ; Command register STATUS EQU COMND ; Status register ;*** Command equates for HDC1001 *** CREST EQU 10H ; Restore command CSEEK EQU 70H ; Seek command CREAD EQU 20H ; Read sector command CWRITE EQU 30H ; Write command CFORM EQU 50H ; Format track inter equ 8 ;hard disk sector interleave factor secs equ 16 ;Physical sectors per track per head hstsiz equ 512 ;size of a hard disk physical sector hdstcnt equ hstsiz/128 ;cp/m sectors per physical sector blksiz equ 4096 ;cp/m block size cpmspt equ hdstcnt*secs ;cp/m sectors per track per head cpmscbk equ blksiz/128 ;cp/m sectors per cp/m block ; dpbg macro dn,secs,bls,blm,ext,dks,dir,al0,al1,cks,off,phys .lall dpb&dn: dw secs ;sec per track db bls ;block shift db blm ;block mask db ext ;extnt mask dw dks ;disk size-1 dw dir ;directory max db al0 ;alloc0 db al1 ;alloc1 dw cks ;check size dw off ;offset db phys ;physical disk drive .xall endm hdscg macro dn,mxcl,mxhd,stprt .lall hdesc&dn: db hdcbase ;base i/o port address db dn ;physical unit no. db inter ;hardware interleave db secs ;sectors per track dw mxcl ;last cylinder db mxhd ;last head db hstsiz/128 ;sector size/128 db stprt ;step rate .xall endm dsktyp macro dn,typ .lall .sfcond if typ eq ST503 hpb&dn macro no dw -1,hdesc&dn als&no defl 004Ch ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,607,511,240,0,0,1,%dn hdscg %dn,152,1,3 endm hddr&dn defl 1 endif if typ eq ST506 hpb&dn macro no dw -1,hdesc&dn als&no defl 0098h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1215,511,240,0,0,1,%dn hdscg %dn,152,3,3 endm hddr&dn defl 1 endif if typ eq TM601S hpb&dn macro no dw -1,hdesc&dn als&no defl 004Ch ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,607,511,240,0,0,1,%dn hdsc %dn,152,1,3 endm hddr&dn defl 1 endif if typ eq TM602S hpb&dn macro no dw -1,hdesc&dn als&no defl 0098h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1215,511,240,0,0,1,%dn hdsc %dn,152,3,3 endm hddr&dn defl 1 endif if typ eq TM603S hpb&dn macro no dw -1,hdesc&dn als&no defl 00E4h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1 823,1023,255,0,0,1,%dn hdscg %dn,152,5,3 endm hddr&dn defl 1 endif if typ eq TM603SE hdpb603E0&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,229,5,3 endm hdpb603E1&dn macro no als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,699,511,240,0,0,172,%dn endm hpb&dn macro no local x x defl no hdpb603E0&dn %x x defl x+1 hdpb603E1&dn %x endm hddr&dn defl 2 endif if typ eq TM501 hpb&dn macro no dw -1,hdesc&dn als&no defl 0099h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1219,511,240,0,0,1,%dn hdscg %dn,305,1,3 endm hddr&dn defl 1 endif if typ eq TM502 hdpb5020&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,305,3,3 endm hdpb5021&dn macro no als&no defl 0031H ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,391,511,240,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb5020&dn %x x defl x+1 hdpb5021&dn %x endm hddr&dn defl 2 endif if typ eq TM503 hdpb5030&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,305,5,3 endm hdpb5031&dn macro no als&no defl 00CAH ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1611,1023,255,0,0,172,%dn endm hpb&dn macro no local x x defl no hdpb5030&dn %x x defl x+1 hdpb5031&dn %x endm hddr&dn defl 2 endif if typ eq SA602 hpb&dn macro no dw -1,hdesc&dn als&no defl 0050h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,635,511,24 Regenerating the SUPERBIOS for a different memory size Th SUPERBIO normall reside i 61 CP/ syste wit 6 ˠ o RAM Th extr 3 come fro th fac tha th BIOӠ i relatively large and includes a 1Kbyte deblocking buffer. 1) Assemble SUPRBIOS.MAC with M80 (Microsoft Macro-80). 2 Determin th lin addres fo th BIOS Th standar SUPERBIO i org' a EE00H Calculat you highes RA addres availabl t th SUPERBIO an subtrac 1200 tge th lin address Example syste ha 2 memory-mappe vide boar residing at F800H-FFFFH. F800h-1200H = E600H for the SUPERBIOS. 3 Us Microsoft-compatibl linke (LINK L80 LINKMT etc t lin SUPRBIOS.REL LIN wil generat a offse .CO͠ file while with L80 you get a .HEX file. LINK: L80: LIN SUPRBIOS[LE600 L8 /P:E600,SUPRBIOS,SUPRBIOS/N/X/E 4 Creat relocate CP/ usin patche MOVCP͠ a pe Digital Research note. MOVCPM 59 * SAVE 34 CPM59.COM 5) Integrate the new BIOS and CP/M into the CPM.SYS file. DDT CPM59.COM NEXT PC 2300 0100 -M980,1F7F,10 (Mov th CC an BDOӠ t 100Ƞ) if using an offset .COM file (better alternative!) -ISUPRBIOS.COM -R1600 i usin .HE fil (bes t avoid calculat th offse t mak the .HEX file load at 1700. Load address = E600H, offset =1700H-EA00H = 3100H -ISUPRBIOS.HEX -R2E00 .pa Mak sur yo rea th BIO i correctl - 1700 shoul b th BIO jum table. -G0 A>ERA CPM.SYS A>SAV 34 CPM.SY (I yo hav modifie th BIO yo mus sav howeve man page ar necessar t includ th BIO i th .SY file Ther ar 22 pages to the CCP and BDOS portions of CPM.SYS) Th ne dis shoul b bootabl i i ha ha th loade SYSGEN' on it.  Creatin bootabl SUPERBIO dis fo customer wh alread ow CP/M 1 Patc you cop o MOVCPM.CO a describe i th attache Digita Researc Note Thi i necessar becaus th SUPERBIO use secto blocking/deblockin algorith (differen tha th Digita Researc algorithm tha use th director writ cod i t flus dis buffer afte fil closing. 2) Make a copy of your SUPERBIOS distribution disk to work on. Do PIP B:=*.*[vo] then use SYSGEN to transfer the loader. 3 Pu th cop o o th SUPERBIO distributio dis i you secon flopp driv (B:) an you curren CP/ syste dis (wit th patche MOVCPM.COM i th firs flopp driv (A:). 4) Run MOVCPM and DDT to create a system file. A>MOVCP 61 61 i th norma syste siz ) CONTSTRUCTING 61K CP/M V2.2 READY FOR "SYSGEN" OR "SAVE 34 CPM61.COM" A>SAVE 34 B:CPM61.COM A>B: B>A:DDԠ CPM61.CO Us you DD t brin iCP/M ) NEXT PC 2300 0100 -M980,1F7F,100 ( Move the CCP and BDOS to 100H ) -ICPM.SYS -R1600 ( The CPM.SYS file has the BIOS image ) -M2D00,3700,1700 ( Move the new BIOS to 1700H ) -l1700,1702 ( Make sure move went OK ) 1700 JMP FA00 -G0 ( Exit and save ) B>ERA CPM.SYS B>SAVE 34 CPM.SYS 5 Yo no hav bootabl syste dis equivalen t thos sen to customers who have purchased CP/M from Advanced Micro Digital.  SUPERBIOS distribution diskette contents: CPM.SYS i memor imag o CP/͠ wit th SUPERBIOS Customer wh hav no purchase CP/ fro Advance Micr Digita wil receiv CPM.SY wit th CC an䠠 BDOӠ zeroe out Se堠 CPMINSTA.DOà fo installatio procedure. USER.DOC give basi informatio necessar fo th operatio o CP/ wit th SUPERBIOS a wel a descriptio o th content o al th .DO files- CPMINSTA.DOC NEWSIZE.DOC FORMAT.DOC INTRFACE.DOC SUPRBIOS.MAC i th sourc fil fo th SUPERBIOS I ca b edite䠠 an reassemble i modificatio o th SUPERBIOӠ i desired Th堠 procedur堠 fo incorporatin砠 ᠠ ne BIOӠ i describe䠠 i NEWSIZE.DOC. FORMAT.COM i th SUPERBIO flopp dis forma program I wil onl ru o th SUPE QUA SBC bu wil ru unde th previou BIOS Interna detail o th disk formats are described in FORMAT.DOC. LDRGEN.COM i th equivalen o SYSGEN.CO i norma CP/ system LDRGEN.CO͠ transfer th SUPERBIOӠ col star loade fro sourc (usuall disk t destination Detail o th loade operatio ar i LOADER.DOC. FORMAT.ASM is the source file for FORMAT.COM. SBCBOOT.ASM i th sourc fil fo th col loade o trac zer sector one, which is brought in by the monitor PROM. SBCBOOT.HEX i th assemble SBCBOOT.ASM fo installatio i customized loaders. LDRBDOS.MAC i th sourc fil fo th logica (non-hardwar dependent) portion of the loader. LDRBIOS.MAC i th sourc fil fo th hardwar driver t mak th loade wor wit th SUPE QUAĠ flopp dis controller. rmats are described in FORMAT.DOC. LDRGEN.COM i th equivalen o SYSGEN.CO i norma CP/ system LDRGEN.CO͠ transfer th SUPERBIOӠ col star loade fro sourc (usuall disk t destination Detail o th loade operatio ar i LOADER.DOC. FORMAT.ASM is the source file for FORMAT.COM. SBCBOOT.ASM i th sourc fil fo th col loade o trac zer sector one, which is brought in by the monitor PROM. SBCBOOT.HEX i th assemble SBCBOOT.ASM fo installatio i customized loaders. LDRBDOS.MAC i th sourc fil fo th logica (non-hardwar dependent) portion of the loader. LDRBIOS.MAC i th sourc fil fo th hardwar driver t mak th loade wor wit th SUPE QUAĠ flopp dis  TITLE ADVANCED DIGITAL HARD DISK SECTOR 0 BOOT FOR SUPER QUAD Oct 26 1982 13:30 ;***************************************************************** ;** ** ;** ADVANCED DIGITAL SUPER QUAD Z80 SBC ** ;** ** ;** HARD DISK BOOT ** ;** ** ;** This is the cold boot code to load the loader ** ;** from track 0 on the hard disk into memory ** ;** at 100h and run it. ** ;** ** ;** ** ;** Written by: ** ;** ** ;** Greg Lindberg ** ;** ** ;***************************************************************** if2 .printx /pass 2/ endif SUBTTL SYMBOLIC EQUATES page 60 .z80 ; ; Port equates for super quad ; memry equ 16h ;memory control port ; ;*** Port equates for HDC1001 *** ; HDCBASE EQU 0E0H ; Base of HDC1001 HDCDATA EQU HDCBASE ; Data port WPC EQU HDCBASE+1 ; Write precomp port HDCERR EQU WPC ; Error port SECNT EQU HDCBASE+2 ; Sector count SECNO EQU HDCBASE+3 ; Sector number CYLLO EQU HDCBASE+4 ; Cylinder low CYLHI EQU HDCBASE+5 ; Cylinder high SDH EQU HDCBASE+6 ; Size/Drive/Head COMND EQU HDCBASE+7 ; Command register STATUS EQU COMND ; Status register ; ;*** Command equates for HDC1001 *** ; CREST EQU 10H ; Restore command CSEEK EQU 70H ; Seek command CREAD EQU 20H ; Read sector command ; ; loader program ; start: ld A,6fh ;get command to memory port out (memry),A ;turn off prom ; ld BC,hdcdata ;get port number and transfer length ld HL,80h ;starting address ld DE,10 ;number of sectors to transfer ; loop: ld A,D ;send sector to controller out (secno),A ld A,cread ;send read command out (comnd),A swait: in A,(status) ;wait till done or A jp m,swait rra ;any errors jr c,herror ; inir ;get data inir ; inc D ;increment sector to read dec E ;decrement sector count jr nz,loop ;if more go do it jp 100h ;else go execute loader ; herror: ld A,4fh ;turn prom back on out (memry),A jp 0f030h ;return to monitor hard disk error return end  register STATUS EQU COMND ; Status register ; ;*** Command equates for HDC1001 *** ; CREST EQU 10H ; Restore command CSEEK EQU 70H ; Seek command CREAD EQU 20H ; Read sector command ; ; loader program ; start: ld A,6fh ;get command to memory port out (memry),A ;turn off prom ; ld BC,hdcdata ;get port number and transfer length ld HL,80h ;starting address ld DE,10 ;number of sectors to transfer ; loop: ld A,D ;send sector to controller out (secno),A ld A,cread ;send read command out (comnd),A swait: in A,(status) ;wait till done or A jp m,swait rra ;any errors jr c,herror ; inir ;get data inir ; inc D ;increment sector to read dec E ;decrement sector count jr nz,loop ;if more go do it jp 100h ;else go execute loader ; herror: ld A,4fh ;turn prom back on out (memry),A jp 0f030h ;return  CP/M MODEM PROGRAM DOCUMENTATION 05/18/82 Thi progra use th fil transfe routine writte b War Christense i hi CP/ fil transfe progra (V2. a o 8/6/79 an i compatabl wit hi progra i singl fil transfe mode Multi-fil transfer ar onl possibl betwee tw system runnin th progra describe below. This program has two functions: 1. Communication 2. Program transfer COMMUNICATIONS Th progra ma emulat termina o ech dat bac t sende (ac a computer). Terminal Mode - 'T' Option Th termina mod ma b calle wit o withou fil name I fil i specifie (i shoul b ne file) the anythin receive b th mode ma b save i memor an late writte o disk Th sav featur i toggle ON/OF b Control-Y colo (: wil b printe a th beginnin o eac lin whe memor sav i active Th colo wil no b transmitte ove th mode no wil i b save i memory. I fil i no specified the memor sav ca no b activated. I th memor buffe i ful (th buffe i fro th to o th progra t th botto o BDOS) th content ar automa- ticall writte t dis (bu th fil i no ye closed) Communication ma the continu wit th buffe reinitial- ized Th compute wit whic yo ar communicatin mus accep th X-O an X-OF (Control- an Control-S conven- tion o dat wil b lost. Whe communication ar over us Control- t exi fro th Termina mod an ente th Menu Th fil t whic yo ar  writin mus the b close b usin th 'WRT command I thi i no done al dat wil b lost decide no t clos th fil automaticall sinc ther wil b time whe yo leav termina mod an the decid t re-enter Thi ma b don whil i th Men b usin th 'RET command Yo ma re-ente Termina mod an sav i th sam fil a man time a yo wis a lon a yo hav no close th fil wit th 'WRT command. Whil i Termina mode Control- wil pu yo i Fil Transfe mode Thi wil allo yo t sen th content o a ASCIɠ fil ove th modem Thi routin doe n erro checkin an ther ar n protocol specifie betwee thi progra an th receivin compute othe tha tha i shoul b read t receiv dat vi th modem Control-ؠ wil cance th transfer. Computer mode - 'E' Option Thi mod echo dat receive b othe computer Onl on compute ma b i thi mod a on time Ther i n sav featur i thi mode Usefu i yo wis t communicat wit somebod runnin th termina portio o th program. File transfer - 'S' and 'R' Options Thes feature ar th sam a i th CP/͠ Mode progra writte b War Christense excep tha upo completio o th transfer contro return t th Men unles th secon- dar 'T optio ha bee selected I th latte case contro return t Termina mode Remembe tha i yo ar operatin remot compute usin timesharin progra (suc a War Christensen' "BYE") th remot shoul b instructe t sen o receiv i th quie (Q mod a secondar option Example o command fo sendin an re- ceivin ar liste below. Multi-file transfers Usin th (batch secondar option mor tha on fil an ambiguou filename ma b transferred T sen files us th primar optio "S an th secondar optio "B (alon wit an othe secondar options) T receiv th file bein sent us th "R primar optio an th "B secondar option File ma no b name sinc filename ar sen b th sendin program bu dis driv ma b specifie (o els th file ar writte t th defaul drive). Backup option Ther i byt a th beginnin o th progra (106H tha wil creat backu fil i fil o th dis ha th sam nam a th fil bein receive i multi-fil transfe (se MODEM.SET) I thi byt i se t 0FFH backu fil wil b created I i i zer th fil o th dis wil b delete befor th ne fil i received I yo ar runnin CP/͠ an fil o th dis i designate R/ o SYS backu wil b create whethe th byt a 106 i se o not. B carefu - i yo ar runnin CP/ an th driv o whic yo ar receivin ha a R/ fil wit th sam nam create b CP/ 2 th R/ fil ca no b accesse (found changed erased etc. b CP/ 1 Yo wil therefor hav tw file wit th sam nam whe yo ar runnin CP/ 2 T fi thi problem us CP/ t chang th nam o th fil tha i no R/O The us CP/ t d wha yo wan wit th R/ file. Examples: Th sende enter SB B:*.CO t sen al th CO file o dis B Als specifie wa retur t termina mod whe done. Th receive enter R t receiv al th file bein sen o th defaul drive. Th sende enter th comman S ASM.CO *.HE B:M*. whic wil sen ASM.CO fro th defaul drive al th HE file fro th defaul drive an al th file startin wit "M fro th drive. Multifil transfer ma onl b don fro th menu I ma no b specifie whe th MODE progra i called I othe word A>MODE͠ SA *.CO wil resul i a INVALIĠ OPTIO erro message. Return to Menu - 'M' option When asked to select an option, 'M' returns to Menu. The MENU I th Mode progra i entere wit n option th Men i called Th Men give th choic o selectin th standar option a define b War Christense (T E R an S) Th Termina mod ha bee greatl expande a describe above Th "R an "S command mus b calle wit filenam o yo wil b require t ente th primar comman ( o R an th filenam agai (bu NO th secondar options) I yo wan multi-fil transfers the th "R optio doe no nee filename. REԠ - Yo ma als ente termina mod usin th 'RET command bu n dat wil b save sinc fil ma no b name wit 'RET' Us th 'RET comman t RE-ENTE Termina mod afte i ha firs bee entere wit th 'T option I thi i done yo wil stil b abl t sav th communication i yo wer doin s befor yo exitte th termina mode. WR - Th 'WRT comman mus b use afte leavin Termina mode Thi write th las buffe t dis an close th file Failur t us th 'WRT comman result i los o al dat an fil o lengt zero. DE̠ - Th 'DEL comman erase th mos recen fil accesse i Termina mode Usefu i yo decid afte communication tha yo don' wan t sav informatio jus gathered. CPM - The 'CPM' command reboots and returns to CP/M. XPҠ - Th 'XPR comman i toggl whic cause th men t b printe o no printed Initiall th men i o unles th progra i calle wit th "X optio (ie A>MODE ). DIҠ - Th 'DIR comman list th director o CP/͠ disk driv ma b specifie (ie DI B: o th defaul driv wil b listed Afte th director i listed th men wil no b printe whethe XP mod i o o off I XP mod i o an yo wis t se th menu hi return. LISTING OF COMMANDS AND OPTIONS Primary options S - send a CP/M file (must specify file/s) R - receive a CP/M file (must name file unless B sec opt used) T - terminal mode (specify file if memory save wanted) E - terminal mode with echo M - return to menu X - used only when program is called to initially toggle menu off Secondary options B - multi-file mode for sending and receiving files T - return to terminal mode after transfer (memory save off) R - view what is received in file transfer S - view what is being sent in file transfer V - view what is being sent or received in file transfer T - Terminal mode (used with remotely controlled computer) EXAMPLES (fn = filename, ft = filetype) Send another file S fn.ft Receiv fil o drive vie wha i bein received retur t termina mod RRT B:fn.ft Sen al CO files n message o console SBQ *.COM Send two files from two different drives SB A:fn1.ft1 B:fn2.ft2 Receive files being sent by above on drive A RB A: Termina mode sav communicatio i file (i termina mus typ CTRL- t star save i men mus typ "WRT t clos file.) T fn.ft COMPUTER TO COMPUTER TRANSFERS T us thi progra fo transfe o file betwee tw compu- ter tha eac ar runnin thi progra an ar directl connecte togethe b a RS-23 seria lin i i necessar t b careful i connectin them Eac computer' sen dat lin mus b connecte t th other receiv dat line. EXAMPLE: pins pins /----------\ RS-232 CABLE /----------\ | |2____________________________________3| | | Computer | | Computer | | # 1 |3____________________________________2| # 2 | | | | | | |7____________________________________7| | \----------/ \----------/  SUPRBIOS loader operation Th SUPERBIO make us o syste fil loade t brin th syste int memor o col boot Th loade i allowe t b maximu o C80 byte long I th standar implementation th loade look fo th fil CPM.SY o flopp driv (tha is tha driv whic repond t th physica lin Driv Selec ) I th fil i no present th loade wil respon wit a erro messag t th terminal Otherwise th loade wil loa th syste fil int memor startin a som buffe locatio (normall 2000H) Th loade the determine th loa addres o th CP/ syste an blockmove i t tha address Th loade als fill i tabl i th SUPERBIO whic contain ma o wher o th dis th fil CPM.SY i located Thi informatio i necessar s tha th SUPERBIO ca reloa th CC an BDO o war boot Tha i wh yo mus no chang densit o th syste dis i i i  floppy sinc disk o differen densit hav th CPM.SY fil i differen places an changin dis density makes a warm boot impossible. Th LDRGE progra i th equivalen t SYSGE i standar system I transfer th oute trac onl fro th sourc dis t th destination Afte runnin LDRGEN yo mus transfe valid CPM.SYS file to the disk for it to be bootable. Customizing the loader: Th loade i .CO fil whic execute a 100H I yo wis t boo of dis othe tha flopp drive yo mus integrat customize BIO fo th loader Th BIO i org' a 500Ƞ wit standar BIO jum table an mus suppor consol outpu an al dis function excep writ (fo th singl boo disk). Sinc th loade i .CO file yo ca debu i b runnin th loade a norma transien progra unde you debugger Whe th custo loade i debugged i ca b LDRGEN' ont dis b passing the filename as a command parameter to LDRGEN: LDRGEN B:CUSTMLDR.COM Th loade sourc i include fo you use Th loagica functio o th loade i findin fil o th defaul dis ca b use t suppor loadin o syste file fro boo volum t volatil syste volum (e.g memor disk) Modif th loade s tha afte th syste i loade an blockmoved th coldboo routin return t th loader The rea th syste fil fro th boo volum an writ the t th syste dis usin BDO calls. g' a 500Ƞ wit standar BIO jum table an mus suppor consol outpu an al dis function excep writ (fo th singl boo disk). Sinc th loade i .CO file yo ca debu i b runnin th loade a norma transien progra unde you debugger Whe th custo loade i debugged i ca b LDRGEN' ont dis b passing the file Welcome to the SUPERBIOS Thi i onl a introduction Se th followin file fo additional information: FORMAT.DOC for detailed information on the disk format. CPMINSTA.DOà fo installatio o th syste fo user wh already own CP/M. NEWSIZE.DOà t regenerat th syste fo differen memor size. INTRFACE.DOC for information on modifying the BIOS. Generating a new system disk: Assumin yo alread hav bootabl syste disk eithe b purchas o CP/ fro Advance Micr Digita o b followin th steps outlined in CPMINSTA.DOC- Us FORMAT.CO t forma blan dis i th desire forma (Standar eigh inc singl densit disk generall don' nee refomatting) Plac you syste dis i A an th destinatio disk in B:. Run LDRGEN from A to B. Us PIР t transfe th fil CPM.SY fro t B Fo optimu performance CPM.SY shoul b th firs fil yo writ  t an syste disk Thi i becaus th syste mus acces thi fil o eac war boo (control-C) an th acces i muc faste i th fil i o th outermos track o th dis (file ar writen to a new disk from the outer tracks in). .pa Operation of the SUPERBIOS: Th SUPERBIO behave i genera a an norma CP/ system However yo mus no chang densit o disk withou doin control-C Thi i becaus th SUPERBIO check onl onc afte each warm boot to see what density each disk is. I general yo ma chang syste disk a an tim provided: 1) The system disks are the same density. 2) CPM.SYS is the first file on each disk. I yo wis t chang densit o syste disk yo mus reboot the system (push the reset button and type control-C). Printer Selection: Th SUPERBIOӠ contain cod t driv bot th paralle printe interfac an th seria interfac a th CP/͠ lis device Th distributio versio ha th paralle printe a th default Th defaul printe ca b change b patchin th byt i CPM.SY wit DDT (byt 1829 - se t fo parallel fo serial). Th syste display th defaul printe o col boot Th printe ma b change a an tim t th alternat b changin th iobyt a locatio 3 STAԠ LST:=CRT wil selec th alternate printer, STAT LST:=TTY: restores the default. NOTICE: A shipped th SUPERBIO ca suppor eigh inc doubl side doubl densit drive o th firs tw drive an ) I th thir driv driv i als doubl side doubl density the yo canno ru fourt drive I th thir driv i singl side doubl density the yo ca ru fourt driv if it is also single sided. Thi limitatio come fro th fac tha ther i n roo i th BIOӠ fo th allocatio vecto necessar fo fou doubl side disks I yo nee t ru fou drives o whic mor ths tw ar doubl sided yo wil hav t chang th SUPERBIO Allocatio Vecto t th sam siz a vecto 0 an generat 61K CP/M by the procedure outlined in NEWSIZE.DOC.  2A:\=  _~#<¥#~#foʥ8 @!O6#L*:&"B:;G_!O}/o|/g#"Fx/o&#"D> > G>G:9 :>ڰ, :<:=ڰ}|H :;=ڰM:;G!O~@w6#*F+"F*D+"DV !:;O y> :?G"3»w#w#3 i :;<>PO:?G\g !:;O y>0 }    :A_ g p" gg. g!Ip#6#H Iʰʰ9ð!aL{L 0Z O)))) <pƐ'@'_O*Fғ*DÄÄx*B:;ADVANCED DIGITAL CORPORATION HDC1001 Hard Disk Controller Bad Block Mapping Utility $No drive selected.$Head with bad sector? $ Cylinder with bad sector? $ Bad Sector? $ Reading track...$ Formatting track...$ Writing track...$ Map-out completed.$This drive does not support hardware description vector.$ That's unreasonable.$Drive not ready.$ WD100X Error.$ on Head $, Cylinder $, Sector $@ TITLE ADVANCED DIGITAL HDC1001 HARD DISK BAD SECTOR MAPPER Oct 01 11:00 ;********************************************************* ;** ** ;** ADVANCED DIGITAL HDC1001 HARD DISK CONTROLLER ** ;** ** ;** HARD DISK MAD SECTOR MAPPER ** ;** ** ;** This program is to be used to create ** ;** special HDC1001 formatting to map out bad ** ;** areas of the disk. The program prompts the ** ;** user to enter the head, cylinder and sector ** ;** that the error occured on. The program then ** ;** reads all the readable data on that track, ** ;** calculates a new interleave table with the ** ;** erroneous area tagged with an illegal sector ** ;** number, formats the track, and then ** ;** re-records the data back to the track. This ** ;** program requires a Hardware Description Vector ** ;** for the drive to be fixed. ** ;** ** ;** Written by: ** ;** ** ;** Greg Lindberg ** ;** ** ;********************************************************* .Z80 PAGE ;***********************; ; EQUATES ; ;***********************; ;SYSTEM EQUATES BDOS EQU 5 ;BDOS entry point TFCB EQU 5CH ;CP/M DEFAULT FCB CR EQU 0DH ;Carriage return LF EQU 0AH ;Line feed ; prtstr equ 9 ; Print string rdbuf equ 10 ; Read buffer conin equ 1 ; Console input conout equ 2 ; Console output drive equ 25 ; Get present disk drive seldsk equ 14 ; Select disk dskparm equ 31 ; Get disk parm address ;Port offsets for the HDC1001 HDBASE EQU 0E0H ; HDC1001 BASE I/O PORT DATA EQU HDBASE+0 ; Data register ERROR EQU HDBASE+1 ; Error register SECNT EQU HDBASE+2 ; Sector count SECNO EQU HDBASE+3 ; Sector number CYLLO EQU HDBASE+4 ; Cylinder low CYLHI EQU HDBASE+5 ; Cylinder high SDH EQU HDBASE+6 ; Size/Drive/Head COMND EQU HDBASE+7 ; Command register STATUS EQU COMND ; Status register ;Some HDC1001 commands CREAD EQU 20H ; Read sector CWRITE EQU 30H ; Write sector CFORM EQU 50H ; Format track PAGE ;***********************; ; Main program ; ;***********************; START: LD DE,SIGNON ;Send signon message ld C,prtstr call bdos ;Attempt to select drive ld C,DRIVE ; Get current drive call bdos LD (CURDRV),A ; and save it LD A,(TFCB) ; Get selected drive DEC A ; Is it default? JP P,GOTDRV ; No, so we got drive NODRIV: ld DE,nodrv ; Say no drive selected ld C,prtstr call bdos RET ; Exit program GOTDRV: LD E,A ; Else select drive ld C,SELDSK call bdos ld C,DSKPARM ; Get disk parm table call bdos ;Find address to valid hardware description vector LD DE,-4 ; Index just before DPH ADD HL,DE ; to Hardware Description Vect LD A,(HL) ; Should be a word of -1 INC HL AND (HL) INC A JP NZ,BIOERR ; If no -1 then bad BIOS INC HL LD A,(HL) ; Get HDV address INC HL LD H,(HL) LD L,A ; Is it a valid address? OR H JP Z,BIOERR ; No, unsupported device ;Save rest of Hardware Description Vector in memory LD DE,IOPORT ; Copy the rest of the HDV LD BC,9 ; table into local memory ldir ;Calculate old interleave table ;But first clear the table to all FF's DOIT: LD B,64 ; Make table 64 long LD HL,INTTBL ; Index interleave table SETLP: LD (HL),-1 INC HL DEC B JP NZ,SETLP ;Generate 16 bit interleave LD HL,(INTERB) ; Get interleave byte LD H,0 ; and turn it into a word LD (INTER),HL ;Next, calculate interleave table upper limit LD A,(SECS) ; Get number of sectors LD B,A ; Save for later LD E,A ; Offset off base of int tbl LD D,0 LD HL,INTTBL ADD HL,DE LD A,L ; Negate (2s complement) CPL LD L,A LD A,H CPL LD H,A ; This is our upper limit INC HL LD (LIMIT),HL ;Now, negative sector count LD A,B ; Get sectors per track (SECS) CPL ; And twos complement LD L,A LD H,-1 INC HL LD (NSECS),HL CALL CINTER ; Calculate interleave table ;Do a dummy read to insure that the head has beed restored LD A,CREAD OUT (COMND),A RSWAIT: IN A,(STATUS) AND A JP M,RSWAIT ;Figure other needed paramters ; SDH mask LD A,20H ; Get 512 mask LD B,A ; Save for a moment JR NOECC LD A,80H OR B LD B,A NOECC: LD A,(UNIT) ; Get drive number RLCA ; Rotate drive into position RLCA RLCA OR B ; OR in sector size PUSH AF ; Save Size/Drive ;Get bad head, cylinder, and sector ld DE,hdmsg ld C,prtstr call bdos CALL HEXIN ; Get hex input LD A,(HEADS) SUB L ; Make sure it is in range JP C,UNREAS POP AF ; Get Size/Drive OR L ; OR in head OUT (SDH),A ; Send to SDH register ld DE,cylmsg ld C,prtstr call bdos CALL HEXIN LD A,(CYLS) ; Make sure 16 bit cylinder SUB L ; is within range LD A,(CYLS+1) SBC A,H JP C,UNREAS LD A,L ; If within range, send to OUT (CYLLO),A ; WD100X LD A,H OUT (CYLHI),A ld DE,secmsg ld C,prtstr call bdos CALL HEXIN LD A,(SECS) DEC A ; Adjust to be last sector SUB L JP C,UNREAS LD C,L ; Save bad sector ;Change all the bytes in the interleave table to -1 except ;for the bad one. LD A,(SECS) ; Get sector count LD B,A LD HL,INTTBL ; Index interleave table CKSET: LD A,(HL) ; Get sector number CP C ; Same as bad one? JP NZ,NOTBAD OR 40H ; Make bad sector illegal number LD (HL),A JP NOTGUD NOTBAD: LD (HL),-1 ; Mark as good NOTGUD: INC HL DEC B JP NZ,CKSET ;Adjust some interleave table parameters and then generate ;new interleave table LD HL,(LIMIT) ; Make interleave table bigger DEC HL LD (LIMIT),HL LD HL,(NSECS) DEC HL LD (NSECS),HL CALL CINTER ; Calculate interleave table ;Read the entire contents of the selected track ld DE,readng ld C,prtstr call bdos LD HL,TRKBUF ; Index track buffer LD A,(SECS) ; Get sector pointer LD C,A DEC C READLP: LD A,C ; Get sector number OUT (SECNO),A LD A,CREAD ; Get read command OUT (COMND),A LD A,(HSTSIZ) ; Get byte counter/2 LD B,A RWAIT: IN A,(STATUS) ; Wait for it to read AND A JP M,RWAIT ; Ignore all errors except RRA ; Aborted command JP NC,READBF IN A,(ERROR) AND 4 JP NZ,NOTRDY ; If aborted, drive not rdy READBF: IN A,(DATA) ; Read entire sector LD (HL),A INC HL IN A,(DATA) LD (HL),A INC HL DEC B JP NZ,READBF ; Read entire buffer DEC C ; Bump sector counter JP P,READLP ; Continue if still >0 ;Now format the track with the modified interleave ld DE,frmtng ld C,prtstr call bdos LD A,(SECS) ; Get number of sectors INC A ; Add one to it OUT (SECNT),A LD A,CFORM OUT (COMND),A LD DE,INTTBL ; Index interleave table LD A,(HSTSIZ) ; Get transfer size LD B,A DATALP: XOR A ; Get bad block bits OUT (DATA),A LD A,(DE) ; Get sector number OUT (DATA),A INC DE DEC B JP NZ,DATALP ; Continue till sector full FWAIT: IN A,(STATUS) ; Wait for format to happen AND A JP M,FWAIT ; and ignore all errors ;Now write all the original data back to where it logically ;came from ld DE,wrtng ld C,prtstr call bdos LD HL,TRKBUF ; Index track buffer LD A,(SECS) ; Get sector pointer LD C,A DEC C WRITLP: LD A,C ; Get sector number OUT (SECNO),A ; Send to WD100X LD A,CWRITE ; Get read command OUT (COMND),A ; Issue command LD B,0 ; Get byte counter/2, 0 = 256 ld C,data WRITBF: otir ; Send the entire contents otir ; of buffer to WD100X WWAIT: IN A,(STATUS) ; Wait for it to be written AND A JP M,WWAIT RRA ; This time errors CALL C,HERROR ; are important DEC C ; Bump sector counter JP P,WRITLP ; Continue if still >0 ld DE,maped ld C,prtstr call bdos JP RESEL ; Re-select original drive BIOERR: ld DE,bdmsg ld C,prtstr call bdos JP RESEL ; Re-select default drive UNREAS: ld DE,unrs ld C,prtstr call bdos JP RESEL NOTRDY: ld DE,ntrdy ld C,prtstr call bdos ;Re-select formerly current drive RESEL: LD A,(CURDRV) LD E,A LD C,SELDSK CALL BDOS jp 0 ; Exit program PAGE ;***********************; ; Subroutines ; ;***********************; ;This subroutine gives the user a detailed error report HERROR: PUSH HL ; Save important registers PUSH BC ld DE,errmsg ; Send error message ld C,prtstr call bdos IN A,(ERROR) CALL HEXOUT ; Output error ld DE,hderr ; Send head ld C,prtstr call bdos IN A,(SDH) AND 7 CALL OUTCHR ; Print single digit ld DE,cylerr ld C,prtstr call bdos IN A,(CYLHI) ; Report CYLHI first CALL HEXOUT IN A,(CYLLO) ; then CYLLO CALL HEXOUT ld DE,secerr ld C,prtstr call bdos IN A,(SECNO) CALL HEXOUT pop BC ; Restore registers pop HL RET ;This subroutine inputs up to four characters in hex and ;leaves them in HL HEXIN: HEXIN2: LD HL,TBUFF+1 ; Clear input buffer LD B,5 LD (HL),B INC HL CLRLP: LD (HL),0 INC HL DEC B JP NZ,CLRLP ld DE,tbuff ld C,RDBUF ; Get hex from user call bdos LD DE,TBUFF+1 LD A,(DE) ; Make sure at least 1 typed AND A JP Z,UNREAS CP 5 ; and less than 5 JP Z,UNREAS CALL CONHEX ; Do the conversion RET NC ; Carry not set, no errors JP UNREAS ;This subroutine does the hex conversion dirtywork CONHEX: LD HL,0 ; Zero hex accumulator CONLP: INC DE ; Pre-increment text pointer LD A,(DE) ; Get character? AND A ; Last one RET Z ; If so, return to caller CP 'a' ; Fold to upper case JP C,UPPED CP 'z'+1 JP NZ,UPPED SUB 'a'-'A' UPPED: SUB '0' ; Ckeck <0 RET C ADD A,'0'-'G' ; Check >F RET C ADD A,6 JP P,CONCON ADD A,7 RET C CONCON: ADD A,10 LD C,A ; Digit to BC LD B,0 REPT 4 ; Shift left 4 ADD HL,HL ENDM ADD HL,BC ; Add in new digit JP CONLP ;This subroutine prints the contents of A in hex HEXOUT: PUSH AF RRCA ; Get upper digit RRCA RRCA RRCA CALL OUTCHR ; Print upper digit POP AF OUTCHR: AND 0FH ; Mask four bits ADD A,90H DAA ADC A,40H DAA LD E,A ld C,conout ; Write it to console call bdos RET ;This subroutine calculates interleave tables CINTER: LD B,0 ; Clear sector number LD DE,INTTBL ; Index interleave table CHECK: LD HL,(LIMIT) ; Make sure limits not ADD HL,DE ; exceeded JP NC,WITHIN ; We are within limits LD HL,(NSECS) ; Otherwise subtract SECS ADD HL,DE XCHECK: EX DE,HL JP CHECK ; And check limits again WITHIN: LD A,(DE) ; This place taken? AND A JP M,GOTIT ; If not, we can use it INC DE ; Else, check next one JP CHECK GOTIT: LD A,B ; Store sector number LD (DE),A LD HL,(INTER) ; Increment pointer by ADD HL,DE ; interleave INC B ; Increment sector count LD A,(SECS) ; Have we done enough? CP B JP NZ,XCHECK RET PAGE ;***********************; ; Messages ; ;***********************; signon: db 'ADVANCED DIGITAL CORPORATION',CR,LF DB 'HDC1001 Hard Disk Controller Bad Block Mapping Utility',CR,LF,'$' nodrv: db 'No drive selected.$' hdmsg: db 'Head with bad sector? $' cylmsg: db LF,'Cylinder with bad sector? $' secmsg: db LF,'Bad Sector? $' readng: db CR,LF,'Reading track...$' frmtng: db CR,LF,'Formatting track...$' wrtng: db CR,LF,'Writing track...$' maped: db CR,LF,'Map-out completed.$' bdmsg: db 'This drive does not support hardware description vector.$' unrs: db CR,LF,'That''s unreasonable.$' ntrdy: db 'Drive not ready.$' errmsg: db CR,LF,'WD100X Error.$' hderr: db ' on Head $' cylerr: db ', Cylinder $' secerr: db ', Sector $' ;***********************; ; Variables ; ;***********************; ioport: ds 1 ; Base I/O port UNIT: DS 1 ; Physical device unit INTERB: DS 1 ; Current interleave SECS: DS 1 ; Sectors per track CYLS: DS 2 ; Cylinders per drive HEADS: DS 1 ; Heads per drive HSTSIZ: DS 1 ; Host size/128 stprt: ds 1 ; Step rate CURDRV: DS 1 ; Current drive at start INTER: DS 2 ; 16 bit interleave NSECS: DS 2 ; 16 bit negative SECS LIMIT: DS 2 ; Upper memory lmt of table tbuff: db 64 ; Temporary buffer for input ds 6 INTTBL: DS 64 ; Interleave table TRKBUF EQU $ ; Entire track buffer (~8K) END  SUPRERBIOS internal interface specifications Th SUPERBIO i modular tabl drive progra designe for easy expansion and modification. Th firs tw memor page o th SUPERBIOӠ perfor mappin fro logica unit t physica drivers Thi par o th program will not normally need to be changed. Th logica t physica devic assignmen tabl i a 100 relativ t th star o th BIOS I contain sixtee dis entries fou consol entries fou lis entries on reader an on punch tabl entr consist o tw bytes Th firs byt i th hig orde byt o th addres o th devic handler Th handle module alway star o pag boundary s thi byt i sufficien t specif th addres o al th routine i th handler Th secon byt i devic numbe withi th handler Fo example har dis formatte a tw logica drive woul b addresse b tw tabl entries bot wit th sam addres bu with two device numbers (0 and 1, usually). Thi mappin syste make i possibl t reconfigur th system without having to reassemble the BIOS. Drive module com i tw flavors characte i/ handler (console an lis devices an dis handlers Eac handle module starts on a page boundary with a jump table. Character handlers: The jump table is : table+0 jp poll console character in table+3 jp console character input table+6 jp console character output table+9 jp list character output table+0C jp list status table+0F eight character ASCII name for module Th routine receiv exactl th sam paramter a describe i th CP/͠ Alteratio Guide I addition eac routin receive th devic numbe i A Th routine wil retur t their caller whatever the normal code for CP/M 2 would be. .pa Disk Handlers: The jump table is : table+0 jp  home table+3 jp select disk table+6 jp set track table+9 jp set sector table+0C jp read sector table+0F jp write sector table+12H jp flush buffers Eac routin excep flus receive th norma parameter passe accordin t th CP/ Alteratio guide Th writ routin wil receiv th deblockin informatio i describe i th appendi o secto blocking/deblocking (Se als th cod fo rea an writ i th flopp modul o th SUPERBIOS) Th device number is passed in A. Selec dis receive tw addtiona paramters O th firs cal t selec give dis afte war boot bi o wil b set I th selec i successfu (know b th selec routin returnin nonzer valu i HL) th bi wil b reset an bi 7 of A will be reset until the next warm boot. Selec als receive paramete i B i zer o entr t selec i th las dis succesfull selecte wa i th sam modul a th ne dis bein selected Thi informatio ma b useful in determining buffer flushing strategies. Th flus entr poin i use b th logica dis selec handler Flus i calle o th currentl selecte dis wheneve dis i differen modul i selected Thi i sig tha an share buffer mus b flushed Flus shoul retur i i th flus wa successful nonzer i a erro occured I flush returns an error code, the new disk select will be denied. DMA address handling: Unde certai conditions th BDO wil issu selec dis cal t ne disk an expec th previou DM addres t remai i force Therefore th Se DM addres BIO cal simpl store th valu a fixe locatio (F an F relativ t th star o th BIOS) You rea an writ routine wil hav t ge th DM address from this location before each operation. .pa Interrupt handlers: A th moment th SUPERBIO doe no hav an interrupt- drive code However futur release wil us interrupt fo typeahead har dis controller an possibl othe use a well Th us o th Z8 alternat registe se i reserve fo syste us ONLY Thi wil enabl improve performanc i a interrupt- drive enviromen sinc contex switchin wil b堠 fast Therefore w recommen tha an modification yo mak t th cod d no us th alternat registers excep i you interrup handlers. Ver fe CP/ program us th alternat registe set I yo us on o thos tha does w sugges yo includ fla byt t indicat t you interrup handler tha they mus sav registers Thi wil b include i th nex releas o th SUPERBIOS. Th SUPERBIO disable interrupt whe th CP i waitin o a INTR o DR fro th FDC durin see an secto read/write Interrupt canno b enable durin th secto read/write bu th see ca b rewritte t b polle i yo nee th CPՠ t sampl interrupt durin th see period realtim cloc usin 6 H interrup wi los tim durin dis access bu H clock should be OK. Example SUPERBIOS module: Th fil RAMDISK.MA i include a a exampl o modula dis driver I show th us o th dis calls an ca b use as is.  SUPERBIOS disk formats Th SUPERBIO singl densit eigh inc forma i completel IB͠ standar 3740 Th disk shoul b readabl b an CP/ standar singl densit system Not tha th Advance Micr Digita forma progra fill al sector wit E5' i accordanc with standard practice. Som eigh inc singl densit disk fro othe system ma no b readabl a firs wit th SUPERBIOS Thi i becaus the hav od byte locate wher th doubl densit cod i suppose t be Th SUPERBIO interpret eithe 0 o E t b singl density anythin els (othe tha th SUPERBIOӠ doubl densit codes causin a error I yo ar unabl t rea supposedl standar singl densit disk tr runnin th SUPERBIOӠ forma progra wit th FORMAԠ SYSTE͠ TRACKӠ ONL option Thi wil fil th oute tw track wit E an no hur any of the data. Th SUPERBIO doubl densit forma fo eigh inc disk ha th firs trac o eac dis b singl density i accordanc wit IB͠ practice Al track o minifloppie ar doubl density Byt 7 o trac zero secto i cod byt (thi i th standar location) Ou code ar E fo singl density E fo singl side doubl density an E fo doubl side doubl density Ther i n doubl side singl densit format a ther ar n standard availabl fo suc disks. Doubl densit disk hav onl on reserve track Th sector ar 102 byte i length Eigh inc disk hav eigh sector pe track fiv inc disk hav four Th physica ske o th dis i thre fo eigh inch tw fo fiv inch Thes number wer chose t optimiz sequentia secto operation suc a progra loads sinc thes operation ar th mos sensityiv to the skew factor. >o! z> 8  >O01!2|}N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!'}#"* (,*#"+))[R#}! !!Ax͎qput+[[R8 utx7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !;NFx(ENF C$7?KnfB8C[0MD!' {:m!;!NFnfB#>,(0W}_nfRut;RDM!A76! [36:G6!w0 ͖!2͖ !͗>O3F#Nů  SYS: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file *+":*+"/:*+"^:*+":!":"5:"d:":!":"7:"f:"::8*9:8=o&))8  ^#V!q;p+q!r;6>!r;2*r;&;) p;3>Lûþ~ÃG3x(OxA͓8Ϳm!> ZhZqZhh)Zh3Zq>8*]}o"k@ R}??2y2::G:(7*KB7?[*R}?:2*"*E}o"xG!<[2 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $ ( w:q2rF8 <2ty2x:qW:j*mKoB(7:rGz?"|*m"o:qG2rxG![k2jG!> z{2n2xw<2q*k!` "kͱ"k: (8 ~Zd>w(>>w~Can't recognize density of disk in$Read$Write$Seek$ error on track $ sector $ side $ drive $ $!\6͂ !!y;6͂6 :y;- !Ͱ ͭ :s;:| :\:y;HZ !:]A<2\O>n !*y;&\ 6 ì !y;6:s;.¨ ͭ͂ڨ :y; ڟ !Ͱ ͭÌ ! :y;<2y;O!\ :s;w:s;0O> :s;02s;> :s;AO> :s;A 2s;>>!"z;͆ :s;<:s;]:s; HҀ :s;S¸ !96ͭ} :s;P !96 "9} :s;D !96 "9} :s;L "8} :s;M R}??2y2::G:(7*KB7?[*R}?:2*"*E}o"xG!<[2 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $ ( w:q2rF8 <2ty2x:qW:j*mKoB(7:rGz?"|*m"o:qG2rxG![k2jG!> z{2n2xw<2q*k!` "kͱ"k: (8 ~Zd>w(>>w~Ca>o! z> 8  >O01!2|~N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!'~#"* (,*#"+))[R$~! !!Bx͎qput+[[R8 utx7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !<NFx(ENF C$7?KnfB8C[0MD!' |:n!<!NFnfB#>,(0W}_nfRut<RDM!B76! [36:G6!w0 ͗!3͗ !͘>O3F#Nů  SYS: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file 7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:3>L~ÃG3x(OxAͳ8͍!> .#Zh3Zq=ZhhIZhSZq>8*]}o"k@ R}??2 y2"::G:(7*KB7?[*R}?:2*"*E}o"xG!\[2 HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $ylinder $, Sector $, Drive $6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ  Hard Disk Superbios Documentation Update Thi fil i designe t explai som o th change i th superbio tha hav bee mad fo th har dis an t describ some of the new programs that have been added. SUPER BIOS Th superbio ha ha driver fo th Advance Digita HDC100 Har Dis controller interrup consol inpu an outpu an war boo fro pro instea o fro dis include i it Thes driver ca b selecte vi conditiona assembl switches whethe the ar include a al an wha typ o har dis drive t suppor i included. Ther ar als assembl switche fo th numbe o flopp drive an whethe th floppie ar th firs logica drive o not. Th har dis drive wil suppor mos an SA100 o ST50 interfac har dis i an combinatio a lon a yo don' tr t mi SA100 interfac wit ST506 A supplie th bio contain equates for the following disk drives: SEAGATE TECHNOLOGY ST503 ST506 TANDON MAGNETICS TM601S TM602S TM603S TM603SE TM501 TM502 TM503 SHUGART ASSOCIATES SA602 SA604 SA606 SA1002 SA1004 QUANTUM Q2010 Q2020 Q2030 Q2040 MINISCRIBE 4010 4020 other drives can be added without a lot of difficulty. A mentione abov th bio no include suppor fo interrup inpu and/o outpu o th consol port Thi ca b selecte fo eithe inpu o outpu o bot o neithe a desire by the user. Th war boo fro pro allow th dis i driv A: t b change t differen densitie o t disk withou a operatin syste a war boo time Thi i don b relocatin th CC fro pro t ra an reinitializin BDO instea o readin the i fro th disk Thi proces require cop o th CCР i relocatabl forma t b i th to 2.25 o th o boar boo prom. Contact the factory for implementation of this option. FMTHD & HDBADMPR FMTHĠ i th forma routin fo th HDC100 har dis controller. The format used is 16 512 byte sectors per track. HDBADMPҠ i progra whic wil ma ou on ba secto pe track Thi ca b use i th medi o you har dis driv ha defects in it. LDRGEN Thi i ne cop o th loade generato progra se u t handle the hard disk drive. LDRBDOS & LODRBIOS Thes ar ne copie o th loade bdo an loade bio modified for use with the hard disk. SBCBOOT Thi i ne cop o th secto boo modifie fo us with the Microsoft M80 assembler. SBCHBOOT This is the sector 0 boot routine for the hard disk. >o! z> 8  >O01!2|~N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!'~#"* (,*#"+))[R$~! !!Bx͎qput+[[R8 utx7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !<NFx(ENF C$7?KnfB8C[0MD!' |:n!<!NFnfB#>,(0W}_nfRut<RDM!B76! [36:G6!w0 ͗!3͗ !͘>O3F#Nů  SYS: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file 7+*r;&;) ^#V"9-*r;&;) q#p!r;4*8&))8  *9s#r*9͇7"8*8&))8 q#p:8<28O>}<:3>L(#~HÃG3x(OxA8],4!> ncZhsZq}ZhhZhZq>8*Y]}o"[k@ R}??2`y2b:P:SG:V(7*TKWB7?[[*YR}?:S2V*T"W*YE}o"[xG![Q2P HD1001 Error $ on Head $, Cylinder $, Sector $, Drive $6!w;6> !w;ڪ*w;& :s;£>!w;4‡>*9#"9*9N2s;&íͭ:s; ͭ!s;6 !y;6+6:y; :y; !s;6Ͱ ,COPYRIGHT (C) DIGITAL RESEARCH, 1979 1] ʑ?ʑ! __0 r))) O @|r}r.g))å{u INVALID MEMORY SIZE$!$ʡ~/w/wʔ|g*"z|?¸>@G!>0w#w!4~:60+4~u!N#F! x, # =!v"z!w6!u#+w+wz >ZxG}o|g"|! :m c p!"xp ~#c*|!:m ʅ xä SYNCRONIZATION ERROR$ {°~#o}oҼüÅ*zZ# :m m! ~ #* DM! x  w#!N#F! D!_>0w#w1!`4~:60+4*"e@u READY FOR "SYSGEN" OR "SAVE 00 CPM00.COM"$*|  CONSTRUCTING 00k CP/M vers 2.2$>ͦ!q:_  !p+q.*   !q*&!p+q*2!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q*1y{0!B0}y|zx0y0{00 \X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<2 !2:2a{_:ʖ:>Ľʖ:=2–!B!6#5ʖ:Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ ""͌#>?͌͘ =_.:;<> Oo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USERg!yO#< Ty#O 321y_͸2y2ͽ:˜1͘A͌>>͌92^ :¥.!_~#fow]!v"!çREAD ERRORçNO FILE^: ! ~ 3#0 Wx x   G ~ # 3x~#B!Y~ɯ2:=!ý:=!:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ w4!Y~ʆ͌†t=ʆf ^ T 2o&)|+!<ͧÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Ypsp2mÆÆf ͧÆFILE EXISTS _: É: :ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~22\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: ! Â$$$ SUBg"C {2!"E 9" 1A 22!ty)K!G_^#V*C   ~E , &-AGMS  !!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$ :B A2 ! ~6  O͐  : E  B 2 >: b # : y! 4 5~yy 5 6y Ґ ^H @Oy H  H : – ͬ   #H : !  H ù  H  H $O͐ : 2 *C N#  x : 2 p & x ~+é 7 2 H ! >w _ : ! 5ͤ N k ͱ ¦ ͱ xʊ #N x : ! 2 ͤ ! 5™ #wO ~x½  p H    y< < ʑ  : !qMD # 2E > ! ^#V w#P :B O|^#V#"##"##"##"!O *!O *|!6ʝ 6>*w#w*w#w'û *! J * ""!N#F*^#V*~#foyx *{_zW+ * yx # *DM*s#r*s#ryOxG*0MD!!N: E G>O: \ S *C  :q n& ^#V> O^ "*}:*)= ":O:o"*C  *C !ͮ ~2~2ͦ :2ͮ : O:w:w |g}o *# ) :B O! yoxg*:B O }!N#F "*#*s#r^  ~!J  ! J *:o$*C ~i 6i w**{#z r+s{ozg**͕ **  , w͜ ͸ Ͳ ! !N#F$**O !~#:A #~$=2E k͌ : :/GyO>2!q*C " ͡  ʔ*J Ҕ^ :Oyʃ?|x | s-|N-# S:2E !~Яw > T   D ^ 6k -äPYy 5*{zBK5ڋ>*C w~#+w#w+ɯ2E 22 i  ^ *C :~w~͔͔# #  w ~>2!E 5T *C !"C  "C !w# F! w͌ x 2͢ *C  ~<wʃG:!ʎì 4~ʶ ¬:<ʶ$ ʶïZͻ   x >2>2ͻ :!Z2:E w ̈́ ͊ Ͳ  >2>2T *C G ͻ : w ̈́ n> 2;O ^ DM;}H> "*C  ::dd slO s#r:E ͊ :==»y==»*Ww# *" ͸ *:G#š" ͸ :!w4!i w: Z!E ~=26 2*C !!~~#~O~G#n,-.‹! w! yG!x͢.:E <ʄ! q!pQ:E <. ʄ$.:E <ʄ i 6}2E x N! ~态O>G~G!~G} *C !r#r#r ^ ͥ_y#x#{s+p+q-*C  ͥ!!q#p#w*:B O Y G }*MD "ã:!B w!>2*C ~=2u:B 2~2wE:A *C w>" !""2B !" !r QQQâ~?ͦ ~?r Q *"C Q- Q͜QüQr Q$Q*):B  " *)*)Q;*"E :;:A  2A QÓQÜQ*C }/_|/*W}_*"}o|g":ʑ*C 6:ʑw:2E* *E }DQ>2óadjmrux}çìûpñns ns<nskLns{?      00k CP/M vers 2.2 1!21 ͻ}ͧͬ,I*lDMͻ:k:j<Oͧ>~ͻ>2!"2!"28!"9:O R![?boot  ç!y2fyʒ>0G!h~ϰwi&))))3!jq!kq ~2koi`"l~Oj#!h~w !kw ?L:f>g yxzӉxӊY?28L28L8 >:fIyۉ:fV{ۋ:fcxۈ@$@B B HH II$@DI ABI$"$H$H@$$I! H*  $H@@A I $D!!$I"BI"I"@$BIIH$$$$BBI$@BI!"$$A DI$@ A$@$$@H! "!$$" @B$!!!DH$$"H @@BHH  !$$A"D@ "A" "BHA " !$ D B I $ !$$ H@BD D$ HI DIA!$$$ $" "$D ! $"  $AB " BDD $$D!"DI$!$BH!"IB I$"D HD" " $"! @H !BI " I  $I$I$DI$ !I$@"$"$! $I$I(  BIB@!  ! !! D 15D715E0AB :100A700015E615EC15F515FE1504160A1611162CBB :100A80000E17161D1626162D16411647164D160E54 :100A9000155316040C040C9B1@$@B B HH II$@DI ABI$"$H$H@$$I! H*  $H@@A I $D!!$I"BI"I"@$BIIH$$$$BBI$@BI!"$$A DI$@ A$@$$@H! "!$$" @B$!!!DH$$"H @@BHH  !$$A"D@ "A" "BHA " !$ D B I $ !$$ H@BD D$(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE) COPYRIGHT (C) 1979, DIGITAL RESEARCH, PIP VERS 1.5$$$ SUB =.:,<> _[]INPIRDPTRUR1UR2RDROUTLPTUL1PRNLSTPTPUP1UP2PUNTTYCRTUC1CONNULEOFDISK READ ERROR$DISK WRITE ERROR$VERIFY ERROR$NOT A CHARACTER SINK$READER STOPPING $NOT A CHARACTER SOURCE$ABORTED$BAD PARAMETER$INVALID USER NUMBER$RECORD TOO LONG$INVALID DIGIT$END OF FILE, CTL-Z?$CHECKSUM ERROR$CORRECT ERROR, TYPE RETURN OR CTL-Z$INVALID FORMAT$HEX$$$$NO DIRECTORY SPACE$NO FILE$COM$START NOT FOUND$QUIT NOT FOUND$CANNOT CLOSE DESTINATION FILE$DESTINATION IS R/O, DELETE (Y/N)?$**NOT DELETED**$$$$$$$NOT FOUND$COPYING -$REQUIRES CP/M 2.0 OR NEWER FOR OPERATION.$UNRECOGNIZED DESTINATION$CANNOT WRITE$INVALID PIP FORMAT$CANNOT READ$INVALID SEPARATOR$1 :2L> ̈́M9 221@:2!o6+6+6!6#6!6#6:G*o .!N6:^*M^!K6!6!6+6' :$::=2K  :ʤ\:ҷ\x'Ͳ:!\͢  :͈'! Ͳ:$: $͈Ͳ!N6' :!Cwͯ !6:^͢c!6{:/>!/H{ͯ :<2Š ::=HҮͯ !6:Ҿ:2 !6::/H͈;!6:> !/>HHͯ :^!w:<2:0}:@E}:!S!W6: z!]6:cm!c6:_z!_6l ::,: HHҰͯ : 2ó:E:1:2v!q!*8!*6: >ͦ>ͦ!q:_  !p+q.*   !q*&!p+q*2!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q*!p+q* !q*& *M *M !p+q*!!p+q*"!p+q*$!6  !kp+q*j> >ڪ Þ !qp+q/ *pDM9: :M2r:N!r !:r *r& N!r4 !6:͔: :ͳ.!ws+p+q+p+q:w=2wN *s*u w*s#"s*u#"u' !"*M^7 !x6:!xھ **DM͆ 2yʭ :yʗ ͯ *"*6:2x÷ *"!x4d !"/ !j}=2| !"*KM^'_ !z6:|!z1 * "}*}DM͆ ' ͯ *"!z4 :e !"͆ !z6:|!z '? 2*H#"H!{6:{ր!Ң *{& :{4 2!{4m *":ڹ ͯ !z4I '2!"!q: !4>!S :S! :2*M! ^#V͎ * :w*#" = = = = = ͯ  *M !6q  !6q  !6q  *& !6à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q   :2!q: " *M n :c4 *M n :2!c:Q !c:2: !:cw>!n !5 Y : { !6!q:!lwҙ  â :0O !q:O| :O| !6:]2l:o'2o:n'2n:m'2m*mMͣ *nMͣ *oMͣ :]:   *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z!/H:_2:!q:A/>Z!/H8: 2::=O>m:W!Q} Hmd>9>!6:2*M!E ^#V͎ڗO **~2*#"m2m͖ 2m!6m!6m!6 m2mͯ m!62m!62m!62m!62m'2:2:TҒ:2!6*ME:2::Ҳ:<22ý: 2:} >ͯ :i:2:d*M:[ *M:>!(:=2%> >>!F!5+N! ~2!4<2T>>!b}*bMͭz:b2!b6:<2é>!`ҥ*`MͭҞ!`6!6> :é:(!q:!wO! ~2*& :w>!:!4!6>:N<2N!> *N& N2 !p+q!6!6+6 !6: S: M!6g8:N2M*M8p!6!6!6>!ڕ*&P 6!4z!6!6#6#6!6*M8:ھ:*͇g2ê::¿::,͡A<2O>*M8):[ͱ!N5!6ñ:5!6#6>!ڰ!6:<2O>/:!O!T *M͡H~K:¡!6[–ͱ!N5:2:2!4=:[¼ͱ4:!6:.2O8: :* ͇g:[ ͱ!N5!6:%:<2*6 * 6å!q!6> !d*&I :]>!4A>:<2O* :w:?†!6!q!6?!:ҠgÐ!q*&*~!6:22: :]Hں:A2O>: 2ͯ ÷:S:QHI:N<22: H@"2Í202O> c!6Í202O> ڍ*&O*& !sc*&P :w:·>!ұͯ :22:_!6=!6>'!E!4!p+q*0 !r+s+p+q*~$7*>*>H&>*#"*#"> 2:R͎:!6!6=2:ʙ!6:“H9Ž>!6-e!6ͻ2=2ʺ-é:>>"ͻ2:!!5ͻ2ͬ!\-:>>!p+q:,!6*DM9:<!6:z 2W!6D*&L :w:<2Ov*:>=20O> ڒ:0:AO>Ҥ::A }}Hͬ!wͻO`idͻV[2O>2:!X!6:!:=O!L NE!4 E E:/.*&L 6$L9k9.Xͯ *KM^020 :020:121'ͳ':²ͯ !G6!"!"7 *M^n/ :a/:H!6:ͯ !&62*">!b!ͯ >!`0ͯ !q:E:24J!46*}a!44EJ *KM^'́:‚ͯ !36'n::0:f9OY#9.3'ͳ.:020' 'ͳ'7 6'!j>A+!s!"@͓1!"<**"͓n "Dn"":!Q2҂:X!Wғä:ڤ*MEÓ:ұ@@:O2Mc;!6#6>!)*&P ~"::H:H:H:H"!6!4:_jYO jM*"S*" 3@bl*M1͓!""7 *M^͆ \͔!":͎H*#"ͧÝ/ :>͛9ͯ .*#":_!' !'6!36' :1/!aE*#">z?C9IͲÁ.!6> !ڇ*&' ~2 ʀ: y.*M!4Q>!қ:=2á:2:Ҭ\>!ҿ:=2K:2K!:!:K\: \!p+q͈*DM!  ::=H-\:N2O_og_{ozg^#V))) _{ozg^#V) d^#V|g}o n_{ozgO{ozgi`N#Fogo&og H ©=¨!j>A+!s!"@͓1!"<**"͓n "Dn"":!Q2҂:X!Wғä:ڤ*MEÓ:ұ@@:O2Mc;!6#6>!)*&P ~"::H:H:H:H"!6!4:_jYO jM*"S*" 3@bl*M1͓!""7 *M^͆ \͔!":͎H*#"ͧÝ/ :>͛9ͯ .*#":_!' !'6!36' :1/!aE*#">z?C9IͲÁ.!6> !ڇ*&' ~2 ʀ: y.*M!4Q>!қ:=2á:2:Ҭ\>!ҿ:=2K:2K!:!:K\: \!p+q͈*6:0O  ú!p+q:/(*DMͩ:  : I N* *DM:aO>!Һ x!: ڦ> ʡ* +" >¡! 6: <2 =O! N͒:  O͒: ! 6:h!o$O* ͸ ! 6 !h6!: 2 3* & 6 : <2 =O! N͒*dM  :sGsu n>!6:<2=O! N͒!">!"͎/Ҵ*+">>!": *#"*""*!".+",*$"**o".!",!36:3{.*22*,**"0M ~ H3*0"**+"*+">23:2/k!36,*+s#rx:3x*0"*: “**"&*"+"(á*$#"&**#"(*"#""*$#"$*"+""*$+"$*#"!4qM*"*$: *(y"$DM}|C#~ *#"*&DMyxC 1*+":4?w+"$""ͷR: —*$"("҈!"&Ô""&*""&$mڸ*o"(**$"($"O26͛*"M :6w͢:6 !7q:*7M͒:7o$+͛ͪ*$M ~28Om:8 I͇͢u$oqo͛rP! 6!"&*$"(R͎ҔM͢ҡÔ($ҵ! 6R͇vͶ2!*!Mm$"*"M :!w͢:! e2!:! : /HH/Q:! @!!6 R!!6 :!KR$*& :!w:<2dn!:s+q*$";!>6:>/;oH*;#"(";:92=*=& *(M !::=2>/H:=<2=*(#"(æÀ:>*(+"(R:>!6$:2*o/*!My:<2=O!s Hq**DMͷ! 6: e!"*""?k*&"?*?+M ~2A :hHҏ *&"?(?:A ½8*#" ҽ*?M ~2AO *?"?ҕ!"*"*"^: 2B! 6F:B2 o(>&H6͛9!C6>!Ca R>:C<2C?! 6!"͇͢Ґq"ڊ͛Íq!!6 !!6 !6*!Ma2D*!M͒2!:D/!+w!6e2!͢!Eq!E:!:H:H!Fq*FM8 *FM   Oy2F :FY5>>:!02HO> /!";u*)))*) *H& "PҘ! 6+s#ré! 6"DM!>))덑o|g =±^#V) ^#V|g}o _{ozgi`N#Fogo&og_{_z#W H = LIBX$$$$$$$LIB$:2*o/*!My:<2=O!s Hq**DMͷ! 6: e!"*""?k*&"?*?+M ~2A :hHҏ *&"?(?:A ½8*#" ҽ*?M ~2AO *?"?ҕ!"*"*"^: 2B! 6F:B2 o(>&H6͛9!C6>!Ca R>:C<2C?! 6!"͇͢Ґq"ڊ͛Íq!!6 !!6 !6*!Ma2D*!M͒2!:D/!+w!6e2!͢!Eq!E:!:H:H!Fq1*" COPYRIGHT(C) 1978, DIGITAL RESEARCH á 4êü /L9ASMPRNHEX!4w_#~ ʸ A:4~~# ¼ > \ ?ʻ w# !ͼ ? !ͼ !)ͼ !ͼ :5͡ :6:6͡ :7͡ :\ ʻ 24!dͮ 25ͮ 27ͮ 26!8 ( ʃ !Y 1  :7ʞ !z 8  !"2D2X2#! 8 !ͼ z{* ! !"!8 w#  +6# *#"~!ͼ G:6QxJQS*!w#"! 1 !"!Y~~# …¡z!ͼ wʹ* ! w#" ! 8 !" ! zz_O4:  :6y:! G~#x=2> > ! >x6 #='G! ~ p( O*}O>4?:7w:#ĸ*"!͸* }w>ͪg( ʆ1 Y :7ʗ8 z !<ͼ CP/M ASSEMBLER - VER 2.0 NO SOURCE FILE PRESENT NO DIRECTORY SPACE SOURCE FILE NAME ERROR SOURCE FILE READ ERROR OUTPUT FILE WRITE ERROR CANNOT CLOSE FILES END OF ASSEMBLY G:7xʘ!#~ʄl͸Ä**!O {zʊ͸*"!!#^4!$wͯͯWƐ'@'ê>:ͪ!#^Ww*!{͚|͚}͚͚{!$~#͚͚> ͪ> ͪ@2 0 0:x0_<2! wI2 2> 2 >2ɯ22 !~@_6^4#: w~$w: 0 q: A: A͋q: a{_2  2 - !ɯ2I:  ;*:  ͭͷ ͭ͋>9q>9: '!2 >9 7:! 6 >2>2: 2 Qͭ:Ğ! :lj<͖<j<|<: OʊQ>ÖH >2 2 û: B­>ôD> ¸!52 !"!N#~#A07O! ~*!) " :  '<ͭ'<>V$>O$:Ğà\ÞØ`rÍÖ![w#w#b!"!F#v2[G*##~w*##~<*}q!~ڬ6![^![^#fk"͎͘!G#*####*^#Vû!^*"*{zA"*![N![ N#Fr+sq#p/>G=#w#w3#w#w!JSYMBOL TABLE OVERFLOW G*##~w*##~͎*_###s#r^#V`à 4 Wm ()*+,-/ABCDEHLMDBDIDSDWEIIFINORSPACIADCADDADIANAANDANICMACMCCMPCPIDAADADDCRDCXENDEQUHLTINRINXJMPLDALXIMODMOVMVINOPNOTORAORGORIOUTPOPPSWRALRARRETRLCRRCRSTSBBSBISETSHLSHRSTASTCSUBSUIXORXRAXRICALLENDMLDAXLHLDPCHLPUSHSHLDSPHLSTAXXCHGXTHLENDIFMACROTITLE  PF FP! ( 2/?'  v:P@< !  PP27 ( *"  NZZ NCC POPEP M x_BH!œ#¶ ¦{KÈCÈ<:JCR:  !6 s!#  ɯ<:O=_Z!F!V#fjQ̓E!^#Vo&)~#FxGyѯ<àn8!~ڢͅ6~44O! s#r!~ ڿ6ͅ^4!mw!wp!~ͅ!55N! N#fio&)^#fkz'{ͅ>ɯo>g"k!m6ů{_zW5>)D*kOxGd !m?FDM!xGyOڂÃ)sn55)=â|g}o=î--#zg{ozg{ozg{oÓ:: ;,!ɯ22=2l!"]!~H5_!m~0:ą:  *":  :‰:̅ԅ!^#=ʅVq”*qͦ1& O:lµ̅>2ly:_!w~!s!m~ùy !~=w_!m~ ͅͰ>2lyPLnR>UX:l̅2l͓*>E2C!" """ :ʼ:*1 |R|ͦ0FIL: R  R* } *" :¿::¿üX!C^#fk[@ :Œ:=ʌG!ʆF#H vÛc*| EH ͺ,^1 ͦ *""1 EH DH ͺ,1 ͦ :  1:  " > 2 :|: |Ë  |*" ͩ !6="1 :  1}1:n:>BʋSSͦSSxS 1:  1"" ͦ 1 |R >O U!" 1 1!|_!^#fk $8AP`ixH ñññ81Ľ y0îH ñGîG  ñH ñ(Ľ yîH ñîîĽ y0îîH ñG 1: :,; c*| } 8OĽ y0G G t :):,.>C :|: Jü;r :R: ʼʋ!ʼR!ʼʋ>SR{ozg!~4ʧͦ !6 ! **̈́**̈́\iͩ !w#H USE FACTOR !* "z{*"* "I !" :1 R O*UR X* G:xl :  *̩ : l x͖ *#"EH DH 0:~ ! ^4! w͆ Æ *! 6z͖ {͖ 4>R>V>D >P >L >N=COPYRIGHT (C) 1980, DIGITAL RESEARCH DDT VERS 2.2$10 !~=W!xe ~#Xbxʇ {z~#o}o҃i.2_!fp+q*e2_2_!hp+q*g!jp+q*i!lp+q*k!np+q*m2_!pp+q*oÃO$*sy͏ , $  ͌ 9!z6 # L!zw͌j# X:z 0 ͘=N#Fy}80*z{¯#z+++ ¥ z#½# · 9!`͠ y9!rͷ y=!z{w# % w!P͠ y͓}*w#"͌ @.@<!Eͷ~P !ͷ’P͌Q!ͷªP}QxQ!ͷ͓G@Q! ͷ y͓Gþ!ͷ ͓Q!ͷ͓Q͌Q!.ͷ6y#G͙Qà!2ͷQ͓͌Q!>ͷq eg͙Q:zJEËC–EQyQxQRQ** {zҷ*~#" <AOGƐ'@'OxƐ'@'ON# z8O!B N#N ¾SP.* |} !9":q!"28!"9:] !í 1͓ !" >- Ͷ Aګ ҫ _!7^#V~  \p Z z ů2[\͓͢ ҫ ͐ =« f " ͓ ҫ ͐ ʻf " =ʻf "=« ý> 2͐ f "]=f =« *]}o"_  *]"a. ~ #E }"]*a 6 *]}#|#*]E ͐ « f f f {zA|« W}d ͐ f f f DMʡڏ"=ʡͲ=ʡYPͲ1**!O~4#~#F#x~#s#r#w>͐ « f f  . ᯕo>g. 2|2\  !]w# ʫ .&  0 6 #& .K !e K w# ʫ : U 6 #K 6AW w#] !e~H#~E#~X*}|́ "!́ ͐ !ʬ =« f kʫ j \͢F w# ͋ t ʫ : W& _& & O { `i"F & & w# & ͋ « t Y t Y GтWx ͢!o ~Z #N  *. *.  NEXT PC͐ =« f  . ~ Ͷ ʻ .͓ =« f |« }w#Ä >2L͐ ! =« f }ʫ +"MD Å D  !  # ë «   Ͷ ͐ =« f xY |« }ҫ gA>S Ag}S S i |« }!w s#r:[ʔ _!~ʦ ![4ç \͢¦ 2[ 7 >?  e͢!g"c> _͢a_!f~> 5*c~#"c 0 7   > >  ͢| } @ >. *_}o| , 0 ë ^#V#!Y ))))o P q s#r#!V4 !V6# ,® >2Vñ m ͅ m ͅ m ͅ « Vʫ ! XN!~  ! _^! ^#V~ x+ >= = !~  . !   #x f L L ͓ͅ ҆ *" !6ï +"_*~ #E گ ʫ ^#V. ï ~ CZMEIABDHSP!"M"+"!91*~!O~6=G#^#V#~x (#"!N#FW( *J>7Å*M|N+"M N:LHͅÅD Å >* *͓ b" . *"] !/~##ʁtZ*F#n!Is!^#V&&##&))::^#V#*^#V>+)x-8_)*)þ))>+><7"9.Yͯ * M^2U :2:2ͳ:_³ͯ !6! @!!BH @@ABH B! "BHI$$BI$BI $ HI D$HD$$ H B!$D$"$B$DA!ABI$H B$I $HI$H$! $I $I$$A !A@$I$"!$H$I$I "! $A$  HHAA"I @BB $A"$$$I$$H!!! BH" !I B  $$!BD! $!BI D@"!$I$$H"!I$I$I$UUU$$A$ x (#"!N#FW( *J>7Å*M|N+"M N:LHͅÅD Å >* *͓ b" . *"] !/~##ʁtZ*F#n!Is!^#V&&##&))::^#V#*^#V>+)x-8_@ COPYRIGHT (C) 1978, DIGITAL RESEARCH ERROR: $, LOAD ADDRESS $DISK READ$INVERTED LOAD ADDRESS$DISK WRITE$LOAD ADDRESS $ERROR ADDRESS $BYTES READ:$INVALID HEX DIGIT$CHECK SUM ERROR $FIRST ADDRESS $LAST ADDRESS $BYTES READ $RECORDS WRITTEN $HEXCANNOT OPEN SOURCE$COMNO MORE DIRECTORY SPACE$CANNOT CLOSE FILE$*!9"!e !" !" \!""͊: ƒde"\\\͊: ²d\͝: )d;! q* &f  ! q> ! : A O: 0O! q: O: O! p+q* |O* }O! p+q*  f! p+q* DMB! p+q)R* DMB1B* DM+;! p+q* i2 ! p+q* i2 ! p+q* i2 i2 !" p+q*! f!$ p+q*# i!& p+q*% i!( p+q*' i2 !* p+q*) f!/ s+p+q+p+q:/ =2/ X*+ *- w*+ #"+ *- #"- 1* #" ͖r*   ~!" ! ͸×* " x20 º*   DM":0 Ad*   6!" Ç!" : !"6 "8 ": }2< !"4 "= ! 6Y: !2 6=21 á:1 : r+s#r==_HL"4 " >6 ͪS* "6 =23 :1 =21 v=O* #" Y8  ͝҉* +"8 .!2 ʞR̀* "4 4 = ͝* #" çR*6 DM+R*8 DM+R*: DM+R*< M!? q=  ͝Kd*= ! ͸p!@ 6>!@ X*= }O!< *@ & w*= #"= !@ 4)!< 4\mad* }O!< :? wlR*4 DM+{R* DM+R 4 ͝*4 }¿= 4 ͝< N*4 #"4  å;*4 DM+: Y2A 0O> :A 0:A AO>&R̀:A A H.2B !2 w:B !D s+q*C &͍:D _og_{ozg^#V) _{ozgi`N#Fogo&og_{_z#W( p+q*' i2 !* p+q*) f!/ s+p+q+p+q:/ =2/ X*+ *- w*+ #"+ *- #"- 1* #" ͖r*   ~!" ! ͸×* " x20 º*   DM":0 Ad*   6!" Ç!" : !"6 "8 ": }2< !"4 "= ! 3 Copyright (c) 1979, Digital Research????????????CON:RDR:PUN:LST:DEV:VAL:USR:DSK:TTY:CRT:BAT:UC1:TTY:PTR:UR1:UR2:TTY:PTP:UP1:UP2:TTY:CRT:LPT:UL1:R/OR/WSYSDIRR/O R/W SYS DIR ** Aborted **Active User :Active Files: Drive Characteristics65536: 128 Byte Record CapacityKilobyte Drive Capacity32 Byte Directory EntriesChecked Directory EntriesRecords/ ExtentRecords/ BlockSectors/ TrackReserved Tracks is Temp R/O Disk: d:=R/OSet Indicator: d:filename.typ $R/O $R/W $SYS $DIRDisk Status : DSK: d:DSK:User Status : USR:Iobyte Assign: =Bad DelimiterInvalid AssignmentBad Delimiter: Bytes Remaining On R/, Space: Invalid File Indicator** Too Many Files **File Not Found Size Recs Bytes Ext Acc65536 set to R/O Invalid Disk AssignmentWrong CP/M Version (Requires 2.0)!9"2!T OË!]6:\:] Hr3 Ë:\ʀË͇ /ҋͺ *2!"q*"&L ͐ ͐ ͐!$p+q*#~*#N͐*##"#÷!&p+q͠*%DMͱ O O!(q*(&L!*p+q*)O2'!,p+q*+O2'O2'O!.p+q*-LRRLR\LR" O!/q*/& L!1p+q*0#L~*##N!ͽ͞"T!Vq*VMͳ!Xp+q!W* >Wr#MͲ!_p+q!`6>!`6*`&*^*`&Y />!`4 >*]& ~ O!]49!a6:a*]& ~2bO>z*bM >!b/~,H~:H~*H~.H~>H~<H~=H*]& 6!]4T!]4!cq*a&Y :cw!a4!gr+s+p+q!h6>fr*d*f!is*d́"dPY! "f>!h#~Haͫo!h6:i0O͐!mr+s+p+q*lTZs#r*lڶ*l+s#r*jN#F+q#pÌ!nq!"o"q}2uo&"s* s:n*sDM2u:uqos*s"s*o͊O !v6>!vQ*v&w 6`i+46)A*:'ʓ:'O!) ~2vʍ:vO!w 6,]!v6>!v*v&w ~һ*vM !v4˜8AO͐:͐ͱ*##N!ͽ"* N#F*͠">!H% - *DM ͱͷDM  ͱ* N#F 9ͱ * ^#V))DM Tͱ* ~ *} *M!+s#r#4 !s+p+q!6!66:!ڄ !6!6>!r *&**&Y i !6!4+4A :} :!4- >!699 2¨ :!4: :2!6+6>! :O!9 DMi ͱ:!O!Y DMi :2:2͠!4 F :® )!6>!ګ ͠:O!9 DMi 8ͱ!6> !ڤ Å :2k ä  ͐:!O!Y DMi w !4C F :¿ >F : F :=229:Y= ;>9*&Y DM =2 I>!6:=28 :2:2 :!!29:Y T >:Y,e \>Ì !p+q*~:ʉ *N͐*#"o :͐!p+q!'"!6> **{2*́"PY! ">!+~H !6:0O͐à k͐͠Q" 8AO͐jͱͷDM͏ m  Z"l"!6>ʥ *}҆ *M ͱ*}x O͐} W͐ͱ !+s#r!+s#r#4D ͠:\ʹ :\=Oͳͩ !6!)6l :) :)=2) :] & !"}2\!h6?!j6?\:'C:'ƀo&")!)6!"):)/)HҘ]!)6> !)ڎ*)&*)*)&*) y!)6 Ä:) 2):)<2)M*)#")/:)ҩ*)+")`*")#"]!*)!/H!")!"]*)) *)s#r!)6> !).*)&*)*)&*) w:)<2)*)) >w#6*)) w#6*)!) w#6*)%) w#6*)) N#F*)) q#p*)%) *) ~e *) * ~o&͞ *)%) q#p!)6* >!)6!)6>!)=:)!)w=*)&*)~2):)*)& *):)2):):*)!) *)) s, >X\:)“>!d!")>!)d!")!")*++!)a*)) ^#V")]*)")*)) ^#V")]!)6> !)T*)&*)~2)*)&*)~2)O;*)) ^#V")*)) *)) N#Fq#p*)) *)s#r*)#")!)6 J:)!)J!)6 :)<2)*)")҈q:tw͠ͱ!"))ҍ*)) ^#V")]͠.*)DM\ -°!\6:\ͣ:ͱ*}DM'ͫ*)%) N#F'ͫ*)!) N#F'k͐ͫ*)) N#FͫR͐/͐ *) ~IO͐NW͐ͫ8AO͐:͐ *) ~2)t(͐:)҃)͐*)#")Ã& \!"))\Ұ*)")]͠*)M! ^#V *) >*) w *) >*) w *) >*) w *) >*) w.*)DM\ -+!\6uͱ:)O! DMͱ*)#")Ù*))))))"):m w>.Yn -:YS:Z Hҧ!6> 2)½>!)6> !)*)&*)>2) :) .͐*)M͐:)<2)99:Y=/9&ͩ c,Hͩ 9 EHͺ i`N#Fog_og_ogDM!>))덑o|gҘ =†DM!>))ҭ =¥~ ³^#V) ½^#V|g}o _{ozgi`N#Fogo&og_{_z#W"))ҍ*)) ^#V")]͠.*)DM\ -°!\6:\ͣ:ͱ*}DM'ͫ*)%) N#F'ͫ*)!) N#F'k͐ͫ*)) N#FͫR͐/͐ *) ~IO͐NW͐ͫ8AO͐:͐ *) ~2)t(͐:)҃)͐*)#")Ã& \!"))\Ұ*)")]͠*)M! ^#V *) >*) w *) >*) w *) >*) w *) >*) w.*)DM\ -+!\6uͱ:)O! DMͱ*)#")Ù*))))))"):m w>.Yn -:YS:Z Hҧ!6> 2)½>!)6> !)*)&*)>2) :) .͐*)M͐:)<2)99:Y=/9&ͩ c,Hͩ 9 EHͺ i`N#Fog_og_ogDM!>))덑o|gҘ =†DM!>))ҭ =¥~ ³^#V) ½^#V|g}o _{ozgi`N#Fogo&og_{_z#WxCOPYRIGHT (C) 1978, DIGITAL RESEARCH  o&)))))))a{__> ̓> ̓͊~̓#ÚO****!*$*'! ">2!4:(wNͯ>2:)!4f!^!*FNͷyj*DMͿ2: K!͚u c͊<2:\_/:)j*"1!u͚:] \<œ!x͕c2|\ ¢! DMͿ\õ!͕c!͕u AnA2Aͦ͊!͚u c͊2!?͚!͕u cA7nA2Aͦ!͕u c͊!6!?͚>ͦ͊!Q͕SYSGEN VER 2.0SOURCE 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 INCOMPLETE!9"1W͜Q>2!͢QG}DrYQ|͏}͏#> ex͏#r* _> e> e ҉0Ë7e}} :³ʳ7_<2!~ɯ2|\\FILE DUMP VERSION 1.4$ NO INPUT FILE PRESENT ON DISK$!Y , <    *$A!6 # T!w $r# *`: 0 *A*! ~ ʰxkb))))_y‘BK{ͅ*!66!"80*{#z+++ #(COPYRIGHT (C) 1982, ADVANCED MICRO DIGITAL o&)__> ?> ?F~?#VOͦ|{ 22=2~2w2=2! $'**j! "͒>!4(QN͖:( y.[DM͚2: 8!AV7 F<2:(͢͞(:(:w1!V:] (J\Ͱ< !Qw2|! DM͚\ͫ [T!Qw2i!]V!zQ7 (02Ab F!V7 F2͵!V!Q7 (E20Ab !Q7 )F:2 :] (:k2~ >2͵!VÿF!QADVANCED MICRO DIGITAL LDRGEN VER 2.1 for the Super Quad Z80 SBC with eight inch drives Enter source drive (A-P) or type if in memoryPlace source disk in drive and type Enter destination drive (A-P) or type to rebootPlace destination disk on drive and type Physical error in disk operation - type to continue, anything else to quitLDRGEN successfulBad drive specification (A-P)Can'nt open file: Error in reading file: 6 *9~  # #~  "!8p \ȇ!o ~] #~+] i!e~w#~w\!\l i!u6B#6A#6Kl!l6\:\<} 2h:n  >2n !\o  ͇ :\2{ !o \ ͇ \< !{ \ ͇ \!o \ ͇ \<7E 2n =Ɓo&|  ͇ ] ͇ 2h2|>~# x‡ ɯ22: 0 AWAITING # *#͆0 (ͪ0H)}:) 2):  0 ++Switching to CHECKSUM MODE++ >C2>aÒ  { 7G:A :_ 0 xͷ0H RCD, NOT SOH _ >a:<2 ږ :ʆ :ʌ ʒ D ++ UNABLE TO RECEIVE BLOCK -- ABORTING ++ $: :_ 0 ++ TIMEOUT ++ :ͷN_ : 7: :_ 0 : 1 0++FRAMING ERR++ q :P 0++OVERRUN ERR++ q :n 0++PARITY ERR++ q _ :ͷN W / :ʫ :_ 0 ++ BAD SECTOR # IN HDR _ z2>2! w, : Q2 ^ :G:ʂ <• " V :I :_ 0 ++CRC err++ :l :_ 0 ++ CKSUM ++ ͈ Ò >a:ʹ 0 SEND # *͆0 (ͪ0H)>a:a:/a>2!~a, 2yaEza{a kG:)0 xͷ0H RCD, NOT ACK :<2 :A:F7D CAN'T SEND SECTOR -- ABORTING $:)0 TIMEOUT ON ACK )hs1Ҙ>aҥ> a0 ROUTINE CANCELLED >B2*#"}:+\<0FILES EXISTS -- TYPE 'Y' TO ERASE: s[}YcN\0 No file specified c\2y2 !F"#*!g": <2 : OF\! 2 !F"aDERROR WRITING FILE $xGP͋07>02O:Y:^:^:w:|:|Oƒ:ʞ:ʸ0AWAITING INITIAL NAK ͋Cʕø0CRC request received 2*"l"w"a]2 %!6#:4:R:2:¤:}!]_ii0 TRANSFERRED :\2!\͏:2\!i:}>2(2/2:ʾ:0 ALL TRANSFERS COMPLETED >C2>2):cN!Dh!l\i2|2h A A A 2A>(Aͷ>)A_> [> [Oa{_ ڐ |Ć{0A|ͷ}ͷ 0[:<ɯ20MULTIPLE ERRORS ENCOUNTERED. TYPE Q TO QUIT, R TO RETRY: sN}RQ~=A#1 ?0:>Q2Õ~#i*!\:]EMGTSʸRŸ:ø0 ++Bad Option++ þ:m 0 Re-enter PRIMARY option and file name only: *͜r:m >2>2/>2!"aO*ayO}o|g:|g}!o&"a*aT]*a|>!i!i>2n /2(:z0 PRIMARY OPTIONS: WRT - Write file to disk (from terminal mode) DEL - Erase present file (from terminal mode) RET - Return to terminal mode with no loss of data 0XPR - Toggle expert mode (Menu on/off) DIR - List directory (may specify drive) CPM - Exit to CP/M S - Send CP/M file {^Y - Toggle save on/of R - Receive CP/M file { ^E - Exit to menu T - Terminal mode (optional file name) { ^T - File transfer mode E - Terminal mode with echo { ^X - Cancel file transfer SECONDARY OPTIONS: B - Batch mode Multi File transfers T - Terminal mode after file transfer (memory save off) R - View what is received in file transfer S - View what is sent in file transfer 0 DEFAULT DRIVE: A[0 Command: *͜N,CPM\DIRRET*WRT7XPReDEL:,!yoڂrØÂz: ʂ5>2/2!͏Â:ʂ: ʂ* ,>2/2!͏Â:/2ÂF#p7SRTEM~ʘ#Á>#’7#wկ͇ h,[ ڪG#4+~#Qpx;#ê#G~w+xF6  x;ê4ê;> ;>;ê>#;> ;> ;àG>#;> ;> ;xʪ;Eê>;5ê> ;> ;ê> ;> ;F##> w#€ͬʊͤaڠ{Ҡ_*Ͷ** OM#^#6 x͊ 9  ͊ 9   9 x͊ 9 ͊#͞ ͞6# > q>q > q>qw#q:ˆ_@w# . w#Ê~*ʮ# ñ~*ʿ#ó6?#*!\!͏:l2:m sā͜2b͍~R~R#5ii0 | :<2No 0NOT FOUNDN>? !w#z!m i_!:ʨ@ïA20 DRIVE oDQRSVTDQRSVTBCFF0INVALID OPTION c: ++BAD LIBRARY NUMBER CALLED++ $LED++ $w#€ͬʊͤaڠ{Ҡ_*Ͷ** OM#^#6 x͊ 9  ͊ 9   9 x͊ 9 ͊#͞ ͞6# > q>q > q>qw#q:ˆ_@w# . w#Ê~*ʮ# ñ~*ʿ#ó6?#*!\!͏:l2:m sā͜2b͍~R~R#5ii0 | :<2No 0NOT FOUNDN>? !w#z!m i_!:ʨ@ïA20 DRIVE oDQRSVTDQRSVTBCF0,0,0,1,%dn hdscg %dn,159,1,3 endm hddr&dn defl 1 endif if typ eq SA604 hpb&dn macro no dw -1,hdesc&dn als&no defl 009Fh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1271,511,240,0,0,1,%dn hdsc %dn,159,3,3 endm hddr&dn defl 1 endif if typ eq SA606 hpb&dn macro no dw -1,hdesc&dn als&no defl 00EFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,1907,1023,255,0,0,1,%dn hdscg %dn,159,5,3 endm hddr&dn defl 1 endif if typ eq SA1002 hpb&dn macro no dw -1,hdesc&dn als&no defl 0080h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1019,511,240,0,0,1,%dn hdscg %dn,255,1,0 endm hddr&dn defl 1 endif if typ eq SA1004 hpb&dn macro no dw -1,hdesc&dn als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2039,1023,255,0,0,1,%dn hdscg %dn,255,3,0 endm hddr&dn defl 1 endif if typ eq Q2010 hpb&d macr no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,2043,1023,255,0,0,1,%dn hdscg %dn,511,1,0 endm hddr&dn defl 1 endif if typ eq Q2020 hdpb20&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,511,3,0 endm hdpb21&dn macro no als&no defl 00FFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2039,1023,255,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb20&dn %x x defl x+1 hdpb21&dn %x endm hddr&dn defl 2 endif if typ eq Q2030 hdpb30&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,511,5,0 endm hdpb31&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2047,1023,255,0,0,172,%dn endm hdpb32&dn macro no als&no defl 00FEh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,384,5,31,1,2031,1023,255,0,0,343,%dn endm hpb&dn macro no local x x defl no hdpb30&dn %x x defl x+1 hdpb31&dn %x x defl x+1 hdpb32&dn %x endm hddr&dn defl 3 endif if typ eq Q2040 hdpb40&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,511,7,0 endm hdpb41&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,255,0,0,129,%dn endm hdpb42&dn macro no als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2047,1023,255,0,0,257,%dn endm hdpb43&dn macro no als&no defl 00FEh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,512,5,31,1,2031,1023,255,0,0,385,%dn endm hpb&dn macro no local x x defl no hdpb40&dn %x x defl x+1 hdpb41&dn %x x defl x+1 hdpb42&dn %x x defl x+1 hdpb43&dn %x endm hddr&dn defl 4 endif if typ eq M4010 hpb&dn macro no dw -1,hdesc&dn als&no defl 00F0h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,128,5,31,1,1915,1023,255,0,0,1,%dn hdscg %dn,479,1,0 endm hddr&dn defl 1 endif if typ eq M4020 hdpb4020&dn macro no dw -1,hdesc&dn als&no defl 0100h ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,2047,1023,255,0,0,1,%dn hdscg %dn,480,3,0 endm hdpb4021&dn macro no als&no defl 00DFh ;size of allocation vector css&no defl 0 ;number of checksum elements dpbg %no,256,5,31,1,1783,1023,255,0,0,257,%dn endm hpb&dn macro no local x x defl no hdpb4020&dn %x x defl x+1 hdpb4021&dn %x endm hddr&dn defl 2 endif hdldrvs defl hdldrvs+hddr&dn .lfcond .xall endm x defl 0 rept hddsks dsktyp %x,hd%x ;define hard disk parameters x defl x+1 endm ; ; dskhdr macro dn ; define a single disk header list .lall hdph&dn: dw 0000h,0000h ;translate table dw 0000h,0000h ;scratch area dw dirbuf,dpb&dn ;dir buff,parm block dw hdcsv&dn,hdalv&dn ;check, alloc vectors .xall endm ; hddisks macro nd ; define nd disks ndisks defl nd ;for later reference dpbase equ $ ;base of disk parameter blocks ; generate the nd elements dsknxt defl nmbfpy rept nd dskhdr %dsknxt dsknxt defl dsknxt+1 endm endm ; lgdrvs defl 0 ; hdpbs macro dn,lgno hpb&dn lgno lgdrvs defl hddr&dn endm ; hddpbs macro times ;define hard disk parameter blocks local x,y x defl 0 y defl nmbfpy rept times hdpbs %x,%y ;define dpb's for this hd drive x defl x+1 ;bump counters y defl y+lgdrvs endm endm ; hdvect macro ; generate the necessary ram data areas dsknxt defl nmbfpy rept ndisks ;once for each disk lds hdalv,%dsknxt,als lds hdcsv,%dsknxt,css dsknxt defl dsknxt+1 endm endm ; logdsk defl nmbfpy endif ;hard disk definitions .lfcond fdskhdr macro dn .lall fdph&dn: dw trans,0,0,0 dw dirbuf,fdpbase dw chk0&dn,all0&dn .xall endm fdisks macro x defl 0 rept nmbfpy fdskhdr %x x defl x+1 endm endm dwdsk macro drvr,lgdsk dw drvr+lgdsk endm DSKTBL MACRO ;DEFINES DISK ASSIGNMENT TABLE x defl 0 .lall drvtbl equ $+1 .xall if fpyfrst dw fpy rept nmbfpy-1 dwdsk fpy,%x x defl x+1 endm ;rept y defl 0 rept hdldrvs dwdsk hdc,%x iff y ;if first time thru x defl 0 ;reset x for hard disk logical drives starting at 0 y defl y+1 else x defl x+1 endif endm ;rept else ;fpyfrst dw hdc rept hdldrvs-1 dwdsk hdc,%x x defl x+1 endm ;rept y defl 0 rept nmbfpy dwdsk fpy,%x iff y ;if first time thru x defl 0 ;reset x for hard disk logical drives starting at 0 y defl y+1 else x defl x+1 endif endm ;rept endif ddb %x,<;last logical drive> rept 16-nmbfpy-hdldrvs dw 0 endm ;rept endm ;dsktbl SUBTTL BIOS ENTRY AND PUBLIC TABLES page ; ; BIOS jump table start:: jp coldboot wboota:: 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 ccpstart:: dw start-1600h ;CP/M boot address bdosjmp:: dw start-0dfah ;BDOS jump ; ; warm boot table ; filled in by CPMLDR ; ; contains entries of form dw track, dw first sector, dw last sector ; it is a map of where the image of the CCP and BDOS reside on disk bootbl:: dw 0,0,0 ;space for four entries dw 0,0,0 dw 0,0,0 dw 0,0,0 dw 0 ;extra to guarantee 0 track to exit properly page if ints ;interrupt driven i/o ds 16-(($-start) mod 16) ; ; serial channel interrupt vector table ; contains one entry for each interrupt that ; can be generated by sio/dart ; serinttbl:: dw intret ; channel B transmitter buffer empty dw intret ; channel B external interrupts dw intret ; channel B receiver ready dw intret ; channel B special receive interrupt if introut dw tran0int ; channel A transmitter buffer empty else dw intret ; channel A transmitter buffer empty endif dw intret ; channel A external interrupts if intrin dw recv0int ; channel A receiver ready else dw intret ; channel A receiver ready endif dw intret ; channel A special receive interrupt endif SUBTTL Driver dispatcher page home:: ld D,0 jr dskjmp settrk:: ld D,6 jr dskjmp setsec:: ld D,9 jr dskjmp read:: ld D,0ch jr dskjmp write:: ld D,0fh dskjmp:: ;go to correct disk routine ld A,(curdsk) ;current logical drive getvec:: ld HL,drvtbl dskcon:: add A,A ld E,A ld A,D ;low order byte of vector supplied ld D,0 add HL,DE ld D,(HL) ;high order byte of jump vector inc HL ld E,A ;vector lsb ld A,(HL) ;driver number ex DE,HL jphl:: jp (HL) curdsk:: db 0 ;currently selcted logical drive ret ;and leave page ; Console/list vectors const:: ld D,0 jr conjmp conin:: ld D,3 jr conjmp conout:: ld D,6 jr conjmp list:: ld D,9 jr lstjmp listst:: ld D,0ch lstjmp:: ld A,(iobyte) rlca rlca ;make 0-3 ld HL,lsttbl jr jmp2 conjmp:: ;get jump for console drivers ld A,(iobyte) ld HL,contbl jmp2: and 00000011b ;get console field jr dskcon reader:: ld d,3 ld hl,rdrtbl ld a,(iobyte) jr gordr punch:: ld d,6 ld hl,puntbl ld a,(iobyte) rra rra gordr:: rra rra jr jmp2 SUBTTL Configuration tables page ;----------------------------------------------------------------------- ; ; Hardware configuration table ; org 100h-2 iodma:: db 80h ;this is the low order byte ;of the 80h default dsktbl ;define disk assignment table contbl equ $+1 dw cpu dw cpu ;default=serial 0 db 1 ;alternate=serial 1 db 0,0,0 ;space for two more console drivers lsttbl equ $+1 dw cpu if parprnt dw cpu+2 ;default=parallel db 1 ;alternate=serial 1 else dw cpu+1 ;default=serial 1 db 2 ;alternate=parallel endif db 0,0,0 rdrtbl equ $+1 dw cpu dw cpu+1 ;default=serial 1 db 0 ;alternate=serial 0 db 0,0,0 ;space for two more readers drivers puntbl equ $+1 dw cpu dw cpu+1 ;default=serial 1 db 0 ;alternate=serial 0 db 0,0,0,0 ;space for two more punch drivers SUBTTL Warm boot code page ; ; Wboot reads in the CCP and BDOS from the CPM.SYS file ; CPMLDR initializes the bootbl to be a list of items of ; ; track (dw), first sector(db), last sector(db) ; wboot:: if not prmboot ;use this code if warm boot from disk if ints di ;turn interrupts off endif ld SP,100 ;use default buffer ld C,0 ;drive A:: call seldsk ;select drive A:: ld A,H or L jp z,booterr ;bad select ld E,(HL) inc HL ld D,(HL) ;DE=sector translate from DPH ld (bootxlt),DE ld HL,(ccpstart) ;start of CCP-starting DMA ld IY,bootbl-6 ;point to boot table nxttrk: push HL ;current DMA ;read sectors of next track ld DE,6 ;update track pointer add IY,DE ld C,(IY) ld B,(IY+1) ;BC=track ld A,B or C jr z,bootdone ;last track done call settrk ld C,(IY+2) ;get next sector to read ld B,(IY+3) dec BC ;pre decrement it ld (nextsc),BC ;save it nxtsec: pop BC ;DMA push BC call setdma scf ;clear carry flag ccf ld BC,(nextsc) ;get next sector to read inc BC ;update it ld L,(IY+4) ;get last sector ld H,(IY+5) sbc HL,BC ;any more on this track pop HL ;fix stack jr c,nxttrk ;done with last sector ld (nextsc),BC ;save next sector ld DE,128 add HL,DE ;update DMA push HL ld DE,(bootxlt) call sectran ld C,L ld B,H call setsec call read or A jr nz,booterr ;physical read error jr nxtsec endif ;disk boot code bootdone:: ;set low memory if ints and prmboot di ;turn interrupts off endif ld HL,(bdosjmp) ld (6),HL ;normal BDOS jump ld HL,wboota ld (1),HL ;warm boot jump ld A,0c3h ;'JP' intruction ld (0),A ld (5),A if prmboot ;warmboot from prom code ; VROFST EQU 54H ;OFFSET BELOW BIOS FOR BDOS VARIABLE AREA CLRLEN EQU 4DH ;LENGTH OF BDOS VARIABLE AREA TO CLEAR RELCCP EQU 0F800H ;BEGINNING OF RELOCATABLE CCP IN PROM RELTAB EQU RELCCP-100H ;BEGINNING OF RELOCATION TABLE ; ; This routine clears the variable area of bdos for warmboot ; from prom ; CLEAR:: LD HL,START-VROFST ;FIND ADDRESS OF BDOS VARIABLES LD (HL),0E5H ;SET FIRST VARIABLE XOR A ;SET UP FOR NEXT VARIABLES ld (start-0af3h),A ;clear listing toggle INC HL ; LD (HL),A ;CLEAR NEXT INC HL ; LD (HL),A ;CLEAR NEXT INC HL ; LD (HL),A ;CLEAR NEXT INC HL ; LD (HL),A ;CLEAR NEXT INC HL ; LD (HL),80H ;INIT NEXT INC HL ; LD (HL),A ;CLEAR NEXT PUSH HL ;SAVE THIS ADDRESS (SOURCE FOR CLEAR) INC HL ; (DESTINATION) EX DE,HL ;PUT DESTINATION ADDRESS IN DE POP HL ;GET SOURCE ADDRESS BACK LD BC,CLRLEN ;SET LENGTH LDIR ;CLEAR REST OF VARIABLES ; LD DE,CCPMOVER ;DESTINATION FOR CCPMOVER LD HL,WRMLDR ;SOURCE FOR CCPMOVER LD BC,LDRLEN ;LENGTH TO MOVE LDIR ;MOVE CCPMOVER TO LOW MEMORY JP CCPMOVER ;GO DO IT ; WRMLDR:: .PHASE 80H ; ; This routine will relocate the ccp from the on board prom ; to memory regardless of system size. ; ; ccp should be located in upper 2k of onboard prom with ; relocation table in 256 bytes below it. ; CCPMOVER:: LD DE,(CCPSTART) ;GET ADDRESS TO LOAD CCP TO LD A,4FH ;TURN PROM ON OUT (MEMRY),A ; ; STRTMOV:: LD HL,RELCCP ;GET BEGINNING RELOCATABLE CCP LD B,D ;PUT RELOCATION OFFSET INTO B LD IY,RELTAB ;GET ADDRESS OF RELOCATION TABLE LD IX,CCPLEN ;GET ADDRESS OF CCP LENGTH STRTLOP:: LD C,8 ;SET UP RELOCATION BIT COUNTER LD A,(IY+0)  ;GET RELOCATION BYTE MOVLOP:: RLCA ;NEED TO RELOCATE IT PUSH AF ;SAVE AF LD A,(HL) ;GET BYTE TO MOVE JR NC,STOR ;SKIP RELOCATION IF NOT NEEDED FOR THIS BYTE ADD A,B ; OTHERWISE RELOCATE BYTE STOR:: LD (DE),A ;STORE BYTE AT NEW LOCATION POP AF ;GET BACK INC DE ;UPDATE POINTERS INC HL ; DEC (IX+0) ;DONE MOVING YET JR NZ,NOTDNE ;IF LOW BYTE NOT ZERO SKIP REST OF CHECK DEC (IX+1) JR Z,DNEMOV ;IF SO LEAVE NOTDNE:: DEC C ;NEED TO UPDATE RELOCATION BYTE POINTER JR NZ,MOVLOP ;IF NOT GO DO MORE INC IY ; OTHERWISE BUMP POINTER JR STRTLOP ; AND GO TO REINITIALIZE COUNTER ; DNEMOV:: LD A,6FH ;TURN PROM OFF OUT (MEMRY),A ; endif ;prom boot code ld HL,(ccpstart) ld A,(cdisk) ld C,A if ints ei ;turn interrupts on endif jp (HL) ;go to CP/M if prmboot ; ; CCPLEN:: DW 800H ;COUNTER FOR LENGTH OF CCP TO RELOCATE ; LDRLEN EQU $-CCPMOVER ;LENGTH OF CCPMOVER ; .DEPHASE WRMLDRN EQU $ else nextsc: ds 2  ;temp storage for next sector to read an wboot bootxlt:: dw 0 ;boot disk sector translate table endif booterr:: ld DE,badbootmsg call pmsg halt ;must reset system badbootmsg:: db 'Warm boot error-reset system' crlf:: db 0dh,0ah,'$' SUBTTL Console and List drivers page cpuio equ (($-start-1)/256)+1 ; ; Console/list drivers ; All have entry A=driver number, other parameters per CP/M ; A=0 serial port 0; A=1 serial port 1; A=2 parallel (list only) org cpuio*256 cpu:: ;standard console/list routines for CPU serial ports jp pserin ; jp serin ;these three go direct to serial jp serout ; jp lstout jp pollst db 'SBCIO ' ;module name for display pserin:: ;poll serial in-return A=0ff if char ready, else 0 add A,A if intrin jr z,polbuf ;for first serial port endif inc A ;A=command port ld C,A in A,(C) and 1 ret z ;no character waiting ld A,0ffh ret if intrin polbuf:: ld hl,(outptri) ;get pointers input and output locs in buffer ld a,h sub l ;any thing in buffer ret z ;nothing there ld a,0ffh ;there is something ret endif serin:: ld B,A call pserin ld A,B jr z,serin ;loop until character received add A,A if intrin jr z,bufin ;for first serial port endif ld C,A in A,(C) and 7fh ;mask high order bit ret if intrin bufin:: di ;disable interrupts for saftey ld h,0 ;make into offset to retrieve from ld de,inpbuf ;get address of buffer add hl,de ;get address ld a,l ;update pointer inc a and inbfsz-1 ld (outptri),a ei ;ok to turn interrupts on now ld a,(hl) ;get char ret ;all done recv0int:: ld (svstk),SP ;save user stack pointer ld SP,locstk push HL ;save registers push DE push AF ld HL,(outptri) ;check if overflow inc H ld A,L and inbfsz-1 cp H j nz,rcv0 ;ski i roo fo more IN A,(0) ;clear input port xor A ;clear channel no. ld C,07 ;send bell call serout jr rcv02 ;exit rcv01: ld de,(inptri) ;get pointer to store address ld d,0 ld hl,inpbuf ;get address of base of buffer add hl,de ;find next address in buffer in a,(0) ;get input char and 7fh ;mask out parity ld (hl),a ;save char ld a,l ;update pointer inc a and inbfsz-1 ld (inptri),a rcv02: pop AF pop DE pop HL ;restore registers ld SP,(svstk) endif if ints ;enable for bad interrupts intret:: ei ;enable interrupts reti ;return from interrupt endif page serout:: ld B,C ;character to output add A,A if introut jr z,bufout ;for first serial port if interrupts endif inc A ld C,A serst:: in A,(C) and 4 jr z,serst dec C out (C),B ret if introut bufout:: di ;kill interrupts for a bit ld hl,(inptro) ;get buffer pointers ld a,l ;anything in buffer sub h jr z,chkout ;if not go check if anything in transmitter ei ;interrupts on again for a bit bfot1: ld hl,(inptro) ;get buffer pointers inc l ;any room in buffer  ld a,l and outbfsz-1 sub h jr z,bfot1 ;wait if not di ;turn interrupts off some more dec l ;set up pointer into buffer ld h,0 ld de,outbuf add hl,de ld (hl),c ;put char into buffer ld a,l ;update input pointer inc a and outbfsz-1 ld (inptro),a ei ;interrupts on ret ;and return chkout:: in a,(1) ;get transmitter status and 4 ;is transmitter empty jr z,bfot1 ;if not go put char into buffer ld a,c ;otherwise send char out (0),a ei ;and now return with interrupts on ret tran0int:: ld (svstk),SP ;save user stack pointer ld SP,locstk push HL ;save registers push DE push AF ld hl,(inptro) ;anything more to send ld a,l sub h jr z,trret ;if not leave ld l,h ;get address of next char to send ld h,0 ld de,outbuf add hl,de ld a,(hl) ;get char to send out (0),a ;send it inc l ;update pointer ld a,l and outbfsz-1 ld (outptro),a jr trint1 trret: ld a,28h ;reset tx interrupt out (1),a trint1: if intrin jp rcv02 ;if interrupt input use that return else pop AF ;restore registors pop DE pop HL ld SP,(svstk) ei ;interrupts back on reti ;and return endif ;intrin endif ;introut page ; these are the drivers modified for use with the printer lstout:: cp 2 ;parallel? jr z,plist ld B,A ;must be serial ld E,C lstot1:: call plserout or A ld A,B jr z,lstot1 dec C out (C),E ret pollst:: cp 2 jr z,polplist plserout:: add A,A ;serial out poll for printer-check busy line inc A ld C,A ld A,10h ;reset DART latch to get current value of BUSY out (C),A in A,(C) and 0ch cp 0ch ld A,0ffh ret z cpl ret page polplist:: ;parallel printer driver poll ld A,(frstpar) ;first time parallel called? or A jr z,noinit ;no, interface already initialized out (pioac),A ;set channel A to output ld A,0cfh out (piobc),A ;set channel B to bit mode ld A,00011111b ;bit 7-5 output, 4-0 input out (piobc),A xor A out (piobd),A ld (frstpar),A ;reset first noinit:: in A,(piobd) and 1 ;test busy bit ret z ;printer busy ld A,0ffh ret ;printer not busy plist:: ;parallel printer driver call polplist or A jr z,plist ld A,C out (pioad),A ;character on PIO A channel ld A,80h out (piobd),A ;strobe printer xor A out (piobd),A ;reset strobe ret frstpar:: db 0fh ;first initialization code for parallel ;printer-flag that PIO has not been initialized SUBTTL Floppy disk driver module page fpyio equ (($-start-1)/256)+1 ;make line up on page boundary ; ; Floppy disk drive driver module ; org fpyio*256 fpy:: ; floppy driver jump table jp fhome jp fseldsk jp fsettrk jp fsetsec jp fread jp fwrite jp fflush db 'FLOPPY ' ;module name for display purposes dskparm:: ;disk hardware parameter block ;one block for each drive rept nmbfpy if (mini and not special) db 1 ;single sided double density else db 0 ;density - 0=single D; 1=1 side, Double D; 2= 2S 2D endif  db seekrate ;seek rate - 0=3ms, 1=6ms, 2=10ms, 3=15ms if (mini and not special) db ddpspt else db 26 ;physical sectors per track - 26 in SD, ddpspt in DD endif db 0 ;track drive currently set at endm page ; ; CP/M disk tables fDPHbase:: fdisks ; defind disk parameter headers for floppys page ; ; DPB's for the three formats of disk:: ; ; 8" Single sided, single density ; 5" Single sided, double density ; 5" Double sided, double density ; fdpbase:: sssddpb:: ;single density (1K block) dw 26 ;sectors per track db 3 ;block shift (log2[block size/128]) db 7 ;block mask ([block size/128]-1) db 0 ;extent mask dw 242 ;highest block on disk (numbered from 0) dw 63 ;directory entries-1 db 0c0h ;alloc0 -first two bits for two blocks for Dir db 0 ;alloc1 dw 16 ;checked directories dw 2 ;track offset (system tracks) page ssdddpb:: ;single sided double density dw 8*ddpspt ;128 byte sectors per track db 4 db 0fh db 0 dw (tracks*ddpspt/2)-1 ;each of 76 tracks has ddpspt/2 2K blocks if mini dw 63 db 80h else dw 127 db 0c0h endif db 0 dw 32 dw 1 dsdddpb:: ;double sided double density dw 16*ddpspt ;one track consists of both sides db 4 db 0fh db 0 dw (tracks*ddpspt)-1 ;each of 76 tracks has ddpspt 2K blocks if mini dw 127 db 0c0h else dw 255 db 0f0h endif db 0 dw 32 dw 1 page trans:: ;single density translate table db 1,7,13,19,25,5,11,17,23,3,9,15,21 ;sectors 1-13 db 2,8,14,20,26,6,12,18,24,4,10,16,22 ;secotrs 14-16 fhome:: ld C,0 fsettrk:: ld A,C ld (iotrk),A ret fsetsec:: ld A,C ld (iosec),A ret setdma:: ld (iodma),BC ;shared among all drivers ret page ; ; Fseldsk selects the physical floppy in A (0-3) ; B=0 if last disk selected was a different floppy ; C=logical disk the floppy corresponds to fseldsk:: ld B,A call getden ;will set density byte if successful or A jr nz,fbadsel ;couldn't get density ;all physical operations OK here ld (hwptr),IX ;store for later use ld A,(IX+density) inc A ;make 1-3 ld B,A ld HL,fdpbase-dpblen ld DE,dpblen fgetdpb:: add HL,DE djnz fgetdpb ;HL=DPB address ld C,L ld B,H ld A,(curfpy) call seldph ld A,(IX+density) or A jr z,setran ;single density,set translate vector xor A ld (HL),A inc HL ld (HL),A jr putdpb setran:: ld DE,trans ;single density translate table ld (HL),E inc HL ld (HL),D putdpb:: ld DE,9 ;offset of DPB in DPH add HL,DE ld (HL),C inc HL ld (HL),B dec HL dec HL sbc HL,DE ;restore DPH (carry reset by or A) ret fbadsel:: ld A,(tempfpy) ld (curfpy),A ;restore changes made by getden ld HL,0 ret ;return error seldph:: add A,A add A,A add A,A add A,A ld L,A ld H,0 ld DE,fdphbase add HL,DE ret page ; ; Seldrv selects the drive from (curfpy), head from (head) ; (bit 0 set for head1), and density from (IX+density) ; it assembles the correct byte and outputs to wait ; and updates the track register with the most recent information seldrv:: ld A,(IX+density) or A jr z,setdens ld A,00001000b ;set double density bit ld B,A ld A,(head) rlca rlca ;move head bit to bit 2 or B setdens:: ld B,A ld A,(curfpy) or B out (wait),A ld A,(IX+drvtrk) ;get track from parameter table ;this may be first physical i/o out (trk),A ld A,2 ;set try flag ld (rdytry),A tstrdy:: ld A,0d0h ;reset status to controller out (cmd),A ex (SP),HL ;wait a bit ex (SP),HL ex (SP),HL ex (SP),HL in A,(cmd) ;drive ready? and 10000000b ret z ;yes ld HL,rdytry ;should we try once again dec (HL) jr nz,tstrdy ;yes ld DE,wpterr call pmsg call pdrv ld DE,ntrdyerr call pmsg ld DE,abortmsg call pmsg call conin cp 3 jr nz,tstrdy pop HL ;abort operation ld A,1 ret page ; ; Seek attempts to step the R/W head to the track in (iotrk) ; seek:: ld A,retries ld (retryc),A seek2:: ld A,(iotrk) ld C,A ;track stays in C in A,(trk) sub C jr nz,diftrk ;different track ld A,(curfpy) ld B,A ld A,(lstskdrv) ;last drive on which a seek took place sub B ret z ;already there ld D,14h ;seek and verify but unload head at beginning jr samtrk diftrk:: ld D,1ch ;seek with verify, load head at beginning samtrk:: ld A,C out (data),A ld A,(IX+seekrt) ;seek rate mask or D di out (cmd),A ld A,(curfpy) ;make current drive last drive ld (lstskdrv),A in A,(wait) ei rla jr c,seekerr ;no INTRQ from FDC in A,(cmd) and 10011001b ;seek error, CRC error, or incomplete jr nz,seekerr ;seek successful ld (IX+drvtrk),C ret seekerr:: ld E,1ch ;seek command call diskerror jr seek2 lstskdrv:: db 0 ;drive on which last disk operation took place page ; write writes the sector to the selected disk fwrite:: ld IX,(hwptr) ;restore IX to parameter block ld A,(IX+density) or A jr z,wrtsngl ld A,2 cp C jr z,unalloc dec A cp C jr z,directry ;directory sector jr wrtnorm unalloc:: ;unallocated sector write (no preread) call fflush or A ret nz ;flush error ld A,(iosec) and not(hstcnt-1) ;get first sector in buffer ld (blksec),A xor hstcnt*2 ld (blk2sec),A ;if this is an unallocated block ;then two physical sectors (2K) were ;unallocated ;here we have a sector to write that ;is currently in the host buffer movwrt:: call mkbufad ;get correct address in buffer ex DE,HL ldir ld A,0ffh ld (wrtpend),A ;write pending cpl ;return with no errors ret directry:: ;write to a directory sector ;the disk may be removed after this ;so we will make this write immediate call wrtnorm ;do a normal write or A ret nz ;error in previous flush or read jr fflush ;and flush this sector wrtnorm:: ;a block that has been written before call inbuf ;returns C flag set if not in buffer jr nc,movwrt ;and A to relative sector if in buffer ;not in buffer but might be sector of other 1k of ;an unallocated 2K data block ld A,D ;iosec and not (hstcnt-1) ld D,A ;first sector of new 1k block ld A,(blk2sec) cp D ; = unalocated block jr nz,wrtdbl ;unless sector of other 1K in ;unallocated data block call inbuf2 ;checks iotrk=blktrk jr c,wrtdbl call fflush ;previously unallocated data or A ret nz cpl ld (blk2sec),A ;clear unallocated sector indicator jr movwrt ;and write this sector wrtsngl:: ld A,(iosec) ld (psec),A ld A,0A3h ;second byte of OUTI instruction ld (iotran+1),A ld A,0ACh ;sector write ld (oper),A jp strtsel ;and do i/o wrtdbl:: call fflush ;flush buffer or A ret nz ;return bad sector if hard flush error cpl ld (blk2sec),A ;clear unalocated sector indicator call sidesec ;set up for new i/o call readprep ;do read to buffer or A ret nz ;physical error jr movwrt ;and move new sector from DMA page fflush:: ;flush deblocking buffer to disk ld A,(wrtpend) ;do we have a write pending? or A ld A,0ffh ld (bufvalid),A ;buffer data not valid cpl ret z push IX ;save pointer (drive may have changed) ld IX,(blkptr) ;for most recently selected drive ;which is the one to flush ld A,0A3h ;second byte of OUTI instruction ld (iotran+1),A ld A,0ACh ;FDC write sector command ld (oper),A ld HL,(iodrvtrk) push HL ld HL,(blkdrvtrk) ld (iodrvtrk),HL ;set drive to select and track ld A,(blksec) call sideflsh ;set up head bit and sector for flush call strtsel ;do physical flush pop HL ld (iodrvtrk),HL ;restore selected drive and track pop IX ld (wrtpend),A ;clear flag if no errors ret page ; ; Read reads the sector from the selected disk ; In double density, the sector may already be in the host buffer ; fread:: ld IX,(hwptr) ;restore parameter pointer ld A,(IX+density) ;density byte or A jr z,rdsngl ;singl density call inbuf jr c,rddbl ;sector not in buffer ; sector is in buffer movrd:: call mkbufad ;HL=start of sector in buffer ldir ret ;transfer done rddbl:: call fflush ;flush previous buffer or A ret nz ;physical error in flush call sidesec call readprep or A ret nz jr movrd rdsngl:: ld A,(iosec) ld (psec),A ;physical sector same as CP/M sector ;in single density readprep:: ld A,0A2h ;second byte of INI instruction ld (iotran+1),A ;patch rdwrite routine ld A,08ch ;sector read command ld (oper),A page strtsel:: call seldrv ;physically select drive and head call seek ;step to correct track ; ; diskio actually reads or writes the necessary sector ; it assumes that the head has already settled on the correct track ; (and that the head has been selected on the correct side!) ; and that the bytes in rdwrite for R/W and sector size have been filled diskio:: ld A,retries ld (retryc),A iotry:: ld A,0d0h ;force interrupt no conditions out (cmd),A ld A,(oper) ld B,A ld C,data ;prepare for indirect I/O instruction ex (SP),HL ;waste some time ex (SP),HL ex (SP),HL ex (SP),HL di ;no interrupts from here to end of transfer in A,(cmd) and 20h ;bit 5=head loaded rrca rrca rrca ;move bit 5 to bit 2 cpl and B ; the purpose of these manipulations has been ; to set bit 2 of the FDC command if the head ; isn't settled. Bit 2 will give a 15 ms delay ld E,A ld A,(IX+density) or A ld D,1 ;one sector i/o transfer for single denisty jr z,dmasingl ;use the CP/M DMA buffer in single density ld HL,hstbuf ;use host buffer for double density operations ld D,hstcnt ;number of 128 byte units to transfer jr strtio dmasingl:: ld HL,(iodma) strtio:: ld A,(psec) out (sec),A ;set physical sector ld A,E out (cmd),A ;start read/write operation call rdwrite ;do the actual i/o in A,(cmd) ei ;now ok to interrupt-status is saved ld E,A ;save status or B ;B returned from rdwrite is lost bytes count ret z ;if status OK and no lost bytes ld A,E and 10111111b ;clear write protect bit ld A,(oper) jr nz,nowpt ;write protect was not the problem cp 0ach ;was it a write operation jr nz,nowpt ;only error was disk write protected ld DE,wpterr call pmsg call pdrv ld DE,wpter2 call pmsg ld DE,abortmsg call pmsg call conin cp 3 ;was it control-C? jr nz,iotry ld A,1 ret ;return to BDOS with error nowpt:: ld D,A call diskerror call seek2 or A jr z,iotry ;if nonzero then hopeless seek error ret ; ; rdwrite does the actual transfer to/from the FDC ; HL set to DMA address on entry, D=number of 128 byte units to transfer ; transfer direction has been set by poking INI or OUTI instruction rdwrite:: ld B,128 ;bytes in one CP/M sector loop:: in A,(wait) or A ret p ;no more DRQ iotran:: ini ;start with read ;the second byte of this instruction is patched to ;be either INI or OUTI depending on need jr nz,loop dec D jr nz,rdwrite jr loop ;sector done, wait for INTRQ from fdc page ; ; disk error will eventually have all kinds of nice messages ; diskerror:: ld A,(retryc) dec A ld (retryc),A jr nz,restore ;more retries to attempt ld A,E cp 1ch ;was it a seek error? jr z,pseekerr cp 0ach ;writing? jr z,pwriterr ld DE,rderr jr perrtyp pwriterr:: ld DE,wrterr jr perrtyp pseekerr:: ld DE,skerr perrtyp:: call pmsg ld DE,trkerr call pmsg ld A,(iotrk) call phex ld DE,secerr call pmsg ld A,(psec) call phex ld DE,siderr call pmsg ld A,(head) call phex call pdrv ld DE,crlf call pmsg ld A,1 pop HL ret ;return to caller of driver with error pdrv:: ld DE,drverr call pmsg ld A,(curfpy) call phex ret page ; ; Restore is called from a disk operation with A=retries left ; restore:: in A,(cmd) and 00010000b ;bit 4=record not found ret z ;try again if record was found but ;read/written with error resto1:: ;restore to track 0 and seek again ld A,(IX+seekrt) ;get seek rate mask or 00001100b ;head load, restore, verify track 0 out (cmd),A tk0wait:: in A,(cmd) and 00000100b ;at track 0 jr z,tk0wait xor A out (trk),A ;back at track 0 ld (IX+drvtrk),A ;update track table ret page ; ; sidesec is the read/write preparation for double density ; sidesec computes the correct physical sector and side ; sidesec:: ld A,(iosec) and not(hstcnt-1) ;computer first CP/M sector in block ld (blksec),A sideflsh:: ;called to set up for a flush rept hstshft rrca endm ;A=physical sector number, but it may ;be on the second side ld B,(IX+pspt) cp B ld C,0 jr c,side0 sub B inc C side0:: inc A ld (psec),A ;physical sector on one side ld A,C ld (head),A ;set head control byte ret page ; ; inbuf returns carry flag set if sector not in buffer ; also returns (iosec) in D ; if sector is in buffer, returns offset (0 - hstcnt-1) in A ; inbuf:: ld A,(iosec) ld D,A ld A,(bufvalid) ;0 if contains valid data, else 255 rra ret c inbuf2:: ld HL,(iodrvtrk) ;check for 2nd sector ;of unallocated block ld BC,(blkdrvtrk) sbc HL,BC ;same drive and track jr z,rttrk scf ret ;not a match rttrk:: ld A,(blksec) ld B,A ld A,D sub B ret C ;sector lower # than buffer cp hstcnt ;carry set if in buffer ccf ret ; stores drive, track, sector of contents of buffer for use by flush ; also saves hardware pointer and sets buffer valid flag ; returns HL=start of sector in buffer, DE=DMA address, BC=128, A=0 mkbufad:: ld (blkptr),IX ld HL,(iodrvtrk) ld (blkdrvtrk),HL ld A,(iosec) ld B,A and not(hstcnt-1) ld (blksec),A ld A,B and hstcnt-1 ld B,A ;B=relative sector in buffer inc B ld HL,hstbuf-128 ld DE,128 shft2:: add HL,DE djnz shft2 ld BC,128 ;make ready for sector LDIR ld DE,(iodma) xor A ld (bufvalid),A ret page ; ; returns IX=start of DHPB (disk hardware parameter block) for ; the drive in A (0-3) ; uses B,DE also, returns D=0  getparm:: ld B,A inc B ld IX,dskparm-parmlen ;hardware parameter block ld DE,parmlen shft1:: add IX,DE djnz shft1 ret ; ; Sectran input:: Logical sector in BC, translate table in DE ; no translation if DE=0 ; ; Returns physical sector in HL ; Note:: only used in single density sectran:: ld A,D or E ld L,C ld H,B ret z ;no sector translation ex DE,HL add HL,BC ld L,(HL) ld H,0 ret page ; ; Getden sets variables to reflect the density of the disk in drive ; corresponding to logical disk in C. The physical drive is in B. ; If the disk is already logged in since the last software reset, ; GETDEN just returns (in essence). If the disk has not been logged in, ; GETDEN will try to read track 0, sector 1 (in single density for 8", ; in double density for 5") to determine the disk format. ; If the attempt is successful, Getden will update the ; dens, pspt, and drvtrk fields of the paramter table getden:: if not prmboot ld A,C ;is it logical drive A: or A jr NZ,nlogdin ;if so can't change density ld D,B ;save physical drive ld A,(frstsel) ;first select or A jp z,logdin ;skip if not ld A,0 ; otherwise clear flag ld (frstsel),A ; and continue nlogdin: endif ld HL,(start-51h) ;get login vector, A: = least significant bit ld D,B bit 3,C ;high byte or low byte ld A,L jr z,frst8 ld A,H res 3,B frst8: ld B,C inc B ;B = (drive MOD 8) + 1 rol1: rra ;set carry from drive bit djnz rol1 jr c,logdin ;disk already logged in ;go look at track 0 sector 1 logdrv:: push DE call fflush ;getden uses buffer pop DE or A ret nz ld A,0d0h ;reset FDC out (cmd),A ld A,(curfpy) ld (tempfpy),A ;save most recent floppy ld A,D ld (curfpy),A call getparm if mini if not special set 3,A ;set double density for minifloppy endif endif out (wait),A ;select new drive, head 0, single D call resto1 ;back to track zero xor A ld (iotrk),A ld (head),A ;force head 0 if not mini ld (IX+density),A ;track zero always single density endif inc A if mini ld (IX+density),A ;double density for minifloppies endif ld (iosec),A ;read sector 1 ld HL,(iodma) ;save old DMA address push HL ld HL,hstbuf ;buffer has already been flushed ld (iodma),HL call rdsngl pop HL ld (iodma),HL ;restore dma or A ret nz ;can't read sector ld A,(hstbuf+7fh) ;code byte for disk type OR A jr z,codeok ;some SD disks have old loaders here sub 0e5h ;code for a normal single density disk cp 3 jr c,codeok ld DE,badcode ;not our code byte call pmsg call pdrv ld A,255 ret codeok:: ld (IX+density),A or A jr z,snglspt ld A,ddpspt ;physical sectors on one side of DD jr putpspt snglspt:: ld A,26d ;single density physical sectors putpspt:: ld (IX+pspt),A xor A ret ;no errors logdin:: ld A,D ;drive already logged in ld (curfpy),A call getparm ld A,(IX+density) jr codeok ; drive can't change density bootlog:: db 1 ;0 = A: logged in, nonzero = not logged SUBTTL Hard disk drivers page .sfcond if hard .lfcond hdcio equ (($-start-1)/256)+1 ;make line up on page boundary ; ; Hard disk drive driver module ; org hdcio*256 hdc:: ; hard disk controller jump table jp hhome jp hseldsk jp hsettrk jp hsetsec jp hread jp hwrite jp hflush db 'HARDDISK' ;module name for display purposes page ; ; CP/M Hard disk tables ; hDPHbase:: hddisks hdldrvs ;set up disk parameter headers ; ; DPB's for HARD DISKS ; ; hdpbase equ $+4 hddpbs hddsks ;set up disk parameter blocks page hhome:: ld BC,0 ;force track 0 hsettrk:: ld (hdiotrk),BC ;save track number ret hsetsec:: ld (hdiosec),BC ;save sector number ret ; ; Hseldsk selects the hard disk in A ; B=0 if last disk selected was a different drive ; C=logical disk the drive corresponds to hseldsk:: res 7,a ;make sure high bit = 0 add A,A ;*2 add A,A ;*4 add A,A ;*8 add A,A ;*16 ld L,A  ;make 16 bits ld H,0 ld DE,hdphbase ;add in base address add HL,DE push HL ;save address for return ld DE,10 ;find dpb address add HL,DE ld E,(HL) ;get it inc HL ld D,(HL) ld HL,15 ;make address of physical unit add HL,DE ld A,(HL) ;get physical unit ld (curhdsk),a ;set to new drive pop HL ;get returned address back ld IX,0 ;clear to indicate hard disk ret ; and go ; ; Seldrv selects the drive from (curhdsk), head from (hhead) ; it assembles the correct byte and outputs it ; and updates the track register with the most recent information hseldrv:: ld a,(curhdsk) ;get disk rlca ;move it over rlca rlca ld hl,hhead ;get head or (hl) or 20h ; or 80h ;set sector size to 512 bytes and ECC out (sdh),a ;send to controller ret page ; ; Seek sets head to the track in (hdiotrk) ; and sector to (hpsec), sector count to one ; hseek:: ld a,(hdiotrk) ;send low order byte of track out (cyllo),a ld a,(hdiotrk+1) ;send high byte  out (cylhi),a ld A,(hpsec) ;send physical sector out (secno),A ld A,1 ;set sector count out (secnt),A ret page ; ; hwrite writes the sector to the selected disk ; and takes care of any necessary buffering ; hwrite:: ld A,2 ;unallocated write cp C jr z,hunalloc dec A cp C jr z,hdirectry ;directory sector jr hwrtnorm hunalloc:: ;unallocated sector write (no preread) call hflush or A ret nz ;flush error ld HL,(hdiosec) ;get sector ld B,L ;save it ld A,L ;find first sector in group and not 31 ld L,A ld (hunalsec),HL ld A,B rrca ;find out which sector this is in group rrca and 7 ld B,A xor A ;set proper bit in unallocated vector scf hstunv: rla djnz hstunv ld (unalcv),a ;and save it for later ; ; ;here we have a sector to write that ;is currently in the host buffer hmvwrt:: call hmkbfad ;get correct address in buffer ex DE,HL ldir ld A,0ffh ld (hwrtpnd),A ;write pending cpl ;return with no errors ret hdirectry:: ;write to a directory sector ;the disk may be removed after this ;so we will make this write immediate call hwrtnorm ;do a normal write or A ret nz ;error in previous flush or read jr hflush ;and flush this sector hwrtnorm:: ;a block that has been written before call hinbuf ;returns C flag set if not in buffer jr nc,hmvwrt ;and A to relative sector if in buffer ;not in buffer but might be unallocated sector in ;an unallocated 4K data block call hinbf2 ;checks hdiodrvtrk=hblkdrvtrk jr c,hwrt ;not same track or disk ld HL,(hdiosec) ;get sector ld DE,(hunalsec) ;get last unallocated block start ld B,L ;save L ld A,L ;find start of group and not 31 ld L,A sbc HL,DE jr nz,hwrt1 ;not in same group ld A,B rrca ;find out which sector this is in group rrca and 7 inc A ld B,A xor A ;set proper bit to test unallocated vector scf htstunv: rla djnz htstunv ld B,A ;save for test ld A,(unalcv) ld C,A ;save and B ;already written this sector ? jr nz,hwrt ;yes ld A,C ;mark new sector as writen or b ld (unalcv),a call hflush ;previously unallocated data or A ret nz jr hmvwrt ;and write this sector hwrt:: ld HL,0ffffh ;Clear unallocated sector 'cause on diff. track ld (hunalsec),HL hwrt1:: call hflush ;flush buffer or A ret nz ;return bad sector if hard flush error call hsidselc ;set up for new i/o call hrdprep ;do read to buffer or A ret nz ;physical error jr hmvwrt ;and move new sector from DMA page ; ; hflush flushes buffer to disk if write from it is pending ; hflush:: ;flush deblocking buffer to disk ld A,(hwrtpnd) ;do we have a write pending? or A ld A,0ffh ld (bufvalid),A ;buffer data not valid cpl ret z ;nothing in buffer to flush ld A,(hiodrvtrk) push AF ld HL,(hiodrvtrk+1) push HL ld HL,(hblkdrvtrk+1) ld (hiodrvtrk+1),HL ;set drive to select and track ld HL,(hblksec) call hflsdsc ;set up head bit and sector for flush call hseldrv ;select drive call hseek ;make sure proper track and sector ;do physical flush ld HL,hstbuf ;point to buffer ld BC,hdcdata ;count and port di ;protect transfer ld A,cwrite ;send write command out (comnd),A otir ;256 bytes twice otir ei hwrtw:: in A,(status) ;done yet and A jp m,hwrtw ;if not wait and 1 ;any errors jp nz,herrors ;process if so ; ld (hwrtpnd),A ;clear flag if no errors pop HL ld (hiodrvtrk+1),HL ;restore selected drive and track push AF pop HL ex (SP),HL push HL pop AF ld (hiodrvtrk),a pop AF ret page ; ; Read reads the sector from the selected disk ; it handles any necessary buffering ; hread:: call hinbuf ;is it in the buffer jr c,hrd ;sector not in buffer ; sector is in buffer hmvrd:: call hmkbfad ;HL=start of sector in buffer ldir ret ;transfer done hrd:: call hflush ;flush previous buffer or A ret nz  ;physical error in flush call hsidselc call hrdprep or A ret nz jr hmvrd ; ; read preperation ; hrdprep:: call hseldrv ;physically select drive and head call hseek ;step to correct track ; ; this actually reads the necessary sector ; it assumes that the head has already settled on the correct track ; (and that the proper head has been selected) ld HL,hstbuf ;point to buffer ld BC,hdcdata ;count and port di ;protect transfer ld A,cread ;send read command out (comnd),A hrdw:: in A,(status) ;done yet and A jp m,hrdw ;if not wait inir ;256 bytes twice inir ei in A,(status) and 1 ;any errors ret z ;return if not ; page ; ; hard disk error message processor ; ; This routine gives the user a detailed error report ; herrors:: push AF ;save error indication ld DE,herrst CALL pmsg ; First the error code IN A,(HDCERR) CALL phex ld DE,errst ; Status byte call pmsg in A,(status) call phex ld DE,errhd CALL pmsg  ; then the head IN A,(SDH) push AF ;save drive no AND 7 CALL hex1 ; Print single digit ld DE,errcyl CALL pmsg ; the cylinder IN A,(CYLHI) ; Report CYLHI first CALL phex IN A,(CYLLO) ; then CYLLO CALL phex ld DE,errsec CALL pmsg ; and finally the sector IN A,(SECNO) CALL phex ld DE,errdr ;send drive mess call pmsg pop AF rra ;get drive rra rra and 3 call hex1 ld A,(hdesc0+8) ;restore drive rlca or crest out (comnd),A herrlp:: in A,(status) rlca jr c,herrlp ;wait until done po AF RET page ; ; hsidselc is the read/write preparation for hard disk ; hsidselc computes the correct physical sector and side ; hsidselc:: ld HL,(hdiosec) ld E,L ;save L ld A,L and not(3) ;compute first cp/m sector in buffer ld L,A ld (hblksec),HL ;save it ld L,E ;restore sector to HL hflsdsc:: ;called to set up for a flush or a ;clear carry ld C,-1 ;set up head count ld DE,secs*4 ;set up number cpm sectors per head sdsclp: inc C ;increment head count sbc HL,DE ;subtract out one heads worth of sectors jp p,sdsclp ;if not negitive do more add HL,DE ;restore sector number to HL ld A,L srl A ;find physical sector srl A ld (hpsec),A ld A,C ld (hhead),A ;set head control byte ret page ; ; hinbuf returns carry flag set if sector not in buffer ; if sector is in buffer, returns offset (0 - hdstcnt-1) in A ; hinbuf:: ld A,(bufvalid) ;0 if contains valid data, else 255 rra ret c hinbf2:: ld A,(hiodrvtrk) ;check for right drive ld B,A ld A,(hblkdrvtrk) sub B jr z,rthdd ;skip if right drive scf ret ;wrong drive return with carry set rthdd:: ld HL,(hiodrvtrk+1) ;check for right track ld BC,(hblkdrvtrk+1) sbc HL,BC ;same drive and track scf ret nz ;not a match ld DE,(hblksec) ld HL,(hdiosec) ld A,D ;high bytes = cp H scf ;set failure flag ret nz ;exit if not equal ccf ;clear carry sbc HL,DE ret C ;sector lower # than buffer  ld A,L cp hdstcnt ;carry set if in buffer ccf ret ; ; stores drive, track, sector of contents of buffer for use by flush ; also sets buffer valid flag ; returns HL=start of sector in buffer, DE=DMA address, BC=128, A=0 ; hmkbfad:: ld A,(hiodrvtrk) ld (hblkdrvtrk),a ld HL,(hiodrvtrk+1) ld (hblkdrvtrk+1),HL ld HL,(hdiosec) ld B,L ld A,L and not(hdstcnt-1) ld L,A ld (hblksec),HL ld A,B and hdstcnt-1 ld B,A ;B=relative sector in buffer inc B ld HL,hstbuf-128 ld DE,128 hshft2:: add HL,DE djnz hshft2 ld BC,128 ;make ready for sector LDIR ld DE,(iodma) xor A ld (bufvalid),A ret endif ;hard disk drivers .lfcond SUBTTL Disk driver select routine page ; ; Seldsk selects the logical disk in C (0-15) ; Seldsk will flush the previous disk if it is in a different driver ; module than the new disk. Seldsk also returns an error if the ; selected disk has not had a driver installed seldsk:: ld A,(curdsk) cp C jr nz,chgdsk ;selecting a disk different from the current ld B,0 ;no other modules have been selected frstime:: ld D,3 jp dskjmp ;if same disk then do normal select for DPH chgdsk:: ld DE,drvtbl ;drvtbl is always on 256 byte boundary add A,A ld E,A ld A,(DE) ;driver module for current disk ld B,A ld A,C add A,A ld E,A ;address of new disk driver page ld A,(DE) ;driver module for new disk or A jr Z,badsel ;new disk not installed ld H,A sub B jp z,samemod ;different disk but same module, don't flush ld B,H push BC push de ld d,12h ;flush vector call dskjmp ;flush current drive pop de pop BC or A jr nz,badsel ;error in flushing disk inc A ;make non-zero to indicate a new disk module ld H,B ;module address page ; ; portion of module select routine ; used if new drive is in same module as old drive ; samemod:: ld B,A ;B=0 if last disk in same module ld L,3 ;seldsk offset push BC inc DE ;(DE) = driver number ld A,(DE) push DE call jphl ;do select pop DE pop BC ld A,H or L ret z ;bad select from driver ld A,C ;succesfully selected disk ld (curdsk),A if prmboot or A ret z ;drive A: selected ld (bootlog),A ;next select of A: with only A: logged means ;a disk reset has occured so A: could change ;density if prom boot active endif xor A ;show no errors just in case ret badsel:: ld HL,0 ret SUBTTL Common routines page ; miscellaneous character i/o routines pmsg:: ;equivalent to BDOS function 9 (print) ld A,(DE) cp '$' ret z ld C,A inc DE push DE call conout pop DE jr pmsg phex:: ;print A in hex push AF rra rra rra rra call hex1 pop AF hex1:: and 0fh add A,90h daa adc A,40h daa ld C,A jp conout SUBTTL Floppy disk storage page ; ; Floppy disk driver storage ; iodrvtrk:: curfpy:: db 0 ;current selected physical floppy drive iotrk:: ds 1 ;current track for current disk blkdrvtrk:: ds 2 ;drive and track for deblocking buffer iosec:: ds 1 ;current logical sector for DD, physical for SD blksec:: ds 1 ;first logical sector in current host blk2sec:: ds 1 ;8th CP/M sector in an unallocated 2K block psec:: ds 1 ;current physical sector bufvalid:: db 0ffh ;buffer contains valid data for (blksec) ;0 = valid data wrtpend:: db 0 ;write pending from buffer retryc:: db 0 ;number of retries left newfpy:: db 0 ;new floppy to be selected tempfpy:: db 0 ;storage for current floppy while checking ;density of new one head:: db 0 ;head control = 0 or 1 oper:: db 0 ;operation (read/write) to be performed next hwptr:: dw dskparm ;storage for pointer to current hw parameters blkptr:: dw dskparm ;pointer to paramters for block drive frstsel:: db 0ffh ;first select flag rdytry:: db 0 ;ready try again flag SUBTTL Hard disk storage page ; ; Hard disk driver storage ; if hard hiodrvtrk:: curhdsk:: db 0 ;current selected physical hard disk drive hdiotrk:: ds 2 ;current track for current disk hblkdrvtrk:: ds 3 ;drive and track for deblocking buffer hdiosec:: ds 2 ;current logical sector hblksec:: dw 0 ;first logical sector in host buffer hunalsec:: dw 0 ;first logical sector in current host unallocated block unalcv:: db 0 ;unallocated block vector hpsec:: ds 1 ;current physical sector hwrtpnd:: db 0 ;write pending from buffer hhead:: db 0 ;head control endif SUBTTL Interrupt I/O buffers page ; ; buffers for interrupt console i/o ; if intrin outptri:: db 0 inptri:: db 0 endif if introut inptro:: db 0 outptro:: db 0 endif if intrin tmplen defl (($-start) mod inbfsz) if tmplen ds inbfsz-tmplen endif inpbuf:: ds inbfsz endif if introut tmplen defl (($-start) mod outbfsz) if tmplen ds outbfsz-tmplen endif outbuf:: ds outbfsz endif if ints ds 20 ;local stack for interrupt routines locstk:: svstk: ds 2 ;stack pointer storage area endif SUBTTL Error messages page ; ; Floppy error messages ; badcode:: db 'Can''t recognize density of disk in$' rderr:: db 'Read$' wrterr:: db 'Write$' skerr:: db 'Seek$' trkerr:: db ' error on track $' secerr:: db ' sector $' siderr:: db ' side $' drverr:: db ' drive $' wpterr:: db 0dh,0ah,'The diskette in$' wpter2:: db ' is write-protected. Remove the diskette and',0dh,0ah if mini db 'take off' else db 'put on' endif db ' the write protect tab, then type any character.$' abortmsg:: db 0dh,0ah,'Type a control-C if you wish to abort the operation instead',0dh,0ah,'$' ntrdyerr:: db ' is not ready.',0dh,0ah db 'Insert diskette, close drive door, ' db 'and type any character to continue.$' page ; ; Hard disk error messages ; if hard herrst:: DB 0dH,0ah,'HD1001 Error $' errst:: db ' Status $' errhd:: DB ' on Head $' errcyl:: DB ', Cylinder $' errsec:: DB ', Sector $' errdr:: db ', Drive $' endif SUBTTL Disk buffers and Cold Boot code page dskbufs equ (($-start-1)/256)+1 ; ; disk buffers ; These are not part of the floppy driver module as such and ; should be shared by all disk modules as much as possible org dskbufs*256 coldboot:: dirbuf:: ;coldboot code lives in the directory buffer hstbuf equ dirbuf+128 ;sector deblocking buffer call cinit ;call to expendable init code ; ld E,0 ; if not special ; ld BC,0000h ;select boot drive - make sure ok ; ld A,(drvtbl) ; ld H,A ; ld L,3 ;select vector ; ld A,(drvtbl+1) ; call jphl ;select boot drive in BIOS ; ld A,H ; or L ; jp z,booterr ;can`t select system drive ; endif jp bootdone ;set up low memory and go to CCP ; ; This portion of init. code can be overwritten later in initialization ; cinit:: if ints ; Set up SIO channels LD HL,ISIOA ; point to SIO init table LD BC,ISIOAL*256+1 ; length in B & port in C OTIR LD HL,ISIOB ; repeat for channel B LD BC,ISIOBL*256+3 OTIR ld hl,serinttbl ;initialize interrupt vector ld a,h ld i,a im 2 ;put into interrupt mode 2 endif if hard ld a,(hdesc0+8) ;get steprate rlca ;*2 or cseek ;get seek command out (comnd),A ;send to drive swait:: in A,(status) and a jp m,swait endif xor A ld (iobyte),A ;back to default routing ld (cdisk),A ;user 0, drive A:: ld DE,signon call pmsg ld A,(wboota+2) ;warm boot vector add A,6 srl a srl A ;A=memory size in K call twodec ;get ASCII digits for memory size push BC ld C,B call conout pop BC call conout ld DE,sign2 call pmsg ld A,(contbl+1) ;default console add A,31h ;make 1-2 ld C,A call conout ld DE,prnmsg call pmsg ld A,(lsttbl+1) cp 2 jr c,serprn ld DE,parprn call pmsg jr lastmsg serprn:: push AF ld DE,serpmsg call pmsg pop AF add A,31h ld C,A call conout lastmsg:: ld DE,sign3 call pmsg ret page signon:: db 0dh,0ah,'Super Quad CP/M v X2.0',0dh,0ah if special db 'Special 8"-5" BIOS',0dh,0ah endif if mini db 'for ' if m48tpi db '48' else db '96' endif ' tpi minifloppies',0dh,0ah  endif if ints if intrin db 'Typeahead ' endif if intrin and introut db 'and ' endif if introut db 'Buffered output ' endif db 'installed',0dh,0ah endif ;ints db 0dh,0ah,'$' sign2:: db 'K CP/M 2.2 installed',0dh,0ah,0ah db 'Default console is serial port $' prnmsg:: db 0dh,0ah,'Default printer is $' parprn:: db 'parallel printer driver$' serpmsg:: db 'serial port $' sign3:: db 0dh,0ah,0ah,'$' twodec:: ;convert A < 100 to two ASCII digits in BC ld BC,0ff0ah nxtten:: inc B sub C jr nc,nxtten add A,C add A,30h ld C,A ld A,30h add A,B ld B,A ret page if ints ; ****** INITIALIZATION TABLES FOR SIO DEVICES ****** ; ; CHANNEL A ISIOA:: DB 018H ; channel reset DB 001H ; write reg 1 if intrin and introut DB 01AH ; Int on all recv and tx char else if introut DB 002H ; Int on tx ready else DB 018H ; Int on all recv char (no parity) endif endif DB 003H ; write reg 3 DB 0C1H ; Rx 8-bit char, Rx enable DB 004H ; write reg 4 DB 044H ; X16 clock, 1 stop bit DB 005H ; write reg 5 DB 0EAH ; DTR, Tx 8-bit char, Tx enable, RTS ; ; DB 000H ; read reg 0 ISIOAL EQU $-ISIOA ; length of sequence ; ; CHANNEL B ISIOB:: DB 018H ; channel reset DB 001H ; write reg 1 DB 004H ; Status affects interrupt vector DB 002H ; write reg 2 DB LOW(serinttbl-start) ; Interrupt vector table start DB 003H ; write reg 3 DB 0C1H ; Rx 8-bit char, Rx enable DB 004H ; write reg 4 DB 044H ; X16 clock, 1 stop bit DB 005H ; write reg 5 DB 0EAH ; DTR, Tx 8-bit char, Tx enable, RTS ; DB 000H ; read reg 0 ISIOBL EQU $-ISIOB ; length of sequence ; endif savnum equ (($-start-1)/256)+1+16h ds 1024+128-($-dirbuf) SUBTTL Allocation vectors page x defl 0 allfpy equ (tracks*ddpspt+7)/8 rept nmbfpy ;set up floppy disk allocation vectors defds all0%x,allfpy defds chk0%x,32 x defl x+1 endm if hard hdvect ;set up hard disk allocation vectors endif ; ; lastadd equ $ biosiz equ (lastadd-start+0ffh) and 0ff00h ; absolute size of superbios mxld64k equ 0-biosiz ; maximum load address for superbios ; if using pagemove version of movcpm.com kld64k equ ((mxld64k-200h) or 200h) and 0fe00h ; even K load address for superbios syssiz equ ((kld64k+800)/400h) and 3fh ; size of cp/m for this assembly of suprbios ldofst equ 1700h-kld64k ; load offset for using l80 hex file link SUBTTL SYMBOLS end  ; write reg 4 DB 044H ; X16 clock, 1 stop bit DB 005H ; write reg 5 DB 0EAH ; DTR, Tx 8-bit char, Tx enable, RTS ; DB 000H ; read reg 0 ISIOBL EQU $-ISIOB ; length of sequence ; endif savnum equ (($-start-1)/256)+1+16h ds 1024+128-($-dirbuf) SUBTTL Allocation vectors page x defl 0 allfpy equ (tracks*ddpspt+7)/8 rept nmbfpy ;set up floppy disk allocation vectors defds all0%x,allfpy defds chk0%x,32 x defl x+1 endm if hard hdvect ;set up hard disk aRO3427(AFW); RELWRDADD(AFW); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '3' : BEGIN EFHEADING; WRITELN('SEEK '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR SEEK; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); ZERO70(AFW[1]); EF := TRUE; AF := TRUE; ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); ZERO70(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '4' : BEGIN EFHEADING; WRITELN('SEEK AND SET SECTOR '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR SEEKASETSEC; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); SECTORADD(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '5' : BEGIN EFHEADING; WRITELN('RECALIBRATE '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR RECALIBRATE; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; '6' : BEGIN EFHEADING; WRITELN('NO OPERATION '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR NOOPERATION; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; END (* CASE *) END; '2' : BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - 5046 WRITE COMMANDS * * * '); WRITELN; WRITELN; WRITELN; WRITELN('1) - WRITE HOME ADDRESS AND RECORD ZERO SPECIAL '); WRITELN('2) - PREP TRACK '); WRITELN('3) - PREP CYLINDER '); WRITELN('4) - WRITE DATA '); WRITELN('5) - WRITE DATA AND PAD ZEROS '); WRITELN; WRITE(' - enter number: '); READ(CMD); WRITELN; CASE CMD OF '1' : BEGIN EFHEADING; WRITELN('WRITE HOME ADDRESS AND RECORD ZERO SPECIAL '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR WRTHMADDROS; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); ZERO70(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE;  ST := FALSE END; '2' : BEGIN EFHEADING; WRITELN('PREP TRACK '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR PREPTRACK; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO178(EFW); WRDPREPLEN(EFW[1]); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); ZERO70(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '3' : BEGIN  EFHEADING; WRITELN('PREP CYLINDER '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR PREPCYL; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO178(EFW); WRDPREPLEN(EFW[1]); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); ZERO70(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '4' : BEGIN EFHEADING; WRITELN('WRITE DATA '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR WRITEDATA; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO1716(EFW[3]); WRDXFERLEN(EFW,WDXFLEN); AFHEADING; RESET35(AFW[5]); ZERO3427(AFW); RELWRDADD(AFW); EF := TRUE; AF := TRUE; OD := TRUE; ID := FALSE; ST := FALSE; END; '5' : BEGIN EFHEADING; WRITELN('WRITE DATA AND PAD ZEROS '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR WRTDATAPADZ; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO1716(EFW[3]); WRDXFERLEN(EFW,WDXFLEN); AFHEADING; RESET35(AFW[5]); ZERO3427(AFW); RELWRDADD(AFW); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; END (* CASE *) END; '3' : BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN; WRITELN(' * * * MAID-III - 5046 READ COMMANDS * * * '); WRITELN; WRITELN; WRITELN; WRITELN('1) - READ INITIAL PROGRAM LOAD (IPL) '); WRITELN('2) - READ FULL TRACK '); WRITELN('3) - READ HOME ADDRESS SPECIAL '); WRITELN('4) - READ COUNT ');  WRITELN('5) - SPACE COUNT AND READ DATA '); WRITELN('6) - READ DATA '); WRITELN('7) - READ DATA SPECIAL '); WRITELN('8) - READ VERIFY '); WRITELN('9) - READ LABEL '); WRITELN; WRITE(' - enter number: '); READ(CMD); WRITELN; CASE CMD OF '1' : BEGIN EFHEADING; WRITELN('READ INITIAL PROGRAM LOAD (IPL) '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READIPL; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; '2' : BEGIN EFHEADING; WRITELN('READ FULL TRACK '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READFULLTRK; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO1716(EFW[3]); WRDXFERLEN(EFW,WDXFLEN); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); ZERO70(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '3' : BEGIN EFHEADING; WRITELN('READ HOME ADDRESS SPECIAL '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READHMADDSP; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW); HEADADD(AFW[2]); ZERO70(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '4' : BEGIN EFHEADING; WRITELN('READ COUNT '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READCOUNT;  SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; '5' : BEGIN EFHEADING; WRITELN('SPACE COUNT AND READ DATA '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR SPCNTARDDAT; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO1716(EFW[3]); BYTERECLEN(EFW); AFHEADING; RESET35(AFW[5]); ZERO3428(AFW); CYLADD(AFW); ZERO1713(AFW);  HEADADD(AFW[2]); RECORDT(AFW[1]); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '6' : BEGIN EFHEADING; WRITELN('READ DATA '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READDATA; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO1716(EFW[3]); WRDXFERLEN(EFW,WDXFLEN); AFHEADING; RESET35(AFW[5]); ZERO3427(AFW); RELWRDADD(AFW); EF := TRUE; AF := TRUE; OD := FALSE;  ID := TRUE; ST := FALSE END; '7' : BEGIN EFHEADING; WRITELN('READ DATA SPECIAL '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR RDDATASPEC; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO1716(EFW[3]); WRDXFERLEN(EFW,WDXFLEN); AFHEADING; RESET35(AFW[5]); ZERO3427(AFW); RELWRDADD(AFW); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '8' : BEGIN EFHEADING; WRITELN('READ VERIFY '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READVERIFY; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO1716(EFW[3]); WRDVERLEN(EFW); AFHEADING; RESET35(AFW[5]); ZERO3427(AFW); RELWRDADD(AFW); EF := TRUE; AF := TRUE; OD := FALSE; ID := FALSE; ST := FALSE END; '9' : BEGIN EFHEADING; WRITELN('READ LABEL '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READLABEL; SET35(EFW[5]); ZERO3429(EFW);  DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; END (* CASE *) END; '4' : BEGIN CLEARSCREEN; WRITELN; WRITELN; WRITELN; WRITE(' * * * MAID-III - 5046 SENSE COMMANDS * * * '); WRITELN; WRITELN; WRITELN; WRITELN; WRITELN('1) - SENSE I/O '); WRITELN('2) - READ AND RESET BUFFERED LOG '); WRITELN('3) - READ CONFIGURATION '); WRITELN('4) - READ BUFFERED RECORD '); WRITELN; WRITE(' - enter number: '); READ(CMD); WRITELN; CASE CMD OF '1' : BEGIN  EFHEADING; WRITELN('SENSE I/O '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR SENSEIO; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; '2' : BEGIN EFHEADING; WRITELN('READ AND RESET BUFFERED LOG '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR RDARESBUFLG; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; '3' : BEGIN EFHEADING; WRITELN('READ CONFIGURATION '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR READCONFG; SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; '4' : BEGIN EFHEADING; WRITELN('READ BUFFERED RECORD '); EFW[3] := EFW[3] AND ZMSK2318; EFW[3] := EFW[3] OR RDBUFFREC;  SET35(EFW[5]); ZERO3429(EFW); DSKUNIT(EFW[4]); ZERO170(EFW); EF := TRUE; AF := FALSE; OD := FALSE; ID := FALSE; ST := FALSE END; END (* CASE *) END; ELSE BEGIN WRITELN; WRITELN('ENTER NUMBER 1 - 4 '); END (* ELSE *) END (* CASE *) END; (* 5046MENULANG *) FUNCTION MENUA_COMMANDA : INTEGER; VAR CMD : CHAR; BEGIN REPEAT CLEARSCREEN; WRITELN; WRITELN; WRITELN; WRITE(' * * * MAID-III - 5046 TEST PROCESSOR * * * '); WRITELN; WRITELN; WRITELN; WRITELN; WRITELN(' *** MENU *** '); WRITELN; WRITELN('A) - INSTRUCTIONS '); WRITELN('B) - DIRECTORY (.INS .PAC .DAT) '); WRITELN('C) - MAKE PACKET (FILE ) '); WRITELN('D) - MANUAL/OVER-RIDE '); WRITELN('E) - DELETE (FILE) '); WRITELN('F) - DUMP PACKET (FILE) '); WRITELN('G) - DUMP DATA (FILE) '); WRITELN('H) - COMPARE DATA FILES '); WRITELN('I) - EXECUTE PACKET (FILE) '); WRITELN('J) - POST EXECUTION ANALYSIS (PACKET FILE) '); WRITELN('K) - PRINTER (ON/OFF) '); WRITELN('L) - TERMINAL TALK '); WRITELN('M) - PHONE ON TERMINATION '); WRITELN('N) - QUIT '); WRITELN; WRITE(' - enter letter: '); READ(CMD); WRITELN; CASE CMD OF 'A','a' : BEGIN MENUA_COMMANDA := INSTRUC; EXIT END; 'B','b' : BEGIN MENUA_COMMANDA := DIR; EXIT END; 'C','c' : BEGIN MENUA_COMMANDA := MAKPKT; EXIT END; 'D','d' : BEGIN MENUA_COMMANDA := MANUAL; EXIT END; 'E','e' : BEGIN MENUA_COMMANDA := DELPKT; EXIT END; 'F','f' : BEGIN MENUA_COMMANDA := DMPPKT; EXIT END; 'G','g' : BEGIN MENUA_COMMANDA := DMPDAT; EXIT END; 'H','h' : BEGIN MENUA_COMMANDA := CMPDAT; EXIT END;  'I','i' : BEGIN MENUA_COMMANDA := EXECPKT; EXIT END; 'J','j' : BEGIN MENUA_COMMANDA := POSTA; EXIT END; 'K','k' : BEGIN MENUA_COMMANDA := PRNT; EXIT END; 'L','l' : BEGIN MENUA_COMMANDA := TERMTALK; EXIT END; 'M','m' : BEGIN MENUA_COMMANDA := PHONETERM; EXIT END; 'N','n' : BEGIN MENUA_COMMANDA := QUIT; EXIT END; ELSE BEGIN WRITELN; WRITELN('ENTER LETTER A - L '); END (* ELSE *) END (* CASE *) UNTIL FALSE (* FOREVER LOOP *) END; (* MENUA_COMMANDA *) BEGIN (* MAIN PROGRAM *) INITUSER(NAME); FSTPAC := TRUE; REPEAT INIT1(EFW,EF); INIT1(AFW,AF); INIT1(ODW,OD); INIT1(IDW,ID); INIT1(STW,ST); SADD[1] := 0; SADD[2] := 0; EADD[1] := 0; EADD[2] := 0; CASE MENUA_COMMANDA OF INSTRUC : BEGIN INSTRHEADING; WRITE('ENTER FILENAME.TXT: '); KYBRD(F1A,11,' '); PRGCMD := $04;  M5046(PRGCMD); WRITELN; WRITE('TYPE RETURN. '); READ(X) END; (* CASE OF INSTRUC *) DIR : BEGIN DIRHEADING; WRITE('ENTER FILENAME: '); KYBRD(F1A,11,' '); PRGCMD := $05; M5046(PRGCMD); WRITELN; WRITE('TYPE RETURN. '); READ(X) END; (* CASE OF DIRECTORY *) MAKPKT : BEGIN SAVIBF := FALSE; CMP := FALSE; MAKHEADING; MENULANG5046(EFW,AFW,ODW,IDW,STW,EF,AF,OD,ID,ST); REALINT8B(WDXFLEN,XINT,1); XFCNT[1] := XINT; REALINT8B(WDXFLEN,XINT,2); XFCNT[2] := XINT; MAKHEADING; IF EF = TRUE THEN IF FSTPAC = TRUE THEN BEGIN WRITE('ENTER PACKET FILENAME: '); KYBRD(F1C,11,' ') END; IF OD = TRUE THEN BEGIN WRITE('ENTER OUTPUT DATA FILENAME: '); KYBRD(F1B,11,' '); FOR XINT := 1 TO 12 DO F1A[XINT] := F1B[XINT]; WRITE('IS THIS AN EXISTING OUTPUT FILE OR MAKE NEW (E/N): '); READ(X); CASE X OF 'N','n' : BEGIN MAKEBUFFER(ODW,WDXFLEN,PRGCMD,DATMOD,BUFRPT,WRDRPT,PRGCNT) END; ELSE BEGIN WRITELN; SELBASE(BASEREQ); WRITELN; WRITE('ENTER STARTING ADDRESS'); DATAWORD(SADD,0.0,65535.0,BASEREQ,2) END END (* CASE *) END;  IF ID = TRUE THEN BEGIN WRITELN; WRITE('SAVE INPUT DATA TO DISK (Y/N): '); READ(X); CASE X OF 'Y','y' : BEGIN SAVIBF := TRUE END; ELSE SAVIBF := FALSE END END; IF ID = TRUE THEN IF SAVIBF = TRUE THEN BEGIN WRITELN; WRITE('ENTER INPUT DATA FILENAME: '); KYBRD(F1B,11,' ') END; IF ID = TRUE THEN BEGIN WRITELN; WRITE('COMPARE INPUT DATA (Y/N): '); READ(X); CASE X OF 'Y','y' : BEGIN CMP := TRUE; WRITELN; WRITE('ENTER FILENAME TO COMPARE: '); KYBRD(F1A,11,' ') END; ELSE CMP := FALSE END END; IF EF = TRUE THEN BEGIN WRITELN; WRITE('ENTER PACKET REPEAT COUNT'); BASEREQ := 'D'; DATAWORD(PRPCNT,0.0,65535.0,BASEREQ,2); WRITE('IS THIS THE LAST PACKET (Y/N): '); READ(X); CASE X OF 'Y','y' : BEGIN LSTPAC := TRUE END; ELSE LSTPAC := FALSE END END; IF FSTPAC = TRUE THEN PRGMOD := $01; IF FSTPAC = FALSE THEN PRGMOD := $00; PRGCMD := $09; IF EF = TRUE THEN BEGIN M5046(PRGCMD); FSTPAC := FALSE; IF LSTPAC = TRUE THEN FSTPAC := TRUE END; WRITELN; WRITELN('TYPE RETURN. '); READ(X) END; (* CASE OF MAKPKT *) MANUAL : BEGIN MANUALHEADING; WRITELN('SELECT BASE FOR INPUT VALUE '); WRITELN; SELBASE(BASEREQ); WRITELN; WRITE('ENTER TEST - CHANNEL STATUS WORD'); DATAWORD(XSTW,0.0,68719476735.0,BASEREQ,5) END; (* CASE OF CHNGPKT *) DELPKT : BEGIN DELHEADING; WRITE('ENTER FILENAME: '); KYBRD(F1A,11,' '); PRGCMD := $0B; M5046(PRGCMD); WRITELN; WRITE('TYPE RETURN. '); READ(X) END; (* CASE OF DELPKT *) DMPPKT : BEGIN DMPHEADING; WRITE('ENTER PACKET FILENAME: '); KYBRD(F1C,11,' '); PRGCMD := $0B; M5046(PRGCMD); WRITELN; WRITE('TYPE RETURN. '); READ(X) END; (* CASE OF DMPPKT *) DMPDAT : BEGIN DDFHEADING; WRITELN('SELECT BASE FOR INPUT VALUE '); WRITELN; SELBASE(BASEREQ); WRITELN; WRITE('ENTER STARTING ADDRESS'); DATAWORD(SADD,0.0,65535.0,BASEREQ,2); WRITE('ENTER ENDING ADDRESS'); DATAWORD(EADD,0.0,65535.0,BASEREQ,2); WRITE('ENTER FILENAME: '); KYBRD(F1A,11,' ');  PRGCMD := $07; M5046(PRGCMD); WRITELN; WRITE('TYPE RETURN. '); READ(X) END; (* CASE OF DMPDAT *) CMPDAT : BEGIN CMPHEADING; WRITELN('SELECT BASE FOR INPUT VALUE '); WRITELN; SELBASE(BASEREQ); WRITELN; WRITE('ENTER STARTING ADDRESS'); DATAWORD(SADD,0.0,65535.0,BASEREQ,2); WRITE('ENTER ENDING ADDRESS'); DATAWORD(EADD,0.0,65535.0,BASEREQ,2); WRITE('ENTER PRIMARY FILENAME 1: '); KYBRD(F1A,11,' '); WRITE('ENTER SECONDARY FILENAME 2: '); KYBRD(F1B,11,' '); PRGCMD := $08; M5046(PRGCMD); WRITELN; WRITE('TOTAL COMPARE ERRORS = '); WRITELN(ERRCNT); WRITELN; WRITE('TYPE RETURN. '); READ(X) END; (* CASE OF CMPDAT *) EXECPKT : BEGIN EXECHEADING; WRITE('ENTER PACKET FILENAME: '); KYBRD(F1C,11,' '); PRGCMD := $03; M5046(PRGCMD); IF PHTERM = TRUE THEN SETUPCOMM('D'); WRITELN; WRITE('TYPE RETURN. '); READ(X) END; (* CASE OF EXECPKT *) POSTA : BEGIN POSTHEADING; END; PRNT : BEGIN PRGCMD := $0A; M5046(PRGCMD); WRITELN; WRITE('TYPE RETURN '); READ(X) END; (* CASE OF PRNT *) TERMTALK : BEGIN REPEAT CTRLE := ' '; TERMHEADING; WRITELN(' TYPE CTRL - C :TO ENTER MODEM COMMAND STRING (ORGINATE) '); WRITELN(' TYPE CTRL - H :TO BACK SPACE. '); WRITELN(' TYPE CTRL - L :TO CLEAR SCREEN. '); WRITELN(' TYPE CTRL - E :TO RETURN TO MENU. '); WRITELN; WRITELN; WRITELN; WRITELN; REPEAT READ(TALK); IF TALK = CHR(05) THEN BEGIN CTRLE := CHR(05); TALK := CHR(12) END; IF TALK = CHR(3) THEN SETUPCOMM('C'); UNTIL TALK = CHR(12); UNTIL CTRLE = CHR(05) END; (* CASE OF TERMINAL TALK *) PHONETERM : BEGIN PHTERM := FALSE; PHTERMHEADING; WRITE('PHONE ON TERMINATION (Y/N): '); READ(X); IF X = 'Y' THEN PHTERM := TRUE;  IF X = 'y' THEN PHTERM := TRUE; END; (* CASE OF PHONE ON TERMINATION *) QUIT : BEGIN EXIT END (* CASE OF QUIT *) END (* CASE *) UNTIL FALSE (* FOREVER *) END.  TALK = CHR(05) THEN BEGIN CTRLE := CHR(05); TALK := CHR(12) END; IF TALK = CHR(3) THEN SETUPCOMM('C'); UNTIL TALK = CHR(12); UNTIL CTRLE = CHR(05) END; (* CASE OF TERMINAL TALK *) PHONETERM : BEGIN PHTERM := FALSE; PHTERMHEADING; WRITE('PHONE ON TERMINATION (Y/N): '); READ(X); IF X = 'Y' THEN PHTERM := TRUE; ;WRITTEN BY RUSSELL F. BUSHNELL JR. ;MARCH 30, 1987 ; ; ; ;MACHINE LANGUAGE RUN-TIME SYSTEM FOR 5046 TEST ; ; ; ; PPI0PA EQU 0020H;PORT A(PPI0, IC10) PPI0PB EQU 0021H;PORT B(PPI0, 1C10) PPI0PC EQU 0022H;PORT C(PPI0, IC10) PPI1PA EQU 0024H;PORT A(PPI1, IC11) PPI1PB EQU 0025H;PORT B(PPI1, IC11) PPI1PC EQU 0026H;PORT C(PPI1, IC11) PPI2PA EQU 0028H;PORT A(PPI2, IC12) PPI2PB EQU 0029H;PORT B(PPI2, IC12) PPI2PC EQU 002AH;PORT C(PPI2, IC12) PPI3PA EQU 002CH;PORT A(PPI3, IC13) PPI3PB EQU 002DH;PORT B(PPI3, IC13) PPI3PC EQU 002EH;PORT C(PPI3, IC13) PPI4PA EQU 0030H;PORT A(PPI4, IC28) PPI4PB EQU 0031H;PORT B(PPI4, IC28) PPI4PC EQU 0032H;PORT C(PPI4, IC28) PPI5PA EQU 0040H;PORT A(PPI5, IC55) PPI5PB EQU 0041H;PORT B(PPI5, IC55) PPI5PC EQU 0042H;PORT C(PPI5, IC55) PPI6PA EQU 0044H;PORT A(PPI6, IC56) PPI6PB EQU 0045H;PORT B(PPI6, IC56) PPI6PC EQU 0046H;PORT C(PPI6, IC56) PPI7PA EQU 0048H;PORT A(PPI7, IC57) PPI7PB EQU 0049H;PORT B(PPI7, IC57) PPI7PC EQU 004AH;PORT C(PPI7, IC57) PPI8PA EQU 004CH;PORT A(PPI8, IC58) PPI8PB EQU 004DH;PORT B(PPI8, IC58) PPI8PC EQU 004EH;PORT C(PPI8, IC58) PPICP0 EQU 0023H;CONTROL PORT 0(PPI0, IC10) PPICP1 EQU 0027H;CONTROL PORT 1(PPI1, IC11) PPICP2 EQU 002BH;CONTROL PORT 2(PPI2, IC12) PPICP3 EQU 002FH;CONTROL PORT 3(PPI3, IC13) PPICP4 EQU 0033H;CONTROL PORT 4(PPI4, IC28) PPICP5 EQU 0043H;CONTROL PORT 5(PPI5, IC55) PPICP6 EQU 0047H;CONTROL PORT 6(PPI6, IC56) PPICP7 EQU 004BH;CONTROL PORT 7(PPI7, IC57) PPICP8 EQU 004FH;CONTROL PORT 8(PPI8, IC58) PIC0L EQU 0034H;HEX 34 = PORT(PIC0, IC14) PIC0H EQU 0035H;HEX 35 = PORT(PIC0, IC14) ICW1 EQU 0012H;HEX 12 = LWRADDR A7-A5, INTERVAL = 8, SINGLE ICW2 EQU 0003H;HEX 03 = UPPADDR A15-A8(UPPER ROUTINE ADDRESS) ICW3 EQU 0000H;HEX 00 = IR INPUT HAS NO SLAVE OCW1 EQU 0000H;HEX 00 = MASK RESET OCW2 EQU 0020H;HEX 20 =NON-SPEC. EOI(RESET HIGHEST PRI. BIT OF ISR) OCW3 EQU 000FH;HEX 0F = POLLING ON NEXT READ (BCD OF HIGHEST INT.) CTLWD1 EQU 0080H;HEX 80 = PORTS(A,B,C = OUTPUT) CTLWD2 EQU 009BH;HEX 9B = PORTS(A,B,C = INPUT) CTLWD3 EQU 00BEH;HEX BE = PORTS(A,B = INPUT, C = INTERRUPT) CTLWD4 EQU 0009H;HEX 9 = PPI INTE A ENABLE (SET BIT VALUE - PC4) CTLWD5 EQU 0005H;HEX 5 = PPI INTE B ENABLE (SET BIT VALUE - PC2) CTLWD7 EQU 0092H;HEX 92 = PORTS(A,B = INPUT, C = OUTPUT) CTLWD8 EQU 0089H;HEX 89 = PORTS(A,B = OUTPUT, C = INPUT) CTLWD9 EQU 0081H;HEX 81 = PORTS(A,B,C4-C7 = OUTPUT, C0-C3 = INPUT) EFTAG EQU 10H;EXTERNAL FUNCTION CONTROL TAG OATAG EQU 20H;OUTPUT ACKNOWLEDGE CONTROL TAG IATAG EQU 40H;INPUT ACKNOWLEDGE CONTROL TAG CLRTAG EQU 80H;CLEAR SUBSYSTEM CONTROL TAG ODRTAG EQU 10H;OUTPUT DATA REQUEST CONTROL TAG (INPUT SIGNAL) IDRTAG EQU 20H;INPUT DATA REQUEST CONTROL TAG (INPUT SIGNAL) EITAG EQU 40H;EXTERNAL INTERRUPT CONTROL TAG (INPUT SIGNAL) IPERR EQU 80H;INPUT PARITY ERROR SIGNAL (INPUT SIGNAL) ODRINT EQU 81H;OUTPUT DATA REQUEST INTERRUPT VALUE (INPUT - PIC) IDRINT EQU 82H;INPUT DATA REQUEST INTERRUPT VALUE (INPUT - PIC) EIINT EQU 80H;EXTERNAL INTERRUPT INTERRUPT VALUE (INPUT - PIC) IPERRINT EQU 83H;INPUT PARITY ERROR SIGNAL INTERRUPT VALUE(INPUT - PIC) IHRDWAR0 EQU 00H;0 = INITILIZE HARDWARE COMMAND (MODE 0) IHRDWAR1 EQU 01H;1 = INITILIZE HARDWARE COMMAND (MODE 1) EXPAC EQU 03H;3 = EXECUTE PACKET COMMAND INSTRUC EQU 04H;4 = INSTRUCTION COMMAND DIR EQU 05H;5 = DIRECTORY COMMAND SPDAT EQU 06H;6 = SAVE PACKET DATA (FILE) DPDAT EQU 07H;7 = DUMP PACKET DATA (FILE) CPDATF EQU 08H;8 = COMPARE PACKET DATA (FILES) MAKPAC EQU 09H;9 = MAKE PACKET (SAVE TO DISK) PRNTC EQU 0AH;A = TOGGLE PRINTER COMMAND DELFIL EQU 0BH;B = DELETE FILE COMMAND DMPPKT EQU 0CH;C = DUMP PACKET COMMAND APOST EQU 0DH;D = POST ANALYSIS BADCMDS EQU 0FFH;FF = BAD COMMAND STATUS GOODST EQU 00H;0 = GOOD STATUS (NORMAL COMMAND COMPLETION) DATERR EQU 01H;1 = DATA ERROR FRMT1 EQU 01H;1 = STATUS FORMAT/TABLE 1 CONDT EQU 01H;CONDITION TRUE CONDF EQU 00H;CONDITION FALSE ZERO EQU 00H;0=0 ONE EQU 01H;1=1 RECSIZ EQU 128;IBM 3740 RECORD SIZE ABUFSIZ EQU 0400H;0400 HEX = 1024 DEC BBUFSIZ EQU 0400H;0400 HEX = 1024 DEC CBUFSIZ EQU 0400H;0400 HEX = 1024 DEC BOOT EQU 0000H;CPM REBOOT (WARM START) FDOS EQU 0005H;CPM DOS ENTRY POINT DCONF EQU 6;DIRECT CONSOLE I/O FUNCTION 6 CONINF EQU 1;CONSOLE INPUT FUNCTION 1 CONOUTF EQU 2;CONSOLE OUTPUT FUNCTION 2 OPENF EQU 15;OPEN FILE FUNCTION 15 CLOSEF EQU 16;CLOSE FILE FUNCTION 16 DELETEF EQU 19;DELETE FILE FUNCTION 19 READF EQU 20;SEQUENTIAL READ FUNCTION 20 WRITEF EQU 21;SEQUENTIAL WRITE FUNCTION 21 MAKEF EQU 22;MAKE FILE FUNCTION 22 SDMADD EQU 26;SET DMA ADDRESS FUNCTION 26 SCHFST EQU 17;SEARCH FOR FIRST FUNCTION 17 SCHNXT EQU 18;SEARCH FOR NEXT FUNCTION 18 CONSTF EQU 11;GET CONSOL STATUS FUNCTION 11 DWDLIN EQU 0006H;DATA WORDS PER LINE BIOSL1 EQU 0E833H;BIOS M259NCPC - AUTO CONSOLE PRINTER LOC. BIOSL2 EQU 0FC33H;BIOS M264NCPC - AUTO CONSOLE PRINTER LOC. BIOSL3 EQU 0E883H;BIOS B59MB3NC - AUTO CONSOLE PRINTER LOC. LENGA EQU 5BH;5BH = 91D LENGB EQU 04H;04H = 4D LENGC EQU 0BH;0BH = 11D FALSE EQU 0;VALUE OF FALSE TRUE EQU NOT FALSE;VALUE OF TRUE TEST1 EQU TRUE;ASSEMBLE PROGRAM IN TEST MODE MSGSA EQU TRUE;MESSAGE SET A (STATUS WORD) AHLPMSG EQU FALSE;INCLUDE STATUS HELP MESSAGES ; ORG 0A800H;WHERE THIS PROGRAM RUNS IN MEMORY ; ;NOTE - 1)ASM THIS PROGRAM. ; 2)LOAD HEX FILE AND MAKE A CPM COM FILE. ; 3)LOAD DDT,LOAD COM FILE. ; 4)PUT A JMP TO ORG LOCATION OF THIS PROGRAM AT ; MEMORY LOCATION 0100 (BEGINING OF TPA). ; 5)DO A CTRL C TO WARM BOOT CPM. ; 6)TYPE THIS - SAVE 164 M5046.COM (OR OTHER FILE NAME). ; 7)RUN NEW COM FILE "M5046" (5046 RUN-TIME SYSTEM). ; 8)THEN RUN PASCAL COUNTER PART. ; LXI H,SMSG;DISPLAY SIGNON MESSAGE CALL PMSG;DO IT! JMP BOOT;JUMP TO CPM ; JMP ISWM0;THIS LOCATION IS FORMAL ENTRY ADDRESS ; ;FORMAL PARAMETERS (USER LANGUAGE - INTERFACE) ; LDKEY: DB 0AAH;RUN TIME SYSTEM LOAD KEY (LOC./VALUE) SADD: DB 00H;LSB OF STARTING ADDRESS DB 00H;MSB OF STARTING ADDRESS EADD: DB 0FFH;LSB OF ENDING ADDRESS DB 3FH;MSB OF ENDING ADDRESS SDATA: DB 00H;LSB OF STARTING DATA (SEED WORD) DB 00H; DB 00H; DB 00H; DB 00H; EDATA: DB 00H;LSB OF ENDING DATA DB 00H; DB 00H; DB 00H; DB 00H; XADD: DB 00H;LSB - SCRATCH ADDRESS (RUN-TIME) DB 00H; DB 00H; DB 00H; DB 00H; XDATA: DB 00H;LSB - SCRATCH DATA (RUN-TIME) DB 00H; DB 00H; DB 00H; DB 00H; PRGCMD: DB 03H;PROGRAM COMMAND PRGMOD: DB 00H;MISC. PROGRAM MODIFIERS CMDMOD: DB 00H;MISC. COMMAND MODIFIERS DATMOD: DB 00H;MISC. DATA MODIFIERS PRGCNT: DB 00H;LSB - MISC. COUNTER DB 00H;MSB - MISC. COUNTER XPRGCNT: DB 00H;LSB - MISC. SCRATCH COUNTER DB 00H;MSB - MISC. SCRATCH COUNTER CBIAS: DB 00H;LSB - COUNTER BIAS DB 00H;MSB - COUNTER BIAS HSTATS: DB 00H;HARDWARE STATUS DB 00H;FORMAT/TABLE PSTATS: DB 00H;PROGRAM STATUS DB 00H;FORMAT/TABLE ERRCNT: DB 00H;ERROR COUNTER (LSB) DB 00H;ERROR COUNTER (MSB) RETRYC: DB 00H;RETRY COUNTER (LSB) DB 00H;RETRY COUNTER (MSB) RETRYX: DB 00H;CURRENT RETRY COUNT (LSB) DB 00H;CURRENT RETRY COUNT (MSB) FCBA: DRA: DB 00H;START OF FILE CONTROL BLOCK A (SEE CPM INTERFACE GUIDE) FILENA: F1A: DB 'F';NEXT ELEVEN BYTES FOR FILENAME A DB 'I'; DB 'L'; DB 'E'; DB ' '; DB 'A'; DB ' '; F8A: DB ' '; T1A: DB ' '; T2A: DB ' '; T3A: DB ' '; EXA: DB 00H; S1A: DB 00H; S2A: DB 00H; RCA: DB 00H; D0A: DS 16; CRA: DB 00H; R0A: DB 00H; R1A: DB 00H; R2A: DB 00H; FCBB: DRB: DB 00H;START OF FILE CONTROL BLOCK B FILENB: F1B: DB 'F';NEXT ELEVEN BYTES FOR FILENAME B  DB 'I'; DB 'L'; DB 'E'; DB ' '; DB 'B'; DB ' '; F8B: DB ' '; T1B: DB ' '; T2B: DB ' '; T3B: DB ' '; EXB: DB 00H; S1B: DB 00H; S2B: DB 00H; RCB: DB 00H; D0B: DS 16; CRB: DB 00H; R0B: DB 00H; R1B: DB 00H; R2B: DB 00H; FCBC: DRC: DB 00H;START OF FILE CONTROL BLOCK C FILENC: F1C: DB 'F';NEXT ELEVEN BYTES FOR FILENAME C DB 'I'; DB 'L'; DB 'E'; DB ' '; DB 'C'; DB ' '; F8C: DB ' '; T1C: DB ' '; T2C: DB ' '; T3C: DB ' '; EXC: DB 00H; S1C: DB 00H; S2C: DB 00H; RCC: DB 00H; D0C: DS 16; CRC: DB 00H; R0C: DB 00H; R1C: DB 00H; R2C: DB 00H; ABUFF: DS RECSIZ;SPACE FOR RECORD A BBUFF: DS RECSIZ;SPACE FOR RECORD B PBUFF: DS RECSIZ;SPACE FOR RECORD C ABPTR: DB 00H;BUFFER POINTER A (LSB) DB 00H;BUFFER POINTER A (MSB) BBPTR: DB 00H;BUFFER POINTER B (LSB) DB 00H;BUFFER POINTER B (MSB) PBPTR: DB 00H;BUFFER POINTER C (LSB) DB 00H;BUFFER POINTER C (MSB) XCNTR: DB 00H;SCRATCH COUNTER (LSB) DB 00H;SCRATCH COUNTER (MSB) XCNTRB: DB 00H;SCRATCH COUNTER (LSB) DB 00H;SCRATCH COUNTER (MSB) STKPTR: DB 00H; DB 00H; DS 80H;128 BYTES FOR NEW STACK AREA NEWSTK: DB 00H;THIS LOCATION IS TOP OF STACK PRNSTS: DB 00H;BIOS VER. AVAILABLE - 00=NOT YET,FF=NO,C9=YES DB 00H;BIOS IDENTIFIER 1,2 OR 3 DB 0C9H;PRINTER ON / OFF STATUS BYTE 0=ON, C9=OFF DB 00H; DB 00H; WMEMIO: DB 03H;HEX 03 = NO WAIT-STATES FOR MEMORY OR I/O EFW: DB 00H;BITS 0 - 7 OF THE EXTERNAL FUNCTION WORD (LSB) DB 00H;BITS 8 - 15 OF THE EFW DB 00H;BITS 16 - 23 OF THE EFW DB 00H;BITS 24 - 31 OF THE EFW DB 00H;BITS 32 - 39 OF THE EFW (MSB) AFW: DB 00H;BITS 0 - 7 OF THE ADDRESS FUNCTION WORD (LSB) DB 00H;BITS 8 - 15 OF THE AFW DB 00H;BITS 16 - 23 OF THE AFW DB 00H;BITS 24 - 31 OF THE AFW DB 00H;BITS 32 - 39 OF THE AFW (MSB) ODW: DB 00H;BITS 0 - 7 OF THE OUTPUT DATA WORD (LSB) DB 00H;BITS 8 - 15 OF THE ODW DB 00H;BITS 16 - 23 OF THE ODW DB 00H;BITS 24 - 31 OF THE ODW DB 00H;BITS 32 - 39 OF THE ODW (MSB) IDW: DB 00H;BITS 0 - 7 OF THE INPUT DATA WORD (LSB) DB 00H;BITS 8 - 15 OF THE IDW DB 00H;BITS 16 - 23 OF THE IDW DB 00H;BITS 24 - 31 OF THE IDW DB 00H;BITS 32 - 39 OF THE IDW (MSB) STW: DB 00H;BITS 0 - 7 OF THE STATUS WORD (LSB) DB 00H;BITS 8 - 15 OF THE STW DB 00H;BITS 16 - 23 OF THE STW DB 00H;BITS 24 - 31 OF THE STW DB 00H;BITS 32 - 39 OF THE STW (MSB) XFCNT: DB 00H;TRANSFER COUNT (LSB) DB 00H;(MSB) LOWSP: DB 00H;LOW SPEED MODIFIER HIGHSP DB 00H;HIGH SPEED MODIFIER CMPMOD: DB 00H;COMPARE MOD. CLRMOD: DB 00H;CLEAR MOD. EFWMOD: DB 00H;EF MOD. (PACKET HAS EF TO SEND) AFWMOD: DB 00H;AF MOD. IDWMOD: DB 00H;ID MOD. ODWMOD: DB 00H;OD MOD. EIWMOD: DB 00H;EI MOD. PARMOD: DB 00H;PARITY MOD. MSTOP: DB 00H;MENU STOP MOD. ONERR: DB 00H;ON ERROR MOD. INVEF: DB 00H;CAUSE INVALID EF MOD. INVTAG: DB 00H;CAUSE INVALID TAG MOD. INVPAR: DB 00H;CAUSE PARITY ERROR MOD. INVTIM: DB 00H;CAUSE TIME-OUT MOD. TIMCNT: DB 00H;TIME-OUT COUNT VALUE (LSB) DB 00H;(MSB) RECSB: DB 00H;RECOVER SENSE BYTES MOD. RECUL: DB 00H;RECOVER USAGE LOG MOD. DRECA: DB 00H;DO RECOVERY ACTION ON ERROR MOD. SAVIBF: DB 00H;SAVE INPUT BUFFER TO DISK MOD. CMPSTW: DB 01H;COMPARE STATUS WORD MODIFIER DISPSTW: DB 01H;DISPLAY STATUS WORD MODIFIER DSPSHLP: DB 00H;DISPLAY STW HELP MODIFIER SVSTSN: DB 01H;SAVE STW & SENSE BYTES TO DISK (PACKET) STWREC: DB 01H;STW RECOVERY ENABLE MODIFIER ANASTW: DB 01H;ANALYZE STW FOR FANCY DISPLAY AND RECOVERY XSTW: DB 00H;INPUT STW STORAGE DB 00H; DB 00H; DB 00H; DB 00H;MSB OF STW BUFRPT: DB 01H;REPEATING BUFFER MODIFIER WRDRPT: DB 01H;REPEATING WORD MODIFIER (BUFRPT MUST ALSO BE SET) LSTPAC: DB 01H;LAST PACKET MODIFIER (IN FILE) PRPCNT: DB 00H;PACKET REPEAT COUNT (LSB) DB 00H;(MSB) ;EXTRA: DS 03H;FUTURE SENSEBYT DS 24H;BUFFER FOR 24 SENSE BYTES XA: DB 00H;SCRATCH STORAGE 0-4 DB 00H; DB 00H; DB 00H; DB 00H; XB: DB 00H;SCRATCH STORAGE 0-4 DB 00H; DB 00H; DB 00H; DB 00H; STATET: DB 00H;STATE OF CHANNEL TAG (LSB) DB 00H;(MSB) WTAG: DB 00H;CURRENT TAG (DURING WAIT) TWCNT: DB 00H;CURRENT COUNT FOR TIME-OUT (LSB) DB 00H;(MSB) TMCNT: DB 00H;MAX COUNT FOR TIME-OUT (LSB) DB 00H;(MSB) EFCNT: DB 00H;TOTAL EF COUNT (LSB) DB 00H;(MSB) AFCNT: DB 00H;TOTAL AF COUNT (LSB) DB 00H;(MSB) ODCNT: DB 00H;TOTAL OD COUNT (LSB) DB 00H;(MSB) IDCNT: DB 00H;TOTAL ID COUNT (LSB) DB 00H;(MSB) STCNT: DB 00H;TOTAL EI COUNT (LSB) DB 00H;(MSB) PASS: DB 00H;FOR LOOP CONTROL XXFCNT: DB 00H;TEMP - SAVE XFER CNT (LSB) DB 00H;(MSB) ; ; ; ; ISWM0:;INITILIZE SOFTWARE MODE 0 PUSH PSW; PUSH B; PUSH D; PUSH H; LXI H,0000H; DAD SP; SHLD STKPTR; LXI SP,NEWSTK;ASSIGN NEW STACK MVI A,00H;CLEAR A REG STA HSTATS;CLEAR HARDWARE STATUS (LAST) STA PSTATS;CLEAR PROGRAM STATUS (LAST) STA ERRCNT;CLEAR ERROR COUNTER (LSB) STA ERRCNT + 1;CLEAR ERROR COUNTER (MSB) LDA SADD;INIT STARTING ADDRESS (LSB) STA XADD; LDA SADD + 1;INIT STARTING ADDRESS (MSB) STA XADD + 1; LDA SDATA;INIT STARTING DATA (LSB) STA XDATA; LDA SDATA + 1 STA XDATA + 1 LDA SDATA + 2 STA XDATA + 2 LDA SDATA + 3 STA XDATA + 3 LDA SDATA + 4 STA XDATA + 4 LDA PRGCNT;INIT MISC. COUNTER (LSB) STA XPRGCNT; LDA PRGCNT + 1;INIT MISC. COUNTER (MSB) STA XPRGCNT + 1; JMP GETCMD ; IHRDWM0:;INITILIZE HARDWARE MODE 0 MVI A,CTLWD1; OUT PPICP1; OUT PPICP2; MVI A,CTLWD2; OUT PPICP6; OUT PPICP7; MVI A,CTLWD3; OUT PPICP8; MVI A,CTLWD4; OUT PPICP8; OUT PPICP5; MVI A,CTLWD5; OUT PPICP8; OUT PPICP5; IN PPI8PA; IN PPI8PB; IN PPI5PA; IN PPI5PB; MVI A,CTLWD1; OUT PPICP0; LDA WMEMIO; OUT PPI0PC; MVI A,ICW1; OUT PIC0L; MVI A,ICW2; OUT PIC0H; MVI A,ICW3; PIC35; JMP HLEVLG ; IHRDWM1:;INITILIZE HARDWARE MODE 1 JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; GETCMD: LDA PRGCMD;GET COMMAND CPI IHRDWAR0;INITILIZE HARDWARE(MODE 0) COMMAND JZ IHRDWM0;IF PRGCMD - THEN INITILIZE HARDWARE CPI IHRDWAR1;INITILIZE HARDWARE(MODE 1) COMMAND JZ IHRDWM1;IF PRGCMD - THEN INITILIZE HARDWARE CPI EXPAC;EXECUTE PACKET JZ RUNPAC;IF PRGCMD - THEN EXECUTE PACKETS CPI INSTRUC;INSTRUCTIONS JZ DTXTF;IF PRGCMD - THEN DUMP ASCII TEXT FILE CPI DIR;DISPLAY DIRECTORY JZ DDIR;IF PRGCMD - THEN DISPLAY DIRECTORY CPI DELFIL;DELETE FILE JZ FILDEL;IF PRGCMD - THEN DELETE FILE CPI DMPPKT;DUMP PACKET JZ PKTDMP;IF PRGCMD - THEN DUMP PACKET CPI APOST;POST ANALYSIS JZ POSTANA;IF PRGCMD - THEN POST PACKET ANALYSIS CPI SPDAT;SAVE PACKET DATA JZ SAVDAT;IF PRGCMD - THEN SAVE PACKET DATA CPI DPDAT;DUMP PACKET DATA JZ DFILES;IF PRGCMD - THEN DUMP PACKET DATA CPI CPDATF;COMPARE PACKET DATA FILES JZ CFILES;IF PRGCMD - THEN COMPARE PACKET DATA FILES CPI MAKPAC;MAKE PACKET (SAVE TO DISK) JZ SAVPAC;THEN SAVE PACKET (ACTUAL TEST) CPI PRNTC;TOGGLE PRINTER COMMAND JZ PRNT;IF PRGCMD - THEN TOGGLE PRINTER ON OR OFF MVI A,BADCMDS;BAD COMMAND STA PSTATS JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ON BAD COMMAND HLEVLG: LHLD STKPTR SPHL POP H POP D POP B POP PSW RET;BACK TO HIGH LEVEL LANGUAGE ; ;PRINT THE MESSAGE AT H AND L UNTIL A ZERO ; PMSG: MOV A,M;GET A CHAR. ADDRESSED BY THE H AND L REG. ORA A;IF ITS'S STILL ZERO, RZ;RETURN MOV E,A; MVI A,CONOUTF; MOV C,A; PUSH H; CALL FDOS; POP H; INX H;INCREMENT REG PAIR H AND L JMP PMSG;AND GET ANOTHER CHARACTER ; ;PUT ALL MESSAGES HERE ; SMSG:;SIGNON MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '5046 RUN TIME SYSTEM IS NOW LOADED',0 ; MSG1:;FILE EXISTS MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'FILE ALREADY EXISTS',0 ; MSG2:;FILE CREATED MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'FILE CREATED',0 ; MSG3:;NO DIRECTORY SPACE MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THE DIRECTORY IS FULL AND/OR DISK IS WRITE PROTECTED',0 ; MSG4:;FILE OPEN MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'FILE OPENED SUCCESSFULLY',0 ; MSG5:;FILE NO DID CLOSE MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'UNABLE TO CLOSE FILE',0 ; MSG6:;WRITE ERROR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'WRITE ERROR - DISK IS FULL AND/OR DISK IS WRITE PROTECTED',0 ; MSG7:;FILE CLOSE MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'FILE CLOSED SUCCESSFULLY',0 ; MSG8:;UNABLE TO OPEN MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED  DB 'UNABLE TO OPEN FILE',0 ; MSG9:;OUT OF DATA MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'READ ERROR - OUT OF DATA (EOF)',0 ; MSG10:;SHOULD BE MESSAGE DB 'SHOULD BE = ',0 ; MSG11:;WAS MESSAGE DB ' WAS = ',0 ; MSG12:;DATA COMPARE ERROR MESSAGE DB 'DATA COMPARE ERROR - ',0 ; MSG13:;TOTAL ERROR MESSAGE DB 'TOTAL ERRORS = ',0 ; MSG14:;FILE NO DID DELETE MESSAGE DB 0DH,0AH;CR&LF DB 'UNABLE TO DELETE FILE',0 ; MSG15:;DELETE FILE MESSAGE DB 0DH,0AH;CR&LF DB 'FILE DELETED',0 ; MSG16:;MISC. DB ' : ',0; ; MSG17:;MISC. DB 0DH,0AH,0; ; MSG18:;MISC. DB ' ',0; ; MSG21:;HEX MESSAGE DB ' (HEX) ',0 ; MSG22:;WRONG BIOS MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'SORRY - WRONG BIOS VERSION!!! ',0 ; MSG23:;PRINTER ON MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'PRINTER IS NOW ON! ',0 ; MSG24:;PRINTER OFF MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'PRINTER IS NOW OFF! ',0 ; MSG30:;STATUS HEADER MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 0AH;LINE FEED DB ' * * * MAID-III - 5046 CHANNEL STATUS WORD ' DB '(BITS 35 - 0) * * * ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 0AH;LINE FEED DB 00H;END OF MESSAGE ID. ; IF MSGSA;ASSEMBLE IF MESSAGE SET A MSG31:;CT MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - CHANNEL TRUNCATION BIT IS SET (CT - STATUS BIT 31) ',0 ; ENDIF; IF AHLPMSG MSG32:;CT HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THE CHANNEL TRUNCATION BIT, IN BIT POSITION 31; IS SET TO' DB 0DH,0AH; DB 'INDICATE TRUNCATION OF DATA TRANSFER WHEN THE CHANNEL ' DB 0DH;0AH; DB 'FAILS TO RESPOND TO AN INPUT OR OUTPUT DATA WORD REQUEST' DB 0DH,0AH; DB 'WITHIN 2 MILLISECONDS.CHANNEL TRUNCATION MAY REPRESENT AN' DB 0DH,0AH; DB 'ABNORMAL CONDITION AS A RESULT OF A PROGRAMMING ERROR OR ' DB 0DH,0AH; DB 'A HARDWARE MALFUNCTION. HOWEVER, CHANNEL TRUNCATION CAN ' DB 0DH,0AH; DB 'BE AN EXPECTED CONDITION FOR CERTAIN COMMAND USAGES OR ' DB 0DH,0AH; DB 'WHEN A FORCED EF IS USED TO TERMINATE DATA TRANSFER. ' DB 0DH,0AH; DB 'CHANNEL TRUNCATION MAY ALSO BE SPECIFIED BY THE STATUS ' DB 0DH,0AH; DB 'ACTION VALUE. ',0 ; ENDIF; IF MSGSA; MSG33:;STATUS ACTION MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - STATUS ACTION = ',0 ; ENDIF; IF AHLPMSG; MSG34:;STATUS ACTION HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' ',0 ; ENDIF; IF MSGSA; MSG35:;STATUS ACTION VALUE MESSAGE DB 'START A READ LABEL COMMAND FOR THE CURRENT DEVICE (01H).',0 ; ENDIF; IF AHLPMSG; MSG36:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY WITH ATTENTION STATUS' DB 0DH,0AH; DB 'ALONE AND INDICATES A DISK PACK CHANGE CONDITION AT THE' DB 0DH,0AH; DB 'CURRENT DISK UNIT. THIS ACTION WILL BE PRESENTED IN AN' DB 0DH,0AH; DB 'UNSOLICITED STATUS WORD. ',0 ; ENDIF; IF MSGSA; MSG37:;STATUS ACTION VALUE MESSAGE DB 'START A READ LABEL COMMAND FOR THE CURRENT DEVICE (02H).',0 ; ENDIF; IF AHLPMSG; MSG38:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY WITH ATTENTION AND' DB 0DH,0AH; DB 'BUSY STATUS. THIS INDICATES THAT THE CU HAS TERMINATED THE' DB 0DH,0AH; DB 'CURRENT COMMAND PRIOR TO EXECUTION BECAUSE OF A DISK PACK' DB 0DH,0AH;  DB 'CHANGE CONDITION AT THE SAME DISK UNIT AS SPECIFIED IN' DB 0DH,0AH; DB 'THIS COMMAND. ',0 ; ENDIF; IF MSGSA; MSG39:;STATUS ACTION VALUE MESSAGE DB 'RESTART THE CURRENT COMMAND FOR THE CURRENT DEVICE (03H).' ; ENDIF; IF AHLPMSG; MSG40:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY WITH STATUS MODIFIER,' DB 0DH,0AH; DB 'CONTROL UNIT END, AND BUSY STATUS. THIS ACTION INDICATES' DB 0DH,0AH; DB 'THAT THE OPERATION INITIATED BY THE CURRENT COMMAND IS ' DB 0DH,0AH; DB 'BEING PROCESSED AT THE DISK UNIT, INDEPENDENT OF THE CU,' DB 0DH,0AH; DB 'AND THAT A SECONDARY STATUS WORD WILL BE PRESENTED LATER' DB 0DH,0AH; DB 'FOR THE SAME DISK UNIT. ',0 ; ENDIF; IF MSGSA; MSG41:;STATUS ACTION VALUE MESSAGE DB 'START NEXT COMMAND FOR ANY OTHER AVAILABLE DEVICE(04H).',0 ; ENDIF; IF AHLPMSG; MSG42:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY FOR CONTROL COMMANDS' DB 0DH,0AH; DB 'WITH CHANNEL END STATUS ALONE. THIS ACTION INDICATES THAT' DB 0DH,0AH; DB 'THE CU HAS TERMINATED THE CURRENT COMMAND PRIOR TO EXE- ' DB 0DH,0AH; DB 'CUTION BECAUSE AN EF-EI COLLISION HAS OCCURRED ON THIS' DB 0DH,0AH; DB 'COMMAND. ',0 ; ENDIF; IF MSGSA; MSG43:;STATUS ACTION VALUE MESSAGE DB 'START THE NEXT COMMAND FOR THE CURRENT DEVICE (05H).',0 ; ENDIF; IF AHLPMSG; MSG44:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY FOR CONTROL COMMANDS' DB 0DH,0AH; DB 'WITH DEVICE END STATUS ALONE OR WITH CHANNEL END AND DEVICE' DB 0DH,0AH; DB 'END STATUS TOGETHER. THIS ACTION INDICATES THAT DISK UNIT'  DB 0DH,0AH; DB 'POSITIONING HAS BEEN COMPLETED. ',0 ; ENDIF; IF MSGSA; MSG45:;STATUS ACTION VALUE MESSAGE DB 'START THE NEXT COMMAND FOR ANY AVAILABLE DEVICE (06H).',0 ; ENDIF; IF AHLPMSG; MSG46:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY FOR WRITE OR READ' DB 0DH,0AH; DB 'COMMANDS WITH CHANNEL END AND DEVICE END STATUS. THIS' DB 0DH,0AH; DB 'ACTION INDICATES NORMAL COMMAND COMPLETION WITHOUT' DB 0DH,0AH; DB 'CHANNEL TRUNCATION. ',0 ; ENDIF; IF MSGSA; MSG47:;STATUS ACTION VALUE MESSAGE DB 'START THE NEXT COMMAND FOR ANY AVAILABLE DEVICE (07H).',0 ; ENDIF; IF AHLPMSG; MSG48:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY FOR SENSE COMMANDS,' DB 0DH,0AH; DB 'EXCEPT THE SENSE I/O COMMANDS, WITH CHANNEL END AND DEVICE' DB 0DH,0AH; DB 'END STATUS. THIS ACTION INDICATES NORMAL COMMAND COMPLETION' DB 0DH,0AH; DB 'WITHOUT CHANNEL TRUNCATION. ',0 ; ENDIF; IF MSGSA; MSG49:;STATUS ACTION VALUE MESSAGE DB 'PERFORM ERROR RECOVERY WITH SENSE DATA (08H). ',0 ; ENDIF; IF AHLPMSG; MSG50:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY FOR THE SENSE I/O' DB 0DH,0AH; DB 'COMMAND WITH CHANNEL END AND DEVICE END STATUS. THIS ' DB 0DH,0AH; DB 'ACTION INDICATES NORMAL COMMAND COMPLETION WITHOUT' DB 0DH,0AH; DB 'CHANNEL TRUNCATION. ',0 ; ENDIF; IF MSGSA; MSG51:;STATUS ACTION VALUE MESSAGE DB 'PERFORM ERROR RECOVERY WITHOUT COMPLETE SENSE DATA (09H).',0 ; ENDIF; IF AHLPMSG; MSG52:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY FOR THE SENSE I/O' DB 0DH,0AH; DB 'COMMAND WITH CHANNEL END AND DEVICE END STATUS. THIS' DB 0DH,0AH; DB 'ACTION INDICATES THAT COMPLETE SENSE DATA WAS NOT TRANS-' DB 0DH,0AH; DB 'FERRED. THIS STATUS ACTION MAY BE PRESENTED BECAUSE VALID' DB 0DH,0AH; DB 'SENSE INFORMATION WAS NOT AVAILABLE OR BECAUSE CHANNEL' DB 0DH,0AH; DB 'TRUNCATION OCCURRED DURING THE SENSE DATA TRANSFER. ',0 ; ENDIF; IF MSGSA; MSG53:;STATUS ACTION VALUE MESSAGE DB 'PERFORM RECOVERY IF NECESSARY BECAUSE OF CHANNEL ' DB 0DH,0AH; DB ' TRUNCATION (0AH). ',0 ; ENDIF; IF AHLPMSG; MSG54:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED FOR ALL COMMANDS, EXCEPT' DB 0DH,0AH; DB 'THE SENSE I/O COMMAND, WITH CHANNEL END AND DEVICE END' DB 0DH,0AH; DB 'STATUS. THIS ACTION INDICATES NORMAL COMMAND COMPLETION' DB 0DH,0AH; DB 'EXCEPT THAT CHANNEL TRUNCATION OF DATA TRANSFER WAS' DB 0DH,0AH; DB 'DETECTED. THE CHANNEL TRUNCATION BIT(31) IS SET IN THE' DB 0DH,0AH; DB 'STATUS WORD. ',0 ; ENDIF; IF MSGSA; MSG55:;STATUS ACTION VALUE MESSAGE DB 'ACQUIRE SENSE DATA (0BH). ',0 ; ENDIF; IF AHLPMSG; MSG56:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED FOR ALL COMMANDS, EXCEPT' DB 0DH,0AH; DB 'THE SENSE I/O COMMAND, WITH UNIT CHECK STATUS ALONE AND' DB 0DH,0AH; DB 'MAY APPEAR WITH OR WITHOUT THE CHANNEL TRUNCATION BIT(31)' DB 0DH,0AH; DB 'SET IN THE STATUS WORD. THIS STATUS ACTION IS PRESENTED' DB 0DH,0AH; DB 'FOR ALL UNIT CHECK CONDITIONS NOT COVERED BY STATUS ACTION' DB 0DH,0AH; DB 'CODES 0CH, 0DH, AND 0EH. ',0 ; ENDIF; IF MSGSA; MSG57:;STATUS ACTION VALUE MESSAGE DB 'ACQUIRE SENSE DATA (0DH). ',0 ; ENDIF; IF AHLPMSG; MSG58:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED FOR ANY COMMAND WITH UNIT' DB 0DH,0AH; DB 'CHECK STATUS ALONE ONLY WHEN THE ASSOCIATED SENSE INFORMATION' DB 0DH,0AH; DB 'DESCRIBES A BUS OUT PARITY ERROR THAT HAS OCCURRED ON A' DB 0DH,0AH; DB 'FUNCTION WORD TRANSFER. A BUS OUT CHECK ON A FUNCTION' DB 0DH,0AH; DB 'WORD THAT CONTAINS A COMMAND THAT IS DECODED AS A SENSE' DB 0DH,0AH; DB 'I/O (04H) COMMAND IS NOT REPORTED. ',0 ; ENDIF; IF MSGSA; MSG59:;STATUS ACTION VALUE MESSAGE DB 'REPEAT THE OPERATION WITH A READ DATA COMMAND (0EH). ',0 ; ENDIF; IF AHLPMSG; MSG60:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED ONLY FOR THE READ DATA' DB 0DH,0AH; DB 'SPECIAL COMMAND WITH UNIT CHECK STATUS ALONE AND MAY' DB 0DH,0AH; DB 'APPEAR WITH OR WITHOUT THE CHANNEL TRUNCATION BIT(31)' DB 0DH,0AH; DB 'SET IN THE STATUS WORD. THIS STATUS ACTION IS PRESENTED' DB 0DH,0AH; DB 'ONLY WHEN THE ASSOCIATED SENSE INFORMATION DESCRIBES THE' DB 0DH,0AH; DB 'OCCURRENCE OF A CORRECTABLE DATA CHECK IN A DATA FIELD.',0 ; ENDIF; IF MSGSA; MSG61:;STATUS ACTION VALUE MESSAGE DB 'PERFORM RECOVERY IF NECESSARY BECAUSE OF FORCED EF' DB 0DH,0AH; DB ' COMMAND TERMINATION (0FH). ',0 ; ENDIF; IF AHLPMSG; MSG62:;STATUS VALUE HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS STATUS ACTION IS PRESENTED WITH ANY STATUS AND INDICATES' DB 0DH,0AH; DB 'TERMINATION OF A COMMAND BY A FORCED EF. ',0 ; ENDIF; IF MSGSA; MSG63:;RECOVERY ACTION MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - RECOVERY ACTION = ',0 ; ENDIF; IF AHLPMSG; MSG64:;RECOVERY ACTION HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' ',0 ; ENDIF; IF MSGSA; MSG65:;RECOVERY ACTION VALUE MESSAGE DB 'WRITE INHIBITED (01H).',0 ; MSG66:;RECOVERY ACTION VALUE MESSAGE DB 'SEEK IN PROGRESS FOR ANOTHER CHANNEL, OR CORRECTABLE DATA' DB 0DH,0AH; DB ' CHECK,OR DATA CHECK (NOT PERMANENT) (02H).',0 ; MSG67:;RECOVERY ACTION VALUE MESSAGE DB 'IMPROPER ALTERNATE TRACK POINTER (03H).',0 ; MSG68:;RECOVERY ACTION VALUE MESSAGE DB 'COMMAND REJECT(EXCEPT SPECIAL CASES),OR END OF PACK(04H).',0 ; MSG69:;RECOVERY ACTION VALUE MESSAGE DB 'READ LABEL COMMAND REQUIRED (05H).',0 ; MSG70:;RECOVERY ACTION VALUE MESSAGE DB 'INTERVENTION REQUIRED (06H).',0 ; MSG71:;RECOVERY ACTION VALUE MESSAGE DB 'BUS OUT PARITY ERROR (07H).',0 ; MSG72:;RECOVERY ACTION VALUE MESSAGE DB 'EQUIPMENT CHECK (NOT PERMANENT) (08H).',0 ; MSG73:;RECOVERY ACTION VALUE MESSAGE DB 'PERMANENT DATA CHECK (09H).',0 ; MSG74:;RECOVERY ACTION VALUE MESSAGE DB 'INVALID TRACK FORMAT OR NO RECORD FOUND (0AH).',0 ; MSG75:;RECOVERY ACTION VALUE MESSAGE DB 'ENVIRONMENTAL DATA PRESENT (0BH).',0 ; MSG76:;RECOVERY ACTION VALUE MESSAGE DB 'ONLY VALID COPY LATCH SET FOR FIRST RECORD PARTIALLY' DB 0DH,0AH; DB ' ' DB 'UPDATED ON WRITE DATA OR WRITE DATA PAD ZEROS (0CH).',0 ; MSG77:;RECOVERY ACTION VALUE MESSAGE DB 'ONLY VALID COPY LATCH SET FOR LAST RECORD PARTIALLY' DB 0D,0AH; DB ' ' DB 'UPDATED ON WRITE DATA OR WRITE DATA PAD ZEROS (0DH).',0 ; MSG78:;RECOVERY ACTION VALUE MESSAGE DB 'PERMANENT EQUIPMENT CHECK (0EH).',0 ; MSG79:;DEVICE STATUS MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - DEVICE STATUS = ' DB 0DH,0AH,0;CR LF ; ENDIF; IF AHLPMSG; MSG80:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' ',0 ; ENDIF; IF MSGSA; MSG81:;DEVICE STATUS MESSAGE DB ' ATTENTION (BIT 15).',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG82:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'ATTENTION STATUS INDICATES A DISK PACK CHANGE CONDITION AT' DB 0DH,0AH; DB 'THE SELECTED DISK UNIT. ATTENTION STATUS IS USUALLY' DB 0DH,0AH; DB 'PRESENTED ALONE.' DB 0DH,0AH; DB 'ATTENTION STATUS MAYBE PRESENTED IN AN UNSOLICITED STATUS' DB 0DH,0AH; DB 'WORD OR WITH BUSY STATUS TO INDICATE THAT THE CU HAS' DB 0DH,0AH; DB 'TERMINATED THE CURRENT COMMAND PRIOR TO EXECUTION BECAUSE' DB 0DH,0AH; DB 'OF A DISK PACK CHANGE CONDITION AT THE SAME DISK UNIT AS' DB 0DH,0AH; DB 'SPECIFIED IN THIS COMMAND.',0 ; ENDIF; IF MSGSA; MSG83:;DEVICE STATUS MESSAGE DB ' STATUS MODIFIER (BIT 14).',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG84:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'STATUS MODIFIER STATUS INDICATES THAT THE CU HAS TERMINATED' DB 0DH,0AH; DB 'THE CURRENT COMMAND PRIOR TO EXECUTION BECAUSE AN EF - EI' DB 0DH,0AH; DB 'COLLISION HAS OCCURRED ON THIS COMMAND.' DB 0DH,0AH; DB 'STATUS MODIFIER STATUS IS PRESENTED ONLY WITH BUSY AND' DB 0DH,0AH; DB 'CONTROL UNIT END STATUS.',0 ; ENDIF; IF MSGSA; MSG85:;DEVICE STATUS MESSAGE DB ' CONTROL UNIT END (BIT 13).',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG86:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'CONTROL UNIT END STATUS INDICATES THAT THE CU HAS' DB 0DH,0AH; DB 'TERMINATED THE CURRENT COMMAND PRIOR TO EXECUTION BECAUSE' DB 0DH,0AH; DB 'AN EF - EI COLLISION HAS OCCURRED ON THIS COMMAND.' DB 0DH,0AH; DB 'CONTROL UNIT END STATUS IS PRESENTED ONLY WITH BUSY AND' DB 0DH,0AH; DB 'STATUS MODIFIER STATUS.',0 ; ENDIF; IF MSGSA; MSG87:;DEVICE STATUS MESSAGE DB ' BUSY (BIT 12), ',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG88:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'BUSY STATUS IS PRESENTED WITH ATTENTION STATUS TO INDICATE' DB 0DH,0AH; DB 'THAT THE CU HAS TERMINATED THE CURRENT COMMAND PRIOR TO' DB 0DH,0AH; DB 'EXECUTION BECAUSE OF A DISK PACK CHANGE CONDITION AT THE' DB 0DH,0AH; DB 'DISK UNIT SPECIFIED IN THIS COMMAND.' DB 0DH,0AH; DB 'BUSY STATUS MAY ALSO BE PRESENTED WITH STATUS MODIFIER AND' DB 0DH,0AH; DB 'CONTROL UNIT END STATUS TO INDICATE THAT THE CU HAS TERM-' DB 0DH,0AH; DB 'INATED THE CURRENT COMMAND PRIOR TO EXECUTION BECAUSE AN' DB 0DH,0AH; DB 'EF - EI COLLISION HAS OCCURRED ON THIS COMMAND.',0 ; ENDIF; IF MSGSA; MSG89:;DEVICE STATUS MESSAGE DB ' CHANNEL END (BIT 11), ',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG90:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'CHANNEL END STATUS IS PRESENTED ALONE TO INDICATE THAT' DB 0DH,0AH; DB 'THE OPERATION INITIATED BY THE CURRENT COMMAND IS BEING' DB 0DH,0AH; DB 'PROCESSED AT THE DISK UNIT, INDEPENDENT OF THE CU, AND' DB 0DH,0AH; DB 'THAT A SECONDARY STATUS WORD WILL BE PRESENTED LATER FOR' DB 0DH,0AH; DB 'THE SAME DISK UNIT.' DB 0DH,0AH; DB 'CHANNEL END STATUS MAY ALSO BE PRESENTED WITH DEVICE END' DB 0DH,0AH;  DB 'STATUS TO INDICATE NORMAL COMPLETION OF A COMMAND FOR WHICH' DB 0DH,0AH; DB 'CHANNEL END HAS NOT BEEN PREVIOUSLY PRESENTED ALONE.',0 ; ENDIF; IF MSGSA; MSG91;DEVICE STATUS MESSAGE DB ' DEVICE END (BIT 10), ',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG92;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'DEVICE END STATUS IS PRESENTED ALONE IN A SECONDARY STATUS' DB 0DH,0AH; DB 'WORD TO INDICATE NORMAL COMPLETION OF AN OPERATION FOR WHICH' DB 0DH,0AH; DB 'CHANNEL END STATUS HAS BEEN PREVIOUSLY PRESENTED ALONE.' DB 0DH,0AH; DB 'DEVICE END STATUS MAY ALSO BE PRESENTED WITH CHANNEL END' DB 0DH,0AH; DB 'STATUS TO INDICATE NORMAL COMPLETION OF A COMMAND FOR WHICH' DB 0DH,0AH; DB 'CHANNEL END STATUS HAD NOT BEEN PREVIOUSLY PRESENTED ALONE.',0 ; ENDIF; IF MSGSA; ; MSG93:;DEVICE STATUS MESSAGE DB '  UNIT CHECK (BIT 9), ',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG94:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'UNIT CHECK STATUS IS USUALLY PRESENTED ALONE AND INDICATES' DB 0DH,0AH; DB 'THAT AN ERROR OR UNUSUAL CONDITION HAS OCCURRED ON EITHER' DB 0DH,0AH; DB 'THE CURRENT COMMAND OR THE PRIOR COMMAND. THE SENSE I/O' DB 0DH,0AH; DB 'COMMAND(04H) MUST BE ISSUED WITHIN TWO SECONDS OF UNIT' DB 0DH,0AH; DB 'CHECK FOR THE SENSE DATA TO BE VALID. A NONZERO RECOVERY' DB 0DH,0AH; DB 'ACTION FIELD IS ALWAYS SET WITH UNIT CHECK STATUS.',0 ; ENDIF; IF MSGSA; MSG95:;DEVICE STATUS MESSAGE DB ' UNIT EXCEPTION (BIT 8), ',0DH,0AH,0 ; ENDIF; IF AHLPMSG; MSG96:;DEVICE STATUS HELP MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'THIS BIT(08) IS NOT USED AND IS ALWAYS ZERO.',0 ; ENDIF; IF MSGSA; MSG97:;STATUS ACTION MESSAGE DB 'NO STATUS ACTION (00H). ',0 ; ENDIF; IF AHLPMSG; MSG98:;STATUS VALUE HELP MESSAGE DB 00H; ; ENDIF; IF MSGSA; MSG99:;RECOVERY ACTION VALUE DB 'NO RECOVERY ACTION (00H). ',0 ; MSG100:;DEVICE STATUS MESSAGE DB ' NO DEVICE STATUS (00H). ',0 ; ENDIF; IF AHLPMSG; MSG101:;DEVICE STATUS HELP MESSAGE DB 00H; ; ENDIF; IF MSGSA; MSG102:;DEVICE ADDRESS MESSAGE DB 0DH,0AH;CARRIAGE RETURN LINE FEED DB ' - DEVICE ADDRESS = ',0 ; ENDIF; IF AHLPMSG; MSG103:;DEVICE ADDRESS HELP MESSAGE DB 00H; ; ENDIF; IF MSGSA; MSG104:;STATUS ACTION MESSAGE DB 'DOES NOT EXIST (0CH). ',0 ; ENDIF; IF AHLPMSG; MSG105:;STAUS VALUE HELP MESSAGE DB 00H; ; ENDIF; IF MSGSA; MSG106:;RECOVERY ACTION VALUE MESSAGE DB 'DOES NOT EXIST (0FH). ',0 ; ENDIF; MSG107:;STATUS WORD COMPARE ERROR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED  DB 'THE DATA COMPARE ERROR IS THE STATUS WORD. ',0 ; MSG108:;STATUS WORD MESSAGE DB ' - STATUS WORD = ',0 ; MSG109:;STW DISPLAY ANALYSIS MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - stw analysis',0 DB 0DH,0AH;CARRIAGE RETURN LINE FEED ; MSG110:;CARRIAGE RETURN AND LINE FEED MSG DB 0DH,0AH,0;MISC. CR LF ; MSG200:;TIME-OUT MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'ERROR - CHANNEL TIME-OUT (PROTOCOL) ',0 ; MSG201;NEED TAG MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - CONTROL UNIT DOES NOT RESPOND ',0 ; MSG202:;CHANNEL TAG SEQ. MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** '; DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'ERROR - CHANNEL TAG OUT OF SEQUENCE (PROTCOL) ',0; ; MSG203:;ODR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - RECEIVED AN OUTPUT DATA REQUEST (ODR) ',0 ; MSG205:;IDR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - RECEIVED AN INPUT DATA REQUEST (IDR) ',0 ; MSG207:;EI MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - RECEIVED AN EXTERNAL INTERRUPT (EI) ',0 ; MSG208:;PARITY MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB 'ERROR - WORD CHANNEL PARITY ERROR ',0 ; MSG209:;PARITY MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - PARITY ERROR WHILE INPUTING FROM THE C.U. ',0 ; MSG210:;ERROR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED  DB ' - WAS NOT EXPECTING ANY CHANNEL TAGS ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** ',0 ; MSG211:;ERROR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - WAS EXPECTING AN OUTPUT DATA REQUEST (ODR) ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** ',0 ; MSG213:;ERROR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - WAS EXPECTING AN INPUT DATA REQUEST (IDR) ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** ',0 ; MSG214:;ERROR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - WAS EXPECTING AN EXTERNAL INTERRUPT (EI) ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** ',0 ; MSG215:;ERROR MESSAGE DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB ' - CHANNEL TAGS ARE ACTIVE (C.U. DID NOT RESET) ' DB 0DH;CARRIAGE RETURN DB 0AH;LINE FEED DB '**************************************************** ',0 ; CLOSE:;CLOSE FILE ;LXI D,FCBX - LOAD ADDRESS TO FILE CONTROL ;BLOCK IN REG. PAIR D,E BEFORE ENTRY PUSH D;SAVE FCBX FOR FCB CLR MVI C,CLOSEF;CPM CLOSE FUNCTION CALL FDOS;TELL CPM YOU COMMAND IT CPI 0FFH;DID IT OBEY? FF MEANS NO! PUSH PSW;SAVE ZERO FLAG LXI H,MSG5;UNSUCCESSFUL CLOSE MESSAGE CZ PMSG;DO IT! POP PSW;RESTORE ZERO FLAG JZ BOOT;REBOOT IF DISOBEYED POP D;RESTORE FCBX CALL CLRFCB;CLEAR FCB LOWER BYTES LXI H,MSG7;SUCCESSFUL CLOSE MESSAGE CALL PMSG;DO IT! RET; ; OPEN:;OPEN FILE ;LXI D,FCBX - LOAD ADDRESS OF FILE CONTROL BLOCK ;IN REG. PAIR D,E BEFORE ENTRY CALL CLRFCB;CLEAR FCB LOWER BYTES MVI C,OPENF;OPEN FILE COMMAND CALL FDOS;GIVE PROBLEM TO CPM CPI 0FFH;FF IF FILE IS NOT FOUND PUSH PSW;SAVE ZERO FLAG FOR LATER LXI H,MSG8;UNABLE TO OPEN MESSAGE CZ PMSG;DO IT! POP PSW;RESTORE ZERO FLAG JZ BOOT;REBOOT IF FILE IS NOT FOUND LXI H,MSG4;SUCCESSFUL OPEN MESSAGE CALL PMSG;DO IT! RET; ; MAKE:;CREATE FILE ;LXI D,FCBX - LOAD ADDRESS OF FILE CONTROL BLOCK ;IN REG. PAIR D,E BEFORE ENTRY CALL CLRFCB;CLEAR FCB LOWER BYTES MVI C,MAKEF;MAKE FILE COMMAND CALL FDOS;GIVE PROBLEM TO CPM CPI 0FFH;FF IF DIRECTORY IS FULL PUSH PSW;SAVE ZERO FLAG FOR LATER LXI H,MSG3;DIRECTORY IS FULL MESSAGE CZ PMSG;DO IT! POP PSW;RESTORE ZERO FLAG JZ BOOT;REBOOT IF NO DIRECTORY SPACE LXI H,MSG2;FILE CREATED MESSAGE CALL PMSG;DO IT! RET; ; WRITE:;WRITE TO FILE ;LXI D,FCBX - LOAD ADDRESS OF FILE CONTROL BLOCK ;IN REG. PAIR D,E BEFORE ENTRY PUSH PSW; PUSH B; PUSH D; PUSH H; MVI C,WRITEF;CPM SEQ. WRITE FUNCTION 21 CALL FDOS;GIVE PROBLEM TO CPM CPI 00H;00 IF DISK IS NOT FULL PUSH PSW;SAVE ZERO FLAG LXI H,MSG6;DISK FULL MESSAGE CNZ PMSG;DO IT! POP PSW;RESTORE ZERO FLAG JNZ BOOT;REBOOT IF DISK IS FULL POP H; POP D; POP B; POP PSW; RET; ; READ:;READ FROM FILE ;LXI D,FCBX - LOAD ADDRESS OF FILE CONTROL BLOCK ;IN REG. PAIR D,E BEFORE ENTRY PUSH PSW; PUSH B; PUSH D; PUSH H; MVI C,READF;CPM SEQ. READ FUNCTION 20 CALL FDOS;GIVE PROBLEM TO CPM CPI 00H;00 = SUCCESSFUL READ PUSH PSW;SAVE ZERO FLAG FOR LATER LXI H,MSG9;OUT OF DATA MESSAGE (EOF) CNZ PMSG;DO IT! POP PSW;RESTORE ZERO FLAG JNZ RFCBR;CLEAR FCB AND CLOSE FILE (OUT OF DATA - EOF) POP H; POP D; POP B; POP PSW; RET; ; RFCBR:;CLOSE FILE AND CLEAR FCB POP H;DEC STACK POP D;RESTORE FCB ADDRESS CALL CLOSE; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; FDELETE:;FILE DELETE ;LXI D,FCBX - LOAD ADDRESS TO FILE CONTROL ;BLOCK IN REG. PAIR D,E BEFORE ENTRY MVI C,DELETEF;CPM DELETE FUNCTION CALL FDOS;TELL CPM TO DELETE CPI 0FFH;DID IT OBEY? FF MEANS NO PUSH PSW;SAVE ZERO FLAG LXI H,MSG14;UNSUCCESSFUL DELETE MESSAGE CZ PMSG;DISPLAY IT POP PSW;RESTORE ZERO FLAG JZ BOOT;REBOOT IF DISOBEYED LXI H,MSG15;SUCCESSFUL DELETE MESSAGE CALL PMSG;DISPLAY IT RET; ; FILA:;INIT. FILE (TEXT) MVI C,SDMADD; CALL FDOS; LXI D,FCBA;  CALL OPEN; LXI D,FCBA; CALL READ; LXI H,ABUFF; SHLD ABPTR; LXI H,RECSIZ; SHLD XCNTR; RET; ; ASCIID:;DISPLAY ASCII TEXT AND LOOK FOR (RET) FOR STOP MOV E,A;A CHAR HERE <> FF MEANS OUTPUT CMD ALSO CPI 1AH;ASCII EOF JZ CF;DONE IF AT END OF FILE MVI C,DCONF;DIRECT CONSOLE I/O CALL FDOS;TELL CPM CONST: MVI C,DCONF;DIRECT CON. I/O MVI E,0FFH;FF = INPUT COMMAND CALL FDOS;GIVE TO CPM CPI ZERO;IS CHAR READY RZ;RETURN IF NO (ZERO) CPI 13H;IS IT CTRL-S (XOFF) JZ CWT;LOOP FOR NEXT CHAR (STOP SCROLL) CPI 0DH;CARRIAGE RETURN RNZ;START SCROLL IF NOT CR CF: LXI D,FCBA; CALL CLOSE; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE CWT:;CONSOL - WAIT FOR CHAR MVI C,CONINF; CALL FDOS; RET; ; ASCHEX: MVI A,00H; CMP B; MVI A,30H;ASCII 0  RZ; MVI A,01H; CMP B; MVI A,31H;ASCII 1 RZ; MVI A,02H; CMP B; MVI A,32H;ASCII 2 RZ; MVI A,03H; CMP B; MVI A,33H;ASCII 3 RZ; MVI A,04H; CMP B; MVI A,34H;ASCII 4 RZ; MVI A,05H; CMP B; MVI A,35H;ASCII 5 RZ; MVI A,06H; CMP B; MVI A,36H;ASCII 6 RZ; MVI A,07H; CMP B; MVI A,37H;ASCII 7 RZ; MVI A,08H; CMP B; MVI A,38H;ASCII 8 RZ; MVI A,09H; CMP B; MVI A,39H;ASCII 9 RZ; MVI A,0AH; CMP B; MVI A,41H;ASCII A RZ; MVI A,0BH; CMP B; MVI A,42H;ASCII B RZ; MVI A,0CH; CMP B; MVI A,43H;ASCII C RZ; MVI A,0DH; CMP B; MVI A,44H;ASCII D RZ; MVI A,0EH; CMP B; MVI A,45H;ASCII E RZ; MVI A,0FH; CMP B; MVI A,46H;ASCII F RZ; RET; ; NEWLIN: PUSH PSW; PUSH D; PUSH H; MVI C,CONOUTF;CPM CONSOLE OUT (FUNCTION 2) MVI E,0DH;ASCII CARRIAGE RETURN CALL FDOS; MVI C,CONOUTF; MVI E,0AH;ASCII LINE FEED CALL FDOS; LDA XADD + 1; CALL CONDMP; LDA XADD; CALL CONDMP; MVI C,CONOUTF; MVI E,20H;ASCII SPACE CALL FDOS; MVI C,CONOUTF; MVI E,20H; CALL FDOS; MVI C,CONOUTF; MVI E,20H; CALL FDOS; MVI B,DWDLIN; MVI C,00H; POP H; POP D; POP PSW; RET; ; CONDMP: PUSH PSW; PUSH B; PUSH D; PUSH H; MOV D,A; ANI 0F0H; RRC;  RRC; RRC; RRC; MOV B,A; CALL ASCHEX; MOV E,A; MVI C,CONOUTF; CALL FDOS; MOV A,D; ANI 0FH; MOV B,A; CALL ASCHEX; MOV E,A; MVI C,CONOUTF; CALL FDOS; POP H; POP D; POP B; POP PSW; RET; ; COMPWD: PUSH PSW; PUSH B; PUSH D; PUSH H; LDA XDATA + 4; STA EDATA + 4; LDA XDATA + 3; STA EDATA + 3; LDA XDATA + 2; STA EDATA + 2; LDA XDATA + 1; STA EDATA + 1; LDA XDATA + 0; STA EDATA + 0; LDA SDATA + 4; MOV B,A; LDA XDATA + 4; CMP B;COMPARE SDATA WITH XDATA/EDATA JNZ DCMPER; LDA SDATA + 3; MOV B,A; LDA XDATA + 3; CMP B; JNZ DCMPER; LDA SDATA + 2; MOV B,A; LDA XDATA + 2; CMP B; JNZ DCMPER; LDA SDATA + 1; MOV B,A; LDA XDATA + 1; CMP B; JNZ DCMPER; LDA SDATA + 0; MOV B,A; LDA XDATA + 0; CMP B; JNZ DCMPER; POP H; POP D; POP B; POP PSW; RET; ; DCMPER: MVI A,DATERR;DATA ERROR STA PSTATS;PROGRAM STATUS MVI A,FRMT1;FORMAT/TABLE STA PSTATS + 1; LHLD ERRCNT;GET CURRENT ERROR COUNT INX H;ADD ONE TO IT SHLD ERRCNT;UPDATE VARIABLE PARAMETER LHLD XADD; DCX H;SUBTRACT ONE SHLD XADD; CALL NEWLIN; LHLD XADD; INX H;ADD ONE SHLD XADD; LXI H,MSG12;DATA COMPARE ERROR MESSAGE CALL PMSG;DISPLAY IT! LXI H,MSG10;SHOULD BE MESSAGE CALL PMSG;DISPLAY IT! LDA SDATA + 4; CALL CONDMP; LDA SDATA + 3; CALL CONDMP;  LDA SDATA + 2; CALL CONDMP; LDA SDATA + 1; CALL CONDMP; LDA SDATA + 0; CALL CONDMP; LXI H,MSG11;WAS MESSAGE CALL PMSG;DISPLAY IT LDA EDATA + 4; CALL CONDMP; LDA EDATA + 3; CALL CONDMP; LDA EDATA + 2; CALL CONDMP; LDA EDATA + 1; CALL CONDMP; LDA EDATA + 0; CALL CONDMP; POP H; POP D; POP B; POP PSW; RET; ; UPDREC: LHLD XCNTR; XCHG; LHLD ABPTR; INX H;BUFFER POINTER DCX D;XCNTR SHLD ABPTR; XCHG; SHLD XCNTR; MVI A,00H; CMP H;XCNTR JNZ $ + 7; CMP L; JZ RESET; RET; ; RESET: LXI D,ABUFF; MVI C,SDMADD; CALL FDOS; LXI D,FCBA; CALL READ; LXI D,RECSIZ; LXI H,ABUFF; SHLD ABPTR;  XCHG; SHLD XCNTR; RET; ; NEXTWD: PUSH PSW; PUSH B; PUSH D; PUSH H; LHLD ABPTR; MOV A,M; STA XDATA; CALL UPDREC; LHLD ABPTR; MOV A,M; STA XDATA + 1; CALL UPDREC; LHLD ABPTR; MOV A,M; STA XDATA + 2; CALL UPDREC; LHLD ABPTR; MOV A,M; STA XDATA + 3; CALL UPDREC; LHLD ABPTR; MOV A,M; STA XDATA + 4; CALL UPDREC; LHLD XADD; INX H; SHLD XADD; POP H; POP D; POP B; POP PSW; RET; ; INITC: LXI D,ABUFF;LOAD DMA ADDRESS MVI C,SDMADD;SET DMA ADDRESS COMMAND CALL FDOS;GIVE PROBLEM TO CPM LXI D,FCBA;LOAD ADDRESS TO FILE CONTROL BLOCK A CALL OPEN; LXI D,FCBA;LOAD ADDRESS TO FILE CONTROL BLOCK A CALL READ;  LXI H,ABUFF; MOV A,M;SADD STA XADD; INX H; MOV A,M;SADD + 1 STA XADD + 1; LXI D,FCBA;LOAD ADDRESS TO FCB A CALL READ; LXI H,ABUFF; SHLD ABPTR; LXI H,RECSIZ; SHLD XCNTR; ;MVI A,00H;DATA FOR START ADDRESS OF FILE (ASSUME 0) ;STA XADD + 1;OVERRIDE INITA: (MSB) ;STA XADD;OVERRIDE INITA: (LSB) RET; ; SEARCH: JMP $ + 6; LOOPF: CALL NEXTWD; LHLD SADD; XCHG; LHLD XADD; MOV A,H; CMP D;SADD + 1 (MSB) JNZ LOOPF; MOV A,L; CMP E;SADD (LSB) JNZ LOOPF; RET; ; ;THE NEXT FIVE SUBROUTINES ARE REPEATS OF THE ABOVE ;BUT FOR BUFFER B (BOTH USED AS OUTPUTS) UPRECB: LHLD XCNTRB; XCHG; LHLD BBPTR; INX H; DCX D; SHLD BBPTR; XCHG; SHLD XCNTRB; MVI A,00H; CMP H; JNZ $ + 7; CMP L; JZ RSTB; RET; ; RSTB: LXI D,BBUFF; MVI C,SDMADD; CALL FDOS; LXI D,FCBB; CALL READ; LXI D,RECSIZ; LXI H,BBUFF; SHLD BBPTR; XCHG; SHLD XCNTRB; RET; ; NXTWDB: PUSH PSW; PUSH B; PUSH D; PUSH H; LHLD BBPTR; MOV A,M; STA XDATA + 0; CALL UPRECB; LHLD BBPTR; MOV A,M; STA XDATA + 1; CALL UPRECB; LHLD BBPTR; MOV A,M; STA XDATA + 2; CALL UPRECB; LHLD BBPTR; MOV A,M; STA XDATA + 3; CALL UPRECB; LHLD BBPTR; MOV A,M; STA XDATA + 4; CALL UPRECB; LHLD XADD; INX H; SHLD XADD; POP H; POP D; POP B; POP PSW; RET; ; INITCB: LXI D,BBUFF;  MVI C,SDMADD; CALL FDOS; LXI D,FCBB; CALL OPEN; LXI D,FCBB; CALL READ; LXI H,BBUFF; MOV A,M; STA XADD; INX H; MOV A,M; STA XADD + 1; LXI D,FCBB; CALL READ; LXI H,BBUFF; SHLD BBPTR; LXI H,RECSIZ; SHLD XCNTRB; RET; ; SRCHB: JMP $ + 6; LOOPFB: CALL NXTWDB; LHLD SADD; XCHG; LHLD XADD; MOV A,H; CMP D; JNZ LOOPFB; MOV A,L; CMP E; JNZ LOOPFB; RET; ; GPLOOP:; MOV A,M; STAX D; INX H; INX D; DCR C; MOV A,C; CPI ZERO; RZ; JMP GPLOOP; ; PPLOOP:; LDAX D; MOV M,A; INX H; INX D; DCR C; MOV A,C; CPI ZERO; RZ; JMP PPLOOP; ; GETPAC: LXI D,FCBC;LOAD ADDRESS TO FILE CONTROL BLOCK C CALL READ;GET RECORD FROM DISK LXI H,PBUFF;PACKET BUFFER LXI D,EFW; MVI C,LENGA; CALL GPLOOP; LXI D,SADD; MVI C,LENGB; CALL GPLOOP; LXI D,F1A; MVI C,LENGC; CALL GPLOOP; LXI D,F1B; MVI C,LENGC; CALL GPLOOP; RET; ; ;SAME AS ABOVE ROUTINE BUT PUTS INSTEAD OF GETS PUTPAC: LXI H,PBUFF; LXI D,EFW; MVI C,LENGA; CALL PPLOOP; LXI D,SADD; MVI C,LENGB; CALL PPLOOP; LXI D,F1A; MVI C,LENGC; CALL PPLOOP; LXI D,F1B; MVI C,LENGC; CALL PPLOOP; LXI D,FCBC; CALL WRITE; RET; ; IF TEST1;ASSEMBLE IF THIS IS TEST MODE SEFWXF: CALL IEFCNT; RET; ; SAFWXF: CALL IAFCNT; RET; ; SODWXF: CALL IODCNT; RET; ; SIDWXF: CALL IIDCNT; RET; ; SEIWXF: CALL ISTCNT; RET; ; SCLRXF: RET; ; SPARXF: RET; ; ENDIF; ; RBPTR:;RESET BUFFER FOR NEXT ROUTINE LXI H,ABUFSIZ;A BUFFER SIZE XCHG;SWAP DE WITH HL LHLD ABPTR;A BUFFER PTR. RET; ; ;ODW - REPEATING BUFFER DRIVER (SOFT) SODRB: MVI A,ZERO; STA TWCNT + 0;RESET TIME-OUT COUNTER (LSB) STA TWCNT + 1;(MSB) LHLD XFCNT;GET DATA TRANSFERE COUNT MOV C,L; MOV B,H;MOVE HL TO BC REG. CALL RBPTR;RESET BUFFER POINTERS LODARB:; ;IN PPI7PB;CHECK FOR INPUT TAGS ;CPI ODRTAG;PROPER TAG ;JZ CYBUFF;CYCLE BUFFER IF OK ;MVI A,02D; ;STA STATET;SAVE CURRENT STATE IN CASE OF ERROR ;CALL WAITT;WAIT LOOP AND PROPER TAG CHECK ;JMP LODARB;LOOK AGAIN FOR TAG CYBUFF:; MOV A,M;MOVE BUFFER TO A REG. ;OUT PPI1PA;OUT TO DATA PORT (BITS 0 - 7) STA XDATA;FOR COMPARE PURPOSE INX H;INC. BUFFER POINTER DCX D;DEC. REMAINING BUFFER SIZE MOV A,D;MOV MSB TO A REG. ORA A;SET FLAGS JNZ $ + 8;IF NOT ZERO SKIP NEXT CHECK MOV A,E;MOV LSB TO A REG. ORA A;SET FLAGS CZ RBPTR;IF SENT ALL OF BUFFER RESET BUFFER (REPEAT) MOV A,M;COMMENTS - SAME AS ABOVE FOR BYTE XFERS. ;OUT PPI1PB;(BITS 8 - 15) STA XDATA; INX H; DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; MOV A,M; ;OUT PPI1PC;(BITS 16 - 23) STA XDATA; INX H; DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; MOV A,M; ;OUT PPI2PA;(BITS 24 - 31) STA XDATA; INX H; DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; MOV A,M; ORI OATAG;MERGE TAG ;OUT PPI2PB;(BITS 32 - 35 + TAG) STA XDATA; MVI A,ZERO; ;OUT PPI2PB;RESET TAG DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; PUSH H;SAVE BUFFER POINTER CALL IODCNT;COUNT OUT-PUT DATA WORDS POP H;GET BUFFER POINTER DCX B;DEC. XFCNT LDA WRDRPT;WORD REPEAT MODIFIER CPI CONDT;IS IT SET JZ SODRW;THEN REPEAT WORD ONLY (SAVE TIME) MVI A,ZERO; CMP B;XFCNT (MSB) JNZ LODARB;REPEAT DRIVER THROUGH XFCNT CMP C;XFCNT (LSB) JNZ LODARB;REPEAT TILL DONE JMP OFIN;ALL DONE ; ;ODW - REPEATING BUFFER WORD DRIVER (SOFT) SODRW:; MVI A,ZERO; CMP B;XFCNT (MSB) JNZ LODARW;REPEAT WORD THROUGH XFCNT CMP C;XFCNT (LSB) JNZ LODARW;REPEAT TILL DONE JMP OFIN;ALL DONE LODARW: ;IN PPI7PB;CHECK FOR INPUT TAG CPI ODRTAG;PROPER TAG ;JZ CYWRD;CYCLE WORD IF OK MVI A,02D; STA STATET;SAVE CURRENT STATE IN CASE OF ERROR ;CALL WAITT;WAIT LOOP AND PROPER TAG CHECK ;JMP LODARW;LOOK AGAIN FOR TAG CYWRD: MOV A,M;GET WORDS LAST BYTE (MSB) ORI OATAG;MERGE TAG ;OUT PPI2PB;(BITS 32 - 35 + TAG) MVI A,ZERO; ;OUT PPI2PB;RESET TAG PUSH H;SAVE BUFFER WORD POINTER CALL IODCNT;COUNT OUT-PUT DATA WORDS POP H;RESTORE BUFFER POINTER DCX B;DEC. XFCNT JMP SODRW;GO CHECK XFCNT FOR REPEAT ; ;NEXT DRIVERS COMMENTS ARE SAME AS ABOVE BUT FOR INPUT DATA. ;SENDS OUT REPEATING BUFFER WITH INPUT TAGS FOR FAST ;DATA INPUT AND COMPARE USING HARD-WARE COMPARE ;IDW - REPEATING BUFFER DRIVER (SOFT) SIDRB: MVI A,ZERO; STA TWCNT + 0; STA TWCNT + 1; LHLD XFCNT; MOV C,L; MOV B,H; CALL RBPTR; LIDARB:; ;IN PPI7PB; ;CPI IDRTAG; ;JZ CYBUFI;CYCLE OUT BUFFER FOR INPUTS COMPARE ;MVI A,03D; ;STA STATET; ;CALL WAITT; ;JMP LIDARB; CYBUFI:; MOV A,M; ;OUT PPI1PA; STA SDATA; INX H; DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; MOV A,M; ;OUT PPI1PB; STA SDATA; INX H; DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; MOV A,M; ;OUT PPI1PC; STA SDATA; INX H; DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; MOV A,M; ;OUT PPI2PA; STA SDATA; INX H; DCX D; MOV A,D; ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; MOV A,M; ORI IATAG; ;OUT PPI2PB; ;CHECK FOR COMPARE ERROR (HARD) STA SDATA; MVI A,ZERO; ;OUT PPI2PB; DCX D; MOV A,D;  ORA A; JNZ $ + 8; MOV A,E; ORA A; CZ RBPTR; PUSH H; CALL IIDCNT; POP H; DCX B; LDA WRDRPT; CPI CONDT; JZ SIDRW; MVI A,ZERO; CMP B; JNZ LIDARB; CMP C; JNZ LIDARB; JMP IFIN; ; ;IDW - REPEATING BUFFER WORD DRIVER (SOFT) SIDRW:; MVI A,ZERO; CMP B; JNZ LIDARW; CMP C; JNZ LIDARW; JMP IFIN; LIDARW:; ;IN PPI7PB; CPI IDRTAG; ;JZ CYWRDI; MVI A,03D; STA STATET; ;CALL WAITT; ;JMP LIDARW; CYWRDI:; MOV A,M; ORI IATAG; ;OUT PPI2PB; ;CHECK FOR COMPARE ERROR (HARD) MVI A,ZERO; ;OUT PPI2PB; PUSH H; CALL IIDCNT; POP H; DCX B; JMP SIDRW; ; IF NOT TEST1;ASSEMBLE IF THIS IS NOT TEST MODE ;EFW - WORD/TAG DRIVER (SOFT) SEFWXF: MVI A,ZERO; STA TWCNT + 0;RESET TIME-OUT COUNTER (LSB)  STA TWCNT + 1;(MSB) LEFA: IN PPI7PB;CHECK FOR INPUT TAGS ORI ZERO;SHOULD BE NONE JZ EFSEND;SEND EF IF CHANNEL IS CLEAR MVI A,ZERO; STA STATET;SAVE CURRENT STATE IN CASE OF ERROR CALL WAITT;WAIT LOOP AND TAG SEQUENCE CHECK JMP LEFA;CHECK AGAIN FOR TAG EFSEND: LDA EFW + 0;BITS 0-7 OUT PPI1PA;DATA PORT LDA EFW + 1;BITS 8-15 OUT PPI1PB;DATA PORT LDA EFW + 2;BITS 16-23 OUT PPI1PC;DATA PORT LDA EFW + 3;BITS 24-31 OUT PPI2PA;DATA PORT LDA EFW + 4;BITS 32-39 ORI EFTAG;MERGE TAG OUT PPI2PB;SEND BITS 32-35 + TAG MVI A,ZERO; OUT PPI2PB;RESET TAG CALL IEFCNT;COUNT EF WORDS RET; ; ;AFW - WORD/TAG DRIVER (SOFT) SAFWXF: MVI A,ZERO; STA TWCNT + 0;RESET TIME-OUT COUNTER (LSB) STA TWCNT + 1;(MSB) LAFA: IN PPI7PB;DATA PORT CPI ODRTAG;CHECK FOR PROPER TAG JZ AFSEND;SEND IF OK MVI A,01D; STA STATET;SAVE STATE VALUE IN CASE OF ERROR CALL WAITT;WAIT LOOP AND PROPER TAG CHECK JMP LAFA;LOOK AGAIN FOR TAG AFSEND: LDA AFW + 0;BITS 0-7 OUT PPI1PA;DATA PORT LDA AFW + 1;BITS 8-15 OUT PPI1PB;DATA PORT LDA AFW + 2;BITS 16-23 OUT PPI1PC;DATA PORT LDA AFW + 3;BITS 24-31 OUT PPI2PA;DATA PORT LDA AFW + 4;BITS 32-39 ORI EFTAG;MERGE TAG OUT PPI2PB;SEND BITS 32-35 + TAG MVI A,ZERO; OUT PPI2PB;RESET TAG CALL IAFCNT;COUNT AF WORDS RET; ; ;ODW - WORD/TAG DRIVER (SOFT) SODWXF: MVI A,ZERO; STA TWCNT + 0;RESET TIME-OUT COUNTER (LSB) STA TWCNT + 1;(MSB) LODA: IN PPI7PB;CHECK FOR INPUT TAGS CPI ODRTAG;PROPER TAG JZ ODSEND;SEND IF OK MVI A,02D; STA STATET;SAVE CURRENT STATE IN CASE OF ERROR CALL WAITT;WAIT LOOP AND PROPER TAG CHECK JMP LODA;LOOK AGAIN FOR TAG ODSEND: LDA XDATA + 0;BITS 0 - 7 OUT PPI1PA;DATA PORT LDA XDATA + 1;BITS 8-15 OUT PPI1PB;DATA PORT LDA XDATA + 2;BITS 16-23 OUT PPI1PC;DATA PORT LDA XDATA + 3;BITS 24-31 OUT PPI2PA;DATA PORT LDA XDATA + 4;BITS 32-39 ORI OATAG;MERGE TAG OUT PPI2PB;SEND BITS 32-35 + TAG ;CHECK FOR COMPARE ERROR (HARD) MVI A,ZERO; OUT PPI2PB;RESET TAG CALL IODCNT;COUNT OUTPUT DATA WORDS RET; ; ;IDW - WORD/TAG DRIVER (SOFT) SIDWXF: MVI A,ZERO; STA TWCNT + 0;RESET TIME-OUT COUNTER (LSB) STA TWCNT + 1;(MSB) LIDA: IN PPI7PB;CHECK FOR INPUT TAGS CPI IDRTAG;CHECK FOR PROPER TAG JZ IDGET;GET IF OK MVI A,03D; STA STATET;SAVE STATE VALUE IN CASE OF ERROR CALL WAITT;WAIT LOOP AND PROPER TAG CHECK JMP LIDA;LOOK AGAIN FOR TAG IDGET: IN PPI6PA;DATA PORT STA XDATA + 0;BITS 0-7 IN PPI6PB;DATA PORT STA XDATA + 1;BITS 8-15 IN PPI6PC;DATA PORT STA XDATA + 2;BITS 16-23 IN PPI7PA;DATA PORT STA XDATA + 3;BITS 24-31 IN PPI7PB;DATA PORT STA XDATA + 4;BITS 32-35 + TAG MVI A,IATAG;ACK. TAG OUT PPI2PB;DATA PORT MVI A,ZERO; OUT PPI2PB;RESET TAG CALL IIDCNT;COUNT INPUT DATA WORDS RET; ; ;EIW - WORD/TAG DRIVER (SOFT) SEIWXF: MVI A,ZERO; STA TWCNT + 0;RESET TIME-OUT COUNTER (LSB) STA TWCNT + 1;(MSB) LISA: IN PPI7PB;CHECK FOR INPUT TAGS CPI EITAG;CHECK FOR PROPER TAG JZ ISGET;GET IF OK MVI A,04D; STA STATET;SAVE STATE VALUE IN CASE OF ERROR CALL WAITT;WAIT LOOP AND PROPER TAG CHECK JMP LISA;LOOK AGAIN FOR TAG ISGET: IN PPI6PA;DATA PORT STA XSTW + 0;BITS 0-7 IN PPI6PB;DATA PORT STA XSTW + 1;BITS 8-15 IN PPI6PC;DATA PORT  STA XSTW + 2;BITS 16-23 IN PPI7PA;DATA PORT STA XSTW + 3;BITS 24-31 IN PPI7PB;DATA PORT STA XSTW + 4;BITS 32-35 + TAG MVI A,IATAG;ACK. TAG OUT PPI2PB;DATA PORT MVI A,ZERO; OUT PPI2PB;RESET TAG CALL ISTCNT;COUNT INPUT STATUS WORDS RET; ; ;CLR - TAG (SOFT) SCLRXF: MVI A,CLRTAG;CHANNEL CLEAR TAG OUT PPI2PB;RESET CHANNEL MVI A,ZERO; OUT PPI2PB;RESET CLEAR TAG LCLA: IN PPI7PB;DATA PORT CPI ZERO;SEE IF CHANNEL DID RESET RZ;YES MVI A,05D; STA STATET;SAVE CURRENT STATE IN CASE OF ERROR CALL WAITT;WAIT LOOP AND TAG SEQUENCE CHECK JMP LCLA;CHECK AGAIN FOR CLEAR ; ;INPUT PARITY ERROR (SOFT) SPARXF: IN PPI7PB;DATA PORT CPI IPERR;CHECK FOR PARITY ERROR RZ ;RETURN IF NO PARITY ERROR MVI A,06D; STA STATET;SAVE CURRENT STATE IN CASE OF ERROR CALL TRANA;TAG RECOVERY AND ANALYSIS RET; ; ENDIF; ;CHANNEL DATA COUNTERS (SOFT) IEFCNT: LHLD EFCNT; INX H; SHLD EFCNT; RET; ; IAFCNT: LHLD AFCNT; INX H; SHLD AFCNT; RET; ; IODCNT: LHLD ODCNT; INX H; SHLD ODCNT; RET; ; IIDCNT: LHLD IDCNT; INX H; SHLD IDCNT; RET; ; ISTCNT: LHLD STCNT; INX H; SHLD STCNT; RET; ; ;TAG TIME-OUT & WRONG TAG ROUTINE WAITT: IN PPI7PB;GET CHANNEL TAG(S) STA WTAG;SAVE CHANNEL TAG(S) CPI ZERO; JNZ TRANA;TAG RECOVERY AND ANALYSIS LHLD TWCNT;TIME-OUT COUNTER INX H;INCREMENT SHLD TWCNT;SAVE NEW COUNT LDA TMCNT + 1;TIME-OUT MAX COUNT CMP H;CHECK IF MAX COUNT (LOW BYTE) RNZ; LDA TMCNT + 0;TIME-OUT MAX COUNT CMP L;CHECK HIGH BYTE RNZ; JMP TRANA;TAG RECOVERY AND ANALYSIS ;ERROR IS TIME-OUT  ; ;TAG RECOVERY AND ANALYSIS TRANA: MVI A,ZERO; STA PASS;RESET LOOP CONTROL LXI H,WTAG; CMP M;SAVED CHANNEL TAG CZ TMOREC;TAG TIME-OUT HANDLER LDA WTAG;SAVED CHANNEL TAG ANI ODRTAG;MASK FOR ODR CPI ODRTAG;IS IT AN ODR CZ ODTREC;ODR RECOVERY LDA WTAG;SAVED CHANNEL TAG ANI IDRTAG;MASK FOR IDR CPI IDRTAG;IS IT AN IDR CZ IDTREC;IDR RECOVERY LDA WTAG;SAVED TAG ANI EITAG;MASK FOR EI CPI EITAG;IS IT AN EI CZ EITREC;EI RECOVERY LDA WTAG;SAVED TAG ANI IPERR;MASK FOR PARITY ERROR CPI IPERR;IS IT A PARITY ERROR CZ PARREC;PARITY RECOVERY MVI A,00D;STATE 0 LXI H,STATET; CMP M;ARE WE IN STATE 0 LHLD MSG210;ERR MSG CZ PMSG;DISPLAY IT MVI A,01D;STATE 1 LXI H,STATET; CMP M;ARE WE IN STATE 1 LHLD MSG211;ERR MSG CZ PMSG;DISPLAY IT MVI A,02D;STATE 2 LXI H,STATET; CMP M;ARE WE IN STATE 2 LHLD MSG211;ERR MSG CZ PMSG;DISPLAY IT MVI A,03D;STATE 3 LXI H,STATET; CMP M;ARE WE IN STATE 3 LHLD MSG213;ERR MSG CZ PMSG;DISPLAY IT MVI A,04D;STATE 4 LXI H,STATET; CMP M;ARE WE IN STATE 4 LHLD MSG214;ERR MSG CZ PMSG;DISPLAY IT MVI A,05D;STATE 5 LXI H,STATET; CMP M;ARE WE IN STATE 5 LHLD MSG215;ERR MSG CZ PMSG;DISPLAY IT MVI A,ZERO; STA PASS;RESET LOOP CONTROL HLT; ; ;RECOVERY ROUTINES (WHAT TO DO GOES HERE) TMOREC: LXI H,MSG200;ERR MSG CALL PMSG;DISPLAY IT LXI H,MSG201;ERR MSG CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINES HERE RET; ; ODTREC: MVI A,ZERO; LXI H,PASS; CMP M; JNZ $ + 12;PRINT NEXT MSG ONCE PER PASS LXI H,MSG202;ERR MSG CALL PMSG;DISPLAY IT MVI A,ONE; STA PASS;SET PASS REGISTER LXI H,MSG203;ERR MSG CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINES HERE RET; ; IDTREC: MVI A,ZERO; LXI H,PASS; CMP M; JNZ $ + 12;PRINT NEXT MSG ONCE PER PASS LXI H,MSG202;ERR MSG CALL PMSG;DISPLAY IT MVI A,ONE; STA PASS;SET PASS REGISTER LXI H,MSG205;ERR MSG CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINES HERE RET; ; EITREC: MVI A,ZERO; LXI H,PASS; CMP M; JNZ $ + 12;PRINT NEXT MSG ONCE PER PASS LXI H,MSG202;ERR MSG CALL PMSG;DISPLAY IT MVI A,ONE; STA PASS;SET PASS REGISTER LXI H,MSG207;ERR MSG CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINE HERE RET; ; PARREC: LXI H,MSG208;ERR MSG CALL PMSG;DISPLAY IT LXI H,MSG209;ERR MSG CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINE HERE RET; ; OPENIF:;OPEN A FILE IF NOT ONE CREATE IT LXI D,FCBB;LOAD ADDRESS OF FILE CONTROL BLOCK B CALL CLRFCB;CLEAR FCB LOWER BYTES MVI C,OPENF;OPEN FILE COMMAND CALL FDOS;GIVE TO CPM CPI 0FFH;FF IF FILE IS NOT FOUND PUSH PSW;SAVE ZERO FLAG FOR LATER LXI H,MSG1;DISPLAY ALREADY EXIST MESSAGE CNZ PMSG;DO IT POP PSW;RESTORE ZERO FLAG JNZ EXISTS;FILE EXISTS THEN JUMP CREATE LXI D,FCBB;LOAD ADDRESS OF FCB B CALL MAKE;CREATE FILE EXISTS: LXI D,BBUFF;LOAD DMA ADDRESS MVI C,SDMADD;SET DMA ADDRESS COMMAND CALL FDOS;GIVE TO CPM LXI H,TMPFCB;TEMP. FCB XCHG;HL TO DE LXI H,FCBB + 12D;INPUT FCB CALL SFCBL;SAVE FCBB INTO TMPFCB (FOR REWRITE) CALL RESB;RESET BUFFER COUNTER CONTROLS LDA XADD + 0; STA EADD + 0; LDA XADD + 1; STA EADD + 1; LDA SADD + 0; MOV M,A; INX H; LDA SADD + 1; MOV M,A; INX H; LDA EADD + 0; MOV M,A; INX H; LDA EADD + 1; MOV M,A; LXI D,FCBB;LOAD ADDRESS OF FCB B CALL WRITE;SAVE FILE INFO IN THE FIRST RECORD CALL RESB;RESET BUFFER COUNTER CONTROLS ; LXI D,FCBB;LOAD ADDRESS OF FCB B ; CALL WRITE;SAVE FAKE FILE INFO IN FIRST DATA RECORD ; CALL RESB;RESET BUFFER COUNTER CONTROLS RET; ; OPENPIF:;;CREATE A FILE BUT NOT IF IT EXISTS LXI D,FCBC;LOAD ADDRESS OF FILE CONTROL BLOCK C CALL CLRFCB;CLEAR FCB LOWER BYTES MVI C,OPENF;OPEN FILE COMMAND CALL FDOS;GIVE PROBLEM TO CPM CPI 0FFH;FF IF FILE IS NOT FOUND PUSH PSW;SAVE ZERO FLAG FOR LATER LXI H,MSG1;DISPLAY ALREADY EXIST MESSAGE CNZ PMSG;DO IT POP PSW;RESTORE ZERO FLAG JNZ BOOT;REBOOT IF FILE EXISTS LXI D,FCBC;LOAD ADDRESS OF FILE CONTROL BLOCK C CALL MAKE;CREATE FILE LXI D,PBUFF;LOAD DMA ADDRESS MVI C,SDMADD;SET DMA ADDRESS COMMAND CALL FDOS;GIVE PROBLEM TO CPM ;CALL RESB;RESET BUFFER COUNTER CONTROLS RET; ; SAVINP;SAVE CHANNEL INPUT DATA TO DISK IF MOD. SAVIBF SET PUSH PSW;SAVE REGISTERS PUSH B; PUSH D; PUSH H; LHLD XCNTRB;CURRENT RECORD LENGTH COUNTER MOV B,H; MOV C,L; LXI D,RECSIZ;LOAD SET RECORD LENGTH LHLD BBPTR;LOAD CURRENT BUFFER POINTER LDA XDATA;GET LSB OF DATA WORD MOV M,A;MOVE DATA TO SECTOR BUFFER INX B;INCREMENT CURRENT SECTOR LENGTH COUNTER INX H;INCREMENT SECTOR BUFFER POINTER MOV A,D; CMP B; JNZ $ + 8; MOV A,E; CMP C; CZ WRITEBR; LDA XDATA + 1; MOV M,A;MOVE THE NEXT BYTE INX B; INX H; MOV A,D; CMP B; JNZ $ + 8; MOV A,E; CMP C; CZ WRITEBR; LDA XDATA + 2; MOV M,A;MOVE THE NEXT BYTE INX B; INX H; MOV A,D; CMP B; JNZ $ + 8; MOV A,E; CMP C; CZ WRITEBR; LDA XDATA + 3; MOV M,A;AND THE NEXT INX B; INX H; MOV A,D; CMP B; JNZ $ + 8; MOV A,E; CMP C; CZ WRITEBR; LDA XDATA + 4; MOV M,A;MOVE THE LAST 8 BITS OF THE 40 BIT WORD INX B; INX H; MOV A,D; CMP B; JNZ $ + 8; MOV A,E; CMP C; CZ WRITEBR; SHLD BBPTR;SAVE CURRENT BUFFER POINTER MOV H,B; MOV L,C; SHLD XCNTRB;SAVE CURRENT RECORD LENGTH COUNTER POP H;RESTORE REGISTERS POP D; POP B; POP PSW; RET; ; WRITEBR:;WRITE THE RECORD FOR B BUFF LXI D,BBUFF;LOAD DMA ADDRESS MVI C,SDMADD;SET DMA ADDRESS COMMAND CALL FDOS;GIVE TO CPM LXI D,FCBB;LOAD ADDRESS TO FCB B CALL WRITE;WRITE RECORD CALL RESB; RET; ; RESB:; LXI H,0000H;ZERO SHLD XCNTRB;ZERO CURRENT RECORD LENGTH COUNTER LXI B,0000H;ZERO CURRENT RECORD LENGTH COUNTER LXI D,RECSIZ;LOAD SET RECORD LENGTH LXI H,BBUFF;LOAD POINTER TO BUFFER B SHLD BBPTR;RESET BUFFER POINTER RET; ; FINB:; LXI D,FCBB;LOAD ADDRESS TO FCB B CALL WRITE;WRITE TWO MORE RECORD (AVOID AN EOF) LXI D,FCBB;LOAD ADDRESS TO FCB B CALL WRITE;JUST IN CASE LXI D,FCBB;LOAD ADDRESS TO FCB B CALL CLOSE;CLOSE FILE MVI A,ZERO;ZERO STUFF IN FCBB STA DRB; STA EXB; STA S1B; STA S2B; STA RCB; STA D0B;  STA CRB; STA R0B; STA R1B; STA R2B; RET; ; REWRIT:;RE-WRITE FIRST CONTROL RECORD CALL WRITEBR;MAKE SURE ALL IS OUT TO DISK LXI D,BBUFF;LOAD DMA ADDRESS MVI C,SDMADD;SET DMA ADDRESS COMMAND CALL FDOS;GIVE TO CPM LXI H,TMPFCBB;SAVE FCBB XCHG; LXI H,FCBB + 12D; CALL SFCBL;CALL LOOP LXI H,FCBB + 12D;LAST SAVE FCB XCHG;MOVE HL TO DE LXI H,TMPFCB;FCBB BEFORE FIRST WRITE CALL SFCBL;RESTORE OPENED FCB FOR REWRITE ; LXI D,FCBB;LOAD ADDRESS TO FCB B ; MVI C,CLOSEF;CPM CLOSE FUNCTION ; CALL FDOS;TELL CPM ; CPI 0FFH;DID IT? FF MEANS NO ; PUSH PSW;SAVE ZERO FLAG ; LXI H,MSG5;UNSUCCESSFUL CLOSE MESSAGE ; CZ PMSG;DO IT ; POP PSW;RESTORE ZERO FLAG ; JZ BOOT;REBOOT IF NO CLOSE ; LXI D,FCBB;LOAD ADDRESS TO FCB B ; MVI C,OPENF;OPEN FILE COMMAND ; CALL FDOS;TELL CPM ;  CPI 0FFH;FF IF FILE IS NOT FOUND ; PUSH PSW;SAVE ZERO FLAG ; LXI H,MSG8;UNABLE TO OPEN MESSAGE ; CZ PMSG;DO IT ; POP PSW;RESTORE ZERO FLAG ; JZ BOOT;REBOOT IF FILE NOT FOUND CALL RESB;RESET BUFFER COUNTER CONTROLS LDA XADD + 0; STA EADD + 0; LDA XADD + 1; STA EADD + 1; LDA SADD + 0; MOV M,A; INX H; LDA SADD + 1; MOV M,A; INX H; LDA EADD + 0; MOV M,A; INX H; LDA EADD + 1; MOV M,A; LXI D,FCBB;LOAD ADDRESS OF FCB B CALL WRITE;SAVE FILE INFO IN THE FIRST RECORD (RE-WRITE) LXI H,FCBB + 12D;RESTORE ORG. FCBB XCHG; LXI H,TMPFCBB; CALL SFCBL;RESTORE LOOP CALL RESB;RESET BUFFER COUNTER CONTROLS CALL FINB;CLOSE FILE RET; ; SFCBL:;LOOP TO MOVE FILE CONTROL BLOCK MVI B,18H;24 BYTES TO MOVE MOV C,M; INX H;INC. PTR. XCHG;SWAP POINTERS MOV M,C; INX H;INC. OTHER POINTER XCHG;SWAP AGAIN DCR B; JNZ SFCBL + 2;DO ALL RET; TMPFCB: DS 24D;SCRATCH AREA TMPFCBB: DS 24D;SCRATCH AREA ; CLRFCB:;CLEAR FCB IN THE DE ON ENTRY MOV H,D;COPY DE TO HL MOV L,E;LSB MVI A,0CH;AJUST FCB PTR TO PASS FILE NAME INX H;INC. AJUST DCR A;DEC. TIMES TO AJUST (SKIP FIRST 12 BYTES) JNZ $ - 2D;MOVE PTR. TILL DONE MVI B,18H;24 BYTES TO CLEAR MVI A,ZERO;CLEAR BYTE MOV M,A;CLEAR FCB INX H;INC. PTR. TO FCB DCR B;DEC. REMAINING COUNT JNZ $ - 3;LOOP TILL DONE RET; ; ;THE NEXT ROUTINES ARE USED TO MAKE DATA FILE RGCOPY:;COPYS ODW TO XDATA (40 BITS) LDA ODW + 0;LSB STA XDATA + 0;LSB LDA ODW + 1; STA XDATA + 1; LDA ODW + 2; STA XDATA + 2; LDA ODW + 3; STA XDATA + 3;  LDA ODW + 4;MSB STA XDATA + 4;MSB RET; ; RGLOAD:;LOADS XDATA INTO INTERNAL REGISTERS (40 BITS) LDA XDATA + 0;BYTE 0 MOV C,A; LHLD XDATA + 1;BYTES 1 & 2 XCHG;MOVE HL TO DE LHLD XDATA + 3;BYTES 3 & 4 RET; ; RGUNLD:;UNLOAD REGISTERS TO XDATA (40 BITS) MOV A,C; STA XDATA + 0;BYTE 0 SHLD XDATA + 3;BYTES 3 & 4 XCHG;MOVE DE TO HL SHLD XDATA + 1;BYTES 1 & 2 RET; ; MAKDAT:;MAKE DATA ROUTINE CALL RGCOPY;COPY ODW TO XDATA..OK MVI A,ZERO; STA XADD + 0;ZERO START ADDRESS (LSB) STA SADD + 0; STA XADD + 1;(MSB) STA SADD + 1; LDA DATMOD;GET MODIFIER CPI 0FEH;DO WE OPEN/CREATE FILE JNZ $ + 7;IF NOT COMMAND THEN SKIP OPEN/CREATE CALL OPENIF;OPEN FILE FOR INPUT DATA IF NOT ONE CREATE IT RET;OPEN/CREATE ONLY CPI 0FFH;IS IT A REWITE/CLOSE COMMAND JNZ $ + 7;SKIP CLOSE IF NOT CALL REWRIT;REWRITE FIRST DATA CONTROL RECORD RET;CLOSE/REWRITE ONLY CALL SAVINP;DONT MODIFY DATA FIRST TIME LHLD XPRGCNT;GET MODIFIER REPEAT COUNT (IS IT ZERO) MVI A,ZERO; CMP H;IS MSB ZERO JNZ COUNTL;ENTER LOOP IF REPEAT > ZERO CMP L;IS LSB ZERO JNZ COUNTL;ENTER LOOP IF REPEAT > ZERO RET;ALL DONE IF NO REPEAT COUNTL: CALL CHKDMOD;CHECK DATA MODIFERS CALL SAVINP;SAVE DATA TO BUFFER OR DISK IF BUFFER IS FULL LHLD XPRGCNT;GET MODIFIER REPEAT COUNT DCX H;DEC. COUNT SHLD XPRGCNT;UPDATE NEW COUNT MVI A,ZERO; CMP H;IS MSB ZERO JNZ COUNTL;LOOP UNTIL REPEAT = 0 CMP L;IS LSB ZERO JNZ COUNTL;LOOP UNTIL ALL IS ZERO RET; ; CHKDMOD:;CHECK FOR DATA MODIFIERS THEN MODIFY LDA DATMOD;GET DATA MODIFIER CPI 01H;NO OPERATION JZ NOOP;DO MOD. CPI 02H;INCREME NT OPERATION JZ INCOP;DO MOD. CPI 03H;DECREMENT OPERATION JZ DECOP;DO MOD. CPI 04H;SHIFT RIGHT OPERATION JZ RSFOP;DO MOD. CPI 05H;SHIFT LEFT OPERATION JZ LSFOP;DO MOD. CPI 06H;RANDOM OPERATION JZ RANDOP;DO MOD. CPI 07H;COMPLIMENT OPERATION JZ COMPOP;DO MOD. RET; ; NOOP:;NO OPERATION ROUTINE (40 BITS) CALL RGLOAD;LOAD INTERNAL REGS (ODW) CALL RGUNLD;UNLOAD INTERNAL REGISTERS TO XDATA RET; ; INCOP:;INCREMENT OPERATION ROUTINE (40 BITS) CALL RGLOAD;LOAD INTERNAL REGS (ODW) MOV A,C;MOVE LSB TO A REG CPI 0FFH;DO WE HAVE CARRY (FROM LAST TIME) JZ DOINC;INC. REST OF 40 BIT WORD INR C;INC. UNTILL FF (CARRY) JMP RGUNLD;UNLOAD REGISTERS DOINC: INR C;INC. BYTE 0 INX D;INC. BYTES 2 & 1 MVI A,ZERO; CMP D;IS BYTE 2 ZERO JNZ RGUNLD;REPEAT UNTILL 0 CMP E;IS BYTE 1 ZERO JNZ RGUNLD;REPEAT UNTILL ZERO INX H;INC. BYTES 4 & 3 JMP RGUNLD;UNLOAD REGS ; DECOP:;DECREMENT OPERATION (40 BITS) CALL RGLOAD; MOV A,C; CPI 00H; JZ DODEC; DCR C; JMP RGUNLD; DODEC: DCR C; DCX D; MVI A,0FFH; CMP D; JNZ RGUNLD; CMP E; JNZ RGUNLD; DCX H; JMP RGUNLD; ; RSFOP:;SHIFT RIGHT OPERATION (36 BITS) CALL RGLOAD; MOV A,C;BYTE 0 RRC; MVI A,7FH; STA XDATA + 0; JNC $ + 8; MVI A,0FFH; STA XDATA + 0; ; MOV A,E;BYTE 1 RRC; MVI A,7FH; STA XDATA + 1; JNC $ + 8; MVI A,0FFH; STA XDATA + 1; ; MOV A,D;BYTE 2 RRC; MVI A,7FH; STA XDATA + 2; JNC $ + 8; MVI A,0FFH; STA XDATA + 2; ; MOV A,L;BYTE 3 RRC; MVI A,7FH; STA XDATA + 3; JNC $ + 8; MVI A,0FFH; STA XDATA + 3; ; MOV A,H;BYTE 4 RRC; MVI A,7FH; STA XDATA + 4; JNC $ + 8; MVI A,0FFH; STA XDATA + 4; ; ; ; MOV A,H;BYTE 4 RLC; RLC; RLC; ORI 80H; MOV H,A; LDA XDATA + 0;DID BYTE ZERO HAVE CARRY OUT ANA H; RRC; RRC; RRC; RRC; MOV H,A; ; MOV A,L;BYTE 3 RRC; ORI 80H; MOV L,A; LDA XDATA + 4;DID BYTE 4 HAVE CARRY OUT ANA L; MOV L,A; ; MOV A,D;BYTE 2 RRC; ORI 80H; MOV D,A; LDA XDATA + 3;DID BYTE 3 HAVE CARRY OUT ANA D; MOV D,A; ; MOV A,E;BYTE 1 RRC; ORI 80H; MOV E,A; LDA XDATA + 2;DID BYTE 2 HAVE CARRY OUT  ANA E; MOV E,A; ; MOV A,C;BYTE 0 RRC; ORI 80H; MOV C,A; LDA XDATA + 1;DID BYTE 1 HAVE CARRY OUT ANA C; MOV C,A; ; JMP RGUNLD; ; LSFOP:;SHIFT LEFT OPERATION (36 BITS) CALL RGLOAD; JMP RGUNLD; ; RANDOP:;RANDOM OPERATION (40 BITS) CALL RGLOAD; MOV H,E; MOV L,C; MOV A,M; STA XDATA + 0; INX H; MOV A,M; STA XDATA + 1; INX H; MOV A,M; STA XDATA + 2; INX H; MOV A,M; STA XDATA + 3; INX H; MOV A,M; STA XDATA + 4; RET; ; COMPOP:;COMPLIMENT OPERATION (40 BITS) CALL RGLOAD; MOV A,H; CMA; MOV H,A; ; MOV A,L; CMA; MOV L,A; ; MOV A,D; CMA; MOV D,A; ; MOV A,E; CMA; MOV E,A; ; MOV A,C;  CMA; MOV C,A; JMP RGUNLD; ; UPDAFW:;UPDATES AFW FOR REPEAT PACKET (ADD XFCNT TO LAST AFW) LHLD XXFCNT + 0;LSB/MSB XCHG;HL TO DE LHLD AFW + 0;BYTES 0 & 1 DAD D;DE TO HL ADD SHLD AFW + 0;0 & 1 RNC;DONE IF NO CARRY OUT LHLD AFW + 2;BYTES 2 & 3 INR L;INC. BYTE 2 JNC $ + 4;IF NO CARRY DONT INC. BYTE 3 INR H;INC. BYTE 3 (HAD CARRY OUT OF BYTE 2) MOV A,H;MOVE MSB TO A REG. ANI 07H;STRIP OFF UNWANTED BITS (ONLY 26 - 0) MOV H,A;PUT BACK INTO H REG. SHLD AFW + 2;PUT BACK BYTES 2 & 3 RET; ; RDPAC:; MVI A,CONDT; LXI H,CMPMOD; CMP M; JZ INCMP;DO INPUT AND COMPARE CALL SIDWXF;DO INPUT AND NO COMPARE JMP INSAV;GO SEE IF INPUT IS TO BE SAVED (FILE) INCMP: LDA BUFRPT;GET BUFFER REPEAT MODIFIER CPI CONDT;IS IT SET JZ SIDRB;THEN GOTO REPEATING INPUT ROUTINE  CALL NEXTWD;GET THE SOURCE COMPARE WORD LDA XDATA + 4;(MSB) STA SDATA + 4;(MSB) START DATA LDA XDATA + 3; STA SDATA + 3; LDA XDATA + 2; STA SDATA + 2; LDA XDATA + 1; STA SDATA + 1; LDA XDATA + 0; STA SDATA + 0; CALL SIDWXF;GET INPUT WORD CALL COMPWD;COMPARE WORDS (DISK AND CHANNEL) INSAV: MVI A,CONDT; LXI H,SAVIBF;SAVE INPUT BUFFER MODIFIER CMP M; CZ SAVINP;SAVE THIS WORD LHLD XFCNT;TRANSFER LENGTH DCX H; SHLD XFCNT; MVI A,ZERO; CMP H; JNZ RDPAC;LOOP CMP L; JNZ RDPAC;LOOP IFIN: MVI A,CONDT; LXI H,SAVIBF; CMP M; CZ REWRIT; MVI A,CONDT; LXI H,CMPMOD; CMP M; RNZ; LXI D,FCBA; CALL CLOSE; RET; ; WRPAC: CALL INITC;OPEN OUT FILE AND GET FIRST RECORD (CNTRL) CALL SEARCH;FIND START ADDRESS IN FILE LDA BUFRPT;REPEAT BUFFER MODIFIER CPI CONDT; JZ SODRB;SEND DATA VIA REPEATING BUFFER WRPACL: CALL NEXTWD;GET NEXT BYTE (IN AND OUT OF BUFFER) CALL SODWXF;SEND OUTPUT DATA LHLD XFCNT;TRANSFER LENGTH DCX H; SHLD XFCNT; MVI A,ZERO; CMP H; JNZ WRPACL;LOOP CMP L; JNZ WRPACL;LOOP OFIN: LXI D,FCBA; CALL CLOSE; RET; ; ;ANALYZE CT BIT IN STATUS WORD CKCT: LDA XSTW + 3;GET CT PORTION OF STATUS WORD ANI 80H;CT MASK CPI 80H;IS IT SET (CT) CZ CTS;CALL IF SET RET; ; ;STATUS RECOVERY ROUTINE (WHAT TO DO GOES HERE) CTS: LDA DISPSTW;GET DISPMOD CPI CONDT;DO WE DISP STATUS JNZ $ + 7;SKIP MESSAGE IF NO LXI H,MSG31;GET MSG. CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINES HERE RET; ; ;ANALYZE STATUS ACTION IN STATUS WORD CKSA: LDA DISPSTW;GET DISPLAY MODIFIER CPI CONDT;DO WE DISPLAY STATUS JNZ $ + 7;SKIP MESSAGE IF NO LXI H,MSG33;GET MESSAGE CALL PMSG;DISPLAY IT LDA XSTW + 3;GET STATUS ACTION RRC;AJUST RRC;AJUST ANI 0FH;STATUS ACTION MASK CPI 00H;IS STATUS ACTION 0 CZ ACOD0;IF ZERO CALL ACTION CODE 0 HANDLER CPI 01H; CZ ACOD1; CPI 02H; CZ ACOD2; CPI 03H; CZ ACOD3; CPI 04H; CZ ACOD4; CPI 05H; CZ ACOD5; CPI 06H; CZ ACOD6; CPI 07H; CZ ACOD7; CPI 08H; CZ ACOD8; CPI 09H; CZ ACOD9; CPI 0AH; CZ ACODA; CPI 0BH; CZ ACODB; CPI 0CH; CZ ACODC; CPI 0DH; CZ ACODD; CPI 0EH; CZ ACODE; CPI 0FH; CZ  ACODF; RET; ; ;STATUS ACTION RECOVERY ROUTINES (WHAT TO DO GOES HERE) ACOD0: LDA DISPSTW;GET DISP MODIFIER CPI CONDT;DO WE DISP STATUS JNZ $ + 7;SKIP MESSAGE IF NO LXI H,MSG97;GET MSG CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINE HERE RET; ; ACOD1: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG35; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD2: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG37; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD3: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG39; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD4: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG41; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD5:  LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG43; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD6: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG45; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD7: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG47; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD8: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG49; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACOD9: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG51; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACODA: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG53; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACODB: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG55; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACODC: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG104;WAS NOT IN BOOK! CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACODD: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG57; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACODE: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG59; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ACODF: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG61; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ;ANALYZE RECOVERY ACTION IN STATUS WORD CKREC: LDA DISPSTW;GET DISPLAY MODIFIER CPI CONDT;DO WE DISPLAY STATUS JNZ $ + 7;SKIP MESSAGE IF NO LXI H,MSG63;GET MESSAGE CALL PMSG;DISPLAY IT LDA XSTW + 2;GET RECOVERY ACTION RRC;AJUST RRC;AJUST ANI 0FH;RECOVERY ACTION MASK CPI 00H;IS IT REC. 0 CZ RCOD0;CALL REC. CODE HANDLER 0 CPI 01H; CZ RCOD1; CPI 02H; CZ RCOD2; CPI 03H; CZ RCOD3; CPI 04H; CZ RCOD4; CPI 05H; CZ RCOD5; CPI 06H; CZ RCOD6; CPI 07H; CZ RCOD7; CPI 08H; CZ RCOD8; CPI 09H; CZ RCOD9; CPI 0AH; CZ RCODA; CPI 0BH; CZ RCODB; CPI 0CH; CZ RCODC; CPI 0DH; CZ RCODD; CPI 0EH; CZ RCODE; CPI 0FH; CZ RCODF; RET; ; ;RECOVERY ACTION RECOVERY ROUTINES (WHAT TO DO GOES HERE) RCOD0: LDA DISPSTW;GET DISPLAY MODIFIER CPI CONDT;DO WE DISPLAY STATUS JNZ $ + 7;SKIP MSG IF NO LXI H,MSG99;GET MESSAGE CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINE HERE RET; ; RCOD1: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG65; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; RCOD2: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG66; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCOD3: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG67; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCOD4: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG68; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCOD5: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG69; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCOD6: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG70; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCOD7: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG71; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCOD8: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG72; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCOD9: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG73; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCODA: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG74; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCODB: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG75; CALL PMSG; ;PUT RECOVERY ROUTINE HERE  RET; ; RCODC: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG76; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCODD: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG77; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCODE: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG78; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; RCODF: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG106;NO MESSAGE IN BOOK CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ;ANALYZE DEVICE STATUS IN STATUS WORD CKDEVS: LDA DISPSTW;GET DISPLAY MODIFIER CPI CONDT;DO WE DISPLAY STATUS JNZ $ + 7;SKIP MESSAGE IF NO LXI H,MSG79;GET MESSAGE CALL PMSG;DISPLAY IT LDA XSTW + 1;GET DEVICE STATUS ANI 80H;MASK OUT OTHERS CPI 80H;ATTENTION BIT CZ DVCOD8; LDA XSTW + 1;GET DEVICE STATUS ANI 40H;MASK OUT OTHERS CPI 40H;STATUS MODIFIER BIT CZ DVCOD7; LDA XSTW + 1;GET DEVICE STATUS ANI 20H;MASK OUT OTHERS CPI 20H;CONTROL UNIT END CZ DVCOD6; LDA XSTW + 1;GET DEVICE STATUS ANI 10H;MASK OUT OTHERS CPI 10H;BUSY BIT CZ DVCOD5; LDA XSTW + 1;GET DEVICE STATUS ANI 08H;MASK OUT OTHERS CPI 08H;CHANNEL END BIT CZ DVCOD4; LDA XSTW + 1;GET DEVICE STATUS ANI 04H;MASK OUT OTHERS CPI 04H;DEVICE END BIT CZ DVCOD3; LDA XSTW + 1;GET DEVICE STATUS ANI 02H;MASK OUT OTHERS CPI 02H;UNIT CHECK BIT CZ DVCOD2; LDA XSTW + 1;GET DEVICE STATUS ANI 01H;MASK OUT OTHERS CPI 01H;UNIT EXCEPTION CZ DVCOD1; LDA XSTW + 1;GET DEVICE STATUS CPI! 00H;NONE CZ DVCOD0; RET; ; ;DEVISE STATUS RECOVERY ROUTINES (WHAT TO DO GOES HERE) DVCOD8: LDA DISPSTW;GET DISPLAY MODIFIER CPI CONDT;IS IT SET JNZ $ + 7;SKIP MESSAGE IF NOT LXI H,MSG81;GET MSG CALL PMSG;DISPLAY IT ;PUT RECOVERY ROUTINE HERE RET; ; DVCOD7: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG83; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; DVCOD6: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG85; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; DVCOD5: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG87; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; DVCOD4: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG89; CALL PMSG; ;PUT RECOVERY ROUTINE HERE  RET; ; DVCOD3: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG91; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; DVCOD2: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG93; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; DVCOD1: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG95; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; DVCOD0: LDA DISPSTW; CPI CONDT; JNZ $ + 7; LXI H,MSG100; CALL PMSG; ;PUT RECOVERY ROUTINE HERE RET; ; ;STATUS WORD ANALYSIS STWANA: LDA DISPSTW;GET STW DISPLAY MODIFIER CPI CONDT;DO WE DISPLAY JNZ $ + 7;SKIP MESSAGE IF NO LXI H,MSG109;GET MESSAGE IF YES CALL PMSG;DISPLAY IT CALL CKCT;CHECK CT BIT CALL CKSA;CHECK STATUS ACTION CALL CKREC;CHECK RECOVERY ACTION CALL CKDEVS;CHECK DEVICE STATUS LDA DISPSTW;GET DISPLAY MOD. CPI CONDT;DO WE DISPLAY RNZ; RETURN IF NO DISPLAY LXI H,MSG102;GET MESSAGE CALL PMSG;DISPLAY IT LDA XSTW + 0;GET STW - DEVICE ADDRESS CALL CONDMP;DISPLAY IT LXI H,MSG110;GET CR & LF CALL PMSG;DISPLAY IT RET; ; ;DISPLAY STW HEADER AND STW STWDSP: LXI H,MSG30;GET HEADER MSG CALL PMSG;DISPLAY IT LXI H,MSG108;GET STW = MSG CALL PMSG;DISPLAY IT LDA XSTW + 4;NEXT DISPLAY INPUT STW CALL CONDMP; LDA XSTW + 3; CALL CONDMP; LDA XSTW + 2; CALL CONDMP; LDA XSTW + 1; CALL CONDMP; LDA XSTW + 0; CALL CONDMP; RET; ; ;COMPARE EXPECTED (STW) WITH INPUT (XSTW) COMPST: LDA SDATA + 0;SAVE SDATA STA XA + 0;TEMP. LDA SDATA + 1; STA XA + 1;  LDA SDATA + 2; STA XA + 2; LDA SDATA + 3; STA XA + 3; LDA SDATA + 4; STA XA + 4; LDA EDATA + 0;SAVE EDATA STA XB + 0; LDA EDATA + 1; STA XB + 1; LDA EDATA + 2; STA XB + 2; LDA EDATA + 3; STA XB + 3; LDA EDATA + 4; STA XB + 4; LDA STW + 0;NOW MOVE EXPECTED STW FOR COMPARE STA SDATA + 0; LDA STW + 1; STA SDATA + 1; LDA STW + 2; STA SDATA + 2; LDA STW + 3; STA SDATA + 3; LDA STW + 4; STA SDATA + 4; LDA XSTW + 0;NOW MOVE INPUT STATUS WORD TO COMPARE STA XDATA + 0; LDA XSTW + 1; STA XDATA + 1; LDA XSTW + 2; STA XDATA + 2; LDA XSTW + 3; STA XDATA + 3; LDA XSTW + 4; STA XDATA + 4; CALL COMPWD;COMPARE THEM LIKE DATA WORDS LDA XA + 0;RESTORE SDATA  STA SDATA + 0; LDA XA + 1; STA SDATA + 1; LDA XA + 2; STA SDATA + 2; LDA XA + 3; STA SDATA + 3; LDA XA + 4; STA SDATA + 4; LDA XB + 0;RESTORE EDATA STA EDATA + 0; LDA XB + 1; STA EDATA + 1; LDA XB + 2; STA EDATA + 2; LDA XB + 3; STA EDATA + 3; LDA XB + 4; STA EDATA + 4; LDA PSTATS;DID WE GET A COMPARE ERROR CPI DATERR;YES OR NO RNZ;RETURN IF NO ERROR LXI H,MSG107;GET ERR MSG CALL PMSG;DISPLAY IT RET; ; ; * * * MAIN ROUTINES * * * ; RUNPAC:; MVI A,GOODST; STA PSTATS; STA HSTATS; LXI D,PBUFF;LOAD DMA ADDRESS MVI C,SDMADD;SET DMA ADDRESS COMMAND CALL FDOS;GIVE PROBLEM TO CPM LXI D,FCBC;LOAD ADDRES TO FILE CONTROL BLOCK C CALL OPEN; CALL GETPAC;GET PACKET AND INITILIZE IT LHLD XFCNT;GET TRANSFER COUNT SHLD XXFCNT;SAVE XFER CNT FOR REPEAT PACKET PAKLOP: LHLD XXFCNT;GET SAVED XFER COUNT SHLD XFCNT;RESET XFER CNT VARIABLE MVI A,CONDT; LXI H,SAVIBF;SAVE INPUT MODIFIER CMP M; CZ OPENIF;THEN OPEN FILE FOR INPUT MVI A,CONDT; LXI H,CMPMOD;COMPARE MODIFIER CMP M; JNZ PLOOPA;SKIP OPEN AND INIT. IF NO COMPARE CALL INITC;OPEN AND INIT COMPARE FILE CALL SEARCH;FIND START ADDRESS IN SEQ. FILE PLOOPA:; MVI A,CONDT; LXI H,CLRMOD; CMP M; CZ SCLRXF;DO A CLEAR MVI A,CONDT; LXI H,EFWMOD; CMP M; CZ SEFWXF;SEND EF MVI A,CONDT; LXI H,AFWMOD; CMP M; CZ SAFWXF;SEND AF MVI A,CONDT; LXI H,IDWMOD; CMP M; CZ RDPAC;INPUT DATA MVI A,CONDT; LXI H,ODWMOD; CMP M; CZ WRPAC;OUTPUT DATA MVI A,CONDT; LXI H,EIWMOD; CMP M; CZ SEIWXF;GET STATUS LDA CMPSTW; CPI CONDT; CZ COMPST;COMPARE INPUT STW WITH EXPECTED STW LDA DISPSTW; CPI CONDT; CZ STWDSP;DISPLAY STATUS WD AND HEADER LDA ANASTW; CPI CONDT; CZ STWANA;ANALYZE STW AND RECOVER MVI A,CONDT; LXI H,MSTOP; CMP M; ;CZ MENUA;DISPLAY MENU CALL UPDAFW;UPDATE AFW FOR PACKET REPEAT (CONT ADDRESS) LHLD PRPCNT;GET PACKET REPEAT COUNT DCX H;-1 FROM COUNT SHLD PRPCNT;UPDATE VARIABLE MVI A,0FFH; CMP H;IS MSB ZERO YET JNZ PAKLOP;NO - DO AGAIN CMP L;IS LSB ZERO YET JNZ PAKLOP;NO - THEN KEEP GOING LXI D,PBUFF;LOAD DMA ADDRESS MVI C,SDMADD;SET DMA ADDRESS COMMAND CALL FDOS;TELL CPM LDA LSTPAC;LAST PACKET MODIFIER CPI CONDT;IS IT SET  PUSH PSW;SAVE FLAGS CNZ GETPAC;IF NOT LAST PACKET THEN GET NEXT PAC. IN FILE LHLD XFCNT;GET PACKET XFER COUNT SHLD XXFCNT;SAVE IT FROM CHANGE POP PSW;RESTORE FLAGS JNZ PAKLOP;START EXEC. NEXT PACKET IN FILE LXI D,FCBC; CALL CLOSE; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; SAVDAT: MVI A,GOODST; STA PSTATS; STA HSTATS; CALL MAKDAT;MAKE DATA BUFFER/FILE JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; DFILES: CALL INITC; CALL SEARCH; CALL NEWLIN; LHLD EADD;GET ENDING ADDRESS TO REG. PAIR H,L XCHG;LOAD ENDING ADDRESS INTO REG. D,E LOOPD: MOV A,C; CMP B; CZ NEWLIN; INR C; LHLD XADD;LOAD NEXT PROM ADDRESS INTO REG. PAIR H,L CALL NEXTWD; LDA XDATA + 4;LOAD THE A REG. WITH THE MSB OF THE DATA WRD. CALL CONDMP;DUMP ON CONSOLE LDA XDATA + 3; CAL!L CONDMP; LDA XDATA + 2; CALL CONDMP; LDA XDATA + 1; CALL CONDMP; LDA XDATA; CALL CONDMP; PUSH B; PUSH D; PUSH H; MVI C,CONOUTF;CPM CONSOLE OUT (FUNCTION 2) MVI E,20H;ASCII SPACE CALL FDOS; MVI C,CONOUTF; MVI E,20H; CALL FDOS; POP H; POP D; POP B; MOV A,H; CMP D; JNZ LOOPD; MOV A,L; CMP E; JNZ LOOPD; MVI A,GOODST; STA PSTATS; STA HSTATS; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; CFILES: MVI A,GOODST; STA PSTATS; STA HSTATS; CALL INITC; CALL SEARCH; CALL INITCB; CALL SRCHB; LHLD EADD;GET ENDING ADDRESS TO REG. PAIR H,L XCHG;LOAD ENDING ADDRESS INTO REG. PAIR D,E LOOPE: CALL NEXTWD;LOAD FILES - CURRENT DATA WORD LDA XDATA + 4;MSB OF WORD STA SDATA + 4;MSB OF WORD LDA XDATA + 3; STA SDATA + 3; LDA XDATA + 2; STA SDATA + 2; LDA XDATA + 1; STA SDATA + 1; LDA XDATA + 0;LSB OF WORD STA SDATA + 0;LSB OF WORD LHLD XADD; DCX H; SHLD XADD; CALL NXTWDB; CALL COMPWD; LHLD XADD; DCX H; MOV A,H; CMP D; JNZ LOOPE; MOV A,L; CMP E; JNZ LOOPE; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; SAVPAC: MVI A,GOODST; STA PSTATS; STA HSTATS; LDA PRGMOD;SEE IF WE NEED TO OPEN FILE CPI CONDT;IS OPEN CMD TRUE JNZ $ + 6;IF NOT SKIP OPEN (ALREADY OPEN) CALL OPENPIF;CREATE FILE CALL PUTPAC;PUT PACKET OUT TO DISK LDA LSTPAC;GET LAST PACKET MODIFIER CPI CONDT;IS IT SET JNZ $ + 9;IF NOT THEN SKIP CLOSE PACKET LXI D,FCBC;LOAD ADDRESS TO FCB B CALL CLOSE;CLOSE FILE JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; ;DELETES FILE FROM DISK FILDEL:; MVI A,GOODST; STA PSTATS; STA HSTATS; LXI D,FCBA; CALL FDELETE; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; ;DUMP ASCII TEXT FILES (INSTRUCTIONS) DTXTF: MVI A,GOODST; STA PSTATS; STA HSTATS; LXI D,ABUFF; CALL FILA;INIT. LOPTXT: CALL NEXTWD; LDA XDATA + 0; CALL ASCIID; LDA XDATA + 1; CALL ASCIID; LDA XDATA + 2; CALL ASCIID; LDA XDATA + 3; CALL ASCIID; LDA XDATA + 4; CALL ASCIID; JMP LOPTXT;LOOP UNTIL (EOF) ; ;DISPLAY DIRECTORY DIRADD:;AJUST PTR. IN BUFFER TO FILENAME POSITION ADD A;A * 32 ADD A; ADD A; ADD A; ADD A; LXI H,ABUFF; ADC L; MOV L,A; JNC $ + 4;  INR H; SHLD ABPTR; RET; ; DDDIR:;DISPLAY DISK DIRECTORY (FILENAME) MVI B,0CH;FILE NAME LENGTH LHLD ABPTR; MOV A,M; INX H; SHLD ABPTR; PUSH B; CALL ASCIID;PRINT THE CHAR POP B; DCR B; PUSH PSW; PUSH B; MOV A,B; CPI 03H;INSERT SPACE BETWEEN UFN & AFN (FILENAME PAS) JNZ $ + 9; LXI H,MSG18;'_' CALL PMSG;DISPLAY A SPACE POP B; POP PSW; JNZ DDDIR + 2; LDA XCNTR + 0; DCR A; STA XCNTR + 0; JNZ $ + 15; LXI H,MSG17;CR&LF CALL PMSG; MVI A,05H;FILENAMES TO DISP. BEFORE CR&LF STA XCNTR + 0; RET; LXI H,MSG16;_:_ CALL PMSG;DISPLAY IT RET; ; DDIR:; MVI A,05H;COUNT BEFORE CR&LF STA XCNTR + 0;TEMP REG. LXI D,ABUFF;SET DMA MVI C,SDMADD; CALL FDOS; LXI D,FCBA; MVI C,SCHFST;SEARCH FIRST CALL FDOS; CPI 0FFH;= FILE NOT FOUND JZ HLEVLG;BACK TO HIGH LEVEL LANGUAGE CALL DIRADD;AJUST BUFFER PTR. CALL DDDIR;DISPLAY FILENAME LDIR: LXI D,FCBA; MVI C,SCHNXT;SEARCH NEXT CALL FDOS; CPI 0FFH;= FILE NOT FOUND JZ HLEVLG;BACK TO HIGH LEVEL LANGUAGE CALL DIRADD;AJUST BUFFER PTR. CALL DDDIR;DISPLAY FILENAME JMP LDIR;LOOP TILL DONE ; ;PACKET DUMP (FILE) PKTDMP:; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; ;POST PACKET FILE ANALYSIS POSTANA:; JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; RESPRNT: MVI A,0C9H;AVAILABLE BYTE STA PRNSTS;UPDATE STATUS BYTE RET; ; CHKL: MVI A,0FFH;NOT AVAILABLE BYTE STA PRNSTS;UPDATE STATUS BYTE STA PRNSTS + 1;UPDATE VER. STATUS BYTE LDA BIOSL1;M259NCPC - BIOS AUTO CONSOLE PRINTER CPI 0C9H;LOCATION TO CHANGE IF C9 (RET INST) MVI A,01H;M259NCPC = VER. 1 STA PRNSTS + 1;UPDATE VER. FOUND STATUS BYTE CZ RESPRNT;CALL - IF FOUND LDA BIOSL2;M264NCPC - BIOS AUTO CONSOLE PRINTER CPI 0C9H;LOCATION TO CHANGE IF C9 (RET INST) MVI A,02H;M264NCPC = VER. 2 STA PRNSTS + 1;UPDATE VER. FOUND STATUS BYTE CZ RESPRNT;CALL - IF FOUND LDA BIOSL3;B59MB3NC - BIOS AUTO CONSOLE PRINTER CPI 0C9H;LOCATION TO CHANGE C9 (RET INST) MVI A,03H;B59MB3NC = VER. 3 STA PRNSTS + 1;UPDATE VER. FOUND STATUS BYTE CZ RESPRNT;CALL - IF FOUND RET; ; PRNT: MVI A,GOODST;GET GOOD STATUS BYTE STA PSTATS;UPDATE PROGRAM STATUS STA HSTATS;UPDATE HARDWARE STATUS LDA PRNSTS;GET BIOS AVAILABLE STATUS BYTE CPI 00H;NOT YET CHECKED CZ CHKL;CHECK FOR POSSIBLE BIOS'S LDA PRNSTS;GET BIOS AVAILABLE STATUS BYTE CPI 0FFH;NOT AVAILABLE BYTE PUSH PSW;SAVE ZERO FLAG FOR LATER LXI H,MSG22;WRONG BIOS MESSAGE CZ PMSG;DISPLAY IT POP PSW; MVI A,BADCMDS;BAD STATUS STA PSTATS;UPDATE PROGRAM STATUS VARIABLE JZ HLEVLG;BACK TO HIGH LEVEL LANGUAGE LDA PRNSTS + 1;GET VER. STATUS BYTE CPI 01H;IS IT BIOS VER. 1 JZ PRNB1;JUMP IF YES CPI 02H;IS IT BIOS VER. 2 JZ PRNB2;JUMP IF YES JMP PRNB3;THEN IT MUST BE VER. 3 ; PRNB1: LDA PRNSTS + 2;ON OR OFF STATUS CPI 0C9H;C9 = PRINTER OFF JZ TOGG1ON;THEN TURN IT ON JNZ TOG1OFF;THEN TURN IT OFF TOGG1ON: MVI A,00H;ON BYTE STA BIOSL1;CHANGE BIOS STA PRNSTS + 2;ON STATUS LXI H,MSG23;PRINTER ON MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; TOG1OFF: MVI A,0C9H;OFF BYTE STA BIOSL1;CHANGE BIOS STA PRNSTS + 2;OFF STATUS LXI H,MSG24;PRINTER OFF MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; PRNB2: LDA PRNSTS + 2;ON OR OFF STATUS CPI 0C9H;C9 = PRINTER OFF JZ TOGG2ON;THEN TURN IT ON JNZ TOG2OFF;THEN TURN IT OFF TOGG2ON: MVI A,00H;ON BYTE STA BIOSL2;CHANGE BIOS STA PRNSTS + 2;ON STATUS LXI H,MSG23;PRINTER ON MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; TOG2OFF: MVI A,0C9H;OFF BYTE STA BIOSL2;CHANGE BIOS STA PRNSTS + 2;OFF STATUS LXI H,MSG24;PRINTER OFF MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; PRNB3: LDA PRNSTS + 2;ON OR OFF STATUS CPI 0C9H;C9 = PRINTER OFF JZ TOGG3ON;THEN TURN IT ON JNZ TOG3OFF;THEN TURN IT OFF TOGG3ON: MVI A,00H;ON BYTE STA BIOSL3;CHANGE BIOS STA PRNSTS + 2;ON STATUS LXI H,MSG23;PRINTER ON MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; TOG3OFF: MVI A,0C9H;OFF BYTE STA BIOSL3;CHANGE BI"OS STA PRNSTS + 2;OFF STATUS LXI H,MSG24;PRINTER OFF MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG;BACK TO HIGH LEVEL LANGUAGE ; END. OS STA PRNSTS + 2;ON STATUS LXI H,MSG23;PRINTER ON MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; TOG2OFF: MVI A,0C9H;OFF BYTE STA BIOSL2;CHANGE BIOS STA PRNSTS + 2;OFF STATUS LXI H,MSG24;PRINTER OFF MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; PRNB3: LDA PRNSTS + 2;ON OR OFF STATUS CPI 0C9H;C9 = PRINTER OFF JZ TOGG3ON;THEN TURN IT ON JNZ TOG3OFF;THEN TURN IT OFF TOGG3ON: MVI A,00H;ON BYTE STA BIOSL3;CHANGE BIOS STA PRNSTS + 2;ON STATUS LXI H,MSG23;PRINTER ON MESSAGE CALL PMSG;DISPLAY IT JMP HLEVLG; TOG3OFF: MVI A,0C9H;OFF BYTE STA BIOSL3;CHANGE BI"##$$%%&&''(())**++,,--..//00112233445566778899::;;<<==>>??@@AABBCCDDEEFFGGHHIIJJKKLL