; MICRO-DECISION ; FORMAT SUBROUTINE FOR INIT VER. 2.2 ; COPYRIGHT 1982 ; MORROW DESIGNS, INC. ; 12/06/82 ; .Z80 ASEG ; ORG 4000H ; RAMDATX EQU 5000H TRKBUF EQU RAMDATX+100H ; FMTCMD EQU 4DH ; SYS EQU 5 PBUFF EQU 9 RDCON EQU 6 IBUF EQU 80H ; WBOOT EQU 1 DISCIO EQU 39H RDBLK EQU 33H SECOFF EQU 1EH SELOFF EQU 18H HMOFF EQU 15H TRKOFF EQU 1BH DMAOFF EQU 21H WROFF EQU 27H MTOFF EQU 41H ; BTERR EQU 18H WRIO EQU 15H MESG EQU 3 ; LF EQU 0AH CR EQU 0DH ASCA EQU 41H ASC0 EQU 30H SPACE EQU 20H CTLC EQU 3 ; LTRK EQU 6 SIZMSK EQU 18H DSD EQU 5 DSM EQU 2 ; START: LD A,'B' ; PUSH AF XOR A LD (EFLAG),A ; POP AF LD B,A ; SKCIN: LD (DRVM),A ;SAVE DRIVE IN MESSAGE LD (DRVT),A SUB 41È ;CONVERÔ TÏ ASCII ; DROK: PUSH AF ;SAVE DRIVE ; LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,MTOFF ;OFFSET TO MTAB POINTER ADD HL,DE ;HL = ADDRESS OF MATB POINTER ; LD E,(HL) ;SET DE = MTAB POINTER INC HL LD D,(HL) ; EX DE,HL ;HL = MTAB POINTER LD E,A ;E=DRIVE ; RLCA ;A = (2 X DRIVE) RLCA ;A = (4 X DRIVE) RLCA ;A = (8 X DRIVE) ADD A,E ;A = (9 X DRIVE) ; LD E,A ;DE = (9 X DRIVE) LD D,0 ; ADD HL,DE INC HL ;HL POINTS TO DSKDEF1 FOR THIS DRIVE ; LD A,3 ;MASK FOR PHYSICAL DRIVE ADDRESS AND (HL) ;MASK OUT PHYSICAL DRIVE ADDRESS ; LD (HDDRV),A ;PUT IN COMMAND BUFFER ; POP AF PUSH HL ;SAVE DSKDEF1 POINTER PUSH AF ; DEC HL ;GET DSKDEF0 POINTER ; BIT DSD,(HL) ;SEE IF DOUBLE SIDED DRIVE ; INC HL ;GET DSKDEF1 RES DSM,(HL) ;SET TO SINGLE SIDED MEDIA ; LD DE,DPBS LD (DPBP),DE ; JR Z,SSIDE ;JMP IF SINGLE SIDED DRIVE ; DSIDE: SET DSM,(HL) ;SET TO DOUBLE SIDED MEDIA LD DE,DPBD LD (DPBP),DE ; SSIDE: POP AF PUSH AF ; LD B,A LD A,(8) CP B JR NC,NVIRT ; LD HL,(1) LD DE,3FH ADD HL,DE LD E,(HL) INC HL LD D,(HL) LD HL,13H ADD HL,DE LD (HL),B LD (HLTMP),HL LD DE,VTMSG LD A,'A' LD (DRVM),A CALL PRNT LD DE,VT1 JR VIRT ; NVIRT: LD DE,MESG2 ;INSERT DISC MESG. VIRT: CALL PRNT ;PRINT MESG. EAGN: CALL CIN CP CR JR Z,EOK ; LD DE,BKSP CALL PRNT JR EAGN ; EOK: LD DE,CRLF CALL PRNT ; ; POP AF ;A=DRIVE LD (HSTDSK),A LD (VDSK),A LD C,A ;C=DRIVE CALL SELDSK ;SELECT DRIVE ; PUSH HL ;CALCULATE THE DPB ADDRESS POP IX ;FOR THIS DRIVE, AND PUT IT LD L,(IX+0AH) ;IN IX. LD H,(IX+0BH) PUSH HL POP IX ; ; AT THIS POINT WE HAVE A POINTER TO DSKDEF1 ON THE ; STACK, AND A POINTER TO DPB IN IX. THIS IS ALL THE ; INFORMATION THAT WE NEED TO DETERMINE WHAT FORMAT ; TO USE. ; POP HL ;GET DSKDEF1 POINTER LD B,(HL) ;B=DSKDEF1 ; PUSH IX ;SAVE DPB POINTER POP HL PUSH HL PUSH BC ;SAVE BC LD A,(HL) LD HL,FTAB256 ;POINTER TO FORMAT TABLE LD DE,M256 ; LD A,32 ;256 BYTES/SECTOR CP (IX+0) ;SEE IF DPB MATCHES JR NZ,NOT32 ; LD A,SIZMSK ;CHECK SECTOR SIZE AND B ;MASK SIZE CODE FROM DSKDEF1 CP 8 ;SEE IF 256 BYTES/SECTOR JR Z,FOK ;JMP IF 256 ; LD HL,FTAB512 LD DE,M512 JR FOK ; NOT32: LD HL,FTAB1K ;HL = POINTER TO FORMAT TABLE LD DE,DMSG ; LD A,40 ;1K TRACKS/SECTOR CP (IX+0) ;SEE IF DPB MATCHES JR FOK ;DO STANDARD 1K FORMAT UNLESS OTHER ;FORMAT IS RECOGNIZED. ; LD DE,IDSK JP ERROR ; FOK: BIT DSM,B ;SEE IF DS MEDIA JR Z,SSD0 ;JMP IF SS PUSH DE LD DE,7 ADD HL,DE POP DE ; SSD0: PUSH HL POP IX CALL PRNT ; PUSH IX ;XFER PARAMS. FROM FTAB TO COMD. BUF. POP HL INC HL INC HL LD DE,FDCCMD+2 LD BC,4 LDIR ; DOK: CALL HOME ;HOME DRIVE ; ; LD DE,FMSGI CALL PRNT ; XOR A ;A=0 ; FORML: LD (HSTTRK),A ;SET TRACK ; POP BC ;B=DSKDEF1 PUSH BC ;SAVE DSKDEF1 PUSH AF ; BIT DSM,B ;SEE IF DS MEDIA ; SCF ;CLEAR CY CCF ; JR Z,SSD1 ;JMP IF SS ; RRA ;SET A & CY FOR DS ; SSD1: LD (PHYTRK),A ; LD A,0 RLA RLA RLA LD (PHYHD),A ; POP AF CALL ASCII ;CONVERT TO ASCII LD (MTRK),BC ;PUT IN MESG. ; LD DE,FORMSG ;FORMATING MESG. CALL PRNT ; LD A,(HDDRV) RES 2,A LD B,A LD A,(PHYHD) OR B LD (HDDRV),A ; LD E,(IX+0) ;DE = PNTR. TO SECTOR TABLE LD D,(IX+1) ; LD HL,TRKBUF ; BLDL: LD A,(PHYTRK) ;A=TRACK LD (HL),A ;SET CYLINDER INC HL ; LD A,(PHYHD) ;A=HEAD RRCA RRCA LD (HL),A ;SET HEAD INC HL ; LD A,(DE) ;A=SECTOR LD (HL),A ;SET RECORD INC DE ;INC SECTOR TABLE POINTER INC HL ; LD A,(IX+2) ;A=N=SIZE BYTE FOR HEADER LD (HL),A ;SET N INC HL ; LD A,(DE) ;A=NEXT SECTOR CP 0FFH ;IS IT THE END JP NZ,BLDL ;JMP IF NOT END ; CALL WRTT ;WRITE TRACK ; OR A JP NZ,ERROR ;JMP IF ERROR ; LD A,(HSTTRK) ;A=TRACK INC A ;INC TRACK CP (IX+LTRK) ;LAST TRACK? JP NZ,FORML ;JMP IF NOT DONE ; ; FDONE: LD DE,VMSGI CALL PRNT ; LD L,(IX+0) ;HL=SECTOR TABLE ADDRESS LD H,(IX+1) ; LD DE,0 ;D=TRACK=0 : E=SECTOR=0 ; VLOOP: CALL VMESG ;PRINT VERIFY MESG. ; LD A,D ;A=TRACK LD (VTRK),A ;SET TRACK ; VLOP1: LD C,E ;BC=SECTOR LD B,0 PUSH HL ;SAVE SECTAB POINTER ADD HL,BC ;ADD SECTOR TO TABLE ; LD A,(HL) ;A=PHYSICAL SECTOR POP HL ;RESTORE HL ; CP 0FFH ;SEE IF DONE JR Z,NTRK ;JMP IF DONE ; CP 0FEH ;SEE IF 1ST PASS DONE JR NZ,NEND ;JMP IF 1ST PASS NOT DONE. ; LD E,1 ;SET FOR 2ND PASS. JR VLOP1 ;START 2ND PASS. ; NENDº INC Å ;INÃ SECTOÒ COUNT. INC E ; LD (VSEC),A ;SET SECTOR PUSH DE ; PUSH HL CALL READ ;READ SECTOR POP HL POP DE ;RESTORE TRK-SECT ; OR A JP NZ,ERROR ; JR VLOP1 ;GO READ NEXT SECTOR ; NTRK: LD E,0 ;SECT=0 INC D ;INC TRACK LD A,(IX+LTRK) ;SEE IF LAST TRACK CP D JR NZ,VLOOP ;LOOP IF NOT DONE ; POP BC ;B=DSKDEF1 POP HL ; NBAD: CALL INIT ;INIT TRACK 0 LD DE,FMESG ;PNTR. TO END MESG. CALL PRNT ; LD DE,FATAL BAD1: LD HL,(HLTMP) LD A,H OR L JR Z,FINI LD (HL),0 FINI: LD A,(DRVM) CP 'A' JR NZ,NTA LD HL,(HLTMP) LD A,L OR H JR Z,NVT LD A,'A' LD (DRVT),A LD DE,VTMSG CALL PRNT LD DE,VT2 CALL PRNT JR FLOP NVT: LD DE,SYSM CALL PRNT FLOP: CALL CIN CP 0DH JR NZ,FLOP NTA: LD BC,0 RET ; ; VMESG: PUSH HL ;SAVE REGS. PUSH DE PUSH BC ; LD A,D ;A=TRACK CALL ASCII ;COMVERT TO ASCII LD (VMTRK),BC ;STORE STRING ; LD DE,VMSG ;PNTR. TO VER.MESG. CALL PRNT ; POP BC POP DE ;RESTORE REGS. POP HL RET ; ; WRTT: PUSH IX ;SAVE IX ; LD HL,FRMDTX ;MOVE RAMDATX LD DE,RAMDATX LD BC,RAMLEN LDIR ; LD IX,RAMDATX ;SET RAMDATX FOR FORMAT ; LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,DISCIO ;OFFSET TO DISCIO JMP ADD HL,DE ;ADD TO HL ; CALL JPHL ; POP IX ;RESTORE IX RET ; JPHL: JP (HL) ;GO TO DISK I/O ; SWRT: LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,WROFF ;OFFSET TO WRITE JMP ADD HL,DE ;ADD TO HL LD C,1 JP (HL) ;GO TO WRITE ; READ: PUSH IX ;SAVE IX ; LD HL,VRMDTX ;MOVE RAMDATX LD DE,RAMDATX LD BC,RAMLEN LDIR ; LD IX,RAMDATX ;SET RAMDATX FOR VERIFY ; LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,RDBLK ;OFFSET TO RDBLK JMP ADD HL,DE ;ADD TO HL ; CALL JPHL ; POP IX RET ; SELDSK: LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,SELOFF ;OFFSET TO SELDSK JMP ADD HL,DE ;ADD TO HL LD E,1 JP (HL) ;GO TO SELDSK ; HOME: LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,HMOFF ;OFFSET TO HOME JMP ADD HL,DE ;ADD TO HL JP (HL) ;GO TO HOME ; SELTRK: LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,TRKOFF ;OFFSET TO SETTRK ADD HL,DE ;ADD TO HL JP (HL) ;GO TO SETTRK ; SELSEC: LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,SECOFF ;OFFSET TO SETSEC ADD HL,DE ;ADD TO HL JP (HL) ;GO TO SETSEC ; SETDMA: LD HL,(WBOOT) ;GET WARM BOOT ADDRESS LD DE,DMAOFF ;OFFSET TO SETDMA ADD HL,DE ;ADD TO HL JP (HL) ;GO TO SETDMA ; INIT: LD C,0 ;TRACK=0 CALL SELTRK ; LD C,1 ;SECTOR=1 CALL SELSEC ; LD BC,IDAT ;DMA ADDR.=IDAT CALL SETDMA ; CALL SWRT ;WRITE SECTOR OR A ;CHECK FOR ERRORS JR NZ,WERROR ;JMP IF ERROR ; LD C,9 ;SECTOR=9 CALL SELSEC ; CALL SWRT ;WRITE SECTOR OR A ;CHECK FOR ERRORS JR NZ,WERROR ;JMP IF ERROR ; LD C,2 ;WRITE DPB INTO BOOT SECTOR CALL SELSEC ; LD BC,(DPBP) CALL SETDMA ; CALL SWRT OR A JR NZ,WERROR ; RET ; ; ERROR: POP DE WERROR: POP BC LD BC,1 RET ; PRNT: LD C,PBUFF ;PRINT BUFFER COMMAND JP SYS ;JUMP TO SYSTEM ; ASCII: LD C,ASC0 ;C=ASCII 0 ALOP: SUB 10 ;SUB 10 JR C,ADN ;JMP IF CY=1 ; INC C ;INC CHAR. JR ALOP ;CONTINUE ; ADN: ADD A,3AH ;FIX CHAR. LD B,A RET ; CIN: LD C,RDCON ;USE DIRECT CONSOLE I/O TO LD E,0FFH ;WAIT FOR A CHARACTER. CALL SYS OR A JR Z,CIN ; CHKIN: CP ASCA ;SEE IF LESS THAN ASCII "A" JR C,NALPH ;JMP IF LESS THAN "A" ; AND 0DFH ;FORCE TO UPPER CASE ; NALPH: LD E,A CP SPACE ;SEE IF CONTROL CHAR. JR NC,NECHO ;JMP IF NOT CONTROL CHAR. ; CP CTLC ;SEE IF CONTROL-C JP Z,0 ; LD E,SPACE ; NECHO: PUSH AF ;SAVE REGS. PUSH BC ; LD C,RDCON ;ECHO CHAR. CALL SYS ; POP BC ;RESTORE REGS. POP AF ; RET ; EFLAG: DB 0 IPNT: DW 0 ICNT: DB 0 HLTMP: DW 0 DPBP: DW 0 ; ; BKSP: DB 8,20H,8,'$' CRLF: DB 0AH,0DH,'$' MESG2: DB 0AH,0DH,'Insert the DESTINATION diskette in drive ' DRVM: DB 'A, then press [RETURN] $' SDMSG: DB CR,LF,'Single or double sided format (S or D) $' ; ; DMSG: DB 0DH,0AH,'Double density format',0DH,0AH,'$' M256: DB CR,LF,'Double density 256 bytes/sector format',CR,LF,'$' M512: DB CR,LF,'Double density 512 bytes/sector format',CR,LF,'$' ; FMSGI: DB 0DH,'Formatting track ' FORMSG EQU FMSGI MTRK: DB '00 $' ; WERR: DB 0DH,0AH,'Write error,$' RMESG: DB 0DH,0AH,'Read error,$' EMESG: DB ' on DESTINATION diskette. Press [RETURN] to try again. $' FMESG: DB 0DH,0AH,0AH,'Formatting done$' FATAL: DB 0DH,0AH,'Press R to start again, or [RETURN] to return to CP/M $' VMSGI: DB 0AH,0DH,'Verifying track ' VMTRK: DB '00 $' VMSG EQU VMSGI+1 IDSK: DB 'Invalid disk parameter block',0DH,0AH,'$' SYSM: DB 0DH,0AH,0AH,'Insert the CP/M DISTRIBUTION diskette in drive A, then press [RETURN] $' VTMSG: DB 0DH,0AH,0AH,'Your drive is being re-assigned as drive ' DRVT: DB 'A.$' VT1: DB 0DH,0AH,'Insert the DESTINATION diskette and press [RETURN] $' VT2: DB 0DH,0AH,'Insert the CP/M DISTRIBUTION diskette, then press [RETURN] $' ; FRMDTX: HSTDSK: DB 0 HSTTRK: DB 0 HSTSEC: DB 0 ; SECCNT: DB 1 RETRY: DB 5 HSTBUF: DW TRKBUF ; ERFLAG: DB 0 PHYTRK: DB 0 PHYHD: DB 0 ; IOADD: DW WRIO SECSIZ: DW 0 ; STADD: DS (7),0 ; CMDCNT: DB 6 FDCCMD: DB FMTCMD HDDRV: DB 0 N: DB 0 SC: DB 0 GPL: DB 0 DAT: DB 0 ; RAMLEN EQU $-FRMDTX ; ; VRMDTX: VDSK: DB 0 VTRK: DB 0 VSEC: DB 0 ; VCNT: DB 1 VRETRY: DB 5 VBUF: DW TRKBUF ; VERFLG: DB 0 VPHTRK: DB 0 VPHYHD: DB 0 ; VADD: DW 0 VSIZE: DW 0 ; VSTAT: DS (7),0 ; CMDBUF: DS (10),0 ; FTAB1K: DW SECTB1K DB 3 ;N = SECTOR SIZE CODE DB 5 ;SC = SECTORS PER TRACK DB 95 ;GPL = GAP3 LENGTH DB 0E5H ;D = FILL BYTE DB 40 ;LAST TRACK ; DW SECTB1K DB 3 ;N = SECTOR SIZE CODE DB 5 ;SC = SECTORS PER TRACK DB 95 ;GPL = GAP3 LENGTH DB 0E5H ;D = FILL BYTE DB 80 ;LAST TRACK ; SECTB1K:DB 1,2,3,4,5,0FFH,0FEH ; FTAB256:DW SCTB256 DB 1 DB 16 DB 50 DB 0E5H DB 40 ; DW SCTB256 DB 1 DB 16 DB 50 DB 0E5H DB 80 ; SCTB256:DB 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,0FFH,0FEH ; FTAB512:DW SCTB512 DB 2 DB 8 DB 80 DB 0E5H DB 40 ; DW SCTB512 DB 2 DB 8 DB 80 DB 0E5H DB 80 ; SCTB512:DB 1,2,3,4,5,6,7,8,0FFH,0FEH ; ; DPBS: DS 9,0 DW 40 DB 4 DB 15 DB 1 DW 94 DW 127 DB 0C0H DB 0 DW 32 DW 2 DB 0E1H DS 80H-25,0 ; DPBD: DB 0 DB 4 DS 7,0 DW 40 DB 4 DB 15 DB 1 DW 194 DW 191 DB 0E0H DB 0 DW 48 DW 2 DB 89H DS 80H-25,0 ; IDAT EQU $ ; .PHASE 0FE00H ; NOP NOP NOP LD A,0C9H LD (0FDFFH),A CALL 0FDFFH RADD: LD HL,-2 ADD HL,SP LD E,(HL) INC HL LD D,(HL) LD HL,EMSG-RADD ADD HL,DE EX DE,HL LD SP,0FF00H OUT (0F6H),A CALL MESG JP BTERR ;JMP TO ROM ; ; EMSG: DB CR,LF,'Not a SYSTEM Diskette.',CR,LF,0 ; DS (80H),0 ; .DEPHASE ; END