Code020  	=	1		; Define for 020 code, comment for 000.
;Debug		=	1		; Define for Say() & ShowReg() macros.

	IFND	Code020
	MACHINE	68000
	ENDC
	IFD	Code020
	MACHINE	68020
	ENDC

	XREF	StrCat
	XREF	StrCmp
	XREF	StrCpy
	XREF	StrChr
	XREF	StrEnd
	XREF	StrFirstNum
	XREF	StrLFCat
	XREF	StrLen
	XREF	StrNCmp
	XREF	StrNumCat
	XREF	StrToNum

	XDEF	Num2ASCII

; 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 overall 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,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	Num2ASCII		; 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
	sub.l	#SIZE_MAXNEW,d0
	cmp.l	d0,d2			; Have we converted a full buffer yet?
	bls.b	MoreCharacters		; Everything okay, continue conversion.
	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
	tst.b	(a5,Mode_SrcDeleted-DT)	; If the sourcefile has been destroyed,
	bne.b	.NoBreak		; don't allow breaking.
	move.l	(sp)+,d3
	bsr	PrintStats
	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	Num2ASCII
	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	Num2ASCII

	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	Num2ASCII
	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	.SkipDir		; Skip directories.
	st	(a5,Flag_FileFound-DT)	; Now we have at least one file.
	move.l	(fib_Size,a0),(fl_Size,a1)
	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

.SkipDir:
	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	Num2ASCII
	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	Num2ASCII
	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/"

	IFD	Code020
	INCLUDE	"Num2ASCII-020.S"
	ENDC

	IFND	Code020
	INCLUDE	"Num2ASCII.S"
	ENDC

	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","[","\\","]","^","_" ;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","[","\\","]","^","_" ;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:
	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
