diff --git a/contrib/toacme/src/Makefile b/contrib/toacme/src/Makefile
new file mode 100644
index 0000000..824c773
--- /dev/null
+++ b/contrib/toacme/src/Makefile
@@ -0,0 +1,57 @@
+CFLAGS		= -O3 -Wall
+#LIBS		= -lm
+CC		= gcc
+RM		= rm
+
+#SRC		=
+
+PROGS		= toacme
+BINDIR		= /usr/local/bin
+USERBIN		= $(HOME)/bin
+
+all: $(PROGS)
+
+ab3.o: config.h ab.h acme.h io.h mnemo.h scr2iso.h ab3.c
+
+ab.o: config.h ab.h acme.h io.h scr2iso.h ab.c
+
+f8ab.o: config.h ab.h acme.h io.h mnemo.h scr2iso.h f8ab.c
+
+giga.o: config.h acme.h gighyp.h io.h mnemo.h pet2iso.h giga.c
+
+gighyp.o: config.h io.h pet2iso.h gighyp.h gighyp.c
+
+hypra.o: config.h acme.h gighyp.h io.h pet2iso.h hypra.c
+
+obj.o: config.h acme.h io.h mnemo.h obj.c
+
+acme.o: config.h acme.h acme.c
+
+main.o: config.h version.h main.c
+
+mnemo.o: config.h mnemo.c
+
+pet2iso.o: config.h pet2iso.h pet2iso.c
+
+platform.o: config.h platform.h platform.c
+
+scr2iso.o: config.h scr2iso.h scr2iso.c
+
+version.o: config.h version.c
+
+toacme: ab.o ab3.o acme.o f8ab.o giga.o gighyp.o hypra.o io.o main.o mnemo.o obj.o pet2iso.o platform.o scr2iso.o version.o
+	$(CC) $(LIBS) $(CFLAGS) -o toacme ab.o ab3.o acme.o f8ab.o giga.o gighyp.o hypra.o io.o main.o mnemo.o obj.o pet2iso.o platform.o scr2iso.o version.o
+	strip toacme
+
+clean:
+	-$(RM) -f *.o $(PROGS) *~ core
+
+install: all
+	install -d $(BINDIR)
+	install $(PROGS) $(BINDIR)
+
+userinstall: all
+	install -d $(USERBIN)
+	install $(PROGS) $(USERBIN)
+
+# DO NOT DELETE
diff --git a/contrib/toacme/src/Makefile.dos b/contrib/toacme/src/Makefile.dos
new file mode 100644
index 0000000..e6173a7
--- /dev/null
+++ b/contrib/toacme/src/Makefile.dos
@@ -0,0 +1,60 @@
+CFLAGS		= -Wall -s
+#LIBS		= -lm
+CC		= gcc
+RM		= rm
+
+#SRC		=
+
+PROGS		= toacme
+#BINDIR		= /usr/local/bin
+#USERBIN	= $(HOME)/bin
+
+all: $(PROGS)
+
+ab3.o: config.h ab.h acme.h io.h mnemo.h scr2iso.h ab3.c
+
+ab.o: config.h ab.h acme.h io.h scr2iso.h ab.c
+
+f8ab.o: config.h ab.h acme.h io.h mnemo.h scr2iso.h f8ab.c
+
+giga.o: config.h acme.h gighyp.h io.h mnemo.h pet2iso.h giga.c
+
+gighyp.o: config.h io.h pet2iso.h gighyp.h gighyp.c
+
+hypra.o: config.h acme.h gighyp.h io.h pet2iso.h hypra.c
+
+obj.o: config.h acme.h io.h mnemo.h obj.c
+
+acme.o: config.h acme.h acme.c
+
+main.o: config.h version.h main.c
+
+mnemo.o: config.h mnemo.c
+
+pet2iso.o: config.h pet2iso.h pet2iso.c
+
+platform.o: config.h platform.h platform.c
+
+scr2iso.o: config.h scr2iso.h scr2iso.c
+
+version.o: config.h version.c
+
+toacme: ab.o ab3.o acme.o f8ab.o giga.o gighyp.o hypra.o io.o main.o mnemo.o obj.o pet2iso.o platform.o scr2iso.o version.o
+	$(CC) $(LIBS) $(CFLAGS) -o toacme.out ab.o ab3.o acme.o f8ab.o giga.o gighyp.o hypra.o io.o main.o mnemo.o obj.o pet2iso.o platform.o scr2iso.o version.o
+	copy /b \djgpp\bin\pmodstub.exe + toacme.out toacme_p.exe
+	djp toacme.exe
+	djp toacme_p.exe
+
+clean:
+	del *.o
+#	-$(RM) -f *.o $(PROGS) *~ core
+
+#install: all
+#	install -d $(BINDIR)
+#	install $(PROGS) $(BINDIR)
+
+#userinstall: all
+#	install -d $(USERBIN)
+#	install $(PROGS) $(USERBIN)
+
+# DO NOT DELETE
diff --git a/contrib/toacme/src/Makefile.riscos b/contrib/toacme/src/Makefile.riscos
new file mode 100644
index 0000000..cb69bc0
--- /dev/null
+++ b/contrib/toacme/src/Makefile.riscos
@@ -0,0 +1,57 @@
+CFLAGS		= -O3 -Wall -mthrowback -mlibscl -mno-poke-function-name
+#LIBS		= -lm
+CC		= gcc
+RM		= rm
+
+#SRC		=
+
+PROGS		= toacme
+#BINDIR		= /usr/local/bin
+#USERBIN	= $(HOME)/bin
+
+all: $(PROGS)
+
+ab3.o: config.h ab.h acme.h io.h mnemo.h scr2iso.h ab3.c
+
+ab.o: config.h ab.h acme.h io.h scr2iso.h ab.c
+
+f8ab.o: config.h ab.h acme.h io.h mnemo.h scr2iso.h f8ab.c
+
+giga.o: config.h acme.h gighyp.h io.h mnemo.h pet2iso.h giga.c
+
+gighyp.o: config.h io.h pet2iso.h gighyp.h gighyp.c
+
+hypra.o: config.h acme.h gighyp.h io.h pet2iso.h hypra.c
+
+obj.o: config.h acme.h io.h mnemo.h obj.c
+
+acme.o: config.h acme.h acme.c
+
+main.o: config.h version.h main.c
+
+mnemo.o: config.h mnemo.c
+
+pet2iso.o: config.h pet2iso.h pet2iso.c
+
+platform.o: config.h platform.h platform.c
+
+scr2iso.o: config.h scr2iso.h scr2iso.c
+
+version.o: config.h version.c
+
+toacme: ab.o ab3.o acme.o f8ab.o giga.o gighyp.o hypra.o io.o main.o mnemo.o obj.o pet2iso.o platform.o scr2iso.o version.o
+	$(CC) $(LIBS) $(CFLAGS) -o toacme ab.o ab3.o acme.o f8ab.o giga.o gighyp.o hypra.o io.o main.o mnemo.o obj.o pet2iso.o platform.o scr2iso.o version.o
+	Squeeze -f -v toacme
+
+#clean:
+#	-$(RM) -f *.o $(PROGS) *~ core
+
+#install: all
+#	install -d $(BINDIR)
+#	install $(PROGS) $(BINDIR)
+
+#userinstall: all
+#	install -d $(USERBIN)
+#	install $(PROGS) $(USERBIN)
+
+# DO NOT DELETE
diff --git a/contrib/toacme/src/ab.c b/contrib/toacme/src/ab.c
new file mode 100644
index 0000000..6b4d11e
--- /dev/null
+++ b/contrib/toacme/src/ab.c
@@ -0,0 +1,397 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2005 Marco Baye
+// Have a look at "main.c" for further info
+//
+// stuff needed for both "AssBlaster 3.x" and "F8-AssBlaster"
+//
+
+
+// Includes
+//
+#include <stdio.h>
+#include "ab.h"
+#include "acme.h"
+#include "io.h"
+#include "scr2iso.h"
+
+
+// Constants
+//
+#define SCREENCODE_UPARROW	(0x1e)
+// replacement characters for problematic label names
+#define AB_LABELSPECIAL_NUL	('O')	// AssBlaster uses only lower case
+#define AB_LABELSPECIAL_LEFT	('L')	// characters for labels, so these
+#define AB_LABELSPECIAL_BACK	('B')	// shouldn't cause any clashes.
+#define AB_LABELSPECIAL_RIGHT	('R')
+#define AB_LABELSPECIAL_UP	('A')
+// meaning of input bytes
+// 0x01-0x1f lower case screen codes (used for label names and comments)
+#define AB_SPACE	0x20
+// 0x20-0x3a special characters
+#define AB_COMMENT	0x3b
+// 0x3c-0x40 unused ?
+// 0x41-0x5f upper case screen codes (used for comments)
+// 0x60-0x7f unused ?
+#define AB_FIRST_MNEMONIC	0x80
+//	0x80-0xec differ between AssBlaster 3.x and F8-AssBlaster
+// 0xed-0xfe unused ?
+// 0xff end-of-line
+#define AB_PSEUDOOFFSET_MACROCALL	7	// index in PO table is equal
+#define AB_PSEUDOOFFSET_MACRODEF	5	// in AB3.x and F8-AB
+// after mnemonic or pseudo opcode, numbers may follow:
+#define AB_NUMVAL_FLAGBIT		0x80	// indicates packed number
+
+// Pre- and postfixes for addressing modes
+// Don't care whether argument is 8, 16 or 24 bits wide
+const char*	ab_address_modes[][2]	= {
+	{"",	""	},	// ($00=%.....) implicit
+	{" ",	""	},	// ($01=%....1) absolute
+	{" ",	",x"	},	// ($02=%...1.) absolute,x
+	{" ",	",y"	},	// ($03=%...11) absolute,y
+	{" #",	""	},	// ($04=%..1..) immediate
+	{NULL,	NULL	},	// ($05=%..1.1) unused (indirect-y)
+	{NULL,	NULL	},	// ($06=%..11.) unused (indirect-y)
+	{NULL,	NULL	},	// ($07=%..111) unused (indirect-y)
+	{" (",	"),y"	},	// ($08=%.1...) indirect-y
+	{" (",	",x)"	},	// ($09=%.1..1) indirect-x
+	{" ",	""	},	// ($0a=%.1.1.) relative (=absolute, actually)
+	{" (",	")"	},	// ($0b=%.1.11) indirect
+	// above: used by both AB3 and F8AB (except $0a, which is no longer
+	// used by F8AB. But it's indistinguishable from $01 anyway).
+	// FIXME - what does AB3 with the other unused addressing modes?
+	// I think old AB3 sources may also use mode 0c!
+	// below: used by F8AB only
+	{NULL,	NULL	},	// ($0c=%.11..) unused (indirect-x)
+	{" [",	"]"	},	// ($0d=%.11.1) indirect long
+	{NULL,	NULL	},	// ($0e=%.111.) unused (absolute)
+	{NULL,	NULL	},	// ($0f=%.1111) unused (absolute-x)
+	{" ",	""	},	// ($10=%1....) MVP/MVN in F8AB: arg1.arg2
+	{NULL,	NULL	},	// ($11=%1...1) unused (indirect)
+	{NULL,	NULL	},	// ($12=%1..1.) unused (indirect long)
+	{" [",	"],y"	},	// ($13=%1..11) indirect-y long
+	{NULL,	NULL	},	// ($14=%1.1..) unused (absolute)
+	{" ",	",s"	},	// ($15=%1.1.1) stack-relative
+	{" (",	",s),y"	},	// ($16=%1.11.) stack-relative-indirect-y
+	// from here on, unused (indirect-y)
+	// addressing mode $10 (for MVP/MVN) is displayed and stored by F8AB
+	// as "arg1.arg2" instead of "arg1,arg2". Therefore the following
+	// constant is used to fix it on-the-fly.
+};
+#define AB_MVP_MVN_ADDRMODE	0x10
+
+
+// Variables
+//
+struct ab_t*	conf;
+
+
+// Functions
+//
+
+
+// Generate error/warning messages
+//
+const char	error_unknown_addressing[]	= "Conversion failed: AssBlaster file contains unknown addressing mode.\n";
+const char	error_unknown_compression[]	= "Conversion failed: AssBlaster file contains unknown number compression.\n";
+const char	warning_unknown_number_format[]	= "Warning: AssBlaster file uses unknown number format. Fallback to hexadecimal.\n";
+void ab_generate_errors(int ErrBits) {
+	if(ErrBits & AB_ERRBIT_UNKNOWN_ADDRMODE) {
+		fputs(error_unknown_addressing, stderr);
+		fprintf(global_output_stream, "; ToACME: %s", error_unknown_addressing);
+	}
+	if(ErrBits & AB_ERRBIT_UNKNOWN_NUMBER_COMPRESSION) {
+		fputs(error_unknown_compression, stderr);
+		fprintf(global_output_stream, "; ToACME: %s", error_unknown_compression);
+	}
+	if(ErrBits & AB_ERRBIT_UNKNOWN_NUMBER_FORMAT) {
+		fputs(warning_unknown_number_format, stderr);
+		fprintf(global_output_stream, "; ToACME: %s", warning_unknown_number_format);
+	}
+}
+
+// Convert macro/label name character.
+// AssBlaster allows '^', '[' and ']' in names, so replace these chars.
+//
+byte_t ab_conv_name_char(byte_t b) {
+	b = Scr2ISO_Table[b];
+	switch(b) {
+		case 0x40:
+		return(AB_LABELSPECIAL_NUL);
+		case '[':
+		return(AB_LABELSPECIAL_LEFT);
+		case '\\':
+		return(AB_LABELSPECIAL_BACK);
+		case ']':
+		return(AB_LABELSPECIAL_RIGHT);
+		case '^':
+		return(AB_LABELSPECIAL_UP);
+		default:
+		return(b);
+	}
+}
+
+// Output binary representation of value
+//
+void ab_output_binary(unsigned long int v) {
+	int	m	= 128;
+
+	if(v > 0xff)
+		ab_output_binary(v >> 8);
+	v &= 0xff;
+	while(m) {
+		PutByte((v & m) ? '1' : '0');
+		m >>= 1;
+	}
+}
+
+// Output hex representation of value
+//
+void ab_output_hexadecimal(unsigned long int v) {
+	if(v > 0xff)
+		ab_output_hexadecimal(v >> 8);
+	io_put_low_byte_hex(v);
+}
+
+// Convert and send macro/label name (until illegal character comes along)
+//
+void ab_pipe_global_name(void) {
+	while((GotByte < 0x20) || ((GotByte >= '0') && (GotByte <= '9'))) {
+		PutByte(ab_conv_name_char(GotByte));
+		GetByte();
+	}
+}
+
+// Convert and send label name (until illegal character comes along)
+// Level 1
+void ab_pipe_name(void) {
+	// Dieser kleine Hack macht alle lokalen ABL-Labels
+	// Auch unter ACME lokal.  nur mit '^' global markierte
+	// Labels werden auch global �bernommen ...
+	if(GotByte == SCREENCODE_UPARROW)
+		GetByte();	// global:	^witharrow => witharrow
+	else
+		PutByte('.');	// local:	allothers => .allothers
+	ab_pipe_global_name();	// this does exactly what is needed
+}
+
+// Parse quoted strings
+//
+void ab_parse_quoted(void) {// now GotByte = unhandled opening quote
+
+	PutByte('"');
+	GetByte();
+	while((GotByte != AB_ENDOFLINE) && (GotByte != '"')) {
+		PutByte(Scr2ISO_Table[GotByte]);
+		GetByte();
+	}
+	PutByte('"');
+
+	// Closing quote is handled, but EndOfLine must remain unhandled
+	if(GotByte == '"')
+		GetByte();
+}
+
+// Parse label names, quoted strings, operators, literal values etc.
+// Read until AB_ENDOFLINE or AB_COMMENT. Returns error bits.
+// Level 1
+// AB uses a full stop character ('.') in some inconvenient places, for example
+// after macro names (at definitions and calls) and in the MVP/MVN addressing
+// mode. The kluge variable "dot_replacement" is used to replace the '.'
+// character with the correct character for ACME.
+int ab_parse_unspecified(char dot_replacement) {
+	int	ErrBits	= 0;
+
+	while((GotByte != AB_ENDOFLINE) && (GotByte != AB_COMMENT)) {
+		// kluge: replace '.' character with current replacement and
+		// remember not to replace anymore from now on.
+		if(GotByte == '.') {
+			GotByte = dot_replacement;	// use replacement
+			dot_replacement = '.';		// in future, keep
+		}
+		if(GotByte & AB_NUMVAL_FLAGBIT)
+			ErrBits |= conf->number_parser();
+		else {
+			if(GotByte < 0x20)
+				ab_pipe_name();
+			else {
+				if(GotByte == '"')
+					ab_parse_quoted();
+				else {
+					PutByte(Scr2ISO_Table[GotByte]);
+					GetByte();
+				}
+			}
+		}
+	}
+	return(ErrBits);
+}
+
+// Parse macro call or start of definition (beware of full stops).
+// Returns error bits.
+//
+int ab_parse_macro_stuff(void) {	// now GotByte = unhandled byte
+	// I guess local macros are useless, so don't
+	// do the scope fixing as for macro names!
+	ab_pipe_global_name();
+	return(ab_parse_unspecified(' '));	// output macro arguments
+}
+
+// Process mnemonics (real opcodes). Returns error bits.
+// Level 1
+int ab_parse_mnemo(int mnemonic_offset) {
+	char		dot_replacement	= '.';
+	int		ErrBits	= 0;
+	byte_t		AddressingMode;
+	const char	*mnemonic,
+			*pre,
+			*post;
+
+	AddressingMode = GetByte();	// get addressing mode
+	GetByte();	// and fetch next (not handled here)
+	mnemonic = conf->mnemonics[mnemonic_offset];
+	if(mnemonic == NULL) {
+		fputs("Found unused mnemo code in input file.\n", stderr);
+		mnemonic = "!error \"ToACME found unused mnemo code in input file\":";
+	}
+	fprintf(global_output_stream, "\t\t%s", mnemonic);
+	// determine prefix and postfix of addressing mode
+	if(AddressingMode < conf->address_mode_count) {
+		pre = ab_address_modes[AddressingMode][0];
+		post = ab_address_modes[AddressingMode][1];
+		if(AddressingMode == AB_MVP_MVN_ADDRMODE)
+			dot_replacement = ',';	// replace '.' with ','
+	} else {
+		pre = NULL;
+		post = NULL;
+	}
+	// if addressing mode is invalid, set error bit
+	// output prefix (or space if invalid)
+	if((pre == NULL) || (post == NULL)) {
+		ErrBits |= AB_ERRBIT_UNKNOWN_ADDRMODE;
+		fprintf(stderr, "Found an unknown addressing mode bit pattern ($%x). Please tell my programmer.\n", AddressingMode);
+	}
+	if(pre)
+		fputs(pre, global_output_stream);
+	else
+		PutByte(' ');
+	ErrBits |= ab_parse_unspecified(dot_replacement);	// output arg
+	if(post) {
+		fputs(post, global_output_stream);
+	}
+	return(ErrBits);
+}
+
+// Process pseudo opcodes. Returns error bits.
+// Level 1
+int ab_parse_pseudo_opcode(int pseudo_offset) {
+	const char*	String;
+	int		ErrBits	= 0;
+
+	GetByte();	// and fetch next (not handled here)
+	fputs("\t\t", global_output_stream);
+	String = conf->pseudo_opcodes[pseudo_offset];
+	if(String)
+		fputs(String, global_output_stream);
+	// check for macro call/definition (need special handlers)
+	switch(pseudo_offset) {
+
+		case AB_PSEUDOOFFSET_MACROCALL:	// (in ACME: '+')
+		// ACME does not like spaces after the macro call char
+		ErrBits |= ab_parse_macro_stuff();
+		break;
+
+		case AB_PSEUDOOFFSET_MACRODEF:	// macro definition
+		if(String)
+			PutByte(' ');// but here a space looks good :)
+		ErrBits |= ab_parse_macro_stuff();
+		fputs(" {", global_output_stream);
+		break;
+
+		default:	// all other pseudo opcodes
+		if((String)
+		&& (GotByte != AB_ENDOFLINE)
+		&& (GotByte != AB_COMMENT))
+			PutByte(' ');// but here a space looks good :)
+		ErrBits |= ab_parse_unspecified('.');	// output pseudo opcode's arg(s)
+	}
+	return(ErrBits);
+}
+
+// Main routine for AssBlaster conversion (works for both AB3.x and F8-AB).
+// Call with first byte of first line pre-read (in GotByte)!
+//
+void ab_main(struct ab_t* client_config) {
+	int		ErrBits;
+	const char	*comment_indent;
+
+	conf = client_config;
+	acme_SwitchToPet();
+	// convert lines until EndOfFile
+	while(!ReachedEOF) {
+		ErrBits = 0;	// no errors yet (in this line)
+		comment_indent = "\t";
+		if(GotByte < AB_FIRST_MNEMONIC) {
+			switch(GotByte) {
+
+				case 0:	// empty line
+				GetByte();	// skip this byte
+				break;
+
+				case AB_COMMENT:	// early comment
+				comment_indent = "";
+				break;	// ignore now, act later
+
+				case AB_SPACE:	// empty line or late comment
+				comment_indent = "\t\t\t\t";
+				GetByte();	// skip this space
+				// output whatever found
+				ErrBits |= ab_parse_unspecified('.');
+				break;
+
+				default:	// implicit label definition
+				ab_pipe_name();
+			}
+		} else if(GotByte < conf->first_pseudo_opcode) {
+			ErrBits |= ab_parse_mnemo(GotByte - AB_FIRST_MNEMONIC);
+		} else if(GotByte < conf->first_unused_byte_value) {
+			ErrBits |= ab_parse_pseudo_opcode(GotByte - conf->first_pseudo_opcode);
+		} else if(GotByte != AB_ENDOFLINE) {
+			fprintf(global_output_stream, "; ToACME: AssBlaster file used unknown code ($%x). ", GotByte);
+			GetByte();	// fetch next
+			ErrBits |= ab_parse_unspecified('.');	// output remainder
+		}
+
+		// everything might be followed by a comment, so check
+		if(GotByte == AB_COMMENT) {
+			// skip empty comments by checking next byte
+			if(GetByte() != AB_ENDOFLINE) {
+				// something's there, so pipe until end of line
+				fputs(comment_indent, global_output_stream);
+				PutByte(';');
+				do
+					PutByte(Scr2ISO_Table[GotByte]);
+				while(GetByte() != AB_ENDOFLINE);
+			}
+		}
+
+		// now check whether line generated any errors
+		if(ErrBits)
+			ab_generate_errors(ErrBits);
+
+		// if not at end-of-line, something's fishy
+		if(GotByte != AB_ENDOFLINE) {
+			if(GotByte == '\0')
+				fputs("; ToACME: found $00 - looks like end-of-file marker.", global_output_stream);
+			else {
+				fputs("Found data instead of end-of-line indicator!?.\n", stderr);
+				fputs("; ToACME: Garbage at end-of-line:", global_output_stream);
+				do
+					PutByte(Scr2ISO_Table[GotByte]);
+				while(GetByte() != AB_ENDOFLINE);
+			}
+		}
+		PutByte('\n');
+		// read first byte of next line
+		GetByte();
+	}
+}
diff --git a/contrib/toacme/src/ab.h b/contrib/toacme/src/ab.h
new file mode 100644
index 0000000..a808fb4
--- /dev/null
+++ b/contrib/toacme/src/ab.h
@@ -0,0 +1,47 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// stuff needed for both "AssBlaster 3.x" and "F8-AssBlaster"
+//
+#ifndef ab_H
+#define ab_H
+
+
+// Includes
+//
+#include "config.h"
+
+
+// Types
+//
+struct ab_t {
+	int		(*number_parser)(void);
+	const char**	pseudo_opcodes;
+	const char**	mnemonics;
+	int		address_mode_count;
+	int		first_pseudo_opcode;
+	int		first_unused_byte_value;
+};
+
+
+// Constants
+//
+#define AB_ENDOFLINE	0xff
+// meaning of internal error word. errors are collected until *after* a line
+// has been finished so the warning messages don't interfere with the generated
+// source code.
+#define AB_ERRBIT_UNKNOWN_ADDRMODE		0x01
+#define AB_ERRBIT_UNKNOWN_NUMBER_COMPRESSION	0x02	// invalid contents of SIZEMASK
+#define AB_ERRBIT_UNKNOWN_NUMBER_FORMAT		0x04	// invalid contents of FORMATMASK
+
+
+
+
+// Prototypes
+//
+extern void	ab_output_binary(unsigned long int v);
+extern void	ab_output_hexadecimal(unsigned long int v);
+extern void	ab_main(struct ab_t* client_config);
+
+#endif
diff --git a/contrib/toacme/src/ab3.c b/contrib/toacme/src/ab3.c
new file mode 100644
index 0000000..a7be2f6
--- /dev/null
+++ b/contrib/toacme/src/ab3.c
@@ -0,0 +1,189 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// AssBlaster 3.x stuff
+//
+
+
+// Includes
+//
+#include <stdlib.h>
+#include <stdio.h>
+#include "config.h"
+#include "ab.h"
+#include "acme.h"
+#include "mnemo.h"
+#include "io.h"
+#include "scr2iso.h"
+
+
+// Constants
+//
+
+// Mnemonic table in AssBlaster 3.x order
+const char*	ab3_mnemonics[]	= {
+	NULL,		// $80 unused
+	MnemonicCPX,	// $81
+	MnemonicCPY,	// $82
+	MnemonicLDX,	// $83
+	MnemonicLDY,	// $84
+	MnemonicSTX,	// $85
+	MnemonicSTY,	// $86
+	"!illegal aax",	// $87 illegal aax (sta+stx)	this is broken in AB3!
+	"!illegal asr",	// $88 illegal asr (?)
+	"!illegal arr",	// $89 illegal arr (?)
+	"!illegal axs",	// $8a illegal axs (x=(a&x)-#)
+	"!illegal dcp",	// $8b illegal dcp (dec+cmp)
+	"!illegal dop",	// $8c illegal dop (double nop, skip next byte)
+	"!illegal isc",	// $8d illegal isc (inc+sbc)			aka isb
+	"!illegal kil",	// $8e illegal kil (kill/crash/halt)
+	"!illegal lar",	// $8f illegal lar (allocated, but never used in AB3?)
+	"!illegal lax",	// $90 illegal lax (lda+ldx)
+	"!illegal rla",	// $91 illegal rla (rol+and)
+	"!illegal rra",	// $92 illegal rra (ror+adc)
+	"!illegal slo",	// $93 illegal slo (asl+ora)
+	"!illegal sre",	// $94 illegal sre (lsr+eor)
+	"!illegal top",	// $95 illegal top (triple nop, skip next word)
+	MnemonicADC,	// $96
+	MnemonicAND,	// $97
+	MnemonicASL,	// $98
+	MnemonicBIT,	// $99
+	MnemonicBCS, MnemonicBEQ, MnemonicBCC, MnemonicBMI,	// $9a-$9d
+	MnemonicBNE, MnemonicBPL, MnemonicBVS, MnemonicBVC,	// $9e-$a1
+	MnemonicBRK,						// $a2
+	MnemonicCLC, MnemonicCLD, MnemonicCLI, MnemonicCLV,	// $a3-$a6
+	MnemonicCMP,						// $a7
+	MnemonicDEC, MnemonicDEX, MnemonicDEY,			// $a8-$aa
+	MnemonicEOR,						// $ab
+	MnemonicINC, MnemonicINX, MnemonicINY,			// $ac-$ae
+	MnemonicJMP, MnemonicJSR,				// $af-$b0
+	MnemonicLDA,						// $b1
+	MnemonicLSR,						// $b2
+	MnemonicNOP,						// $b3
+	MnemonicORA,						// $b4
+	MnemonicPHA, MnemonicPHP, MnemonicPLA, MnemonicPLP,	// $b5-$b8
+	MnemonicROL, MnemonicROR,				// $b9-$ba
+	MnemonicRTI, MnemonicRTS,	// ($bf-$c0 in F8-AB)	   $bb-$bc
+	MnemonicSBC,						// $bd
+	MnemonicSEC, MnemonicSED, MnemonicSEI,			// $bc-$c0
+	MnemonicSTA,						// $c1
+	MnemonicTAX, MnemonicTAY, MnemonicTSX,			// $c2-$c4
+	MnemonicTXA, MnemonicTXS, MnemonicTYA,			// $c5-$c7
+};
+
+// PseudoOpcode table in AssBlaster 3.x order
+const char*	ab3_pseudo_opcodes[]	= {
+	NULL,			// (la) $c8
+	// NULL because ACME does not need a pseudo opcode for label defs
+	PseudoOp_SetPC,		// (ba) $c9
+	PseudoOp_Byte,		// (by) $ca
+	PseudoOp_Fill,		// (br) $cb
+	PseudoOp_PetTxt,	// (tx) $cc
+	PseudoOp_MacroDef,	// (md) $cd	index 5 in this table
+	PseudoOp_EndMacroDef,	// (me) $ce
+	PseudoOp_MacroCall,	// (ma) $cf	index 7 in this table
+	PseudoOp_EOF,		// (st) $d0
+	PseudoOp_ScrTxt,	// (ts) $d1
+	PseudoOp_ToFile,	// (to) $d2
+	PseudoOp_Word,		// (wo) $d3
+	"; ToACME: Cannot convert \\kc.\n",
+				// (kc) $d4
+};
+
+// Parse AssBlaster's packed number format. Returns error bits.
+//
+//#define AB_NUMVAL_FLAGBIT	0x80	// 10000000 indicates packed number
+#define AB3_NUMVAL_ADD_1	0x40	// 01000000
+#define AB3_NUMVAL_ADD_256	0x20	// 00100000
+#define AB3_NUMVAL_FORMATMASK	0x1a	// 00011010
+#define AB3_NUMVAL__FORMAT_HEX	0x10	// 00010000=16 (oh my god, the base is
+#define AB3_NUMVAL__FORMAT_DEC	0x0a	// 00001010=10  given directly, without
+#define AB3_NUMVAL__FORMAT_BIN	0x02	// 00000010= 2  any encoding... :))
+#define AB3_NUMVAL_SIZEMASK	0x05	// 00000101
+#define AB3_NUMVAL__SIZE_0	0x01	// 00000001
+#define AB3_NUMVAL__SIZE_1	0x04	// 00000100
+#define AB3_NUMVAL__SIZE_2	0x00	// 00000000
+int ab3_parse_number(void) {	// now GotByte = first byte of packed number
+	int			Flags	= GotByte,
+				ErrBits	= 0;
+	unsigned long int	Value	= 0,
+				Add	= 0;
+
+	// decode value
+	if(Flags & AB3_NUMVAL_ADD_1)
+		Add += 1;
+	if(Flags & AB3_NUMVAL_ADD_256)
+		Add += 256;
+	switch(Flags & AB3_NUMVAL_SIZEMASK) {
+
+		case AB3_NUMVAL__SIZE_0:// no bytes follow (0, 1, 256, 257)
+		Value = Add;
+		break;
+
+		case AB3_NUMVAL__SIZE_1:// one byte follows (2 to 511)
+		Value = Add + GetByte();
+		break;
+
+		case AB3_NUMVAL__SIZE_2:// two bytes follow (512 to 65535)
+		Value = Add + GetLE16();
+		break;
+
+		default:	// unknown number compression
+		// remember to generate error
+		ErrBits |= AB_ERRBIT_UNKNOWN_NUMBER_COMPRESSION;
+	}
+	// continue parsing on next byte
+	GetByte();
+
+	// decode output format
+	switch(Flags & AB3_NUMVAL_FORMATMASK) {
+
+		case AB3_NUMVAL__FORMAT_BIN:
+		PutByte('%');
+		ab_output_binary(Value);
+		break;
+
+		case AB3_NUMVAL__FORMAT_DEC:
+		fprintf(global_output_stream, "%lu", Value);
+		break;
+
+		case AB3_NUMVAL__FORMAT_HEX:
+hex_fallback:	PutByte('$');
+		ab_output_hexadecimal(Value);
+		break;
+
+		default:	// unknown output format
+		// remember to warn
+		ErrBits |= AB_ERRBIT_UNKNOWN_NUMBER_FORMAT;
+		goto hex_fallback;
+	}
+	return(ErrBits);
+}
+
+// config struct for shared ab code
+struct ab_t	ab3_conf	= {
+	ab3_parse_number,
+	ab3_pseudo_opcodes,
+	ab3_mnemonics,
+	12,	// number of addressing modes
+	// meaning of input bytes (0x80-0xec differ between AB 3.x and F8-AB)
+	// 0x80 unused, then 56 legals + 15 illegals = 71
+	0xc8,	// first pseudo opcode
+	0xd5,	// first unused byte value
+	// 0xd5-0xfe are unused in AB 3.x
+};
+
+// main
+//
+void ab3_main(void) {
+	input_set_padding(AB_ENDOFLINE);
+	io_process_load_address();
+	// first byte after load address should be AB_ENDOFLINE in AB3 sources
+	if(GetByte() == AB_ENDOFLINE) {
+		GetByte();	// skip it and pre-read first valid byte
+		fputs("Input has AB3 header.\n", stderr);
+	} else
+		fputs("Input does not have any known AB3 header.\n", stderr);
+	ab_main(&ab3_conf);
+}
diff --git a/contrib/toacme/src/acme.c b/contrib/toacme/src/acme.c
new file mode 100644
index 0000000..f2220ad
--- /dev/null
+++ b/contrib/toacme/src/acme.c
@@ -0,0 +1,53 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// ACME syntax
+//
+
+// Includes
+//
+#include "acme.h"
+#include "io.h"
+
+
+// Constants
+//
+
+// Pseudo opcodes
+const char	PseudoOp_Byte[]		= "!byte";
+const char	PseudoOp_Else[]		= "} else {";
+const char	PseudoOp_EndIf[]	= "}; (end of conditional assembly)\n";
+const char	PseudoOp_EndMacroDef[]	= "}; (end of macro definition)\n";
+const char	PseudoOp_EOF[]		= "!eof";
+const char	PseudoOp_Fill[]		= "!fill";
+const char	PseudoOp_If[]		= "!if";
+const char	PseudoOp_LabelDump[]	= "!sl";
+const char	PseudoOp_MacroCall[]	= "+";
+const char	PseudoOp_MacroDef[]	= "!macro";
+const char	PseudoOp_PetTxt[]	= "!pet";
+const char	PseudoOp_ScrTxt[]	= "!scr";
+const char	PseudoOp_SetPC[]	= "*=";
+const char	PseudoOp_Source[]	= "!src";
+const char	PseudoOp_ToFile[]	= "!to";
+const char	PseudoOp_Word[]		= "!word";
+// Pseudo opcodes for 65816 (used by F8-AssBlaster)
+const char	PseudoOp_al[]		= "!al";
+const char	PseudoOp_as[]		= "!as";
+const char	PseudoOp_rl[]		= "!rl";
+const char	PseudoOp_rs[]		= "!rs";
+
+
+// Functions
+//
+
+
+// Output pseudo opcode to make ACME use PetSCII encoding
+//
+void acme_SwitchToPet(void) {
+
+	fputs(
+"; ToACME: Adding pseudo opcode to use PetSCII encoding by default:\n"
+"!convtab pet\n"
+	, global_output_stream);
+}
diff --git a/contrib/toacme/src/acme.h b/contrib/toacme/src/acme.h
new file mode 100644
index 0000000..ff81f0f
--- /dev/null
+++ b/contrib/toacme/src/acme.h
@@ -0,0 +1,43 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// ACME syntax
+//
+#ifndef acme_H
+#define acme_H
+
+
+// Constants
+//
+
+// pseudo opcodes
+extern const char	PseudoOp_Byte[];
+extern const char	PseudoOp_Else[];
+extern const char	PseudoOp_EndIf[];
+extern const char	PseudoOp_EndMacroDef[];
+extern const char	PseudoOp_EOF[];
+extern const char	PseudoOp_Fill[];
+extern const char	PseudoOp_If[];
+extern const char	PseudoOp_LabelDump[];
+extern const char	PseudoOp_MacroCall[];
+extern const char	PseudoOp_MacroDef[];
+extern const char	PseudoOp_PetTxt[];
+extern const char	PseudoOp_ScrTxt[];
+extern const char	PseudoOp_SetPC[];
+extern const char	PseudoOp_Source[];
+extern const char	PseudoOp_ToFile[];
+extern const char	PseudoOp_Word[];
+// pseudo opcodes for 65816 cpu
+extern const char	PseudoOp_al[];
+extern const char	PseudoOp_as[];
+extern const char	PseudoOp_rl[];
+extern const char	PseudoOp_rs[];
+
+
+// Prototypes
+//
+extern void	acme_SwitchToPet(void);
+
+
+#endif
diff --git a/contrib/toacme/src/config.h b/contrib/toacme/src/config.h
new file mode 100644
index 0000000..961a957
--- /dev/null
+++ b/contrib/toacme/src/config.h
@@ -0,0 +1,26 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Configurable stuff
+// ...this file gets included by almost all others, even *.h files
+//
+#ifndef config_H
+#define config_H
+
+
+// Types
+//
+typedef unsigned char	byte_t;
+
+
+// Constants
+//
+#ifndef FALSE
+typedef int	bool;
+#define FALSE	0
+#define TRUE	1
+#endif
+
+
+#endif
diff --git a/contrib/toacme/src/f8ab.c b/contrib/toacme/src/f8ab.c
new file mode 100644
index 0000000..ebb7a75
--- /dev/null
+++ b/contrib/toacme/src/f8ab.c
@@ -0,0 +1,276 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// F8-AssBlaster stuff
+//
+
+
+// Includes
+//
+#include <stdlib.h>
+#include <stdio.h>
+#include "config.h"
+#include "ab.h"
+#include "acme.h"
+#include "mnemo.h"
+#include "io.h"
+#include "scr2iso.h"
+
+
+// Constants
+//
+
+// Mnemonic table in F8-AssBlaster order (without: MnemonicJML, MnemonicWDM)
+const char*	f8ab_mnemonics[]	= {
+	MnemonicADC,	// $80 6502
+	MnemonicAND,	// $81 6502
+	MnemonicASL,	// $82 6502
+	MnemonicBCC,	// $83 6502
+	MnemonicBCS,	// $84 6502
+	MnemonicBEQ,	// $85 6502
+	MnemonicBIT,	// $86 6502
+	MnemonicBMI,	// $87 6502
+	MnemonicBNE,	// $88 6502
+	MnemonicBPL,	// $89 6502
+	MnemonicBRA,	// $8a 65c02
+	MnemonicBRK,	// $8b 6502
+	MnemonicBRL,	// $8c 65816
+	MnemonicBVC,	// $8d 6502
+	MnemonicBVS,	// $8e 6502
+	MnemonicCLC,	// $8f 6502
+	MnemonicCLD,	// $90 6502
+	MnemonicCLI,	// $91 6502
+	MnemonicCLV,	// $92 6502
+	MnemonicCMP,	// $93 6502
+	MnemonicCOP,	// $94 65816
+	MnemonicCPX,	// $95 6502
+	MnemonicCPY,	// $96 6502
+	MnemonicDEC,	// $97	F8AB uses DEA as the 65816's "DEC-implicit"
+	MnemonicDEC,	// $98 6502
+	MnemonicDEX,	// $99 6502
+	MnemonicDEY,	// $9a 6502
+	MnemonicEOR,	// $9b 6502
+	MnemonicINC,	// $9c	F8AB uses INA as the 65816's "INC-implicit"
+	MnemonicINC,	// $9d 6502
+	MnemonicINX,	// $9e 6502
+	// seems as if F8AB does not know MnemonicJML (65816)...
+	MnemonicINY,	// $9f 6502
+	MnemonicJMP,	// $a0 6502
+	MnemonicJSL,	// $a1 65816	...but it *does* know JSL? Strange.
+	MnemonicJSR,	// $a2 6502
+	MnemonicLDA,	// $a3 6502
+	MnemonicLDX,	// $a4 6502
+	MnemonicLDY,	// $a5 6502
+	MnemonicLSR,	// $a6 6502
+	"+F8AB_BROKEN_MVN",	// $a7 65816	F8AB uses non-standard argument
+	"+F8AB_BROKEN_MVP",	// $a8 65816	ordering with MVP/MVN
+	MnemonicNOP,	// $a9 6502
+	MnemonicORA,	// $aa 6502
+	MnemonicPEA,	// $ab 65816
+	MnemonicPEI,	// $ac 65816
+	MnemonicPER,	// $ad 65816
+	MnemonicPHA,	// $ae 6502
+	MnemonicPHB,	// $af 65816
+	MnemonicPHD,	// $b0 65816
+	MnemonicPHK,	// $b1 65816
+	MnemonicPHP,	// $b2 6502
+	MnemonicPHX,	// $b3 65c02
+	MnemonicPHY,	// $b4 65c02
+	MnemonicPLA,	// $b5 6502
+	MnemonicPLB,	// $b6 65816
+	MnemonicPLD,	// $b7 65816
+	MnemonicPLP,	// $b8 6502
+	MnemonicPLX,	// $b9 65c02
+	MnemonicPLY,	// $ba 65c02
+	MnemonicREP,	// $bb 65816
+	MnemonicROL,	// $bc 6502
+	MnemonicROR,	// $bd 6502
+	MnemonicRTI,	// $be 6502
+	MnemonicRTL,	// $bf 65816
+	MnemonicRTS,	// $c0 6502
+	MnemonicSBC,	// $c1 6502
+	MnemonicSED,	// $c2 6502	strange order - SED before SEC?
+	MnemonicSEC,	// $c3 6502
+	MnemonicSEI,	// $c4 6502
+	MnemonicSEP,	// $c5 65816
+	MnemonicSTA,	// $c6 6502
+	MnemonicSTP,	// $c7 65816
+	MnemonicSTX,	// $c8 6502
+	MnemonicSTY,	// $c9 6502
+	MnemonicSTZ,	// $ca 65c02
+	MnemonicTAX,	// $cb 6502
+	MnemonicTAY,	// $cc 6502
+	MnemonicTCD,	// $cd 65816
+	MnemonicTCS,	// $ce 65816
+	MnemonicTDC,	// $cf 65816
+	MnemonicTRB,	// $d0 65c02
+	MnemonicTSB,	// $d1 65c02
+	MnemonicTSC,	// $d2 65816
+	MnemonicTSX,	// $d3 6502
+	MnemonicTXA,	// $d4 6502
+	MnemonicTXS,	// $d5 6502
+	MnemonicTXY,	// $d6 65816
+	MnemonicTYA,	// $d7 6502
+	MnemonicTYX,	// $d8 65816
+	MnemonicWAI,	// $d9 65816
+	// seems as if F8AB does not know MnemonicWDM (65816)
+	MnemonicXBA,	// $da 65816
+	MnemonicXCE,	// $db 65816
+};
+
+// PseudoOpcode table in F8-AssBlaster order
+const char*	f8ab_pseudo_opcodes[]	= {
+	NULL,			// (la) $dc
+	// NULL because ACME does not need a pseudo opcode for label defs
+	PseudoOp_SetPC,		// (ba) $dd
+	PseudoOp_Byte,		// (by) $de
+	PseudoOp_Fill,		// (br) $df
+	PseudoOp_PetTxt,	// (tx) $e0
+	PseudoOp_MacroDef,	// (md) $e1	index 5 in this table
+	PseudoOp_EndMacroDef,	// (de) $e2
+	PseudoOp_MacroCall,	// (ma) $e3	index 7 in this table
+	PseudoOp_EOF,		// (st) $e4
+//	PseudoOp_ScrTxt is not available in F8AB. Huh?!
+	"; ToACME: Cannot convert \\wa.\n",
+				// (wa) $e5
+	PseudoOp_ToFile,	// (on) $e6
+	PseudoOp_Word,		// (wo) $e7
+	"; ToACME: Cannot convert \\kc.\n",
+				// (kc) $e8
+	PseudoOp_rl,		// (rl) $e9
+	PseudoOp_rs,		// (rs) $ea
+	PseudoOp_al,		// (al) $eb
+	PseudoOp_as,		// (as) $ec
+};
+
+// Parse AssBlaster's packed number format. Returns error bits.
+//
+//#define AB_NUMVAL_FLAGBIT	0x80	// 10000000 indicates packed number
+#define F8AB_NUMVAL_ADD_65536	0x40	// 01000000
+#define F8AB_NUMVAL_ADD_256	0x20	// 00100000
+#define F8AB_NUMVAL_ADD_1	0x10	// 00010000
+#define F8AB_NUMVAL_FORMATMASK	0x0c	// 00001100
+#define F8AB_NUMVAL__FORMAT_BIN	0x00	// 00000000
+#define F8AB_NUMVAL__FORMAT_DEC	0x04	// 00000100
+#define F8AB_NUMVAL__FORMAT_HEX	0x08	// 00001000
+#define F8AB_NUMVAL__FORMAT_ILL	0x0c	// 00001100 never used by F8AB
+#define F8AB_NUMVAL_SIZEMASK	0x03	// 00000011
+#define F8AB_NUMVAL__SIZE_0	0x00	// 00000000
+#define F8AB_NUMVAL__SIZE_1	0x01	// 00000001
+#define F8AB_NUMVAL__SIZE_2	0x02	// 00000010
+#define F8AB_NUMVAL__SIZE_3	0x03	// 00000011
+int f8ab_parse_number(void) {	// now GotByte = first byte of packed number
+	int			Flags	= GotByte,
+				ErrBits	= 0;
+	unsigned long int	Value	= 0,
+				Add	= 0;
+
+	// decode value
+	if(Flags & F8AB_NUMVAL_ADD_65536)
+		Add += 65536;
+	if(Flags & F8AB_NUMVAL_ADD_256)
+		Add += 256;
+	if(Flags & F8AB_NUMVAL_ADD_1)
+		Add += 1;
+	switch(Flags & F8AB_NUMVAL_SIZEMASK) {
+
+		case F8AB_NUMVAL__SIZE_0:// no bytes follow (0, 1, 256, 257)
+		Value = Add;
+		break;
+
+		case F8AB_NUMVAL__SIZE_1:// one byte follows (2 to 511)
+		Value = Add + GetByte();
+		break;
+
+		case F8AB_NUMVAL__SIZE_2:// two bytes follow (512 to 65535)
+		Value = Add + GetLE16();
+		break;
+
+		case F8AB_NUMVAL__SIZE_3:// three bytes follow (anything else)
+		Value = Add + GetByte() + (GetLE16() << 8);
+		break;
+
+		default:	// unknown number compression
+		// this is actually dead code for the F8-AB converter, as
+		// there are only four possible bit combinations... :)
+		// remember to generate error
+		ErrBits |= AB_ERRBIT_UNKNOWN_NUMBER_COMPRESSION;
+	}
+	// continue parsing on next byte
+	GetByte();
+
+	// decode output format
+	switch(Flags & F8AB_NUMVAL_FORMATMASK) {
+
+		case F8AB_NUMVAL__FORMAT_BIN:
+		PutByte('%');
+		ab_output_binary(Value);
+		break;
+
+		case F8AB_NUMVAL__FORMAT_DEC:
+		fprintf(global_output_stream, "%lu", Value);
+		break;
+
+		case F8AB_NUMVAL__FORMAT_HEX:
+hex_fallback:	PutByte('$');
+		ab_output_hexadecimal(Value);
+		break;
+
+		default:	// unknown output format
+		// remember to warn
+		ErrBits |= AB_ERRBIT_UNKNOWN_NUMBER_FORMAT;
+		goto hex_fallback;
+	}
+	return(ErrBits);
+}
+
+// config struct for shared ab code
+struct ab_t	f8ab_conf	= {
+	f8ab_parse_number,
+	f8ab_pseudo_opcodes,
+	f8ab_mnemonics,
+	23,	// number of addressing modes (FIXME - check back later!)
+	// meaning of input bytes (0x80-0xec differ between AB 3.x and F8-AB)
+	// 0x80: mnemos (56 6502 + 8 65c02 + 26 65816 + jml/jsl = 92)
+	0xdc,	// first pseudo opcode
+	0xed,	// first unused byte value
+	// 0xed-0xfe are unused in F8-AB (FIXME - true? I only checked 0xed)
+};
+
+// main
+//
+void f8ab_main(void) {
+	const char*	header_message;
+
+	header_message = "Input does not have any known F8AB header.\n";
+	input_set_padding(AB_ENDOFLINE);
+	fputs(
+"; ToACME: Adding pseudo opcode to enable 65816 opcodes:\n"
+"!cpu 65816\n"
+"; ToACME: Adding two macros to fix F8AB's non-standard argument order\n"
+"; ToACME:   concerning MVP/MVN. While the commands are assembled with\n"
+"; ToACME:   the destination bank byte first, the WDC docs say that in\n"
+"; ToACME:   source codes, the source bank byte is given first.\n"
+"!macro F8AB_BROKEN_MVP .dest,.source {mvp .source,.dest}\n"
+"!macro F8AB_BROKEN_MVN .dest,.source {mvn .source,.dest}\n"
+	, global_output_stream);
+	io_process_load_address();
+	// most AB files have this format:
+	// load_address_low, load_address_high, AB_ENDOFLINE, actual content
+	// newer versions of F8AB seem to use this:
+	// $ff, $00, $00, $03, AB_ENDOFLINE, actual content
+	if(GetByte() == AB_ENDOFLINE) {
+		GetByte();	// skip it and pre-read first valid byte
+		header_message = "Input has F8AB 1.0 header.\n";
+	} else {
+		if((GotByte == 0)
+		&& (GetByte() == 3)
+		&& (GetByte() == AB_ENDOFLINE)) {
+			GetByte();// skip and pre-read first valid byte
+			header_message = "Input has F8AB 1.2 header.\n";
+		}
+	}
+	fputs(header_message, stderr);
+	ab_main(&f8ab_conf);
+}
diff --git a/contrib/toacme/src/giga.c b/contrib/toacme/src/giga.c
new file mode 100644
index 0000000..f0f21ba
--- /dev/null
+++ b/contrib/toacme/src/giga.c
@@ -0,0 +1,198 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2005 Marco Baye
+// Have a look at "main.c" for further info
+//
+// "GigaAss" stuff
+//
+
+
+// Includes
+//
+#include <stdio.h>
+#include "config.h"
+#include "acme.h"
+#include "gighyp.h"
+#include "mnemo.h"
+#include "io.h"
+#include "pet2iso.h"
+
+
+// Constants
+//
+
+// token-to-(pseudo)opcode conversion table (FIXME)
+const char*	giga_token[]	= {
+	"FIXME-CALL",		// $a0	.CALL
+	PseudoOp_MacroDef,	// $a1	.MACRO
+	PseudoOp_EndMacroDef,	// $a2	.ENDMACRO
+	NULL,			// $a3	.GLOBAL	(ACME does not need a pseudo
+	NULL,			// $a4	.EQUATE	 opcode for label definitions)
+	// bis hier wird nicht einger�ckt
+	// ab hier wird einger�ckt
+	PseudoOp_Byte,		// $a5	.BYTE
+	PseudoOp_Word,		// $a6	.WORD
+	PseudoOp_Fill,		// $a7	.DS
+	PseudoOp_PetTxt,	// $a8	.TEXT
+	// bis hier wird einger�ckt
+	// ab hier wird nicht einger�ckt
+	PseudoOp_ToFile,	// $a9	.OBJECT
+	PseudoOp_SetPC,		// $aa	.BASE
+	"FIXME-CODE",		// $ab	.CODE
+	"FIXME-ON",		// $ac	.ON
+	"FIXME-GOTO",		// $ad	.GOTO
+	PseudoOp_If,		// $ae	.IF
+	PseudoOp_Else,		// $af	.ELSE
+	PseudoOp_EndIf,		// $b0	.ENDIF
+	PseudoOp_LabelDump,	// $b1	.SYMBOLS
+	"FIXME-LISTING",	// $b2	.LISTING
+	PseudoOp_EOF,		// $b3	.END
+	"FIXME-STOP",		// $b4	.STOP
+	"FIXME-PAGE",		// $b5	.PAGE
+	"FIXME-NOCODE",		// $b6	.NOCODE
+	"FIXME-START",		// $b7	.START
+	"FIXME-NOEXP",		// $b8	.NOEXP
+	"FIXME-$b9",		// $b9
+	"FIXME-$ba",		// $ba
+	"FIXME-$bb",		// $bb
+	"FIXME-$bc",		// $bc
+	"FIXME-$bd",		// $bd
+	"FIXME-$be",		// $be
+	"FIXME-$bf",		// $bf
+	// bis hier wird nicht einger�ckt
+	// ab hier wird einger�ckt
+	MnemonicCPX,		// $c0
+	MnemonicCPY,		// $c1
+	MnemonicLDX,		// $c2
+	MnemonicLDY,		// $c3
+	MnemonicCMP,		// $c4
+	MnemonicADC,		// $c5
+	MnemonicAND,		// $c6
+	MnemonicDEC,		// $c7
+	MnemonicEOR,		// $c8
+	MnemonicINC,		// $c9
+	MnemonicLDA,		// $ca
+	MnemonicASL,		// $cb
+	MnemonicBIT,		// $cc
+	MnemonicLSR,		// $cd
+	MnemonicORA,		// $ce
+	MnemonicROL,		// $cf
+	MnemonicROR,		// $d0
+	MnemonicSBC,		// $d1
+	MnemonicSTA,		// $d2
+	MnemonicSTX,		// $d3
+	MnemonicSTY,		// $d4
+	MnemonicJMP,		// $d5
+	MnemonicJSR,		// $d6
+	MnemonicTXA,		// $d7
+	MnemonicTAX,		// $d8
+	MnemonicTYA,		// $d9
+	MnemonicTAY,		// $da
+	MnemonicTSX,		// $db
+	MnemonicTXS,		// $dc
+	MnemonicPHP,		// $dd
+	MnemonicPLP,		// $de
+	MnemonicPHA,		// $df
+	MnemonicPLA,		// $e0
+	MnemonicBRK,		// $e1
+	MnemonicRTI,		// $e2
+	MnemonicRTS,		// $e3
+	MnemonicNOP,		// $e4
+	MnemonicCLC,		// $e5
+	MnemonicSEC,		// $e6
+	MnemonicCLI,		// $e7
+	MnemonicSEI,		// $e8
+	MnemonicCLV,		// $e9
+	MnemonicCLD,		// $ea
+	MnemonicSED,		// $eb
+	MnemonicDEY,		// $ec
+	MnemonicINY,		// $ed
+	MnemonicDEX,		// $ee
+	MnemonicINX,		// $ef
+	MnemonicBPL,		// $f0
+	MnemonicBMI,		// $f1
+	MnemonicBVC,		// $f2
+	MnemonicBVS,		// $f3
+	MnemonicBCC,		// $f4
+	MnemonicBCS,		// $f5
+	MnemonicBNE,		// $f6
+	MnemonicBEQ,		// $f7
+	// bis hier wird einger�ckt
+	// ab hier wird nicht einger�ckt
+	"FIXME-$f8",		// $f8
+	"FIXME-$f9",		// $f9
+	"FIXME-$fa",		// $fa
+	"FIXME-$fb",		// $fb
+	"FIXME-$fc",		// $fc
+	"FIXME-$fd",		// $fd
+	"FIXME-$fe",		// $fe
+	"FIXME-$ff",		// $ff
+};
+
+
+// Functions
+//
+
+
+// I don't know whether it's correct, but I had to start somewhere
+#define FIRST_TOKEN	0xa0
+// Process opcode or pseudo opcode (tokenized)
+//
+int giga_Tokenized(void) {
+	const char*	token;
+
+	if(GotByte < FIRST_TOKEN)
+		fprintf(global_output_stream, "small value:$%x", GotByte);
+	else {
+		token = giga_token[GotByte-FIRST_TOKEN];
+		if(token != NULL)
+			fputs(token, global_output_stream);
+	}
+	GetByte();
+	return(0);
+}
+
+// When tokens are known, maybe use the PseudoOpcode function from hypra?
+// ...for now deleted
+// [...]
+
+// Main routine for GigaAss conversion
+//
+void giga_main(void) {
+	int	indent;
+
+	input_set_padding(0);
+	io_process_load_address();
+	acme_SwitchToPet();
+	// loop: once for every line in the file
+	while(!ReachedEOF) {
+		// skip link pointer (if it's zero, report as end marker)
+		if(GetLE16() == 0)
+			fputs("; ToACME: Found BASIC end marker.\n", global_output_stream);
+
+		GetLE16();	// skip line number
+
+		// process line
+		GetByte();
+		if((GotByte == ' ') || (GotByte == ';') || (GotByte == '\0') ||(GotByte>0x7f))
+			indent = 0;
+		else
+			indent = gigahypra_LabelDef();
+
+		// skip spaces
+		while(GotByte == ' ')
+			GetByte();
+
+		// if there is an opcode, process it
+		if((GotByte != ';') && (GotByte != '\0')) {
+			gigahypra_Indent(indent);
+			gigahypra_Opcode(giga_Tokenized());
+		}
+
+		// skip comment, if there is one
+		if(GotByte == ';')
+			gigahypra_ConvComment();
+
+		// end of line
+		PutByte('\n');
+	}
+}
diff --git a/contrib/toacme/src/gighyp.c b/contrib/toacme/src/gighyp.c
new file mode 100644
index 0000000..62907db
--- /dev/null
+++ b/contrib/toacme/src/gighyp.c
@@ -0,0 +1,154 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2005 Marco Baye
+// Have a look at "main.c" for further info
+//
+// stuff needed for both "Hypra-Ass" and "Giga-Ass"
+//
+
+
+// Includes
+//
+#include "gighyp.h"
+#include "io.h"
+#include "pet2iso.h"
+
+
+// Process comment (GotByte == ';')
+//
+void gigahypra_ConvComment(void) {
+
+	// check whether anything follows (empty comments => empty lines)
+	if(GetByte()) {
+		PutByte(';');
+		do
+			PutByte(Pet2ISO_Table[GotByte]);
+		while(GetByte());
+	}
+}
+
+// Process operator
+//
+void gigahypra_Operator(void) {// '!' was last read
+	byte_t	Middle;
+
+	Middle	= Pet2ISO_Table[GetByte()];
+	if((Middle != ';') && (Middle != 0)) {
+		if(GetByte() == '!') {
+			switch(Middle) {
+
+				case 'n':
+				PutByte('!');
+				break;
+
+				case 'o':
+				PutByte('|');
+				break;
+
+				case 'a':
+				PutByte('&');
+				break;
+
+				case '=':
+				PutByte('=');
+				break;
+
+				case '<':
+				fputs(" < ", global_output_stream);
+				break;
+
+				case '>':
+				fputs(" > ", global_output_stream);
+				break;
+
+				default:
+				PutByte('!');
+				PutByte(Middle);
+				PutByte('!');
+			}
+			GetByte();
+		} else {
+			PutByte('!');
+			PutByte(Middle);
+		}
+	} else
+		PutByte('!');
+	// exit with unused byte pre-read
+}
+
+// output one or two TABs
+//
+void gigahypra_Indent(int indent) {
+	if(indent < 8)
+		PutByte('\t');
+	PutByte('\t');
+}
+
+// Process opcode and arguments
+//
+void gigahypra_Opcode(int Flags) {
+	int	NowOpen	= 0;// number of parentheses to close
+
+	// if needed, add separating space between opcode and argument
+	if(((Flags & FLAGS_NOSPACE) == 0) && (GotByte != ' ') && (GotByte != ';') && (GotByte != '\0'))
+			PutByte(' ');
+	// character loop
+	while((GotByte != ';') && (GotByte != 0)) {
+		if(GotByte == '!')
+			gigahypra_Operator();
+		if(GotByte == '"') {
+			// don't parse inside quotes
+			PutByte(GotByte);
+			GetByte();
+			while((GotByte != 0) && (GotByte != '"')) {
+				PutByte(Pet2ISO_Table[GotByte]);
+				GetByte();
+			}
+			PutByte('"');
+			if(GotByte == '"') GetByte();
+		} else {
+			// most characters go here
+			switch(GotByte) {
+
+				case '(':
+				if(Flags & FLAGS_STRIPOPENING) {
+					Flags &= ~FLAGS_STRIPOPENING;
+					Flags |= FLAGS_STRIPCLOSING;
+				} else {
+					NowOpen++;
+					PutByte(Pet2ISO_Table[GotByte]);
+				}
+				break;
+
+				case ')':
+				if((Flags&FLAGS_STRIPCLOSING) && (NowOpen==0))
+					Flags &= ~FLAGS_STRIPCLOSING;
+				else {
+					NowOpen--;
+					PutByte(Pet2ISO_Table[GotByte]);
+				}
+				break;
+
+				default:
+				PutByte(Pet2ISO_Table[GotByte]);
+
+			}
+			GetByte();
+		}
+	}
+	if(Flags & FLAGS_ADDLEFTBRACE)
+		PutByte('{');
+}
+
+// Convert and send label name.
+// Returns length (for proper indentation).
+//
+int gigahypra_LabelDef(void) {
+	int	count	= 0;
+
+	do {
+		PutByte(Pet2ISO_Table[GotByte]);
+		count++;
+		GetByte();
+	} while((GotByte != ' ') && (GotByte != ';') && (GotByte != 0));
+	return(count);
+}
diff --git a/contrib/toacme/src/gighyp.h b/contrib/toacme/src/gighyp.h
new file mode 100644
index 0000000..d0a862f
--- /dev/null
+++ b/contrib/toacme/src/gighyp.h
@@ -0,0 +1,33 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// stuff needed for both "Hypra-Ass" and "Giga-Ass"
+//
+#ifndef gigahypra_H
+#define gigahypra_H
+
+
+// Includes
+//
+#include "config.h"
+
+
+// Constants
+//
+#define FLAGS_NOSPACE		(1u << 0)
+#define FLAGS_ADDLEFTBRACE	(1u << 1)
+#define FLAGS_STRIPOPENING	(1u << 2)
+#define FLAGS_STRIPCLOSING	(1u << 3)
+
+
+// Prototypes
+//
+extern void	gigahypra_ConvComment(void);
+extern void	gigahypra_Operator(void);
+extern void	gigahypra_Indent(int indent);
+extern void	gigahypra_Opcode(int Flags);
+extern int	gigahypra_LabelDef(void);
+
+
+#endif
diff --git a/contrib/toacme/src/hypra.c b/contrib/toacme/src/hypra.c
new file mode 100644
index 0000000..0c4da9b
--- /dev/null
+++ b/contrib/toacme/src/hypra.c
@@ -0,0 +1,227 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// "HypraAss" stuff
+//
+
+
+// Includes
+//
+#include <stdio.h>
+#include "config.h"
+#include "acme.h"
+#include "gighyp.h"
+#include "io.h"
+#include "pet2iso.h"
+
+
+// Functions
+//
+
+
+// Process pseudo opcode
+//
+int hypra_PseudoOpcode(void) {// '.' was last read
+	byte_t	a,
+		b	= '\0';
+	bool	fBlah	= TRUE;
+	int	Flags	= 0;
+
+	a = Pet2ISO_Table[GetByte()];
+	if((a != ' ') && (a != ';') && (a != '\0')) {
+		b = Pet2ISO_Table[GetByte()];
+		if((b != ' ') && (b != ';') && (b != '\0')) {
+			switch(a) {
+
+				case '.':
+				if(b == '.') {	// "..." = macro call
+					fBlah = FALSE;
+					fputs(PseudoOp_MacroCall, global_output_stream);
+					Flags |= FLAGS_STRIPOPENING;
+				}
+				break;
+
+				case 'a':
+				if(b == 'p') {	// ".ap" = append source file
+					fBlah = FALSE;
+					fputs(PseudoOp_Source, global_output_stream);
+				}
+				break;
+
+				case 'b':
+				if(b == 'a') {	// ".ba" = set base address
+					fBlah = FALSE;
+					fputs(PseudoOp_SetPC, global_output_stream);
+				}
+				if(b == 'y') {	// ".by" = insert bytes
+					fBlah = FALSE;
+					fputs(PseudoOp_Byte, global_output_stream);
+				}
+				break;
+
+				case 'e':
+				switch(b) {
+
+					case 'i':	// ".ei" = endif
+					fBlah = FALSE;
+					fputs(PseudoOp_EndIf, global_output_stream);
+					break;
+
+					case 'l':	// ".el" = else
+					fBlah = FALSE;
+					fputs(PseudoOp_Else, global_output_stream);
+					break;
+
+					case 'n':	// ".en" = end
+					fBlah = FALSE;
+					fputs(PseudoOp_EOF, global_output_stream);
+					break;
+
+					case 'q':	// ".eq" = label def
+					fBlah = FALSE;
+					Flags |= FLAGS_NOSPACE;
+					break;
+				}
+				break;
+
+				case 'g':
+				if(b == 'l')	// ".gl" = global label def
+					fBlah = FALSE;
+				Flags |= FLAGS_NOSPACE;
+				break;
+
+				case 'i':
+				if(b == 'f') {	// ".if" = conditional assembly
+					fBlah = FALSE;
+					fputs(PseudoOp_If, global_output_stream);
+					Flags |= FLAGS_ADDLEFTBRACE;
+				}
+				break;
+
+				case 'm':
+				if(b == 'a') {	// ".ma" = macro definition
+					fBlah = FALSE;
+					fputs(PseudoOp_MacroDef, global_output_stream);
+					Flags |= FLAGS_STRIPOPENING | FLAGS_ADDLEFTBRACE;
+				}
+				break;
+
+				case 'o':
+				if(b == 'b') {	// ".ob" = output to file
+					fBlah = FALSE;
+					fputs(PseudoOp_ToFile, global_output_stream);
+				}
+				break;
+
+				case 'r':
+				if(b == 't') {	// ".rt" = end of macro def
+					fBlah = FALSE;
+					fputs(PseudoOp_EndMacroDef, global_output_stream);
+				}
+				break;
+
+				case 's':
+				if(b == 'y') {	// ".sy" = symbol dump
+					fBlah = FALSE;
+					fputs(PseudoOp_LabelDump, global_output_stream);
+					fputs("\"symboldump.txt\";", global_output_stream);
+				}
+				break;
+
+				case 't':
+				if(b == 'x') {	// ".tx" = insert string
+					fBlah = FALSE;
+					fputs(PseudoOp_PetTxt, global_output_stream);
+				}
+				if(b == 's') {	// ".ts" = screen code string
+					fBlah = FALSE;
+					fputs(PseudoOp_ScrTxt, global_output_stream);
+				}
+				break;
+
+				case 'w':
+				if(b == 'o') {	// ".wo" = insert words
+					fBlah = FALSE;
+					fputs(PseudoOp_Word, global_output_stream);
+				}
+				break;
+
+			}
+			GetByte();// exit with unused byte pre-read
+		} else
+			fBlah = TRUE;
+	} else
+		fBlah = TRUE;
+	if(fBlah) {
+		fputs("; ToACME: .", global_output_stream);
+		if(a)
+			PutByte(a);
+		if(b)
+			PutByte(b);
+		fputs(" cannot be converted\n", global_output_stream);
+	}
+	return(Flags);
+}
+
+// Process ocpode
+//
+int hypra_RealOpcode(void) {// character was last read
+
+	PutByte(Pet2ISO_Table[GotByte]);
+	GetByte();
+	if((GotByte == ' ') || (GotByte == ';') || (GotByte == 0))
+		return(0);
+	PutByte(Pet2ISO_Table[GotByte]);
+	GetByte();
+	if((GotByte == ' ') || (GotByte == ';') || (GotByte == 0))
+		return(0);
+	PutByte(Pet2ISO_Table[GotByte]);
+	GetByte();// exit with unused byte pre-read
+	return(0);
+}
+
+// Main routine for HypraAss conversion
+//
+void hypra_main(void) {
+	int	indent;
+
+	input_set_padding(0);
+	io_process_load_address();
+	acme_SwitchToPet();
+	// loop: once for every line in the file
+	while(!ReachedEOF) {
+		// skip link pointer (if it's zero, report as end marker)
+		if(GetLE16() == 0)
+			fputs("; ToACME: Found BASIC end marker.\n", global_output_stream);
+
+		GetLE16();	// skip line number
+
+		// process line
+		GetByte();
+		indent = 0;
+		if((GotByte != ' ') && (GotByte != ';') && (GotByte != '\0'))
+			indent = gigahypra_LabelDef();
+
+		// skip spaces
+		while(GotByte == ' ')
+			GetByte();
+
+		// if there is an opcode, process it
+		if((GotByte != ';') && (GotByte != '\0')) {
+			gigahypra_Indent(indent);
+			// branch to relevant routine
+			if(GotByte == '.')
+				gigahypra_Opcode(hypra_PseudoOpcode());
+			else
+				gigahypra_Opcode(hypra_RealOpcode());
+		}
+
+		// skip comment, if there is one
+		if(GotByte == ';')
+			gigahypra_ConvComment();
+
+		// end of line
+		PutByte('\n');
+	}
+}
diff --git a/contrib/toacme/src/io.c b/contrib/toacme/src/io.c
new file mode 100644
index 0000000..199dc05
--- /dev/null
+++ b/contrib/toacme/src/io.c
@@ -0,0 +1,98 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// input/output
+//
+
+
+// Includes
+//
+#include <stdio.h>
+#include "config.h"
+#include "io.h"
+
+
+// Variables
+//
+byte_t	PaddingValue;
+FILE	*global_input_stream;
+FILE	*global_output_stream;
+byte_t	GotByte		= 0;
+bool	ReachedEOF	= FALSE;
+
+
+// Input functions
+//
+
+
+// Set byte sent after EOF
+//
+inline void input_set_padding(byte_t pad) {
+
+	PaddingValue = pad;
+}
+
+// Fetch and buffer byte
+//
+byte_t GetByte(void) {
+	int	w;
+
+	if(ReachedEOF)
+		GotByte = PaddingValue;
+	else {
+		w = getc(global_input_stream);
+		if(w == EOF)
+			ReachedEOF = TRUE;
+		GotByte = (byte_t) w;
+	}
+	return(GotByte);
+}
+
+// Read little-endian 16-bit value
+//
+unsigned int GetLE16(void) {
+	return(GetByte() | (GetByte() << 8));
+}
+
+
+// Output functions
+//
+
+
+// Write byte to output file
+//
+inline void PutByte(const char b) {
+	putc(b, global_output_stream);
+}
+
+// output low nibble of argument as hexadecimal digit
+//
+void put_low_nibble_hex(int v) {
+	putc("0123456789abcdef"[v & 15], global_output_stream);
+}
+
+// output low byte of argument as two hexadecimal digits
+//
+void io_put_low_byte_hex(int v) {
+	put_low_nibble_hex(v >> 4);
+	put_low_nibble_hex(v);
+}
+
+// output low 16 bits of arg as four hexadecimal digits
+//
+void io_put_low_16b_hex(int w) {
+	io_put_low_byte_hex(w >> 8);
+	io_put_low_byte_hex(w);
+}
+
+// read load address from input file and write as comment to output file
+//
+void io_process_load_address(void) {
+	int	load_address;
+
+	load_address = GetLE16();
+	fputs("; ToACME: Original source code file had load address $", global_output_stream);
+	io_put_low_16b_hex(load_address);
+	PutByte('\n');
+}
diff --git a/contrib/toacme/src/io.h b/contrib/toacme/src/io.h
new file mode 100644
index 0000000..922df7f
--- /dev/null
+++ b/contrib/toacme/src/io.h
@@ -0,0 +1,36 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// input/output
+//
+#ifndef io_H
+#define io_H
+
+
+// Includes
+//
+#include <stdio.h>
+#include "config.h"
+
+
+// Variables
+//
+extern byte_t	GotByte;
+extern bool	ReachedEOF;
+extern FILE	*global_input_stream;
+extern FILE	*global_output_stream;
+
+
+// Prototypes
+//
+extern void		input_set_padding(const byte_t);
+extern byte_t		GetByte(void);
+extern unsigned int	GetLE16(void);	// get little-endian 16-bit value
+extern void		PutByte(const char b);
+extern void		io_put_low_byte_hex(int v);
+extern void		io_put_low_16b_hex(int w);
+extern void		io_process_load_address(void);
+
+
+#endif
diff --git a/contrib/toacme/src/main.c b/contrib/toacme/src/main.c
new file mode 100644
index 0000000..ac9467e
--- /dev/null
+++ b/contrib/toacme/src/main.c
@@ -0,0 +1,82 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+
+
+// Includes
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "config.h"
+#include "acme.h"
+#include "io.h"
+#include "platform.h"
+#include "version.h"
+
+
+// Main program
+//
+int main(int argc, char *argv[]) {
+
+	// handle "toacme -h" and "toacme --help" just like "toacme"
+	if(argc == 2) {
+		if((strcmp(argv[1], "-h") == NULL)
+		|| (strcmp(argv[1], "--help") == NULL))
+			argc = 1;
+	}
+	// "toacme" without any switches gives info and exits successfully
+	if(argc == 1) {
+		version_show_info(argv[0]);
+		return(EXIT_SUCCESS);
+	}
+	// check argument count
+	if(argc != 4) {
+		fputs("Wrong number of arguments.\n", stderr);
+		return(EXIT_FAILURE);
+	}
+	// check format id
+	if(version_parse_id(argv[1])) {
+		fputs("Unknown format id.\n", stderr);
+		return(EXIT_FAILURE);
+	}
+	// be nice and ensure input and output are different
+	if(strcmp(argv[2], argv[3]) == NULL) {
+		fputs("Input and output files must be different.\n", stderr);
+		return(EXIT_FAILURE);
+	}
+	// try to open input file
+	global_input_stream = fopen(argv[2], "rb");
+	if(global_input_stream == NULL) {
+		fputs("Cannot open input file.\n", stderr);
+		return(EXIT_FAILURE);
+	}
+	// try to open output file
+	global_output_stream = fopen(argv[3], "w");
+	if(global_output_stream == NULL) {
+		fputs("Cannot open output file.\n", stderr);
+		return(EXIT_FAILURE);
+	}
+	// do the actual work
+	version_main();
+	// and then tidy up and exit
+	fclose(global_output_stream);
+	PLATFORM_SETFILETYPE(argv[3], FILETYPE_TEXT);
+	fclose(global_input_stream);
+	return(EXIT_SUCCESS);
+}
diff --git a/contrib/toacme/src/mnemo.c b/contrib/toacme/src/mnemo.c
new file mode 100644
index 0000000..e0d8d4e
--- /dev/null
+++ b/contrib/toacme/src/mnemo.c
@@ -0,0 +1,104 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// assembler mnemonics
+//
+
+// Mnemonics of legal 6502 instructions
+const char	MnemonicADC[]	= "adc";
+const char	MnemonicAND[]	= "and";
+const char	MnemonicASL[]	= "asl";
+const char	MnemonicBCC[]	= "bcc";
+const char	MnemonicBCS[]	= "bcs";
+const char	MnemonicBEQ[]	= "beq";
+const char	MnemonicBIT[]	= "bit";
+const char	MnemonicBMI[]	= "bmi";
+const char	MnemonicBNE[]	= "bne";
+const char	MnemonicBPL[]	= "bpl";
+const char	MnemonicBRK[]	= "brk";
+const char	MnemonicBVC[]	= "bvc";
+const char	MnemonicBVS[]	= "bvs";
+const char	MnemonicCLC[]	= "clc";
+const char	MnemonicCLD[]	= "cld";
+const char	MnemonicCLI[]	= "cli";
+const char	MnemonicCLV[]	= "clv";
+const char	MnemonicCMP[]	= "cmp";
+const char	MnemonicCPX[]	= "cpx";
+const char	MnemonicCPY[]	= "cpy";
+const char	MnemonicDEC[]	= "dec";
+const char	MnemonicDEX[]	= "dex";
+const char	MnemonicDEY[]	= "dey";
+const char	MnemonicEOR[]	= "eor";
+const char	MnemonicINC[]	= "inc";
+const char	MnemonicINX[]	= "inx";
+const char	MnemonicINY[]	= "iny";
+const char	MnemonicJMP[]	= "jmp";
+const char	MnemonicJSR[]	= "jsr";
+const char	MnemonicLDA[]	= "lda";
+const char	MnemonicLDX[]	= "ldx";
+const char	MnemonicLDY[]	= "ldy";
+const char	MnemonicLSR[]	= "lsr";
+const char	MnemonicNOP[]	= "nop";
+const char	MnemonicORA[]	= "ora";
+const char	MnemonicPHA[]	= "pha";
+const char	MnemonicPHP[]	= "php";
+const char	MnemonicPLA[]	= "pla";
+const char	MnemonicPLP[]	= "plp";
+const char	MnemonicROL[]	= "rol";
+const char	MnemonicROR[]	= "ror";
+const char	MnemonicRTI[]	= "rti";
+const char	MnemonicRTS[]	= "rts";
+const char	MnemonicSBC[]	= "sbc";
+const char	MnemonicSEC[]	= "sec";
+const char	MnemonicSED[]	= "sed";
+const char	MnemonicSEI[]	= "sei";
+const char	MnemonicSTA[]	= "sta";
+const char	MnemonicSTX[]	= "stx";
+const char	MnemonicSTY[]	= "sty";
+const char	MnemonicTAX[]	= "tax";
+const char	MnemonicTAY[]	= "tay";
+const char	MnemonicTSX[]	= "tsx";
+const char	MnemonicTXA[]	= "txa";
+const char	MnemonicTXS[]	= "txs";
+const char	MnemonicTYA[]	= "tya";
+
+// Mnemonics of 65c02 instructions
+const char	MnemonicBRA[]	= "bra";
+const char	MnemonicPHX[]	= "phx";
+const char	MnemonicPHY[]	= "phy";
+const char	MnemonicPLX[]	= "plx";
+const char	MnemonicPLY[]	= "ply";
+const char	MnemonicSTZ[]	= "stz";
+const char	MnemonicTRB[]	= "trb";
+const char	MnemonicTSB[]	= "tsb";
+
+// Mnemonics of 65816 instructions
+const char	MnemonicJML[]	= "jml";
+const char	MnemonicJSL[]	= "jsl";
+const char	MnemonicMVN[]	= "mvn";
+const char	MnemonicMVP[]	= "mvp";
+const char	MnemonicPEI[]	= "pei";
+const char	MnemonicBRL[]	= "brl";
+const char	MnemonicPER[]	= "per";
+const char	MnemonicCOP[]	= "cop";
+const char	MnemonicPEA[]	= "pea";
+const char	MnemonicREP[]	= "rep";
+const char	MnemonicSEP[]	= "sep";
+const char	MnemonicPHB[]	= "phb";
+const char	MnemonicPHD[]	= "phd";
+const char	MnemonicPHK[]	= "phk";
+const char	MnemonicPLB[]	= "plb";
+const char	MnemonicPLD[]	= "pld";
+const char	MnemonicRTL[]	= "rtl";
+const char	MnemonicSTP[]	= "stp";
+const char	MnemonicTCD[]	= "tcd";
+const char	MnemonicTCS[]	= "tcs";
+const char	MnemonicTDC[]	= "tdc";
+const char	MnemonicTSC[]	= "tsc";
+const char	MnemonicTXY[]	= "txy";
+const char	MnemonicTYX[]	= "tyx";
+const char	MnemonicWAI[]	= "wai";
+const char	MnemonicWDM[]	= "wdm";
+const char	MnemonicXBA[]	= "xba";
+const char	MnemonicXCE[]	= "xce";
diff --git a/contrib/toacme/src/mnemo.h b/contrib/toacme/src/mnemo.h
new file mode 100644
index 0000000..acbedcb
--- /dev/null
+++ b/contrib/toacme/src/mnemo.h
@@ -0,0 +1,65 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// 6502 mnemonics
+//
+#ifndef mnemo_H
+#define mnemo_H
+
+// Mnemonics of legal 6502 instructions
+extern const char	MnemonicADC[], MnemonicSBC[];
+extern const char	MnemonicAND[], MnemonicEOR[], MnemonicORA[];
+extern const char	MnemonicASL[], MnemonicLSR[];
+extern const char	MnemonicBCC[], MnemonicBCS[];
+extern const char	MnemonicBEQ[], MnemonicBNE[];
+extern const char	MnemonicBMI[], MnemonicBPL[];
+extern const char	MnemonicBRK[], MnemonicRTI[];
+extern const char	MnemonicBVC[], MnemonicBVS[];
+extern const char	MnemonicCLC[], MnemonicSEC[];
+extern const char	MnemonicCLD[], MnemonicSED[];
+extern const char	MnemonicCLI[], MnemonicSEI[];
+extern const char	MnemonicBIT[], MnemonicCLV[], MnemonicNOP[];
+extern const char	MnemonicCMP[], MnemonicCPX[], MnemonicCPY[];
+extern const char	MnemonicDEC[], MnemonicDEX[], MnemonicDEY[];
+extern const char	MnemonicINC[], MnemonicINX[], MnemonicINY[];
+extern const char	MnemonicJMP[], MnemonicJSR[], MnemonicRTS[];
+extern const char	MnemonicLDA[], MnemonicLDX[], MnemonicLDY[];
+extern const char	MnemonicPHA[], MnemonicPLA[];
+extern const char	MnemonicPHP[], MnemonicPLP[];
+extern const char	MnemonicROL[], MnemonicROR[];
+extern const char	MnemonicSTA[], MnemonicSTX[], MnemonicSTY[];
+extern const char	MnemonicTSX[], MnemonicTXA[], MnemonicTAY[];
+extern const char	MnemonicTYA[], MnemonicTAX[], MnemonicTXS[];
+
+// Mnemonics of 65c02 instructions
+extern const char	MnemonicBRA[];
+extern const char	MnemonicPHX[], MnemonicPHY[];
+extern const char	MnemonicPLX[], MnemonicPLY[];
+extern const char	MnemonicSTZ[];
+extern const char	MnemonicTRB[], MnemonicTSB[];
+
+// Mnemonics of 65816 instructions
+extern const char	MnemonicJML[], MnemonicJSL[];
+extern const char	MnemonicMVN[], MnemonicMVP[];
+extern const char	MnemonicPEI[];
+extern const char	MnemonicBRL[];
+extern const char	MnemonicPER[];
+extern const char	MnemonicCOP[];
+extern const char	MnemonicPEA[];
+extern const char	MnemonicREP[], MnemonicSEP[];
+extern const char	MnemonicPHB[];
+extern const char	MnemonicPHD[];
+extern const char	MnemonicPHK[];
+extern const char	MnemonicPLB[];
+extern const char	MnemonicPLD[];
+extern const char	MnemonicRTL[];
+extern const char	MnemonicSTP[];
+extern const char	MnemonicTCD[], MnemonicTCS[];
+extern const char	MnemonicTDC[], MnemonicTSC[];
+extern const char	MnemonicTXY[], MnemonicTYX[];
+extern const char	MnemonicWAI[];
+extern const char	MnemonicWDM[];
+extern const char	MnemonicXBA[], MnemonicXCE[];
+
+#endif
diff --git a/contrib/toacme/src/obj.c b/contrib/toacme/src/obj.c
new file mode 100644
index 0000000..056d077
--- /dev/null
+++ b/contrib/toacme/src/obj.c
@@ -0,0 +1,266 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2005 Marco Baye
+// Have a look at "main.c" for further info
+//
+// disassembly stuff
+//
+
+
+// Includes
+//
+#include <stdio.h>
+#include "config.h"
+#include "acme.h"
+#include "mnemo.h"
+#include "io.h"
+
+
+// Constants
+//
+
+// 6502 code table (mnemonics only)
+const char*	mnemo_of_code[]	= {
+	MnemonicBRK,	MnemonicORA,	NULL,		NULL,	// $00-$03
+	NULL,		MnemonicORA,	MnemonicASL,	NULL,	// $04-$07
+	MnemonicPHP,	MnemonicORA,	MnemonicASL,	NULL,	// $08-$0b
+	NULL,		MnemonicORA,	MnemonicASL,	NULL,	// $0c-$0f
+	MnemonicBPL,	MnemonicORA,	NULL,		NULL,	// $10-$13
+	NULL,		MnemonicORA,	MnemonicASL,	NULL,	// $14-$17
+	MnemonicCLC,	MnemonicORA,	NULL,		NULL,	// $18-$1b
+	NULL,		MnemonicORA,	MnemonicASL,	NULL,	// $1c-$1f
+	MnemonicJSR,	MnemonicAND,	NULL,		NULL,	// $20-$23
+	MnemonicBIT,	MnemonicAND,	MnemonicROL,	NULL,	// $24-$27
+	MnemonicPLP,	MnemonicAND,	MnemonicROL,	NULL,	// $28-$2b
+	MnemonicBIT,	MnemonicAND,	MnemonicROL,	NULL,	// $2c-$2f
+	MnemonicBMI,	MnemonicAND,	NULL,		NULL,	// $30-$33
+	NULL,		MnemonicAND,	MnemonicROL,	NULL,	// $34-$37
+	MnemonicSEC,	MnemonicAND,	NULL,		NULL,	// $38-$3b
+	NULL,		MnemonicAND,	MnemonicROL,	NULL,	// $3c-$3f
+	MnemonicRTI,	MnemonicEOR,	NULL,		NULL,	// $40-$43
+	NULL,		MnemonicEOR,	MnemonicLSR,	NULL,	// $44-$47
+	MnemonicPHA,	MnemonicEOR,	MnemonicLSR,	NULL,	// $48-$4b
+	MnemonicJMP,	MnemonicEOR,	MnemonicLSR,	NULL,	// $4c-$4f
+	MnemonicBVC,	MnemonicEOR,	NULL,		NULL,	// $50-$53
+	NULL,		MnemonicEOR,	MnemonicLSR,	NULL,	// $54-$57
+	MnemonicCLI,	MnemonicEOR,	NULL,		NULL,	// $58-$5b
+	NULL,		MnemonicEOR,	MnemonicLSR,	NULL,	// $5c-$5f
+	MnemonicRTS,	MnemonicADC,	NULL,		NULL,	// $60-$63
+	NULL,		MnemonicADC,	MnemonicROR,	NULL,	// $64-$67
+	MnemonicPLA,	MnemonicADC,	MnemonicROR,	NULL,	// $68-$6b
+	MnemonicJMP,	MnemonicADC,	MnemonicROR,	NULL,	// $6c-$6f
+	MnemonicBVS,	MnemonicADC,	NULL,		NULL,	// $70-$73
+	NULL,		MnemonicADC,	MnemonicROR,	NULL,	// $74-$77
+	MnemonicSEI,	MnemonicADC,	NULL,		NULL,	// $78-$7b
+	NULL,		MnemonicADC,	MnemonicROR,	NULL,	// $7c-$7f
+	NULL,		MnemonicSTA,	NULL,		NULL,	// $80-$83
+	MnemonicSTY,	MnemonicSTA,	MnemonicSTX,	NULL,	// $84-$87
+	MnemonicDEY,	NULL,		MnemonicTXA,	NULL,	// $88-$8b
+	MnemonicSTY,	MnemonicSTA,	MnemonicSTX,	NULL,	// $8c-$8f
+	MnemonicBCC,	MnemonicSTA,	NULL,		NULL,	// $90-$93
+	MnemonicSTY,	MnemonicSTA,	MnemonicSTX,	NULL,	// $94-$97
+	MnemonicTYA,	MnemonicSTA,	MnemonicTXS,	NULL,	// $98-$9b
+	NULL,		MnemonicSTA,	NULL,		NULL,	// $9c-$9f
+	MnemonicLDY,	MnemonicLDA,	MnemonicLDX,	NULL,	// $a0-$a3
+	MnemonicLDY,	MnemonicLDA,	MnemonicLDX,	NULL,	// $a4-$a7
+	MnemonicTAY,	MnemonicLDA,	MnemonicTAX,	NULL,	// $a8-$ab
+	MnemonicLDY,	MnemonicLDA,	MnemonicLDX,	NULL,	// $ac-$af
+	MnemonicBCS,	MnemonicLDA,	NULL,		NULL,	// $b0-$b3
+	MnemonicLDY,	MnemonicLDA,	MnemonicLDX,	NULL,	// $b4-$b7
+	MnemonicCLV,	MnemonicLDA,	MnemonicTSX,	NULL,	// $b8-$bb
+	MnemonicLDY,	MnemonicLDA,	MnemonicLDX,	NULL,	// $bc-$bf
+	MnemonicCPY,	MnemonicCMP,	NULL,		NULL,	// $c0-$c3
+	MnemonicCPY,	MnemonicCMP,	MnemonicDEC,	NULL,	// $c4-$c7
+	MnemonicINY,	MnemonicCMP,	MnemonicDEX,	NULL,	// $c8-$cb
+	MnemonicCPY,	MnemonicCMP,	MnemonicDEC,	NULL,	// $cc-$cf
+	MnemonicBNE,	MnemonicCMP,	NULL,		NULL,	// $d0-$d3
+	NULL,		MnemonicCMP,	MnemonicDEC,	NULL,	// $d4-$d7
+	MnemonicCLD,	MnemonicCMP,	NULL,		NULL,	// $d8-$db
+	NULL,		MnemonicCMP,	MnemonicDEC,	NULL,	// $dc-$df
+	MnemonicCPX,	MnemonicSBC,	NULL,		NULL,	// $e0-$e3
+	MnemonicCPX,	MnemonicSBC,	MnemonicINC,	NULL,	// $e4-$e7
+	MnemonicINX,	MnemonicSBC,	MnemonicNOP,	NULL,	// $e8-$eb
+	MnemonicCPX,	MnemonicSBC,	MnemonicINC,	NULL,	// $ec-$ef
+	MnemonicBEQ,	MnemonicSBC,	NULL,		NULL,	// $f0-$f3
+	NULL,		MnemonicSBC,	MnemonicINC,	NULL,	// $f4-$f7
+	MnemonicSED,	MnemonicSBC,	NULL,		NULL,	// $f8-$fb
+	NULL,		MnemonicSBC,	MnemonicINC,	NULL,	// $fc-$ff
+};
+
+// output 2-digit hex argument with correct addressing mode
+//
+static void put_argument2(const char pre[], int byte, const char post[]) {
+	fputs(pre, global_output_stream);
+	io_put_low_byte_hex(byte);
+	fputs(post, global_output_stream);
+}
+
+// output 4-digit hex argument with correct addressing mode
+//
+static void put_argument4(const char pre[], int word, const char post[]) {
+	fputs(pre, global_output_stream);
+	io_put_low_16b_hex(word);
+	fputs(post, global_output_stream);
+}
+
+static int	pc;	// needed by "relative" addressing mode handler
+
+// addressing mode handler functions
+// all of these output the opcode's argument and return the number to add
+// to the program counter
+
+// addressing mode handler function for 1-byte-instructions
+static int am_implicit(void) {
+	return(1);
+}
+// addressing mode handler functions for 2-byte-instructions
+static int am_immediate(void) {
+	put_argument2(" #$", GetByte(), "");
+	if(GotByte > 15) {
+		fprintf(global_output_stream, "	; (= %d", GotByte);
+		if((GotByte > 31) && (GotByte != 127))
+			fprintf(global_output_stream, " = '%c'", GotByte);
+		PutByte(')');
+	}
+	return(2);
+}
+static int am_absolute8(void) {
+	put_argument2(" $", GetByte(), "");
+	return(2);
+}
+static int am_abs_x8(void) {
+	put_argument2(" $", GetByte(), ",x");
+	return(2);
+}
+static int am_abs_y8(void) {
+	put_argument2(" $", GetByte(), ",y");
+	return(2);
+}
+static int am_indirect_x(void) {
+	put_argument2(" ($", GetByte(), ",x)");
+	return(2);
+}
+static int am_indirect_y(void) {
+	put_argument2(" ($", GetByte(), "),y");
+	return(2);
+}
+static int am_relative(void) {
+	put_argument4(" L", pc + 2 + (signed char) GetByte(), "");
+	return(2);
+}
+// addressing mode handler functions for 3-byte-instructions
+static int am_absolute16(void) {
+	put_argument4(" L", GetLE16(), "");
+	return(3);
+}
+static int am_abs_x16(void) {
+	put_argument4(" L", GetLE16(), ",x");
+	return(3);
+}
+static int am_abs_y16(void) {
+	put_argument4(" L", GetLE16(), ",y");
+	return(3);
+}
+static int am_indirect16(void) {
+	put_argument4(" (L", GetLE16(), ")");
+	return(3);
+}
+
+// 6502 code table (addressing mode handler functions)
+int (*addressing_mode_of_code[])(void)	= {
+	am_implicit,	am_indirect_x,	am_implicit,	am_implicit, // $00-$03
+	am_implicit,	am_absolute8,	am_absolute8,	am_implicit, // $04-$07
+	am_implicit,	am_immediate,	am_implicit,	am_implicit, // $08-$0b
+	am_implicit,	am_absolute16,	am_absolute16,	am_implicit, // $0c-$0f
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $10-$13
+	am_implicit,	am_abs_x8,	am_abs_x8,	am_implicit, // $14-$17
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $18-$1b
+	am_implicit,	am_abs_x16,	am_abs_x16,	am_implicit, // $1c-$1f
+	am_absolute16,	am_indirect_x,	am_implicit,	am_implicit, // $20-$23
+	am_absolute8,	am_absolute8,	am_absolute8,	am_implicit, // $24-$27
+	am_implicit,	am_immediate,	am_implicit,	am_implicit, // $28-$2b
+	am_absolute16,	am_absolute16,	am_absolute16,	am_implicit, // $2c-$2f
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $30-$33
+	am_implicit,	am_abs_x8,	am_abs_x8,	am_implicit, // $34-$37
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $38-$3b
+	am_implicit,	am_abs_x16,	am_abs_x16,	am_implicit, // $3c-$3f
+	am_implicit,	am_indirect_x,	am_implicit,	am_implicit, // $40-$43
+	am_implicit,	am_absolute8,	am_absolute8,	am_implicit, // $44-$47
+	am_implicit,	am_immediate,	am_implicit,	am_implicit, // $48-$4b
+	am_absolute16,	am_absolute16,	am_absolute16,	am_implicit, // $4c-$4f
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $50-$53
+	am_implicit,	am_abs_x8,	am_abs_x8,	am_implicit, // $54-$57
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $58-$5b
+	am_implicit,	am_abs_x16,	am_abs_x16,	am_implicit, // $5c-$5f
+	am_implicit,	am_indirect_x,	am_implicit,	am_implicit, // $60-$63
+	am_implicit,	am_absolute8,	am_absolute8,	am_implicit, // $64-$67
+	am_implicit,	am_immediate,	am_implicit,	am_implicit, // $68-$6b
+	am_indirect16,	am_absolute16,	am_absolute16,	am_implicit, // $6c-$6f
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $70-$73
+	am_implicit,	am_abs_x8,	am_abs_x8,	am_implicit, // $74-$77
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $78-$7b
+	am_implicit,	am_abs_x16,	am_abs_x16,	am_implicit, // $7c-$7f
+	am_implicit,	am_indirect_x,	am_implicit,	am_implicit, // $80-$83
+	am_absolute8,	am_absolute8,	am_absolute8,	am_implicit, // $84-$87
+	am_implicit,	am_implicit,	am_implicit,	am_implicit, // $88-$8b
+	am_absolute16,	am_absolute16,	am_absolute16,	am_implicit, // $8c-$8f
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $90-$93
+	am_abs_x8,	am_abs_x8,	am_abs_y8,	am_implicit, // $94-$97
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $98-$9b
+	am_implicit,	am_abs_x16,	am_implicit,	am_implicit, // $9c-$9f
+	am_immediate,	am_indirect_x,	am_immediate,	am_implicit, // $a0-$a3
+	am_absolute8,	am_absolute8,	am_absolute8,	am_implicit, // $a4-$a7
+	am_implicit,	am_immediate,	am_implicit,	am_implicit, // $a8-$ab
+	am_absolute16,	am_absolute16,	am_absolute16,	am_implicit, // $ac-$af
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $b0-$b3
+	am_abs_x8,	am_abs_x8,	am_abs_y8,	am_implicit, // $b4-$b7
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $b8-$bb
+	am_abs_x16,	am_abs_x16,	am_abs_y16,	am_implicit, // $bc-$bf
+	am_immediate,	am_indirect_x,	am_implicit,	am_implicit, // $c0-$c3
+	am_absolute8,	am_absolute8,	am_absolute8,	am_implicit, // $c4-$c7
+	am_implicit,	am_immediate,	am_implicit,	am_implicit, // $c8-$cb
+	am_absolute16,	am_absolute16,	am_absolute16,	am_implicit, // $cc-$cf
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $d0-$d3
+	am_implicit,	am_abs_x8,	am_abs_x8,	am_implicit, // $d4-$d7
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $d8-$db
+	am_implicit,	am_abs_x16,	am_abs_x16,	am_implicit, // $dc-$df
+	am_immediate,	am_indirect_x,	am_implicit,	am_implicit, // $e0-$e3
+	am_absolute8,	am_absolute8,	am_absolute8,	am_implicit, // $e4-$e7
+	am_implicit,	am_immediate,	am_implicit,	am_implicit, // $e8-$eb
+	am_absolute16,	am_absolute16,	am_absolute16,	am_implicit, // $ec-$ef
+	am_relative,	am_indirect_y,	am_implicit,	am_implicit, // $f0-$f3
+	am_implicit,	am_abs_x8,	am_abs_x8,	am_implicit, // $f4-$f7
+	am_implicit,	am_abs_y16,	am_implicit,	am_implicit, // $f8-$fb
+	am_implicit,	am_abs_x16,	am_abs_x16,	am_implicit, // $fc-$ff
+};
+
+// output mnemonic of given byte
+//
+void output_mnemonic(int byte) {
+	const char*	mnemo	= mnemo_of_code[byte];
+
+	if(mnemo)
+		fputs(mnemo, global_output_stream);
+	else
+		put_argument2("$", byte, "");
+}
+
+// Main routine for disassembly
+//
+void obj_main(void) {
+
+	input_set_padding(0);
+
+	// process load address
+	pc = GetLE16();
+	put_argument4("\t\t*=$", pc, "\n");
+	GetByte();
+	while(!ReachedEOF) {
+		put_argument4("L", pc, "\t\t");
+		output_mnemonic(GotByte);
+		pc += addressing_mode_of_code[GotByte]();
+		PutByte('\n');
+		GetByte();
+	}
+	// report end-of-file
+	fputs("; ToACME: Reached end-of-file.\n", global_output_stream);
+}
diff --git a/contrib/toacme/src/pet2iso.c b/contrib/toacme/src/pet2iso.c
new file mode 100644
index 0000000..6077182
--- /dev/null
+++ b/contrib/toacme/src/pet2iso.c
@@ -0,0 +1,51 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Converting CBM PetSCII code to ISO 8859/1
+//
+
+
+// Includes
+//
+#include "pet2iso.h"
+
+
+// Constants
+//
+
+// Conversion table
+const byte_t	Pet2ISO_Table[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+	0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5a, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+};
diff --git a/contrib/toacme/src/pet2iso.h b/contrib/toacme/src/pet2iso.h
new file mode 100644
index 0000000..883f20f
--- /dev/null
+++ b/contrib/toacme/src/pet2iso.h
@@ -0,0 +1,21 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Converting CBM PetSCII code to ISO 8859/1
+//
+#ifndef pet2iso_H
+#define pet2iso_H
+
+
+// Includes
+//
+#include "config.h"
+
+
+// Constants
+//
+extern const byte_t	Pet2ISO_Table[256];	// Conversion table
+
+
+#endif
diff --git a/contrib/toacme/src/platform.c b/contrib/toacme/src/platform.c
new file mode 100644
index 0000000..56449e1
--- /dev/null
+++ b/contrib/toacme/src/platform.c
@@ -0,0 +1,36 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Platform specific stuff
+//
+
+
+// Includes
+//
+#include "platform.h"
+
+
+#ifdef __riscos__
+//
+// RISC OS
+//
+#include <kernel.h>	// defines _kernel_swi_regs
+#define OS_FILE	0x00008	// constant to call relevant SWI
+
+// Setting the created files' types
+void Platform_SetFileType(const char *Filename, int Filetype) {
+	_kernel_swi_regs	RegSet;
+
+	RegSet.r[0] = 18;// = SetFileType
+	RegSet.r[1] = (int) Filename;
+	RegSet.r[2] = Filetype;
+	_kernel_swi(OS_FILE, &RegSet, &RegSet);
+}
+
+#else
+//
+// other OS (not that much here)
+//
+
+#endif
diff --git a/contrib/toacme/src/platform.h b/contrib/toacme/src/platform.h
new file mode 100644
index 0000000..4b0aa18
--- /dev/null
+++ b/contrib/toacme/src/platform.h
@@ -0,0 +1,33 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Platform specific stuff
+//
+#ifndef platform_H
+#define platform_H
+
+
+// check for RISC OS
+#ifdef __riscos__
+#define PLATFORM_VERSION	"Ported to RISC OS by Marco Baye."
+extern void	Platform_SetFileType(const char *Filename, int Filetype);
+#define PLATFORM_SETFILETYPE(a, b)	Platform_SetFileType(a, b);
+#define FILETYPE_TEXT	0xfff	// File types used
+#endif
+
+// all other platforms
+#ifndef PLATFORM_VERSION
+#define PLATFORM_VERSION	"Platform independent version."
+#define PLATFORM_SETFILETYPE(a, b)
+#endif
+
+// fix umlaut for DOS version
+#ifdef __DJGPP__
+#define STEFAN	"Stefan H�bner"
+#else
+#define STEFAN	"Stefan H�bner"
+#endif
+
+
+#endif
diff --git a/contrib/toacme/src/scr2iso.c b/contrib/toacme/src/scr2iso.c
new file mode 100644
index 0000000..afb9866
--- /dev/null
+++ b/contrib/toacme/src/scr2iso.c
@@ -0,0 +1,51 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Converting CBM screen code to ISO 8859/1
+//
+
+
+// Includes
+//
+#include "scr2iso.h"
+
+
+// Constants
+//
+
+// Conversion table
+const byte_t	Scr2ISO_Table[256] = {
+	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+	0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
diff --git a/contrib/toacme/src/scr2iso.h b/contrib/toacme/src/scr2iso.h
new file mode 100644
index 0000000..f4e0d3a
--- /dev/null
+++ b/contrib/toacme/src/scr2iso.h
@@ -0,0 +1,21 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Converting CBM screen code to ISO 8859/1
+//
+#ifndef scr2iso_H
+#define scr2iso_H
+
+
+// Includes
+//
+#include "config.h"
+
+
+// Constants
+//
+extern const byte_t	Scr2ISO_Table[256];	// Conversion table
+
+
+#endif
diff --git a/contrib/toacme/src/version.c b/contrib/toacme/src/version.c
new file mode 100644
index 0000000..19b1139
--- /dev/null
+++ b/contrib/toacme/src/version.c
@@ -0,0 +1,90 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// Version
+//
+#define RELEASE_NUMBER	"0.8"		// change before release (FIXME)
+#define CHANGE_DATE	"16 Jun"	// change before release
+#define CHANGE_YEAR	"2005"		// change before release
+#define HOME_PAGE	"http://home.pages.de/~mac_bacon/smorbrod/acme/"
+
+
+// Includes
+//
+#include <stdio.h>
+#include <string.h>
+#include "io.h"
+#include "platform.h"
+
+
+// Variables
+//
+void	(*client_main)(void)	= NULL;
+
+
+// Functions
+//
+
+// show version info and usage
+//
+void version_show_info(const char program_name[]) {
+	printf(
+"\n"
+"ToACME - converts other assemblers' source codes to ACME format.\n"
+"Release "RELEASE_NUMBER" ("CHANGE_DATE" "CHANGE_YEAR"), Copyright (C) 1999-"CHANGE_YEAR" Marco Baye.\n"
+PLATFORM_VERSION"\n"
+"Fixes for AssBlaster macro conversion done by "STEFAN".\n"
+"Token table for Giga-Assembler supplied by Andreas Paul.\n"
+"\n"
+"The newest version can be found at the ACME homepage:\n"
+HOME_PAGE"\n"
+"\n"
+"ToACME comes with ABSOLUTELY NO WARRANTY; for details read the help file.\n"
+"This is free software, and you are welcome to redistribute it under\n"
+"certain conditions; as outlined in the GNU General Public License.\n"
+"\n"
+"Syntax: %s <format_id> <input_file> <output_file>\n"
+"\n"
+"format_id   source file format             quality\n"
+"--------------------------------------------------\n"
+"ab3         C64: AssBlaster 3.0 to 3.2        good\n"
+"f8ab        C64: Flash8-AssBlaster              ok\n"
+"giga        C64: Giga-Assembler      needs testing\n"
+"hypra       C64: Hypra-Assembler                ok\n"
+"object      object code files                 poor\n"
+"\n"
+	, program_name);
+}
+
+// Check id string. Returns whether illegal.
+//
+extern void ab3_main(void);
+extern void f8ab_main(void);
+extern void giga_main(void);
+extern void hypra_main(void);
+extern void obj_main(void);
+int version_parse_id(const char id[]) {
+
+	if(strcmp(id, "ab3") == NULL)
+		client_main = ab3_main;
+	else if(strcmp(id, "f8ab") == NULL)
+		client_main = f8ab_main;
+	else if(strcmp(id, "giga") == NULL)
+		client_main = giga_main;
+	else if(strcmp(id, "hypra") == NULL)
+		client_main = hypra_main;
+	else if(strcmp(id, "object") == NULL)
+		client_main = obj_main;
+	return(client_main ? 0 : 1);
+}
+
+// do the actual work
+//
+void version_main(void) {
+	fputs(
+";ACME 0.85\n"
+"; ToACME: Converted by ToACME, release " RELEASE_NUMBER ".\n"
+	, global_output_stream);
+	client_main();
+}
diff --git a/contrib/toacme/src/version.h b/contrib/toacme/src/version.h
new file mode 100644
index 0000000..b6ade28
--- /dev/null
+++ b/contrib/toacme/src/version.h
@@ -0,0 +1,18 @@
+// ToACME - converts other source codes to ACME format.
+// Copyright (C) 1999-2003 Marco Baye
+// Have a look at "main.c" for further info
+//
+// version
+//
+#ifndef version_H
+#define version_H
+
+
+// Prototypes
+//
+extern void	version_show_info(const char[]);
+extern int	version_parse_id(const char[]);
+extern void	version_main(void);
+
+
+#endif
diff --git a/src/output.c b/src/output.c
index 2c2d295..cf78b7d 100644
--- a/src/output.c
+++ b/src/output.c
@@ -3,7 +3,7 @@
 // Have a look at "acme.c" for further info
 //
 // Output stuff
-// 24 Nov 2007	Added possibility to suppress segment overlap warnings 
+// 24 Nov 2007	Added possibility to suppress segment overlap warnings
 // 25 Sep 2011	Fixed bug in !to (colons in filename could be interpreted as EOS)
 //  5 Mar 2014	Fixed bug where setting *>0xffff resulted in hangups.
 // 19 Nov 2014	Merged Johann Klasek's report listing generator patch
@@ -344,10 +344,10 @@ void Output_save_file(FILE *fd)
 		PLATFORM_SETFILETYPE_APPLE(output_filename);
 		// output 16-bit load address in little-endian byte order
 		putc(start & 255, fd);
-		putc(start >>  8, fd);
+		putc(start >> 8, fd);
 		// output 16-bit length in little-endian byte order
 		putc(amount & 255, fd);
-		putc(amount >>  8, fd);
+		putc(amount >> 8, fd);
 		break;
 	case OUTPUT_FORMAT_UNSPECIFIED:
 	case OUTPUT_FORMAT_PLAIN:
@@ -357,7 +357,7 @@ void Output_save_file(FILE *fd)
 		PLATFORM_SETFILETYPE_CBM(output_filename);
 		// output 16-bit load address in little-endian byte order
 		putc(start & 255, fd);
-		putc(start >>  8, fd);
+		putc(start >> 8, fd);
 	}
 	// dump output buffer to file
 	fwrite(out->buffer + start, amount, 1, fd);