;TAPE100 - Tape/Disk & Disk/Tape Xfer Utility
	TITLE	<TAPE100 - LS-DOS 6.2>
;
BREAKLC	EQU	0F440H		;<BREAK> key location
LOADA	EQU	3AH		; LD  A,(nnnn) opcode
WRMASK	EQU	'W'-'A'		;WRINTMASK port mask byte
MODMASK	EQU	'M'-'A'		;MODOUT port mask byte
;
@INIT	EQU	58		;@INIT SVC #
@OPEN	EQU	59		;@OPEN SVC #
;
PORTE0	EQU	0E0H
MODOUT	EQU	0ECH
PORTFF	EQU	0FFH
OPREG$	EQU	78H		;Operating Register
@OPREG	EQU	84H		;Video/Keyboard Control Port
VIDEO	EQU	0F800H		;Start of Video RAM
;
WHICH1	EQU	22H		;Which one - 0 or 1 ?
TOOSHRT	EQU	0FH		;Pulse too Short ?
TOOLONG	EQU	3EH		;Pulse too Long ?
ROUTOFF	EQU	6		;Interrupt rout offset
DIFFER	EQU	0DH		;Difference between 2 pulses
DELAY0	EQU	2B2FH		;Bit = 0 Delay count
DELAY1	EQU	1217H		;Bit = 1 Delay count
;
CURON	EQU	14		;Cursor on
CUROFF	EQU	15		;Cursor off
;
*GET	SVCMAC:3		;SVC Macro equivalents
*GET	VALUES:3		;Misc. equates
*GET	COPYCOM:3		;Copyright message
;
	ORG	2600H
;
START
	@@CKBRKC		;Check for break
	JR	Z,STARTA	;Continue if not
	LD	HL,-1		;  else abort
	RET
;
STARTA	LD	(OLDSP+1),SP	;Save entry stack
	CALL	DOINIT		;Do initialization
;
;	Was READ or WRITE entered ?
;
	LD	A,(RRESP)	;P/u read response
	LD	B,A		;Xfer to B
	LD	A,(WRESP)	;P/u write response
	XOR	B		;Are both the same ?
	JR	Z,INP_R_W	;Yes - prompt
;
;	Both weren't entered - which one was
;
CHKPRM	INC	B		;READ entered ?
	DEC	B
	JR	Z,WRTAPE	;<W>rite a tapefile
	JP	RDTAPE		;<R>ead a tapefile
;
;	Prompt for READ or WRITE
;
INP_R_W	PUSH	HL		;Save command ptr
;
	LD	HL,RDORWR	;"Read or Write"
	CALL	DSPLY
;
;	Input R (Read) or W (Write)
;
	LD	B,1		;Take input, 1 char
	CALL	INPUT
	LD	A,(HL)		;P/u first char
	POP	HL		;Recover command ptr
	RES	5,A		;Convert to U/C
	CP	'R'		;<R>ead ?
	JP	Z,RDTAPE
	CP	'W'		;<W>rite ?
	JR	NZ,INP_R_W	;No - re-prompt
;
;	WRITE diskfile to tapefile
;
WRTAPE	LD	DE,FCB1		;DE => Source FCB
	@@FSPEC			;If a bad spec,
	CALL	NZ,PRSOUR	;  prompt for source
;
;	WRITE - check if destination filespec input
;
WRTAPE2	LD	DE,FCB2		;DE => Destination FCB
	@@FSPEC
	CALL	NZ,PRDEST	;Prompt for destination
	CALL	GTFILE		;Xfer into Filename
;
;	Open Disk Source file
;
OPDSRC	LD	DE,FCB1		;DE => Source
	CALL	OPEN
	JP	NZ,IOERR	;NZ - abort
;
;	Can this disk file fit into memory ?
;
	LD	HL,(FCB1+12)	;P/u ERN
	INC	H		;Too big ?
	DEC	H
	JP	NZ,TOOBIG	;Yes - forget it
ENUF	LD	A,$-$		;Enough memory ?
	ADD	A,MEM<-8	;Add mem start
	CP	L
	JP	C,TOOBIG	;No - forget it
;
;	Read in Disk file & Write to tape
;
	CALL	PRTAPE		;Display "Ready Tape"
	CALL	CURSOFF		;Turn of cursor
	LD	HL,READING	;Init "Reading : "
	CALL	DSPLY		;Display line
	LD	HL,DFBUF	;HL => Disk Filename
	CALL	DSPLY
	CALL	READSRC		;Read the source file
	CALL	GETPOS		;Get new cursor pos
	CALL	ENDOKI		;Bring in Video
	LD	HL,WRITING	;Display "Writing : "
	CALL	DISPSTR
	LD	HL,FILENM	;"filenm"
	CALL	DISPSTR
	CALL	CASSON		;Turn on cassette
	LD	B,80H		;Pause a bit
	@@PAUSE
	CALL	WRHEAD		;Write Header
	CALL	WRDAT		;Write Data
	LD	HL,(CURPOS)	;P/u new cursor pos
	CALL	GETCRS
	LD	B,3		;Give to system
	@@VDCTL
	CALL	DISDOKI		;Restore video
	CALL	CASSOFF		;Turn off cassette
	JP	EXIT		;Clean exit
;
;	Get Source & Destination for READ
;
RDTAPE	LD	DE,FCB1		;First filespec legal ?
	@@FSPEC
	JR	Z,CHKSEC	;Yes - check for second
;
;	Accept first filename on tape
;
	LD	A,0C9H
	LD	(CORRECT),A
	LD	DE,FCB2		;Prompt for dest filename
	CALL	PRDEST2		;Prompt for dest
	JR	READFIL		;  and read file
;
;	Copy source FCB into destination
;
CHKSEC	PUSH	HL		;Save comm ptr
	EX	DE,HL
	LD	DE,FCB2		;DE => Disk FCB
	LD	BC,32
	PUSH	DE		;Save dest FCB
	LDIR
	POP	DE
	POP	HL
;
;	P/u destination filespec
;
	DEC	HL		;Skip leading spaces
SKPSPC	INC	HL
	LD	A,(HL)		;P/u char
	CP	' '		;Space ?
	JR	Z,SKPSPC
	CP	CR+1		;Eol ?
	JR	C,GTFILE2	;Yes - use default
	CP	'('		;Eol ?
	JR	Z,GTFILE2
	@@FSPEC			;Xfer in if legal
;
;	Transfer filename into buffer left just'd
;
GTFILE2	LD	DE,FCB1		;DE => Source
	CALL	GTFILE		;Stuff Filename into buff
;
;	Read in Tape Source file
;
READFIL	LD	DE,FCB2		;@INIT the dest file
	CALL	INIT
	JP	NZ,IOERR
	LD	C,(IX+6)	;P/u drive #
	@@CKDRV			;Write protected ?
	LD	A,15		;Write Protected Disk
	JP	C,IOERR		;Good bye
	CALL	PRTAPE		;"Ready Cassette"
	CALL	CURSOFF
	CALL	ENDOKI		;Bring in KI & DO RAM
	CALL	GETPOS		;Calculate cursor posn
	LD	HL,READING	;Display "Reading : "
	CALL	DISPSTR
	CALL	CASSON		;Turn on cassette
	CALL	RDHEAD		;Search for header
	CALL	RDDAT		;Read in Data
	DI			;Make sure off
	CALL	CASSOFF		;Turn off cassette
	LD	HL,WRITING	;Display "Writing : "
	CALL	DISPSTR		;
	LD	HL,DFBUF	;HL => Destination
	CALL	DISPSTR		;
	LD	HL,(CURPOS)	;P/u new cursor position
	CALL	GETCRS		;Convert to Row, Column
	LD	B,3		;Give system new cursor
	@@VDCTL			;
	CALL	DISDOKI		;Enable real RAM
	JR	WRTDES2		;
FORNOW	CALL	DISDOKI		;Enable real RAM
	CALL	CASSOFF		;Turn off cassette
WRTDES2	CALL	WRTDEST		;Write Destination file
	JP	EXIT		;Clean exit
;
;
IOERR	LD	L,A		;Xfer error # to HL
	LD	H,0		;
	OR	0C0H		;Abbrev, return
	LD	C,A
	@@ERROR			;Display error
	JR	OLDSP		;  and abort
;
ILLEGAL	JP	ABORT		;For now
;
ABORT	LD	HL,-1		;Show error return
	DB	0DDH		;Skip LD HL,0
EXIT	LD	HL,0		;Clean exit
OLDSP	LD	SP,$-$		;P/u original SP
	EI			;Re-enable interrupts
	@@CKBRKC		;Clear Break
	RET			;  and RETurn
;
DLEN	DB	0,0,0
CURPOS	DW	0		;Cursor Position
READERR	DB	LF,'Tape Read Error  ',CR
READING	DB	'Reading: ',ETX
WRITING	DB	LF,'Writing: ',ETX
FILENM	DB	'FILENM',CR
BUFFER	DS	6
DFBUF	DB	'Filename/ext:d',ETX
;
;
;	GTFILE - Stuff filename from FCB into buffer
;	DE => FCB with filename contained
;
GTFILE	LD	HL,FILENM	;HL => Filename buffered
	PUSH	HL		;Save it
	LD	B,6		;Init to all spaces
CLEAN	LD	(HL),' '
	INC	HL
	DJNZ	CLEAN
	POP	HL		;HL => Filename dest
	LD	B,6		;Only accept first 6
;
GETFILN	LD	A,(DE)		;P/u char
	CP	CR+1		;End ?
	RET	C		;Yes - done
	CP	'.'		;Start of password?
	RET	Z		;Yes - done
	LD	(HL),A		;Stuff into filename buff
	INC	HL		;Bump
	INC	DE
	DJNZ	GETFILN
	RET			;Done - RETurn
;
;	DOINIT - Do initialization
;
DOINIT	@@FLAGS			;IY => System Flags
;
;	Calculate highest mem address of buffer
;
	PUSH	HL		;Save command line stuff
	LD	HL,0		;P/u HIGH$
	LD	B,L
	BIT	1,(IY+CFLAG$)	;@CMNDR ?
	JR	Z,USEHI
	INC	B		;Use LOW$
USEHI	@@HIGH$
	INC	HL		;Set hi-mem byte
	DEC	H		;Give some lee-way
	DEC	H
	LD	A,H		;  & stuff in R/W routines
	LD	(ENUF+1),A
;
;	Display Log-on message
;
	LD	HL,HELLO$	;Display banner
	CALL	DSPLY
	POP	HL		;Process parm line
;
;	P/u READ or WRITE parm if entered
;
	PUSH	HL		;Save HL
	DEC	HL		;Back up one
CKPLP	INC	HL		;Bump
	LD	A,(HL)		;P/u char
	CP	CR+1		;Eol ?
	JR	C,DUNLIN	;Yes - done
	CP	'('		;Paramter entered ?
	JR	NZ,CKPLP	;No - go til eol
;
;	Process parameter entry
;
	LD	DE,PARMTBL	;DE => Param table
	@@PARAM
	JP	NZ,PRMERR	;NZ - parameter error
DUNLIN	POP	HL		;Rcvr command ptr
;
;	If C=N entered then use checksum
;
CPARM	LD	BC,0FFFFH	;Default no checksum
	INC	B		;User requesting checksum?
	RET	NZ		;Yes, return
	LD	A,0C9H		;Init RET opcode
	LD	(CHKERR+1),A	;Stuff into Checksum error
	RET
;
;	PRSOUR/PRDEST - Prompt for Source & Destination
;
PRSOUR	PUSH	HL		;Save HL
	LD	HL,DSF		;"Disk Source Filename"
	LD	B,23		;23 chars max
	JR	DOINPUT
PRDEST	PUSH	HL		;Save HL
	LD	HL,TDF		;"Tape Dest Filename"
	LD	B,6		;6 char max
DOINPUT	CALL	DSPLY		;Display prompt
	PUSH	HL		;Save prompt start
	CALL	INPUT		;Input
	@@FSPEC			;Legal ?
	POP	HL		;HL => Prompt string
	JR	NZ,DOINPUT	;Reprompt on bad name
	POP	HL		;Recover ptr
	RET			;  and return
;
;	PRSOUR2/PRDEST2 - Prompt for READ source/dest
;
PRSOUR2	PUSH	HL		;Save HL
	LD	HL,TSF		;"Tape Source filename"
	LD	B,6		;6 char max
	JR	DOINPUT
PRDEST2	PUSH	HL		;Save HL
	LD	HL,DDF		;"Disk Destination file"
	LD	B,23		;23 char max
	JR	DOINPUT
;
;	INPUT - Line input routine
;
INPUT	PUSH	DE		;Save DE
	PUSH	BC		;  and BC
	LD	HL,INBUFF	;HL => Input buffer
	@@KEYIN			;Input line
	JP	C,ABORT		;<BREAK> abort
	POP	BC		;Restore regs
	POP	DE
	RET
;
DSP	PUSH	DE		;Save DE
	@@DSP			;Output char
	JR	EXDSP
;
DSPLY	PUSH	DE		;Save DE
	@@DSPLY			;Display message
EXDSP	POP	DE		;Rcvr DE
	RET	Z		;RETurn if OK
	JP	IOERR		;  else abort
;
COUNT	DB	0		;Count
;
HELLO$	DB	1CH,1FH,'TAPE100'
*GET	CLIENT:3
;
RDORWR	DB	'<R>ead or <W>rite ? ',CURON,ETX
TSF	DB	'Tape Source Filespec ? ',CURON,ETX
DSF	DB	'Disk Source Filespec ? ',CURON,ETX
TDF	DB	'Tape Destination Filespec ? ',CURON,ETX
DDF	DB	'Disk Destination Filespec ? ',CURON,ETX
TREADY	DB	'Ready Cassette & Press <ENTER>'
	DB	CURON,ETX
PRMERR$	DB	'Parameter error',LF,CR
TOOBIG$	DB	'File too large to fit in available '
	DB	'memory',LF,CR
;
;
;	Error Exit routine
;
PRMERR	LD	HL,PRMERR$	;"Parameter Error"
	DB	0DDH		;Skip
TOOBIG	LD	HL,TOOBIG$	;"File too Big"
;
	@@LOGOT			;Display error
	JP	ABORT		;Good bye
;
;	Parameter Table
;
PARMTBL	DB	80H		;6.x @PARAM
	DB	FLAG!ABB!5
	DB	'WRITE'
WRESP	DB	0
	DW	WPARM
;
	DB	FLAG!ABB!4
	DB	'READ'
RRESP	DB	0
	DW	RPARM
;
	DB	FLAG!ABB!4
	DB	'CHECK'
CRESP	DB	0
	DW	CPARM+1
;
	DB	0
;
RPARM	DW	0
WPARM	DW	0
;
	DC	50,0		;Patch space
;
*GET	TAPE100A:3
*GET	TAPE100B:3
;
FCB1	DS	32
FCB2	DS	32
INBUFF	DS	25
;
	ORG	$<-8+1<+8
;
IOBUFF	DS	256
MEM	EQU	$
;
	END	START
