
; FAME TestDoor.asm
;
; FAME asm door examples by BLOODROCK/tRSi © 1996 Oliver Lange
;
; This is an easy assembler example for FIM door writers.
; I have written many comments. I think it's better to write too much
; than not enough. Later, if you delete all the gabble, you'll see that
; this example is really simple and easy to use.
; If there are questions left about FAME assembler door writing, don't
; hesitate to contact me (BLOODROCK) and ask about the things you wanna
; know. Answers to important questions will be added to future FAME
; asm include updates.
;
; Using this source code saves much initial work. You may directly come
; to the main functions of your door without wasting time by thinking
; about how to communicate with the Node. Another point is that this
; example is written in a correct form and you'll avoid errors and other
; quirks which don't fulfil the AmigaOS standards and the FAME door rules.
;
; There is nothing left to do for you without sending door commands. All data
; elements you need can be reached reading n(a5), where n is declared in the
; following structure called MyData. For example, to get the dos library base
; address, use "move.l DOSBase(a5),a6".
; Note: if you're using A5 another way, you MUST push it on the stack first
; and restore it later (before exiting). You *must* preserve A5 on exit !
;
; There is *no need* to restore the stack on exit. The init code saves the
; current sp in the MyData structure, so you may directly jump into your
; door exit code from any sub routine without fixing sp first. A very
; useful feature..
;
; Last note: this door startup source and programming technique makes your
; door re-entrant, meaning that it may be loaded resident into memory.
;
;-----------------------------------------------------------------------------


FAMELibVersion EQU 1	; Define the minimum FAME library version we need.


	Section	DoorCode1,Code	; Some assemblers require this.

	incdir	"include:"	; Remove this if your assembler doesn't
				; accept it (like the SAS-"asm", for example).

	include	"FAME/FAMEEasyDoorStartup.i"	; That magic thing that does
						; all startup for us..

	STRUCTURE	MyData,0	; Some data space for us as follows:

	APTR	AbsExecBase		; Exec library base address
	APTR	ByeMessage		; Door's last output text on exit
	APTR	DoorControlPort		; Our DoorControlPort
	APTR	DoorMessage		; Our DoorMessage
	ULONG	DoorSigBits		; Our SignalSet to Wait() for
	ULONG	DoorPortNum		; Our door port number
	APTR	DoorReplyPort		; Our ReplyPort we have created
	APTR	DOSBase			; DOS library base
	APTR	FAMEBase		; FAME library base
	STRUCT	FAMEDoorPortName,256	; Name + number of our FAME door port
	APTR	InitialStack		; The initial stack gets saved here
	APTR	OwnTask			; Our Process structure

	UBYTE	ReturnCode		; Our ReturnCode (not really needed)

	ALIGNLONG




	; Insert your additional data here, like APTR GFXBase, APTR MyWindow
	; etc. You may define up to 32K of global data your door may need.





	LABEL	MyData_SIZEOF		; Marks the size it'll finally get

;-----------------------------------------------------------------------------

; Some macros follow. Use it, or replace it by your own macro set.

dos	Macro
		move.l	DOSBase(a5),a6
	EndM

exec	Macro
		move.l	AbsExecBase(a5),a6	; Not using "move.l 4.w,a6"
	EndM					; means doing a quicker move
						; from FastMem.
fame	Macro
		move.l	FAMEBase(a5),a6
	EndM

call	Macro
		Jsr	_LVO\1(a6)
	EndM

;-----------------------------------------------------------------------------

	bra.s	DoorStart

	; Early $VER: strings make version commands find it quick.

	dc.b	"$VER: TestDoor.asm 0.20 (8.8.88)",0	; Fill-in!

	cnop	0,4

; Your door code begins here.
; A5 holds the pointer to your data area. YOU MUST PRESERVE A5 ON EXIT !
; Accessing all your local data via offset(An) keeps your door re-entrant,
; raises execution speed and reduces code size.
;
; Note: ReturnCode(a5) is still set to RETURN_FAIL, a0 and d0 (the CLI args)
; are trashed. Use the NR_NodeID door command to get your node number,
; if you need it. All other elements in the MyData structure are initialized
; and valid.

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

DoorStart:

	move.l	DoorMessage(a5),a1
	lea	TestText(pc),a0		; bla-bla-bla..
	move.l	a0,Fdom_StringPtr(a1)	; Set output string
	clr.l	Fdom_Data1(a1)		; No additional CR/LF

	send	AR_SendStr	; Finally, our text gets displayed. Yo!
				; No result check needed! The "send" macro
				; does this for you ! This macro and the
				; function belonging to it, can be found
				; in "FAMEEasyDoorStartup.i".


	move.b	#RETURN_OK,ReturnCode(a5)	; Clears the ReturnCode.
						; Not really needed, but
						; doors called from a script
						; may break it.

; REMEMBER that if a FAME DoorMessage fails, "Abort:" is directly called
; without ever leaving the "send" macro. Be prepared for the event that
; your door gets shut down any time you send a door command ! Shutting down
; is done best by checking if resources have to be freed. For example:
;
;Abort:
;	dos
;	move.l	MyFH(a5),d1 	; some temporary File Handle
;	beq.s	FileNotOpened
;	call	Close
;
;FileNotOpened:
;	rts
;
; To make sure that MyFH(a5) is NULL when the file is closed, do the
; following in your door code:
;
;	dos
;	call	Open
;	move.l	d0,MyFH(a5)
;	...
;	move.l	MyFH(a5),d1
;	call	Close
;	clr.l	MyFH(a5)	; states that this file is not to close
;				; at the Abort: section.
;
; -so you may safely test and trust MyFH(a5) in the Abort: section.
; The Abort: section follows next.
;
; If you want to have the door displaying a "Last Message", put the address
; of your message text to ByeMessage(a5).
; If ByeMessage(a5) is ZERO, nothing will be typed to the user.
; The ByeMessage is useful if a door which redefines the ANSI scroll borders
; gets shut down by the sysop.
; Therefor, the function NR_ResetANSIOnExit is designed. And now we come
; to the ByeMessage: this text is displayed AFTER the console and terminal
; reset is done.
; So, you may leave a message to the user if he gets back to his prompt, e.g.
; an error message or such.
;
; Example:
; Move.l	AddressOfMyText,ByeMessage(a5)	; MyText gets sent on exit.
;
; In the case of a door command error, ByeMessage gets set to the correct
; error phrase.
; Advanced programmers may replace the error text setting routine by different
; exit code. To do this, edit the file "FAMEEasyDoorStartup.i".

Abort:
	exec
	move.l	DoorMessage(a5),a1
	clr.b	Fdom_IOString(a1)	; clear ExitMsg first
	move.l	ByeMessage(a5),d0	; ByeMsg(a5) non-zero ?
	beq.s	NoByeMsg		; Then skip.
	move.l	d0,a0
	bsr	SetIOString		; Otherwise, set ByeMessage

NoByeMsg
	moveq	#MC_ShutDownLastWords,d0
	bsr	Do_SendCommand		; MC_ShutDownXXX MUST be sent; should
					; be done BEFORE you save data etc.,
					; because the user may continue
					; walkin' around the BBS while
					; your door shuts down in back-
					; ground. With other words:
					; this saves time.
					; We cannot use the send macro this
					; time, because an error would loop
					; forever; another thing is that
					; it doesn't matter anyway if an
					; error occurs with any MC_Shut-
					; down execution.

; Again: "FAMEEasyDoorStartup.i" saves your initial stack, so you may
; send messages while being in sub routine calls WITHOUT taking care
; about how to manage the stack if the door command fails and directly
; falls into the exit code. You may change the stack and directly jump
; into your Abort: code without returning from sub routine calls, or
; "withdrawing" any data from the stack.
;
;-----------------------------------------------------------------------------
;
; Free your resources now.
;
; Important: DO NOT CALL ANY DOOR COMMANDS from this Label on ! Only
; free your resources ! Last messages (without ByeMessage(a5) must be
; sent BEFORE the "Abort:" routine is called. The "Abort:" label is also
; used on the event of a FAME_ErrorCode, and the last and only allowd door
; command "MC_ShutDownXXXX", has already been sent.












; Don't forget to restore A5 to it's initial state if you have changed it !

	rts	; The end.

;-----------------------------------------------------------------------------

TestText:	dc.b	13,10
		dc.b	"Hi ! This is your door speaking !  :^)"
		dc.b	13,10,13,10,0

;-----------------------------------------------------------------------------

	end	; Some assemblers still insist on finding this command here.
