;+
;
; Break up a big file into little files.
;
; 09/08/98	JMBW	Created.
;
;-
	.radix	8
	locals
;
lf=	12
cr=	15
;
bufl=	177000			;buffer length (64 KB minus one block)
;
error	macro	string
	local	a,b
	call	err1		;;print error msg, punt
a	db	b,&string
b=	$-a-1
	endm
;
code	segment	'code'
	assume	cs:code
;
start:	cld			;DF=0
	mov	ax,seg data	;point at data segment
	mov	ds,ax
	; open input file
	mov	dx,offset inprm	;input prompt
	call	getstr		;get filename
	mov	ax,3D00h	;func=open /RONLY
	int	21h
	jnc	@@1		;success
	error	'?Open error'
@@1:	mov	ds:inhnd,ax	;save
	; get size for each output file
	mov	dx,offset kbprm	;prompt for # KB
	call	getstr		;get it
	mov	si,dx		;point at it
	xor	bx,bx		;init
@@2:	lodsb			;get next char
	test	al,al		;end of string?
	jz	@@3		;yes
	sub	al,'0'		;convert digit to binary
	cmp	al,9d		;it was a digit right?
	ja	@@2		;no, ignore
	cbw			;AH=0
	xchg	ax,bx		;save, get old number
	mov	dx,10d		;multiplier
	mul	dx		;make space for new digit
	add	bx,ax		;add it in
	jmp	short @@2	;handle next
@@3:	test	bx,bx		;get anything?
	jnz	@@4		;yes
	error	'?Invalid file size'
@@4:	mov	ax,1024d	;bytes per KB
	mul	bx		;find bytes per file
	mov	ds:outsiz,ax	;save
	mov	ds:outsiz+2,dx
@@5:	; read next bufferload from input file
	xor	dx,dx		;offset=0
	mov	cx,bufl		;max # bytes
	mov	ax,ds:outsiz	;# bytes per output file
	mov	bx,ds:outsiz+2
	sub	ax,ds:cursiz	;find # to go in current file
	sbb	bx,ds:cursiz+2
	jnz	@@6		;> 64 KB, just fill the buf
	cmp	ax,cx		;more than a bufferful?
	ja	@@6		;yes, just fill the buf
	mov	cx,ax		;stop short
	test	cx,cx		;anything?
	jnz	@@6		;yes
	; output file full, close it
	mov	ds:cursiz,cx	;start next file at 0
	mov	ds:cursiz+2,cx
	mov	bx,-1		;load -1
	xchg	bx,ds:outhnd	;get handle, set to -1
	mov	ah,3Eh		;func=close
	int	21h
	jmp	short @@5	;now write to fresh file
@@6:	mov	bx,ds:inhnd	;input file handle
	push	ds		;save
	mov	ax,seg buf	;point at buf
	mov	ds,ax
	mov	ah,3Fh		;func=read
	int	21h
	pop	ds		;[restore]
	jnc	@@7
	error	'?File read error'
@@7:	test	ax,ax		;EOF?
	jz	@@12		;yes
	push	ax		;save
	cmp	word ptr ds:outhnd,-1 ;is there an output file?
	jne	@@9		;yes
	mov	dx,offset outprm ;prompt for next output file
	call	getstr
	xor	cx,cx		;mode=default
	mov	ah,3Ch		;func=create
	int	21h
	jnc	@@8
	error	'?File creation error'
@@8:	mov	ds:outhnd,ax	;save
@@9:	pop	cx		;restore length
	; write next bufferload to current output file
	xor	dx,dx		;offset=0
	mov	bx,ds:outhnd	;get handle
	push	ds		;save
	mov	ax,seg buf	;point at buf
	mov	ds,ax
	mov	ah,40h		;func=write
	int	21h
	pop	ds		;[restore]
	jc	@@10		;error
	cmp	ax,cx		;wrote all?
	je	@@11		;yes, success
@@10:	error	'?File write error'
@@11:	add	ds:cursiz,ax	;update # bytes written
	adc	word ptr ds:cursiz+2,0
	jmp	@@5		;go read new buffer
@@12:	; EOF on input file
	mov	ah,3Eh		;func=close
	int	21h		;(INHND is still in BX)
	mov	bx,ds:outhnd	;get output handle
	cmp	bx,-1		;open?
	je	@@13		;no
	mov	ah,3Eh		;func=close
	int	21h
@@13:	mov	ax,4C00h	;func=exit, errorlevel=0
	int	21h
;+
;
; Print an error message and exit.
;
; ss:sp	return address points to counted string in code segment
;
;-
err1:	pop	si		;restore
	push	cs		;copy CS to DS
	pop	ds
	lodsb			;get length
	cbw			;AH=0
	mov	dx,si		;point at it
	mov	cx,ax		;length
	mov	bx,0001h	;handle=STDOUT
	mov	ah,40h		;func=write
	int	21h
	mov	dl,cr		;CR
	mov	ah,02h		;func=CONOUT
	int	21h
	mov	dl,lf		;LF
	mov	ah,02h		;func=CONOUT
	int	21h
	mov	ax,4C01h	;func=punt, errorlevel=1
	int	21h
;+
;
; Get a string
;
; On entry:
; ds:dx	prompt (ending in '$')
;
; On exit:
; ds:dx	.ASCIZ string
;
;-
getstr:	mov	ah,09h		;func=print
	int	21h
	mov	dx,offset kbbuf	;keyboard
	mov	si,dx		;(copy)
	mov	ah,0Ah		;func=string input
	int	21h
	mov	dl,lf		;echo LF
	mov	ah,02h		;func=CONOUT
	int	21h
	inc	si		;skip buf length
	lodsb			;get actual length
	cbw			;AH=0
	mov	dx,si		;point at actual string
	add	si,ax		;skip to end
	mov	[si],ah		;mark end
	ret
;
code	ends
;
data	segment	'data'
inprm	db	'BREAKUP  V1.0  by John Wilson <wilson@dbit.com>',cr,lf
	db	cr,lf
	db	'Input file: $'
kbprm	db	'Number of KB per output file: $'
outprm	db	'Output file: $'
;
outhnd	dw	-1		;output file handle (or -1 if none)
inhnd	dw	1 dup(?)	;input file handle
outsiz	dw	2 dup(?)	;# bytes per output file
cursiz	dw	0,0		;# bytes so far in current output file
;
kbbuf	db	80d,?,(80d+1) dup(?) ;keyboard input buffer
;
data	ends
;
stk	segment	stack 'stack'
	dw	800h dup(?)
stk	ends
;
buf	segment	'buffer'
	db	bufl dup(?)	;I/O buffer
buf	ends
;
	end	start
