	; PC-FX timer interrupt example
	; by Matej Horvat

	; I do not know how exactly the interrupt level functionality on the
	; PC-FX works and how it is related to V810 interrupt levels, but I
	; did succeed at using the timer interrupt. This program shows how.
	; It depends on the default hardware state as set up by the BIOS.

	!ORG 0x8000

EntryPoint:
	?br Main

.timer:
	; The timer vector jumps here
	?br TimerInterruptHandler

Main:
	; Initialize the stack pointer to the end of the RAM
	?mov 0x200000, $SP

	; Set the timer vector (0x7FD8 - obtained experimentally because
	; interrupt levels and their relation to the V810 are unclear).
	; 0x8A00 is the opcode of BR.
	?mov (EntryPoint.timer - 0x7FD8) | 0x8A00, $10
	st.h $10, 0x7FD8[$0]

	; Interrupt mask (only the timer is allowed)
	?mov 0x3F, $10
	out.h $10, 0xE40[$0]

	; Set up the timer frequency
	out.h $0, 0xFC0[$0]	; Timer counter = 0
	?mov 1432, $10		; ~1 ms
	out.h $10, 0xF80[$0]	; Timer period
	mov 7, $10		; Timer on + interrupt on + IRQ pending
	out.h $10, 0xF00[$0]

	; Set the V810 interrupt level
	?mov 0x90000, $10
	ldsr $10, $PSW

	; Main loop. In this example, we do nothing.
.loop:
	halt
	br .loop

TimerInterruptHandler:
	; This is called each time the timer counter reaches 0.

	; Save $1
	add -4, $SP
	st.w $1, 0[$SP]

	; Insert your code here. In this example, we just increment $2.
	; In an emulator's debugger, you will see it change even though
	; the main program loop does nothing.
	add 1, $2

	; Reset the timer for the next interrupt
	mov 3, $1		; Timer enabled + interrupt enabled
	out.h $1, 0xF00[$0]

	; Restore $1
	ld.w 0[$SP], $1
	add 4, $SP

	; Return from interrupt handler
	reti