***
*** Startup code for DeliTracker genies (and players too if necessary) programmed in SAS/C
*** which is a somewhat more pleasant experience than doing the same in assembly language...
***
*** $VER: delistartup.asm 2.0 (10.08.94) by Necro\Banana Dezign
***
*** Code is VERY inspired by the SAS/C startup code (c.a)
***
*** To assemble: asm -u delistartup.asm
***

	include	"exec/types.i"
	include	"exec/alerts.i"
	include	"exec/nodes.i"
	include	"exec/lists.i"
	include	"exec/ports.i"
	include	"exec/libraries.i"
	include	"exec/tasks.i"
	include	"exec/memory.i"
	include	"exec/execbase.i"
	include	"exec/funcdef.i"
	include	"exec/exec_lib.i"
	include	"dos/dosextens.i"
	include	"dos/dos_lib.i"
	include	"utility/tagitem.i"
	include	"misc/DeliPlayer.i"
	include	"necro/macros.i"


	xdef	_XCEXIT		* exit(code) is standard way to leave C
	xdef	@_XCEXIT

	xref	DeliTags
	xref	LinkerDB	* linker defined base value
	xref	_BSSBAS		* linker defined base of BSS
	xref	_BSSLEN		* linker defined length of BSS
	xref	__stack

;;;
;;;   Stack map.
;;;
      OFFSET  0
           ds.b    4
savereg    ds.b    13*4
stackbtm   ds.b    4



	section	text,code

	xref	__main
	xref	__fpinit
	xref	__fpterm

	bra.w	errorMsg
	dc.b	"DELIRIUM"
	dc.l	DeliTags

errorMsg	move.l	4.w,a6
		move.l	ThisTask(a6),a3
		tst.l	pr_CLI(a3)
		beq	.wb

		lea	dosName(pc),a1
		moveq	#36,d0
		LVOEXE	OpenLibrary
		tst.l	d0
		bne.s	.ok
		moveq	#20,d0
		rts
.ok		move.l	d0,a6
		lea	errorText(pc),a0
		move.l	a0,d1
		LVO	PutStr
		move.l	a6,a1
		LVOEXE	CloseLibrary
		moveq	#20,d0
		rts

.wb		lea	pr_MsgPort(a3),a0
		LVO	WaitPort
		lea	pr_MsgPort(a3),a0
		LVO	GetMsg
		move.l	d0,d7

		lea	dosName(pc),a1
		moveq	#36,d0
		LVOEXE	OpenLibrary
		tst.l	d0
		bne.s	.wok
		moveq	#20,d0
		bra	.end
.wok		move.l	d0,a6
		lea	errorStream(pc),a0
		move.l	a0,d1
		move.l	#MODE_OLDFILE,d2
		LVO	Open
		move.l	d0,d6
		beq	.errclose
		move.l	d6,d1
		lea	errorText(pc),a0
		move.l	a0,d2
		LVO	FPuts
		move.l	d6,d1
		lea	pressText(pc),a0
		move.l	a0,d2
		LVO	FPuts
		move.l	d6,d1
		LVO	FGetC
		move.l	d6,d1
		LVO	Close
.errclose	move.l	a6,a1
		LVOEXE	CloseLibrary
		moveq	#20,d0

.end		move.l	d0,-(sp)
		move.l	d7,a1
		LVOEXE	Forbid
		move.l	d7,a1
		LVO	ReplyMsg
		move.l	(sp)+,d0
		rts

*** process entry code starts here - this is the entry point when DeliTracker launches us

	xdef	@initCode
	xdef	initCode

@initCode
initCode	movem.l	d1-d6/a0-a6,-(a7)

		lea	LinkerDB,a4
		move.l	4.w,a6
		move.l	a7,_StackPtr(a4)
		move.l	a6,SysBase(a4)

*** get stacksize (we don't allocate bigger stacks as the tag DTG_StackSize should be good enough...)

		move.l	ThisTask(a6),a3
		move.l	a7,d0
		sub.l	TC_SPLOWER(a3),d0

*** set __base for stack checking

		move.l	a7,d1
		sub.l	d0,d1
		add.l	#128,d1
		move.l	d1,__base(a4)

		move.l	ThisTask(a6),a3

*** get available libraries from DeliBase

		move.l	DeliBase,a0
		move.l	dtg_DOSBase(a0),DOSBase(a4)
		move.l	dtg_IntuitionBase(a0),IntuitionBase(a4)
		move.l	dtg_GfxBase(a0),GfxBase(a4)
		move.l	dtg_GadToolsBase(a0),GadToolsBase(a4)
		move.l	dtg_AslBase(a0),AslBase(a4)

*** here would be the CLI/WB argument collection (WBMsgs, etc.), but DeliTracker uses none of that...
*** so note that main goes as follows: main(void) - not main(argc,argv) !!

		move.l	pr_CurrentDir(a3),__curdir(a4)
		move.l	LN_NAME(a3),_ProgramName(a4)	* use task name as program name

*** the startup

main		jsr	__fpinit(pc)		* init floating point
		tst.l	d0
		bne.s	exit2
		jsr	__main(pc)		* call C entry point
		moveq	#0,d0			* set successful status
		bra.s	exit2

XCEXIT
_XCEXIT		move.l	4(a7),d0		* get return code

@XCEXIT
@_XCEXIT
exit2		move.l	_StackPtr(a4),a7
		move.l	d0,-(a7)

		move.l	_ONEXIT(a4),d0		* call any exit trap functions
		beq.s	exit3
		move.l	d0,a0
		jsr	(a0)
exit3		jsr	__fpterm(pc)		* clean up floating point

		move.l	(a7)+,d0		* restore return code
return		movem.l	(a7)+,d1-d6/a0-a6
		rts

***
*** Here are the C stubs for the DeliTracker interface functions
***
*** They're all mostly the same thing repeated over and over with different offsets, but it was the
*** best solution I could come up with at the time. I don't trust C to handle the calling directly.
***

	xdef	dt_GetListDataPos

dt_GetListDataPos	* dtg_GetListData had to be split up as you can't return two parameters
		bsr.s	dt_GetListDataSize
		move.l	a0,d0
		rts

	xdef	dt_GetListDataSize

dt_GetListDataSize
		move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_GetListData(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_LoadFile

dt_LoadFile	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_LoadFile(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_CopyDir

dt_CopyDir	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_CopyDir(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_CopyFile

dt_CopyFile	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_CopyFile(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_CopyString

dt_CopyString	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_CopyString(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_AudioAlloc

dt_AudioAlloc	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_AudioAlloc(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_AudioFree

dt_AudioFree	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_AudioFree(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_StartInt

dt_StartInt	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_StartInt(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_StopInt

dt_StopInt	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_StopInt(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_SongEnd

dt_SongEnd	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_SongEnd(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_CutSuffix

dt_CutSuffix	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_CutSuffix(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_SetTimer

dt_SetTimer	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_SetTimer(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_WaitAudioDMA

dt_WaitAudioDMA
		move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_WaitAudioDMA(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_LockScreen

dt_LockScreen	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_LockScreen(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_UnlockScreen

dt_UnlockScreen
		move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_UnlockScreen(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_NotePlayer

dt_NotePlayer	move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_NotePlayer(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_AllocListData

dt_AllocListData
		move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_AllocListData(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

	xdef	dt_FreeListData

dt_FreeListData
		move.l	a5,-(a7)
		move.l	DeliBase,a5
		move.l	dtg_FreeListData(a5),a0
		jsr	(a0)
		move.l	(a7)+,a5
		rts

*** just some strings for the error routine

dosName		dc.b	"dos.library",0
errorText	dc.b	"This program is a DeliTracker genie, and can only be started from DeliTracker.",10,0
pressText	dc.b	10,"Press RETURN...",0
errorStream	dc.b	"CON:160/14/320/64/Error Requester/AUTO/CLOSE",0

*** variable space

	section __MERGED,bss

	xdef	NULL,SysBase,DOSBase,IntuitionBase,GfxBase,GadToolsBase,AslBase
	xref	_FPERR

	xref	_WBenchMsg
	xref	__curdir
	xref	_OSERR,_SIGFPE,_ONERR,_ONEXIT,_ONBREAK
	xref	_SIGINT
	xref	_ProgramName,_StackPtr,__base

	xdef	DeliBase
	xdef	DeliPort

NULL		ds.b	4
DOSBase		ds.b	4
IntuitionBase	ds.b	4
GfxBase		ds.b	4
GadToolsBase	ds.b	4
AslBase		ds.b	4
SysBase		ds.b	4
mystk_Lower	ds.b	4
mystk_Upper	ds.b	4
mystk_Pointer	ds.b	4

DeliBase	ds.b	4
DeliPort	ds.b	4

newstack	ds.b	4
newstacksize	ds.b	4


	end

