; Never leave these on:
;Code020  	=	1		; Define for 020 code, comment for 000.
;Debug		=	1		; Define for Say() & ShowReg() macros.

	IFD	Code020
	MACHINE	68020
	ELSE
	MACHINE	68000
	ENDC

	INCLUDE	"SRC:Routines/String/StringLib.I"

	XREF	NumToStr

; Last CodeError code used: 4

; During the translation loop:
; A0 = Pointer to source data
; A1 = Pointer to destination data
; A2 = Pointer to space buffer
; A3 = Pointer to translation table
; A4 = Pointer to InterNet header stripper buffer.
; A5 = Data base pointer. (Ptr to DT)

; D0 = Current char
; D1 = Counter of bytes left in the source buffer.
; D2 = Counter of converted bytes in the destination buffer.
; D3 = Counter of total converted bytes.

	INCDIR	"INCLUDE:"
	INCLUDE	"Darkness.I"
	INCLUDE	"Exec.Offsets"
	INCLUDE	"Dos.Offsets"
	INCLUDE "exec/types.i"
	INCLUDE	"exec/execbase.i"
	INCLUDE	"exec/memory.i"
	INCLUDE	"hardware/intbits.i"
	INCLUDE	"dos/dos.i"
	INCLUDE	"dos/dosasl.i"
	INCLUDE "libraries/ppbase.i"
	INCLUDE "libraries/powerpacker_lib.i"
	INCLUDE	"utility/tagitem.i"

	STRUCTURE	FileLink,0
	LONG	fl_Next
	LONG	fl_Size
	STRUCT	fl_FullName,256
	STRUCT	fl_FileName,256
	LABEL	fl_SIZEOF

; Modes which want CRs must be negative.
MODE_TOPC	=	-1
MODE_TOSF7	=	-2

MODE_FROMPC	=	 1
MODE_FROMSF7	=	 2
MODE_TOUPCASE	=	 3
MODE_TOLOWCASE	=	 4
MODE_TONULL	=	 5
MODE_TOASCII	=	 7
MODE_COMBINED	=	 8

SIZE_MAXNEW	=	16		; Maximum size change in one cycle.

CR		=	13
LF		=	10
TAB		=	 9

TRUE		= 	-1
FALSE		=	 0

ANSI_CLEAR	=	 0		; No ANSI code currently active.
ANSI_WAIT	=	 1		; ESC found, but no "[" yet.
ANSI_CODE	=	 2		; In progress of skipping the code.

; A macro to call a library routine.

Call	MACRO
	move.l	_\1Base,a6
	jsr	_LVO\2(a6)
	ENDM

BToLong	MACRO
	IFD	Code020			; Convert TabSize
	extb.l	\1
	ENDC
	IFND	Code020
	ext.w	\1
	ext.l	\1
	ENDC
	ENDM

SaveR	MACRO
	movem.l	d0-d7/a0-a6,-(sp)
	ENDM

LoadR	MACRO
	movem.l	(sp)+,d0-d7/a0-a6
	ENDM

Say	MACRO
	IFD	Debug
	SaveR
	lea	DebugBuf,a0
	lea	.Shit\@,a1
	bsr	StrCpy
	lea	DebugBuf,a0
	bsr	StrLFCat
	move.l	#DebugBuf,d2
	bsr	PrintText
	LoadR
	bra	.Skip\@

.Shit\@:
	dc.b	\1,"\c0K",0

	EVEN

.Skip\@:
	ENDC
	ENDM

ShowPtr	MACRO
	IFD	Debug
	SaveR
	move.l	\1,d2
	bsr	PrintText
	LoadR
	ENDC
	ENDM

ShowReg	MACRO
	IFD	Debug
	SaveR
	lea	.Shit\@,a0
	clr.b	(a0)
	move.l	\1,d0
	bsr	StrNumCat
	lea	.Shit\@,a0
	bsr	StrLFCat
	move.l	#.Shit\@,d2
	bsr	PrintText
	LoadR
	bra	.Skip\@

.Shit\@:
	ds.b	256

	EVEN

.Skip\@:
	ENDC
	ENDM

ProgStart:
	move.l	sp,OldStack
	lea	DT,a5
	clr.b	-1(a0,d0.w)
	move.l	a0,-(sp)
	add.l	d0,a0
	subq.l	#1,a0

	lea	_DosName,a1
	moveq	#37,d0
	Call	Exec,OpenLibrary
	move.l	d0,_DosBase
	beq	Err_NewerKickNeeded

	IFD	Code020
	move.l	_ExecBase,a6		; Tests if we have 68020.
	move.w	AttnFlags(a6),d0
	btst.w	#AFB_68020,d0
	beq	Err_OldProcessor
	ENDC

	Call	Dos,Output		; Find the Shell output stream.
	move.l	d0,(a5,OutStruct-DT)

	move.l	#Text_Header,d2
	bsr	PrintText

	lea	PPName,a1		; Open PP library if we have it.
	moveq	#35,d0			; If change to higher check 'PPNeed'.
	Call	Exec,OpenLibrary
	move.l	d0,_PPBase

	move.l	4.w,a6			; Set up the interrupt.
	move.l	VBlankFrequency(a6),(a5,TickDelay-DT)

	moveq	#INTB_VERTB,d0		; Add the counter interrupt.
	lea	VertBInterrupt,a1
	Call	Exec,AddIntServer
	st	(a5,Flag_IntActive-DT)

	move.l	(a7),a0			; CommandStart
	tst.b	(a0)			; If blank commandline, instructions.
	beq.w	HelpText
	cmp.b	#"?",(a0)
	beq.w	HelpText

	bsr	LoadPrefs		; Load user preferences.
	move.l	(a7)+,a0		; CommandStart

ParseStart:
	cmp.b	#"-",(a0)
	beq.b	CheckOption

Parse:
	cmp.b	#" ",1(a0)		; At least one space after option
	bne	Err_BadComLine
	cmp.b	#"p",(a0)
	beq.w	FromPCMode
	cmp.b	#"P",(a0)
	beq.w	ToPCMode
	cmp.b	#"c",(a0)
	beq.w	CombinedMode
	cmp.b	#"s",(a0)
	beq.w	FromSF7Mode
	cmp.b	#"S",(a0)
	beq.w	ToSF7Mode
	cmp.b	#"u",(a0)
	beq.w	ToUpCaseMode
	cmp.b	#"l",(a0)
	beq.w	ToLowCaseMode
	cmp.b	#"n",(a0)
	beq.w	ModeToNull
	cmp.b	#"o",(a0)
	beq.w	ModeToOnlyASCII
	bra.w	Err_BadComLine

CheckOption:
	cmp.b	#"a",1(a0)
	beq.b	Opt_AStrip
	cmp.b	#"e",1(a0)
	beq.b	Opt_MakeEOLs
	cmp.b	#"i",1(a0)
	beq.b	Opt_INStrip
	cmp.b	#"n",1(a0)
	beq.b	Opt_NoCutSpace
	cmp.b	#"p",1(a0)
	beq	Opt_PPackOut
	cmp.b	#"l",1(a0)
	beq	Opt_LhAPackOut
	cmp.b	#"?",1(a0)
	beq	Credits
	cmp.b	#"t",1(a0)
	beq	Opt_TabConv
	cmp.b	#"s",1(a0)
	beq	Opt_SpaceConv
	cmp.b	#"b",1(a0)
	beq	Opt_NoBufferMode
	bra	Err_BadComLine		; Unknown option, report error.

Opt_AStrip:
	cmp.b	#"!",2(a0)
	beq.b	.Off
	addq.l	#2,a0
	st	(a5,Flag_AStrip-DT)
	bra	Opt_Next

.Off:
	addq.l	#3,a0
	clr.b	(a5,Flag_AStrip-DT)
	bra	Opt_Next

Opt_INStrip:
	addq.l	#3,a0
	cmp.b	#"!",-1(a0)
	beq.b	.Off
	cmp.b	#"1",-1(a0)
	beq.b	.PutInfo
	cmp.b	#"2",-1(a0)
	beq.b	.NoInfo
	bra	Err_BadComLine

.Off:
	clr.b	(a5,Flag_INStrip-DT)
	bra.b	Opt_Next

.PutInfo:
	move.b	#1,(a5,Flag_INStrip-DT)
	bra.b	Opt_Next

.NoInfo:
	move.b	#2,(a5,Flag_INStrip-DT)
	bra.b	Opt_Next

Opt_NoCutSpace:
	cmp.b	#"!",2(a0)
	beq.b	.Off
	tst.b	(a5,Size_MakeEOLs-DT)
	bne	Err_BadLogic
	st	(a5,Mode_NoCutSpace-DT)
	addq.l	#2,a0
	bra.w	Opt_Next

.Off:
	addq.l	#3,a0
	clr.b	(a5,Mode_NoCutSpace-DT)
	bra	Opt_Next

Opt_LhAPackOut:
	cmp.b	#"!",2(a0)
	beq.b	.Off
	tst.b	(a5,Flag_CrunchBuf-DT)
	bne	Err_BadLogic
	addq.l	#2,a0
	st	(a5,Flag_LhAPack-DT)
	bra	Opt_Next

.Off:
	addq.l	#3,a0
	clr.b	(a5,Flag_LhAPack-DT)
	bra	Opt_Next

Opt_PPackOut:
	cmp.b	#"!",2(a0)
	beq.b	.Off
	tst.b	(a5,Flag_LhAPack-DT)
	bne	Err_BadLogic
	addq.l	#2,a0
	st	(a5,Flag_CrunchBuf-DT)
	tst.l	_PPBase
	bne.b	Opt_Next
	move.l	#Text_PowerPackNeed,d2
	bra	ShowErr

.Off:
	addq.l	#3,a0
	clr.b	(a5,Flag_CrunchBuf-DT)
	bra.b	Opt_Next

Opt_TabConv:
	addq.l	#2,a0
	cmp.b	#"!",(a0)
	beq.b	.Off
	tst.b	(a5,TabSize-DT)
	bne	Err_BadLogic
	cmp.b	#" ",(a0)
	beq.b	Opt_TabConv1
	move.l	a0,-(sp)
	bsr	GetNum
	move.l	(sp)+,a0
	bsr	FindWhite
	cmp.l	#16,d0
	bhi	Err_BadComLine
	cmp.l	#1,d0
	bcs	Err_BadComLine
	move.b	d0,(a5,TabSize-DT)
	bra.b	Opt_Next

.Off:
	addq.l	#1,a0
	tst.b	(a5,SpaceSize-DT)	; SpaceConv has TabConv always on, don't
	bne	Opt_Next		; turn that off.
	clr.b	(a5,TabSize-DT)
	bra	Opt_Next

Opt_TabConv1:
	move.b	#8,(a5,TabSize-DT)
	bra.b	Opt_Next

Opt_SpaceConv:
	addq.l	#2,a0
	cmp.b	#"!",(a0)
	beq.b	.Off
	tst.b	(a5,SpaceSize-DT)	; If we have a old SpaceConv, new is ok.
	bne.b	.Okay
	tst.b	(a5,TabSize-DT)
	bne	Err_BadLogic

.Okay:
	tst.b	(a5,Size_MakeEOLs-DT)
	bne	Err_BadLogic
	cmp.b	#" ",(a0)
	beq.b	.Default
	move.l	a0,-(sp)
	bsr	GetNum
	move.l	(sp)+,a0
	bsr	FindWhite
	cmp.l	#16,d0
	bhi	Err_BadComLine
	cmp.l	#1,d0
	bcs	Err_BadComLine
	move.b	d0,(a5,SpaceSize-DT)
	bra.b	Opt_Next

.Default:
	move.b	#8,(a5,SpaceSize-DT)
	move.b	#8,(a5,TabSize-DT)
	bra	Opt_Next

.Off
	addq.l	#1,a0
	tst.b	(a5,SpaceSize-DT)
	beq.b	Opt_Next
	clr.b	(a5,SpaceSize-DT)
	clr.b	(a5,TabSize-DT)
	bra	Opt_Next

Opt_MakeEOLs:
	cmp.b	#"!",2(a0)
	beq	.Off
	tst.b	(a5,SpaceSize-DT)
	bne	Err_BadLogic
	move.b	2(a0),d0
	cmp.b	#" ",d0
	beq.w	Err_BadComLine
	sub.b	#"0",d0
	cmp.b	#9,d0
	bhi	Err_BadComLine
	cmp.b	#1,d0
	bcs	Err_BadComLine
	move.b	3(a0),d1
	cmp.b	#" ",d1
	beq.b	Opt_MakeEOLs1
	sub.b	#"0",d1
	cmp.b	#9,d1
	bhi	Err_BadComLine
	cmp.b	#0,d1
	bcs	Err_BadComLine
	ext.w	d0
	mulu	#10,d0
	add.b	d1,d0
	move.b	d0,(a5,Size_MakeEOLs-DT)
	addq.l	#4,a0
	bra.b	Opt_Next

.Off:
	clr.b	(a5,Size_MakeEOLs-DT)
	addq.l	#3,a0
	bra.b	Opt_Next

Opt_MakeEOLs1:
	move.b	d0,(a5,Size_MakeEOLs-DT)
	addq.l	#3,a0
	bra.b	Opt_Next

Opt_NoBufferMode:
	addq.l	#2,a0
	cmp.b	#"!",(a0)
	beq.b	.Off
	st	(a5,Mode_NoBuffer-DT)
	bra	Opt_Next

.Off:
	addq.l	#1,a0
	clr.b	(a5,Mode_NoBuffer-DT)

Opt_Next:
	cmp.b	#" ",(a0)
	bne	Err_BadComLine
	bsr	SkipSpace
	cmp.l	#0,a0
	beq.w	Err_BadComLine
	bra.w	ParseStart

FromPCMode:
	move.b	#MODE_FROMPC,(a5,Mode-DT)
	move.l	#Table_FromPC,(a5,Table-DT)
	bra.w	NameParse

FromSF7Mode:
	move.b	#MODE_FROMSF7,(a5,Mode-DT)
	move.l	#Table_FromSF7,(a5,Table-DT)
	bra.w	NameParse

ToSF7Mode:
	move.b	#MODE_TOSF7,(a5,Mode-DT)
	move.l	#Table_ToSF7,(a5,Table-DT)
	bra.w	NameParse

CombinedMode:
	move.b	#MODE_COMBINED,(a5,Mode-DT)
	move.l	#Table_Combined,(a5,Table-DT)
	bra.w	NameParse

ToPCMode:
	move.b	#MODE_TOPC,(a5,Mode-DT)
	move.l	#Table_ToPC,(a5,Table-DT)
	bra.w	NameParse

ToUpCaseMode:
	move.b	#MODE_TOUPCASE,(a5,Mode-DT)
	move.l	#Table_Uppercase,(a5,Table-DT)
	bra.b	NameParse

ToLowCaseMode:
	move.b	#MODE_TOLOWCASE,(a5,Mode-DT)
	move.l	#Table_Lowercase,(a5,Table-DT)
	bra.b	NameParse

ModeToNull:
	move.b	#MODE_TONULL,(a5,Mode-DT)
	move.l	#Table_Null,(a5,Table-DT)
	bra.b	NameParse

ModeToOnlyASCII:
	move.b	#MODE_TOASCII,(a5,Mode-DT)
	move.l	#Table_Null,(a5,Table-DT)

NameParse:
	addq.l	#1,a0			; One after Mode
	bsr	SkipSpace
	cmp.l	#0,a0
	beq.w	Err_BadComLine
	move.l	a0,(a5,SourceNameStart-DT)
	bsr	FindEnd
	move.l	a0,(a5,SourceNameEnd-DT)
	addq.l	#1,a0			; Find the length for source name.
	sub.l	(a5,SourceNameStart-DT),a0
	move.l	a0,(a5,SourceNameLen-DT)

	move.l	(a5,SourceNameStart-DT),a0
	lea	(a5,SourceName-DT),a1	; Copy the name to SourceName
	move.l	(a5,SourceNameLen-DT),d0
	bsr	CopyName

	lea	(a5,SourceName-DT),a0
	bsr	FormFileLinks
	move.l	#FileLinkBase,(a5,CurrentLink-DT)
	beq	LinkEnd

StartNewFile:
	move.l	(a5,CurrentLink-DT),a0	; Get the next FileLink.
	move.l	(a0,fl_Next),a0
	move.l	a0,(a5,CurrentLink-DT)
	beq	LinkEnd

	clr.b	(a5,Flag_CrunchTried-DT)
	move.l	(fl_Size,a0),(a5,SourceLen-DT)
	lea	(fl_FileName,a0),a1
	lea	(a5,RealSourceName-DT),a0
	bsr	StrCpy

	move.l	(a5,SourceNameEnd-DT),a0
	addq.l	#1,a0
	tst.b	(a0)
	beq.w	NoDest
	bsr	SkipSpace
	move.l	a0,(a5,DestNStart-DT)	; If 0, go NoDest
	beq.w	NoDest
	bsr	FindEnd
	addq.l	#1,a0			; Add 1 to DestName end, and get
	sub.l	(a5,DestNStart-DT),a0	; DestNameLen in a0
	move.l	a0,d0
	move.l	(a5,DestNStart-DT),a0	; Copy the destination name to DestName.
	lea	(a5,DestName-DT),a1
	bsr	CopyName

	move.l	#DestName,d1		; Try to lock dest filename.
	move.l	#ACCESS_READ,d2
	Call	Dos,Lock
	move.l	d0,(a5,DestLock-DT)
	beq.w	DestNameCheck		; If no lock, we'll have a file.

	move.l	(a5,DestLock-DT),d1	; Otherwise check it
	move.l	#FIB,d2
	Call	Dos,Examine
	move.l	d0,-(sp)		; Save result code
	move.l	(a5,DestLock-DT),d1
	Call	Dos,UnLock
	clr.l	(a5,DestLock-DT)
	move.l	(sp)+,d0		; Boolean
	beq.w	Err_DestCorrupt		; 0 means error
	lea	FIB,a0
	tst.l	fib_DirEntryType(a0)	; Dir or a file?
	bgt	DestIsDir		; > 0 means directory.

DestNameCheck:
	lea	MyAnchor,a0
	btst.b	#APB_ITSWILD,(a0,ap_Flags)
	bne	Err_FileDest
	bra 	OpenFiles

LinkEnd:
	tst.b	(a5,Flag_FileFound-DT)
	beq	Err_NoSource
	st	(a5,Flag_Stop-DT)
	bra	EndProgram

DestIsDir:
	move.l	#DestName,d1		; Add the source name to dest path.
	move.l	#RealSourceName,d2
	move.l	#256,d3
	Call	Dos,AddPart
	moveq	#3,d7
	tst.l	d0
	beq	CodeError
	bra.b	OpenFiles

NoDest:
	clr.b	Flag_DestName
	move.l	(a5,CurrentLink-DT),a1
	add.l	#fl_FullName,a1		; If no destination name, use the
	lea	(a5,DestName-DT),a0	; sourcename (i.e. writing on the
	bsr	StrCpy			; original).
	subq.l	#1,a0
	move.l	a0,a1

	tst.b	(a5,Flag_LhAPack-DT)	; Or if we are LhA packing the source.
	bne.b	.NoSuffix
	tst.b	(a5,Mode_NoBuffer-DT)	; If we have a buffer, add no suffix.
	bne.b	.AddSuffix

.NoSuffix:
	st	(a5,Mode_SrcDeleted-DT)
	bra.b	OpenFiles

.AddSuffix:
	cmp.b	#MODE_TOPC,(a5,Mode-DT)	; Add the right type of suffix.
	beq.b	PCSuffix
	cmp.b	#MODE_TOSF7,(a5,Mode-DT)
	beq.b	SF7Suffix

AmigaSuffix:
	lea	Text_AmigaSuf,a0
	bra.b	AddSuffix

PCSuffix:
	lea	Text_PCSuf,a0
	bra.b	AddSuffix

SF7Suffix:
	lea	Text_SF7Suf,a0

AddSuffix:
	move.b	(a0)+,(a1)+
	bne.b	AddSuffix

OpenFiles:
	tst.b	(a5,Mode_NoBuffer-DT)	; We have a buffer, go to OpenFilesBuf.
	beq.w	OpenFilesBuf
	bsr	AllocBuffers
	bsr	OpenCheckPP
	bsr	OpenDest
	moveq	#0,d3
	bra.w	ReadBlock

; Open file CurrentLink.fl_FullName and check if it's PowerPacked.
; If we have PP library, decrunch the file.
; If not, show error.

OpenCheckPP:
	move.l	(a5,CurrentLink-DT),a0
	bsr	ClearPrintBuf		; Start a new buffer.
	move.l	#Text_ConvFile1,a0
	bsr	AddPrintBuf
	move.l	(a5,CurrentLink-DT),a0
	lea	fl_FileName(a0),a0
	bsr	AddPrintBuf
	move.l	#Text_ConvFile2,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf

	move.l	(a5,CurrentLink-DT),d1
	add.l	#fl_FullName,d1
	move.l	#MODE_OLDFILE,d2
	Call	Dos,Open
	moveq	#1,d7			; Unlikely error -code.
	move.l	d0,(a5,SourceHandle-DT)
	beq.w	CodeError

	bsr	PrintReading
	move.l	(a5,SourceHandle-DT),d1	; Read 4 bytes.
	move.l	#TempBuf,d2
	move.l	#4,d3
	Call	Dos,Read
	cmp.l	#4,d0			; Did we read 4 bytes?
	bne.b	.SeekBack		; No, just seek back.
	move.l	(a5,TempBuf-DT),d0	; Get a long from the buffer, and check
	cmp.l	#"PP20",d0		; if it is a PowerPacker datafile.
	beq.w	.PackedData
	cmp.l	#"PX20",d0		; if it is a PowerPacker datafile.
	beq.w	.PackedData

.SeekBack:
	move.l	(a5,SourceHandle-DT),d1	; Seek back to the
	moveq	#0,d2			; beginning of the file.
	moveq	#OFFSET_BEGINNING,d3
	Call	Dos,Seek
	bsr	MakeSourceASCII
	rts

.PackedData:
	move.l	(a5,SourceHandle-DT),d1
	Call	Dos,Close
	clr.l	(a5,SourceHandle-DT)

	move.l	_PPBase,a6
	IFD	Code020
	tst.l	a6
	ENDC
	IFND	Code020
	cmp.l	#0,a6
	ENDC
	beq	Err_PowerPacked
	tst.b	(a5,Mode_NoBuffer-DT)
	bne	Err_NeedBufPP

	move.l	#Text_Decrunching,d2
	bsr	PrintText

	st	(a5,Flag_PPUsed-DT)
	move.l	(a5,CurrentLink-DT),a0
	add.l	#fl_FullName,a0
	moveq	#DECR_NONE,d0
	moveq	#0,d1			; Memory type.
	lea	(a5,SourcePointer-DT),a1
	lea	(a5,SourceLen-DT),a2
	move.l	#0,a3			; Use default PW function.
	Call	PP,ppLoadData	
	tst.l	d0
	bne.b	.PackedError		; If error.
	bsr	MakeSourceASCII
	rts

.PackedError:
	cmp.l	#PP_OPENERR,d0		; Should never happen, since we did
	beq	Err_SourceCorrupt	; check that it was a PP file.
	cmp.l	#PP_READERR,d0
	beq	Err_SourceCorrupt
	cmp.l	#PP_NOMEMORY,d0
	beq	Err_NoMem
	cmp.l	#PP_PASSERR,d0
	beq	Err_PassError
	cmp.l	#PP_EMPTYFILE,d0
	beq	Err_SourceCorrupt
	cmp.l	#PP_UNKNOWNPP,d0
	beq	Err_UnknownPP
	moveq	#2,d7
	bra	CodeError

OpenFilesBuf:
	bsr	OpenCheckPP

	tst.b	(a5,Flag_PPUsed-DT)	; If the file was loaded by PP, we
	beq	OpenFilesNoPP		; don't have to alloc memory or read.
	move.l	(a5,SourceLen-DT),(a5,ReadBytes-DT)
	bra	ReadFinished

OpenFilesNoPP:
	move.l	(a5,SourceLen-DT),d0		; Allocate for the whole source file.
	moveq	#0,d1			; No special needs for the memory.
	Call	Exec,AllocMem
	move.l	d0,(a5,SourcePointer-DT)
	beq.w	Err_NoMem

ReadFile:
	move.l	(a5,SourceHandle-DT),d1
	move.l	(a5,SourcePointer-DT),d2
	add.l	(a5,ReadBytes-DT),d2	; To our file buffer.
	move.l	RBlockSize,d3
	clr.w	(a5,TickCount-DT)
	Call	Dos,Read
	cmp.l	#-1,d0
	beq.w	Err_ReadFail		; If error reading the file.
	add.l	d0,(a5,ReadBytes-DT)
	move.l	d0,-(sp)		; Save "bytes read".

	bsr	CalcReadRate		; Determine the optimal block size.

	bsr	ClearPrintBuf		; Start a new buffer.

	move.l	#Text_Read,a0		; Print our progress to Shell.
	bsr	AddPrintBuf

	lea	(a5,ReadASCII-DT),a0	; First convert the number into a
	move.l	(a5,ReadBytes-DT),d0	; string, and then add the string into
	bsr	NumToStr		; the buffer.

	bsr	AddPrintBuf

	move.l	#Text_Slash,a0
	bsr	AddPrintBuf

	move.l	(a5,SourceLenASCIIAddr-DT),a0
	bsr	AddPrintBuf

	move.l	#Text_CR,a0		; And back to the beginning of the line.
	bsr	AddPrintBuf
	bsr	WritePrintBuf

	move.l	(a7)+,d0		; How many bytes we read, if null, we're
	beq.b	ReadFinished		; finished.

	moveq	#0,d0			; Get the signals.
	moveq	#0,d1
	Call	Exec,SetSignal

	btst	#SIGBREAKB_CTRL_C,d0	; Check if ^C was pressed.
	bne	BreakPressed

	bra.w	ReadFile		; Read more of the file.

ReadFinished:
	bsr	AllocBuffers
	move.l	(a5,ReadBytes-DT),(a5,LeftBytes-DT)
	tst.b	(a5,Flag_PPUsed-DT)
	bne	ReadFinished2

	move.l	(a5,SourceHandle-DT),d1	; Close the source, since we're done.
	Call	Dos,Close
	clr.l	(a5,SourceHandle-DT)	; Note that it's closed.

ReadFinished2:
	bsr	OpenDest
	moveq	#0,d3
	bra.w	MoreData

ReadBlock:
	tst.b	(a5,Mode_NoBuffer-DT)
	beq.b	MoreData		; We have a buffer -> MoreData
	movem.l	d0/d2-d7/a0-a6,-(sp)
	bsr	PrintReading
	move.l	(a5,SourceHandle-DT),d1	; Otherwise read.
	move.l	(a5,SourcePointer-DT),d2
	move.l	(a5,Size_SrcBuf-DT),d3
	Call	Dos,Read
	cmp.l	#-1,d0
	beq.w	Err_ReadFail		; Couldn't read?  -> Err_ReadFail.
	add.l	d0,(a5,ReadBytes-DT)
	add.l	d0,(a5,InputBytes-DT)
	move.l	d0,d1
	beq.b	RB_CloseFiles		; !ReadBytes -> Quit.
	movem.l	(sp)+,d0/d2-d7/a0-a6
	movem.l	d0/d2-d7/a0-a6,-(sp)
	bsr	PrintStats
	movem.l	(sp)+,d0/d2-d7/a0-a6
	subq.l	#1,d1			; Counter always one less than loops.
	move.l	(a5,SourcePointer-DT),a0
	bra.w	CheckOutBuf		; Continue converting.

RB_CloseFiles:				; Same as CloseFiles, but pops
	movem.l	(sp)+,d0/d2-d7/a0-a6	; the regs after ReadBlock messing with
	bra.w	CloseFiles		; them.

MoreData:
	tst.l	(a5,LeftBytes-DT)	; We have no more bytes left?
	beq.w	CloseFiles		; -> Quit.
	move.l	(a5,LeftBytes-DT),d1
	clr.l	(a5,LeftBytes-DT)
	move.l	(a5,SourcePointer-DT),a0
	add.l	(a5,InputBytes-DT),a0
	add.l	d1,(a5,InputBytes-DT)
	subq.l	#1,d1			; Loop counter starts from 0, i.e. -1.
	bra.w	CheckOutBuf

MoreCharacters:
	move.b	(a0)+,d0		; Get a new byte from the buffer.
	and.w	#$ff,d0			; a3 contains the table base-address.
	move.l	d3,-(sp)
	move.b	(a3,d0.w),d0		; Replace the original character.
	beq.b	NoChar			; $00 - Trash this byte.

	tst.b	(a5,Flag_AStrip-DT)
	beq.b	.NoAStrip
	bsr	ANSIStrip
	bra.b	NoChar

.NoAStrip:
	tst.b	(a5,Flag_INStrip-DT)
	beq.b	.NoINStrip
	bsr	InterNetStrip
	bra.b	NoChar

.NoINStrip:
	bsr	WhiteProcess
	tst.l	d0			; Null = Insert nothing.
	beq.b	NoChar
	bsr	InsertInDest

NoChar:
	move.l	(sp)+,d3
	addq.l	#1,d3			; Total bytes converted.
	subq.l	#1,d1			; One less byte in the read buffer.
	bmi	ReadBlock		; Went negative, load more.

CheckOutBuf:
	tst.b	(a5,Flag_StatsDue-DT)	; Check if we should show the stats.
	bne.b	.DoStats

.ContCheckOutBuf:
	move.l	(a5,Size_DstBuf-DT),d0
	Say	"Dest buf size:"
	ShowReg	d0
	ShowReg	d2
	ShowReg	a5
	sub.l	#SIZE_MAXNEW,d0
	cmp.l	d0,d2			; Have we converted a full buffer yet?
	bls.b	MoreCharacters		; Everything okay, continue conversion.
	Say	"Wrote it."
	bra.b	WriteDestBuf

.DoStats:
	bsr	PrintStats
	bra.b	.ContCheckOutBuf

WriteDestBuf:
	movem.l	d1/d3-d7/a0/a2-a5,-(sp)
	move.l	d3,-(sp)
	bsr	PrintWriting
	move.l	(a5,DestHandle-DT),d1	; Write the converted data.
	move.l	d2,d3			; Number of bytes to write.
	add.l	d2,(a5,WrittenBytes-DT)	; Add the buffer to WrittenBytes.
	move.l	(a5,DestPointer-DT),d2
	Call	Dos,Write
	cmp.l	#-1,d0
	beq.w	Err_WriteFail
	move.l	(sp)+,d3
	bsr	PrintStats
	tst.b	(a5,Mode_SrcDeleted-DT)	; If the sourcefile has been destroyed,
	bne.b	.NoBreak		; don't allow breaking.
	moveq	#0,d0			; Get the signals.
	moveq	#0,d1
	Call	Exec,SetSignal
	btst	#SIGBREAKB_CTRL_C,d0	; Check if ^C was pressed.
	bne.w	BreakPressed

.NoBreak:
	movem.l	(sp)+,d1/d3-d7/a0/a2-a5
	moveq	#0,d2			; No converted bytes now.
	move.l	(a5,DestPointer-DT),a1
	bra.w	MoreCharacters

CloseFiles:
	tst.l	(a5,EOLs-DT)
	beq	.NoEOLsLeft
	addq.l	#1,d2
	bsr	InsertSingleEOL
	tst.b	(a5,Mode-DT)		; If ToPC or ToSF7, add a CR too.
	bpl	.NoEOLsLeft
	addq.l	#1,d2

.NoEOLsLeft:
	bsr	PrintWriting
	move.l	d2,d3			; Do we have stuff in DestBuf?
	beq.b	CF_TellData		; No, show the final stats.
	move.l	(a5,DestHandle-DT),d1	; We do, flush it.
	add.l	d2,(a5,WrittenBytes-DT)	; Add the buffer to WrittenBytes.
	move.l	(a5,DestPointer-DT),d2
	Call	Dos,Write
	cmp.l	#-1,d0
	beq.w	Err_WriteFail

CF_TellData:
	bsr	ClearPrintBuf		; Tell the file size change.
	move.l	#Text_Final,a0
	bsr	AddPrintBuf

	move.l	(a5,WrittenBytes-DT),d0

	sub.l	(a5,ReadBytes-DT),d0
	bmi	CloseFiles1		; Negative

	move.l	d0,d7
	beq.b	CloseFiles2		; If zero, no sign.

	move.l	#Text_PosSign,a0
	bsr	AddPrintBuf

	bra.b	CloseFiles2

CloseFiles1:
	neg.l	d0
	move.l	#Text_NegSign,a0
	bsr	AddPrintBuf

CloseFiles2:
	lea	(a5,NumberBuf-DT),a0	; Print the final statistics.
	bsr	NumToStr
	bsr	AddPrintBuf

	move.l	#Text_DoubleSpace,a0
	bsr	AddPrintBuf

	move.l	(a5,WrittenBytes-DT),d0	; File size change as a percentage.
	move.l	(a5,ReadBytes-DT),d1
	bsr	Percentage

	lea	(a5,NumberBuf-DT),a0
	bsr	NumToStr

	bsr	AddPrintBuf

	move.l	#Text_PercentSign,a0
	bsr	AddPrintBuf

	move.l	#Text_LF,a0
	bsr	AddPrintBuf
	tst.b	(a5,Flag_CrunchBuf-DT)
	bne	.OnlyOneLF
	move.l	#Text_LF,a0
	bsr	AddPrintBuf

.OnlyOneLF:
	bsr	WritePrintBuf
	bra.w	EndProgram

HelpText:
	st	(a5,Flag_Stop-DT)	; We don't want to continue after
	move.l	#Text_HelpText,d2	; printing the help text.
	bsr	PrintText
	bra.w	EndProgram

Credits:
	st	(a5,Flag_Stop-DT)	; Neither after credits.
	move.l	#Text_Credits,d2
	bsr	PrintText
	bra.w	EndProgram

********************
** ERROR ROUTINES **
********************

CodeError:
	st	(a5,Flag_Stop-DT)	; Tell a serious error has occured,
	move.l	d7,-(sp)		; and a special error code in D7.
	move.l	#Text_CodeError,d2
	bsr	PrintText
	lea	(a5,NumberBuf-DT),a0
	move.l	(sp)+,d0
	bsr	NumToStr
	move.l	a0,d2
	move.l	d0,d3
	bsr	PrintTextLen
	move.l	#Text_LF,d2
	bsr	PrintText
	bra.w	EndProgram

Err_CrunchReadWrite:
	move.l	#Text_CrunchReadWrite,d2
	bra	ShowWarn

Err_CrunchOverflow:
	move.l	#Text_CrunchOverflow,d2
	bra	ShowWarn

Err_NoCrunchMem:
	move.l	#Text_NoCrunchMem,d2
	bra	ShowWarn

Err_NoCrunchFile:
	move.l	#Text_NoCrunchFile,d2
	bra	ShowWarn

Err_NeedBufPP:
	move.l	#Text_NeedBufPP,d2
	bra	ShowErr

Err_UnknownPP:
	move.l	#Text_UnknownPP,d2
	bra	ShowErr

Err_PassError:
	move.l	#Text_WrongPass,d2
	bra	ShowErr

Err_FileDest:
	move.l	#Text_FileDest,d2
	bra	ShowErr

	IFD	Code020

Err_OldProcessor:
	move.l	#Text_OldProcessor,d2
	bra	ShowErr

	ENDC

Err_NewerKickNeeded:
	move.l	#Text_NewKickNeed,d2
	bra	ShowErr

Err_NoSource:
	move.l	#Text_NoSource,d2
	bra.b	ShowErr

Err_BadComLine:
	move.l	#Text_BadComLine,d2
	bra.b	ShowErr

Err_NoDest:
	move.l	#Text_NoDest,d2
	bra.b	ShowErr

Err_NoComLineSpace:
	move.l	#Text_NoComLineSpace,d2
	bra.b	ShowErr

Err_BadLogic:
	move.l	#Text_BadLogic,d2
	bra.b	ShowErr

Err_NoMem:
	move.l	#Text_NoMemory,d2
	bra.b	ShowErr

Err_PowerPacked:
	move.l	#Text_PowerPacked,d2
	bra.b	ShowErr

Err_ReadFail:
Err_SourceCorrupt:
	move.l	#Text_BadSource,d2
	bra.b	ShowErr

Err_DestCorrupt:
	move.l	#Text_BadDest,d2
	bra.b	ShowErr

Err_SourceIsDir:
	move.l	#Text_SourceIsDir,d2
	bra.b	ShowErr

Err_WriteFail:
	move.l	#Text_WriteFail,d2
	bra.b	ShowErr

BreakPressed:
	st	(a5,Flag_Stop-DT)
	move.l	#Text_Break,d2
	bsr	PrintText
	bra.b	EndProgramErr

ShowWarn:				; Show a non-fatal error.
	move.l	d2,-(sp)
	bsr	ClearPrintBuf
	lea	Text_Warning,a0
	bsr	AddPrintBuf
	move.l	(sp)+,a0
	bsr	AddPrintBuf
	lea	Text_ClearEOL,a0
	bsr	AddPrintBuf
	lea	Text_LF,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf
	bra.b	EndProgram

ShowErr:
	move.l	d2,-(sp)
	bsr	ClearPrintBuf
	lea	Text_Error,a0
	bsr	AddPrintBuf
	move.l	(sp)+,a0
	bsr	AddPrintBuf
	lea	Text_ClearEOL,a0
	bsr	AddPrintBuf
	lea	Text_LF,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf
	bra.b	EndProgramErr

EndProgram:
	clr.b	(a5,Mode_DeleteErrDest-DT)
	bra	EndProgramNoErr

EndProgramErr:
	move.l	#20,(a5,ErrorCode-DT)
	st	(a5,Flag_Stop-DT)

EndProgramNoErr:
	move.l	(a5,SourceHandle-DT),d1
	beq.b	EndProgram1
	Call	Dos,Close
	clr.l	(a5,SourceHandle-DT)

EndProgram1:
	move.l	(a5,DestHandle-DT),d1
	beq.b	EndProgram2
	Call	Dos,Close
	clr.l	(a5,DestHandle-DT)

EndProgram2:
	move.l	(a5,SourceLock-DT),d1
	beq.b	EndProgram3
	Call	Dos,UnLock
	clr.l	(a5,SourceLock-DT)

EndProgram3:
	move.l	(a5,DestLock-DT),d1
	beq.b	EndProgram4
	Call	Dos,UnLock
	clr.l	(a5,DestLock-DT)

EndProgram4:
	tst.b	(a5,Mode_DeleteErrDest-DT)
	beq.b	EndProgram5
	bsr	ClearPrintBuf
	lea	Text_Quote,a0
	bsr	AddPrintBuf
	lea	(a5,DestName-DT),a0
	bsr	AddPrintBuf
	lea	Text_Deleted,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf
	move.l	#DestName,d1
	Call	Dos,DeleteFile

EndProgram5:
	move.l	(a5,BigBufPtr-DT),a1
	IFD	Code020
	tst.l	a1
	ENDC
	IFND	Code020
	cmp.l	#0,a1
	ENDC
	beq.b	EndProgram6
	move.l	(a5,BigBufSize-DT),d0
	Call	Exec,FreeMem
	clr.l	(a5,BigBufPtr-DT)
	bra	EndProgram6

EndProgram6:
	tst.b	(a5,Mode_NoBuffer-DT)
	bne.b	EndProgram7
	move.l	(a5,SourcePointer-DT),a1
	IFD	Code020
	tst.l	a1
	ENDC
	IFND	Code020
	cmp.l	#0,a1
	ENDC
	beq.b	EndProgram7
	move.l	(a5,SourceLen-DT),d0
	Call	Exec,FreeMem
	clr.l	(a5,SourcePointer-DT)

EndProgram7:

EndProgram8:
	move.l	(a5,CrBuf-DT),a1
	IFD	Code020
	tst.l	a1
	ENDC
	IFND	Code020
	cmp.l	#0,a1
	ENDC
	beq	EndProgram9
	move.l	(a5,CrBuf-DT),a1
	move.l	(a5,CrSize-DT),d0
	Call	Exec,FreeMem
	clr.l	(a5,CrBuf-DT)

EndProgram9:
	move.l	(a5,CrFile-DT),d1
	beq	EndProgram10
	Call	Dos,Close
	clr.l	(a5,CrFile-DT)

EndProgram10:
	move.l	(a5,CrCrunchInfo-DT),a0
	IFD	Code020
	tst.l	a0
	ENDC
	IFND	Code020
	cmp.l	#0,a0
	ENDC
	beq	EndProgram11
	Call	PP,ppFreeCrunchInfo
	clr.l	(a5,CrCrunchInfo-DT)

EndProgram11:
	tst.b	(a5,Flag_Stop-DT)
	bne.b	EndProgram12
	tst.b	(a5,Flag_CrunchBuf-DT)
	bne.b	.Cont
	tst.b	(a5,Flag_LhAPack-DT)
	bne.b	.Cont
	bra.b	EndProgram12

.Cont:
	tst.b	(a5,Flag_CrunchTried-DT)
	bne.b	EndProgram12
	bsr	CrunchDestFile

EndProgram12:
	lea	(a5,CrunchSrcName-DT),a0
	tst.b	(a0)
	beq.b	EndProgram13
	move.l	a0,d1
	Call	Dos,DeleteFile
	lea	(a5,CrunchSrcName-DT),a0
	clr.b	(a0)

EndProgram13:
	tst.b	Flag_DestName		; We had a destination, continue.
	bne.b	EndProgram14
	tst.b	(a5,Flag_LhAPack-DT)	; The file wasn't LhA'ed.
	beq.b	EndProgram14
	tst.b	(a5,Flag_DidLhAPack-DT)
	beq.b	EndProgram14
	move.l	#SourceName,d1		; LhA & No destination = Delete source.
	Call	Dos,DeleteFile

EndProgram14:
	tst.b	(a5,Flag_Stop-DT)
	bne	EndProgram15
	bsr	ClearVars
	bra	StartNewFile

EndProgram15:
	tst.b	(a5,Flag_AnchorUsed-DT)
	beq	EndProgram16
	move.l	#MyAnchor,d1
	Call	Dos,MatchEnd

EndProgram16:
	move.l	_PPBase,a1
	IFD	Code020
	tst.l	a1
	ENDC
	IFND	Code020
	cmp.l	#0,a1
	ENDC
	beq	EndProgram17
	Call	Exec,CloseLibrary

EndProgram17:
	tst.b	(a5,Flag_IntActive-DT)
	beq.b	EndProgram18
	moveq	#INTB_VERTB,d0		; Remove the counter interrupt.
	lea	VertBInterrupt,a1
	Call	Exec,RemIntServer

EndProgram18:
	move.l	(a5,FileLinkBase-DT),a2
	cmp.l	#0,a2
	beq.b	EndProgramFinal

.ContFree:
	move.l	a2,a1
	move.l	(a2,fl_Next),a2		; Get the link after this one.
	move.l	#fl_SIZEOF,d0
	Call	Exec,FreeMem
	cmp.l	#0,a2
	bne.b	.ContFree

EndProgramFinal:
	move.l	#Text_CursorOn,d2
	bsr	PrintText
	move.l	_DosBase,a1
	Call	Exec,CloseLibrary
	move.l	OldStack,sp		; At least it's ok this way...
	move.l	(a5,ErrorCode-DT),d0
	rts

*********************
** VERTB INTERRUPT **
*********************

; On a 14.3MHz CPU the interrupt code takes .03% of the total cycles/sec.
; Without the code, we could convert 13 more bytes/sec, as the conversion
; rate is currently 50kB/sec.

VertBIntCode:
	addq.b	#1,(a1)			; Add the frame counter.              12
	addq.w	#1,4(a1)		; Add the tick counter.               16
	move.b	1(a1),d0		; Get TickDelay.			      12
	cmp.b	(a1),d0			; One second passed?                   8
	bls.b	.StuffDue		;                                   10/8
	moveq	#0,d0			;                                      4
	rts				;                                     16

.StuffDue:
	clr.b	(a1)			; Reset counter.                      12
	st	2(a1)			; Set statistics due flag.            16
	moveq	#0,d0			;                                      4
	rts				;                                     16

**********
** SUBS **
**********

ANSIStrip:
	cmp.b	#ANSI_WAIT,(a5,Flag_ANSIState-DT)
	beq	.Wait
	bcs	.Clear
	bhi	.Code
	IFD	Debug			; ANSIState should always be one of the
	move.w	#$f00,$dff180		; above.
	rts
	ENDC

.Wait:
	cmp.b	#"[",d0			; We have found $1B, now there should be
	beq	.On			; a "[" for a CSI.
	move.b	#ANSI_CLEAR,(a5,Flag_ANSIState-DT)
	move.l	d0,-(sp)
	move.l	#$1b,d0			; Otherwise clear the buffered chars,
	bsr	InsertANSIOn		; and back to ANSI_CLEAR state.
	move.l	(sp)+,d0
	bsr	InsertANSIOn
	rts

.On:
	move.b	#ANSI_CODE,(a5,Flag_ANSIState-DT)
	rts				; Chars will be skipped until an alpha.

.Code:
	cmp.b	#"A",d0			; An ANSI code ends in a alpha char,
	bcc	.Check1			; check if we have such now.
	bra.b	.Check2

.Check1:
	cmp.b	#"Z",d0
	bls	.Off

.Check2:
	cmp.b	#"a",d0
	bcc	.Check3
	rts

.Check3:
	cmp.b	#"z",d0
	bls	.Off
	rts

.Off:
	move.b	#ANSI_CLEAR,(a5,Flag_ANSIState-DT)
	rts				; Found the end of the ANSI code.

.Clear:
	cmp.b	#$1b,d0			; A possible CSI start.
	beq.b	.GoWait
	cmp.b	#$9b,d0			; A CSI.
	beq.b	.On
	bsr	InsertANSIOn		; Otherwise just insert the new char.
	rts

.GoWait:
	move.b	#ANSI_WAIT,(a5,Flag_ANSIState-DT)
	rts				; Expecting a "[" next, for a CSI.

InsertANSIOn:
	tst.b	(a5,Flag_INStrip-DT)	; If InterNet strip is on, pass the
	beq.b	.NoINStrip		; char to that routine.
	bsr	InterNetStrip
	rts

.NoINStrip:
	bsr	WhiteProcess		; Otherwise send it to WhiteProcess().
	tst.l	d0			; Null = Insert nothing.
	bne.b	.Insert			; Otherwise insert it to the write buf.
	rts

.Insert:
	bsr	InsertInDest
	rts	

InsertInDest:
	move.b	d0,(a1)+		; Store the translated byte in the buf.
	addq.l	#1,d2			; Add the bytes to be saved.
	addq.w	#1,(a5,Col-DT)		; And add the column counter.
	rts

InterNetStrip:
	move.b	d0,(a4)+		; Insert the byte.
	addq.w	#1,(a5,INBufSize-DT)	; If it was an EOL, we have a full line.
	cmp.b	#LF,d0			; Now check the new line.
	beq.b	.FullLine
	cmp.b	#CR,d0
	beq.b	.FullLine
	rts

.FullLine:
	SaveR
	move.w	(a5,INBufSize-DT),d0	; Insert a null in the end of buffer.
	lea	(a5,InterNetBuf-DT),a4
	clr.b	(a4,d0.w)
	tst.b	(a5,Flag_INStripActive-DT) ; If strip is not active, check if it
	beq.b	.TestInterNet		; should be made active.
	clr.w	(a5,INBufSize-DT)	; Otherwise kill this line, and check
	cmp.b	#LF,(a4)		; if stripping should continue.
	beq.b	.CutOff
	cmp.b	#CR,(a4)		; If the line only has an EOL, it's the
	beq.b	.CutOff			; end of the header.
	LoadR
	lea	(a5,InterNetBuf-DT),a4	; Reset the buffer ptr.
	rts

.CutOff:
	clr.b	(a5,Flag_INStripActive-DT) ; Last line of the header encountered.
	cmp.b	#1,(a5,Flag_INStrip-DT)	; If the flag is 1, insert a note to the
	beq	.InsertInfo		; file, otherwise insert nothing.
	LoadR
	bsr	ResetArea		; Clear any stuff WhiteProcess has
	lea	(a5,InterNetBuf-DT),a4	; buffered, and reset our own buffer.
	rts

.InsertInfo:
	lea	(a5,InterNetBuf-DT),a0	; Insert a "HEADER REMOVED" text.
	lea	Text_INRemoved,a1
	bsr	StrCpy
	move.w	#81,(a5,INBufSize-DT)
	LoadR
	bsr	ResetArea
	lea	(a5,InterNetBuf-DT),a4
	add.l	#81,a4
	rts

.TestInterNet:
;	move.l	a4,a0			; Check if there's a period in the line.
;	moveq	#".",d0
;	bsr	StrChr
;	tst.l	d0
;	bne.b	.Cont			; If so, a possible header line.
;	bra.b	.FeedLine		; If not, just feed the line on.

.Cont:
;	move.l	a4,a0			; Check for an exclamation mark, if
;	moveq	#"!",d0			; found this could be a header start.
;	bsr	StrChr
;	tst.l	d0
;	bne.b	.Cont1
;	bra.b	.FeedLine		; Otherwise just feed the line.

.Cont1:
	move.l	a4,a0			; Check if the line starts "From ".
	lea	Text_INFrom,a1
	moveq	#5,d0
	bsr	StrNCmp
	tst.l	d0
	beq.b	.PossibFrom
	move.l	a4,a0			; Check if the line starts "Path: ".
	lea	Text_INPath,a1
	moveq	#6,d0
	bsr	StrNCmp
	tst.l	d0
	beq.b	.CutOn
	bra.b	.FeedLine		; Otherwise it's not a header start.

.PossibFrom:
	move.l	a4,a0			; If "From ", must also have a date and
	bsr	StrFirstNum		; time, which means numbers.
	tst.l	d0
	bne.b	.CheckNext		; Found, turn on the cut.
	bra.b	.FeedLine

.CheckNext:
	move.l	a4,a0			; Check if there's a colon (in time).
	moveq	#":",d0
	bsr	StrChr
	tst.l	d0
	bne.b	.CutOn			; If so, a possible header line.

.FeedLine:
	LoadR
	move.w	(a5,INBufSize-DT),d7
	subq.w	#1,d7
	lea	(a5,InterNetBuf-DT),a4

.FeedByte:
	addq.l	#1,d3			; Total bytes converted.
	move.b	(a4)+,d0
	bsr	WhiteProcess
	tst.l	d0			; Null = Insert nothing.
	beq.b	.NoInsert
	bsr	InsertInDest		; Insert all the bytes we have buffered
					; to the write buffer.
.NoInsert
	dbf.b	d7,.FeedByte
	lea	(a5,InterNetBuf-DT),a4
	clr.w	(a5,INBufSize-DT)
	rts

.CutOn:
	clr.w	(a5,INBufSize-DT)
	st	(a5,Flag_INStripActive-DT)
	LoadR
	lea	(a5,InterNetBuf-DT),a4
	rts

WhiteProcess:
	cmp.b	#" ",d0			; Process white.
	beq.b	FoundSpace
	bhi.b	FoundBlack
	cmp.b	#TAB,d0
	beq.b	FoundTab
	cmp.b	#LF,d0
	beq.b	FoundLF
	bra.b	FoundBlack

FoundSpace:
	tst.b	(a5,TabSize-DT)		; Test for Tab-Space conversion.
	beq.b	.NoSpaceTab
	addq.l	#1,(a5,SpaceNumber-DT)
	addq.w	#1,(a5,Col-DT)
	tst.b	(a5,SpaceSize-DT)
	bne.b	.SpaceConv
	moveq	#0,d0			; Insert nothing in write buffer.
	rts

.SpaceConv:
	bsr	SpaceConv
	moveq	#0,d0			; Insert nothing in write buffer.
	rts

.NoSpaceTab:
	bsr	BufChar
	moveq	#0,d0			; Insert nothing in write buffer.
	rts	

FoundTab:
	tst.b	(a5,TabSize-DT)		; Test for Tab-Space conversion.
	beq	.NoSpaceTab
	bsr	TabConv
	tst.b	(a5,SpaceSize-DT)
	bne	.SpaceConv
	moveq	#0,d0			; Insert nothing in write buffer.
	rts

.SpaceConv:
	bsr	SpaceConv
	moveq	#0,d0			; Insert nothing in write buffer.
	rts

.NoSpaceTab:
	bsr	BufChar
	moveq	#0,d0			; Insert nothing in write buffer.
	rts

FoundLF:
	clr.w	(a5,Col-DT)
	tst.b	(a5,Mode_NoCutSpace-DT)
	bne.b	.NoEndSpaceRem
	addq.l	#1,(a5,EOLs-DT)
	bsr	ResetArea
	moveq	#0,d0			; Insert nothing in write buffer.
	rts

.NoEndSpaceRem:
	bsr	FlushArea
	bsr	InsertOneEOL	
	moveq	#0,d0			; Insert nothing in write buffer.
	rts

FoundBlack:
	bsr	InsertEOLs		; Insert all buffered EOLs.
	move.b	(a5,Size_MakeEOLs-DT),d3
	beq	.NoMakeEOLs		; If MakeEOLs is on, convert all the
	BToLong	d3			; buffered area to a single EOL.
	cmp.l	(a5,SpaceNumber-DT),d3
	bhi	.NoMakeEOLs
	bsr	ResetArea
	bsr	InsertSingleEOL
	addq.l	#1,d2
	rts

.NoMakeEOLs:				; MakeEOLs is off, write all area to
	bsr	FlushArea		; the buffer.
	rts

; Gets the number starting at A0, and ending in ~[0-9]. Returns the number in
; D0.

GetNum:
	lea	(a5,NumberBuf-DT),a1

.Loop:
	cmp.b	#"0",(a0)
	bcc.b	.CheckLow
	bra.b	.End

.CheckLow:
	cmp.b	#"9",(a0)
	bls.b	.Copy
	bra.b	.End

.Copy:
	move.b	(a0)+,(a1)+
	bra.b	.Loop

.End:
	clr.b	(a1)
	lea	(a5,NumberBuf-DT),a0
	bsr	StrToNum
	rts

; Finds a space, tab, LF, CR or a null from a string pointed by A0. Returns
; location in A0.

FindWhite:
	cmp.b	#" ",(a0)
	beq	.Found
	cmp.b	#TAB,(a0)
	beq	.Found
	cmp.b	#LF,(a0)
	beq	.Found
	cmp.b	#CR,(a0)
	beq	.Found
	tst.b	(a0)
	beq	.Found
	addq.l	#1,a0
	bra	FindWhite

.Found:
	rts

LoadPrefs:
	move.l	#PrefName,d1
	move.l	#MODE_OLDFILE,d2
	Call	Dos,Open
	move.l	d0,(a5,PrefHandle-DT)
	beq	.PrefsError

	move.l	d0,d1
	move.l	#FIB,d2
	Call	Dos,ExamineFH
	tst.l	d0
	beq	.PrefsError

	lea	FIB,a0			; Alloc memory for the whole prefs file.
	move.l	fib_Size(a0),(a5,Size_Prefs-DT)
	move.l	(a5,Size_Prefs-DT),d0
	moveq	#0,d1
	Call	Exec,AllocMem
	move.l	d0,(a5,PrefPtr-DT)
	move.l	d0,(a5,PrefDecode-DT)
	beq	.PrefsError

	move.l	(a5,PrefHandle-DT),d1	; Read the prefs file in the buf.
	move.l	(a5,PrefPtr-DT),d2
	move.l	(a5,Size_Prefs-DT),d3
	Call	Dos,Read
	cmp.l	#-1,d0
	beq	.PrefsError

.ContDecode:
	move.l	(a5,PrefDecode-DT),a0	; Get the current address in the prefs
	bsr	SkipCrap		; file, and skip comments & whitespace.
	tst.b	(a0)			; If we are at a null, we are at the
	beq	EndPrefs		; end of the file.
	bsr	CopySymbol		; Otherwise in the start of a symbol,
	tst.l	d0			; copy it and check for error.
	beq	EndPrefs		; If error, exit.
	move.l	a0,(a5,PrefDecode-DT)	; Save the new address.
	bsr	DetermineArg		; Decode the argument for the option,
	move.l	d0,-(sp)		; and save it in D0.

	lea	(a5,CopySymBuf-DT),a0	; Compare the found option to those
	lea	Text_ANSIStrip,a1	; we know, and branch to a corresponding
	bsr	StrCmp			; subroutine.
	tst.l	d0
	beq	.Opt_ANSIStrip

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_INStrip,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_INStrip

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_ConvBuf,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_ConvBuf

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_MakeEOLs,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_MakeEOLs

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_EndSpaceRemoval,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_EndSpaceRemoval

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_PowerPackOutput,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_PowerPackOutput

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_SpacesToTabs,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_SpacesToTabs

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_TabsToSpaces,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_TabsToSpaces

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_TickDelay,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_TickDelay

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_TempDir,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_TempDir

	lea	(a5,CopySymBuf-DT),a0
	lea	Text_LhAPack,a1
	bsr	StrCmp
	tst.l	d0
	beq	.Opt_LhAPack

	addq.l	#4,sp			; Pop D0 ("arg") from stack.
	lea	(a5,PrintBuf-DT),a0	; The option didn't match to anything
	lea	Text_UnknownOpt,a1	; we know, so print an error.
	bsr	StrCpy
	lea	(a5,PrintBuf-DT),a0
	lea	(a5,CopySymBuf-DT),a1
	bsr	StrCat

	lea	(a5,PrintBuf-DT),a0
	lea	Text_Quote,a1
	bsr	StrCat

	lea	(a5,PrintBuf-DT),a0
	lea	Text_Period,a1
	bsr	StrCat

	lea	(a5,PrintBuf-DT),a0
	bsr	StrLFCat
	bsr	WritePrintBuf
	bra	.ContDecode		; Get the next option.

; Code for each different option. Stack has the option argument.
; -1 True.  0 False.  >0 option value.

.Opt_ANSIStrip:
	move.l	(sp)+,d0
	bmi	.Opt_ANSIStripTrue
	clr.b	(a5,Flag_AStrip-DT)
	bra	.ContDecode

.Opt_ANSIStripTrue:
	st	(a5,Flag_AStrip-DT)
	bra	.ContDecode

.Opt_INStrip:
	move.l	(sp)+,d0
	bmi	.BadOptArg
	bne.b	.Opt_INStripTrue
	clr.b	(a5,Flag_INStrip-DT)
	bra	.ContDecode

.Opt_INStripTrue:
	cmp.l	#1,d0
	bne.b	.Opt_INStripCheck
	move.b	d0,(a5,Flag_INStrip-DT)
	bra	.ContDecode

.Opt_INStripCheck:
	cmp.l	#2,d0
	bne.b	.BadOptArg
	move.b	d0,(a5,Flag_INStrip-DT)
	bra	.ContDecode

.Opt_ConvBuf:
	move.l	(sp)+,d0
	bmi	.Opt_ConvBufTrue
	st	(a5,Mode_NoBuffer-DT)
	bra	.ContDecode

.Opt_ConvBufTrue:
	clr.b	(a5,Mode_NoBuffer-DT)
	bra	.ContDecode

.Opt_MakeEOLs:
	move.l	(sp)+,d0
	beq	.ContDecode
	IFD	Code020
	cmp2.b	.MakeEOLsRange,d0
	bcs	.BadOptArg
	ENDC
	IFND	Code020
	cmp.b	#1,d0
	bcs	.BadOptArg
	cmp.b	#99,d0
	bhi	.BadOptArg
	ENDC
	move.b	d0,(a5,Size_MakeEOLs-DT)
	bra	.ContDecode

	IFD	Code020

.MakeEOLsRange:
	dc.b	1
	dc.b	99

	ENDC

.Opt_EndSpaceRemoval:
	move.l	(sp)+,d0
	beq	.Opt_EndSpaceRemoval1
	bra	.ContDecode

.Opt_EndSpaceRemoval1:
	tst.b	(a5,Size_MakeEOLs-DT)
	bne.b	.OptConflict
	st	(a5,Mode_NoCutSpace-DT)
	bra	.ContDecode

.Opt_PowerPackOutput:
	move.l	(sp)+,d0
	bne.b	.Opt_PowerPackOutput1
	bra.b	.ContDecode

.Opt_PowerPackOutput1:
	st	(a5,Flag_CrunchBuf-DT)
	bra.b	.ContDecode

.Opt_TempDir:
	move.l	(sp)+,d0
	cmp.l	#-1,d0
	beq	.ContDecode		; TempDir was OFF.
	cmp.l	#-2,d0
	bne	.BadTempDir		; The argument wasn't a string? Error.
	lea	(a5,TempDir-DT),a0
	lea	(a5,StrBuf-DT),a1
	bsr	StrCpy
	move.l	#TempDir,d1
	move.l	#ACCESS_READ,d2
	Call	Dos,Lock
	move.l	d0,d1
	beq	.BadTempDir		; Can't find TempDir? Error.
	move.l	d0,-(sp)
	move.l	#FIB,d2
	Call	Dos,Examine
	move.l	d0,-(sp)
	move.l	4(sp),d1
	Call	Dos,UnLock
	move.l	(sp)+,d0		; Can't examine TempDir? Error.
	beq	.BadTempDir
	addq.l	#4,sp			; Get rid of the lock on the stack.
	lea	FIB,a0
	tst.l	fib_DirEntryType(a0)	; Not a directory? Error.
	beq	.BadTempDir
	bmi	.BadTempDir
	bra.w	.ContDecode

.BadTempDir:
	clr.b	(a5,TempDir-DT)
	bra	.BadOptArg

.Opt_SpacesToTabs:
	move.l	(sp)+,d0
	beq	.ContDecode
	IFD	Code020
	cmp2.b	.SpacesToTabsRange,d0
	bcs	.BadOptArg
	ENDC
	IFND	Code020
	cmp.b	#2,d0
	bcs	.BadOptArg
	cmp.b	#16,d0
	bhi	.BadOptArg
	ENDC
	tst.b	(a5,TabSize-DT)
	bne.b	.OptConflict
	move.b	d0,(a5,SpaceSize-DT)
	move.b	d0,(a5,TabSize-DT)
	bra	.ContDecode

	IFD	Code020

.SpacesToTabsRange:
	dc.b	2
	dc.b	16

	ENDC

.Opt_TabsToSpaces:
	move.l	(sp)+,d0
	beq	.ContDecode
	IFD	Code020
	cmp2.b	.TabsToSpacesRange,d0
	bcs	.BadOptArg
	ENDC
	IFND	Code020
	cmp.b	#1,d0
	bcs	.BadOptArg
	cmp.b	#16,d0
	bhi	.BadOptArg
	ENDC
	tst.b	(a5,SpaceSize-DT)
	bne	.OptConflict
	move.b	d0,(a5,TabSize-DT)
	bra	.ContDecode

	IFD	Code020

.TabsToSpacesRange:
	dc.b	1
	dc.b	16

	ENDC

.Opt_TickDelay:
	move.l	(sp)+,d0
	IFD	Code020
	cmp2.b	.TickRange,d0
	bcs	.TickVB
	ENDC
	IFND	Code020
	cmp.b	#1,d0
	bcs	.TickVB
	cmp.b	#255,d0
	bhi	.TickVB
	ENDC
	move.b	d0,(a5,TickDelay-DT)
	bra	.ContDecode

.TickVB:
	move.l	4.w,a6
	move.l	VBlankFrequency(a6),(a5,TickDelay-DT)
	bra	.ContDecode

	IFD	Code020

.TickRange:
	dc.b	1
	dc.b	255

	ENDC

.Opt_LhAPack:
	move.l	(sp)+,d0
	beq.b	.Opt_LhAPackOff
	cmp.l	#-1,d0
	bne	.BadOptArg
	tst.b	(a5,Flag_CrunchBuf-DT)
	bne.b	.OptConflict
	st	(a5,Flag_LhAPack-DT)
	bra	.ContDecode

.Opt_LhAPackOff:
	clr.b	(a5,Flag_LhAPack-DT)
	bra	.ContDecode

.BadOptArg:				; Jumped into, if the arg for the option
	lea	(a5,PrintBuf-DT),a0	; made no sense.
	lea	Text_BadOptArg,a1
	bsr	StrCpy

	lea	(a5,PrintBuf-DT),a0
	lea	(a5,CopySymBuf-DT),a1
	bsr	StrCat

	lea	(a5,PrintBuf-DT),a0
	lea	Text_Quote,a1
	bsr	StrCat

	lea	(a5,PrintBuf-DT),a0
	lea	Text_Period,a1
	bsr	StrCat

	lea	(a5,PrintBuf-DT),a0
	bsr	StrLFCat
	bsr	WritePrintBuf
	bra	.ContDecode

.OptConflict:				; Jumped into if an option caused a
	lea	(a5,PrintBuf-DT),a0	; conflict with another one.
	clr.b	(a0)
	lea	Text_Error,a1
	bsr	StrCat
	lea	(a5,PrintBuf-DT),a0
	lea	Text_OptConflict,a1
	bsr	StrCat
	lea	(a5,PrintBuf-DT),a0
	bsr	StrLFCat
	bsr	WritePrintBuf
	bra	EndPrefs

.PrefsError:				; Error loading the prefs.
	move.l	#Text_PrefsError,d2
	bsr	PrintText

EndPrefs:
	move.l	(a5,PrefHandle-DT),d1	; If we opened the prefs file, close it.
	beq.b	.EndPrefs1
	Call	Dos,Close

.EndPrefs1:
	move.l	(a5,PrefPtr-DT),a1	; If we allocated memory for the prefs,
	IFD	Code020			; free it.
	tst.l	a1
	ENDC
	IFND	Code020
	cmp.l	#0,a1
	ENDC
	bne.b	.EndPrefs2
	rts

.EndPrefs2:
	move.l	(a5,Size_Prefs-DT),d0
	Call	Exec,FreeMem
	rts

SkipCrap:
	move.b	(a0),d0			; Skip characters other than [A-Z] [a-z]
	IFD	Code020			; and comments (start with semicolon).
	cmp2.b	CapRange,d0		; Comment is from the semicolon to the
	bcs.b	.CheckLow		; EOL.
	ENDC
	IFND	Code020
	cmp.b	#"A",d0
	bcs.b	.CheckLow
	cmp.b	#"Z",d0
	bhi.b	.CheckLow
	ENDC
	rts

.CheckLow:
	IFD	Code020
	cmp2.b	LowRange,d0
	bcs.b	.CheckOther
	ENDC
	IFND	Code020
	cmp.b	#"a",d0
	bcs.b	.CheckOther
	cmp.b	#"z",d0
	bhi.b	.CheckOther
	ENDC
	rts

.CheckOther:
	cmp.b	#";",(a0)
	bne	.SkipChar
	bsr	SkipLine
	subq.l	#1,a0

.SkipChar:
	addq.l	#1,a0			; Check that we don't run out of the
	tst.b	(a0)			; string, and continue.
	bne.b	SkipCrap
	rts

CopySymbol:
	lea	(a5,CopySymBuf-DT),a1

.ContCopy:
	move.b	(a0),d0			; A symbol only has chars [A-Z] [a-z],
	IFD	Code020			; and ends in equal sign. Otherwise
	cmp2.b	CapRange,d0		; return error.
	bcs	.CheckLow
	ENDC
	IFND	Code020
	cmp.b	#"A",d0
	bcs.b	.CheckLow
	cmp.b	#"Z",d0
	bhi.b	.CheckLow
	ENDC
	move.b	(a0)+,(a1)+
	bra	.ContCopy

.CheckLow:
	IFD	Code020
	cmp2.b	LowRange,d0
	bcs.b	.CheckOther
	ENDC
	IFND	Code020
	cmp.b	#"a",d0
	bcs.b	.CheckOther
	cmp.b	#"z",d0
	bhi.b	.CheckOther
	ENDC
	move.b	(a0)+,(a1)+
	bra.b	.ContCopy

.CheckOther:
	tst.b	(a0)
	bne.b	.StillLeft
	moveq	#0,d0			; If we ran out of the string in the
	rts				; process, return an error.

.StillLeft:
	cmp.b	#"=",(a0)		; Only a-Z & =, otherwise skip the whole
	bne.b	.SkipThisLine		; line.
	addq.l	#1,a0			; Skip the "=".
	clr.b	(a1)			; Close the symbol string.
	moveq	#-1,d0			; Everything okay.
	rts

.SkipThisLine:				; Skip all characters until an LF is
	bsr	SkipLine		; found, or end of string hit.
	bra	CopySymbol

SkipLine:
	cmp.b	#"\n",(a0)+
	bne	.SkipLine2
	rts

.SkipLine2:
	tst.b	(a0)
	bne.b	SkipLine
	rts

DetermineArg:
	lea	(a5,StrBuf-DT),a1

.NextChar:
	cmp.b	#'"',(a0)		; If starts with a quote, we have str.
	beq.b	.String
	cmp.b	#"O",(a0)		; Copy bytes that match O,N,F,0-9.
	beq.b	.GoodChar
	cmp.b	#"N",(a0)
	beq.b	.GoodChar
	cmp.b	#"F",(a0)
	beq.b	.GoodChar
	cmp.b	#"0",(a0)
	bcc.b	.CheckOther
	bra.b	.Decode			; When none of those was found, check
					; what we got.
.CheckOther:
	cmp.b	#"9",(a0)
	bls.b	.GoodChar
	bra.b	.Decode

.GoodChar:
	move.b	(a0)+,(a1)+
	bra.b	.NextChar

.Decode:
	clr.b	(a1)			; Close the copied string.
	lea	(a5,StrBuf-DT),a0
	cmp.b	#"O",(a0)		; If it starts with "O", it's ON | OFF.
	beq.b	.Boolean
	bsr	StrToNum		; Not a str or a bool, must be number.
	rts				; Return the number.

.Boolean:
	cmp.b	#"N",1(a0)
	beq.b	.True
	moveq	#0,d0			; False.
	rts

.True:
	moveq	#-1,d0
	rts

.String:
	move.w	#256,d0			; Max 256 bytes tolerated.
	addq.l	#1,a0			; Skip the initial quote.

.Copy:
	cmp.b	#'"',(a0)		; Another quote ends the string.
	beq.b	.Finished
	tst.b	(a0)			; Check we don't run out of the data.
	beq.b	.BadString
	move.b	(a0)+,(a1)+
	subq.w	#1,d0			; One less free byte in A1.
	beq.b	.BadString
	bra.b	.Copy

.Finished:
	clr.b	(a1)			; Finished the copied string.
	moveq	#-2,d0
	rts

.BadString:				; Bad string, return OFF.
	moveq	#0,d0
	rts

PrintReading:				; Print "Reading".
	SaveR
	lea	(a5,PrintBuf-DT),a0
	clr.b	(a0)
	lea	Text_Reading,a1
	bsr	StrCat
	lea	(a5,PrintBuf-DT),a0
	lea	Text_ClearEOL,a1
	bsr	StrCat
	lea	(a5,PrintBuf-DT),a0
	lea	Text_CR,a1
	bsr	StrCat
	bsr	WritePrintBuf
	LoadR
	rts

PrintWriting:				; Print "Writing".
	SaveR
	lea	(a5,PrintBuf-DT),a0
	clr.b	(a0)
	lea	Text_Writing,a1
	bsr	StrCat
	lea	(a5,PrintBuf-DT),a0
	lea	Text_ClearEOL,a1
	bsr	StrCat
	lea	(a5,PrintBuf-DT),a0
	lea	Text_CR,a1
	bsr	StrCat
	bsr	WritePrintBuf
	LoadR
	rts

; Allocates the read and write buffers for the file depending on free
; memory.

AllocBuffers:
	move.l	(a5,CurrentLink-DT),a0
	move.l	(a5,SourceLen-DT),d0
	tst.b	(a5,Mode_NoBuffer-DT)	; We have a full read buffer, so
	beq.b	.OnlyDest		; allocate only the write buffer.
	move.l	d0,d1
	lsr.l	#3,d1
	add.l	d0,d0
	add.l	d1,d0			; D0 = 212% D0
	bra.b	.DoAlloc

.OnlyDest:
	move.l	d0,d1
	lsr.l	#3,d1
	add.l	d1,d0			; D0 = 112% D0

.DoAlloc:
	move.l	d0,-(sp)
	moveq	#0,d1
	Call	Exec,AllocMem
	tst.l	d0
	beq.b	.NewTry
	move.l	d0,(a5,BigBufPtr-DT)
	move.l	(sp)+,(a5,BigBufSize-DT)

	tst.b	(a5,Mode_NoBuffer-DT)	; We have a full read buffer, so
	beq.b	.SetOnlyDest		; allocate only the write buffer.
	move.l	(a5,BigBufSize-DT),d0
	lsr.l	#1,d0
	move.l	(a5,BigBufPtr-DT),(a5,SourcePointer-DT)
	move.l	d0,(a5,Size_SrcBuf-DT)
	move.l	(a5,BigBufPtr-DT),(a5,DestPointer-DT)
	add.l	d0,(a5,DestPointer-DT)
	move.l	d0,(a5,Size_DstBuf-DT)
	rts

.SetOnlyDest:
	move.l	(a5,BigBufSize-DT),(a5,Size_DstBuf-DT)
	move.l	(a5,BigBufPtr-DT),(a5,DestPointer-DT)
	rts

.NewTry:
	move.l	(sp)+,d0
	lsr.l	#2,d0			; D0 = 75% D0
	move.l	d0,d1
	add.l	d0,d0
	add.l	d1,d0
	cmp.l	#102400,d0		; Lower limit of 100kB for buffer(s).
	bcs.b	.NoAllocPossib
	bra.b	.DoAlloc

.NoAllocPossib:
	move.l	#Text_NoMemConvert,d2
	bra	ShowErr

CrunchDestFile:
	st	(a5,Flag_CrunchTried-DT)
	bsr	ClearPrintBuf
	lea	Text_Crunching1,a0
	bsr	AddPrintBuf
	lea	(a5,DestName-DT),a0
	bsr	AddPrintBuf
	lea	Text_Crunching2,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf

	tst.b	(a5,Flag_LhAPack-DT)
	bne	DoLhAPack

	move.l	#CrunchSrcName,d1	; Open the DestName file.
	move.l	#ACCESS_READ,d2
	Call	Dos,Lock
	move.l	d0,(a5,DestLock-DT)
	beq.w	Err_NoCrunchFile	; If no lock, cannot crunch.
	move.l	(a5,DestLock-DT),d1	; Otherwise check it
	move.l	#FIB,d2
	Call	Dos,Examine
	move.l	d0,-(sp)		; Save result code
	move.l	(a5,DestLock-DT),d1
	Call	Dos,UnLock
	clr.l	(a5,DestLock-DT)
	move.l	(sp)+,d0		; Boolean
	beq.w	Err_NoCrunchFile	; If no Examine(), cannot crunch.
	lea	FIB,a0
	move.l	fib_Size(a0),(a5,CrSize-DT)

	move.l	(a5,CrSize-DT),d0
	moveq	#0,d1
	Call	Exec,AllocMem
	move.l	d0,(a5,CrBuf-DT)
	beq	Err_NoCrunchMem

	move.l	#CrunchSrcName,d1
	move.l	#MODE_OLDFILE,d2
	Call	Dos,Open
	move.l	d0,(a5,CrFile-DT)

	bsr	PrintReading
	move.l	(a5,CrFile-DT),d1
	move.l	(a5,CrBuf-DT),d2
	move.l	(a5,CrSize-DT),d3
	Call	Dos,Read
	cmp.l	#-1,d0
	beq	Err_CrunchReadWrite

	move.l	(a5,CrFile-DT),d1
	Call	Dos,Close
	clr.l	(a5,CrFile-DT)

	move.l	#CRUN_BEST,d0
	move.l	#SPEEDUP_BUFFLARGE,d1

	lea	CrunchProgress,a0	; Routine to be called for progress
	sub.l	a1,a1
	Call	PP,ppAllocCrunchInfo
	move.l	d0,(a5,CrCrunchInfo-DT)
	beq	Err_NoCrunchMem

	move.l	(a5,CrCrunchInfo-DT),a0
	move.l	(a5,CrBuf-DT),a1
	move.l	(a5,CrSize-DT),d0

	Call	PP,ppCrunchBuffer

	move.l	d0,(a5,CrDestSize-DT)

	cmp.l	#PP_CRUNCHABORTED,d0
	beq	BreakPressed
	cmp.l	#PP_BUFFEROVERFLOW,d0
	beq	Err_CrunchOverflow

	move.l	#DestName,d1
	move.l	#MODE_NEWFILE,d2
	Call	Dos,Open
	move.l	d0,(a5,CrFile-DT)
	beq	Err_CrunchReadWrite

	move.l	(a5,CrFile-DT),d0
	move.l	#CRUN_BEST,d1
	move.l	#FALSE,d2
	moveq	#0,d3
	Call	PP,ppWriteDataHeader
	tst.l	d0
	beq	Err_CrunchReadWrite

	bsr	PrintWriting
	move.l	(a5,CrFile-DT),d1
	move.l	(a5,CrBuf-DT),d2
	move.l	(a5,CrDestSize-DT),d3
	Call	Dos,Write
	cmp.l	#-1,d0
	beq	Err_CrunchReadWrite

	move.l	(a5,CrFile-DT),d1
	Call	Dos,Close
	clr.l	(a5,CrFile-DT)

	move.l	(a5,CrBuf-DT),a1
	move.l	(a5,CrSize-DT),d0
	Call	Exec,FreeMem
	clr.l	(a5,CrBuf-DT)

	move.l	(a5,CrCrunchInfo-DT),a0
	Call	PP,ppFreeCrunchInfo
	clr.l	(a5,CrCrunchInfo-DT)

	move.l	(a5,CrSize-DT),-(sp)
	move.l	(a5,CrDestSize-DT),-(sp)
	move.l	(a5,CrSize-DT),-(sp)
	st	(a5,Flag_StatsDue-DT)
	bsr	CrunchProgress
	add.l	#12,sp

	move.l	#Text_LF,d2
	bsr	PrintText
	move.l	#Text_LF,d2
	bsr	PrintText
	rts

DoLhAPack:
	lea	(a5,StrBuf-DT),a0
	lea	Text_LhALine,a1
	bsr	StrCpy
	lea	(a5,StrBuf-DT),a0
	bsr	StrEnd
	lea	(a5,DestName-DT),a1
	bsr	MakeLhAName
	lea	(a5,StrBuf-DT),a0
	lea	Text_Space,a1
	bsr	StrCat
	lea	(a5,StrBuf-DT),a0
	lea	(a5,CrunchSrcName-DT),a1
	bsr	StrCat
	move.l	#StrBuf,d2
	bsr	PrintText
	move.l	#Text_LF,d2
	bsr	PrintText

	move.l	#StrBuf,d1
	move.l	#LhATagList,d2
	Call	Dos,SystemTagList
	move.l	d0,(a5,ErrorCode-DT)
	bne	EndProgramErr
	st	(a5,Flag_DidLhAPack-DT)
	move.l	#Text_LF,d2
	bsr	PrintText
	rts

; A0  Ptr for the converted name.
; A1  Ptr to the original name.

MakeLhAName:
	movem.l	a0-a1,-(sp)
	move.l	a1,a0
	bsr	StrLen
	move.w	d0,(a5,MakeNameLen-DT)
	movem.l	(sp)+,a0-a1
	move.l	a0,-(sp)		; Copy the original name to destination.
	bsr	StrCpy
	move.l	(sp)+,a0
	bsr	StrEnd
	move.w	(a5,MakeNameLen-DT),d0
	Say	"Length:"
	ShowReg	d0
	cmp.l	#3,d0			; Doesn't have space for the simplest,
	bcs.b	.AddSuf			; "a.b", so just add the suffix.
	subq.l	#2,a0
	subq.l	#2,d0
	cmp.b	#".",(a0)		; ".x"
	beq.b	.KillOldSuffix
	subq.l	#1,a0
	subq.l	#1,d0
	beq.b	.AddSuf
	cmp.b	#".",(a0)		; ".xx"
	beq.b	.KillOldSuffix
	subq.l	#1,a0
	subq.l	#1,d0
	beq.b	.AddSuf
	cmp.b	#".",(a0)		; ".xxx"
	beq.b	.KillOldSuffix
	bra.b	.AddSuf

.KillOldSuffix:
	lea	Text_LhASuffix,a1	; ".LHA"
	bsr	StrCpy			; Copy the suffix on the old suffix.
	rts

.AddSuf:
	bsr	StrEnd
	lea	Text_LhASuffix,a1	; ".LHA"
	bsr	StrCpy
	rts

CrunchProgress:
	SaveR
	lea	DT,a5
	tst.b	(a5,Flag_StatsDue-DT)
	bne.b	.DoStats
	LoadR
	moveq	#-1,d0
	rts

.DoStats:
	clr.b	(a5,Flag_StatsDue-DT)

	moveq	#0,d0			; Get the signals.
	moveq	#0,d1
	Call	Exec,SetSignal
	btst	#SIGBREAKB_CTRL_C,d0	; Check if ^C was pressed.
	bne.b	.Abort

	bsr	ClearPrintBuf
	lea	Text_Done,a0
	bsr	AddPrintBuf

	move.l	4+60(sp),d0
	move.l	12+60(sp),d1
	bsr	Percentage
	bsr	NumPrintBuf

	lea	Text_PercentSign,a0
	bsr	AddPrintBuf

	lea	Text_Gain,a0
	bsr	AddPrintBuf

	move.l	8+60(sp),d0
	move.l	4+60(sp),d1
	bsr	Percentage
	moveq	#100,d1
	sub.l	d0,d1
	move.l	d1,d0
	bsr	NumPrintBuf

	lea	Text_PercentSign,a0
	bsr	AddPrintBuf

	lea	Text_CR,a0
	bsr	AddPrintBuf

	bsr	WritePrintBuf

	LoadR	
	moveq	#-1,d0
	rts

.Abort:
	LoadR
	moveq	#0,d0
	rts

; A0 - Ptr to pattern.

FormFileLinks:
	move.l	a0,d1			; Get the first file.
	move.l	#MyAnchor,d2
	pea	(a5,FileLinkBase-DT)
	Call	Dos,MatchFirst
	st	(a5,Flag_AnchorUsed-DT)
	tst.l	d0
	bne.b	.NoMatch

.GetNextFile:
	move.l	#fl_SIZEOF,d0		; Allocate a new FileLink.
	move.l	#MEMF_CLEAR,d1
	Call	Exec,AllocMem
	move.l	(sp)+,a0		; Link it to the old FileLink.
	move.l	a0,(a5,OldFileLinkPtr-DT)
	move.l	d0,(a0)
	move.l	d0,a1			; Prepare copying data from the anchor

.UseOldLink:
	lea	MyAnchor+ap_Info,a0	; to the FileLink.
	tst.l	(fib_DirEntryType,a0)
	bgt.b	.SkipThis		; Skip directories.
	st	(a5,Flag_FileFound-DT)	; Now we have at least one file.
	move.l	(fib_Size,a0),(fl_Size,a1)
	beq.b	.SkipThis		; Skip empty files.
	move.l	a1,-(sp)		; Store for .GetNextFile linkage.
	lea	(fib_FileName,a0),a0	; Copy the name from FIB to current
	lea	(fl_FileName,a1),a1	; FileLink.
	exg	a0,a1
	bsr	StrCpy
	move.l	(sp),a1
	add.l	#fl_FullName,a1
	lea	MyAnchor+ap_Buf,a0
	exg	a0,a1
	bsr	StrCpy

	move.l	#MyAnchor,d1		; Get the next file.
	Call	Dos,MatchNext
	tst.l	d0
	bne.b	.NoMatch
	bra	.GetNextFile

.SkipThis:
	move.l	a1,-(sp)
	move.l	#MyAnchor,d1
	Call	Dos,MatchNext
	move.l	(sp)+,a1
	tst.l	d0			; Got a new file, copy the data to old
	beq.b	.UseOldLink		; FileLink.
	move.l	#fl_SIZEOF,d0		; No new file, kill this FileLink.
	Call	Exec,FreeMem
	move.l	(a5,OldFileLinkPtr-DT),a0
	clr.l	(a0)			; Clear the link to next in the last true
	bra.b	.NoMatchNoStack		; FileLink.

.NoMatch:
	addq.l	#4,sp

.NoMatchNoStack:
	lea	MyAnchor,a0		; Check if ^C has been pressed.
	tst.l	ap_FoundBreak(a0)
	bne.b	BreakPressed
	Call	Dos,IoErr		; Find the reason for stopping.
	cmp.l	#ERROR_NO_MORE_ENTRIES,d0
	bne.b	.RealError		; If that wasn't the reason, we have an
	rts				; error.

.RealError:
	st	(a5,Flag_Stop-DT)
	cmp.l	#ERROR_OBJECT_NOT_FOUND,d0
	beq	Err_NoSource
	cmp.l	#ERROR_DEVICE_NOT_MOUNTED,d0
	beq	Err_NoSource
	move.l	d0,d1
	move.l	#Text_Error,d2
	move.l	#PrintBuf,d3
	move.l	#256,d4
	Call	Dos,Fault
	lea	(a5,PrintBuf-DT),a0
	bsr	StrLFCat
	bsr	WritePrintBuf
	bra	EndProgramErr

InsertEOLs:
	move.l	(a5,EOLs-DT),d3		; Insert "EOLs" EOLs.
	bne.b	.EOLsWaiting
	rts

.EOLsWaiting:
	clr.l	(a5,EOLs-DT)
	add.l	d3,d2			; Add the number of LFs.
	tst.b	(a5,Mode-DT)		; If ToPC or ToSF7, add a CR too.
	bpl.b	.DoInsertEOLs
	add.l	d3,d2			; Add the number of CRs.

.DoInsertEOLs:
	subq.l	#1,d3

.DoInsert:
	bsr	InsertSingleEOL
	dbf.b	d3,.DoInsert
	rts

; Inserts an EOL according to Mode, and adds D2.

InsertOneEOL:
	move.b	#LF,(a1)+
	tst.b	(a5,Mode-DT)		; If ToPC or ToSF7, add a CR too.
	bmi.b	.ForeignEOL
	addq.l	#1,d2
	rts

.ForeignEOL:
	move.b	#CR,(a1)+
	addq.l	#2,d2
	rts

; Inserts an EOL according to Mode, but does not add D2.

InsertSingleEOL:
	move.b	#LF,(a1)+
	tst.b	(a5,Mode-DT)		; If ToPC or ToSF7, add a CR too.
	bmi.b	.ForeignEOL
	rts

.ForeignEOL:
	move.b	#CR,(a1)+
	rts

FlushArea:
	tst.b	(a5,TabSize-DT)		; Insert buffered spaces and tabs to
	bne.b	.SpaceTabConv		; the write buffer.
	lea	(a5,SpaceBuf-DT),a2
	move.l	(a5,SpaceNumber-DT),d3
	beq.b	.NothingToCopy
	add.l	d3,d2
	subq.l	#1,d3

.CopyArea:
	move.b	(a2)+,(a1)+
	dbf.b	d3,.CopyArea

.NothingToCopy:
	bsr	ResetArea
	rts

.SpaceTabConv:
	tst.b	(a5,PreSpace-DT)
	beq	.NoPreSpace
	move.b	#" ",(a1)+
	addq.l	#1,d2

.NoPreSpace:
	move.l	(a5,Tabs-DT),d3
	beq	.NoTabs
	add.l	d3,d2
	subq.l	#1,d3

.InsertTabs:
	move.b	#TAB,(a1)+
	dbf	d3,.InsertTabs

.NoTabs:
	move.l	(a5,SpaceNumber-DT),d3
	beq.b	.NoSpaces
	add.l	d3,d2
	subq.l	#1,d3

.InsertSpaces
	move.b	#" ",(a1)+
	dbf.b	d3,.InsertSpaces

.NoSpaces:
	bsr	ResetArea
	rts

ResetArea:
	tst.b	(a5,TabSize-DT)		; Clear all buffered spaces and tabs.
	beq.b	.NoSpaceTabConv
	clr.l	(a5,SpaceNumber-DT)
	clr.l	(a5,Tabs-DT)
	clr.b	(a5,PreSpace-DT)
	rts

.NoSpaceTabConv:
	lea	(a5,SpaceBuf-DT),a2
	clr.l	(a5,SpaceNumber-DT)
	rts

BufChar:
	move.b	d0,(a2)+		; No Space-Tab conversion active,
	addq.l	#1,(a5,SpaceNumber-DT)	; buffer all area found.
	addq.w	#1,(a5,Col-DT)
	rts

SpaceConv:
	cmp.l	#1,(a5,SpaceNumber-DT)	; If Spacenumber<1, don't try to convert
	bcc.b	.ContConv		; to tabs.  No use, and time wasted in
	rts

.ContConv:
	move.w	(a5,Col-DT),d5
	ext.l	d5
	move.l	(a5,SpaceNumber-DT),d3
	move.b	(a5,SpaceSize-DT),d4
	IFD	Code020			; Convert TabSize
	extb.l	d4
	ENDC
	IFND	Code020
	ext.w	d4
	ext.l	d4
	ENDC
	divu.w	d4,d5			; If column is divisible by SpaceSize,
	swap	d5			; it can be converted to a tab.
	tst.w	d5
	beq.b	.CanConv
	rts

.CanConv:
	cmp.l	#1,(a5,SpaceNumber-DT)	; If only one space is won, instead
	beq.b	.GotPreSpace		; of conversion, make it PreSpace.
	addq.l	#1,(a5,Tabs-DT)		; More tabs.
	clr.l	(a5,SpaceNumber-DT)	; Take the spaces out.
	rts

.GotPreSpace:
	st	(a5,PreSpace-DT)
	clr.l	(a5,SpaceNumber-DT)	; Reset SpaceNumber.
	rts

TabConv:
	move.b	(a5,TabSize-DT),d4	; TabSize = 0 means no Tabs2Spaces conv.
	IFD	Code020			; Convert TabSize
	extb.l	d4
	ENDC
	IFND	Code020
	ext.w	d4
	ext.l	d4
	ENDC
	move.w	(a5,Col-DT),d3		; Get current column.
	ext.l	d3
	divu.w	d4,d3			; Divide column with TabSize -> we get
	swap	d3			; the offset from last tab as chars.
	sub.w	d3,d4			; Get the # of spaces to the next tab.
	add.l	d4,(a5,SpaceNumber-DT)	; Add the converted spaces to SpaceBuf.
	add.w	d4,(a5,Col-DT)		; And add column too.
	rts

OpenDest:
	tst.b	(a5,Flag_CrunchBuf-DT)	; If we have any packing mode on, check
	bne.b	.CheckTempFile		; if we should use a temporary dir.
	tst.b	(a5,Flag_LhAPack-DT)
	bne.b	.CheckTempFile
	move.l	#DestName,d1		; Open the DestName file.

.DoOpen:
	move.l	#MODE_NEWFILE,d2
	Call	Dos,Open
	move.l	d0,(a5,DestHandle-DT)
	beq.w	Err_NoDest
	st	(a5,Mode_DeleteErrDest-DT)
	moveq	#0,d2
	move.l	(a5,DestPointer-DT),a1
	move.l	(a5,Table-DT),a3	; Get the table.
	lea	(a5,SpaceBuf-DT),a2
	lea	(a5,InterNetBuf-DT),a4
	rts

.CheckTempFile:
	lea	(a5,CrunchSrcName-DT),a0
	lea	(a5,DestName-DT),a1	; The default is to write on the dest.
	bsr	StrCpy
	lea	(a5,TempDir-DT),a0
	move.l	#CrunchSrcName,d1
	tst.b	(a0)
	beq.b	.DoOpen			; No TempDir, write on destination.
	lea	(a5,StrBuf-DT),a0
	lea	(a5,TempDir-DT),a1
	bsr	StrCpy
	move.l	#StrBuf,d1
	move.l	(a5,CurrentLink-DT),d2
	add.l	#fl_FileName,d2
	move.l	#256,d3
	Call	Dos,AddPart
	moveq	#4,d7
	tst.l	d0
	beq.b	CodeError
	lea	(a5,CrunchSrcName-DT),a0
	lea	(a5,StrBuf-DT),a1
	bsr	StrCpy
	move.l	#CrunchSrcName,d1
	bra.b	.DoOpen

MakeSourceASCII:
	lea	(a5,SourceLenASCII-DT),a0
	move.l	(a5,SourceLen-DT),d0
	bsr	NumToStr
	move.l	a0,(a5,SourceLenASCIIAddr-DT)
	rts
	
CalcReadRate:
	move.w	(a5,TickCount-DT),d1	; Check the optimal read block size so
	ext.l	d1			; we get progress reports at the user
	add.l	d1,ReadTime		; chosen intervals.
	move.l	ReadTime,d1
	move.l	(a5,ReadBytes-DT),d0
	move.b	(a5,TickDelay-DT),d2
	IFD	Code020
	and.l	#$ff,d2
	divu.l	d1,d0			; Bytes/tick.
	mulu.l	d2,d0			; Bytes/sec.
	ENDC
	IFND	Code020
	and.w	#$ff,d0
	divu.w	d1,d0
	bvs.b	.Overflow
	ext.l	d0
	mulu.w	d2,d0
	ENDC
	cmp.l	#10240,d0
	bcs	.TooLow
	move.l	d0,RBlockSize
	rts

.TooLow:
	move.l	#10240,RBlockSize
	rts

.Overflow:
	move.l	#65535,d0
	mulu.w	d2,d0
	move.l	d0,RBlockSize
	rts

PrintStats:
	movem.l	d1-d3/a0-a1,-(sp)
	moveq	#0,d0			; Get the signals.
	moveq	#0,d1
	Call	Exec,SetSignal
	movem.l	(sp)+,d1-d3/a0-a1
	btst	#SIGBREAKB_CTRL_C,d0	; Check if ^C was pressed.
	bne	BreakPressed
	clr.b	(a5,Flag_StatsDue-DT)
	movem.l	d1-d7/a0-a6,-(sp)
	move.l	d3,-(sp)
	bsr	ClearPrintBuf
	move.l	#Text_Converted,a0	; The progress info for fully buffered
	bsr	AddPrintBuf		; input.
	lea	(a5,NumberBuf-DT),a0
	move.l	(sp)+,d0		; The bytes converted.
	bsr	NumToStr
	bsr	AddPrintBuf
	move.l	#Text_Slash,a0
	bsr	AddPrintBuf
	move.l	(a5,SourceLenASCIIAddr-DT),a0
	bsr	AddPrintBuf
	move.l	#Text_ClearEOL,a0
	bsr	AddPrintBuf
	move.l	#Text_CR,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf
	movem.l	(sp)+,d1-d7/a0-a6
	rts

ClearVars:				; Clear variables that may change
	lea	(a5,SpaceBuf-DT),a2	; between different files.
	clr.l	(a5,EOLs-DT)
	clr.l	(a5,WrittenBytes-DT)
	clr.l	(a5,ReadBytes-DT)
	clr.l	(a5,LeftBytes-DT)
	clr.l	(a5,InputBytes-DT)
	clr.b	(a5,Flag_PPUsed-DT)
	clr.b	(a5,Flag_DidLhAPack-DT)
	clr.l	(a5,SpaceNumber-DT)
	clr.l	(a5,Tabs-DT)
	clr.b	(a5,PreSpace-DT)
	rts

ClearPrintBuf:
	move.l	#PrintBuf,(a5,PrintBufPtr-DT)
	rts

AddPrintBuf:				; Add the string in A0 to PrintBuf.
	move.l	(a5,PrintBufPtr-DT),a1

apb_Copy:
	move.b	(a0)+,(a1)+
	bne.b	apb_Copy
	subq.l	#1,a1			; A1 is 1 past the null. We want to
	move.l	a1,(a5,PrintBufPtr-DT)	; overwrite the null.
	rts

NumPrintBuf:				; Add the string in A0 to PrintBuf.
	move.l	(a5,PrintBufPtr-DT),a0
	bsr	StrNumCat
	move.l	(a5,PrintBufPtr-DT),a0
	bsr	StrEnd
	move.l	a0,(a5,PrintBufPtr-DT)
	rts

WritePrintBuf:
	move.l	#PrintBuf,d2
	bsr.b	PrintText
	rts

PrintText:
	move.l	d2,a0
	move.l	_DosBase,a6		; Check if "dos.library" has been
	IFD	Code020			; opened.
	tst.l	a6
	ENDC
	IFND	Code020
	cmp.l	#0,a6
	ENDC
	beq.b	OpenErrDos		; If it hasn't, open a temporary
	tst.l	(a5,OutStruct-DT)	; "dos.library".
	beq.b	OpenErrDos

PrintText1:
	tst.b	(a0)+			; Find out the length of the string.
	bne.b	PrintText1
	sub.l	d2,a0
	subq.w	#1,a0
	move.l	a0,d3
	move.l	(a5,OutStruct-DT),d1
	jsr	_LVOWrite(a6)
	tst.l	_DosBase
	beq.b	CloseErrDos
	rts

OpenErrDos:
	movem.l	d0-d7/a0-a5,-(sp)
	lea	_DosName,a1
	moveq	#0,d0
	Call	Exec,OpenLibrary
	move.l	d0,(a5,ErrDosBase-DT)
	move.l	d0,a6
	IFD	Code020
	tst.l	a6
	ENDC
	IFD	Code020
	cmp.l	#0,a6
	ENDC
	bne.b	OpenErrDos2
	movem.l	(sp)+,d0-d7/a0-a5
	rts

OpenErrDos2:
	move.l	d0,a6
	jsr	_LVOOutput(a6)
	move.l	d0,(a5,OutStruct-DT)
	bne.b	OpenErrDos1
	movem.l	(sp)+,d0-d7/a0-a5
	rts

OpenErrDos1:
	movem.l	(sp)+,d0-d7/a0-a5
	bra.b	PrintText1

CloseErrDos:
	move.l	(a5,ErrDosBase-DT),a1
	Call	Exec,CloseLibrary
	rts

PrintTextLen:
	move.l	(a5,OutStruct-DT),d1
	Call	Dos,Write
	rts

; Skips spaces in a string pointed to by A0, returns A0 as zero if it ran out
; of string.

SkipSpace:
	cmp.b	#" ",(a0)
	beq.b	SkipSpace1
	rts

SkipSpace1:
	addq.l	#1,a0
	tst.b	(a0)
	bne.b	SkipSpace
	sub.l	a0,a0
	rts

FindEnd:
	cmp.b	#'"',(a0)		; If the first letter is a quote,
	beq.b	FindEnd_Quote		; go to FindEnd_Quote

FindEnd_Space:
	addq.l	#1,a0			; Get the next position, if it is a
	cmp.b	#" ",(a0)		; Space, we found the end
	beq.b	FindEnd_Space1
	tst.b	(a0)			; If it's the end of comline, we found
	beq.b	FindEnd_Space1		; the end of the name.
	bra.b	FindEnd_Space

FindEnd_Space1:
	subq.l	#1,a0
	rts

FindEnd_Quote:
	addq.l	#1,a0			; Return the address of the first quote
	tst.b	(a0)			; in a string in A0, or 0 for error.
	beq.b	FindEnd_Quote2
	cmp.b	#'"',(a0)
	bne.b	FindEnd_Quote
	rts

FindEnd_Quote2:
	sub.l	a0,a0
	rts

	INCDIR	"SRC:Routines/"

	INCLUDE	"Percentage.S"
	INCLUDE	"CopyName.S"

**********
** DATA **
**********

	SECTION	FastData,DATA

MyAnchor:
	dc.l	0			; ap_Base
	dc.l	0			; ap_Last
	dc.l	SIGBREAKF_CTRL_C	; ap_BreakBits
	dc.l	0			; ap_FoundBreak
	dc.b	0			; ap_Flags
	dc.b	0
	dc.w	256			; ap_Strlen
	ds.b	fib_SIZEOF
	ds.b	256

VertBInterrupt:
	dc.l	0			; Successor.
	dc.l	0			; Predecessor.
	dc.b	NT_INTERRUPT		; Type.
	dc.b	0			; Pri.
	dc.l	Text_VertBIntName	; Ptr to name.
	dc.l	TimeCounter		; Ptr to TimeCounter, IS_DATA.
	dc.l	VertBIntCode		; Ptr to VBLANK code.

RBlockSize:				; Bytes of data for a single Read().
	dc.l	10240

LhATagList:
	dc.l	TAG_END,TAG_END

ReadTime:				; Time taken in all Read()'s.
	dc.l	1

***********************
** Conversion tables **
***********************

Table_ToPC:
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0A,$00,$00,$00,$00,$00 ;00
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/" ;20
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?" ;30
	dc.b	"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O" ;40
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^"
	dc.b	"_" ; 50
	dc.b	"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o" ;60
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","{","|","}","~",$B1
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$9b,$00,$00,$00,$00 ;90
	dc.b	" ",$AD,$9B,$9C,"$",$9D,"|",$15,'"',"C",$A6,$AE,$AA,"-","R","-"
	dc.b	$F8,$F1,$FD,"3","'",$E6,$14,$F9,",","1",$A7,$AF,$AC,$AB,"3",$A8
	dc.b	$85,$A0,$8F,"A",$8E,$8F,$92,$80,$8A,$90,$88,$89,$8D,$A1,$8C,$8B
	dc.b	"D","N",$95,$A2,$93,"O",$99,"x","0",$97,$A3,$96,$9A,"Y","B",$E1
	dc.b	$85,$A0,"a","a",$84,$83,$91,$87,$8A,$82,$88,$89,$8D,$A1,$8C,$8B
	dc.b	$EB,"n",$95,$A2,$93,"o",$94,$F6,"0",$97,$A3,$96,$81,"y","B",$98

Table_Null:
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0A,$00,$00,$00,$00,$00 ;10
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/"
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?"
	dc.b	"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_"
	dc.b	"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o"
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","{","|","}","~",$7F
	dc.b	$80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F
	dc.b	$90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F
	dc.b	$A0,"¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯"
	dc.b	"°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿"
	dc.b	"À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï"
	dc.b	"Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß"
	dc.b	"à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï"
	dc.b	"ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ"

Table_Lowercase:
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0A,$00,$00,$00,$00,$00 ;10
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/"
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?"
	dc.b	"@","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o"
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","[","\\","]","^","_"
	dc.b	"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o"
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","{","|","}","~",$7F
	dc.b	$80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F
	dc.b	$90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F
	dc.b	$A0,"¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯"
	dc.b	"°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿"
	DC.B	"à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï"
	dc.b	"ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ß"
	dc.b	"à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï"
	dc.b	"ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ"

Table_Uppercase:
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0A,$00,$00,$00,$00,$00 ;10
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/"
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?"
	dc.b	"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_"
	dc.b	"`","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","{","|","}","~",$7F
	dc.b	$80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F
	dc.b	$90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F
	dc.b	$A0,"¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯"
	dc.b	"°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿"
	dc.b	"À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï"
	dc.b	"Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß"
	dc.b	"À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï"
	dc.b	"Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ÿ"

Table_ToSF7:
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0A,$00,$00,$00,$00,$00 ;10
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/"
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?"
	dc.b	"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^","_"
	dc.b	"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o"
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","{","|","}","~",$7F
	dc.b	$80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F
	dc.b	$90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F
	dc.b	$A0,"¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯"
	dc.b	"°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿"
	dc.b	"À","Á","Â","Ã","[","]","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï"
	dc.b	"Ð","Ñ","Ò","Ó","Ô","Õ","\\","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß"
	dc.b	"à","á","â","ã","{","}","æ","ç","è","é","ê","ë","ì","í","î","ï"
	dc.b	"ð","ñ","ò","ó","ô","õ","|","÷","ø","ù","ú","û","ü","ý","þ","ÿ"

Table_FromSF7:
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0A,$00,$00,$00,$00,$00 ;10
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/"
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?"
	dc.b	"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","Ä","Ö","Å","^","_"
	dc.b	"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o"
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","ä","ö","å","~",$7F
	dc.b	$80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F
	dc.b	$90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F
	dc.b	$A0,"¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","­","®","¯"
	dc.b	"°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿"
	dc.b	"À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï"
	dc.b	"Ð","Ñ","Ò","Ó","Ô","Õ","Ö","×","Ø","Ù","Ú","Û","Ü","Ý","Þ","ß"
	dc.b	"à","á","â","ã","ä","å","æ","ç","è","é","ê","ë","ì","í","î","ï"
	dc.b	"ð","ñ","ò","ó","ô","õ","ö","÷","ø","ù","ú","û","ü","ý","þ","ÿ"

; df is the upper block.
; dc is the lower block.

Table_FromPC:	;0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0a,$00,$00,$00,$00,$00 ;00
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/" ;20
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?" ;30
	dc.b	"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O" ;40
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]","^"
	dc.b	"_" ;50
	dc.b	"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o" ;60
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","" ;70
	dc.b	"Ç","ü","é","å","ä","à","å","ç","ê","ë","è","ï","î","ì","Ä","Å" ;80
	dc.b	"È","æ","Æ","ô","ö","ò","û","ù","ÿ","Ö","Ü",$a2,"£",$a5,"P","f" ;90
	dc.b	"á","í","ó","ú","ñ","Ñ","ª","º","¿",".",".","½","¼","¡","«","»" ;A0
	dc.b	$7f,$7f,$7f,"|","+","#","+",".","#","#","|","#","#","'","#","." ;B0
	dc.b	"`","+","+","+","-","+","#","+","#","#","#","#","#","=","#","#" ;C0
	dc.b	"+","#","+","`","#","#",".","+","#","'",".",$7f,"o","[","]","°" ;D0
	dc.b	"c","ß","r","+","E","ó",$b5,"i","o","0","O","ð","ø","ø","E","A" ;E0
	dc.b	"=","±",">","<","í","j","÷","~","°","·","·","V","n","²","·"," " ;F0

Table_Combined:	;0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$09,$0a,$00,$00,$00,$00,$00 ;00
	dc.b	$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$1b,$00,$00,$00,$00 ;10
	dc.b	" ","!",'"',"#","$","%","&","'","(",")","*","+",",","-",".","/" ;20
	dc.b	"0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?" ;30
	dc.b	"@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O" ;40
	dc.b	"P","Q","R","S","T","U","V","W","X","Y","Z","Ä","Ö","Å","^","_" ;50
	dc.b	"`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o" ;60
	dc.b	"p","q","r","s","t","u","v","w","x","y","z","ä","ö","å","~","" ;70
	dc.b	"Ç","ü","é","å","ä","à","å","ç","ê","ë","è","ï","î","ì","Ä","Å" ;80
	dc.b	"È","æ","Æ","ô","ö","ò","û","ù","ÿ","Ö","Ü",$a2,"£",$a5,"P","f" ;90
	dc.b	"á","í","ó","ú","ñ","Ñ","ª","º","¿",".",".","½","¼","¡","«","»" ;A0
	dc.b	$7f,$7f,$7f,"|","+","#","+",".","#","#","|","#","#","'","#","." ;B0
	dc.b	"`","+","+","+","-","+","#","+","#","#","#","#","#","=","#","#" ;C0
	dc.b	"+","#","+","`","#","#",".","+","#","'",".",$7f,"æ","[","]","^" ;D0
	dc.b	"c","ß","r","+","E","ó",$b5,"i","o","0","O","ð","ø","ø","E","A" ;E0
	dc.b	"=","±",">","<","í","j","÷","~","°","·","·","V","n","²","·"," " ;F0

	INCDIR	"SRC:Port/"

	IFD	Code020

CapRange:
	dc.b	"A"
	dc.b	"Z"

LowRange:
	dc.b	"a"
	dc.b	"z"

	ENDC

Flag_DestName:				; We have a real destination.
	dc.b	$ff

_DosName:
	dc.b	"dos.library",0

PPName:
	PPNAME

PrefName:
	dc.b	"ENV:Port.Prefs",0

***********
** TEXTS **
***********

Text_VertBIntName:
	dc.b	"Port VBlank Timer",0

Text_CodeError:
	INCBIN	"PortCodeError"
	dc.b	0

Text_HelpText:
	IFD	Debug
	INCBIN	"TestVersion.TXT"
	ENDC
	INCBIN	"PortOpts1"
	dc.b	0

Text_Credits:
	INCBIN	"PortOpts2"
	dc.b	0

Text_Header:
	INCBIN	"Port.Header"
	dc.b	0

Text_CursorOff:
	dc.b	"\c0 p",0

Text_CursorOn:
	dc.b	"\c1 p",0

Text_Error:
	dc.b	"Error!  ",0

Text_Warning:
	dc.b	"Warning:  ",0

; These need the LF even though they are error messages, because there must
; be one LF between the messages of each different file.

Text_CrunchReadWrite:
	dc.b	"Could not read/write the file for PowerPacking\n",0

Text_NoCrunchMem:
	dc.b	"Not enough memory for PowerPacking.\n",0

Text_CrunchOverflow:
	dc.b	"Buffer overflow.  File was not PowerPacked.\n",0

Text_NoCrunchFile:
	dc.b	"Could not lock the file for PowerPacking.\n",0

Text_NeedBufPP:
	dc.b	"Cannot use NoBuffer mode with PowerPacked files.",0

Text_Decrunching:
	dc.b	"Loading & decrunching a PowerPacked file...\n",0

Text_UnknownPP:
	dc.b	"The file is packed with an unknown version of PowerPacker.",0

Text_WrongPass:
	dc.b	"Incorrect password, can't decrypt.",0

Text_FileDest:
	dc.b	"Can't have a file destination for wildcards.",0

	IFD	Code020

Text_OldProcessor:
	dc.b	"At least 68020 is needed.",0

	ENDC

Text_NewKickNeed:
	dc.b	"At least system V37 is needed.",0

Text_PrefsError:
	dc.b	"Error reading preferences, defaults used.\n\n",0

Text_BadComLine:
	dc.b	"Bad commandline.",0

Text_Reading:
	dc.b	"Reading...",0

Text_Writing:
	dc.b	"Writing...",0

Text_ANSIStrip:
	dc.b	"ANSIStrip",0

Text_MakeEOLs:
	dc.b	"MakeEOLs",0

Text_INStrip:
	dc.b	"InterNetStrip",0

Text_EndSpaceRemoval:
	dc.b	"EndSpaceRemoval",0

Text_PowerPackOutput:
	dc.b	"PowerPackOutput",0

Text_SpacesToTabs:
	dc.b	"SpacesToTabs",0

Text_TabsToSpaces:
	dc.b	"TabsToSpaces",0

Text_TickDelay:
	dc.b	"TickDelay",0

Text_TempDir:
	dc.b	"TempDir",0

Text_LhAPack:
	dc.b	"LhAPack",0

Text_INFrom:
	dc.b	"From ",0

Text_INPath:
	dc.b	"Path: ",0

Text_UnknownOpt:
	dc.b	"Unknown preferences option \"",0

Text_BadOptArg:
	dc.b	"Bad argument for preferences option \"",0

Text_ConvBuf:
	dc.b	"ConversionBuffer",0

Text_NoSource:
	dc.b	"Could not open source file.",0

Text_NoDest:
	dc.b	"Could not open destination file.",0

Text_SourceIsDir:
	dc.b	"Source cannot be a directory.",0

Text_WriteFail:
	dc.b	"Can't write data.",0

Text_NoComLineSpace:
	dc.b	"The mode must be separated with at least one space.",0

Text_BadLogic:
	dc.b	"Conflicting options.",0

Text_OptConflict:
	dc.b	"Conflicting options in preferences.",0

Text_NoMemConvert:
	dc.b	"Not enough memory to convert the file.",0

Text_NoMemory:
	dc.b	"Not enough memory to load the file.",0

Text_PowerPacked:
	dc.b	"File is a PowerPacked, \"powerpacker.library\" is needed to read.",0

Text_PowerPackNeed:
	dc.b	"\"powerpacker.library\" V35+ is required.",0

Text_BadSource:
	dc.b	"Source file corrupted.",0

Text_BadDest:
	dc.b	"Destination corrupted.",0

Text_Crunching1:
	dc.b	"Packing \"",0

Text_INRemoved:
	dc.b	"\nHEADER-REMOVED--HEADER-REMOVED--HEADER-REMOVED--HEADER-REMOVED--HEADER REMOVED\n\n",0

Text_Deleted:
	dc.b	'" deleted.\n\0'

Text_ConvFile1:
	dc.b	"Converting file \"",0

Text_Crunching2:
Text_ConvFile2:
	dc.b	"\"...\n",0

Text_Done:
	dc.b	"Done: ",0

Text_Gain:
	dc.b	"  Gain: ",0

Text_Input:
	dc.b	"Input: ",0

Text_Output:
	dc.b	"  Output: ",0

Text_Read:
	dc.b	"Read: ",0

Text_Converted:
	dc.b	"Converted: ",0

Text_Checking:
	dc.b	"Checking file type...\c0K\r",0

Text_LhALine:
	dc.b	"LhA r ",0

Text_LhASuffix:
	dc.b	".LHA",0

Text_Break:
	dc.b	"-BREAK-\c0K\n",0

Text_ClearEOL:
	dc.b	"\c0K",0

Text_AmigaSuf:
	dc.b	".AMY",0

Text_PCSuf:
	dc.b	".PC",0

Text_SF7Suf:
	dc.b	".SF7",0

Text_CR:
	dc.b	CR,0

Text_LF:
	dc.b	LF,0

Text_Final:
	dc.b	"File size change: ",0

Text_NegSign:
	dc.b	"-",0

Text_PosSign:
	dc.b	"+",0

Text_PercentSign:
	dc.b	"%\c0K",0

Text_DoubleSpace:
	dc.b	" "
Text_Space:
	dc.b	" ",0

Text_Slash:
	dc.b	"/",0

Text_Period:
	dc.b	".",0

Text_Quote:
	dc.b	'"',0


	SECTION	FastBlank,BSS

DT:					; Section base address.

FIB:
	ds.b	fib_SIZEOF

ErrorCode:				; Port return code.
	ds.l	1

OldFileLinkPtr:				; Ptr to the next to last (last) 'Link.
	ds.l	1

PrefDecode:				; Ptr to the current place in data.
	ds.l	1

PrefPtr:				; Ptr to loaded preferences data.
	ds.l	1

Size_Prefs:				; Size of the loaded preferences data.
	ds.l	1

PrefHandle:				; Preferences file handle.
	ds.l	1

BigBufPtr:				; Ptr for conversion buffer(s).
	ds.l	1

BigBufSize:				; Size of the conversion buffer(s).
	ds.l	1

TempBuf:				; Buffer for checking PP 4 byte ID.
	ds.l	1

CrDestSize:				; Size of the packed buffer.
	ds.l	1

CrCrunchInfo:				; Ptr to PP CrunchInfo structure.
	ds.l	1

CrBuf:					; Ptr to the buffer to crunch.
	ds.l	1

CrFile:					; File handle for file to crunch.
	ds.l	1

CrSize:					; Size of the file to be crunched.
	ds.l	1

FileLinkBase:				; Pointer to the first FileLink.
	ds.l	1

CurrentLink:				; Pointer to the current FileLink.
	ds.l	1

ErrDosBase:				; DosBase used in case of error.
	ds.l	1

PrintBufPtr:
	ds.l	1

OldStack:
	ds.l	1

SourceLock:
	ds.l	1

DestLock:
	ds.l	1

EOLs:
	ds.l	1

Table:					; Ptr to the current translation table.
	ds.l	1

SourceLen:				; Size of the source file in bytes.
	ds.l	1

Tabs:					; Counter of buffered tabs.
	ds.l	1

WrittenBytes:
	ds.l	1

ReadBytes:
	ds.l	1

LeftBytes:
	ds.l	1

InputBytes:
	ds.l	1

SourceHandle:
	ds.l	1

DestHandle:
	ds.l	1

OutStruct:
	ds.l	1

DestNStart:
	ds.l	1

SourceNameStart:
	ds.l	1

SourceNameEnd:
	ds.l	1

SourceNameLen:
	ds.l	1

_DosBase:
	ds.l	1

_PPBase:
	ds.l	1

SpaceNumber:
	ds.l	1

SourceLenASCIIAddr:
	ds.l	1

SourcePointer:				; Ptr to the read buffer.
	ds.l	1

DestPointer:				; Ptr to the write buffer.
	ds.l	1

Size_SrcBuf:				; Size of the read buffer.
	ds.l	1

Size_DstBuf:				; Size of the write buffer.
	ds.l	1

MakeNameLen:				; MakeLhAName length.
	ds.w	1

INBufSize:				; Number of bytes buffered by INStrip.
	ds.w	1

Col:
	ds.w	1

; VBLANK interrupt's IS_DATA.

TimeCounter:				; Frame counter.
	ds.b	1
TickDelay:				; Update tick delay.
	ds.b	1
Flag_StatsDue:				; Statistics due -flag.
	ds.b	1
	ds.b	1			; Padding.
TickCount:				; VB counter for read sync.
	ds.w	1

RealSourceName:
	ds.b	108			; Max filename size in FIB

CopySymBuf:				; Buffer for CopySymbol.
	ds.b	160

CrunchSrcName:				; Name of the file to crunch.
	ds.b	256

TempDir:				; Name of the temporary directory.
	ds.b	256

StrBuf:
	ds.b	256

SourceName:
	ds.b	256

DestName:
	ds.b	256

PrintBuf:
	ds.b	256

	IFD	Debug

DebugBuf:
	ds.b	256

	ENDC

SpaceBuf:
	ds.b	1024

InterNetBuf:
	ds.b	1024

NumberBuf:
	ds.b	11

ReadASCII:
	ds.b	11

SourceLenASCII:
	ds.b	11

Flag_IntActive:				; VBLANK interrupt is active.
	ds.b	1

Flag_AnchorUsed:			; Indicates that we need to MatchEnd().
	ds.b	1

Flag_Stop:				; Indicates that exit should be taken.
	ds.b	1

Flag_FileFound:				; At least one file was found.
	ds.b	1

Flag_PPUsed:				; PowerPacker library was used to load
	ds.b	1			; the file.

Flag_CrunchBuf:				; PowerPack the output file.
	ds.b	1

Flag_LhAPack:				; LhA pack the output file.
	ds.b	1

Flag_AStrip:				; Strip ANSI codes.
	ds.b	1

Flag_CrunchTried:			; Already tried crunching this file.
	ds.b	1

Flag_INStrip:				; Strip InterNet headers.
	ds.b	1			; 1-"HEADER STRIPPED" 2-Nothing.

Flag_INStripActive:			; Current data is of the header.
	ds.b	1

Flag_ANSIState:				; Are we waiting for a CSI etc.
	ds.b	1

Flag_DidLhAPack:			; The file was really packed, safe to
	ds.b	1			; delete the source if NoDest.

Mode:
	ds.b	1

TabSize:
	ds.b	1

SpaceSize:
	ds.b	1

Size_MakeEOLs:
	ds.b	1

PreSpace:
	ds.b	1

Mode_NoCutSpace:
	ds.b	1

Mode_NoBuffer:
	ds.b	1

Mode_DeleteErrDest:
	ds.b	1

Mode_SrcDeleted:
	ds.b	1
