home *** CD-ROM | disk | FTP | other *** search
- ;********************************************************
- ;* *
- ;* HARDWARE DEPENDANT DISK COPY PROGRAM *
- ;* FOR MORROW DESIGNS DJ2D AND CP/M 2.X *
- ;* *
- ;********************************************************
- ;
- ; By: Bill Bolton
- ; Software Tools
- ; P.O. Box 63
- ; Newport Beach
- ; NSW, 2106
- ; AUSTRALIA
- ;
- ; COPYRIGHT (C) 1980,1981 SOFTWARE TOOLS
- ;
- ; ALL COMMERCIAL RIGHTS RETAINED BY AUTHOR
- ;
- ; History:
- ; All versions prior to release 2 were
- ; for North Star disk systems and
- ; I'd rather forget all about them
- ; so dont ask !
- ;
- ; July 16, 1980 Version 2.0 developed as a universal
- ; disk copy program for CP/M 2.X, but
- ; it was too slow.
- ;
- ; July 22,1980 Version 2.10 developed as much faster
- ; faster hardware dependant version
- ; for DJ2D & CP/M 2.2
- ;
- ; July 25,1980 Version 2.11 error message bugs fixed
- ; and conditional assembly for system
- ; density added.
- ;
- ; August 17,1980 Version 2.12 doublesided disk routines
- ; bugs fixed
- ;
- ; Feb 10, 1981 Version 2.13 pause before error reboot added
- ;
- ; Mar 26, 1981 Version 2.14 correctly detects two sided disks
- ; with Model A Disk Jockeys
- ;
- ; May 22, 1981 Version 2.15 clobbers incorrect format determination
- ; in some circumstances due to some "undocumented
- ; feature" of the DJ2D or 1791, still don't know why it
- ; happens in the first place but I found a way to
- ; stop it . Also ^C abort is now correctly detected
- ; immediately. FDOS$SIZE values corrected.
- ;
- TITLE 'DJ2D Disk Copier Ver 2.15'
- ;
- TRUE EQU 0FFFFH
- FALSE EQU NOT TRUE
- SINGLE EQU FALSE ;Single density CP/M system with DJ2D
- MODELB EQU FALSE ;Model B DJ2D controller (for debugging)
- ; In practice this equate should be FALSE
- ; even for Model B DJ2Ds
- HARD EQU FALSE ;Hard disk/floppy disk system, floppys must
- ; be drives A,B,C,D for this to work, otherwise
- ; you'll have to hack the code yourself
- ;
- DJORG EQU 0F800H ;DJ2D BASE ADDRESS
- ;
- IF SINGLE OR MODELB
- BASE EQU DJORG ;USE ROM FIRMWARE
- ELSE
- BASE EQU DJORG+400H ;USE RAM IMAGE OF DJ FIRMWARE
- ENDIF
- ;
- DJTRKSET EQU BASE+0CH
- DJSETSEC EQU BASE+0FH
- DJSETDMA EQU BASE+12H
- DJREAD EQU BASE+15H
- DJWRITE EQU BASE+18H
- DJSELDRV EQU BASE+1BH
- DJDMAST EQU BASE+24H
- DJSTATUS EQU BASE+27H
- DJSETSID EQU BASE+30H
- WBOOT EQU 00000H
- BDOS EQU 00005H
- CNTRL$C EQU 003H ;ASCII ETX (^C)
- ACR EQU 00DH ;ASCII CARRIAGE RETURN
- VERSION EQU 12 ;BDOS VERSION NO. FUNCTION
- ;
- IF SINGLE AND NOT HARD
- FDOS$SIZE EQU 01100H ;SIZE OF BDOS+BIOS
- ENDIF
- IF NOT SINGLE AND NOT HARD
- FDOS$SIZE EQU 01400H ;SIZE OF BDOS+BIOS
- ENDIF
- IF HARD AND NOT SINGLE
- FDOS$SIZE EQU 01700H ;SIZE OF BDOS+BIOS
- ENDIF
- ;
- ORG 0100H
- ;
- MACLIB MACRO3 ;SOFTWARE TOOLS SPECIAL MACROS
- ;
- BEGIN:
- MVI C,VERSION
- CALL BDOS ;GET CP/M VERSION NO.
- MOV A,L
- SUI 022H ;VERSION 2.2 OR LATER?
- JM WRONG$VERSION ;NO
- LXI H,BASE ;POINT TO ADDRESS OF FIRMWARE
- MOV A,M ;GET FIRST BYTE OF FIRMWARE
- CPI 0C3H ;IS IT A 'JMP' INSTRUCTION
- JNZ WRONG$VERSION ;NO
- LXI SP,STACK$TOP ;YES, SET UP STACK
- IF SINGLE
- PRINT <CR,LF,'COPY - Ver 2.15 (1D)',CR,LF>
- ELSE
- PRINT <CR,LF,'COPY - Ver 2.15 (2D)',CR,LF>
- ENDIF
- PRINT <'Copyright (C) 1980/81 - Bill Bolton, Software Tools',CR,LF>
- PRINT <'For Morrow Designs Disk Jockey 2D and CP/M 2.2',CR,LF,LF>
- PRINT 'BOTH Source and Destination MUST be the same format'
- ;
- MENU:
- PRINT <CR,LF,LF,' ***** O P T I O N S *****'>
- PRINT <CR,LF,LF>
- PRINT ' "A" = Copy ALL '
- DECOUT TRACKS
- PRINT <' tracks',CR,LF>
- PRINT ' "M" = Copy all tracks UNTIL '
- PRINT <'0E5H track',CR,LF>
- PRINT <' "O" = Copy ONLY CP/M system tracks',CR,LF>
- PRINT <' "F" = Copy FILES to end of disk',CR,LF>
- PRINT <' "N" = Copy files UNTIL 0E5H track',CR,LF>
- PRINT ' "E" = EXIT to CP/M (FIRST insert system disk)'
- PRINT <CR,LF,LF,'Enter your selection - '>
- ;
- CALL GET$CONSOLE ;GET CONSOLE INPUT
- STA COMMAND ;SAVE FOR LATER
- LXI H,TRACKS ;GET NUMBER OF TRACKS
- MOV H,M ;H <--- MAX NO. TRACKS
- MVI L,0 ;L <--- TRACK 0 TO START
- CPI 'A'
- JZ SELECT$DRIVES
- CPI 'M'
- JZ SELECT$DRIVES
- LXI H,0200H ;H <--- TRACK 2
- CPI 'O' ;L <--- TRACK 0 TO START
- JZ SELECT$DRIVES
- LXI H,TRACKS
- MOV H,M ;H <--- MAX NO. TRACKS
- MVI L,2 ;L <--- TRACK 2 TO START
- CPI 'F'
- JZ SELECT$DRIVES
- CPI 'N'
- JZ SELECT$DRIVES
- CPI 'E'
- JZ WBOOT
- PRINT <CR,LF,BEL,'Illegal selection - try again.'>
- JMP MENU
- ;
- SELECT$DRIVES:
- SHLD START$TRACK ;L= TRACK TO START
- ;H= LAST TRACK TO COPY
- SOURCE$DRIVE:
- PRINT <CR,LF,'Enter SOURCE drive (A, B, C or D)'>
- PRINT <CR,LF,' ( CR copies from A to B ) - '>
- ;
- CALL GET$CONSOLE ;GET CONSOLE INPUT
- CPI ACR
- JZ DEFAULT
- ANI 05FH ;MAKE INTO UPPER CASE
- STA SOURCE
- SUI 'A' ;SUBTRACT ASCII OFFSET
- CPI 4 ;GREATER THAN 4?
- JNC SOURCE$DRIVE ;YES, TRY AGAIN
- DEST$DRIVE:
- PRINT <CR,LF,'Enter DESTINATION drive (A, B, C or D) - '>
- CALL GET$CONSOLE ;GET CONSOLE INPUT
- STA DEST
- SUI 'A' ;REMOVE ASCII OFFSET
- CPI 4
- JNC DEST$DRIVE
- COMMENCE:
- LXI SP,STACK$TOP ;RESET STACK
- PRINT <CR,LF,'Insert SOURCE in '>
- CHAROUT SOURCE
- PRINT <', DEST in '>
- CHAROUT DEST
- PRINT <' and press RETURN to copy.',CR,LF>
- PRINT <' (Press any other key to reset options) - '>
- CALL GET$CONSOLE ;GET CONSOLE INPUT
- CPI ACR ;IS IT A 'RETURN'
- JNZ MENU ;NO, DISPLAY THE MENU
- LDA START$TRACK
- STA CURRENT$TRACK
- DISKIO INITIAL ;RESET THE DISK SYSTEM
- LDA SOURCE ;GET SOURCE DRIVE NO.
- SUI 'A' ;SUBTRACT ASCII OFFSET
- MVI B,0
- MOV C,A ;BC <--- DRIVE NO.
- CALL DJSELDRV
- MVI C,1
- CALL DJTRKSET
- MVI C,1 ;SET UP SECTOR FOR READ
- CALL DJSETSEC
- LXI B,STACK$TOP+1 ;GET FIRST FREE MEMORY LOC.
- CALL DJSETDMA
- CALL DJREAD ;FIRST TIME CLEARS ?????? ON DJ2D
- CALL DJSTATUS ;DITTO
- CALL DJREAD ;THIS TIME ITS FOR REAL
- STATUS1:
- CALL DJSTATUS ;GET DISK DATA
- ANI 0FCH ;DISCARD DRIVE NO. BITS
- MOV C,A ;C <--- STATUS
- LDA DJORG+3FAH ;GET DJ2D 1791 STATUS
- ANI 8 ;MASK OUT SIDE BIT
- XRI 8 ;COMPLEMENT IT
- RLC ;INTO BIT 4
- RLC ;INTO BIT 5
- ORA C ;MERGE WITH PREVIOUS STATUS
- PUSH PSW ;TEMP SAVE SOURCE DISK DATA (TO BE POPPED AS B)
- LDA DEST ;GET DESTINATION DRIVE NO.
- SUI 'A' ;REMOVE ASCII OFFSET
- MOV C,A
- CALL DJSELDRV
- MVI C,1 ;SET UP TRACK FOR READ
- CALL DJTRKSET
- MVI C,1 ;SET UP SECTOR FOR READ
- CALL DJSETSEC
- CALL DJREAD ;FIRST TIME CLEARS ?????? ON DJ2D
- CALL DJSTATUS ;DITTO
- CALL DJREAD ;THIS TIME ITS FOR REAL
- STATUS2:
- CALL DJSTATUS ;GET DISK DATA
- ANI 0FCH ;DISCARD DRIVE NO. BITS
- MOV C,A ;C <--- STATUS
- LDA DJORG+3FAH ;GET DJ2D 1791 STATUS
- ANI 8 ;MASK OUT SIDE BIT
- XRI 8 ;COMPLEMENT IT
- RLC ;INTO BIT 4
- RLC ;INTO BIT 5
- ORA C ;MERGE WITH PREVIOUS STATUS
- POP B ;RESTORE SOURCE DISK DATA (PUSHED AS PSW)
- STATUS$CHECK:
- CMP B ;DISK DATA SAME FOR BOTH DRIVES?
- JNZ FORMAT$ERROR ;NO, ERROR
- ANI 00CH ;MASK OUT SECTOR SIZE BITS
- STA SEC$BITS
- MOV A,B ;A <--- DISK DATA
- ANI 020H ;MASK OUT SIDE BIT
- CNZ MERGE ;MERGE SIDE BITS WITH SECTOR BITS
- LDA SEC$BITS
- LXI H,SECTOR$LENGTH$TB
- MVI D,0 ;FORM OFFSET
- MOV E,A
- DAD D ;ADD OFFSET
- MOV E,M ;GET LOW BYTE OF SEC$LENGTH
- INX H
- MOV D,M ;GET HIGH BYTE OF SEC$LENGTH
- INX H
- MOV A,M ;GET LOW BYTE OF SPT
- INX H
- MOV H,M ;GET HIGH BYTE OF SPT
- MOV L,A ;FORM VALUE
- SHLD SPT ;SAVE SECTORS/TRACK
- SDED SEC$LENGTH ;SAVE SECTOR LENGTH
- LXI H,0
- SIZE$LOOP:
- DAD D ;ADD 1 SECTOR LENGTH
- DCR A ;ADJUST SECTOR COUNT
- JNZ SIZE$LOOP
- SHLD BUFFER$SIZE
- XCHG ;DE <--- BUFFER SIZE
- LXI H,STACK$TOP+1 ;GET FIRST FREE MEMORY LOC.
- SHLD TRACK$BUFFER
- DAD D ;FORM ADDRESS OF VERIFY BUFFER
- SHLD VERIFY$BUFFER
- DAD D ;FORM ADDRESS OF TOP OF BUFFER
- SHLD BUFFER$TOP
- XCHG ;DE <--- BUFFER TOP
- LHLD BDOS+1 ;GET BDOS BASE ADDRESS
- DSUB ;ENOUGH MEMORY FOR BUFFERS?
- JC OUT$OF$MEMORY ;NO, ERROR
- LDA SEC$BITS ;YES, GET DISK DATA
- ANI 010H ;MASK OUT DOUBLE SIDED BIT
- JZ SIDE$FLAG
- LDA SPT ;GET SECTORS/TRACK
- RRC ;DIVIDE BY 2
- PUSH PSW
- ORI 080H ;SET SIDE 1 BIT
- STA SPT ;SAVE NEW LAST SECTOR NO.
- POP PSW
- INR A
-
- SIDE$FLAG:
- STA SIDE$ONE ;SIDE CHANGE SECTOR NO.
- PRINT <CR,LF,LF,'Copy in progress - '>
- PRINT <'Control C to abort',CR,LF>
- CALL COPY ;DO THE COPY
- PRINT <CR,LF,'Copy complete - '>
- LDA ERRORS ;CHECK FOR ERRORS
- ORA A
- JNZ ERROR$MESSG
- PRINT <'NO errors were detected.'>
- JMP COPY$AGAIN
- ;
- MERGE:
- RRC ;ROTATE SIDE BIT INTO POSITION
- MOV B,A ;B <--- SIDE BIT
- LDA SEC$BITS ;GET SECTOR BITS
- ORA B ;MERGE THEM
- STA SEC$BITS ;KEEP STACK RIGHT
- RET
- ;
- ERROR$MESSG:
- PRINT <'Errors detected. *** ERRORS ***',BEL>
- ;
- COPY$AGAIN:
- PRINT <CR,LF,LF,'Press RETURN to copy again or'>
- PRINT <CR,LF,'any other key to reset options. - '>
- CALL GET$CONSOLE ;GET CONSOLE INPUT
- CPI ACR
- JZ COMMENCE
- JMP MENU
- ;
- FORMAT$ERROR:
- PRINT <CR,LF,LF,BEL>
- PRINT 'Destination disk is NOT the same'
- PRINT <' format as Source disk.',CR,LF>
- PRINT 'BOTH disks MUST be the same format.'
- PRINT <CR,LF,LF,'Press any key to reset options. - '>
- CALL GET$CONSOLE
- JMP MENU
- ;
- DEFAULT:
- MVI A,'A' ;DEFAULT TO A DRIVE
- STA SOURCE
- INR A ; AND B DRIVE
- STA DEST
- JMP COMMENCE
- ;
- COPY:
- XRA A ;RESET ERROR FLAG
- STA ERRORS
- CALL FIRST$TIME ;INITIALISE TRACK PARAMETERS
- COPY$LOOP:
- CALL ABORT$CHECK ;WANT TO QUIT?
- LDA SOURCE ;GET SOURCE DRIVE NO.
- SUI 'A' ;REMOVE ASCII OFFSET
- CALL SETUP$TRACK ;SET UP INITIAL PARAMETERS
- LHLD TRACK$BUFFER
- CALL READ$A$TRACK
- CALL CHECK$EMPTY ;CHECK IF E5 TRACK
- RC ;CARRY SET IF E5 TRACK
- CALL ABORT$CHECK ;CHECK FOR QUIT BEFORE BDOS SWALLOWS ANY
- ; WAITING CHARACTER DURING CONSOLE OUTPUT
- PRINT '*' ;DISPLAY TRACK DONE MARKER
- MVI A,5 ;NUMBER OF RETRIES
- STA RETRIES
- TRY$WRITE:
- LXI H,RETRIES ;GET REMAINING RETRIES
- DCR M ;ADJUST IT
- JM LAST$TRY
- LDA DEST ;GET DESTINATION DRIVE NO.
- SUI 'A' ;REMOVE ASCII OFFSET
- CALL SETUP$TRACK
- LHLD TRACK$BUFFER
- CALL WRITE$A$TRACK
- LDA DEST ;GET DESTINATION DRIVE IDENT
- SUI 'A' ;REMOVE ASCII OFFSET
- CALL SETUP$TRACK
- LHLD VERIFY$BUFFER
- CALL READ$A$TRACK
- CALL VERIFY
- JC TRY$WRITE ;CARRY SET MEANS RETRY
- LAST$TRY:
- LXI H,CURRENT$TRACK
- INR M ;ADJUST IT
- LDA LAST$TRACK
- CMP M ;LAST TRACK?
- JNZ COPY$LOOP ;NO, COPY ANOTHER
- RET
- ;
- READ$A$TRACK:
- LXI B,1 ;SET START SECTOR NO.
- READ$TRACK:
- PUSH B ;SAVE START SECTOR NO.
- PUSH H ;SAVE CURRENT DMA ADDRESS
- MVI A,1FH
- ANA C ;MASK OF HIGH BITS
- MOV C,A ;C <--- MASKED SECTOR
- CALL DJSETSEC ;SET THE SECTOR
- POP B ;BC <--- DMA ADDRESS
- PUSH B ;SAVE IT AGAIN
- CALL DJSETDMA
- MVI B,5 ;RETRY COUNT
- READ$RETRY:
- DCR B
- JM READ$PARAM ;FINISHED RETRIES?
- PUSH B ;NO, SAVE COUNT
- CALL DJREAD ;READ A SECTOR
- POP B ;RESTORE RETRY COUNT
- JC READ$RETRY ;READ ERROR, TRY AGAIN
- READ$PARAM:
- POP H ;GET CURENT DMA ADDRESS
- LDED SEC$SIZE ;GET SECTOR LENGTH
- DAD D ;FORM NEW DMA ADDRESS
- POP B ;GET SECTOR NO.
- CNZ READ$ERROR ;READ ERROR MESSAGE
- INX B ;ADJUST SECTOR NO.
- LDA SECTORS ;GET MAX NO SECTORS
- INR A
- CMP C ;DONE LAST SECTOR
- RZ ;YES
- LDA OTHER$SIDE
- CMP C ;TIME TO CHANGE SIDES?
- JNZ READ$TRACK ;NO, DO ANOTHER SECTOR
- MVI C,1
- CALL DJSETSID ;SELECT SIDE 1
- LXI B,081H ;SET SECTOR 1 ON SIDE 1
- JMP READ$TRACK
- ;
- CHECK$EMPTY:
- LDA COMMAND ;GET CURRENT COMMAND
- CPI 'N' ;FILES UNTIL E5 TRACK?
- JZ SETUP$E5 ;YES, TEST FOR EMPTY TRACK
- CPI 'M' ;ALL UNTIL E5 TRACK?
- JNZ RESET$CARRY ;NO,FORCE COPY TILL END
- SETUP$E5:
- LDA CURRENT$TRACK ;TRACK NUMBER
- CPI 2 ;DON'T TEST TRACKS 0 & 1
- JC RESET$CARRY ;RESET CARRY FLAG
- LHLD BUFFER$SIZE
- PUSH H
- POP B ;BC <--- NO BYTES TO CHECK
- LHLD TRACK$BUFFER
- TEST$E5:
- MOV A,M ;GET A BYTE FROM TRACK BUFFER
- CPI 0E5H ;DATA FILLER?
- JNZ RESET$CARRY ;RESET FLAG
- INX H ;POINT TO NEXT BYTE
- DCX B ;ADJUST CONTROL COUNTER
- MOV A,B ;FINISHED LOOP YET?
- ORA C
- JNZ TEST$E5 ;NO, DO IT AGAIN
- STC ;SET CARRY AS A FLAG
- RET
- ;
- RESET$CARRY:
- STC ;DEFINE CARRY STATUS
- CMC ;COMPLEMENT IT
- RET
- ;
- WRITE$A$TRACK:
- LXI B,1 ;SET UP SECTOR NO.
- WRITE$TRACK:
- PUSH B ;SAVE SECTOR NO.
- PUSH H ;SAVE DMA ADDRESS
- MVI A,1FH ;1AH IS MAX NO. SECTORS ON ANY FORMAT
- ANA C ;MASK OF HIGH BITS
- MOV C,A ;C <--- MASKED SECTOR
- CALL DJSETSEC ;NEXT SECTOR TO WRITE
- POP B ;BC <--- DMA ADDRESS
- PUSH B ;SAVE IT AGAIN
- CALL DJSETDMA ;NEXT ADDRESS TO WRITE FROM
- MVI B,5 ;RETRY COUNTER
- WRITE$RETRY:
- DCR B ;ADJUST RETRY COUNT
- JM WRITE$PARAM ;FINISHED RETRIES?
- PUSH B ;SAVE RETRY COUNT
- CALL DJWRITE ;WRITE THE SECTOR
- POP B ;RESTORE RETRY COUNT
- JC WRITE$RETRY ;YES, TRY AGAIN
- WRITE$PARAM:
- POP H ;GET CURRENT DMA ADDRESS
- LDED SEC$SIZE ;GET SECTOR LENGTH
- DAD D ;FORM NEW DMA ADDRESS
- POP B ;GET LAST SECTOR DONE NO.
- CNZ WRITE$ERROR ;MESSAGE IF WRITE ERROR
- INX B ;ADJUST SECTOR NO.
- LDA SECTORS ;GET MAX NO. SECTORS
- INR A
- CMP C ;DONE LAST SECTOR?
- RZ ;YES
- LDA OTHER$SIDE
- CMP C ;TIME TO CHANGE SIDES?
- JNZ WRITE$TRACK ;NO, DO ANOTHER SECTOR
- MVI C,1
- CALL DJSETSID ;SELECT SIDE 1
- LXI B,081H ;SET SECTOR 1 ON SIDE 1
- JMP WRITE$TRACK
- ;
- SETUP$TRACK:
- STA DRIVE$NO ;SAVE DRIVE NO.
- MOV C,A
- CALL DJSELDRV ;SELECT THE DRIVE
- LDA CURRENT$TRACK
- MOV C,A
- CALL DJTRKSET ;SET THE TRACK
- LXI B,0
- CALL DJSETSID ;SET THE SIDE
- LDA CURRENT$TRACK
- ORA A ;TRACK 0?
- JZ TRACK$0
- CPI 1 ;TRACK 1?
- RNZ ;NO
- ;YES, RESET PARAMETERS
- FIRST$TIME:
- LHLD SPT ;SECTORS/TRACK
- SHLD SECTORS
- LHLD SEC$LENGTH ;BYTES/SECTOR
- SHLD SEC$SIZE
- LDA SIDE$ONE ;SECTOR NO. TO CHANGE SIDES
- STA OTHER$SIDE
- RET
- ;
- TRACK$0:
- LXI H,26 ;26 SECTORS/TRACK
- SHLD SECTORS
- LXI H,128 ;128 BYTES/SECTOR
- SHLD SEC$SIZE
- MVI A,0 ;FORCE SINGLE SIDED
- STA OTHER$SIDE
- RET
- ;
- VERIFY:
- XRA A
- STA ESECTOR ;RESET ERROR SECTOR
- LHLD TRACK$BUFFER ;POINT TO BASE OF DATA WRITTEN
- LDED VERIFY$BUFFER ;POINT TO BASE OF DATA READ
- LDA CURRENT$TRACK
- ORA A ;TRACK 0?
- LXI B,26*128 ;TRACK 0 PARAMETERS ARE FIXED
- JZ SINGLE2 ;YES
- PUSH H
- LHLD BUFFER$SIZE
- PUSH H
- POP B ;BC <--- NO. OF BYTES TO CHECK:
- POP H
- SINGLE2:
- LDAX D ;GET A WRITTEN BYTE
- CMP M ;GET A READ BYTE
- JZ NEXT$COMPARE ;IF THE SAME GET NEXT PAIR
- LDA RETRIES ;GET NO RETRIES LEFT
- ORA A ;ANY LEFT?
- STC ;SET CARRY AS RETRY FLAG
- RNZ ;YES, RETRY TRACK
- CALL COMPARE$ERROR ;NO, HARD ERROR
- NEXT$COMPARE:
- INX H ;POINT TO NEXT WRITTEN BYTE
- INX D ;POINT TO NEXT READ BYTE
- DCX B ;ADJUST NUMBER DONE COUNT
- MOV A,C ;FINISHED?
- ORA B
- JNZ SINGLE2 ;NO, COMPARE BYTES
- RET
- ;
- COMPARE$ERROR:
- PUSH H ;SAVE WRITTEN DATA LOC.
- PUSH D ;SAVE READ DATA LOC.
- MVI A,0
- STA SECTOR$COUNT
- SECTOR$LOOP:
- LDED SEC$SIZE ;NO. BYTES IN A SECTOR
- DSUB ;SUBTRACT SECTOR FROM ERROR LOC.
- LDA SECTOR$COUNT
- INR A ;ADJUST SECTOR COUNT
- STA SECTOR$COUNT
- LDED TRACK$BUFFER
- CPHL ;COMPARE TO BASE OF BUFFER
- JNC SECTOR$LOOP ;FINISHED WHEN GONE MINUS
- LDA SECTOR$COUNT
- MOV C,A ;BC <--- SECTOR NO.
- MVI B,0
- PUSH B ;SAVE ERROR SECTOR
- PRINT <CR,LF,'Compare'>
- JMP ERROR$END
- ;
- READ$ERROR:
- SAVE H,D,B
- PRINT <CR,LF,'Read'>
- JMP ERROR$END
- ;
- WRITE$ERROR:
- SAVE H,D,B
- PRINT <CR,LF,'Write'>
- ;
- ERROR$END:
- PRINT ' error at Track '
- DECOUT CURRENT$TRACK
- PRINT ', Physical Sector '
- POP H ;HL <--- SECTOR NO.
- PUSH H ;SAVE IT AGAIN
- MOV A,L ;A <--- SECTOR NO.
- ANI 080H ;MASK OUT DOUBLE SIDED BIT
- JZ ONE$SIDE
- LDA SIDE$ONE ;GET SECTORS ON (SIDE 0) + 1
- DCR A ;NO. SECTORS ON SIDE ZERO
- ADD L ;A <--- NO. OF BAD SECTOR
- ANI 07FH ;MASK OFF BIT 7
- MOV L,A ;HL <--- NO BAD SECTOR
- ONE$SIDE:
- DECOUT
- PRINT ', on Drive '
- LDA DRIVE$NO
- ADI 'A'
- CHAROUT
- PRINT <BEL,' '>
- MVI A,0FFH ;SET ERROR FLAG
- STA ERRORS
- CALL ABORT$CHECK
- NO$ERROR:
- RESTORE B,D,H
- RET
- ;
- GET$CONSOLE:
- CHARIN ;GET A CHARACTER
- CPI 'B' ;MAKE INTO UPPER CASE
- RC
- CPI '{'
- RNC
- ANI '_'
- RET
- ;
- ABORT$CHECK:
- CALLBIOS DSTAT ;CHECK IF KEY PRESSED
- ORA A
- RZ
- CALLBIOS DCONIN
- CPI CNTRL$C
- RNZ
- PRINT <CR,LF,BEL,'^C ABORT'>
- CHARSTAT ;SEE IF ^C GOT INTO BDOS
- JZ MENU ;NO
- CHARIN ;YES, DISCARD IT
- JMP MENU
- ;
-
- OUT$OF$MEMORY:
- PRINT <BEL,CR,LF,LF,' TRACK BUFFER OVERFLOW',CR,LF,LF>
- PRINT <'Your present CP/M system does not have enough memory'>
- PRINT <CR,LF,'in the Transient Program Area for copying disks'>
- PRINT <CR,LF,'in the format you are trying to copy.'>
- PRINT <BEL,CR,LF,LF,'You need at least a '>
- LHLD BUFFER$TOP ;GET SIZE OF BUFFERS
- LXI D,FDOS$SIZE ;GET SIZE OF BDOS+BIOS
- DAD D ;MINIMUM SYSTEM SIZE IN BYTES
- MOV A,H ;GET PAGE NO.
- RRC ;DIVIDE BY 4 TO GET KBYTES
- RRC
- ANI 03FH
- INR A ;ADD AN EXTRA KBYTE
- MVI H,0
- MOV L,A
- DECOUT ;DISPLAY THE SYSTEM SIZE
- PRINT <'K system to copy this disk.'>
- PRINT <CR,LF,LF,'Insert a disk which has DJ2D CP/M system on it'>
- PRINT <CR,LF,'into the A: drive, then press any key to exit to CP/M'>
- WAITLP:
- DIRIN ;SET UP FOR DIRECT CONSOLE READ
- ORA A ;ANY KEY PRESSED?
- JZ WAITLP ;NO, WAIT UNTIL ONE IS PRESSED
- PRINT <CR,LF,LF,'Warm booting CP/M'>
- JMP WBOOT
- ;
- WRONG$VERSION:
- PRINT <'Sorry, you need CP/M Version 2.2 or later',CR,LF>
- PRINT <'and a Morrow Designs Disk Jockey 2D Controller'>
- PRINT <CR,LF,'to run this disk copy utility.'>
- RET ;BACK TO CP/M
- ;
- SECTOR$LENGTH$TB:
- DW 128 ;1S/1D/128
- DW 26
- DW 256 ;1S/2D/256
- DW 26
- DW 512 ;1S/2D/512
- DW 15
- DW 1024 ;1S/2D/1024
- DW 8
- DW 128 ;2S/1D/128
- DW 52
- DW 256 ;2S/2D/256
- DW 52
- DW 512 ;2S/2D/512
- DW 30
- DW 1024 ;2S/2D/1024
- DW 16
- ;
- CURRENT$TRACK:
- DW 0
- START$TRACK:
- DB 0
- LAST$TRACK:
- DB 0
- ESECTOR:
- DB 0
- SECTOR$COUNT:
- DB 0
- ERRORS: DB 0
- RETRIES:
- DB 0
- DRIVE$NO:
- DB 0
- COMMAND:
- DB 0
- SIDE$ONE:
- DB 0 ;1ST SECTOR ON SIDE ONE + 1
- OTHER$SIDE:
- DB 0 ;SECTOR NO. TO CHANGE SIDES
- SEC$BITS:
- DB 0 ;SECTOR SIZE BITS
- SEC$LENGTH:
- DW 00 ;FORMATED BYTES/SECTOR
- SEC$SIZE:
- DW 00 ;SEC$LENGTH
- TRACKS: DW 77 ;NO TRACKS PER DISK
- SOURCE: DW 00
- DEST: DW 00
- BADSEC: DW 00
- SPT: DW 00 ;FORMATTED SECTORS/TRACK
- SECTORS:
- DW 00 ;SECTORS/TRACK
- BUFFER$SIZE:
- DW 00
- TRACK$BUFFER:
- DW 00 ;LOCATION OF TRACK BUFFER
- VERIFY$BUFFER:
- DW 00 ;LOCATION OF VERIFY BUFFER
- BUFFER$TOP:
- DW 00 ;LOCATION OF TOP OF BUFFERS
- ;
- ; AN INITIALISED STACK MAKES DEBUGGING EASIER
- ;
- DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
- ;
- STACK$TOP EQU $
- ;
- END BEGIN
-