diff --git a/cfg/atari-cart.cfg b/cfg/atari-cart.cfg
new file mode 100644
index 000000000..cf6472656
--- /dev/null
+++ b/cfg/atari-cart.cfg
@@ -0,0 +1,43 @@
+FEATURES {
+    STARTADDRESS: default = $2000;
+}
+SYMBOLS {
+    __CART_HEADER__:     type = import;
+    __STACKSIZE__:       type = weak,   value = $0800; # 2k stack
+    __STARTADDRESS__:    type = export, value = %S;
+    __RESERVED_MEMORY__: type = export, value = $0000;
+    __CARTFLAGS__:       type = weak,   value = $01;   # see documentation for other possible values
+}
+MEMORY {
+    ZP:         file = "", define = yes, start = $0082, size = $007E;
+    RAM:        file = "", define = yes, start = %S,    size = $2000;
+    ROM:        file = %O, define = yes, start = $A000, size = $1FFA, fill = yes, fillval = $ff;
+    CARTID:     file = %O,               start = $BFFA, size = $0006;
+}
+SEGMENTS {
+    STARTUP:   load = ROM,            type = ro,  define = yes;
+    LOWCODE:   load = ROM,            type = ro,  define = yes, optional = yes;
+    INIT:      load = ROM,            type = ro,                optional = yes;
+    CODE:      load = ROM,            type = ro,  define = yes;
+    RODATA:    load = ROM,            type = ro;
+    DATA:      load = ROM, run = RAM, type = rw,  define = yes;
+    BSS:       load = RAM,            type = bss, define = yes;
+    CARTHDR:   load = CARTID,         type = ro;
+    ZEROPAGE:  load = ZP,             type = zp;
+    EXTZP:     load = ZP,             type = zp,                optional = yes;
+}
+FEATURES {
+    CONDES: type    = constructor,
+            label   = __CONSTRUCTOR_TABLE__,
+            count   = __CONSTRUCTOR_COUNT__,
+            segment = INIT;
+    CONDES: type    = destructor,
+            label   = __DESTRUCTOR_TABLE__,
+            count   = __DESTRUCTOR_COUNT__,
+            segment = RODATA;
+    CONDES: type    = interruptor,
+            label   = __INTERRUPTOR_TABLE__,
+            count   = __INTERRUPTOR_COUNT__,
+            segment = RODATA,
+            import  = __CALLIRQ__;
+}
diff --git a/libsrc/atari/carthdr.s b/libsrc/atari/carthdr.s
new file mode 100644
index 000000000..7ec2fc9a6
--- /dev/null
+++ b/libsrc/atari/carthdr.s
@@ -0,0 +1,20 @@
+; Cartridge "header"
+; (In fact, it's at the end of the cartridge, so more a "trailer".)
+;
+; Christian Groessler, 06-Jan-2014
+
+.ifndef __ATARIXL__
+
+.import		__CARTFLAGS__, cartinit, cartstart
+.export		__CART_HEADER__: absolute = 1
+
+.include	"atari.inc"
+
+		.segment "CARTHDR"
+
+		.word	cartstart	; start routine
+		.byte	0		; must be zero
+		.byte	<__CARTFLAGS__
+		.word	cartinit	; init routine
+
+.endif	; .ifndef __ATARIXL__
diff --git a/libsrc/atari/cartinit.s b/libsrc/atari/cartinit.s
new file mode 100644
index 000000000..5930c62ec
--- /dev/null
+++ b/libsrc/atari/cartinit.s
@@ -0,0 +1,13 @@
+; Cartridge init routine
+;
+; Christian Groessler, 06-Jan-2014
+
+.ifndef __ATARIXL__
+
+.export		cartinit
+
+.segment	"STARTUP"
+
+cartinit:	rts
+
+.endif	; .ifndef __ATARIXL__
diff --git a/libsrc/atari/cartstart.s b/libsrc/atari/cartstart.s
new file mode 100644
index 000000000..60771d54f
--- /dev/null
+++ b/libsrc/atari/cartstart.s
@@ -0,0 +1,67 @@
+; Cartridge start routine
+;
+; Christian Groessler, 06-Jan-2014
+
+.ifndef __ATARIXL__
+
+.export		cartstart
+
+.import		start
+.import		__DATA_LOAD__, __DATA_SIZE__, __DATA_RUN__
+.importzp	ptr1, ptr2, tmp1, tmp2
+
+.include	"atari.inc"
+
+.segment	 "STARTUP"
+
+; start routine of cartridge
+; copy data segment to RAM and chain to entry point of crt0.s
+
+cartstart:	lda	#<__DATA_LOAD__
+		sta	ptr1
+		lda	#>__DATA_LOAD__
+		sta	ptr1+1
+		lda	#<__DATA_RUN__
+		sta	ptr2
+		lda	#>__DATA_RUN__
+		sta	ptr2+1
+		lda	#>__DATA_SIZE__
+		sta	tmp2
+		lda	#<__DATA_SIZE__
+		sta	tmp1
+		jsr	memcopy
+		jsr	start			; run program
+		jmp	(DOSVEC)		; return to DOS
+
+
+; routine taken from http://www.obelisk.demon.co.uk/6502/algorithms.html
+;
+; copy memory
+; ptr1	    - source
+; ptr2	    - destination
+; tmp2:tmp1 - len
+
+.proc	memcopy
+
+		ldy	#0
+		ldx	tmp2
+		beq	last
+pagecp:		lda	(ptr1),y
+		sta	(ptr2),y
+		iny
+		bne	pagecp
+		inc	ptr1+1
+		inc	ptr2+1
+		dex
+		bne	pagecp
+last:		cpy	tmp1
+		beq	done
+		lda	(ptr1),y
+		sta	(ptr2),y
+		iny
+		bne	last
+done:		rts
+
+.endproc
+
+.endif	; .ifndef __ATARIXL__