COUNTR	EQU	72 ;16572 HZ

TCADRC	EQU	43H
TCADRD	EQU	40H

TCMODE	EQU	34H

;-------------------------------------------

STK	SEGMENT	STACK
	DW	128 DUP (0)
STK	ENDS

;-------------------------------------------

CODE	SEGMENT	PARA
	ASSUME	CS:CODE,DS:CODE,SS:STK
	ASSUME	ES:NOTHING

;-------------------------------------------

COMADRS	DW	3FEH
	DW	2FEH
	DW	3EEH
	DW	2EEH
COMADR	DW	0
FILELEN	DW	0
HANDLE	DW	0
MSG1	DB	'Press a key to start '
	DB	'and stop.',0DH,0AH,24H
MSG2	DB	'Disk error',0DH,0AH,24H
MSG3	DB	'COM port number not'
	DB	' valid',0DH,0AH,24H
MSG4	DB	'Recording...',0DH,0AH,24H
MSG5	DB	'End recording',0DH,0AH,24H

;-------------------------------------------

START:

	CALL	PARSE

;set DS and ES

	PUSH	CS
	POP	DS
	PUSH	CS
	POP	ES

;decide which COM port to use

	MOV	BL,FIRSTPARM
	SUB	BL,31H
	JNC	CHKCOMHI
COMERR:	MOV	DX,OFFSET MSG3
	MOV	AH,9
	INT	21H
	MOV	AX,4C01H
	INT	21H
CHKCOMHI: CMP	BL,3
	JA	COMERR
	SHL	BL,1
	SUB	BH,BH
	ADD	BX,OFFSET COMADRS
	MOV	AX,[BX]
	MOV	COMADR,AX

;create the file

	MOV	DX,OFFSET SECONDPARM
	MOV	CX,0
	MOV	AX,3C00H
	INT	21H
	JNC	L1
	JMP	DSKERR
L1:	MOV	HANDLE,AX

;substitute local keyboard interrupt routine

	MOV	AX,3509H
	INT	21H
	MOV	WORD PTR OLDKBINT,BX
	MOV	WORD PTR OLDKBINT+2,ES

	MOV	DX,OFFSET KBINT
	MOV	AX,2509H
	INT	21H

;delay 1 second

	MOV	AX,40H
	MOV	ES,AX
	MOV	BX,6CH
	MOV	AX,ES:[BX]
	MOV	CX,18
DL1:	CMP	AX,ES:[BX]
	JE	DL1
	MOV	AX,ES:[BX]
	LOOP	DL1
	PUSH	DS
	POP	ES

;print the prompt

	MOV	DX,OFFSET MSG1
	MOV	AH,9
	INT	21H

;wait for a complete keystroke

	STI
	MOV	BP,0
WFKS:	CMP	BP,2
	JB	WFKS

;display message

	MOV	DX,OFFSET MSG4
	MOV	AH,9
	INT	21H

;get vector of timer current timer interrupt

	MOV	AX,3508H
	INT	21H
	MOV	WORD PTR OLDTMRINT,BX
	MOV	WORD PTR OLDTMRINT+2,ES

;mask timer interrupt

	IN	AL,21H
	OR	AL,01H
	OUT	21H,AL

;plug in the local timer interrupt routine

	MOV	DX,OFFSET TIMERINT
	MOV	AX,2508H
	INT	21H

;rev up timer

	MOV	AL,TCMODE
	OUT	TCADRC,AL
	MOV	AX,COUNTR
	OUT	TCADRD,AL
	MOV	AL,AH
	OUT	TCADRD,AL

;set DS

	ASSUME	DS:NOTHING
	MOV	AX,HIMEM
	MOV	DS,AX

;initialize registers

	MOV	BP,0
	MOV	BX,0
	MOV	AH,0
	MOV	DX,COMADR

;unmask timer interrupt

	IN	AL,21H
	AND	AL,0FEH
	OUT	21H,AL
	STI

;test for done

TFD:
	OR	BP,BP
	JE	TFD

;save data length

	MOV	FILELEN,BX

;mask timer interrupt

	CLI
	IN	AL,21H
	OR	AL,01H
	OUT	21H,AL
	STI

;fix DS

	MOV	AX,CS
	MOV	DS,AX
	ASSUME	DS:CODE

;fix timer

	MOV	AL,TCMODE
	OUT	TCADRC,AL
	MOV	AL,0
	OUT	TCADRD,AL
	OUT	TCADRD,AL

;restore original timer interrupt vector

	PUSH	DS
	LDS	DX,CS:OLDTMRINT
	MOV	AX,2508H
	INT	21H
	POP	DS

;unmask timer interrupt

	IN	AL,21H
	AND	AL,0FEH
	OUT	21H,AL

;restore keyboard interrupt vector

	PUSH	DS
	LDS	DX,CS:OLDKBINT
	MOV	AX,2509H
	INT	21H
	POP	DS

;display message

	MOV	DX,OFFSET MSG5
	MOV	AH,9
	INT	21H

;figure out how long the system 18.2 Hz
; timer has been off

	MOV	AX,COUNTR
	SHL	AX,1
	SHL	AX,1
	SHL	AX,1
	MOV	CX,FILELEN
	MUL	CX

;adjust the BIOS time of day to catch up

	PUSH	ES
	MOV	AX,40H
	MOV	ES,AX
	MOV	BX,6CH
	CLI
	ADD	ES:[BX],DX
	ADC	WORD PTR ES:[BX+2],0
	CMP	WORD PTR ES:[BX+2],18H
	JB	BIOSFIXED
	JA	WRAP
	CMP	WORD PTR ES:[BX],0B0H
	JB	BIOSFIXED
WRAP:	SUB	WORD PTR ES:[BX],0B0H
	SBB	WORD PTR ES:[BX+2],18H
BIOSFIXED: STI
	POP	ES

;save the whole mess in the file

	MOV	AX,HIMEM
	MOV	DS,AX

	ASSUME	DS:NOTHING

	MOV	BX,HANDLE
	MOV	CX,FILELEN
	MOV	AH,40H
	MOV	DX,0
	INT	21H
	JC	DSKERR

	MOV	AH,3EH
	INT	21H

;clean up & exit

	CALL	FLUSHKB
	MOV	AX,4C00H
	INT	21H

;disk error message exit

DSKERR:
	MOV	AX,CS
	MOV	DS,AX
	MOV	DX,OFFSET MSG2
	MOV	AH,9
	INT	21H
	CALL	FLUSHKB
	MOV	AX,4C01H
	INT	21H

;-------------------------------------------

;flush the keyboard buffer

FLUSHKB	PROC

	MOV	AH,1
	INT	16H
	JZ	FLUSHKB1
	MOV	AH,0
	INT	16H
	JMP	FLUSHKB
FLUSHKB1: RET

FLUSHKB	ENDP

;-------------------------------------------

;timer interrupt routine

	ASSUME	DS:NOTHING,ES:NOTHING
	ASSUME	SS:NOTHING

	EVEN

OLDTMRINT DD	0

TIMERINT PROC	FAR

	OR	BP,BP
	JNZ	TMRINT1

	IN	AL,DX

	MOV	CL,4
	RCL	AL,CL
	RCL	CH,1

	INC	AH
	CMP	AH,8
	JNE	TMRINT1
	SUB	AH,AH

	MOV	[BX],CH

	INC	BX
	OR	BX,BX
	JNZ	TMRINT1
	INC	BP

TMRINT1:
	MOV	AL,20H
	OUT	20H,AL
	IRET

TIMERINT ENDP

;-------------------------------------------

;keyboard interrupt routine

	ASSUME	DS:NOTHING,ES:NOTHING
	ASSUME	SS:NOTHING

	EVEN

OLDKBINT DD	0

KBINT	PROC	FAR

	INC	BP

	JMP	CS:OLDKBINT

KBINT	ENDP

;-------------------------------------------

FIRSTPARM	DB	128 DUP (0)
SECONDPARM	DB	128 DUP (0)

SPECERRMSG	DB	'File specification'
	DB	' error',0DH,0AH,24H

;it is assumed that DS and ES both point
; to the PSP.

PARSE	PROC

	CLD
	MOV	DI,80H
	MOV	CL,[DI]
	SUB	CH,CH
	INC	DI

;find first non-blank character

	MOV	AL,20H
	REPE	SCASB
	JNE	PARS2
	PUSH	CS
	POP	DS
	MOV	DX,OFFSET SPECERRMSG
	MOV	AH,9
	INT	21H
	MOV	AX,4C01H
	INT	21H

;find next blank character

PARS2:
	DEC	DI
	INC	CX
	MOV	BX,DI
	REPNE	SCASB
	JE	PARS3
	PUSH	CS
	POP	DS
	MOV	DX,OFFSET SPECERRMSG
	MOV	AH,9
	INT	21H
	MOV	AX,4C01H
	INT	21H

;save first filename

PARS3:
	DEC	DI
	INC	CX
	PUSH	CX
	PUSH	DI
	PUSH	ES
	PUSH	CS
	POP	ES
	MOV	CX,DI
	SUB	CX,BX
	MOV	SI,BX
	MOV	DI,OFFSET FIRSTPARM
	REP	MOVSB
	POP	ES
	POP	DI
	POP	CX

;find next non-blank character

	MOV	AL,20H
	REPE	SCASB
	JNE	PARS4
	PUSH	CS
	POP	DS
	MOV	DX,OFFSET SPECERRMSG
	MOV	AH,9
	INT	21H
	MOV	AX,4C01H
	INT	21H

;find next blank character or end

PARS4:
	DEC	DI
	INC	CX
	MOV	BX,DI
	REPNE	SCASB

;save second filename

	JCXZ	PARS5
	DEC	DI
PARS5:	PUSH	CX
	PUSH	DI
	PUSH	ES
	PUSH	CS
	POP	ES
	MOV	CX,DI
	SUB	CX,BX
	MOV	SI,BX
	MOV	DI,OFFSET SECONDPARM
	REP	MOVSB
	POP	ES
	POP	DI
	POP	CX

	RET

PARSE	ENDP

;-------------------------------------------

CODE	ENDS

;-------------------------------------------

HIMEM	SEGMENT	PARA
HIMEM	ENDS

	END	START
