
; LaunchApplication - by Joseph Fenton
;
; Copyright (C) 1997 By Microcode Solutions, all rights reserved!
;
; This is a demonstartion of how to use the InnerCommunications Port
;
; Assemble with Devpac.  Other assemblers will require modifications
; to the code.

; Includes ----------------------------------------------------------

		incdir	DEVPAC:includes

		include	exec/exec.i
		include	dos/dosextens.i
		include	workbench/startup.i
		include	workbench/workbench.i
		include	intuition/intuition.i

		include	macinterface.i

		include	offsets.lib		; all the LVO's

		output	FUSION:ICP/LaunchApp

; Macros ------------------------------------------------------------

CALLSYS		MACRO
		jsr	_LVO\1(a6)
		ENDM

CALLEXE		MACRO
		movea.l	_ExecBase,a6
		CALLSYS	\1
		ENDM

CALLDOS		MACRO
		movea.l	_DOSBase,a6
		CALLSYS	\1
		ENDM

CALLINT		MACRO
		movea.l	_IntuitionBase,a6
		CALLSYS	\1
		ENDM

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

entry_pt	bra.b	main

		dc.b	0,'$VER:LaunchApp 1.0 (21.6.97)',0

		cnop	0,4

main		move.l	d0,d2
		movea.l	a0,a2			; save for DOS

		movea.l	4.w,a6
		move.l	a6,_ExecBase

		lea	err_bad_name,a4

		suba.l	a1,a1
		CALLSYS	FindTask
		movea.l	d0,a5
		tst.l	pr_CLI(a5)
		bne.w	.fromdos		; not run from WB

; run from WB
		lea	pr_MsgPort(a5),a0
		CALLSYS	WaitPort		; wait for startup message
		lea	pr_MsgPort(a5),a0
		CALLSYS	GetMsg			; get startup message
		move.l	d0,StartupMsg
		movea.l	d0,a0
		cmpi.l	#2,sm_NumArgs(a0)
		bne.w	.done			; wrong # of args
		movea.l	sm_ArgList(a0),a3
		addq.l	#8,a3			; skip 1st entry (tool)

		moveq	#37,d0
		lea	DOSName,a1
		CALLSYS	OpenLibrary
		move.l	d0,_DOSBase
		beq.w	.wberror1

		move.l	wa_Lock(a3),d1
		CALLDOS	CurrentDir
		move.l	d0,prevCurrDir

		moveq	#37,d0
		lea	IconName,a1
		CALLEXE	OpenLibrary
		tst.l	d0
		beq.b	.wberror2

		movea.l	wa_Name(a3),a0
		movea.l	d0,a6
		CALLSYS	GetDiskObject
		move.l	d0,applObject
		beq.b	.wberror3

		movea.l	d0,a0
		movea.l	do_ToolTypes(a0),a0
		lea	applToolType,a1
		CALLSYS	FindToolType
		tst.l	d0
		beq.b	.wberror4

		movea.l	d0,a0
		lea	fileName+1,a1
		moveq	#-1,d0
.wcloop		addq.b	#1,d0
		move.b	(a0)+,(a1)+
		bne.b	.wcloop
		move.b	d0,fileName		; set length

		suba.l	a4,a4			; okay

.wberror4	movea.l	applObject,a0
		CALLSYS	FreeDiskObject

.wberror3	movea.l	a6,a1
		CALLEXE	CloseLibrary

.wberror2	move.l	prevCurrDir,d1
		CALLDOS	CurrentDir

		movea.l	a6,a1
		CALLEXE	CloseLibrary

.wberror1	move.l	a4,d0
		bne.b	.done			; error
		bra.b	.geticp

; run from DOS

.fromdos	lea	fileName,a1
		subq.w	#1,d2			; for CR
		ble.b	.done			; error
		move.b	d2,(a1)+

		subq.w	#1,d2			; for dbra
		cmpi.w	#254,d2
		bhi.b	.done			; error

.dcloop		move.b	(a2)+,(a1)+
		dbra	d2,.dcloop

.geticp		lea	err_not_running,a4

		lea	icpName,a1
		CALLSYS	FindPort		; get ICP address
		move.l	d0,ICPort
		beq.b	.done			; FUSION not running

		bsr.w	doLaunch

.done		move.l	a4,d0
		beq.b	.exit			; no error message

		tst.l	pr_CLI(a5)
		bne.b	.doserr			; print error to StdOut

		moveq	#37,d0
		lea	IntuitionName,a1
		CALLSYS	OpenLibrary
		move.l	d0,_IntuitionBase
		beq.b	.done			; for safety

		suba.l	a0,a0			; appear on Workbench
		movea.l	a4,a1			; easyStruct for error
		suba.l	a2,a2			; no extra IDCMP flags for termination
		suba.l	a3,a3			; no arguments
		CALLINT	EasyRequestArgs

		move.l	a6,a1
		CALLEXE	CloseLibrary
		bra.b	.exit

.doserr		moveq	#0,d0
		lea	DOSName,a1
		CALLSYS	OpenLibrary
		move.l	d0,_DOSBase
		beq.b	.exit			; for safety

		move.l	es_TextFormat(a4),d1	; error string
		CALLDOS	PutStr

		move.l	#newline,d1		; CR and LF
		CALLSYS	PutStr

		movea.l	a6,a1
		CALLEXE	CloseLibrary

.exit		move.l	StartupMsg,d0
		bne.b	.wbexit
		rts				; return with 0 in d0 to DOS

.wbexit		CALLSYS	Forbid
		movea.l	StartupMsg,a1
		CALLSYS	ReplyMsg
		moveq	#0,d0
		rts

;--------------------------------------------------------------------
; Found FUSION's public port, create msgport/message for innercommunication

		cnop	0,4

doLaunch	lea	err_cant_setup,a4	; in case of error

		CALLSYS	CreateMsgPort
		move.l	d0,SDPort
		beq.w	.error1			; couldn't create port

		movea.l	d0,a0
		moveq	#FM_SIZE,d0
		CALLSYS	CreateIORequest
		move.l	d0,SDMsg
		beq.w	.error2			; couldn't create message

; execute LocateAppl function

		movea.l	d0,a1
		move.l	#FMCMD_EXECUTE,FM_OP(a1)
		move.l	#LocateAppl,FM_ARG1(a1)
		move.l	#FMFF_Switch,FM_FLAGS(a1)
		move.l	#600,FM_TIMEOUT(a1)	; 10 sec
		movea.l	ICPort,a0
		CALLSYS	PutMsg
		movea.l	SDPort,a0
		CALLSYS	WaitPort
		movea.l	SDPort,a0
		CALLSYS	GetMsg
		movea.l	d0,a1
		lea	err_bad_name,a4
		tst.l	FM_RES1(a1)
		bne.w	.cleanup	; error

; bring MAC screen to the front

		movea.l	SDMsg,a1
		move.l	#FMCMD_FRONT,FM_OP(a1)
		movea.l	ICPort,a0
		CALLSYS	PutMsg
		movea.l	SDPort,a0
		CALLSYS	WaitPort
		movea.l	SDPort,a0
		CALLSYS	GetMsg

; execute LaunchAppl function

		movea.l	SDMsg,a1
		move.l	#FMCMD_EXECUTE,FM_OP(a1)
		move.l	#LaunchAppl,FM_ARG1(a1)
		move.l	#FMFF_Switch,FM_FLAGS(a1)
		move.l	#600,FM_TIMEOUT(a1)	; 10 sec
		movea.l	ICPort,a0
		CALLSYS	PutMsg
		movea.l	SDPort,a0
		CALLSYS	WaitPort
		movea.l	SDPort,a0
		CALLSYS	GetMsg
		movea.l	d0,a1
		suba.l	a4,a4			; no error message
		tst.l	FM_RES1(a1)
		beq.b	.cleanup
		lea	err_cant_launch,a4

.cleanup	movea.l	SDMsg,a0
		CALLSYS	DeleteIORequest

.error2		movea.l	SDPort,a0
		CALLSYS	DeleteMsgPort

.error1		rts


; Emulator-Side Function Code ---------------------------------------

; This code runs on the emulator's task.  No registers need to be saved.

		cnop	0,4

LocateAppl	clr.w	-(a7)			; result
		clr.w	-(a7)			; vRefNum
		clr.l	-(a7)			; dirID
		pea	fileName		; fileName
		pea	spec			; spec
		moveq	#1,d0			; FSMakeFSSpec
		dc.w	$AA52			; _HighLevelFSDispatch
		moveq	#0,d0
		move.w	(a7)+,d0
		rts

		cnop	0,4

fileName	dcb.b	256,0

spec		dc.w	0			; launchAppSpec.vRefNum
		dc.l	0			; launchAppSpec.parID
		dcb.b	64,0			; launchAppSpec.name

		cnop	0,4

LaunchAppl	lea	LaunchParamBlk,a0	; LaunchParams
		dc.w	$A9F2			; _LaunchApp
		andi.l	#$FFFF,d0		; result
		rts

		cnop	0,4

LaunchParamBlk	dc.l	0			; reserved1
		dc.w	0			; reserved2
		dc.w	$4C43			; launchBlockID (extended block)
		dc.l	32			; launchEPBLength
		dc.w	0			; launchFileFlags
		dc.w	$4800			; launchControlFlags (launchContinue|launchNoFileFlags)
		dc.l	spec			; launchAppSpec
		dc.l	0,0			; launchProcessSN
		dc.l	0			; launchPreferredSize
		dc.l	0			; launchMinimumSize
		dc.l	0			; launchAvailableSize
		dc.l	0			; launchAppParameters


; Variables ---------------------------------------------------------

		cnop	0,4

_ExecBase	dc.l	0
_IntuitionBase	dc.l	0
_DOSBase	dc.l	0

StartupMsg	dc.l	0

prevCurrDir	dc.l	0
applObject	dc.l	0

SDPort		dc.l	0
SDMsg		dc.l	0
ICPort		dc.l	0

; Name Strings ------------------------------------------------------

		cnop	0,2

icpName		FusionPortName
		even

IntuitionName	dc.b	'intuition.library',0
		even

DOSName		dc.b	'dos.library',0
		even

IconName	dc.b	'icon.library',0
		even

applToolType	dc.b	'APPL',0
		even

; Error Messages ----------------------------------------------------

		cnop	0,4

err_bad_name	dc.l	es_SIZEOF
		dc.l	0
		dc.l	errTitle
		dc.l	bad_name_msg
		dc.l	errOkay

err_not_running	dc.l	es_SIZEOF
		dc.l	0
		dc.l	errTitle
		dc.l	not_running_msg
		dc.l	errOkay

err_cant_setup	dc.l	es_SIZEOF
		dc.l	0
		dc.l	errTitle
		dc.l	cant_setup_msg
		dc.l	errOkay

err_cant_launch	dc.l	es_SIZEOF
		dc.l	0
		dc.l	errTitle
		dc.l	cant_launch_msg
		dc.l	errOkay

errTitle	dc.b	'Error while trying to launch application.',0
		even

errOkay		dc.b	'Okay',0
		even

bad_name_msg	dc.b	'Could not locate application.',0
		even

not_running_msg	dc.b	'FUSION is not running!',0
		even

cant_setup_msg	dc.b	'InnerCommunications Port interface could not be setup.',0
		even

cant_launch_msg	dc.b	'Application could not be launched.',0
		even

newline		dc.b	10,13,0
		even


		END

