TestMode	=	0


* 12-Sep-93
* 59 days of hard coding

; Needs 150K to compile in AsmOne.

; 1.39 - 4:13.82
;                - +8% speed!
; 1.40 - 3:54.53
; 1.40 & A1200NoF - 2:57.93
;        A1200FastMem - 1:15.73

; Things to do:
; - Load the first 10K, check, then load the rest.
; - Don't scan back in the file when checking for PP.
; - Adjustment of the buffer sizes used for conversion.
; - Wildcards.
; - Some kind of a config file.
; - Full Amiga->PC character support.
; - Add exit error codes.
; - PowerPacker decrunch.
; - Insert a "useless" linefeed on the last line.
; - Tell when a partial file is deleted.
; - Intuition interface?
; - Use the regs more effectively.
; - Make a PC+SF7 mode.
; - Sync'ed text output, should be updated at same intervals on all machines.
; - 020 support, NO 000 support!
; - Normal text output with NoBuffer mode.
; - Lowercase mode which makes the first letter after "." uppercase,
;   or all words start uppercase.

; During the translation loop:
; A0 = Pointer to source data
; A1 = Pointer to destination data
; A2 = Pointer to space buffer
; A3 = Pointer to translation table

; D0 = Current char
; D1 = Load counter
; D2 = Counter of converted bytes in the destination buffer.
; D3 = Character read in Translation routine.

	AUTO	E\

	>EXTERN	"INCLUDE:Date.TXT",Text_HelpText+17
	INCDIR	"INCLUDE:"
	INCLUDE	"Darkness.I"
	INCLUDE	"LibOffSet"
	INCLUDE	"Exec/Memory.I"
	INCLUDE	"Dos/Dos.I"

; 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_AUTOMODE	=	 6

SIZE_DESTBUF	=	10240
SIZE_MAXNEW	=	9		; Maximum size change in one cycle.

CR		=	13
LF		=	10
TAB		=	 9

	IF	TestMode=1
	lea	Test_ComLine,a0
	move.l	#Test_Len,d0
	ENDC

ProgStart:
	move.l	a7,OldStack
	clr.b	-1(a0,d0.w)
	movem.l	a0,-(a7)
	add.l	d0,a0
	subq.l	#1,a0

	lea	_DosName,a1
	moveq	#0,d0
	move.l	ExecBase,a6
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,_DosBase

	move.l	_DosBase,a6
	jsr	_LVOOutput(a6)
	move.l	d0,OutStruct

	IF	TestMode=1
	bne	Err_TestMode
	ENDC

	move.l	#Text_CursorOff,d2
	bsr	PrintText

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

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

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

CheckOption:
	cmp.b	#"e",1(a0)
	beq	Opt_MakeEOLs
	cmp.b	#"n",1(a0)
	beq	Opt_NoCutSpace
	cmp.b	#"?",1(a0)
	beq	Credits
	cmp.b	#"t",1(a0)
	beq	Opt_TabConv
	cmp.b	#"s",1(a0)
	beq	Opt_SpaceConv
	cmp.b	#"q",1(a0)
	beq	Opt_QuietMode
	cmp.b	#"b",1(a0)
	beq	Opt_NoBufferMode
	bra	Err_BadComLine

Opt_NoCutSpace:
	tst.b	Size_MakeEOLs
	bne	Err_BadLogic
	move.b	#1,Mode_NoCutSpace
	addq.l	#2,a0
	bra	Opt_Next

Opt_TabConv:
	tst.b	TabSize
	bne	Err_BadLogic
	move.b	2(a0),d0
	cmp.b	#" ",d0
	beq	Opt_TabConv1
	sub.b	#"0",d0
	cmp.b	#TAB,d0
	bhi	Err_BadComLine
	cmp.b	#1,d0
	bcs	Err_BadComLine
	bra	Opt_BothConv

Opt_TabConv1:
	move.b	#8,d0
	subq.l	#1,a0
	bra	Opt_BothConv

Opt_SpaceConv:
	tst.b	TabSize
	bne	Err_BadLogic
	tst.b	Size_MakeEOLs
	bne	Err_BadLogic
	move.b	2(a0),d0
	cmp.b	#" ",d0
	beq	Opt_SpaceConv1
	sub.b	#"0",d0
	cmp.b	#TAB,d0
	bhi	Err_BadComLine
	cmp.b	#2,d0			; No sense in converting to one tab
	bcs	Err_BadComLine		; so 2 is the lower limit.
	move.b	d0,SpaceSize
	bra	Opt_BothConv

Opt_SpaceConv1:
	move.b	#8,d0
	move.b	d0,SpaceSize
	subq.l	#1,a0

Opt_BothConv:
	move.b	d0,TabSize
	addq.l	#3,a0
	bra	Opt_Next

Opt_QuietMode:
	move.b	#1,Mode_Quiet
	addq.l	#2,a0
	bra	Opt_Next

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

Opt_MakeEOLs1:
	move.b	d0,Size_MakeEOLs
	addq.l	#3,a0
	bra	Opt_Next

Opt_NoBufferMode:
	move.b	#1,Mode_NoBuffer
	addq.l	#2,a0

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

FromPCMode:
	move.b	#MODE_FROMPC,Mode
	move.l	#Table_FromPC,Table
	bra	NameParse

FromSF7Mode:
	move.b	#MODE_FROMSF7,Mode
	move.l	#Table_FromSF7,Table
	bra	NameParse

ToSF7Mode:
	move.b	#MODE_TOSF7,Mode
	move.l	#Table_ToSF7,Table
	bra	NameParse

ToPCMode:
	move.b	#MODE_TOPC,Mode
	move.l	#Table_ToPC,Table
	bra	NameParse

ToUpCaseMode:
	move.b	#MODE_TOUPCASE,Mode
	bra	NameParse

ToLowCaseMode:
	move.b	#MODE_TOLOWCASE,Mode
	bra	NameParse

AutoMode:
	tst.b	Mode_NoBuffer		; Mode_NoBuffer=0? means we have buffer
	bne	Err_NeedBuffer		; if not
	move.b	#MODE_AUTOMODE,Mode
	bra	NameParse

ModeToNull:
	move.b	#MODE_TONULL,Mode
	move.l	#Table_Null,Table
	bra	NameParse

ModeToOnlyASCII:
	move.b	#MODE_TOASCII,Mode
	move.l	#Table_Null,Table

NameParse:
	addq.l	#1,a0			; One after Mode
	bsr	SkipSpace
	cmp.l	#0,a0
	beq	Err_BadComLine
	move.l	a0,SourceNameStart
	bsr	FindEnd
	movem.l	a0,-(a7)		; Push sourcename end in stack
	addq.l	#1,a0			; Find the length for sourcename
	sub.l	SourceNameStart,a0
	move.l	a0,SourceNameLen

	move.l	SourceNameStart,a0	; Copy the name to SourceName
	move.l	#SourceName,a1
	move.l	SourceNameLen,d0
	bsr	CopyName
	clr.b	(a1)

	move.l	#SourceName,d1		; Now let's try to find the source
	move.l	#ACCESS_READ,d2
	move.l	_DosBase,a6
	jsr	_LVOLock(a6)
	move.l	d0,SourceLock
	beq	CheckAllNames		; If no lock, try different suffixes

CheckFile:
	move.l	SourceLock,d1
	move.l	#FIB,d2
	move.l	_DosBase,a6
	jsr	_LVOExamine(a6)
	movem.l	d0,-(a7)		; Save result code

	move.l	SourceLock,d1
	move.l	_DosBase,a6
	jsr	_LVOUnLock(a6)
	clr.l	SourceLock

	move.l	(a7)+,d0		; Boolean
	beq	Err_SourceCorrupt	; 0 means error
	lea	FIB,a0
	tst.l	fib_DirEntryType(a0)	; Dir or a file?
	bpl	Err_SourceIsDir		; >=0 means directory, error
	move.l	fib_Size(a0),SourceLen
	move.l	#fib_FileName,a1	; Copy the name from FIB to
	add.l	a0,a1			; RealSourceName
	move.l	#RealSourceName,a0
	exg	a0,a1
	bsr	CopyUntilNull

	movem.l	(a7)+,a0		; Get SourceName's end from stack
	addq.l	#1,a0
	tst.b	(a0)
	beq	NoDest

	bsr	SkipSpace
	move.l	a0,DestNameStart	; If 0, go NoDest
	beq	NoDest
	bsr	FindEnd
	addq.l	#1,a0			; Add 1 to DestName end, and get
	sub.l	DestNameStart,a0	; DestNameLen in a0
	move.l	a0,d0
	move.l	d0,DestNameLen

	move.l	DestNameStart,a0	; Copy the destination name to DestName.
	lea	DestName,a1
	bsr	CopyName

	move.l	#DestName,d1		; Try to lock dest filename
	move.l	#ACCESS_READ,d2
	move.l	_DosBase,a6
	jsr	_LVOLock(a6)
	move.l	d0,DestLock
	beq	OpenFiles		; If no lock, we'll have a file.

	move.l	DestLock,d1		; Otherwise check it
	move.l	#FIB,d2
	move.l	_DosBase,a6
	jsr	_LVOExamine(a6)
	movem.l	d0,-(a7)		; Save result code

	move.l	DestLock,d1
	move.l	_DosBase,a6
	jsr	_LVOUnLock(a6)
	clr.l	DestLock

	move.l	(a7)+,d0		; Boolean
	beq	Err_DestCorrupt		; 0 means error

	lea	FIB,a0
	tst.l	fib_DirEntryType(a0)	; Dir or a file?
	bpl	DestIsDir		; >=0 means directory

	bra	OpenFiles

DestIsDir:
	lea	DestName,a0		; Get DestName
	add.l	DestNameLen,a0		; Go to the end
	cmp.b	#":",-1(a0)		; If the last char is ":",
	beq	LinkName
	cmp.b	#"/",-1(a0)		; or "/" just link the sourcename to it.
	beq	LinkName
	tst.b	-1(a0)
	beq	LinkName
	move.b	#"/",(a0)+		; If not dir suffix, add it.

LinkName:
	move.l	#RealSourceName,a1	; Add the real name of the sourcefile
	exg	a0,a1			; to the destination dir name.
	bsr	CopyUntilNull
	bra	OpenFiles

NoDest:
	move.l	SourceNameStart,a0	; If no destination name, use the
	move.l	SourceNameLen,d0	; sourcename (i.e. writing on the
	lea	DestName,a1		; original).
	bsr	CopyName

	tst.b	Mode_NoBuffer		; If we have a buffer, add no suffix.
	beq	ProtectSrc

	cmp.b	#MODE_TOPC,Mode		; Add the right type of suffix.
	beq	PCSuffix
	cmp.b	#MODE_TOSF7,Mode
	beq	SF7Suffix

AmigaSuffix:
	lea	Text_AmigaSuf,a0
	moveq	#4-1,d0
	bra	AddSuffix

PCSuffix:
	lea	Text_PCSuf,a0
	moveq	#3-1,d0
	bra	AddSuffix

SF7Suffix:
	lea	Text_SF7Suf,a0
	moveq	#4-1,d0

AddSuffix:
	move.b	(a0)+,(a1)+
	dbf	d0,AddSuffix

OpenFiles:
	clr.b	(a1)			; Add the terminating null.

	tst.b	Mode_NoBuffer		; We have a buffer, go to OpenFiles1.
	beq	OpenFiles1

	move.l	#SourceName,d1		; Open the sourcefile.
	move.l	#MODE_OLDFILE,d2
	move.l	_DosBase,a6
	jsr	_LVOOpen(a6)
	moveq	#1,d7			; Unlikely error code
	move.l	d0,SourceHandle
	beq	CodeError

	move.l	SourceHandle,d1		; Read 4 bytes.
	move.l	#SourceBuf,d2
	move.l	#4,d3
	move.l	_DosBase,a6
	jsr	_LVORead(a6)
	cmp.l	#4,d0			; Did we read 4 bytes?
	bne	OpenFiles3

	move.l	SourceBuf,d0		; Get a long from the buffer, and check
	cmp.l	#"PP20",d0		; if it is a PowerPacker datafile.
	beq	Err_PowerPacked

OpenFiles3:
	move.l	SourceHandle,d1		; Seek back to the
	moveq	#0,d2			; beginning of the file.
	moveq	#OFFSET_BEGINNING,d3
	move.l	_DosBase,a6
	jsr	_LVOSeek(a6)

	move.l	#DestName,d1		; Open the destination.
	move.l	#MODE_NEWFILE,d2
	move.l	_DosBase,a6
	jsr	_LVOOpen(a6)
	move.l	d0,DestHandle
	beq	Err_NoDest
	move.b	#1,Mode_DeleteErrDest	; Delete the dest file in case of error.

	lea	DestBuf,a1
	moveq	#0,d2

	bra	ReadBlock

CheckAllNames:
	lea	SourceName,a0

CAN_NameLen:
	tst.b	(a0)+			; Loop until null found = end.
	bne	CAN_NameLen
	subq.l	#1,a0			; Move back on the null.
	move.l	a0,a2			; Where to add suffixes in a2.
	lea	Text_Suffixes,a1

CAN_TrySuffix:
	move.b	(a1)+,(a0)+		; Copy the suffix.
	bne	CAN_TrySuffix		; Copy until a null moved.
	movem.l	a0-a2,-(a7)

	move.l	#SourceName,d1		; Try to lock the source with that
	move.l	#ACCESS_READ,d2		; suffix.
	move.l	_DosBase,a6
	jsr	_LVOLock(a6)
	move.l	d0,SourceLock
	beq	CAN_NoSuccess		; No lock, try the next suffix
	movem.l	(a7)+,a0-a2
	bra	CheckFile
	
CAN_NoSuccess:
	movem.l	(a7)+,a0-a2
	cmp.b	#$ff,(a1)		; $ff = End of suffixes.
	beq	Err_NoSource		; If so, couldn't find the file.
	move.l	a2,a0			; Otherwise, suffixplace back in a0,
	bra	CAN_TrySuffix		; and try again.

ProtectSrc:
	move.b	#1,Mode_SrcDeleted

OpenFiles1:
	lea	SourceLenASCII,a0	; Make a string out of the file length.
	move.l	SourceLen,d0
	bsr	Num2ASCII
	move.l	a0,SourceLenASCIIAddr
	move.l	d0,SourceLenASCIILen

	move.l	#SourceName,d1		; Open the source.
	move.l	#MODE_OLDFILE,d2
	move.l	_DosBase,a6
	jsr	_LVOOpen(a6)
	moveq	#2,d7			; Unlikely error code
	move.l	d0,SourceHandle		; If we couldn't open the file.
	beq	CodeError		; Weird, because we did Lock() it.

	move.l	SourceHandle,d1		; Read the first 4 bytes.
	move.l	#SourceBuf,d2
	move.l	#4,d3
	move.l	_DosBase,a6
	jsr	_LVORead(a6)
	cmp.l	#4,d0
	bne	OpenFiles2		; If 4 bytes couldn't be read.

	move.l	SourceBuf,d0		; Test if a PowerPacker datafile.
	cmp.l	#"PP20",d0
	beq	Err_PowerPacked

OpenFiles2:
	move.l	SourceHandle,d1		; Seek back to the
	moveq	#0,d2			; beginning of the file.
	moveq	#OFFSET_BEGINNING,d3
	move.l	_DosBase,a6
	jsr	_LVOSeek(a6)

	move.l	SourceLen,d0		; Allocate for the whole source file.
	moveq	#0,d1			; No special needs for the memory.
	move.l	ExecBase,a6
	jsr	_LVOAllocMem(a6)
	move.l	d0,SourcePointer
	beq	Err_NoMem

ReadFile:
	move.l	SourceHandle,d1		; Read 10KB at a time.
	move.l	SourcePointer,d2	; To our file buffer.
	add.l	ReadBytes,d2
	move.l	#10240,d3
	move.l	_DosBase,a6
	jsr	_LVORead(a6)
	cmp.l	#-1,d0
	beq	Err_ReadFail		; If error reading the file.
	add.l	d0,ReadBytes
	movem.l	d0,-(a7)
	tst.b	Mode_Quiet		; Check if we should be quiet.
	bne	TestRead		; If so, go to TestRead.

	bsr	ClearPrintBuf		; Start a new buffer.

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

	lea	ReadASCII,a0		; First convert the number into a
	move.l	ReadBytes,d0		; string, and then add the string into
	bsr	Num2ASCII		; the buffer.
	move.l	a0,ReadASCIIAddr
	move.l	d0,ReadASCIILen

	bsr	AddPrintBuf

	move.l	#Text_Slash,a0
	bsr	AddPrintBuf

	move.l	SourceLenASCIIAddr,a0	; The size of the source file.
	bsr	AddPrintBuf

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

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

	moveq	#0,d0			; Get the signals.
	moveq	#0,d1
	move.l	ExecBase,a6
	jsr	_LVOSetSignal(a6)

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

	bra	ReadFile		; Read more of the file.

ReadFinished:
	move.l	ReadBytes,LeftBytes

	move.l	SourceHandle,d1		; Close the source, since we're done.
	move.l	_DosBase,a6
	jsr	_LVOClose(a6)
	clr.l	SourceHandle		; Note that it's closed.

	cmp.b	#MODE_AUTOMODE,Mode	; AutoMode on?
	beq	DetectMode		; Determine the real mode to use.

ReadFinished1:
	move.l	#DestName,d1		; Open the DestName file.
	move.l	#MODE_NEWFILE,d2
	move.l	_DosBase,a6
	jsr	_LVOOpen(a6)
	move.l	d0,DestHandle
	beq	Err_NoDest
	move.b	#1,Mode_DeleteErrDest	; Delete the dest file in case of error.

	moveq	#0,d2
	lea	DestBuf,a1

	bra	MoreData

DetectMode:
	move.l	#Text_Checking,d2	; Tell that we're checking the mode.
	bsr	PrintText

	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	move.l	SourcePointer,a0
	cmp.l	#10240,LeftBytes	; Less data to determine with, otherwise
	bcs	DetectMode1		; use 10KB.
	move.l	#10240-1,d1

DetectMode2:
	move.b	(a0)+,d0		; Get a byte.
	cmp.b	#"{",d0			; Signs of possible SF7.
	beq	DM_SF7
	cmp.b	#"[",d0
	beq	DM_SF7
	cmp.b	#"|",d0
	beq	DM_SF7
	cmp.b	#"\",d0
	beq	DM_SF7

	cmp.b	#"ä",d0			; Signs of possible Amiga format.
	beq	DM_Amy
	cmp.b	#"Ä",d0
	beq	DM_Amy
	cmp.b	#"ö",d0
	beq	DM_Amy
	cmp.b	#"Ö",d0
	beq	DM_Amy

	cmp.b	#$84,d0			; Signs of possible PC format.
	beq	DM_PC
	cmp.b	#$8e,d0
	beq	DM_PC
	cmp.b	#$94,d0
	beq	DM_PC
	cmp.b	#$99,d0
	beq	DM_PC

	cmp.b	#CR,d0			; CR, can't be an Amiga format.
	beq	DM_Foreign

DetectMode3:
	dbf	d1,DetectMode2		; If bytes left to check, do so.

	cmp.l	d2,d3			; xx0
	beq	SameWarn1
	cmp.l	d2,d4			; x0x
	beq	SameWarn1
	cmp.l	d3,d4			; 0xx
	beq	SameWarn2

DetectMode4:
	movem.l	d2-d4,-(a7)
	move.l	#Text_Uses,d2		; Tell what mode it uses.
	bsr	PrintText
	movem.l	(a7)+,d2-d4

	cmp.l	d2,d3			; SF7 or Amy
	bhi	DM_NotSF7

DM_NotAmy:
	cmp.l	d2,d4			; SF7 or PC
	bhi	DM_MakePC
	bra	DM_MakeSF7

DM_NotSF7:
	cmp.l	d3,d4			; Amy or PC
	bhi	DM_MakePC

DM_MakeAmy:
	move.b	#MODE_TONULL,Mode	; Amiga file, use Null mode.
	move.l	#Table_Null,Table

	move.l	#Text_NullMode,d2	; Tell the user that.
	bsr	PrintText

	bra	ReadFinished1

DM_MakePC:
	move.b	#MODE_FROMPC,Mode	; PC file, use FromPC mode.
	move.l	#Table_FromPC,Table

	move.l	#Text_PCMode,d2		; And tell that.
	bsr	PrintText

	bra	ReadFinished1

DM_MakeSF7:
	move.b	#MODE_FROMSF7,Mode	; SF7 file, use FromSF7 mode.
	move.l	#Table_FromSF7,Table

	move.l	#Text_SF7Mode,d2	; Tell it.
	bsr	PrintText

	bra	ReadFinished1

SameWarn1:
	cmp.l	d3,d4			; Could be either one.
	beq	Err_SameProbability
	bra	DetectMode4

SameWarn2:				; Same as above.
	cmp.l	d2,d3
	beq	Err_SameProbability
	bra	DetectMode4

DetectMode1:				; Since we don't have 10KB for
	move.l	LeftBytes,d1		; comparing, take all we can get.
	subq.l	#1,d1
	bra	DetectMode2

DM_SF7:
	addq.l	#1,d2			; One point to SF7.
	bra	DetectMode3

DM_Amy:
	addq.l	#1,d3			; One to Amiga.
	bra	DetectMode3

DM_PC:
	addq.l	#1,d4			; etc...
	bra	DetectMode3

DM_Foreign:
	addq.l	#1,d2			; One point to SF7 and PC.
	addq.l	#1,d4
	bra	DetectMode3

ReadBlock:
	tst.b	Mode_NoBuffer
	beq	MoreData		; We have a buffer -> MoreData

	movem.l	d0/d2-d7/a0-a6,-(sp)
	move.l	SourceHandle,d1		; Otherwise read one KB.
	move.l	SourcePointer,d2
	move.l	#1024,d3
	move.l	_DosBase,a6
	jsr	_LVORead(a6)
	cmp.l	#-1,d0
	beq	Err_ReadFail		; Couldn't read?  -> Err_ReadFail.
	add.l	d0,ReadBytes
	move.l	d0,d1
	beq	RB_CloseFiles		; ReadBytes = 0? -> Quit.
	movem.l	(sp)+,d0/d2-d7/a0-a6
	subq.l	#1,d1			; Counter always one less than loops.
	lea	SourceBuf,a0		; Buffer locations to regs.
	bra	CheckOutBuf		; Continue converting.

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

MoreData:
	tst.l	LeftBytes		; We have no more bytes left?
	beq	CloseFiles		; -> Quit.
	cmp.l	#1024,LeftBytes		; Do we still have a full KB left?
	bls	MoreData1		; No? -> MoreData1.
	sub.l	#1024,LeftBytes		; One KB less left.
	move.l	SourcePointer,a0	; Start of the buffer in a0.
	add.l	InputBytes,a0		; Add the offset (how much converted).
	add.l	#1024,InputBytes	; Tell that we've done another KB.
	move.l	#1024-1,d1		; Convert the next K of bytes.
	bra	CheckOutBuf		; And continue.

MoreData1:
	move.l	LeftBytes,d0		; Less than 1024 bytes left, take the
	clr.l	LeftBytes		; rest.
	move.l	SourcePointer,a0
	add.l	InputBytes,a0
	add.l	d0,InputBytes
	subq.l	#1,d0			; Loop counter starts from 0, i.e. -1.
	move.l	d0,d1
	bra	CheckOutBuf

MoreCharacters:
;	movem.l	d0-d7/a0-a6,-(sp)

;	bsr	ClearPrintBuf

;	lea	NumberBuf,a0
;	move.l	d1,d0
;	bsr	Num2ASCII
;	bsr	AddPrintBuf
;	lea	Text_LF,a0
;	bsr	AddPrintBuf
;	bsr	WritePrintBuf
;	movem.l	(sp)+,d0-d7/a0-a6

	move.b	(a0)+,d0		; Get a new byte from the buffer.

	tst.b	Mode			; ToSF7 & ToPC both negative.
	bmi	Translate		; Lower than 0. -> Translate.

	cmp.b	#MODE_FROMSF7,Mode
	beq	Translate
	cmp.b	#MODE_TOUPCASE,Mode
	beq	ToUpCase
	cmp.b	#MODE_TOLOWCASE,Mode
	beq	ToLowCase
	cmp.b	#MODE_TONULL,Mode
	beq	Translate
	cmp.b	#MODE_TOASCII,Mode
	beq	OnlyASCIIMode

FromPC:
	cmp.b	#" ",d0			; If the char is a control code,
	bcs	PC_Translate
	cmp.b	#"~",d0			; or non-ASCII. -> PC_Translate.
	bhi	PC_Translate
	bra	NextChar		; Otherwise just take the next char.

PC_Translate:
	tst.b	d0			; The two characters not in the Table
	beq	NoChar
	cmp.b	#$1a,d0			; ^Z, a dull end of file marker.
	beq	NoChar
	cmp.b	#CR,d0			; CRs out!
	beq	NoChar
	cmp.b	#$80,d0			; The ASCII table ends here.
	bcs	NextChar
	lea	Table_FromPC,a3
	sub.b	#$80,d0			; Currently only the non-ASCII chars
	ext.w	d0			; are in the table.
	ext.l	d0
	add.l	d0,a3			; Add the offset to the table.
	move.b	(a3),d0			; And replace the original character.
	beq	NoChar			; If 0 = drop this byte.
	bra	CutSpace

Translate:
	move.l	Table,a3		; The table address is stored here.
	tst.b	d0			; If the char is null, drop it.
	beq	NoChar

Translate1:
	move.w	(a3)+,d3		; Get a word from the table. (to|from)
	beq	NextChar		; 0 = End of Table
	cmp.b	d3,d0			; If the lower byte matches,
	beq	Translate2		; -> Translate2.
	bra	Translate1		; Otherwise compare with the next.

Translate2:
	lsr.w	#8,d3			; The upper part is the byte to
	move.b	d3,d0			; translate into.
	beq	NoChar			; If 0 = Drop this char.

NextChar:
	bra	CutSpace		; Otherwise proceed to CutSpace.

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

NoChar:
;	movem.l	d0-d7/a0-a6,-(sp)

;	bsr	ClearPrintBuf

;	lea	Text_Note,a0
;	bsr	AddPrintBuf
;	lea	Text_CR,a0
;	bsr	AddPrintBuf
;	bsr	WritePrintBuf
;	movem.l	(sp)+,d0-d7/a0-a6

	subq.l	#1,d1			; One less byte in the sourcebuffer.
	bmi	ReadBlock		; Went negative, load more.
CheckOutBuf:
					; Have we converted a full buffer yet?
	cmp.l	#SIZE_DESTBUF-SIZE_MAXNEW,d2
	bcc	WriteDestBuf
	bra	MoreCharacters		; Everything okay, continue conversion.

WriteDestBuf:
	movem.l	d1/d3-d7/a0-a6,-(sp)
	move.l	DestHandle,d1		; Write the converted data
	move.l	d2,d3
	add.l	d2,WrittenBytes		; Add the buffer to WrittenBytes.
	move.l	#DestBuf,d2
	move.l	_DosBase,a6
	jsr	_LVOWrite(a6)
	cmp.l	#-1,d0
	beq	Err_WriteFail

	tst.b	Mode_SrcDeleted		; If the sourcefile has been destroyed,
	bne	NoBreak			; don't allow breaking.

	moveq	#0,d0			; Get the signals.
	moveq	#0,d1
	move.l	ExecBase,a6
	jsr	_LVOSetSignal(a6)

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

NoBreak:
	movem.l	(sp)+,d1/d3-d7/a0-a6
	tst.b	Mode_Quiet		; See if we should be quiet.
	bne	SetWriteRegs

	movem.l	d1-d7/a0-a6,-(sp)

	tst.b	Mode_NoBuffer		; If we have a buffer, other kind of
	beq	AlternateOutput		; progress info.

	bsr	ClearPrintBuf

	move.l	#Text_Input,a0		; Tell how much has been read and how
	bsr	AddPrintBuf		; much written.

	lea	NumberBuf,a0
	move.l	ReadBytes,d0
	bsr	Num2ASCII
	bsr	AddPrintBuf

	move.l	#Text_Output,a0
	bsr	AddPrintBuf

	lea	NumberBuf,a0
	move.l	WrittenBytes,d0
	bsr	Num2ASCII
	bsr	AddPrintBuf

	move.l	#Text_CR,a0
	bsr	AddPrintBuf

	bsr	WritePrintBuf

	bra	SetWriteRegs

AlternateOutput:
	bsr	ClearPrintBuf
	move.l	#Text_Converted,a0	; The progress info for fully buffered
	bsr	AddPrintBuf		; input.

	lea	NumberBuf,a0
	move.l	InputBytes,d0
	bsr	Num2ASCII
	bsr	AddPrintBuf

	move.l	#Text_Slash,a0
	bsr	AddPrintBuf

	move.l	ReadASCIIAddr,a0
	bsr	AddPrintBuf

	move.l	#Text_CR,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf

	bra	SetWriteRegs

SetWriteRegs:
	movem.l	(sp)+,d1-d7/a0-a6
	moveq	#0,d2			; No converted bytes now.
	lea	DestBuf,a1
	bra	MoreCharacters

CutSpace:
	move.l	SpacePointer,a2		; Pointer to the SpaceBuffer
	cmp.b	#" ",d0
	beq	AddSpace
	cmp.b	#TAB,d0
	beq	AddTab
	bsr	AddEOL			; Check if the char is a LF, and add
					; it to EOLs.
	tst.b	Mode_NoCutSpace		; If NoCutSpace is on -> CutSpace2.
	bne	CutSpace2

	cmp.b	#LF,d0			; If a LF is found, all spaces will be
	beq	CutSpaces		; cut from the EOL.

CutSpace1:				; A character which is not a space,
	tst.b	PreSpace		; tab or a LF. Trigger things.
	bne	InsertPreSpace		; PreSpace exists so that a place for
	tst.l	Tabs			; a tab can be replaced with a space.
	bne	LinkSpaces		; Spaces normally come after tabs, so
					; without this, the tabs could start
CutSpace3:				; from wrong place, and one extra space
	tst.l	SpaceNumber		; would be left after them.
	bne	LinkSpaces2

CutSpace4:
	cmp.b	#LF,d0			; Has been buffered, NoChar.
	beq	NoChar
	tst.b	Mode_NoCutSpace		; If CutSpace -> TestForSpace.
	beq	TestForSpace

LinkEOLs:
	bsr	InsertEOLs		; Insert any buffered EOLs.

	cmp.b	#" ",d0			; If the char was a space or a tab,
	beq	NoChar			; we don't want it to pass straight
	cmp.b	#TAB,d0			; in the main write buffer.
	beq	NoChar			; Otherwise it's ok.
	bra	CheckNormal

TestForSpace:
	cmp.b	#" ",d0			; If CutSpace is on, spaces and tabs
	beq	NoChar			; don't automatically trigger EOLs
	cmp.b	#TAB,d0			; in: They will be triggered when
	beq	NoChar			; the tabs and spaces get triggered.
	bra	LinkEOLs

CutSpace2:
	cmp.b	#LF,d0			; LF resets column.
	bne	CutSpace1
	clr.w	Col
	bra	CutSpace1

AddSpace:
	move.b	d0,(a2)+		; Throw d0 in the SpaceBuffer.
	move.l	a2,SpacePointer
	addq.l	#1,SpaceNumber		; Add the counter for the SpaceBuffer.
	addq.w	#1,Col			; Add the col, though the char didn't
	bra	CheckConvSpace		; get in the buffer.

AddTab:
	move.b	TabSize,d4		; TabSize = 0 means no Tabs2Spaces conv
	bne	TabConv			; is active. Just throw it in SpaecBuf.
	bra	AddSpace		; Otherwise go to TabConv.

TabConv:
	ext.w	d4			; Convert TabSize
	ext.l	d4
	move.w	Col,d3			; Get current column
	ext.l	d3
	divu	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,SpaceNumber		; Add the converted spaces to SpaceBuf.
	add.w	d4,Col			; And add column too.
	subq.w	#1,d4			; One less, because it's a loop reg.
	move.b	#" ",d0

TabConv1:
	move.b	d0,(a2)+		; Copy the spaces in the buffer.
	dbf	d4,TabConv1
	move.l	a2,SpacePointer		; And save the SpaceBuffer pointer.

CheckConvSpace:
	tst.b	SpaceSize		; SpaceSize=0 means no Spaces2Tabs.
	beq	CutSpace4
	cmp.l	#1,SpaceNumber		; If Spacenumber<1, don't try to convert
	bcs	CutSpace4		; to tabs.  No use, and time wasted in
	move.w	Col,d5			; divu.
	ext.l	d5
	move.l	SpaceNumber,d3
	move.b	SpaceSize,d4
	ext.w	d4
	ext.l	d4
	divu	d4,d5			; If column is divisible by SpaceSize,
	swap	d5			; it can be converted to a tab.
	tst.w	d5
	beq	FoundConvSpace
	bra	CutSpace4		; Otherwise just continue.

FoundConvSpace:
	cmp.l	#1,SpaceNumber		; If only one space is won, instead
	beq	FoundConvSpace2		; of conversion, make it PreSpace.
	move.l	#SpaceBuf,SpacePointer	; Reset SpacePointer.
	addq.l	#1,Tabs			; More tabs.
	clr.l	SpaceNumber		; Take the spaces out.
	bra	CutSpace4

FoundConvSpace2:
	move.b	#1,PreSpace		; Enable the PreSpace system.
	move.l	#SpaceBuf,SpacePointer	; Reset SpacePointer.
	clr.l	SpaceNumber		; Reset SpaceNumber.
	bra	CutSpace4

CutSpaces:
	clr.b	PreSpace		; Flushes all buffered space etc.
	clr.l	SpaceNumber
	clr.l	Tabs
	move.l	#SpaceBuf,SpacePointer
	clr.w	Col
	bra	NoChar

AddEOL:
	cmp.b	#LF,d0
	beq	AddEOL1
	rts

AddEOL1:
	addq.l	#1,EOLs
	rts

LinkSpaces:
	tst.b	Mode_NoCutSpace		; If CutSpace is not on -> LinkSpaces4
	bne	LinkSpaces4
	bsr	InsertEOLs

LinkSpaces4:
	move.l	Tabs,d3			; Copy the tabs to the real buffer.
	clr.l	Tabs
	add.l	d3,d2			; Bytes to be written += # of tabs.
	subq.l	#1,d3

LinkSpaces1:
	move.b	#TAB,(a1)+
	dbf	d3,LinkSpaces1
	bra	CutSpace3

LinkSpaces2:
	tst.b	Mode_NoCutSpace		; If CutSpace is not on -> LinkSpaces5
	bne	LinkSpaces5
	bsr	InsertEOLs

LinkSpaces5:
	move.l	SpaceNumber,d3
	tst.b	Size_MakeEOLs		; If MakeEOLs is on -> ls_CheckMakeEOLs.
	bne	ls_CheckMakeEOLs
LinkSpaces6:
	add.l	d3,d2			; Spaces -> bytes to be written.
	subq.l	#1,d3			; Copy all spaces and possibly tabs
	lea	SpaceBuf,a2		; to the main buffer.
	move.l	a2,SpacePointer
	clr.l	SpaceNumber

LinkSpaces3:
	move.b	(a2)+,(a1)+
	dbf	d3,LinkSpaces3
	bra	CutSpace4

ls_CheckMakeEOLs:
	cmp.b	Size_MakeEOLs,d3	; d3 = size of SpaceBuffer.
	bcs	LinkSpaces6
	addq.l	#1,d2			; Add the EOL to bytes to be written.
	move.b	#LF,(a1)+
	clr.l	SpaceNumber
	move.l	#SpaceBuf,SpacePointer
	tst.b	Mode			; If ToPC or ToSF7, add a CR too.
	bmi	ls_CheckMakeEOLs1
	bra	CutSpace4

ls_CheckMakeEOLs1:
	move.b	#CR,(a1)+
	addq.l	#1,d2
	bra	CutSpace4

InsertPreSpace:
	clr.b	PreSpace
	move.b	#" ",(a1)+
	addq.l	#1,d2
	bra	CutSpace1

ToUpCase:
	cmp.b	#$e0,d0			; Bitmask 32 controls whether the char
	bcs	ToUpCase2		; is upper or lowecase. If it's on, the
	cmp.b	#$fe,d0			; char is lowercase, otherwise the
	bhi	NextChar		; char's uppercase.
	bra	ToUpCase1

ToUpCase2:
	cmp.b	#"a",d0
	bcs	NextChar
	cmp.b	#"z",d0
	bhi	NextChar

ToUpCase1:
	and.b	#%11011111,d0
	bra	NextChar

ToLowCase:				; Check the special character ranges.
	cmp.b	#$c0,d0			; If it doesn't match, either try the
	bcs	ToLowCase1		; ASCII, or if that's hopeless, pass
	cmp.b	#$de,d0			; the char unchanged.
	bhi	NextChar
	bra	ToLowCase2

ToLowCase1:
	cmp.b	#"A",d0
	bcs	NextChar
	cmp.b	#"Z",d0
	bhi	NextChar

ToLowCase2:
	or.b	#%00100000,d0
	bra	NextChar

OnlyASCIIMode:
	btst	#7,d0			; ASCII chars don't have the bit 7,
	bne	NoChar			; if this does, drop it.
	bra	Translate

CloseFiles:
	move.l	d2,d3			; Do we have stuff in DestBuf?
	beq	CF_TellData		; No, show the final stats.

	move.l	DestHandle,d1		; We do, flush it.
	add.l	d2,WrittenBytes		; Add the buffer to WrittenBytes.
	move.l	#DestBuf,d2
	move.l	_DosBase,a6
	jsr	_LVOWrite(a6)
	cmp.l	#-1,d0
	beq	Err_WriteFail

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

	move.l	WrittenBytes,d0

	sub.l	ReadBytes,d0
	bmi	CloseFiles1		; Negative

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

	move.l	#Text_PosSign,a0
	bsr	AddPrintBuf
	bra	CloseFiles2

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

CloseFiles2:
	lea	NumberBuf,a0
	bsr	Num2ASCII
	bsr	AddPrintBuf

	move.l	#Text_DoubleSpace,a0
	bsr	AddPrintBuf

	move.l	WrittenBytes,d0
	move.l	ReadBytes,d1
	bsr	Percentage

	lea	NumberBuf,a0
	bsr	Num2ASCII

	bsr	AddPrintBuf

	move.l	#Text_PercentSign,a0
	bsr	AddPrintBuf

	move.l	#Text_LF,a0
	bsr	AddPrintBuf
	bsr	WritePrintBuf
	bra	EndProgram

HelpText:
	move.l	#Text_HelpText,d2
	bsr	PrintText
	bra	EndProgram

Credits:
	move.l	#Text_Credits,d2
	bsr	PrintText
	bra	EndProgram

CodeError:
	movem.l	d7,-(a7)
	move.l	#Text_CodeError,d2
	bsr	PrintText
	lea	NumberBuf,a0
	movem.l	(a7)+,d0
	bsr	Num2ASCII
	move.l	a0,d2
	move.l	d0,d3
	bsr	PrintTextLen
	bra	EndProgram

	IF	TestMode=1

Err_TestMode:
	move.l	#$ffff,d0

Err_TestMode1:
	move.w	#$f00,$dff180
	dbf	d0,Err_TestMode1
	bra	EndProgramErr

	ENDC

Err_NoSource:
	move.l	#Text_NoSource,d2
	bra	ShowErr

Err_BadComLine:
	move.l	#Text_BadComLine,d2
	bra	ShowErr

Err_NoDest:
	move.l	#Text_NoDest,d2
	bra	ShowErr

Err_BadMode:
	move.l	#Text_BadMode,d2
	bra	ShowErr

Err_NoComLineSpace:
	move.l	#Text_NoComLineSpace,d2
	bra	ShowErr

Err_BadLogic:
	move.l	#Text_BadLogic,d2
	bra	ShowErr

Err_NoMem:
	move.l	#Text_NoMemory,d2
	bra	ShowErr

Err_PowerPacked:
	move.l	#Text_PowerPacked,d2
	bra	ShowErr

Err_SeekFail:
	move.l	#Text_BadSource,d2
	bra	ShowErr

Err_ReadFail:
	move.l	#Text_BadSource,d2
	bra	ShowErr

Err_SourceCorrupt:
	move.l	#Text_BadSource,d2
	bra	ShowErr

Err_DestCorrupt:
	move.l	#Text_BadDest,d2
	bra	ShowErr

Err_SourceIsDir:
	move.l	#Text_SourceIsDir,d2
	bra	ShowErr

Err_WriteFail:
	move.l	#Text_WriteFail,d2
	bra	ShowErr

Err_NeedBuffer:
	move.l	#Text_NeedBuffer,d2
	bra	ShowErr

Err_SameProbability:
	move.l	#Text_SameProbability,d2
	bra	ShowErr

BreakPressed:
	move.l	#Text_Break,d2

ShowErr:
	bsr	PrintText
	bra	EndProgramErr

EndProgram:
	clr.b	Mode_DeleteErrDest

EndProgramErr:
	move.l	_DosBase,a6
	move.l	SourceHandle,d1
	beq	EndProgram1
	jsr	_LVOClose(a6)

EndProgram1:
	move.l	DestHandle,d1
	beq	EndProgram2
	jsr	_LVOClose(a6)

EndProgram2:
	move.l	SourceLock,d1
	beq	EndProgram3
	jsr	_LVOUnLock(a6)

EndProgram3:
	move.l	DestLock,d1
	beq	EndProgram4
	jsr	_LVOUnLock(a6)

EndProgram4:
	tst.b	Mode_DeleteErrDest
	beq	EndProgram5
	move.l	#DestName,d1
	jsr	_LVODeleteFile(a6)	; *!* Error detection here

EndProgram5:
	move.l	ExecBase,a6
	cmp.l	#SourceBuf,SourcePointer
	beq	EndProgram6
	move.l	SourcePointer,a1
	move.l	SourceLen,d0
	jsr	_LVOFreeMem(a6)

EndProgram6:
	move.l	#Text_CursorOn,d2
	bsr	PrintText

	move.l	ExecBase,a6
	move.l	_DosBase,a1
	jsr	_LVOCloseLibrary(a6)
	moveq	#0,d0			; *!* Add some error codes.
	move.l	OldStack,a7		; At least it's safe this way...
	rts				; *!* Add some check to see if the stack
					; was okay.

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

ClearPrintBuf:
	move.l	#PrintBuf,PrintBufPtr
	rts

AddPrintBuf:
	move.l	PrintBufPtr,a1

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

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

InsertEOLs:
	move.l	EOLs,d3
	bne	InsertEOLs1
	rts

InsertEOLs1:
	add.l	d3,d2
	subq.l	#1,d3

InsertEOLs2:
	tst.b	Mode			; If Mode is negative, adds CRs.
	bmi	InsertCR
InsertEOLs3:
	move.b	#LF,(a1)+
	dbf	d3,InsertEOLs2
	clr.l	EOLs
	rts

InsertCR:
	move.b	#CR,(a1)+
	addq.l	#1,d2
	bra	InsertEOLs3

PrintError:
	movem.l	d2,-(a7)
	move.l	#Text_Error,d2
	bsr	PrintText
	movem.l	(a7)+,d2
	bsr	PrintText
	rts

PrintText:
	IF	TestMode=1
	rts
	ENDC

	move.l	d2,a0

PrintText1:
	tst.b	(a0)+
	bne	PrintText1

	sub.l	d2,a0
	subq.w	#1,a0
	move.l	a0,d3
	move.l	OutStruct,d1
	move.l	_DosBase,a6
	jsr	_LVOWrite(a6)
	rts

PrintTextLen:
	IF	TestMode=1
	rts
	ENDC

	move.l	OutStruct,d1
	move.l	_DosBase,a6
	jsr	_LVOWrite(a6)
	rts

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

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

FindEnd:
	cmp.b	#'"',(a0)		; If the first letter is a quote,
	beq	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	FindEnd_Space1
	tst.b	(a0)			; If it's the end of comline, we found
	beq	FindEnd_Space1		; the end of the name.
	bra	FindEnd_Space

FindEnd_Space1:
	subq.l	#1,a0
	rts

FindEnd_Quote:
	addq.l	#1,a0
	tst.b	(a0)			; If end of comline, error.
	beq	FindEnd_Quote2
	cmp.b	#'"',(a0)
	bne	FindEnd_Quote
	rts

FindEnd_Quote2:
	sub.l	a0,a0
	rts

CopyUntilNull:
	move.b	(a0)+,(a1)+
	bne	CopyUntilNull
	rts

	INCDIR	"SRC:Routines/"
	INCLUDE	"Num2ASCII.S"
	INCLUDE	"Percentage.S"
	INCLUDE	"CopyName.S"

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

	SECTION	FastData,DATA

SourcePointer:
	dc.l	SourceBuf

SpacePointer:
	dc.l	SpaceBuf

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

; The byte from which to convert is on the right, and the byte into which it
; turns is on the left.  If a null is on the left, it means the byte doesn't
; get to the destination file at all.  Must be word aligned since the data
; gets fetched one word at a time.


Table_ToPC:
	dc.b	$00,$0d
	dc.b	$00,$1a
	dc.b	$84,"ä"
	dc.b	$8e,"Ä"
	dc.b	$94,"ö"
	dc.b	$99,"Ö"
	dc.w	0

Table_Null:
	dc.b	$00,$0d
	dc.b	$00,$1a
	dc.w	0

Table_ToSF7:
	dc.b	$00,$0d
	dc.b	$00,$1a
	dc.b	"{","ä"
	dc.b	"|","ö"
	dc.b	"[","Ä"
	dc.b	"\","Ö"
	dc.w	0

Table_FromSF7:
	dc.b	$00,$0d
	dc.b	$00,$1a
	dc.b	"ä","{"
	dc.b	"ö","|"
	dc.b	"Ä","["
	dc.b	"Ö","\"
	dc.w	0

Table_FromPC:	;0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
	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/"

Text_CodeError:
	INCBIN	"PortCodeError"
	dc.b	0

Text_HelpText:
	INCBIN	"PortOpts1"
	dc.b	0

Text_Credits:
	INCBIN	"PortOpts2"
	dc.b	0

Text_CursorOff:
	dc.b	$9b,"0 p",0

Text_CursorOn:
	dc.b	$9b,"1 p",0

Text_Error:
	dc.b	"ERROR!  ",0

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

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

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

Text_SourceIsDir:
	dc.b	"Source file is a directory.",LF,0

Text_BadMode:
	dc.b	"Bad mode specification.",LF,0

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

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

Text_BadLogic:
	dc.b	"Conflict in commandline.",LF,0

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

Text_PowerPacked:
	dc.b	"File is a PowerPacker data file, can't process.",LF,0

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

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

Text_NeedBuffer:
	dc.b	"Auto-mode only works with buffered input.",LF,0

Text_SameProbability:
	dc.b	"Can't decide between modes.",LF,0

Text_Input:
	dc.b	$9b,"1mInput:",$9b,"0m ",0

Text_Output:
	dc.b	"  ",$9b,"1mOutput:",$9b,"0m ",0

Text_Read:
	dc.b	$9b,"1mRead:",$9b,"0m ",0

Text_Converted:
	dc.b	$9b,"1mConverted:",$9b,"0m ",0

Text_Checking:
	dc.b	$9b,"1mChecking file type...",$9b,"0m",$9b,"0K",CR,0

Text_Uses:
	dc.b	$9b,"1mType:",$9b,"0m ",0

Text_NullMode:
	dc.b	"Amiga",$9b,"0K",LF,0

Text_SF7Mode:
	dc.b	"SF7",$9b,"0K",LF,0

Text_PCMode:
	dc.b	"PC",$9b,"0K",LF,0

Text_Break:
	dc.b	$9b,"1m-BREAK-",$9b,"0m",$9b,"0K",LF,0

Text_ClearEOL:
	dc.b	$9b,"0K",0

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

Text_AmigaSuf:
	dc.b	".AMY"

Text_PCSuf:
	dc.b	".PC"

Text_SF7Suf:
	dc.b	".SF7"

Text_CR:
	dc.b	CR,0

Text_LF:
	dc.b	LF,0

Text_Final:
	dc.b	$9b,"1mFile size change:",$9b,"0m ",0

Text_NegSign:
	dc.b	"-",0

Text_PosSign:
	dc.b	"+",0

Text_PercentSign:
	dc.b	"%",$9b,"0K",0

Text_DoubleSpace:
	dc.b	"  ",0

Text_Slash:
	dc.b	"/",0

Text_Suffixes:
	dc.b	".TXT",0
	dc.b	".DOC",0
	dc.b	".AMY",0
	dc.b	".SF7",0
	dc.b	".PC",0
	dc.b	".ASC",0
	dc.b	".ANS",0
	dc.b	".LST",0
	dc.b	".NFO",0
	dc.b	$ff

Text_Note:
	dc.b	"Hit!",LF,0

	IF	TestMode=1

Test_ComLine:
	dc.b	"-s -b n dh1:text/mags/jargon2910 dh2:Jar2",LF

Test_ComLineEnd:

Test_Len	=	Test_ComLineEnd-Test_ComLine

	ENDC

	SECTION	FastBlank,BSS

FIB:
	ds.b	fib_SIZEOF

PrintBufPtr:
	ds.l	1

OldStack:
	ds.l	1

DestNameLen:
	ds.l	1

SourceLock:
	ds.l	1

DestLock:
	ds.l	1

EOLs:
	ds.l	1

ReadASCIIAddr:
	ds.l	1

Table:
	ds.l	1

SourceLen:
	ds.l	1

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

DestNameStart:
	ds.l	1

SourceNameStart:
	ds.l	1

SourceNameLen:
	ds.l	1

Commandstarrt:
	ds.l	1

_DosBase:
	ds.l	1

SpaceNumber:
	ds.l	1

ReadASCIILen:
	ds.l	1

SourceLenASCIILen:
	ds.l	1

SourceLenASCIIAddr:
	ds.l	1

Col:
	ds.w	1

SourceBuf:
	ds.b	1024

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

SourceName:
	ds.b	256

DestName:
	ds.b	256

PrintBuf:
	ds.b	256

DestBuf:
	ds.b	SIZE_DESTBUF

SpaceBuf:
	ds.b	1024

NumberBuf:
	ds.b	11

ReadASCII:
	ds.b	11

SourceLenASCII:
	ds.b	11

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_Quiet:
	ds.b	1

Mode_NoBuffer:
	ds.b	1

Mode_DeleteErrDest:
	ds.b	1

Mode_SrcDeleted:
	ds.b	1


; *** Version history ***

; V1.01
; - Added bigger understanding of PC box characters.
; - Now also understands one-wide box chars, and thick corner changed to #,
;   single corner to +.

; V1.02
; - Added bad mode error, and error on no space between mode and the rest.

; V1.10
; - Cut endspace.
; - Text output.

; V1.13
; - Percentage & size change.
; - Extra LF.
; - Extra CR removal in ToPC mode.

; V1.16
; - Faster translate routines - 25% speedup in FromPC.
; - 6 more in FromPC.
; - New helptext.

; V1.18  11-Feb-93
; - Upper and lower case modes.

; V1.22  19-Feb-93
; - Tabs to spaces:
; - 3 new PC box chars.
; - Bug fixed that confused Port if the end of the commandline had spaces.
; - Spaces to tabs.

; V1.24  21-Feb-93
; - Size reduced by 48.
; - Bug fixed where tabconversion wasn't turned on in SpacesToTabs
;   causing some strange behavior.
; - Reduced code size by making routines use same parts of code.
; - Logic check for options.
; - +20% when quiet.

; V1.25  11-Mar-93
; - Buffer overflow bug fixed.
; - New table conversion system.
; - Buffered input.
; - Handles one filename differently.
; - CTRL+C detection.
; - Doesn't screw up PP files.
; - 6856 -> 6636.
; - 9 new PC chars.
; - End LF removal.
; - No longer translates one space.

; V1.28  20-Mar-93
; - First 7292 -> 6952 = -340 !
; - Bug fixed: Some bytes got cut off from the beginning if the file was
;   less than 4 bytes long.
; - Bug fix: Amy->PC didn't make CR+LF pairs as it should have in V1.25
;   same with Amy->SF
; - Most modes use table now.
; - Priorities changed for EndSpace removal and translation. This also fixes
;   the bug where endLFs didn't get removed if there were nulls or CTRL+Zs
;   etc.
; - Code rationalized, size down.
; - Doesn't trigger anything from CR's.
; - Make EOLs option.
; - Automode.

; V1.30  27-Mar-93
; - Added 13 PC chars.
; - No longer can convert 1 space to tabs (made no sense).

; V1.37  30-Apr-93
; - Changed automatic "Mode" to "Type".
; - Full PC->Amiga support implemented.
; - Optimized and reduced code.
; - Now uses includes.
; - Automatically find differently suffixed files by the the prefacing
;   name.
; - Ami changed to Amy.
; - A mode which throws out everything except pure ASCII stuff.
; - Fixed the slight flickering of various texts.
; - Fixed a bug which caused endspace removal to leave a space after some
;   lines when SpacesToTabs was on.
; - A fast PC->Amiga conversion routine.
; - Now you can specify only the destination directory, and the file will
;   be written correctly.

; V1.38  5-May-93
; - Fixed some small bugs in commandline handling which caused big shit.
;   65535 bytes big, ;)
; - Fixed errors in stack handling which caused gurus on errors.

; V1.39  4-Jun-93
; - Fixed the FromPC table, most of the box characters were messed up, and
;   made a few better choices for conversion.
; - FromPC didn't remove CRs anymore, oops.
; - ToPC and ToSF7 didn't work, now they do. (Were always FromPC)

; V1.46  12-Sep-93
; - Better translation of PC corner characters.
; - Many accented characters didn't have the accents in FromPC until now,
;   FINALLY, the FromPC SHOULD be as good as it will get.
; - Now in ToPC or ToSF7, MakeEOLs also adds a CR.
; - Uppercase and Lowercase modes should now support ALL characters.
; - Code much improved, should now be safer.
; - Disables break when converting to same file.
; - Text output buffered == much faster.
; - Output overflow buffering, Port now converts 10K at a time, and then
;   flushes the output buffer.
