
*	BothStartup.obj
*
*	A drop in replacement for Astartup.obj
*	For Workbench programs, or CLI programs with or without command
*	line parameters.
*	Modified from Astartup.asm by Bryce Nesbitt.  Release V1.0
*
******* Included Files *************************************************

	NOLIST
	INCLUDE "exec/types.i"
	IFND EXEC_ABLES_I
	INCLUDE "exec/ables.i"
	ENDC
	IFND EXEC_EXECBASE_I
	INCLUDE "exec/execbase.i"
	ENDC
	IFND LIBRARIES_DOS_I
	INCLUDE "libraries/dos.i"
	ENDC
	IFND LIBRARIES_DOESEXTENS_I
	INCLUDE "libraries/dosextens.i"
	ENDC
	IFND WORKBENCH_STARTUP_I
	INCLUDE "workbench/startup.i"
	ENDC
	LIST

******* Imported *******************************************************

	xref	_Input
	xref	_Output
	xref	_main			; C code entry point

callsys macro
	xref	_LVO\1
	jsr	_LVO\1(a6)
	endm

blink	macro
	bchg.b	#1,$bfe001
	endm

******* Exported *******************************************************

	xdef	_SysBase
	xdef	_DOSBase

	xdef	_errno
	xdef	_stdin
	xdef	_stdout
	xdef	_stderr

	xdef	_exit			; standard C exit function

************************************************************************
*
*	Standard Program Entry Point
*
*	main (argc, argv)
*	   int	argc;	    ;Passed as 32 bits. 0=from Workbench
*	   char *argv[];    ;Passed as 32 bits. If from workbench,
*			    ;then this is the WB message pointer.
*
;
;a3 - frame pointer
;a4 - ThisTask
;a5-  DOSBase
dosCmdLen	equr	d6
dosCmdBuf	equr	d5
;
startup:	move.l	d0,dosCmdLen
		move.l	a0,dosCmdBuf
		lea.l	ss,a3		; set up "frame pointer"
		clr.l	(a3)+		; _errno
		move.l	sp,(a3)+	; initailSP

	;------ get Exec's library base pointer:
		move.l	4,a6		; get _AbsExecBase
		move.l	a6,(a3)+	; _SysBase

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

		lea.l	DOSName(pc),A1
		callsys OldOpenLibrary	; Look ma, no error check!
		move.l	d0,(a3)+	; _DOSBase
		move.l	d0,a5

	;------ get the address of our task
		move.l	ThisTask(a6),a4

	;------ are we running as a son of Workbench?
		tst.l	pr_CLI(A4)
		beq	fromWorkbench
		clr.l	(a3)+		; returnMsg

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

	;------ find command name:
fromCLI 	move.l	pr_CLI(a4),a0
		add.l	a0,a0		; bcpl pointer conversion
		add.l	a0,a0
		move.l	cli_CommandName(a0),a0
		add.l	a0,a0		; bcpl pointer conversion
		add.l	a0,a0

	;------ create buffer and array:
		lea.l	argvBuffer-_stdin(a3),a2
		lea.l	argvArray-_stdin(a3),a1
		moveq.l #1,d2		; param counter

	;------ fetch command name:
		moveq.l #0,d0
		move.b	(a0)+,d0	; size of command name
		move.l	a2,(a1)+	; ptr to command name
		bra.s	1$
2$		move.b	(a0)+,(a2)+
1$		dbf	d0,2$
		clr.b	(a2)+

	;------ collect parameters:
		move.l	dosCmdLen,d0
		move.l	dosCmdBuf,a0

	;------ skip control characters and space:
parmloopa:	move.b	(a0)+,d1
		subq.l	#1,d0
		ble.s	parmExit
		cmp.b	#' ',d1
		ble.s	parmloopa

	;------ copy parameter:
		addq.l	#1,d2
		cmp.w	#32,d2
		beq	parmExit    ;!!Too many parms!!
		move.l	a2,(a1)+
		bra.s	5$

4$		move.b	(a0)+,d1
		subq.l	#1,d0
		cmp.b	#' ',d1
		ble.s	endofarg
5$		move.b	d1,(a2)+
		bra.s	4$

endofarg	clr.b	(a2)+	    ;Null terminate
		bra.s	parmloopa

	;------ Clear out ends, and go away
parmExit:	clr.b	(a2)+
		clr.l	(a1)+

		move.l	d2,d0		; Arg count
		pea	argvArray	; Arg array pointer
		move.l	d0,-(sp)

	;------ get standard input handle:
		move.l	a5,a6		; Get DOSBase
		callsys Input
		move.l	d0,(a3)+	; _stdin

	;------ get standard output handle:
		callsys Output
		move.l	d0,(a3)+	; _stdout
		move.l	d0,(a3)+	; _stderr

	;------ call C main entry point
		bra	domain

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

	;------ we are now set up.  wait for a message from our starter
fromWorkbench:	;[a4=ThisTask]
		;[a5=DOSBase]
		lea.l	pr_MsgPort(A4),a0	; our process base
		callsys WaitPort
		lea.l	pr_MsgPort(A4),a0	; our process base
		callsys GetMsg

	;------ save the message so we can return it later
		move.l	d0,(a3)+ ; set returnMsg. NOTE: no ReplyMsg yet!

	;------ push argc and argv.  if argc = 0 program came from
	;------ Workbench, and argv will have the WB message.
		move.l	d0,-(SP)	; set argv to the WB message
		clr.l	-(SP)		; set argc to 0

	;------ get the first argument
		;[d0=WBMessage]
		move.l	a5,a6		;Get DOSBase
		move.l	d0,a2
		move.l	sm_ArgList(a2),d0
		beq.s	docons

	;------ and set the current directory to the same directory
		move.l	d0,a0
		move.l	wa_Lock(a0),d1
		callsys CurrentDir

docons: ;------ ignore the toolwindow argument
domain: 	jsr	_main
		moveq.l #0,d0		; Successful return code
		bra.s	exit2

************************************************************************
*
*	C Program exit(returncode) Function
*
*  Warning: no resources are deallocated.  If you took it, you must
*  have already given it back!!
*
*
_exit:		move.l	4(SP),d0	 ; extract return code
exit2:		lea.l	ss,a3		 ; set "frame pointer" back up
		move.l	initialSP-ss(a3),SP ; restore stack pointer
		move.l	d0,-(SP)	 ; save return code

	;------ close DOS library:
		move.l	4,a6
		move.l	_DOSBase-ss(a3),a1
		callsys CloseLibrary

	;------ if we ran from CLI, skip workbench cleanup:
		move.l	returnMsg-ss(a3),d0
		beq.s	exitToDOS

	;------ return the startup message to our parent
	;------ we forbid so workbench can't UnLoadSeg() us
	;------ before we are done:
		FORBID
		;[d0=returnMsg]
		move.l	d0,a1
		callsys ReplyMsg

	;------ this rts sends us back to DOS:
exitToDOS:	move.l	(SP)+,d0
		rts
DOSName:	dc.b 'dos.library',0
		cnop 0,2

******* DATA ***********************************************************
		BSS
ss			; placemarker
_errno		ds.l 1	; error number from OS routines
initialSP	ds.l 1	; initial stack pointer
_SysBase	ds.l 1	; exec library base pointer
_DOSBase	ds.l 1	; dos library base pointer
returnMsg	ds.l 1	; Workbench message, or zero for CLI startup
_stdin		ds.l 1
_stdout 	ds.l 1
_stderr 	ds.l 1
argvArray	ds.l 32  ;maximum 32 args
argvBuffer	ds.b 256 ;and 256 characters

		END
