;
; resspr.s
;
; Handling of the application's private sprite area (MDW)
;
;  1994-1998 Straylight
;

;----- Licensing note -------------------------------------------------------
;
; This file is part of Straylight's Sapphire library.
;
; Sapphire 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.
;
; Sapphire 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 Sapphire.  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

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

		GET	sapphire:alloc
		GET	sapphire:msgs
		GET	sapphire:res
		GET	sapphire:resources
		GET	sapphire:sapphire
		GET	sapphire:string

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- resspr_load ---
;
; On entry:	R0 == pointer to filename
;
; On exit:	May return an error
;
; Use:		Loads a sprite file into memory and allows it to be
;		referenced through resspr_area.  Note that Straylight's
;		Sprinkle module must be loaded if more than one sprite file
;		is to be used for resources.

		EXPORT	resspr_load
resspr_load	ROUT

		STMFD	R13!,{R0-R6,R12,R14}	;Stack some registers
		WSPACE	resspr__wSpace		;Find my workspace

		; --- Find out how big the sprite file is ---

		MOV	R1,R0			;Point to the filename
		MOV	R0,#17			;Find information about file
		SWI	XOS_File		;Get information about it
		BVS	%99resspr_load		;If it failed, go ahead

		; --- Allocate a buffer for it ---

		ADD	R3,R4,#12+3		;Add 12 byte overhead and...
		BIC	R3,R3,#3		;... word align
		MOV	R0,R3			;Get the size
		BL	alloc			;Allocate the memory
		BLCS	alloc_error		;If it failed, get error
		BCS	%99resspr_load		;And go tidy up
		MOV	R6,R0			;Remember the address

		; --- Set up the sprite area and load the file ---

		STR	R3,[R0,#0]		;Store size in first word
		MOV	R0,#16			;Load the file into memory
		ADD	R2,R6,#12		;Point past first word
		MOV	R3,#0			;Load where I want it
		SWI	XOS_File		;Load the file
		BVS	%98resspr_load		;If it failed, tidy up

		; --- Now set up the sprite area ---

		ADD	R14,R6,#12		;Point to sprite block base
		LDMIA	R14,{R0-R2}		;Load those out nicely
		ADD	R1,R1,#8		;Grow the extension words
		ADD	R2,R2,#8		;Allow 8 more bytes here
		LDR	R3,resspr__splk		;Get magic word for SprLink
		LDR	R4,resspr__last		;Find the list terminator
		ADD	R14,R6,#4		;Point to appropriate place
		STMIA	R14,{R0-R4}		;Store all that lot away

		; --- Link this into the list ---

		LDR	R14,resspr__listEnd	;Find the list end
		STR	R6,[R14,#20]		;Store that away nicely
		STR	R6,resspr__listEnd	;This is now the last block

		LDMFD	R13!,{R0-R6,R12,R14}	;Restore all registers
		BICS	PC,R14,#V_flag		;And return to caller

		; --- It couldn't load -- tidy up ---

98resspr_load	MOV	R5,R0			;Keep error pointer safe
		MOV	R0,R6			;Find the heap block
		BL	free			;Free the block now
		MOV	R0,R5			;Restore error pointer

		; --- Something went wrong -- make an error ---

99resspr_load	ADD	R2,R0,#4		;Point to error string
		ADR	R0,resspr__err		;Point to error skeleton
		BL	msgs_error		;Build the error up
		ADD	R13,R13,#4		;Move stack pointer past R0
		LDMFD	R13!,{R1-R6,R12,R14}	;Restore registers
		ORRS	PC,R14,#V_flag		;And return the error

resspr__splk	DCB	"SPLK"			;SprLink's magic number

resspr__err	DCD	1
		DCB	"rsprSLE",0

		LTORG

; --- resspr_area ---
;
; On entry:	--
;
; On exit:	R0 == pointer to application's sprite area
;
; Use:		Locates the application's `Sprites' resource in memory and
;		returns a pointer to it.  If the resource has not been
;		loaded, 1 is returned, to indicate to use the WIMP area.
;		If multiple sprite files have been loaded, this call returns
;		the address of the first: they will have been linked together
;		so that Sprinkle will treat them as one big area.

		EXPORT	resspr_area
resspr_area	ROUT

		STMFD	R13!,{R14}		;Save a register
		LDR	R0,resspr__wSpace	;Find my workspace
		LDR	R14,sapph_workspace	;Find workspace base address
		LDR	R0,[R0,R14]		;Locate sprite area
		LDMFD	R13!,{PC}^		;Return to caller

		LTORG

; --- resspr_init ---
;
; On entry:	R0 == pointer to application name
;
; On exit:	--
;
; Use:		Initalises resspr, loading the Sprites resource.

		EXPORT	resspr_init
resspr_init	ROUT

		STMFD	R13!,{R0,R1,R12,R14}	;Save registers
		WSPACE	resspr__wSpace		;Find my workspace

		; --- Avoid multiple initialisation ---

		LDR	R14,resspr__area	;Get the area pointer
		CMP	R14,#0			;Is it NULL
		LDMNEFD	R13!,{R0,R1,R12,PC}^	;No -- we've already done it

		; --- Fallback position -- use the WIMP area ---

		ADR	R14,resspr__area-20	;Put obscure address in
		STR	R14,resspr__listEnd	;As the list end

		MOV	R14,#1			;Use the WIMP area
		STR	R14,resspr__area	;Save as sprite area pointer

		; --- Set up the shared resource sprites ---

		MOV	R0,#rsType_sprite	;Find the sprite resource
		BL	resources_find		;Try to find the resources
		STRCS	R0,resspr__area		;It will do as a sprite area
		MOVCC	R0,#0			;Otherwise terminate normally
		STR	R0,resspr__last		;Store that as last pointer

		; --- Now initialise res and load the sprites ---

		LDR	R0,[R13,#0]		;Find the application name
		BL	msgs_init		;This will start up res

		ADR	R0,resspr__sprites	;Point to the leafnae
		MOV	R1,R11			;Build name in scratchpad
		BL	res_find		;Translate the name
		BLCS	resspr_load		;If there, load the file
		SWIVS	OS_GenerateError	;If failed, there's no hope

		; --- That's it, then ---

		LDMFD	R13!,{R0,R1,R12,PC}^	;Return to caller

resspr__sprites	DCB	"Sprites",0

		LTORG

resspr__wSpace	DCD	0

;----- Workspace ------------------------------------------------------------

		^	0,R12
resspr__wStart	#	0

resspr__area	#	4			;Pointer to sprite area
resspr__listEnd	#	4			;Last block in the list
resspr__last	#	4			;Pointer to list terminator

resspr__wSize	EQU	{VAR}-resspr__wStart

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	resspr__wSize
		DCD	resspr__wSpace
		DCD	256
		DCD	resspr_init

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

		END
