home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ENTERPRS
/
CPM
/
UTILS
/
S
/
SPLIT14.LBR
/
SPLIT14.ZZ0
/
SPLIT14.Z8°
Wrap
Text File
|
2000-06-30
|
12KB
|
611 lines
; File Splitter
;
;By Guy Cousineau 1988-02-02
;
;This utility has no copyright and is
;being released to the public domain. It
;has been thouroughly tested and should
;behave as advertized. The author,
;however, will assume no responsibility
;for loss or damage resulting from the
;use of the program. The source code
;only is being released; it should
;assemble easily with any Z80 assembler.
;
;comments or suggestions?
;
; Guy Cousineau
; 1059 Hindley Street
; Ottawa Ontario
; K2B 5L9
; 613-829-6354
; Ottawa RCPM (613) 829-2530
;
;Syntax SPLIT [d:]ufn [d:]nn [/n]
;
;Drive spec optional.
;If source and destination are the same,
;swap prompts will be given unless the
;'/n' option is used to create the split
;files on the same media.
;
;files are split in 16k segments unless
;overriden by 'nn'
;
;e.g. SPLIT long.doc 20 /n
;will split long.doc in 20k segments
;on the default drive with no disk swaps
;
; Warning I
;The output files will have the same name
;except that the last 2 characters of the
;file type will have the section number
;starting at 01. For example, splitting
;LONG.DOC would yield files LONG.D01
;LONG.D02, etc. Be Sure Your Input File
;Does Not Have A Number In The Last Two
;Position.
;
; Warning Ii
;
;The utility will not work with Wordstar
;type files with high bit set on <LF>.
;
;
;Revision History:
;
; 1.0 ??-?? first release
; 1.1 ??-?? introduced the noswap option
; 1.2 92-06 fixed split bug on files over 144k
; added variable output file size
; 1.3 92-07 fixed write bug for generic CP/M
; 1.4 93-04 increased output file size to max of 48K
; made 32K the default
;
;System Equates
;
GETKEY EQU 1 ;Read keyboard
PRINTC EQU 2 ;Print character
PRINT EQU 9 ;Print string
RESET EQU 13 ;Log in drive for R/W
OPEN EQU 15 ;Open file
CLOSE EQU 16 ;Close file
DELETE EQU 19 ;Delete file
READ EQU 20 ;Read sequential
WRITE EQU 21 ;Write sequential
MAKE EQU 22 ;Make file
GETDSK EQU 25 ;Get current disk
SETDMA EQU 26 ;Set memory address for R/W
;
FCB EQU 5CH
FCB2 EQU 6CH
BDOS EQU 5
DMA EQU 80H
;
ORG 100H
LD (OLDSP),SP
LD SP,STACK
;
LD HL,FCB+1
LD A,(HL)
LD DE,SYNTAX
CP ' '
JP Z,QUIT ;No file given, show syntax
;
;Check For Wild Cards
;
LD BC,11
LD A,'?'
CPIR
LD DE,WILD
JP Z,QUIT
;
;Check For Invalid Type
;
LD DE,NUMERR
LD A,(FCB+11)
CP '1' ;'0' is Ok
JR C,NONUM
CP '9'+1
JP C,QUIT ;if last digit between 1 and 9
;
NONUM
XOR A
LD (FCB+12),A ;extent
LD (FCB+14),A ;S2
LD (FCB+32),A ;record count
;
LD HL,FCB ;input file
LD DE,WFCB ;store it here for write
LD BC,12
LDIR
;
LD A,(FCB2)
OR A ;if none specified then same
JR Z,SAMEDISK
LD HL,FCB
CP (HL) ;if same as source drive
JR Z,SAMEDISK
LD (WFCB),A
LD (SAMEDSK),A
XOR A
LD (SWAPFLG),A ;if different clear swap flag
JR SETDISK
;
;Check For Noswap
;
SAMEDISK
LD HL,DMA
LD C,(HL)
LD B,0
LD A,'/' ;option delimiter
CPIR
JR NZ,SETDISK
LD A,(HL)
AND 5FH
SUB 'N'
LD (SWAPFLG),A ;Will be zero only if 'n' or 'N'
;
;Set Default Drive To Actual
;Since Disk Reset Will Interfere
;
SETDISK
LD C,GETDSK
CALL BDOS
LD B,A
INC B ;adjust to drive code
LD HL,FCB
LD A,(HL)
OR A
JR NZ,SETD1
LD (HL),B
SETD1
LD HL,WFCB
LD A,(HL)
OR A
JR NZ,CHECKSIZE
LD (HL),B
;
;check for override of default split size
;
CHECKSIZE:
LD HL,FCB+17 ;byte 1 of FCB 2
LD A,(HL) ;check to see
CP ' ' ;if it is empty
JR Z,SETLAST ;then use default 16k
CP '/' ;or option character
JR Z,SETLAST ;
SUB '0' ;is it a number
JP C,BADNUM ;abort program
CP 10 ;make sure less than 10
JP NC,BADNUM
LD B,A ;save a times 1
RLCA ;2*a
RLCA ;4*a
ADD A,B ;5*a
RLCA ;10*a
LD B,A ;save in B temporarily
INC HL ;next byte
LD A,(HL) ;get it and check vailidity
SUB '0'
JP C,BADNUM
CP 10
JP NC,BADNUM
ADD A,B ;add Tens to units just retrieved
CP 49
JP NC,BADNUM ;set max to 32k
;
;now turn it into records
;
LD H,0
LD L,A
ADD HL,HL
ADD HL,HL
ADD HL,HL ;*8
LD (PATCH1),HL
LD (PATCH2),HL
LD (PATCH3),HL
ADD HL,HL ;*16
ADD HL,HL ;*32
ADD HL,HL ;*64
ADD HL,HL ;*128
ADD HL,HL ;*256
ADD HL,HL ;*512
ADD HL,HL ;*1024
LD DE,BUFFER
ADD HL,DE ;get offset to end of buffer
LD (PATCH4),HL
DEC HL
DEC HL
LD (PATCH5),HL
;
;Set Last Character Of File Type To '0'
;
SETLAST
LD HL,WFCB+11 ;Last Digit Of File Type
LD B,'0'
LD (HL),B ;Set Count To 0
DEC HL
LD (HL),B
DEC HL
LD A,(HL) ;set first of fle type to '0' if blank
CP ' '
JR NZ,GO
LD (HL),B
;
GO
LD DE,START
CALL PROMPT ;in case we need a swap to start
;
;Find File And Open It
;
LD DE,FCB
LD C,OPEN
CALL BDOS
LD DE,NOFL ;error message just in case
INC A ;255+1=0 on error
JP Z,QUIT ;show error and exit
;
;Zero Record Count
;
READAGAIN
XOR A
SBC HL,HL
LD (IRCNUM),HL
;
LD DE,FCB
PUSH DE
;
;Set Up DMA For Read
;
LD HL,BUFFER
LD DE,(OBUFF) ;Get read-in offset
ADD HL,DE ;write in file here
CALL INCB1 ;set DMA and buffer
;
;Read Next Record Of File
;
LD BC,32*8 ;read 32k at a time
PATCH1 EQU $-2
READF
POP DE ;FCB
PUSH DE
PUSH BC
LD C,READ
CALL BDOS
OR A ;=0 if good read and not EOF
JR NZ,XDISK ;get ready to write
CALL INCBUF ;increment DMA for next record
LD HL,(IRCNUM)
INC HL ;In record count
LD (IRCNUM),HL
CALL DUMPIT ;print value in HL
POP BC
DEC BC
LD A,B
OR C
JR NZ,READF
;
;Prompt For Disk Change
;
XDISK
POP DE ;Clean up stack
LD A,(SWAPFLG)
OR A
JR Z,NOSWAP
LD DE,DDISK ;Swap disk message
CALL PROMPT
LD C,RESET
CALL BDOS
;
;Increment File Type
;
NOSWAP
LD HL,WFCB+11 ;Last digit of file type
LD A,(HL)
INC A
CP '9'+1
JR NZ,GOODNUMBER ;just increment last digit
DEC HL ;move to previous
INC (HL) ;bump it up
INC HL ;back to last
LD A,'0' ;make it Zero
GOODNUMBER:
LD (HL),A
XOR A
SBC HL,HL
LD (ORCNUM),HL ;output record count
LD (WFCB+12),A ;extent
LD (WFCB+14),A ;S2
LD (WFCB+32),A ;record number
;
;Delete File Name From Destination Disk
;
LD DE,WFCB
PUSH DE
LD C,DELETE
CALL BDOS
;
;Create New File
;
POP DE
PUSH DE
LD C,MAKE
CALL BDOS
LD DE,BADIR ;error message
INC A ;255+1=0 on error
JR Z,QUIT
;
;Find Last <LF> In File
;
LD HL,(IRCNUM)
LD BC,32*8 ;Read a full PARTITION?
PATCH2 EQU $-2
OR A
SBC HL,BC
JP NZ,LASTWRITE
LD HL,SAFEREC ;safety buffer to read all of last extent
INC (HL) ;write one more record for each split
;
;Start At The End Of The Buffer -2 Characters
;If Either Of The Last 2 Characters Are <LF>
;We Will Get A Negative Offset Later.
;
LD HL,BUFFER+32*1024-2
PATCH5 EQU $-2
LD A,10 ;<LF>
LD BC,-1 ;Make sure we find one
CPDR
;Presume One Is Found
INC HL ;Move back to last <LF>
INC HL ;Use next character after <LF>
LD (LASTLF),HL ;Save the address
LD A,(HL)
LD (LASTC),A ;Save character
LD (HL),26 ;Write EOF
;
;Set Up DMA For Write
;
WRITE1
LD HL,BUFFER ;Write file from start of buffer
CALL INCB1 ;set DMA
;
;Start To Write File
;
WRITEF
POP DE ;FCB
PUSH DE
LD C,WRITE
CALL BDOS
LD DE,BADFL ;Write error message
OR A
JP NZ,QUIT
CALL INCBUF ;Get next DMA
LD HL,(ORCNUM) ;Records written
INC HL
LD (ORCNUM),HL
PUSH HL
CALL DUMPIT
LD HL,(IRCNUM) ;Amount to copy
POP DE
OR A
SBC HL,DE ;Write as many as we read?
JR NZ,WRITEF ;Not done yet
;
;Close File
;
POP DE ;FCB
LD C,CLOSE
CALL BDOS
LD DE,BDCLOSE ;Error message
INC A ;255+1=0 on error
JR Z,QUIT
;
;Write Output File Name To Screen
;
LD A,32 ;Start with a space
CALL PRCHR
LD HL,WFCB+1 ;Name starts here
LD B,11 ;Length of name
FNAME1
LD A,(HL)
CALL PRCHR
INC HL
DJNZ FNAME1
;
;Check If Last Read
;
LD HL,(ORCNUM)
LD BC,32*8 ;Did we write 32k?
PATCH3 EQU $-2
OR A
SBC HL,BC
JR Z,NOTYET
LD DE,DONE
QUIT
LD C,PRINT
CALL BDOS
QUIT1
LD SP,(OLDSP)
RET
;
;bad number specification in output file size
;
BADNUM:
LD DE,BADSIZE
JR QUIT
;
;*** End Of Program ***
;
;Not Done Yet
;
NOTYET
LD DE,SDISK ;Swap disk message
LD A,(SWAPFLG)
OR A
CALL NZ,PROMPT
;
;Restore Old Character
;
LD HL,(LASTLF)
LD A,(LASTC)
LD (HL),A
;
;Move From This Byte To End Of Read Buffer
;To Beginning Of Read Buffer
;And Calculate New Offset
;
EX DE,HL ;DE=last character
LD HL,BUFFER+1024*32 ;Normal buffer end
PATCH4 EQU $-2
LD BC,(OBUFF) ;Get read offset
ADD HL,BC ;Current end of data
XOR A
SBC HL,DE ;New offset and bytes to relocate
LD (OBUFF),HL
PUSH HL
POP BC ;Bytes to move
EX DE,HL ;Start at last character
LD DE,BUFFER ;Move to here
LDIR
JP READAGAIN
;
;Get Extra Record Count For Last Write
;
LASTWRITE
LD A,(SAFEREC) ;Extra records to write
LD B,A
LD HL,(ORCNUM) ;Output record number=0
SAFE
DEC HL ;Set to -1, -2, Etc
DJNZ SAFE
LD (ORCNUM),HL
JP WRITE1 ;Write out last segment
;
;
;*** Subroutines ***
;
;Print Message In DE
;Get Keypress And Abort On ^c
;
PROMPT LD C,PRINT
CALL BDOS
LD C,GETKEY
CALL BDOS ;Wait for keypress
CP 3 ;^c
JR Z,QUIT1 ;if aborted
RET
;
;Advance DMA By 1 Record
;
INCBUF LD HL,(TDMA) ;Where it was
LD DE,80H ;Add 1 record
ADD HL,DE
INCB1 LD (TDMA),HL
EX DE,HL
LD C,SETDMA
CALL BDOS
RET
;
;Display HL In DECIMAL
;
DUMPIT:
LD A,13 ;<CR>
CALL PRCHR
;
PUSH HL
PUSH DE
PUSH BC
LD BC,2 ;leading zeroes and BDOS print
LD DE,10000
CALL SUBDIV
LD DE,1000
CALL SUBDIV
LD DE,100
CALL SUBDIV
LD E,10
CALL SUBDIV
LD A,L
JR SUBDV4
SUBDIV
XOR A
SUBDV1
SBC HL,DE
INC A
JR NC,SUBDV1
ADD HL,DE
DEC A
JR Z,SUBDV2
LD B,A
JR SUBDV3
SUBDV2
CP B
JR NZ,SUBDV3
LD A,32-'0'
SUBDV3
PUSH HL
PUSH DE
PUSH BC
SUBDV4
ADD A,'0'
LD E,A
CALL 5
POP BC
POP DE
POP HL
RET
;
;Falls Through To Print Routine
;
PRCHR
PUSH BC
PUSH DE
PUSH HL
LD E,A ;Character To Print
LD C,PRINTC ;Function
CALL BDOS
POP HL
POP DE
POP BC
RET
;
;Messages
;Note Wild Message Links To Syntax
;
WILD DB 7,'No Wild Cards Allowed',13,10
SYNTAX DB 'SYNTAX: SPLIT [d:]ufn [d:]nn [/N]'
DB 13,10,'Where /N means no disk swap'
DB 13,10,'and nn is the split size (default 32K)$'
NUMERR DB 7,'No numbers allowed in last character$'
START DB 12,9,'FILE SPLITTER V1.3',13,10
DB 9,'BY Guy Cousineau',13,10,10
DB 7,'Insert source (^C ABORTS)',13,10,10,'$'
NOFL DB 13,10,'Can''t find source$'
DDISK DB 7,' Records read--insert dest',10,'$'
SDISK DB 7,' written',13,10,9,' Insert source',10,'$'
BADIR DB 13,10,'No directory space$'
BADFL DB 13,10,'Bad write$'
DONE DB 13,10,7,9,'--ALL DONE--',13,10,'$'
BDCLOSE DB 13,10,'Can''t close file$'
BADSIZE DB 13,10,'Bad split size specification'
DB 13,10,'Must be between 10 and 48$'
;
;Data Storage Area
;
SAMEDSK DB 0 ;Source and destination same
SWAPFLG DB 1 ;Print Swap message
SAFEREC DB 0 ;Number of extra records to write at end
IRCNUM DW 0 ;Input record number count
ORCNUM DW 0 ;Output record number count
OBUFF DW 0 ;Offset between read and write buffers
TDMA DS 2 ;Save DMA address here
OLDSP DS 2
LASTLF DS 2 ;Save address of last found <LF>
LASTC DS 1 ;Save last charcater at EOF
WFCB DS 33
DS 20H ;Generous stack space
STACK
BUFFER EQU $ ;Copy buffer starts here
END
;