diff --git a/Makefile b/Makefile
index 7c0a765..b0d7b92 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,6 @@ endif
 .SECONDARY:
 
 obj :=
-obj += obj/crt0.o
 obj += obj/autoinit.o
 obj += obj/eapiglueasm.o
 obj += obj/texts.o
@@ -36,11 +35,20 @@ obj += obj/write.o
 obj += obj/usbtest.o
 obj += obj/util.o
 
+obj_prg :=
+obj_prg += obj/crt0.o
+obj_prg += $(obj)
+
+obj_bin :=
+obj_bin += obj/crt0_crt.o
+obj_bin += $(obj)
+
 bin_acme :=
 bin_acme += obj/startup.bin
 bin_acme += obj/sprites.bin
 
-eapi := eapi-am29f040-14
+eapi := eapi-29f040
+eapi += eapi-am29f040-14
 eapi += eapi-m29w160t-03
 eapi += eapi-mx29640b-12
 eapi += eapi-sst39sf040-10
@@ -111,13 +119,33 @@ obj/%.bin: src/%.s | obj
 obj:
 	mkdir -p $@
 
-easyprog: $(obj) src/ld.cfg $(eload) $(libprint) $(libef3usb)
-	cl65 -o $@ -m $@.map -C src/ld.cfg -t c64 $(obj) $(eload) $(libprint) $(libef3usb)
+easyprog: $(obj_prg) src/ld.cfg $(eload) $(libprint) $(libef3usb)
+	cl65 -o $@ -m $@.map -Ln $@.label -C src/ld.cfg -t c64 $(obj_prg) $(eload) $(libprint) $(libef3usb)
 	cat $@.map | grep -e "^Name\|^CODE\|^DATA\|^BSS\|^RODATA\|^LOWCODE"
 
 easyprog.prg: easyprog
 	exomizer sfx 0x080d -o $@ -q $^
 
+#easyprog.bin allows you to install EasyProg into a cartridge. It can be programmed into a ROM by an EPROM
+#programmer. You could consider to pad the file with $ff bytes to 512KB, but common EPROM programming software
+#already eats the file as it is. The code has been designed in a way you can program two flash ROMs with
+#easyprog.bin each and then it doesn't #matter which ROM you plug into the EasyFlash cartridge as low or high ROM.
+easyprog.bin: $(obj_bin) src/ld_crt.cfg $(eload) $(libprint) $(libef3usb)
+	cl65 -o $@ -m $@.map -Ln $@.label -C src/ld_crt.cfg -t c64 $(obj_bin) $(eload) $(libprint) $(libef3usb)
+	cat $@.map | grep -e "^Name\|^CODE\|^DATA\|^BSS\|^RODATA\|^LOWCODE"
+
+#easyprog.crt achieves the same in a .crt file: The low and high ROM's contain the same content and the C64 boots
+#with EasyProg.
+easyprog.crt: easyprog.bin
+	split easyprog.bin -b 8192 easyprog_
+	cat easyprog_aa easyprog_aa easyprog_ab easyprog_ab easyprog_ac easyprog_ac easyprog_ad easyprog_ad > easyprog_1mb.bin
+	perl -e 'print "\xff"x983040;' >> easyprog_1mb.bin
+	cartconv -t easy -i easyprog_1mb.bin -o easyprog.crt -n "EasyProg $(version)"
+	rm -f easyprog_*
+	rm -f easyprog_1mb.bin
+
+
+
 easyprog-$(version).zip: easyprog.prg CHANGES
 	rm -rf easyprog-$(version)
 	rm -f $@
diff --git a/src/crt0_crt.s b/src/crt0_crt.s
new file mode 100644
index 0000000..9bb0509
--- /dev/null
+++ b/src/crt0_crt.s
@@ -0,0 +1,355 @@
+;
+; Startup code for cc65 (C64 EasyFlash CRT)
+; No IRQ support at the moment
+;
+
+        .export _exit
+        .export __STARTUP__ : absolute = 1      ; Mark as startup
+
+        .import _main
+
+        .import initlib, donelib, copydata
+        .import zerobss
+        .import BSOUT,RESTOR,CINT,IOINIT
+        .import __RAM_START__, __RAM_SIZE__     ; Linker generated
+        .import __CODE_RUN__, __CODE_SIZE__
+        .import __DATA_RUN__, __DATA_SIZE__
+        .import __TRAMPOLINE_SIZE__, __TRAMPOLINE_LOAD__, __TRAMPOLINE_RUN__
+        .import __LOWCODE_SIZE__, __LOWCODE_LOAD__, __LOWCODE_RUN__
+        .import __SPRITES_SIZE__, __SPRITES_LOAD__, __SPRITES_RUN__
+        .import __RODATA_SIZE__, __RODATA_LOAD__, __RODATA_RUN__
+
+        .include "zeropage.inc"
+        .include "c64.inc"
+
+EASYFLASH_BANK    = $DE00
+EASYFLASH_CONTROL = $DE02
+EASYFLASH_LED     = $80
+EASYFLASH_16K     = $07
+EASYFLASH_KILL    = $04
+
+.SEGMENT "ONCE"
+
+LOWCODE_END = __LOWCODE_LOAD__ + __LOWCODE_SIZE__
+SPRITES_END = __SPRITES_LOAD__ + __SPRITES_SIZE__
+RODATA_END = __RODATA_LOAD__ + __RODATA_SIZE__
+
+.proc c64_16kcrt_entry
+        ; same init stuff the kernel calls after reset
+        ldx #0
+        stx $d016
+        jsr IOINIT   ; Initialise I/O
+
+        ; These may not be needed - depending on what you'll do
+        jsr fast_ramtas   ; Initialize memory
+        jsr RESTOR   ; Restore Kernal Vectors
+        jsr CINT     ; Initialize screen editor
+
+        ; Switch to second charset
+        ldy #0
+@2:
+        lda bootmessage,y
+        beq @1
+        jsr BSOUT
+        iny
+        jmp @2
+@1:
+
+        lda #$02
+        sta $0a
+
+        lda #0
+        sta $02
+        lda #>__LOWCODE_LOAD__
+        sta $03
+        lda #<__LOWCODE_LOAD__
+        sta $04
+
+        lda #0
+        sta $05
+        lda #>__LOWCODE_RUN__
+        sta $06
+        lda #<__LOWCODE_RUN__
+        sta $07
+
+        lda #<LOWCODE_END
+        sta $08
+        lda #>LOWCODE_END
+        sta $09
+
+
+@3:
+		ldy $04
+		lda ($02),y
+		ldy $07
+		sta ($05),y
+		
+		inc $04   ; Increase <source
+		bne @4
+		inc $03   ; Increase >source
+@4:
+        inc $07   ; Increase <dest
+        bne @5
+        inc $06   ; Increase >dest
+@5:
+        lda $04   ; End? Check <
+        cmp $08
+        bne @3
+        lda $03   ; End? Check >
+        cmp $09
+        bne @3
+
+        dec $0a
+        beq @6
+        bmi @7
+        
+        ; LOWCODE segment is followed by SPRITES segment in ROM
+
+;        lda #>__SPRITES_LOAD__
+;        sta $03
+;        lda #<__SPRITES_LOAD__
+;        sta $04
+
+        lda #>__SPRITES_RUN__
+        sta $06
+        lda #<__SPRITES_RUN__
+        sta $07
+
+        lda #<SPRITES_END
+        sta $08
+        lda #>SPRITES_END
+        sta $09
+        bmi @3  ; always because SPRITES_END is in ROM
+
+@6:
+        ; SPRITES segment is followed by RODATA segment in ROM
+
+;        lda #>__RODATA_LOAD__
+;        sta $03
+;        lda #<__RODATA_LOAD__
+;        sta $04
+
+        lda #>__RODATA_RUN__
+        sta $06
+        lda #<__RODATA_RUN__
+        sta $07
+
+        lda #<RODATA_END
+        sta $08
+        lda #>RODATA_END
+        sta $09
+        bmi @3  ; always because RODATA_END is in ROM
+
+@7:
+        jsr zerobss
+
+        ; and here
+        ; Set argument stack ptr
+        lda #<(__RAM_START__ + __RAM_SIZE__)
+        sta sp
+        lda #>(__RAM_START__ + __RAM_SIZE__)
+        sta sp + 1
+
+        dec $01     ; Disable BASIC (cartridge ROM still visible)
+        jsr initlib
+        jsr trampoline2
+
+::_exit:
+        jsr donelib
+exit:
+        jmp (reset_vector) ; reset, mhhh
+.endproc
+
+bootmessage:
+		.byte 14, "EasyFlash",0
+
+;
+; The RAM test in KERNAL takes a long time and Doing a full RAM test during
+; boot is a bit pointless for EasyProg purposes, so this routine duplicates
+; the KERNAL RAMTAS routine at $ff87 without the RAM test;
+;
+
+tape_buffer = $033c
+
+.proc fast_ramtas
+		lda #0
+		tay
+@1:
+		sta $0002,y
+		Sta $0200,y
+		sta $0300,y
+		iny
+		bne @1
+		
+		ldx #<tape_buffer
+		ldy #>tape_buffer
+		stx $b2
+		sty $b3
+		
+		; Top of memory at $a000
+		ldx #$00
+		ldy #$a0
+		clc
+		jsr $fe2d    ; SETTOP
+		lda #$08     ; Bottom of memory at $0800
+		sta $0282
+		lsr          ; Screen RAM a $0400
+		sta $0288
+		rts
+.endproc
+
+; ------------------------------------------------------------------------
+; This code is executed in Ultimax mode. It is called directly from the
+; reset vector and must do some basic hardware initializations.
+; It also contains trampoline code which will switch to 16k cartridge mode
+; and call the normal startup code.
+;
+        .segment "ULTIMAX"
+.proc ultimax_reset
+ultimax_reset:
+        ; === the reset vector points here ===
+        sei
+        ldx #$ff
+        txs
+        cld
+
+        ; copy the final start-up code to RAM (bottom of CPU stack)
+        ldx #<__TRAMPOLINE_SIZE__
+@1:
+        lda __TRAMPOLINE_LOAD__,x
+        sta <__TRAMPOLINE_RUN__,x   ; < to force ZP addressing mode
+        dex
+		bpl @1
+        ;cpx #$ff  ; repliace bpl with cpx/bne if trampoline size > 128 bytes
+        ;bne @2
+        jmp __TRAMPOLINE_RUN__
+.endproc
+
+		.segment "TRAMPOLINE":zeropage
+
+code_end = __CODE_RUN__ + __CODE_SIZE__
+data_end = __DATA_RUN__ + __DATA_SIZE__
+
+; ------------------------------------------------------------------------
+; To switch from Ultimax mode to another mode, we need a trampoline in the
+; lowest 4KB of RAM. Our trampoline uses self-modifying code and self
+; modifying code is most efficient in the zero page, so our trampoline is
+; copied to the zero page.
+;
+; The code does some inits, scans the keyboard and if necessary kills the
+; cartridge. If no inhibit key is pressed, it copies the code and data
+; segments from cartridge ROM to RAM, and then jumps to cartridge ROM in
+; 16K CRT mode to continue with the rest of the startup.
+;
+
+.proc trampoline
+        lda #EASYFLASH_16K + EASYFLASH_LED
+        sta EASYFLASH_CONTROL
+
+        ; Check if one of the magic kill keys is pressed
+        ; This should be done in the same way on any EasyFlash cartridge!
+
+        ; Prepare the CIA to scan the keyboard
+        lda #$7f
+        sta $dc00   ; pull down row 7 (DPA)
+
+        ldx #$ff
+        stx $dc02   ; DDRA $ff = output (X is still $ff from copy loop)
+        inx
+        stx $dc03   ; DDRB $00 = input
+
+        ; Read the keys pressed on this row
+        ; This is ugly but also a work of art in compact 6502 zero page
+        ; coding! The 01 in $dc01 doubles also as an initialized
+        ; variable containing the current bank number user later in the code.
+@bankno = * + 1
+        lda $dc01   ; read coloumns (DPB)
+
+        ; (leave the CIA registers as they are, IOINIT will initialize them properly)
+
+        ; Check if one of the magic kill keys was pressed
+        and #$e0    ; only leave "Run/Stop", "Q" and "C="
+        cmp #$e0
+        bne @kill    ; branch if one of these keys is pressed
+
+        ;
+        ; The trampoline jumps to cartridge ROM in 16K CRT mode. When we execute
+        ; from cartridge ROM we cannot bankswitch easily, so it's best to copy code
+        ; from other banks now. These are the CODE and DATA segments, so let's copy
+        ; these segments to RAM.
+        ;
+
+        ; Start at bank 1
+        inx					; ldx = 0, increase
+        stx EASYFLASH_BANK
+
+@1:
+@lsrc:
+		lda $a000           ; Begin of cartridge ROM
+@ldst:
+		sta __CODE_RUN__
+		inc @lsrc+1
+		bne @2
+		ldy @lsrc+2
+		iny
+		cpy #$c0
+		bne @3
+		inc <@bankno       ; < needed to force ZP adressing mode
+		ldy <@bankno       ; < needed to force ZP adressing mode
+		sty EASYFLASH_BANK
+		ldy #$a0
+@3:
+		sty @lsrc+2
+@2:
+        inc @ldst+1
+        bne @4
+        inc @ldst+2
+@4:
+		lda @ldst+1
+		cmp <@endl,x      ; < needed to force ZP adressing mode
+		bne @1
+		lda @ldst+2
+		cmp <@endh,x      ; < needed to force ZP adressing mode
+		bne @1
+
+        dex
+        bmi @5
+        
+        ; Code segment is followed by data segment in ROM
+
+        lda #<__DATA_RUN__
+        sta @ldst+1
+        lda #>__DATA_RUN__
+        sta @ldst+2
+        bne @1  ; always
+
+@5:
+		inx
+		stx EASYFLASH_BANK ; switch to bank 0
+        ; Branch to the normal start-up code
+        jmp c64_16kcrt_entry
+
+@kill:
+        lda #EASYFLASH_KILL
+        sta EASYFLASH_CONTROL
+        jmp (reset_vector) ; reset
+@endl:
+		.byte <data_end,<code_end
+@endh:
+		.byte >data_end,>code_end
+;@bankno:
+;		.byte 1
+.endproc
+
+		.segment "LOWCODE"
+.proc trampoline2
+        lda #EASYFLASH_KILL + EASYFLASH_LED
+        sta EASYFLASH_CONTROL
+        jmp _main   ; don't return here, but to parent
+.endproc
+
+        .segment "VECTORS"
+.word   0
+reset_vector:
+.word   ultimax_reset
+.word   0 ;irq
diff --git a/src/easyprog.c b/src/easyprog.c
index c862074..5cdede5 100644
--- a/src/easyprog.c
+++ b/src/easyprog.c
@@ -557,7 +557,7 @@ static void toggleFastLoader(void)
  */
 void __fastcall__ setStatus(const char* pStrStatus)
 {
-    strncpy(strStatus, pStrStatus, sizeof(strStatus - 1));
+    strncpy(strStatus, pStrStatus, sizeof(strStatus) - 1);
     strStatus[sizeof(strStatus) - 1] = '\0';
     refreshStatusLine();
 }
diff --git a/src/ld_crt.cfg b/src/ld_crt.cfg
new file mode 100644
index 0000000..6635b4e
--- /dev/null
+++ b/src/ld_crt.cfg
@@ -0,0 +1,50 @@
+
+# This configuration is for a EF cartridge at $8000..$BFFF
+
+MEMORY {
+    ZP:       start = $0002, size = $001A, define = yes;
+    TRAMPOLINE: start = $0080, size = $0080, define = no;
+    CPUSTACK: start = $0100, size = $0100;
+
+    LORAM:    start = $0800, size = $0800, define = yes;
+    RAM:      start = $1000, size = $A000, define = yes;
+    STARTROM: start = $A000, size = $1F60, fill = yes, fillval = $ff, file = %O, define = yes;
+    ULTIMAX:  start = $FF60, size = $009A, fill = yes, fillval = $ff, file = %O, define = yes;
+    VECTORS:  start = $FFFA, size = $0006, fill = yes, fillval = $ff, file = %O, define = yes;
+    ROM:      start = $1000, size = $6000, fill = yes, fillval = $ff, file = %O;
+    EXOBUFFER:      file = "", define = yes, start = $B000, size = $1000;
+    EAPI:           file = "", define = yes, start = $C000, size = $0400;
+    HIRAM:          file = "", define = yes, start = $C400, size = $0A00;
+    BLOCK_BUFFER:   file = "", define = yes, start = $CE00, size = $0100;
+}
+
+SEGMENTS {
+    ULTIMAX:  load = ULTIMAX,        type = ro;
+    TRAMPOLINE:  load = ULTIMAX, run = TRAMPOLINE,       type = rw, define = yes;
+    VECTORS:  load = VECTORS,        type = ro;
+    ONCE:     load = STARTROM,       type = ro,  define = yes, optional = yes;
+    LOWCODE:  load = STARTROM, run = LORAM, type = ro, define = yes, optional = yes;
+    SPRITES:  load = STARTROM, run = LORAM, type = ro, define = yes, align = $40;
+    CODE:     load = ROM, run=RAM,   type = ro,  define = yes, align = $20;
+    RODATA:   load = STARTROM, run = RAM, type = ro,  define = yes, align = $100;
+    DATA:     load = ROM, run = RAM, type = rw,  define = yes;
+    BSS:      load = RAM,            type = bss, define = yes;
+    HEAP:     load = RAM,            type = bss, optional = yes; # must sit just below stack
+    ZEROPAGE: load = ZP,             type = zp,  define = yes;
+}
+
+FEATURES {
+    CONDES: segment = INIT,
+            type = constructor,
+            label = __CONSTRUCTOR_TABLE__,
+            count = __CONSTRUCTOR_COUNT__;
+    CONDES: segment = RODATA,
+            type = destructor,
+            label = __DESTRUCTOR_TABLE__,
+            count = __DESTRUCTOR_COUNT__;
+    CONDES: type = interruptor,
+            segment = RODATA,
+            label = __INTERRUPTOR_TABLE__,
+            count = __INTERRUPTOR_COUNT__;
+}
+
