***************************************************************
**
** LetterMatcher - matches font characters with bitmap data
**
** v1.0 - 12/08/93 by Henri Veisterä
**
** LetterMatcher is PD.  Do whit it what ever you want.
** If you want to distribute modified versions of LetterMatcher
** indicate somewhere in the distribution that it is a
** modified version.
**
***************************************************************

	opt	o+,c+

        include	exec/exec.i
        include	exec/exec_lib.i

        include dos/dos_lib.i

	include	libraries/dosextens.i
	include	libraries/diskfont_lib.i

	include graphics/graphics_lib.i
	include graphics/text.i

	include	devices/timer.i
	include	devices/timer_lib.i

CALLGFX MACRO
        move.l  _GfxBase(pc),a6
        jsr     _LVO\1(a6)
        ENDM

	move.l	$4,_ExecBase

	movem.l	d0/a0,-(sp)		save initial values
	clr.l	returnMsg

	sub.l	a1,a1
	CALLEXEC FindTask		find us
	move.l	d0,a4

	tst.l	pr_CLI(a4)
	beq.s	fromWorkbench

	movem.l	(sp)+,d0/a0		restore regs
	bra.s	end_startup		and run the user prog

fromWorkbench
	lea	pr_MsgPort(a4),a0
	CALLEXEC WaitPort		wait for a message
	lea	pr_MsgPort(a4),a0
	CALLEXEC GetMsg			then get it
	move.l	d0,returnMsg		save it for later reply

	movem.l	(sp)+,d0/a0		restore
end_startup
	bsr.s	_main			call our program

	move.l	d0,-(sp)		save it

	tst.l	returnMsg
	beq.s	exitToDOS		if I was a CLI

	CALLEXEC Forbid
	move.l	returnMsg(pc),a1
	CALLEXEC ReplyMsg

exitToDOS
	move.l	(sp)+,d0		exit code
	rts

versio	dc.b	"$VER: LetterMatcher 1.0 (1993-08-12) by Henri Veisterä",0
	cnop	0,4
_main	
	move.l	a0,line
	move.l	d0,linel
	
	lea     dosname(pc),a1
        moveq   #0,d0
        CALLEXEC OpenLibrary
        move.l  d0,_DOSBase
        beq     exit

        tst.l	returnMsg
        beq.s	clioutput

        lea	errorcon(pc),a0
        move.l	a0,d1
        move.l	#MODE_NEWFILE,d2
        CALLDOS Open
        move.l	d0,outfile
        beq	closedos

	bra.s	ercon

clioutput
        CALLDOS Output
        move.l  d0,outfile
ercon

* Parse command line options

	move.l	line(pc),a0
	move.l	linel(pc),d0
	lea	-1(a0,d0.l),a1

	cmp.l	a0,a1
	ble	usage
	bsr	nexta
uuess	cmp.b	#'-',(a0)
	bne	noswit
uues	cmp.b	#'s',1(a0)
	beq.s	yestr
	cmp.b	#'S',1(a0)
	beq.s	yestr
	cmp.b	#'m',1(a0)
	beq.s	yesibm
	cmp.b	#'M',1(a0)
	beq.s	yesibm
	cmp.b	#'l',1(a0)
	beq.s	yesloos
	cmp.b	#'L',1(a0)
	beq.s	yesloos
	cmp.b	#'t',1(a0)
	beq.s	yestime
	cmp.b	#'T',1(a0)
	beq.s	yestime
	cmp.b	#'q',1(a0)
	beq.s	yesquie
	cmp.b	#'Q',1(a0)
	beq.s	yesquie

uhsa	addq.l	#1,a0
	cmp.b	#32,(a0)
	bhi.s	uues
	bsr	nexta
	bra.s	uuess

yestr	move.w	#1,strip
	bra.s	uhsa
yesibm	move.w	#1,ibm
	bra.s	uhsa
yesloos	move.w	#1,loose
	bra.s	uhsa
yestime	move.w	#1,timeit
	bra.s	uhsa
yesquie	move.w	#1,quiet
	bra.s	uhsa

noswit	move.l	a0,outname
	bsr	nextb
	clr.b	(a0)
	addq.l	#1,a0
	cmp.l	a0,a1
	ble	usage
	bsr	nexta
	move.l	a0,rawname
	bsr	nextb
	clr.b	(a0)
	addq.l	#1,a0
	cmp.l	a0,a1
	ble	usage
	bsr	nexta
	bsr	atoi
	move.l	d0,d1
	beq	usage
	cmp.l	#2048,d0
	bgt	usage
	asr.l	#3,d0
	move.l	d0,picw
	beq	usage
	and.w	#$7,d1
	beq.s	oke
	lea	non8(pc),a0
	bsr	print
	bra	closecli
oke	cmp.l	a0,a1
	ble	usage
	bsr	nexta
	bsr	atoi
	and.b	#$f8,d0
	move.l	d0,pich
	beq	usage
	cmp.l	a0,a1
	ble	endcli
	bsr	nexta
	move.l	a0,parseline
	bsr	nextb
	move.l	a0,parseend
	cmp.l	a0,a1
	ble	endcli
	bsr	nexta
	move.l	a0,fontname
	bsr	nextb
	clr.b	(a0)
	bra	endcli

nexta	cmp.b	#33,(a0)
	bcs.s	uhhoh
	cmp.b	#'"',(a0)
	bne.s	noqu
	moveq	#1,d1
	addq.l	#1,a0
	rts
noqu	moveq	#0,d1
	rts
uhhoh	addq.l	#1,a0
	cmp.l	a0,a1
	bgt.s	nexta
	rts

nextb	tst.w	d1
	beq.s	kelp
nextbl	cmp.b	#'"',(a0)
	beq.s	endi
	addq.l	#1,a0
	cmp.l	a0,a1
	bgt.s	nextbl
	rts
kelp	cmp.b	#33,(a0)
	bcs.s	endi
	addq.l	#1,a0
	cmp.l	a0,a1
	bgt.s	kelp
endi	rts

* Print out usage if no good options were given

usage	lea	usages(pc),a0
	bsr	print
	bra	closecli

* Open input and output files and allocate memory for input file
* and read it

endcli	move.l	outname(pc),d1
	move.l	#MODE_NEWFILE,d2
	CALLDOS Open
	move.l	d0,myfile
	bne.s	got

	lea	nooutp(pc),a0
	lea	datas(pc),a1
	move.l	outname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	closecli

got	move.l	rawname(pc),d1
	move.l	#MODE_OLDFILE,d2
	CALLDOS Open
	move.l	d0,rawfile
	bne.s	gotr

	lea	noraw(pc),a0
	lea	datas(pc),a1
	move.l	rawname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	closeout

gotr	move.l  d0,d1
	moveq	#0,d2
	moveq	#1,d3
	CALLDOS Seek
	move.l  rawfile(pc),d1
	moveq	#0,d2
	moveq	#-1,d3
	CALLDOS Seek
	move.l	d0,rawsize
	bne.s	gots

	lea	noraw2(pc),a0
	lea	datas(pc),a1
	move.l	rawname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	closeraw

gots	move.l	#MEMF_ANY,d1
	CALLEXEC AllocMem
	move.l	d0,picture
	bne.s	gotp

	lea	nomem(pc),a0
	lea	datas(pc),a1
	move.l	rawsize(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	closeraw

gotp	move.l	rawfile(pc),d1
	move.l	picture(pc),d2
	move.l	rawsize(pc),d3
	CALLDOS Read
	cmp.l	d0,d3
	beq.s	gota

	lea	noraw3(pc),a0
	lea	datas(pc),a1
	move.l	rawname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	freeraw

* Parse the given FontRange, place a -1 for every character in
* byte array chart to be used in matching, otherwise zero

gota	move.l	parseline(pc),a0
	move.l	parseend(pc),a2
	lea	chart(pc),a1

norange	cmp.l	a0,a2
	ble	endpars
	bsr	nextt
	bsr	atoh
	bsr	chemi
	tst.w	d1
	bne.s	range
	move.b	#-1,(a1,d0.l)
	bra.s	norange

range	lea	(a1,d0.l),a4
	bsr	atoh
	lea	(a1,d0.l),a3
poixx	cmp.l	a4,a3
	blt.s	norange
	move.b	#-1,(a4)+
	bra.s	poixx

chemi	moveq	#0,d1
chemil	cmp.b	#'0',(a0)
	bcs.s	ojki
	cmp.b	#'9',(a0)
	bhi.s	ojki
	rts
ojki	cmp.b	#'-',(a0)+
	beq.s	chemis
	cmp.l	a0,a2
	bgt.s	chemil
outsd	rts
chemis	moveq	#1,d1
	cmp.l	a0,a2
	bgt.s	chemil
	rts

nextt	cmp.b	#'0',(a0)
	bcs.s	poij
	cmp.b	#'9',(a0)
	bhi.s	poij
	rts
poij	addq.l	#1,a0
	cmp.l	a0,a2
	bgt.s	nextt
	rts

atoh	moveq	#0,d0
	moveq	#0,d1
atohl	cmp.b	#'0',(a0)
	bcs.s	poij2
	cmp.b	#'9',(a0)
	bhi.s	poij2
	move.b	(a0)+,d1
	sub.b	#'0',d1
	move.l	d0,d2
	asl.l	#3,d0
	add.l	d2,d0
	add.l	d2,d0
	add.l	d1,d0
	bra	atohl
poij2	cmp.l	#256,d0
	blt.s	oks
	move.l	#255,d0
oks	rts

atoi	moveq	#0,d0
	moveq	#0,d1
atoil	cmp.b	#'0',(a0)
	bcs.s	poij3
	cmp.b	#'9',(a0)
	bhi.s	poij3
	move.b	(a0)+,d1
	sub.b	#'0',d1
	move.l	d0,d2
	asl.l	#3,d0
	add.l	d2,d0
	add.l	d2,d0
	add.l	d1,d0
	bra.s	atoil
poij3	rts

* Open misc libraries, devices and fonts

endpars	lea     gfxname(pc),a1
        moveq   #0,d0
        CALLEXEC OpenLibrary
        move.l  d0,_GfxBase
	bne.s	gotgf
	lea	nogfx(pc),a0
	bsr	print
        bra     freeraw

gotgf	lea	dfname(pc),a1
	moveq	#0,d0
	CALLEXEC OpenLibrary
	move.l	d0,_DiskfontBase
	bne.s	gotdf
	lea	nodf(pc),a0
	bsr	print
        bra     closegfx

gotdf	CALLEXEC CreateMsgPort
	move.l	d0,myport
	beq	closedf

	move.l	d0,a0
	move.b	MP_SIGBIT(a0),sigbit
	move.l	#IOTV_SIZE,d0
	CALLEXEC CreateIORequest
	move.l	d0,myioreq
	beq	cl_port

	lea	timer_name(pc),a0
	moveq.l	#0,d0			;unit
	move.l	myioreq(pc),a1
	moveq.l	#0,d1			;flags
	CALLEXEC OpenDevice

	lea	mytattr(pc),a0
	move.l	fontname(pc),(a0)
	CALLDISKFONT OpenDiskFont
	move.l	d0,myfont
	bne.s	gotfo

* Could not open font

	lea	nofont1(pc),a0
	lea	datas(pc),a1
	move.l	fontname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	cl_timer

gotfo	move.l	myfont(pc),a0
	btst	#FPB_PROPORTIONAL,tf_Flags(a0)
	beq.s	noprop

* Font is proportional, exit

	lea	nofont2(pc),a0
	lea	datas(pc),a1
	move.l	fontname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	cl_timer

noprop	move.l	tf_CharData(a0),fontdata
	move.l	tf_CharLoc(a0),charloc
	move.w	tf_Modulo(a0),fontmod+2
	move.b	tf_LoChar(a0),lowchar+3
	move.b	tf_HiChar(a0),hichar+3
	move.w	tf_YSize(a0),ysize
	subq.w	#1,ysize
	move.w	tf_XSize(a0),d0
	cmp.w	#8,d0
	beq.s	okwi

* Font width is not 8 pixels, exit

	lea	nofont3(pc),a0
	lea	datas(pc),a1
	move.l	fontname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	cl_timer

okwi	move.l	hichar(pc),d6
	sub.l	lowchar(pc),d6
	subq.l	#1,d6
	move.w	d6,nochars

	move.l	rawsize(pc),d0
	divu.w	picw+2(pc),d0
	cmp.w	pich+2(pc),d0
	bge.s	ums
	and.b	#$f8,d0
	move.w	d0,pich+2

ums	move.l	#0,pich2

* Allocate memory for linear font bitmap data

	moveq	#1,d0
	add.w	nochars(pc),d0
	asl.l	#3,d0
	move.l	d0,fontmapsize
	move.l	#MEMF_ANY,d1
	CALLEXEC AllocMem
	move.l	d0,fontmap
	bne.s	gotfm

* Out of memory, exit

	lea	nomem(pc),a0
	lea	datas(pc),a1
	move.l	fontmapsize(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	closefont

* Copy the bitplane font data to linear form so we can match it
* long word at a time

gotfm	move.l	fontdata(pc),a2
	move.l	charloc(pc),a3
	move.l	fontmap(pc),a1
	move.l	fontmod(pc),d0
	move.w	nochars(pc),d1
loopi	move.w	(a3)+,d2
	asr.w	#3,d2
	lea	(a2,d2.w),a0
	addq.l	#2,a3
	move.b	(a0),(a1)+
	add.l	d0,a0
	move.b	(a0),(a1)+
	add.l	d0,a0
	move.b	(a0),(a1)+
	add.l	d0,a0
	move.b	(a0),(a1)+
	add.l	d0,a0
	move.b	(a0),(a1)+
	add.l	d0,a0
	move.b	(a0),(a1)+
	add.l	d0,a0
	move.b	(a0),(a1)+
	add.l	d0,a0
	move.b	(a0),(a1)+
	dbf	d1,loopi

	tst.w	quiet
	bne.s	nouut

* Print status info to CLI

	lea	report(pc),a0
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	datas(pc),a1
	move.l	pich2(pc),(a1)
	move.l	pich(pc),4(a1)
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

* Start time constant

nouut	move.l	myioreq(pc),a2
	move.l	IO_DEVICE(a2),a6
	lea	IOTV_TIME(a2),a0
	jsr	_LVOReadEClock(a6)
	move.l	EV_HI+IOTV_TIME(a2),time1
	move.l	EV_LO+IOTV_TIME(a2),time2

* Start matching the picture

	move.l	picture(pc),a0
	move.l	picw(pc),d3

allrows	move.l	picw(pc),d5
	subq.l	#1,d5
	lea	outline(pc),a2

allcols	move.l	d5,-(sp)

	lea	chart(pc),a4
	add.l	lowchar(pc),a4
	move.w	nochars(pc),d6
	moveq	#0,d5
	move.l	lowchar(pc),d4

* Copy the bitmap source data to linear form

	movem.l	a0,-(sp)
	lea	vert(pc),a1
	move.b	(a0),(a1)+
	add.l	d3,a0
	move.b	(a0),(a1)+
	add.l	d3,a0
	move.b	(a0),(a1)+
	add.l	d3,a0
	move.b	(a0),(a1)+
	add.l	d3,a0
	move.b	(a0),(a1)+
	add.l	d3,a0
	move.b	(a0),(a1)+
	add.l	d3,a0
	move.b	(a0),(a1)+
	add.l	d3,a0
	move.b	(a0),(a1)+
	move.l	fontmap(pc),a1

* Test if to use loose matching

	tst.w	loose
	bne	loosema

* Innermost loop, match source bitmap with all font characters

allxs	tst.b	(a4)+
	beq	nobigis

	moveq	#0,d7
	move.l	vert(pc),d0
	move.l	(a1)+,d1
	eor.l	d1,d0

* Count matching bits

	btst	#0,d0
	bne.s	noad401
	addq	#1,d7
noad401	btst	#1,d0
	bne.s	noad402
	addq	#1,d7
noad402	btst	#2,d0
	bne.s	noad403
	addq	#1,d7
noad403	btst	#3,d0
	bne.s	noad404
	addq	#1,d7
noad404	btst	#4,d0
	bne.s	noad405
	addq	#1,d7
noad405	btst	#5,d0
	bne.s	noad406
	addq	#1,d7
noad406	btst	#6,d0
	bne.s	noad407
	addq	#1,d7
noad407	btst	#7,d0
	bne.s	noad408
	addq	#1,d7
noad408	btst	#8,d0
	bne.s	noad409
	addq	#1,d7
noad409	btst	#9,d0
	bne.s	noad410
	addq	#1,d7
noad410	btst	#10,d0
	bne.s	noad411
	addq	#1,d7
noad411	btst	#11,d0
	bne.s	noad412
	addq	#1,d7
noad412	btst	#12,d0
	bne.s	noad413
	addq	#1,d7
noad413	btst	#13,d0
	bne.s	noad414
	addq	#1,d7
noad414	btst	#14,d0
	bne.s	noad415
	addq	#1,d7
noad415	btst	#15,d0
	bne.s	noad416
	addq	#1,d7
noad416	btst	#16,d0
	bne.s	noad417
	addq	#1,d7
noad417	btst	#17,d0
	bne.s	noad418
	addq	#1,d7
noad418	btst	#18,d0
	bne.s	noad419
	addq	#1,d7
noad419	btst	#19,d0
	bne.s	noad420
	addq	#1,d7
noad420	btst	#20,d0
	bne.s	noad421
	addq	#1,d7
noad421	btst	#21,d0
	bne.s	noad422
	addq	#1,d7
noad422	btst	#22,d0
	bne.s	noad423
	addq	#1,d7
noad423	btst	#23,d0
	bne.s	noad424
	addq	#1,d7
noad424	btst	#24,d0
	bne.s	noad425
	addq	#1,d7
noad425	btst	#25,d0
	bne.s	noad426
	addq	#1,d7
noad426	btst	#26,d0
	bne.s	noad427
	addq	#1,d7
noad427	btst	#27,d0
	bne.s	noad428
	addq	#1,d7
noad428	btst	#28,d0
	bne.s	noad429
	addq	#1,d7
noad429	btst	#29,d0
	bne.s	noad430
	addq	#1,d7
noad430	btst	#30,d0
	bne.s	noad431
	addq	#1,d7
noad431	btst	#31,d0
	bne.s	noad432
	addq	#1,d7
noad432

	move.l	vert+4(pc),d0
	move.l	(a1)+,d1
	eor.l	d1,d0

	btst	#0,d0
	bne.s	noad501
	addq	#1,d7
noad501	btst	#1,d0
	bne.s	noad502
	addq	#1,d7
noad502	btst	#2,d0
	bne.s	noad503
	addq	#1,d7
noad503	btst	#3,d0
	bne.s	noad504
	addq	#1,d7
noad504	btst	#4,d0
	bne.s	noad505
	addq	#1,d7
noad505	btst	#5,d0
	bne.s	noad506
	addq	#1,d7
noad506	btst	#6,d0
	bne.s	noad507
	addq	#1,d7
noad507	btst	#7,d0
	bne.s	noad508
	addq	#1,d7
noad508	btst	#8,d0
	bne.s	noad509
	addq	#1,d7
noad509	btst	#9,d0
	bne.s	noad510
	addq	#1,d7
noad510	btst	#10,d0
	bne.s	noad511
	addq	#1,d7
noad511	btst	#11,d0
	bne.s	noad512
	addq	#1,d7
noad512	btst	#12,d0
	bne.s	noad513
	addq	#1,d7
noad513	btst	#13,d0
	bne.s	noad514
	addq	#1,d7
noad514	btst	#14,d0
	bne.s	noad515
	addq	#1,d7
noad515	btst	#15,d0
	bne.s	noad516
	addq	#1,d7
noad516	btst	#16,d0
	bne.s	noad517
	addq	#1,d7
noad517	btst	#17,d0
	bne.s	noad518
	addq	#1,d7
noad518	btst	#18,d0
	bne.s	noad519
	addq	#1,d7
noad519	btst	#19,d0
	bne.s	noad520
	addq	#1,d7
noad520	btst	#20,d0
	bne.s	noad521
	addq	#1,d7
noad521	btst	#21,d0
	bne.s	noad522
	addq	#1,d7
noad522	btst	#22,d0
	bne.s	noad523
	addq	#1,d7
noad523	btst	#23,d0
	bne.s	noad524
	addq	#1,d7
noad524	btst	#24,d0
	bne.s	noad525
	addq	#1,d7
noad525	btst	#25,d0
	bne.s	noad526
	addq	#1,d7
noad526	btst	#26,d0
	bne.s	noad527
	addq	#1,d7
noad527	btst	#27,d0
	bne.s	noad528
	addq	#1,d7
noad528	btst	#28,d0
	bne.s	noad529
	addq	#1,d7
noad529	btst	#29,d0
	bne.s	noad530
	addq	#1,d7
noad530	btst	#30,d0
	bne.s	noad531
	addq	#1,d7
noad531	btst	#31,d0
	bne.s	noad532
	addq	#1,d7
noad532

	cmp.w	d5,d7
	bls.s	bobib
	move.w	d4,biguns+2
	move.w	d7,d5
	cmp.b	#64,d7
	bne.s	bobib
	movem.l	(sp)+,a0
	bra	tiktis
nobigis	addq.l	#8,a1
bobib	addq.l	#1,d4
	dbf	d6,allxs

	movem.l	(sp)+,a0
	bra	tiktis

loosema	tst.b	(a4)+
	beq	nobigu2

	moveq	#0,d7
	move.l	vert(pc),d0
	move.l	(a1)+,d1
	eor.l	d1,d0
	move.l	d0,-(sp)
	move.l	vert+4(pc),d0
	move.l	(a1)+,d1
	eor.l	d1,d0
	or.l	(sp)+,d0

	btst	#0,d0
	bne.s	noad301
	addq	#1,d7
noad301	btst	#1,d0
	bne.s	noad302
	addq	#1,d7
noad302	btst	#2,d0
	bne.s	noad303
	addq	#1,d7
noad303	btst	#3,d0
	bne.s	noad304
	addq	#1,d7
noad304	btst	#4,d0
	bne.s	noad305
	addq	#1,d7
noad305	btst	#5,d0
	bne.s	noad306
	addq	#1,d7
noad306	btst	#6,d0
	bne.s	noad307
	addq	#1,d7
noad307	btst	#7,d0
	bne.s	noad308
	addq	#1,d7
noad308	btst	#8,d0
	bne.s	noad309
	addq	#1,d7
noad309	btst	#9,d0
	bne.s	noad310
	addq	#1,d7
noad310	btst	#10,d0
	bne.s	noad311
	addq	#1,d7
noad311	btst	#11,d0
	bne.s	noad312
	addq	#1,d7
noad312	btst	#12,d0
	bne.s	noad313
	addq	#1,d7
noad313	btst	#13,d0
	bne.s	noad314
	addq	#1,d7
noad314	btst	#14,d0
	bne.s	noad315
	addq	#1,d7
noad315	btst	#15,d0
	bne.s	noad316
	addq	#1,d7
noad316	btst	#16,d0
	bne.s	noad317
	addq	#1,d7
noad317	btst	#17,d0
	bne.s	noad318
	addq	#1,d7
noad318	btst	#18,d0
	bne.s	noad319
	addq	#1,d7
noad319	btst	#19,d0
	bne.s	noad320
	addq	#1,d7
noad320	btst	#20,d0
	bne.s	noad321
	addq	#1,d7
noad321	btst	#21,d0
	bne.s	noad322
	addq	#1,d7
noad322	btst	#22,d0
	bne.s	noad323
	addq	#1,d7
noad323	btst	#23,d0
	bne.s	noad324
	addq	#1,d7
noad324	btst	#24,d0
	bne.s	noad325
	addq	#1,d7
noad325	btst	#25,d0
	bne.s	noad326
	addq	#1,d7
noad326	btst	#26,d0
	bne.s	noad327
	addq	#1,d7
noad327	btst	#27,d0
	bne.s	noad328
	addq	#1,d7
noad328	btst	#28,d0
	bne.s	noad329
	addq	#1,d7
noad329	btst	#29,d0
	bne.s	noad330
	addq	#1,d7
noad330	btst	#30,d0
	bne.s	noad331
	addq	#1,d7
noad331	btst	#31,d0
	bne.s	noad332
	addq	#1,d7
noad332

	cmp.w	d5,d7
	bls.s	nobig22
	move.w	d4,biguns+2
	move.w	d7,d5
	cmp.b	#32,d7
	bne.s	nobig22
	move.l	(sp)+,a0
	bra.s	tiktis
nobigu2	addq.l	#8,a1
nobig22	addq.l	#1,d4
	dbf	d6,loosema
	move.l	(sp)+,a0

* Append matched character to output line

tiktis	move.b	biguns+3(pc),(a2)+
	addq.l	#1,a0
	move.l	(sp)+,d5
	dbf	d5,allcols

* Do/Don't do stripping of trailing spaces and/or CR+LF/LF appending

	tst.w	strip
	beq.s	nostrip
jas	cmp.b	#' ',-1(a2)
	bne.s	nostrip
	subq.l	#1,a2
	lea	outline(pc),a6
	cmp.l	a6,a2
	bgt.s	jas
nostrip	tst.w	ibm
	beq.s	onlylf
	move.b	#13,(a2)+
onlylf	move.b	#10,(a2)+
	move.b	#0,(a2)

	movem.l	d0-d3/a0-a4,-(sp)

* Output one line to output file

	lea	outline(pc),a0
	move.l	a0,d2
noze	tst.b	(a0)+
	bne.s	noze
	sub.l	d2,a0
	move.l	a0,d3
	subq.l	#1,d3
	move.l	myfile(pc),d1
	CALLDOS Write
	cmp.l	d0,d3
	beq.s	ok_wr

	lea	nowrite(pc),a0
	lea	datas(pc),a1
	move.l	outname(pc),(a1)
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

	bra	ctrlc

ok_wr	addq.l	#8,pich2
	move.l	pich(pc),d0
	cmp.l	pich2(pc),d0
	ble	noctrlc		; all done, don't check break or print status info

	tst.w	quiet
	bne.s	readc

* Print matching status info to CLI

	lea	report(pc),a0
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	datas(pc),a1
	move.l	pich2(pc),d0
	move.l	d0,(a1)
	move.l	pich(pc),d1
	move.l	d1,4(a1)
	
	mulu.w	#100,d0
	divu.w	d1,d0
	asr.l	#1,d1
	swap	d0
	cmp.w	d1,d0
	blt.s	swa
	swap	d0
	addq.w	#1,d0
	bra.s	yswa
swa	swap	d0
yswa	and.l	#$ffff,d0
	move.l	d0,8(a1)
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print
	bra.s	readc

* Subroutine to pass to RawDoFmt()

putter	cmp.l	a3,a4
	bgt.s	putok
	lea	outline(pc),a3
putok	move.b	d0,(a3)+
	rts

* Test if user BREAK'ed the program

readc   moveq	#0,d0
        moveq	#0,d1
        CALLEXEC SetSignal
        and.l	#SIGBREAKF_CTRL_C,d0
        beq.s	noctrlc

* Break signal received, exit

        moveq	#0,d0
        move.l	#SIGBREAKF_CTRL_C,d1
        CALLEXEC SetSignal

        lea	break(pc),a0
	bsr	print

ctrlc	movem.l	(sp)+,d0-d3/a0-a4

        bra	closefont

noctrlc	movem.l	(sp)+,d0-d3/a0-a4

	move.w	ysize(pc),d0
	move.l	picw(pc),d1
	mulu.w	d0,d1
	add.l	d1,a0
	move.l	picture(pc),d0
	add.l	rawsize(pc),d0
	cmp.l	a0,d0
	ble.s	tatsit
	move.l	pich(pc),d0
	cmp.l	pich2(pc),d0
	bgt	allrows

* End time constant

tatsit	move.l	myioreq(pc),a2
	move.l	IO_DEVICE(a2),a6
	lea	IOTV_TIME(a2),a0
	jsr	_LVOReadEClock(a6)
	move.l	d0,ticks

	tst.w	quiet
	bne.s	timeko

* Print done message to CLI

	lea	report2(pc),a0
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	lea	datas(pc),a1
	move.l	pich2(pc),(a1)
	lea	putter(pc),a2
	CALLEXEC RawDoFmt
	lea	outline(pc),a0
	bsr	print

timeko	tst.w	timeit
	beq.s	notimes

* Print elapsed time to CLI

	move.l	myioreq(pc),a2
	move.l	EV_HI+IOTV_TIME(a2),d0
	move.l	EV_LO+IOTV_TIME(a2),d1
	move.l	time1(pc),d2
	move.l	time2(pc),d3
	sub.l	d3,d1
	;subx.l	d2,d0

	lea	datas(pc),a1
	move.l	d1,(a1)
	move.l	ticks(pc),4(a1)
	
	lea	str2(pc),a0
	lea	putter(pc),a2
	lea	outline(pc),a3
	lea	outlineend(pc),a4
	CALLEXEC RawDoFmt

	lea	outline(pc),a0
	bsr	print

* All matching done, free everything

notimes	move.l	#0,error

freemap	tst.l	fontmap
	beq.s	closefont
	move.l	fontmapsize(pc),d0
	move.l	fontmap(pc),a1
	CALLEXEC FreeMem

closefont
	tst.l	myfont
	beq.s	closedf
	move.l	myfont(pc),a1
	CALLGFX CloseFont

cl_timer
	move.l	myioreq(pc),a1
	move.l	IO_DEVICE(a1),d0
	beq.s	cl_req
	CALLEXEC CloseDevice

cl_req	tst.l	myioreq
	beq.s	cl_port
	move.l	myioreq(pc),a0
	CALLEXEC DeleteIORequest

cl_port	tst.l	myport
	beq.s	closedf
	move.l	myport(pc),a0
	CALLEXEC DeleteMsgPort

closedf	tst.l	_DiskfontBase
	beq.s	closegfx
	move.l	_DiskfontBase(pc),a1
	CALLEXEC CloseLibrary

closegfx
	tst.l	_GfxBase
	beq.s	freeraw
	move.l	_GfxBase(pc),a1
	CALLEXEC CloseLibrary

freeraw	tst.l	picture
	beq.s	closeraw
	move.l	rawsize(pc),d0
	move.l	picture(pc),a1
	CALLEXEC FreeMem

closeraw
	move.l	rawfile(pc),d1
	beq.s	closeout
	CALLDOS Close

closeout
	move.l	myfile(pc),d1
	beq.s	closecli
	CALLDOS Close

closecli
	tst.l	returnMsg
	beq.s	closedos
	move.l	outfile(pc),d1
	beq.s	closedos
	CALLDOS Close

closedos
	tst.l	_DOSBase
	beq.s	exit
	move.l	_DOSBase(pc),a1
	CALLEXEC CloseLibrary

exit	move.l	error(pc),d0
	rts

* Sub routine to print a null terminated string to CLI

print	move.l	a0,-(sp)
nosep	tst.b	(a0)+
	bne.s	nosep
	sub.l	(sp),a0
	move.l	a0,d3
	subq.l	#1,d3
	move.l	(sp)+,d2
	move.l	outfile(pc),d1
	CALLDOS Write
	rts

* Variables and pointers

picw		dc.l	640/8		; picture width in bytes
pich		dc.l	256		; picture height in pixels
pich2		dc.l	0		; rows already matched
picture		dc.l	0		; pointer to raw bitmap data
biguns		dc.l	0		; character with the most matches
fontmapsize	dc.l	0		; size of linear font bitmap data
fontmap		dc.l	0		; ptr to linear font bitmap data
rawsize		dc.l	0		; input file size
rawfile		dc.l	0		; file handle of input file
myfile		dc.l	0		; file handle of output file
outname		dc.l	0		; ptr to output name string
rawname		dc.l	0		; ptr to input name string
fontname	dc.l	topazname	; ptr to font name string
parseline	dc.l	defrange	; ptr to font range string
parseend	dc.l	defrangeend-1	; ptr to end of font range string
line		dc.l	0		; ptr to command line options
linel		dc.l	0		; length of command line
charloc		dc.l	0		; ptr to font bitmap offsets
fontdata	dc.l	0		; ptr to original font bitmap data
fontmod		dc.l	0		; modulo of original font bitmap
lowchar		dc.l	0		; lowest char found in font
hichar		dc.l	0		; highest -"-
ysize		dc.w	0		; font ysize-1, for dcb loops
nochars		dc.w	0		; number of chars in font-1
strip		dc.w	0		; bool strip trailing spaces
ibm		dc.w	0		; bool CR+LF appending
loose		dc.w	0		; bool loose matching
timeit		dc.w	0		; bool display timing info
quiet		dc.w	0		; bool display match status
outfile		dc.l	0		; file handle of CLI output file
myfont		dc.l	0		; ptr to font used
returnMsg	dc.l	0		; if started from WB, reply
error		dc.l	20		; return code to CLI
_ExecBase	dc.l	0		; library bases
_GfxBase	dc.l	0
_DOSBase	dc.l	0
_DiskfontBase	dc.l	0
sigbit		dc.l	0		; sigbit of timer.device port
myport		dc.l	0		; ptr to timer.device port
myioreq		dc.l	0		; ptr to timer.device ioreq
time1		dc.l	0		; start time eclocks high lword
time2		dc.l	0		; start time eclocks low lword
ticks		dc.l	0		; no of ticks/second

* Misc strings

dosname		dc.b	"dos.library",0
		even
gfxname		dc.b	"graphics.library",0
		even
dfname		dc.b	"diskfont.library",0
		even
timer_name	dc.b	"timer.device",0
		even
errorcon        dc.b    "CON:///216/LetterMatcher ERROR MSG/CLOSE/AUTO/WAIT",0
                even
break		dc.b	10,"***BREAK",10,0
		even
topazname	dc.b	"topaz.font",0
		even
defrange	dc.b	"32-126,160-254"
		even
defrangeend
usages		dc.b	"LetterMatcher v1.0 - 12/08/93 by Henri Veisterä",10
		dc.b	"USAGE from CLI:",10
		dc.b	"LetterMatcher [-stmlq] OutName Picture Width Height [FontRange [FontName]]",10,10
		dc.b	" OutName   - Name of the output text file",10
		dc.b	" Picture   - Input picture in raw bitmap format",10
		dc.b	" Width     - Width of the input Picture in pixels (max 2048)",10
		dc.b	" Height    - Height of the input Picture in pixels",10
		dc.b	" FontRange - Range of font characters to use for matching",10
		dc.b	"             ASCII codes of chars separated with commas ",10
		dc.b	"             Or ranges like LOWCHAR-HICHAR (default: 32-126,160-254)",10
		dc.b	" FontName  - Name of font to use for matching (default: topaz.font)",10
		dc.b	"             Font must be nonproportional and have a width",10
		dc.b	"             and height of 8 pixels",10
		dc.b	" Switches:",10
		dc.b	" -s        - Strip trailing spaces from output",10
		dc.b	" -t        - Report elapsed matching time (in EClock ticks)",10
		dc.b	" -m        - Add CR/LF after each line (default: only LF)",10
		dc.b	" -l        - Loose matching, twice as fast",10
		dc.b	" -q        - Suppress any CLI output but error messages",10,10
		dc.b	"EXAMPLE:",10
		dc.b	"LetterMatcher -stl MyPic.txt MyPic.raw 640 200 3-6,21,32-126,128-254 ibm.font",10,0
		even
report		dc.b	10,27,"[ALetterMatcher: Converting line %ld/%ld (%ld%% done) ...",0
		even
report2		dc.b	10,27,"[A",27,"[KLetterMatcher: Converted %ld lines.",10,0
		even
non8		dc.b	"Picture width not divisible by 8.  Reformat your picture.",10,0
		even
nooutp		dc.b	"Could not open output file '%s'.",10,0
		even
noraw		dc.b	"Could not open input picture file '%s'.",10,0
		even
noraw2		dc.b	"Input picture file '%s' size zero.",10,0
		even
noraw3		dc.b	"Error reading input picture file '%s'.",10,0
		even
nomem		dc.b	"Out of memory allocating %ld bytes.",10,0
		even
nogfx		dc.b	"Could not open graphics.library.",10,0
		even
nodf		dc.b	"Could not open diskfont.library.",10,0
		even
nofont1		dc.b	"Could not open your font '%s' (height 8).",10,0
		even
nofont2		dc.b	"Font '%s' is proportional.  Use a fixed width font.",10,0
		even
nofont3		dc.b	"Font '%s' width is not 8 pixels.",10,0
		even
nowrite		dc.b	10,"Error writting to output file '%s'.",10,0
		even
str2		dc.b	"Time elapsed: %lu ticks (%lu ticks/sec)",10,0
		even

* Data blocks

mytattr		dc.l	topazname
		dc.w	8
		dc.b	0,FPF_DISKFONT!FPF_DESIGNED
datas		dcb.l	4,0		; data stream for RawDoFmt()
vert		dcb.b	8,0		; buffer for linear source data
chart		dcb.b	256,0		; -1 for chars to use for matching
outline		dcb.b	260,0		; buffer for output lines
outlineend
