*******************************************************************************

		incdir	'df0:include/'
		include	'intuition/intuition.i'
		include	'intuition/intuition_lib.i'
		include	'exec/io.i'
		include	'exec/exec_lib.i'
		include	'devices/input.i'
		include	'devices/inputevent.i'
		include	'libraries/dosextens.i'
		include	'libraries/dos_lib.i'

NULL		equ	0

CALLSYS		MACRO
		movea.l	(4).w,a6
		jsr	_LVO\1(a6)
		ENDM

*******************************************************************************
*                                                                             *
* This first hunk, handily based on the ProTracker Source, will run the next  *
* code hunk in the background and release the CLI for other uses.             *
*                                                                             *
*******************************************************************************

		section	RunBackHunk,CODE

rb_HunkStart:	sub.l	a1,a1			; a1 = 0 = find our task
		CALLSYS	FindTask		; Find our task/process
		move.l	d0,a4			; process in a4
		moveq.l	#0,d0			; no WB msg ptr
		tst.l	pr_CLI(a4)		; are we called from CLI?
		bne.s	CalledFromCLI		; yes, do other stuff
		lea	pr_MsgPort(a4),a0	; running from wb, otherwise
		CALLSYS	WaitPort		; wait for the WB msg
		lea	pr_MsgPort(a4),a0	;
		CALLSYS	GetMsg			; get the WB msg
		
CalledFromCLI:	move.l	d0,d7			; d7 = WB msg
		lea	DOSLib,a1		; 'dos.library'
		moveq.l	#0,d0			; and ol' version
		CALLSYS	OpenLibrary		; open it
		tst.l	d0			; did we get it?
		beq.s	QuickExit		; I sure hope so!!
		move.l	d0,_DOSBase		; save dosbase ptr

		CALLSYS	Forbid			; stop multitasking for a sec
		move.l	#ProgName,d1		; ptr to the name of the prog
		moveq.l	#0,d2			; zero out d2
		move.b	LN_PRI(a4),d2		; priority
		lea	rb_HunkStart-4(pc),a0	; get ptr to next hunk
		move.l	(a0),d3			; ptr to next segment
		clr.l	(a0)			; unlink segment
		move.l	#4000,d4		; stack size
		CALLDOS	CreateProc		; spawn the process
		CALLSYS	Permit			; multitasking on

QuickExit:	tst.l	d7			; is there a WB msg?
		beq.b	RBExit			; no, skip this part
		CALLSYS	Forbid			; yes, multitask off
		move.l	d7,a1			; move msg ptr to a1
		CALLSYS	ReplyMsg		; reply to the message
RBExit:		moveq.l	#0,d0			; result code = 0
		rts				; program returns to DOS here
		
*******************************************************************************

		section	Main,CODE
		
MainStart:	bra.w	OpenAll			; open everything we need

main:		move.l	UserPort,a0		; adr of window's msg port
		CALLSYS	WaitPort		; wait for a message
		move.l	d0,a1			; message ptr in d0->a1

		move.l	UserPort,a0		; adr of msg port
		CALLSYS	GetMsg			; retrieve the message
		move.l	d0,a1			; message ptr in d0, a1
		move.l	im_Class(a1),d2		; message class in d2
		move.w	im_Code(a1),d3		; message code in d3
		CALLSYS	ReplyMsg		; send the message back
		
		cmp.l	#CLOSEWINDOW,d2		; was it a CLOSEWINDOW msg?
		bne.b	NotCloseWindow		; no
		st.b	Exit			; yes
NotCloseWindow:
		tst.b	Exit			; are we done?
		beq.b	main			; no, so repeat

		bra.w	CloseAll		; clean up everything
		
*******************************************************************************

InputHandler:	movem.l	d1-d7/a0-a6,-(sp)

		move.l	a0,a1			; save ptr to first event
ih_Start:	cmp.b	#IECLASS_RAWKEY,ie_Class(a0)
		bne.b	NotAKey			; it was not a rawkey event
		move.w	ie_Code(a0),d1		; get the keycode
		cmp.b	#$20,d1			; an l?
		bne.b	NotL			; nope
		move.w	#$12,ie_Code(a0)	; yes, make it an r
		bra.b	Next			; look for next event
		
NotL:		cmp.b	#$12,d1			; got an r?
		bne.b	Next			; no
		move.w	#$20,ie_Code(a0)	; yes, make it an l
		bra.b	Next			; look for next event

NotAKey:	cmp.b	#IECLASS_RAWMOUSE,ie_Class(a0)
		bne.b	Next			; not a mouse event
		neg.w	ie_X(a0)		; reverse mouse x movements
		neg.w	ie_Y(a0)		; reverse mouse y movements

Next:		move.l	(a0),a0			; get ptr to next event
		cmp.l	#NULL,a0		; is there a next event?
		bne.b	ih_Start		; yes, loop again
		move.l	a1,d0			; pass ptr to first event
		movem.l	(sp)+,d1-d7/a0-a6	;   in list to next handler
		rts				; end of interrupt

*******************************************************************************

OpenAll:	lea	IntuitionLib,a1		; 'intuition.library'
		moveq.l	#33,d0			; version 33 or higher
		CALLSYS	OpenLibrary		; try to open it
		tst.l	d0			; did we get it?
		beq.w	Error			; no
		move.l	d0,_IntuitionBase	; yes, keep the ptr

		lea	MyNewWindow,a0		; adr of newwindow struct
		CALLINT	OpenWindow		; try to open it
		tst.l	d0			; did we get it?
		beq.w	Error			; no
		move.l	d0,MyWindow		; yes, keep the ptr
		move.l	d0,a0			; window ptr in a0
		move.l	wd_UserPort(a0),UserPort
						; get address of window msgport
		sub.l	a1,a1			; a1 = 0 = find our task
		CALLSYS	FindTask		; do it
		lea	InputPort,a1		; reply port for input device
		move.l	d0,MP_SIGTASK(a1)	; signal us when msg received
		CALLSYS	AddPort			; add the port to the system
		
		lea	InputDevName,a0		; 'input.device'
		lea	InputIOReq,a1		; IOStdReq structure for it
		move.l	#InputPort,MN_REPLYPORT(a1)
		moveq.l	#0,d0			; unit number (n/a)
		moveq.l	#0,d1			; flags (n/a)
		CALLSYS	OpenDevice		; try to open input.device
		tst.l	d0			; got it?
		beq.b	NoError			; yes, all is well
		moveq.l	#1,d0			; d0 = 1 = device error
		bra.w	Error			; shut down
NoError:
		lea	InputIOReq,a1		; input.device io request
		move.w	#IND_ADDHANDLER,IO_COMMAND(a1)
		move.l	#InputInterrupt,IO_DATA(a1)
		CALLSYS	DoIO			; install my input handler
				
		bra.w	main			; resume with main program

*******************************************************************************

CloseAll:	cmp.l	#1,d0			; an opendevice error?
		beq.b	DeviceError		; yep

		lea	InputIOReq,a1		
		move.w	#IND_REMHANDLER,IO_COMMAND(a1)
		move.l	#InputInterrupt,IO_DATA(a1)
		CALLSYS	DoIO			; remove my input handler
		lea	InputIOReq,a1		
		CALLSYS	CloseDevice		; close the input.device

DeviceError:	lea	InputPort,a1		; ptr to the msgport
		CALLSYS	RemPort			; uninstall it

		tst.l	MyWindow		; is the window open?
		beq.b	ca_2			; no, try the screen
		move.l	MyWindow,a0		; yes, get the ptr
		CALLINT	CloseWindow		; and close it

ca_2:		tst.l	_IntuitionBase		; is the intui library open?
		beq.b	ca_1			; no, exit the program
		move.l	_IntuitionBase,a1	; yes, get the ptr
		CALLSYS	CloseLibrary		; and close it

ca_1:		CALLSYS	Forbid
		lea	MainStart-4(pc),a0	; ptr to start of process code
		move.l	a0,d1			; move to d1
		lsr.l	#2,d1			; BCPL! Acckk!
		CALLDOS	UnLoadSeg		; free memory used by process
		move.l	_DOSBase,a1
		CALLSYS	CloseLibrary		; close dos.library
		CALLSYS	Permit
		rts				; exit the program

*******************************************************************************

Error:		moveq.l	#-1,d0			; repeat 65000+ times
e_Loop:		move.w	#$f00,$dff180		; flash screen red
		dbra	d0,e_Loop		; repeat
		bra.w	CloseAll		; shut ourself down

*******************************************************************************

		section	TheData,DATA

ProgName:	dc.b	'Shikina!',0
IntuitionLib:	dc.b	'intuition.library',0
DOSLib:		dc.b	'dos.library',0
InputDevName:	dc.b	'input.device',0
		even

MyNewWindow:	dc.w	0,22,242,11
		dc.b	2,1
		dc.l	CLOSEWINDOW,WINDOWDRAG+WINDOWCLOSE+WINDOWDEPTH
		dc.l	NULL,NULL,WindowTitle,NULL,NULL
		dc.w	16,9,640,200,WBENCHSCREEN
WindowTitle:	dc.b	'Shikina v1.0',0
		even		

InputInterrupt:	dc.l	NULL,NULL
		dc.b	NT_INTERRUPT,52
		dc.l	InputInterruptName,NULL,InputHandler
InputInterruptName:
		dc.b	'Shikinterrupt',0
		even

*******************************************************************************

		section	TheBSS,BSS

_IntuitionBase:	ds.l	1
_DOSBase:	ds.l	1
MyWindow:	ds.l	1
UserPort:	ds.l	1
InputIOReq:	ds.b	IOSTD_SIZE
InputPort:	ds.b	MP_SIZE
Exit:		ds.b	1
		even

*******************************************************************************

