;
; loadlocal.s
;
; Loading and initialising extension DLLs
;
;  1994 Straylight
;

;----- Standard stuff -------------------------------------------------------

		GET	libs:header
		GET	libs:swis

;----- Other external dependencies ------------------------------------------

		IMPORT	|x$stack_overflow|
		IMPORT	malloc
		IMPORT	free
		IMPORT	|_dll_giveMemory|

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

		AREA	|DLL$$Code|,CODE,READONLY

; dll _dll_loadExtension(char *name)

		EXPORT	|_dll_loadExtension|
|_dll_loadExtension|
dle		ROUT

		; --- APCS header ---

		MOV	ip,sp
		STMFD	sp!,{v1-v3,fp,ip,lr,pc}
		SUB	fp,ip,#4
		CMP	sp,sl
		BLLT	|x$stack_overflow|

		; --- Find the size of the DLL file ---

		MOV	v3,a1			;Look after the name pointer
		MOV	a2,a1			;Pass filename to OS_File
		MOV	a1,#17			;Load, no path variable
		SWI	XOS_File		;Find information about DLL
		BVS	%10dle			;If it failed, return 0
		CMP	a1,#1			;Check that it's a file
		BNE	%10dle			;If not, return failure

		; --- Allocate a block for the DLL ---

		ADD	a1,v1,#20		;Allocate an extra 20 bytes
		BL	malloc			;Allocate the workspace
		CMP	a1,#0			;Did it work?
		BEQ	%10dle			;No -- return failure
		MOV	v2,a1			;Look after this pointer

		; --- Load the DLL into the block ---

		MOV	a2,v3			;Point to DLL name
		SWI	XDLL_Load		;Load the DLL into memory
		BVS	%11dle			;If it failed, free the block

		; --- Allocate workspace for the DLL ---

		MOV	a1,v2			;Point to the DLL
		SWI	XDLL_Info		;Find information about it
		MOV	a1,v1			;Allocate the right amount
		BL      malloc			;Allocate some workspace
		CMP	a1,#0			;Ensure that it worked
		BEQ	%11dle			;Kill everything if it failed
		MOV	a2,a1			;Set up workspace pointer
		MOV	a1,v2			;Point to DLL
		SWI	XDLL_SetInstanceVars	;Give it the memory

		; --- Allocate space for any other DLLs loaded ---

		BL	|_dll_giveMemory|	;Allocate space for new DLLs

		; --- Return the DLL handle to the caller

		MOV	a1,v2			;Put the handle away nicely
		LDMDB	fp,{v1-v3,fp,sp,pc}^	;Return to caller

		; --- Free DLL block and return to caller ---

11dle		MOV	a1,v2			;Point to DLL block
		BL	free			;Free the memory it used

		; --- Return to caller with tail between legs ---

10dle		MOV	a1,#0			;Return a NULL pointer
		LDMDB	fp,{v1-v3,fp,sp,pc}^	;Return to caller

		LTORG

; void _dll_freeExtension(dll d)

		EXPORT	|_dll_freeExtension|
|_dll_freeExtension|

		MOV	ip,sp
		STMFD	sp!,{v1,fp,ip,lr,pc}
		SUB	fp,ip,#4
		CMP	sp,sl
		BLLT	|x$stack_overflow|

		MOV	v1,a1
		SWI	DLL_FindInstanceVars
		BL	free
		MOV	a1,v1
		LDMDB	fp,{v1,fp,sp,lr}
		B	free

		LTORG

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

		END
