;
; dynTask.s
;
; The background compacting WIMP task
;
;  1994-1998 Straylight
;
;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Dynamite
;
; Dynamite is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2, or (at your option)
; any later version.
;
; Dynamite is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with Dynamite.  If not, write to the Free Software Foundation,
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.


;----- Standard header ------------------------------------------------------

		GET	libs:header
		GET	libs:swis

		GET	libs:stream

;----- External dependencies ------------------------------------------------

		GET	sh.dynHeap
		GET	sh.wSpace

		GET	sh.messages

		IMPORT	dyn_base

;----- Main code ------------------------------------------------------------

		AREA	|Dynamite$$Code|,CODE,READONLY

; --- dt_service ---
;
; On entry:	R1 == service call number
;		Other registers depend on R1
;
; On exit:	Depends on service call
;
; Use:		Handles service calls for Dynamite

		EXPORT	dt_service
dt_service	ROUT

		; --- Get rid of unwanted services quickly ---

		CMP	R1,#&4A
		CMPNE	R1,#&27
		CMPNE	R1,#&49
		MOVNES	PC,R14

		; --- Now dispatch wanted services ---

		LDR	R12,[R12,#0]		;Get my workspace pointer
		STMFD	R13!,{R14}		;Save some useful registers

		CMP	R1,#&27			;Service_Reset...
		BEQ	%20dt_service

		CMP	R1,#&4A			;Service_StartedWimp
		BEQ	%10dt_service

		; --- Service_StartWimp ---

		LDR	R14,dyn_taskHandle	;Get my task handle
		CMP	R14,#0			;Am I already running?
		MOVEQ	R14,#-1			;I'm trying to start up
		STREQ	R14,dyn_taskHandle	;Store as my task handle
		ADREQL	R0,dt__commands		;Point to the command string
		MOVEQ	R1,#0			;Claim the service call
		LDMFD	R13!,{PC}^		;Return to RISC OS

		; --- Service_StartedWimp ---

10dt_service	LDR	R14,dyn_taskHandle	;Get my task handle
		CMP	R14,#-1			;Am I already running?
		MOVEQ	R14,#0			;No -- blank out task handle
		STREQ	R14,dyn_taskHandle	;Store it over the old one
		LDMFD	R13!,{PC}^		;Return happily

		; --- Service_Reset ---

20dt_service	MOV	R14,#0			;Blank out my task handle
		STR	R14,dyn_taskHandle	;Store it over the old one
		LDMFD	R13!,{PC}^		;Return to RISC OS now

		LTORG

; --- dt__startTask ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Starts up the Dynamite application from a *Command.

dt__startTask	ROUT

		LDR	R12,[R12]		;Load my workspace address
		LDR	R0,dyn_taskHandle	;Get my task handle variable
		CMP	R0,#-1			;Am I waiting to start?
		ADRNEL	R0,msg_errDesk		;No -- moan at stupid user
		ORRNES	PC,R14,#V_flag		;And return the error
		MOV	R0,#1			;We're launching the app
		STR	R0,dyn_launch		;So set the launch flag
		STMFD	R13!,{R14}		;Save a register nicely
		MOV	R0,#2			;Start my module up
		ADR	R1,dt__myName		;Point to the module name
		SWI	XOS_Module		;Start up the task proper
		LDMFD	R13!,{PC}		;And return to caller

dt__myName	DCB	"Dynamite",0

		LTORG

; --- dt_quit ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Closes down Dynamite's WIMP task (used for background
;		compaction of the heap).

		EXPORT	dt_quit
dt_quit		ROUT

		STMFD	R13!,{R0,R1,R14}	;Save some registers
		LDR	R0,dyn_taskHandle	;Find my task handle
		LDR	R1,=&4B534154		;The magic number thing
		SWI	XWimp_CloseDown		;Close down the application
		MOV	R14,#0			;Now we don't have a task
		STR	R14,dyn_taskHandle	;So zap my task handle
		LDMFD	R13!,{R0,R1,PC}^	;And return to caller

		LTORG

; --- dt_run ---
;
; On entry:	R12 == address of module private word
;
; On exit:	Via OS_Exit
;
; Use:		Runs the Dynamite WIMP task.

		EXPORT	dt_run
dt_run		ROUT

		LDR	R12,[R12]		;Find my workspace address
		ADR	R13,dyn_pollBlk+256	;Make a microstack

		; --- Is it worth doing anything? ---

		MOV	R0,#0			;How many Wimp tasks?
		SWI	Wimp_ReadSysInfo	;Read the number back
		CMP	R0,#0			;Are there any running?
		SWIEQ	OS_Exit			;Nope: then don't bother

		; --- Handle the ultra-weird launch sequence ---

		LDR	R14,dyn_launch		;Load the launch flag
		CMP	R14,#0			;Are we launching?
		BEQ	%50dt_run		;No -- launch then

		; --- Start up the WIMP thing ---

		MOV	R0,#200			;Make it run under RISC OS 2
		LDR	R1,=&4B534154		;Get the magic number thing
		ADR	R2,dt__taskName		;Point to the task name
		SWI	Wimp_Initialise		;Start up the WindowManager
		STR	R1,dyn_taskHandle	;Save the task handle

		; --- Remove my name from the Switcher's list ---

		ADR	R1,dyn_pollBlk		;Point to the poll block
		MOV	R0,#20			;Minimum message size
		STR	R0,[R1,#0]		;Save in position 0
		MOV	R2,#0			;This is not a reply
		MOV	R3,#&40000		;The TaskCloseDown message
		ORR	R3,R3,#&000C3		;It comes in two episodes
		ADD	R0,R1,#12		;Point to bit of message blk
		STMIA	R0,{R2,R3}		;Build the message in there
		MOV	R0,#17			;Don't get a reply
		MOV	R2,#0			;Give everyone a shot at it
		SWI	XWimp_SendMessage	;Send it the message

		; --- Now do the main loop ---

00dt_run	LDR	R14,dyn_hpFlags		;Load the heap's flags
		TST	R14,#hpFlag_tidy	;Is the heap tidy?
		LDREQ	R14,dyn_lockCount	;No -- then load lock count
		CMPEQ	R14,#0			;Is the heap locked?
		MOVNE	R0,#1			;Tidy or locked, so be nice
		MOVEQ	R0,#0			;Otherwise use idles
		ADR	R1,dyn_pollBlk		;Point to my pollblock
		ADD	R13,R1,#256		;Make a bogus stack
		SWI	Wimp_Poll		;Do the poll thing
		CMP	R0,#0			;Is it an idle event?
		SWIEQ	Dynamite_Reduce		;Yes -- then reduce the heap
		CMP	R0,#17			;Is it a message
		CMPNE	R0,#18			;Of either type
		LDREQ	R0,[R1,#16]		;Get the message type
		CMPEQ	R0,#0			;Is it a Message_Quit
		LDRNE	R14,dyn_hpFlags		;No -- load the flags
		BICNE	R14,R14,#hpFlag_mSent	;...clear the message sent
		STRNE	R14,dyn_hpFlags		;...save the flags back
		BNE	%00dt_run		;...loop round again

		; --- I've been told to quit ---
		;
		; Seeing as I've viciously and nastily removed myself from
		; the TaskManager's task table, I know this must have been
		; a broadcast quit, so I hari-kiri with wanton abandon.

		SWI	Wimp_CloseDown		;Close down the task
		MOV	R0,#0			;No task handle any more
		STR	R0,dyn_taskHandle	;So zero it then
		SWI	OS_Exit			;Farewell, cruel world

dt__taskName	DCB	"DynamiteCompactor",0

		; --- Launch the Compactor task ---

50dt_run	MOV	R0,#200			;Make it run under RISC OS 2
		LDR	R1,=&4B534154		;Get the magic number thing
		ADR	R2,dt__launchName	;Point to the task name
		SWI	Wimp_Initialise		;Start up the WindowManager

		MOV	R0,#-1			;Fake a startup sequence
		STR	R0,dyn_taskHandle	;Save this as my task handle
		LDR	R0,=dt__commands	;Point to my main command
		BL	dyn_base		;Find the module base
		ADD	R0,R14,R0		;Relocate the address
		SWI	Wimp_StartTask		;Start it up nicely

		SWI	Wimp_CloseDown		;Tell WIMP to get knotted
		SWI	OS_Exit			;And kill self evilly

dt__launchName	DCB	"DynamiteLauncher",0

		LTORG

; --- dt_message ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Sends a silly message to the Compactor task so that it gets
;		control again if it disabled idle events.

		EXPORT	dt_message
dt_message	ROUT

		STMFD	R13!,{R0-R3,R14}	;Save some registers
		LDR	R14,dyn_taskHandle	;Load my task handle
		CMP	R14,#0			;Is it vaguely sensible?
		LDMLEFD	R13!,{R0-R3,PC}^	;No -- don't bother then
		LDR	R14,dyn_hpFlags		;Load the flags
		TST	R14,#hpFlag_mSent	;Has a message been sent?
		LDMNEFD	R13!,{R0-R3,PC}^	;Yes -- then return
		ORR	R14,R14,#hpFlag_mSent	;Set the flag
		STR	R14,dyn_hpFlags		;And save the flags back
		ADR	R1,dyn_pollBlk		;Point to the poll block
		MOV	R0,#20			;Minimum message size
		STR	R0,[R1,#0]		;Save in position 0
		MOV	R2,#0			;This is not a reply
		MOV	R3,#&4A000		;A bogus message number
		ORR	R3,R3,#&003C0		;(My SWI chunk base)
		ADD	R0,R1,#12		;Point to bit of message blk
		STMIA	R0,{R2,R3}		;Build the message in there
		MOV	R0,#17			;Don't get a reply
		MOV	R2,R14			;Get my task handle
		SWI	XWimp_SendMessage	;Send it the message
		LDMFD	R13!,{R0-R3,PC}^	;And return to caller

		LTORG

		; --- *Commands ---

		AREA	|Dynamite$$Commands|,CODE,READONLY

dt__commands	DCB	"Desktop_DynamiteCompactor",0
		DCD	dt__startTask
		DCD	0
		DCD	synt_compactor
		DCD	help_compactor

;----- That's all, folks ----------------------------------------------------

		END
