IMD 1.17: 3/01/2010 9:23:13 xpro source list emerald microware kaypro ssdd format   422'i]  EAD     .\X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<ԯ2 Շ!۶2:2a{_:۷ʖ:۷>Ľʖ:=2–!B!6#5ʖ:S:2E!~Яw>T D^6k-äPYy 5*{zBK5ڋ>*Cw~#+w#w+ɯ2E22i^ *C :~w~͔͔# #  w ~>2!E5T*C!"C"C!w# F! w͌x2͢*C ~<wʃG:!ʎ ٯw4!Y~ʆ͌†t=ʆf ^ T ٯ2o&)|+!<ͧÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Yڸpsp2mÆÆf ͧÆFILE EXISTS _: É: :۷ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~2ۯ2\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOO*!O*|!6ʝ6>*w#w*w#w'û*! J*""!N#F*^#V*~#foyx*{_zW+*yx#*DM*s#r*s#ryOxG*0MD!!N: EG>O: \S*C :qn& ^#V>O^"*}:*)=":O:页o"*C *C!ͮ~2~2ͦ:2ͮ:O:w:w |g}o*鯆# ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:o$*C~i6iw*Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ "ַ"͌#>?͌͘ =_.:;<> Oօo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USER!yO#< Ty#O 3ׯ21y_͸2y2ͽ:Էì 4~ʶ¬:<ʶ$ʶïZͻx>2>2ͻ:!Z2:E߷ẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C ::ddslO s#r:E߷͊:==»y==»*Ww#*"͸*:G#š"͸:!w4 iw:Z!E~=262*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄADCOMf^: !۶ Â$$$ SUBܙܥܫܱ"C{2!"E9"1A߯22!ty)K!G_^#V*Cސ~E ,&-AGMSߛ!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6 O͐  :߷E B 2>: ߷b# : ߷y! 4 5~yy5 6y*{#zr+s{ozg**͕** ,w͜͸Ͳ!!N#F$**O!~#:A߾#~$=2Ek͌::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | s-|N-# 1͘A͌>>͌92^ :۷¥.!_~#fow]٭ڎڥ!v"!çREAD ERRORçNO FILE^:۷ ! ~ 3#0 Wx x ր ւ G ~ # 3x~#B!Y~ɯ2:۷=!۾ý:۷=!۾:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇҐ^H@Oy H H: –ͬ  #H: ! ߾ Hù H H $O͐: 2 *CN# x: 2 p&x~+é7ݯ2 H! >w_: ! ߾5ͤNkͱ¦ͱxʊ#Nx: ߷! ߖ2 ͤ! 5™#wO~x½p Hy<< ʑ :!qMD#2E>! ^#V w#P:BO|^#V#"##"##"##"!  BIOS MACk CRCKLISTCRCMONITOR MAC0XPRO205 COM XPRO206 COM  XPROCRT MACT!"#$%&'()*+XPRODISKMAC,-./0123456789:;XPRODISKMAC<=>?@ABCDEFGHIJKXPRODISKMACLMNXPROIO MACNOPQRSTUVWXXPRORAM MACYZ[\XPRORAM PRNF]^_`abcdeXPRORAM RELfXPROROM MACghiXPROROM REL$jklmn-XPRO SRC; ; Assemble with Z80MR the z80 macro assembler from Micro Cornucopia ; though M80 can handle it if you add an ASEG and .Z80 and change ; .LOW. to LOW ; Z80MR XBIOS ; Integrate into your System Image ; MOVCPM 63 * ; save 40 xcpm.com ; ddt xcpm.com ; ixbios.hex ; or ixbios8s.hex or ixbios8d.com ; r2980 ; ^C ; sysgen (when asked for a source drive answer with a carriage ; return and then choose a destination drive) ; The new bios will be loaded on the next cold start (reset) ; .z80 f2~?~((y.Kf:G.*H>ͷ(: .-;.7. 3.!/y2.'y2.C.:ĩ@.Es41&e1y2U!;!A2x.> (O.!

:0::  !7>#(>>2bM~#OCF MACopqrstuvwxyz{|}~CF MACCF MACCF15HDR MACQK21 COMQK21 DOCDQK21 UPDNULU COMxSWEEP COM\NULU11 DOCalse equ 0 true equ not false ; ; Set for type of assembler used ; m80 equ true z80mr equ false ; ;## Conditionals for destination ("A") drive type ######################### ; ONLY ONE OF THESE SHOULD BE TRUE Sing8 equ FALSE ; Eight inch single density Doub8 equ FALSE ; Eight inch double density Doub5 equ TRUE ; Five inch double density (Kaypro Format) qpm equ true ; TRUE if QP/M, FALSE if CP/M ferg equ false ; TRUE if Ferguson board ; system MUST come up mapped as followi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!B߾w!>2*C~=2u:B2~2wE:A*C߶w>"!""2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*W}_*"}o|g":ʑ*C6:ʑw:2E**E}DQ>2=÷éá?Tà;ó  !5#F#N#~(.l6~#2:k2!f""22 1:;<()pEra M˯Y 2go6:62pXpro Plus2 v0.7 gp Boot err1Y?|(N!n("'BKT ( yݾ8!4~! O>!2"!2":O!;(8yOͳ:< !tSETCLK>!  s: ; logical physical byte value ; 0 C 0CH ; 1 D 1DH ; 2 E 2EH ; 3 F 3FH ;NOTE: PLUS2 does this for you already ; ;!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!! ; ; SYstem MUST be set at least TWO pages (512 bytes) lower ; to accomodate the Ferguson transfer buffer & other stuff ; ; It is possible to EXCEED the max BIOS size of 400h ; ;## Conditionals for prir or a jr z,nopint ;initialize single port parallel printer nopint: xor a ; clear system disk number ld (4),a IF user31 ; only makes sense if user 31 ld (usrloc),a ENDIF ;user31 ; ; Ferguson code ; IF ferg call print db 1ah,'Era M?',0 call conin res 5,a cp 'Y' jr nz,noera di xor a ;swap in page 0 ld (0ffffh),a ld hl,0 ld de,1 ld (hl),0e5h ld bc,32*32 ;direc entries ldir ld a,0ch ld (0ffffh),a ;back to top page ei ENDIF ;ferg noera: ze variables ############################################ ; ; Max size for PLUS2 is 62k ; msize equ 62 ; system memory size in k moff equ 0 ; 1/4k increment: 0, 1, 2, or 3 for ; 0.00, 0.25, 0.5, and 0.75 k bias equ (msize-20)*1024+moff*256 ; bias for systems ; larger than 20k qcp equ 3400H+bias ; start of QCP qdos equ qcp+806H ; start of QDOS bios equ qcp+1600H ; start of Basic I/O Subsystem (BIOS) qpml equ bios-qcp ; length of QP/M system in bytes (less BIOS) nsects equ qpml/ess jp read ; read selected sector jp write ; write selected sector jp listst ; list status (Ready to print a char) jp sectran ; sector translate jp getdt ; right in the bios - get time/date ; ioconfig: defb 00000001B ; initial value for i/o byte (may be patched) wrtsafe: defb FALSE ; write safe flag bdrata: defb 7 ;1200 for both bdratb: defb 7 serprt: db 0 ;serial printer type protocol: ; 0=none, 1=xon/xoff, 2=etx/ack parprt: db 0 ;parallel printer type: 0=normal, ; 1=nter driver ####################################### ; ; Printer driver handled from printer driver code byte ; ; If you need other printer drivers, you will need to muck around ; with the code ; ; ;## Xerox port information ; ptsioc equ 07h ; serial printer port b status/control ptsiod equ 05h ; serial printer port b data sysdat equ 01ch ; system control port bauda equ 0 ; baud rate port a baudb equ 0Ch ; baud rate port b ;## Misc Conditionals #########################################call print db 26,13,10 db 'Xpro 820+2 (MICROCode) v2.6' db 13,10,0 call const ; flush boot charater from keyboard or a call nz,conin jr goccp ; ; Warm boot entry point, re-load the QCP and QDOS ; wboot: call diskint ; ; I REFUSE to put this junk in! (normally) ; call print db 13,10,'Boot',13,10,0 wb0: ld sp,100H ; re-set stack ld c,0 ; select drive A: call seldsk IF DOUB8 ld bc,1 ELSE ld bc,0 ; set track ENDIF ;DOUB8 call settrk ld hl,qcp ; first mem128 ; length of QP/M system in sectors(less BIOS) IF Sing8 trksec equ 27 ; sectors/track + 1 nexsec equ 1 ; first sector on track 1 firsec equ 1 ; first sector on track ENDIF ;Sing8 IF Doub8 trksec equ 64 ; sectors per track nexsec equ 1 ; doesn't matter firsec equ 0 ; first sector on track ENDIF ;Doub8 IF doub5 trksec equ 40 ; sectors per track nexsec equ 16 ; first sector on track 1 firsec equ 0 ; first sector on track ENDIF ;doub5 IF m80 aseg orsingle port A, 2=single port B ; IF HiBit vtab: defb ' ',3,' ' ; vector pad xlate table defb 8,' *+ -.' defb 12 ; setup for Keytronic kbd (FRANKLIN ACE) defb '0123456789 ' defb 27,' ',10 ENDIF ;HiBit ; ; Cold boot entry point, set up system pointers and pass control to the QCP boot: ld a,(ioconfig) ; init value for i/o byte ld (iobyte),a ld a,(bdrata) ; set baud rates out (bauda),a ld a,(bdratb) out (baudb),a ld a,(parprt) ;see if need to initialize parallel printe############ HiBit equ FALSE ; set to true to enable translation of ; keys with high bit set (msb). slodrv equ FALSE ; TRUE slows 'reads' down for disk drives ; with slow settling times (older 5 1/4's) user31 equ true ; TRUE for QP/M 31 user area reference ; (qpm MUST also be true) usrloc equ 000Bh ;location for 31 user location hold ;should be clear of drive/user flag & motor flg iobyte equ 3 ; logical to physical map maxdsk equ 4 ; max disk # ;## CP/M system sig 100h .phase bios ELSE org bios ENDIF ;m80 jp boot ; arrive here from cold start jp wboot ; arrive here for warm start jp const ; console status return in A FF=ready, 00=not jp conin ; console char in jp conout ; console char out jp list ; listing char out jp punch ; punch char out jp reader ; reader char in jp home ; move to track 0 on selected disk drive jp seldsk ; select disk drive jp settrk ; set track # jp setsec ; set sector # jp setdma ; set DMA addr  ory location to load ld bc,nsects*256+(firsec+1) wb1: push hl push bc ld b,h ld c,l call setdma pop bc push bc ; save sector count and current sector call setsec ; select sector call read pop bc pop hl or a jr nz,wb0 ; oops, error on warm boot ; ld de,128 ; new dma address add hl,de dec b jr z,goccp ; done loading inc c ; bump sector count ld a,trksec ; on to next track? cp c jr nz,wb1 ; ld c,nexsec ; first sector on next track push bc ; save counter or e jp nz,ilp djnz olp xor a ld (newdsk),a pass: ENDIF ;slodrv ld l,1BH ; read a logical sector jr callrom write: IF ferg ld a,(mdisk) cp 'M'-'A' jr z,frgout ENDIF ;ferg ld l,1EH ; write a logical sector ld a,(wrtsafe) ; write safe flag or a ; true or false jr z,callrom ; normal operation ld c,1 ; directory write code (forces write op) jr callrom IF ferg frgout: inc a frgio: or a call nz,m64 ;move into high mem di ld a,0 mtrack equ $-1 lk * 8 sectors/k db 3 db 7 db 0 dw (256-64)-1 ;max size dw 31 ;32 dir entries db 80h,00h ;pre-alloc for dir dw 0 ;no check dw 0 ;or offset ENDIF ;ferg ; I/O devices are selected using the IOBYTE ; logical devices are con: rdr: pun: and lst: ; physical devices are: ; crt: video and kbd ; tty: serial ; lpt: centronics parallel ; ul1: serial with cts as busy ; pun: same as ul1 ; ;con: tty, crt bits 0,1 ;rdr: tty bits 2,3 ;pun: tty, pun bits 4,5 ;lst: tty, crt, lpt, ul1 bitsp ; save current stack (may be under rom) ld sp,stack ; set a local stack di exx ; save cp/m arguments in a,(sysdat) ; turn rom on or 80h ; is faster than set out (sysdat),a ld de,biosret ; rom to "RET" here push de exx ; restore cp/m arguments and call loc ei ld h,0 ;ROM base at 0000h callhl: jp (hl) ; to routine specified in hl ; biosret: di ex af,af' ; save reg A ld sp,0 ; restore stack savsp equ $-2 in a,(sysdat) and 7fh out (sysdat),a ex af,af' ; restors push hl ld c,1 call settrk ; set track pop hl pop bc jr wb1 ; goccp: ld a,0C3H ; set up CP/M jumps to bdos and wboot ld hl,bios+3 ; wboot entry point ld (0),a ld (1),hl ld hl,qdos ; entry point to qdos ld (5),a ld (6),hl ld a,(4) ; last logical disk unit used ld c,a ; pass to ccp to select and 0fh ; make sure this is valid drive IF ferg cp 'm'-'a' jr z,okdsk0 ENDIF cp maxdsk jr c,okdsk0 ld a,c and 0f0h ld c,a ; okdsk0: IF qpm ;make d (0ffffh),a ld hl,0 msect equ $-1 ex af,af' srl h rr l ex af,af' ld de,mbuf jr z,rdw2 ex de,hl rdw2: ld bc,128 ldir ld a,0ch ;restore ld (0ffffh),a ei ret nz ;end for write m64: ld hl,mbuf ld de,0 mdma equ $-2 jr z,isrd0 ex de,hl isrd0: ld bc,128 ldir ret ENDIF ;ferg list: ld a,(iobyte) and 0C0H ; strip IOBYTE to lst: devices jr z,serial ; serial on SIO port B if lst:=tty:=00xxxxxxb pioad equ 8 pioac equ 10 piobd equ 9 cp 80h jr z,noxpl s 6,7 getdt: ld l,4bh jr callrom const: ld l,2ah jr callrom conin: ld l,2dh jr callrom ;; call callrom IF HiBit or a ; if msb set translate character ret p ; msb not set AND 01FH ; FORM TABLE INDEX TO VTAB ld hl,vtab ld c,a ld b,0 add hl,bc ld a,(hl) ; pick up xlated character ENDIF ;HiBit ;; and 07FH ; strip bit 7 ret reader: ret punch: ret diskint: ld l,03H ; re-set disk software sub-system jr callrom home: ld l,0CH ; home disk drive rom route reg A ei ret ; done with rom routine seldsk: IF ferg ld a,c ld (mdisk),a cp 'M'-'A' ld hl,dphm ret z ENDIF ;ferg IF slodrv ld a,0ffh ; set new disk flag ld (newdsk),a ; store it ENDIF ;slodrv ld l,0FH ; select disk drive jr callrom read: IF ferg ld a,0 mdisk equ $-1 sub 'M'-'A' jr z,frgio ENDIF ;ferg ; IF slodrv ld a,0ffh ; waste some time if its a new drive newdsk equ $-1 or a jr z,pass olp: ld de,80h ; delay loop ilp: dec de ld a,dsure clock is set call getdt ld a,(hl) or a jr nz,isokdt ; ld hl,tdprg ;time/date prog ld de,qcp+7 ld bc,tdprge-tdprg ;size ldir ;move it in jp qcp ;assume A0 ; tdprg: db 6,'SETCLK' ; set Emerald Microware clock tdprge equ $ ; MUST be capitals isokdt: ENDIF ;qpm ld a,3 ;so can do auto-boot on cold start ld hl,qcp qcpval equ $-2 ld (qcpval),a jp (hl) IF ferg dphm: dw 0 ;dphm dw 0 dw 0 dw 0 dw dirm ;dirbuf dw dpbm dw 0 dw alloc dpbm: dw 16*8 ;16ine jr callrom sectran: ld l,21H ; xlate logical to physical sector jr callrom settrk: IF ferg ld a,c ld (mtrack),a ENDIF ;ferg ld l,12H ; seek track jr callrom setsec: IF ferg ld a,c ld (msect),a ENDIF ;ferg ld l,15H ; set sector number jr callrom setdma: IF ferg ld (mdma),bc ENDIF ;ferg ld l,18H ; set dma address jr callrom conout: ld l,45h ; video output ; ; put here since conout is most frequently called of any ; callrom: ld (savsp),   listxp: call listst jr z,listxp ld a,c out (pioad),a xor a ;Send strobe out (piobd),a dec a out (piobd),a ret ld l,3FH ; centronics with polled status cp 80H ; as lst:=lpt: (same as Kaypro) jp z,callrom noxpl: ld l,45H ; video cp 40H ; video if lst:=crt:=01xxxxxxb jp z,callrom ld l,39h jp callrom ; if lst:=ul1:=11xxxxxxb ; serial: in a,(ptsioc) ; see if SIO port is busy and 4 jr z,serial ;loop until it's ready ld a,c out (ptsiod),a ;send the characte .Z80 LF EQU 0AH ; Ascii Linefeed CR EQU 0DH ; Ascii Carriage Return IOSEL EQU 1CH ; Control Port (Kaypro System Bit Port) ESC EQU 1BH ; Ascii Escape Character RAMST equ 0F600h MONITOR: LD HL,LODEND+1 LD BC,RAMEN-RAMST LD DE,RAMST LDIR JP RAMST LODEND: NOP .PHASE RAMST ; Start of Monitor in Ram IN A,(IOSEL) RES 7,A ; Bank 0 OUT (IOSEL),A STMON: LD SP,XSTACK LD HL,STMON PUSH HL ; save mon start addr LD A,'_' LD (CURCHR),A IN A,(BITPORT) SET 6,A Oinc hl ex (sp),hl ; save new return address or a ; is it a zero byte? ret z ld c,a ; no, so print it call conout jr print ;## I/O initialization table ############################################## ;## First byte is how many to send, next byte is where to send, following # ;## is what to send ####################################################### ;; ;; Int driven par. prnt. ;; ;; defb 3,LSTCNT ;; defb 0fh ;; defb LOW gpvec ;; defb 087h defb 0ffh defb 'MjM' ; to mark e --> FILE: -XPRO .SRC CRC = 00 00 --> FILE: BIOS .MAC CRC = 0C 22 --> FILE: MONITOR .MAC CRC = EE D8 --> FILE: XPRO206 .COM CRC = 9E 8E --> FILE: XPROCRT .MAC CRC = 07 E0 --> FILE: XPRODISK.MAC CRC = AA 43 --> FILE: XPROIO .MAC CRC = 4D 7C --> FILE: XPRORAM .MAC CRC = DF B1 --> FILE: XPRORAM .PRN CRC = A6 C6 --> FILE: XPRORAM .REL CRC = D8 57 --> FILE: XPROROM .MAC CRC = 97 E5 --> FILE: XPROROM .REL CRC = F6 21 --> FILE: HUTIL .COM CRC = 42 42 --> FILE: HUTILr ;; ;;; XON/XOFF ;; ;; call serin ;get serial in char, else 0 if none ;; ret z ;; cp 'S'-'A'+1 ;check for ctrl-s ;; ret nz ;;serwt: call serin ;wait for any char ;; jr z,serwt ;; ;;; etxack ;; ;; cp 0ah ;lf? ;; ret nz ;nope - forget it ;;serwt1: call siost ;get status ;; jr z,serwt1 ;; ld a,3 ;send ETX ;; out (ptsiod),a ;;serwt: call serin ;; jr z,serwt ret serin: in a,(ptsioc) ;else wait for another char and 1 ret z in a,(ptsiod) ;else get data ret listst:UT (BITPORT),A CALL PMESG ; Print following Message Function DB 1ah,esc,'=',24h,20h,'XPRO System Monitor Version 2.06' DB CR,LF,LF DB 'B = boot CP/M from Drive A',CR,LF DB 'D nn = dump MEMORY from PAGE nn',CR,LF DB 'E nnnn = examine/edit MEMORY from nnnn',CR,LF DB 'P nn = display/write PORT nn',CR,LF DB 'X nnnn = execute CODE @ nnnn',CR,LF DB 'Z = zero MEMORY',CR,LF,LF DB 'Select option: ',0H LD IY,KBDIN CALL XQROM ; get keycode AND 5FH ; Upper Case Conversion nd of bios stack equ bios+400h IF ferg alloc equ $ dirm equ alloc+(256-64)/8+2 mbuf equ dirm+128 mbufe equ mbuf+128 ENDIF ;ferg biose equ $ IF (stack-64) lt biose printx / #### Problem, bozo breath #### / ENDIF IF m80 .DEPHASE ENDIF ;m80 end driven par. prnt. ;; ;; defb 3,LSTCNT ;; defb 0fh ;; defb LOW gpvec ;; defb 087h defb 0ffh defb 'MjM' ; to mark eC .COM CRC = 8A 25 ld a,(iobyte) ; check i/o byte and 0C0H jp z,siost ;check status on sio port b cp 80h jr z,giveup in a,(piobd) ;Xerox parallel cable and 10000b xor 10000b ld a,0 ret z ;else fall through to ready ld l,3CH ; centronics cp 80H jp z,callrom giveup: or 0ffh ; 0ffh=ready ret ; siost: in a,(ptsioc) and 4 ; is it ready ret z jr giveup ;is true print: ex (sp),hl ; pop return address, points to text to print ld a,(hl) ; get a byte of text, stop on zero byte    PUSH AF CALL TVID ; Output to screen POP AF CP 'B' ; Boot 8" disks? LD IY,BOOT8 JP Z,XQROM NXCH1: CP 'D' ; Dump memory? JP Z,DUMP CP 'E' ; Insert in memory? JP Z,INSRT CP 'P' ; Read/write port? JP Z,PORT CP 'X' ; eXecute program? JR NZ,NXCH2 CALL NUMIN JP (HL) NXCH2: CP 'Z' ;zero memory? RET NZ LD HL,0 ; Set source ptr LD (HL),0 ; Zero source LD DE,1 ; Set dest ptr LD BC,RAMST-1H ; Get ByteCount Note: we only fill memory up ; to the bottom of this Mo 4 right RRA RRA CALL HEX1 ;output 1st char POP AF ;restore data HEX1: AND 0FH ;mask msn ADD A,30H ;make ascii CP 3AH ;alpha? JR C,HEX2 ADD A,7H HEX2: JP TVID ;call + ret ; SPAC: LD A,20H ;ascii space ; ; TVID: PUSH BC ;output char in A.. PUSH HL ;..to terminal pgm LD C,A LD IY,VIDOUT CALL XQROM POP HL POP BC RET ; INTSCR: LD A,1AH CALL TVID RET ; ;### Execute the Code in ROM at the address in IY ######################### ; XQROM: IN A,(IOSEL) ;get sys 20H ;sp? JP Z,DMP1 ;do nxt page CP CR ;done? RET Z JR DMP7 ;try agn ; ; INSRT: CALL NUMIN ;get addr PUSH HL ;save it.. POP IX ;..in IX CALL INTSCR ;clr scr CALL PMESG DB 'Insert Mode: (sp) to skip, (cr) to exit' DB CR,LF,0 INSR1: CALL PMESG ;start new line DB CR,LF,0 PUSH IX ;get.. POP HL ;..addr LD A,H CALL HEXO LD A,L ;display addr CALL HEXO CALL PMESG DB ' = ',0 LD A,(IX) ;display.. CALL HEXO ;..contents CALL PMESG DB ' <-',0 CALL NUMIN  A ;dec port# LD (CPORT),A CALL PORT5 ;baudb port? JR Z,PORT4 ;yes, skip JR PORT1 PORT5: AND 9CH ;mask don't care bits XOR 0CH ;invert baudb port# RET ;Z=1 for baudb port ; CPORT: DS 1 ; ; ; second level subroutines ; PMESG: EX (SP),HL LD A,(HL) INC HL EX (SP),HL OR A RET Z CALL TVID ;char to screen JR PMESG ; NUMIN: CALL SPAC ;ascii space LD B,0 ;init keycnt LD HL,0 ;init HL=0 NUMN1: LD IY,KBDIN CALL XQROM RES 7,A CP 60H ;LC? JR C,NUMN2 SUB 20Hnitor LDIR ; block move RET ; ;### first level routines ############################################## ; DUMP: CALL NUMIN ;get page addr LD H,L ;make.. LD L,0 ;..full addr DMP1: PUSH HL CALL INTSCR ;clr scr CALL PMESG DB 'Dump Mode: (sp) for next page, (cr) to exit' DB CR,LF,LF,0 POP HL LD B,10H ;16 lines DMP2: PUSH BC ;display 1 line LD A,H CALL HEXO ;msb addr LD A,L CALL HEXO ;lsb addr CALL SPAC LD B,10H ;char cnt PUSH HL ;save addr ptr DMP3: CALL Stem port.. LD (SPSAV),A ;..save value SET 7,A ;..and insure OUT (IOSEL),A ;..bank 1 PUSH HL ;place ret addr.. LD HL,ROMRT ;..on XSTACK, but EX (SP),HL ;..leave HL unchanged JP (IY) ;execute subroutine.. ROMRT: PUSH AF ;..and return here LD A,(SPSAV) ;restore.. OUT (IOSEL),A ;..system port POP AF RET ; SPSAV: DS 1 ;system port storage ; DS 30H ;XSTACK space XSTACK EQU $ RAMEN EQU XSTACK ; .DEPHASE  ;new val? LD A,B OR A ;check keycnt JR Z,INSR2 LD (IX),L ;enter new val JR INSR3 INSR2: LD A,C ;get keycode CP CR RET Z INSR3: INC IX ;next addr JR INSR1 ; ; PORT: CALL NUMIN ;get port# LD A,L LD (CPORT),A ;save it CALL INTSCR ;clr scr CALL PMESG DB 'Port Mode: < to last port, > to next port, ' DB '(sp) same port, (cr) to exit',CR,LF,0 PORT1: CALL PMESG DB CR,LF,0 LD A,(CPORT) ;get the.. LD C,A ;..current port# CALL HEXO ;to screen CALL PMESG DB ' = ', ;cnvt to UC NUMN2: LD C,A ;save keycode SUB '0' RET C ;too small CP 0AH JR C,NUMN3 ;from 0 to 9 SUB 7H ;ASCII to HEX CP 0AH ;char between.. RET C ;..a 9 and an A CP 10H ;char greater.. RET NC ;..than F NUMN3: ADD HL,HL ;here only if 0-9 or A-F ADD HL,HL ADD HL,HL ;shift 4 left ADD HL,HL ADD A,L ;enter new.. LD L,A ;..value, and INC B ;..bump keycnt LD A,C ;get code.. CALL TVID ;..to screen JR NUMN1 ; HEXO: PUSH AF ;save data in A RRA RRA ;shiftPAC ;display hex LD A,(HL) INC HL CALL HEXO ;to screen DJNZ DMP3 POP HL ;restore addr LD B,10H ;char cnt CALL PMESG DB ' |',0 DMP4: LD A,(HL) ;display ascii INC HL CP 20H ;cntrl char? JR C,DMP5 ;delete it CP 80H ;printable? JR C,DMP6 ;yes DMP5: LD A,'.' ;replace char DMP6: CALL TVID ;ascii to scr DJNZ DMP4 CALL PMESG DB '|',CR,LF,0 POP BC ;restore linecnt DJNZ DMP2 ;do 16 lines (256 bytes) DMP7: LD IY,KBDIN CALL XQROM AND 07Fh ;strip high bit CP0 IN A,(C) ;port content CALL HEXO ;to screen CALL PMESG DB ' <-',0 CALL NUMIN ;new val? LD A,B OR A ;keycnt=0? JR Z,PORT2 ;yes LD A,(CPORT) ;reload C.. LD C,A ;..register OUT (C),L ;new val out JR PORT1 PORT2: LD A,C ;get keycode CP CR ;done? RET Z ;yes, exit CP '>' ;->? JR Z,PORT3 CP '<' ;<-? JR Z,PORT4 JR PORT1 PORT3: LD A,(CPORT) INC A ;inc port# LD (CPORT),A CALL PORT5 ;baudb port? JR Z,PORT3 ;yes, skip JR PORT1 PORT4: LD A,(CPORT) DEC  KÃÈ  G|ËL T c d j r Å Ä | Ù Ò1 ͒ ͈ ̓> 2.ͳ =$ XPRO System Monitor Version 2.05 >22>2R>vL ( >T 2͒̓>2)>2&>2(>2*>2:((:(¨: KCKKA: +:2&: 2: 2.: 2):&g(%:2':2(:(_(:( >?2*¨*" :*< :*'(ͳ > Bad System Disk <T &c&cR(KÃÈ  G|ËL T c d j r Å Ä | Ù Ò1 ͒ ͈ ̓> 2.ͳ =$ XPRO System Monitor Version 2.06 >22>2R>vL ( >T 2͒̓>2)>2&>2(>2*>2:((:(¨: KCKKA: +:2&: 2: 2.: 2):&g(%:2':2(:(_(:( >?2*¨*" :*< :*'(ͳ > Bad System Disk <T &c&cR(s#r>U!:#( ( (!>v ͞gR2>ÞR:( (yO0:(=:0 :&( 8-:'8#y2G8y>͞yyxGy2>Þ:(=(=(:(g:(o:(w:(:)G:((Wy( :y   :y Wy(z`i n&>|:(  ><_ܳ!w˷2͒z•vG >j>J:Wͪ O:W͙ O:O)Ki:O. =$ XPRO System Monitor Version 2.00 B = boot CP/M from Drive A D nn = dump MEMORY from PAGE nn E nnnn = examine/edit MEMORY from nnnn P nn = display/write PORT nn X nnnn = execute CODE @ nnnn Z = zero MEMORY Select option: !T t_aB!tDTEPSX Z!6e.n Dump Mode: (sp) for next page, (cr) to exit |I}I__~#I |~# 88>.a | !T t Z n Insert Mode: (sp) to skip, (cr) ?     (?(_?@+      @/ !R!2R2 2 >2>2222 2#! "!:9y2)y2CC:O: 2 O:2 >22>2Å:´2y2=>2 :2 *" :2: }=2 :! }! }:!}4:*v6* #" 2Å2 <22:2! ~6:!º!º:!: :2*":2:2 :o&)))))))[: >?     (?(_?@+      @/ !R!2R2 2 >2>2222 2#! "!:9y2)y2CC:O: 2 O:2 >22>2Å:´2y2=>2 :2 *" :2: }=2 :! }! }:!}4:*v6* #" 2Å2 <22:2! ~6:!º!º:!: :2*":2:2 :o&)))))))[: >:W<ͱ2 O:W<͠2 O:O)Ki:O˿*!*!R˿!f~6xG {((v v (v v 2f͞>  DDO    O!F#N#~y!@"!= >G^/22M:>L (>2:d ((y>>] >2021> 2-!-F*+|0gp ~2- :.w"+˹0 y 8:1G(ya8Oq#}PX ͳ ! ͩ to exit |I}I = ~I <-x(uy #}2 n Port Mode: < to last port, > to next port, (sp) same port, (cr) to exit : OI = xI <-x(: Oiy >(<(: <2 (: =2 ( ~#a_!!T t˿`8 O0 8 ))))oyaR0:8a> O! t>a2!:)))oyaR0:8a> O! t>a2!:2 ͊::2 :!#!:&g yyз!2(!C( !(!:_y2!{#( ( (( y!#(! ( !(!~(Ec!>'2*:(#(((!+!s!I>?2*!:>2R5(> 2R5V>'2*s#r cs#r5c!> : 8 8 !+> >>!2 :(W:(((Z &R  J B rs#r Ts#r>ͮ>2R5ͨ >>?2*s#r cs#r5 :8 !0>!sS>!IS> 2s#r  M / = 5 X t ] ' + >>}+}O#}xP}o˧}o!00 6 >2/}O>PG t :/O}|(ͨ |0&;|<&0}|Oͨ :/ )|2/}oP6 # >6 /y=(&_G(A(E(MRʄ :121:1ˇ21> >:/0`g.< y P0Po X }|:/W_z0Wbk{z bk ͝ PX X }|O:/  ͨ PX  N#F~#O͙ &c ,&cRr! ˿1!>_2  2 ͊::2 :!#!:&g yyз!2(!C( !(!:_y2!{#( ( (( y!#(! ( !(!~(Ec!>'2*:(#(((!+!s!I>?2*!:>2R5(> 2R5V>'2*s#r cs#r5c!> : 8 8 !+> >>!2 :(W:(((Z &R  J B rs#r Ts#r>ͮ>2R5ͨ >>?2*s#r cs#r5 :8 !0>!sS>!IS> 2s#r  CALL OUTCH ; ; NOW STORE A NEW CURSOR CHARACTER AT THE CURSOR LOCATION ; LD A,(HL) ;GET CHARACTER AT NEW CURSOR LOCATION LD (CHRSAV),A ;SAVE FOR NEXT TIME 'CRTOUT' IS CALLED CP ' ' ;TEST IF CHARACTER IS A SPACE SET 7,A ;THEN TURN ON BIT 7 TO ENABLE BLINK JR NZ,CRT2 ;JUMP IF CHARACTER IS NON-BLANK LD A,(curchr) ; ELSE GET CHARACTER USED FOR CURSOR CRT2: LD (HL),A ;STORE CHARACTER IN A AS CURSOR MARK LD (CURSOR),HL ;SAVE HL AS CURSOR POINTER pop bc pop de pop hl ret OUTCH: R M / = 5 X t ] ' + >>}+}O#}xP}o˧}o!00 6 >2/}O>PG t :/O}|(ͨ |0&;|<&0}|Oͨ :/ )|2/}oP6 # >6 /y=(&_G(A(E(MRʄ :121:1ˇ21> >:/0`g.< y P0Po X }|:/W_z0Wbk{z bk ͝ PX X }|O:/  ͨ PX  N#F~#O͙ &c ,&cRr! ˿1!>_2subttl XproCRT *** Memory Mapped CRT Driver with Hardware Scroll *** page ;******************************************************** ;* * ;* MEMORY-MAPPED CRT OUTPUT DRIVER * ;* * ;* Russell Smith 18-August-1980 * ;* * ;******************************************************** ; ; CRTBAS EQU 30H ;STARTING PAGE# OF 3K CRT SPACE CRTTOP EQU 3CH ;ENDING PAGE# OF CRT SPACE ; GRKBIT EQU 0 ;bit of CRTFLG indicating greek mode ; ; VIDINIT: call clrscn ; fill video mems#r>U!:#( ( (!>v ͞gR2>ÞR:( (yO0:(=:0 :&( 8-:'8#y2G8y>͞yyxGy2>Þ:(=(=(:(g:(o:(w:(:)G:((Wy( :y   :y Wy(z`i n&>|:(  ><_ܳ!w˷2͒z•vG >j>J:Wͪ O:W͙ O:O)Ki:OES 7,C ;FIRST make sure no wierd characters LD DE,LEADIN ; have been sent to us LD A,(DE) ;GET LEAD-IN SEQUENCE STATE OR A JP NZ,MULTI ;JUMP IF IN A LEAD-IN SEQUENCE LD A,C ; ELSE PROCESS CHARACTER IN C CP ' ' JR C,CONTRL ;JUMP IF A CONTROL CHARACTER DISPLA: ;ELSE display the character in C LD A,(CRTFLG) ;first see if greek mode is set BIT GRKBIT,A JR Z,DSPL1 ;IF not greek mode THEN display 'as is' LD A,C CP 'a' ;IF < 'a' THEN don't change JR C,DSPL1 AND 1Fh ;ELS. =$ XPRO System Monitor Version 2.06 B = boot CP/M from Drive A D nn = dump MEMORY from PAGE nn E nnnn = examine/edit MEMORY from nnnn P nn = display/write PORT nn X nnnn = execute CODE @ nnnn Z = zero MEMORY Select option: !T v_cB!vDTEPUX Z!6e.p Dump Mode: (sp) for next page, (cr) to exit |K}Kaa~#K |~# 88>.c | !T v Z p Insert Mode: (sp) to skip, (crory with blanks ld a,0 ld (leadin),a ld (crtflg),a ld a,' ' ld (chrsav),a ret VIDOUT: push hl push de push bc ; FIRST REMOVE THE OLD CURSOR CHARACTER FROM THE SCREEN LD HL,CHRSAV ;GET CHARACTER NOW OVERLAYED BY CURSOR LD B,(HL) LD HL,(CURSOR) ;LOAD HL WITH CURSOR POINTER LD A,H AND 00001111B ;A LITTLE INSURANCE THAT HL CAN'T OR CRTBAS ; EVER POINT OUTSIDE THE CRT MEMORY LD H,A LD (HL),B ;REMOVE CURSOR BY RESTORING CHARACTER ; ; PROCESS CHARACTER PASSED IN C ; :W<ͱ2 O:W<͠2 O:O)Ki:O˿*!*!R˿!f~6xG {((v v (v v 2f͞>  DDO    O!F#N#~y!@"!= >G^/22M:>L (>2:d ((y>>] >2021> 2-!-F*+|0gp ~2- :.w"+˹0 y 8:1G(ya8Oq#}PX ͳ ! ͩ ) to exit |K}K = ~K <-x(uy #}2 p Port Mode: < to last port, > to next port, (sp) same port, (cr) to exit : OK = xK <-x(: Oiy >(<(: <2 (: =2 ( ~#ca!!T v˿`8 O0 8 ))))oycT0:8c> O! v>c2!:)))oycT0:8c> O! v>c2!:  E make lower case into a control char. LD C,A ;and put back into C to display it DSPL1: LD (HL),C ; STORE DISPLAYABLE CHARACTER INC HL ; AND ADVANCE POINTER TO NEXT COLUMN LD A,L AND 01111111B ;EXTRACT COLUMN# FROM HL CP 80 RET C ; EXIT IF NOT PAST COLUMN 79 CALL RETURN ; ELSE DO AUTOMATIC CARRIAGE RETURN CALL LFEED ; AND LINEFEED RET CONTRL: PUSH HL LD HL,CTLTAB ;SEARCH FOR CONTROL CHARACTER LD BC,CTLSIZ/3 ; HANDLING SUBROUTINE IN TABLE CALL SEARCH POP HL RET NZ ;EX BEFORE MOVING DOWN RET NZ ;EXIT IF NOT AT BOTTOM PUSH HL ;ELSE PREP TO SCROLL SCREEN UP CALL CLRLIN ;FILL NEW BOTTOM LINE WITH SPACES ADD HL,HL LD A,H ;GET ROW# COMPONENT OF HL INTO A AND 00011111B LD (BASE),A ;STORE NEW BASE LINE# OUT (SCROLL),A ;NOW SCROLL UP NEW BLANK BOTTOM LINE POP HL RET ; ; CLRLIN: LD A,L AND 10000000B ;POINT HL TO FIRST COLUMN OF ROW LD L,A LD B,80 CLR: LD (HL),' ' ;STORE ASCII SPACES AT ADDRESS IN HL INC HL ; AND INCREMENT HL DJNZ CLR ;REPRET ; FOR CONTROL CHAR OUTPUT MODE ; ; BAKSPC: LD A,L ;CHECK FOR LEFT MARGIN AND 01111111B RET Z ;ABORT IF IN LEFTMOST COLUMN DEC HL ;BACK UP CURSOR POINTER RET ; ; FORSPC: LD A,L ;CHECK FOR RIGHTMOST COLUNM AND 01111111B CP 79 RET NC ;DO NOTHING IF ALREADY THERE INC HL RET ;ELSE ADVANCE THE CURSOR POINTER ; ; TAB: LD DE,8 ;TABS ARE EVERY 8 COLUMNS LD A,L ;GET COLUMN COMPONENT OF AND 01111000B ; PREVIOUS TAB POSITION ADD A,E CP 80 ;EXIT IF NEXT TAB COLUMN WOULDCOPY BASE SCREEN ROW# TO C CLRS1: LD A,L RLA LD A,H RLA ;GET ROW# COMPONENT OF HL INTO A AND 00011111B CP C ;SEE IF HL IS AT BOTTOM ROW OF SCREEN JR Z,CLRS2 ; AND LEAVE CLEAR LOOP IF SO CALL DNCSR ;ELSE POINT HL TO NEXT ROW DOWN CALL CLRLIN ; AND FILL THAT LINE WITH SPACES JR CLRS1 CLRS2: POP HL ;RESTORE ORIGINAL CURSOR POINTER RET ; ; UPCSR: LD DE,-128 ;SUBTRACT 1 FROM ROW# COMPONENT ADD HL,DE ; OF CURSOR POINTER IN HL LD A,H CP CRTBAS ;CHECK FOR UNDERFLOW OF POINIT IF NOT IMPLEMENTED PUSH BC RET ;DO SNEAKY JUMP TO PRESERVE REGISTERS CTLTAB: DEFB '_'-64 DEFB '^'-64 DEFB '['-64 DEFB 'Z'-64 DEFB 'X'-64 DEFB 'Q'-64 DEFB 'W'-64 DEFB 'M'-64 DEFB 'L'-64 DEFB 'K'-64 DEFB 'J'-64 DEFB 'I'-64 DEFB 'H'-64 DEFB 'G'-64 DEFW BELLRNG ;CTL-G IS THE BELL DEFW BAKSPC ;CTL-H IS CURSOR LEFT DEFW TAB ;CTL-I IS TAB DEFW LFEED ;CTL-J IS CURSOR DOWN DEFW UPCSR ;CTL-K IS CURSOR UP DEFW FORSPC ;CTL-L IS CURSOR RIGHT DEFW RETURN ;CTL-MEAT NUMBER OF TIMES GIVEN BY B RET ; ; HOMEUP: LD C,' ' ;FAKE-OUT CURSOR ADDRESSING ROUTINE JR SETROW ; TO DO HOMEUP ALMOST FOR FREE ; ; MULTI: EX DE,HL ;UNCONDITIONALLY RESET THE LEAD-IN LD (HL),0 ; STATE TO ZERO BEFORE GOING ON EX DE,HL CP 1 JR NZ,M2TST LD A,C ;GET SECOND CHAR OF SEQUENCE CP '=' ;IF cursor address command JR Z,SETXY ;THEN set the leadin to get it next time AND 5Fh ;ELSE uppercase it and try these CP 'G' ;IF 'display greek' JR Z,SETGRK ;THEN set the RET NC ; BE PAST THE RIGHT MARGIN LD A,L AND 11111000B ;ELSE INCREMENT THE CURSOR LD L,A ; POINTER FOR REAL ADD HL,DE RET ; ; BELLRNG: IN A,(BITPORT) SET 4,A ;TOGGLE BIT 5 OF SYSTEM PIO TO OUT (BITPORT),A ; TRIGGER BELL HARDWARE TO SOUND RES 4,A OUT (BITPORT),A RET ; ; RETURN: LD A,L AND 10000000B LD L,A ;MOVE CURSOR POINTER BACK RET ; TO START OF LINE ; ; CLRSCN: LD HL,CRTMEM PUSH HL LD DE,CRTMEM+1 LD BC,24*128 LD (HL),' ' LDIR ;FILL CRT MEMORY WITHTER RET NC LD H,CRTTOP-1 ;WRAP CURSOR AROUND MODULO 3K RET ; ; DNCSR: LD DE,128 ;ADD 1 TO ROW# COMPONENT ADD HL,DE ; OF CURSOR POINTER IN HL LD A,H CP CRTTOP ;CHECK FOR OVERFLOW OF POINTER RET C LD H,CRTBAS ;RESET POINTER MODULO 128*24 RET ; ; ; LFEED: LD A,L RLA LD A,H RLA ;EXTRACT ROW# COMPONENT OF HL AND 00011111B LD C,A ;COPY ROW# INTO C FOR SCROLL TEST CALL DNCSR ;MOVE CURSOR TO NEXT ROW DOWN LD A,(BASE) ;TEST IF CURSOR WAS ON BOTTOM ROW CP C ; OF SCREEN IS CARRIAGE RETURN DEFW CLREOS ;CTL-W IS ALSO CLEAR EOS FOR COMPATIBILITY DEFW CLREOS ;CTL-Q IS CLEAR TO END-OF-SCREEN DEFW CLREOL ;CTL-X IS CLEAR TO END-OF-LINE DEFW CLRSCN ;CTL-Z IS CLEAR SCREEN DEFW ESCAPE ;CTL-[ IS ESCAPE DEFW HOMEUP ;CTL-^ IS HOME UP DEFW STUFF ;CTL-_ IS DISPLAY CONTROL CHARS CTLSIZ EQU $-CTLTAB ; ; ESCAPE: LD A,1 LD (DE),A ;SET LEAD-IN SEQUENCE STATE RET ; FOR XY CURSOR POSITIONING MODE ; ; STUFF: LD A,4 LD (DE),A ;SET LEAD-IN SEQUENCE STATE  SPACES POP HL ;POINT TO HOME CURSOR POSITION LD A,23 LD (BASE),A ;MAKE BASE LINE# BE 23 AND OUT (SCROLL),A ; STORE IN SCROLL REGISTER RET ; ; CLREOL: PUSH HL ;SAVE CURSOR POINTER LD A,L AND 01111111B ;GET COLUMN# COMPONENT OF LD C,A ; CURSOR POINTER INTO C LD A,80 ;CALCULATE HOW MANY CHARACTERS SUB C ; REMAIN ON CURRENT LINE LD B,A CALL CLR ;CLEAR REST OF LINE @ HL POP HL RET ; ; CLREOS: CALL CLREOL ;CLEAR REMAINDER OF CURRENT ROW PUSH HL LD A,(BASE) LD C,A ;   bit to do it CP 'A' ;IF 'don't display greek' JR Z,RSTGRK ;THEN reset the greek bit CP 'E' ;IF insert line commands JR Z,INLIN ;THEN insert it already! CP 'R' ;IF delete line command JP Z,DELLIN ;THEN get it out of here RET ; SETGRK: LD A,(CRTFLG) ;set greek display SET GRKBIT,A ;all it takes is this bit being set LD (CRTFLG),A RET ; RSTGRK: LD A,(CRTFLG) ;reset greek display RES GRKBIT,A LD (CRTFLG),A RET ; SETXY: LD A,2 LD (DE),A ;MAKE LEADIN=2 NEXT TIME RET M2subttl XproDISK *** Disk and Boot Routines *** page aseg ORG 0 .comment % ######################################################## ## ## ## Cold start routine, reset and configure ## ## system for power up condition. ## ## ## ## Copyright (C) 1982 By Non-Linear Systems, Inc ## ## No warranty is made, expressed or implied. ## ## LD A,H ; FOR END RLA AND 1FH PUSH AF ; NOW SAVE IT ; LD A,(BASE) ;GET CURRENT BOTTOM LINE RRA ; AND CONVERT IT TO 16-BIT LD D,A ; FOR USE AS MEM POINTER RRA AND 80H ;GET RID OF EXTRANEOUS BITS LD E,A LD A,D ;NOW TAKE CARE OF HOUSE KEEPING OR CRTBAS ;MAKE SURE WE ARE IN CRT MEMORY LD D,A ; AND PUT BACK IN DE LD H,D ;PUT THE POINTER INTO HL LD L,E ; ; INLIN1: LD A,E ; GET ROW# FROM DE RLA LD A,D RLA AND 1FH POP BC ;RETRIEVE END LINE # CP B ;SEE IF THIS  CALL DNCSR ; AND MOVE TO NEXT LINE DOWN POP DE ; NOW MAKE OLD LINE NEW DESTINATION LD BC,80 ;COPY 80 BYTES LDIR ;MOVE IT CALL RETURN ;PUT CARRIAGE BACK AT BEGINNING OF LINE JR DLIN1 ;GO UPDATE NEXT LINE ; ;---------------------------------------------------------------------- ; SEARCH: CPIR RET NZ add hl,bc add hl,bc add hl,bc ld c,(hl) inc hl ld b,(hl) ret PRINT: ex (sp),hl ld a,(hl) inc hl ex (sp),hl or a ret z ld c,a call vidout jr print TST: CP 2 JR NZ,M3TST LD A,3 LD (DE),A ;MAKE LEADIN=3 NEXT TIME SETROW: LD A,(BASE) ;ARRIVE HERE ON THIRD CHARACTER ADD A,C ; OF ESC,'=',ROW,COL SEQUENCE SUB ' '-1 SETR2: SUB 24 JR NC,SETR2 ;MAKE SURE ROW# IS BETWEEN 0 AND 23 ADD A,24 OR 60H ;CRTMEM.SHR.7 (MERGE IN MSB'S OF CRT MEMORY) LD H,A LD L,0 SRL H RR L RET M3TST: CP 3 JR NZ,M4TST SETCOL: LD A,C ;ARRIVE HERE ON FOURTH CHARACTER SUB ' ' ; OF ESC,'=',ROW,COL SEQUENCE SETC2: SUB 80 JR NC,SETC2 ;MAKE SURE COL#  ## ######################################################## ## xPRO 8+ System Disk Drivers 7/22/84 DmC ## ## Micro Cornucopia ## ## NLS monitor patched by Dana Cotant ## ######################################################## % .z80 cr equ 0dh lf equ 0ah ; ROM master jump table jp start ; start up computer jp diskinit ; disk initialize jp vidinit ; video initialize jp devinit ; device initializWAS THE LAST ONE JR NZ,INLIN2 ; IF NOT THEN GO DO ANOTHER LD H,D ;OTHERWISE GO DOWN ONE LINE LD L,E CALL CLRLIN ;CLEAR THE NEW LINE POP HL ;POINT TO BEGINNING OF LINE RET ;AND GO BACK ; INLIN2: PUSH BC ;SAVE ENDING LINE# PUSH HL ;SAVE CURRENT SOURCE LINE CALL UPCSR ;POSTITION SOURCE UP ONE LINE POP DE ; PUT OLD LINE INTO DE IT IS NEW DESTINATION LD BC,80 ;COPY 80 CHARACTERS LDIR ;MOVE THEM CALL RETURN ;PUT CARRIAGE AT BEGINNING OF LINE JR INLIN1 ;GO CHECK FOR END ;IS BETWEEN 0 AND 79 ADD A,80 OR L ;MERGE IN COL# WITH L LD L,A RET M4TST: CALL DISPLA ;DISPLAY THE CONTROL CHARACTER RET ; PASSED IN C ; ;-------------------------------------------------------------------- ;----- INSERTION TO HANDLE INSERT & DELETE LINES -------------------- ;-------------------------------------------------------------------- ; INLIN: CALL RETURN ;POINT TO BEGINNING OF LINE PUSH HL ;SAVE CUR-POS FOR RETURN LD A,L ;GET ROW # INTO A RLA ;FOR FUTURE CHECK  ;-------------------------------------------------------------------- ; DELLIN: CALL RETURN ;PUT POINTER TO START OF LINE PUSH HL ;SAVE FOR EXIT ; DLIN1: LD A,L ;GET ROW# OF HL INTO A RLA LD A,H RLA AND 1FH LD C,A ;PUT INTO C FOR TEST LD A,(BASE) ;SEE IF CURSOR IS ON BOTTOM LINE CP C JR NZ,DLIN2 ;IF NOT THEN GO MOVE ANOTHER CALL CLRLIN ;OTHERWISE CLEAR THE BOTTOM LINE POP HL ;POINT TO BEGINNING OF DELETED LINE RET ; AND GO BACK ; DLIN2: PUSH HL ;SAVE CURRENT CURSOR   e jp home ; home selected disk drive jp seldsk ; select a disk drive jp settrk ; seek a track jp setsec ; set sector number to read jp setdma ; set dma address jp read ; read logical sector jp write ; write logical sector jp sectran ; xlate sector number jp diskon ; turn on disk jp diskoff ; turn off disk jp kbdstat ; KeyBoarD character ready jp kbdin ; input from keyboard jp kbdout ; output to keyboard (used to ring bell) jp ttystat ; status of serial input port jp ttyin ;ve type byte ld (trkflg),a ; store in scratch ram ld a,(0F60BH) ld (ramtry),a ld a,(0F60CH) ; cursor character location ld (curchr),a ; where it is stored in scratch ram ld a,(0F60DH) ; slow step rate to use (if required) ld (speed),a ; ld a,(trkflg) ; lets see if this is four drive bit 4,a ; if bit 4 is set it is four drive system jr z,twodrv ; jump if so ld a,(0F60Eh) ; external drive type ld (xtrkflg),a ; store in scratch ram ld a,(0f60fh) ; Describes drive characterics r drive B: 0=96tpi 1=48tpi ; ; BIT 4 DETERMINES EXTERNAL DRIVE CAPABILITY ; ; 1 IF EXTERNAL ; 09 defb 0 ; 0A defb config ; DC if the disk has been configged with ; ; drivetype and cursor char ; 0B defb ramtry ; retry outer loop count for r/w errors ; 0C defb cursor ; cursor character ; 0D defb stprt ; slow step rate to use for slow drives ; 0E DEFB exter ; MSB for drive c: 0=96tpi 1=48tpi ; ; LSB for drive d: 0=96tpi 1=48tpi ; 0F DEFB x8flg ; ABCDabcd each bit refers to a drive ; ,0 call seldsk ; select disk, set density, do home after ; diskinit ld a,2 ld (ramtry),a ld a,(sidflg) cp 0fh ; if double density go to track 1 ld bc,1 ; set track for 8 double jr z,loadprms cp 0dfh jr z,loadprms ld bc,0 ; set track for 8 single or 5 double loadprms: call settrk ld c,0 ld a,(denflag) or a jr z,ldprms ld c,1 ldprms: call setsec ld bc,0F600H ; header sector to go here call setdma call read ; read sector to F600 di ; read does EI upo serial input jp ttyout ; serial output jp liststat ; list output status (Centronics) jp list ; list output JP TTYOSTAT ; TEST STATUS OF SERIAL OUTPUT jp vidout ; video output jp thnsd ; short delay start: di ; stop interupts while setup ld sp,stack ; rom stack point ld b,10 ; a delay to let the hardware stabilize call thnsd call devinit ; init device sub-system call vidinit ; init video sub-system call diskinit ; init disk sub-system jr bootsys ; boot system org 66H  ; ABCDabcd ; abcd..if a is 1 A: is 8" etc. ; ABCD..if A is 1 use slow step rate ; on drive A: etc. ld (x8flag),a ; put it away noload: ld a,(x8flag) ; in case we are coming from above ; branch bit 3,a ld c,2 ; sector 2 is next for 8" single jr z,twodrv ld a,(sidflg) cp 0fh jr z,cbx ; if A is 8" double we want to go to ; sector 1 next cp 0dfh ; see if A is 8" double sided jr nz,cb1 ; must be 8" single density cbx: ld a,63 ld (cpmspt),a twodrv:  ; High nibble---A one in a given drive ; ; location means use slow step rate for ; ; that drive. ; ; Low nibble---A one in a given drive ; ; position means that drive is 8 inch ; ; (* the rest of the sector is not used *) ; ; This sector image is loaded and inspected at 0FA00H during the boot process crlf equ 0D0AH ; new line codes esc equ 1BH ; ascii esc bell equ 07H ; kbd bell bootsys: ld a,20h ld (curchr),a call print defb esc,'=',24h,20h defb 'XPRO System Monin exit or a ; trouble reading? jp nz,booterr ; tell crt LD A,(0F60AH) ; BYTE that determines if disk was init ld bc,(0F602H) ; where to load system image ld (dmaadr),bc ; ld bc,(0F604H) ; where to go after loading system push bc ; save for latter use ld bc,(0F606H) ; length of system in 128 byte sectors ld b,c ; reg B holds # of sectors to load LD A,(0F60AH) ; see if this disk configured for pro8 cp 0DCH ; config flag jr nz,noload ; nope use RAM values ld a,(0F608H) ; dri; nmi vector ret ; return from "halt", NMI sequence when in rom ; boot system, the first sector (1) of the first track (0) ; hold system boot information. It does NOT hold a short boot routine! ; the image is: ; self: jr self ; hang if booted and run ; defw loadpt ; where to load the opsys image ; defw bios ; where to go after booting system ; defw length ; length of image in 128 byte sectors ; 08 defb drvtyp ; type of drives being used ; ; MSB for drive A: 0=96tpi 1=48tpi ; ; LSB fotor Version 2.06 ',0 ld a,0 ld (dsk),a ld (kbdav),a ld a,ddbit ld (denflag),a call ready bootlp: ei ld a,11010100B out (cmnd),a halt call kbdstat or a jr z,autoboot ld a,ficmd out (cmnd),a call kbdin jp monitor autoboot: ld b,50 call thnsd ;***** Boot an 8 inch disk ************************************************ boot8: call diskinit ld a,3 ld (speed),a ld a,91h ld (trkflg),a ld a,10001000b ld (x8flag),a ld a,26 ld (cpmspt),a boot0: ld c  ld c,1 ; initial sector (0 was header sector) cb1: push bc ; save sector count and current sector call setsec ; select sector call read di ; read does EI upon exit pop bc or a jp nz,booterr ; bad read of sector ld hl,(dmaadr) ; update dma address for next sector ld de,128 ; new dma address add hl,de ld (dmaadr),hl dec b ret z ; done booting goto system inc c ; bump sector count ld a,(cpmspt) ; over sectors per track inc a cp c jr nz,cb1 ; fetch another sector k: ;double sided double track parameters defb 40,0 ;spt defb 05H ;bsh defb 1FH ;blm defb 03H ;exm defb 0C4H,0 ;dsm defb 5FH,0 ;drm defb 80H,0 ;al0,al1 defb 18H,0 ;cks defb 2,0 ;off sd8: ; single density 8" parameters defw 26 ; spt defb 3 ; bsh defb 7 ; blm defb 0 ; exm defw 242 ; dsm defw 63 ; drm defb 192 ; al0 defb 0 ; al1 defw 16 ; cks defw 2 ; off dd8: ; double density default parameters defw 64 ; spt defb 4 ; bsh defb 15 ;t equ 20H ; single density bit control equ 10H ; I/O port of disk controller status equ control+0 ; status register cmnd equ control+0 ; command register track equ control+1 ; track register sector equ control+2 ; sector register data equ control+3 ; data register ficmd equ 11010000B ; force interrupt (Abort current command) rdcmd equ 10001000B ; read command wrtcmd equ 10101100B ; write command seekcmd equ 00011000B ; seek command rstcmd equ 00000000B ; home (restore) command adrcmd equ 11000 defb 0 ; (exm) extent mask defw 82 ; (dsm) max logical block # defw 31 ; (drm) max directory # defb 80H ; (al0) directory allocation map defb 00H ; (al1) defw 8 ; (cks) size of directory check vector defw 3 ; (off) reserved tracks ;dpbd: ;( double density ); dddb: defw 40 ; (spt) sectors per track defb 3 ; (bsh) block shift factor defb 7 ; (blm) block mask defb 0 ; (exm) extent mask defw 194 ; (dsm) max logical block # defw 63 ; (drm) max directory # defb 0F0H ; (al ld a,(cpmspt) cp 39 ld c,16 ; first sector to read on next track ; for double density 5 1/4" jr z,do5b ld c,1 ; first sector for 8 single ; 8 double never gets to these tests do5b: push bc ; save counts ld bc,1 ; set for next track call settrk pop bc jr cb1 booterr:call print defw crlf, crlf defb '> Bad System Disk <',0 ei call kbdin jp monitor .comment % ############################################################### ##  blm defb 0 ; extent mask defw 299 ; dsm defw 127 ; drm defb 192 ; al0 defb 0 ; al1 defw 32 ; cks defw 2 ; off tbl8: db 1,7,13,19 ; sector translate table for 8" SD db 25,5,11,17 db 23,3,9,15 db 21,2,8,14 db 20,26,6,12 db 18,24,4,10 db 16,22 nop x8end: dsd8: ; double sided 8" double density dw 64 ; spt db 5 ; bsh db 31 ; blm db 1 ; exm dw 303 ; disksize - 1 dw 127 ; drm db 128 ; al0 db 0 ; al1 dw 32 ; cks dw 2 ; off nop ;*****100B ; read track address rdmask equ 10011100B ; read status mask wrtmask equ 11111100B ; write status mask tries1 equ 4 ; re-home on bad sector # of tries+1 tries2 equ 15 ; re-read/write # of retries+1 spdsafe equ 03h ; strip all but steprate bits from speed ; (just in case ). retcod equ 0C9H ; return op code nmivec equ 0066H ; non-maskable interupt vector ; (used in rd/wt loop) ; This section defines the disk parameters (dph's are images moved to RAM) dph0: defw 0,0,0,0 ; dph fo0) directory allocation map & BIOS space defb 00H ; (al1) defw 16 ; (cks) size of directory check vector defw 1 ; (off) reserved tracks ; sector interleave table ( single density ) ;tbl1: defb 1,6,11,16 defb 3,8,13,18 defb 5,10,15,2 defb 7,12,17,4 defb 9,14 ENDDPH: ddintrl: ; double sided disk parameters defb 40,0 ;spt defb 04H ;bsh defb 0FH ;blm defb 01H ;exm defb 0C4H,0 ;dsm defb 3FH,0 ;drm defb 0C0H,0 ;al0,al1 defb 10H,0 ;cks defb 1,0 ;off dtr ## ## Disk support routines (Deblocking) ## ## ## ############################################################### ## Last Update:12/28/83 DmC ## ############################################################### % .z80 bitport equ 01CH ; bit port (m80 does not support extrn bytes) drvmask equ 0DCH ; drive select mask ddbit equ 00H ; double density bit sdbir unit A: defw dirbuf,dpbd ; directory buffer, Disk Parameter Block defw csva, alva ; check sum pointer, allocation map pointer defb ddbit ; density flag for this drive defw 0,0,0,0 ; dph for unit B: defw dirbuf,dpbd ; directory buffer, Disk Parameter Block defw csvb, alvb ; check sum pointer, allocation map pointer defb ddbit ; density flag for this drive ;dpbs: ;( single density ); defw 18 ; (spt) sectors per track defb 3 ; (bsh) block shift factor defb 7 ; (blm) block mask   ************************************************ ;* Logical BIOS entry points * ;* Sector Deblocking Algorithms * ;***************************************************** blksiz equ 1024 ;CP/M allocation size hstsiz equ 512 ;host disk sector size hstspt equ 10 ;host disk sectors/trk hstblk equ hstsiz/128 ;CP/M sects/host buff ;cpmspt equ hstblk * hstspt ;CP/M sectors/track secmsk equ hstblk-1 ;sector mask secshf equ 2 ;log2(hstblk) sector mask wrall seksec) ;compute host sector or a ;carry = 0 rra ;shift right or a ;carry = 0 rra ;shift right ld (sekhst),a ;host sector to seek ; active host sector? ld hl,hstact ;host active flag ld a,(hl) ld (hl),1 ;always becomes 1 or a ;was it already? jp z,filhst ;fill host if not ; host buffer active, same as seek buffer? ld a,(sekdsk) ld hl,hstdsk ;same disk? cp (hl) ;sekdsk = hstdsk? jp nz,nomatch ; same disk, same track? ld hl,hsttrk call SEKCMP ;sektrk = hsttrkysical disk select (If needed to check den) setsec: ;set sector given by register c ld a,c ld (seksec),a ;sector to seek ;single secset ret setdma: ld (dmaadr),bc ;set dma address given by BC ret settrk: ld (sektrk),bc ;set track given by registers BC ;single trkst ret home: single dohome ; if single goto dohome ld a,(hstwrt) ; patch by DRI or a jp nz,homed ld (hstact),a homed: jp dohome ; go do home disk drive read: ;read the selected CP/M sector sinsk? jp nz,alloc ;skip if not ; disks are the same ld hl,unatrk call SEKCMP ;sektrk = unatrk? jp nz,alloc ;skip if not ; tracks are the same ld a,(seksec) ;same sector? ld hl,unasec cp (hl) ;seksec = unasec? jp nz,alloc ;skip if not ; match, move to next sector for future ref inc (hl) ;unasec = unasec+1 ld a,(cpmspt) ;end of track? cp (hl) ;count CP/M sectors jp nc,noovf ;skip if no overflow ; overflow to next track ld (hl),0 ;unasec = 0 ld hl,(unatrk) equ 0 ;write to allocated wrdir equ 1 ;write to directory wrual equ 2 ;write to unallocated ;trkflg is in scratch ram ; ram location for watching drive type ;xtrkflg watches external drive type single macro lbl ld a,(denflag) or a jp nz,lbl endm diskinit: ;enter here on system boot to initialize ld hl,ioimage ;move rd/wrt routines into RAM ld de,move ld bc,imaglen ldir ld hl,dph0 ; set dph's ld de,dpha ld bc,ENDDPH-DPH0 ldir xor a ;0 to accumulator ld (hstact? jp nz,nomatch ; same disk, same track, same buffer? ld a,(sekhst) ld hl,hstsec ;sekhst = hstsec? cp (hl) jp z,match ;skip if match nomatch: ;proper disk, but not correct sector ld a,(hstwrt) ;host written? or a call nz,writehst ;clear host buff filhst: ;may have to fill the host buffer ld a,(sekdsk) ld (hstdsk),a ld hl,(sektrk) ld (hsttrk),hl ld a,(sekhst) ld (hstsec),a ld a,(rsflag) ;need to read? or a call nz,readhst ;yes, if 1 xor a ;0 to accum ld (hgle xrd128 ;128 byte sector? xor a ; a patch by DRI ld (unacnt),a ld a,1 ld (readop),a ;read operation ld (rsflag),a ;must read data ld a,wrual ld (wrtype),a ;treat as unalloc jp rwoper ;to perform the read write: ;write the selected CP/M sector single xwrt128 ;128 byte sector? xor a ;0 to accumulator ld (readop),a ;not a read operation ld a,c ;write type in c ld (wrtype),a cp wrual ;write unallocated? jp nz,chkuna ;check for unalloc ; write to unallocated, set inc hl ld (unatrk),hl ;unatrk = unatrk+1 noovf: ;match found, mark as unnecessary read xor a ;0 to accumulator ld (rsflag),a ;rsflag = 0 jp rwoper ;to perform the write alloc: ;not an unallocated record, requires pre-read xor a ;0 to accum ld (unacnt),a ;unacnt = 0 inc a ;1 to accum ld (rsflag),a ;rsflag = 1 ;* Common code for READ and WRITE follows *; rwoper: ;enter here to perform the read/write xor a ;zero to accum ld (erflag),a ;no errors (yet) ld a,(),a ;host buffer inactive ld (unacnt),a ;clear unalloc count ld a,ddbit ;set double density flag ld (denflag),a ld a,255 ;set track numbers to 255 ld (dsk),a ;clear disk number ld (tracka),a ld (trackb),a ld (trackc),a ld (trackd),a ld hl,dphx ld de,dphc ld bc,xendx-dphx ldir ld hl,sd8 ; move 8" disk params into RAM ld de,x8sd ld bc,x8end-sd8 ldir ret seldsk: ;select disk ld a,c ;selected disk number ld (sekdsk),a ;seek disk number jp dsksel ;phparameters ld a,blksiz/128 ;next unalloc recs ld (unacnt),a ld a,(sekdsk) ;disk to seek ld (unadsk),a ;unadsk = sekdsk ld hl,(sektrk) ld (unatrk),hl ;unatrk = sectrk ld a,(seksec) ld (unasec),a ;unasec = seksec chkuna: ;check for write to unallocated sector ld a,(unacnt) ;any unalloc remain? or a jp z,alloc ;skip if not ; more unallocated records remain dec a ;unacnt = unacnt-1 ld (unacnt),a ld a,(sekdsk) ;same disk? ld hl,unadsk cp (hl) ;sekdsk = unad  stwrt),a ;no pending write match: ;copy data to or from buffer ld a,(seksec) ;mask buffer number and secmsk ;least signif bits ld l,a ;ready to shift ld h,0 ;double count add hl,hl ;shift left 7 add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl add hl,hl ; hl has relative host buffer address ld de,hstbuf add hl,de ;hl = host address ld de,(dmaadr) ;de = dma address ld bc,128 ;length ld a,(readop) ;which way? or a jr nz,rwmove ;skip if read ; write operationd de,9 ; move foward in dph to dpb pointer add hl,de ld de,dpbd ; double density dpb ld (hl),e inc hl ld (hl),d in a,(bitport) or 4 ; sets side select to one out (bitport),a ; call dcheck ; ld bc,0FH ; byte count ld de,dpbd ; ld hl,dddb ; ld a,0 ; jr nz,dend1 ; ld a,(dddd+2) ; cp 0AH ; jr c,dosing ; do single sided disk cp 14H ; 20 is added to double track sector #s jr c,dodub ; nope k4 format ld hl,dtrk ; pointer to double track parameters ld a,0F0H ;d a,c ; if two drive system do this routine cp 2 jr both do4: ld a,c ; do this if four drive cp 4 both: ret nc ; drive number > maximum drive or a ; zero flag set => A: drive else check for drive ld hl,dpha ; select proper dph for drive jr z,sel0 ld hl,dphb cp 1 jr z,sel0 ld hl,dphc cp 2 jr z,sel0 ld hl,dphd sel0: ld a,(dsk) ; selecting disk already selected? ld e,a ; save it for later in e reg cp c ; c contains the drive desired ret z ; yes, no further ald (cpmspt),a ld a,(sidflg) ; is address FE19 or a ; jr z,sel2a ; double density single side cp 0FFH ; means double track disk jr z,dblsid ; jump if K4 disk cp 0fh ; check for 8" double den jr z,d8dd cp 0dfh ; check for 8" double double jr z,dsd8d ld hl,dtrk ; double track parameter image jr sel2a ; and jump over next line dsd8d: ld hl,dsd8 jr d8dd1 d8dd: ld hl,dd8 d8dd1: ld a,63 ld (cpmspt),a jr sel2a dblsid: ld hl,ddintrl ; load k4 parameters (D, mark and switch direction ld a,1 ld (hstwrt),a ;hstwrt = 1 ex de,hl ;source/dest swap rwmove: call move ;move a logical sector to/from buffer ; data has been moved to/from host buffer ld a,(wrtype) ;write type cp wrdir ;to directory? ld a,(erflag) ;in case of errors ret nz ;no further processing ; clear host buffer for directory write or a ;errors? ret nz ;skip if so xor a ;0 to accum ld (hstwrt),a ;buffer written call writehst ld a,(erflag) ret ;* Utility su this is for dbl trk sidflg jr dend1 ; ready to do it dosing: ld a,0 ; for sidflg jr dend1 ; dodub: ld a,0FFH ; for sidflg (kay4 format) ld hl,ddintrl ; dend1: ldir selsid2: ld (sidflg),a ; in a,(bitport) ; and 0FBH ; out (bitport),a ; jp den1 ; ;*********** Single Density with 8" Routines ****************************** ;*********** Code added so can boot from 8" Single Density **************** dens: push hl ; (* single density *) hl^ to dph push de ;************ction needed ld a,c ; save new disk number ld (dsk),a push hl ; hl=dph of disk to be selected ld hl,comtrk ; is address FE17 ld a,e ; retrieve the disk we are leaving cp 3 ld de,trackd ; ld de with track of drive that we are jr z,sel1 ; leaving cp 2 ld de,trackc jr z,sel1 cp 1 ld de,trackb jr z,sel1 ld de,tracka sel1: ld a,(de) ; have we been on the disk we are "leaving" cp 255 ; if not do not update trackx jr z,selnot ; push bc ; ld bc,3 ; ldir ; pSDD single track) sel2a: ldir ; ld a,(comtrk) ; out (track),a ; pop hl ; ret ; sel2b: pop hl ; ld a,0 ; ld (denflag),a ; call ready ; call home ; call dcheck ; jr z,dend ; ld a,sdbit ; 20H ld (denflag),a ; call ready ; call dcheck ; ret nz ; jr dens ; dend: push hl ; (* double density *) hl^ to dph push de ld a,39 ld (cpmspt),a ld de,0 ; no xlate table (done by FORMAT program) ld (hl),e ; store table^ into dph inc hl ld (hl),d lbroutine for 16-bit compare *; SEKCMP: ;HL = .unatrk or .hsttrk, compare with sektrk ex de,hl ld hl,sektrk ld a,(de) ;low byte compare cp (hl) ;same? ret nz ;return if not ; low bytes equal, test high 1s inc de inc hl ld a,(de) cp (hl) ;sets flags ret ; select disk drive, C=drive number 0=A:, 1=B:, 2=C:, 3=D: ; return HL=dph for selected drive, or HL=0 for non-existent drive dsksel: ld hl,0 ; hl = 0 for non-existent drive ld a,(trkflg) bit 4,a jr nz,do4 lop bc ; ld de,comtrk ; selnot: ld a,c ; c still has the drive # we want to select cp 3 ; ld hl,trackd ; jr z,sel2 ; cp 2 ; ld hl,trackc ; jr z,sel2 ; cp 1 ; ld hl,trackb ; jr z,sel2 ; ld hl,tracka ; sel2: ld a,(hl) ; cp 255 ; if 255 drive has not yet been selected jr z,sel2b ; there is more work to do ld bc,3 ; moves track? to comtrk ldir ; ld bc,0fH ; length of dp header ld de,dpbd ; is address FEAA ld hl,dddb ; is address 0165 ld a,39   ****** Determine Whether or Not 8" *************************** ld a,(x8flag) ld d,a ld a,(dsk) cp 3 jr z,chkd cp 2 jr z,chkc cp 1 jr z,chkb chka: bit 3,d jr nz,den8 jr den5 chkb: bit 2,d jr nz,den8 jr den5 chkc: bit 1,d jr nz,den8 jr den5 chkd: bit 0,d jr nz,den8 ;*************** 5 inch Single Density ************************************ den5: ld de,tbl1 ; single density sector xlate table ld (hl),e ; store table^ into dph inc hl ld (hl),d ld de,9 ; mdrive was C: the zero flag will ; still be set from test above so will call jr commie ; the correct routine in commie doa: rla ; check bit 7 jr c,trkst4 ; is 40 track drive so don't dbl step ydoit: ld a,c ; track wanted is in C ld (comtrk),a ; so we needn't worry later push bc ; +will mess with these so save the enviro in a,(track) ; +get the track register ld b,a ; +into b for safe keeping cp c ; +track wanted > track reg jr c,swptrk ; +if so do other routine sub c ; d11 ld a,0dfh ; double sided sidflg ld hl,dsd8 ; double sided params jp dend1 dend11: ld a,0fh ; single sided disk ld hl,dd8 jp dend1 ;************** 8 inch Single Density ************************************* xdens: ld a,sdbit ld (denflag),a ld de,x8tbl ld (hl),e inc hl ld (hl),d ld de,9 add hl,de ld de,x8sd ;single density dpb ld (hl),e inc hl ld (hl),d ld a,0 jp selsid2 den1: ld hl,comtrk ; ld a,(dsk) ; cp 3 ld de,trackd jr z,den2 cp 2 ldmask to select side 1 sid0 equ 00h ; select side 0 trkst: call ready ; make sure drive is on and ready ld b,sid0 ld a,(sidflg) ; or a ; jr z,trkst2 ; cp 0fh ; 8" single sided jr z,trkst2 trkfix: ld a,c ; move track number to A rra ; ld c,a ; jr nc,trkst2 ; select side 0 if no carry ld b,sid1 trkst2: in a,(bitport) and sidmsk or b out (bitport),a ; trkst3: ld a,(sidflg) ; cp 0F0H ; see if dbl track disk jr z,trkst4 ; is dbl track so don't adjust tracks ld a,ove foward in dph to dpb pointer add hl,de ld de,dpbs ; single density dpb ld (hl),e inc hl ld (hl),d ld a,0 jr selsid2 den8: ; 8 inch density select routines call inone ; step to track one to see if this is ld a,0 ; a double density disk ! ld (denflag),a call ready call dcheck push af ; save 0 flag call outone ; back to track 0 pop af ; restore 0 flag jr nz,xdens ; must be single density couldn't read ;*********************************************************+otherwise track reg - track wanted add a,b ; +so controller will think it is ; +farther away than it is out (track),a ; +give track to controller ld a,c ; +track wanted to A comon: out (data),a ; +track wanted to controller ld a,seekcmd ; seek command ; no need for speed set since this ; is 96tpi for sure out (cmnd),a ; issue command call busy ; test and wait for not busy ld a,c ; +track number we really wanted out (track),a ; +fix the track register pop bc ; +restor de,trackc jr z,den2 cp 1 ld de,trackb jr z,den2 ld de,tracka ; den2: push bc ; ld bc,3 ; ldir ; pop bc ; pop de ; pop hl ; ret ; dcheck: push hl ; push bc ; ld hl,dddd ; going to trash this part of scratch RAM ld bc,0613H ; 6 bytes through port 13 ld a,adrcmd ; read track address to dddd di out (cmnd),a ; this is how we see if we can read this disk dchk: halt ; ini ; jr nz,dchk ; call busy ; wait for command done bit 4,a ; record not found(dsk) ; see which drive is selected cp 2 ; see if AorB or CorD jr nc,CorD ; ; AorB: or a ; sets 0 flag if a drive ; ld a,(trkflg) ; byte in memory that keeps track of drive ; type ( 40 or 80 track) bit 7 is one if ; A: is 40 trk bit 0 is set if B: is 40 trk commie: jr z,doa ; drive a is selected jump to its routine rra ; see if bit 0 is set jr c,trkst4 ; is 40 track drive so don't dbl step jr ydoit ; jump over routine for drive a CorD: ld a,(xtrkflg) ; if the ***************** xdend: ; double density 8 inch ld a,63 ld (cpmspt),a ld de,0 ;xtbl8 ; no translate table ld (hl),e inc hl ld (hl),d ld de,9 add hl,de ld de,dpbd ld (hl),e inc hl ld (hl),d ;***************** Now check for Single or Double Sided ******************* in a,(bitport) or 4 out (bitport),a call dcheck ld bc,0fh jr nz,dend11 ; couldn't read so must be single sided ld a,(dddd+2) cp 17 jr c,dend11 ; fooler stay with single side cp 33 jr nc,den flag pop bc ; pop hl ; ret ; return status ;************* home disk head ******************************************** dohome: call ready ; make sure drive is on and ready in a,(bitport) ; and 0FBH ; out (bitport),a ; xor a ; ld (comtrk),a ; push bc call setspd ld a,08 ; restore command or b out (cmnd),a ; issue command pop bc jp busy ; test and wait for not busy ; seek track #, BC=Track # sidmsk equ 11111011b ; mask to Strip side bits sid1 equ 00000100b ;   e the enviroment ret ; +as if nothing happened swptrk: ld a,c ; +track wanted > track reg so put in A sub b ; +subtract the track register add a,c ; +add to track wanted jr comon ; +the rest of the routine is the same trkst4: push bc call setspd ; get speed mask (is in b on ret) ld a,b ; save it in a pop bc ; get track back ld b,a ; load mask back into b ld a,c ; get track to seek to ld (comtrk),a ; save for system out (data),a ; give it to the controller ld a,seekcm** 8 inch read and write bullet proofing ** ;************************************************************************** xwrt128: ; write a 128 byte sector ld e,0fh ; retry count ld a,(ramtry) ld d,a xwrths: push de call xhstco call wrt128 pop de ret z dec e jr nz,xwrths dec d ret z call dohome ld e,tries2 jr xwrths xrd128: ld e,0fh ld a,(ramtry) ld d,a xrdhst: push de call xhstco call rd128 pop de ret z dec e jr nz,xrdh a,(sidflg) cp 0fh jr z,sec8 cp 0dfh jr z,sec8 sec2: in a,(bitport) ; see what side we are on! bit 2,a ; ld a,c ; move sector number to A jr z,sec1 ; ld a,(sidflg) ; cp 0F0H ; ld a,c ; jr nz,seca ; add a,0AH ; seca: add a,0AH ; sec1: out (sector),a ; ret sec8: inc c ; we will start with sector 1 for 8" ld a,(sidflg) cp 0dfh ld a,c jr nz,sec1 in a,(bitport) bit 2,a ld a,c jr z,sec1 ; no bias on side 0 add a,16 jr sec1 ; perform logical to de pop hl ret ; turn disk motor on, delay for drive speed diskon: in a,(bitport) ; get current drive motor status bit 6,a ; is motor on? ret z ; motor on, do nothing res 6,a ; motor on bit out (bitport),a ; turn motor on ld b,50 ; delay call thnsd ret ; turn disk motor off diskoff:in a,(bitport) set 6,a ; motor off bit out (bitport),a ret ; delay for B th's @ 4Mhz thnsd: ld de,1670 tlp: dec de ld a,d or e jp nz,tlp djnz thnsd ret ; check status of controd ; seek track command or b ; or with speed mask out (cmnd),a ; give it to the controller jp busy ; wait for command to complete ;************************************************************************** ;*** Set speed routine. Find drive selected and look at x8flag to see if ** ;*** slow steprate is necessary. Load mask into B if so otherwise 0 in B ** ;************************************************************************** setspd: ld b,0 ld a,(dsk) or a jr z,achck dec a jr zst dec d ret z call dohome ld e,tries2 jr xrdhst xhstco: ld a,(sekdsk) ld c,a call dsksel ld bc,(sektrk) call trkst ld a,(seksec) ld c,a call secset ret ;******* 5 1/4 ***************************************; ;* WRITEHST performs the physical write to *; ;* the host disk, READHST reads the physical *; ;* disk. *; ; ;hstdsk = host disk #, hsttrk = host track #, ;hstsec = host sect #. write "hstsiz" bytes ;from hstbuf and return error flag in erflag. physical sector translation. ; logical sector number in BC, table address in DE ; return physical sector number in HL sectran:ld a,d ; table address 0? or e ld h,b ; if so no xlate ld l,c ret z ex de,hl ; table address in hl add hl,bc ; index by logical sector number ld l,(hl) ld h,0 ret ; ready disk drive, perform physical disk select, set density bit ready: push hl ; save hl push de ; and de push bc ld a,ficmd ; abort any controller action out (cmnd),a call disller, wait for command to finish executing busy: di halt ; wait for command done bsy: in a,(status) ; now wait for not busy bit 0,a jr nz,bsy ei ret outone: ; step out one track ld a,01101010b ; step out no verify no update out (cmnd),a jr busy inone: ld a,01001010b ; step in one track no verify no out (cmnd),a ; update jr busy subttl Writehst and Readhst logical to Physical routines page ;************************************************************************** ;,bchck dec a jr z,cchck dchck: ld a,(x8flag) bit 4,a ret z jr slow cchck: ld a,(x8flag) bit 5,a ret z jr slow bchck: ld a,(x8flag) bit 6,a ret z jr slow achck: ld a,(x8flag) bit 7,a ret z slow: ld a,(speed) and spdsafe ; make sure nothing weird happens ld b,a ret ;************************************************************************** ; ; select sector #, BC=Sector # ; ;************************************************************************** secset: ldkon ; turn drive motor on ld a,(dsk) ; A=drive # cp 3 ; if 3 = 11b so don't futz (D: = 11b) jr z,outdrv cp 2 ; C: drive jr nz,arb ; if not C: jump to A<->B routine ld a,00h ; C: is 00b jr outdrv ; arb: inc a ; bump a A:=01b B:=10b outdrv: ld e,a ; save drive # in E in a,(bitport) ; A=bit port and 0DCH ; strip current drive bits or e ; or in requested drive ld hl,denflag ; hl^ to density bit for this drive or (hl) out (bitport),a ; to bit port pop bc pop   ;return erflag non-zero if error ; writehst: ld e,0FH ;retries on error ld a,(ramtry) ld d,a wrthst: push de ;save error count call hstcom ; set track and sector call wrt512 ; FEF8 ld (erflag),a ; error return flag pop de ; restore error flags ret z ; good op dec e ; retry count jr nz,wrthst ; try again dec d ; home and reseek count ret z ; can't recover call dohome ; re seek ld e,tries2 ; reset retry count jr wrthst readhst:;hstdsk = host disk #, hsttrk =subttl XproIO *** I/O Drive and Initialize *** page .COMMENT% ############################################################### ## System device I/O routines for KBD, TTY and LST ## ## ## ############################################################### % .z80 ;*************** ;* sio equates * ;*************** sio equ 04H ; base address of sio sioa0 equ sio+2 ; channel a command/status sioa1 equ sio+0 ; channel a data siob0 edress of operation ld b,1 ; read a 128 byte sector jr rd ;rd512: ld hl,hstbuf ld b,4 ; read a 512 byte sector ; read a sector, return A=0 for no errors, A=1 for non-recoverable error ; if b=1 128, b=2 256, b=3 384, b=4 512 bytes/sector rd: ld de,rdmask*256+rdcmd ; d=read status mask, e=read command jr action ;wrt128: ld hl,(dmaadr) ld b,1 ; write a 128 byte sector jr wrt ;wrt512: ld hl,hstbuf ld b,4 ; write a 512 byte sector ; write a sector, return as per read wrt: ld de ; read loop done, exit wstart: out (cmnd),a ; write loop pop af jr z,wl2 wl1: halt outi jr nz,wl1 wl2: halt outi jr nz,wl2 done: ex af,af' ; byte at nmi vector address ld (nmivec),a ; restore it in a,(bitport) ; turn rom back on set 7,a out (bitport),a ; ei ; turn interrupts on call busy ; get status when contoller not busy and d ; status mask ret z ; no bit set, return operation ok ld a,1 ; cp/m error return ret imaglen equ $-ioimage ; length of th host track #, ;hstsec = host sect #. read "hstsiz" bytes ;into hstbuf and return error flag in erflag. ld e,0FH ; retry error counts ld a,(ramtry) ld d,a rdhst: push de ; save error counts call hstcom ; set track and sector call rd512 ; read sector ld (erflag),a ; error return flag pop de ; restore error flags ret z ; good op dec e ; retry count jr nz,rdhst ; try again dec d ; home and reseek count ret z ; can't recover call dohome ; re seek ld e,tries2 ; reset requ sio+3 ; channel b command/status siob1 equ sio+1 ; channel b data ; write registers 0-7 and control bits ; init registers in the following order 0,2,4,3,5,1 WR0 equ 0 ; command register, crc reset, reg pointer ; bits 0-2 are register pointers to WRx and RRx ; bits 3-5 and commands as given bellow null equ 0 ; null command extrset equ 10H ; reset ext/status interrupts reset equ 18H ; channel reset ienrc equ 20H ; Enable Int on Next Rx Character rtip equ 21H ; reset transmitter interrupt pen,wrtmask*256+wrtcmd ; d=status mask, e=write command ;fall through to action action: call ready ; make sure drive is on and ready di ; no interrupts during disk I/O ; operations in a,(bitport) ; turn rom off res 7,a out (bitport),a push hl ; save address of disk buffer ld hl,nmivec ; set up nmi vector ld a,(hl) ; save current contents ex af,af' ld (hl),retcod ; this is a return after HALT in loop pop hl ; hl = dma address ld a,b ; sector multiple ld bc,128*is image try count jr rdhst hstcom: ld a,(hstdsk) ; select disk ld c,a call dsksel ld bc,(hsttrk) ; set track to hsttrk call trkst ; physical seek ld a,(hstsec) ; set physical sector ld c,a ; c=sector call secset ret ioimage: ;move: ; block memory move, turn rom on/off in a,(bitport) ; turn rom off res 7,a out (bitport),a ldir ; move logical sector from hstbuf in a,(bitport) ; turn rom back on set 7,a out (bitport),a ret ; back to rom ;rd128: ld hl,(dmaadr) ; ad256+data ; b=sector length, c=data port bit 0,a ; if 0 then 256 or 512 bytes/sector jr nz,actn ; b set for 128 or 384 bytes/sector ld b,0 ; b set for 256 or 512 bytes/sector actn: cp 1 ; compute entry point 1st or 2nd loop push af ; save as Z flag ld a,e ; i/o command cp wrtcmd ; a write? jr z,wstart ; start write command out (cmnd),a ; fall through to read loop pop af jr z,rl2 rl1: halt ; wait for controller ini jr nz,rl1 rl2: halt ini jr nz,rl2 jr done   ding errset equ 30H ; error reset retint equ 31H ; return from interrupt WR1 equ 1H ; interrupt enable and Wait/Ready modes esie equ 1H ; external/status interrupt enable tie equ 2H ; transmitter interrupt enable tid equ 0 ; transmitter interrupt disable statav equ 4H ; Status affects vector (z80 mode 2) (see WR2) ; bits 3-4 affect receive interrupt mode rid equ 0 ; receive interrupts disabled rifc equ 8H ; receive interrupt on first char only riep equ 10H ; recv interrupts enabled, parity err hghlow equ 20H ; high/low ) mode 3 only andor equ 40H ; and/or of bits to gen interrupt ) intena equ 80H ; enable interrupt (bit low disable interrupts) intcmd equ 03H ; set interrupt enable/disable without changing status as sicw ;*************** ;* ctc equates * ;*************** ctc equ 18H ; ctc base address ctc0 equ ctc+0 ; ctc channel 0 ctc1 equ ctc+1 ; ctc channel 1 ctc2 equ ctc+2 ; ctc channel 2 ctc3 equ ctc+3 ; ctc channel 3 ; channel control register bits ctccmd equ 01H ; ctate = parity odd ; bits 2-3 are number of stop bits syncmd equ 0 ; sync mode is to be selected sbits1 equ 4 ; 1 stop bit sbits5 equ 8H ; 1.5 stop bits sbits2 equ 0CH ; 2 stop bits ; bits 6-7 control clock rate cr1 equ 0 ; data rate x1=clock rate cr16 equ 40H ; x16 cr32 equ 80H ; x32 cr64 equ 0CH ; x64 WR5 equ 5 ; control bits that affect xmt te equ 8H ; transmit enable break equ 10H ; send break ; bits 5-6 are number of bits/character to transmit tbits5 equ 0  piobc equ pio+3 ; pio b control piobd equ pio+2 ; pio b data spio equ 01CH ; base address of pio (system status bits port) spioac equ spio+1 ; pio a control spioad equ spio+0 ; pio a data spiobc equ spio+3 ; pio b control spiobd equ spio+2 ; pio b data bitport equ spioad ; system bit port for status and control ;0 drive sel A: ;1 drive sel B: ;2 side select ;3 keyboard data available sense ;4 bell for keyboard ;5 single density (not 5 is double density) ;6 drive motor off (not 6 is motorSpecial Recv Cond rie equ 18H ; same as riep but parity error not Special Recv Cond WR2 equ 2 ; interrupt vector address/pointer (chan b only) ; interrupt address (z80 reg I+WR2=interrupt address) ; returned as is if not statav above in wr1 ; if statav then bits 1-3 are modified as bellow: ; 000 ch b transmit buffer empty ; 001 ch b external/status change ; 010 ch b receive char available ; 011 ch b special receive condition (parity error, Rx overrun, ; framing error, end of frame(sdlc) ) ; 1tc command byte ctcint equ 80H ; interrupt enable ctcm1 equ 40H ; set ctc mode is counter ctcm0 equ 00H ; set ctc mode is timer range equ 20H ; timer prescaler factor is 256 (not range is 16) slope equ 10H ; edge triger positive (not slope is negative edge) trigger equ 8H ; ext trigger ltc equ 4H ; load time constant (followed by time constant) rsetctc equ 2H ; reset channel ctcivec equ 0 ; set ctc interrupt vector, bits 3-7 are vector addr ctcvmsk equ 0F8H ; interrupt vector mask to strip bits 0-; 5 or less bits/character tbits7 equ 20H ; 7 bits/character tbits6 equ 40H ; 6 bits/character tbits8 equ 60H ; 8 bits/character rts equ 2 ; RTS output dtr equ 80H ; DTR output WR6 equ 6 ; sdlc transmit sync character WR7 equ 7 ; sdlc receive sync character ; read registers 0-2 and status bits rr0 equ 0 ; general recv and xmt status rca equ 1 ; receive character available intped equ 2 ; interrupt pending (ch a only) tbe equ 4 ; transmit buffer empty synhnt equ 10H ; sync/hunt dcd equ 8H ;  on) ;7 rom enable (not 7 is rom off) ; control register setiv equ 0 ; set interrupt vector, bits 1-7 are vector address som equ 0FH ; set operating mode. bits 6-7 specify mode mode0 equ 0 ; output mode1 equ 40H ; input mode2 equ 80H ; bidirectional mode3 equ 0C0H ; control(bit by bit i/o,mode3 command is followed by ; byte where bit pattern specifies i/o bits ; 1=input, 0=output sicw equ 7H ; set interrupt control word, bits 4-7 are parameters imask equ 10H ; bit mask follows ) xx ch a (* same vectors as for channel b above *) WR3 equ 3 ; receiver logic control and parameters re equ 1 ; receiver enable autoe equ 20H ; auto enable (use dcd and cts to enable recv and xmt ; bits 6-7 are receiver bits/character rbits5 equ 0 ; 5 bits/character rbits7 equ 40H ; 7 bits/character rbits6 equ 80H ; 6 bits/character rbits8 equ 0C0H ; 8 bits/character WR4 equ 4 ; control bits that affect both xmt and recv pon equ 1 ; enable parity (parity on) pstate equ 2 ; parity even not psDCD input cts equ 20H ; CTS input xmtundr equ 40H ; transmit underrun/ EOM brk equ 80H ; break/abort status rr1 equ 1 ; Special Receive conditions and Residue codes ; bits 4-7 are special receive conditions rpe equ 10H ; parity error rovr equ 20H ; Rx overrun error framerr equ 40H ; framing error rr2 equ 2 ; interrupt vector address/pointer ;*************** ;* pio equates * ;*************** pio equ 08H ; base address of pio pioac equ pio+1 ; pio a control pioad equ pio+0 ; pio a data   2 ;*************** ;* baud rate * ;*************** bauda equ 00H ; baud rate generator for serial chan a baudb equ 0CH ; baud rate generator for serial chan b ; baud rate factors, output to baudx to select baud rate baud10 equ 02H ; 110 baud rate baud30 equ 05H ; 300 baud rate baud12 equ 07H ; 1200 baud rate baud24 equ 0AH ; 2400 baud rate baud48 equ 0CH ; 4800 baud rate baud96 equ 0EH ; 9600 baud rate baud19k equ 0FH ; 19.2k baud rate subttl I/O configuration tables page iotabint: subttl XproRAM *** Scratch Ram Allocation *** page .comment% ############################################################### ## ## ## System scratch RAM used by ROM software ## ## ## ############################################################### % .z80 ramscratch equ 0FC00H ; scratch ram sekdsk equ ramscratch ;seek disk number sektrk equ sekdsk+1 ;seek track number seksec equ sektrk+2 ;seek sector number hstdsk equ seksec+1 ;host disk number hsttrk equ hstdsk+l bits defb spioac, intcmd ; disable interrupts defb spioad, 10000001B ; set system status bits ; (before setting mode!) defb spioac, som or mode3 ; set mode to #3 defb spioac, 00001000B ; bit pattern for mode 3 ; bit 3 is only input (kbd dav) ;init pio used for keyboard ;defb spiobc, intcmd defb spiobc, som or mode1 ; set keyboard port as input defb spiobc, 1ah ; interupt vector defb spiobc, intcmd or intena ; enable interupts ; init pio used to drive printer defb pioacr is ready ret ; 0=no char kbdin: call kbdstat ; loop till char avail or a jr z,kbdin ld a,0 ld (kbdav),a ld a,(kbdchr) ret kbdout: ret ttystat:in a,(sioa0) ; serial port status input and rca JR COMOUT ttyin: call ttystat ; is a char ready? jr z,ttyin in a,(sioa1) ret ttyout: in a,(sioa0) ; output a char to serial port and tbe jr z,ttyout ; xmit buffer full? ld a,c out (sioa1),a ; xmit character ret TTYOSTAT: ;TEST STATUS OF SERIAL OUTPUT IN A,(; i/o device initialization table ; first byte is port # ; second byte is byte to send to port defb (iotblend-iotabint)/2 ; table length in arguments ; init sio channel b defb siob0, reset ; reset sio channel defb baudb, baud30 ; 300 baud defb siob0, wr4 defb siob0, sbits1 or cr16 ; one stop bit, 16x clock defb siob0, wr3 defb siob0, re or rbits8 ; recv enable, 8 bits/char defb siob0, wr5 defb siob0, te or tbits8 or dtr ; xmt enable, 8bits/char, assert dtr defb siob0, wr1 defb s1 ;host track number hstsec equ hsttrk+2 ;host sector number sekhst equ hstsec+1 ;seek shr secshf hstact equ sekhst+1 ;host active flag hstwrt equ hstact+1 ;host written flag unacnt equ hstwrt+1 ;unalloc rec cnt unadsk equ unacnt+1 ;last unalloc disk unatrk equ unadsk+1 ;last unalloc track unasec equ unatrk+2 ;last unalloc sector erflag equ unasec+1 ;error reporting rsflag equ erflag+1 ;read sector flag readop equ rsflag+1 ;1 if read operation wrtype equ readop+1 ;write operation type dmaadr eq, intcmd ; disable interrupts defb pioac, som or mode0 ; set mode to #0 (output) defb piobc, intcmd ; disable interrupts defb piobc, som or mode1 ; set mode to #1 (input) ; init CTC (no interrupts for now) defb ctc, ctccmd iotblend: ; end of table keysrv equ 0FA40h devinit:ld hl,iotabint ; initialize i/o devices ld b,(hl) ; number of bytes to send to i/o devices iolp: inc hl ld c,(hl) ; port to send inc hl ld a,(hl) ; byte to send out (c),a djnz iolp in a,(spiobSIOA0) AND TBE ;TX BUF FULL ? COMOUT: ret z ; 0=busy ld a,0FFH ; FF=ready ret list: ret liststat: ld a,0ffh ret iob0, tid or rid ; xmt & recv interrupts disabled ; init sio channel a defb sioa0, reset ; reset sio channel defb bauda, baud30 ; 300 baud defb sioa0, wr4 defb sioa0, sbits1 or cr16 ; one stop bit, 16x clock defb sioa0, wr3 defb sioa0, re or rbits8 or autoe ; recv enable, 8 bits/char, auto enable defb sioa0, wr5 defb sioa0, te or tbits8 or dtr ; xmt enable, 8bits/char, assert dtr defb sioa0, wr1 defb sioa0, tid or rid ; xmt & recv interrupts disabled ; init pio used form system controd) ; get garbage character from keybd PIO ld hl,keysrv ld (0fa1ah),hl ex de,hl ld hl,ksrv ld bc,kend-ksrv ldir ld a,0fah ld i,a im 2 ret ; done ksrv: push af in a,(1eh) cpl ld (kbdchr),a ld (kbdav),a pop af ei reti kend: nop subttl Device I/O handlers page ;conin: ld a,(ioflag) ; or a ; jr z,kbdin ; jp ttyin ; ;conout: ld a,(ioflag) ; or a ; jr z,kbdstat ; jp tty kbdstat: ld a,(kbdav) or a ret z ld a,0FFH ; the ready goes low when characte  u wrtype+1 ;last dma address hstbuf equ dmaadr+2 ;host buffer ;**** Track and disk type variables ************************************* dsk equ hstbuf+512 ; current disk drive comtrk equ dsk+1 denflag equ comtrk+1 ; density flag for current drive sidflg equ denflag+1 tracka equ sidflg+1 ; track of disk A (255=density unknown) trackb equ tracka+3 ; track of disk B trackc equ trackb+3 ; track of disk C trackd equ trackc+3 ; track of disk D ;**** Drive type variables ************************ sektrk equ sekdsk+1 ;seek track number FC03 seksec equ sektrk+2 ;seek sector number FC04 hstdsk equ seksec+1 ;host disk number FC05 hsttrk equ hstdsk+1 ;host track number FC07 hstsec equ hsttrk+2 ;host sector number FC08 sekhst equ hstsec+1 ;seek shr secshf FC09 hstact equ sekhst+1 ;host active flag FC0A rd512+10 ; routine to write 128 byte sector wrt512 equ wrt128+7 ; routine to wrtie 512 byte sector rdwrtend equ rd128+140 ; end of read and write routines dirbuf equ rdwrtend+1 ; bdos directory buffer hereis equ dirbuf+128 ; end of scratch stack equ 0FFFFH ; boot up stack space ;************************************************************************** ;** Extra scratch ram section ;************************************************************************** ramx equ 0FA80H csva equ ramx  MACRO-80 3.44 09-Dec-81 PAGE 1 XproRAM *** Scratch Ram Allocation *** subttl XproRAM *** Scratch Ram Allocation *** page MACRO-80 3.44 09-Dec-81 PAGE 1-1 XproRAM *** Scratch Ram Allocation *** .comment% ############################################################### ## ## ********************* trkflg equ trackd+3 ; keeps track of A and B drive types xtrkflg equ trkflg+1 ; keeps track of C and D drive types x8flag equ xtrkflg+1 ; 8 inch and use slow step rate desig speed equ x8flag+1 ; slow step rate to use cpmspt equ speed+1 ;**** video scratch ram *************************************************** cursor equ cpmspt+1 chrsav equ cursor+2 curchr equ chrsav+1 base equ curchr+1 leadin equ base+1 ; video leadin sequence count CRTFLG EQU leadin+1 ; mode bits ( hstwrt equ hstact+1 ;host written flag FC0B unacnt equ hstwrt+1 ;unalloc rec cnt FC0C unadsk equ unacnt+1 ;last unalloc disk FC0D unatrk equ unadsk+1 ;last unalloc track FC0F unasec equ unatrk+2 ;last unalloc sector FC10 erflag equ unasec+1 ;error reporting FC11 rsflag equ erflag+1 ;read sector flag FC12 re alva equ csva+32 csvb equ alva+38 alvb equ csvb+32 csvc equ alvb+38 alvc equ csvc+32 csvd equ alvc+38 alvd equ csvd+32 dphc equ alvd+38 dphd equ dphc+17 x8sd equ dphd+17 x8dd equ x8sd+15 x8tbl equ x8dd+15 ramtry equ x8tbl+27 IOFLAG equ ramtry+1 kbdav equ ioflag+1 kbdchr equ kbdav+1 thatsit equ kbdchr+1 ch ram section ;************************************************************************** ramx equ 0FA80H csva equ ramx  ## System scratch RAM used by ROM software ## ## ## ############################################################### % .z80 FC00 ramscratch equ 0FC00H ; scratch ram FC00 sekdsk equ ramscratch ;seek disk number FC01 only bit 0 is currently used) ;************************************************************************** dpha equ crtflg+1 ; DPH for A: dphb equ dpha+17 ; DPH for B: dpbs equ dphb+17 ; single density dpb dpbd equ dpbs+15 ; double density dpb tbl1 equ dpbd+15 ; single density skew table dddd equ tbl1+18 ; double sided dpb move equ dddd+6 ; move logical sector from hstbuf rd128 equ move+15 ; routine to read 128 byte sector rd512 equ rd128+7 ; routine to read 512 byte sector wrt128 equ   adop equ rsflag+1 ;1 if read operation FC13 wrtype equ readop+1 ;write operation type FC14 dmaadr equ wrtype+1 ;last dma address FC16 hstbuf equ dmaadr+2 ;host buffer ;**** Track and disk type variables ************************************* FE16 dsk equ hstbuf+512 ; current disk drive FE17  equ ramx FAA0 alva equ csva+32 FAC6 csvb equ alva+38 FAE6 alvb equ csvb+32 FB0C csvc equ alvb+38 FB2C alvc equ csvc+32 FB52 csvd equ alvc+38 FB72 alvd equ csvd+32 FB98 dphc equ alvd+38 FBA9 dphd equ dphc+17 FBBA x8sd equ dphd+17  cpmspt equ speed+1 ;**** video scratch ram *************************************************** FE2B cursor equ cpmspt+1 FE2D chrsav equ cursor+2 MACRO-80 3.44 09-Dec-81 PAGE 1-2 XproRAM *** Scratch Ram Allocation *** FE2E curchr equ chrsav+1 FE2F base equ curchr+1 FE30  FEAA wrt128 equ rd512+10 ; routine to write 128 byte sector FEB1 wrt512 equ wrt128+7 ; routine to wrtie 512 byte sector FF25 rdwrtend equ rd128+140 ; end of read and write routines FF26 dirbuf equ rdwrtend+1 ; bdos directory buffer FFA6 hereis equ dirbuf+128 ; end of scratch FFFF stack equ 0FFFFH ; boot up stack space  comtrk equ dsk+1 FE18 denflag equ comtrk+1 ; density flag for current drive FE19 sidflg equ denflag+1 FE1A tracka equ sidflg+1 ; track of disk A (255=density unknown) FE1D trackb equ tracka+3 ; track of disk B FE20 trackc equ trackb+3 ; track of disk C FE23 trackd equ trackc+3 ; track of disk D  FBC9 x8dd equ x8sd+15 FBD8 x8tbl equ x8dd+15 FBF3 ramtry equ x8tbl+27 FBF4 IOFLAG equ ramtry+1 FBF5 kbdav equ ioflag+1 FBF6 kbdchr equ kbdav+1 FBF7 thatsit equ kbdchr+1 MACRO-80 3.44 09-Dec-81 PAGE S XproRAM *** Scratch Ram Allocation ***  leadin equ base+1 ; video leadin sequence count FE31 CRTFLG EQU leadin+1 ; mode bits (only bit 0 is currently used) ;************************************************************************** FE32 dpha equ crtflg+1 ; DPH for A: FE43 dphb equ dpha+17 ; DPH for B: FE54 dpbs e ;************************************************************************** ;** Extra scratch ram section ;************************************************************************** FA80 ramx equ 0FA80H FA80 csva ;**** Drive type variables ********************************************* FE26 trkflg equ trackd+3 ; keeps track of A and B drive types FE27 xtrkflg equ trkflg+1 ; keeps track of C and D drive types FE28 x8flag equ xtrkflg+1 ; 8 inch and use slow step rate desig FE29 speed equ x8flag+1 ; slow step rate to use FE2A qu dphb+17 ; single density dpb FE63 dpbd equ dpbs+15 ; double density dpb FE72 tbl1 equ dpbd+15 ; single density skew table FE84 dddd equ tbl1+18 ; double sided dpb FE8A move equ dddd+6 ; move logical sector from hstbuf FE99 rd128 equ move+15 ; routine to read 128 byte sector FEA0 rd512 equ rd128+7 ; routine to read 512 byte sector   Macros: Symbols: FAA0 ALVA FAE6 ALVB FB2C ALVC FB72 ALVD FE2F BASE FE2D CHRSAV FE17 COMTRK FE2A CPMSPT FE31 CRTFLG FA80 CSVA FAC6 CSVB FB0C CSVC FB52 CSVD FE2E CURCHR FE2B CURSOR FE84 DDDD FE18 DENFLAG FF26 DIRBUF FC14 DMAADR FE63 DPBD FE54 DPBS FE32 DPHA tor by Russell Smith 2-August-1980 * ;* NLS Kaypro Resident Software System * ;* * ;* * ;************************************************************************** ; ; ASEG .Z80 ORG 0000H CRTMEM EQU 3000H ; BASE OF 4K CRT MEMORY SCROLL EQU 14H ; scroll register ;**** Disk and boot routines ********************************************** INCLUDE XPRODISK.MAC ;**** I/O Device routines ****************** FC13 WRTYPE FBC9 X8DD FE28 X8FLAG FBBA X8SD FBD8 X8TBL FE27 XTRKFLG No Fatal error(s)  FE29 SPEED FFFF STACK FE72 TBL1 FBF7 THATSITtitle XproROM for XEROX 820-1 Version 1 Revision 15 DmC...8/5/84 subttl XproROM *** Header File For Assembly *** ;************************************************************************** ;* * ;* XPRO8 Monitor For Pro8+ operation on Xerox I * ;* Version 1 * ;* REV. # 1. Initial test DmC 5/13/84 * ;* 5. First 5 1/4 working version * ;* 6. Clear lead in flag problem * ;* 7. First FE43 DPHB FB98 DPHC FBA9 DPHD FE16 DSK FC10 ERFLAG FFA6 HEREIS FC09 HSTACT FC16 HSTBUF FC04 HSTDSK FC07 HSTSEC FC05 HSTTRK FC0A HSTWRT FBF4 IOFLAG FBF5 KBDAV FBF6 KBDCHR FE30 LEADIN FE8A MOVE FC00 RAMSCRATCH FBF3 RAMTRY FA80 RAMX FE99 RD128 FEA0 RD512 FF25 R**************************** INCLUDE XPROIO.MAC ;**** Memory Mapped CRT Driver ******************************************** INCLUDE XPROCRT.MAC ;**** External drive DPH's ************************************************ dphx: defw 0,0,0,0 ; dph for unit C: defw dirbuf,dpbd ; defw csvc,alvc defb ddbit defw 0,0,0,0 ; dph for unit D: defw dirbuf,dpbd defw csvd,alvd defb ddbit xendx: INCLUDE MONITOR.MAC ;**** Scratch pad Ram Allocation *********************************ԐeXPRO206 COM  XPROCRT MACT!"#$%&'()*+XPRODISKMAC,-./0123456789:;XPRODISKMAC<=>?@ABCDEFGHIJKXPRODISKMACLMNXPROIO MACNOPQRSTUVWXXPRORAM MACYZ[\XPRORAM PRNF]^_`abcdeXPRORAM $$$XPROROM MACghiXPROROM REL$jklmn-XPRO SRC working 5 and 8 inch mixed version * ;* 8. Added bullet proofing to 8 inch routines * ;* 9. Increase ALV of 8 inch disks and make * ;* the speed fix safer * ;* 10-14 Double density 8" ATTEMPTS * ;* 15. First working 8" double density * ;* * ;* Portions of Code derived from * ;* PFM MoniDWRTEND FC12 READOP FC11 RSFLAG FC00 SEKDSK FC08 SEKHST FC03 SEKSEC FC01 SEKTRK FE19 SIDFLG FE29 SPEED FFFF STACK FE72 TBL1 FBF7 THATSIT FE1A TRACKA FE1D TRACKB FE20 TRACKC FE23 TRACKD FE26 TRKFLG FC0B UNACNT FC0C UNADSK FC0F UNASEC FC0D UNATRK FEAA WRT128 FEB1 WRT512   ******** INCLUDE XPRORAM.MAC ; END ** INCLUDE XPROCRT.MAC ;**** External drive DPH's ************************************************ dphx: defw 0,0,0,0 ; dph for unit C: defw dirbuf,dpbd ; defw csvc,alvc defb ddbit defw 0,0,0,0 ; dph for unit D: defw dirbuf,dpbd defw csvd,alvd defb ddbit xendx: INCLUDE MONITOR.MAC ;**** Scratch pad Ram Allocation *********************************>? 0@'&2Os]'Uн`9YPQ>1@l lp0>u@/<3#&" ) d/[d12GC-2#I#Ht/ Z``c82ì @ < b(-MkDfNS\sޣ{>W`W1as]`s8Y,W+5: hJjX)} `CA@X(t2Dyt7c)i7!pl B@ D#y !o6#I ADA !pHyHCI lҠ% 7}s> )@@  A@A€b (|`08 0Ba(,"AP    (|/% @EՀڰW/-> d Ou2?B7~ `ڰA9;V a@ vK~2GA݄OOŻ _2xt-L:d ~# d~C  hWO&C2@_ kt~ -e@cѐ-:? }Aht>@7_01T_41T ~@d~0Р5x /54Ax+Y;5ThU'ì<Ioi9YF%Bg >D#Gp 7A>OPa?D%@K4sQih]nY4$fS@M7 Ps8 DCxk4A) )t c 7\4>Ioh1  K|A/x ߋp>2? l[ 1!?% B~3CF:? wOŻ #T~!2A݈+@s`R)E"Yv : ?02?lSt~?#`+@4X /1i|3gO/`y q(HoP o!TAg}r<(.=aP"C@ "@)D.S5 ;,ԓ ` aL4@%`&4om@ aL0 Gπv,&Xe@K a,3P%rР>XiK $y_0)C j Ac0$|  ՘,6= <@S<ΆSho7N󐀬e9&pd. d d3J@wJP 4aiPp&jHA1>H d(C!Sf@C_x@ 3[ pt- p@fkd{kv:=C ?#ي%)ncCd&oa:=B _á3g G@N!Ct(2 : @Y@5yV%@T~PȈ(Sx7BN @ 3[&aY@P4| !Lt2D(!e9m0 rGB\t?b(?"3,  @2B`!#9A D9CajWa)٣P3՚Dd*@!#96Ï`#L8 &:C?1! )G $)Gal>b3D WO>0ʠQ]: ?0(AP B! ?ڰ`\,+BB`a!횞 %RÎgL8Vk| >,a <f`2[oxy 0s> 02<Y kqЙ( t'q2 r8 P 0ajxyiX,AvY1G*>^.`{`L`; R{BNϗ > 3LoKl82G>Yoq!C>\oKt|ÏL>Y^8=K|A@v4h]x[[4'5 aof"aj:G [|;82e3Ʒd3Lo՚a| side is set IF FIVE trkst3: ld a,(emulate) ; do following routines for dbl step or a ; if zero no dbl step jr z,trkst4 ; trkst4 = no dbl step ld a,(tmptrk) ; get the track ld c,a ; keep in c for later arithmetic in a,(trkp) ; get current track from track reg. ld b,a ; save in b cp c ; which is bigger? jr c,swptrk ; c is bigger than a sub c ; else get difference add a,b ; and add it back on out (trkp),a ; send it to the controller ld a,(tmptrk) ; get the actualACROS ################################################################ ; upper case a character in a ucase macro res 5,a endm ; write cnt number of val bytes into memory (hl) bytes macro val, cnt local loop ld de,cnt loop: ld (hl),val inc hl dec de ld a,d or e jr nz,loop endm ;### Utility Subroutines ################################################### print: ex (sp),hl ; inline print routine ld a,(hl) inc hl ex (sp),hl or a ret z call conout jr print conout: t z jr rdydrv ENDIF home: call seldsk ; home that disk drive in a,(bitport) and sidmsk or sid0 out (bitport),a ld a,rstcmd out (cmnd),a jr busy settrk: call seldsk ; set that track call busy call trkset ld a,(track) ; extra delay on track 0 or a ; for them teac drives ld b,50 call z,thnsd ret busy: call delay ; do a delay then check status bsy: in a,(status) ; wait for not busy bit 0,a jr nz,bsy ret delay: call dly dly: ex (sp),hl ex (sp),hl  track comon: out (data),a ; what happens is that the controller ld a,fseekcmd ; thinks its twice as far as it out (cmnd),a ; actually is so it issues two step call busy ; pulses for each track on a quad ld a,(tmptrk) ; drive running 48 tpi disks out (trkp),a ; but must fix after we are done ret ; and get back. swptrk: ld a,(tmptrk) ; this is for c bigger than a sub b ; just get other difference add a,c ; and continue jr comon ENDIF ; FIVE trkst4: ld a,(tmptrk) ld c,6 ; console output ld e,a call bdos ret conin: ld c,6 ; console input ld e,0ffh call bdos or a jr z,conin ret echo: cp esc ; check for abort, otherwise echo a to conout jp z,start1 push af call conout pop af ret seldsk: in a,(bitport) ; select disk drive allow delay for spin up ld b,a ; save for checking motor status and drvmsk and denmsk and mtrmsk ld c,a ld a,(curdrv) or c IF EIGHT ld c,a ; save so we can test flag ld a,(sden) ; set single  ret trkset: ld a,(track) ; seek that track ld (tmptrk),a ; temporary track storage ld a,(dsflag) ; see if double sided or a IF EIGHT jr z,trkst4 ; zero means not dbl sided ELSE jr z,trkst3 ENDIF ld a,(track) ; shift logical track to get physical srl a ; and pop side bit into carry flag ld (tmptrk),a in a,(bitport) jr c,trkst1 IF UBOARD set 2,a ELSE res 2,a ENDIF jr trkst2 trkst1: IF UBOARD res 2,a ELSE set 2,a ENDIF trkst2: out (bitport),a ; now the;########################################################################## ;# Formatter and Copier for Kaypros, BigBoards, or Xerox's # ;# Eight or Five inch # ;# Actual Program file # ;# DmC # ;########################################################################## ORG 100h jp start ; get to start of program (in menu) ;## Mdensity if in that mode or a ld a,c jr z,sel1 or 20h ; selects single density ENDIF sel1: or mtron out (bitport),a IF EIGHT jr rdydrv ENDIF IF UBOARD bit 4,b ; check for motor on, return if so else delay ret nz ELSE bit 6,b ret z ENDIF ld b,50 thnsd: ld de,1670 ; a dippy little delay routine tlp: dec de ld a,d or e jr nz,tlp djnz thnsd ret IF EIGHT ficmd equ 11010000B rdydrv: ld a,ficmd out (cmnd),a call delay in a,(status) bit 7,a re  ; no fancy stuff just get to the out (data),a ; track requested. Either is a ld a,fseekcmd ; quad disk or 48 tpi drive or out (cmnd),a ; eight inch drive jp busy ; wait for the smoke to clear ;### Read or write all sectors on a Track to Buffer pointed to by hl ###### ;### READOP marks direction ( 0 for write non 0 for read ) hl better ###### ;### contain the DMA location on entry #################################### wrdtrk: ld a,(format) IF EIGHT cp '1' ; load correct sector taall echo cp 'C' jr z,copy cp 'F' jr z,formatf cp 'E' jp z,0 jr start1 copy: ld (option),a ; copy operation call getsrc ; get the source disk call getdst ; get the destination disk call cpy ; copy them jr again ; see if repeat is desired formatf: ld (option),a ; format a floppy disk call getdst ; get the destination disk call getform ; get the format desired call fmt ; do it jr again ; do it again ? again: call print db cr,lf,lf db 'Repeat last selection ( ld a,(readop) ; is this a read or a jr z,wrop ; nope a write-jump to right routine ld a,vrdcmd ; send read command out (cmnd),a ; to controller pop af ; get loop size jr z,rl2 ; and go to middle of loops for 512 rl0: halt ini jr nz,rl0 rl1: halt ini jr nz,rl1 ELSE ld a,(readop) ; same as for eight but always 512 or a jr z,wrop ld a,vrdcmd out (cmnd),a ENDIF rl2: halt ini jr nz,rl2 rl3: halt ini jr nz,rl3 call bsy ; no delay needed here, ld (66h),a xor a ; good op or we wouldn't be here ret ; get back..get back......... nmisav: nop ; space for saving code at 66h IF EIGHT rls: ld b,128 ; single density read ld a,(readop) or a jr z,wls ld a,vrdcmd out (cmnd),a jr rl3 wls: ld a,vwrcmd ; single density write out (cmnd),a jr wl3 ENDIF ;### Program Start ######################################################## start: ld sp,stack ; new stack call print db clrscr db cr,lf db 'Disk Utility ble ld de,stran jr z,vstrt cp '2' ld de,xtran jr z,vstrt ld de,btran ELSE ld de,xtran ; five inch are all the same ENDIF vstrt: ld a,(066h) ; save nmi byte ld (nmisav),a ld a,0C9h ; replace with RET op code ld (066h),a push de ; de points to sector table call seldsk ; select the disk call busy ; make sure controller isn't busy pop de vlp: ld a,(track) ; loop for all sectors in table bit 0,a ; first check for bias on back side ld a,(de) ; get sector  Y or N ) ? ' db 0 call conin ucase call echo cp 'Y' jp nz,start1 ; not a repeat, give them the menu repeat: ld a,(option) ; else repeat last operation cp 'C' jr nz,fmtagn call cpy jr again ; return here so we can again again fmtagn: call fmt jr again ;### Get Destination Disk ################################################# getdst: call print ; get the destination disk db cr,lf db 'Destination Disk ( A,B,C,D ) ? ',0 call conin ucase call echo ld (addrv),a ; loadjust check status ; again and vrdmsk ; mask unwanted status bits jr z,nexsec ; good read, do next sector push af ; else clean up and return non zero ld a,(nmisav) ; calling program handles retries ld (66h),a ; reload the code that was at nmi pop af ; restore error status ( for retry ) ld (error),a ; and save for reporting ret IF EIGHT wrop: ld a,vwrcmd ; write operations come here out (cmnd),a pop af jr z,wl2 wl0: halt outi jr nz,wl0 wl1: halt outi jr nz,wl1 for ' IF EIGHT db 'Eight' ELSE db 'Five' ENDIF db ' Inch Drives' IF CLK4 AND EIGHT db ' 4 MHz' ENDIF IF CLK5 AND EIGHT db ' 5 MHz' ENDIF db ' Version ' db ver,'.',rev db ' [DmC] ' db cr,lf,' Copyright (c) 1985 Micro Cornucopia ' db cr,lf,lf db ' aborts and returns to menu ',0 start1: ld sp,stack ; reload stack pointer for reentries call print ; get option desired db cr,lf,lf db 'Copy, Format, or Exit ( C,F,E ) ? ' db 0 call conin ucase cin a jr z,nobias ; don't add bias (front side of disk) ld b,a ; else add it onto sector # in a ld a,(secbias) ; where its kept add a,b ; add it nobias: out (secp),a ; give it to controller ld c,data ; c gets i/o port # ld b,0 ; b gets 0 for 256 byte loops IF EIGHT ld a,(format) ; get format so we can enter proper cp '1' ; loop according to sector length jr z,rls ; 128 byte sector cp '2' ; if '2' a will be 0 for 512 byte push af ; else will default to 1024 byte  ELSE wrop: ld a,vwrcmd out (cmnd),a ENDIF wl2: halt outi jr nz,wl2 wl3: halt outi jr nz,wl3 call bsy ; no delay and vwrmsk ; error mask jr z,nexsec ; good op procede push af ; else save status ld a,(nmisav) ; reload nmi code ld (66h),a pop af ; restore status ld (error),a ret nexsec: inc de ; get next sector in table ld a,(de) cp 0ffh ; ff is end of table jp nz,vlp ; not ff loop back for another sector ld a,(nmisav) ; else restore nmi    ascii into confirmation message call getdrv ; convert to bit pattern for select jr nz,getdst ; not zero if not A-D ld (ddrv),a ; else load pattern for seldsk ret ;### Convert Ascii Drive letter into bit pattern for bitport ############## getdrv: cp 'A' jr nz,dstb ld a,asel ret dstb: cp 'B' jr nz,dstc ld a,bsel ret dstc: cp 'C' jr nz,dstd ld a,csel ret dstd: cp 'D' ret nz ld a,dsel ret ;### Get Source Drive #####################################################  ; get ready to start signal call print db cr,lf db 0 call dstprn ; print destination disk call print db ' Enter carriage return to begin formatting. ',0 call conin cp cr ret z jp start1 dstprn: call print ; print destination drive poop db 'Insert destination disk in drive ' addrv: db 0 db ': ',0 ret abort: call print ; bad disk operation, tell and get out db cr,lf db 'Unrecoverable errors. Strike any key to return to menu',0 call errpt ; report the error type caIF IF EIGHT getagn: jp getform ENDIF IF FIVE cp '2' jr nz,try2 ld a,39 ld (maxtrk),a jr quadqry try2: cp '4' jr nz,k8 ld a,0ffh ld (dsflag),a ld a,10 ld (secbias),a ld a,79 ld (maxtrk),a jr quadqry k8: cp '8' jp nz,getform ld a,0ffh ld (dsflag),a ld a,20 ld (secbias),a ld a,159 ld (maxtrk),a ret quadqry: ; emulating 48tpi on a quad drive ? ld a,0 ld (emulate),a call print db cr,lf db 'Is the destination DRIVE a 96 tpi drive (Y or N) ? ',0 ccall maketrk ; build track image call prntrk ; display current track call wrttrk ; format it ld a,(track) ; bump track counter inc a ld (track),a pop af ; restore actual format ld (format),a ENDIF floop: call settrk ; seek to current track call maketrk ; build track image ld a,'0' ; reset retry counter ld (retry),a rfloop: call clrret ; another track, clear retry print track # rloop: call wrttrk ; format the track ld hl,vbuff ; now read it back to vbuff ld a,0ffh ; ye getsrc: call print db cr,lf db 'Source Disk ( A,B,C,D ) ? ',0 call conin ucase call echo ld (asdrv),a call getdrv jr nz,getsrc src1: ld (sdrv),a ret ;### Get Format Desired (for FORMAT option) ############################### getform: ; get the format ld a,0 ld (dsflag),a ; start with not dbl sided ld (secbias),a ; ditto ld (emulate),a ; and no emulation call print db cr,lf db 'Choose Format' db cr,lf IF EIGHT db '1 = Single Density (IBM 3740)' db cr,lf ll conin ; wait for user to wake up jp start1 ; and go back to menu prnret: call prntrk ; print retry information call print db ' Retry #' retry: db 0 db ' ',0 ret clrret: call print ; clear retry display db cr,' ',0 call prntrk ; reprint current track ret ;### Print Current Track ################################################## prntrk: call print db cr,'Track => ',0 ld a,(track) ;### Convert binary track to ascii and print as we go along ####all conin ucase call echo cp 'Y' ret nz ld a,0ffh ld (emulate),a ret ENDIF IF EIGHT dschk: ld a,76 ld (maxtrk),a call print db cr,lf,'Double Sided (Y or N) ? ',0 call conin ucase call echo cp 'Y' ret nz ld a,0ffh ld (dsflag),a ld a,152 ld (maxtrk),a ld a,(format) cp '3' jr z,bias1k ld a,16 ld (secbias),a ret bias1k: ld a,9 ld (secbias),a ret ENDIF ;### Format A Disk ######################################################## fmt: call formcon ; s I said read it ld (readop),a call wrdtrk ; read a track to (hl) jr z,wrtnext ; good read, format next track ld a,(retry) ; else bump the retry counter inc a ld (retry),a push af call prnret ; print the retry count pop af cp '4' jp z,abort ; tried hard enough, give up jr rloop wrtnext: ld hl,track ; onto next track ld a,(maxtrk) ; all done cp (hl) ; if they match yes ret z ; then we are finished inc (hl) ; else bump jr floop ; and do next track formcon:  db '2 = Double Density (16 512 Byte Sectors)' ENDIF IF EIGHT AND ONEK db cr,lf db '3 = Double Density (9 1024 Byte Sectors)' ENDIF IF FIVE db '2 = Kaypro 2 Format (191K)' db cr,lf db '4 = Kaypro 4 Format (390K)' db cr,lf db '8 = Kaypro 8 Format (784K)' ENDIF db cr,lf,'Selection ? ',0 call conin call echo ld (format),a IF EIGHT cp '1' jr nz,try2 ld a,76 ld (maxtrk),a ret try2: cp '2' jp z,dschk ENDIF IF EIGHT AND ONEK cp '3' jr nz,getagn jp dschk ENDremind user of destination disk call print ; and wait for cr db cr,lf,0 ; seperate display with a couple lines ld a,0 ; 0 is first track ld (track),a ld a,(ddrv) ; destination drive selection location ld (curdrv),a ; now the current drive call home ; home it IF EIGHT ld a,(format) ; save actual format so that we can force cp '1' jr z,floop ; single density no tricks needed push af ; single density on track 0 ld a,'1' ld (format),a call settrk ; seek to current track   ########### ld e,'0' hund: sub 100 jr c,tens inc e jr hund tens: add a,100 push af ld a,e cp '0' jr z,ten1 ld c,6 call bdos ten1: pop af ld e,'0' ten2: sub 10 jr c,ones inc e jr ten2 ones: add a,10+'0' push af ld c,6 call bdos pop af ld e,a ld c,6 call bdos ld e,20h ; an extra space to make it look better ld c,6 call bdos ret ;### Copy a Disk ########################################################## cpy: call print db cr,lf,0 call dstprn ; re ld bc,10*512 ; # of bytes for five inch drives ELSE ; else get number of bytes / track of sectors ld a,(format) cp '1' ld bc,26*128 jr z,vloop cp '2' ld bc,10*512 jr z,vloop ld bc,9*1024 ENDIF vloop: ld a,(de) cp (hl) jp nz,badcmp ; no match, call it bad dec bc ld a,c or b ret z inc de inc hl jr vloop IF EIGHT dotrk0: ld a,(format) ; force single density on track 0 push af ld a,'1' ld (format),a ld a,(ddrv) ld (curdrv),a call settrk call maketrk call cpyone ; copy one track ld hl,track ; see if all done ld a,(maxtrk) ; maximum tracks to do cp (hl) ; same as current track ? ret z ; yes, all done inc (hl) ; no bump track counter jr cpy2 ; and loop back to do another cpyone: ld a,(sem) ; source emulator flag ld (emulate),a ld a,(sdrv) ; source drive storage location ld (curdrv),a ; now current drive call settrk ; set the track do0: ld a,'0' ; no retries yet ld (retry),a ld a,0ffh ; going to be a read operation lds, and verifies ret ; another track done coptrk: call clrret ; clear the retry counter display ld a,'0' ld (retry),a call settrk ; set the track call maketrk ; create the track image copt1: call wrttrk ; first format the track ld a,0 ; then write the sectors to destination disk ld (readop),a ; not a read op ld hl,rbuff ; source of data call wrdtrk ; perform the operation jr z,copt2 ; good write, do the read/verify ld a,(retry) ; else bump the retry counter inc a ld (remind user of destination selection call print ; print source drive selection too db ' Source disk in drive ' asdrv: db 0 db ':' db cr,lf,'Strike any key when ready ',0 call conin ; wait for KEY hit chksrc: ld a,(sdrv) ; check out source drive format ld (curdrv),a call seldsk ; select the disk call home ; home it call dcheck ; get format of source disk call formrpt ; report format and wait for start IF FIVE c0: ld a,(maxtrk) cp 159 jr nz,cpy1 ld a,0 ld (dem),a ; cancall prntrk call wrttrk ld a,(track) inc a ld (track),a ld a,0 ; reset density flag for impending read ld (sden),a ; of track one pop af ld (format),a ret ENDIF ;### Figure out Source Disk and load appropriate parameters ############### dcheck: ld a,(66h) ; figure format of source disk push af ld a,0c9h ld (66h),a IF FIVE call dchk ; see if we can read at all jp nz,baddrv ; nope, no good in a,(bitport) ; if readable, check back side of disk and sidmsk or sid1 o (readop),a ; now marked as such dox: ld hl,rbuff ; rbuff gets the source disk data call wrdtrk ; read the track to rbuff jr z,do1 ; good op continue ld a,(retry) ; else do the retry thing inc a ld (retry),a push af call prnret ; print the retry we are on pop af cp '4' ; 4 retries done ? jp z,badrd ; yep let it be known jr dox ; else continue do1: ld a,(dem) ; now get destination poop ld (emulate),a ld a,(track) ; get current track or a jr z,cpy0 ; track 0 ? Don't dtry),a push af call prnret pop af cp '4' jp z,badwrt ; tried enough, tell the bad news jr copt1 ; jump back to try again copt2: ld a,'0' ld (retry),a call clrret ; clear retry display copt3: ld a,0ffh ; now read it back ld (readop),a ld hl,vbuff ; read the data to vbuff call wrdtrk jr z,copt4 ld a,(retry) inc a ld (retry),a push af call prnret pop af cp '4' jp z,badrd1 jr copt3 copt4: ld hl,rbuff ; byte for byte compare of two buffers ld de,vbuff IF FIVE cel emulate if this is quad copy ld (sem),a ENDIF cpy1: ld a,(ddrv) ; now set up destination drive ld (curdrv),a call seldsk call home ; home destination drive ld a,0 ; start on track 0 ld (track),a call print db cr,lf,lf,0 ; seperate display with a couple lines IF EIGHT ld a,(format) ; get format selected cp '1' ; single density ? jr z,cpy2 ; if yes, no special tricks call dotrk0 ; else force single density on track 0 ENDIF cpy2: call prntrk ; print current track ec the track register ld a,(dsflag) ; single sided ?, skip following tests or a jr z,cp0 ld a,(track) bit 0,a ; back side ?, don't dec the track register jr nz,cpy0 cp0: in a,(trkp) ; adjust the track register on the controller dec a ; for destination disk (its one trk behind) out (trkp),a cpy0: ld a,(ddrv) ; destination drive selection location ld (curdrv),a ; now it is the current drive call coptrk ; coptrk builds track image, formats the ; track, writes in the sector  ut (bitport),a call dchk ; try a read jr nz,singsid ld a,(adrbuf+2) cp 10 jr c,singsid cp 14h jr c,doubsid ld a,0 ld (sem),a ; no emulate on a quad format ld a,0ffh ; quads are double sided ld (dsflag),a ld a,20 ; secbias for quad ld (secbias),a ld a,159 ; # of tracks for quad ld (maxtrk),a ld a,'8' ld (format),a ELSE ld a,0 ld (secbias),a call stepin ; in one track ld a,0 ld (sden),a ; try double density call seldsk ; make it stick call dchk ge Return to begin copy operation,' db ' any other key to abort',0 call conin cp cr jp nz,start1 ret badcmp: call print db cr,lf,'Compare Error. Strike any key to return to menu ',0 call conin jp start1 badwrt: call print db cr,lf,'Write Error on destination disk. Strike any key to' db ' return to menu ',0 call errpt call conin jp start1 badrd: call print db cr,lf,'Read Error on source disk. Strike any key to return' db ' to menu ',0 call errpt call conin jp stara ld (sden),a jr outski singsid: ld a,0 ld (dsflag),a ld (sden),a ld a,76 ld (maxtrk),a ENDIF outski: in a,(bitport) ; finish up (back to side 0) and sidmsk or sid0 out (bitport),a IF FIVE ld a,(format) cp '8' jr z,ddone call quadqry ld a,(emulate) ld (dem),a ELSE call stepout ENDIF ddone: pop af ld (66h),a ; restore nmi ret IF FIVE singsid: ; Kaypro 2 source disk ld a,'2' ld (format),a ld a,39 ; # of tracks ld (maxtrk),a ld a,0 ; not doy ENDIF adrbuf: ds 8 baddrv: call print db cr,lf,'Cannot read source disk. Strike any key to return' db ' to menu',0 call conin jp start1 formrpt: ld a,(format) IF EIGHT cp '1' ld hl,form1 jp z,fout cp '3' ld hl,form3 jr nz,f2f ld a,(dsflag) or a jp z,fout ld hl,form4 jp fout f2f: ld hl,form2s ld a,(dsflag) or a jp z,fout ld hl,form2d jp fout form1: db 'Single Density (IBM 3740) ' form2s: db 'Single Sided 512 byte sectors ' form2d: db 'Double S; check it out jr z,dden8 ; could read must be dbl den ld a,0ffh ld (sden),a call seldsk call dchk jp nz,baddrv ; couldn't read single either get out ld a,'1' ld (format),a ld a,0 ld (dsflag),a ld a,76 ld (maxtrk),a jp outski dden8: ld a,(adrbuf+3) cp 3 jr nz,dblchk ld a,'3' ld (format),a in a,(bitport) and sidmsk or sid1 out (bitport),a call dchk jr nz,ssid1 ld a,(adrbuf) cp 1 jr nz,ssid1 ld a,(adrbuf)+2 cp 10 jr c,ssid1 cp 19 jr nc,ssid1 t1 badrd1: call print db cr,lf,'Read Error on destination disk. Strike any key to' db ' return to menu ',0 call errpt call conin jp start1 ;### Report Error, can report multiple errors if they occur ############### errpt: ld a,(error) bit 7,a call nz,notrdy bit 6,a call nz,wrtprt bit 5,a call nz,wrtflt bit 4,a call nz,rnf bit 3,a call nz,crc bit 2,a call nz,lstdat ret error: db 0 notrdy: push af call print db cr,lf,'Drive Not Ready ',0 pop af ret wrtuble sided ld (dsflag),a ld (secbias),a ; and no sector bias ld a,0ffh ld (sem),a in a,(bitport) and sidmsk or sid0 out (bitport),a call qchk jr z,outski ld a,0 ; not 0, not quad ld (sem),a jr outski doubsid: ld a,'4' ld (format),a ld a,79 ld (maxtrk),a ld a,0ffh ld (dsflag),a ld (sem),a ld a,10 ld (secbias),a call qchk jr z,outski ld a,0 ld (sem),a call quadqry ld a,(emulate) ld (dem),a jr outski ENDIF dchk: call seldsk ld hl,adrbuf ldided 512 byte sectors ' form3: db 'Single Sided 1024 byte sectors' form4: db 'Double Sided 1024 byte sectors' ELSE cp '2' ld hl,form2 jp z,fout cp '4' ld hl,form4 jp z,fout ld hl,form8 jr fout form2: db 'Kaypro 2 Format (191K) ' form4: db 'Kaypro 4 Format (390K) ' form8: db 'Kaypro 8 Format (784K) ' ENDIF fout: ld de,fdest ld bc,30 ldir call print db cr,lf db 'Source Drive is ' fdest: db ' ' db cr,lf db ' Enter Carriald a,152 ld (maxtrk),a ld a,0ffh ld (dsflag),a ld a,9 ld (secbias),a xor a ld (sden),a jr outski ssid1: ld a,76 ld (maxtrk),a ld a,0 ld (dsflag),a ld (sden),a jr outski dblchk: ld a,'2' ld (format),a in a,(bitport) and sidmsk or sid1 out (bitport),a call dchk jr nz,singsid ld a,(adrbuf) cp 1 jr nz,singsid ld a,(adrbuf+2) cp 17 jr c,singsid cp 33 jr nc,singsid ld a,152 ld (maxtrk),a ld a,0ffh ld (dsflag),a ld a,16 ld (secbias),a xor  bc,6*256+data ld a,0c4h out (cmnd),a dchk1: halt ini jr nz,dchk1 call busy bit 4,a ret IF FIVE qchk: ld a,04ah out (cmnd),a call busy ld a,04ah out (cmnd),a call busy call dchk ld a,06ah out (cmnd),a call busy ld a,06ah out (cmnd),a call busy ld a,(adrbuf) ; track address cp 1 ; step twice but still on track 1 ? ret ; if so (zero) this is a quad drive ELSE stepin: ld a,01001011b out (cmnd),a jp busy stepout: ld a,01101011b out (cmnd),a jp bus  prt: push af call print db cr,lf,'Disk Write Protected ',0 pop af ret wrtflt: push af call print db cr,lf,'Write Fault ',0 pop af ret rnf: push af call print db cr,lf,'Record Not Found ',0 pop af ret crc: push af call print db cr,lf,'CRC Error ',0 pop af ret lstdat: call print db cr,lf,'Lost Data ',0 ret ;### Format a Track ####################################################### wrttrk: di IF CLK4 AND EIGHT call seldsk call nmiswap ; load nmi vector stuff pre ID gap ELSE bytes 04EH, 16 ENDIF xtrksec: IF EIGHT bytes 0, 12 ELSE bytes 0, 8 ENDIF bytes 0F5H, 3 ; Writes A1 bytes 0FEH, 1 ; ID AM ld a,(dsflag) or a ld a,(track) ; track # ld c,a ; c now has raw track jr z,xovnext srl a xovnext: ld (hl),a ; track number inc hl IF EIGHT bytes 00100000B, 1 ; side number = 00 with 16 in upper bits ELSE bytes 0, 1 ENDIF ex (sp),hl ; pointer to tran table ld a,(dsflag) ; is this a double sider or a ld a,(hl) ; gd (hl),a ld a,c ld (de),a inc hl inc de djnz nmilp ret outcod: outi ret ELSE ; not clk4 and eight (i.e. 5 inch or > 4MHz ) call seldsk ld c,data ld hl,tbuff ld a,(66h) push af ld a,0C9h ld (66h),a ld a,fwrtcmd out (cmnd),a wrtlp: halt outi in a,(status) bit 0,a jp nz,wrtlp pop af ld (66h),a ret ENDIF ;### Build Track Images ################################################### maketrk: IF EIGHT ld a,(format) cp '2' jp z,dmaktrk ENDIF IF EIa field bytes 0F7H, 1 ; CRC bytes 0FFH, 27 ; post data gap / pre ID gap dec b ; down sector count jp nz,strksec ; another sector to do in image? bytes 0FFH, 512 ; plenty of bytes til controller finishes ex (sp),hl ; tran tbl adr not needed pop hl ret ; exit with hl=len of track stran: ;new translate table for single density defb 1, 2, 3, 4 defb 5, 6, 7, 8 defb 9, 10, 11, 12 defb 13, 14, 15, 16 defb 17, 18, 19, 20 defb 21, 22, 23, 24 defb 25, 26 defb 0ffh  ld hl,tbuff ; beginning of track buffer ld a,(hl) ; get first byte exx ; save pointer in alternate registers ld hl,(nopcod) ; pick up bytes to load cp 04eh ; if single density no need to do weird stuff jr nz,comcode ; yep single den has no 4e ld hl,(calcod) ; else modify program for two byte two step comcode: ld (dummy),hl ; fox trot at 4 MHz exx ; get old registers back ld c,data ; the port of interest ld hl,tbuff ; hl^ to track image, de is length ld a,fwrtcmd ; track writet sector number first jr z,xmktk2 ; isn't double skip next routines bit 0,c ; if even track, do not add bias jr z,xmktk2 ld a,(secbias) ; secbias must be 0 for single sided disks add a,(hl) ; hl still points at sector number xmktk2: inc hl ; next table entry ex (sp),hl ; back on stack ld (hl),a ; sector number inc hl bytes 2, 1 ; sector length = 512 bytes 0F7H, 1 ; CRC IF EIGHT bytes 04EH, 24 ; post ID gap ELSE bytes 04Eh, 22 ENDIF bytes 0, 12 bytes 0F5H, 3 ; wrGHT AND ONEK cp '3' jp z,bmaktrk ENDIF IF EIGHT ld a,0ffh ; single density ld (sden),a ; single density flag call seldsk ; make it stick ELSE jr dmaktrk ENDIF IF EIGHT ;### Make a single density track image #################################### smaktrk: ld hl,stran ; sector skew table push hl ; store on stack for use ld hl,tbuff ; hl^ to track image in memory ld b,26 ; number of sectors to gen bytes 0FFH, 40 ; post index gap bytes 0, 6 bytes 0FCH, 1 ; index AM b ENDIF ;### Make a 16*512 byte track image ####################################### ;### Or a five inch image ################################################# dmaktrk: xor a ld (sden),a ld hl,xtran ; sector skew table push hl ; store on stack for use ld hl,tbuff ; hl^ to track image in memory IF EIGHT ld b,16 ; number of sectors to gen ELSE ld b,10 ENDIF bytes 04EH, 80 ; post index gap bytes 0, 12 bytes 0F6H, 3 ; Writes C2 bytes 0FCH, 1 ; index AM IF EIGHT bytes 04EH, 50 ;e command out (cmnd),a ; issue command wrtlp: halt ; wait for controller in a,(status) dummy: nop ; this gets modified for 4 MHz operation nop ; and the nmi code gets called a second time nop and 1 ; check out busy bit jr nz,wrtlp ; more bytes call nmiswap ; restore nmi stuff ret calcod: db 0CDh db 066h nopcod: db 00h db 00h nmiswap: ; swap the three bytes at outcod with the ld hl,outcod ; three bytes at nmivec ld de,0066h ld b,3 nmilp: ld c,(hl) ld a,(de) lytes 0FFH, 26 ; pre ID gap strksec: bytes 0, 6 bytes 0FEH, 1 ; ID AM ld a,(track) ; track # ld (hl),a ; track number inc hl bytes 0, 1 ; side number = 00 ex (sp),hl ; pointer to tran table ld a,(hl) ; get sector number first smktk2: inc hl ; next table entry ex (sp),hl ; back on stack ld (hl),a ; sector number inc hl bytes 0, 1 ; sector length = 128 bytes 0F7H, 1 ; CRC bytes 0FFH, 11 ; post ID gap bytes 0, 6 bytes 0FBH, 1 ; data AM bytes 0E5H, 128 ; dat  ites A1 bytes 0FBH, 1 ; data AM bytes 0E5H, 512 ; data field bytes 0F7H, 1 ; CRC ; mark these if's with a label so we know IF EIGHT ; only one is selected pdg: bytes 04EH, 30 ; post data gap / pre ID gap 26? ENDIF IF ( NOT EIGHT ) AND XPRO pdg: bytes 04Eh, 16 ENDIF IF ( NOT EIGHT ) AND ( NOT XPRO ) pdg: bytes 04Eh, 26 ENDIF dec b ; down sector count jp nz,xtrksec ; another sector to do in image? bytes 04EH, 512 ; pre index gap (fill out track) ex (sp),hl ; tran;########################################################################## ;# Formatter and Copier for Kaypros, BigBoards, or Xerox's # ;# Eight or Five inch # ;# Program Header File # ;# Version 1.5 # ;# DmC # ;######################################################################### table ld a,(dsflag) ; is this a double sider or a ld a,(hl) ; get sector number first jr z,bmktk2 ; isn't double skip next routines bit 0,c ; if even track, do not add bias jr z,bmktk2 ld a,(secbias) ; secbias must be 0 for single sided disks add a,(hl) ; hl still points at sector number bmktk2: inc hl ; next table entry ex (sp),hl ; back on stack ld (hl),a ; sector number inc hl bytes 3, 1 ; sector length = 1024 bytes 0F7H, 1 ; CRC bytes 04EH, 22 ; post ID gap ecbias+1 ; emulation flag dem equ emulate+1 ; emulate destination disk flag sem equ dem+1 ; emulate source disk flag readop equ sem+1 ; read or write flag maxtrk equ readop+1 ; maximum track to format stack equ maxtrk+80 ; stack vbuff equ stack+2 ; verify buffer rbuff equ vbuff+(9*1024) ; read buffer tbuff equ rbuff+(9*1024) ; space for track image  tbl adr not needed pop hl ret IF EIGHT xtran: ;new translate table skew of 3 defb 1,14,11,8 defb 5,2,15,12 defb 9,6,3,16 defb 13,10,7,4 defb 0ffh ELSE xtran: defb 0,8,3,6 defb 1,9,4,7 defb 2,5 defb 0ffh ENDIF IF EIGHT AND ONEK ;### Make a 9*1024 track image ############################################ bmaktrk: xor a ld (sden),a ld hl,btran ; sector skew table push hl ; store on stack for use ld hl,tbuff ; hl^ to track image in memory ld b,9 ; number of sectors# ASEG .Z80 false equ 0 true equ not false ver equ '1' rev equ '5' ;******* 4 or 5 Mhz ? ***************************************************** CLK4 equ false CLK5 equ NOT CLK4 ;******* Which Computer ? ************************************************* UBOARD equ false ; universal board XPRO equ false ; xerox PRO88 equ true ; old 2's and 4's BB equ false ; Big Board ;******* Five or Eight Inch ? ********************************************* EIGHT equ false ; eight  bytes 0, 12 bytes 0F5H, 3 ; writes A1 bytes 0FBH, 1 ; data AM bytes 0E5H, 512 ; data field bytes 0E5H, 512 ; more data field bytes 0F7H, 1 ; CRC bytes 04EH, 40 ; post data gap / pre ID gap 26? dec b ; down sector count jp nz,btrksec ; another sector to do in image? bytes 04EH, 512 ; pre index gap (fill out track) ex (sp),hl ; tran tbl adr not needed pop hl ret btran: ;new translate table skew of 3 defb 1,8,6 defb 4,2,9 defb 7,5,3 defb 0ffh ENDIF  to gen bytes 04EH, 50 ; post index gap ;## No Index Mark (or so they say) ; bytes 0, 12 ; bytes 0F6H, 3 ; Writes C2 ; bytes 0FCH, 1 ; index AM ; bytes 04EH, 50 ; pre ID gap 16? btrksec: bytes 0, 12 bytes 0F5H, 3 ; Writes A1 bytes 0FEH, 1 ; ID AM ld a,(dsflag) or a ld a,(track) ; track # ld c,a ; c now has raw track jr z,bovnext srl a bovnext: ld (hl),a ; track number inc hl bytes 00010010B, 1 ; side number = 00 with 9 in upper bits ex (sp),hl ; pointer to tran;### variable storage areas ############################################## ddrv equ $ ; destination drive bit pattern sdrv equ ddrv+1 ; source drive bit pattern curdrv equ sdrv+1 ; current drive bit pattern track equ curdrv+1 ; current track format equ track+1 ; selected format tmptrk equ format+1 ; temporary track storage dsflag equ tmptrk+1 ; double sided flag option equ dsflag+1 ; option ( for again ) sden equ option+1 ; density flag secbias equ sden+1 ; sector bias value emulate equ s  inch formats FIVE equ NOT EIGHT ; five inch formats ONEK equ EIGHT ; 1024 byte sectors (not important if FIVE) ;************************************************************************** wboot equ 0 ; restart system entry point (Warm boot) bdos equ 5 ; bdos entry crlf equ 0D0AH ; new line codes cr equ 0DH lf equ 0AH return equ 0DH ; ascii return code esc equ 1BH ; ascii esc clrscr equ 1AH ; clear the screen tab equ 9 ; data equ 013H ; controller data port cmnd equ 010H ; controller \\P*\ ? cG F\ !*#^#V*"[  ~# q#~2#~2 *[>w# ’:2*"!1&.6>*"{/_z/W*"::ʓ!2# !"# *w**w#w#"*w#"og""{/_z/W*|~*|d~***s#r#"***s#r#"**:¤:ʫw#Ö*#~2#~2##^#V" ##^#V" ##^#V"*|g" 2G 2I Û÷E ect bits denmsk equ 11011111b ; reset density select bits IF UBOARD sid0 equ 00000100b sid1 equ 00000000b mtrmsk equ 11101111b mtron equ 00010000b mtroff equ 00000000b bitport equ 14h ELSE ; ALL others use these sid0 equ 00000000b sid1 equ 00000100b mtrmsk equ 10111111b ; reset motor bit mask mtron equ 00000000b ; motor on mtroff equ 01000000b ; motor off bitport equ 1ch ENDIF secp equ 012H ; sector port trkp equ 011h ; track port INCLUDE CF.MAC ; the guts of t QwikKey V2.1 for CP/M-80 Copyright (c) 1984,1985 by Anton R. Fleig QwikKey may be used for non-commercial purposes only. No commercial use of QwikKey may be made without the author's express written permission. $Usage: QK initialize QwikKey QK R remove QwikKey QK L [file] load key definitions QK S [file] save key definitions $ Enter attention/termination character: $ Enter escape sequence lead-in character: $QwikKey removed from memory. $:]2command port status equ 010H ; status port for controller fwrtcmd equ 0F4H ; write track command. 15 ms delay frdcmd equ 0E4H ; read track command, 15 ms delay rstcmd equ 00001011b ; home drive fseekcmd equ 00011011b ; seek track vrdcmd equ 088h ; read a sector vwrcmd equ 0A8h ; write a sector vrdmsk equ 09Ch ; read error mask vwrmsk equ 0FCh ; write error mask ;### Drive Select Bit Patterns (for or operations) ######################## if uboard asel equ 00000010b bsel equ 000*QK21*yʛ"E :5 >:5 \:6 G:E xp4Vb!6 b*C F#"C ~25 xɯ2B !6 ~ʌp#À4ʣ2B 6 w#¦ G:E xpw#ôw25 :B O>  2O:B <2B  !6 w#G:F xw + w# 6!%  :6 O m=6 #bgTG#>> ^:B <2B @ÌO:B <2B :G ʨ! 1 :O*(s#r##2s#r Key: = he program end 101111b mtron equ 00010000b mtroff equ 00000000b bitport equ 14h ELSE ; ALL others use these sid0 equ 00000000b sid1 equ 00000100b mtrmsk equ 10111111b ; reset motor bit mask mtron equ 00000000b ; motor on mtroff equ 01000000b ; motor off bitport equ 1ch ENDIF secp equ 012H ; sector port trkp equ 011h ; track port INCLUDE CF.MAC ; the guts of t :m l!\w# *"!k {/_z/W}5$L*.|g"*#^#V !ci# ʧU*QK21* :L…!E "ÿ  ʕ2E  ʮ2F Ͱ*"!"!"!"!k "**#s#r*+r+s+>w"* ^@_QwikKey definition file not found. $QwikKey definitions saved. $QwikKey definitions loaded. $QWIKKEY DEF:R]*#^#V^#V":LS\P*\ 400001b csel equ 00000011b dsel equ 00000000b endif if xpro asel equ 00000001b bsel equ 00000010b csel equ 00000000b dsel equ 00000011b endif if pro88 asel equ 00000001b bsel equ 00000010b csel equ 00000000b dsel equ 00000011b endif if BB asel equ 00000000b bsel equ 00000001b csel equ 00000010b dsel equ 00000011b endif ;### Masks for anding, other stuff for oring ############################## drvmsk equ 11111100b ; reset drive select bits sidmsk equ 11111011b ; reset side sel  QwikKey definition table full. QwikKey loaded.   which generate escape sequences rather than single characters. This is almost always the ESCAPE character (ASCII 27 decimal). After the attention and lead-in characters are entered, QwikKey loads itself below the CCP (Console Command Processor), and returns control to CP/M. The message "QwikKey loaded." will appear at each warm boot to remind you that QwikKey is indeed active. At this poid keys generating escape sequences are supported. The maximum length of the defined string is 31 minus the length of the character or string normally generated by the key in question. Thirty-one different keys may be defined. 2.0 OPERATION 2.1 The First Time QwikKey V2.0 should be invoked for the first time with the command "QK". QwikKey will prompt for an "attention/termination characternt, striking the attention character key will cause QwikKey to respond with the following prompt: Key: Now strike the key you wish to define. The character normally generated by the key will be displayed, followed by an equals sign. Suppose for example, you wished to define the control-K key. The following would appear after striking CTRL-K: Key: ^K = Now enter the definition string, followed by Q W I K K E Y A Keyboard Redefinition Program V2.1 24-MAR-1985 Copyright (c) 1984, 1985 by Anton R. Fleig QwikKey may be used for non-commercial purposes only. No commercial use of QwikKey may be made without the author's express written permission. 1.0 INTRODUCTION QwikKey allows the user to assign a cha" and an "escape sequence lead-in character". The attention/termination character is used to gain the attention of QwikKey in order to enter a new key definition. The same character is used to terminate the definition string. Thus, this character should be one that is seldom if ever used, both from the keyboard, and in key definition strings. The escape sequence lead-in character is the first character generated by keysracter strings to keys. When a key having a string defined in this way is struck, the defined string, rather than the character normally associated with the key, is delivered to the program running at the time. Key definitions may be loaded from files containing previously saved definitions, or they may be defined on-the-fly, even while a program is running. Both normal keys (i.e. keys generating a single character) an   the attention character again. Suppose we wished to define ^K as "PIP A:=B:*.*[V]". The following would be displayed just before we hit the attention character to terminate the definition: Key: ^K = PIP A:=B:*.*[V] Upon entry of the termination character, the key definition dialogue is erased. Note that characters overwritten by the definition dialogue are not rewritten, but replaced on the screen  0101 1B . Quit now (note lead-in char) -S120 First definition 0120 56 08 Key string is BS char 0121 1A 00 Null terminate 0122 09 7F Delete char is definition 0123 AC 00 Null terminate -G0 Mods done A>SAVE 5 QWIKKEY.DEF Save on disk able in memory, replacing any current definitions. It can only be issued at the CCP prompt level (e.g. A>). A>QK LOAD KEYDEF.DAT If the filename is omitted in the above example, the definitions will be read from the file QWIKKEY.DEF. LOAD may be abbreviated to the single character "L". Note that the attention/termination character and the escape sequence lead-in character are also read from the definition aracter and the lead-in character, respectively. The third byte contains a warm boot flag (see section 3.2). The remainder of the first record is currently unused and uninitialized. The remaining 31 records contain definition strings in the following format: [Key string] 0 [Definition string] 0 The key string is the keyboard generated character(s). Both the key string and the definition string are null-te with spaces. At this point, the key has been defined, and striking the defined key will result in the definition string being delivered to the current program (perhaps the CCP). 2.2 Saving Definitions The following command will save your current definitions for later recall in the file KEYDEF.DAT. It can only be issued at the CCP prompt level (e.g. A>). A>QK SAVE KEYDEF.DAT If the filename  3.2 Disabling the Warm Boot Message The third byte in the key definition file, if non-zero, (the default) causes the "QwikKey loaded." message to be displayed on each warm boot. Setting this byte to zero will disable this feature. 4.0 MISCELLANEOUS QwikKey occupies the memory space just below CP/M's Console Command Processor (CCP). In order to accomplish this, several pointers within the system are modified as QwikKey  file. 2.4 Removing QwikKey QwikKey can be removed from memory with the following command. A>QK REMOVE The word "remove" in the above command can be abbreviated with the single character "R". 3.0 ADVANCED TOPICS The following topics are intended for those familiar with DDT and the attendant risks in its use. 3.1 Creating Definitions Containing Non-keyboard Characters Definitions may be created containing chararminated, as shown above. The following is an example of the sequence of commands used to define CTRL-D to be DELETE, assuming the keyboard being used cannot generate the DELETE character. A>DDT QWIKKEY.DEF Default definition file DDT VERS 2.2 NEXT PC 0500 0100 -S100 First record 0100 2B 0B Make ^K attn char is omitted in the above example, the definitions will be saved in the file QWIKKEY.DEF. SAVE may be abbreviated to the single character "S". Note that the attention/termination character and the escape sequence lead-in character are also saved in the definition file. 2.3 Loading Previously Saved Definitions The following command will load previously saved commands from KEYDEF.DAT into QwikKey's definition tcters not generated by any key on the computer's keyboard through direct modification of the key definition file(s). This might be useful to add a DELETE key to a computer having only a BACKSPACE key, for example. In order to do this, the structure of the key definition file must be understood. The key definition file consists of 32 logical records of 32 bytes each. The first record's first two bytes are the attention ch!  is installed (notably the WBOOT, CONST, and CONIN vectors in the BIOS jump table, and the BDOS vector at location 5). It is possible that QwikKey could interact detrimentally with other programs, especially any that attempt similar modifications. Should this circumstance occur, you may want to remove QwikKey while the other program is executing. The REMOVE command may be used for this.  undeleted--name existsU&7÷~(#>):< +6>2:2> 92 2 g Tj !=2 º ͪ4>2  Ͷ4 |  2:\2:=Ī4:0ͪ4221em:À>?Ͷ!͚92<2ɗ2B *<;<= *6Ϳ: >:͟7 ͊7:= !<*6>͛ *6" *U" !"U:0!" >O2 :͗+Jo7:͗+y$y;`i#"" N8 e<% s#r#6 #%:B=N7s#r#å oN8 7!"* ͪ4! y;;< " gKey is invoked with no arguments on the command line. o Messages are displayed indicating that key definitions have beed loaded or saved when those operations are invoked. o Undefined key escape sequences are now passed unaltered. In the previous version, everything but the escape character was stripped, leaving only the escape character, thus programs prepared to accept the raw key sequences failed with QwikKey installed. elp! FJKMNSUVdktdisk fullcan't make filemedia changeddisk i/odisk r/ofile r/obad drivepassword existsambiguityfile table fullchecksumno memoryuser cancelsyntaxfile not foundincompatible cp/m versionbad decode table͔4!͓TYPE -H FOR HELP  * &j;e9*<"RN8 :8= ^>V l21!N#W>ͼ: 6!!"6>2yʈ:2 ÈABORTEDï2*6>!  2j%y$>2j%G ͪ4ð4 ͔>ë5:<2Clos͑Ͷ4\$:Ͷ|<") 2[ {<": ͪ4!Ͷ4.>͇5!|&͏.."6!R I6>  7>k2X Ͷ4 : 4O6ABCDEFLMOPQRTUVWXYZ? ] y͆!Ú9* # * +} * Õ g Ͷ4?h4 *) { %͡4Deleting: .&:>O >> >U&Ͷ4    Ͷ4ind what? s  O >*w#w#wC% %}BK;<, * Ͷ4Log: g "6g >*s͡4, , Print, , or View (DEPQV) Enter one: 42 O6EQDPV y͆ ͡4Destination? \[-  ͭ.>::#6} >D ͼ |&."6 F NULU 1.5 (11/01/85) Copyright (C) 1984, 1985 by Martin Murray!:7O<`Ͱ4 âPPF>2>G3:8=0ډm͔Ï!"1!9"1!9"*e&###:fO *<"8*hDM) "<22m332r2(3 ͔"8=}0 -͔m͔">_Tm͔*"!"ͯ+ -Y *LBR -O<  WORK-LBR.$$$ NCF NOF LBR )ibrary lL membersNULU/s oryDiskUn>\>g222ê4 Ͷ4 changes?h4͡4͑2<~-#~GͶxN*U6ml! ͚͡4inreceived from :.͗>ON)ʨ:e2,2e*4m ã:͗+mTo! ͡4outsent to F+:.͗2O9ͪ4>KN) v2~5mͧ4ö4,}*6\, ͡4Press ^C to stopF+t9ȗ,:͗+X*h,1/Xͤ9.,w͡4Deleting: :.G3́.>P͛13,3*6Ϳ *6) ʣ úC% N8 ͡4Undeleting%" ͡4 %.&*%*%*/&.C%"%"% Ͷ4 can't be QK21 Update Notes March 24, 1985 o QwikKey Version 2.1 contains a complete re-write of the installation routines in an attempt to make QwikKey compatible with a greater number of other programs, notably the SD97 directory program. o The REMOVE command has been added, allowing users to remove QwikKey from memory without resorting to a cold boot. o Usage instructions are displayed if QwikDfile erroreleteress RETURN CRCreadunwritten datalRe runchKBrief entriesAbandonConsole put to be ing enameRWildcard specsqueezeFilesweep Extract drive/user to: ...ReplacedirectAddtoggleClose themodeGetHelpListOpen aPrintStrsearch/AddDrive/User changeViewopenExit inputoutputREADYNextPreviousCloseFindLog newMass operationsOpen newPrintTagUntagViewrExit command modeH"   : D{  Ͷ4 name: g "6kg  Ͷ4  ͱ Ͷ4  ;{ ͫ*c >*"22s Ͷ4 Tagged = >k͆Ë ͫ ʔ O<> e  ͡4Old:  =<Oͼ:"6͡4New: K N g o7!"6!"U >!͖564O6LOXYZ?y?` a ͽ Menu>52x 2$>2d !~> 2x ^No. ;^No open. Jͧ4ö4+j; !"2!#";<ڑgk<>ʨ#N#F<* g##~"i #k<*>::*6"*<"6*Ù6!"6B*U>"#:6#"U1'>M 212l"n͡4Library: +͡4Name Index Size KiloBytes CRC2j%>!C%"<%% y¸͋>5͡4DIRECTORY >5xͪ4(&>P5͂>P5͂>P5:B=N7͂>P5>2<*&&=I6>0 7͓x"<*%?͋*%X͋p͋>5͡4Active sectors ͡4Unused ͡4Total <2j%>5G ͈Ó=> 2 72$:l,2՗C%<N8=[-2\BK.F+͡4Extracting...>͗+t9%<7#:N87g,!:,2=ͭ.!=͘7oG3F+͛1>5!ͭ. will be ked to >W4>5ͪ42ʬ!"%"r"%!oG3)2"+!"I"&&!="t9ʕ+"*&&}O<Ͷ4 -Continue?h4ʕ!}+"+͡4 Copying: !#"U&#!:"$ͼ:͓.% s#r###"ͨ&+>+>G3ͺ+`}*%"%*j"jʦ>MʦM•*,DM!"r:,G3>ͱ*ʕ*,",I8 :,G3'2*!O9Ͷ4 abortedreopenold>K2 *6!"6k"6m7*j}*,DM*r:,G3>ͱ*2͡4 is READ-ONLY. Modify anyway?h4g22 <2>S ͡4now O:2^>NÆͼ4FF:2: 6'":;BHIJLOUYZ<>ʋ>Í>?2 g,:,*<ͭ.> 6¨ > 6'":;ABCDEFGHJKLNOPQRSTUVWXYZ<>?*6Ϳ:22*6) ͢! >2:22?CmU:2*U>U=͘76,}"*6\, !I-͘7 w<2yOyO}o|g|g}!oi a_{zı9{z33:l,>͗+*,*,w*,O<K'H",ė+G3Z͔z   :=,m>"*6Ϳ2?2=2E!\>,8) C% >ʁ>͗+',,\3!=33ͭ.́.<:>ON)2E `iÎ%%(&>a(ž; 3;!#"> ͇5Ͷ4--> found;Ð!"͡4Now searching: O9e9TʬBO: 2y2 6':;BCFHKLXY>:y6"JZ:e:m m4 CmlF+͹2:.GG31Insert disk containx͗͡4 and pC]O9e9!W>"6"U>¾!J~6>¬͡4-:: 6ABCDEFGHKLNOPQRSTUVWXY<>?O!͡4 %*/&͏.\͋Ͷ4 to ͨ&>7a(: ͗ '2RyN!=;6̓͗>&ʑa(S‘'ʑ:͗++*&&}O<>K \[-BK!=. '\͹2!=>ͭ.>K<:N)+ *!O9:<'4&*,>ͱ* 'C%͡4Deleting...%ʼ%͡4 .&y =U& >U&*%+"E >2< *,"; !; w3A ͡4Active entries: *%Ͷ4, Deleted: *%Ͷ4, Free: *&Ͷ4, Total: *%Ͷ4.ɗ2<>ON)!"&"&"&}#",J*ʁ!~’! #~ ’! #|<A<’!{<{<"T!'))Ͳ&y!ʕ\:=G3͛1:,G3g,!>::#>.682͑Ͷ4 ked.m7÷!"jͪ4eT) +!<+*6\[-K !52>-2$>2!>?2ͧ4͔4Ͷ4 >5ö4l2 :.G32(321F+m2>͗+G>g,*<:,ͭ.o1Can't find ͑͡4Replace it and pCʑ1F+: 6KOXm͡4NO LIBRARY OPENmlF+! ͥ 2͑͘222 Ͷ4 open. (Buffer size: *,*,O<><Ͷ4 sectors)múU :>U !=> 6͓Ͱ4 not found.  G >G:cx2> 2<5&o:2͡4ERROR Ͷ4: }!Z:!]W!Oͥ7͓ê4unnamed!W>{ʍ)ʍʍʍw# p6y~<#O!ͥ7͓Õ͉ÕJ*: 6VPS<+4T`UC} O P)Pk#E N d] = W ) / E Z  ,}\,͔4\:.́.!=<:>ON)3!DMc'',,LUS"`i#>(<"))"Ͳ&<:>PN)>2< <",;<͞:!  :`i"!rs#rͶ'!ͥ MSe<>K͛ͥ7͘7͓͉͆9z>:4Ͷ4:>>a*6:eG:͗+G&H6[7 !!̀6"U*62>͗+ʦt9ʑfʑ!+"z}l C5!"z!"zͣ:,2e'd>ͫ5O*6> ڷw# ²,2͋!33ͭ.!W>ͭ.> 6;76 #!U=͘7>O2 !mT5}"z:e͗+*:2i~5͒ERROR ͧ4>v>Ç5>&H%'2e9͒closed. 2~5͡4CONOUT file ö4!=:,ͭ.\[-og2G'3OG3;<1> y$`i""N8% |& To make it, enter the number of to allow.!"͡4 Pnow to abort making the. Allow how many: ~~<~T#͓É!> ͖5ʑ52}>N ;<ڪ;<ҼDM!=o͇M Too many.2!<"*6>=:6#͌:"o5f5> 4o5f5͡4 ͧ42ʧ4O> >͇5#ͪ4>Ćy͆͆9͓#:2 :2ͪ4͓2>@mm͌:2|e<͘7o9*<@>ͫ5u*6̀66~ž:‹um*U6 :͗+mͪ4l*6) *<;<>>̀$K >Oà>Rà:>O mg,͘#  "%"a!!j;"!e9<:*<>N):.2,>;;k *, ~͊& yi!:l,͙!>M'ʕ!ʕ!'>dO9'C%t9%ʼx5̔4̪4%(&c'å!2A",2#<=,"+t9q#+"H$2j%<$><$,q#,=;=m$#"!I->.:#m$#"!!"W$#ͪ4C%q"|<"W$V$q">Oʠ"Rʠ".&Ͷ4 already exists--not added.!:A"R "d$Ͷ4 not in library--not replaced!=3"d$Ͷ4: Cannot add an 8 megabyte file!!"#V$>U&z$%"%"#*#O<"#e#>1W+}11z 1`i:B=-1)=(1<0ͼ<͔=1@=::8=1ȗ+w+w<͔ʼe1>Z3<͔ʼZ3<"͔ʼOZ3<!͔ʼOZ3S͔<Z3*< 2ͼ<"<,g,͛1'USɗ%'>%'>%'<<;'<4'K'g,1ȗ2e,K,*,7<*,DMF/g,*,͸,`i",>a('Gyʀ'Ͷ4---> !=͓x5:o'>5͡4^C=abort,^X=next file,L=next line,=next page>5>2(ͪ4x' (a('_(x5'4<͡4press RETURN...4>N͉ t9<>=2(x53(:o2(446 L3(!H(Ú9R(W(<\(R(>(>(>N2((2(+>ͺ:l,2(!("/"(!"(*<"(*, "(>(U/"(®(t(*,O<",*tڨ(!/"(>2(!;<~#"(:l,2)>͗+J**, "(*+-!I-ͭ."-!I-[-G3!1O+},-2-y!`O #[-332.<2'32.>::~ʰ-͟7 # 6> 2<5ʙ-|™-}*kҙ-2.6ʯ-@O:j".+q# -*?-.- ڴ-3;-ô-xʴ- y-xʴ--w#.x >?-> H99>?:.>2<+:#>>;7#Pd.12Ͱ4File exists-delete it?h4>P͛12U2KU.2w.)2US>M<2!=ͭ.ɗÕ.> !=ͭ.>::#6ͼ 2<2@w#i&I6;76:#:>.:# .ͺ:<~#Ͷ4No room for: d$<[#*&}>fG#Ͷ4No directory space for: #*H$"#*%O<#e#V$>U&!2# !>2j%U2$V$ʘ#Ͷ4Replacing: ç#Ͷ4Adding: "*$U&!=͘7;d$ q#p###"$4$=)2*,DM!"6$>+2$:.G3ͺ+:,G3$($+"<*#>ͱ**6$"6$($#!>U&q#pz$%%;332(3:I3< ͔2I3<ͼ<2I3_ ÔG:8=0yu3xn3u3|y| d4:|<"A4{<")4{<"04{<"3|Ÿ3}=!I<Ҵ3DM)ң3`i÷34+}¾3#"3# 43!O<33 43!O<33*34þ3|g}o#4:g4A4!4;4;4J4 :f4-7J4͋9YͶ4No>N>5>2ͪ4ö4ͪ4ͼ4 o9ö4͓͓43;>́:42S=.:C5~>5~͆>5#4> 4͗+(S>*,DM8)/)**5)!)#",*,;<>RS*, ~2)")`i>(<> <"):l,͗+*,:gG~})#p)>F:g<͗+<:*g98PYO<گ)><> <³)>ڳ)ʳ)>MDMO<)BKe<*,s#r`i",!:)=$:)[-2,G3:<>,.K,9,,*,N8g,!$9:l,͗+>2e,*,DM*,!",J*<F*{><<2*]*"*",`i",*,}DM*,*,O<><>M;ҙ*2!3͋1,,*,DM*,O<",Ҿ*"*`i",BK*,*,g,*2!3{1*g,͸,:<,*<*,> 2-/#~?/?/>2-/~=/#PY:>< #~?A/6/`i>(t×/ʹ/=2/>////>==2/:/2/O! "/O>/70O>=2/yO! 0##^#Vz/y2/z&0{/*/O<>70>J<2@2T0@ͳ0Ͷ4Drive : Total *I=T]*E=#zW{_u0+j0:B=ʆ0)=~0Ͷ4k, Used O<Ͷ4k, Free Ͷ4k<21:8=00*<*<22=_.͔D^#V2<0`Z30><<͔*E=#--new name existsï$<2<͏.Ͷ4 to ! ͼ:͏.ï$A%7 <2%:.\[-2.e¤%!#"%!"%ò%!#"%!"%l%s#r#l%"%DM"%y>U!}+"%!^#V#"%!O<*,DM"&|&"/&<~ k2<~!&n&<##d&^#Vr+swÊ&+> <*,!&ʙ&<##Ï&4Ÿ!Aj; >9~ʼ&ʾ7#&y&~&&# &<<*+*B+w*D++}K'*,#"2g,!",",3͋12g,:,́.<ͬ<*,*,"B+*,O<"D+ͼ<33:l,2v+ :gj+͗+G3ù2y͗+W+*h,~W+! ~###~1)2wwW+:e,K,2l,,,ȷ:,G3:gO*<9,N8O ,N8*h,\$͋9<*,DM!",*,:",ͼ<*,*,*,O|,O:g,>Bɷ!+ "b,!++ ",v<"h,8 ",2!͞:R1<#22!͞:j1<2#!"-*-#"-< -[$  #~55#N#65 ͆S5:2:2::2O:<͆9É5*5++"5ͫ5##"5qܨ<#6+ ͔^#r{ͬ<=I6Ó՗2F6͌:A62ͼ<"k6:<O͜;}Q6{0:j6!w#"k66~ͮ9#v6+Ͷ6"6W>~ʧ6ʥ6#ͫ6ʎ6Ͷ6y~6 #ͫ6¶6Z:;7.*>.ͥ:] > !I.] ~#4 :\=29.!I.]NT ͙!]I. 怶w#\ !\n. `:.G:9.ʅ  r À@ Squeeze, Unsqueeze or Reverse (S,U,R)? 2.S U R€> 2D.9:.2:. a!͈4~+Fƒ x2:.:D.O :.G:9.O ::.G:;.O @ Skipping, same drive & user --> à :D.s ʊ @ Copying --> Þ @ SQ/USQ --> Þ @ Setting --> @ to :D.) !o. ~ #» !w. ~  ~ # e ~Q# ~w#;OyO}o|g,;g}!o;a{ շ^;_2e;DMd;j;I;W:e;2e;I;!g;>՗2;>)ܔ;yOxG҈;ܔ;=v;:;><2;?y";}|;3333x;՗yOxG{_zWñ;z;}o|g!";é;*;<`ite? Y:e2e\\_* .*.{ozg))))xV~# xL* .+" .*.,+".@ Erase Tagged or Untagged files (T/U)? TʤU€T>ʬ2 .@ Do you wish to be prompted (Y/N/A)? ʀAʀNY>¯24.!".͈4~G: .f@ Deleting ---> :4.W@ Delete (Y/N/A)? AzYfʃ;h#* .#}z+,!".À!".Ü ~6ʩ#*1."1.*/."/.*/.@K (*1.@K).*.͈4͌u@ Tagged files = *.͈ͩ;[SAS<2$7e<͘7=/O>9:3;287̈́<>U~3;G3;#<(<)=U7"f7!N#F# ͌:{7 bk ͑7ü:͘7 ͌:ò:͌:ü:.:ü:|< xʼ7:#zª7<:`:88*Mm8*8*hOTDM#"8*8 w#s#r8e<"<#9ʼs#rÐ828"88*8;<><#|<8#98"8v<>8O<8"ÿ8ê8!}!#~#8~ 9 1 2 3 4 R/W R/O SYS ARC :9.AQ:;.< ::.o& G >:Q:.e @ with CRC.:D.z ʴ } z 6ʜ #* ., 9ñ @ --- Aborted ---ÀH. `~6`2:.d!I.o. ~ww# H.!I. `} !͈4~3 @ Retagging --> > Q4͌#* ., À"@(~#a QS @)~ Q#j ".͵ *."".*. v,­ *.:.U$ R$ *.:.Rʽ U !0͂#*. 0!H.n. 6`!w.~ 6Q#6Q#6Q@(!o.j >.QkNSWP is copyright (c) 1983 by Dave Rand 10232-160 Street Edmonton, Alberta (403) 484-4114!9"1=*."7.2.2. 2.2.2. 0ڱ2.-!]. `>?!" .".!^#6#6!M ͼr@Drive :.AQ:.<>*Q>? =__o&S2.@:!.]@ !" .#"+."-.w!=.͊}+h#" .!e2*.+" .#͈".!"."/."1.1=:.2:.d* .#}»@ No files.XL'SʪÀ9*.͈dG!!5~ȸ###^#V:._:.__1*-.u4~6#*1.~"1.*/.~"/.@ New drive/user/mask? @!!~ʀ#">.:\`:.<=2.:;.y#~*>y:.2.:] ‘!]^ 6?`!\. `992.~ʸV#ª2.@ Illegal drive code.Àͥ:.2;.:.29.~0ں:AںQҺA29.#~:ȷ*:0:'G#~:33036302;.x 2;.>2;.! !!^#6#p#~iwV@ Copy to drive/user? @!!~ʀ r#:D.::.G:;.ʧ:9.G:.@ Can't copy to same drive and user.À*.͈2H.I. `~2:.@ Copy to (;<#8++~<2$9~>269bk",9<>=2$9!##",9>v<<<<:*g9< O<*g9O<`9"g9<>M!"g9>Æ>́:>N:> Æͼ<͙<~w#_N::ͼ<_ 9 9 9:9=ü9 9 9>9><29ÔW:d 9999 y:2:͙<6#;;O~*:<#:<#2:yͬ<*:Q9x2.rÀ@ Which flags (1-4,R,S,A)? @!o. 6#L!!~ʀ#">.*>.#">.ʊ!o. ʄ#w_>_> 1234zzzzRSA@ Delete file? Y€*.;À͈]2\ `6`__^_:e!@ R/O. Dele%  j @)s*.!H.͘'}0!0D C @ Not a SQ file.">."B.:;.2;.!\n.6 `s!"| _h *B.,}0@ ERROR - Checksum error in file nngo͵ @ Premature EOF on file... aborted.À0*:9.G:.::.G:;.ȸ!H.n. `2n.!"@.sd*."5.:.–H.l"5.*7.,ܺCͺ}0 |g}o{))))))),*.*7.~y|±}ڳ.&],H.͇"5. ||¥ͺÖ͏ʀl&)o$#:*.ZK<}>o}}o}}o}#~#`a{_:._<ʀ0`:02*."0L L* .9ͩ9L*>.!\w=L!\*>.:. O0O:77:.Lx,yH,py2;.ͷr#*b6?dwQͷyh#6 r.¢ͷʢ#*’6?ÔwͷʩØ#6 ¢#6«">. =_.:;<> !.!yg)>g>!or$sR!mI. `H.!)))))*. T.`H..ý@ Directory full.À<¨!=!o `*7.,@ OUT OF MEMORY?<¨i`@ Old name? @!!">.!.:. ʀ:;.2 .@ New name? @!!">.!n.:o. ʀ9!͈.¢@ Renaming -->  ~2:.@ to !mG:2#* .,R9>. r~ F: .?G># ɯ/o.m> ?,n.Y*$.,*&."$.*&.*$.~}yC#|N}P.],n.V͏%* .*".,ʂ~#"".d*.""." . :.H.¼* ." .—n*".* .,n= ,*".H.͏*"." .n͏ʀl&͇*"." .ü* .!==~V# `~##~#~  x$>[I* .".+|*.|ȯ|g}o".„#".* .+}o|g".!".*.".*.*.".*.*.}o|g".á*.#".*.,oÛ*.͈".*.͈". ~O͇"5.l:.@ Verifying --> R!z.{.6`n..!]~ ʀ ~ µ6?#­@ !/€".À@ Tag what? @!!">.!]~ ʀ@ !/%# :.~#, *@.O!. ~W$^"@. @ ~#Q@ _{dldr_!u! ~#G~d#z))))= NSWEEP - Version 2.07 07/17/1984 (c) Dave Rand, 1983, 1984 Edmonton, Alberta $ A - Retag files | Q - Squeeze/Unsqueeze tagged files B - Back one file | R - Rename file(s) C - Copy file | S - Check remaining space D - Delete file | T - Tag file for mass E - Erase T/U files | U - Untag file~#=:;.::.:.AQ n&} 5 >:QyJ> Qͧ>.QͧJ*.#@. #~#> Q@K : ʢ*ʢ#yQ~Q#§9>2=.92=.<23.@Press ^X to abort, L to advance a line, cr to advance a page. >2<.*.͈ v,!nD*."".!0D D9!"L*.""."bnu>-_ ‚:3.<23.:<.O:=.O:3.G:OLʹlʹ23.O:3.=23.O0ÀO iiX!T.U.## *.*.Fwx# |}!".".#".* ." .Q͟h*.".#".* .+" .|E*.͈*.`*.#".*.͈".*.͈". #•*.~ F. x:.?G># ɷ!"-.* .#}!=*-."-. x',?,$?d,2?} =?yRR> Q=G ] |S{0Q }0*0#*0~.Ҙg xʩ|-“#Ï}o|g:*.ʽ)=õ"+.:._.*:GxG|g}o ý^)))))#~&o)))€@ Tagging --> ͈> Q4͌#* .,J͈]N/> ~?\#Q*.͈ ~2:.@ New name, or *? @!!">.!l#~ ʀ ?#¡:;.¶::.w*.͈. r*.* .#" .e2*.+" .".,ڀ!".À:.29.\2\ `d:e9:e2e:u2u\:;._::.F__!mI. `2H.H.*.͊}ʒ@ Destination file exists! rÀ:;.ʢG::.::.___\__!m `::.__!\H. `2H.>?2T.*.H.͊}ʽ" .H.6`H.2H. `~2:.d*.""." .H.<@ Can't open file!À__:9._:;._ :._::.^*."&."$."(.R"n.<:w.ʻ:w.2w."!w.E.`6$#6$#6$ ""<@ Destination disk directory full.À!z.{.6`dH.<@ Can't close file!ÀRn."Rn.<=m"!n.~.`!E..`n.<=!E.w.`:Q.G:w.2w.:y.2y.n.*(.*$.G,xw#"$.*$.*&.,R:.&   F - Find file | V - View file L - Log new disk/user | W - Wildcard tag of files M - Mass file copy | Y - Set file status. P - Print file | ? - Display this help X - Exit to CP/M | cr, sp - Forward one file $"x#"z#!9""c#v]#>2t#2w#c#"~#*x#n͝"Gp#Œ"<"c#"#]#c">*z#"|#|ʓ"c#s#r#c#s#r#*|#+h"1>*x#*~#a{_USQ section (C) 1983, 1984 by Dave Rand (403) 484-4114!9"":w#"=2w#:v#### NULU.DOC Documentatio fo NULU.COM a o 02/01/85 Versio 1.1 NULU.CO an NULU.DO ar bot Copyrigh 198 an 1985 b Marti Murray P.O Bo 35972 Dallas T 75235 Bot ma b use freel fo non-commercia purposes bu neithe ma b sold include i packag fo sale o use a a incentiv t buy b an person organizatio o corporatio withou prio arra+#%>26,:*!5,4!'>28,#%~!,͍+~2;,&! ,̈́,2+*+))>͍+ ,",!",!,͒+~w6#w#w#w͒+̈́,!+̈́,*+* ,ͨ+>Ґ'*,* ,:+ʡ'"D,!9",1,!v(*+(!͡+"+*D,#~ ')#'>.)x͍+~ ')#')*+())*+~)#z(2+2+>2+c+v(c+(!+Y(#45v(~6J(G+~(=(v(>(<(v(v(#4~(>(~6(:+2+((:+ʑ(>(<(>́+###(:+ʰ(G:+¨()>2+*+|>(*,((́+F#^#V:+O{_zW:+ ()2+(y2+}P-A~w#-y2V-*R-DM*P-*N-#:V-=2V--?,*P-*R-"P-"R-,7H-*P-xH "-!- "-i`)))#"-A!-6#„-A*-+~w-kbA+~w›-Һ-*-!-Aw#°-!-5Œ-#455Ì-#>==2w#:v#2v#:u#O:t#.#nŒ"O>=2t#yO*z#=###^#Vz#y2u#z>Z#{/|}nŒ"nŒ"go>2+"B,!9",1,*B,}o>͍+"+">,"@,&+2+W+#>Ð'vͨ+#>Ð'}2++|#c+?$!+$#456$~6 $G+~+#6$>+<+6$6$#4~#>+~6+:+2++#:+Q$>+<+*>,^#V#N#zl$#V$>Ð'~*@,w#s#r#q#"+>2+#^#V#N#~#2<,{$:+G*@,#ͮ+ڶ$####Ÿ$y2=,$*+y2=, }O|GT]+++:<,w#s#r#:=,w*+####"+:+<2+„$:+!*ngemen wit蠠 th堠 copyrigh holder Marti Murray Furthermore Marti Murra wil bea n responsibilit fo losse resultin fro th us o inabilit t us thi program NULU.CO͠ ma no b distribute withou NULU.DOC no ma th copyrigh message b remove fro eithe fil no cause t no b displayed. ACKNOWLEDGEMENTS Thi progra woul no hav bee possibl wer i no fo th elegan wor o Gar P Novosielsk an tho)|:8,I):+*+*+G:+Os#r#}0) z:)`)%)"+"+y2+!+4~`)2+!+~w:*=Gp)>':8,~):7,¤&!*p:8,#%28,27,#%́+:+w#*++2,,+!"," ,,!,e- ,!,͒+:+!$,͍+4!+5:8,)*+6:+O})7zW{_~*A+~+}* *~)*s#r*+/w#6#"+}!+4>́+###!I*͗)*+>+w+,կ++ä,**x!+4#%45 %%%#%!*p27,28,l*g2+2+<27,29, '>29,! ,,ͻ+&29,!,:5,͍+::,Nw:6,/< 'G:;, '4x26,&!$,,+!,:5,͍+~2:,:6,&w:9,#%! ,,4#4#4++*o&))*>,4#4#4ɯGO*>,w#w#w#q# ,+!+w#w#w#w#!+++!"+c+oc+gnk+*+͍+"+!+4#4#4*>,G͍+x͍+xo$շ#•+}o|g|}##~+~+~H + +x ~#+x ~++yxX+G]T~w+”,kb ,xG-"L-"N-Hi&)))#"T-!W-^-Aw#,!W-"P-!^-"R-*N-A#,C-A*L-~w#,!T-5,#5G-*'  s other workin wit th L librar structure. Additionally woul lik t than th peopl wh hav supporte th developmen o NUL i variet o ways fro suggestion t financia젠 contributions Al젠 comment (good ba䠠 an disasterous ar welcome Specia thank t Keit W Antclif o Mead Washingto fo hi developmen o NULUTERM.ASM patche overlay an t Ro Fowle o Nightow Softwar fo hi graciou permissio t includ MLOAD23.CO i th NUL rele on i tha i librar fil i los o damaged al o th membe file ar los a well Th solutio t thi proble ca b summe u i on word BACKUP NULՠ probabl isn' perfect an w al kno tha dis system aren't s backu you importan libraries please ɠ don' wan t hea an sa stories. Almos a importan a backin u librarie i th us o discretio whe decidin wha t pu int them Let' fac it i fil i i librar i i Numerous user patches DIFFERENCES BETWEEN NULU AND LU NUL no support L styl CR verification However becaus o m desir achiev a orderl transitio betwee th ol an ne versions NUL 1. wil no verif CR value fo member whos initia value wer 0000h I othe words i yo us NUL 1. t ope librar las change b NUL 1.0 CR erro wil no b th firs thin tha yo see Afte changin th librar wit NULՠ 1.1 i th diring o execution o ma b extracte fro th librar t assum th statu o stand-alon fil onc again. Th reason fo doin thi ar many Fo one unde CP/͠ eac fil occupie minimu amoun o dis space Thi amoun ca rang fro 1 t 16k dependin o th system Eve thoug fil ma onl b byt i length i wil stil occup th minimu require amount th res o th spac i wasted Puttin thes file i librar minimize th poas library. Honor fo Courag g t Denni Recl an Sig Kluge fo havin th gut t "ris everything b testin NULՠ an offerin suggestions and pointing out bugs. INTRODUCTION NUL i complet replacemen fo L an LSWEEP Weighin i a 15k i include al feature o bot program an the some I features: Tw operatio mode wit ful men fo each L styl CR suppor an verification Viewin an printin o membe f no a eas t ge to I yo nee t ge t fil ever 1 minutes i probabl shouldn' b i librar excep a backu measure. A ASID CONCERNIN FILESPECS Whe specifyin filespec wildcard ma b use freely however unlik mos programs NUL doesn' insis tha ". separat th filenam fro th filetype Fo example th filespe "** mean th sam thin a "*.* t NULU O th othe hand th filespe "FRED.TXT sector CR doe no matc th nex tim th librar i opened a erro messag wil b generated Th assumptio behin al thi i tha th likelyhoo o fil havin CR o 0000 i extremel small I versio 1. o NULU al librar member wil "enjoy CR validatio eve i thei initia CR wa 0000h. NULU T th bes o m knowledge NUL wil ru o an syste runnin CP/ 2. o higher howeve i ha onl bee teste bssibl wast t 12 bytes. Eac fil als occupie director entry O mos flopp dis systems th maximu numbe o fil entrie pe dis i 64 B includin fil i librar th director spac i use t occup i free fo anothe file. Additionally usin librar file ca simplif th proces o categorizatio b subsumin severa file o simila type o subject int on file. However ther ar als danger associate wit usin libraries Th maiiles unsqueezin whe necessary Extractio o membe file wit a optio t unsqueez wher appropriate Bigge libraries u t 80 member o mor dependin o availabl memory Automati membe sorting al member kep sorte a al times Faster reorganization Enhanced error handling Access to deleted members Optional read only patch CP/M Plus support General compatibility with LU and NSWEEP syntax m o th Osborn an th Osborn Executiv computers I i writte entirel i 808 assembl language. complet discussio o th natur an advantage o librar file i beyon th scop o m endurance howeve shor reca i i order. librar fil i singl CP/ fil whic maintain o mor smalle file a it members Eac fil i writte int th librar an recorde i th librar directory Afte that i ma b accesse fo viewing print