		opt	o+,ow-,ow6+
		output	Source:Install

		; Install v1.1
		; © 1990 by David Kinder

		; "It installs disks!"

		; Assemble using Devpac v3

		; Note that the header "system.gs" must be compiled
		; with v36 or higher include files.

		; Thanks to HiSoft, Iron Maiden, Megadeth, Judas Priest,
		; The Sisters of Mercy, The Damned and Oriel...

		section	Install_Code,code

		incdir	Source:include/
		include	devices/trackdisk.i
		include	workbench/icon_lib.i
		include	workbench/workbench.i

LINKSYS		MACRO				; A usefull macro, saves
		jsr	_LVO\1(a6)		; a few bytes
		ENDM

LINKDOS		MACRO
		movea.l	_DosBase(a4),a6
		jsr	_LVO\1(a6)
		ENDM

LINKICON	MACRO
		movea.l	_IconBase(a4),a6
		jsr	_LVO\1(a6)
		ENDM

LINKINT		MACRO
		movea.l	_IntuitionBase(a4),a6
		jsr	_LVO\1(a6)
		ENDM

		suba.l	a1,a1
		CALLEXEC FindTask
		move.l	d0,a5

		tst.l	pr_CLI(a5)		; Are we CLI or Workbench?
		beq.s	Do_WBStartup
		move.l	#0,a5
		bra.s	EndStartup

Do_WBStartup	lea	pr_MsgPort(a5),a0
		CALLEXEC WaitPort		; Wait for a message
		lea	pr_MsgPort(a5),a0
		LINKSYS	GetMsg			; Then get it
		move.l	d0,a5

EndStartup	move.l	#Data_SIZEOF,d0
		move.l	#MEMF_CLEAR,d1
		CALLEXEC AllocMem
		movea.l	d0,a4
		tst.l	d0
		beq.s	EndAll

		move.l	a5,ReturnMsg(a4)
		bsr.s	_Main
		move.l	ReturnMsg(a4),a5

		movea.l	a4,a1
		move.l	#Data_SIZEOF,d0
		CALLEXEC FreeMem

EndAll		cmp.l	#0,a5
		beq.s	ExitToDOS

		CALLEXEC Forbid
		move.l	a5,a1
		LINKSYS	ReplyMsg

ExitToDOS	moveq	#0,d0
		rts

_Main		lea	IntName,a1		; Open 'intuition.library'
		moveq	#36,d0
		CALLEXEC OpenLibrary
		move.l	d0,_IntuitionBase(a4)
		beq.s	NoNewOS

		lea	Gadg0,a0
		bsr.s	ModGadg2
		lea	Gadg1,a0
		bsr.s	ModGadg2
		lea	Gadg2,a0
		bsr.s	ModGadg
		lea	Gadg3,a0
		bsr.s	ModGadg

		eori	#CHECKED,KS13+mi_Flags
		eori	#CHECKED,KS20+mi_Flags
		bra.s	RunAllOS

ModGadg		subi	#1,gg_TopEdge(a0)	; Changes for OS 2.0
ModGadg2	subi	#2,gg_LeftEdge(a0)
		addi	#4,gg_Width(a0)
		addi	#2,gg_Height(a0)
		move.l	#x2_GBord1,gg_GadgetRender(a0)
		move.l	gg_GadgetText(a0),a1
		addi	#2,it_LeftEdge(a1)
		addi	#1,it_TopEdge(a1)
		move.b	#2,it_FrontPen(a1)
		rts

NoNewOS		lea	IntName,a1		; Try again
		moveq	#0,d0
		CALLEXEC OpenLibrary
		move.l	d0,_IntuitionBase(a4)
		beq	NoIntuition		; Open failed

RunAllOS	lea	DosName,a1		; Open 'dos.library'
		moveq	#0,d0
		LINKSYS	OpenLibrary
		move.l	d0,_DosBase(a4)
		beq	NoDos

		move.l	ReturnMsg(a4),a3	; Workbench?
		cmpa.l	#0,a3
		beq.s	NoIconLib

		lea	IconName,a1		; Open 'icon.library'
		moveq	#0,d0
		LINKSYS	OpenLibrary
		move.l	d0,_IconBase(a4)
		beq.s	NoIconLib

		move.l	sm_ArgList(a3),a3
		move.l	wa_Lock(a3),d1
		LINKDOS	CurrentDir		; Move to current directory

		move.l	wa_Name(a3),a0
		LINKICON GetDiskObject
		move.l	d0,a5
		tst.l	d0
		beq.s	EndIconFind

		move.l	do_ToolTypes(a5),a0
		lea	ToolType,a1
		LINKSYS	FindToolType
		beq.s	EndIconCode

		move.b	#1,CheckTest(a4)
EndIconCode	move.l	a5,a0
		LINKSYS	FreeDiskObject

EndIconFind	move.l	_IconBase(a4),a1
		CALLEXEC CloseLibrary

NoIconLib	move.l	#2048,d0
		move.l	#MEMF_CHIP!MEMF_CLEAR,d1
		CALLEXEC AllocMem		; Get some ChipRam
		move.l	d0,DiskBuffer1(a4)
		beq	NoMemory
		addi.l	#1024,d0
		move.l	d0,DiskBuffer2(a4)

		moveq	#0,d0
		lea	SBBlock,a0
		move.l	DiskBuffer1(a4),a1
BootLoop1	move	(a0,d0),(a1,d0)		; Transfer bootblock
		addq	#2,d0
		cmpi	#EBBlock-SBBlock,d0
		bne	BootLoop1

		moveq	#0,d0
		lea	SNBBlock,a0
		move.l	DiskBuffer2(a4),a1
BootLoop2	move	(a0,d0),(a1,d0)
		addq	#2,d0
		cmpi	#ENBBlock-SNBBlock,d0
		bne	BootLoop2

		moveq	#MP_SIZE,d0		; Put together a port where
		move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
		LINKSYS	AllocMem		; we can recieve messages
		move.l	d0,a3			; from 'trackdisk.device'
		beq	NoMemPort
		move.l	a3,MsgPort(a4)
		moveq	#-1,d0
		LINKSYS	AllocSignal
		cmpi.b	#-1,d0
		beq	NoSigPort
		move.b	d0,MP_SIGBIT(a3)
		movea.l	#0,a1
		LINKSYS	FindTask
		move.b	#NT_MSGPORT,LN_TYPE(a3)
		move.b	#PA_SIGNAL,MP_FLAGS(a3)
		move.l	d0,MP_SIGTASK(a3)
		lea	MP_MSGLIST(a3),a0
		NEWLIST	a0

		moveq	#IOSTD_SIZE,d0		; Now use message port
		move.l	#MEMF_PUBLIC!MEMF_CLEAR,d1
		LINKSYS	AllocMem		; to construct an
		tst.l	d0			; IORequest struct so we
		beq	NoMemIO			; can communicate with
		move.l	d0,a0			; the drive
		move.l	a0,IORequest(a4)
		move.l	a3,MN_REPLYPORT(a0)
		move	#IOSTD_SIZE,MN_LENGTH(a0)
		move.b	#NT_MESSAGE,LN_TYPE(a0)

		moveq	#0,d0			; Which drives are present?
		lea	Gadg0+gg_Flags,a5
		bsr	CheckDevice
		moveq	#1,d0
		lea	Gadg1+gg_Flags,a5
		bsr	CheckDevice
		moveq	#2,d0
		lea	Gadg2+gg_Flags,a5
		bsr	CheckDevice
		moveq	#3,d0
		lea	Gadg3+gg_Flags,a5
		bsr	CheckDevice

		lea	MyWindow,a0		; Open our window on
		LINKINT	OpenWindow		; Workbench screen
		move.l	d0,Windowhd(a4)
		beq	NoWindow		; Open window failed
		move.l	d0,a0
		move.l	wd_UserPort(a0),UserPort(a4)
		move.l	wd_RPort(a0),a0
		lea	Text,a1
		moveq	#0,d0
		moveq	#68,d1
		LINKSYS	PrintIText		; Print credit
		move.l	Windowhd(a4),a0
		lea	BootMenu,a1
		LINKSYS	SetMenuStrip
		move.l	Windowhd(a4),a0
		movea.l	#-1,a1
		lea	ScreenTitle,a2
		LINKSYS	SetWindowTitles		; Change title

MainLoop	move.l	UserPort(a4),a0		; Wait for an Intuition
		CALLEXEC WaitPort		; message...
CheckMessage	move.l	UserPort(a4),a0
		CALLEXEC GetMsg
		tst.l	d0
		beq	MainLoop
		move.l	d0,a1
		move.l	im_Class(a1),d2		; Store the message
		move.l	im_IAddress(a1),a2
		LINKSYS	ReplyMsg
		cmpi.l	#CLOSEWINDOW,d2		; Is it close time?
		beq.s	QuitProper
		cmpi.l	#GADGETUP,d2
		beq	StartInstall
		bra	CheckMessage

QuitProper	move.l	Windowhd(a4),a0		; Close window
		LINKINT	ClearMenuStrip
		move.l	Windowhd(a4),a0
		LINKSYS	CloseWindow
NoWindow	move.l	IORequest(a4),a1	; Free IORequest
		moveq	#IOSTD_SIZE,d0
		CALLEXEC FreeMem
NoMemIO		move.l	MsgPort(a4),a3		; Unlink MsgPort
		moveq	#0,d0
		move.b	MP_SIGBIT(a3),d0
		CALLEXEC FreeSignal
NoSigPort	move.l	MsgPort(a4),a1		; Free MsgPort
		moveq	#MP_SIZE,d0
		CALLEXEC FreeMem
NoMemPort	move.l	DiskBuffer1(a4),a1	; Free Buffer
		move.l	#2048,d0
		CALLEXEC FreeMem
NoMemory	move.l	_DosBase(a4),a1		; Close DOS
		CALLEXEC CloseLibrary
NoDos		move.l	_IntuitionBase(a4),a1	; Close Intuition
		CALLEXEC CloseLibrary
NoIntuition	rts

CheckDevice	lea	TrackDisk,a0		; Check for a drive and
		move.l	IORequest(a4),a1	; disable gadget if not
		moveq	#0,d1			; present
		CALLEXEC OpenDevice
		cmpi	#TDERR_BadDriveType,d0
		bne.s	DeviceOn
		move	#GADGHCOMP!GADGDISABLED,(a5)
		rts
DeviceOn	tst	d0
		bne.s	OtherFail
		move.l	IORequest(a4),a1
		LINKSYS	CloseDevice
OtherFail	rts

StartInstall	move.l	DiskBuffer2(a4),DiskBuffer(a4)
		move	KS13+mi_Flags,d0	; Which bootblock?
		andi	#CHECKED,d0
		beq.s	StartGadg
		move.l	DiskBuffer1(a4),DiskBuffer(a4)

StartGadg	move	gg_GadgetID(a2),d0	; Which gadget was it?
		move.b	d0,d7
		addi.b	#$30,d0
		move.b	d0,CheckTxtPt
		cmpi.b	#1,CheckTest(a4)
		beq.s	NoTest

		move.l	Windowhd(a4),a0
		lea	CheckText,a1
		lea	CYes,a2
		lea	CNo,a3
		moveq	#0,d0
		moveq	#0,d1
		move	#360,d2
		moveq	#53,d3
		LINKINT	AutoRequest		; Are you sure?
		tst.l	d0
		beq	CheckMessage

NoTest		lea	TrackDisk,a0
		moveq	#0,d0
		move.b	d7,d0
		move.l	IORequest(a4),a1
		moveq	#0,d1
		CALLEXEC OpenDevice
		beq.s	NoOpenErr

		moveq	#1,d0
		bsr	ErrorTime
		bra	CheckMessage

NoOpenErr	move.l	IORequest(a4),a1
		move	#TD_CHANGESTATE,IO_COMMAND(a1)
		LINKSYS	DoIO
		move.l	IORequest(a4),a1
		move.l	IO_ACTUAL(a1),d0
		beq.s	NoDiskError

		move.l	Windowhd(a4),a0
		lea	NoDiskErr,a1
		move.l	#0,a2
		lea	AbortText,a3
		moveq	#0,d0
		moveq	#0,d1
		move	#281,d2
		moveq	#53,d3
		LINKINT	AutoRequest
		bra.s	CloseInstall

NoDiskError	move	#TD_PROTSTATUS,IO_COMMAND(a1)
		LINKSYS	DoIO			; Check write protect
		move.l	IORequest(a4),a1
		move.l	IO_ACTUAL(a1),d0
		beq.s	NoProtErr

		move.l	Windowhd(a4),a0
		lea	ProtectErr,a1
		move.l	#0,a2
		lea	AbortText,a3
		moveq	#0,d0
		moveq	#0,d1
		move	#265,d2
		moveq	#53,d3
		LINKINT	AutoRequest
		bra.s	CloseInstall

NoProtErr	move.l	#1024,IO_LENGTH(a1)	; Set up command
		move.l	DiskBuffer(a4),IO_DATA(a1)
		move	#CMD_WRITE,IO_COMMAND(a1)
		move.l	#0,IO_OFFSET(a1)
		LINKSYS	DoIO			; Send new bootblock

		move.l	IORequest(a4),a1
		move.b	IO_ERROR(a1),d0
		beq.s	NoWriteErr
		bsr.s	ErrorTime

CloseInstall	move.l	IORequest(a4),a1
		CALLEXEC CloseDevice
		bra	CheckMessage

NoWriteErr	move	#CMD_UPDATE,IO_COMMAND(a1)
		LINKSYS	DoIO			; Force track write

		move.l	IORequest(a4),a1
		move.l	#0,IO_LENGTH(a1)
		move	#TD_MOTOR,IO_COMMAND(a1)
		LINKSYS	DoIO			; Motor off

		move.l	IORequest(a4),a1
		LINKSYS	CloseDevice		; Tidy and leave
		bra	CheckMessage

ErrorTime	move.l	Windowhd(a4),a0
		lea	GeneralErr,a1
		move.l	#0,a2
		lea	AbortText,a3
		moveq	#0,d0
		moveq	#0,d1
		move	#276,d2
		moveq	#53,d3
		LINKINT	AutoRequest
		rts

		; The following code represents the standard 1.3 bootblock

SBBlock		dc.b	"DOS",0
		dc.l	$C0200F19
		dc.l	$00000370
		lea	Boot1(pc),a1
		jsr	_LVOFindResident(a6)
		tst.l	d0
		beq.s	Boot2
		move.l	d0,a0
		move.l	22(a0),a0
		moveq	#0,d0
Boot3		rts
Boot2		moveq	#-1,d0
		bra.s	Boot3
Boot1		dc.b	"dos.library"
		even
EBBlock
		; This code is the 2.04 bootblock

SNBBlock	dc.b	"DOS",0
		dc.l	$E33D0E73
		dc.l	$00000370
		lea	NBoot1(pc),a1
		moveq	#37,d0
		jsr	_LVOOpenLibrary(a6)
		tst.l	d0
		beq.s	NBoot2
		movea.l	d0,a1
		bset	#6,34(a1)
		jsr	_LVOCloseLibrary(a6)
NBoot2		lea	NBoot3(pc),a1
		jsr	_LVOFindResident(a6)
		tst.l	d0
		beq.s	NBoot4
		movea.l	d0,a0
		movea.l	22(a0),a0
		moveq	#0,d0
		rts
NBoot4		moveq	#-1,d0
		rts

NBoot3		dc.b	"dos.library",0
NBoot1		dc.b	"expansion.library",0
		even
ENBBlock
		section	Install_Data,data

MyWindow	dc.w	80,35,202,81
		dc.b	0,1
		dc.l	GADGETUP!CLOSEWINDOW
		dc.l	WINDOWDRAG!WINDOWDEPTH!WINDOWCLOSE!ACTIVATE!SMART_REFRESH
		dc.l	Gadg0,0,WindName,0,0
		dc.w	0,0,0,0,WBENCHSCREEN
WindName	dc.b	"Install v1.1",0
		even

BootMenu	dc.l	0
		dc.w	5,0,88,0,MENUENABLED
		dc.l	BootName
		dc.l	KS13
		dc.w	0,0,0,0
BootName	dc.b	"BootBlock",0
		even

KS13		dc.l	KS20
		dc.w	0,0,120+COMMWIDTH+CHECKWIDTH,10
		dc.w	HIGHCOMP!ITEMENABLED!ITEMTEXT!COMMSEQ!CHECKIT!CHECKED
		dc.l	2,KS13Name,0
		dc.b	"1",0
		dc.l	0
		dc.w	0
KS13Name	dc.b	0,1,0,0
		dc.w	1+CHECKWIDTH,1
		dc.l	0,KS13Text,0
KS13Text	dc.b	"KickStart 1.3",0
		even

KS20		dc.l	0
		dc.w	0,10,120+COMMWIDTH+CHECKWIDTH,10
		dc.w	HIGHCOMP!ITEMENABLED!ITEMTEXT!COMMSEQ!CHECKIT
		dc.l	1,KS20Name,0
		dc.b	"2",0
		dc.l	0
		dc.w	0
KS20Name	dc.b	0,1,0,0
		dc.w	1+CHECKWIDTH,1
		dc.l	0,KS20Text,0
KS20Text	dc.b	"KickStart 2.0",0
		even

Gadg0		dc.l	Gadg1
		dc.w	14,15,80,20,GADGHCOMP,RELVERIFY,BOOLGADGET
		dc.l	GadgBord1,0,Gadg0Text,0,0
		dc.w	0
		dc.l	0
Gadg0Text	dc.b	1,0,0,0
		dc.w	28,6
		dc.l	NormText,Gadg0Txt,0
Gadg0Txt	dc.b	"DF0",0
		even

Gadg1		dc.l	Gadg2
		dc.w	108,15,80,20,GADGHCOMP,RELVERIFY,BOOLGADGET
		dc.l	GadgBord1,0,Gadg1Text,0,0
		dc.w	1
		dc.l	0
Gadg1Text	dc.b	1,0,0,0
		dc.w	28,6
		dc.l	NormText,Gadg1Txt,0
Gadg1Txt	dc.b	"DF1",0
		even

Gadg2		dc.l	Gadg3
		dc.w	14,42,80,20,GADGHCOMP,RELVERIFY,BOOLGADGET
		dc.l	GadgBord1,0,Gadg2Text,0,0
		dc.w	2
		dc.l	0
Gadg2Text	dc.b	1,0,0,0
		dc.w	28,6
		dc.l	NormText,Gadg2Txt,0
Gadg2Txt	dc.b	"DF2",0
		even

Gadg3		dc.l	0
		dc.w	108,42,80,20,GADGHCOMP,RELVERIFY,BOOLGADGET
		dc.l	GadgBord1,0,Gadg3Text,0,0
		dc.w	3
		dc.l	0
Gadg3Text	dc.b	1,0,0,0
		dc.w	28,6
		dc.l	NormText,Gadg3Txt,0
Gadg3Txt	dc.b	"DF3",0
		even

CheckText	dc.b	0,0,0,0
		dc.w	9,7
		dc.l	NormText,CheckTxt,0
CheckTxt	dc.b	"Install disk in drive DF"
CheckTxtPt	dc.b	"0. Are you sure?",0
		even

Text		dc.b	1,0,0,0
		dc.w	13,0
		dc.l	NormText,Txt,0
Txt		dc.b	"© 1990 by David Kinder",0
		even

GadgBord1	dc.w	-2,-1
		dc.b	1,0,0,5
		dc.l	Coords1,GadgBord2
Coords1		dc.w	0,0,83,0,83,21,0,21,0,0

GadgBord2	dc.w	-2,-1
		dc.b	1,0,0,2
		dc.l	Coords2,GadgBord3
Coords2		dc.w	1,0,1,21

GadgBord3	dc.w	-2,-1
		dc.b	1,0,0,2
		dc.l	Coords3,0
Coords3		dc.w	82,0,82,21

x2_GBord1	dc.w	0,0
		dc.b	2,0,0,5
		dc.l	x2_Coords1,x2_GBord2
x2_Coords1	dc.w	82,0,0,0,0,21,1,20,1,0

x2_GBord2	dc.w	0,0
		dc.b	1,0,0,5
		dc.l	x2_Coords2,0
x2_Coords2	dc.w	1,21,83,21,83,0,82,1,82,21

NormText	dc.l	NormFont
		dc.w	8
		dc.b	0,0
NormFont	dc.b	"topaz.font",0
		even

TrackDisk	dc.b	"trackdisk.device",0
		even

ScreenTitle	dc.b	"Insert disk to be installed then click"
		dc.b	" on the appropriate gadget",0
		even

AbortText	dc.b	0,1,0,0
		dc.w	6,3
		dc.l	NormText,AbortTxt,0
AbortTxt	dc.b	"Abort Operation",0
		even

GeneralErr	dc.b	0,1,0,0
		dc.w	9,7
		dc.l	NormText,GeneralTxt,0
GeneralTxt	dc.b	"Cannot install specified disk",0
		even

ProtectErr	dc.b	0,1,0,0
		dc.w	9,7
		dc.l	NormText,ProtectTxt,0
ProtectTxt	dc.b	"The disk is write protected!",0
		even

NoDiskErr	dc.b	0,1,0,0
		dc.w	9,7
		dc.l	NormText,NoDiskTxt,0
NoDiskTxt	dc.b	"There is no disk in the drive!",0
		even

CYes		dc.b	0,1,0,0
		dc.w	6,3
		dc.l	NormText,TYes,0
TYes		dc.b	"Yes",0
		even

CNo		dc.b	0,1,0,0
		dc.w	6,3
		dc.l	NormText,TNo,0
TNo		dc.b	"No",0
		even

ToolType	dc.b	"NOCHECK",0
		even

DosName		DOSNAME
IconName	ICONNAME
IntName		INTNAME

		rsreset				; Install uninitialised
IORequest	rs.l	1			; data structure
MsgPort		rs.l	1
Windowhd	rs.l	1
UserPort	rs.l	1
DiskBuffer	rs.l	1
DiskBuffer1	rs.l	1
DiskBuffer2	rs.l	1
ReturnMsg	rs.l	1
_DosBase	rs.l	1
_IconBase	rs.l	1
_IntuitionBase	rs.l	1
CheckTest	rs.b	1
Data_SIZEOF	rs.b	0
