*******************************************************************************
* Amiga MC680x0 Hardware "Read-Keyboard" Interrupt Handler
* ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
* This source provides a nice and easy way of polling the Amiga keyboard from
* a hardware environment. The OS *must* be disabled in order to use this code!
* Use this for games, demo`s and the like.
*
* The nice thing about the routine is that it supports Keyboard Qualifiers, not
* many hardware keyboard handlers I have seen in the past do this! Also this
* routine uses cpu-independant & fully relocatable (completly pc-relative) code
*
* Once the Level 2 interrupt has been installed simply call 'ReadKeys' from
* either your level 3 interrupt or your Vblank... 
*
* $Outputs:	d0.b = current key
*		d1.b = keyboard qualifiers (see bit settings below)
*
* In this example if you press "CURSORLEFT" it will flash screen RED.. if
* you continue to hold the key and then hold SHIFT as well it will flash both
* RED and yellow.. a quick example of determining keyboard qualifiers!
*******************************************************************************
LSHIFT		=	1			* Bit: 0 (2^0)
RSHIFT		=	2			* Bit: 1 (2^1)
CAPS		=	4			* Bit: 2 (2^2)
CTRL		=	8			* Bit: 3 (2^3)
LALT		=	16			* Bit: 4 (2^4)
RALT		=	32			* Bit: 5 (2^5)
LAMIGA		=	64			* Bit: 6 (2^6)
RAMIGA		=	128			* Bit: 7 (2^7)

CURSORUP	=	$4C			* for a complete list of the
CURSORLEFT	=	$4F			* keys.. see RAWKEY codes..
						* in Hardware Ref.Manual or
						* work them out for yourself!

test:		move.l	4.w,a6
		jsr	-132(a6)		* forbid() - disable multitasking

		lea	Level2(pc),a1		* our new interrupt

		move.l	_VBR(pc),a4		* get vectorbase
		lea	OldLev2(pc),a0		* our level2 save
		move.l	$68(a4),(a0)		* save os level2
		move.l	a1,$68(a4)		* install new keyboard level2

*-------------- main loop

main		cmp.b	#255,$dff006		* wait vblank
		bne.s	main

DoKeys		bsr	ReadKeys		* Returns: d0.b = key code
						*	 : d1.b = qualifiers
		cmp.b	#CURSORLEFT,d0
		bne.s	no_more

		cmp.b	#LSHIFT,d1
		bne.s	no_shift
		move.w	#$ff0,$dff180		* screen yellow..
no_shift	move.w	#$f00,$dff180		* screen red..

no_more		cmp.b	#CURSORUP,d0
		bne.s	no_less

		move.w	#$00f,$dff180		* screen blue...
no_less
		btst	#6,$BFE001.l		* check leftmouse
		bne.s	main			* if pressed... exit..

*-------------- exit

		move.l	_VBR(pc),a4		* get vectorbase
		move.l	OldLev2(pc),$68(a4)	* restore os level2

		move.l	4.w,a6
		jsr	-138(a6)		* permit() - restore multitask

		lea	kb_temp(pc),a1
		moveq	#0,d0
		move.b	kb.Qualifiers(a1),d0
		move.b	kb.key(a1),d1
		rts	

_VBR:		dc.l	0			* current vectorbase
OldLev2		dc.l	0



		rsreset
kb.qualifiers:	rs.b	1
kb.keytmp:	rs.b	1
kb.lastkeytmp:	rs.b	1
kb.keydelaytmp:	rs.b	1
kb.repspeedtmp:	rs.b	1
kb.key:		rs.b	1
kb.reserved:	rs.w	1
kb.sizeof	rs.b	0
		rsreset

Level2		movem.l	d0-d7/a0-a6,-(sp)	* preserve irq reg`s..

		lea	$DFF000.l,a6		* hardware base..
		move.w	$1E(a6),d0		* intreqr
		and.w	#8,d0			* level 2 request ?
		beq.s	Exit_Lev2

		btst	#3,$BFED01.l		* from keyboard?
		beq.s	_Exit_Lev2

		lea	kb_temp(pc),a1
		move.b	$BFEC01,d0		* get key
		bset	#6,$BFEE01		* start ciaa
		not.w	d0
		ror.b	#1,d0
		bsr.s	GetKeycodes

		lea	$dff006,a1
		moveq	#4-1,d2
key6:		move.b	(a1),d3
key1:		cmp.b	(a1),d3			* wait 4 rasters... before ciaa
		beq.b	key1			* stop.. ack`ing keyboard
		dbf	d2,key6

		bclr	#6,$BFEE01.l		* stop ciaa - acknowlege kb

_Exit_Lev2	move.w	#8,$9C(a6)		* clear irq bit..
Exit_Lev2	movem.l	(sp)+,d0-d7/a0-a6	* restore irq reg`s..

		nop		* NB: these nop`s are here for 040/060
		nop		* cache compatibility! you should do
		rte		* the same for any other hardware irq`s
		nop		* like a Level3 that you setup to make
		nop		* sure your code works on MC680x0!

		
GetKeycodes	lea	Qualifier_Table(pc),a0
		moveq	#7,d7
		moveq	#0,d2
		move.b	(a1),d3			;kb.Qualifiers(a1),d3
check_qual1	move.b	(a0)+,d1
		cmp.b	d0,d1
		bne.s	checkqual2
		bset	d2,d3
		move.b	d3,(a1)			;kb.Qualifiers(a1)
		rts
checkqual2	add.w	#$80,d1
		cmp.b	d0,d1
		bne.s	checkqual4
		bclr	d2,d3
checkqual3	move.b	d3,(a1)			;kb.Qualifiers(a1)
		rts
checkqual4	addq.b	#1,d2
		dbra	d7,check_qual1
		tst.b	d0
		bpl.s	KeyOk
		move.b	d0,d1
		sub.b	#$80,d1
		cmp.b	kb.KeyTMP(a1),d1
		beq.s	KeyOk
		rts
KeyOk		move.b	d0,kb.KeyTMP(a1)
		rts


		cnop	0,4
ReadKeys	lea	kb_temp(pc),a1
		moveq	#0,d0
		move.b	kb.KeyTMP(a1),d0
		cmp.b	kb.LastKeyTMP(a1),d0
		beq.s	Repeat
		move.b	d0,kb.LastKeyTMP(a1)
		sf.b	kb.KeyDelayTMP(a1)
		bra.s	DoKey3
Repeat		tst.b	kb.KeyDelayTMP(a1)
		beq.s	DoKey
		subq.b	#1,kb.KeyDelayTMP(a1)
		bra.s	No_Key
DoKey		tst.b	kb.RepSpeedTMP(a1)
		beq.s	DoKey2
		subq.b	#1,kb.RepSpeedTMP(a1)
		bra.s	No_Key
DoKey2		sf.b	kb.RepSpeedTMP(a1)
DoKey3		tst.b	d0
		bpl.s	DoKey4
No_Key		st.b	d0
DoKey4		move.b	d0,kb.KEY(a1)		* d0.b = keycode..
		move.b	(a1),d1			;kb.Qualifiers(a1),d1	* d1.b = qualifiers..
		rts

kb_temp:	ds.b	kb.sizeof
Qualifier_Table	dc.b	"`abcdefg"

