;	TempoTopaz V1.0
;	by Preben Nielsen
	OPT O+
;	OPT O1+		;Tells when a branch could be optimised to short
;	OPT i+		;Tells when '#' is probably missing

	incdir	"INCLUDE:"
	include "exec/memory.i"
	include "exec/exec_lib.i"
	include "graphics/rastport.i"
	include "graphics/text.i"
	include "graphics/graphics_lib.i"
	include "intuition/intuition.i"
	include "libraries/dos.i"
	include "libraries/dos_lib.i"
	include "libraries/diskfont.i"
	include "libraries/diskfont_lib.i"
	include "libraries/dosextens.i"
	include "Workbench/startup.i"
	include "Workbench/workbench.i"
	include "Workbench/icon_lib.i"

LF		=10

LoadBase	MACRO
		IFNC		'\1','ExecBase'
		movea.l		\1(PC),A6
		ENDC
		IFC		'\1','ExecBase'
		movea.l		4.W,A6
		ENDC
		ENDM
CallLib		MACRO
		jsr		_LVO\1(A6)
		ENDM
Call		MACRO
		bsr		\1
		ENDM
Push		MACRO
		movem.l		\1,-(SP)
		ENDM
Pop		MACRO
		movem.l		(SP)+,\1
		ENDM

Arg		EQUR		A4
ArgLen		EQUR		D4
Installed	EQUR		D7

Start		Push		D0-D7/A0-A6
		move.l		D0,ArgLen
		move.l		A0,Arg
		LoadBase	ExecBase
		lea		DosName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,DosBase
		beq		Exit
		lea		GfxName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,GfxBase
		beq		Exit
		LoadBase	GfxBase
		lea		FontAttr(PC),A0
		CallLib		OpenFont
		move.l		D0,TFont
		move.l		D0,FontCheck+2		;This makes 'cmp.l #Font,52(A1)'
		beq		Exit
FindFunc	LoadBase	ExecBase
		lea		PortName(PC),A1
		CallLib		FindPort		;Are we installed ?
		move.l		D0,Installed
		suba.l		A1,A1
		CallLib		FindTask		;Find us
		movea.l		D0,A2
		tst.l		pr_CLI(A2)
		bne.S		CLIStartup
WBenchStartup	lea		pr_MsgPort(A2),A0
		CallLib		WaitPort		;Wait for a message
		lea		pr_MsgPort(A2),A0
		CallLib		GetMsg			;Get the message
		move.l		D0,WBenchMsg		;Save it for later reply
		tst.l		Installed		;Install or Remove ?
		bne.S		CLIAndWBStartup
		moveq		#0,ArgLen		;Signal that we haven't found args yet
		move.l		D0,A2
		move.l		sm_NumArgs(A2),D0	;Any args ?
		move.l		sm_ArgList(A2),A2
		subq.l		#1,D0
		blt.S		CLIAndWBStartup
		beq.S		FoundArg
		addq.w		#wa_SIZEOF,A2
FoundArg	move.l		wa_Lock(A2),D1
		move.l		wa_Name(A2),A2		;Name of icon
		beq.S		NoLock
		LoadBase	DosBase
		CallLib		CurrentDir
NoLock		LoadBase	ExecBase
		lea		IconName(PC),A1
		CallLib		OldOpenLibrary
		move.l		D0,IconBase
		beq.S		CLIAndWBStartup
		LoadBase	IconBase
		move.l		A2,A0
		CallLib		GetDiskObject		;Get the icon
		move.l		D0,DiskObj
		beq.S		CLIAndWBStartup
		move.l		D0,A2
		move.l		do_ToolTypes(A2),A0
		lea		FontTxt(PC),A1
		CallLib		FindToolType		;Find 'FONT=??????'
		move.l		D0,Arg
		move.l		D0,ArgLen		;Signal that we have or haven't found args
		bra.S		CLIAndWBStartup
CLIStartup	subq.l		#1,ArgLen
		clr.b		0(Arg,ArgLen)
CLIAndWBStartup	tst.l		Installed		;Install or Remove ?
		beq.S		Install

Remove		move.l		Installed,A1
		lea		MyText-MyPort(A1),A1	;This is the start of the text function
		move.l		GfxBase(PC),A0
		cmpa.l		_LVOText+2(A0),A1
		lea		AlteredTxt(PC),A1
		bne		Write2Lines
		move.l		Installed,A1
		CallLib		RemPort
		move.l		Installed,A0
		CallLib		Forbid
		move.w		#NFuncEnd-NFunc,D0
		lea		NFunc(PC),A1
		lea		NFunc-MyPort(A0),A0	;This is the memory we allocated
		Call		MemCopy
		movea.w		#_LVOText,A0
		movea.l		GfxBase(PC),A1
		move.l		OldFunc+2(PC),D0	;Function to restore
		CallLib		SetFunction		;Install the old function
		tst.l		OFont			;Were we useing unmodified topaz-80
		beq.S		DoneResFont
		move.l		TFont(PC),A1		;Restore topaz-80
		lea		tf_YSize(A1),A1
		lea		TopazMisc(PC),A0
		moveq		#tf_SIZEOF-tf_YSize,D0
		move.w		tf_Accessors(A1),D1
		Call		MemCopy
		move.w		D1,tf_Accessors(A1)
DoneResFont	CallLib		Permit
		lea		RemovedTxt(PC),A1
		bra		Write2Lines

Install		tst.l		ArgLen
		ble		DoneLoadFont
		move.l		Arg,FontAttr
		LoadBase	GfxBase
		lea		FontAttr(PC),A0
		move.b		#FPB_DISKFONT,ta_Flags(A0)
		CallLib		OpenFont
		tst.l		D0
		bne.S		FoundFont
		LoadBase	ExecBase
		lea		DFName(PC),A1
		CallLib		OldOpenLibrary
		lea		NoLibTxt(PC),A1
		move.b		#LF,35(A1)		;Set a LF
		move.l		D0,DFBase
		beq		Write2Lines
		LoadBase	DFBase
		lea		FontAttr(PC),A0
		CallLib		OpenDiskFont
		move.l		D0,D7
		LoadBase	ExecBase
		movea.l		DFBase(PC),A1
		CallLib		CloseLibrary
		move.l		D7,D0
FoundFont	move.l		D0,OFont
		lea		NoFontTxt(PC),A1
		beq		Write2Lines
		move.l		D0,A0
		move.l		TFont(PC),A2
		moveq		#8,D0
		lea		Not8x8Txt(PC),A1
		cmp.w		tf_YSize(A0),D0
		bne		Write2Lines
		cmp.w		tf_XSize(A0),D0
		bne		Write2Lines
		lea		Mismatch(PC),A1
		move.w		tf_Baseline(A0),D0
		cmp.w		tf_Baseline(A2),D0
		bne		Write2Lines
		lea		CantUseProp(PC),A1
		btst		#FPB_PROPORTIONAL,tf_Flags(A0)
		bne		Write2Lines
DoneLoadFont	LoadBase	ExecBase
		move.l		#BufMem,D0
		move.l		#MEMF_CHIP!MEMF_CLEAR,D1
		CallLib		AllocMem		;Allocate memory for temporary text
		lea		NoMemTxt(PC),A1
		move.l		D0,BMem
		beq		Write2Lines
		move.l		#FuncMem,D0
		move.l		#MEMF_PUBLIC!MEMF_CLEAR,D1
		CallLib		AllocMem		;Allocate memory for function
		lea		NoMemTxt(PC),A1
		move.l		D0,FMem
		beq		Write2Lines
		CallLib		Forbid
		tst.l		OFont
		beq.S		DoneRepFont		;Shall we use unmodified topaz-80
		move.l		TFont(PC),A0		;Save something from topaz-80
		lea		tf_YSize(A0),A0
		lea		TopazMisc(PC),A1
		moveq		#tf_SIZEOF-tf_YSize,D0
		Call		MemCopy
		move.l		OFont(PC),A0		;Overwrite topaz-80
		lea		tf_YSize(A0),A0
		move.l		TFont(PC),A1
		lea		tf_YSize(A1),A1
		moveq		#tf_SIZEOF-tf_YSize,D0
		move.w		tf_Accessors(A1),D1
		Call		MemCopy
		move.w		D1,tf_Accessors(A1)
DoneRepFont	move.l		TFont(PC),A0
		moveq		#0,D0
		move.b		tf_LoChar(A0),D0
		move.w		D0,IsItLow+2		;This makes 'subi.w #tf_LoChar,D1'
		move.b		tf_HiChar(A0),D0
		sub.b		tf_LoChar(A0),D0
		move.w		D0,IsItHigh+2		;This makes 'cmpi.w #tf_HiChar-tf_LoChar,D1'
		addq.w		#1,D0
		move.w		D0,WriteDummy+2		;This makes 'move.w #tf_HiChar-tf_LoChar+1,D1'
		move.w		tf_Baseline(A0),D0
		andi.w		#%0000000000000111,D0
		lsl.w		#8,D0
		lsl.w		#1,D0
		ori.w		#%0101000101000011,D0
		move.w		D0,SubBaseLine		;We just made a subq.w tf_baseline,D3
		move.w		#NFuncEnd-NFunc,D0
		lea		NFunc(PC),A0
		movea.l		FMem(PC),A1
		movea.l		A1,A2
		Call		MemCopy
		LoadBase	ExecBase
		lea		MyPort-NFunc(A2),A1
		lea		PortName-NFunc(A2),A0
		move.l		A0,10(A1)		;Set portname
		CallLib		AddPort		
		moveq		#MyText-NFunc,D0
		add.l		A2,D0
		lea		FontCheck+2-NFunc(A2),A1
		move.l		A1,LockFunc+2-NFunc(A2)			;\
		move.l		A1,UnLockFunc+2-NFunc(A2)		; \Modify some absolute code
		move.l		GfxBase(PC),A1				; /
		move.l		_LVOText+2(A1),OldFunc+2-NFunc(A2)	;/Save the address of the old 'Text' function
		move.w		#_LVOText,A0
		CallLib		SetFunction
		move.l		D0,OldFunc+2-NFunc(A2)	;Save the address of the old 'Text' function
		clr.l		BMem			;\
		clr.l		FMem			; >Don't free memory until we are re-run
		clr.l		OFont			;/
		CallLib		Permit
		lea		FontName(PC),A1
		move.l		FontAttr(PC),A0
CopyFName	move.b		(A0)+,(A1)+
		bne.S		CopyFName
		move.b		#LF,-1(A1)
		clr.b		(A1)
		lea		InstalledTxt(PC),A1
Write2Lines	Call		OpenCON			;A0/A1=First/Second line
		lea		NameOfFunc(PC),A0
		Call		WriteCON
		move.l		A1,A0
		Call		WriteCON
		Call		CloseCON

Exit
FreeTopaz	LoadBase	GfxBase
		move.l		TFont(PC),D0
		beq.S		FreeFont
		movea.l		D0,A1
		CallLib		CloseFont
FreeFont	move.l		OFont(PC),D0
		beq.S		FreeBMem
		movea.l		D0,A1
		CallLib		CloseFont
FreeBMem	LoadBase	ExecBase
		move.l		BMem(PC),D0
		beq.S		FreeFMem
		movea.l		D0,A1
		move.l		#BufMem,D0
		CallLib		FreeMem			;Free temporary buffer
FreeFMem	move.l		FMem(PC),D0
		beq.S		FreeGfx
		movea.l		D0,A1
		move.l		#FuncMem,D0
		CallLib		FreeMem			;Free function memory
FreeGfx		move.l		GfxBase(PC),D0
		beq.S		FreeDos
		movea.l		D0,A1
		CallLib		CloseLibrary
FreeDos		move.l		DosBase(PC),D0
		beq.S		Flush
		movea.l		D0,A1
		CallLib		CloseLibrary
Flush		moveq		#0,D1			;Flush unused libs, fonts etc.
		move.l		#$FFFFFF,d0
		CallLib		AllocMem
ReplyWB		move.l		WBenchMsg(PC),D0
		beq.S		AllDone
		move.l		DiskObj(PC),D0
		beq.S		FreeIcon
		move.l		D0,A0
		LoadBase	IconBase
		CallLib		FreeDiskObject
FreeIcon	LoadBase	ExecBase	
		move.l		IconBase(PC),D0
		beq.S		WBEnd
		move.l		D0,A1
		CallLib		CloseLibrary
WBEnd		CallLib		Forbid
		movea.l		WBenchMsg(PC),A1
		CallLib		ReplyMsg		;Reply WBenchMessage if we are started from WB
AllDone		Pop		D0-D7/A0-A6
		moveq		#0,D0
		rts

OpenCON		Push		D0-D7/A0-A6
		LoadBase	DosBase
		tst.l		WBenchMsg
		beq.S		FromCLI
FromWB		move.l		#CONName,D1
		move.l		#MODE_OLDFILE,D2
		CallLib		Open
		bra.S		DoneOpen
FromCLI		CallLib		Output
DoneOpen	move.l		D0,Handle
		bra.S		DoneCON
;A0=NULL terminated text to write
WriteCON	Push		D0-D7/A0-A6
		LoadBase	DosBase
		move.l		Handle(PC),D1
		beq.S		DoneCON
		move.l		A0,D2
		moveq		#-1,D3
strlenLoop	addq.l		#1,D3
		tst.b		(A0)+
		bne.S		strlenLoop
		CallLib		Write
		bra.S		DoneCON
CloseCON	Push		D0-D7/A0-A6
		LoadBase	DosBase
		move.l		Handle(PC),D2
		beq.S		DoneCON
		tst.l		WBenchMsg
		beq.S		DoneCON
		move.l		#150,D1
		CallLib		Delay
		move.l		D2,D1
		CallLib		Close
DoneCON		Pop		D0-D7/A0-A6
		rts

;A0=Source, A1=Dest, D0:16=Count
MemCopy		Push		D0/A0-A1
		subq.w		#1,D0
MemLoop		move.b		(A0)+,(A1)+
		dbf		D0,MemLoop
		Pop		D0/A0-A1
		rts


;================ Here comes the new Text-Function =================
Rp		EQUR		A1
BData		EQUR		A2
Buf		EQUR		A3
CharData	EQUR		A4
CharLoc		EQUR		A5
Modulo		EQUR		D6

;D0=count	D1=ascii	D2=x		D3=y
;D4=count	D5=temp. A4	D6=tf_Modulo	D7=layer
;A0=string	A1=RastPort	A2=bitmap data	A3=temp buffer
;A4=tf_CharData	A5=tf_CharLoc	A6=GfxBase	A7=SP
* Put the code between NFunc and NFuncEnd
NFunc
OldFunc		jmp		123455678		;This instruction will be changed by the installation
MyText		tst.b		rp_AlgoStyle(Rp)	;We can only write strings with style 0
		bne.S		OldFunc
		cmpi.w		#MaxL,D0		;Is string too long for MyText
		bgt.S		OldFunc
FontCheck	cmp.l		#12345678,rp_Font(Rp)	;This instruction will be changed by the installation
		bne.S		OldFunc
LockFunc	not.w		12345678		;This instruction will be changed by the installation
		Push		D2-D7/A2-A5
		move.l		D0,D4
		beq		UnLockFunc
		move.l		(Rp),D7
		beq.S		LetsWrite
		move.l		D7,A5
		CallLib		LockLayerRom		;Commodore says this doesn't destroy registers
LetsWrite	movem.l		BMem(PC),Buf/A4		;Get BMem/Font pointers
		move.l		Buf,D5
		move.w		tf_Modulo(A4),Modulo
		move.l		tf_CharLoc(A4),CharLoc
		move.l		tf_CharData(A4),CharData
		subq.w		#1,D0
MoveChar	moveq		#0,D1
		move.b		(A0)+,D1
IsItLow		subi.w		#12345,D1		;This instruction will be changed by the installation
		bmi.S		WriteDummy
IsItHigh	cmpi.w		#12345,D1		;This instruction will be changed by the installation
		ble.S		Cont	
WriteDummy	move.w		#12345,D1		;This instruction will be changed by the installation
Cont		add.w		D1,D1
		add.w		D1,D1
		move.w		0(CharLoc,D1),D1	;D1=bitoffset into tf_CharData
		lsr.w		#3,D1			;D1=byteOffset info tf_CharData
		movea.l		CharData,BData
		adda.w		D1,BData		;Here is the character bitmap
		move.b		(BData),(Buf)+
		add.w		Modulo,BData
		move.b		(BData),1*MaxL-1(Buf)
		add.w		Modulo,BData
		move.b		(BData),2*MaxL-1(Buf)
		add.w		Modulo,BData
		move.b		(BData),3*MaxL-1(Buf)
		add.w		Modulo,BData
		move.b		(BData),4*MaxL-1(Buf)
		add.w		Modulo,BData
		move.b		(BData),5*MaxL-1(Buf)
		add.w		Modulo,BData
		move.b		(BData),6*MaxL-1(Buf)
		add.w		Modulo,BData
		move.b		(BData),7*MaxL-1(Buf)
		dbra		D0,MoveChar
		move.l		D5,A0
		moveq		#0,D0
		moveq		#MaxL,D1
		movem.w		rp_cp_x(Rp),D2-D3
SubBaseLine	subq.w		#1,D3			;This instruction will be changed by the installation
		lsl.w		#3,D4
		add.w		D4,rp_cp_x(Rp)
		moveq		#8,D5			;Height
		CallLib		BltTemplate
		tst.l		D7
		beq.S		UnLockFunc
		move.l		D7,A5
		CallLib		UnlockLayerRom
UnLockFunc	not.w		12345678		;This instruction will be changed by the installation
		Pop		D2-D7/A2-A5
		jmp		_LVOWaitBlit(A6)
FMem		dc.l		0
BMem		dc.l		0			;Buffer to blit from
TFont		dc.l		0
OFont		dc.l		0
TopazMisc	dcb.b		tf_SIZEOF-tf_YSize,0
MyPort
;struct MsgPort {
;		struct Node {	;struct  Node mp_Node; 
		dc.l		0	;struct  Node *ln_Succ;
		dc.l		0	;struct  Node *ln_Pred;
		dc.b		0	;UBYTE   ln_Type;
		dc.b		0	;BYTE    ln_Pri; 
		dc.l		PortName;char    *ln_Name; 
;		}
		dc.b		0	;UBYTE   mp_Flags; 
		dc.b		0	;UBYTE   mp_SigBit;
		dc.l		0	;struct  Task *mp_SigTask;
;		struct List {	;struct  List mp_MsgList;
		dc.l		0	;struct  Node *lh_Head;
		dc.l		0	;struct  Node *lh_Tail;
		dc.l		0	;struct  Node *lh_TailPred;
		dc.b		0	;UBYTE   lh_Type;
		dc.b		0	;UBYTE   l_pad;
;		}
;}
PortName	dc.b		'TempoTopaz.Port',0
NFuncEnd
MaxL		=90				;Longest string MyText can write
FuncMem		=NFuncEnd-NFunc
BufMem		=8*MaxL

FontTxt		dc.b		'FONT',0
NameOfFunc	dc.b		$9B,'1;33mTempoTopaz ',$9B,'0;31mV1.0 by ',$9B,'3;33mPreben Nielsen',$9B,'0;31m in 1990',LF,0
InstalledTxt	dc.b		' TempoTopaz has now been installed with '
FontName
RemovedTxt	dc.b		' TempoTopaz has now been removed',LF,0
AlteredTxt	dc.b		" ERROR: The 'Text' Vector has been changed. Can't remove",LF,0
Mismatch	dc.b		" ERROR: Baseline mismatch",LF,0
CantUseProp	dc.b		" ERROR: Can't use Proportional font",LF,0
Not8x8Txt	dc.b		" ERROR: Not a 8x8 font",LF,0
NoFontTxt	dc.b		" ERROR: Can't open font",LF,0
NoMemTxt	dc.b		" ERROR: Can't get memory",LF,0
NoLibTxt	dc.b		" ERROR: Can't open "
DFName		dc.b		'diskfont.library',0,0
DosName		dc.b		'dos.library',0
GfxName		dc.b		'graphics.library',0
IconName	dc.b		'icon.library',0
CONName		dc.b		'CON:40/40/500/45/This window goes away after 3 seconds',0
		EVEN
DiskObj		dc.l		0
DosBase		dc.l		0
GfxBase		dc.l		0
DFBase		dc.l		0
IconBase	dc.l		0
WBenchMsg	dc.l		0
Handle		dc.l		0

		EVEN
FontAttr	dc.l		TopazName
		dc.w		TOPAZ_EIGHTY
		dc.b		FS_NORMAL,FPB_ROMFONT
TopazName	dc.b		'topaz.font',0
		END

