TD^ֈ)b,Ampro Z80 System Source Code - #1   d -A60102 F  QAD-3-3 ASMU CFG-2-6 ASMQCRC CRCDIR COMDT-1-0 ASME !"#$UES-2-3 ASM7%&'()*+,-./0MD-2-4 ASM123456789:;<=>?@MD-2-4 ASM`ABCDEF4MF-2-3 ASMGHIJKLMNOPQRSTUVMF-2-3 ASM?WXYZSC-2-2 ASMS[\]^_`abcdefghSET-1-0 ASM$ijklmnopqrsSG-3-3 ASMtuvwxyz{|}SW-2-0 ASM~SW-2-0 ASM4HYTM-1-0 ASM84DF-1-2 ASMDF-1-2 ASM2u * * *  &DISKETTE MAINTENANCE UTILITY * * qTO FORMAT, VERIFY AND COPY AMPRO DISKETTES * * COPYRIGHT (C) 1983, 1984, 1985 AMPRO COMPUTERS, INC. * * * ; assemble with asm.com or equivalent. there is no z80 code. VER EQU 33 ; REVISION HISTORY: ; ; Version 3.3 12 Dec 85 Changed SETUP and READY routines to ;  work better with microfl oppies. ; & Added interrupt disable/enable so ; can be used with future s/w rtc code. ; ; Version 3.2 24 Jun 85 Changed cmds to FDC to use proper step ; rate if 2.x+ bios. ; ; Version 3.1 21 Feb 85 Changed prompt & display routine to get ; real unit # (version 2.0+). Removed ; warning message of 12-dec-84. ; ; Version 3.0 12 Dec 84 Added warning message when used with ; hard disk bios. ; ; Version 2.6 10 May 84 Cleaned up one more response. ; ; Version 2.5 8 May 84 Cleaned up the responses so that only ; characters of interest are acted upon. ; ; Version 2.4 5/3/84 Added 10 ms delay after any line feed. ; Only ESC or CTLC will exit the program. ; ; Version 2.3 3/20/84 Increased restore timeout to 5 sec ; ; Version 2.2 Delayed step until after index pulse ; due to apparent 1770 problem resulting ; in improper stepping ; ; Version 2.1 Added motor on delay to restore command ; ; Version 2.0 Initial release YES d cr equ 13 lf equ 10 DISPLAY$FDEV: lda lb$vers cpi 20 rm LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call lb$get$ldte ; Get address of unit id MOV A,M ; Get unit id CPI 01 ; Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; . ani 03h ; mask out excess bits MOV l,a ; update floppy device number mvi h,0 ; . dad h ; x2 xchg LXI H,FNAMES ; . dad d ; x2 dad d EQU 1 NO EQU 0 RAW EQU NO ; wd1770 equates REST EQU 00 ; slow restore RDSEC EQU 88H ; read sector command WRSEC EQU 0A8H ; write sector command WRTRK EQU 0F8H ; write track command STEPI EQU 58H ; step in command RDID EQU 0C8H ; read address command MOT EQU 80H ; motor on status WPR EQU 40H ; write protected status SPU EQU 20H ; disk at speed status (type i) TYP EQU 20H ; record type status (types ii and iii) RNF EQU 10H ; record not found status CRC EQU 8 ; crc error status ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lda unit ; adi 'A' ; sta d$current ; LXI D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTR: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? jm D$NEXT$FDEV ; No -- go do the next one RET unit: db 0 D$FDEV$HDR: DB CR,LF,'FLOPPY DISK ASSIGNMENTS',CR,LF DB 'CP/M drive ' DB 'Floppy disk',CR,LF DB ' --3',CR,LF,'$' D$FDEV$LIN: DB ' ' D$CURRENT: DB TK0 EQU 4 ; track zero status (type i) LDT EQU 4 ; lost data status (types ii and iii) IDX EQU 2 ; index status (type i) DRQ EQU 2 ; data request status (types ii and iii) BSY EQU 1 ; controller busy status ERRII EQU WPR+RNF+CRC+LDT ; type ii error status mask ERRIII EQU WPR+LDT ; type iii error status mask CMND EQU 0C0H ; fdc command register WTRK EQU CMND+1 ; write to track register WSEC EQU WTRK+1 ; write to sector register WDAT EQU WSEC+1 ; write to data register STAT EQU WDA 'x ' D$EDISK: DB ' ' D$EBLANK: DB ' ' D$FNAME: DB ' ' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' ; end of DISPLAY$FDEV TO$UPPER: CPI 'z'+1 ; Convert to upper case JP UPPER$ALREADY ; . CPI 'a' ; . JM UPPER$ALREADY ; . ANI 5FH ; . UPPER$ALREADY: RET ; and return GET$BIOS$VERS: LHLD 1 ; Get start of bios jump table LXI D,LB$BIOS$TBL ; Move bios to local storage LXI BOT+1 ; fdc status register RTRK EQU STAT+1 ; read from track register RSEC EQU RTRK+1 ; read from sector register RDAT EQU RSEC+1 ; read from data register CONT EQU 0 ; system control port ROMOFF EQU 40H ; turn rom off SID0 EQU 0EFH ; mask side bit off SID1 EQU 10H ; side bit in control register SDEN EQU 20H ; single density bit in control register TRY EQU 3 ; tries TRYHARD EQU 10 ; we try harder MSEC EQU 167 ; constant for 1 ms delay CTLC EQU 3 ; control c CR EQU 13 ; carr?,LB$LEN ; . (length of bios area) DB 0edh,0b0h ; . (LDIR) MVI A,0 ; Test CP/M version CALL LB$GETNXT ; Get next jump table STA LB$VERS ; Save bios version INX H ; See if HL is 0FFFFh MOV A,H ; . ORA L ; . RZ ; If so, then old version DCX H ; Fix HL as it has the table addr LXI D,LB$XTBL ; Move extra table to local storage LXI B,LB$XLEN ; . (length of extra table) DB 0edh,0b0h ; . (LDIR) MVI A,0FFH ; Set NZ to indicate bios ORA A ; ... version 2.1+ RET ; ... and iage return LF EQU 10 ; line feed ESC EQU 27 ; escape key UPCASE EQU 5FH ; upper case mask ORG 100H start: lxi sp,stack call clrsc call get$bios$vers mvi a,16 jnz new$sys lhld 1 mvi l,5ch mov a,m jmp plugem new$sys: push psw mvi a,0 lxi h,jplug1 mov m,a inx h mov m,a inx h mov m,a lxi h,jplug2 mov m,a inx h mov m,a inx h mov m,a pop psw plugem: adi '@' sta plug1 sta plug2 inr a sta cplug1 sta cplug2 jmp doit ***** bdos equ 5return. ; Replicated BIOS to make direct calls easier . . . LB$BIOS$TBL: LB$WBOOT DS 3 ; Warm boot LB$CONST DS 3 ; Console status LB$CONIN DS 3 ; Console input LB$CONOUT DS 3 ; Console output LB$LISTOUT DS 3 ; List output LB$PUNCH DS 3 ; Punch output LB$READER DS 3 ; Reader input LB$HOMDSK DS 3 ; Home disk (move to track 00) LB$SELDSK DS 3 ; Select disk drive LB$SETTRK DS 3 ; Select track number LB$SETSEC DS 3 ; Select sector number LB$SETDMA DS 3 ; Set DMA address LB$DSKREAD DS 3 ; Dis k read LB$DSKWRITE DS 3 ; Disk write LB$LISTST DS 3 ; List status LB$SECTRN DS 3 ; Sector translate routine ; AMPRO-specific BIOS calls LB$GETNXT DS 3 ; Get bios ver & next tbl address LB$GETEDSK DS 3 ; Get pointer to E-disk storage LB$IOINIT DS 3 ; Set new I/O parameters LB$SCSIDRV DS 3 ; SCSI direct driver LB$LEN EQU $-LB$WBOOT ; Length of bios table LB$XTBL: ; 'Extra' table definitions ... LB$SWAP$DRV DS 3 ; Swap two logical drives LB$GET$WDP DS 3 ; Set/get win drive parameters LB$PHYTABg side 96 tpi' db cr,lf,' 4. Double side 96 tpi' db cr,lf,lf,'Choose one (1, 2, 3 or 4). $' ASK2E: CALL CONIN ; get the answer CPI ESC JZ EXIT CPI CTLC JZ EXIT CPI '1' ; less than 1? JC ASK2E ; error return CPI '5' ; more than 4? JNC ASK2E push psw call conout pop psw ANI 0FH ; mask hi order DCR A ; 1 side = 0, two sides = 1 JZ SS48 DCR A JZ DS48 DCR A JZ SS96 DS96: STA TWOSID STA TPI96 MVI A,16 STA SBIAS ORA A RET SS48: STA TWOSID STA TPI DS 3 ; Set/get phytab access LB$GET$LDTE DS 3 ; Get logical device table entry LB$RESERVED DS 3 ; Reserved entry LB$XLEN EQU $-LB$XTBL ; Length of extra table LB$VERS DB 0 ; Bios version number doit: CALL ILPRT ; print following text DB CRn,LF,' AMPRO Copy/Format/Verify Utility' DB CR,LF,' Copyright (C) 1984 AMPRO Computers, Inc.' DB CR,LF,' Version ',VER/10+'0','.' DB VER MOD 10+'0','$' ASK1: CALL ILPRT ; print following string DB CR,LF,LF,'COPY, FORMAT or VERIFY?$96 STA SBIAS ORA A RET DS48: STA TPI96 INR A STA TWOSID MVI A,16 STA SBIAS ORA A RET SS96: STA SBIAS STA TWOSID INR A STA TPI96 ORA A ; reset error flag RET ASK3: LDA TPI96 ORA A MVI A,79 JNZ ASK3X MVI A,39 ASK3X: STA MAXTRK ORA A RET ASK4: CALL ILPRT DB CR,LF,LF,'Source drive? (A - ' plug1: DB 'x) $' ask4e: call conin cpi esc jz exit cpi ctlc jz exit ani upcase cpi 'A' jc ask4E cplug1: equ $+1 cpi 'E' JNC ASK4E STA ASK40 pusD (C, F or V)' DB CR,LF,'Press or ^C to quit. $' ASK1A: CALL CONIN ; get response CPI ESC JZ EXIT ; exit to operation system CPI 3 JZ EXIT ; ctl c ANI UPCASE ; force upper case CPI 'V' JZ SETV ; if verify CPI 'C' JZ SETC ; if copy CPI 'F' JNZ ASK1A ; otherwise, do this again ; set function code and do it SETF: MVI A,1 STA FUNC JMP FORMAT SETV: MVI A,2 STA FUNC JMP VERIFY SETC: MVI A,3 STA FUNC JMP COPY FORMAT: CALL CLRSC CALL ILPRT DB 8,32,CR,LFh psw call conout pop psw sui 'A' jplug1: jmp ask40s call lb$get$ldte mov a,m cpi 01h jnz ask4 inx h mov a,m ani 03h ask40s STA SDRIV ; source ask40E: CALL ILPRT DB CR,LF,LF,'Place source disk on drive ' ASK40: DB 'a',CR,LF,'Press to continue, to quit.$' ask40h CALL CONIN CPI CR RZ CPI ESC JZ EXIT CPI CTLC JZ EXIT JMP ASK40h ASK5: CALL ILPRT DB CR,LF,LF,'Destination drive? (A - ' plug2: DB 'x) $' ASK5E: CALL CONIN ; get the answer CPI ESC ,LF ; overwrite response and make new line DB 'FORMAT prepares a fresh diskette for data or program storage.',cr,lf,'$' call display$fdev CALL ASK5 ; ask destination JC ASK1 ; restart if bad selection CALL ASK2 JC ASK1 CALL ASK3 FORM0: CALL ASK6 ; give warning JC ASK1 CALL EXEC ; do it JMP ASK1 ; restart at end of format VERIFY: CALL CLRSC CALL ILPRT DB 8,32,CR,LF DB CR,LF,'VERIFY checks the reliability of data on a disk.',cr,lf,'$' call display$fdev CALL ASK5 ; ask f JZ EXIT CPI CTLC JZ EXIT ANI UPCASE ; force upper case CPI 'A' ; first valid drive JC ASK5e cplug2: equ $+1 CPI 'E' ; first invalid drive JNC ASK5e sta ask60 push psw call conout pop psw sui 'A' jplug2: jmp ask50s call lb$get$ldte mov a,m cpi 1 jnz ask5 inx h mov a,m ani 3 ask50s: STA DDRIV ; save drive designator CALL SETSEL ; disk select bits ORA A RET ASK6: CALL ILPRT ; print the following string DB CR,LF,LF,'Place destination disk on drive ' asWor destination disk JC ASK1 CALL EXEC ; do it JMP ASK1 COPY: CALL CLRSC CALL ILPRT DB 8,32,CR,LF DB CR,LF,'COPY creates a duplicate of a disk.',cr,lf,'$' call display$fdev CALL ASK4 ; ask for source JC ASK1 CALL ASK5 JC ASK1 CALL ASK6 ; give warning JC ASK1 CALL EXEC ; do it JMP ASK1 ASK2: CALL ILPRT ; print following string DB CR,LF,LF,'Formats Available:' db cr,lf,' 1. Single side 48 tpi' db cr,lf,' 2. Double side 48 tpi' db cr,lf,' 3. Singlek60 db 'x' DB CR,LF,'Press to write, ' DB ' to quit. $' ASK6E: CALL CONIN ; get answer CPI CR RZ CPI ESC JZ EXIT JMP ASK6E EXEC: CALL ILPRT DB CR,LF,LF,'$' LDA FUNC ; function 1=fmt, 2=vfy, 3=cpy CPI 1 JZ FMT CPI 2 JZ VFY ; else fall through to cpy CPY: MVI A,0 STA HEAD MVI A,39 STA MAXTRK LDA DDRIV ; destination CALL SETSEL CALL SETUP LDA SDRIV CALL SETSEL CALL SETUP MVI A,TRY STA TRIES CP0: CALL READID JZ CP1 LXI H,TRIES DC  RR M JNZ CP0 CALL ILPRT DB CR,LF,LF,'COPY failed. Cannot read source disk.',CR,LF,'$' RET CP1: LDA IDSV+2 ; sector # CPI 17 ; two-sided if no carry MVI A,0 JC CP2 INR A CP2: STA TWOSID ORA A ; reset carry RAL RAL RAL RAL STA SBIAS XRA A ; get a zero STA TRACK CALL SETDSK CPYLP: CALL KEY LDA HEAD ORA A PUSH PSW LDA SDRIV CALL SETSEL POP PSW LDA SELBYT JZ CPL0 ORI SID1 CPL0: OUT CONT ; select destination STA SELBYT LXI H,RDMSG CALL PRINT CALM: CALL WRITRK JZ NT2 LXI H,TRIES DCR M JNZ NT3 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT failed.',CR,LF,'$' CALL REPORT RET NT2: IF RAW LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES NT4: CALL READTRK JZ NT5 LXI H,TRIES DCR M JNZ NT4 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT failed. Bad destination disk.',CR,LF,'$' CALL REPORT RET NT5: ENDIF ; RAW LDA TWOSID ORA A LDA TRACK JZ NT0 LDA u|L TMRPRT cp14: MVI A,TRYHARD STA TRIES CP3: CALL READTRK JZ CP4 LXI H,TRIES DCR M JNZ CP3 CALL ILPRT DB CR,' ' DB CR,LF,'COPY failed. Unrecoverable read error on source disk.',CR,LF,'$' call report call ilprt db cr,lf,'Try again? (Y or N) $' cf002z: call conin ani upcase cpi 'N' rz cpi 'Y' jnz cf002z call ilprt db cr,lf,lf,'$' jmp cp14 g CP4: LDA HEAD ORA A PUSH PSW LDA DDRIV CALL SETSEL POP PSW LDA SELBYT JZ CPL1 ORI SI]HEAD ORA A LDA TRACK JZ NT1 NT0: LXI H,MAXTRK CMP M JNZ NT1 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT complete.',CR,LF,LF,'$' IF RAW RET ; finished ENDIF JMP VFY NT1: INR A STA TRACK CALL STEPIN JMP NEXTRK VFY: MVI A,0 STA HEAD LDA DDRIV CALL SETSEL CALL SETUP MVI A,TRY STA TRIES V1: CALL READID JZ V0 LXI H,TRIES DCR M JNZ V1 CALL ILPRT DB CR,LF,'VERIFY failed. Cannot read source disk.',cr,lf,'$' RET V0: LDA IDSV+&D1 CPL1: OUT CONT STA SELBYT LXI H,WRMSG CALL PRINT CALL TMRPRT CALL MAKETRK ; format destination MVI A,TRY STA TRIES CP5: CALL WRITRK JZ CP6 LXI H,TRIES DCR M JNZ CP5 CALL ILPRT DB CR,' ' DB CR,LF,'COPY failed. Cannot write destination disk.',CR,LF,'$' JMP REPORT CP6: MVI A,TRY STA TRIES CP7: CALL WRITETRK JZ CP8 LXI H,TRIES DCR M JNZ CP7 CALL ILPRT DB CR,' )' DB CR,LF,'COPY failed. Unrecoverable2 CPI 17 MVI A,0 JC VF0 INR A VF0: STA TWOSID ORA A RAL RAL RAL RAL STA SBIAS XRA A STA TRACK ; start with track 0 CALL SETDSK VLOOP: CALL KEY LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES VL1: CALL READTRK@ JZ VL0 LXI H,TRIES DCR M JNZ VL1 CALL ILPRT DB CR,' ' DB CR,LF,'VERIFY failed. Unrecoverable read error.',CR,LF,'$' CALL REPORT RET VL0: LDA TWOSID ORA A LDA TRACK JZ VF1 LDA HEAD ORA A LDA TRAA write error on destination disk.',CR,LF,'$' JMP REPORT CP8: IF RAW LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES CP9: CALL READTRK JZ CP10 LXI H,TRIES DCR M JNZ CP9 CALL ILPRT DB CR,' ' DB CR,LF,'COPY failed. Unrecoverable read error on destination disk.',CR,LF,'$' JMP REPORT CP10: ENDIF ; RAW LDA TWOSID ORA A LDA TRACK JZ CP11 LDA HEAD ORA A LDA TRACK JZ CP12 CP11: LXI H,MAXTRK CMP M JNZ CP12 CALL ILPRT DBGCK JZ VF2 VF1: LXI H,MAXTRK CMP M JNZ VF2 CALL ILPRT DB CR,' ' DB CR,LF,'VERIFY complete.',CR,LF,'$' RET VF2: INR A STA TRACK CALL STEPIN JMP VLOOP SETDSK: LDA IDSV+3 CPI 3 JZ SDSK MVI A,39 STA MAXTRK XRA A STA SKEW RET SDSK: MVI A,79 STA MAXTRK MVI A,1 STA SKEW RET STEPIN: LDA TWOSID ORA A JZ STI ; single sided LDA HEAD ORA A MVI A,1 JZ STI0 MVI A,0 STI0: STA HEAD JZ STI1 STI: LDA SELBYT ANI SID0 ; mask  CR,' ' DB CR,LF,'COPY complete.',CR,LF,LF,'$' IF RAW RET ENDIF JMP VFY CP12: INR A STA TRACK CALL STEPIN LDA TWOSID ORA A JZ CP13 LDA HEAD CMA ANI 1 STA HEAD JNZ CP13 LXI H,TRACK INR M CP13: LDA SDRIV CALL SETSEL CALL STEPIN LDA TRACK OUT WTRK JMP CPYLP FMT: LDA DDRIV CALL SETSEL CALL SETUP XRA A STA TRACK STA HEAD NEXTRK: CALL KEY LXI H,FRMSG CALL PRINT CALL TMRPRT CALL MAKETRK MVI A,TRY STA TRIES NT3{side bit off OUT CONT ; select side 0 STA SELBYT CALL WAIT MVI A,STEPI CALL OUTCMD STILP: IN STAT RAR JC STILP RET STI1: LDA SELBYT ORI SID1 OUT CONT ; select side 1 STA SELBYT LXI H,TRACK DCR M JMP WAIT WRITRK: IN STAT RAR JC WRITRK LXI H,TKBUF MVI A,WRTRK ; write track command CALL OUTCMD CALL WR MOV A,B STA STATUS ANI ERRIII RET WR: IN STAT ; get fdc status MOV B,A ; save status RAR ; check busy RNC ; end of command, return to cal ler RAR ; check for drq JNC WR ; if not MOV A,M ; get a byte from buffer OUT WDAT ; to fdc INX H ; bump hl JMP WR ; again MAKETRK: LXI H,TKBUF ; create track image in memory MVI B,60 MVI A,4EH MTLP: MOV M,A ; write gap4a INX H DCR B JNZ MTLP SHLD DMAADR ; sector 1 starts here LDA HEAD STA SIDE LDA TPI96 ORA A LXI H,128*256+2 JZ MTL1 LXI H,3 MTL1: CALL CHGFMT CALL GETSKW ; point hl to skew table LOOP: MOV C,M INX H INR C JZ ENDTRK ; if c was 0clear any trash LHLD DMAADR ; pointer to read buffer MVI A,RDSEC ; read sector command CALL OUTCMD ; to fdc CALL RD ; read the data SHLD DMAADR ; save pointer MOV A,B STA STATUS ANI ERRII RZ POP H ; adjust stack from readtrk POP H RET ; to previous caller RD: IN STAT ; get fdc status byte MOV B,A ; save status RAR ; rotate busy bit to carry RNC ; end of command, return to caller RAR ; rotate data request to carry JNC RD ; wait for data request RD0: IN R|ffh DCR C LDA SBIAS ADD C STA SECTOR PUSH H ; save skew pointer on stack CALL MAKTRK POP H JMP LOOP ENDTRK: LHLD DMAADR LXI B,1000 ETLP: MVI M,4EH INX H DCX B MOV A,B ORA C JNZ ETLP SHLD DMAADR RET CHGFMT: MOV A,L STA SIZE MOV A,H MVI B,4 LXI H,DAT0 LXI D,2 CHG0: MOV M,A DAD D DCR B JNZ CHG0 RET MAKTRK: LHLD DMAADR ; track image PUSH H ; save it LXI H,TABLE ; track format table MAKT1: MOV D,M ; get count INX H ; bump pointer MOV E,MDAT ; get data from fdc MOV M,A ; put it into buffer INX H ; bump hl JMP RD ; again READID: IN STAT IN RDAT LXI H,IDSV MVI A,RDID CALL OUTCMD CALL RD MOV A,B ; get status STA STATUS ANI ERRIII RET WAIT: LXI B,50 * MSEC WT0: DCX B MOV A,B ORA C JNZ WT0 RET WAIT10: LXI B,10 * MSEC ; wait 10 ms JMP WT0 ; wt0 returns to caller LOAD: MOV M,E ; (e) to track buffer INX H ; increment pointer DCR D ; decrement count JNZ LOAD ; again RET CLRSC: MVI D ; get data INX H ; bump pointer MOV A,E ; check for end of table (0ffh) INR A ; 0ffh + 1 = 0 JZ MAKT2 ; if end of table XTHL ; point to track buffer CALL LOAD ; fill track buffer XTHL ; point to format table JMP MAKT1 ; again MAKT2: POP H ; get track buffer address from stack SHLD DMAADR ; save pointer to track buffer RET ; to caller WRITETRK: ; write current track from read buffer LXI H,RDBUF SHLD DMAADR CALL GETSKW ; point hl to skew table WTLOOP: MOV C,M a,24 ; print 24 line feed chars to clear screen CLS: MVI A,LF CALL CONOUT ; out to console CALL WAIT10 ; wait 10 ms after line feed DCR D ; decrement count JNZ CLS ; again RET PRINT: MOV A,M ; hl points to text string INX H ; bump hl CPI '$' ; check for terminator RZ ; return to caller PUSH PSW ; save for test CALL CONOUT ; send byte to console POP PSW ; get the character CPI LF ; if line feed.. CZ WAIT10 JMP PRINT ; again ILPRT: XTHL ; return address to hlnINX H ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C OUT WSEC ; to fdc PUSH H ; save skew pointer CALL WRITESEC POP H JMP WTLOOP WRITESEC: ; write a sector from dma buffer IN STAT ; clear status IN RDAT ; clear any trash LHLD DMAADR MVI A,WRSEC ; write sector command CALL OUTCMD ; to fdc CALL WR ; write the data SHLD DMAADR ; save pointer MOV A,B ; get status STA STATUS ANI ERRII RZ ; return to this caller POP H ; -, point to text CALL PRINT XTHL ; return address follows text RET CONOUT: PUSH B ; save PUSH D ; the PUSH H ; registers MOV E,A ; text to be printed mvi c,6 call bdos POP H ; restore POP D ; the POP B ; registers RET BIOS: LHLD 1 MOV L,A PCHL CONIN: CONINB: PUSH B PUSH D ; save PUSH H ; registers mvi e,0ffh MVI C,6 ; console input function CALL 5 ; bdos POP H ; restore POP D ; registers POP B RET ; The current setup routine doRadjust stack from writetrk POP H RET ; return to previous caller READTRK: ; read current track into read buffer LXI H,RDBUF SHLD DMAADR CALL GETSKW ; piont hl to skew table RTLOOP: MOV C,M ; get sector number from table INX H ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C STA SECTOR OUT WSEC ; to fdc PUSH H ; save skew pointer CALL READSEC ; read the sector RT0: POP H JMP RTLOOP READSEC: IN STAT ; clear status IN RDAT ; yes a restore with the 1772 ; motor on flag enabled. It exits as soon as the BUSY ; status bit goes away, or after a 4 second timeout. SETUP: LDA SELBYT ; get selected drive OUT CONT ; select the drive MVI A,REST ; restore command CALL OUTCMD ; output the command LXI H,4000 ; 4000 ms timeout setup DEL0: MVI C,0 DEL1: DCR C JNZ DEL1 IN STAT RAR JNC READY ; go on if 1772 done DCX H MOV A,H ORA L JNZ DEL1 MVI A,0D0H ; timed out -- force interrupt, CALL OUTCMD ;  then report failure JMP FAILED ; The current ready function checks to see if a diskette ; is inserted in a drive. A read address command with ; the motor on flag enabled is used. If the command ; hangs up, the 1772 is not receiving index pulses, ; indicating the lack of a spinning diskette. READY: MVI A,0C0H ; read address command CALL OUTCMD LXI H,4000 ; 4000 mS timeout setup MVI C,0 RDY1: DCR C JNZ RDY1 IN STAT RAR RNC ; finished, if 1772 done DCX H MOV A,H 2 SDNR: LXI H,DNRER CALL MOV3 JMP RPRT2 SRNF: LXI H,RNFER CALL MOV3 RPRT2: LXI H,ERRMSG RPRT3: JMP PRINT ; print returns to caller MOV3: MVI B,3 MOVL: MOV A,M STAX D INX H INX D DCR B JNZ MOVL RET BINASC: PUSH PSW ; save value PUSH D ; save string ptr MVI A,'0' ; ascii zero STAX D LXI B,2 ; b=0, c=2 XRA A ; a=0 B0: INX D ; bump ptr STAX D ; zero to str DCR C JNZ B0 ; again please POP D ; restore de LXI H,TBL ; conversion table B1: MVI C,0 ; cleadORA L JNZ RDY1 ; loop till timeout MVI A,0D0H ; timeout -- force interrupt, CALL OUTCMD ; then report failure FAILED: LDA SELBYT ANI 0FH MVI C,0 FLD1: INR C RAR JNC FLD1 MOV A,C adi 30H ; add ascii bias STA DRI CALL ILPRT ; print following string DB CR,LF,'Drive ' DRI: DB 'A Not Ready, Insert disk, close door, and try again.',CR,LF,'$' POP B ; adjust stack RET GETSKW: ; point hl to skew table MVI H,0 LDA SKEW ; skew factor -1 MOV L,A ; hl holds sr count MOV A,M ; table value INR A JZ BEND ; end of table, conv done POP PSW ; restore value B3: SUB M ; begin division JC B2 INR C ; keep count JMP B3 B2: ADD M ; restore acc PUSH PSW ; save it MOV A,C ; count CPI 0 JNZ STSTR ; set ascii value in string MOV A,B CPI 0 ; 1st time? JNZ STSTR B4: INX H ; bump tbl ptr JMP B1 ; next STSTR: MVI B,1 ; flag 1st time MOV A,C ; count to c ADI 30H ; ascii bias STAX D ; write it into string INX D ; bump str kew factor -1 DAD H ; *2 XCHG LXI H,SK1 ; first skew table address DAD D ; hl points to correct table pointer MOV E,M ; get lo order INX H MOV D,M ; get hi order XCHG ; hl points to skew table RET OUTCMD: OUT CMND MVI A,10 OC0: DCR A JNZ OC0 ; wait 35 us. for fdc to set-up RET KEY: push b push d MVI C,6 mvi e,0ffh CALL 5 pop d pop b ORA A RZ CPI CTLC JZ EXIT PUSH PSW CALL ILPRT DB CR,' ',CR,'$' ; clear the line ptr JMP B4 BEND: POP PSW ; adjust stack RET ; return to caller TBL: DB 100 DB 10 DB 1 DB 255 ; end of table SETSEL: inr a MOV C,A XRA A STC STSL: RAL DCR C JNZ STSL ORI ROMOFF STA SELBYT RET ERRMSG: DB CR,LF,' Error: Drive ' DR: DB 0,': Track ' TK: DB 0,0,0,' Head ' HD: DB 0,0,0,' Sector ' SC: DB 0,0,0,' Status ' ST: DB 0,0,0,CR,LF,'$' TKMSG: DB 'Track ' TKMSG0: DB 0,0,0,' Side ' SDMSG0: DB 0,0,0,CR,'$' WRMSG: DB 'Writing $' VFMSG: DB 'Verify $' POP PSW CPI ESC RNZ POP H RET EXIT: JMP 0 ; warm boot TMRPRT: LDA TRACK LXI D,TKMSG0 CALL BINASC LDA HEAD LXI D,SDMSG0 CALL BINASC LXI H,TKMSG JMP PRINT ; print returns to caller REPORT: LXI D,DR ; point to error message LDA SELBYT ANI 0FH ; mask upper nybble MVI C,0 ; clear counter R1: INR C ; bump it RAR ; rotate selbit into carry JNC R1 ; again? MOV A,C ADI 30H ; add ascii bias STAX D ; store it in message STA WPRMSG0 LDA STATUS ANI WPRV RDMSG: DB 'Reading $' FRMSG: DB 'Format $' CPMSG: DB 'Copy $' WPRMSG: DB CR,' ' DB CR,LF,'Remove write protect tab from destination diskette.' DB CR,LF,'Place diskette in drive ' WPRMSG0:DB 'A, then press to write or to quit. $' DNRER: DB 'DNR' RNFER: DB 'RNF' CRCER: DB 'CRC' TABLE: DB 12,0 ; defines sector format (#bytes,data) DB 3,0F5H ; write 0a1h DB 1,0FEH ; id address mark DB 1 TRACK: DB 0 DB 1 SIDE: DB 0 DB 1 SECTOR: DB 1 ; is disk protected? JZ R2 LXI H,WPRMSG ; write protected message CALL PRINT POP H ; adjust the stack R1A: CALL CONIN ; get response CPI CTLC JZ EXIT CPI CR ; yes? JZ EXEC ; if so CPI ESC JNZ R1A RET ; get out of here R2: LXI D,TK ; in error message LDA TRACK CALL BINASC LXI D,HD LDA SIDE ORA A ; set flags JZ RPRT1 MVI A,1 RPRT1: CALL BINASC LXI D,SC LDA SECTOR CALL BINASC LXI D,ST LDA STATUS ANI RNF JNZ SRNF LXI H,CRCER CALL MOV3 JMP RPRT DB 1 SIZE: DB 2 ; always 512 bytes DB 1,0F7H ; write crc (2 bytes) GAP2: DB 22,4EH ; gap 2 length, data DB 12,0 ; preamble DB 3,0F5H ; write 0a1h DB 1,0FBH ; data address mark DAT0: DB 128,0E5H ; 128 bytes of data fill DB 128,0E5H ; 128 bytes of data fill DB 128,0E5H ; 128 bytes of data fill DB 128,0E5H ; 128 bytes of data fill DB 1,0F7H ; write crc (2 bytes) GAP3: DB 24,4EH ; gap 3 length, data DW -1 ; end of table (0ffffh) SK1: DW SKW1 ; point to skw1 SK2: DW SKW2 ; 2 SKW1: DB 1,6,2,7,3,8,4,9,5,10,255 ; skew factor 2 SKW2: DB 1,4,2,5,3,255 ; skew 2 (Osborne) FUNC: DS 1 ; function 1=format, 2=verify, 3=copy MAXTRK: DS 1 ; maximum track TWOSID: DS 1 HEAD: DB 0 SDRIV: DS 1 ; source drive DDRIV: DS 1 ; destination drive SELBYT: DS 1 SBIAS: DB 0 ; sector bias 0=ss, 10h=ds, 30h=ds96 TPI96: SKEW: DB 0 ; default skew factor 2 DMAADR: DS 2 STATUS: DS 1 TRIES: DS 1 DS 64 ; space for 32 level stack STACK: DS 2 ; space for ccp stack pointer IDSVI72 step rates in main display ; ;Version 2.5 28 Jun 85 Show options on 1770 and 1772 FDC chips. ; ;Version 2.4 18 Jun 85 Always show "4" drives if 3.0+ bios. ; ;Version 2.3 21 May 85 Duplicated step rate logic to support ; four individual step rates. ; ;Version 2.2 27 Mar 85 Mods to LDTE routine ; ;Version 2.1 22 Feb 85 Added routine to show the floppy drive ; assignments. ; ;Version 2.0 10 Dec 84 Expanded to allow operation with up to ; 16 Logical disk drives. ; ; Added c^: DS 6 ; id save area RDBUF: DS 10 * 512 ; read buffer TKBUF: END START ; end of program 1=format, 2=verify, 3=copy MAXTRK: DS 1 ; maximum track TWOSID: DS 1 HEAD: DB 0 SDRIV: DS 1 ; source drive DDRIV: DS 1 ; destination drive SELBYT: DS 1 SBIAS: DB 0 ; sector bias 0=ss, 10h=ds, 30h=ds96 TPI96: SKEW: DB 0 ; default skew factor 2 DMAADR: DS 2 STATUS: DS 1 TRIES: DS 1 DS 64 ; space for 32 level stack STACK: DS 2 ; space for ccp stack pointer IDSVode in DSKIO routine to get the ; data from Track 1 sector 5 for floppies, ; or from Track 0 sector 45 for hard disk. ; ; Added test during Get From Disk time to ; insure that a System is on the target ; disk. ; ;Version 1.4 7 May 84 : Cleaned up some of the responses, caused ; only the characters of interest to be ; acted upon eliminating action by control ; characters generated by the terminal. ; ;Version 1.3 3 May 84 : Modified to exit on ESC, answer Yes ;  instead of CR. Also add 10 ms delay ; after LF output to console. ; ;Version 1.2 6 April 84 : Modified CONOUT routine to call BDOS ; instead of BIOS ; Added disk written message ; char equates CTLC EQU 3 ; control c ESC EQU 27 ; escape key CR EQU 13 ; carriage return (^m) LF EQU 10 ; line feed (^j) UPCASE EQU 01011111B ; upper case mask ; bdos equates BDOS EQU 5 ; bdos entry RDCON EQU 10 ; read console buffer CONBUF EQU 80H ; console buffer ; bios equates CNIN EQU 9 ; console in CNOT EQU 12 ; console out HOM EQU 24 ; disk home SLDSK EQU 27 ; select disk STTRK EQU 30 ; set track STSEC EQU 33 ; set sector STDMA EQU 36 ; set dma address READS EQU 39 ; read sector WRITS EQU 42 ; write sector IOINT EQU 57 ; initialize i/o ORG 100H START: LXI SP,STACK MVI A,0 CALL CGTTBL ;get table address vers 2.1 > sta lb$vers INX H MOV A,H ;if < 2.1 then hl=ffff ORA L MVI# * * * / * * AMPRO SYSTEM CONFIGURATION UTILITY * * R * * Copyright (C) 1984,85,86 AMPRO COMPUTERS, INC. * * All rights reserved. * *  * * ^* VER EQU 26 ; Version number prints in signon message. ;Vers 2.6 rbl 5 Feb 86 Show 17 A,16 ;for 2.1 max 16 drives JNZ STNEW LHLD 1 ;get NDSKS parameter current MVI L,5CH ;offset MOV A,M STNEW: ADI '@' ;set drive letters STA GDSK1 STA PDSK1 inr a STA DSK1 ;and insert to utility STA DSK2 JMP SIGNON CGTTBL: LHLD 1 MVI L,33H PCHL ;for <2.1 does Unlog ; 2.1 returns next table address < ffff lb$get$ldte: push psw lda lb$vers ; If version 1.x bios cpi 20 jp lb$2x lxi h,lb$d ; then point to a dummy floppy unit jmp lb$ok lb$1: db 1 lb$d: lx ;i h,lb$1 ret lb$2x: call cgttbl ; otherwise (2.x) get unit from table lxi d,9 dad d lb$ok: pop psw pchl DISPLAY$FDEV: call clearscreen LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call lb$get$ldte ; Get address of unit id MOV A,M ; Get unit id CPI 01 ; Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; . ani 03h ; mask out excess bits MOV l,a ; update floppy device number?cape key? JZ EXIT ; quit ANI UPCASE ; force upper case CPI 'M' ; memory? JZ XXX CPI 'D' ; disk? JNZ ASK1 ; try again ; say 'disk' and ask which ASKG: CALL ILPRT DB 'Disk$' ASK2: lda lb$vers cpi 20 cp display$fdev ask222: CALL ILPRT DB CR,LF,LF,'Which disk shall you read from? (A thru ' GDSK1: DB 'P) $' ASK2A: CALL CONIN ; get response CPI CTLC JZ EXIT CPI ESC JZ DISP ; start over ANI UPCASE ; force upper case CPI 'A' JC ASK2A ; bad selection, try again DS mvi h,0 ; . dad h ; x2 xchg LXI H,FNAMES ; . dad d ; x2 dad d ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lda unit ; adi 'A' ; sta d$current ; LXI D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTR: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? jm D$NEXT$FDEV ; No -- go do the next one RET unit: db 0 D$FDEV$HDR: DB 'FLOPPY DISK ASSIGNMENTS:',CR,LF DB 'CP/M drive ' DB 'Floppy disk',CR,LF DB '-mK1: EQU $+1 ;modified for max drive name CPI 'P'+1 JNC ASK2A ; bad selection MOV C,A ; save for conout ANI 0FH ; strip ascii DCR A ; adjust rel 0 STA DISK ; remember it CALL CONOUT ; to console (echo) CALL GETD ; read the disk JZ DISP ; display parms if a good system disk CALL ILPRT ;issue a message DB CR,LF,'There is no system on this disk $' JMP ASK222 ;and get a new disk to try XXX: CALL ILPRT DB 'Memory$' CALL GETM ; get parameters from memory ; display th --]-',CR,LF,'$' D$FDEV$LIN: DB ' ' D$CURRENT: DB 'x ' D$EDISK: DB ' ' D$EBLANK: DB '  ' D$FNAME: DB ' ' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' LB$VERS DB 0 ; Bios version number clearscreen: mvi b,24 ; clear screen clsc2: MVI A,0Dh ; Send carriage returmn CALL CON$CHR ; . MVI A,0Ah ; and line feed CALL CON$CHR ; . CALL WAIT ; wait for the s-l-o-w teie parameters in iobuf DISP: CALL ILPRT DB CR,LF,LF,LF,'Configuration Table:' DB CR,LF,LF,'Parameter: &Currently:' DB CR,LF,LF,'1. Terminal r $' LDA IOBYT ANI 3 LXI H,SPA JNZ DISP1 LXI H,SPB DISP1: CALL PRINT CALL ILPRT DB CR,LF,'2. Printer $' LDA IOBYT ANI 0C0H ; isolate lst assignment CPI 0 LXI H,SPB JZ DISP2 CPI 40H LXI H,SPA JZ DISP2 LXI H,PP DISP2: CALL PRINT CALL ILPRT DB CR,LF,'3. Max. Floppy Drives $' LDA LB$VERS C9rminals dcr b jnz clsc2 RET ; and return CON$CHR: PUSH B MVI C,2 MOV E,A CALL BDOS POP B RET SIGNON: call clearscreen CALL ILPRT DB ' t AMPRO System Configuration Utility',CR,LF DB ' Copyright (c) 1984,85,86 - AMPRO Computers, Inc.',CR,LF DB ' Version ' DB VER/10+'0','.',VER MOD 10+'0',CR,LF,LF DB 'With this utility you may view and change the various',CR,LF DB 'parameters of your AMPRO system. You will be asked to',CR,LF DB 'choPI 30 JC DISP2X MVI A,4 JMP DISP2Y DISP2X: LDA NDSKS DISP2Y: ORI 30H MOV C,A CALL CONOUT CALL ILPRT DB CR,LF,'4. Step Rate $' LDA STPRAT CALL DISP2Z CALL ILPRT DB ', $' LDA STPRAT+1 CALL DISP2Z CALL ILPRT DB ', $' LDA STPRAT+2 CALL DISP2Z CALL ILPRT DB ', $' LDA STPRAT+3 CALL DISP2Z CALL ILPRT DB ' $' JMP DISP6A DISP2z: ORA A JNZ DISP3 g CALL ILPRT DB '6ms$' JMP DISP6 DISP3: DCR A JNZ DISP4 CALL ILPRT DB '12ms$' JMP DISP6 DIfose to view the current parameters now in memory or',CR,LF DB 'to view the parameters on a system disk. You will be',CR,LF DB 'asked for any changes you might make. After any changes',CR,LF DB 'you will be asked whether to install the new parameters',CR,LF DB 'in memory and/or on a system disk.',CR,LF,LF DB 'View parameters from Memory or from Disk? (M or D)',CR,LF,LF DB 'Press to quit. $' ASK1: CALL CONIN ; get the response CPI CTLC ; control c? JZ EXIT ; quit CPI ESC ; esSP4: DCR A JNZ DISP5 CALL ILPRT DB '2ms$' JMP DISP6 DISP5: CALL ILPRT DB '3ms$' DISP6: RET DISP6a: LDA LB$VERS CPI 30 ; skip msg if bios 3.0 JNC DISP6b CALL ILPRT DB cr,lf,9,9,'Note: The first step rate is used for all drives' DB cr,lf,9,9,' when using bios 1.x or 2.x',CR,LF,'$' DISP6b: CALL ILPRT DB CR,LF,'5. Autocommand $' LXI H,AUTOCMD+1 CALL PRINT CALL ILPRT DB CR,LF,LF,'6. $' LXI H,SPA CALL PRINT LXI D,SIOA+3 CALL DISP16 CALL ILPRT % DB CR,LF,' Tbaud rate $' LXI B,CT0 LXI D,SIOA+1 CALL PBAUD CALL ILPRT DB CR,LF,' hand shake $' LDA HSA ORA A LXI H,N JZ DISP15 LXI H,Y DISP15: CALL PRINT CALL ILPRT DB CR,LF,LF,'7. $' LXI H,SPB CALL PRINT LXI D,SIOB+3 CALL DISP16 CALL ILPRT DB CR,LF,' Tbaud rate $' LXI B,CT1 LXI D,SIOB+1 CALL PBAUD CALL ILPRT DB CR,LF,' $hand shake $' LDA HSB ORA AMVI C,0 JZ CH41A CPI '2' MVI C,1 JZ CH41A CPI '3' MVI C,2 JZ CH41A CPI '4' MVI C,3 JNZ CH4A CH41A: PUSH PSW MOV A,C STA STPRAT POP PSW MOV C,A CALL CONOUT CH42A: CALL ILPRT DB CR,LF,'Second floppy drive rate (1-4): $' CH4B: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI CR JZ CH42B CPI '1' MVI C,0 JZ CH41B CPI '2' MVI C,1 JZ CH41B CPI '3' MVI C,2 JZ CH41B CPI '4' MVI C,3 JNZ CH4B CH41B: PUSH PSW MOV A,C STA ST LXI H,N JZ DISP17 LXI H,Y DISP17: CALL PRINT CALL ILPRT DB CR,LF,LF,'Any (more) changes? (1 through 7 or No) $' DSP17A: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI 'N' JZ FINI CPI 'n' JZ FINI CPI '1' JC DSP17A CPI '8' JNC DSP17A CPI '7' JZ CH7 CPI '6' JZ CH6 CPI '5' JZ CH5 CPI '4' JZ CH4 CPI '3' JZ CH3 CPI '2' JZ CH2 CH1: CALL ILPRT DB CR,LF,LF,'1. Terminal, Serial port A or Serial port B. (A or B)$' CH1A: CALL CONIN CPI CTLC JZ EXIT PRAT+1 POP PSW MOV C,A CALL CONOUT CH42B: CALL ILPRT DB CR,LF,'Third floppy drive rate (1-4): $' CH4C: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI CR JZ CH42C CPI '1' MVI C,0 JZ CH41C CPI '2' MVI C,1 JZ CH41c CPI '3' MVI C,2 JZ CH41c CPI '4' MVI C,3 JNZ CH4c CH41c: PUSH PSW MOV A,C STA STPRAT+2 POP PSW MOV C,A CALL CONOUT ch42c: CALL ILPRT DB CR,LF,'Foruth floppy drive rate (1-4): $' CH4D: CALL CONIN CPI CTLC JZ EXIT CP CPI ESC JZ DISP ANI UPCASE CPI 'C' JNC CH1A CPI 'A' JC CH1A MVI C,1 JZ CH10 DCR C CH10: LDA IOBYT ANI 0FCH ORA C STA IOBYT JMP DISP CH2: CALL ILPRT DB CR,LF,LF,'2. Printer, Serial port A, Serial port B ' DB 'or Parallel port. (A, B or P)$' CH2A: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP ANI UPCASE CPI 'A' JZ CH20 CPI 'B' JZ CH20 CPI 'P' JNZ CH2A CH20: CPI 'B' MVI C,0 JZ CH21 CPI 'A' MVI C,40H JZ CH21 MVI C,80H CH21: LDA IOBYT ANI 3F[I ESC JZ DISP CPI CR JZ CH42d CPI '1' MVI C,0 JZ CH41D CPI '2' MVI C,1 JZ CH41D CPI '3' MVI C,2 JZ CH41D CPI '4' MVI C,3 JNZ CH4D CH41D: PUSH PSW MOV A,C STA STPRAT+3 POP PSW MOV C,A CALL CONOUT CH42D: JMP DISP CH5: CALL ILPRT DB CR,LF,LF,'5. Autocommand. Command file to be executed ' DB 'on cold boot. $' LXI D,CONBUF MVI A,8 STAX D MVI C,RDCON CALL BDOS LXI H,CONBUF+1 MOV E,M MVI D,0 DAD D INX H MVI M,0 LXI H,CONBUF+1 L$H ORA C STA IOBYT JMP DISP CH3: LDA LB$VERS CPI 30 JC CH3X CALL ILPRT DB CR,LF,LF,'3. The maximum number of floppy disk ' DB 'drives is preset to four (4)',CR,LF DB 'in the Ampro BIOS version 3.0 or greater.',CR,LF,LF DB 'Press the RETURN key to continue - ','$' CH3R: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI CR JZ DISP JMP CH3R CH3X: CALL ILPRT DB CR,LF,LF,'3. Max. drives. (1, 2, 3 or 4)$' CH3A: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI JXI D,AUTOCMD LXI B,10 CALL LDIR JMP DISP CH6: CALL ILPRT DB CR,LF,LF,'Serial port A configuration' DB CR,LF,LF,'Data bits. (5, 6, 7 or 8) $' CH6A: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI CR JZ CH6B ; next CPI '5' JC CH6A ; again CPI '9' JNC CH6A CPI '8' MVI C,60H JZ CH60 CPI '7' MVI C,20H JZ CH60 CPI '6' MVI C,40H JZ CH60 MVI C,0 ; 5 bits CH60: LXI H,SIOA+3 MOV A,M ; wr5 info ANI 9FH ; mask ORA C ; add selection MOV M,A ; store i'1' JC CH3A CPI '5' JNC CH3A ANI 0FH STA NDSKS JMP DISP CH4: CALL ILPRT DB CR,LF,LF,'4. Step rates for each floppy drive ' DB '(in milliseconds).',CR,LF,LF DB 'Choices: 1770 1772',CR,LF DB ' 1 -- 6ms 6ms',CR,LF DB ' 2 -- 12ms 12ms',CR,LF DB ' 3 -- 20ms 2ms',CR,LF DB ' 4 -- 30ms 3ms',CR,LF DB '$' CALL ILPRT DB CR,LF,'First floppy drive rate (1-4): $' CH4A: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI CR JZ CH42A CPI '1'  t MOV A,C RAL MOV C,A ; shift selection left LXI H,SIOA+5 MOV A,M ; wr3 info ANI 3FH ; mask ORA C MOV M,A ; store it CH6B: CALL ILPRT DB CR,LF,LF,'Stop bits. A=1, B=1.5, C=2. (A, B or C)$' CH6BA: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI CR JZ CH6C ANI UPCASE CPI 'A' JC CH6BA CPI 'D' JNC CH6BA CPI 'A' MVI C,4 JZ CH6B1 CPI 'B' MVI C,8 JZ CH6B1 MVI C,0CH CH6B1: LXI H,SIOA+1 MOV A,M ; wr4 info ANI 0F3H ; mask ORA C MOV M,A ; store n zew info CH6C: CALL ILPRT DB CR,LF,LF,'Parity. Odd, Even or None. (O, E or N) $' CH6CA: CALL CONIN CPI CR JZ CH6D CPI CTLC JZ EXIT CPI ESC JZ DISP ANI UPCASE CPI 'O' MVI C,1 JZ CH6C0 CPI 'E' MVI C,3 JZ CH6C0 CPI 'N' MVI C,0 JNZ CH6CA CH6C0: LXI H,SIOA+1 MOV A,M ; wr4 info ANI 0FCH ; mask ORA C MOV M,A ; store it CH6D: CALL ILPRT DB CR,LF,LF,'Baud rates:' DB CR,LF,'0. 110 5. 2400' DB CR,LF,'1. 300 6. 4800' DB CR,LH ORI 80H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH6E B110: LXI H,CT0 MVI A,7H MOV M,A INX H MVI A,71 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 80H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A CH6E: CALL ILPRT DB CR,LF,LF,'Hand shake? (Yes or No) $' CH6EA: CALL CONIN CPI CTLC JZ EXIT CPI CR JZ DISP ANI UPCASE CPI 'Y' MVI C,1 JZ CH6E1 CPI 'N' MVI C,0 JNZ CH6EA CH6E1: MOV A,C STA HSA JMP DISP CH7: CALL ILPRT DB C0 F,'2. 450 7. 9600' DB CR,LF,'3. 600 8. 19200' DB CR,LF,'4. 1200 9. 38400' DB CR,LF,LF,'Choose one. (0 through 9) $' CH6DA: CALL CONIN CPI CR JZ CH6E CPI CTLC JZ EXIT CPI ESC JZ DISP CPI ':' JNC CH6DA CPI '0' JC CH6DA JZ B110 CPI '1' JZ B300 CPI '2' JZ B450 CPI '3' JZ B600 CPI '4' JZ B1200 CPI '5' JZ B2400 CPI '6' JZ B4800 CPI '7' JZ B9600 CPI '8' JZ B19200 B38400: LXI H,CT0 MVI A,3 MOV M,A R,LF,LF,'Serial port B configuration' DB CR,LF,LF,'Data bits. (5, 6, 7 or 8) $' CH7A: CALL CONIN CPI CTLC JZ EXIT ; quit CPI ESC JZ DISP CPI CR JZ CH7B ; next CPI '5' JC CH7A ; again CPI '9' JNC CH7A CPI '8' MVI C,60H JZ CH70 CPI '7' MVI C,20H JZ CH70 CPI '6' MVI C,40H JZ CH70 MVI C,0 ; 5 bits CH70: LXI H,SIOB+3 MOV A,M ; wr5 info ANI 9FH ; mask ORA C ; add selection MOV M,A ; store it MOV A,C RAL MOV C,A ; shift selection left LXI H,SIOB INX H MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H ; point to wr5 MOV A,M ANI 7FH ; turn dtr off MOV M,A JMP CH6E B19200: LXI H,CT0 MVI A,3 MOV M,A INX H MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 80H MOV M,A INX H INX H MOV A,M ANI 7FH MOV M,A JMP CH6E B9600: LXI H,CT0 MVI A,47H MOV M,A INX H MVI A,13 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP C+5 MOV A,M ; wr3 info ANI 3FH ; mask ORA C MOV M,A ; store it CH7B: CALL ILPRT DB CR,LF,LF,'Stop bits. A=1, B=1.5, C=2. (A, B or C)$' CH7BA: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP CPI CR JZ CH7C ANI UPCASE CPI 'A' JC CH7BA CPI 'D' JNC CH7BA CPI 'A' MVI C,4 JZ CH7B1 CPI 'B' MVI C,8 JZ CH7B1 MVI C,0CH CH7B1: LXI H,SIOB+1 MOV A,M ; wr4 info ANI 0F3H ; mask ORA C MOV M,A ; store new info CH7C: CALL ILPRT DB CR,LF,LF,'Parity. Odd, Even orH6E B4800: LXI H,CT0 MVI A,47H MOV M,A INX H MVI A,26 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH6E B2400: LXI H,CT0 MVI A,47H MOV M,A INX H MVI A,52 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH6E B1200: LXI H,CT0 MVI A,47H MOV M,A INX H MVI A,104 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H None. (O, E or N) $' CH7CA: CALL CONIN CPI CR JZ CH7D CPI CTLC JZ EXIT CPI ESC JZ DISP ANI UPCASE CPI 'O' MVI C,1 JZ CH7C0 CPI 'E' MVI C,3 JZ CH7C0 CPI 'N' MVI C,0 JNZ CH7CA CH7C0: LXI H,SIOB+1 MOV A,M ; wr4 info ApNI 0FCH ; mask ORA C MOV M,A ; store it CH7D: CALL ILPRT DB CR,LF,LF,'Baud rates:' DB CR,LF,'0. 110 5. 2400' DB CR,LF,'1. 300 6. 4800' DB CR,LF,'2. 450 %7. 9600' DB CR,LF,'3. 600' DB CR, MOV A,M ORI 80H MOV M,A JMP CH6E B600: LXI H,CT0 MVI A,47H MOV M,A INX H MVI A,208 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH6E B450: LXI H,CT0 MVI A,47H MOV M,A INX H MVI A,139 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FH ORI 80H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH6E B300: LXI H,CT0 MVI A,47H MOV M,A INX H MVI A,208 MOV M,A LXI H,SIOA+1 MOV A,M ANI 3FLF,'4. 1200' DB CR,LF,LF,'Choose one. (0 through 7) $' CH7DA: CALL CONIN CPI CR JZ CH7E CPI CTLC JZ EXIT CPI ESC JZ DISP CPI '8' JNC CH7DA CPI '0' JC CH7DA JZ BB110 CPI '1' JZ BB300 CPI '2' JZ BB450 CPI '3' JZ BB600 CPI '4' JZ BB1200 CPI '5' JZ BB2400 CPI '6' JZ BB4800 BB9600: LXI H,CT1 MVI A,47H MOV M,A INX H MVI A,13 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH7E BB4 {800: LXI H,CT1 MVI A,47H MOV M,A INX H MVI A,26 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH7E BB2400: LXI H,CT1 MVI A,47H MOV M,A INX H MVI A,52 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH7E BB1200: LXI H,CT1 MVI A,47H MOV M,A INX H MVI A,104 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV  JMP FINI PUTDSK: lda lb$vers cpi 20 cp display$fdev PDSK0: CALL ILPRT DB CR,LF,LF,'Install changes on which disk? (A thru ' PDSK1: DB 'P) $' PTDSKA: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ DISP ANI UPCASE CPI 'A' JC PTDSKA DSK2: EQU $+1 ;MODIFIED CPI 'P'+1 JNC PTDSKA PUSH PSW MOV C,A CALL CONOUT POP PSW STA PDSK ANI 0FH DCR A STA DISK CALL PUTD JNZ FINI ;in case disk error CALL ILPRT DB CR,LF,LF,'Changes installed on disk ' PDSK: DB 'A$' JMP #A,M ORI 80H MOV M,A JMP CH7E BB600: LXI H,CT1 MVI A,47H MOV M,A INX H MVI A,208 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH ORI 40H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH7E BB450: LXI H,CT1 MVI A,47H MOV M,A INX H MVI A,139 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH ORI 80H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH7E BB300: LXI H,CT1 MVI A,47H MOV M,A INX H MVI A,208 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH hFINI ; print the baud rate ; bc points to ctc init string, de points to sio init string PBAUD: LDAX B ; get first ctc byte CPI 3 ; reset? JZ DISP13 CPI 47H LXI H,B1 JNZ DISP14 ; must be 7, print 110 baud INX B ; point to second byte of ctc string LDAX B CPI 13 LXI H,B96 JZ DISP14 ; print 9600 baud CPI 26 LXI H,B48 JZ DISP14 CPI 52 LXI H,B24 JZ DISP14 CPI 104 LXI H,B12 JZ DISP14 CPI 208 LXI H,B4 JNZ DISP14 LDAX D ; wr4 info ANI 0C0H ; mask CPI 4ORI 80H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A JMP CH7E BB110: LXI H,CT1 MVI A,7H MOV M,A INX H MVI A,71 MOV M,A LXI H,SIOB+1 MOV A,M ANI 3FH ORI 80H MOV M,A INX H INX H MOV A,M ORI 80H MOV M,A CH7E: CALL ILPRT DB CR,LF,LF,'Hand shake? (Yes or No) $' CH7EA: CALL CONIN CPI CTLC JZ EXIT CPI CR JZ DISP ANI UPCASE CPI 'Y' MVI C,1 JZ CH7E1 CPI 'N' MVI C,0 JNZ CH7EA CH7E1: MOV A,C STA HSB JMP DISP DISP16: CALL ILPRT DB ' U0H LXI H,B6 JZ DISP14 LXI H,B3 JMP DISP14 DISP13: LDAX D ; wr4 info ANI 0C0H CPI 40H LXI H,B384 JZ DISP14 LXI H,B192 DISP14: JMP PRINT ; print returns to caller ; get parameters from memory GETM: LHLD 1 ; bios address MVI L,64 ; parameters start here LXI D,IOBUF ; and go here LXI B,64 ; 64 bytes JMP LDIR ; move it ; put parameters in memory PUTM: LHLD 1 ; bios address MVI L,64 ; parms go here XCHG ; in de LXI H,IOBUF ; parms from here LXI B,64 ;  data bits $' LDAX D ; wr5 info ANI 60H ; mask CPI 60H ; 8 bits MVI C,'8' JZ DISP7 CPI 20H ; 7 bits MVI C,'7' JZ DISP7 CPI 40H ; 6 bits MVI C,'6' JZ DISP7 MVI C,'5' DISP7: CALL CONOUT CALL ILPRT DB CR,LF,' configuration stop bits $' DCX D DCX D LDAX D ; wr4 info ANI 0CH ; mask CPI 8 JNZ DISP8 CALL ILPRT DB '1.5$' JMP DISP10 DISP8: CPI 4 MVI C,'1' JZ DISP9 MVI C,'2' DISP9: CALL CONOUT DISP10: CALL ILPRT DB CR,LF,' [64 bytes JMP LDIR ; move it ; get parameters from disk GETD: MVI A,1 STA TRACK ; track 1 STA RDOP ; this is a read MVI A,5 STA SECTOR ; bios starts here CALL DSKIO ; read it ; check to see if the system is really here... LXI H,BUFFER LXI D,3 LXI B,17 ;test for 17 C3 bytes GETD0: MOV A,M ;Calculate check sum on Jump table ORA B MOV B,A DAD D DCR C JNZ GETD0 MOV A,B CPI 0C3H ; If any other bit is an error RNZ GETD1: LXI H,BUFFER+64 ; from second ha parity $' LDAX D ; wr4 info ANI 3 ; mask CPI 1 LXI H,ODD JZ DISP12 CPI 3 LXI H,EVEN JZ DISP12 LXI H,NONE DISP12: JMP PRINT FINI: CALL ILPRT DB CR,LF,LF,'Install changes in Memory or on Disk? (M or D)' DB CR,LF,'Press to exit.$' FINIA: CALL CONIN CPI CTLC JZ EXIT CPI ESC JZ EXIT ANI UPCASE CPI 'M' JZ PUTMEM CPI 'D' JZ PUTDSK JMP FINIA PUTMEM: CALL PUTM CALL IOINIT CALL ILPRT DB CR,LF,LF,'Changes installed in memory.$'Tlf of buffer LXI D,IOBUF ; to io buffer LXI B,64 ; 64 bytes JMP LDIR ; move it ; put parameters on disk PUTD: lda disk call lb$get$ldte mov a,m ora a jnz putdok call ilprt db cr,lf,lf,'No disk at this letter ',cr,lf,'$' mvi a,0ffh ora a ret putdok: MVI A,1 STA TRACK STA RDOP ; read first MVI A,5 STA SECTOR CALL DSKIO ; do the read LXI H,IOBUF ; parms from here LXI D,BUFFER+64 ; to here LXI B,64 ; 64 bytes CALL LDIR ; move it XRA A STA RDOP ; writ )Ye CALL DSKIO ;do the write ORA A RZ CALL ILPRT DB CR,LF,LF,'Disk Write Error ',CR,LF,'$' MVI A,0FFH ORA A ;set nz on return RET ; reads or writes one sector of the disk DSKIO: LDA DISK ; chosen disk call lb$get$ldte mov a,m ora a rz lda disk MOV C,A MVI E,0 ; new mount, get new dpb CALL SELDSK ; select the disk LXI D,10 ; OFFSET TO CURRENT DPB DAD D MOV A,M INX H MOV H,M MOV L,A MOV A,M ; THIS IS THE SECTOR PER TRACK CPI 64 ; IF NOT 64 THEN IS TR%al Port A$' SPB: DB 'Serial Port B$' PP: DB 'Parallel Port$' ODD: DB 'odd$' EVEN: DB 'even$' NONE: DB 'none$' B384: DB '38400$' B192: DB '19200$' B96: DB '9600$' B48: DB '4800$' B24: DB '2400$' B12: DB '1200$' B6: DB '600$' B4: DB '450$' B3: DB '300$' B1: DB '110$' Y: DB 'yes$' N: DB 'no$' BUFFER: EQU $ + 7FH AND 0FF80H ; at sector boundary for readability ORG BUFFER DS 128 IOBUF: CT0: DS 2 CT1: DS 2 CT2: DS 2 CT3: DS 2 SIOA: DS 10 SIOB: DS 10 NDSKS: DS 1 STPRAT: DS 4 IOBYT)K 1 SECT 5 JNZ DSKIF ; NO THEN USE FLOPPY VALUES MVI A,45 ; SET TRACK 0 SECTOR 45 FOR HARD DISK STA SECTOR XRA A ; AND TRACK 0 STA TRACK DSKIF: CALL HOME ; reset hstact flag, forces readhst LDA TRACK ; chosen track MOV C,A CALL SETTRK LDA SECTOR ; chosen sector MOV C,A CALL SETSEC LXI B,BUFFER ; all reads and writes to/from here CALL SETDMA LDA RDOP ; read operation flag ORA A JZ WRIT ; must be write JMP READ ; read returns to caller WRIT: MVI C,1 ; force prM: DS 1 AUTOCMD:DS 10 HSA: DS 1 HSB: DS 1 DS 32 STACK: END START 400$' B192: DB '19200$' B96: DB '9600$' B48: DB '4800$' B24: DB '2400$' B12: DB '1200$' B6: DB '600$' B4: DB '450$' B3: DB '300$' B1: DB '110$' Y: DB 'yes$' N: DB 'no$' BUFFER: EQU $ + 7FH AND 0FF80H ; at sector boundary for readability ORG BUFFER DS 128 IOBUF: CT0: DS 2 CT1: DS 2 CT2: DS 2 CT3: DS 2 SIOA: DS 10 SIOB: DS 10 NDSKS: DS 1 STPRAT: DS 4 IOBYTe-read and write JMP WRITE ; write returns to caller ; logical z80 'ldir' instruction LDIR: MOV A,M ; from source STAX D ; to destination INX H ; next INX D DCX B ; decrement byte count MOV A,B ORA C JNZ LDIR ; again RET ; prints the string pointed to by hl PRINT: MOV A,M ; get a byte INX H ; bump pointer CPI '$' ; terminator? RZ ; yes, return CPI 0 RZ ANI 7FH ; force ascii PUSH PSW MOV C,A CALL CONOUT ; to console POP PSW CPI LF CZ WAIT ; waitO 10 ms after line feed JMP PRINT ; again ; prints the string folloing the call to ilprt ILPRT: XTHL ; point hl to next byte CALL PRINT XTHL ; put next address on stack RET WAIT: PUSH B LXI B,10 * 167 ; wait x (* 167) milliseconds WT0: DCX B MOV A,B ORA C JNZ WT0 POP B RET CONOUT: PUSH H PUSH D PUSH B MOV E,C MVI C,2 CALL 5 POP B POP D POP H RET ; direct bios calls CONIN: MVI A,CNIN JMP BIOS HOME: MVI A,HOM JMP BIOS SELDSK: MVI A,SLDSK JMP BIOS SETTRK: MVI A,STTRK JMP BIOS SETSEC: MVI A,STSEC JMP BIOS SETDMA: MVI A,STDMA JMP BIOS READ: MVI A,READS JMP BIOS WRITE: MVI A,WRITS JMP BIOS IOINIT: MVI A,IOINT BIOS: LHLD 1 MOV L,A PCHL EXIT: JMP 0 ; 'stubs' for testing, to be removed later T1: CALL ILPRT DB 'T1',CR,LF,'$' RET T2: CALL ILPRT DB 'T2',CR,LF,'$' RET T3: CALL ILPRT DB 'T3',CR,LF,'$' RET DISK: DB 2 ; disk c: TRACK: DB 1 SECTOR: DB 5 RDOP: DB 1 ; read operation SPA: DB 'Seri 7 Filename.Typ Size Recs CRC 1 -A60102 .D 0K 0 0000 2 AD-3-3 .ASM 28K 213 88D1 3 CFG-2-6 .ASM 28K 209 90A1 4 CRC .CRC 0K 0 0000 5 DIR .COM 2K 16 BE35 6 DT-1-0 .ASM 10K 69 6E2A 7 ES-2-3 .ASM 24K 183 3FF1 8 MD-2-3 .ASM 44K 351 A0F7 9 MF-2-3 .ASM 40K 319 72CA 10 SC-2-2 .ASM 28K 211 1481 11 SET-1-0 .ASM 22K 164 A03A 12 SG-3-3 .ASM 20K 155=A ~ "#~+"##= *V/F##x_*V^#V#~ѷ"VU y0>.> > *. O*. ) OGHNWoHdWor# xo*}ʄ$.Ɉ*. O*. ) OGHNWoHdWor# xo*}ʄ M **>* * AMPRO Computers Inc. * * Date.asm * * ** * Adapted from DATE.MAC * *  by Don Delwood, * *  with mods by Roger Warren *  **1* ; ; Version date by History ; ------- -- ------ --B ; 1.0 4 mar 86 fsw Version 1.0 for use with bios 3.6 ; *--- Z3ENV* R!]~  >?E]/|DIR 1.0 Syntax: DIR dir:afn o Options: A=All, S=System, T=File Type/Name SorX!m~#ʼ ʉTʨSʯA‰>ñy OÉ>@y?OOÉ̈́xyY Ovf!"!q#p22xy:|#+*"͆  ~$rx:<2e:<2+##=e2Pause - e x: > }.xAyDʨ~# * --͆* Files Using͆K ͆K Left ~~#>2--* VER EQU 10 ; version 1.0 CR EQU 13 LF EQU 10 LDIR EQU 0B0EDH ; z80 ldir ORG 100H JMP BEGIN ; jump over logo HELP: CALL PRINT DB CR,LF,LF DB 'DATE ' DB 'Version ',VER/10+'0','.',VER MOD 10+'0',CR,LF DB 'AMPRO Computers Inc.' DB CR,LF,'To change the date, enter change ' DB 'on the command line as follows:',cr,lf,lf DB 'du>DATE mm-dd-yy',cr,lf DB 0 JMP EXIT BEGIN: DW 73EDH,OLDSTK ; save old stack pointer LXI SP,LOCSTK ; set new stack ; LXI D,WBOOT  ; build bios entry table LHLD 1 ; get bios start LXI B,51 ; bytes to move DW LDIR ; move it ; CALL GETTBL ; get address of next jmp tbl CPI 36 ; must be bios ver 3.6 or higher JC BADVER ; give message and exit LXI D,NXTTBL ; 'hl' has bios nxttbl address LXI B,15 ; DW LDIR ; move the table LXI H,0 ; make sure that clock is enabled CALL TOD ; get clock base address MOV A,L ; see if address of tick was returned ORA H JZ NOCLK ; exit clock not enabled ; 'hl' has addthe pattern hh:mm:ss. test for ; valid numeric characters. it has already been determined that ; somthing was entered on the command line ; VALID: LXI H,80H ; character count MOV B,M ; get number of characters typed INX H DCR B JZ NVALMS ; exit only spaces or one char on line MOV A,M ; get first char CPI ' ' JZ VALID+4 ; filter the spaces VAL1: MOV A,M INX H ; point to next char ANA A ; 00h is terminator or zero count RZ CPI '/' JZ HELP ; show instructions CPI '?' res of clock LXI D,SEC ; move time LXI B,6 DW LDIR ; save time ; Everthing needed has been moved into program area now. ; parse command tail to see if time was entered on command line. ; LXI H,80H ; point to command tail MOV A,M ; get character count ANA A ; if zero nothing on cmd line STA UPDATE ; save possible entry on cmd line JZ SHDATE ; skip no char on command line PUSH H CALL VALID ; test for valid numeric ascii POP H LOOP: INX H ; point to first char on comman JZ HELP ; show insturctions CPI '-' JZ VAL1 ; delimeter ok CPI '0' JC NVALMS ; less than ascii 0 CPI '9'+1 JNC NVALMS ; more than ascii 9 JMP VAL1 ; NVALMS: CALL PRINT DB 'Invalid date',cr,lf,0 JMP EXIT ; ; time of day TOD jmp was not in bios ; NOCLK: CALL PRINT DB 'Clock not installed',cr,lf,0 JMP EXIT ; ; wrong version bios ; BADVER: CALL PRINT DB 'Requires Bios 3.6 or higher.',cr,lf,0 ; fall through to exit ; ; Normal program exit. Restores system stack d line MOV A,M CPI ' ' JZ LOOP ; filter leading spaces CALL EVAL10 CPI 12+1 ; see if more than december JNC NVALMS STA TMONTH ; set temp month MOV C,A ; save month INX H CALL EVAL10 PUSH H LXI H,MTHS-1 ; MVI B,0 DAD B ; point to number of days in month CMP M ; see if valid entry for the month POP H JZ CONT JNC NVALMS CONT: STA TDAY ; set temp month INX H CALL EVAL10 STA YEAR ; set year CALL MD2J ; convert the month/day to julian SHDATE: CALL J2MD jand returns ; EXIT: DW 7BEDH,OLDSTK ; recover old stack pointer RET ; ; Print string of characters terminated with zero '0'. ; PRINT: POP H MOV A,M ; get byte ANA A JZ PRNEND PUSH H ; MOV C,A CALL CONOUT ; call bios routine PTOP H INX H ; next byte JMP PRINT+1 PRNEND: XTHL ; hl has return RET ;**o* ; convert binary to ascii ; in: a - binary value ; out: bc - ascii character (low high) (mod. after Ri; convert julian date to month/day LDA TMONTH DCR A ; adjust MOV E,A ; ADD A ; times 2 ADD E ; times 3 MOV E,A MVI D,0 LXI H,AMONTHS ; find month in string DAD D LXI D,MON LXI B,3 ; move 3 bytes DW LDIR LDA TDAY CALL BINASC DW 43EDH,DAY LDA YEAR CALL BINASC DW 43EDH,YR CALL PRINT ; print message CURDAT: DB 'Current date is ' MON: DB ' ' DAY: DB ' , 19' YR: DB ' ' DB 0 ; ; if time was not changed from the command line, do not place ; the time ch Conn) ;*** BINASC: MVI C,0 ; init count MVI B,10 BIN1: SUB B JC BINEXT INR C JMP BIN1 binext: ADD B ; A = ones digit C = tens digit ADI '0' MOV B,A MOV A,C ADI '0' MOV C,A RET   ;*** ; eval10 - convert ascii string to decimal value ; in: hl - points to beginning of string ; out: a - e ; de - value ; hl - points to delimiter (error character prameters back into the bios clock area. ; LDA UPDATE ANA A ; if zero time was only displayed JZ EXIT ; ; move the newly set time prameters to bios clock area ; CALL TOD ; get address of time counters LXI D,3 ; offset to date DAD D ; add offset to 'hl' XCHG ; bios time counter addresss to 'de' LXI H,JDAY ; LXI B,3 ; date only, not time DW LDIR ; move it to bios memory JMP EXIT ; ; Test the command for valid time entry. Scan the command tail ; for along its legnth for %) ; (mod. after Rich Conn) ;*** EVAL10: PUSH B LXI D,0 ; init de to zero E10L: MOV A,M ; next digit, check range '0'-'9' CPI '0' JC EVLOUT ; less than ascii 0 CPI '9'+1 JNC EVLOUT ; more than ascii 9 SUI '0' MUL10: PUSH H ; multiply DE by 10 MOV H,D MOV L,E DAD H ; *2 DAD H ; *4 DAD D ; *5 DAD H ; *10 MOV E,A ; add in latest digit MVI D,0 DAD D XCHG POP H INX H JMP E10L EVLOUT: MO /V A,E POP B RET ; **& ; convert month/day to julian ; ** MD2J: LXI D,MTHS-1 ; init month pointer LXI H,0 LDA TMONTH ; get binary month MOV B,A ; set count MD2J1: LDAX D ; get number of days in month ADD L MOV L,A ; update 'l' CC MD2J3 ; adjust 'h' if carry DCR B INX D ; next month JCNZ MD2J1 MD2J2: LDA TDAY ; get binary day MOV E,A ; MVI D,\aage for month TDAY: DS 1 ; temp storage for day TYEAR: DS 1 ; temp storage for year END turns bioss ; version in 'a'. NXTTBL: SWAP: DS 3 ; jmp swap HD$INF: DS 3 ; get hd table info PHTBAC: DS 3 ; get/set phytab acces PAGET: DS 3 ; get phytab entry address TOD: DS 3 ; get base address of clock tick ; time/date counters from bios SEC: DS 1 MIN: DS 1 HOUR: DS 1 JDAY: DS 2 ; julian day 0-366 for leap year YEAR: DS 1 TMONTH: DS 1 ; temp stor…0 DAD D ; add the day DCX H ; adjust for ordinal 0 SHLD JDAY RET MD2J3: MVI A,1 ; if carry add 1 to 'h' ADD H MOV H,A RET ; ** ;  convert julian to month/day ; ** J2MD: LXI D,MTHS ; int month pointer LHLD JDAY ; julian day in 'hl' INX H ; adjust for ordinal 0 XRA A MOV B,A ; init high byte of sub with 0 INR A STA TMONTH ; init monPth to 1 J2MD1: LDAX D ORA A ; clear carry MOV C,A MOV A,L ; may be day DW 42EDH ; sbc hl,bc JC J2MD2 JZ J2MD2 LDA TMONTH INR A ; update month STA TMONTH INX D JMP J2MD1 J2MD2: STA TDAY ; set day RET DB 0 MTHS: DB 31,29,31,30,31,30,31,31,30,31,30,31 AMONTHS: DB 'JanFebMarAprMayJunJulAugSepOctNovDec' ; local stack area ; DS 32 ; 16 level stack LOCSTK: DW EXIT ; exit point on top of stack OLDSTK: DS 2 ; save for old stack UPDATE DS 1 ; flag for commannd entry ; ; bios jmp table, moved from the bios during init. ; WBOOT: DS 3 ; Warm start CONST: DS 3 ; Console status CONIN: DS 3 ; Console character in CONOUT: DS 3 ; Console character out LIST: DS 3 ; List character out PUNCH: DS 3 ; Punch character out READER: DS 3 ; Reader character in HOME: DS 3 ; Seek to home position SELDSK: DS 3 ; Select disk SETTRK: DS 3 ; Set track number SETSEC: DS 3 ; Set sector number SETDMA: DS 3 ; Set DMA address READ: DS 3 ; Read disk WRITE: DS 3;+#--+ ;|# | ;| ESET.ASM ?| ;| Public Domain - 1984 Konrad Roeder, Albuquerque, NM | ;|# | ;+#--A+ ; ; ; Revision Log: ; 12/12/84 V2.0 Warning for use with ha ; Write disk LISTST: DS 3 ; Return list status SECTRAN:DS 3 ; Sector translate GETTBL: DS 3 ; Point to more jumps, returns bioss ; version in 'a'. NXTTBL: SWAP: DS 3 ; jmp swap HD$INF: DS 3 ; get hd table info PHTBAC: DS 3 ; get/set phytab acces PAGET: DS 3 ; get phytab entry address TOD: DS 3 ; get base address of clock tick ; time/date counters from bios SEC: DS 1 MIN: DS 1 HOUR: DS 1 JDAY: DS 2 ; julian day 0-366 for leap year YEAR: DS 1 TMONTH: DS 1 ; temp storkrd disk bios. ; ; 7/16/84 V1.0 release to AMPRO-1 ; ; Purpose: ; ; ESET allows any one of the four possible drives A, B, C, and D, ; to read a foreign format. The emulated foreign drive is called ; "E" when it is used with the foreign format and by its regular ; name when it is used with the normal format of the machine. ; ; ESET changes the specifications of the "E" drive in four areas: ; 1 - Disk Drive Select Byte ; 2 - Type Byte ; 3 - Disk Parameter Block ; 4 - Skew Table ; ; The follo Wxwing is a description of those data structures: ; ; DISK DRIVE SELECT BYTE ; Tells the system which drive is aliased to the foreign format "E" ; 00 - A 01 - B 02 - C 03 - D ; ; TYPE BYTE ; ; ; bit 7 density: 0=single; 1=double ; bit 6 double sided media if = 1 ; bit 5 double sided mode: ; 1 = continuous sector numbers (first ; sector on side one = last sector ; on side 0 + 1). ; both tracks are treated as a ; single track with twice as many ; secve d PCHL ;return with dpb addr ; ;bioret returns with the bios location of eparm ;and saves it for use later. ; BIORET: DCX H ;back up to type byte location SHLD ADDR ;save location ; ;print the signon message. ; SIGN: LXI D,SIGNON ;point to sign on message CALL OUTPUT ; call get$bios$vers mvi a,16 jnz new$sys lhld 1 mvi l,5ch mov a,m jmp plugem new$sys push psw mvi a,0 lxi h,jplug1 mov m,a inx h mov m,a inx h mov m,a pop psw plugem adi '@tors. ; 0 = same sectors on both sides ; (normal method) ; bit 4 reserved ; bits 3-2 00 = 1k allocation blocks ; 01 = 2k allocation blocks ; 10 = not used ; 11 = not used ; bits 1-0 00 = 128 byte sectors ; 01 = 256 byte sectors ; 10 = 512 byte sectors ; 11 = 1024 byte sectors ; ; ; DISK PARAMETER BLOCK ; The disk parameter block tells the system about how the data ; is arranged on the disk. The DPB has ten entries: ; SPT Sectors Per Track (word) ; BSH Bl' sta plug1 inr a sta cplug1 jmp doit DISP$FDEV: ; ; [E2.15] ; ; lda lb$vers ora a rz LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call lb$get$ldte ; Get address of unit id MOV A,M ; Get unit id CPI 01 ; Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; . ani 03h ; mask out excess bits MOV l,a ; update floppy device number mvi h,0 ; . dad h ; x2 xchg Lxock SHift (byte) ; BLM BLock Mask (byte) ; EXM EXtent Mask (byte) ; DSM Directory Size Minus one (word) ; DRM DiRectory entries Minus one (word) ; AL0 directory group ALlocation 0 (byte) ; AL1 directory group ALlocation 1 (byte) ; CKS ChecK Size (word) ; OFF OFFset (# reserved tracks) (word) ; ; SKEW TABLE ; The skew table translates between logical and physical sector ; numbers. On some systems the sectors are not contiguously ; arranged so that access times can be improved. ; ; *XI H,FNAMES ; . dad d ; x2 dad d ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lda unit ; adi 'A' ; sta d$current ; LXI D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTR: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? jm D$NEXT$FDEV ; No -- go do the next one RET unit: db 0 D$FDEV$HDR: DB cr,lf,'FLOPPY DISK ASSIGNMENTS:',CR,LF DB ' CP/M drive ' DB 'Floppy disk',CR,LF DB '  -- ',CR,LF,'"** CR: EQU 0DH ;carrige return LF: EQU 0AH ;line feed ESC: EQU 01BH ;escape CAPS: EQU 05FH ;upper case FF: EQU 00H ;ignore form feed ETX: EQU 3 ;^c bdos equ 5 ORG 0100H ;base of tpa BEGIN: JMP START ;leave room for copyright ; DB 'ESET Vers 2.3 Copyright (c) 1984,1985' DB ' AMPRO Computers, Inc. ' ; START: LXI H,0 ;zero out h&l DAD SP ;add sp to hl SHLD OLDSP ;save it LXI SP,STACK ;set up new stack ]$' D$FDEV$LIN: DB ' ' D$CURRENT: DB 'x ' D$EDISK: DB ' ' D$EBLANK: DB ' ' D$FNAME: DB ' ' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' GET$BIOS$VERS: ; Get bios version -- Brings the current BIOS jump tables (starting ; at warm boot) to a local area for ease of utility access. If ; this BIOS is version 2.1 or greater, the secondary jump table ; is brought in as well. ; ; E ; ;ckdrv loads the default drive and compares it ;against the e drive which isn't allowed. prints ;error message if true. ; CKDRV: LDA 4 ;get default drive CPI 4 ;is it drive "e"? JZ WRGDRV ;get ready to quit if it is ; lhld 01H ; [2.3] mvi l,74h mov a,m ani 3fh ; mask off D-speed & D-step mov m,a ; ;eaddr gets the location of eparm in the bios. ; EADDR: LHLD 1 ;get warm boot vector MVI L,36H ;getedsk offset LXI D,BIORET ;point to bios return point PUSH D ;saXntry: none ; Exit: Z = bios < 2.1 (old bios) ; NZ = bios 2.1+ (fixed disk bios) ; All registers are modified ; LHLD 1 ; Get start of bios jump table LXI D,LB$BIOS$TBL ; Move bios to local storage LXI B,LB$LEN ; . (length of bios area) db 0edh,0b0h ; . (move routine) MVI A,0 ; Test CP/M version CALL LB$GETNXT ; Get next jump table STA LB$VERS ; Save bios version INX H ; See if HL is 0FFFFh MOV A,H ; . ORA L ; . RZ ; If so, then old version DCX H ; Fix H I L as it has the table addr LXI D,LB$XTBL ; Move extra table to local storage lxI B,LB$XLEN ; . (length of extra table) db 0edh,0b0h ; . (move routine) MVI A,0FFH ; Set NZ to indicate bios ORA A ; ... version 2.1+ RET ; ... and return.  * 2* * * * Data area . . . * * * * ^* ; Replicated BIOS for ease of use . . . LB$BIOS$TBL: LB$WBOOT DB 0,0,0 ; Warm boot LB$ MTB: LDA TYPE ;ssdd = 10xxxxxx ORI 80H STA TYPE JMP PTALL FMTC: LDA TYPE ;dssd = 01xxxxxx ORI 40H STA TYPE JMP PTSEC FMTD: LDA TYPE ;dsdd = 11xxxxxx ORI 0C0H STA TYPE JMP PTSEC PTSEC: LXI D,SELSEC CALL OUTPUT GETSEC: CALL CONIN ;get sector numbering CPI ESC ;esc? JZ PTMAIN CPI ETX ;ctrl-c? JZ DONE ANI CAPS CPI 'A' ;a? JZ SECA CPI 'B' ;b? JZ SECB JMP GETSEC ; SECA: LDA TYPE ; continuous xx1xxxxx ORI 20H STA TYPE JMP PTALL SECB: JMP PTALL ; s CONST DB 0,0,0 ; Console status LB$CONIN DB 0,0,0 ; Console input LB$CONOUT DB 0,0,0 ; Console output LB$LISTOUT DB 0,0,0 ; List output LB$PUNCH DB 0,0,0 ; Punch output LB$READER DB 0,0,0 ; Reader input LB$HOMDSK DB 0,0,0 ; Home disk (move to track 00) LB$SELDSK DB 0,0,0 ; Select disk drive LB$SETTRK DB 0,0,0 ; Select track number LB$SETSEC DB 0,0,0 ; Select sector number LB$SETDMA DB 0,0,0 ; Set DMA address LB$DSKREAD DB 0,0,0 ; Disk read LB$DSKWRITE DB 0,0,0 ; Disk write LB$LISTST DB 0,0,0 ; oame xx0xxxxx (no change) ; PTALL: LXI D,SELALL CALL OUTPUT GETALL: CALL CONIN ; get allocation block size CPI ESC ;esc? JZ PTMAIN ; if so -- start over CPI ETX ;ctrl-c? JZ DONE ; if so -- bye ANI CAPS ; convert to caps CPI 'A' ;a? JZ ALLA CPI 'B' ;b? JZ ALLB JMP GETALL ALLA: JMP PTBPS ; 1k xxxx00xx ALLB: LDA TYPE ; 2k xxxx01xx ORI 04H STA TYPE PTBPS: LXI D,SELBPS ; get bytes per sector memu CALL OUTPUT GETBPS: CALL CONIN ; get bps CPI ESC ;esc? JZ  List status LB$SECTRN DB 0,0,0 ; Sector translate routine ; AMPRO-specific BIOS calls LB$GETNXT DB 0,0,0 ; Get bios ver & next tbl address LB$GETEDSK DB 0,0,0 ; Get pointer to E-disk storage LB$IOINIT DB 0,0,0 ; Set new I/O parameters LB$SCSIDRV DB 0,0,0 ; SCSI direct driver LB$LEN EQU $-LB$WBOOT ; Length of bios table LB$XTBL: LB$SWAP$DRV DB 0,0,0 ; Swap two logical drives LB$WINDRV DB 0,0,0 ; Set/get win drive parameters LB$PHYTAB DB 0,0,0 ; Set/get phytab access LB$GET$LDTE DB 0,0,0 ; Get CPTMAIN ; if so -- start over CPI ETX ;ctrl-c? JZ DONE ; if so -- bye ANI CAPS ; caps to caps CPI 'A' ;a? JZ BPSA CPI 'B' ;b? JZ BPSB CPI 'C' ;c? JZ BPSC CPI 'D' ;d? JZ BPSD JMP GETBPS BPSA JMP FCMAIN ; 128 bps xxxxxx00 BPSB LDA TYPE ; 256 bps xxxxxx01 ORI 01H STA TYPE JMP FCMAIN BPSC LDA TYPE ; 512 bps xxxxxx10 ORI 02H STA TYPE JMP FCMAIN BPSD LDA TYPE ;1024 bps xxxxxx11 ORI 03H STA TYPE FCMAIN: LXI D,SELSPT ;sectors per track (word) CALL OUTPUT  physical table entry address LB$RESERVED DB 0,0,0 ; Reserved entry LB$XLEN EQU $-LB$XTBL ; Length of extra table LB$VERS DB 0 doit: call disp$fdev lxi d,sign2 call output ; ;getdrv checks which drive is selected as the "e" drive. ; GETDRV: CALL CONIN ;get drive selection CPI ESC ;esc? JZ DONE ;endit CPI ETX ;^c? JZ DONE ; ANI CAPS ;force upper case cpi 'A' jc getdrv cplug1 equ $+1 cpi 'E' jnc getdrv sta drsel+7 sui 'A' jplug1 jmp get$20e call lb$get J CALL DBIN SHLD DPB ;store in dpb & dpb + 1 LXI D,SELBSH ;block shift c (byte) CALL OUTPUT CALL DBIN MOV A,L ;store in dpb+2 STA DPB+2 LXI D,SELBLM ;block mask c(byte) CALL OUTPUT CALL DBIN MOV A,L ;store in dpb+3 STA DPB+3 LXI D,SELEXM ;extent mask (byte) CALL OUTPUT CALL DBIN MOV A,L ;store in dpb+4 STA DPB+4 LXI D,SELDSM ;disk size - 1 (word) CALL OUTPUT CALL DBIN SHLD DPB+5 LXI D,SELDRM ;# directories - 1 (word) CALL OUTPUT $ldte mov a,m cpi 1 jnz getdrv inx h mov a,m ani 3 get$20e: sta drive ptmain XRA A ;clear type byte STA TYPE LXI D,SELFMT CALL OUTPUT ;print the format selection GETFMT: CALL CONIN ;get the format selection CPI ESC ;esc? JZ PTMAIN ;start over CPI ETX ;ctrl-c? JZ DONE ANI CAPS ;force caps CPI 'A' ;a? JZ FMTA CPI 'B' ;b? JZ FMTB CPI 'C' ;c? JZ FMTC CPI 'D' ;d? JZ FMTD JMP GETFMT ;back until its ok FMTA: JMP PTALL ;sssd = 00xxxxxx (no change) F VCALL DBIN SHLD DPB+7 LXI D,SELAL0 ;allocation 0 (byte) CALL OUTPUT CALL DBIN MOV A,L STA DPB+9 LXI D,SELAL1 ;allocation 1 (byte) CALL OUTPUT CALL DBIN MOV A,L STA DPB+10 LXI D,SELCKS ;dir check size (word) CALL OUTPUT CALL DBIN SHLD DPB+11 LXI D,SELOFF ;reserved tracks (word) CALL OUTPUT CALL DBIN SHLD DPB+13 LXI D,SELOK CALL OUTPUT GETOK: CALL CONIN CPI ETX JZ DONE ANI CAPS CPI 'Y' JZ PTSKW CPI 'N' JZ FCMAIN JMP GETOK PTSKW  e: LXI D,SELSKW CALL OUTPUT GETSKW: CALL CONIN CPI ESC ;esc? JZ PTSKW CPI ETX ;ctrl-c? JZ DONE ANI CAPS CPI 'A' JZ SKWWA CPI 'B' JZ SKWWB CPI 'C' JZ SKWWC CPI 'D' JZ SKWWD CPI 'E' JZ SKWWE CPI 'F' JZ SKWWF CPI 'G' JZ SKWWG CPI 'H' JZ SKWWH CPI 'I' JZ SKWWI CPI 'J' JZ SKWWJ CPI 'K' JZ SKWWK CPI 'L' JZ SKWWL CPI 'M' JZ SKWWM CPI 'N' JZ SKWWN CPI 'O' JZ SKWWO CPI 'P' JZ SKWWP CPI 'Z' JZ MKSKW JMP GETSKW SKWWA: LXI D,SKWA JMP st2: lhld 1 ; set double speed bit mvi l,74h mov a,m ori 80h mov m,a jmp loop2a dsmsga: DB CR,LF,'Should the double speed bit be set (Y/N)? ','$' ; loop2a: ; ; clean up ; LXI D,SGNOFF CALL OUTPUT LHLD OLDSP SPHL ;put the old stack back into use JMP 0H ;go to bios reset address ; ; ; ;conin gets a character from the console through bios and ;puts it in the accumulator. ; CONIN: MVI A,9 ; bios call avoids echo to console LHLD 1 MOV L,A PCHL ; ; ;co Y SKWFIN SKWWB: LXI D,SKWB JMP SKWFIN SKWWC: LXI D,SKWC JMP SKWFIN SKWWD: LXI D,SKWD JMP SKWFIN SKWWE: LXI D,SKWE JMP SKWFIN SKWWF: LXI D,SKWF JMP SKWFIN SKWWG: LXI D,SKWG JMP SKWFIN SKWWH: LXI D,SKWH JMP SKWFIN SKWWI: LXI D,SKWI JMP SKWFIN SKWWJ: LXI D,SKWJ JMP SKWFIN SKWWK: LXI D,SKWK JMP SKWFIN SKWWL: LXI D,SKWL JMP SKWFIN SKWWM: LXI D,SKWM JMP SKWFIN SKWWN: LXI D,SKWN JMP SKWFIN SKWWO: LXI D,SKWO JMP SKWFIN SKWWP: LXI D,SKWP JMP SKWFIN MKSKW: LXI D,MKMSG ;di nout gets a single character from the accumulator and ;sends it to the console through bios ; CONOUT: MOV C,A MVI A,12 LHLD 1 MOV L,A PCHL ; ; ;output sends the message pointed to by de to the screen. ; OUTPUT: MVI C,9 ;print string function CALL 5 ;bdos RET ; ; ; ; dbin ascii decimal to 16 bits in hl ; DBIN: PUSH D ;save registers LXI H,0 ;clear hl DBIN2: PUSH H ;save hl CALL CONIN POP H CPI ETX ;ctrl-c? JZ ABORT CPI CR ;return? JZ DBIN3 PUSH H }d not find the skew table, ;so we will build one! CALL OUTPUT LXI H,SKW ;hl will point at the temp buffer MVI B,20 ;b will count out twenty entries MKSKW1: PUSH B ;save b for now PUSH H ;hl too LXI D,PROMPT ;print the prompt CALL OUTPUT CALL DBIN ;get a value in decimal -> hl MOV A,L POP H ;get the address it goes into MOV M,A ;and move it there INX H POP B DCR B ;count down JNZ MKSKW1 ;not done yet - go again LXI D,SKWOK ;ask 'em if its ok CALL OUTPUT GETSOK  CALL CONOUT POP H SUI '0' ;convert this digit to binary JC DBIN4 ; <0 CPI 10 JNC ERRDB ; >10 MOV D,H ; hl -> de MOV E,L DAD H ; *2 DAD H ; *4 DAD D ; *5 DAD H ; *10 MOV E,A ; new byte -> de MOV D,0 DAD D ; de + hl -> hl JMP DBIN2 ; next DBIN4: CPI (' '-'0') AND 0FFH JNZ ERRDB ;not blank DBIN3: POP D ;restore RET ERRDB: LXI D,DBERR CALL OUTPUT POP D JMP DBIN ;try again ABORT: POP D JMP DONE DBERR: DB CR,LF,'unrecognizable digit on input -- try ag s: CALL CONIN ;get their answer CPI ETX ;ctrl-c? JZ DONE ;end it ANI CAPS ;convert to caps CPI 'Y' ;y? JZ LDDPB CPI 'N' ;n? JZ MKSKW JMP GETSOK ;someday they may type y or n! ; SKWFIN: LXI H,SKW MVI B,20 CALL LOOP ;move the appropriate skew table in the ;temporary buffer area ; ; ; ; move the temporary buffer area into bios ; LDDPB: LHLD ADDR ;get bios pointer back MVI B,37 ;number of bytes to move (1+15+1+20) LXI D,TYPE ;point to the temporary dpb CALL LOOP ݭGain :$' ; ; ;loop moves data from an address pointed to by de ; to an address pointed to by hl ; for b bytes. ; LOOP: LDAX D MOV M,A INX D INX H DCR B JNZ LOOP ;loop until done RET ; ; ; ; ;the signon message... ; SIGNON: DB CR,LF DB FF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB 0,0 8 ; ; Set double step and/or double speed ; lxi d,dsmsg call output askd2x call conin cpi esc jz done cpi etx jz done ani 05fh cpi 'Y' jz setdst cpi 'N' jz loop2 jmp askd2x setdst: lhld 1 mvi l,74h mov a,m ori 40h mov m,a jmp loop2 dsmsg: DB CR,LF,'Is the E-drive a 96tpi drive (Y/N)? ','$' ; loop2: lxi d,dsmsga call output askd2xa call conin cpi esc jz done cpi etx jz done ani 05fh cpi 'Y' jz setdst2 cpi 'N' jz loop2a jmp askd2xa setd y,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB 'ESET 2.3 prepares your AMPRO system to read, and' DB ' write diskettes formatted ',CR,LF,'for many other' DB ' computers &- not supported by MULTIDSK ' DB CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF,'$' sign2: db cr,lf,lf DB 'Which drive do you wish to use as the "E" drive? (A - ' plug1: DB 'D) $' ; SELFMT: DB CR,LF DB FF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,60 DB 'Defining TYPE byte for drive "E" ',CR,LF DB  0,LF DB  0,LF DB 'A) sin  ,0,0,LF DB  0,[LF DB '# of logical sectors per track (SPT):$' SELBSH: DB CR,LF DB 'block shift factor , (BSH):$' SELBLM: DB CR,LF DB 'block mask (BLM):$' SELEXM: DB CR,LF DB 'extent mask / DB alloc. size (EXM):$' SELDSM: DB CR,LF DB 'maximum data block number - 1 (DSM):$' SELDRM: DB CR,LF DB 'maximum directory entries - 1 (DRM):$' SELAL0: DB CR,LF DB 'directory group allocation 0 9 (AL0):$' SELAL1: DB CR,LF DB 'directory group alloca 'gle sided, single density ',CR,LF DB  0,50 DB 'B) single sided, double density ',CR,LF DB  0,50 DB 'C) double sided, single density ',CR,LF DB  0,50 DB 'D) double sided, double density ',CR,LF DB  0,0 DB LF DB  0,Q0 DB 'Select a FORMAT or to start over:$' SELSEC: DB CR,LF DB FF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0, 0 DB 'A) {4tion 1 (AL1):$' SELCKS: DB CR,LF DB 'check size ` (CKS):$' SELOFF: DB CR,LF DB 'number of reserved tracks (OFF):$' SELOK: DB CR,LF DB  0,LF DB  0,JLF DB 'Are all entries in the dpb ok? $' SELSKW: DB CR,LF DB FF DB  0,LF DB  0,LF DB  0,LF DB  0,LF DB  0,LF DB  0,"0 DB 'A) 1,2,3,4,5 ',LF,CR DB  0, 0 DB 'B) 1 *Continuous sector numbers -- ',CR,LF DB  0,I0 DB ' first sector on side 1 = last sector on side 0 + 1' DB CR,LF ,0 DB LF ,08 DB 'B) Same sector numbers on both sides',CR,LF DB  0,'0 DB ' (normal method)',CR,LF DB  0, 0 DB LF ,08 DB 'Select the way sectors are numbered ',CR,LF DB  0,A0 DB 'or to start over:$' SELALL: DB CR,LF DB FF DB  0,LF DB 0, ,3,5,2,4 ',LF,CR DB  0,"0 DB 'C) 1,4,2,5,3 ',LF,CR DB  0,(0 DB 'D) 1,2,3,4,5,6,7,8 ',LF,CR DB  0,*0 DB 'E) 1,2,3,4,5,6,7,8,9 ',LF,CR DB  0,*0 DB 'F) 1,3,5,7,9,2,4,6,8 ',LF,CR DB  0,*0 DB 'G) 1,4,7,2,5,8,3,6,9 ',LF,CR DB  0,-0 DB 'H) 1,2,3,4,5,6,7,8,9,10 ',LF,CR DB  0,-0 DB 'I) 1,3,5,7,9,2,4,6,8,10 ',LF,CR DB  0,,0 DB 'J) 0,1,2,3,4,5,6,7,8,9 ',LF,CR DB 0, 0,LF DB  0,LF DB  0,.LF DB 'A) 1k allocation blocks ',CR,LF DB  0,-0 DB 'B) 2k allocation blocks ',CR,LF DB  0,}LF DB 'Select the size of the allocation blocks',CR,LF DB 'or type to start over:$' SELBPS: DB CR,LF DB FF DB  0,LF DB  0,LF DB  0,LF DB  0,+LF DB 'A) 128 byte sectors ',CR,LF DB  0,0 DB 'B) 256 byte sector uE0,0,0,0 DB 'K) 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 ',LF,CR DB  0,D0 DB 'L) 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 ' DB LF,CR ,0C DB 'M) 1,3,5,7,9,11,13,15,17,2,4,6,8,10,12,14,16,18 ' DB LF,CR ,0C DB 'N) 1,5,9,13,17,3,7,11,15,2,6,10,14,18,4,8,12,16 ' DB LF,CR ,0C DB 'O) 1,6,11,16,3,8,13,18,5,10,15,2,7,12,17,4,9,14 ' DB LF,CR ,0B DB 'P) 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 ' DB LF,CR,0 |ss ',CR,LF DB  0,*0 DB 'C) 512 byte sectors ',CR,LF DB  0,*0 DB 'D) 1024 byte sectors ',CR,LF DB  0,YLF DB 'Select the sector size or to start over:$' SELSPT: DB CR,LF DB FF DB  0,LF DB  0,LF DB  0,LF DB  0,ALF DB 'Defining Disk Parameter Block for drive "E"',CR,LF DB  0,LF DB  0,LF DB  0,LF DB 0,0 y,0) DB 'Z) none of the above ',LF,CR DB  0, 0 DB LF,CR ,0 DB 'Select a skew table :$' MKMSG: DB FF,'Enter the skew table -- enter zeros for ' DB 'the extra bytes ',CR,LF DB '$' PROMPT: DB CR,LF,'skw:$' SKWOK: DB CR,LF,LF,'Are the skew table entries ok?$' ;ending message... ; SGNOFF: DB CR,LF DB FF DB  0,x0 DRSEL: DB LF,'Drive # is now the new format drive when you ' DB 'call it "E" .',CR,LF,'$' ; ; ;wrgdrv loads t E he wrong drive error message, prints ;it and exits to cp/m. ; WRGDRV: LXI D,ERROR ;load error message CALL OUTPUT ;bdos DONE: LHLD OLDSP ;get stack back SPHL ;put it in sp RET ;return to zcpr3 ; ERROR: DB 7,CR,LF DB  0,r0 DB LF,'Wrong drive selected.',CR,LF DB 'MULTIDSK can only be run from drive A, B, C, or D.' DB CR,LF DB  0,y0 DB LF,'$' ; ; SKWA: DB 1, 2, 3, 4, 5, 0, 0, 0, 0, 0 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWB: DB 1, 3, 5, 2,   4, 0, 0, 0, 0, 0 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWC: DB 1, 4, 2, 5, 3, 0, 0, 0, 0, 0 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWD: DB 1, 2, 3, 4, 5, 6, 7, 8, 0, 0 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWE: DB 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWF: DB 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWG: DB 1, 4, 7, 2, 5, 8, 3, 6, 9, 0 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWH: DB 1, 2, 3, 4, 5, 6, 7, 8, 9,10 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKW ݏ * * * *  * &MULTIDSK * * *  L* COPYRIGHT (C) 1984,85,86 - AMPRO COMPUTERS, INC. * * * * * ;revision log: ; ; 4/24/86 Ver 2.4 ; Fixed problem with 96tpi. ; ; 4/08/86 Ver 2.3 ; Fixed display bug. Non-functional change. ; ; 5/22/85 Ver 2.2 ; Added support for 48tpi formats in a 96tpi ; drive I DB 1, 3, 5, 7, 9, 2, 4, 6, 8,10 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWJ DB 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 SKWK DB 1, 2, 3, 4, 5, 6, 7, 8, 9,10 DB 11,12,13,14,15,16, 0, 0, 0, 0 SKWL DB 1, 2, 3, 4, 5, 6, 7, 8, 9,10 DB 11,12,13,14,15,16,17,18, 0, 0 SKWM DB 1, 3, 5, 7, 9,11,13,15,17, 2 DB 4, 6, 8,10,12,14,16,18, 0, 0 SKWN DB 1, 5, 9,13,17, 3, 7,11,15, 2 DB 6,10,14,18, 4, 8,12,16, 0, 0 SKWO DB 1, 6,11,16, 3, 8,13,18, 5,10 DB 15, 2, 7,12,17, 4, 9,14, 0, . Added support for 8" 3740 with bios ; 3.0+ (assembly time option) ; ; 2/28/85 Ver 2.1 ; Removed warning message of 12/12/84, added ; translation of drive letters for bios 2.0+ ; ; 12/12/84 Ver 2.0 ; Added warning message for use with ; Hard disk bios. ; ; 5/13/84 Ver 1.4 ; Added nulls to line feeds for ; S-L-O-W terminals (VT100 etc.). ; ; 5/08/84 Unreleased Ver.1.3X ; Added Televideo, Sanyo, Pmc Type A. ; ; 3/09/84 Release Ver 1.2 ; Deleted IBM DS, TI D f0 SKWP DB 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 DB 10,11,12,13,14,15,16,17, 0, 0 ; ; TYPE: DS 1 ;type byte DPB: DS 15 ;disk parameter block DRIVE: DS 1 ;drive selection SKW: DS 32 ;skew table ADDR: DS 2 ;"e" drive parms adr. OLDSP: DS 2 ;room fUor old stack pointer ; DS 010H ;16 level stack STACK: ; ; END BEGIN 13,17, 3, 7,11,15, 2 DB 6,10,14,18, 4, 8,12,16, 0, 0 SKWO DB 1, 6,11,16, 3, 8,13,18, 5,10 DB 15, 2, 7,12,17, 4, 9,14, 0, bS. Added OSB 1, ; H/Z 89 SD, TRS80-3. Corrected menus ; This version requires Bios 3/5 ; or later. ; ; 2/17/84 Release Ver 1.1 ; Now allow drive A to be used as "E". ; Corrected bug in H9 (H89 DSXD) ; WS added a few lines of extra code! ; ; 2/3/84 Release version 1.0 ; ; ;MULTIDSK allows the "E" drive of the AMPRO series 100 computers ;to read and write several different 48 & 96 tpi disk formats. Multidsk ;changes the TYPE byte, DPB, Drive, and the SKEW table in the bios  . A ;total of 37 bytes are allowed (1 TYPE byte, 15 for DPB, 1 for Drive ;selected 20 for SKEW table). Type byte is a single byte which defines ;the particulars of the foreign disk format. The DPB (disk parameter ;block) is the standard Digital Research dpb and can be learned by ;studying the CP/M 2 Alteration Guide as supplied by Digital Research. ;The drive select byte defines which drive will be used as the "E" drive ;(01=B, 02=C, and 03=D). The skew table defines the skew of the physi [ Rcal ;sectors not the logical sectors. ; ;definition of type byte: ; ; bit 7 density: 0=single; 1=double ; bit 6 double sided media if = 1 ; bit 5 double sided mode: ; 1 = continuous sector numbers (first ; sector on side one = last sector ; on side 0 + 1). ; both tracks are treated as a ; single track with twice as many ; sectors. ; 0 = same sectors on both sides ; (normal method) ; bit 4 reserved ; bits 3-2 00 = 1k allocation blo op+1 chk$eight: lda lb$vers cpi 30 if eight$inch ; If 8" is enabled, then blot out text only jp doit ; if bios is less than version 3.0. If 8" endif ; is not enabled, always blot out text. mvi a,0c3h ; change 'jz' to 'jmp' sta zplug3a mvi a,'$' ; add '$' to text sta zplug3b lxi h,zplug3c ; remove '4, ' from text mvi m,0 inx h mvi m,0 inx h mvi m,0 jmp doit DISPLAY$FDEV: lda lb$vers cpi 20 rm LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos cks ; 01 = 2k allocation blocks ; 10 = not used ; 11 = not used ; bits 1-0 00 = 128 byte sectors ; 01 = 256 byte sectors ; 10 = 512 byte sectors ; 11 = 1024 byte sectors ; ; CR: EQU 0DH ;carrige return LF: EQU 0AH ;line feed ESC: EQU 01BH ;escape CAPS: EQU 05FH ;upper case ETX: EQU 3 ;^c EIGHT$INCH: EQU 0 ; Set to 1 to show 8" entries bdos equ 5 ORG 0100H ;base of tpa ; BEGIN: LXI H,0 ;zero out h&l DAD SP ;add sp to hl SHLD OLDSP ;save it LXI F mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call lb$get$ldte ; Get address of unit id MOV A,M ; Get unit id CPI 01 ; Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; . ani 03h ; mask out excess bits MOV l,a ; update floppy device number mvi h,0 ; . dad h ; x2 xchg LXI H,FNAMES ; . dad d ; x2 dad d ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lda unit ; adi 'A' ; sta d$current ; LXI n SP,STACK ;set up new stack ; ;ckdrv loads the default drive and compares it ;against the e drive which isn't allowed. prints ;error message if true. ; CKDRV: LDA 4 ;get default drive CPI 4 ;is it drive "e"? JZ WRGDRV ;get ready to quit if it is lhld 01H mvi l,74h mov a,m ani 3fh ; mask off D-speed & D-step mov m,a ; ;eaddr gets the location of eparm in the bios. ; EADDR: LHLD 1 ;get warm boot vector MVI L,36H ;getedsk offset LXI D,BIORET ;point to bios re ?D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTR: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? jm D$NEXT$FDEV ; No -- go do the next one RET unit: db 0 D$FDEV$HDR: DB CR,LF,'FLOPPY DISK ASSIGNMENTS',CR,LF 6 DB 'CP/M drive ' DB 'Floppy disk',CR,LF DB ' --\',CR,LF,'$' D$FDEV$LIN: DB ' ' D$CURRENT: DB 'x ' D$EDISK: DB ' ' D$EBLANK: DB '  ' D$FNAME: DB ' 6' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line turn point PUSH D ;save d PCHL ;return with dpb addr ; ;bioret returns with the bios location of eparm ;and saves it for use later. ; BIORET: DCX H ;back up to type byte location SHLD ADDR ;save location ; Interrogate the command line for any characters lxi h,80h mov a,m inx h ora a jz sign mov b,a lxi d,cldrive mvi c,4 nextchr: mov a,m dcr b inx h jm sign cpi ' ' jz nextchr stax d inx d dcr c jz sign jmp nextchr cldrive db 0 clmenu db 0 c e length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' ; end of DISPLAY$FDEV GET$BIOS$VERS: ; Get bios version -- Brings the current BIOS jump tables (starting ; at warm boot) to a local area for ease of utility access. If ; this BIOS is version 2.1 or greater, the secondary jump table ; is brought in as well. ; 6 ; Entry: none ; Exit: Z = bios < 2.1 (old bios) ; $NZ = bios 2.1+ (fixed disk bios) ; *All registers are modified ; LHLD 1 ; Fltype db 0 cl4896 db 0 ; ;print the signon message. ; SIGN: mvi a,0 ; clear bios version sta lb$vers call get$bios$vers ; get bios version mvi a,16 jnz new$sys lhld 1 mvi l,5ch mov a,m jmp plugem new$sys: push psw xra a lxi h,jplug1 mov m,a inx h mov m,a inx h mov m,a pop psw plugem: adi '@' sta plug1 inr a sta cplug1 lda lb$vers cpi 30 jp chk$eight mvi a,0c3H ; change nop's to jmp if less than bios 3.0 sta loop lxi h,loop2 shld lo {Get start of bios jump table LXI D,LB$BIOS$TBL ; Move bios to local storage lxi B,LB$LEN ; . (length of bios area) db 0edh,0b0h ; . (move routine) MVI A,0 ; Test CP/M version CALL LB$GETNXT ; Get next jump table STA LB$VERS ; Save bios version INX H ; See if HL is 0FFFFh MOV A,H ; . ORA L ; . RZ ; If so, then old version DCX H ; Fix HL as it has the table addr LXI D,LB$XTBL ; Move extra table to local storage lxi B,LB$XLEN ; . (length of extra table) db 0edh,0b0h ; .  fr(move routine) MVI A,0FFH ; Set NZ to indicate bios ORA A ; ... version 2.1+ RET ; ... and return. * 2* * * * Data area . . . * * * * * ; Replicated BIOS for ease of use . . . LB$BIOS$TBL: LB$WBOOT DB 0,0,0 ; Warm boot LB$CONST DB 0,0,0 ; Console status LB$CONIN DB 0,0,0 ; Console input LB$CONOUT DB 0,0,0 ; Console output LB$LISTOUT DB 0,0,0 ; List output LB   JZ DONE ; ANI 7FH ;clean it up STA TYPE ; cpi '1' jz prtsub cpi '2' jz prtsub cpi '3' jz prtsub zplug3a: jz zplug3ax IF EIGHT$INCH cpi '4' jz prtsub ENDIF zplug3ax: lda clmenu ora a jz comp xra a sta clmenu jmp main ; PRTSUB: lda cltype ora a jnz ckmenu lda type LXI D,SS48 ;load d with sub-menu CPI '1' ;single sided 48 tpi? JZ PRTSUB2 ; LXI D,DS48 ; CPI '2' ;double sided 48 tpi? JZ PRTSUB2 ; LXI D,TPI96 ; CPI '3' ;96 tpi? JZ P 7$PUNCH DB 0,0,0 ; Punch output LB$READER DB 0,0,0 ; Reader input LB$HOMDSK DB 0,0,0 ; Home disk (move to track 00) LB$SELDSK DB 0,0,0 ; Select disk drive LB$SETTRK DB 0,0,0 ; Select track number LB$SETSEC DB 0,0,0 ; Select sector number LB$SETDMA DB 0,0,0 ; Set DMA address LB$DSKREAD DB 0,0,0 ; Disk read LB$DSKWRITE DB 0,0,0 ; Disk write LB$LISTST DB 0,0,0 ; List status LB$SECTRN DB 0,0,0 ; Sector translate routine ; AMPRO-specific BIOS calls LB$GETNXT DB 0,0,0 ; Get bios ver & next tbl address RTSUB2 ; LXI D,IBM3740 cpi '4' jz ibm3740 prtsub2 CALL OUTPUT ;prints the submenu selected ; ;ckmenu determines which sub-menu has been selected ;and jumps to the appropriate comparison routine. ; CKMENU: LDA TYPE ;get sub menu CPI '1' ;ss48? JZ COMP1 ; CPI '2' ;ds48? JZ COMP2 ; CPI '3' ;96tpi? JZ COMP3 ; CPI '4' JZ IBM3740 JMP MAIN ;this should never happen! ; ;comp1 checks to see which single sided format has been ;selected. ^c allows exit to cp/m. ;  LB$GETEDSK DB 0,0,0 ; Get pointer to E-disk storage LB$IOINIT DB 0,0,0 ; Set new I/O parameters LB$SCSIDRV DB 0,0,0 ; SCSI direct driver LB$LEN EQU $-LB$WBOOT ; Length of bios table LB$XTBL: LB$SWAP$DRV DB 0,0,0 ; Swap two logical drives LB$WINDRV DB 0,0,0 ; Set/get win drive parameters LB$PHYTAB DB 0,0,0 ; Set/get phytab access LB$GET$LDTE DB 0,0,0 ; Get physical table entry address LB$RESERVED DB 0,0,0 ; Reserved entry LB$XLEN EQU $-LB$XTBL ; Length of extra table LB$VERS DB 0 doit /COMP1: lda cltype ora a jnz comp1z CALL CONIN ; comp1z CPI ESC ;esc? JZ MAIN ;return to main menu CPI ETX ;^c? JZ DONE ;endit ANI CAPS ;force upper case CPI 'A' ;a? JZ ACT ;actrix CPI 'B' ;b? JZ DEC ;dec vt180 CPI 'C' ;c? JZ H10 ;heath/zenith 100 ssdd CPI 'D' ;d? JZ H12 ;heath/zenith 89 sssd CPI 'E' ;e? JZ H1 ;heath/zenith ssdd CPI 'F' ;f? JZ H4 ;heath/zenith ssxd CPI 'G' ;g? JZ H3 ;heath w/magnolia CPI 'H' ;h? JZ IBMSS ;ibm ssdd CP : lda cldrive ora a jnz getdrvc sign2c: LXI D,SIGNON ;point to sign on message CALL OUTPUT ; lda lb$vers cpi 20 cp display$fdev lxi d,sign2 call output ; ;getdrv checks which drive is selected as the "e" drive. ; GETDRV: CALL CONIN ;get drive selection getdrvc CPI ESC ;esc? JZ DONE ;endit CPI ETX ;^c? JZ DONE ; ANI CAPS ;force upper case cpi 'A' jc another cplug1 equ $+1 cpi 'E' jnc another sta drvsel+7 sta sgnoff+19 sui 'A' jplug1: jmp ge I 'I' ;i? JZ KAY2 ;kaypro ii CPI 'J' ;j? JZ LOBO ;lobo ssdd CPI 'K' ;k? JZ MOR ;morrow md2 CPI 'L' ;l? JZ NEC ;nec pc8001a CPI 'M' ;m? JZ OS1 ;osborne 1 sssd CPI 'N' ;n? JZ OSB ;osborne 2 ssdd CPI 'O' ;o? JZ TISS ;ti ssdd CPI 'P' ;p? JZ TRS80 ;trs80-1 CPI 'Q' ;q? JZ TRS3 ;trs80-3 CPI 'R' ;r? JZ TRS4 ;trs80-4 CPI 'S' ;s? JZ XERSD ;xerox 820-1 CPI 'T' ;t? JZ XERDD ;xerox 820-2 lda cltype ora a jz comp1 xra a sta cltype jmp prts t$20e call lb$get$ldte mov a,m cpi 1 jnz another inx h mov a,m ani 3 get$20e sta drive jmp main another lda cldrive ora a jz getdrv xra a sta cldrive jmp sign2c MAIN: lda clmenu ora a jnz compc LXI D,MAINMU ;point to main menu CALL OUTPUT ;print the main menu lxi d,mainm2 call output ; ;comp checks which sub-menu is selected and prints it. ;^c allows exit to cp/m. ; COMP: CALL CONIN ; compc CPI ESC ;esc? JZ DONE ;end if so CPI ETX ;^c? ub ; ;comp2 checks to see which double sided 48 tpi format ;has been selected. ^c exits to cp/m. ; COMP2: lda cltype ora a jnz comp2z CALL CONIN ; comp2z CPI ESC ;esc? JZ MAIN ;return to main menu CPI ETX ;^c? JZ DONE ;endit ANI CAPS ;force upper case CPI 'A' ;a? JZ H11 ;heath/zenith 100 dsdd CPI 'B' ;b? JZ H2 ;heath/zenith 89 dsdd CPI 'C' ;c? JZ H5 ;heath/zenith dsxd CPI 'D' ;d? JZ KAY4 ;kaypro 4/10 CPI 'E' ;e? JZ LOBO1 ;lobo dsdd CPI 'F' ;f Z? JZ MOR1 ;morrow md3 CPI 'G' ;g? JZ PMC ;pmc type a CPI 'H' ;h? JZ SAN ;sanyo mbc1000/1100 CPI 'I' ;i? JZ TEL ;televideo 802/803 lda cltype ora a jz comp2 xra a sta cltype jmp prtsub ; ;comp3 checks to see which 96 tpi format has been selected. ;a ^c will allow you to exit directly ;to cp/m. ; COMP3: lda cltype ora a jnz comp3z CALL CONIN ; comp3z CPI ESC ;esc? JZ MAIN ;return to main menu CPI ETX ;^c? JZ DONE ;endit ANI CAPS ;force upper c |;B LF DB ' MULTIDSK MAIN MENU',CR,LF DB ' -- ---- ----',CR,LF,LF DB ' 1 - Single Sided 48 TPI Menu',CR,LF DB ' 2 - Double Sided 48 TPI Menu',CR,LF DB ' 3 - 96 TPI Menu',CR,LF zplug3b db 0 IF EIGHT$INCH DB ' 4 - SSSD IBM 3740 8" format',CR,LF ENDIF DB '$' mainm2: DB  0,0 DB LF DB  0,70 DB LF DB ' - Exit to CP/M',CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 D ase CPI 'A' ;a? JZ DEC1 ;dec rainbow CPI 'B' ;b? JZ EGL ;eagle 2e-2 ss CPI 'C' ;c? JZ H6 ;h/z 89 ssdd CPI 'D' ;d? JZ H7 ;h/z 89 dsdd CPI 'E' ;e? JZ H8 ;h/z 89 ssxd CPI 'F' ;f? JZ H9 ;h/z 89 dsxd lda cltype ora a jz comp3 xra a sta cltype jmp prtsub ; ;conin gets a single character from the keyboard and ;puts it in the accumulator. ; CONIN: MVI A,9 ; bios call avoids echo to console LHLD 1 MOV L,A PCHL ; ;output sends the message pointed to  B LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DRVSEL: DB CR,'Drive A Selected as the "E" Drive.',CR,LF DB 'Select 1, 2, 3, ' zplug3c db '4, ' DB 'or to Exit: $' ; ;the single sided 48 tpi menu... ; SS48: DB CR,LF,' ' DB 'These formats require a single or double sided 48% tpi ' DB 'drive.' DB CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0, 0 DB LF Lby de to the screen. ; OUTPUT: MVI C,9 ;print string function CALL 5 ;bdos RET ; ; TYPE: DB '1' ;which sub menu selected ; DRIVE: DB 1 ;selected drive ; ADDR: DS 2 ;"e" drive parms addr ; ;the signon message... ; SIGNON: DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB 0,0   DB '  U SINGLE SIDED 48 TPI MENU' DB CR,LF DB ' ------ ----- -- --- ----',CR,LF DB  0,0 DB LF DB ' A - ACTRIX (ACCESS) ' DB ' K - MORROW MD2',CR,LF DB ' B - DEC VT180 ' DB ' L - NEC PC8001A',CR,LF DB ' C - HEATH/ZENITH 100 ' DB ' M - OSBORNE 1',CR,LF DB ' D - HEATH/ZENITH 89 SD ' DB ' N - OSBORNE 2',CR,LF DB ' E - HEATH/ZENITH 89 DD ' DB ' O - TI Pro (CP/M 86)',CR,LF DB ' F - HEATH/ZENITH 89 XD ' DB ' P - TRS80-1 w/OMIKRON',CR,LF DB ' G - ,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB ' AMPRO Disk Compatibility Utility - Version ' VERSION: DB '2.4',CR,LF DB ' Copyright (c) 1984,85,86 AMPRO Computers, Inc.' DB CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,f0 DB LF DB ' MULTIDSK prepares your AMPRO system to read, write, ' DB 'run programs,',CR,LF,' an  HEATH w/MAGNOLIA ' DB ' Q - TRS80-3 w/MEM MERCHANT CP/M',CR,LF DB ' H - IBM (CP/M 86) ' DB ' R - TRS80-4 w/MONTEZUMA CP/M',CR,LF DB ' I - KAYPRO II ' DB ' S - XEROX 820-I',CR,LF DB ' J - LOBO MAX80 ' DB ' T - XEROX 820-II',CR,LF DB CR,LF DB 0,A0 DB LF DB ' - Return to Main Menu',CR,LF DB 0,0 DB LF DB 0,0 DB LF DB 0,W0 DB LF DB 'Select a format or to Main Menu: $' ; ;the double sided 48 tp gld access data on 5 1/4 inch ' DB 'diskettes formatted for many other',CR,LF,' computers.' DB CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB '$' sign2: DB lf,' Which drive do you wish to use as the "E" drive? ' DB '(A - ' plug1: DB 'D) $' MAINMU: DB CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 D #i menu... ; DS48: DB CR,LF DB 0,^0 DB LF,' ' DB 'These formats require a double sided 48 tpi drive.' DB CR,LF DB 0,0 DB LF DB 0,0 DB LF DB 0,0 DB LF DB 0,0 DB LF DB '  DOUBLE SIDED 48 TPI MENU' DB CR,LF DB ' ------ ----- -- --- ----',CR,LF DB LF DB ' ' DB 'A - HEATH/ZENITH 100',CR,LF DB ' ' DB 'B - HEATH/ZENITH 89 DD',CR,LF DB ' ' DB 'C - HEATH/ZENITH 89 XD',CR,LF DB s &' ' DB 'D - KAYPRO 4/10',CR,LF DB ' ' DB 'E - LOBO MAX80',CR,LF DB ' ' DB 'F - MORROW MD3',CR,LF DB ' ' DB 'G - PMC-101 MicroMate (Type "A")',CR,LF DB ' ' DB 'H - SANYO MBC 1000/1100',CR,LF DB ' ' DB 'I - TELEVIDEO 802/80H3',CR DB LF,LF DB ' - Return to Main Menu',CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,D0 DB LF DB 'Select a format or to Main Menu: $' ; ;the i 'N' jz loop2 jmp askd2x setdst: push h lhld 1 mvi l,74h mov a,m ori 40h mov m,a pop h jmp loop2 dsmsg: DB CR,LF,'Is the E-drive a 96tpi drive (Y/N)? ','$' ; ;loop moves the type byte, dpb, drive,and ;skew table to the location in the bios pointed to ;by the hl registers. the bytes to be moved are pointed ;to by the de registers and b contains the number ;of bytes to be moved. ; LOOP: nop nop nop lda type cpi '1' jz askd cpi '2' jz askd LOOP2: LDAX S2 96 tpi menu follows... ; TPI96: DB CR,LF DB  0, 0 DB LF,'  @ ' DB 'These formats require a 96 tpi drive.' DB CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB '  96 TPI MENU' DB CR,LF DB ' -- --- ----',CR,LF DB LF DB ' ' DB 'A - DEC RAINBOW (CP/M)',CR,LF DB ' ' DB 'B - EAGLE IIE-2 SSDD',CR,LF DB ' ' DB 'C - HEATH/ZENITH 89 SSDD',CR,LF D ;put 1st byte into a MOV M,A ;store it in bios INX D ;roll up d INX H ;roll up h DCR B ;decrement b JNZ LOOP2 ;loop until done LXI D,SGNOFF ; CALL OUTPUT ;print it RET ; ;the following tables contain the type byte, dpb, drive ;selected, and skew for the different formats ;which can be read/write. ; KAY2: LDA DRIVE ;get drive pointer back STA K2DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,27 ;number of bytes to move (1+15+1+10) LXI D,K2DPB ;point -DB ' ' DB 'D - HEATH/ZENITH 89 DSDD',CR,LF DB ' ' DB 'E - HEATH/ZENITH 89 SSXD',CR,LF DB ' ' DB 'F - HEATH/ZENITH 89 DSXD',CR,LF DB  0,0 DB LF DB  0,B0 DB LF DB ' - Return to Main Menu',CR,LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,0 DB LF DB  0,>0 DB LF DB 'Select a format or to Main Menu: $' ; to new dpb CALL LOOP ;put into memory LXI D,K2END ;point to end message JMP PRINT ; ; K2DPB: ;type byte DB 082H ;kaypro ii ssdd ;dpb DW 40 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 0C2H ;disk size-1 DW 63 ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 1 ;reserved tracks ;drive DB 1 ;drive selected ;skew table DB 0,1,2,3,4,5,6,7,8,9 ; K2END: DB ' KAYPRO II$' ; SAN: LDA DRIVE ;get drive 0 ;ending message... ; SGNOFF: DB CR,LF DB  0,0 DB LF,'Drive B is now a$' ENDIT: DB CR,LF,'drive when you call it "E".',CR,LF,'$' ; PRINT: CALL OUTPUT ;print it LXI D,ENDIT ;set up end routine PRINT1: CALL OUTPUT ; JMP 0 ;done ; ;wrgdrv loads the wrong drive error message, prints ;it and exits to cp/m. ; WRGDRV: LXI D,ERROR ;load error message CALL OUTPUT ;bdos DONE: LHLD OLDSP ;get stack back SPHL ;put it in sp RET ;return to zcpr3 ; ERROR: DB 7  pointer back STA SANDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,33 ;number of bytes to move (1+15+1+16) LXI D,SANDPB ;point to new dpb CALL LOOP ;put into memory LXI D,SANEND ;point to end message JMP PRINT ; ; SANDPB: ;type byte DB 0C5H ;sanyo dsdd ;dpb DW 32 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 9BH ;disk size-1 DW 63 ;# of directories-1 DB 80H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 2 ;reserve i ,CR,LF DB  0,r0 DB LF,'Wrong drive selected.',CR,LF DB 'MULTIDSK can only be run from drive A, B, C, or D.' DB CR,LF DB  0,0 DB LF,'$' ; askd: lda cl4896 cpi 'Y' jz setdst cpi 'y' jz setdst cpi 'N' jz loop2 cpi 'n' jz loop2 push b push d push h lxi d,dsmsg call output pop h pop d pop b askd2x push b push d push h call conin pop _h pop d pop b cpi esc jz done cpi etx jz done ani 05fh cpi 'Y' jz setdst cp d tracks ;drive DB 1 ;drive selected ;skew table DB 1,4,7,10,13,16,3,6,9,12,15,2,5,8,11,14 ; SANEND: DB ' SANYO MBC 1000/1100$' ; TEL: LDA DRIVE ;get drive pointer back STA TELDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,35 ;number of bytes to move (1+15+1+18) LXI D,TELDPB ;point to new dpb CALL LOOP ;put into memory LXI D,TELEND ;point to end message JMP PRINT ; ; TELDPB: ;type byte DB 0C5H ;televideo dsdd ;dpb DW 36 ;spt DB 4 ;block shift m DB 15 ;block mask DB 0 ;extent mask DW 0AAH ;disk size-1 DW 63 ;# of directories-1 DB 80H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 4 ;reserved tracks ;drive DB 1 ;drive selected ;skew table DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 ; TELEND: DB ' TELEVIDEO 802/803$' ; PMC: LDA DRIVE ;get drive pointer back STA PMCDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,PMCDPB ;point to new P PRINT ; EGLDPB: ;type byte DB 087H ;eagle 2e-2 ss ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 0C2H ;disk size-1 DW 191 ;# of directories-1 DB 0E0H ;allocation 0 DB 0 ;allocation 1 DW 30H ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,3,5,2,4 ; EGLEND: DB ' EAGLE IIE-2 SSDD 96tpi$' ; ACT: LDA DRIVE ;get drive pointer back STA ACTDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,26 ;number of dpb CALL LOOP ;put into memory LXI D,PMCEND ;point to end message JMP PRINT ; ; PMCDPB: ;type byte DB 0C7H ;pmc type a dsdd ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 194 ;disk size-1 DW 127 ;# of directories-1 DB 192 ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;drive selected ;skew table DB 1,2,3,4,5 ; PMCEND: DB ' PMC-101 MicroMate (Type "A")$' ; DEC: LDA DRIVE ;get vbytes to move (1+15+1+9) LXI D,ACTDPB ;point to new dpb CALL LOOP ;put into memory LXI D,ACTEND ;point to end message JMP PRINT ; ACTDPB: ;type byte DB 082H ;actrix (access) ;dpb DW 36 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 0AAH ;disk size-1 DW 63 ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,4,7,2,5,8,3,6,9 ; ACTEND: DB 'n ACTRIX (ACCESS) S drive pointer back STA DECDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,26 ;number of bytes to move (1+15+1+9) LXI D,DECDPB ;point to new dpb CALL LOOP ;put into memory LXI D,DECEND ;point to end message JMP PRINT ; DECDPB: ;type byte DB 082H ;dec vt180 ssdd ;dpb DW 36 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 0AAH ;disk size-1 DW 63 ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 2 ;r rSDD$' ; ; KAY4: LDA DRIVE ;get drive pointer back STA K4DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,27 ;number of bytes to move (1+15+1+10) LXI D,K4DPB ;point to new dpb CALL LOOP ;put into memory LXI D,K4END ;point to end message JMP PRINT ; ; K4DPB: ;type byte DB 0E6H ;kaypro 4/10 dsdd ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW (40*79)/16-1 ;disk size-1 DW 63 ;# of directories-1 DB 192 ;allocation 0 DB 0  eserved tracks ;drive DB 1 ;skew table DB 1,3,5,7,9,2,4,6,8 ; DECEND: DB ' DEC VT180$' ; ; DEC1: LDA DRIVE ;get drive pointer back STA DEC1DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,27 ;number of bytes to move (1+15+1+10) LXI D,DEC1DPB ;point to new dpb CALL LOOP ;put into memory LXI D,DEC1END ;point to end message JMP PRINT ; DEC1DPB: ;type byte DB 086H ;dec rainbow ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask ;allocation 1 DW 16 ;dir check size DW 1 ;reserved tracks ;drive DB 1 ;default b ;skew table DB 0,1,2,3,4,5,6,7,8,9 ; K4END: DB ' KAYPRO 4/10 DSDD$' ; ; H1: LDA DRIVE ;get drive pointer back STA H1DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,33 ;number of bytes to move (1+15+1+16) LXI D,H1DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H1END ;point to end message JMP PRINT ; ; H1DPB: ;type byte DB 081H ;heath/zenith ssdd ;dpb DW 32 ;s  DW 0C2H ;disk size-1 DW 127 ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,3,5,7,9,2,4,6,8,10 ; DEC1END: DB ' DEC RAINBOW SSDD 96tpi$' ; EGL: LDA DRIVE ;get drive pointer back STA EGLDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,EGLDPB ;point to new dpb CALL LOOP ;put into memory LXI D,EGLEND ;point to end message JM @pt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 097H ;disk size-1 DW 127 ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;default to b ;skew table DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 ; H1END: DB ' HEATH/ZENITH 89 SSDD$' ; ; H2: LDA DRIVE ;get drive pointer back STA H2DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,33 ;number of bytes to move (1+15+1+16) LXI D,  H2DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H2END ;point to end message JMP PRINT ; ; H2DPB: ;type byte DB 0C5H ;heath/zenith dsdd ;dpb DW 32 ;spt DB 4 ;block shift DB 15 ;block mask DB 0 ;extent mask DW 09BH ;disk size-1 DW 0FFH ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 040H ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 ; H2END: DB ' HEATH/ZENITH 89 DSDD  it LHLD ADDR ;get bios pointer back MVI B,33 ;number of bytes to move (1+15+1+16) LXI D,H6DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H6END ;point to end message JMP PRINT ; H6DPB: ;type byte DB 085H ;h/z 89 ssdd ;dpb DW 32 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 09BH ;disk size-1 DW 127 ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table _$' ; ; H3: LDA DRIVE ;get drive pointer back STA H3DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,26 ;number of bytes to move (1+15+1+9) LXI D,H3DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H3END ;point to end message JMP PRINT ; ; H3DPB: ;type byte DB 086H ;heath w/magnolia ssdd ;dpb DW 36 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 052H ;disk size-1 DW 05FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;alloca  DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 ; ; H6END: DB ' HEATH/ZENITH SSDD 96tpi$' ; H7: LDA DRIVE ;get drive pointer back STA H7DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,33 ;number of bytes to move (1+15+1+16) LXI D,H7DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H7END ;point to end message JMP PRINT ; H7DPB: ;type byte DB 0C5H ;h/z 89 dsdd ;dpb DW 32 ;spt DB 4 ;block shift DB 15 ;block mask DB 0 ;extent mask DW 013BH ;disk size-1 tion 1 DW 018H ;dir check size DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5,6,7,8,9 ; H3END: DB ' HEATH w/MAGNOLIA SSDD$' ; ; H4: LDA DRIVE ;get drive pointer back STA H4DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,H4DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H4END ;point to end message JMP PRINT ; ; H4DPB: ;type byte DB 083H ;heath ssxd ;dpb DW 40 ;spt DB 3 ;block s  DW 255 ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 64 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 ; H7END: DB ' HEATH/ZENITH DSDD 96tpi$' ; ; H8: LDA DRIVE ;get drive pointer back STA H8DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,H8DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H8END ;point to end message JMP PRI hift DB 7 ;block mask DB 0 ;extent mask DW 0BDH ;disk size-1 DW 07FH ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 020H ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5 ; H4END: DB ' HEATH/ZENITH SS EXTENDED DENSITY$' ; ; H5: LDA DRIVE ;get drive pointer back STA H5DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,H5DPB ;point to new dpb CALL LOOP ;put int NT ; H8DPB: ;type byte DB 087H ;h/z 89 ssxd ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 0C2H ;disk size-1 DW 127 ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,2,3,4,5 ; H8END: DB ' HEATH/ZENITH SSXD 96tpi$' ; H9: LDA DRIVE ;get drive pointer back STA H9DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to m o memory LXI D,H5END ;point to end message JMP PRINT ; ; H5DPB: ;type byte DB 0C7H ;heath dsxd ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 0 ;extent mask DW 0C2H ;disk size-1 DW 255 ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 64 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5 ; H5END: DB ' HEATH/ZENITH DS EXTENDED DENSITY$' ; ; H6: LDA DRIVE ;get drive pointer back STA H6DPB+16 ;store ove (1+15+1+5) LXI D,H9DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H9END ;point to end message JMP PRINT ; H9DPB: ;type byte DB 0C7H ;h/z 89 dsxd ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 0 ;extent mask DW 395 ;disk size-1 DW 255 ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 64 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,2,3,4,5 ; H9END: DB ' HEATH/ZENITH DSXD 96tpi$' ; H10: LDA DRI VE ;get drive pointer back STA H10DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,25 ;number of bytes to move (1+15+1+8) LXI D,H10DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H10END ;point to end message JMP PRINT ; H10DPB: ;type byte DB 82H ;h/z 100 ssdd ;dpb DW 20H ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 97H ;disk size-1 DW 127 ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size D&; NECEND: DB ' NEC PC8001A$' ; ; IBMSS: LDA DRIVE ;get drive pointer back STA IBMDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,25 ;number of bytes to move (1+15+1+8) LXI D,IBMDPB ;point to new dpb CALL LOOP ;put into memory LXI D,IBMEND ;point to end message JMP PRINT ; ; IBMDPB: ;type byte DB 082H ;ibm ssdd (cp/m 86) ;dpb DW 32 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 09BH ;disk size-1 DW 03FH ;# of directories-1 DB 0C0H iW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,2,3,4,5,6,7,8 ; H10END: DB ' HEATH/ZENITH 100 SSDD$' ; H11: LDA DRIVE ;get drive pointer back STA H11DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,25 ;number of bytes to move (1+15+1+8) LXI D,H11DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H11END ;point to end message JMP PRINT ; H11DPB: ;type byte DB 0C6H ;h/z 100 dsdd ;dpb DW 20H ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 1 ;reserved tracks ;drive DB 1 ;skew table DB 1,2,3,4,5,6,7,8 ; IBMEND: DB 'n IBM SSDD (CP/M 86)$' ; ; TISS: LDA DRIVE ;get drive back STA T1DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,25 ;number of bytes to move (1+15+1+8) LXI D,T1DPB ;point to new dpb CALL LOOP ;put into memory LXI D,T1END ;point to end message JMP PRINT ; ; T1DPB: ;type byte DB 082H ;ti pro ssdd (cp/m 86) ;dpb D& mask DW 9BH ;disk size-1 DW 255 ;# of directories-1 DB 0F0H ;allocation 0 DB 0 ;allocation 1 DW 64 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ;skew table DB 1,2,3,4,5,6,7,8 ; H11END: DB ' HEATH/ZENITH 100 DSDD$' ; H12: LDA DRIVE ;get drive pointer back STA H12DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,27 ;number of bytes to move (1+15+1+10) LXI D,H12DPB ;point to new dpb CALL LOOP ;put into memory LXI D,H12END ;point to end message JM W 32 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 09BH ;disk size-1 DW 03FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 1 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5,6,7,8 ; T1END: DB ' TI Pro SSDD (CP/M 86)$' ; ; XERDD: LDA DRIVE ;get drive back STA XDDDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,35 ;number of bytes to move (1+15+1+18) LXI D,XDDDPB ;point to new dpb CP PRINT ; H12DPB: ;type byte DB 01H ;h/z 89 sssd ;dpb DW 14H ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 5BH ;disk size-1 DW 63 ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 3 ;reserved tracks ;drive DB 1 ;skew table DB 1,2,3,4,5,6,7,8,9,10 ; H12END: DB ' HEATH/ZENITH 89 SSSD$' ; ; NEC: LDA DRIVE ;get drive pointer back STA NECDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,33 ;numALL LOOP ;put into memory LXI D,XDDEND ;point to end message JMP PRINT ; ; XDDDPB: ;type byte DB 081H ;xerox 820-ii ssdd ;dpb DW 34 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 09CH ;disk size-1 DW 03FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 ; XDDEND: DB ' XEROX 820-II SSDD$' ; ; XERSD: LDA D9ber of bytes to move (1+15+1+16) LXI D,NECDPB ;point to new dpb CALL LOOP ;put into memory LXI D,NECEND ;point to end message JMP PRINT ; ; NECDPB: ;type byte DB 081H ;nec pc8001a ;dpb DW 32 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 097H ;disk size-1 DW 03FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 RIVE ;get drive back STA XSDDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,35 ;number of bytes to move (1+15+1+18) LXI D,XSDDPB ;point to new dpb CALL LOOP ;put into memory LXI D,XSDEND ;point to end message JMP PRINT ; ; XSDDPB: ;type byte DB 0 ;xerox 820-i sssd ;dpb DW 18 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 052H ;disk size-1 DW 01FH ;# of directories-1 DB 080H ;allocation 0 DB 0 ;allocation 1 DW 8 ;dir check size aK DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,6,11,16,3,8,13,18,5,10,15,2,7,12,17,4,9,14 ; XSDEND: DB ' XEROX 820-I SSSD$' ; ; TRS80: LDA DRIVE ;get drive back STA TRSDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,35 ;number of bytes to move (1+15+1+18) LXI D,TRSDPB ;point to new dpb CALL LOOP ;put into memory LXI D,TRSEND ;point to end message JMP PRINT ; ; TRSDPB: ;type byte DB 0 ;trs-80 1 w/ omikron sssd ;dpb DW 18 ;spt DB 3 ;block s DB 15 ;block mask DB 1 ;extent mask DW 05EH ;disk size-1 DW 07FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,4,2,5,3 ; MSSEND: DB ' MORROW MD2 SSDD$' ; ; MOR1: LDA DRIVE ;get drive back STA MDSDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,MDSDPB ;point to new dpb CALL LOOP ;put into memory LXI D,MDSEND ;9hift DB 7 ;block mask DB 0 ;extent mask DW 052H ;disk size-1 DW 03FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,5,9,13,17,3,7,11,15,2,6,10,14,18,4,8,12,16 ; TRSEND: DB ' TRS80-1 w/OMIKRON SSSD$' ; ; LOBO: LDA DRIVE ;get drive back STA LSSDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,35 ;number of bytes to move (1+15+1+18) LXI D,LSSDPB ;point to new dpb point to end message JMP PRINT ; ; MDSDPB: ;type byte DB 0C7H ;morrow md3 dsdd ;dpb DW 40 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 0C2H ;disk size-1 DW 0BFH ;# of directories-1 DB 0E0H ;allocation 0 DB 0 ;allocation 1 DW 48 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,4,2,5,3 ; MDSEND: DB ' MORROW MD3 DSDD$' ; ; OSB: LDA DRIVE ;get drive back STA OSBDPB+16 ;store it LHLD ADDR ;get bios pointer backw CALL LOOP ;put into memory LXI D,LSSEND ;point to end message JMP PRINT ; ; LSSDPB: ;type byte DB 081H ;lobo max-80 ssdd ;dpb DW 36 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 0A5H ;disk size-1 DW 03FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 ; LSSEND: DB ' LOBO MAX-80 SSDD$' ; ; LOBO1: LDA D MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,OSBDPB ;point to new dpb CALL LOOP ;put into memory LXI D,OSBEND ;point to end message JMP PRINT ; ; OSBDPB: ;type byte DB 083H ;osborne 2 ssdd ;dpb DW 40 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 0B8H ;disk size-1 DW 03FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5 ; OSBENDpRIVE ;get drive back STA LDSDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,35 ;number of bytes to move (1+15+1+18) LXI D,LDSDPB ;point to new dpb CALL LOOP ;put into memory LXI D,LDSEND ;point to end message JMP PRINT ; ; LDSDPB: ;type byte DB 0C5H ;lobo max-80 dsdd ;dpb DW 36 ;spt DB 4 ;block shift DB 15 ;block mask DB 0 ;extent mask DW 0ACH ;disk size-1 DW 07FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check s: DB 'n OSBORNE 2 SSDD$' ; OS1: LDA DRIVE ;get drive back STA OS1DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,27 ;number of bytes to move (1+15+1+10) LXI D,OS1DPB ;point to new dpb CALL LOOP ;put into memory LXI D,OS1END ;point to end message JMP PRINT ; ; OS1DPB: ;type byte DB 05H ;osborne 1 sssd ;dpb DW 14H ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 2DH ;disk size-1 DW 3FH ;# of directories-1 DB 80H ;allocation 0 DB 0 uize DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17 ; LDSEND: DB ' LOBO MAX-80 DSDD$' ; ; MOR: LDA DRIVE ;get drive back STA MSSDPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,22 ;number of bytes to move (1+15+1+5) LXI D,MSSDPB ;point to new dpb CALL LOOP ;put into memory LXI D,MSSEND ;point to end message JMP PRINT ; ; MSSDPB: ;type byte DB 087H ;morrow md2 ssdd ;dpb DW 40 ;spt DB 4 ;block shift ;allocation 1 DW 16 ;dir check size DW 3 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,3,5,7,9,2,4,6,8,10 ; OS1END: DB 'n OSBORNE 1 SSSD$' ; ; TRS3: LDA DRIVE ;get drive back STA T3DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,27 ;number of bytes to move (1+15+1+10) LXI D,T3DPB ;point to new dpb CALL LOOP ;put into memory LXI D,T3END ;point to end message JMP PRINT ; ; T3DPB: ;type byte DB 86H ;trs80- w/memory merchant cp/m ssdd ;dpb DW 40 @ ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 5EH ;disk size-1 DW 7FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,2,3,4,5,6,7,8,9,10 ; T3END: DB ' TRS80-3 w/MEMORY MERCHANT CP/M SSDD$' ; TRS4: LDA DRIVE ;get drive back STA T4DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,35 ;number of bytes to move (1+15+1+18) LXI D,T4DPB ;point to new d restore to use 6ms rate ; ; 02/27/85 Version 2.1 ; Deleted warning message, and added a ; list of the floppy drives available. ; ; 12/12/84 Version 2.0 ; Added warning message for use with ; Bios version 2.1+ ; ; 05/13/84 Version 1.2 ; Added delays after line feeds. ; ; 05/08/84 Unreleased Ver. 1.1X ; Added Pmc, Sanyo and Televideo. ; ; 03/20/84 Release version 1.0. ;MULTIFMT allows formatting several foreign diskettes. It is based ;on the code developed for?pb CALL LOOP ;put into memory LXI D,T4END ;point to end message JMP PRINT ; ; T4DPB: ;type byte DB 81H ;trs80-4 w/montezuma cp/m ssdd ;dpb DW 36 ;spt DB 4 ;block shift DB 15 ;block mask DB 1 ;extent mask DW 54H ;disk size-1 DW 7FH ;# of directories-1 DB 0C0H ;allocation 0 DB 0 ;allocation 1 DW 32 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,3,5,7,9,11,13,15,17,2,4,6,8,10,12,14,16,18 ; T4END: DB ' TRS80-4 w/MONTEZUMA CP/M SSD_ AMPRODSK and uses most of the algorithms ;in that program. The major differences are: ; ; 1. Added a selection menu at the beginning of the program ; to allow different formats. Jump routines from this ; menu update TABLE near the end of the program for the ; new format. ; ; 2. Removed the "copy" code as it is not needed. ; ; 3. Added routines after formatting and before verify ; to write a "boot loader" on the diskette (required ; by several different formats). The TYPE byte dvD$' IBM3740: lhld 1 ; set double speed bit mvi l,74h mov a,m ori 80h mov m,a LDA DRIVE ;get drive back STA IBM3740DPB+16 ;store it LHLD ADDR ;get bios pointer back MVI B,43 ;number of bytes to move (1+15+1+26) LXI D,IBM3740DPB ;point to new dpb CALL LOOP2 ;put into memory LXI D,IBM3740END ;point to end message JMP PRINT ; ; IBM3740DPB: ;type byte DB 00H ; IBM 3740 ;dpb DW 26 ;spt DB 3 ;block shift DB 7 ;block mask DB 0 ;extent mask DW 242 ;d etermines ; which formats require a "boot loader". ; wd1770 equates REST EQU 0 ; slow restore RDSEC EQU 88H ; read sector command WRSEC EQU 0A8H ; write sector command WRTRK EQU 0F8H ; write track command STEPI EQU 58H ; step in command RDID EQU 0C8H ; read address command MOT EQU 80H ; motor on status WPR EQU 40H ; write protected status SPU EQU 20H ; disk at speed status (type i) TYP EQU 20H ; record type status (types ii and iii) RNF EQU 10H ; record not found status CRC EQUisk size-1 DW 63 ;# of directories-1 DB 192 ;allocation 0 DB 0 ;allocation 1 DW 16 ;dir check size DW 2 ;reserved tracks ;drive DB 1 ; ;skew table DB 1,7,13,19,25,5,11,17,23,3,9,15,21 DB 2,8,14,20,26,6,12,18,24,4,10,16,22 ; IBM3740END: DB ' SSSD IBM 3740 8"$' ; ; DS 64 ;32 level stack STACK: ; OLDSP: DS 2 ;room for old stack pointer ; ; ; END BEGIN 6L 8 ; crc error status TK0 EQU 4 ; track zero status (type i) LDT EQU 4 ; lost data status (types ii and iii) IDX EQU 2 ; index status (type i) DRQ EQU 2 ; data request status (types ii and iii) BSY EQU 1 ; controller busy status ERRII EQU WPR+RNF+CRC+LDT ; type ii error status mask ERRIII EQU WPR+LDT ; type iii error status mask CMND EQU 0C0H ; fdc command register WTRK EQU CMND+1 ; write to track register WSEC EQU WTRK+1 ; write to sector register WDAT EQU WSEC+1 ; write to data rK * * * * * MULTIFMT.ASM * * * * COPYRIGHT (C) 1984,85,86 AMPRO COMPUTERS, INC. * * * * * ; Assemble with ASM.COM or equivalent. There is no Z80 code. ;REVISION LOG: ; ; 02/05/86 Version 2.3 ; Changed index pulse detection so works ; better with microfloppies ; ; 06/24/85 Version 2.2 ; Changed floppy egister STAT EQU WDAT+1 ; fdc status register RTRK EQU STAT+1 ; read from track register RSEC EQU RTRK+1 ; read from sector register RDAT EQU RSEC+1 ; read from data register CONT EQU 0 ; system control port ROMOFF EQU 40H ; turn rom off SID0 EQU 0EFH ; mask side bit off SID1 EQU 10H ; side bit in control register SDEN EQU 20H ; single density bit in control register TRY EQU 3 ; tries TRYHARD EQU 10 ; we try harder MSEC EQU 167 ; constant for 1 ms delay CR EQU 13 ; carria 9ge return LF EQU 10 ; line feed ESC EQU 27 ; escape key UPCASE EQU 5FH ; upper case mask bdos equ 5 ORG 100H ;embed the copyright notice ; START: JMP BEGIN ; leave room for copyright DB ' MULTIFMT Copyright (c) 1984,85,86 AMPRO Computers, Inc. ' DB 13,10,26 ;set up the stack and print signon message ; BEGIN: LXI SP,STACK ; set local stack CALL CLRSC ; clear the screen CALL ILPRT ; print following text DB CR,LF,' Foreign Diskette Format/Verify Utility' DB CR,LF,' LB$BIOS$TBL ; Move bios to local storage LXI B,LB$LEN ; . (length of bios area) DB 0edh,0b0h ; . (move routine) MVI A,0 ; Test CP/M version CALL LB$GETNXT ; Get next jump table STA LB$VERS ; Save bios version INX H ; See if HL is 0FFFFh MOV A,H ; . ORA L ; . RZ ; If so, then old version DCX H ; Fix HL as it has the table addr LXI D,LB$XTBL ; Move extra table to local storage LXI B,LB$XLEN ; . (length of extra table) db 0edh,0b0h ; . (move routine) MVI A,0FFH ; Set NZ or <^C> to exit.$' ASK1A: CALL CONIN ; get response CPI ESC JZ EXIT ; exit to operation system CPI 3 JZ EXIT ; ctl c ANI UPCASE ; force upper case CPI 'F' JZ SETF ; if format CPI 'V' JZ SETV ; if verify JMP ASK1A ; otherwise, do this again ; set function code and do it ; SETF: MVI A,1 STA FUNC JMP FORMAT SETV: MVI A,2 STA FUNC JMP VERIFY ;setup the forma  t routine ; FORMAT: CALL CLRSC CALL ILPRT DB 8,32,CR,LF,LF ; overwrite response and make new line DB 'FORMAT prepares a fresh diskette for data or ' DB 'program storage.$' CALL ASK5 ; ask destination JC ASK1 ; restart if bad selection JMP ASK2 FORM0: CALL ASK6 ; give warning JC ASK1 CALL EXEC ; do it JMP ASK1 ; restart at end of format ;setup the verify routine ; VERIFY: CALL CLRSC CALL ILPRT DB 8,32,CR,LF DB CR,LF,'VERIFY checks the reliability of data on a disk.$'c; r? JZ H5 ; h/z 89 ssdd 96tpi CPI 'S' ; s? JZ H6 ; h/z 89 dsdd 96tpi CPI 'T' ; t? JZ H7 ; h/z 89 ssxd 96tpi CPI 'U' ; u? JZ H8 ; h/z 89 dsxd 96tpi JMP ASKAGN ; anything else ask again typeletter: db 'a' ASK2E: STC ; set error flag RET ;update TABLE routines begin here... ; K2: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,24 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA TYPE ; no type byte ST CALL ASK5 ; ask for destination disk JC ASK1 JMP ASK2 VERF0: CALL ASK3 ; ask to load disk JC ASK1 CALL EXEC ; do it JMP ASK1 ;get selection and update TABLE ; ASK2: CALL ILPRT ; print following string DB CR,LF,LF,'Formats Available:' DB CR,LF,LF DB ' ' DB '48 TPI FORMATS',CR,LF DB ' (48 tpi Drive Required)',CR,LF,LF DB 'A - H/Z 89 SSDD ' DB 'I - MORROW MD3 DSDD',CR,LF DB 'B - H/Z 89 DSDD ' DB 'J - OSBORNE 2 SSDD',CR,LF DB 'C - H/Z 89 SSXD ' DB 'K - JA SBIAS ; no bias STA TWOSID ; single sided format STA TPI96 ; 0=48tpi, 1=96tpi format LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,K2SKW ; point to skew table JMP MOVSKW ; move it to skew K2SKW: DB 0,8,3,6,1,9,4,7,2,5,255 EG: MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MVI A,79 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA TYPE ; no type byte STA SBIAS ; no bias STA TWOSID ; single sided formfPMC-101 MicroMate DSDD',CR,LF DB 'D - H/Z 89 DSXD ' DB 'L - SANYO MBC 1000/1100 DSDD',CR,LF DB 'E - H/Z 100 SSDD ' DB 'M - TELEVIDEO 802/803 DSDD',CR,LF DB 'F - H/Z 100 DSDD ' DB 'N - TRS80-3 w/MEM MERCH CP/M SSDD',CR,LF DB 'G - KAYPRO II SSDD ' DB 'O - TRS80-4 w/MONTEZUMA CP/M SSDD',CR,LF DB 'H - MORROW MD2 SSDD',CR,LF,LF DB ' ' DB '96 TPI FORMATS',CR,LF DB ' (96 tpi Drive Required)',CR,LF,LF DB 'P - DEC RAINBOW SSDD ' DB 'S - H/Z 89 DSDD ',CR,LF DB 'Q - EAGLE IIE-at INR A ; STA TPI96 ; 0=48tpi, 1=96tpi format LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew T4: MVI A,1 ; 256 bytes/sectors STA SIZE ; store it MVI A,21 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA TYPE ; no type byte STA SBIAS ; no bias STA TWOSID ; single sided format STA TPI96 ; 0=48tpi, 1=96tpi format LXI D,SEC256 ; point to data CALL M 2 SSDD ' DB 'T - H/Z 89 SSXD',CR,LF DB 'R - H/Z 89 SSDD ' DB 'U - H/Z 89 DSXD' DB CR,LF,LF,'Choose one or to Restart: $' ASKAGN: CALL CONIN ; get the answer CPI 3 ; ^c? JZ EXIT ; exit CPI ESC ; esc? JZ ASK1 ; return ANI UPCASE ; mask upper case sta typeletter CPI 'A' ; a? JZ H1 ; h/z 89 ssdd 48tpi CPI 'B' ; b? JZ H2 ; h/z 89 dsdd 48tpi CPI 'C' ; c? JZ H3 ; h/z 89 ssxd 48tpi CPI 'D' ; d? JZ H4 ; h/z 89 dsxd 48tpi CPI 'E' ; e? JZ H9 ; h/z 10OVDAT ; move to dat0 LXI D,T4SKW ; point to skew table JMP MOVSKW ; move it to skew T4SKW: DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,255 TR: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,24 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA TYPE ; no type byte STA SBIAS ; no bias STA TWOSID ; single sided format STA TPI96 ; 0=48tpi, 1=96tpi format LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI Dl0 ssdd CPI 'F' ; f? JZ H10 ; h/z 100 dsdd CPI 'G' ; g? JZ K2 ; kaypro 2 CPI 'H' ; h? JZ MD2 ; morrow md2 CPI 'I' ; i? JZ MD3 ; morrow md3 CPI 'J' ; j? JZ OSB ; osborne 2 CPI 'K' ; k? JZ PMC ; pmc-101 type a CPI 'L' ; l? JZ SAN ; sanyo mbc 1000/1100 CPI 'M' ; m? JZ TEL ; televideo 802/803 CPI 'N' ; n? JZ TR ; trs80-3 w/mem merchant cp/m CPI 'O' ; o? JZ T4 ; trs80-4 CPI 'P' ; p? JZ DEC ; dec rainbow CPI 'Q' ; q? JZ EG ; eagle CPI 'R' 8,TRSKW ; point to skew table JMP MOVSKW ; move it to skew TRSKW: DB 1,6,2,7,3,8,4,9,5,10,255 OSB: MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA TYPE ; no type byte STA SBIAS ; no sector bias STA TWOSID ; single sided format STA TPI96 ; 0=48tpi, 1=96tpi format LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew OSBSKW: DB 1,2,3,4,5,255 PMC: MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA TYPE ; no type byte STA SBIAS ; no sector bias STA TPI96 ; 0=48tpi, 1=96tpi format INR A STA TWOSID ; double sided format LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew SAN: MVI A,1 ; 256 byteAS ; no sector bias STA TWOSID ; single sided format MVI A,1 ; STA TPI96 ; 0=48tpi, 1=96tpi format LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,DECSKW ; point to skew table JMP MOVSKW ; move it to skew DECSKW: DB 1,2,3,4,5,6,7,8,9,10,255 H1: MVI A,1 ; 256 bytes/sectors STA SIZE ; store it MVI A,45 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TWOSID ; single sided format STA TPIs/sectors STA SIZE ; store it MVI A,45 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format STA TYPE ; type byte INR A ; roll up a STA TWOSID ; double sided format LXI D,SEC256 ; point to data CALL MOVDAT ; move to dat0 LXI D,SANSKW ; point to skew table JMP MOVSKW ; move it to skew SANSKW: DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,255 TEL: MVI A,1 ; 256 bytes/sectors STA <96 ; 0=48tpi, 1=96tpi format MVI A,4 ; STA TYPE ; type byte LXI D,SEC256 ; point to data CALL MOVDAT ; move to dat0 LXI D,H1SKW ; point to skew table JMP MOVSKW ; move it to skew H1SKW: DB 1,12,7,2,13,8,3,14,9,4,15,10,5,16,11,6,255 H2: MVI A,1 ; 256 bytes/sectors STA SIZE ; store it MVI A,45 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format INR A ; roll up a STA TWOSIZE ; store it MVI A,21 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format STA TYPE ; type byte INR A ; roll up a STA TWOSID ; double sided format LXI D,SEC256 ; point to data CALL MOVDAT ; move to dat0 LXI D,TELSKW ; point to skew table JMP MOVSKW ; move it to skew TELSKW: DB 1,4,7,10,13,16,2,5,8,11,14,17,3,6,9,12,15,18,255 MD2: MVI A,2 ; STA TYPE ; MVI A,3 ; 1024 ;SID ; double sided format MVI A,5 ; STA TYPE ; type byte LXI D,SEC256 ; point to data CALL MOVDAT ; move to dat0 LXI D,H1SKW ; point to skew table JMP MOVSKW ; move it to skew H3: MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TWOSID ; single sided format STA TPI96 ; 0=48tpi, 1=96tpi format MVI A,6 ; STA TYPE ; type byte LXI D,SEC1K ;bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no sector bias STA TWOSID ; single sided format STA TPI96 ; 0=48tpi, 1=96tpi format LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew MD3: MVI A,3 ; STA TYPE ; MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MV point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew H4: MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format INR A ; roll up a STA TWOSID ; double sided format MVI A,7 ; STA TYPE ; type byte LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKWI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no sector bias STA TPI96 ; 0=48tpi, 1=96tpi format INR A ; STA TWOSID ; double sided format LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew DEC: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,24 ; gap3 size STA GAP3 ; MVI A,79 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA TYPE ; no type byte STA SBI| ; point to skew table JMP MOVSKW ; move it to skew H5: MVI A,1 ; 256 bytes/sectors STA SIZE ; store it MVI A,45 ; gap3 size STA GAP3 ; MVI A,79 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TWOSID ; single sided format INR A ; 96 tpi format STA TPI96 ; 0=48tpi, 1=96tpi format MVI A,8 ; STA TYPE ; type byte LXI D,SEC256 ; point to data CALL MOVDAT ; move to dat0 LXI D,H1SKW ; point to skew table JMP MOVSKW ; move it to skew  H6: MVI A,1 ; 1024 bytes/sectors STA SIZE ; store it MVI A,45 ; gap3 size STA GAP3 ; MVI A,79 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias INR A ; roll up a STA TPI96 ; 0=48tpi, 1=96tpi format STA TWOSID ; double sided format MVI A,9 ; STA TYPE ; type byte LXI D,SEC256 ; point to data CALL MOVDAT ; move to dat0 LXI D,H1SKW ; point to skew table JMP MOVSKW ; move it to skew H7: MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it <MOVSKW: LXI H,SKEW ; point to skew MOVSK: LDAX D ; move into accum MOV M,A ; store it CPI 0FFH ; done? JZ RETURN ; INX D ; roll up de INX H ; roll up hl JMP MOVSK ; again RETURN: LDA FUNC ; get function # CPI 1 ; was it a format? JZ FORM0 ; JMP VERF0 ; if not format must be verify SEC128: DB 32,0E5H,32,0E5H,32,0E5H,32,0E5H SEC256: DB 64,0E5H,64,0E5H,64,0E5H,64,0E5H SEC512: DB 128,0E5H,128,0E5H,128,0E5H,128,0E5H SEC1K: DB 0,0E5H,0,0E5H,0,0E5H,0,0E5H ;tell them to pMVI A,102 ; gap3 size STA GAP3 ; MVI A,79 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TWOSID ; single sided format INR A ; roll up a STA TPI96 ; 0=48tpi, 1=96tpi format MVI A,10 ; STA TYPE ; type byte LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew H8: MVI A,3 ; 1024 bytes/sectors STA SIZE ; store it MVI A,102 ; gap3 size STA GAP3 ; MVI A,79 ; # of trJut the disk in ; ASK3: lda typeletter call conout CALL ILPRT ; print the following string DB CR,LF,LF,'Place disk in Drive ' ASK30s: db 'a' DB CR,LF,LF,'Press to VERIFY, ' DB ' to quit. $' JMP ASK6E ASK5: call disp$fdev CALL ILPRT DB CR,LF,LF,'Destination drive? (A - ' plug1: db 'D) $' ASK5E: CALL CONIN ; get the answer CPI ESC JZ EXIT CPI 3 JZ EXIT ANI UPCASE ; force upper case CPI 'A' ; first valid drive JC ASK5E cplug1: equ $+1 CPI 'E' ; fiacks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias INR A ; roll up a STA TPI96 ; 0=48tpi, 1=96tpi format STA TWOSID ; double sided format MVI A,11 ; STA TYPE ; type byte LXI D,SEC1K ; point to data CALL MOVDAT ; move to dat0 LXI D,OSBSKW ; point to skew table JMP MOVSKW ; move it to skew H9: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,121 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS Qrst invalid drive JNC ASK5E sta ask60d sta ask30s push psw call conout pop psw sui 'A' jplug1: jmp ask50s call lb$get$ldte mov a,m cpi 1 jnz ask5 inx h mov a,m ani 3 ask50s: STA DDRIV CALL SETSEL ; disk select bits ORA A RET ASK6: lda typeletter call conout CALL ILPRT ; print the following string DB CR,LF,LF,'Place destination disk on drive ' ask60d DB 'a' DB CR,LF,LF,'Press to write, ' DB ' to quit. $' ASK6E: CALL CONIN ; get answer CT ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format STA TWOSID ; single sided format MVI A,12 ; STA TYPE ; type byte LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,H100SKW ; point to skew table JMP MOVSKW ; move it to skew H100SKW: DB 1,2,3,4,5,6,7,8,255 H10: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,121 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi PI CR RZ CPI ESC JZ EXIT JMP ASK6E ;execute it! ; EXEC: CALL ILPRT DB CR,LF,LF,'$' LDA FUNC ; function 1=fmt, 2=vfy CPI 1 JZ FMT CPI 2 JZ VFY ; RET ;format routines... ; FMT: LDA DDRIV CALL SETSEL CALL SETUP XRA A STA TRACK STA HEAD NEXTRK: CALL KEY LXI H,FRMSG CALL PRINT CALL TMRPRT CALL MAKETRK MVI A,TRY STA TRIES NT3: CALL WRITRK JZ NT5 LXI H,TRIES DCR M JNZ NT3 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT yformat INR A ; roll up a STA TWOSID ; double sided format MVI A,13 ; STA TYPE ; type byte LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,H100SKW ; point to skew table JMP MOVSKW ; move it to skew ;move the new data to TABLE ; MOVDAT: MVI B,8 ; # of bytes to move LXI H,DAT0 ; point to data location MOVDT: LDAX D ; move byte to accum MOV M,A ; store it INX D ; roll up reg de INX H ; roll up reg hl DCR B ; count down 1 JNZ MOVDT ; done? RET failed.',CR,LF,'$' CALL REPORT RET NT5: LDA TWOSID ORA A LDA TRACK JZ NT0 LDA HEAD ORA A LDA TRACK JZ NT1 NT0: LXI H,MAXTRK CMP M JNZ NT1 CALL ILPRT DB CR,' ' DB CR,LF,'FORMAT complete.',CR,LF,LF,'$' ;check the TYPE byte to see if a boot loader is needed ; LDA TYPE ANI 0FH ; mask off upper nibble CPI 2 ; if morrow md2 JZ MD2GEN ; write boot loader CPI 3 ; if morrow md3 JZ MD3GEN ; wri)te boot loader CPI 4 ; if h/z 89 ssdd  JZ H1GEN ; write boot loader CPI 5 ; if h/z 89 dsdd JZ H2GEN ; write boot loader CPI 6 ; if h/z 89 ssxd (48tpi) JZ H3GEN ; write boot loader CPI 7 ; if h/z 89 dsxd (48tpi) JZ H4GEN ; write boot loader CPI 8 ; if h/z 89 ssdd (96tpi) JZ H5GEN ; write boot loader CPI 9 ; if h/z 89 dsdd (96tpi) JZ H6GEN ; write boot loader CPI 10 ; if h/z 89 ssxd (96tpi) JZ H7GEN ; write boot loader CPI 11 ; if h/z 89 dsxd (96tpi) JZ H8GEN ; write boot loader CPI 12 ; if h/z 100 s\ LOAD ; CALL MOVE5 ; CALL LOAD ; CALL MOVE5 ; CALL LOAD ; CALL MOVE5 ; CALL LOAD ; LXI D,DAT3 ; MVI B,60 ; CALL MOVDT ; MVI D,68 ; MVI E,0 ; CALL LOAD ; CALL MOVE5 CALL LOAD CALL MOVE5 CALL LOAD CALL MOVE5 CALL LOAD CALL MOVE5 CALL LOAD JMP GEN ; MOVE5: MVI E,0E5H ; MVI D,0 ; RET H1GEN: CALL HGEN ; load skew1 LXI D,H1DAT ; point to h1 data JMP HGEN1 ; store data H2GEN: CALL HGEN ; load skew1 LXI D,H2DAT ; point to h2 data Jmsdd JZ H9GEN ; write boot loader CPI 13 ; if h/z 100 dsdd JZ H10GEN ; write boot loader JMP VFY ; anything else begin verify NT1: INR A STA TRACK CALL STEPIN JMP NEXTRK ;verify routines begin here ; VFY: MVI A,0 STA HEAD LDA DDRIV CALL SETSEL CALL SETUP MVI A,TRY STA TRIES V1: CALL READID JZ V0 LXI H,TRIES DCR M JNZ V1 CALL ILPRT DB CR,LF,'VERIFY failed. Cannot read source disk.',cr,lf,'$' RET V0: LDA TWOSID CPI 1 MVI A,0 JC VF0 INR A VF0: MP HGEN1 ; store the data H3GEN: CALL HGEN LXI D,H3DAT JMP HGEN2 H4GEN: CALL HGEN LXI D,H4DAT JMP HGEN2 H5GEN: CALL HGEN LXI D,H5DAT JMP HGEN1 H6GEN: CALL HGEN LXI D,H6DAT JMP HGEN1 H7GEN: CALL HGEN LXI D,H7DAT JMP HGEN2 H8GEN: CALL HGEN LXI D,H8DAT JMP HGEN2 H9GEN: CALL HGEN LXI D,H9DAT JMP HGEN2 H10GEN: CALL HGEN LXI D,H10DAT JMP HGEN2 HGEN: MVI A,1 ; load STA SKEW1 ; skew MVI A,255 ; table STA SKEW1+1 ; RET HGEN1: ;use this routiSTA TWOSID XRA A STA TRACK ; start with track 0 VLOOP: CALL KEY LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES VL1: CALL READTRK JZ VL0 LXI H,TRIES DCR M JNZ VL1 CALL ILPRT DB CR,' ' DB CR,LF,'VERIFY failed. Unrecoverable read error.',CR,LF,'$' CALL REPORT RET VL0: LDA TWOSID ORA A LDA TRACK JZ VF1 LDA HEAD ORA A LDA TRACK JZ VF2 VF1: LXI H,MAXTRK CMP M JNZ VF2 CALL ILPRT DB CR,' 'ne for 256 byte sector h/z formats MVI B,29 ; # of bytes to move LXI H,TKBUF ; point to buffer area CALL MOVDT ; move data MVI E,0E5H ; fill data MVI D,227 ; # of bytes to move CALL LOAD ; move them JMP GEN HGEN2: ;use this routine for 512/1024 byte sector h/z formats MVI B,29 ; # of bytes to move LXI H,TKBUF ; point to buffer area CALL MOVDT ; move data MVI E,0E5H ; fill data MVI D,227 ; # of bytes to move CALL LOAD ; move them CALL MOVE5 CALL LOAD CALL MOVE5  DB CR,LF,'VERIFY complete.',CR,LF,'$' RET VF2: INR A STA TRACK CALL STEPIN JMP VLOOP ;boot loader routine begin here ; ;gen as in sysgen! ; GEN: LDA DDRIV ; CALL SETSEL ; CALL SETUP ; setup write XRA A ; zero out acc STA TRACK ; track 0 STA HEAD ; LXI H,TKBUF ; get point SHLD DMAADR ; save buffer pointer LXI H,SKEW1 ; point to new skew CALL WTLOOP ; write data JMP VFY MD2GEN: CALL MDGEN ; LXI D,DAT4 ; point to next data MVI B,25 ; CALL M CALL LOAD CALL MOVE5 CALL LOAD JMP GEN ;step in the drive ; STEPIN: LDA TWOSID ORA A JZ STI ; single sided LDA HEAD ORA A MVI A,1 JZ STI0 MVI A,0 STI0: STA HEAD JZ STI1 STI: LDA SELBYT ANI SID0 ; mask side bit off OUT CONT ; select side 0 STA SELBYT CALL WAIT MVI A,STEPI CALL OUTCMD STILP: IN STAT RAR JC STILP RET STI1: LDA SELBYT ORI SID1 OUT CONT ; select side 1 STA SELBYT LXI H,TRACK DCR M JMP WAIT ;write a track ; WRITRK: INOVDT ; JMP MD1GEN ; MD3GEN: CALL MDGEN ; LXI D,DAT5 ; point to next data MVI B,25 ; move double sided dpb CALL MOVDT ; JMP MD1GEN ; MDGEN: MVI A,1 ; STA SKEW1 ; INR A ; STA SKEW1+1 ; MVI A,255 ; STA SKEW1+2 ; LXI D,DAT3 ; point to morrow data MVI B,60 ; # of bytes to move LXI H,TKBUF ; point to buffer area CALL MOVDT ; move data MVI E,0 ; fill data MVI D,68 ; # of bytes to move CALL LOAD ; move them RET MD1GEN: MVI E,0 ; MVI D,103 ; CALL STAT RAR JC WRITRK LXI H,TKBUF MVI A,WRTRK ; write track command CALL OUTCMD CALL WR MOV A,B STA STATUS ANI ERRIII RET WR: IN STAT ; get fdc status MOV B,A ; save status RAR ; check busy RNC ; end of command, return to caller RAR ; check for drq JNC WR ; if not MOV A,M ; get a byte from buffer OUT WDAT ; to fdc INX H ; bump hl JMP WR ; again ;make a track in memory ; MAKETRK: LXI H,TKBUF ; create track image in memory MVI B,60 MVI A,4EH MT LP: MOV M,A ; write gap4a INX H DCR B JNZ MTLP SHLD DMAADR ; sector 1 starts here LDA HEAD STA SIDE LXI H,SKEW ;load skew table pointer LOOP: MOV C,M INX H INR C JZ ENDTRK ; if c was 0ffh DCR C LDA SBIAS ADD C STA SECTOR PUSH H ; save skew pointer on stack CALL MAKTRK POP H JMP LOOP ENDTRK: LHLD DMAADR LXI B,1000 ETLP: MVI M,4EH ;end track fill data INX H DCX B MOV A,B ORA C JNZ ETLP SHLD DMAADR RET MAKTRK: LHLD DMAADR ; track image PUSH ; end of command, return to caller RAR ; rotate data request to carry JNC RD ; wait for data request RD0: IN RDAT ; get data from fdc MOV M,A ; put it into buffer INX H ; bump hl JMP RD ; again READID: IN STAT IN RDAT LXI H,IDSV MVI A,RDID CALL OUTCMD CALL RD MOV A,B ; get status STA STATUS ANI ERRIII RET ;allow FDC to setup properly ; WAIT: LXI B,50 * MSEC WT0: DCX B MOV A,B ORA C JNZ WT0 RET WAIT10: LXI B,10 * MSEC JMP WT0 LOAD: MOV M,E ; H ; save it LXI H,TABLE ; track format table MAKT1: MOV D,M ; get count INX H ; bump pointer MOV E,M ; get data INX H ; bump pointer MOV A,E ; check for end of table (0ffh) INR A ; 0ffh + 1 = 0 JZ MAKT2 ; if end of table XTHL ; point to track buffer CALL LOAD ; fill track buffer XTHL ; point to format table JMP MAKT1 ; again MAKT2: POP H ; get track buffer address from stack SHLD DMAADR ; save pointer to track buffer RET ; to caller ;write current track fr (e) to track buffer INX H ; increment pointer DCR D ; decrement count JNZ LOAD ; again RET CLRSC: MVI D,24 ; print 24 line feed chars to clear screen CLS: MVI A,LF CALL CONOUT ; out to console CALL WAIT10 ; wait 10 ms after line feed DCR D ; decrement count JNZ CLS ; again RET PRINT: MOV A,M ; hl points to text string INX H ; bump hl CPI '$' ; check for terminator RZ ; return to caller CALL CONOUT ; send byte to console JMP PRINT ; again pCONOUT: PUSH Rom read buffer ; WRITETRK: LXI H,RDBUF SHLD DMAADR LXI H,SKEW ; point to skew table WTLOOP: MOV C,M INX H ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C OUT WSEC ; to fdc PUSH H ; save skew pointer CALL WRITESEC POP H JMP WTLOOP ;write a sector from DMA buffer ; WRITESEC: IN STAT ; clear status IN RDAT ; clear any trash LHLD DMAADR MVI A,WRSEC ; write sector command CALL OUTCMD ; to fdc CALL WR ; write the data UB ; save PUSH D ; the PUSH H ; registers MOV E,A ; text to be printed MVI C,2 ; console output function CALL 5 ; bdos POP H ; restore POP D ; the POP B ; registers RET ;prints next byte pointed to by top of stack ;until delimiter $ is found ; ILPRT: XTHL ; return address to hl points to text ILP: MOV A,M ; get next byte INX H ; bump pointer CPI '$' ; check for string terminator JZ ILPE ; if end of string CALL pCONOUT ; send byte to console JMP ILP SHLD DMAADR ; save pointer MOV A,B ; get status STA STATUS ANI ERRII RZ ; return to this caller POP H ; adjust stack from writetrk POP H RET ; return to previous caller ;read current track into read buffer ; READTRK: LXI H,RDBUF SHLD DMAADR LXI H,SKEW ; point to skew table RTLOOP: MOV C,M ; get sector number from table INX H ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C STA SECTOR OUT WSEC ; to fdc PUSH H ; save sk  ; again ILPE: XTHL ; put updated pointer on stack RET CONOUT: PUSH B ; save PUSH D ; the PUSH H ; registers MOV E,A ; text to be printed MVI C,6 ; console output function CALL 5 ; bdos POP H ; restore POP D ; the POP B ; registers RET CONIN: MVI A,9 ; bios call avoids echo to console BIOS: LHLD 1 MOV L,A PCHL CONINB: PUSH B PUSH D ; save PUSH H ; registers MVI C,1 ; console input function CALL 5 ; bdos POP H ; restore POP D ; registerew pointer CALL READSEC ; read the sector RT0: POP H JMP RTLOOP READSEC: IN STAT ; clear status IN RDAT ; clear any trash LHLD DMAADR ; pointer to read buffer MVI A,RDSEC ; read sector command CALL OUTCMD ; to fdc CALL RD ; read the data SHLD DMAADR ; save pointer MOV A,B STA STATUS ANI ERRII RZ POP H ; adjust stack from readtrk POP H RET ; to previous caller RD: IN STAT ; get fdc status byte MOV B,A ; save status RAR ; rotate busy bit to carry RNCs POP B RET ; ;restore the disk and wait for status ; ; The current setup routine does a restore with the 1772 ; motor on flag enabled. It exits as soon as the BUSY ; status bit goes away, or after a 4 second timeout. SETUP: LDA SELBYT ; get selected drive OUT CONT ; select the drive MVI A,REST ; restore command CALL OUTCMD ; output the command LXI H,4000 ; 4000 ms timeout setup DEL0: MVI C,0 DEL1: DCR C JNZ DEL1 IN STAT RAR JNC READY ; go on if 1772 done DCX   H MOV A,H ORA L JNZ DEL1 MVI A,0D0H ; timed out -- force interrupt, CALL OUTCMD ; then report failure JMP FAILED ; The current ready function checks to see if a diskette ; is inserted in a drive. A read address command with ; the motor on flag enabled is used. If the command ; hangs up, the 1772 is not receiving index pulses, ; indicating the lack of a spinning diskette. READY: MVI A,0C0H ; read address command CALL OUTCMD LXI H,4000 ; 4000 mS timeout setup MVIWSH PSW ; save value PUSH D ; save string ptr MVI A,'0' ; ascii zero STAX D LXI B,2 ; b=0, c=2 XRA A ; a=0 B0: INX D ; bump ptr STAX D ; zero to str DCR C JNZ B0 ; again please POP D ; restore de LXI H,TBL ; conversion table B1: MVI C,0 ; clear count MOV A,M ; table value INR A JZ BEND ; end of table, conv done POP PSW ; restore value B3: SUB M ; begin division JC B2 INR C ; keep count JMP B3 B2: ADD M ; restore acc PUSH PSW ; save it MOV A,C ; couC C,0 RDY1: DCR C JNZ RDY1 IN STAT RAR RNC ; finished, if 1772 done DCX H MOV A,H ORA L JNZ RDY1 ; loop till timeout MVI A,0D0H ; timeout -- force interrupt, CALL OUTCMD ; then report failure FAILED: LDA SELBYT ANI 0FH MVI C,0 FLD1: INR C RAR JNC FLD1 MOV A,C adi 30H ; add ascii bias STA DRI CALL ILPRT ; print following string DB CR,LF,'Drive ' DRI: DB 'A Not Ready, Insert disk, close door, and try again.',CR,LF,'$' POP B ; adjust stack RET nt CPI 0 JNZ STSTR ; set ascii value in string MOV A,B CPI 0 ; 1st time? JNZ STSTR B4: INX H ; bump tbl ptr JMP B1 ; next STSTR: MVI B,1 ; flag 1st time MOV A,C ; count to c ADI 30H ; ascii bias STAX D ; write it into string INX D ; bump str ptr JMP B4 BEND: POP PSW ; adjust stack RET ; return to caller TBL: DB 100 DB 10 DB 1 DB 255 ; end of table ;setup the selbyt ; SETSEL: inr a MOV C,A XRA A STC STSL: RAL DCR C JNZ STSL ORI ROMOFF  ;send a command to the FDC ; OUTCMD: OUT CMND MVI A,10 OC0: DCR A JNZ OC0 ; wait 35 us. for fdc to set-up RET KEY: push b push d mvi c,6 mvi e,0ffh call 5 pop d pop b rz CPI 3 JZ EXIT PUSH PSW CALL ILPRT DB CR,' ',CR,'$' ; clear the line POP PSW CPI ESC RNZ POP H RET EXIT: JMP 0 ; warm boot TMRPRT: LDA TRACK LXI D,TKMSG0 CALL BINASC LDA HEAD LXI D,SDMSG0 CALL BINASC LXI H,TKMSG JMP PRINT ; print returns t STA SELBYT RET ;error messages... ERRMSG: DB CR,LF,' Error: Drive ' DR: DB 0,': Track ' TK: DB 0,0,0,' Head ' HD: DB 0,0,0,' Sector ' SC: DB 0,0,0,' Status ' ST: DB 0,0,0,CR,LF,'$' TKMSG: DB 'Track ' TKMSG0: DB 0,0,0,' Side ' SDMSRG0: DB 0,0,0,CR,'$' VFMSG: DB 'Verify $' FRMSG: DB 'Format $' WPRMSG: DB CR,' ' DB CR,LF,'Remove write protect tab from ' DB 'destination diskette.' DB CR,LF,'Place diskette in drive ' WPRMSG0:DB 'A, then press . $' DNRER: DB 'DNR' RNFER: DB 'RNF' CRCER: DB 'CRC' ;the main data table.. ; TABLE: DB 12,0 ; defines sector format (#bytes,data) DB 3,0F5H ; write 0a1h DB 1,0FEH ; id address mark DB 1 TRACK: DB 0 DB 1 SIDE: DB 0 DB 1 SECTOR: DB 1 DB 1 SIZE: DB 3 ; always 512 bytes DB 1,0F7H ; write crc (2 bytes) GAP2: DB 22,4EH ; gap 2 length, data PREAM: DB 12,0 ; preamble DB 3,0F5H ; write 0a1h DB 1,0FBH ; data address mark DAT0: DB 0,0E5H ; bytes of data fill DB 0,0E5out of here R2: LXI D,TK ; in error message LDA TRACK CALL BINASC LXI D,HD LDA SIDE ORA A ; set flags JZ RPRT1 MVI A,1 RPRT1: CALL BINASC LXI D,SC LDA SECTOR CALL BINASC LXI D,ST LDA STATUS ANI RNF JNZ SRNF LXI H,CRCER CALL MOV3 JMP RPRT2 SDNR: LXI H,DNRER CALL MOV3 JMP RPRT2 SRNF: LXI H,RNFER CALL MOV3 RPRT2: LXI H,ERRMSG RPRT3: JMP PRINT ; print returns to caller MOV3: MVI B,3 MOVL: MOV A,M STAX D INX H INX D DCR B JNZ MOVL RET BINASC: PUH ; bytes of data fill DB 0,0E5H ; bytes of data fill DB 0,0E5H ; bytes of data fill DB 1,0F7H ; write crc (2 bytes) GAP3: DB 0,4EH ; gap 3 length, data DW -1 ; end of table (0ffffh) SKEW: DS 40 DAT3: DB 0,0,0,3EH,0C9H,32H,255,253,0CDH,255,253,21H,254,255,39H,5EH DB 23H,56H,21H,17H,0,19H,0EBH,31H,0,255,0D3H,0F6H,0CDH,3,0,0C3H DB 18H,0,CR,LF,'Not a SYSTEM Diskette',CR,LF DAT4: DB 0,C0 DB 40,0,4,15,1,5EH,0,7FH,0,0C0H,0,32,0,2,0,0E1H DAT5: DB 0,4,0 DB d 40,0,4,15,1,0C2H,0,0BFH,0,0E0H,0,30H,0,2,0,89H H1DAT: DB 0E5H,0E5H,0E5H,0E5H,0,62H,0E5H,2,8,0E5H,0E5H,0,0E5H DB 20H,0,3,7,0,97H,0,7FH,0,0F0H,0,20H,0,2,0,0ADH H2DAT: DB 0E5H,0E5H,0E5H,0E5H,0,63H,0E5H,2,16,0E5H,0E5H,0,0E5H DB 20H,0,4,15,0,9BH,0,255,0,0F0H,0,40H,0,2,0,0F7H H3DAT: DB 0E5H,0E5H,0E5H,0E5H,0,66H,0E5H,8,8,0E5H,0E5H,0,0E5H DB 28H,0,3,7,0,0BDH,0,7FH,0,0F0H,0,20H,0,2,0,75H H4DAT: DB 0E5H,0E5H,0E5H,0E5H,0,67H,0E5H,8,16,0E5H,0E5H,0,0E5H DB 28H,0,4,15,0,0C2H,0,255,0,0F0H,0,40H,0,2,0,\ 0 the destination R/O attribute - RLH ; ; ** NOTE **R ; * Version 2.0 and later require AMPRO BIOS Version 2 and later * ;  ** ; 2.0 1/28/86 ZImproved SWAPCOPY program - RLH ; 2.1 1/29/86 Added trap for Version 1 BIOS - rbl ; 2.2 1/30/86 MAdded trap for valid floppy drives only - RLH ; ; ;allows files to be tran0BEH H5DAT: DB 0E5H,0E5H,0E5H,0E5H,0,6AH,0E5H,2,16,0E5H,0E5H,1,0E5H DB 20H,0,4,15,1,9BH,0,7FH,0,0C0H,0,20H,0,2,0,0BEH H6DAT: DB 0E5H,0E5H,0E5H,0E5H,0,6BH,0E5H,2,16,0E5H,0E5H,1,0E5H DB 20H,0,4,15,0,3BH,1,255,0,0F0H,0,40H,0,2,0,4DH H7DAT: DB 0E5H,0E5H,0E5H,0E5H,0,6EH,0E5H,8,16,0E5H,0E5H,1,0E5H DB 28H,0,4,15,1,0C2H,0,7FH,0,0C0H,0,20H,0,2,0,85H H8DAT: DB 0E5H,0E5H,0E5H,0E5H,0,6FH,0E5H,8,16,0E5H,0E5H,1,0E5H DB 28H,0,4,15,0,8AH,1,255,0,0F0H,0,40H,0,2,0,0ECH H9DAT: DB 0E5H,0E5H,0E5H,0E5H,0,2lsfered from one diskette to ;another in a system with only a single drive. ; ;allows ambiguous file specifications. ;allows transfer of files larger than available memory, ;and transfer of multiple files in a single pass. ; ;allows use of dissimiliar media (i.e., to copy ;programs from a single density master diskette ;to a double density working diskette). ;self prompting for operator convience ; ;for use with AMPRO 8 bit machines ONLY ; ;developed using CP/M 2.0, but uses only those bdos c=2H,1,4,8,27H,80H,0,11H DB 20H,0,3,7,0,97H,0,127,0,0F0H,0,20H,0,2,0,0C6H H10DAT: DB 0E5H,0E5H,0E5H,0E5H,0,23H,1,4,16,27H,80H,0,11H DB 20H,0,4,15,1,9BH,0,255,0,0F0H,0,40H,0,2,0,15 SKEW1: DS 4 ; TYPE: DB 0 ; 2=morrow ss, 3=morrow ds etc. FUNC: DS 1 ; function 1=format, 2=verify, MAXTRK: DB 39 ; maximum track TWOSID: DB 0 ; 0=ss , 1=ds HEAD: DB 0 ; SDRIV: DS 1 ; source drive DDRIV: DS 1 ; destination drive SELBYT: DS 1 ; SBIAS: DB 0 ; sector bias 0=ss, 10h=ds, 30h=ds96 TPI96: alls ;which are supported under CP/M 1.4 except BDOS CALL 30 - SET FILE ATTRIBUTES ; ; disk to disk file transfer program. ; ; at the command level, the command: ; ; SWAPCOPY ; ; will copy the file filename.ext from the source diskette ; to destination diskette, prompting as necessary to allow the ; diskettes to be swapped if necessary. ; BOOT EQU 0 ;system reboot BDOS EQU 5 ;bdos entry point MEMTOP EQU 6 ;pointer to start of fbase FCB1 EQU 5CH ;first file name & source fōDB 1 ; 0=48tpi , 1=96tpi DMAADR: DS 2 ; STATUS: DS 1 ; TRIES: DS 1 ; DS 64 ; space for 32 level stack STACK: DS 2 ; space for ccp stack pointer IDSV: DS 6 ; id save area RDBUF: DS 10 * 512 ; read buffer TKBUF: END START ; end of program  ? ; source drive DDRIV: DS 1 ; destination drive SELBYT: DS 1 ; SBIAS: DB 0 ; sector bias 0=ss, 10h=ds, 30h=ds96 TPI96:  cb FCB2 EQU 6CH ;second file name TPA EQU 100H ;beginning of tpa ; FALSE EQU 0 TRUE EQU 255 ; NUMKEYS EQU 14 CNTRLC EQU 3 ESC EQU 1BH TAB EQU 9 NUL EQU 0 LF EQU 10 CR EQU 13 BELL EQU 7 SECSIZ EQU 128 ;bytes per sector ; ORG TPA ; SWAPCOPY: LXI SP,STACK ;set up local stack space ; SETUP: MVI A,FALSE STA DONE ;we're not done yet STA ONE2GO ;nor do we have a file to go ; LXI H,BUF+EOFO MVI M,TRUE ;set initial eof to true ; LHLD MEMTO ;SWAPCOPY.ASM.....a single drive copy program. ; November 1980 ;by John M. Kodis, Buffalo, New York. ; Used with permission of Mr. Kodis. ; ;modified by Jerry W. Haigwood, 4/21/84 for use ; with the AMPRO Little Board (tm) CPU ; ;Revision history: ; ;Version 1.1 8/07/84 Modified to work with 48tpi.com - rbl ; 1.2 10/17/84 Improved disk reset logic - rbl ; 1.3 12/10/85 4Modified to copy R/O files - RLH ; 1.3A 1/08/86 %Modified to copy R/O files and set ;  (P LXI D,-(SECSIZ+FREEO+8) DAD D ;highest availiable dma buffer SHLD BUFTOP ; LXI H,BUF SHLD FPBPNT ;free space starts at buf ; MVI A,1 STA NAMES ;initial next-names count ; ASKUSR: LXI D,MENU ;load the menu MVI C,9 ;print the menu CALL BDOS call cget call dfdev ;print the floppy drive menu jm wrong$bios ;can't use version 1 bios LXI D,MENU2 ;load the continuation menu MVI C,9 ;print the menu CALL BDOS LXI D,SOURINP ;POINT TO SOURCE MESSAGE CALL RESPONSE  STA SOURDRV ;SAVE THE DRIVE LETTER dcr a ;change input to real drive STA SDISK ;source disk LXI D,DESTINP ;POINT TO DESTINATION MESSAGE CALL RESPONSE STA DESTDRV ;SAVE THE DRIVE LETTER dcr a ;change input to real drive STA DDISK ;destination disk LXI D,FNMSG ;DISPLAY FILENAME INPUT STRING MVI C,PRINTF CALL BDOS CALL FNINP ;INPUT THE FILE NAME ASKSR: CALL CRLF ;CR & LF THE CRT CALL CRLF LXI D,SOURMX CALL PROMPT ;ask for the source disk CALL RDRST ;reset disk #f not, we're done. LXI H,BUF SHLD FPBPNT ;fpbpnt := buf CALL ADJPNT LXI D,DESTMX CALL PROMPT ;prompt(destmx) CALL WRRST ;reset disk unless dest = "e" LDA DDISK MOV E,A CALL SELDSK WRNEXT: LHLD MADE MOV A,M ANA A JNZ A$M ;if already made, don't make it again ; MVI M,TRUE ;if not made, set made := true LHLD OPENED MVI M,TRUE ;then set opened := true, ;** * V1.3A **P* PUSH H PUSH D PUSH B PUSH PSW LHLD DFCB LXI D,RENFCB LXI B,32 unless source = "e" LDA SDISK ;get the source disk MOV E,A ;move it to e CALL SELDSK ;select it CALL FFNAME ;get the first matching file name CALL ADJPNT CALL FILFPB ;set rdma & wdma pointers, fill in file name MVI A,TRUE STA ONE2GO ;if so, set 'one to go' to true, then copy it ; RDLOOP: LDA FILEOF ANA A JM WR ;start writing when the last file has been read LHLD RDMA CALL FULBUF JC WR ; or when the buffer space has been exhausted ; LHLD EOF MOV A,M ANA A JZ SAMFI CALL LDIR ;TRANSFER LOWERCASE FILENAME TO RENAME FCB LXI H,RENFCB+9 MOV A,M ANI 20H ;CHECK FOR R/O FLAG JZ NORO ;NO R/O FLAG MOV A,M ANI 05FH ;SET UPPERCASE AND INSURE NO R/O FLAG MOV M,A LXI D,RENFCB ;RESET R/O VECTOR MVI C,SETATRF CALL BDOS CPI 4 ;CHECK FOR ERRORS JNC NORO LXI D,RENFCB MVI C,DELETEF CALL BDOS LXI D,DELRO ;DISPLAY DELETED MESSAGE MVI C,PRINTF CALL BDOS NORO: POP PSW POP B POP D POP H ;** * V1.3A *** rL ;if not end-of-file, we're on the same file. ; CALL ADJPNT ;else, this is the start of a new file... CALL FILFPB ;adjust pointers & fill new fpb XRA A LHLD SFEXT MOV M,A ;source file extent := 0 LHLD SFCR MOV M,A ;source file current record := 0 LHLD DFEXT MOV M,A ;dest file extent := 0 LHLD DFCR MOV M,A ;dest file current record := 0 LHLD EOF MOV M,A ;eof := false LHLD MADE MOV M,A ;made := false LHLD OPENED MOV M,A ;opened := false LHLD LAST MOV M,A ;lasCALL MAKE ;then make the file. ; A$M: LHLD OPENED MOV A,M ANA A JNZ A$OP ;if already opened, don't open it again MVI M,TRUE LHLD DFCB CALL OPEN ;if not open, open it & set opened := true ; A$OP: LHLD RDMA MOV E,M INX H MOV D,M ;de gets rdma LHLD WDMA MOV A,E CMP M ;compare least signifigant bytes JNZ NEQUAL INX H MOV A,D CMP M JZ EQUAL ;is wdma equal to rdma? ; NEQUAL: CALL WRITE ;if not, write a sector LHLD WDMA CALL BUMP ;wdma := wdma + secsiz JMP A$OPt := false MVI A,TRUE STA FPBUSD ;mark current fpb as used LHLD SFCB CALL OPEN ; SAMFIL: CALL READ LHLD EOF MOV A,M ANA A JZ SAMNAM ;read sectors until eof or buffer full ; NXTNAM: CALL FFNAME ;on eof, find the next name to be considered LXI H,NAMES MOV A,M STA NAMCNT NNLOOP: CALL FNNAME ;find next name... LXI H,NAMCNT DCR M JNZ NNLOOP ;as many times as necessary. LXI H,NAMES INR M ;then bump the count for the next pass ; LDA FILEOF ANA A ;if all matching fil ; EQUAL: CALL CLOSE ;when wdma = rdma, close the file LHLD EOF MOV A,M ANA A ;done with file? JZ SKPRPT ;if not, don't report the transfer yet. ;******** V 1.3A ******** PUSH H PUSH D PUSH B PUSH PSW LHLD DFCB LXI D,RENFCB LXI B,16 CALL LDIR ;SET UP RENAME SOURCE LHLD DFCB LXI B,16 CALL LDIR ;SET UP DESTINATION FCB ;**** V1.3A - 1/8/86 **** LDA RENFCB+9 ;CHECK FOR R/O SOURCE FILE ANI 20H ;MOVE THE POSSIBLE R/O FLAG INTO CARRY FLAG JZ EQUALJP ;SKe names have been copied JM WR ;(or passed over), start writing. MVI A,TRUE STA ONE2GO ;if so, set 'one to go' to true, then copy it LDA FPBUSD ANA A ;if the current fpb is unused, use it JZ SAMNAM LHLD RDMA ;else set up the next fpb, and use it MOV A,M INX H MOV H,M MOV L,A SHLD FPBPNT ;next block starts just past rdma JMP RDLOOP ; SAMNAM: LHLD RDMA CALL BUMP ;rdma := rdma + secsiz JMP RDLOOP ; WR: LDA ONE2GO ;anything for the destination disk? ANA A JZ FINI ;iIP THE RENAME TO R/O FILE - IT WASN'T ;**** V1.3A - 1/8/86 **** LXI H,RENFCB+25 ;POINT TO RENAME DESTINATION TYPE CHAR 1 MOV A,M ANI 0DFH ;RESET TO UPPER CASE ORI 80H ;SET R/O FLAG MOV M,A LXI D,RENFCB MVI C,RENAMEF CALL BDOS CPI 4 ;CHECK SUCCESS OF RENAME LXI D,RENERR JNC ABORT ;ERROR EQUALJP: POP PSW POP B POP D POP H ;******** V 1.3A ******** LXI D,CPYDMX CALL PRINT ;print 'copied ' LXI H,RENFCB+16 ;V1.3A was LHLD DFCB CALL PFNAME ;print the fi le name ; SKPRPT: LHLD WDMA CALL FULBUF ;if the whole buffer has been written, JC WREXIT ;try to read another some more in ; LHLD RDMA ;else, set up to write the next file MOV E,M INX H MOV D,M XCHG ;hl points to next fpb SHLD FPBPNT ;set up the file param. block pointer LHLD LAST MOV A,M STA DONE ANA A JNZ FINI ;if the last file has been written, we're done CALL ADJPNT JMP WRNEXT ;else adjust pointers, then write the next file ; WREXIT: LDA DONE ANA A ;shall weNg INX H SHLD EOF ;pointer to end-of-file flag, INX H SHLD LAST ;pointer to the 'last-file' flag, INX H SHLD FSPACE ;and the pointer to the start of free space. RET ; FILFPB: LHLD FPBPNT XCHG LHLD FILEOF ;get offset into directory bufffer MVI H,0 DAD H DAD H DAD H DAD H DAD H ;multiply by 32 LXI B,DIRBUF DAD B ;hl points to file name LXI B,NAMSIZ PUSH H PUSH B CALL LDIR ;move file name to source fcb POP B LHLD DFCB XCHG POP H CALL LDIR ;move file  exit or read more files? JNZ FINI ;we're done, so exit ; LXI B,FREEO LXI D,BUF LHLD FPBPNT CALL LDIR ;move the last fpb to the start of the buffer ; LXI H,BUF SHLD FPBPNT CALL ADJPNT CALL FILFPB ;set up the pointers at the start of the buffer ; LXI D,SOURMX CALL PROMPT ;ask for the source disk CALL RDRST ;reset disk unless source = "e" LDA SDISK MOV E,A CALL SELDSK JMP RDLOOP ; WRONG$BIOS: LXI D,BIOSMSG CALL ABORT ; FINI: LXI D,NORMAL CALL PRINT ;show [name to destination fcb ; ; ** * V1.3A *** PUSH H ;MAKE SURE I DON'T DESTROY ANYTHING PUSH D PUSH B PUSH PSW LHLD DFCB LXI D,9 ;SET INCREMENT TO FCB TYPE CHARACTER 1 DAD D MOV A,M RLC ;CHECK FOR R/O BIT SET JNC NORO2 ;NOT A READ ONLY FILE MOV A,M ANI 7FH ;RESET THE R/O BIT ORI 20H ;CHANGE LETTER TO LOWER CASE MOV M,A ;AND PUT IN THE FCB NAME NORO2: POP PSW ;MAKE SURE I DON'T DESTROY ANYTHING POP B POP D POP H ; ***copy complete LXI D,SYSTMX CALL PROMPT ;prompt for system disk RST BOOT ;exit to CP/M ; ABORT: CALL PRINT LXI D,SYSTMX CALL PROMPT ;prompt for system disk RST BOOT ;exit to CP/M ; NAMSIZ EQU 12 ;size of a disk file name (1+8+3) FCBSIZ EQU 36 ;size of a file control block SFCBO EQU 0 ;offset to source fcb SFEXTO EQU 12 ;offset to source file extent SCRO EQU 32 ;offset to source file current record DFCBO EQU 36 ;offset to destination file control block DFEXTO EQU 48 ;offset t V1.3A ** ; LHLD FSPACE XCHG LHLD RDMA MOV M,E INX H MOV M,D ;point rdma to start of free space INX H MOV M,E INX H MOV M,D ;point wdma to start of free space RET ; BUMP: MVI A,SECSIZ ADD M MOV M,A ;add sector size to l.s. byte of address RNC INX H INR M ;if carry, increment m.s. byte of address RET ; FULBUF: MOV E,M INX H MOV D,M ;de gets address to be compared LHLD BUFTOP MOV A,L SUB E MOV A,H SBB D RET ;return with carry set if*o destination file extent DCRO EQU 68 ;offset to destination file current record RDMAO EQU 72 ;offset to read zone pointer WDMAO EQU 74 ;offset to write zone pointer MADEO EQU 76 ;offset to file-made flag OPENO EQU 77 ;offset to file-open flag EOFO EQU 78 ;offset to end-of-file flag LASTO EQU 79 ;offset to last-file flag FREEO EQU 80 ;offset to start of freespace ; ADJPNT: LHLD FPBPNT ;compute and save the... LXI D,SFEXTO DAD D SHLD SFEXT ;pointer to source file extent LXI D,SCRO] @(de) > buftop ; PFNAME: MVI A,8 CALL PATHL ;print 8 characters in the name, MVI E,'.' CALL CO ;print a period, MVI A,3 ;print the 3 characters in the extension. ; PATHL: INX H MOV E,M CALL CO ;print the character @+(hl) DCR A JNZ PATHL ;repeat (a) times RET ; ; system interface routines ; CIF EQU 1 ;console input function # COF EQU 2 PRINTF EQU 9 ;print buffer function # LINEF EQU 10 ;line input function # CSTSF EQU 11 ;get console status function # RES-SFEXTO DAD D SHLD SFCR ;pointer to source file current record, LXI D,DFCBO-SCRO DAD D SHLD DFCB ;pointer to dest fcb, LXI D,DFEXTO-DFCBO DAD D SHLD DFEXT ;pointer to dest file extent, LXI D,DCRO-DFEXTO DAD D SHLD DFCR ;pointer to dest file current record, LXI D,RDMAO-DCRO DAD D SHLD RDMA ;pointer to read dma zone, INX H INX H SHLD WDMA ;pointer to write dma zone, INX H INX H SHLD MADE ;pointer to file made flag, INX H SHLD OPENED ;pointer to file-open fla@ETF EQU 13 ;select & write enable drive a OPENF EQU 15 ;open file function # CLOSEF EQU 16 ;close file function # SFFF EQU 17 ;search for first function # SFNF EQU 18 ;search for next function # DELETEF EQU 19 ;delete file function # READF EQU 20 ;sequential file read WRITEF EQU 21 ;sequential file write MAKEF EQU 22 ;create & open a new file RENAMEF EQU 23 ;V1.3A rename a file DMAF EQU 26 ;set dma address function # SETATRF EQU 30 ;set file attributes *** V2. <{2 CP/M *** ; OPEN: MVI C,OPENF XCHG CALL BDOS INR A RNZ ;successful open of requested file OPENNG: LXI D,CANTOP JMP ABORT ; CLOSE: MVI C,CLOSEF LHLD DFCB XCHG CALL BDOS LHLD OPENED MVI M,FALSE RET ; READ: LHLD RDMA MOV E,M INX H MOV D,M CALL SETDMA MVI C,READF LHLD FPBPNT XCHG CALL BDOS LHLD EOF MOV M,A ANA A ; RNZ RET ;RETURNS WITH 'Z' FLAG INDICATING STATUS ; WRITE: LHLD WDMA MOV E,M INX H MOV D,M CALL SETDMA MVI C,WRITEF LHLD DFCthan 2.1 Bios level ; ;"--- CGET: LHLD 1 ;GET START OF BIOS CODE AREA LXI D,BBOOT ;MOVE TO LOCAL STORAGE MVI B,BLEN ;SET COUNT CALL CGET0 ;MOVE STRING MVI A,0 ;TEST FOR VERSION CALL BGETT ;IF 0, THEN LESS TAHN 1.4 STA BVERS ;SAVE BIOS VERS INX H ;SEE IF HL IS FFFF MOV A,H ORA L RZ ;IF SO, THEN OLD SYSTEM DCX H ;FIX HL SINCE HAS THE TABLE ADDRESS LXI D,BNXTTBL ;SAVE NEXT TABLE MVI B,BSLEN CALL CGETB XCHG CALL BDOS ANA A RZ CANTWR: LXI D,SPACE JMP ABORT ; MAKE: MVI C,DELETEF LHLD DFCB XCHG CALL BDOS MVI C,MAKEF LHLD DFCB XCHG CALL BDOS INR A RNZ MAKENG: LXI D,WRPROT CALL PRINT LXI D,NODIR JMP ABORT ; SETDMA: MVI C,DMAF JMP BDOS ; WRRST: ;skip reset if destination drive is "e" because 48tpi.com ;will crash if a 48tpi "e" disk is in a 96tpi "a" drive LDA DDISK ;check destination disk number CPI 4 ;is it "e"? RZ MVI C,RESETF JMP BDOS ; RDRST)0 MVI A,0FFH ;SET NZ ORA A RET ;TO ID THIS LEVEL CGET0: MOV A,M STAX D INX H INX D DCR B JNZ CGET0 RET DFDEV: lda bvers cpi 20 rm LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call bpaget ; Get address of unit id MOV A,M ; Get unit id CPI 01 ; Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; . ani 03h ; mask out excess bits MOV l,a ; update floppy : ;skip reset if source drive is "e" because 48tpi.com ;will crash if a 48tpi "e" disk is in a 96tpi "a" drive LDA SDISK ;check destination disk number CPI 4 ;is it "e"? RZ MVI C,RESETF JMP BDOS ; CRLF: MVI E,CR CALL CO MVI E,LF CO: PUSH H PUSH PSW MVI C,COF CALL BDOS POP PSW POP H RET ; PRINT: MVI C,PRINTF JMP BDOS ; FFNAME: LXI D,DIRBUF CALL SETDMA MVI C,SFFF LXI D,FCB1 CALL BDOS STA FILEOF INR A RNZ LXI D,NOFILE JMP ABORT ; FNNAME: LXI D,DIRBdevice number mvi h,0 ; . dad h ; x2 xchg LXI H,FNAMES ; . dad d ; x2 dad d ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lxi h,valdrv ; point to the valid drive table mvi d,00h ; prepare to index into storage table mov e,a ; finish index value dad d ; index hl to the table lda unit ; adi 'A' ; sta d$current ; mov m,a ;put the ascii drive letter in the table LXI D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTRUF CALL SETDMA MVI C,SFNF LXI D,FCB1 CALL BDOS STA FILEOF ADD A SBB A ;a:=255 if fileof=255, else 0 LHLD LAST MOV M,A RET ; PROMPT: CALL PRINT CLEAR: MVI C,CSTSF CALL BDOS ANA A JZ WAIT MVI C,CIF CALL BDOS ;if there's a char waiting, get it & ignore it. JMP CLEAR WAIT: MVI C,CIF CALL BDOS ;get the next char CPI CNTRLC JZ BOOT CPI ESC JZ BOOT ;quit if ctrl-c or escape CPI CR JNZ BADCH ;explain the procedure call crlf RET SELDSK: MVI C,14 ;se: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? jm D$NEXT$FDEV ; No -- go do the next one ret unit: db 0 D$FDEV$HDR: DB cr,lf,lf,'FLOPPY DISK ASSIGNMENTS:',CR,LF DB ' CP/M drive Floppy disk',CR,LF DB ' --\',CR,LF,'$' D$FDEV$LIN: DB ' ' D$CURRENT: DB 'x ' D$EDISK: DB ' ' D$EBLANK: DB '  ' D$FNAME: DB ' z' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB lect disk function CALL BDOS RET BADCH: LXI D,EXPLAN JMP PROMPT ; LDIR: MOV A,M STAX D INX H INX D DCX B MOV A,C ORA B JNZ LDIR RET ;#--- ; ; CCGET GET SYSTEM BIOS JUMP TABLES ; ; Brings the current BIOS Jump tables starting at WARM BOOT ; to this local area for ease of utility access. ; ; If this BIOS is Version 2.1 or greater, also brings in the ; secondary Jump Table. ; ; Exits with Z set if lower 'Fourth' VALDRV: db 00h,00h,00h,00h,'E',00h,00h,00h ;valid drive table db 00h,00h,00h,00h,00h,00h,00h,00h ;null means no drive ; 'E' is forced since it is the virtual drive RESPONSE: MVI C,9 CALL BDOS ;PRINT OUT THE PASSED MESSAGE CONIN: mvi e,0ffh mvi c,6 call bdos ;input the character ani 5fh ;insure upper case character ora a ;anything there? jz conin CPI CNTRLC ;a ctrl-C? JZ BOOT ;get out if so... CPI ESC ;an escape? JZ BOOT ;ditto ; CPI 'A' ;is it a "q valid drive letter? ; JC CONIN ; CPI 'Q' ;is it in the valid range? ; JNC CONIN lxi h,valdrv ;point to the valid drive table lxi b,16 ;load the max number of loops db 0edh,0b1h ; Z80 CPIR instruction jnz conin ;if no match - enter a new character PUSH PSW ;save the character MOV E,A mvi c,6 call bdos ;output the character POP PSW ;RETURN THE CHARACTER ret FNINP: ;FILE NAME INPUT ROUTINE lxi h,keybuff mvi m,numkeys ;set max buffer size xra a inx h mov m,a  jnz fnielp ;loop till done FNDONE: RET ; FLINE: push d pop h dcr b ;reduce one for counter call allfile ;copy '?' into fcb1 jp fniext ;input the file extent ; FEXT: push d pop h dcr b ;reduce one for counter call allfile ;copy '?' into fcb1 jp fndone ; FFCB: push d pop h inr b ;add both ext characters inr b call allfile jp fndone ; ALLFILE: ;enters - HL=source & bc=number to transfer mvi a,'?' ;load character for fcb mov m,a ;load 1st character  ;zero current key count mvi c,linef lxi d,keybuff call bdos ;get the keyboard input lda keybuff+1 ;load the input count ana a lxi d,kbuff0 jz abort ;exit if no file name input lxi h,keybuff+1 inr m ;increment the number of inputs mov e,m mvi d,0 dad d mvi m,cr ;append cr to the end of input lxi h,fcb1 ;point to the file control block xra a ;clear the accumulator mov m,a ;set to default drive lxi h,fcb1+1 ;WRITE SPACES TO FCB1 filename.ext lxi d,fcb1+2 1push h pop d inx d ;point to destination location mov c,a mvi c,0 call mldir ;load the remainder of file name with '?" call zfcb ;zero out the remainder of the fcb ret ; ZFCB: lxi h,fcb1+12 ;zeros out the remainder of the fcb xra a ;load character for fcb (zero) mov m,a mvi b,23 lxi d,fcb1+13 call mldir ;load the remainder of file name with '?" ret ; MLDIR: MOV A,M ;same as Z80 LDIR except, this only uses B reg. STAX D INX H INX D DCR B JNZ MLDIR RET  mvi m,' ' mvi b,10 call mldir lxi h,keybuff+2 ;point to the 1st input character lxi d,fcb1+1 ;point to destination in fcb1 mvi c,'.' ;load character to look for mvi b,9 ;load the max count before or at EXT FNILP: shld kpoint ;save input pointer mov a,m ;load the input character cpi '*' ;check for '?' remainder of input line jz fline ;if zero - finish the fcb line cmp c ;check for end of file name jz fniext ;jump to ext input cpi cr jz fndone ;if carriage return - le ; VALID: cpi 20h ;changes lower case characters to upper case jc badinp ;abort if control character cpi 61h ;< 'a' ? jc v1 cpi 7bh ;< '{' jnc v1 ani 5fh ;create upper case character V1: ret ; BADINP: lxi d,kgoof jp abort ; ; console messages ; SOURINP: DB CR, LF, 'Enter Source Drive? (A thru P) $' SOURMX: DB CR, LF, LF, 'Place SOURCE on ' SOURDRV: DB 'A:, then type $' DESTINP: DB CR, LF, LF, 'Enter Destination Drive? (A thru P) $' DESTMX: DB CR, L7ave remainder spaces call valid ;set to upper case stax d ;load character into destination fcb location inx h inx d dcr b jnz fnilp FNIEXT: lhld kpoint ;restore the keyboard input pointer inx h ;point to first non period mov a,b ;check last counter cpi 0 jnz fnigo mov a,m ;get the next character cpi '.' ;it had better be the dot. lxi d,kgoof jnz abort ;you goofed - sorry, you can do it all again FNIGO: lxi d,fcb1+9 ;point to destination in fcb1 mvi c,'.' ;loaF, 'Place DESTINATION on ' DESTDRV: DB 'A:, then type $' SYSTMX: DB 'Insert SYSTEM disk ...then press $' FNMSG: DB CR, LF, 'Enter FILENAME.EXT to copy ... then type $' COPYMX: DB 'Copy $' CPYDMX: DB CR, LF, 'Copied $' QMARK: DB '? $' EXPLAN: DB 'Press to continue, ' DB 'or C to quit.', CR, LF, '$' NORMAL: DB CR, LF, LF, 'Copy complete.', CR, LF, '$' KGOOF: db CR,LF,LF,'Invalid input, check entries and try again',LF,CR,'$' KBUFF0:d character to look for mvi b,3 ;load the max count before or at EXT FNIELP: mov a,m ;load the input character cpi '*' ;check for '?' remainder of input line jz fext ;if zero - finish the fcb line cmp c ;check for end of file name jz fniejp ;skip over fcb1 storage if '.' cpi cr jz fndone ;if carriage return - leave remainder spaces call valid ;set to upper case stax d ;load character into destination fcb location inx d dcr b FNIEJP: inx h mov a,b ana a ;check for zero v DB CR, LF, LF, 'No filename input, please try again', CR,LF,'$' NOFILE: DB CR, LF, 'No source files', CR, LF, '$' NODIR: DB CR, LF, 'Directory space exhausted', CR, LF, '$' CANTOP: DB CR, LF, 'Can''t reopen file.', CR, LF, '$' SPACE: DB CR, LF, 'Data space exhausted', CR, LF, '$' WRPROT: DB CR, LF, 'Write protected?', CR, LF, '$' RENERR: DB CR, LF, 'Destination R/O error', CR, LF, '$' DELRO: DB CR, LF, 'Destination R/O file deleted$' BIOSMSG: db CR, LF, 'BIOS Version 2 or later required!', CR, L KF, '$' MENU: DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NULag RENFCB: DS 32 ;rename fcb buffer OPENED: DS 2 ;pointer to file open flag EOF: DS 2 ;pointer to end of file flag LAST: DS 2 ;pointer to last file flag FSPACE: DS 2 ;pointer to start of free buffer space FILEOF: DS 1 ;file offset. index into dirbuf DONE: DS 1 ;all files copied flag NAMES: DS 1 ;number of the next file to be copied NAMCNT: DS 1 ;copy of 'names'. used as a counter FPBUSD: DS 1 ;current fpb has been used flag ONE2GO: DS 1 ;there is a file to be transfered flag SDISK: DBK DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB CR, LF, 'Single Drive Copy Utility for AMPRO Little' DB ' Board and S3 0 ;source disk-default to A DDISK: DB 1 ;destination disk-default to A ; DS 64 ;32 level stack STACK: DS 0 ; DIRBUF: DS SECSIZ ;buffer for searching the directory ; ASKBUF: DS 129 ;buffer for response to query ; BUF: DS 0 ;buffer st2arts here and extends to fbase ; END SWAPCOPY 'sed as a counter FPBUSD: DS 1 ;current fpb has been used flag ONE2GO: DS 1 ;there is a file to be transfered flag SDISK: DBo#eries 100' VERSION: DB CR, LF, ' n Version 2.2' DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB '$' MENU2: DB CR, LF DB  ' E rUser defined' DB CR, LF, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL, NUL DB '$' ; ; data areas ; ; ;!--: ; ; REPLICATED BIOS JUMP TABLE FOR EASE OF USAGE. ; ;!-- ; BBOOT DS B3 BCSTS DS 3 BCIN DS 3 BCOUT DS 3 BLST DS 3 BPNCH DS 3 BRDR DS 3 BHOME DS 3 BSEL DS 3 BSTRK DS 3 BSSEC DS 3 BSDMA DS 3 BSRD DS 3 BSWRT DS 3 BLSTS DS 3 BSTRN DS 3 BGETT DS 3 ;GET 2.1 JUMP TABLES BGETE DS 3 BIOINT DS 3 BSCSI DS 3 BLEN EQU $-BBOOT ;LENGTH TO GET ; BNXTTBL: ;VERSION 2.1 > SECONDARY TABLE BSWAP DS 3 BSXBINT DS 3 BPHTBAC DS 3 BPAGET DS 3 DS 3 DS 3 DS 3 DS 3 BSLEN EQU $-BNXTTBL BVERS: DB 0 ;VERSION OF BIOS CODE KPOINT: DS 1 KEYBUFF: ds NUMKEY;S+2 SFCB: DS 0 FPBPNT: DS 2 ;pointer to start of the file param. block SFEXT: DS 2 ;pointer to source file extent byte SFCR: DS 2 ;pointer to source file current record byte DFCB: DS 2 ;pointer to destination file control block DFEXT: DS 2 ;pointer to dest file extent byte DFCR: DS 2 ;pointer to dest file current record byte BUFTOP: DS 2 ;pointer to top of free memory RDMA: DS 2 ;pointer to next read dma zone WDMA: DS 2 ;pointer to next write dma zone MADE: DS 2 ;pointer to file made fl !;  *** ;  *  * ;  * SET.ASM * ;  * AMPRO Little Board  * ; 4 * Serial/Parallel Port Setup Utility * ;  *  * ; 3 * Copyright (C) 1985, AMPRO Computers Inc. * ; * ݙ"RT B, or PARALLEL',cr,lf,lf DB ' %SET PORT A=9600,8,A,N,Y',cr,lf DB '  |  |',cr,lf DB ' : | | | | Hardware Hand shake: (Y)es or (N)o',cr,lf DB ' 1 | | | Parity: (O)dd,(E)ven,(N)one',cr,lf DB ' 2 | | Stop bits: (A)=1,(B)=1.5,(C)=2',cr,lf DB ' , | Data bits: (5),(6),(7),(8)',cr,lf DB ' 9 Baud rate: (110),(300),(450),(600),(1200),',cr,lf DB '  (2400 * ;  *** ; Version 1.0 - 15 June 85 - Initial release (fsw) ; VERS EQU 10 ; ver 1.0 ; ; SET.ASM will allow the system communication prameters to be ; changed from the command line. All changes will be in memory ; resident bios and will not modify the disk as in CONFIG.COM. ; Commands are in the following format and variations. ; ; SET TERMINAL=PORT A ; SET TERMINAL=PORT B ; SET PRINTER=6),(4800),(9600),(19200),(38400)',cr,lf,lf DB ' SET PORT B=same as port A (no 19200,38400 baud)',cr,lf,lf DB ' SET ? --> to display current settings',cr,lf,0 ; JMP EXIT ; BEGIN: CALL GETBIO ; get current system parameters LXI H,CMDTAL BEG1: INX H ; point to begining of command input MOV A,M CPI SPC ; skip the spaces JZ BEG1 ANA A ; end of command line=0 JZ START1 ; had just spaces, give message and exit XCHG ; 'de'=start of command CALL COMPARE DB 'PORT A',0 RPORT A ; SET PRINTER=PORT B ; SET PRINTER=PARALLEL ; SET PORT A=9600,8,A,N,Y ; ^  ^ ; $| | | | Hand shake (Y)es or (N)o ; $| | | Parity (O)dd,(E)ven,(N)one ; !| | Stop bits (A=1,B=1.5,C=2) ; | Data bits (5,6,7,8) ; Baud rate (110,300,450,600,1200,2400,4800,9600,19.2,38.4) ; SET PORT B=same as port A (no 19.2,38.4 baud) ; SET ? show current prameters ; ; ---p; set port A JNC PORTA CALL COMPARE DB 'PORT B',0 ; set port B JNC PORTB CALL COMPARE DB 'PRINTER',0 ; printer JNC PRN CALL COMPARE DB 'TERMINAL',0 JNC TERM ; set terminal port CALL COMPARE DB '?',0 ; give current system parameters JNC NOW JMP BDEXIT ; no match, exit ; ; ; set terminal to port a or b ; TERM: CALL DELIM ; get position of subcmd JC BDEXIT ; was none XCHG ; address of subcmd in 'de' CALL COMPARE DB 'PORT A',0 MVI B,01H ; con:=crt: JNC PTA -- ; ; ascii equates ; LF EQU 0AH ; line feed CR EQU 0DH ; carriage return SPC EQU 20H ; space ESC EQU 1BH ; ; cp/m equates ; BDOS EQU 05H ; bdos entry point BIOS EQU 01H ; address of warm boot in bios FCN EQU 5CH ; default fcn CMDTAL EQU 80H ; location of command tail WMBOOT EQU 00H ; jmp to warm boot TPA EQU 100H ; start of tpa ; ORG TPA ; start of tpa ; START: LXI H,0 DAD SP ; hl=ccp stack pointer SHLD RETURN ; save ccp stack pointer LXI SP,STACK CALL CALL COMPARE DB 'PORT B',0 MVI B,00H ; con:=tty: JC BDEXIT ; PTA: LDA IOBYT ; get i/o byte ANI 0FCH ; mask con: bits ORA B ; or new con: bits STA IOBYT ; save JMP GOODEX ; ; ; set up the ports ; PORTB: MVI A,0AH ; offset in dart table STA PORT JMP PORTC ; ; PORTA: XRA A ; clear a STA PORT ; set work value to port A PORTC: CALL DELIM ; find the delimeter '=' JC BDEXIT ;  ??M? CALL GETSPD ; get speed, set ctc ; ; do the rest ; PORTD: CALL GETNX4*CLRSCN ; clear screen CALL ILPRT DB ' i AMPRO Serial/Parallel Port Setup Utility' DB ' (ver ',VERS/10+'0','.',VERS MOD 10+'0',')',cr,lf DB ' Copyright (C) 1985 - AMPRO Computers, Inc.',cr,lf,0 LDA CMDTAL ; see if entry on command line ORA A ; zero ? JNZ BEGIN ; ; START1: CALL ILPRT ; DB cr,lf,0 START2: CALL ILPRT DB 'No command given. SET command choices are:',cr,lf,lf DB ' .SET TERMINAL=PORT A or PORT B',cr,lf,lf DB ' SET PRINTER=PORT A, POT ; get the next option MVI A,'5' CMP M JZ BIT5 ; 5 data bits INR A CMP M JZ BIT6 ; 6 data bits INR A CMP M JZ BIT7 ; 7 data bits INR A CMP M JNZ BDEXIT ; if bad input no changes made MVI A,60H ; word length=8 JMP SETWR5 ; BIT5: XRA A ; word length=5 JMP SETWR5 ; BIT6: MVI A,40H ; word length=6 JMP SETWR5 ; BIT7: MVI A,20H ; word length=7 ; SETWR5: PUSH PSW ; save 'a' MVI A,60H ; clear word length MVI B,3 ; offset to wr5 CALL CLRWR ; clear word leng .,th bits POP PSW ; get 'a' PUSH PSW ; and save again ORA M ; or in the new value MOV M,A ; new value to wr5 ; MVI A,0C0H ; do wr3 also, mask value MVI B,5 ; offset to wr3 CALL CLRWR POP PSW ; get bits back RLC ; rotate bits into position ORA M MOV M,A ; new value in wr3 ; ; stop bits 1,1.5,2 ? ; STPBIT: LHLD TEMP0 ; where we are on the command line STPBT1: INX H MOV A,M ; next char CPI ',' JZ STPBT1 ; skip over the ',' ANA A JZ BDEXIT ; no input CPI 'A' 5A,3 ; 3=600 baud JNC SPDEXT CALL COMPARE DB '1200',0 MVI A,4 ; 4=1200 baud JNC SPDEXT CALL COMPARE DB '2400',0 MVI A,5 ; 5=2400 baud JNC SPDEXT CALL COMPARE DB '4800',0 MVI A,6 ; 6=4800 baud JNC SPDEXT CALL COMPARE DB '9600',0 MVI A,7 ; 7=9600 baud JNC SPDEXT CALL COMPARE DB '19200',0 MVI A,8 ; 8=19200 baud JNC SPDEXT CALL COMPARE DB '38400',0 MVI A,9 ; 9=38400 baud JNC SPDEXT CALL COMPARE DB '19.2',0 MVI A,8 ; 8=19200 baud JNC SPDEXT CALL  ; first value JC BDEXIT ; not valid CPI 'C'+1 ; last value JNC BDEXIT ; not valid SHLD TEMP0 ; save command line pointer CPI 'A' JZ STPBT2 ; one stop bit CPI 'B' JZ STPBT3 ; 1.5 stop bit ; MVI A,0CH ; two stop bits JMP STPBT4 ; STPBT2: MVI A,04H ; one stop bit JMP STPBT4 ; STPBT3: MVI A,08H ; 1.5 stop bit ; STPBT4: PUSH A ; save 'a' MVI B,1 ; offset to wr4 command MVI A,0CH ; clear stop bits CALL CLRWR ; POP A ORA M MOV M,A ; save new value in wr4 ; COMPARE DB '38.4',0 MVI A,9 ; 9=38400 baud JC BDEXIT ; SPDEXT: STA SPEED MVI A,0C0H ; clear clock divisor mask MVI B,1 ; offset to wr4 command CALL CLRWR PUSH H ; save wr4 address LDA SPEED LXI H,CLK ; clock table CALL LOOKUP ; get clock divisor address MOV A,M ; clock divisor POP H ; get wr4 address ORA M ; or in clock divisor bits MOV M,A ; and save LDA SPEED LXI H,CTCDIV ; ctc divisor table CALL LOOKUP ; returns 'l'=ctc command, 'h'=ctc divisor LDA PORT ;; parity odd,even,none ; PARITY: LHLD TEMP0 ; get command line pointer back PAR1: INX H ; MOV A,M CPI ',' JZ PAR1 ; skip ',' SHLD TEMP0 ; save command line pointer ANA A JZ BDEXIT ; no entry CPI 'E' ; even JC BDEXIT ; not valid CPI 'O'+1 ; odd JNC BDEXIT ; must be between 'E' and 'O' CPI 'E' JZ PAR2 ; even parity CPI 'O' JZ PAR3 ; odd parity ; XRA A ; no parity JMP PAR4 ; PAR2: MVI A,03H ; even parity JMP PAR4 ; PAR3: MVI A,01 ; odd parity ; PAR4: P2 see if port a or b ANA A JZ SPEX1 ; zero=port a LDA SPEED ; get speed setting CPI 8 ; more than 9600 ? JNC BDEXIT ; yes, exit SHLD CTC1 ; for port b RET ; SPEX1: SHLD CTC0 ; for dart a LDA SPEED CPI 8 ; less than 19.2 JC SPDEX2 ; yes MVI A,80H ; turn off dtr MVI B,3 ; offset to wr5 CALL CLRWR RET ; SPDEX2: MVI A,80H ; clear dtr MVI B,3 ; offset to wr5 CALL CLRWR MVI A,80H ; set dtr ORA M MOV M,A ; store dtr on RET ; PRN: CALL DELIM ; get subcommaUSH A ; save 'a' MVI A,3 ; bits to clear for parity MVI B,1 ; offset to wr4 command reg LXI H,DART CALL CLRWR ; clear bits POP A ORA M MOV M,A ; save parity ; HANDSK: LHLD TEMP0 ; get command line pointer HAND1: INX H MOV A,M ; CPI ',' ; skip delimiter JZ HAND1 ANA A JZ BDEXIT ; end of command line CPI 'Y' ; yes JZ HAND2 CPI 'N' ; no JNZ BDEXIT ; HAND2: PUSH PSW ; save Y or N LDA PORT ; port A or B ANA A JZ HAND3 ; do port A POP PSW ; ANI 01H nd pointer JC BDEXIT ; delimeter not found, exit XCHG ; subcommand pointer in 'de' CALL COMPARE DB 'PORT A',0 MVI B,40H JNC PRN1 CALL COMPARE DB 'PORT B',0 MVI B,00H JNC PRN1 CALL COMPARE DB 'PARALLEL',0 MVI B,80H JC BDEXIT ; no match, exit ; PRN1: LDA IOBYT ANI 3FH ; mask lst: bits ORA B STA IOBYT JMP GOODEX ; ; exit back to system ; GOODEX: CALL PUTBIO ; put changes in bios LXI H,GDEXIT PUSH H ; set up for return MVI A,57 ; ioinit offset LHLD BIOS e; lsb of Y=1,N=0 STA HSB JMP GOODEX ; ; HAND3: POP PSW ; restore 'a' ANI 01H ; mask lsb STA HSA JMP GOODEX ; make changes ; ; getspd, sets port speed value, entered with 'de'= to command ; input. set ctc divisor wr4 in syspram ; GETSPD: XCHG ; string to 'de' CALL COMPARE DB '110',0 MVI A,0 ; 0=110 baud JNC SPDEXT CALL COMPARE DB '300',0 MVI A,1 ; 1=300 baud JNC SPDEXT CALL COMPARE DB '450',0 MVI A,2 ; 2=450 baud JNC SPDEXT CALL COMPARE DB '600',0 MVI x ; get warm boot address MOV L,A ; modify with offset to init PCHL ; do bios init ; GDEXIT: CALL ILPRT DB cr,lf,lf DB ' New parameters installed in bios and initialized' DB cr,lf,0 ; ; exit, no warm boot ; EXIT: LHLD RETURN ; recover ccp stack pointer SPHL ; RET ; ; exit, error in command line ; BDEXIT: CALL ILPRT DB cr,lf,'Command line error',cr,lf,lf,0 JMP START2 ; ; getnxt, return the single character options seperated by commas ; on the command line. 'hl' 0points to option ; GETNXT: LHLD TEMP0 ; get command line pointer GETNX1: MOV A,M CPI ',' INX H ; point to value or next position JNZ GETNX1 MOV A,M ; get option SHLD TEMP0 ; save pointer ANA A RNZ STC ; set carry=end of command line RET ; ; ; clrwr, clear bits in dart wr. entered with mask in 'a' and offset ; in 'b'. returns address of reg in 'hl' ; CLRWR: PUSH PSW ; save 'a' LXI H,DART ; dart sysint values LDA PORT ; port has offset MVI D,0 MOV E,A DAD D ; dar ; CALL ILPRT DB cr,lf,lf DB 'Serial Port B: ' DB 'Baud Rate = ',0 LXI B,CTC1 LXI D,BWR4C ; A dart wr4 CALL GTBAUD ; get baud rate CALL PRINT ; print baud rate CALL ILPRT DB cr,lf DB ' | Data bits = ',0 LDA BWR3C ; wr3 has number of data bits CALL SHDBIT ; show data bits CALL ILPRT DB cr,lf DB ' r Stop bits = ',0 LDA BWR4C ; wr4 has stop bits CALL SHSBIT ; show stop bits CALL ILPRT DB cr,lf DB '  Par t 'a' or 'b' side MOV E,B ; offset to reg DAD D ; 'hl'=reg location POP A ; restore mask CMA ; invert bits ANA M ; clear bits MOV M,A ; save wr with bits cleared RET ; ; lookup, entered with address table in 'hl' and multiplier in 'a', ; returns with 'hl' pointing to variable length data string. ; LOOKUP: MVI D,0 ; zero 'd' ADD A ; 'a'x2 MOV E,A DAD D ; add 'de' to 'hl' MOV E,M ; get address table in 'de' INX H ; next byte MOV D,M XCHG ; address of string in 'hYity = ',0 LDA BWR4C ; wr4 has parity CALL SHPBIT CALL ILPRT DB cr,lf DB ' Handshake = ',0 LDA HSB CALL SHHSK ; show handshake CALL ILPRT DB CR,LF,0 JMP EXIT ; ; show handshake ; SHHSK: LXI H,HNDSH ; yes or no CALL LOOKUP JMP PRINT ; print, return ; ; show parity ; SHPBIT: ANI 03H ; mask parity bits LXI H,PRTY ; parity table CALL LOOKUP JMP PRINT ; print parity, and return ; ; show stop bits ; SHSBIT: ANI 0CH ; mask stop bits RRC l' RET ; ; delim, returns address of first character after delimiter (=) ; or carry set if none found ; DELIM: LXI H,CMDTAL ; command tail DELIM1: INX H MOV A,M ANA A ; see if zero JZ DELIM2 ; end of command line CPI '=' JNZ DELIM1 ; loop till delimiter or end INX H ; start of subcommand SHLD TEMP0 ; save start of subcomand RET ; DELIM2: STC ; set carry=no subcommad RET ; ; now, print current parameters ; NOW: CALL ILPRT DB cr,lf,'Current System Configuration is:',lRRC ; put bits in position LXI H,SBITS ; stop bits table CALL LOOKUP JMP PRINT ; print it, return to caller ; ; show data bits ; SHDBIT: ANI 0C0H ; mask data bit length RLC RLC ; put bits in low nibble LXI H,DBITS ; data bits table CALL LOOKUP JMP PRINT ; print it, return to caller ; ; print the baud rate. 'bc' points to ctc init string, ; 'de' points to dart init string ; GTBAUD: LDAX B ; get first ctc byte CPI 3 ; reset? JZ GTBAU1 ; must be 19.2 + CPI 47H LXI ]f DB cr,lf,'Terminal = ',0 LDA IOBYT ANI 03H ; mast CON: bits LXI H,DEV ; device table CALL LOOKUP CALL PRINT ; print device CALL ILPRT DB cr,lf,'Printer = ',0 LDA IOBYT ANI 0C0H ; mask LST: bits RLC RLC ; put bits in low nibble LXI H,DEV ; device table CALL LOOKUP CALL PRINT ; CALL ILPRT DB cr,lf,lf DB 'Serial Port A: ' DB 'Baud Rate = ',0 LXI B,CTC0 LXI D,AWR4C ; A dBart wr4 CALL GTBAUD ; get baud rate CALL PRINT ; print baud IH,B1 RNZ ; must be 7, print 110 baud INX B ; point to second byte of ctc string LDAX B CPI 13 LXI H,B96 RZ ; print 9600 baud CPI 26 LXI H,B48 RZ ; print 4800 baud CPI 52 LXI H,B24 RZ ; print 2400 baud CPI 104 LXI H,B12 RZ ; print 1200 baud CPI 208 LXI H,B4 RNZ ; print 450 baud LDAX D ; wr4 info ANI 0C0H ; mask CPI 40H LXI H,B6 RZ ; 600 baud LXI H,B3 ; 300 baud RET ; GTBAU1: LDAX D ; wr4 info ANI 0C0H CPI 40H LXI H,B384 RZ LXI H#rate CALL ILPRT DB cr,lf DB ' | Data bits = ',0 LDA AWR3C ; wr3 has number of data bits CALL SHDBIT ; show data bits CALL ILPRT DB cr,lf DB ' r Stop bits = ',0 LDA AWR4C ; wr4 has stop bits CALL SHSBIT ; show stop bits CALL ILPRT DB cr,lf DB ' l Parity = ',0 LDA AWR4C ; wr4 has parity CALL SHPBIT ; show parity CALL ILPRT DB cr,lf DB ' ; Handshake = ',0 LDA HSA CALL SHHSK ; show handshakeD,B192 RET ; ; compare a string of characters addressed by 'de' terminated ; with 0h. returns with cary set if no match ; COMPARE: XTHL ; the stack has the pointer to the PUSH D ; save string address CMPA: MOV A,M ; ANA A ; the end ? JZ SAME ; made it to end all equal LDAX D ; CMP M ; JNZ NSAME ; not same INX H ; INX D ; JMP CMPA ; ; NSAME: XRA A ; keep going till end '0' so we INX H ; return to correct place CMP M ; JNZ NSAME+1 ; STC ; set carry ; S AME: POP D ; restore string address INX H ; point to next inst after compare string XTHL ; replace value on stack with 'hl' for ret. RET ; ; ilprt, display a string of characters terminated by a 0h ; ILPRT: XTHL ; stack has address of string ILPRT1: MOV A,M ANA A ; zero ? JZ ILPRT2 CALL FCN2 INX H JMP ILPRT1 ; ILPRT2: XTHL ; put new return address on stack RET ; ; clear the screen ; CLRSCN: MVI A,CR ; print carriage return CALL FCN2 MVI B,18 ; load 'b' count CLR CK16 ; 600 baud DW CK16 ; 1200 baud DW CK16 ; 2400 baud DW CK16 ; 4800 baud DW CK16 ; 9600 baud DW CK32 ; 19200 baud DW CK16 ; 38400 baud ; ; ctc commamds ; CTCDIV: DB 07H,142 ; timer mode, 110 baud DB 47H,208 ; counter mode, 300 baud DB 47H,139 ; counter mode, 450 baud DB 47H,208 ; counter mode, 600 baud DB 47H,104 ; counter mode, 1200 baud DB 47H,52 ; counter mode, 2400 baud DB 47H,26 ; counter mode, 4800 baud DB 47H,13 ; counter mode, 9600 baud DB 3,0 ; clSC1: MVI A,LF ; do line feeds CALL FCN2 DCR B JNZ CLRSC1 RET ; ; print a string terminated by 0h. entered with 'hl' pointing to string ; PRINT: MOV A,M ; get byte ANA A RZ ; the end CALL FCN2 ; console write INX H JMP PRINT ; ; wait, wait 10 msec after 'lf' for slow terminals ; WAIT: MVI B,4 ; LXI D,0 ; WAIT1: INX D ; 1.50 MOV A,E ; 1.00 CMP D ; 1.00 JNZ WAIT1 ; 2.50 = 6.00 DCR B RZ JMP WAIT1 ; ; getbio, finds current system parameters in bios and moveear ctc above 9600, 19.2 baud DB 3,0 ; ditto for 38.4 baud ; ; table for device ports ; DEV: DW SPB ; serial port b, i/o bit 00 DW SPA ; serial port a, i/o bit 01 DW PPO ; parallel port, i/o bit 10 ; ; handshake ; HNDSH: DW N DW Y ; ; data bits per character ; DBITS: DW BITS5 DW BITS7 DW BITS6 DW BITS8 ; ; number of stop bits ; SBITS: DW PRTS DW SBIT1 DW SBIT15 DW SBIT2 ; ; parity table ; PRTY: DW PRTN DW PRTO DW PRTN DW PRTE ; ; --s them into ; program area. ; GETBIO: LHLD BIOS ; get warm boot bios address MVI L,40H ; parameters start here MVI B,64 ; number of bytes to move LXI D,SYSPRAM ; store here JMP LDIR ; move it ; ; putbio, takes updated parameters and places them in bios ; PUTBIO: LHLD BIOS ; get warm boot bios address MVI L,40H ; parameters start here XCHG ; destination in 'de' MVI B,64 ; number of bytes to move LXI H,SYSPRAM ; new param here ; fall thru and move it ; ; ldir, simulates |-- ; data strings ;-- ; SPA: DB 'Serial Port A',0 SPB: DB 'Serial Port B',0 PPO: DB 'Parallel Port',0 ; BITS5: DB '5 bits per character',0 BITS6: DB '6 bits per character',0 BITS7: DB '7 bits per character',0 BITS8: DB '8 bits per character',0 ; SBIT1: DB '1 stop bit',0 SBIT15: DB '1.5 stop bits',0 SBIT2: DB '2 stop bits',0 ; PRTN: DB 'none',0 PRTO: DB 'odd',0 PRTE: DB 'even',0 PRTS: DB '?? illegal bit gthe z80 ldir instruction ; LDIR: MOV A,M ; get byte from source STAX D ; store destination INX H ; next source INX D ; next destination DCR B ; count down JNZ LDIR ; no RET ; yes zero, return ; ; --- ; *** system calls *** ; --- ; bdos function 1, console read ; FCN1: PUSH H ; save registers PUSH D PUSH B MVI C,1 ; console read CALL BDOS POP B vcombination',0 ; B384: DB '38400',0 B192: DB '19200',0 B96: DB '9600',0 B48: DB '4800',0 B24: DB '2400',0 B12: DB '1200',0 B6: DB '600',0 B4: DB '450',0 B3: DB '300',0 B1: DB '110',0 ; Y: DB 'yes',0 N: DB 'no',0 ; SRA: DB 0 SRB: DB 1 SRCC: DB 2 SRD: DB 3 ; CK16 DB 40H CK32 DB 80H CK64 DB 0C0H ; ; --- ; parameter storage area ; PORT: DS 1 ; port a=0,port b=1 SPEED: DS 1 ; save speed value TEMP0: DW 1 ; storage for start of  POP D POP H RET ; ; bdos function 2, console write ; FCN2: PUSH H ; save registers PUSH D PUSH B PUSH PSW MOV E,A MVI C,2 ; console write CALL BDOS POP PSW CPI LF CZ WAIT ; wait after 'lf' for slow POP B ; terminals POP D POP H RET ; ;-- ; lookup tables ;--c ; ; clock divisor ; CLK: DW CK16 ; 110 baud DW CK32 ; 300 baud DW CK16 ; 450 baud DWisubcommand RETURN: DW 1 ; storage for ccp stack pointer ; ; system parameters from bios as located at bios+40h ; SYSPRAM: CTC0: DW 1 ; ctc0 init values CTC1: DW 1 ; ctc1 init values CTC2: DW 1 ; ctc2 init values CTC3: DW 1 ; ctc3 init values ; DART: ; dart init values AWR4: DS 1 ; wr 4, dart 'A' side AWR4C: DS 1 ; wr 4 command AWR5: DS 1 ; wr 5 AWR5C: DS 1 ; wr 5 command AWR3: DS 1 ; wr 3 AWR3C: DS 1 ; wr 3 command DS 4 ; BWR4: DS 1 ; wr 4, dart 'B' side BWR4C: DS 1 ; w cr 4 command BWR5: DS 1 ; wr 5 BWR5C: DS 1 ; wr 5 command BWR3: DS 1 ; wr 3 BWR3C: DS 1 ; wr 3 command DS 4 ; NDISK: DS 1 ; number of disk drives ; STPRAT: DS 4 ; disk drive step rate ; IOBYT: DS 1 ; i/o byte ; ATOCMD: DS 10 ; auto-command ; HSA: DS 1 ; hand shake port a HSB: DS 1 ; hand shake port b ; VER: DS 1 ; bios version number ; ORG SYSPRAM+40H DS 32 ; stack area STACK: END START )^e ; disk(ette) onto the Destination disk(ette). ; ; The system images moved consist of CCP BDOS BIOS and ZCPR ; if currently active on the source drive. ; ; For AMPRO diskettes, the disk layout is as follows: ; ; Track 0 sector 0 Boot loader ; ; Track 0 sector 1 thru 39 CCP BDOS ; Track 1 sector 0 thru 4 BDOS continued. ; ; Track 1 sector 5 thru 39 BIOS ; ; For the AMPRO hard disk systems, the disk layout is as follows: ; ; Track 0 sector 0 Boot loader ; ; Track 0 sector 1 thru 44 Q CCP BDOS ; ; Track 0 sector 45 thru 63 BIOS ; ; Track 1 sector 0 thru 11 BIOS ; ; All unused sectors on the hard disk tracks 0 and 1 are reserved. ; ; ; NOTE: This utility will support any source or destination ; device, either floppy or hard disk (or partition). ; ; The single requirement is that the target device must ; have 80 CP/M sectors available in the reserved area ; beginning at CP/M Track 0 Sector 0. Track incrementing ; is automatically done whXen required. ; ; This includes mixture of single and double-sided devices. ; ;$--M- ; Revision History: ; ; Ver Date Who Description ; --- ----- --- -- ; 3.3 E6.17 RJB Removed HD controller type from SCSI drive ; letter listing ; ; 3.2 E2.22 RJB Added message to display the floppy and hard ; disk CP/M drive letters, switched input from ; BIOS calls to BDOS calls & allowed '.'=, ; ','= in prompt (to make SUBMIT-able). ; ; 3.1 E2.12 RJB Added a "don't care" read to flush the last ; written sector to disk. ; ; 3.0 DC.10 RLD Massive changes to allow disk A-P floppy or ; hard disks. Removed all primitive hardware- ; dependant code since already exists with the ; system BIOS. Almost a total re-write. ; ; 2.2 D5.08 Cleaned up responses. ; 2.1 D5.03 Add 10 ms delay after line feeds. ; 2.0 Release version. CTLC EQU 3 ;O * * * SYSTEM RE-GENERATION UTILITY  * * COPYRIGHT (C) 1984  * *  AMPRO COMPUTERS, INC.  * * W* ; assemble with asm.com or equivalent. there is no z80 code. VER EQU 33 ; ;"--g- ; ; SYSTEM GENERATION UTILITY SYSGEN.ASM ; ; This utility copies the system images from the Sourc( control c CR EQU 13 ; carriage return LF EQU 10 ; line feed ESC EQU 27 ; escape key UPCASE EQU 5FH ; upper case mask BDOS EQU 5 ; bdos entry point FCB EQU 5CH ; default file control block OPEN EQU 15 ; bdos open file READS EQU 20 ; bdos read sequential STDMA EQU 26 ; bdos set dma address IMAGE EQU 900H ; 'sysgen' image location BUFFER EQU IMAGE TBUF EQU IMAGE+(80*128) ; default disk buffer and kbd buffer ONDSKS EQU 5CH ;BIOS OFFET TO (NDSKS) PARAMETER OFCOPY EQU 98H ;OFFSET P TO COPYRIGHT STRING ORG 100H JMP START CURCNT DB 0 CURPNT DW 0 OPER DB 0 SECTOR DW 0 TRACK DB 0 MAXSEC DB 0 SDRIV DB 0 DDRIV DB 0 DMAADR DW 0 clchr db 0 clptr dw 0 DFDEV: lda bvers cpi 20 rm LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call bpaget ; Get address of unit id MOV A,M ; Get unit id CPI 01 ; Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; .  sp,stack lxi h,80h mov a,m inx h mov c,a ora a jz nocmdline delimiter: mov a,m inx h dcr c jz nocmdline cpi '/' jnz delimiter shld clptr nocmdline: mov a,c sta clchr CALL CGET ;SET BIOS TABLES TO LOCAL JUMPS ;#-- ; ; IF ZERO SET ON RETURN, MODIFY THE MAX SOURCE AND DESTINATION ; MESSAGES AND COMPARES TO USE BIOS VARIABLE (NDSKS) ; ; This is done to prevent a system hang on pre-2.1 Bios wherw ani 03h ; mask out excess bits MOV l,a ; update floppy device number mvi h,0 ; . dad h ; x2 xchg LXI H,FNAMES ; . dad d ; x2 dad d ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lda unit ; adi 'A' ; sta d$current ; LXI D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTR: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? jm D$NEXT$FDEV ; No -- go do the next one RET unit: db 0 D$FDEV$HDR: DB cr,lf,lf,'FLOP^e ; a non-existant floppy will hang. ; ; In the 2.1 Bios, a select error is returned ; ;#-- JNZ STT1 ;JUMP FOR VERSION 2.1 OR GREATER LHLD 1 ;GET BIOS ADDRESS BACK MVI L,0 ;POINT TO COLD ENTRY LXI D,ONDSKS ;OFFSET TO KNOW VARIABLES DAD D MOV A,M ;GET MAX DISK NUMBER ADI '@' ;SET ASCII BIAS STA SMXD STA DMXD INR A ;+1 FOR COMPARE STA SDXS ;SET DISPLAY VALUES STA DDXS STT1: CALL CLEAR ;CLEANSPY DISK ASSIGNMENTS:',CR,LF DB 'CP/M drive ' DB 'Floppy disk',CR,LF DB ' --\',CR,LF,'$' D$FDEV$LIN: DB ' ' D$CURRENT: DB 'x ' D$EDISK: DB ' ' D$EBLANK: DB '  ' D$FNAME: DB ' ' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' DSDEV: lda bvers cpi 20 rm LXI D,HD$HEADER ; Display table header mvi c,9 CALL bdos mvi a,0 D$NEXT$SDEV: sta unit call bpagD THE SCREEN LXI D,MSG1 CALL CMESS ;AND DISPLAY WE ARE HERE ;"--- ; ; TEST THE DEFAULT FCB FOR A FILENAME ENTRY ; ; If the first character of the default FCB is not a Space, ; then use the filename provided within that FCB as the source ; file in place of a source diskette. ; ; The entry format from CCP is: SYySGEN d:Fname.Ext ; ; If the first character of the 'filename' is an asterisk, ; then use the console buffer as input et mov a,m cpi 03 jnz d$next$unit inx h inx h mov a,m ; logical unit number ani 0e0h ; . RLC ; . (move bits 7-5 to 2-0) RLC ; . RLC ; . ANI 07H ; . (mask out other bits) ADI '0' ; . (convert to ascii 0-7) STA DRIVE$UNIT ; . inx h MOV A,M mvi b,0ffh ora a jz sc$conv sc$nxt$bit inr b rrc jnc sc$nxt$bit sc$conv mov a,b ADI '0' ; . (convert to ascii 0-7) STA DRIVE$ADDRESS ; . lda unit adi 'A' sta drive$letters lxi d,drive$info mviT_for the drive names. ; ;!--- LDA FCB+1 ; first file name character cpi '/' ; star means use console input jz asksrc ; CPI ' ' ; check for space JNZ GETFIL ; read the named file ;!--- ; ; GET SOURCE DISK ENTRY ; ; Get entry and then a Carriage Return key. When CR hit, go ; and read from the source drive. ; ;--b c,9 call bdos D$NEXT$UNIT: LDA UNIT ; Get unit we're working on INR A ; Bump to next Cpi 16 ; Are we done? JM D$NEXT$SDEV ; No -- go do another RET HD$HEADER: DB cr,lf,lf,'HARD DISK ASSIGNMENTS:',CR,LF DB 'CP/M drive ' DB 'Addr Unit #',CR,LF DB '--B-' DB '',CR,LF,'$' DRIVE$INFO: DB ' ' DRIVE$LETTERS: DB ' o ' DRIVE$ADDRESS: DB '0 ' DRIVE$UNIT: DB '0',CR,LF,'$' ; ; S T A R T . . . ; START: lxi -- ASKSRC: call dfdev call dsdev asks2: LXI D,MSGS CALL CMESS ASKS: CALL crdc call switch ANI UPCASE CPI ESC JZ DCLR ;CLEAR SCREEN AND RETURN CPI CTLC JZ DCLR CPI CR ;IF CR THEN MEMORY IMAGE JZ RMIMAG CPI 'A' JC ASKS2 SDXS: EQU $+1 CPI 'P'+1 ;A THRU P ALLOWED JNC ASKS2 STA SDRIV STA SDR MOV C,A LXI D,MSG2 CALL CMESS SDRA: CALL CRDC call switch CPI CR JZ RDSRC ;NOW READ IN THE SOURCE CPI CTLC JZ DCLR CPI ESC JZ DCLR JMP NU SDRA ;!--- ; ; GET DESTINATION DISK ENTRY ; ; Get entry and then a Carriage Return key. When CR hit, go ; and write to the source drive. ; ;!-- ASKDES: call dfdev call dsdev askd2: LXI D,MSGD CALL CMESS ASKD: CALL crdc call switch ani upcase CPI ESC JZ DCLR CPI CTLC JZ DCLR CPI CR JZ DCLR CPI 'A' JC ASKD2 DDXS: EQU $+1 CPI 'P'+1 ;A  DMAADR LXI D,128 DAD D SHLD DMAADR JMP GF2 NOFIL: LXI D,NFLM CALL CMESS JMP 0 NFLM: DB CR,LF,LF,'Cannot find source file!',CR,LF,'$' ;!--- ; ; READ SYSTEM FROM SOURCE DISK ; ; Reads in 80 CP/M sectors starting at Trk 0 Sector 0, to ; to system ram at BUFFER. ; ;!--X ; RDSRC: LXI H,0 ;START AT TRK 0 SECTOR 0 SHLD SECTOR MVI A,01H ;SET A READ O)THRU P ALLOWED JNC ASKD2 STA DDRIV STA DDR MOV C,A LXI D,MSG4 CALL CMESS DDRA: CALL CRDC call switch CPI CR JZ DDRB ; write destination disk CPI CTLC JZ DCLR CPI ESC JZ DCLR JMP DDRA DDRB: CALL CWTC JMP WRDES switch: cpi ',' jnz notcr mvi a,cr ret notcr: cpi '.' jnz notesc mvi a,esc ret notesc: cpi '!' rnz mvi a,3 ret ;"--8- ; ; SOURCE ENTRY IS MEMORY ; ; Test to see if a syPERATION IN PROGRESS STA OPER LDA SDRIV ;GET SOURCE DRIVE CALL SELECT JNZ ASKSRC ;ASK FOR A NEW SOURCE MVI A,80 ;SET 80 SECTORS TO READ FOR CCP BDOS BIOS STA CURCNT ;SET COUNTER CALL MOVE ;AND DO IT... JP ASKDES ;NOW GET THE DESTINAT ION ;!--- ; ; WRITE SYSTEM FROM RAM BUFFER ; ; Writes 80 CP/M sectors to the target destination disk from ; the system ram BUFFER, starting at Track 0 Sector 0. ; ; -- stem really there. ; ; This is done via a simple string compare starting at ; Buffer + OFCOPY looking for the Copyright string. ; ; If the system is in memory, then prompts for destination. ; ; If no system currently in memory, prompts for new sou rce. ; ;"--- RMIMAG: LXI H,BUFFER+OFCOPY ;POINT TO WHERE STRING SHOULD BE LXI D,CMPSTG MVI B,CMPEND-CMPSTG ;FOR LENGTH RMI0: LDAX D CMP M JNZ RMI2 ;NOT THERE INX H INXĝ--- ; WRDES: LXI H,0 ;START AT TRK 0 SECTOR 0 SHLD SECTOR MVI A,02H ;SET A WRITE OPERATION IN PROGRESS STA OPER LDA DDRIV ;GET DEST DRIVE CALL SELECT JNZ ASKDES ;ASK FOR A NEW DEST MVI A,80 ;SET 80 SECTORS TO WRITE FOR CCP BDOS STA CURCNT ;SET COUNTER CALL MOVE ;AND DO IT... call flush ; now read t0,s0 to flush write JP ASKDES ;NOW GET THE NEXT DESTINATION ; ;--֑ D DCR B JNZ RMI0 ; RMI1: LXI D,MEM1 ;SHOW FROM MEMORY CALL CMESS JMP ASKDES ;AND GET THE DESTINATION RMI2: LXI D,MEM2 ;SHOW NO SYSTEM IN MEMORY CALL CMESS JMP ASKS2 ;AND GET NEW SOURCE ; CMPSTG: DB 'COPYRIGHT (C)' CMPEND:  ; --Y- ; ; IF A SOURCE FILENAME WAS ENTERED, THEN READ THE FILE AS ; THE SOURCE DISK. ; ; --$- GETFIL: LXI D,FCB+12 ;CLEAR FCB2------- ; ; SELECT DISK ; ; Selects the requested disk drive in (A) , and aquires the current ; Sectors-per-track entry from the DPB for this drive. ; ; If a select error, returns with NZ set. ; ;"-- SELECT: DCR A ;-1 ANI 0FH ;ISOLATE LUN MOV C,A MVI E,0 ;FORCE RE-TYPE ID THIS DRIVE CALL BSEL ;DO THE SELECT MOV A,H ORA L ;WATCH FOR SELECT ERROR JZ SELERR ;IF ERROR ON SOURCE SELECT LXI D,10 ;OFFSET TO CURREN EXTENT BEFORE OPEN MVI B,23 XRA A GF0: STAX D INX D DCR B JNZ GF0 LXI D,FCB ;OPEN FILE MVI C,OPEN CALL BDOS INR A JZ NOFIL ; file cannot be found LXI D,TBUF MVI C,STDMA CALL BDOS MVI B,16 ; read 16 dummies GF1: PUSH B ; save count LXI D,FCB MVI C,READS CALL BDOS POP B DCR B JNZ GF1 LXI H,IMAGE SHLD DMAADR GF2: XCHG MVI C,STDMA CALL BDOS LXI D,FCB MVI C,READS CALL BDOS ORA A JNZ ASKDES ;FILE READ COMPLETED - GET DESTINATION LHLD4T DPB THIS DRIVE DAD D MOV A,M ;GET THE DPB ADDRESS FROM THE DPB INX H MOV H,M MOV L,A MOV A,M ;THIS GIVES US THE SECTORS PER TRACK STA MAXSEC ;SAVE IT FOR LATER LXI H,BUFFER ;SET DMA TRANSFER ADDRESS SHLD CURPNT ;SET BUFFER TO START XCHG CALL BSDMA XRA A ;LEAVE WITH Z SET RET SELERR: LXI D,SELM ;ISSUE SELECT ERROR CALL CMESS MVI A,0FFH ORA A ;AND SET NZ RET SELM: DB 07H,CR,LF,LF,' DRIVE SELECT ERROR ',CR,'$' ;--- ] -- ; ; MOVE SYSTEM ; ; This is the work code to Read or Write the number of sectors ; starting at (SECTOR) for (CURCNT) with data buffer at ; (CURPNT), and the drive sectors-per-track at (MAXSEC). ; ; Returns with Z set if done and no errors, else N Z set. ; ;"--- MOVE: LXI D,CRSTG ;CR LF STRING CALL CMESS MOV0: MVI A,'.' ;SHOW WE ARE BUSY CALL CWTC LHLD CURPNT ;GET CURRENT BUFFER POINTER X this BIOS is Version 2.1 or greater, also brings in the ; secondary Jump Table. ; ; Exits with Z set if lower than 2.1 Bios level ; ;"--- CGET: LHLD 1 ;GET START OF BIOS CODE AREA LXI D,BBOOT ;MOVE TO LOCAL STORAGE MVI B,BLEN ;SET COUNT CALL CGET0 ;MOVE STRING MVI A,0 ;TEST FOR VERSION CALL BGETT ;IF 0, THEN LESS TAHN 1.4 STA BVERS ;SAVE BIOS VERS INX H ;SEE IF 1HL IS FFFF MOV A,H ORA L RZ ;IF SO, THEN jCHG CALL CDMA ;AND SET DMA ADDRESS LHLD SECTOR ;GET TRK AND SECTOR LDA OPER CALL CRDWR ;AND READ OR WRITE ONE SECTOR JNZ MOVERR ;DISK ERROR LHLD CURPNT LXI D,128 DAD D ;BUMP DMA ADDRESS SHLD CURPNT LHLD SECTOR INX H ;AND BUMP SECTOR +1 SHLD SECTOR LDA MAXSEC ;TEST AGAINST CURRENT MAX SECTOR CMP L JNZ MOV1 ;NOT THERE YET MVI L,0 ;RESET SECTOR TO 0 INR H ;AND BUMP TRACK +1 SHLD SECTOR MOV1: LDA CURCNT ;SECTOR COUNTER -1 DCR A STA CURCNT JNZ MOV0 ;DO NEXYOLD SYSTEM DCX H ;FIX HL SINCE HAS THE TABLE ADDRESS LXI D,BNXTTBL ;SAVE NEXT TABLE MVI B,BSLEN CALL CGET0 MVI A,0FFH ;SET NZ ORA A RET ;TO ID THIS LEVEL CGET0: MOV A,M STAX D INX H INX D DCR B JNZ CGET0 RET ; ;!--k- ; ; CMESS SEND MESSAGE STRING ; ; Outputs the string pointed to be (DE) until the ($) delimeter ; ;!--- CMESS: MVI C,9 J T RET ;ALL DONE HERE ; MOVERR: LXI D,MESER ;JUST ISSUE THE MESSAGE CALL CMESS JP 0 ;AND WARM BOOT ; MESER: DB CR,LF,LF,'R/W ERROR - ABORTED - ' DB CR,LF,'$' ; flush: ; flush data with a "don't care" read lhld curpnt ; set dma xchg ; . call cdma ; . lxi h,0 ; read track 0, sector 0 mvi a,01h ; . call crdwr ; . jnz moverr ; display any error ret ; and return ;"-- ; ; READ OR WRITE SECTO  MP BDOS ;"--/- ; ; CDMA Set (DE) to the DMA address ; ;"--&- CDMA: MVI C,26 JMP BDOS ; ;#--/ ; ; CRDC Read and Echo a Console Input ; ;"--^- ; CRDC: lda clchr ora a jz crdc2 dcr a sta clchr lhld clptr mov a,m inx h R ENTRY ; ; Enter with the operation in (A) READ = 01 WRITE = 02 ; Track in (H) Logical Sector in (L) ; ; Data is stored at (DMA) ; ; Exits with A and HL set as entered ; ; Returns with NZ set id R/W error ; ;!-- COPR DB 0 ;SAVED OPER BYTE CSEC DW 0 ;TRK AND SECTOR SAVED ; CRDWR: STA COPR ;SAVE OPER CODE SHLD SECTOR ;AND TRK/SECTOR MOV C,H MVI B,0 ;SET TRACK FIRST CALL BSTRK LDA SECTOR ;GET SECTOR NEXT MOV(V shld clptr push psw call cwtc pop psw ret crdc2: MVI C,1 JMP BDOS ; ;"--7 ; ; CWTC Write character in (A) to the console ; ;"--. CWTC: MVI C,2 MOV E,A JMP BDOS ;!--4- ; ; CLEAR THE SCREEN USING LINE-FEEDS ONLY ; ;!-- C  C,A MVI B,0 CALL BSSEC LDA COPR ;GET OPERATION CODE CPI 01H ;READ? JNZ CWRTE CALL BSRD ;READ SECTOR JMP CSEND CWRTE: CALL BSWRT ;ELSE WRITE ONE CSEND: CPI 0 ;TEST STATUS LDA COPR ;RESTORE A AND HL LHLD SECTOR RET ;RETURN WITH Z SET IF OK ;#--- ; ; CCGET GET SYSTEM BIOS JUMP TABLES ; ; Brings the current BIOS Jump tables starting at WARM BOOT ; to this local area for ease of utility access. ; ; IfǙLEAR: MVI A,24 ;SET TO CLEAR 24 LINES STA CURCNT ;USE THE COUNTER CLR0: MVI A,LF ;ISSUE A LINE FEED CALL CWTC LXI B,1670 ;SET ABOUT 10 MSEC DELAY CLR1: ;DO DELAY BETWEEN SO ALL CRTS CAN FOLLOW DCX B MOV A,C ORA B JNZ CLR1 6LDA CURCNT DCR A STA CURCNT JNZ CLR0 RET ; ;"--R ; ; EXIT PROGRAM ; ; Clear screen and Warm Boot System. (same as JMP 0) ; ;--- `---- DCLR: JP BBOOT ;TO WARM BOOT ; ;!--: ; ; REPLICATED BIOS JUMP TABLE FOR EASE OF USAGE. ; ;!-- ; BBOOT DS 3 BCSTS DS 3 BCIN DS 3 BCOUT DS 3 BLST DS 3 BPNCH DS 3 BRDR DS 3 BHOME DS 3 BSEL DS 3 BSTRK DS 3 BSSEC DS 3 BSDMA DS 3 BSRD DS 3 BSWRT DS 3 BLSTS DS 3 BSTRN DS 3 BGETT DS 3 ;GET 2.1 JUMP TABLES BGETE DS 3 BIOINT DS 3 BSCS I DS 3 B Removed HD controller name from display. ; ; 1.0 E2.19 RJB Original version ; VER EQU 20 ; version SWIDTH EQU 80 ; Screen width PWIDTH EQU 132 ; Maximum printer width THIS$MONTH EQU 2 ; This version's month THIS$DAY EQU 05 ; . day THIS$YEAR EQU 86 ; . year MIN$VERSION EQU 31 ; Minimum bios version allowed FALSE EQU 0 TRUE EQU NOT FALSE YES EQU 1 NO EQU 0 ; Character equates CTRLC EQU 3 ; CP/M break key TAB EQU 9 ; Tab character (CTRL-I) ESC EQU 27 ; escape key (ClBLEN EQU $-BBOOT ;LENGTH TO GET ; BNXTTBL: ;VERSION 2.1 > SECONDARY TABLE BSWAP DS 3 BSXBINT DS 3 BPHTBAC DS 3 BPAGET DS 3 DS 3 DS 3 DS 3 DS 3 BSLEN EQU $-BNXTTBL BVERS: DB 0 ;VERSION OF BIOS CODE MSG1: DB CR,LF,' AMPRO Sy`stem Generation Utility' DB CR,LF,'Copyright (C) 1984,1985 AMPRO Computers, Inc.' DB CR,LF,' Version ' DB VER/10+'0','.',VER MOD 10+'0' DB CR,LF,'$' MSGS: DB CR,LF,'Enter Source Drive? (A thru ' SMXD: DB 'P) $' MSG2: DB CR,LF,'PlaTRL-[) CR EQU 13 ; carriage return (CTRL-M) LF EQU 10 ; line feed (CTRL-J) EOF EQU 26 ; CP/M end-of-file (CTRL-Z) EOS EQU '$' ; CP/M end-of-string (dollar sign) ; bdos equates BDOS EQU 5 ; bdos entry RDCON EQU 10 ; read console buffer CONBUF EQU 80h ; location of console buffer ; other equates NDEV EQU 16 ; number of disk devices supported ORG 0100H JMP START SCREEN$WIDTH: DB SWIDTH-1; 1 less than actual # of characters SLOW$TERM: DB 0 ; Set to delay (ms) for slow terminal ce source on ' SDR: DB 'A, then type $' MSGD: DB CR,LF,LF,'Enter Destination Drive? (A thru ' DMXD: DB 'P) $' MSG4: DB CR,LF,'Place destination disk on ' DDR: DB 'A, then type $' CRSTG: DB CR,LF,'$' MEM2: DB cr,lf,rlf,'NO SYSTEM IN MEMORY.',lf,'$' MEM1: DB cr,lf,lf,'Source = Memory Image.',lf,'$' ds 32 stack: END 0+'0','.',VER MOD 10+'0' DB CR,LF,'$' MSGS: DB CR,LF,'Enter Source Drive? (A thru ' SMXD: DB 'P) $' MSG2: DB CR,LF,'Pla0 CMD$LINE$CHRS: DB 0 ; Count of cmd line characters left CMD$LINE$PTR: DW 0 ; Pointer to next cmd line chr NAME$MSG: DB 0DH,'AMPRO ' NAME: DB 'SWAP' NLEN: EQU $-NAME DB ' Utility',CR,LF DB 'Copyright (C) 1985 AMPRO Computers, Inc.',CR,LF DB 'Version ',VER/10+'0','.',VER MOD 10+'0' DB ' [',THIS$YEAR-80+'@',THIS$MONTH+'0','.' DB THIS$DAY/10+'0',THIS$DAY MOD 10 + '0',']' DB CR,LF,LF,'$',CR HELP$MSG: DB 'Usage: SWAP' DB CR,LF,'$',CR,' ',CR BIOS$PLUS: DB 'This program requires AMPRMO bios version ' DB MIN$VERSION/10+'0','.',MIN$VERSION MOD 10+'0' DB ' or later.',CR,LF,'$' DB CR,' ',CR,EOF SIGNON$MSG: DB 'The AMPRO SWAP utility allows you to swap the ' DB 'definition of any two CP/M drive letters. For example, ' DB 'if you have two floppy drives at A: and B:, and two ' DB 'hard disk partitions at F: and G:, you could swap pairs ' DB 'A and F, B and G, C and F, and D and G, ' DB 'to place the hard disk partitions at A: and B:, ' DB 'and the floppy drives at C: and xy * P* * * * Copyright (C) 1985,1986 AMPRO COMPUTERS, INC. * * * * * ; Assemble with asm.com or equivalent. There is no Z80 code. ; Revision history: ; ; Ver Date Who Description ; --- ----- --- --> ; 2.0 F2.05 RJB Fixed foreign format display error. ;  ?Changed to allow foreign drive letter swap. ; ; 1.1 E6.17 RJD:.',CR,LF,LF DB 'NOTE: Swapping drive A: has these two restrictions:',CR,LF,LF DB ' (1) The A: drive can only be swapped with an existing ' DB 'drive (one of those listed by SWAP under "current ' DB 'assignments"). ',CR,LF,LF DB ' (2) Be sure to use the AMPRO SYSGEN utility to ' DB 'write a system to the drive which is to become drive ' DB 'A:, before swapping drive A: with any other drive. ',CR,LF,LF DB '$' ; ; Initialize the stack and command line input pointer. ; START: LX BjI H,0 ; Get old stack pointer DAD SP ; . SHLD OLDSP ; Save it for later LXI SP,STACK ; Put SP at our stack LXI H,0080H ; Copy command line to a 'safe' area LXI D,INBUF ; . MVI B,128 ; . CALL MOVE$BLOCK ; . XCHG ; Set up pointers and count of chrs MOV A,M ; . STA CMD$LINE$CHRS ; . INX H ; . INX H ; . SHLD CMD$LINE$PTR ; . ; ; Display the name and signon message ; TOP$MENU: ORA A ; If cmd line, then no signon JNZ WHICH$BIOS ; . CALL CLEAR$SCREEN ; Otherwise, 'swap' drive A:? JNZ GS$SWAP$EM ; . MOV A,B ; . if so, make sure other is active GS$TESTFORA: CALL LB$GET$LDTE ; Get logical device table entry MOV A,M ; Zero means not active ORA A ; . JNZ GS$SWAP$EM ; . (not zero means ok to swap) LXI D,GS$NOT$ACTIVE ; Display error message if drive CALL JUSTIFY ; . not active CALL RET$TO$CONT ; Wait for a RETURN XRA A ; Clear command line on an error STA CMD$LINE$CHRS ; . JMP SHOW$CURRENT ; and show 'em what's available GS$SWAP$EM: CALL clear the screen LXI D,NAME$MSG ; Display the name, etc. CALL CENTER$OUTPUT ; . LXI D,SIGNON$MSG ; and the initial message CALL JUSTIFY ; . ; ; Copy the bios to a local area (to make direct bios calls easier) ; and check for version 2.0+. If not version 2.0+, display an ; error message and exit. ; WHICH$BIOS: CALL GET$BIOS$VERS ; Copy the bios to a local area ; ; Check the version of the bios against the minimum version allowed. ; If the bios is not at least the minimum, display LB$SWAP$DRV ; otherwise, swap the drives. LXI D,S$SWAPPED ; and tell 'em about it CALL JUSTIFY ; . JMP DO$ANOTHER S$WHO$MSG: DB CR,LF DB 'Which drive do you want to swap ' DB '(A-P, ? for list, to quit): ','$' S$WITH$MSG: DB ' Swap ' S$WHO$LETTER: DB 'x: with which drive ' DB '(A-P, ? for list, to quit): ','$' S$SWAPPED: DB TAB,'<<< Drive ' S$SW1: DB 'x: successfully swapped with drive ' S$SW2: DB 'x: >>>',CR,LF,'$' S$WHO$OKC: S$WITH$OKC: DB '?ABCDEF an error message ; and exit to the operating system. ; CHECK$B$VERS: LDA LB$VERS ; Get bios version # CPI MIN$VERSION ; Check against minimum version JNC MINBIOS ; At least minimum version . . . LXI D,BIOS$PLUS ; Not minimum, display error message CALL JUSTIFY ; . JMP ALL$DONE ; and exit. ; ; Perform any initialization particular to each version of the Ampro ; bios, if necessary. ; MINBIOS: ; ; Copy the device descriptors of the active devices to a local area ; and sort thGHIJKLMNOP',0 GS$NOT$ACTIVE: DB CR,LF,'ERROR -- Cannot swap drive A: with a non-existant ' DB 'drive letter.',CR,LF,LF,'$' SHOW$CURRENT: CALL CLEAR$SCREEN ; Clear the screen LXI D,CURRENT$LTR ; "Current CP/M drive letter assignments" CALL CENTER$OUTPUT ; . CALL DISPLAY$FDEV ; Display floppy devices CALL DO$CRLF ; . CALL DISPLAY$EINF ; Display message about E-drive CALL DO$CRLF ; . CALL DISPLAY$SDEV ; Display SCSI devices CALL DO$CRLF ; . JMP DO$ANOTHER CURRENT$LTR: DB '>em. If the count of active devices is zero, display ; an error message and exit. ; DO$ANOTHER: CALL GET$ACTIVE$DEV ; Get the active device descriptors CALL SORT$ACTIVE ; and sort them LXI D,S$WHO$MSG ; Prompt for drive to swap LXI H,S$WHO$OKC ; . CALL PROMPT ; . JZ ALL$DONE ; exit if key pressed STA S$WHO$LETTER ; save letter in second prompt STA S$SW1 ; . CPI '?' ; check for help JZ SHOW$CURRENT ; . show current assignments SUI 'A' ; Convert A-P to 00H-0FH MOV C,A>> Current CP/M Drive Letter Assignments <<<' DB CR,LF,LF,'$' ; ; Restore the old stack pointer and exit the program. ; ALL$DONE: JMP LB$WBOOT ; Return via warm boot * 8* * * * Library routines . . . * * * * * CENTER$OUTPUT: ; ; [DC.20] ; ; Automatically centers the output line(s) based on the line width ; stored in SCREEN$WIDTH. Each line is delimited with ; save swap drive LXI D,S$WITH$MSG ; Prompt for drive to swap with LXI H,S$WITH$OKC ; . PUSH B ; . CALL PROMPT ; . POP B ; . JZ ALL$DONE ; exit if key pressed CPI '?' ; check for help JZ SHOW$CURRENT ; . show current assignments STA S$SW2 ; SUI 'A' ; convert A-P to 00h-0Fh MOV B,A ; save swap with drive ; ORA A ; Is 'swap with' drive A:? JNZ GS$OTHER ; . MOV A,C ; . if so, make sure other is active JMP GS$TESTFORA ; . GS$OTHER: MOV A,C ; ORA A ; Is CR+LF. This ; routine will return to the caller when it encounters the string ; terminator, '$'. Any additional LF characters after a CR+LF pair ; will be passed through. ; ; Entry: ; DE = Pointer to output string(s), terminated with CR+LF. ; ; Exit: ; The output string(s) are sent to the screen ; ; Modifies: DE ; PUSH PSW ; Save registers PUSH B ; . PUSH H ; . CENTER$NEXT$LN: CALL GET$STRLEN ; Get length to next CR or '$' in B MOV A,B ; Check for zero length ORA A ; . JZ \NEXT$DELIM ; If so, output the CR, LF, etc. LDA SCREEN$WIDTH ; Compute offset needed to center line STC ; . SBB B ; . (if there are too many chrs, just JC NO$BLANKS ; . print the line as is . . . ) ANI 0FEh ; Clear least significant bit RRC ; . and rotate to divide by two MVI C,' ' ; Output enough blanks to center line CNZ CON$CHR$AC ; . (only if count is non-zero) NO$BLANKS: MOV A,M ; Save CR for later MVI M,'$' ; Plug position with '$' for cp/m CALL CON$MSG ; . print ; A = character from console, except for ctrl-c, which causes ; an immediate jump to ALL$DONE ; ; Modifies: ; A ; CALL LB$CONIN CPI CTRLC JZ ALL$DONE RET CON$MSG: ; ; [DC.20] ; ; Console message ; ; Entry: ; DE = pointer to message string, terminated with '$' ; ; Exit: ; message printed on console ; ; Modifies: A, BC ; PUSH PSW ; Save registers PUSH B ; . PUSH D ; . PUSH H ; . MVI C,9 ; BDOS print string command CALL BDOS ; . POP H ; Restore regis string function MOV M,A ; Restore saved CR NEXT$DELIM: MOV A,M ; Get character CPI CR ; Print it if CR JZ OUTPUT$DELIM ; . CPI LF ; Print it if LF JZ OUTPUT$DELIM ; . CPI EOS ; Stop processing if EOS ('$') JZ CENTER$DONE ; . XCHG ; Put new pointer in DE JMP CENTER$NEXT$LN ; Go & do the next line OUTPUT$DELIM: CALL CON$CHR ; Output delimiter CPI LF ; Wait 10ms if we have a line feed CZ WAIT ; . INX H ; Point to next chr JMP NEXT$DELIM ; and check that one, also CEters POP D ; . POP B ; . POP PSW ; . RET ; and return DISPLAY$FDEV: ; ; [E2.15] ; ; LXI D,D$FDEV$HDR ; Print header CALL CENTER$OUTPUT ; . LXI H,ACTIVE$FDEV ; Get pointer to active floppies LXI B,0004H ; Set starting and maximum # D$NEXT$FDEV: MOV A,M ; Get unit # ORA A ; If zero, skip to next JZ D$BUMP$PTR ; . PUSH H ; Copy output line to output buffer PUSH B ; . LXI H,D$FDEV$LIN ; . LXI D,OUTBUF ; . MVI B,D$FDEV$HLEN ; . CALL MOVE$BLOCK ; . POP5NTER$DONE: POP H ; Restore registers POP B ; . POP PSW ; . RET ; and return CLEAR$SCREEN: ; ; [E1.28] ; ; This routine clears the screen by calling DO$CRLF 26 times. ; ; Entry: ; None ; ; Exit: ; The screen is cleared ; ; Modifies: ; None ; PUSH PSW ; Save just in case MVI A,26 ; 26 CRLF's C$NEXT$LINE: CALL DO$CRLF ; Next line DCR A ; Done? JNZ C$NEXT$LINE ; Nope. POP PSW ; Restore original AF RET ; and return CON$CHR: ; ; [DC.20] ; ; This routiZ B ; . POP H ; . PUSH PSW ; update 'current' drive letter ANI 07FH ; . (mask out 'E-disk' bit) STA OUTBUF+D$CURRENT; . POP PSW ; . ANI 080H ; get 'E-disk' bit back JNZ D$EDISK$OK ; 'E-disk' present, leave E: alone PUSH H ; . PUSH B ; . LXI H,D$EBLANK ; . LXI D,OUTBUF+D$EDISK; . MVI B,4 ; . CALL MOVE$BLOCK ; . POP B ; . POP H ; . D$EDISK$OK: PUSH B ; PUSH H ; MOV A,B ; update floppy device number LXI H,FNAMES ; . LXI B,FNAMES$LEN ; . CALL INDEX$TAune sends the character in the "A" register to the console ; through the BDOS conout call. ; ; Entry: ; A = character to send ; ; Exit: ; character is sent to the console ; ; Modifies: ; None ; PUSH PSW PUSH B PUSH D PUSH H MVI C,2 MOV E,A CALL BDOS POP H POP D POP B POP PSW RET CON$CHR$AC: ; ; [DC.20] ; ; This routine sends the character in the C register to the console ; the number of times in the A register. ; ; Entry: ; A = Number of times to send charactbBLE ; . LXI D,OUTBUF+D$FNAME; . MVI B,FNAMES$LEN ; . CALL MOVE$BLOCK ; . POP H ; . POP B ; . LXI D,OUTBUF ; and output the line CALL CENTER$OUTPUT ; . D$BUMP$PTR: INX H ; Bump pointer to next device, INR B ; increment letter count, MOV A,B ; Compare to maximum, CMP C ; . JNZ D$NEXT$FDEV ; Do another if we're not done. RET D$FDEV$HDR: DB '> FLOPPY DISK ASSIGNMENTS <',CR,LF DB 'CP/M drive ' DB 'Floppy disk',CR,LF DB ' --',CR,LF,'$' D$FDEer ; C = Character to send ; ; Exit: ; Same ; ; Modifies: ; None ; PUSH PSW ; Save all registers PUSH B ; . PUSH D ; . PUSH H ; . MOV B,A ; Move data to accomodate CP/M MOV A,C ; . NEXT$CHR$OUT: CALL CON$CHR ; Send 1 chr DCR B ; Decrement counter JNZ NEXT$CHR$OUT ; Done? POP H ; Restore all registers POP D ; . POP B ; . POP PSW ; . RET ; and return CONIN$NE$XC: ; ; [E1.28] ; ; Console input, no echo, exit on ctrl-c ; ; Entry: ; none ; ; Exit:V$LIN: DB ' ' D$CURRENT: EQU $-D$FDEV$LIN DB 'x ' D$EDISK: EQU $-D$FDEV$LIN DB '(' E$LETTER$1 DB '*)' D$EBLANK: DB ' ' D$FNAME: EQU $-D$FDEV$LIN DB ' ' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' FNAMES$LEN: EQU 6 ; end of DISPLAY$FDEV DISPLAY$EINF: ; ; [F2.05] ; ; Display message about E-drive labeling. ; LXI D,D$EINFO$MSG ; Print the message CALL CENTER$OUTPUT ; . RET ; " D$EINFO$MSG: DB '(' E$LETTER$2: DB '*) = Current foreign format drive letter.' DB CR,LF,LF,'$' ; DISPLAY$SDEV: ; ; [E2.15] ; ; Display the hard disk data in the active device table. ; ; Entry ; Active devices in the ACTIVE$SDEV area ; ; Exit ; Devices are displayed on the console ; ; Modifies ; All ; LDA TOTAL$ACTIVE ; Check how many devices ORA A ; . RZ ; Return if no devices active LXI D,FD$HEADER ; Display table header CALL CENTER$OUTPUT ; . LXI D,LAST$SCSI ; lags and PUSH D ; . D just in case LXI D,OUTBUF ; Send line to console CALL CENTER$OUTPUT ; . D$SEND$DONE: POP D ; POP PSW RET LOGICAL$UNIT: DB 0 ; Current logical unit LAST$SCSI: DB 0 ; Last hard disk scsi address LAST$CTRL: DB 0 ; Last hard disk controller LAST$DTYPE: DB 0 ; Last hard disk drive type LAST$DRIVE: DB 0 ; Last hard disk drive CPM$PTR: DW 0 ; Pointer to next CP/M letter pos FD$HEADER: DB '> HARD DISK ASSIGNMENTS <',CR,LF DB 'CP/M drive(s) ' DB 'Addr SInit local data LXI B,04FFH ; . (fill last info with 0FFh's) CALL FILL$BLOCK ; . XRA A ; Current logical D$GET$UNIT: STA LOGICAL$UNIT ; save current unit # CALL INDEX$ACTIVE ; HL = address of active table entry LXI D,LAST$SCSI ; See if same device MVI B,4 ; Compare for 4 bytes CALL STR$COMP ; . JZ D$ADD$LETTER ; Same device -- add CP/M letter LDAX D ; Not same device, check to see ORA A ; . if last device was 'FF'. If so, JM D$DONT$DISP ; . don't display the line. Unit #',CR,LF DB ' -- ' DB '--J-',CR,LF,'$' DRIVE$INFO: EQU $ DRIVE$LETTERS: EQU $-DRIVE$INFO DB ' ' DRIVE$CTRL: EQU $-DRIVE$INFO DB ' ' DRIVE$ADDRESS: EQU $-DRIVE$INFO DB '0 ' DRIVE$UNIT: EQU $-DRIVE$INFO DB '0' DB CR,LF,'$' DRIVE$LEN EQU $-DRIVE$INFO DO$CRLF: ; ; [DC.27] ; ; This routine sends a carriage return and a eline feed to the terminal, ; and then waits 'SLOW$TERM' ms for a slow terminal to catch up. ; ; EnCALL D$SEND$LINE ; Send line to console D$DONT$DISP: MVI B,4 ; Since DE & HL still point to last & CALL MOVE$BLOCK ; . current, move current to last. PUSH H ; save ptr LXI H,DRIVE$INFO ; Copy template to output buffer LXI D,OUTBUF ; . MVI B,DRIVE$LEN ; . CALL MOVE$BLOCK ; . LXI H,OUTBUF+DRIVE$LETTERS ; Setup CP/M letter ptr SHLD CPM$PTR ; . POP H ; Restore ptr to current PUSH H ; . and save it back MOV A,M ; Plug output buffer w/device info CALL SCSI$TO$BIN ; SCSI Jtry: ; none ; ; Exit: ; CR + LF is sent to the screen. ; ; Modifies: ; none ; PUSH PSW ; Save AF MVI A,0Dh ; Send carriage return CALL CON$CHR ; . MVI A,0Ah ; and line feed CALL CON$CHR ; . LDA SLOW$TERM ; Check slow flag ORA A ; . CNZ WAIT ; wait for the s-l-o-w terminals POP PSW ; recover original AF RET ; and return FILL$BLOCK: ; ; [E1.29] ; ; Fills the buffer pointed to by DE with the character in C for ; a length of B bytes (max 256). ; ; Entry: ; B =gaddress ADI '0' ; . (convert to ascii 0-7) STA OUTBUF+DRIVE$ADDRESS ; . INX H ; . INX H ; . INX H MOV A,M ; Logical unit # RLC ; . (move bits 7-5 to 2-0) RLC ; . RLC ; . ANI 07H ; . (mask out other bits) ADI '0' ; . (convert to ascii 0-7) STA OUTBUF+DRIVE$UNIT ; . POP H ; Restore ptr so we agree D$ADD$LETTER: INX H ; Get CP/M letter for this device INX H ; . INX H ; . INX H ; . INX H ; . MOV B,M ; . LHLD CPM$PTR ; Get ptr to CP/M letter Length to fill ; C = Character to fill with ; DE = Start of buffer ; ; Exit: ; Buffer filled ; ; Modifies: ; Only buffer area affected ; PUSH B ; Save registers PUSH D ; . XCHG ; Set up M register use F$NEXT: MOV M,C ; Stuff a char INX H ; Bump pointer DCR B ; Bounce counter JNZ F$NEXT ; Do it again if not done XCHG ; We are done. restore old HL POP D ; Restore other registers POP B ; . RET ; and return GET$ACTIVE$DEV: ; ; [E2.15] ; ; Get the active i area MOV M,B ; Save CP/M drive letter INX H ; Bump pointer INX H ; . SHLD CPM$PTR ; Save CP/M letter area pointer back D$NEXT$UNIT: LDA TOTAL$ACTIVE ; Get count of active units MOV B,A ; Save for a moment LDA LOGICAL$UNIT ; Get unit we're working on INR A ; Bump to next CMP B ; Are we done? JNZ D$GET$UNIT ; No -- go do another CALL D$SEND$LINE ; Send this line out, too. CALL DO$CRLF ; Send out an extra CR+LF. RET ; all done D$SEND$LINE: PUSH PSW ; Save A & fdevices. Store the floppy and E-disk descriptions ; in the ACTIVE$FDEV table, and store the SCSI descriptions in the ; ACTIVE$SDEV table. ; ; Entry: ; none ; ; Exit: ; The active device descriptions will be in tables. ; ; ACTIVE$FDEV (4 entries, 1 byte each) format: ; ; +0: Current CP/M letter and "E" disk status. ; (Bit 7 set indicates this device is the "E" disk) ; ; ACTIVE$SDEV (11 entries, 8 bytes each) format: ; ; +0: SCSI Address ; +1: Controller type (0-3) ; +2: Drive type (0-3 s) ; +3: Drive unit (0-7) -- shifted for use with SCSI commands ; +4: Logical partition (0-7) ; +5: Current CP/M letter ; +6: spare ; +7: spare ; ; Calls: ; LB$GET$LDTE Get logical drive table entry address ; ; Modifies: All ; LXI D,ACTIVE$SDEV ; Clear the table LXI B,ACTIVE$TLEN SHL 8 ; CALL FILL$BLOCK XCHG ; SHLD NEXT$POS ; Save pointer for later XRA A ; Clear count of active SCSI devices STA TOTAL$ACTIVE ; . G$GET$INFO: PUSH PSW ; Save current logical unit # CALL LB$GET$LM ; . ANI 0E0H ; . STA DRV$LUN ; . INX H ; (+3) SCSI address MOV A,M ; . STA SCSI$ADDR ; . POP PSW ; PUSH PSW ; Get CP/M letter ADI 'A' ; . STA CPM$LETTER ; . LHLD NEXT$POS ; Get next buffer position LXI D,SCSI$ADDR ; . and current scratch area XCHG ; Now DE=buffer, HL=scratch MVI B,8 ; Save data CALL MOVE$BLOCK ; . LXI H,8 ; Update buffer pointer DAD D ; . SHLD NEXT$POS ; . LXI H,TOTAL$ACTIVE ; Bump count of SCSI devices INR M ; . G$NEXT$DEV: PO&DTE ; Get logical drive table entry addr MOV A,M ; If zero, non-active device ORA A ; . JZ G$NEXT$DEV ; . CPI 8 ; Only driver codes 0-7 supported JP G$NEXT$DEV ; . LXI D,OUTBUF ; Clear scratch area LXI B,0800H ; Fill with 00h for length of 8 bytes CALL FILL$BLOCK ; . XCHG ; Save pointer to drive entry LXI H,G$EXE$TBL ; JMP GO$TABLE ; Jump to proper routine G$EXE$TBL: DW G$NEXT$DEV ; Driver code = 00 DW G$FLOPPY ; Driver code = 01 DW G$EDISK ; Driver code = 02 DW GP PSW ; Get logical back INR A ; Bump to next logical CPI 16 ; Do maximum of 16 logicals JNZ G$GET$INFO ; Not done -- go get more RET DS 16-($ MOD 16) ACTIVE$SDEV: DS 12*8 ; SCSI device info ACTIVE$FDEV: DB 'A','B' ; Floppy CP/M letters DB 'C','D' ; . ACTIVE$TLEN: EQU $-ACTIVE$SDEV ; Active table length ACTIVE$EOT: DB 0,0,0,0 ; End of table, spares TOTAL$ACTIVE: DB 0 ; # of active SCSI devices NEXT$POS: DW 0 ; Next SCSI buffer position SCSI$ADDR: DB 0 ; SCSI Address (0-7) CTR,$HARD ; Driver code = 03 DW G$NEXT$DEV ; Driver code = 04 DW G$NEXT$DEV ; Driver code = 05 DW G$NEXT$DEV ; Driver code = 06 DW G$NEXT$DEV ; Driver code = 07 G$F$DRIVE: ; Convert floppy drive to ptr INX H ; Get byte MOV A,M ; Floppy drive byte ANI 03h ; Isolate drive bits LXI H,ACTIVE$FDEV ; Compute table addr MOV C,A ; . MVI B,0 ; . DAD B ; . RET ; and return G$FLOPPY: XCHG ; Get pointer to drive entry back CALL G$F$DRIVE ; Convert floppy drive POP PSW ; GetL$TYPE: DB 0 ; Controller type (0-3) DRV$TYPE: DB 0 ; Drive type (0-3) DRV$LUN: DB 0 ; Drive logical unit # (0-7) PARTITION: DB 0 ; Drive partition (0-7) CPM$LETTER: DB 0 ; CP/M letter (0-15) UNIT: DB 0 ; Unit number (1-8) SPARE: DB 0 ; Spare ; end of GET$ACTIVE$DEV routine GET$BIOS$VERS: ; ; [DC.20] ; ; Get bios version -- Copies the current BIOS jump tables (starting ; at warm boot) to a local area for ease of utility access. If the ; BIOS is version 2.0 or greater, the secondary   logical unit PUSH PSW ; . ADI 'A' ; Convert 0-15 to A-P ORA M ; Or in E-disk, if present MOV M,A ; Save new disk letter JMP G$NEXT$DEV ; Get next device info G$EDISK: CALL LB$GETEDSK ; Get pointer to E-disk parameters LXI B,15 ; Bump pointer to E-disk drive DAD B ; . DCX H ; Decrement ptr because next routine bumps it CALL G$F$DRIVE ; Convert floppy drive MOV A,M ; Set high bit for E disk ORI 80h ; . MOV M,A ; . POP PSW ; Get drive letter PUSH PSW ; Save it backjump table is copied ; also. ; ; Entry: ; none ; ; Exit: ; Z = bios 1.0 - 1.4 (floppy only bios) ; NZ = bios 2.0 or greater (floppy & fixed disk bios) ; ; Modifies: All registers ; LHLD 1 ; Get start of bios jump table LXI D,LB$BIOS$TBL ; Move bios to local storage MVI B,LB$LEN ; . (length of bios area) CALL MOVE$BLOCK ; . (move routine) MVI A,0 ; Test CP/M version CALL LB$GETNXT ; Get next jump table STA LB$VERS ; Save bios version INX H ; See if HL is 0FFFFh MOV A,H ;  ADI 'A' ; Convert 0-15 to A-P STA E$LETTER$1 ; Save in '(*)' location STA E$LETTER$2 ; and in description JMP G$NEXT$DEV ; Get next device info G$HARD: XCHG ; Get pointer to drive entry back INX H ; (+1) Controller, Drive, Partition MOV A,M ; Get controller (0-3) RRC ; . RRC ; . ANI 03H ; . STA CTRL$TYPE ; . MOV A,M ; Get drive type (0-3) ANI 03H ; . STA DRV$TYPE ; . MOV A,M ; Get partition ANI 0F0H ; . STA PARTITION ; . INX H ; (+2) Unit # MOV A,,. ORA L ; . RZ ; If so, then old version DCX H ; Fix HL as it has the table addr LXI D,LB$XTBL ; Move extra table to local storage MVI B,LB$XLEN ; . (length of extra table) CALL MOVE$BLOCK ; . (move routine) MVI A,0FFH ; Set NZ to indicate bios ORA A ; ... version 2.1+ RET ; ... and return. GET$HL$PTR: ; ; [DC.20] ; ; Gets the pointer pointed to by HL and puts it in HL ; ; Entry: ; HL = pointer to put in HL ; ; Exit: ; HL = pointer ; ; Modifies: none ; PUSH PS t&W ; Save A register MOV A,M ; Get low byte of pointer INX H ; . MOV H,M ; Get high byte of pointer MOV L,A ; Pointer is now together POP PSW ; Restore A register RET ; and return GET$STRLEN ; Searches the string pointed to by HL and returns the string length ; to the next carriage return. The length is returned in B. PUSH D ; Save start of string MVI B,0 ; Clear counter TRY$NEXT$CHR: LDAX D ; Get character CPI CR ; Is it CR? JZ EOS$FOUND ; . CPI '$' ; Is it '$'?\gainst ORA A ; End of table? JNZ I$NOT$EOT ; No, check chr DCR A ; Decrement to get 0ffh MOV B,A ; Stuff for later move JMP I$CHR$OK ; And exit I$NOT$EOT: CPI 0FFH ; Place holder character? JZ I$NEXT$PTR ; . Yes, bump pointers CMP C ; Chrs match? JZ I$CHR$OK ; . Yes, return I$NEXT$PTR: INX H ; . No, bump pointer INR B ; . . and bump counter JMP I$CHK$NEXT ; . . and check next chr I$CHR$OK: MOV A,B ; Set status based on ORA A ; . position counter MOV A,C ; Get user9 JZ EOS$FOUND ; . INR B ; No -- increment count and INX D ; . point to the next character JMP TRY$NEXT$CHR ; . EOS$FOUND: POP H ; CR or '$' found, recall orig ptr XCHG ; DE=orginial, HL=current RET ; and return GO$TABLE: ; ; [E2.05] ; ; Jump to a routine based on a table of pointers ; ; Entry: ; A = index into table ; HL = table base address ; ; Exit: ; Routine at (A*2)+HL is executed ; ; Modifies: ; B, HL ; LXI B,2 ; Compute offset to table of routines CALL ; chr back I$DONE: POP H ; and original "OK" pointer RET ; and return JUSTIFY: ; ; [E1.30] ; ; This routine will send a data stream to the console, with each line ; justified based on the SCREEN$WIDTH value. The stream must terminate ; with the CP/M end of string character ($) and may contain imbedded ; CR,LF pairs to separate paragraphs. ; ; NOTE: To insure proper operation, the LF character should only follow ; a CR character or another LF character, as the CR character is used to INDEX$TABLE ; . CALL GET$HL$PTR ; . PCHL ; Jump to proper routine INDEX$ACTIVE: ; ; [E2.10] ; ; Compute index into active table ; ; Entry: ; A = Table entry number (00h-0fh) ; ; Exit: ; HL = Address of table entry ; ; Modifies: ; PSW, DE, HL ; LXI B,8 ; Length of active device entry LXI H,ACTIVE$SDEV ; Table base address JMP INDEX$TABLE ; Return through INDEX$TABLE INDEX$TABLE: ; ; [E1.30] ; ; Computes offset to table given base address, entry length, and entry ; r@ ; flush the current line without justification. ; ; Two entry points are provided: ; JUSTIFY Justify output, flush right ; JUSTIFY$RAGGED Justify output, ragged right ; ; As of E1.30, the flush right routine was not installed, so either ; entry point will provide the same results. ; ; Entry: ; DE = pointer to line(s) to output ; ; Exit: ; The data is sent to the screen. ; ; Modifies: All registers ; MVI A,80H ; Set flush right mode JMP E$JUSTIFY ; Jump to routine entry JUSTIFY$RAGGED/equested. ; ; Entry: ; A = entry # ; BC = table entry length ; HL = base address ; ; Exit: ; HL = address to entry ; ; Modifies: ; A, BC, HL ; ORA A ; Set up flags for first check I$TBL$ADD: RZ ; If A=0, we're done DAD B ; Otherwise add length to base, DCR A ; . decrement counter, JMP I$TBL$ADD ; . and check again. IS$IT$OK: ; ; [E1.28] ; ; Check the character in A against the list of "OK" chrs pointed ; to by HL. The value 0FFH is ignored in the list of "OK" chrs : MVI A,00H ; Set ragged right mode E$JUSTIFY: STA J$MODE ; Save mode byte MVI A,'$' ; Mark start of buffer STA OUTBUF-1 ; . XCHG ; DE is usually print source J$NEXT$LINE: XRA A ; Clear character counter STA BLANK$LEN ; . MOV B,A ; . LXI D,OUTBUF ; Set up buffer pointer J$CHECK$CHR: MOV A,M ; Get character STAX D ; Save in output buffer CPI CR ; CR? CZ J$FLUSH$LINE ; . Yes, flush output line, CZ J$LITERAL ; . . output CR & bump ptr JZ J$NEXT$LINE ; . . and do ; and may be used as a place holder. ; ; Entry: ; A = character to check ; HL = pointer to list of "OK" characters ; ; Exit: ; A = original character if ok, 0ffh if not in list ; B = position of character in list ; ; Modifies: ; BC ; PUSH H ; Save original "OK" pointer MOV C,A ; Save chr to check against MVI B,0 ; Clear counter CPI ESC ; If chr is JZ I$CHR$OK ; . then automatically ok INR B ; . otherwise start counting at 1 I$CHK$NEXT: MOV A,M ; Get chr to check aanother. CPI LF ; LF? CZ J$LITERAL ; . Yes, output LF & bump ptr JZ J$CHECK$CHR ; . . and check next chr. CPI '$' ; End of string? CZ J$FLUSH$LINE ; . Yes, flush output line, RZ ; . . and return to caller CPI ' ' ; Blank? JNZ J$NOT$A$BLANK ; . No, don't save position SHLD BLANK$POS ; Save position for later XCHG ; and save corresponding position SHLD OUTBUF$BLANK ; . of the blank we just saved XCHG ; . in the output buffer MOV A,B ; . STA BLANK$LEN ; Save curre jnt length also J$NOT$A$BLANK: INR B ; Increment counter INX H ; . and pointer INX D ; . and output pointer LDA SCREEN$WIDTH ; Compare counter against screen width SUB B ; . JP J$CHECK$CHR ; And continue checking if not past end ; ; Screen width exceeded, send this line to the screen. ; LHLD OUTBUF$BLANK ; Get pos of last blank in output buf MVI M,'$' ; and plug with eos ('$') LDA J$MODE ; Justify right edge only if the CM J$ADD$BLANKS ; . right-justify flag is non-zero CALor the command line for input. ; ; Two entry points are provided: ; PROMPT standard entry, CRLF after chr from user ; PROMPT$NOLF special entry, No CRLF after chr from user ; ; When the command line is used for input, the following characters ; ar^e translated to new values or new functions: ; ; Character New character or new function ; -- --p ; (space) Ignored ; , (comma) key ; . (period) key ; @ (at-sign) repeat existing command lL J$SEND$BUFFER ; Output the line to the screen CALL DO$CRLF ; and a CR / LF LHLD BLANK$POS ; Get pointer to where we left off J$SKIP$BLANKS: INX H ; Bump pointer past blank(s) MOV A,M ; . CPI ' ' ; . JZ J$SKIP$BLANKS ; . JMP J$NEXT$LINE ; and check next segment J$FLUSH$LINE: ; Flush line when CR or EOS encountered PUSH PSW ; Save chr & zero flag MVI A,'$' ; Plug current position with EOS ($) STAX D ; . CALL J$SEND$BUFFER ; Send this line of data POP PSW ; Restore chr &ine ; _ (underscore) Prompt and get character from user ; ; Entry: ; DE = pointer to prompt string ; HL = pointer to list of valid chars (terminated with 00H) ; ; Exit: ; A = char from the user ; B = position of this character (0, 1, 2, ... n) ; ; Z = char was the escape key ; NZ = char was not the escape key ; ; Modifies: ; A, BC ; MVI A,01H ; Set CRLF after chr JMP E$PROMPT ; Jump to entry point PROMPT$NOLF: MVI A,00H ; Set no CRLF after chr E$PROMPT: STA PROMPT$MODE ; Save zero flag RET ; and return J$LITERAL: ; Send the chr in A PUSH PSW ; Save zero flag CALL CON$CHR ; Console chr out through CP/M INX H ; Bump chr pointer POP PSW ; Restore zero flag RET J$ADD$BLANKS: RET ; At a later time, this routine will justify ; the right margin by inserting extra blanks ; in the output line. J$SEND$BUFFER: MOV A,B ; If line to output is of zero length, ORA A ; . then don't output the line. RZ ; . LXI D,OUTBUF ; Get address of out prompt mode flag RE$PROMPT: LDA CMD$LINE$CHRS ; Are there any characters left from ORA A ; . the command line? JZ P$DISP ; No -- display & get chr from bios PUSH H ; Yes, save oklist pointer LHLD CMD$LINE$PTR ; and get chr from command line DCR A ; . Reduce count of chrs by one STA CMD$LINE$CHRS ; . . MOV A,M ; . Get command line character INX H ; . Increment pointer SHLD CMD$LINE$PTR ; . . POP H ; . Restore oklist pointer CPI '@' ; Repeat existing cmd line? JNZ P$`put buffer CALL CON$MSG ; and call our print message routine RET ; return J$MODE DB 0 ; Current right justify mode BLANK$POS DW 0 ; Last blank on this line OUTBUF$BLANK DW 0 ; Last blank in the output buffer BLANK$LEN DB 0 ; Length of line to the blank ; NOTE: OUTBUF is defined to be after the stack and before the heap. ; end of justify$output data area MOVE$BLOCK: ; ; [DC.20] ; ; Move a block of memory (up to 256 bytes) ; ; Entry: ; HL = source ; DE = destination ; B = NOT$REPEAT ; . (check other chrs if not) PUSH H ; . Save oklist pointer LXI H,INBUF ; . Set command line pointer back INX H ; . . to the beginning SHLD CMD$LINE$PTR ; . . POP H ; . Restore oklist pointer MVI A,07FH ; . Set the count of chars to 127 STA CMD$LINE$CHRS ; . . (the most it could be) JMP RE$PROMPT ; . and get the next character P$NOT$REPEAT: CPI ' ' ; Ignore spaces JZ RE$PROMPT ; . CPI ',' ; Change ',' to CR JNZ P$NOT$COMMA ; . MVI A,CR ; . P$NOT$COM>count ; Exit: ; data moved ; ; Modifies: ; none ; PUSH PSW ; Save registers PUSH B ; . PUSH D ; . PUSH H ; . M$NEXT$CHR: MOV A,M ; Get next byte, STAX D ; Save in destination. INX H ; Increment pointer to source. INX D ; Increment pointer to dest. DCR B ; Decrement counter. JNZ M$NEXT$CHR ; Loop back if we're not done. POP H ; Restore registers POP D ; . POP B ; . POP PSW ; . RET ; No more to do -- return. PROMPT: ; ; [E2.19] ; ; Prompt the user MA: CPI '.' ; Change '.' to ESC JNZ P$NOT$DOT ; . MVI A,ESC ; . P$NOT$DOT: CPI '_' ; Underline means prompt & get chr JZ P$DISP ; . from bios anyway (user input) CALL TO$UPPER ; Convert the chr to upper case CALL IS$IT$OK ; Check the chr against the ok list RP ; If ok, return XRA A ; Otherwise, cancel the cmd line STA CMD$LINE$CHRS ; . buffer and fall through to p$disp P$DISP: PUSH H ; Save pointer to ok-chrs CALL JUSTIFY ; and call justify routine POP H ; . P$TRY$AGA IN: CALL CONIN$NE$XC ; Console input, no echo, except ^C CALL TO$UPPER ; Convert the chr to upper case CALL IS$IT$OK ; If the character is not "OK" JM P$TRY$AGAIN ; . get another CNZ CON$CHR ; . otherwise display it PUSH PSW ; Check mode flag in case we need LDA PROMPT$MODE ; . to send a CR+LF after the ANI 01H ; . user's input CNZ DO$CRLF ; . POP PSW ; . RET ; and return PROMPT$MODE: DB 0 ; Prompt mode flag RET$TO$CONT: ; ; [E2.19] ; ; Prompts and waits for the RE: ; HL = source ; DE = destination ; B = count ; Exit: ; Z = two strings equal ; M = source < dest ; P = source >= dest ; ; Modifies: all ; PUSH D PUSH H NEXT$COMPARE: MOV C,M INX H LDAX D INX D CMP C JNZ NOT$EQUAL DCR B JNZ NEXT$COMPARE NOT$EQUAL: POP H POP D RET STR$SWAP: ; Swap two strings ; ; [E1.18] ; ; Entry: ; HL = source ; DE = destination ; B = count ; Exit: ; data moved ; ; Modifies: all ; MOV C,M LDAX D MOV M,A MOV A,C STTURN key to be pressed. ; ; Entry: ; none ; ; Exit: ; Display message and wait for a RETURN key. ; ; Modifies: ; all ; LXI D,RTC$MSG ; Press RETURN to continue ... CALL CENTER$OUTPUT ; . LXI D,NO$MSG ; . LXI H,RTC$OKC ; . CALL PROMPT ; . [ CR ] RET RTC$MSG: DB 'Press the RETURN key to continue ...' NO$MSG: DB '$' RTC$OKC: DB CR,0 ; end of RET$TO$CONT routine SCSI$TO$BIN: ; ; [DC.27] ; ; Converts SCSI address to binary 0-7 ; ; Entry: ; A = SCSI address to convert AX D INX H INX D DCR B JNZ STR$SWAP RET TO$UPPER: ; ; [E1.08] ; ; Convert the character in A to upper case. ; ; Entry: ; A = character to convert ; ; Exit: ; A = upper case character (if alpha) ; ; Modifies: ; A ; CPI 'z'+1 ; Convert to upper case JP UPPER$ALREADY ; . CPI 'a' ; . JM UPPER$ALREADY ; . ANI 5FH ; . UPPER$ALREADY: RET ; and return WAIT: ; Wait A ms ; ; Entry: ; milliseconds in A ; ; Exit: ; time waited ; ; Modifies: A ; PUSH PSW C ; ; Exit: ; A = converted address (0-7) [0FFH = error] ; ; Modifies: B ; MVI B,0FFH ; Set up B register for possible error ORA A ; If A=0, error JZ SCSI$CONVERTED ; . SCSI$NEXT$BIT: INR B ; Increment count RRC ; Shift address right 1 bit JNC SCSI$NEXT$BIT ; Bit shifted to cary means we're done SCSI$CONVERTED: MOV A,B ; Move converted addr to A RET SORT$ACTIVE: ; ; [E2.21] ; ; Sort active device table entries ; ; Entry: ; none ; ; Exit: ; Active device table iP MVI A,221 WAIT$2: DCR A JNZ WAIT$2 POP PSW DCR A JNZ WAIT RET * 2* * * * Data area . . . * * * * * ; ; All data after this point is after the end of the program ; ; Replicated BIOS to make direct calls easier . . . LB$BIOS$TBL: LB$WBOOT DS 3 ; Warm boot LB$CONST DS 3 ; Console status LB$CONIN DS 3 ; Console input LB$CONOUT DS 3 ; Console output LB$Ls sorted. ; ; Modifies: ; All ; LDA TOTAL$ACTIVE ; Get # of items to sort CPI 02 ; Less than two items? RM ; . yes -- no sort necessary S$NEXT$BLOCK: ; . STA SORT$MAX ; Save # to sort LXI B,0001H ; Setup initial compare pointers S$NEXT$ELEM: PUSH B ; Save compare pointers MOV A,C ; Convert pointers to address CALL INDEX$ACTIVE ; . in DE and HL PUSH H ; . MOV A,B ; . CALL INDEX$ACTIVE ; . POP D ; . MVI B,8 ; Compare length = 8 chrs CALL STR$COMP ; Compare strinOISTOUT DS 3 ; List output LB$PUNCH DS 3 ; Punch output LB$READER DS 3 ; Reader input LB$HOMDSK DS 3 ; Home disk (move to track 00) LB$SELDSK DS 3 ; Select disk drive LB$SETTRK DS 3 ; Select track number LB$SETSEC DS 3 ; Select sector number LB$SETDMA DS 3 ; Set DMA address LB$DSKREAD DS 3 ; Disk read LB$DSKWRITE DS 3 ; Disk write LB$LISTST DS 3 ; List status LB$SECTRN DS 3 ; Sector translate routine ; AMPRO-specific BIOS calls LB$GETNXT DS 3 ; Get bios ver & next tbl address LB$GETEDSK DS 3 ; $g in [DE] to [HL] MVI B,8 ; Swap length = 8 chrs CM STR$SWAP ; Swap if first is less than second POP B ; Get pointers back INR B ; Point to next item INR C ; LDA SORT$MAX ; Compare with max CMP C ; . JNZ S$NEXT$ELEM ; Not done with this pass ... DCR A ; Make sort limit one smaller CPI 03H ; Done if only 2 elements JP S$NEXT$BLOCK ; Not done if > 2 elements RET SORTMAX: DW 0 ; Sort max range (0-255 elements) STR$COMP: ; ; [E1.18] ; ; Compare two strings ; ; EntryQGet pointer to E-disk storage LB$IOINIT DS 3 ; Set new I/O parameters LB$SCSIDRV DS 3 ; SCSI direct driver LB$LEN EQU $-LB$BIOS$TBL ; Length of bios table (20 entries) LB$XTBL: ; 'Extra' table definitions ... LB$SWAP$DRV DS 3 ; Swap two logical drives LB$GET$WDP DS 3 ; Set/get win drive parameters LB$PHYTAB DS 3 ; Set/get phytab access LB$GET$LDTE DS 3 ; Get logical device table entry LB$RESERVED DS 3 ; Reserved entry LB$XLEN EQU $-LB$XTBL ; Length of extra table (5 entries) LB$VERS DS 1 ; Г Bios version number ; ; Stack, I/O buffers, HEAP ; OLDSP: DS 2 ; old stack pointer DS 63 ; STACK: DS 1 ; 31-level stack INBUF: DS 128 ; Command line input buffer INBUFL: EQU $-INBUF ; Input buffer length OBPLUG: DS 1 ; Start of outbuf ('$') OUTBUF: DS PWIDTH ; Output buffer OBUFL: EQU PWIDTH ; Output buffer length HEAP: EQU $ ; Next available area for data END ;--* VER EQU 10 ; version 1.0 CR EQU 13 LF EQU 10 LDIR EQU 0B0EDH ; z80 ldir ORG 100H JMP BEGIN ; jump over logo HELP: CALL PRINT DB CR,LF,LF DB 'TIME ' DB 'Version ',VER/10+'0','.',VER MOD 10+'0',CR,LF DB 'AMPRO Computers Inc.' DB CR,LF,'To change the time, enter change ' DB 'on the command line as follows:',cr,lf,lf DB 'du>TIME hh:mm:ss',cr,lf DB 0 JMP EXIT BEGIN: DW 73EDH,OLDSTK ; save old stack pointer LXI SP,LOCSTK ; set new stack ; LXI D,WBOOT  ; build bios entry table LHLD 1 ; get bios start LXI B,51 ; bytes to move DW LDIR ; move it ; CALL GETTBL ; get address of next jmp tbl CPI 36 ; must be bios ver 3.6 or higher JC BADVER ; give message and exit LXI D,NXTTBL ; 'hl' has bios nxttbl address LXI B,15 ; DW LDIR ; move the table LXI H,0 ; make sure that clock is enabled CALL TOD ; get clock base address MOV A,L ; see if address of tick was returned ORA H JZ NOCLK ; exit clock not enabled ; 'hl' has addCres of clock LXI D,SEC ; move time LXI B,6 DW LDIR ; save time ; Everthing needed has been moved into program area now. ; parse command tail to see if time was entered on command line. ; LXI H,80H ; point to command tail MOV A,M ; get character count ANA A ; if zero nothing on cmd line STA UPDATE ; save possible entry on cmd line JZ SHTIME ; skip PUSH H CALL VALID ; see if numeric ascii POP H LOOP: INX H ; point to first entry MOV A,M CPI ' ' ; should be no leadin*g spaces JZ LOOP ; exit CALL EVAL10 CPI 24 ; see if more the 24:00 hrs JNC NVALMS STA HOUR ; store hour INX H CALL EVAL10 CPI 60 ; see if more than 59 min JNC NVALMS ; STA MIN ; store min INX H CALL EVAL10 CPI 60 ; see if more than 59 sec JNC NVALMS STA SEC ; ; convert the binary counts to ascii characters and dispaly ; ; make seconds SHTIME: LDA SEC ; get seconds count CALL BINASC ; convert to ascii DW 43EDH,SC ; ld(sc),bc - save seconds ; make minute9M **>* * AMPRO Computers Inc. * * Time.asm * * ** * Adapted from TIME.MAC * *  by Don Delwood, * *  with mods by Roger Warren *  **1* ; ; Version date by History ; ------- -- ------ --B ; 1.0 4 mar 86 fsw Version 1.0 for use with bios 3.6 ; *---s LDA MIN ; get minutes count CALL BINASC ; convert to ascii DW 43EDH,MN ; ld(mn),bc - save minutes ; make hours LDA HOUR ; get hours CALL BINASC ; convert to ascii DW 43EDH,HR ; ld(hr),bc - save hours CALL PRINT ; print message CURTIM: DB 'Current time is ' HR: DB ' :' MN: DB ' :' SC: DB ' ' DB 0 ; ; if time was not changed from the command line, do not place ; the time prameters back into the bios clock area. ; LDA UPDATE ANA A ; if zero time was only disp f layed JZ EXIT ; ; move the new time prameters to bios clock area ; CALL TOD ; get address of time counters XCHG ; bios time counter addresss to 'de' LXI H,SEC ; LXI B,3 ; time only, not date DW LDIR ; move it to bios memory JMP EXIT ; ; Test the command for valid time entry. Scan the command tail ; for along its legnth for the pattern hh:mm:ss. test for ; valid numeric characters. it has already been determined that ; somthing was entered on the command line ; VALID: LXI H,80it, check range '0'-'9' CPI '0' JC EVLOUT ; less than ascii 0 CPI '9'+1 JNC EVLOUT ; more than ascii 9 SUI '0' MUL10: PUSH H ; multiply DE by 10 MOV H,D MOV L,E DAD H ; *2 DAD H ; *4 DAD D ; *5 DAD H ; *10 MOV E,A ; add in latest digit MVI D,0 DAD D XCHG POP H INX H JMP E10L EVLOUT: MOV A,E POP B RET ; local stack area ; DS 32 ; 16 level stack LOCSTK: DW EXIT ; exit point on top of stack OLDSTK: DS 2 ; save for old stack UPDATE DS 1 ; flag 5H ; character count MOV B,M ; get number of characters typed INX H DCR B JZ NVALMS ; exit only spaces or one char on line MOV A,M ; get first char CPI ' ' JZ VALID+4 ; filter the spaces VAL1: MOV A,M INX H ; point to next char ANA A ; 00h is terminator or zero count RZ CPI '/' JZ HELP ; show help CPI '?' JZ HELP ; show help CPI ':' JZ VAL1 ; delimeter ok CPI '0' JC NVALMS ; less than ascii 0 CPI '9'+1 JNC NVALMS ; more than ascii 9 JMP VAL1 NVALMfor command entry ; ; bios entry table ; WBOOT: DS 3 ; Warm start CONST: DS 3 ; Console status CONIN: DS 3 ; Console character in CONOUT: DS 3 ; Console character out LIST: DS 3 ; List character out PUNCH: DS 3 ; Punch character out READER: DS 3 ; Reader character in HOME: DS 3 ; Seek to home position SELDSK: DS 3 ; Select disk SETTRK: DS 3 ; Set track number SETSEC: DS 3 ; Set sector number SETDMA: DS 3 ; Set DMA address READ: DS 3 ; Read disk WRITE: DS 3 ; Write disk LISTSTQS: CALL PRINT DB 'Invalid time',cr,lf,0 JMP EXIT ; ; time of day TOD jmp was not in bios ; NOCLK: CALL PRINT DB 'Clock not installed',cr,lf,0 JMP EXIT ; ; wrong version bios ; BADVER: CALL PRINT DB 'Requires Bios 3.6 or higher.',cr,lf,0 ; fall through to exit ; ; Normal program exit. Restores system stack and returns ; EXIT: DW 7BEDH,OLDSTK ; recover old stack pointer RET ; ; Print string of characters terminated with zero '0'. ; PRINT: POP H MOV A,M ; get byte : DS 3 ; Return list status SECTRAN:DS 3 ; Sector translate GETTBL: DS 3 ; Point to more jumps, returns bioss ; version in 'a'. ; NXTTBL: SWAP: DS 3 ; jmp swap HD$INF: DS 3 ; get hd table info PHTBAC: DS 3 ; get/set phytab acces PAGET: DS 3 ; get phytab entry address TOD: DS 3 ; get base address of clock tick SEC: DS 1 MIN: DS 1 HOUR: DS 1 DAY: DS 2 YEAR: DS 1 END 2̓ ANA A JZ PRNEND PUSH H ; MOV C,A CALL CONOUT ; call bios routine POP H INX H ; next byte JMP PRINT+1 PRNEND: XTHL ; hl has return RET ;**z* ; convert binary to ascii ; in: a - binary value ; out: bc - ascii character (low high) (mod. after Rich Conn) ;**g* BINASC: MVI C,0 ; init count MVI B,10 BIN1: SUB B JC BINEXT INR C JMP BIN1 binext: AD@`D B ; A = ones digit C = tens digit ADI '0' MOV B,A MOV A,C ADI '0' MOV C,A RET   ;*** ; eval10 - convert ascii string to decimal value ; in: hl - points to beginning of string ; out: a - e ; de - value ; hl - points to delimiter (error character) ; (mod. after Rich Conn) ;**M* EVAL10: PUSH B LXI D,0 ; init de to zero E10L: MOV A,M ; next dig xѡ * #* * * * *  ,* Written for AMPRO by Paul Bartholomew \* * * * COPYRIGHT (C) 1985,86 AMPRO COMPUTERS, INC. * * * * * ; Assemble with ASM.COM or equivalent. There is no Z80 code. ;REVISION LOG: ; ; Vers 1.2 fsw Corrected BPB's to work with DOS 3.2 ; ; Vers 1.1 rbl Changed diskette sensing so more reliable ; QU RSEC+1 ; read from data register CONT EQU 0 ; system control port ROMOFF EQU 40H ; turn rom off SID0 EQU 0EFH ; mask side bit off SID1 EQU 10H ; side bit in control register SDEN EQU 20H ; single density bit in control register TRY EQU 3 ; tries TRYHARD EQU 10 ; we try harder MSEC EQU 167 ; constant for 1 ms delay CR EQU 13 ; carriage return LF EQU 10 ; line feed ESC EQU 27 ; escape key UPCASE EQU 5FH ; upper case mask bdos equ 5 ORG 100H ;embed the copyright n0f with microfloppies. ; Changed format selection menu text. ; ; 08/08/85 Release version 1.0. ; "Supports the following formats: ; * IBM PC-DOS version 1.x SSDD (8 Sector) ; * IBM PC-DOS version 1.x DSDD (8 Sector) ; * IBM PC-DOS version 2.x SSDD (9 Sector) ; p IBM PC-DOS version 2.x DSDD (9 Sector) ; ;PCFMT allows formatting IBM PC-DOS disk formats. It is based on otice ; START: JMP BEGIN ; leave room for copyright DB ' DOSFMT Copyright (C) 1985,86 AMPRO Computers, Inc. ' DB 13,10 DB ' Written for AMPRO by Paul Bartholomew ' DB 13,10,26 ;set up the stack and print signon message ; BEGIN: LXI SP,STACK ; set local stack CALL CLRSC ; clear the screen CALL ILPRT ; print following text DB CR,LF,' IBM PC-DOS Diskette Format/Verify Utility' DB CR,LF,' Copyright (c) 1985,86 AMPRO Computers, Inc.' DB CR,LF,'  Version 1.2$'  ;the code developed for AMPRODSK and uses most of the algorithms ;in that program. The major differences are: ; ; 1. Modified GEN routine to be a CALLable subroutine. ; ; 2. Modified GEN routine to allow writes to SIDE-1. ; ; 3.3 "TYPE" byte removed, because ALL formats have a ; 3write after the FORMAT. "TYPELETTER" is used to ; see which write routine is to be used. ; ; wd1770 equates REST EQU 0 ; slow restore RDSEC EQU 88H ; read sector command WRSEC _call get$bios$vers mvi a,16 jnz new$sys lhld 1 mvi L,5ch mov a,m jmp plugem new$sys: push psw mvi a,0 lxi h,jplug1 mov m,a inx h mov m,a inx h mov m,a pop psw plugem: adi '@' sta plug1 inr a sta cplug1 jmp doit DISP$FDEV: ; ; [E2.15] ; ; lda lb$vers cpi 20 rm LXI D,D$FDEV$HDR ; Print header mvi c,9 call bdos mvi a,0 ; starting unit # D$NEXT$FDEV: sta unit call lb$get$ldte ; Get address of unit id MOV A,M ; Get unit id CPI 01 ;LEQU 0A8H ; write sector command WRTRK EQU 0F8H ; write track command STEPI EQU 58H ; step in command RDID EQU 0C8H ; read address command MOT EQU 80H ; motor on status WPR EQU 40H ; write protected status SPU EQU 20H ; disk at speed status (type i) TYP EQU 20H ; record type status (types ii and iii) RNF EQU 10H ; record not found status CRC EQU 8 ; crc error status TK0 EQU 4 ; track zero status (type i) LDT EQU 4 ; lost data status (types ii and iii) IDX EQU 2 ; index status (type iH Floppy? JNZ D$BUMP$PTR ; No -- go to the next device inx h ; Get drive # mov a,m ; . ani 03h ; mask out excess bits MOV l,a ; update floppy device number mvi h,0 ; . dad h ; x2 xchg LXI H,FNAMES ; . dad d ; x2 dad d ; x4 dad d ; x6 lxi d,d$fname ; lxi b,6 ; db 0edh,0b0h ; . (LDIR) lda unit ; adi 'A' ; sta d$current ; LXI D,D$FDEV$LIN ; and output the line mvi c,9 call bdos D$BUMP$PTR: lda unit inr a ; Bump to next unit cpi 16 ; Done yet? j) DRQ EQU 2 ; data request status (types ii and iii) BSY EQU 1 ; controller busy status ERRII EQU WPR+RNF+CRC+LDT ; type ii error status mask ERRIII EQU WPR+LDT ; type iii error status mask CMND EQU 0C0H ; fdc command register WTRK EQU CMND+1 ; write to track register WSEC EQU WTRK+1 ; write to sector register WDAT EQU WSEC+1 ; write to data register STAT EQU WDAT+1 ; fdc status register RTRK EQU STAT+1 ; read from track register RSEC EQU RTRK+1 ; read from sector register RDAT Em D$NEXT$FDEV ; No -- go do the next one RET unit: db 0 D$FDEV$HDR: DB CR,LF,LF,'- FLOPPY DISK ASSIGNMENTS -',CR,LF DB ' CP/M drive ' DB 'Floppy disk',CR,LF DB '  --]',CR,LF,'$' D$FDEV$LIN: DB ' ' D$CURRENT: DB 'x ' D$EDISK: DB ' ' D$EBLANK: DB '  ' D$FNAME: DB ' ' DB CR,LF,'$' D$FDEV$HLEN EQU $-D$FDEV$LIN ; Line length FNAMES: DB 'First ' DB 'Second' DB 'Third ' DB 'Fourth' ; end of DISPLAY$FDEV GET$BIOS$VERS: ; Ge t bios version -- Brings the current BIOS jump tables (starting ; at warm boot) to a local area for ease of utility access. If ; this BIOS is version 2.1 or greater, the secondary jump table ; is brought in as well. ; ; Entry: none ; Exit: Z = bios < 2.1 (old bios) ; NZ = bios 2.1+ (fixed disk bios) ; All registers are modified ; LHLD 1 ; Get start of bios jump table LXI D,LB$BIOS$TBL ; Move bios to local storage LXI B,LB$LEN ; . (length of bios area) DB 0edhnuble-Sided 9 Sector (360K)' DB CR,LF,LF,'Choose one or to Restart: $' ASKAGN: CALL CONIN ; get the answer CPI 3 ; ^c? JZ EXIT ; exit CPI ESC ; esc? JZ ASK1 ; return ; ANI UPCASE ; mask upper case sta typeletter CPI '1' ; 1? JZ DOS1SS ; DOS ver 1 SSDD CPI '2' ; 2? JZ DOS1DS ; DOS ver 1 DSDD CPI '3' ; 3? JZ DOS2SS ; DOS ver 2 SSDD CPI '4' ; 4? JZ DOS2DS ; DOS ver 2 DSDD JMP ASKAGN ; anything else ask again typeletter: db 'a' ASK2E: STC ; set er,0b0h ; . (move routine) MVI A,0 ; Test CP/M version CALL LB$GETNXT ; Get next jump table STA LB$VERS ; Save bios version INX H ; See if HL is 0FFFFh MOV A,H ; . ORA L ; . RZ ; If so, then old version DCX H ; Fix HL as it has the table addr LXI D,LB$XTBL ; Move extra table to local storage LXI B,LB$XLEN ; . (length of extra table) db 0edh,0b0h ; . (move routine) MVI A,0FFH ; Set NZ to indicate bios ORA A ; ... version 2.1+ RET ; ... and return. doit: ; main prror flag RET ;update TABLE routines begin here... ; DOS1SS: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,80 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format STA TWOSID ; single sided format LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,S1SKW ; point to skew table JMP MOVSKW ; move it to skew S1SKW: DB 1,2,3,4,5,6,7,8,255 DOS1DS: MVI A,2 ogram begins here ; ASK1: CALL ILPRT ; print following string DB CR,LF,LF,'FORMAT or VERIFY? (F or V)' DB CR,LF,'Press or <^C> to exit.$' ASK1A: CALL CONIN ; get response CPI ESC JZ EXIT ; exit to operation system CPI 3 JZ EXIT ; ctl c ANI UPCASE ; force upper case CPI 'F' JZ SETF ; if format CPI 'V' JZ SETV ; if verify JMP ASK1A ; otherwise, do this again ; set function code and do it ; SETF: MVI A,1 STA FUNC JMP FORMAT SETV: MVI A,2 STA FUNC JMP V; 512 bytes/sectors STA SIZE ; store it MVI A,80 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format INR A STA TWOSID ; double sided format LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,D1SKW ; point to skew table JMP MOVSKW ; move it to skew D1SKW: DB 1,2,3,4,5,6,7,8,255 DOS2SS: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,80 ; gap3 size STAERIFY ;setup the format routine ; FORMAT: CALL CLRSC CALL ILPRT DB 8,32,CR,LF,LF ; overwrite response and make new line DB 'FORMAT prepares a fresh diskette for data or ' DB 'program storage.$' CALL ASK5 ; ask destination JC ASK1 ; restart if bad selection JMP ASK2 FORM0: CALL ASK6 ; give warning JC ASK1 CALL EXEC ; do it JMP ASK1 ; restart at end of format ;setup the verify routine ; VERIFY: CALL CLRSC CALL ILPRT DB 8,32,CR,LF DB CR,LF,'VERIFY checks the reliaba GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format STA TWOSID ; single sided format LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,S2SKW ; point to skew table JMP MOVSKW ; move it to skew S2SKW: DB 1,2,3,4,5,6,7,8,9,255 DOS2DS: MVI A,2 ; 512 bytes/sectors STA SIZE ; store it MVI A,80 ; gap3 size STA GAP3 ; MVI A,39 ; # of tracks STA MAXTRK ; XRA A ; zero out accum $ility of data on a disk.$' CALL ASK5 ; ask for destination disk JC ASK1 JMP ASK2 VERF0: CALL ASK3 ; ask to load disk JC ASK1 CALL EXEC ; do it JMP ASK1 ;get selection and update TABLE ; ASK2: CALL ILPRT ; print following string DB CR,LF,LF DB 'Formats Available: (48 tpi Drive Required)' DB CR,LF,LF DB ' 1 - Single-Sided 8 Sector (160K)' DB CR,LF DB ' 2 - Double-Sided 8 Sector (320K)' DB CR,LF DB ' 3 - Single-Sided 9 Sector (180K)' DB CR,LF DB ' 4 - Do STA SBIAS ; no bias STA TPI96 ; 0=48tpi, 1=96tpi format INR A STA TWOSID ; double sided format LXI D,SEC512 ; point to data CALL MOVDAT ; move to dat0 LXI D,D2SKW ; point to skew table JMP MOVSKW ; move it to skew D2SKW: DB 1,2,3,4,5,6,7,8,9,255 ;move the new data to TABLE ; MOVDAT: MVI B,8 ; # of bytes to move LXI H,DAT0 ; point to data location MOVDT: LDAX D ; move byte to accum MOV M,A ; store it INX D ; roll up reg de INX H ; roll up reg hl DCR B ; count  Fdown 1 JNZ MOVDT ; done? RET MOVSKW: LXI H,SKEW ; point to skew MOVSK: LDAX D ; move into accum MOV M,A ; store it CPI 0FFH ; done? JZ RETURN ; INX D ; roll up de INX H ; roll up hl JMP MOVSK ; again RETURN: LDA FUNC ; get function # CPI 1 ; was it a format? JZ FORM0 ; JMP VERF0 ; if not format must be verify SEC512: DB 128,0E5H,128,0E5H,128,0E5H,128,0E5H ;tell them to put the disk in ; ASK3: lda typeletter call conout CALL ILPRT ; print the following j**8* ; ; Write data for IBM PC-DOS version 1.x SSDD ; ;&*** WRT1S: MVI A,1 ;We'll be writing 7 sectors LXI H,SKEW1 MVI B,7 WRT1SA: MOV M,A INX H INR A DCR B JNZ WRT1SA MVI M,255 ; ;Boot record ; LXI D,B1DAT ;Move 512 bytes for boot record LXI H,TKBUF MVI B,128 CALL MOVDT MVI B,Y128 CALL MOVDT MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT ; ;FAT 1 ; LXI D,  string DB CR,LF,LF,'Place disk in Drive ' ASK30s: db 'a' DB CR,LF,LF,'Press to VERIFY, ' DB ' to quit. $' JMP ASK6E ASK5: call disp$fdev CALL ILPRT DB CR,LF,LF,'Destination drive? (A - ' plug1: db 'D) $' ASK5E: CALL CONIN ; get the answer CPI ESC JZ EXIT CPI 3 JZ EXIT ANI UPCASE ; force upper case CPI 'A' ; first valid drive JC ASK5E cplug1: equ $+1 CPI 'E' ; first invalid drive JNC ASK5E sta ask60d sta ask30s push psw call conout pop psw F1SDAT ;Move 3 FAT bytes (FAT 1) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT1 CALL LOAD MVI C,3 ;3 more 128-byte sectors F1S1: PUSH B MVI E,0 MVI D,128 CALL LOAD ;128-bytes of FAT1 POP B DCR C JNZ F1S1 ; ;FAT 2 ; LXI D,F1SDAT ;Move 3 FAT bytes (FAT 2) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT2 CALL LOAD MVI C,3 ;3 more 128-byte sectors F2S1: PUSH B MVI E,0 MVI D,128 CALL LOAD ;128-bytes of FA A sui 'A' jplug1: jmp ask50s call lb$get$ldte mov a,m cpi 1 jnz ask5 inx h mov a,m ani 3 ask50s: STA DDRIV CALL SETSEL ; disk select bits ORA A RET ASK6: lda typeletter call conout CALL ILPRT ; print the following string DB CR,LF,LF,'Place destination disk on drive ' ask60d DB 'a' DB CR,LF,LF,'Press to write, ' DB ' to quit. $' ASK6E: CALL CONIN ; get answer CPI CR RZ CPI ESC JZ EXIT JMP ASK6E ;execute it! ; EXEC: CALL ILPRT DB CR, JT2 POP B DCR C JNZ F2S1 ; ;Directory ; MVI C,16*4 ;16 128-byte sectors S1DIR: PUSH B MVI E,0E5H ;Use E5 as marker for erased file MVI D,1 CALL LOAD MVI E,0F6H MVI D,31 CALL LOAD POP B DCR C JNZ S1DIR XRA A STA TRASCK STA HEAD CALL GEN ;Write the info out to disk JMP VFY ;Go do verify ;&**8* ; ; Write data for IBM PC-DOS version 1.x DSDD ; ;** LF,LF,'$' LDA FUNC ; function 1=fmt, 2=vfy CPI 1 JZ FMT CPI 2 JZ VFY ; RET ;format routines... ; FMT: LDA DDRIV CALL SETSEL CALL SETUP XRA A STA TRACK STA HEAD NEXTRK: CALL KEY LXI H,FRMSG CALL PRINT CALL TMRPRT CAtLL MAKETRK MVI A,TRY STA TRIES NT3: CALL WRITRK JZ NT5 LXI H,TRIES DCR M JNZ NT3 CALL ILPRT DB CR,' o' DB CR,LF,'FORMAT failed.',CR,LF,'$' CALL REPORT RET NT5: LDA TWOSID ORA A LDA TRACK JZ NT0 L ^*** WRT1D: MVI A,1 ;We'll be writing 8 sectors LXI H,SKEW1 MVI B,8 WRT1DA: MOV M,A INX H INR A DCR B JNZ WRT1DA MVI M,255 ; ;Boot record ; LXI D,B1DAT ;Move 512 bytes for boot record LXI H,TKBUF MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT ; ;FAT 1 ; LXI D,F1DDAT ;Move 3 FAT bytes (FAT 1) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT1 CALL LOAD MVI C, }`DA HEAD ORA A LDA TRACK JZ NT1 NT0: LXI H,MAXTRK CMP M JNZ NT1 CALL ILPRT DB CR,' s' DB CR,LF,'FORMAT complete.',CR,LF,LF,'$' LDA TYPELETTER CPI '1' JZ WRT1S ;8 sector SS DD CPI '2'  ) JZ WRT1D ;8 sector DS DD CPI '3'  ) JZ WRT2S ;9 sector SS DD CPI '4'  M JZ WRT2D ;9 sector DS DD JMP VFY ; anything else begin verify ;** #3 ;3 more 128-byte sectors F1D1: PUSH B MVI E,0 MVI D,128 CALL LOAD ;128-bytes of FAT1 POP B DCR C JNZ F1D1 ; ;FAT 2 ; LXI D,F1DDAT ;Move 3 FAT bytes (FAT 2) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT2 CALL LOAD MVI C,3 ;3 more 128-byte sectors F2D1: PUSH B MVI E,0 MVI D,128 CALL LOAD ;128-bytes of FAT2 POP B DCR C JNZ F2D1 ; ;Directory (up to end of track) ; MVI C,20*4 ;20 128-byte sectors D1DIR1: PUSH B MVI E,0E  5H ;Use E5 as marker for erased file MVI D,1 CALL LOAD MVI E,0F6H MVI D,31 CALL LOAD POP B DCR C JNZ D1DIR1 XRA A STA TRACK STA HEAD CALL GEN ;Write the info out to disk ; ;Directory (Side 1 of Track 0) ; MVI A,1 ;We'll be writing 2 sectors LXI H,SKEW1 MVI B,2 WRT1DB: MOV M,A INX H INR A DCR B JNZ WRT1DB MVI M,255 LXI H,TKBUF ;Initialize pointer MVI C,8*4 ;8 128-byte sectors D1DIR2: PUSH B MVI E,0E5H ;Use E5 as marker for erased file MVI D,1 ;Move DS-specific data into boot data LXI D,B$DAT LXI B,B$LEN DB 0EDH,0B0H LXI D,B2DAT ;Move 512 bytes for boot record LXI H,TKBUF MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT ; ;FAT 1 ; LXI D,F2DDAT ;Move 3 FAT bytes (FAT 1) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT1 CALL LOAD MVI C,7 ;7 more 128-byte sectors F1D2: PUSH B MVI E,0 MVI D,128 CALL LOAD ;128-bytes of FAT1 POP B DCR jw CALL LOAD MVI E,0F6H MVI D,31 CALL LOAD POP B DCR C JNZ D1DIR2 XRA A STA TRACK INR A STA HEAD CALL GEN JMP VFY ;Go do verify ;&**8* ; ; Write data for IBM PC-DOS version 2.x SSDD ; ;&*** WRT2S: MVI A,1 ;We'll be writing 9 sectors LXI H,SKEW1 MVI B,9 WRT2SA: MOV M,A INX H INR A DCR B JNZ WRT2SA MVI M,255 ; ;B C JNZ F1D2 ; ;FAT 2 ; LXI D,F2DDAT ;Move 3 FAT bytes (FAT 2) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT2 CALL LOAD MVI C,7 ;7 more 128-byte sectors F2D2: PUSH B MVI E,0 MVI D,128 CALL LOAD ;128-bytes of FAT2 POP B DCR C JNZ F2D2 ; ;Directory (up to end of track) ; MVI C,16*4 ;16 128-byte sectors D2DIR1: PUSH B MVI E,0 ;Use 00 as marker for no more files MVI D,1 CALL LOAD MVI E,0F6H MVI D,31 CALL LOAD POP B DCR C Woot record ; LXI H,BPB$BPS$2S ;Move SS-specific data into boot data LXI D,B$DAT LXI B,B$LEN DB 0EDH,0B0H LXI D,B2DAT ;Move 512 bytes for boot record LXI H,TKBUF MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT MVI B,128 CALL MOVDT ; ;FAT 1 ; LXI D,F2SDAT ;Move 3 FAT bytes (FAT 1) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT1 CALL LOAD MVI C,7 ;7 more 128-byte sectors F1S2: PUSH B MVI E,0 MVI D,128 CALL LOAD  JNZ D2DIR1 XRA A STA TRACK STA HEAD CALL GEN ;Write the info out to disk ; ;Directory (Side 1 of Track 0) ; MVI A,1 ;We'll be writing 3 sectors LXI H,SKEW1 MVI B,3 WRT2DB: MOV M,A INX H INR A DCR B JNZ WRT2DB MVI M,255 LXI H,TKBUF ;Initialize pointer MVI C,12*4 ;12 128-byte sectors D2DIR2: PUSH B MVI E,0 ;Use 00 as marker for no more files MVI D,1 CALL LOAD MVI E,0F6H MVI D,31 CALL LOAD POP B DCR C JNZ D2DIR2 XRA A STA TRACK INR A STA ;128-bytes of FAT1 POP B DCR C JNZ F1S2 ; ;FAT 2 ; LXI D,F2SDAT ;Move 3 FAT bytes (FAT 2) MVI B,3 CALL MOVDT MVI E,0 MVI D,125 ;Rest of first 128-bytes of FAT2 CALL LOAD MVI C,7 ;7 more 128-byte sectors F2S2: PUSH B MVI E,0 MVI D,128 CALL LOAD ;128-bytes of FAT2 POP B DCR C JNZ F2S2 ; ;Directory ; MVI C,16*4 ;16 128-byte sectors S2DIR: PUSH B MVI E,0 ;Use 00 as marker for no more files MVI D,1 CALL LOAD MVI E,0F6H MVI D,31 CALL LOAD PO R HEAD CALL GEN JMP VFY ;Go do verify F1SDAT: DB 0FEH,0FFH,0FFH ;FAT marker DOS 1.x SSDD F1DDAT: DB 0FFH,0FFH,0FFH ;FAT marker DOS 1.x DSDD F2SDAT: DB 0FCH,0FFH,0FFH ;FAT marker DOS 2.x SSDD F2DDAT: DB 0FDH,0FFH,0FFH ;FAT marker DOS 2.x DSDD ; ;Boot record for DOS 1.x (SS and DS) ; B1DAT: DB 0EBH,027H,090H,003H,001H,014H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000 w|P B DCR C JNZ S2DIR XRA A STA TRACK STA HEAD CALL GEN ;Write the info out to disk JMP VFY ;Go do verify ;&**8* ; ; Write data for IBM PC-DOS version 2.x DSDD ; ;&*** WRT2D: MVI A,1 ;We'll be writing 9 sectors LXI H,SKEW1 MVI B,9 WRT2DA: MOV M,A INX H INR A DCR B JNZ WRT2DA MVI M,255 ; ;Boot record ; LXI H,BPB$BPS$2D H,000H,000H,000H,000H,0CDH DB 019H,0FAH,08CH,0C8H,08EH,0D8H,033H,0D2H DB 08EH,0D2H,0BCH,000H,07CH,0FBH,0B8H,060H DB 000H,08EH,0D8H,08EH,0C0H,033H,0D2H,08BH DB 0C2H,0CDH,013H,072H,069H,0E8H,085H,000H DB 072H,0DDH,02EH,083H,03EH,003H,07CH,008H DB 074H,006H,02EH,0C6H,006H,064H,07DH,002H DB 0BBH,000H,000H,02EH,08BH,00EH,003H,07CH DB 051H,0B0H,009H,02AH,0C1H,0B4H,000H,08BH DB 0F0H,056H,033H,0D2H,033H,0C0H,08AH,0C5H DB 02EH,0F6H,036H,064H,07DH,08AH,0E8H,08AH DB 0F4H,08BH,0C6H,0B4H,002H,0CDH, !!013H,072H DB 02DH,05EH,059H,02EH,029H,036H,005H,07CH DB 074H,01FH,08BH,0C6H,02EH,0F7H,026H,065H DB 07DH,003H,0D8H,0FEH,0C5H,0B1H,001H,051H DB 0BEH,008H,000H,02EH,03BH,036H,005H,07CH DB 07CH,005H,05EH,08BH,036H,005H,07CH,0EBH DB 0C0H,0EAH,000H,000H,060H,000H,0BEH,067H DB 07DH,0E8H,002H,000H,0EBH,0FEH,032H,0FFH DB 02EH,0ACH,024H,07FH,074H,00BH,056H,0B4H DB 00EH,0BBH,007H,000H,0CDH,010H,05EH,0EBH DB 0EFH,0C3H,0E9H,033H,0FFH,0BBH,000H,000H DB 0B9H,004H,000H,0B8H,001H,002H,0CDH,013H DB 01!EH,02AH,006H,015H DB 07CH,0FEH,0C0H,032H,0E4H,050H,0B4H,002H DB 0E8H,0C1H,000H,058H,072H,038H,02EH,028H DB 006H,020H,07CH,076H,00EH,02EH,001H,006H DB 013H,07CH,02EH,0F7H,026H,00BH,07CH,003H DB 0D8H,0EBH,0CEH,00EH,01FH,0CDH,011H,0D0H DB 0C0H,0D0H,0C0H,025H,003H,000H,075H,001H DB 040H,040H,08BH,0C8H,0F6H,006H,01EH,07CH DB 080H,075H,002H,033H,0C0H,08BH,01EH,07EH DB 07DH,0EAH,000H,000H,070H,000H,0BEH,0C9H DB 07DH,0E8H,002H,000H,0EBH,0FEH,02EH,0ACH DB 024H,07FH,074H,04DH,0B4H,00EH,0BBH,007H!EH,072H,033H,08CH,0C8H,08EH,0D8H,0BFH DB 000H,000H,0B9H,00BH,000H,026H,080H,00DH DB 020H,026H,080H,04DH,020H,020H,047H,0E2H DB 0F4H,0BFH,000H,000H,0BEH,08BH,07DH,0B9H DB 00BH,000H,0FCH,0F3H,0A6H,075H,00FH,0BFH DB 020H,000H,0BEH,097H,07DH,0B9H,00BH,000H DB 0F3H,0A6H,075H,002H,01FH,0C3H,0BEH,01BH DB 07DH,0E8H,0A2H,0FFH,0B4H,000H,0CDH,016H DB 01FH,0F9H,0C3H DB 0DH,0AH DB 'Non-System disk or disk error' DB 0DH,0AH DB 'Replace and strike any key when ready' DB 0DH,0AH,0 DB 001H,000H,0! DB 000H,0CDH,010H,0EBH,0F1H,0B8H,050H,000H DB 08EH,0C0H,00EH,01FH,02EH,0A1H,003H,07CH DB 0E8H,043H,000H,0BBH,000H,000H,0B8H,001H DB 002H,0E8H,058H,000H,072H,02CH,033H,0FFH DB 0B9H,00BH,000H,026H,080H,00DH,020H,026H DB 080H,04DH,020H,020H,047H,0E2H,0F4H,033H DB 0FFH,0BEH,0DFH,07DH,0B9H,00BH,000H,0FCH DB 0F3H,0A6H,075H,00EH,0BFH,020H,000H,0BEH DB 0EBH,07DH,0B9H,00BH,000H,0F3H,0A6H,075H DB 001H,0C3H,0BEH,080H,07DH,0E8H,0A6H,0FFH DB 0B4H,000H,0CDH,016H,0F9H,0C3H,01EH,00EH DB 01FH,033H,0!?02H DB 0DH,0AH DB 'Disk Boot failure' DB 0DH,0AH,0 DB 'Microsoft,Inc ' DB 'ibmbio com','0' DB 'ibmdos com','0' DB 005H,0C6H,006H,077H,02FH DB 0FFH,083H,07EH,0FCH,000H,075H,00BH,080H DB 07EH,0F7H,03BH,075H,005H,0C6H,006H,076H DB 02FH,0FFH,089H,0ECH,05DH,0CAH,004H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,00!LD2H,0F7H,036H,018H,07CH,0FEH DB 0C2H,088H,016H,015H,07CH,033H,0D2H,0F7H DB 036H,01AH,07CH,088H,016H,01FH,07CH,0A3H DB 008H,07CH,01FH,0C3H,02EH,08BH,016H,008H DB 07CH,0B1H,006H,0D2H,0E6H,02EH,00AH,036H DB 015H,07CH,08BH,0CAH,086H,0E9H,02EH,08BH DB 016H,01EH,07CH,0CDH,013H,0C3H,000H,000H DB 0DH,0AH DB 'Non-System disk or disk error' DB 0DH,0AH DB 'Replace and strike any key when ready' DB 0DH,0AH,0 DB 0DH,0AH DB 'Disk Boot failure' DB 0DH,0AH,0 DB 'ibmbio com','0' DB 'ibmdos !0H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H DB 000H,000H,000H,000H,000H,000H,000H,000H ; ;Boot record for DOS 2.x (Modified above for SS or DS) ; B2DAT: DB 0EBH,02CH,090H DB 'IBM 2.0' B$DAT: DW 512 DB 1 DW 1 Db 2 DW 64 DW 9*40 DB 0FCH DW 0 DW 9 DW 1 DW 0 B$LEN EQU $-B$DAT Dw 000H DB 00AH,0DFH,002H,025H,002H,009H,02AH,0FFH DB 050H,0F6H,00FH,002H,0CDH,019H,0FAH,033H DB 0C0H,08EH,0D0H,0BCH,000H,07CH,08EH,0D8H DB 0A3H,!;com','0' DB 000H DB 000H,000H,000H,000H,000H,000H,055H,0AAH ; ;BPB data for DOS 2.x SSDD ; BPB$BPS$2S: DW 512 BPB$SPC$2S: DB 1 BPB$RES$2S: DW 1 BPB$FAT$2S: Db 2 BPB$DIR$2S: DW 64 BPB$SEC$2S: DW 9*40 BPB$DES$2S: DB 0FCH BPB$FSC$2S: DW 2 B$SPT$2S: DW 9 B$HDS$2S: DW 1 B$HSC$2S: DW 0 ; ;BPB data for DOS 2.x DSDD ; BPB$BPS$2D: DW 512 BPB$SPC$2D: DB 2 BPB$RES$2D: DW 1 BPB$FAT$2D: Db 2 BPB$DIR$2D: DW 112 BPB$SEC$2D: DW 9*80 BPB$DES$2D: DB 0FDH BP!J07AH,000H,0C7H,006H,078H,000H,021H DB 07CH,0FBH,0CDH,013H,073H,003H,0E9H,095H DB 000H,00EH,01FH,0A0H,010H,07CH,098H,0F7H DB 026H,016H,07CH,003H,006H,01CH,07CH,003H DB 006H,00EH,07CH,0A3H,003H,07CH,0A3H,013H DB 07CH,0B8H,020H,000H,0F7H,026H,011H,07CH DB 005H,0FFH,001H,0BBH,000H,002H,0F7H,0F3H DB 001H,006H,013H,07CH,0E8H,07EH,000H,072H DB 0B3H,0A1H,013H,07CH,0A3H,07EH,07DH,0B8H DB 070H,000H,08EH,0C0H,08EH,0D8H,0BBH,000H DB 000H,02EH,0A1H,013H,07CH,0E8H,0B6H,000H DB 02EH,0A0H,018H,07CH,02!=B$FSC$2D: DW 2 B$SPT$2D: DW 9 B$HDS$2D: DW 2 B$HSC$2D: DW 0 NT1: INR A STA TRACK CALL STEPIN JMP NEXTRK ;verify routines begin here ; VFY: MVI A,0 STA HEAD LDA DDRIV CALL SETSEL CALL SETUP MVI A,TRY STA TRIES V1: CALL READID JZ V0 LXI H,TRIES DCR M JNZ V1 CALL ILPRT DB CR,LF,'VERIFY failed. Cannot read source disk.',cr,lf,'$' RET V0: LDA TWOSID CPI 1 MVI A,0 JC VF0 INR A VF0: STA TWOSID XRA A STA TRACK ; start with track 0 VLOOP: C !!ALL KEY LXI H,VFMSG CALL PRINT CALL TMRPRT MVI A,TRY STA TRIES VL1: CALL READTRK JZ VL0 LXI H,TRIES DCR M JNZ VL1 CALL ILPRT DB CR,' ' DB CR,LF,'VERIFY failed. Unrecoverable read error.',CR,LF,'$' CALL REPORT RET VL0: LDA TWOSID ORA A LDA TRACK JZ VF1 LDA HEAD ORA A LDA TRACK JZ VF2 VF1: LXI H,MAXTRK CMP M JNZ VF2 CALL ILPRT DB CR,' ?' DB CR,LF,'VERIFY complete.',CR,LF,'$' RET VF2: INR A !data INX H ; bump pointer MOV A,E ; check for end of table (0ffh) INR A ; 0ffh + 1 = 0 JZ MAKT2 ; if end of table XTHL ; point to track buffer CALL LOAD ; fill track buffer XTHL ; point to format table JMP MAKT1 ; again MAKT2: POP H ; get track buffer address from stack SHLD DMAADR ; save pointer to track buffer RET ; to caller ;write current track from read buffer ; WRITETRK: LXI H,RDBUF SHLD DMAADR LXI H,SKEW ; point to skew table WTLOOP: MOV C,M INX H !8 STA TRACK CALL STEPIN JMP VLOOP ;boot loader routine begin here ; ;gen as in sysgen! ; GEN: LDA DDRIV ; CALL SETSEL ; CALL SETUP ; setup write LDA SELBYT ANI SID0 MOV B,A LDA HEAD ORA A JZ GEN2 MOV A,B ORI SID1 MOV B,A GEN2: MOV A,B STA SELBYT OUT CONT LXI H,TKBUF ; get point SHLD DMAADR ; save buffer pointer LXI H,SKEW1 ; point to new skew CALL WTLOOP ; write data RET ;step in the drive ; STEPIN: LDA TWOSID ORA A JZ STI ; single! ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C OUT WSEC ; to fdc PUSH H ; save skew pointer CALL WRITESEC POP H JMP WTLOOP ;write a sector from DMA buffer ; WRITESEC: IN STAT ; clear status IN RDAT ; clear any trash LHLD DMAADR MVI A,WRSEC ; write sector command CALL OUTCMD ; to fdc CALL WR ; write the data SHLD DMAADR ; save pointer MOV A,B ; get status STA STATUS ANI ERRII RZ ; return to this caller POP H ; a! sided LDA HEAD ORA A MVI A,1 JZ STI0 MVI A,0 STI0: STA HEAD JZ STI1 STI: LDA SELBYT ANI SID0 ; mask side bit off OUT CONT ; select side 0 STA SELBYT CALL WAIT MVI A,STEPI CALL OUTCMD STILP: IN STAT RAR JC STILP RET STI1: LDA SELBYT ORI SID1 OUT CONT ; select side 1 STA SELBYT LXI H,TRACK DCR M JMP WAIT ;write a track ; WRITRK: IN STAT RAR JC WRITRK LXI H,TKBUF MVI A,WRTRK ; write track command CALL OUTCMD CALL WR MOV A,B STA STATU!djust stack from writetrk POP H RET ; return to previous caller ;read current track into read buffer ; READTRK: LXI H,RDBUF SHLD DMAADR LXI H,SKEW ; point to skew table RTLOOP: MOV C,M ; get sector number from table INX H ; bump pointer INR C RZ ; finished, end of table is 0ffh DCR C LDA SBIAS ADD C STA SECTOR OUT WSEC ; to fdc PUSH H ; save skew pointer CALL READSEC ; read the sector RT0: POP H JMP RTLOOP READSEC: IN STAT ; clear status IN RDAT ;!7S ANI ERRIII RET WR: IN STAT ; get fdc status MOV B,A ; save status RAR ; check busy RNC ; end of command, return to caller RAR ; check for drq JNC WR ; if not MOV A,M ; get a byte from buffer OUT WDAT ; to fdc INX H ; bump hl JMP WR ; again ;make a track in memory ; MAKETRK: LXI H,TKBUF ; create track image in memory MVI B,60 MVI A,4EH MTLP: MOV M,A ; write gap4a INX H DCR B JNZ MTLP SHLD DMAADR ; sector 1 starts here LDA HEAD STA SIDE LXI ! clear any trash LHLD DMAADR ; pointer to read buffer MVI A,RDSEC ; read sector command CALL OUTCMD ; to fdc CALL RD ; read the data SHLD DMAADR ; save pointer MOV A,B STA STATUS ANI ERRII RZ POP H ; adjust stack from readtrk POP H RET ; to previous caller RD: IN STAT ; get fdc status byte MOV B,A ; save status RAR ; rotate busy bit to carry RNC ; end of command, return to caller RAR ; rotate data request to carry JNC RD ; wait for data request RD0: IN !H,SKEW ;load skew table pointer LOOP: MOV C,M INX H INR C JZ ENDTRK ; if c was 0ffh DCR C LDA SBIAS ADD C STA SECTOR PUSH H ; save skew pointer on stack CALL MAKTRK POP H JMP LOOP ENDTRK: LHLD DMAADR LXI B,1000 ETLP: MVI M,4EH ;end track fill data INX H DCX B MOV A,B ORA C JNZ ETLP SHLD DMAADR RET MAKTRK: LHLD DMAADR ; track image PUSH H ; save it LXI H,TABLE ; track format table MAKT1: MOV D,M ; get count INX H ; bump pointer MOV E,M ; get !RDAT ; get data from fdc MOV M,A ; put it into buffer INX H ; bump hl JMP RD ; again READID: IN STAT IN RDAT LXI H,IDSV MVI A,RDID CALL OUTCMD CALL RD MOV A,B ; get status STA STATUS ANI ERRIII RET ;allow FDC to setup properly ; WAIT: LXI B,50 * MSEC WT0: DCX B MOV A,B ORA C JNZ WT0 RET WAIT10: LXI B,10 * MSEC JMP WT0 LOAD: MOV M,E ; (e) to track buffer INX H ; increment pointer DCR D ; decrement count JNZ LOAD ; again RET CLRSC: MVI D,2 ""r4 ; print 24 line feed chars to clear screen CLS: MVI A,LF CALL CONOUT ; out to console CALL WAIT10 ; wait 10 ms after line feed DCR D ; decrement count JNZ CLS ; again RET PRINT: MOV A,M ; hl points to text string INX H ; bump hl CPI '$' ; check for terminator RZ ; return to caller CALL CONOUT ; send byte to console JMP PRINT ; again pCONOUT: PUSH B ; save PUSH D ; the PUSH H ; registers MOV E,A ; text to be printed MVI C,2 ; console output function "oop till timeout MVI A,0D0H ; timeout -- force interrupt, CALL OUTCMD ; then report failure FAILED: LDA SELBYT ANI 0FH MVI C,0 FLD1: INR C RAR JNC FLD1 MOV A,C adi 30H ; add ascii bias STA DRI CALL ILPRT ; print following string DB CR,LF,'Drive ' DRI: DB 'A Not Ready, Insert disk, close door, and try again.',CR,LF,'$' POP B ; adjust stack RET ;send a command to the FDC ; OUTCMD: OUT CMND MVI A,10 OC0: DCR A JNZ OC0 ; wait 35 us. for fdc to set-up "P CALL 5 ; bdos POP H ; restore POP D ; the POP B ; registers RET ;prints next byte pointed to by top of stack ;until delimiter $ is found ; ILPRT: XTHL ; return address to hl points to text ILP: MOV A,M ; get next byte INX H ; bump pointer CPI '$' ; check for string terminator JZ ILPE ; if end of string CALL pCONOUT ; send byte to console JMP ILP ; again ILPE: XTHL ; put updated pointer on stack RET CONOUT: PUSH B ; save PUSH D ; the PUSH H ; reg" RET KEY: push b push d mvi c,6 mvi e,0ffh call 5 pop d pop b rz CPI 3 JZ EXIT PUSH PSW CALL ILPRT DB CR,' ',CR,'$' ; clear the line POP PSW CPI ESC RNZ POP H RET EXIT: JMP 0 ; warm boot TMRPRT: LDA TRACK LXI D,TKMSG0 CALL BINASC LDA HEAD LXI D,SDMSG0 CALL BINASC LXI H,TKMSG JMP PRINT ; print returns to caller REPORT: LXI D,D]R ; point to error message LDA SELBYT ANI 0FH ; mask upper nybble MVI C,0 ; clear co"isters MOV E,A ; text to be printed MVI C,6 ; console output function CALL 5 ; bdos POP H ; restore POP D ; the POP B ; registers RET CONIN: MVI A,9 ; bios call avoids echo to console BIOS: LHLD 1 MOV L,A PCHL CONINB: PUSH B PUSH D ; save PUSH H ; registers MVI C,1 ; console input function CALL 5 ; bdos POP H ; restore POP D ; registers POP B RET ; ;restore the disk and wait for status ; ; The current setup routine does a restore with the"unter R1: INR C ; bump it RAR ; rotate selbit into carry JNC R1 ; again? MOV A,C ADI 30H ; add ascii bias STAX D ; store it in message STA WPRMSG0 LDA STATUS ANI WPR ; is disk protected? JZ R2 LXI H,WPRMSG ; write protected message CALL PRINT POP H ; adjust the stack CALL CONIN ; get response CPI CR ; carriage return? JZ EXEC ; if so RET ; get out of here R2: LXI D,TK ; in error message LDA TRACK CALL BINASC LXI D,HD LDA SIDE ORA A ; set flags JZ "k 1772 ; motor on flag enabled. It exits as soon as the BUSY ; status bit goes away, or after a 4 second timeout. SETUP: LDA SELBYT ; get selected drive OUT CONT ; select the drive MVI A,REST ; restore command CALL OUTCMD ; output the command LXI H,4000 ; 4000 ms timeout setup DEL0: MVI C,0 DEL1: DCR C JNZ DEL1 IN STAT RAR JNC READY ; go on if 1772 done DCX H MOV A,H ORA L JNZ DEL1 MVI A,0D0H ; timed out -- force interrupt, CALL OUTCMD ; then report failure"RPRT1 MVI A,1 RPRT1: CALL BINASC LXI D,SC LDA SECTOR CALL BINASC LXI D,ST LDA STATUS ANI RNF JNZ SRNF LXI H,CRCER CALL MOV3 JMP RPRT2 SDNR: LXI H,DNRER CALL MOV3 JMP RPRT2 SRNF: LXI H,RNFER CALL MOV3 RPRT2: LXI H,ERRMSG RPRT3: JMP PRINT ; print returns to caller MOV3: MVI B,3 MOVL: MOV A,M STAX D INX H INX D DCR B JNZ MOVL RET BINASC: PUSH PSW ; save value PUSH D ; save string ptr MVI A,'0' ; ascii zero STAX D LXI B,2 ; b=0, c=2 XRA A ; a=0" JMP FAILED ; The current ready function checks to see if a diskette ; is inserted in a drive. A read address command with ; the motor on flag enabled is used. If the command ; hangs up, the 1772 is not receiving index pulses, ; indicating the lack of a spinning diskette. READY: MVI A,0C0H ; read address command CALL OUTCMD LXI H,4000 ; 4000 mS timeout setup MVI C,0 RDY1: DCR C JNZ RDY1 IN STAT RAR RNC ; finished, if 1772 done DCX H MOV A,H ORA L JNZ RDY1 ; l" B0: INX D ; bump ptr STAX D ; zero to str DCR C JNZ B0 ; again please POP D ; restore de LXI H,TBL ; conversion table B1: MVI C,0 ; clear count MOV A,M ; table value INR A JZ BEND ; end of table, conv done POP PSW ; restore value B3: SUB M ; begin division JC B2 INR C ; keep count JMP B3 B2: ADD M ; restore acc PUSH PSW ; save it MOV A,C ; count CPI 0 JNZ STSTR ; set ascii value in string MOV A,B CPI 0 ; 1st time? JNZ STSTR B4: INX H ; bump tbl pt ""r JMP B1 ; next STSTR: MVI B,1 ; flag 1st time MOV A,C ; count to c ADI 30H ; ascii bias STAX D ; write it into string INX D ; bump str ptr JMP B4 BEND: POP PSW ; adjust stack RET ; return to caller TBL: DB 100 DB 10 DB 1 DB 255 ; end of table ;setup the selbyt ; SETSEL: inr a MOV C,A XRA A STC STSL: RAL DCR C JNZ STSL ORI ROMOFF STA SELBYT RET ;error messages... ERRMSG: DB CR,LF,' Error: Drive ' DR: DB 0,': Track ' TK: DB 0,0,0,' He"Octor translate routine ; AMPRO-specific BIOS calls LB$GETNXT DS 3 ; Get bios ver & next tbl address LB$GETEDSK DS 3 ; Get pointer to E-disk storage LB$IOINIT DS 3 ; Set new I/O parameters LB$SCSIDRV DS 3 ; SCSI direct driver LB$LEN EQU $-LB$WBOOT ; Length of bios table LB$XTBL: LB$SWAP$DRV DS 3 ; Swap two logical drives LB$WINDRV DS 3 ; Set/get win drive parameters LB$PHYTAB DS 3 ; Set/get phytab access LB$GET$LDTE DS 3 ; Get physical table entry address LB$RESERVED DS 3 ; Reserved entry "ad ' HD: DB 0,0,0,' Sector ' SC: DB 0,0,0,' Status ' ST: DB 0,0,0,CR,LF,'$' TKMSG: DB 'Track ' TKMSG0: DB 0,0,0,' Side ' SDMSG0: DB 0,0,0,CR,'$' VFMSG: DB 'Verify $' FRMSG: DB 'Format $' WPRMSG: DB CR,' ' DB CR,LF,'Remove write protect tab from ' DB 'destination diskette.' DB CR,LF,'Place diskette in drive ' WPRMSG0:DB 'A, then press . $' DNRER: DB 'DNR' RNFER: DB 'RNF' CRCER: DB 'CRC' ;the main data table.. ; TABLE: DB 12,0 ; defines se"pLB$XLEN EQU $-LB$XTBL ; Length of extra table LB$VERS DS 1 DS 64 ; space for 32 level stack STACK: DS 2 ; space for ccp stack pointer IDSV: DS 6 ; id save area RDBUF: DS 10 * 512 ; read buffer TKBUF: END ; end of program  Length of bios table LB$XTBL: LB$SWAP$DRV DS 3 ; Swap two logical drives LB$WINDRV DS 3 ; Set/get win drive parameters LB$PHYTAB DS 3 ; Set/get phytab access LB$GET$LDTE DS 3 ; Get physical table entry address LB$RESERVED DS 3 ; Reserved entry  ">ctor format (#bytes,data) DB 3,0F5H ; write 0a1h DB 1,0FEH ; id address mark DB 1 TRACK: DB 0 DB 1 SIDE: DB 0 DB 1 SECTOR: DB 1 DB 1 SIZE: DB 3 ; always 512 bytes DB 1,0F7H ; write crc (2 bytes) GAP2: DB 22,4EH ; gap 2 length, data PREAM: DB 12,0 ; preamble DB 3,0F5H ; write 0a1h DB 1,0FBH ; data address mark DAT0: DB 0,0E5H ; bytes of data fill DB 0,0E5H ; bytes of data fill DB 0,0E5H ; bytes of data fill DB 0,0E5H ; bytes of data fill DB 1,0F7H ; write crc (2 ""bytes) GAP3: DB 0,4EH ; gap 3 length, data DW -1 ; end of table (0ffffh) FUNC: DS 1 ; function 1=format, 2=verify, MAXTRK: DB 39 ; maximum track TWOSID: DB 0 ; 0=ss , 1=ds HEAD: DB 0 ; SDRIV: DS 1 ; source drive DDRIV: DS 1 ; destination drive SELBYT: DS 1 ; SBIAS: DB 0 ; sector bias 0=ss, 10h=ds, 30h=ds96 TPI96: DB 1 ; 0=48tpi , 1=96tpi DMAADR: DS 2 ; STATUS: DS 1 ; TRIES: DS 1 ; ; SKEW: DS 40 SKEW1: DS 40 ; ; Replicated BIOS for ease of use . . . LB$BIOS$TBL: LB$WBO""wOT DS 3 ; Warm boot LB$CONST DS 3 ; Console status LB$CONIN DS 3 ; Console input LB$CONOUT DS 3 ; Console output LB$LISTOUT DS 3 ; List output LB$PUNCH DS 3 ; Punch output LB$READER DS 3 ; Reader input LB$HOMDSK DS 3 ; Home disk (move to track 00) LB$SELDSK DS 3 ; Select disk drive LB$SETTRK DS 3 ; Select track number LB$SETSEC DS 3 ; Select sector number LB$SETDMA DS 3 ; Set DMA address LB$DSKREAD DS 3 ; Disk read LB$DSKWRITE DS 3 ; Disk write LB$LISTST DS 3 ; List status LB$SECTRN DS 3 ; Se" ########### ########### $5$$$$$$$$$$ $$$$$$$$$$$ %%%%%%%%%%% %+%%%%%%%%%% &'&&&&&&&&&& &&&&&&&&&&& ''''''''''' '9'''''''''''9