home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************
- ;* *
- ;* CP/M FILE DUMP UTILITY *
- ;* DUAL DENSITY VERSION *
- ;* *
- ;****************************************************************
- ;
- ; History : Originally published through CPMUG as
- ; version 1.2 by Sam SINGER
- ;
- ; Updated to version 1.3 through CPMUG
- ; by Sam SINGER
- ;
- ; Updated to version 1.4 by Dave Hatch
- ; and published by GED
- ;
- ; FEB 1,1980 Revised and extended to version 1.5
- ; for double density with static density
- ; allocation (two sector sizes) for CP/M
- ; 1.4 by Bill Bolton and published by 80AT
- ;
- ; JULY 11,1980 Revised and extended to version 2.0
- ; for double density with dynamic density
- ; allocation (four sector sizes) for CP/M
- ; 2.2 by Bill Bolton and published by 80AT
- ;
- ; JULY 23,1980 Minor bugs exterminated and version updated
- ; to 2.1
- ;
- ; AUGUST 26,1980 Sector translation for all disk operations
- ; and reserved track offset in block dump
- ; routine added, version updated to 2.2
- ;
- ; OCT 23,1980 Bugs in the DIR and GRP2 routines which
- ; showed up when tried on an Morrow HDCA-3
- ; were eliminated. Conditional assembly for
- ; hard disk added. Flag for sector display
- ; header and track 0 added.
- ;
- ; FEB 10, 1981 Macro library changed to MACRO3 and DJORG
- ; equate added for easier DJ2D address change,
- ; version updated to 2.3A
- ;
- ; FEB 11, 1981 Two sided status check changed to direct
- ; check on 1791 controller as Model DJ2Ds
- ; do not return a side bit in the disk status
- ; firmware call. Version updated to 2.4
- ;
- ; NOV 25, 1981 Modified for use with Godbout Disk 1 and
- ; Morrow HDCA-3 controller, all track number
- ; references changed to 16 bit values. Version
- ; updated to 2.5
- ;
- ; --- DDH ---
- ;
- TITLE 'Disk 1 + HDCA-3 Disk Dump DDH Ver 2.5'
- ;
- TRUE EQU 0FFH
- FALSE EQU 0
- ;
- HARD EQU TRUE ;TRUE FOR MORROW HARD DISK
- FIRST EQU TRUE ;TRUE FOR MORROW HARD DISK A,B,C
- ; & FLOPPY DISKS D,E,F,G
- ; FALSE FOR FLOPPY DISKS A,B,C,D
- ; & MORROW HARD DISK E,F,G
- ;
- FCB EQU 0005CH ;CP/M FILE CONTROL BLOCK LOC.
- WBOOT EQU 00000H ;CP/M WARM BOOT ENTRY LOC.
- BDOS EQU 00005H ;CP/M BDOS ENTRY LOC.
- ST$OFFSET EQU 01EH ;Offset to set track routine in BIOS
- ;
- MACLIB MACRO3 ;INCLUDE MACRO LIBRARY
- ;
- ORG 100H ;SET PROG START
- ;
- BEGIN:
- LXI H,0
- DAD SP ;GET STACK POINTER
- SHLD OLDSTK
- LXI SP,NEWSTK ;SET UP NEW STACK
- DISKIO ?DRIVE ;GET CURRENTLY LOGGED DRIVE NO
- STA DRVNO ;SAVE FOR EXIT
- STA NEWDRV ;ALSO SAVE IN NEW DRIVE NO
- MVI C,12 ;FIRST, CHECK VERSION NUMBER
- CALL BDOS
- MOV A,L ;A <--- VERSION NO.
- CPI 20H ;VERSION 2.0 OR LATER?
- JC VERSION$ERROR ;NO, ERROR MESSAGE
- CALL DISKDATA ;GET DISK PARAMETERS
- LDA 81H ;CONSOLE INPUT ALREADY HERE ?
- ORA A
- JZ SIGNON ;BUFFER EMPTY, INPUT FROM CONSOLE
- LDA 80H ;GET NO OF CHAR INPUT
- ORI 80H ;ADD 128
- MOV L,A ;TO L
- XRA A ;ZERO
- MOV H,A ;HL CONTAINS ADDR OF END OF BUFFER
- ZBFF:
- INR L
- JZ START ;REMAINDER OF BUFFER ZEROED
- MOV M,A
- JMP ZBFF ;LOOP
- SIGNON:
- PRINT <CR,LF,'CP/M Disk Dump Utility VERS 2.5',CR,LF,LF>
- PRINT <'Copyright (C) 1978 By Sam Singer',CR,LF>
- PRINT <'Copyright (C) 1980 By Bill Bolton',CR,LF,LF>
- PRINT <'For Godbout Disk 1 Controller',CR,LF>
-
- IF HARD
- PRINT <'and Morrow HDCA-3 Hard Disk Controller',CR,LF>
- ENDIF
-
- IF HARD AND FIRST
- PRINT <'Hard Disk Logical Drives A,B,C',CR,LF>
- PRINT <'Floppy Drives D,E,F,G',CR,LF>
- ELSE
- PRINT <'Floppy Drives A,B,C,D,',CR,LF>
- ENDIF
-
- IF HARD AND NOT FIRST
- PRINT <'Hard Disk Logical Drives E,F,G',CR,LF>
- ENDIF
-
- NEWIN:
- PRINT <CR,LF,'*'>
- MVI A,0FFH ;SET SWITCH TO RETURN HERE AGAIN
- STA INFLAG
- LXI SP,NEWSTK ;RESET STACK POINTER
- LXI H,0
- SHLD LINE ;SET LINE COUNT TO ZERO
- FILL 80H,0FFH ;ZERO INPUT BUFFER
- INPUT 80H ;READ FILE NAME
- ;
- ; SELECT DISK DRIVE AND SET UP FILE CONTROL BLOCK
- ;
- START:
- FILL FCB,FCB+32 ;ZERO FILE CONTROL BLOCK
- MATCH 82H,'A:' ;DRIVE A
- JZ ADISK
- MATCH 82H,'B:' ;DRIVE B
- JZ BDISK
- MATCH 82H,'C:' ;DRIVE C
- JZ CDISK
- MATCH 82H,'D:' ;DRIVE D
- JZ DDISK
- MATCH 82H,'E:' ;DRIVE E
- JZ EDISK
- MATCH 82H,'F:' ;DRIVE F
- JZ FDISK
- MATCH 82H,'G:' ;DRIVE G
- JZ GDISK
- JMP GETNAM ;NO DRIVE SPECIFIED
- ;
- ADISK:
- XRA A ;SELECT DRIVE A
- JMP SETDRV
- ;
- BDISK:
- MVI A,1 ;SELECT DRIVE B
- JMP SETDRV
- ;
- CDISK:
- MVI A,2 ;SELECT DRIVE C
- JMP SETDRV
- ;
- DDISK:
- MVI A,3 ;SELECT DRIVE D
- JMP SETDRV
- ;
- EDISK:
- MVI A,4 ;SELECT DRIVE E
- JMP SETDRV
- ;
- FDISK:
- MVI A,5 ;SELECT DRIVE F
- JMP SETDRV
- ;
- GDISK:
- MVI A,6 ;SELECT DRIVE G
- SETDRV:
- STA NEWDRV ;STORE THE SELECTED DRIVE
- CALL DISKDATA ;GET DISK PARAMETERS
- MOVE 82H,80H,40H ;SHIFT BUFFER DOWN TWO BYTES
- ;
- ; SEARCH FOR DIRECT READ OF TRACK AND SECTOR OR VALIDATE
- ;
- GETNAM:
- INSTR 82H,40H,'GROUP'
- JC GROUP ;DISPLAY CPM ALLOCATION GROUP
- INSTR 82H,40H,'G ' ;SEARCH FOR 'G'
- JC GROUP ;DISPLAY GROUP
- INSTR 82H,40H,'MAP' ;ALLOCATION MAP
- JC MAP ;DISPLAY GROUP ALLOCATION MAP
- INSTR 82H,40H,'DIR' ;DIRECTORY REQUEST
- JC DIR ;DISPLAY DIRECTORY
- INSTR 82H,40H,'TRACK' ;SEARCH FOR TRACK
- JC TRK1
- INSTR 82H,40H,'T ' ;SEARCH FOR 'T'
- JNC FILNAM ;NO TRACK GO TO READ FILE
- TRK1:
- SCAN ;FIND AND CONVERT NUMBER
- DECIN
- JC INERR ;INPUT ERROR ON CARRY
- LXI D,0
- SHLD TRACK ;SAVE TRACK NO.
- CPHL ;TRACK 0?
- JNZ SECSCH ;NO, CONTINUE
- LDA HARD$D ;ON HARD DISK?
- ORA A
- JNZ SECSCH ;YES, TRACK 0 SAME AS OTHERS
- MVI A,TRUE ;NO, SET A FLAG
- STA TK0FLAG ; FOR TRACK 0
- SECSCH:
- INSTR 82H,40H,'SECTOR';SEARCH FOR SECTOR
- JC SEC1
- INSTR 82H,40H,'S ' ;TRY 'S'
- JNC WHLTRK ;DUMP ENTIRE TRACK
- SEC1:
- SCAN
- DECIN
- JC INERR ;INPUT ERROR ON CARRY
- SHLD BSEC ;BEGINNING SECTOR
- SHLD ESEC ;SAVE IN END SECTOR ALSO
- XCHG ;SET BUFFER POINTER FOR SCAN
- SHLD IPOINT ;SAVE BUFFER POINTER FOR EDIT
- INSTR ,40H,'-' ;SEARCH FOR '-'
- JNC EDIT ;CHECK FOR EDIT OF SECTOR
- SCAN
- DECIN ;SCAN AND CONVERT ANOTHER NO
- JC INERR ;ERROR IF CARRY SET
- SHLD ESEC ;SAVE IN END SECTOR
- PUSH H
- LHLD BSEC
- XCHG ;DE <--- START SECTOR NO.
- POP H ;HL <--- END SECTOR NO.
- CPHL ;COMPARE BEGIN AND END
- JP DOREAD ;OK IF END>=BEGIN
- SHLD BSEC ;OTHERWISE SWITCH THEM
- XCHG ;HL <--- NEW END SECTOR
- SHLD ESEC
- DOREAD:
- CALL RDISK ;READ DIRECT
- JMP ENDFIL ;BACK FOR MORE INPUT
- ;
- EDIT:
- LHLD IPOINT ;RESET BUFFER POINTER
- INSTR ,40H,'EDIT' ;CHECK EDIT FUNCTION
- JNC DOREAD ;GO TO DISPLAY SECTOR
- CALL RDISK ;DISPLAY SECTOR
- EDIT1:
- PRINT <CR,LF,'EDIT - '>
- FILL INBUF,INBUF+9
- INPUT INBUF,6 ;INPUT MAXIMUM 6 CHAR
- INSTR INBUF,8,'WRITE' ;WRITE EDITED SECTOR ON DISK?
- JC WRTDSK ;WRITE BUFFER BACK ON DISK
- INSTR INBUF,8,'STOP' ;STOP EDITING WITHOUT WRITING?
- JC ENDFIL ;EXIT
- HEXIN INBUF+2 ;CONV ASCII TO HEX
- JNC CKLIM ;IF NO ERROR, CHECK ADDR
- LDAX D ;GET ASCII CHAR
- CPI '.' ;CHECK FOR EXIT CHAR
- JZ EDIT3 ;BACK FOR MORE EDITING
- JMP ADERR ;ADDRESS ERROR
- CKLIM:
- LXI D,0080H ;CHECK ADDR LIMIT
- CPHL
- JP ADERR ;ADDRESS ERROR
- SHLD IPOINT ;SAVE ADDRESS
- PRINT CRLF,$
- PTX:
- HEXOUT IPOINT+1
- HEXOUT IPOINT ;ECHO THE ADDRESS
- PRINT SPACE,$
- LHLD IPOINT ;ECHO PRESENT CONTENTS
- LXI D,080H
- DAD D ;COMPUTE MEMORY ADDR
- MOV A,M ;GET BYTE FROM MEMORY
- HEXOUT
- PRINT SPACE,$
- FILL INBUF,INBUF+5 ;ZERO INPUT BUFFER
- INPUT INBUF,4 ;INPUT 4 CHAR MAX
- HEXIN INBUF+2 ;CONVERT
- JNC EDIT2 ;HEX CHAR
- LDAX D ;GET ASCII CHAR
- CPI '.' ;PERIOD ENDS INPUT
- JZ EDIT3 ;BACK FOR MORE EDITING
- JMP HEXERR ;ERROR NOT HEX CHAR
- EDIT2:
- LDA INBUF+1 ;LOAD NO OF CHAR TYPED
- ORA A
- JZ EDITX ;NO REPLACEMENT IF JUST CR
- MOV A,L ;CONVERTED CHAR BACK TO A
- LHLD IPOINT ;LOAD MEMORY BUFFER POINTER
- LXI D,080H ;OFFSET
- DAD D ;CALC MEMORY ADDR
- MOV M,A ;STORE NEW INPUT TO MEMORY
- EDITX:
- PRINT CRLF,$
- LDA IPOINT ;LEAST SIGNIFICANT HALF OF ADDR
- INR A ;INCR BY ONE
- ANI 7FH ;COUNT MOD 128
- STA IPOINT
- JMP PTX ;INPUT MORE DATA
- EDIT3:
- LXI H,0
- SHLD LINE ;RESET LINE NO TO ZERO
- CALL PRTSEC ;PRINT BUFFER WITH HEADING
- JMP EDIT1 ;BACK FOR ADDITIONAL EDITING
- ;
- WRTDSK:
- LDA TK0FLAG ;ON TRACK 0 ?
- ORA A
- ; JNZ WRITE$0 ;YES, NEEDS SPECIAL TREATMENT
- CALLBIOS DWRITE ;WRITE BUFFER BACK ON DISK
- JMP ENDFIL ;EXIT
- ;
- WRITE$0:
- JMP ENDFIL
- ;
- ; READ TRACK AND SECTOR DIRECT
- ;
- RDISK:
- CALL SETUP
- RDISK1:
- LDED BSEC ;GET NEXT SECTOR TO READ
- LDA HARD$D
- ORA A ;HARD DISK?
- JNZ RDISK2 ;TRACK 0 SAME AS OTHERS
- LDA TK0$FLAG
- ORA A ;TRACK 0 NEEDS SPECIAL TREATMENT
- JNZ READ$0
- RDISK2:
- LHLD SPT ;GET SECTORS/TRACK FROM DPB
- SHLD SPT$ERR
- CPHL ;SECTOR NO. > SPT?
- JC GO$ON ;YES, ERROR
- MOV A,D
- ORA E ;SECTOR 0?
- JZ BADSEC ;YES, NOT ALLOWED
- LHLD BSEC ;NO, GET SECTOR NO.
- DCR L ;ADJUST FOR SECTRAN
- PUSH H
- POP B ;BC <--- SECTOR NUMBER
- LHLD XLT ;GET SECTOR TABLE ADDRESS
- RDISK3:
- XCHG ;PUT INTO DE
- CALLBIOS DSECTRAN ;GET THE PHYSICAL SECTOR
- ORA A ;RESET CARRY
- PUSH H
- POP B ;BC <--- SECTOR TO READ
- CALLBIOS DSETSEC
- GO$ON:
- JC BADSEC ;WRONG SECTOR NO
- TRK2:
- LHLD TRACK ;GET TRACK NO.
- PUSH H
- POP B
- LXI H,TRK$RET
- PUSH H ;RETURN ADDRESS ONTO STACK
- LHLD WBOOT+1
- MVI L,ST$OFFSET
- PCHL ;WERE OFF TO SEE THE WIZARD
- TRK$RET:
- JC BADTRK ;WRONG TRACK NO
- CALLBIOS DREAD ;READ TRACK AND SECTOR
- JMP PRTSEC
- ;
- READ$0:
- LXI H,26 ;SINGLE DENSITY SECTORS PER TRACK
- SHLD SPT$ERR
- CPHL ;SECTOR NO. TOO BIG?
- JC GO$ON ;YES, ERROR
- MOV A,D
- ORA E ;SECTOR 0?
- JZ BADSEC ;YES, NOT ALLOWED
- LHLD BSEC ;NO, GET SECTOR NUMBER
- DCR L
- PUSH H
- POP B ;BC <--- SECTOR NUMBER
- LXI H,XLT$SD ;TRANSLATE TABLE
- JMP RDISK3
- ;
- ; PRINT DRIVE, TRACK AND SECTOR HEADING
- ;
- PRTSEC:
- LDA NEWDRV ;NEW DRIVE NO
- ADI 41H ;ADD ASCII OFFSET
- PUSH PSW
- PRINT <CR,LF,' Drive '>
- POP PSW
- MOV E,A
- MVI C,2
- CALL BDOS
- PRINT HEADER,$
- PRINT '- Track '
- LHLD TRACK
- DECOUT
- PRINT ' Logical Sector '
- LXI H,0
- LHLD BSEC
- DECOUT
- PRINT ' Dump Count '
- LHLD DCOUNT
- INX H
- SHLD DCOUNT
- DECOUT
- PRINT CRLF,$
- PRINT CRLF,$
- CALL PRTBUF ;PRINT IT
- LDA LINE+1 ;GET HI BYTE OF HEX ADDRESS
- ORA A ;IF NOT 0
- JNZ SECOMP ;DONT ZERO LINE COUNT
- LXI H,0
- SHLD LINE ;RESET HEX ADDRESS COUNT
- SECOMP:
- LHLD ESEC ;END SECTOR NUMBER
- XCHG ;DE <--- END SECTOR
- LHLD BSEC ;SECTOR JUST READ
- CPHL ;COMPARE THEM
- RZ ;EXIT IF THEY ARE EQUAL
- INX H ;BUMP TO NEXT SECTOR
- SHLD BSEC
- JMP RDISK1
- ;
- ; DUMP ENTIRE TRACK IF NO SECTOR INPUT
- ;
- WHLTRK:
- LXI H,1 ;BEGIN SECTOR
- SHLD BSEC ;SAVE IT FOR THIS DUMP
- LDA TK0FLAG
- ORA A ;ON FLOPPY TRACK 0?
- LXI H,26 ;FLOPPY TRACK 0 ALWAYS HAS 26 SECTORS
- JNZ ENDSEC ;YES, SAVE IT IMMEDIATELY
- LHLD SPT ;NO, HIGHEST SECTOR NO. FROM DPB
- ENDSEC:
- SHLD ESEC ;SAVE IT FOR THIS DUMP
- JMP DOREAD ;GO READ IT
- ;
- ; FILL IN FCB FOR NAMED FILE
- ;
- FILNAM:
- MVI A,TRUE
- STA FDFLAG ;SET FILE DUMP FLAG
- FILFCB FCB,82H ;FILL IN FCB NAME FROM INPUT BUFFER
- JC NAMERR ;ERROR IN FILE NAME
- MATCH FCB+9,'COM' ;TEST FOR COM FILE
- JNZ SELDR
- LXI H,100H
- SHLD LINE ;SET LINE NO. TO 100
- SELDR:
- LDA NEWDRV ;SELECT NEW DRIVE
- MOV E,A
- DISKIO LOGIN
- FILSER:
- DISKIO SEARCH,FCB ;LOOK FOR FILE
- ORA A ;FOUND IT?
- PUSH PSW ;SAVE BDOS RETURN INFO
- LDA EXFLAG ;GET EXTENT COUNT
- ORA A ;1ST EXTENT?
- JZ ERR1 ;YES, CHECK FOR FILE NOT FOUND
- POP PSW ;RESTORE BDOS RETURN INFO
- JM ENDFIL ;IF NOT FOUND, BACK FOR MORE INPUT
- JMP RDFILE ;
- ;
- ERR1:
- POP PSW ;RESTORE BDOS RETURN INFO
- JM OPNERR ;IF NOT FOUND, TELL THE USER
- RDFILE:
- RRC
- RRC
- RRC ;SAME AS 5 'ADD A' INSTRUCTIONS
- ANI 60H ;MASK THE BITS OF INTEREST
- ADI 80H ;ADD BASE ADDRESS OF BUFFER
- ADI 0CH ;ADD OFFSET TO EXTENT NO.
- PUSH PSW
- FILL DIRBUF,DIRBUF+21,00 ;INITIALISE BUFFER
- POP PSW
- MOV L,A
- MVI H,0 ;SET UP SOURCE ADDRESS
- LXI D,DIRBUF ;SET UP DESTINATION ADDRESS
- MVI C,20 ;SET UP COUNT
- MVI B,0 ;DITTO
- MOVE ;DO THE MOVE
- LXI H,RCOUNT ;POINT TO RECORD COUNT
- MOV A,M ;GET RECORD COUNT
- CPI 128 ;POSSIBLY ANOTHER EXTENT?
- JNZ NOEXT ;NO, DUMP THE GROUPS
- LDA EXFLAG ;YES, GET EXTENT COUNT
- INR A ;ADD 1 TO IT
- STA EXFLAG ;SAVE IT
- NOEXT:
- PUSH H ;TEMP SAVE H
- LHLD DSM ;GET DSM VALUE
- LXI D,0FF00H ;SET NO. BYTES / GROUP
- DAD D ;IF > 255 THEN TWO BYTES
- POP H
- JC TWO$BYTE
- ONE$BYTE:
- INX H ;BUMP TO NEXT GROUP NO.
- PUSH H
- MOV A,M ;GET THE NEXT GROUP NO.
- CPI 00 ;DONE LAST GROUP?
- JZ QUIT ;YES, CHECK FOR MORE EXTENTS
- MVI H,0
- MOV L,A ;GROUP NO. IN HL
- CALL GROUPS ;DISPLAY THE SECTORS
- POP H
- JMP ONE$BYTE
- ;
- TWO$BYTE:
- MVI A,8 ;GROUP POSITIONS/DIR ENTRY
- STA P$COUNT
- LOOP2:
- INX H ;POINT TO NEXT GROUP NO.
- MOV A,M ;GET LOW BYTE
- INX H
- PUSH H ;SAVE POINTER
- MOV H,M ;GET HI BYTE
- MOV L,A ;FORM GROUP NUMBER
- DJZ QUIT ;QUIT IF EMPTY GROUP POSITION
- CALL GROUPS ;DISPLAY THE SECTORS
- LDA P$COUNT ;CHECK IF LAST GROUP NO.
- DCR A
- JZ QUIT ;YES, CHECK FOR NEXT EXTENT
- STA P$COUNT ;SAVE FOR NEXT LOOP CHECK
- POP H
- JMP LOOP2
- ;
- QUIT:
- POP H ;KEEP STACK CLEAN
- XRA A
- STA SCOUNT ;RESET SECTOR COUNT
- LXI H,FCB+12 ;POINT TO EXTENT NO. IN FCB
- LDA EXFLAG ;GET NEXT EXTENT NO.
- CMP M ;ARE THEY EQUAL
- JZ ENDFIL ;YES, NO MORE EXTENTS SO EXIT
- MOV M,A ;NO, STUFF NEXT EXTENT NUMBER
- JMP FILSER ;LOOK FOR NEXT EXTENT
- ;
- ENDFIL:
- XRA A
- STA TK0FLAG ;RESET TRACK 0 FLAG
- STA EXFLAG ;RESET EXTENT COUNT
- STA FDFLAG ;RESET FILE DUMP FLAG
- STA SCOUNT ;RESET SECTORS DONE COUNT
- STA DCOUNT ;RESET DUMP COUNT LOW BYTE
- STA DCOUNT+1 ; " " " HI BYTE
- LDA INFLAG ;SEE WHERE TO GO
- ORA A
- JZ MONITOR
- JMP NEWIN
- ;
- ;
- ; PRTBUF - PRINT BUFFER IN HEX AND ASCII
- ;
- PRTBUF:
- MVI B,8 ;8 LINES
- LXI H,080H ;INITIAL BUFFER POINTER
- SHLD IPOINT ;STORAGE FOR POINTER
- BPRN:
- LHLD IPOINT ;LOAD POINTER
- MVI C,16 ;CHAR PER LINE
- SAVE B,H ;PROTECT B,H DURING PRINT CALLS
- LDA LINE+1 ;GET HIGH BYTE OF HEX ADDR
- ORA A ;IS IT 00?
- JZ SIMPLE ;YES, PAD 1ST TWO POSITIONS
- HEXOUT LINE+1 ;PRINT HIGH BYTE OF HEX ADDR
- JMP LOWBYT
- SIMPLE:
- PRINT ' ' ;PRINT SPACES INSTEAD OF,
- LOWBYT:
- HEXOUT LINE ;PRINT LOW BYTE OF ADDRESS
- PRINT ' : '
- RESTORE H,B
- PLOOP:
- MOV A,M ;GET A BYTE
- SAVE B,H
- HEXOUT
- PRINT SPACE,$
- RESTORE H,B
- INX H ;INCR MEMORY POINTER
- DCR C ;DECR CHARACTER COUNT
- JZ SKIP ;DONE 16 YET?
- MOV A,C ;NO, SO CONTINUE
- ANI 3 ;TIME FOR SPACE MARKER?
- JNZ PLOOP ;NO, PRINT SOME MORE
- SAVE B,H
- PRINT SPACE,$ ;YES, PRINT SPACE MARKER
- RESTORE H,B
- JMP PLOOP ;PRINT SOME MORE
- SKIP:
- SAVE B
- PRINT SPACE,$
- RESTORE B
- LHLD IPOINT ;RESET POINTER FOR ASCII
- MVI C,10H ;RESET CHAR COUNT
- PLOOP1:
- MOV A,M ;GET A BYTE
- ANI 7FH ;MASK OFF HIGH BIT
- CPI 7FH ;DELETE CODE
- JZ PERIOD ;PRINT PERIOD FOR DELETE
- CPI 20H ;TEST FOR CONTROL CHAR
- JP SKIPX ;SKIP SUBSTITUTION
- PERIOD:
- MVI A,2EH ;ASCII PERIOD
- SKIPX:
- SAVE B,H
- CHAROUT ;PRINT IT SAVE REGS
- RESTORE H,B
- INX H ;INCR MEMORY POINTER
- MOV A,C
- CPI 9 ;CHECK 8 CHAR
- JNZ DECC2
- SAVE B,H
- PRINT SPACE,$
- RESTORE H,B
- DECC2:
- DCR C ;DECR CHAR COUNT
- JNZ PLOOP1 ;PRINT SOME MORE
- SAVE B
- PRINT CRLF,$ ;CARRIAGE RETURN
- CALL PRNCON ;PRINT CONTROL?
- POP B
- INDEX LINE,16 ;INCR LINE NO BY 16
- DCR B ;DECR LINE COUNT
- RZ ;RETURN IF LINE COUNT ZERO
- INDEX IPOINT,16 ;INCR POINTER BY 16
- JMP BPRN ;LOOP BACK
- ;
- ; PRINT CONTROL AND ESCAPE
- ;
- PRNCON:
- MVI C,11
- CALL 5
- ANI 1
- RZ ;RETURN
- CHARIN ;READ CONSOLE
- CPI 3 ;TEST FOR CONTROL C
- JZ ENDFIL ;EXIT IF CONTROL C
- CPI ' ' ;TEST FOR SPACE
- JZ ENDFIL ;ABORT FUNCTION
- RET
- ;
- ; THIS SECTION DISPLAYS A CPM ALLOCATION GROUP
- ;
- GROUP:
- SCAN ;GET THE GROUP NO
- DECIN ;CONVERT TO BINARY
- JC INERR ;INPUT ERROR IF CARRY SET
- CALL GROUPS ;DO THIS GROUP
- JMP ENDFIL ;EXIT
- ;
- GROUPS:
- SHLD G ;SAVE GROUP NO
- XCHG ;DE <--- GROUP NO.
- LHLD DSM ;GET MAX GROUP NO.
- CPHL ;GROUP NO. TOO BIG?
- JC BADGRP ;YES, ERROR MESSAGE
- LXI H,0 ;NO
- SHLD S ;SET SECTOR COUNT TO 0
- GRP1:
- CALL GRPTS ;CONVERT TO TRACK AND SECTOR
- LHLD TRACK ;GET LAST TRACK ACCESSED
- LDED NEW$TRACK ;GET NEXT TRACK TO ACCESS
- CPHL ;SAME TRACK ?
- XCHG
- SHLD TRACK ;STORE TRACK NO.
- CNZ SETUP ;NO, SET UP THE DRIVE
- CALL RDISK1 ;PRINT THE SECTOR
- LDA FDFLAG ;FILE DUMP IN PROGRESS?
- ORA A
- JZ GRP2 ;NO, CONTINUE
- LDA SCOUNT ;GET SECTORS DONE COUNT
- INR A
- STA SCOUNT ;SAVE IT AGAIN
- LXI H,RCOUNT
- CMP M ;HAVE WE DONE ALL THE SECTORS
- RZ ;YES, RETURN
- GRP2:
- LXI H,BLM ;POINT TO (SECTORS/BLOCK)-1
- MOV L,M ;GET (SECTORS/BLOCK)-1
- MVI H,0
- XCHG ;DE <--- " "
- LHLD S ;GET SECTOR COUNT
- CPHL ;DONE LAST SECTOR IN BLOCK?
- RZ ;YES
- INX H ;NO, BUMP SECTOR COUNT
- SHLD S ;SAVE IT
- JMP GRP1 ;PRINT ANOTHER SECTOR
- ;
- ; GRPTS CONVERT CPM GROUP AND SECTOR NUMBER TO TRK AND SEC
- ;
- GRPTS:
- LHLD SPT
- XCHG ;DE <--- SECTORS/TRACK
- LXI H,0
- DSUB ;FORM DIVISOR
- SHLD DIVISOR ;SAVE IT
- LHLD G ;GET GROUP NO.
- LDA BSH ;GET BLOCK SHIFT FACTOR
- SHIFT$LOOP:
- DAD H ;SHIFT LEFT ONE
- DCR A ;ENOUGH SHIFTS ?
- JNZ SHIFT$LOOP ;NO DO IT AGAIN
- PUSH H ;TEMP SAVE HL
- LHLD S ;GET SECTOR NO.
- XCHG ;DE <--- " "
- POP H
- DAD D ;HL NOW HAS G*(BLOCK SIZE)+S
- PUSH H ;TEMP SAVE HL
- LHLD DIVISOR
- XCHG ;DE <--- DIVISOR
- LHLD OFF ;GET NO. OF RESERVED TRACKS
- PUSH H
- POP B ;BC <--- NO. OF RESERVED TRACKS
- POP H ;HL <--- DIVIDEND
- DCX B ;ADJUST FOR LOOP ENTRY
- DIVIDE:
- DAD D ;SUBTRACT DIVISOR
- INX B ;ADJUST TRACK NO.
- JC DIVIDE ;LOOP TILL MINUS
- PUSH H
- PUSH B
- POP H
- SHLD NEW$TRACK ;STORE TRACK NO.
- LHLD SPT ;INDEX INTO TABLE
- XCHG ;DE <--- INDEX
- POP H
- STORE:
- DAD D ;FORM LOGICAL SECTOR NUMBER
- INR L ;ADJUST FOR SECTRAN LATER
- SHLD BSEC ;SAVE IN BEGINNING SECTOR
- SHLD ESEC ;SAVE IN END SECTOR TOO
- RET
- ;
- ; THIS ROUTINE DISPLAYS THE DISK SECTOR ALLOCATION MAP
- ;
- MAP:
- LDA NEWDRV
- MOV E,A
- DISKIO LOGIN ;LOG IN SELECTED DRIVE
- DISKIO ?ALLOC ;GET POINTER TO ALLOCATION MAP
- MOV H,B
- MOV L,A ;HL <--- POINTER TO MAP
- SHLD IPOINT ;SAVE IT
- LXI H,0
- SHLD G ;ZERO COUNT OF UNUSED GROUPS
- PRINT <CR,LF,LF,' '>
- PRINT <'GROUP ALLOCATION MAP - DRIVE '>
- LDA NEWDRV ;NEW DRIVE NO
- ADI 41H ;ADD ASCII OFFSET
- MOV E,A
- MVI C,2
- CALL BDOS
- PRINT <CR,LF,LF>
- XRA A
- LHLD DSM ;GET NO. BLOCKS (GROUPS)
- INX H
- SHLD MAP$COUNT ;SAVE FOR BLOCKS+1
- LXI D,-48 ;48 BITS MAPPED/LINE
- MAP1:
- DAD D ;SUBTRACT A LINE
- INR A ;BUMP LINE COUNT
- JC MAP1
- MOV D,A ;D <--- NO. LINE TO DISPLAY
- LHLD IPOINT ;POINTER TO DISK ALLOCATION MAP
- MAP2:
- MVI C,6 ;WORDS PER LINE
- MAPX:
- SAVE
- PRINT ' '
- RESTORE
- MAP3:
- MVI B,8 ;BITS PER WORD
- MOV A,M ;GET A BYTE FROM ALLOC MAP
- MAP4:
- RAL ;SHIFT LEFT THRU CARRY
- SAVE B,D,H,PSW
- JC MAP5 ;PRINT A ONE
- PRINT '0' ;PRINT A ZERO
- LHLD G ;UNUSED GROUPS
- INX H ;ADD 1
- SHLD G ;STORE IT BACK
- JMP MAP6
- MAP5:
- PRINT '1' ;PRINT A ONE
- MAP6:
- RESTORE PSW,H,D,B
- SAVE PSW,H ;SAVE BIT MAP BYTE
- LHLD MAP$COUNT ;GET BYTES REMAINING
- DCX H
- SHLD MAP$COUNT ;SAVE NEW BYTES LEFT
- DJZ FINISHED ;QUIT IF DONE
- MOV A,B ;BIT COUNT
- CPI 1 ;LAST BIT OF BYTE?
- JZ BITS ;YES
- DCR B
- RESTORE H,PSW
- JMP MAP4
- ;
- BITS:
- RESTORE H
- MOV A,C ;GET WORD COUNT
- CPI 1 ;LAST WORD OF LINE?
- JZ NEW$LINE ;YES
- DCR C ;ADJUST WORD COUNT
- INX H ;BUMP POINTER TO NEXT BYTE
- RESTORE PSW
- JMP MAP3
- ;
- NEW$LINE:
- INX H ;BUMP BYTE POINTER
- SAVE
- PRINT CRLF,$ ;NEXT LINE ON SCREEN
- RESTORE
- RESTORE PSW
- JMP MAP2
- ;
- FINISHED:
- RESTORE PSW
- PRINT <CR,LF,LF,' '>
- DECOUT G ;PRINT NO OF UNUSED BLOCKS/GROUPS
- PRINT <' GROUPS REMAINING ON DISK OUT OF '>
- DECOUT DSM ;PRINT MAX NUMBER OF BLOCKS/GROUPS
- PRINT <CR,LF>
- JMP ENDFIL ;EXIT
- ;
- ; THIS ROUTINE DUMPS THE DIRECTORY GROUPS
- ;
- DIR:
- LXI D,0FFFFH ;SET UP DE
- LDA AL0 ;GET FIRST DIR ALLOC MAP
- DIR$TEST:
- RAL ;IS BIT SET?
- JNC DIR$DUMP2 ;NO, DUMP THE DIRECTORY
- INX D ;YES, BUMP BLOCK COUNT
- PUSH PSW
- MVI A,8 ;NO. OF BITS IN A BYTE
- CMP E ;DONE 8 BITS?
- JZ NEXT$BYTE ;YES, TTEST AL1
- MVI A,16 ;MAX NO. OF BITS
- CMP E ;DONE 16 BITS?
- JZ DIR$DUMP1 ;YES, DUMP DIRECTORY
- POP PSW
- JMP DIR$TEST ;TEST NEXT BIT
- ;
- NEXT$BYTE:
- POP PSW ;KEEP STACK STRAIGHT
- LDA AL1 ;GET AL1
- JMP DIR$TEST ;GO TEST IT
- ;
- DIR$DUMP1:
- POP PSW ;KEEP STACK STRAIGHT
- DIR$DUMP2:
- LXI H,0 ;START WITH GROUP 0
- DIR$LOOP:
- SAVE H,D
- CALL GROUPS ;DO THE DUMP
- RESTORE D,H
- CPHL ;DONE ALL THE DIR GROUPS?
- INX H ;BUMP GROUP NO.
- JNZ DIR$LOOP ;YES, NO DO IT AGAIN
- JMP ENDFIL ;EXIT
- ;
- SETUP:
- LDA NEWDRV
- MOV E,A
- DISKIO LOGIN ;SELECT NEW DRIVE (IF REQUESTED)
- CALLBIOS DHOME ;HOME SELECTED DRIVE
- RET
- ;
- ; FIND THE SECTOR SIZE AND NUMBER OF SIDES OF THE MEDIA
- ;
- DISKDATA:
- CALL SETUP ;LOG DRIVE INTO BDOS
- LDA NEWDRV ;GET DRIVE NO.
-
- IF HARD AND FIRST
- CPI 3 ;HARD DISK?
- JNC FLOPPY ;NO
- MVI A,TRUE ;SET A FLAG
- STA HARD$D
- JMP NEXT
- ENDIF
-
- IF HARD AND NOT FIRST
- CPI 2 ;HARD DISK?
- JC FLOPPY ;NO
- MVI A,TRUE ;SET A FLAG
- STA HARD$D
- JMP NEXT
- ENDIF
-
- FLOPPY:
- XRA A
- STA HARD$D
- NEXT:
- LXI B,NEWSTK ;END OF THIS PROGRAM
- CALLBIOS DSETDMA
- LDA NEWDRV ;NOW GET THE
- MOV C,A ; XLT LOCATION
- CALLBIOS DSELDSK ;SELECT THE DRIVE
- MOV A,M ;GET XLT ADDR LO BYTE
- INX H ;POINT TO XLT HI BYTE
- MOV H,M ;GET XLT ADDR HI BYTE
- MOV L,A ;FORM ADDRESS
- SHLD XLT ;SAVE XLT ADDRESS
- MVI C,1 ;SET TO TRACK OTHER THAN 0
- CALLBIOS DSETTRK ;DO IT
- MVI C,1
- CALLBIOS DSETSEC ;SET THE SECTOR
- CALLBIOS DREAD ;READ THE DISK
- MVI C,31 ;GET DISK PARAMETER BLOCK
- CALL BDOS ;HL POINTS TO BIOS DPB ON RETURN
- SHLD DPB$ADDR ;SAVE DPB ADDRESS
- LXI D,DPB ;POINT TO PROGRAM DPB STORAGE AREA
- LXI B,15 ;LENGTH TO MOVE
- MOVE ;COPY DPB FROM BIOS
- LDA HARD$D
- ORA A ;ON HARD DISK?
- CALL HARDWARE ;NO, HARDWARE SPECIFIC ROUTINE
- LXI B,0080H ;RESET DMA ADRESS
- CALLBIOS DSETDMA
- RET
- ;
- ;
- ;****************************************************************
- ;* *
- ;* HARDWARE *
- ;* *
- ;* This is routine has to be provided by the user *
- ;* to suit their disk controller hardware. It must *
- ;* set up the display header to suit the types *
- ;* of drive you are using. This is up to you *
- ;* but I would suggest something informative *
- ;* about the disk format, i.e. single/double *
- ;* sided, single/double density, sector size *
- ;* etc. as in the DJ2D example below. *
- ;* *
- ;****************************************************************
- ;
- HARDWARE:
- LXI H,HEAD$HARD ;POINTER TO HEADER FOR HARD DISK
- JNZ MOVER ;DISPLAY ONLY IF HARD FLAG SET
- LHLD DPB$ADDR ;GET DPB START
- DCX H ;GODBOUT HAS DISK TYPE BEFORE XLT
- MOV A,M ;A <---- DISK TYPE
- LXI H,HEAD$TABLE
- RAL ;MULTIPLY DISK TYPE BY 2
- MVI D,0
- MOV E,A ;DE <---- OFFSET INTO TABLE
- DAD D ;HL <---- POINTS TO HEADER ADDRESS
- CONTENTS ;HL <---- POINTS TO HEADER
- MOVER:
- LXI D,HEADER ;BUFFER FOR DISPLAY HEADER
- LXI B,14 ;LENGTH OF MESSAGE
- MOVE ;MOVE IT
- RET
- ;
- HEAD$TABLE:
- DW HEAD$128S
- DW HEAD$128D
- DW HEAD$256S
- DW HEAD$256D
- DW HEAD$512S
- DW HEAD$512D
- DW HEAD$1024S
- DW HEAD$1024D
- ;
- HEAD$128S:
- DB ' : 1S/1D/128 '
- ;
- HEAD$256S:
- DB ' : 1S/2D/256 '
- ;
- HEAD$512S:
- DB ' : 1S/2D/512 '
- ;
- HEAD$1024S:
- DB ' : 1S/2D/1024 '
- ;
- HEAD$128D:
- DB ' : 2S/1D/128 '
- ;
- HEAD$256D:
- DB ' : 2S/2D/256 '
- ;
- HEAD$512D
- DB ' : 2S/2D/512 '
- ;
- HEAD$1024D:
- DB ' : 2S/2D/1024 '
- ;
- HEAD$HARD:
- DB ' : Hard Disk '
- ;
- ; ERROR AND EXIT ROUTINES
- ;
- ;
- INERR:
- PRINT <CR,LF,'INPUT ERROR'>
- JMP ENDFIL
- ;
- BADSEC:
- PRINT <CR,LF,'INCORRECT SECTOR NUMBER, 0 OR GREATER THAN '>
- DECOUT SPT$ERR
- JMP ENDFIL
- ;
- BADTRK:
- PRINT <CR,LF,'INCORRECT TRACK NUMBER'>
- JMP ENDFIL
- ;
- BADGRP:
- PRINT <CR,LF,'INCORRECT GROUP NUMBER, GREATER THAN '>
- DECOUT DSM
- RET
- ;
- OPNERR:
- PRINT <CR,LF,'NO FILE BY THAT NAME ON DRIVE '>
- LDA NEWDRV ;NEW DRIVE NO
- ADI 41H ;ADD ASCII OFFSET
- MOV E,A
- MVI C,2
- CALL BDOS
- JMP ENDFIL
- ;
- RDERR:
- PRINT <CR,LF,'DISK READ ERROR'>
- JMP MONITOR
- ;
- NAMERR:
- PRINT <CR,LF,'ERROR IN FILE NAME'>
- JMP ENDFIL
- ;
- ADERR:
- PRINT <CR,LF,LF,'ADDRESS ERROR'>
- JMP EDIT1 ;ADDRESS ERROR ON EDIT
- ;
- HEXERR:
- PRINT <CR,LF,' ERROR - HEX INPUT ONLY',CR,LF>
- JMP PTX
- ;
- VERSION$ERROR:
- PRINT <'Sorry, you need CP/M version 2.0 or later',CR,LF>
- PRINT <'to run this disk dump program'>
- ;
- MONITOR:
- PRINT CRLF,$
- LDA DRVNO ;RESTORE LOGGED DRIVE NO
- MOV E,A
- DISKIO LOGIN
- LHLD OLDSTK
- SPHL ;RESET OLD STACK POINTER
- RET
- ;
- ;
- ; DATA ALLOCATIONS
- ;
- SPACE: DB ' $' ;ASCII SPACE
- CRLF: DB 0DH,0AH,24H ;ASCII CR LF
- XLT: DW 00 ;SECTOR TRANSLATE TABLE ADDDR
- DIVISOR:DW 00 ;USED IN GROUP CALCS
- SEC$INDEX:DW 00 ;DITTO
- I: DW 00 ;PSEUDO INDEX REGISTER
- LINE: DW 00 ;LINE NUMBER FOR LISTING
- IPOINT: DW 00 ;VARIABLE BUFFER POINTER
- LASTIN: DB 0 ;LAST CONSOLE INPUT CHAR
- INFLAG: DB 0 ;FLAG, RET FOR MORE CONSOLE INPUT
- DRVNO: DB 0 ;STORAGE FOR ORIGINALLY LOGGED DRIVE
- NEWDRV: DB 0 ;STORAGE FOR NEW DRIVE NO
- TK0FLAG:DB 0 ;DRIVE ON TRACK 0
- HARD$D: DB 0 ;HARD DISK FLAG
- TRACK: DW 0 ;SELECTED TRACK
- NEW$TRACK:DW 0 ;NEXT TRACK TO ACCESS
- BSEC: DW 00 ;SELECTED BEGINNING SECTOR
- ESEC: DW 00 ;SELECTED ENDING SECTOR
- DCOUNT: DW 00 ;SECTORS DUMPED COUNT
- SCOUNT: DB 0 ;SECTORS DUMPED IN CURRENT EXTENT
- P$COUNT:DB 0 ;GROUPS DONE COUNT
- G: DW 00 ;CPM GROUP NO
- S: DW 00 ;SECTOR NO WITHIN GROUP G
- MAP$COUNT:DW 00 ;GROUPS REMAINING TO MAP
- OLDSTK: DW 00 ;STORAGE FOR OLD STACK POINTER
- INB: DW 00 ;STORES POINTER TO INPUT BUFFER AREA
- OUTB: DW 00 ;STORES POINTER TO DIRECTORY BUFFER AREA
- FDFLAG: DB 0 ;FILE DUMP IN PROGRESS FLAG
- EXFLAG: DB 0 ;EXTENT CHECK FLAG AND COUNT
- SPT$ERR:DW 0 ;MAX SECTOR NO. FOR BADSEC ERROR
- ;
- DPB$ADDR:
- DW 0 ;START OF DPB IN BIOS
- DPB: ;START OF DISK PARAMETER BLOCK
- SPT: DW 00 ;TOTAL NUMBER OF SECTORS/TRACK
- BSH: DB 0 ;DATA ALLOC BLOCK SHIFT FACTOR
- BLM: DB 0 ;CP/M DOCUMENTATION STRIKES AGAIN
- EXM: DB 0 ;EXTENT MASK
- DSM: DW 00 ;MAXIMUM DATA BLLOCK (GROUP) NUMBER
- DRM: DW 00 ;TOTAL NO. OF DIRECTORY ENTRIES
- AL0: DB 0 ;BIT MAP OF THE NO. OF BLOCKS (GROUPS)
- AL1: DB 0 ; RESERVED FOR THE DIRECTORY
- CKS: DW 00 ;DIRECTORY CHECK VECTOR
- OFF: DW 00 ;NUMBER OF RESERVED TRACKS
- ;
- HEADER: DS 14 ;DISPLAY HEADER MESSAGE BUFFER
- DB '$'
- ;
- INBUF: DS 10 ;USED AS CONSOLE INPUT BUFFER
- DIRBUF: DS 03 ;BUFFER FOR FILE GROUP ALLOCATION INFO
- RCOUNT: DS 01 ;NO. OF RECORDS IN CURRENT EXTENT
- ALLOC: DS 18 ;GROUP ALLOCATION TABLE
- ;
- XLT$SD:
- DB 00,06,12,18,24,04,10,16,22,02,08,14,20
- DB 01,07,13,19,25,05,11,17,23,03,09,15,21
- ;
- ENDSTK: DS 64 ;STACK SPACE ALLOCATION
- NEWSTK: ;SP LOAD POINT
-
- END BEGIN
-
-