Index: code/C/alien_message/Makefile
===================================================================
--- code/C/alien_message/Makefile	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
+++ code/C/alien_message/Makefile	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
@@ -0,0 +1,55 @@
+# Project settings ----------------------------------------------
+OBJECTS=obj/$(TARGET)/main.o obj/$(TARGET)/thomson.o
+CFLAGS=-Os -std=gnu99 -Wall
+
+ifeq ($(TARGET),TO8)
+  CFLAGS += -DPLATFORM=8
+else
+ifeq ($(TARGET),MO5)
+  CFLAGS += -DPLATFORM=5
+else
+# No target defined. Fail.
+all: 
+	echo "make TARGET=MO5 or make TARGET=TO8"
+endif
+endif
+
+# System settings -----------------------------------------------
+PREFIX=m6809-thomson
+CC=$(PREFIX)-gcc
+AS=$(PREFIX)-as
+
+# Generic rules -------------------------------------------------
+# HFE  disk image (for HxC FE)
+out_sap.hfe: out.sap
+	hxcfloppyemulator_convert out.sap -HFE
+	cp out_sap.hfe /mo5/MO5/
+	unmount /mo5
+	rm -r /mo5
+
+# Disk Image
+out.sap: TEST.BIN TEST.PIC
+	#cp DOS-MO.SAP $@ # Using this floppy directly results in files going above the 40th track, which MO5 DOS doesn't like.
+	sapfs -c $@ 40 2
+	sapfs -a $@ $^
+
+# Linking
+TEST.BIN TEST.map: $(OBJECTS) TEST.script
+	#$(CC) -v -Os $(OBJECTS) -o TEST.BIN -Wl,--map -Wl,-m -Wl,-Ttext,0x6100 -nostdlib -lgcc
+	lwlink --decb $(OBJECTS) --output=TEST.BIN --map=TEST.map --script=TEST.script --library-path=/boot/home/config/lib/gcc/m6809-thomson/4.6.1 --library-path=/boot/home/config/m6809-thomson/lib -lgcc
+
+#Compiling
+obj/$(TARGET)/%.o: %.c obj/$(TARGET)
+	$(CC) $(CFLAGS) -c $< -o $@
+
+obj/$(TARGET)/%.o: pff/%.c obj/$(TARGET)
+	$(CC) $(CFLAGS) -c $< -o $@
+
+obj/$(TARGET)/%.o: %.s obj/$(TARGET)
+	$(AS) $< -o $@
+
+obj/$(TARGET):
+	mkdir -p $@
+
+TEST.PIC: ForeverXIII.png
+	png2mo5 $^ $@
Index: code/C/alien_message/TEST.script
===================================================================
--- code/C/alien_message/TEST.script	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
+++ code/C/alien_message/TEST.script	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
@@ -0,0 +1,6 @@
+section .text.startup load 5000
+section .text
+section *,!bss
+section *,bss
+
+entry _main
Index: code/C/alien_message/main.c
===================================================================
--- code/C/alien_message/main.c	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
+++ code/C/alien_message/main.c	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
@@ -0,0 +1,139 @@
+#include "thomson.h"
+
+int main()
+{
+
+	my_puts("\x1F\x20\x29\x1B\x20\x43\x1B\x20\x50\x0C\n\n\n            IN THE YEAR 2012");
+	for (int i = 25; --i >= 0;) asm(" SYNC\n");
+	my_puts("\x1B\x73\r\n\n       Shinra\r\n");
+	for (int i = 25; --i >= 0;) asm(" SYNC\n");
+	my_puts("\x1B\x70         IS PROUD TO PRESENT YOU\r\n");
+	for (int i = 25; --i >= 0;) asm(" SYNC\n");
+	my_puts("         ANOTHER PARTYMADE PROD!");
+	for (int i = 25; --i >= 0;) asm(" SYNC\n");
+	my_puts("\x1B\x73\r\n\n   ALIEN  MESSAGE\r\n");
+	for (int i = 25; --i >= 0;) asm(" SYNC\n");
+
+	asm(" ORCC #$50"); // Disable interrupts (cursor blink)
+
+#define MEA_CMD *(volatile unsigned char*)(0xA7CF)
+#define MEA_DATA *(volatile unsigned char*)(0xA7CE)
+volatile unsigned char* vram = 0;
+
+	MEA_CMD = 16 + 12;
+
+	// COLOR RAM
+	asm(" SWI\n"
+		" FCB 4");
+
+	for(int k = 73; k <= 200; k++)
+	{
+		char color = ((k+40)>>4) & 15;
+		*(vram + k * 40) = color;
+		*(vram + k * 40 + 39) = color <<4;
+	}
+	
+	char i = 0;
+	char pos = 0;
+	unsigned char z = 0;
+
+	unsigned char dir = 1;
+	unsigned char t = 20;
+
+	MEA_DATA = 0xFF;
+
+	static const unsigned char music[] =
+	{
+		0xFF, 0x80, 0x07, 0x80,
+		0x00, 0x53, 0x37, 0x90,
+		0xFF, 0x80, 0x07, 0x80,
+		0x55, 0x53, 0x37, 0x90,
+		0xFF, 0x80, 0x07, 0x80,
+		0x66, 0x53, 0x37, 0x90,
+		0xFF, 0x80, 0x07, 0x80,
+		0xBB, 0x53, 0x37, 0x90,
+
+		0xFF, 0xD2, 0x07, 0x86,
+		0x00, 0x53, 0x37, 0x90,
+		0xFF, 0xD2, 0x07, 0x80,
+		0x55, 0x53, 0x37, 0x90,
+		0xFF, 0xD2, 0x07, 0x80,
+		0x66, 0x53, 0x37, 0x90,
+		0xFF, 0xD2, 0x07, 0x80,
+		0xBB, 0x53, 0x37, 0x90,
+
+		0xFF, 0xD2, 0x07, 0x9B,
+		0x00, 0x53, 0x37, 0x90,
+		0xFF, 0xD2, 0x07, 0x80,
+		0x55, 0x53, 0x37, 0x90,
+		0xFF, 0xD2, 0x07, 0x80,
+		0x66, 0x53, 0x37, 0x90,
+		0xFF, 0xD2, 0x07, 0x80,
+		0xBB, 0x53, 0x37, 0x90,
+
+		0xFF, 0xD2, 0x07, 0x80,
+		0x00, 0x53, 0x37, 0x90,
+		0xFF, 0xD2, 0x07, 0x88,
+		0x55, 0x53, 0x37, 0x80,
+		0xFF, 0xD2, 0x07, 0x98,
+		0x66, 0x53, 0x37, 0x80,
+		0xFF, 0xD2, 0x07, 0x80,
+		0xBB, 0x53, 0x37, 0x83,
+	};
+
+	for(;;)
+	{
+		// AUDIO
+
+		for (int j = 0; j < 4; j++)
+		{
+			MEA_DATA = music[j | (pos<<2)];
+		}	
+		i++;
+		if (i > 6) {
+			i = 0;
+			pos ++;
+			if (pos >= 32)
+				pos = 0;
+		}
+
+		// VIDEO
+
+		for(int k = 73; k <= 200; k++)
+		{
+			// FORME RAM
+			asm(" LDX #0xA7C0	\n"
+				" LDA #0x51	\n"
+				" STA ,X	\n"
+				::
+				: "x", "a");
+			*(vram + k * 40) = z+k;
+			*(vram + k * 40 - 1) = -z+k;
+
+			// FORME RAM
+			asm(" LDX #0xA7C0	\n"
+				" LDA #0x50	\n"
+				" STA ,X	\n"
+				::
+				: "x","a"
+			);
+
+			char off = t + (k & 7);
+			*(vram + k * 40 - off) = 0x7F;
+			*(vram + k * 40 + off) = 0x7F;
+			off ++;
+			*(vram + k * 40 - off) = 0x30;
+			*(vram + k * 40 + off) = 0x30;
+
+		}
+		z++;
+		
+		t += dir;
+		if (t > 25) dir = - 1;
+		if (t < 9) dir = 1;
+
+		asm(" SYNC");
+	}
+
+	return 0;
+}
Index: code/C/alien_message/thomson.c
===================================================================
--- code/C/alien_message/thomson.c	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
+++ code/C/alien_message/thomson.c	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
@@ -0,0 +1,7 @@
+#include "thomson.h"
+
+void my_puts(char* s)
+{
+	int j = 0;
+	while(s[j]) PUTC(s[j++]);
+}
Index: code/C/alien_message/thomson.h
===================================================================
--- code/C/alien_message/thomson.h	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
+++ code/C/alien_message/thomson.h	(revision fe55aa51ad021343aab06b8b8c74086e7030577e)
@@ -0,0 +1,218 @@
+// 5 : MO5 / 8: TO8
+
+#ifndef PLATFORM
+	#error "make TARGET=TO8 or make TARGET=MO5"
+#endif
+
+///////////////////////////////////////
+// THOMSON.H
+///////////////////////////////////////
+
+/* MONITOR ZERO-PAGE */
+#define TERMIN	(*(volatile unsigned char*)(MONBASE + 0x00)) // 0x18 bytes
+#define STATUS	(*(volatile unsigned char*)(MONBASE + 0x19))
+#define TABPT	(*(volatile unsigned int*)(MONBASE + 0x1A))
+#define RANG	(*(volatile unsigned char*)(MONBASE + 0x1B)) // Part of TABPT?
+#define COLN	(*(volatile unsigned char*)(MONBASE + 0x1C))
+#define TOPTAB	(*(volatile unsigned char*)(MONBASE + 0x1D))
+#define TOPRAN	(*(volatile unsigned char*)(MONBASE + 0x1E))
+#define BOTTAB	(*(volatile unsigned char*)(MONBASE + 0x1F))
+#define BOTRAN	(*(volatile unsigned char*)(MONBASE + 0x20))
+
+#define PLOTX	(*(volatile unsigned int*)(MONBASE + 0x32))
+#define PLOTY	(*(volatile unsigned int*)(MONBASE + 0x34))
+#define CHDRAW	(*(volatile unsigned char*)(MONBASE + 0x36))
+#define KEY		(*(volatile unsigned char*)(MONBASE + 0x37))
+#define DKOPC	(*(volatile unsigned char*)(MONBASE + 0x48))
+#define DKDRV	(*(volatile unsigned char*)(MONBASE + 0x49))
+/* 204A is unused */
+#define DKTRK	(*(volatile unsigned char*)(MONBASE + 0x4B))
+#define DKSEC	(*(volatile unsigned char*)(MONBASE + 0x4C))
+#define DKSTA	(*(volatile unsigned char*)(MONBASE + 0x4E))
+#define DKBUF	(*(volatile unsigned int*)(MONBASE + 0x4F))
+
+#define DKint1 (*(volatile unsigned int*)(MONBASE + 0x52))
+
+void printhex(unsigned char i);
+extern unsigned char mark[];
+
+/* HARDWARE */
+#define FDC_STATUS (*(volatile unsigned char*)(FDCBASE))
+
+////////////////////////////////////////
+// MO5.H
+////////////////////////////////////////
+
+#if PLATFORM == 5
+/*****************************************************************************
+ * MOx CODE
+ ****************************************************************************/
+	#define MONBASE 0x2000
+	#define FDCBASE	0xA7D0
+
+	/* MONITOR ENTRY POINTS */
+
+	static inline void MENU() {
+		asm(" SWI	\n"
+			" FCB	0"
+			);
+	}
+
+	static inline void PUTC(unsigned char car) {
+    	asm(" swi \n"
+		    " fcb 2"
+			::"B" (car)
+		);
+	}
+
+	static inline void FRM0() {
+		asm(" SWI	\n"
+			" FCB	4"
+			);
+	}
+
+	static inline void FRM1() {
+		asm(" SWI	\n"
+			" FCB	6"
+			);
+	}
+
+	static inline void BEEP() {
+		asm(" SWI	\n"
+			" FCB	8"
+			);
+	}
+
+	// TODO GETC and KTST return values in B,A and Z-flag. How to get these
+	// back in C ?
+
+	static inline void DRAW(int x, int y) {
+		asm(" SWI	\n"
+			" FCB	0xE"
+			:: "X" (x), "Y" (y)
+		);
+	}
+
+	static inline void PLOT(int x, int y) {
+		asm(" SWI	\n"
+			" FCB	0x10"
+			:: "X" (x), "Y" (y)
+		);
+	}
+
+	static inline void CHPL(int x, int y) {
+		asm(" SWI	\n"
+			" FCB	0x12"
+			:: "X" (x), "Y" (y)
+		);
+	}
+
+	// TODO GETP returns in B, LPIN in flag C, GETL flag C and regs XY
+	// GETS and JOYS in A
+	
+	enum Note {
+		DO  = 0,
+		DOs = 1,
+		RE  = 2,
+		REs = 3,
+		MI  = 4,
+		FA  = 5,
+		FAs = 6,
+		SO  = 7,
+		SOs = 8,
+		LA  = 9,
+		LAs = 9,
+		SI  = 10,
+		UT  = 11,
+		// TODO what happens with other values ?
+	};
+
+	static inline void NOTE(enum Note note)
+	{
+		asm(" SWI	\n"
+			" FCB	0x1E"
+			:: "B" (note)
+		);
+	}
+
+
+	/* FLOPPY DRIVE MONITOR ROM */
+	// NOTE DKOPC was split into several commands to make it easier to use from
+	// C code.
+	static inline void write(unsigned char track, unsigned char sector, unsigned char* buffer) {
+		DKTRK = (unsigned char)track;
+		DKSEC = (unsigned char)sector;
+		DKOPC = 8;
+		DKBUF = (unsigned int)buffer;
+
+    	asm(" swi \n"
+		    " fcb 0x26"
+			);
+	}
+
+static inline void read(unsigned char track, unsigned char sector, unsigned char* output)
+{
+	for(;;)
+	{
+		DKTRK = (unsigned char)track;
+		DKSEC = (unsigned char)sector;
+		DKOPC = 2;
+		DKBUF = (unsigned int)output;
+
+    	asm(" swi \n"
+		    " fcb 0x26"
+			);
+
+		if (DKSTA == 0x44 || DKSTA == 0) return; // Sector read ok!
+		printhex(DKSTA);
+	}
+}
+
+	static inline void BOOT() {
+		asm(" SWI	\n"
+			" FCB	0x28"
+		);
+	}
+
+#else
+/*****************************************************************************
+ * TOx CODE
+ ****************************************************************************/
+	/* MONITOR ENTRY POINTS */
+	#define mon_putc(car) { \
+    	asm("JSR \t0xE803  \t; TO8 PUTC\n"\
+			::"B" ((unsigned char) (car))\
+		); \
+	}
+
+	#define MONBASE 0x6000
+
+#define write(track, sector, buffer) {\
+		DKTRK = (unsigned char)track;\
+		DKSEC = (unsigned char)sector;\
+		DKOPC = 8;\
+		DKBUF = (unsigned int)buffer;\
+\
+    	asm("JSR \t 0xE004 \t; TO8 DKCONT\n"\
+		); \
+	}
+
+	/* FLOPPY DRIVE MONITOR ROM */
+inline void read(unsigned char track, unsigned char sector,
+	unsigned char* output)
+{
+	for(;;)
+	{
+		DKTRK = (unsigned char)track;
+		DKSEC = (unsigned char)sector;
+		DKOPC = 2;
+		DKBUF = (unsigned int)output;
+
+    	asm("JSR \t 0xE004 \t \n"); \
+
+		if (DKSTA == 0x44 || DKSTA == 0) return; // Sector read ok!
+		printhex(DKSTA);
+	}
+}
+#endif
+
