;	TurboTopaz 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+CharMem,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
		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		tf_Modulo(A0),D1
		moveq		#0,D5
		moveq		#0,D6
		move.b		tf_LoChar(A0),D5
		move.b		tf_HiChar(A0),D6
		movea.l		tf_CharData(A0),A1
		movea.l		tf_CharLoc(A0),A2
		movea.l		FMem(PC),A0
		lea		FontData-NFunc(A0),A0
		moveq		#0,D7			;0 to tf_LoChar-1 dummy characters
LowLoop		cmp.w		D5,D7
		bge.S		MidLoop
		move.l		D6,D0
		sub.l		D5,D0
		addq.l		#1,D0
		Call		CopyChar
		addq.l		#1,D7
		bra.S		LowLoop
MidLoop		cmp.w		D6,D7			;tf_LoChar to tf_HiChar real characters
		bgt.S		HighLoop
		move.l		D7,D0
		sub.l		D5,D0
		Call		CopyChar
		addq.l		#1,D7
		bra.S		MidLoop
HighLoop	cmpi.w		#255,D7			;tf_HiChar to 255 dummy characters
		bgt.S		InstallFunction
		move.l		D6,D0
		sub.l		D5,D0
		addq.l		#1,D0
		Call		CopyChar
		addq.l		#1,D7
		bra.S		HighLoop
InstallFunction
		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
		bra.S		Exit

;D0=character to copy (0-256)
;D1=tf_Modulo
;A0=where to put character
;A1=tf_CharData
;A2=tf_CharLoc
CopyChar	lsl.w		#2,D0
		move.w		(A2,D0),D0		;D0=bitoffset into tf_CharData
		lsr.w		#3,D0			;D0=byteOffset info tf_CharData
		lea		0(A1,D0.W),A3		;Here is the character bitmap
		moveq		#7,D0
CharLoop	move.b		(A3),(A0)+
		adda.w		D1,A3
		dbf		D0,CharLoop
		rts

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+CharMem,D0
		CallLib		FreeMem			;Free function and character 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

;D0=count	D1=ascii	D2=x		D3=y
;D4=count	D5=temp. A4	D6=not used	D7=not used
;A0=string	A1=RastPort	A2=bitmap data	A3=temp buffer
;A4=CharData	A5=layer	A6=GfxBase	A7=SP
* Put the code between NFunc and NFuncEnd
NFunc
OldFunc		jmp		12345678		;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 this 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-D5/A2-A5
		move.l		D0,D4
		beq.S		UnLockFunc
		move.l		(Rp),D1
		move.l		D1,A5
		beq.S		LetsWrite
		CallLib		LockLayerRom		;Commodore says this doesn't destroy registers
LetsWrite	move.l		BMem(PC),Buf		;Get BMem pointer
		move.l		Buf,D5
		lea		FontData(PC),CharData
		subq.w		#1,D0
MoveChar	moveq		#0,D1
		move.b		(A0)+,D1
		asl.w		#3,D1
		movea.l		CharData,BData
		adda.w		D1,BData		;Find bitmap-data
		move.b		(BData)+,(Buf)+
		move.b		(BData)+,1*MaxL-1(Buf)
		move.b		(BData)+,2*MaxL-1(Buf)
		move.b		(BData)+,3*MaxL-1(Buf)
		move.b		(BData)+,4*MaxL-1(Buf)
		move.b		(BData)+,5*MaxL-1(Buf)
		move.b		(BData)+,6*MaxL-1(Buf)
		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
		move.l		A5,D0
		beq.S		UnLockFunc
		CallLib		UnlockLayerRom
UnLockFunc	not.w		12345678		;This instruction will be changed by the installation
		Pop		D2-D5/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		'TurboTopaz.Port',0
NFuncEnd
FontData
MaxL		=90				;Longest string MyText can write
FuncMem		=NFuncEnd-NFunc
CharMem		=8*256
BufMem		=8*MaxL

FontTxt		dc.b		'FONT',0
NameOfFunc	dc.b		$9B,'1;33mTurboTopaz ',$9B,'0;31mV1.0 by ',$9B,'3;33mPreben Nielsen',$9B,'0;31m in 1990',LF,0
InstalledTxt	dc.b		' TurboTopaz has now been installed with '
FontName
RemovedTxt	dc.b		' TurboTopaz 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

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

