;
;	DATA TRANSFER LOGIC - BLOCK AND ASCII
;
;	02.00 KRS 07/30/81	INITIAL VERSION OF NAXFER
;	02.01 10/18/81 RLR - SEPARATE MODULE & SOME CLEAN-UP
;	02.02 11/15/81 RLR - ALL DATA OPERATIONS HERE
;
CR	EQU	13
LF	EQU	10
DLR	EQU	'$'
TAB	EQU	'I'-'@'
SPC	EQU	20H
EOF	EQU	'Z'-'@'		;CTL-Z
;
	NAM	XFERC
	ENT	NAXFER	;02.00 BLOCK MODE
	ENT	DOXFR	;02.02 ASCII MODE
	ENT	RECOUT,XOFREC
	LST	NASC
;
	EXT	DOXOT9,DOXOT7,DOXOT5,DOXOT2		;02.02
;
	EXT	IFCB,IFCB2,OFCB,OFCB2
	EXT	PASS,CNTLO,CNTHI,TABCT,CNTLN		;02.02
	EXT	SWPHX,SWASC,SWIGNR,SWSTRP,SWTAB,SWFIL	;02.02
;
	EXT	GCHAR,PCHAR				;02.02
	EXT	MOVE,CMPHL,PNAME,MUL32,BINH2,BINH4,NEGHL
	EXT	BADLEN,BADFLG,VRYFM,FIOER
	EXT	MEMORY,DOS
;
SWRIT:	EQU	21
RREAD	EQU	33
CRRSZ	EQU	35
RWRIT	EQU	34
;
;	**** DO ASCII MODE DATA TRANSFER ****
;
DOXFR:	LXI	D,IFCB
	CALL	GCHAR
	PUSH	PSW
	LDA	SWASC
	ORA	A
	JZ	NOASC
;
; HANDLE ASCII DATA
;
	LDA	SWIGNR	; IF IGNORE EOF
	ORA	A
	JZ	ASCEOF
	POP	AF
	RZ		; THEN TEST TRUE EOF
	ANI	7FH	; AND IF ASC EOF
	CPI	EOF	; THEN NEXT CHAR
	JEQ	DOXFR
	JMP	DOASC	; ELSE PROCESS NORMALLY
;
ASCEOF:	POP	PSW
	ANI	7FH
	CPI	EOF	; EOF
	RZ		; NEXT INPUT FILE
DOASC:	MOV	B,A
;
; ASCII SPECIAL FUNCTIONS
;
	LDA	SWSTRP
	ORA	A
	JZ	NOSTRP	; IF STRIP
;
	MOV	A,B
	CPI	7FH	; THEN IF RUBOUT
	JEQ	DOXFR
	ORA	A	; OR NUL
	JEQ	DOXFR
	CPI	LF	; OR LF
	JEQ	DOXFR	; THEN IGNORE
NOSTRP:	MOV	A,B	; IF >=SPC
	CPI	SPC
	JLT	XFCTL
	CALL	DOXOTA	; THEN NORMAL CHAR
	JMP	DOXFR
;
XFCTL:	CPI	TAB
	JNE	XFSPEC
;			IF TAB 
	LDA	SWTAB	; THEN IF NOT TAB EXPAND
	ORA	A
	JNZ	NXTAB	; THEN OUT(TAB)
	MOV	A,B
	CALL	DOXOTA
	JMP	DOXFR
;			; ELSE EXPAND TAB
NXTAB:	MVI	A,SPC
	CALL	DOXOTA
	LXI	H,TABCT
	MOV	A,M
	ANI	7	; THEN DO EXPAND
	JNZ	NXTAB	; UNTIL COLM MOD 8=0
	JMP	DOXFR
;
; SPECIAL CTRL CHARS:
;	1) IF CR & STRIP THEN OUT(CR,LF)
;	2) IF CR THEN TABCT:=0
;	3) IF STRIP THEN THROW AWAY ALL LF'S
;	4) IF FILTER THEN ONLY PASS CR,^L,^K
;
XFSPEC:	CPI	CR
	JNE	XSPEC3
	CALL	DOXOT	; OUT(CR)
	LXI	H,TABCT
	MVI	M,0	; TABCT:=0
	LHLD	CNTLN	; COUNT LINES
	INX	H
	SHLD	CNTLN
	LDA	SWSTRP	; IF STRIP
	ORA	A
	JZ	XSPEC1	; THEN ADD LF
	MVI	A,LF
	CALL	DOXOT
XSPEC1:	JMP	XSPECE
;
XSPEC3:	LDA	SWFIL	; ELSE IF OTHER 
	ORA	A
	JNZ	XSPEC4	; AND NOT FILTER
	MOV	A,B
	CALL	DOXOT	; THEN XMIT
	JMP	XSPECE
;
XSPEC4:	MOV	A,B
	CPI	'L'-'@'	; ELSE IF ^L(FF)
	JEQ	XSPEC5	; OR ^K(ALTRN FF)
	CPI	'K'-'@'
	JNE	XSPEC6
XSPEC5:	CALL	DOXOT	; THEN XMIT
	JMP	XSPECE
;			ELSE OUT ('^',CHR+'@')
XSPEC6:	MVI	A,'^'
	CALL	DOXOTA
	MOV	A,B
	ORI	'@'
	CALL	DOXOTA
;
XSPECE:	JMP	DOXFR
;
; *** HANDLE BINARY DATA
;
NOASC:	POP	PSW
	RZ		; EOF-NEXT FILE
	CALL	DOXOT
	JMP	DOXFR
	EJECT
;
; **** XMIT DATA TO OUTPUT FILE
;
DOXOTA:	LXI	H,TABCT	; ASCII (CNT TABS)
	INR	M
;
DOXOT:		; IF PASS=0 THEN OUT(OFCB,CHAR)
;		    ELSE COMPARE A=IN(OFCB)
	MOV	C,A
	LDA	PASS
	ORA	A
	JZ	DOXOT1
;
	LXI	D,OFCB
	CALL	GCHAR
	JZ	BADLEN	; BAD EOF
	CMP	C
	JEQ	DOXOT2	; COMPARES OK
	MOV	B,A
	CALL	DOXOT9					;02.00
	JMP	DOXOT2
;
DOXOT1:ûýøþÑÐƒB‚PÐSTÒTƒB‚R–‚Q’SÑT‚Nåååå DIE ON WRITE ERROR
	JMP	DOXOT2	; COUNT BYTES
	EJECT
;
; NON-ASCII TRANSFER (BLOCK MODE) MODULE
;
NAXFER:	LXI	H,MEMORY	;02.01
	SHLD	INBUF1		; INPUT BUFFERS - 8192 BYTES
	LXI	D,8192
	DAD	D
	SHLD	OUBUF1		; OUTPUT BUFFERS - 8192 BYTES
	LXI	H,XINFCB	; INPUT FCB/RANDOM
	LXI	D,IFCB2		; ZDOS VERSION
	MVI	C,33
	CALL	MOVE
	LXI	H,XOUFCB	; OUTPUT FCB/RANDOM
	LXI	D,OFCB2		; ZDOS VERSION
	MVI	C,33
	CALL	MOVE
;
;	TRANSFER FILE IN 16K CHUNCKS BY RECORDS
;	VERIFY IN 8K CHUNKC BY RECORDS
;	ON READ SET FLAGS IN 'VECTOR', ONE PER RECORD--
;	       -1 = PAST END OF FILE (NOT READ)
;		0 = GOOD DATA
;		1 = NOT ALLOCATED (NOT READ)
;		4 = MISSING EXTENT
;
;	ON VERIFY OPERATIONS, ORIGINAL INPUT IS READ FIRST TO
;	KEY CONDITION, AS ALLOCATION ON OUTPUT MAY DIFFER!!!
;
;	USES 'RANDOM' I/O CALLS A'LA CP/M VERSION 2.X
;
	LXI	D,XINFCB
	MVI	C,CRRSZ		; COMPUTE FILE SIZE
	CALL	DOS
	LHLD	XIFREC
	SHLD	XINHI
	MOV	A,H
	ORA	L
	RZ			; IF A 0, NULL FILE, DONE
	LDA	PASS
	ORA	A
	JZ	NOOSZ		; ON PASS <> 0, GET OUTPUT SIZE TOO
	XCHG			; SAVE IN SIZE IN DE
	DCX	D		; -1 FOR COMPARIZON!!!
	LHLD	XOFREC		; CURRENT OUTPUT POINTER
	PUSH	H		; SAVED
	PUSH	D
	LXI	D,XOUFCB
	MVI	C,CRRSZ
	CALL	DOS
	LHLD	XOFREC
	SHLD	XOUHI
	POP	D
	CALL	CMPHL		; SIZE COMPARIZON
	LXI	D,OFCB		; JUST IN CASE OF ERROR!!!!!
	JGE	BADLEN		; LENGTH COMPARE ERROR!!! IN-1 >= OU
	POP	H
	SHLD	XOFREC		; RESTORE POINTER
NOOSZ:	XRA	A
	STA	EOFRRI
	LXI	H,XIFREC
	MOV	M,A
	INX	H
	MOV	M,A
	INX	H
	MOV	M,A
	EJECT
;
;  MORE BLOCKS TO MOVE
;
RRMORE:	LHLD	INBUF1
	PUSH	H
	LXI	B,ADESC
	PUSH	B
	MVI	L,130
	XRA	A
     .DO		; ZERO BUFFER DESCRIPTOR
	STAX	B
	INX	B
	DCR	L
	JNZ	.DO
     .UNTIL
	POP	B
	POP	H
;
; GET INPUT LOAD
;
	LDA	PASS
	ORA	A
	MVI	A,128		;MOVE = 128 RECORDS
	JZ	LOOPI
	MVI	A,64		;VERIFY=64  RECORDS
;				A==RECORDS
LOOPI:	PUSH	H		; BUFFER
	PUSH	PSW
	PUSH	B
	XCHG			; BUFFER TO DE
	MVI	C,26		; SET BUFFER
	CALL	DOS
	XCHG			; FCB BACK TO DE
RRNXTX:	MVI	C,RREAD		; READ BLOCK
	LXI	D,XINFCB
	CALL	DOS
;
	ORA	A
	JZ	RDROK		; 0 = OK
	CPI	1
	JEQ	NODATA
	CPI	4
	JNE	RIOERR
	LHLD	XIFREC
	LXI	B,128
	DAD	B
	SHLD	XIFREC
	LHLD	XOFREC
	DAD	B
	SHLD	XOFREC
	JMP	RRNXTX
;
NODATA:	MVI	A,1
RDROK:	POP	H
	PUSH	H
	MOV	M,A		; I/O STATUS
	LHLD	XIFREC
	INX	H
	SHLD	XIFREC
	XCHG
	LHLD	XINHI
	CALL	CMPHL
	JEQ	RRALL
	POP	B
	INX	B
	POP	PSW
	POP	H
	LXI	D,128
	DAD	D
	DCR	A
	JNZ	LOOPI
RRXXX:	STA	EOFRRI
;
;  DO OUTPUT OR COMPARE LOOP
;
	LDA	PASS
	ORA	A
	JNZ	RRCOMP
	EJECT
;
; OUTPUT LOOP
;
	MVI	A,128	;RECORDS
	LXI	B,ADESC	;BUFFER DESC
	LHLD	INBUF1
LOOPO:	PUSH	H
	PUSH	PSW
	PUSH	B
	XCHG
	MVI	C,26		; SET BUFFER
	CALL	DOS
	XCHG			; FCB TO DE
	POP	H		; VECTOR
	PUSH	H		; STILL THERE
	MOV	A,M		; GOT IT
	CPI	1
	JEQ	ISSKIP
	JGE	ISEOF
	MVI	C,RWRIT
	LXI	D,XOUFCB
	CALL	DOS
;
	ORA	A
	JNZ	RIOERR		; 0 = OK
;
	LHLD	RECOUT
	INX	H
	SHLD	RECOUT
;
ISSKIP:	LHLD	XOFREC		; SKIP A HOLE
	INX	H
	SHLD	XOFREC
	POP	B
	INX	B
	POP	PSW
	POP	H
	LXI	D,128
	DAD	D
	DCR	A
	JNZ	LOOPO
	LDA	EOFRRI
	ORA	A
	JZ	RRMORE
	LXI	D,XOUFCB
	LDA	XOUFCB+15
	CPI	80H
	JNE	RRRET2
	MVI	C,SWRIT
	CALL	DOS
;
RRRET:	LDA	EOFRRI
	ORA	A
	JZ	RRMORE
	LXI	D,XOUFCB	; OUTPUT FCB/RANDOM
RRRET2:	LXI	H,OFCB2		; ZDOS VERSION
	MVI	C,33
	CALL	MOVE
	RET
	EJECT
;
;  COMPARE THE BUFFERS
;
RRCOMP:	LHLD	XOFREC
	SHLD	SOFREC
	LHLD	OUBUF1
	LXI	B,BDESC	; USED 2ND PART OF BUFFER FOR COMPARE LOAD
	MVI	A,64		; RECORDS
LOOPC:	PUSH	H		; BUFFER
	PUSH	PSW
	PUSH	B
	XCHG			; BUFFER TO DE
	MVI	C,26		; SET BUFFER
	CALL	DOS
	XCHG			; FCB BACK TO DE
	MVI	C,RREAD		; READ BLOCK
	LXI	D,XOUFCB
	CALL	DOS
;
	ORA	A
	JZ	RCROK		; 0 = OK
	CPI	1
	JEQ	NCDATA		; 1 = UNWRITTEN DATA
	CPI	4
	JNE	RIOERR		; 4 = UNWRITTEN EXTENT
;
;	MISSING EXTENT
;
	LHLD	XOFREC
	LXI	B,MISEXT
	CALL	MISEIT
	LHLD	XIFREC
	LXI	B,64		; 1/2 EXTENT TO ADD
	DAD	B
	SHLD	XIFREC
	XCHG
	LHLD	XINHI
	CALL	CMPHL
	JGE	DOXOT7		; DONE
	LHLD	XOFREC
	LXI	B,128		; FULL EXTENT HERE
	DAD	B
	SHLD	XOFREC
	XCHG
	LHLD	XOUHI
	CALL	CMPHL
	JGE	RCALL
	POP	B
	POP	PSW
RRRXT:	POP	H
	JMP	RRRET
	EJECT
;
; REPORT MISSING EXTENT OR BLOCK
;
MISEIT:	PUSH	H
	PUSH	B
	LXI	H,BADFLG
	MVI	A,1
	CMP	M
	MOV	M,A
	JZ	MISNVM
	LXI	H,VRYFM
	DCX	D
	DCX	D
	CALL	PNAME
MISNVM:	POP	D
	MVI	C,9
	CALL	DOS
	POP	D
	LXI	B,128
	CALL	MUL32
	PUSH	H		; SAVE LOWER
	MOV	A,E
	LXI	H,RRPOSI
	CALL	BINH2
	POP	B
	CALL	BINH4
	LXI	D,RRPOSI
	MVI	C,9
	CALL	DOS
	LDA	SWPHX
	ORA	A
	JZ	DOXOT7		; AT RETURN FROM PNAME CALL!!!!!!
	RET
	EJECT
;
;  READ/COMPARE IS OK
;
RCROK:	LHLD	RECOUT
	INX	H
	SHLD	RECOUT
	JMP	RCROK1
;
; ENTER HERE IF MISSING BLOCK
;
NCDATA:	MVI	A,1
RCROK1:	POP	H
	PUSH	H
	MOV	M,A		; I/O STATUS
	LHLD	XOFREC
	INX	H
	SHLD	XOFREC
	XCHG
	LHLD	XINHI
	CALL	CMPHL
	JEQ	RCALL
	POP	B
	INX	B
	LDAX	B
	CPI	-1		; DID INPUT HIT EOF?
	JNE	NOIEF
	POP	PSW
	POP	H
	JMP	RCXXX		; YES!!!
;
NOIEF:	POP	PSW
	POP	H
	LXI	D,128
	DAD	D
	DCR	A
	JNZ	LOOPC		; ?????
	EJECT
;
;   ALL DATA LOADED/ NOW DO COMPARE OF BUFFERS
;
RCXXX:	MVI	A,64
	STA	RCT01
	LHLD	INBUF1
	PUSH	H
	LHLD	OUBUF1
	PUSH	H
	POP	B
	LXI	H,BDESC-1
	LXI	D,ADESC-1
;
RCL001:	INX	H
	INX	D
	LDAX	D
	CPI	1
	JEQ	SK001
	JGE	RRRXT
	CMP	M
	JEQ	NRBERR
	PUSH	H
	PUSH	D
	PUSH	B
	LDA	RCT01
	CMA
	ADI	65
	MOV	E,A
	MVI	D,0
	LHLD	SOFREC
	DAD	D
	LXI	B,MISBLK
	LXI	D,XOUFCB
	CALL	MISEIT
	POP	B
	POP	D
	POP	H
	JMP	SK001
;
NRBERR:	XTHL			; IN BUF
	PUSH	D
	MVI	E,128		; BLOCK
;
RCL002:	LDAX	B
	CMP	M
	CNE	RRXERR		; CALL IF ERROR
	INX	B
	INX	H
	DCR	E
	JNZ	RCL002
;
	POP	D
	XTHL
RCL003:	LDA	RCT01
	DCR	A
	STA	RCT01
	JNZ	RCL001
	POP	H
	JMP	RRRET
;
RRXERR:	PUSH	H
	PUSH	D
	PUSH	B
	MOV	B,A
	MOV	C,M
	LXI	D,XOUFCB-2
	LDA	SWPHX		; MESSAGES?
	ORA	A
	JZ	DOXOT5		;NO
	PUSH	D
	PUSH	B
	XCHG
	LHLD	INBUF1
	CALL	NEGHL
	DAD	D		; POSITION
	PUSH	H
	LHLD	SOFREC
	XCHG
	LXI	B,128
	CALL	MUL32
	POP	B
	DAD	B
	JNC	NOCARY
	INX	D
NOCARY:	SHLD	CNTLO
	XCHG
	SHLD	CNTHI
	POP	B
	POP	D
	CALL	DOXOT9
	POP	B
	POP	D
	POP	H
	RET
;
;	LOOP FOR INPUT FILE EOF!!!
;
SK001:	SHLD	RCS01
	POP	H
	PUSH	D
	LXI	D,128
	DAD	D
	POP	D
	PUSH	H
	LXI	H,128
	DAD	B
	PUSH	H
	POP	B
	LHLD	RCS01
	JMP	RCL003
	EJECT
;
;  ALL RANDOM DONE
;
RRALL:	POP	H
	POP	PSW
	INX	H
	MVI	M,-1		; END OF FILE
	LDA	PASS		; IS IT COMPARE
	ORA	A
	JZ	RRNOTC		; NO, ELSE
	LXI	B,65
	DAD	B
	MVI	M,-1		; TELL OTHER HALF
RRNOTC:	POP	H
	XRA	A
	DCR	A		; RETURN -1  IN AF!!!
	JMP	RRXXX
;
;	RANDOM I/O ERRRORS
;  1 - UNWRITTEN DATA 		NOT AN ERROR
;  2 - DISK FULL
;  3 - CAN NOT CLOSE EXTENT
;  4 - UNWRITTEN EXTENT		NOT AN ERROR
;  5 - DIR FULL
;  6 - DISK FULL
;
RIOERR:	LXI	H,RRFUL	;02.01
	CPI	2	;02.01 2/6 - DISK FULL
	JEQ	..1	;02.01
	CPI	6	;02.01
	JEQ	..1	;02.01
	LXI	H,RDFUL	;02.01  5 - DIRECTORY FULL
	CPI	5	;02.01
	JEQ	..1	;02.01
	LXI	H,RRERR	;02.01 3  - I/O ERROR
..1:	DCX	D	;02.01	; FOR PFNAM
	DCX	D
	JMP	FIOER	;02.01 FATAL ERROR
;
; FINALLY REAL EOF
;
ISEOF:	POP	B
	POP	H		; DUMMY'
	POP	H
	JMP	RRRET
	EJECT
;
RCALL:	POP	H
	POP	PSW
	INX	H
	MVI	M,-1		; END OF FILE
	POP	H
	XRA	A
	DCR	A		; RETURN -1  IN AF!!!
	JMP	RCXXX
	EJECT
;
;	MISC:
;
MISEXT:	DB	'...Missing EXTENT at character ',DLR		;02.00
MISBLK:	DB	'...Missing RECORD at character ',DLR		;02.00
RRPOSI:	DB	'XXXXXX',CR,LF,DLR
RRERR:	DB	' random I/O error',CR				;02.00
RRFUL:	DB	' disk full',CR					;02.00
RDFUL:	DB	' directory full',CR	;02.01
;
	RAM
;
;   DATA AREA
;
INBUF1:	DW	0		; 8K BUFFER ADDRESS	 02.00
OUBUF1:	DW	0		; 8K BUFFER ADDRESS	 02.00
;
ADESC:	DS	65	;DESCRIPTOR FOR 1ST 8K OF BUFFERS	02.01
BDESC:	DS	65	;DESCRIPTOR FOR 2ND 8K OF BUFFERS	02.01
;
XINFCB:	DS	33	;RANDOM INPUT FCB		;02.00
XIFREC:	DW	0					;02.00
	DB	0					;02.00
;
XINHI:	DW	0					;02.00
XOUHI:	DW	0					;02.00
;
XOUFCB:	DS	33	;RANDOM OUTPUT FCB		;02.00
XOFREC:	DW	0					;02.00
	DB	0					;02.00
;
SOFREC:	DW	0					;02.00
RECOUT:	DW	0					;02.00
EOFRRI:	DB	0					;02.00
RCT01:	DW	0					;02.00
RCS01:	DW	0					;02.00
;
