org	00000H

	jmp	hdlr_RST
;
	nop
	jmp	hdlr_IRQ
;
	nop
	nop
	retr
;
hdlr_RST:
	dis	i		; disable IRQ
	dis	tcnti		; disabler timer IRQ
	sel	rb0		; set up main register bank (dmem[0..7])
	sel	mb0		; select memory bank 0
	orl	p1,#0FFH	; p1=0xff (CPU data)
	orl	p2,#0FFH	; p2=0xff (control: p25=CNT49/in, p26=INT49, p27=WR49); BUS goes to MSM6200
	mov	r0,#019H	; xptr (main)
	mov	r1,#020H	; dptr (main)
	mov	r2,#000H	; dptr (main CPU to 8049)
	mov	r3,#000H
	mov	r4,#000H	; CPU port rescue
	mov	r5,#080H	; add flag (main)
	mov	r6,#000H
	mov	r7,#000H	; register rescue (main)
	sel	rb1		; set up IRQ register bank (dmem[8..15])
	mov	r0,#000H	; xptr (IRQ)
	mov	r1,#020H	; dptr (IRQ)
	mov	r2,#000H
	mov	r3,#000H
	mov	r4,#000H
	mov	r5,#080H	; add flag (IRQ)
	mov	r6,#000H
	mov	r7,#000H	; register rescue (IRQ)
	sel	rb0		; select register bank 0
t0h_0032:
	jt0	t0h_0032	; loop if test0 (SYNC49) is high (i.e. pending WR49#)
t1h_0034:
	jt0	t1h_0034	; loop if test1 (triggered by main CPU) is high -- probably "wait for me", not used on FZ-1, but HT6000
	mov	a,#0FFH		; delay, probably wait for MSM6200 to settle
dly_0038:
	dec	a
	jnz	dly_0038
t0h_003B:			
	jt0	t0h_003B	; wait for pending WR49#/SYNC49, if any
t0h_003D:			
	jt0	t0h_003D	; wait for pending WR49#/SYNC49, if any
	mov	a,r0		; save xptr
	mov	r7,a		
	mov	r0,#008H	; msm[0x08] = 0
	movx	@r0,a
	mov	a,r7		; restore xptr
	mov	r0,a
	mov	a,#0FFH		; wait 0xff
dly_0048:
	dec	a
	jnz	dly_0048
	en	i		; enable interrupts
	call	MSM_xfer
	anl	p2,#0EFH	; clear p2.4		neither used on FZ-1 nor HT6000
	jmp	mainloop
;
mainloop:
	call	CPU_xfer
	call	MSM_xfer
	mov	r0,#019H	; index IRQ.dptr (bank1, R1)
	mov	r5,#080H
	jmp	mainloop
;
MSM_xfer:
	mov	a,r0		; r0 to A
	mov	r7,a		; rescue r0
	mov	r0,#007H	; msm[0x07]=(0x00/0x19)	either "CPU ready for next key(s)" or "stop scanning"
	movx	@r0,a
	mov	r0,#002H
	dis	i		; mutex write/read
	movx	@r0,a		; msm[0x02]=(0x00/0x19)	probably status read trigger + read
	movx	a,@r0		; (val) = msm[0x02]	
	en	i
	outl	p1,a		; port1 = (val)		
	dec	r0		; msm[0x01] = (val)	probably "resume scanning / ready for next key"
	movx	@r0,a
	anl	p2,#0F7H	; toggle p2.3 (neither used on FZ-1 nor HT6000)
	orl	p2,#008H	;
	mov	a,r7		; restore r0
	mov	r0,a
	ret
;

; MSM access:	  0x00/0x01/0x00/0x01
; memory storage: 0x20|0x21|0x22|0x23 (0x82|0x83 -> wraps over)
hdlr_IRQ:
	sel	rb1		; switch to IRQ register set
	mov	r7,a		; save A
IRQ_loop:
	movx	@r0,a		; msm[0x00] = A 	presumably "get key" trigger
	movx	a,@r0		; A=msm[xptr]		key number
	mov	@r1,a		; data[0x20] = A
	inc	r0		
	inc	r1		
	movx	@r0,a		; msm[0x01] = A		presumably "get velocity" trigger
	movx	a,@r0		; A=msm[xptr+1]		velocity
	mov	@r1,a		; data[0x21] = A
	inc	r1		; 
	mov	a,r1		; dptr+=0x80 (wraps back to 0x2* due to dmem size)
	add	a,r5
	jnc	L0082		; reset dptr after 0x20/0x21/0x22/0x23 (0x20/0x21/0x82/0x83->0x103)
	mov	r1,#020H	; 
L0082:
	dec	r0		; back to msm[0x00]
	jni	IRQ_loop	; got another key/vel pair?
	mov	r0,#000H	; reset xptr
	mov	r5,#080H	; why needed? Noone alters r5.
	mov	a,r7		; restore A
	sel	rb0		; switch to main register set
	retr
;
CPU_xfer:
	orl	p2,#010H	; set p2.4 (mark start of transfer; neither used on FZ-1 nor HT6000)
	orl	p2,#010H	; busy wait
	in	a,p1		; rescue CPU port configuration
	mov	r4,a		; 
	mov	a,r1		; get dptr
	xrl	a,@r0		; xor mem[@B0.R0 or @B1.R1] -- simple way of comparing dptr-read vs. dptr-write
	jz	CPU_xfer_done
	mov	a,@r1		; p1 = dmem[dptr] = key if CPU ready
wait4sync1:
	jt0	wait4sync1
	outl	p1,a		; a to CPU
	dis	i
	anl	p2,#01FH	; clear WR49#, INT49# / CONT49#=0 (start of data transfer)
	orl	p2,#080H	; set WR49# (-> set SYNC49 via DFF.PR#)
	orl	p2,#080H	; set WR49# (busy wait)
	orl	p2,#040H	; set INT49# (trigger CPU IRQ)
	en	i
loop_CPU_xfer:
	inc	r1
	mov	a,@r1		; p1 = dmem[dptr] = vel if CPU ready
wait4sync2:
	jt0	wait4sync2
	outl	p1,a		
	dis	i
	anl	p2,#07FH	; clear WR49#
	orl	p2,#080H	; set WR49# (-> set SYNC49)
	en	i
	inc	r1
	mov	a,r1
	add	a,r5
	jnc	wait4sync3
	mov	r1,#020H	; reset dptr
wait4sync3:
	jt0	wait4sync3
	mov	a,r1
	xrl	a,@r0
	jz	CPU_xfer_EOX
	mov	a,@r1		; p1 = dmem[dptr] = key (CPU is already ready, starting second data set)
	outl	p1,a
	dis	i
	anl	p2,#07FH	; clear WR49#
	orl	p2,#080H	; set WR49#
	en	i
	jmp	loop_CPU_xfer
;
CPU_xfer_EOX:
	orl	p2,#020H	; set CONT49# (end of data transfer)
CPU_xfer_done:
	mov	a,r4		; restore CPU port configuration
	outl	p1,a
	anl	p2,#0EFH	; clear p2.4 (end of transfer)
	ret
;