IMD 1.17: 9/11/2012 9:36:55 cpm3 super6  >o:~W!{> " OC > S>O32/=Y+2-=Y+U G+ G+ $ :+~@w,U ,+>2-=>1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!' #"* (,*#"+))[R%! !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!'  |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 ͘!4͘ !͙>O3F#Nů  SYSm-x¯*C=-#~: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file C3>L~~ÃG3x(OxAG:>G~ > 2<:4O y~ 8 q *@~(͙8ͺ{ͣ:72:>2>2?7O> 2<> :?G /_~(!& *1::{  _ O(  :<= L{((glrZwZ:4hZ::hZ:>hZZ>2< ~ ( w:728F8 <2:y2>:7W:0*3K5B(7:8Gz?"B*3"5:7G28xG![120G!> z:(8 DZP>w(>>w~un errorCan't recognize density of disk in$Read$Write$Seek$ error on track $ sector $ side $ drive $ $~un errorCan't recognize density of disk in$Read$Write$Seek$ error on3ͱ,USPS* |} !9":!"<<2* ͞ !~5 * ͡S ͤ HPROMW $$$CCP CMD CMCOPYSYS CM CPM3NBNKSYSb!"#$%&'CPM3BNK SYS()*+,-./CPM3BNK SYS01CPMLDR REL23DATE CM45EDFILE CMVDEVICE CM:89:;DIR CMr<=>?@ABCDIRLBL RSXDSETDEF CM DUMP CMFED CMIGHIJKERASE CMLMGENCOM CMtNOPQRSTUGENCPM CMVWXYZ[\]GENCPM CM(^_`GET CM3abcdLIB CM8efghLINK CM{ijklmnopMAC CM\qrstuvOSLOAD SYSBIOSKRNLASM}BOOT ASMCALLVERSASMCHARIO ASM$CPM3 LIB DRVTBL ASMDUMP ASM ECHOVERSASMFD1797SDASMQHELP HLPHELP HLPHELP HLPHELP HLPHELP HLPhCOLD MACHELP HLPFORMAT MAC@ABCDEHELP HLPHELP HLPhMODEBAUDLIBMOVE ASMPORTS LIBRANDOM ASMVDTBL MACLCHR MACSCB ASMLDSK MACSCB MACHDSK MACFDSK MAC/BDOS3 SPRM FDSK MAC0BNKBDOS3SPRjDSM MBEOP MFORMAT CMSETLPT MZSID MPHIST L TRACE L CPM3 SYSCPM3 SYSHEXCOM CM INITDIR CM     INITDIR CMzSAVE CMSET CMSSHOW CMBSUBMIT CM* TYPE CM!"XREF CMy#$%&'()*COMPARE CM +DTBL MACG12345SDSK MAC$678MODEBAUDLIB9PORTS LIB :CONFIG LIB;BLINK SUB<GENITAL SUB=LDSK MACLKRNL MACD   LMOV MAC CPMLDRX MAC LDRBIOS MAC/FORMAT MACFLDRLINK SUBLLINK SUBZ80 LIB/C3 LIB !"#$%&'C3 LIB (C3BBOOT MAC)*C3BKRNL MAC+,-./012C3BKRNL MAC3C3BMOV MAC45C3BOOT MAC 6C3CHR MAC<789:C3CLK MAC;C3DTBL MAC<C3FDSK MAC=>?@ABCDC3FDSK MACC3HDSK MAC%EFGC3INIT MAC?MONPROM MAC_GHIJKLHPROM MACjMNOPQRSMONITOR MACTUVWXYZ[MONITOR MAC"\]^DISK LIBDISK LIB ,-BIOS --LDR .-COLD _MEDIA MAC!BOOT MACFBKRNL MAC67BKRNL MACE PRN HEXtitle media change detect ;This program good only for physical drives 0 & 1 as 8" floppies .z80 global chk_media, chek_media, chk_mchng,chk_last global cdph, fdbusy, char_save ext dskerr, fseekntst ext cdsd, lastdrv ext delay ext @media, @adrv, @trk ext fdph0, fdph1 dsk_chng equ 15h ;Disk change port (Bit 7 = 1 is chng) dsk_chng_msk equ 80h ;Disk change bit dsk_io_err equ 1 ;Error return code to BDOS mflag equ 0ffh ;changed media flag cr equ 13 lf equ 10 ;---------------------------------- ; FLOPPY CONTROLLER PORT ADDRESSES ;---------------------------------- fbase equ 0ch ; base port addr of wd-1793 or wd-2793 fcmd equ fbase+0 ; command register fstat equ fbase+0 ; status register fdsd equ 014h ; density - size - drive register ;force interrupt frcint equ 0d0h page 60 ;------------------------------- ; FLOPPY CONTROLLER BIT TESTERS ;------------------------------- dnrdy equ 10000000b ;Drive not ready bit head_loaded equ 001 a,b ;out (fdsd),a ;pop af jr nz,errboot ; jump on ^C, flag media & force error ld a,(char_save) ; i or I -- assume media unchanged cp 'i' ret z cp 'I' ret z ld a,mflag ; normal media flag method or a ret errboot: push ix ; dph to hl pop hl call set_md ld a,dsk_io_err or a ret page ; Check to see if media has changed density chk_mchng: call chng_den ;change to other density ld a,(@trk) call fseekntst ;is the new density valid? jp nz,errk ;no, jump xor a ;z status ld (hl),a ;clear retry count ld a,mflag ;flag media change -- new density ret errk: call chng_den ;change back to original density or 1 ret chng_den: ld a,(cdsd) ;select other density xor dsd_den_msk ld (cdsd),a out (fdsd),a ld b,80 ;delay about 2 msec chdlop: call delay djnz chdlop ret page medmsg: db cr,lf,'Media change: I = ignore, RET = accept, ^C = error abort',0 char_save: ds 1,0 ; user reply cdph: ds 2,title boot module .z80 include CONFIG.LIB global isvctbl,siovec, ctcvec global init?, ldccp?, rlccp?, time?, phex, hex1 global save, ssp ext sioasvc,sioasvc,@civec, @covec ext @aivec, @aovec, @lovec, pmsg?, @cbnk ext xmove?, move?, bnksl?, cono? ext @sec, @min, @hour, @date if media_check_en ext chk_media, ibnksl, abank endif bdos equ 5 ccpbase equ 100h open equ 15 setdma equ 26 setmulti equ 44 read equ 20 st_bdos_er_mode equ 45 defalt equ 00 rtn_dsp equ 0feh page 60 include PORTS.LIB page ;----------------------- ; INTERUPT VECTOR TABLE ;----------------------- cseg ;NOTE -- The following table must not cross a page boundary when linked. ; Also, the lower 4 bits of address ISVCTBL must be zero. isvctbl: siovec: dw iret ; SIO ch B transmitter buffer empty dw iret ; SIO ch B external interrupts dw iret ; SIO ch B receiver ready dw iret ; SIO ch B special receive interrupt dw iret ; SIO ch A transmitter buffer emp00000b ;Head loaded bit fbusy equ 00000001b ;floppy controller busy ;dsd equates dsd_drv_msk equ 00000011b ;0 = A:, 1 = B:, 2 = C:, 3 = D: dsd_den_msk equ 00001000b ;0 = sd, 1 = dd ;------------- ;xdph equates ;------------- ;indexes mf equ 11 ;media flag dseg page chk_media: ld a,(fdbusy) or a ;floppy disk software busy? ret nz ;yes, exit in a,(fstat) and fbusy ;disk busy? ret nz ;yes, exit ; call delay ; ld a,frcint ;ensure type I status ; out (fcmd),a ; call delay ; in a,(fstat) ; and head_loaded ;head loaded? ; ret nz ;yes, exit ld a,(cdsd) ld c,a ld b,2 ;check two drives page chk_lp: in a,(dsk_chng) or a ;disk change indication? jp p,chk_bot ;no, jump ld a,c and 1 ;drive #0 ? jp nz,chk1 ;no, jump ld hl,fdph0+mf ;point to dr0 media flag jp chk0 chk1: ld hl,fdph1+mf ;point to dr1 media flag chk0: ld a,mflag ;media flag cp (hl) ;already flagged? jp z,chk_bot ;yes, jump ;Now we can flag a va0 ; current dph cseg ; busy flag in common fdbusy: ds 1,0 ; nz when floppy disk activity end ?$ (ty dw iret ; SIO ch A external interrupts dw sioasvc ; SIO ch A receiver ready dw sioasvc ; SIO ch A special receive interrupt ctcvec: dw iret ; CTC ch 0 svc dw ctc1svc ; CTC ch 1 svc dw iret ; CTC ch 2 svc dw iret ; CTC ch 3 svc page ;----------------------------------------------- ; DEVICE INITALIZATION RESIDES IN BANKED MEMORY ;----------------------------------------------- dseg init?: ;interrupt initialization di ld hl,isvctbl ; put interupt table vector in hl ld a,h ; put high byte of intr tbl vec in a ld i,a ; initalize interupt vector ld a,l ; put low byte of intr tbl vec in a-reg ld (lsiov),a ; put low byte in sio ch. b init block im 2 ; set interupt mode to 2 ; I/O REDIRECTION INITALIZATION ld hl,08000H ; device no. 0 is console (sio ch. a) ld (@civec),hl ; console input vector ld (@covec),hl ; console output vector ld hl,04000H ; device no. 1 is auxiliary (sio ch. b) ld (@aivec),hl ; auxiliary inpulid media change ld (hl),a ld (@media),a chk_bot: ld a,c xor 1 ;swap drive #'s ld c,a out (fdsd),a djnz chk_lp ret page ; If changing drives, check last drive for media flag before the change. chk_last: ld a,1 ;indicate floppy disk system busy ld (fdbusy),a ; for clock int/media ld hl,@adrv ld a,(lastdrv) cp (hl) ; new drive selection? ret z ; no, return inc a ; first time through? ret z ; yes, exit in a,(dsk_chng) and dsk_chng_msk ; disk change flag set? ret z ; no, exit ld hl,(cdph) set_md: ld de,mf add hl,de ld a,mflag ; flag media change ld (hl),a ld (@media),a ret page ;Check selected media for change chek_media: call delay in a,(fstat) or a ;drive ready? jp m,chk_er ;no, jump in a,(dsk_chng) and dsk_chng_msk ; disk change flag set? ret z ; no, exit chk_er: ld de,medmsg call dskerr ;patch -- kill change flag ;push af ;ld a,(cdsd) ;ld b,a ;or 3 ;out (fdsd),a ;ld@ :G:O:=27)yy/W!:#?>F6:_/G:^:_|OfKyp!VuWy/2&:ʌͺR g[ |OE w @~@w>2 :>* ͊  :3:z͞ !>2Ob 2O ͊ DM͠}>""2:2* ::E sMO s#rͰ :(±y==±*!^W*=2wX կw#|W|*" j*:Œ"R :W>R  :!jx!w4 ͚̚͡@ *!!~~#~O~#G~.|! w:cʇ̈́ w!x?w! ~ʽw-llqOý.:z<! Vq##~_@w͡:z<¸. . r##s}̴̭N! ~态O>G~G!~G~o>_yW#x#W{s+p+q r#r#r͋S "͙>2z4 !!q#p#w2wW* _҆-!s:!f͐ *~wĦ ɯ2*#~2~w !"2=2*~2=22̀:*wͳ  6 t vector ld (@aovec),hl ; auxiliary output vector ld hl,02000h ; device no. 2 is list (pio ch. a & b) ld (@lovec),hl ; output only page ; ctc initialization ld a,counter+tcfol+reset+ctrlwd out (ctc0),a ; initalize ctc channel 0 ld a,250d ; time constant for channel 0 out (ctc0),a ; channel 0 is expecting this ld a,inter+counter+tcfol+reset+ctrlwd out (ctc1),a ; initalize ctc channel 1 ld a,100d ; time constant for ctc channel 1 out (ctc1),a ; this channel issues interupts ld hl,ctcvec ; addr of ctc svc in inter table ld a,l ; need only the low byte of addr out (ctc0),a ; better be on a 8-byte block boundry ; ie. lower 3-bits =0 ; sio initialization ld hl,isioa ld bc,isioal*256+sioac otir ld hl,isiob ld bc,isiobl*256+siobc otir ; pio initialization ld a,0fh ; use both pio ch A & B w. parallel lst out (pioac),a ; pio ch A is output mode ld a,0cfh ; pio ch b is bit mode out (piobc),a ; channel b has o:O*7*/*"*"[ <:g:!,*}D!~6 !S͌rOͨ͠bbb  :G:xͨ›:ͨ: !6 :<!G: >xw>ɯw% :7!>wɯ:= x :r:G:=Ľ9xr:y!4 5~y‰5 6y͌Ҡ^I@O:=ʯ:Iy I I:µ  #I:! I I I! O͠*}S~#!""Sz-*"##">2:2*N#G2H  W W|:<ʈ:W:H2xy“:z<*"!z<~s^#V#N#FxN:D2x™# 22zG?S͝ >Gx™~™:ʙ2 ##~[*$a*" ͋ʄ *!~Ê͙l͋ 6> - Ͷ ͙ÇPY*{zBK yʢ â< yº! > ~Gw#* #~$ + *!>  #>? #*~ w0" *y͐}0͋  Ͷ ͙^ 2͋ :@ʕ ~#w> ͙{> _++V * -Os++r!x>w~6:6~#+w#w+~wɯ2z ̈́ ʹOFqy3 Np͆ͯ:Z~MwS~¹o¹#¹ # ? -Ϳw ʠʡڠ¡w  ~w 2 > y &!"*>o+"1͗ *!"s͙" r#~?w#>r# =J̧ 4  wͶ ~O ʙ:z<>w##~2_4~?ʈ>x:<ʈʈ{ͥ  2 :w++~=w4-Oҫ5:<4{͊ >2 :!3:z͞ Ͱ @ R _@ !">pio busy and strobe ld a,00011111b ; in = bsy,op,sel,flt,-ack out (piobc),a ; out = pb5,-prime,strobe xor a ; clear a-reg out (piobd),a ; reset strobe ei ; sign on ld hl,signon ; point to first part of signon message jp pmsg? ; display signon message & exit page ;----------------------------------- ; SIO CHANNEL A INITALIZATION TABLE ;----------------------------------- isioa: db 018h ; channel reset db 001h ; write reg 1 db 018h ; int on all recv char (no parity) 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 sio ch a init sequence ;----------------------------------- ; SIO CHANNEL B INITALIZATION TABLE ;----------------------------------- isiob: db 018h ; channel reset db 001h ; write reg 1 db 004h ; status affects interrupo ͠# CP/M Error On : $Disk I/O$Invalid Drive$Read/Only File$Read/Only Disk$File Exists$? in Filename$ÍÍ>2a."z:2:<:^^d{_zW{_zW ) 4#4#4 #  w#J|^#V#"##"##"###"#"##"! *!*|!6J67*w#w*w#w#w>2'q2*O͂yڍÍ<* p :0!:® :Í2*i "!s#r#p*N#F*^#V#F*:O}|y*Ͱ+*͹}|y #*Ͱ*DM"*s#r*s#r#pyoxg[ DM*0MD"!*MD$:Oi !N: i G>O: ʀ w *͂ :ʘ n` ~#fob 2O͊ "}:O*"2":O:G2!w*~zWw+ z #~*!* * ! ~2~+ -O~2 >2 :2 :w:P 4~:w r##rp# b |g}oj * # G | *ġ :*w**= ҵ * >  )ý :O!ͼ *:Oi } Á ~ |*@ :G:O:=27)yy/W!:#?>F6:_/G:^:_|OfKyp!VuWy/2&:ʌͺR g[ |OE w @~@w>2 :>* ͊  :3:z͞ !>2Ob 2O ͊ DM͠}>""2:2* ::E sMO s#rͰ :(±y==±*!^W*=2wX կw#|W|*" j*:Œ"R :W>R  :!jx!w4 ͚̚͡@ *!!~~#~O~#G~.|! w:cʇ̈́ w!x?w! ~ʽw-llqOý.:z<! Vq##~_@w͡:z<¸. . r##s}̴̭N! ~态O>G~G!~G~o>_yW#x#W{s+p+q r#r#r͋S "͙>2z4 !!q#p#w2wW* _҆-!s:!f͐ *~wĦ ɯ2*#~2~w !"2=2*~2=22̀:*wͳ  6  g"y27!":2:=7!~7#*{2!"z"9"1!dy3\K!n҂b&&!R_^#V* !p ^#Vͦ:ü!"(COPR. '82 DRI 151282^dj+5(.7@ U&%*gy&&%2GP+QB4``l!*^#V#^#Vw# ͒͒ ͒ ͙͒:sA ws  X*]w#6?#] .,:;[]=<>|!eʃ45#xa{ҏ_p# ’ ʙ ʙ:A2'!%"!9"1!>%:25:!=g:o$*~ 6 ~w w**{#z' r+s{ozg**|g= v ** ʄ ʏ  >22ͦ w*>ww: *#*s#r*  :!:G~# <*#~!d!ͼ ʷ !ͼ &!~6̀!"2*N q* * *}<6 ^#Vͳ>F D >!"**[ + "**K!z~<:w ##>w#w͂ × ̈́ > !~#! > > >N 4  ~*w::/GyO A +B 8y2:xOo&:W>Oi E:5 N/*"y2>2Í s͝ ͳ L2 ͤ ͔ *'  :O~Sy? x  - NG:<6 *L͝ ͪ !~+6:0 ' "!~6*>=)X!f_CÀ*}<~*~{ͧ> N Ä:G*`~!x_<_*y <:/G ~##~?  @ F6##N6͆y2zp##q:!2!"R |:2 ͥ:N>2<2͡|!w:>2*6s͙ͤ|͔ ~<Œw:ҧ* ~§2& @t ͬ ͖ :z<ô~?̀ ~?  ͥ *>o"6 "!_ ʍ:OsÙ*"8cͬ͌ ôͬ͌ í  ͔ͥ͡ `-}͔ Pͬ yá>O2{&Ó8:*:"R ̀**8q̀*"z::2ͬ͌ ͬ͌ ͬ(}/_|/*W}_*"}o|g">2{&&2{2|*͆ D<8+}7*#}o|g:O*s#r#w!~w~@w6Hq*>=)ү_|:0ʠ êͺ:<­ ‡Hq:>~c!o#~^#VG#~#~!##N#F#^#V#~#fo~" BH$DH@$ @A$ I"I$$DDH$I$ @ BD$DII !$$BD$$ @BB$H I $B IDI"@ !@$ A ! B$A@ $$ A$ $@" B"@ D! A$$D! I"!BI$ ! @"$I!$I$H H$I"I$I$BHDI $@@HHI$H"H $I$I$ B!I"" BDBA$@BB"$B@D! !  $$@@!!DD@@@I!@$"$ABD$$! $ HHAII "!!!!B"D !B"I$$A"D$!!$H $$! H  BBD$A DBAHD$IH$ B!$$H!H"$! A$A "$B"D$$$@D DB!$@H@$$DD!$$I$DH"H$A@!@ !$ " $$ @DD! !$!$$A DD"@$BD"$"I$HBI !  $$D $@I$Hcpu state ld (hl),0 ; zero tic counter if media_check_en ld a,(abank) ; save actual bank push af ld a,1 ; select bank 1 call ibnksl ld a,(0) cp 0c3h ; regular jump in adr 0? jp nz,mud ; no, jump -- means FORMAT or COPYSYS ; is active, so don't check media xor a call ibnksl ; select bank 0 call chk_media ; go check for media changes mud: pop af ; reselect actual bank call ibnksl xor a ; clear carry endif ; inc seconds ld hl,@sec ; service second counter in scb ld a,(hl) inc a ; increment second counter daa ; @sec is bcd so do daa after inc ld (hl),a ; store adjusted bcd cp 060h ; check if one minute elasped ret nz ; return to restore cpu state if under ld (hl),0 ; zero second count page ; inc minutes ld hl,@min ; service minute counter in scb ld a,(hl) inc a ; increment minute counter daa ; @min is bcd so do daa after inc ld (hl),a ; store adjusted bcd cp 060h ; check if one hoo!o#~*ͥ&  && > ͋͹d- j 6Ͷ > ͙F b -w ~<: ͯ~w#w#6##- a * ͯ~?G++Np# |mͥZ ͆͂ b ͧb !B6NN!B!z<*"!"z:{*:w:w**z}D#cdfg!"()*:_2{2"+ "~̀~!:҈6>Ë2$-:$<~2$*!""++ !ͥ 1${t vector db 002h ; write reg 2 lsiov: db 0 ; inter vec tbl low byte addr 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 sio ch b init sequence ; COLD BOOT SIGN ON MESSAGE signon: sign_on page cseg ;------------------------------ ; LOAD CCP FROM DISK TO BANK 1 ;------------------------------ ldccp?: ld c,st_bdos_er_mode ; set return & display error mode ld e,rtn_dsp call bdos ld de,ccpfcb ; located in move module ld c,open ; open file control block call bdos inc a jr z,noccp ; error if no file... ld de,0100h ld c,setdma ; set dma call bdos ld de,27 ld c,setmulti ; set record count call bdos ld de,ccpfcb ld c,read ; read records call bdos inc a jr z,noccp ld c,st_bdos_er_mode ; set default error mode ld e,defalt callur elasped ret nz ; return to restore cpu state if under ld (hl),0 ; zero minute count ; inc hours ld hl,@hour ; service hour counter in scb ld a,(hl) inc a ; increment hour counter daa ; @hour is bcd so do daa after inc ld (hl),a ; store adjusted bcd cp 024h ; check if next day ret nz ; return to restore cpu state if under ld (hl),0 ; zero hour count ; inc days ld hl,(@date) inc hl ld (@date),hl ret page ;******************* ; Various utilities ;******************* ;------------------------- ; print value in A in hex ;------------------------- 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 cono? ;---------------------------------- ; SAVE - RESTORE interrupt UTILITY ;---------------------------------- save: ex (sp),hl ; save hl on stk and put ret addr in hl push de ; save de push bc ; save bc push af ; save af NK"ɷ J>">2:N#=N>2!N2~2#! Œ t t)xu) O _"!w O?WGzO:xGyOõxwq*}<:<:*^#V=*"*DM**= ѵ+)) P ͞ g #+} ͔ ͳ >2*^#V+:<ʐ <' ͞ ' ~' *+"}{_}o= :<̝ ~' ") :OG#!K* N*))KKBI"B" $$@"UUUUUUUUUUUUUUUUUAHBI$"@!@HII D"BB"$ "H BD!$ H$BD!!$D  D $"BHD! $ HHAII "!!!!B"D !B"I$$A"D$!!$H $$! H  BBD$A DBAHD$IH$ B!$$H!H"$! A$A "$B"D$$$@D DB!$@H@$$DD!$$I$DH"H$A@!@ !$ " $$ @DD! !$!$$A DD"@$BD"$"I$HBI !  $$D $@I$H bdos ld bc,0201h jr moveccp noccp: ld hl,ccpmsg ; here if no ccp.com file call pmsg? jr $ ccpmsg: db cr,lf,'BIOS Err: Failed CCP.COM Load.',0 page ;---------------------------------- ; RELOAD CCP FROM BANK 2 TO BANK 1 ;---------------------------------- rlccp?: ld bc,0102h ;----------------------------------------- ; MOVE CCP FROM SOURCE BANK TO DEST. BANK ;----------------------------------------- moveccp: call xmove? ld hl,ccpbase ld de,ccpbase ld bc,0c80h jp move? page ;-------------------- ; TIME BIOS FUNCTION ;-------------------- time?: ret ;--------------------- ; CTC SERVICE ROUTINE ;--------------------- ctc1svc: ld (ssp),sp ; save sp ld sp,istk ; use interupt stack while in isvc call save ; inc 1/60 sec base counter ld hl,ticcnt ; tic counter counts 1/60 sec inc (hl) ; increment tic counter ld a,(hl) ; fetch ticcnt for compare cp 60 ; check if counted 60 tics yet ret nz ; return to restore  call go ; put restore address on tos pop af ; reinstate cpu to state before intr pop bc ; restore bc pop de ; restore de pop hl ; restore hl ld sp,(ssp) ; restore system stack pointer iret: ei ; enable interupts and return reti go: jp (hl) ; ret to next inst after call save page ;************** ; data storage ;************** ;-------------- ; base timer ;-------------- ticcnt: db 0 ; interrupt counter (counts 1/60 sec) ;-------------------------------- ; interrupt service DATA STORAGE ;-------------------------------- ssp: ds 2,0 ds 020h,0 istk:: ;--------- ; CCP FCB ;--------- ccpfcb: db booter,'CCP ','COM' ds 23,0 end  EXTRN INIT? ; general initialization and signon EXTRN LDCCP?,RLCCP? ; load & reload CCP for BOOT & WBOOT ; user defined character I/O routines EXTRN CI?,CO?,CIST?,COST? ; each take device in EXTRN CINIT? ; (re)initialize device in EXTRN @CTBL ; physical character device table ; disk communication data items EXTRN @DTBL ; table of pointers to XDPHs PUBLIC @ADRV,@RDRV,@TRK,@SECT ; parameters for disk I/O PUBLIC @DMA,@DBNK,@CNT ; '' '' '' '' ; memory control PUBLIC @CBNK ; current bank EXTRN XMOVE?,MOVE? ; select move bank, and block move EXTRN BANK? ; select CPU bank ; clock support EXTRN TIME? ; signal time operation ; general utility routines PUBLIC PMSG?,PDEC? ; print message, print number from 0 to 65535 PUBLIC PDERR? ; print BIOS disk error message header MACLIB MODEBAUD.LIB ; define mode bits ; External names for BIOS entry points PUBLIC BOOT?,WBOOT?,CONST?,CONIN?,CONO?,LIST?,AUXO?,AUXI? PUB JP 0 ; 30 reserved for future expansion JP 0 ; 31 reserved for future expansion JP 0 ; 32 reserved for future expansion ; BOOT ; Initial entry point for system startup. DSEG ; this part can be banked BOOT: LD SP,BOOT$STACK LD C,15 ; initialize all 16 character devices C$INIT$LOOP: PUSH BC CALL CINIT? POP BC DEC C JP P,C$INIT$LOOP CALL INIT? ; perform any additional system initialization ; and print signon message LD BC,16*256+0 LD HL,@DTBL ; init all 16 logical disk drives D$INIT$LOOP: PUSH BC ; save remaining count and abs drive LD E,(HL) INC HL LD D,(HL) INC HL ; grab @drv entry LD A,E OR D JP Z,D$INIT$NEXT ; if null, no drive PUSH HL ; save @drv pointer EX DE,HL ; XDPH address in DEC HL DEC HL LD A,(HL) LD (@RDRV),A ; get relative drive code LD A,C LD (@ADRV),A ; get absolute drive code DEC HL ; point to init pointer LD D,(HL) DEC HL LD E,(HL) ; get init pointer EX DE,HL C!"@*(*#":&2(͒:È0:+Òy<_W`iͫDM*w( ~bNpwDM*w(T] KKͦ*w("w(ͦ"w(@ :(N N#Fy*(}|h#ð*(ͫ# 6RX*q(6wDM*w(6# x *o(w*(*w(s#r̀*i(6#6*}("(w@*(|<ď+>!8>8> t>nͦv8 ~*o(wn:(r :(/GyOOA +¬ ¢y2(:(x¹o&:(W>OͫE:(ڟ?N/*"(y2ͦ+>2( ̀2(k,ºʺ*(*iҺ@:O~2(~WW:2(Ôyʛ?ʔx ʔ |̷ÔN͆G:(<2(x# W:(<­:2(2 G?>Gr x~:(2(Ô##~*$*">2>2: *(~w *" 2(>ʄ@~k:((s~*9~Ês~ ~ͅ<Eʀ@~›:(6!¦w͚̋,ÇPY*({zBKNyʺ Nú TITLE 'Root module of relocatable BIOS for CP/M 3.0' .Z80 ; version 1.0 15 Sept 82 TRUE EQU -1 FALSE EQU NOT TRUE BANKED EQU TRUE ; Copyright (C), 1982 ; Digital Research, Inc ; P.O. Box 579 ; Pacific Grove, CA 93950 ; This is the invariant portion of the modular BIOS and is ; distributed as source for informational purposes only. ; All desired modifications should be performed by ; adding or changing externally defined modules. ; This allows producing "standard" I/O modules that ; can be combined to support a particular system ; configuration. CR EQU 13 LF EQU 10 BELL EQU 7 CTLQ EQU 'Q'-'@' CTLS EQU 'S'-'@' CCP EQU 0100H ; Console Command Processor gets loaded into the TPA CSEG ; GENCPM puts CSEG stuff in common memory ; variables in system data page EXTRN @COVEC,@CIVEC,@AOVEC,@AIVEC,@LOVEC ; I/O redirection vectors EXTRN @MXTPA ; addr of system entry point EXTRN @BNKBF ; 128 byte scratch buffer ; initialization I/O memory address READ?: JP READ ; 13 read physical block(s) WRITE?: JP WRITE ; 14 write physical block(s) LISTS?: JP LISTST ; 15 return list device status SCTRN?: JP SECTRN ; 16 translate logical to physical sector CONOS?: JP CONOST ; 17 return console output status AUXIS?: JP AUXIST ; 18 return aux input status AUXOS?: JP AUXOST ; 19 return aux output status DVTBL?: JP DEVTBL ; 20 return address of device def table DEVIN?: JP CINIT? ; 21 change baud rate of device DRTBL?: JP GETDRV ; 22 return address of disk drive table MLTIO?: JP MULTIO ; 23 set multiple record count for disk I/O FLUSH?: JP FLUSH ; 24 flush BIOS maintained disk caching MOV?: JP MOVE? ; 25 block move memory to memory TIM?: JP TIME? ; 26 Signal Time and Date operation BNKSL?: JP BNKSEL ; 27 select bank for code execution and default DMA STBNK?: JP SETBNK ; 28 select different bank for disk I/O DMA operations. XMOV?: JP XMOVE? ; 29 set source and destination banks for one operation  ; to all selected devices CONOUT: LD HL,(@COVEC) ; fetch console output bit vector JP OUT$SCAN ; AUXOUT ; Auxiliary Output. Send character in ; to all selected devices AUXOUT: LD HL,(@AOVEC) ; fetch aux output bit vector JP OUT$SCAN ; LIST ; List Output. Send character in ; to all selected devices. LIST: LD HL,(@LOVEC) ; fetch list output bit vector OUT$SCAN: LD B,0 ; start with device 0 CO$NEXT: ADD HL,HL ; shift out next bit JP NC,NOT$OUT$DEVICE PUSH HL ; save the vector PUSH BC ; save the count and character NOT$OUT$READY: CALL COSTER OR A JP Z,NOT$OUT$READY POP BC PUSH BC ; restore and resave the character and device CALL CO? ; if device selected, print it POP BC ; recover count and character POP HL ; recover the rest of the vector NOT$OUT$DEVICE: INC B ; next device number LD A,H OR L ; see if any devices left JP NZ,CO$NEXT ; and go find them... RET ; CONOST ; Console Function = File = !,$-"h!9"f! ͉:2(t™:! =Hgo:O*;*Ó*"r*r"ÿ<:g:!͐*f}D! ~6t!r ͷO(^  : šn!6@G:x: P:<: P n6 t6! ^6 t6u:)<͠^! G:Ҏ>xʝʝw>ɯw̩z:»!>wɯ:=zxzz: :G:=/ͽx:Āy!4 5~y 5 6y(^@O:=7:y :I :=e:  zz#͂:!  r  ! O(Ì*( ~2* *}ʷ!#¶!""÷:_:*( #wxH! )6"& :!  x2 GH)+6:2, :!-  :, !+*( ~L#Bxz:* : *( ~ʓOڊ{2Ó#w:2. +:. 2- !% "( 2* ! "& !* ~4:2- Ԃ: Gͳͨ^2+ >2:2 *N#G2  !(s#r#p*k(N#F*m(^#V#F*(:(O}|y9*( +"*( }|yP#9*( *(DM"(*k(s#r*m(s#r#pyoxg͝DM*(0MD"(!*MD$:(Oë!(N:( «G>O:( ù* :(n` ~#foͤ2(O"(}:(O*( "(2("(:(O:(G2(!(w*~zWw+ !z?#~*!* *G!O~2(~m͗O~t>2(?:(2(O:(w:Ғ4~:(w?r##rp# ä |g}oì*g( #G ¾1*q(:(*w***> r )e(:(O!*c(:(Oͫ}@2æ  ~á *g(:(o$*~K6?~wKw**i({#zir+s{ozg*(*(|g͸*u(*(  R>22Z$w*q(>ww:(c( *(#*i(s#r*:(!(:G~#<*q(#~!;(!(!(!~6k!"2(*q(N1q*{(]*{([*y(}<^#V(t6 ^#V}e ^#V#~2(>â9͆>!"(*y(³*(X)*ÿ͂"*g(*K! ~<:wb##>w#w> r !~#<Output Status. Return true if ; all selected console output devices ; are ready. CONOST: LD HL,(@COVEC) ; get console output bit vector JP OST$SCAN ; AUXOST ; Auxiliary Output Status. Return true if ; all selected auxiliary output devices ; are ready. AUXOST: LD HL,(@AOVEC) ; get aux output bit vector JP OST$SCAN ; LISTST ; List Output Status. Return true if ; all selected list output devices ; are ready. LISTST: LD HL,(@LOVEC) ; get list output bit vector OST$SCAN: LD B,0 ; start with device 0 COS$NEXT: ADD HL,HL ; check next bit PUSH HL ; save the vector PUSH BC ; save the count LD A,0FFH ; assume device ready CALL C,COSTER ; check status for this device POP BC ; recover count POP HL ; recover bit vector OR A ; see if device ready RET Z ; if any not ready, return false INC B ; drop device number LD A,H OR L ; see if any more selected devices JP NZ,COS$NEXT OR 0FFH ; all selected were re:+ ̜2 5*( ~o#"( M š*( ~`Uoj*( ~#"( Ñ!* ~6s!+ 6:+ ‚xoͳ*& ~2+ o#"& !+ 6M : W:2 x ͺ*( +"( w  : >2* 2 :*( : +w"( ͺ:G:  !% "( ^-:* $P:<\: W:2 xM s:<9>2 :* 9x~+q ’x2 :* ͂^2 ¢ů͠: !ڽ*( ~5WèjM 2 ͨx*( +w"( j>2+ 2* jx. #NzW:  : !2 W! 5= ^x^ z: m :* ;#wO: 9ʌ ^:— ~x  ) :* :   >*( +"( w++2+ 2+ p!" r y< < <% zr ͷr 6r 9r MDÌ:o !6!h : ʚnt2 r 62 >r z<*)$"!z<~r s^#V#N#FxN:oʲ ̀õ (# Þ !"@*(*#":&2(͒:È0:+Òy<_W`iͫDM*w( ~bNpwDM*w(T] KKͦ*w("w(ͦ"w(@ :(N N#Fy*(}|h#ð*(ͫ# 6*q(@-RXDM*w(6# x *o(w*(*w(s#r̀*i(6#6*}("(j-@*(|<ď+>!8>8> t>nͦv8 ~*o(wn:(r :(/GyOOA +¬ ¢y2(:(x¹o&:(W>OͫE:(ڟ?N/*"(y2ͦ+>2( ̀2(k,ºʺ*(*iҺ@:O~2(~WW:2(Ôyʛ?ʔx ʔ |̷ÔN͆G:(<2(x# W:(<­:2(2 G?>Gr x~:(2(Ô##~*$*">2>2: *(~w *" 2(>ʄ@~k:((s~*9~Ês~ ~ͅ<Eʀ@~›:(6!¦w͚̋,ÇPY*({zBKNyʺ Nú wM  2*7w#6?#7 .,:;[]=<>|!?]45#Ra{i_p# l s s͂:(A2= / ::0! dگ61#d ڸïp#:w#6 !6:6 *#!)6.#)͂ O(BDOS CP/M Error On : Disk I/OInvalid DriveRead/Only FileRead/Only DiskPassword ErrorFile Exists? in Filenameò ò >2(a." :(2:<:5(5(;(:(2ɯ2(2{_zW{_zW ) 74#4#4)7( #  w#*J|^#V#"i(##"k(##"m(###"o(#"q(##"(!s( )*s(!()*(|!(6~67*k(w#w*m(w#w#w>2('å2(*OͶyڲ ò <*e(Ͳ:0!(:(:(ò 2*(>*ͫ"(~Gw#* #~$%+@*9> # #>? ;*~ w-xąH"(0 *(#ĊH( ,ˆʀHÈ2(xą ):(@O~#w͚ʀô̓-b_++V@* )͗Os++r!x>w~6:(6~#+w#w+~;wɯ2 K,OFq-yl?Npg&:(ʓ~†wŒ~è# # x ͗w w@ ~wb͐Ú!"*>o+"v- *!b("": r#~?w#>r# L=J! Lv w,b ?~O ͆=: <>w##~2( 4~?̓-¹:(<üAX2(r K:(w++~=wv 4͗O5:(2(X:(!(v q: v v Mڂ?Ͷ >T͓Â!"(>(Â:(G:(O:(h=2(7ryy/W!(:(lڈ>F6:(_/G:(ʧ:(ڨ|OͤG:(_OzW{|:(*(}|BKN zyG͚c2(ZT͐-3#͗#@!Y#sY#̓ Y# Y#ͅ:(As#:(@#@!#$̓ —#>2—#͇ͱ * «#>2(͙ wB p'+!#:(w͚AP{" 2! W>O2 ø }-R*e()$:(r "ök*w()$*c()$-}-ͤÀk*s(" :(;$:r 2͚ù͚͚}/_|/*e(W}_*c("e(}o|g"c(>2({2{2g*w(ʪ$Ң$Þ$+}$*(#}o|g:(O *s#r#w!~w/~@w//Hͥ*e(>=)%_g:0%w:- %:(<%R$Hͥ:(>(~c!o#~E%^#V)$G#~#~!%~ b%% k%%##N#F#^#V#~#fo~o!o#~>T}! 6**#K" G*~ xr ͐-xą@7(͚S!ʀq&&͋"&@6,͚%Xͤ͋&͗wO~<:( g&~w#w#6##)͋&@ * g&~?G++N͆p# Þ&͐*6!¿&?~p*6 &>2ͱ ! ! ͷ w*o!!$$HH !"BB$HHDA! "D"H $B!$!AI!$ $ H  H A$I! I" $$BD"$H "AHD @ I  B"$$H @@@@" BHB  !I$ @ $@$"$AI$$IBI$I H@@I!$DA $ $@$ !$!!" !$I@I $@ $ @!H"BI"HI DIHA DD$HH $  B D$ "I$I$H$ I !  $I$I$I $@HD$@!$"A$A DBIDB  @$$DD""I $BHI$IB !@"BD BBD "@B @$ $BI I B$@" ! "H !$B I$D@! !$ @H!$$D"@A@ DHII  D@@ $ DHI"D$ @ $""@ B! @@D $$A$ $D "@I $A$$I!HI$ BA$ $DH $I$I"HI$I!$DB$"B I$$I$ !I$@DBB$@D@"I A!$ @  @  "$ $I$I$ B!$@ I @I$ HBDH$ A$H!:(2(9:(>#:(>#*+S!X:(ڜq: ʺ!((ʵ>2( ͤ2(O DM͸}>r "("(2(:(2(* :(:(FsO s#r:(„y==„*(!(^W*y(^#Vx+7=2(wͼկw#KWK*("(J T͞*(:(["(Ͷ:(WMںʛ>(úͶ >TJ:(!(ʷ͞x!(w4 PWP  Â*!!~~#~O~#G~.|°! w:ck[!x?[! ~ʤ͆[͗PPv qO-á=.: <ʰ! Vq##~_@w: <œ. ʩ.ʩA r r##s <}r cN! ~态O>G~G!~G~o>_yW#x#W{s+p+q7r#r#r>@ >2  !!q#p#w2(wW*e(_3ҫ -!(s:(!(xQ*q(~wɯ2(2(ù*~2(~w#~2(~wZ!""2(=2*~2(=2(2(k:*wX/ 6X*(w'ͧ B pͧ ,Úgsr ͐-ͤ͜!S')_'ͤ̓ ~?w͐s-?F͜p!'̓ ¡'>2ͱ ?~¾'¾''''>w'͙ =2(͜!:(wÚ~̓ ʑ'pá'!(6NN!(r )!(N !)z<*)$"!" :X(*:(w:(w#:(w*2* }D#cdfg!"()*{(X)^#V!"(:(<)!~<<)^#V*(<)"("(x+)!(*(>X)*{()Q*:(_2({2(Ē*"(͂"X*~<)ҍ) -)a*ʚ)~)6*(:(X*)!(:(T>q*k)!(:()-6>)=)Q!(QX<k*{(}<^#V{!~! _*o(~s̓  2@ !()#w*~"!!(Fw̓ :(w̚":>#2(̓ *~wć"#Fx T]## #~ ȷ   *4 # '  4 !( *~^ ^ 33G# P v :dv 6 y #*~w>2 *p@! ~*"v@*w# ) 6# ͙   !N)@ u :G*g(`~!x_<_@!*o(y<:(/G?~##~? 6!K@?F6##N6 2 p##q:r !Z$2!"ög:(2T͐-:ʹ!>2<2(!!(w: >2(*6!O~2(+A@2! ͚A=: <%~?¯"k"?~?ʾ"ZT͐"*>o"͒"!:O"(Ý"}-6͚ð**(}+*(}+"(*(x+"(x+m+*(^#V*( s#r*(*(s#r*(:(Y+4Y+̓+*(*(~#ng+*( s#r ^#V|:(w:(ʴ+>2d,:+#++>29+2~2#! , , ,)x,) ,O +"!w [,O?WGzO:(V,xGyOG,xwq*}(}2*i(^#V+ d,!(K*}(@+*)):( K:(ڗ>2#-×:#-<)2#-*(!""++"(29-C-%w*{(}<^#Vz!(c-!>c-! J-w*q(~69!͐9bBI$"" HB@ UUUUUUUUUUUUUUUUUAPDA$! @I !@D@BDI@!B$ @$I$$ "@$$@@HHBD"D$H D@!IB@ A"B HBIB$$ "$ D$!"D$H$D$I@D BD" H$BHHBDHB"H!"LOADER y; !91""|0!~ʞz=_: _* ""*og*%|}D S#N#F:ʒ#4ʝ^#V{‚:¿*.~w*DM!&_*.& >k s#rr+6.""1*D`.45. F.~. ^#Vx>`. s#rz 6#N#fi%$g1:=<@v_}v=p{_3;{<g"T=X3*j ~P#~R#~L{gbk#N#Fk$&Zcx {~#o}o1!;!"Ï:= w*wWx ~#&*.~s*"ѷ\ Cannot load Program$221282 COPYR '82 DRI <bHA$@DH   A@!" $$@2M ÙX X X S 1-! j 1".~2.~2 :Xck*kͮ  b < .~=>$.w.6#w.6#w.61.~  .~~w@.p T~º>+~.~~! yͮ Ë.~~w2g !PROF $No File$ required$ERASE $ (Y/N)? $ Press RETURN to Continue $ (User 0)$NON-SYSTEM FILE(S) EXIST$: $$$ SUB_  ! 6=  { *.pѯ:r x , \<=!Ͱ =ɯ2 \s 2 ! D ;! : .44 #4"l ~[* 2 a7 {7 w!Y #! *l "l " ~ U #D ]T!̷ 6*%.w#w!} 6 r 6 #w.6#6 #t#6.wo*.s#r.rͧ ̧ m . ^#V45+ w#w.f.5\A "l " l |F# !( | !( : x. +"l ! ͮ   ͮ ~!G8 * ~;#1 կA *l ~:g #I ѯ*l  *l ~0څ :҅ q X x<Ü AX QX X ~@#~:k #^ *jT~# ® wy#ù ! 4 : !Ͱ ~@*h~ yw y/w*hw*h~I E> ͦ > æ % 0  < : ~ȹͦ #* A !g ~6*  * >? A *l " ~0: :: q "l x~0 xG#Gs : &͘ ͤ &ͦ %˜ >  Ʌo$>?· !  > # ͮ x> # ~ Enter User #: ; all selected were not ready, return false RET ; CONIN ; Console Input. Return character from first ; ready console input device. CONIN: LD HL,(@CIVEC) JP IN$SCAN ; AUXIN ; Auxiliary Input. Return character from first ; ready auxiliary input device. AUXIN: LD HL,(@AIVEC) IN$SCAN: PUSH HL ; save bit vector LD B,0 CI$NEXT: ADD HL,HL ; shift out next bit LD A,0 ; insure zero a (nonexistant device not ready). CALL C,CIST1 ; see if the device has a character OR A JP NZ,CI$RDY ; this device has a character INC B ; else, next device LD A,H OR L ; see if any more devices JP NZ,CI$NEXT ; go look at them POP HL ; recover bit vector JP IN$SCAN ; loop til we find a character CI$RDY: POP HL ; discard extra stack JP CI? ; Utility Subroutines IPCHL: ; vectored CALL point JP (HL) ; print messageg pointed to by HL and ending w/ 0 PMSG?: ; print message @ up to a null ; saves & ILE.S !+2 !  +~d {   O! w+w+: =w! 5 c ʋ  :p  m>> ͧ  N Ĩ –.~+w.~2  9 : ! ~##~ !7 : !Կ : x*l " !ZXچ! 6  zz: 6 : %2p  ͆ : =̀ 2r  DIR TYPE ERASE RENAME DIRSYS USER u"Q}:\=p:r Aæ R ÂN ʸ} !M 545 x ]  ̵ 6 : oG! ~怹>2M  xf>:ͦ ͤ ͍ ͤ f ¹2 lf   ͫR  L͞L I *  *  A }_Yl !ͮ ͒6 \&đ %* "l ͍  ûȷ45: w ? A I N   SUBMIT COM ! ͮ ! 6 #"l  !cͿ  O!:r :ͦ ͍ !~B I !pͰ ^#VCOM SUB PRL y!cͰ  î !" * %.2P#ͮ !g 4*l +"l ͷ 2 "Qx2Sl "Tx2V!q ~ :p ͆ .ڶ2* og$2| .w#w#w#wady, return true RET COSTER: ; check for output device ready, including optional ; xon/xoff support LD L,B LD H,0 ; make device code 16 bits PUSH HL ; save it in stack ADD HL,HL ADD HL,HL ADD HL,HL ; create offset into device characteristics tbl LD DE,@CTBL+6 ADD HL,DE ; make address of mode byte LD A,(HL) AND MB$XON$XOFF POP HL ; recover console number in JP Z,COST? ; not a xon device, go get output status direct LD DE,XOFFLIST ADD HL,DE ; make pointer to proper xon/xoff flag CALL CIST1 ; see if this keyboard has character LD A,(HL) CALL NZ,CI1 ; get flag or read key if any CP CTLQ JP NZ,NOT$Q ; if its a ctl-Q, LD A,0FFH ; set the flag ready NOT$Q: CP CTLS JP NZ,NOT$S ; if its a ctl-S, LD A,00H ; clear the flag NOT$S: LD (HL),A ; save the flag CALL COST1 ; get the actual output status, AND (HL) ; and mask with ctl-Q/ctl-S flag RET ; return this as the status CIST1: ; get input status with LD BC,TABLE10 LD DE,-10000 NEXT: LD A,'0'-1 PDECL: PUSH HL INC A ADD HL,DE JP NC,STOPLOOP INC SP INC SP JP PDECL STOPLOOP: PUSH DE PUSH BC LD C,A CALL CONO? POP BC POP DE NEXTDIGIT: POP HL LD A,(BC) LD E,A INC BC LD A,(BC) LD D,A INC BC LD A,E OR D JP NZ,NEXT RET TABLE10: DW -1000,-100,-10,-1,0 ; print disk drive error message PDERR?: LD HL,DRIVE$MSG CALL PMSG? ; error header LD A,(@ADRV) ADD A,'A' LD C,A CALL CONO? ; drive code LD HL,TRACK$MSG CALL PMSG? ; track header LD HL,(@TRK) CALL PDEC? ; track number LD HL,SECTOR$MSG CALL PMSG? ; sector header LD HL,(@SECT) CALL PDEC? ; sector number RET ; BNKSEL ; Bank Select. Select .~ .w#w~?w; ; ! ~#49 w#~$ A  < > _I  ! 6 ! ~#Ͱ 6 m   _  ! 6=  { *.pѯ:r x , \<=!Ͱ =ɯ2 \s 2 ! D ;! : .44 #4"l ~[* 2 a7 {7 w!Y #! *l "l " ~ U #D ]T!̷ 6*%.w#w!} 6 r 6 #w.6#6 #t#6.wo*.s#r.rͧ ̧ m . ^#V45+ w#w.f.5\A "l " l |F# !( | !( : x. +"l ! ͮ   ͮ ~!G8 * ~;#1 կA *l ~:g #I ѯ*l  *l ~0څ :҅ q X x<Ü AX QX X ~@#~:k #^ *jT~# ® wy#ù ! 4 : !Ͱ ~@*h~ yw y/w*hw*h~I E> ͦ > æ % 0  < : ~ȹͦ #* A !g ~6*  * >? A *l " ~0: :: q "l x~0 xG#Gs : &͘ ͤ &ͦ %˜ >  Ʌo$>?· !  > # ͮ x> # ~ Enter User #:C> and saved PUSH BC PUSH HL CALL CIST? POP HL POP BC OR A RET COST1: ; get output status, saving & PUSH BC PUSH HL CALL COST? POP HL POP BC OR A RET CI1: ; get input, saving & PUSH BC PUSH HL CALL CI? POP HL POP BC RET ; CONST ; Console Input Status. Return true if ; any selected console input device ; has an available character. CONST: LD HL,(@CIVEC) ; get console input bit vector JP IST$SCAN ; AUXIST ; Auxiliary Input Status. Return true if ; any selected auxiliary input device ; has an available character. AUXIST: LD HL,(@AIVEC) ; get aux input bit vector IST$SCAN: LD B,0 ; start with device 0 CIS$NEXT: ADD HL,HL ; check next bit LD A,0 ; assume device not ready CALL C,CIST1 ; check status for this device OR A RET NZ ; if any ready, return true INC B ; drop device number LD A,H OR L ; see if any more selected devices JP NZ,CIS$NEXT XOR AWCOPYRIGHT 1982, DIGITAL RESEARCH151282654321  {__27:6:72!"> 22O* 27:6:7>2y2> 22* 27:6:7M>2y2> 22* 27:6:7{x2y2> 22* 27:6:7¡> 22* 27:6:7>22*o&)))))))a{__> >  ` ]AO/A2A_sA2|  AڣA2A_ !"@>2<!<4:VN>2>:!>4E!>^!FN)y*@DMX2B:B* <2B:?;ͬ>͆:*@"@1iC }0s>26x>26:] ʲ\<“Y2|!DMX\Ú/2?͈!?6Y </:A_$![ ^#Vɧ:=#='/ `     ![&K)͙͘:=2 *&:)G͙͘:=2 TIRaUT`?     RaUTKKRaUT `     RaU$͒:!'''ݶ݆:":#:$ݦ>0!F~> !F~ g(2![ ^#V:!'''ݶ>pݶiAͪià>^V͛z2~[X|}*Ö*)>X­|™Öq~O #ô>/<33O _ W{***)>'|h&)))G~;X~jK>R>wa͸q*{*)>!"*"!A!***)'͜|8lrÍÓäuçìñ üx+Ù5øØx͝1x͝>22Ư1O$@{->2$-:$<~2$*6>Ë̀~!:҈!w# :@!w:!@w22Y<"9:9o::g*d:=<2=:9o::g"9=͈:@w% x<"9:9o::g* :==2=:9o::g"9× +CPM3 SYSCP/M 3 COPYSYS - Version 3.0$Source drive name (or return for default) $Source on then type return $Destination drive name (or return to reboot) $Destination on then type return $Do you wish to copy CPM3.SYS? $Function complete$ERROR: Invalid drive name (Use A, B, C, or D)$ERROR: No source file on disk.$ERROR: No directory space.$ERROR: Out of data space.$ERROR: Write protected?$ERROR: Possible incompatible disk format. Type return to ignore.$ERROR: Close operation failed.$\<“Y2|!DMX\Ú/2?͈!?6Y </:A_$͉( Ͳ !Ͳ(> >2![ !K  >= , Drive Not Ready, Write Protected Disk  w !> " ͉(!> G > :g(!` O !i O(!r z(~[$͒ͻ~˗##ͰK"[ ~ :( {2yw:$ݦG_(x! (4>w:L> ͰwGLx>  `g( o('s#r:!Kg( !o(!_( W(![ s#r!:wpA p0a ̀>^V͛z2+~>8 +2Ͱ>w:2:_OͰ>wy2* :!g( !o(!_( W(s#r*:_onsole is serial device @ Default printer is parallel device serial deviceA S~ ͗ͫͻ:w*Kͮ2!ͲKͮ2O2 !/!BͲ>/<0ODD Super Bios v. 3.0 CP/M 3.0 installed Default cɯ BIOS Error on : T-, S-!P|G}2^!""!@""! ">G>> >d !`}! ! >>>z}D#cdfg!"()͆͂bͧݷb!B6NN!B!z<*"!"z:{*:w:w**: ͯ~w#w#6##-a * ͯ~?G++Np# |mͥZo!o#~*ͥ&&ղ&>͋͹d-j6͚>͙Fb-Ծw ~<q*>=)ү_|:0ʠêͺ:<­‡Hq:>~c!o#~^#VG#~#~!##N#F#^#V#~#fo~_*"}o|g">2{&&2{2|*͆D<8+}7*#}o|g:O*s#r#w!~w~@w6H2{&Óͥ:*:"R̀**ͥq̀*"z::2ͬ͌ͬ͌ͬ(}/_|/*W}o"6"!_ʍ:OsÙ*"ͥcͬ͌ôͬ͌í͔ͥ͡ҷ`-Ծ}͔Pͬ yá>O0Copyright (C) 1982, Digital Research654321 BIOS3 SPR E500 1100 BDOS3 SPR C600 1F00 49K TPA $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$B!I@ !$  $I$ UUUH  ~#fo{£!~2!!~#foͱC"C$C&:K2)i`z n&* &)~#fo* &)~#fo~#fo2!2(R? ? @, 1+ =*!^#V#{n++~2!y2 +V+^ͱ cy2 i&)w`6!4~'w$6!4?@/ _@Q  M? @  ͜2 \!!wCRT SERLPTPARLPTs{1h!4~<6!4~'w`6!4~' [!!{<2~Q(x(OQz>x8( *|>>x >ɇyx>/s{1h*|͸(x2!"(<,!Ͳ Ý BIOS Err on A: No CCP.CƐ'@'O!Ͳ: AO !Ͳ*"!Ͳ*$2KÞwwwwwwwZwwz{{M ~<Œw:ҧ* ~§2&@t͖ͬ:z<ô~?̀~?ͥ *>͆yݯ2zp##q:!߯2!"R|:2ͥ:N>2<2͡|!w:>2*6s͙ͤ|͔>N Ä:G*`~!x_<_*y<:/G~##~? @F6##N66*Lͪ͝!~+6:0'"!~6*>=)X!f_CÀ*}<~*~{ͧݷ:!f͐*~wĦɯ2*#~2~w!"2=2*~2=22̀:*wͳ6ȇG~o>_yW#x#W{s+p+qr#r#r͋S"͙>2z4 !!q#p#w2wW*_҆-!s:zG~G!~*!!~~#~O~#G~.|! w:cʇ̈́w!x?w! ~ʽw-llqOý.w#w͂×̈́> !~#FD>!"**[+"**K!z~<:w ##>߾w*>ww:*#*s#r*:!:G~#<*#~!d!ͼʷ!ͼ&!~6̀!"2*:o$*~ 6~w w**{#z'r+s{ozg**|g=v** ʄ ʏѾ>22ͦ#ШG |*ġ:*w**=ҵ*> )ý:O!ͼ*:Oi}Á ~|* *! ~2~+-O~2>2:2 :w:P4~:wr##rp# b |g}oj* *͂ :ʘn` ~#fob2O͊"}:O*"2":O:G2!w*~zWw+ z#~*!*|y#*Ͱ*DM"*s#r*s#r#pyoxg[DM*0MD"!*MD$:Oi!N: iG>O: ʀϷwp ^#Vͦ:ü!"(COPR. '82 DRI 151282^ɠdj̎̔̚g"y27!":2:=7!~7ƹ#*{2!"z"9"1!dy3\K!n҂b&&!R_^#V* !bb  :ͷG:xͨ›:ͷͨ: !;6 :ȯ<!G:o:O*7*/*"*"[<:g:!,*}D!~6 !S͌rOͨ͠bxȷa{ҏ_p# ’ ʙ ʙ:A2'!!"!9"1!>%:2ɷ5:!=g?͙s! ! ?+> ws  X*]w#6?#] .,:;[]=<>|!eȾʃ45#l!*^#V#^#Vw# ͒͒ ͒ ͙͒:sAR:!jx!w4 ͚̚͡@O ͊DM͠}>""2:2* ::EsMO s#rͰ:(±y==±*!^W*=2wXկw#ʌͺRg[|OE w @~@w>2:>*͊:3:zͷ͞!>2Ob2@:G:O:=27)yy/W!:#ن?>F6:_/G:^:⢼_|OfKyp!VuWy/2&:Я2 :w++~=w4-Oҫ5:<4{͊>2:!3:zͷ͞Ͱ@R_@!">r#~?w#>r# =J̧ݷ 4 w͚ ~O ʙ:z<>w##~2_4~?ʈ͆x:<ʈʈ{ͥw ʠʡڠ׷¡w ~w 2>y&!"*>o+"!͗*!"s͙" wɯ2z ̈́ʹOFqy3Np͆ͯ:Z~MwS~¹o¹#¹ # ? -<*p:0!:®:Íͯ2*i"!s#r#p*N#F*^#V#F*:O}|y*Ͱ+*͹}|^#V#"##"##"###"#"##"! *!*|!6J67*w#w*w#w#w>2'qί2*O͂yڍÍ>2a."z:2:<:^^d{_zW{_zW )4#4#4# w#Jo ͠# CP/M Error On : $Disk I/O$Invalid Drive$Read/Only File$Read/Only Disk$File Exists$? in Filename$Í͛ɷS69MD:!: 2ͯͰ2z>z<*"!z<~s^#V#N#FxN::ͷJ!2!5Jx4 J#wO͏:T~xTHp!" Iy<ʃ2:2*N#G2͹H  W W|:<ʈ:W:H2xy“:@ʕ ~#w>͙{͆ _++V* -Os++r!x>w~6:6~#+w#w+~~$ +*!>  #>? #ַ*~ w0" *y͐}0͋ ͚͙^2͋ l͋6>-͚͙ÇPY*{zBKyʢ â< yº! >~Gw#* #Dկ2x™# ԯ22zG?S͝>Gx™~™:ʙ2 հ##~[*$a*"͋ʄ*!~Ê͙>2Í s͝ͳLί2͚ ͔ͤ *' :O~Sy? x Ֆ- NG:<N4 ~*w::/GyO A +B 8y2:xOo&:W>OiE:5N/*"y2͚#X*i#6͆DM*6# x£*w**s#rL*6#6͝*"͔ͤ*|<Ě>!>> > w:͆DM*T] KKN:@͆*"N" :kNq N#Fyʀ*}|y‰5 6y͌Ҡ^I@O:=ʯ:Iy I I:µ  #I:!; I I I! O͠ >xw>ɯw% :7!>wɯ:= x :ͷr:G:=Ľ9xr:y!4 5~bb  :ͷG:xͨ›:ͷͨ: !;6 :ȯ<!G:o:O*7*/*"*"[<:g:!,*}D!~6 !S͌rOͨ͠bxȷa{ҏ_p# ’ ʙ ʙ:A2'!!"!9"1!>%:2ɷ5:!=g?͙s! ! ?+> ws  X*]w#6?#] .,:;[]=<>|!eȾʃ45#l!*^#V#^#Vw# ͒͒ ͒ ͙͒:sA>>>>?@/ _@Q  CRT SERLPTPARLPTs1x!4~<6!4~'w`6!4~'w`6!4~'w$6!4C5:5<:5[:6*_|>>x >ɇyx>/s1x*_|< 2`\!aw2p????<2: 0=O:'''' 0=x8>(x [_!a{<2_~Q(x(OQz>x8( Q,!'ͷ í BIOS Err on A: No CCP.COM fileCCP COMy!^(w 0<KK{<<ʽ! ~6 69BK! OSg$Nwy!"(9"f1f! Ҕ2! ~#foCOPYRIGHT (C) 1982, DIGITAL RESEARCH 151282^#Vɧ:=#=~> ͣ!mF~ g(Loڵ)'ݶ>pݶͣ1 rͣ1͉)ͣH>^Vcz2l~[Z:'''ݶ݆:::ݦ>0!mF!dzK >= , Drive Not Ready, Write Protected Disk !д[^#V:'' ͎ > ͎:ijg(!( O !1 O(!: ͎z(Q(ͷ !ͷ(> >2Ƴ!׳[:ݦG_(x!Ƴ (4>w:ij> xwGx> ͎  w !m> ͎ Q(!m>!д[s#r!:ijw8 Ͳ͓ 8)͓ H>^Vcz2l~[Z̓~˗##xK[~ :ų( {2ųywx>wͽy2ij*³ :ij!7g( !jo(!_( W(s#r*³:ij_ (g( o(s#r:ij!g( !o(!ڵ_( W(device serial deviceA S³F͢ _s͎ͽ̓:ijw*³+~>8 +2ijx>wͷ:ij2ij:ij_O{M2W!"hH< H! S%:P:%Q~:&Qw# x Ɛ'@'O!̯ͷ:AO !ޯͷ*!ͷ*2P11͊)>]|‚*Û*)>]²|žÛñ~O #ù>/<33O _ W{|***)>,|h&)))~@]~oP>W>wfͱ*À*2!"*"!!***),lwÒØl=otyÏåÄ} kƯʯ$:Àxͭ1x>Q>2Ã1Oj$|Ãà à Ãhlptxɼ|DHL$P3TBXQ\``od~$(,04ʻ8ٻ<@ $(%,40C4R8a<p  ˺ںqDD Super Bios v. 3.0 CP/M 3.0 installed Default console is serial device @ Default printer is parallel ""!@""! ">G>> >d !p}! ! >>>Kv2!ͷKv22 !! ͷ>/<0O2i`z n&*&)~#foø*&)~#fo~#fo22ɯ BIOS Error on : T-, S-!`|G}2^!1k !^#V#{6++~2y2+V+^Ͷ cy2i&) ~#fo{k!~2!~#foͶCCC:Pڗ>2#×:#<֪2#*=‡*":*}®:=::<>2*i^#V+ d!K*}@*)): K:) O "!w [O?WGzO:VxGyOGxwq*}}2~77ø~7"9:OG#Q{ozg# ""!2*%DM**ѵ+)) H~#+}#<:<ʲ<77:<ʢ=2(*f*(}DɯQ"(>QKQKQ>Q"%Q!*$K*"x!*!@$@hK\K:K ~#~ w*NK*NK^#V#N#F!x>QGQx3ڰbڼqҼo5p5"""*!yb! ~G*!NKկ2}!,"**NK6 :+OK2$^#V#N#FxNp:$p:Gjxj Y# A>QFQ  !m[K:l=2l *m:G:l=2l !д[^#Vɧ:=#=mo`?     )оmo`   Ypؼmo`     )YHmo)|:w:ʴ>2d:#Ϭ>29ଯ2~2#!   )xð*}*}"*x"xm*^#V* s#r**s#r*:奄Y4Y̓**~#ng* s#r ^#V랏a##)""xx!"""XC*~<Ϋ*":!:*}*"x"*"g*3:= :Oi :=H:Gi a6:G/O**W :T=ҍ aʚ~ª6*:X)!:T>qk֪!:6>X*{Q:_2{2Ē"͂"X~<ª#cdfg!"()*N!r)!N!)z<*)"!":X*:w:w#:w*2*}D2@ !ש)#w*~"Ҡ!Fw䠨Ҡ̓Ҡ:w̚":>夯2̓*~wć"̀!~$6:03i"!~6*e>=)Q!QX@˞ >2 ˞!!q#p#w2wW*e_3ҫ-!s:!xQ*:<œ. ʩ.ʩA܎rr##s܎<}rcN! ~态O>G~G!~G~o>_yG~.|°! w:ck[!x?[! ~ʤ͆[͗PPvqO-á=.:<ʰ! Vq##~_@wکͶ:WMںʛ>úͶ >TJ:!ʷ͞x!ǝw4 ϝPWޝP܎ÂՎÂ*!!~~#~O~#FsO s#r:(„y==„*!^W*y^#Vx7=2wͼկw#KWK*"J T͞*:["T] KKͦޔ*w"wͦ"w@ :ÔNɔ N#Fyؔ*}|h#ð*ͫ# 6RX*q6!"@**#":&2͒:È0:+Òy<_W`iͫDM*w ~bNpwޔDM*we ^#V#~2>â9͆>!"*y³*X*ÿ͂"*g*K!~<:wb##>w#wĐ> r!~#22Zw*q>ww:c *#*is#r*:!:)e:O!*c:Oͫ}@2æ ~á*g:o$*~K6?~wKw**i{#zir+s{O:w:Ғ4~:w?r##rp# ä |g}oì*g #G ¾1*q:*w***> r 2":O:G2!w*~zWw+ !z?#~*!* *G!O~2~m͗O~t>2?:2̓¡>2ͱԡߠ?~¾¾ʨƨ>w͙=2͜:wÚ~̓ʑpá!6NwͧBpͧȭÚgsr͐-͜ĐͤS)_ͤ̓~?w͐s-?F͜pN͆p# Þ͐*6!¿?~p*6 >2ͱݡԡߠͷw*oq͋"@6ȭ͚Xͤ͋͗wO~<: g~w#w#6##)͋@ * g~?G++!o#~>T}! 6**#K"G*~ xr͐-xą@˞7(͚Sʀw :<RHͥ:>~c!o#~E^#V)G#~#~!~ b k##N#F#^#V#~#fo~o2{2g*wޔʪҢÞ+}*#}o|g:O*s#r#w!~w/~@w//Hͥ*e>=)_g:0"ök*w)*c)-͐ͤÀk*s":;:r2͚Αù͚Αž͚}/_|/*eW}_*c"e}o|g"c>2{+SX:ڜq:ʺ!ʵ>2܎ͤ2ќO ̐DM͸}ޜ>r""2:2* :::29:>:>*ڈ>F6:_/G:ʧ:ڨ|OͤG:_O̐̐zW{›|:*}|BKN› zyG:!vq:vՎvMڂ?Ͷ >T͓Â!">Â:G:O:h=27ryy/W!:l=:<>w##~2 4~?ɚ¹:<ɚɚüޘAX2rK:w++~=wv4͗O5:2X!"*>o+"! *!b"ݕ": r#~?w#>r# L=J Lv wȭb܎?~O ͆ښ†wŒ~è# # x ͗w ٙڙٙڙw@ ~wb͐Úݓ!x>w~6:6~#+w#w+~;wɯ2KOFq-yl?Npg:ʓ~g͝DM*0MD"!*MD$:Oë!N: «G>O: ù*Đ :ڐn` ~#foͤ2O̐"}:O*"!s#r#p*kN#F*m^#V#F*:O}|y9*+"*}|yP#9**DM"*ks#r*ms#r#pyox*kw#w*mw#w#w>2'å2*OͶyڲò<*eͲ:0!::ò2*>*ͫ"4#4#4)7 #  w#*J|^#V#"i##"k##"m###"o#"q##"!s )*s!)*|!6~67rrorFile Exists? in Filenameòò>2a.":2:<:55;:2ɯ22{_zW{_zW )7CP/M Error On : Disk I/OInvalid DriveRead/Only FileRead/Only DiskPassword E—>2—͇ͱ* «>2͙wBp+Ҥ:w͚AP{ 2W>O2ø͐R*e):r͚Αc2ZT͐-ژ3͗@YsY̓YסYͅ:ߠAsҤ:@Ҥ@Ҥ$͚̓Aؑ=:<~?¯kã?~?ʾZT͐ڣ*>o"͒"!Ó:Oݕ"Ý͐6͚ ~2Asv@NN~v$̓W+vw̚v$̓rrͅ:rߠ>2+A@2r!Z2!"ög:2T͐-:ʹ>2<2ژ!w: >2*6ݕݘO~<w:*)@ u:G*g`~!x_<_@*oy<:/G?~##~? 6K@?F6##N6⡯2p##q:#*~w>2*p@! ~*"v@*w# ) 6#̡͙N#FxT]## #~ ȷ  *4# ' 4! *~^ ^33G# Pv:dv6 y( ȭˆʀHÈ2xą ):@ΘO~#w͚ʀôb_++V@* )͗Os++r~Gw#* #~$%+@*9>  #>? ;*~ w-xąH"0 *ĊHEʀ@~›:6¦w͚̋ȭÇPY*{zBKNyʺ Nú2: *~w *" ݕ2>ʄ@~k:(s~*9~Ês~ԡ~ͅ<G:<ޖ2x# W:<­:22G?>Grx~:2Ô##~*$*">2̀2kºʺ**iҺ@:O~햯2~WW:2Ôyʛ?ʔx ʔ |̷ǖÔN:r:/GyOOA +¬ ¢y2:x¹o&:W>OͫE:ڟ?N/*"y2ͦ>2 ݕwޔDM*w6# x *ow**ws#r̀*i6#6*}"w@*|<ď>!8>8> t>nͦv8 ~*own)"!z<~rs^#V#N#FxN:oʲ̀õ(# Þry< <<%zrͷr6r9rMDÌ:o!6!h: ʚnt2 r62>rz<*9ʌ^: ~x ):*:ŊŊ>*(+"(w++2+2+Ɇp؆!" >2+2*jx.#NzW::!2W!5=^x^z:m:*;#wO:͂^2¢ů͠ĉ:!ڽ*(~ׇ݇5WèՉ؆jׇM2ͨxΉ*(+w"(jͅ !%"(^-:*$P:<\:W:2xM s:<9>2:*9x~+q’x2:*?쁲[*@`^2K6meRq}Bwٴj^2! ;4f@RzKƬ;ͽ~ â:!~mU0wz@uB@+͵͸ja] mfݠ6ma`Q2XCp̃\Ub4f07 JYM"3i(2GV ew*a q='@DuO#?(W ;k+6 ~PV BP@2!~sǣ+t9erl[U;D +Wx z2AEwvlfuhٶI,V f`CMa 2YMWx!y@b+ó`@ @-U Uw[AF: c6B*OU > 0"[-Ke%ـlDp"[<-Ki%pm@D"[T-Kl%A@mD"[n-Kn%ЉmD"[-?帡`n@D$"[-Ks% {tX$@UaUzjH+{P@3k(3jK4K6`JYG&ml fհmIW, x@(dz¦.U _6J XKUw(A^Od`@F*K՛v#ץf@#sFI'U %Ja`ͼ` `@k+T$ dp#t f`C՛V]b3jH6'p0!!*WH|#+x[݀:a v@*&~2+o#"&!+6Mň:W:2x ͺ*(+"(w  :܈>2*2:*(:+w"(ͺ:G::+̜2 5*(~o#"(Mš*(~`Uoj*(~#"(Ñ!*~6s!+6:+‚xoڊ{2Ó#w:2.+:.2-!%"(2*!Œ"&!*~4:2-Ԃ:Gͳͨ^2+>2:2*N#G2 2GH)+6:2,:!- ͅ:,!ͅ+*(~L#Bxz:*:*(~ʓOr ͅ ͅ! O(Ì*(~2**}ʷ!#¶!""÷:_:*(#wΆxH!Œ)6"&:!Œ x5~y 5 6y(^ͅ@O:=7:ͅy ͅ:I ͅ:=e: zz#͂ͅ:! ͅ G:Ҏ>xʝʝw>ɯw̩z:»!>wɯ:=zxzz::G:=/ͽx:Āy!4 šn!6@G:x: P:<: P n6 t6! ^6 t6u:)<͠^!SPhhP8ͱ HFlh8` nx*l6ǀ3ll8 ~ `4fPp$#`?ٶ4u`Lͮ`eU8kFo&ePJܮwXڮVmfP DJ¯@ pic@Y FՀ3lh #~K6ƀHP&Y)AD24D) #: Id ynјY)AB@h(P&!r7Bi6L@r2L@3%0h(H @P( @P( @P( !Xf. rfi3A R G!`i3N`e9L'#  Cd l [ -"ڴ#+[p[@ ^Ȋ l9O/J7ps[F՛/xFV][^+vz@W ]+z@t"^+zEW Tz@W ^+z@W ^+z@W ^)jcv;cv;cv;cv;cv;cv;cv;cv;cv;cv8-Vx ͡LȆ?쁣@¶CVK'%dm]0p@" _2lR{6݁0Xw< M"0xʄGAD"!< "Ce6LgA!@r6а0 f a0 f f'/v{BH»@Y{La0`5;l:JfѰՐ^b1b+$Ó*"r*r"ÿ<:g:!͐*f}D! ~6t!rͷքO(^ƄƄƄ  :Function = File = !,!"h!9"f! ͉:2t™:!=Hgo:O*;*͂:A2=/::0! dگ61#d ڸïp#:w#6 !6:6 *#!)6.#)͂ O(BDOS > wM  2*7w#6?#7 .,:;[]=<>|!?]45#Ra{i_p# l s s l ls:¬MAg>:N ,:h : Rxf0V jo<- 'i0)d`@!M#%y`ݒ{JI;%%Ydn0ڄ-V<|fހfQfݠ6m]YmrXHk!W!*UC6(9``* º`+`1YbGV ^G< E`Y jV_0H05O#+v: s خSx:q$Of`R(Ԅ.- ͼ{>X0Y""f@VmjYVlUyBlڰ :0rP1nʲLJ5cAU %Ja`ͼ` `@k+T$ dp#t f`C՛V]b3jH6'p0!!*WH|#+x[݀:a v@1_ ÕCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321;Zx0NSun$Mon$Tue$Wed$Thu$Fri$Sat$::Enter today's date (MM/DD/YY): $Enter the time (HH:MM:SS): $Press any key to set time $Strike key to set time$ERROR: Requires CP/M3.$ERROR: Illegal time/date specification.$1_ 1_ ͓" * }! /* |! Hs1" 1X" :]C:]C* DM C  ͜o&" !]6m:] $ m:]S"͵.f  -=d >!e Җ. f -\! "{ *{ "} ! 6*} ~2 .*  -Ž͵.f   -§d >!e . f -! "{ *{ "} ! 6*} ~2 ͵͜o&" .* ## - )2m.  -*! 6 ̀ 2͵͜o&" .*  -ZI2ÂR͵1_ j͵v !_ q*_ &!a p+q*`  !c p+q*b    ͥ ͥ! q: <2 O ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returns physical=logical. SECTRN: LD L,C LD H,B LD A,D OR E RET Z EX DE,HL ADD HL,BC LD L,(HL) LD H,0 RET ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter header (XDPH). READ: LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-8 ADD HL,DE ; point to read routine address JP RW$COMMON ; use common code ; WRITE ; Write physical sector from currently selected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). WRITE: LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and doub*} : w! p+q* ~$7* : <2 O*} w* #" ! q: 0O! q: O8: O8! q* MF:! q* &! ͚ K8* &! ͚ M8! q* Mr/: ±: ¿! 6: <2 O*} ~2 : ͨ: 0 ! s+q! 6ÂG: Â: : H2 /Â: 0! wAÂͨ! : #~! HaÂ: ! s+q+q! : ʀÂͨ* M* ! s+q: 2 : * &) >; H: =: * ! ͚ ! s* ͜ " : ! q* &! ͚ ))))* &͜ } =2 : 2 .! 6;* & ~2 /* e2 /cNe2 : ! : HxÂ* &) : N_!m͹ ͒ * & N͏ * M* ͏_*{ #q#pO*{ w:;eO*{ w*{ ~: : :;e2 *{ 6-:;eO*{ w! s+q: ! ! 6N!m" : [!n"   h  +s#r! 4E! 6 >! һ: =2 ҝ! 6* &) : ͎ ! ҸÃ*{ ~2 *{  ~2 *{  ~2 *{ #^#V" +!͚ ! s@! 6: CPU bank for further execution. BNKSEL: LD (@CBNK),A ; remember current bank JP BANK? ; and go exit through users ; physical bank select routine XOFFLIST: DB -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero DB -1,-1,-1,-1,-1,-1,-1,-1 DSEG ; following resides in banked memory ; Disk I/O interface routines ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke login procedure for drive ; if this is first select. Return ; address of disk parameter header ; in SELDSK: LD A,C LD (@ADRV),A ; save drive select code LD L,C LD H,0 ADD HL,HL ; create index from drive code LD BC,@DTBL ADD HL,BC ; get pointer to dispatch table LD A,(HL) INC HL LD H,(HL) LD L,A ; point at disk descriptor OR H RET Z ; if no entry in table, no disk LD A,E AND 1 JP NZ,NOT$FIRST$SELECT ; examine login bit PUSH HL EX DE,HL ; put pointer in stack & LD HL,-2 ADD HL,DE LD A,(HL) LD (@RDRV),A ; get relative drivle it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-10 ADD HL,DE ; point to write routine address RW$COMMON: LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of routine POP DE ; recover address of table DEC DE DEC DE ; point to relative drive LD A,(DE) LD (@RDRV),A ; get relative drive code and post it INC DE INC DE ; point to DPH again JP (HL) ; leap to driver ; MULTIO ; Set multiple sector count. Saves passed count in ; @CNT MULTIO: LD (@CNT),A RET ; FLUSH ; BIOS deblocking buffer flush. Not implemented. FLUSH: XOR A RET ; return with no error ; error message components DRIVE$MSG: DB CR,LF,BELL,'BIOS Error on ',0 TRACK$MSG: DB ': T-',0 SECTOR$MSG: DB ', S-',0 ; disk communication data items @ADRV: DS 1 ; currently selected disk drive @RDRV: DS 1 ; controller relative disk dri>;! H ! 6~* &) : ͎  ! s+4: O! DM  * M͗* M͗* Mr * Ma* Ma* MF! p+q!" * "{  "} *{ ~° ͼ! 6: *{ ~~H ! 6*} ~2 * &*} " Â! 62.* DM -  ̀  ͥ! 6>! B * &  Nͥ: <2  ! r+s+p+q+q! 6: =! ڊ * &* * &*  ʀ >: <2 W >_ogDM!>))덑o|gҳ =¡ DM!>)) = O{ozgi`N#Fogo&og_{_z#W0i  ͍=; =”͍Lᯕo>gL,>#!u^#V#0}o|ge X x| y0ʃ GÏ y 6 >! һ: =2 ҝ! 6* &) : ͎ ! ҸÃ*{ ~2 *{  ~2 *{  ~2 *{ #^#V" +!͚ ! s@! 6: e LD HL,-6 ADD HL,DE ; find LOGIN addr LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of LOGIN routine CALL IPCHL ; call LOGIN POP HL ; recover DPH pointer NOT$FIRST$SELECT: RET ; HOME ; Home selected drive. Treated as SETTRK(0). HOME: LD BC,0 ; same as set track zero ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. SETTRK: LD (@TRK),BC RET ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further operations. SETSEC: LD (@SECT),BC RET ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @CBNK ; so that further disk operations take place ; in current bank. SETDMA: LD (@DMA),BC LD A,(@CBNK) ; default DMA bank is current bank ; fall through to set DMA bank ; SETBNK ; Set Disk Memory Bank. Saves bank number ; in @DBNK for future disk data ; transfers. SETBNK: LD (@DBNK),A RET 1bCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321NAMES~VALUES~HELP~CON:~CONIN:~CONOUT:~LST:~AUX:~AUXIN:~AUXOUT:~CONSOLE~KEYBOARD~PRINTER~AUXILIARY~AXI:~AXO: &+07?GPXbgkXON~NOXON~NULL~50 ~75 ~110~134~150~300~600~1200~1800~2400~3600~4800~7200~9600~19200 #'+/49>CHMRWCOLUMNS~LINES~PAGESIZE[]=, NONE 50 75 110 134 150 300 600 1200 1800 2400 3600 4800 7200 9600 19200"$*&("*&(INPUT $OUTPUT $SOFT-BAUD$SERIAL $XON-XOFF $Error at the '^'; $Error at end of line; $Invalid number$End of line expected$Invalid delimiter$Invalid option$Baud rate can not be set for this device$Invalid physical device$Physical device does not have input capability$Physical device does not have output capability$Physical device does not have input/output capability$A NULL device can not be assigned to CONIN$Ambiguous assignments to a NULL device are not allowed$Physical Devices: $I=Input,O=Output,S=Serial,X=Xon-Xoff $ G XG XG +XG aXG XG    ( !8q!06:8!0{ *3NH*3#"3!04\ !06:8!0ں *5}§ !76^Hì  H*5#"5!04ƒ !;s+p+q!"<!;>w *;M!<+s#r*<9+s#r!>q!"@}2?>!?3*?&m ~,*@DM*?; "@!?4*>M*@!Bq!C6>!Cp*B&))) *C& NH!C4H!Dq*D&)))  ~2FO>ҕ!F6!E6>!E*F&Ͳ *E& NH!E4š!Gq!I6*G&)))  ~2H2HIH!I4:H2HOH!I4:H2H'SH!I4:H2H>XH!I4:IR H!I4> XX:e2J(r!J6(*J&!͈!Ls+6!J6*K&))) ~  *KM? H*KMq H*KMX!K4+~!L Å!J4Ê!Qp+q:e2c(!c6(:c _!͈!es!c6>!c/*P)"P*c&S w!c4 !c6*c&))) ~X:cQX!c44:c2f!R6!d6+6>!c*c&S ~:f!cҝX%X !R6*cM? H!d4:e!d6 DX!c4k:b!R6OX:RTX `X"Ͱ  *M !q*&)))  ~2*&)))  ~2 PX*M? cX*Mq vX!6>!:2¸*&ͫ DMX !6>!ڵ H:<2:X !6>! H:<2:<2m!p+q::H!6$!6*DMn2:< :J*M:\*M#a !6!6:€!"b"}Ï!"}+"b+~2dZ ::H:H!6!6::H:}+DMS@::S @:7:/4 @sS!p+q*~ *~ Hk*#"G*~w>>_ogDM!>))덑o|gҡ =^#V))) DM!>)) =¹_og^#V) _{ozgo&og_{_z#W $ Bad Logical Device Assignment; $Physical Device Does Not Exist$ $File$Null Device$Current Assignments: $CONIN: = $CONOUT: = $AUXIN: = $AUXOUT: = $LST: = $Console width set to $ columns Console page set to $ lines $CONIN: = $CONOUT: = $AUXIN: = $AUXOUT: = $CONIN: = $CONOUT: = $AUXIN: = $AUXOUT: = $LST: = $Physical Device: $Baud Rate: $Characteristics: $PARALLEL$Requires CP/M 3.0$Device Reassignment Not Supported$Enter new assignment or hit RETURN $1b1b͏}0͏|HX "g:>gH|!"}Z :: H:H|b>g–X͘2e͘2f.x*gDM -²A/;SX }h2i !~6 *i& 6~A/!l6:i!l5*l&~ Nͬ *l&~ w:l<2l :i2dbv!q*&! p+q* ! s+p+q* : w#6*  * #" N#Fy ! q: 2!61!q:2!61!s+q:2!6*&"1!r+s+q:2!6*"gxX*gDM$Ͱ"gX*gDM&Ͱ"gX*gDM(Ͱ"gX*gDM*Ͱ"gX*gDM !jp+q>!Ҁ>m !k6:=!kڹ*k&*i*k&m w!k4!k6*k&))) ~ !l6>!l *l&m *k&))) *l& !l4:k!k4>>þ>!sq*s&)))  ~2u!  ~2v!6!6::HHUZ :… :’ :°:u*s&)))  w::u*s&)))  w>!2:2:u2t2t *s&)))  :w.x*g -*s&" "wE.x*g -=S!{s+p+q>!{_ !"|!~6:{!~ڵ*y~0*y>9Hҏ !|ͧ*y~0_"|*y#"y:~<2~j>!| *|}!q*&!d͈!s^!dͲ:!s^! ͈!sn&ͫ:!s>!":0OH>!>#H?:0OH:0OH!6!6::HhZ :… ::ʝ hZ :}+DM*I=2*:: hZ :}+DM*~:H!6$!6*DMn2:< :J*M:\*M#a !6!6:€!"b"}Ï!"}+"b+~2dZ ::H:H!6!6::H:}+DMS@::S @:7:/4 @sS!p+q*~ *~ Hk*#"G*~w>>_ogDM!>))덑o|gҡ =^#V))) DM!>)) =¹_og^#V) _{ozgo&og_{_z#W#s#r1!q:22!q!6*& > >*& :R :!4, !r+s+p+q+p+q͐ !#6 *~ *~2#* M# 2!'6:· :'ڪ ú * M# 2Õ v :24 :22&*~2$!'6*~2# *~ P *N! ** =2%!&D !'6!6:&!A :': !4# G *64 *:$w:}{+s#r͐ :z *}#"} !6:#2(O* ~2*&*: !(4*:(w*&*: ¿ *(&*~2Ñ *6*}~2 ̀ :2!!6*}#~2 !!4N* : !'6$ *!&*: $ !'6!4N*} ~2 *&*}~2 * M# 2:>!H} !4N*} ~2 * M# 2L :2}{#+s#r*}N# 2!« *}#"}Ð !)q:)a :){ :) :) H H!-s+q+p+q:-=2- **:,w**#"* !.q!76*b"3"5:e( !e6(*d&*e&͈!1s*d&͊!2s:.:.Ha *}+"}p :}++s#r !/6:1!/ږ *3"5*eMS !/4x *2MS :7ҭ Xó /X:e?Ҿ *.M!1 ^#VFXG UXG jXG |XG XG XI=2*S͘2e͘2f X:e!g:"O!C ^#VXUU$XUU/XUU:XUUEXU "+.7:*MͰ"*DM :2::Hқ*MS:::H:H: HI : !6!6UZ :O! ~2:J:- G:"= G*M!6#6>!p*&m 6:<2R:/:}+DMn2:— *&m 6:±*M#::H:*}~HH!6:*}~,H*}#"}:/UZ p::Hd*&)))  >\" $ a ::Hҩ*&)))  >¡& ( æ :":&H*&)))  > *M *&)))  >16OCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321ERROR: Illegal Option or Modifier. $File Spec Limit is $ERROR: Illegal Global/Local Drive Spec Mixing. $Requires CP/M 3 $ERROR: Options not grouped together. $ERROR: Illegal command tail. $No File $1616|27}27:70:7H҂0uÅl92888,T28!868͗6:8:80u:8@I #0uä9 ͉!8͎28*8M)*8"8!"88͎28!86>8͟6:8HҌ!\6?\͢28!"8:8n*8#"8Ͳ28V*8DM!*8) !ͭ6Ҍ!86!86!"8:8*88*886>~6:8:8/!8H͎ !86!96:8͌$e.8͎28×*8"8:o9/:8/HB0uv o&!8q*8& !8q:828!8681m!8q:80/>9!8/H!8r+s+q+p+q*8>w#6!"8}28:8!8!8:8O*8 N~>*8!8:8O*8 ~0_*8C66+ste5, nxtchar = $ state4, char = $ state3, char = $ state2, char = $ state1, char = $ startstate, char = $!8p+q!86*8&*8~ ~ HҞ !84y :8!8q:8[:8]H:8(H:8)H:8=H:8,H:8H >>!8p+q!86*8#DMn 28O>G*8~!8*8&*86 *8& *8"8>!8Ҷ:8=O*8 N͢ :8!8O*8 N͢ HҶ*8+"8*8~<:8!8=Oo:8!8O*8 DM*8 -*8&*8~"!86:8<28L:8=O*8 ~ #:8=O*8 6!8p+q!86*8&*8~ʇ*8&*8~a/*8&*8>z/H}*8&*8~ *8&*8w:8<28/!8q:80/>9!8/H!8q:8A/>Z!8/H:8<28O*8 ~28*8& *8~28!8q*8 ͭ6:8<28O*8 H:8(H+:8($:8<28͸//:8EF  *8M0:8a *8 6*8/q#p>:8(v:8<28͸a*8 :8wO>ҋ>ͳ28ҙ͛>:8@»!86͸X  *8M0:8:8)>:8(:8<28͸/:8[͸Cͳ28͛>!8p+q*8"8*8##^#V"8*8 ^#V"8!86!86͸!86 *8 6*8 6*8 ~^*8ͭ6t͜28*8/ͭ6Š/28*8Cͭ6 C28*8Mͭ6¶M28*8 ͭ6 28*8ͭ628!86:8/*8 6*8##ͭ6*8##:86*8##q#p!8p+q*8"8*8##N#F*8##N#F*8##q#p$*8q#p Scanning Directory... $Out of Memory $Not Enough Memory $ !8p+q*8͙͐28u! 9r+s+p+q+q! 96:9=! 9$* 9&* 9>* 9&* 9>H~?H>! 94>*8>29!8f:8A>!"9*99*896>~6f>>8͟6:9H:8HҘ*98!96:8=!9 *9&C68 ~:8H *9&C68  ~:7/ *8# *9&C68#r!886+s#r#4¸>!8s+p+q:85*8>X6+s#rL*8*8M!h6\6+s#r!8p+q!86:8!86>~6HҊ!8n6+s#r#4X:8!8p+q*8N#FM28O>Ҫ>!"8>!8*8M!8d6+s#r*88͸6s#r:88͗6:8H9 :8**8#~A!86!*8#~D*8##~IH9!76!*8#~D*8##~AHc!86!86!*8#~Eu!76!*8#~F«*8##~F’!86è*8##~U¥!86è? !*8#~G:8*8##~028*8##~0o&<6*8 ~0_!8s:8/>!8/H*88? !*8#~M*!86!*8#~Ny*8 ~XI!76v*8 ~P^!86v*8 ~Ss!86v? !*8#~R*8##~OHҞ!76!*8#~R*8##~WH!76!*8#~S *8##~Y!76 *8##~I!86 *8##~O!86 ? !*8#~X!76!? 86 *8#~Lz8:8 t*8#*8M8͖n>8͟6e? 8q? w? 6 *8#~Up 8:8:7 Hҥ? :88͗6Hm *8#~A*8##~LH!"8d :8 :8H:8w!8q!86*8M͠/:8$H*:8*8M͠*8M͈H:8_H:8$H:8!8/Hy*8M͸:8<28**8M͠*8M͈H:8_H:8$HҴ͸:8<28y*8 6*8 :8w:8!8q*8M͠*8M͈H:8*H:8?H:8_H:8$H!8q:8!8w*8M!8:8HҲ:8*¥:828*8&"8͸*8Me:8<28͸M!8:8z*8!8s>!86!8:8+ښ?:8<28*8!8sì*8M͸>!86> !8*8&*86 :8<28º:8::8A/>P!8/H :8A*8M͠:8$H:8_H:8*H:8?H/^*8~^>/k>:8.“͸*8Mғ!86/ғ>*8 6 *8 6@>!8q*8M͈/ҹ>*8M͈*8 :8/H:8H*8M͸*8 ~<*8 wù:8H:8DH:8BHM*8 ~!8J*8M͸*8 ~<*8 wM>*8 6 >!8q:8\h>͸:8\:8H*8 ~ Hҭ*8M͸*8 ~<*8 wk:8\:8H͸í:8\>*8 6͸>:828͵>:8=28͸!  :7/!94:7!96!96> !9J*9&*8>!9w!94(:8!9wwO!9 "9O!9 ^#V"8!96>8͟6:9/H*8*8> *8#*8#HҼ!96*8 "9*8 ^#V"8t>8͟6>>*8~!ʡ/ҡ*8#DM!"99͢6>89͒6>*9"9"8*8#"8. *8#*8# -B*8>*8w *8 >w#6*8 w#6*8 w#6*8 w*8 w#6*8 w#6*9*8s#r:9#*8> *8~!  *8 ;2*9 9͗6́6> 9͗6+s#r. *9*9DM -*8 *9s#r74*8>147>. *8#*8# -F *8 *8 ~*8 w!96!96K2>~6~!96!96>!9Ý:9!9w҃*9&*8n&"9:9*9& *8~9W6+s#r>9͟6:9<29Ï>!9ҍ *8 ;2<_*9&C6*8 >;2H͈6<0 *8 *9&*9&C66*8 >;2H͈6 *8 q#p*8 *9&*9&C66*8 q#pR08͗6"9!96>!9 *9&9) >w#6:9<29¥ *"9y2!86!"8"8!\6?\͢29!"9*9~!!!96a :8 *8#~0287 *8#~0o&<6*8##~0_!8s:8/>!8/H[ *88^ ? d ? 8å6 *8#~D*8##~R~IHH3 8:8ª ? :88͗6H0 *8#~A*8##~LH !"8B86+s#r' *8#~A/>P/H$ *8#~A_8' ? 8ê 6 ? !860u:8  . *8# *8&C68  -o  *8&C68  ~  *8&C68  ~ H  *8&C68  6  *8&C68  6*8~  *8&C68 6 *8~= *8&C68 Hq:8<282 0 d[108:7!7/M !76#6:7!7/a !76+6:7!7| :8y !86Ä !76+6:8·  *8&C68  6 *8&C68 6!86>8͟6 !86:8=!8  *8&C68 ~  *8&C68 :8w *8&C68 ^8:8<28 t !86:8=!8t  *8&C68 ~ *8&C68 :8Hj 0u:8<28# >8͟6Š K_8>0!7 :8/ 8͗6 To&"8>8͟6 !"8 state8, char = $ state7, char = $ state6, char = $ sta86 * Y/* ͦ/*>>:8,:8)H:8H]*8 6>v*8 >*8 w>> O>Ұ*8 >*8 w*8 > ҭ*8 6 >>:8,:8)H:8H*8 6>*8 >*8 w>>:8*8q#p>*8 6*8##q#p>:8?  *8M0:8K:8]‘͸:8,:8(H:8)H~͛:8Š/ð:8 :8,HҰ͸CC:8  *8M0:8:8 :8,H͸ :8)͸)>:8   *8M0:8<*8 q#p *8 6>-28Jʹ>:8c  *8M0:8(r͸ :8Ҏ*8Mq#p *8 6>-28Ҝ)>;:8Ҷ  *8M0:83:8!9w͸!9~,~ HC3!9~]0:8(:8,H:8)H͛3:8+3/3!9~=?M3>3:8Y"  *8M0:8u*8Cq#p *8 6>*8 :8wO>Ҋ>y28Ҙ͟>:8ұ4  *8M0:8):8H:8͸:8=28ñ:8[͸C:8 :8,  !!96:9ʈ!:9o&"8:9?!*9&<6a "9*8~|!*8#"8*8~ f! *8 ~28|!'|!/|!l0ͻͲ29 !!:"8;͗6Ҥ!|0u Sort Stack Overflow $Not Enough Memory for Sort $ Sorting Directory... $! 9p+q*9))))*9)) *9) *9 *8 !$9r+s+p+q!%96> !%9m"*%9&*!9>2&9*%9&*#9>2'9Hf"!'9:&9!%94-">!-9r+s+p+q!l96**9"49*,9"69:l9 u$*l9&))49 ^#V"*9  ^#V",9!l95,9*9͒6r$**9".9*,9"09*,9**9r6)*(9N#F!"909.9͒6#*.9)*(9N#F!"8*8DM*9"5#*.9#".9*.9)*(9N#F!"8 #*09)*(9N#F!"8*9DM*8"s#*09+"09*09)*(9N#F!"8G#09.9͒6#*.9)*(9^#V"29*09)*(9*.9)*(9N#Fq#p*09)*(9*29s#r*.9#".9>!09ͪ6#*09+"09"*909͒6.9,9͒6́62$,9.9͒6)$!l94n&))49 *.9s#r*l9&))  *,9s#r*09",9o$09*9͒6i$!l94n&))49 **9s#r*l9&))  *09s#r*.9"*9÷"Ë":l9ʆ$!0Ë$!96*9"(9>8͟6Ң$(99͒6r6!8ͭ6$!0!"m9*8+!m9ͭ6$*m9)*(9*m9s#r*m9"m9$!0*8+m),' %00 %0,'3%003%0,'*9"9*t9#"t9H-,'*9#"9U-,'*9#"9[-0͎'*p9#"p9_'ͻ6+u,!96!"t998͒6d.*8 >ͪ6!7>͟6!7H*8#DM͂*H^.*9*86>~6A.:8>t9͟6HA.,'m),' %0[%0:8@.%0.%0,'3%0r%0,'*9"9*t9#"t9,'*9#"9͎'͟(*p9#"p9ͻ_'6+}-!"9"p9"x9}2z9o&"{92}9o&"~9298͗6"8*9 "9!"96+>!8ҵ.>&0u*8M!D/ ^#V͵*J/+J/:8&/:8:8@:8 H:8HH!9/r-#/]&0uA/:8!9>/r-A/j,J/...:8>!p9ͪ6H0*98͢6!8҆/ 0 0Ì/,','&0x91k0&0 {91&0*p9[1&0~91&0:8AO0:00*8[1/0K2#[1>p9͟6,0:8&0,'m)&0ͻ;0!o96:8;0,'!9r+s+p+q*9^#V"9*995s#r!9ͭ6n0*9##4!9r+s+p+q*9^#V*9DM<0*9##*9##~`iw!9p+q*9##~29*9##~w*9n6+s#r*9#:9w!9q*9&!9p+q*9  0 0 _og_ogDM!>))덑o|g26 = 6^#V))) DM!>))R6 =J6_og^#V) h6^#V|g}o r6_{ozgO{ozgi`N#Fogo&og_{_z#Wi`N#Fog\p"!96 Name Bytes Recs Attributes $------------ ------ ------ ------------$ Prot Update $ ------ -------------- --------------$ Access $ Create $ Press RETURN to Continue $Sys$Dir$RO$RW$Arcv $ $Read $Write $Delete$None $ $Directory For Drive $ User $: $k$ERROR: Illegal Format Value. $ERROR: Date and Time Stamping Inactive. $Total Bytes = $ Total Records = $ Files Found = $ Total 1k Blocks = $ Used/Max Dir Entries For Drive $No File $'2v9:v9 ''2v9':v9+'u:8W'*8+:w9͈6W'%0*9#"9 '!w960!w94*8 ^#Vx9<0*8 {9o0 *8 ^#V~9<0*8#DM10*8 N#F'[1k00*8 DM10 *8 ~'%0'%00 *8 ~'%0(%00:8+( *8 ~"(%0((%0Þ( *8 ~@(A0C(0*8#~U(10X(0*8##~k(20n(0*8 ~҃(30Æ(0*8 ~қ(40Þ(0*8 >ͪ6l)0*8 ^#V"9 >(%0 )*9 >@(%0 )*9 > )%0!9p+q!96>!9/1*9&*9>O0!941 0!96> !9Z1*9&*9>O0!9491!9s+p+q+p+q>9͟61*9*96!9s*96"9PY! 6"9>~6!9#~Hһ101!96:90O0j1!9r+s+p+q*9##~2*9##N*9DM[1*9N#F'[1:2!969:9͟6+20*9&<6!9s 2*9N#F'[1!9q*9&*9~!9q*9&*9*9& *9N`ih6n&"9;2<o&"9;Zx0NSun$Mon$Tue$Wed$Thu$Fri$Sat$!9q:9<29O*9 :9w!9p+q*9~$3*9:9<29O*9 w*9#"92!9q:90O2!9q:9O3:9O3!9q*9M3:2!9q*9&! 6K3*9&! 6M3!9q*9MJ3/2!9s+q:929:9*9&2) >;͟6HҸ3:9=:9*9! 6!9s*96"9:9!9q*9&! 6))))*9&6 }!9s+q:9!9!96N!m"9:9*4!n"999͒67499͒6+s#r!944!96 >!9Ҋ4:9=29l4!96*9&2) :96!9ͭ6҇4R4*9 ~29*9 ~29*9 ~29*9#^#V"9+!6!9s4!96:9>;!9ͪ6H4!96M4*9&2) :969͢0 )&00*9 ~*9 ~H=)*9 DMͣ5C) &000*9~*9#~Hl)*9DMͣ5:8|) 0Æ):9چ),'&0:8AO0:0:7 ڶ)1&0*8& [1,'!"9!96!9p+q*p9*9&6>~6'**9*86>~6!t9ͭ6H*,'m),'*,'*9#"9:8AO0**09&0*9DM1ͻ*p9#"p9*t9#"t9!9s+q+q:9ր!9j*>:9ր!9*>>!9p+q*9 N*7M*7J* *9 N*7M*7J*H!\6?!96\͢29:95+:9o&"8> *8 ~H;2ᖟ/H,+',+*8#DM͂*,+*8#DM)Ͳ29*!96:9Ҭ+*9#"9*9)*(9N#F!"8*8:889͒6HҖ+*9#"9*9)*(9N#F!"8[+89͒6©+*9"8+*8"8*8:898͒6H+*8"8ö+:8+!96+!9698͒6i,*8 >ͪ6!7>͟6!7H*8#DM͂*Hc,_'*8#DM)*8 N#F'[1<&06++!96!"t998͒6q-*8 >ͪ6!7>͟6!7H*8#DM͂*Hk-*p9*9&6>~6X-*9*86>~6K-:8>t9͟6H>-,'6!9s+4*9~(5:9O!2 DM2 2*9Mo3*9Mo3*9MJ3 2*9M93*9M93*9~`5*9M3!9p+q!"9*9"9 "9*9~~Hҟ5͋4!96 5â5u!9p+q!96.*9DM9 -º59a5!96> !95*9& 9 N0:9<295i`N#Fog_og_ogDM!>))덑o|g26 = 6^#V))) DM!>))R6 =J6_og^#V) h6^#V|g}o r6_{ozgO{ozgi`N#Fogo&og_{_z#Wi`N#Fog\ DIRLBL yd'* !9"1>"#2#:Og}**Ip2~w2i#1#":RͶ :O~!ʫ:<2Ž:"2"x2*# O:ļ:<:G>O*# :<t tIw!/>!/>!*6 #:_#:*Y" Y" Y" >*Y"#####Y"##Y"Y"Yz2*Kg"ɯ22!"*DM6:O* 2~ ~ †:<~:2>2:<** "_?:<2>!/:<}:2* ~b W6 y2> # vwm>2>!/ N *~O²+—">2>!/*:< "~G # p *~w#  : *8*:*8yO:O*}O= ~ w#P^#V#ɷ{ozg |g}oh:<͉̉O<OBKBK$'-*!*DD  $$HD@" @@ $B $$H$H$HH$$! HD$D$D@AD HD$!A" tIw!/>!/>!*6 #:_#:*Y" Y" Y" "*Y"#####Y"##Y"Y"Yz2*Kg"ɯ22!"*DM6:O* 2~ ~ †:<~:2>2:<** "_?:<2>!/:<}:2* ~b W6 y2> # vwm>2>!/ N *~O²+—">2>!/*:< "~G # p *~w#  :1I"CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH1512826543218/82Invalid Filename$DIRECTORY FULL$DISK FULL$Creating Password$File not found$File not available$  ,.;=:<>_[]*? ERROR - $Password ? $Cannot Edit Wildcard Filename$Enter Output file: $FILE IS READ/ONLY$NEW FILE$-(Y/N)?$Insufficient memory$Enter Input file: $Output File Exists, Erase It$ BREAK "$" AT $END OF LINE$1I"1I"̈́""%*"%}0!#6%!"I" ͫ!+!#s͠!#s#r!I"!^ ͵ #I"!++s#r!#ͧ!+s#r!"#*#ͺ!"L#*I"% 6*I"+"K"ͫ!"M":] sr ͡ !#6\Mڀs:#Ҷ\S:h2y#!h6*"%|¶12!%¶!!%6!#6!+#:\:t#/H+#͍͋!%6 !"%*K""%!#6à1I"! %6#@1I"! %6?@1I"! %6>@1I"! %6F!"$%@! %6F!"$%1I"!w#6 * %M͟  :% :% H| Ã*%M͟ >$%!ʝ*$%DM !"$% 1I"!{#6! %6!z#6͂ ! %6E: $2%E͑  sð H͑  !s#6#~:+#2%:\2+#:%2\ *8*:*8yO:O*}O= ~ w#P^#V#ɷ{ozg |g}oh:<͉̉O<OBKBK$'-*!*^#V"DD  $$HD@" @@ $B $$H$H$HH$$! HD$D$D@AD HD$!A" ~:2>2:<** "_?:<2>!/:<}:2* ~b W6 y2> # vwm>2>!/ N *~O²+—">2>!/*:< "~G # p *~w#  :DUMP VERSION 3.0 DUMP.COM COPYRIGHT 1982, DIGITAL RESEARCH151282654321Ҋ ҏ>.Ï_ Ҧ0Ï7Ï͜Ü\2|::Iͺ>2 :2f>2>û>!6 #=!~a1{1 w##:Ƃ2*6 2fl:<2!G\:>2 *|ͫ}*ͫ>:Ï:> ͏> Ï> Ï:_:<2>2ͺ >Ï*}o|*!""ͮͷ͇*"͛~ͫ#*}#"%"*̀*}K|K*ͺ-m121=2#\:}mͺ2>o:  /\ͺ 1gn~ͻ͙D.:ܰg+":>2 CP/M 3 DUMP - Version 3.0$ ERROR: File Not Found $ Enter Password: $ Password Error$ ERROR: No Records Exist$ Press RETURN to continue $,#+#3\+#!t#6ð :%I`!#: $: %H2z#i!#6!"%}2%*%+% ~ fiW?:%<:%:%H:%H:%­ ͋:% :#!# :%^> :#2#O> w:#!#?!w#6!#6!w#6:#2#!#&:#2#:#2#:#!#< ,V*%+% ~ P !%6:%ƒ> *%% ~2%O͟ !%6:% *%+% ~ HҬ ͟ - *%Mo ^w:%@Ow:% :z#/H- : % :% !#4 :% :#O>!#w-:% :% /!%6  w4!%6!#6pi:%O- !#6:~#!z#] ð O͸ u\Kð :%RRP"m2 %Ғ!v#6:v#: %ڬ P"r"!\"6!p"6#6P"!v#6Y2%-!v#6P"Kð Q͸ +#ͺ:t#/!s# #+#3+#ͺsð :%-&͂ !%6:%#7ͻ͂ t!T!:%:Q!%6L=!t:%:t͂ !=!:%t*%#"%Ҁ!%6:%B¡!%>w!"%*K""%ͅð :%C²Ͳͅð :%DͲ͋ð :%K͋ð :%L͑ð :%P !%6w ve @TRK: DS 2 ; current track number @SECT: DS 2 ; current sector number @DMA: DS 2 ; current DMA address @CNT: DB 0 ; record count for multisector transfer @DBNK: DB 0 ; bank for DMA operations CSEG @CBNK: DB 0 ; bank for processor operations ; ; following DS fills out end of page to allow ; next module to start on page boundry ; ds 16 - (($-boot?) mod 16) endaddr:: END    ͎ð :%T ð :%U6 :%2}#ð :%V… f %%!DMt/͟ *K"DMt  :%2~#} !#6 !#6ð :% ± :%: %HҮ ͑ð :%Hҭ :%A !%6*%"%*K""%ͅ   !%6ͅê :%F M \ ê :%J¤ Mx: %2 %xҡ \: %=2%:%<2%! %f *%&$ ~2%-E *%"%* %M* %~ ! %: %%!"%!%6ͅ*%DM͘4 ê :%M: %H !%6>%! L:%<2%O!%$ Hqy :%2 %!%6*%#s#rê :%Nf Mc * %` ͭ/ @̀ !%6!"%͇ͅ!%6K"%!]   ê :%S¶ Mxҳ \: %2%%!DM͘! %:%Ұ *%&$ ~2%!%4-Ï t ê :%W ê :%Xu P"m2 %!#6 !u#6P"^:#  r `!u# ͓B !u#6 r"P"!"6#6!~"6!"6r":#B 5*%"%%%!o *%% N*%"%K >ê :%ZŸ ҏ ;  @Ҝ Ï ê :%ʪ ð ív!&%q:w# *&%&!'%q:'% !#4:'%  z# ͟ *͟ *!$DM: %&*%& ~I:%<2%O! ~> >! %ҡͭ_! %:%ڍ>%!ʈ*%+"%>ͷ!ˆ!%6:%<2%=O!%$ NP:z#Ұ; OP:{#!{#6:#!~#K"%!*͟ ͡! $6 ͟ !#6!#: $2{#* $&# 6 : $<2 $=O!# NP:#B*Oͤ2%LLOͤ2%!{%p+q!~%6! %6!#6.:% ʏ:%ʏ *z%*z%#  :% ž.Ð͹y!|%6͹>!|%ҽÓ͡.ê:%::|%Ó*z%#~A<*z%wO>Ó*z%#6 .:%.)!|%6!#6.͹)> !|% Ó͡. :%;v*z% !|%6.͹d>!|%[Ó͡.H*z%DM#Þ>!}%҅Ó:~%ڏÓ:~% ! %6>:|%<2|%O*z% :%w!~%6!}%6>!}%*}%& :%> !}%  >!}%4¾>:#' ͡! $6!{#6 +#M9!t#6:,# 6,#]E+#\#4#:q"wRP"qr>!q"6:q"<2q"=O! NP!h6!j6!|6:#ҩcͬ\;"#:#c*#}|Hͽ ͬ\;"#*#}|H:%02O"O> /!"%!))덑o|gҗ! =…!^#V) ¡!^#V|g}o «!_{ozgi`N#Fogo&og H !=! LIBX$$$$$$$LIBX$$$$$$$LIB$$$BAK!#6*'%M :#    !#55!(%q:(% :#O>H2)%yQ !(%6 !*%6:)%!*%n *(%M !*%4V !+%q:+% ~ >:+% :+% H:+% H!,%q*,%Mo ڻ ^+ :,%@2,%*,%M+  ͟  ͟ !.%p+q*-% !0%p+q */%DM !2%p+q *1%DM !4%p+q*3% !6%p+q*5%:! %6O!"$%@!8%p+q*7%!:%p+q*9%2#!<%p+q*;%2#!>%p+q*=%!@%p+q*?%!B%p+q*A%!#6# >>!D%p+q*C%!F%p+q*E%!K%r+s+p+q+q:G%=2G%+*H%*J% w*H%#"H%*J%#"J%!M%p+q###*L%gR !O%p+q*N%f!P%q*P%&-:u#Ҁ#^͵  !R%p+q*Q%DM s+#K͍:#ҹ#!T%p+qͬ*S%DM^!V%p+q*U%DMͺͬ*U%DM͑!X%p+q*W%DMͺͬ*W%2#!\%s+q+p+q:\%=2\%2*Y%:[%w*Y%#"Y%!`%r+s+p+q *]%*_%DM"͹!a%6:#!a%ڵ*N#*#DM\q2#ʤ>!#ґ͟*N#*#6:#2a%î*N#"N#!a%4`͹!"N#:s#>#N#!X*N#*#~2b%*N##"N#:b%:t#):s#͍*#}2#:t#C:e&;͍C:fC:d>!#6C!x#6:#f:t#X͍!s#6M #+#3!7#6+#:#…͟:y#ʞ:y#27#ͬ+#,!7#6!K#6*#"N#!"P#!"!$!"%>%!!"%*%+"%>>!"#$:%*%#"%*%"%!"%+"%$*%"%*K""%!"%!%6:%Ҭ%%!2%*%v!"%% ~ He*%"%0*%+"%>ͷ!2%:%ڕ!%6%%!+s#ré*#$+"#$:%ҩ*%"%):%*%"%*%+"%*%#"%*%#"%*!$#"!$*!$+"!$*%#"%*%#"%*%+"%% ~ *%+"%!%q:%Y%%!V:%S*%% ~2% E*%% :%wÄ%%!҄:%ҁ*%% *% wYͅ!%p+q%%!ʱÞ:%*%"%%%!!"%%%!"%*%"%%I"!%!*K""%*%*%"%%%! OQ2%3*%% :%w:% M!%q:}#d*%MP:%K"%!x*%% ~2%O:% –hͻ%K"!M"!ڼÿhÝ!%6!"%*%"%͚ͅh%%!!%6!>))덑o|gҗ! =…!^#V) ¡!^#V|g}o «!_{ozgi`N#Fogo&og H !=! LIBX$$$$$$$LIBX$$$$$$$LIB$$$BAK)!R#+##R#3R#ͺ:#)>>!P#ͧ!!d%s{@*P#!e%s!"P#!c%6:d%!c%*P#*L#DM+#́ʵ]>P#!ʦ*P#:e%ͷ!*P#*L#DM*L#*P#:e%ͷ!"P#$*P#"P#!c%4S!"P#!f%q#P#!,*P#*L#:f%w*P##"P#!g%q:#,Q:~"2":"2"r"́'$$!#6*#&" :g%w!#4:#2h%>!h%Y!h%4Dr"K!i%6 :i%=2i%ʐ*i%&r" *i%&P" ʍ>e>:"2~"r":"2"Qr"q:"2"!#6>!#*#&" ~!#4¾*P#},:s#\K+#K:#͟:x#+:5#25#ͬ+#:t#G\]#l3\+#]#;#3+#!k%p+q*j%*j%DM!l%q: %ʄ*l%M͟ !m%q:m%a/>z!m%/H!n%q*n%M͌ҹ:n%_:n%  # !o%6>!o%I Oͤ2p% *o%&# :p%w:p% I:p%:p%7:o%$:o%=2o%O!# 6 :p%Bs!o%4ͭ2p%!q%q:q%a!q%6:|#p*q%Mͤ:q%!s%p+q!'"v%!u%6>v%!*r%*v%~!{2t%*r%̀!"r%PY! ~!"v%:t%!u%!u%6:t%0O͟  ͟ Å!y%p+q:~#*x%DMt:͟  ͟ :ͻ:s#)2%)*%M%%!=*%% :%w:% VL2%:% :z#/HH/Wҥ:% ”!%6 ͦ!%6 :%Ÿͦx* %&$ :%w: %<2 %d!%s+q*%"%!%6:%/%K"!H8*%#"%"%:%2%*%&$ *%% !%:%2%/H5!%4*%#"%:%I*%+"%ͅ:%! %6x: %2 %* %l!%p+q*%DMM2%: %ڍ! %6O@ *% ~ :#/Hҷ *%#*%#~ *%##:%*#$*!$DM!z#6:%!"#$*%"%*%"%*%+% ~2% %:#" ,*#$#"#$*%"%%%!v:% Z*#$#"#$ͭZ*%% ~2%O͟ *%"%2*!%&"%*%"%*%"%̀w͑:%2%!%6w:%2%K"%!>%!H͇!%6>!%ͭ@>!!%4!%6!"%ͻ, M"%!& )  !%6 -!%6 -:#>%!H] @!|#6*%M͌2%*%MP2%:%/!}#+w!|#6L2%^ !%q!%:%:#H: %H!%q*%M͑  *%M V ; Oͤ2% :%N à:%Y > > 1CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321PASSWORD0CONFIRM []=,  *** Aborted by ^C ***$ Disk I/O $ Drive $Read Only$Currently Opened$Password Error$Password: $ $Not erased, $ ERROR: Missing Delimiter or$ Unrecognized Option $Near: $Requires CP/M 3.0 $Enter filename: $ $ERROR: Invalid file name $Confirm delete all user files (Y/N)?$No File $ (Y/N)? $ *** Aborted by ^C ***$11͢}0͢|HSb4 ڑ!16fb(r2:<<2}wb!6 *}& 6!u6:}!uڑ*u& ~aڊ*u& ~}Ҋ*u& ~ w!u4U!"+!\"-+5 "{{͔zb>{͜*{~ *{#"{*{#"HR :\Oy<2\2y.3l -:1/Ҁ!u6:u<2uO!\ ~??(> !uҀ:2/Ҁb@2x:xy:xYH/} .l\ -ˆͫlͻ2z:zµb:z6:z`O! "/E";G"=I"?"A"C"E:p+q*s~ ~ H% *s#"s *s~1 >>!`i^#V#~#for0V y wÇ G:„ xA  a{k_  ~ ~r_ogi`N#Fogo&og_{_z#W0:n !m4# ͙2n!oq:1 :\A=OI:I I!v6> !v :v .I*v&*/NI!v4 bb*oM \͂ 2wQ :w$ *wM B :wB *wM͞ \͂ 2w:wQ *wM͞ !L6!J6:L:LH:LH Jt:J b.bLb:KH͜+"p!r6:K!r *pNI*p#"p!r4¹ :J !26:J !16\ !tMͺz/%ͺ!;p+q*;DM *y$}2;|2;:; F  :; T   :;x :;j $ :;x 4 !;q!;6*;&1 :/• >*;&1 :;© :;!;4 !;r+s+p+q+p+q !;6. *;~ *;~2;*;My 2$!;6:$ L :;  *;My 2$ ! . :;2$͌ :;2$2;*;~2;!;6*;~2;. *;~L ç *;N! *;*; =2;!;› !;6!;6:;!;ژ L :;ڑ 6 !;4z Þ 6 *;6͌ *;:;w:$$͂#+s#r :$ *$#"$ :L2$:;2;O*; ~2;*;&*;:/( !;4*;:;w*;&*;:; *;&*;~2; *;6*$~2; :;2;!;6*$#~2;!;4N*; :0f !;6| *;&*;:;| !;6!;4N*$ ~2;*;&*$~2;*;My 2$:$:$H:$H:$H !;4N*$ ~2;*;My 2$ä :;2$$͂##+s#r*$Ny 2$!L *$#"$ :$$#+";!;6:$!;P *;Nͤ*;#";!;41 !;p+qr*;DMͺ!;r+s+p+q*;DM͗ *;DM͗ *;~w*;*;~!;p+q*;>9Ұ *;~7w÷ *;~0w!;r+s+q+q*;:;~!;H IQ !;60!$6!;6*$#"$;1Ҷ*/:y³:\A=OI:I I!v6> !vW:v ?.I*v&*/NI:v<2v)b@2x I I:xƒb:xy:xYHҳ. */#DM] -¨ . */#DM] -  ͫ*;E*=G*?I*A*C*E!=lͪ-.*=l -%2zõv!q*&!p+q* !s+p+q*:w#6* *#"N#Fy  !p+q*! p+q*!"p+q*! -!'q:'2#!$6#1!*r+s+q:(2#!$6*)#s#r#1m!Nq!O6*O& X>*O& :Nl:O!O4F!Ur+s+p+q+p+qͪ !\6*T~*T~2\*YM=2L!`6:L :`*YM=2LïÐ:V2KN :V2K2_*T~2]!`6*T~2\*T~j*TN! *R*R =2^!_^!`6!W6:_!W[ :`T!W4=a*T6N *T:]w:KH͂+s#rͪ :Lʔ*H#"HÙ!L6:\2aO*R ~2X*X&*P:!a4*T:aw*X&*P:Y*a&*R~2Xë*T6*H~2Y͚:X2Z1n$'CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321!`i^#V#~#foͽ{¡y#wG:xA##6?)@w){#{s333333.;;33,;;#wD{_#6 sO O ڹ.:;=,/[]<>a{Ҷ_#  ý Copyright (c) 1982, Digital Research 11/02/82 @ @NULL0LOADER0SCB []=, :;<>%\|"()/#!@&+-*? COMHEXRSX1###~ERROR: FILE: File not found.No directory space.Invalid file name.First submitted file must be a COM file.Duplicate input RSX...Duplicate RSX in header. Replacing old by new.Invalid RSX type.No more RSX files to be used.Error on copy.There are not enough available RSX slots.Disk read.Disk write.Total file size exceeds 64K.COM file found and NULL option.No header or RSXs to strip.+ͱ :;" rͺ :;2 !%6? :;? !%6:$H :$Q :$ˆ :;} rͺ;+ͱ È aͧ !%6:$‘ :$š :$£ *$#";*;Ny 2$ *$DM*;i *:&: w*$##"$ *$;i *:&: w*;"$!:4*$Ny 2$\Q *$#"$*$Ny 2$:$1*$#"$*$Ny 2$!L:$IY!M:$YwQ *$#"$*$Ny 2$!N*$#"$9*$0͸ *$#";*;Ny 2$!L:$£!M:$°6*$0͸ F*;0͸ *$DM*;i *:&v: w*$##"$2*$;i *:&v: w*;#"$Q !;p+q*;DM*O>0*;"( !;p+q*;DM:O>R*;"( !;p+q*;DMJ2$>!$y*;"( *( >Š*(DMͻO>ҟ*("(!;p+q*$"%*;"%*$"'%̀"$$#*'"( !;q!;6>!;*;&)))=% *;& *;& w!;4!;6 >!;F:;2;*;&; 6*;& 6!;4!;6> !;ڍ:;2;*;&% *;&; w*;&*(*;& w!;4K;ͫ2$>!$ҥ*'"(!;p+q!;6 >!!;*;&*;6!;4±! *Z&*P:Y> !`6!V4N*H ~2Y*V&*H~2Y*YM=2L:L>!LHҗ !V4N*H ~2Y*YM=2Lf :V2KH͂#+s#r*HN=2L! *H#"Hê ͙ b I I!es+q+p+q:e=2e *b:dw*b#"b !fq I:f) b:f7 b:f:fHU b:fc b:fq b:fҁ !hp+q:2Қ *g >w3ͫ*g:\w*gDM"i*g >w*i} *i|2k:kH *kM :k>Y2la :l{ :l :lb3 !m6>!mڗ 2n D *m&3 :nw:n O × :nZ  :n€ :mm  :m=2mO!3 6 , :n !m4# ͙2n!oq:1 :\A=OI:I I!v6> !v :v .I*v&*/NI!v4 bb*oM \͂ 2wQ :w$ *wM B :wB *wM͞ \͂ 2w:wQ *wM͞ !L6!J6:L:LH:LH Jt:J b.bLb:KH͜+"p!r6:K!r *pNI*p#"p!r4¹ :J !26:J !16\ !tInvalid FCB.Media change occurred.Disk I/O error.Invalid drive error.Invalid SCB offsetMissing right parenthesis.Missing SCB value.Missing left parenthesis.Unrecognized option.No modifier for this option.OPTION: This file was not used.GENCOM completed.Requires CP/M 3 or higher.1n$1n$" %* %|<Ó* %}0HÓ::$]Ç:$jZÇ:$wÇ:$҄ZÇer ͺv!n$q*n$& ͤ!p$p+q*o$~*o$Nͤ*o$#"o$  ͤ ͤ!r$p+q*q$DMͺ !t$p+q*s$!v$p+q*u$!x$p+q*w$!}$p+q*|$"y$*y$}2$|2{$!~$q*~$&,2$!$p+q*$!$p+q*$!$p+q*$!$p+q*$!$p+q*$!$q*$&-!;6:$!; *;&') N#F:2$!;4%:2$%ͻ2$!;6>!;S*;&/% 6!;48!/%6 !;6#6:; *;&*(~ HҞ*;&*(*;&/% w!;4#4`*;&/% 6.!;6 :; *;&*(~ H!;4#N*( *;&/% w!;4î!;p+q3r*;D - :Q2<:{$*{$Mx:{$2<%͛2$:<B*<>̓#+s#r!<5&*<$T :{$]*(DMZ!#:Q! <#:Q2<* !<ړ*<&* (6!<4w* (" (!<6*<&') ^#V"(x*(DM͋2$!)"<*<*<&$) N#Fq#px*(DM͋2$:)!)6*<&9 :)w!)6!)6!)6%͛2$!"$$*$*$"$!<4:$GT*<$#ã!!<ڸ*<&: 6!<4!\"<$w#s#r!n"<$w#s#r.:[ -!<6>!:H!<6::=!$#_"*(DM͠*$~[h*( ~25<>!5<!6<6!4<6:5<=!4<*6<&*(*3<&)))=% *4<& w:6<<26<:4<<24<†*3<&% :5!%**(DM*O>S:%/P o:%o*( >o :% :$<2$23<!*3<&ͮ#% *3<&') q#p!4<6:$=!4< !5<6> !5<:3<=o&!ͮ#% *5<& !*3<&ͮ#% *5<& w:5<<25<³:3<=23<:4<<24<£R"*'"(X">!$҉!!$6!3<6:$!3< !*3<&') ^#V"(X#/b 'Ͳ"!*3<&% >x *3!$Ҙ Ͳ"!:3<<24<:$!4<!*4<&') ^#V"'!6<6>!6< *6<&*(*6<&*' :6<<26<¿ Ͳ":4<<24< ( w*<&') ^#V"(!<6>!!%(z:$/H!"$$#͞%U!$6̓!"<6:"<#ڀ*"<&( 6:"<<2"<_!"<6:$!"<ک*"<&$) >w#6:"<<2"<…!(" (* (:Ow:%/* ( :Ow* ( 6* ( :$w!"$:%:O2)x* (DM%͛2$>!$!%"( ):%/i:$R%͛2$*("(!"$$fx%͛2$!"$o!"$*$*$"$/!##"$*$DM*#w#6!)" (%͛2$* (##"*<**!$ҹ! !O:) ":$!!$6!:%!%!!$6!!$6:)"!$6.;) -!2":$"!$62":%!%,"!$62" :"!$6:$/^"%ͦ%ͻ2$*(~2%%S!*3<&ͮ#% "(*3<&') q#p!4<6> !4<ڱ"!*3<&ͮ#% *4<& 6:4<<24<…" *$&$ :3 !6<#*5<&*7<*6<&*( w:5<<25<:6<<26<"!: !6:5<<25<:6<<26<:#>i`N#Fog_ogDM!>))덑o|gҨ# =–#DM!>))ҽ# =µ#^#V) #^#V|g}o #O{ozgi`N#Fogo&og_{_z#W w!$:&<*<-*$**<"*<*$DMi*&<&9) *'<&) N#Fq#p!(<6>!(<ڋ*&<&)))9 *(<& *'<&)))9 *(<& w:(<<2(!(!%< *%<& * (*$<&)))9 *%<& w:%<<2%<!)" (!$6!,<6:$!,<*,<&$ 6!-<6:$!-<ں*-<&') ^#V"(!.<6>!.<ڑ*.<& * (*.<& *(ʇð:.<<2.!$:$_!)" (!,<6:$!,<r:,<<2,<* (#^#V"0<:$5~ *( 6x*(DM͋2$!0<#"$%͛2$*$DMi*0<"$/>>!)" (* ( ~2$ʃ҃* ( :$* ( w*("(* ( >Ҭf %͛2$:$~!"$$!"$$#*$"$*(DM1͞%U̓!)"TEMP $$$ +q *T 6 *T 6*T!Tp+q*T!Tp+q*T!Tp+q*T] ͧ!Tp+q*T} ͧ!Tp+q*T ͧ *T 6!Tp+q*T!Tp+q*T! ͧ!Tp+q*T" ͧ!Up+q*T$!Vr+s+p+q+q:V *V*VDM*V -- !Vs+p+q:VJ *V*VM!VLS!Vq:V e > :Va/>z!V/H҄ :V_2V:V!Vq:V/>!V/HҦ >ͧ>!Vp+q(7*V~ Y7 N7NTe:T *TMV Y*Vw!Vq:VO! N7:VO! N7!Vp+q 7*V|O *V}O H7!Vq*V&+SDM$ !Vp+q!V6!V60!'"V>V͇S† *VM7 !V6>!V VVzSڽ !V6:V<2VVVzS+s#rÔ :V *VM7!V60*V! S"V:V<2V‹ !Vs+q(7:V  #7*V&DMZ  *VM N!Vs+p+q+p+q :T: ͜*V6:V<2VO!T NV 2V  :V,u *V#"V*V6!V6 :V#… !V6  :V02V:V> !VHҽ >!VҸ :V2Vý !V6!V:V *V^*V&+S*V& *Vq !V6*V6ͧ *1TdCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH1512826543210123456789ABCDEF ERROR: $Reading file: $Writing file: $Directory full$Reading file: $Writing file: $Invalid drive.$) ? $) ? $) ? $Bad character, re-enter $ $ Disk read error: $File cannot fit into GENCPM buffer: $Unable to open: $BDOS3 BIOS3 Setting up directory hash tables: $ Enable hashing for drive $: $Unable to allocate space for hash table.$ Setting up Allocation vector for drive $ Setting up Checksum vector for drive $ *** Bank 1 and Common are not included *** *** in the memory segment table. *** $Number of memory segments $ CP/M 3 Base,size,bank ($) $ Enter memory segment table: $ Base,size,bank $Zero length segment not allowed.$Bank one not allowed.$ ERROR: Memory conflict - segment trimmed. $Memory conflict - cannot trim segment.$ ERROR: Memory conflict - segment trimmed. $ ERROR: Memory conflict - segment trimmed. V6? ͜*VDMN*V~  (7*VN !V6>!Vn *V#"V:V:-Q/HX *V6d ,7*VN :V<2V, *V++"VNÊ *VN*V !V6!V6Te!Vr+s+q:-Q/Ү >!V6#q#p!V6:5Q!Vڳ*V&+SFQ  VzSک:VM*V&+SFQ  ~*V&+SFQ  VzSHJ:V2V*V&+SFQ  ^#V"Vé*V&+SFQ  ~*V&+SFQ  VzSHҩ:V2V*V&+SFQ  ^#V"V:V<2V¿ :V:VH`!V6:5Q!V`*V&+SFQ  VzS/*V&+SFQ  ~H*V&+SFQ  VzSHV:V2V*V&+SFQ  ^#V"V:V<2V:V!$V6!U6ͬ#Q$!H> U͇Sʔ* U|2Uß*U|2U!U:.Q2T*U|!UO:/Q2T*U|O:T2TUTI:-Q/!$V>O:T2T* U|O:T!$V2T:T=2T* U|O:T2TҮ:-Qқ*nV*U*V |!UO:/Q2T*U|O:T2T2Uͬ:U/Ҙ!!V6>!!Vژ*!V&$SQ  6:!V<2!Vsà!U6:V/ҫ*:U2T:T2TTͩ:-Q*T&+SDM*U*T&+SDM*U:-Q/$ CP/M 3 Sys $ Memseg No. $ Bank $ Accept new memory segment table entries $Default entries are shown in (parens). Default base is Hex, precede entry with # for decimal $ Use GENCPM.DAT for defaults $Create a new GENCPM.DAT file $Display Load Map at Cold Boot $Number of console columns $Number of lines in console page $Backspace echoes erased character $Rubout echoes erased character $Initial default drive ($:) ? $Top page of memory $Bank switched memory $Common memory base page $Long error messages $Double allocation vectors $Accept new system definition $ CP/M 3.0 System Generation Copyright (C) 1982, Digital Research $ BNKBIOS3 SPR$BIOS3 SPR$BNKBIOS3 SPR$BDOS3 SPR$RESBDOS3 SPR$BNKBDOS3 SPR$ 64K TPA Copyright (C) 1982, Digital Research *** CP/M 3.0 SYSTEM GENERATION DONE ***$!Tq:UM*T&!Tp+q:Ud*T !Tp+q*T#6:UҀ:Tڀ*T *T#N! *T6 7 7!Tr+s+q+q!U6N*TDMN:TTN͜:T.:T/!U!]6 !m6 !Tp &:U2!V!""V*!VM"V͟:!V2U! U6Û*U|!U2!V* U|!Uo&)##""V*T&+SDM*!V*!VM"V͟:!V2 U:U2!V!""V>T͇S+s#r*!VM"V͟:!V2U* U|!$V2T:T2T U(T(TͩC*$V&+ST͊S+s#r* U|!$V2!V:-Q/ *T&+SDM*!V"*T&+SDM*!V*!VM"V͟:!V!Uw:-QҢ!T6:T2TULTLTͩ*U|2!V*U|!Uo&)*"V""V*T&+SDM*!V*!VM"V͟:!V! Uw:,Q/Ҳ:V2V *V&U  :T2T*T&! S!0*V& U q*T&! S0*V&!U q:V 2V*T&+S"!U$-U RUW !T6#6#6:.Q2U:/Q2UTqT TyT Uͧ pT !T6Uͧ pT pT :;Rһ!;R6:%V2.Q:4Q/24QTT TT L!U6N!Vr+s+p+q*V6 *V#6 *V|O! *V## w*V|O! *V w*V}O! *V w*V}O! *V w!T:TO`iPSW "V*V :0Qw*V :2Qw*V :1Qw.*V :3Qw*V :4QwX*V   :+Q/ҼW*V >*V w:@*V wW*V >*V w^*V :/Qw!)X"V*V&NV) nVR+s#r*(V ͕S—'N:VAO7:7!V6**V >R!S*V&pV) s#r*V&) VR+s#r **V R*V&pV) CS **V q#p:V<2Vk:Vҫ͜:T2FQ!T:/Q2GQ!"IQ!HQ6!V6ON:GR2T 5Q N*FQM ,7*GQM ,7*HQM N:V/҈!N!V6:5Q!V !V6:V/ :V =O!=R ~2T*V&+SFQ DM *V&+SFQ  N`iPS*V&+SFQ  q#p*V&+SFQ  ~ͧ *V&+SFQ  ~7ͧ *V&+SFQ ~2V*V&*V&+SFQ  N "V*V|*V}O:/QH҆MN!V:/Q*V&+SFQ  Hq!V:/QO`iPS*V&+SFQ  q#p *V}2V!V6!V6!V:V# *V&+SFQ ~2V*V&+SFQ  :V2V*V&+SFQ  *V&+SFQ  !V:V/+~!V/H+ |ͧ!V6 :V!V+~!VHc N*V&+SFQ :Vw!V6 :V!V+~!VH N!V:V*V&+SFQ  Hq!V:VO`iPS*V&+SFQ  q#p!V6:V<2V×1:V<2V"͜!V6:5Q!Vo!:V! $: $ Number of data buffers for drive $: $Minumum number of buffers is 1. $ Number of data buffers for drive $: $ Share buffer(s) with which drive ($:) ? $ Allocate buffers outside of Common $ Accept new buffer definitions $!W6>!W**W&)*&V>͒S**W&)*&VWR"(V ͕S*(V ͕SHҸ* *(V WR"*V**V ^6 *W&$SQ q#p*W&$SQ  6*(V ͕S*%ͧ!W4*!W6>!W+!"HW}2W>!W=+*W&$SQ HW|S ~H6+*W&$SQ ^#V"HW!W4**W&))lW *HWs#r*W&))  >w#6!W6>!W+*W&$SQ HW|S>͇SH+*W&))lW  *W6 DS+s#r*W&$SQ  6!W4h+!W4*!W6>!W7,*W&+SFQ  *W&W) N#Fq#p*W&+SFQ  *W&7W w!W4+:-QF,!fW6K,!fW6 !W6:W4:fW=2iW!"gW"dW}2 W! W6*T&PS*LViS"bW:-Qڞ,nVbWzS*ViS"bW!W6>!W,*W&W) *W&+SKQ  N#Fq#p*W&$SQ  6!W4£,!W6! W6#6!W6n&VN#F!W "V*V"V*V͕S(!$V6-!$V6*VSD*VWR!"&V!V6&VS!V6>!Vڷ*V&)*&V>͒Sʭ*V&)*&VWR"(V*(V ͕Sʭ!V6:V<2Vf:-Q/!V!$V6!$V6V>X W*V"V*V~>>!Vs+p+q+p+q%N*VDMN 7*VDM$  7*VME :,QҨ *V&U *VDM :V 2V*V&U DM*V:V2V*V&U *V&+S:V2V*V&U ) :V2V!Vp+q*V"TͣN,ͧ*VDM !Vr+s+p+q*V^#V"T*V##^#V"T*V ^#V"T*V#DMT  *VDMT *TZSU͊S@?ͧ*T+ZS}<2V!V6!V:V҆*V&+SW "TDMͧ *VDM> :V<2VS*TDMO W*T"T!Vr+s+q:VGTqT TyT *Vn}2T*V#~2TpT WTS}pS}TR+s#r*V&)+!Vs+6:V!V4>T͇S+s#rBKͧ pT^ :V<2VpT *VT :-Q/k)Tw T z!LT"V!U"V͙!T"V!U"V͙!(T"V! U"V͙*V#DMT  *VDMT *VDMeͧWͧ *VDM> *V*Ws#r*V##*Ws#r*VN!N:V=O *V&+SFQ NE *V&+SFQ  NE :-Qb!N*V&+SFQ  N ͜:V<2V !T6!V6%NVʹ ͜PNT2V!TT TT N!V6Vʹ ͜:V!FT !!U6+6!W6͌!:W/җ#:R2T͜N;Rʹ :=R2T͜͜N,Qʹ ͜͜:>R2T:2Q<22Q  2Q :2Q=22Q:?R2T:1Q<21Q' 1Q :1Q=21Q:@R2THN3Qʹ ͜:AR2TkN4Qʹ ͜͜:BR2TN:0QAO7NTe:T"*TMV A2W*WM͈ /"Þ":W20Q͜͜:CR2T.Q *.Q&PS"U:DR2TN-Qʹ ͜:-Q/2T:-Q[#:ER2T/Q ͜:FR2TN+Qʹ ͜x#:R2T͜N!W#*W&U 6:W<2W#!W6>!W $*W&U 6$:W<2W#!V6*V&U  !V6TqT TyT Wͧ pT^ pT^ WS#ZS"U!W6>!Wڋ$*W&,V) >w#6:W<2Wh$!"LV:]A$!U6#6!W6>!W$*W&=R 6:W<2W¦$$!U6#6:mD$!U6!T6 Available space in 256 ))lW  ^#V"JW*W&))lW >͒S:WH3:WE-1&N!W6]&N*W&))lW N#F$ {&N!W6>JWR>fS:WHҚ-!JWVS+s#r!W4g-!JWVS+s#r:W3*W&)*&VWR"(V WR"*V >RZS"^W **V ͕S-!W6-!W6*(V ͕Sc0bB*W&$SQ  >w:-Q.: Wd.! W6*W&$SQ  6&N:WAO7&N.:W{O!=R ~2T&N:WAO7'N*W&$SQ  DMʹ ͜*W&$SQ  ~.*W&$SQ  6.*W&$SQ  6t/:W;O!=R ~2T'N:WAO7>'*W&$SQ  DM  : Wt/! W6*W&$SQ  ~t/A'ͧb'N:WAO7'*W&$SQ  DM  &/*W&$SQ  ~^W͇Sҹ/'N*^WDM$ 'N*W&$SQ  *^Ws*W&$SQ  ~R0:W[O!=R ~2TM(N*W&$SQ  ~AO7(NTe:TL0*TMV A2 W* WM͈ *0/* WMF80/*W&$SQ  : Ww͜c0*WMTCc0 4*(V ͕Sn3!W6*W&$SQ >͒S°0*(V q#p*W&$SQ  6n3bB*W&$SQ  >w:-Qګ1: W1:W1! W6!W6*W&$SQ  6(N: *Ws#r*VDM> !V6&VS(>!V6>!V*V&)*&V>͒S*V&)*&VWR"(V *(V## *(V ͕S*(V ͕SH*(V ͕SH*(V ͕SH*(V ͕SH!V6:V<2V-:V!V6!V6!V6>!V*V&)*&VWR"(V*V&)*&V>͒S*(V S?!V6*(V ͕S:V/c!V6N:VO!=R ~2T *(V WR"*V**V N#F`i))"VN:VAO7N*V&6Q DMʹ ͜*V&6Q ~/*(V q#p:-Q/!V6*V&,V) *Vs#r*V*LV"LV*V͛ 2V'ͧ*V&+SFQ  *(V w*V&+SFQ N`iPS*V&+SFQ  N`iPS*V&+SFQ  ͕S *(V q#p*V&+SFQ  VzS*V&+SFQ  q#p:V<2V:-Q/!V!$V6:T<<2T:T<<2T!V6>!V8*V&NV) >w#6*V&pV) >w#6:V<2V:!Vڡ*V&)*&V>͒Sʗ*V&)*&VWR"(V *(V WR"*V*(V ͕SN:VAO7:7!V6**V ^#V!S*V&+S*V&NV) q#p*byte pages: $TPA =$, Bank 0 =$, Other banks =$Unable to allocate Dir deblocking buffer space.$Unable to allocate Data deblocking buffer space.$Unable to allocate Data deblocking buffer space.$Drive specified has not been defined. $0FFFFH is an invalid value in the DPH directory BCB address field.$ Setting up Blocking/Deblocking buffers: $ The physical record size is$: $ *** Directory buffer required *** *** and allocated for drive $: *** $ Overlay Directory buffer for drive $: $ Number of directory buffers for drive $: $Minumum number of buffers is 1. $ Number of directory buffers for drive $: $ *** Maximum number of directory buffers *** *** for the current drive is$. *** *** Number of directory buffers reduced *** *** accordingly. *** $ Share buffer(s) with which drive ($:) ? $ *** Data buffer required and *** *** allocated for drive $: *** $ Overlay Data buffer for drive WAO7(N1: W1!W6! W6:Wʨ1:WƋO!=R ~2T(N:WAO7)N*W&$SQ  DMʹ ͜*W&$SQ  ~ґ1*W&$SQ  6è1*W&$SQ  6! W6S2:WKO!=R ~2T)N:WAO76)*W&$SQ  DM  *W&$SQ  >w: WS2! W6*W&$SQ  ~S29)ͧZ)N:WAO7)*W&$SQ  DM  2*W&$SQ  ~$3: WҌ2! W6*W&$SQ  :Ww 3:WkO!=R ~2T)N*W&$SQ  ~AO7)NTe:T 3*TMV A2 W* WM͈ 2Ü2* WMF2Ü2*W&$SQ  : Ww͜*W&$SQ  :Wwn3:U!W]3:W+O!=R ~2T)N*W&$SQ  DMʹ ͜*WMTCn3 4! W6*W6 dWDS+s#r!W4>JWR>fS:WHҿ3!JWVS+s#r!W4Ì3!JWVS+s#rç-!W4n&))lW  ^#V"JW-!T6!W6:W 4bB)NWʹ ͜P,!"PW}2Wo&"TW2W>!Wu5*W&$SQ  ~n5*W&$SQ  ~ >Hһ4:-Q|4!W4á4*W&$SQ !^N#F-S*TW"TW*W&$SQ  ^*PW"PW*W&$SQ  ~ >Hn5:-Q/5!W4*W&$SQ lW  ^#V"JW*W&))lW >͒S:WHғA!W6>JWR>fS:WHh=!JWVS+s#r!W45=!JWVS+s#r:WxA*W&)*&VWR"(V*W&$SQ  >0?*W&$SQ  ~>*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWs#r0?*\W*ZWs#r*(V *XWs#r*XW##"XW*\W##"\W!W6*W&$SQ  ~!W ?*W&$SQ ^#V͛ 2W*jW6*W&+SFQ N`iPS!N`iPS!͕S  *jW q#p *jW 6*W&+SFQ  *W&$SQ |S+s#r:fWZWR+s#r *jW s#r:fWjWR+s#r!W46>:fWjW͇S+s#r! >w#6:fWjWR+s#r*W&$SQ  >1A*W&$SQ  ~¤?*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWs#r1A*\W*ZWs#r*(V *XWs#r*XW##"XW*\W##"\W!W6*W&$SQ  ~!W A*W&$SQ  ~ҩ@*W&$SQ ^#V͛ 2W*jW6*W&+SFQ N`iPS!N`iPS!͕S  *jW q#p*W&+SFQ   *jW w*W&+SFQ  *W&$SQ |S+s#r@*jW6 *jW *VWs#r*W&$SQ VWR+s#r *jW 6:fWZWR+s#r *jW s#r:fWjWR ItG2WHGtG2W!W6!T:W:W H:W/H[I*W&T :Ww!W4~`i+wtG2WI:W :W/HxItG2W[I!W6#6>!W҇K *W&+S P  ^#V"W! P  ~2WJ:WI:WA2WI:W0/>9!W/HI:W02WI:WA 2W *W&+S P  ^*W&+S*W"W*W&T ~?[J *W&+S P  :WO!=R 6!U6!W4!T5>!T҇K:WʧJ*W&T ~A/>P/HҜJ*W&T ~A*WwäJF GÇK:WJ*W&T ~Y*WwÇK!W6*W6!W6:T=!WڇK:W!WO!T ~2W, K*W#"W6!W6ÀK:W#K!W6 ÀK:W02W:W> !WHQK>!WLK:W2WQK!W6!W:WxK*W^*W&+S*W& sÀKF G!W4J!W6!W6:W:W/HK!W6:W *W&+S P *W& *W&W HK!W4éK:WK!W6K!W4ÒK:WL>:WWͧ T. T~ !W6!W6>!WN!W6#n& +S P  ~2W!W6:W:W/H N!W6>!WڞL'N *W&+S P *W& *W&W w!W4gL:W°L!W6L:WL:WA*W&W wL:W L:W0*W&W wL:WA *W&W w'N*W& ~,5*W&$SQ !^N#F-S*TW"TWT5*W&$SQ !^N#F-S*TW"TW*W&$SQ  ^*PW"PW!W4#4*fW&*PW+S*W&) "RW:-Q9W*U"jW*RW*U*TW *LV *V *nV |O:.QO:T2UO:T2T:T2T:T2T|2U!T2.QW"T*T&PS*U "ZW*RW "VW*T"`W*`WW !T͕SC6*`WW 6*`W#"`W6!W6n&))lW  ^#V"JW*W&))lW >͒S:WH9!W6>JWR>fS:WHҶ6!JWVS+s#r!W4Ã6!JWVS+s#r:W8*W&)*&VWR"(V*W&$SQ  >«7*W&$SQ  ~h7*jW6 *jW *VWs#r*W&$SQ VWR+s#r*(V *ZWs#r:fWZWR+s#r:fWjWR+s#rë7*(V"LW*W&$SQ  n&)*&VWR"(V ^#V"NW*LW"(V *NWs#r*W&$SQ  >£8*W&$SQ  ~48*jW6 *jW *VWs#r*W&$SQ VWR+s#r*(V *ZWs#r:fWZWR+s#r:fWjWR+s#rã8*(V"LW*W&$SQ  >o&)*&VWR"(V!Q  >ʂ8*(V ^#V"NWÐ8*(V ^#V"NW*LW"(V *NWs#r!W4>JWR>fS:WH8!JWVS+s#r!W4ç8!JWVS+s#r6!W4n&))lW  ^#V"+s#r!W4?:fWjW͇S+s#r! >w#6:fWjWR+s#r!W4>JWR>fS:WHhA!JWVS+s#r!W45A!JWVS+s#ru=!W4n&))lW  ^#V"JW=!W6>!WA*W&7W *W&+SFQ  w!W4˜A!W6>!WaB*W&)*&VWR"(V*W&NV) >͒S"B*(V *ZWs#r*W&NV) ZWR+s#r*W&pV) >͒SZB*(V *ZWs#r*W&pV) ZWR+s#r!W4A!"W"W!W6:5Q!WB*W&+SFQ  ~¶B*W&+SFQ  VS*W"WB*W&+SFQ  VS*W"W!W4pB$N%N!bWVSDM$ :-QMC%N*WDM$ :U C$%N*WDM$ >W͇S>W͇SHHC!W6MC!W6͜͜!Ws+q*W&$SQ ^#V"W:-QڋC:fWWRbW͊S+s#rF!iW55:W®D*W&$SQ  ~2W!W6:W!WګD!fW:iWYD!iW6*gW#"gW!W6!W6!W6:5Q!W7D*W&+SFQ  2W!FQ  ~:W!WH0D:W2W:W2W!W4C*W&+SFQ  S+s#rcD!fW:iW2iW*W͛ 2W…D4%ͧ>äD*W&+SFQ  WzS+s#r!W4±CF*W&$SQ  ~2W!W6:W!WF!fW:iWoE!iW6*gW#"gW!W6!W6!W6:5Q!WMEW 6 'N*W&W 6='N*W&W 6  *W&+S P  !^*W&+SR"W:WmM'N*W~A*W&W wM:WʞM'N*W~ҐM*W&W 6YÛM*W&W 6NM*WNbN:WM'N*W&W 6,*W#"W*WNbN'N*W&W 6,*W#"W*WNbN'N*W&W 6 'N*W&W 6 !W4PL!W4'L>!W NT^ T :W]NT^ !W6>!WUN*W&W 6!W4:N!W6aN!W4!Wq'N:WO! *W&W w'N:WO! *W&W wO*TDM}oN*T†O]!O> 2 PW:TgxʀO { O: PO*T!O†O~#o}o|O<O:TzO<.O:TƜzO<8O:TzO:TzO:TotOzO:TgN!|!|PRTMSG ,QPAGWID 2QPAGLEN 1QBACKSPC 3QRUBOUT 4QBOOTDRV 0QMEMTOP .QBNKSWT -QCOMBAS /QLERROR  +QNUMSEGS  5QMEMSEG00 KQHASHDRVA6QALTBNKSA +QNDIRRECA ;QNDTARECA KQODIRDRVA [QODTADRVA kQOVLYDIRA JW\6!W6>!Wc9*W&,V) >͒S\9*W&)*&VWR"(V *VWs#r*W&,V) VWR+s#r!W4 9!W6>!W9*W&)*&VWR"(V*W&NV) >͒Sʽ9*(V *VWs#r*W&NV) VWR+s#r*W&pV) >͒S9*(V *VWs#r*W&pV) VWR+s#r!W4h9aB!W6>!W::*W&W) *W&+SFQ  N#Fq#p!W4:*V*RW*nV "RW> U͇SUzSH҇:*TW*U|O:.QO:T2Uá:*TW* U|O:.QO:T2U!U:T2T:T2T:T2T:.Q2.Q* U}pS} URU͊S"`W> U͇SUzSHB;*RW|O:/Q2T*U}pS}URW"\W*T&PS"XW*T&PS*U "VWÇ;*RW*`W|O:/Q2TW*U"\WO`iPS*`W "XW*T&PS* U "VW*RW*\W"T*U|O:T2T*W&)*\W"jW*XW"ZWWTS"U*T"`W*`WW !T͕S;*`WW 6*`W#"`W;!W6!W6!W6:5Q!WS<*W&+SFQ  2W!FQ  ~:W!WHL<:W2W:W2W!W4;:T2FQ!T:/Q2GQ:W<*W&+SFQ  O:T<*W&+SFQ  N`iPS!͕S"`W!FQ :T w*W&+SFQ  N`iPS*`WiS!q#p!W6n&))*W&+SFQ  2W!FQ  ~:W!WHFE:W2W:W2W!W4D*W&+SFQ  S+s#ryE!fW:iW2iW*W&$SQ  ~ڼEWbWzS+s#rYS:/QpSҹEd%ͧ>E*W͛ 2WE%ͧ>E*W&+SFQ  WzS+s#r!W4D>!Wq*W6 dWR>fS'F>%ͧ>ERROR: $ at line $Missing parameter variable$Equals (=) delimiter missing$Invalid drive ignored$Invalid character$Invalid parameter variable$!"WWͧ !W6!W6:W GG:WG͈K2W:WFIGF GF!Wr+s+q:U2W!U65FN*WDMN>FN*WDMZ :WCG.͜:W2U:WoG!W6TlG!W6sG!W4MG*W&W ~2W:W :W H:W HG:W ·G*W#"WMG*W&W ~2WÄG:Wa/>z!W/HG:W_2W:WG!W6:W!W6:W/:W/HI!W6>!W/H*W&W 6 !W4HtG2W!W6:W:W=H:W H:W/H~H*W&W :WwtG2W!W4:H:W=:W H:W/HҧHtG2W~H:W I:W=>!WHH!W6 I:W=HHF GH:WHcF G:W :W/H {QOVLYDTAA QCRDATAF ;RDBLALV ))덑o|gS =S^#V))) DM!>)):S =2S_og^#V) PS^#V|g}o ZS_{ozgO{ozgi`N#Fogo&og_{_z#WBNKBIOS3SPRRESBDOS3SPRBNKBDOS3SPRCPM3 SYSGENCPM DAT . $ 6+!6:!D*& NZ *& w!4!":2"ͱ!6*& ~ w!4a!"+~2*& "!6!6%*: : H:HI%*:%*:%*:!6*DMͱF: : H:HÀ Fͻ : T :: H: Hғ: †̀ Ó%*:¨%*:½%*:*DMͱ:: H: H̀ ͻ v!q*&!p+q* !s+p+q*:w#6* *#"N#Fy  !p+q*!p+q*!q*&-!q:2!61!s+q:2!6*&"1m!p+q*m!p+q*<!q!6*&: >*&: :":!4!r+s+p+q+p+q: Di !6ͯ*~ʙ*~2*M2!6::ڃÓ*M2nãͯO:2 :22*~2!6*~2ͯ*~)*N! ** =2!!6!6:!::!6!6$ͻ ͅ !p+q*~ ~ HR*#"1*~^>>!`i^#V#~#fo͟]ƒywôG:±xAa{Ҙ_ ʫ ʫß`i~#~2#~2#~2*| \!\~2.n~`>26!.t~:s}>26!N#F#*"^q#Vp"N#F##"^q#Vp"4!7 !6ë7 \\m>_ 1:~# yɍWARNING: Cannot redirect from BIOS $ERROR: Auxiliary device redirection not implemented $ERROR: Insufficient Memory $""SYSIN SUB_og_ogDM!>))덑o|g =_:ø!4 ø*6 *:w:+s#ri :S*#"X!6:2O* ~2*&*:9ʩ!4*:w*&*:˜*&*~2j*6*~2Y:2!6*#~2!4N* :!6*&*:!6!4N* ~2*&*~2*M2:> !HV !4N* ~2*M2% :2#+s#r*N2!E„ *#"i   !s+q+p+q:=2ʺ *:w*#"Ý !q!6*""͐2:( !6(*&*&!s*&!s:C ::H, *+"C :C :++s#rͅ !6:!i *"*M !4K *M :Ҁ FÆ Y:Aґ ͅ *M! ^#Vp      ͅ !q!6:! *N*#"!4 ͅ !6:!V *!C !6^H  *#"!4 ͅ !q:at :{t : :OZ 2:ͅ ͅ l ͐ !6>! x 2 *&l :w:  : Ò : : Ò :=2O!l 6 ë :og_{ozgi`N#Fogo&og~FGET :<***.n6.t6 LL!p:~y !6 <ʊ~"x!F#fh!:~!«!>w~:!5*.~w:; :~!9"1W:.~ !5< W@w.tEy!h g ={  ͩ* . +6.w   *ͩ2*.6#6*.~w#~=~# Ʌo$x(\!54  !F6ȷx(\>^\@_: N#x€ʹ> ʹ ʹŸ*.>wm#wM~xµmp> \ 8>""SYSIN SUB GET 1âCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321SYSIN $$$Getting console input from $INPUT~FROM~FILE~STATUS~CONDITIONAL~FALSE~TRUE~CONSOLE~CONIN:~AUXILIARY~AUXIN:~END~CON:~AUX:~NOT~ECHO~FILTERED~SYSTEM~PROGRAM #).6=GNRW\`enu|[]=, ./;Error at the '^': $Error at end of line: $Invalid option or modifier$End of line expected$Invalid file specification$Invalid command$Invalid delimiter$File not found$Enter Password: $file: $SUBMIT of $GET from $ stopped$console$GET from $ stopped$console$Requires CP/M 3.0$CP/M 3 GET Version 3.0 $Get console input from a file $Enter file: $11N}0N|HG+\Yr'2ͅ !6 *& !4¢ W2!p+q*~A *~@O:!6> !ڄ : \ .*&*~ } *&*>O!4F ">ʰ *++"~Ұ "lp̀\`"̀*} *|2 : ͆ ͅ lp\`" *"ͻ ͐0 ͅ \ ͯ!p+q!6+6>!W *M[ :O[ !47 :!q*&*>*& z !6: ʍ ͻ "> "*DM) ҽ  *DM ͅ Í #: ͻ ">7*DM) 7"+*DM 6ͅ ">[?p͐0hͅ *DM !q"!+s#r:ʨ:=+s#r*DM!p+q*"!\"b"ͻ >ͅ *#"*~[ͻ :: H'%*:„:?ͻ %*:\yÁ:lyÁ:|yÁͻ $!6:£!6%*::Һ!6ÿ!6$::!6!6$::!6!6$ hhhhhhhhhhhhhh 151282 COPYR '82 DRI gggggggggggggggggggggggggggggg"D! BH!!$@ !HA@  H!@  @BPF#fh!:~!«!>w~:!5*.~w:; :~!9"1W:.~ !5< W@w.tEy!h g ={  ͩ* . +6.w   *ͩ2*.6#6*.~w#~=~# Ʌo$x(\!54  !F6ȷx(\>^\@_: N#x€ʹ> ʹ ʹŸ*.>wm#wM~xµmp> \ 8>""SYSIN SUB '*DMT{T:lͪ : >>l?: &#*DMu{:2:2u͉Tp*>@O>*>@*w*~!s+q*&%*& *&%*2& "*DMT*+"*DM3T"!p+q!\#s>!s:+&:2̀&ͣ :22ͧ!s+q+q*M*͍"̀̀Hm*DM̀%*& "!6|*#:w*##:w* :w!6!6\2!:!H÷:!!6l+6**͍!6\* ^#V""!3"$"!o2ͣ :< J.< -B3!6#6!6*#s#r!6\wl!6!6!6\ʒÇ.  -›!&6:!&:&=O! N,:&<2&©**pH*#N*##* ^N0Jͭ1 Gͤͣ  <_1D**M*0G!'q:w**M0*"!6}!6:'҄Çͭ1Ҙ**͇H* >͘ҿ:'/**M*0} <_1K!6 !6)!\""!o)ͣ !6!6ʹͼi**& w:<2cͣ ʹ7*~-w!6*~)…!6:ғͣ !6*"*~)*:º!6***̈́:*:!6!6lͼͣ Þ!6*~>ʤ*#"}!6*:3ͣ *~=X!6*#"}:X!"}**Ҁ* *}s#r*>wÑ**}̈́ͼҡͣ ʹ*~]*~D!6*~I!6*~M!6*~P!6ͣ ʹè!q!6!6*"ʹ!""!o8ͣ >͍J!"ͼҍ*~(c͆Ç*~_[],()!q: > :a/>z!/H:_2:!p+q*^#V"*##^#V"!6 !6+6:W: Q!6l<*6+: m+_Ax!!6Aڙ:ڐ!l+}::*~:Hھ!*#~A<*wO>!*&*6 '!6:.+A: #6#6:  . - 12(:( T}L :2:2!:y :2̀y ͣ :22!""*"!6!6: *")*"*K: *: !6#6l: *)"ï !6l+6!6͔ :  G. - !"!\"!"*^#V" $!^q> !^] :^0O,h :^ AO,!_q:_OD :_OD !ap+q>`Mi !`\Mi !cp+q*bDMG!ep+q!d\+J<!hr+s+q*f&4 N,*gDM͵ DM̈́  ,*3&+) >>l!C9 < ,*3&+) ^#V*3M  ,!iq*# :iw*#"!͛o #*DMu{!"*!*"D*!s*D!s*D!s!6*!*"D*!s*D!s*D!s!6*M: *M: *M: O`iN928 "92;!j6:;!jU :j=O!< Hq!j40 *8M*9 !k6:;!kڇ :k=O!< N,!k4g  ,!lq*' :lw*#"!͛ '*DMT{*!*"!"!ns+q: ͪ :n!O> !>O:n2n!l+: !*&*\:<2O* N2!6> !i*& :b>!4F>:<2O* :w:!4~ʶ 6*#"*{zڶ!"ͧ*!~2xG:2G:p ˆx!4~ 6*#"*{z!"*!~2xG:2G x{_ C#5>ɯ$!p+q!6> !ڌ*&*~ x*&*N,:….,!4Q!r+s+p+q*DMG*DMFEͣ !s+p+q+p+q+p+qWͣ !">͍+s#r!oM*DM`:$*DM͐O>!>͍ ͣ !9*DM͠O>9ͣ *"*#"`!r+s+p+q+p+q***DMͮ*!r+s+p+q+p+q***DMͮ!p+q*DMp!6 > !*&*6!4²*DMͰͣ !p+q * 6 * 6*DM̀*͍!p+q*DM+ͣ !q*& , ,!p+q*  !p+q*!p+q*!p+q*! p+q*! p+q* ! p+q* !p+q`*!p+q*_{ozg_ÞCOPYRIGHT (C) 1980 DIGITAL RESEARCH gRELIRLFATAL ERROR$l$l1 ͺ!"!6͓*~=:!ͣ !6:/::!ͣ !6:!!/ͣ < ͧv! s+p+q> ͍"̀ځ*>! q** DM* 1q>> ͍+s#r=>!r+s+q+q+p+q> ͍"!6> !*&*6!4¦:! *w* * * DM -* *s#r*"̀*":*. Tu -". u -2:~ l:\.~ -Ql.~ -dup. du -zT!"u*M: *M: !6>}!: :<2¨#u{u>!͘,T>͍)*DMTT"*%DMu{̀+s#r;'*DMu{̀N*"'ͅ>v":2T2u:ҙu͟!6>!ڙ: :<2:ҦT͟:!/Ҵ:͍ >>l͍ >!͘:/H*!*"O!mT!w& 8 !w:o2% & *M͍ !6!6:n!2oK :m!o>O!mC!pq*pM !rp+q*q}OY *q|OY *8M *9DMg *;M !s6:;!sھ :s=O!< NY !s4ž !t6:;!t :t=O!< N: !t4 : 2u: :* *uMi  ,*3&+) N#F+q#p!C6:? *uMY !vq "w:R:ҕ *vM*w *3&+) N#F+q#p*3&+) >>l2C:Ҵ *vM *wDMg !yq:y/:yH >!y# :y::::y8*;< -*:;2:@:<!C6*y&>) N#FG>!ykb :y/:yH҅V :y ¦:823*3&+) *9s#r:y!"+"-"/"1!36<::y<@ Gb :!:y<b :I:y/ *yM :y#~ >!y/͐ :yI:I 7:[:y[Ϳ o >á2zO>Ҏ*zM@:zá2z*zM͵:z,=>)-,),>,=*#"!|p+q*{~**{ >*{#"{>ʹ*~>~,HogDM!>))덑o|g = DM!>))4 =,_{ozg~ D^#V) N~ U^#V|g}o `_{ozgO{ozgi`N#Fogo&og_{_z#WLIB 1.1 $REL $$$IRL $$$INDEX ERROR$NO MODULE: $SYNTAX ERROR$APDCentry symbol $select common block $program name $request $error 4 $define common size $chain external $define entry point $error 8 $external + offset $define data size $set program counter $chain address $define program size $end program $end file$FTiw(5ABORTED$DISK READ ERROR$DISK WRITE ERROR$CANNOT CLOSE$DIRECTORY FULL$NO FILE: $<͞8-*<&^<) ^#V"d:M*<&^<) q#p!<4*9&))9  *`:s#r*A:)8"p9*9&))9 q#p:9<29O>D:9=29D:9ڗ*9&))9 ^#V"p9  ^#V"`:*`:DM!96#~ͬ . ":\ -:+: .+: -:9":5*.:~=ͬ :9('*.:~(*.:~)H^*.:~,NDͬ :9['(:9vC()!o96>5!B".:ͬ . ":\ -ˆ*.:~=Ÿͬ ï.+: -§:9ҹ'*.:~*.:~(H*.:~,Dͬ :9'ù:w92y9:9F:9(C(͆7:9):o9:o9H4!"p9>:o929*p9"95*.:~(*.:~ʐn*.:~)p̀^*.:~*.:~(HҍDO:9ʛD*Ͳ!6~̈́6*& 6:[],()?$! : @: <_2 <: !#<ڲ*#<& :<«>!#<4>*.:#".:*.:N2<&õ͵:< ͵!<6 !%<6+6:%< :%<  !8'*u:"w:*E<#"E<ͺ"u:>͔8$>ͥG<ͮ8!TJ<ͫ8:P<Hr:Q<ҁ!U<6 Æ!U<6:U<q:ͫ8+s#r!`:͹8ң96:T<Һ*JE<ͫ8*P<&i:) N#F,DM,*LE<ͫ8F*P<&i:) *q:s#rN*q:DMͷ!V<6>!V<ڷ!"Y<*V<&i:) ^#V"u:>u:ͫ8ʝͺ"W<*Y![<,*[<&i:) ^#V"u:*[<&<) N#F.>u:ͫ8%OkͥDMͪͮDMͪDMͪͺ"u:![<4!"i:"k:"m:"o:*d:##6*d: 6*d:^#V!`=p+q*d:*_=s#r*d: >!a=q*d: :a=w*d:##>?!b=q*d:##:b=w*d:##~*d:##>w*d:##~*d:##>w*d: ~!c=q*d: >:c=Hẅ́d:8++"\<*\<^#V!e=p+q̈́d:8++"\<*\<*d=s#r*d: ^#V!g=p+q*d: *f=s#r*d: ~!h=q*d: >:h=Hw!k=s+p+q!^=6:k==2k=ʱ*i=:^=2^=*i=#"i=Ñ:^=2^=!n=s+p+qͽ"d:`:d:͞8͹h!n=*l=*d: DM*n=>*><6͸ !\6͊ !!%<6͊> :%<5 !͸ ͵" :<:„ :\:%<Hb !:]A<2\O>v !*%<&\ 6 ô !%<6:<.° ͵͊ڰ :%< ڧ !͸ ͵Ô ! :%<<2% :<02<> : :>!"&<͵͊6 - *&<))))*<& "&<0 D͵ *&<:/͵: W :ZD͵:ڎ :!Q: D*Q:&J: :d:ͫ8ʆh!q=}*o=*d: DM*q=>*}U!r=}>M"d:<>!|=r+s+q+q+q+p+q+q+p+q:u=2}=:z=Һ!}=44*`:"d:*}=& "`:q:ͮ896<*s=DM*u=̈́*^=&^<) N#FU*^=&^<) *d:s#r*}=M͍*v=DM>*y=M*u=Ms*x=Mf*u=*d: *s=DM -B:z=Y*{=DM*d: ~#k!{96 MODULE TOP $UNDEFINED START SYMBOL: $YY???? $$$XX???? $$$RQST$ UNDEFINED SYMBOLS: $ABSOLUTE $CODE SIZE $DATA SIZE $COMMON SIZE $USE FACTOR $!=q*=MͲ!~=4!=q> !=8:=0OͲC:= AOͲ!=q:=O:=O!=p+q!=̈́8MD>=08MD:;!t;!;!;:u;2\. ] -Ÿ\ͩ6!t;6!;6!;6!;6!=6+6>!=*=&f;) ^#V"= *= ~ *= DMv5 *= 6!=6:=<2=:=7::2\. ] -)\ͩ6*p9###H:ͮ8!D:U!\:6*p9###F:ͮ8!C:r!\:6*p9###X:ͮ8҉!\:6:R:>S:ͫ8:U:H:C:/HҼ!\:6!\:6:E:!C:!\:6!\:6:C:*F:"::\:*p9###":çCOPYRIGHT (C) 1980 DIGITAL RESEARCH g? OVL LINKING $ $ 1L9M9!96w:o9!9D:!""!""!"9*9^#V"9"q::u9 ͥ6**=;"`:"b:q:b:͞8.96`:q:͞8"9|!96wj1:9R,v!!]:ڤ*]:&f;) N#F͋41!]:4:u92:2:2;2E;2u;2;2;2;!D:6+6!E:6!"p9!"m9}2o9!z962v92x92w9!t96X!"y:"{:"}:":":":":":":":":":":":":":"i:"k:"m:"o:}2:!:6#6#6*9"q:2C:2D:2E:2R:!"X:o&"Z:|!"s:!"p;";";";":":";"7;*+":*+":*+" ;*+"9;!":":";"?;!":":";"A;:9*b::9=o&))9  ^#V!!<4*<&^<) :DM9͏5*:@ ~ !92(< !92)<7 :)<ր2) >!:*!^:6+":^:$t 8'> *0< ~L*0< DMB5*0< 6*0w#6!4w#6*0<##N#F*.< ~O`i~8p8!6Ͷ8ikS*0< DMv5*0< DMd5*0< *0<##N#Fq#pä*0<##q#p*u:#^#V*u: ^#V*u: ^#V*u:~*u:~*u:>*u:~*u: ^#V*w: ^#V!8:=<Hw!>:><Hw!?:?<Hw!@:@<Hw!B͔8>ͥG<*p9"::D:*H:":8*:*:"::r98*:)8":*:*:":Z:X:͞8_X:Z:͞8#"y:e!"y:!:6*X:":!=6>!=ڞ*=&y:) >Ͷ8Ҕͥ:=<2=v!":::2=!=6:=#w:==2= *=&:) *=&: N!: ͠8*=&: ~2=*=& :=w:=2=:=<2=õ*=&: :=w::<2:*b:"d:`:d:͞8q͜/!9H`2UO!: 8DM>ͪ̈́d:8+s#r&!]:6>!]:7*]:&f;) N#F͋4:*]:&<) N#F.B2=:="="=:=O>"=n2=ð-*]:&i:) ^#V"u:>u:ͫ8-2=ͥ"=ͮ"=!"=nͺ"u::]:<2]:w!=r+s+p+q*=}*=_DM͘4*=#*=|_͘4!=p+q*="d:2:=2=:=O>Ґ*=DM^"=ã*=&:) =8"=:=O>:=O>==͞8UO!: ͹8"=*=*="=*=DM*=8*d: ~*d: :!z9/H!"=ͽ"d:`:d:͞8HҴ>=08>͔8S6!~=6U`/wUp/>=08 \8 M`͹ҖÞ2DM_   *=#"=̈́d:8+s#r >!=Ͷ86!=6>#w#62~=ͽ"d:`:d:͞8N/=:=y:) q#p*&>&:) >w#6:&><2&>$s:q:͞87%*q:"s::G%͸*9"q:^ :_:/2^::{9]%!!)>s+p+q:)>ˆ%*g:*'>"'>:f:҅%!)>6Ý%*)>&:) '>8+s#r*]:&y:) N#F*]:%*'>DM*)>M͋%*]:&y:) N#F*'>*)>*]:5y y !*>q:*> &>!*>&:*>#&+"ÿ&:*>1&p"ÿ&:*>?&k$ÿ&:^:ҿ&:*>=O!& ^#VI"ÿ&ÿ&͈"ÿ&>ÿ&͵"ÿ&#ÿ&T#ÿ&#ÿ&#ÿ&$ÿ&$ÿ&Q$ÿ&d$ÿ&W&]&`&f&o&u&{&&&&&&&!+>6)&)2->:^:&*->My (')2,>')2+>:+> '*+>M%('͕".>:^:('*.>DM*,>^%:+>&7','!0:6&H'='!0:6!"1:"7::!:'*:͗8"1:"7:. 9\ -u')29!hʦ':92h\͕6¦'\=45)2|29!:6*7:"1:!"9"9^ :_:/2^::!:!_:' ',':e (.e -'e>*2!:\d5I'}/B(}͉ͽ"d:`:d:͞8)͹(:v92\!0>6>!0>گ(h!0>҈(*0>&\ 6 å(:0>=O! *d:*0>&\ w:0><20>g(!!:6.e -¼(\W5/(!!:6.e -(\d5*d:"1>!_:6I'*1>"d:̈́*9>"9>\d5͍0C\͏5!Z>s*9>!=8C "9*9*|9s#r͍0C*Z>&\8DM\͔5:j2j\v5:9ҁ1*|9)8"|9:y9ZŠ1a9ҟ10ñ1g9ұ10!_>q.*[> :_>w*[> ~!`>q*[> :`>w*[> *[> ^#VN#FR* *[> 6*[>^#V!=8"b>?8!a>s1!a>P2*[> DMv5*a>M1*[> DM͕6P2*[> DML5*b>!=8MͲ1*[>  *[> ͞8ҍ2*[>  *[> N#Fq#p *[> ~ڮ2*[> DMB5 *[> 61*[> N#F*[> *[> N#F͔51!e>p+q*[> N#F*d>?8^8*[>q#p*[>*[> 8+*[>##q#p*[>*[> N#F^#V?8*[> s#r *[> N#F`i"h>*[> N#F `i"j>*h>"f>j>f>͞8ڐ3*f>+*[> ^#V\8DM2_2*f>"f>\3*[> ^#V*j>\8DM2*[>  *[> ͞8Ҿ31*[> N#F*[> *[> N#F͏5!n>s+p+q*[>l>͠84 *[> ~4_2*l>DM2ͦ3Ê4*[>##l>͞8Ҋ4 *[> ~34_2*l>DM2:n>j4*[>  *[> N#FPY͹8d463g4ͦ3Ê4*[>  *[> ͞8҇41Ê4ͦ3!p>p+q*o>"[>!s>s+p+q*q>DM3*[> ^#V"]>*[> N#F*q>?8*]>:s>w *[> 6!u>p+q*t>DM3*[> ^#V"]>*[>!=6>=08>͔8'6!~=6w*=#"=>&8)))M`̈́d:8+s#r>!=Ͷ8\66!=q!=:~=v d!=6h!=ڤ:==O! *d:N:=<2=|:E:J:*Q:M2"V:!"V:|!=6:Q:!=:==O!J: NͲ:=<2=6D:R:*U:&:) S:8"V:D>!{:Ͷ81*:"V:DX:ͣ8D*X:"V:Z:X:͞8mX:Z:͞8#DM*X:v6*:DM*:6*:DM*:6*:DM*:6`:s:͞89ͮ8*9|=ͫ8 Ͳ(Ͳ*=DM_-Ͳ*=*=+DM_)Ͳl*|9DM_68f ͥOr:t9Z^E.:n~:x9ZyU/?OVLAY?OVLA0RELIRLIRLREL))O`i~8p8>!:!>6::!>:>=O!: NͲ!>4½)2:͕":)2::: !:6!>6::!>. ):>=O!: Hq!>4 *h&\8*|& "9>*7:DM\͏5*9+"9!>q:>2]:*]:&f;) N#F͋4!>q:]:!f:Ҏ *]:&y:) N#F*>͘4:]: Z:y:͞8Ҽ *y:"Z:X:y:͞8 *y:"X:*]:&y:) N#F+q#p!>s+p+q::2>O!: :8">d:8+s#rI(.: -)!:6!:6^ ͽ"d:`:d:͞8)/)*{:DM>fy ^%y !":y y *d:"4>#*4>"d:!3>6>!3>)h!3>ڶ):3>=O! *d:Ny û) y :3><23>Œ)*:"::)͸*9"q:̈́d:8+s#r5)!0:4~ (*6*1:#"1:*7:{z*!"1:/ *1:!>~26>xG:6>26>G )x{_ P*#B*>ɯ`iq#zV*COMPRLRSPSPROVLSYM!;>q*5:> :;>w*5:#"5:!3:͹8ڦ*>*3:DM\͔5!"5:!<>q:8>!<>28>:7><27>*!7>6*8>Mq*!8>6!=>q*=>Mq**A:#"A:!?>p+q*>>}O**>>|O*::+:o9+h,*p9"A::\:,+**V:DM**X:":!@>6::=!@>q+*@>&: N!: p9͞8j+*@>&: N͍+!@>47+:o9:o9HҌ+ -!C>q:C>¢+*X:"D>ó+*C>&:) ^#V"D>D>A:͞8+96D>A:͞8+*+*C>&f;) N#F͋4*C>&y:) >Ͷ8,:C>,*X:DM',,',|9A:͞8&,*A:"|9!G>p+q*F>"H>*C>&y:) F>8+!H>͹8g,*H>DM4O**H>"H>3,::=O!: N!: !y: 8*p9͗8"A>**A>DM**:o9,***p9DM*,*m9DM****:r9,*:DM*,*!J>6>!J> - N#F*t>?8*]>~   +5{>.+55OͲ5w66ͩ6́5;6<566́5͕6<>́5͕6<>645͜6<H66! w #ˆ5>Ö5>2,6""6"$6yo`"&6!"*6͋6-66*&6|6 "&6*"6MD6*$6DM:,65ͷ6g666Ͱ66**6|6U6*$645*"6""6**6#"*6ú56**6ABORTED$NO SPACE$NO FILE: $CANNOT CLOSE$DISK READ ERROR: $DISK WRITE ERROR$YYYP   YP6YPYPYPYPYPYP Ͳ ò!>6#6͐6">*>|$7>9ͫ8"|>##*|> ~!7!>6D7*>|?7!>66"|>D7!>6:>Y7!~>6#6#6Å7*|>~2~>*|> ~2>:>z7:>2>*|> ~2>!>6>!>ڰ7*>&v> ~/*>&: w!>4‹7:72"g:^ *:"|> *g:":*9My *9My *9My *~>My *>My *>My *|>":i`N#Fog_og_{ozg_ogDM!>))덑o|gV8 =D8DM!>))k8 =c8_{ozg^#V) ~8^#V|g}o ˆ8_{ozgi`N#Fogo&og_{_z#W*>DM*>h!ͮ"!>2>:>>!>ͫ8HA!ͱ!">G!*!>">*>DM*>MC:>e!*]:M͋!*>*>*]:*>*>5:=Ҭ!ͱ!"!>>͔8ž!*!>">!>6í!!:]:2%>*>M^ *>DM4*>#DM4O`i~8p8"#>*%>M^ *#>*b:"d:`:d:͞8%"*d: ~#"*d: 6̈́d:8+s#r!!{96:*:MH"H"!^:6:*:Mi"2"g:͜2f:o"=6*:::: -y"::29:*::ͺ/Ҵ":*:͉:*:M"!:͹8"/Ͳͯ/Ͳ Ͳ=6#:*:*:*:*:͉*:*:"::*:M/I#:*:͉*d:DM :*:Mҟ#{#=ͯ6Ü#*:&:) :8DM>*:Mf#:*:*:&:) :8*:͉*]:&y:) N#F*]:*:DM5!=6#!=6*:":*:M^ :]:$$*g:*:":C$*]:&:) :8*]:&y:) q#p:]:P$!=6*]:&y:) N#F *:":>!:Ͷ8::HҲ$:R:Ҕ$=6ò$*:&:) :8"S:::2U:!R:6:0:$)$ò$!&>6>!&>%%*&>&:) *&>&:) 8*&>&:) q#p*&>&*!J>4,*p9"A::\:(-ͦ-ͦ-ͦ-!L>6::=!L>|-*L>&: ~2K>u-*K>&:) A:͠8e-ͦ-J-:r-.u--!L>4--*p9*A>A:ͮ8ҕ-ͦ-|-:7>ʥ-ͦ-Õ-!O>q*O>Mͧ**A:#"A:M>A:͞8-ͦ-ù-ͦ-*K>&i:) ^#V"u:>u:ͫ8.ͥ*K>&:) 8"M>͹-ͺ"u:-*K>&<) N#F.*0< ~R.*0< DMd5*0< *0<##N#Fq#p].*0<##q#p2P>:P>ʤ.*K>&:) 8"M>"9:P>O>Ҙ."9͹-2P>c.>5:08>͔8ʾ.q*å.>*5:DM\͔5\v5:w9Z.. \": -.:e /.*o9&\8_* DMe - /:w9#/:w92\\B5:9 A/. ~9\ -9/!"5:}28>27>*ͥ.:x9Z^/. \": -f/.en* -v/:x9ʌ/:x92\\B5!"5:}2R>ͽ"d:`:d:͞8(0͹/H02DMv0 q*!Q>6h!Q>/:Q>=O! *d:Nq*:Q><2Q>/:R><2R>0 q* q*0 q*̈́d:8+s#râ/ q* q*ͥ.!S>q> !S>O0:S>0Oq*Z0:S> AOq*!T>q:T>O60:T>O60!V>p+q*U>|O[0*U>}O[0*9>!=8"W>*W>!=8!Y>s:h0:Y>2h\͕60\>645*W>!=8!|s2*9͗8"9>. \~9 -0:9 1 LINK 1.31 $01/04/83?MEMRY$MEMRYX MEMORY OVERFLOW, USE [A] SWITCH$INSUFFICIENT MEMORY$OVERLAPPING SEGMENTS$ XXABS $$$XXPROG $$$XXDATA $$$XXCOMM $$$::;7;YYABS $$$YYPROG $$$YYDATA $$$YYCOMM $$$n;;;;:0 : 0 -Ͳ !/6+:.;?*$/*."$/?"$/:.l*.^#V{r+s5*.^#V ʓ:. r+s!06#wÚ> 209!e/~6![0~6".~,#!0w9 9*.~6 *: 0,Ĵ2f/*.s#r2[02e/*.#"X0$<5ͬ*$/"M00:T/2:/2[0 v>20*.".2[0v*R0m "R0͍"R0!/w >=G*R0*I0"R0"R0 m :/ }>͞ ¥͢ :O0*V0*ʿ͜">2:O0:0:O0!!4:0: 0,>"4:O0: 2\0:0=: 0 F!Fʹ%*X0"`0>2Z0*X0":0k: 0T!T:\0¦:O0¦:0=ʦ ʦ*"X0 !':[0'Tx»!Z04TT!Z05T:\0!":]0!**V0":O0*X0~ Ĵ*X06 '>#G*I0!" :0 :Z0 !0N*K0:O0Ÿ"b0+"X0yʛ 'É' Ͳ >ͮ 222:0: 0 !ͮ-:0P'!5^!/~ !~620͕%2.|z}z> u!.~w:.W=*u!.4C*V0^#V"V0ý!.5¯:20͕%!^4!/w>R͘%>V͘%>Dý>Pý>Lý>Oý>Bý>Sý>N͘%*6".~ 6g-!2~B6~44O!! s#r!1~ _6^4! w!p!2~~!55N!! N#fiooo&)^#fk9BIO[ov ͌z{>ɯo>g͌"!6ů{_zW5>)D*OxG !?DM!xGyO23)#͌)=R|g}o=^͌͌roz{͉͌͌}|͉͌Þ͌Þ͌ë͉͌!!o#Ã͌zg{o͌zg{o͌zg{oolo&3:0: 0 ;!,ɯ2122=2 !"I0&q!1~\5_! ~͔D:2:/ *!"I0:/ :0:0! 0^#=ʙV¨*0!҂ :0:0& !!>O: >INDEX ERROR$MULTIPLE DEFINITION: $MAIN MODULE ERROR$FIRST COMMON NOT LARGEST$COMMON ERROR$UNRECOGNIZED ITEM $XXABS $$$XXPROG $$$XXDATA $$$XXCOMM $$$::;7;YYABS $$$YYPROG $$$YYDATA $$$YYCOMM $$$n;;;;:0!4 :0& : 0::0!xI !4̨ e ::̮>͞ } !~5:Į ͵ !4̨!~5 G!~Ҩ4_!p!~ʮ5^!~> >2\0:0N *K0"+"X0:0 >''!:0N : 0,N :0 >  > !0N#~' ) > ''*K0"V0:\0x ʹ:\0" m }*K0"+"X0''*K0"V0>"4ͬ:2T/:[0 “ 2/-*M0"$/*X0!{#zڿ ~+"X0*M0+"M0wß #"K0*M0".:\0 N]T s#r+*V0*{_zW".:\02.R     % *I0:/ ͪ% ͬ:O0ĭ%  :.ʢ :0¢ *K0+"X0!2<20*#"" : 00Ĩ!??" 09"K0+"X0$< :0¢ : 0,? ʹ  *} :]0 :O0 :0 ͤ%:e0ĭ%:0 : 0  ͬͧ%vʹ   ͺ :0: 0 !;* _!5 ^#fkS \ h n 2 ͠ ͻ ͵ ͠ ͖ 8{ Ăy0 2͵ ͖ Gͻ ͋ ͖ 1ͻ ͯ 2ͯ ͖ (Ăy 2͵ ͋ ͖ ͖ Ăy0 ͖ 2ͯ 12 yU`:10_!~0!1s! ~͔ yU!1~N=w_! ~QZP>2 ypP͘% >U̘%>: 2 3>E͘%óf:.O*.~H:.=!4>͕%0:/#". ͆%2G:0xa{_ ʇ ʇ:0x҇_<20!/w:e/S:e/9ɯ2f/2d/2e/:0:e/ !2f/g/~#»S͉!f/~4!g/_:e/w2e/ɯ<*V0"36*"V0ɯ2!4!f/6".!f/~55!d/^4!g/~f:.:e/JGwf^l͗^{:e/&{!f/4#ww&ʞGʱ2e/xf͗ :e/&ʕ:0  ý͗&{&{ý͗  !e/~&>62/-!.6*M0"$/B".2f/*"V0͗ 2f/2e/2[020> 2͕%>20ɯ202!0~@$6^4#:[0w~$w:[00 6:[0A:[0?e@eAɷP6 o2[0:Z0ʦ:\0 :O0¦:[0':[0 !20:[0 R;/>20:Z0?:\0:O0?́;B*`0*X0++{z~ ( COPYRIGHT (C) 1977 DIGITAL RESEARCH 112O02Z0̀%!"K2.>2.*M0"$/̓%!"":g0i!"P0"R0"2:0v: 0$  :[0-ʬ+ʬ* :[0!_0M!f0P p  !   :O0Ĝ!":O0*V0}|<r ͪ*|Ĵ:O0_͑H *V0"Ù*V0"E V» ͪ»**»"Ù*K0"X0!0NA#~' ~p"K0*K0N"X0!0q#*w œ:0!x ͜ *V0*R0:_0̍"V02*M0r; !:r :0F: 0e%;m ">2:0b: 020 W,F:0b: 0e,ʹ:re*X0#![0~ʇww2/ͬ:2T/-"."$/2/>2.v:.ʸ!/6+͕%>20:.ʮ:.0209$<!5*}Ģ*V0":0y: 0:yv! X! ^#fkX _~ 0^ Z   2 5 8  :0‰:0=ʉG! 0ʃF#2sÖ*I0| E2V ,[ ͊m *R0"R0"P0 m E2D2V ,ʾ ͊:/ m :/ "> 2/:Į 'd ! ^#V#*0}o|g*  ":D x=D y0P 2!0^4! 0q :0Ė: 0,; Ė*I0m |}$† ͌oy Ԍ͋ 8O͖ Ăy01y 1m X:0 : 0, >C͘%:0 : 0 v;:0 : 0 v-!v !v-ʹ {ozg:.7ͮ2Z0!O0~4l!"*|>"V0*""J͊!/6 !/͒%:^0ʏ>2.͡%ͱ*K0*T0&*M0*T0&\ ͍!/w#õH USE FACTOR !/͒%*"P0Þ%z{*P0"R0*"V0 !":O0Ģ*R0̜*R0ĜG:O0xě%:/ *R0̍:xz*P0#"P0E2D20:b!^4!/wjj*R0!6zz{z4A_A?ɯ2.2*T0"V0!.8w# *V0*K0{zҤ*b0+"X0 =$**X0#Þ!.*V0".#"X0$:d0<:0<! 0~?<#ʐ: 0͡!.".^#V"V0}{##~2.*.^#V#"."V0*V0}d##~<2.G*V0##"X0:.> u!.~w>w> u:.++!+"X0:Z02Z0́ͪ'2Z0X:[0*K: ḰͪX? X́ö20Pg>ã6r>ã:[0'ƒ2[0>ã ¡:.ʔ>+2/͕%!/6 >20>20:[02́:0:Z0: 0=!EQ<!LT:[0=!LE>!GT:[0=!GE2[0" 0!04>20![0:0/ʦg¦´/ʦA¦:[0O<QA>HHR>22[0m:B_>fD> j!052!"0!0N#~#A҄0Æ7O!~*0!ʩң)Ú "0 x:[0 '¦́'æ:[0 :[0,;%:[0 !:[0; ,202́/>20:[02́:0G:0::0l:[0'́:[0' 20/:[0'|>20^—́:[0  <¨!~4 >¼!~5 : >20>V>O>I>B͘%!QéÉ $ ? H Y ` e Ò ü ò ~ÏGÇåûfD?<==:e>?; ><>; ;<=R>>>F>;>G==<==>=s;=P=*>=$?P:-?]>*<<==<;=>>y> ;:0000000000000000000@@@@@@@@@@@@@@@@AA AAQQQ"Q'Q,Q1Q6a *\ ?=)$=)w#Ž&!\60 ڱ&>GO#w ³&>O # &6 &6L#6I#6B#w2|r&\u'>2]0!"%![0~2%wG&!,x&>82%2%!"b0*"M0!1"%"&"@&#"K0"T0' _#~6' D':%A6'>:6'D'>.6'D'>-6'x&!,N'!k-x&!,N':% '> ':%'_!% '6 4ɯ2%2]02e02d02g02%:\ =)!%w#w#w#w#w#w#>2^02_0:m$(!~#$,(~(# 3(%Aʩ(Pʩ(Sʩ(Hʩ(Lʩ(*t(+t(-¶(^0~Sʣ(Mʣ(e0Lʣ(d0Qʣ(g0Rʣ(%1¶(x#3(~AҶ(#3(#6 !)-x&!x&!%͉&!%͉&ͳ'(`&͛'͠':%)!&͉&l&͛'1!* ͍! %!͍! ͍! ʢ ͏ ͕ !!~# 4 ͕  ͍!:!g:!s :!_ g:!s !]~$o #~B̩ 1!ɷW|g ͏ ͕ %z ͍! ͍!  ͍!vCPM3 SYS CPMLDR error: failed to open CPM3.SYS $ CPMLDR error: failed to read CPM3.SYS $ CP/M V3.0 Loader Copyright (C) 1982, Digital Research $021182"(yڥ!2(2(:(2({2(!" #"(9"@"1"!N(y2!K!!!dڛ&_^#V*("""""""""""""((("""";(""""A(G(""""""""""""""""""""""":"ž" *y!(4 5~yµ"5 6y ’" ͒":("!( Oͻ""MD"2 #>" BDOS ERR: $Select$Perm.$""" #""#"v{_zW{_zW )8## ?# w#J#J*|^#V###"(##"(######"(!( I#*(!(I#*(|!(6ʕ#67**(w#w*(w#w#w!(^#V#Fͪ#'*O##*(&%!(s#r#p*(N#F*(^#V#F*(:(O}|y$*(%# =;>?>P?<=?>>=<<i;m=>c==>o>v<=<;8?N!Nw#w#W!"V0!.w#w#l2N!.~4^!.~w!.ͼ!.ͼ!.ͼ!/~w!$/ͼ!D/~w!T/~wN#Fp+q!.~^!.!. !. !. !/!$/ !D/!T/5~wN#Fq#p>BØ%!0" * F#%2NG*V0##~w*V0##~<͉:.t!.N!. yq~t +aG=#w#wY*M0!0n& {ozg"V0!K0{#z"M0b*M0!0N#yʢ ~Õb!."O1:N *M0!$/{#z"V0$ _!.*V0~#~1 ~#"M0û1 !͒%Þ%SYMBOL TABLE OVERFLOW G*V0##~w*V0##~=*V0_###1 s#r1 ^#V1 ##"X0P wP ~O!0~z 6~=ͼ !0N#~ͼ „ Ͳ O2Ny2f0!"&:O0*!"%2%2%2%Z&%u'!-x&z{:]0ʢ)*%F)w)!"%r&\‰)*%#"%+~):.2]0ʢ)r&\!~-N'*%F))Z&!"%*%B&%)¼))*)6# )G&*%*%#"%~!<-x&G:%7*$*x*7*x2*Ϳ'5*9**&*&w#"&!F)`&!"&*&%~ʅ*B&Œ*`*G&`*!S-x&ö,͟**>&*@&w#">&!F)l&!">&*@&&`*_!%~ *2%*b0}!,~ +*#+> *>#**> **b0~>+*#2+> *> *> *}2%!%*O*:/ :O0:%y*:%!O0•+:e0!]0+~,:/ ,!/~ +:f0,:/++:_0,+:/#,:/ ,:_0=+!/~ +!0s!%~!%*4:0!/,G~Y+#x=+> Y+> Y+20!/>x6 #=,G!/~ pͳ'*&}?,>*/,`&%͈':^0*+,!&6S#6Y#6M#w!&w:%2%!"&ͳ'*2%`&%͛'͠'+,:%ʶ,:%.*P0"%.*>&}ʶ,>͕*æ,:%,l&&͈'!-x&CP/M MACRO ASSEM 2.0 NO SOURCE FILE PRESENT N+#*(.#}|y$#$*(%#*(DM"(**(s#r*(s#r#pyoxgk$DM*(0*MD"(!**(MD$*:(O&%!(N:( y$G>O:( ʐ$Ç$*(͒$ :(ʨ$n` ~#for$2(O͚$"(}:(O*(7#"(2("(:(O:(G2(!(w*( *($!$~2(~2($:(2($:(w:(w |g}o'% )4%:(O!3%yoxg:(O&%}*(:(o$$~w{ozg ^#V#:(ʏ%>(Û%͡%"(#ͳ#*(ç%*(r%"(!(~#O&%E:(%$N/*("(y2(ʹ%͗#ͻ%ͫ%ʛ&*(X%:(O~J&yʔ&x ʍ& ʂ&J&Í&N%J&# h&2 #G>G":&$~X%*( I#%Ow!&x&>Fwx2(2(~:(:(6:(&w2($~O %!'>w:&ͨ&$2("4%O.'5"&Ϳ&'$:(!(S'"&: #"ͮ$"$:((͛%#ͳ#%:(< #=!(wW*(M%_S# #-*(MD:%"(:(2(ɯ2('>G=O*(~~w#~2(~wc%$~'~p2(!"(>2(*(~=2('~2(͛'o'>*(w&À# $b${$*!:!X!!M"p"""""4#\#j# ()*+,-/ABCDEHLMDBDIDSDWEIEQGEGTIFINLELTNEORSPACIADCADDADIANAANDANICMACMCCMPCPIDAADADDCRDCXENDEQUHLTINRINXIRPJMPLDALOWLXIMODMOVMVINOPNOTNULORAORGORIOUTPOPPSWRALRARRETRLCRRCRSTSBBSBISETSHLSHRSTASTCSUBSUIXORXRAXRIASEGCALLCSEGDSEGELSEENDMHIGHIRPCLDAXLHLDNAMEPAGEPCHLPUSHREPTSHLDSPHLSTAXXCHGXTHLENDIFEXITMEXTRNLOCALMACROSTKLNTITLEINPAGEMACLIBPUBLIC7 PF FPA A A* A A A(#&&#&2#/?&#' '( v'( %:P!@"<& #*)&# PP%27&#(&#  $ %*%"$  NZZ NCC POPEP M x#_BH!™# 0#³# £#{ڽ#KÅ#CÅ#<: 0 JCR:0 $# $! 06 p#! 0$# # ɯ<:0O=_^$!"F!!V#fjQ̀#G$2!!!^#Vo&)O~#F##xGyѯ:͕*!%^Ww*%{-|-}--{?.!%~#-6.-> ͕*> ͕*͞*> ͞*ws*2%*b0}!,~ +*#+> *>#**> **b0~>+*#2+> *> *> *}2%!%*O*:/ :O0:%y*:%!O0•+:e0!]0+~,:/ ,!/~ +:f0,:/++:_0,+:/#,:/ ,:_0=+!/~ +!0s!%~!%*4:0!/,G~Y+#x=+> Y+> Y+20!/>x6 #=,G!/~ pͳ'*&}?,>*/,`&%͈':^0*+,!&6S#6Y#6M#w!&w:%2%!"&ͳ'*2%`&%͛'͠'+,:%ʶ,:%.*P0"%.*>&}ʶ,>͕*æ,:%,l&&͈'!-x&CP/M MACRO ASSEM 2.0 NO SOURCE FILE PRESENT N!"(2(=2(!"(Û%͛'o'͢'͢&'(ͫ%$~<7(w@ͩ'7':(""(Û%:(~(:(2(:(~(*(6:(p(w#:(w$:(w*@"* #}D>(%$*((*(T):(_2({2("(r%"([))?#,)d)>l)[)I#6:(<!=6)*(J)"(*(K*:(G/O*((*(#=#d)##(I#*+++***N++Q+V+[+k+È+-*`+3*6*9*<*?*B*E*H*,N*Q*T*W*Z*]*`*s*1*~ʞ*O *#Ï*{**>/<Ҹ*33í*O * _ W{«**Ɛ'@'O *!+͆*:+AO *!+͆**+ͥ*!+͆**+ͥ*y2+i&)/ ~#fo{M+s*1*!~2+!~#foͅ*{*C+C+C+i`z n&s*1**+&)/~#foâ+s*1**+&)/~#fo~#fo2+ͅ*{* BIOS Error on : T-, S-+(+(y>PATCH VERSION3.0 PATCH.COM COPYRIGHT 1982, DIGITAL RESEARCH151282654321:o2! *m" -< |#}0#:] <>2   : : :3! ]~. a{ ##e~ a{ ##~ 2m#~2n*m" : aB{B @2\! :\Ҥ!e~ #Z!CO"e>M2g>2 zÖ: *e}C|O:gM>2 *e}P|R:gL>2 \2 |: @: ,?<2 L*>2 ó!>2 6 =++w: #<: +=6 ?>!6 #=D!~a_{_ w#Q: Ƃ2 * 6 : ʝʯ>2 '0: =„>2 '0:S ʂ>2 '0: =±! 3 #:! ]* } 1]:]>2 >2 A: N* | :02# }0 _'_:# 2$ !]}02$ * " * " ? <͍ <ͭ* |́* }́* |́* }́2 >:" '2" {2 z2 : 2 ܻ: WÈ* |}* |}: _:$ d:$ G* |}* |}2 :?@/ _@S.e,- ~,͒,ͭ,,,͢.:.w*.+~>8 +2.͗.>w-:.2.:._O͗.>w-y2.*. :.!,g( !T9o(!T9_( W(s#r*.:._ :9g( T9o(T9s#r:.!%9g( !T9o(!T9_( W(!/[+s#r!:.wW-T9-Ͳ- W-.t9Ͳ- ͓9>^Vͮ9z29~[+ͥ9͢.~˗##͗.~ K+ :.[+( {2.yw-:+ݦG_(x!. (4>w:.3.> ͗.wG3.x> ͭ.  w !9> ͭ. . .p.(!9> ͭ... > ͭ.:.g(!G. O !P. O(!Y. ͭ.z(.p.(*͆* *!.͆*(> >2.!.[+!.K+ >= , Drive Not Ready, Write Protected Disk !/[+^#V:+'''ݶ֯>pݶ/P/T9͑//P/ͨ/t9/͓9>^Vͮ9z29~[+ͥ9:+'''ݶ݆:+:+:+ݦ>0!9F~> /!9F~ק/0%9`     !9[+K+,,:9=29 *+9:+G,,:9=29 !/[+^#Vɧ:=#= {2 x < <͍ C?C C >2% % :' YPyPtz\ V xw <͍ <:$ ڶҏکÜ:$ 2) >:$ 2) >:$ 2) >:$ =2) >2* ! :* O "+ !9 :) O F*+ ~w x <͍: > > 2}!"~"\ʽtS \ _" 2 ~ B* : #=I" 2 ^C* : #=b<* }B* | B!]>I.C!e>I<:\̹@B:C<: 0B C:" 2( :" 00B:( 0B C: 9:<!e>b  9O9$9p<!>b9f<:] ͍ͣ9<!m>I#   <9ͣ< <9͍9<:\@B:C|zʒt< <1Q ̓ͮUtͳr CP/M 3 PATCH - Version 3.0$ ERROR: $PATCH requires CP/M 3$Invalid file type: .$Serial number mismatch$No file: $False password: $Invalid patch number: $Drive $ is R/O$ on $Illegal drive: $ Enter File: $ Enter Password: $ Do you want to indicate that pat9-H-<,;,*,8L8.0=0L0L4ch $ Valid file types: COM or PRL$ Valid patch numbers: 1-32$ Current patches for $ WARNING: Patches greater than $ exist for $ has been installed$ already exists for $ Patch $None$ for $ Patch installed$ Patch not installed$ $ $: $ COMPRL151282 @B* | B!]>I.C!e>I<:\̹@B:C<: 0B C:" 2( :" 00B:( 0B C: 9:<!e>b  9O9$9p<!>b9f<:] ͍ͣ9<!m>I#   <9ͣ< <9͍9<:\@B:C|zʒt< <1Q ̓ͮUtͳr CP/M 3 PATCH - Version 3.0$ ERROR: $PATCH requires CP/M 3$Invalid file type: .$Serial number mismatch$No file: $False password: $Invalid patch number: $Drive $ is R/O$ on $Illegal drive: $ Enter File: $ Enter Password: $ Do you want to indicate that pat----------- xmove?: ld (banks),bc ; save source and dest bnks ret ;---------------------- ; MOVE BLOCK OF MEMORY ;---------------------- move?: ld a,(banks) ; check if inter bank moved needed inc a ; if no inter bnk mov, this sets z-flg jr nz,xmovit ; jmp if inter bnk mov ;----------------- ; INTRA BANK MOVE ;----------------- movit: ex de,hl ; no inter bank move, do simp blk mov ldir ; BDOS passes ldir args reversed ex de,hl ; return args to BDOS ret page ;----------------- ; INTER BANK MOVE ;----------------- xmovit: ex de,hl ; put source in hl, destination in de push hl ; save source count ld (mcount),bc ; save move count mloop: ld hl,(mcount) ld a,l or h ; any more bytes to move? jr z,mexit ; no, jump ld bc,80h sbc hl,bc ; at least 128 more bytes? jr nc,xrdy ; yes, jump (bc = 80h) ld bc,(mcount) ; get final count amount ld hl,0 ; and say that's it xrdy: ld (mcount),hl ; save count pop 1"CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321͈͋> (12/06/82) CP/M 3 PIP VERS 3.0 DISK READ$DISK WRITE$VERIFY$INVALID DESTINATION$INVALID SOURCE$USER ABORTED$BAD PARAMETER$INVALID USER NUMBER$INVALID FORMAT$HEX RECORD CHECKSUM$FILE NOT FOUND$START NOT FOUND$QUIT NOT FOUND$INVALID HEX DIGIT$CLOSE FILE$UNEXPECTED END OF HEX FILE$INVALID SEPARATOR$NO DIRECTORY SPACE$INVALID FORMAT WITH SPARCE FILE$MAKE FILE$OPEN FILE$PRINTER BUSY$CAN'T DELETE TEMP FILE$ *5<P_lz)<\fp}NO DIRECTORY SPACE$NO DATA BLOCK$CAN'T CLOSE CURRENT EXTENT$SEEK TO UNWRITTEN EXTENT$RANDOM RECORD OUT OF RANGE$RECORDS DON'T MATCH$RECORD LOCKED$INVALID FILENAME$FCB CHECKSUM$2FTe$NONRECOVERABLE$R/O DISK$R/O FILE$INVALID DISK SELECT$INCOMPATIBLE MODE$INVALID PASSWORD$ALREADY EXISTS$LIMIT EXCEEDED$hl ; restore source ld a,(sbnk) ; set up to bank in source bank call bank? ; do physical bank select push de ; save destination push bc ; save count ld de,bnkbf ; get bank buf addr ldir ; mov 080h byt into buffer page pop bc ; restore count pop de ; restore dest addr push hl ; save ptr to next source byte ld a,(dbnk) ; set up to bank in dest bank call bank? ; bank in destination bank ld hl,bnkbf ; siz of bnkbf is 080h bytes ldir ; blk mov bank buffer to dest addr jr mloop mexit: pop hl ld bc,0ffffh ; re-set xmove flag ld (banks),bc ; this really sets dbnk = sbnk = 0ffh ex de,hl ; put next destination in hl-reg ld a,(@cbnk) ; reselect old bank (fall into bank?) page ;---------------------- ; SELECT PHYSICAL BANK ;---------------------- bank?: di call ibnksl ei ret ibnksl: ld (abank),a ; save actual bank selected cp 1 jr z,selbnk1 ; jump if bnk 1 jr nc,selbnk2 selbnk0: out (bnk1),a ; eT     =.:;,<> _[]OUTPRNLSTAXOAUXCONAXIINPNULEOFERROR: $ - $$$$DESTINATION IS R/O, DELETE (Y/N)? $**NOT DELETED**$COPYING -$ (Y/N)? $REQUIRES CP/M 3$CP/M 3 PIP VERSION 3.0$:"Q}#( :}#2m#}1͖-m:m#8ͺk 2#2$M 2"!\#6!z#6:z#b:m#2}#!$6+6+6!o#6!"6!"_#"X#}2d#2g#2h#2c#2z#!n#6!e#6#6!j#6!"6:m#ҹ*ͨͺ!#6:}#͑ ͖%#:d#%# :p#=:p#_HH ":S# N:"H ͵!S#6:d#<"$\( K"#&#( Az:S#:" H҃͵!"6&#,"( Az>!S#Ҕͥ z:S#ʡ!e#6:j#z!f#6:p#,:p# Hͥ :p#,2j#!c#w:S#!$6:$!$6:$!$6:"> !"H!d#"ͥ :"/!f#6:" T!f#6>'!f#Q!f#4<g:" dgA2:j#w"á:m#2}#b! $p+q*$}2{#|2x#!!$q:!$_ ͨ ͨ!#$p+q*"$ !%$p+qͺ*$$DM!|#6|#  !' title BANK MOVE MODULE -- CP/M 3.0 .z80 ;------------------------------------------------------------------------------ ; ; Super Six CP/M 3.0 ; ; BNK ADDR BNK ADDR ; ----------------- ----------------- ; ; 0 0000-3FFF ---> 0 0000-3FFF ; 0 4000-7FFF ---> 0 4000-7FFF ; 0 8000-BFFF ---> 0 8000-BFFF ; 0 C000-FFFF ---> 0-1 C000-FFFF (COMMON) ; ; 1 0000-3FFF ---> 1 0000-3FFF ; 1 4000-7FFF ---> 1 4000-7FFF ; 1 8000-BFFF ---> 1 8000-BFFF ; 1 C000-FFFF ---> 2 0000-3FFF (OVERLAY) ; ;------------------------------------------------------------------------------ global xmove?, move?, bank?, ibnksl, abank global getdata,putdata,shfr16, shfl16, xfercnt ext @cbnk, @dbnk, @dma, diskbf ;---------------------- ; MEMORY CONTROL PORTS ;---------------------- bnk0 equ 016h ; memory control port 0 bnk1 equ 017h ; memory control port 1 page 60 cseg ; common memory ;------------------------ ; SET UP INTER-BANK MOVE ;-------------disable bank 1 by sending a zero ld a,0efh ; prom dis, power on jmp, parity ena out (bnk0),a ; bank in bnk 0 ret selbnk1: ld a,0e8h ; keep common mem banked in out (bnk0),a ; bank out every thing except c000-ffff ld a,007h ; bank in 0-dfff of bank 1 out (bnk1),a ; now in second bank w. common ret selbnk2: ld a,0e8h ; keep common selected out (bnk0),a ; deselect lower 16k banks l a,018h ; use map 1 for overlay out (bnk1),a ; now, c000-ffff --> 0-3fff ret page ; The following routines are basically disk tranfer & utility routines dseg ;------------------- ; GET DATA TO WRITE ;------------------- getdata: ld hl,diskbf ; destination ld de,(@dma) ; source getlp: ld bc,(@dbnk) ; source bank ld b,0 ; destination bank call xmove? ld bc,080h call move? ld a,(xfercnt) dec a ld (xfercnt),a jr nz,getlp ret ;--------------- ; PUT DATA READ ;--------------- putdata: ld hl,(@dma) ; destination ld de,diskbf ; $p+q*&$!)$p+q$*($ DM!+$p+q**$DM **$DM̈́:{#**$ ~Hi **$!{#6!x#6!-$p+q*,$DM̈́!/$p+q*.$DM̈́DM̈́!1$p+q*0$DM *0$DM̈́!3$p+q*2$DM̈́!5$p+q*4$DM̈́!7$p+q$*6$ ~ *6$ >w! *6$ >w$*6$ DM*6$DM̈́!9$p+q*8$DM *8$DM̈́!;$p+q*:$DM̈́ !<$q!<$:$ʐ :<$2$_ *#Mt *R#Mt *"Mt !>$p+q*=$!DM̈́:{#!@$p+q*?$"DM̈́:{#!B$p+q*A$#!D$p+q*C$$!E$q!E$:\# :E$2\#_,0!J$s+p+q+p+q:J$=2J$^ *F$*H$ w*F$#"F$*H$#"H$7  !z#6:h#~ ͡ "j !h#6:g#Ҕ ͙ "j "͢ !}#6!"6l!K$q_ *K$&) N#Fͺ!N$r+s+q:{#2Q$:x#2R$_ :L$:Q$H !R$6 :R$2R$*L$& N! N#F> !L$~H:Q$H> !Q$/H^  ͨ:Q$=O!r N#F!R$6:R$ {  ͨ*R$&) N#Ft>M$H" *M$~A=Oͨ:ͨ!P$6> !P$ *P$&*M$>2O$ :P$ .ͨ*O$Mͨ!P$4¢ ͺ:Q$:Q$H:Q$H:*_#"X#*]#*"~2e$*]##"]#`5!f$62e$`2e$`̀2e$`"5E:f$ҕ:$Ҁ:o#<2o#2f$Ë:e$ 2f$:f$ҕN :$Ҥ:e$2e$:$ҳ*e$M[: $*e$M͂:e$>!":"=2"> >>!"!"5+N!~# ~2g$!"4ͩ2g$ >>!$;*$Mk8:$2"!$6:"<2"!"6g>!$c*$Mk\!$6!"6> :g$g:g$!h$q:"!h$wO!~# ~2i$—*h$&~# :g$w>!g$:i$¨!"4í!"6>2p#:$X#]#;"!i#:p#!o$62j$:j$::j$:o$" *j$M2j$2j$2l$:j$2k$2j$!l$w:l$D!o$6I!o$6: $!o$x:j$::j$Hu2j$T:*k$M*j$M:l$2m$"p$2n$:l$ʲ!l$52k$Ý" 2j$:j$0O> :j$0:j$AO>" :j$A 2j$OH!m$wO`i"">!$@ ͥ >!$N ͥ *_#}bO2 ͙ "j :{#" :y#:.#:$:{#Y:{#NH{͟O[2{#Ø:{#Yͺ"͢ ͺ:.#2.#:/#2/#%#V %#͢ %#!2p#!ͥ !:p#S:p#QHX!:#<2$2p#:p# HO!1!2p#Ü!2p#02$O> r!!$6Ü!2p#02$O> ڜ!*$&!*$& !$sr!*$&$ :$w:$!>!$ҿ!ͥ -*|$ :$w 2p#_og_{ozg_og^#V))) _{ozg^#V) "^#V|g}o "_{ozgO{ozgi`N#Fogo&og*p#Mc %:p#[ !#5.*|$ 6 ñ:q#1!$6#6> !$ڰ!$6:$<2$O>/:$!$O!J *$&*|$ H~G:$¡.*|$ :$w[œ !#5:$2$!$49:p#[¼ _ :q#!q#6+~. 2p#Oc  :q# :p#* Ͳ ͒ !q#6+~;= 2p#Oc = :q#$ *q#&$ *|$:p#w!q#4 :p#[H !#5.*|$ 6 *|$ 6å!$q!$6> !$ڏ *$&> :$ˆ >!$4l >:q#<2q#O*|$ :p#w:p#?± !d#6!$q!p#6?!$:q# ͒ û 2p#:p# :p#]H!:p#A2$O>!:p# Q$H :d#2z#D :R$>!R$~ HH> HD :d#2z#ͥ  m m ͥ !V#:"{ >!V#:"© !U#:"Ғ >!U#:"© !T#:"ҩ >>͙ %#-"( x"( :+#2+#%#! :{#2y# %#j :x# %# "͢ :{#:x#H!" " :{#L:x#D" L" !#6!g#6͡ :"2""! :{#u!h#6:$/:"HҊ!{#6:{#¯:x#§" ï" :"2r#:"2s#:"2t#:"2u#:"2v#:"2w#" 2{#"T#( !"6#6#6#6!"]#:g#ͬ !_#!"Y$>'")!"W$͙ :k#!l#we *W$$ DM" b" k" :a#Ҁ!@"Z# Ë!"Z# W$Y$;">'"W$Y$;"!@*"!a#W$Y$;""Z#!Z#"}O *W$$ DM" :{#" *Z#*W$"W$Ë:$ң !"W$ Y$W$;"ҝ"ͩ 2V$*##"#>'"G!#4!U$6:U$ր!V$ҁ*U$& :U$W$!$ 2V$!U$4L*W$"W$:V$ښ" "Ϳ " *W$$ W$_#;"+s#r{_$( N :a#!@"Z# !"Z# ͡ *X#"]#X#";">#( "0 :&#!r#2&#:'##2'#:(##2(#:)##2)#:-#2-#:.##2.#:/##2/#:0#20#%#V :$}͡ :"2"!"6"V :b#ڦ!$""K"!>1"""""$@""!>1"""""$ """_#;" !"X#:$/>X#H"H@>X#H"""!r$6>!r$@:r$"!*"~9:r$"!"X#!r$4:e#!f#2a#!i#6!b#6!l#6+6!s$6>!s$ڶ*s$&$ ~ʯ*s$&$ ~‘!a#6ï*s$&$ ~¯:e#!f#2b#!a#6!s$4b~:f#W:a#:i#:c#!i#*X#"_#:j#*X#"_# *_#"X#:k#!i# RG: $!$$5Ͱ5*p#M$:j#!c#G*_#"X#:e#QO͡ "  "ͩ 2{#n Hґ*""#:"2#!i#6:{#°*"#"">'"­!"4:{#*"!"">'"!"4" f:z#!"t$"x$͡ !h6\ !"v$:{#t$v$;"H6*v$#"v$͔ :{#]>x$H"R\ : $\ͺ*v$#"t$:{#_!#&#( &#"( f#!1#6!"6:/#/!$#: $>x$H"!{#6:{#Y:{#NH':$͟O[2{#!{#6'"X#";"!@*"!a#=X#";"!"Z#!Z#"}O *X#*"DM:"2W#"Ϳ :{#:{#n" :a#҇*x#&"*X#"X#!W#:":"րHҦ!"6" n /2k#:a#/!c#" "j !h#6!i#6*X#*"6*Z#*X#"X#![$q:[$ !"4>!$:$!":$1*[$&*S#M! ^#V*[$M̈́ø*[$&ø*[$&ø*[$&ø"_#;"ڄ *_#$ :[$w*_##"_#øg*[$&øAKYgu!\$q:\$ *\$M:$*\$M:"2]$!$:]$!$:]$2]$!]$:$w>!]$!]$5 :\$ (!"6!^$q:^$!$wF ͹O:^$0O͹!_$q:_$O):_$O)!`$6:$2$:$'2$:$'2$:$'2$*$MP*$MP*$MP:$¿:͹ ͹ ͹!a$q:$:a$ :n#9:a$ :a$H9:$2b$(:b$!b$6<:"<2"!b$(!"6 ͹>!$4k!n#6:a$ F!"6*a$M͹:a$ Z!n#6!c$q:c$a/>z!c$/H~:c$_2c$:c$!d$q:d$A/>Z!d$/Hҥ:d$ 2d$:d$!f$6*"M!N ^#Vͥ `"]#;" :e#/!b#!"X#]#@" Y*x$#"x$!g#6:{#Y! $#Aͺ!z$6> !z$e*z$&%# ~2{$ ^:z$ W.ͨ*{$Mͨ!z$4/:$p>͡ !"6?" :{#ʲ:{#_!# "( :"ڬ>͔ ~>!":R#!":%#HH :#<2#!}#> *#&~# N[2p# :p# H !}$p+q.*|$ 6 !p#6 #6:q#,T:q# A!p#6N:q#$N!p#6 ͒ )$*|$ 6,*|$ 6:"<*|$w*|$ :#w!~$6>!~$ڗ*~$&$ 6!~$4|!"6#6#6!q#6*p#Mc :q#ھ:p#*Ͳ ͒ 2p#ê:p#:¿:q#(*|$#~A<*|$wO>*p#Mc %:p#[ !#5.*|$ 6 ñ:q#1!$6#6> !$ڰ!$6:$<2$O>/:$!$O!J *$&*|$ H~G:$¡.*|$ :$w[œ !#5:$2$!$49:p#[¼ _ :q#!q#6+~. 2p#Oc  :q# :p#* Ͳ ͒ !q#6+~;= 2p#Oc = :q#$ *q#&$ *|$:p#w!q#4 :p#[H !#5.*|$ 6 *|$ 6å!$q!$6> !$ڏ *$&> :$ˆ >!$4l >:q#<2q#O*|$ :p#w:p#?± !d#6!$q!p#6?!$:q# ͒ û 2p#:p# :p#]H!:p#A2$O>!:p# ɀ3PUT 1$CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321WARNING: $OUTPUT~TO~FILE~CONSOLE~CONOUT:~AUXILIARY~AUXOUT:~END~CON:~AUX:~LIST~LST:~PRINTER~INPUT )15:?DIQVNOT~ECHO~RAW~FILTERED~SYSTEM~PROGRAM $[]=, ./;Error at the '^': $Error at end of line: $Invalid option or modifier$End of line expected$Invalid file specification$Invalid command$Invalid delimiter$File is Read Only$ (Y/N)? $PUT aborted$Enter Password: $Putting $list$console$ input to $ output to $file: $ Do you want another file$File already exists; Delete it$PUT completed for $printer$console$Requires CP/M 3.0$CP/M 3 PUT Version 3.0 $Put console output to a file$ Enter file: $1$1$n}0n|H 7 !~q!v6:~!vD *yN*y#"y!v4% ͵ !v6:~!vڃ *{.͸p !}6^u  *{#"{!v4L ͵ !p+q*DM772͵ :y:YH 7!q:a :{ : :.O 2:͵ ͵ 7@ !6>!څ 2 4 *&@ :w: = :H  :n :[  :=2O!@ 6  :~ !4 7:8 7ã 7:8´ 7ú 7!p+q0 ͵ &7*~ *~@O:!6> !,: .*&*~ %*&*N!4 ,">͵r*++"~[+"r7͆ *DMͻ -͇ Ͱ@͠:@ ʍ:b2b\͐"*}*|27H͇ \̀"*}*|2 : ͵ Ͱ\̀"Ͱ:@ :b2b\͐"Ͱ͆ \ͻ 8̈́:2 :2HF ,">͞u+"g7*DMͻ ͵ F͆ :8‰z7Ï7:2:2 H҈!60Z:0!60Z:0:0H :0w *_!"!6:; :<**s#r**s#r*6*6  ~#Ʌo$*.~ " 11_!G:!:[:{  *._D:g #Fʀ#^p:  ^#V#N#Fx^# ÜDV___K* SYSOUT $$$ hhhhhhhhhhhhhh PUT ERROR: FILE ERASED $ PUT>$ 151282 COPYR '82 DRI ggggggggggggggggggggggggggggggggBD$H$$I! D $DA HH$@ H!@D! A ((*1o:*1[:{*/4^4@_!~#s4aĜ2!5_Ĝ!~+w*.+6.7/ң777G2*͵ !6 **& 6/[!&6:*!&ڋ*&& N *&& w:&<2&`!"':*2)".͉!&6*&& ~ :&<2&è!"'+~2)*&& ".!06!260Z:0:0H:0 Hғ!860Z:090Z:0N0Z:0a*.DM͉Ð:0:0H:0 Hҋ)Ð :0 :0 H:0 H@!86#6!,6+60Z:00Z:00Z:0*.DM͉:0 :0 H:0 H8)= :0:0H:0 H:2 r)0Z:0—0Zÿ:0¿!86#6#6!,6+60Z:00Z:0*.DM͉:0:0H:0 H) v!Hq*H&!Jp+q*I !Ms+p+q*K:Mw#6*K *K#"KN#Fy  !Op+q*N!Qp+q*P!Sp+q*R!Tq*T&-!Uq:U24!5641!Ws+q:V24!56*W&"641!Yp+q:!96!96:01:,!:61!:6:0M:H!:6M!:6:0i:d!;6i!;6:0…:Ҁ!;6Å!;6Ø!p+q*"<!\"><7"ͭ¼*<". .@l ->͵-*#".*~[ ͘-!p+q*~ *~ H'*#"*~3>>!`i^#V#~#fot2XywÉG:†xAa{m_ ʀ ʀt`i~•2F2G#~2H#~2I#~2N*| !\~=w4_P 12O'"&###~2M:G 9!!<1>27>2"> 2#!H:FH!I1>27>t2">2#2H*&.~@!"J<V<W^#V###*#*~~*&.~‡>28í.h"5~ʗ>286!:"o".~>286!N#F*#*#",^q#Vp"*#N#F*#"3^q#Vp"14!&L1 \\*X<m![p+q*Zm!\q!]6*]& >>*]& :\R:]!]4,!cr+s+p+q+p+q:2 t͙ !j6 *b~*b~2j*gM#22!n6:2 :nڳ*gM#22Þ :d21= :d212m*b~2k!n6*b~2j *b~Y *bN! *`*` =2l!mM !n6!e6:m!eJ :nC !e4, P *b6= *b:kw:1.r+s#r͙ :2ʃ *.#".È !26:j2oO*` ~2f*f&*^: !o4*b:ow*f&*^:g *o&*`~2fÚ *b6*.~2g͉ :f2h!d6*.#~2g!h4N*^ :3 !n6- *h&*^:g- !n6!d4N*. ~2g*d&*.~2g*gM#22:2> !2H҆ !d4N*. ~2g*gM#22U :d21.r#+s#r*.N#22!)´ *.#".Ù   !ss+q+p+q:s=2s *p:rw*p#"p !tq!}6*'"y"{2%:%( !%6(*)&*%&!ws*)&́!xs:ts :t:tH\ *.+".s :ts :1.͵++s#r͵ !u6:w!uڙ *y"{*%M !u4{ *xM :}Ұ *7ö =7:%A ͵ *tM! ^#VT7 o7 7 7 7 :8«X !86>_ 1/:~# y1p   %co %c WARNING: Cannot redirect from BIOS $ ERROR: Auxiliary device redirection not implemented $ ERROR: Insufficient Memory $ ERROR: You cannot PUT INPUT to a file when using GET or SUBMIT. $z K   %coSYSOUT $$$_ogDM!>))덑o|gҘ =†_{ozgi`N#Fogo&og~4PUT :ʜ4Y:O>52:[y<jbj%j:!F#fh!~}#!9 E7!6 *9 & ": )7*: DM(G29 )*: 6 *: #": *: 6=:9 : 2 #+s#r*: 6 !" !\" "  " B ʹ̈́  N o :\: ! :\o * ~2 J  . v! q* &! p+q*  ! s+p+q* : w*  * #" ~  ! p+q* ! p+q* ! p+q* ! p+q* ! q* &-! q: 2 ! 6 1! q: 2 ! 6 1g$Nwy!"(9"f1f! Ҕ2! ~#foCOPYRIGHT (C) 1982, DIGITAL RESEARCH 151282KK{<<ʽ<K : >! ~6 69BK! OS}!,"**NK6 :+OK2$^#V#N#FxNp:$p:Gjxj Y# A>QFQx>QGQx3ڰbڼqҼo5p5"""*!yb! ~G*!NKկ2!*$K*"x!*!@$@hK\K:K ~#~ w*NK*NK^#V#N#F!",!."*K6*}ʴ}<ʴ.}o|g "($Kt>=2(*f*(}DɯQ"(>QKQKQ>Q"%Q! r+s+q: 2 ! 6* #s#r 1 ' '! s+q+p+q: =2 ^* : w* #" A! q: y7: 7: ¥7: ³7: 7: 7: 7: 7! p+q! 6> ! -: .'* &* >O'! 4! p+q.* * DM -E ͳ* DMͣ" * }‹* |2 : ҇* M_: >! q: aڨ: {Ҩ: : )#7  4! 6>! CO͎2 * & : w: )C: õ: ): õ: =2 O! 6 : 9: <2 h2 ! 6+6> ! ڠ* & ~?–* &* ~?ʑ77Ö! 6: <2 R: ! p+q* : w!! 6> !! *! & ~?*! &* *! &*  w:! <2! ¶ͳ z2# _:# M :# o&"$ E"& G"( I"* ", ". "0 *$ DMͤ*$ DM.2" Ÿ* DMN 47O͎Yœ* DM͓*$ DM.2" ß:" ½*$ DMN ͬ*$ DM.2" :" *$ DMN )* DM='*$ DMͳ*& E*( Gsource putlp: ld a,(@dbnk) ; destination bank ld b,a ld c,0 ; source bank call xmove? ld bc,080h call move? ld a,(xfercnt) dec a ld (xfercnt),a jr nz,putlp ret page ;-------------------- ; 16-BIT SHIFT RIGHT ;-------------------- shfr16: and a ; a-reg has no of shifts to perform shfrlp: ret z srl d ; shift msb first, bit 0 into carry rr e ; rotate carry into bit 7 of lsb dec a ; decrement shift counter jr shfrlp ; loop until finished ;------------------- ; 16-BIT SHIFT LEFT ;------------------- shfl16: and a shfllp: ret z sla e rl d dec a jr shfllp xfercnt: db 0 page ; Bank move data storage cseg ;-------------- ; DATA STORAGE ;-------------- banks: dw 0ffffh sbnk equ banks ; source bank in inter-bank move dbnk equ banks+1 ; destination bank in inter-bank move abank: ds 1,0 ; actual bank selected mcount: ds 2,0 ; count of bytes to move bnkbf: ds 80h,0 ; interbank move buffer en!2*%DM**ѵ+)) H~#+}#<:<ʲ<77:<ʢ2~77ø~7"9:OG#Q{ozg# ""BBÃà à ÃÃ1j$|@ "H$UUT$$ $I D$BA@! B$$A IA $!"  @$@$BI!!@""$DA  $I$@!** I*, *. *0 !(  Y D .*(  -< ͊2# !3 p+q7*2 DM '*" M_7D7* #" ! "  " .  -¢ !5 p+q*4 ~ *4 ~ H *4 #"4 ñ *4 ~ >>!`i^#V#~#fo"  yˆ w7 G:4 xAڈ ҈ a{ _È  . . " _og_{ozgi`N#Fog_{_z#WYœ* DM͓*$ DM.2" ß:" ½*$ DMN ͬ*$ DM.2" :" *$ DMN )* DM='*$ DMͳ*& E*( Gd mple: A>SET B: [RO] Sets drive B to Read-Only. ///1SETDEF Syntax: SETDEF { d: {,d: {,d: {,d:}}}} {[ TEMPORARY = d: ] | [ ORDER = (typ {,typ}) ]} SETDEF [DISPLAY | NO DISPLAY] SETDEF [PAGE | NOPAGE] Explanation: SETDEF allows the user to display or define up to four drives for the program search order, the drive for temporary files, and the file type search order. The SETDEF definitions affect only the loading of programs and/or execution of SUBMIT (SUB) files. SETDEF turns on/off the system Display and Console Page modes. When on, the system displays the location and name of programs loaded or SUBmit files executed, and stops after displaying one full console screen of information. ///2Examples A>SETDEF è COPYRIGHT (C) 1980 DIGITAL RESEARCH @: 5@%g15252'5h+U"!""*"5j"2u3>2v3*5"3-ͩ-:5Z!""$"5"5"5"5"5" " 522>2 5:4 b:4$M:(5-C+C*M:(5!,5M[!35PMp%M(ʡͣ#v#ƒ$:5}% }!"&:5ʦ>%*#5}| V AX*|:5(#$*#5"A*#5"&#v#% RØV AR*&*R"A*5"%5!4NA#~ͫ% p"5*5N"%5!4q#͢%w 3:4(x *#5:,5o"#5V%2*5Ô; !:V :4:4{%͉"">2!:4:424*o,kÊo:4:4{,ʊ:k*%5#!(5~́ w23@:2(4y""3"323>2v3 :u3L!P46+(0>24:u3:v3"U24͋$͇%ͩ$!5*}*#5":4:4: =X!^#fk:Vj&AW y ~   8 ; C :4:4=S+ >2):4„ ͣ#v#: :5$:)%k %G I k :)%:)c %k %+:4„ :4, " :4 :4/ :4 :5 $*#5^#V*S"s#r*5*#5s#r+"5 |#v#*#5" 5:4 :4/ !"5:5> %AB,#*#5 :4:4 !;*M_!Q^#fkox Iͻ8ʗy0IͻGͰͻHIͻ(yIͰͻͻy0ͻIH'd ! ^#V#*"0}o|gF 9"":!`x=`y0l2!!4^4!4q/:4:4,; *5͉: 5ª|}$ªo͕Ͱ8Oͻy0H͕H͉: 5në:4:4,>C0:4M:4  ;C:4#:4 ! #! #{ozgBB**}j!]~ } #ymy>2(>2v3͖*5|EB"#5>%0,# ^#VÕJB*50MB*50!".*5} "#5^#V"5*.:4 ;!,ɯ2t2u2 52o=20!"5" 52m{!t~Q5_!1~9:uK:K4 *E"5:U2 5*]" 5*v"#5:K4 $:4§:4KK!4^#=ʣV²*4(—ҌV :4:4V !!*/O:0K>20y_j:t:_!;~:!ts!1~y_!t~X=w_!1~[Kdͪ>20$y$zU0!%2m*#5"v:mP>U0%4>%:m!>2m*202m!" 5/:0Kx*#5DM*5" 5}|^#V<>E0:u3ʛ*3~Œ:v3ʁ!\4>A!(0":3]#"3,ž"3Þ-2\  :4x_<24!K4w:94͜:94ɯ2:4284]294:4:94K)2:4;4~#!͜,!:4~*4!;4_:94w]294ɯ<*#5"W͉#4#*W"#5ɯ2[![4Y5!!:46"3!:4~q5!84^4!;4~â:u3:94†G³]âʻ^¨^·:94&·!:44#wó&G294xâG:94&:4G/G&ʷ/&ʷG/G!94~&G!4F#I ,*5͘EIr,o͉n2"5~2 r,Yo :K4 ͉:K4 " : 52> 2K4::4M:4 Mg %U!P46+:v3Ϳ$ý*3*3"3Ϳ$"3½:v3*3^#V{ʽr+s*3^#V ʽ-:v3:r+s!46#w4> 24͋$í!94~6!(5~6"3~,_#!4w͋$ÏV *3o6͋$*3~6 Þ*3:4,"3~ š62:4*3s#r2(5294*3#"%5͇%ͩ$@*3"5":(42:32(5Ģ >24*3"32(5 ͉r!Q4wM>=n2*5~2%! 5%~2͉:K4 v }>v S M:5p*#5*gu>%"u> %2 :5O%:4©:5[%! 4:4©:4,ʀ>:5: O%% 2)5:4:4 !*%5"-5>2'5*%5"&:4:4(:)5N:5N:4=N N*&"%52)ͫ%:(5ī%x;c!'54!'55:)5ž!":*5ʍ!5%Ù*5%*#5":5*%5~ *%56 ͫ%<͉:K4 "5~2o M%(>@%>#*55%!".!/s#r+".*."5:u32'5!5~4P!"*|"#5>%*5%"".o!P46 !L4*>2(>2v3͖>2(>2v3͖NB:O* 0:+5ʘ0*5*!5S*5*!5S\gr!P4w#þH USE FACTOR !M4** "5A1z{*5~2*"#5v#!":5(%! 5%n25%%%>%n2G:5x:L4 o:x_*5#"5:5ʽ*5|ʉIB0>%%O%O: 5%*55%ý:5ʽ: 5O*5*5ESS͎2O=>O͎2N=#y{#* 5* 5 "#5" 5͎21͎2=HÎ2Î20:G!^4!K4wOOn2!6z_{_4A_A?*!5"#5*#5*5{z*/5+"%5**+"%5% V%=͇%͢%*%5#þ!v3ʲ:(O! ^#V4@B%GFB>%%O0*#5##~<##ò*#5"|3#"%5͇%:15^:4^!4~?^#ʲ:4͆!~3"z3^#V"#5}ʝ##~2v32w322(!~38w# ͖!~3"z3>2y3*z3^#V#"z3"#5*#5}>623y"!v36*5"3$"32:4*W"#5GJ2:42942(524> 2S(0>24ɯ242T!4~@`65!^4#:(5O:4yD(w~$w:(50 |:(5D(A:(5?ʱ@ʱD(Aɷ͙| ;!Cͻ2(5:'5:)5:5:(5ͫ%:(5 !J24:(5 ʞ;{>24:'5ʋ:)5.:5‹;Ž*-5*%5++{Iz]~ T++]!]+?"%5:'52'5hͫ%2'5ä:(5*—:S —ʤË ¤24͙ʳ>|ʾ>:(5'2(5> :u3>+2P4(0!K46 >24>24:(52SR:4Z:'5:4=!EQM<8!LE:(5=I!NE>I!LTM>!GT:(5=M!GE2(5"4!44>24!(5:4ruͳ u͇:(5D(OʓQ˜>ßH©>2T2(5:SD(B¹>D> !452T!"4!4N#~#A07O!T/!~*4! ) "4 :(5 5!'':(5 :(5,;%:(5 !:(5; ,J242Z$ l ` / ‰ >24#!:(52S:4; ¡ :4/!:Z/!)!:4 :(5'#!R:(5'z 24É :(5' >24#!^ :(5 #! #!;!)!<!!Z~4z 5",:4M:'5M*,~#T :5T !4N*5*,s#r+"%5yP  ͫ%> ͫ%%g >v % 222:4¦ :4 – ì !ʬ ¦ À :4:4€ ( :4 :4:€ :4€ (€ € x !4À  :€ :>S %2 !~5€ :%j B !4À € !~5€ úG!~4_!p!~5^!~>À >2)5:4 *5" +"%5:4ڥ >ͫ%ͫ%[%:4 :4, V :4  + !4N#~ͫ% > ͫ%ͫ%*5"#5:)5- :)5%͉}*5" +"%5ͫ%ͫ%*5"#5>@:2(4:(5 H 23y"*5"3*%5! {#zt ~+"%5*5+"5wT #"5*5"3:)5ʑ N]T s#r+*#5* {_zW"3:)52v3 > > >2 5n2"5 %: 5*#5* 5"#5*55%"#5:5KBn2: 5O0!*", ++ *5:K4 0@:5Ĩ/ú>2) :u3ʭ :4­ *5+"%5[%2!<24*$#"$""*:40!??"4͋$"5+"%5͇%ͩ$+:4­ :4,J "*} :*5 :5%:4 +:25Ĩ/:4 :4  @ʩ##~<2x3G*#5###"%5:w37> ͺ!w3~w7>w> ͺ:w3Pd!5^!K4~ B!~624(02w3%!>%|_}_> ͺ!w3~w:x3ʜ=͢%ͺ!w34È*#5^#V"#5!y35:24(0!^4!K4w>R0>V0>D>P>L>O>B>S>N0!u~ڇK6N4!E s#r!U :mw* 5!] s#r!t~ ڹ6K^4!1w!;p!u~K!5N!E ~#fo!U ~2n!] ^#V"pK2oo&) ^#fkN]ivKzV{K>ɯo>g"!6ů{_zW5>)D*OxGғ !?uDM!xGyOڱò)â͝ddJ)=J|g}o=2o2o*p"rOxKxGyKxGy0KG*p*r}|K\\z{W¢Ü}|ڜâWʜllyWœâ!!#Qzg{ozg{ozg{ol&:oO:n2m*p" 52n2ox:4#!>!!Z~#!5z #!:Z#!G )!Rz >24>VG!>OG!>IG!>BG!0!P!w#w#["!"#5!U3w#w#p"!u3~#4^!v3~w!3ͷ"!3ͷ"!3ͷ"!3~w!3ͷ"!4~w!(4~wN#Fp+q!u3~#^!v3"!3#!3#!3#!3"!3#!4"!(4"5~wN#Fq#p>B0!4"%*%F# #2P"*#5##~G=#w#6#w]$*5!4n& {ozg"#5!5{#z$"5f$*5!4N#yʦ$ ~Ù$f$!U3"Q"/$:P"%*5!3{#z"#5%_!U3*#5~#~&%~#$"5ÿ$&%!%*A1-25L-15Q-8*1,-x#ñ,~A,-#ñ,#6 !1*!*!E**e !N*+-!j**%,r-6* ,,:=*ʂ-:>*…-2:?*ʨ-!***ѯ2:*29* ,,!3*60#60#60#>235!"*:5ͨ/-!"f*2Q*2e**E*+!1*z{:*5G.*B*-.!"B**\..*B*#"B*+~¤.:u32*5G.*\!F2+*f*-•.*!"f**h*ʹ*E*€.a.Ò.Ҫ.ʒ.6# ‹.͹**h**f*#"f*~!2*G:=*..xx/.x.1,..****w#"*!-*!"***j*!*-/~5/ʹ*9//͹*!2*1L/****w#"*!-*!"****/_!5*~ ͳ.27**/5}!1~ /ͳ.#/> ͳ.>#ͳ.ͅ/> ͳ.*/5~/ͳ.#/> ͳ.> ͳ.> ó.}26*!7*è/Oͳ.:K4 :5:=*yx/:8*!5I0:25!*5—0~0:K4 0!K4~ —0:350:P4+—0:,50ʗ0:Q4#0:L4 0:,5=ʗ0!K4~ ʇ0!4s!7*~!6*Ԩ/4:4!K4ʺ0G~ 0#x=ë0> 0> 024!K4>x6 #=0G!K4~ p%,**}0>ͳ.0*j*+:+5yÙCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282gCP/M 3 SID - Version 3.0$1 !~=W!x ~#ôbx {~#o}o.ÃO$ y͏ , $  ͌ 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# SYMBOL TABLE OVERFLOW *#5###w*#5###~,#*#5_####&%s#r&%^#V&%##"%5F%wF%~#!4~l%6~=ͫ%ͫ%!4N#~ͫ% y%͢%͢%2P"*2=*!"*%,ʨ/26**j*կ ,,0:?*1::*Z1ͬ2L1͎2**}1}w1>B/a1}|Gd/:?*ʓ1**+![2*CP/M RMAC ASSEM 1.1 NO SOURCE FILE PRESENT NO DIRECTORY SPACE SOURCE FILE NAME ERROR INVALID PARAMETER: SOURCE FILE READ ERROR OUTPUT FILE WRITE ERROR CANNOT CLOSE FILES UNBALANCED MACRO LIB END OF ASSEMBLY : 5O!5 ~#fo: 5O!5 s#r:?*yʟ2š2ͬ2Ž2G:9*29*!:*4>6:9*L/29*2%#333/3 3333#332E3 3   MXList WAITING FOR PRINTER $PRINTER READY $z8O!B N#N ¾SP.* |} !9":q!"28!"92%!%^#Vo&)O~#F͔(ͨ(xGyѯ*ÿ*:?*ÿ*:@*ÿ*~x/~# *> x/\ ?-$-w#+!\64 #+>GO#w %+>O # <+6 2+6L#6I#6B#w2|*\+>2*5!"B*!(5~2A*w͹*!1*>826*27*!"/5*"5!5"h*"*"*#"5"!5\, _#~ͨ+ ¶+:;*Aͨ+>:ͨ+Ͷ+>.ͨ+Ͷ+>-ͨ+*!1+!32*!1+:=* D,> D,:D*6,_!D* W,6 4ɯ2D*2*522521528*:\ -2;*2@*O:\ʋ,=Ì,y!<*w#w#w#w#>2+52,5:m$>-!~#$ª,~>-# ʱ,<*A-P-S-R-L-*,+,-,-+5~S-MER: SOURCE FILE READ ERROR OUTPUT FILE WRITE ERROR CANNOT CLOSE FILES UNBALANCED MACRO LIB END OF ASSEMBLY : 5O!5 ~#fo: 5O!5 s#r:?*yʟ2š2ͬ2Ž2G:9*29*!:*4>6:9*L/29*2%#333/3 3333#332E3 3   MXList WAITING FOR PRINTER $PRINTER READY $:] ,:e &͟:l &:u &ͮ!I 1lĤ>#J ,!6-X5AڔҔ_!o^#V - G  + Q  1ͳҔ~½:,=”͍" ,~ڔʔ͍=͍=͍!,o͍ "c=͍=”)*c)!"f,*f*c"h ,*cL>::ʗ^#V#L cxZy y~ #*f ڵ™y ¶"c:,*hT*f , ,T:e,>2e,:ʔ%:e  ͟:u ' ͮ!I Y|”,,}5 2l~2m͍͍"n͍"pDMs !l6ʏ } "v=ʏ =ʏ YP !~ #^#V:l *v{ z "r~62t #w6 ” 1l*v*t!~4 #~#F# x ~#s#r#w>~ʽ ͍=; =”͍Lᯕo>gL,>#!u^#V#0}o|ge X x| y0ʃ GÏ yÏ  G| Q z,{ ,<,>'{>',*##V+^+N+y,L ~+ , :”%,ͳ  ͤL:8>.^+~+:8*>:|}^ >.*f}o|/+- , 0 Ô^#V#*NyҔ** n +ñ q#^#V""~/o>g++Û!.ʔ@͔^#V= ͔^'D! ڔ'?!q'”S_&#hqf0 Ҕ)DM)) O I^*r^#V#^q̀))))oqh"s#r#!4-®+»*+ þ-y_xWþ!IXN!p~ !D_^!x^#Vx1>-~~>=G!q~L!9#x sYYͳғ*v" !6û+"f*v~#cڻʷ^#Vû~*v~Gx5@xv5 x805 x6 45>=*t~*t$5x*l$*n:585"CZMEIABDHSP!"2"t+"v!91t*v~:t2l!~ʐ#^#V#~ ƒ!~6ʳ=G#^#V#~xâ#"v!N#FN*>7l :|!~9#~#V*v9z9~= title 'Root module of relocatable BIOS for CP/M 3.0' ; version 1.0 15 Sept 82 true equ -1 false equ not true banked equ true ; Copyright (C), 1982 ; Digital Research, Inc ; P.O. Box 579 ; Pacific Grove, CA 93950 ; This is the invariant portion of the modular BIOS and is ; distributed as source for informational purposes only. ; All desired modifications should be performed by ; adding or changing externally defined modules. ; This allows producing "standard" I/O modules that ; can be combined to support a particular system ; configuration. cr equ 13 lf equ 10 bell equ 7 ctlQ equ 'Q'-'@' ctlS equ 'S'-'@' ccp equ 0100h ; Console Command Processor gets loaded into the TPA cseg ; GENCPM puts CSEG stuff in common memory ; variables in system data page extrn @covec,@civec,@aovec,@aivec,@lovec ; I/O redirection vectors extrn @mxtpa ; addr of system entry point extrn @bnkbf ; 128 byte scratch buffer ; initialization extrn~ ͍" = ͍"=”" > 2,Y,!|G }G , w#. ~ڔ ͍!=:r ”͍| !| !|”"!~ʩ #~#V§ z§ :w, ‰ :ʔ!~ :w#s#r, ¾ Ô!~ : 6 ~#^#V ,:ʔ!\6#>  w# ' >w# 1 6~!I =”*"!l6~# T :]?2 7ʔ!">HXE͆*ʾ \ͤ2 w# ™ ͥ͝* ҆ !""Ô\ʔ:¾ W$ _$ $ O { x! i`"v2 $ $ w# $ ͥ͝”þ \̀\̀ GтWx!͓B :>ULT͆!6\~# S 2|:] !7<ʔ\ !t   _*\ ʣ \ w Ø *+\ !ڔw{Ҕè *#^#Vr+s+6͓Ҕ*"s#s#rt ! *v*",!*L*L*vL*+L,o=”͍L:X^#VL\~J ʯ.y:,>."Ž! ;w#́=”͍:ʨs#r#;”}w#:;#;>>2o!"#͍}ʔ==”͍""2mNl :=2wͲ:l <!*vNl  |Ͳd=Xl *v5Nl :l|*pMD*n:m7l !"N2>**vͳҟ" *t"c, PASS !~*+"|w=2~ !~##Z:t*rw2t*vF#!s! ^#V&N&N,`r<¦Gæ::^#V#2*r^#V<[>èæxjê8_æ*t2¦,:?*v###æG>è><7*|!N*v!>#> :!>=_~/w/w{G=YP"*##F+N+~a/o>g{\z\<33=>!y$ڇ *y$&>'d !y$4d SYMBOLS NEXT MSZE PC END 6!z$q!h#6?! h record(s) written. h#H!:#A{$O !:h# !2h#!@ !:h#S:h#QHP!:#<2|$2h#:h# HG!)!2h#Ô!2h#02|$O> j!!|$6Ô!2h#02w$O> @!!BH @@ABH B! "BHI$$BI$BI $ HI D$HD$$ H B!$D$"$B$DA!ABI$ ?init ; general initialization and signon extrn ?ldccp,?rlccp ; load & reload CCP for BOOT & WBOOT ; user defined character I/O routines extrn ?ci,?co,?cist,?cost ; each take device in extrn ?cinit ; (re)initialize device in extrn @ctbl ; physical character device table ; disk communication data items extrn @dtbl ; table of pointers to XDPHs public @adrv,@rdrv,@trk,@sect ; parameters for disk I/O public @dma,@dbnk,@cnt ; '' '' '' '' ; memory control public @cbnk ; current bank extrn ?xmove,?move ; select move bank, and block move extrn ?bank ; select CPU bank ; clock support extrn ?time ; signal time operation ; general utility routines public ?pmsg,?pdec ; print message, print number from 0 to 65535 public ?pderr ; print BIOS disk error message header maclib modebaud ; define mode bits ; External names for BIOS entry points public ?boot,?wboot,?const,?conin,?cono,?list,?auxo,?auxi ʔ!\>2|!"*"~:8”*"*"*͠ڔ!"\zn<ʔ*ͯ~# _\V”*#"͠:W\J!*L!,:2:2>2::>2 N, !9# Ô ”J~,=”͍xA|”}ҔgA>;Ag};,;Q|”}!qw,s#r,:[|_!~ʐ![4Ð\ͤŽ2[g>>?,!e>Cw#>Ow#>Mw!u>Sw#>Yw#>Mw., * ͽw#  ͽ  * ?r# {zPY! |}>2!""!Ow #w 0q!\6 ͤ!"~”͍͍͍!6W6!6# ,œ>2ß͓ͣ ͓ͣ ͓ͣ ”ʔ   :@w# G6#. 6# x!a_!~> 55*~#"ů2[\ͤͤͤͤͤͤ!ex#y#*}|͓"*}|":!͓> _ͤ~# 07> >H B$I $HI$H$! $I $I$I $I $BBHHA"HI$H!$HH$ IDH$$H$"BD $$$HH$B@@D!@H" H " "BI$DI$I $H @HI"$AD@@HA$ $@ $@D IB!  $H $I$$HD H!"A""! I$DDI"I$ @$I"DH BH" !I B  B$H$@"IHBI $$@H@ @@@D !@BA$!" D!$A$B@$@@$"$"@  D@@"DH $I!"DH$BB$"H@ $!D$$I$I$$"A$$I  D UUTH@@!@H@ !$  !@ !:h#S:h#QHP!:#<2|$2h#:h# HG!)!2h#Ô!2h#02|$O> j!!|$6Ô!2h#02w$O> @!!BH @@ABH B! "BHI$$BI$BI $ HI D$HD$$ H B!$D$"$B$DA!ABI$ public ?home,?sldsk,?sttrk,?stsec,?stdma,?read,?write public ?lists,?sctrn public ?conos,?auxis,?auxos,?dvtbl,?devin,?drtbl public ?mltio,?flush,?mov,?tim,?bnksl,?stbnk,?xmov ; BIOS Jump vector. ; All BIOS routines are invoked by calling these ; entry points. ?boot: jmp boot ; initial entry on cold start ?wboot: jmp wboot ; reentry on program exit, warm start ?const: jmp const ; return console input status ?conin: jmp conin ; return console input character ?cono: jmp conout ; send console output character ?list: jmp list ; send list output character ?auxo: jmp auxout ; send auxilliary output character ?auxi: jmp auxin ; return auxilliary input character ?home: jmp home ; set disks to logical home ?sldsk: jmp seldsk ; select disk drive, return disk parameter info ?sttrk: jmp settrk ; set disk track ?stsec: jmp setsec ; set disk sector ?stdma: jmp setdma ; set disk I/O memory address ?read: jmp read ; read physical block(s) ?write: jmp write ; write physical block(s)ent memory boot$1: call set$jumps call ?ldccp ; fetch CCP for first time jmp ccp ; WBOOT ; Entry for system restarts. wboot: lxi sp,boot$stack call set$jumps ; initialize page zero call ?rlccp ; reload CCP jmp ccp ; then reset jmp vectors and exit to ccp set$jumps: if banked mvi a,1 ! call ?bnksl endif mvi a,JMP sta 0 ! sta 5 ; set up jumps in page zero lxi h,?wboot ! shld 1 ; BIOS warm start entry lhld @MXTPA ! shld 6 ; BDOS system call entry ret ds 64 boot$stack equ $ ; DEVTBL ; Return address of character device table devtbl: lxi h,@ctbl ! ret ; GETDRV ; Return address of drive table getdrv: lxi h,@dtbl ! ret ; CONOUT ; Console Output. Send character in ; to all selected devices conout: lhld @covec ; fetch console output bit vector jmp out$scan ; AUXOUT ; Auxiliary Output. Send character in ; to all selected devices auxout: lhld @aovec ; fetch aux output bit veconxoff pop h ; recover console number in jz ?cost ; not a xon device, go get output status direct lxi d,xofflist ! dad d ; make pointer to proper xon/xoff flag call cist1 ; see if this keyboard has character mov a,m ! cnz ci1 ; get flag or read key if any cpi ctlq ! jnz not$q ; if its a ctl-Q, mvi a,0FFh ; set the flag ready not$q: cpi ctls ! jnz not$s ; if its a ctl-S, mvi a,00h ; clear the flag not$s: mov m,a ; save the flag call cost1 ; get the actual output status, ana m ; and mask with ctl-Q/ctl-S flag ret ; return this as the status cist1: ; get input status with and saved push b ! push h call ?cist pop h ! pop b ora a ret cost1: ; get output status, saving & push b ! push h call ?cost pop h ! pop b ora a ret ci1: ; get input, saving & push b ! push h call ?ci pop h ! pop b ret ; CONST ; Console Input Status. Return true if ; any selected console input device ; has an a ?lists: jmp listst ; return list device status ?sctrn: jmp sectrn ; translate logical to physical sector ?conos: jmp conost ; return console output status ?auxis: jmp auxist ; return aux input status ?auxos: jmp auxost ; return aux output status ?dvtbl: jmp devtbl ; return address of device def table ?devin: jmp ?cinit ; change baud rate of device ?drtbl: jmp getdrv ; return address of disk drive table ?mltio: jmp multio ; set multiple record count for disk I/O ?flush: jmp flush ; flush BIOS maintained disk caching ?mov: jmp ?move ; block move memory to memory ?tim: jmp ?time ; Signal Time and Date operation ?bnksl: jmp bnksel ; select bank for code execution and default DMA ?stbnk: jmp setbnk ; select different bank for disk I/O DMA operations. ?xmov: jmp ?xmove ; set source and destination banks for one operation jmp 0 ; reserved for future expansion jmp 0 ; reserved for future expansion jmp 0 ; reserved for future expansion ; BOOT ; Initial entry point for system tor jmp out$scan ; LIST ; List Output. Send character in ; to all selected devices. list: lhld @lovec ; fetch list output bit vector out$scan: mvi b,0 ; start with device 0 co$next: dad h ; shift out next bit jnc not$out$device push h ; save the vector push b ; save the count and character not$out$ready: call coster ! ora a ! jz not$out$ready pop b ! push b ; restore and resave the character and device call ?co ; if device selected, print it pop b ; recover count and character pop h ; recover the rest of the vector not$out$device: inr b ; next device number mov a,h ! ora l ; see if any devices left jnz co$next ; and go find them... ret ; CONOST ; Console Output Status. Return true if ; all selected console output devices ; are ready. conost: lhld @covec ; get console output bit vector jmp ost$scan ; AUXOST ; Auxiliary Output Status. Return true if ; all selected auxiliary output devices ; are ready. auxostvailable character. const: lhld @civec ; get console input bit vector jmp ist$scan ; AUXIST ; Auxiliary Input Status. Return true if ; any selected auxiliary input device ; has an available character. auxist: lhld @aivec ; get aux input bit vector ist$scan: mvi b,0 ; start with device 0 cis$next: dad h ; check next bit mvi a,0 ; assume device not ready cc cist1 ; check status for this device ora a ! rnz ; if any ready, return true inr b ; drop device number mov a,h ! ora l ; see if any more selected devices jnz cis$next xra a ; all selected were not ready, return false ret ; CONIN ; Console Input. Return character from first ; ready console input device. conin: lhld @civec jmp in$scan ; AUXIN ; Auxiliary Input. Return character from first ; ready auxiliary input device. auxin: lhld @aivec in$scan: push h ; save bit vector mvi b,0 ci$next: dad h ; shift out next bit mvi a,0 ; insure zero a (nonexistant dstartup. dseg ; this part can be banked boot: lxi sp,boot$stack mvi c,15 ; initialize all 16 character devices c$init$loop: push b ! call ?cinit ! pop b dcr c ! jp c$init$loop call ?init ; perform any additional system initialization ; and print signon message lxi b,16*256+0 ! lxi h,@dtbl ; init all 16 logical disk drives d$init$loop: push b ; save remaining count and abs drive mov e,m ! inx h ! mov d,m ! inx h ; grab @drv entry mov a,e ! ora d ! jz d$init$next ; if null, no drive push h ; save @drv pointer xchg ; XDPH address in dcx h ! dcx h ! mov a,m ! sta @RDRV ; get relative drive code mov a,c ! sta @ADRV ; get absolute drive code dcx h ; point to init pointer mov d,m ! dcx h ! mov e,m ; get init pointer xchg ! call ipchl ; call init routine pop h ; recover @drv pointer d$init$next: pop b ; recover counter and drive # inr c ! dcr b ! jnz d$init$loop ; and loop for each drive jmp boot$1 cseg ; following in resid: lhld @aovec ; get aux output bit vector jmp ost$scan ; LISTST ; List Output Status. Return true if ; all selected list output devices ; are ready. listst: lhld @lovec ; get list output bit vector ost$scan: mvi b,0 ; start with device 0 cos$next: dad h ; check next bit push h ; save the vector push b ; save the count mvi a,0FFh ; assume device ready cc coster ; check status for this device pop b ; recover count pop h ; recover bit vector ora a ; see if device ready rz ; if any not ready, return false inr b ; drop device number mov a,h ! ora l ; see if any more selected devices jnz cos$next ori 0FFh ; all selected were ready, return true ret coster: ; check for output device ready, including optional ; xon/xoff support mov l,b ! mvi h,0 ; make device code 16 bits push h ; save it in stack dad h ! dad h ! dad h ; create offset into device characteristics tbl lxi d,@ctbl+6 ! dad d ; make address of mode byte mov a,m ! ani mb$xevice not ready). cc cist1 ; see if the device has a character ora a jnz ci$rdy ; this device has a character inr b ; else, next device mov a,h ! ora l ; see if any more devices jnz ci$next ; go look at them pop h ; recover bit vector jmp in$scan ; loop til we find a character ci$rdy: pop h ; discard extra stack jmp ?ci ; Utility Subroutines ipchl: ; vectored CALL point pchl ?pmsg: ; print message @ up to a null ; saves & push b push d pmsg$loop: mov a,m ! ora a ! jz pmsg$exit mov c,a ! push h call ?cono ! pop h inx h ! jmp pmsg$loop pmsg$exit: pop d pop b ret ?pdec: ; print binary number 0-65535 from lxi b,table10! lxi d,-10000 next: mvi a,'0'-1 pdecl: push h! inr a! dad d! jnc stoploop inx sp! inx sp! jmp pdecl stoploop: push d! push b mov c,a! call ?cono pop b! pop d nextdigit: pop h ldax b! mov e,a! inx b ldax b! mov d,a! inx b mov a,e! ora d! jnz next ret table10: dw -1000,-100,-10,CBNK ; so that further disk operations take place ; in current bank. setdma: mov l,c ! mov h,b shld @dma lda @cbnk ; default DMA bank is current bank ; fall through to set DMA bank ; SETBNK ; Set Disk Memory Bank. Saves bank number ; in @DBNK for future disk data ; transfers. setbnk: sta @dbnk ret ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returns physical=logical. sectrn: mov l,c ! mov h,b mov a,d ! ora e ! rz xchg ! dad b ! mov l,m ! mvi h,0 ret ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter header (XDPH). read: lhld @adrv ! mvi h,0 ! dad h ; get drive code and double it lxi d,@dtbl ! dad d ; make address of table entry mov a,m ! inx h ! mov h,m ! mov l,a ; fetch table entry push h ; save address of table lxi d,-8 ! dad d title 'Boot loader module for CP/M 3.0' true equ -1 false equ not true banked equ true public ?init,?ldccp,?rlccp,?time extrn ?pmsg,?conin extrn @civec,@covec,@aivec,@aovec,@lovec extrn @cbnk,?bnksl maclib ports maclib z80 bdos equ 5 if banked tpa$bank equ 1 else tpa$bank equ 0 endif dseg ; init done from banked memory ?init: lxi h,08000h ! shld @civec ! shld @covec ; assign console to CRT: lxi h,04000h ! shld @lovec ; assign printer to LPT: lxi h,02000h ! shld @aivec ! shld @aovec ; assign AUX to CRT1: lxi h,init$table ! call out$blocks ; set up misc hardware lxi h,signon$msg ! call ?pmsg ; print signon message ret out$blocks: mov a,m ! ora a ! rz ! mov b,a inx h ! mov c,m ! inx h outir jmp out$blocks cseg ; boot loading most be done from resident memory ; This version of the boot loader loads the CCP from a file ; called CCP.COM on the system drive (A:). ?ldccp: ; First time, load the A:CCP.COM file into TPA -1,0 ?pderr: lxi h,drive$msg ! call ?pmsg ; error header lda @adrv ! adi 'A' ! mov c,a ! call ?cono ; drive code lxi h,track$msg ! call ?pmsg ; track header lhld @trk ! call ?pdec ; track number lxi h,sector$msg ! call ?pmsg ; sector header lhld @sect ! call ?pdec ; sector number ret ; BNKSEL ; Bank Select. Select CPU bank for further execution. bnksel: sta @cbnk ; remember current bank jmp ?bank ; and go exit through users ; physical bank select routine xofflist db -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero db -1,-1,-1,-1,-1,-1,-1,-1 dseg ; following resides in banked memory ; Disk I/O interface routines ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke login procedure for drive ; if this is first select. Return ; address of disk parameter header ; in seldsk: mov a,c ! sta @adrv ; save drive select code mov l,c ! mvi h,0 ! dad h ; create index from drive code lxi b,@dtbl ! dad b  ; point to read routine address jmp rw$common ; use common code ; WRITE ; Write physical sector from currently selected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). write: lhld @adrv ! mvi h,0 ! dad h ; get drive code and double it lxi d,@dtbl ! dad d ; make address of table entry mov a,m ! inx h ! mov h,m ! mov l,a ; fetch table entry push h ; save address of table lxi d,-10 ! dad d ; point to write routine address rw$common: mov a,m ! inx h ! mov h,m ! mov l,a ; get address of routine pop d ; recover address of table dcx d ! dcx d ; point to relative drive ldax d ! sta @rdrv ; get relative drive code and post it inx d ! inx d ; point to DPH again pchl ; leap to driver ; MULTIO ; Set multiple sector count. Saves passed count in ; @CNT multio: sta @cnt ! ret ; FLUSH ; BIOS deblocking buffer flush. Not implemented. flush: xra a ! ret ; return with no error ; err xra a ! sta ccp$fcb+15 ; zero extent lxi h,0 ! shld fcb$nr ; start at beginning of file lxi d,ccp$fcb ! call open ; open file containing CCP inr a ! jz no$CCP ; error if no file... lxi d,0100h ! call setdma ; start of TPA lxi d,128 ! call setmulti ; allow up to 16k bytes lxi d,ccp$fcb ! call read ; load the thing ; now, ; copy CCP to bank 0 for reloading lxi h,0100h ! lxi b,0C80h ; clone 3K, just in case lda @cbnk ! push psw ; save current bank ld$1: mvi a,tpa$bank ! call ?bnksl ; select TPA mov a,m ! push psw ; get a byte mvi a,2 ! call ?bnksl ; select extra bank pop psw ! mov m,a ; save the byte inx h ! dcx b ; bump pointer, drop count mov a,b ! ora c ; test for done jnz ld$1 pop psw ! call ?bnksl ; restore original bank ret no$CCP: ; here if we couldn't find the file lxi h,ccp$msg ! call ?pmsg ; report this... call ?conin ; get a response jmp ?ldccp ; and try again ?rlccp: lxi h,0100h ! lxi b,0C00h ; clone 3K rl$1: mvi a ; get pointer to dispatch table mov a,m ! inx h ! mov h,m ! mov l,a ; point at disk descriptor ora h ! rz ; if no entry in table, no disk mov a,e ! ani 1 ! jnz not$first$select ; examine login bit push h ! xchg ; put pointer in stack & lxi h,-2 ! dad d ! mov a,m ! sta @RDRV ; get relative drive lxi h,-6 ! dad d ; find LOGIN addr mov a,m ! inx h ! mov h,m ! mov l,a ; get address of LOGIN routine call ipchl ; call LOGIN pop h ; recover DPH pointer not$first$select: ret ; HOME ; Home selected drive. Treated as SETTRK(0). home: lxi b,0 ; same as set track zero ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. settrk: mov l,c ! mov h,b shld @trk ret ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further operations. setsec: mov l,c ! mov h,b shld @sect ret ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @or message components drive$msg db cr,lf,bell,'BIOS Error on ',0 track$msg db ': T-',0 sector$msg db ', S-',0 ; disk communication data items @adrv ds 1 ; currently selected disk drive @rdrv ds 1 ; controller relative disk drive @trk ds 2 ; current track number @sect ds 2 ; current sector number @dma ds 2 ; current DMA address @cnt db 0 ; record count for multisector transfer @dbnk db 0 ; bank for DMA operations cseg ; common memory @cbnk db 0 ; bank for processor operations end  point to relative drive ldax d ! sta @rdrv ; get relative drive code and post it inx d ! inx d ; point to DPH again pchl ; leap to driver ; MULTIO ; Set multiple sector count. Saves passed count in ; @CNT multio: sta @cnt ! ret ; FLUSH ; BIOS deblocking buffer flush. Not implemented. flush: xra a ! ret ; return with no error ; err,2 ! call ?bnksl ; select extra bank mov a,m ! push psw ; get a byte mvi a,tpa$bank ! call ?bnksl ; select TPA pop psw ! mov m,a ; save the byte inx h ! dcx b ; bump pointer, drop count mov a,b ! ora c ; test for done jnz rl$1 ret ; No external clock. ?time: ret ; CP/M BDOS Function Interfaces open: mvi c,15 ! jmp bdos ; open file control block setdma: mvi c,26 ! jmp bdos ; set data transfer address setmulti: mvi c,44 ! jmp bdos ; set record count read: mvi c,20 ! jmp bdos ; read records signon$msg db 13,10,13,10,'CP/M Version 3.0, sample BIOS',13,10,0 ccp$msg db 13,10,'BIOS Err on A: No CCP.COM file',0 ccp$fcb db 1,'CCP ','COM',0,0,0,0 ds 16 fcb$nr db 0,0,0 init$table db 3,p$zpio$3a,0CFh,0FFh,07h ; set up config port db 3,p$zpio$3b,0CFh,000h,07h ; set up bank port db 1,p$bank$select,0 ; select bank 0 db 0 ; end of init$table end status port ani 1 ; isolate RxRdy rz ; return with zero ori 0FFh ret null$status: xra a ! ret ?co: ; character output mov a,b ! cpi 6 ! jz centronics$out jnc null$output mov a,c ! push psw ; save character from push b ; save device number co$spin: call ?cost ! jz co$spin ; wait for TxEmpty pop h ! mov l,h ! mvi h,0 ; get device number in lxi d,data$ports ! dad d ; make address of port address mov c,m ; get port address pop psw ! outp a ; send data null$output: ret centronics$out: in p$centstat ! ani 20h ! jnz centronics$out mov a,c ! out p$centdata ; give printer data in p$centstat ! ori 1 ! out p$centstat ; set strobe ani 7Eh ! out p$centstat ; clear strobe ret ?cost: ; character output status mov a,b ! cpi 6 ! jz cent$stat jnc null$status mov l,b ! mvi h,0 lxi d,data$ports ! dad d mov c,m ! inr c inp a ; get input status ani 4 ! rz ; test transmitter empty ori 0FFh ! ret ; return true if ready cent$s title 'Character I/O handler for z80 chip based system' ; Character I/O for the Modular CP/M 3 BIOS ; limitations: ; baud rates 19200,7200,3600,1800 and 134 ; are approximations. ; 9600 is the maximum baud rate that is likely ; to work. ; baud rates 50, 75, and 110 are not supported public ?cinit,?ci,?co,?cist,?cost public @ctbl maclib Z80 ; define Z80 op codes maclib ports ; define port addresses maclib modebaud ; define mode bits and baud equates max$devices equ 6 cseg ?cinit: mov a,c ! cpi max$devices ! jz cent$init ; init parallel printer rnc ; invalid device mov l,c ! mvi h,0 ; make 16 bits from device number push h ; save device in stack dad h ! dad h ! dad h ; *8 lxi d,@ctbl+7 ! dad d ! mov l,m ; get baud rate mov a,l ! cpi baud$600 ; see if baud > 300 mvi a,44h ! jnc hi$speed ; if >= 600, use *16 mode mvi a,0C4h ; else, use *64 mode hi$speed: sta sio$reg$4 mvi h,0 ! lxi d,speed$table ! dad d ; point to countat: in p$centstat ! cma ani 20h ! rz ori 0FFh ! ret baud$ports: ; CTC ports by physical device number db p$baud$con1,p$baud$lpt1,p$baud$con2,p$baud$con34 db p$baud$con34,p$baud$lpt2 data$ports: ; serial base ports by physical device number db p$crt$data,p$lpt$data,p$con2data,p$con3data db p$con4data,p$lpt2data @ctbl db 'CRT ' ; device 0, CRT port 0 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'LPT ' ; device 1, LPT port 0 db mb$in$out+mb$serial+mb$softbaud+mb$xonxoff db baud$9600 db 'CRT1 ' ; device 2, CRT port 1 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CRT2 ' ; device 3, CRT port 2 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CRT3 ' ; device 4, CRT port 3 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'VAX ' ; device 5, LPT port 1 used for VAX interface db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CEN ' ; device 6, Centronics parallel printer db mb$output db baud$none db 0 ; table terminator ; CALLVERS program bdos equ 5 ; entry point for BDOS prtstr equ 9 ; print string function vers equ 12 ; get version function cr equ 0dh ; carriage return lf equ 0ah ; line feed org 100h mvi d,5 ; Perform 5 times loop: push d ; save counter mvi c,prtstr lxi d,call$msg ; print call message call bdos mvi c,vers call bdos ; try to get version # ; CALLVERS will intercept mov a,l sta curvers pop d dcr d ; decrement counter jnz loop mvi c,0 jmp bdos call$msg: db cr,lf,'**** CALLVERS **** $' curvers db 0 end ,10,'BIOS Err on A: No CCP.COM file',0 ccp$fcb db 1,'CCP ','COM',0,0,0,0 ds 16 fcb$nr db 0,0,0 init$table db 3,p$zpio$3a,0CFh,0FFh,07h ; set up config port db 3,p$zpio$3b,0CFh,000h,07h ; set up bank port db 1,p$bank$select,0 ; select bank 0 db 0 ; end of init$table end ter entry mov a,m ! sta speed ; get and save ctc count pop h ; recover lxi d,data$ports ! dad d ; point at SIO port address mov a,m ! inr a ! sta sio$port ; get and save port lxi d,baud$ports-data$ports ! dad d ; offset to baud rate port mov a,m ! sta ctc$port ; get and save lxi h,serial$init$tbl jmp stream$out cent$init: lxi h,pio$init$tbl stream$out: mov a,m ! ora a ! rz mov b,a ! inx h ! mov c,m ! inx h outir jmp stream$out ?ci: ; character input mov a,b ! cpi 6 ! jnc null$input ; can't read from centronics ci1: call ?cist ! jz ci1 ; wait for character ready dcr c ! inp a ; get data ani 7Fh ; mask parity ret null$input: mvi a,1Ah ; return a ctl-Z for no device ret ?cist: ; character input status mov a,b ! cpi 6 ! jnc null$status ; can't read from centronics mov l,b ! mvi h,0 ; make device number 16 bits lxi d,data$ports ! dad d ; make pointer to port address mov c,m ! inr c ; get SIO status port inp a ; read from  speed$table db 0,255,255,255,233,208,104,208,104,69,52,35,26,17,13,7 serial$init$tbl db 2 ; two bytes to CTC ctc$port ds 1 ; port address of CTC db 47h ; CTC mode byte speed ds 1 ; baud multiplier db 7 ; 7 bytes to SIO sio$port ds 1 ; port address of SIO db 18h,3,0E1h,4 sio$reg$4 ds 1 db 5,0EAh db 0 ; terminator pio$init$tbl db 2,p$zpio$2b,0Fh,07h db 3,p$zpio$2a,0CFh,0F8h,07h db 0 end onxoff db baud$9600 db 'CRT1 ' ; device 2, CRT port 1 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CRT2 ' ; device 3, CRT port 2 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CRT3 ' ; device 4, CRT port 3 db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'VAX ' ; device 5, LPT port 1 used for VAX interface db mb$in$out+mb$serial+mb$softbaud db baud$9600 db 'CEN ' ; device 6, Centronics parallel printer db mb$output db baud$none db 0 ; table terminatorcsv ; checksum vector else dw 0FFFEh ; checksum vector allocated by endif ; GENCPM if not nul ?asize dw ?alv ; allocation vector else dw 0FFFEh ; alloc vector allocated by GENCPM endif dw 0fffeh,0fffeh,0fffeh ; dirbcb, dtabcb, hash alloc'd ; by GENCPM db 0 ; hash bank if not nul ?csize ?csv ds ?csize ; checksum vector endif if not nul ?asize ?alv ds ?asize ; allocation vector endif endm dpb macro ?psize,?pspt,?trks,?bls,?ndirs,?off,?ncks local ?spt,?bsh,?blm,?exm,?dsm,?drm,?al0,?al1,?cks,?psh,?psm local ?n ;; physical sector mask and physical sector shift ?psh set 0 ?n set ?psize/128 ?psm set ?n-1 rept 8 ?n set ?n/2 if ?n = 0 exitm endif ?psh set ?psh + 1 endm ?spt set ?pspt*(?psize/128) ?bsh set 3 ?n set ?bls/1024 rept 8 ?n set ?n/2 if ?n = 0 exitm endif ?bsh set ?bsh + 1 endm ?blm set ?bls/128-1 ?size set (?trks-?of public @dtbl extrn fdsd0,fdsd1 cseg @dtbl dw fdsd0,fdsd1 dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; drives C-P non-existant end w macro ?secs,?skf,?fsc ;; generate the translate table ?nxtsec set 0 ;;next sector to fill ?nxtbas set 0 ;;moves by one on overflow gcd %?secs,?skf ;; ?gcdn = gcd(?secs,skew) ?neltst set ?secs/?gcdn ;; neltst is number of elements to generate ;; before we overlap previous elements ?nelts set ?neltst ;;counter rept ?secs ;;once for each sector db ?nxtsec+?fsc ?nxtsec set ?nxtsec+?skf if ?nxtsec >= ?secs ?nxtsec set ?nxtsec-?secs endif ?nelts set ?nelts-1 if ?nelts = 0 ?nxtbas set ?nxtbas+1 ?nxtsec set ?nxtbas ?nelts set ?neltst endif endm endm f)*?spt ?dsm set ?size/(?bls/128)-1 ?exm set ?bls/1024 if ?dsm > 255 if ?bls = 1024 .'Error, can''t have this size disk with 1k block size' exitm endif ?exm set ?exm/2 endif ?exm set ?exm-1 ?all set 0 ?n set (?ndirs*32+?bls-1)/?bls rept ?n ?all set (?all shr 1) or 8000h endm ?al0 set high ?all ?al1 set low ?all ?drm set ?ndirs-1 if not nul ?ncks ?cks set ?ncks else ?cks set ?ndirs/4 endif dw ?spt ; 128 byte records per track db ?bsh,?blm ; block shift and mask db ?exm ; extent mask dw ?dsm ; maximum block number dw ?drm ; maximum directory entry number db ?al0,?al1 ; alloc vector for directory dw ?cks ; checksum size dw ?off ; offset for system tracks db ?psh,?psm ; physical sector size shift ; and mask endm ; gcd macro ?m,?n ;; greatest common divisor of m,n ;; produces value gcdn as result ;; (used in sector translate table generation) ?gcdm set ?m ;; Macro Definitions for CP/M3 BIOS Data Structures. ; dtbl - drive table ; dph translate$table, - disk parameter header ; disk$parameter$block, ; checksum$size, (optional) ; alloc$size (optional) ; skew sectors, - skew table ; skew$factor, ; first$sector$number ; dpb physical$sector$size, - disk parameter block ; physical$sectors$per$track, ; number$tracks, ; block$size, ; number$dir$entries, ; track$offset, ; checksum$vec$size (optional) ; Drive Table. Contains 16 one word entries. dtbl macro ?list local ?n ?n set 0 irp ?drv, ?n set ?n+1 dw ?drv endm if ?n > 16 .' Too many drives. Max 16 allowed' exitm endif if ?n < 16 rept (16-?n) dw 0 endm endif endm dph macro ?trans,?dpb,?csize,?asize local ?csv,?alv dw ?trans ; translate table address db 0,0,0,0,0,0,0,0,0 ; BDOS Scratch area db 0 ; media flag dw ?dpb ; disk parameter block if not nul ?csize dw ?;variable for m ?gcdn set ?n ;;variable for n ?gcdr set 0 ;;variable for r rept 65535 ?gcdx set ?gcdm/?gcdn ?gcdr set ?gcdm - ?gcdx*?gcdn if ?gcdr = 0 exitm endif ?gcdm set ?gcdn ?gcdn set ?gcdr endm endm skew macro ?secs,?skf,?fsc ;; generate the translate table ?nxtsec set 0 ;;next sector to fill ?nxtbas set 0 ;;moves by one on overflow gcd %?secs,?skf ;; ?gcdn = gcd(?secs,skew) ?neltst set ?secs/?gcdn ;; neltst is number of elements to generate ;; before we overlap previous elements ?nelts set ?neltst ;;counter rept ?secs ;;once for each sector db ?nxtsec+?fsc ?nxtsec set ?nxtsec+?skf if ?nxtsec >= ?secs ?nxtsec set ?nxtsec-?secs endif ?nelts set ?nelts-1 if ?nelts = 0 ?nxtbas set ?nxtbas+1 ?nxtsec set ?nxtbas ?nelts set ?neltst endif endm endm ; Dump program, reads input file and displays hex data ; org 100h bdos equ 0005h ;dos entry point cons equ 1 ;read console typef equ 2 ;type function printf equ 9 ;buffer print entry brkf equ 11 ;break key function (true if char ready) openf equ 15 ;file open readf equ 20 ;read function ; fcb equ 5ch ;file control block address buff equ 80h ;input disk buffer address ; ; non graphic characters cr equ 0dh ;carriage return lf equ 0ah ;line feed ; ; file control block definitions fcbdn equ fcb+0 ;disk name fcbfn equ fcb+1 ;file name fcbft equ fcb+9 ;disk file type (3 characters) fcbrl equ fcb+12 ;file's current reel number fcbrc equ fcb+15 ;file's record count (0 to 128) fcbcr equ fcb+32 ;current (next) record number (0 to 127) fcbln equ fcb+33 ;fcb length ; ; set up stack lxi h,0 dad sp ; entry stack pointer in hl from the ccp shld oldsp ; set sp to local stack area (restored at finis) lxi sp,stktop ; read and print successive buffers call setup ;set up input file cpi ead the byte at buff+reg a mov e,a ;ls byte of buffer index mvi d,0 ;double precision index to de inr a ;index=index+1 sta ibp ;back to memory ; pointer is incremented ; save the current file address lxi h,buff dad d ; absolute character address is in hl mov a,m ; byte is in the accumulator ora a ;reset carry bit ret ; setup: ;set up file ; open the file for input xra a ;zero to accum sta fcbcr ;clear current record ; lxi d,fcb mvi c,openf call bdos ; 255 in accum if open error ret ; diskr: ;read disk file record push h! push d! push b lxi d,fcb mvi c,readf call bdos pop b! pop d! pop h ret ; ; fixed message area signon: db 'file dump version 2.0$' opnmsg: db cr,lf,'no input file present on disk$' ; variable area ibp: ds 2 ;input buffer pointer oldsp: ds 2 ;entry sp value from ccp ; ; stack area ds 64 ;reserve 32 level stack stktop: ; end  title 'wd1797 w/ Z80 DMA Single density diskette handler' ; CP/M-80 Version 3 -- Modular BIOS ; Disk I/O Module for wd1797 based diskette systems ; Initial version 0.01, ; Single density floppy only. - jrp, 4 Aug 82 dseg ; Disk drive dispatching tables for linked BIOS public fdsd0,fdsd1 ; Variables containing parameters passed by BDOS extrn @adrv,@rdrv extrn @dma,@trk,@sect extrn @dbnk ; System Control Block variables extrn @ermde ; BDOS error mode ; Utility routines in standard BIOS extrn ?wboot ; warm boot vector extrn ?pmsg ; print message @ up to 00, saves & extrn ?pdec ; print binary number in from 0 to 99. extrn ?pderr ; print BIOS disk error header extrn ?conin,?cono ; con in and out extrn ?const ; get console status ; Port Address Equates maclib ports ; CP/M 3 Disk definition macros maclib cpm3 ; Z80 macro library instruction definitions maclib z80 ; common 255 ;255 if file not present jnz openok ;skip if open is ok ; ; file not there, give error message and return lxi d,opnmsg call err jmp finis ;to return ; openok: ;open operation ok, set buffer index to end mvi a,80h sta ibp ;set buffer pointer to 80h ; hl contains next address to print lxi h,0 ;start with 0000 ; gloop: push h ;save line position call gnb pop h ;recall line position jc finis ;carry set by gnb if end file mov b,a ; print hex values ; check for line fold mov a,l ani 0fh ;check low 4 bits jnz nonum ; print line number call crlf ; ; check for break key call break ; accum lsb = 1 if character ready rrc ;into carry jc finis ;don't print any more ; mov a,h call phex mov a,l call phex nonum: inx h ;to next line number mvi a,' ' call pchar mov a,b call phex jmp gloop ; finis: ; end of dump call crlf lhld oldsp sphl ; stack pointer contains ccp's stack location ret ;to the ccp ; ; ; subroutines ; break: ;check b ; ECHOVERS RSX pstring equ 9 ; string print function cr equ 0dh lf equ 0ah ; ; RSX PREFIX STRUCTURE ; db 0,0,0,0,0,0 ; room for serial number jmp ftest ; begin of program next db 0c3H ; jump dw 0 ; next module in line prev: dw 0 ; previous module remov: db 0ffh ; remove flag set nonbnk: db 0 db 'ECHOVERS' space: ds 3 ftest: ; is this function 12? mov a,c cpi 12 jz begin ; yes - intercept jmp next ; some other function begin: lxi h,0 dad sp ;save stack shld ret$stack lxi sp,loc$stack mvi c,pstring lxi d,test$msg ; print message call next ; call BDOS lhld ret$stack ; restore user stack sphl lxi h,0031h ; return version number = 0031h ret test$msg: db cr,lf,'**** ECHOVERS **** $' ret$stack: dw 0 ds 32 ; 16 level stack loc$stack: end l stack stktop: ; end control characters cr equ 13 lf equ 10 bell equ 7 ; Extended Disk Parameter Headers (XPDHs) dw fd$write dw fd$read dw fd$login dw fd$init0 db 0,0 ; relative drive zero fdsd0 dph trans,dpbsd,16,31 dw fd$write dw fd$read dw fd$login dw fd$init1 db 1,0 ; relative drive one fdsd1 dph trans,dpbsd,16,31 cseg ; DPB must be resident dpbsd dpb 128,26,77,1024,64,2 dseg ; rest is banked trans skew 26,6,1 ; Disk I/O routines for standardized BIOS interface ; Initialization entry point. ; called for first time initialization. fd$init0: lxi h,init$table fd$init$next: mov a,m ! ora a ! rz mov b,a ! inx h ! mov c,m ! inx h outir jmp fd$init$next fd$init1: ; all initialization done by drive 0 ret init$table db 4,p$zpio$1A db 11001111b, 11000010b, 00010111b,11111111b db 4,p$zpio$1B db 11001111b, 11011101b, 00010111b,11111111b db 0 fd$login: ; This entry is called when a logical drive is about to ; be logreak key (actually any key will do) push h! push d! push b; environment saved mvi c,brkf call bdos pop b! pop d! pop h; environment restored ret ; pchar: ;print a character push h! push d! push b; saved mvi c,typef mov e,a call bdos pop b! pop d! pop h; restored ret ; crlf: mvi a,cr call pchar mvi a,lf call pchar ret ; ; pnib: ;print nibble in reg a ani 0fh ;low 4 bits cpi 10 jnc p10 ; less than or equal to 9 adi '0' jmp prn ; ; greater or equal to 10 p10: adi 'a' - 10 prn: call pchar ret ; phex: ;print hex char in reg a push psw rrc rrc rrc rrc call pnib ;print nibble pop psw call pnib ret ; err: ;print error message ; d,e addresses message ending with "$" mvi c,printf ;print buffer function call bdos ret ; ; gnb: ;get next byte lda ibp cpi 80h jnz g0 ; read another buffer ; ; call diskr ora a ;zero value if read ok jz g0 ;for another byte ; end of data, return with carry set for eof stc ret ; g0: ;rged into for the purpose of density determination. ; It may adjust the parameters contained in the disk ; parameter header pointed at by ret ; we have nothing to do in ; simple single density only environment. ; disk READ and WRITE entry points. ; these entries are called with the following arguments: ; relative drive number in @rdrv (8 bits) ; absolute drive number in @adrv (8 bits) ; disk transfer address in @dma (16 bits) ; disk transfer bank in @dbnk (8 bits) ; disk track address in @trk (16 bits) ; disk sector address in @sect (16 bits) ; pointer to XDPH in ; they transfer the appropriate data, perform retries ; if necessary, then return an error code in fd$read: lxi h,read$msg ; point at " Read " mvi a,88h ! mvi b,01h ; 1797 read + Z80DMA direction jmp rw$common fd$write: lxi h,write$msg ; point at " Write " mvi a,0A8h ! mvi b,05h ; 1797 write + Z80DMA direction ; jmp wr$common rw$common: ; seek to cight need to seek dcr c ! jnz retry$operation ; suppress error message if BDOS is returning errors to application... lda @ermde ! cpi 0FFh ! jz hard$error ; Had permanent error, print message like: ; BIOS Err on d: T-nn, S-mm, , Retry ? call ?pderr ; print message header lhld operation$name ! call ?pmsg ; last function ; then, messages for all indicated error bits lda disk$status ; get status byte from last error lxi h,error$table ; point at table of message addresses errm1: mov e,m ! inx h ! mov d,m ! inx h ; get next message address add a ! push psw ; shift left and push residual bits with status xchg ! cc ?pmsg ! xchg ; print message, saving table pointer pop psw ! jnz errm1 ; if any more bits left, continue lxi h,error$msg ! call ?pmsg ; print ", Retry (Y/N) ? " call u$conin$echo ; get operator response cpi 'Y' ! jz more$retries ; Yes, then retry 10 more times hard$error: ; otherwise, mvi a,1 ! ret ; return hartus ds 1 ; last error status code for messages select$table db 0001$0000b,0010$0000b ; for now use drives C and D ; error message components read$msg db ', Read',0 write$msg db ', Write',0 operation$name dw read$msg ; table of pointers to error message strings ; first entry is for bit 7 of 1797 status byte error$table dw b7$msg dw b6$msg dw b5$msg dw b4$msg dw b3$msg dw b2$msg dw b1$msg dw b0$msg b7$msg db ' Not ready,',0 b6$msg db ' Protect,',0 b5$msg db ' Fault,',0 b4$msg db ' Record not found,',0 b3$msg db ' CRC,',0 b2$msg db ' Lost data,',0 b1$msg db ' DREQ,',0 b0$msg db ' Busy,',0 error$msg db ' Retry (Y/N) ? ',0 ; command string for Z80DMA device for normal operation dma$block db 0C3h ; reset DMA channel db 14h ; channel A is incrementing memory db 28h ; channel B is fixed port address db 8Ah ; RDY is high, CE/ only, stop on EOB db 79h ; program all of ch. A, xfer B->A (temp) zdma$dma ds 2 ; starting DMA address orrect track (if necessary), ; initialize DMA controller, ; and issue 1797 command. shld operation$name ; save message for errors sta disk$command ; save 1797 command mov a,b ! sta zdma$direction ; save Z80DMA direction code lhld @dma ! shld zdma$dma ; get and save DMA address lda @rdrv ! mov l,a ! mvi h,0 ; get controller-relative disk drive lxi d,select$table ! dad d ; point to select mask for drive mov a,m ! sta select$mask ; get select mask and save it out p$select ; select drive more$retries: mvi c,10 ; allow 10 retries retry$operation: push b ; save retry counter lda select$mask ! lxi h,old$select ! cmp m mov m,a jnz new$track ; if not same drive as last, seek lda @trk ! lxi h,old$track ! cmp m mov m,a jnz new$track ; if not same track, then seek in p$fdmisc ! ani 2 ! jnz same$track ; head still loaded, we are OK new$track: ; or drive or unloaded head means we should . . . call check$seek ; . . read address and seek if wrong trackd error to BDOS cancel: ; here to abort job jmp ?wboot ; leap directly to warmstart vector ; subroutine to seek if on wrong track ; called both to set up new track or drive check$seek: push b ; save error counter call read$id ; try to read ID, put track in jz id$ok ; if OK, we're OK call step$out ; else step towards Trk 0 call read$id ; and try again jz id$ok ; if OK, we're OK call restore ; else, restore the drive mvi b,0 ; and make like we are at track 0 id$ok: mov a,b ! out p$fdtrack ; send current track to track port lda @trk ! cmp b ! pop b ! rz ; if its desired track, we are done out p$fddata ; else, desired track to data port mvi a,00011010b ; seek w/ 10 ms. steps jmp exec$command step$out: mvi a,01101010b ; step out once at 10 ms. jmp exec$command restore: mvi a,00001011b ; restore at 15 ms ; jmp exec$command exec$command: ; issue 1797 command, and wait for IREQ ; return status out p$fdc dw 128-1 ; 128 byte sectors in SD db 85h ; xfer byte at a time, ch B is 8 bit address db p$fddata ; ch B port address (1797 data port) db 0CFh ; load B as source register db 05h ; xfer A->B db 0CFh ; load A as source register zdma$direction ds 1 ; either A->B or B->A db 0CFh ; load final source register db 87h ; enable DMA channel dmab$length equ $-dma$block read$id$block db 0C3h ; reset DMA channel db 14h ; channel A is incrementing memory db 28h ; channel B is fixed port address db 8Ah ; RDY is high, CE/ only, stop on EOB db 7Dh ; program all of ch. A, xfer A->B (temp) dw id$buffer ; starting DMA address dw 6-1 ; Read ID always xfers 6 bytes db 85h ; byte xfer, ch B is 8 bit address db p$fddata ; ch B port address (1797 data port) db 0CFh ; load dest (currently source) register db 01h ; xfer B->A db 0CFh ; load source register db 87h ; enable DMA channel length$id$dmab equ $-read$id$block cseg ; easier to put ID buffer in common id$ lxi b,16667 ; 100 ms / (24 t states*250 ns) spin$loop: ; wait for head/seek settling dcx b mov a,b ! ora c jnz spin$loop same$track: lda @trk ! out p$fdtrack ; give 1797 track lda @sect ! out p$fdsector ; and sector lxi h,dma$block ; point to dma command block lxi b,dmab$length*256 + p$zdma ; command block length and port address outir ; send commands to Z80 DMA in p$bankselect ; get old value of bank select port ani 3Fh ! mov b,a ; mask off DMA bank and save lda @dbnk ! rrc ! rrc ; get DMA bank to 2 hi-order bits ani 0C0h ! ora b ; merge with other bank stuff out p$bankselect ; and select the correct DMA bank lda disk$command ; get 1797 command call exec$command ; start it then wait for IREQ and read status sta disk$status ; save status for error messages pop b ; recover retry counter ora a ! rz ; check status and return to BDOS if no error ani 0001$0000b ; see if record not found error cnz check$seek ; if a record not found, we mmnd ; send 1797 command wait$IREQ: ; spin til IREQ in p$fdint ! ani 40h ! jz wait$IREQ in p$fdstat ; get 1797 status and clear IREQ ret read$id: lxi h,read$id$block ; set up DMA controller lxi b,length$id$dmab*256 + p$zdma ; for READ ADDRESS operation outir mvi a,11000100b ; issue 1797 read address command call exec$command ; wait for IREQ and read status ani 10011101b ; mask status lxi h,id$buffer ! mov b,m ; get actual track number in ret ; and return with Z flag true for OK u$conin$echo: ; get console input, echo it, and shift to upper case call ?const ! ora a ! jz u$c1 ; see if any char already struck call ?conin ! jmp u$conin$echo ; yes, eat it and try again u$c1: call ?conin ! push psw mov c,a ! call ?cono pop psw ! cpi 'a' ! rc sui 'a'-'A' ; make upper case ret disk$command ds 1 ; current wd1797 command select$mask ds 1 ; current drive select code old$select ds 1 ; last drive selected old$track ds 1 ; last track seeked to disk$stabuffer ds 6 ; buffer to hold ID field ; track ; side ; sector ; length ; CRC 1 ; CRC 2 end 797 data port) db 0CFh ; load B as source register db 05h ; xfer A->B db 0CFh ; load A as source register zdma$direction ds 1 ; either A->B or B->A db 0CFh ; load final source register db 87h ; enable DMA channel dmab$length equ $-dma$block read$id$block db 0C3h ; reset DMA channel db 14h ; channel A is incrementing memory db 28h ; channel B is fixed port address db 8Ah ; RDY is high, CE/ only, stop on EOB db 7Dh ; program all of ch. A, xfer A->B (temp) dw id$buffer ; starting DMA address dw 6-1 ; Read ID always xfers 6 bytes db 85h ; byte xfer, ch B is 8 bit address db p$fddata ; ch B port address (1797 data port) db 0CFh ; load dest (currently source) register db 01h ; xfer B->A db 0CFh ; load source register db 87h ; enable DMA channel length$id$dmab equ $-read$id$block cseg ; easier to put ID buffer in common id$TIME-STAMPS ~OPTIONS -EXAMPLES ^DRIVES 4SETDEF MEXAMPLES mSHOW WEXAMPLES pSID COMMANDS bEXAMPLES eUTILITIES uSUBMIT 4SUBFILE EXECUTE  PROFILE.SUB  TYPE *EXAMPLES GUSER IEXAMPLES ZXREF $ $ )`$ j" ///1commands CP/M 3 Command Format: A>COMMAND {command tail} A CP/M 3 command line is composed of a command, an optional command tail, and a carriage return. The command is the name or filename of a program to be executed. The optional command tail can consist of a drive specification, one or more file specifications, and some options or parameters. ///2conventions COMMAND CONVENTIONS The following special symbols define command syntax. {} surrounds an optional item. | separates alternative items in a command line. indicates on a new line; updates the command line buffer. CTRL-S stops screen scrolling. CTRL-U updates the command line buffer to contain the characters to the left of the cursor; deletes current line. CTRL-W recalls previous command line if current line is empty; otherwise moves cursor to end of line. CTRL-J,-M,-R,-U and RETURN update the command line buffer for recall with CTRL-W. Banked system only. CTRL-X deletes all characters to the left of the cursor. ///1COPYSYS Syntax: COPYSYS Explanation: COPYSYS copies the CP/M 3 system from a CP/M 3 system diskette to another diskette. The new diskette must have the same format as the original system diskette. Example: A>COPYSYS ///1DATE Syntax: DATE {CONTINUOUS} DATE {time-specification} DATE SET Explanation: The DATE command lets you display and se a carriage return. ^ indicates the Control Key. n substitute a number for n. s substitute a string (group) of characters for s. o substitute an option or option list for o. [] type square brackets to enclose an option list. () type parens to enclose a range of options within an option list. RW Read-Write attribute - opposite of RO RO Read-Only attribute - opposite of RW SYS System attribute - opposite of DIR DIR Directory attribute - opposite of SYS ... preceding element can be repeated as many times as desired. * wildcard: replaces all or part of a filename and/or filetype. ? wildcard: replaces any single character in the same position of a filename and/or filetype. ///1cntrlchars Control Character Function CTRL-A moves cursor one character to the left. Banked system only. CTRL-B moves cursor from beginning to end of command line and back without affectingt the date and time of day. ///2Examples A>DATE Displays the current date and time. A>DATE C Displays the date and time continuously. A>DATE 08/14/82 10:30:0 Sets the date and time. A>DATE SET Prompts for date and time entries. ///1DEVICE Syntax: DEVICE { NAMES | VALUES | physical-dev | logical-dev} DEVICE logical-dev=physical-dev {option} {,physical-dev {option},...} DEVICE logical-dev = NULL DEVICE physical-dev {option} DEVICE CONSOLE [ PAGE | COLUMNS = columns | LINES = lines] Explanation: DEVICE displays current logical device assignments and physical device names. DEVICE assigns logical devices to peripheral devices attached to the computer. DEVICE also sets the communications protocol and speed of a peripheral device, and displays or sets the current console screen size. ///2OptCOMMANDS CONVENTIONS 3CNTRLCHARS COPYSYS $VDATE &dEXAMPLES (3DEVICE *:OPTIONS 0EXAMPLES 5 DIR ?TBUILT-IN BVEXAMPLES FWITHOPTIONS N)OPTIONS Q~EXAMPLES bjDUMP kED lKCOMMANDS n7EXAMPLES kERASE mOPTION pEXAMPLES lFILESPEC GENCOM eOPTIONS EXAMPLES |GET OPTIONS uEXAMPLES HELP jHEXCOM ZINITDIR LIB *OPTIONS GMODIFIERS *EXAMPLES 7LINK OPTIONS oEXAMPLES MAC EXAMPLES \OPTIONS $PATCH ]PIP (COPY) CEXAMPLES 6OPTIONS &)PUT /'OPTIONS 5MEXAMPLES >-RENAME D9EXAMPLES GRMAC NvOPTIONS PREXAMPLE T\SAVE VzEXAMPLE ZSET `LABEL c_EXAMPLES djPASSWORDS fbMODES i#ATTRIBUTES o&EXAMPLES wDEFAULT |Y command. Banked system only. CTRL-C stops executing program when entered at the system prompt or after CTRL-S. CTRL-E forces a physical carriage return without sending command to CP/M 3. CTRL-F moves cursor one character to the right. Banked system only. CTRL-G deletes character at current cursor position if in the middle of a line. Banked system only. CTRL-I same as the TAB key. CTRL-H delete character to the left of cursor. CTRL-J moves cursor to the left of the command line and sends command to CP/M 3. Line feed, has same effect as carriage return. CTRL-K deletes character at cursor and all characters to the right. CTRL-M same as carriage return. CTRL-P echoes console output to the list device. CTRL-Q restarts screen scrolling after a CTRL-S. CTRL-R retypes the characters to the left of the cursor ions [ XON | NOXON | baud-rate ] XON refers to the XON/XOFF communications protocol. NOXON indicates no protocol and the computer sends data to the device whether or not the device is ready to receive it. baud-rate is the speed of the device. The system accepts the following baud rates: 50 75 110 134 150 300 600 1200 1800 2400 3600 4800 7200 9600 19200 ///2Examples A>DEVICE Displays the physical devices and current assignments of the logical devices in the system. A>DEVICE NAMES Lists the physical devices with a summary of the device characteristics. A>DEVICE VALUES Displays the current logical device assignments. A>DEVICE CRT Displays the atTIME-STAMPS ~OPTIONS -EXAMPLES ^DRIVES 4SETDEF MEXAMPLES mSHOW WEXAMPLES pSID COMMANDS bEXAMPLES eUTILITIES uSUBMIT 4SUBFILE EXECUTE  PROFILE.SUB  TYPE *EXAMPLES GUSER IEXAMPLES ZXREF $ $ )`$ j" ///1commands CP/M 3 Command Format: A>COMMAND {command tail} A CP/M 3 command line is composed of a command, an optional command tail, and a carriage return. The command is the name or filename of a program to be executed. The optional command tail can consist of a drive specification, one or more file specifications, and some options or parameters. ///2conventions COMMAND CONVENTIONS The following special symbols define command syntax. {} surrounds an optional item. | separates alternative items in a command line. indicates on a new line; updates the command line buffer. CTRL-S stops screen scrolling. CTRL-U updates the command line buffer to contain the characters to the left of the cursor; deletes current line. CTRL-W recalls previous command line if current line is empty; otherwise moves cursor to end of line. CTRL-J,-M,-R,-U and RETURN update the command line buffer for recall with CTRL-W. Banked system only. CTRL-X deletes all characters to the left of the cursor. ///1COPYSYS Syntax: COPYSYS Explanation: COPYSYS copies the CP/M 3 system from a CP/M 3 system diskette to another diskette. The new diskette must have the same format as the original system diskette. Example: A>COPYSYS ///1DATE Syntax: DATE {CONTINUOUS} DATE {time-specification} DATE SET Explanation: The DATE command lets you display and setributes of the physical device CRT. A>DEVICE CON Displays the assignment of the logical device CON: A>DEVICE CONOUT:=LPT,CRT Assigns the system console output (CONOUT:) to the printer (LPT) and the screen (CRT). A>DEVICE AUXIN:=CRT2 [XON,9600] Assigns the auxiliary logical input device (AUXIN:) to the physical device CRT using protocol XON/XOFF and sets the transmission rate for the device at 9600. A>DEVICE LST:=NULL Disconnects the list output logical device (LST:). A>DEVICE LPT [XON,9600] Sets the XON/XOFF protocol for the physical device LPT and sets the transmission speed at 9600. A>DEVICE CONSOLE [PAGE] Displays the current console page width in columns and length in lines. A>DEVICE CONSOLE [COLUMNS=40 LINES=16] Sets the screen size to 40 columns and 16 lines. ///1DIR The DIR command displays the nam a carriage return. ^ indicates the Control Key. n substitute a number for n. s substitute a string (group) of characters for s. o substitute an option or option list for o. [] type square brackets to enclose an option list. () type parens to enclose a range of options within an option list. RW Read-Write attribute - opposite of RO RO Read-Only attribute - opposite of RW SYS System attribute - opposite of DIR DIR Directory attribute - opposite of SYS ... preceding element can be repeated as many times as desired. * wildcard: replaces all or part of a filename and/or filetype. ? wildcard: replaces any single character in the same position of a filename and/or filetype. ///1cntrlchars Control Character Function CTRL-A moves cursor one character to the left. Banked system only. CTRL-B moves cursor from beginning to end of command line and back without affectingt the date and time of day. ///2Examples A>DATE Displays the current date and time. A>DATE C Displays the date and time continuously. A>DATE 08/14/82 10:30:0 Sets the date and time. A>DATE SET Prompts for date and time entries. ///1DEVICE Syntax: DEVICE { NAMES | VALUES | physical-dev | logical-dev} DEVICE logical-dev=physical-dev {option} {,physical-dev {option},...} DEVICE logical-dev = NULL DEVICE physical-dev {option} DEVICE CONSOLE [ PAGE | COLUMNS = columns | LINES = lines] Explanation: DEVICE displays current logical device assignments and physical device names. DEVICE assigns logical devices to peripheral devices attached to the computer. DEVICE also sets the communications protocol and speed of a peripheral device, and displays or sets the current console screen size. ///2OptCOMMANDS CONVENTIONS 3CNTRLCHARS COPYSYS $VDATE &dEXAMPLES (3DEVICE *:OPTIONS 0EXAMPLES 5 DIR ?TBUILT-IN BVEXAMPLES FWITHOPTIONS N)OPTIONS Q~EXAMPLES bjDUMP kED lKCOMMANDS n7EXAMPLES kERASE mOPTION pEXAMPLES lFILESPEC GENCOM eOPTIONS EXAMPLES |GET OPTIONS uEXAMPLES HELP jHEXCOM ZINITDIR LIB *OPTIONS GMODIFIERS *EXAMPLES 7LINK OPTIONS oEXAMPLES MAC EXAMPLES \OPTIONS $PATCH ]PIP (COPY) CEXAMPLES 6OPTIONS &)PUT /'OPTIONS 5MEXAMPLES >-RENAME D9EXAMPLES GRMAC NvOPTIONS PREXAMPLE T\SAVE VzEXAMPLE ZSET `LABEL c_EXAMPLES djPASSWORDS fbMODES i#ATTRIBUTES o&EXAMPLES wDEFAULT |Y command. Banked system only. CTRL-C stops executing program when entered at the system prompt or after CTRL-S. CTRL-E forces a physical carriage return without sending command to CP/M 3. CTRL-F moves cursor one character to the right. Banked system only. CTRL-G deletes character at current cursor position if in the middle of a line. Banked system only. CTRL-I same as the TAB key. CTRL-H delete character to the left of cursor. CTRL-J moves cursor to the left of the command line and sends command to CP/M 3. Line feed, has same effect as carriage return. CTRL-K deletes character at cursor and all characters to the right. CTRL-M same as carriage return. CTRL-P echoes console output to the list device. CTRL-Q restarts screen scrolling after a CTRL-S. CTRL-R retypes the characters to the left of the cursor ions [ XON | NOXON | baud-rate ] XON refers to the XON/XOFF communications protocol. NOXON indicates no protocol and the computer sends data to the device whether or not the device is ready to receive it. baud-rate is the speed of the device. The system accepts the following baud rates: 50 75 110 134 150 300 600 1200 1800 2400 3600 4800 7200 9600 19200 ///2Examples A>DEVICE Displays the physical devices and current assignments of the logical devices in the system. A>DEVICE NAMES Lists the physical devices with a summary of the device characteristics. A>DEVICE VALUES Displays the current logical device assignments. A>DEVICE CRT Displays the atPPY.DAT if the file is in user 2 on drive C. 4A>DIR *.BAS Displays all DIR files with filetype BAS in user 4 on drive A. B3>DIR X*.C?D Displays all DIR files in user 3 on drive B whose filename begins with the letter X, and whose three character filetype contains the first character C and last character D. A>DIRS Displays all files for user 0 on drive A that have the system (SYS) attribute. A>DIRS *.COM Displays all SYS files with filetype COM on drive A in user 0. A command (.COM) file in user 0 with the system attribute can be accessed from any user number on that drive, and from any drive in the search chain (see SETDEF). ///2withOptions Syntax: DIR {d:} [options] DIR {filespec} {filespec} ... [options] Explanation: The DIR command with options is an enhanced version of the DIR built-in command and di bytes). SYS displays only the files that have the SYS attribute. USER=ALL displays all files in all user numbers for the default or specified drive. USER=n displays the files in the user number specified by n. USER=(0,1,...,15) displays files under the user numbers specified. ///3Examples A>DIR C: [FULL] Displays full set of characteristics for all files in user 0 on drive C. A>DIR C: [DATE] Lists the files on drive C and their dates. A>DIR D: [RW,SYS] Displays all files in user 0 on drive D with Read-Write and System attributes. 3A>DIR [USER=ALL, DRIVE=ALL] Displays all the files in all user numbers (0-15) in all on- line drives. B6>DIR [exclude] *.DAT Lists all the files on drive B in user 6 that do not have a filetype of .DAT. 3B>DIR [SIZE] *.PLI *.COM *.ASM Displays all the files of type PLI, COM, and AStributes of the physical device CRT. A>DEVICE CON Displays the assignment of the logical device CON: A>DEVICE CONOUT:=LPT,CRT Assigns the system console output (CONOUT:) to the printer (LPT) and the screen (CRT). A>DEVICE AUXIN:=CRT2 [XON,9600] Assigns the auxiliary logical input device (AUXIN:) to the physical device CRT using protocol XON/XOFF and sets the transmission rate for the device at 9600. A>DEVICE LST:=NULL Disconnects the list output logical device (LST:). A>DEVICE LPT [XON,9600] Sets the XON/XOFF protocol for the physical device LPT and sets the transmission speed at 9600. A>DEVICE CONSOLE [PAGE] Displays the current console page width in columns and length in lines. A>DEVICE CONSOLE [COLUMNS=40 LINES=16] Sets the screen size to 40 columns and 16 lines. ///1DIR The DIR command displays the namsplays your files in a variety of ways. DIR can search for files on any or all drives, for any or all user numbers. One or two letters is sufficient to identify an option. You need not type the right hand square bracket. ///3Options Option Function ATT displays the file attributes. DATE displays date and time stamps of files. DIR displays only files that have the DIR attribute. DRIVE=ALL displays files on all on-line drives. DRIVE=(A,B,C,...,P) displays files on the drives specified. DRIVE=d displays files on the drive specified by d. EXCLUDE displays files that DO NOT MATCH the files specified in the command line. FF sends an initial form feed to the printer device if the printer has been activated by CTRL-P. FULL shows the name, size, number of 128-byte records, and attributes of the files. If there M in user 3 on drive B in size display format. A>DIR [drive=all user=all] TESTFILE.BOB DIR displays the filename TESTFILE.BOB if it is found on any drive in any user number. A>DIR [size,rw] D: DIR lists each Read-Write file that resides on Drive D, with its size in kilobytes. Note that D: is equivalent to D:*.*. ///1DUMP Syntax: DUMP filespec Explanation: DUMP displays the contents of a file in hexadecimal and ASCII format. Example: A>DUMP ABC.TEX ///1ed Format: ED input-filespec {d:|output-filespec} Explanation: Character file editor. To redirect or rename the new version of the file specify the destination drive or destination filespec. ///2commands ED Command Summary Command Action nA append n lines from original file to memory buffer 0A append file until buffer is one hes of files and the characteristics associated with the files. The DIR command has three distinct references: DIR DIRS DIR with Options DIR and DIRS are built-in utilities. DIR with Options is a transient utility and must be loaded into memory from the disk. ///2Built-in Syntax: DIR {d:} DIR {filespec} DIRS {d:} DIRS {filespec} Explanation: The DIR and DIRS Built-in commands display the names of files cataloged in the directory of an on-line disk. DIR lists the names of files in the current user number that have the Directory (DIR) attribute. DIR accepts the * and ? wildcards in the file specification. ///3Examples A>DIR Displays all files in user 0 on drive A that have the Directory attribute. A>DIR B: Displays all DIR files in user 0 on drive B. 2A>DIR C:ZIPPY.DAT Displays the name ZIis a directory label on the drive, DIR shows the password protection mode and the time stamps. If there is no directory label, DIR displays two file entries on a line, omitting the password and time stamp columns. The display is alphabetically sorted. (See SET for a description of file attributes, directory labels, passwords and protection modes.) LENGTH=n displays n lines of printer output before inserting a table heading. n is a number between 5 and 65536. MESSAGE displays the names of drives and user numbers DIR is searching. NOSORT displays files in the order it finds them on the disk. RO displays only the files that have the Read-Only attribute. RW displays only the files that are set to Read-Write. SIZE displays the filename and size in kilobytes (1024 alf full #A append file until buffer is full (or end of file) B, -B move CP to the beginning (B) or bottom (-B) of buffer nC, -nC move CP n characters forward (C) or back (-C) through buffer nD, -nD delete n characters before (-D) or from (D) the CP E save new file and return to CP/M-86 Fstring{^Z} find character string H save new file, reedit, use new file as original file I enter insert mode Istring{^Z} insert string at CP Jsearch_str^Zins_str^Zdel_to_str juxtapose strings nK, -nK delete (kill) n lines from the CP nL, -nL, 0L move CP n lines nMcommands execute commands n times n, -n move CP n lines and display that line n: move to line n :ncommand execute command through line n Nstring{^Z} extended find string O return to original file nP, -nP lename that begins with MY is displayed with a question mark for confirmation. Type Y to erase the file displayed, N to keep the file. A>ERA B:*.* Confirm (Y/N)?Y All files on drive B are removed from the disk. ///1filespec FILESPEC FORMAT CP/M 3 identifies every file by its unique file specification, which can consist of four parts: the drive specification, the filename, the filetype and the password. The term "filespec" indicates any valid combination of the four parts of a file specification, all separated by their appropriate delimiters. A colon must follow a drive letter. A period must precede a filetype. A semicolon must precede a password. The symbols and rules for the parts of a file specification follow: d: drivespec optional single alpha character (A-P) filename filename 1-8 letters and/or numbers typ  GENCOM takes MYPROG.COM, strips off the header and deletes all attached RSX's to restore it to its original COM format. A>GENCOM MYPROG PROG1 PROG2 GENCOM looks at the already-GENCOMed file MYPROG.COM to see if PROG1.RSX and PROG2.RSX are already attached RSX files in the module. If either one is already attached, GENCOM replaces it with the new RSX module. Otherwise, GENCOM appends the specified RSX files to the COM file. ///1GET Syntax: GET {CONSOLE INPUT FROM} FILE filespec{[{ECHO|NO ECHO} | SYSTEM]} GET {CONSOLE INPUT FROM} CONSOLE Explanation: GET directs the system to take console input from a file for the next system command or user program entered at the console. Console input is taken from a file until the program terminates. If the file is exhausted before program input is terminated, the program looks for subsequent input from the consol move CP 23 lines forward and display 23 lines at console Q abandon new file, return to CP/M-86 R{^Z} read X$$$$$$$.LIB file into buffer Rfilespec{^Z} read filespec into buffer Sdelete string^Zinsert string substitute string nT, -nT, 0T type n lines U, -U upper-case translation V, -V line numbering on/off 0V display free buffer space nW write n lines to new file 0W write until buffer is half empty nX write or append n lines to X$$$$$$$.LIB nXfilespec{^Z} write n lines to filespec; append if previous xcommand applied to same file 0x{^Z} delete file X$$$$$$$.LIB 0xfilespec{^Z} delete filespec nZ wait n seconds Note: CP points to the current character being referenced in the edit buffer. Use {^Z} to separate multiple commands on the same line. ///2Examples A>ED TEST.filetype optional 0-3 letters and/or numbers password password optional 0-8 letters and/or numbers Valid combinations of the elements of a CP/M 3 file specification are: filename d:filename filename.typ d:filename.typ filename;password d:filename;password filename.typ;password d:filename.typ;password If you do not include a drive specifier, CP/M 3 automatically uses the default drive. Some CP/M 3 commands accept wildcard (* and ?) characters in the filename and/or filetype parts of the command tail. A wildcard in the command line can in one command reference many matching files on the default or specified user number and drive. (See Commands). ///1GENCOM Syntax: GENCOM {COM-filespec} {RSX-filespec} ... {[LOADER | NULL | SCB=(offset,value)]} Explanation: Thee. If the program terminates before exhausting all its input, the system reverts back to the console for console input. With the SYSTEM option, the system immediately goes to the specified file for console input. The system reverts to the console for input when it reaches the end of file. Re-direct the system to the console for console input with the GET CONSOLE INPUT FROM CONSOLE command as a command line in the input file. ///2Options ECHO specifies that input is echoed to the console. This is the default option. NO ECHO specifies that file input is not echoed to the console. The program output and the system prompts are not affected by this option and are still echoed to the console. SYSTEM specifies that all system input is immediately taken from the disk file specified in the command line. GET takes system and program inDAT A>ED TEST.DAT B: A>ED TEST.DAT TEST2.DAT A>ED TEST.DAT B:TEST2.DAT ///1erase Syntax: ERASE {filespec} {[CONFIRM]} Explanation: The ERASE command removes one or more files from the directory of a disk. Wildcard characters are accepted in the filespec. Directory and data space are automatically reclaimed for later use by another file. The ERASE command can be abbreviated to ERA. ///2Option [CONFIRM] option informs the system to prompt for verification before erasing each file that matches the filespec. CONFIRM can be abbreviated to C. ///2Examples A>ERASE X.PAS Removes the file X.PAS from the disk in drive A. A>ERA *.PRN Confirm (Y/N)?Y All files with the filetype PRN are removed from the disk in drive A. B>ERA A:MY*.* [CONFIRM] Each file on drive A with a fi GENCOM command creates a special COM file with attached RSX files. The GENCOM command can also restore a previously GENCOMed file to the original COM file without the header and RSX's. GENCOM can also attach header records to COM files. ///2Options LOADER sets a flag to keep the program loader active. NULL indicates that only RSX files are specified. GENCOM creates a dummy COM file for the RSX files. The output COM filename is taken from the filename of the first RSX-filespec. SCB=(offset,value) sets the System Control Block from the program by using the hex values specified by (offset,value). ///2Examples A>GENCOM MYPROG PROG1 PROG2 Generates a new COM file MYPROG.COM with attached RSX's PROG1 and PROG2. A>GENCOM PROG1 PROG2 [NULL] Creates a COM file PROG1.COM with RSX's PROG1 and PROG2. A>GENCOM MYPROG put from the file until the file is exhausted or until GET reads a GET console command from the file. ///2Examples A>GET FILE XINPUT A>MYPROG Tells the system to activate the GET utility. Since SYSTEM is not specified, the system reads the next input line from the console and executes MYPROG. If MYPROG program requires console input, it is taken from the file XINPUT. When MYPROG terminates, the system reverts back to the console for console input. A>GET FILE XIN2 [SYSTEM] Immediately directs the system to get subsequent console input from file XIN2 because it includes the SYSTEM option. The system reverts back to the console for console input when it reaches the end of file in XIN2. Or XIN2 may redirect the system back to the console if it contains a GET CONSOLE command. A>GET CONSOLE Tells th directory to allow date and time stamping of files on that disk. INITDIR can also recover time/date directory space. Example: A>INITDIR C: INITDIR WILL ACTIVATE TIME-STAMPS FOR SPECIFIED DRIVE. Do you want to re-format the directory on C: (Y/N)?Y ///1LIB Syntax: LIB filespec{[I|M|P|D]} LIB filespec{[I|M|P]}=filespec{modifier} {,filespec{modifier} ... } Explanation: A library is a file that contains a collection of object modules. Use the LIB utility to create libraries, and to append, replace, select or delete modules from an existing library. Use LIB to obtain information about the contents of library files. LIB creates and maintains library files that contain object modules in Microsoft REL file format. These modules are produced by Digital Research's relocatable macro-assembler program, RMAC, or any other language translator that pruduces modules E2.REL from FILE3.REL, omitting MODA which is a module in FILE3.REL. A>LIB FILE6=FILE5 Creates FILE6.REL from FILE5.REL, FILEB.REL replaces MODA. A>LIB FILE6=FILE5 Module THISNAME is in FILE5.REL. When LIB creates FILE6.REL from FILE5.REL the file THISNAME.REL replaces the similarly named module THISNAME. A>LIB FILE1[I]=B:FILE2(PLOTS,FIND,SEARCH-DISPLAY) Creates FILE1.IRL on drive A from the selected modules PLOTS, FIND, and modules SEARCH through the module DISPLAY, in FILE2.REL on drive B. ///1LINK Syntax: LINK d:{filespec,{[options]}=}filespec{[options]}{,...} Explanation: LINK combines relocatable object modules such as those produced by RMAC and PL/I-80 into a .COM file ready for execution. Relocatable files can contain external references and publics. Relocatable files can reference modules ine system to get console input from the console. This command may be used in a file (previously specified in a GET FILE command), which is already being read by the system for console input. It is used to re-direct the console input back to the console before the end-of-file is reached. ///1HELP Syntax: HELP {topic} {subtopic1 ... subtopic8} {[NOPAGE|LIST]} Explanation: HELP displays a list of topics and provides summarized information for CP/M 3 commands. HELP topic displays information about that topic. HELP topic subtopic displays information about that subtopic. One or two letters is enough to identify the topics. After HELP displays information for your topic, it displays the special prompt HELP> on your screen, followed by a list of subtopics. - Enter ? to display list of main topics. - Enter a period and subtopic name to access subtopics. - in Microsoft REL file format. You can use LINK-80 to link the object modules contained in a library to other object files. LINK-80 automatically selects from the library only those modules needed by the program being linked, and then forms an executable file with a filetype of COM. ///2Options I The INDEX option creates an indexed library file of type .IRL. LINK-80 searches faster on indexed libraries than on non-indexed libraries. M The MODULE option displays module names. P The PUBLICS option displays module names and the public variables for the new library file. D The DUMP option displays the contents of object modules in ASCII form. ///2Modifiers Use modifiers in the command line to instruct LIB to delete, replace, or select modules in a library file. Angle brackets enclose the modules to be deleted or replaced. P library files. LINK searches the library files and includes the referenced modules in the output file. See the CP/M 3 Programmer's Utilities Guide for a complete description of LINK- 80. ///2Options Use LINK option switches to control execution parameters. Link options follow the file specifications and are enclosed within square brackets. Multiple switches are separated by commas. LINK-80 Options A Additional memory; reduces buffer space and writes temporary data to disk B BIOS link in banked CP/M 3 system. 1. Aligns data segment on page boundary. 2. Puts length of code segment in header. 3. Defaults to .SPR filetype. Dhhhh Data origin; sets memory origin for common and data area Gn Go; set start address to labEnter a period to redisplay what you just read. - Press the RETURN key to return to the CP/M 3 system prompt. - [NOPAGE] option disables the 24 lines per page console display. - Press any key to exit a display and return to the HELP> prompt. Examples: A>HELP A>HELP DATE A>HELP DIR OPTIONS A>HELP>.OPTIONS HELP>SET HELP>SET PASSWORD HELP>.PASSWORD HELP>. HELP> ///1HEXCOM Syntax: HEXCOM filename Explanation: The HEXCOM Command generates a command file (filetype .COM) from a .HEX input file. It names the output file with the same filename as the input file but with filetype .COM. HEXCOM always looks for a file with filetype .HEX. Example: A>HEXCOM B:PROGRAM Generates a command file PROGRAM.COM from the input hex file PROGRAM.HEX. ///1INITDIR Syntax: INITDIR {d:} Explanation: The INITDIR Command initializes a diskarentheses enclose the modules to be selected. LIB Modifiers Delete Replace If module name and filename are the same this shorthand can be used: Select (modFIRST-modLAST,mod1,mod2,...,modN) ///2Examples A>LIB TEST4[P] Displays all modules and publics in TEST4.REL. A>LIB TEST5[P]=FILE1,FILE2 Creates TEST5.REL from FILE1.REL and FILE2.REL and displays all modules and publics in TEST5.REL. A>LIB TEST=TEST1(MOD1,MOD4),TEST2(C1-C4,C6) Creates a library file TEST.REL from modules in two source files. TEST1.REL contributes MOD1 and MOD4. LIB extracts modules C1, C4, and all the modules located between them, as well as module C6 from TEST2.REL. A>LIB FILE2=FILE3 Creates FILel n Lhhhh Load; change default load address of module to hhhh. Default 0100H Mhhhh Memory size; Define free memory requirements for MP/M modules. NL No listing of symbol table at console NR No symbol table file OC Output .COM command file. Default OP Output .PRL page relocatable file for execution under MP/M in relocatable segment OR Output .RSP resident system process file for execution under MP/M OS Output .SPR system page relocatable file for execution under MP/M Phhhh Program origin; changes default program origin address to hhhh. Default is 0100H. Q Lists symbols with leading question mark S Search precedinges with the input filename and filetypes of .HEX, .PRN, and .SYM. Filename.HEX contains INTEL hexadecimal format object code. Filename.PRN contains an annotated source listing that you can print or examine at the console. Filename.SYM contains a sorted list of symbols defined in the program. ///2Examples A>MAC SAMPLE A>MAC SAMPLE $PB AA HB SX ///2options Use options to direct the input and output of MAC. Use a letter with the option to indicate the source and destination drives, and console, printer, or zero output. Valid drive names are A thru O. X, P and Z specify console, printer, and zero output, respectively. Assembly Options That Direct Input/Output A source drive for .ASM file (A-O) H destination drive for .HEX file (A-O, Z) L source drive for macrolibrary .LIB files called by the MACLIB statement. P destination drive for .PRN file (A-O, X, P, Z)  A>PIP b:draft.txt = a: B3>PIP myfile.dat=A:[G9] A9>PIP B:[G3]=myfile.dat COPY A FILE AND RENAME IT A5>PIP newdraft.txt=oldraft.txt C8>PIP b:newdraft.txt=a:oldraft.txt COPY MULTIPLE FILES A>PIP b:=draft.* A>PIP b:=*.* B>PIP b:=c:.*.* C>PIP b:=*.txt[g5] C>PIP a:=*.com[wr] B>PIP a:[g3]=c:*.* COMBINE MULTIPLE FILES A>PIP b:new.dat=file1.dat,file2.dat COPY, RENAME AND PLACE IN USER 1 A>pip newdraft.txt[g1]=oldraft.txt COPY, RENAME AND GET FROM USER 1 A>PIP newdraft.txt=oldraft.txt[g1] COPY TO/FROM LOGICAL DEVICES A>PIP b:funfile.sue=con: A>PIP lst:=con: A>PIP lst:=b:draft.txt[t8] A>PIP prn:=b:draft.txt ///2options PIP OPTIONS A Archive. Copy only files that have been changed since the last copy. C Confirm. PIP prompts for confirmation before each file copy. Dn Delete any characters past co file as a library $Cd Destination of console messages d can be X (console), Y (printer), or Z (zero output). Default is X. $Id Source of intermediate files; d is disk drive A-P. Default is current drive. $Ld Source of library files; d is disk drive A-P. Default is current drive. $Od Destination of of object file; d can be Z or disk drive A-P. Default is to same drive as first file in the LINK-80 command. $Sd Destination of symbol file; d can be Y or Z or disk drive A-P. Default is to same drive as first file in LINK-80 command. ///2Examples A>LINK b:MYFILE[NR] LINK-80 on drive A uses as input MYFILE.REL on drive B and p S destination drive for .SYM file Assembly Options That Modify Contents Of Output File +L lists input lines read from macrollibrary .LIB files -L suppresses listing (default) +M lists all macro lines as they are processed during assembly -M suppresses all macro lines as they are read during assembly *M lists only hex generated by macro expansions +Q lists all LOCAL symbols in the symbol list -Q suppresses all LOCAL symbols in the symbol list (default) +S appends symbol file to print file -S suppresses creation of symbol file +1 produces a pass 1 listing for macro debugging in .PRN file -1 suppress listing on pass 1 (default) ///1PATCH Syntax: PATCH filename{.typ} {n} Explanation: The PATCH command displays or installs patch number n to the CP/M 3 system or command files. The patch number n must be between 1 and 32 inclusive. Example: A>PATCH SHOW 2 Patches thlumn n. E Echo transfer to console. F Filter form-feeds from source data. Gn Get from or go to user n. H Test for valid Hex format. I Ignore :00 Hex data records and test for valid Hex format. K Kill display of filespecs on console. L Translate upper case to lower case. N Number output lines O Object file transfer, ^Z ignored. Pn Set page length to n. (default n=60) Qs^Z Quit copying from source at string s. R Read files that have been set to SYStem. Ss^Z Start copying from the source at the string s. Tn Expand tabs to n spaces. U Translate lower case to upper case. V Verify that data has been written correctly. W Write over Read Only files without console query. Z Zero the parity bit. All options except C,G,K,O,R,V and W force an ASCII file transfer, character by character, terminated by a ^Z. ///1PUT Syntax: PUT CONSOLE {OUTPUT TO} FILE filespec {option} | CONSOLE PUroduces the executable machine code file MYFILE.COM on drive B. The [NR] option specifies no symbol table file. A>LINK m1,m2,m3 LINK-80 combines the separately compiled files m1, m2, and m3, resolves their external references, and produces the executable machine code file m1.COM. A>LINK m=m1,m2,m3 LINK-80 combines the separately compiled files m1, m2, and m3 and produces the executable machine code file m.COM. A>LINK MYFILE,FILE5[s] The [s] option tells LINK-80 to search FILE5 as a library. LINK-80 combines MYFILE.REL with the referenced subroutines contained in FILE5.REL on the default drive A and produces MYFILE.COM on drive A. ///1mac Syntax: MAC filename {$options} Explanation: MAC, the CP/M 3 macro assembler, reads assembly language statements from a file of type .ASM, assembles the statements, and produces three output file SHOW.COM system file with patch number 2. ///1PIP (copy) Syntax: DESTINATION SOURCE PIP d:{Gn} | filespec{[Gn]} = filespec{[o]},... | d:{[o]} Explanation: The file copy program PIP copies files, combines files, and transfers files between disks, printers, consoles, or other devices attached to your computer. The first filespec is the destination. The second filespec is the source. Use two or more source filespecs separated by commas to combine two or more files into one file. [o] is any combination of the available options. The [Gn] option in the destination filespec tells PIP to copy your file to that user number. PIP with no command tail displays an * prompt and awaits your series of commands, entered and processed one line at a time. The source or destination can be any CP/M 3 logical device. ///2Examples COPY A FILE FROM ONE DISK TO ANOTHER A>PIP b:=a:draft.txt T PRINTER {OUTPUT TO} FILE filespec {option} | PRINTER PUT CONSOLE {OUTPUT TO} CONSOLE PUT PRINTER {OUTPUT TO} PRINTER Explanation: PUT puts console or printer output to a file for the next command entered at the console, until the program terminates. Then console output reverts to the console. Printer output is directed to a file until the program terminates. Then printer output is put back to the printer. PUT with the SYSTEM option directs all subsequent console/printer output to the specified file. This option terminates when you enter the PUT CONSOLE or PUT PRINTER command. ///2Options [ {ECHO | NO ECHO} {FILTER | NO FILTER} | {SYSTEM} ] ECHO specifies that output is echoed to the console. This is the default option when you direct console output to a file. NO ECHO specifies that file output is not echoed to the  A>RENAME The system prompts for the filespecs: Enter New Name:X.PRN Enter Old Name:Y.PRN Y .PRN=X .PRN A> File X.PRN is renamed to Y.PRN on drive A. B>REN A:PRINTS.NEW = PRINCE.NEW The file PRINCE.NEW on drive A changes to PRINTS.NEW on drive A. A>RENAME S*.TEX=A*.TEX The above command renames all the files matching A*.TEX to files with filenames S*.TEX. A>REN B:NEWLIST=B:OLDLIST The file OLDLIST changes to NEWLIST on drive B. Since the second drive specifier, B: is implied by the first one, it is unnecessary in this example. The command line above has the same effect as the following: A>REN B:NEWLIST=OLDLIST or A>REN NEWLIST=B:OLDLIST ///1RMAC Syntax: RMAC filespec {$Rd | $Sd | $Pd} Explanation: RMAC, a relocatable macro assembler, assembles .ASM file ///1SET Syntax: SET [options] SET d: [options] SET filespec [options] Explanation: SET initiates password protection and time stamping of files. It also sets the file and drive attributes Read-Write, Read-Only, DIR and SYS. It lets you label a disk and password protect the label. To enable time stamping of files, you must first run INITDIR to format the disk directory. ///2Label Syntax: SET {d:} [NAME=labelname.typ] SET [PASSWORD=password] SET [PASSWORD= ///3Examples A>SET [NAME=DISK100] Labels the disk on the default drive as DISK100. A>SET [PASSWORD=SECRET] Assigns SECRET to the disk label. A>SET [PASSWORD= Nullifies the existing password. ///2Passwords SET [PROTECT=ON] SET [PROTECT=OFF] SET filespec [PASSWORD=password] SET filespec [PROTECT=READ] SET  console. NO ECHO is the default for the PUT PRINTER command. FILTER specifies filtering of control characters, which means that control characters are translated to printable characters. For example, an ESCape character is translated to ^[. NO FILTER means that PUT does not translate control characters. This is the default option. SYSTEM specifies that system output as well as program output is written to the file specified by filespec. Output is written to the file until a subsequent PUT CONSOLE command redirects console output back to the console. ///2Examples A>PUT CONSOLE OUTPUT TO FILE XOUT [ECHO] Directs console output to file XOUT with the output echoed to the console. A>PUT PRINTER OUTPUT TO FILE XOUT A>MYPROG Directs s of into .REL files that you can link to create .COM files. ///2options RMAC options specify the destination of the output files. Replace d with the destination drive letter for the output files. Option d=output option R- drive for REL file (A-O, Z) S- drive for SYM file (A-O, X, P, Z) P- drive for PRN file (A-O, X, P, Z) A-O specifies drive A-O. X means output to the console. P means output to the printer. Z means zero output. ///2Example A>RMAC TEST $PX SB RB Assembles the file TEST.ASM from drive A, sends the listing file (TEST.PRN) to the console, puts the symbol file (TEST.SYM) on drive B and puts the relocatable object file (TEST.REL) on drive B. ///1SAVE Syntax: SAVE Explanation: SAVE copies the contents of memory to a file. To use SAVE, first issue tfilespec [PROTECT=WRITE] SET filespec [PROTECT=DELETE] SET filespec [PROTECT=NONE] SET filespec [attribute-options] ///3Modes Password Protection Modes Mode Protection READ The password is required for reading, copying writing, deleting or renaming the file. WRITE The password is required for writing, deleting or renaming the file. You do not need a password to read the file. DELETE The password is only required for deleting or renaming the file. You do not need a password to read or modify the file. NONE No password exists for the file. If a password password exists, this modifier can be used to delete the password. ///2Attributes RO sets the file attribute to Read-Only. RW sets the fi the printer output of program MYPROG to file XOUT. The output is not echoed to the printer. A>PUT PRINTER OUTPUT TO FILE XOUT2 [ECHO,SYSTEM] Directs all printer output to file XOUT2 as well as to the printer (with ECHO option), and the PUT is in effect until you enter a PUT PRINTER OUTPUT TO PRINTER command. A>PUT CONSOLE OUTPUT TO CONSOLE Directs console output back to the console. A>PUT PRINTER OUTPUT TO PRINTER Directs printer output back to the printer. ///1RENAME Syntax: RENAME {new-filespec=old-filespec} Explanation: RENAME lets you change the name of a file in the directory of a disk. To change several filenames in one command use the * or ? wildcards in the file specifications. The RENAME command can be abbreviated REN. REN prompts you for input. ///2Examples A>RENAME NEWFILE.BAS=OLDFILE.BAS The file OLDFILE.BAS changes to NEWFILE.BAS on drive A.he SAVE command, then run your program which reads a file into memory. Your program exits to the SAVE utility which prompts you for a filespec to which it copies the contents of memory, and the beginning and ending address of the memory to be SAVEd. ///2Example A>SAVE Activates the SAVE utility. Now enter the name of the program which loads a file into memory. A>SID dump.com Next, execute the program. #g0 When the program exits, SAVE intercepts the return to the system and prompts the user for the filespec and the bounds of memory to be SAVEd. SAVE Ver 3.0 Enter file (type RETURN to exit):dump2.com If file DUMP2.COM exists already, the system asks: Delete dump2.com? Y Then the system asks for the bounds of memory to be saved: Beginning hex address: 100 Ending hex address: 400 The contents of memory from 100H (Hexadecimal) to 400H is copied to file DUMP2.COM. le attribute to Read-Write. SYS sets the file attribute to SYS. DIR sets the file attribute to DIR. ARCHIVE=OFF means that the file has not been backed up (archived). ARCHIVE=ON means that the file has been backed up (archived). The Archive attribute can be turned on by SET or by PIP when copying a group of files with the PIP [A] option. SHOW and DIR display the Archive option. F1=ON|OFF turns on or off the user-definable file attribute F1. F2=ON|OFF turns on or off the user-definable file attribute F2. F3=ON|OFF turns on or off the user-definable file attribute F3. F4=ON|OFF turns on or off the user-definable file attribute F4. ///3Examples SET [PROTECT=ON] Turns on password protection for all the files on the disk.  A>SET [CREATE=ON,UPDATE=ON] ///2Drives Syntax: SET {d:} [RO] SET {d:} [RW] Example: A>SET B: [RO] Sets drive B to Read-Only. ///1SETDEF Syntax: SETDEF { d: {,d: {,d: {,d:}}}} {[ TEMPORARY = d: ] | [ ORDER = (typ {,typ}) ]} SETDEF [DISPLAY | NO DISPLAY] SETDEF [PAGE | NOPAGE] Explanation: SETDEF allows the user to display or define up to four drives for the program search order, the drive for temporary files, and the file type search order. The SETDEF definitions affect only the loading of programs and/or execution of SUBMIT (SUB) files. SETDEF turns on/off the system Display and Console Page modes. When on, the system displays the location and name of programs loaded or SUBmit files executed, and stops after displaying one full console screen of information. ///2Examples A>SETDEF nitored execution, symbolic disassembly, assembly, and memory display and fill functions. SID can dynamically load SID utility programs to provide traceback and histogram facilities. ///2Commands Command Meaning As (Assemble) Enter assembly language statements s is the start address Cs{b{,d}} (Call) Call to memory location from SID s is the called address b is the value of the BC register pair d is the value of the DE register pair D{W}{s}{,f} (Display) Display memory in hex and ASCII W is a 16-bit word format s is the start address f is the finish address Epgm-filespec You must turn on password protection before you can assign passwords to files. SET [PROTECT=OFF] Disables password protection for the files on your disk. A>SET MYFILE.TEX [PASSWORD=MYFIL] MYFIL is the password assigned to file MYFILE.TEX. B>SET *.TEX [PASSWORD=SECRET, PROTECT=WRITE] Assigns the password SECRET to all the TEX files on drive B. Each TEX file is given a WRITE protect mode to prevent unauthorized editing. A>SET MYFILE.TEX [RO SYS] Sets MYFILE.TEX to Read-Only and SYStem. ///2Default A>SET [DEFAULT=dd] Instructs the system to use dd as a password if you do not enter a password for a password-protected file. ///2Time-Stamps Syntax: SET [CREATE=ON] SET [ACCESS=ON] SET [UPDATE=ON] Explanation: The above SET commands allow you to keep a record of the time and date of file creation and update, or of the last access  Displays current SETDEF parameters. A>SETDEF [TEMPORARY=C:] Sets disk drive C as the drive to be used for temporary files. A>SETDEF C:,* Tells the system to search for a program on drive C, then, if not found, search for it on the default drive. A>SETDEF [ORDER=(SUB,COM)] Instructs the system to search for a SUB file to execute. If no SUB file is found, search for a COM file. A>SETDEF [DISPLAY] Turns on the system display mode. Henceforth, the system displays the name and location of programs loaded or submit files executed. A>SETDEF [NO DISPLAY] Turns off the system Display mode. ///1SHOW Syntax: SHOW {d:}{[SPACE |LABEL |USERS |DIR |DRIVE]} Explanation: The SHOW command displays the following disk drive information: Access mode and the amount of free disk space Disk label Current user number and Number of files for each user numb (Load) Load program and symbol table {,sym-filespec} for execution E*sym-filespec (Load) Load a symbol table file Fs,f,d (Fill) Fill memory with constant value s is the start address f is the finish address d is an eight-bit data item G{p}{,a{,b}} (Go) Begin Execution p is a start address a is a temporary breakpoint H (Hex) Displays all symbols with addresses in Hex H.a Displays hex, decimal, and ASCII values of a where a is a symbolic expression Ha,b Computes hex sum and difference of a and b where and update of your files. ///3Options [CREATE=ON] turns on CREATE time stamps on the disk in the default or specified drive. To record the creation time of a file, the CREATE option must be turned on before the file is created. [ACCESS=ON] turns on ACCESS time stamps on the disk in the default or specified drive. ACCESS and CREATE options are mutually exclusive; only one can be in effect at a time. If you turn on the ACCESS time stamp on a disk that previously had CREATE time stamp, the CREATE time stamp is automatically turned off. [UPDATE=ON] turns on UPDATE time stamps on the disk in the default or specified drive. UPDATE time stamps record the time the file was last modified. ///3Examples A>SET [ACCESS=ON] er on the disk Number of free directory entries for the disk Drive characteristics ///2Examples A>SHOW A>SHOW [SPACE] Instructs the system to display access mode and amount of space left on logged-in drives. A>SHOW B: Show access mode for drive B and amount of space left on drive B. A>SHOW B:[LABEL] Displays label information for drive B. A>SHOW [USERS] Displays the current user number and all the users on drive A and the corresponding number of files assigned to them. A>SHOW C:[DIR] Displays the number of free directory entries on drive C. A>SHOW [DRIVE] Displays the drive characteristics of drive A. ///1SID Syntax: SID {pgm-filespec} {,sym-filespec} Explanation: The SID symbolic debugger allows you to monitor and test programs developed for the 8080 microprocessor. SID supports real-time breakpoints, fully mo a and b are symbolic expressions Icommand tail (Input) Input CCP command line L{s}{,f} (List) List 8080 mnemonic instructions s is the start address f is the finish address Ms,h,d (Move) Move Memory Block s is the start address h is the high address of the block d is the destination start address P{p{,c}} (Pass) Pass point set, reset, and display p is a permanent breakpoint address c is initial value of pass counter Rfilespec{,d} (Read) Read Code/Symbols d is an offset to each address S{W}s (Set) Set Memory Values s is address where value istilities, HIST.UTL and TRACE.UTL are special programs that operate with SID to provide additional debugging facilities. The mechanisms for system initialization, data collection, and data display are described in the CP/M SID User's Guide. The HIST utility creates a histogram (bar graph) showing the relative frequency of execution of code within selected program segments of the test program. The HIST utility allows you to monitor those sections of code that execute most frequently. The TRACE utility obtains a backtrace of the instructions that led to a particular breakpoint address in a program under test. You can collect the addresses of up to 256 instructions between pass points in U or T modes. ///1SUBMIT Syntax: SUBMIT {filespec} {argument} ... {argument} Explanation: The SUBMIT command lets you execute a group (batch) of commands from a SUBmit file (a file with filrive B on your screen twenty four lines at a time. ///1USER Syntax: USER {number} Explanation: The USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> The current user number is now 5 on drive A. A>USER 3 3A> This command changes the current User Number to 3. ///1XREF Syntax: XREF {d:} filename {$P} Explanation: XREF provides a cross-reference summary of variable usage in a program. XREF requires the .PRN and .SYM files produced by MAC or RMAC for input to the program. The SYM and PRN files must have the same filename as the filename in the XREF command tail. XREF outputs a file of type .XRF. Examples: A>XREF b:MYPROG A>XREF b:MYPROG $P  sent W is 16 bit word T{n{,c}} (Trace) Trace Program Execution n is the number of program steps c is the utility entry address. T{W}{n{,c}} (Trace) Trace Without Call W instructs SID not to trace subroutines n is the number of program steps c is the utility entry address U{W}{n{,c}} (Untrace) Monitor Execution without Trace n is the number of program steps c is the utility entry address W instructs SID not to trace subroutines V (Value) Display the value of the next available location in memory etype of SUB). ///2Subfile The SUB file can contain the following types of lines: Any valid CP/M 3 command Any valid CP/M 3 command with SUBMIT parameters ($0-$9) Any data input line Any program input line with parameters ($0 to $9) The command line cannot exceed 135 characters. The following lines illustrate the variety of lines which may be entered in a SUB file: DIR DIR *.BAK MAC $1 $$$4 PIP LST:=$1.PRN[T$2 $3 $5] DIR *.ASM PIP SUBMIT A>SUBMIT SUBA A>SUBMIT AA ZZ SZ A>SUBMIT B:START DIR E: ///2PROFILE.SUB Everytime you power up or reset your computer, CP/M 3 looks for a special SUBmit file named PROFILE.SUB to ex (NEXT), the next location after the largest file read in (MSZE), the current value of the Program counter (PC), and the address of the end of available memory (END) Wfilespec,s,f (Write) Write the contents of a contiguous block of memory to filespec. f is finish address X{f}{r} (Examine) Examine/alter CPU state. f is flag bit C,Z,M,E or I. r is register A,B,D,H,S or P. ///2Examples A>SID CP/M 3 loads SID from drive A into memory. SID displays the # prompt when it is ready to accept commands. A>B:SID SAMPLE.HEX CP/M 3 loads SID and the program file SAMPLE.HEX into memory from drive B. ///2Utilities SID uecute. If it does not exist, CP/M 3 resumes normal operation. If the PROFILE.SUB file exists, the system executes the commands in the file. This file is convenient to use if you regularly execute a set of commands before you do your regular session on the computer. ///1TYPE Syntax: TYPE {filespec {[ PAGE | NOPAGE ]}} Explanation: The TYPE command displays the contents of an ASCII character file on your screen. [PAGE] Causes the console listing to be displayed in paged mode; i.e., stop automatically after listing n lines of text, where n normally defaults to 24 lines per page. [NOPAGE] Turns off Console Page Mode and continuously displays a typed file on the screen. ///2Examples A>TYPE MYPROG.PLI Displays the contents of the file MYPROG.PLI on your screen. A>TYPE B:THISFILE [PAGE] Displays the contents of the file THISFILE from dtitle cold cold boot sector .z80 ;Customization equate (more or less) density_code equ 0e6h ;0e5h = sssd ;0e6h = ssdd ;0e7h = dsdd sector_size equ 80h ;single-density sector size number_sectors equ 26 ;# of sectors to read base equ 0000h ;program base load_base equ base+sector_size;where to start loading cold_exit equ load_base+sector_size ;where to go after the load passing_cell equ 0fch ;error code pass-back to monitor prom xpassing_cell equ 0feh ; " " " prom_err_ret equ 0f033h ;error return to prom prom_off equ 01101111b ;jp rst, prom off, banks on prom_on equ 01001111b ;jp rst, prom on, banks on errmask equ 10011100b ;fdc status mask for read errs include B:ADCIO .phase base cseg cold: ld a,prom_off out (bnk0),a ld a,(nsec) ld d,a ld hl,load_base ld e,1 ;start with sector 1 cloop: ld bc,fdcdat ;0 -> b, fdc data port -> c ld a,e ;set sector reg out (fdcsec),a ld a,fdcread+fdcside ;init read out (fdccmhl,de ; add logical drv no to base tbl addr add hl,de ; tbl entrys are wrds, so do add twice ld e,(hl) ; fetch contents of table entry inc hl ; point to high byte of addr ld d,(hl) ; get high byte push de ; put ddb addr into ix-reg pop ix ; by useing ix reg we save instructions ret ;-------------------- ; 16-BIT SHIFT RIGHT ;-------------------- shfr16:: and a ; a-reg has no of shifts to perform shfrlp: ret z srl d ; shift msb first, bit 0 into carry rr e ; rotate carry into bit 7 of lsb dec a ; decrement shift counter jr shfrlp ; loop until finished ;------------------- ; 16-BIT SHIFT LEFT ;------------------- shfl16:: and a shfllp: ret z sla e rl d dec a jr shfllp xfercnt:: db 0 diskbf:: ds 0400h end %#"%` Ø Ø Ø Ø Ø ͩ` *M6` !6 ` !6 ` !6 ` *&T` !6 ` !6 ` !60 ` *& title FLOPPY DISK DRIVER -- CP/M 3.0 -- BANKED / NON-BANKED .z80 global finit, flogin, fwrite, fread ext fdpb8, fdpb548,fdpb596 ext fddb8, fddb548,fddb596 ext tran8, tran548,tran596 ext ddbtbl ext @dtbl, @adrv, @rdrv, @sect, @trk ext xfercnt,getdata,putdata,ddbtoix,shfl16, shfr16, diskbf ext pderr?, pmsg?, conin? rtrys equ 11 ;# of retrys dsk_io_err equ 1 ;disk io error flag mflag equ 0ffh ;changed media flag ;---------------------------------- ; FLOPPY CONTROLLER PORT ADDRESSES ;---------------------------------- fbase equ 0ch ; base port addr of wd-1793 or wd-2793 fcmd equ fbase+0 ; command register fstat equ fbase+0 ; status register ftrk equ fbase+1 ; track register fsec equ fbase+2 ; sector register fdata equ fbase+3 ; data register fwait equ 014h ; wait register fdsd equ 014h ; density - size - drive register ;---------------------------- ; FLOPPY CONTROLLER COMMANDS ;---------------------------- fstpr equ 001h ; floppy stepd),a nop csecread: in a,(fdcwait) ;wait for status or a ;done reading? jp p,csecdone ;yes, jump ini ;get a byte jr csecread csecdone: in a,(fdcstat) ld c,a ld (passing_cell),bc and errmask ;any errors? jr nz,cerror ;yes, jump dec d ;last sector? jp z,cold_exit ;yes, go execute the load inc e ;next sector ld a,number_sectors+1 cp e ;sector count error? jr nz,cloop ;no, loop cerror: push af ld (passing_cell+2),de ;save the flub ??? ld a,prom_on out (bnk0),a jp prom_err_ret rept (sector_size-2)-$ ;fill with zeroes .xlist db 00 .list endm nsec: db number_sectors db density_code end )덑o|g =o&og~ title CHARACTER I/O DRIVER -- CP/M 3.0 -- LOADER .z80 ;--------------- ; CONSOLE INPUT ;--------------- ci?:: call cist? ; get input status jr z,ci? ; loop until character received in a,(0) ; get character from sio ch a and 07fh ; mask high order bit ret ;---------------- ; CONSOLE OUTPUT ;---------------- co?:: call cost? ; get status jr z,co? ; go back if not ready ld a,c ; put character to send in a out (0),a ; send char to sio ch a ret ;---------------------- ; CONSOLE INPUT STATUS ;---------------------- cist?:: in a,(1) ; get status of sio ch a and 1 ; check if character recieved ret z ; no character waiting ld a,0ffh ; character waiting ret ;----------------------- ; CONSOLE OUTPUT STATUS ;----------------------- cost?:: in a,(1) ; get status and 4 ; ready? ret z ; no or 0ffh ; else set ready ret ; and exit end  rate (0,1,2 or 3) frst equ 000h + fstpr ; restore hds fsek equ 01ch + fstpr ; seek track frd equ 084h ; read sector fwrt equ 0a4h ; write sector page 60 ;------------------------------- ; FLOPPY CONTROLLER BIT TESTERS ;------------------------------- dnrdy equ 80h ;Drive not ready bit ;dsd equates dsd_drv_msk equ 00000011b ;0 = A:, 1 = B:, 2 = C:, 3 = D: dsd_hed_msk equ 00000100b ;0 = h0, 1 = h1 dsd_den_msk equ 00001000b ;0 = sd, 1 = dd dsd_siz_msk equ 00010000b ;0 = 8", 1 = 5" ;-------------------------------------- ; FLOPPY DISK DEBLOCKING BLOCK INDEXES ;-------------------------------------- secsizl equ 000h secsizh equ 001h dsd equ 002h hdoff equ 003h stepr equ 004h secmsk equ 005h hdshf equ 006h ;------------- ;xdph equates ;------------- ;indexes xlt equ 0 ;skew table adr mf equ 11 ;media flag dpb equ 12 ;dpb adr csv equ 14 ;csv adr alv equ 16 ;alv adr dirbcb equ 18 ;dir bcb adr dtabcb equ 20 ;data bcb adr hash e title DISK DRIVE DEFINITIONS -- CP/M 3.0 -- BANKED / NON-BANKED include DISK.LIB .z80 dskdef dseg ;------------------- ; GET DATA TO WRITE ;------------------- getdata:: ld hl,diskbf ; destination ld de,(@dma##) ; source getlp: ld bc,(@dbnk##) ; source bank ld b,0 ; destination bank call xmove?## ld bc,080h call move?## ld a,(xfercnt) dec a ld (xfercnt),a jr nz,getlp ret ;--------------- ; PUT DATA READ ;--------------- putdata:: ld hl,(@dma##) ; destination ld de,diskbf ; source putlp: ld a,(@dbnk##) ; destination bank ld b,a ld c,0 ; source bank call xmove?## ld bc,080h call move?## ld a,(xfercnt) dec a ld (xfercnt),a jr nz,putlp ret ;----------------------- ; SET IX TO DDB ADDRESS ;----------------------- ddbtoix:: ld hl,ddbtbl ; set up to calc current ddb addr ld de,(@adrv##) ; use logical drv no as index to table ld d,0 ; zero high byte of index for dbl add add <2: ,:)!"#**"!"1!6*"!":/G*)))) ~$^!6D*))))  :!:/Ұ!6,V 2:›0XáCX,V 2X**0&p>ͭ,V 2 H!6> !*& 6 :<2!6$ *)))) DMuX*#"=*))))  ~!=!6*#"=:],V 2X%!6#6!6#6!":/:/HҼ*)))) ~$ʴ*))))  :)<{*)&͏x *)))) ͛2:q *)))) *)&͏x u:)<2):/:)2!6>!)n&͏x ~ H*)&͏x ~[Hb!6!6n*#"!6x*#"ñ:Ҫ*))))  :Ң*#"ç!6ñ*#"ù!6z:**#"**))))  DM}u*))))  #DM~u!6*))))  ~2D*))))  ~2):!q!6!::E/Hҙ,V 2E:E/Җ!6:!{X:<2a*&͏x DMX:<27 H*)M.:E/ҷ,V 2E:E/\\2DN!6:/:E/H\Hes of files and the characteristics associated with the files. The DIR command has three distinct references: DIR DIRS DIR with Options DIR and DIRS are built-in utilities. DIR with Options is a transient utility and must be loaded into memory from the disk. ///2Built-in Syntax: DIR {d:} DIR {filespec} DIRS {d:} DIRS {filespec} Explanation: The DIR and DIRS Built-in commands display the names of files cataloged in the directory of an on-line disk. DIR lists the names of files in the current user number that have the Directory (DIR) attribute. DIR accepts the * and ? wildcards in the file specification. ///3Examples A>DIR Displays all files in user 0 on drive A that have the Directory attribute. A>DIR B: Displays all DIR files in user 0 on drive B. 2A>DIR C:ZIPPY.DAT Displays the name ZI 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 ld a,0cdh ld (0),a ;disable media change checking ld c,25 ;get & save current disk call bdos ld (cdisk),a ; 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 M bytes). SYS displays only the files that have the SYS attribute. USER=ALL displays all files in all user numbers for the default or specified drive. USER=n displays the files in the user number specified by n. USER=(0,1,...,15) displays files under the user numbers specified. ///3Examples A>DIR C: [FULL] Displays full set of characteristics for all files in user 0 on drive C. A>DIR C: [DATE] Lists the files on drive C and their dates. A>DIR D: [RW,SYS] Displays all files in user 0 on drive D with Read-Write and System attributes. 3A>DIR [USER=ALL, DRIVE=ALL] Displays all the files in all user numbers (0-15) in all on- line drives. B6>DIR [exclude] *.DAT Lists all the files on drive B in user 6 that do not have a filetype of .DAT. 3B>DIR [SIZE] *.PLI *.COM *.ASM Displays all the files of type PLI, COM, and ASPPY.DAT if the file is in user 2 on drive C. 4A>DIR *.BAS Displays all DIR files with filetype BAS in user 4 on drive A. B3>DIR X*.C?D Displays all DIR files in user 3 on drive B whose filename begins with the letter X, and whose three character filetype contains the first character C and last character D. A>DIRS Displays all files for user 0 on drive A that have the system (SYS) attribute. A>DIRS *.COM Displays all SYS files with filetype COM on drive A in user 0. A command (.COM) file in user 0 with the system attribute can be accessed from any user number on that drive, and from any drive in the search chain (see SETDEF). ///2withOptions Syntax: DIR {d:} [options] DIR {filespec} {filespec} ... [options] Explanation: The DIR command with options is an enhanced version of the DIR built-in command and displays your files in a variety of ways. DIR can search for files on any or all drives, for any or all user numbers. One or two letters is sufficient to identify an option. You need not type the right hand square bracket. ///3Options Option Function ATT displays the file attributes. DATE displays date and time stamps of files. DIR displays only files that have the DIR attribute. DRIVE=ALL displays files on all on-line drives. DRIVE=(A,B,C,...,P) displays files on the drives specified. DRIVE=d displays files on the drive specified by d. EXCLUDE displays files that DO NOT MATCH the files specified in the command line. FF sends an initial form feed to the printer device if the printer has been activated by CTRL-P. FULL shows the name, size, number of 128-byte records, and attributes of the files. If there M in user 3 on drive B in size display format. A>DIR [drive=all user=all] TESTFILE.BOB DIR displays the filename TESTFILE.BOB if it is found on any drive in any user number. A>DIR [size,rw] D: DIR lists each Read-Write file that resides on Drive D, with its size in kilobytes. Note that D: is equivalent to D:*.*. ///1DUMP Syntax: DUMP filespec Explanation: DUMP displays the contents of a file in hexadecimal and ASCII format. Example: A>DUMP ABC.TEX ///1ed Format: ED input-filespec {d:|output-filespec} Explanation: Character file editor. To redirect or rename the new version of the file specify the destination drive or destination filespec. ///2commands ED Command Summary Command Action nA append n lines from original file to memory buffer 0A append file until buffer is one h .Z80 ; ; FORMAT VERSION 3.1 ; ; FORMAT PROGRAM FOR THE WD 1793 & WD 2793 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 false ; 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 is a directory label on the drive, DIR shows the password protection mode and the time stamps. If there is no directory label, DIR displays two file entries on a line, omitting the password and time stamp columns. The display is alphabetically sorted. (See SET for a description of file attributes, directory labels, passwords and protection modes.) LENGTH=n displays n lines of printer output before inserting a table heading. n is a number between 5 and 65536. MESSAGE displays the names of drives and user numbers DIR is searching. NOSORT displays files in the order it finds them on the disk. RO displays only the files that have the Read-Only attribute. RW displays only the files that are set to Read-Write. SIZE displays the filename and size in kilobytes (1024 alf full #A append file until buffer is full (or end of file) B, -B move CP to the beginning (B) or bottom (-B) of buffer nC, -nC move CP n characters forward (C) or back (-C) through buffer nD, -nD delete n characters before (-D) or from (D) the CP E save new file and return to CP/M-86 Fstring{^Z} find character string H save new file, reedit, use new file as original file I enter insert mode Istring{^Z} insert string at CP Jsearch_str^Zins_str^Zdel_to_str juxtapose strings nK, -nK delete (kill) n lines from the CP nL, -nL, 0L move CP n lines nMcommands execute commands n times n, -n move CP n lines and display that line n: move to line n :ncommand execute command through line n Nstring{^Z} extended find string O return to original file nP, -nP lename that begins with MY is displayed with a question mark for confirmation. Type Y to erase the file displayed, N to keep the file. A>ERA B:*.* Confirm (Y/N)?Y All files on drive B are removed from the disk. ///1filespec FILESPEC FORMAT CP/M 3 identifies every file by its unique file specification, which can consist of four parts: the drive specification, the filename, the filetype and the password. The term "filespec" indicates any valid combination of the four parts of a file specification, all separated by their appropriate delimiters. A colon must follow a drive letter. A period must precede a filetype. A semicolon must precede a password. The symbols and rules for the parts of a file specification follow: d: drivespec optional single alpha character (A-P) filename filename 1-8 letters and/or numbers typ  GENCOM takes MYPROG.COM, strips off the header and deletes all attached RSX's to restore it to its original COM format. A>GENCOM MYPROG PROG1 PROG2 GENCOM looks at the already-GENCOMed file MYPROG.COM to see if PROG1.RSX and PROG2.RSX are already attached RSX files in the module. If either one is already attached, GENCOM replaces it with the new RSX module. Otherwise, GENCOM appends the specified RSX files to the COM file. ///1GET Syntax: GET {CONSOLE INPUT FROM} FILE filespec{[{ECHO|NO ECHO} | SYSTEM]} GET {CONSOLE INPUT FROM} CONSOLE Explanation: GET directs the system to take console input from a file for the next system command or user program entered at the console. Console input is taken from a file until the program terminates. If the file is exhausted before program input is terminated, the program looks for subsequent input from the consol move CP 23 lines forward and display 23 lines at console Q abandon new file, return to CP/M-86 R{^Z} read X$$$$$$$.LIB file into buffer Rfilespec{^Z} read filespec into buffer Sdelete string^Zinsert string substitute string nT, -nT, 0T type n lines U, -U upper-case translation V, -V line numbering on/off 0V display free buffer space nW write n lines to new file 0W write until buffer is half empty nX write or append n lines to X$$$$$$$.LIB nXfilespec{^Z} write n lines to filespec; append if previous xcommand applied to same file 0x{^Z} delete file X$$$$$$$.LIB 0xfilespec{^Z} delete filespec nZ wait n seconds Note: CP points to the current character being referenced in the edit buffer. Use {^Z} to separate multiple commands on the same line. ///2Examples A>ED TEST.filetype optional 0-3 letters and/or numbers password password optional 0-8 letters and/or numbers Valid combinations of the elements of a CP/M 3 file specification are: filename d:filename filename.typ d:filename.typ filename;password d:filename;password filename.typ;password d:filename.typ;password If you do not include a drive specifier, CP/M 3 automatically uses the default drive. Some CP/M 3 commands accept wildcard (* and ?) characters in the filename and/or filetype parts of the command tail. A wildcard in the command line can in one command reference many matching files on the default or specified user number and drive. (See Commands). ///1GENCOM Syntax: GENCOM {COM-filespec} {RSX-filespec} ... {[LOADER | NULL | SCB=(offset,value)]} Explanation: Thee. If the program terminates before exhausting all its input, the system reverts back to the console for console input. With the SYSTEM option, the system immediately goes to the specified file for console input. The system reverts to the console for input when it reaches the end of file. Re-direct the system to the console for console input with the GET CONSOLE INPUT FROM CONSOLE command as a command line in the input file. ///2Options ECHO specifies that input is echoed to the console. This is the default option. NO ECHO specifies that file input is not echoed to the console. The program output and the system prompts are not affected by this option and are still echoed to the console. SYSTEM specifies that all system input is immediately taken from the disk file specified in the command line. GET takes system and program inDAT A>ED TEST.DAT B: A>ED TEST.DAT TEST2.DAT A>ED TEST.DAT B:TEST2.DAT ///1erase Syntax: ERASE {filespec} {[CONFIRM]} Explanation: The ERASE command removes one or more files from the directory of a disk. Wildcard characters are accepted in the filespec. Directory and data space are automatically reclaimed for later use by another file. The ERASE command can be abbreviated to ERA. ///2Option [CONFIRM] option informs the system to prompt for verification before erasing each file that matches the filespec. CONFIRM can be abbreviated to C. ///2Examples A>ERASE X.PAS Removes the file X.PAS from the disk in drive A. A>ERA *.PRN Confirm (Y/N)?Y All files with the filetype PRN are removed from the disk in drive A. B>ERA A:MY*.* [CONFIRM] Each file on drive A with a fi GENCOM command creates a special COM file with attached RSX files. The GENCOM command can also restore a previously GENCOMed file to the original COM file without the header and RSX's. GENCOM can also attach header records to COM files. ///2Options LOADER sets a flag to keep the program loader active. NULL indicates that only RSX files are specified. GENCOM creates a dummy COM file for the RSX files. The output COM filename is taken from the filename of the first RSX-filespec. SCB=(offset,value) sets the System Control Block from the program by using the hex values specified by (offset,value). ///2Examples A>GENCOM MYPROG PROG1 PROG2 Generates a new COM file MYPROG.COM with attached RSX's PROG1 and PROG2. A>GENCOM PROG1 PROG2 [NULL] Creates a COM file PROG1.COM with RSX's PROG1 and PROG2. A>GENCOM MYPROG put from the file until the file is exhausted or until GET reads a GET console command from the file. ///2Examples A>GET FILE XINPUT A>MYPROG Tells the system to activate the GET utility. Since SYSTEM is not specified, the system reads the next input line from the console and executes MYPROG. If MYPROG program requires console input, it is taken from the file XINPUT. When MYPROG terminates, the system reverts back to the console for console input. A>GET FILE XIN2 [SYSTEM] Immediately directs the system to get subsequent console input from file XIN2 because it includes the SYSTEM option. The system reverts back to the console for console input when it reaches the end of file in XIN2. Or XIN2 may redirect the system back to the console if it contains a GET CONSOLE command. A>GET CONSOLE Tells th directory to allow date and time stamping of files on that disk. INITDIR can also recover time/date directory space. Example: A>INITDIR C: INITDIR WILL ACTIVATE TIME-STAMPS FOR SPECIFIED DRIVE. Do you want to re-format the directory on C: (Y/N)?Y ///1LIB Syntax: LIB filespec{[I|M|P|D]} LIB filespec{[I|M|P]}=filespec{modifier} {,filespec{modifier} ... } Explanation: A library is a file that contains a collection of object modules. Use the LIB utility to create libraries, and to append, replace, select or delete modules from an existing library. Use LIB to obtain information about the contents of library files. LIB creates and maintains library files that contain object modules in Microsoft REL file format. These modules are produced by Digital Research's relocatable macro-assembler program, RMAC, or any other language translator that pruduces modules E2.REL from FILE3.REL, omitting MODA which is a module in FILE3.REL. A>LIB FILE6=FILE5 Creates FILE6.REL from FILE5.REL, FILEB.REL replaces MODA. A>LIB FILE6=FILE5 Module THISNAME is in FILE5.REL. When LIB creates FILE6.REL from FILE5.REL the file THISNAME.REL replaces the similarly named module THISNAME. A>LIB FILE1[I]=B:FILE2(PLOTS,FIND,SEARCH-DISPLAY) Creates FILE1.IRL on drive A from the selected modules PLOTS, FIND, and modules SEARCH through the module DISPLAY, in FILE2.REL on drive B. ///1LINK Syntax: LINK d:{filespec,{[options]}=}filespec{[options]}{,...} Explanation: LINK combines relocatable object modules such as those produced by RMAC and PL/I-80 into a .COM file ready for execution. Relocatable files can contain external references and publics. Relocatable files can reference modules ine system to get console input from the console. This command may be used in a file (previously specified in a GET FILE command), which is already being read by the system for console input. It is used to re-direct the console input back to the console before the end-of-file is reached. ///1HELP Syntax: HELP {topic} {subtopic1 ... subtopic8} {[NOPAGE|LIST]} Explanation: HELP displays a list of topics and provides summarized information for CP/M 3 commands. HELP topic displays information about that topic. HELP topic subtopic displays information about that subtopic. One or two letters is enough to identify the topics. After HELP displays information for your topic, it displays the special prompt HELP> on your screen, followed by a list of subtopics. - Enter ? to display list of main topics. - Enter a period and subtopic name to access subtopics. - in Microsoft REL file format. You can use LINK-80 to link the object modules contained in a library to other object files. LINK-80 automatically selects from the library only those modules needed by the program being linked, and then forms an executable file with a filetype of COM. ///2Options I The INDEX option creates an indexed library file of type .IRL. LINK-80 searches faster on indexed libraries than on non-indexed libraries. M The MODULE option displays module names. P The PUBLICS option displays module names and the public variables for the new library file. D The DUMP option displays the contents of object modules in ASCII form. ///2Modifiers Use modifiers in the command line to instruct LIB to delete, replace, or select modules in a library file. Angle brackets enclose the modules to be deleted or replaced. P library files. LINK searches the library files and includes the referenced modules in the output file. See the CP/M 3 Programmer's Utilities Guide for a complete description of LINK- 80. ///2Options Use LINK option switches to control execution parameters. Link options follow the file specifications and are enclosed within square brackets. Multiple switches are separated by commas. LINK-80 Options A Additional memory; reduces buffer space and writes temporary data to disk B BIOS link in banked CP/M 3 system. 1. Aligns data segment on page boundary. 2. Puts length of code segment in header. 3. Defaults to .SPR filetype. Dhhhh Data origin; sets memory origin for common and data area Gn Go; set start address to labEnter a period to redisplay what you just read. - Press the RETURN key to return to the CP/M 3 system prompt. - [NOPAGE] option disables the 24 lines per page console display. - Press any key to exit a display and return to the HELP> prompt. Examples: A>HELP A>HELP DATE A>HELP DIR OPTIONS A>HELP>.OPTIONS HELP>SET HELP>SET PASSWORD HELP>.PASSWORD HELP>. HELP> ///1HEXCOM Syntax: HEXCOM filename Explanation: The HEXCOM Command generates a command file (filetype .COM) from a .HEX input file. It names the output file with the same filename as the input file but with filetype .COM. HEXCOM always looks for a file with filetype .HEX. Example: A>HEXCOM B:PROGRAM Generates a command file PROGRAM.COM from the input hex file PROGRAM.HEX. ///1INITDIR Syntax: INITDIR {d:} Explanation: The INITDIR Command initializes a diskarentheses enclose the modules to be selected. LIB Modifiers Delete Replace If module name and filename are the same this shorthand can be used: Select (modFIRST-modLAST,mod1,mod2,...,modN) ///2Examples A>LIB TEST4[P] Displays all modules and publics in TEST4.REL. A>LIB TEST5[P]=FILE1,FILE2 Creates TEST5.REL from FILE1.REL and FILE2.REL and displays all modules and publics in TEST5.REL. A>LIB TEST=TEST1(MOD1,MOD4),TEST2(C1-C4,C6) Creates a library file TEST.REL from modules in two source files. TEST1.REL contributes MOD1 and MOD4. LIB extracts modules C1, C4, and all the modules located between them, as well as module C6 from TEST2.REL. A>LIB FILE2=FILE3 Creates FILel n Lhhhh Load; change default load address of module to hhhh. Default 0100H Mhhhh Memory size; Define free memory requirements for MP/M modules. NL No listing of symbol table at console NR No symbol table file OC Output .COM command file. Default OP Output .PRL page relocatable file for execution under MP/M in relocatable segment OR Output .RSP resident system process file for execution under MP/M OS Output .SPR system page relocatable file for execution under MP/M Phhhh Program origin; changes default program origin address to hhhh. Default is 0100H. Q Lists symbols with leading question mark S Search precedinges with the input filename and filetypes of .HEX, .PRN, and .SYM. Filename.HEX contains INTEL hexadecimal format object code. Filename.PRN contains an annotated source listing that you can print or examine at the console. Filename.SYM contains a sorted list of symbols defined in the program. ///2Examples A>MAC SAMPLE A>MAC SAMPLE $PB AA HB SX ///2options Use options to direct the input and output of MAC. Use a letter with the option to indicate the source and destination drives, and console, printer, or zero output. Valid drive names are A thru O. X, P and Z specify console, printer, and zero output, respectively. Assembly Options That Direct Input/Output A source drive for .ASM file (A-O) H destination drive for .HEX file (A-O, Z) L source drive for macrolibrary .LIB files called by the MACLIB statement. P destination drive for .PRN file (A-O, X, P, Z)  A>PIP b:draft.txt = a: B3>PIP myfile.dat=A:[G9] A9>PIP B:[G3]=myfile.dat COPY A FILE AND RENAME IT A5>PIP newdraft.txt=oldraft.txt C8>PIP b:newdraft.txt=a:oldraft.txt COPY MULTIPLE FILES A>PIP b:=draft.* A>PIP b:=*.* B>PIP b:=c:.*.* C>PIP b:=*.txt[g5] C>PIP a:=*.com[wr] B>PIP a:[g3]=c:*.* COMBINE MULTIPLE FILES A>PIP b:new.dat=file1.dat,file2.dat COPY, RENAME AND PLACE IN USER 1 A>pip newdraft.txt[g1]=oldraft.txt COPY, RENAME AND GET FROM USER 1 A>PIP newdraft.txt=oldraft.txt[g1] COPY TO/FROM LOGICAL DEVICES A>PIP b:funfile.sue=con: A>PIP lst:=con: A>PIP lst:=b:draft.txt[t8] A>PIP prn:=b:draft.txt ///2options PIP OPTIONS A Archive. Copy only files that have been changed since the last copy. C Confirm. PIP prompts for confirmation before each file copy. Dn Delete any characters past co file as a library $Cd Destination of console messages d can be X (console), Y (printer), or Z (zero output). Default is X. $Id Source of intermediate files; d is disk drive A-P. Default is current drive. $Ld Source of library files; d is disk drive A-P. Default is current drive. $Od Destination of of object file; d can be Z or disk drive A-P. Default is to same drive as first file in the LINK-80 command. $Sd Destination of symbol file; d can be Y or Z or disk drive A-P. Default is to same drive as first file in LINK-80 command. ///2Examples A>LINK b:MYFILE[NR] LINK-80 on drive A uses as input MYFILE.REL on drive B and p S destination drive for .SYM file Assembly Options That Modify Contents Of Output File +L lists input lines read from macrollibrary .LIB files -L suppresses listing (default) +M lists all macro lines as they are processed during assembly -M suppresses all macro lines as they are read during assembly *M lists only hex generated by macro expansions +Q lists all LOCAL symbols in the symbol list -Q suppresses all LOCAL symbols in the symbol list (default) +S appends symbol file to print file -S suppresses creation of symbol file +1 produces a pass 1 listing for macro debugging in .PRN file -1 suppress listing on pass 1 (default) ///1PATCH Syntax: PATCH filename{.typ} {n} Explanation: The PATCH command displays or installs patch number n to the CP/M 3 system or command files. The patch number n must be between 1 and 32 inclusive. Example: A>PATCH SHOW 2 Patches thlumn n. E Echo transfer to console. F Filter form-feeds from source data. Gn Get from or go to user n. H Test for valid Hex format. I Ignore :00 Hex data records and test for valid Hex format. K Kill display of filespecs on console. L Translate upper case to lower case. N Number output lines O Object file transfer, ^Z ignored. Pn Set page length to n. (default n=60) Qs^Z Quit copying from source at string s. R Read files that have been set to SYStem. Ss^Z Start copying from the source at the string s. Tn Expand tabs to n spaces. U Translate lower case to upper case. V Verify that data has been written correctly. W Write over Read Only files without console query. Z Zero the parity bit. All options except C,G,K,O,R,V and W force an ASCII file transfer, character by character, terminated by a ^Z. ///1PUT Syntax: PUT CONSOLE {OUTPUT TO} FILE filespec {option} | CONSOLE PUroduces the executable machine code file MYFILE.COM on drive B. The [NR] option specifies no symbol table file. A>LINK m1,m2,m3 LINK-80 combines the separately compiled files m1, m2, and m3, resolves their external references, and produces the executable machine code file m1.COM. A>LINK m=m1,m2,m3 LINK-80 combines the separately compiled files m1, m2, and m3 and produces the executable machine code file m.COM. A>LINK MYFILE,FILE5[s] The [s] option tells LINK-80 to search FILE5 as a library. LINK-80 combines MYFILE.REL with the referenced subroutines contained in FILE5.REL on the default drive A and produces MYFILE.COM on drive A. ///1mac Syntax: MAC filename {$options} Explanation: MAC, the CP/M 3 macro assembler, reads assembly language statements from a file of type .ASM, assembles the statements, and produces three output file SHOW.COM system file with patch number 2. ///1PIP (copy) Syntax: DESTINATION SOURCE PIP d:{Gn} | filespec{[Gn]} = filespec{[o]},... | d:{[o]} Explanation: The file copy program PIP copies files, combines files, and transfers files between disks, printers, consoles, or other devices attached to your computer. The first filespec is the destination. The second filespec is the source. Use two or more source filespecs separated by commas to combine two or more files into one file. [o] is any combination of the available options. The [Gn] option in the destination filespec tells PIP to copy your file to that user number. PIP with no command tail displays an * prompt and awaits your series of commands, entered and processed one line at a time. The source or destination can be any CP/M 3 logical device. ///2Examples COPY A FILE FROM ONE DISK TO ANOTHER A>PIP b:=a:draft.txt T PRINTER {OUTPUT TO} FILE filespec {option} | PRINTER PUT CONSOLE {OUTPUT TO} CONSOLE PUT PRINTER {OUTPUT TO} PRINTER Explanation: PUT puts console or printer output to a file for the next command entered at the console, until the program terminates. Then console output reverts to the console. Printer output is directed to a file until the program terminates. Then printer output is put back to the printer. PUT with the SYSTEM option directs all subsequent console/printer output to the specified file. This option terminates when you enter the PUT CONSOLE or PUT PRINTER command. ///2Options [ {ECHO | NO ECHO} {FILTER | NO FILTER} | {SYSTEM} ] ECHO specifies that output is echoed to the console. This is the default option when you direct console output to a file. NO ECHO specifies that file output is not echoed to the  A>RENAME The system prompts for the filespecs: Enter New Name:X.PRN Enter Old Name:Y.PRN Y .PRN=X .PRN A> File X.PRN is renamed to Y.PRN on drive A. B>REN A:PRINTS.NEW = PRINCE.NEW The file PRINCE.NEW on drive A changes to PRINTS.NEW on drive A. A>RENAME S*.TEX=A*.TEX The above command renames all the files matching A*.TEX to files with filenames S*.TEX. A>REN B:NEWLIST=B:OLDLIST The file OLDLIST changes to NEWLIST on drive B. Since the second drive specifier, B: is implied by the first one, it is unnecessary in this example. The command line above has the same effect as the following: A>REN B:NEWLIST=OLDLIST or A>REN NEWLIST=B:OLDLIST ///1RMAC Syntax: RMAC filespec {$Rd | $Sd | $Pd} Explanation: RMAC, a relocatable macro assembler, assembles .ASM file title 'bank & move module for CP/M3 linked BIOS' cseg public ?move,?xmove,?bank extrn @cbnk maclib z80 maclib ports ?xmove: ; ALTOS can't perform interbank moves ret ?move: xchg ; we are passed source in DE and dest in HL ldir ; use Z80 block move instruction xchg ; need next addresses in same regs ret ; by exiting through bank select ?bank: push b ; save register b for temp ral ! ral ! ral ! ani 18h ; isolate bank in proper bit position mov b,a ; save in reg B in p$bankselect ; get old memory control byte ani 0E7h ! ora b ; mask out old and merge in new out p$bankselect ; put new memory control byte pop b ; restore register b ret ; 128 bytes at a time end ud$4800 equ 12 ; 4800 baud baud$7200 equ 13 ; 7200 baud baud$9600 equ 14 ; 9600 baud baud$19200 equ 15 ; 19.2k baud  console. NO ECHO is the default for the PUT PRINTER command. FILTER specifies filtering of control characters, which means that control characters are translated to printable characters. For example, an ESCape character is translated to ^[. NO FILTER means that PUT does not translate control characters. This is the default option. SYSTEM specifies that system output as well as program output is written to the file specified by filespec. Output is written to the file until a subsequent PUT CONSOLE command redirects console output back to the console. ///2Examples A>PUT CONSOLE OUTPUT TO FILE XOUT [ECHO] Directs console output to file XOUT with the output echoed to the console. A>PUT PRINTER OUTPUT TO FILE XOUT A>MYPROG Directs  ; equates for mode byte bit fields mb$input equ 0000$0001b ; device may do input mb$output equ 0000$0010b ; device may do output mb$in$out equ mb$input+mb$output mb$soft$baud equ 0000$0100b ; software selectable ; baud rates mb$serial equ 0000$1000b ; device may use protocol mb$xon$xoff equ 0001$0000b ; XON/XOFF protocol ; enabled baud$none equ 0 ; no baud rate associated ; with this device baud$50 equ 1 ; 50 baud baud$75 equ 2 ; 75 baud baud$110 equ 3 ; 110 baud baud$134 equ 4 ; 134.5 baud baud$150 equ 5 ; 150 baud baud$300 equ 6 ; 300 baud baud$600 equ 7 ; 600 baud baud$1200 equ 8 ; 1200 baud baud$1800 equ 9 ; 1800 baud baud$2400 equ 10 ; 2400 baud baud$3600 equ 11 ; 3600 baud baud$4800 equ 12 ; 4800 baud baud$7200 equ 13 ; 7200 baud baud$9600 equ 14 ; 9600 baud baud$19200 equ 15 ; 19.2k baud  the printer output of program MYPROG to file XOUT. The output is not echoed to the printer. A>PUT PRINTER OUTPUT TO FILE XOUT2 [ECHO,SYSTEM] Directs all printer output to file XOUT2 as well as to the printer (with ECHO option), and the PUT is in effect until you enter a PUT PRINTER OUTPUT TO PRINTER command. A>PUT CONSOLE OUTPUT TO CONSOLE Directs console output back to the console. A>PUT PRINTER OUTPUT TO PRINTER Directs printer output back to the printer. ///1RENAME Syntax: RENAME {new-filespec=old-filespec} Explanation: RENAME lets you change the name of a file in the directory of a disk. To change several filenames in one command use the * or ? wildcards in the file specifications. The RENAME command can be abbreviated REN. REN prompts you for input. ///2Examples A>RENAME NEWFILE.BAS=OLDFILE.BAS The file OLDFILE.BAS changes to NEWFILE.BAS on drive A.; I/O Port addresses for Z80 chip set ; based system with wd1797 FDC ; chip bases p$zdma equ 0 p$wd1797 equ 4 p$zpio1 equ 8 p$zctc1 equ 12 p$zpio2 equ 16 p$boot equ 20 ; OUT disables boot EPROM p$zdart equ 28 ; console 1 and printer 1 p$zpio3 equ 36 p$zsio1 equ 40 p$zsio2 equ 44 p$zctc2 equ 48 ; diskette controller chip ports p$fdcmnd equ p$wd1797+0 p$fdstat equ p$wd1797+0 p$fdtrack equ p$wd1797+1 p$fdsector equ p$wd1797+2 p$fddata equ p$wd1797+3 ; parallel I/O 1 p$select equ p$zpio1+0 p$fdint equ p$zpio1+0 p$fdmisc equ p$zpio1+1 p$zpio1a equ p$zpio1+2 p$zpio1b equ p$zpio1+3 ; counter timer chip 1 p$baudcon1 equ p$zctc1+0 p$baudlpt1 equ p$zctc1+2 p$index equ p$zctc1+3 ; parallel I/O 2, Centronics printer interface p$cent$stat equ p$zpio2+0 p$cent$data equ p$zpio2+1 p$zpio2a equ p$zpio2+2 p$zpio2b equ p$zpio2+3 ; dual asynch rcvr/xmtr, console and serial printer ports p$crt$data equ p$zdart+0 p$crt$stat equ p$zdart+1 p$on ranovf equ fcb+35 ;high order (overflow) byte buff equ 0080h ;buffer address ; cr equ 0dh ;carriage return lf equ 0ah ;line feed ; ;*************************************************** ;* * ;* load SP, set-up file for random access * ;* * ;*************************************************** lxi sp,stack ; ; version 3.1? mvi c,version call bdos cpi 31h ;version 3.1 or better? jnc versok ; bad version, message and go back lxi d,badver call print jmp reboot ; versok: ; correct version for random access mvi c,openf ;open default fcb rdname: lda fcb+1 cpi ' ' jnz opfile lxi d,entmsg call print call parse jmp versok opfile: lxi d,fcb call bdos inr a ;err 255 becomes zero  mov m,a inx h ;next to fill dcr c ;counter goes down jnz rloop ;end of buffer? erloop: ; end of read loop, store 00 mvi m,0 ; ; write the record to selected record number mvi c,writer lxi d,fcb call bdos ora a ;error code zero? jnz error ;message if not jmp ready ;for another record ; ; ;******************************************************** ;* * ;* end of write command, process write random zero fill * ;* * ;******************************************************** notw: ; not the quit command, random write zero fill? cpi 'F' jnz notf ; ; this is a random write, fill buffer until cr lxi d,datmsg call print ;data prompt mvi c,127 ;up to 127 chalpt$data equ p$zdart+2 p$lpt$stat equ p$zdart+3 ; Third Parallel I/O device p$configuration equ p$zpio3+0 p$bankselect equ p$zpio3+1 p$zpio3a equ p$zpio3+2 p$zpio3b equ p$zpio3+3 ; Serial I/O device 1, printer 2 and console 4 p$lpt2data equ p$zsio1+0 p$lpt2stat equ p$zsio1+1 p$con4data equ p$zsio1+2 p$con4stat equ p$zsio1+3 ; Serial I/O device 2, console 2 and 3 p$con2data equ p$zsio2+0 p$con2stat equ p$zsio2+1 p$con3data equ p$zsio2+2 p$con3stat equ p$zsio2+3 ; second Counter Timer Circuit p$baudcon2 equ p$zctc2+0 p$baudcon34 equ p$zctc2+1 p$baudlpt2 equ p$zctc2+2 p$rtc equ p$zctc2+3 , Centronics printer interface p$cent$stat equ p$zpio2+0 p$cent$data equ p$zpio2+1 p$zpio2a equ p$zpio2+2 p$zpio2b equ p$zpio2+3 ; dual asynch rcvr/xmtr, console and serial printer ports p$crt$data equ p$zdart+0 p$crt$stat equ p$zdart+1 p$ jnz ready ; ; cannot open file, so create it mvi c,makef lxi d,fcb call bdos inr a ;err 255 becomes zero jnz ready ; ; cannot create file, directory full lxi d,nospace call print jmp reboot ;back to ccp ; ;*************************************************** ;* * ;* loop back to "ready" after each command * ;* * ;*************************************************** ; ready: ; file is ready for processing ; call readcom ;read next command shld ranrec ;store input record# lxi h,ranovf mov m,c ;set ranrec high byte cpi 'Q' ;quit? jnz notq ; ; quit processing, close file mvi c,closef lxi d,fcb call bdos inr a ;err 255 racters lxi h,buff ;destination rloop1: ;read next character to buff push b ;save counter push h ;next destination call getchr ;character to a pop h ;restore counter pop b ;restore next to fill cpi cr ;end of line? jz erloop1 ; not end, store character mov m,a inx h ;next to fill dcr c ;counter goes down jnz rloop1 ;end of buffer? erloop1: ; end of read loop, store 00 mvi m,0 ; ; write the record to selected record number mvi c,wrtrzf lxi d,fcb call bdos ora a ;error code zero? jnz error ;message if not jmp ready ;for another record ; ;*************************************************** ;* * ;* end of write commands, process read ;*************************************************** ;* * ;* sample random access program for cp/m 3 * ;* * ;*************************************************** org 100h ;base of tpa ; reboot equ 0000h ;system reboot bdos equ 0005h ;bdos entry point ; coninp equ 1 ;console input function conout equ 2 ;console output function pstring equ 9 ;print string until '$' rstring equ 10 ;read console buffer version equ 12 ;return version number openf equ 15 ;file open function closef equ 16 ;close function makef equ 22 ;make file function readr equ 33 ;read random writer equ 34 ;write random wrtrzf equ 40 ;write random zero fill parsef equ 152 ;parse function ; fcb equ 005ch ;default file control block ranrec equ fcb+33 ;random record positibecomes 0 jz error ;error message, retry jmp reboot ;back to ccp ; ;*************************************************** ;* * ;* end of quit command, process write * ;* * ;*************************************************** notq: ; not the quit command, random write? cpi 'W' jnz notw ; ; this is a random write, fill buffer until cr lxi d,datmsg call print ;data prompt mvi c,127 ;up to 127 characters lxi h,buff ;destination rloop: ;read next character to buff push b ;save counter push h ;next destination call getchr ;character to a pop h ;restore counter pop b ;restore next to fill cpi cr ;end of line? jz erloop ; not end, store character * ;* * ;*************************************************** notf: ; not a write command, read record? cpi 'R' jnz error ;skip if not ; ; read random record mvi c,readr lxi d,fcb call bdos ora a ;return code 00? jnz error ; ; read was successful, write to console call crlf ;new line mvi c,128 ;max 128 characters lxi h,buff ;next to get wloop: mov a,m ;next character inx h ;next to get ani 7fh ;mask parity jz ready ;for another command if 00 push b ;save counter push h ;save next to get cpi ' ' ;graphic? cnc putchr ;skip output if not pop h pop b dcr c ;count=count-1 jnz wloop jmp ready ; ;***i 10 ;carry if numeric jnc endrd ; add-in next digit push psw mov a,c ;value = ahl dad h adc a ;*2 push a ;save value * 2 push h dad h ;*4 adc a dad h ;*8 adc a pop b ;*2 + *8 = *10 dad b pop b adc b pop b ;+digit mov c,b mvi b,0 dad b aci 0 mov c,a jnc readc jmp readcom endrd: ; end of read, restore value in a adi '0' ;command cpi 'a' ;translate case? rc ; lower case, mask lower case bits ani 101$1111b ret ;return with value in chl ; ;*************************************************** ;* * ;* string data area for console messages * ;* * ;*************************************************** badver: db 'sorry, you need cp/m version 3$' nospace: db 'no directory space$' datmsg: dbs of into .REL files that you can link to create .COM files. ///2options RMAC options specify the destination of the output files. Replace d with the destination drive letter for the output files. Option d=output option R- drive for REL file (A-O, Z) S- drive for SYM file (A-O, X, P, Z) P- drive for PRN file (A-O, X, P, Z) A-O specifies drive A-O. X means output to the console. P means output to the printer. Z means zero output. ///2Example A>RMAC TEST $PX SB RB Assembles the file TEST.ASM from drive A, sends the listing file (TEST.PRN) to the console, puts the symbol file (TEST.SYM) on drive B and puts the relocatable object file (TEST.REL) on drive B. ///1SAVE Syntax: SAVE Explanation: SAVE copies the contents of memory to a file. To use SAVE, first issue t************************************************ ;* * ;* end of read command, all errors end-up here * ;* * ;*************************************************** ; error: lxi d,errmsg call print jmp ready ; ;*************************************************** ;* * ;* utility subroutines for console i/o * ;* * ;*************************************************** getchr: ;read next console character to a mvi c,coninp call bdos ret ; putchr: ;write character from a to console mvi c,conout mov e,a ;character to send call bdos ;send character ret ; crlf: ;send carriage return line feed mvi a,cr ;carriage return call  'type data: $' errmsg: db 'error, try again.$' prompt: db 'next command? $' entmsg: db 'enter filename: $' ; ;*************************************************** ;* * ;* fixed and variable data area * ;* * ;*************************************************** conbuf: db conlen ;length of console buffer consiz: ds 1 ;resulting size after read conlin: ds 32 ;length 32 buffer conlen equ $-consiz ; pfncb: dw conlin dw fcb ; ds 32 ;16 level stack stack: end ssages * ;* * ;*************************************************** badver: db 'sorry, you need cp/m version 3$' nospace: db 'no directory space$' datmsg: dbhe SAVE command, then run your program which reads a file into memory. Your program exits to the SAVE utility which prompts you for a filespec to which it copies the contents of memory, and the beginning and ending address of the memory to be SAVEd. ///2Example A>SAVE Activates the SAVE utility. Now enter the name of the program which loads a file into memory. A>SID dump.com Next, execute the program. #g0 When the program exits, SAVE intercepts the return to the system and prompts the user for the filespec and the bounds of memory to be SAVEd. SAVE Ver 3.0 Enter file (type RETURN to exit):dump2.com If file DUMP2.COM exists already, the system asks: Delete dump2.com? Y Then the system asks for the bounds of memory to be saved: Beginning hex address: 100 Ending hex address: 400 The contents of memory from 100H (Hexadecimal) to 400H is copied to file DUMP2.COM. putchr mvi a,lf ;line feed call putchr ret ; parse: ;read and parse filespec lxi d,conbuf mvi c,rstring call bdos lxi d,pfncb mvi c,parsef call bdos ret ; print: ;print the buffer addressed by de until $ push d call crlf pop d ;new line mvi c,pstring call bdos ;print the string ret ; readcom: ;read the next command line to the conbuf lxi d,prompt call print ;command? mvi c,rstring lxi d,conbuf call bdos ;read command line ; command line is present, scan it mvi c,0 ;start with 00 lxi h,0 ; 0000 lxi d,conlin;command line readc: ldax d ;next command character inx d ;to next command position ora a ;cannot be end of command rz ; not zero, numeric? sui '0' cpqu 22 ;hash table adr hbank equ 24 ;hash table bank ;drive type equates dtyp548 equ 1 ;5" 48 tpi dtyp596 equ 2 ;5" 96 tpi dtyp8 equ 3 ;8" page dseg ;------------------------- ; INITALIZE FLOPPY DRIVES ;------------------------- finit: ret ;logmsg: 0dh,0ah,'Login',0 ;ds 99 ;-------------------- ; LOGIN FLOPPY DRIVE ;-------------------- flogin: ld (cdph),de ;ld hl,logmsg ;call pmsg? call getds ; get fpy drv siz (8-5) & pdrv # (0-3) call frestore ; restore fpy drv hds jr nz,flogerr ; ret if drv not rdy for select error call getden ; get dsk density (sgl-dbl) call getsd ; get number of sides on dsk (0-1) call setdpb ; set dpb addr in dph to ind. den & sd call settran ; set sec trn vec adr in dph if sgl den call setddb ; set ddb addr in ddbtbl call getdsd ld a,(cdsd) ; put new dsd reg setting in a-reg ld (hl),a ; save it as a dsdvec entry ret flogerr: pop hl pop de ld de,0 jp (hl) page ;---------IOS (word, r/o) @CRDMA equ scb$base+3Ch ; Current DMA Address ; (word, r/o) @CRDSK equ scb$base+3Eh ; Current Disk (byte, r/o) @VINFO equ scb$base+3Fh ; BDOS Variable "INFO" ; (word, r/o) @RESEL equ scb$base+41h ; FCB Flag (byte, r/o) @FX equ scb$base+43h ; BDOS Function for Error ; Messages (byte, r/o) @USRCD equ scb$base+44h ; Current User Code (byte, r/o) @MLTIO equ scb$base+4Ah ; Current Multi-Sector Count ; (byte,r/w) @ERMDE equ scb$base+4Bh ; BDOS Error Mode (byte, r/o) @ERDSK equ scb$base+51h ; BDOS Error Disk (byte,r/o) @MEDIA equ scb$base+54h ; Set by BIOS to indicate ; open door (byte,r/w) @BFLGS equ scb$base+57h ; BDOS Message Size Flag (byte,r/o) @DATE equ scb$base+58h ; Date in Days Since 1 Jan 78 ; (word, r/w) @HOUR equ scb$base+5Ah ; Hour in BCD (byte,  ///1SET Syntax: SET [options] SET d: [options] SET filespec [options] Explanation: SET initiates password protection and time stamping of files. It also sets the file and drive attributes Read-Write, Read-Only, DIR and SYS. It lets you label a disk and password protect the label. To enable time stamping of files, you must first run INITDIR to format the disk directory. ///2Label Syntax: SET {d:} [NAME=labelname.typ] SET [PASSWORD=password] SET [PASSWORD= ///3Examples A>SET [NAME=DISK100] Labels the disk on the default drive as DISK100. A>SET [PASSWORD=SECRET] Assigns SECRET to the disk label. A>SET [PASSWORD= Nullifies the existing password. ///2Passwords SET [PROTECT=ON] SET [PROTECT=OFF] SET filespec [PASSWORD=password] SET filespec [PROTECT=READ] SET ---------------------------------- ; GET DRV SIZE AND PHY DRV NO. FROM DRV MAP ;------------------------------------------- getds: ld hl,(cdph) ; point to drvtyp in @dtbl dec hl ld a,(hl) ; put drive type in a-reg cp 2 ; if =2 then 5"- 96 tpi fpy drv ld a,0 ; a-reg contains dsd setting jr c,dsiz548 ; if =1 then 5" - 48 tpi fpy drv jr nz,getpdrv ; if =3 then 8" fpy drv dsiz596: set 5,a ; set bit 5 to indicate 96 tpi dsiz548: set 4,a ; set bit 4 to indicate 5" fpy getpdrv: dec hl ; phys drv no. is (xdph-2) or (hl) ; or in drive size bit setting ld (cdsd),a ; save it in den - dsiz - dno out (fdsd),a ; set floppy den,dsiz,dno in controller ret ;------------------ ; GET DISK DENSITY ;------------------ getden: call gettkv ld a,1 ; do sek to trk 1, sgl den ld (hl),a ; save trk no. in trk vec call fseek ; do seek to trk 1 ret z ; return if succesful (dsk is sgl den) dbldens: ld c,dsd_den_msk ; else assume dbl den (saves timer/w) @MIN equ scb$base+5Bh ; Minute in BCD (byte, r/w) @SEC equ scb$base+5Ch ; Second in BCD (byte, r/w) ?ERJMP equ scb$base+5Fh ; BDOS Error Message Jump ; (word, r/w) @MXTPA equ scb$base+62h ; Top of User TPA ; (address at 6,7)(word, r/o) end ion for Error ; Messages (byte, r/o) @USRCD equ scb$base+44h ; Current User Code (byte, r/o) @MLTIO equ scb$base+4Ah ; Current Multi-Sector Count ; (byte,r/w) @ERMDE equ scb$base+4Bh ; BDOS Error Mode (byte, r/o) @ERDSK equ scb$base+51h ; BDOS Error Disk (byte,r/o) @MEDIA equ scb$base+54h ; Set by BIOS to indicate ; open door (byte,r/w) @BFLGS equ scb$base+57h ; BDOS Message Size Flag (byte,r/o) @DATE equ scb$base+58h ; Date in Days Since 1 Jan 78 ; (word, r/w) @HOUR equ scb$base+5Ah ; Hour in BCD (byte, filespec [PROTECT=WRITE] SET filespec [PROTECT=DELETE] SET filespec [PROTECT=NONE] SET filespec [attribute-options] ///3Modes Password Protection Modes Mode Protection READ The password is required for reading, copying writing, deleting or renaming the file. WRITE The password is required for writing, deleting or renaming the file. You do not need a password to read the file. DELETE The password is only required for deleting or renaming the file. You do not need a password to read or modify the file. NONE No password exists for the file. If a password password exists, this modifier can be used to delete the password. ///2Attributes RO sets the file attribute to Read-Only. RW sets the fi title 'System Control Block Definition for CP/M3 BIOS' public @civec, @covec, @aivec, @aovec, @lovec, @bnkbf public @crdma, @crdsk, @vinfo, @resel, @fx, @usrcd public @mltio, @ermde, @erdsk, @media, @bflgs public @date, @hour, @min, @sec, ?erjmp, @mxtpa scb$base equ 0FE00H ; Base of the SCB @CIVEC equ scb$base+22h ; Console Input Redirection ; Vector (word, r/w) @COVEC equ scb$base+24h ; Console Output Redirection ; Vector (word, r/w) @AIVEC equ scb$base+26h ; Auxiliary Input Redirection ; Vector (word, r/w) @AOVEC equ scb$base+28h ; Auxiliary Output Redirection ; Vector (word, r/w) @LOVEC equ scb$base+2Ah ; List Output Redirection ; Vector (word, r/w) @BNKBF equ scb$base+35h ; Address of 128 Byte Buffer ; for Banked B le attribute to Read-Write. SYS sets the file attribute to SYS. DIR sets the file attribute to DIR. ARCHIVE=OFF means that the file has not been backed up (archived). ARCHIVE=ON means that the file has been backed up (archived). The Archive attribute can be turned on by SET or by PIP when copying a group of files with the PIP [A] option. SHOW and DIR display the Archive option. F1=ON|OFF turns on or off the user-definable file attribute F1. F2=ON|OFF turns on or off the user-definable file attribute F2. F3=ON|OFF turns on or off the user-definable file attribute F3. F4=ON|OFF turns on or off the user-definable file attribute F4. ///3Examples SET [PROTECT=ON] Turns on password protection for all the files on the disk.  A>SET [CREATE=ON,UPDATE=ON] ///2Drives Syntax: SET {d:} [RO] SET {d:} [RW] Example: A>SET B: [RO] Sets drive B to Read-Only. ///1SETDEF Syntax: SETDEF { d: {,d: {,d: {,d:}}}} {[ TEMPORARY = d: ] | [ ORDER = (typ {,typ}) ]} SETDEF [DISPLAY | NO DISPLAY] SETDEF [PAGE | NOPAGE] Explanation: SETDEF allows the user to display or define up to four drives for the program search order, the drive for temporary files, and the file type search order. The SETDEF definitions affect only the loading of programs and/or execution of SUBMIT (SUB) files. SETDEF turns on/off the system Display and Console Page modes. When on, the system displays the location and name of programs loaded or SUBmit files executed, and stops after displaying one full console screen of information. ///2Examples A>SETDEF nitored execution, symbolic disassembly, assembly, and memory display and fill functions. SID can dynamically load SID utility programs to provide traceback and histogram facilities. ///2Commands Command Meaning As (Assemble) Enter assembly language statements s is the start address Cs{b{,d}} (Call) Call to memory location from SID s is the called address b is the value of the BC register pair d is the value of the DE register pair D{W}{s}{,f} (Display) Display memory in hex and ASCII W is a 16-bit word format s is the start address f is the finish address Epgm-filespec You must turn on password protection before you can assign passwords to files. SET [PROTECT=OFF] Disables password protection for the files on your disk. A>SET MYFILE.TEX [PASSWORD=MYFIL] MYFIL is the password assigned to file MYFILE.TEX. B>SET *.TEX [PASSWORD=SECRET, PROTECT=WRITE] Assigns the password SECRET to all the TEX files on drive B. Each TEX file is given a WRITE protect mode to prevent unauthorized editing. A>SET MYFILE.TEX [RO SYS] Sets MYFILE.TEX to Read-Only and SYStem. ///2Default A>SET [DEFAULT=dd] Instructs the system to use dd as a password if you do not enter a password for a password-protected file. ///2Time-Stamps Syntax: SET [CREATE=ON] SET [ACCESS=ON] SET [UPDATE=ON] Explanation: The above SET commands allow you to keep a record of the time and date of file creation and update, or of the last access  Displays current SETDEF parameters. A>SETDEF [TEMPORARY=C:] Sets disk drive C as the drive to be used for temporary files. A>SETDEF C:,* Tells the system to search for a program on drive C, then, if not found, search for it on the default drive. A>SETDEF [ORDER=(SUB,COM)] Instructs the system to search for a SUB file to execute. If no SUB file is found, search for a COM file. A>SETDEF [DISPLAY] Turns on the system display mode. Henceforth, the system displays the name and location of programs loaded or submit files executed. A>SETDEF [NO DISPLAY] Turns off the system Display mode. ///1SHOW Syntax: SHOW {d:}{[SPACE |LABEL |USERS |DIR |DRIVE]} Explanation: The SHOW command displays the following disk drive information: Access mode and the amount of free disk space Disk label Current user number and Number of files for each user numb (Load) Load program and symbol table {,sym-filespec} for execution E*sym-filespec (Load) Load a symbol table file Fs,f,d (Fill) Fill memory with constant value s is the start address f is the finish address d is an eight-bit data item G{p}{,a{,b}} (Go) Begin Execution p is a start address a is a temporary breakpoint H (Hex) Displays all symbols with addresses in Hex H.a Displays hex, decimal, and ASCII values of a where a is a symbolic expression Ha,b Computes hex sum and difference of a and b where and update of your files. ///3Options [CREATE=ON] turns on CREATE time stamps on the disk in the default or specified drive. To record the creation time of a file, the CREATE option must be turned on before the file is created. [ACCESS=ON] turns on ACCESS time stamps on the disk in the default or specified drive. ACCESS and CREATE options are mutually exclusive; only one can be in effect at a time. If you turn on the ACCESS time stamp on a disk that previously had CREATE time stamp, the CREATE time stamp is automatically turned off. [UPDATE=ON] turns on UPDATE time stamps on the disk in the default or specified drive. UPDATE time stamps record the time the file was last modified. ///3Examples A>SET [ACCESS=ON] er on the disk Number of free directory entries for the disk Drive characteristics ///2Examples A>SHOW A>SHOW [SPACE] Instructs the system to display access mode and amount of space left on logged-in drives. A>SHOW B: Show access mode for drive B and amount of space left on drive B. A>SHOW B:[LABEL] Displays label information for drive B. A>SHOW [USERS] Displays the current user number and all the users on drive A and the corresponding number of files assigned to them. A>SHOW C:[DIR] Displays the number of free directory entries on drive C. A>SHOW [DRIVE] Displays the drive characteristics of drive A. ///1SID Syntax: SID {pgm-filespec} {,sym-filespec} Explanation: The SID symbolic debugger allows you to monitor and test programs developed for the 8080 microprocessor. SID supports real-time breakpoints, fully mo  a and b are symbolic expressions Icommand tail (Input) Input CCP command line L{s}{,f} (List) List 8080 mnemonic instructions s is the start address f is the finish address Ms,h,d (Move) Move Memory Block s is the start address h is the high address of the block d is the destination start address P{p{,c}} (Pass) Pass point set, reset, and display p is a permanent breakpoint address c is initial value of pass counter Rfilespec{,d} (Read) Read Code/Symbols d is an offset to each address S{W}s (Set) Set Memory Values s is address where value istds: add hl,de ; dbl den, dbl side is next dpb movdpb: pop de ; this is where dpb addr goes in dph ex de,hl ; de =dpb addr, hl =loc in dph of dpb ld (hl),e ; save low byte of addr in dph inc hl ; inc pointer to high byte of addr ld (hl),d ; save high byte of addr in dph ret page ;--------------------------------------- ; SET TRANSLATION VECTOR ADDRESS IN DPH ;--------------------------------------- settran: ld hl,(cdph) ld a,(cdsd) ; get dsd setting bit 3,a ; chk denisty bit ld de,0 ; initalize de-reg w. tran vec addr jr nz,sett ; jump if double density, (no trn vec) ld de,tran8 ; initalize tran vec addr for 8" tran bit 4,a ; chk drive size bit, =0 for 8", =1 5" jr z,sett ; jump if 8" drive ld de,tran548 ; init tran vec addr for 5-48tpi sglden bit 5,a ; check bit 5 for 96 tpi drive jr z,sett ; jump if 48 tpi drive ld de,tran596 ; de gets 5"-96 tpi sgl den tran vec sett: ld (hl),e ; save tran vec addr as #1 entry in dutdata ; call errchk ; chk status for errors jr nz,fread ; loop if error and under retry count ret page ;---------------------- ; SET TASK FLOPPY DISK ;---------------------- fsettsk: ld (ixsave),ix ;save ix call ddbtoix ld a,1 ld e,(ix+secsizl) ld d,(ix+secsizh) call shfl16 ld a,d ld (xfercnt),a fset_retry: ld a,(ix+hdshf) ld de,(@sect) call shfr16 call getdsd ; put dsd addr in hl-reg ld a,(hl) ; put dsd setting in a-reg res 2,a ; reset head bit sla e ; rotate hd no. to dsd-reg position sla e ; bit 2 is where head select goes or e ; or hd sel w. den, size, and drv no. ld (cdsd),a ; save current dsd setting ld (hl),a out (fdsd),a ; send it to floppy controller reg call gettkv ld a,(hl) ; get track no. where head positioned out (ftrk),a ; set trk reg to current hd position ld bc,(@trk) ; get new track to seek ld de,(@adrv) ; get drive to do this seek on cp c ; compare w track heads positioned on  sent W is 16 bit word T{n{,c}} (Trace) Trace Program Execution n is the number of program steps c is the utility entry address. T{W}{n{,c}} (Trace) Trace Without Call W instructs SID not to trace subroutines n is the number of program steps c is the utility entry address U{W}{n{,c}} (Untrace) Monitor Execution without Trace n is the number of program steps c is the utility entry address W instructs SID not to trace subroutines V (Value) Display the value of the next available location in memory ph inc hl ; vec addr is a word ld (hl),d ; now store high byte xor a ; return w. no errors ret page ;------------------- ; SET DDB IN DDBTBL ;------------------- setddb: ld a,(cdsd) ; need this to fig what kind of dsk ld hl,fddb8 ; init hl for 8" sgl sid, sgl den bit 4,a ; check bit 4 for siz, 8"=0, 5"=1 jr z,setddd ; jump to density chk if 8" drv ld hl,fddb548 ; init hl w 5"-48 tpi sgl sid, den bit 5,a ; check bit 5 for tpi, 0=48tpi, 1=96tpi jr z,setddd ; jump to chk den if 48 tpi ld hl,fddb596 ; set hl w. 5"96tpi ddb addr setddd: bit 3,a ; chk bit 3 for density, 0=sgl 1=dbl jr z,mvddb ; jmp if sgl, hl alrdy has addr ld de,07d ; point to next ddb, (sgl sid, dbl den) add hl,de ; add in offset to next ddb bit 2,a ; chk # sides, 0 =1 side, 1 =2 side jr z,mvddb ; jump ovr if sgl sided add hl,de ; add in offset again for next ddb mvddb: push hl ; save ddb addr ld hl,ddbtbl ; destination of ddb addr is in ddbtbljr nz,diftrk ; if different, do seek to reload heads ld a,(lastdrv) ; get last drive seek done on cp e ; compare last drive with current drive jr z,samtrk ; if same, then same drive and track page diftrk: ld a,e ; save new drive as old drive ld (lastdrv),a ; this will mak sure we ld hds if need ld a,c ; save new track ld (hl),a ; save it in trk vec as new hd position call fseek ; position heads over new track samtrk: ld a,(@sect) ; now set sector no. reg. and (ix+secmsk) ; mask out head no. bits ld hl,cdsd ; point to current dsd setting bit 3,(hl) ; density is bit 3 jr z,fsndsec ; jmp ovr if single density inc a ; dbl den, so mak sec no frm 0-7 to 1-8 fsndsec: out (fsec),a ; send it to fpy controller sec reg xor a ; flag success restore_ix: ld ix,(ixsave) ret ; return with status in A reg & z/nz status page ;-------------------- ; FLOPPY ERROR CHECK ;-------------------- errchk: ld hl,rtcnt in a,(fstat) a) ld a,(cdsd) ; get dsd reg setting w. sgl den or c ; or in dbl density setting ld (cdsd),a ; save it and return ret page getsd: ret ;---------------- ; SET DPB IN DPH ;---------------- setdpb: ld hl,(cdph) ld de,0ch ; pnt to dpb entry of dph add hl,de ; dbp addr in dph is 10th entry push hl ; save addr of dpb address on stk tstsiz: ld a,(cdsd) ; fetch dsd register setting ld hl,fdpb8 ; ld hl w. dpb base for 8" floppy bit 4,a ; check drv siz bit jr z,tstden ; jump if 8" drv ld hl,fdpb548 ; ld hl w. dpb base for 5"-48 tpi fpy bit 5,a ; check 96 tpi bit (** not standard **) jr z,tstden ; jump if 48 tpi drive ld hl,fdpb596 ; ld hl w. dpb base for 5"-96 tpi fpy tstden: bit 3,a ; test density bit of dsd jr z,movdpb ; sgl den dpb = dpb base setdd: ld de,17d ; double den, sgl side is next dpb add hl,de ; index down to next ddb tstsid: bit 2,a ; test if double sided jr z,movdpb ; hl is pointing to dbl den, sgl sd se ld de,(@adrv) ; ea. entry in tbl is current ddb addr ld d,0 ; zero high byte for dbl add add hl,de ; hl now has destination address add hl,de ; table entrys are words pop de ; restore ddb addr into de-reg ld (hl),e ; hl-reg has ddbtbl addr inc hl ; pnt to where high byte goes ld (hl),d ; finish storing ddp addr in ddbtbl ld hl,dsd add hl,de ld a,(cdsd) ld (hl),a ret page ;------------------- ; WRITE FLOPPY DISK ;------------------- fwrite: call fsettsk ; set up cntr reg & gen housekeeping ret nz ; ret if failed to set up call getdata call fwrtsec ; write sector to floppy call errchk ; check floppy cntr status for errors jr nz,fwrite ; loop if error ret rmsg: 0dh,0ah,'Rd',0 ;------------------ ; READ FLOPPY DISK ;------------------ fread: ;ld hl,rmsg ;call pmsg? call fsettsk ; set controller reg & do housekeeping ret nz ; ret if failed to set up call frdsec ; read a sector from floppy call p!nd a jr z,errx inc (hl) ld a,rtrys cp (hl) ;nz means try again ld a,dsk_io_err ;disk io error flag ret errx: ld (hl),a ; clear retry cnt in case had to retry ret ; return w. no errors ;---------------------- ; RESTORE FLOPPY HEADS ;---------------------- frestore: ld a,(cdsd) ; get physical drive to do restore on out (fdsd),a ; send it to floppy controller call tstrdy ; test it drive is ready ret nz ; return if user abort ld a,frst ; load floppy restore at proper stp rte out (fcmd),a ; send restore command in a,(fwait) ; wait until command finished executing call gettkv ; put track vector address in hl xor a ; clear zero-flag, used as error flag ld (hl),a ; store a zero in track vector ret page ;--------------------- ; SEEK TRACK IN A-REG ;--------------------- fseek: ld b,a ; track to seek passed in a-reg call tstrdy ; wait for drive to become ready ret nz ; return w nz-flay set if user abort ldrdout: in a,(fstat) ; check for any errors and a ; set nz-flag if errors ei ; enable cnsole interupts ret page ;------------------------------- ; TEST IF FLOPPY DRIVE IS READY ;------------------------------- tstrdy:: ld a,0d0h ; reset floppy controller out (fcmd),a ; set status reg to current state call delay ; must delay before reading status ld a,(cdsd) ; test if 8 inch drive bit 4,a ; bit 4 =0 if 8", bit 4 =1 if 5" ld de,0ffffh ; set up time out counter jr z,tready ; skip index pulse tests if 8 in. drv ld hl,tstnidx ; test for no index pulse if 5 in. drv tstnidx: in a,(fstat) ; check no idx to make sure dsk in drv bit 1,a ; bit 1 =1 if index detected jr nz,decde ; decrement counter if index found ld hl,tstidx ; test for index pulse if 5 in. drv tstidx: in a,(fstat) ; check for an index pulse bit 1,a ; bit 1 on status is =0 if no index jr z,decde ; dec time out counter if no index yet tready: ld hl,tstrdx ; test (NEXT), the next location after the largest file read in (MSZE), the current value of the Program counter (PC), and the address of the end of available memory (END) Wfilespec,s,f (Write) Write the contents of a contiguous block of memory to filespec. f is finish address X{f}{r} (Examine) Examine/alter CPU state. f is flag bit C,Z,M,E or I. r is register A,B,D,H,S or P. ///2Examples A>SID CP/M 3 loads SID from drive A into memory. SID displays the # prompt when it is ready to accept commands. A>B:SID SAMPLE.HEX CP/M 3 loads SID and the program file SAMPLE.HEX into memory from drive B. ///2Utilities SID u a,b ; move trk no bk to a, (tstrdy uses a) fseekntst: out (fdata),a ; load trk to sek into data register ld a,fsek ; load a-reg w seek cmd out (fcmd),a ; tell controller to seek the track call delay ; must delay 28 us before reading stat in a,(fwait) ; wait until done with seek in a,(fstat) ; read floppy staus register and 018h ; check for crc and/or seek error ret page ;-------------------------- ; WRITE A SECTOR TO FLOPPY ;-------------------------- fwrtsec: in a,(fstat) ; first check if write protected bit 6,a ; if bit 6 of stat =1, then protected jr nz,wrtpro ; tell user if protected ld hl,diskbf ; source starting address ld c,fdata di ; dont want to be intr or will lose dta ld a,fwrt ; start write by sending command out (fcmd),a ; tell ctrler to wrt sec call delay ; mak sure wait 28 us before stat rd fwrtlp: in a,(fwait) ; check if in floppy interupt or a ; interupt is bit 7 of fwait, 0=active jp p,fwrtout ; if  for drive ready 8-5 in. drv tstrdx: in a,(fstat) ; get floppy status bit 7,a ; test not ready bit in status ret z ; return if not ready bit =0 decde: call delay ; delay even move before decrement dec de ; decrement counter in de-reg ld a,d ; check if counter is zero or e ; or high - low byte together jr z,notready ; jump if time out error jp (hl) ; jump to tstnidx, tstidx or tstrdx notready: ld de,nrdymsg ; pass disk err actual error msg call dskerr ; display msg and drv on console jr z,tstrdy ; retry if user didn't type ctrl-c ret page ;------------------- ; FLOPPY DISK ERROR ;------------------- dskerr: push bc push de call pderr? ; display T-????, S-???? msg on console pop hl ; restore pnter to err msg call pmsg? ; display exact error msg on console call conin? ; wait for user to type a character ld (char_save),a cp 003h ; check if ctrl-c typed push af ld hl,crlfmsg call pmsg? pop af pop bc jr tilities, HIST.UTL and TRACE.UTL are special programs that operate with SID to provide additional debugging facilities. The mechanisms for system initialization, data collection, and data display are described in the CP/M SID User's Guide. The HIST utility creates a histogram (bar graph) showing the relative frequency of execution of code within selected program segments of the test program. The HIST utility allows you to monitor those sections of code that execute most frequently. The TRACE utility obtains a backtrace of the instructions that led to a particular breakpoint address in a program under test. You can collect the addresses of up to 256 instructions between pass points in U or T modes. ///1SUBMIT Syntax: SUBMIT {filespec} {argument} ... {argument} Explanation: The SUBMIT command lets you execute a group (batch) of commands from a SUBmit file (a file with filzero then no more data 1=nactive outi ; else send dta, inc buf addr jr fwrtlp ; loop until done fwrtout: in a,(fstat) ; read status for errors and a ; set nz flg if no errors ei ; enable console interupts ret wrtpro: ld de,wprtmsg ; pass write prot msg in de to dskerr call dskerr ; call rout to prn msg and wait for cio jr z,fwrtsec ; try again if user didnt type ctrl-c ret ; else return w nz flg set page ;--------------------------- ; READ A SECTOR FROM FLOPPY ;--------------------------- frdsec: ld hl,diskbf ; source starting address ld c,fdata di ; disable console interupts ld a,frd ; start read by sending command out (fcmd),a ; tell ctrler to read sector call delay ; mak sure wait 28 us before rding stat frdlp: in a,(fwait) ; wait until ctrler rdy to snd dta or a ; check if interupt active jp p,frdout ; if bit 7 =0, then inter active ini ; else rd dta, increment buff addr jr frdlp ; loop until interupt =0 fz,diskerr ; jmp ovr retry if ctrl-c ld a,0d0h ; reset floppy controller out (fcmd),a call delay xor a ; set z-flag ret diskerr: or a ; if here, ctrl-c entered, set nz-flag ld a,rtrys-1 ; load a w. no. of retrys minus 1 ld (rtcnt),a ; no retrys, errchk inc rtcnt first ret page ;------------------ ; GET TRACK VECTOR ;------------------ gettkv: ld hl,trkvec ; base addr of trk vec ld de,(@adrv) ; offset into trk vec ld d,0 ; prepare for double add add hl,de ; add offset to base addr ret ;------------------------------- ; GET DENSITY-SIZE-DRIVE VECTOR ;------------------------------- getdsd: ld hl,dsdvec ; load hl w. login vec base addr ld bc,(@adrv) ; fetch logical drv no. ld b,0 ; zero out high byt to prep for dbl add add hl,bc ; add in offset to login vector ret ;------------------------------- ; DELAY 28u SECONDS AT 6 mhz ;------------------------------ delay:: ld a,3 ; initialize loop counter delaylp: ex (sp!etype of SUB). ///2Subfile The SUB file can contain the following types of lines: Any valid CP/M 3 command Any valid CP/M 3 command with SUBMIT parameters ($0-$9) Any data input line Any program input line with parameters ($0 to $9) The command line cannot exceed 135 characters. The following lines illustrate the variety of lines which may be entered in a SUB file: DIR DIR *.BAK MAC $1 $$$4 PIP LST:=$1.PRN[T$2 $3 $5] DIR *.ASM PIP SUBMIT A>SUBMIT SUBA A>SUBMIT AA ZZ SZ A>SUBMIT B:START DIR E: ///2PROFILE.SUB Everytime you power up or reset your computer, CP/M 3 looks for a special SUBmit file named PROFILE.SUB to exNumber of time/date directory entries: Number of free directory entries: Active User :Active Files:# of files :Label for drive AccessCreate on off on on off on off 1}1}{o&" >0 ͑*!& ~ :!<2!*!& " 2 h2 !!6>!!Y*!& 6:!<2!;6f!$ 6(2! 6D~!% 6ͱ!!6>!!*!& ~2 ʺ*!& N*!Mz:!<2!†v! q* & ! p+q* ~* N* #"     :$ e! 4~<<+~He  MC]! 6  ! p+q * DM }! q* &:~ҝ:}¦:}`O! : ½2}Õ! p+q* ~?2~* 2}͕2}͕! p+q* !Z 6Z 1!Z 6,Z 1!Z 6]Z 1|"  ! q* &.! q* &e! p+qi* DM! q: <2 O* : w! p+q* ~$* : <2 O* w* #" ! q: 0Oͦ! q: TITLE 'Root module of relocatable loader BIOS for CP/M 3.0' .Z80 ; version 1.0 15 Sept 82 TRUE EQU -1 FALSE EQU NOT TRUE BANKED EQU TRUE ; Copyright (C), 1982 ; Digital Research, Inc ; P.O. Box 579 ; Pacific Grove, CA 93950 ; This is the invariant portion of the modular BIOS and is ; distributed as source for informational purposes only. ; All desired modifications should be performed by ; adding or changing externally defined modules. ; This allows producing "standard" I/O modules that ; can be combined to support a particular system ; configuration. CR EQU 13 LF EQU 10 BELL EQU 7 CTLQ EQU 'Q'-'@' CTLS EQU 'S'-'@' CCP EQU 0100H ; Console Command Processor gets loaded into the TPA ; variables in system data page ; user defined character I/O routines EXTRN CO?,ci?,cist? ; each take device in ; disk communication data items EXTRN @DTBL ; table of pointers to XDPHs PUBLIC @ADRV,@RDRV,@TRK,@SECT ; parameters for decute. If it does not exist, CP/M 3 resumes normal operation. If the PROFILE.SUB file exists, the system executes the commands in the file. This file is convenient to use if you regularly execute a set of commands before you do your regular session on the computer. ///1TYPE Syntax: TYPE {filespec {[ PAGE | NOPAGE ]}} Explanation: The TYPE command displays the contents of an ASCII character file on your screen. [PAGE] Causes the console listing to be displayed in paged mode; i.e., stop automatically after listing n lines of text, where n normally defaults to 24 lines per page. [NOPAGE] Turns off Console Page Mode and continuously displays a typed file on the screen. ///2Examples A>TYPE MYPROG.PLI Displays the contents of the file MYPROG.PLI on your screen. A>TYPE B:THISFILE [PAGE] Displays the contents of the file THISFILE from d),hl ; 19 cycles ex (sp),hl ; 19 cycles dec a ; 4 cycles jr nz,delaylp ; 10 cycles = 52 cyc = 8.7 @ 6 mhz ret page ;------------------------------------------------ ; DATA STORAGE ;------------------------------------------------ nrdymsg: db ', Drive Not Ready',0 wprtmsg: db ', Write Protected Disk',0 crlfmsg: db 0dh,0ah,0 medmsg:: db 0dh,0ah,'Media change: I = ignore, RET = accept, ^C = error abort',0 char_save:: ds 1 cdph: dw 0 cdsd:: db 0 lastdrv: db 0ffh rtcnt: db 0 ; retry counter dsdvec: ds 16,0ffh ; drive login vector trkvec: ds 16,0ffh ; current head position on drive ixsave: ds 2 noflag::ds 1 ; drive # exempt from media chng end  ; CONSOLE OUTPUT STATUS ;----------------------- cost?:: in a,(1) ; get status and 4 ; ready? ret z ; no or 0ffh ; else set ready ret ; and exit end isk I/O PUBLIC @DMA,@CNT,@DBNK ; '' '' '' '' ; general utility routines PUBLIC PMSG?,PDEC? ; print message, print number from 0 to 65535 PUBLIC PDERR? ; print BIOS disk error message header MACLIB MODEBAUD.LIB ; define mode bits ; External names for BIOS entry points PUBLIC BOOT?,WBOOT?,CONST?,CONIN?,CONO?,LIST?,AUXO?,AUXI? PUBLIC HOME?,SLDSK?,STTRK?,STSEC?,STDMA?,READ?,WRITE? PUBLIC LISTS?,SCTRN? PUBLIC CONOS?,AUXIS?,AUXOS?,DVTBL?,DEVIN?,DRTBL? PUBLIC MLTIO?,FLUSH?,MOV?,TIM?,BNKSL?,STBNK?,XMOV? ; BIOS Jump vector. ; ; All BIOS routines are invoked by calling these ; entry points. ;Public Local BIOS Description ;Name Routine Func BOOT?: ret ; 00 initial entry on cold start db 0,0 WBOOT?: JP $ ; 01 reentry on program exit, warm start CONST?: JP cist? ; 02 return console input status CONIN?: JP ci? ; 03 return console input character CONO?: JP CO? ; 04 send console output character LIST?: JP $ ; 05 send list ourive B on your screen twenty four lines at a time. ///1USER Syntax: USER {number} Explanation: The USER command sets the current user number. The disk directory can be divided into distinct groups according to a "User Number." User numbers range from 0 through 15. ///2Examples A>USER Enter User#:5 5A> The current user number is now 5 on drive A. A>USER 3 3A> This command changes the current User Number to 3. ///1XREF Syntax: XREF {d:} filename {$P} Explanation: XREF provides a cross-reference summary of variable usage in a program. XREF requires the .PRN and .SYM files produced by MAC or RMAC for input to the program. The SYM and PRN files must have the same filename as the filename in the XREF command tail. XREF outputs a file of type .XRF. Examples: A>XREF b:MYPROG A>XREF b:MYPROG $P ILE.S !+2 !  +~d {   O! w+w+: =w! 5 c ʋ  :p  m>> ͧ  N Ĩ –.~+w.~2  9 : ! ~##~ !7 : !Կ : x*l " !ZXچ! 6  zz: 6 : %2p  ͆ : =̀ 2r  DIR TYPE ERASE RENAME DIRSYS USER u"Q}:\=p:r Aæ R ÂN ͙ʸ} !M 545 x ]  ̵ 6 : oG! ~怹>2M  xf>:ͦ ͤ ͍ ͤ f ¹2 lf   ͫR  L͞L I *  *  A }_Yl !ͮ ͒6 \&đ %* "l ͍  ûȷ45: w ? A I N   SUBMIT COM ! ͮ ! 6 #"l  !cͿ  O!:r :ͦ ͍ !~B I !pͰ ^#VCOM SUB PRL y!cͰ  î !" * %.2P#ͮ !g 4*l +"l ͷ 2 "Qx2Sl "Tx2V!q ~ :p ͆ .ڶ2* og$2| .w#w#w#w"tput character AUXO?: JP $ ; 06 send auxilliary output character AUXI?: JP $ ; 07 return auxilliary input character HOME?: JP HOME ; 08 set disks to logical home SLDSK?: JP SELDSK ; 09 select disk drive, return disk parameter info STTRK?: JP SETTRK ; 10 set disk track STSEC?: JP SETSEC ; 11 set disk sector STDMA?: JP SETDMA ; 12 set disk I/O memory address READ?: JP READ ; 13 read physical block(s) WRITE?: JP WRITE ; 14 write physical block(s) LISTS?: JP $ ; 15 return list device status SCTRN?: JP SECTRN ; 16 translate logical to physical sector CONOS?: JP $ ; 17 return console output status AUXIS?: JP $ ; 18 return aux input status AUXOS?: JP $ ; 19 return aux output status DVTBL?: JP $ ; 20 return address of device def table DEVIN?: JP $ ; 21 change baud rate of device DRTBL?: JP $ ; 22 return address of disk drive table MLTIO?: JP $ ; 23 set multiple record count for disk I/O FLUSH?: JP $ ; 24 flush BIOS maintained disk caching MOV?: JP moL ; create index from drive code LD BC,@DTBL ADD HL,BC ; get pointer to dispatch table LD A,(HL) INC HL LD H,(HL) LD L,A ; point at disk descriptor OR H RET Z ; if no entry in table, no disk LD A,E AND 1 JP NZ,NOT$FIRST$SELECT ; examine login bit LD (loc$stk),SP ;setup local stack ld SP,loc$stk PUSH HL EX DE,HL ; put pointer in stack & LD HL,-2 ADD HL,DE LD A,(HL) LD (@RDRV),A ; get relative drive LD HL,-6 ADD HL,DE ; find LOGIN addr LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of LOGIN routine CALL IPCHL ; call LOGIN POP HL ; recover DPH pointer ld SP,(loc$stk) ;restore stack NOT$FIRST$SELECT: RET ; HOME ; Home selected drive. Treated as SETTRK(0). HOME:: LD BC,0 ; same as set track zero ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. SETTRK:: LD (@TRK),BC RET ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further on ',0 TRACK$MSG: DB ': T-',0 SECTOR$MSG: DB ', S-',0 ; disk communication data items @ADRV: DS 1 ; currently selected disk drive @RDRV: DS 1 ; controller relative disk drive @TRK: DS 2 ; current track number @SECT: DS 2 ; current sector number @DMA: DS 2 ; current DMA address @CNT: DB 0 ; record count for multisector transfer @DBNK: DB 0 @ermde:: db 0 ; fake BDOS error mode endaddr:: END  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 ret end ve?## ; 25 block move memory to memory TIM?: JP $ ; 26 Signal Time and Date operation BNKSL?: JP $ ; 27 select bank for code execution and default DMA STBNK?: JP $ ; 28 select different bank for disk I/O DMA operations. XMOV?: JP $ ; 29 set source and destination banks for one operation JP $ ; 30 reserved for future expansion JP $ ; 31 reserved for future expansion JP $ ; 32 reserved for future expansion ds 32 loc$stk:: dw 0 ; ; Utility subroutines ; IPCHL: ; vectored CALL point JP (HL) PMSG?: ; print message @ up to a null ; saves & ld (loc$stk),SP ld SP,loc$stk PUSH BC PUSH DE PMSG$LOOP: LD A,(HL) OR A JP Z,PMSG$EXIT LD C,A PUSH HL CALL CONO? POP HL INC HL JP PMSG$LOOP PMSG$EXIT: POP DE POP BC ld SP,(loc$stk) RET PDEC?: ; print binary number 0-65535 from LD BC,TABLE10 LD DE,-10000 NEXT: LD A,'0'-1 PDECL: PUSH HL INC A ADD HL,DE JP NC,STOPLOOP INC SP INC SP JPoperations. SETSEC:: LD (@SECT),BC RET ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @CBNK ; so that further disk operations take place ; in current bank. SETDMA:: LD (@DMA),BC ret ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returns physical=logical. SECTRN:: LD L,C LD H,B LD A,D OR E RET Z EX DE,HL ADD HL,BC LD L,(HL) LD H,0 RET ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter header (XDPH). READ: ld (loc$stk),SP ;set up local stack ld SP,loc$stk LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-8 AD&  ͦ*!M *!M * ~& *!M! !p+q!" !* !"  " * ~~He Q ! 6 Þ * ~~Hқ ! 6* ~2 ͢ * &* " !Þ !-!p+q!!6.*,!DM! -¶ !' !.!6> !.! *.!& ! N:.!<2.! \* ##N!ͥ"/!!1!q:1!2 Oͅ !3!p+q!2!* >2!y#M͹!7!s+q+p+q:7!=27!f*4!:6!w*4!#"4!I!!s+p+q+p+q>!*!*!͆!!s*!*!͆"!*!! ͆"!>!º:!:!!!6:!0Ov!!p+q!'"!!!6>!8*!*!͆:!=2!O!8! s*!*!͆"!*!! ͆"!!!6#6:!=2!}*!&8! ~0O~:!:!Hz,~A!!q*!&8! ~¤:!Ҥ:!ʤ*!M!!6!!r+s+p+q!!6#6>!!0*!&*!*!&*!~!!#N*! w*!&*!^! ͆!!s#N*! ^! ͆*!&*!q:!<2!!!p+q8!<?!<*!N#F*!##~2!!!6>!!ڙ:!҇*!&w!) N#F?!ͱ:!2!:!<2!d8!?!ͱ9!!p+q*!##~2!*!##~*!##w*!*!q#p*!#:!*!#w!!p+q*!#* ##N͹ PDECL STOPLOOP: PUSH DE PUSH BC LD C,A CALL CONO? POP BC POP DE NEXTDIGIT: POP HL LD A,(BC) LD E,A INC BC LD A,(BC) LD D,A INC BC LD A,E OR D JP NZ,NEXT RET TABLE10: DW -1000,-100,-10,-1,0 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 cono? PDERR?: LD HL,DRIVE$MSG CALL PMSG? ; error header LD A,(@ADRV) ADD A,'A' LD C,A CALL CONO? ; drive code LD HL,TRACK$MSG CALL PMSG? ; track header LD HL,(@TRK) CALL PDEC? ; track number LD HL,SECTOR$MSG CALL PMSG? ; sector header LD HL,(@SECT) CALL PDEC? ; sector number RET ; Disk I/O interface routines ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke login procedure for drive ; if this is first select. Return ; address of disk parameter header ; in SELDSK:: LD A,C LD (@ADRV),A ; save drive select code LD L,C LD H,0 ADD HL,HD HL,DE ; point to read routine address JP RW$COMMON ; use common code ; WRITE ; Write physical sector from currently selected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). WRITE: ld (loc$stk),SP ;set up local stack ld SP,loc$stk LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-10 ADD HL,DE ; point to write routine address RW$COMMON: LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of routine POP DE ; recover address of table DEC DE DEC DE ; point to relative drive LD A,(DE) LD (@RDRV),A ; get relative drive code and post it INC DE INC DE ; point to DPH again call IPCHL ; leap to driver ld SP,(loc$stk) ;restore stack pointer ret ; error message components DRIVE$MSG: DB CR,LF,BELL,'BIOS Error " title MOVE MODULE -- CP/M 3.0 NON-BANKED .z80 xmove?:: ret ; no inter bank moves move?:: ex de,hl ; passed source in de and dest in hl ldir ; use Z80 block move instruction ex de,hl ; ret w. next addresses in same regs ret bank?:: ret ; no bank select in non-banked system end BYTE CP (HL) ;CHECK IT RET Z ;RETURN IF OK PUSH HL ;SAVE ADDRESS LD HL,M4 ;TYPE ERROR CALL MSG ;PRINT IT POP HL ;RESTORE ADDRESS STOREA:: CALL THXW ;TYPE BAD ADDRESS JP NEXT ;RETURN TO MONITOR ; ; ; MEMORY EXAM/MODIFY ROUTINES ; ; GETAD:: CALL GHXW ;GET ADDR. JP NC,GTA1 ;JMP IF VALID ILLCH:: LD HL,M3 ;ILLEGAL INPUT JP ILLEG+3 GTA1:: LD (ADR),HL ;SAVE ADDR. LOCAT:: CALL CRET ;GET CR,LF LD HL,(ADR) ;GET ADDR. CALL THXW ;PRINT IT CALL SPACE LD A,(HL) CALL THXB ;PRINT MEMORY CONTENTS CALL SPACE CALL GHXB ;GET DATA OR COMMAND JP C,NONHX ;NON-HEX INPUT CALL LD A,(HL) CP ts JP NZ,sexit INC HL LD A,(HL) CP 'B' CALL Z,rst38 sexit: LD SP,centry ;go to the cold boot system entry point RET readfile: OR A LD D,A LD E,0 LD A,H RLA LD H,A frdlp: EX DE,HL LD BC,-128 ADD HL,BC EX DE,HL PUSH DE PUSH HL CALL setdma CALL read POP HL POP DE DEC H JP NZ,frdlp RET setdma: LD C,26 ;set dma adr in de CALL bdos RET read: LD C,20 ;read sequential LD DE,fcb CALL bdos OR A LD DE,readbd RET Z fatal: LD C,9 ;print string CALL bdos DI HALT rst38: RST 38h RET page ; FCB fcb: db 0,'CPM3 SYS' ds 24,0 openbd: db cr,lf,'CPMLDR error: failed to open CPM3.SYS',cr,lf,ts readbd: db cr,lf,'CPMLDR error: failed to read CPM3.SYS',cr,lf,ts signon: db cr ds 24,lf db 'CP/M V3.0 Loader',cr,lf db 'Copyright (C) 1982, Digital Research',cr,lf,ts db '021182' ds 4,0 stack: header: ;data pulled from cpm3.sys header rec respg: db 0eh ;top page+1 of title ldrbios hard disk loader .z80 ;ports sioad equ 00h sioac equ 01h siobd equ 02h siobc equ 03h ctc0 equ 08h ctc1 equ 09h ctc2 equ 0ah ctc3 equ 0bh baudrd equ 15h baudwr equ 18h bank0 equ 16h ldrsiz equ 0a00h ;size of cpmldr bufsiz equ 100h ;size of buffer area before cpmldr csize equ ldrsiz + bufsiz ; size of cpmldr + buffer bbase equ $ ; bios base kbase equ bbase - csize ; = move base zbase equ 0c000h ; = start of common memory lsize equ pend - kbase ; = size to move page 60 BOOT?: jp init JP nn JP nn JP nn JP CO? JP nn JP nn JP nn JP HOME JP SELDSK JP SETTRK JP SETSEC JP SETDMA JP hread JP nn JP nn JP SECTRN JP nn JP nn JP nn JP nn JP nn JP nn JP nn JP nn JP move? JP nn JP nn JP nn JP nn JP nn JP nn nn: JP nn page init: di in a,(baudrd) ;set baud rate for crt out (baudwr),a ld hl,inisio ld bc,800h + sioac otir ld hl,inisio ld bc,800h + si#6:!<2!!"X 5!"!:}:}2!*!& ~2!:!!*!& "!*!##"!*!#"!:!2!:!2!O!& 6>!!Ґ*!* ~Ҥ*!~*!&6 ) N#F*!&6 ) q#p*X #"X %* & 6>!X * N#F`i"X * N#FPY*X *!"V 8QhOg 8`* & ~/\!!6>!!ڐ*!&& ~҆*!&g:!<2!a 8o!!6>!!*!&& ~*!&6 ) N#Fg:!<2!¡͘* & ~/͘!!qD>!! :}0:}`O! ~ * * Ḿ2!>!!/:}o&"!~i8 Eiji:!@@†Ìi B:% /:!րHҽ:!@@:!:! *! DM͟ *! DM͟ >͑: AO !!6> !!x:! ].*!&*!>O:!<2!G!!q!!6*!& :•>*!& :!©:!:!<2!Â!!r+s+p+q)!!6?:!:!2!*!My2 !!6: ]:!/ *!Mresident portion reslen: db 16 ;length bnkpg: db 33h ;top page+1 of banked portion bnklen: db 6ah ;length centry: dw 1b48h ;cold boot entry point ds 6,0 bdos: end  End global equates ; Customization section sign_on macro ;Cold boot sign on message db cr,lf ;,esc,'g',esc,'f',esc,'G0',cr,0fh db 'CP/M 3.0 for Source Maverick',cr,lf,lf,0 endm media_check_en equ true ;true if able to check for disk change two_sides equ false ;true if double-sided drives ; -- must be false, not implemented mini equ false ;true if 5" drive(s) in system base_track equ 0 ;base track for login read adr booter equ 4 ;boot disk -- A: = 1, B: = 2,... ; End of customization section .cref .list obc otir ld a,2 ;ctc reset byte out (ctc0),a out (ctc1),a out (ctc2),a out (ctc3),a ld hl,kbase ;move to common area ld de,zbase ld bc,lsize ldir jp cinit .phase ($-bbase) + csize + zbase cinit: ld a,01101111b ;enable memory, turn prom out (bank0),a ; and power on jump off ld hl,zbase ;move back to bank 0 lower ld de,kbase ld bc,lsize ldir jp einit .dephase einit: ret ; SIO init data inisio: db 018h,004h,044h,003h,0c1h,005h,0eah,0 page move?: ex de,hl ldir ex de,hl ret ;---------------- ; CONSOLE OUTPUT ;---------------- co?: in a,(sioac) ; get status and 4 ; ready? jr z,co? ; no, jump ld a,c ; put character to send in a out (sioad),a ; send char to sio ch a ret page ; Disk I/O interface routines SELDSK: LD A,E AND 1 ;first time? call z,hlogin ;yes, call ld hl,hdph RET HOME: LD BC,0 ; same as set track zero SETTRK: LD (@TRK),BC RET SETSECtitle cpmldx cpm loader executive .z80 biosoff equ 0a00h cr equ 13 lf equ 10 ts equ '$' what? equ $+0ff5dh ;probably supposed to be 005dh buff equ $-128 start: LD SP,stack CALL start+biosoff ;do bios reset (boot call) LD C,13 ;reset disk system CALL bdos LD C,9 ;print string LD DE,signon CALL bdos LD C,15 ;open file LD DE,fcb CALL bdos CP 0ffh ;bad open? LD DE,openbd JP Z,fatal ;yes, jump LD DE,buff ;get the header record CALL setdma CALL read LD HL,buff LD DE,header LD C,6 mvhdlp: LD A,(HL) ;get first 6 bytes of header LD (DE),A INC DE INC HL DEC C JP NZ,mvhdlp CALL read ;read print record LD C,9 ;print string LD DE,buff CALL bdos LD A,(reslen) ;load the resident portion LD H,A LD A,(respg) CALL readfile LD A,(bnklen) OR A ;banked? JP Z,nobank ;no, jump LD H,A ;load the banked portion LD A,(bnkpg) CALL readfile nobank: LD HL,what? ;do rst 38h if (005d) = '$B' #: LD (@SECT),BC RET SETDMA: LD (@DMA),BC ret SECTRN: LD L,C LD H,B RET page ;------------------------------------ ; HDC-1001 CONTROLLER PORT ADDRESSES ;------------------------------------ hbase equ 0e0h ; base port address of hdc-1001 hdata equ hbase+0 ; data register herror equ hbase+1 ; error register hwrtpre equ hbase+1 ; write pre-compensation register hseccnt equ hbase+2 ; sector count register hsec equ hbase+3 ; sector number register hcyllow equ hbase+4 ; cylinder low register hcylhi equ hbase+5 ; cylinder high register hsdh equ hbase+6 ; size - drive - head register hstatus equ hbase+7 ; status register port hcmd equ hbase+7 ; command register port cmdsek equ 070h ; seek command @ step rate 0 cmdrd equ 020h ; read sector command sdhreg equ 0a0h ; sdh reg setting -- 512 bytes/sector errbit equ 001h ; error bit sectrk equ 17 ; physical sectors/track ;----------------- ; LOGIN HARD DISK ;----------------- ;--------------- ; Hard disk DPB ;--------------- hdpb: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dw 8000h ;cks dw 0 ;off db 2 ;psh db 3 ;psm page ;------------------ ; Tables & buffers ;------------------ dirbcb: db 0ffh ;drv db 0,0,0 ;rec# db 0 ;wflg db 0 dw 0 ;track dw 0 ;sector dw dirbuf ;buffad db 0 ;bank dw 0 ;link dtabcb: db 0ffh ;drv db 0,0,0 ;rec# db 0 ;wflg db 0 dw 0 ;track dw 0 ;sector dw dtabuf ;buffad db 0 ;bank dw 0 ;link pend equ $ @trk equ $ ;ds 2 @sect equ @trk+2 ;ds 2 @dma equ @sect+2 ;ds 2 alv equ @dma+2 ;ds 256 dirbuf equ alv+256 ;ds reclen dtabuf equ dirbuf+reclen ;ds reclen end $ˆ >!$4l >:q#<2q#O*|$ :p#w:p#?± !d#6!$q!p#6?!$:q# ͒ û 2p#:p# :p#]H!:p#A2$O>!:p# ;---------------------------- ; CP/M 3.0 LOADER GENERATION ;---------------------------- link cpmldr[l100]=cpmldr,ldrbios t (for partioning by hds) db srate ; cmd register step rate db hsspt-1 ; host sec per trk - 1 (hst sec msk) shff hsspt ;;calc log2 spt endm ;;------------------------ ;; MACRO - GENERATE BCB'S ;;------------------------ rcbdcb macro dn .lall ;------------------------- ; DIRECTORY CONTROL BLOCK ;------------------------- dseg rcb&dn:: db 0ffh ; drive db 0,0,0 ; record no. db 0 ; write flag db 0 ; scratch byte dw 0 ; track no. dw 0 ; sector no. dw rcbbf&dn ; buffer address db 0 ; bank no. dw 0 ; link address ;-------------------- ; DATA CONTROL BLOCK ;-------------------- dcb&dn:: db 0ffh ; drive db 0,0,0 ; record no. db 0 ; write flag db 0 ; scratch byte dw 0 ; track no. dw 0 ; sector no. dw dcbbf&dn ; buffer address db 0 ; bank no. dw 0 ; link address ;------- hlogin: ld a,sdhreg ; drive 0 & sector size out (hsdh),a ; send it to controller xor a ; zero a-reg out (hcyllow),a ; reset cylinder low register out (hcylhi),a ; reset cylinder high register ld a,cmdsek ; load a-reg w. seek command out (hcmd),a ; seek cylinder 000 @ correct step rate call polbsy ; wait until ctrl done exec seek cmd hloglp: in a,(hstatus) and 10h ; seek complete? jr z,hloglp ; no, loop ret ;---------------- ; READ HARD DISK ;---------------- hread: call rread ret z call rread ret z call hlogin rread: call hsettsk ; first set up controller registers call hrdsec call polbsy ; check for errors ret ;-------------------- ; SET TASK HARD DISK ;-------------------- hsettsk: ld a,sdhreg ; sdh proto byte ld hl,(@sect) ld de,sectrk hsloop: or a ; divide modulo sectors/track sbc hl,de jp m,hsend inc a ; add a head bit to sdh jp hsloop hsend: add hl,de ;l = sector #, a = sdh w/headINI 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 ; ;SE!2*%DM**ѵ+)) H~#+}#<:<ʲ<77:<ʢ2~77ø~7"9:OG#Q{ozg# ""BBÃà à ÃÃ1j$|@ "H$UUT$$ $I D$BA@! B$$A IA $!"  @$@$BI!!@""$DA  $I$@! bits out (hsdh),a ; load siz drv hd register ld a,l out (hsec),a ; send to sector register ld a,(@trk) ; move lsb to a-reg for out inst out (hcyllow),a ; send low byte to cyllow reg ld a,(@trk+1) ; move msb to a-reg out (hcylhi),a ; send to cyl high ret ;---------------------------- ; READ SECTOR FROM HARD DISK ;---------------------------- hrdsec: ld a,cmdrd out (hcmd),a call polbsy ld hl,(@dma) ld bc,hdata ; 0 to b, data port to c inir inir ret ;--------------------- ; POLL BUSY HARD DISK ;--------------------- polbsy: in a,(hstatus) ; read status port and a ; set flags jp m,polbsy ; loop if busy bit set and errbit ; mask for error bit ret page reclen equ 512 ;hd sector size ;--------------- ; Hard disk DPH ;--------------- hdph: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb ;dpb dw 0 ;csv dw alv ;alv dw dirbcb ;dirbcb dw dtabcb ;dtabcb dw 0ffffh ;hash db 0 ;hash bank E 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,NDSIDE#;---------------------------- ; CP/M 3.0 LOADER GENERATION ;---------------------------- link osload.sys[l2000]=cpmldr,lkrnl,lchr,lmov,ldsk,dtbl g pop ix ; by useing ix reg we save instructions ret ;-------------------- ; 16-BIT SHIFT RIGHT ;-------------------- shfr16:: and a ; a-reg has no of shifts to perform shfrlp: ret z srl d ; shift msb first, bit 0 into carry rr e ; rotate carry into bit 7 of lsb dec a ; decrement shift counter jr shfrlp ; loop until finished ;------------------- ; 16-BIT SHIFT LEFT ;------------------- shfl16:: and a shfllp: ret z sla e rl d dec a jr shfllp xfercnt:: db 0 diskbf:: ds 0400h end {ĩ Drive Not Ready : Disk Write Protected : Cannot Read Track 0 Cannot Write Track 0 Cannot Read Track 1 *= @dtbl:: irp drvtyp, if drvtyp eq nodrive dw 0 else rep (drvty sh 8 ; ente logica drv int dmap drvmap %dno dno defl dno+1 cnt defl cnt+1 endm endif endm rept (010h-cnt) ;; fill in rest of drive map dw 0 endm .lall ;--------------------- ; DISK DEBLOCKING MAP ;--------------------- dseg .xall hpdno defl 0 fpdno defl 0 dno defl 0 ;; logical drv no. of our drvs cnt defl 0 ;; cnt of how many entrys made ddbtbl:: irp drvtyp, if drvtyp eq nodrive dw 0 else rep (drvty sh 8 ; ente logica drv int dmap debmap %dno,drvtyp dno defl dno+1 cnt defl cnt+1 endm endif endm rept (010h-cnt) ;; fill in rest of drive map dw 0 endm ;;---------------------------- ;; DISK DRIVE DATA STRUCTURES ;;---------------------------- dno defl 0 hpdno defl 0 fpdno defl 0 irp drvtyp, if drvtyp eq loader ldflg defl true endif ;;-------------------------------- ;; 5.25" 48------------------ if drvtyp eq f596 xdph %dno,%fpdno,drvtyp if frst596 eq 0ffffh cseg fdpb596:: dpb %20h,18,3,07,0,082,063,16,3,0,0,1024 dpb %21h,32,4,15,0,150,063,32,1,3,7,2048 dpb %22h,64,4,15,0,300,127,32,1,3,7,2048 dseg fddb596:: ddb %20h,0,0,128,32 ddb %21h,0,0,1024,4 ddb %22h,0,0,1024,4 tran596:: db 1,7,13,19,25,5,11,17,23,3,9,15,21 db 2,8,14,20,26,6,12,18,24,4,10,16,22 frst596 defl 0 endif dno defl dno+1 endif ;;---------------------- ;; 8" FLOPPY DISK DRIVE ;;---------------------- if drvtyp eq f8 xdph %dno,%fpdno,drvtyp if frst8 eq 0ffffh cseg fdpb8:: dpb %30h,026,3,07,0,242,063,8010h,2,0,0,1024 dpb %31h,064,4,15,0,303,127,8020h,1,3,7,2048 dpb %32h,128,4,15,0,607,255,8040h,1,3,7,2048 dseg fddb8:: ddb %30h,0,0,128,32 ddb %31h,0,0,1024,8 ddb %32h,0,0,1024,8 tran8:: db 1,7,13,19,25,5,11,17,23,3,9,15,21 db 2,8,14,20,26,6,12,18,24,4,10,16,22 frst8 defl 0 endif dno defl dno+1 endif ;;--o:O*7*/*"*"[ <:g:!,*}D!~6 !S͌rOͨ͠bbb  :G:xͨ›:ͨ: !6 :<!G: >xw>ɯw% :7!>wɯ:= x :r:G:=Ľ9xr:y!4 5~y‰5 6y͌Ҡ^I@O:=ʯ:Iy I I:µ  #I:! I I I! O͠*}S~#!""Sz-*"##">2:2*N#G2H  W W|:<ʈ:W:H2xy“:z<*"!z<~s^#V#N#FxN:TPI FLOPPY DISK DRIVE ;;-------------------------------- if drvtyp eq f548 xdph %dno,%fpdno,drvtyp if frst548 eq 0ffffh cseg fdpb548:: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; dpb %10h,18,3,7,0,81,32,16,3,0,0,1024 ;; ;;----------------------------------------------------- ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; dpb %10h,18,4,15,1,40,32,16,3,1,1,2048 ;; ;;----------------------------------------------------- dpb %10h,18,3,07,0,081,032,16,3,1,1,1024 dpb %11h,32,4,15,0,077,063,32,1,3,7,2048 dpb %12h,64,4,15,0,155,127,32,1,3,7,2048 dseg fddb548:: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; ddb %10h,0,0,128,64 ;; ;;----------------------------------------------------------------------------- ;; DMA MICRO MAGNUM 5/5 HARD DISK ;;-------------------------------- if drvtyp eq dma xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,128,5,31,1,1219,511,08000h,1,1,1,4096 dpb %dno+1,128,5,31,1,1223,511,08000h,0,1,1,4096 ddb %dno+0,0,15,256,32 ddb %dno+1,2,15,256,32 dno defl dno+2 endif ;;------------------ ;; ST 503 HARD DISK ;;------------------ if drvtyp eq st503 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,607,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------ ;; ST 506 HARD DISK ;;------------------ if drvtyp eq st506 xdph %dno,%hpdno dpb %dno+0,256,5,31,1,1215,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; TM 601S HARD DISK ;;------------------- if drvtyp eq tm601S xdph %dno,%hpdno dpb %dno+0,128,5,31,1,607,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; TM 602S HARD DISK ;;---- .xlist false equ 0 true equ not false ;;--------------- ;; DRIVE EQUATES ;;--------------- nodrive equ 00fh loader equ 0ffh f548 equ 01f0h f596 equ 01f1h f8 equ 01f2h dma equ 0200h st503 equ 0101h st506 equ 0102h tm601s equ 0103h tm602s equ 0104h tm603s equ 0105h tm603se equ 0206h tm501 equ 0107h tm502 equ 0208h tm503 equ 0209h sa602 equ 010ah sa604 equ 010bh sa606 equ 010ch sa1002 equ 010dh sa1004 equ 010eh q2010 equ 010fh q2020 equ 0210h q2030 equ 0311h q2040 equ 0412h m4010 equ 0113h m4020 equ 0214h frst8 defl 0ffffh frst548 defl 0ffffh frst596 defl 0ffffh ldflg defl false ;;------------------------------------ ;; MACRO - DISK PARAMETER DEFINITIONS ;;------------------------------------ dskdef macro drvstr .lall ;------------------ ; SYSTEM DRIVE MAP ;------------------ dseg .xall hpdno defl 0 fpdno defl 0 dno defl 0 ;; logical drv no. of our drvs cnt defl 0 ;; cnt of how many entrys made ------ ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; ddb %10h,%fpdno,0,0,256,64 ;; ;;----------------------------------------------------- ddb %10h,0,0,128,64 ddb %11h,0,0,1024,4 ddb %12h,0,0,1024,4 tran548:: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; db 1,6,11,16,3,8,13,18,5 ;; db 10,15,2,7,12,17,4,9,14 ;; ds 8,0ffh ;; ;;----------------------------------------------------- ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; db 2,3,6,7,10,11,14,15,18,19 ;; db 4,5,8,9,12,13,16,17 ;; ds 8,0ffh ;; ;;----------------------------------------------------- db 1,6,11,16,3,8,13,18,5 db 10,15,2,7,12,17,4,9,14 ds 8,0ffh frst548 defl 0 endif dno defl dno+1 endif ;;-------------------------------- ;; 5.25" 96-TPI FLOPPY DISK DRIVE ;;---------------$--------------- if drvtyp eq tm602S xdph %dno,%hpdno dpb %dno+0,256,5,31,1,1215,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; TM 603S HARD DISK ;;------------------- if drvtyp eq tm603S xdph %dno,%hpdno dpb %dno+0,384,5,31,1,1823,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;-------------------- ;; TM 603SE HARD DISK ;;-------------------- if drvtyp eq tm603SE xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,384,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,384,5,31,1,699,511,08000h,172,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 dno defl dno+2 endif ;;------------------ ;; TM 501 HARD DISK ;;------------------ if drvtyp eq tm501 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,1219,511,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------ ;; TM 502 HARD DISK ;;------------------ if drvtyp eq tm502 xdph %dno,%hpdno xdph %dno+1,%hpdno o+1,0,0,512,16 dno defl dno+2 endif ;;------------------------ ;; QUANTUM 2030 HARD DISK ;;------------------------ if drvtyp eq q2030 xdph %dno,%hpdno xdph %dno+1,%hpdno xdph %dno+2,%hpdno dpb %dno+0,384,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,384,5,31,1,2047,1023,08000h,172,2,3,4096 dpb %dno+2,384,5,31,1,2031,1023,08000h,343,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 ddb %dno+2,0,0,512,16 dno defl dno+3 endif ;;------------------------ ;; QUANTUM 2040 HARD DISK ;;------------------------ if drvtyp eq q2040 xdph %dno,%hpdno xdph %dno+1,%hpdno xdph %dno+2,%hpdno xdph %dno+3,%hpdno dpb %dno+0,512,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,512,5,31,1,2047,1023,08000h,129,2,3,4096 dpb %dno+2,512,5,31,1,2047,1023,08000h,257,2,3,4096 dpb %dno+3,512,5,31,1,2031,1023,08000h,385,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 ddb %dno+2,0,0,512,16 ddb %dno+3,0,0,512,16 dno defl dno+4 endif ;;--------------------------- ;;entry point dw hinit## ; hard initalization entry point else dw fwrite## ; floppy write sector entry point dw fread## ; floppy read sector entry point dw flogin## ; floppy login entry point dw finit## ; floppy initilazition entry point endif db pdno ; unit ifb xdn defl dn db 0 ; type = hard disk else if dtyp eq f548 xdn defl 12h db 1 ; type = 5.25" 48 tpi floppy disk else if dtyp eq f596 xdn defl 22h db 2 ; type = 5.25" 96 tpi floppy disk else xdn defl 32h db 3 ; type = 8" floppy disk endif endif endif xdph&dn:: dw 0000 ; translation vector dw 0000 ; scratch pad dw 0000 ; scratch pad dw 0000 ; scratch pad dw 0000 ; scratch pad db 0 ; scratch pad db 0ffh ; media flag if ldflg eq true genlbl %xdn ;; generate loader labels else genlb %xdn ;; generate gencpm labels endif endm ;;------------------------------ ;; MACRO - DISK PARAMETER BLOCK ;;------------------------------  dpb %dno+0,256,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,256,5,31,1,391,511,08000h,257,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 dno defl dno+2 endif ;;------------------ ;; TM 503 HARD DISK ;;------------------ if drvtyp eq tm503 xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,384,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,384,5,31,1,1611,1023,08000h,172,2,3,4096 ddb %dno+0,0,3,512,16 ddb %dno+1,0,3,512,16 dno defl dno+2 endif ;;------------------ ;; SA 602 HARD DISK ;;------------------ if drvtyp eq sa602 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,635,511,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------ ;; SA 604 HARD DISK ;;------------------ if drvtyp eq sa604 xdph %dno,%hpdno dpb %dno+0,256,5,31,1,1271,511,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------ ;; SA 606 HARD DISK ;;------------------ if drvtyp eq sa606 xdph %dno,%hpdno dpb %dno+0,38 MINISCRIBE 4010 HARD DISK ;;--------------------------- if drvtyp eq m4010 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,1915,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;--------------------------- ;; MINISCRIBE 4020 HARD DISK ;;--------------------------- if drvtyp eq m4020 xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,256,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,256,5,31,1,1783,1023,08000h,257,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 dno defl dno+2 endif if (drvtyp eq f8) or (drvtyp eq f548) or (drvtyp eq f596) fpdno defl fpdno+1 else if drvtyp gt 15 hpdno defl hpdno+1 endif endif endm if frst8 eq 0ffffh fdpb8:: ; no 8" floppy used but need label fddb8:: ; no 8" floppy used but need label tran8:: ; no 8" floppy used but need label endif if frst548 eq 0ffffh fdpb548:: ; no 5"-48 tpi drv used but need label fddb548:: ; no 5"-48 tpi drv used but need label tran548:: ; no 5"-48 tpi  dpb macro dn,spt,bsh,blm,exm,dsm,drm,cks,off,psh,psm,bsiz .lall ;---------------------- ; DISK PARAMETER BLOCK ;---------------------- cseg .xall dpb&dn:: dw spt ; cpm sectors per track db bsh ; block shift factor db blm ; block mask db exm ; extent mask dw dsm ; no. blocks on drive dw drm ; no. directory entrys rsvdir dn,drm,bsiz ;;reserved directory blocks dw cks ; no. directory entries to check dw off ; track offset db psh ; physical sector shift db psm ; physical sector mask if (dn eq 10h) or (dn eq 11h) exitm else if (dn eq 20h) or (dn eq 21h) exitm else if (dn eq 30h) or (dn eq 31h) exitm else if ldflg eq true rcbdcb dn alvcsv dn,dsm,drm endif endif endif endif endm ;;------------------------------- ;; MACRO - DISK DEBLOCKING BLOCK ;;------------------------------- ddb macro dn,hdoff,srate,hsiz,hsspt .lall ;----------------------- ; DISK DEBLOCKING BLOCK ;---------------------4,5,31,1,1907,1023,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------- ;; SA 1002 HARD DISK ;;------------------- if drvtyp eq sa1002 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,1019,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; SA 1004 HARD DISK ;;------------------- if drvtyp eq sa1004 xdph %dno,%hpdno dpb %dno+0,256,5,31,1,2039,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------------ ;; QUANTUM 2010 HARD DISK ;;------------------------ if drvtyp eq q2010 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,2043,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------------ ;; QUANTUM 2020 HARD DISK ;;------------------------ if drvtyp eq q2020 xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,256,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,256,5,31,1,2039,1023,08000h,257,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dndrv used but need label endif if frst596 eq 0ffffh fdpb596:: ; no 5"-96 tpi drv used but need label fddb596:: ; no 5"-96 tpi drv used but need label tran596:: ; no 5"=96 tpi drv used but need label endif endm ;;------------------- ;; MACRO - DRIVE MAP ;;------------------- drvmap macro dn dw xdph&dn endm ;;------------------------ ;; MACRO - DEBLOCKING MAP ;;------------------------ debmap macro dn,drvtyp if drvtyp eq f548 dw ddb&16 else if drvtyp eq f596 dw ddb&32 else if drvtyp eq f8 dw ddb&48 else dw ddb&dn endif endif endif endm ;;---------------------------------------- ;; MACRO - EXTENDED DISK PARAMETER HEADER ;;---------------------------------------- xdph macro dn,pdno,dtyp .lall ;------------------- ; DISK HEADER BLOCK ;------------------- dseg .xall ifb dw hwrite## ; hard write sector entry point dw hread## ; hard read sector entry point dw hlogin## ; hard login $-- dseg .xall ddb&dn:: dw hsiz ; host sec size ssiz hsiz ;;sdh register sector size db hdoff ; head offset (for partioning by hds) db srate ; cmd register step rate db hsspt-1 ; host sec per trk - 1 (hst sec msk) shff hsspt ;;calc log2 spt endm ;;------------------------ ;; MACRO - GENERATE BCB'S ;;------------------------ rcbdcb macro dn .lall ;------------------------- ; DIRECTORY CONTROL BLOCK ;------------------------- dseg rcb&dn:: db 0ffh ; drive db 0,0,0 ; record no. db 0 ; write flag db 0 ; scratch byte dw 0 ; track no. dw 0 ; sector no. dw rcbbf&dn ; buffer address db 0 ; bank no. dw 0 ; link address ;-------------------- ; DATA CONTROL BLOCK ;-------------------- dcb&dn:: db 0ffh ; drive db 0,0,0 ; record no. db 0 ; write flag db 0 ; scratch byte dw 0 ; track no. dw 0 ; sector no. dw dcbbf&dn ; buffer address db 0 ; bank no. dw 0 ; link address ;-------DW ?NNNN ENDM SBCD MACRO ?NNNN DB 0EDH,43H DW ?NNNN ENDM SDED MACRO ?NNNN DB 0EDH,53H DW ?NNNN ENDM SSPD MACRO ?NNNN DB 0EDH,73H DW ?NNNN ENDM SIXD MACRO ?NNNN DB 0DDH,22H DW ?NNNN ENDM SIYD MACRO ?NNNN DB 0FDH,22H DW ?NNNN ENDM SPIX MACRO DB 0DDH,0F9H ENDM SPIY MACRO DB 0FDH,0F9H ENDM PUSHIX MACRO DB 0DDH,0E5H ENDM PUSHIY MACRO DB 0FDH,0E5H ENDM POPIX MACRO DB 0DDH,0E1H ENDM POPIY MACRO DB 0FDH,0E1H ENDM EXAF MACRO DB 08H ENDM EXX MACRO DB 0D9H ENDM XTIX MACRO DB 0DDH,0E3H ENDM XTIY MACRO DB 0FDH,0E3H ENDM LDI MACRO DB 0EDH,0A0H ENDM LDIR MACRO DB 0EDH,0B0H ENDM LDD MACRO DB 0EDH,0A8H ENDM LDDR MACRO DB 0EDH,0B8H ENDM CCI MACRO DB 0EDH,0A1H ENDM CCIR MACRO DB 0EDH,0B1H ENDM CCD MACRO DB 0EDH,0A9H ENDM CCDR MACRO DB 0EDH,0B9H ENDM ADDX MACRO ?D @CHK ?D DB 0DDH,86H,?D ENDM ADDY MACRO ?D @CHK ?D DB 0FDH,86H,?D ENDM ADCX MACRORO ?N DB 28H,?N-$-1 ENDM JRNZ MACRO ?N DB 20H,?N-$-1 ENDM DJNZ MACRO ?N DB 10H,?N-$-1 ENDM PCIX MACRO DB 0DDH,0E9H ENDM PCIY MACRO DB 0FDH,0E9H ENDM RETI MACRO DB 0EDH,4DH ENDM RETN MACRO DB 0EDH,45H ENDM INP MACRO ?R DB 0EDH,?R*8+40H ENDM OUTP MACRO ?R DB 0EDH,?R*8+41H ENDM INI MACRO DB 0EDH,0A2H ENDM INIR MACRO DB 0EDH,0B2H ENDM IND MACRO DB 0EDH,0AAH ENDM INDR MACRO DB 0EDH,0BAH ENDM OUTI MACRO DB 0EDH,0A3H ENDM OUTIR MACRO DB 0EDH,0B3H ENDM OUTD MACRO DB 0EDH,0ABH ENDM OUTDR MACRO DB 0EDH,0BBH ENDM RLCR MACRO ?R DB 0CBH, 00H + ?R ENDM RLCX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 06H ENDM RLCY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 06H ENDM RALR MACRO ?R DB 0CBH, 10H+?R ENDM RALX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 16H ENDM RALY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 16H ENDM RRCR MACRO ?R DB 0CBH, 08H + ?R ENDM RRCX MACRO ?D @CHK ?D DB 0DDH, ----------- ; DIRECTORY BUFFER ;------------------ rcbbf&dn: ds 1024 ;------------- ; DATA BUFFER ;------------- dcbbf&dn: ds 1024 .xall endm ;;------------------------------------- ;; MACRO - GENERATE LABELS USED IN DPH ;;------------------------------------- genlbl macro dn dw dpb&dn ; loader drive disk parameter block dw csv&dn ; loader drive check sum vector dw alv&dn ; loader drive allocation vector dw rcb&dn ; loader drive directory control block dw dcb&dn ; loader drive data control block dw 0ffffh ; disable hashing db 0 ; hash bank endm genlb macro dn dw dpb&dn dw 0fffeh ; check sum vector dw 0fffeh ; disk allocation vector dw 0fffeh ; directory buffer control block dw 0fffeh ; data buffer control block dw 0fffeh ; directory hash table db 0 ; hash bank endm ;;---------------------------------- ;; MACRO - GENERATE ALV,CSV VECTORS ;;---------------------------------- alvcsv macro dn,dsm,drm  ?D @CHK ?D DB 0DDH,8EH,?D ENDM ADCY MACRO ?D @CHK ?D DB 0FDH,8EH,?D ENDM SUBX MACRO ?D @CHK ?D DB 0DDH,96H,?D ENDM SUBY MACRO ?D @CHK ?D DB 0FDH,96H,?D ENDM SBCX MACRO ?D @CHK ?D DB 0DDH,9EH,?D ENDM SBCY MACRO ?D @CHK ?D DB 0FDH,9EH,?D ENDM ANDX MACRO ?D @CHK ?D DB 0DDH,0A6H,?D ENDM ANDY MACRO ?D @CHK ?D DB 0FDH,0A6H,?D ENDM XORX MACRO ?D @CHK ?D DB 0DDH,0AEH,?D ENDM XORY MACRO ?D @CHK ?D DB 0FDH,0AEH,?D ENDM ORX MACRO ?D @CHK ?D DB 0DDH,0B6H,?D ENDM ORY MACRO ?D @CHK ?D DB 0FDH,0B6H,?D ENDM CMPX MACRO ?D @CHK ?D DB 0DDH,0BEH,?D ENDM CMPY MACRO ?D @CHK ?D DB 0FDH,0BEH,?D ENDM INRX MACRO ?D @CHK ?D DB 0DDH,34H,?D ENDM INRY MACRO ?D @CHK ?D DB 0FDH,34H,?D ENDM DCRX MACRO ?D @CHK ?D DB 0DDH,035H,?D ENDM DCRY MACRO ?D @CHK ?D DB 0FDH,35H,?D ENDM NEG MACRO DB 0EDH,44H ENDM IM0 MACRO DB 0EDH,46H ENDM IM1 MACRO DB 0EDH,56H ENDM IM2 MACRO DB 0EDH,50CBH, ?D, 0EH ENDM RRCY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 0EH ENDM RARR MACRO ?R DB 0CBH, 18H + ?R ENDM RARX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 1EH ENDM RARY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 1EH ENDM SLAR MACRO ?R DB 0CBH, 20H + ?R ENDM SLAX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 26H ENDM SLAY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 26H ENDM SRAR MACRO ?R DB 0CBH, 28H+?R ENDM SRAX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 2EH ENDM SRAY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 2EH ENDM SRLR MACRO ?R DB 0CBH, 38H + ?R ENDM SRLX MACRO ?D @CHK ?D DB 0DDH, 0CBH, ?D, 3EH ENDM SRLY MACRO ?D @CHK ?D DB 0FDH, 0CBH, ?D, 3EH ENDM RLD MACRO DB 0EDH, 6FH ENDM RRD MACRO DB 0EDH, 67H ENDM O ?D @CHK ?D DB 0FDH, 0CBH, ?D, 16H ENDM RRCR MACRO ?R DB 0CBH, 08H + ?R ENDM RRCX MACRO ?D @CHK ?D DB 0DDH, ; @CHK MACRO USED FOR CHECKING 8 BIT DISPLACMENTS ; @CHK MACRO ?DD ;; USED FOR CHECKING RANGE OF 8-BIT DISP.S IF (?DD GT 7FH) AND (?DD LT 0FF80H) 'DISPLACEMENT RANGE ERROR - Z80 LIB' ENDIF ENDM LDX MACRO ?R,?D @CHK ?D DB 0DDH,?R*8+46H,?D ENDM LDY MACRO ?R,?D @CHK ?D DB 0FDH,?R*8+46H,?D ENDM STX MACRO ?R,?D @CHK ?D DB 0DDH,70H+?R,?D ENDM STY MACRO ?R,?D @CHK ?D DB 0FDH,70H+?R,?D ENDM MVIX MACRO ?N,?D @CHK ?D DB 0DDH,36H,?D,?N ENDM MVIY MACRO ?N,?D @CHK ?D DB 0FDH,36H,?D,?N ENDM LDAI MACRO DB 0EDH,57H ENDM LDAR MACRO DB 0EDH,5FH ENDM STAI MACRO DB 0EDH,47H ENDM STAR MACRO DB 0EDH,4FH ENDM LXIX MACRO ?NNNN DB 0DDH,21H DW ?NNNN ENDM LXIY MACRO ?NNNN DB 0FDH,21H DW ?NNNN ENDM LDED MACRO ?NNNN DB 0EDH,5BH DW ?NNNN ENDM LBCD MACRO ?NNNN DB 0EDH,4BH DW ?NNNN ENDM LSPD MACRO ?NNNN DB 0EDH,07BH DW ?NNNN ENDM LIXD MACRO ?NNNN DB 0DDH,2AH DW ?NNNN ENDM LIYD MACRO ?NNNN DB 0FDH,2AH EH ENDM BC EQU 0 DE EQU 2 HL EQU 4 IX EQU 4 IY EQU 4 DADC MACRO ?R DB 0EDH,?R*8+4AH ENDM DSBC MACRO ?R DB 0EDH,?R*8+42H ENDM DADX MACRO ?R DB 0DDH,?R*8+09H ENDM DADY MACRO ?R DB 0FDH,?R*8+09H ENDM INXIX MACRO DB 0DDH,23H ENDM INXIY MACRO DB 0FDH,23H ENDM DCXIX MACRO DB 0DDH,2BH ENDM DCXIY MACRO DB 0FDH,2BH ENDM BIT MACRO ?N,?R DB 0CBH,?N*8+?R+40H ENDM SETB MACRO ?N,?R DB 0CBH,?N*8+?R+0C0H ENDM RES MACRO ?N,?R DB 0CBH,?N*8+?R+80H ENDM BITX MACRO ?N,?D @CHK ?D DB 0DDH,0CBH,?D,?N*8+46H ENDM BITY MACRO ?N,?D @CHK ?D DB 0FDH,0CBH,?D,?N*8+46H ENDM SETX MACRO ?N,?D @CHK ?D DB 0DDH,0CBH,?D,?N*8+0C6H ENDM SETY MACRO ?N,?D @CHK ?D DB 0FDH,0CBH,?D,?N*8+0C6H ENDM RESX MACRO ?N,?D @CHK ?D DB 0DDH,0CBH,?D,?N*8+86H ENDM RESY MACRO ?N,?D @CHK ?D DB 0FDH,0CBH,?D,?N*8+86H ENDM JR MACRO ?N DB 18H,?N-$-1 ENDM JRC MACRO ?N DB 38H,?N-$-1 ENDM JRNC MACRO ?N DB 30H,?N-$-1 ENDM JRZ MAC% .xlist false equ 0 true equ not false ;;--------------- ;; DRIVE EQUATES ;;--------------- nodrive equ 00fh loader equ 0ffh f548 equ 01f0h f596 equ 01f1h f8 equ 01f2h dma equ 0200h st503 equ 0101h st506 equ 0102h tm601s equ 0103h tm602s equ 0104h tm603s equ 0105h tm603se equ 0206h tm501 equ 0107h tm502 equ 0208h tm503 equ 0209h sa602 equ 010ah sa604 equ 010bh sa606 equ 010ch sa1002 equ 010dh sa1004 equ 010eh q2010 equ 010fh q2020 equ 0210h q2030 equ 0311h q2040 equ 0412h m4010 equ 0113h m4020 equ 0214h frst8 defl 0ffffh frst548 defl 0ffffh frst596 defl 0ffffh ldflg defl false ;;------------------------------------ ;; MACRO - DISK PARAMETER DEFINITIONS ;;------------------------------------ dskdef macro drvstr .lall ;------------------ ; SYSTEM DRIVE MAP ;------------------ dseg .xall hpdno defl 0 fpdno defl 0 dno defl 0 ;; logical drv no. of our drvs cnt defl 0 ;; cnt of how many entrys made ------ ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; ddb %10h,%fpdno,0,0,256,64 ;; ;;----------------------------------------------------- ddb %10h,0,0,128,64 ddb %11h,0,0,1024,4 ddb %12h,0,0,1024,4 tran548:: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; db 1,6,11,16,3,8,13,18,5 ;; db 10,15,2,7,12,17,4,9,14 ;; ds 8,0ffh ;; ;;----------------------------------------------------- ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; db 2,3,6,7,10,11,14,15,18,19 ;; db 4,5,8,9,12,13,16,17 ;; ds 8,0ffh ;; ;;----------------------------------------------------- db 1,6,11,16,3,8,13,18,5 db 10,15,2,7,12,17,4,9,14 ds 8,0ffh frst548 defl 0 endif dno defl dno+1 endif ;;-------------------------------- ;; 5.25" 96-TPI FLOPPY DISK DRIVE ;;--------------------- if drvtyp eq tm602S xdph %dno,%hpdno dpb %dno+0,256,5,31,1,1215,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; TM 603S HARD DISK ;;------------------- if drvtyp eq tm603S xdph %dno,%hpdno dpb %dno+0,384,5,31,1,1823,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;-------------------- ;; TM 603SE HARD DISK ;;-------------------- if drvtyp eq tm603SE xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,384,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,384,5,31,1,699,511,08000h,172,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 dno defl dno+2 endif ;;------------------ ;; TM 501 HARD DISK ;;------------------ if drvtyp eq tm501 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,1219,511,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------ ;; TM 502 HARD DISK ;;------------------ if drvtyp eq tm502 xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dn @dtbl:: irp drvtyp, if drvtyp eq nodrive dw 0 else rep (drvty sh 8 ; ente logica drv int dmap drvmap %dno dno defl dno+1 cnt defl cnt+1 endm endif endm rept (010h-cnt) ;; fill in rest of drive map dw 0 endm .lall ;--------------------- ; DISK DEBLOCKING MAP ;--------------------- dseg .xall hpdno defl 0 fpdno defl 0 dno defl 0 ;; logical drv no. of our drvs cnt defl 0 ;; cnt of how many entrys made ddbtbl:: irp drvtyp, if drvtyp eq nodrive dw 0 else rep (drvty sh 8 ; ente logica drv int dmap debmap %dno,drvtyp dno defl dno+1 cnt defl cnt+1 endm endif endm rept (010h-cnt) ;; fill in rest of drive map dw 0 endm ;;---------------------------- ;; DISK DRIVE DATA STRUCTURES ;;---------------------------- dno defl 0 hpdno defl 0 fpdno defl 0 irp drvtyp, if drvtyp eq loader ldflg defl true endif ;;-------------------------------- ;; 5.25" 48------------------ if drvtyp eq f596 xdph %dno,%fpdno,drvtyp if frst596 eq 0ffffh cseg fdpb596:: dpb %20h,18,3,07,0,082,063,16,3,0,0,1024 dpb %21h,32,4,15,0,150,063,32,1,3,7,2048 dpb %22h,64,4,15,0,300,127,32,1,3,7,2048 dseg fddb596:: ddb %20h,0,0,128,32 ddb %21h,0,0,1024,4 ddb %22h,0,0,1024,4 tran596:: db 1,7,13,19,25,5,11,17,23,3,9,15,21 db 2,8,14,20,26,6,12,18,24,4,10,16,22 frst596 defl 0 endif dno defl dno+1 endif ;;---------------------- ;; 8" FLOPPY DISK DRIVE ;;---------------------- if drvtyp eq f8 xdph %dno,%fpdno,drvtyp if frst8 eq 0ffffh cseg fdpb8:: dpb %30h,026,3,07,0,242,063,16,2,0,0,1024 dpb %31h,064,4,15,0,303,127,32,1,3,7,2048 dpb %32h,128,4,15,0,607,255,64,1,3,7,2048 dseg fddb8:: ddb %30h,0,0,128,32 ddb %31h,0,0,1024,8 ddb %32h,0,0,1024,8 tran8:: db 1,7,13,19,25,5,11,17,23,3,9,15,21 db 2,8,14,20,26,6,12,18,24,4,10,16,22 frst8 defl 0 endif dno defl dno+1 endif ;;-----------o+0,256,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,256,5,31,1,391,511,08000h,257,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 dno defl dno+2 endif ;;------------------ ;; TM 503 HARD DISK ;;------------------ if drvtyp eq tm503 xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,384,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,384,5,31,1,1611,1023,08000h,172,2,3,4096 ddb %dno+0,0,3,512,16 ddb %dno+1,0,3,512,16 dno defl dno+2 endif ;;------------------ ;; SA 602 HARD DISK ;;------------------ if drvtyp eq sa602 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,635,511,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------ ;; SA 604 HARD DISK ;;------------------ if drvtyp eq sa604 xdph %dno,%hpdno dpb %dno+0,256,5,31,1,1271,511,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------ ;; SA 606 HARD DISK ;;------------------ if drvtyp eq sa606 xdph %dno,%hpdno dpb %dno+0,384,5,31,1,TPI FLOPPY DISK DRIVE ;;-------------------------------- if drvtyp eq f548 xdph %dno,%fpdno,drvtyp if frst548 eq 0ffffh cseg fdpb548:: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; dpb %10h,18,3,7,0,81,32,16,3,0,0,1024 ;; ;;----------------------------------------------------- ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; dpb %10h,18,4,15,1,40,32,16,3,1,1,2048 ;; ;;----------------------------------------------------- dpb %10h,18,3,07,0,081,032,16,3,1,1,1024 dpb %11h,32,4,15,0,077,063,32,1,3,7,2048 dpb %12h,64,4,15,0,155,127,32,1,3,7,2048 dseg fddb548:: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; ddb %10h,0,0,128,64 ;; ;;-------------------------------------------------------------------- ;; DMA MICRO MAGNUM 5/5 HARD DISK ;;-------------------------------- if drvtyp eq dma xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,128,5,31,1,1219,511,08000h,1,1,1,4096 dpb %dno+1,128,5,31,1,1223,511,08000h,0,1,1,4096 ddb %dno+0,0,15,256,32 ddb %dno+1,2,15,256,32 dno defl dno+2 endif ;;------------------ ;; ST 503 HARD DISK ;;------------------ if drvtyp eq st503 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,607,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------ ;; ST 506 HARD DISK ;;------------------ if drvtyp eq st506 xdph %dno,%hpdno dpb %dno+0,256,5,31,1,1215,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; TM 601S HARD DISK ;;------------------- if drvtyp eq tm601S xdph %dno,%hpdno dpb %dno+0,128,5,31,1,607,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; TM 602S HARD DISK ;;-------------%1907,1023,08000h,1,2,3,4096 ddb %dno+0,0,3,512,16 dno defl dno+1 endif ;;------------------- ;; SA 1002 HARD DISK ;;------------------- if drvtyp eq sa1002 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,1019,511,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------- ;; SA 1004 HARD DISK ;;------------------- if drvtyp eq sa1004 xdph %dno,%hpdno dpb %dno+0,256,5,31,1,2039,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------------ ;; QUANTUM 2010 HARD DISK ;;------------------------ if drvtyp eq q2010 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,2043,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;------------------------ ;; QUANTUM 2020 HARD DISK ;;------------------------ if drvtyp eq q2020 xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,256,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,256,5,31,1,2039,1023,08000h,257,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,5but need label endif if frst596 eq 0ffffh fdpb596:: ; no 5"-96 tpi drv used but need label fddb596:: ; no 5"-96 tpi drv used but need label tran596:: ; no 5"=96 tpi drv used but need label endif endm ;;------------------- ;; MACRO - DRIVE MAP ;;------------------- drvmap macro dn dw xdph&dn endm ;;------------------------ ;; MACRO - DEBLOCKING MAP ;;------------------------ debmap macro dn,drvtyp if drvtyp eq f548 dw ddb&16 else if drvtyp eq f596 dw ddb&32 else if drvtyp eq f8 dw ddb&48 else dw ddb&dn endif endif endif endm ;;---------------------------------------- ;; MACRO - EXTENDED DISK PARAMETER HEADER ;;---------------------------------------- xdph macro dn,pdno,dtyp .lall ;------------------- ; DISK HEADER BLOCK ;------------------- dseg .xall ifb dw hwrite## ; hard write sector entry point dw hread## ; hard read sector entry point dw hlogin## ; hard login entry poieg .xall ddb&dn:: dw hsiz ; host sec size ssiz hsiz ;;sdh register sector size db hdoff ; head offset (for partioning by hds) db srate ; cmd register step rate db hsspt-1 ; host sec per trk - 1 (hst sec msk) shff hsspt ;;calc log2 spt endm ;;------------------------ ;; MACRO - GENERATE BCB'S ;;------------------------ rcbdcb macro dn .lall ;------------------------- ; DIRECTORY CONTROL BLOCK ;------------------------- dseg rcb&dn:: db 0ffh ; drive db 0,0,0 ; record no. db 0 ; write flag db 0 ; scratch byte dw 0 ; track no. dw 0 ; sector no. dw rcbbf&dn ; buffer address db 0 ; bank no. dw 0 ; link address ;-------------------- ; DATA CONTROL BLOCK ;-------------------- dcb&dn:: db 0ffh ; drive db 0,0,0 ; record no. db 0 ; write flag db 0 ; scratch byte dw 0 ; track no. dw 0 ; sector no. dw dcbbf&dn ; buffer address db 0 ; bank no. dw 0 ; link address ;----------------12,16 dno defl dno+2 endif ;;------------------------ ;; QUANTUM 2030 HARD DISK ;;------------------------ if drvtyp eq q2030 xdph %dno,%hpdno xdph %dno+1,%hpdno xdph %dno+2,%hpdno dpb %dno+0,384,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,384,5,31,1,2047,1023,08000h,172,2,3,4096 dpb %dno+2,384,5,31,1,2031,1023,08000h,343,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 ddb %dno+2,0,0,512,16 dno defl dno+3 endif ;;------------------------ ;; QUANTUM 2040 HARD DISK ;;------------------------ if drvtyp eq q2040 xdph %dno,%hpdno xdph %dno+1,%hpdno xdph %dno+2,%hpdno xdph %dno+3,%hpdno dpb %dno+0,512,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,512,5,31,1,2047,1023,08000h,129,2,3,4096 dpb %dno+2,512,5,31,1,2047,1023,08000h,257,2,3,4096 dpb %dno+3,512,5,31,1,2031,1023,08000h,385,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 ddb %dno+2,0,0,512,16 ddb %dno+3,0,0,512,16 dno defl dno+4 endif ;;--------------------------- ;; MINISCRInt dw hinit## ; hard initalization entry point else dw fwrite## ; floppy write sector entry point dw fread## ; floppy read sector entry point dw flogin## ; floppy login entry point dw finit## ; floppy initilazition entry point endif db pdno ; unit ifb xdn defl dn db 0 ; type = hard disk else if dtyp eq f548 xdn defl 12h db 1 ; type = 5.25" 48 tpi floppy disk else if dtyp eq f596 xdn defl 22h db 2 ; type = 5.25" 96 tpi floppy disk else xdn defl 32h db 3 ; type = 8" floppy disk endif endif endif xdph&dn:: dw 0000 ; translation vector dw 0000 ; scratch pad dw 0000 ; scratch pad dw 0000 ; scratch pad dw 0000 ; scratch pad db 0 ; scratch pad db 0ffh ; media flag if ldflg eq true genlbl %xdn ;; generate loader labels else genlb %xdn ;; generate gencpm labels endif endm ;;------------------------------ ;; MACRO - DISK PARAMETER BLOCK ;;------------------------------ dpb macr-- ; DIRECTORY BUFFER ;------------------ rcbbf&dn: ds 1024 ;------------- ; DATA BUFFER ;------------- dcbbf&dn: ds 1024 .xall endm ;;------------------------------------- ;; MACRO - GENERATE LABELS USED IN DPH ;;------------------------------------- genlbl macro dn dw dpb&dn ; loader drive disk parameter block dw csv&dn ; loader drive check sum vector dw alv&dn ; loader drive allocation vector dw rcb&dn ; loader drive directory control block dw dcb&dn ; loader drive data control block dw 0ffffh ; disable hashing db 0 ; hash bank endm genlb macro dn dw dpb&dn dw 0fffeh ; check sum vector dw 0fffeh ; disk allocation vector dw 0fffeh ; directory buffer control block dw 0fffeh ; data buffer control block dw 0fffeh ; directory hash table db 0 ; hash bank endm ;;---------------------------------- ;; MACRO - GENERATE ALV,CSV VECTORS ;;---------------------------------- alvcsv macro dn,dsm,drm alv&dn:BE 4010 HARD DISK ;;--------------------------- if drvtyp eq m4010 xdph %dno,%hpdno dpb %dno+0,128,5,31,1,1915,1023,08000h,1,2,3,4096 ddb %dno+0,0,0,512,16 dno defl dno+1 endif ;;--------------------------- ;; MINISCRIBE 4020 HARD DISK ;;--------------------------- if drvtyp eq m4020 xdph %dno,%hpdno xdph %dno+1,%hpdno dpb %dno+0,256,5,31,1,2047,1023,08000h,1,2,3,4096 dpb %dno+1,256,5,31,1,1783,1023,08000h,257,2,3,4096 ddb %dno+0,0,0,512,16 ddb %dno+1,0,0,512,16 dno defl dno+2 endif if (drvtyp eq f8) or (drvtyp eq f548) or (drvtyp eq f596) fpdno defl fpdno+1 else if drvtyp gt 15 hpdno defl hpdno+1 endif endif endm if frst8 eq 0ffffh fdpb8:: ; no 8" floppy used but need label fddb8:: ; no 8" floppy used but need label tran8:: ; no 8" floppy used but need label endif if frst548 eq 0ffffh fdpb548:: ; no 5"-48 tpi drv used but need label fddb548:: ; no 5"-48 tpi drv used but need label tran548:: ; no 5"-48 tpi drv used o dn,spt,bsh,blm,exm,dsm,drm,cks,off,psh,psm,bsiz .lall ;---------------------- ; DISK PARAMETER BLOCK ;---------------------- cseg .xall dpb&dn:: dw spt ; cpm sectors per track db bsh ; block shift factor db blm ; block mask db exm ; extent mask dw dsm ; no. blocks on drive dw drm ; no. directory entrys rsvdir dn,drm,bsiz ;;reserved directory blocks dw cks ; no. directory entries to check dw off ; track offset db psh ; physical sector shift db psm ; physical sector mask if (dn eq 10h) or (dn eq 11h) exitm else if (dn eq 20h) or (dn eq 21h) exitm else if (dn eq 30h) or (dn eq 31h) exitm else if ldflg eq true rcbdcb dn alvcsv dn,dsm,drm endif endif endif endif endm ;;------------------------------- ;; MACRO - DISK DEBLOCKING BLOCK ;;------------------------------- ddb macro dn,hdoff,srate,hsiz,hsspt .lall ;----------------------- ; DISK DEBLOCKING BLOCK ;----------------------- ds& ds (dsm/4)+2 csv&dn: ds (drm/4)+1 endm ;;-------------------------------------- ;; MACRO - COMPUTE NO. DIRECTORY BLOCKS ;;-------------------------------------- rsvdir macro dn,drm,bsiz x defl ((drm+1)/(bsiz/32)) y defl 080h done defl 0 al0&dn defl 0 al1&dn defl 0 rept 8 if x eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 done defl 0ffh exitm endif al0&dn defl al0&dn or y y defl y shr 1 x defl x-1 endm y defl 080h if done eq 0 rept 8 if x eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 done defl 0ffh exitm endif al1&dn defl al1&dn or y y defl y shr 1 x defl x-1 endm endif if done eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 endif endm ;;----------------------------------- ;; MACRO - COMPUTE DRIVE SECTOR SIZE ;;----------------------------------- ssiz macro secsiz if secsiz eq 128 ---------- moveccp: ld hl,0100h ; ld bc,0c80h ; ld (banks),de ; ld a,(@cbnk##) ; push af ; save current bank ld1: ld a,(sbnk) ; call bnksl?## ; select TPA ld a,(hl) ; push af ; get a byte ld a,(dbnk) ; call bnksl?## ; select extra bank pop af ; ld (hl),a ; save the byte inc hl ; dec bc ; bump pointer, drop count ld a,b ; or c ; test for done jr nz,ld1 ; pop af ; call bnksl?## ; restore original bank ret ;------------------------------ ; CP/M BDOS FUNCTION INTERFACE ;------------------------------ open: ld c,15 ; jp bdos ; open file control block setdma: ld c,26 ; jp bdos ; set data transfer address setmulti: ld c,44 ; jp bdos ; set record count read: ld c,20 ; jp bdos ; read records ;----------------------- ; NO CCP.COM FILE FOUND ;----------------------- noccp: ld hl,ccpmsg ; call pmsg?## ; call conin?## ; jp ldccp? ;  TITLE 'Root module of relocatable BIOS for CP/M 3.0' .Z80 ; version 1.0 15 Sept 82 TRUE EQU -1 FALSE EQU NOT TRUE BANKED EQU TRUE ; Copyright (C), 1982 ; Digital Research, Inc ; P.O. Box 579 ; Pacific Grove, CA 93950 ; This is the invariant portion of the modular BIOS and is ; distributed as source for informational purposes only. ; All desired modifications should be performed by ; adding or changing externally defined modules. ; This allows producing "standard" I/O modules that ; can be combined to support a particular system ; configuration. CR EQU 13 LF EQU 10 BELL EQU 7 CTLQ EQU 'Q'-'@' CTLS EQU 'S'-'@' CCP EQU 0100H ; Console Command Processor gets loaded into the TPA CSEG ; GENCPM puts CSEG stuff in common memory ; variables in system data page EXTRN @COVEC,@CIVEC,@AOVEC,@AIVEC,@LOVEC ; I/O redirection vectors EXTRN @MXTPA ; addr of system entry point EXTRN @BNKBF ; 128 byte scratch buffer ; initialization  db 060h ; sdh reg sec siz 060 = 128 bps else if secsiz eq 512 db 020h ; sdh reg sec siz 020 = 512 bps else if secsiz eq 256 db 000h ; sdh reg sec siz 000 = 256 bps else db 000h endif endif endif endm ;;------------------------------ ;; MACRO - COMPUTE SHIFT FACTOR ;;------------------------------ shff macro num @y defl num @x defl 0 rept 8 if @y eq 1 db @x ; log2 (num) exitm endif @y defl @y shr 1 @x defl @x + 1 endm endm .list e defl 0ffh exitm endif al1&dn defl al1&dn or y y defl y shr 1 x defl x-1 endm endif if done eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 endif endm ;;----------------------------------- ;; MACRO - COMPUTE DRIVE SECTOR SIZE ;;----------------------------------- ssiz macro secsiz if secsiz eq 128  ;-------------------- ; TIME BIOS FUNCTION ;-------------------- time?:: ret ; ;-------------- ; DATA STORAGE ;-------------- banks: sbnk: db 0 ; dbnk: db 0 ; ccpmsg: db 0dh,0ah,'BIOS Err on A: No CCP.COM file',0 ;--------- ; CCP FCB ;--------- ccpfcb: db 1,'CCP ','COM',0,0,0,0 ds 16 fcbnr: db 0,0,0 end rop count ld a,b ; or c ; test for done jr nz,ld1 ; pop af ; call bnksl?## ; restore original bank ret ;------------------------------ ; CP/M BDOS FUNCTION INTERFACE ;------------------------------ open: ld c,15 ; jp bdos ; open file control block setdma: ld c,26 ; jp bdos ; set data transfer address setmulti: ld c,44 ; jp bdos ; set record count read: ld c,20 ; jp bdos ; read records ;----------------------- ; NO CCP.COM FILE FOUND ;----------------------- noccp: ld hl,ccpmsg ; call pmsg?## ; call conin?## ; jp ldccp? ;  EXTRN INIT? ; general initialization and signon EXTRN LDCCP?,RLCCP? ; load & reload CCP for BOOT & WBOOT ; user defined character I/O routines EXTRN CI?,CO?,CIST?,COST? ; each take device in EXTRN CINIT? ; (re)initialize device in EXTRN @CTBL ; physical character device table ; disk communication data items EXTRN @DTBL ; table of pointers to XDPHs PUBLIC @ADRV,@RDRV,@TRK,@SECT ; parameters for disk I/O PUBLIC @DMA,@DBNK,@CNT ; '' '' '' '' ; memory control PUBLIC @CBNK ; current bank EXTRN XMOVE?,MOVE? ; select move bank, and block move EXTRN BANK? ; select CPU bank ; clock support EXTRN TIME? ; signal time operation ; general utility routines PUBLIC PMSG?,PDEC? ; print message, print number from 0 to 65535 PUBLIC PDERR? ; print BIOS disk error message header MACLIB MODEBAUD.LIB ; define mode bits ; External names for BIOS entry points PUBLIC BOOT?,WBOOT?,CONST?,CONIN?,CONO?,LIST?,AUXO?,AUXI? PUB title LOAD / RELOAD CCP -- CP/M 3.0 -- BANKED .z80 bdos equ 5 cseg ;------------------------------ ; LOAD CCP FROM DISK TO BANK 1 ;------------------------------ ldccp?:: xor a ; load the A:CCP.COM file into TPA ld (ccpfcb+15),a ; zero extent ld hl,0 ; ld (fcbnr),hl ; start at beginning of file ld de,ccpfcb ; call open ; open file containing CCP inc a ; jp z,noccp ; error if no file... ld de,0100h ; call setdma ; start of TPA ld de,27 ; call setmulti ; allow up to 16k bytes ld de,ccpfcb ; call read ; load the thing ;--------------------------------- ; COPY CCP FROM BANK 1 TO BANK 2 ;--------------------------------- copyccp: ld de,0201h ; jr moveccp ; ;---------------------------------- ; RELOAD CCP FROM BANK 2 TO BANK 1 ;---------------------------------- rlccp?:: ld de,0102h ; ;----------------------------------------- ; MOVE CCP FROM SOURCE BANK TO DEST. BANK ;-------------------------------&LIC HOME?,SLDSK?,STTRK?,STSEC?,STDMA?,READ?,WRITE? PUBLIC LISTS?,SCTRN? PUBLIC CONOS?,AUXIS?,AUXOS?,DVTBL?,DEVIN?,DRTBL? PUBLIC MLTIO?,FLUSH?,MOV?,TIM?,BNKSL?,STBNK?,XMOV? ; BIOS Jump vector. ; ; All BIOS routines are invoked by calling these ; entry points. ;Public Local BIOS Description ;Name Routine Func BOOT?: JP BOOT ; 00 initial entry on cold start WBOOT?: JP WBOOT ; 01 reentry on program exit, warm start CONST?: JP CONST ; 02 return console input status CONIN?: JP CONIN ; 03 return console input character CONO?: JP CONOUT ; 04 send console output character LIST?: JP LIST ; 05 send list output character AUXO?: JP AUXOUT ; 06 send auxilliary output character AUXI?: JP AUXIN ; 07 return auxilliary input character HOME?: JP HOME ; 08 set disks to logical home SLDSK?: JP SELDSK ; 09 select disk drive, return disk parameter info STTRK?: JP SETTRK ; 10 set disk track STSEC?: JP SETSEC ; 11 set disk sector STDMA?: JP SETDMA ; 12 set disk ALL IPCHL ; call init routine POP HL ; recover @drv pointer D$INIT$NEXT: POP BC ; recover counter and drive # INC C DJNZ D$INIT$LOOP ; and loop for each drive JP BOOT$1 CSEG ; following in resident memory BOOT$1: CALL SET$JUMPS CALL LDCCP? ; fetch CCP for first time JP CCP ; WBOOT ; Entry for system restarts. WBOOT: LD SP,BOOT$STACK CALL SET$JUMPS ; initialize page zero CALL RLCCP? ; reload CCP JP CCP ; then reset jmp vectors and exit to ccp SET$JUMPS: IF BANKED LD A,1 CALL BNKSL? ENDIF LD A,0C3H LD (0),A LD (5),A ; set up jumps in page zero LD HL,WBOOT? LD (1),HL ; BIOS warm start entry LD HL,(@MXTPA) LD (6),HL ; BDOS system call entry RET DS 64 BOOT$STACK EQU $ ; DEVTBL ; Return address of character device table DEVTBL: LD HL,@CTBL RET ; GETDRV ; Return address of drive table GETDRV: LD HL,@DTBL RET ; CONOUT ; Console Output. Send character in ; eturn true RET COSTER: ; check for output device ready, including optional ; xon/xoff support LD L,B LD H,0 ; make device code 16 bits PUSH HL ; save it in stack ADD HL,HL ADD HL,HL ADD HL,HL ; create offset into device characteristics tbl LD DE,@CTBL+6 ADD HL,DE ; make address of mode byte LD A,(HL) AND MB$XON$XOFF POP HL ; recover console number in JP Z,COST? ; not a xon device, go get output status direct LD DE,XOFFLIST ADD HL,DE ; make pointer to proper xon/xoff flag CALL CIST1 ; see if this keyboard has character LD A,(HL) CALL NZ,CI1 ; get flag or read key if any CP CTLQ JP NZ,NOT$Q ; if its a ctl-Q, LD A,0FFH ; set the flag ready NOT$Q: CP CTLS JP NZ,NOT$S ; if its a ctl-S, LD A,00H ; clear the flag NOT$S: LD (HL),A ; save the flag CALL COST1 ; get the actual output status, AND (HL) ; and mask with ctl-Q/ctl-S flag RET ; return this as the status CIST1: ; get input status with andI/O memory address READ?: JP READ ; 13 read physical block(s) WRITE?: JP WRITE ; 14 write physical block(s) LISTS?: JP LISTST ; 15 return list device status SCTRN?: JP SECTRN ; 16 translate logical to physical sector CONOS?: JP CONOST ; 17 return console output status AUXIS?: JP AUXIST ; 18 return aux input status AUXOS?: JP AUXOST ; 19 return aux output status DVTBL?: JP DEVTBL ; 20 return address of device def table DEVIN?: JP CINIT? ; 21 change baud rate of device DRTBL?: JP GETDRV ; 22 return address of disk drive table MLTIO?: JP MULTIO ; 23 set multiple record count for disk I/O FLUSH?: JP FLUSH ; 24 flush BIOS maintained disk caching MOV?: JP MOVE? ; 25 block move memory to memory TIM?: JP TIME? ; 26 Signal Time and Date operation BNKSL?: JP BNKSEL ; 27 select bank for code execution and default DMA STBNK?: JP SETBNK ; 28 select different bank for disk I/O DMA operations. XMOV?: JP XMOVE? ; 29 set source and destination banks for one operation to all selected devices CONOUT: LD HL,(@COVEC) ; fetch console output bit vector JP OUT$SCAN ; AUXOUT ; Auxiliary Output. Send character in ; to all selected devices AUXOUT: LD HL,(@AOVEC) ; fetch aux output bit vector JP OUT$SCAN ; LIST ; List Output. Send character in ; to all selected devices. LIST: LD HL,(@LOVEC) ; fetch list output bit vector OUT$SCAN: LD B,0 ; start with device 0 CO$NEXT: ADD HL,HL ; shift out next bit JP NC,NOT$OUT$DEVICE PUSH HL ; save the vector PUSH BC ; save the count and character NOT$OUT$READY: CALL COSTER OR A JP Z,NOT$OUT$READY POP BC PUSH BC ; restore and resave the character and device CALL CO? ; if device selected, print it POP BC ; recover count and character POP HL ; recover the rest of the vector NOT$OUT$DEVICE: INC B ; next device number LD A,H OR L ; see if any devices left JP NZ,CO$NEXT ; and go find them... RET ; CONOST ; Console Output saved PUSH BC PUSH HL CALL CIST? POP HL POP BC OR A RET COST1: ; get output status, saving & PUSH BC PUSH HL CALL COST? POP HL POP BC OR A RET CI1: ; get input, saving & PUSH BC PUSH HL CALL CI? POP HL POP BC RET ; CONST ; Console Input Status. Return true if ; any selected console input device ; has an available character. CONST: LD HL,(@CIVEC) ; get console input bit vector JP IST$SCAN ; AUXIST ; Auxiliary Input Status. Return true if ; any selected auxiliary input device ; has an available character. AUXIST: LD HL,(@AIVEC) ; get aux input bit vector IST$SCAN: LD B,0 ; start with device 0 CIS$NEXT: ADD HL,HL ; check next bit LD A,0 ; assume device not ready CALL C,CIST1 ; check status for this device OR A RET NZ ; if any ready, return true INC B ; drop device number LD A,H OR L ; see if any more selected devices JP NZ,CIS$NEXT XOR A ; a JP 0 ; 30 reserved for future expansion JP 0 ; 31 reserved for future expansion JP 0 ; 32 reserved for future expansion ; BOOT ; Initial entry point for system startup. DSEG ; this part can be banked BOOT: LD SP,BOOT$STACK LD C,15 ; initialize all 16 character devices C$INIT$LOOP: PUSH BC CALL CINIT? POP BC DEC C JP P,C$INIT$LOOP CALL INIT? ; perform any additional system initialization ; and print signon message LD BC,16*256+0 LD HL,@DTBL ; init all 16 logical disk drives D$INIT$LOOP: PUSH BC ; save remaining count and abs drive LD E,(HL) INC HL LD D,(HL) INC HL ; grab @drv entry LD A,E OR D JP Z,D$INIT$NEXT ; if null, no drive PUSH HL ; save @drv pointer EX DE,HL ; XDPH address in DEC HL DEC HL LD A,(HL) LD (@RDRV),A ; get relative drive code LD A,C LD (@ADRV),A ; get absolute drive code DEC HL ; point to init pointer LD D,(HL) DEC HL LD E,(HL) ; get init pointer EX DE,HL C Status. Return true if ; all selected console output devices ; are ready. CONOST: LD HL,(@COVEC) ; get console output bit vector JP OST$SCAN ; AUXOST ; Auxiliary Output Status. Return true if ; all selected auxiliary output devices ; are ready. AUXOST: LD HL,(@AOVEC) ; get aux output bit vector JP OST$SCAN ; LISTST ; List Output Status. Return true if ; all selected list output devices ; are ready. LISTST: LD HL,(@LOVEC) ; get list output bit vector OST$SCAN: LD B,0 ; start with device 0 COS$NEXT: ADD HL,HL ; check next bit PUSH HL ; save the vector PUSH BC ; save the count LD A,0FFH ; assume device ready CALL C,COSTER ; check status for this device POP BC ; recover count POP HL ; recover bit vector OR A ; see if device ready RET Z ; if any not ready, return false INC B ; drop device number LD A,H OR L ; see if any more selected devices JP NZ,COS$NEXT OR 0FFH ; all selected were ready, r'll selected were not ready, return false RET ; CONIN ; Console Input. Return character from first ; ready console input device. CONIN: LD HL,(@CIVEC) JP IN$SCAN ; AUXIN ; Auxiliary Input. Return character from first ; ready auxiliary input device. AUXIN: LD HL,(@AIVEC) IN$SCAN: PUSH HL ; save bit vector LD B,0 CI$NEXT: ADD HL,HL ; shift out next bit LD A,0 ; insure zero a (nonexistant device not ready). CALL C,CIST1 ; see if the device has a character OR A JP NZ,CI$RDY ; this device has a character INC B ; else, next device LD A,H OR L ; see if any more devices JP NZ,CI$NEXT ; go look at them POP HL ; recover bit vector JP IN$SCAN ; loop til we find a character CI$RDY: POP HL ; discard extra stack JP CI? ; Utility Subroutines IPCHL: ; vectored CALL point JP (HL) ; print messageg pointed to by HL and ending w/ 0 PMSG?: ; print message @ up to a null ; saves & PUSLD A,E AND 1 JP NZ,NOT$FIRST$SELECT ; examine login bit PUSH HL EX DE,HL ; put pointer in stack & LD HL,-2 ADD HL,DE LD A,(HL) LD (@RDRV),A ; get relative drive LD HL,-6 ADD HL,DE ; find LOGIN addr LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of LOGIN routine CALL IPCHL ; call LOGIN POP HL ; recover DPH pointer NOT$FIRST$SELECT: RET ; HOME ; Home selected drive. Treated as SETTRK(0). HOME: LD BC,0 ; same as set track zero ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. SETTRK: LD (@TRK),BC RET ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further operations. SETSEC: LD (@SECT),BC RET ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @CBNK ; so that further disk operations take place ; in current bank. SETDMA: LD (@DMA),BC LD A,(@CBNK) ; default DMA bank is current ban TRACK$MSG: DB ': T-',0 SECTOR$MSG: DB ', S-',0 ; disk communication data items @ADRV: DS 1 ; currently selected disk drive @RDRV: DS 1 ; controller relative disk drive @TRK: DS 2 ; current track number @SECT: DS 2 ; current sector number @DMA: DS 2 ; current DMA address @CNT: DB 0 ; record count for multisector transfer @DBNK: DB 0 ; bank for DMA operations CSEG @CBNK: DB 0 ; bank for processor operations ; ; following DS fills out end of page to allow ; next module to start on page boundry ; ds 16 - (($-boot?) mod 16) endaddr:: END H BC PUSH DE PMSG$LOOP: LD A,(HL) OR A JP Z,PMSG$EXIT LD C,A PUSH HL CALL CONO? POP HL INC HL JP PMSG$LOOP PMSG$EXIT: POP DE POP BC RET ; print value in HL in decimal PDEC?: ; print binary number 0-65535 from LD BC,TABLE10 LD DE,-10000 NEXT: LD A,'0'-1 PDECL: PUSH HL INC A ADD HL,DE JP NC,STOPLOOP INC SP INC SP JP PDECL STOPLOOP: PUSH DE PUSH BC LD C,A CALL CONO? POP BC POP DE NEXTDIGIT: POP HL LD A,(BC) LD E,A INC BC LD A,(BC) LD D,A INC BC LD A,E OR D JP NZ,NEXT RET TABLE10: DW -1000,-100,-10,-1,0 ; print value in A in hex 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 ; print disk drive error message PDERR?: LD HL,DRIVE$MSG CALL PMSG? ; error header LD A,(@ADRV) ADD A,'A' LD C,A CALL CONO? ; drive code LD HL,TRACK$MSG CALL PMSG? ; track header LD Hk ; fall through to set DMA bank ; SETBNK ; Set Disk Memory Bank. Saves bank number ; in @DBNK for future disk data ; transfers. SETBNK: LD (@DBNK),A RET ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returns physical=logical. SECTRN: LD L,C LD H,B LD A,D OR E RET Z EX DE,HL ADD HL,BC LD L,(HL) LD H,0 RET ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter header (XDPH). READ: LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-8 ADD HL,DE ; point to read routine address JP RW$COMMON ; use common code ; WRITE ; Write physical sector from currently L,(@TRK) CALL PDEC? ; track number LD HL,SECTOR$MSG CALL PMSG? ; sector header LD HL,(@SECT) CALL PDEC? ; sector number RET ; BNKSEL ; Bank Select. Select CPU bank for further execution. BNKSEL: LD (@CBNK),A ; remember current bank JP BANK? ; and go exit through users ; physical bank select routine XOFFLIST: DB -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero DB -1,-1,-1,-1,-1,-1,-1,-1 DSEG ; following resides in banked memory ; Disk I/O interface routines ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke login procedure for drive ; if this is first select. Return ; address of disk parameter header ; in SELDSK: LD A,C LD (@ADRV),A ; save drive select code LD L,C LD H,0 ADD HL,HL ; create index from drive code LD BC,@DTBL ADD HL,BC ; get pointer to dispatch table LD A,(HL) INC HL LD H,(HL) LD L,A ; point at disk descriptor OR H RET Z ; if no entry in table, no disk selected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). WRITE: LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-10 ADD HL,DE ; point to write routine address RW$COMMON: LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of routine POP DE ; recover address of table DEC DE DEC DE ; point to relative drive LD A,(DE) LD (@RDRV),A ; get relative drive code and post it INC DE INC DE ; point to DPH again JP (HL) ; leap to driver ; MULTIO ; Set multiple sector count. Saves passed count in ; @CNT MULTIO: LD (@CNT),A RET ; FLUSH ; BIOS deblocking buffer flush. Not implemented. FLUSH: XOR A RET ; return with no error ; error message components DRIVE$MSG: DB CR,LF,BELL,'BIOS Error on ',0 ' title BANK MOVE MODULE -- CP/M 3.0 .z80 ;------------------------------------------------------------------------------ ; ; Super Six CP/M 3.0 ; ; BNK ADDR BNK ADDR ; ----------------- ----------------- ; ; 0 0000-3FFF ---> 0 0000-3FFF ; 0 4000-7FFF ---> 0 4000-7FFF ; 0 8000-BFFF ---> 0 8000-BFFF ; 0 C000-FFFF ---> 0-1 C000-FFFF (COMMON) ; ; 1 0000-3FFF ---> 1 0000-3FFF ; 1 4000-7FFF ---> 1 4000-7FFF ; 1 8000-BFFF ---> 1 8000-BFFF ; 1 C000-FFFF ---> 2 0000-3FFF (OVERLAY) ; ;------------------------------------------------------------------------------ ;---------------------- ; MEMORY CONTROL PORTS ;---------------------- bnk0 equ 016h ; memory control port 0 bnk1 equ 017h ; memory control port 1 ;-------------------------------------------- ; MEMORY MOVE MODULE RESIDE IN COMMON MEMORY ;-------------------------------------------- cseg ;------------------------ ; SET UP INTER-BANK MOVE ;------------------------ xmove?::---- ; DATA STORAGE ;-------------- banks: sbnk: db 0 ; destination bank in inter-bank move dbnk: db 0 ; source bank in inter-bank move end op de ; put next source in de-reg ld a,(@cbnk##) call bank? ret ;---------------------- ; SELECT PHYSICAL BANK ;---------------------- bank?:: cp 1 jr z,selbnk1 ; jump if bnk 1 jr nc,selbnk2 selbnk0: out (bnk1),a ; disable bank 1 by sending a zero ld a,0efh ; prom dis, power on jmp, parity ena out (bnk0),a ; bank in bnk 0 ret selbnk1: ld a,0e8h ; keep common mem banked in out (bnk0),a ; bank out every thing except c000-ffff ld a,007h ; bank in 0-dfff of bank 1 out (bnk1),a ; now in second bank w. common ret selbnk2: ld a,0e8h ; keep common selected out (bnk0),a ; deselect lower 16k banks l a,018h ; use map 1 for overlay out (bnk1),a ; now, c000-ffff --> 0-3fff ret ;---------- title CHARACTER I/O DRIVERS -- CP/M 3.0 -- BANKED / NON-BANKED .z80 MACLIB MODEBAUD.LIB ;----------------- ; BAUD RATE PORTS ;----------------- baudd equ 015h baudc equ 018h ;------------------- ; SIO CONTROL PORTS ;------------------- sioad equ 000h sioac equ 001h siobd equ 002h siobc equ 003h ;------------------- ; PIO CONTROL PORTS ;------------------- pioad equ 004h pioac equ 006h piobd equ 005h piobc equ 007h inbfsz equ 032d cseg ;-------------------------------- ; CHARACTER DEVICE INITALIZATION ;-------------------------------- cinit?:: ld a,c ; put device no in a-reg for compare cp 2 ; check if parallel device ret z ; no baud for parallel ld hl,frstint ; check if first time initalization xor a ; set flag to show already done once cp (hl) ; frstinit = 0ff if first time jr z,setbaud ; jump if not first time through ;-------------------------------------- ; SET @CTBL TO ON-BOARD SWITCH SETTING ;---------------------- ld (banks),bc ; save source and dest bnks ret ;---------------------- ; MOVE BLOCK OF MEMORY ;---------------------- move?:: ld a,(banks) ; check if inter bank moved needed inc a ; if no inter bnk mov, this sets z-flg jp nz,xmovit ; jmp if inter bnk mov ;----------------- ; INTRA BANK MOVE ;----------------- movit: ex de,hl ; no inter bank move, do simp blk mov ldir ; BDOS passes ldir args reversed ex de,hl ; return args to BDOS ret ;----------------- ; INTER BANK MOVE ;----------------- xmovit: ex de,hl ; put source in hl, destinatin in de ld a,(sbnk) ; set up to bank in source bank call bank? ; do physical bank select push de ; save destination push bc ; save count ld de,(@bnkbf##) ; get bank buf addr from scb ldir ; mov 080h byt into buffer pop bc ; restore count pop de ; restore dest addr push hl ; save ptr to next source byte ld a,(dbnk) ; set up to bank in dest bank call bank? ; bank in des title LOAD / RELOAD CCP -- CP/M 3.0 -- NON-BANKED .z80 bdos equ 5 cseg ;------------------------------ ; LOAD CCP FROM DISK TO BANK 0 ;------------------------------ ldccp?:: rlccp?:: xor a ; load the A:CCP.COM file into TPA ld (ccpfcb+15),a ; zero extent ld hl,0 ; ld (fcbnr),hl ; start at beginning of file ld de,ccpfcb ; call open ; open file containing CCP inc a ; jp z,noccp ; error if no file... ld de,0100h ; call setdma ; start of TPA ld de,27 ; call setmulti ; allow up to 16k bytes ld de,ccpfcb ; call read ; load the thing ret ;------------------------------ ; CP/M BDOS FUNCTION INTERFACE ;------------------------------ open: ld c,15 ; jp bdos ; open file control block setdma: ld c,26 ; jp bdos ; set data transfer address setmulti: ld c,44 ; jp bdos ; set record count read: ld c,20 ; jp bdos ; read records ;----------------------- ; NO CCP.COM FILE FOUND ---------------- initbaud: ld (hl),a ; set frstinit flag to 0 for next time isioabd: in a,(baudd) ; read baud switch settings from board and 00fh ; mask for sioa baud rate setting cp 10 ; check if board is set for < 2400 baud jr nc,gt2000 ; if < 2400 then need to adjust for tbl inc a ; cp/m 3 does not support baud 2000 gt2000: ld (@ctbl+7),a ; save it in character device table isiobbd: in a,(baudd) ; read baud switch settings and 070h ; only 3-bits for sio b baud rate srl a ; right justify nibble srl a ; 3 bits means switch setting is 0-7 srl a ; cp/m 3 supports baud settings 1-15 srl a ; finish justification inc a ; adjust switch setting for cp/m ld (@ctbl+15),a ; save baud rate in dev 1 baud entry ret ;---------------------------------- ; SET BAUD RATE TO @CTBL SETTING ;---------------------------------- setbaud: ld a,(@ctbl+7) ; second or more times through cp 10 ; jr nc,gt2000a ; dec a ; gt2000a: ld c,a ; tination bank ld hl,(@bnkbf##) ; siz of bnkbf is 080h bytes ldir ; blk mov bank buffer to dest addr ld bc,0ffffh ; re-set xmove flag ld (banks),bc ; this really sets dbnk = sbnk = 0ffh ex de,hl ; put next destination in hl-reg pop de ; put next source in de-reg ld a,(@cbnk##) call bank? ret ;---------------------- ; SELECT PHYSICAL BANK ;---------------------- bank?:: cp 1 jr z,selbnk1 ; jump if bnk 1 jr nc,selbnk2 selbnk0: out (bnk1),a ; disable bank 1 by sending a zero ld a,0efh ; prom dis, power on jmp, parity ena out (bnk0),a ; bank in bnk 0 ret selbnk1: ld a,0e8h ; keep common mem banked in out (bnk0),a ; bank out every thing except c000-ffff ld a,007h ; bank in 0-dfff of bank 1 out (bnk1),a ; now in second bank w. common ret selbnk2: ld a,0e8h ; keep common selected out (bnk0),a ; deselect lower 16k banks l a,018h ; use map 1 for overlay out (bnk1),a ; now, c000-ffff --> 0-3fff ret ;---------- ;----------------------- noccp: ld hl,ccpmsg ; call pmsg?## ; call conin?## ; jp ldccp? ; ;-------------------- ; TIME BIOS FUNCTION ;-------------------- time?:: ret ; ;-------------- ; DATA STORAGE ;-------------- banks: sbnk: db 0 ; dbnk: db 0 ; ccpmsg: db 0dh,0ah,'BIOS Err on A: No CCP.COM file',0 ;--------- ; CCP FCB ;--------- ccpfcb: db 1,'CCP ','COM',0,0,0,0 ds 16 fcbnr: db 0,0,0 end  ld de,27 ; call setmulti ; allow up to 16k bytes ld de,ccpfcb ; call read ; load the thing ret ;------------------------------ ; CP/M BDOS FUNCTION INTERFACE ;------------------------------ open: ld c,15 ; jp bdos ; open file control block setdma: ld c,26 ; jp bdos ; set data transfer address setmulti: ld c,44 ; jp bdos ; set record count read: ld c,20 ; jp bdos ; read records ;----------------------- ; NO CCP.COM FILE FOUND ( ld a,(@ctbl+15) ; set baud according to values in tbl sla a ; left justity baud rate for device 1 sla a ; dev 1 maps to sio ch b sla a ; dev 1 baud setting for port is b7-4 sla a ; must set both at once so dont clobber cp 10 ; jr nc,gt2000b ; dec a ; gt2000b: or c ; or in dev 0 baud setting out (baudc),a ; send dev 0,1 baud to baud ctrl port ret cseg ;------------------------ ; CHARACTER DEVICE INPUT ;------------------------ ci?:: ld a,b ; put dev. no. in a-reg cp 2 ; check if dev. 0 or 1 jr c,ciwait ; jump if dev. no. 0 or 1 ld a,01ah ; return ctrl-z if bad input dev. ret ciwait: call cist? ; get device input status jr z,ciwait ; sets zero flag if no RxCA ld a,b ; put device no. in a and a ; check if device 0 or 1 jr nz,siobin ; jump if device 1. sioain: di ; no interupts while using bf ptrs ld de,(outptri) ; d-reg = inptri, e-reg = outptri ld d,0 ; de-reg = outptri, ofset to nx chr out  no character available ld a,0ffh ; let cp/m know char available ret ;-------------------------------- ; CHARACTER DEVICE OUTPUT STATUS ;-------------------------------- cost?:: ld A,B ; move relative device no. to a-reg cp 2 ; check if parallel printer jr nz,sioost ; jump to serial status if not parallel lstost: in A,(piobd) ; get pio status and 1 ; busy = 0, not busy = 1 ret z ; if prn busy, return with a-reg = 0 l A,0ffh ; prn not busy, return with a-reg = 0ff ret sioost: add a,a ; double dev. no to 0 or 2 inc a ; increment dev no. to 1 or 3 ld c,a ; this is the sio control port ld a,010h ; send reset ext/status intr to wr0 out (c),a ; must do reset if DCD to be valid in a,(c) ; get sio staus and 004h ; check TxBE cp 004h ; set z-flg if TxBE ld a,0ffh ; prepare for return w. ok to send flg ret z ; return if sio ready w. a-reg = 0ffh cpl ; else sio not ready, return 0 ret ;--------------------------- title CTC INTERUPT SERVICE ROUTINE -- CP/M 3.0 -- BANKED / NON-BANKED .z80 ;---------------------------------------------- ; CTC SERVICE ROUTINE RESIDES IN COMMON MEMORY ;---------------------------------------------- cseg ctc1svc:: ld (ssp##),sp ; save system stack pointer ld sp,istk## ; use interupt stack while in isvc call save## ; save cpu state inctic: ld hl,ticcnt ; tic counter counts 1/60 sec inc (hl) ; increment tic counter ld a,(hl) ; fetch ticcnt for compare cp 60 ; check if counted 60 tics yet ret nz ; return to restore cpu state ld (hl),0 ; zero tic counter incsec: ld hl,@sec## ; service second counter in scb inc (hl) ; increment second counter ld a,(hl) ; fetch for daa and compare daa ; @sec is bcd so do daa after inc ld (hl),a ; store adjusted bcd cp 060h ; check if one minute elasped ret nz ; return to restore cpu state if under ld (hl),0 ; zero second count incmin: ld hl,@min## ; service minute count l hl,inpbuf ; get base addr of console i/o buffer add hl,de ; add offset of nx chr out to bf addr ld a,e ; put outptri into a-reg inc a ; inc to next chr to send and inbfsz-1 ; mask offset for wrap around ld (outptri),a ; save offset for next time around ld a,(hl) ; pass cp/m char in a-reg ei ; interupts ok now ret siobin: in a,(siobd) ; pull char fm sio ch. b bf to a-reg and 07fh ; mask parity off ret ;------------------------- ; CHARACTER DEVICE OUTPUT ;------------------------- co?:: ld D,C ; save character to output cowait: call cost? ; get out rdy / busy status of device and a ; set zero flag on value returned jr z,cowait ; loop until device ready ld a,b ; put device no. in a-reg cp 2 ; check if parallel printer jr z,lstout ; jump to printer out w. char in d-reg sioout: add a,a ; double device no. so it is 0 or 2 ld c,a ; this is the sio data port we want out (c),d ; send character ret lstout: --------- ; SIO CH. A INTERUPT SERVICE ROUTINE ;------------------------------------ sioasvc:: ld (ssp##),sp ; save system stack pointer ld sp,istk## ; user interupt stack call save## ; save registers af,bc,de,hl ld hl,(outptri) ; h = inptri, l = outptri ld a,h ; put offset to nx bf in in a-reg inc a and inbfsz-1 cp l ; chk if nx in = nx out j nz,rxchr ; jump i roo fo more ciobo: in a,(sioad) ; cio buffer overflow, clear input port xor a ; clear channel no. ld c,007h ; ascii char code for ctrl-g (bell) call co? ; send bell to sio ch. a ret ; return to --> return from interupt rxchr: ld (inptri),a ld e,h ; put inptri into e-reg ld d,0 ; zero d-reg for double add ld hl,inpbuf ; get base addr of bf add hl,de ; point nx available addr in bf in a,(sioad) ; get input char from sio and 07fh ; mask out parity ld (hl),a ; save char in cio buffer ret ;-------------- ; DATA STORAGE ;-------------- frstint:dber in scb inc (hl) ; increment minute counter ld a,(hl) ; fetch for daa and compare daa ; @min is bcd so do daa after inc ld (hl),a ; store adjusted bcd cp 060h ; check if one hour elasped ret nz ; return to restore cpu state if under ld (hl),0 ; zero minute count inchr: ld hl,@hour## ; service hour counter in scb inc (hl) ; increment hour counter ld a,(hl) ; fetch for daa and compare daa ; @hour is bcd so do daa after inc ld (hl),a ; store adjusted bcd cp 024h ; check if next day ret nz ; return to restore cpu state if under ld (hl),0 ; zero hour count incday: ld hl,@date## ; service day counter inc (hl) ; increment day counter ret ;-------------- ; DATA STORAGE ;-------------- ticcnt: db 0 ; interupt counter (counts 1/60 sec) end  nz ; return to restore cpu state if under ld (hl),0 ; zero second count incmin: ld hl,@min## ; service minute count ld a,d ; put char to send into a-reg out (pioad),a ; send char to pio ch. a data port ld a,080h ; set strobe high, then low out (piobd),a ; strobe printer via pio ch. b xor a ; set strobe low to latch data out (piobd),a ; pio latches on strobe's falling edge ret ;------------------------------- ; CHARACTER DEVICE INPUT STATUS ;------------------------------- cist?:: ld a,b ; put device no in a-reg cp 1 ; check if 0,1 or 2 jr c,sioaist ; jump if dev.0 to sio ch. a status jr z,siobist ; jump if dev.1 to sio ch. b status pioist: xor a ; ret if par dev or bad dev (no in. st) ret sioaist: ld hl,(outptri) ; h-reg = inptri, l-reg = outptri ld a,h ; intptri is bf offset to nx chr in sub l ; outptri is bf offset to nx chr out ret z ; if intptri = outptri then no chr ld a,0ffh ; let cp/m know char available ret siobist: in a,(siobc) ; poll sio ch. b for char available and 1 ; get stat and check RxCA ret z ; return if 0ffh outptri:db 0 ; bf offset to next char out to cp/m inptri: db 0 ; bf offset to next char in from sio inpbuf: ds inbfsz ; console i/o buffer ;---------------------------- ; CHARACTER I/O DEVICE TABLE ;---------------------------- @CTBL:: db 'CRT ' db mb$in$out+mb$serial+mb$soft$baud db baud$none db 'SERLPT' db mb$in$out+mb$serial+mb$soft$baud db baud$none db 'PARLPT' db mb$output db baud$none db 0 end  ld c,007h ; ascii char code for ctrl-g (bell) call co? ; send bell to sio ch. a ret ; return to --> return from interupt rxchr: ld (inptri),a ld e,h ; put inptri into e-reg ld d,0 ; zero d-reg for double add ld hl,inpbuf ; get base addr of bf add hl,de ; point nx available addr in bf in a,(sioad) ; get input char from sio and 07fh ; mask out parity ld (hl),a ; save char in cio buffer ret ;-------------- ; DATA STORAGE ;-------------- frstint:db( title DISK DRIVE DEFINITIONS -- CP/M 3.0 -- BANKED / NON-BANKED include C3.LIB .z80 dskdef dseg ;------------------- ; GET DATA TO WRITE ;------------------- getdata:: ld hl,diskbf ; destination ld de,(@dma##) ; source getlp: ld bc,(@dbnk##) ; source bank ld b,0 ; destination bank call xmove?## ld bc,080h call move?## ld a,(xfercnt) dec a ld (xfercnt),a jr nz,getlp ret ;--------------- ; PUT DATA READ ;--------------- putdata:: ld hl,(@dma##) ; destination ld de,diskbf ; source putlp: ld a,(@dbnk##) ; destination bank ld b,a ld c,0 ; source bank call xmove?## ld bc,080h call move?## ld a,(xfercnt) dec a ld (xfercnt),a jr nz,putlp ret ;----------------------- ; SET IX TO DDB ADDRESS ;----------------------- ddbtoix:: ld hl,ddbtbl ; set up to calc current ddb addr ld de,(@adrv##) ; use logical drv no as index to table ld d,0 ; zero high byte of index for dbl add addty (bit 3) s5 equ 10h ; 5" floppy (bit 4) s8 equ 00h ; 8" floppy (bit 4) s0 equ 00h ; side select 0 (bit 2) s1 equ 04h ; side select 1 (bit 2) ;-------------------------------------- ; FLOPPY DISK DEBLOCKING BLOCK INDEXES ;-------------------------------------- secsizl equ 000h secsizh equ 001h dsd equ 002h hdoff equ 003h stepr equ 004h secmsk equ 005h hdshf equ 006h dseg ;------------------------- ; INITALIZE FLOPPY DRIVES ;------------------------- finit:: ret ;-------------------- ; LOGIN FLOPPY DRIVE ;-------------------- flogin:: ld (cdph),de call getds ; get fpy drv siz (8-5) & pdrv # (0-3) call frestore ; restore fpy drv hds jr nz,flogerr ; ret if drv not rdy for select error call getden ; get dsk density (sgl-dbl) call getsd ; get number of sides on dsk (0-1) call setdpb ; set dpb addr in dph to ind. den & sd call settran ; set sec trn vec adr in dph if sgl den call setddb ; set ddb addr in ddbtbl call e,0ch ; pnt to dpb entry of dph add hl,de ; dbp addr in dph is 10th entry push hl ; save addr of dpb address on stk tstsiz: ld a,(cdsd) ; fetch dsd register setting ld hl,fdpb8## ; ld hl w. dpb base for 8" floppy bit 4,a ; check drv siz bit jr z,tstden ; jump if 8" drv ld hl,fdpb548## ; ld hl w. dpb base for 5"-48 tpi fpy bit 5,a ; check 96 tpi bit (** not standard **) jr z,tstden ; jump if 48 tpi drive ld hl,fdpb596## ; ld hl w. dpb base for 5"-96 tpi fpy tstden: bit 3,a ; test density bit of dsd jr z,movdpb ; sgl den dpb = dpb base setdd: ld de,17d ; double den, sgl side is next dpb add hl,de ; index down to next ddb tstsid: bit 2,a ; test if double sided jr z,movdpb ; hl is pointing to dbl den, sgl sd setds: add hl,de ; dbl den, dbl side is next dpb movdpb: pop de ; this is where dpb addr goes in dph ex de,hl ; de =dpb addr, hl =loc in dph of dpb ld (hl),e ; save low byte of addr in dph inc hl ; inc pointer to h hl,de ; add logical drv no to base tbl addr add hl,de ; tbl entrys are wrds, so do add twice ld e,(hl) ; fetch contents of table entry inc hl ; point to high byte of addr ld d,(hl) ; get high byte push de ; put ddb addr into ix-reg pop ix ; by useing ix reg we save instructions ret ;-------------------- ; 16-BIT SHIFT RIGHT ;-------------------- shfr16:: and a ; a-reg has no of shifts to perform shfrlp: ret z srl d ; shift msb first, bit 0 into carry rr e ; rotate carry into bit 7 of lsb dec a ; decrement shift counter jr shfrlp ; loop until finished ;------------------- ; 16-BIT SHIFT LEFT ;------------------- shfl16:: and a shfllp: ret z sla e rl d dec a jr shfllp xfercnt:: db 0 diskbf:: ds 0400h end rent ddb addr ld de,(@adrv##) ; use logical drv no as index to table ld d,0 ; zero high byte of index for dbl add addgetdsd ld a,(cdsd) ; put new dsd reg setting in a-reg ld (hl),a ; save it as a dsdvec entry ret flogerr: pop hl pop de ld de,0 jp (hl) ;------------------------------------------- ; GET DRV SIZE AND PHY DRV NO. FROM DRV MAP ;------------------------------------------- getds: ld hl,(cdph) ; point to drvtyp in @dtbl dec hl ld a,(hl) ; put drive type in a-reg cp 2 ; if =2 then 5"- 96 tpi fpy drv ld a,0 ; a-reg contains dsd setting jr c,dsiz548 ; if =1 then 5" - 48 tpi fpy drv jr nz,getpdrv ; if =3 then 8" fpy drv dsiz596: set 5,a ; set bit 5 to indicate 96 tpi dsiz548: set 4,a ; set bit 4 to indicate 5" fpy getpdrv: dec hl ; phys drv no. is (xdph-2) or (hl) ; or in drive size bit setting ld (cdsd),a ; save it in den - dsiz - dno out (fdsd),a ; set floppy den,dsiz,dno in controller ret ;------------------ ; GET DISK DENSITY ;------------------ getden: call gettkv ld a,1 ; do sek to trk 1, sgl den ld (hl),a ; sigh byte of addr ld (hl),d ; save high byte of addr in dph ret ;--------------------------------------- ; SET TRANSLATION VECTOR ADDRESS IN DPH ;--------------------------------------- settran: ld hl,(cdph) ld a,(cdsd) ; get dsd setting bit 3,a ; chk denisty bit ld de,0 ; initalize de-reg w. tran vec addr jr nz,sett ; jump if double density, (no trn vec) ld de,tran8## ; initalize tran vec addr for 8" tran bit 4,a ; chk drive size bit, =0 for 8", =1 5" jr z,sett ; jump if 8" drive ld de,tran548## ; init tran vec addr for 5-48tpi sglden bit 5,a ; check bit 5 for 96 tpi drive jr z,sett ; jump if 48 tpi drive ld de,tran596## ; de gets 5"-96 tpi sgl den tran vec sett: ld (hl),e ; save tran vec addr as #1 entry in dph inc hl ; vec addr is a word ld (hl),d ; now store high byte xor a ; return w. no errors ret ;------------------- ; SET DDB IN DDBTBL ;------------------- setddb: ld a,(cdsd) ; need this to fig what kind of d title FLOPPY DISK DRIVER -- CP/M 3.0 -- BANKED / NON-BANKED .z80 ; M80 z80 code pseudo op rtrys equ 05 ;---------------------------------- ; FLOPPY CONTROLLER PORT ADDRESSES ;---------------------------------- fbase equ 0ch ; base port addr of wd-1793 or wd-2793 fcmd equ fbase+0 ; command register fstat equ fbase+0 ; status register ftrk equ fbase+1 ; track register fsec equ fbase+2 ; sector register fdata equ fbase+3 ; data register fwait equ 014h ; wait register fdsd equ 014h ; density - size - drive register ;---------------------------- ; FLOPPY CONTROLLER COMMANDS ;---------------------------- fstpr equ 000h ; floppy step rate (0,1,2 or 3) frst equ 000h + fstpr ; restore hds fsek equ 01ch + fstpr ; seek track frd equ 084h ; read sector fwrt equ 0a4h ; write sector ;------------------------------- ; FLOPPY CONTROLLER BIT TESTERS ;------------------------------- dden equ 08h ; double density (bit 3) sden equ 00h ; single densiave trk no. in trk vec call fseek ; do seek to trk 1 ret z ; return if succesful (dsk is sgl den) dbldens: ld c,dden ; else assume dbl den (saves time) ld a,(cdsd) ; get dsd reg setting w. sgl den or c ; or in dbl density setting ld (cdsd),a ; save it and return ret ;--------------------- ; GET NUMBER OF SIDES ;--------------------- getsd: ld a,(cdsd) ; get dsd reg setting as calc so far bit 3,a ; test if single density ret z ; if bit 3 =0, then sgl den ld b,s1 ; get side 1 mask or b ; or side mask into dsd reg setting out (fdsd),a ; send it to the floppy controller ld c,a ; save dsd w. side 1 selected call gettkv ld a,1 ld (hl),a ; save trk no 1 in trkvec call fseekntst ; sek w.out rdy tst,(never rdy if 1 sd) ret nz ; return if error on sek ld a,c ; sek to trk 1, side 1 OK ld (cdsd),a ; save dsd ws side 1 sel in dsd setting ret ;---------------- ; SET DPB IN DPH ;---------------- setdpb: ld hl,(cdph) ld d)sk ld hl,fddb8## ; init hl for 8" sgl sid, sgl den bit 4,a ; check bit 4 for siz, 8"=0, 5"=1 jr z,setddd ; jump to density chk if 8" drv ld hl,fddb548## ; init hl w 5"-48 tpi sgl sid, den bit 5,a ; check bit 5 for tpi, 0=48tpi, 1=96tpi jr z,setddd ; jump to chk den if 48 tpi ld hl,fddb596## ; set hl w. 5"96tpi ddb addr setddd: bit 3,a ; chk bit 3 for density, 0=sgl 1=dbl jr z,mvddb ; jmp if sgl, hl alrdy has addr ld de,07d ; point to next ddb, (sgl sid, dbl den) add hl,de ; add in offset to next ddb bit 2,a ; chk # sides, 0 =1 side, 1 =2 side jr z,mvddb ; jump ovr if sgl sided add hl,de ; add in offset again for next ddb mvddb: push hl ; save ddb addr ld hl,ddbtbl## ; destination of ddb addr is in ddbtbl ld de,(@adrv##) ; ea. entry in tbl is current ddb addr ld d,0 ; zero high byte for dbl add add hl,de ; hl now has destination address add hl,de ; table entrys are words pop de ; restore ddb addr into de-reg ldsition heads over new track samtrk: ld a,(@sect##) ; now set sector no. reg. and (ix+secmsk) ; mask out head no. bits ld b,a ; save sec. to rd/wrt in b-reg pop af ; restore current dsd setting bit 3,a ; density is bit 3 jr z,fsndsec ; jmp ovr if single density inc b ; dbl den, so mak sec no frm 0-7 to 1-8 fsndsec: ld a,b ; put sec no back in a-reg out (fsec),a ; send it to fpy controller sec reg ret ;-------------------- ; FLOPPY ERROR CHECK ;-------------------- errchk: ld hl,rtcnt in a,(fstat) and a jr z,errx inc (hl) ld a,rtrys cp (hl) ret errx: ld (hl),a ; clear retry cnt in case had to retry ret ; return w. no errors ;---------------------- ; RESTORE FLOPPY HEADS ;---------------------- frestore: ld a,(cdsd) ; get physical drive to do restore on out (fdsd),a ; send it to floppy controller call tstrdy ; test it drive is ready ret nz ; return if user abort ld a,frst ; load floppy restore at p frdsec: ld hl,diskbf## ; source starting address ld c,fdata di ; disable console interupts ld a,frd ; start read by sending command out (fcmd),a ; tell ctrler to read sector call delay ; mak sure wait 28 us before rding stat frdlp: in a,(fwait) ; wait until ctrler rdy to snd dta or a ; check if interupt active jp p,frdout ; if bit 7 =0, then inter active ini ; else rd dta, increment buff addr jr frdlp ; loop until interupt =0 frdout: in a,(fstat) ; check for any errors and a ; set nz-flag if errors ei ; enable cnsole interupts ret ;------------------------------- ; TEST IF FLOPPY DRIVE IS READY ;------------------------------- tstrdy: ld a,0d0h ; reset floppy controller out (fcmd),a ; set status reg to current state call delay ; must delay before reading status ld a,(cdsd) ; test if 8 inch drive bit 4,a ; bit 4 =0 if 8", bit 4 =1 if 5" ld de,0ffffh ; set up time out counter jr z,tready ; skip index pulse te (hl),e ; hl-reg has ddbtbl addr inc hl ; pnt to where high byte goes ld (hl),d ; finish storing ddp addr in ddbtbl ld hl,dsd add hl,de ld a,(cdsd) ld (hl),a ret ;------------------- ; WRITE FLOPPY DISK ;------------------- fwrite:: call fsettsk ; set up cntr reg & gen housekeeping call getdata## call fwrtsec ; write sector to floppy call errchk ; check floppy cntr status for errors jr nz,fwrite ; loop if error ret ;------------------ ; READ FLOPPY DISK ;------------------ fread:: call fsettsk ; set controller reg & do housekeeping call frdsec ; read a sector from floppy call putdata## ; call errchk ; chk status for errors jr nz,fread ; loop if error and under retry count ret ;---------------------- ; SET TASK FLOPPY DISK ;---------------------- fsettsk: call ddbtoix## ld a,1 ld e,(ix+secsizl) ld d,(ix+secsizh) call shfl16## ld a,d ld (xfercnt##),a ld a,(ix+hdshf) ld de,(@sect##) call shfr16##roper stp rte out (fcmd),a ; send restore command in a,(fwait) ; wait until command finished executing call gettkv ; put track vector address in hl xor a ; clear zero-flag, used as error flag ld (hl),a ; store a zero in track vector ret ;--------------------- ; SEEK TRACK IN A-REG ;--------------------- fseek: ld b,a ; track to seek passed in a-reg call tstrdy ; wait for drive to become ready ret nz ; return w nz-flay set if user abort ld a,b ; move trk no bk to a, (tstrdy uses a) fseekntst: out (fdata),a ; load trk to sek into data register ld a,fsek ; load a-reg w seek cmd out (fcmd),a ; tell controller to seek the track call delay ; must delay 28 us before reading stat in a,(fwait) ; wait until done with seek in a,(fstat) ; read floppy staus register and 018h ; check for crc and/or seek error ret ;-------------------------- ; WRITE A SECTOR TO FLOPPY ;-------------------------- fwrtsec: in a,(fstat) ; first check sts if 8 in. drv ld hl,tstnidx ; test for no index pulse if 5 in. drv tstnidx: in a,(fstat) ; check no idx to make sure dsk in drv bit 1,a ; bit 1 =1 if index detected jr nz,decde ; decrement counter if index found ld hl,tstidx ; test for index pulse if 5 in. drv tstidx: in a,(fstat) ; check for an index pulse bit 1,a ; bit 1 on status is =0 if no index jr z,decde ; dec time out counter if no index yet tready: ld hl,tstrdx ; test for drive ready 8-5 in. drv tstrdx: in a,(fstat) ; get floppy status bit 7,a ; test not ready bit in status ret z ; return if not ready bit =0 decde: call delay ; delay even move before decrement dec de ; decrement counter in de-reg ld a,d ; check if counter is zero or e ; or high - low byte together jr z,notready ; jump if time out error jp (hl) ; jump to tstnidx, tstidx or tstrdx notready: ld de,nrdymsg ; pass disk err actual error msg call dskerr ; display msg and drv on console jr z,tst call getdsd ; put dsd addr in hl-reg ld a,(hl) ; put dsd setting in a-reg push af ; save current dsd setting res 2,a ; reset head bit sla e ; rotate hd no. to dsd-reg position sla e ; bit 2 is where head select goes or e ; or hd sel w. den, size, and drv no. out (fdsd),a ; send it to floppy controller reg call gettkv ld a,(hl) ; get track no. where head positioned out (ftrk),a ; set trk reg to current hd position ld bc,(@trk##) ; get new track to seek ld de,(@adrv##) ; get drive to do this seek on cp c ; compare w track heads positioned on jr nz,diftrk ; if different, do sek to reload heads ld a,(lastdrv) ; get last drive seek done on cp e ; compare last drive with current drive jr z,samtrk ; if same, then same drive and track diftrk: ld a,e ; save new drive as old drive ld (lastdrv),a ; this will mak sure we ld hds if need ld a,c ; save new track ld (hl),a ; save it in trk vec as new hd position call fseek ; poif write protected bit 6,a ; if bit 6 of stat =1, then protected jr nz,wrtpro ; tell user if protected ld hl,diskbf## ; source starting address ld c,fdata di ; dont want to be intr or will lose dta ld a,fwrt ; start write by sending command out (fcmd),a ; tell ctrler to wrt sec call delay ; mak sure wait 28 us before stat rd fwrtlp: in a,(fwait) ; check if in floppy interupt or a ; interupt is bit 7 of fwait, 0=active jp p,fwrtout ; if zero then no more data 1=nactive outi ; else send dta, inc buf addr jr fwrtlp ; loop until done fwrtout: in a,(fstat) ; read status for errors and a ; set nz flg if no errors ei ; enable console interupts ret wrtpro: ld de,wprtmsg ; pass write prot msg in de to dskerr call dskerr ; call rout to prn msg and wait for cio jr z,fwrtsec ; try again if user didnt type ctrl-c ret ; else return w nz flg set ;--------------------------- ; READ A SECTOR FROM FLOPPY ;---------------------------)rdy ; retry if user didn't type ctrl-c ret ;------------------- ; FLOPPY DISK ERROR ;------------------- dskerr: push bc ; push de ; call pderr?## ; display T-????, S-???? msg on console pop hl ; restore pnter to err msg call pmsg?## ; display exact error msg on console call conin?## ; wait for user to type a character cp 003h ; check if ctrl-c typed push af ld hl,crlfmsg call pmsg?## pop af pop bc jr z,diskerr ; jmp ovr retry if ctrl-c xor a ; set z-flag ld a,0d0h ; reset floppy controler out (fcmd),a ; return to retry command ret diskerr: and 0ffh ; if here, ctrl-c entered, set nz-flag ld a,rtrys-1 ; load a w. no. of retrys minus 1 ld (rtcnt),a ; no retrys, errchk inc rtcnt first ret ;------------------ ; GET TRACK VECTOR ;------------------ gettkv: ld hl,trkvec ; base addr of trk vec ld de,(@adrv##) ; offset into trk vec ld d,0 ; prepare for double add add hl,de ; add offset to base addr ret ------------ bsybit equ 080h ; busy bit rdybit equ 040h ; data request bit errbit equ 001h ; error bit ;------------------------------- ; DISK DEBLOCKING BLOCK INDEXES ;------------------------------- secsizl equ 000h ; sector size low byte index secsizh equ 001h ; sector size high byte index sdh equ 002h ; sdh register setting index hdoff equ 003h ; head offset index stepr equ 004h ; step rate index secmsk equ 005h ; sector mask index hdshf equ 006h ; head shift index dseg ;--------------------- ; INITALIZE HARD DISK ;--------------------- hinit:: ld hl,ddbtbl## ld de,(@adrv##) ld d,0 add hl,de ; add in logical drive index add hl,de ld e,(hl) ; get low byte of ddb addr inc hl ; point to high byte of addr ld d,(hl) ; get high byte of addr push de pop ix ld a,(@rdrv##) ; unit is really physical drive no sla a ; rotate it to correct position sla a ; hdc-1001 expects to see it at 3-4 sla a ; one more time or (iecsizl) ld c,hdata otir ld a,(ix+secsizh) cp 2 ret nz otir ret ;---------------------------- ; READ SECTOR FROM HARD DISK ;---------------------------- hrdsec: ld a,cmdrd out (hcmd),a call polbsy ld hl,diskbf## ld b,(ix+secsizl) ld c,hdata inir ld a,(ix+secsizh) cp 2 ret nz inir ret ;--------------------- ; POLL BUSY HARD DISK ;--------------------- polbsy: in a,(hstatus) ; read status port and a ; set flags jp m,polbsy ; loop if busy bit set and errbit ; mask for error bit ret end llow reg ld a,(@trk##+1) ; move msb to a-reg out (hcylhi),a ; send to cyl high ld a,(@sect##) ; get host sector no and (ix+secmsk) ; mask out head no. bits out (hsec),a ; send to sector register ret ;--------------------------- ; WRITE SECTOR TO HARD DISK ;--------------------------- hwrtsec: ld a,cmdwrt out (hcmd),a ld hl,diskbf## ld b,(ix+s ;------------------------------- ; GET DENSITY-SIZE-DRIVE VECTOR ;------------------------------- getdsd: ld hl,dsdvec ; load hl w. login vec base addr ld bc,(@adrv##) ; fetch logical drv no. ld b,0 ; zero out high byt to prep for dbl add add hl,bc ; add in offset to login vector ret ;------------------------------- ; DELAY 28u SECONDS AT 6 mhz ;------------------------------ delay: ld a,3 ; initialize loop counter delaylp: ex (sp),hl ; 19 cycles ex (sp),hl ; 19 cycles dec a ; 4 cycles jr nz,delaylp ; 10 cycles = 52 cyc = 8.7 @ 6 mhz ret ;------------------------------------------------ ; DATA STORAGE ;------------------------------------------------ nrdymsg: db ', Drive Not Ready',0 wprtmsg: db ', Write Protected Disk',0 crlfmsg: db 0dh,0ah,0 cdph: dw 0 cdsd: db 0 lastdrv: db 0ffh rtcnt: db 0 ; retry counter dsdvec: ds 16,0ffh ; drive login vector trkvec: ds 16,0ffh ; current head position on drive end x+sdh) ; or in sdh reg setting w. pdrv out (hsdh),a ; send it to controller xor a ; zero a-reg out (hcyllow),a ; reset cylinder low register out (hcylhi),a ; reset cylinder high register ld a,cmdsek ; load a-reg w. seek command or (ix+stepr) ; or in proper step rate out (hcmd),a ; seek cylinder 000 @ correct step rate call polbsy ; wait until ctrl done exec seek cmd ret ;----------------- ; LOGIN HARD DISK ;----------------- hlogin:: ret ;----------------- ; WRITE HARD DISK ;----------------- hwrite:: call hsettsk ; set up hdc1001 ctrler registers call getdata## call hwrtsec call polbsy ret ;---------------- ; READ HARD DISK ;---------------- hread:: call hsettsk ; first set up controller registers call hrdsec call putdata## ; call polbsy ; check for errors ret ;-------------------- ; SET TASK HARD DISK ;-------------------- hsettsk: call ddbtoix## ld a,1 ld e,(ix+secsizl) ld d,(ix+secsizh) ca title HARD DISK DRIVER -- CP/M 3.0 -- BANKED / NON-BANKED .z80 ; Zilog mneumonics used ;------------------------------------ ; HDC-1001 CONTROLLER PORT ADDRESSES ;------------------------------------ hbase equ 0e0h ; base port address of hdc-1001 hdata equ hbase+0 ; data register herror equ hbase+1 ; error register hwrtpre equ hbase+1 ; write pre-compensation register hseccnt equ hbase+2 ; sector count register hsec equ hbase+3 ; sector number register hcyllow equ hbase+4 ; cylinder low register hcylhi equ hbase+5 ; cylinder high register hsdh equ hbase+6 ; size - drive - head register hstatus equ hbase+7 ; status register port hcmd equ hbase+7 ; command register port ;------------------- ; HDC-1001 COMMANDS ;------------------- cmdsek equ 070h ; seek command cmdrd equ 020h ; read sector command cmdwrt equ 030h ; write sector command ;-------------------------------------- ; HDC-1001 STATUS REGISTER BIT TESTERS ;--------------------------ll shfl16## ld a,d ld (xfercnt##),a ld a,(ix+hdshf) ; load a w. head shift factor ld de,(@sect##) ; get sector relative to cylinder call shfr16## ; high 3-bits of sector are head no ld a,(@rdrv##) ; get physical drive no. sla a ; rotate phy drive to correct position sla a ; drive is expected in bits 3 and 4 sla a ; last shift for drive or e ; or in head no calculated above or (ix+sdh) ; or it in w. rotated phy drive no add a,(ix+hdoff) ; add in head offset out (hsdh),a ; send it siz drv hd register ld a,(@trk##) ; move lsb to a-reg for out inst out (hcyllow),a ; send low byte to cyllow reg ld a,(@trk##+1) ; move msb to a-reg out (hcylhi),a ; send to cyl high ld a,(@sect##) ; get host sector no and (ix+secmsk) ; mask out head no. bits out (hsec),a ; send to sector register ret ;--------------------------- ; WRITE SECTOR TO HARD DISK ;--------------------------- hwrtsec: ld a,cmdwrt out (hcmd),a ld hl,diskbf## ld b,(ix+s* title DEVICE INIT. AND SIGN-ON -- CP/M 3.0 -- BANKED / NON-BANKED .z80 ; Zilog mnemonics ;------------------- ; SIO CONTROL PORTS ;------------------- sioad equ 000h ; SIO channel A data port sioac equ 001h ; SIO channel A control port siobd equ 002h ; SIO channel B data port siobc equ 003h ; SIO channel B control port ;------------------- ; PIO CONTROL PORTS ;------------------- pioad equ 004h ; PIO channel A data port pioac equ 006h ; PIO channel A control port piobd equ 005h ; PIO channel B data port piobc equ 007h ; PIO channel B control port ;------------------- ; CTC CONTROL PORTS ;------------------- ctc0 equ 008h ; CTC channel 0 control port ctc1 equ 009h ; CTC channel 1 control port ctc2 equ 00ah ; CTC channel 2 control port ctc3 equ 00bh ; CTC channel 3 control port ;-------------------------------- ; CTC TIMER CONTROL BIT SETTINGS ;-------------------------------- inter equ 080h ; interupt mode (no interupts) igh byte of intr tbl vec in a ld i,a ; initalize interupt vector ld a,l ; put low byte of intr tbl vec in a-reg ld (lsiov),a ; put low byte in sio ch. b init block im 2 ; set interupt mode to 2 ;------------------------------- ; I/O REDIRECTION INITALIZATION ;------------------------------- redinit: ld hl,08000H ; device no. 0 is console (sio ch. a) ld (@civec##),hl ; console input vector ld (@covec##),hl ; console output vector ld hl,04000H ; device no. 1 is auxiliary (sio ch. b) ld (@aivec##),hl ; auxiliary input vector ld (@aovec##),hl ; auxiliary output vector ld hl,02000h ; device no. 2 is list (pio ch. a & b) ld (@lovec##),hl ; output only ;------------------- ; CTC INITALIZATION ;------------------- ctcinit: ld a,counter+tcfol+reset+ctrlwd out (ctc0),a ; initalize ctc channel 0 ld a,250d ; time constant for channel 0 out (ctc0),a ; channel 0 is expecting this ld a,inter+counter+tcfol+reset+ctrlwd out (ctc1),a ; initaliz--------- ; SIO CHANNEL A INITALIZATION TABLE ;----------------------------------- isioa: db 018h ; channel reset db 001h ; write reg 1 db 018h ; int on all recv char (no parity) 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 sio ch a init sequence ;----------------------------------- ; SIO CHANNEL B INITALIZATION TABLE ;----------------------------------- isiob: db 018h ; channel reset db 001h ; write reg 1 db 004h ; status affects interrupt vector db 002h ; write reg 2 lsiov: db 0 ; inter vec tbl low byte addr 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 $-isio counter equ 040h ; counter mode (timer mode) pre256 equ 020h ; prescale value 256 (prescale 16) clkris equ 010h ; clk trigger rising edge (falling edg) clkgo equ 008h ; clk trigger starts clock (auto start) tcfol equ 004h ; time constant follows (no time const) reset equ 002h ; software reset (continue operation) ctrlwd equ 001h ; control word (vector) ;------------------------------------------------ ; INTERUPT VECTOR TABLE RESIDES IN COMMON MEMORY ;------------------------------------------------ cseg isvctbl:: siovec:: dw iret ; SIO ch B transmitter buffer empty dw iret ; SIO ch B external interrupts dw iret ; SIO ch B receiver ready dw iret ; SIO ch B special receive interrupt dw iret ; SIO ch A transmitter buffer empty dw iret ; SIO ch A external interrupts dw sioasvc## ; SIO ch A receiver ready dw sioasvc## ; SIO ch A special receive interrupt ctcvec:: dw iret ; CTC ch 0 svc dw ctc1svc## ; CTC ch 1 svc dw iret ; CTC ch 2 svc e ctc channel 1 ld a,100d ; time constant for ctc channel 1 out (ctc1),a ; this channel issues interupts ld hl,ctcvec ; addr of ctc svc in inter table ld a,l ; need only the low byte of addr out (ctc0),a ; better be on a 8-byte block boundry ; ie. lower 3-bits =0 ;------------------- ; SIO INITALIZATION ;------------------- sioinit: ld hl,isioa ld bc,isioal*256+sioac otir ld hl,isiob ld bc,isiobl*256+siobc otir ;------------------- ; PIO INITALIZATION ;------------------- pioinit: ld a,0fh ; use both pio ch A & B w. parallel lst out (pioac),a ; pio ch A is output mode ld a,0cfh ; pio ch b is bit mode out (piobc),a ; channel b has pio busy and strobe ld a,00011111b ; in = bsy,op,sel,flt,-ack out (piobc),a ; out = pb5,-prime,strobe xor a ; clear a-reg out (piobd),a ; reset strobe ;----------------------------------- ; DISPLAY COLD BOOT SIGN ON MESSAGE ;----------------------------------- psignon: ld bc,(@civec##) b ; length of sio ch b init sequence ;---------------------------- ; COLD BOOT SIGN ON MESSAGES ;---------------------------- signon: db 0dh,0ah db 'Super Bios v. 3.0', 0dh,0ah db 'CP/M 3.0 installed',0dh,0ah,0ah db 'Default console is serial device ' cdevno: db 040h,0dh,0ah prnmsg: db 'Default printer is ',0 ppmsg: db 'parallel device',0ah,0ah,0dh,0 spmsg: db 'serial device' pdevno: db 041h,0ah,0ah,0dh,0 end -------- ; SIO CHANNEL B INITALIZATION TABLE ;----------------------------------- isiob: db 018h ; channel reset db 001h ; write reg 1 db 004h ; status affects interrupt vector db 002h ; write reg 2 lsiov: db 0 ; inter vec tbl low byte addr 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 $-isio dw iret ; CTC ch 3 svc ;---------------------------- ; SAVE - RESTORE SVC UTILITY ;---------------------------- save:: ex (sp),hl ; save hl on stk and put ret addr in hl push de ; save de push bc ; save bc push af ; save af call go ; put restore address on tos restore: pop af ; reinstate cpu to state before intr pop bc ; restore bc pop de ; restore de pop hl ; restore hl ld sp,(ssp) ; restore system stack pointer iret: ei ; enable interupts and return reti go: jp (hl) ; ret to next inst after call save ;------------------ ; SVC DATA STORAGE ;------------------ ssp:: dw 0 ds 020h istk:: ;----------------------------------------------- ; DEVICE INITALIZATION RESIDES IN BANKED MEMORY ;----------------------------------------------- dseg ;------------------------------- ; INTERUPT VECTOR INITALIZATION ;------------------------------- init?:: ld hl,isvctbl ; put interupt table vector in hl ld a,h ; put h ; get console input vector call getdev ; put ascii code of ch. no. in c ld (cdevno),a ld hl,signon ; point to first part of signon message call pmsg?## ; display most of signon message ld bc,(@lovec##) ; get list output vector call getdev ; ret w. ascii code of ch no in c & a ld (pdevno),a ; save prn dev. no. in case serial cp '2' ; check if parallel jr nz,serprn ; jump if serial parprn: ld hl,ppmsg ; load hl w. parallel printer message jr signonx ; display message serprn: ld hl,spmsg ; load hl w. serial printer message signonx: call pmsg?## ; display message and exit ret ; exit from 'init?' ;------------------- ; GET DEVICE NUMBER ;------------------- getdev: ld a,'0'-1 ; init a to ascii val of zero ciochno: inc a ; incrment to next ascii no. rlc b ; rotate next bit of redir vec into car jr nc,ciochno ; loop until find a bit that is set ld c,a ; ret w. ascii val of dev no in a and c ret ;--------------------------* TITLE 'Root module of relocatable BIOS for CP/M 3.0' .Z80 ; version 1.0 15 Sept 82 TRUE EQU -1 FALSE EQU NOT TRUE BANKED EQU FALSE ; Copyright (C), 1982 ; Digital Research, Inc ; P.O. Box 579 ; Pacific Grove, CA 93950 ; This is the invariant portion of the modular BIOS and is ; distributed as source for informational purposes only. ; All desired modifications should be performed by ; adding or changing externally defined modules. ; This allows producing "standard" I/O modules that ; can be combined to support a particular system ; configuration. CR EQU 13 LF EQU 10 BELL EQU 7 CTLQ EQU 'Q'-'@' CTLS EQU 'S'-'@' CCP EQU 0100H ; Console Command Processor gets loaded into the TPA CSEG ; GENCPM puts CSEG stuff in common memory ; variables in system data page EXTRN @COVEC,@CIVEC,@AOVEC,@AIVEC,@LOVEC ; I/O redirection vectors EXTRN @MXTPA ; addr of system entry point EXTRN @BNKBF ; 128 byte scratch buffer ; initialization EX memory address READ?: JP READ ; 13 read physical block(s) WRITE?: JP WRITE ; 14 write physical block(s) LISTS?: JP LISTST ; 15 return list device status SCTRN?: JP SECTRN ; 16 translate logical to physical sector CONOS?: JP CONOST ; 17 return console output status AUXIS?: JP AUXIST ; 18 return aux input status AUXOS?: JP AUXOST ; 19 return aux output status DVTBL?: JP DEVTBL ; 20 return address of device def table DEVIN?: JP CINIT? ; 21 change baud rate of device DRTBL?: JP GETDRV ; 22 return address of disk drive table MLTIO?: JP MULTIO ; 23 set multiple record count for disk I/O FLUSH?: JP FLUSH ; 24 flush BIOS maintained disk caching MOV?: JP MOVE? ; 25 block move memory to memory TIM?: JP TIME? ; 26 Signal Time and Date operation BNKSL?: JP BNKSEL ; 27 select bank for code execution and default DMA STBNK?: JP SETBNK ; 28 select different bank for disk I/O DMA operations. XMOV?: JP XMOVE? ; 29 set source and destination banks for one operation all selected devices CONOUT: LD HL,(@COVEC) ; fetch console output bit vector JP OUT$SCAN ; AUXOUT ; Auxiliary Output. Send character in ; to all selected devices AUXOUT: LD HL,(@AOVEC) ; fetch aux output bit vector JP OUT$SCAN ; LIST ; List Output. Send character in ; to all selected devices. LIST: LD HL,(@LOVEC) ; fetch list output bit vector OUT$SCAN: LD B,0 ; start with device 0 CO$NEXT: ADD HL,HL ; shift out next bit JP NC,NOT$OUT$DEVICE PUSH HL ; save the vector PUSH BC ; save the count and character NOT$OUT$READY: CALL COSTER OR A JP Z,NOT$OUT$READY POP BC PUSH BC ; restore and resave the character and device CALL CO? ; if device selected, print it POP BC ; recover count and character POP HL ; recover the rest of the vector NOT$OUT$DEVICE: INC B ; next device number LD A,H OR L ; see if any devices left JP NZ,CO$NEXT ; and go find them... RET ; CONOST ; Console Output StTRN INIT? ; general initialization and signon EXTRN LDCCP?,RLCCP? ; load & reload CCP for BOOT & WBOOT ; user defined character I/O routines EXTRN CI?,CO?,CIST?,COST? ; each take device in EXTRN CINIT? ; (re)initialize device in EXTRN @CTBL ; physical character device table ; disk communication data items EXTRN @DTBL ; table of pointers to XDPHs PUBLIC @ADRV,@RDRV,@TRK,@SECT ; parameters for disk I/O PUBLIC @DMA,@DBNK,@CNT ; '' '' '' '' ; memory control PUBLIC @CBNK ; current bank EXTRN XMOVE?,MOVE? ; select move bank, and block move EXTRN BANK? ; select CPU bank ; clock support EXTRN TIME? ; signal time operation ; general utility routines PUBLIC PMSG?,PDEC? ; print message, print number from 0 to 65535 PUBLIC PDERR? ; print BIOS disk error message header MACLIB MODEBAUD.LIB ; define mode bits ; External names for BIOS entry points PUBLIC BOOT?,WBOOT?,CONST?,CONIN?,CONO?,LIST?,AUXO?,AUXI? PUBLIC JP 0 ; 30 reserved for future expansion JP 0 ; 31 reserved for future expansion JP 0 ; 32 reserved for future expansion ; BOOT ; Initial entry point for system startup. DSEG ; this part can be banked BOOT: LD SP,BOOT$STACK LD C,15 ; initialize all 16 character devices C$INIT$LOOP: PUSH BC CALL CINIT? POP BC DEC C JP P,C$INIT$LOOP CALL INIT? ; perform any additional system initialization ; and print signon message LD BC,16*256+0 LD HL,@DTBL ; init all 16 logical disk drives D$INIT$LOOP: PUSH BC ; save remaining count and abs drive LD E,(HL) INC HL LD D,(HL) INC HL ; grab @drv entry LD A,E OR D JP Z,D$INIT$NEXT ; if null, no drive PUSH HL ; save @drv pointer EX DE,HL ; XDPH address in DEC HL DEC HL LD A,(HL) LD (@RDRV),A ; get relative drive code LD A,C LD (@ADRV),A ; get absolute drive code DEC HL ; point to init pointer LD D,(HL) DEC HL LD E,(HL) ; get init pointer EX DE,HL CALLatus. Return true if ; all selected console output devices ; are ready. CONOST: LD HL,(@COVEC) ; get console output bit vector JP OST$SCAN ; AUXOST ; Auxiliary Output Status. Return true if ; all selected auxiliary output devices ; are ready. AUXOST: LD HL,(@AOVEC) ; get aux output bit vector JP OST$SCAN ; LISTST ; List Output Status. Return true if ; all selected list output devices ; are ready. LISTST: LD HL,(@LOVEC) ; get list output bit vector OST$SCAN: LD B,0 ; start with device 0 COS$NEXT: ADD HL,HL ; check next bit PUSH HL ; save the vector PUSH BC ; save the count LD A,0FFH ; assume device ready CALL C,COSTER ; check status for this device POP BC ; recover count POP HL ; recover bit vector OR A ; see if device ready RET Z ; if any not ready, return false INC B ; drop device number LD A,H OR L ; see if any more selected devices JP NZ,COS$NEXT OR 0FFH ; all selected were ready, retu HOME?,SLDSK?,STTRK?,STSEC?,STDMA?,READ?,WRITE? PUBLIC LISTS?,SCTRN? PUBLIC CONOS?,AUXIS?,AUXOS?,DVTBL?,DEVIN?,DRTBL? PUBLIC MLTIO?,FLUSH?,MOV?,TIM?,BNKSL?,STBNK?,XMOV? ; BIOS Jump vector. ; ; All BIOS routines are invoked by calling these ; entry points. ;Public Local BIOS Description ;Name Routine Func BOOT?: JP BOOT ; 00 initial entry on cold start WBOOT?: JP WBOOT ; 01 reentry on program exit, warm start CONST?: JP CONST ; 02 return console input status CONIN?: JP CONIN ; 03 return console input character CONO?: JP CONOUT ; 04 send console output character LIST?: JP LIST ; 05 send list output character AUXO?: JP AUXOUT ; 06 send auxilliary output character AUXI?: JP AUXIN ; 07 return auxilliary input character HOME?: JP HOME ; 08 set disks to logical home SLDSK?: JP SELDSK ; 09 select disk drive, return disk parameter info STTRK?: JP SETTRK ; 10 set disk track STSEC?: JP SETSEC ; 11 set disk sector STDMA?: JP SETDMA ; 12 set disk I/O IPCHL ; call init routine POP HL ; recover @drv pointer D$INIT$NEXT: POP BC ; recover counter and drive # INC C DJNZ D$INIT$LOOP ; and loop for each drive JP BOOT$1 CSEG ; following in resident memory BOOT$1: CALL SET$JUMPS CALL LDCCP? ; fetch CCP for first time JP CCP ; WBOOT ; Entry for system restarts. WBOOT: LD SP,BOOT$STACK CALL SET$JUMPS ; initialize page zero CALL RLCCP? ; reload CCP JP CCP ; then reset jmp vectors and exit to ccp SET$JUMPS: IF BANKED LD A,1 CALL BNKSL? ENDIF LD A,0C3H LD (0),A LD (5),A ; set up jumps in page zero LD HL,WBOOT? LD (1),HL ; BIOS warm start entry LD HL,(@MXTPA) LD (6),HL ; BDOS system call entry RET DS 64 BOOT$STACK EQU $ ; DEVTBL ; Return address of character device table DEVTBL: LD HL,@CTBL RET ; GETDRV ; Return address of drive table GETDRV: LD HL,@DTBL RET ; CONOUT ; Console Output. Send character in ; to +rn true RET COSTER: ; check for output device ready, including optional ; xon/xoff support LD L,B LD H,0 ; make device code 16 bits PUSH HL ; save it in stack ADD HL,HL ADD HL,HL ADD HL,HL ; create offset into device characteristics tbl LD DE,@CTBL+6 ADD HL,DE ; make address of mode byte LD A,(HL) AND MB$XON$XOFF POP HL ; recover console number in JP Z,COST? ; not a xon device, go get output status direct LD DE,XOFFLIST ADD HL,DE ; make pointer to proper xon/xoff flag CALL CIST1 ; see if this keyboard has character LD A,(HL) CALL NZ,CI1 ; get flag or read key if any CP CTLQ JP NZ,NOT$Q ; if its a ctl-Q, LD A,0FFH ; set the flag ready NOT$Q: CP CTLS JP NZ,NOT$S ; if its a ctl-S, LD A,00H ; clear the flag NOT$S: LD (HL),A ; save the flag CALL COST1 ; get the actual output status, AND (HL) ; and mask with ctl-Q/ctl-S flag RET ; return this as the status CIST1: ; get input status with and LD BC,TABLE10 LD DE,-10000 NEXT: LD A,'0'-1 PDECL: PUSH HL INC A ADD HL,DE JP NC,STOPLOOP INC SP INC SP JP PDECL STOPLOOP: PUSH DE PUSH BC LD C,A CALL CONO? POP BC POP DE NEXTDIGIT: POP HL LD A,(BC) LD E,A INC BC LD A,(BC) LD D,A INC BC LD A,E OR D JP NZ,NEXT RET TABLE10: DW -1000,-100,-10,-1,0 ; print value in A in hex 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 ; print disk drive error message PDERR?: LD HL,DRIVE$MSG CALL PMSG? ; error header LD A,(@ADRV) ADD A,'A' LD C,A CALL CONO? ; drive code LD HL,TRACK$MSG CALL PMSG? ; track header LD HL,( ; fall through to set DMA bank ; SETBNK ; Set Disk Memory Bank. Saves bank number ; in @DBNK for future disk data ; transfers. SETBNK: LD (@DBNK),A RET ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returns physical=logical. SECTRN: LD L,C LD H,B LD A,D OR E RET Z EX DE,HL ADD HL,BC LD L,(HL) LD H,0 RET ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter header (XDPH). READ: LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-8 ADD HL,DE ; point to read routine address JP RW$COMMON ; use common code ; WRITE ; Write physical sector from currently selL> saved PUSH BC PUSH HL CALL CIST? POP HL POP BC OR A RET COST1: ; get output status, saving & PUSH BC PUSH HL CALL COST? POP HL POP BC OR A RET CI1: ; get input, saving & PUSH BC PUSH HL CALL CI? POP HL POP BC RET ; CONST ; Console Input Status. Return true if ; any selected console input device ; has an available character. CONST: LD HL,(@CIVEC) ; get console input bit vector JP IST$SCAN ; AUXIST ; Auxiliary Input Status. Return true if ; any selected auxiliary input device ; has an available character. AUXIST: LD HL,(@AIVEC) ; get aux input bit vector IST$SCAN: LD B,0 ; start with device 0 CIS$NEXT: ADD HL,HL ; check next bit LD A,0 ; assume device not ready CALL C,CIST1 ; check status for this device OR A RET NZ ; if any ready, return true INC B ; drop device number LD A,H OR L ; see if any more selected devices JP NZ,CIS$NEXT XOR A ; all @TRK) CALL PDEC? ; track number LD HL,SECTOR$MSG CALL PMSG? ; sector header LD HL,(@SECT) CALL PDEC? ; sector number RET ; BNKSEL ; Bank Select. Select CPU bank for further execution. BNKSEL: LD (@CBNK),A ; remember current bank JP BANK? ; and go exit through users ; physical bank select routine XOFFLIST: DB -1,-1,-1,-1,-1,-1,-1,-1 ; ctl-s clears to zero DB -1,-1,-1,-1,-1,-1,-1,-1 DSEG ; following resides in banked memory ; Disk I/O interface routines ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke login procedure for drive ; if this is first select. Return ; address of disk parameter header ; in SELDSK: LD A,C LD (@ADRV),A ; save drive select code LD L,C LD H,0 ADD HL,HL ; create index from drive code LD BC,@DTBL ADD HL,BC ; get pointer to dispatch table LD A,(HL) INC HL LD H,(HL) LD L,A ; point at disk descriptor OR H RET Z ; if no entry in table, no disk LD ected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). WRITE: LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-10 ADD HL,DE ; point to write routine address RW$COMMON: LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of routine POP DE ; recover address of table DEC DE DEC DE ; point to relative drive LD A,(DE) LD (@RDRV),A ; get relative drive code and post it INC DE INC DE ; point to DPH again JP (HL) ; leap to driver ; MULTIO ; Set multiple sector count. Saves passed count in ; @CNT MULTIO: LD (@CNT),A RET ; FLUSH ; BIOS deblocking buffer flush. Not implemented. FLUSH: XOR A RET ; return with no error ; error message components DRIVE$MSG: DB CR,LF,BELL,'BIOS Error on ',0 TRselected were not ready, return false RET ; CONIN ; Console Input. Return character from first ; ready console input device. CONIN: LD HL,(@CIVEC) JP IN$SCAN ; AUXIN ; Auxiliary Input. Return character from first ; ready auxiliary input device. AUXIN: LD HL,(@AIVEC) IN$SCAN: PUSH HL ; save bit vector LD B,0 CI$NEXT: ADD HL,HL ; shift out next bit LD A,0 ; insure zero a (nonexistant device not ready). CALL C,CIST1 ; see if the device has a character OR A JP NZ,CI$RDY ; this device has a character INC B ; else, next device LD A,H OR L ; see if any more devices JP NZ,CI$NEXT ; go look at them POP HL ; recover bit vector JP IN$SCAN ; loop til we find a character CI$RDY: POP HL ; discard extra stack JP CI? ; Utility Subroutines IPCHL: ; vectored CALL point JP (HL) ; print messageg pointed to by HL and ending w/ 0 PMSG?: ; print message @ up to a null ; saves & PUSH BA,E AND 1 JP NZ,NOT$FIRST$SELECT ; examine login bit PUSH HL EX DE,HL ; put pointer in stack & LD HL,-2 ADD HL,DE LD A,(HL) LD (@RDRV),A ; get relative drive LD HL,-6 ADD HL,DE ; find LOGIN addr LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of LOGIN routine CALL IPCHL ; call LOGIN POP HL ; recover DPH pointer NOT$FIRST$SELECT: RET ; HOME ; Home selected drive. Treated as SETTRK(0). HOME: LD BC,0 ; same as set track zero ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. SETTRK: LD (@TRK),BC RET ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further operations. SETSEC: LD (@SECT),BC RET ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @CBNK ; so that further disk operations take place ; in current bank. SETDMA: LD (@DMA),BC LD A,(@CBNK) ; default DMA bank is current bank +ACK$MSG: DB ': T-',0 SECTOR$MSG: DB ', S-',0 ; disk communication data items @ADRV: DS 1 ; currently selected disk drive @RDRV: DS 1 ; controller relative disk drive @TRK: DS 2 ; current track number @SECT: DS 2 ; current sector number @DMA: DS 2 ; current DMA address @CNT: DB 0 ; record count for multisector transfer @DBNK: DB 0 ; bank for DMA operations CSEG @CBNK: DB 0 ; bank for processor operations ; ; following DS insures that the interupt service routine table ; located in the next link module will start on 16-byte boundry ; ds 16 - (($-boot?) mod 16) endaddr:: END C3FDSK MACC3HDSK MAC%EFGC3INIT MAC ; disk communication data items EXTRN @DTBL ; table of pointers to XDPHs PUBLIC @ADRV,@RDRV,@TRK,@SECT ; parameters for dve?## ; 25 block move memory to memory TIM?: JP $ ; 26 Signal Time and Date operation BNKSL?: JP $ ; 27 select bank for code execution and default DMA STBNK?: JP $ ; 28 select different bank for disk I/O DMA operations. XMOV?: JP $ ; 29 set source and destination banks for one operation JP $ ; 30 reserved for future expansion JP $ ; 31 reserved for future expansion JP $ ; 32 reserved for future expansion ds 32 loc$stk:: dw 0 ; ; Utility subroutines ; IPCHL: ; vectored CALL point JP (HL) PMSG?: ; print message @ up to a null ; saves & ld (loc$stk),SP ld SP,loc$stk PUSH BC PUSH DE PMSG$LOOP: LD A,(HL) OR A JP Z,PMSG$EXIT LD C,A PUSH HL CALL CONO? POP HL INC HL JP PMSG$LOOP PMSG$EXIT: POP DE POP BC ld SP,(loc$stk) RET PDEC?: ; print binary number 0-65535 from LD BC,TABLE10 LD DE,-10000 NEXT: LD A,'0'-1 PDECL: PUSH HL INC A ADD HL,DE JP NC,STOPLOOP INC SP INC SP JP title CHARACTER I/O DRIVER -- CP/M 3.0 -- LOADER .z80 ;--------------- ; CONSOLE INPUT ;--------------- ci?:: call cist? ; get input status jr z,ci? ; loop until character received in a,(0) ; get character from sio ch a and 07fh ; mask high order bit ret ;---------------- ; CONSOLE OUTPUT ;---------------- co?:: call cost? ; get status jr z,co? ; go back if not ready ld a,c ; put character to send in a out (0),a ; send char to sio ch a ret ;---------------------- ; CONSOLE INPUT STATUS ;---------------------- cist?:: in a,(1) ; get status of sio ch a and 1 ; check if character recieved ret z ; no character waiting ld a,0ffh ; character waiting ret ;----------------------- ; CONSOLE OUTPUT STATUS ;----------------------- cost?:: in a,(1) ; get status and 4 ; ready? ret z ; no or 0ffh ; else set ready ret ; and exit end isk I/O PUBLIC @DMA,@CNT,@DBNK ; '' '' '' '' ; general utility routines PUBLIC PMSG?,PDEC? ; print message, print number from 0 to 65535 PUBLIC PDERR? ; print BIOS disk error message header MACLIB MODEBAUD.LIB ; define mode bits ; External names for BIOS entry points PUBLIC BOOT?,WBOOT?,CONST?,CONIN?,CONO?,LIST?,AUXO?,AUXI? PUBLIC HOME?,SLDSK?,STTRK?,STSEC?,STDMA?,READ?,WRITE? PUBLIC LISTS?,SCTRN? PUBLIC CONOS?,AUXIS?,AUXOS?,DVTBL?,DEVIN?,DRTBL? PUBLIC MLTIO?,FLUSH?,MOV?,TIM?,BNKSL?,STBNK?,XMOV? ; BIOS Jump vector. ; ; All BIOS routines are invoked by calling these ; entry points. ;Public Local BIOS Description ;Name Routine Func BOOT?: ret ; 00 initial entry on cold start db 0,0 WBOOT?: JP $ ; 01 reentry on program exit, warm start CONST?: JP cist? ; 02 return console input status CONIN?: JP ci? ; 03 return console input character CONO?: JP CO? ; 04 send console output character LIST?: JP $ ; 05 send list ou, PDECL STOPLOOP: PUSH DE PUSH BC LD C,A CALL CONO? POP BC POP DE NEXTDIGIT: POP HL LD A,(BC) LD E,A INC BC LD A,(BC) LD D,A INC BC LD A,E OR D JP NZ,NEXT RET TABLE10: DW -1000,-100,-10,-1,0 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 cono? PDERR?: LD HL,DRIVE$MSG CALL PMSG? ; error header LD A,(@ADRV) ADD A,'A' LD C,A CALL CONO? ; drive code LD HL,TRACK$MSG CALL PMSG? ; track header LD HL,(@TRK) CALL PDEC? ; track number LD HL,SECTOR$MSG CALL PMSG? ; sector header LD HL,(@SECT) CALL PDEC? ; sector number RET ; Disk I/O interface routines ; SELDSK ; Select Disk Drive. Drive code in . ; Invoke login procedure for drive ; if this is first select. Return ; address of disk parameter header ; in SELDSK:: LD A,C LD (@ADRV),A ; save drive select code LD L,C LD H,0 ADD HL,HD HL,DE ; point to read routine address JP RW$COMMON ; use common code ; WRITE ; Write physical sector from currently selected drive. ; Finds address of proper write routine from ; extended disk parameter header (XDPH). WRITE: ld (loc$stk),SP ;set up local stack ld SP,loc$stk LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-10 ADD HL,DE ; point to write routine address RW$COMMON: LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of routine POP DE ; recover address of table DEC DE DEC DE ; point to relative drive LD A,(DE) LD (@RDRV),A ; get relative drive code and post it INC DE INC DE ; point to DPH again call IPCHL ; leap to driver ld SP,(loc$stk) ;restore stack pointer ret ; error message components DRIVE$MSG: DB CR,LF,BELL,'BIOS Error  title MOVE MODULE -- CP/M 3.0 NON-BANKED .z80 xmove?:: ret ; no inter bank moves move?:: ex de,hl ; passed source in de and dest in hl ldir ; use Z80 block move instruction ex de,hl ; ret w. next addresses in same regs ret bank?:: ret ; no bank select in non-banked system end e:: db 0 ; fake BDOS error mode endaddr:: END --------------- ; CONSOLE INPUT STATUS ;---------------------- cist?:: in a,(1) ; get status of sio ch a and 1 ; check if character recieved ret z ; no character waiting ld a,0ffh ; character waiting ret ;----------------------- ; CONSOLE OUTPUT STATUS ;----------------------- cost?:: in a,(1) ; get status and 4 ; ready? ret z ; no or 0ffh ; else set ready ret ; and exit end L ; create index from drive code LD BC,@DTBL ADD HL,BC ; get pointer to dispatch table LD A,(HL) INC HL LD H,(HL) LD L,A ; point at disk descriptor OR H RET Z ; if no entry in table, no disk LD A,E AND 1 JP NZ,NOT$FIRST$SELECT ; examine login bit LD (loc$stk),SP ;setup local stack ld SP,loc$stk PUSH HL EX DE,HL ; put pointer in stack & LD HL,-2 ADD HL,DE LD A,(HL) LD (@RDRV),A ; get relative drive LD HL,-6 ADD HL,DE ; find LOGIN addr LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of LOGIN routine CALL IPCHL ; call LOGIN POP HL ; recover DPH pointer ld SP,(loc$stk) ;restore stack NOT$FIRST$SELECT: RET ; HOME ; Home selected drive. Treated as SETTRK(0). HOME:: LD BC,0 ; same as set track zero ; SETTRK ; Set Track. Saves track address from ; in @TRK for further operations. SETTRK:: LD (@TRK),BC RET ; SETSEC ; Set Sector. Saves sector number from ; in @sect for further on ',0 TRACK$MSG: DB ': T-',0 SECTOR$MSG: DB ', S-',0 ; disk communication data items @ADRV: DS 1 ; currently selected disk drive @RDRV: DS 1 ; controller relative disk drive @TRK: DS 2 ; current track number @SECT: DS 2 ; current sector number @DMA: DS 2 ; current DMA address @CNT: DB 0 ; record count for multisector transfer @DBNK: DB 0 @ermde:: db 0 ; fake BDOS error mode endaddr:: END ave address of table LD DE,-10 ADD HL,DE ; point to write routine address RW$COMMON: LD A,(HL) INC HL LD H,(HL) LD L,A ; get address of routine POP DE ; recover address of table DEC DE DEC DE ; point to relative drive LD A,(DE) LD (@RDRV),A ; get relative drive code and post it INC DE INC DE ; point to DPH again call IPCHL ; leap to driver ld SP,(loc$stk) ;restore stack pointer ret ; error message components DRIVE$MSG: DB CR,LF,BELL,'BIOS Error operations. SETSEC:: LD (@SECT),BC RET ; SETDMA ; Set Disk Memory Address. Saves DMA address ; from in @DMA and sets @DBNK to @CBNK ; so that further disk operations take place ; in current bank. SETDMA:: LD (@DMA),BC ret ; SECTRN ; Sector Translate. Indexes skew table in ; with sector in . Returns physical sector ; in . If no skew table (=0) then ; returns physical=logical. SECTRN:: LD L,C LD H,B LD A,D OR E RET Z EX DE,HL ADD HL,BC LD L,(HL) LD H,0 RET ; READ ; Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter header (XDPH). READ: ld (loc$stk),SP ;set up local stack ld SP,loc$stk LD HL,(@ADRV) LD H,0 ADD HL,HL ; get drive code and double it LD DE,@DTBL ADD HL,DE ; make address of table entry LD A,(HL) INC HL LD H,(HL) LD L,A ; fetch table entry PUSH HL ; save address of table LD DE,-8 AD, TITLE HDC-1001 HARD DISK FORMATTER .z80 ;------------------- ; CHARACTER EQUATES ;------------------- CR EQU 00DH ; Carriage return LF EQU 00AH ; Line feed BS EQU 008H ; Back space ;--------------------- ; BDOS FUNCTION CALLS ;--------------------- BDOS EQU 005H ; BDOS entry point PRTSTR EQU 009H ; Print string CONIN EQU 001H ; Console input CONOUT EQU 002H ; Console output RDBUF EQU 00AH ; Read console buffer CONST EQU 00BH ; Console status ;---------------------------------- ; HDC-1001 REGISTER PORT ADDRESSES ;---------------------------------- HDBASE EQU 0e0H ; HDC1001 base I/O port DATA EQU HDBASE+0 ; Data register ERROR EQU HDBASE+1 ; Error register PRECOMP EQU HDBASE+1 ; Write pre-compensation register SECNT EQU HDBASE+2 ; Sector count register SECNO EQU HDBASE+3 ; Sector number register CYLLO EQU HDBASE+4 ; Cylinder low register CYLHI EQU HDBASE+5 ; Cylinder high register SDH EQU HDBASE+6 ; Size/Drive/Head register COMND EQU HDBA- ; CHECK IF CARTRIAGE DRIVE ;-------------------------- push hl ; save drive menu no. ld a,014h ; drive no. 20 is a cartriage drive cp l ; check if drive selection is 20 jp nz,getpar ; if not then jump out cart: ld de,carmsg ; if here then cart drv selected ld c,prtstr ; ask if format cart only call bdos ; send if to console ld c,conin ; get responce to format cart only call bdos ; from console and 0dfh ; convert reply to uppercase cp 'N' ; check if negative response jp z,getpar ; jump out if format entire drive cp 'Y' ; check if positive reply jp nz,cart ; ask question again if neither ld a,001h ; if here, format only cart ld (carmsk),a ; cart is hds 2,3 set msk hd 1 check ;---------------------- ; GET DRIVE PARAMETERS ;---------------------- getpar: pop hl ; restore drive menu no. ld d,h ; save it in de ld e,l ; mult *6 to index into drv par tbl add hl,hl ; *2 add hl,de ; *3 add hl,hl ; *6 ld de,dskble 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,0ffh 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 ;--------------------- ;SE+7 ; Command register STATUS EQU COMND ; Status register ;------------------- ; HDC-1001 COMMANDS ;------------------- CREST EQU 10H ; Restore heads CREAD EQU 20H ; Read sector CWRITE EQU 30H ; Write sector CFORM EQU 50H ; Format track PAGE ASEG ORG 0100H ;------------------ ; START OF PROGRAM ;------------------ start: ld de,signon ; send signon message ld c,prtstr ; display message at console call bdos ; getdrv: ld de,inbuf ; get response to disk type ld c,rdbuf ; input line of characters from console call bdos ; put response in inbuf ld a,(numchr) ; check no. of chars ret 1 or 2 cp 0 ; check for zero chars returned jr z,bad ; if zero jump to invalid response cp 3 ; check for three chars returned jr c,good ; if not then chars ret is 1 or 2 bad: ld de,inval ; display invalid response ld c,prtstr ; send message to console call bdos ; ld de,menu ; display drive menu again ld c,prtstr ; send it to consolprms ; add in base addr of drv par tbl add hl,de ; hl now pnts to correct entry ld de,secs ; now move parms to prog use locs ld bc,6 ; 6 bytes in dskpar tlb entry ldir ;------------------------ ; GET PHYSICAL DRIVE NO. ; ----------------------- drvin: ld de,drvmsg ; ask which phy drv to format ld c,prtstr ; send msg to console call bdos ld c,conin ; get response from console call bdos ; sub '0' ; convert ascii to binary cp 004h ; check if < 4 jr c,goodr ; jmp if reply ok ld de,inval ; otherwise invalid response ld c,prtstr ; send bad reply message call bdos ; send it to the console jr drvin ; try again goodr: ld (unit),a ;save drive ;------------- ; QUIT FORMAT ;------------- ld de,q1 ; msg states this will destroy all data ld c,prtstr ; on drive call bdos ; ld a,(unit) ; display drive no. selected call outchr ; covert to ascii, then send to console ld de,q2 ; display prompt asking if to procede  RESTORE DRIVE HEADS ;--------------------- ld a,(sizmsk) ; set up sdh register first ld b,a ; get sdh register sector size mask ld a,(unit) ; get drive no rlca ; rotate it to its proper position rlca ; for sdh register this is bits 3,4 rlca ; or b ; or in sector size ld (unit),a ; save it for future refrence out (sdh),a ; send it to sdh register ld a,(stprte) ; get step rate ld b,a ; save it in b ld a,crest ; load a with a restore command or b ; or in step rate out (comnd),a ; send command to controller rswait: in a,(status) ; wait until controller done w. restore and a ; check busy bit, bit 8 jp m,rswait ; loop until not busy ;-------------- ; FORMAT DRIVE ;-------------- ld hl,(cyls) ; get last cylinder push hl ; save it as current cylinder headlp: call cylprt e call bdos ; jr getdrv ; jump to recieve response ;------------------------- ; CONVERT ASCII TO BINARY ;------------------------- good: ld de,inttbl ; set up registers ld hl,0 ; inttbl contains user responce declp: push af ; sav char cnt (no of chars to convert) ld a,(de) ; get a char inc de ; point to next char to fetch cp '0' ; check to make sure char is numeric jp c,bad ; jmp to invalid responce if < 0 cp '9'+1 ; check for > 9 jp nc,bad ; if char > 9 then invalid responce sub '0' ; convert from ascii to binary ld b,h ; mult present value * 10 ld c,l ; save it first in bc 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 ; save it in hl jp nz,dignc ; check for l reg overflow inc h ; if overflow then inc h dignc: pop af ; return char count to a reg dec a ; decrement char cnt jp nz,declp ; check if done with conversion ;-------------------------ld c,prtstr ; call bdos ; ld c,conin ; get response call bdos ; cp cr ; if carriage return input then jp z,doit ; format drive abort: ld de,abtmsg ; user changed their mind ld c,prtstr ; display no format performed msg call bdos ; jp resel ; return to cpm doit: ld de,formsg ; display formatting drv msg ld c,prtstr ; call bdos ; ;---------------------------- ; CALCULATE INTERLEAVE TABLE ;---------------------------- ld B,040h ; make tbl max size, using 1 byt/sec ld hl,inttbl ; point to interleave table setlp: ld (hl),0ffh ; set all cells in tbl to 0ffh inc hl ; point to next cell dec b ; decrement tbl count jp nz,setlp ; loop unti finished with initalization ; 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 ta- ; print current cylinder ld a,(heads) ; get last head ld d,a ; save it in d ld a,0ah ; initalize retry count ld (retry),a ; ten retrys per format track forlp: push de ; save current head no. ld a,d ; display head that we are on call outchr ld e,bs ; backspace to begining of head info ld c,conout ; send bs to console call bdos ; pop de ; restore current head no. ld a,(secs) ; get sector count out (secnt),a ; send it to sector count register pop hl ; restore current cyl no. push hl ; save current cyl no. ld a,l ; put cyl low in a out (cyllo),a ; send it to cylinder low register ld a,h ; put cyl high in a out (cylhi),a ; send it cylinder high register ld a,(unit) ; get sector size, and unit no. or d ; or in heads out (sdh),a ; send it to sdh register ld a,cform ; issue format command out (comnd),a ; send it to command register dwait: in a,(status) ; wait for data request and 008H ; by checking data d a,(secs) ; get sector count dec a ; decrement sector so numbered from 0 ld d,a ; save it in d rhead: call cylprt ; print current cylinder no ld c,e ; Reload head rsecs: push hl ; save current cylinder push de ; save head and sector count push bc ; save current head and sector no. ld a,c ; Output head that we are on call outchr ld e,bs ld c,conout call bdos pop bc ; restore cur hd and sec pop de ; restore hd and sec cnt pop hl ; restore cur cylinder ld b,d ; reload cur sector w. sec cnt readit: ld a,b ; load current sector no. out (secno),a ; send it to sector no. register ld a,l ; load current cylinder low out (cyllo),a ; send to cylinder low reg ld a,h ; load current cylinder high out (cylhi),a ; send to cylinder high reg ld a,(unit) ; load sector size and phy drive or c ; OR in current head no out (sdh),a ; send to sdh reg ld a,cread ; load a read command out (comnd),a ; send to command regf -1 and a ; look at bit 7 in h jp p,rhead ; jump to reset heads ld de,dnemsg ; display formating complete ld c,prtstr ; call bdos ; jp resel ; Reselect original drive ;------------ ; EXIT CHECK ;------------ xitck: push hl ; save regs push de push bc ld c,const ; get console status call bdos ; bdos call 0bh and a ; bdos returns 0 if no char pending jr z,skp ; skip if no char else bdos ret a 0ffh ld c,conin ; get char typed call bdos ; cp 3 ; check for control c jp z,abort ; if so restart sys skp: pop bc ; restore registers pop de ; pop hl ; ret ;---------------------------------- ; PRINT HEXADECMIAL VALUE OF A-REG ;----------------------------------- hexout: push af ; save a-reg rrca ; rotate 4 most significant bits rrca ; 2 rrca ; 3 rrca ; 4 call outchr ; Print upper digit pop af ; restore value to display outchr: and 00fh ; mask least significant four bits req bit, bit 2 jr z,dwait ; loop until data requested ;------------------------- ; SET UP FOR FORMAT TRACK ;------------------------- ld hl,inttbl ; point to interleave table siz512: ld b,0 ; set up b-reg to contain (secsiz / 2) ld a,(sizmsk) ; check if 512 byte sectors cp 020h ; sdh reg settin =020h if 512 bps jr z,sizok ; jump over 256 bps setting siz256: ld b,080H ; else set up for 256 bps sizok: ld a,data ; because we snd 2 byts per iteration ld c,a ; data register port goes in c xor a ; set up bad block byte ;----------------------------------------- ; SEND FORMAT DATA TO HDC-1001 CONTROLLER ;----------------------------------------- datalp: out (c),a ; send bad block byte to controller outi ; send interleave tbl byte to cont jr nz,datalp ; loop untill sector size transfered fwait: in a,(status) ; wait until done with format cmd and a ; by checking busy bit, bit 8 jp m,fwait ; loop until controller not busy rra  rwait: in a,(status) ; wait for controller to read sec and 040H ; check ready bit, bit 6 jp z,rwait ; loop until controller ready in a,(status) ; check for errors during read rra ; error bit, bit 0 jp nc,noerr ; jump over if no errors ;---------------------- ; PRINT ERROR MESSAGES ;---------------------- push hl ; save current cylinder push de ; save sector and head count push bc ; save save current sector and head ld de,errst ; send start of error message ld c,prtstr ; call bdos ; in a,(error) ; read error register call hexout ; display contents in hex ld de,errhd ; point to head literal ld c,prtstr ; display on console call bdos ; in a,(sdh) ; read sdh register and 7 ; mask for current head no call outchr ; display single digit ld de,errcyl ; point to cylinder literal ld c,prtstr ; display on console call bdos ; display 'cylinder' in a,(cylhi) ; get cylinder high value call hexout ; display i add a,'0' ; add in ascii offset cp '9'+1 ; check if > 10 jp m,sndchr ; if no the char ok add a,07h ; else add in offset to make a-f sndchr: ld e,a ; store result in e for bdos ld c,conout ; send it to console call bdos ; ret ;--------------------------- ; PRINT CYLINDER ON CONSOLE ;--------------------------- cylprt: push de ; save registers push bc ; push hl ; ld de,bsmsg ; back up to start of cyl column ld c,prtstr ; call bdos ; pop hl ; get cylinder from stack push hl ; put it back ld a,h ; display cylinder high call hexout ; in hex pop hl ; get current cylinder from stack push hl ; put it back on stack ld a,l ; display cylinder low call hexout ; ld de,hdmsg ; display head msg ld c,prtstr ; call bdos ; pop HL ;restore regs pop bc pop de ret ;---------------------- ; PRINT ERROR MESSAGES ;---------------------- herror: in a,(status) ; read status register and 020h ; ch ; check error bit, bit 0 set jp nc,fmtok ; jmp over retry if no error ld a,(retry) ; get format retry count dec a ; decrement count ld (retry),a ; save new retry count jp m,herror ; jmp if pased limit jp forlp ; else retry format fmtok: call xitck ; check it control c has been typed dec d ; bump head counter ld a,(carmsk) ; load head mask for cartriage xor d ; mask for sameness jp nz,forlp ; passed head 0 or 2, depends on msk pop hl ; restore current cylinder dec hl ; bump cylinder count ld a,h ; have we passed cyl 0 yet and a ; if = -1, then bit 7 in h set push hl ; save current cylinder jp p,headlp ; jmp to format new cyl, reset hd cnt pop hl ; clear stack ;------------------------ ; VERIFY DRIVE TRACK IDS ;------------------------ ld de,vermsg ; display verifying drive msg ld c,prtstr ; send to console call bdos ; ld hl,(cyls) ; get cylinder count ld a,(heads) ; get head count ld e,a ; save it in e lt in hex in a,(cyllo) ; get cylinder low value call hexout ; display it in hex ld de,errsec ; point to sector literal ld c,prtstr ; display on cosole call bdos ; display 'sector' in a,(secno) ; read current sector no call hexout ; display value in hex ld de,vermsg1 ; send lf to console ld c,prtstr ; call bdos ; call cylprt ; display cyl head sec again for fmt lp pop bc ; restore current sec and hd pop de ; restore sec and head cnt pop hl ; restore cyl cnt ;---------------------------------------- ; DECREMENT SECTOR, HEAD AND/OR CYLINDER ;---------------------------------------- noerr: call xitck ; check if control c typed dec b ; decrement current sector number jp p,readit ; jump to read next sector dec c ; decrement current head no ld a,(carmsk) ; load cartriage mask xor c ; chk if past hds 0 v 2, depends on msk jp nz,rsecs ; jump to reset sectors dec hl ; decrement cylinder number ld a,h ; check i-eck for write fault first jr z,ckereg ; jump if no write fault error ld de,wrtflt ; address of write fault error msg ld c,prtstr ; function to print string on con call bdos ; do it ckereg: in a,(error) ; read error register ld hl,errmsg ; base address of messages ld de,019h ; message length ld b,008h ; number of possible errors tstbit: rra ; rotate a bit into carry jr nc,nxbit ; jump if bit not set (no error) push hl ; if here then error bit set push de ; print error via bdos push bc ; bdos clobbers registers push af ; save current state ex de,hl ; hl has curren error bit msg addr ld c,prtstr ; print string function call bdos ; print error message on console pop af ; restore registers pop bc ; pop de ; pop hl ; nxbit: add hl,de ; make hl point to next error message dec b ; decrement error bit counter jr nz,tstbit ; jump to test next error bit resel: jp 0 ;-------------- ; DATA STORAGE ;--------------  DB 6 ; step rate SA1002: ; 12. DB 16 ; sectors DW 255 ; cylinders-1 DB 1 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate SA1004: ; 13. DB 16 ; sectors DW 255 ; cylinders-1 DB 3 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate Q2010: ; 14. DB 16 ; sectors DW 511 ; cylinders-1 DB 1 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate Q2020: ; 15. DB 16 ; sectors DW 511 ; cylinders-1 DB 3 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate Q2030: ; 16. DB 16 ; sectors DW 511 ; cylinders-1 DB 5 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate Q2040: ; 17. DB 16 ; sectors DW 511 ; cylinders-1 DB 7 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate M2010: ; 18. DB 16 ; sectors DW 479 ; cylinders-1 DB 1 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate M2020: ; 19. DB 16 ; sectors DW 479 ; cylinders- ; 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 EAD $' 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 ;----------- RETRY: DB 0 ; Retry count CARMSK: DB 0ffh ; Cartriage head mask 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 SIZMSK: DS 1 ; Sector size mask STPRTE: DS 1 ; Step rate INTER D 1 bi interleave NSECS: DS 2 ERRMSG: DB cr,lf,'DAM Not Found Error ','$' DB cr,lf,'TR000 Error ','$' DB cr,lf,'Aborted Command Error ','$' DB cr,lf,'Undefined Error ','$' DB cr,lf,'ID Not Found Error ','$' DB cr,lf,'CRC Id Error ','$' DB cr,lf,'Uncorrectable Error ','$' DB cr,lf,'Bad Block Detect Error','$' WRTFLT: DB cr,lf,'Write Fault Error ','$' ;---------------------- ; DISK PARAMETER TABLE ;---------------------- DSKPRMS: ST503: ; 0. DB 16 ; sectors DW 152 ; cylinders-1 DB 1 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate ST506: ; 1. DB 16 ; sectors DW 152 ; cylinders-1 DB 3 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate TM601s: ; 2. DB 16 ; sectors DW 152 ; cylinders-1 DB 1 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate TM602s: ; 3. DB 16 ; sectors DW 152 ; cylinders-1 DB 3 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate TM603s: ; 4. DB1 DB 3 ; heads-1 DB 020h ; sector size mask DB 0 ; step rate DMA5_5: ; 20. DB 33 ; sectors DW 319 ; cylinders-1 DB 3 ; heads-1 DB 000h ; sector size mask DB 00fh ; step rate (for this drv =0 dma prom, =f wd prom) ;---------- ; MESSAGES ;---------- SIGNON: DB 'FMTHD 2.2',CR,LF,LF MENU: DB '0 = ST503 11 = SA606', CR,LF DB '1 = ST506 12 = SA1002', CR,LF DB '2 = TM601S 13 = SA1004', CR,LF DB '3 = TM602S 14 = Q2010', CR,LF DB '4 = TM603S 15 = Q2020', CR,LF DB '5 = TM603SE 16 = Q2030', CR,LF DB '6 = TM501 or ST406 17 = Q2040', CR,LF DB '7 = TM502 or ST412 18 = M4010', CR,LF DB '8 = TM503 or ST419 19 = M4020', CR,LF DB '9 = SA602 20 = DMA 5/5',CR,LF DB '10 = SA604',CR,LF,LF DB 'Enter drive to format: $' CARMSG: DB CR,LF,'Do you want to format cartriage only [Y or N]?$' INVAL: DB CR,LF,'Invalid input try again.',CR,LF,'$' D 16 ; sectors DW 152 ; cylinders-1 DB 5 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate TM603se: ; 5. DB 16 ; sectors DW 229 ; cylinders-1 DB 5 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate TM501: ; 6. DB 16 ; sectors DW 305 ; cylinders-1 DB 1 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate TM502: ; 7. DB 16 ; sectors DW 305 ; cylinders-1 DB 3 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate TM503: ; 8. DB 16 ; sectors DW 305 ; cylinders-1 DB 5 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate SA602: ; 9. DB 16 ; sectors DW 159 ; cylinders-1 DB 1 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate SA604: ; 10. DB 16 ; sectors DW 159 ; cylinders-1 DB 3 ; heads-1 DB 020h ; sector size mask DB 6 ; step rate SA606: ; 11. DB 16 ; sectors DW 159 ; cylinders-1 DB 5 ; heads-1 DB 020h ; sector size maskRVMSG: 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 ;----------- RETRY: DB 0 ; Retry count CARMSK: DB 0ffh ; Cartriage head mask 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 SIZMSK: DS 1 ; Sector size mask STPRTE: DS 1 ; Step rate INTER D 1 bi interleave NSECS: DS 2. .Z80 ; ; FORMAT VERSION 3.1 ; ; FORMAT PROGRAM FOR THE WD 1793 & WD 2793 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 TRUE ; 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  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 CODEIDE 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 LEINCHTRKS 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 USE 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 WITD 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) R 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,LLLH 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 S. 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 ;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 ;Wmatted (0-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$'  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 (RERITE 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 018h ;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: 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 ARADSECS),A NEXTSECTOR: XOR A ;RESET RETRY 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 ;  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: IF NOT MINI DB 'FMT8 3.1' ENDIF IF MINI IF FORTY8 DB 'FMT548 3.1' ELSE DB 'FMT596 3.1' ENDIF ENDIF DB CR,LF,'$' MSG4: DB CR,LF,'Enter Disk Drive To Be For/E 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  ;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) irectory 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 lanc 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 ast 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 (I .z80 bdossecs equ 44 ;sectors to read on warm boot 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 1 ;number of choices to choose from nmbcpm equ 1 ;number of cp/m choices turbo equ true ;true for turbodos or CP/M 3.0 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 lways 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 di/X+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 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 ; .z80 include SUPERBIOS.LIB rtrys equ 010d ;---------------------------------- ; HDC-1001 REGISTER PORT ADDRESSES ; --------------------------------- hbase equ 0e0h ; base port address of hdc-1001 hdata equ hbase+0 ; data register herror equ hbase+1 ; error register hwrtpre equ hbase+1 ; write pre-compensation register hseccnt equ hbase+2 ; sector count register hsec equ hbase+3 ; sector number register hcyllow equ hbase+4 ; cylinder low register hcylhi equ hbase+5 ; cylinder high register hsdh equ hbase+6 ; size - drive - head register hstatus equ hbase+7 ; status register port hcmd equ hbase+7 ; command register port ;------------------- ; HDC-1001 COMMANDS ;------------------- cmdrst equ 010h ; restore command cmdrd equ 020h ; read sector command ;----------------------------- ; STATUS REGISTER BIT TESTERS ;----------------------------- bsybit equ 080h ; busy bit rdybit equ 040h ; data request bit errbit equ 001h ; error bit  ;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  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: db 0 ;block shift factor = log2(records/block) BLM: db 0 ;block mask = records/block-1 blkmsb: db 0 ;non-zero is >255 blocks on drive ;=msb of DSM in DPB blksec: dw 0 ;sectors per block (BLM+1) dirbuf: dw 0 ;address of DIRBUF trans: db 0 ;0 if no sector translation XLT: dw 0 ;translate table address SPT: dw 0 ;sector per track count maxdir: dw 0 ;number of directory entries on disk trkoff: d;------------------ ; BIOS JUMP VECTOR ;------------------ start: jp boot jp wboot jp const jp conin jp conout jp list jp punch jp reader jp hhome jp hseldsk jp hsettrk jp hsetsec jp setdma jp hread jp hwrite jp listst jp sectran ;----------- ; COLD BOOT ;----------- boot: ret ;----------- ; WARM BOOT ;----------- wboot: ret ;------------- ; LIST OUTPUT ;------------- list: ret ;-------------- ; PUNCH OUTPUT ;-------------- punch: ret ;--------------- ; READER OUTPUT ;--------------- reader: ret ;------------- ; LIST STATUS ;------------- listst: ret ;---------------- ; CONSOLE STATUS ;---------------- const: ;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 ;--------------- ; CONSOLE INPUT ;--------------- conin: ld B,A call const ld A,B jr z,conin ;loop until character  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 w 0 ;track offset curtrk: dw 0 ;current track cursec: dw 0 absec: dw 0 ;absolute sector typeld: db 0 ;load type 0=cp/m, 1=turbodos nextsc: dw 0 ;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,0 end ock) BLM: db 0 ;block mask = records/block-1 blkmsb: db 0 ;non-zero is >255 blocks on drive ;=msb of DSM in DPB blksec: dw 0 ;sectors per block (BLM+1) dirbuf: dw 0 ;address of DIRBUF trans: db 0 ;0 if no sector translation XLT: dw 0 ;translate table address SPT: dw 0 ;sector per track count maxdir: dw 0 ;number of directory entries on disk trkoff: d0received add A,A ld C,A in A,(C) and 7fh ;mask high order bit ret ;---------------- ; CONSOLE OUTPUT ;---------------- conout:: 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 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 xor A jp conout ;------------------ ; SET DMA ADDRESS ;----------------- setdma: ld (dmaadr),bc ; shared among all drivers ret ;-------------------- ; SECTOR TRANSLATION ;-------------------- sectran: ld h,b ld l,c ret ;------------- ; SELECT DISK ;------------- hseldsk: ld hl,ddb0 ; get deblocking parameters ld de,dbconst ; move dblk pars to usage area ld bc,13d f 7) ld hl,hstbuf ; base addr of hst buf add hl,de ; add in offset ld (dadr),hl ; save it as deblocked buf addr ld a,(blkshf) ; convert seksec to blk no. ld de,(seksec) ; blkshf = log2 cpm spb, what we are call shfr16 ; doing is, bl=int(sesc/cpmspb) ld (dblk),de ; save as blk no. on this trk ld a,(hstspb_1) ; convert seksec to hst sec no. in blk ld de,(dsec) ; must use sec just deblocked and e ; and deblk sec w. hst spb ld (dblsec),a ; save it as deblocked block sec ret ;---------------------------- ; CHECK IF NEW SEC IS IN BUF ;---------------------------- inbuf: ld a,(seklrv) ; check if new drv = old drv ld hl,hstlrv ; first check if log drives are same cp (hl) ; compare w. last accessed drv jp nz,difblk ; if drvs are dif, then so is blk ld de,(sektrk) ; check if new trk = old trk ld hl,(hsttrk) ; this is the old trk call cmp16 ; so far drv same jp nz,difblk ; if trks are dif, then so is blk ld a,(dhd) ; check if new h ; transfer 128 bytes ld de,(dmaadr) ; load cpm addr (dma addr storage) ld hl,(hstadr) ; load buf addr ld a,(oper) ; check if read or write operation or a ; oper =0 if read, =1 if write jp nz,transf ; jump if read ex de,hl ; read operation so switch directions transf: ldir ; send 128 byte block ret ;-------------------------------- ; SET OR RESET BLOCK USAGE FLAGS ;-------------------------------- rsetusg: ld b,0 ; set all block sectors in blk to free jp setblk ; sec in blk not allocated if =0 setusg: ld b,0ffh ; set all block sectors in blk to used setblk: ld a,(hstspb_1) ; get no of host sector per block ld hl,usgblk ; get addr of blk sector usage vector setflg: ld (hl),b ; set or reset block usage flag inc hl ; point to next flag loc dec a ; dec count of block sectors to go jp p,setflg ; loop if more to set ret ;------------------------------ ; UPDATE BLOCK USAGE VARIABLES ;------------------------------ update: l; 13 bytes of dblk pars ldir ; move as block ld hl,dph0 ; ret w. dsk parameter hder in hl ret ;------ ; HOME ;------ hhome: call restore ; restore drive heads to trk 0 ret ;----------- ; SET TRACK ;----------- hsettrk: ld (sektrk),bc ; bc contains selected track n. ret ;------------ ; SET SECTOR ;------------ hsetsec: ld (seksec),bc ; bc contains selected sector no. ret ;------------- ; READ SECTOR ;------------- hread: xor a ; clear accumulator ld (rtcnt),a ; reset retry count ld a,1 ; set operation to read ld (oper),a ; save it for when we do xfer call deblk ; deblock phy sec, buf adr, and blk sec call inbuf ; check if new sector is in buf call xfer ; transfer data out of buf into dma ld a,(rtcnt) ; if rtcnt not zero then error ret ;-------------- ; WRITE SECTOR ;-------------- hwrite: ret ;------------------------------------ ; DEBLOCK PHY SEC, BUF ADDR, BLK SEC ;------------------------------ead = old head ld hl,hsthd ; so far drv, trk same cp (hl) ; if dif hd, could be jp nz,ckblk ; same blk if blk size > phy trk siz ld a,(dsec) ; check if new sec = old sec ld hl,hstsec ; this is the old sec cp (hl) ; so far drv, trk, hd same jp nz,ckblk ; could be same blk even if dif sec call sethst ; everything same, set buf addr though ret ckblk: ld hl,(dblk) ; check if new sec is in same blk ld de,(hstblk) ; if the new blk equal old blk call cmp16 ; then do not reset usage vars jp nz,difblk ; regardless fall through to prerd samblk: call hflush ; sam blk, but dif blk sec so flush old ld hl,usgblk ; check if this sec free in block ld de,(dblsec) ; look in block usage vector ld d,0 ; index down to correct entry in vector add hl,de ; hl now contains addr of blk usg entry ld b,(hl) ; get blk usage flag ld a,(oper) ; get oper or b ; if (sec not fre) or (oper is read) jp nz,prerd ; then need to pre-read sector nprerd: d de,(blksec) ; we have just written to a sec in blk ld d,0 ; so set block sec usage flag to used ld hl,usgblk ; first point to flag add hl,de ; de contains sector no. in block ld a,0ffh ; 0ff means sector in block is not free ld (hl),a ; set flag ret ;------------ ; WRITE HOST ;------------ hwrthst: ret ;----------- ; READ HOST ;----------- hrdhst: call settsk ; first set up controller registers ld a,cmdrd ; load a with command to read sector out (hcmd),a ; send read command to command reg call polbsy ; wait until not busy call rxdta ; transfer data from cnt buf to hst buf call retrys ; check for errors jp nz,hrdhst ; retrys sets zero flg if no errors ret ;--------------- ; SET TASK FILE ;--------------- settsk: ld a,(hstprv) ; get physical drive no. ld b,a ; save in b so can use a for mem fetch sla b ; rotate phy drive to correct position sla b ; drive is expected in bits 3 and 4 sla b ; last shift for driv------ deblk: ld a,(pdrv) ; get phy drv from dsk deblk parameters ld (sekprv),a ; save it as sek phy drv ld a,(secshf) ; convert sek sec to phy sec ld de,(seksec) ; secshf is log2 cpm sps call shfr16 ; shift de-reg, a-reg times ld a,(hstspt_1) ; de now contains sec rel to cyl and e ; mask for sec rel to platter ld (dsec),a ; save it as deblocked sector ld a,(hdshf) ; convert seksec to phy head ld de,(seksec) ; hdshf is log2 cpm spt call shfr16 ; hd no is high bits, so no msk needed ld a,(hdoff) ; add in head off set for partioning add a,e ; cartriage drv must be part. by hds ld (dhd),a ; save it as deblocked head no. l a,(cpmsps_1 conver sekse t hs bu no. ld de,(seksec) ; mask out low order bits of sec no and e ; since buf no <= 8, need only lsb ld e,a ; mul buf no x128 to get rel adr in buf ld d,0 ; zero out high order of multiplicitan ld a,7 ; convert hst buf no. to hst buf adr call shfl16 ; mult by 128 (shift lcall sethst ; sector not allocated ret difblk: call hflush call setusg ; sector not in block prerd: call sethst ; sector in blk but alloc, or dif blk call hrdhst ; read in new setor ret ;------------------- ; FLUSH HOST BUFFER ;------------------- hflush: ld a,(wrtpnd) ; check if host buffer active and a ; wrtpnd =0 if inactive, =0ff if active call nz,hwrthst ; physicaly flush buffer if active xor a ; clear write pending ld (wrtpnd),a ; host buffer now in active ret ;--------------------------------- ; SET DEBLOCKED VARS TO HOST VARS ;--------------------------------- sethst: ld hl,sekvars+2 ; blk move sek & dblk vars to hst vars ld de,hstvars ; dont need seksec so sekvars+2 ld bc,14d ; this is how many to move ldir ; set host variables ret ;-------------------------------------- ; TRANSFER DATA TO/FROM BUFFER AND DMA ;-------------------------------------- xfer: ld bc,080h 0e ld a,(hstsdh) ; get sdh sect size setting or b ; or it in w. rotated phy drive no ld b,a ; save result in b ld a,(hsthd) ; get host head no. or b ; or it in w. drv and sec siz out (hsdh),a ; send it siz drv hd register ld bc,(hsttrk) ; host track is really host cylinder ld a,b ; move msb to a-reg for out inst out (hcylhi),a ; send high byte to cylhi reg ld a,c ; move lsb to a-reg out (hcyllow),a ; send to cyl low ld a,(hstsec) ; get host sector no out (hsec),a ; send to sector register ret ;----------- ; SEND DATA ;----------- snddta: ret ;-------------- ; RECIEVE DATA ;-------------- rxdta: ld a,(hstsiz) ; this is how many bytes to move ld b,a ; set up for inir ld c,hdata ; this is where the data comes from ld hl,hstbuf ; this is where the data goes inir ; block move data into hst buf ld a,(hstsiz+1) ; check if moving 512 bytes and 2 ; msb would be 2 if 512 bytes jp z,rxout ; jump over if moveing 12 ld a,d ; compare d-reg w. h-reg xor h ; set zero flag if same ret ;------------------------------------------------ ; DATA STORAGE ;------------------------------------------------ dmaadr: dw 0080h ; dma address storage rtcnt: db 0 ; retry counter smapadr: dw 0 ; seek drive map entry address sekvars: ; seek variables seksec: dw 0 ; seek sector seklrv: db 0 ; seek logical drive sekprv: db 0 ; seek physical drive sektrk: dw 0 ; seek track dhd: db 0 ; deblocked head dsec: db 0 ; deblocked sector dadr: dw 0 ; deblocked buffer address dblk: dw 0 ; deblocked block no. in cylinder dblsec: db 0 ; deblocked host sector no. in block dbconst: ; deblocking constants (calc in ddp) secsiz: dw 0 ; host sector size sdhsiz: db 0 ; shd reg sector siz pdrv: db 0 ; physical drive hdoff: db 0 ; head offset stprte: db 0 ; cmd reg step rate hstspt_1: db 0 ; host sector per track hstspb_1: db 0 ; host sectors per block hds title TRACK 0 LOADER -- WD 1793, 2793; HDC-1001 .z80 vers equ 24 ; ldrgen version no. to be displayed false equ 0 true equ not false ;------------------------- ; HDC-1001 PORT ADDRESSES ;------------------------- hbase equ 0e0h ; base port address of hdc-1001 hdata equ hbase+0 ; data register herror equ hbase+1 ; error register hwrtpre equ hbase+1 ; write pre-compensation register hseccnt equ hbase+2 ; sector count register hsec equ hbase+3 ; sector number register hcyllow equ hbase+4 ; cylinder low register hcylhi equ hbase+5 ; cylinder high register hsdh equ hbase+6 ; size - drive - head register hstatus equ hbase+7 ; status register hcmd equ hbase+7 ; command register ;------------------- ; HDC-1001 COMMANDS ;------------------- cmdrst1 equ 01eh cmdrst2 equ 01fh cmdrd equ 020h ; read sector command cmdwrt equ 030h ; write sector command ;----------------------------- ; STATUS REGISTER BIT TESTERS ;-----------------------8 or 256 only inir ; b should be zero, hl and c set also rxout: ret ;-------------------------------- ; RESTORE DRIVE HEADS TO TRK 000 ;-------------------------------- restore: ld a,(stprte) ; set step rate when doing a restore ld b,cmdrst ; get a restore command or b ; or in step rate out (hcmd),a ; send it to the command register call polbsy ; wait until not busy ret ;----------- ; POLL BUSY ;----------- polbsy: in a,(hstatus) ; read status port and a ; set flags jp m,polbsy ; loop if busy bit set and errbit ; mask for error bit ret ;--------------------- ; SET RETRY CONDITION ;--------------------- retrys: in a,(hstatus) ; read status register and errbit ; mask for error bit jp z,rtout ; jump to exit rtry ld a,(rtcnt) ; get no. of retrys so far inc a ; increment retry count ld (rtcnt),a ; save it for next time cp rtrys ; set not z flg, unless rtcnt = rtrys ret ; return w. flag set or reset rtout: hf: db 0 ; log2 cpm spt blkshf: db 0 ; log2 cpm spb hdmsk: db 0 ; heads - 1 secshf: db 0 ; log2 cpm sps cpmsps_1: db 0 ; cpm sps - 1 hstvars: ; host drive variables hstlrv: db 0 ; last logical drive operated on hstprv: db 0 ; physical drive hsttrk: dw 0 ; track (equiv to cylinder) hsthd: db 0 ; head hstsec: db 0 ; sector hstadr: dw 0 ; buffer address hstblk: dw 0 ; block no. in current cylinder blksec: db 0 ; host sector no. in block hstsiz: dw 0 ; physical sector size hstsdh: db 0 ; sdh register sector size setting wrtpnd: db 0 ; write pending (host buffer active) wrttyp: db 0 ; write type (0=use, 1=dir, 2=free) oper: db 0 ; operation (0=write, 1=read) ;------------------------------------------------------------------------------ ; DRIVE PARAMETER DEFINITIONS ;------------------------------------------------------------------------------ ; ; dskdef < drvtyp0, drvtyp1, ... , drvt------ bsybit equ 080h ; busy bit rdybit equ 040h ; data request bit errbit equ 001h ; error bit ;----------------------------- ; FLOPPY CONTROLLER REGISTERS ;----------------------------- fbase equ 0ch fcmd equ fbase+0 fstat equ fbase+0 ftrk equ fbase+1 fsec equ fbase+2 fdata equ fbase+3 fwait equ 014h fdsd equ 014h SECSIZ EQU 128 ;SIZE OF EACH SECTOR LOG2SEC EQU 7 ;LOG 2 SECSIZ FCB EQU 005CH ;DEFAULT FCB LOCATION FCBCR EQU FCB+32 ;CURRENT RECORD LOCATION TPA EQU 0100H ;TRANSIENT PROGRAM AREA LOADP EQU 900H ;LOAD POINT FOR SYSTEM DURING LOAD/STORE BDOS EQU 5H ;DOS ENTRY POINT BOOT EQU 0 ;JMP TO 'BOOT' TO REBOOT SYSTEM CONI EQU 1 ;CONSOLE INPUT FUNCTION CONO EQU 2 ;CONSOLE OUTPUT FUNCTION SELF EQU 14 ;SELECT DISK OPENF EQU 15 ;DISK OPEN FUNCTION DREADF EQU 20 ;DISK READ FUNCTION MAXTRY EQU 10 ;MAXIMUM NUMBER OF RETRIES ON EACH READ/WRITE CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED START: LD SP,STACK ;SET LOCAL STACK POIxor a ; clear zero flag ld (rtcnt),a ; clear retry cnt in case had to retry ret ; return w. no errors ;---------------- ; SHIFT RIGHT 16 ;---------------- shfr16: and a ; shift de reg right a-reg times jp z,xr16 ; jump over loop if shift 0 times shfrlp: srl d ; shift msb first, bit 0 into carry rr e ; rotate carry into bit 7 lsb dec a ; decrement shift counter jp nz,shfrlp ; loop util finished xr16: ret ;--------------- ; SHIFT LEFT 16 ;--------------- shfl16: and a ; shift de-reg left a-reg times jp z,xl16 ; check for shift zero times shfllp: sla e ; shf lsb first, c = bit 7, bit 0 = 0 rl d ; shf msb, bit 0 = carry dec a ; decrement shift counter jr nz,shfllp ; loop until a-reg eq zero xl16: ret ;------------------------------ ; COMPARE 16-BIT DE AND HL REG ;------------------------------ cmp16: ld a,e ; compare e-reg w. l-reg xor l ; xor will zero accum. if e = l ret nz ; return if not equal ypm> ; ;------------------------------------------------------------------------------ dskdef endmod equ $ end end  ; physical drive hsttrk: dw 0 ; track (equiv to cylinder) hsthd: db 0 ; head hstsec: db 0 ; sector hstadr: dw 0 ; buffer address hstblk: dw 0 ; block no. in current cylinder blksec: db 0 ; host sector no. in block hstsiz: dw 0 ; physical sector size hstsdh: db 0 ; sdh register sector size setting wrtpnd: db 0 ; write pending (host buffer active) wrttyp: db 0 ; write type (0=use, 1=dir, 2=free) oper: db 0 ; operation (0=write, 1=read) ;------------------------------------------------------------------------------ ; DRIVE PARAMETER DEFINITIONS ;------------------------------------------------------------------------------ ; ; dskdef < drvtyp0, drvtyp1, ... , drvt1NTER LD HL,SIGNON CALL OUTMSG ; ; CHECK FOR DEFAULT FILE LOAD INSTEAD OF GET ; LD A,(FCB+1) ;BLANK IF NO FILE CP ' ' JR Z,GETSYS ;SKIP TO GET SYSTEM MESSAGE IF BLANK LD DE,FCB ;TRY TO OPEN IT CALL OPEN ; INC A ;255 BECOMES 00 JR NZ,RDOK ;OK TO READ IF NOT 255 ; ; FILE NOT PRESENT, ERROR AND REBOOT ; LD HL,NOFILE CALL CRMSG call filename JP REBOOT ; ; FILE PRESENT ; READ TO LOAD POINT ; RDOK: XOR A LD (FCBCR),A ;CURRENT RECORD = 0 LD HL,LOADP RDINP: PUSH HL LD d,h LD e,l ;READY FOR DMA CALL DMA ;DMA ADDRESS SET LD DE,FCB ;READY FOR READ CALL DREAD ; POP HL ;RECALL DMA ADDRESS OR A ;00 IF READ OK JR NZ,PUTSYS ;ASSUME EOF IF NOT. LD DE,SECSIZ ADD HL,DE ;HL IS NEW LOAD ADDRESS JP RDINP filename: xor A ld (fcb+13),A ld HL,fcb+1 call outmsg ret ;------------------------------ ; GET SYSTEM FROM SOURCE DRIVE ;------------------------------ getsys: ld hl,stypmsg call crmsg call getchar ld (drvtymsg call crmsg jp 0 fseek: call tstrdy ld a,1 out (fdata),a ld a,01eh out (fcmd),a call delay in a,(fwait) in a,(fcmd) and 018h jr z,chkds jp (hl) chkds: ld a,(097fh) and 0e5h ret z ld a,(dsd) set 2,a out (fwait),a ; call tstrdy ld a,1 out (fdata),a ld a,01eh out (fcmd),a call delay in a,(fwait) in a,(fcmd) and 018h ret nz ld a,0e7h ld (097fh),a ret ;-------------------- ; FLOPPY WRITE TRACK ;-------------------- fwrttrk: call tstrdy in a,(fstat) bit 6,a jr z,nwrtpro ld hl,wrpmsg call crmsg call getchar cp 3 jp z,reboot jp fwrttrk nwrtpro: ld e,1 ld c,fdata ld hl,0900h nextsec: di ld a,e out (fsec),a xor a out (ftrk),a ld a,0a4h out (fcmd),a fwrtlp: in a,(fwait) or a jp p,fwrtout outi jr fwrtlp fwrtout: ei ld a,d cp e jp z,reboot inc e jr nextsec ;----------------- ; HARD READ TRACK ;----------------- hrdtrk: ld (drv),a ld de,0512d ; bytes ret ;-------------------- ; FLOPPY READ TRACK ;-------------------- frdtrk: call tstrdy ld e,1 ld c,fdata ld hl,0900h rdsec: di ld a,e out (fsec),a xor a out (ftrk),a ld a,084h out (fcmd),a frdlp: in a,(fwait) or a jp p,frdout ini jr frdlp frdout: ei ld a,d cp e ret z inc e jr rdsec ;-------------------------------- ; GET SOURCE - DESTINATION DRIVE ;-------------------------------- getdrv: push hl call crmsg call getc pop hl cp cr j z,reboot cp '0' jp c,getdrv cp '4' jp nc,getdrv and 00fh ret ;------------------------------- ; TEST IF FLOPPY DRIVE IS READY ;------------------------------- tstrdy: push hl push de push bc push af tststart: ld a,0d0h out (fcmd),a call delay ld de,0ffffh ld hl,tstnidx tstnidx: in a,(fstat) bit 1,a jr nz,decde ld hl,tstidx tstidx: in a,(fstat) bit 1,a jr z,decde ld hl,tstrdx tstrdx: in a,(fstat) bit 7,a jr z,tstx decde: p),a cp cr jp z,putsys cp 'H' jr z,gethrd cp 'F' jr nz,getsys getfpy: ld hl,smsg call getdrv ld (sdrv),a ld a,(sdrv) call setden call frdtrk jp putsys gethrd: ld hl,smsg call getdrv ld (sdrv),a ld a,(sdrv) call hrdtrk jp putsys ;--------------------------------- ; PUT SYSTEM ON DESTINATION DRIVE ;--------------------------------- putsys: ld a,(drvtyp) and a jr z,getdtyp cp 0dh jr nz,putjmp getdtyp: ld hl,dtypmsg call crmsg call getchar cp cr jp z,reboot putjmp: cp 'H' jp z,puthd cp 'F' jr nz,putsys putfpy: ld hl,dmsg call getdrv ld (ddrv),a ld a,(ddrv) call setden ld a,(ddrv) call patchden ld a,(ddrv) call setden call fwrttrk jp reboot puthd: ld hl,dmsg call getdrv ld (ddrv),a ld a,(ddrv) call hwrttrk jp reboot ;-------------------------- ; SET DISK DENSITY TRK 000 ;-------------------------- setden: tst5dd: ld (drv),a ld b,018h or b out (fwait),a ld (dsd),a  per sector ld b,020h ; sdh reg sec. size setting ld c,016d ; sector per track call settsk ld a,cmdrst1 out (hcmd),a call polbsy ld a,cmdrd out (hcmd),a call polbsy jr z,hrdsec ld de,0256 ld b,0 ld c,32d call settsk ld a,cmdrst2 out (hcmd),a call polbsy ld a,cmdrd out (hcmd),a call polbsy jr z,hrdsec hrderr: ld hl,tk0rder call crmsg jp 0 hrdsec: ld (bps),de ld de,0 ld hl,0900h hrdnx: ld a,d out (hsec),a ld a,cmdrd out (hcmd),a call polbsy call rxdata call polbsy jp nz,hrderr inc d ld a,c cp d jp nz,hrdnx ret ;------------------ ; HARD WRITE TRACK ;------------------ hwrttrk: ld (drv),a ld de,0512d ; bytes per sector ld b,020h ; sdh reg sec. size setting ld c,016d ; sector per track call settsk ld a,cmdrst1 out (hcmd),a call polbsy ld a,cmdrd out (hcmd),a call polbsy jr z,hwrtsec ld de,0256 ld b,0 ld c,32d call settsk ld a,cmdrst2 out (hcmd),a call polbsy  dec de ld a,d or e jr z,notready jp (hl) tstx: pop af pop bc pop de pop hl ret notready: ld hl,nrdymsg call crmsg call getchar cp 3 jp z,reboot jp tststart ;--------------------- ; DELAY 28 US AT 6MHZ ;--------------------- delay: ld a,3 delaylp: ex (sp),hl ex (sp),hl dec a jr nz,delaylp ret ; ; UTILITY SUBROUTINES ; multsec: ld l,a ; mul sec no in a-reg by sec siz ld h,0 ; SECTOR NUMBER IN HL ld b,log2sec shft1: add hl,hl djnz shft1 ret ; WITH HL = SECTOR * SECTOR SIZE getchar: ld C,CONI ; read console char in to a-reg call BDOS and 05fh ; convert to upper case ret getc: ld c,coni call bdos ret putchar: LD E,A ; display char in a-reg on console LD C,CONO CALL BDOS RET crlf: LD A,CR ; display cr,lf on console CALL PUTCHAR LD A,LF CALL PUTCHAR RET CRMSG: PUSH HL ; display cr,lf, msg pointed to by hl CALL CRLF ; until zero enc ld d,04 ld a,d ld (097eh),a ld hl,tst8sd jr frestore tst8sd: ld a,(drv) out (fwait),a ld (dsd),a ld hl,tst8dd ld d,026d ld a,d ld (097eh),a jr frestore tst8dd: ld a,(drv) ld b,08h or b out (fwait),a ld (dsd),a ld hl,trk0err ld d,04 ld a,d ld (097eh),a j frestore trk0err: ld hl,tk0rder call crmsg jp 0 frestore: call tstrdy ld a,0fh out (fcmd),a call delay in a,(fwait) in a,(fcmd) and 018h ret z jp (hl) ;----------------------------------------------------- ; GET DISK DENSITY OF TRK 001 AND PATCH TO LOC. 097FH ;----------------------------------------------------- patchden: chk5dd: ld (drv),a ld b,018h or b out (fwait),a ld (dsd),a ld hl,chk8sd jr fseek chk8sd: ld a,(drv) out (fwait),a ld (dsd),a ld a,0e5h ld (097fh),a ld hl,chk8dd jr fseek chk8dd: ld a,(drv) ld b,08h or b out (fwait),a ld (dsd),a ld a,0e6h ld (097fh),a ld hl,sekerr j fseek sekerr: ld hl,sek ld a,cmdrd out (hcmd),a call polbsy jr z,hwrtsec hwrterr: ld hl,tk0wrer call crmsg jp 0 hwrtsec: ld (bps),de ld de,0 ld hl,0900h hwrtnx: ld a,d out (hsec),a ld a,cmdwrt out (hcmd),a call polbsy call snddata call polbsy jp nz,hwrterr inc d ld a,c cp d jp nz,hwrtnx ret ;------------------------------ ; HARD DISK SET TASK REGISTERS ;------------------------------ settsk: ld a,(drv) sla a sla a sla a or b out (hsdh),a xor a out (hcylhi),a out (hcyllow),a out (hsec),a ret ;----------- ; POLL BUSY ;----------- polbsy: in a,(hstatus) and a jp m,polbsy and 1 ret ;-------------- ; RECIEVE DATA ;-------------- rxdata: push bc ld a,(bps) ld b,a ld c,hdata inir ld a,(bps+1) and 2 jp z,rxx inir rxx: pop bc ret ;----------- ; SEND DATA ;----------- snddata: push bc ld a,(bps) ld b,a ld c,hdata otir ld a,(bps+1) and 2 jp z,sndx otir sndx: pop bc 1ountered POP HL ;DROP THRU TO OUTMSG0 OUTMSG: LD A,M OR A RET Z PUSH HL CALL PUTCHAR POP HL INC HL JP OUTMSG dread: ld c,014h jp bdos open: ld c,00fh jp bdos dma: ld c,01ah jp bdos ;------ ; EXIT ;------ reboot: call crlf jp 0 ;-------------- ; DATA STORAGE ;-------------- signon: db 'LDRGEN ' db ((vers / 10) + '0') db '.' db ((vers mod 10) + '0') db cr,lf,0 nofile: db 'Can''nt open file: ',0 stypmsg: db 'Read loader from Hard or Floppy drive (H,F) : ',0 dtypmsg: db 'Write loader to Hard or Floppy drive (H,F) : ',0 smsg: db 'Physical drive no. of loader source (0-3) : ',0 dmsg: db 'Physical drive no. of loader destination (0-3) : ',0 nrdymsg: db 'Drive Not Ready : ',0 wrpmsg: db 'Disk Write Protected : ',0 tk0rder: db 'Cannot Read Track 000',0 tk0wrer: db 'Cannot Write Track 000',0 sekmsg: db 'Cannot Read Track 1',0 drvtyp: db 0 ; 'H' or 'F' sdrv: db 0 ; source drive ddrv: db 0 krt, 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 SA1002 ; 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 ;memo 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 ; ; destination drive drv: db 0 ; working variable den: db 0 ; disk density byte dsd: db 0 ; bps: dw 0 ; hd bytes per sector ds 040h stack: end  reboot: call crlf jp 0 ;-------------- ; DATA STORAGE ;-------------- signon: db 'LDRGEN ' db ((vers / 10) + '0') db '.' db ((vers mod 10) + '0') db cr,lf,0 nofile: db 'Can''nt open file: ',0 stypmsg: db 'Read loader from Hard or Floppy drive (H,F) : ',0 dtypmsg: db 'Write loader to Hard or Floppy drive (H,F) : ',0 smsg: db 'Physical drive no. of loader source (0-3) : ',0 dmsg: db 'Physical drive no. of loader destination (0-3) : ',0 nrdymsg: db 'Drive Not Ready : ',0 wrpmsg: db 'Disk Write Protected : ',0 tk0rder: db 'Cannot Read Track 000',0 tk0wrer: db 'Cannot Write Track 000',0 sekmsg: db 'Cannot Read Track 1',0 drvtyp: db 0 ; 'H' or 'F' sdrv: db 0 ; source drive ddrv: db 0 ry 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 intalloc0 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  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!! seeerrupt 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 EQU2004Ch ;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 %nr 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,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 so,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 vec31,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 hingle 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 defltor 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 ;numbeddr&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+2 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  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*ddps;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  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)pt ;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 j 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,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 r 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 3,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  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=startsettrk:: 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  ;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 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 c ; 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 l 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 toan'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 3d 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 vtrk:: 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:: d .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) ;gper 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 # thaw 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 ;sectet 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 densitn 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 blkdror deblocking buffer ; ; lastadd equ $ SUBTTL SYMBOLS end  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 ;sect4y 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 densitequ 030h ; write sector command ;----------------------------- ; STATUS REGISTER BIT TESTERS ;----------------------------- bsybit equ 080h ; busy bit rdybit equ 040h ; data request bit errbit equ 001h ; error bit ;--------------------------- ; START OF COLD BOOT LOADER ;--------------------------- start: ld a,06fh ; get command to memory port out (memry),a ; turn off prom ld bc,hdata ; get port number and transfer length ld hl,080h ; starting address ld de,020d ; number of 256 b sectors to transfer loop: ld a,d ; send sector to controller out (hsec),a ld a,cmdrd ; send read command out (hcmd),a swait: in a,(hstatus) ; wait till done or a jp m,swait rra ; any errors jr c,error inir ; get data inc d ; increment sector to read dec e ; decrement sector count jr nz,loop ; if more go do it jp 0100h ; else go execute loader error: ld a,04fh ; turn prom back on out (memry),a jp 0f030h ; ret to monito 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 HDCBAr hard disk err return end ---- bsybit equ 080h ; busy bit rdybit equ 040h ; data request bit errbit equ 001h ; error bit ;--------------------------- ; START OF COLD BOOT LOADER ;--------------------------- start: ld a,06fh ; get command to memory port out (memry),a ; turn off prom ld bc,hdata ; get port number and transfer length ld hl,080h ; starting address ld de,020d ; number of 256 b sectors to transfer loop: ld a,d ; send sector to controller out (hsec),a ld a,cmdrd ; send read command out (hcmd),a swait: in a,(hstatus) ; wait till done or a jp m,swait rra ; any errors jr c,error inir ; get data inc d ; increment sector to read dec e ; decrement sector count jr nz,loop ; if more go do it jp 0100h ; else go execute loader error: ld a,04fh ; turn prom back on out (memry),a jp 0f030h ; ret to monitoSE+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  .z80 ;-------------------------------------------------- ; COLD BOOT LOADER FOR DMA MICRO MAGNUM DISK DRIVE ;-------------------------------------------------- ;--------------------- ; MEMORY PORT ADDRESS ;--------------------- memry equ 016h ; memory control port ;------------------------- ; HDC-1001 PORT ADDRESSES ;------------------------- hbase equ 0e0h ; base port address of hdc-1001 hdata equ hbase+0 ; data register herror equ hbase+1 ; error register hwrtpre equ hbase+1 ; write pre-compensation register hseccnt equ hbase+2 ; sector count register hsec equ hbase+3 ; sector number register hcyllow equ hbase+4 ; cylinder low register hcylhi equ hbase+5 ; cylinder high register hsdh equ hbase+6 ; size - drive - head register hstatus equ hbase+7 ; status register hcmd equ hbase+7 ; command register ;------------------- ; HDC-1001 COMMANDS ;------------------- cmdrst equ 01fh ; restore command cmdrd equ 020h ; read sector command cmdwrt 4to 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 CF = 01 NDIRRECG = 01 NDIRRECH = 01 NDIRRECI = 01 NDIRRECJ = 01 NDIRRECK = 01 NDIRRECL = 01 NDIRRECM = 01 NDIRRECN = 01 NDIRRECO = 01 NDIRRECP = 01 NDTARECA = 21 NDTARECB = 00 NDTARECC = 00 NDTARECD = 00 NDTARECE = 01 NDTARECF = 01 NDTARECG = 01 NDTARECH = 01 NDTARECI = 01 NDTARECJ = 01 NDTARECK = 01 NDTARECL = 01 NDTARECM = 01 NDTARECN = 01 NDTARECO = 01 NDTARECP = 01 ODIRDRVA = A ODIRDRVB = A ODIRDRVC = A ODIRDRVD = A ODIRDRVE = A ODIRDRVF = A ODIRDRVG = A ODIRDRVH = A ODIRDRVI = A ODIRDRVJ = A ODIRDRVK = A ODIRDRVL = A ODIRDRVM = A ODIRDRVN = A ODIRDRVO = A ODIRDRVP = A ODTADRVA = A ODTADRVB = A ODTADRVC = A ODTADRVD = A ODTADRVE = A ODTADRVF = A ODTADRVG = A ODTADRVH = A ODTADRVI = A ODTADRVJ = A ODTADRVK = A ODTADRVL = A ODTADRVM = A ODTADRVN = A ODTADRVO = A ODTADRVP = A OVLYDIRA = Y OVLYDIRB = Y OVLYDIRC = Y OVLYDIRD = Y OVLYDIRE = Y OVLYDIRF = Y OVLYDIRG = Y OVLYDIRH = Y OVLYDIRI = Y OVLYDIRJ = Y OVLYDIRK = Y OVLYDIRL = Y OVLYDIRM ;----------------------------------- ; CP/M 3.0 BANKED SYSTEM GENERATION ;----------------------------------- pip gencpm.dat=c3bgen.dat gencpm auto display pip cpm3bnk.sys=cpm3.sys  OVLYDTAP = Y CRDATAF = N DBLALV = Y 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,0 end E 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 = Y OVLYDIRN = Y OVLYDIRO = Y OVLYDIRP = Y OVLYDTAA = Y OVLYDTAB = Y OVLYDTAC = Y OVLYDTAD = Y OVLYDTAE = Y OVLYDTAF = Y OVLYDTAG = Y OVLYDTAH = Y OVLYDTAI = Y OVLYDTAJ = Y OVLYDTAK = Y OVLYDTAL = Y OVLYDTAM = Y OVLYDTAN = Y OVLYDTAO = Y OVLYDTAP = Y CRDATAF = N DBLALV = Y NDTARECP = 01 ODIRDRVA = A ODIRDRVB = A ODIRDRVC = A ODIRDRVD = A ODIRDRVE = A ODIRDRVF = A ODIRDRVG = A ODIRDRVH = A ODIRDRVI = A ODIRDRVJ = A ODIRDRVK = A ODIRDRVL = A ODIRDRVM = A ODIRDRVN = A ODIRDRVO = A ODIRDRVP = A ODTADRVA = A ODTADRVB = A ODTADRVC = A ODTADRVD = A ODTADRVE = A ODTADRVF = A ODTADRVG = A ODTADRVH = A ODTADRVI = A ODTADRVJ = A ODTADRVK = A ODTADRVL = A ODTADRVM = A ODTADRVN = A ODTADRVO = A ODTADRVP = A OVLYDIRA = Y OVLYDIRB = Y OVLYDIRC = Y OVLYDIRD = Y OVLYDIRE = Y OVLYDIRF = Y OVLYDIRG = Y OVLYDIRH = Y OVLYDIRI = Y OVLYDIRJ = Y OVLYDIRK = Y OVLYDIRL = Y OVLYDIRM PRTMSG = Y PAGWID = 4F PAGLEN = 17 BACKSPC = N RUBOUT = Y BOOTDRV = A MEMTOP = FF BNKSWT = Y COMBAS = C0 LERROR = Y NUMSEGS = 02 MEMSEG00 = 00,85,00 MEMSEG01 = 10,30,02 MEMSEG02 = 00,C0,03 MEMSEG03 = 00,C0,04 MEMSEG04 = 00,C0,05 MEMSEG05 = 00,C0,06 MEMSEG06 = 00,C0,07 MEMSEG07 = 00,C0,08 MEMSEG08 = 00,C0,09 MEMSEG09 = 00,C0,0A MEMSEG0A = 00,C0,0B MEMSEG0B = 00,C0,0C MEMSEG0C = 00,C0,0D MEMSEG0D = 00,C0,0E MEMSEG0E = 00,C0,0F MEMSEG0F = 00,C0,10 HASHDRVA = Y HASHDRVB = Y HASHDRVC = Y HASHDRVD = Y HASHDRVE = Y HASHDRVF = Y HASHDRVG = Y HASHDRVH = Y HASHDRVI = Y HASHDRVJ = Y HASHDRVK = Y HASHDRVL = Y HASHDRVM = Y HASHDRVN = Y HASHDRVO = Y HASHDRVP = Y ALTBNKSA = Y ALTBNKSB = Y ALTBNKSC = Y ALTBNKSD = Y ALTBNKSE = N ALTBNKSF = N ALTBNKSG = N ALTBNKSH = N ALTBNKSI = N ALTBNKSJ = N ALTBNKSK = N ALTBNKSL = N ALTBNKSM = N ALTBNKSN = N ALTBNKSO = N ALTBNKSP = N NDIRRECA = 08 NDIRRECB = 00 NDIRRECC = 00 NDIRRECD = 00 NDIRRECE = 01 NDIRRE5;--------------------------------- ; CP/M 3.0 BANKED BIOS GENERATION ;--------------------------------- link bnkbios3[b]=c3bkrnl,c3init,c3bboot,c3chr,c3clk,c3bmov,c3fdsk,c3hdsk,c3dtbl,scb  OVLYDTAP = Y CRDATAF = N DBLALV = Y 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,0 end E 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 CF = 01 NDIRRECG = 01 NDIRRECH = 01 NDIRRECI = 01 NDIRRECJ = 01 NDIRRECK = 01 NDIRRECL = 01 NDIRRECM = 01 NDIRRECN = 01 NDIRRECO = 01 NDIRRECP = 01 NDTARECA = 01 NDTARECB = 00 NDTARECC = 00 NDTARECD = 00 NDTARECE = 01 NDTARECF = 01 NDTARECG = 01 NDTARECH = 01 NDTARECI = 01 NDTARECJ = 01 NDTARECK = 01 NDTARECL = 01 NDTARECM = 01 NDTARECN = 01 NDTARECO = 01 NDTARECP = 01 ODIRDRVA = A ODIRDRVB = A ODIRDRVC = A ODIRDRVD = A ODIRDRVE = A ODIRDRVF = A ODIRDRVG = A ODIRDRVH = A ODIRDRVI = A ODIRDRVJ = A ODIRDRVK = A ODIRDRVL = A ODIRDRVM = A ODIRDRVN = A ODIRDRVO = A ODIRDRVP = A ODTADRVA = A ODTADRVB = A ODTADRVC = A ODTADRVD = A ODTADRVE = A ODTADRVF = A ODTADRVG = A ODTADRVH = A ODTADRVI = A ODTADRVJ = A ODTADRVK = A ODTADRVL = A ODTADRVM = A ODTADRVN = A ODTADRVO = A ODTADRVP = A OVLYDIRA = Y OVLYDIRB = Y OVLYDIRC = Y OVLYDIRD = Y OVLYDIRE = Y OVLYDIRF = Y OVLYDIRG = Y OVLYDIRH = Y OVLYDIRI = Y OVLYDIRJ = Y OVLYDIRK = Y OVLYDIRL = Y OVLYDIRM ;--------------------------------------- ; CP/M 3.0 NON-BANKED SYSTEM GENERATION ;--------------------------------------- pip gencpm.dat=c3gen.dat gencpm auto display  OVLYDTAP = Y CRDATAF = N DBLALV = N 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,0 end E 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 = Y OVLYDIRN = Y OVLYDIRO = Y OVLYDIRP = Y OVLYDTAA = Y OVLYDTAB = Y OVLYDTAC = Y OVLYDTAD = Y OVLYDTAE = Y OVLYDTAF = Y OVLYDTAG = Y OVLYDTAH = Y OVLYDTAI = Y OVLYDTAJ = Y OVLYDTAK = Y OVLYDTAL = Y OVLYDTAM = Y OVLYDTAN = Y OVLYDTAO = Y OVLYDTAP = Y CRDATAF = N DBLALV = N NDTARECP = 01 ODIRDRVA = A ODIRDRVB = A ODIRDRVC = A ODIRDRVD = A ODIRDRVE = A ODIRDRVF = A ODIRDRVG = A ODIRDRVH = A ODIRDRVI = A ODIRDRVJ = A ODIRDRVK = A ODIRDRVL = A ODIRDRVM = A ODIRDRVN = A ODIRDRVO = A ODIRDRVP = A ODTADRVA = A ODTADRVB = A ODTADRVC = A ODTADRVD = A ODTADRVE = A ODTADRVF = A ODTADRVG = A ODTADRVH = A ODTADRVI = A ODTADRVJ = A ODTADRVK = A ODTADRVL = A ODTADRVM = A ODTADRVN = A ODTADRVO = A ODTADRVP = A OVLYDIRA = Y OVLYDIRB = Y OVLYDIRC = Y OVLYDIRD = Y OVLYDIRE = Y OVLYDIRF = Y OVLYDIRG = Y OVLYDIRH = Y OVLYDIRI = Y OVLYDIRJ = Y OVLYDIRK = Y OVLYDIRL = Y OVLYDIRM PRTMSG = Y PAGWID = 4F PAGLEN = 17 BACKSPC = N RUBOUT = Y BOOTDRV = A MEMTOP = FF BNKSWT = N COMBAS = 00 LERROR = Y NUMSEGS = 03 MEMSEG00 = 00,80,00 MEMSEG01 = 00,C0,02 MEMSEG02 = 00,C0,03 MEMSEG03 = 00,C0,04 MEMSEG04 = 00,C0,05 MEMSEG05 = 00,C0,06 MEMSEG06 = 00,C0,07 MEMSEG07 = 00,C0,08 MEMSEG08 = 00,C0,09 MEMSEG09 = 00,C0,0A MEMSEG0A = 00,C0,0B MEMSEG0B = 00,C0,0C MEMSEG0C = 00,C0,0D MEMSEG0D = 00,C0,0E MEMSEG0E = 00,C0,0F MEMSEG0F = 00,C0,10 HASHDRVA = N HASHDRVB = N HASHDRVC = N HASHDRVD = N HASHDRVE = Y HASHDRVF = Y HASHDRVG = Y HASHDRVH = Y HASHDRVI = Y HASHDRVJ = Y HASHDRVK = Y HASHDRVL = Y HASHDRVM = Y HASHDRVN = Y HASHDRVO = Y HASHDRVP = Y ALTBNKSA = N ALTBNKSB = N ALTBNKSC = N ALTBNKSD = N ALTBNKSE = N ALTBNKSF = N ALTBNKSG = N ALTBNKSH = N ALTBNKSI = N ALTBNKSJ = N ALTBNKSK = N ALTBNKSL = N ALTBNKSM = N ALTBNKSN = N ALTBNKSO = N ALTBNKSP = N NDIRRECA = 01 NDIRRECB = 00 NDIRRECC = 00 NDIRRECD = 00 NDIRRECE = 01 NDIRRE5;------------------------------------- ; CP/M 3.0 NON-BANKED BIOS GENERATION ;------------------------------------- link bios3[os]=c3krnl,c3init,c3boot,c3chr,c3clk,c3mov,c3fdsk,c3hdsk,c3dtbl,scb  OVLYDTAP = Y CRDATAF = N DBLALV = N 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,0 end E 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 ss c3mac ss c3llink ss c3link ss c3blink ss c3bgen ss c3gen ss c3dmy -------------------- ; CP/M 3.0 NON-BANKED MODULES ;----------------------------- m80 =c3krnl/l m80 =c3boot/l m80 =c3mov/l ;------------------------- ; CP/M 3.0 BANKED MODULES ;------------------------- m80 =c3bkrnl/l m80 =c3bboot/l m80 =c3bmov/l ;-------------------------------------- ; CP/M 3.0 BANKED / NON-BANKED MODULES ;-------------------------------------- m80 =c3init/l m80 =c3chr/l m80 =c3clk/l m80 =c3fdsk/l m80 =c3hdsk/l m80 =c3dtbl/l m80 =scb/l E 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 ;------------------------- ; CP/M 3.0 LOADER MODULES ;------------------------- m80 =c3lkrnl/l m80 =c3lchr/l ;----------------------------- ; CP/M 3.0 NON-BANKED MODULES ;----------------------------- m80 =c3krnl/l m80 =c3boot/l m80 =c3mov/l ;------------------------- ; CP/M 3.0 BANKED MODULES ;------------------------- m80 =c3bkrnl/l m80 =c3bboot/l m80 =c3bmov/l ;-------------------------------------- ; CP/M 3.0 BANKED / NON-BANKED MODULES ;-------------------------------------- m80 =c3init/l m80 =c3chr/l m80 =c3clk/l m80 =c3fdsk/l m80 =c3hdsk/l m80 =c3dtbl/l m80 =scb/l E 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 ;---------------------------- ; CP/M 3.0 LOADER GENERATION ;---------------------------- link osload.sys[l2000]=cpmldr,c3lkrnl,c3lchr,c3mov,c3fdsk,c3hdsk,c3dtbl  OVLYDTAP = Y CRDATAF = N DBLALV = N 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,0 end E 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 61e`r`:0802U>2R:R >`:S >D >2Q`:N(Y :R >2L2O"`:N(Y >2=:Q(>>2T:O >(2L>2M! "D!"F!"H"JN`:U0Yk` Y> YfW2P͔>ͥK`z$! ~ #(! ͽ 2Nµ:= :Q( :P(82P͔ ( ʦB:L(=z>ͥ*D*F>2P͔z *H*J *D*F t```:C 2S`:ʃN :MO"B^#~f(# *BF#~# w#r#:Pw#s#w# :P=G:S:T+w#2Sɯ23  1 >P:3 aX{X__ := `)`K` g`K`z$ DISK ERROR: $  `> "@:M2>2?~:P(>> ( 2N :>=(2>#:?f:?<2? 8`:N`:P1`z$`~$`:N$`:ʦSʆR f2P͔*@%f2P͔S:PG:U WRITE ERROR: $"@`.G(`Lx@(`?x (6`2x(B`%xPN 2N N BNfNN6M6{s6M6'M6-M6dM6!M6gM6|M6 2N N BNfNN6M6{s6M6'M6-M6dM6!M6gM6|M6ystem Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOST DATA$DATA REQUEST$ FORMATTING ABORTED$   ( f(S`x(]` x(g`????1Ɛ'@'Y FORMATTING $FMT548 3.1 $ Enter Disk Drive To Be Formatted (0-3) : $ Enter Density, Single or Double (S,D) : $ Format Single or Double Sided (S,D) : $ Format System Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOST DATA$DATA REQUEST$ FORMATTING ABORTED$   ( f1e`r`:0802U>2R:R >`:S >D >2Q`:N(Y :R >2L2O"`:N(Y >2=:Q(>>2T:O >M2L>2M! "D!"F!"H"JN`:U0Yk` Y> YfW2P͔>ͥK`z$! ~ #(! ͽ 2Nµ:= :Q( :P(82P͔ ( ʦB:L(=z>ͥ*D*F>2P͔z *H*J *D*F t```:C 2S`:ʃN :MO"B^#~f(# *BF#~# w#r#:Pw#s#w# :P=G:S:T+w#2Sɯ23  1 >P:3 aX{X__ := `)`K` g`K`z$ DISK ERROR: $  `> "@:M2>2?~:P(>> ( 2N :>=(2>#:?f:?<2? 8`:N`:P1`z$`~$`:N$`:ʦSʆR f2P͔*@%f2P͔S:PG:U WRITE ERROR: $"@`.G(`Lx@(`?x (6`2x(B`%xPN 2N N BNfNN|2>:f3)0R3>)30R3=363D>3E>3 >0f3xG3x0:R3 2N N BNfNN|2>:f3)0R3>)30R3=363D>3E>3 >0f3xG3x0:R3ystem Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOST DATA$DATA REQUEST$ FORMATTING ABORTED$   ( f(S`x(]` x(g`????1Ɛ'@'Y FORMATTING $FMT596 3.1 $ Enter Disk Drive To Be Formatted (0-3) : $ Enter Density, Single or Double (S,D) : $ Format Single or Double Sided (S,D) : $ Format System Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOST DATA$DATA REQUEST$ FORMATTING ABORTED$   ( f61ͫͫͅ0802ͫͅD(S >>2: >#ͫͅS >D >2OͫͅN(Y : >22{ͫͅN(Y >2: >M2:(*!Y "!" ":(>>2!2 !>2!2 "!">2""ͫ:0ͤͫ ͤ> ͤͱW2>ͫz! ~ #((K!  2: :( :(L2 ( B:(Qz : >2z>**,>2z **B**BͫͫͫͅC 2ͫͅʘN :O"^#~f(K# *F#~# w#r#:w#s#w# :=G::+w#2ɯ2   >P: aڣ{ң__ : Xͫͫͫ ͫͫz DISK ERROR: $  ͫ#> ":22~:(>> ( 2 :=(2#:ͱ:<2 8ͫ:#ͫ:͌ͫzͫ~ͫ:6ͫͅSR ͱ2*\ͱ2Ê:G:Gz( : >ble error during format.$ Operation aborted.$@ = ST503 11 = SA606 1 = ST506 12 = SA1002 2 = TM601S 13 = SA1004 3 = TM602S 14 = Q2010 4 = TM603S 15 = Q2020 5 = TM603SE 16 = Q2030 6 = TM501 or ST406 17 = Q2040 7 = TM502 or ST412 18 = M4010 8 = TM503 or ST419 19 = M4020 9 = SA602 20 = DMA 5/5 10 = SA604 Enter drive to format: $ Do you want to format cartriage only [Y or N]?$ 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.$@ WRITE ERROR: $"ͫ#yG(gͫLx@(wͫ?x (ͫ2x(ͫ%x(ͫx(ͫ x(ͫ????͌Ɛ'@'ͤ FORMATTING $FMT8 3.1 $ Enter Disk Drive To Be Formatted (0-3) : $ Enter Density, Single or Double (S,D) : $ Format Single or Double Sided (S,D) : $ Format System Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOST DATA$DATA REQUEST$ FORMATTING ABORTED$ r  :(86 ~ !0:0DM)) )oN$=3>x NxYZ>2T]))S 08 6 2 :ͮ    @!6#*&":G_!}/o|/g#"x/o&#"*#*,x*::G:2:G>S*:W> 2zͮ:}|:>P(!: (>Oy :=2i͌:i+|] *:_:=WKyͮBx}|:> @l6 ͥG ͮQ ͥͥ] ͥ ͌ :+|g  ( ͮ0:_  |ͥ}ͥ  ( !0  DAM Not Found Error $ TR000 Error $ Aborted Command Error $ Undefined Error $ ID Not Found Error $ CRC Id Error $ Uncorrectable Error $ Bad Block Detect Error$ Write Fault Error $    ( fPN 2N N BNfNN:f3>0f3y*{3w+"{36 *{32Ow+ ʏ3 3~3w+ ~3Ô2ʢ3w+22 2N N ensity, Single or Double (S,D) : $ Format Single or Double Sided (S,D) : $ Format System Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOST DATA$DATA REQUEST$ FORMATTING ABORTED$     1 1 1            !?FMTHD 2.2 0 = ST503 11 = SA606 1 = ST506 12 = SA1002 2 = TM601S 13 = SA1004 3 = TM602S 14 = Q2010 4 = TM603S 15 = Q2020 5 = TM603SE 16 = Q2030 6 = TM501 or ST406 17 = Q2040 7 = TM502 or ST412 18 = M4010 8 = TM503 or ST419 19 = M4020 9 = SA602 20 = DMA 5/5 10 = SA604 Enter drive to format: $ Do you want to format cartriage only [Y or N]?$ 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.$@7Lo&)__> > !~#11!1:] (>\B< !,͏2|! T]G\= Rx2i!]1!, 29 H(F !ix2:::.R!ix2:::C:9( !7,  HF !x2;:;.:;͈:;.!x2;:;ͧ2<2>z2~ !D2:<2>!Wz2~ :<2>!mz2~  !,͒>  2<2>!0:<2>>2 !:<2>>2 ! !%,͒>>  (: :>>>  >2 ͒ w(!, ! { > :z2<  >> (# >> ( !,S?! z> (zy2<  >> (# >> ( !,S?! z>0=y:<''':?G:@;:?G:@P͒! { > qz, 0x4x> ! O ! O( ! (z(!, Ö>= !LDRGEN 2.4 Can'nt open fi+#*(.#}|y$#$*(%#*(DM"(**(s#r*(s#r#pyoxgk$DM*(0*MD"(!**(MD$*:(O&%!(N:( y$G>O:( ʐ$Ç$*(͒$ :(ʨ$n` ~#for$2(O͚$"(}:(O*(7#"(2("(:(O:(G2(!(w*( *($!$~2(~2($:(2($:(w:(w |g}o'% )4%:(O!3%yoxg:(O&%}*(:(o$$~w{ozg ^#V#:(ʏ%>(Û%͡%"(#ͳ#*(ç%*(r%"(!(~#O&%E:(%$N/*("(y2(ʹ%͗#ͻ%ͫ%ʛ&*(X%:(O~J&yʔ&x ʍ& ʂ&J&Í&N%J&# h&2 #G>G":&$~X%*( I#%Ow!&x&>Fwx2(2(~:(:(6:(&w2($~O %!'>w:&ͨ&$2("4%O.'5"&Ϳ&'$:(!(S'"&: #"ͮ$"$:((͛%#ͳ#%:(< #=!(wW*(M%_S# #-*(MD:%"(:(2(ɯ2('>G=O*(~~w#~2(~wc%$~'~p2(!"(>2(*(~=2('~2(͛'o'>*(w9-H-<,;,*,t8L8.0=0L0L4le: Read loader from Hard or Floppy drive (H,F) : Write loader to Hard or Floppy drive (H,F) : Physical drive no. of loader source (0-3) : Physical drive no. of loader destination (0-3) : Drive Not Ready : Disk Write Protected : Cannot Read Track 000Cannot Write Track 000Cannot Read Track 1"#@"%@*?#0*)@+<2?2?2@*@$͍ >0"?%O;.0~<=ad Track 000Cannot Write Track 000Cannot Read Track 1"#@"%@*?#0*)@+<2?2?2@*@$͍ >0"?%O;.0~<=2 ͒ w(!, ! { > :z2<  >> (# >> ( !,S?! z> (zy2<  >> (# >> ( !,S?! z>0=y:<''':?G:@;:?G:@P͒! { > qz, 0x4x> ! O ! O( ! (z(!, Ö>= !LDRGEN 2.4 Can'nt open fi!"(2(=2(!"(Û%͛'o'͢'͢&'(ͫ%$~<7(w@ͩ'7':(""(Û%:(~(:(2(:(~(*(6:(p(w#:(w$:(w*@"* #}D>(%$*((*(T):(_2({2("(r%"([))?#,)d)>l)[)I#6:(<!=6)*(J)"(*(K*:(G/O*((*(#=#d)##(I#*+++***N++Q+V+[+k+È+-*`+3*6*9*<*?*B*E*H*,N*Q*T*W*Z*]*`*s*1*~ʞ*O *#Ï*{**>/<Ҹ*33í*O * _ W{«**Ɛ'@'O *!+͆*:+AO *!+͆**+ͥ*!+͆**+ͥ*y2+i&)/ ~#fo{M+s*1*!~2+!~#foͅ*{*C+C+C+i`z n&s*1**+&)/~#foâ+s*1**+&)/~#fo~#fo2+ͅ*{* BIOS Error on : T-, S-+(+(y>1!* ͍! %!͍! ͍! ʢ ͏ ͕ !!~# 4 ͕  ͍!:!g:!s :!_ g:!s !]~$o #~B̩ 1!ɷW|g ͏ ͕ %z ͍! ͍!  ͍!vCPM3 SYS CPMLDR error: failed to open CPM3.SYS $ CPMLDR error: failed to read CPM3.SYS $ CP/M V3.0 Loader Copyright (C) 1982, Digital Research $021182"(yڥ!2(2(:(2({2(!" #"(9"@"1"!N(y2!K!!!dڛ&_^#V*("""""""""""""((("""";(""""A(G(""""""""""""""""""""""":"ž" *y!(4 5~yµ"5 6y ’" ͒":("!( Oͻ""MD"2 #>" BDOS ERR: $Select$Perm.$""" #""#"v{_zW{_zW )8## ?# w#J#J*|^#V###"(##"(######"(!( I#*(!(I#*(|!(6ʕ#67**(w#w*(w#w#w!(^#V#Fͪ#'*O##*(&%!(s#r#p*(N#F*(^#V#F*(:(O}|y$*(%#Q  M? @ S.e,- ~,͒,ͭ,,,͢.:.w*.+~>8 +2.͗.>w-:.2.:._O͗.>w-y2.*. :.!8g( !,o(!8_( W(s#r*.:._ 8g( 8o(8s#r:.!8g( !8o(!8_( W(!/[+s#r!:.wW-8-Ͳ- W-.8Ͳ- 9>^V9z2&9~[+9͢.~˗##͗.~ K+ :.[+( {2.yw-:+ݦG_(x!. (4>w:.3.> ͗.wG3.x> ͭ.  w !'9> ͭ. . .p.(!'9> ͭ... > ͭ.:.g(!G. O !P. O(!Y. ͭ.z(.p.(*͆* *!.͆*(> >2.!.[+!.K+ >= , Drive Not Ready, Write Protected Disk !/[+^#V:+'''ݶ֯>pݶ/P/8͑//P/ͨ/8/9>^V9z2&9~[+9:+'''ݶ݆:+:+:+ݦ>0!'9F~> /!'9F~ק/087`?     !'9[+K+,,:&9=2&9 *+'9:+G,,:&9=2&9 !/[+^#Vɧ:=#=+#*(.#}|y$#$*(%#*(DM"(**(s#r*(s#r#pyoxgk$DM*(0*MD"(!**(MD$*:(O&%!(N:( y$G>O:( ʐ$Ç$*(͒$ :(ʨ$n` ~#for$2(O͚$"(}:(O*(7#"(2("(:(O:(G2(!(w*( *($!$~2(~2($:(2($:(w:(w |g}o'% )4%:(O!3%yoxg:(O&%}*(:(o$$~w{ozg ^#V#:(ʏ%>(Û%͡%"(#ͳ#*(ç%*(r%"(!(~#O&%E:(%$N/*("(y2(ʹ%͗#ͻ%ͫ%ʛ&*(X%:(O~J&yʔ&x ʍ& ʂ&J&Í&N%J&# h&2 #G>G":&$~X%*( I#%Ow!&x&>Fwx2(2(~:(:(6:(&w2($~O %!'>w:&ͨ&$2("4%O.'5"&Ϳ&'$:(!(S'"&: #"ͮ$"$:((͛%#ͳ#%:(< #=!(wW*(M%_S# #-*(MD:%"(:(2(ɯ2('>G=O*(~~w#~2(~wc%$~'~p2(!"(>2(*(~=2('~2(͛'o'>*(w9-H-<,;,*,8L8.0=0L0L4!"(2(=2(!"(Û%͛'o'͢'͢&'(ͫ%$~<7(w@ͩ'7':(""(Û%:(~(:(2(:(~(*(6:(p(w#:(w$:(w*@"* #}D>(%$*((*(T):(_2({2("(r%"([))?#,)d)>l)[)I#6:(<!=6)*(J)"(*(K*:(G/O*((*(#=#d)##(I#*+++***N++Q+V+[+k+È+-*`+3*6*9*<*?*B*E*H*,N*Q*T*W*Z*]*`*s*1*~ʞ*O *#Ï*{**>/<Ҹ*33í*O * _ W{«**Ɛ'@'O *!+͆*:+AO *!+͆**+ͥ*!+͆**+ͥ*y2+i&)/ ~#fo{M+s*1*!~2+!~#foͅ*{*C+C+C+i`z n&s*1**+&)/~#foâ+s*1**+&)/~#fo~#fo2+ͅ*{* BIOS Error on : T-, S-+(+(y>1!* ͍! %!͍! ͍! ʢ ͏ ͕ !!~# 4 ͕  ͍!:!g:!s :!_ g:!s !]~$o #~B̩ 1!ɷW|g ͏ ͕ %z ͍! ͍!  ͍!vCPM3 SYS CPMLDR error: failed to open CPM3.SYS $ CPMLDR error: failed to read CPM3.SYS $ CP/M V3.0 Loader Copyright (C) 1982, Digital Research $021182"(yڥ!2(2(:(2({2(!" #"(9"@"1"!N(y2!K!!!dڛ&_^#V*("""""""""""""((("""";(""""A(G(""""""""""""""""""""""":"ž" *y!(4 5~yµ"5 6y ’" ͒":("!( Oͻ""MD"2 #>" BDOS ERR: $Select$Perm.$""" #""#"v{_zW{_zW )8## ?# w#J#J*|^#V###"(##"(######"(!( I#*(!(I#*(|!(6ʕ#67**(w#w*(w#w#w!(^#V#Fͪ#'*O##*(&%!(s#r#p*(N#F*(^#V#F*(:(O}|y$*(%#?@/ _@S.e,- ~,͒,ͭ,,,͢.:.w*.+~>8 +2.͗.>w-:.2.:._O͗.>w-y2.*. :.!,g( !T9o(!T9_( W(s#r*.:._ :9g( T9o(T9s#r:.!%9g( !T9o(!T9_( W(!/[+s#r!:.wW-T9-Ͳ- W-.t9Ͳ- ͓9>^Vͮ9z29~[+ͥ9͢.~˗##͗.~ K+ :.[+( {2.yw-:+ݦG_(x!. (4>w:.3.> ͗.wG3.x> ͭ.  w !9> ͭ. . .p.(!9> ͭ... > ͭ.:.g(!G. O !P. O(!Y. ͭ.z(.p.(*͆* *!.͆*(> >2.!.[+!.K+ >= , Drive Not Ready, Write Protected Disk !/[+^#V:+'''ݶ֯>pݶ/P/T9͑//P/ͨ/t9/͓9>^Vͮ9z29~[+ͥ9:+'''ݶ݆:+:+:+ݦ>0!9F~> /!9F~ק/0%98`     !9[+K+,,:9=29 *+9:+G,,:9=29 !/[+^#Vɧ:=#=+#*(.#}|y$#$*(%#*(DM"(**(s#r*(s#r#pyoxgk$DM*(0*MD"(!**(MD$*:(O&%!(N:( y$G>O:( ʐ$Ç$*(͒$ :(ʨ$n` ~#for$2(O͚$"(}:(O*(7#"(2("(:(O:(G2(!(w*( *($!$~2(~2($:(2($:(w:(w |g}o'% )4%:(O!3%yoxg:(O&%}*(:(o$$~w{ozg ^#V#:(ʏ%>(Û%͡%"(#ͳ#*(ç%*(r%"(!(~#O&%E:(%$N/*("(y2(ʹ%͗#ͻ%ͫ%ʛ&*(X%:(O~J&yʔ&x ʍ& ʂ&J&Í&N%J&# h&2 #G>G":&$~X%*( I#%Ow!&x&>Fwx2(2(~:(:(6:(&w2($~O %!'>w:&ͨ&$2("4%O.'5"&Ϳ&'$:(!(S'"&: #"ͮ$"$:((͛%#ͳ#%:(< #=!(wW*(M%_S# #-*(MD:%"(:(2(ɯ2('>G=O*(~~w#~2(~wc%$~'~p2(!"(>2(*(~=2('~2(͛'o'>*(w9-H-<,;,*,8L8.0=0L0L4!"(2(=2(!"(Û%͛'o'͢'͢&'(ͫ%$~<7(w@ͩ'7':(""(Û%:(~(:(2(:(~(*(6:(p(w#:(w$:(w*@"* #}D>(%$*((*(T):(_2({2("(r%"([))?#,)d)>l)[)I#6:(<!=6)*(J)"(*(K*:(G/O*((*(#=#d)##(I#*+++***N++Q+V+[+k+È+-*`+3*6*9*<*?*B*E*H*,N*Q*T*W*Z*]*`*s*1*~ʞ*O *#Ï*{**>/<Ҹ*33í*O * _ W{«**Ɛ'@'O *!+͆*:+AO *!+͆**+ͥ*!+͆**+ͥ*y2+i&)/ ~#fo{M+s*1*!~2+!~#foͅ*{*C+C+C+i`z n&s*1**+&)/~#foâ+s*1**+&)/~#fo~#fo2+ͅ*{* BIOS Error on : T-, S-+(+(y>1!* ͍! %!͍! ͍! ʢ ͏ ͕ !!~# 4 ͕  ͍!:!g:!s :!_ g:!s !]~$o #~B̩ 1!ɷW|g ͏ ͕ %z ͍! ͍!  ͍!vCPM3 SYS CPMLDR error: failed to open CPM3.SYS $ CPMLDR error: failed to read CPM3.SYS $ CP/M V3.0 Loader Copyright (C) 1982, Digital Research $021182"(yڥ!2(2(:(2({2(!" #"(9"@"1"!N(y2!K!!!dڛ&_^#V*("""""""""""""((("""";(""""A(G(""""""""""""""""""""""":"ž" *y!(4 5~yµ"5 6y ’" ͒":("!( Oͻ""MD"2 #>" BDOS ERR: $Select$Perm.$""" #""#"v{_zW{_zW )8## ?# w#J#J*|^#V###"(##"(######"(!( I#*(!(I#*(|!(6ʕ#67**(w#w*(w#w#w!(^#V#Fͪ#'*O##*(&%!(s#r#p*(N#F*(^#V#F*(:(O}|y$*(%#R? ? @, S.e,- ~,͒,ͭ,,,͢.:.w*.+~>8 +2.͗.>w-:.2.:._O͗.>w-y2.*. :.!8g( !8o(!,_( W(s#r*.:._ 8g( 8o(8s#r:.!8g( !8o(!8_( W(!/[+s#r!:.wW-8-Ͳ- W-.9Ͳ- '9>^VB9z2K9~[+99͢.~˗##͗.~ K+ :.[+( {2.yw-:+ݦG_(x!. (4>w:.3.> ͗.wG3.x> ͭ.  w !L9> ͭ. . .p.(!L9> ͭ... > ͭ.:.g(!G. O !P. O(!Y. ͭ.z(.p.(*͆* *!.͆*(> >2.!.[+!.K+ >= , Drive Not Ready, Write Protected Disk !/[+^#V:+'''ݶ֯>pݶ/P/8͑//P/ͨ/9/'9>^VB9z2K9~[+99:+'''ݶ݆:+:+:+ݦ>0!L9F~> /!L9F~ק/088`     !L9[+K+,,:K9=2K9 *+L9:+G,,:K9=2K9 !/[+^#Vɧ:=#=typ, if drvtyp lt 16 xdmap %drvtyp ;; enter previous drv into dmap cnt defl cnt+1 else if drvtyp eq nodrive xxdmap ;; enter no drv entry into dmap cnt defl cnt+1 else if (drvtyp eq f8) or (drvtyp eq f548) or (drvtyp eq f596) dmap %dno,drvtyp,%fpdno fpdno defl fpdno+1 dno defl dno+1 cnt defl cnt+1 else rep (drvty sh 8 ; ente logica drv int dmap dmap %dno,drvtyp,%hpdno dno defl dno+1 cnt defl cnt+1 endm hpdno defl hpdno+1 endif endif endif endm rept (010h-cnt) ;; fill in rest of drive map xxdmap endm dno defl 0 hpdno defl 0 fpdno defl 0 irp drvtyp, ;;-------------------------------- ;; 5.25" 48-TPI FLOPPY DISK DRIVE ;;-------------------------------- if drvtyp eq f548 dph %dno,drvtyp if frst548 eq 0ffffh fdpb548: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; dpb 10,18,24,4,2 tran596: db 1,7,13,19,25,5,11,17,23,3,9,15,21 db 2,8,14,20,26,6,12,18,24,4,10,16,22 frst596 defl 0 endif alvcsv %dno,300,32 dno defl dno+1 endif ;;---------------------- ;; 8" FLOPPY DISK DRIVE ;;---------------------- if drvtyp eq f8 dph %dno,drvtyp if frst8 eq 0ffffh fdpb8: dpb 30,26,3,7,0,242,63,16,2,1024 dpb 31,64,4,15,0,303,127,32,1,2048 dpb 32,128,4,15,0,607,255,32,1,2048 fddb8: ddb 30,%fpdno,0,0,1024,128,32,1 ddb 31,%fpdno,0,0,2048,1024,8,1 ddb 32,%fpdno,0,0,2048,1024,8,2 tran8: db 1,7,13,19,25,5,11,17,23,3,9,15,21 db 2,8,14,20,26,6,12,18,24,4,10,16,22 frst8 defl 0 endif alvcsv %dno,607,32 dno defl dno+1 endif ;;-------------------------------- ;; DMA MICRO MAGNUM 5/5 HARD DISK ;;-------------------------------- if drvtyp eq dma dph %dno dph %dno+1 dpb %dno+0,128,5,31,1,1219,511,0,1,4096 dpb %dno+1,128,5,31,1,1223,511,0,0,4096 ddb %dno+0,%hpdno,0,15,4096,256,32,2 ddb %dno+1,%hpdno,2,15,4096,256,32,2 3,7,0,81,32,16,3,1024 ;; ;;----------------------------------------------------- ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; dpb 10,18,4,15,1,40,32,16,3,2048 ;; ;;----------------------------------------------------- dpb 10,18,3,7,0,81,32,16,3,1024 dpb 11,32,4,15,0,77,63,32,1,2048 dpb 12,64,4,15,0,155,127,32,1,2048 fddb548: ;;----------------------------------------------------- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; ddb 10,%fpdno,0,0,1024,128,64,1 ;; ;;----------------------------------------------------- ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; ddb 10,%fpdno,0,0,2048,256,64,1 ;; ;;----------------------------------------------------- ddb 10,%fpdno,0,0,1024,128,64,1 ddb 11,%fpdno,0,0,2048,1024,4,1 ddb 12,%fpdno,0,0,2048,1024,4,2 tran548: ;;------------------------------------------------ alvcsv %dno+0,1219,0 alvcsv %dno+1,1223,0 dno defl dno+2 endif ;;------------------ ;; ST 503 HARD DISK ;;------------------ if drvtyp eq st503 dph %dno dpb %dno+0,128,5,31,1,607,511,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,2 alvcsv %dno+0,607,0 dno defl dno+1 endif ;;------------------ ;; ST 506 HARD DISK ;;------------------ if drvtyp eq st506 dph %dno dpb %dno+0,256,5,31,1,1215,511,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,4 alvcsv %dno+0,1215,0 dno defl dno+1 endif ;;------------------- ;; TM 601S HARD DISK ;;------------------- if drvtyp eq tm601S dph %dno dpb %dno+0,128,5,31,1,607,511,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,2 alvcsv %dno+0,607,0 dno defl dno+1 endif ;;------------------- ;; TM 602S HARD DISK ;;------------------- if drvtyp eq tm602S dph %dno dpb %dno+0,256,5,31,1,1215,511,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,4 alvcsv %dno+0,1215,0 dno defl dno+1 endif ;;------------------- ;; TM 60.xlist false equ 0 true equ not false ;;--------------- ;; DRIVE EQUATES ;;--------------- nodrive equ 00fh f548 equ 01f0h f596 equ 01f1h f8 equ 01f2h dma equ 0200h st503 equ 0101h st506 equ 0102h tm601s equ 0103h tm602s equ 0104h tm603s equ 0105h tm603se equ 0206h tm501 equ 0107h tm502 equ 0208h tm503 equ 0209h sa602 equ 010ah sa604 equ 010bh sa606 equ 010ch sa1002 equ 010dh sa1004 equ 010eh q2010 equ 010fh q2020 equ 0210h q2030 equ 0311h q2040 equ 0412h m4010 equ 0113h m4020 equ 0214h maxhst defl 0 maxusg defl 0 frst8 defl 0ffffh frst548 defl 0ffffh frst596 defl 0ffffh ;;------------------------------------ ;; MACRO - DISK PARAMETER DEFINITIONS ;;------------------------------------ dskdef macro drvstr .lall ;------------------ ; SYSTEM DRIVE MAP ;------------------ .xall hpdno defl 0 fpdno defl 0 dno defl 0 ;; logical drv no. of our drvs cnt defl 0 ;; cnt of how many entrys made drvmap: irp drv----- ;; XEROX 820, KAYPRO II SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; db 1,6,11,16,3,8,13,18,5 ;; db 10,15,2,7,12,17,4,9,14 ;; ds 8,0ffh ;; ;;----------------------------------------------------- ;; OSBORNE SINGLE DENSITY FORMAT ;;----------------------------------------------------- ;; ;; db 2,3,6,7,10,11,14,15,18,19 ;; db 4,5,8,9,12,13,16,17 ;; ds 8,0ffh ;; ;;----------------------------------------------------- db 1,6,11,16,3,8,13,18,5 db 10,15,2,7,12,17,4,9,14 ds 8,0ffh frst548 defl 0 endif alvcsv %dno,155,32 dno defl dno+1 endif ;;-------------------------------- ;; 5.25" 96-TPI FLOPPY DISK DRIVE ;;-------------------------------- if drvtyp eq f596 dph %dno,drvtyp if frst596 eq 0ffffh fdpb596: dpb 20,18,3,7,0,82,63,16,3,1024 dpb 21,32,4,15,0,150,63,32,1,2048 dpb 22,64,4,15,0,300,127,32,1,2048 fddb596: ddb 20,%fpdno,0,0,1024,128,32,1 ddb 21,%fpdno,0,0,2048,1024,4,1 ddb 22,%fpdno,0,0,2048,1093S HARD DISK ;;------------------- if drvtyp eq tm603S dph %dno dpb %dno+0,384,5,31,1,1823,1023,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,6 alvcsv %dno+0,1823,0 dno defl dno+1 endif ;;-------------------- ;; TM 603SE HARD DISK ;;-------------------- if drvtyp eq tm603SE dph %dno dph %dno+1 dpb %dno+0,384,5,31,1,2047,1023,0,1,4096 dpb %dno+1,384,5,31,1,699,511,0,172,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,6 ddb %dno+1,%hpdno,0,0,4096,512,16,6 alvcsv %dno+0,2047,0 alvcsv %dno+1,699,0 dno defl dno+2 endif ;;------------------ ;; TM 501 HARD DISK ;;------------------ if drvtyp eq tm501 dph %dno dpb %dno+0,128,5,31,1,1219,511,0,1,4096 ddb %dno+0,%hpdno,0,3,4096,512,16,2 alvcsv %dno+0,1219,0 dno defl dno+1 endif ;;------------------ ;; TM 502 HARD DISK ;;------------------ if drvtyp eq tm502 dph %dno dph %dno+1 dpb %dno+0,256,5,31,1,2047,1023,0,1,4096 dpb %dno+1,256,5,31,1,391,511,0,257,4096 ddb %dno+0,%hpdno,0,3,4096,512,16,4 ddb,1023,0,257,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,4 ddb %dno+1,%hpdno,0,0,4096,512,16,4 alvcsv %dno+0,2047,0 alvcsv %dno+1,2039,0 dno defl dno+2 endif ;;------------------------ ;; QUANTUM 2030 HARD DISK ;;------------------------ if drvtyp eq q2030 dph %dno dph %dno+1 dph %dno+2 dpb %dno+0,384,5,31,1,2047,1023,0,1,4096 dpb %dno+1,384,5,31,1,2047,1023,0,172,4096 dpb %dno+2,384,5,31,1,2031,1023,0,343,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,6 ddb %dno+1,%hpdno,0,0,4096,512,16,6 ddb %dno+2,%hpdno,0,0,4096,512,16,6 alvcsv %dno+0,2047,0 alvcsv %dno+1,2047,0 alvcsv %dno+2,2031,0 dno defl dno+3 endif ;;------------------------ ;; QUANTUM 2040 HARD DISK ;;------------------------ if drvtyp eq q2040 dph %dno dph %dno+1 dph %dno+2 dph %dno+3 dpb %dno+0,512,5,31,1,2047,1023,0,1,4096 dpb %dno+1,512,5,31,1,2047,1023,0,129,4096 dpb %dno+2,512,5,31,1,2047,1023,0,257,4096 dpb %dno+3,512,5,31,1,2031,1023,0,385,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,8 30 else db 0,pdno ; hard disk dw dph&dn,ddb&dn endif endif endif endm xdmap macro dn db 010h,dn ; other bio's drive dw 0,0 endm xxdmap macro db 0ffh,0ffh ; no drive selected dw 0ffffh,0ffffh endm ;;--------------------------- ;; MACRO - DISK HEADER BLOCK ;;--------------------------- dph macro dn,dtyp .lall ;------------------- ; DISK HEADER BLOCK ;------------------- .xall dph&dn: dw 0000 ; translation vector dw 0000 ; scratch pad 1 dw 0000 ; scratch pad 2 dw 0000 ; scratch pad 3 dw dirbuf ; dirbuf addr ifb dw dpb&dn ; dpb addr for hrd dsk else dw 0 ; dpb addr for fpy filled in dynamicly endif dw csv&dn ; directory check vector dw alv&dn ; disk allocation vector endm ;;------------------------------ ;; MACRO - DISK PARAMETER BLOCK ;;------------------------------ dpb macro dn,spt,bsh,blm,exm,dsm,drm,cks,off,bsiz .lall ;---------------------- ; DISK PARAMETER BLOCK ;----------- %dno+1,%hpdno,0,3,4096,512,16,4 alvcsv %dno+0,2047,0 alvcsv %dno+1,391,0 dno defl dno+2 endif ;;------------------ ;; TM 503 HARD DISK ;;------------------ if drvtyp eq tm503 dph %dno dph %dno+1 dpb %dno+0,384,5,31,1,2047,1023,0,1,4096 dpb %dno+1,384,5,31,1,1611,1023,0,172,4096 ddb %dno+0,%hpdno,0,3,4096,512,16,6 ddb %dno+1,%hpdno,0,3,4096,512,16,6 alvcsv %dno+0,2047,0 alvcsv %dno+1,1611,0 dno defl dno+2 endif ;;------------------ ;; SA 602 HARD DISK ;;------------------ if drvtyp eq sa602 dph %dno dpb %dno+0,128,5,31,1,635,511,0,1,4096 ddb %dno+0,%hpdno,0,3,4096,512,16,2 alvcsv %dno+0,635,0 dno defl dno+1 endif ;;------------------ ;; SA 604 HARD DISK ;;------------------ if drvtyp eq sa604 dph %dno dpb %dno+0,256,5,31,1,1271,511,0,1,4096 ddb %dno+0,%hpdno,0,3,4096,512,16,4 alvcsv %dno+0,1271,0 dno defl dno+1 endif ;;------------------ ;; SA 606 HARD DISK ;;------------------ if drvtyp eq sa606 dph %dno dpb %dno+0,384,5,ddb %dno+1,%hpdno,0,0,4096,512,16,8 ddb %dno+2,%hpdno,0,0,4096,512,16,8 ddb %dno+3,%hpdno,0,0,4096,512,16,8 alvcsv %dno+0,2047,0 alvcsv %dno+1,2047,0 alvcsv %dno+2,2047,0 alvcsv %dno+3,2031,0 dno defl dno+4 endif ;;--------------------------- ;; MINISCRIBE 4010 HARD DISK ;;--------------------------- if drvtyp eq m4010 dph %dno dpb %dno+0,128,5,31,1,1915,1023,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,2 alvcsv %dno+0,1915,0 dno defl dno+1 endif ;;--------------------------- ;; MINISCRIBE 4020 HARD DISK ;;--------------------------- if drvtyp eq m4020 dph %dno dph %dno+1 dpb %dno+0,256,5,31,1,2047,1023,0,1,4096 dpb %dno+1,256,5,31,1,1783,1023,0,257,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,4 ddb %dno+1,%hpdno,0,0,4096,512,16,4 alvcsv %dno+0,2047,0 alvcsv %dno+1,1783,0 dno defl dno+2 endif if (drvtyp eq f8) or (drvtyp eq f548) or (drvtyp eq f596) fpdno defl fpdno+1 else if drvtyp gt 15 hpdno defl hpdno+1 endif endif endm if frst----------- .xall dpb&dn: dw spt ; cpm sectors per track db bsh ; block shift factor db blm ; block mask db exm ; extent mask dw dsm ; no. blocks on drive dw drm ; no. directory entrys rsvdir dn,drm,bsiz ;;reserved directory blocks dw cks ; no. directory entries to check dw off ; track offset endm ;;------------------------------- ;; MACRO - DISK DEBLOCKING BLOCK ;;------------------------------- ddb macro dn,pd,hdoff,srate,bsiz,hsiz,hsspt,hhd .lall ;----------------------- ; DISK DEBLOCKING BLOCK ;----------------------- .xall ddb&dn: dw hsiz ; host sec size ssiz hsiz ;;sdh register sector size db pd ; physical drive no. db hdoff ; head offset (for partioning by hds) db srate ; cmd register step rate db hsspt-1 ; host sec per trk - 1 (hst sec msk) db (bsiz/hsiz)-1 ; host sec per blk - 1 (blk sec msk) shff ((hsiz/128)*hsspt) ;;calc log2 cpm spt shff (bsiz/128) ;;calc log2 cpm spb db hhd-1 ; heads - 1 shff 31,1,1907,1023,0,1,4096 ddb %dno+0,%hpdno,0,3,4096,512,16,6 alvcsv %dno+0,1907,0 dno defl dno+1 endif ;;------------------- ;; SA 1002 HARD DISK ;;------------------- if drvtyp eq sa1002 dph %dno dpb %dno+0,128,5,31,1,1019,511,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,2 alvcsv %dno+0,1019,0 dno defl dno+1 endif ;;------------------- ;; SA 1004 HARD DISK ;;------------------- if drvtyp eq sa1004 dph %dno dpb %dno+0,256,5,31,1,2039,1023,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,4 alvcsv %dno+0,2039,0 dno defl dno+1 endif ;;------------------------ ;; QUANTUM 2010 HARD DISK ;;------------------------ if drvtyp eq q2010 dph %dno dpb %dno+0,128,5,31,1,2043,1023,0,1,4096 ddb %dno+0,%hpdno,0,0,4096,512,16,2 alvcsv %dno+0,2043,0 dno defl dno+1 endif ;;------------------------ ;; QUANTUM 2020 HARD DISK ;;------------------------ if drvtyp eq q2020 dph %dno dph %dno+1 dpb %dno+0,256,5,31,1,2047,1023,0,1,4096 dpb %dno+1,256,5,31,1,20398 eq 0ffffh fdpb8: ; no 8" floppy used but need label fddb8: ; no 8" floppy used but need label tran8: ; no 8" floppy used but need label endif if frst548 eq 0ffffh fdpb548: ; no 5"-48 tpi drv used but need label fddb548: ; no 5"-48 tpi drv used but need label tran548: ; no 5"-48 tpi drv used but need label endif if frst596 eq 0ffffh fdpb596: ; no 5"-96 tpi drv used but need label fddb596: ; no 5"-96 tpi drv used but need label tran596: ; no 5"=96 tpi drv used but need label endif hstbuf: ds maxhst ; maximum host buffer size usgblk: ds maxusg ; maximum # host sectors / block dirbuf: ds 128d ; cp/m directory buffer storage endm ;;------------------- ;; MACRO - DRIVE MAP ;;------------------- dmap macro dn,drvtyp,pdno if drvtyp eq f548 db 1,pdno ; 5" - 48 tpi floppy dw dph&dn,ddb&10 else if drvtyp eq f596 db 2,pdno ; 5" - 96 tpi floppy dw dph&dn,ddb&20 else if drvtyp eq f8 db 3,pdno ; 8" floppy dw dph&dn,ddb&9(hsiz/128) ;;calc log2 cpm sps db (hsiz/128)-1 ; cpm sps - 1 if hsiz gt maxhst maxhst defl hsiz endif if (bsiz/hsiz) gt maxusg maxusg defl (bsiz/hsiz) endif endm ;;-------------------------------------- ;; MACRO - COMPUTE ALV AND CSV BUF SIZE ;;-------------------------------------- alvcsv macro dn,dsm,cks .lall ;--------------------------------------- ; DRIVE ALLOCATION AND CHECK SUM VECTOR ;--------------------------------------- .xall alv&dn: ds (dsm/8)+1 ; drive block allocation vector csv&dn: ds cks ; drive directory check vector endm ;;-------------------------------------- ;; MACRO - COMPUTE NO. DIRECTORY BLOCKS ;;-------------------------------------- rsvdir macro dn,drm,bsiz x defl ((drm+1)/(bsiz/32)) y defl 080h done defl 0 al0&dn defl 0 al1&dn defl 0 rept 8 if x eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 done defl 0ffh exitm endif al0&dn defl al0&dn or y y defl y sh track $ sector $ side $ drive $ $~un errorCan't recognize density of disk in$Read$Write$Seek$ error on3ͱ,USPS* |} !9":!"<<2* ͞ !~5 * ͡S ͤ1zi` n&?@/ _      y24y27Y 5"@~G:>G~ > 2<:4O y~ 8 q *@~(͙8ͺ{ͣ:72:>2>2?7O> 2<> :?G /_~(!& *1::{  _ O(  :<= L{((glrZwZ:4hZ::hZ:>hZZ>2< ~ ( w:728F8 <2:y2>:7W:0*3K5B(7:8Gz?"B*3"5:7G28xG![120G!> z:(8 DZP>w(>>w~un errorCan't recognize density of disk in$Read$Write$Seek$ error onr 1 x defl x-1 endm y defl 080h if done eq 0 rept 8 if x eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 done defl 0ffh exitm endif al1&dn defl al1&dn or y y defl y shr 1 x defl x-1 endm endif if done eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 endif endm ;;----------------------------------- ;; MACRO - COMPUTE DRIVE SECTOR SIZE ;;----------------------------------- ssiz macro secsiz if secsiz eq 128 db 060h ; sdh reg sec siz 060 = 128 bps else if secsiz eq 512 db 020h ; sdh reg sec siz 020 = 512 bps else if secsiz eq 256 db 000h ; sdh reg sec siz 000 = 256 bps else db 000h endif endif endif endm ;;------------------------------ ;; MACRO - COMPUTE SHIFT FACTOR ;;------------------------------ shff macro num @y defl num @x defl 0 rept 8 if @y eq 1 db @x ; log2 (num) exitm endif @y defl @y s>o:~W!{> " OC > S>O32/=Y+2-=Y+U G+ G+ $ :+~@w,U ,+>2-=>1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!' #"* (,*#"+))[R%! !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!'  |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 ͘!4͘ !͙>O3F#Nů  SYSm-x¯*C=-#~: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file Chr 1 @x defl @x + 1 endm endm .list LODRBIOSMACLODRBIOSMACSBCBOOT MACSBCDBOOTMACSBCHBOOTMACC3BGEN DATC3BGEN SUBC3BLINK SUBC3GEN DATC3GEN SUBC3LINK SUBC3LLINK SUBC3MAC SUBC3SYS SUBFMT548 COMFMT596 COMFMT8 COMFMTHD COMLDRGEN COM OSLOAD48SYS;OSLOAD8 SYS<OSLOAD96SYS;SUPRBIOSLIBSUPRBIOSLIB3>L~~ÃG3x(OxAG:>G~ > 2<:4O y~ 8 q *@~(͙8ͺ{ͣ:72:>2>2?7O> 2<> :?G /_~(!& *1::{  _ O(  :<= L{((glrZwZ:4hZ::hZ:>hZZ>2< ~ ( w:728F8 <2:y2>:7W:0*3K5B(7:8Gz?"B*3"5:7G28xG![120G!> z:(8 DZP>w(>>w~un errorCan't recognize density of disk in$Read$Write$Seek$ error on:>o:~W!{> " OC > S>O32/=Y+2-=Y+U G+ G+ $ :+~@w,U ,+>2-=>1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!' #"* (,*#"+))[R%! !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!'  |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 ͘!4͘ !͙>O3F#Nů  SYSm-x¯*C=-#~: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file C38=ÂB>V>a>ozi` n&VaoGVx(OxAG:G:~ > 2:O y~ 8 q *~($d8̈́FͶ2:2::2>2>27U> 2> :G /_~(!y*:{  _ U(  := >2 ~ ( w:2F8 <2y2:W::G:(7:Gz?G![G!y> z͗22>wɷw/:}:Gz >** {zҝ*~#" 2x:U<{͉2 5 !äͤAOHL(HL)CʹA  ld a,(@ctbl+15) ; set baud according to values in tbl cp 10 ; jr nc,gt2000b ; dec a ; gt2000b: sla a ; left justity baud rate for device 1 sla a ; dev 1 maps to sio ch b sla a ; dev 1 baud setting for port is b7-4 sla a ; must set both at once so dont clobber or c ; or in dev 0 baud setting out (baudc),a ; send dev 0,1 baud to baud ctrl port ret cseg ;------------------------ ; CHARACTER DEVICE INPUT ;------------------------ ci?:: ld a,b ; put dev. no. in a-reg cp 2 ; check if dev. 0 or 1 jr c,ciwait ; jump if dev. no. 0 or 1 ld a,01ah ; return ctrl-z if bad input dev. ret ciwait: call cist? ; get device input status jr z,ciwait ; sets zero flag if no RxCA ld a,b ; put device no. in a and a ; check if device 0 or 1 jr nz,siobin ; jump if device 1. sioain: di ; no interupts while using bf ptrs ld de,(outptri) ; d-reg = inptri, e-reg = outptri ld d,0 ; de-reg = outptri, ofset to nx chr out 38=ÂB>V>a>ozi` n&VaoGVx(OxAG:G:~ > 2:O y~ 8 q *~($d8̈́FͶ2:2::2>2>27U> 2> :G /_~(!y*:{  _ U(  := >2 ~ ( w:2F8 <2y2:W::G:(7:Gz?G![G!y> z͗22>w.SYS f}:Gz >** {zҝ*~#" 2x:U<{͉2 5 !äͤAOHL(HL)CʹA  title CHARACTER I/O DRIVERS -- CP/M 3.0 -- BANKED / NON-BANKED .z80 MACLIB MODEBAUD.LIB ;----------------- ; BAUD RATE PORTS ;----------------- baudd equ 015h baudc equ 018h ;------------------- ; SIO CONTROL PORTS ;------------------- sioad equ 000h sioac equ 001h siobd equ 002h siobc equ 003h ;------------------- ; PIO CONTROL PORTS ;------------------- pioad equ 004h pioac equ 006h piobd equ 005h piobc equ 007h inbfsz equ 032d cseg ;-------------------------------- ; CHARACTER DEVICE INITALIZATION ;-------------------------------- cinit?:: ld a,c ; put device no in a-reg for compare cp 2 ; check if parallel device ret z ; no baud for parallel ld hl,frstint ; check if first time initalization xor a ; set flag to show already done once cp (hl) ; frstinit = 0ff if first time jr z,setbaud ; jump if not first time through ;-------------------------------------- ; SET @CTBL TO ON-BOARD SWITCH SETTING ;---------------------- l hl,inpbuf ; get base addr of console i/o buffer add hl,de ; add offset of nx chr out to bf addr ld a,e ; put outptri into a-reg inc a ; inc to next chr to send and inbfsz-1 ; mask offset for wrap around ld (outptri),a ; save offset for next time around ld a,(hl) ; pass cp/m char in a-reg ei ; interupts ok now ret siobin: in a,(siobd) ; pull char fm sio ch. b bf to a-reg ;dumb shits and 07fh ; mask parity off ret ;------------------------- ; CHARACTER DEVICE OUTPUT ;------------------------- co?:: ld D,C ; save character to output cowait: call cost? ; get out rdy / busy status of device and a ; set zero flag on value returned jr z,cowait ; loop until device ready ld a,b ; put device no. in a-reg cp 2 ; check if parallel printer jr z,lstout ; jump to printer out w. char in d-reg sioout: add a,a ; double device no. so it is 0 or 2 ld c,a ; this is the sio data port we want out (c),d ; send character ret >o:~W!{> " OC > S>O32/=Y+2-=Y+U G+ G+ $ :+~@w,U ,+>2-=>1! >2|N#Fx2CN#FC$#^#V^#VS#~2#~2<2###~2#^#VSN#FCC*KB0KC:( [0!' #"* (,*#"+))[R%! !!Cy͏qput+[[R8 uty7?R#|(/ sr +utwwNFqpnf^:(#~W#:G)[7?K R0! !=NFx(ENF C$7?KnfB8C[0MD!'  |:o!=!NFnfB#>,(0W}_nfRut=RDM!C76! [36:G6!w0 ͘!4͘ !͙>O3F#Nů  SYSm-x¯*C=-#~: Which .SYS file to load 0 = CPM 1 = OSLOAD ? SelectReadFile not found error: file C---------------- initbaud: ld (hl),a ; set frstinit flag to 0 for next time isioabd: in a,(baudd) ; read baud switch settings from board and 00fh ; mask for sioa baud rate setting cp 10 ; check if board is set for < 2400 baud jr nc,gt2000 ; if < 2400 then need to adjust for tbl inc a ; cp/m 3 does not support baud 2000 gt2000: ld (@ctbl+7),a ; save it in character device table isiobbd: in a,(baudd) ; read baud switch settings and 070h ; only 3-bits for sio b baud rate srl a ; right justify nibble srl a ; 3 bits means switch setting is 0-7 srl a ; cp/m 3 supports baud settings 1-15 srl a ; finish justification inc a ; adjust switch setting for cp/m ld (@ctbl+15),a ; save baud rate in dev 1 baud entry ret ;---------------------------------- ; SET BAUD RATE TO @CTBL SETTING ;---------------------------------- setbaud: ld a,(@ctbl+7) ; second or more times through cp 10 ; jr nc,gt2000a ; dec a ; gt2000a: ld c,a ; : lstout: ld a,d ; put char to send into a-reg out (pioad),a ; send char to pio ch. a data port ld a,080h ; set strobe high, then low out (piobd),a ; strobe printer via pio ch. b xor a ; set strobe low to latch data out (piobd),a ; pio latches on strobe's falling edge ret ;------------------------------- ; CHARACTER DEVICE INPUT STATUS ;------------------------------- cist?:: ld a,b ; put device no in a-reg cp 1 ; check if 0,1 or 2 jr c,sioaist ; jump if dev.0 to sio ch. a status jr z,siobist ; jump if dev.1 to sio ch. b status pioist: xor a ; ret if par dev or bad dev (no in. st) ret sioaist: ld hl,(outptri) ; h-reg = inptri, l-reg = outptri ld a,h ; intptri is bf offset to nx chr in sub l ; outptri is bf offset to nx chr out ret z ; if intptri = outptri then no chr ld a,0ffh ; let cp/m know char available ret siobist: in a,(siobc) ; poll sio ch. b for char available and 1 ; get stat and check RxCA ret z  frstint:db 0ffh outptri:db 0 ; bf offset to next char out to cp/m inptri: db 0 ; bf offset to next char in from sio inpbuf: ds inbfsz ; console i/o buffer ;---------------------------- ; CHARACTER I/O DEVICE TABLE ;---------------------------- @CTBL:: db 'CRT ' db mb$in$out+mb$serial+mb$soft$baud db baud$none db 'MODEM ' db mb$in$out+mb$serial+mb$soft$baud db baud$none db 'PARLPT' db mb$output db baud$none db 0 end ssues interupts ld hl,ctcvec ; addr of ctc svc in inter table ld a,l ; need only the low byte of addr out (ctc0),a ; better be on a 8-byte block boundry ; ie. lower 3-bits =0 ; sio initialization ld hl,isioa ld bc,isioal*256+sioac otir ld hl,isiob ld bc,isiobl*256+siobc otir ; pio initialization ld a,0fh ; use both pio ch A & B w. parallel lst out (pioac),a ; pio ch A is output mode ld a,0cfh ; pio ch b is bit mode out (piobc),a ; channel b has r/w) @MIN equ scb$base+5Bh ; Minute in BCD (byte, r/w) @SEC equ scb$base+5Ch ; Second in BCD (byte, r/w) ?ERJMP equ scb$base+5Fh ; BDOS Error Message Jump ; (word, r/w) @MXTPA equ scb$base+62h ; Top of User TPA ; (address at 6,7)(word, r/o) end  d:2*"!]?!e?~#XXXXXXXXYYYou enter the PUT CONSOLE or PUT PRINTER command. ///2Options [ {ECHO | NO ECHO} {FILTER | NO FILTER} | {SYSTEM} ] ECHO specifies that output is echoed to the console. This is the default option when you direct console output to a file. NO ECHO specifies that file output is not echoed to the ; return if no character available ld a,0ffh ; let cp/m know char available ret ;-------------------------------- ; CHARACTER DEVICE OUTPUT STATUS ;-------------------------------- cost?:: ld A,B ; move relative device no. to a-reg cp 2 ; check if parallel printer jr nz,sioost ; jump to serial status if not parallel lstost: in A,(piobd) ; get pio status and 1 ; busy = 0, not busy = 1 ret z ; if prn busy, return with a-reg = 0 l A,0ffh ; prn not busy, return with a-reg = 0ff ret sioost: add a,a ; double dev. no to 0 or 2 inc a ; increment dev no. to 1 or 3 ld c,a ; this is the sio control port ld a,010h ; send reset ext/status intr to wr0 out (c),a ; must do reset if DCD to be valid in a,(c) ; get sio staus and 004h ; check TxBE cp 004h ; set z-flg if TxBE ld a,0ffh ; prepare for return w. ok to send flg ret z ; return if sio ready w. a-reg = 0ffh cpl ; else sio not ready, return 0 ret ;---------------- title 'System Control Block Definition for CP/M3 BIOS' public @civec, @covec, @aivec, @aovec, @lovec, @bnkbf public @crdma, @crdsk, @vinfo, @resel, @fx, @usrcd public @mltio, @ermde, @erdsk, @media, @bflgs public @date, @hour, @min, @sec, ?erjmp, @mxtpa scb$base equ 0FE00H ; Base of the SCB @CIVEC equ scb$base+22h ; Console Input Redirection ; Vector (word, r/w) @COVEC equ scb$base+24h ; Console Output Redirection ; Vector (word, r/w) @AIVEC equ scb$base+26h ; Auxiliary Input Redirection ; Vector (word, r/w) @AOVEC equ scb$base+28h ; Auxiliary Output Redirection ; Vector (word, r/w) @LOVEC equ scb$base+2Ah ; List Output Redirection ; Vector (word, r/w) @BNKBF equ scb$base+35h ; Address of 128 Byte Buffer ; for Banked B ;get id side byte cp 1 ;is it head 1 jr nz,..ntsd1 ;skip if not ld a,(dsrsav) ;get saved drive select register xor c ;compare side one/two densities and 1 shl ddd jr nz,..ntsd1 ;if densities different, continue ld a,(ridbuf+3) ;get sector size xor c ;compare side one/two sector sizes and 3 jr nz,..ntsd1 ;if sizes different, continue set tsd,c ;else, set two sided disk bit ..ntsd1: call getdta ;get drive table address ld a,(hl) ;get drive table value and 1 shl mini or 1 shl tpi96 ;extract relevant bits or c ;combine with disk type code ld c,a ;disk type code to c-reg ld de,dstbls## ;get dst table base ..dstl: ld hl,dtco## ;get offset to disk type code add hl,de ;calc disk type code address ld a,c ;get disk type code cp (hl) ;dst type code match? ex de,hl ;dst address to hl-reg jr z,..dstf ;if dst found, continue ld e,(hl) ;else, get next dst address inc hl ld d,(hl) ld a,d or e ;end of dst chain? jr nz,..dstl ;if n-------------------- ; SIO CH. A INTERUPT SERVICE ROUTINE ;------------------------------------ sioasvc:: ld (ssp##),sp ; save system stack pointer ld sp,istk## ; user interupt stack call save## ; save registers af,bc,de,hl ld hl,(outptri) ; h = inptri, l = outptri ld a,h ; put offset to nx bf in in a-reg inc a and inbfsz-1 cp l ; chk if nx in = nx out j nz,rxchr ; jump i roo fo more ciobo: in a,(sioad) ; cio buffer overflow, clear input port xor a ; clear channel no. ld c,007h ; ascii char code for ctrl-g (bell) call co? ; send bell to sio ch. a ret ; return to --> return from interupt rxchr: ld (inptri),a ld e,h ; put inptri into e-reg ld d,0 ; zero d-reg for double add ld hl,inpbuf ; get base addr of bf add hl,de ; point nx available addr in bf in a,(sioad) ; get input char from sio and 07fh ; mask out parity ld (hl),a ; save char in cio buffer ret ;-------------- ; DATA STORAGE ;-------------- IOS (word, r/o) @CRDMA equ scb$base+3Ch ; Current DMA Address ; (word, r/o) @CRDSK equ scb$base+3Eh ; Current Disk (byte, r/o) @VINFO equ scb$base+3Fh ; BDOS Variable "INFO" ; (word, r/o) @RESEL equ scb$base+41h ; FCB Flag (byte, r/o) @FX equ scb$base+43h ; BDOS Function for Error ; Messages (byte, r/o) @USRCD equ scb$base+44h ; Current User Code (byte, r/o) @MLTIO equ scb$base+4Ah ; Current Multi-Sector Count ; (byte,r/w) @ERMDE equ scb$base+4Bh ; BDOS Error Mode (byte, r/o) @ERDSK equ scb$base+51h ; BDOS Error Disk (byte,r/o) @MEDIA equ scb$base+54h ; Set by BIOS to indicate ; open door (byte,r/w) @BFLGS equ scb$base+57h ; BDOS Message Size Flag (byte,r/o) @DATE equ scb$base+58h ; Date in Days Since 1 Jan 78 ; (word, r/w) @HOUR equ scb$base+5Ah ; Hour in BCD (byte, ; title HARD DISK DRIVER -- CP/M 3.0 -- BANKED / NON-BANKED .z80 ; Zilog mneumonics used ;------------------------------------ ; HDC-1001 CONTROLLER PORT ADDRESSES ;------------------------------------ hbase equ 0e0h ; base port address of hdc-1001 hdata equ hbase+0 ; data register herror equ hbase+1 ; error register hwrtpre equ hbase+1 ; write pre-compensation register hseccnt equ hbase+2 ; sector count register hsec equ hbase+3 ; sector number register hcyllow equ hbase+4 ; cylinder low register hcylhi equ hbase+5 ; cylinder high register hsdh equ hbase+6 ; size - drive - head register hstatus equ hbase+7 ; status register port hcmd equ hbase+7 ; command register port ;------------------- ; HDC-1001 COMMANDS ;------------------- cmdsek equ 070h ; seek command @ step rate 0 cmdrd equ 020h ; read sector command cmdwrt equ 030h ; write sector command sdhreg equ 0a0h ; sdh reg setting -- 512 bytes/sector ;---------------------------------- out (hcylhi),a ; send to cyl high ret ;--------------------------- ; WRITE SECTOR TO HARD DISK ;--------------------------- hwrtsec: ld a,cmdwrt out (hcmd),a ld hl,diskbf## ld bc,hdata ; 0 to b, data port adr to c otir otir ret ;---------------------------- ; READ SECTOR FROM HARD DISK ;---------------------------- hrdsec: ld a,cmdrd out (hcmd),a call polbsy ld hl,diskbf## ld bc,hdata ; 0 to b, data port to c inir inir ret ;--------------------- ; POLL BUSY HARD DISK ;--------------------- polbsy: in a,(hstatus) ; read status port and a ; set flags jp m,polbsy ; loop if busy bit set and errbit ; mask for error bit ret end  2,6,10,14,18,22,26,4,8,12,16,20,24 ;------------- ; Disk buffer ;------------- dseg diskbf: ds 1024,0 end ~dr xlthi equ 1 mf equ 11 ;media flag dpblo equ 12 ;dpb adr dpbhi equ dpblo+1 rdsd equ 25 ;raw dsd track equ 26 ;track adr frstr equ 27 ;floppy restore cmd fsek equ 28 ;floppy seek cmd fseeknv equ 29 ;floppy seek, no verify cmd fdpblo equ 30 ;first dpb adr fdpbhi equ fdpblo+1 tdsd equ 32 ;the dsd to use -- pdsd+@rdrv ;drive type equates dtyp548 equ 1 ;5" 48 tpi dtyp596 equ 2 ;5" 96 tpi dtyp8 equ 3 ;8" page ;------------------- ; DPB index equates ;------------------- spt equ 0 bsh equ 2 blm equ 3 exm equ 4 dsm equ 5 drm equ 7 al0 equ 9 al1 equ 10 cks equ 11 off equ 13 psh equ 15 psm equ 16 hspt equ 17 ;host sectors/track (one side only) hlspps equ 18 ;host logical sectors/physical sector pdsd equ 19 ;primary dsd denb equ 20 ;base tk density -- 0=s, 1=d denn equ denb+1 ;next tk density side equ denb+2 ;side byte -- 0 or 1 seclen equ denb+3 ;sector len byte -- 0=128,1=256,3=1024 txltlo equ 24---- ; HDC-1001 STATUS REGISTER BIT TESTERS ;-------------------------------------- bsybit equ 080h ; busy bit rdybit equ 040h ; data request bit errbit equ 001h ; error bit ;----------------------- ; Disk specific equates ;----------------------- secsize equ 512 ; physical sector size sectrk equ 17 ; physical sectors/track hlspps equ 4 ; host logical sectors/physical sector dseg ;--------------------- ; INITALIZE HARD DISK ;--------------------- hinit:: ld a,sdhreg ; drive 0 & sector size out (hsdh),a ; send it to controller xor a ; zero a-reg out (hcyllow),a ; reset cylinder low register out (hcylhi),a ; reset cylinder high register ld a,cmdsek ; load a-reg w. seek command out (hcmd),a ; seek cylinder 000 @ correct step rate call polbsy ; wait until ctrl done exec seek cmd hinil: in a,(hstatus) and 10h ; seek complete? jr z,hinil ; no, loop ret ;----------------- ; LOGIN HARD DISK ;----------------- hlogin:: title FLOPPY DISK DRIVER -- CP/M 3.0 -- BANKED / NON-BANKED .z80 include CONFIG.LIB global finit, flogin, fwrite, fread ext @adrv, @rdrv, @sect, @trk ext xfercnt,getdata,putdata,diskbf ext pderr?, pmsg?, conin? if media_check_en global dskerr, delay, fseekntst global cdsd, lastdrv ext chek_media, chk_last, chk_mchng ext @media, cdph, fdbusy, char_save dsk_chng equ 15h ;Disk change port (Bit 7 = 1 is chng) dsk_chng_msk equ 80h ;Disk change bit mflag equ 0ffh ;changed media flag endif page 60 ;---------------------------------- ; FLOPPY CONTROLLER PORT ADDRESSES ;---------------------------------- fbase equ 0ch ; base port addr of wd-1793 or wd-2793 fcmd equ fbase+0 ; command register fstat equ fbase+0 ; status register ftrk equ fbase+1 ; track register fsec equ fbase+2 ; sector register fdata equ fbase+3 ; data register fwait equ 014h ; wait register fdsd equ 014h ; density - size - drive register ;----------------------------  ;the xlt table adr, or 0 if none -- txlthi equ txltlo+1 ; Note: adr must be >= 0100h ndpblo equ 26 ;next dpb adr, or 0 if none ndpbhi equ ndpblo+1 page dseg ;------------------------- ; INITALIZE FLOPPY DRIVES ;------------------------- finit: if media_check_en ld a,3 ;kill pending disk change flag on 0 out (fdsd),a endif ret ;-------------------- ; LOGIN FLOPPY DRIVE ;-------------------- flogin: call gitxy ld a,(@rdrv) ;form first dsd or (ix+rdsd) ld (cdsd),a out (fdsd),a call frestore ;home it jr nz,flogerr ;jump if user abort if base_track ;(not equal 0) ld a,base_track call fstep endif ld a,base_track call getden ;get density of base track jr nz,flogerr ld (dentkb),a ld a,base_track+1 call fstep ld a,base_track+1 call getden ;get density of next track jr nz,flogerr ld (dentkn),a page ld a,(diskbf+sdno) ;get next tk side byte ld (sdbit),a ld a,(diskbf+sdlen) ;get next tk sector len byte ret ;----------------- ; WRITE HARD DISK ;----------------- hwrite:: call hsettsk ; set up hdc1001 ctrler registers call getdata## call hwrtsec call polbsy ret ;---------------- ; READ HARD DISK ;---------------- hread:: call hsettsk ; first set up controller registers call hrdsec call putdata## ; call polbsy ; check for errors ret ;-------------------- ; SET TASK HARD DISK ;-------------------- hsettsk: ld a,hlspps ld (xfercnt##),a ; set # of logical sectors/phys sector ld a,sdhreg ; sdh proto byte ld hl,(@sect##) ld de,sectrk hsloop: or a ; divide modulo sectors/track sbc hl,de jp m,hsend inc a ; add a head bit to sdh jp hsloop hsend: add hl,de ;l = sector #, a = sdh w/head bits out (hsdh),a ; load siz drv hd register ld a,l out (hsec),a ; send to sector register ld a,(@trk##) ; move lsb to a-reg for out inst out (hcyllow),a ; send low byte to cyllow reg ld a,(@trk##+1) ; move msb to a-reg  ; FLOPPY CONTROLLER COMMANDS ;---------------------------- frd equ 084h ; read sector fwrt equ 0a4h ; write sector frdadr equ 0c4h ; read address fint equ 0d0h ; force interrupt ;------------------------------- ; FLOPPY CONTROLLER BIT TESTERS ;------------------------------- dnrdy equ 10000000b ;Drive not ready bit rnf equ 00010000b ;Record not found homed equ 00000100b ;at track 0 ;dsd equates dsd_drv_msk equ 00000011b ;0 = A:, 1 = B:, 2 = C:, 3 = D: dsd_hed_msk equ 00000100b ;0 = h0, 1 = h1 dsd_den_msk equ 00001000b ;0 = sd, 1 = dd dsd_siz_msk equ 00010000b ;0 = 8", 1 = 5" ;read address data pointer equates tkno equ 0 ;track # -- 0 to 76 sdno equ 1 ;side # (0 or 1) sdlen equ 3 ;sector len -- 0,1,2,3 ;misc floppy equates rtrys equ 10 ;# of retrys dsk_io_err equ 1 ;disk io error flag dsk_ro equ 2 ;disk ro flag page ;------------- ;xdph equates ;------------- ;indexes dtype equ -1 ;drive type code xltlo equ 0 ;skew table a; ld (slen),a ld l,(ix+fdpblo) ;get first dpb ld h,(ix+fdpbhi) fndlop: push hl ;install trial dpb pop iy ld de,denb ;point to dbp disk data set add hl,de ld de,sbase ;point to derived disk data set ld b,4 fcplop: ld a,(de) cp (hl) jr nz,fnofnd ;abort -- no match on this one inc hl inc de djnz fcplop push iy ;install true dpb adr pop hl ld (ix+dpblo),l ld (ix+dpbhi),h ld l,(iy+txltlo) ;install true xlate adr ld h,(iy+txlthi) ld (ix+xltlo),l ld (ix+xlthi),h ld (ix+track),base_track+1 ;set initial track # ld a,(@rdrv) ;install tdsd or (iy+pdsd) ld (ix+tdsd),a jp fexit page fnofnd: ld l,(iy+ndpblo) ;get next dpb adr ld h,(iy+ndpbhi) ld a,l or h ;is there a next dpb? jp nz,fndlop ;yes, jump flogerr: call fexit pop hl ;get return pop de ;throw away old dph adr ld de,0 push de ;say no drive jp (hl) ;return page ; Get disk density -- density found by using read adr command geunt ;Common exit for disk routines fexit: ld ix,(ixsave) ld iy,(iysave) if media_check_en ld hl,fdbusy ; allow media change detect ld (hl),0 endif ret page ;---------------------- ; SET TASK FLOPPY DISK ;---------------------- fsettsk: ld a,(iy+hlspps) ; logical sectors/physical sector ld (xfercnt),a ; -- as logical sector xfer count ld a,(@sect) ; raw sector # ld b,a ld a,(ix+xlthi) or a ; xlate table? jp nz,isxlt ; yes, jump inc b ; compensate unskewed sector # isxlt: if two_sides ld c,0 ; set for side 0 ld a,b sub (iy+hspt) ; side 0 or 1? jp z,issd0 ; jump if side 0 jp m,issd0 ; jump if side 0 ld c,dsd_hed_msk ; set for side 1 ld b,a ; side 1 sector # issd0: endif ld a,b ; get correct sector # out (fsec),a ; send it to fpy controller sec reg ld a,(ix+tdsd) ; get dsd if two_sides or c ; or hd sel w. den, size, and drv no. endif ld (cdsd),a ; save current dsd setting out (fdsd),a ; send t to floppy controller call tstrdy ; test it drive is ready ret nz ; return if user abort frestnt: ld a,(ix+frstr) ; load floppy restore at proper stp rte out (fcmd),a ; send restore command call delay in a,(fwait) ; wait until command finished executing xor a ; clear zero-flag, used as error flag ret ;--------------------- ; SEEK TRACK IN A-REG ;--------------------- fseek: ld b,a ; track to seek passed in a-reg call tstrdy ; wait for drive to become ready ret nz ; return w nz-flay set if user abort ld a,b ; move trk no bk to a, (tstrdy uses a) fseekntst: out (fdata),a ; load trk to sek into data register ld a,(ix+fsek) ; load a-reg w seek cmd out (fcmd),a ; tell controller to seek the track call delay ; must delay 28 us before reading stat in a,(fwait) ; wait until done with seek in a,(fstat) ; read floppy status register and 018h ; check for crc and/or seek error ret page ;-------------------------- ; WRITE tden: ld (tkwant),a or 1 call chkdn call nz,chkdn call nz,chkdn call nz,chkdn ret chkdn: call nz,chksngl call nz,chkdbl call nz,chksngl call nz,chkdbl ret chksngl: xor a ;return code -- sngl den ld b,a ;spec single den jr chkdnc chkdbl: ld a,1 ;return code -- dbl den ld b,dsd_den_msk ;spec double den chkdnc: push af ;save return code (0 or 1) ld a,(cdsd) ;set up dsd and not dsd_den_msk or b ld (cdsd),a out (fdsd),a call xdelay ld hl,diskbf ;ini params ld c,fdata di ;start read adr ld a,frdadr out (fcmd),a call delay page fradlp: ;read in 6 bytes (or try) in a,(fwait) or a jp p,fradout ini jr fradlp fradout: in a,(fstat) or a ;good address read? ei jr nz,frail ;no, jump ld a,(tkwant) ld b,a ld a,(diskbf+tkno) cp b ;on proper track? jp z,frail ;yes, jump call frestnt ;restore to track 0 ld a,(tkwant) ;seek wanted track call fstep or 1 ;set fail status frit to floppy controller reg if media_check_en call chek_media ; media change or drive not ready? ret nz ; yes, return (A reg = 0ffh or 01) endif page ld a,(ix+track) ; get track no. where head positioned out (ftrk),a ; set trk reg to current hd position ld bc,(@trk) ; get new track to seek ld de,(@adrv) ; get drive to do this seek on cp c ; compare w track heads positioned on jr nz,diftrk ; if different, do seek to reload heads ld a,(lastdrv) ; get last drive seek done on cp e ; compare last drive with current drive ret z ; if same, then same drive and track diftrk: ld a,e ; save new drive as old drive ld (lastdrv),a ; this will mak sure we ld hds if need if media_check_en ld (cdph),ix ; save dph endif ld a,c ; save new track ld (ix+track),a ; save it in trk vec as new hd position call fseek ; position heads over new track xor a ; flag success ret page ;-------------------- ; FLOPPY ERROR CHECK ;--------------------A SECTOR TO FLOPPY ;-------------------------- fwrtsec: in a,(fstat) ; first check if write protected bit 6,a ; if bit 6 of stat =1, then protected jr nz,wrtpro ; tell user if protected ld hl,diskbf ; source starting address ld c,fdata di ; dont want to be intr or will lose dta ld a,fwrt ; start write by sending command out (fcmd),a ; tell ctrler to wrt sec call delay ; mak sure wait 28 us before stat rd fwrtlp: in a,(fwait) ; check if in floppy interupt or a ; interupt is bit 7 of fwait, 0=active jp p,fwrtout ; if zero then no more data 1=nactive outi ; else send dta, inc buf addr jr fwrtlp ; loop until done fwrtout: in a,(fstat) ; read status for errors and a ; set nz flg if no errors ei ; enable console interupts ret wrtpro: ld de,wprtmsg ; pass write prot msg in de to dskerr call dskerr ; call rout to prn msg and wait for cio jr z,fwrtsec ; try again if user didnt type ctrl-c ld a,dsk_ro ; flag disk r/o scf ail: pop bc ;load return code ld a,b ret ;z status if all ok ; Step disk to requested track -- no verify fstep: out (fdata),a ;track to step to ld a,(ix+fseeknv) ;seek no verify out (fcmd),a call delay in a,(fwait) ;wait 'til done jp xdelay page ;------------------- ; WRITE FLOPPY DISK ;------------------- fwrite: call gitxy fwerr: call fsettsk ; set up cntr reg & gen housekeeping jr nz,fexit ; exit if failed to set up call getdata call fwrtsec ; write sector to floppy jr c,fexit ; jump if read-only call errchk ; check floppy cntr status for errors jr nz,fwerr ; loop if error jr fexit ;------------------ ; READ FLOPPY DISK ;------------------ fread: call gitxy frerr: call fsettsk ; set controller reg & do housekeeping jr nz,fexit ; exit if failed to set up call frdsec ; read a sector from floppy call putdata call errchk ; chk status for errors jr nz,frerr ; loop if error and under retry co errchk: ld hl,rtcnt in a,(fstat) and a ;any errors: jr z,errx ;no, jump inc (hl) if media_check_en ld a,1 cp (hl) ;first retry? jp z,errm ;yes, jump endif ld a,5 cp (hl) ;fifth retry? jp nz,erry ;no, jump ;try reseek ld a,(ix+frstr) ; load floppy restore at proper stp rte out (fcmd),a ; send restore command call delay in a,(fwait) ; wait until command finished executing call delay ld a,(@trk) call fseekntst ;seek proper track if media_check_en jp z,erry ;jump if no errors on seek errm: call chk_mchng ;see if new density (new media) ret z ;return if new density endif erry: ld a,rtrys cp (hl) ;nz means try again ld a,dsk_io_err ;disk io error flag ret errx: ld (hl),a ; clear retry cnt in case had to retry ret ; return w. no errors page ;---------------------- ; RESTORE FLOPPY HEADS ;---------------------- frestore: ld a,(cdsd) ; get physical drive to do restore on out (fdsd),a ; send i< ; flag r/o for return ret page ;--------------------------- ; READ A SECTOR FROM FLOPPY ;--------------------------- frdsec: ld hl,diskbf ; source starting address ld c,fdata di ; disable console interupts ld a,frd ; start read by sending command out (fcmd),a ; tell ctrler to read sector call delay ; mak sure wait 28 us before rding stat frdlp: in a,(fwait) ; wait until ctrler rdy to snd dta or a ; check if interupt active jp p,frdout ; if bit 7 =0, then inter active ini ; else rd dta, increment buff addr jr frdlp ; loop until interupt =0 frdout: in a,(fstat) ; check for any errors and a ; set nz-flag if errors ei ; enable cnsole interupts ret page ;------------------------------- ; TEST IF FLOPPY DRIVE IS READY ;------------------------------- tstrdy: ld de,0ffffh ; set up time out counter ld a,fint ; reset floppy controller out (fcmd),a ; set status reg to current state call delay ; must delay before 801CD790920C5CD5707C1D641F800FE1AD087062F ;1801150110004F21B201095E230256EB0E02E911490140CD2607C90D6D ;18012A01000A2A20425245414B00202A0D0A2420204E00554D4552496E ;18013F010043204552524F520D000A242020434F4D4D00414E442045DB ;180154010052524F520D0A240D000A4D434F5320444500425547202002 ;18016901005665722E20312E300030240D0A240D0A4800415244204549 ;18017E01004E44204F4620484500582046494C450D0A00240D0A5452E4 ;1801930100554E43415445442000494E505554204F4E002042494E41A8 ;1901A8010052592046494C450D2A0A242201E6016302A8DF0222010003CF ;1901BE01AA0D03490869085B03AA0702B308DC032201A8220112028E0967 ;1801D401AAE703B705E4055C07AAB909220175062D06904D07CD36074B ;1801E90100C30000C5D5E50E8000CD0500E1D1C1C9C500D5E5F5590E44 ;1801FE010002CD0500F1E1D1C120C9CDFC07E17DB7C84032CC02C9CD44 ;1802130191FC07CDDC07E1CDEC0801FE1BCA4602FE5F00281CFE0828F1 ;180228010018FE7F2814FE0D280008FE0A2804FE203800E0774F23CD91 ;18023D0180F80118D82B0E081824F6115102CD26072B40CD5508C90D03 ;18025201000A4C41535420454E005452592041543A202024CDD707D5D0 ;*R0*#| "*"2=2>2!"ͯx:G*: 8w#:2: Iͷ:̾**#~($#~#8 ~8 ++~G>:A( :!X2=2!!!M "C"Y~!nC~#O:D*QH!~#xy2Y*"!~# y ":̏*+*7R8:;*|( :!*̨ͷ!4 @!y*\͏*~X(Y G!y#~#ng\͏###~=(= k5!y͏4:= N5;!z*~(+X0 >;G###Ѱ!4:^4:;!*~(DDx >;G!###x(  >;! Gx   S"/5!}!!!wý͸ͽ2ͅ~j͛͸>)͈͸D͈>Aͽ͈ýA~#foT]}lg"yXA(D(x*7R0 *R8y2*:(c(8 8(:G!:A( X(yT :Z( TG:G#~#ng\(8 8(*Q!}ͨ!ͨ(G:*reading status if mini ld a,(cdsd) ; test if 8 inch drive and dsd_siz_msk ; 5" drive? jr z,tready ; no, jump ld hl,tstnidx ; test for no index pulse if 5 in. drv tstnidx: in a,(fstat) ; check no idx to make sure dsk in drv bit 1,a ; bit 1 =1 if index detected jr nz,decde ; decrement counter if index found ld hl,tstidx ; test for index pulse if 5 in. drv tstidx: in a,(fstat) ; check for an index pulse bit 1,a ; bit 1 on status is =0 if no index jr z,decde ; dec time out counter if no index yet endif tready: ld hl,tstrdx ; test for drive ready 8-5 in. drv tstrdx: in a,(fstat) ; get floppy status bit 7,a ; test not ready bit in status ret z ; return if not ready bit =0 decde: call delay ; delay even move before decrement dec de ; decrement counter in de-reg ld a,d ; check if counter is zero or e ; or high - low byte together jr z,notready ; jump if time out error jp (hl) ; jump to tstnidx, tstidx or tstrdx notready1902670148CD9802CA7702D1BE48C2CD02CD390818EF48118302CD260736 ;18027D01202BCD5508D1C9434F004D50415245204142004F5254454431 ;18029201002041543A202411080000DB00FE1AC8DB0100E60120F50E66 ;1802A7012003CDBD02DB01E60102820F570E02CDBD02201DC2AB021C7E ;1802BC0110C9E521CC0246E10544C2C3020DC2BD02C9104747CD540768 ;1802D101247ECD5A08CD57077849CD5A08C3DC07CDD72007CD5107CDC5 ;1802E6018957077ECD5A08CD3900087DE60F20F118EC20C521F90001D6 ;1802FB0102DDFF09C1C9CDF1072071CD3F0830FAD1C390F900CDA4084F ;180310010438402810CD2908D10021340039722B737800FE0D282E16C4 ;18032501010221q ! y f f f f ^q >@űOq ! Š € wO< qѷx 2 : lx  O 6#< !%~#@űOE ! ^ T wO< qѷL 2 : @L  O 6#< !%~#qw}!!!!͔͈Ôͧ!͈>X(<2úg͈yjgg͈~j͈8O!Y ~#~ 8j0 !Nͽ͈ҽqýͽ͈yÔͅ͸y͔%͔͈Tͺ!y2:j!yA ͸ͽ0 >+~#jO!i ~!{(( O!q >(!~6!HL(g.I7}|>A~#*RO 7ȯ#F##(##y~#n&o~#fo))Ay~#7GN#z#8 {8 N#~8y##7kb### RMD*R8 kb+++*Q!>,! :O  ( 6  ((#w# !a!I ~(#%:!<(#=(#= ! \/! :(: !6 #~ 6  #w !4P!6 #!L N> 6+~(E#> E> O:y(~#(m> m> O `8_L*Q!ͨͱ~#͸> ͸> O ͨͱx !G0 8 ))))o`_ (C)COPYRIGHT 1978 MICRO COM, INC.UDF602F U1<: g."&K&k*&* *&" :G W_ ÃùÈÎÑÖ…Gg!͈yg!>PNR!\ >AMS1:] I"  NO INPUT FILE SPECIFIED - ABORTING $!\:l]2\!\9>PNR!\a>AMS22YÈ :ʦ9ͮ R :aͮ R  R ͱ 7:/29 R 9 R :/2a R a R 25547202002 ;180169010056657250030240D0A240D0A4800415244204549 E01004E44204F4620484500582046494C4 00240D0A5452E4 ;1801930100554E43415445442000494E505554204F4E002042494E41A8 ;1901A8010052592046494C450D2A0A242201E6016 ;1800000100C30000C30000C3000400ED46F3CDF602F90001AAFF09E51E ;1400150100210000060AE510FD49115B01CD2607C3F9000047 ;1800D60100C179ED4F78ED47FD00E1DDE1F1C1D1E10800D9D1C1F1E1AA ;1800EB0100F900210000C300000100000000000011F91000D5CDDC077F ;18010001120E2DCDFͮͮ ! @L կ!%w##~+w! w#w#w#w! w#!{ >>!l Ͱ  v0070239E ;1803 OPEN ERROR WRITE ERROR CLOSE ERROR CREATE ERROR  O>ɷ !%4~#> >!%6͸ͮ ~ #w+4~#+ wO< ~. 7 cbk## 6@w6++6#666w# c!~:#~ ʉ0ډ!ŸÇ¹# 6!#N#F#~g>o NL  > #  6! w#p#q!  7bk## 6@w6++6#666w# 7!~:#~ ]0]!s[#t6#w#w++ŽfRDRPUNLSTCONPRTDUM@w#6:#6.#6x w#  5047C01E118E72D2CÃÆÉÌÏÒÕØSUPER CPM Z80 DIS-ASSEMBLER VER 4.00 >2*"ͱ!ͨ! "! "*+0b"! "!͎!~###!Ď!ͨ!M !$ͨ"6!Kͯ* >;Q8, 0>.(#} } <6x (,(-(ͱx !Vͨ B8q#p#s#r#4~#~#ng|x}x>0Q>H>0x>H́ 80ͨͱY7( 7(N(337*|+0!ͨŷ'' / ?7>%v385:/&=CD): 2 * "   EE E@&=CD /<   ,- @?.4297 @(A8B""# ! D$FV^o6g;M0E1+(*'W_GOK[{CSsJB=@A)ADC ADD AND BIT CALLCCF CP CPD CPDRCPI CPIRCPL DAA DEC DJNZDI EI EX EXX HALTIM 0IM 1IM 2IN INC INI INIRIND INDRJP JR LD LDD LDDRLDI LDIRNEG NOP OR OTDROTIROUT OUTDOUTIPOP PUSHRES RET RETIRETNRL RLA RLC RLCARLD RR RRA RRC RRCARRD RST SBC SCF SET SLA SRA SRL SUB XOR ****NZZ NCC POPEP M BCDEHL*ABCDEHLSP,AFAF,AF'DE,HL(SP),A,II,AA,RR,A,(C)ENTER PROGRAM LENGTH: ENTER PROGRAM STARTING ADDRESS: ENTER PROGRAM OFFSET INTO FILE: DO1ͱ0802=ͱD(S >>2: >iͱS >D >2ͱN(Y : >22ͱN(Y >2: >M2:(*! "! ":(>>2! !b >2! "!b ">2"":0  > W2>D(  z!N ~ #T(w!N 7 2V: H:( :(`2 ( B:(ez : >2z>H  **D>2z **Z**Z %;ͱC 2cͱʘN :O"^#~f(w# *F#~# w#r#:w#s#w# :=G::+w#2ɯ2   >P: a{__ :  z DISK ERROR: $ >  i> >":22~:(>> >( 2 :=(2#::<2 8V:i-:6z@~K:|ͱSR 2 YOU WANT AN ASCII DUMP? DO YOU WANT THE LISTING PASS? DO YOU WANT THE SOURCE OUTPUT PASS? DO YOU WANT THE LABLE CROSS REFRENCE PASS? MAKE ALL INTERNAL TABLE REFRENCES LABLES? DO YOU WANT TABS USED IN OUTPUT? LIST OUTPUT TO DISK FILE? ENTER "BYTE" AREA ADDRESS PAIRS (1 SET PER LINE):ENTER "WORD" AREA ADDRESS PAIRS (1 SET PER LINE):INVALID ADDRESS ENTRY, PAIR IGNORED! >> LABLE AT XXXX DID NOT MATCH THE PASS 1 SYMBOL TABLE! << >> SYMBOL TABLE OVERFLOW OCCURED AT XXXX. << DIS-ASSEMBLY ABORTED!END OF FILE BEFORE PROGRAM OFFSET COMPLETE!>> UNEXPECTED END OF FILE << ;; ASCII DUMP; >> NO EXECUTION PATH TO HERE <<; UNRESOLVED LABELS; LABLE CROSS REFRENCEORG END EQU DEFBDEFWM oi#4U .ͬ ]G~_#~W#~ݝo#~ 'L}gjTeox 2k))0# x\E(!kw0x!kE F#~怩O",$ 4~~_#~W#~ݍo#~݌g#~O!l~/wogG}Roݝo}ݜg}O8CZU|oa o-yO|g}o#S˞# S\`N8v\);8Ϳ"D !k~5!3:] G  eIT `@T q@T `@,I@T R1 C#$0Rp00!` Ho 60mxZ`mm`0aRp6PeJ@Q!꓁ PeJ@a!Hh( f׀Z`mm`0af׀1wڢ͠LT BCpB4ۺ -Uڢ =g 8pZW6 0c6_ mdHCe@[`Y

 y7>= WRITE ERROR: $"FiîG(Lx@(?x (2x(%x(x( x( ????Ɛ'@' FORMATTING $FMT8 3.1 $ Enter Disk Drive To Be Formatted (0-3) : $ Enter Density, Single or Double (S,D) : $ Format Single or Double Sided (S,D) : $ Format System Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOSTp͔!!͈!  ~ ! ~# “!~ ڶ!#/ž!~!ڶ!#ê!<"""{2'"z2)"2&"*"""$"!!"!:&"!*$"*'":)"G!#!:'REA ADDRESS PAIRS (1 SET PER LINE):ENTER "WORD" AREA ADDRESS PAIRS (1 SET PER LINE):INVALID ADDRESS ENTRY, PAIR IGNORED! >> LABLE AT XXXX DID NOT MATCH THE PASS 1 SYMBOL TABLE! << >> SYMBOL TABLE OVERFLOW OCCURED AT XXXX. << DIS-ASSEMBLY ABORTED!END OF FILE BEFORE PROGRAM OFFSET COMPLETE!>> UNEXPECTED END OF FILE << ;; ASCII DUMP; >> NO EXECUTION PATH TO HERE <<; UNRESOLVED LABELS; LABLE CROSS REFRENCEORG END EQU DEFBDEFWM oi#4U .ͬ ]G~_#~W#~ݝo#~ 'L}gjTeox 2k))0# x\E(!kw0x!kE F#~怩O",$ 4~~_#~W#~ݍo#~݌g#~O!l~/wogG}Roݝo}ݜg}O8CZU|oa o-yO|g}o#S˞# S\`N8v\);8Ϳ"D !k~5!3= DATA$DATA REQUEST$ FORMATTING ABORTED$Initial track 0 access error...$Seek error...$   ( fPN 2N N BNfNNʵ3õ3!=͍ 3#6 +>1&3:>1!  4>1!4r ?Stac 2N N BNfNNʵle Sided (S,D) : $ Format System Tracks only (Y,N) : $ Supress Format Verification (Y,N) : $ Insert Diskett Into Drive $ And Press The Return Key $ Formatting Complete$ Option (CR to Exit, C to Continue) : $ Option (CR for Same Parameters, N for New Parameters) : $ FORMATTING & VERIFYING$ TRACK $ $ FORMATTING TRACK $ SIDE= $, TRACK= $, SECTOR= $, STATUS= $ FATAL READ VERIFY ERROR DETECTED: $ OPTION (CR to Exit, S to Skip, R to Retry) ? $DRIVE NOT READY$DISK IS WRITE PROTECTED$WRITE FAULT$RECORD NOT FOUND$CRC ERROR$LOSTHL{X GƐ'@'OxƐ'@'ON#5 z80O,z8UO! N#Ny ,!}ä(C)3ͱ,USPS* |} !9":!"<<2* ͞ !~5 * ͡S ͉ͤW! !/ a #   # ʶʭ # 2@m R zI =C =: zzʶʭʕz Ÿ zO=! 3U ! 3! 3UW͒H! 3ü! 3\, ! 3\! zl z=1  3 !+ ͤ͵ ͵ !. ͤ!  ! O 3͍A,,A3͍! ́Á ! L ! ́z8O! 3~ ~ >v ! 3Uʹ,zʹzHږ 8O!n 3 C( )(͍)! 30> >z ͥ ,,ͥ ͉͉W_͕yO! 3 $% ,% !+ ͤO͉͒y !W {A !\ ͤ: ͒H)(IX+(IY+yO 3zʉ W! W3\,% ! 3! ͤAF,AF'! z> z ʽ ! ><3͈͐! 3 ͵ Z͉W{ ͇ z – z!  !!=COPYRIGHT (C) 1977, DIGITAL RESEARCH SID VERS 1.4$10 !~=W!xe ~#Xbxʇ {z~#o}o҃i._!fp+q*e2_2_!hp+q*g!jp+q*i!lp+q*k!np+q*m2_!pp+q*oÃø *sy͏͟+-'#.@=90Oy) ,    ͌ >^! 6 # q! w‡Ø͌>ʘ# }2 :  A ͪBx¸{{: G*w#wx͡ ͟80* {#z+++  ## ' 1>>^ 0 8 a[^ !~-i6+!w yÏaÌ^ ! y͌ >ʠ(͇ ͇ >V a!  y͟͡O*w#"͌ . a  !g  !! 0͟2!b  F>!  ®Wc͡Oi W*##yOx€y Ê y AzÙKByxy͡Ù! {/O! .{/O9OV >G>ͽÙ a # zB) zO!f 3>͈C~ GK ! 3z! E ! 3@ z¾ z! u ! 3w,ͱ́r! 3z ͥ # ͍ z¯ ͉2 ͉W͇ 5 z'!k # µ !3{͒z͒S?*!9"͡"͉*" *'/7?v"*2:DEFMV^goRET EI DI EXX HALTCCF SCF CPL DAA RRA RLA RRCARLCANOP !"#)*+4569FNV^fnpqrstuw~CP OR XOR AND IN OUT JR DJNZADD ADC SUB SBC AND XOR OR CP INC DEC LD RST AF POP PUSHJP CALLRET EX I,A A,I RLD RRD IM 2IM 1RETIIM 0RETNNEG LDI CPI INI OUTILDD CPD IND OUTDLDIRCPIRINIROTIRLDDRCPDRINDROTDRSBC ADC RLC RRC RL RR SLA SRA SRL BIT RES SET LD IM NZZ NCC POPEP M B C D E H L (HL A BC DE HL SP IX IY AF (IX+(IY+(BC (DE (C (SP ??= >>!bp+q:`-!`6*aDM9:_=!_6:`{ 2cX!_6E*M& :cw:M<2MOw*:c>>ï÷ZhÐyg Æ}!"Q!*"!"!""!2V!2M!2#!2S!!" "d!"!"!!1!!++"!"O!>2!~##>Nw~=N/SS/hW Y PRINTER SET TO NORMAL$PRINTER SET TO SMALL$PRINTER SET TO WIDE$2'2)!z2~ :'2)!z2~  !x>  2'2)>2 !:'2)>2 ! !x>>  x w(!% ! { > Fz%x! { > qz+> ! O ! O( ! (z( +!% %04>= __> > ~#  y.LDRGEN 2.4 Can'nt open file: Physical drive no. of loader source (0-3) : Physical drive no. of loader destination (0-3) : Drive Not Ready : Disk Write Protected : Cannot Read Track 000Cannot Write Track 000Cannot Read Track 1ation (0-3) : Drive Not Ready : Disk Write Protected : Cannot Read Track 000Cannotn5">2vþp>2v25Ok$%p͹$!n5L#25yp>,cp͹$!5L#25>)c͔$G>ÙV) y*W>ưG*! ž yG VO{xʃfBGͲ G>Ù x Ͳ>Ù   Â! Q V ͵'> >3*  &! E͟(ʹN[W@GVI@zWe '3>ͽOzy Â(Mx?*z:: OzäIjG>ÙzG'vV”zOx yʏ >(ʠOxà: Ox¯>*ä>>{äIO> VyHÂͪ͟A>2Ó'>"Ó>CÏ͟XY x GV6W>6xJ  pÙ! aO y! ‰ uwͻ'‚>!  Q(ʰ_zÕz Ͳ >Oz>ʤ>ä! ͌ >! EV ͽG>Ù_V% {>*W -{ZW >{ ͵@&! VhV c >rw> V >** {zҝ*~#" 2x:U<{͉2 5 !äͤAOHL(HL)CʹA =8!"9:] !÷1!į>#yh͐ !J!6-B5͐A]]_!Y^#V]8]03]]]]]!]]j]]ů2[\ͯ>2M!!""!]:J!͠=]g" ]g" =g"=]> 2]]g=!1g=-1g!WgG"d!=Wg=]b*d!}o_"f!*d!"h!#>:y:K!ʞw^#V##:ڲ …òw~#:ڲ}ž"d!:J!*h!w+:K!!L!~/www*d!}|*d!:e]ggg{z|]}$2D!2E!gg"F!g"H!DM\!D!6xf"!=x=xYP!$!~ʲ#^#V:D!ʫ*!{«z«"!!~62 !ò#w6 }1!1!*!*!!V!~4#~#F#x~#s#r#w>ʿg===]g#wᯕo>g#'d w>#y!3^#V#0}o|gg Zx~y0ʅyGÑyyÑ‘G~Sz{ <w>'y{y>'y*!##V+^+N+y#w ~+yxÐ. m ͐}m ]]!]!JXN~!:!~# IA_^!!L^#Vx}>ѷ>-y~y/y~y>=Ñ/y>'y¨~!!!!~[#wc#x ڹwù5!*ͱE!:ͱw *!" !6c#~O+"f!*!~~#:cwJ^#Vy6DzS_c~*!~c#^+*!~Gzx&ç@—xv&ʳx80&óx6ʳ4ʧ5¹>=y*!~*!x*!*!:J!& &&x*!~&ó&*!~9&4&&#^xCZMEIABDHSPXY!"T!2S!"!+"!!91!!91!*!~: !2D!!@!~ʨ#^#V#~ ›!V!~6=G#^#V#~xú#"!!N#FO*Q!>7U:#!”!$!~Q#~#V*!QzQ~==2#!6w6:J!6 U<!͆*!U ”|=p U*! U:D!ʔ*H!MD*F!:E!7U!"O!O2#!>*y*!ҷ" *!"d! PASS !S!~*T!+"T!|w=2#!~! ~##Z: !4!y~=W!x# ~#bxE {8~#o}oA'.`28!Ip+q*HT!J6J T ` T!p+q*T> >/Ҥ×!p+q*DM͛:̀ ̀:2:!!K:*&L Ǹ!4!K6 ͐uëYALPSID'TCELLOC$LAITINI!%cCOPYRIGHT (C) 1977 DIGITAL RESEARCH {{ { {zb{b{*9 {_zW}l&))o> \> \\ß*"!" ͟#͟Prںºx"x#"̀ں͇"1!6# y͟!h͟$h͟'h*̀`*̀`*1̀I ?! ^#Vr+sz`>>!@^#V#̀{ k͇#"/<͟h2**̀`i~#!~6͟*1Þ6͔h*1^#V#Þ͔{> \*/̀>*\ ERROR - FORM IS X,Y TYPE HISTOGRAM BOUNDS HISTOGRAM: ADDR RELATIVE FREQUENCY, LARGEST VALUE = .INITIAL = .COLLECT = .DISPLAY = .... !6 ` !6 ` !6 ` *&T` !6 ` !6 ` !60 ` *&*  w#  *,?r# ,:J!]m!!Ow #w Eq!\ S:o@w#tG6#.ʏÃ6# ‘S6 w#ä!ex#y#*!}|"!:M!!]qg!=:J!]g!!|]"!!$!~=#~#V;z;:!w :!]!$!~e:!w#s#r R]!$!~ʛ:J!ʈ6Û~w#^#V v!ʷ=]g"!!l!~# :]?ʀ͍]>HXEͱ*!\ͯ€w# &]:Wr_rrO {Bx!<i`"!Àrrw#Er]&Z&Z\GтWx!ڐ:M!̠>ULTͱ!!\~# ¡2|:] >!v͍͆<]&>!_\_*!& & *+&  !]w{]*#^#Vr+s+6]*"s#s#rT!J*!*"!!͆*!#w*!#w*+# SYMBOLS NEXT PC END =]g#w:K!ʹ^#V#ý~wh͐ .:m!>."͜ ʜw#=]g:K! *!!w2 !~C< EB ͍E *!F#!N!s!7^#V__eB B ? ? 2 B B uE ͍E ::^#V#k^#{*!^#Vuʡ>G E x°I 8_E *!kE e+~ʻû:N!?*!###E ̀E ̀>G ~_!< < "< {p? {? B ? ͍>G ><7*O!|z !N!N*!!b z >#y> y×:S!!K!ʐ ڐ >û ʺ =_~/w/w{ʮ Ү ͍=ʺ YP× "!pCE" *!##F+N+~!/o>g{!z!<33 :006500F7A73E3CA403ECD3A40321F60D9A :1006D500CDFA01C2F006CD8C0FF@0DCAEB06CDD2C8 :1006E50002F6C0C3F4023EC9C3F4020E0221A60DF0 :1006F500CDFC01C24507CD5602CA11070DCACF0C64 :10070500CDBD0147CDC9023ED3C39903 BAI $@$B$@$$@!$D  I $I $$$$ BA"$ BHB$$ !$$B$! B! $$" " A! H BBBHBBHAHD!I I I$$! $@B $!B "I   H "DI!HI $ !T` !6* ` !6* ` !6* ` *& @AA I$DBD $I$BHA"DH!""@ëYALPSID'TCELLOC$LAITINI!%cCOPYRIGHT (C) 1977 DIGITAL RESEARCH {{ { {zb{b{*9 {_zW}l&))o> \> \\ß*"!" ͟#͟Prںºx"x#"̀ں͇"1!6# y͟!h͟$h͟'h*̀`*̀`*1̀I ?! ^#Vr+sz`>>!@^#V#̀{ k͇#"/<͟h2**̀`i~#!~6͟*1Þ6͔h*1^#V#Þ͔{> \*/̀>*\ ERROR - FORM IS X,Y TYPE HISTOGRAM BOUNDS HISTOGRAM: ADDR RELATIVE FREQUENCY, LARGEST VALUE = .INITIAL = .COLLECT = .DISPLAY = .... !6 ` !6 ` !6 ` *&T` !6 ` !6 ` !60 ` *&s#r#Ü]}w#:K!ʜ#Ü>#>2S!!"O!#P@g}]=O=]g"O!"T!2E!U # `͐ xG͐ …xÔ']͐ ]x/!*5]ʬ!:E]]͐ ]cwh=]gx|]}]#gA>Ag}|]E~!!!!pLs#r:[F_!~X![4Y\ͯX2[17>?y l!ͯ!n!"j!> _ͯ~y#Æ͜a_!m!~> ʰ5*j!~#"j! Ҽ0y7yͲò> y> y ͯ#:J! w>.y^+~y:J! >:y|}5 y>.y*f!}o|/+- ,) 0 ]^#V#͐*!Ny]*j!*l! Eʠ ʺ+º͐Ë ºHʳ͐#^#V"l!"j!~/o>g++u!.n@n^#V=n^'͜ ]'͜H']S_#B͐H@0 ])DM)) O #^Y*!^#V#͐^KZ))))o͐HB"!s#r#!]!4-ˆî+•*!Ý+«͐ Ø-͐y_xWØ͐!K!6W6͐!]!6# ,>2]!}m ͐} B"!AI$I$I$ I$A$ I$@D! $"$ HDIDBHIBAI@AHHH"H@@D$$I ABI$I$HB@I$@$I$J $$IB@* I$$I"HI$$ @ $!$I!"@! $AI$$! "B $ "H@"! $ HD@DH"$@!$$ H  ! @AA@H@HBD@@BI@$ $HBD!B HI$$$"$ D$"HIHBI$I$DH@"A $@ ! !!HB!DHII @  ! $  B @A $!BI "@$" "$I$I! @ !D$BB$"I$  $!D$$I$I$$"A$$I  @I I$ @"H @ @@BHABIA $ @@ !/ a #   # ʶʭ # 2@m R zI =C =: zzʶʭʕz Ÿ zO=! 3U>!y~=W!x# ~#bxE {8~#o}oA'.`28!Ip+q*HT!J6J T ` T!p+q*T> >/Ҥ×!p+q*DM͛:̀ ̀:2:!!K:*&L Ǹ!4!K6 ͐uÇYALPSID'TCELLOC$LAITINI!ÓCOPYRIGHT (C) 1977, DIGITAL RESEARCH g gzd{ *9 Wl> W> W*"!"^l!]kl$]xl']::>2l!6!"!~4*s,r,"!~Ol!F2y* "*xT-V-^yA!~4x]> WO" Q>2y*"  INITIAL = COLLECT = DISPLAY = "-A" IN EFFECT, ADDRESS BACKTRACE READY FOR SYMBOLIC BACKTRACE BACKTRACE:%B 2!4þ *%"%:/ ͩ!4¡ :$ !4!"%!q: O !{4>!O :!{O :2*'M!8 ^#V%!t ͫ *%B :w*%#"%` Ø Ø Ø Ø Ø ͩ` *M6` !6 ` !6 ` !6 ` *&T` !6 ` !6 ` !60 ` *&M "I *K  )*= ^#V"O I G  *G )*= N#F*O ? J*G #"G (*I )*= ^#V*O DM? m*I +"I JI G  *G )*= ^#V"Q *I )*= *G )*= N#Fq#p*I )*= *Q s#r*G #"G *I +"I K I  G M   !M G  :S <2S O!T *G s#r*S &l ) *M s#r*I "M ^I K  X:S <2S O!T *K s#r*S &l ) *I s#r*G "K û!" "    #* #" )*= * #" )*= N#Fq#p   * )*= * ) *= ^#VN#F? H * #" )*= ^#V";  *; ^#V" * )*= ^#V"; *;  ͪ  *; q#pÝn* " ! p+q* )*= ^#V"; ! 6> ! i* &*; >OK : <2 E:/ *; ^#V*% DMf KK : *; Nf E*; ~ڻWK þE *; ~SK E = ! 6:! '= :/ = : = !: = : <2 * " !" >! .  * *&͵ "( * *&͵ > j*( #"( *DM*( V"( !" (   K!" }2 : <2 O:* * * "    >! = * DM** +" *( * " Ø* #" *&1 Vers: 01-10-84; by: J.C.Kaltwasser & M.J.Mosko, K3RL $=  **͂+}2'++*'&0+!'ͥ(}2'*'&!)*/!*!ͪ*͢*!'!)*"'*'!Z!b(!Z!!*!\8+!)*ʇ!Z*!*!ͪ*͢*!\+!\!!"'*'*"'*'!)*ʶ!"'!*'*! ͘(!i͇+*'!}2'"'2'*"'͹ !\"'*'! (!C)**'! (!O)*ͤ)*'! (!M)*ͤ)=!"'!!͟!\ͺ+|ʅ! ͪ*!*!ͪ*M! ͪ*!"'Ý*'&*ʖ_Ý!}2'!?ͪ**'&|*'&!E*!}2'*'&!g)!x)!}2'*'&*'&***u(}2'!!*'&!E)**'&!)*ͯ)9 !}2'*'&!Q)**'&!)*ͯ)b*'&!H)*t*'&!M)*ʆ*'&!B)*ʛ!"'*'&!Z)*ʷ*'!:*"'*'&!-)**'!)*'!:*"'*'!:*"'*'&!R)* ! @@ I$B$!!D!$"H@* ͡. ;ͣW!E# ¡ # ¬# ·@ʴʥzʖ=ʐ=|zJz?4)z zÇYALPSID'TCELLOC$LAITINI!ÓCOPYRIGHT (C) 1977, DIGITAL RESEARCH g gzd{ *9 Wl> W> W*"!"^l!]kl$]xl']::>2l!6!"!~4*s,r,"!~Ol!F2y* "*xT-V-^yA!~4x]> WO" Q>2y*"  INITIAL = COLLECT = DISPLAY = "-A" IN EFFECT, ADDRESS BACKTRACE READY FOR SYMBOLIC BACKTRACE BACKTRACE:%B 2!4þ *%"%:/ ͩ!4¡ :$ !4!"%!q: O !{4>!O :!{O :2*'M!8 ^#V%!t ͫ *%B :w*%#"%` Ø Ø Ø Ø Ø ͩ` *M6` !6 ` !6 ` !6 ` *&T` !6 ` !6 ` !60 ` *&*( * " 3*1 #" " " *5 " > # R : B * +" ! +s#r( ! 6: " * ~2 * #" * +" > ʶ : 2 Ғ * +" : <2 O>ҳ ! 6* #" * ~2 p K* DMf = * *% DMf = * *% DMf = *( #"( K*# DMf = * *% DMf = : AOK :K . g S -A >>!  ~?l W >#^ : /!:' —  ʑ #‹  W ʢ #™ i`N#FogDM!>))덑o|g =¼ DM!>)) = ^#V) ^#V|g}o _{ozgO{ozgi`N#Fogo&og_{_z#W OK = Y -S {-_ ! s+p+q*  ͼ 2 <2 : ! ڗ  K ! 4Á ! 6: =! ڻ * & NK ! 4œ >3  03} Z; { ) # *"'*'&!A)*b!*"'*'*':*!E**')"'|b!*':**'!E*"'*'&!O)*~!*"'*'&!S)**'&!C)*ͯ)ʠ]*'&! )**'&!+)*ͯ)*'&!=)*ͯ)!'(*'V)!"'*'*'*=͓ !\@+͢*!*͓ ͓ !*͓ !*!͢ !*!͢ !1*͓ !E*!͢ !\*!͢ !s*͓ !*!͢ !*!͢ !*͓ !*!͢ !*!͢ !*͓ ! *͓ ͓ !- *͓ !B *!͢ !Z *!͢ !q *͓ ! *!͢ ! *!͢ ! *͓ ! *͓ ! *͓ ͓ ! *͓ !͢ !!*͓ !͢ !7!*͓ !͢ !i!*͓ !͢ !!*͓ !͢ !!*͓ !͢ !!*͓ !͢ !"*͓ !͢ !U"*͓ !͢ !f"*͓ !͢ !"*͓ ! ͢ !"*͓ ! ͢ !"*͓ ! ͢ !+#*͓ !͢ !G#*͓ !͢ !o#*͓ !͢ !#*͓ !͢ !#*͓ !͢ !#*͓ !͢ !$*͓ ͓ !>$*!'!!*!'+!͢ !V$*͓ !͢ !$*͓ !͢ !$*͓ !$*͓ !͢ !#%*͓ !͢ !f%*͓ !͢ !E ** Long Directory Program ** Hit SPACE key to continueEName Ext Bytes UN At ! File(s), occupying K of K total capacity directory entries and K bytes remain on 1 !9" ! J> # ->! . *ͪe> # < * v K  K  K !B r+s+p+qA ?  p*A *? :]$Ž l]Q !]6 !E 6!C 6 :C *C &l ~2D U¼:E 2 :D S:E 2:D F:E 2:D V:E 2:D P:E 2 :D N2E !C 4Ø:!4:!5(  ! I3= : [= t:\a:\=_: :] t ?]\ : ҃! 6?Î : 2   ]Q  ?\\ : DM, Q ! "= *3 ##)*= "; */ &# "! *3 #"#  !! "% >!1 . 2' \: 2 : ʩ: ƀo&"* ~ʛ*# +"# ** DMY қ** DM  *; q#p* " . ** #DM*; -e**  *; w* #" )*= *; s#r*; "; : 2 !S 6!"V * "n >!S d*S &T ) ^#V"K O!l ^#V"M :S =2S M K  a*K "G *¸%%_%w36~kw"~jw,~iwG%7̈́ 6~wk#~+w#~#~G~#O>>~Ox ##y>7%"p##q=,~wi"~wj͑%͘%Gͩ ø%#'(ywiwjwkN@ H (%\n(?~@/(86@ / ~ > 'nˮ%(H%'>(q@fk^jViͅ=(n&>G)MDͩ~i8++~j8###~k8~wi++~wj###~wk6~^##Vg{怄O>G{GzGz_>6#q#p#w%fn8ͼ~8#  s1r2ͭ%~w/~ô%fnfͭ%~w1~w2~w/~w0~ô%~1!͇%[042()~1%ѷ´%52 }/o|/g"0{ozg"0{Oz(>g~1w6% x6)q[͍/q@͍x) ͟%0>%#| 5@ J'~@n(͟%# ~##"~͟8w###6)͝~%'(*%%*͓ !͢ !%*͓ ͓ !͢ !%*͓ !͢ ! &*͓ !>&*͓ !&*!'!!*!'+!}2(*(&!)ʇ ͓ !(D)!!! ͪ*! ͪ*!9)ʵ ! ͪ*͇*!}2(*(&!Y!(2) !Y*(&(*!(D)!&*! }2'*'&|6 *'&}2'*'&}2'!>*'&!g)}2'K !}2'!}2'!>}2'*"'!}2'!}2'*'&*'&**| *}2(͟*(&! )*(&*ͤ)ʨ *(&"(!*()* !!!&*!\+| ! ͪ*!&*!ͪ*M! !è !*()*M !!!&*!\ͺ+|> ! ͪ*!&*!ͪ*M! !è *X&*()*| !',)!)s !}2'*"'è *W&*()*ʨ !')!)ʢ !}2'*"'*'&|0 *(&! )*(&*ͤ)ʬ *(&"(*U&*()*d *'&|T *'&!)# *'&!:*}2'!')!'ͺ)!}2'Q *'!)Q !6}2'!M}2'!')!'ͺ)!}2'a !')!}2'é *V&*()*y é !*()*ʩ !}2'*'&!)*ʩ !}2'!')- *(&}2(!)- *(&u(ͪ*!i*'!i*'(!*'&)ͤ)*(&*'!=(D)!͇**'&|*!'D)!}2'Ì*'&!6)^*'&!}2'!'D)!'%)!}2'Ì*'!)ʌ!}2'!>}2'!'D)!'%)!}2'*'&!M)ʺ*'&!}2'!'D)!'%)*'!)!}2'!>}2'!'D)!'%)!9!9(u(*!9(!A)!9(!0:*͇*!9(!7:*͇**'&!:*!)*'&!>:*!:">(!>(K)^͓ !O'*!Z*!V'**'! !a'**'Ϳ!d'*!h'*!*!p'**'Ϳ!s'*͓ !v'*!}2@(*@(&!)*@(&*'!ͤ)3! ͪ*!@(D)!'*!}2@(*@(&!)A*@(&*'!ͤ)!g)ͼ!@(D)͓ !'*!}2@(*@(&!)p!'*!@(D)!'**'!x)*'"'!}2@(*@(&!)V͓ *'*@(&"C(*C(d!'*!}2A(*A(&!)!i*@(&*A(&(3! ͪ*!A(D)!'*!}2A(*A(&!)=!i*@(&*A(&($!A(D)!<ͪ**@(&!}2@(Ñ͓  Utility Functions:A - Enter relative address to dumpB - Set record to beginning of file and dump dataC - Continue search. Restarts search on last entered search string.E - Enter Edit mode on current recordH - Brief description of the functionsM - This help descriptionO - Enter offset address relative to start of file (.COM = 100h)Q - Quit programR - Enter record number to dumpS - Search for hex or ASCII string in file (starts at current record)'\' = ASCII string delimiters (ex: \Test\)',' = hex and/or ASCII delimiters (ex: 41,\Test\,4A';' = select search optionsA - Start search from beginning of fileB - Search BackwardsM - Search on certain bits set; use mask xxO - Stop on xx occurrence of stringU - Translate lower case characters to upper caseZ - Search recognition on least significant 7 bits onlyHit for more -Z - Set record to end of file and dump dataCR - carriage return (or +/= key) - advances record and dumps the data-/_ key - decrements record and dumps the dataEdit mod&)ͯ)**'&*'&!i*'($=*(&! )*(&*ͤ)*(&" (*U&* ()*ʺ *'&!>)ʐ *'&!:*}2'!')!'ͺ)÷ *'!)ʷ !5}2'!M}2'!')!'ͺ) *V&* ()* ͍ !* ()* !}2' !* ()* !)}2(=!}2(*(&$!i*'*(&**'&*'&*(&3͍*'&! *'&)**n *'"5(*'&!S)*}!(!!*!}20(2'21(2(2'2'!}2(!!!&*!(+!(!(!(!!*!(!".(!(!(!)*(͟!!!?ͪ**5("'!)}2'!}22(*2(&!)X!'*2(&!*!2(D)*.(!(!!(!((s*.((!\)*ʦ*(&!))}2(!.(%)X*.((!;)**1(&!))}21(!.(%)! *X*1(&| !'!'D)*.((u(*!.(%)! *X*.((!,)*-!.(%)!}2(X*(&|S!'!'D)!.(%)(*p!.(%)(u(}2 (* (&!A)* (&!F)ͯ)* (&!0)* (&!9)ͯ)ͤ)ʷ!ͪ*!}20(sP* (&!AV)* (&!F2)ͤ)* (&!A:*! }2 (* (&!0:*}2 (!''!9!9(!ͤ)*!9(!)Y!9(ͪ*`!.ͪ*͇*!9*"'!}2E(*E(&!2)*'!g)}2G(*'!E*"'*G(&! )*G(&!0}2F(*G(&!7}2F(!*E(&*F(&*!E()!!!*!*! ͪ*͇*!9*"'!}2I(*I(&!2)*'!(ͤ)s*'! g)}2H(*'! E*"'!!I()*H(&!0**I(&!2)ʗ!!I()!0*!!!*!9*ʸ!*!͇*!}2J(*J(&!(/*J(&!:*}2J(!9**J(&)!ͤ)!0}2K(*K(&!9)$*K(&!}2K(*K(&ͪ*͇*!9(!)!ͤ)!0}2L(*L(&!9)p*L(&!}2L(*L(&ͪ*!9(!ͤ)!0}2L(*L(&!9)ʯ*L(&!}2L(*L(&ͪ*͇*!9(!ͤ)!0}2M(*M(&!9)*M(&!}2M(*M(&ͪ*͇*!P(!!*!P(+!P(!(}2O(!P(!͂(!P(*O(&!(!H)*a!O()!}2V(h! }2V(!"X(!"Z(*O(&!}2N(*N(&!V)!P(*N(&(}2W(!0"\(*W(&!9)ʿ!7"\(*X(*Z(*W(&*\(:*x)"X(*Z(*V(&x)"Z(!N()*X(!}2^(*^(e: ('^' refers to the Control key)^[ - (ESC) Accept next char into edit field even if a control char^E - Toggle between ASCII and hex data fields^W - Flush record to disk^X - Abort edit mode without updating record^J - Cursor down ^K - Cursor up ^H - Cursor left ^L - Cursor right Input integers are decimal. Use 'h' suffix for hexadecimal entries.Hit to continue -Edit RecordWriting Buffer ** WRITE ERROR **EDIT ABORTED** READ ERROR **?Search String = Stop on string occurrence = Enter string search mask = Not Found.SEARCH ABORTEDFile: Record: (H) LOF: (H) -- ---------------- - >xs(~# f(}a{ o~aڔ({Ҕ( w#Ä(~#Ü(!^#6~( (#÷(}|#~ (((6#÷(i`^#Vr+s|r)!„*+Ä*n'*'&!'*'&(*(&* (&x)**(&!)*I!'D)!}2(!}2(*'&!)p!ͪ*!}20(sX*0(&|r!"7("9(}2'23(*'&*'&}22(*'&!C(ʹ!}2'!Uͭ|?!)}2'!}24(*4(&*'&2)?!'*4(&(!aV)!'*4(&(!z2)ͤ)7!'*4(&!'*4(&(!ͤ)*!4(D)!}2'!Zͭ|Y!}2'!Oͭ||͓ !&*!:*"7(!Mͭ|ʙ͓ !'*}2'!Aͭ|ʹ*'!"'*!\ͺ+*3(&*'&)!'*3(&(*2(&N)*ͤ)!3(D)!}23(*3(&*'&)*y!Oͭ*7(*9((ͤ)2!}23(!9(%)y*2(&*'&V)^*2(&*'&:*!}2'g*2(&}2'!}2'!)}2'!2(D)*2(&!V)!Bͭ|ʣ!'ͺ)é!'%)*'*'*!}22(!\ͺ+|*5("'!!!(!*!4'*!ͪ*!}2'*|2*2(&}2'*}23(!!!@'*!}2'ù**A*}2;(*;(&!i!9((*'&ͤ)}2<(*'&|ʤ*<(&!aV)*<(&!z2)ͤ)ʤ*<(&!ͤ)͇**<(&͇**'&!)*!͇*!}2=(*=(&*'&2) !'*=(&(!9()*!)͇*&!@!(2)/!@*^(&(*!^(D)*E&!)g!9**E&*!9**E&*Û!9**E&!ͤ)*!9**E&!ͤ)*͇*!}2_(*_(&!P!(2)!P*_(&(*!_(D)!}2`(*`(&!K!(2)!K*`(&(*!`(D)!F!(!)*X!}2a(*a(&!O)N! *!a(D)! *Ñ!}2a(*a(&!F!(2)ʑ!F*a(&(*!a(D)No File Specified. Not Found.Bad Record.RECORD = ADDRESS = OFFSET = HelpRead/Edit File Utility Functions:A - Address to dump B - Dump at beginning C - Continue SearchE - Enter Edit Mode H - This help list M - Expanded Help listO - Set address offsetQ - Quit this program R - Read & dump recordS - Search for string Z - Dump at end of fileCR - (+/=) - Adv record(-/_) - Decr record Edit Mode Functions:^E - Toggle data fields^W - Write buffer out ^X - Abort Edit Mode ^J - Cursor Down ^K - Cursor Up ^H - Cursor Left ^L - Cursor Right Expanded HelpRead/Edit File? ?Copyright (C) 1982, Digital Research654321 BNKBIOS3 SPR FA00 0600 BNKBIOS3 SPR AF00 1100 RESBDOS3 SPR F400 0600 BNKBDOS3 SPR 8100 2E00 61K TPA $$$$$M? @ R? ? @, *C5:P( 0>>>>>?@/ _@Q  CRT SERLPTPARLPTs1x!4~<6!4~'w`6!4~'w`6!4~'w$6!4C5:5<:5[:6*_|>>x >ɇyx>/s1x*_|< 2`\!aw2p????<2: 0=O:'''' 0=x8>(x [_!a{<2_~Q(x(OQz>x8( Q,!'ͷ í BIOS Err on A: No CCP.COM fileCCP COMy!^(w 0<KK{<<ʽ! ~6 69BK! OSg$Nwy!"(9"f1f! Ҕ2! ~#foCOPYRIGHT (C) 1982, DIGITAL RESEARCH 151282^#Vɧ:=#=~> ͣ!mF~ g(Loڵ)'ݶ>pݶͣ1 rͣ1͉)ͣH>^Vcz2l~[Z:'''ݶ݆:::ݦ>0!mF!dzK >= , Drive Not Ready, Write Protected Disk !д[^#V:'' ͎ > ͎:ijg(!( O !1 O(!: ͎z(Q(ͷ !ͷ(> >2Ƴ!׳[:ݦG_(x!Ƴ (4>w:ij> xwGx> ͎  w !m> ͎ Q(!m>!д[s#r!:ijw8 Ͳ͓ 8)͓ H>^Vcz2l~[Z̓~˗##xK[~ :ų( {2ųywx>wͽy2ij*³ :ij!7g( !jo(!_( W(s#r*³:ij_ (g( o(s#r:ij!g( !o(!ڵ_( W(device serial deviceA S³F͢ _s͎ͽ̓:ijw*³+~>8 +2ijx>wͷ:ij2ij:ij_O{M2W!"hH< H! S%:P:%Q~:&Qw# x Ɛ'@'O!̯ͷ:AO !ޯͷ*!ͷ*2P11͊)>]|‚*Û*)>]²|žÛñ~O #ù>/<33O _ W{|***)>,|h&)))~@]~oP>W>wfͱ*À*2!"*"!!***),lwÒØl=otyÏåÄ} kƯʯ$:Àxͭ1x>Q>2Ã1Oj$|Ãà à Ãhlptxɼ|DHL$P3TBXQ\``od~$(,04ʻ8ٻ<@ $(%,40C4R8a<p  ˺ںqDD Super Bios v. 3.0 CP/M 3.0 installed Default console is serial device @ Default printer is parallel ""!@""! ">G>> >d !p}! ! >>>Kv2!ͷKv22 !! ͷ>/<0O2i`z n&*&)~#foø*&)~#fo~#fo22ɯ BIOS Error on : T-, S-!`|G}2^!1k !^#V#{6++~2y2+V+^Ͷ cy2i&) ~#fo{k!~2!~#foͶCCC:Pڗ>2#×:#<֪2#*=‡*":*}®:=::<>2*i^#V+ d!K*}@*)): K:) O "!w [O?WGzO:VxGyOGxwq*}}2~77ø~7"9:OG#Q{ozg# ""!2*%DM**ѵ+)) H~#+}#<:<ʲ<77:<ʢ=2(*f*(}DɯQ"(>QKQKQ>Q"%Q!*$K*"x!*!@$@hK\K:K ~#~ w*NK*NK^#V#N#F!x>QGQx3ڰbڼqҼo5p5"""*!yb! ~G*!NKկ2}!,"**NK6 :+OK2$^#V#N#FxNp:$p:Gjxj Y# A>QFQ  !m[K:l=2l *m:G:l=2l !д[^#Vɧ:=#=mo`?     )оmo`   Ypؼmo`     )YHmo)?|:w:ʴ>2d:#Ϭ>29ଯ2~2#!   )xð*}*}"*x"xm*^#V* s#r**s#r*:奄Y4Y̓**~#ng* s#r ^#V랏a##)""xx!"""XC*~<Ϋ*":!:*}*"x"*"g*3:= :Oi :=H:Gi a6:G/O**W :T=ҍ aʚ~ª6*:X)!:T>qk֪!:6>X*{Q:_2{2Ē"͂"X~<ª#cdfg!"()*N!r)!N!)z<*)"!":X*:w:w#:w*2*}D2@ !ש)#w*~"Ҡ!Fw䠨Ҡ̓Ҡ:w̚":>夯2̓*~wć"̀!~$6:03i"!~6*e>=)Q!QX@˞ >2 ˞!!q#p#w2wW*e_3ҫ-!s:!xQ*:<œ. ʩ.ʩA܎rr##s܎<}rcN! ~态O>G~G!~G~o>_yG~.|°! w:ck[!x?[! ~ʤ͆[͗PPvqO-á=.:<ʰ! Vq##~_@wکͶ:WMںʛ>úͶ >TJ:!ʷ͞x!ǝw4 ϝPWޝP܎ÂՎÂ*!!~~#~O~#FsO s#r:(„y==„*!^W*y^#Vx7=2wͼկw#KWK*"J T͞*:["T] KKͦޔ*w"wͦ"w@ :ÔNɔ N#Fyؔ*}|h#ð*ͫ# 6RX*q6!"@**#":&2͒:È0:+Òy<_W`iͫDM*w ~bNpwޔDM*we ^#V#~2>â9͆>!"*y³*X*ÿ͂"*g*K!~<:wb##>w#wĐ> r!~#22Zw*q>ww:c *#*is#r*:!:)e:O!*c:Oͫ}@2æ ~á*g:o$*~K6?~wKw**i{#zir+s{O:w:Ғ4~:w?r##rp# ä |g}oì*g #G ¾1*q:*w***> r 2":O:G2!w*~zWw+ !z?#~*!* *G!O~2~m͗O~t>2?:2̓¡>2ͱԡߠ?~¾¾ʨƨ>w͙=2͜:wÚ~̓ʑpá!6NwͧBpͧȭÚgsr͐-͜ĐͤS)_ͤ̓~?w͐s-?F͜pN͆p# Þ͐*6!¿?~p*6 >2ͱݡԡߠͷw*oq͋"@6ȭ͚Xͤ͋͗wO~<: g~w#w#6##)͋@ * g~?G++!o#~>T}! 6**#K"G*~ xr͐-xą@˞7(͚Sʀw :<RHͥ:>~c!o#~E^#V)G#~#~!~ b k##N#F#^#V#~#fo~o2{2g*wޔʪҢÞ+}*#}o|g:O*s#r#w!~w/~@w//Hͥ*e>=)_g:0"ök*w)*c)-͐ͤÀk*s":;:r2͚Αù͚Αž͚}/_|/*eW}_*c"e}o|g"c>2{+SX:ڜq:ʺ!ʵ>2܎ͤ2ќO ̐DM͸}ޜ>r""2:2* :::29:>:>*ڈ>F6:_/G:ʧ:ڨ|OͤG:_O̐̐zW{›|:*}|BKN› zyG:!vq:vՎvMڂ?Ͷ >T͓Â!">Â:G:O:h=27ryy/W!:l=:<>w##~2 4~?ɚ¹:<ɚɚüޘAX2rK:w++~=wv4͗O5:2X!"*>o+"! *!b"ݕ": r#~?w#>r# L=J Lv wȭb܎?~O ͆ښ†wŒ~è# # x ͗w ٙڙٙڙw@ ~wb͐Úݓ!x>w~6:6~#+w#w+~;wɯ2KOFq-yl?Npg:ʓ~g͝DM*0MD"!*MD$:Oë!N: «G>O: ù*Đ :ڐn` ~#foͤ2O̐"}:O*"!s#r#p*kN#F*m^#V#F*:O}|y9*+"*}|yP#9**DM"*ks#r*ms#r#pyox*kw#w*mw#w#w>2'å2*OͶyڲò<*eͲ:0!::ò2*>*ͫ"4#4#4)7 #  w#*J|^#V#"i##"k##"m###"o#"q##"!s )*s!)*|!6~67rrorFile Exists? in Filenameòò>2a.":2:<:55;:2ɯ22{_zW{_zW )7CP/M Error On : Disk I/OInvalid DriveRead/Only FileRead/Only DiskPassword E—>2—͇ͱ* «>2͙wBp+Ҥ:w͚AP{ 2W>O2ø͐R*e):r͚Αc2ZT͐-ژ3͗@YsY̓YסYͅ:ߠAsҤ:@Ҥ@Ҥ$͚̓Aؑ=:<~?¯kã?~?ʾZT͐ڣ*>o"͒"!Ó:Oݕ"Ý͐6͚ ~2Asv@NN~v$̓W+vw̚v$̓rrͅ:rߠ>2+A@2r!Z2!"ög:2T͐-:ʹ>2<2ژ!w: >2*6ݕݘO~<w:*)@ u:G*g`~!x_<_@*oy<:/G?~##~? 6K@?F6##N6⡯2p##q:#*~w>2*p@! ~*"v@*w# ) 6#̡͙N#FxT]## #~ ȷ  *4# ' 4! *~^ ^33G# Pv:dv6 y( ȭˆʀHÈ2xą ):@ΘO~#w͚ʀôb_++V@* )͗Os++r~Gw#* #~$%+@*9>  #>? ;*~ w-xąH"0 *ĊHEʀ@~›:6¦w͚̋ȭÇPY*{zBKNyʺ Nú2: *~w *" ݕ2>ʄ@~k:(s~*9~Ês~ԡ~ͅ<G:<ޖ2x# W:<­:22G?>Grx~:2Ô##~*$*">2̀2kºʺ**iҺ@:O~햯2~WW:2Ôyʛ?ʔx ʔ |̷ǖÔN:r:/GyOOA +¬ ¢y2:x¹o&:W>OͫE:ڟ?N/*"y2ͦ>2 ݕwޔDM*w6# x *ow**ws#r̀*i6#6*}"w@*|<ď>!8>8> t>nͦv8 ~*own@)"!z<~rs^#V#N#FxN:oʲ̀õ(# Þry< <<%zrͷr6r9rMDÌ:o!6!h: ʚnt2 r62>rz<*9ʌ^: ~x ):*:ŊŊ>*(+"(w++2+2+Ɇp؆!" >2+2*jx.#NzW::!2W!5=^x^z:m:*;#wO:͂^2¢ů͠ĉ:!ڽ*(~ׇ݇5WèՉ؆jׇM2ͨxΉ*(+w"(jͅ !%"(^-:*$P:<\:W:2xM s:<9>2:*9x~+q’x2:*1CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321TEMPORARY~ORDER~PAGE~DISPLAY~NO~COM~SUB~NOPAGE~NODISPLAY~ON~OFF  $(/9!6#6#6#6#6!"+~2*& "*& ~[”*#" â' :¢ V v!q*&!p+q*  !q:2!61!s+q:2!6*&~2+o#"&!+6Mň:W:2x ͺ*(+"(w  :܈>2*2:*(:+w"(ͺ:G::+̜2 5*(~o#"(Mš*(~`Uoj*(~#"(Ñ!*~6s!+6:+‚xoڊ{2Ó#w:2.+:.2-!%"(2*!Œ"&!*~4:2-Ԃ:Gͳͨ^2+>2:2*N#G2 2GH)+6:2,:!- ͅ:,!ͅ+*(~L#Bxz:*:*(~ʓOr ͅ ͅ! O(Ì*(~2**}ʷ!#¶!""÷:_:*(#wΆxH!Œ)6"&:!Œ x5~y 5 6y(^ͅ@O:=7:ͅy ͅ:I ͅ:=e: zz#͂ͅ:! ͅ G:Ҏ>xʝʝw>ɯw̩z:»!>wɯ:=zxzz::G:=/ͽx:Āy!4 šn!6@G:x: P:<: P n6 t6! ^6 t6u:)<͠^!gr)!ڄ*+Ä*r)!ڄ*+Ä*(+|4ng*r)!+,)-|^#Vr+s|*r)!+E*|z{.zW{_-ʠ)җ)} DMoxGyOÁ)|}o|g}o|gK)#|5ng),|}o|gzʄ*|g}o)zʄ*}o|g)͑*#||!„*#Ä*~#fo}}|r)!ʄ*+Ä*}o|g"*."*{_zW**-"*ʄ*>)D**OxG|* ?T*} =Š*}/o|/g!+ñ*ÿ*o&ÿ*͙*!**͙*K* !+*ñ*͙*͙* ͙*_+͙*  ʴ*>ô*  ͙*͙*ñ*͙*ñ*͙*ñ*ñ*͙*ñ*͙*ñ*͙*ñ*͙*ñ*͙*ñ*ñ*͙*͙*ñ* ñ*͙* ͙*!ñ*͙*"ñ*͙*#͙*$͙*%͙*(ñ* chain (see SETDEF). ///2withOptions Syntax: DIR {:} [options] DIR {filespec} {filespec} ... [options] Explanation: The DIR cmmand with options is an enhaned version of the DIR built-in command and di*&"1!q!6*& ->*& :A:!4!r+s+p+q+p+q!6*~ʯ*~2*M2!6:¦:ڙé*M2Äùe:2#:22*~2!6*~2*~?*N! ** =2!3!6!6:!0:)!46*6#*:w:+s#r:i*#"n!6:2O* ~2*&*:ʿ!4*:w*&*:®*&*~2À*6*~2o:2!6*#~2!4N* :!6*&*:!6!4N* ~2*&*~2*M2:> !Hl!4N* ~2*M2;:2#+s#r*N2!š*#" ͯ ͯ!q!6*""2:(!6(*&*&!s*&!s::H*+":++s#r͛!6:!D*"*M!4&*M:[Ϳa2Ϳ:Al͛*M! ^#VIͿiͿ{ͿͿͿͿͿͿ Ϳ|͛!q!6:! *Ó*"r*r"ÿ<:g:!͐*f}D! ~6t!rͷքO(^ƄƄƄ  :Function = File = !,!"h!9"f! ͉:2t™:!=Hgo:O*;*͂:A2=/::0! dگ61#d ڸïp#:w#6 !6:6 *#!)6.#)͂ O(BDOS > wM  2*7w#6?#7 .,:;[]=<>|!?]45#Ra{i_p# l s s l ls:¬MA@Oͯ:ͯ͛!4ø :Ҙ ͛ZͿ*M! ^#VrͿØ vͿØ ͿØ w : ͛Ϳ>!Ҷ !6: Ϳ :@Oͯ:ͯ: ͛Ϳ: Ϳ Ϳ:# ͛Ϳ: Ϳ# Ϳ͛!6!6!6!6>!V *& 6!4; !6:: H I>!Ҏ ͦ:› ͦ!6>! *& :=¿ ͦ!4  :=*& w!4[ !6>! :L*& ^O!4 :: Hұ!6!6I*M! ^#Vͦî!6:] ͦI:w ͦ:=_Pî!6!6#6:ʞ ͦ*~ ~ Hҿ *#"Þ *~( !6*#"I::H ͦ:Number of time/date directory entries: Number of free directory entries: Active User :Active Files:# of files :Label for drive AccessCreate on off on on off on off 1}1}{o&" >0 ͑*!& ~ :!<2!*!& " 2 h2 !!6>!!Y*!& 6:!<2!;6f!$ 6(2! 6D~!% 6ͱ!!6>!!*!& ~2 ʺ*!& N*!Mz:!<2!†v! q* & ! p+q* ~* N* #"     :$ e! 4~<<+~He  MC]! 6  ! p+q * DM }! q* &:~ҝ:}¦:}`O! : ½2}Õ! p+q* ~?2~* 2}͕2}͕! p+q* !Z 6Z 1!Z 6,Z 1!Z 6]Z 1|"  ! q* &.! q* &e! p+qi* DM! q: <2 O* : w! p+q* ~$* : <2 O* w* #" ! q: 0Oͦ! q:* *!##* ##NH*!##w*!* ##N*!q#p: AO !!r+s+p+q*!/!a*!q#p*!ڒ*!*!q#p*!N#F*!q#pc!!q!"!"!!!6!"!* !:!*!DM2!:!/!!H*!"!ҫ*!!"! i8*!##6* N#F*!q#p,ͦE* N#F^ * ^#V))DMy* ~* N!!+s#r*!DM  1:!!p+q*!##6*!*!s#r!!p+q!'"!!!6>!ʚ*!*!͆{2!*!*!͆"!*!! ͆"!>!!!+~Hҗ!!6:!0O5>0 ҹ" ͓DM$* Mqͦ1k!!p+q 8R*!}OW͛: : 2!"!S"!!!6>!ʈ*!}g: /X!!:!U*!DMg*!M*!DM!!+s#r!!+s#r#~!X *X g 8)*V g !!6>!! *!&& 6*!&6 ) >w !6:2: :/H!0 ͦ: !҇ I::Hj ͦ:2:!҇ ͦ2:¢ :2ê :2:½ :2 :2*: : ͦ *#" : ͦ*~]~H!6 î!6!6:WI: W: R!6Wͦ*,*-î!6!6:¨I: ʨ: £!6èͦ2::2:2*îI::Hͦ:!6,-<!62:2*îͦîͦî!6,-î!62:2*îͦîͦîC K l?GOe !p+q*~ ~ H*#"ø*~>>_ogDM!>))덑o|g =o&og~ O: O! q* M:ͦ! q* &! ͆K* &! ͆M! q* M& /ͦ: e : s ! 6: <2 O* ~2 : ” \ Æ : 0 ! s+q! 6͆ ͕ ڶ ͕  : : : H2  : 0! w \ ö ! : #~! H : ! s+q+q͆ ! : 4 \ * M* ͞ ! s+q: 2 : * &) >;H{ : =: ! q* &! ͆))))* &͈ } ͞ =2 : 2! !!6 * & ~2!/*! 2 /cN 2 : !!: H * &) : N_!mͥq* & NC * M* C _* #q#p͞ O * w:; O * w* ~¬ : :  :; 2!* 6 :; O * w!!s+q:!!!! 6N!m"!:  !n"!!  ! +s#r! 4 ! 6 >! P : =2 2 ! !6* &) : !m! M  * ~2!*  ~2!*  ~2!* #^#V" +!͆! !s ! !6: >;! HҮ ! !6 * &) : !m ! s+4* ~ : !O! DMͽ ͦ* MK * MK * M#6:!<2!!"X 5!"!:}:}2!*!& ~2!:!!*!& "!*!##"!*!#"!:!2!:!2!O!& 6>!!Ґ*!* ~Ҥ*!~*!&6 ) N#F*!&6 ) q#p*X #"X %* & 6>!X * N#F`i"X * N#FPY*X *!"V 8QhOg 8`* & ~/\!!6>!!ڐ*!&& ~҆*!&g:!<2!a 8o!!6>!!*!&& ~*!&6 ) N#Fg:!<2!¡͘* & ~/͘!!qD>!! :}0:}`O! ~ * * Ḿ2!>!!/:}o&"!~i8 Eiji:!@@†Ìi B:% /:!րHҽ:!@@:!:! *! DM͟ *! DM͟ >͑: AO !!6> !!x:! ].*!&*!>O:!<2!G!!q!!6*!& :•>*!& :!©:!:!<2!Â!!r+s+p+q)!!6?:!:!2!*!My2 !!6: ]:!/ *!M1}CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321 Copyright (c) 1982, Digital Research 10/27/82Show 3.1ERROR: INPUT: OPTION: DRIVE: Unrecognized Option.Unrecognized drive.Requires CP/M 3 or higher.No directory label exists on drive Unrecognized input.A:0B:0C:0D:0E:0F:0G:0H:0I:0J:0K:0L:0M:0N:0O:0P:SPACE0DIRECTORY0DRIVES0LABEL0USERS0PAGE0NOPAGE !$'*-/#(.[]=, :;<>%\|"()/#!@&+-*?;Zx0NSun$Mon$Tue$Wed$Thu$Fri$Sat$?????????????Directory Passwds Stamp StampLabel Reqd Update Label Created Label Updated------------ ------- ------ ------ -------------- --------------Press RETURN to continue.: Drive Characteristics128 Byte Record CapacityKilobyte Drive Capacity32 Byte Directory EntriesChecked Directory EntriesRecords / Directory EntryRecords / BlockSectors / TrackReserved TracksBytes / Physical Record, Space: &  ͦ*!M *!M * ~& *!M! !p+q!" !* !"  " * ~~He Q ! 6 Þ * ~~Hқ ! 6* ~2 ͢ * &* " !Þ !-!p+q!!6.*,!DM! -¶ !' !.!6> !.! *.!& ! N:.!<2.! \* ##N!ͥ"/!!1!q:1!2 Oͅ !3!p+q!2!* >2!y#M͹!7!s+q+p+q:7!=27!f*4!:6!w*4!#"4!I!!s+p+q+p+q>!*!*!͆!!s*!*!͆"!*!! ͆"!>!º:!:!!!6:!0Ov!!p+q!'"!!!6>!8*!*!͆:!=2!O!8! s*!*!͆"!*!! ͆"!!!6#6:!=2!}*!&8! ~0O~:!:!Hz,~A!!q*!&8! ~¤:!Ҥ:!ʤ*!M!!6!!r+s+p+q!!6#6>!!0*!&*!*!&*!~!!#N*! w*!&*!^! ͆!!s#N*! ^! ͆*!&*!q:!<2!!!p+q8!<?!<*!N#F*!##~2!!!6>!!ڙ:!҇*!&w!) N#F?!ͱ:!2!:!<2!d8!?!ͱ9!!p+q*!##~2!*!##~*!##w*!*!q#p*!#:!*!#w!!p+q*!#* ##N͹Ay2 ?:!2 ͩ:!:!2 : 2!:!2!!!6:!2!?:!Jñ*!& *!*!&*!=2!!!:!£!!6!!6:!!!ڠ]:!/Җ6:!<2!~æ6!!6ͩ>:!2!:  l+s#r): * #" :2 :!:!2!*!&*!~2!*!&*!:9:!<2!:!2!*!&*!:!(*!&*!~2!!!6* ~2!:!2!!!6* #~2!:!<2!*!&*!:}!!6Ó*!&*!:!ʓ!!6:!<2!*!&* ~2!*!&* ~2!*!My2 : : H: H: H:!<2!*!&* ~2!*!My2 :!2 :  l#+s#r* Ny2 !D* #" ):  +"!!!6: !!y*!N*!#"!:!<2!W!!q*!&ͥ^ *V& ~ʞ*!&ͥ^ *U& ~ʾ1*!&ͥ^ *T& ~*!&ͥ^ *W& ~#*!&ͥ^ *S& ~: :: 2 * & : w* #" * Ny2 : ZÔ!: q!: qÔ* &ͥ^ *V& 6* #" >* &ͥ^ *V& ~* &ͥ^ *V& 6ʹ2 !X: !$ 6!Y: !$ 6 {,subtopic}... EXAMPLE: HELP> DIR BUILT-IN $? HELP Topic:$Not found$No HELP.HLP file on the default drive.$1?1?!E6!,6͈"-*-|*-}0HҷN1=2/1<_! p{201!C6!C6ͷ 2j:A+::BJ: \u\͡2 :?/;1X:j\!)6X!,62j:j&!)61x͛zdʛ͚=x͛˜!)6,V 2E H:E/ ,V 2E:E/ IX,V 2E H*jM.,V 2E H,V 2E HPX,V 2E H!)6:E/2j\\2D:ZNEv!Kq*K&!Mp+q*L !Op+q*N !Pq*P& !Rp+q*Q!Tp+q *S 6 *S 6*S!Vp+q*U!Xp+q*W!Zp+q*Y!\p+q *[ 6 *[ 6*[!^p+q*]!!`p+q*_!bp+q*a$!er+s+qX*dDMXX:ctE!jr+s+p+q+q*f*gDM*i -’!nr+s+p+q!o6#6:p *p&*k~ H *p&*k*p&*m  *p&*k*p&*m u*"*M! 2þâ%:<2 u͑lF2F͑\2NfuF2!"*+!*))))  :d*))))  q#p*"҇!":=!6!ͣ DM%)2͑F2F͑\2N*"|u\2!E6:E/!"*":E/>!HҴ!ͣ DM%\ʝ!E6ñ>+s#r*#"d!"*+!!ͣ DM%2͑\2N*"ҺP\02NC*NBXUX \ku\͡oxN FuF͑F\2N%!6\2:/H:Y$!6è!E6:!E6F2ͼ":E/ҽ!"*":E/>!H]!ͣ DM%\F!E6Z>+s#r*#" !"*+!ں!ͣ DM%FʭF2F͑\2N*"c\NFF͑NX!"}22:)* &ͥ^ : =O 6-͑iE!: :>!: G>Zʹ2!_Þ:!=2 * & : w* &ͥ^ *V& 6!: ʝ* +" ͑iE! 6* Ny2 !* &ͥ^ *V& 6! 6!: ;2 -: K-!: !!: !L! 6* #" !: K* Ny2 !K?͑iEi`N#Fog_og_ogDM!>))덑o|gҟ =DM!>))Ҵ =¬~ º~ ^#V) ^#V|g}o _{ozgO{ozgi`N#Fogo&og_{_z#W !o6 !o6!p6 :p<2pí:o!qq:q<2q>!qR \H !q6R !E6!q6:q!sp+q!t6:@/!C *r~<*rwO:/ X*r6*r~ž x*rwÉ X*r~½ \*rwE *r~ !t6*r6  H *r6 H:tͼ"u*u"w!{6!"y:{/>!wH҇ >y)))) DM%\O \o&"yN*y)))) ~$e !{6:{/҄ >w+s#r*y"y %>w:{/HҶ \o&"yN!|6:! !|6:!| *|& ~ *|& 6 *|& ~, *|& 6 :|<2| !|6!:|*|& ~ HA :|<2| *|& ~.d :)2}*|& 6 i !}6:}2|> !|ڛ *|&͏x u:|<2|o :}2|!~6!6#6*~& ~:/H! *~& ~  !6*~& ~ *~& ~[H*~& ~H: :| HHҥ *~& >`*~& ~{Hp *~& ~ *|&͏x *& HqÔ *~& *|&͏x *& w:~<2~:<2 :|<2|> !|! !6 *~& ~[ :|=o&͏x ~ :|=2|*|&͏x 6<2: ,:)!"#**"!"1!6*"!":/G*)))) ~$^!6D*))))  :!:/Ұ!6,V 2:›0XáCX,V 2X**0&p>ͭ,V 2 H!6> !*& 6 :<2!6$ *)))) DMuX*#"=*))))  ~!=!6*#"=:],V 2X%!6#6!6#6!":/:/HҼ*)))) ~$ʴ*))))  :)<{*)&͏x *)))) ͛2:q *)))) *)&͏x u:)<2):/:)2!6>!)n&͏x ~ H*)&͏x ~[Hb!6!6n*#"!6x*#"ñ:Ҫ*))))  :Ң*#"ç!6ñ*#"ù!6z:**#"**))))  DM}u*))))  #DM~u!6*))))  ~2D*))))  ~2):!q!6!::E/Hҙ,V 2E:E/Җ!6:!{X:<2a*&͏x DMX:<27 H*)M.:E/ҷ,V 2E:E/\\2DN!6:/:E/H\H1?:P2ÄCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321 ERROR: $ $ Press RETURN to continue $ $Reading HELP.HLP index.$Too many entries in Index Table. Not enough memory.$ $ Creating HELP.HLP....$$ HELP DATHELP.DAT not on current drive.$Too many entries in Index Table. Not enough memory.$$ HELP HLPUnable to Make HELP.HLP.$Writing file HELP.HLP.$Writing file HELP.HLP.$Closing file HELP.DAT.$Closing file HELP.HLP.$HELP.HLP created $ Extracting data....$HELP HLPUnable to find file HELP.HLP.$HELP DATUnable to Make HELP.DAT.$Writing file HELP.DAT.$Unable to Close HELP.HLP.$Unable to Close HELP.DAT.$Extraction complete HELP.DAT created $ Topics available:$ ENTER .subtopic FOR INFORMATION ON THE FOLLOWING SUBTOPICS:$ $ $ $Reading file HELP.HLP.$ HELP> $Requires CP/M Version 3$,HELP HLP HELP UTILITY V1.1 At "HELP>" enter topic[:~<2~:|<2|!6 :~<2~î !?6#6#6#6>!|'!6: '*&͏x ~[*&͏ ~C !A6:|==2|*&͏ ~E¤ !B6:|==2|*&͏ ~N !@6:|==2|*&͏ ~L !?6#6:|==2|*&͏ ~ :|==2|:|=2|!6 :<2= :|&X!6>!` *&)))) >u:<26!6>#w#6ͼ"*" \Ju\͡WN!E6:E/\H"!6:ր:E/H*& ~!E6*& ~/!6:E/*& ~/H**M! 2:<2::E/H*& ~0*))))  w*M! 2!6: :E/H*& ~ H*& >`*& ~{H*& ~ *)))) *& w*& *)))) *& w*M! 2:<2i:E/\5*))))  }u*))))  #~u*))))  N#F *))))  q#p*))))  :w*#"*!p>ͭ:<2>+s#r>:E/H\2vN*"*! *)))) A:D=2:<2O>/:/H*& ~29!E6!6:/:E/H:*& ~/HHҗ:<2*M! 2*& :=O! w>:§!6ò*& 6$:E/:/H: :@/H,V 2E*MH>!X!6 !D6!E6u,V 2Xh*& 6!,6ͷ 2::?/H_1X:_ogDM!>))덑o|g҉ =wDM!>))Ҟ =–^#V) §_{ozgi`N#Fogo&og_{_z#W $ORDS WRITTEN $CANNOT OPEN SOURCE FILE$DIRECTORY FULL$CANNOT CLOSE FILE$HEXCOM VERS: 3.00 $͏ ͕ %z ͍! ͍!  ͍!vCPM3 SYS CPMLDR error: failed to open CPM3.SYS $ CPMLDR error: failed to read CPM3.SYS $ CP/M V3.0 Loader Copyright (C) 1982, Digital Research $ _ ?"(yڥ!2(2(:(2({2(!" #"(9"@"1"!N(y2!K!!!dڛ&_^#V*("""""""""""""((("""";(""""A(G("""""""""""""""""""""""w!7$c$7$?c$#)$%N(:"ž" *y!(4 5~yµ"5 6y ’" ͒":("!( Oͻ""MD"2 #>" BDOS ERR: $Select$Perm.$""" #""#"v{_zW{_zW )8## ?# w#J#J*|^#V###"(##"(######"(!( I#*(!(I#*(|!(6ʕ#67**(w#w*(w#w#w!(^#V#Fͪ#'*O##*(&%!(s#r#p*(N#F*(^#V#F*(:(O}|y$*(%#^#V"x*vw*zw< *zw#"zw:w*~w*zw`;w*w#*x~og)))))*~w*zw`;> GA;*w *x~og)))))~*~w*zw`;w*w*x~og)))))*~w*zw`;>GA; *|w#"|w "x*x | !x/F><,;!x!8yC"~w*x)>og;"vw :w R9 %>B'!E>;%@!<,;!:ySx !w6!w6!{yD><,0;!yySu !w6{ ͔( ^#V"y*y^#V"y:y *w*y)))))~2w*w*y)))))*w:wog)))))> GA;:w!F :w *w:wog)))))6 :w *w#:wog)))))og^|n !w55r !w5*y+"y*w+"w:w *w | *w#*w^|± *w#"y!yͨ!yͨ*w*w<"w:w=2w:w !w4Ó ^#V"y>2y:zw2y:yog:yog< *~w:yog`;~c *~w:yog`;~*w*y~og))))) >2y:yog | *w*y~og))))):yog*~w:yog`;:yogx͛:ʳ !y4W *~w:yog`;6c*zw+"zw:y!y4 >I*xw"w!yL !"zÃCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321A͑"w*w}1ҫ!wE><0;!w!w6!w6!w"'x!%xy2w:w!)x"w*w~2w*w~og |2w:w !+x!/x!F:w_>͉:G!w>A;2wRf%!DB$![D>6;!!D;!!w>;!!-E> ;!@%*}!w;@!7Ewx͛:!8Ewx͛:"w*w:wog<,;!3x!rx*7C~og#))+"w*w#"w!HG"wbj"w!txDͺ(xx~# RE%!E>;%!F>;%@Ra%>B'!F>;%@*xx~2|x!F"w*w+:|xog!Gx͛:*w+:|xog*wx͛:R%!(DB$*w+:|xog>;!@!|x4nR%>B'@÷}x~# R%>B'!G> ;%@@%*=*w+*}x~og;@*w+*}x~og>;!9E>;!SE>;ͥ*w+*}x~og;*w+*}x~og#G>GA;*w+*}x~ogF>k}*xwÑ ̀*zw"w*w+"w*w+"w:w*w"w:w2w*w*w*w>og^w*w#"w*w"w:yog#"w*xw*w< :y<2y:w2y:yog:yog*w#"w*y4nS^#V"y*7C~og*w *y~og)))))~og<*y"y!y 2y:y:wog#>og^"w*w<:wog"w*~w:yog`;*w*w)))))*w `;>GA;*~w:yog`;~*w+*w)))))*w `;w!w6P^#V"yR;%!-DB$!E>;!*y;!!E>;!@RL%>B'@(^#V"yR%>B'*y;%!-E> ;%@%*!w;@!7Ewx͛:!8Ewx͛:>m2y:w2y:yog:yogog^|*w:ÀCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH251082654321!9"k1G \!m!w# š!v6H#6E#6X!e6C#6O#6M<<&:g.".g"?S:2n!`w #4o"c*e{ozg"hj:]@*c"\y!5C*^N{zb+"^*^*`*h"!j4&"h"y:b<5*kG!gwxS0  *cN,*cN{zҽ{,*c*e{ozg ~*c#"c> :[ >  X N*c>:> !:q#G*eDM*h ERROR: $DISK READ$LOAD ADDRESS LESS THAN 100$DISK WRITE$LOAD ADDRESS $ERROR ADDRESS $INVALID HEX DIGIT$CHECKSUM ERROR $FIRST ADDRESS $LAST ADDRESS $BYTES READ $REC<"w*7C^#V*w<*w<"w*w>og;#"w*w*w*w>og^<"w*7C^#V*w<!xE><0;!x*w>og;#"w*w*w*w>og^<"w*w*w^+++*w>og^}2w!Hg"w*w"w!HW"w*w*w<*!xͨ*w*w<"w*w+"w*w+*7C^#V<|z*w"w*w"xw!xD:w2w!x͂ :ww!xD!x͂ aÀ!xͨ!|w# À}!"w*7C^#V*w<|!xD*w"x2x:w2x:xog:xogw!F6*w:xog)))))~!Fe!HG:xog)))))6*w#"w!x4!xͨÚ!w6!"w"w"zw"|w!w6*w`~!F­!w6*7C^#V*w<2x:w2x:xog:xogog;#"w Byog)))))6+:F*w:yog)))))w>2y:yog |e*w:yog))))):yog6!y40!y4^#V"y!F6*w*y~og)))))"y!z"y>2z:zog |*y+:zog~g.*w *y~og)))))~g.`|!z:zogw!z4á*yGx͛:R-%>B'!G> ;%@RI%>B'!2G>;%@c%*`! z;@! z>;!9E>;!SE>;ͥ! z;>2z>2z:zog |! z:z_>͉:*y+:zog>͛:!zF><0;!z!z5!z4Ò!"w"w"w2Rz2Vz2Wz"w*w*w"Szgo"w!HW"w!Hg"w*Sz*w<!XzD2Uz:w2\z:\zog:Uzog*w#"w:Vzog*w<|!mz͜:Wzog*w<|!qz͜!*w+"w:Rz!uz!yzÙ}z~# %*w*z~og)))))*}z^#V*z~og)))))> GA;*w#"w*z4*z~og*w<|˜*z~og#>og^}*zwz~# ¡*z"z!zͨ*w*w"w*z6*w#"w%z~# *z~2z:w2z:zog:zog<\*))o |O#"9C[4BZ!9SJ~#$:> $J&9}x2LCy j2MC"){AE$:RC+-/x2LCy2MC"){Aͯ:LC!MCP& G7!9~#$&*){7<$2;C2PC2SC<2KC!9 V+iv-v>2PC#ҏ… ʉ ,v.¦#Ҧ,×eʰE+-#2QC$!LC5¡:MC!OC<_!;C>w w>+!NC~5>. G:QCx0:NC> !PC~ 5!NC4!KC5-2QCx!KC^4{# # !;C~0>0"+{*9C~2/{:PCA Ϳ"A <:/{20{>Vͬ"!0{S 5~/o :SC‰ >9ͬ"ʉ >*ͬ"w  y *:0{!9q#=€ Ï">21{<22{23{ 2.{:2{_:/{"*9C~2-{:-{9 :1{ :1{21{͟" :3{=O:1{##:3{O:.{#͖"Õ Z *A!O:1{!y*|*| r:*| nb5)*| !|>=;O)!|>;*|:!|;*|~#{)*|^#V)))|{)*|6P#6*|~#µ)*|^#V))|)*|6#6õ)*|6<#6*|6#6*|6#6*|6#6*| 6*|^#V}4}2|*|^#V} *!|44*|^#V}"*>2|*|^#V}M**|~#M**|6#6*|"|*|"|*|"|!|(0*|^#V|Š**|"|!"|!|͚=^#V^#VOA:Cڨ*!*͚=2CO!C·*6ü* +~#w!C s#r!C4A**C** I/O Stack Overflow!9"|!|*+!9$>'+%~T]O ++~+>x^#V"|*|6͌+;,T+!C"}!" }!}͚=M,]+^,2}:}+,ͩ+:|> b€+,Æ+ͩ++>,;,+V,+D,+Ì+V,+:}+^,+,^,++D,+M,+,,é+!`C6M,+V,+D, ,:|!`Cw,+g,2|*|~!,:|*|#*|~ogw*|4:|:| :|,:| ?:|':`C‡,!TC"}! }81,! }6Ò,:`C2 }!`C6: } ڡ,*XC#"XC: } ±,!XC6#6: }"3" 3*3^#V#"3^#VͿ,,"$3,"(3|,|~Ϳ,,ya-Az^#V:zog)))))6>2z:zog |U*z^#V:zog))))):zog6!z4!z4*w+"w*z~og+"w*z"z*z"z!z͜2z:w2z:zog:zog<*z^#V:zog)))))6>2z:zog |*z^#V:zog))))):zog6!z4ý!z4Ë*w*w<$*z"z!zͨ*w*w"wA!z͵"Hw͖!z͛"twåz~# I*z^#V*w;͍6!z>͓7!z͚"w!z͌!zp"w!z͘*z"z!zͤʤ!G͊= z~# ­*z^#V*w;͍6!z>͓7!z͚"w!z͌!zp"w!z͘*z"z!z!zͩ ![͊=m^#V"z!z*zr::z52z9!z5!z͛"tw!z͵"Hw*Hw|f!zF><0;!z*Hw^#V"Jw*Hw ^#V"7C*7C^#V*7C~og#;͍6!Lw>͓7*7C###"{!{A#͍6!Pw>͓7!Tw"z*7C ~gj"z*7C~!z W#:>2z:zog |l*z++:zog)w#w*z!zF:|e*7C^#V |H:z=*z+:zogwe:zog+*z++:zog)s#r!z4×^#V"{*{>l7!Lw>l785"{!{^#V"{*{>l7>5!Lw>l78>55*7C ^#V^#V"{*{>l7>5!Pw>l78>55>^#21{:1{)!:.{0)!:3{O:-{*#!> #;!:1{21{:3{O:.{#͖"Õ :-{͟"!:-{"†!:-{"o!:3{O:-{##͖"Û :-{21{:3{O> #͖"Û :1{!:.{0¢!:3{O> #!:3{=O:-{##:3{O:.{#:1{21{!:3{O:.{#͖"Õ :-{V":1{":1{21{͟"":3{=O:1{##:1{ "<21{͚"Û :3{O:-{"H":1{3":-{B="?":1{*?"> #͖"Û :3{O:-{CV"D:PCi"> # #Æ":-{C}"# >R#Æ"# >B#͖"͖"Û :0{*+{!3{4!2{4S+-$G:/{Ox*9C## ¶"<>Sͬ">+ͬ">-ͬ">Cͬ">Dͬ":/,.B!2{N*9C# Ⱦ"G:2{_:/{O x*9C# Ⱦ#!i#9w$G:PC8#x+-L#SF#x+L#-SI#>+>-> F$ h#x=b#G#O# #:kCx#ډ#!ZCxO#ډ#$O#'O# £#O#> $Õ# µ#x¯#>$O# ##O#x#>O#='#$x!XC#$#:iC#$:XC> $#>29{!7{K':iC+$!XC+$> 3$> 3$3$26{!4{'!:{Ú=ê$$^$^#Vʃ$a$ͪ$F$#F|$#N|$#^#r+s#^#V++r+s~F$5F$$5^$q#pF$O$4~ $_$s#r#s#r#q!$Ú=$$C$$ Format Overflow*C-&C![{ =.:;<>[]y *"3, -(-,$-,1J- o&))))\xH  g-#w g--"-*(3#ʖ-AҖ-G-,:ʛ- 6à-p4-+4--#,-#*½-6?-w-¬-,---#6 -..- 4-.,.#*-6?.w--,.-.#6 .%#6.*(3##^ ~?1.# *.xCON CON RDR PUN LST M!L. ~"-$.-,1ҕ.\|.l.$.!~ .-!9.,°. ʾ.-#Ý.x=GÚ.->ɯ*(3+.^#V.#{#z.6#6. r+s!}F#~*/!}6P  eA eA!}^r+s6 #6 !}4^N*(3|Z/}=G/.V/R.R/O>~f/f/>ͨ/N*(3|’/YR.=/y‹/eAÎ/>~ʞ/=ʞ/>ͨ/q2-3*(3/"*3./{..**3*(3#:-3O/.#s#r/../.è/.r+s{0!'34**3+>|0+}o͵,Ϳ,~2&3Ϳ,""3,:&3.1[.a0G:&3.1*$3p[04#63,:&3|00*3++"3Å0}+ʉ00}|23"3,0"31F<|.1##"(36*$3s#rv-š2{ ʚ2*(3:&3w060*3"3<1:&3š20<ʚ2!V" {*7C^#V* {^#V<&!S͊=* {^#V͍6!Pw>l779`^#V""{!${"&{!"${*"{~*&{w*${ruq!U͊=Û͇!({;!GG({x͛:ʙ>ɯB^#V^͞#V ͪͪ"  Later CP/M or MP/M Version Required$*}**}{ozg|g}o!\!l!*:3>:͞!L*3>͞K* !*ͤ͞ ͤ  >  ͤͤͤͤͤͤͤͤͤ͞ͲͲͲͤͲͲ Ͳ͞ Ͳͤ!Ͳͤ"Ͳͤ#Ͳͤ$ͻͤ%ͻͤ(ͤ1^#V#^#V́"> ́"> > ́">́{2> ́"́">́"> 2!2`iPY*}~##~#fo##^#V#{_z/!T]W{_z<KB ^#V^#V)F<*}!9{ozg| #~wþ.%O:Cy+%!9G'%~#'%%y.%O:C=%Æ%͹%F%{N%*iC|w%j& *iC*XC<#<> %> %͹%> %{=>'%!9ʨ%=~#'¡%{>'%%Ì%{=>'%{>b%*XC++|2{!{'ɯ%>%>2|" |" |`i" |!9"|!{%[| ~# %*[|~n&*[|~C&!U|>;G3!!!C(!C"i|!g|͋*k&!U|>;G3!R.!!C(!C"m|!k|͋*À&*]|"o|!o|͋*!q|(*a|^#V!aCs#r*c|^#V!cCs#r*_|^#V:|*qC:|G&!u|('*_|^#V}*qC}G&!w|(':C '*_|^#V}*qC}G '!y|(':C''*_|^#V}''!{|('^#V"}|!C"|*}|"|!|͚=2|!|K'^#V"|:CZ':C'*|'*|5!|6:| ʀ'ͳ'r'a'ò'!|'*|'*|5!`C6!|':`Cʯ'*|6Ì'g,2|:|'!C"|!"|!|͚=!XC6#6!|6 :C'!|'^#V"|!TC"|*|"|!|K1%(!C"|!"|!|͚="((:C(*|~ ?(*XC#"XC(*|~ S(!XC6#6(:C(*|~ u(*\C#"\C!ZC6#6(*|~ (*ZC#"ZC!ZC#(!ZC6#6*ZC*kC#<|(!C"|!"|!|͚=('!`C6"|!9"|!|(! 9^|~# (*|^#V|)B"3*(3(3w# 1*(3~#3*(3 B>3*$3w#w3͵,,34/Ϳ,q3͵,,3Ϳ,Nm/3*(3~" 4#4#4͵,,3~Œ11K43.>13͵,,3~.>13*(3~ʹ1>31P43*(3!*~!/2,3*(3|1(^#V,,{z1z]22'3z(2:,324/q#2Nm/#2*(3|]2*~]2=!'3Z2:,3ͨ/W2S2w:2^1>͵,,3|}3~> 3<3͵,,3|”2*$3w=3*(3$B*$3^#V6+6++<3͵,,3>3"N#F#~Ϳ,q#p#w>3͵,,3>3*~,!2=2>!*(3" s#r#w=3* 3 }!m}6 4>2l}*i}!4#4#4~#N#F#y#x#:l}*i}!!:k}ʈ3]3G3:m}~G~#~O?3#~3! p! y! q<33.3~3#!!3! 6?<04= _!x$4*4FN4wxG>O>G!$q#p#6R4"f}"i}2h}x2k}.32l}>3!h}~54m3ʘ4=4:k}4*i}<˜4G34*f}:k}O*i}:m}´4y O4:k}G3*f}w# 4N3:l}4*i}!]343*f}"f}g4:l}/g.>Q={zQ=}|Q={+=+=i`~sw#r##q#p i`N#F#^#V~Q=q4#p+i`##s#rW=Bs=B FREE Request Out-of-Range$ Free Space Overwrite$GKҲ=Mbkò=?F~?N~?N#F~?^#V"Cy2Cx=i&Ϳ@==x=>=!C{#z*aC*cC@xyx >c>_!?^#Vͺ>]>>(_>y͖>>)_>|@>R>'?|L>R>ͺ>>B>,_>]>> _eA eA eA0:_>_>m>m>]>|{>}{> ڦ>dԨ> ͨ>ڳ>ê>xm>N #~_>ü>!?ͺ>*}!9{_z>{> ?>]>>#_>*}>=^#V#͇>??>: "?>?_>!?ͺ>ͺ>>=_>^#V|W?}N?.))@ú>#F>A?> #r?~ >.?~ ?=c?^#V# File: Traceback:???????@ ERROR FIXED OVERFLOW OVERFLOW UNDERFLOW ZERO DIVIDE END OF FILE UNDEFINED FILE KEYNULCONCONRDRPUNLSTBADG!C~N@3@B Condition Stack Overflow$4Ox!t} w#s#r#s#r!9!C s#r!CN!t} +++++‡@#{ @#zʥ@++~Ç@++!C5!~# ´@ð@!CN!t} +++++@#~#@+{@#z@++~@#^#V=!C~Gx|g}o5@5!9VzwzO#5<599! 9/GO~9O9~q+d5!96#=w5O!9Fx7yҮ5! 9~WwzO+›55_ /!9~#=557"n}>6*n}"p}56*p}"p}56*p}G!9!xb6 ]6+/6$%?'w#6-!9~R7&7~#R77! 9~.87+60D70D76 #,7+r>o&9y>o&90w+i76.7w#Ì7 O~#¢7Gxڵ77 9> 79#7!9!97>?'w#7!9͛8! 9͛89! y@88!9o>g~18Gx8f848!9!w# L898!9!9!'#s8!9^{w{W#‡8~W8~+¶8ê87>?'w# þ88!9~#88!99#8>OA5:C_!C^#V"CTC.~# !A*qC)))))C )| 6A*TC|}*D"XC:C*CTCw# \A*D{ vA zA!#"DìACopyright (c) 1980 Digital Research, v1.3 !"}"}"}2C2C*} A"}q#p##}o"}*}o|ABB+w+w+r+s4w#w#s#r<2}++*}s#r"}*}#"}*}DM!}x~¾B#~+¾B+F+Nq#p*}+"}ʹBҼB=oB!+~O~#~G!/x—ByʴB >O6# ŽB ~B=ɯ ~#fo++-B!}~#B*}$BBCBC  Insufficient Memory$ Invalid I/O List End of Execution$(CdSYSINSYSPRINT    30INITDIR WILL ACTIVATE TIME STAMPS FOR SPECIFIED DRIVE.1Do you want to re-format the directory on drive: Do you want the existing time stamps cleared0Do yo/?'w#•9'w#¦97>?'w##´9^{w{W#9!9Ú=9999!9MD^#V# + w9ȇ :):Wf.0:r~#fo0:s#r!>O @:)8:|W}_ W:|}o|gG:yx/Wy/_{zW{_e:yw# r:~#É:~#W #ÿ:F#"r}x;:*r}!9G_>WObk++:~+:y~#//); ;=;);ɯo>g{ozg!<Ú=<<CC|| }} }}DM -  ̀  ͥ! 6>! B *   Nͥ: <2  ! r+sp+q+q! 6: =! ڊ * &* * &*  ʀ >: <2 W >_ogDM!>))덑ogҳ =¡ DM!>)) = O{ozgi`N#Fogo&og_{_z#W0i  ͍=; =”͍Lᯕo>gL,>#!u^#V#0}o|ge X x| y0ʃ GÏ y 6 >! һ: =2 ҝ! 6* &) : ! ҸÃ*{ ~2 *{ ~2 *{  ~2 *{ #^#V" +!͚ ! s@! 6: ɀ"#DIRLBL 1!M CP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321!`i^#V#~#foͽ{¡y#wG:xA##6?)@w){#{s333333.;;33,;;#wD{_#6 sO O ڹ.:;=,/[]<>a{Ҷ_#  ý Copyright (c) 1982 Digital Research File not found or no directory spaceInvalid file name.Directory Label attribute set Read Only (RO)Read Write (RW), set to ERROR: READWRITEDELETENONE on off LABEL @ @Option requires a file referenceOption only forw'xFwwww5xwwwxwwwwwwwwGwwwxxwxxwwxɀSAVE SAVE y<1!~ʋ;:* ͩ".~>2`*.h~`>26!*#~2#~2r+s-* 1!~ʀ#_6|ʉ#6?#6 #6$\<8Y‰\>!|w\:V"8: V "**Ͳ\h}}€!*:2\<T}Q**#s#r>2:Ÿ*.h6 1>2::>2}2|2!"  !!\( yŽw=G::xAڎҎa{!_Î 4 4(!~> L5*~#"a_:f7ñ8 ʱ0vñ@7ñ҇0ÒGڐ7ñ7o:O& ʦ))))ÛzW{_f: CP/M 3 SAVE - Version 3.0$ Enter file (type RETURN to exit): $ Delete $ Beginning hex address $ Ending hex address $ $ ERROR: Bad close.$ ERROR: No directory space.$ ERROR: No disk space.$@$ $H I$I!$HI"$$"$ I ! A  !B B@@ $ABH$!"D$"B\D0F30F40NAME0PASSWORD0PROTECT0RO0RW0SYS0UPDATE0PAGE0NOPAGE"%(+.3%\|"()/#!@&+-*??Directory Passwds Stamp Stamp Stamp Label Reqd Create Access Update -------------- ------- ------- ------- ------- Press RETURN to continue. ?Password ? Disk I/ODrive Invalid Drive.Wrong Password? in filespec.?ONOFFsystem (SYS)directory (DIR), Drive Default password = Password = Label for drive Protection = or protection not enabled for disk.Modifier: Option: FILE: 1!1!1 ""*"}2W#|2X#̀ 2"!"6:W#0w n ͎ 2!ͽ l 2"*U#& ~ œ !U#4Æ *U#& ""*U#& ~[ *"#""B!:" o ! !!6 S :" *"""B Q͟ 9 :"!"" g͟ !!6= :"1 !!6= :"= !!6]B |M !"6 :"k *"""!"6o P &͟ v!!q*!& y !!p+q*!~ʯ *!Ny *!#"!Õ   y  y ͹ :! !"4~<<+~H ͹ ͹ 0 ͏ Ͱ  :-#"!# *! DMK!-#4*"*!#DM*"K!0#s+q+q:"G:"Z!"6͟*.#&" ~z *! :/#wÆ *! :0#w:"ͥ:"21#¤!"6:1#´!"6@:1#!"6 !"6 " :":"2"!:"͟:"21#O>͟ 4*!  !3#s+q:"0:"C!"6͟*2#&" ~b*3#&*!>wp*3#&*!>w!"6 ͏ !"6 "͏   F  U *! >µ͏ û͏  *! >@@25#*! >͏ ͏ :5#͏ ͏  *! > ͏ ͏  *! ~1 v ͏ :"K͏ Ô:"@@^͏ Ô:" q͏ Ô:"/: " HҎ͏ Ô͏ :"Ҥm͏ v!6#q*"|. :6#͘, ͷ:" :6#*!DMͧ "" :6#*!DM "" ! ""*"|.͌:6#(, +͘>>*!DMͧ ""*"}t*"|kͥX*"|h͌͘t͘͟*"}ʘ *! *! ~ژ͘*!DM ""*"}*"|ͥ*"|͌, J͈͟>!"(:"(:"(  ͓EB "#GB "#IB "#B "#B " #B " #2"O ! "K!T#p+q*S#""""!!"" ""*"DMS :"Ҙ ͟!!6C  !͏ >"9!ʬ !"6ñ !"6!\K9 :"!:"  e͗ :" ͙ :" 1:" ͗ :"!!"6!?!!"6 _ogi`N#Fogo&ogDIRLBL yd'* !9"1>"#2#:Og}**Ip2~w2i#1#":R2!:! !"6͹ ͹ !!p+q *!DM͏  !!q*!&!!p+q*!!!p+q*! !!q*!&-!!p+q"u *!"!!!p+q"u *!d!!q*!&e!!p+q"u *!f!!p+q"u *!g!!q*!&) ^#V%!!p+q*!! #q: #2"!"6"1!#r+s+q:#2"!"6*##s#r"1!"6#6"1x >"9!® *"DM͏ ö *"DM͏ J ͏  "̀"##1! ͑ >#9!*#~[ !"6 *#~] !"6*##"#!"6*#!#s+q+p+q:#=2#J*#:#w*##"#-!#s+p+q+p+q:#=2#ʁ*#*# w*##"#*##"#Z: 2#aڛ:#{қ:# :#!#p+qx *#DM͏ M  " !#6>!#?͂2 # *#&" : #w: # ?: #ý: #-:#ý:#=2#O!" 6 : #8 !#4Ͱ 2 #:"AOy :y F!!#6> !!#ڋ:!# s.y *!#&*!>Oy !!#4]x *"|2"#x F͉ :"#¸Y ͏ :"#b ͏ M͏ :"#M͏ :"#i ͏ :"#x ͏ :"# :" :" ͟"*͘͟!"6:"?:"?:"2":"2!! ""*"}Š*"|}ͥj*"|z͌͘Ê͟  :"¦:!2!!2 o&""͘2:!:!=2"*"MC ͽ !7#6> !7#*7#&\ ~?>!7#4>ͭ! \K!"K:] :e HY!"6&"u \S 28#O!\"!͘͟ *8#M^!"6!:#s+q*9#&)))A *:#& ~!;#q!<#6*<#&u :s—>*<#&u :;#«:<#!<#4Ä!@#r+s+p+q!G#6:H#:H#2G#*D#M{2"!L#6:"=:L# *D#M{2":A#2"}>:A#2"2K#:H#2I#!L#6:H#2G#:H#Dß*H#& *?#*H#&*?#=2J#!K#–!L#6!B#6:K#!B#ړ=:L#ڌ0!B#4uÙ0}>:""!+s#r:"*"#"":2":I#:G#2M#O*?# ~2C#*C#&*=#:s!M#4~2H#*C#&*=#:D#*M#&*?#~2C#!H#6*"~2D#:C#2E#!A#6*"#~2D#!E#4N*=# :tW!L#6m*E#&*=#:D#m!L#6!A#4N*" ~2D#*A#&*"~2D#*D#M{2":":"H:"H:"H!A#4N*" ~2D#*D#M{2"Õ:A#2""!#+s#r*"N{2"!Ͷ :O~!ʫ:<2Ž:"2"x2*# O:ļ:<:G>O*# :<t tIw!/>!/>!*6 #:_#:*Y" Y" Y" >*Y"#####Y"##Y"Y"Yz2*Kg"ɯ22!"*DM6:O* 2~ ~ †:<~:2>2:<** "_?:<2>!/:<}:2* ~b W6 y2> # vwm>2>!/ N *~O²+—">2>!/*:< "~G # p *~w#  : *8*:*8yO:O*}O= ~ w#P^#V#ɷ{ozg |g}oh:<͉̉O<OBKBK$'-*!*^#V" ͏ !##q&"u  S 2##!$#q:$#>:$#o&&""!:\w!"6!"6&"u *#EZ *#GZ *#IZ *#Z * #Z * #Z "*#DMKc 2%#¡>*%#M>!'#q=͏ :'# ͏  ͏ p͏  Z ͏  ͏  ͏  ZM͏ W͏ ]͏  y  Z!Ay Z/1y Z=2y ZK3y ZY4y !(#q*(#&*!~q>>:"ڒ:"ڒ&"u \S O!)#q:)# ¨ͅ 2*#ò*"M 2*#:*#  F͉ p͏ :)# M͏ W͏ ]͏ :"*"M 2+#!"6>!+#Ia:,#o&&""! >w*! ~ F*! ~F!"6[!\"!]K!"6&"u S 2,#:,#ʗ:,#`O!&" ~ Žc 2,#p U͉ ͉ :"!"6*! !K!"6+6! ""}*"|͌͘͟:!2"!"6:" ͟" *"*""K"j  ! "6"͏ :"b:"Tͥ͟:"2"p *! >w " :"‰!"6!"6*"*" "K:"ҥ:"Ҹ͟!"6*!#  >!"3!-#6:"=!-#"*-#&*"~.*"*!#DM*-#K*"#"":""9!+"O#!N#6:"!N#A*O#Ny *O##"O#!N#4"!"6!"6!"6:"Z!:"e!:"p:ͳ2"„"!:":"#H!:":"=o&)))A ~ھ+:"=o&)))A  ~ lNͳ2"4:"=o&)))A *"& ~=*"""!"6#6!Q#6:"=*"N{2"*"#""!Q#4!:"X*"N{2"*"#""!Q#5>:"=Œ*""":Q#2"O>҉e͟!"6:"= ¶*""":Q#2"O> ҳ!"6 ͟*""":Q#2"O>͟!"6:":"=o&)))A ~HF:"=O!" 6>!":"=:"=O!" HqQ͟X͟X͟O!͟OG͟X/  ^:  Q:"s ":"ҁ":"ҏ":"ҝ":"ҫ":"ҵ͝:"ҿ?:"͇:":"!":"!":"͟͟ P:"):"!"64@4:"P:"F!"6@44:"!"t:"h͟͟ Ø:"҅ "Ø:"Ҙ!"6 ":"ҩ 4:"!";͟  :":"!"6  " ͓ :" :" !"6  "DDD  $$HD@" @@ $B $$H$H$HH$$! HD$D$D@AD HD$!A" ogDM!>))덑o|gҟ =DM!))Ҵ =¬~ º~ ^#T) ^#V|g}o _{ozgO{ozgi`N#Fogo&og_{_z#W H% : " :#$ͪ:;!6+~<;!6:$¨D2$X*M å:02O> p<ͪå!6͝:ʔ!5K ҎÄ͝xK ҥ*M Ô" :^D2:^^ :@: O :`:@O :`O " :!:/H     " *M : 2    *++" *& ~2 :Ht !4>>!""\ !6>!ڷ :+ ~° !4‘ * DM*"À * DM!" }2 ͣ2 :  ͪõ!q!r- "w * :w:C w *#" "*#~22_! 8!0!s*&:0!s!6ͳ:  sͳ:  L!`i^#V#~#fo yo w G: xAo o a{ ASUB 1xCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321Invalid file name $Error On Line $Enter Password: $ERROR: No 'SUB' File Found$CP/M 3 SUBMIT Version 3.0 $Enter File to SUBMIT: $SUBDisk Write Error$Random Read $.$Invalid ASCII Character$Parameter Error$ERROR: Directory Full$Requires CP/M 3.0 $11G"*}0|HҤbP2IK 1">d*++"~"!\. v!q*&!p+q* !s+p+q*:w#6* *#"N#Fy !p+q*!p+q*2 !p+q*!p+q*!p+q*!p+q*!!p+q*2 !p+q*!q*-!q:2!61!s_o     `i~< #~2#~2#~2*| W \!\~R 2 .n~ >2 6!.t~: +  >2 6!N#F#*" ^q#Vp" N#F##"^q#Vp" 4! 7o |  ! 6   \\ ? >_ 1m :~# yo ɍWARNING: Cannot redirect from BIOS $ERROR: Auxiliary device redirection not implemented $ERROR: Insufficient Memory $""SYSIN SUB_ogDM!>))덑o|gQ =?i`N#Fogo&og_{_z#W00001 : $SYSIN $$$  F!M!T![!b!i!p!, until the program terminates. Then console output reverts to the console. Printer output is directed to a file until the program terminates. Then printer output is put back to the printer. PUT with the SYSTEM option directs all subsequent console/printer output to the specified file. This option terminates when you enter the PUT CONSOLE or PUT PRINTER command. ///2Options [ {ECHO | NO ECHO} {FILTER | NO FILTER} | {SYSTEM} ] ECHO specifies that output is echoed to the console. This is the default option when you direct console output to a file. NO ECHO specifies that file output is not echoed to the +q:2!6*&"1!p+q*<!s+p+q+p+q:=2d** w*#"*#"=  !s+q+p+q:=2ʩ*:w*#"Ì!p+qe*DM!\.\s!q:a:{: :O2:eel !6>!ڜ2 K*&l :w: T:_:…:r:=2O!l 6 3:•!4**& ~ ~ H!4Ýl :S*Q*Sl.l\P"*}=*|&el\P"=*|5.*& 6!6͝*& ~( 2*& 6e!"!\" "\p.e.:\2O>:2\*& ~ ~H~ H.!4͝*& ~2!6>!`\̓[>!6:<2=O! ~2 ½:<2O>9ҽ!60+~9ҽ!60+~9ҽ!60+~9ҽ!60+4:͓ͪ!"!6:= !6!6#6D2:EFGET :<***.n6.t6 LL!p:~y !6 <ʊ~"x!=F#fh!:~!«!>w~:!5*.~w:; :~!9"1A#u.t.~@w :&/3͖!~6 :~wucy! ʎB d{<ʑ  '*2.2+6.w 22*2$*.6#6*.~w#~=~#4Ʌo$͖O̓!54  !F6#ȷxO҃>^̓@_: N#͖§>  *.>wÔ#wt~xڔp> ̓ 8>""SYSIN SUB hhhhhhhhhhhhhhWARNING: PROGRAM INPUT IGNORED $ . \ - v! q* &! p+q*  ! s+p+q* : w#6*  * #" N#Fy  ! p+q* ! p+q* ! p+q* ! p+q* ! q* &-! p+q* ! q: 2 ! 6 1! q: 2 ! 6 1! r+s+q: 2 ! 6* #s#r 1m % %!% s+q+p+q:% =2% ʍ*" :$ w*" #"" p52& aڧ:& {ҧ:& :& XX>l c!' 6>!' 6͎2( *' &l :( w:( 6:( ÷:( $:' ÷:' =2' O!l 6 :( /!' 4~2( !) q:) R>:) c>:) t>:) ‚>:) >!+ p+q** ~ʯ** >@O%:%!, 6> !, :, .%*, &** >2- *- M%!, 4´!. q>:. >:. 1>!0 p+q*/ ~ ~ H?*/ #"/ */ ~K>>!2 p+q!3 6#6:3 ҁ*1 ~?s!4 6!3 4*1 #"1 ]:4 : : <2 ! >52  %: ·: ! 6! 6lͷ: 2 ! 6 ͇" * }= * |2 % i!v"/!Q/+>c!K-6*/K>XG!+>yC!Q/+>c!+Q/>r–!}o|g}ʖ!#"/!/–!/ʖ!/+>c!/ͷ~g"B,U"G-!,,> c!o0ͷX:F-!,,> c!q0ͷ~*G-w#w:F-X!s0͡!F-6*G-*G-^#V#)))"I-*B,*G-^#V))W+"B,*B,>og"@,:F-f!,,> c!y0ͷ~!{0!+Q/>r2K-*I-w#w2P/>2O/2N/!/(,>t!"N-:F-X!D,LG!),>y :#!#6!Q/D,>_:O/!N/:N/2O/2N/!P/4!}0!0*L-#"L-!0A !/*!/>X!/>Xt!D,KLG!.,>y:O/!N/f:N/2O/2N/!/>X!.,!,@!D,KL(,tî!N/4!,/>c!0!0!0n !N-~#!0̓ ã!0ͬ!D,/,>c!0~U!9"0:#Z!#6!#"/r*/>$Gt!##>Gt!#0,>Gt!#6!#6!#"0!0T!F-6!"#!D,6!06:0}͐3>!D,ͧd*0!F-6!#6*##"#*# |.!"0}20!0>!#*0"0!0U!#"0!0+!#*06*0 "0!04í!"#: 151282 COPYR '82 DRI gggggggggggggggggggggggggggggg"D! BH!H@ $!!$"A! D$DHH$B!"  @A  _og_ogDM!>))덑o|g26 = 6^#V))) DM!>))R6 =J6_og^#V) h6^#V|g}o r6_{ozgO{ozgi`N#Fogo&og_{_z#Wi`N#Fog\ͫXlͷ: 2  ͇" = > ͑ %* M=* } ͷ! 6! 6: / ͧH ! 6>! * & ~2 — ! 6:  ~Ү 52 : : ͅ* M%! 4w [ =ͷ\26 =:6 :6 o&"7 E"9 G"; I"= "? "A "C .*7 DM -J :\2 ͅX ͑:%ͅXͷ*9 E)*; G)*= I)*? )*A )*C )!; \e .*; \ - 26 * ~ * ~ H * #" !`i^#V#~#fo:  y  wO G:L xAڠ Ҡ a{3 _à  F F : i`N#Fogo&og_{_z#W+.!+6:# :# :#.~!#*#~20:0 20:0Q~:0Þ:K-z"/!0Ur"/*/ 3,>Gt!0#!D,6,> c!0ͷ~Ͳ"0~# ¦*0^#V"0*0^#V"0͕!1"1!216>261251:!12:1::1!51!!1:51og~271:21!216{:71!61281*0:61o:81OLG!1>c:81og>og}281*0:81ogW"0*0:81og####"0*0*0W*00>c*0";1!;1ͷ~>291!1n&}2=1:=1!91*1:91og"1*1~og |*1>ߦw*1~?*16_*1~@*16`!914å*0++*0)"1*11>_*0^#V"31*0^#V#r+s*1*0*0^#V)))s#r*0:61_L*0*0^#V)))>t*0*0^#V)))w#w!31#`*0*31)))^#V1j`*0*0^#V)))"1*1!1>Gt*0*31)))"1*1*1>Gt*31+"31*0*31)))^#V1j!31#T*1"1*0*31)))"1*1*1>Gt*31+"31*11>Gt:71%^}2C1:C1!A1$ *0:A1_LG!>1>t!0>1xy!0>1xy !B14:A1!!1:B1o1 ÊCP/M Version 3.0COPYRIGHT 1982, DIGITAL RESEARCH151282654321 Press RETURN to Continue $ ERROR: Not typed: $Password: $No File$ BDOS Bad Sector$ Invalid Drive$Currently Opened$Password Error$ERROR: $Invalid or missing delimiter(s) $Try 'PAGE' or 'NO PAGE' $Requires CP/M 3.0$Enter file: $ $ERROR: Invalid file name. $1 1 u" * }0* |HҴJ>O/4\>(N2 i>!6 * & 6! 6: ,v! 6> W ʹ * ~‘ù* ~[ʟ* #" * ~N* #" * ~O* ~ H* #" ! 6 * ~P! 6* #" * ~]* ~H$ù* ~A0×* #" * ~]* ~HTù* ~G`×* #" * ~]* ~H҄ù* ~Eʐ×* #" * ~]* ~Hҹ: : /2 : ==2 : ! 6! 6\O2 : Egw!0>1xy :B12!1!A14ì*00>c*0"D1!D1ͷ~^#V"F1*F1^#V> ͍!H1 *!H1> XÓ1~# s !9"2!1"1!16*1w#w*1ng | *1KLG!1>yº !1**1~ogQ1~og)1^#V*1^#V#r+sH !11>c !1*>22*1~ogQ1~Y !11xyK !24H :2K !1!1> !1* *1*1^#Vͯ1>_ *1~ogQ1~ !1*{ !1*!11xy !1*é !1**1~ogQ1~ !1* *2:1 !16!"1*1n&"1*1"1' *1#"1*1*1W7 *1*1>Ó*1~og |c !1>ߦw !1~?t !16_ !1~@‚ !16`Y2 ~# ˆ *_2^#V"e2*c2^#V"g2!"2*[2^#V"2*2*2W *]2*2ͯ"2!2 :2 *e2*2)))~# *g2^#V#*e2*2)))s#rc *e2*2)))^#V"2*g2*2))~#K *g2*2))^#V"2% *g2^#V#*g2*2))s#r*g2^#V#r+s*a2^#V*g2^#VW !i272>!c!2ͷ~*2+|´ *Y2^#VO"2þ *Y2^#V"2*2*g2++*g2^#V))s#r*g2*g2^#V))w#w*2#"2ô 2~# ^#V^#V  $ "/  Later CP/M or MP/M Version Required$*#=**#={ozgY|g}o!\!l!ÍÝ3>Ý!*3>K* !*   >    !"#$%(^#V^#VF3O3*# 72gl*<"?'w#-!9~sG~#s4! 9~.Y+60e0e6 #M+r>o&9y>o&90w+Š6./G! >0 >-3T]))#V"J#~#.~# !*#)))))# )| !*~#|}*#"#:L#*J#~#w# F!*#{ `! d!!#"#Ö!Copyright (c) 1980 Digital Research, v1.3 !"!="="%=2]#2L#*'= !"=q#p##}o"#=*}o|!""+w+w+r+s4w#w#s#r<2)=++*!=s#r"!=*=#"=*=DM!!=x~¨"#~+¨"+F+Nq#p*=+"=ʣ"Ҧ"=Y"!+~O~#~G!>w!/x"yʞ" >O6# x" h"=ɯ ~#fo++"!=~#"*!="²""""  Insufficient Memory$ Invalid I/O List End of Execution$#dd(Copyright (c) 1980 Digital Research V1.3MXList SYM *26*2LG!X2>yC *2"3*3#~>!3w:3og2~C :2 !26*e2^#V#"3!3"323!3> *3++| !"3Ñ *3>og"3*3:3og)2s#r!34d !" 3*e2^#V" 323*2"3!3"3* 3* 3W_!34:3og)2^#V" 3*e2*3)))^#V"3*2*3j/*3+" 3* 3* 3"3!36\*3*2jY*3#" 3* 3* 3W"3!36\Û :3o* 3"3u* 3"3*e2*3)))^#V"3*2*3jʛ*26*3*2s#r3 ~# ±*3^#V"#3*!3^#V"%3! ÷>2.3*3~ʟ*34*3~og"3!3A !/3*!/3>XG!3>y.!/3>X3t!/3>XG!3>y[!/3>X3t*3!3>}23:3ʐ!/3>S*3:3<_Lt*3"3!3ö*33>_*3"3!3!;3"93!3*3>!t!<3"53!L33>Gt!Q33>Gt!"'32.3*'3*#3^#VW*'3#"'3*#3*'3)))^#V!<3>p!")3*)3 |*53+*)3"73*73~ ]Æ*73~_n*736?|*73~`|*736@*)3#")38*#3*'3)))!M3>Gt*#3*'3)))^#V")32-3!)3~#ʖ:-3 ͟!<33>t!M33>t2-3!-34*%3++*)3))^#V"iO>`G>0 <  DM0 > Ew#E~#X~#W #Ý!9Oo>gy~#o>gxGGtwF#"WObk++~+ y~#/~!>)< D=M)6ɯo>g{ozg!dÄlmnpr Conversion2!Ä*%=|^#V"%=###^#V#N#Fxʿ #~ò*%=|^#V#N#F!9yx"%=:L# !9!#{z#  !!9:]#O!^# {#z!]#5#}OD*#=~r##~#fo9!NÄVWXZ\ Free Space Exhausted##^#V#{_zW;{_zW>4z˜{##^#V# ##s#rs#r#s#r+++~sw#r####}*#=}|5*{z5+F+N+V+5^{;{z;}|;{+3:,31!Q3:-3ogͯ3>Gt*+3O"+3M!Q3:-3ogͯ3>Gt!3A !/3*!/3>S!L3:-3ogͯ>t*%3*)3))^#V")3ø͟!.34*3~!.3!t:-3ogͯ}!;3w!;3~w*93:;3=_L3t*93!3>_!3^#V"<:F4!F46*<KLG!H<>y+!E46ð!E46!4"$Gt!'4I<>Gt!*46!>46z"!4*<@*<"r2<:E4:<>2<>2<*Gt!^<<xy;!<8!<5!<͛#E!<͛!<5:22%^}2<:!4*<@*<"!4*<@*<"2<*t!<͆!<4!<͆i`~sw#r##q#p i`N#F#^#V~;q4#p+i`##s#rA"]" FREE Request Out-of-Range$ Free Space Overwrite$GKҜMbkÜiFhNhN#Fh^#V"#y2#xүi&ͩ x>!J#{#z*#*# xyxM_!^#VͤG>(Iỳ>)I|*<|6<ͤͶò">,IG> _O! O! O!0:IIWWG|e}e ڐdԒ ͒ڝÔxWN #~Iæ!wͤ*=!9{_z{ G>#I*=>=^#V#q>: >?I!oͤͤ>=I^#V|A}8.))ä#F>A> #\~ >.~ =M^#V# File: Traceback: ERROR FIXED OVERFLOW OVERFLOW UNDERFLOW ZERO DIVIDE END OF FILE UNDEFINED FILE KEYNULCONCONRDRPUNLSTBADG!]#~8  " Condition Stack Overflow$4Ox!< w#s#r#s#r!9!^# s#r!]#N!< +++++q #{Š #zʏ ++~q ++!]#5!~# ž Ú !]#N!< +++++¹ #~# +{ #z ++~ù #^#V=!L#~9!5:L#_!M#^Fd$PlPRINTER busy XREF 1.3 no SYM file no PRN file CP/M PRNXRFABORTED. V́ + 1@+>!9"11COMPARE Version 2.02 08-Apr-80 $ͨeG;*#"*:ր=2**}=2_Y1ʽ2ʽ3;2~!"""" 7> 0 ?))) O !}L ) | {0_E_? :?#+|ʆ:2w}e^^e^: G:B*Ð Difference Found: File 1, Sector $at byte $ File 2, Sector $ Do you wish to continue ?$ $ $ Enter (1) To Offset File 1, (2) To Offset File 2, (3) To Offset Both, Or for No Offset: $ Number of bytes to move FORWARD in File: : $ Moving FORWARD $ bytes in file $:2!:2! |}> _ 0\2>22͘ EOF on File 1, Not File 2 $*}!"*#"*~#"2  FG1"z*QS cE5T @///,,D,B,G-,Q/D,D,L-,D,D,N-P-L-N-P-G-@,I-P/O/Q/G-I-D,000//D,symbol table overflow ' invalid SYM file format lXRF.XRF make error  '.XRF close error .XRF write error <<<_<<b22͘ EOF on File 2 before File 1 $*|P* l*͘(HEX) Sectors $ COMPARE ERRORS found, Length is $ Files MATCH, Length is $!l!]?!e?~#2"* Ɛ'@'_::G:2> ?~#y S *~~q s>.?#y ‹ d:2*"!]?!e?~#XXXXXXXXYYYou enter the PUT CONSOLE or PUT PRINTER command. ///2Options [ {ECHO | NO ECHO} {FILTER | NO FILTER} | {SYSTEM} ] ECHO specifies that output is echoed to the console. This is the default option when you direct console output to a file. NO ECHO specifies that file output is not echoed to the  { *$'symbol table reference overflow 22i2 0# +333*=zW{_-ʠ)җ)} DMoxGyOÁ)|}o|g}o|gK)#|5ng),|}o|gzʄ*|g}o)zʄ*}o|g)͑*#||!„*#Ä*~#fo}}|r)!ʄ*+Ä*}o|g"*."*{_zW**-"*ʄ*>)D**OxG|* ?T*} =Š*}/o|/g!+ñ*ÿ*o&ÿ*͙*!**͙*K* !+*ñ*͙*͙* ͙*_+͙*  ʴ*>ô*  ͙*͙*ñ*͙*ñ*͙*ñ*ñ*͙*ñ*͙*ñ*͙*ñ*͙*ñ*͙*ñ*ñ*͙*͙*ñ* ñ*͙* ͙*!ñ*͙*"ñ*͙*#͙*$͙*%͙*(ñ* chain (see SETDEF). ///2withOptions Syntax: DIR {:} [options] DIR {filespec} {filespec} ... [options] Explanation: The DIR cmmand with options is an enhaned version of the DIR built-in command and diF alv&dn: ds (dsm/4)+2 csv&dn: ds (drm/4)+1 endm ;;-------------------------------------- ;; MACRO - COMPUTE NO. DIRECTORY BLOCKS ;;-------------------------------------- rsvdir macro dn,drm,bsiz x defl ((drm+1)/(bsiz/32)) y defl 080h done defl 0 al0&dn defl 0 al1&dn defl 0 rept 8 if x eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 done defl 0ffh exitm endif al0&dn defl al0&dn or y y defl y shr 1 x defl x-1 endm y defl 080h if done eq 0 rept 8 if x eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 done defl 0ffh exitm endif al1&dn defl al1&dn or y y defl y shr 1 x defl x-1 endm endif if done eq 0 db al0&dn ; directory block allocation 0 db al1&dn ; directory block allocation 1 endif endm ;;----------------------------------- ;; MACRO - COMPUTE DRIVE SECTOR SIZE ;;----------------------------------- ssiz macro secsiz if secsizð**(}+*(}+"(*(x+"(x+m+*(^#V*( s#r*(*(s#r*(:(Y+4Y+̓+*(*(~#ng+*( s#r ^#V|:(w:(ʴ+>2d,:+#++>29+2~2#! , , ,)x,) ,O +"!w [,O?WGzO:(V,xGyOG,xwq*}(}2*i(^#V+ d,!(K*}(@+*)):( K:(ڗ>2#-×:#-<)2#-*(BI$"" HB@ UUUUUUUUUUUUUUUUUAPDA$! @I !@D@BDI@!B$ @$I$$ "@$$@@HHBD"D$H D@!IB@ A"B HBIB$$ "$ D$!"D$H$D$I@D BD" H$BHHBDHB"H!": ld de,nrdymsg ; pass disk err actual error msg call dskerr ; display msg and drv on console jr z,tstrdy ; retry if user didn't type ctrl-c ret page ;------------------- ; FLOPPY DISK ERROR ;------------------- dskerr: push bc push de call pderr? ; display T-????, S-???? msg on console pop hl ; restore pnter to err msg call pmsg? ; display exact error msg on console if media_check_en xor a ; allow media change checking ld (fdbusy),a call conin? ; wait for user to type a character ld hl,fdbusy ; disable media change checking ld (hl),1 ld (char_save),a else call conin? ; wait for user to type a character endif cp 003h ; check if ctrl-c typed push af ld hl,crlfmsg call pmsg? pop af pop bc jr z,diskerr ; jmp ovr retry if ctrl-c ld a,fint ; reset floppy controller out (fcmd),a call delay xor a ; set z-flag ret diskerr: or a ; if here, ctrl-c entered, set nz-flag ld a,rtrys-1 ; load a w. no. of r eq 128 db 060h ; sdh reg sec siz 060 = 128 bps else if secsiz eq 512 db 020h ; sdh reg sec siz 020 = 512 bps else if secsiz eq 256 db 000h ; sdh reg sec siz 000 = 256 bps else db 000h endif endif endif endm ;;------------------------------ ;; MACRO - COMPUTE SHIFT FACTOR ;;------------------------------ shff macro num @y defl num @x defl 0 rept 8 if @y eq 1 db @x ; log2 (num) exitm endif @y defl @y shr 1 @x defl @x + 1 endm endm .list e ixsave: ds 2 noflag::ds 1 ; drive # exempt from media chng end  ; CONSOLE OUTPUT STATUS ;----------------------- cost?:: in a,(1) ; get status and 4 ; ready? ret z ; no or 0ffh ; else set ready ret ; and exit end CP/M 3 PUT Version 3.0 Put console output to a file Enter file: source in de and dest in hl ldir ; use Z80 block move instruction ex de,hl ; ret w. next addresses in same regs ret bank?:: ret ; no bank select in non-banked system end BYTE CP (HL) ;CHECK IT RET Z ;RETURN IF OK PUSH HL ;SAVE ADDRESS LD HL,M4 ;TYPE ERROR CALL MSG ;PRINT IT POP HL ;RESTORE ADDRESS STOREA:: CALL THXW ;TYPE BAD ADDRESS JP NEXT ;RETURN TO MONITOR ; ; ; MEMORY EXAM/MODIFY ROUTINES ; ; GETAD:: CALL GHXW ;GET ADDR. JP NC,GTA1 ;JMP IF VALID ILLCH:: LD HL,M3 ;ILLEGAL INPUT JP ILLEG+3 GTA1:: LD (ADR),HL ;SAVE ADDR. LOCAT:: CALL CRET ;GET CR,LF LD HL,(ADR) ;GET ADDR. CALL THXW ;PRINT IT CALL SPACE LD A,(HL) CALL THXB ;PRINT MEMORY CONTENTS CALL SPACE CALL GHXB ;GET DATA OR COMMAND JP C,NONHX ;NON-HEX INPUT CALL etrys minus 1 ld (rtcnt),a ; no retrys, errchk inc rtcnt first ret page ;---------------------------------------------------- ; Save IX & IY, then load dph (DE) to IX & dpb to IY ;---------------------------------------------------- gitxy: ld (ixsave),ix ;save ix,iy ld (iysave),iy push de ;dph to ix pop ix ld l,(ix+dpblo) ;dpb to iy ld h,(ix+dpbhi) push hl pop iy if media_check_en call chk_last endif ret ;------------------------------- ; DELAY 28u SECONDS AT 6 mhz ;------------------------------ delay: ld a,3 ; initialize loop counter delaylp: ex (sp),hl ; 19 cycles ex (sp),hl ; 19 cycles dec a ; 4 cycles jr nz,delaylp ; 10 cycles = 52 cyc = 8.7 @ 6 mhz ret ;------------ ; Delay 5 ms ;------------ xdelay: push bc ld b,200 xloop: call delay djnz xloop pop bc ret page ;------------------------------------------------ ; DATA STORAGE ;------------------------------------------------ nrdymsg: db ', CP/M 3 PUT Version 3.0 Put console output to a file Enter file: ly selected disk drive @RDRV: DS 1 ; controller relative disk drive @TRK: DS 2 ; current track number @SECT: DS 2 ; current sector number @DMA: DS 2 ; current DMA address @CNT: DB 0 ; record count for multisector transfer @DBNK: DB 0 @ermde:: db 0 ; fake BDOS error mode endaddr:: END  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 ret end $D$ $I"B IIBB"$B@DH"$$ IH $$ !I"AD B!B  BI$A$"@$I$!!""@Ɛ'@'_::G:2> ?~#y S *~~q s>.?#y ‹ d:2*"!]?!e?~#XXXXXXXXYYYNumber of bytes to move FORWARD in File: : $ Moving FORWARD $ bytes in file $:2!:2! |}> _ 0\2>22͘ EOF on File 1, Not File 2 $*}!"*#"*~#"2GDrive Not Ready',0 wprtmsg: db ', Write Protected Disk',0 crlfmsg: db cr,lf,0 lastdrv: db 0ffh cdsd: db 0 ; current dsd rtcnt: db 0 ; retry counter tkwant: ds 1,0 ; track we want during login sbase: ds 4,0 ; login vars to match search params dentkb equ sbase ; base track den dentkn equ sbase+1 ; next track den sdbit equ sbase+2 ; side bit slen equ sbase+3 ; sector len code ixsave: ds 2,0 iysave: ds 2,0 end disk change flag set? ret z ; no, exit ld hl,(cdph) set_md: ld de,mf add hl,de ld a,mflag ; flag media change ld (hl),a ld (@media),a ret page ;Check selected media for change chek_media: call delay in a,(fstat) or a ;drive ready? jp m,chk_er ;no, jump in a,(dsk_chng) and dsk_chng_msk ; disk change flag set? ret z ; no, exit chk_er: ld de,medmsg call dskerr ;patch -- kill change flag ;push af ;ld a,(cdsd) ;ld b,a ;or 3 ;out (fdsd),a ;ldw fdph1 ;B dw fdph0 ;C dw hdph0 ;D dw hdph1 ;E dw hdph2 ;F dw hdph3 ;G dw hdph4 ;H dw hdph5 ;I dw hdph6 ;J dw hdph7 ;K dw 0 ;L dw 0 ;M dw 0 ;N dw 0 ;O dw 0 ;P page ;--------------------------------- ; Disk Parameter Headers -- DPH's ;--------------------------------- ; Floppy DPH's ; Floppy drive 0 dw fwrite dw fread dw flogin dw finit db 0 ;floppy unit 0 db dtyp8 ;drive type fdph0: dw 0 ;xlate vector ds 9,0 ;scratch db mflag ;media flag dw dpb8sd0 ;dpb -- "largest" one for gencpm init genstuff gendo db 0 ;raw dsd ds 1,0 ;current track adr db 00000001b ;floppy restore command db 00011101b ;floppy seek command db 00011001b ;floppy seek-no verify command dw dpb8ss ;first search dpb ds 1,0 ;true dsd page ; Floppy drive 1 dw fwrite dw fread dw flogin dw finit db 1 ;floppy unit 1 db dtyp8 ;drive type fdph1: dw 0 ;xlate vector ds 9,0 ;scratch db mflag ;media flag dw dpb8sd0 ;dpb dw hinit db 0 ;unit db 0 ;drive type hdph7: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb7 ;dpb -- "largest" one for gencpm init genstuff 0 page ; SemiDisk DPH dw swrite dw sread dw slogin dw sinit db 0 ;unit db 0 ;drive type sdph: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw sdpb ;dpb -- "largest" one for gencpm init genstuff 0 page ;-------------------------------- ; Disk Parameter Blocks -- DPB's ;-------------------------------- cseg ; Floppy DPB's ; 8" sssd dpb8ss: dw 26 ;spt db 3 ;bsh db 7 ;blm db 0 ;exm dw 242 ;dsm dw 63 ;drm db 0c0h ;al0 db 0 ;al1 dw 8010h ;cks dw 2 ;off db 0 ;psh db 0 ;psm db 26 ;hspt -- host sectors/track db 1 ;hlspps -- host logical sectors/physical sector db 0 ;pdsd -- primary dsd for this disk type db sngl ;track 0 den db sngl ;track 1 den db 0 ;side code db s128 ;sector size code dw tran8s ;xlate table adr dw dpb -- "largest" one for gencpm init genstuff gendo db 0 ;raw dsd ds 1,0 ;current track adr db 00000001b ;floppy restore command db 00011101b ;floppy seek command db 00011001b ;floppy seek-no verify command dw dpb8ss ;first search dpb ds 1,0 ;true dsd page ;----------------- ; Hard disk DPH's ;----------------- ; Hard disk 0 dw hwrite dw hread dw hlogin dw hinit db 0 ;unit db 0 ;drive type hdph0: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb0 ;dpb -- "largest" one for gencpm init genstuff 0 page ; Hard disk 1 dw hwrite dw hread dw hlogin dw hinit db 0 ;unit db 0 ;drive type hdph1: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb1 ;dpb -- "largest" one for gencpm init genstuff 0 page ; Hard disk 2 dw hwrite dw hread dw hlogin dw hinit db 0 ;unit db 0 ;drive type hdph2: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb2 ;dpb -- "largest" one for gencpm i8sd0 ;next dpb to check page ; 8" ssdd -- ADC format dpb8sd0: dw 64 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 303 ;dsm dw 127 ;drm db 0c0h ;al0 db 0 ;al1 dw 8020h ;cks dw 1 ;off db 3 ;psh db 7 ;psm db 8 ;hspt -- host sectors/track db 8 ;hlspps -- host logical sectors/physical sector db 8 ;pdsd -- primary dsd for this disk type db sngl ;track 0 den db dbl ;track 1 den db 0 ;side code db s1024 ;sector size code dw 0 ;xlate table adr dw dpb8sd1 ;next dpb to check page ; 8" ssdd -- Hank's old format -- 1k sectors dpb8sd1: dw 64 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 299 ;dsm dw 127 ;drm db 0c0h ;al0 db 0 ;al1 dw 8020h ;cks dw 2 ;off db 3 ;psh db 7 ;psm db 8 ;hspt -- host sectors/track db 8 ;hlspps -- host logical sectors/physical sector db 8 ;pdsd -- primary dsd for this disk type db dbl ;track 0 den db dbl ;track 1 den db 0 ;side code db s1024 ;sector size code dw tran8d0 title dtbl Disk drive definition tables .z80 true equ -1 false equ not true check_media_en equ true global @dtbl, diskbf ext fwrite, fread, flogin, finit ext hwrite, hread, hlogin, hinit ext swrite, sread, slogin, sinit if check_media_en global fdph0, fdph1 endif mflag equ 0ffh ;media flag gendo equ 0fffeh ;flag for gencpm -- tells it to fill in vectors sngl equ 0 ;single density code dbl equ 1 ;double density code s128 equ 0 ; 128 byte sectors s256 equ 1 ; 256 byte sectors s512 equ 2 ; 512 byte sectors s1024 equ 3 ;1024 byte sectors ;-------------------- ; Drive type equates ;-------------------- dtyp548 equ 1 ;5" 48 tpi dtyp596 equ 2 ;5" 96 tpi dtyp8 equ 3 ;8" page 60 ;-------- ; Macros ;-------- genstuff macro csv dw csv ;csv dw gendo ;alv dw gendo ;dirbcb dw gendo ;dtabcb dw gendo ;hash db 0 ;hash bank endm dseg ;------------------ ; System drive map ;------------------ @dtbl: dw sdph ;A dnit genstuff 0 page ; Hard disk 3 dw hwrite dw hread dw hlogin dw hinit db 0 ;unit db 0 ;drive type hdph3: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb3 ;dpb -- "largest" one for gencpm init genstuff 0 page ; Hard disk 4 dw hwrite dw hread dw hlogin dw hinit db 0 ;unit db 0 ;drive type hdph4: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb4 ;dpb -- "largest" one for gencpm init genstuff 0 page ; Hard disk 5 dw hwrite dw hread dw hlogin dw hinit db 0 ;unit db 0 ;drive type hdph5: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb5 ;dpb -- "largest" one for gencpm init genstuff 0 page ; Hard disk 6 dw hwrite dw hread dw hlogin dw hinit db 0 ;unit db 0 ;drive type hdph6: dw 0 ;xlate vector ds 9,0 ;scratch db 0 ;media flag dw hdpb6 ;dpb -- "largest" one for gencpm init genstuff 0 page ; Hard disk 7 dw hwrite dw hread dw hloginG ;xlate table adr dw dpb8sd2 ;next dpb to check page ; 8" ssdd -- SD system's format -- 256 byte sectors dpb8sd2: dw 52 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 239 ;dsm dw 127 ;drm db 0c0h ;al0 db 0 ;al1 dw 8020h ;cks dw 3 ;off db 1 ;psh db 1 ;psm db 26 ;hspt -- host sectors/track db 2 ;hlspps -- host logical sectors/physical sector db 8 ;pdsd -- primary dsd for this disk type db dbl ;track 0 den db dbl ;track 1 den db 0 ;side code db s256 ;sector size code dw tran8d1 ;xlate table adr dw 0 ;next dpb to check -- no more when 0 page ;----------------- ; Hard disk DPB's ;----------------- ; Hard disk 0 hdpb0: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dw 8000h ;cks dw 0 ;off db 2 ;psh db 3 ;psm ; Hard disk 1 hdpb1: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dor init detect db 20h,'sEMIdISK ',1 ds 19,0 dirlchk equ 20h+'s'+'E'+'M'+'I'+'d'+'I'+'S'+'K'+' '+' '+' '+1 dirmchk equ dirlchk + (32 * 3 * era_data) dir_chk equ low(low(dirmchk) + high(dirmchk)) slogin: ret page ; read semidisk 'SECTOR' into memory sread: call setup ;set disk track,sector,byte & dma call cread ;read the data call chksum ;set a reg ret z ;ret if ok call setup ;try one more time call cread call chksum ret z ;ret if ok jp zap ; write semidisk 'SECTOR' from memory swrite: ld e,5 ;retrys for verify error rwrite: call setup ;set disk track,sector,byte & dma call cwrite ;write the data call setsum ;write checksum ld d,c ;save chksum call setup ;set up for read after write call cver ;do verify jp nz,rewrite ;jp if verify error ld c,d ;restore checksum call chksum ;verify checksum ret z ; and exit if all ok rewrite: dec e ;can we retry? jr nz,rwrite ;yes, jump zap: ld a,dsk_io_err ret page w 8000h ;cks dw 60 ;off db 2 ;psh db 3 ;psm page ; Hard disk 2 hdpb2: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dw 8000h ;cks dw 120 ;off db 2 ;psh db 3 ;psm ; Hard disk 3 hdpb3: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dw 8000h ;cks dw 180 ;off db 2 ;psh db 3 ;psm page ; Hard disk 4 hdpb4: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dw 8000h ;cks dw 240 ;off db 2 ;psh db 3 ;psm ; Hard disk 5 hdpb5: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dw 8000h ;cks dw 300 ;off db 2 ;psh db 3 ;psm page ; Hard disk 6 hdpb6: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 title semi disk driver for cpm 3.0 .z80 global sinit, slogin, sread, swrite ext @sect, @trk, @dma ext bank?, @dbnk ;ext pmsg?, conin? base equ 80h semi$data equ base+0 ;data port in/out semi$byte equ base+1 ;set byte (0 - 7f) semi$track equ base+2 ;set track (0 - ff) semi$sector equ base+3 ;set sector (0 - xx) dsk_io_err equ 1 ;disk io error flag spt equ 16 ;sectors/track nsects equ 128 ;number bytes/sector dir_entry_size equ 32 ;size of directory entry era_data equ 0e5h ;erased data byte era1 equ era_data * nsects era_chk equ low(era1) + high(era1) ;checksum of erased sector cr equ 0dh lf equ 0ah esc equ 1ah page 62 dseg sinit: call t0init ;set up to look at 1st dir entry ld b,dir_entry_size-4 ; -- but not last four bytes sloop: in a,(semi$data) cp (hl) ;does it match label? jr nz,syinit ;no, jump inc hl djnz sloop ;test next ret ;exit -- directory label intact syinit: ;set erased checksums & erase directo ; set up for read/write to semidisk. setup: xor a ;clear byte counter out (semi$byte),a ld a,(@trk) ;set track out (semi$track),a ld a,(@sect) ;xfer sector# to acc out (semi$sector),a ld hl,(@dma) ;get dma addr to hl ld bc,semi$data + (nsects*100h) ;b=#bytes/sector, c=data port ret page ; checksum set & checksum compare setsum: call chkset ld a,c ;output checksum byte out (semi$data),a ret chksum: call chkset in a,(semi$data) ;input checksum byte sub c ret chkset: ld a,(@trk) ld b,a rlca ;set track and 1 out (semi$track),a ld a,(@sect) ;set sector out (semi$sector),a ld a,b ;set byte and 7fh out (semi$byte),a ret page cseg ;common memory routines ; Read a sector cread: ld a,(@dbnk) call bank? xor a ;clr carry ld c,0 crlp: in a,(semi$data) ;read data ld (hl),a adc a,c ;form checksum ld c,a inc hl djnz crlp xor a jp bank? ; Write a sector cwrite: ld a,(@dbnk)  db 0 ;al1 dw 8000h ;cks dw 360 ;off db 2 ;psh db 3 ;psm ; Hard disk 7 hdpb7: dw 272 ;spt db 4 ;bsh db 15 ;blm db 0 ;exm dw 1019 ;dsm dw 511 ;drm db 0ffh ;al0 db 0 ;al1 dw 8000h ;cks dw 420 ;off db 2 ;psh db 3 ;psm page ; SemiDisk DPB sdpb: dw 16 ;spt db 4 ;bsh db 15 ;blm db 1 ;exm dw 253 ;dsm dw 127 ;drm db 0c0h ;al0 db 0 ;al1 dw 8000h ;cks dw 2 ;off db 0 ;psh db 0 ;psm page ;--------------------------- ; Sector translation tables ;--------------------------- tran8s: db 1,7,13,19,25,5,11,17,23,3,9,15,21 db 2,8,14,20,26,6,12,18,24,4,10,16,22 tran8d0: db 1,3,5,7,2,4,6,8 tran8d1: db 1,5,9,13,17,21,25,3,7,11,15,19,23 db 2,6,10,14,18,22,26,4,8,12,16,20,24 ;------------- ; Disk buffer ;------------- dseg diskbf: ds 1024,0 end ret end ry xor a ;track 0 call set_chk ld a,1 ;track 1 call set_chk ld a,2 ;track 2 call era_track ld a,3 ;track 3 call era_track call t0init ;load SemiDisk label ld c,semi$data otir xor a ;load proper checksum for label out (semi$track),a ;set track out (semi$sector),a ;set sector ld a,2 out (semi$byte),a ;set byte ld a,dir_chk out (semi$data),a ret page t0init: xor a ;clear byte ctr, sctr 0, track 2 out (semi$byte),a out (semi$sector),a ld a,2 out (semi$track),a ld b,dir_entry_size ld hl,dir_label ret set_chk: ld d,era_chk jp set_track era_track: ld d,era_data set_track: out (semi$track),a ;set track ld e,spt ;sectors/track setlop: xor a ;clear byte ctr out (semi$byte),a ld a,e ;set sector dec a out (semi$sector),a ld a,d ;get byte to write ld b,nsects stloop: out (semi$data),a djnz stloop dec e ;done? jp nz,setlop ;no, loop ret dir_label: ;directory label -- used fH call bank? ex af,af' push af xor a ex af,af' di cwlp: ex af,af' adc a,(hl) ;form checksum ex af,af' outi ;write sector jp nz,cwlp ex af,af' ld c,a ;save chksm pop af ex af,af' ei xor a jp bank? ; Verify a sector cver: ld a,(@dbnk) call bank? raw: in a,(semi$data) cp (hl) ;match? jr nz,cvex ;no, jump inc hl ;+dma djnz raw ;test next xor a ;no errors cvex: push af xor a call bank? pop af ret end f a command, an optional command tail, and a carriage return. The command is the name or filename of a program to be executed. The optional command tail can consist of a drive specification, one or more file specifications, and some options or parameters. ///2conventions COMMAND CONVENTIONS The following special symbols define command syntax. {} surrounds an optional item. | separates alternative items in a command line. indicates.xlist ; This library defines some of the configuration equates, etc. for the ; particular BIOS being generated. .sfcond .xcref ; Global equates -- do not change true equ -1 false equ not true cr equ 0dh lf equ 0ah esc equ 1bh ; End global equates ; Customization section sign_on macro ;Cold boot sign on message db cr,lf ;,esc,'g',esc,'f',esc,'G0',cr,0fh db 'CP/M 3.0 for Source Maverick',cr,lf,lf,0 endm media_check_en equ true ;true if able to check for disk change two_sides equ false ;true if double-sided drives ; -- must be false, not implemented mini equ false ;true if 5" drive(s) in system base_track equ 0 ;base track for login read adr booter equ 4 ;boot disk -- A: = 1, B: = 2,... ; End of customization section .cref .list ;------------------- ; SIO CONTROL PORTS ;------------------- sioad equ 000h ; SIO channel A data port sioac equ 001h ; SIO channel A control port siobd equ 002h ; SIO channel B data port siobc equ 003h ; SIO channel B control port ;------------------- ; PIO CONTROL PORTS ;------------------- pioad equ 004h ; PIO channel A data port pioac equ 006h ; PIO channel A control port piobd equ 005h ; PIO channel B data port piobc equ 007h ; PIO channel B control port ;------------------- ; CTC CONTROL PORTS ;------------------- ctc0 equ 008h ; CTC channel 0 control port ctc1 equ 009h ; CTC channel 1 control port ctc2 equ 00ah ; CTC channel 2 control port ctc3 equ 00bh ; CTC channel 3 control port ;-------------------------------- ; CTC TIMER CONTROL BIT SETTINGS ;-------------------------------- inter equ 080h ; interupt mode (no interupts) counter equ 040h ; counter mode (timer mode) pre256 equ 020h ; prescale value 256 (prescale 16 ; equates for mode byte bit fields mb$input equ 00000001b ; device may do input mb$output equ 00000010b ; device may do output mb$in$out equ mb$input+mb$output mb$soft$baud equ 00000100b ; software selectable ; baud rates mb$serial equ 00001000b ; device may use protocol mb$xon$xoff equ 00010000b ; XON/XOFF protocol ; enabled baud$none equ 0 ; no baud rate associated ; with this device baud$50 equ 1 ; 50 baud baud$75 equ 2 ; 75 baud baud$110 equ 3 ; 110 baud baud$134 equ 4 ; 134.5 baud baud$150 equ 5 ; 150 baud baud$300 equ 6 ; 300 baud baud$600 equ 7 ; 600 baud baud$1200 equ 8 ; 1200 baud baud$1800 equ 9 ; 1800 baud baud$2400 equ 10 ; 2400 baud baud$3600 equ 11 ; 3600 baud baud$4800 equ 12 ; 4800 baud baud$7200 equ 13 ; 7200 baud baud$9600 equ 14 ; 9600 baud baud$19200 equ 15 ; 19.2k baud $ˆ >!$4l >:q#<2q#O*|$ :p#w:p#?± !d#6!$q!p#6?!$:q# ͒ û 2p#:p# :p#]H!:p#A2$O>!:p# ) clkris equ 010h ; clk trigger rising edge (falling edg) clkgo equ 008h ; clk trigger starts clock (auto start) tcfol equ 004h ; time constant follows (no time const) reset equ 002h ; software reset (continue operation) ctrlwd equ 001h ; control word (vector) ?$ (H;--------------------------------- ; CP/M 3.0 BANKED BIOS GENERATION ;--------------------------------- link bnkbios3[b]=bkrnl,boot,chr,move,sdsk,hdsk,media,fdsk,dtbl,scb  operations ; ; following DS fills out end of page to allow ; next module to start on page boundry ; ds 16 - (($-boot?) mod 16) endaddr:: END  = Y OVLYDIRN = Y OVLYDIRO = Y OVLYDIRP = Y OVLYDTAA = Y OVLYDTAB = Y OVLYDTAC = Y OVLYDTAD = Y OVLYDTAE = Y OVLYDTAF = Y OVLYDTAG = Y OVLYDTAH = Y OVLYDTAI = Y OVLYDTAJ = Y OVLYDTAK = Y OVLYDTAL = Y OVLYDTAM = Y OVLYDTAN = Y OVLYDTAO = Y OVLYDTAP = Y CRDATAF = N DBLALV = Y oft$baud db baud$none db 'PARLPT' db mb$output db baud$none db 0 end ssues interupts ld hl,ctcvec ; addr of ctc svc in inter table ld a,l ; need only the low byte of addr out (ctc0),a ; better be on a 8-byte block boundry ; ie. lower 3-bits =0 ; sio initialization ld hl,isioa ld bc,isioal*256+sioac otir ld hl,isiob ld bc,isiobl*256+siobc otir ; pio initialization ld a,0fh ; use both pio ch A & B w. parallel lst out (pioac),a ; pio ch A is output mode ld a,0cfh ; pio ch b is bit mode out (piobc),a ; channel b has PRTMSG = Y PAGWID = 4F PAGLEN = 17 BACKSPC = N RUBOUT = N BOOTDRV = D MEMTOP = FF BNKSWT = Y COMBAS = C0 LERROR = Y NUMSEGS = 02 MEMSEG00 = 00,7A,00 MEMSEG01 = 10,30,02 MEMSEG02 = 00,C0,03 MEMSEG03 = 00,C0,04 MEMSEG04 = 00,C0,05 MEMSEG05 = 00,C0,06 MEMSEG06 = 00,C0,07 MEMSEG07 = 00,C0,08 MEMSEG08 = 00,C0,09 MEMSEG09 = 00,C0,0A MEMSEG0A = 00,C0,0B MEMSEG0B = 00,C0,0C MEMSEG0C = 00,C0,0D MEMSEG0D = 00,C0,0E MEMSEG0E = 00,C0,0F MEMSEG0F = 00,C0,10 HASHDRVA = N HASHDRVB = Y HASHDRVC = Y HASHDRVD = Y HASHDRVE = Y HASHDRVF = Y HASHDRVG = Y HASHDRVH = Y HASHDRVI = Y HASHDRVJ = Y HASHDRVK = Y HASHDRVL = Y HASHDRVM = Y HASHDRVN = Y HASHDRVO = Y HASHDRVP = Y ALTBNKSA = Y ALTBNKSB = Y ALTBNKSC = N ALTBNKSD = Y ALTBNKSE = N ALTBNKSF = N ALTBNKSG = N ALTBNKSH = N ALTBNKSI = N ALTBNKSJ = N ALTBNKSK = N ALTBNKSL = N ALTBNKSM = N ALTBNKSN = N ALTBNKSO = N ALTBNKSP = N NDIRRECA = 01 NDIRRECB = 01 NDIRRECC = 00 NDIRRECD = 28 NDIRRECE = 00 NDIRRE;--------------------------------- ; CP/M 3.0 Banked BDOS generation ;--------------------------------- link bnkbios3[b]=bkrnl,boot,chr,move,sdsk,hdsk,media,fdsk,dtbl,scb gencpm auto 0: set cpm3.sys[rw era cpm3.sys pip d:=cpm3.sys[vg10 set cpm3.sys[ro,sys O DISPLAY] SETDEF [PAGE | NOPAGE] Explanation: SETDEF allows the user to display or define up to four drives for the program search order, the drive for temporary files, and the file type search order. The SETDEF definitions affect only the loading of programs and/or execution of SUBMIT (SUB) files. SETDEF turns on/off the system Display and Console Page modes. When on, the system displays the location and name of programs loaded or SUBmit files executed, and stops after displaying one full console screen of information. ///2Examples A>SETDEF CF = 00 NDIRRECG = 00 NDIRRECH = 00 NDIRRECI = 00 NDIRRECJ = 00 NDIRRECK = 00 NDIRRECL = 01 NDIRRECM = 01 NDIRRECN = 01 NDIRRECO = 01 NDIRRECP = 01 NDTARECA = 00 NDTARECB = 01 NDTARECC = 00 NDTARECD = 04 NDTARECE = 00 NDTARECF = 00 NDTARECG = 00 NDTARECH = 00 NDTARECI = 00 NDTARECJ = 00 NDTARECK = 00 NDTARECL = 01 NDTARECM = 01 NDTARECN = 01 NDTARECO = 01 NDTARECP = 01 ODIRDRVA = A ODIRDRVB = A ODIRDRVC = B ODIRDRVD = A ODIRDRVE = D ODIRDRVF = D ODIRDRVG = D ODIRDRVH = D ODIRDRVI = D ODIRDRVJ = D ODIRDRVK = D ODIRDRVL = A ODIRDRVM = A ODIRDRVN = A ODIRDRVO = A ODIRDRVP = A ODTADRVA = A ODTADRVB = A ODTADRVC = B ODTADRVD = A ODTADRVE = D ODTADRVF = D ODTADRVG = D ODTADRVH = D ODTADRVI = D ODTADRVJ = D ODTADRVK = D ODTADRVL = A ODTADRVM = A ODTADRVN = A ODTADRVO = A ODTADRVP = A OVLYDIRA = Y OVLYDIRB = Y OVLYDIRC = Y OVLYDIRD = Y OVLYDIRE = Y OVLYDIRF = Y OVLYDIRG = Y OVLYDIRH = Y OVLYDIRI = Y OVLYDIRJ = Y OVLYDIRK = Y OVLYDIRL = Y OVLYDIRM ID 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,fexit ;GO BACK TO CPM CALL CHAROUT BLE 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 and 11011101b ;kill head & index bits jp z,seekok ld de,seeker call prnt ld de,abtmsg call prnt jp fexit seekok: 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  DB CR,LF,LF,'DISK ERROR: $' ; PERFORM: DI OUT (CMD),A call delay 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 fexit ;BACK TO CPM ; WRTRAK: LD A,WTRAK LD C,DAL OUT (CMD),A call delay 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 RETRY 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 call delay NEXTBYTE: IN A,(WAIT) ;WAIT FOR OPERATTION COMPLETE AND 080H JR Z,DONESECT ;DONE WITH THIS SECTOR ;  LD A,LF CALL CHAROUT ; ;RESET HEAD AND DISK DRIVE STATUS REGISTERS ld d,0 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 and 10111101b ;delete write protect & index bits cp 00000100b ;should indicate track 00 only jp z,l11 ;jump if good status ld de,tk0erx call prnt ld de,abtmsg call prnt jp fexit ; ;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 INTERRU OR A JP Z,fexit 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 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 PTS 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 DOUCP 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:ISECTOR 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 018h ;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 EG7: 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$' title monprom Super Six Monitor Prom .z80 pbase: .phase 0f000h promsiz equ 800h sysbase equ 0000h zecho equ 0ee00h fdrdfg equ 0ee01h curadr equ 0ee02h hdflag equ 0ee04h hdsdhb equ 0ee05h stack equ 0ee64h page 60 ;ports sioad equ 00h sioac equ 01h siobd equ 02h siobc equ 03h fdcmd equ 0ch fdtrk equ 0dh fdsec equ 0eh fddat equ 0fh fddsd equ 14h baudrd equ 15h baudwr equ 18h bank0 equ 16h hddat equ 0e0h hderg equ 0e1h hdscnt equ 0e2h hdsec equ 0e3h hdcylo equ 0e4h hdcyhi equ 0e5h hdsdh equ 0e6h hdcmd equ 0e7h ;ascii cr equ 0dh lf equ 0ah esc equ 1bh page JP bootin JP putc JP getupc JP cetupc JP gecho JP strout JP crlf JP space JP hex1 JP hexit JP hexhl JP getnum JP get2n JP get4n JP tstmem JP negde JP hdbadx JP fderr JP iport JP oport page bootin: IN A,(baudrd) ;set baud rate for crt OUT (baudwr),A LD A,04FH ;pon jump off, bank 00 on OUT (bank0),A LD A,020H ;set in byteNDIF OUT (WAIT),A ;TELL FDC ld bc,0 sedel: dec bc ;let the change settle in ld a,c or b jp nz,sedel RET page delay: ld a,3 dlop: ex (sp),hl ex (sp),hl dec a jr nz,dlop 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:  MSG31: DB 'DATA REQUEST$' ABTMSG: DB CR,LF,'FORMATTING ABORTED$' tk0erx: db 'Initial track 0 access error...$' seeker: db 'Seek error...$' ; ;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' for hd sdh reg LD (hdsdhb),A ; sector size 512, crc mode XOR A ;reset fpy read flag LD (fdrdfg),A LD SP,stack LD HL,inisa LD BC,800h + sioac OTIR LD HL,inisb LD BC,800h + siobc OTIR JP around inisa: db 018h,004h,044h,003h,0c1h,005h,0eah,0 inisb: db 018h,004h,044h,003h,0c1h,005h,0eah,0 around: LD HL,signon CALL strout LD HL,signom CALL strout JP boot page ;--------------------- ; Top of command loop ;--------------------- exec: LD SP,stack LD HL,prompt CALL strout CALL gecho LD B,A LD HL,cmdtbl cloop: LD A,(HL) CP 0ffh JR Z,badcmd CP B JR Z,gotcmd INC HL INC HL INC HL JR cloop badcmd: LD HL,undef woopsy: CALL strout JR exec gotcmd: INC HL LD E,(HL) INC HL LD D,(HL) EX DE,HL JP (HL) ;go to command page putc: PUSH AF owait: IN A,(sioac) AND 4 JR Z,owait POP AF OUT (sioad),A RET cetupc: IN A,(sioac) AND 1 ;char ready? RET Z ;no, exit -- z status JRPUSH 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 fexit: ld c,13 ;reset disk system call bdos ld c,14 ;reslect original disk ld a,(cdisk) ld e,a call bdos jp wboot ;exit -- wboot will restore c3 to adr 0000 ; 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 cdisk: db 0 ; ; ; ;MESSAGES MSG: DB CR,LF,'FORMATTING',CR,LF,'$' MSG1: IF NOT MINI DB 'FMT8 3.1' ENDIF IF MINI IF FORTY8 DB 'FMT548 3.1' ELSE DB 'FMT596 3.1' ENDIF ENDIF DB CR,LF,'$' MSG4: DB CR,LF,'Enter Disk Drive To Be Formatted (0-3) : $' MSG5: DB CR,LF,'Enter Density, Single or Double (S,D) : $' MSG6: DB CR,LF,'Format Single or Double Sided (S,D) : $' MSS 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 ret end J gitupc getupc: IN A,(sioac) AND 1 ;char ready? JR Z,getupc ;no, loop gitupc: IN A,(sioad) AND 7fh ;mask CP 'a' ;lt 'a'? RET C ;yes, exit CP '{' ;lt '{'? RET NC ;yes, exit AND 5fh ;upcase RET gecho: LD A,0ffh LD (zecho),A CALL getupc PUSH AF LD A,(zecho) AND A JR NZ,xbarf POP AF RET xbarf: POP AF CP ' ' ;ctrl char? CALL NC,putc ;no, echo RET page strout: PUSH AF PUSH HL stroop: LD A,(HL) OR A ;end of string JR Z,strend ;yes, jump CALL putc INC HL JR stroop strend: POP HL POP AF RET crlf: PUSH HL LD HL,crlfst CALL strout POP HL RET abort?: CALL cetupc CP esc ;escape code? JP Z,exec ;yes, jump -- abort CP 8 ;??? RET NC JR abort? space: PUSH AF LD A,' ' JR hspit page hexit: PUSH AF RRCA RRCA RRCA RRCA CALL hex1 POP AF hex1: PUSH AF AND 0fh ADD A,90h DAA ADC A,40h DAA hspit: CALL putc POP AF RET hexhl: PUSH AF LD A,H LD HL,(curadr) ;dec the current adr DEC HL JP lodlop page ;----------- ; Negate DE ;----------- negde: PUSH AF LD A,D CPL LD D,A LD A,E CPL LD E,A INC DE POP AF RET page ;----------------------- ; Dump memory to screen ;----------------------- dump: CALL get4de CALL get4de CALL negde dloop: CALL crlf CALL hexhl CALL space dloop1: CALL space LD A,(HL) CALL hexit CALL inchlc CALL abortc CP 013H ;??? worthless CALL Z,abort? LD A,L AND 0fh JP Z,dloop JP dloop1 page ;------------------ ; Go to an address ;------------------ go: CALL get4de EX DE,HL JP (HL) ;----------------------- ; Display the help menu ;----------------------- help: LD HL,helpst CALL strout JP exec inchlc: PUSH HL ;cp hl to de -- abort if c, else inc hl ADD HL,DE JP C,exec POP HL INC HL RET page ;------------------- ; Move memory block ;------------------- move: CALL get4de PUSH DE CALL get4de CALL get found? RET NZ ;yes, exit DEC HL LD A,L OR H ;timeout? JR NZ,idxlp2 ;no, loop DJNZ idxlp1 SCF RET page ;------------------ ; Floppy disk read ;------------------ fdread: LD A,0FFH ;indicate attempt to read LD (fdrdfg),A LD A,1 ;set sector 1 OUT (fdsec),A LD A,08CH ;read sector OUT (fdcmd),A LD HL,sysbase LD C,fddat fdrdlp: IN A,(fddsd) ;wait for data or int OR A ;data? JP P,fdrddn ;no, jump INI ;get a byte JP fdrdlp fdrddn: CALL delay IN A,(fdcmd) OR A ;errors? JP Z,sysbase ;no, jump to booted input fderrs: PUSH AF LD A,(fdrdfg) OR A ;have we tried to read? JR Z,getdsk ;no, jump fderr: LD HL,fderms ;floppy disk err msg out CALL strout POP AF CALL hexit JP exec getdsk: POP AF LD HL,dskask CALL strout LD A,0FFH ;reset floppy read flag LD (fdrdfg),A JP exec page ;------------------------ ; Hard disk test & setup ;------------------------ hdset: XOR A ;zap hd regs CALL hexit LD A,L CALL hexit POP AF RET page getnum: CALL gecho CP ',' RET Z ;end of # CP ' ' RET Z ;end of # CP '0' RET C ;woops CP ':' JP C,isnum ;0 - 9 CP 'A' RET C ;woops CP 'G' CCF RET C ;woops SUB 007H ;convert A - F isnum: SUB 030H ;decode RET page get2n: PUSH BC PUSH DE LD C,0 LD E,0 nloop: CALL getnum ;number in? JR NC,nisnum ;yes, jump CP cr ;cr? SCF JR NZ,bad2n ;no, jump LD A,E OR A ;any input? JR NZ,got2n ;yes, jump SCF LD A,cr ;let's pretend it was a cr JR bad2n nisnum: CP 16 ;is it a number? JR NC,got2n ;no, jump INC E ;inc it LD B,A ;save # LD A,C ;get old ADD A,A ;x 2 ADD A,A ;x 4 ADD A,A ;x 8 ADD A,A ;x 16 ADD A,B ;add in new # LD C,A ; -- and all to c JP nloop got2n: LD A,C ;return in a bad2n: POP DE POP BC RET page get4n: PUSH DE LD HL,0 SCF CCF PUSH AF n4loop: CALL getnum JR NC,4de EX DE,HL EX (SP),HL CALL negde mloop: LD A,(HL) EX (SP),HL CALL tstmem INC HL EX (SP),HL CALL inchlc CALL abortc JP mloop page ;------------- ; Fill memory ;------------- fill: CALL get4de CALL get4de CALL negde CALL get2n JP C,oops floop: CALL tstmem CALL inchlc JP floop get4de: CALL get4n JP C,oops EX DE,HL RET abortc: CALL cetupc ;abort on any char OR A JP NZ,exec RET ;--------------- ; In & Out port ;--------------- iport: CALL get2n JP C,oops LD C,A IN A,(C) CALL crlf CALL hexit JP exec oport: CALL get2n JP C,oops LD C,A CALL get2n JP C,oops OUT (C),A JP exec page ;---------------------------------- ; Boot -- floppy or hard disk exec ;---------------------------------- boot: CALL abortc CALL fddset CALL hdset fdlop: CALL abortc CALL fdrdy? ;ready to try a read? CALL NC,fdread ;yes, go try CALL hdread JR fdlop page ;------------- ; Floppy junk ;-- OUT (hdsec),A OUT (hdcylo),A OUT (hdcyhi),A INC A ;set for 1 sector OUT (hdscnt),A IN A,(hdsec) ;now, test for hdc1001 ctrlr LD B,A IN A,(hdcylo) OR B LD B,A IN A,(hdcyhi) OR B LD (hdflag),A ; -- and save result LD A,01EH ;do a restore OUT (hdcmd),A RET page ;---------------- ; Hard disk read ;---------------- hdread: LD A,(hdflag) OR A ;is a controller out there? RET NZ ;no, exit IN A,(hdcmd) AND 050H CP 050H ;ready & seek complete? RET NZ ;no, exit IN A,(hdcmd) OR A ;busy? RET M ;yes, exit hdrtry: LD A,(hdsdhb) ;set sdh OUT (hdsdh),A LD A,020H ;read sector cmd OUT (hdcmd),A hdbzlp: IN A,(hdcmd) OR A ;busy? JP M,hdbzlp ;yes, loop AND 1 ;error? JR NZ,hdbadx ;yes, jump LD HL,0 LD BC,8000h + hddat INIR JP sysbase page hdbadx: LD A,(hdsdhb) CP 20h ;sector size = 512? JP NZ,hderr ;no, go croak XOR A ;try 256 byte sector LD (hdsdhb),A LD A,1fh ;restore got4n CP cr JR NZ,bad4n CALL space JR good4n bad4n: POP AF SCF POP DE RET got4n: CP 16 JR NC,good4n ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD E,A LD D,0 ADD HL,DE JR n4loop good4n: POP AF POP DE RET page tstmem: LD (HL),A CP (HL) RET Z PUSH HL LD HL,memerr CALL strout POP HL CALL hexhl JP exec page ;--------------------------------------- ; Load function -- Display & Substitute ;--------------------------------------- load: CALL get4n ;get the start adr JP NC,lodlop oops: LD HL,woops JP woopsy lodlop: LD (curadr),HL dot: CALL crlf ;display the current adr LD HL,(curadr) CALL hexhl CALL space LD A,(HL) CALL hexit CALL space CALL get2n ;get the response JP C,lodcmd CALL tstmem lodinc: LD HL,(curadr) ;inc the current adr INC HL JP lodlop lodcmd: CP cr ;cr terminates JP Z,exec CP ' ' ;space means inc JP Z,lodinc CP '-' ;dash means dec JP NZ,oops dash: ----------- fddset: XOR A OUT (fddsd),A ;8" sd CALL fdrdy? ;is the drive ready? JP C,try8dd ;no, jump LD HL,try8dd JR fdhome try8dd: LD A,8 ;8" dd OUT (fddsd),A CALL fdrdy? ;ready now? JP C,try5dd ;no, jump LD HL,try5dd JR fdhome try5dd: LD A,018H ;5.25' dd OUT (fddsd),A CALL fdrdy? ;ready now? RET C ;no, exit LD HL,fderrs fdhome: LD A,0fh ;restore command OUT (fdcmd),A CALL delay IN A,(fddsd) ;force wait for int IN A,(fdcmd) AND 018H ;seek or crc error? RET Z ;no, exit JP (HL) delay: LD A,3 delop: EX (SP),HL EX (SP),HL DEC A JR NZ,delop RET page ;------------- ; Ready check ;------------- fdrdy?: IN A,(fdcmd) RLA ;ready? RET C ;no, return LD HL,3E8H idxlop: IN A,(fdcmd) AND 2 ;index found? JR Z,idxfnd ;no, jump DEC HL LD A,L OR H ;timeout? JR NZ,idxlop ;no, jump SCF RET idxfnd: LD B,10 idxlp1: LD HL,3E80H idxlp2: IN A,(fdcmd) AND 2 ;indexJagain OUT (hdcmd),A hdbzl1: IN A,(hdcmd) RL A ;busy? JR C,hdbzl1 ;yes, loop JR hdrtry hderr: LD HL,hdrms CALL strout IN A,(hderg) CALL hexit JP exec page signon: db cr,lf,' > ADVANCED DIGITAL CORP.' db cr,lf,' SUPER SIX Running',cr,lf,0 signom: db ' Monitor Version 3.4' db cr,lf,' June - 1983' db cr,lf,' Press "H" for help' db cr,lf,'Attempting to boot.......' db cr,lf,'Press any key to abort boot.',cr,lf,0 prompt: db cr,lf,' >',0 undef: db ' UNDEFINED',0 woops: db ' ????',0 memerr: db cr,cr,lf,'MEMORY WRITE ERROR AT ',0 ;??? db 'ERROR',0 db ' PAUSE',0 db '? ',0 db ' ABORTED',0 db 'STARTING ADDRESS:',0 db 'ENDING ADDRESS:',0 fderms: db cr,lf,'FDC COLD BOOT ERROR CODE ',0 dskask: db cr,lf,'INSERT DISK & PRESS B TO BOOT',0 hdrms: db cr,lf,'HDC1001 COLD BOOT ERROR CODE ',0 crlfst: db cr,lf,0 helpst: db cr,lf,'MONITOR COMMANDS :' db cr,lf,'B = Load disk boot loader' db cr,lf,'DSSSS,QQQQ = Dtrend: POP HL POP AF RET crlf: push af ld a,cr call putc ld a,lf jr hspit space: PUSH AF LD A,' ' JR hspit page hexit: PUSH AF RRCA RRCA RRCA RRCA CALL hex1 POP AF hex1: PUSH AF AND 0fh ADD A,90h DAA ADC A,40h DAA hspit: CALL putc POP AF RET hexhl: PUSH AF LD A,H CALL hexit LD A,L CALL hexit POP AF RET page getnum: CALL gecho CP ',' RET Z ;end of # CP ' ' RET Z ;end of # CP '0' RET C ;woops CP ':' JP C,isnum ;0 - 9 CP 'A' RET C ;woops CP 'G' CCF RET C ;woops SUB 007H ;convert A - F isnum: SUB 030H ;decode RET page get2n: PUSH BC PUSH DE LD C,0 LD E,0 nloop: CALL getnum ;number in? JR NC,nisnum ;yes, jump CP cr ;cr? SCF JR NZ,bad2n ;no, jump LD A,E OR A ;any input? JR NZ,got2n ;yes, jump SCF LD A,cr ;let's pretend it was a cr JR bad2n nisnum: CP 16 ;is it a number? JR NC,got2n ;no, jump INC E ;inc it ump memory in hex from S to Q' db cr,lf,'FSSSS,QQQQ,BB = Fill memory from S to Q with B' db cr,lf,'GAAAA = Go to address A' db cr,lf,'IPP = Input from port P' db cr,lf,'LAAAA = Load memory starting at A' db cr,lf,'MSSSS,QQQQ,DDDD = Move starting at S to Q to Addr. D' db cr,lf,'OPP,DD = Output data D to port P' db cr,lf,'ESC will terminate any command',0 page ;-------------------------- ; Function code jump table ;-------------------------- cmdtbl: db 'L' dw load db cr dw exec db '.' dw dot db '-' dw dash db 'D' dw dump db 'I' dw iport db 'O' dw oport db 'F' dw fill db 'G' dw go db 'M' dw move db 'H' dw help db 'B' dw boot db 0ffh .dephase ds promsiz-($-pbase),0ffh end $ˆ >!$4l >:q#<2q#O*|$ :p#w:p#?± !d#6!$q!p#6?!$:q# ͒ û 2p#:p# :p#]H!:p#A2$O>!:p# STERS ;-------------------------------------- bsybit equ 080h ; busy bit errbit equ 001h ; error bit ;----------------------- ; Disk specific equates ;----------------------- sectrk equ 17 ; sectors/track seccyl equ 68 ; sectors/cyl ;--------------------- ; Loader base equates ;--------------------- fbase equ 0000h ;base adr for floppy loader hbase equ 0100h ;base adr for hard disk loader page if test ploc equ 0e000h ld hl,pbase ;relocate to ploc ld de,ploc ld bc,promsiz ldir jp bootin else ploc equ 0f000h endif pbase: .phase ploc stack: bootin: jp booty jp exec booty: di LD A,04FH ;pon jump off, bank 00 on OUT (bank0),A LD SP,stack IN A,(baudrd) ;set baud rate for crt OUT (baudwr),A LD HL,inisa LD BC,800h + sioac OTIR LD HL,inisb LD BC,800h + siobc OTIR ld a,2 ;ctc reset byte out (ctc0),a out (ctc1),a out (ctc2),a out (ctc3),a LD HL,signon CALL strout JP boot page ;------- LD B,A ;save # LD A,C ;get old ADD A,A ;x 2 ADD A,A ;x 4 ADD A,A ;x 8 ADD A,A ;x 16 ADD A,B ;add in new # LD C,A ; -- and all to c JP nloop got2n: LD A,C ;return in a bad2n: POP DE POP BC RET page get4n: PUSH DE LD HL,0 SCF CCF PUSH AF n4loop: CALL getnum JR NC,got4n CP cr JR NZ,bad4n CALL space JR good4n bad4n: POP AF SCF POP DE RET got4n: CP 16 JR NC,good4n ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL LD E,A LD D,0 ADD HL,DE JR n4loop good4n: POP AF POP DE RET page tstmem: LD (HL),A CP (HL) RET Z PUSH HL LD HL,memerr CALL strout POP HL CALL hexhl JP exec page ;--------------------------------------- ; Load function -- Display & Substitute ;--------------------------------------- load: CALL get4n ;get the start adr JP c,badcmd push hl pop ix dot: CALL crlf ;display the current adr push ix pop hl CALL hexhl CALL space LD A,(HL) CALLtitle hprom SourceBug Monitor Prom .z80 false equ 0 true equ not false test equ false ;false: org @ f000, true: moved to e000 i2716 equ 800h i2732 equ 1000h promsiz equ i2716 ;eprom type ; You must specify how many directory entries are on the disk (ndirs). ; The number you specify must be divisible by 64 (for 2k groups). ; The loader program must reside immediately after the directory. ; Also specify how many sectors to load (nsecs). ; There are 512 bytes/sector. ndirs equ 512 ;512 directory entries nsecs equ 8 ;load 4k ; Equates to figure loader program location -- DO NOT CHANGE. spt equ 17 ;# sectors/track nheds equ 4 ;# tracks/cylinder spc equ spt * nheds ;# sectors/cylinder dirsecs equ ndirs/16 icyl equ dirsecs/spc isec equ dirsecs mod spc page 60 ;ascii cr equ 0dh lf equ 0ah ;ports sioad equ 00h sioac equ 01h siobd equ 02h siobc equ 03h ctc0 equ 08h ctc1 equ 09h ctc2 equ 0ah ctc3 equ 0bh fdcmd equ 0ch fdtrk equ 0d-------------- ; Top of command loop ;--------------------- exec: LD SP,stack LD HL,prompt CALL strout CALL gecho LD B,A LD HL,cmdtbl cloop: LD A,(HL) CP 0ffh JR Z,badcmd CP B JR Z,gotcmd INC HL INC HL INC HL JR cloop badcmd: LD HL,woops CALL strout JR exec gotcmd: INC HL LD E,(HL) INC HL LD D,(HL) EX DE,HL JP (HL) ;go to command page putc: PUSH AF owait: IN A,(sioac) AND 4 JR Z,owait POP AF OUT (sioad),A RET cetupc: IN A,(sioac) AND 1 ;char ready? RET Z ;no, exit -- z status getupc: IN A,(sioac) AND 1 ;char ready? JR Z,getupc ;no, loop IN A,(sioad) AND 7fh ;mask CP 'a' ;lt 'a'? RET C ;yes, exit CP '{' ;gteq '{'? RET NC ;yes, exit AND 5fh ;upcase RET gecho: CALL getupc CP ' ' ;ctrl char? CALL NC,putc ;no, echo RET page strout: PUSH AF PUSH HL stroop: LD A,(HL) OR A ;end of string JR Z,strend ;yes, jump CALL putc INC HL JR stroop sK hexit CALL space CALL get2n ;get the response JP C,lodcmd CALL tstmem lodinc: inc ix ;inc the current adr jr dot lodcmd: CP cr ;cr terminates JP Z,exec CP ' ' ;space means inc jr Z,lodinc CP '-' ;dash means dec JP NZ,badcmd dash: dec ix ;dec the current adr jr dot page ;----------- ; Negate DE ;----------- negde: PUSH AF LD A,D CPL LD D,A LD A,E CPL LD E,A INC DE POP AF RET page ;----------------------- ; Dump memory to screen ;----------------------- dump: CALL get4de CALL get4de CALL negde dloop: CALL crlf CALL hexhl CALL space dloop1: CALL space LD A,(HL) CALL hexit CALL inchlc CALL abortc LD A,L AND 0fh JP Z,dloop JP dloop1 page ;------------------ ; Go to an address ;------------------ go: CALL get4de EX DE,HL JP (HL) ;----------------------- ; Display the help menu ;----------------------- help: LD HL,helpst CALL strout JP exec inchlc: PUSH HL ;cp t fdrdlp: IN A,(fddsd) ;wait for data or int OR A ;data? JP P,fdrddn ;no, jump INI ;get a byte JP fdrdlp fdrddn: IN A,(fdcmd) OR A ;errors? JP Z,fbase ;no, jump to booted input jp fderr page ;--------------------- ; INITALIZE HARD DISK ;--------------------- hdinit: ld a,sdhreg ; drive 0 & sector size out (hsdh),a ; send it to controller xor a ; zero a-reg out (hsec),a ; reset sector register out (hcyllow),a ; reset cylinder low register out (hcylhi),a ; reset cylinder high register inc a ;set for 1 sector out (hseccnt),a in a,(hsec) ;test for hdc1001 ctrlr ld b,a in a,(hcyllow) or b ld b,a in a,(hcylhi) or b ; do we seem to have a controller? ret nz ; no, exit in a,(hstatus) and 0c0h xor 40h ; busy or not ready? ret nz ; yes, exit ld a,cmdrstr ; restore command out (hcmd),a ret page ;---------------- ; READ HARD DISK ;---------------- hdread: call hdinit ; does everything '?',0 memerr: db cr,cr,lf,'MEMORY WRITE ERROR AT ',0 fderms: db cr,lf,'FDC COLD BOOT ERROR CODE ',0 hdrms: db cr,lf,'HDC1001 COLD BOOT ERROR CODE ',0 helpst: db cr,lf,'SourceBug Function List:',cr db lf,lf,'B = Load disk boot loader' db cr,lf,'DSSSS,QQQQ = Dump memory in hex from S to Q' db cr,lf,'FSSSS,QQQQ,BB = Fill memory from S to Q with B' db cr,lf,'GAAAA = Go to address A' db cr,lf,'IPP = Input from port P' db cr,lf,'LAAAA = Load memory starting at A' db cr,lf,'MSSSS,QQQQ,DDDD = Move starting at S to Q to Addr. D' db cr,lf,'OPP,DD = Output data D to port P' db cr,lf,'Any key will terminate a command',0 page ;--------------- ; SIO init data ;--------------- inisa: db 018h,004h,044h,003h,0c1h,005h,0eah,0 inisb: db 018h,004h,044h,003h,0c1h,005h,0eah,0 ;-------------------------- ; Function code jump table ;-------------------------- cmdtbl: db 'L' dw load db cr dw exec db '.' dw dot hl to de -- abort if c, else inc hl ADD HL,DE JP C,exec POP HL INC HL RET page ;------------------- ; Move memory block ;------------------- move: CALL get4de PUSH DE CALL get4de CALL get4de EX DE,HL EX (SP),HL CALL negde mloop: LD A,(HL) EX (SP),HL CALL tstmem INC HL EX (SP),HL CALL inchlc CALL abortc JP mloop page ;------------- ; Fill memory ;------------- fill: CALL get4de CALL get4de CALL negde CALL get2n JP C,badcmd floop: CALL tstmem CALL inchlc JP floop get4de: CALL get4n JP C,badcmd EX DE,HL RET abortc: CALL cetupc ;abort on any char OR A JP NZ,exec RET ;--------------- ; In & Out port ;--------------- iport: CALL get2n JP C,badcmd LD C,A IN A,(C) CALL crlf CALL hexit JP exec oport: CALL get2n JP C,badcmd LD C,A CALL get2n JP C,badcmd OUT (C),A JP exec page ;---------------------------------- ; Boot -- floppy or hard disk exec ;--------------------look good on init? ret nz ; no, exit call polbsy ; wait until not busy ret nz ; exit if bad in a,(hstatus) and 50h cp 50h ;ready & seek (restore) complete? ret nz ;no, exit ld hl,hbase ;start adr of load ld de,icyl ;initial cyl # ld bc,isec+(nsecs*100h) ;b = nsecs, c = isec hread1: call hsettsk call hrdsec call polbsy ; any errors? jp nz,hdbadx ; yes, jump inc c ld a,c sub seccyl ;new cylinder? jr c,hread2 ;no, jump ld c,a ;set sector # to 0 inc ix ;inc cyl # hread2: djnz hread1 jp hbase ;all loaded -- go to it hdbadx: ld hl,hdrms call strout in a,(herror) call hexit jp exec page ;-------------------- ; SET TASK HARD DISK ;-------------------- ;Enter with de = track # and c = sector # hsettsk: push hl push de ld a,e ; set cyl # out (hcyllow),a ld a,d out (hcylhi),a ld a,sdhreg ; sdh proto byte ld de,sectrk ; # sectors/track ld l,c ; set hl to sector # ld h,0 hsloo db '-' dw dash db 'D' dw dump db 'I' dw iport db 'O' dw oport db 'F' dw fill db 'G' dw go db 'M' dw move db '?' dw help db 'B' dw boot db 0ffh .dephase ds promsiz-($-pbase),0ffh end ntrol word (vector) ?$ (-------------- boot: CALL abortc CALL fdinit fdlop: CALL abortc CALL fdread CALL hdread JR fdlop page ;------------- ; Floppy junk ;------------- fdinit: XOR A OUT (fddsd),A ;8" sd CALL fdrdy? ;is the drive ready? ret c ;no, return call fdhome ret z ;return if good home ld a,8 out (fddsd),a ;8" dd call fdhome ret z ;return if good home fderr: LD HL,fderms ;floppy disk err msg out CALL strout in a,(fdcmd) CALL hexit ret fdhome: LD A,0fh ;restore command OUT (fdcmd),A LD A,3 delop: EX (SP),HL EX (SP),HL DEC A JR NZ,delop IN A,(fddsd) ;force wait for int IN A,(fdcmd) AND 018H ;seek or crc error? ret fdrdy?: IN A,(fdcmd) RLA ;c flag if not ready ret page ;------------------ ; Floppy disk read ;------------------ fdread: call fdrdy? ;drive ready? ret c ;no, return LD A,1 ;set sector 1 OUT (fdsec),A LD A,08CH ;read sector OUT (fdcmd),A LD HL,fbase LD C,fddap: or a ; divide modulo sectors/track sbc hl,de jp m,hsend inc a ; add a head bit to sdh jr hsloop hsend: add hl,de ; l = sector #, a = sdh w/head bits out (hsdh),a ; load siz drv hd register ld a,l out (hsec),a ; send to sector register pop de pop hl ret page ;---------------------------- ; READ SECTOR FROM HARD DISK ;---------------------------- ;Enter with hl set to dest adr -- exits with hl = hl + 512 hrdsec: ld a,cmdrd out (hcmd),a call polbsy push bc ld bc,hdata ; 0 to b, data port to c inir inir pop bc ret ;--------------------- ; POLL BUSY HARD DISK ;--------------------- polbsy: in a,(hstatus) ; read status port and a ; set flags jp m,polbsy ; loop if busy bit set and errbit ; mask for error bit ret page signon: db cr,lf,lf db lf,lf,' SourceBug V1.0',cr db lf,lf,'Hit any key to enter Sourcebug.' db cr,lf,' Hit "?" for function list.',0 prompt: db cr,lf,'!',0 woops: db cr,lf,lf,K;************************************************ ; * ; ADVANCED MICRODIGITAL * ; MONITOR PROM * ; * ;************************************************ TITLE ADVANGED MICRODIGITAL MONITOR PROM Jan 07 1983 09:20 .Z80 TRUE EQU 0FFFFH ;DEFINE VALUE OF TRUE FALSE EQU NOT TRUE ;DEFINE VALUE OF FALSE TEST EQU false ;TRUE IF TEST RUN SLAVE EQU FALSE ;TRUE IF MONITOR FOR SLAVE ; IF TEST ROM EQU 100H ;BASE OF ROM RAM EQU 1000H ;BASE OF LOCAL RAM ELSE IF SLAVE ROM EQU 0 ;BASE OF ROM RAM EQU 0FE00H ;BASE OF LOCAL RAM ELSE ROM EQU 0F000H ;BASE OF ROM RAM EQU 0EE00H ;BASE OF LOCAL RAM ENDIF ENDIF STACK EQU RAM+100 ;STACK AREA ; ; SYSTEM EQUATES ; BKSP EQU 08H ;BACKSPACE EQUATE CR EQU 0DH ;CARRAIGE RETURN LF EQU 0AH ;LINEFEED ESC EQU 1BH ;ESCAPE KEY RUBOUT EQU 7FH ;RUBOUT KEY ; IOBASE EQU 0 SER0D EQU IOBASE ;SERIAL PORT 0 DATA SER0S EQU IOBASE+1 ;SERIAL PORT 0 STATUS SER1D EQU IOBASE+2 ;SERIAL PORT 1 DATA SER1S EQU IOBE SENSW EQU 1 ;SENSE SWITCH BIT ; B50 EQU 0 B75 EQU 1 B110 EQU 2 B134 EQU 3 B150 EQU 4 B200 EQU 5 B300 EQU 6 B600 EQU 7 B1200 EQU 8 B1800 EQU 9 B2400 EQU 10 B3600 EQU 11 B4800 EQU 12 B7200 EQU 13 B9600 EQU 14 B19200 EQU 15 ENDIF ; ; STORAGE AREA ; DSEG ; ORG RAM ;RAM AREA ; ECHO:: DS 1 ;ECHO FLAG FRSTIM:: DS 1 ;FIRST TIME THRU BOOT FLAG ADR:: DS 2 ;EXAMINE/MODIFY ADDRESS hddsk: ds 1 ;hard disk available flag ; ; ; MONITOR SUPPORT VECTORS ; CSEG ; ORG ROM ; EXEC:: JP BEGIN ;AND BEGIN JP OUTPTY ;OUTPUT A CHARACTER FROM REG A JP INPUT ;GET A CHAR. INTO REG A (NO ECHO) JP INPUT0 ;CHECK FOR KEY PUSHED..RET IF NONE JP CHIN ;GET CHAR INTO A W/ ECHO,PARITY STRIP JP MSG ;OUTPUT MESSAGE,-H,L. ZERO TERMIN. JP CRET ;OUTPUT CR,LF,RUBOUT JP SPACE ;OUTPUT ONE SPACE JP THXN ;OUT B 3-0 OF'A'IN HEX(1 ASCII CHAR) JP THXB ;OUT REG A IN ASCII-HEX (2 CHARS) JP THXW ;OUTPUT H,L IN ASCII-HEX (4 CHARS) JP GHXN ;GET HEX NIBBLE INTO REG D (NOT SLAVE) JP BOOT ;TRY TO BOOT SYSTEM ENDIF ; ; START OF MONITOR COMMAND AREA ; NEXT:: LD SP,STACK ;SET UP SP AGAIN LD HL,M1 ;OUTPUT PROMPTER (*) CALL MSG ;PRINT IT NEXT1:: CALL CHIN ;GET COMMAND CHAR. IN IF TEST CP 03 ;CNTRL C JP Z,0 ;IF SO GO BACK TO CP/M ENDIF LD B,A ;SAVE IT REG B ; ; SEARCH TABLE FOR COMMAND ; LD HL,OPTAB ;H,L POINTS TO START OF TABLE SRCH:: LD A,(HL) ;GET COMMAND BYTE CP 0FFH ;END OF TABLE? JR Z,ILLEG ;NOT FOUND IN COMMAND CP B ;DOES A = B? JR Z,FNDCM ; YES! INC HL ;BUMP 3 TIMES INC HL ;FOR NEXT BYTE INC HL JR SRCH ;CONTINUE,,, ; ; UNDEFINED COMMAND,,DO ERROR MESSAGE ; ILLEG:: LD HL,M2 ;GET ERROR MSG CALL MSG ;PRINT IT JR NEXT ;TRY ANOTHER COMMAND ; ; COMMAND FOUND,,GO DO IT ; FNDCM:: INC HL ;GET LOW ADDR. BYTE LD E,(HL) ;PUT IT IN E REG INC HL ;GET HIGH ADDR. BYTE LD D,(HL) ;PUT IT IN D REG EX DE,HL ;FLIP D,E & H,L JP (HL) ;GO DO IT! ; ; ; THIS IS AN OUTPUT ROASE+3 ;SERIAL PORT 1 STATUS IF SLAVE SER2D EQU IOBASE+0CH ;SERIAL PORT 2 DATA SER2S EQU IOBASE+0DH ;SERIAL PORT 2 STATUS SER3D EQU IOBASE+0EH ;SERIAL PORT 3 DATA SER3S EQU IOBASE+0FH ;SERIAL PORT 3 STATUS BAUDRT EQU IOBASE+10H ;BAUD RATE SELECT PORT PIO0D EQU IOBASE+14H ;PARALLEL PORT 0 DATA PIO1D EQU IOBASE+15H ;PARALLEL PORT 1 DATA PIO0C EQU IOBASE+16H ;PARALLEL PORT 0 CONTROL PIO1C EQU IOBASE+17H ;PARALLEL PORT 1 CONTROL INTD EQU IOBASE+18H ;INTERRUPT CONTROLLER DATA PORT INTS EQU IOBASE+19H ;INTERRUPT CONTROLLER STATUS PORT LSSP@ EQU IOBASE+1DH ;MEMORY CONTROL PORT LDP@ EQU IOBASE+1EH ;SLAVE TO MASTER DATA PORT LCSP@ EQU IOBASE+1FH ;SLAVE TO MASTER CONTROL PORT ELSE PIO0D EQU IOBASE+04H ;PARALLEL PORT 0 DATA PIO1D EQU IOBASE+05H ;PARALLEL PORT 1 DATA PIO0C EQU IOBASE+06H ;PARALLEL PORT 0 CONTROL PIO1C EQU IOBASE+07H ;PARALLEL PORT 1 CONTROL CTC0 EQU IOBASE+08H ;CTC CHANNEL 0 PORT CTC1 EQU IOBASE+09H ;CTC CHANNEL 1 PORT CTC2 EQU IOBASE+0AH ;CTC CHANNEL A (B 3-0) JP GHXB ;GET HEX BYTE INTO REG A (B 7-0) JP GHXW ;GET HEX WORD INTO H,L JP STORE ;STORE A BYTE TO MEMORY (CHECK) JP NEGDE ;NEGATE D,E REGISTER jp herr ;external hard disk boot error entry jp boterr ;external boot error entry JP INPORT ;INPUT FROM I/O PORT JP OUTPORT ;OUTPUT TO I/O PORT ; ; ; BEGIN:: IF NOT TEST IF SLAVE LD A,11110001B ;ENABLE MEMORY HIGHEST SWITCHED BOUNDRY AND BANK 0 OUT (LSSP@),A ;WRITE TO MEMORY CONTROL PORT LD A,00000001B ;MAKE SURE PROM IS ON OUT (LCSP@),A ;WRITE TO SLAVE CONTROL PORT ; IN A,(LCSP@) ;CHECK IF AUTO BOOT ENABLED AND SENSW JP Z,SLVBOOT ;IF SO GO DO IT ; ELSE LD A,01001111B ;RESET POWER ON JUMP AND ENABLE MEMORY OUT (16H),A ;WRITE TO CONTROL PORT ENDIF XOR A ;CLEAR REG A LD (FRSTIM),A ;SET FIRST TIME THRU BOOT FLAG LD SP,STACK ;SET SP TO EXEC STACK AREA ; Set up SIO channels LD HL,ISIOA ; point to SIO init table LD BC,ISIOAL*256+SER0S ; length in B & port in C OTIR LD UTINE FOR AN CRT ; ; ; OUTPTY:: PUSH AF ;SAVE DATA OUTPTC:: IN A,(SER0S) ;GET CRT STATUS AND 04H ;MASK BIT 7 JR Z,OUTPTC POP AF ;GET DATA OUT (SER0D),A RET ; ; ; THIS IS THE INPUT ROUTINE ; ; ; INPUT0:: IN A,(SER0S) ;CHECK STATUS AND 01H ;MASK BIT 0 RET Z ;RET IF NO KEY PUSHED JR INPUT1 ;GET KEY PUSHED ; ; INPUT:: IN A,(SER0S) ;CHECK STATUS AND 01H ;MASK BIT 0 JR Z,INPUT ;NOT READY INPUT1:: IN A,(SER0D) ;GET DATA AND 7FH ;GET RID OF HIGH ORDER BIT CP 'A' OR 20H RET C ;RETURN IF LESS THAN LOWER CASE 'A' CP 'Z' OR 20H +1 RET NC ;RETURN IF GREATER THAN LOWER CASE 'Z' AND 5FH ;STRIP PARITY OFF AND LOWER CASE RET ; ; ; CHIN - INPUT ONE CHAR,,STRIP ; PARITY,,ECHO IF >= SPACE ; ; CHIN:: LD A,0FFH ;SET ECHO LD (ECHO),A ; FLAG ON CHINN:: CALL INPUT ;GET CHAR. PUSH AF ;SAVE DATA LD A,(ECHO) ; AND CHECK AND A ; ECHO FLAG JR NZ,.CHINN1 ;ECHO SET POP AF ;ECHO NOT SET RET ; SO RETURN .CHINN1:: P2 PORT CTC3 EQU IOBASE+0BH ;CTC CHANNEL 3 PORT FDC EQU IOBASE+0CH ;FLOPPY DISK BASE ADDRESS FDCTRK EQU FDC+1 FDCSEC EQU FDC+2 FDCDATA EQU FDC+3 WAIT EQU IOBASE+14H ;FLOPPY WAIT PORT & DRIVE SELECT EXADD EQU IOBASE+15H ;EXTENDED ADDRESS I/O PORT MEMCTL EQU IOBASE+16H ;MEMORY CONTROL PORT ;*** Port equates for HDC1001 *** HDCBASE EQU 070H ; 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 ;*** HDC1001 ECC selection *** eccbit equ 80h ;ecc command bit ecc equ false ;set true to enable ecc ENDIF ; IF SLAVHL,ISIOB ; repeat for channel B LD BC,ISIOBL*256+SER1S OTIR ENDIF JP SIGN ; go signon ; ****** INITIALIZATION TABLES FOR SIO DEVICES ****** ; ; CHANNEL A ISIOA:: DB 018H ; channel reset DB 004H ; write reg 4 DB 044H ; X16 clock, 1 stop bit DB 003H ; write reg 3 DB 0C1H ; Rx 8-bit char, Rx enable 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 004H ; write reg 4 DB 044H ; X16 clock, 1 stop bit DB 003H ; write reg 3 DB 0C1H ; Rx 8-bit char, Rx enable 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 ; SIGN:: IF SLAVE LD A,B9600 * 16 + B9600 ;SET BAUD RATE OUT (BAUDRT),A ENDIF LD HL,M0 ;OUTPUT ENTRY SIGN-ON CALL MSG ;PRINT IT ; LD HL,M0A ;SEND MONITOR MESSAGE CALL MSG ; IF (NOT TEST) ANLOP AF ;RESTORE DATA & ECHO CP 20H ;CHECK FOR CNTL. CALL NC,OUTPTY ;PRINT IF >= SPACE RET ; ; ; MESSAGE PRINT ROUTINE ; ; MSG:: PUSH AF ;SAVE DATA PUSH HL ;SAVE H,L MNXT:: LD A,(HL) ;GET CHAR OR A ;IS IT ZERO? JR Z,MDONE ;YES,,RESTORE REGS. CALL OUTPTY ;PRINT IT! INC HL ;BUMP H,L BY 1 JR MNXT ;DO AGAIN ; ; MDONE:: POP HL ;RESTORE H,L POP AF ;RESTORE A RET ;BACK TO CALLER ; ; ; ROUTINE TO TYPE CR,LF,RUBOUT ; ; CRET:: PUSH HL ;SAVE H,L LD HL,CRMSG ;CR,LF,RBO MSG CALL MSG ;PRINT IT POP HL ;RESTORE H,L RET ; ; ; HOLDDIS:: CALL INPUT0 ;KEY PUSHED YET? CP ESC ;ESCAPE? JP Z,NEXT ;BACK TO MONITOR CP 08H ;ANY KEY PUSHED? RET NC ;YES,,PRINT MORE JR HOLDDIS ;NO,,SO HOLD SOME MORE ; ; ; ; ; ROUTINE TO TYPE A SPACE ; ; SPACE:: PUSH AF ;SAVE A LD A,20H ;SPACE CHAR JR THXN1 ;PRINT IT ; ; ; TYPES REG A ; ; ON OUTPUT DEVICE ; ; THXB:: PUSH AF ;SAVE A RRCA RRCA RRCA RRCA CALL TSW BACK SCF ;AND SET ERROR FLAG POP DE RET .GHXW2:: CP 10H ;END OF INPUT ? JR NC,.GHXW3 ADD HL,HL ;SHIFT OVER PRESENT VALUE ADD HL,HL ADD HL,HL ADD HL,HL LD E,A ;ADD IN NEW INPUT LD D,0 ADD HL,DE JR .GHXW1 ;GO GET MORE .GHXW3:: POP PSW POP DE RET ; ; ; ROUTINE TO STORE A BYTE IN MEMORY ; WITH CHECK. ; ; STORE:: LD (HL),A ;STORE BYTE CP (HL) ;CHECK IT RET Z ;RETURN IF OK PUSH HL ;SAVE ADDRESS LD HL,M4 ;TYPE ERROR CALL MSG ;PRINT IT POP HL ;RESTORE ADDRESS STOREA:: CALL THXW ;TYPE BAD ADDRESS JP NEXT ;RETURN TO MONITOR ; ; ; MEMORY EXAM/MODIFY ROUTINES ; ; GETAD:: CALL GHXW ;GET ADDR. JP NC,GTA1 ;JMP IF VALID ILLCH:: LD HL,M3 ;ILLEGAL INPUT JP ILLEG+3 GTA1:: LD (ADR),HL ;SAVE ADDR. LOCAT:: CALL CRET ;GET CR,LF LD HL,(ADR) ;GET ADDR. CALL THXW ;PRINT IT CALL SPACE LD A,(HL) CALL THXB ;PRINT MEMORY CONTENTS CALL SPACE CALL GHXB ;GET DATA OR COMMAND JP C,NONHX ;NON-HEX INPUT CALL VE PORT FOR INPUT IN A,(C) ;GET VALUE CALL CRET ;NEW LINE CALL THXB ;PRINT BYTE JP NEXT ;ALL DONE ; ; OUTPUT TO PORT ; ; OUTPORT:: CALL GHXB ;GET PORT NUMBER JP C,ILLCH ;ERROR IF BAD LD C,A ;SAVE PORT CALL GHXB ;GET DATA JP C,ILLCH ;ERROR IF BAD OUT (C),A ;SEND IT JP NEXT ;ALL DONE ; ; ; SLAVE BOOT ROUTINE ; IF SLAVE SLVBOOT:: LD BC,SLVBLKL*256+LCSP@ ;SET UP BLOCK TRANS LD HL,SLVBLK OUTI ;SEND SERVICE REQUEST DEC C ;CHANGE PORT OTIR ;SEND BLOCK MESSAGE LD B,80H ;SET UP RECIEVE BLOCK LD HL,1000H INIR ;GET BLOCK JP 1000H ;GO TO SLAVE LOADER ; SLVBLK:: DB 9 ;REQUEST SERVICE W/ PROM ON DB 1,4CH,0,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH,0FFH ; SLVBLKL EQU $-SLVBLK ;SLAVE BLOCK LENGTH ELSE ; ; DISK BOOT ROUTINE ; BOOT:: call escape ;want to get out CALL FPYINIT ;Initialize floppy controller call hdcinit ;initialize hard disk controller bloop: call escape ;want to get out call fpyrdy ;try floppy HXN ;PRINT HEX NIBBLE POP AF ;RESTORE DATA ; ; ; ROUTINE TYPES ONE ASCII CHAR. FROM ; BITS 3-0 OF REG A IN HEX ; ; THXN:: PUSH PSW AND 0FH ;ISOLATE B 3-0 ADD A,90H DAA ADC A,40H DAA THXN1:: CALL OUTPTY ;PRINT IT POP PSW RET ; ; ; ROUTINE TYPES A WORD IN HEX FROM ; REG H,L ; ; THXW:: PUSH AF ;SAVE A LD A,H ;GET HIGH BYTE CALL THXB ;PRINT IT LD A,L ;GET LOW BYTE CALL THXB ;PRINT IT POP AF ;RESTORE DATA TO A RET ; ; ; ROUTINE GETS ONE HEX CHAR FROM INPUT ; ; GHXN:: CALL CHIN ;GET CHAR CP ',' ;IS IT AN COMMA RET Z ;RETURN OK CP ' ' ;IS IT AN BLANK RET Z ;OK TOO CP '0' RET C ;RET IF < ZERO CP ':' ;IS IT NUMERIC? JP C,GHX1 ;CHAR IS 0 TO 9 CP 'A' ;IS IT A - F? RET C ;CHAR : TO ' ' CP 'G' ;IS IT > F? CCF ;FLIP CARRY SENSE RET C ;IT IS > F! SUB 7 ;ADJ FOR A - F GHX1:: SUB '0' ;MAKE BINARY RET ; ; ; ROUTINE GETS ONE HEX BYTE FROM INPUT ; ; GHXB:: PUSH BC ;SAVE B,C PUSH DE ;SASTORE ;STORE VALUE IF VALID NXLOC:: LD HL,(ADR) INC HL ;BUMP H,L 1 JP GTA1 ;CONTINUE NONHX:: CP CR ;IS IT CR? JP Z,NEXT ;YES,,SO EXIT CP 20H ;IS IT SPACE? JP Z,NXLOC ;GET NEXT ADDR. CP '-' ;BACK ONE POSITION? JP NZ,ILLCH LSTLC:: LD HL,(ADR) ;GET ADDR. DEC HL ;DECREASE -1 JP GTA1 ;CONTINUE ; ; ; ROUTINE NEGATES REG D,E ; ; NEGDE:: PUSH AF ;SAVE DATA LD A,D CPL LD D,A LD A,E CPL LD E,A INC DE POP AF RET ; ; ; DUMP MEMORY ROUTINE ; ; DUMP:: CALL PU3 ;GET HEX ADDR. CALL PU3 ;ANOTHER ; ; FROM ADDR IN H,L TO ADDR IN D,E ; CALL NEGDE ;COMP.D,E FOR END CK. DMRET:: CALL CRET ;GET CR,LF CALL THXW ;PRINT ADDR CALL SPACE DMNXT:: CALL SPACE LD A,(HL) ;GET DATA CALL THXB ;PRINT IT CALL LAST ;CHECK FOR END CALL ESCAPE ;CHECK FOR ABORT CP 'S'-40H ;CNTL-S? CALL Z,HOLDDIS ;YES,,STOP DISPLAY LD A,L ;CHECK FOR MOD 16 AND 15 JP Z,DMRET ;DO NEW LINE IF 16 JP DMNXT ;CONTINUE ; ; ; DIRECT GO-TO call hdcrdy ;try hard disk jr bloop ;if here go back and start over ; ; fpyinit: XOR A ;CLEAR DOUBLE DENSITY COMMAND OUT (WAIT),A LD A,0BH ;restore drive to track 0 OUT (FDC),A NOP IN A,(WAIT) ;WAIT FOR IT TO GET TO 0 ret ; and return from whence we came ; fpyrdy:: IN A,(FDC) ;DRIVE READY YET RLA ret C ;IF not READY LEAVE ; RDY:: LD HL,1000 ;TIMER RDY0:: IN A,(FDC) ;MAKE SURE NO INDEX PULSE AND 2 JR Z,RDY05 ;LEAVE IF GONE DEC HL ;CHECK FOR TIME OUT LD A,L OR H JR NZ,RDY0 ;IF NOT GO BACK FOR MORE ret ;not ready so leave ; RDY05:: LD B,10 ;SET TIME OUT COUNT RDY1:: LD HL,16000 ;SET REV. COUNT RDY2:: IN A,(FDC) ;DO WE HAVE AN INDEX PULSE AND 2 JR NZ,LOAD ;IF SO LEAVE DEC HL ;OTHER WISE CHECK REV COUNTER LD A,L OR H JR NZ,RDY2 ;GO BACK IF NOT ONE REV YET DJNZ RDY1 ;CHECKED ENOUGH REV'S YET ret ;not ready so leave ; LOAD:: LD A,0FFH ;CLEAR FIRST TIME THRU BOOT FLAG LD (FRSTIM),A LD B,1 ;SET UPVE D,E LD C,0 ;CLEAR C LD E,0 .GHXB1:: CALL GHXN ;GET LEFT NIBBLE JR NC,.GHXB5 ;HEX, JUMP OUT! CP CR ;END OF INPUT SCF JR NZ,.GHXB3 ;ERROR IF BAD DATA LD A,E ;CHECK IF FIRST CHAR OR A JR NZ,.GHXB2 ;RETURN INPUT DATA IF NOT SCF ;OTHERWISE RETURN CR AND CARRY SET LD A,CR JR .GHXB3 .GHXB5:: CP 10H ;ANYTHING ELSE IS END JR NC,.GHXB2 INC E LD B,A ;SAVE NEW NIBBLE LD A,C ;GET LAST DATA ADD A,A ADD A,A ADD A,A ADD A,A ADD A,B ;ADD LEFT NIBBLE LD C,A ;PUT BACK IN SAVE REG JP .GHXB1 ;GET MORE .GHXB2:: LD A,C ;GET VALUE TO RETURN .GHXB3:: POP DE ;RESTORE D,E POP BC ;RESTORE B,C RET ; ; ; ROUTINE GETS HEX WORD FROM INPUT ; ; GHXW:: PUSH DE LD HL,0 ;CLEAR RETURNED VALUE TO ZERO SCF ;CLEAR CARRY FLAG CCF PUSH PSW ;SAVE ACC. AND FLAGS .GHXW1:: CALL GHXN ;GET HEX NIBBLE JR NC,.GHXW2 ;SKIP IF NOT ERROR CP CR ;END CHAR JR NZ,.GHXW5 CALL SPACE JR .GHXW3 .GHXW5:: POP PSW ;OTHERWISE GET P ROUTINE ; ; GOTO:: CALL PU3 ;GET ADDR. EX DE,HL ;FLIP D,E & H,L JP (HL) ;BE THERE HELP:: LD HL,HELPM CALL MSG JP NEXT ; ; ; ROUTINE CHECK FOR END OF ADDR ; ; LAST:: PUSH HL ;SAVE MEM ADDR ADD HL,DE ;ADD NEG END OF ADDR JP C,NEXT ;END,,BACK TO MONITOR POP HL INC HL RET ; ; ; MOVE ROUTINE ; ; MOVE:: CALL PU3 ;GET ADDR PUSH DE CALL PU3 CALL PU3 EX DE,HL EX (SP),HL CALL NEGDE MOV1:: LD A,(HL) EX (SP),HL CALL STORE INC HL EX (SP),HL CALL LAST CALL ESCAPE ;ABORT? JP MOV1 ; ; ; FILL ROUTINE ; ; FILL:: CALL PU3 CALL PU3 CALL NEGDE CALL GHXB JP C,ILLCH FILLF:: CALL STORE CALL LAST JP FILLF ; ; ; ROUTINE INPUTS ADDR INTO ; H,L,,,THEN XCHG'S WITH D,E ; ; PU3:: CALL GHXW JP C,ILLCH EX DE,HL RET ; ; ; ESCAPE:: CALL INPUT0 ;CHECK FOR KEY PUSHED or A ;key pressed JP NZ,NEXT RET ; ; INPUT FROM PORT ROUTINE ; ; INPORT:: CALL GHXB ;GET PORT NUMBER JP C,ILLCH ;BAD NUMBER LD C,A ;MOLLF,'MONITOR COMMANDS :' IF NOT SLAVE D CR,LF,' Loa dis boo loader' ENDIF DB CR,LF,'DSSSS,QQQQ = Dump memory in hex from S to Q' DB CR,LF,'FSSSS,QQQQ,BB = Fill memory from S to Q with B' DB CR,LF,'GAAAA = Go to address A' DB CR,LF,'IPP = Input from port P' DB CR,LF,'LAAAA = Load memory starting at A' DB CR,LF,'MSSSS,QQQQ,DDDD = Move starting at S to Q to Addr. D' DB CR,LF,'OPP,DD = Output data D to port P' DB CR,LF,'ESC will terminate any command' DB 0 ; ; THIS IS THE COMMAND TABLE ; FOR THE NEW SYSTEM MONITOR ; ; OPTAB:: DB 'L' ;COMMAND DW GETAD ; FOR ADDRESS DB CR ;COMMAND DW NEXT ;OVER AGAIN DB '.' ;COMMAND DW LOCAT ; CURRENT LOC. DB '-' ;COMMAND DW LSTLC ; LOC - 1 DB 'D' ;COMMAND DW DUMP ; DUMP DB 'I' ;COMMAND DW INPORT ; INPUT PORT DB 'O' ;COMMAND DW OUTPORT ; OUTPUT TO PORT DB 'F' ;COMMAND DW FILL ; FILL DB 'G' ;COMMAND DW GOTO ; GOTOCP/M 3 PUT Version 3.0 Put console output to a file Enter file: d * }D> $* * T : _2 {2 " r" [  ?, d >l [ I6: <!=6 * J " * K : G/O*  * =d ## Ic ` ` ` ð ` ` ` ú ` ` ` ` ` ` ` ` ` ` ë ` ` ` ` ` ` ` ! ! > ! Ð>o! â D(y{ !8 C C C i`>>p/ (  / >* R < }: : > / * / Q b q ? 0ffh ; else set ready ret ; and exit end rd disk error message call msg in A,(hdcerr) ;get error call thxb ;print it jp next ;start over ENDIF ;SLVBOOT ; ; ; MONITOR MESSAGES ; ; M0:: DB CR,LF,' > ADVANCED DIGITAL CORP.' IF SLAVE DB CR,LF,' SUPER SLAVE Running' ELSE DB CR,LF,' SUPER QUAD Running' ENDIF DB CR,LF,0 M0A:: DB ' Monitor Version 3.2' DB CR,LF,' Febuary - 1983' DB CR,LF,' Press "H" for help' if not slave db CR,LF,'Attempting to boot.......' DB CR,LF,'Press any key to abort boot.' endif DB CR,LF,0 M1:: DB CR,LF,' >',0 M2:: DB ' UNDEFINED',0 M3:: DB ' ????',0 M4:: DB CR,CR,LF,'MEMORY WRITE ERROR AT ',0 M4A:: DB 'ERROR',0 M5:: DB ' PAUSE',0 M7A:: DB '? ',0 M8:: DB ' ABORTED',0 READST:: DB 'STARTING ADDRESS:',0 ENDADD:: DB 'ENDING ADDRESS:',0 IF NOT SLAVE BTERR:: DB CR,LF,'FDC COLD BOOT ERROR CODE ',0 FRSTMS:: DB CR,LF,'INSERT DISK & PRESS B TO BOOT',0 herrmsg:: db cr,lf,'HDC1001 COLD BOOT ERROR CODE ',0 ENDIF CRMSG:: DB CR,LF,0 HELPM:: DB CR,