home *** CD-ROM | disk | FTP | other *** search
- TITLE '"PASTOCPM" - Convert Pascal file to CP/M file'
- ;From DR. DOBB'S - August 1979
- ;Copyright (C) 1979 Ronald G. Parsons
- ;Modified by T. Mueller 9/1/79
- ; Changes include:
- ; Provisions for designating disk drives.
- ; Re-ordering calls to disk routines to be of the form:
- ; select disk, select track, select sector, read/write.
- ; Cleaned up handling of null codes in .TEXT files.
- ; Set up new stack area and data buffers.
- ; Changed exit to simple return, no re-boot.
- ; Guaranteed .TEXT file on CP/M disk ends in EOF.
- ; Memory size independance for BIOS calls.
- ;9/22/79 - Corrected handling of DLE as last byte of read block.
- ;
- ;Transfers a Pascal file to CP/M file.
- ;
- ;Syntax -- PASTOCPM <[d:]CP/M filename> <[d:]Pascal filename>
- ;
- ;Disk drive (d:) identifiers may be entered. If none are supplied
- ; defaults are: CP/M file on logged drive, Pascal file on drive B:.
- ;
- ;Transfers the Pascal filename on a Pascal disk
- ; to the CP/M filename on a CP/M disk. If the CP/M file already exists,
- ; you will be asked for permission to overwrite.
- ;If the Pascal file is a .TEXT file, then two blocks are skipped
- ; and tabs replaced by spaces. LF is added after each CR.
- ;If the Pascal file is a .CODE file, then one block is skipped.
- ;If file is neither .TEXT or .CODE, the copy is exact.
- ;
- ;
- DLE EQU 10H
- DENTSZ EQU 26 ;DIRECTORY ENTRY SIZE IN BYTES
- DTITLE EQU 6 ;OFFSET TO ENTRY TITLE
- ;
- ORG 100H
- START LXI H,0
- DAD SP
- SHLD STACK
- LXI SP,STACK ;SET UP PRIVATE STACK
- ;
- MVI C,LOGGED ;GET LOGGED DISK DRIVE
- CALL BDOS
- STA LDRIVE
- LDA FCB ;GET CP/M DRIVE
- ORA A
- JNZ DOIT ;NOT LOGGED DRIVE
- LDA LDRIVE ;GET LOGGED DRIVE
- INR A
- STA FCB ;FORCE SELECTION OF DRIVE
- DOIT LXI H,BUFF ;GET PASCAL FILE NAME
- LXI D,SYSTLE+1
- MVI A,1
- STA RDRIVE ;SET PASCAL DEFAULT TO DRIVE B
- SCN1 CALL SCBLK ;FIND NON-BLANK
- JZ SCN1
- SCN2 CALL SCBLK ;FIND BLANK
- JNZ SCN2
- SCN3 CALL SCBLK ;FIND START OF SECOND PARM
- JZ SCN3
- INX H
- MOV A,M
- CPI ':' ;CHECK IF DRIVE ENTERED
- DCX H
- JNZ SCN4
- MOV A,M ;GET DRIVE
- SUI 'A'
- STA RDRIVE ;SAVE READ DRIVE
- INX H
- INX H ;SKIP DRIVE
- SCN4 PUSH H
- LXI H,RDRIVE
- LDA FCB
- DCR A
- CMP M ;CHECK IF READ AND WRITE DRIVES ARE SAME
- POP H
- JZ DRVERR
- MVI C,0
- PFN2 MOV A,M
- ORA A
- JZ PFN3
- STAX D
- INX H
- INX D
- INR C
- JMP PFN2
- ;
- PFN3 MOV A,C ;GET FILENAME LENGTH
- STA SYSTLE
- ORA A
- JZ NOFLNM
- ;CHECK FOR .TEXT OR .CODE FILENAME
- LXI D,TEXT+6
- DCX H ;HL POINTS TO END OF FILENAME
- PUSH H
- MVI C,5
- TEXTLP LDAX D
- CMP M
- JNZ NOTEXT ;FILENAME DOES NOT END IN .TEXT
- DCX H
- DCX D
- DCR C
- JNZ TEXTLP
- LXI H,TXTFLG ;GOT .TEXT FILE
- MVI M,2
- LXI D,TEXT
- MVI C,WRITECB
- CALL BDOS
- ;
- NOTEXT POP H ;POINT TO END OF FILENAME
- LXI D,CODE+6
- MVI C,5
- CODELP LDAX D
- CMP M
- JNZ NOTCODE ;FILENAME DOES NOT END IN .CODE
- DCX H
- DCX D
- DCR C
- JNZ CODELP
- LXI H,TXTFLG
- MVI M,1 ;GOT .CODE FILE
- LXI D,CODE
- MVI C,WRITECB
- CALL BDOS
- ;
- NOTCODE LXI D,FCB
- MVI C,OPENF ;OPEN FILE
- CALL BDOS
- CPI 0FFH ;NON-EXISTANT?
- JZ CREF ;YES - CREATE IT
- LXI D,PERMSG ;GET PERMISSION TO DELETE IT
- MVI C,WRITECB
- CALL BDOS
- ;
- RDCHR MVI C,READC ;READ CONSOLE
- CALL BDOS
- CPI ABORT
- JZ EXIT
- CPI CR
- JNZ RDCHR ;INVALID RESPONSE, TRY AGAIN
- MVI E,LF
- MVI C,WRITEC ;CHARACTER TO CONSOLE
- CALL BDOS
- LXI D,FCB
- MVI C,DELETEF ;KILL FILE
- CALL BDOS
- ;
- CREF LXI D,FCB
- MVI C,CREATEF ;CREATE FILE
- CALL BDOS
- CPI 0FFH ;ERROR?
- JZ CERROR ;YES
- ;
- ;INITIALIXE BUFFER POINTERS
- ;
- INIT LXI H,BUFF
- SHLD BOL
- LXI H,BUFF+127
- SHLD EOB
- LXI H,BLKBUF+512
- SHLD BUFADD
- ;
- LXI B,DIRTOP ;READ DIRECTORY INTO THIS
- CALL READ$DIR
- ;
- LXI H,DIRTOP ;SET DIRECTORY ENTRY POINTER
- LXI D,DENTSZ ; TO FIRST ENTRY AFTER VOLUME NAME
- DAD D
- SHLD DENTP
- ;
- CALL FIND$FILE ;FIND THE FILE
- ;
- LHLD DENTP ;START OF DIRECTORY ENTRY
- MOV E,M
- INX H
- MOV D,M
- PUSH D ;SAVE FIRST BLOCK
- INX H
- MOV E,M
- INX H
- MOV D,M
- XCHG ;LAST BLOCK+1 IN HL
- DAD H ;X2
- DAD H ;X4
- SHLD LSTLSN ;(LAST LSN + 1) * 4
- POP H ;GET FIRST BLOCK
- LDA TXTFLG
- SKPBL1 DCR A ;SKIP BLOCKS DEPENDING ON
- JM SKPBL2 ; .TEXT OR .CODE
- INX H
- JMP SKPBL1
- ;
- SKPBL2 DAD H ;X2
- DAD H ;X4
- SHLD LSN ;(FIRST LSN) * 4
- ;
- LR80B CALL R80B ;READ 128 BYTES
- LDA EOFFLAG
- ORA A ;LAST PASCAL SECTOR READ?
- JNZ FILL1A ;YES
- CALL WB ;WRITE BUFFER
- JMP LR80B
- ;
- FILL1A CALL CT ;FILL BUFFER WITH EOF
- CALL WB ;WRITE BUFFER
- LDA TXTFLG
- CPI 2 ;.TEXT?
- JNZ FILL2 ;NO
- LHLD EOB
- MOV A,M
- CPI EOF ;CHECK IF LAST SECTOR WRITTEN HAS EOF
- JZ FILL2
- LXI H,BUFF
- SHLD BOL
- JMP FILL1A
- FILL2 LXI D,FCB
- MVI C,CLOSEF ;CLOSE FILE
- CALL BDOS
- EXIT LXI D,BUFF
- MVI C,DMAADD
- CALL BDOS
- LDA LDRIVE ;GET LOGGED DRIVE
- MOV E,A
- MVI C,SELECTD ;RESTORE LOGGED DRIVE
- CALL BDOS
- LHLD STACK
- SPHL ;RESTORE SP
- RET ;JOB DONE - GO BACK
- ;
- ;*********************************************************
- ;
- ; SUBROUTINES
- ;
- ;*********************************************************
- ;
- ;READ DIRECTORY'S 4 BLOCKS TO BUFFER
- ;BUFFER ADDRESS IS ALREADY IN REG-BC
- ;
- READ$DIR:
- MVI E,4 ;DIRECTORY IS 4 BLOCKS LONG
- LXI H,2 ; AND STARTS AT BLOCK 2
- CALL SYSRD ;GET IT
- RET
- ;
- ;
- FIND$FILE:
- MVI C,77 ;STOP AFTER THE 77'TH ENTRY
- LHLD DENTP ;GET STARTING ENTRY
- FI$SCH$LP:
- LXI D,DTITLE ;ADVANCE TO TILTE STRING
- DAD D
- LXI D,SYSTLE ;SET REG-DE TO COMPARISON STRING
- LDA SYSTLE ;COMPARISON LENGTH
- INR A ;COMPARE INCLUDES LENGTH BYTE
- MOV B,A
- FI$CMP$LP:
- LDAX D
- CMP M
- JNZ FI$CONT ;IT'S NOT THIS ONE
- INX D
- INX H
- DCR B ;CHECK FOR END OF STRING
- JNZ FI$CMP$LP ;NOT YET
- JMP FI$FOUND ;FOUND IT
- ;
- FI$CONT:
- LHLD DENTP ;ON TO THE NEXT ENTRY
- LXI D,DENTSZ
- DAD D
- SHLD DENTP
- DCR C ;IS THERE ANY DIRECTORY LEFT?
- JNZ FI$SCH$LP ;YES
- FI$HANG:
- JMP NOFILE ;FILE NOT THERE
- ;
- FI$FOUND:
- RET ;GOT IT
- ;
- ;
- ;READ BLOCKS FROM PASCAL DISKETTE
- ;
- SYSRD PUSH D ;SAVE BLOCK COUNT
- PUSH H ; AND BLOCK NUMBER
- CALL READ$RX ;BUFFER IS ADVANCED BY 512 BYTES
- POP H
- POP D
- INX H ;ADVANCE TO NEXT BLOCK
- DCR E ;SEE IF WE'RE DONE
- JNZ SYSRD
- RET
- ;
- ;
- ;READ A PASCAL BLOCK
- ;
- READ$RX:
- DAD H ;THERE ARE 4 SECTORS TO A BLOCK
- DAD H ;MULT LOGICAL BLOCK BY 4
- MVI E,4
- RR$LP PUSH B ;SET BUFFER ADDRESS
- PUSH D
- PUSH H
- CALL SETDMA
- POP H ;NOW COMPUTE TRACK/SECTOR
- PUSH H
- CALL MAP ;CONVERTS LOGICAL SECTOR IN HL
- PUSH H
- LDA RDRIVE
- MOV E,A
- MVI C,SELECTD ;SELECT READ DISK
- CALL BDOS
- POP H
- MOV C,H ; INTO TRACK H, SECTOR L
- PUSH H
- CALL SETTRK
- POP H
- MOV C,L
- CALL SETSEC
- CALL READ
- ORA A
- JNZ RWERR
- POP H
- POP D
- POP B
- PUSH H ;ADVANCE THE BUFFER ADDRESS
- LXI H,128
- DAD B
- MOV B,H
- MOV C,L
- POP H
- INX H ;ADVANCE THE BLOCK COUNT
- DCR E ;SEE IF WE CONTINUE
- JNZ RR$LP ;YES
- RET
- ;
- ;
- ;READ SECTOR GIVEN BY LSN
- ;
- RDSEC MVI C,DMAADD
- CALL BDOS
- LHLD LSN
- CALL MAP ;CONVERT LOGICAL SECTOR # TO TRACK/SECTOR
- MOV C,H
- PUSH H
- CALL SETTRK
- POP H
- MOV C,L
- CALL SETSEC
- CALL READ
- ORA A
- JNZ RWERR
- LHLD LSN
- INX H
- SHLD LSN
- RET
- ;
- ;CLEAR TO END OF BUFFER
- ;
- CT LHLD EOB
- INX H
- XCHG
- LHLD BOL
- CT1 CALL EQUAL
- RZ
- MVI M,EOF
- INX H
- JMP CT1
- ;
- EQUAL MOV A,L
- CMP E
- RNZ
- MOV A,H
- CMP D
- RET ;ZERO IF DE=HL
- ;
- ;READ A SECTOR TO BUFFER
- ;
- R80B MVI B,128
- LXI H,BUFF
- R80B1 PUSH B
- PUSH H
- CALL RB
- POP H
- POP B
- PUSH PSW
- LDA EOFFLAG
- ORA A
- JZ R80B2 ;NOT EOF
- POP PSW
- SHLD BOL
- RET
- ;
- R80B2 POP PSW
- MOV M,A
- INX H
- DCR B
- JNZ R80B1
- RET
- ;
- ;WRITE 128 BYTE BUFFER
- ;
- WB LXI D,BUFF
- MVI C,DMAADD
- CALL BDOS
- LXI D,FCB
- MVI C,WRITER
- CALL BDOS
- ORA A
- JNZ RWERR
- RET
- ;
- ;SCAN FOR BLANKS IN COMMAND LINE
- ;
- SCBLK INX H
- MOV A,M
- CPI 0 ;CHECK IF END OF INPUT LINE
- JZ NOFLNM
- CPI ' '
- RET
- ;
- ;PROCESS LF AND TAB FILL, GET BYTE FROM READ BUFFER
- ;
- RB LDA TXTFLG
- CPI 2
- JNZ RBFB ;NOT .TEXT
- RCCKLF LDA NLF ;NEED LF?
- ORA A
- JZ RBCKTB
- XRA A
- STA NLF
- MVI A,LF
- RET
- ;
- RBCKTB LDA NTB ;NEED TAB?
- ORA A
- JZ RBFB
- DCR A
- STA NTB
- MVI A,' '
- RET
- ;
- ;GET BYTE FROM READ BUFFER, AND FILL IF NEEDED
- ;
- RBFB LHLD BUFADD
- LXI D,BLKBUF+512
- CALL EQUAL ;CHECK FOR END OF BUFFER
- JZ RBLK
- LDA TXTFLG
- CPI 2 ;.TEXT?
- JNZ NOTEXT2
- LDA DFLAG ;WAS LAST CHAR DLE?
- ORA A
- JNZ RBFBT ;YES
- MOV A,M
- ORA A
- INX H
- SHLD BUFADD
- JZ RBFB ;SKIP BYTE OF ZERO
- CPI CR
- JNZ CKDLE
- STA NLF ;PUT LF AFTER CR
- RET
- ;PROCESS BYTE FOLLOWING DLE
- ;
- RBFBT MOV A,M
- INX H
- SHLD BUFADD
- SUI 32 ;GET INDENTATION
- STA NTB ;SAVE NUMBER OF COLUMNS TO INDENT
- XRA A
- STA DFLAG ;CLEAR TAB FLAG
- JMP RBCKTB ;DO BLANK EXPANSION
- ;
- ;CHECK FOR DLE CODE - USED FOR INDENTATION
- ;
- CKDLE CPI DLE
- RNZ
- STA DFLAG ;SET FLAG FOR DLE FOUND
- JMP RBFB ;GET NEXT BYTE (COUNT)
- ;
- NOTEXT2 MOV A,M
- INX H
- SHLD BUFADD
- RET
- ;
- ;READ 4 SECTORS (A PASCAL BLOCK)
- ;
- RBLK LHLD LSN ;GET START LOGICAL SECTOR NUMBER
- XCHG
- LHLD LSTLSN
- CALL EQUAL
- JZ SETEOF ;FOUND LAST SECTOR
- LDA RDRIVE ;GET READ DRIVE NUMBER
- MOV E,A
- MVI C,SELECTD ;SELECT DISK
- CALL BDOS
- LXI D,BLKBUF ;READ 4 SECTORS
- CALL RDSEC
- LXI D,BLKBUF+128
- CALL RDSEC
- LXI D,BLKBUF+256
- CALL RDSEC
- LXI D,BLKBUF+384
- CALL RDSEC
- LXI H,BLKBUF
- SHLD BUFADD ;RESET POINTER TO START OF BUFFER
- JMP RBFB
- ;
- SETEOF LXI H,EOFFLAG
- MVI M,1 ;LAST SECTOR ALREADY READ
- RET
- ;
- ;ERROR MESSAGES
- ;
- NOFLNM LXI D,NOFLNMSG
- JMP GENERR
- ;
- NOFILE LXI D,NOFMSG
- JMP GENERR
- ;
- RWERR ORI '0' ;MAKE IT ASCII
- STA WERMSG
- LXI D,WERMSG
- GENERR MVI C,WRITECB
- CALL BDOS
- JMP EXIT
- ;
- CERROR LXI D,ERRMSG
- ORI '0'
- STA ERRMSG
- JMP GENERR
- ;
- DRVERR LXI D,DERMSG
- JMP GENERR
- ;
- ;TURN LSN INTO TRACK/SECTOR
- ;
- ;NOTE - TRACK 0 IS NOT USED, SO BLOCK 0 IS AT TRACK 1 SECTOR 1
- ;
- ;ON ENTRY - REG-HL HAS LOGICAL BLOCK # * 4 = LOGICAL SECTOR #
- ;ON EXIT - REG-H HAS PHYSICAL TRACK
- ; REG-L HAS PHYSICAL SECTOR
- ;
- MAP PUSH B
- PUSH D
- CALL DIV26
- MOV A,L
- ADD A
- MOV B,A
- MVI A,12
- CMP L
- JNC MAPC
- INR B
- MAPC MOV C,E
- XRA A
- MOV D,A
- MOV H,A
- MOV L,B
- MVI A,6
- MAP$LOOP:
- DAD D
- DCR A
- JNZ MAP$LOOP
- PUSH B
- CALL DIV26
- POP B
- INR L
- MOV H,C
- INR H
- POP D
- POP B
- RET
- ;
- ;
- DIV26 LXI B,-26
- MVI E,0FFH
- DIVL INR E
- DAD B
- MOV A,H
- ORA A
- JP DIVL
- LXI B,26
- DAD B
- RET
- ;
- ;
- ;
- ;BIOS ENTRIES
- ;
- SETTRK LHLD 1
- MVI L,1EH
- PCHL
- ;
- SETSEC LHLD 1
- MVI L,21H
- PCHL
- ;
- SETDMA LHLD 1
- MVI L,24H
- PCHL
- ;
- READ LHLD 1
- MVI L,27H
- PCHL
- ;
- NOFLNMSG DB CR,LF,'ERROR - Missing file name$'
- NOFMSG DB CR,LF,'"Pascal" file does not exist$'
- WERMSG DB ' Read/Write ERROR$'
- PERMSG DB CR,LF,'"CP/M" file already exists.'
- DB CR,LF,'C/R to continue, CTRL-C to abort$'
- ERRMSG DB ' ERROR in file Create or Open$'
- TEXT DB CR,LF,'.TEXT file being processed$'
- CODE DB CR,LF,'.CODE file being processed$'
- DERMSG DB CR,LF,'ERROR - Both files on same drive$'
- ;
- ;
- TXTFLG DB 0
- DENTP DS 2
- EOFFLAG DB 0
- NLF DB 0
- NTB DB 0
- DFLAG DB 0
- BUFADD DS 2
- LSN DS 2
- LSTLSN DS 2
- BOL DS 2
- EOB DS 2
- SYSTLE DS 22
- RDRIVE DS 1 ;DRIVE FOR READ
- LDRIVE DS 1 ;LOGGED DRIVE ON ENTRY
- ;
- DS 64 ;STACK AREA
- STACK DS 2 ;ENTRY SP
- BLKBUF DS 512
- DIRTOP DS 2048
- ;
- ;
- ;CP/M EQUATES
- ;
- BDOS EQU 5
- FCB EQU 5CH
- BUFF EQU 80H
- READC EQU 1 ;READ CONSOLE CHARACTER
- WRITEC EQU 2 ;WRITE CONSOLE CHARACTER
- WRITECB EQU 9 ;WRITE CONSOLE BUFFER
- SELECTD EQU 14 ;SELECT DRIVE
- OPENF EQU 15 ;OPEN FILE
- CLOSEF EQU 16 ;CLOSE FILE
- DELETEF EQU 19 ;DELETE FILE
- WRITER EQU 21 ;WRITE RECORD
- CREATEF EQU 22 ;CREATE FILE
- LOGGED EQU 25 ;GET LOGGED DRIVE
- DMAADD EQU 26 ;SET DMA ADDRESS
- ;
- CR EQU 0DH
- LF EQU 0AH
- ABORT EQU 3 ;CRTL-C
- EOF EQU 1AH
- ;
- END START
-