; TYPE3HDR will eventually fail if your system is interrupt driven.
; If an interrupt occurs after the RET planted at 0000H is executed
; and before the two  DEC   SP  operations are executed the address
; that you find on the stack will be that pushed by the interrupt.
; It may close but that only counts in horseshoes. And the ZCPR33
; program running on your ZCPR33 system will mysteriously exit.
; The fix is to include a DI and an EI as shown below.
;   9-25-87   C. S. Irvine

; This is header code that can be used at the beginning of a type-3-environment
; program so that it will abort with an error message when not loaded to the
; correct address (such as when a user tries to run it under CP/M or Z30).

entry:
	jr	start0		; Must use relative jump
	defb	0		; Filler
	db	'Z3ENV',3	; Type-3 environment
z3env:	dw	0		; Filled in by Z33
	dw	entry		; Intended load address

start0:
	ld	hl,0		; Point to warmboot entry
	ld	a,(hl)		; Save the byte there
	ld	(hl),0c9h	; Replace it with a return opcode

	di		; PROTECT THE RETURN ADDRESS   CSI

	rst	0		; Call address 0, pushing RETADDR onto stack
retaddr:
	ld	(hl),a		; Restore byte at 0
	dec	sp		; Fake a push (leaving stack as it was)
	dec	sp

	ei		; NOW THAT WE HAVE RESET THE SP ALLOW INTERRUPTS   CSI

	pop	hl		; HL now has actual address of RETADDR
	ld	de,retaddr	; This is where we should be
	xor	a		; Clear carry flag
	push	hl		; Save address again
	sbc	hl,de		; Subtract -- we should have 0 now
	pop	hl		; Restore value of RETADDR
	jr	z,start		; If addresses matched, begin real code

	ld	de,notz33msg-retaddr ; Offset to message
	add	hl,de
	ex	de,hl		; Switch pointer to message into DE
	ld	c,9
	jp	0005h		; Return via BDOS print string function

notz33msg:
	defb	'Not Z33+$'	; Abort message if not Z33-compatible

start:
	ret			; Replace with real code

	end
