	section	text,CODE
* C initial startup procedure under AmigaDOS
* 
* Requirements:

	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 "libraries/dos.i"
	INCLUDE "libraries/dosextens.i"
	INCLUDE "workbench/startup.i"

; some usefull macros:
xlib	macro
	xref	_LVO\1
	endm

callsys	macro
	CALLLIB	_LVO\1
	endm
	

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

	xref	_LinkerDB		* linker defined base value

	xref	_Debug
	xref	__main			* Name of C program to start with.
	xref	_MemCleanup
	xref	_AbsExecBase
	xref	_FindTask
	xref	_DOSBase
	xref	_MathBase
	xref	_MathTransBase
        xref	_myhandler

	xlib	Alert
	xlib	FindTask
	xlib	Forbid
	xlib	GetMsg
	xlib	OpenLibrary
	xlib	CloseLibrary
	xlib	ReplyMsg
	xlib	Wait
	xlib	WaitPort
	xlib	Open
	xlib	Close
	xlib	CurrentDir

start:
	move.l	d0,dosCmdLen
	move.l	a0,dosCmdBuf
	move.l	a7,d0			; save old stack ptr
	movem.l	d1-d6/a0-a6,-(a7)
	move.l	d0,a5
	move.l	_AbsExecBase,a6
	move.l	a6,_SysBase
	move.l	a7,__StackPtr		* Save stack ptr
	clr.l	_WBenchMsg

;------ get the address of our task
	suba.l	a1,a1
	callsys	FindTask
	move.l	d0,a4

;------ are we running as a son of Workbench?
	move.l	pr_CurrentDir(A4),_curdir
	tst.l	pr_CLI(A4)
	beq	fromWorkbench

;=======================================================================
;====== CLI Startup Code ===============================================
;=======================================================================

fromCLI:
	move.l	a5,D0		; get top of stack
	sub.l	4(a5),D0	; compute bottom 
	move.l	D0,__base	; save for stack checking
;------	attempt to open DOS library:
	bsr	openDOS

;------ find command name:
	move.l	#start,a0
	clr.l	-(sp)
	jsr	_FindTask
	addq.l	#4,sp
	move.l	d0,a0
	move.l	pr_CLI(a0),a0
	add.l   a0,a0		; bcpl pointer conversion
	add.l   a0,a0
	move.l	cli_CommandName(a0),a1
	add.l   a1,a1		; bcpl pointer conversion
	add.l   a1,a1

;------	collect parameters:
	move.l	dosCmdLen,d0		; get command line length
	move.l	a1,__ProgramName
	addq.l	#1,d0			; allow for space after command	

	clr.w	-(A7)			; set null terminator for command line
	addq.l	#1,D0			; force to even number of bytes
	andi.w	#$fffe,D0		;(round up)
	sub.l	D0,A7			; make room on stack for command line
	subq.l	#2,D0
	clr.w	0(A7,D0)

;------ copy command line onto stack
	move.l	dosCmdLen,d0		; get command line length
	move.l	dosCmdBuf,a0
	move.l	d0,d2
	subq.l	#1,d0

copy_line:
	move.b	0(A0,D0.W),0(A7,D2.W)	; copy command line to stack
	subq.l	#1,d2
	dbf	d0,copy_line
	move.b	#' ',0(a7,d2.w)		; add space between command and parms
	subq.l	#1,d2

copy_cmd:
	move.l	A7,A1
	move.l	A1,-(A7)		; push command line address
	bra	goto_main		        * call C entrypoint

;=======================================================================
;====== Workbench Startup Code =========================================
;=======================================================================

fromWorkbench:

	move.l	TC_SPLOWER(a4),__base	; set base of stack
;------ open the DOS library:
	bsr	openDOS

;------ we are now set up.  wait for a message from our starter
	bsr	waitmsg
	move.l	d0,_WBenchMsg
	move.l	d0,-(SP)
;
	move.l	d0,a2			; get first argument
	move.l	sm_ArgList(a2),d0
	beq.s	do_cons
	move.l	_DOSBase,a6
	move.l	d0,a0
	move.l	wa_Lock(a0),d1
	move.l	d1,_curdir
	callsys	CurrentDir
do_cons:
	move.l	sm_ToolWindow(a2),d1	; get the window argument
	beq.s	do_main
	move.l	#MODE_OLDFILE,d2
	callsys	Open
	move.l	d0,stdin
	beq.s	do_main
	lsl.l	#2,d0
	move.l	d0,a0
	move.l	fh_Type(a0),pr_ConsoleTask(A4)
do_main:
	move.l	_WBenchMsg,a0		; get address of workbench message
	move.l	sm_ArgList(a0),a0	; get address of arguments
	move.l	wa_Name(a0),__ProgramName	; get name of program
	moveq	#0,d0
	move.l	d0,-(A7)

goto_main:
	lea	_LinkerDB,a6		; load base register
	jsr	__main		        * call C entrypoint
	moveq.l	#0,d0			; set successful status
	bra.s	exit2
;

_XCEXIT:
	move.l	4(SP),d0	; extract return code
exit2:
	move.l	d0,-(a7)
	move.l	_SysBase,a6
	move.l	_DOSBase,a1
	callsys	CloseLibrary		; close Dos library
done_1b:
;------ if we ran from CLI, skip workbench cleanup:
	tst.l	_WBenchMsg
	beq.s	exitToDOS
	move.l	_console_dev,d1
	beq.s	done_2
	callsys	Close
done_2:
	move.l	stdin,d1
	beq.s	done_4
	callsys	Close
done_4:

;------ return the startup message to our parent
;	we forbid so workbench can't UnLoadSeg() us
;	before we are done:
	move.l	_AbsExecBase,A6
	callsys Forbid
	move.l	_WBenchMsg,a1
	callsys	ReplyMsg

;------ this rts sends us back to DOS:
exitToDOS:
	MOVE.L	(A7)+,D0
	movea.l  __StackPtr,SP		* restore stack ptr
	movem.l	(a7)+,d1-d6/a0-a6
	rts				* and exit

;-----------------------------------------------------------------------
noDOS:
		ALERT	(AG_OpenLib!AO_DOSLib)
		moveq.l	#100,d0
		bra	exit2


;-----------------------------------------------------------------------
; This routine gets the message that workbench will send to us
; called with task id in A4

waitmsg:
		lea	pr_MsgPort(A4),a0  	* our process base
		callsys	WaitPort
		lea	pr_MsgPort(A4),a0  	* our process base
		callsys GetMsg
		rts

;-----------------------------------------------------------------------
;  Open the DOS library:

openDOS
		lea	DOSName,A1
		moveq.l	#0,D0
		callsys OpenLibrary
		move.l	D0,_DOSBase
		beq	noDOS
		rts

*************************************************************************
*   HandlerInterface()
*
*   This code is needed to convert the calling sequence performed by
*   the input.task for the input stream management into something
*   that a C program can understand.
*
*   This routine expects a pointer to an InputEvent in A0, a pointer
*   to a data area in A1.  These values are transferred to the stack
*   in the order that a C program would need to find them.  Since the
*   actual handler is written in C, this works out fine. 
*
*   Author: Rob Peck, 12/1/85
*

_HandlerInterface:
	movem.L	A0/A1,-(A7)
	jsr	_myhandler
	addq.L	#8,A7
	rts

	section	"__MERGED",DATA
;
	XDEF	_NULL,_SysBase,_LoadAddress,_console_dev,_WBenchMsg
	XDEF	_curdir,__mbase,__mnext,__msize,__tsize
	XDEF	__oserr,__OSERR,__FPERR,__SIGFPE,__ONERR,__ONEXIT,__ONBREAK
	XDEF	__SIGINT,__ECS
	XDEF	__ProgramName,__StackPtr,__base
;
_NULL		dc.l	0		;
__base		dc.l	0		; base of stack
__mbase		dc.l	0		; base of memory pool
__mnext		dc.l	0		; next available memory location
__msize		dc.l	0		; size of memory pool
__tsize		dc.l	0		; total size?
__oserr		equ	*
__OSERR		dc.l	0
__FPERR		dc.l	0
__SIGFPE	dc.l	0
__SIGINT	dc.l	0
__ONERR		dc.l	0
__ONEXIT	dc.l	0
__ONBREAK	dc.l	0
__ECS		dc.l	0		; extended character set flag
_curdir		dc.l	0
_console_dev	dc.l	0
_SysBase	dc.l	0
_LoadAddress	dc.l	0			; program load address
_WBenchMsg	dc.l	0
__StackPtr	dc.l	0
dosCmdLen	dc.l	0
dosCmdBuf	dc.l	0
stdin		dc.l	0
__ProgramName	dc.l	0
DOSName 	DOSNAME

	END
