home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Oakland CPM Archive
/
oakcpm.iso
/
sigm
/
sigmv013.ark
/
MITSCNVT.ASM
< prev
next >
Wrap
Assembly Source File
|
1985-02-09
|
28KB
|
1,349 lines
TITLE 'MITS 88DCDD DISK TO CP/M FILE TRANSFER'
PAGE 58
; MITS TO CP/M FILE CONVERSION ROUTINE
; CODED 11/80 THRU 1/81 (MY FIRST CP/M PROGRAM)
; FOLLOWS CONVPATB FAIRLY CLOSELY ( SEE THIS WELL DOCUMENTED PROGRAM )
; USES DIFFERENT USER INTERFACE ETC...
;
;
;
;
TRUE EQU 0FFFFH
FALSE EQU NOT TRUE
DEBUGGING EQU TRUE ; SAY BUGS NOT OUT YET ***** CHANGE LATER *****
CHECKOUT EQU FALSE ; USED TO INTERFERE WITH CARD BUFFER
LOCATION EQU 100H ; LOCATION OF THE START OF THIS STUFF
NFILES EQU 255 ; NUMBER OF FILES IN MITS DIRECTORY
NSECTS EQU 32 ; 32 SECTORS PER TRACK
DBIAS EQU 7 ; BIAS IN MITS DIRECTORY
; WHY ISN'T ANY PROGRAM IN HARMONY WITH ITS DOC?
DSIZE EQU 16 ; LENGTH OF MITS DIRECTORY ENTRY
BSIZE EQU 137 ; SECTOR LENGTH ON 88-DCDD PERTEC FD-400'S
NFPS EQU BSIZE/DSIZE ; NUMBER FILES/SECTOR (TRUNCATED)
VERS EQU 10 ; VERSION 1.0
MODL EQU 1 ; MODIFICATION LEVEL 0
DTRACK EQU 70 ; DIRECTORY TRACK
ENDSLOT EQU 0377Q ; FLAG FOR LAST FILE
CTLC EQU 'C'-64 ; CONTROL C
CTLU EQU 'U'-64 ; CONTROL U
BACKSP EQU 'H'-64 ; BACKSPACE (CTL H)
CTLD EQU 'D'-64 ; CONTROL D
CTLP EQU 'P'-64 ; CONTROL P
CTLZ EQU 'Z'-64 ; CONTROL Z
CTLS EQU 'S'-64
CTLQ EQU 'Q'-64
CR EQU 0DH ; CARRIAGE RETURN
LF EQU 0AH ; LINE FEED
;
; MACROS
;
CPM MACRO ?F,?P
PUSH B
PUSH D
PUSH H
IF NOT NUL ?F
MVI C,?F
ENDIF
IF NOT NUL ?P
LXI D,?P
ENDIF
CALL BDOS
POP H
POP D
POP B
ENDM
MSG MACRO ?M,?J
IF NOT NUL ?M
LXI H,?M
ENDIF
CALL PRMSG
IF NOT NUL ?J
JMP ?J
ENDIF
ENDM
;
;
ORG LOCATION ; START OF SOMETHING
;
; THIS≡PROGRAM WILL READ A MITS FILE THRU THE 88-DCDD CONTROLLER AND
; BY MEANS OF RESIDENT CP/M WRITE THE FILE TO A CP/M DISK.
; .........................................................................
;
; PROGRAMMED BY A. L. BENDER, M.D.
;
; .........................................................................
;
; MCNVT WILL USE ANY REPRESENTATION OF THE CP/M FILENAME ALLOWED
;
JMP MCNVT
IF DEBUGGING
PATCH DS 50
ENDIF
OND DS NFILES*DSIZE
OP DS 1 ; CURRENTr.
****
Where is further documentation available: MITSCNVT.DOC as
well as program listing.
**********
Hardware dependRENT MITS DISK
ADDR DW 0 ; I/O ADDRESS IN MITS PACKAGE (LIKE DMA ADDR)
NWDS DB 0 ; NUMBER OF WORDS TO BE READ BY MITS PACKAGE
FCOUNT DS 1 ; NUMBER OF FILES ACTUALLY IN MITS DIRECTORY
BUFFER DS BSIZE ; READ MITS BUFFER
FCB DS 33 ; FILE CONTROL BLOCK
FN DB 0 ; CURRENT FILE NUMBER BEING PROCESSED
RWFLAG DB 0 ; READ/WRITE FLAG FOR MAKEFCB
RANDFLAG: DB 0 ; 0=SEQUENTIAL 2=RANDOM 1=ISFMS (SPECIAL NSI FILE)
WRCOUNT:DB 0 ; BYTES WRITTEN
MITSNAME: DS 8 ; MITS FILE NAME
CRCEL DW 0 ; I-RECORD ADDR
CRCL1 DW 0 ; L RECORD ADDR
FRSTCH: DB 0 ; FIRST CHARACTER IN MITS FILE
NREC: DW 0 ; NUMBER RECORDS WRITTEN
;
; --- CP/M INTERFACE EQUATES ---
;
BDOS EQU 5 ; ENTRY TO CP/M I/O ROUTINE
DOSBUF EQU 0080H ; DEFAULT BUFFER
CLOSEF EQU 16 ; CLOSE FILE
CONS EQU 1 ; READ CONSOLE INPUT BYTE TO A
CONSTAT EQU 11
EXIT EQU 0 ; EXIT ADDRESS
CREATEF EQU 22 ; CREATE FILE
DELETEF EQU 19 ; DELETE FILE COMMAND
OPENF EQU 15 ; OPEN FILE
READF EQU 20 ; READ FILE
WRITEF EQU 21 ; WRITE FILE
TBUFF EQU 0080H ; DEFAULT BUFFER
TFCB EQU 005CH ; DEFAULT FCB
SETDMA: EQU 26 ; SET ADDRESS OF DMA
RDBUF: EQU 10 ; READ BUFFERED CONSOLE
TYPEF EQU 2 ; CONSOLE OUTPUT
SRCHF EQU 17 ; SEARCH FOR FILE IN DIRECTORY
;
;----- CONVASCI - CONVERT BINARY NUMBER IN BC TO ASCII
; IF RADIX=8 CONVERSION WILL BE OCTAL
; IF RADIX=10 CONVERSION WILL BE DECIMAL
;
; ENTER WITH NUMBER IN BC (B=LSB, C=MSB)
; RETURNS WITH NUMBER IN M1-M5 (LSB->MSB) AND
; ADDRESS OF M1 IN BC
;
; REGISTERS DE AND HL PRESERVED
;
; RADIX IS IN A ON ENTRY (A=10 OR A=8) (THIS WORKS FOR ANY BASE <=10)
;
; IF ENTRY IS AT SETRADIX THEN A MUST BE SET IF CONVASCI IS USED THEN
; RADIX IS ASSUMED 10 OR SET.
;
SETRADIX STA RADIX
RET
;
CONVASCI PUSH H
PUSH B
LXI H,M1
XRA A
MVI B,5
CV1:
MOV M,A
INX H
DCR B
JNZ CV1
POP B
MOV H,B
MOV L,C
PUSH D
MVI D,5
LXI B,M1
CV2 CALL CONVONE
STAX B
INX B
DCR D
JNZ CV2
POP D
POP H
LXI B,M1
RET
CONVONE PUSH B
MVI C,10
RADIX EQU $-1
CALL DIVIDE
POP B
ADI '0'
RET
M1 DB 0,0,0,0,0
;
;
; DIVIDE 16 BITS BY 8 BITS
; HL=>DIVIDEND
; C=>DIVISOR
;
; RETURNS WITH HL=>QUOTIENT
; C=>DIVISOR
; A=>REMAINDER
;
DIVIDE XRA A
CMP C
STC
RZ
MVI B,16 ; NUMBER OF TIMES TO LOOP
D1 DAD H
RAL
CMP C
JC D2
SUB C
INX H
D2 DCR B
JNZ D1
RET
; DIRECTORY LOOKUP ROUTINE
; USED TO SEARCH MFD BEGINNING AT OND
;
LOOKUP: LXI H,OND ; GET BASE OF DIRECTORY
LDA FCOUNT ; NUMBER OF FILES IN DIRECTORY
MOV B,A ; NUMBR OF FILES IN DIRECTORY
LOOK1 MVI C,8 ; NUMBER OF BYTES IN FILENAME
PUSH D
LOOK2 LDAX D ; INPUT FILE TO LOOKUP ADDR IN DE
CMP M
JNZ LOOK3 ; NOT THIS ENTRY
INX D
INX H
DCR C
JNZ LOOK2
MOV A,M
STA TRACK ; SET TRACK ADDRESS
INX H
MOV A,M
STA SECTOR
INX H
MOV A,M ; FILE TYPE
SUI 2 ; ZERO FOR SEQUENTIAL
STA RANDFLAG ; RANDOM/SEQUENTIAL FLAG
INX H
MOV A,M ; FILE NUMBER
STA FN ; SAVE FILE NUMBER (PREVENT FILE LINK ERROR LATER)
POP D
ORA A ; CLEAR CARRY
RET ;HL=>ENTRY
LOOK3 DCR B ; DECREMENT NUMBER OF FILES
JNZ LOOK4 ; JUMP IF MORE TO DO
POP D
STC ; FAILED, FILE NOT IN DIRECTORY
RET
LOOK4 MVI A,DSIZE-8
ADD C ; NUMBER OF BYTES TO SKIP PAST
CALL ADDAHL ; ADD A TO HL
POP D
JMP LOOK1
;
PRMPT PUSH H
PUSH D
CALL CRLF
MVI A,'*'
CALL OUTEEE
POP D
POP H
RET
NAMEMOV:
LXI B,8
MVI A,' '
LXI D,MITSNAME
PUSH D
CALL FILLB
POP D
MVI C,9 ; MITS FILE NAME SIZE+1
MOVE1:
MOV A,M ; PICK UP MITS FILE NAME OR DISK
CALL TERMT ; CHECK TERMINATION
RZ ; PROPER
STAX D ; SAVE IT AWAY
INX H
INX D
DCR C ; COUNT
JNZ MOVE1
MSG BMFN ; IMPROPER MITS FILE NAME
XRA A
STA TBUFF
JMP INPUTX ; GET CARD IMAGE
BADTERM: MSG BADPUNK,INPUTX ; IMPROPER PUNCTUATION
BADDISK: MSG DSKERR,INPUTX ; BAD DISK NUMBER (MITS DISK)
;
INPUTCDI:
LXI H,TBUFF
MOV A,M ; GET CHARACTER COUNT OF TBUFFER
CPI 2 ; IF 0 OR 1 CHARACTER, NO INPUT ON TBUFF
JC INPUT1 ; NO LINE IMAGE
PUSH H
INR A ; POSITION BEYOND INPUT
CALL ADDAHL ; UPDATE POINTER
MVI M,CR ; PUT CR AT END OF LINE BUFFER
POP H
LXI D,FCB ; SET FCB ADDRESS
INX H ; SET H TO FW OF TBUFF
CALL SKIPS ; SKIP BLANKS LEADING MSG
MOV A,M ; GET F.C OF IMAGE
CPI '=' ; IF FC IS = THEN WANT DIRECTORY ONLY
JZ PUTDIR ; PUT OUT DIRECTORY THEN RESTORE STACK REINITIALIZE
CALL MAKEFCB ; BUILD FCB
JNC SCAN2 ; GO TO SCAN MITS FILE NAME
LXI H,CPFMSG ; INDICATE CP/M FILE NAME IS IN ERROR
INPERR: CALL PRMSG
INPUTX: XRA A
LXI H,TBUFF
MOV M,A
INX H
LXI B,080H ; C=128 BYTE BUFFER, B=NR WDS READ
INPUT1 CALL PRMPT ; PROMPT INPUT FROM CONSOLE
MVI A,125 ; SO IT WILL FIT TBUFF...
STA BUFFER ; CONSTRUCT READ BUFFER
CPM RDBUF,BUFFER
LXI D,BUFFER+1 ; TRANSFER IMAGE TO TBUFF
LXI H,TBUFF ; [PRETEND IT WAS THERE ALWAYS]
LDA BUFFER+1 ; GET COUNT OF BUFFER BYTES
INR A ; COUNT BYTE
MOV B,A ; STUFF INTO COUNTER
INPUT2 LDAX D ; MOVE STRING FROM BUFFER TO TBUFF
MOV M,A ;
INX H ;
INX D ;
DCR B ;
JNZ INPUT2 ; LOOP
MVI A,CR ; TACK ON FINAL C/R CHARACTER
MOV M,A ; TO BUFFER (10 FUNCTION DOESN'T PUT IT THERE)
CALL CRLF
JMP INPUTCDI
SCAN2: CPI CR ; SEE IF IMAGE IS NOT COMPLETE
JNZ SCAN3 ; SO FAR SO GOOD
LXI H,NOMITS
JMP INPERR ; ERROR IN INPUT
SCAN3: LXI D,MITSNAME
CALL NAMEMOV ; MOVE MITS FILE NAME
JC BADTERM
CPI ',' ; LOOK FOR COMMA TERM
JNZ BADTERM
INX H ; GET TO THE NUMBER NOT THE COMMA
CALL DN ; CONVERT DISK NUMBER TO BINARY
STA DISK
CPI 16 ; HIGHEST DISK + 1
JNC BADDISK
MOV A,M
CALL TERMT
JNZ BADDISK
XRA A
STA TBUFF
RET
;
; DN / CONVERTS STRING AT HL TO BINARY IN A
; HL ADVANCED TO END OF INTEGER
DN: XRA A
PUSH D
DN1: MOV D,A ; SAVE A
MOV A,M
SUI '0' ; TAKE BIAS AWAY
JC DNX ; DONE, GET OUT
CPI 10 ; DONE, IF >
JNC DNX
MOV E,A
MOV A,D
RLC ;
RLC ; *4
ADD D ; *5
RLC ; *10
ADD E ; ADD DIGIT
INX H
JMP DN1
DNX:
MOV A,D
POP D
RET
; MAKEFCB.LIB 9/4/78
; ORIGINAL VERSION IN CP/M LIBRARY VOL 8
; CORRECTED 9/78 BY P. HOLLIDAY
;
; LOCAL SYMBOLS
;
FCBSIZ: EQU 33 ; SIZE OF FCB
FNMLEN: EQU 11 ; LENGTH OF FILE NAME
MAKEFCB:DS 0 ; ENTRY POINT LABEL
MTFCB: PUSH H ; COMMAND STRING POINTER
PUSH D ; FCB ADDRESS
STA RWFLAG ; SAVE READ/WRITE FLAG
LXI B,FCBSIZ ; FILL FCB WITH ZERO
CALL CLRB ; CLEAR FCB
LXI D,FCB+1
LXI B,FNMLEN ; FILL FILE NAME AREA
MVI A,' ' ; WITH BLANKS
CALL FILLB
POP D
POP H ; RESTORE POINTERS
CALL SKIPS ; PASS LEADING BLANKS
INX H ; CHECK FOR DISK CODE
MOV A,M
DCX H
CPI ':' ; EXPLICIT DISK
JNZ MTFCB1 ; NOT EXPLICIT DISK
MOV A,M ; VALID DISK CODE?
INX H
INX H
SBI '@' ; SENSE A-Z
RC ; IN CASE ZERO TEST FAILS
CPI 'Z'-'A'+1
CMC
RC ; SET IF IN ERROR
STAX D ; SAVE DISK CODE AT FCB+0
;PROCESS FILE NAME FIELD
MTFCB1: INX D
MVI C,8
CALL GETNAM
MOV A,M ; TEST FOR FILE TYPE SEPARATOR
INX H
CPI '.'
JNZ MTFCB2
MVI C,3
CALL GETNAM
MOV A,M
INX H
;CHECK TERMINATION OF FIELD
MTFCB2: CALL TERMT
RET ; RETURN TO USER
;
;PROCESS NAME FIELD
;
GETNAM: MOV A,M ; GET CHARACTER FROM COMMAND STRING
INX H
CPI '?' ; ALLOW AMBIGUITY TO EXIST IN NAME
JNZ GETN20 ; NOT AMBIGUOUS CHARACTER
LDA RWFLAG ; GET R/W FLAG
ORA A ; SET FLAGS
MVI A,'?' ; RESET ? CHAR
JZ GETNA1 ; STORE AMBIG CHAR
JMP GETNA3 ; NG,WRITING FILE ? DISALLOWED
GETN20: CPI '*' ; CHECK FOR FULL FIELD OF ???
JZ GETNA2
CALL VALCHR ; TEST FOR VALID CHARACTERS IN NAME
JC GETNA3 ; INVALID, SKIP OVER REMAINDER OF FIELD
GETNA1: STAX D ; SAVE FILE NAME OR TYPE
INX D
DCR C ; ACCUMULATE EVERYTHING
JNZ GETNAM ; LOOP TO FINISH FIELD
RET ; DONE WITH SCAN
GETNA2: LDA RWFLAG
ORA A ; TEST FOR WRITE OPERATION ON FILE
JZ GETNA3 ; NG,WRITE ON AMBIGUOUS FILE NAME
MVI A,'?'
MVI B,0 ; FILL WITH ?
JMP FILLB ; FILLB WILL RETURN TO USER
GETNA3: INX D ; SKIP TO END OF FIELD IN FCB
DCR C
JNZ GETNA3
DCX H ; POINT TO NEXT CHARACTER IN INPUT STRING
RET
; TEST FOR VALID CHARACTER IN NAME FIELD
; RETURN IF INVALID WITH CARRY SET
; ADDED TEST FOR = SIGN ALSO 12/19/80
;
VALCHR: CPI CR ; TEST FOR C/R
CMC ; COMPL CARRY
RZ
CPI '*'
CMC
RZ
CPI ','
CMC
RZ
CPI '='
CMC
RZ
CPI '.'
CMC
RZ
CPI ' '
RC
CPI '^'+1
CMC
RC
CPI ':'
CMC
RNC
CPI 'A'-1
RET
;
;TEST FOR VALID FILE NAME TERMINATOR
;
TERMT: CPI ' '
RZ
CPI ','
RZ
CPI CR
RZ
CPI ';'
RZ
CPI '='
RZ
STC
RET
;
;SKIP SPACES IN COMMAND STRING
;
SKIPS: MVI A,' '
SKIPS1: CMP M
RNZ
INX H
JMP SKIPS1
; FILL BLOCK WITH VALUE
; ENTER WITH VALUE IN A
; DE=START OF BLOCK
; BC=LENGTH OF BLOCK
;
CLRB: XRA A ; ENTRY TO ZERO BLOCK
FILLB: INR B ; DOUBLE TALK TO AVOID MESSING WITH A
DCR B
JNZ FILLB1
INR C
DCR C
RZ
FILLB1: STAX D
INX D
DCX B
JMP FILLB
;
; END OF MAKEFCB.LIB
;
;
;
;
; FNCALC - CALCULATES THE FILE NUMBER RELATIVE TO THE OLD DIRECTORY
;
; ENTER WITH B=SLOT-K
;
; THE TERM NEW DIRECTORY REFERS TO THE MITS DIRECTORY WITH ALL DELETED FILES
; REMOVED. OND=>IS THE "ORIGIN OF THE NEW DIRECTORY" FCOUNT=>THE NUMBER OF
; FILES REALLY PRESENT IN THE NEW DIRECTORY
;
FNCALC LDA BUFFER+1
PUSH B
RLC ; *2
RLC ; *4
RLC ; *8 (THE BOOK IS WRONG, ITS 8*SSECTOR+)
MOV C,A ; SECTOR
MVI A,9
SUB B
ADD C ; 8*SECTOR+(SLOT+1)
POP B
RET
;
;
; MESSAGES
;
SIGNON DB 0DH,0AH,'MITS FILE COPY VERS '
DB VERS/10+'0','.',VERS MOD 10+'0'
DB ' (,',MODL+'0',')'
DB 0
FMTERR DB 0DH,0AH,'DIRECTRY FMT ERR'
DB 0
NFMSG DB 0DH,0AH,'NMBR OF FILES IN CURRENT '
DB 'DIRECTORY:',0
FLERRM DB 0DH,0AH,'FILE LINK ERROR ON MITS DISK',0
CKSUM DB 0DH,0AH,'CHECKSUM ERROR ON MITS FILE',0
DIRRD DB 0DH,0AH,'ERROR TRYING TO RECOVER MITS DIRECTORY FROM DISK',0
CPFMSG DB 0DH,0AH,'CP/M FILE NAME IN ERROR',0
TRKERR DB 0DH,0AH,'BAD TRACK ADDRESS',0
SECERR DB 0DH,0AH,'BAD SECTOR ADDRESS',0
FMTNG DB 0DH,0AH,'DATA SECTOR FORMAT IMPROPER',0
RDMSG DB 0DH,0AH,'READING MITS FILE',0
ENDMSG DB CR,0AH,'END OF CP/M DISK MEDIUM',0
EXTMSG DB CR,0AH,'ERROR ENCOUNTERED EXTENDING CP/M DISK',0
FULMSG: DB CR,0AH,'CP/M DIRECTORY FULL',0
NOMITS: DB CR,0AH,'NO MITS DISK FILE SPECIFIED',0
NAMERR DB CR,0AH,'ERROR SPECIFYING MITS DISK',0
DSKERR DB CR,0AH,'ERROR IN CONVERTING DISK NUMBER',0
NFMDMS DB ' FILES IN MITS DIRECTORY',CR,LF,0
DB CR,0AH,'TOO MANY OR TOO LONG ARGUMENTS',0
BMFN DB CR,LF,'BAD MITS FILE NAME (TOO LONG)',0
BADPUNK DB CR,LF,'IMPROPER FILE SYNTAX',0
FSRCHF DB CR,LF,'MITS FILE SEARCH FAILED',0
;
; CHARACTER OUTPUT TO CONSOLE
;
OUTEEE: MOV E,A
CPM TYPEF ; TYPE A CHARACTER
RET
CRLF MVI A,0DH
CALL OUTEEE
MVI A,0AH
JMP OUTEEE
;
PRMSG:
;
;PRINT MESSAGE TO ZERO BYTE
;FOR DETAILS SEE INTEL ISIS MANUAL OR CP/M SAMPLE BIOS
MOV A,M
ORA A
RZ
MOV E,A
CPM TYPEF
INX H
JMP PRMSG
;
;
;
; START OF MAIN PROGRAM
;
MCNVT LXI H,0
DAD SP ; SAVE CP/M STATUS AS THIS PROGRAM DOESN'T CLOBBER IT
SHLD CPMSTK ; STACK POINTER FOR CP/M
MCNVT1 LXI SP,STACK ; GET NEW STACK ADDRESS
MSG SIGNON ; PUT OUT SIGNON MESSAGE
MCNVT1A: CALL INITIAL ; INITIALIZE
CALL SETFILES
CALL MDRD ; RECOVER MITS FILE DIRECTRY
CALL SORT ; SORT DIRECTORY
CALL PRINTDIRECTRY
LXI D,MITSNAME
CALL LOOKUP ; LOOKUP NAME IN DIRECTORY
JNC MCNVT2 ; SEARCH SUCCESSFUL
MSG FSRCHF,MCNVT1A ; SEARCH FAILED
MCNVT2: CALL COPYFILE
CALL CRLF
LHLD NREC ; GET WRITE COUNTER
MOV B,H
MOV C,L
CALL CONVASCI ; CONVERT TO ASCII
LXI H,M1+4 ; START OF DIGIT STRING
MVI B,5 ; NO OF ASCII DIGITS
MVI E,0 ; FLAG TO SUPRESS ZERO
MCNVT3: MOV A,M ; GET A DIGIT
CPI '0'
JZ MCNVT6
MOV E,A ; SET FLAG SIGNIFICANT DIGIT
MCNVT4: CALL OUTEEE
MCNVT5: DCX H
DCR B
JNZ MCNVT3
CALL MCNVT8
MSG BLOCKMSG,MCNVT7
MCNVT6: MOV D,A
MOV A,E
ORA A
JZ MCNVT5 ; LEADING ZEROS
MOV A,D ; IN SIGNIFICANT PART OF INTEGER
JMP MCNVT4
BLOCKMSG: DB ' SECTORS COPIED TO CP/M FILE.',CR,LF,0
MCNVT7: CALL CLWRF ; CLOSE WRITE FILE
JMP MCNVT1A
MCNVT8: LXI H,BINARY
LDA FRSTCH
INR A
JZ MCNVT9 ; JUMP IF BINARY DATA
LXI H,ASCII
MCNVT9: CALL PRMSG
RET
BINARY: DB ' BINARY DATA',0
ASCII: DB ' ASCII BYTE DATA',0
; PRINT DIRECTORY ON MITS DISK - INVOKED BY =N
;
PUTDIR: INX H
CALL DN
STA DISK
CALL PMITS ; PRINT SORTED DIRECTORY
XRA A
STA TBUFF ; ZEROIZE TO PREVENT COMING BACK IN A LOOP
LXI SP,STACK
JMP MCNVT1A
; PRINT MITS FILE DIRECTORY
; THE DIRECTORY IS STORED AT OND
; IT MAY BE PRESORTED BY SORT OR IT MAY BE PRINTED
; WITHOUT SORTING.
;
PRINTDIRECTRY:
CALL CRLF
LDA FCOUNT
CALL DECOUT
MSG NFMDMS ; PUT OUT NUMBER OF FILES
LDA FCOUNT ; GET PRESET
MOV B,A ; NUMBER OF FILES IN DIRECTORY
LXI D,OND ; ORIGIN OF THE NEW MITS DIRECTORY
PRDIR1: CALL DLIST ; PRINT ONE DIRECTORY ENTRY
LXI H,DSIZE ; LENGTH OF A DIRECTORY ENTRY
DAD D ; PLUS ADDRESS
XCHG ; TO D
DCR B
JNZ PRDIR1 ; LOOP UNTIL ENTIRE DIRECTORY PRINTED
RET
DLIST: PUSH H
PUSH D
PUSH B ; SAVE EVERYTHING
XCHG ; HL=ADDRESS OF THIS ENTRY
LXI B,0803H ; MVI C,3; MVI B,8
DLIST1 MOV A,M ; FILE NAME TO A
CALL OUTEEE
INX H
DCR B
JNZ DLIST1
MVI A,' ' ; BLANK
DLIST2: CALL OUTEEE ; (THREE OF THEM)
DCR C
JNZ DLIST2 ; TO PRINTER
MOV A,M ; GET TRACK NUMBER
CALL DECOUT ; PRINT IT
MVI A,',' ; PRINT BLANK
INX H
CALL OUTEEE
MOV A,M ; GET SECTOR NUMBER
CALL DECOUT ; PRINT SECTOR NUMBER
MVI A,','
CALL OUTEEE
INX H
MOV A,M
MVI B,'R'
CPI 4 ; 4=RANDOM
JZ DLIST3
MVI B,'S'
DLIST3: MOV A,B
CALL OUTEEE ; PRINT FILE TYPE
MVI A,','
CALL OUTEEE
INX H ; GET TO FILE NUMBER
MOV A,M
CALL DECOUT ; PRINT FILE NUMBER
CALL CRLF
POP B
POP D
POP H
RET
;
; DECOUT => DECIMAL OUTPUT
;
; SUPPRESS LEADING ZERO
; OUTPUT A BLANK INSTEAD
;
DECOUT: PUSH D
PUSH B
MVI E,0 ; CLEAR ZERO FLAG
MVI C,100 ; DIVIDE BY 100
CALL DECOU1
MVI C,10 ; DIVIDE BY 10
CALL DECOU1
ADI '0' ; DIVIDE BY '1'
CALL OUTEEE ; UNITS
POP B
POP D
RET
DECOU1: MVI B,'0'-1
INR B
SUB C
JNC DECOU1+2 ; LOOP UNTIL DIVIDE RESULTS IN REMAINDER
ADD C
MOV D,A
MOV A,B
CPI '0' ; SENSE ZERO
JNZ DECOU2 ; NOT ZERO, SET FLAG NZ, OUTPUT ASCII
MOV A,E ; GET ZERO FLAG
ORA A ; SET
MOV A,D
RZ
DECOU2: INR E ; SET FLAG
MOV A,B
CALL OUTEEE
MOV A,D
RET
;
; COPYFILE => READS MITS FILE / WRITES CPM FILE
;
; AT THE START OF THE COPY, TRACK=TRACK ADDRESS OF FILE
; SECTOR = SECTOR ADDRESS OF FILE. DISK IS SELECTED FROM READ OF DIRECTORY
; TRACK AND SECTOR WERE SET BY DIRECTORY SEARCH SUBROUTINE.
;
; COPY PROCEEDS ONE SECTOR AT A TIME.
; READ MITS SECTOR, UPDATE TRACK AND SECTOR, WRITE CP/M SECTOR LOOP ETC.
; TERMINATES ON ZERO TRACK/SECTOR OR EOF CHARACTER.
;
COPYFILE:
LDA RANDFLAG ; IS FILE RANDOM
ORA A ; SET
JNZ APOLOGY ; DONT DO AT THIS TIME
CPYFL1: CALL RDMITS ; READ MITS DISK
CALL WRCPM ; WRITE CP/M FILE
LHLD BUFFER+5
MOV A,L
ORA H
JNZ CPYFL1
RET
APOLOGY: MSG APMSG,MCNVT
APMSG DB CR,LF,'CANT DO RANDOM FILES YET',0
;
;INITIALIZE
;
INITIAL: LXI H,BUFFER ; SET BUFFER ADDRESS
SHLD ADDR
MVI A,BSIZE
STA RWFLAG ; SAY READING
STA NWDS
XRA A
STA OP ; READING=0
STA RWFLAG
IF CHECKOUT
STA TBUFF
ENDIF
OUT 8 ; SELECT DRIVE 0
LXI H,0
SHLD NREC ; INITIALIZE WRITE COUNTER
CALL INPUTCDI
RET
;
; PMITS => RECOVERS AND PRINTS MITS DIRECTORY
;
PMITS CALL MDRD
CALL SORT
CALL PRINTDIRECTRY
RET
;
; SETFILES
; THIS ROUTINE SETS UP THE OUTPUT FILE
; IT CALLS ON CP/M TO SEARCH FOR THE FILE AND THEN IT
; DESTROYS IT IF FOUND.
;
SETFILES: LXI D,FCB ; SET UP FCB ADDRESS AS INPUT
PUSH D
CPM SRCHF
INR A ; NOT FOUND?
JZ SET1 ; YES
POP D
PUSH D
CPM DELETEF
SET1 POP D
PUSH D
CPM CREATEF
POP D
CALL SETUPO ; OPEN FILE
CPM SETDMA,BUFFER+7 ; DMA ADDRESS TO WRITE MITS FILE
RET ; RETURN TO USER
;
; END OF PROGRAM
;
;
; SECTOR TRACK ROUTINE FOR 88-DCDD
;
SECGET DI ; SECTOR ACQUIRE DON'T ALLOW TRAPPING
SG1 IN 9 ; GET CURRENT DATA STUFF
RAR
JC SG1
ANI 31 ; MASK OFF SECTOR NUMBER
CMP E ; E=>DESIRED SECTOR
JNZ SG1 ; NXT ONE MAYBE
RET
;
; TRACK ROUTINE
;
TRACKGET IN 8 ; GET STATUS OF DISK
ANI 4 ; IS HEAD LOADED?
CNZ LOADHEAD ; NOPE, LOAD IT
CALL FINDTRACK ; FIND TRACK IN RAT
LDA TRK ; FOR DEBUGGING TRK IS PUT HERE WHEN FOUND IN RAT
CMP D ; IS THIS THE DESIRED TRACK ON THIS DISK?
RZ ; YES
PUSH PSW ; SAVE RESULTS OF COMPARE
CALL LOADHEAD
POP PSW
JM STEPIN ; NEGATIVE MEANS HEAD IS TOO FAR TOWARDS EDGE
STEPOUT
CALL POUT ; POSITIVE, MEANS TOO FAR TOWARDS CENTER
LDA TRK
DCR A
STA TRK ; COUNT DOWN TRACK AS WE STEP HEAD
CMP D ; IS THIS THE DESIRED TRACK?
JNZ STEPOUT ; NO, KEEP COUNTING
CALL STORETRACK ; PUT TRACK BACK IN RAT
JMP MOVE
STEPIN CALL PIN
LDA TRK
INR A
STA TRK ; INCREMENT AS WE GO IN TOWARDS THE HUB
CMP D
JNZ STEPIN
CALL STORETRACK
JMP MOVE
PIN CALL MOVE
MVI A,1
OUT 9
RET ; STEPS HEAD INWARDS 1 TRACK
LOADHEAD MVI A,4 ; 4 SAYS MOVE HEAD ONTO THE SURFACE
OUT 9
LH1 IN 8 ; GET DISK STATUS
ANI 4 ; MOVEMENT ALLOWED?
RZ
JMP LH1
TRACK0 XRA A
STA TRK ; SET IT TO ZERO
CALL STORETRACK ; FIX RAT
TR01 CALL MOVE
IN 8
ANI 0100Q ; CHECK IF ON TRACK ZERO
RZ ; YES, DONE
CALL POUT ; STEP HEAD TOWARDS TRACK 0
JMP TR01
POUT CALL MOVE
MVI A,2 ; COMMAND TO STEP OUT
OUT 9
RET
MOVE IN 8
ANI 2 ; IS HEAD MOVEMENT ALLOWED (VALID SECTOR INDEX PULSE)
RZ ; YES
JMP MOVE
HEADUNLOAD MVI A,8 ; UNLOAD COMMAND
OUT 9
RET
FINDTRACK PUSH H ; FINDS TRACK IN RAPID ACCESS TABLE
LDA DISK
LXI H,RAT
CALL ADDAHL ; ADD A TO HL (GET WHICH DISK IT IS)
MOV A,M ; GET THE ENTRY FOR THAT DISK
STA TRK ; SET THAT TOO
POP H
RET
ADDAHL:
ADD L
MOV L,A
RNC
INR H
RET ; THATS ALL THERE IS TO IT
STORETRACK PUSH H
LXI H,RAT
LDA DISK
CALL ADDAHL ; ADD A TO HL GET THE RIGHT SLOT IN RAT
LDA TRK
MOV M,A
POP H
RET
; RAPID ACCESS TABLE
RAT DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
TRK EQU RAT+16
;
; READ A SECTOR FROM MITS DISK. SECTOR AND TRACK ARE ASSUMED SET
; PRIOR TO ENTRY. IF SECTOR AND TRACK ARE WRONG FOR FILE
; GROUP INDICATES "FILE LINK ERROR"
;
; IF CHECKSUM IS IN ERROR, "CHECKSUM ERROR" WILL BE INDICATED
;
RDMITS LDA TRACK
CPI 77 ; SENSE OFF DISK
JP BADTRK
ADI 0
JM BADTRK
LDA SECTOR
ADI 0
JM BADSEC
CPI 32
JP BADSEC
LXI H,BUFFER
SHLD ADDR
MVI A,BSIZE
STA NWDS
CALL DISKIN ; INPUT THE SECTOR
LDA FN ; GET CURRENT FILE NUMBER
LXI H,BUFFER+2 ; FILENUMBER ON DISK
CMP M ; SHOULD ALWAYS BE =
JNZ BADLNK ; FILE LINK ERROR
INX H
MOV A,M ; NUMBER DATA BYTES IN SECTOR
STA WRCOUNT ; SAVE NUMBER OF BYTES TO WRITE
INX H
MOV C,M ; GET CHECKSUM
LHLD BUFFER+5
MOV A,H
ANI 1
MOV A,H
JZ RDMIT1
ADI 16
ANI 1FH
RDMIT1: STA SECTOR
MOV A,L
STA TRACK
ADD H
MOV B,A
LDA FN
ADD B
MOV B,A
LDA WRCOUNT
ADD B
MVI B,128
LXI H,BUFFER+7
CSCALC ADD M
INX H
DCR B
JNZ CSCALC
XRA C ; CHECKSUM
JNZ BADCKS
PUSH H
LHLD NREC
MOV A,H
ORA L
JNZ SKIPIT
LDA BUFFER+7
STA FRSTCH ; SAVE FIRST CHARACTER OF FILE
SKIPIT: POP H
IF DEBUGGING
MOV A,M ; LOOK FOR CHECK BYTE
INR A ; 255+1=0
RZ
LXI H,CKBYTE ; CHECK BYTE ERROR
JMP CPMERR
CKBYTE DB CR,LF,'CHECK BYTE NOT FOUND IN MITS FILE'
ENDIF
IF NOT DEBUGGING
RET
ENDIF
;
; WRITE CP/M DISK FILE
;
WRCPM: LDA WRCOUNT ; GET WORD COUNT
CPI 128 ; CHECK FOR FULL BUFFER
JZ WRCPM1 ; YES,WRITE IT
MOV B,A ; SAVE COUNT
LXI H,BUFFER+7 ; START OF DATA REGION
CALL ADDAHL ; ADD WORDS WRITTEN
LDA FRSTCH
INR A ; =255=>BINARY FILE
JZ ZSR ; ZERO OUT REMAINDER OF BUFFER
MVI A,1AH ; EOF MARK FOR ASCII FILES
ZSR MOV M,A ; STORE ZERO OR 1A IN BUFFER
MVI A,128
SUB B
INX H
DCR A
JZ WRCPM1 ; JUMP IF ONLY ONE CHARACTER REMAINING (DONE)
MOV B,A
XRA A
ZRLOOP: MOV M,A ; ZEROIZE THE REST OF THE BUFFER
INX H
DCR B
JNZ ZRLOOP
WRCPM1: CPM WRITEF,FCB
LHLD NREC ; INCREMENT RECORD COUNT
INX H
SHLD NREC
ORA A
RZ ; WRITE OPERATION COMPLETED OK
CPI 2 ; < MEANS ERROR EXTENDING > MEANS DIRECTRY ERR
JZ ENDDSK
JC EXTERR
JMP DIRFUL
;
; SET UP CPM FILE
;
SETUPO: CPM OPENF ; OPEN CP/M FILE
CPI 255
JZ DIRFUL
RET
;
; SET UP FCB FOR OUTPUT
;
; DATA IS IN TFCB AND TFCB+16
;
KATHY: PUSH B
LDAX D
MOV M,A
INX D
INX H
DCX B
MOV A,B
ORA C
JNZ KATHY+1
POP B
RET
;
; CLOSE WRITE FILE
;
CLWRF: CPM CLOSEF,FCB ; CLOSE WRITE FILE
RET
;
;
;
; ERROR CONDITIONS
;
BADLNK LXI H,FLERRM
CALL PRMSG
JMP EXIT ; WE ARE ROGH ON ERRORS - YOU MIGHT WANT TO GO ON
BADSEC LXI H,SECERR ; SECTOR NOT 0-31
CALL PRMSG
JMP EXIT
BADTRK LXI H,TRKERR ; TRACK NOT 0-76
CALL PRMSG
JMP EXIT
BADCKS LXI H,CKSUM
CALL PRMSG
JMP EXIT
BADFMT LXI H,FMTNG
CALL PRMSG
JMP EXIT
ENDDSK: LXI H,FULMSG ; DISK FULL
JMP CPMERR ; ERROR ENCOUNTERED IN CP/M SEGMENT OF PROGRAM
EXTERR: LXI H,EXTMSG
JMP CPMERR
DIRFUL LXI H,FULMSG
CPMERR CALL PRMSG
JMP EXIT
;
;
;; READ MITS FILE DIRECTORY
;
; DESTROYS EVERYTHING - USES EVERYTHING
; DISK IS LEFT WITH HEAD UNLOADED ON TRACK 70
;
; DOESN'T SORT DIRECTORY
;
;
MDRD LDA DISK ; SELECT DISK
CALL DISKSET
XRA A
STA SECTOR
STA FCOUNT ; ZER OFILE COUNTER
STA OP ; READ=>0
MVI A,DTRACK ; DIRECTORY TRACK
STA TRACK ; DIRECTORY TRACK
LXI D,OND ; SET ORIGIN OF THE NEW DIRECTORY
MDRD1 LXI H,BUFFER ; SET ORIGIN OF INPUT BUFFER
SHLD ADDR ; SET ADDRESS OF INPUT BUFFER TO READ RTN
MVI A,BSIZE ; BUFFER SIZE
STA NWDS ; SET
CALL DISKIN ; READ A SECTOR
LXI H,BUFFER+DBIAS ; START OF MEANINGFUL DATA IN DIRECTORY
MVI B,NFPS
MDRD2 MOV A,M
ORA A
JZ MDRD5 ; DELETED OR EMPTY FILE
CPI ENDSLOT ; LAST ENTRY IN MITS DIRECTORY
RZ
PUSH H
MVI A,11
CALL ADDAHL ; POINT TO FIRST UNUSED LOC IN THIS ENTRY
CALL FNCALC
MOV M,A ; PUT FILE NUMBER IN OLD DIRECTORY
IF DEBUGGING
LDA SECTOR
INX H
MOV M,A
INX H
MVI A,9
SUB B
MOV M,A
ENDIF
POP H
MVI C,DSIZE ; SIZE OF ENTRY
MDRD3 MOV A,M
STAX D
INX D
INX H
DCR C
JNZ MDRD3 ; LOOP TILL DIRECTORY IS OBTAINED
LDA FCOUNT ; INCREMENT FILE COUNT
INR A
STA FCOUNT
MDRD4 DCR B ; NUMBER OF DIRECTORY ENTRIES/SECTOR
JNZ MDRD2
JMP MDRD6 ; READ NEXT DIRECTORY SECTOR
MDRD5 PUSH D
LXI D,DSIZE ; PASS VACANT DIRECTORY ENTRY
DAD D
POP D
JMP MDRD4
MDRD6 LDA SECTOR
ADI 17 ; LATENCY CALCULATION SCHTICK
CPI 32
JC MDRD7
SUI 32 ; REDUCE MODULO 32
MDRD7 STA SECTOR
JMP MDRD1
;SHELL-METZNER SORT
; THIS IS AN 8080 ADAPTATION OF THE SHELL SORT AS MODIFIED BY MARLENE METZNER
;
; IT WILL SORT ANY FIXED LENGTH RECORD OF UP TO 255 BYTES INTO ASCENDING ORDER.
; BY MODIFICATION OF THE PROGRAM AT "COMP" IT CAN SORT INTO DESCENDING ORDER OR
; CAN BE MADE TO EXIT EACH TIME THAT AN EQUAL RECORD IS FOUND.
;
;
;
; REGISTER USE:
;
; B=VAR I , C= VAR J , D= VAR K , E= VAR L , H= VAR M
; FOR MORE DETAILS SEE KNUTH, DONALD E.: THE ART OF COMPUTER PROGRAMMING,
; VOL. 3: SORTING AND SEARCHING. ADDISON-WESLEY, 1973
; THERE IS NO DIRECT REFERENCE TO METZNER'S MODIFICATION
SORT: LDA FCOUNT ; NUMBER OF RECORDS TO SORT
MOV H,A ; PUT IT IN H (FIRST TIME ONLY)
SORT1: MOV A,H ; START NEW PASS
ORA A ; CLEAR CARRY FLAG
RAR ;M=M/2 (VARM)
ORA A ; CLEAR CARRY
MOV H,A ; M=INT(M/2)
RZ ; SORT FINISHED
LDA FCOUNT ; GET N (NUMBER OF RECORDS)
SUB H ; MINUS M
MOV D,A ; SAVE IN D (K)
MVI C,1 ; SET VAR J=1
SORT2: MOV B,C ; SET I=J INNER LOOP
SORT3: MOV A,B
ADD H ; L=I+M (VAR L)
MOV E,A
SORT4: PUSH H
PUSH D
PUSH B
MOV A,B ; GET I
CALL SETAD ; CALCULATE ADDRESS (DISPLACEMENTS INTO RECORD)
SHLD CRCEL ; SAVE I ADDRESS DISPLACED
POP B
POP D
POP H
SORT5: PUSH H
PUSH D
PUSH B
MOV A,E ; GET L
CALL SETAD ; CALCULATE ADDRESS (DISPLACEMENT INTO RECORD)
SHLD CRCL1 ; SAVE L ADDRESS DISPLACED
POP B
POP D
POP H
SORT6: PUSH H
PUSH D
PUSH B
MVI B,8 ; LENGTH OF SORT FIELD
LHLD CRCL1 ; L RECORD ADDRESS
XCHG ; MOVE L RECORD COMPARE ADDRESS TO DE
LHLD CRCEL ; I-RECORD
XCHG ; I-RECORD ADDRESS TO DE, L RECORD TO HL
CALL COMP ; COMPARE STRINGS
POP B
POP D
POP H
TEST: ORA A
JZ SORT7
JM SORT7 ; SORT7=>NO SWAP
CALL XFER ; SWAP SUBROUTINE
MOV A,B
SUB H
MOV B,A ; I=I-M
JC SORT7
JNZ SORT3 ; SET NEW L
SORT7: INR C ; INCREMENT J COUNT
MOV A,D
CMP C ; J>K?
JC SORT1 ; YES, START NEW (NEXT) PASS
JMP SORT2 ; ELSE CONTINUE THIS PASS
; SUBROUTINES
;SETAD - SET ADDRESS
;
SETAD: MVI D,0
MOV E,A
MVI A,DSIZE ; LENGTH OF RECORD TO SORT
MOV H,D
MOV L,D
MVI B,8
SETAD1: DAD H
RLC
JNC SETAD2
DAD D
SETAD2: DCR B
JNZ SETAD1
XCHG
LXI H,OND-DSIZE
DAD D
RET
;
; XFER - SWAPS STRINGS I AND J
;
XFER: PUSH H
PUSH D
PUSH B
MVI B,DSIZE
LHLD CRCEL
XCHG
LHLD CRCL1
XFER1: LDAX D
MOV C,A
MOV A,M
STAX D
MOV M,C
INX D
INX H
DCR B
JNZ XFER1
POP B
POP D
POP H
RET
COMP: DCR B
RM
LDAX D
SUB M
INX D
INX H
JZ COMP
RET
;
; HARD SECTOR DISK INPUT
;
HSDI CALL SECGET
MVI C,BSIZE
HSDI1 IN 8
ORA A
JM HSDI1
IN 10
MOV M,A
INX H
DCR C
JZ HSDI2
DCR C
NOP
IN 10
MOV M,A
INX H
JNZ HSDI1
HSDI2 EI
RET
;
;DISK INPUT DRIVER COUPLER
;
DISKIN PUSH H
PUSH D
PUSH B
LDA DISK
OUT 8 ; SELECT DISK
LDA TRACK
MOV D,A
CALL TRACKGET
LDA SECTOR
MOV E,A
LHLD ADDR
CALL HSDI
CALL HEADUNLOAD
POP B
POP D
POP H
RET
DISKSET:
PUSH PSW
OUT 8 ; SELECT DISK
NOP ; IN CASE HARDWARE DOESN'T WORK
IN 8 ; SENSE READY
ANI 020H ; SENSE INTERRUPTS ENABLED (READY)
JNZ WAITUP ;
POP PSW
CALL TRACK0
RET
WAITUP: MVI A,200
WAIT1: DCR A
JNZ WAIT1
POP A
OUT 8
NOP
NOP
JMP DISKSET
DS 50 ; STACK REGION
STACK EQU $
CPMSTK DW 0 ; CP/M STACK POINTER
END 0100H ; START OF TPA