;++
; RSXTEM - RSXMAKER RSX Template
;
; Copyright (c) 1986 by AutoSoft Incorporated
;
; See RSXMAKER.DOC for information.
;
;--

;+
; RSX Header RFLAGS Flag bit definitions
;-
FIRST	EQU	1	; First RSX installed
LAST	EQU	2	; Last RSX installed
NOREMOV	EQU	4	; RSX may be removed
REINIT	EQU	8	; Re-initialize on subsequent installation requests
MULTI	EQU	16	; Install another copy on subsequent installs
OVRLAY	EQU	32	; Overlay CCP if first RSX installed
NOMORE	EQU	64	; No more RSX's may be installed
NORELO	EQU	128	; Do not relocate this RSX
RELINI	EQU	256	; Call INIT routine after relocation

;+
; RSX Header Section begins here
;-
	ORG	100H		; Origin *must* be at 100H

;+
; Do not modify these 14 fields
;-
RSX:	JMP	RSTART		; Jump to real code (jumped to from 0005)
RSXRST:	JMP	RESET		; Reset handler
RINIT:	JMP	INIT		; Initialization code
RTERM:	JMP	TERM		; Termination code
RELST:	JMP	RSXCODE		; Start of relocatable code
DATAST:	JMP	RSXDATA		; Start of data section (copied as is)
RELEND:	JMP	RSXEND		; End of RSX code and data to be relocated
NXTWB:	JMP	$-$		; WBOOT path (filled in by RSXMAKER)
NEXT:	JMP	$-$		; BDOS path (filled in by RSXMAKER)
WBADR:	DW	$-$		; Filled in by RSXMAKER
WBJMP:	DW	$-$		; Filled in by RSXMAKER
RSIZE:	DW	RSXEND-RSX	; Size of RSX code and data
RSXID:	DB	'AutoSoft'	; ID - Must be 'AutoSoft'

;+
; The next three fields may be modified by the RSX programmer
;-
RFLAGS:	DW	RELINI+REINIT 	; RSX flags (combine with +)
RNAME:	DB	'OSB-EMU '	; Name - must be 8 bytes - pad on rt w/spaces
RDESC:	DB	'Osborne (ADM-3A) emulator for CPC464.',0
				; Description (null terminated)


;+
; RSX Code Section begins here
;-
RSXCODE EQU $			; Executable code *only* between here
				; and RSXDATA (no in-line prints allowed)

;+
; Initialization Routine (end with RET)
;-
INIT:				; This *must* be the label

	MVI	C,9		; Just write a message to the console
	LXI	D,INITMSG	;
	CALL	NEXT		;
	RET			; And return

;+
; Termination Routine (end with RET)
;-
TERM:				; This *must* be the label


	MVI	C,9		; Just write a message to the console
	LXI	D,TERMMSG	;
	CALL	NEXT		;
	RET			; And return

;+
; BDOS Intercept Routine (end with JMP NEXT or RET)
;-
RSTART:				; This *must* be the label

	MVI	H,0		; Clear HL
	MVI	L,0
	DAD	SP		; Get current stack pointer
	SHLD	USRSTK		; Save it
	LXI	SP,LOCSTK	; Switch to local stack

	PUSH	D		; Save environment
	PUSH	B		;
	PUSH	PSW		;
;
	MOV	A,C		; Get BDOS call
	CPI	2		; Console output?
	JZ	OUTCHAR		; Then check character
	CPI	6		; Direct console i/o?
	JNZ	FINISH1		; No, then go to BDOS
	MOV	A,E		; Get byte to BDOS
	CPI	0FDH		; Is it console output?
	JNC	FINISH1		; No, then go to BDOS
OUTCHAR:
	LXI	H,CTDATA1	; Get flag for control character
	XRA	A
	CMP	M		; Is it zero?
	JNZ	OUTCH1		; No, then something has to be done
	MOV	A,E		; Get character to console
	CPI	1AH		; Clear screen?
	JZ	CLRSCR
	CPI	1EH		; Cursor home?
	JZ	CURHOME
	CPI	1BH		; Is it 'esc'?
	JNZ	RMOVCTL		; No, then continue to BDOS
	STA	CTDATA1		; Store it in flag position
	JMP	FINISH		; Return to caller
;
OUTCH1:
	MOV	A,M		; Get flag character
	CPI	1
	JZ	GET1ST		; Get row
	CPI	2
	JZ	GET2ND		; Get column
	XRA	A
	MOV	M,A		; Zero out flag
	MOV	A,E		; Get character
 	CPI	'z'
 	JNC	FINISH		; Not a valid character
	LXI	H,CTDATA2	; Point to control character to be converted
	LXI	D,CTDATA3	; Point to new control character
	MVI	B,4		; Number of control characters
LOOP:
	CMP	M		; Compare with ADM-3A control character
	JZ	FOUND
	INX	D		; Increase pointers
	INX	H
	DCR	B		; Decrease counter
	JNZ	LOOP
;
	CPI	'='		; Cursor position prefix?
	JZ	CURSPR
	CPI	'R'		; Delete line?
	JNZ	FINISH		; Not a valid ESC-sequence
	MVI	E,11H
	MVI	C,6
	PUSH	B
	CALL	NEXT
	POP	B
	MVI	E,12H
	CALL	NEXT
	JMP	FINISH
;
CLRSCR:
	MVI	A,0CH
	JMP	PRCHAR
;
CURHOME:
	MVI	A,1EH
	JMP	PRCHAR
;
CURSPR:
	MVI	A,1		; Indicate start of cur. pos. sequence
	JMP	STFLAG
;
GET1ST:
	MOV	A,E		; Get row position
	STA	ROW		; And store
	MVI	A,2		; Wait for next cur. position
STFLAG:
	STA	CTDATA1	
	JMP	FINISH		; Return to caller
;
GET2ND:
	XRA	A
	STA	CTDATA1		; End of sequence
	MOV	A,E
	STA	COL		; Store column
	MVI	C,6
	MVI	E,1FH		; Cursor prefix
	PUSH	B
	CALL	NEXT
	POP	B
	LDA	COL		; Get first part of position report
	SUI	1FH		; In correct range
	PUSH	B
	MOV	E,A
	CALL	NEXT
	POP	B
	LDA	ROW		; Second part of report
	SUI	1FH
	JMP	PRCHAR		; And jump to BDOS
;
FOUND:
	LDAX	D		; Get new control character
PRCHAR:
	MOV	E,A		; Store character in right place
	CALL	NEXT		; Call BDOS
; 	
FINISH:
	POP	PSW		; Restore environment
	POP	B		;
	POP	D		;
	LHLD	USRSTK		; And stack pointer
	SPHL			;
	RET
;
RMOVCTL:
	LXI	H,UNWANT	; Point to table of unwanted characters
	MVI	B,11		; Number of characters
RMLOOP:
	CMP	M
	JZ	FINISH		; If found, return to caller
	INX	H		; Next character
	DCR	B		; Decrease counter
	JNZ	RMLOOP		; Next character
;				Fall through to FINISH1
;
FINISH1:
	POP	PSW		; Restore environment
	POP	B		;
	POP	D		;
	LHLD	USRSTK		; And stack pointer
	SPHL			;
	JMP	NEXT		; Pass control to next RSX

;+
; WBOOT Intercept Routine (end with JMP NXTWB)
;-
RESET:	LXI	SP,LOCSTK	; Local stack

	LHLD	RFLAGS		; HL = flags word
	MOV	A,L		; Low byte
	ANI	FIRST		; First?
	JZ	NOT1ST		; If Z, no

	MVI	C,13		; Disk system reset
	CALL	NEXT		; (you might want to comment this and the
				; previous line out to speed up warm boots)

NOT1ST:	MOV	A,L		; Get flags
	ANI	LAST		; Last?
	JZ	NOTLST		; If Z, no

	LXI	H,RSX		; Else reload BDOS vector
	SHLD	0006		;
	LHLD	WBJMP		; HL -> WBOOT vector in BIOS jump table
	SHLD	0001		; Insert WBOOT vector
	INX	H		; Point past JMP
	LXI	D,RSXRST	; Our WB address
	MOV	M,E		; Copy it into BIOS jump table
	INX	H		;
	MOV	M,D		;

NOTLST:	JMP	NXTWB		; And pass control to next RSX (or CCP)

;+
; RSX Data Section
;-
RSXDATA EQU $			; Data *must* start here - no data
				; allowed before this point; no executable
				; code beyond.

TERMMSG:
	DB	'Osborne emulator is removed.',13,10,'$'
INITMSG:
	DB	'Osborne emulator is installed.',13,10,'$'
CTDATA1:
	DB	0
CTDATA2:
	DB	'T','Y',')','('
CTDATA3:
	DB	12H,14H,18H,18H
UNWANT:
	DB	04H,05H,06H,0EH,0FH,15H,16H,17H,19H,1CH,1DH
;
ROW:
	DS	1
COL:
	DS	1
;
	DS	16		; 16-byte stack
LOCSTK:				; Initial SP
USRSTK:	DW	0		; Caller's SP

RSXEND EQU $			; No code or data allowed beyond this label
