*-----------------------------------------------------------------------
* CASPATCH.ASM - Patch the editor/assembler to allow use of Altair 680
*   cassette interface. The editor "E" command (punch edit buffer to
*   tape) and the assembler "2T" command (punch S-record tape) are
*   patched to output to the cassette interface as well as the console
*   port. The console input routine is patched to accept input from the
*   cassette interface during an "I" command.
*
*   Mike Douglas, Dec 11, 2023
*-----------------------------------------------------------------------

* Console and Cassette Equates

CONSR	EQU	$F000		;CONSOLE SERIAL PORT
CONDR	EQU	$F001
CASSR	EQU	$F010		;CASSETTE SERIAL PORT
CASDR	EQU	$F011

*-------------------------------------------------------------------------
* This patch code is located in spare space made by starting the
*   edit buffer at $1CD8 instead of $1C81.
*-------------------------------------------------------------------------
	ORG	$1C81
PUNFLAG	FCB	0		;NON-ZERO IF PUNCHING
IFLAG	FCB	0		;NON-ZERO IF "I" COMMAND IN PROCESS

* INCHAR - Return byte in B from console or the cassette. Cassette
*    input is returned only if an 'I' was the last character typed
*    on the console.

INCHAR	LDAB	CONSR		;ANYTHING FROM CONSOLE?
	RORB
	BCC	CHKCAS		;NO, CHECK CASSETTE

	JSR	$FF00		;GET THE NEW CONSOLE CHARACTER
	CLR	IFLAG		;ASSUME NOT AN 'I'
	CMPB	#'I		;POSSIBLE 'I' COMMAND?
	BNE	ICEXIT		;NO
	INC	IFLAG		;ELSE, IT COULD BE
ICEXIT	RTS

CHKCAS	LDAB	CASSR		;ANYTHING FROM THE CASSETTE
	RORB
	BCS	INCHAR		;NO, GO CHECK CONSOLE AGAIN

	LDAB	CASDR		;GET THE BYTE FROM CASSETTE
	TST	IFLAG		;IN A POSSIBLE 'I' COMMAND?
	BEQ	INCHAR		;NO, IGNORE IT (PROBABLY GARBAGE)
	ANDB	#$7F		;ELSE, RETURN THE CHARACTER
	RTS

* OUTCHAR - Output byte in A (or B) to console, and if PUNFLAG true,
*   output to the cassette port as well

OUTCHAR	JSR	$FF81		;OUTPUT B TO CONSOLE (IN MONITOR)
	TST	PUNFLAG		;WRITING TO PUNCH TOO?
	BEQ	NOPUN		;NO, EXIT

WAITPUN	LDAB	CASSR		;WAIT FOR XMIT READY
	BMI	WAITPUN

	STAA	CASDR		;SEND BYTE TO CASSETTE

NOPUN	JMP	$0230		;JSR/RTS IS TOO SLOW FOR 9600 BAUD

* STARTE - Start of the editor E command (punch source tape). Set
*   PUNFLAG true.

STARTE	INC	PUNFLAG		;SET PUNFLAG TRUE
	LDX	#1		;PERFORM INSTRUCTION CLOBBERED AT $1AC6
	RTS

* EXITE - Exiting the editor E command. Set PUNFLAG false.

EXITE	CLR	PUNFLAG		;NO LONGER PUNCHING
	JMP	$167C		;THE REPLACED JUMP WENT HERE

* START2T - Start of an assembler pass 2 command. If it is the 2T
*   command to punch a tape, set PUNFLAG true.

START2T	LDAA	$001A		;PUNCH S-RECORD TAPE (2T)?
	STAA	PUNFLAG		;PUNFLAG TRUE IF SO
	CLRA			;PERFORM INSTRUCTIONS CLOBBERED AT $974
	STAA	$0026
	RTS

* EXIT2T - Exiting the assembler pass 2 command. Set PUNFLAG false

EXIT2T	CLR	PUNFLAG		;NO LONGER PUNCHING
	LDX	#$04D9		;PERFORM INSTRUCTION CLOBBERED AT $0B8A
	RTS

*-------------------------------------------------------------------------
* Hooks into the Assembler/Editor
*-------------------------------------------------------------------------

* Move the start of the edit buffer from $1C81 to $1CD8 to make
*   room for the patch code.

	ORG	$0126		;IN MEMORY SIZE ROUTINE (START)
	LDX	#$1CD6

	ORG	$088B		;IN ASSEMBLER
	LDX	#$1CD9

	ORG	$1648		;IN EDITOR
	LDX	#$1CD8

* Re-direct the console input routine to INCHAR

	ORG	$0183
	JSR	INCHAR

* Re-direct the console output routine to OUTCHAR

	ORG	$022D
	JMP	OUTCHAR

* Jump to the init patch for the assembler 2T command

	ORG	$0974
	JSR	START2T

* Jump to the exit patch for the assembler 2T command

	ORG	$0B8A
	JSR	EXIT2T

* Jump to the init patch for the editor E command

	ORG	$1AC6
	JSR	STARTE

* Jump to the exit patch for the assembler E command

	ORG	$1AE5
	JMP	EXITE

* Disable the punch 50 nulls routine

	ORG	$0167
	RTS

	END
