diff --git a/libsrc/common/.cvsignore b/libsrc/common/.cvsignore
index aab101ac4..789eb14f2 100644
--- a/libsrc/common/.cvsignore
+++ b/libsrc/common/.cvsignore
@@ -31,5 +31,4 @@ realloc.s
 rewind.s
 strtok.s
 strxfrm.s
-vcprintf.s
 vprintf.s
diff --git a/libsrc/common/Makefile b/libsrc/common/Makefile
index 1594714e9..aabe87d68 100644
--- a/libsrc/common/Makefile
+++ b/libsrc/common/Makefile
@@ -16,7 +16,7 @@ C_OBJS = fclose.o fgets.o calloc.o _fopen.o\
 	 _hextab.o fdopen.o strtok.o\
 	 _afailed.o fopen.o fgetc.o fputc.o puts.o gets.o perror.o getchar.o\
 	 vprintf.o abort.o qsort.o putchar.o\
-	 errormsg.o vcprintf.o freopen.o locale.o fsetpos.o\
+	 errormsg.o freopen.o locale.o fsetpos.o\
 	 fgetpos.o rewind.o fseek.o ftell.o
 
 S_OBJS = 	_fdesc.o	\
@@ -86,6 +86,7 @@ S_OBJS = 	_fdesc.o	\
 		strupper.o	\
 		tolower.o	\
 		toupper.o	\
+		vcprintf.o	\
 		vfprintf.o	\
 		vsprintf.o	\
 		zerobss.o
diff --git a/libsrc/common/cprintf.s b/libsrc/common/cprintf.s
index 0beba092a..d5e569153 100644
--- a/libsrc/common/cprintf.s
+++ b/libsrc/common/cprintf.s
@@ -47,11 +47,10 @@ _cprintf:
 	lda	(ptr1),y
 	jsr	pushax
 
-; Push va_list (last parameter to vcprintf)
+; Load va_list (last and __fastcall__ parameter to vfprintf)
 
 	lda    	ptr1
 	ldx    	ptr1+1
-	jsr	pushax
 
 ; Call vcprintf
 
@@ -62,4 +61,4 @@ _cprintf:
 	ldy	ParamSize
 	jmp	addysp
 
-  
+
diff --git a/libsrc/common/vcprintf.c b/libsrc/common/vcprintf.c
deleted file mode 100644
index 64d0e5c96..000000000
--- a/libsrc/common/vcprintf.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * vcprintf.c
- *
- * Ullrich von Bassewitz, 11.08.1998
- */
-
-
-
-#include <stdarg.h>
-#include <conio.h>
-#include "_printf.h"
-
-
-
-static void out (struct outdesc* d, const char* buf, unsigned count)
-/* Routine used for writing */
-{
-    /* Fast screen output */
-    d->ccount += count;
-    while (count) {
-    	cputc (*buf);
-    	++buf;
-        --count;
-    }
-}
-
-
-
-int vcprintf (const char* format, va_list ap)
-{
-    struct outdesc d;
-
-    /* Setup descriptor */
-    d.fout = out;
-
-    /* Do formatting and output */
-    _printf (&d, format, ap);
-
-    /* Return bytes written */
-    return d.ccount;
-}
-
-
-
diff --git a/libsrc/common/vcprintf.s b/libsrc/common/vcprintf.s
new file mode 100644
index 000000000..f994ad29a
--- /dev/null
+++ b/libsrc/common/vcprintf.s
@@ -0,0 +1,158 @@
+;
+; int vcprintf (const char* Format, va_list ap);
+;
+; Ullrich von Bassewitz, 2.12.2000
+;
+
+   	.export	      	_vcprintf
+	.import	      	pushax, popax
+	.import	      	__printf, _cputc
+	.importzp     	sp, ptr1, ptr2, ptr3, tmp1
+
+	.macpack      	generic
+
+
+.data
+
+; ----------------------------------------------------------------------------
+;
+; Static data for the _vsprintf routine
+;
+
+outdesc:	    	 	; Static outdesc structure
+	.word	0   	 	; ccount
+	.word	out 	 	; Output function pointer
+	.word	0   	 	; ptr
+       	.word  	0   		; uns
+
+.code
+
+; ----------------------------------------------------------------------------
+; Callback routine used for the actual output.
+;
+; static void out (struct outdesc* d, const char* buf, unsigned count)
+; /* Routine used for writing */
+; {
+;     /* Fast screen output */
+;     d->ccount += count;
+;     while (count) {
+;  	  cputc (*buf);
+;  	  ++buf;
+;  	  --count;
+;     }
+; }
+;
+; We're using ptr1 and tmp1, since we know that the cputc routine will not use
+; them (they're also used in cputs, so they must be safe).
+
+out:	jsr	popax 		; count
+  	sta    	ptr2
+	eor	#$FF
+	sta	outdesc+6
+	txa
+	sta	ptr2+1
+	eor	#$FF
+       	sta	outdesc+7
+
+  	jsr	popax 		; buf
+       	sta    	ptr1
+  	stx	ptr1+1
+
+  	jsr	popax 		; d
+  	sta	ptr3
+  	stx	ptr3+1
+
+; Sum up the total count of characters
+
+  	ldy	#0  		; ccount in struct outdesc
+	sty	tmp1		; Initialize tmp1 while we have zero available
+  	lda	(ptr3),y
+  	add	ptr2
+  	sta	(ptr3),y
+  	iny
+  	lda	(ptr3),y
+  	adc	ptr2+1
+  	sta	(ptr3),y
+
+; Loop outputting characters
+
+@L1:	inc	outdesc+6
+   	beq	@L4
+@L2:	ldy	tmp1
+    	lda	(ptr1),y
+    	iny
+    	bne	@L3
+       	inc    	ptr1+1
+@L3:	sty	tmp1
+    	jsr	_cputc
+    	jmp	@L1
+
+@L4:	inc	outdesc+7
+    	bne	@L2
+   	rts
+
+; ----------------------------------------------------------------------------
+; vcprintf - formatted console i/o
+;
+; int vcprintf (const char* format, va_list ap)
+; {
+;     struct outdesc d;
+;
+;     /* Setup descriptor */
+;     d.fout = out;
+;
+;     /* Do formatting and output */
+;     _printf (&d, format, ap);
+;
+;     /* Return bytes written */
+;     return d.ccount;
+; }
+;
+; It is intentional that this function does not have __fastcall__ calling
+; conventions - we need the space on the stack anyway, so there's nothing
+; gained by using __fastcall__.
+
+_vcprintf:
+  	sta	ptr1  		; Save ap
+  	stx	ptr1+1
+
+; Setup the outdesc structure
+
+   	lda	#0
+   	sta	outdesc
+   	sta	outdesc+1	; Clear ccount
+
+; Get the format parameter and push it again
+
+	ldy	#1
+	lda	(sp),y
+	tax
+	dey
+	lda	(sp),y
+	jsr	pushax
+
+; Replace the passed format parameter on the stack by &d - this creates
+; exactly the stack frame _printf expects. Parameters will get dropped
+; by _printf.
+
+	ldy	#2    		; Low byte of d
+	lda	#<outdesc
+	sta	(sp),y
+	iny
+	lda	#>outdesc
+	sta	(sp),y
+
+; Restore ap and call _printf
+
+	lda	ptr1
+	ldx	ptr1+1
+	jsr	__printf
+
+; Return the number of bytes written.
+
+    	lda	outdesc		; ccount
+    	ldx	outdesc+1
+	rts
+
+		      
+