;***************************************************************************
;			InstallLibs.asm - Jeff Glatt, dissidents
;
; Set your editor's TAB width to 3.
;
; PURPOSE:
; This program facilitates copying amiga, disk-based libraries to the LIBS
; drawer of a boot disk (i.e. greatly simplifies hard disk installation of
; custom libraries). A WB user can click on this program's icon to
; install the libraries. A CLI user can CD to the directory of this program,
; and run the program. The libraries that are copied are specified by
; altering variables in this program before assembling.
;
; REQUIREMENTS:
; The programmer must modify the block of NamePtrs to reflect the
; names of the libraries to copy. All of the libraries should be placed in
; the same drawer, and PathName should reflect that. This program should
; be placed in a drawer relative to DrawerName. (i.e. the program uses the
; exact path you specify, and does not hunt for the libs.)
; Libraries must not be > 32000 bytes in size.
;
; ASSEMBLING:
; assemble this file as Install.o
; link as follows:
; blink Install.o small.lib nodebug to InstallLibs

	;C.A.P.E. assembler directives (delete these if using another asm)
	ADDSYM
	SMALLOBJ
	OBJFILE	"rad:install.o"

 ;================= from small.lib or amiga.lib (Commodore ==============
	XREF	_LVOWaitPort,_LVOGetMsg,_LVOReplyMsg
	XREF	_LVOCloseLibrary,_LVOOldOpenLibrary
	XREF	_LVODisplayAlert,_LVOCurrentDir,_LVOWrite,_LVORead,_LVOExamine
	XREF	_LVOOpen,_LVOClose,_LVODelay,_LVOOutput,_LVOLock,_LVOUnLock
	XREF	_LVOAllocMem,_LVOFreeMem

ThisTask			equ $114	;AHA! Now we don't have to use UGLY, SLOW INCLUDES!!
pr_CLI			equ $AC
pr_MsgPort		equ $5C
sm_ArgList		equ 36
wa_Lock			equ 0
TDNestCnt		equ 295
MODE_NEWFILE	equ 1006
MODE_OLDFILE	equ 1005

				bra.s	StartUp
				CNOP	0,4
CopyMsg		dc.b	'Copying '
FileInfoBlock:		;overwrite the beginning of our program to use as a File-
						;InfoBlock since we can overwrite it safely and it is
						;LONG-WORD aligned. Note: this is NOT self-modifying code.
						;Let's see you do this in C or Modula2.
DOSName		dc.b	'dos.library',0
IntuiName	dc.b	'intuition.library',0
NoMem			dc.b	'Not enough memory to do installation',0
				ds.b	30
		CNOP	0,2
StartUp:
		moveq		#0,d4					;no mem
		moveq		#0,d5					;initially, assume failure
	;---Get Exec library base
		movea.l	$0004,a6
		movea.l	a6,a4					;save SysBase
	;---get the address of our task
		movea.l	ThisTask(a6),a3
	;---Open the DOS library
		lea		DOSName(pc),a1
		jsr		_LVOOldOpenLibrary(a6)
		movea.l	d0,a5					;no error check because this is in ROM
	;---Open the Intuition library
		lea		IntuiName(pc),a1
		jsr		_LVOOldOpenLibrary(a6)
		move.l	d0,d7					;ditto
	;---are we running as a son of Workbench? If not (i.e. CLI), exit
		move.l	pr_CLI(a3),d0
		beq.s		WB
		suba.l	a3,a3
		movea.l	a5,a6
		jsr		_LVOOutput(a6)
		move.l	d0,d6
		bra.s		clii
	;---Wait for WB startup msg
WB		lea		pr_MsgPort(a3),a0
		jsr		_LVOWaitPort(a6)
		lea		pr_MsgPort(a3),a0
		jsr		_LVOGetMsg(a6)
		movea.l	d0,a3					;WB msg
		movea.l	a5,a6					;get DOSBase
	;---get the sm_ArgList list
		move.l	sm_ArgList(a3),d0
		beq.s		_ex
		movea.l	d0,a0
		move.l	(a0),d1
		jsr		_LVOCurrentDir(a6)
	;---Open a CON window to serve as DOS output window
_ex	lea		CONspec(pc),a0
		move.l	a0,d1
		moveq		#0,d2
		move.w	#MODE_NEWFILE,d2
		jsr		_LVOOpen(a6)
		move.l	d0,d6
	;---Get a 32K buffer to load/copy libs
clii	movea.l	a4,a6
		moveq		#0,d1
		moveq		#0,d0
		move.w	#32000,d0
		jsr		_LVOAllocMem(a6)
		lea		NoMem(pc),a1
		move.l	d0,d4
		beq		dspMSG
	;---Setup for loop
		movea.l	a5,a6
		lea		NamePtrs(pc),a2
		lea		FileInfoBlock(pc),a4
;=================== Copy libs (1 at a time) to LIBS: ================
NEXT:
	;---Append the next library name to our PathName
		move.l	(a2),d5
		beq		AllDone		;is this the final 0 LONG?
		lea		PathName(pc),a0
		bsr		MakeName
	;---Open the library
		moveq		#0,d2
		move.w	#MODE_OLDFILE,d2
		jsr		_LVOOpen(a6)
		move.l	d0,d5
		beq.s		fail3
	;---Print which file we are copying
		lea		CopyMsg(pc),a1
		bsr		dsp_alert
	;---Lock it
	;	You know, I really think that AmigaDOS is an incredibly bad DOS.
	;	BCPL??? No one at CBM should ever say anything bad about MS-DOS. At
	;	least MS-DOS is well-documented. Why couldn't the file handle have an
	;	easy access to the lock for the file? Because it makes good sense.
		move.l	a4,d1			;I wish that they used an Addr Reg for passing
									;the string name. Ugh!
		moveq		#-2,d2
		jsr		_LVOLock(a6)
		move.l	d0,d1
		beq.s		fail3
		move.l	d1,-(sp)
	;---Get the size of the lib, and read in the entire lib
		move.l	a4,d2
		jsr		_LVOExamine(a6)
		move.l	(sp),d1
		move.l	d0,(sp)
		jsr		_LVOUnLock(a6)
		move.l	(sp)+,d0
fail3	beq.s		faill
		move.l	124(a4),d3	;filesize
		move.l	d4,d2
		move.l	d5,d1
		jsr		_LVORead(a6)
		sub.l		d3,d0
		bne.s		faill
		move.l	d5,d1
		jsr		_LVOClose(a6)
	;---Copy our buffer (lib) to LIBS:
		lea		SysName(pc),a0
		move.l	(a2)+,d5
		bsr		MakeName
		moveq		#0,d2
		move.w	#MODE_NEWFILE,d2
		jsr		_LVOOpen(a6)
		move.l	d0,d5
		beq.s		faill
		;size still in d3
		move.l	d4,d2
		move.l	d5,d1
		jsr		_LVOWrite(a6)
		sub.l		d3,d0
		bne.s		faill
		move.l	d5,d1
		jsr		_LVOClose(a6)
		bra		NEXT
	;---Show Success or Failure message to user, then delay
faill	move.l	d5,d1
		beq.s		fail2
		jsr		_LVOClose(a6)
fail2	lea		Failure(pc),a1
		moveq		#0,d5
		bra.s		dspMSG
AllDone:
		lea		Success(pc),a1
		moveq		#1,d5
dspMSG:
		bsr		dsp_alert
;================= EXIT ROUTINE =====================
	;---close the CON window if WB
		move.l	a3,d0
		beq.s		fmem
		moveq		#127,d1
		add.l		d1,d1
		jsr		_LVODelay(a6)
		move.l	d6,d1
		beq.s		fmem
		jsr		_LVOClose(a6)
	;---Free 32K buffer
fmem	movea.l	$0004,a6
		move.l	d4,d0
		beq.s		exit
		moveq		#0,d0
		move.w	#32000,d0
		movea.l	d4,a1
		jsr		_LVOFreeMem(a6)
	;---close DOS library
exit	movea.l	a5,a1
		jsr		_LVOCloseLibrary(a6)
	;---Close Intuition
		movea.l	d7,a1
		jsr		_LVOCloseLibrary(a6)
	;---return the startup message to our parent
		move.l	a3,d0
		beq.s		ignore
		addq.b	#1,TDNestCnt(a6)
		movea.l	a3,a1
		jsr		_LVOReplyMsg(a6)
	;---adjust for our DOS cmd buffer
ignore:
	;---this rts sends us back to DOS (what a frightening prospect!)
		move.l	d5,d0
		rts

MakeName:
		;lib name in d5
		movea.l	a4,a1
		move.l	a1,d1			;put in d1 for Open()
pthn	move.b	(a0)+,(a1)+
		bne.s		pthn
		subq.l	#1,a1
		movea.l	d5,a0
libn	move.b	(a0)+,(a1)+
		bne.s		libn
		rts

;This makes an alert message out of the passed string in a1
;and displays it in our CON window, or as an Alert. 80 chars MAX in string.
;Uses a6, d2, d3. IntuitionBase in d7, DOSBase in a5, CONwindowHandle in d6.
dsp_alert:
		suba.w	#100,sp		;local buffer
		movea.l	sp,a0
		addq.l	#2,a0 		;for Alert, skip X pos
		moveq		#20,d0
		move.b	d0,(a0)+		;y co-ordinate = 20
		move.l	a0,d2			;start of string for _LVOWrite
  ;---copy passed string to buffer and get numOfChars
		movea.l	a1,a6
		moveq		#80-1,d0
lens	move.b	(a6)+,(a0)+
		Dbeq		d0,lens(pc)
		subq.l	#1,a6
		suba.l	a1,a6			;numOfChars (not counting NULL)
  ;---If our CON window open, write the msg there
		move.l	d6,d1
		beq.s		WBalert
		moveq		#10,d0
		move.b	d0,-(a0)
		move.l	a6,d3
		addq.l	#1,d3
		movea.l	a5,a6
		jsr		_LVOWrite(a6)
		bra.s		frbf
  ;---If no CON window, post an alert
WBalert:
		clr.b		(a0)			;continuation byte = 0
	;---center the string by adjusting the x position
		moveq		#80-1,d1		;80 chars MAX
		sub.l		a6,d1
		bcc.s		aler
		moveq		#1,d1
aler	lsr.l		#1,d1
		lsl.w		#3,d1
		movea.l	d2,a0
		subq.l	#3,a0
		move.w	d1,(a0)		;x co-ordinate = (numOfChars/2) * 8 (WORD)
	;---display the alert
		moveq		#50,d1		;Height
		moveq		#0,d0			;RECOVERY_ALERT
		movea.l	d7,a6
		jsr		_LVODisplayAlert(a6)
		movea.l	a5,a6			;make sure that we get DOSBase back
frbf	adda.w	#100,sp
		rts

;================== MODIFY THESE VARIABLES ==============

NamePtrs		dc.l	ReqLib	;change these to add or subtract libs
				dc.l	TextName
				dc.l	DisEdName
				dc.l	ILBMlib
				dc.l	ColorLib
				dc.l	0			;table MUST end with a 0 LONG

;These are the libraries I want to copy to the boot disk
ReqLib		dc.b	'requester.library',0
ILBMlib		dc.b	'ilbm.library',0
ColorLib		dc.b	'color.library',0
TextName		dc.b	'text_ed.library',0
DisEdName	dc.b	'dised.library',0

;This is where InstallLibs is supposed to find them. For example, I put all
;my libs in a drawer called "libs", and placed InstallLibs in this drawer's
;parent.
PathName		dc.b	'libs/',0

;==================== Don't touch this stuff ======================

SysName		dc.b	'libs:',0
Success		dc.b	'installation successful',0
Failure		dc.b	'installion failure',0
CONspec		dc.b	'CON:10/10/500/125/InstallLibs',0

