; --- DUMP --- ; ; BY: S. J. SINGER ; ; THIS PROGRAM IS AN IMPROVED DUMP UTILITY FOR CP/M. ANY CPM FILE ;MAY BE DUMPED TO THE CONSOLE IN A FORMAT SIMILAR TO THAT USED BY THE ;DDT DUMP COMMAND. IN ADDITION, ANY SECTOR OR GROUP OF SECTORS MAY ;BE DUMPED IN THE SAME FORMAT. ; THE CURRENT VERSION OF DUMP SUPPORTS 4 DISK DRIVES DESIGNATED ;A, B, C, AND D RESPECTIVELY. ; ; -- OPERATION -- ; ; THE PROGRAM MAY BE RUN EITHER BY TYPING DUMP, OR DUMP FOLLOWED ;BY THE FILE NAME OR TRACK AND SECTOR. IF DUMP IS TYPED THE PROGRAM ;RESPONDS WITH A HEADING FOLLOWED BY A '*' AND WAITS FOR MORE INPUT. ;OPERATION IN THIS MODE IS SIMILAR TO OTHER UTILITIES LIKE PIP OR DDT. ; THE OPERATION DESIRED MAY THEN BE TYPED IN AS FOLLOWS: ; ; DUMP FILE.NAM ; DUMP A:FILE.NAM ; DUMP B:FILE.NAM ; ; OR DUMP MAY BE TYPED SEPARATELY AS: ; ; DUMP ; ; *FILE.NAM ; *B:FILE.NAM (THE * IS A PROGRAM PROMPT) ; ; THE PROGRAM MAY ALSO BE USED TO DUMP DISK SECTORS DIRECTLY, ;DUMP ANY CP/M EIGHT SECTOR GROUP OR A MAP OF THE GROUP ALLOCATIONS FOR THE ;ENTIRE DISK. ; ; DUMP TRACK 3 SECTOR 7 ; DUMP TRACK 5 SECTOR 3 - 9 ; DUMP TRACK 6 (DUMPS ALL 26 SECTORS) ; DUMP GROUP 19 ; DUMP MAP ; ; THE WORDS TRACK, SECTOR AND GROUP MAY BE ABREVIATED AS FOLLOWS ; ; DUMP G 4 ; DUMP T 7 S 3-4 ; *TRACK 5 S 6 ; *SECTOR 2- 9 T 14 ; ; ; DUMP B: TRACK 3 ; DUMP D: T 9 S 4-6 ; DUMP C: G 5 ; DUMP B:MAP ; ; NOTE THAT THE FORMAT IS QUITE FREE. SPACES ARE USUALLY IGNORED ;THEY ARE ONLY REQUIRED AFTER THE WORDS TRACK AND SECTOR OR T AND S, ;AND AFTER THE WORD DUMP. ; A TRACK MAY ALSO BE DUMPED WITH ALL THE ADDRESS AND FORMATTING ;INFORMATION. THIS FEATURE IS USEFUL FOR RECOVERING "CRASHED" DISKS, AND ;FOR EVALUATING HARDWARE PROBLEMS OR MODIFICATIONS. UNFORTUNATELY THE TRACK ;READ FEATURE IS HARDWARE SPECIFIC AND NOT SUPPORTED BY CP/M. THE CODE ;CONTAINED IN THIS SECTION OF THE DUMP PROGRAM IS FOR THE WESTERN DIGITAL 1771 ;AND TARBELL FLOPPY DISK CONTROLER. TO DUMP AN ENTIRE TRACK TYPE: ; ; DUMP TRACK 5 FORMAT ; *C:T 3 FORMAT ; ; A LIMITED EDITING FEATURE IS INCLUDED IN THE DUMP UTILITY TO ;ALLOW CHANGING DATA ON THE DISK. THE EDIT FEATURE WORKS AS FOLLOWS. ;ANY SINGLE SECTOR ON EITHER DRIVE MAY BE EDITED BY REQUESTING DISPLAY ;OF THE SECTOR FOLLOWED BY THE WORD EDIT. ; ; DUMP B:TRACK 4 SECTOR 2 EDIT ; ; THE REQUESTED SECTOR WILL BE DISPLAYED FOLLOWED BY AN EDIT PROMPT ; ; EDIT - ; ; ENTER THE ADDRESS OF THE FIRST BYTE TO BE CHANGED. THE PROGRAM WILL ;RESPOND BY TYPING BACK THE ADDR ENTERED AND THE PRESENT CONTENTS OF THAT ;ADDRESS. TO CHANGE THE CONTENTS OF THE ADDRESS ENTER THE NEW BYTE FOLLOWED ;BY A CARRIAGE RETURN. THE PROGRAM WILL DISPLAY THE NEXT ADDRESS AND ITS ;CONTENTS. TO STOP ENTERING DATA TYPE A PERIOD. THE PROGRAM WILL REDISPLAY ;THE SECTOR SHOWING THE CHANGES MADE. THE EDIT FEATURE WORKS ALMOST EXACTLY ;LIKE THE S ENTRY FEATURE IN DDT. TYPING ONLY A CARRIAGE RETURN OMITS ENTRY. ; TYPING A PERIOD MERELY REDISPLAYS THE SECTOR FROM MEMORY, IT DOES ;NOT CAUSE IT TO BE WRITTEN BACK ON THE DISK. WHEN EDITING IS COMPLETE, ;REDISPLAY THE SECTOR BY TYPING A PERIOD AND TYPE ; ; WRITE (WRITE SECTOR BACK TO SAME LOCATION) ; WRITE T 3 S 4 (WRITE SECTOR TO SPECIFIED LOACTION) ; WRITE B:TRACK 5 SECTOR 7 ; ; STOP (STOP EDITING WITHOUT WRITING ON DISK) ; ; ALL EDIT ENTRIES MUST BE MADE IN HEX. ENTERING NON HEX CHARACTERS ;RESULTS IN AN ERROR MESSAGE. THE PERMISSABLE ADDRESS RANGE IS 0000 TO 007F. ;LARGER ADDRESSES GIVE AN ERROR MESSAGE. WHEN ENTERInG A GROUP OF BYTES THE ;ADDRESSES ARE COMPUTED MODULO 128, THE NEXT ADDRESS AFTER 007F IS 0000. ; THE EDIT FEATURE SHOULD BE USED WITH CAUTION SINCE IT IS POSSIBLE ;TO EDIT CP/M TO "DEATH" BY CHANGING A SINGLE BYTE. ONE OCCASIONAL VALUABLE ;USE IS TO RESTORE FILES THAT HAVE BEEN ACCIDENTALLY ERASED. ERASING A FILE ;USING THE ERA COMMAND DOES NOT ERASE THE DATA FROM THE DISK, BUT ONLY ENTERS ;AN E5 INTO THE FIRST BYTE OF THE DIRECTORY. TO RESTORE A FILE, DISPLAY ;THE DIRECTORY BY DISPLAYING GROUPS 0 AND 1. FIND THE SECTOR CONTAINING THE ;NAME OF THE FILE TO BE RESTORED AND DISPLAY IT USING THE EDIT FEATURE ;CHANGE THE BYTE PRECEEDING THE FILE NAME FROM E5 TO 00 AND WRITE THE SECTOR ;BACK ON THE DISK. THIS WILL RESTORE THE FILE PROVIDED NONE OF THE SECTORS ;IN THE FILE WERE CHANGED AFTER THE FILE WAS "ERASED". ; ; AN ADDITIONAL FEATURE OF DUMP IS THE ABILITY TO VALIDATE A DISK. ; ; DUMP VALIDATE ; DUMP A:VALIDATE ; DUMP C:VALIDATE ; ; THIS CAUSES THE ENTIRE DISK SELECTED TO BE READ ONE SECTOR AT A ;TIME. THE SECTOR NUMBER OF ANY SECTOR CAUSING A READ ERROR WILL BE DISPLAYED. ;WHEN VALIDATING THE PROGRAM READS EVERY FIFTH SECTOR FOR SPEED. ; ; AS WITH OTHER CP/M UTILITIES ^S "FREEZES" THE DISPLAY, AND ^C ;RETURNS TO THE MONITOR. DUMP CONTAINS MANY ERROR AND CONSISTANCY ;CHECKS. THE RESULTING MESSAGES SHOULD BE SELF EXPLANATORY. ; ; DUMP WAS ASSEMBLED USING THE CP/M MACRO ASSEMBLER, AND USES A LARGE ;NUMBER OF MACROS INCLUDED IN A LIBRARY CALLED MACRO.LIB ; MACLIB MACRO ;INCLUDE MACRO LIBRARY ORG 100H ;SET PROG START LXI H,0 DAD SP ;GET STACK POINTER SHLD OLDSTK LXI SP,NEWSTK ;SET UP NEW STACK DISKIO ?DRIVE ;GET CUPRENTLY LOGGED DRIVE NO STA DRVNO ;SAVE ORIGINAL DRIVE NUMBER STA NEWDRV ;ALSO SAVE IN NEW DRIVE NO 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 PRINT <'COPYRIGHT 1978 BY S. J. SINGER',CR,LF> NEWIN: PRINT MVI A,0FFH ;SET SWITCH TO RETURN HERE AGAIN STA INFLAG LXI SP,NEWSTK ;RESET STACK POINTER XRA A STA VALFLG ;RESET VALIDATION ERROR FLAG 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 LXI H,82H ;POINT TO START OF INPUT BUFFER CALL GETDRV ;GET DRIVE NAME FROM INPUT BUFFER JNC GETNAM ;DEFAULT TO A IF NO DISK NAME STA NEWDRV ;SAVE DRIVE NAME DOWN: MOVE 82H,80H,40H ;SHIFT BUFFER DOWN TWO BYTES ; ; SEARCH FOR DIRECT READ OF TRACK AND SECTOR OR VALIDATE ; GETNAM: INSTR 82H,40H,'VALIDATE' JC VALID ;VALIDATE DISK INSTR 82H,40H,'GROUP' JC GROUP ;DISPLAY CPM 8 SECTOR 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,'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 STA TRACK ;SAVE TRACK NO INSTR 82H,40H,'FORMAT' ;SEARCH FOR FORMAT JC FORMAT ;DUMP TRACK WITH ADDR INFO 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 STA BSEC ;BEGINNING SECTOR STA 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 EDITION OF SECTOR SCAN DECIN ;SCAN AND CONVERT ANOTHER NO JC INERR ;ERROR IF CARRY SET STA ESEC ;SAVE IN END SECTOR LXI H,BSEC ;POINTS TO BSEC CMP M ;COMPARE BEGIN AND END JP DOREAD ;OK IF END>=BEGIN MOV B,A ;OTHERWISE MOV A,M ;SWITCH THEM STA ESEC MOV M,B DOREAD: CALL RDISK0 ;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 RDISK0 ;DISPLAY SECTOR EDIT1: PRINT FILL INBUF,INBUF+29 INPUT INBUF,28 ;INPUT MAXIMUM 6 CHAR INSTR INBUF,28,'WRITE' ;WRITE EDITED SECTOR ON DISK? JC WRTDSK ;WRITE BUFFER BACK ON DISK INSTR INBUF,28,'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,0080H 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,0080H ;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: INSTR INBUF,29,'T ' ;CHANGED TRACK SPECIFICATION JC WR1 INSTR INBUF,29,'TRACK ' JNC WRTDSK4 ;NO TRACK SPEC SO WRITE TO OLD ADDR WR1: SCAN ;LOOK FOR A NUMBER DECIN ;CONVERT IT TO BINARY JC INERR ;ERROR MESSAGE IF NOT DECIMAL NO STA NTRK ;SAVE IT INSTR INBUF,29,'S ' ;CHANGED SECTOR SPECIFICATION JC WR2 INSTR INBUF,29,'SECTOR ' JNC WRTDSK4 ;NO SECTOR NO SO WRITE TO OLD ADDR WR2: SCAN DECIN JC INERR ;ERROR IF NOT DECIMAL NO STA NBSEC LXI H,INBUF CALL GETDRV ;FIND DRIVE NUMBER IF SPECIFIED JNC WR5 STA NEWDRV ;SAVE DRIVE NO WR5: PRINT PRINT <'CAUTION - THIS COMMAND MOVES A SECTOR ON THE DISK'> PRINT CHARIN ;GET A CHAR IN A CPI 'Y' JNZ ENDFIL ;STOP IF NOT 'Y' MOVE 80H,TRKBUF,128 ;SAVE BUFFER IN CASE OF READ SETSEC NBSEC ;SET NEW SECTOR NO SETTRK NTRK ;SET NEW TRACK NO LDA NEWDRV MOV E,A DISKIO LOGIN ;LOG IN SELECTED DRIVE MOVE TRKBUF,80H,128 ;MOVE BUFFER BACK WRTDSK4:CALLBIOS DWRITE ;WRITE BUFFER BACK ON DISK JMP ENDFIL ;EXIT ; ; READ TRACK AND SECTOR DIRECT ; RDISK0: CALL FIXB RDISK: SETSEC BSEC ;SET SECTOR JC BADSEC ;WRONG SECTOR NO TRK2: SETTRK TRACK ;SET TRACK JC BADTRK ;WRONG TRACK NO LDA NEWDRV MOV E,A DISKIO LOGIN ;SELECT NEW DEIVE IF SPECIFIED CALLBIOS DREAD ;READ TRACK AND SECTOR ; ; PRINT DRIVE, TRACK AND SECTOR HEADING ; PRTSEC: PRINT LDA NEWDRV CALL PRNDRV ;PRINT DRIVE NAME PRNTRK: PRINT ' - TRACK ' LXI H,0 LDA TRACK MOV L,A DECOUT PRINT ' SECTOR ' LXI H,0 LDA BSEC MOV L,A DECOUT PRINT CRLF,$ CALL PRTBUF ;PRINT IT LXI H,BSEC ;ADDR OF SECTOR NUMBER LDA ESEC ;END SECTOR NUMBER CMP M ;COMPARE THEM RZ ;EXIT IF THEY ARE EQUAL INR M ;INCR BSEC JMP RDISK ; ; DUMP ENTIRE TRACK IF NO SECTOR INPUT ; WHLTRK: MVI A,1 ;BEGIN SECTOR STA BSEC MVI A,26 ;END SECTOR STA ESEC CALL RDISK0 ;TO READ DISK JMP ENDFIL ;BACK FOR MORE INPUT ; ; FILL IN FCB FOR NAMED FILE ; FILNAM: 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 DISKIO OPEN,FCB ;0PEN FILE CPI 255 ;CHECK FILE PRESENT JZ OPNERR ;EXIT IF ERROR RDFILE: DISKIO READ,FCB ;READ A BLOCK ORA A ;ZERO INDICATES SUCESSFUL READ JNZ ENDFIL ;1 INDICATES EOF CALL PRTBUF ;DO PRINT SUBROUTINE JMP RDFILE ;BACK FOR NEXT BLOCK ENDFIL: PRINT CRLF,$ LDA DRVNO ;RESTORE LOGGED DRIVE NO MOV E,A DISKIO LOGIN 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,80H ;INITIAL BUFFER POINTER SHLD IPOINT ;STORAGE FOR POINTER BPRN: LHLD IPOINT ;LOAD POINTER MVI C,16 ;CHAR PER LINE LDA LINE+1 ;LINE NUMBER SAVE B,H HEXOUT LDA LINE ;SECOND TWO DIGITS HEXOUT 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 MOV A,C CPI 9 ;CHECK 8 CHAR JNZ DECC ;SKIP IF NOT SAVE B,H PRINT SPACE,$ RESTORE H,B DECC: DCR C ;DECR CHAR COUNT JNZ PLOOP ;PRINT SOME MORE 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 ; ; THIS SECTION VALIDATES A DISK ; VALID: MVI A,1 ;START WITH SECTOR 1 STA SNUM XRA A ;START WITH TRACK 0 STA TNUM LDA NEWDRV ;SELECT NEW DRIVE MOV E,A DISKIO LOGIN RS0: SETTRK TNUM JC BADTRK RS1: SETSEC SNUM JC BADSEC CALLBIOS DREAD ORA A CNZ VALERR ;ERROR IF NOT ZERO CALL PRNCON ;ESCAPE ON CONTROL C LDA SNUM ;SECTOR NO ADI 5 ;INCR BY 5 STA SNUM ;STORE IT BACK SBI 27 ;CALC SECTOR MOD 26 JM RS1 ;SECTOR OK IF MINUS INR A ;SECTOR MOD 26 STA SNUM ;STORE IT BACK CPI 1 ;ARE WE BACK TO ONE YET JNZ RS1 ;READ SOME MORE LDA TNUM ;TRACK NUMBER INR A ;INCR BY ONE CPI 77 ;CHECK LIMIT JZ VALOUT ;TO EXIT STA TNUM ;STORE BACK TRACK NO JMP RS0 ;BACK TO READ ROUTINE VALOUT: LDA VALFLG ;CHECK ERROR FLAG ORA A JNZ ENDFIL PRINT LDA NEWDRV CALL PRNDRV ;PRINT DRIVE LABEL JMP ENDFIL VALERR: PRINT LDA TNUM LXI H,0 MOV L,A DECOUT PRINT ' SECTOR ' LXI H,0 LDA SNUM MOV L,A DECOUT PRINT CRLF,$ MVI A,-1 STA VALFLG ;SET ERROR FLAG RET ; ; ; TRACK READ AND DUMP FORMATTING INFORMATION AS WELL AS DATA ; FORMAT: CALL FIXB SETTRK TRACK ;SET TRACK NO JC BADTRK ;WRONG TRACK NO LDA NEWDRV MOV E,A DISKIO LOGIN ;SELECT NEW DRIVE IF SELECTED LXI H,TRKBUF ;BUFFER ADDR TO HL LXI D,0 ;BYTE COUNT MVI A,0E4H ;READ TRACK CMND FOR TARBELL CONTROLER OUT 0F8H ;SEND CMND TO 1771 F1: IN 0FCH ;WAIT FOR DRQ OR INTRQ ORA A JP PTRK ;TO PRINT ROUTINE IN 0FBH ;READ DISK DATA MOV M,A ;STORE IT IN BUFFER INX H ;INCR MEMORY POINTER INX D ;INCR BYTE COUNT JMP F1 ;KEEP READING TILL INTERRUPT PTRK: XCHG ;BYTE COUNT TO HL SHLD BYTECNT ;SAVE BYTES READ FROM TRACK PRINT LDA NEWDRV ;DRIVE NO CALL PRNDRV ;PRINT IT PTRK0: PRINT ' TRACK ' LXI H,0 LDA TRACK MOV L,A DECOUT ;PRINT TRACK NO PRINT CRLF,$ PTRK2: LHLD BYTECNT ;COUNT OF BYTES IN BUFFER XCHG ;MOVE IT TO DE LXI H,TRKBUF ;ADDR OF TRACK BUFFER PTRK3: MVI C,16 ;CHAR PER LINE LDA LINE+1 ;LINE NO SAV ;PUSH REGISTERS HEXOUT LDA LINE HEXOUT PRINT ' ' RES ;POP REGISTERS PTRK4: MOV A,M ;GET A BYTE SAV HEXOUT PRINT SPACE,$ RES MOV A,C CPI 9 ;CHECK IF 8 CHAR PRINTED JNZ PTRK5 SAV PRINT SPACE,$ RES PTRK5: DCX D ;DECR BYTE COUNT MOV A,D ORA E JZ ENDFIL ;BYE INX H ;BUFFER POINTER DCR C ;BYTES PER LINE JNZ PTRK4 ;LOOP TILL END OF LINE SAV PRINT CRLF,$ CALL PRNCON ;PRINT CONTROL INDEX LINE,16 ;INCR LINE COUNT RES JMP PTRK3 ; ; 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 RET ; ; THIS SECTION DISPLAYS A CPM GROUP OF 8 SECTORS ; GROUP: SCAN ;GET THE GROUP NO DECIN ;CONVERT TO BINARY JC INERR ;INPUT ERROR IF CARRY SET STA G ;SAVE GROUP NO ADI 13 ;CHECK LEGAL RANGE JC BADGRP XRA A STA S ;SET SECTOR COUNT TO 0 CALL FIXB ;RESTORE DRIVE B IF SELECTED GRP1: CALL GRPTS ;CONVERT TO TRACK AND SECTOR CALL RDISK ;PRINT THE SECTOR LDA S ;CHECK SECTOR»COUNT INR A STA S ;INCR S BY 1 CPI 8 ;CHECK LIMIT JNZ GRP1 ;PRINT ANOTHER SECTOR JMP ENDFIL ;BACK FOR MORE INPUT ; ; GRPTS CONVERT CPM GROUP AND SECTOR NUMBER TO TRK AND SEC ; GRPTS: MVI H,0 ;ZERO H LDA G ;GROUP NO MOV L,A ;TO L MOV D,H ;ZERO D DAD H DAD H DAD H ;SHIFT LEFT 3 LDA S ;GET SECTOR NO MOV E,A ;TO DE DAD D ;HL HAS G*8+S LXI D,-26 ;DIVISOR MVI A,1 ;CONTAINS DIVIDEND DIV: DAD D ;SUB 26 INR A JC DIV ;LOOP TILL MINUS LXI D,TABLE+26 ;INDEX INTO TABLE DAD D STA TRACK ;STORE TRACK NO MOV A,M ;GET SECTOR NO STA BSEC ;SAVE IN BEGINNING SECTOR STA 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 ;TO HL SHLD IPOINT ;SAVE MAP POINTER LXI H,0 ;ZERO HL SHLD G ;ZERO COUNT OF UNUSED GROUPS PRINT LDA NEWDRV ;LOGGED DRIVE CALL PRNDRV ;PRINT DRIVE NAME PRINT CRLF2,$ MAP1: LHLD IPOINT ;POINTER TO DISK ALLOCATION MAP MVI D,8 ;NO OF LINES MAP2: MVI C,4 ;WORDS PER LINE MAPX: SAV PRINT ' ' RES 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 LDA G ;UNUSED GROUPS INR A ;ADD 1 STA G ;STORE IT BACK JMP MAP6 MAP5: PRINT '1' ;PRINT A ONE MAP6: RESTORE PSW,H,D,B PUSH PSW ;SAVE BIT MAP BYTE MOV A,B ;BIT COUNT CPI 7 JNZ MAPY MOV A,C ;WORD COUNT CPI 2 JNZ MAPY MOV A,D ;LINE COUNT CPI 1 JNZ MAPY POP PSW JMP MAP7 ;TO PRINT UNUSED GROUPS MAPY: POP PSW DCR B ;DCR BIT COUNT JNZ MAP4 ;PRINT MORE BITS DCR C ;DECR WORD COUNT INX H ;INCR ALLOC MAP POINTER JNZ MAP3 SAV PRINT CRLF,$ RES DCR D ;DECR LINE COUNT JMP MAP2 MAP7: PRINT DECOUT G ;PRINT NO OF UNUSED SECTORS PRINT <' GROUPS REMAINING ON DISK OUT OF 243',CR,LF> JMP ENDFIL ;EXIT ; ; THIS ROUTINE SORTS AND DISPLAYS THE DIRECTORY ; (NOT IMPLEMENTED IN THIS VERSION) ; DIR: JMP ENDFIL ;EXIT ; ; THIS ROUTINE RESTORES DRIVE B ; FIXB: LDA NEWDRV ;CHECK DRIVE NO ORA A RZ ;RETURN IF DRIVE A LDA NEWDRV ;SELECT DRIVE B MOV E,A DISKIO LOGIN XRA A STA TNUM ;SELECT TRACK ZERO INR A ;SELECT SECTOR 1 STA SNUM SETSEC SNUM SETTRK TNUM CALLBIOS DHOME ;HOME DRIVES CALLBIOS DREAD ;READ TRACK ZERO DIRECT RET ; ; ERROR AND EXIT ROUTINES ; ; INERR: PRINT JMP ENDFIL ; BADSEC: PRINT JMP ENDFIL ; BADTRK: PRINT JMP ENDFIL ; BADGRP: PRINT JMP ENDFIL ; OPNERR: LDA NEWDRV ;CURRENT DRIVE NO ORA A JNZ OPNER1 PRINT JMP ENDFIL OPNER1: PRINT JMP ENDFIL ; RDERR: PRINT JMP MONITOR NAMERR: PRINT JMP ENDFIL ; ADERR: PRINT JMP EDIT1 ;ADDRESS ERROR ON EDIT ; HEXERR: PRINT JMP PTX ; MONITOR: PRINT CRLF,$ LDA DRVNO ;RESTORE LOGGED DRIVE NO MOV E,A DISKIO LOGIN LHLD OLDSTK SPHL ;RESET OLD STACK POINTER RET ; ; GETDRV SEARCH COMMAND STRING FOR DRIVE NAME AND RETURN CODE ; A:=0 B:=1 C:=2 D:=3 CARRY SET IF DRIVE PRESENT ; GETDRV IS CALLED WITH HL POINTING TO STARTING POSITION FOR SEARCH ; GETDRV: SAV ;SAVE REGS LXI D,DSKNAME ;POINT TO NAME TABLE MVI C,0 ;DRIVE NUMBER GD1: SAV MVI B,40H ;STRING LENGTH MVI C,2 ;SUBSTRING LENGTH INSTR RES JC GD3 ;FOUND NAME ON CARRY MOV A,C ;DRIVE NO TO A CPI 3 ;CHECK LIMIT JZ GD3 INR C ;INCR DRIVE NO INX D INX D ;POINT TO NEXT NAME JMP GD1 ;LOOP FOR 4 DRIVES GD3: MOV A,C ;DRIVE NO TO A RES RET ; DSKNAME:DB 'A:' ;TABLE OF DISK NAMES DB 'B:' DB 'C:' DB 'D:' ; ; PRNDRV PRINT DRIVE NAME CORRESPONDING TO CODE IN A REG ; 0=A 1=B 2=C 3=D >3 ERROR ; PRNDRV: SAV CPI 4 ;CHECK RANGE JP PRDR3 ;ERROR IF > 3 ADI 'A' ;CALC LETTER TO PRINT CHAROUT ;PRINT IT PRDR1: RES RET PRDR3: PRINT JMP PRDR1 ; ; ; ; DATA ALLOCATIONS ; FCB EQU 5CH ;FILE CONTROL BLOCK SPACE: DB ' $' ;ASCII SPACE CRLF: DB 0DH,0AH,24H ;ASCII CR LF CRLF2: DB 0DH,0AH,0AH,'$' ;ASCII CR LF LF I: DW 0 ;PSEUDO INDEX REGISTER LINE: DW 0 ;LINE NUMBER FOR LISTING IPOINT: DW 00 ;VARIABLE BUFFER POINTER INBUF: DS 30 ;USED AS CONSOLE INPUT BUFFER 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 NBSEC: DB 0 ;TEMPORARY STORAGE FOR SECTOR NO NTRK: DB 0 ;TEMPORARY STORAGE FOR TRACK NO TRACK: DB 0 ;SELECTED TRACK BSEC: DB 0 ;SELECTED BEGINNING SECTOR ESEC: DB 0 ;SELECTED ENDING SECTOR TNUM: DB 0 ;TRACK NO FOR VALIDATE SNUM: DB 0 ;SECTOR NO FOR VALIDATE VALFLG: DB 0 ;VALIDATION ERROR FLAG G: DB 0 ;CPM GROUP NO S: DB 0 ;SECTOR NO WITHIN GROUP G COUNT: DB 0 ;COUNT OF DIRECTORY ENTRIES OLDSTK: DW 0 ;STORAGE FOR OLD STACK POINTER ENDSTK: DS 24 ;STORAGE FOR NEW STACK NEWSTK: DW 0 ;NEW STACK INB: DW 0 ;STORES POINTER TO INPUT BUFFER AREA OUTB: DW 0 ;STORES POINTER TO DIRECTORY BUFFER AREA BYTECNT:DW 0 ;BYTE COUNT FOR TRACK READ TABLE: DB 01H ;SECTOR LOOK UP TABLE DB 07H DB 0DH DB 13H DB 19H DB 05H DB 0BH DB 11H DB 17H DB 03H DB 09H DB 0FH DB 15H DB 02H DB 08H DB 0EH DB 14H DB 1AH DB 06H DB 0CH DB 12H DB 18H DB 04H DB 0AH DB 10H DB 16H TRKBUF: DW 0 ;START OF TRACK BUFFER END