;
; xfer.load.s
;
; Loading and importing of files (MDW)
;
;  1994 Straylight
;

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

		GET	libs:swis
		GET	libs:header

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

		GET	sapphire:alloc
		GET	sapphire:event
		GET	sapphire:fastMove
		GET	sapphire:flex
		GET	sapphire:msgs
		GET	sapphire:sapphire
		GET	sapphire:string
		GET	sapphire:wimp
		GET	sapphire:win

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

		AREA	|Sapphire$$Code|,CODE,READONLY

; --- load ---
;
; On entry:	R0 == pointer to entry point block
;		R1 == value of R10 to pass to entry points
;		R2 == value of R12 to pass to entry points
;
; On exit:	--
;
; Use:		Attempts to load a file after receipt of a Message_DataSave,
;		Message_DataLoad or Message_DataOpen.  If user entries for
;		RAM transfer are provided, this is attempted, although the
;		entries must also be aware that file transfer may be
;		required.

		EXPORT	load
load		ROUT

		STMFD	R13!,{R0-R6,R10,R12,R14} ;Save a load of registers
		WSPACE	load__wSpace		;Locate my workspace address

		; --- Save the handler information ---

		ADR	R14,load__entries	;Point to my entry info
		STMIA	R14,{R0-R2}		;And save the handler info

		; --- Read the current message ---

		BL	event_last		;Read the actual last event
		CMP	R0,#17			;Is it a normal message?
		CMPNE	R0,#18			;Or a bouncy one?
		BNE	%90load			;Neither -- ignore it then

		LDR	R0,[R1,#16]		;Load the message action
		CMP	R0,#1			;Is it a Message_DataSave?
		BEQ	%20load			;Yes -- handle it then
		CMP	R0,#3			;Is it a Message_DataLoad?
		BEQ	%50load			;Yes -- deal with that
		CMP	R0,#5			;Is it a Message_DataOpen?
		BEQ	%60load			;Yes -- deal with that too
		B	%90load			;Otherwise ignore it

		; --- Deal with a Message_DataSave ---
                ;
		; First, set up all the data in my workspace.

20load		MOV	R6,R1			;Keep the message pointer
		ADR	R0,load__message	;Point to my message buffer
		LDR	R2,[R6,#0]		;Get the message block size
		BL	fastMove		;Copy it over nicely

		; --- Find out if he can do RAM transfer ---

		LDR	R5,load__entries	;Find his handler block
		LDR	R14,[R5,#lEntry__initBuf] ;Point to his initBuf entry
		CMP	R14,#0			;Is it defined?
		BEQ	%40load			;No -- just do scrap xfer

		; --- Set up for RAM transfer ---

		ADR	R0,load__name		;Point to the leafname
		LDR	R1,[R6,#36]		;Load the estimated size
		MOV	R2,#0			;Pass a zero buffer handle
		ADR	R14,load__R10		;Point to his R10/R12 values
		LDMIA	R14,{R10,R12}		;Load them out ready
		ADDS	R0,R0,#0		;Clear lots of flags
		MOV	R14,PC			;Set up a return address
		ADD	PC,R5,#lEntry__initBuf	;Make him give me a buffer
		WSPACE	load__wSpace		;Get my workspace back again
		STR	R10,load__R10		;Save his returned R10 value
		BLVS	load__finish		;If it failed, tidy it up
		BVS	%90load			;And return right now
		ADR	R14,load__buffStart	;Point to the buffer info
		STMIA	R14,{R0-R2}		;And save the buffer stuff
		MOV	R14,#0			;We've not read any data yet
		STR	R14,load__totalSize	;So zero the total size

		; --- Build the Message_RAMFetch ---

		MOV	R14,#28			;Size of a RAMFetch message
		STR	R14,[R11,#0]		;Store it in the scratchpad
		ADD	R14,R11,#12		;Point to your_ref word
		MOV	R2,R0			;Point to the buffer start
		MOV	R3,R1			;And get the buffer size
		LDR	R0,[R6,#8]		;Load his reference number
		MOV	R1,#6			;The RAMFetch message code
		STMIA	R14,{R0-R3}		;Save all that lot away
		MOV	R0,#18			;Make it bounce if ignored
		MOV	R1,R11			;Point to my message block
		LDR	R2,[R6,#4]		;Load his task handle
		SWI	Wimp_SendMessage	;And send along his message

		; --- Set everything up for the acknowledgement ---

		MOV	R14,#lState__test	;We're seeing if he'll cope
		STR	R14,load__state		;So save this state info

		ADR	R0,load__unknown	;Point to my unknown handler
		MOV	R1,#0			;Nothing interesting in R4
		MOV	R2,#0			;Nothing interesting in R10
		MOV	R3,R12			;Pass workspace in R12
		BL	win_unknownHandler	;Register my unknown handler
		B	%90load			;And finish everything off

		; --- Set up scrap transfer ---

40load		BL	load__doScrap		;Start scrap transfer going
		B	%90load			;And finish everything off

		; --- Handle a Message_DataLoad ---
		;
		; If this is *not* a reply to a Message_DataSaveAck then we
		; should clear all the associated data from out message
		; cache.

50load		LDR	R14,[R1,#12]		;Load message's your_ref
		CMP	R14,#0			;Is this a new message?
		BNE	%70load			;No -- don't do setting up

		; --- Handle a new Message_DataLoad or Message_DataOpen ---
		;
		; First, copy all the message data over

60load		ADR	R0,load__message	;Point to my message buffer
		LDR	R2,[R1,#0]		;Get the message block size
		BL	fastMove		;Copy it over nicely

		; --- Remember we're doing file transfer ---

		MOV	R14,#lState__file	;This is file transfer
		STR	R14,load__state		;Save this state value

		; --- Send an immediate acknowledgement ---
		;
		; For a Message_DataOpen, this is very important -- if we
		; don't, and the application dies, we then get started all
		; over again from the command line, and probably die again
		; if it's a duff file.  For a Message_DataLoad it doesn't
		; matter too much, although I suspect we should really send
		; the acknowledgement after we loaded the file.

70load		MOV	R6,R1			;Keep the message pointer
		ADD	R0,R11,#20		;Copy to the scratchpad
		ADD	R1,R6,#20		;Point to the message data
		LDR	R2,[R6,#0]		;Get the message block size
		SUB	R2,R2,#20		;Subtract the bit not copied
		BL	fastMove		;Copy it over nicely

		LDR	R14,[R6,#0]		;Load the message size word
		STR	R14,[R11,#0]		;Save it in my dummy message
		LDR	R0,[R6,#8]		;Load his my_ref field
		MOV	R1,#4			;This is Message_DataLoadAck
		ADD	R14,R11,#12		;Point to the your_ref field
		STMIA	R14,{R0,R1}		;Save them in there

		MOV	R0,#17			;Don't want acknowledgement
		MOV	R1,R11			;Point to the message block
		LDR	R2,[R6,#4]		;Get his task handle ready
		SWI	Wimp_SendMessage	;And acknowledge his message

		; --- Tell the client to load the file ---

		ADR	R0,load__name		;Point to apparent filename
		ADD	R1,R6,#44		;Point to filename to load
		LDR	R2,load__state		;Load state (safeness flag)
		ADR	R14,load__entries	;Point to the entry data
		LDMIA	R14,{R5,R10,R12}	;Load the important stuff
		ADDS	R0,R0,#0		;Clear C and V flags
		MOV	R14,PC			;Set up his return address
		ADD	PC,R5,#lEntry__file	;Tell him to load the file
		WSPACE	load__wSpace		;Find my workspace again
		STR	R10,load__R10		;Save the new R10 value
		BL	load__finish		;Send a completed message

		; --- Now delete the Wimp$Scrap file if we need to ---

		CMP	R2,#0			;Is the file `safe'?
		BNE	%90load			;Yes -- then do nothing
		MOV	R0,#27			;Wipe files please
		ADD	R1,R6,#44		;Point to the filename
		MOV	R3,#&3			;No confirm, recurse
		SWI	XOS_FSControl		;Do the Wipe job

		; --- We finished at last! ---

90load		LDMFD	R13!,{R0-R6,R10,R12,PC}^ ;Return to caller

		LTORG

; --- load__doScrap ---
;
; On entry:	--
;
; On exit:	--
;
; Use:		Sets everything up for Wimp$Scrap-type data transfer.

load__doScrap	ROUT

		STMFD	R13!,{R0-R4,R14}	;Save some registers

		; --- First, ensure the variable <Wimp$Scrap> exists ---

		ADR	R0,load__wimpScrap	;Point to my variable name
		MOV	R1,R11			;Point to a convenient buffer
		MOV	R2,#256			;Get the buffer size
		MOV	R3,#0			;This is the first call
		MOV	R4,#0			;Don't expand or anything
		SWI	XOS_ReadVarVal		;Read the variable value
		BLVS	load__finish		;If it failed, abort now
		BVS	%90load__doScrap	;And return to caller

		; --- Build the message and send it ---

		ADD	R0,R11,#20		;Point at scratch msg data
		ADR	R1,load__message+20	;And the saved bits of data
		MOV	R2,#24			;All up to the filename
		BL	fastMove		;Copy all that lot over

		MOV	R14,#60			;The size of this message
		STR	R14,[R11,#0]		;Store it in the right place
		LDR	R0,load__message+8	;Load the message's my_ref
		MOV	R1,#2			;This is Message_DataSaveAck
		ADD	R14,R11,#12		;Point to your_ref
		STMIA	R14,{R0,R1}		;Save your_ref and action

		ADD	R0,R11,#44		;Point to the filename area
		ADR	R1,load__scrapVar	;Point to the variable name
		BL	str_cpy			;Copy the string over

		MOV	R14,#-1			;Say that the data's not safe
		STR	R14,[R11,#36]		;Save -1 as estimated size
		MOV	R0,#17			;This should be send normal
		MOV	R1,R11			;Point at my message
		LDR	R2,load__message+4	;Load his task handle
		SWI	Wimp_SendMessage	;Send the message back

		; --- Now remember we're doing scrap transfer ---

		MOV	R14,#lState__scrap	;Get the right state number
		STR	R14,load__state		;And save it away nicely

		; --- That's it -- we're done ---

90load__doScrap	LDMFD	R13!,{R0-R4,PC}^	;Return to caller

load__wimpScrap	DCB	"Wimp$Scrap",0
load__scrapVar	DCB	"<Wimp$Scrap>",0

		LTORG

; --- load__unknown ---
;
; On entry:	R0 == an event code
;		R1 == pointer to event data
;
; On exit:	CS if we handled the event, CC otherwise
;
; Use:		Handles unknown events (i.e. user messages) during a RAM
;		transfer.

load__unknown	ROUT

		CMP	R0,#17			;Is it a user message?
		CMPNE	R0,#18			;Or a bouncy user message?
		BEQ	%00load__unknown	;Yes -- handle it then
		CMP	R0,#19			;Is it a bounced message?
		BEQ	%60load__unknown	;Yes -- deal with that
		MOVS	PC,R14			;Nothing we could do about it

		; --- Deal with a message ---

00load__unknown	STMFD	R13!,{R14}		;Save a register
		LDR	R14,[R1,#16]		;Load the message code
		CMP	R14,#7			;Is it a Message_RAMTransmit?
		LDMNEFD	R13!,{PC}^		;No -- ignore it then

		; --- Data transfer is go ---

		STMFD	R13!,{R0-R6,R10}	;Save loads of registers
		MOV	R6,R1			;Look after the message ptr
		MOV	R14,#lState__ram	;We're doing RAM transfer now
		STR	R14,load__state		;So save this state away

		; --- Have we finished data transfer yet? ---

		ADR	R14,load__buffStart	;Point to the buffer info
		LDMIA	R14,{R0-R2}		;Load all the buffer stuff
		LDR	R3,[R6,#24]		;How much has he sent?
		LDR	R4,load__totalSize	;Load the total so far
		ADD	R4,R4,R3		;Add on this new size
		STR	R4,load__totalSize	;And save back the new total
		CMP	R1,R3			;Has he sent enough data?
		BNE	%30load__unknown	;No -- then it's all over

		; --- Get some more buffer space ---

		ADR	R14,load__entries	;Point at his entry info
		LDMIA	R14,{R5,R10,R12}	;Load all his info out
		ADDS	R0,R0,#0		;Clear C and V flags
		MOV	R14,PC			;Set up the return address
		ADD	PC,R5,#lEntry__extend	;Extend your buffer please
		WSPACE	load__wSpace		;Find my workspace again
		BVS	%40load__unknown	;If it failed, kill buffer
		ADR	R14,load__buffStart	;Point to the buffer info
		STMIA	R14,{R0-R2}		;Save the buffer info again

		; --- Send another RAMFetch along ---

		MOV	R14,#28			;Size of a RAMFetch message
		STR	R14,[R11,#0]		;Store it in the scratchpad
		ADD	R14,R11,#12		;Point to your_ref word
		MOV	R2,R0			;Point to the buffer start
		MOV	R3,R1			;And get the buffer size
		LDR	R0,[R6,#8]		;Load his reference number
		MOV	R1,#6			;The RAMFetch message code
		STMIA	R14,{R0-R3}		;Save all that lot away
		MOV	R0,#18			;Make it bounce if ignored
		MOV	R1,R11			;Point to my message block
		LDR	R2,[R6,#4]		;Load his task handle
		SWI	Wimp_SendMessage	;And send along his message
		B	%50load__unknown	;Finish off everything

		; --- Tell the client to wrap things up ---

30load__unknown	ADR	R0,load__name		;Point to the `filename'
		MOV	R1,R4			;Get the total data size
		ADR	R14,load__entries	;Point at his entry info
		LDMIA	R14,{R5,R10,R12}	;Load all his info out
		ADDS	R0,R0,#0		;Clear C and V flags
		MOV	R14,PC			;Set up the return address
		ADD	PC,R5,#lEntry__doneBuf	;Tidy up your buffer please
		WSPACE	load__wSpace		;Find my workspace again
		BVS	%40load__unknown	;If it failed, tidy up
		BL	load__finish		;It's all over now

		; --- Unattach this unknown handler ---

		ADR	R0,load__unknown	;Point to my unknown handler
		MOV	R1,#0			;Nothing interesting in R4
		MOV	R2,#0			;Nothing interesting in R10
		MOV	R3,R12			;Pass workspace in R12
		BL	win_removeUnknownHandler ;Unattach the handler
		B	%50load__unknown	;And return nicely

		; --- Tidy up after buffer extension failed ---

40load__unknown	MOV	R4,R0			;Look after the error pointer
		ADR	R14,load__buffStart	;Point to the buffer info
		LDMIA	R14,{R0-R2}		;Load it all out
		LDR	R12,load__R12		;Find the client's R12
		MOV	R14,PC			;Set up a return address
		ADD	PC,R5,#lEntry__killBuf	;Destroy the buffer
		WSPACE	load__wSpace		;Find my workspace again
		MOV	R14,#V_flag		;Get the V bit position
		TEQVCP	R14,PC			;If clear, set it again
		MOV	R0,R4			;Point at the error again
		BL	load__finish		;Report the error

		; --- We don't need the unknown handler any more ---

		ADR	R0,load__unknown	;Point to my unknown handler
		MOV	R1,#0			;Nothing interesting in R4
		MOV	R2,#0			;Nothing interesting in R10
		MOV	R3,R12			;Pass workspace in R12
		BL	win_removeUnknownHandler ;Unattach the handler

		; --- Return to caller ---

50load__unknown	LDMFD	R13!,{R0-R6,R10,R14}	;Unstack all the registers
		ORRS	PC,R14,#C_flag		;And claim the event

		; --- Handle a bounced message ---

60load__unknown	STMFD	R13!,{R14}		;Save a register
		LDR	R14,[R1,#16]		;Load the message action
		CMP	R14,#6			;Is it one of my RAMFetches?
		LDMNEFD	R13!,{PC}^		;No -- ignore it then

		; --- My RAMFetch bounced! ---

		LDR	R14,load__state		;Get my current state?
		CMP	R14,#lState__test	;Was I just testing the water
		BLEQ	load__doScrap		;Yes -- set up for scrap xfer

		; --- Shut down the data transfer ---

		STMFD	R13!,{R0-R3,R10}	;Save some more registers
		ADR	R14,load__buffStart	;Point to the buffer info
		LDMIA	R14,{R0-R2}		;Load it all out
		ADR	R14,load__entries	;Point to entry information
		LDMIA	R14,{R3,R10,R12}	;Load all the stuff out
		MOV	R14,PC			;Set up a return address
		ADD	PC,R3,#lEntry__killBuf	;Destroy the buffer
		WSPACE	load__wSpace		;Find my workspace again
		MOV	R14,#V_flag		;Get the V bit position
		TEQVCP	R14,PC			;If clear, set it again
		MOV	R0,#0			;Don't report any errors
		BL	load__finish		;Report the error

		; --- We don't need the unknown handler any more ---

		ADR	R0,load__unknown	;Point to my unknown handler
		MOV	R1,#0			;Nothing interesting in R4
		MOV	R2,#0			;Nothing interesting in R10
		MOV	R3,R12			;Pass workspace in R12
		BL	win_removeUnknownHandler ;Unattach the handler

		LDMFD	R13!,{R0-R3,R10,R14}	;Unstack all the registers
		ORRS	PC,R14,#C_flag		;And return with C set

		LTORG

; --- load__finish ---
;
; On entry:	VS and R0 points to error, or VC
;
; On exit:	R10 corrupted
;
; Use:		Calls the appropriate client routine for finishing off
;		a load operation.

load__finish	ROUT

		STMFD	R13!,{R0-R2,R12,R14}	;Save some registers
		MOVVS	R1,#1			;If error, set button count
		ADRVC	R0,load__name		;Point to apparent name
		LDRVC	R1,load__state		;And load my state
		AND	R1,R1,#1		;Leave only safeness flag
		ADR	R14,load__entries	;Point to the entry points
		LDMIA	R14,{R2,R10,R12}	;Load the entry info
		ADDVS	R2,R2,#4		;If error, call fail entry
		MOV	R14,PC			;Set up the return address
		ADD	PC,R2,#lEntry__done	;Call the correct entry pt
		LDMFD	R13!,{R0-R2,R12,PC}^	;Return to caller

		LTORG

; --- load_initBuf ---
;
; On entry:	R1 == estimated file size
;		R2 == pointer to flex anchor (unallocated)
;
; On exit:	R0 == pointer to buffer start
;		R1 == buffer size
;		May return an error
;
; Use:		Initialises a flex block for use as a RAM transfer buffer.
;		This routine is suitable for use as the initBuf routine for
;		RAM transfer loading.

		EXPORT	load_initBuf
load_initBuf	ROUT

		STMFD	R13!,{R14}		;Save some registers
		MOV	R0,R2			;Point to caller's anchor
		BL	flex_alloc		;Try to allocate the buffer
		MOVCS	R1,#4096		;Otherwise assume 4K size
		BLCS	flex_alloc		;And try again...
		BLCS	alloc_error		;If it failed, get an error
		LDRCC	R0,[R0,#0]		;Otherwise load buffer start
		LDMFD	R13!,{R14}		;Restore the link register
		BICCCS	PC,R14,#V_flag		;If no error, clear V on exit
		ORRCSS	PC,R14,#V_flag		;Otherwise set it

		LTORG

; --- load_killBuf ---
;
; On entry:	R2 == pointer to flex anchor
;
; On exit:	--
;
; Use:		Frees a flex block.  This routine should be used to free
;		the buffer used for RAM transfer.

		EXPORT	load_killBuf
load_killBuf	ROUT

		STMFD	R13!,{R0,R14}		;Save some registers
		MOV	R0,R2			;Point to the flex anchor
		BL	flex_free		;Free the block
		MOV	R14,#0			;Get a zero word
		STR	R14,[R2,#0]		;Write this over the anchor
		LDMFD	R13!,{R0,PC}^		;Return to caller

		LTORG

; --- load_extendBuf ---
;
; On entry:	R0 == pointer to previous buffer
;		R1 == size of previous buffer
;		R2 == pointer to flex anchor
;
; On exit:	R0 == pointer to a new buffer
;		R1 == size of the new buffer
;		May return an error
;
; Use:		Extends the flex block if it was initially too small.
;		This routine is designed to be used as the extend routine
;		during RAM transfer.

		EXPORT	load_extendBuf
load_extendBuf	ROUT

		STMFD	R13!,{R3,R14}		;Save some registers
		MOV	R0,R2			;Point to the flex anchor
		BL	flex_size		;Read the block's size
		MOV	R3,R0			;Look after the size
		MOV	R0,R2			;Point to the flex anchor
		ADD	R1,R3,#&1000		;Extend buffer by 4K
		BL	flex_extend		;Make more space for loading
		BLCS	alloc_error		;If it failed, get an error
		LDRCC	R0,[R2,#0]		;Otherwise load the anchor
		ADDCC	R0,R0,R3		;And add the old size
		MOVCC	R1,#&1000		;Get the buffer size
		LDMFD	R13!,{R3,R14}		;Restore the registers
		BICCCS	PC,R14,#V_flag		;If no error, clear V on exit
		ORRCSS	PC,R14,#V_flag		;Otherwise set it

		LTORG

; --- load_doneBuf ---
;
; On entry:	R1 == actual size of data
;		R2 == pointer to flex anchor
;
; On exit:	--
;
; Use:		Sets the block into which the data has been loaded to the
;		correct exact size.

		EXPORT	load_doneBuf
load_doneBuf	ROUT

		STMFD	R13!,{R0,R14}		;Save some registers
		MOV	R0,R2			;Point to the anchor
		BL	flex_extend		;Set the block's correct size
		LDMFD	R13!,{R0,PC}^		;Return to caller

		LTORG

; --- load_file ---
;
; On entry:	R1 == pointer to filename to load
;		R2 == pointer to flex anchor
;
; On exit:	R0 == size of file loaded
;		May return an error
;
; Use:		Loads a named file into a flex block for your delectation.

		EXPORT	load_file
load_file	ROUT

		STMFD	R13!,{R0-R6,R14}	;Save some registers
		MOV	R6,R2			;Keep the flex anchor safe

		; --- Find the file information ---

		MOV	R0,#17			;Read file information
		SWI	XOS_File		;Find the file's size
		BVS	%90load_file		;If it failed, handle error
		TST	R0,#1			;Is the object a file?
		BEQ	%80load_file		;No -- get an error for it
		STR	R4,[R13,#0]		;Save the file size in R0

		; --- Allocate the flex block ---

		MOV	R1,R4			;Get the object size in R1
		MOV	R0,R6			;Point to caller's anchor
		BL	flex_alloc		;Try to allocate the block
		BLCS	alloc_error		;No memory -- get the message
		BCS	%90load_file		;If it failed, handle error

		; --- Load file into the flex block ---

		MOV	R0,#16			;Load the file
		LDR	R1,[R13,#4]		;Load the filename address
		LDR	R2,[R6,#0]		;Load the flex anchor
		MOV	R3,#0			;Load into my buffer please
		SWI	XOS_File		;Try to do the load op
		BVS	%85load_file		;If it failed, tidy up
		LDMFD	R13!,{R0-R6,R14}	;Unstack registers
		BICS	PC,R14,#V_flag		;And return with no error

		; --- We found a bad object type ---

80load_file	MOV	R2,R0			;Get object type in R2
		MOV	R0,#19			;Get the error message
		SWI	XOS_File		;Return pointer in R0
		B	%90load_file		;Handle error in usual way

		; --- Tidy up after various errors ---

85load_file	MOV	R1,R0			;Look after the error pointer
		MOV	R0,R6			;Point to the flex anchor
		BL	flex_free		;Free up all tht memory
		MOV	R14,#0			;Get a zero word
		STR	R14,[R6,#0]		;And zero out the anchor
		MOV	R0,R1			;Restore the error pointer

90load_file	ADD	R13,R13,#4		;Don't restore R0 on exit
		LDMFD	R13!,{R1-R6,R14}	;Unstack registers
		ORRS	PC,R14,#V_flag		;And return with the error

		LTORG

load__wSpace	DCD	0

;----- User entry points ----------------------------------------------------

		^	0

lEntry__initBuf	#	4			;Create a load buffer
						;On entry:
						;  R0 == ptr to `filename'
						;  R1 == estimated file size
						;  R2 == 0
						;On exit:
						;  R0 == ptr to buffer start
						;  R1 == ptr to buffer end
						;  R2 == buffer `handle'
						;  R10 may be updated

lEntry__killBuf	#	4			;Destroy the load buffer
						;On entry:
						;  R0 == ptr to buffer start
						;  R1 == ptr to buffer end
						;  R2 == buffer `handle'
						;On exit:
						;  --

lEntry__extend	#	4			;Extend the load buffer
						;On entry:
						;  R0 == ptr to buffer start
						;  R1 == ptr to buffer end
						;  R2 == buffer `handle'
						;On exit:
						;  R0-R2 updated

lEntry__doneBuf	#	4			;All data is now loaded
						;On entry:
						;  R0 == ptr to `filename'
						;  R1 == total size of data
						;  R2 == buffer `handle'
						;On exit:
						;  --

lEntry__file	#	4			;Load data from a file
						;On entry:
						;  R0 == ptr to `filename'
						;  R1 == file to load
						;  R2 == 0 if file unsafe
						;On exit:
						;  R10 may be updated

lEntry__done	#	4			;Completed loading
						;On entry:
						;  R0 == ptr to `filename'
						;  R1 == safeness indicator
						;On exit:
						;  --

lEntry__failed	#	4			;Failed to load file
						;On entry:
						;  R0 == pointer to error
						;  R1 == 1
						;On exit:
						;  --

; --- Explanation ---
;
; Loading is several orders of magnitude harder than saving, at a guess.
; I've tried to make it fairly straightforward here -- there are a few
; standard routines provided for simple things like loading into a flex
; block, and a coroutine-based system for unified RAM/file transfer is
; available.
;
; Like saving, loading is based around a table of branch instructions which
; perform application-specific actions during the load operation.  All the
; message passing protocol is hidden away, and all you have to do is write
; the entries for the table.
;
; If you want to support RAM-transfer, you must provide three buffer
; handling routines:
;
; * initBuf is called when load is attempting to start a RAM transfer with
;   the saving application.  It should create a buffer of appropriate size
;   (possibly based on the estimated file size already given).  You can
;   declare a buffer handle at this point, which is passed to all other
;   routines that need to deal with the buffer.  It may return an error.
;
;   If you can't handle RAM transfer, you should replace the branch
;   instruction here with a null word.
;
; * extend is called if the previous buffer was filled and there is more
;   data to come.  The address of the previous buffer is returned to you,
;   so either you can process it there and then, or extend the buffer in
;   some way.  You just have to return a new area of memory to fill with
;   data.  It may return an error.
;
; * doneBuf is called when all the data has been loaded, so that the buffer
;   can be set to the exact right size.
;
; * killBuf is called if the attempt to load via RAM transfer failed and
;   the buffer has to be destroyed.  It is always called whenever there is
;   a fault during RAM transfer, even if one of your other entry points
;   raised the error.
;
; * file is called if you have to load a file from the filing system, either
;   because RAM transfer failed or because you received a direct load from
;   the Filer.  It may return an error.
;
; * done is called when the data transfer is successfully completed.
;
; * failed is called when the data transfer fails due to an error.

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

		^	0,R12
load__wStart	#	0

load__state	#	4			;The current state (1 byte)

load__entries	#	4			;Pointer to entry pt block
load__R10	#	4			;Client's R10 value
load__R12	#	4			;Client's R12 value

load__buffStart	#	4			;The buffer's start address
load__buffSize	#	4			;And its size
load__buffHnd	#	4			;Client's buffer handle

load__totalSize	#	4			;How much data we've received

load__message	#	44			;The original load/save msg
load__name	#	212			;The file's apparent name

load__wSize	EQU	{VAR}-load__wStart

		; --- States ---
		;
		; These have been carefully arranged so that we can return
		; the safeness flag to various routines.  If we only
		; consider files, then the state /is/ the safeness flag.
		; Otherwise we only use the bottom bit of the state.

lState__scrap	EQU	0			;We're doing scrap transfer
lState__file	EQU	1			;We're loading from a file
lState__test	EQU	2			;We're testing RAM transfer
lState__ram	EQU	4			;We're doing RAM transfer

		AREA	|Sapphire$$LibData|,CODE,READONLY

		DCD	load__wSize
		DCD	load__wSpace
		DCD	256
		DCD	0

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

		END
